├── .gitattributes ├── .github └── workflows │ └── main.yml ├── .gitignore ├── .vscode └── launch.json ├── .vscodeignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── extension.ts ├── language-configuration.json ├── ollama-modelfile-color-theme.json ├── package-lock.json ├── package.json ├── snippets.json ├── syntaxes └── modelfile.tmLanguage.json └── tsconfig.json /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behavior to automatically normalize line endings. 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Publish VSCode Extension 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | publish: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - name: Conventional Changelog 13 | id: changelog 14 | uses: TriPSs/conventional-changelog-action@v4.1.1 15 | with: 16 | github-token: ${{ secrets.GITHUB_TOKEN }} 17 | 18 | - uses: actions/setup-node@v1 19 | with: 20 | node-version: 21.1.0 21 | registry-url: https://registry.npmjs.org/ 22 | - run: npm install 23 | # - run: npm run build 24 | - name: Publish to VS Marketplace 25 | uses: HaaLeo/publish-vscode-extension@v1.0.0 26 | with: 27 | pat: ${{ secrets.VS_MARKETPLACE_TOKEN }} 28 | registryUrl: https://marketplace.visualstudio.com -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | Thumbs.db 4 | node_modules/ 5 | out/ 6 | */.vs/ 7 | tsconfig.lsif.json 8 | *.lsif 9 | *.db 10 | *.vsix -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "args": [ 13 | "--extensionDevelopmentPath=${workspaceFolder}" 14 | ], 15 | "preLaunchTask": "npm: test-compile" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | .gitignore 4 | vsc-extension-quickstart.md 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.0.18](https://github.com/technovangelist/OllamaModelFile-VSCodeExtension/compare/v0.0.17...v0.0.18) (2023-10-30) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * starting to add theme ([d7e78f5](https://github.com/technovangelist/OllamaModelFile-VSCodeExtension/commit/d7e78f51b4721d19f2b3c3e0ac167a7e2f2dbf79)) 7 | 8 | 9 | 10 | ## [0.0.17](https://github.com/technovangelist/OllamaModelFile-VSCodeExtension/compare/v0.0.16...v0.0.17) (2023-10-30) 11 | 12 | 13 | ### Bug Fixes 14 | 15 | * local models, better grammar ([a7624e1](https://github.com/technovangelist/OllamaModelFile-VSCodeExtension/commit/a7624e1c3c2d2646e292632bc54ee323c8d619a7)) 16 | 17 | 18 | 19 | ## [0.0.16](https://github.com/technovangelist/OllamaModelFile-VSCodeExtension/compare/v0.0.15...v0.0.16) (2023-10-30) 20 | 21 | 22 | ### Bug Fixes 23 | 24 | * activation event ([05714ae](https://github.com/technovangelist/OllamaModelFile-VSCodeExtension/commit/05714aeddb2bea8e69eb830ffa5022e035aa6826)) 25 | 26 | 27 | 28 | ## [0.0.15](https://github.com/technovangelist/OllamaModelFile-VSCodeExtension/compare/v0.0.14...v0.0.15) (2023-10-30) 29 | 30 | 31 | ### Bug Fixes 32 | 33 | * asht ([4741e0f](https://github.com/technovangelist/OllamaModelFile-VSCodeExtension/commit/4741e0f4ac662379fa16506845676887720492cb)) 34 | 35 | 36 | 37 | ## [0.0.14](https://github.com/technovangelist/OllamaModelFile-VSCodeExtension/compare/432ee8c23e30708709523e07b3550089f46f60f5...v0.0.14) (2023-10-30) 38 | 39 | 40 | ### Bug Fixes 41 | 42 | * another try ([9ea9777](https://github.com/technovangelist/OllamaModelFile-VSCodeExtension/commit/9ea9777d20d8189236300298b3456700f4108595)) 43 | * get auto publish to work ([432ee8c](https://github.com/technovangelist/OllamaModelFile-VSCodeExtension/commit/432ee8c23e30708709523e07b3550089f46f60f5)) 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Matt Williams 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ollama Modelfile Extension for VS Code 2 | 3 | Ollama is the best way to run AI Models on your laptop. This extension will help you create and run those models. 4 | 5 | ## Features 6 | 7 | This extension includes two types of functionality. First there are completions for all the common things that go into a modelfile, including all the models you have pulled or that are available on the Ollama hub. Second there are a few commands that make it easier to work with models. 8 | 9 | ## Requirements 10 | 11 | You will need to have Ollama installed and running. See [Ollama.ai](https://ollama.ai) for more information. 12 | -------------------------------------------------------------------------------- /extension.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from "vscode"; 2 | import axios from "axios"; 3 | import * as path from "path"; 4 | import { Ollama } from "ollama-node"; 5 | 6 | async function getRepositoryList(): Promise { 7 | const response = await axios.get("https://registry.ollama.ai/v2/_catalog"); 8 | const repositories = response.data.repositories; 9 | return repositories; 10 | } 11 | 12 | async function getTagsForRepository(repository: string): Promise { 13 | const response = await axios.get( 14 | `https://registry.ollama.ai/v2/${repository}/tags/list` 15 | ); 16 | const tags = response.data.tags; 17 | return tags; 18 | } 19 | 20 | async function getPulledModels(): Promise { 21 | let allModels: vscode.CompletionItem[] = []; 22 | const response = await axios.get("http://localhost:11434/api/tags"); 23 | const models = response.data.models; 24 | for (const model of models) { 25 | const item = new vscode.CompletionItem(`${model.name} - pulled`); 26 | item.kind = vscode.CompletionItemKind.Text; 27 | item.insertText = model.name; 28 | allModels.push(item); 29 | } 30 | 31 | return allModels; 32 | } 33 | 34 | async function getModels(): Promise { 35 | const repos = await getRepositoryList(); 36 | let allModels: string[] = []; 37 | for (const repo of repos) { 38 | const tags = await getTagsForRepository(repo); 39 | for (const tag of tags) { 40 | allModels.push(`${repo.substring(8)}:${tag}`); 41 | } 42 | } 43 | return allModels; 44 | } 45 | 46 | function getFilterText(input: string): string | undefined { 47 | let filtertext; 48 | if (input.includes("beluga")) { 49 | filtertext = `${input} beluga`; 50 | } 51 | 52 | return filtertext; 53 | } 54 | 55 | export async function activate(context: vscode.ExtensionContext) { 56 | const ollama = new Ollama(); 57 | const allModels = (await ollama.listModels()).models; 58 | // // const allModels = await getModels(); 59 | // // const pulledModels = await getPulledModels(); 60 | 61 | const createModel = vscode.commands.registerCommand( 62 | "ollamamodelfile.createModel", 63 | async () => { 64 | const filePath = 65 | vscode.window.activeTextEditor?.document.uri.fsPath || ""; 66 | const parentFolder = path.basename(path.dirname(filePath)); 67 | const modelName = await vscode.window.showInputBox({ 68 | placeHolder: "Name for the Model", 69 | prompt: "Enter the name of the Model to create", 70 | value: parentFolder, 71 | }); 72 | 73 | vscode.window.terminals[0].sendText( 74 | `ollama create ${modelName} -f ${filePath}` 75 | ); 76 | // // const model = await axios.post("http://localhost:11434/api/create", { 77 | // // name: modelName, 78 | // // path: vscode.window.activeTextEditor?.document.uri.fsPath, 79 | // // }); 80 | } 81 | ); 82 | 83 | const runModel = vscode.commands.registerCommand( 84 | "ollamamodelfile.runModel", 85 | async () => { 86 | const filePath = 87 | vscode.window.activeTextEditor?.document.uri.fsPath || ""; 88 | const parentFolder = path.basename(path.dirname(filePath)); 89 | const modelName = await vscode.window.showInputBox({ 90 | placeHolder: "Name for the Model", 91 | prompt: "Enter the name of the Model to create", 92 | value: parentFolder, 93 | }); 94 | vscode.window.terminals[0].sendText(`ollama run ${modelName}`, true); 95 | } 96 | ); 97 | 98 | const runModelVerbose = vscode.commands.registerCommand( 99 | "ollamamodelfile.runModelVerbose", 100 | async () => { 101 | const filePath = 102 | vscode.window.activeTextEditor?.document.uri.fsPath || ""; 103 | const parentFolder = path.basename(path.dirname(filePath)); 104 | const modelName = await vscode.window.showInputBox({ 105 | placeHolder: "Name for the Model", 106 | prompt: "Enter the name of the Model to create", 107 | value: parentFolder, 108 | }); 109 | vscode.window.terminals[0].sendText( 110 | `ollama run ${modelName} --verbose`, 111 | true 112 | ); 113 | } 114 | ); 115 | 116 | const provider = vscode.languages.registerCompletionItemProvider( 117 | "modelfile", 118 | { 119 | provideCompletionItems( 120 | document: vscode.TextDocument, 121 | position: vscode.Position, 122 | token: vscode.CancellationToken, 123 | context: vscode.CompletionContext 124 | ) { 125 | // let modelArray = [new vscode.CompletionItem('model')]; 126 | let modelArray: vscode.CompletionItem[] = []; 127 | allModels.forEach((m) => { 128 | const item = new vscode.CompletionItem(m); 129 | item.kind = vscode.CompletionItemKind.Text; 130 | item.filterText = getFilterText(m); 131 | modelArray.push(item); 132 | }); 133 | // modelArray = modelArray.concat(pulledModels); 134 | // const simpleCompletion = new vscode.CompletionItem(`FROM ${allModels}`); 135 | // const snippetCompletion = new vscode.CompletionItem('Good part of the day'); 136 | 137 | // snippetCompletion.insertText = new vscode.SnippetString('Good ${1|morning,afternoon,evening|}. It is ${1}, right?'); 138 | // const docs: any = new vscode.MarkdownString("Inserts a snippet that lets you select [link](x.ts)."); 139 | // snippetCompletion.documentation = docs; 140 | // docs.baseUri = vscode.Uri.parse('http://example.com/a/b/c/'); 141 | 142 | return modelArray; 143 | }, 144 | } 145 | ); 146 | 147 | context.subscriptions.push(provider, createModel, runModel); 148 | } 149 | -------------------------------------------------------------------------------- /language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | // symbol used for single line comment. Remove this entry if your language does not support line comments 4 | "lineComment": "# " 5 | }, 6 | // symbols used as brackets 7 | "brackets": [["{{", "}}"]], 8 | // symbols that are auto closed when typing 9 | "autoClosingPairs": [ 10 | ["{{", "}}"], 11 | ["[", "]"], 12 | ["<", ">"], 13 | ["\"\"\"", "\"\"\""] 14 | ], 15 | // symbols that can be used to surround a selection 16 | "surroundingPairs": [ 17 | ["\"\"\"", "\"\"\""], 18 | ["{{", "}}"], 19 | ["[", "]"], 20 | ["<", ">"] 21 | ], 22 | 23 | } 24 | -------------------------------------------------------------------------------- /ollama-modelfile-color-theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "tokenColors":[ 3 | { 4 | "scope": "modelfile.keyword", 5 | "settings": { 6 | "foreground": "#e33333f8" 7 | } 8 | } 9 | ] 10 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ollamamodelfile", 3 | "version": "0.0.16", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "ollamamodelfile", 9 | "version": "0.0.16", 10 | "dependencies": { 11 | "axios": "^1.6.0", 12 | "node-fetch": "^2.6.12", 13 | "ollama-node": "^0.1.24", 14 | "path": "^0.12.7" 15 | }, 16 | "devDependencies": { 17 | "@types/node": "^20.4.9", 18 | "@types/node-fetch": "^2.6.4", 19 | "@types/vscode": "^1.81.0", 20 | "esbuild": "^0.19.0" 21 | }, 22 | "engines": { 23 | "vscode": "^1.81.0" 24 | } 25 | }, 26 | "node_modules/@esbuild/darwin-arm64": { 27 | "version": "0.19.0", 28 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.0.tgz", 29 | "integrity": "sha512-HkxZ8k3Jvcw0FORPNTavA8BMgQjLOB6AajT+iXmil7BwY3gU1hWvJJAyWyEogCmA4LdbGvKF8vEykdmJ4xNJJQ==", 30 | "cpu": [ 31 | "arm64" 32 | ], 33 | "dev": true, 34 | "optional": true, 35 | "os": [ 36 | "darwin" 37 | ], 38 | "engines": { 39 | "node": ">=12" 40 | } 41 | }, 42 | "node_modules/@types/node": { 43 | "version": "20.8.9", 44 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", 45 | "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", 46 | "dependencies": { 47 | "undici-types": "~5.26.4" 48 | } 49 | }, 50 | "node_modules/@types/node-fetch": { 51 | "version": "2.6.4", 52 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", 53 | "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", 54 | "dev": true, 55 | "dependencies": { 56 | "@types/node": "*", 57 | "form-data": "^3.0.0" 58 | } 59 | }, 60 | "node_modules/@types/node-fetch/node_modules/form-data": { 61 | "version": "3.0.1", 62 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", 63 | "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", 64 | "dev": true, 65 | "dependencies": { 66 | "asynckit": "^0.4.0", 67 | "combined-stream": "^1.0.8", 68 | "mime-types": "^2.1.12" 69 | }, 70 | "engines": { 71 | "node": ">= 6" 72 | } 73 | }, 74 | "node_modules/@types/vscode": { 75 | "version": "1.83.1", 76 | "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.83.1.tgz", 77 | "integrity": "sha512-BHu51NaNKOtDf3BOonY3sKFFmZKEpRkzqkZVpSYxowLbs5JqjOQemYFob7Gs5rpxE5tiGhfpnMpcdF/oKrLg4w==", 78 | "dev": true 79 | }, 80 | "node_modules/asynckit": { 81 | "version": "0.4.0", 82 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 83 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 84 | }, 85 | "node_modules/axios": { 86 | "version": "1.6.0", 87 | "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", 88 | "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", 89 | "dependencies": { 90 | "follow-redirects": "^1.15.0", 91 | "form-data": "^4.0.0", 92 | "proxy-from-env": "^1.1.0" 93 | } 94 | }, 95 | "node_modules/combined-stream": { 96 | "version": "1.0.8", 97 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 98 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 99 | "dependencies": { 100 | "delayed-stream": "~1.0.0" 101 | }, 102 | "engines": { 103 | "node": ">= 0.8" 104 | } 105 | }, 106 | "node_modules/delayed-stream": { 107 | "version": "1.0.0", 108 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 109 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 110 | "engines": { 111 | "node": ">=0.4.0" 112 | } 113 | }, 114 | "node_modules/esbuild": { 115 | "version": "0.19.0", 116 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.0.tgz", 117 | "integrity": "sha512-i7i8TP4vuG55bKeLyqqk5sTPu1ZjPH3wkcLvAj/0X/222iWFo3AJUYRKjbOoY6BWFMH3teizxHEdV9Su5ESl0w==", 118 | "dev": true, 119 | "hasInstallScript": true, 120 | "bin": { 121 | "esbuild": "bin/esbuild" 122 | }, 123 | "engines": { 124 | "node": ">=12" 125 | }, 126 | "optionalDependencies": { 127 | "@esbuild/android-arm": "0.19.0", 128 | "@esbuild/android-arm64": "0.19.0", 129 | "@esbuild/android-x64": "0.19.0", 130 | "@esbuild/darwin-arm64": "0.19.0", 131 | "@esbuild/darwin-x64": "0.19.0", 132 | "@esbuild/freebsd-arm64": "0.19.0", 133 | "@esbuild/freebsd-x64": "0.19.0", 134 | "@esbuild/linux-arm": "0.19.0", 135 | "@esbuild/linux-arm64": "0.19.0", 136 | "@esbuild/linux-ia32": "0.19.0", 137 | "@esbuild/linux-loong64": "0.19.0", 138 | "@esbuild/linux-mips64el": "0.19.0", 139 | "@esbuild/linux-ppc64": "0.19.0", 140 | "@esbuild/linux-riscv64": "0.19.0", 141 | "@esbuild/linux-s390x": "0.19.0", 142 | "@esbuild/linux-x64": "0.19.0", 143 | "@esbuild/netbsd-x64": "0.19.0", 144 | "@esbuild/openbsd-x64": "0.19.0", 145 | "@esbuild/sunos-x64": "0.19.0", 146 | "@esbuild/win32-arm64": "0.19.0", 147 | "@esbuild/win32-ia32": "0.19.0", 148 | "@esbuild/win32-x64": "0.19.0" 149 | } 150 | }, 151 | "node_modules/follow-redirects": { 152 | "version": "1.15.3", 153 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", 154 | "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", 155 | "funding": [ 156 | { 157 | "type": "individual", 158 | "url": "https://github.com/sponsors/RubenVerborgh" 159 | } 160 | ], 161 | "engines": { 162 | "node": ">=4.0" 163 | }, 164 | "peerDependenciesMeta": { 165 | "debug": { 166 | "optional": true 167 | } 168 | } 169 | }, 170 | "node_modules/form-data": { 171 | "version": "4.0.0", 172 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 173 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 174 | "dependencies": { 175 | "asynckit": "^0.4.0", 176 | "combined-stream": "^1.0.8", 177 | "mime-types": "^2.1.12" 178 | }, 179 | "engines": { 180 | "node": ">= 6" 181 | } 182 | }, 183 | "node_modules/inherits": { 184 | "version": "2.0.3", 185 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 186 | "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" 187 | }, 188 | "node_modules/mime-db": { 189 | "version": "1.52.0", 190 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 191 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 192 | "engines": { 193 | "node": ">= 0.6" 194 | } 195 | }, 196 | "node_modules/mime-types": { 197 | "version": "2.1.35", 198 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 199 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 200 | "dependencies": { 201 | "mime-db": "1.52.0" 202 | }, 203 | "engines": { 204 | "node": ">= 0.6" 205 | } 206 | }, 207 | "node_modules/node-fetch": { 208 | "version": "2.6.12", 209 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", 210 | "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", 211 | "dependencies": { 212 | "whatwg-url": "^5.0.0" 213 | }, 214 | "engines": { 215 | "node": "4.x || >=6.0.0" 216 | }, 217 | "peerDependencies": { 218 | "encoding": "^0.1.0" 219 | }, 220 | "peerDependenciesMeta": { 221 | "encoding": { 222 | "optional": true 223 | } 224 | } 225 | }, 226 | "node_modules/ollama-node": { 227 | "version": "0.1.24", 228 | "resolved": "https://registry.npmjs.org/ollama-node/-/ollama-node-0.1.24.tgz", 229 | "integrity": "sha512-ZSaVC1E80XNm8utH74Vu7Qgfdmb9tWZKyPWqRo9uzMNaRMiHOd8qydBIngosISPHSDeCGqlo4YTm1PwNlUc/fw==", 230 | "dependencies": { 231 | "@types/node": "^20.8.4" 232 | } 233 | }, 234 | "node_modules/path": { 235 | "version": "0.12.7", 236 | "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", 237 | "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", 238 | "dependencies": { 239 | "process": "^0.11.1", 240 | "util": "^0.10.3" 241 | } 242 | }, 243 | "node_modules/process": { 244 | "version": "0.11.10", 245 | "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", 246 | "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", 247 | "engines": { 248 | "node": ">= 0.6.0" 249 | } 250 | }, 251 | "node_modules/proxy-from-env": { 252 | "version": "1.1.0", 253 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 254 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" 255 | }, 256 | "node_modules/tr46": { 257 | "version": "0.0.3", 258 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 259 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" 260 | }, 261 | "node_modules/undici-types": { 262 | "version": "5.26.5", 263 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 264 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" 265 | }, 266 | "node_modules/util": { 267 | "version": "0.10.4", 268 | "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", 269 | "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", 270 | "dependencies": { 271 | "inherits": "2.0.3" 272 | } 273 | }, 274 | "node_modules/webidl-conversions": { 275 | "version": "3.0.1", 276 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 277 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" 278 | }, 279 | "node_modules/whatwg-url": { 280 | "version": "5.0.0", 281 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 282 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 283 | "dependencies": { 284 | "tr46": "~0.0.3", 285 | "webidl-conversions": "^3.0.0" 286 | } 287 | } 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ollamamodelfile", 3 | "displayName": "Ollama Modelfile", 4 | "description": "Language extension for Ollama Modelfiles", 5 | "version": "0.0.18", 6 | "publisher": "technovangelist", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/technovangelist/OllamaModelFile-VSCodeExtension" 10 | }, 11 | "engines": { 12 | "vscode": "^1.81.0" 13 | }, 14 | "main": "./out/extension.js", 15 | "activationEvents": [ 16 | "workspaceContains:modelfile", 17 | "onStartupFinished" 18 | ], 19 | "categories": [ 20 | "Programming Languages" 21 | ], 22 | "contributes": { 23 | "themes": [ 24 | { 25 | "label": "Ollama Modelfile", 26 | "uiTheme": "hc-light", 27 | "path": "./ollama-modelfile-color-theme.json" 28 | } 29 | ], 30 | "languages": [ 31 | { 32 | "id": "modelfile", 33 | "aliases": [ 34 | "Ollama Modelfile", 35 | "modelfile" 36 | ], 37 | "filenamePatterns": [ 38 | "*.modelfile", 39 | "Modelfile", 40 | "Modelfile.*" 41 | ], 42 | "configuration": "./language-configuration.json" 43 | } 44 | ], 45 | "snippets": [ 46 | { 47 | "language": "modelfile", 48 | "path": "./snippets.json" 49 | } 50 | ], 51 | "grammars": [ 52 | { 53 | "scopeName": "source.modelfile", 54 | "language": "modelfile", 55 | "path": "./syntaxes/modelfile.tmLanguage.json" 56 | } 57 | ], 58 | "commands": [ 59 | { 60 | "command": "ollamamodelfile.createModel", 61 | "title": "Create Model", 62 | "category": "Ollama Modelfile" 63 | }, 64 | { 65 | "command": "ollamamodelfile.runModel", 66 | "title": "Run a Model", 67 | "category": "Ollama Modelfile" 68 | }, 69 | { 70 | "command": "ollamamodelfile.runModelVerbose", 71 | "title": "Run a Model with Verbose", 72 | "category": "Ollama Modelfile" 73 | } 74 | ] 75 | }, 76 | "scripts": { 77 | "vscode:prepublish": "npm run esbuild-base -- --minify", 78 | "esbuild-base": "esbuild extension.ts --bundle --outfile=out/extension.js --external:vscode --format=cjs --platform=node", 79 | "esbuild": "npm run esbuild-base -- --sourcemap", 80 | "esbuild-watch": "npm run esbuild-base -- --sourcemap --watch", 81 | "test-compile": "tsc -p ./" 82 | }, 83 | "devDependencies": { 84 | "@types/node": "^20.4.9", 85 | "@types/node-fetch": "^2.6.4", 86 | "@types/vscode": "^1.81.0", 87 | "esbuild": "^0.19.0" 88 | }, 89 | "dependencies": { 90 | "axios": "^1.6.0", 91 | "node-fetch": "^2.6.12", 92 | "ollama-node": "^0.1.24", 93 | "path": "^0.12.7" 94 | } 95 | } -------------------------------------------------------------------------------- /snippets.json: -------------------------------------------------------------------------------- 1 | { 2 | "Parent Model": { 3 | "prefix": "FROM", 4 | "body": "FROM ${1:model}", 5 | "description": "Specify parent model" 6 | }, 7 | "System Prompt": { 8 | "prefix": "SYSTEM", 9 | "body": [ 10 | "SYSTEM \"\"\"", 11 | "${1:You are an AI that answers every question as honestly as possible.}", 12 | "\"\"\"" 13 | ], 14 | "description": "Specify system prompt" 15 | }, 16 | "Empty Template": { 17 | "prefix": ["template"], 18 | "body": ["TEMPLATE \"\"\"", "$1", "\"\"\""], 19 | "description": "Template" 20 | }, 21 | "Template": { 22 | "prefix": ["template llama2"], 23 | "body": [ 24 | "TEMPLATE \"\"\"", 25 | "{{- if and .First .System }}", 26 | "<>", 27 | "{{ .System }}", 28 | "<>", 29 | "{{- end }}", 30 | "", 31 | "[INST] {{ .Prompt }} [/INST]", 32 | "\"\"\"" 33 | ], 34 | "description": "Specify First System Prompt for Llama2 Models" 35 | }, 36 | "Template for Alpaca": { 37 | "prefix": ["template alpaca"], 38 | "body": [ 39 | "TEMPLATE \"\"\"", 40 | "{{- if and .First .System }}", 41 | "### Input:", 42 | "{{ .System }}", 43 | "{{- end }}", 44 | "### Instruction:", 45 | "{{ .Prompt }}", 46 | "### Response:", 47 | "\"\"\"" 48 | ], 49 | "description": "Specify First System Prompt for Alpaca Models" 50 | }, 51 | "Template for Orca": { 52 | "prefix": ["template orca"], 53 | "body": [ 54 | "TEMPLATE \"\"\"", 55 | "{{- if and .First .System }}", 56 | "### System:", 57 | "{{ .System }}", 58 | "{{- end }}", 59 | "### User:", 60 | "{{ .Prompt }}", 61 | "### Response:", 62 | "\"\"\"" 63 | ], 64 | "description": "Specify First System Prompt for Alpaca Models" 65 | }, 66 | "Template for Pygmalion": { 67 | "prefix": ["template pygmalion"], 68 | "body": [ 69 | "TEMPLATE \"\"\"", 70 | "{{- if .First }}", 71 | "${1:name}'s Persona: Describe the persona here", 72 | "", 73 | "You: How are you doing on this wonderful day?", 74 | "${1:name}: Great, its a lovely day. How are you?", 75 | "{{- end }}", 76 | "You: {{.Prompt }}", 77 | "${1:name}: ", 78 | "\"\"\"" 79 | ], 80 | "description": "Specify First System Prompt for Pygmalion Models" 81 | }, 82 | "Temperature": { 83 | "prefix": "TEMPERATURE", 84 | "body": ["PARAMETER TEMPERATURE ${1:0.9}", ""], 85 | "description": "Specify temperature" 86 | }, 87 | "TopP": { 88 | "prefix": "top p", 89 | "body": ["PARAMETER TOP_P ${1:0.50}", ""], 90 | "description": "Specify Top P" 91 | }, 92 | "TopK": { 93 | "prefix": "top k", 94 | "body": ["PARAMETER TOP_K ${1:10}", ""], 95 | "description": "Specify Top K" 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /syntaxes/modelfile.tmLanguage.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", 3 | "name": "modelfile", 4 | "patterns": [ 5 | { 6 | "include": "#keywords" 7 | }, 8 | { 9 | "include": "#strings" 10 | } 11 | ], 12 | "repository": { 13 | 14 | "keywords": { 15 | 16 | "patterns": [ 17 | { 18 | 19 | "name": "modelfile.keyword", 20 | "match": "FROM|TEMPLATE|SYSTEM|PARAMETER" 21 | 22 | } 23 | ] 24 | }, 25 | 26 | "strings": { 27 | "name": "string.quoted.double.modelfile", 28 | "begin": "\"", 29 | "end": "\"", 30 | "patterns": [ 31 | { 32 | "name": "constant.character.escape.modelfile", 33 | "match": "\\\\." 34 | } 35 | ] 36 | } 37 | }, 38 | "scopeName": "source.modelfile" 39 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2020", 5 | "lib": ["es2020"], 6 | "outDir": "out", 7 | "sourceMap": true, 8 | "strict": true 9 | }, 10 | "exclude": ["node_modules", ".vscode-test"], 11 | } 12 | --------------------------------------------------------------------------------