mirror of
https://github.com/voideditor/void
synced 2026-05-23 09:28:23 +00:00
Merge remote-tracking branch 'origin/main' into model-selection
This commit is contained in:
commit
a5a8559a20
11 changed files with 249 additions and 220 deletions
|
|
@ -23,11 +23,11 @@ Most of Void's code lives in the folder `src/vs/workbench/contrib/void/`.
|
|||
|
||||
## Building Void
|
||||
|
||||
### a. Build Prerequisites - Mac
|
||||
### a. Mac - Build Prerequisites
|
||||
|
||||
If you're using a Mac, you need Python and XCode. You probably have these by default.
|
||||
|
||||
### b. Build Prerequisites - Windows
|
||||
### b. Windows - Build Prerequisites
|
||||
|
||||
If you're using a Windows computer, first get [Visual Studio 2022](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community) (recommended) or [VS Build Tools](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools) (not recommended). If you already have both, you might need to run the next few steps on both of them.
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ Go to the "Individual Components" tab and select:
|
|||
|
||||
Finally, click Install.
|
||||
|
||||
### c. Build Prerequisites - Linux
|
||||
### c. Linux - Build Prerequisites
|
||||
|
||||
First, run `npm install -g node-gyp`. Then:
|
||||
|
||||
|
|
@ -50,27 +50,28 @@ First, run `npm install -g node-gyp`. Then:
|
|||
- Red Hat (Fedora, etc): `sudo dnf install @development-tools gcc gcc-c++ make libsecret-devel krb5-devel libX11-devel libxkbfile-devel`.
|
||||
- Others: see [How to Contribute](https://github.com/microsoft/vscode/wiki/How-to-Contribute).
|
||||
|
||||
### d. Building Void
|
||||
### d. Building Void from inside VSCode
|
||||
|
||||
To build Void, open `void/` inside VSCode. Then open your terminal and run:
|
||||
|
||||
1. `npm install` to install all dependencies.
|
||||
2. `npm run watchreact` to build Void's browser dependencies like React. (If this doesn't work, try `npm run buildreact`).
|
||||
3. Build Void.
|
||||
2. Build Void.
|
||||
- Press <kbd>Cmd+Shift+B</kbd> (Mac).
|
||||
- Press <kbd>Ctrl+Shift+B</kbd> (Windows/Linux).
|
||||
- This step can take ~5 min. The build is done when you see two check marks (one of the items will continue spinning indefinitely - it compiles our React code).
|
||||
4. Run Void.
|
||||
3. Run Void.
|
||||
- Run `./scripts/code.sh` (Mac/Linux).
|
||||
- Run `./scripts/code.bat` (Windows).
|
||||
6. Nice-to-knows.
|
||||
4. Nice-to-knows.
|
||||
- You can always press <kbd>Ctrl+R</kbd> (<kbd>Cmd+R</kbd>) inside the new window to reload and see your new changes. It's faster than <kbd>Ctrl+Shift+P</kbd> and `Reload Window`.
|
||||
- You might want to add the flags `--user-data-dir ./.tmp/user-data --extensions-dir ./.tmp/extensions` to the above run command, which lets you delete the `.tmp` folder to reset any IDE changes you made when testing.
|
||||
- You can kill any of the build scripts by pressing `Ctrl+D` in VSCode terminal. If you press `Ctrl+C` the script will close but will keep running in the background (to open all background scripts, just re-build).
|
||||
|
||||
If you get any errors, scroll down for common fixes.
|
||||
|
||||
#### Building Void from Terminal
|
||||
|
||||
Alternatively, if you want to build Void from the terminal, instead of pressing <kbd>Cmd+Shift+B</kbd> you can run `npm run watch`. The build is done when you see something like this:
|
||||
To build Void from the terminal instead of from inside VSCode, follow the steps above, but instead of pressing <kbd>Cmd+Shift+B</kbd>, run `npm run watch`. The build is done when you see something like this:
|
||||
|
||||
```
|
||||
[watch-extensions] [00:37:39] Finished compilation extensions with 0 errors after 19303 ms
|
||||
|
|
@ -80,15 +81,17 @@ Alternatively, if you want to build Void from the terminal, instead of pressing
|
|||
```
|
||||
|
||||
|
||||
|
||||
#### Common Fixes
|
||||
|
||||
- Make sure you followed the prerequisite steps.
|
||||
- Make sure you followed the prerequisite steps above.
|
||||
- Make sure you have Node version `20.18.2` (the version in `.nvmrc`)!
|
||||
- If you get `"TypeError: Failed to fetch dynamically imported module"`, make sure all imports end with `.js`.
|
||||
- If you get an error with React, try running `NODE_OPTIONS="--max-old-space-size=8192" npm run buildreact`.
|
||||
- If you see missing styles, wait a few seconds and then reload.
|
||||
- If you have any questions, feel free to [submit an issue](https://github.com/voideditor/void/issues/new). You can also refer to VSCode's complete [How to Contribute](https://github.com/microsoft/vscode/wiki/How-to-Contribute) page.
|
||||
- If you get errors like `npm error libtool: error: unrecognised option: '-static'`, make sure you have GNU libtool instead of BSD libtool (BSD is the default in macos)
|
||||
- If you get errors like `npm error libtool: error: unrecognised option: '-static'`, when running ./scripts/code.sh, make sure you have GNU libtool instead of BSD libtool (BSD is the default in macos)
|
||||
- If you get erorrs like `The SUID sandbox helper binary was found, but is not configured correctly` when running ./scripts/code.sh, run
|
||||
`sudo chown root:root .build/electron/chrome-sandbox && sudo chmod 4755 .build/electron/chrome-sandbox` and then run `./scripts/code.sh` again.
|
||||
- If you have any other questions, feel free to [submit an issue](https://github.com/voideditor/void/issues/new). You can also refer to VSCode's complete [How to Contribute](https://github.com/microsoft/vscode/wiki/How-to-Contribute) page.
|
||||
|
||||
|
||||
## Packaging
|
||||
|
|
|
|||
146
package-lock.json
generated
146
package-lock.json
generated
|
|
@ -42,6 +42,7 @@
|
|||
"@xterm/addon-webgl": "^0.19.0-beta.98",
|
||||
"@xterm/headless": "^5.6.0-beta.98",
|
||||
"@xterm/xterm": "^5.6.0-beta.98",
|
||||
"ajv": "^8.17.1",
|
||||
"cross-spawn": "^7.0.6",
|
||||
"diff": "^7.0.0",
|
||||
"eslint-plugin-react": "^7.37.4",
|
||||
|
|
@ -1686,6 +1687,30 @@
|
|||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc/node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "9.25.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.25.0.tgz",
|
||||
|
|
@ -5477,16 +5502,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
|
|
@ -5511,30 +5535,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/ajv-formats/node_modules/ajv": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv-formats/node_modules/json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ajv-keywords": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
||||
|
|
@ -9272,6 +9272,23 @@
|
|||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/glob-parent": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
||||
|
|
@ -9285,6 +9302,13 @@
|
|||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/esniff": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
|
||||
|
|
@ -9743,7 +9767,6 @@
|
|||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-fifo": {
|
||||
|
|
@ -9788,7 +9811,6 @@
|
|||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
|
||||
"integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
|
|
@ -9898,6 +9920,23 @@
|
|||
"webpack": "^4.0.0 || ^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/file-loader/node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/file-loader/node_modules/ajv-keywords": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||
|
|
@ -9908,6 +9947,13 @@
|
|||
"ajv": "^6.9.1"
|
||||
}
|
||||
},
|
||||
"node_modules/file-loader/node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/file-loader/node_modules/schema-utils": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
|
||||
|
|
@ -14925,10 +14971,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true,
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-stable-stringify-without-jsonify": {
|
||||
|
|
@ -20618,7 +20663,6 @@
|
|||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
|
|
@ -21109,30 +21153,6 @@
|
|||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/schema-utils/node_modules/ajv": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/schema-utils/node_modules/json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/scope-tailwind": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/scope-tailwind/-/scope-tailwind-1.0.9.tgz",
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@
|
|||
"@xterm/addon-webgl": "^0.19.0-beta.98",
|
||||
"@xterm/headless": "^5.6.0-beta.98",
|
||||
"@xterm/xterm": "^5.6.0-beta.98",
|
||||
"ajv": "^8.17.1",
|
||||
"cross-spawn": "^7.0.6",
|
||||
"diff": "^7.0.0",
|
||||
"eslint-plugin-react": "^7.37.4",
|
||||
|
|
|
|||
|
|
@ -5,9 +5,6 @@
|
|||
|
||||
import React, { JSX, useMemo, useState } from 'react'
|
||||
import { marked, MarkedToken, Token } from 'marked'
|
||||
import katex from 'katex'
|
||||
import 'katex/dist/katex.min.css'
|
||||
import dompurify from '../../../../../../../base/browser/dompurify/dompurify.js'
|
||||
|
||||
import { convertToVscodeLang, detectLanguage } from '../../../../common/helpers/languageHelpers.js'
|
||||
import { BlockCodeApplyWrapper } from './ApplyBlockHoverButtons.js'
|
||||
|
|
@ -36,59 +33,59 @@ function isValidUri(s: string): boolean {
|
|||
|
||||
// renders contiguous string of latex eg $e^{i\pi}$
|
||||
const LatexRender = ({ latex }: { latex: string }) => {
|
||||
return <span className="katex-error text-red-500">{latex}</span>
|
||||
// try {
|
||||
// let formula = latex;
|
||||
// let displayMode = false;
|
||||
|
||||
try {
|
||||
let formula = latex;
|
||||
let displayMode = false;
|
||||
// // Extract the formula from delimiters
|
||||
// if (latex.startsWith('$') && latex.endsWith('$')) {
|
||||
// // Check if it's display math $$...$$
|
||||
// if (latex.startsWith('$$') && latex.endsWith('$$')) {
|
||||
// formula = latex.slice(2, -2);
|
||||
// displayMode = true;
|
||||
// } else {
|
||||
// formula = latex.slice(1, -1);
|
||||
// }
|
||||
// } else if (latex.startsWith('\\(') && latex.endsWith('\\)')) {
|
||||
// formula = latex.slice(2, -2);
|
||||
// } else if (latex.startsWith('\\[') && latex.endsWith('\\]')) {
|
||||
// formula = latex.slice(2, -2);
|
||||
// displayMode = true;
|
||||
// }
|
||||
|
||||
// Extract the formula from delimiters
|
||||
if (latex.startsWith('$') && latex.endsWith('$')) {
|
||||
// Check if it's display math $$...$$
|
||||
if (latex.startsWith('$$') && latex.endsWith('$$')) {
|
||||
formula = latex.slice(2, -2);
|
||||
displayMode = true;
|
||||
} else {
|
||||
formula = latex.slice(1, -1);
|
||||
}
|
||||
} else if (latex.startsWith('\\(') && latex.endsWith('\\)')) {
|
||||
formula = latex.slice(2, -2);
|
||||
} else if (latex.startsWith('\\[') && latex.endsWith('\\]')) {
|
||||
formula = latex.slice(2, -2);
|
||||
displayMode = true;
|
||||
}
|
||||
// // Render LaTeX
|
||||
// const html = katex.renderToString(formula, {
|
||||
// displayMode: displayMode,
|
||||
// throwOnError: false,
|
||||
// output: 'html'
|
||||
// });
|
||||
|
||||
// Render LaTeX
|
||||
const html = katex.renderToString(formula, {
|
||||
displayMode: displayMode,
|
||||
throwOnError: false,
|
||||
output: 'html'
|
||||
});
|
||||
// // Sanitize the HTML output with DOMPurify
|
||||
// const sanitizedHtml = dompurify.sanitize(html, {
|
||||
// RETURN_TRUSTED_TYPE: true,
|
||||
// USE_PROFILES: { html: true, svg: true, mathMl: true }
|
||||
// });
|
||||
|
||||
// Sanitize the HTML output with DOMPurify
|
||||
const sanitizedHtml = dompurify.sanitize(html, {
|
||||
RETURN_TRUSTED_TYPE: true,
|
||||
USE_PROFILES: { html: true, svg: true, mathMl: true }
|
||||
});
|
||||
// // Add proper styling based on mode
|
||||
// const className = displayMode
|
||||
// ? 'katex-block my-2 text-center'
|
||||
// : 'katex-inline';
|
||||
|
||||
// Add proper styling based on mode
|
||||
const className = displayMode
|
||||
? 'katex-block my-2 text-center'
|
||||
: 'katex-inline';
|
||||
// // Use the ref approach to avoid dangerouslySetInnerHTML
|
||||
// const mathRef = React.useRef<HTMLSpanElement>(null);
|
||||
|
||||
// Use the ref approach to avoid dangerouslySetInnerHTML
|
||||
const mathRef = React.useRef<HTMLSpanElement>(null);
|
||||
// React.useEffect(() => {
|
||||
// if (mathRef.current) {
|
||||
// mathRef.current.innerHTML = sanitizedHtml as unknown as string;
|
||||
// }
|
||||
// }, [sanitizedHtml]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (mathRef.current) {
|
||||
mathRef.current.innerHTML = sanitizedHtml as unknown as string;
|
||||
}
|
||||
}, [sanitizedHtml]);
|
||||
|
||||
return <span ref={mathRef} className={className}></span>;
|
||||
} catch (error) {
|
||||
console.error('KaTeX rendering error:', error);
|
||||
return <span className="katex-error text-red-500">{latex}</span>;
|
||||
}
|
||||
// return <span ref={mathRef} className={className}></span>;
|
||||
// } catch (error) {
|
||||
// console.error('KaTeX rendering error:', error);
|
||||
// return <span className="katex-error text-red-500">{latex}</span>;
|
||||
// }
|
||||
}
|
||||
|
||||
const Codespan = ({ text, className, onClick }: { text: string, className?: string, onClick?: () => void }) => {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import { MAX_FILE_CHARS_PAGE, MAX_TERMINAL_INACTIVE_TIME, ToolName, toolNames }
|
|||
import { RawToolCallObj } from '../../../../common/sendLLMMessageTypes.js';
|
||||
import ErrorBoundary from './ErrorBoundary.js';
|
||||
import { ToolApprovalTypeSwitch } from '../void-settings-tsx/Settings.js';
|
||||
import { terminalNameOfId } from '../../../terminalToolService.js';
|
||||
|
||||
|
||||
|
||||
|
|
@ -696,6 +697,7 @@ type ToolHeaderParams = {
|
|||
children?: React.ReactNode;
|
||||
bottomChildren?: React.ReactNode;
|
||||
onClick?: () => void;
|
||||
desc2OnClick?: () => void;
|
||||
isOpen?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
|
@ -713,6 +715,7 @@ const ToolHeaderWrapper = ({
|
|||
bottomChildren,
|
||||
isError,
|
||||
onClick,
|
||||
desc2OnClick,
|
||||
isOpen,
|
||||
isRejected,
|
||||
className, // applies to the main content
|
||||
|
|
@ -781,7 +784,7 @@ const ToolHeaderWrapper = ({
|
|||
data-tooltip-content={'Canceled'}
|
||||
data-tooltip-place='top'
|
||||
/>}
|
||||
{desc2 && <span className="text-void-fg-4 text-xs">
|
||||
{desc2 && <span className="text-void-fg-4 text-xs" onClick={desc2OnClick}>
|
||||
{desc2}
|
||||
</span>}
|
||||
{numResults !== undefined && (
|
||||
|
|
@ -1416,7 +1419,7 @@ const toolNameToDesc = (toolName: ToolName, _toolParams: ToolCallParams[ToolName
|
|||
const toolParams = _toolParams as ToolCallParams['run_command']
|
||||
return {
|
||||
desc1: `"${toolParams.command}"`,
|
||||
desc1Info: toolParams.bgTerminalId
|
||||
desc1Info: toolParams.persistentTerminalId
|
||||
}
|
||||
},
|
||||
'open_persistent_terminal': () => {
|
||||
|
|
@ -1425,7 +1428,7 @@ const toolNameToDesc = (toolName: ToolName, _toolParams: ToolCallParams[ToolName
|
|||
},
|
||||
'kill_persistent_terminal': () => {
|
||||
const toolParams = _toolParams as ToolCallParams['kill_persistent_terminal']
|
||||
return { desc1: toolParams.terminalId }
|
||||
return { desc1: toolParams.persistentTerminalId }
|
||||
},
|
||||
'get_dir_tree': () => {
|
||||
const toolParams = _toolParams as ToolCallParams['get_dir_tree']
|
||||
|
|
@ -2081,6 +2084,7 @@ const toolNameToComponent: { [T in ToolName]: { resultWrapper: ResultWrapper<T>,
|
|||
const accessor = useAccessor()
|
||||
const commandService = accessor.get('ICommandService')
|
||||
const terminalToolsService = accessor.get('ITerminalToolService')
|
||||
const toolsService = accessor.get('IToolsService')
|
||||
const isError = toolMessage.type === 'tool_error'
|
||||
const title = getTitle(toolMessage)
|
||||
const { desc1, desc1Info } = toolNameToDesc(toolMessage.name, toolMessage.params, accessor)
|
||||
|
|
@ -2090,19 +2094,21 @@ const toolNameToComponent: { [T in ToolName]: { resultWrapper: ResultWrapper<T>,
|
|||
const { rawParams, params } = toolMessage
|
||||
const componentParams: ToolHeaderParams = { title, desc1, desc1Info, isError, icon, isRejected, }
|
||||
|
||||
const { command, persistentTerminalId } = params
|
||||
if (persistentTerminalId) {
|
||||
componentParams.desc2 = terminalNameOfId(persistentTerminalId)
|
||||
componentParams.desc2OnClick = () => terminalToolsService.focusTerminal(persistentTerminalId)
|
||||
}
|
||||
|
||||
|
||||
if (toolMessage.type === 'success') {
|
||||
const { result } = toolMessage
|
||||
const { command } = params
|
||||
const { resolveReason, result: terminalResult } = result
|
||||
|
||||
// it's unclear that this is a button and not an icon.
|
||||
// componentParams.desc2 = <JumpToTerminalButton
|
||||
// onClick={() => { terminalToolsService.openTerminal(terminalId) }}
|
||||
// />
|
||||
|
||||
const additionalDetailsStr = resolveReason.type === 'done' ? (resolveReason.exitCode !== 0 ? `\nError: exit code ${resolveReason.exitCode}` : null)
|
||||
: resolveReason.type === 'timeout' ? `\n(timed out)`
|
||||
: null
|
||||
const msg = toolsService.stringOfResult['run_command'](params, result)
|
||||
|
||||
componentParams.children = <ToolChildrenWrapper className='whitespace-pre text-nowrap overflow-auto text-sm'>
|
||||
<div className='!select-text cursor-auto'>
|
||||
|
|
@ -2110,25 +2116,14 @@ const toolNameToComponent: { [T in ToolName]: { resultWrapper: ResultWrapper<T>,
|
|||
<span className="text-void-fg-1 font-sans">{`Ran command: `}</span>
|
||||
<span className="font-mono">{command}</span>
|
||||
</div>
|
||||
{(terminalResult + additionalDetailsStr).length && <div>
|
||||
{msg.length && <div>
|
||||
<span className='text-void-fg-1'>{`Result: `}</span>
|
||||
<span className="font-mono">{terminalResult}</span>
|
||||
<span className="font-mono">{additionalDetailsStr}</span>
|
||||
<span className="font-mono">{msg}</span>
|
||||
</div>}
|
||||
</div>
|
||||
</ToolChildrenWrapper>
|
||||
|
||||
if (params.bgTerminalId)
|
||||
componentParams.desc2 = `(terminal ${params.bgTerminalId})`
|
||||
|
||||
}
|
||||
else if (toolMessage.type === 'rejected' || toolMessage.type === 'tool_error' || toolMessage.type === 'running_now' || toolMessage.type === 'tool_request') {
|
||||
const { bgTerminalId, command } = params
|
||||
if (bgTerminalId) {
|
||||
componentParams.desc2 = '(persistent terminal)'
|
||||
if (terminalToolsService.terminalExists(bgTerminalId))
|
||||
componentParams.onClick = () => terminalToolsService.focusTerminal(bgTerminalId)
|
||||
}
|
||||
if (toolMessage.type === 'tool_error') {
|
||||
const { result } = toolMessage
|
||||
componentParams.children = <ToolChildrenWrapper>{result}</ToolChildrenWrapper>
|
||||
|
|
@ -2158,12 +2153,9 @@ const toolNameToComponent: { [T in ToolName]: { resultWrapper: ResultWrapper<T>,
|
|||
|
||||
if (toolMessage.type === 'success') {
|
||||
const { result } = toolMessage
|
||||
const { terminalId } = result
|
||||
if (terminalId) {
|
||||
componentParams.desc2 = `(terminal ${terminalId})`
|
||||
if (terminalToolsService.terminalExists(terminalId))
|
||||
componentParams.onClick = () => terminalToolsService.focusTerminal(terminalId)
|
||||
}
|
||||
const { persistentTerminalId } = result
|
||||
componentParams.desc1 = terminalNameOfId(persistentTerminalId)
|
||||
componentParams.onClick = () => terminalToolsService.focusTerminal(persistentTerminalId)
|
||||
}
|
||||
else if (toolMessage.type === 'tool_error') {
|
||||
const { result } = toolMessage
|
||||
|
|
@ -2181,6 +2173,7 @@ const toolNameToComponent: { [T in ToolName]: { resultWrapper: ResultWrapper<T>,
|
|||
resultWrapper: ({ toolMessage }) => {
|
||||
const accessor = useAccessor()
|
||||
const commandService = accessor.get('ICommandService')
|
||||
const terminalToolsService = accessor.get('ITerminalToolService')
|
||||
|
||||
const { desc1, desc1Info } = toolNameToDesc(toolMessage.name, toolMessage.params, accessor)
|
||||
const title = getTitle(toolMessage)
|
||||
|
|
@ -2195,7 +2188,9 @@ const toolNameToComponent: { [T in ToolName]: { resultWrapper: ResultWrapper<T>,
|
|||
const componentParams: ToolHeaderParams = { title, desc1, desc1Info, isError, icon, }
|
||||
|
||||
if (toolMessage.type === 'success') {
|
||||
const { result } = toolMessage
|
||||
const { persistentTerminalId } = params
|
||||
componentParams.desc1 = terminalNameOfId(persistentTerminalId)
|
||||
componentParams.onClick = () => terminalToolsService.focusTerminal(persistentTerminalId)
|
||||
}
|
||||
else if (toolMessage.type === 'tool_error') {
|
||||
const { result } = toolMessage
|
||||
|
|
|
|||
|
|
@ -726,6 +726,7 @@ export const VoidInputBox2 = forwardRef<HTMLTextAreaElement, InputBox2Props>(fun
|
|||
rows={1}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
{/* <div>{`idx ${optionIdx}`}</div> */}
|
||||
{isMenuOpen && (
|
||||
<div
|
||||
ref={refs.setFloating}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { ChatMarkdownRender } from '../markdown/ChatMarkdownRender.js';
|
|||
import { AddModelInputBox, AnimatedCheckmarkButton, OllamaSetupInstructions, OneClickSwitchButton, SettingsForProvider } from '../void-settings-tsx/Settings.js';
|
||||
import { ColorScheme } from '../../../../../../../platform/theme/common/theme.js';
|
||||
import ErrorBoundary from '../sidebar-tsx/ErrorBoundary.js';
|
||||
import { isLinux } from '../../../../../../../base/common/platform.js';
|
||||
|
||||
const OVERRIDE_VALUE = false
|
||||
|
||||
|
|
@ -603,7 +604,7 @@ const VoidOnboardingContent = () => {
|
|||
|
||||
{/* Slice of Void image */}
|
||||
<div className='max-w-md w-full h-[30vh] mx-auto flex items-center justify-center'>
|
||||
<VoidIcon />
|
||||
{!isLinux && <VoidIcon />}
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { registerSingleton, InstantiationType } from '../../../../platform/insta
|
|||
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
|
||||
import { TerminalExitReason, TerminalLocation } from '../../../../platform/terminal/common/terminal.js';
|
||||
import { ITerminalService, ITerminalInstance } from '../../../../workbench/contrib/terminal/browser/terminal.js';
|
||||
import { MAX_TERMINAL_CHARS, MAX_TERMINAL_INACTIVE_TIME } from '../common/prompt/prompts.js';
|
||||
import { MAX_TERMINAL_BG_COMMAND_TIME, MAX_TERMINAL_CHARS, MAX_TERMINAL_INACTIVE_TIME } from '../common/prompt/prompts.js';
|
||||
import { TerminalResolveReason } from '../common/toolsServiceTypes.js';
|
||||
|
||||
|
||||
|
|
@ -39,11 +39,11 @@ function isCommandComplete(output: string) {
|
|||
}
|
||||
|
||||
|
||||
const nameOfId = (id: string) => {
|
||||
export const terminalNameOfId = (id: string) => {
|
||||
if (id === '1') return 'Void Agent'
|
||||
return `Void Agent (${id})`
|
||||
}
|
||||
const idOfName = (name: string) => {
|
||||
export const idOfTerminalName = (name: string) => {
|
||||
if (name === 'Void Agent') return '1'
|
||||
|
||||
const match = name.match(/Void Agent \((\d+)\)/)
|
||||
|
|
@ -66,7 +66,7 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ
|
|||
const initializeTerminal = (terminal: ITerminalInstance) => {
|
||||
// when exit, remove
|
||||
const d = terminal.onExit(() => {
|
||||
const terminalId = idOfName(terminal.title)
|
||||
const terminalId = idOfTerminalName(terminal.title)
|
||||
if (terminalId !== null && (terminalId in this.terminalInstanceOfId)) delete this.terminalInstanceOfId[terminalId]
|
||||
d.dispose()
|
||||
})
|
||||
|
|
@ -75,7 +75,7 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ
|
|||
|
||||
// initialize any terminals that are already open
|
||||
for (const terminal of terminalService.instances) {
|
||||
const proposedTerminalId = idOfName(terminal.title)
|
||||
const proposedTerminalId = idOfTerminalName(terminal.title)
|
||||
if (proposedTerminalId) this.terminalInstanceOfId[proposedTerminalId] = terminal
|
||||
|
||||
initializeTerminal(terminal)
|
||||
|
|
@ -111,7 +111,7 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ
|
|||
const terminalId = this.getValidNewTerminalId();
|
||||
const terminal = await this.terminalService.createTerminal({
|
||||
location: TerminalLocation.Panel,
|
||||
config: { name: nameOfId(terminalId), title: nameOfId(terminalId) },
|
||||
config: { name: terminalNameOfId(terminalId), title: terminalNameOfId(terminalId) },
|
||||
})
|
||||
|
||||
|
||||
|
|
@ -207,26 +207,34 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ
|
|||
// send the command here
|
||||
await terminal.sendText(command, true)
|
||||
|
||||
// inactivity-based timeout
|
||||
const waitUntilInactive = new Promise<void>(res => {
|
||||
let globalTimeoutId: ReturnType<typeof setTimeout>;
|
||||
const resetTimer = () => {
|
||||
clearTimeout(globalTimeoutId);
|
||||
globalTimeoutId = setTimeout(() => {
|
||||
if (resolveReason) return
|
||||
|
||||
const waitUntilInterrupt = isBG ?
|
||||
// timeout after X seconds
|
||||
new Promise<void>((res) => {
|
||||
setTimeout(() => {
|
||||
resolveReason = { type: 'timeout' };
|
||||
res();
|
||||
}, MAX_TERMINAL_INACTIVE_TIME * 1000);
|
||||
};
|
||||
res()
|
||||
}, MAX_TERMINAL_BG_COMMAND_TIME * 1000)
|
||||
})
|
||||
// inactivity-based timeout
|
||||
: new Promise<void>(res => {
|
||||
let globalTimeoutId: ReturnType<typeof setTimeout>;
|
||||
const resetTimer = () => {
|
||||
clearTimeout(globalTimeoutId);
|
||||
globalTimeoutId = setTimeout(() => {
|
||||
if (resolveReason) return
|
||||
|
||||
const dTimeout = terminal.onData(() => { resetTimer(); });
|
||||
disposables.push(dTimeout, toDisposable(() => clearTimeout(globalTimeoutId)));
|
||||
resetTimer();
|
||||
});
|
||||
resolveReason = { type: 'timeout' };
|
||||
res();
|
||||
}, MAX_TERMINAL_INACTIVE_TIME * 1000);
|
||||
};
|
||||
|
||||
const dTimeout = terminal.onData(() => { resetTimer(); });
|
||||
disposables.push(dTimeout, toDisposable(() => clearTimeout(globalTimeoutId)));
|
||||
resetTimer();
|
||||
})
|
||||
|
||||
// wait for result
|
||||
await Promise.any([waitUntilDone, waitUntilInactive,])
|
||||
await Promise.any([waitUntilDone, waitUntilInterrupt])
|
||||
|
||||
disposables.forEach(d => d.dispose())
|
||||
if (!isBG) {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import { computeDirectoryTree1Deep, IDirectoryStrService, stringifyDirectoryTree
|
|||
import { IMarkerService, MarkerSeverity } from '../../../../platform/markers/common/markers.js'
|
||||
import { timeout } from '../../../../base/common/async.js'
|
||||
import { RawToolParamsObj } from '../common/sendLLMMessageTypes.js'
|
||||
import { MAX_CHILDREN_URIs_PAGE, MAX_FILE_CHARS_PAGE, MAX_TERMINAL_INACTIVE_TIME, ToolName } from '../common/prompt/prompts.js'
|
||||
import { MAX_CHILDREN_URIs_PAGE, MAX_FILE_CHARS_PAGE, MAX_TERMINAL_BG_COMMAND_TIME, MAX_TERMINAL_INACTIVE_TIME, ToolName } from '../common/prompt/prompts.js'
|
||||
import { IVoidSettingsService } from '../common/voidSettingsService.js'
|
||||
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ const validateRecursiveParamStr = (paramsUnknown: unknown) => {
|
|||
}
|
||||
|
||||
const validateProposedTerminalId = (terminalIdUnknown: unknown) => {
|
||||
if (!terminalIdUnknown) return '1'
|
||||
if (!terminalIdUnknown) throw new Error(`A value for terminalID must be specified, but the value was "${terminalIdUnknown}"`)
|
||||
const terminalId = terminalIdUnknown + ''
|
||||
return terminalId
|
||||
}
|
||||
|
|
@ -259,19 +259,19 @@ export class ToolsService implements IToolsService {
|
|||
// ---
|
||||
|
||||
run_command: (params: RawToolParamsObj) => {
|
||||
const { command: commandUnknown, terminal_id: terminalIdUnknown } = params;
|
||||
const { command: commandUnknown, persistent_terminal_id: terminalIdUnknown } = params;
|
||||
const command = validateStr('command', commandUnknown);
|
||||
const proposedTerminalId = terminalIdUnknown ? validateProposedTerminalId(terminalIdUnknown) : null;
|
||||
return { command, bgTerminalId: proposedTerminalId };
|
||||
const persistentTerminalId = terminalIdUnknown ? validateProposedTerminalId(terminalIdUnknown) : null;
|
||||
return { command, persistentTerminalId };
|
||||
},
|
||||
open_persistent_terminal: (_params: RawToolParamsObj) => {
|
||||
// No parameters needed; will open a new background terminal
|
||||
return {};
|
||||
},
|
||||
kill_persistent_terminal: (params: RawToolParamsObj) => {
|
||||
const { terminal_id: terminalIdUnknown } = params;
|
||||
const terminalId = validateProposedTerminalId(terminalIdUnknown);
|
||||
return { terminalId };
|
||||
const { persistent_terminal_id: terminalIdUnknown } = params;
|
||||
const persistentTerminalId = validateProposedTerminalId(terminalIdUnknown);
|
||||
return { persistentTerminalId };
|
||||
},
|
||||
|
||||
}
|
||||
|
|
@ -425,21 +425,20 @@ export class ToolsService implements IToolsService {
|
|||
return { result: lintErrorsPromise }
|
||||
},
|
||||
// ---
|
||||
run_command: async ({ command, bgTerminalId }) => {
|
||||
const { terminalId, resPromise } = await this.terminalToolService.runCommand(command, bgTerminalId)
|
||||
run_command: async ({ command, persistentTerminalId }) => {
|
||||
const { terminalId, resPromise } = await this.terminalToolService.runCommand(command, persistentTerminalId)
|
||||
const interruptTool = () => {
|
||||
this.terminalToolService.killTerminal(terminalId)
|
||||
}
|
||||
return { result: resPromise, interruptTool }
|
||||
},
|
||||
open_persistent_terminal: async () => {
|
||||
// Open a new background terminal without waiting for completion
|
||||
const terminalId = await this.terminalToolService.createTerminal()
|
||||
return { result: { terminalId } }
|
||||
const persistentTerminalId = await this.terminalToolService.createTerminal()
|
||||
return { result: { persistentTerminalId } }
|
||||
},
|
||||
kill_persistent_terminal: async ({ terminalId }) => {
|
||||
kill_persistent_terminal: async ({ persistentTerminalId }) => {
|
||||
// Close the background terminal by sending exit
|
||||
await this.terminalToolService.killTerminal(terminalId)
|
||||
await this.terminalToolService.killTerminal(persistentTerminalId)
|
||||
return { result: {} }
|
||||
},
|
||||
|
||||
|
|
@ -517,18 +516,18 @@ export class ToolsService implements IToolsService {
|
|||
resolveReason,
|
||||
result: result_,
|
||||
} = result
|
||||
const { bgTerminalId } = params
|
||||
const { persistentTerminalId } = params
|
||||
|
||||
// success
|
||||
if (resolveReason.type === 'done') {
|
||||
const desc = bgTerminalId ? ` in terminal ${bgTerminalId}` : ''
|
||||
const desc = persistentTerminalId ? ` in terminal ${persistentTerminalId}` : ''
|
||||
return `Terminal command executed and finished${desc}. Result (exit code ${resolveReason.exitCode}):\n${result_}`
|
||||
}
|
||||
|
||||
// bg command
|
||||
if (bgTerminalId !== null) {
|
||||
if (persistentTerminalId !== null) {
|
||||
if (resolveReason.type === 'timeout') {
|
||||
return `Terminal command is running in the background in terminal ${bgTerminalId}. Here were the outputs after ${MAX_TERMINAL_INACTIVE_TIME} seconds:\n${result_}`
|
||||
return `Terminal command is running in terminal ${persistentTerminalId}. Here are the current outputs (after ${MAX_TERMINAL_BG_COMMAND_TIME} seconds):\n${result_}`
|
||||
}
|
||||
}
|
||||
// normal command
|
||||
|
|
@ -541,11 +540,11 @@ export class ToolsService implements IToolsService {
|
|||
throw new Error(`Unexpected internal error: Terminal command did not resolve with a valid reason.`)
|
||||
},
|
||||
open_persistent_terminal: (_params, result) => {
|
||||
const { terminalId } = result;
|
||||
return `Successfully created background terminal with ID ${terminalId}`;
|
||||
const { persistentTerminalId } = result;
|
||||
return `Successfully created persistent terminal. persistentTerminalId="${persistentTerminalId}"`;
|
||||
},
|
||||
kill_persistent_terminal: (params, _result) => {
|
||||
return `Successfully closed terminal ${params.terminalId}.`;
|
||||
return `Successfully closed terminal "${params.persistentTerminalId}".`;
|
||||
},
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ export const MAX_CHILDREN_URIs_PAGE = 500
|
|||
// terminal tool info
|
||||
export const MAX_TERMINAL_CHARS = 100_000
|
||||
export const MAX_TERMINAL_INACTIVE_TIME = 8 // seconds
|
||||
export const MAX_TERMINAL_BG_COMMAND_TIME = 5
|
||||
|
||||
|
||||
// Maximum character limits for prefix and suffix context
|
||||
|
|
@ -133,12 +134,12 @@ const changesExampleContent = `\
|
|||
// {{change 3}}
|
||||
// ... existing code ...`
|
||||
|
||||
// const editToolDescriptionExample = `\
|
||||
// ${tripleTick[0]}
|
||||
// ${changesExampleContent}
|
||||
// ${tripleTick[1]}`
|
||||
const editToolDescriptionExample = `\
|
||||
${tripleTick[0]}
|
||||
${changesExampleContent}
|
||||
${tripleTick[1]}`
|
||||
|
||||
const fileNameEditExample = `${tripleTick[0]}typescript
|
||||
const chatSuggestionDiffExample = `${tripleTick[0]}typescript
|
||||
/Users/username/Dekstop/my_project/app.ts
|
||||
${changesExampleContent}
|
||||
${tripleTick[1]}`
|
||||
|
|
@ -180,6 +181,13 @@ const paginationParam = {
|
|||
// [K in keyof T as SnakeCase<Extract<K, string>>]: T[K]
|
||||
// };
|
||||
|
||||
const applyToolDescription = (type: 'edit tool' | 'chat suggestion') => `\
|
||||
${type === 'edit tool' ? 'A' : 'a'} code diff describing the change to make to the file. \
|
||||
Your DIFF is the only context that will be given to another LLM to apply the change, so it must be accurate and complete. \
|
||||
Your DIFF MUST be wrapped in triple backticks. \
|
||||
NEVER re-write the whole file. Always bias towards writing as little as possible. \
|
||||
Use comments like "// ... existing code ..." to condense your writing. \
|
||||
Here's an example of a good output:\n${type === 'edit tool' ? editToolDescriptionExample : chatSuggestionDiffExample}`
|
||||
|
||||
|
||||
export const voidTools = {
|
||||
|
|
@ -313,7 +321,7 @@ export const voidTools = {
|
|||
description: `Runs a terminal command and waits for the result (times out after ${MAX_TERMINAL_INACTIVE_TIME}s of inactivity). You can use this tool to run any command: sed, grep, etc. Do not edit any files with this tool; use edit_file instead. When working with git and other tools that open an editor (e.g. git diff), you should pipe to cat to get all results and not get stuck in vim.`,
|
||||
params: {
|
||||
command: { description: 'The terminal command to run.' },
|
||||
bg_terminal_id: { description: 'Optional. This only applies to terminals that have been opened with open_persistent_terminal. Runs the command in the terminal with the specified ID.' },
|
||||
persistent_terminal_id: { description: 'Optional. Runs the command in the persistent terminal that you created with open_persistent_terminal.' },
|
||||
},
|
||||
},
|
||||
|
||||
|
|
@ -324,8 +332,8 @@ export const voidTools = {
|
|||
},
|
||||
kill_persistent_terminal: {
|
||||
name: 'kill_persistent_terminal',
|
||||
description: `Closes a BG terminal with the given ID.`,
|
||||
params: { terminal_id: { description: `The terminal ID to interrupt and close.` } }
|
||||
description: `Interrupts and closes a persistent terminal that you opened with open_persistent_terminal.`,
|
||||
params: { persistent_terminal_id: { description: `The ID of the persistent terminal.` } }
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -421,14 +429,14 @@ Please assist the user with their query.`)
|
|||
<system_info>
|
||||
- ${os}
|
||||
|
||||
- Open workspaces:
|
||||
${workspaceFolders.join('\n') || 'NO WORKSPACE OPEN'}
|
||||
- The user's workspace contains these folders:
|
||||
${workspaceFolders.join('\n') || 'NO FOLDERS OPEN'}
|
||||
|
||||
- Active file:
|
||||
${activeURI}
|
||||
|
||||
- Open files:
|
||||
${openedURIs.join('\n') || 'NO OPENED EDITORS'}${''/* separator */}${mode === 'agent' && persistentTerminalIDs.length !== 0 ? `
|
||||
${openedURIs.join('\n') || 'NO OPENED FILES'}${''/* separator */}${mode === 'agent' && persistentTerminalIDs.length !== 0 ? `
|
||||
|
||||
- Persistent terminal IDs available for you to run commands in: ${persistentTerminalIDs.join(', ')}` : ''}
|
||||
</system_info>`)
|
||||
|
|
@ -460,7 +468,7 @@ ${directoryStr}
|
|||
details.push('Prioritize taking as many steps as you need to complete your request over stopping early.')
|
||||
details.push(`You will OFTEN need to gather context before making a change. Do not immediately make a change unless you have ALL relevant context.`)
|
||||
details.push(`ALWAYS have maximal certainty in a change BEFORE you make it. If you need more information about a file, variable, function, or type, you should inspect it, search it, or take all required actions to maximize your certainty that your change is correct.`)
|
||||
details.push(`NEVER modify a file outside the user's workspace(s) without permission from the user.`)
|
||||
details.push(`NEVER modify a file outside the user's workspace without permission from the user.`)
|
||||
}
|
||||
|
||||
if (mode === 'gather') {
|
||||
|
|
@ -475,12 +483,8 @@ ${directoryStr}
|
|||
- The remaining contents of the file should proceed as usual.`)
|
||||
|
||||
details.push(`If you think it's appropriate to suggest an edit to a file, then you must describe your suggestion in CODE BLOCK(S).
|
||||
- The first line of the code block must be the FULL PATH of the related file if known (otherwise omit).
|
||||
- The remaining contents should be \
|
||||
a brief code description of the change you want to make, with comments like "// ... existing code ..." to condense your writing. \
|
||||
NEVER re-write the whole file. Instead, use comments like "// ... existing code ...". Bias towards writing as little as possible. \
|
||||
Here's an example of a good edit suggestion:
|
||||
${fileNameEditExample}.`)
|
||||
- The first line of the code block must be the FULL PATH of the related file.
|
||||
- The remaining contents should be ${applyToolDescription('chat suggestion')}`)
|
||||
}
|
||||
|
||||
details.push(`NEVER write the FULL PATH of a file when speaking with the user. Just write the file name ONLY.`)
|
||||
|
|
|
|||
|
|
@ -48,9 +48,9 @@ export type ToolCallParams = {
|
|||
'create_file_or_folder': { uri: URI, isFolder: boolean },
|
||||
'delete_file_or_folder': { uri: URI, isRecursive: boolean, isFolder: boolean },
|
||||
// ---
|
||||
'run_command': { command: string; bgTerminalId: string | null },
|
||||
'run_command': { command: string; persistentTerminalId: string | null },
|
||||
'open_persistent_terminal': {},
|
||||
'kill_persistent_terminal': { terminalId: string },
|
||||
'kill_persistent_terminal': { persistentTerminalId: string },
|
||||
}
|
||||
|
||||
// RESULT OF TOOL CALL
|
||||
|
|
@ -69,7 +69,7 @@ export type ToolResultType = {
|
|||
'delete_file_or_folder': {},
|
||||
// ---
|
||||
'run_command': { result: string; resolveReason: TerminalResolveReason; },
|
||||
'open_persistent_terminal': { terminalId: string },
|
||||
'open_persistent_terminal': { persistentTerminalId: string },
|
||||
'kill_persistent_terminal': {},
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue