@knightcodeai/cli 0.17.4 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1303 -0
- package/README.md +2 -2
- package/dist/bundle/chunks/anthropic-messages-A2IH2IY3.js +6 -0
- package/dist/bundle/chunks/anthropic.js +101 -0
- package/dist/bundle/chunks/azure-openai-responses-XZILQZOG.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +89 -0
- package/dist/bundle/chunks/chunk-253N4337.js +7 -0
- package/dist/bundle/chunks/chunk-2QIKI63P.js +108 -0
- package/dist/bundle/chunks/chunk-3LX7U45C.js +130 -0
- package/dist/bundle/chunks/chunk-4CRI7BMY.js +2 -0
- package/dist/bundle/chunks/chunk-57BPR4HF.js +2 -0
- package/dist/bundle/chunks/chunk-A5LJINMT.js +2 -0
- package/dist/bundle/chunks/chunk-AANBXVWQ.js +2 -0
- package/dist/bundle/chunks/chunk-AHB7JV5B.js +2 -0
- package/dist/bundle/chunks/chunk-B2FT7RH5.js +2 -0
- package/dist/bundle/chunks/chunk-BPNRVFVQ.js +2 -0
- package/dist/bundle/chunks/chunk-BRKUE2MD.js +2 -0
- package/dist/bundle/chunks/chunk-BXZL5C3N.js +58 -0
- package/dist/bundle/chunks/chunk-DGACKL4S.js +30 -0
- package/dist/bundle/chunks/chunk-DKOURXGU.js +2 -0
- package/dist/bundle/chunks/chunk-DVFCXHT4.js +2 -0
- package/dist/bundle/chunks/chunk-ETOMYYZC.js +2 -0
- package/dist/bundle/chunks/chunk-FA32X2UJ.js +7 -0
- package/dist/bundle/chunks/chunk-FHM6KUY3.js +44 -0
- package/dist/bundle/chunks/chunk-FO7CEQB3.js +11 -0
- package/dist/bundle/chunks/chunk-FXS5MU6B.js +2 -0
- package/dist/bundle/chunks/chunk-HHWP56PR.js +2 -0
- package/dist/bundle/chunks/chunk-HSL72VZI.js +2 -0
- package/dist/bundle/chunks/chunk-HUQB436V.js +2 -0
- package/dist/bundle/chunks/chunk-HWXGL4YB.js +2 -0
- package/dist/bundle/chunks/chunk-KQKUEQJA.js +6 -0
- package/dist/bundle/chunks/chunk-LROWZ6UF.js +1333 -0
- package/dist/bundle/chunks/chunk-MOALMQWH.js +9 -0
- package/dist/bundle/chunks/chunk-MXIWLMNT.js +8 -0
- package/dist/bundle/chunks/chunk-N6VDWLND.js +2 -0
- package/dist/bundle/chunks/chunk-NCIBB66G.js +2 -0
- package/dist/bundle/chunks/chunk-NDQ5OW6U.js +2 -0
- package/dist/bundle/chunks/chunk-O6JSP6YG.js +6 -0
- package/dist/bundle/chunks/chunk-OFST7FDG.js +2 -0
- package/dist/bundle/chunks/chunk-SPAUY3RD.js +12 -0
- package/dist/bundle/chunks/chunk-UZWP3NHW.js +2 -0
- package/dist/bundle/chunks/chunk-V5ANFNKF.js +11 -0
- package/dist/bundle/chunks/chunk-VJJ6J35N.js +20 -0
- package/dist/bundle/chunks/chunk-ZW7FVRHT.js +31 -0
- package/dist/bundle/chunks/cli-DFJTSQI6.js +51 -0
- package/dist/bundle/chunks/cloudflare-workers-ai-system-one-6E2UM7IG.js +2 -0
- package/dist/bundle/chunks/codemode-worker.js +478 -0
- package/dist/bundle/chunks/dist-DKI7Q6GY.js +13 -0
- package/dist/bundle/chunks/easter-egg-3d-7O2AHLAQ.js +2 -0
- package/dist/bundle/chunks/execute-4CLOTQIS.js +499 -0
- package/dist/bundle/chunks/github-copilot.js +2 -0
- package/dist/bundle/chunks/google-generative-ai-CSWR3ORZ.js +2 -0
- package/dist/bundle/chunks/google-vertex-QIDRFOFB.js +2 -0
- package/dist/bundle/chunks/image-resize-worker.js +2 -0
- package/dist/bundle/chunks/jiti-loader-BXVX3Y2R.js +21 -0
- package/dist/bundle/chunks/jiti-static-loader-NNBCFAO5.js +2 -0
- package/dist/bundle/chunks/kimi-coding.js +2 -0
- package/dist/bundle/chunks/knightcode-messages-3GNOTMSI.js +8 -0
- package/dist/bundle/chunks/lib-IHWMWJDR.js +9 -0
- package/dist/bundle/chunks/llama-cpp-classify-HRPRKOZA.js +22 -0
- package/dist/bundle/chunks/meta.js +2 -0
- package/dist/bundle/chunks/mistral-conversations-46TK5OBA.js +5 -0
- package/dist/bundle/chunks/multipart-parser-VTTMF2EO.js +3 -0
- package/dist/bundle/chunks/node-7S3GFMOZ.js +16 -0
- package/dist/bundle/chunks/node-MAEICQNS.js +2 -0
- package/dist/bundle/chunks/openai-chatgpt.js +101 -0
- package/dist/bundle/chunks/openai-codex-responses-IT7VEKUU.js +10 -0
- package/dist/bundle/chunks/openai-codex.js +101 -0
- package/dist/bundle/chunks/openai-completions-LOKIW33V.js +7 -0
- package/dist/bundle/chunks/openai-decisions-4F3LWHMG.js +5 -0
- package/dist/bundle/chunks/openai-responses-OK36GJXP.js +3 -0
- package/dist/bundle/chunks/openrouter-images-ZI7LLZ4Y.js +2 -0
- package/dist/bundle/chunks/openrouter.js +101 -0
- package/dist/bundle/chunks/radius.js +101 -0
- package/dist/bundle/chunks/runtime-IN7ZPKFY.js +2 -0
- package/dist/bundle/chunks/src-ETRMT73D.js +4 -0
- package/dist/bundle/chunks/typesafe-system-one-J2CJBWEH.js +2 -0
- package/dist/bundle/chunks/virtual-modules-7VXI3TVN.js +2 -0
- package/dist/bundle/chunks/xai.js +2 -0
- package/dist/bundle/cli-runtime.js +3 -0
- package/dist/bundle/cli.js +16 -0
- package/dist/bundle/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
- package/dist/bundle/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
- package/dist/bundle/native/linux/prebuilds/linux-arm64/linux-platform-x11.node +0 -0
- package/dist/bundle/native/linux/prebuilds/linux-x64/linux-platform-x11.node +0 -0
- package/dist/bundle/native/win32/prebuilds/win32-arm64/win32-platform.node +0 -0
- package/dist/bundle/native/win32/prebuilds/win32-x64/win32-platform.node +0 -0
- package/dist/core/export-html/template.css +1015 -0
- package/dist/core/export-html/template.html +55 -0
- package/dist/core/export-html/template.js +1929 -0
- package/dist/core/export-html/vendor/highlight.min.js +1213 -0
- package/dist/core/export-html/vendor/marked.min.js +78 -0
- package/dist/modes/interactive/theme/dark.json +74 -0
- package/dist/modes/interactive/theme/light.json +74 -0
- package/dist/modes/interactive/theme/system-theme.ts +579 -0
- package/dist/modes/interactive/theme/theme-controller.ts +253 -0
- package/dist/modes/interactive/theme/theme-schema.ts +145 -0
- package/dist/modes/interactive/theme/theme-tokens.ts +145 -0
- package/dist/modes/interactive/theme/theme.ts +1076 -0
- package/docs/app-server.md +479 -0
- package/docs/app-server.schema.json +8128 -0
- package/docs/cli-integration.md +106 -0
- package/docs/cli.md +393 -0
- package/docs/codemode.md +230 -0
- package/docs/compaction.md +463 -0
- package/docs/configuration.md +48 -0
- package/docs/containerization.md +143 -0
- package/docs/custom-provider.md +225 -0
- package/docs/desktop.md +73 -0
- package/docs/docs.json +236 -0
- package/docs/environment-variables.md +138 -0
- package/docs/extensions.md +420 -0
- package/docs/how-knightcode-works.md +49 -0
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/index.md +39 -0
- package/docs/json.md +226 -0
- package/docs/keybindings.md +197 -0
- package/docs/llama-cpp.md +121 -0
- package/docs/mcp.md +272 -0
- package/docs/message-types.md +279 -0
- package/docs/models-configuration.md +187 -0
- package/docs/models.md +221 -0
- package/docs/nvidia-rtx-llama-cpp.md +96 -0
- package/docs/packages.md +129 -0
- package/docs/plan-mode.md +121 -0
- package/docs/prompt-templates.md +59 -0
- package/docs/providers.md +282 -0
- package/docs/quickstart.md +128 -0
- package/docs/remote.md +87 -0
- package/docs/rpc-commands.md +860 -0
- package/docs/rpc-extension-ui.md +214 -0
- package/docs/rpc.md +193 -0
- package/docs/sdk.md +197 -0
- package/docs/security.md +99 -0
- package/docs/session-format.md +358 -0
- package/docs/sessions.md +135 -0
- package/docs/settings.md +220 -0
- package/docs/shell-aliases.md +93 -0
- package/docs/skills.md +93 -0
- package/docs/slash-commands.md +78 -0
- package/docs/terminal-setup.md +242 -0
- package/docs/termux.md +117 -0
- package/docs/themes.md +140 -0
- package/docs/tmux.md +55 -0
- package/docs/tui.md +195 -0
- package/docs/usage.md +167 -0
- package/docs/virtual-models.md +114 -0
- package/docs/windows.md +67 -0
- package/examples/README.md +36 -0
- package/examples/extensions/README.md +214 -0
- package/examples/extensions/auto-commit-on-exit.ts +55 -0
- package/examples/extensions/bash-spawn-hook.ts +30 -0
- package/examples/extensions/bookmark.ts +50 -0
- package/examples/extensions/border-status-editor.ts +151 -0
- package/examples/extensions/built-in-tool-renderer.ts +225 -0
- package/examples/extensions/claude-rules.ts +89 -0
- package/examples/extensions/commands.ts +72 -0
- package/examples/extensions/confirm-destructive.ts +60 -0
- package/examples/extensions/custom-compaction.ts +118 -0
- package/examples/extensions/custom-footer.ts +66 -0
- package/examples/extensions/custom-header.ts +73 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +617 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
- package/examples/extensions/custom-provider-anthropic/package.json +19 -0
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +399 -0
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
- package/examples/extensions/debug-provider.ts +90 -0
- package/examples/extensions/dirty-repo-guard.ts +56 -0
- package/examples/extensions/doom-overlay/README.md +46 -0
- package/examples/extensions/doom-overlay/doom/build.sh +152 -0
- package/examples/extensions/doom-overlay/doom/doomgeneric_knightcode.c +72 -0
- package/examples/extensions/doom-overlay/doom-component.ts +132 -0
- package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
- package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
- package/examples/extensions/doom-overlay/index.ts +74 -0
- package/examples/extensions/doom-overlay/wad-finder.ts +55 -0
- package/examples/extensions/dynamic-resources/SKILL.md +8 -0
- package/examples/extensions/dynamic-resources/dynamic.json +75 -0
- package/examples/extensions/dynamic-resources/dynamic.md +5 -0
- package/examples/extensions/dynamic-resources/index.ts +15 -0
- package/examples/extensions/dynamic-tools.ts +74 -0
- package/examples/extensions/entry-renderer.ts +41 -0
- package/examples/extensions/event-bus.ts +43 -0
- package/examples/extensions/file-trigger.ts +41 -0
- package/examples/extensions/git-checkpoint.ts +53 -0
- package/examples/extensions/git-merge-and-resolve.ts +115 -0
- package/examples/extensions/github-issue-autocomplete.ts +185 -0
- package/examples/extensions/gondolin/index.ts +531 -0
- package/examples/extensions/gondolin/package-lock.json +185 -0
- package/examples/extensions/gondolin/package.json +19 -0
- package/examples/extensions/handoff.ts +190 -0
- package/examples/extensions/hello.ts +26 -0
- package/examples/extensions/hidden-thinking-label.ts +53 -0
- package/examples/extensions/inline-bash.ts +94 -0
- package/examples/extensions/input-transform-streaming.ts +39 -0
- package/examples/extensions/input-transform.ts +43 -0
- package/examples/extensions/interactive-shell.ts +196 -0
- package/examples/extensions/jev-router.ts +113 -0
- package/examples/extensions/mac-system-theme.ts +47 -0
- package/examples/extensions/message-renderer.ts +59 -0
- package/examples/extensions/minimal-mode.ts +353 -0
- package/examples/extensions/modal-editor.ts +85 -0
- package/examples/extensions/model-status.ts +31 -0
- package/examples/extensions/notify.ts +57 -0
- package/examples/extensions/overlay-qa-tests.ts +1450 -0
- package/examples/extensions/overlay-test.ts +153 -0
- package/examples/extensions/permission-gate.ts +34 -0
- package/examples/extensions/pirate.ts +47 -0
- package/examples/extensions/plan-mode/README.md +66 -0
- package/examples/extensions/plan-mode/index.ts +387 -0
- package/examples/extensions/plan-mode/utils.ts +168 -0
- package/examples/extensions/preset.ts +436 -0
- package/examples/extensions/project-trust.ts +64 -0
- package/examples/extensions/prompt-customizer.ts +49 -0
- package/examples/extensions/protected-paths.ts +30 -0
- package/examples/extensions/provider-payload.ts +18 -0
- package/examples/extensions/qna.ts +118 -0
- package/examples/extensions/question.ts +278 -0
- package/examples/extensions/questionnaire.ts +440 -0
- package/examples/extensions/rainbow-editor.ts +88 -0
- package/examples/extensions/reload-runtime.ts +37 -0
- package/examples/extensions/rpc-demo.ts +118 -0
- package/examples/extensions/sandbox/index.ts +321 -0
- package/examples/extensions/sandbox/package-lock.json +92 -0
- package/examples/extensions/sandbox/package.json +19 -0
- package/examples/extensions/send-user-message.ts +97 -0
- package/examples/extensions/session-name.ts +27 -0
- package/examples/extensions/shutdown-command.ts +63 -0
- package/examples/extensions/snake.ts +343 -0
- package/examples/extensions/space-invaders.ts +560 -0
- package/examples/extensions/ssh.ts +220 -0
- package/examples/extensions/status-line.ts +32 -0
- package/examples/extensions/structured-output.ts +65 -0
- package/examples/extensions/subagent/README.md +177 -0
- package/examples/extensions/subagent/agents/planner.md +37 -0
- package/examples/extensions/subagent/agents/reviewer.md +35 -0
- package/examples/extensions/subagent/agents/scout.md +50 -0
- package/examples/extensions/subagent/agents/worker.md +24 -0
- package/examples/extensions/subagent/agents.ts +157 -0
- package/examples/extensions/subagent/index.ts +1010 -0
- package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
- package/examples/extensions/subagent/prompts/implement.md +10 -0
- package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
- package/examples/extensions/summarize.ts +199 -0
- package/examples/extensions/system-prompt-header.ts +17 -0
- package/examples/extensions/tic-tac-toe.ts +1004 -0
- package/examples/extensions/timed-confirm.ts +70 -0
- package/examples/extensions/titlebar-spinner.ts +58 -0
- package/examples/extensions/todo.ts +294 -0
- package/examples/extensions/tool-override.ts +144 -0
- package/examples/extensions/tools.ts +146 -0
- package/examples/extensions/trigger-compact.ts +50 -0
- package/examples/extensions/truncated-tool.ts +195 -0
- package/examples/extensions/widget-placement.ts +9 -0
- package/examples/extensions/with-deps/index.ts +32 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +22 -0
- package/examples/extensions/working-indicator.ts +121 -0
- package/examples/extensions/working-message-test.ts +25 -0
- package/examples/rpc-client.ts +35 -0
- package/examples/rpc-extension-ui.ts +661 -0
- package/examples/sdk/01-minimal.ts +26 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +70 -0
- package/examples/sdk/04-skills.ts +55 -0
- package/examples/sdk/05-tools.ts +48 -0
- package/examples/sdk/06-extensions.ts +94 -0
- package/examples/sdk/07-context-files.ts +42 -0
- package/examples/sdk/08-prompt-templates.ts +51 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +34 -0
- package/examples/sdk/10-settings.ts +53 -0
- package/examples/sdk/11-sessions.ts +52 -0
- package/examples/sdk/12-full-control.ts +74 -0
- package/examples/sdk/13-session-runtime.ts +67 -0
- package/examples/sdk/14-codemode-mcp.ts +61 -0
- package/examples/sdk/README.md +141 -0
- package/package.json +15 -15
- package/bin/knightcode +0 -62
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import { createRequire as __kcCreateRequire } from "node:module"; const require = __kcCreateRequire(import.meta.url);
|
|
2
|
+
import{Bm25Ranker,CODEMODE_DOCS_PATH,CODEMODE_STORE_ENTRY_TYPE,DEFAULT_TOOL_SEARCH_LIMIT,combineUsage,createToolSearchDocument,formatSize,getCodemodeCallableTools,parseCodemodeSource,renderToolSample,toCodemodeDeclaration,toCodemodeIdentifier,writeOutputFile}from"./chunk-BXZL5C3N.js";import"./chunk-3LX7U45C.js";import"./chunk-MXIWLMNT.js";import"./chunk-KQKUEQJA.js";import"./chunk-O6JSP6YG.js";import"./chunk-MOALMQWH.js";import{getCodemodeWorkerSpecifier,getQuickJSWasmPath}from"./chunk-BPNRVFVQ.js";import"./chunk-AHB7JV5B.js";function isWorkerToHostMessage(value){if(typeof value!="object"||value===null)return!1;let type=value.type;return type==="call"||type==="output"||type==="done"||type==="crash"||type==="started"||type==="idle"}var DEFAULT_TIMEOUT_MS=3e5,IDENTIFIER=/^[A-Za-z_$][A-Za-z0-9_$]*$/,RESERVED_GLOBALS=new Set(["tools","ALL_TOOLS","console","text","image","exit","globalThis","store","load"]);function errorMessage(error){return error instanceof Error?error.message:String(error)}function serializeStore(store){let serialized={};for(let[key,value]of Object.entries(store??{})){let json=JSON.stringify(value);json!==void 0&&(serialized[key]=json)}return serialized}var BridgeError=class extends Error{};function parseBridgeJson(json,what){try{return JSON.parse(json)}catch{throw new BridgeError(`${what} is not valid JSON`)}}function parseStoreWrites(json){let entries=parseBridgeJson(json,"store writes");if(!Array.isArray(entries))throw new BridgeError("store writes are not an array");let writes={set:{},delete:[]};for(let entry of entries){if(!Array.isArray(entry)||typeof entry[0]!="string"||(entry.length===2?typeof entry[1]!="string":entry.length!==1))throw new BridgeError("store writes contain a malformed entry");let[key,value]=entry;value===void 0?writes.delete.push(key):writes.set[key]=parseBridgeJson(value,`store value for ${JSON.stringify(key)}`)}return writes}function parseScriptError(json){let parsed=parseBridgeJson(json,"script error");if(typeof parsed!="object"||parsed===null)throw new BridgeError("script error is not an object");let{name,message,stack}=parsed;if(typeof message!="string"||name!==void 0&&typeof name!="string"||stack!==void 0&&typeof stack!="string")throw new BridgeError("script error is malformed");return{kind:"script",name,message,stack}}function checkGlobals(globals){let names=new Set,namespaces=new Set;for(let global of globals){let parts=global.name.split(".");if(parts.length>2||!parts.every(part=>IDENTIFIER.test(part))||RESERVED_GLOBALS.has(parts[0]))throw new Error(`Invalid global name "${global.name}"`);if(names.has(global.name))throw new Error(`Global "${global.name}" is already registered`);parts.length===2&&namespaces.add(parts[0]),names.add(global.name)}for(let name of namespaces)if(names.has(name))throw new Error(`Global "${name}" conflicts with the namespace "${name}"`)}var Execution=class{promise;resolveResult;channel;unsent=[];executors;control;delivered=new Set;signal;timer;output=[];calls=[];pending=new Map;finished=!1;constructor(options){if(this.promise=new Promise(resolve=>{this.resolveResult=resolve}),this.executors=options.executors,this.control=options.control,this.signal=options.signal,Number.isFinite(options.timeoutMs)&&(this.timer=setTimeout(()=>{this.finish({kind:"timeout",message:`Execution timed out after ${options.timeoutMs} ms`})},options.timeoutMs)),options.signal&&(options.signal.aborted?this.onAbort():options.signal.addEventListener("abort",this.onAbort,{once:!0})),this.finished)return;let data={code:options.code,tools:options.tools.map(tool=>({name:tool.name,jsName:tool.jsName??toCodemodeIdentifier(tool.name),description:tool.description??""})),globals:options.globals.map(global=>({name:global.name,spread:global.spread===!0})),memoryLimitBytes:options.memoryLimitBytes,store:options.store,...options.deterministic?{deterministic:options.deterministic}:{}},events={message:message=>this.receive(message),failure:error=>this.finish(error)};new Promise(resolve=>resolve(options.launch(data,events))).then(channel=>{if(this.finished){channel.stop().catch(()=>{});return}this.channel=channel;for(let message of this.unsent.splice(0))channel.post(message)},error=>{this.finish({kind:"sandbox",message:errorMessage(error)})})}deliver(seq,now,id,outcome){if(this.finished)return;if(!Number.isFinite(now))throw new Error(`The clock value of result ${seq} is not a finite number`);if(!Number.isInteger(seq)||seq<1||this.delivered.has(seq))throw new Error(`Result number ${seq} is not a positive integer used once`);let pending=this.pending.get(id);if(pending===void 0)throw new Error(`Call ${id} is not waiting for a result`);if(!outcome.ok&&outcome.properties!==void 0){let{properties:properties2}=outcome;if(typeof properties2!="object"||properties2===null||Array.isArray(properties2))throw new Error(`The properties of result ${seq} are not an object`)}let payload=outcome.ok?outcome.value===void 0?void 0:JSON.stringify(outcome.value):outcome.message,properties=!outcome.ok&&outcome.properties!==void 0?JSON.stringify(outcome.properties):void 0;this.delivered.add(seq),this.pending.delete(id),pending.record&&(pending.record.status=outcome.ok?"ok":"error",pending.record.durationMs=performance.now()-pending.startedAt),this.post({type:"result",id,ok:outcome.ok,payload,seq,now,...properties===void 0?{}:{properties}})}abort(message){return this.finish({kind:"aborted",message}),this.promise}onAbort=()=>{let reason=this.signal?.reason;this.finish({kind:"aborted",message:reason instanceof Error?reason.message:"Execution aborted"})};post(message){this.channel?this.channel.post(message):this.unsent.push(message)}receive(message){try{this.handleMessage(message)}catch(error){this.finish({kind:"sandbox",message:error instanceof BridgeError?`Sandbox bridge broken: ${error.message}. The script may have modified built-ins such as a prototype's toJSON.`:`Sandbox host failed: ${errorMessage(error)}`})}}handleMessage(message){if(!this.finished){if(!isWorkerToHostMessage(message))throw new BridgeError("unknown message from the worker");switch(message.type){case"output":this.output.push(message.item);break;case"call":if(this.pending.has(message.id))throw new BridgeError(`duplicate call id ${message.id}`);this.control?this.forwardCall(message,this.control):this.handleCall(message);break;case"started":this.control?.onStarted?.(message.fingerprint);break;case"idle":this.control?.onIdle?.(message.seq,message.issued);break;case"done":this.handleDone(message);break;case"crash":this.finish({kind:"sandbox",message:message.message});break}}}handleDone(message){if(!message.ok){this.finish(parseScriptError(message.error),void 0,void 0,message.during);return}let value=message.value===void 0?void 0:parseBridgeJson(message.value,"return value");this.finish(void 0,value,parseStoreWrites(message.writes),message.during)}forwardCall(message,control){let{id,name,target}=message,args=message.args===void 0?void 0:parseBridgeJson(message.args,"call arguments"),record=target==="tool"?{name,status:"cancelled",durationMs:0}:void 0;record&&this.calls.push(record),this.pending.set(id,{record,startedAt:performance.now(),controller:new AbortController}),control.onCall({id,target,name,args})}async handleCall(message){let{id,name}=message,isTool=message.target==="tool",record=isTool?{name,status:"cancelled",durationMs:0}:void 0;record&&this.calls.push(record);let pending={record,startedAt:performance.now(),controller:new AbortController};this.pending.set(id,pending);let status,reply;try{let tool=(isTool?this.executors.tools:this.executors.globals).get(name);if(!tool)throw new Error(`Unknown ${isTool?"tool":"global"} "${name}"`);let args=message.args===void 0?void 0:JSON.parse(message.args),value=await tool.execute(args,{signal:pending.controller.signal});reply={type:"result",id,ok:!0,payload:value===void 0?void 0:JSON.stringify(value)},status="ok"}catch(error){reply={type:"result",id,ok:!1,payload:errorMessage(error)},status="error"}this.pending.delete(id)&&(record&&(record.status=status,record.durationMs=performance.now()-pending.startedAt),this.post(reply))}finish(error,value,writes,during){if(this.finished)return;this.finished=!0,clearTimeout(this.timer),this.signal?.removeEventListener("abort",this.onAbort);let now=performance.now();for(let pending of this.pending.values())pending.record&&(pending.record.durationMs=now-pending.startedAt),pending.controller.abort();this.pending.clear(),this.unsent=[];let ended=during===void 0?{}:{during:{seq:during.seq,issued:during.issued}},result=error?{ok:!1,error,output:this.output,calls:this.calls,...ended}:{ok:!0,value,output:this.output,calls:this.calls,storeWrites:writes??{set:{},delete:[]},...ended};if(!this.channel){this.resolveResult(result);return}this.channel.stop().catch(()=>{}).then(()=>this.resolveResult(result))}},CodemodeSandboxBase=class{toolsByName=new Map;globalsByName=new Map;timeoutMs;memoryLimitBytes;launch;running=new Set;closed=!1;constructor(options,launch){this.timeoutMs=options.timeoutMs??DEFAULT_TIMEOUT_MS,this.memoryLimitBytes=options.memoryLimitBytes,this.launch=launch;for(let tool of options.tools??[])this.registerTool(tool);checkGlobals(options.globals??[]);for(let global of options.globals??[])this.globalsByName.set(global.name,global)}registerTool(tool){if(this.toolsByName.has(tool.name))throw new Error(`Tool "${tool.name}" is already registered`);this.toolsByName.set(tool.name,tool)}unregisterTool(name){return this.toolsByName.delete(name)}get tools(){return[...this.toolsByName.values()]}get globals(){return[...this.globalsByName.values()]}execute(code,options={}){if(this.closed)return Promise.reject(new Error("Sandbox is closed"));let tools=new Map(this.toolsByName),execution=new Execution({code,tools:[...tools.values()],globals:[...this.globalsByName.values()],executors:{tools,globals:this.globalsByName},timeoutMs:options.timeoutMs??this.timeoutMs,signal:options.signal,memoryLimitBytes:this.memoryLimitBytes,store:serializeStore(options.store),launch:this.launch});return this.running.add(execution),execution.promise.finally(()=>this.running.delete(execution))}start(code,options){if(this.closed)throw new Error("Sandbox is closed");if(!Number.isFinite(options.startedAt)||options.startedAt<0)throw new Error("startedAt must be a non-negative number of milliseconds since the epoch");if(!Number.isInteger(options.seed)||options.seed<0||options.seed>4294967295)throw new Error("seed must be a 32-bit unsigned integer");let tools=options.tools??[];if(new Set(tools.map(tool=>tool.name)).size!==tools.length)throw new Error("Tool names must be unique");let scriptNames=tools.map(tool=>tool.jsName??toCodemodeIdentifier(tool.name));if(new Set(scriptNames).size!==tools.length)throw new Error("Tool script names must be unique");let globals=options.globals??[];checkGlobals(globals);let execution=new Execution({code,tools,globals,executors:{tools:new Map,globals:new Map},timeoutMs:options.timeoutMs??Number.POSITIVE_INFINITY,signal:options.signal,memoryLimitBytes:this.memoryLimitBytes,store:serializeStore(options.store),deterministic:{startedAt:options.startedAt,seed:options.seed},control:{onStarted:options.onStarted,onCall:options.onCall,onIdle:options.onIdle},launch:this.launch});return this.running.add(execution),{result:execution.promise.finally(()=>this.running.delete(execution)),deliver:(seq,now,id,outcome)=>execution.deliver(seq,now,id,outcome),get finished(){return execution.finished}}}async close(){this.closed=!0,await Promise.all([...this.running].map(execution=>execution.abort("Sandbox closed")))}};import{Worker}from"node:worker_threads";import{readFile}from"node:fs/promises";import{createRequire}from"node:module";var modules=new Map;function loadQuickJSWasm(path){let resolved=path??createRequire(import.meta.url).resolve("quickjs-wasi/quickjs.wasm"),module=modules.get(resolved);if(!module){let{WebAssembly:WebAssembly2}=globalThis;module=readFile(resolved).then(bytes=>WebAssembly2.compile(bytes)).catch(error=>{throw modules.delete(resolved),error}),modules.set(resolved,module)}return module}function defaultWorkerUrl(){return new URL(import.meta.url.endsWith(".ts")?"./worker.ts":"./worker.js",import.meta.url)}function workerLauncher(options){return async(data,events)=>{let module;try{module=await(options.wasm??loadQuickJSWasm())}catch(error){throw new Error(`Failed to load QuickJS: ${errorMessage(error)}`)}let interrupt=new SharedArrayBuffer(4),workerData={...data,wasm:module,interrupt},releaseWorker=options.acquireWorker?.(),worker;try{worker=new Worker(options.workerUrl??defaultWorkerUrl(),{workerData})}catch(error){throw releaseWorker?.(),new Error(`Failed to start worker: ${errorMessage(error)}`)}releaseWorker&&worker.once("exit",releaseWorker),worker.on("message",message=>{typeof message=="object"&&message!==null&&("watch:import"in message||"watch:require"in message)||events.message(message)}),worker.on("error",error=>{events.failure({kind:"sandbox",name:error instanceof Error?error.name:void 0,message:errorMessage(error)})}),worker.on("exit",code=>{events.failure({kind:"sandbox",message:`Worker exited with code ${code} before the script settled`})});let stop=async()=>{Atomics.store(new Int32Array(interrupt),0,1),worker.terminate().catch(()=>{}),worker.unref()};try{options.onWorkerStarted?.(new Promise(resolve=>worker.once("exit",()=>resolve())))}catch(error){throw stop(),error}return{post:message=>worker.postMessage(message),stop}}}var CodemodeSandbox=class extends CodemodeSandboxBase{constructor(options={}){super(options,workerLauncher(options))}};var decoder=new TextDecoder;var MAX_STACK_SIZE=512*1024;var wtf8Decoder=new TextDecoder,wtf8Encoder=new TextEncoder;var IMAGE_HELPER_EXPECTS='image expects a non-empty image URL string, an object with image_url, or an image block { type: "image", data, mimeType }',PRELUDE_SOURCE=`(function (bridge, toolsJson, globalsJson, storeJson) {
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
// Freeze every object reachable from the built-in globals, plus the intrinsics that are only
|
|
6
|
+
// reachable from instances (iterator and generator prototypes, %TypedArray%).
|
|
7
|
+
//
|
|
8
|
+
// Freezing alone breaks ordinary code through the "override mistake": a data property that is
|
|
9
|
+
// read-only on a prototype cannot be assigned on an instance either, so
|
|
10
|
+
// this.name = "MyError" in an Error subclass would throw. Commonly overridden properties
|
|
11
|
+
// become accessors whose setter defines an own property on the instance instead.
|
|
12
|
+
(function lockdown() {
|
|
13
|
+
const OVERRIDABLE = new Set(["constructor", "name", "message", "toString", "toLocaleString", "valueOf", "toJSON"]);
|
|
14
|
+
const seen = new Set([globalThis]);
|
|
15
|
+
const queue = [];
|
|
16
|
+
const add = (value) => {
|
|
17
|
+
if ((typeof value === "object" && value !== null) || typeof value === "function") {
|
|
18
|
+
if (!seen.has(value)) {
|
|
19
|
+
seen.add(value);
|
|
20
|
+
queue.push(value);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Accessors from an object literal have no own prototype object, unlike function expressions,
|
|
26
|
+
// whose prototype.constructor would be converted again without end.
|
|
27
|
+
function allowOverride(object, key, value, enumerable) {
|
|
28
|
+
const { get, set } = Object.getOwnPropertyDescriptor(
|
|
29
|
+
{
|
|
30
|
+
get accessor() {
|
|
31
|
+
return value;
|
|
32
|
+
},
|
|
33
|
+
set accessor(next) {
|
|
34
|
+
if (this === object) {
|
|
35
|
+
throw new TypeError("Cannot assign to read only property '" + String(key) + "' of a built-in");
|
|
36
|
+
}
|
|
37
|
+
if ((typeof this !== "object" || this === null) && typeof this !== "function") return;
|
|
38
|
+
Object.defineProperty(this, key, { value: next, writable: true, enumerable: true, configurable: true });
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
"accessor",
|
|
42
|
+
);
|
|
43
|
+
Object.defineProperty(object, key, { get, set, enumerable, configurable: false });
|
|
44
|
+
add(get);
|
|
45
|
+
add(set);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
for (const key of Reflect.ownKeys(globalThis)) {
|
|
49
|
+
const descriptor = Object.getOwnPropertyDescriptor(globalThis, key);
|
|
50
|
+
add(descriptor.value);
|
|
51
|
+
add(descriptor.get);
|
|
52
|
+
add(descriptor.set);
|
|
53
|
+
if ("value" in descriptor && descriptor.configurable) {
|
|
54
|
+
Object.defineProperty(globalThis, key, { writable: false, configurable: false });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
add(Object.getPrototypeOf(function* () {}));
|
|
58
|
+
add(Object.getPrototypeOf(async function () {}));
|
|
59
|
+
add(Object.getPrototypeOf(async function* () {}));
|
|
60
|
+
add(Object.getPrototypeOf(Int8Array));
|
|
61
|
+
add(Object.getPrototypeOf([][Symbol.iterator]()));
|
|
62
|
+
add(Object.getPrototypeOf(new Map()[Symbol.iterator]()));
|
|
63
|
+
add(Object.getPrototypeOf(new Set()[Symbol.iterator]()));
|
|
64
|
+
add(Object.getPrototypeOf(""[Symbol.iterator]()));
|
|
65
|
+
add(Object.getPrototypeOf(/a/[Symbol.matchAll]("")));
|
|
66
|
+
if (typeof Iterator === "function") {
|
|
67
|
+
if (typeof Iterator.prototype.map === "function") add(Object.getPrototypeOf([].values().map((x) => x)));
|
|
68
|
+
if (typeof Iterator.from === "function") add(Object.getPrototypeOf(Iterator.from({ next() {} })));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
while (queue.length > 0) {
|
|
72
|
+
const object = queue.pop();
|
|
73
|
+
add(Object.getPrototypeOf(object));
|
|
74
|
+
const descriptors = Object.getOwnPropertyDescriptors(object);
|
|
75
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
76
|
+
const descriptor = descriptors[key];
|
|
77
|
+
if ("value" in descriptor) {
|
|
78
|
+
add(descriptor.value);
|
|
79
|
+
if (
|
|
80
|
+
descriptor.writable &&
|
|
81
|
+
descriptor.configurable &&
|
|
82
|
+
(object === Object.prototype || OVERRIDABLE.has(key))
|
|
83
|
+
) {
|
|
84
|
+
allowOverride(object, key, descriptor.value, descriptor.enumerable);
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
add(descriptor.get);
|
|
88
|
+
add(descriptor.set);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
Object.freeze(object);
|
|
92
|
+
}
|
|
93
|
+
})();
|
|
94
|
+
const stringify = JSON.stringify;
|
|
95
|
+
const parse = JSON.parse;
|
|
96
|
+
const promiseThen = Promise.prototype.then;
|
|
97
|
+
const ErrorCtor = Error;
|
|
98
|
+
const TypeErrorCtor = TypeError;
|
|
99
|
+
const RangeErrorCtor = RangeError;
|
|
100
|
+
const pending = new Map();
|
|
101
|
+
let nextId = 1;
|
|
102
|
+
let finished = false;
|
|
103
|
+
// Thrown by exit() to unwind the script after it already reported success.
|
|
104
|
+
const EXIT = Object.freeze({});
|
|
105
|
+
|
|
106
|
+
function done(ok, payload, writes) {
|
|
107
|
+
if (finished) return;
|
|
108
|
+
finished = true;
|
|
109
|
+
bridge("done", ok, payload, writes);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function serialize(value) {
|
|
113
|
+
return value === undefined ? undefined : stringify(value);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// QuickJS stacks list frames only. Prefix "Name: message" like V8 so the
|
|
117
|
+
// text reads the same as a Node error, and drop this prelude's frames.
|
|
118
|
+
function errorText(error) {
|
|
119
|
+
const head = error.message ? error.name + ": " + error.message : String(error.name);
|
|
120
|
+
const frames =
|
|
121
|
+
typeof error.stack === "string"
|
|
122
|
+
? error.stack.split("\\n").filter((line) => line.trim() && !line.includes("codemode-prelude.js"))
|
|
123
|
+
: [];
|
|
124
|
+
return [head, ...frames].join("\\n");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function format(value) {
|
|
128
|
+
if (typeof value === "string") return value;
|
|
129
|
+
if (value instanceof ErrorCtor) return errorText(value);
|
|
130
|
+
try {
|
|
131
|
+
const json = stringify(value);
|
|
132
|
+
return json === undefined ? String(value) : json;
|
|
133
|
+
} catch {
|
|
134
|
+
return String(value);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// The host requires string fields. A script can set an error's name or message to anything, so
|
|
139
|
+
// they are coerced, and a value whose coercion throws gets a placeholder.
|
|
140
|
+
function describeError(error) {
|
|
141
|
+
try {
|
|
142
|
+
if (error instanceof ErrorCtor) {
|
|
143
|
+
return stringify({ name: String(error.name), message: String(error.message), stack: errorText(error) });
|
|
144
|
+
}
|
|
145
|
+
return stringify({ message: String(format(error)) });
|
|
146
|
+
} catch {
|
|
147
|
+
return stringify({ message: "The script threw a value that cannot be described" });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function caller(kind, name, spread) {
|
|
152
|
+
return (...args) =>
|
|
153
|
+
new Promise((resolve, reject) => {
|
|
154
|
+
let json;
|
|
155
|
+
try {
|
|
156
|
+
json = serialize(spread ? args : args[0]);
|
|
157
|
+
} catch (error) {
|
|
158
|
+
reject(error);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const id = nextId++;
|
|
162
|
+
pending.set(id, { resolve, reject });
|
|
163
|
+
bridge(kind, id, name, json);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const tools = Object.create(null);
|
|
168
|
+
const allTools = [];
|
|
169
|
+
for (const { name, jsName, description } of parse(toolsJson)) {
|
|
170
|
+
const fn = caller("call", name);
|
|
171
|
+
// The first tool wins when two names normalize to the same identifier.
|
|
172
|
+
if (!(jsName in tools)) {
|
|
173
|
+
tools[jsName] = fn;
|
|
174
|
+
allTools.push(Object.freeze({ name: jsName, description }));
|
|
175
|
+
}
|
|
176
|
+
if (!(name in tools)) tools[name] = fn;
|
|
177
|
+
}
|
|
178
|
+
Object.freeze(tools);
|
|
179
|
+
Object.freeze(allTools);
|
|
180
|
+
|
|
181
|
+
// Reading a member that does not exist throws an error that names the close matches, instead of
|
|
182
|
+
// a later "not a function". \`in\` checks still work.
|
|
183
|
+
const comparable = (name) => name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
184
|
+
function guard(target, label, names, hint) {
|
|
185
|
+
return new Proxy(target, {
|
|
186
|
+
get(object, property, receiver) {
|
|
187
|
+
if (typeof property !== "string" || property in object || property in Object.prototype || property === "then" || property === "toJSON") {
|
|
188
|
+
return Reflect.get(object, property, receiver);
|
|
189
|
+
}
|
|
190
|
+
const wanted = comparable(property);
|
|
191
|
+
const exact = names.filter((name) => comparable(name) === wanted);
|
|
192
|
+
const close = exact.length > 0 ? exact : names.filter((name) => wanted && (comparable(name).includes(wanted) || wanted.includes(comparable(name))));
|
|
193
|
+
let message = label + "." + property + " does not exist.";
|
|
194
|
+
if (close.length > 0) message += " Did you mean " + close.slice(0, 5).map((name) => label + "." + name).join(", ") + "?";
|
|
195
|
+
else if (names.length <= 20) message += " Available: " + names.join(", ") + ".";
|
|
196
|
+
if (hint) message += " " + hint;
|
|
197
|
+
message += ' Check for a member with "' + property + '" in ' + label + ".";
|
|
198
|
+
throw new TypeErrorCtor(message);
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
const toolsProxy = guard(
|
|
203
|
+
tools,
|
|
204
|
+
"tools",
|
|
205
|
+
allTools.map((tool) => tool.name),
|
|
206
|
+
"ALL_TOOLS lists every tool; searchTools(query) finds tools by topic.",
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
const namespaces = new Map();
|
|
210
|
+
for (const { name, spread } of parse(globalsJson)) {
|
|
211
|
+
const fn = caller("global", name, spread);
|
|
212
|
+
const dot = name.indexOf(".");
|
|
213
|
+
if (dot === -1) {
|
|
214
|
+
Object.defineProperty(globalThis, name, { value: fn, enumerable: true });
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
const namespace = name.slice(0, dot);
|
|
218
|
+
if (!namespaces.has(namespace)) namespaces.set(namespace, Object.create(null));
|
|
219
|
+
namespaces.get(namespace)[name.slice(dot + 1)] = fn;
|
|
220
|
+
}
|
|
221
|
+
for (const [namespace, members] of namespaces) {
|
|
222
|
+
Object.freeze(members);
|
|
223
|
+
const value = guard(members, namespace, Object.keys(members));
|
|
224
|
+
Object.defineProperty(globalThis, namespace, { value, enumerable: true });
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// key -> JSON text. Sizes count key and JSON characters.
|
|
228
|
+
const stored = new Map(Object.entries(parse(storeJson)));
|
|
229
|
+
const writes = new Map();
|
|
230
|
+
let storedChars = 0;
|
|
231
|
+
for (const [key, json] of stored) storedChars += key.length + json.length;
|
|
232
|
+
|
|
233
|
+
const STORE_HINT =
|
|
234
|
+
"store() is for small state such as IDs or summaries. Show images with image(), keep large data in variables, or write it to a file with a tool.";
|
|
235
|
+
|
|
236
|
+
function checkKey(name, key) {
|
|
237
|
+
if (typeof key !== "string") throw new TypeError(name + "() key must be a string");
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function store(key, value) {
|
|
241
|
+
checkKey("store", key);
|
|
242
|
+
const previous = stored.has(key) ? key.length + stored.get(key).length : 0;
|
|
243
|
+
if (value === undefined) {
|
|
244
|
+
stored.delete(key);
|
|
245
|
+
storedChars -= previous;
|
|
246
|
+
writes.set(key, undefined);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
let json;
|
|
250
|
+
try {
|
|
251
|
+
json = stringify(value);
|
|
252
|
+
} catch (error) {
|
|
253
|
+
throw new TypeError("store(" + stringify(key) + ") value is not JSON-serializable: " + format(error));
|
|
254
|
+
}
|
|
255
|
+
if (json === undefined) {
|
|
256
|
+
throw new TypeError("store(" + stringify(key) + ") value is not JSON-serializable");
|
|
257
|
+
}
|
|
258
|
+
if (json.length > 262144) {
|
|
259
|
+
throw new RangeError(
|
|
260
|
+
"store(" + stringify(key) + ") value has " + json.length + " characters of JSON, more than the limit of 262144. " +
|
|
261
|
+
STORE_HINT,
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
const next = storedChars - previous + key.length + json.length;
|
|
265
|
+
if (next > 1048576) {
|
|
266
|
+
throw new RangeError(
|
|
267
|
+
"store is full: stored values would exceed 1048576 characters of JSON. Delete keys with store(key, undefined). " +
|
|
268
|
+
STORE_HINT,
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
stored.set(key, json);
|
|
272
|
+
storedChars = next;
|
|
273
|
+
writes.set(key, json);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function load(key) {
|
|
277
|
+
checkKey("load", key);
|
|
278
|
+
const json = stored.get(key);
|
|
279
|
+
return json === undefined ? undefined : parse(json);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function serializeWrites() {
|
|
283
|
+
const entries = [];
|
|
284
|
+
for (const [key, json] of writes) entries.push(json === undefined ? [key] : [key, json]);
|
|
285
|
+
return stringify(entries);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
Object.defineProperty(globalThis, "store", { value: store, enumerable: true });
|
|
289
|
+
Object.defineProperty(globalThis, "load", { value: load, enumerable: true });
|
|
290
|
+
|
|
291
|
+
let outputChars = 0;
|
|
292
|
+
let outputItems = 0;
|
|
293
|
+
|
|
294
|
+
// Past the output limits the script fails: done() reports the error, so catching it does not
|
|
295
|
+
// resume output, and the host ends the script.
|
|
296
|
+
function output(kind, data, mimeType) {
|
|
297
|
+
if (finished) return;
|
|
298
|
+
outputChars += data.length;
|
|
299
|
+
outputItems++;
|
|
300
|
+
if (outputChars > 16777216 || outputItems > 100000) {
|
|
301
|
+
const error = new RangeErrorCtor(
|
|
302
|
+
"script output exceeded the limit of 16777216 characters or 100000 text(), image(), and console calls. " +
|
|
303
|
+
"Print a summary instead, or write large data to a file with a tool.",
|
|
304
|
+
);
|
|
305
|
+
done(false, describeError(error));
|
|
306
|
+
throw error;
|
|
307
|
+
}
|
|
308
|
+
bridge("output", kind, data, mimeType);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Primitives become their string form, everything else JSON.
|
|
312
|
+
function outputText(value) {
|
|
313
|
+
if (value === undefined || value === null || typeof value !== "object" && typeof value !== "function") {
|
|
314
|
+
return String(value);
|
|
315
|
+
}
|
|
316
|
+
const json = stringify(value);
|
|
317
|
+
return json === undefined ? String(value) : json;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function text(value) {
|
|
321
|
+
let rendered;
|
|
322
|
+
try {
|
|
323
|
+
rendered = outputText(value);
|
|
324
|
+
} catch (error) {
|
|
325
|
+
throw new TypeErrorCtor(error instanceof ErrorCtor ? error.message : String(error));
|
|
326
|
+
}
|
|
327
|
+
output("text", rendered);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function imageUrl(value) {
|
|
331
|
+
if (typeof value === "string") return value;
|
|
332
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
333
|
+
throw new TypeErrorCtor(${JSON.stringify(IMAGE_HELPER_EXPECTS)});
|
|
334
|
+
}
|
|
335
|
+
if (value.image_url !== undefined) {
|
|
336
|
+
if (typeof value.image_url !== "string") throw new TypeErrorCtor(${JSON.stringify(IMAGE_HELPER_EXPECTS)});
|
|
337
|
+
return value.image_url;
|
|
338
|
+
}
|
|
339
|
+
if (typeof value.type !== "string") throw new TypeErrorCtor(${JSON.stringify(IMAGE_HELPER_EXPECTS)});
|
|
340
|
+
if (value.type !== "image") {
|
|
341
|
+
throw new TypeErrorCtor('image only accepts image blocks, got "' + value.type + '"');
|
|
342
|
+
}
|
|
343
|
+
if (typeof value.data !== "string" || value.data === "") throw new TypeErrorCtor("image expected image block data");
|
|
344
|
+
if (value.data.toLowerCase().startsWith("data:")) return value.data;
|
|
345
|
+
return "data:;base64," + value.data;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Base64 of the signatures of the formats providers accept inline (PNG, JPEG except
|
|
349
|
+
// JPEG-LS, GIF, "RIFF....WEBP"). Signatures start at byte 0, so their encodings are prefixes.
|
|
350
|
+
const IMAGE_SIGNATURES = [
|
|
351
|
+
["image/png", /^iVBORw0KGg/],
|
|
352
|
+
["image/jpeg", /^[/]9j[/](?!9)/],
|
|
353
|
+
["image/gif", /^R0lGOD[dl]h/],
|
|
354
|
+
["image/webp", /^UklG.{8}RUJQ/],
|
|
355
|
+
];
|
|
356
|
+
|
|
357
|
+
function image(value) {
|
|
358
|
+
const url = imageUrl(value);
|
|
359
|
+
if (url === "") throw new TypeErrorCtor(${JSON.stringify(IMAGE_HELPER_EXPECTS)});
|
|
360
|
+
const colon = url.indexOf(":");
|
|
361
|
+
const scheme = colon === -1 ? "" : url.slice(0, colon).toLowerCase();
|
|
362
|
+
if (scheme === "http" || scheme === "https") {
|
|
363
|
+
throw new TypeErrorCtor("remote image URLs are not supported in tool outputs. Pass a base64 data URI instead");
|
|
364
|
+
}
|
|
365
|
+
const comma = url.indexOf(",");
|
|
366
|
+
const header = comma === -1 ? [] : url.slice(colon + 1, comma).split(";");
|
|
367
|
+
if (scheme !== "data" || comma === -1 || header.slice(1).every((part) => part.toLowerCase() !== "base64")) {
|
|
368
|
+
throw new TypeErrorCtor("invalid image output. Pass a base64 data URI instead");
|
|
369
|
+
}
|
|
370
|
+
// Providers reject the whole request on a bad image, and a persisted image block would be
|
|
371
|
+
// resent on every later turn. Line breaks from wrapped base64 are dropped. The declared type
|
|
372
|
+
// is ignored in favor of the detected one, as providers also reject mismatches.
|
|
373
|
+
const data = url.slice(comma + 1).replace(/\\s+/g, "");
|
|
374
|
+
if (data.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(data)) {
|
|
375
|
+
throw new TypeErrorCtor("invalid image output. The image data is not valid base64 (truncated or corrupted?)");
|
|
376
|
+
}
|
|
377
|
+
const head = data.slice(0, 16);
|
|
378
|
+
const signature = IMAGE_SIGNATURES.find(([, pattern]) => pattern.test(head));
|
|
379
|
+
if (!signature) {
|
|
380
|
+
throw new TypeErrorCtor("invalid image output. The image data is not a PNG, JPEG, GIF, or WebP image");
|
|
381
|
+
}
|
|
382
|
+
output("image", data, signature[0]);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function exit() {
|
|
386
|
+
let writesJson;
|
|
387
|
+
try {
|
|
388
|
+
writesJson = serializeWrites();
|
|
389
|
+
} catch (error) {
|
|
390
|
+
done(false, describeError(error));
|
|
391
|
+
throw EXIT;
|
|
392
|
+
}
|
|
393
|
+
done(true, undefined, writesJson);
|
|
394
|
+
throw EXIT;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const console = {};
|
|
398
|
+
for (const level of ["log", "info", "warn", "error", "debug"]) {
|
|
399
|
+
console[level] = (...args) => {
|
|
400
|
+
output("console", args.map(format).join(" "));
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
Object.freeze(console);
|
|
404
|
+
|
|
405
|
+
Object.defineProperty(globalThis, "tools", { value: toolsProxy, enumerable: true });
|
|
406
|
+
Object.defineProperty(globalThis, "ALL_TOOLS", { value: allTools, enumerable: true });
|
|
407
|
+
Object.defineProperty(globalThis, "console", { value: console, enumerable: true });
|
|
408
|
+
Object.defineProperty(globalThis, "text", { value: text, enumerable: true });
|
|
409
|
+
Object.defineProperty(globalThis, "image", { value: image, enumerable: true });
|
|
410
|
+
Object.defineProperty(globalThis, "exit", { value: exit, enumerable: true });
|
|
411
|
+
|
|
412
|
+
return {
|
|
413
|
+
settle(id, ok, payload, propertiesJson) {
|
|
414
|
+
const entry = pending.get(id);
|
|
415
|
+
if (!entry) return;
|
|
416
|
+
pending.delete(id);
|
|
417
|
+
if (!ok) {
|
|
418
|
+
const error = new ErrorCtor(payload);
|
|
419
|
+
if (propertiesJson !== undefined) {
|
|
420
|
+
const properties = parse(propertiesJson);
|
|
421
|
+
for (const key of Object.keys(properties)) {
|
|
422
|
+
if (key === "name" || key === "message" || key === "stack") continue;
|
|
423
|
+
Object.defineProperty(error, key, { value: properties[key], writable: true, enumerable: true, configurable: true });
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
entry.reject(error);
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
let value;
|
|
430
|
+
try {
|
|
431
|
+
value = payload === undefined ? undefined : parse(payload);
|
|
432
|
+
} catch (error) {
|
|
433
|
+
entry.reject(error);
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
entry.resolve(value);
|
|
437
|
+
},
|
|
438
|
+
run(fn) {
|
|
439
|
+
let promise;
|
|
440
|
+
try {
|
|
441
|
+
promise = fn(toolsProxy, console);
|
|
442
|
+
} catch (error) {
|
|
443
|
+
done(false, describeError(error));
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
promiseThen.call(
|
|
447
|
+
promise,
|
|
448
|
+
(value) => {
|
|
449
|
+
let json;
|
|
450
|
+
try {
|
|
451
|
+
json = serialize(value);
|
|
452
|
+
} catch (error) {
|
|
453
|
+
done(false, describeError(error));
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
done(true, json, serializeWrites());
|
|
457
|
+
},
|
|
458
|
+
(error) => {
|
|
459
|
+
done(false, describeError(error));
|
|
460
|
+
},
|
|
461
|
+
);
|
|
462
|
+
},
|
|
463
|
+
stalled() {
|
|
464
|
+
if (finished || pending.size > 0) return false;
|
|
465
|
+
done(
|
|
466
|
+
false,
|
|
467
|
+
stringify({
|
|
468
|
+
name: "Error",
|
|
469
|
+
message:
|
|
470
|
+
"The script is waiting on a promise that can never settle: no tool call is pending, and timers do not exist here.",
|
|
471
|
+
}),
|
|
472
|
+
);
|
|
473
|
+
return true;
|
|
474
|
+
},
|
|
475
|
+
};
|
|
476
|
+
})`;function fnv1a(text){let hash=2166136261;for(let index=0;index<text.length;index++)hash^=text.charCodeAt(index),hash=Math.imul(hash,16777619);return(hash>>>0).toString(16).padStart(8,"0")}var PRELUDE_HASH=fnv1a(PRELUDE_SOURCE);var INLINE_MAX_STACK_SIZE=256*1024;var FLUSH_CHARS=1<<20;var ARGS_PREVIEW_CHARS=200,ERROR_PREVIEW_CHARS=500,MAX_CONCURRENT_MODEL_CALLS=4,CODEMODE_MEMORY_LIMIT_BYTES=256*1024*1024,MAX_CONCURRENT_CODEMODE_WORKERS=2,activeCodemodeWorkers=0,MODEL_TYPES=new Set(["chat","image","classifier"]);function truncateText(text,maxChars){return text.length>maxChars?`${text.slice(0,maxChars-3)}...`:text}function previewArgs(args){if(args===void 0)return"";try{return truncateText(JSON.stringify(args)??"",ARGS_PREVIEW_CHARS)}catch{return""}}function textOf(result){return(result.content??[]).filter(block=>block.type==="text").map(block=>block.text).join(`
|
|
477
|
+
`)}function toModelType(value){if(typeof value=="string"&&MODEL_TYPES.has(value))return value;throw new Error(`Unknown model type ${JSON.stringify(value)}. Use "chat", "image", or "classifier".`)}function toProvider(value){if(value!=null){if(typeof value!="string")throw new Error("provider must be a string");return value}}function toModelInfo(model){let info={...model};return delete info.headers,info}function withArticle(word){return`${/^[aeiou]/.test(word)?"an":"a"} ${word}`}function describeValue(value){if(value==null)return String(value);if(Array.isArray(value))return value.length===0?"an empty array":"an array";if(typeof value=="object"){let keys=Object.keys(value);return keys.length===0?"{}":`{ ${keys.slice(0,6).join(", ")}${keys.length>6?", ...":""} }`}return typeof value=="string"?"a string":`a ${typeof value}`}var CLASSIFIER_CONTEXT_SHAPE='{ state: { ... }, images?: [{ type: "image", data: <base64>, mimeType }], questions: { <id>: { type: "choice", instructions, criteria: { <label>: <meaning> } } | { type: "score", instructions, criteria: [<lowest level>, ..., <highest level>] } | { type: "bool", instructions, criteria: { true: <meaning>, false: <meaning> } } } }';function checkClassifierContext(context){let fail=problem=>new Error(`models.classify() ${problem}. Expected context: ${CLASSIFIER_CONTEXT_SHAPE}. See "Classify" in ${CODEMODE_DOCS_PATH}.`);if(typeof context!="object"||context===null||Array.isArray(context))throw fail(`expects a context object as its second argument, got ${describeValue(context)}`);let{state,images,questions}=context;if(typeof state!="object"||state===null||Array.isArray(state))throw fail(`context.state must be an object, got ${describeValue(state)}`);if(images!==void 0){if(!Array.isArray(images))throw fail(`context.images must be an array, got ${describeValue(images)}`);images.forEach((image,index)=>{if(image?.type!=="image"||typeof image.data!="string"||typeof image.mimeType!="string")throw fail(`context.images[${index}] must be an image block, got ${describeValue(image)}`)})}if(typeof questions!="object"||questions===null||Array.isArray(questions)||Object.keys(questions).length===0)throw fail(`context.questions must map question IDs to questions, got ${describeValue(questions)}`);let isStrings=values=>values.length>0&&values.every(value=>typeof value=="string");for(let[id,question]of Object.entries(questions)){let at=`context.questions.${id}`;if(typeof question!="object"||question===null||Array.isArray(question))throw fail(`${at} must be a question object, got ${describeValue(question)}`);let{type,instructions,criteria}=question;if(typeof instructions!="string")throw fail(`${at}.instructions must be a string`);if(type==="choice"){if(typeof criteria!="object"||criteria===null||Array.isArray(criteria)||!isStrings(Object.values(criteria)))throw fail(`${at} is a "choice" question, so criteria must map each label to its meaning`)}else if(type==="score"){if(!Array.isArray(criteria)||!isStrings(criteria))throw fail(`${at} is a "score" question, so criteria must list the levels as strings, lowest first`)}else if(type==="bool"){let labels=criteria;if(typeof labels?.true!="string"||typeof labels.false!="string")throw fail(`${at} is a "bool" question, so criteria must be { true: string, false: string }`)}else throw fail(`${at}.type must be "choice", "score", or "bool", got ${JSON.stringify(type)}`)}return context}function checkImagesContext(context){let fail=problem=>new Error(`models.generateImages() ${problem}. Expected context: { input: [{ type: "text", text: <prompt> }, ...optional { type: "image", data: <base64>, mimeType } references] }. See "Generate images" in ${CODEMODE_DOCS_PATH}.`);if(typeof context!="object"||context===null||Array.isArray(context))throw fail(`expects a context object as its second argument, got ${describeValue(context)}`);let{input}=context;if(!Array.isArray(input)||input.length===0)throw fail(`context.input must be a non-empty array of blocks, got ${describeValue(input)}`);return input.forEach((block,index)=>{if(!(block?.type==="text"&&typeof block.text=="string")&&!(block?.type==="image"&&typeof block.data=="string"&&typeof block.mimeType=="string"))throw fail(`context.input[${index}] must be a text or image block, got ${describeValue(block)}`)}),context}function createLimiter(limit){let active=0,waiting=[];return async run=>{active>=limit&&await new Promise(resolve=>waiting.push(resolve)),active++;try{return await run()}finally{active--,waiting.shift()?.()}}}function isStoreEntryData(data){if(typeof data!="object"||data===null)return!1;let{set,delete:deleted}=data;return typeof set=="object"&&set!==null&&Array.isArray(deleted)&&deleted.every(key=>typeof key=="string")}function readCodemodeStore(branch){let store=new Map;for(let entry of branch)if(!(entry.type!=="custom"||entry.customType!==CODEMODE_STORE_ENTRY_TYPE||!isStoreEntryData(entry.data))){for(let key of entry.data.delete)store.delete(key);for(let[key,value]of Object.entries(entry.data.set))store.set(key,value)}return Object.fromEntries(store)}var DEFAULT_MAX_OUTPUT_TOKENS=1e4,CHARS_PER_TOKEN=4;function valueText(value){return typeof value=="string"?value:JSON.stringify(value)??String(value)}function formatOutput(output){let total=output.filter(item=>item.type==="text"&&!item.console).length,items=[],consoleLines=[],index=0;for(let item of output)item.type==="image"?items.push(item):item.console?consoleLines.push(item.text):(index++,items.push({type:"text",text:total>1?`==> text ${index}/${total} <==
|
|
478
|
+
${item.text}`:item.text}));return consoleLines.length>0&&items.push({type:"text",text:`<console_output>
|
|
479
|
+
${consoleLines.join(`
|
|
480
|
+
`)}
|
|
481
|
+
</console_output>`}),items}function joinAdjacentText(items){let joined=[],parts=[],lastPart="",flush=()=>{parts.length>0&&joined.push({type:"text",text:parts.join("")}),parts=[],lastPart=""};for(let item of items){if(item.type!=="text"){flush(),joined.push(item);continue}lastPart!==""&&!lastPart.endsWith(`
|
|
482
|
+
`)&&(parts.push(`
|
|
483
|
+
`),lastPart=`
|
|
484
|
+
`),parts.push(item.text),item.text!==""&&(lastPart=item.text)}return flush(),joined}function formatCallSummary(calls){return calls.length===0?"No tool calls were made.":`Tool calls made before the failure (they are not undone): ${calls.map(call=>`${call.name} (${call.status})`).join(", ")}`}function formatError(result,calls){let{error}=result;return`${error.kind==="script"?error.stack??`${error.name??"Error"}: ${error.message}`:error.kind==="timeout"?`Script timed out: ${error.message}`:error.kind==="aborted"?`Script aborted: ${error.message}`:`Script sandbox failed: ${error.message}`}
|
|
485
|
+
|
|
486
|
+
${formatCallSummary(calls)}`}async function spillOutput(text){try{return{path:await writeOutputFile("knightcode-codemode",".txt",text)}}catch(error){return{error:error instanceof Error?error.message:String(error)}}}var IMAGE_EXTENSIONS={"image/png":".png","image/jpeg":".jpg","image/gif":".gif","image/webp":".webp"};async function saveImages(items){let labels=new Map,label=async({data,mimeType})=>{let bytes=Buffer.from(data,"base64"),kind=`${mimeType}, ${formatSize(bytes.length)}`,extension=IMAGE_EXTENSIONS[mimeType];if(!extension)throw new Error(`No file extension for image type ${mimeType}`);try{return`[Image saved to ${await writeOutputFile("knightcode-codemode",extension,bytes)} (${kind})]`}catch(error){return`[Image (${kind}) could not be saved: ${error instanceof Error?error.message:String(error)}]`}};return(await Promise.all(items.map(async item=>{if(item.type!=="image")return[item];let pending=labels.get(item.data);return pending||(pending=label(item),labels.set(item.data,pending)),[{type:"text",text:await pending},item]}))).flat()}async function truncateOutput(items,maxTokens){let texts=items.filter(item=>item.type==="text").map(item=>item.text),combined=texts.join(`
|
|
487
|
+
`),budget=maxTokens*CHARS_PER_TOKEN;if(texts.length===0||combined.length<=budget)return{items};let headChars=Math.floor(budget/2),tailChars=budget-headChars,removed=combined.length-headChars-tailChars,head=combined.slice(0,headChars),tail=tailChars>0?combined.slice(-tailChars):"",text=`Warning: truncated output (original token count: ${Math.ceil(combined.length/CHARS_PER_TOKEN)})
|
|
488
|
+
Total output lines: ${combined.split(`
|
|
489
|
+
`).length}
|
|
490
|
+
|
|
491
|
+
${head}\u2026${Math.ceil(removed/CHARS_PER_TOKEN)} tokens truncated\u2026${tail}`,spilled=await spillOutput(combined);return text+="path"in spilled?`
|
|
492
|
+
|
|
493
|
+
[Full output: ${spilled.path} (read with offset/limit)]`:`
|
|
494
|
+
|
|
495
|
+
[Could not save the full output: ${spilled.error}]`,{items:[{type:"text",text},...items.filter(item=>item.type==="image")],..."path"in spilled?{fullOutputPath:spilled.path}:{}}}function toScriptValue(tool,outcome){let{result}=outcome;if(tool.outputSchema&&result.structuredContent!==void 0)return result.structuredContent;let text=textOf(result);if(outcome.isError)throw new Error(text||`Tool "${tool.name}" failed`);return text}async function executeCodemode(toolCallId,input,signal,onUpdate,ctx,options={}){let startedAt=performance.now(),{code,options:sourceOptions}=parseCodemodeSource(input.code),calls=[],modelUsage,generatedImages=0,addGeneratedImages=count=>{generatedImages+=count},addModelUsage=usage=>{modelUsage=modelUsage?combineUsage(modelUsage,usage):usage},snapshot=()=>({calls:calls.map(call=>({...call}))}),publish=()=>onUpdate?.({content:[],details:snapshot()});publish();let callable=ctx?getCodemodeCallableTools(ctx.tools):[],guidelines=options.getToolGuidelines?.(),samples=new Map(callable.map(tool=>[tool.name,renderToolSample(toCodemodeDeclaration(tool,guidelines?.get(tool.name)))])),sandboxTools=callable.map(tool=>({name:tool.name,description:samples.get(tool.name),execute:async(args,{signal:callSignal})=>{let record={id:`${toolCallId}/?`,name:tool.name,args:previewArgs(args),status:"running"};calls.push(record),publish();let callStartedAt=performance.now();if(!ctx)throw new Error("Tool calls need a session");let outcome=await ctx.executeTool(tool.name,args,{signal:callSignal});return record.id=outcome.toolCall.id,record.durationMs=performance.now()-callStartedAt,outcome.isError?(record.status=callSignal.aborted?"cancelled":"error",record.error=truncateText(textOf(outcome.result)||`Tool "${tool.name}" failed`,ERROR_PREVIEW_CHARS)):record.status="ok",publish(),toScriptValue(tool,outcome)}})),sandbox=new CodemodeSandbox({tools:sandboxTools,globals:[...createDiscoveryGlobals(callable,samples,options),...options.models&&ctx?createModelGlobals(ctx.modelRegistry,toolCallId,calls,publish,addModelUsage,addGeneratedImages):[]],timeoutMs:sourceOptions.timeoutMs??Number.POSITIVE_INFINITY,memoryLimitBytes:CODEMODE_MEMORY_LIMIT_BYTES,wasm:loadQuickJSWasm(getQuickJSWasmPath()),workerUrl:getCodemodeWorkerSpecifier(),acquireWorker:()=>{if(activeCodemodeWorkers>=MAX_CONCURRENT_CODEMODE_WORKERS)throw new Error(`Codemode worker limit reached (${MAX_CONCURRENT_CODEMODE_WORKERS} workers are still running or shutting down). Retry after they exit.`);return activeCodemodeWorkers++,()=>{activeCodemodeWorkers--}}}),result;try{let store=ctx?readCodemodeStore(ctx.sessionManager.getBranch()):{};result=await sandbox.execute(code,{signal,store})}finally{await sandbox.close()}for(let call of calls)call.status==="running"&&(call.status="cancelled");let scriptOutput=[...result.output];if(result.ok){let{set,delete:deleted}=result.storeWrites;(Object.keys(set).length>0||deleted.length>0)&&options.appendEntry?.(CODEMODE_STORE_ENTRY_TYPE,{set,delete:deleted}),result.value!==void 0&&scriptOutput.push({type:"text",text:valueText(result.value)})}let items=formatOutput(scriptOutput);result.ok||items.push({type:"text",text:`Script error:
|
|
496
|
+
${formatError(result,calls)}`}),generatedImages>0&&!items.some(item=>item.type==="image")&&items.push({type:"text",text:`Note: models.generateImages() returned ${generatedImages} image${generatedImages===1?"":"s"} that the script did not show. Show each image block of result.output with image(block).`});let truncated=await truncateOutput(joinAdjacentText(items),sourceOptions.maxOutputTokens??DEFAULT_MAX_OUTPUT_TOKENS),output=joinAdjacentText(await saveImages(truncated.items)),wallTime=((performance.now()-startedAt)/1e3).toFixed(1),header=`${result.ok?"Script completed":"Script failed"}
|
|
497
|
+
Wall time ${wallTime} seconds
|
|
498
|
+
Output:
|
|
499
|
+
`,details=snapshot();return truncated.fullOutputPath&&(details.fullOutputPath=truncated.fullOutputPath),{content:[{type:"text",text:header},...output],details,...modelUsage?{usage:modelUsage}:{},...result.ok?{}:{isError:!0}}}function isNamespaceName(namespace,query){let queryId=toCodemodeIdentifier(query);return[namespace.name,...namespace.aliases??[]].some(name=>name===query||toCodemodeIdentifier(name)===queryId)}function createDiscoveryGlobals(tools,samples,options){let ranker=new Bm25Ranker,entry=name=>({name:toCodemodeIdentifier(name),description:samples.get(name)??""});return[{name:"searchTools",spread:!0,execute:args=>{let[query,searchOptions]=args;if(typeof query!="string")throw new Error("searchTools() expects a query string");let limit=searchOptions?.limit??DEFAULT_TOOL_SEARCH_LIMIT;if(typeof limit!="number"||!Number.isInteger(limit)||limit<=0)throw new Error("searchTools() limit must be a positive integer");let namespace=searchOptions?.namespace;if(namespace!=null&&typeof namespace!="string")throw new Error("searchTools() namespace must be a string");let documents=tools.flatMap(tool=>{let toolNamespace=options.getToolNamespace?.(tool.name);return namespace&&(!toolNamespace||!isNamespaceName(toolNamespace,namespace))?[]:[createToolSearchDocument(tool,toolNamespace)]});return ranker.rank(query,documents,limit).map(match=>entry(match.name))}},{name:"describeTool",spread:!0,execute:args=>{let[name]=args;if(typeof name!="string")throw new Error("describeTool() expects a tool name");let tool=tools.find(candidate=>candidate.name===name||toCodemodeIdentifier(candidate.name)===name);return tool?samples.get(tool.name):void 0}},{name:"describeNamespace",spread:!0,execute:args=>{let[name]=args;if(typeof name!="string")throw new Error("describeNamespace() expects a namespace name");let namespace,names=[];for(let tool of tools){let toolNamespace=options.getToolNamespace?.(tool.name);!toolNamespace||!isNamespaceName(toolNamespace,name)||(namespace??=toolNamespace,names.push(toCodemodeIdentifier(tool.name)))}if(namespace)return{name:namespace.name,...namespace.description?{description:namespace.description}:{},...namespace.instructions?{instructions:namespace.instructions}:{},tools:names}}}]}function createModelGlobals(models,toolCallId,calls,publish,addUsage,addGeneratedImages){let limit=createLimiter(MAX_CONCURRENT_MODEL_CALLS),callCount=0,runModelCall=async(name,type,[model,context],checkContext,run)=>{let listHint=`List the ${type} models you can use with models.getAvailableOfType("${type}").`,given=model;if(typeof given?.provider!="string"||typeof given.id!="string"){let undefinedHint=model==null?" models.getModelOfType() returns undefined for an unknown provider or id.":"";throw new Error(`${name}() expects ${withArticle(type)} model as its first argument, got ${describeValue(model)}.${undefinedHint} ${listHint}`)}let provider=given.provider,id=given.id,ref=`${provider}/${id}`,resolved=models.getModelOfType(type,provider,id);if(!resolved){let actualType=[...MODEL_TYPES].find(other=>other!==type&&models.getModelOfType(other,provider,id)!==void 0);throw new Error(actualType?`"${ref}" is ${withArticle(actualType)} model, not ${withArticle(type)} model. ${listHint}`:`Unknown ${type} model "${ref}". ${listHint}`)}let checked=checkContext(context),record={id:`${toolCallId}/${name}/${++callCount}`,name,args:`${resolved.provider}/${resolved.id}`,status:"running"};calls.push(record),publish();let startedAt=performance.now(),result=await limit(()=>run(resolved,checked));return record.durationMs=performance.now()-startedAt,record.status=result.stopReason==="stop"?"ok":result.stopReason==="aborted"?"cancelled":"error",result.errorMessage&&(record.error=truncateText(result.errorMessage,ERROR_PREVIEW_CHARS)),result.usage&&(record.cost=result.usage.cost.total,addUsage(result.usage)),publish(),result};return Object.entries({"models.getModelsOfType":args=>{let[type,provider]=args;return models.getModelsOfType(toModelType(type),toProvider(provider)).map(toModelInfo)},"models.getAvailableOfType":async(args,{signal})=>{let[type,provider]=args;return(await models.getAvailableOfType(toModelType(type),toProvider(provider),{signal})).map(toModelInfo)},"models.getModelOfType":args=>{let[type,provider,id]=args;if(typeof provider!="string"||typeof id!="string")throw new Error(`models.getModelOfType(type, provider, id) expects three strings, got (${args.map(describeValue).join(", ")}). The provider and the id are separate arguments, for example models.getModelOfType("classifier", "typesafe", "jev-latest").`);let model=models.getModelOfType(toModelType(type),provider,id);return model===void 0?void 0:toModelInfo(model)},"models.classify":(args,{signal})=>runModelCall("models.classify","classifier",args,checkClassifierContext,(resolved,context)=>models.classify(resolved,context,{signal})),"models.generateImages":(args,{signal})=>runModelCall("models.generateImages","image",args,checkImagesContext,async(resolved,context)=>{let result=await models.generateImages(resolved,context,{signal});return addGeneratedImages(result.output.filter(block=>block.type==="image").length),result})}).map(([name,execute])=>({name,spread:!0,execute}))}export{executeCodemode,readCodemodeStore};
|