u
This commit is contained in:
@@ -122,29 +122,11 @@ export function createJavascriptExecuteTool({ googleAuthId }) {
|
||||
return defineTool({
|
||||
name: 'javascript_execute',
|
||||
description:
|
||||
'Run JavaScript in a sandboxed Node environment and return the result. ' +
|
||||
'Runs in an isolated worker thread with a hard wall-clock timeout. ' +
|
||||
'Return a value by assigning `module.exports` (sync value or a promise). ' +
|
||||
'For async code: `module.exports = (async () => { ... })()`. ' +
|
||||
'console.* is captured and returned as stdout. ' +
|
||||
'To query the Dashback REST API from JavaScript: call `await fetch("/route")` (e.g. `const res = await fetch("/article/2"); const data = await res.json();`). ' +
|
||||
'Relative paths automatically resolve against Dashback and are authenticated with your user credentials. ' +
|
||||
'A virtual filesystem (fs / vfs) is available to store and retrieve artifacts (files, images, JSON data, buffers) across runs (e.g. `fs.writeFileSync("artifact.json", data)`). ' +
|
||||
'IMAGES WRITTEN TO THE VFS ARE DISPLAYED INLINE IN THE CHAT. After writing an image into the virtual filesystem (e.g. `fs.writeFileSync("artifacts/example.png", buf)`), ' +
|
||||
'reference the exact path you wrote with standard markdown `` and it renders as an image inline. ' +
|
||||
'Note the `image/` folder is reserved for database images and is read-only; write generated images anywhere else. ' +
|
||||
'Always embed images you generate this way so the user sees them. Other file types do not render inline. ' +
|
||||
'For TEXT use the dedicated find_files / read_file / patch tools instead of hand-rolling fs calls — they validate paths and persist to the database. ' +
|
||||
'Use this sandbox for BINARY work and computation: images, PDFs, buffers, charts, encoding. ' +
|
||||
'To find or inspect images, use the search_images and analyze_image tools — they are not available inside the sandbox. ' +
|
||||
'The `sharp` image library is a pre-injected GLOBAL. ' +
|
||||
'Also global: `validateLabelObjects(objects)` and `validateLabelObject(object)` from react-canvas-label-editor. ' +
|
||||
'CRYPTO: only the WebCrypto global `crypto` is available. Node\'s `crypto` module is NOT installed, so ' +
|
||||
'`require("crypto")` will fail. Available: `crypto.randomUUID()`, `crypto.getRandomValues(typedArray)`, ' +
|
||||
'and the async `crypto.subtle` API (digest/hash, sign/verify, encrypt/decrypt, importKey/exportKey, deriveBits). ' +
|
||||
'`crypto.subtle` is async, so use it inside an async IIFE: ' +
|
||||
'`module.exports = (async () => (await crypto.subtle.digest("SHA-256", data)).byteLength)();`. ' +
|
||||
'Typed arrays work correctly across the sandbox boundary (verified against Node\'s real digests).',
|
||||
'Execute JS in isolated Node worker sandbox. Assign `module.exports` to return value (sync value or Promise; no bare top-level await — wrap async in IIFE: `module.exports = (async () => { ... })()`). ' +
|
||||
'REST API: `await fetch("/path")` (authenticated). ' +
|
||||
'VFS: `fs.readFileSync`/`writeFileSync` for binary artifacts/buffers/images (`image/` is read-only). ' +
|
||||
'Embed generated images in markdown: ``. Use find_files/read_file/patch for text. ' +
|
||||
'Globals: `fs`/`vfs`, `sharp`, WebCrypto `crypto` (`subtle`, `randomUUID`), web standard globals. Node built-ins unavailable (`require` fails).',
|
||||
strict: false,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
@@ -153,25 +135,15 @@ export function createJavascriptExecuteTool({ googleAuthId }) {
|
||||
properties: {
|
||||
code: {
|
||||
type: 'string',
|
||||
description:
|
||||
'JavaScript source to run in a CommonJS wrapper. Set `module.exports` to return a value; ' +
|
||||
'for async code assign the PROMISE, e.g. `module.exports = (async () => { ... })()`. ' +
|
||||
'To query Dashback REST API: `const res = await fetch("/article/2"); const data = await res.json();`. ' +
|
||||
'To persist BINARY artifacts between runs: use `fs.writeFileSync("name.ext", buffer)` and `fs.readFileSync("name.ext")`. ' +
|
||||
'For text files prefer the find_files / read_file / patch tools. ' +
|
||||
'Bare top-level `await` is a syntax error here — always wrap it in that async IIFE. ' +
|
||||
'Globals available: `fetch`, `console`, `fs`/`vfs`, `sharp`, `performance`, `URL`, `URLSearchParams`, `Headers`, ' +
|
||||
'`Request`, `Response`, `FormData`, `Blob`, `File`, `TextEncoder`, `TextDecoder`, `AbortController`, ' +
|
||||
'`AbortSignal`, `setTimeout`, `clearTimeout`, and WebCrypto `crypto` (`randomUUID`, `getRandomValues`, `subtle`). ' +
|
||||
'No Node built-ins are installable — `require("crypto")`, `require("fs")`, `require("path")` etc. all fail.',
|
||||
description: 'CommonJS JS code. Assign result to `module.exports`. Async code must use IIFE.',
|
||||
},
|
||||
timeout: {
|
||||
type: 'number',
|
||||
description: `Hard wall-clock limit in ms. Default ${DEFAULT_TIMEOUT_MS}, max ${MAX_TIMEOUT_MS}.`,
|
||||
description: `Execution timeout in ms. Default ${DEFAULT_TIMEOUT_MS}, max ${MAX_TIMEOUT_MS}.`,
|
||||
},
|
||||
max_output: {
|
||||
type: 'number',
|
||||
description: `Max chars of captured console output to return. Default ${DEFAULT_MAX_OUTPUT}.`,
|
||||
description: `Max stdout chars. Default ${DEFAULT_MAX_OUTPUT}.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user