experimental-ash 0.34.0 → 0.36.0
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 +35 -0
- package/dist/docs/internals/context.md +6 -5
- package/dist/docs/internals/core-beliefs.md +2 -2
- package/dist/docs/internals/hooks.md +16 -11
- package/dist/docs/internals/mechanical-invariants.md +4 -4
- package/dist/docs/internals/testing.md +1 -1
- package/dist/docs/public/README.md +1 -1
- package/dist/docs/public/auth-and-route-protection.md +12 -3
- package/dist/docs/public/channels/{README.md → index.md} +2 -2
- package/dist/docs/public/channels/slack.md +3 -3
- package/dist/docs/public/cli-build-and-debugging.md +1 -1
- package/dist/docs/public/faqs.md +4 -5
- package/dist/docs/public/hooks.md +18 -23
- package/dist/docs/public/meta.json +4 -4
- package/dist/docs/public/sandbox.md +51 -30
- package/dist/docs/public/schedules.md +1 -1
- package/dist/docs/public/session-context.md +26 -28
- package/dist/docs/public/skills.md +3 -4
- package/dist/docs/public/subagents.md +1 -1
- package/dist/docs/public/tools.md +13 -17
- package/dist/docs/public/typescript-api.md +10 -11
- package/dist/src/channel/session.d.ts +3 -29
- package/dist/src/channel/session.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +2 -2
- package/dist/src/compiled/@vercel/sandbox/index.d.ts +11 -2
- package/dist/src/compiled/@vercel/sandbox/index.js +3 -3
- package/dist/src/compiled/@vercel/sandbox/package.json +1 -1
- package/dist/src/compiled/_chunks/node/{auth-ZhCJAHxl.js → auth-CVVvWjaK.js} +1 -1
- package/dist/src/compiled/_chunks/node/{version-D4IYmfaS.js → version-nR4RSpFw.js} +1 -1
- package/dist/src/context/build-callback-context.d.ts +8 -0
- package/dist/src/context/build-callback-context.js +1 -0
- package/dist/src/context/hook-lifecycle.js +1 -1
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/sandbox/bash-tool.d.ts +2 -1
- package/dist/src/execution/sandbox/bash-tool.js +1 -1
- package/dist/src/execution/sandbox/bindings/vercel.d.ts +1 -1
- package/dist/src/execution/sandbox/glob-tool.d.ts +2 -1
- package/dist/src/execution/sandbox/glob-tool.js +3 -3
- package/dist/src/execution/sandbox/grep-tool.d.ts +2 -1
- package/dist/src/execution/sandbox/grep-tool.js +3 -3
- package/dist/src/execution/sandbox/read-file-tool.d.ts +2 -1
- package/dist/src/execution/sandbox/read-file-tool.js +1 -1
- package/dist/src/execution/sandbox/session.js +1 -1
- package/dist/src/execution/sandbox/write-file-tool.d.ts +2 -1
- package/dist/src/execution/sandbox/write-file-tool.js +1 -1
- package/dist/src/execution/tool-compaction.js +1 -1
- package/dist/src/harness/code-mode-approval.js +1 -1
- package/dist/src/harness/code-mode.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/logging.js +1 -1
- package/dist/src/internal/workflow-bundle/builder.js +2 -2
- package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/index.js +1 -1
- package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime/manager.js +1 -0
- package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime/worker-source.js +408 -0
- package/dist/src/packages/ash-scaffold/src/channels.js +2 -12
- package/dist/src/packages/ash-scaffold/src/pnpm-workspace.js +11 -0
- package/dist/src/packages/ash-scaffold/src/project.js +1 -1
- package/dist/src/packages/ash-scaffold/src/web-template.js +2 -2
- package/dist/src/public/channels/auth.d.ts +22 -11
- package/dist/src/public/channels/auth.js +1 -1
- package/dist/src/public/context/index.d.ts +3 -2
- package/dist/src/public/context/index.js +1 -1
- package/dist/src/public/definitions/callback-context.d.ts +22 -0
- package/dist/src/public/definitions/callback-context.js +1 -0
- package/dist/src/public/definitions/hook.d.ts +9 -49
- package/dist/src/public/definitions/sandbox.d.ts +1 -1
- package/dist/src/public/definitions/tool.d.ts +14 -15
- package/dist/src/public/hooks/index.d.ts +1 -1
- package/dist/src/public/sandbox/index.d.ts +1 -2
- package/dist/src/public/sandbox/index.js +1 -1
- package/dist/src/public/sandbox/vercel-sandbox.d.ts +4 -4
- package/dist/src/public/skills/index.d.ts +0 -1
- package/dist/src/public/skills/index.js +1 -1
- package/dist/src/public/tools/defaults.js +1 -1
- package/dist/src/public/tools/define-bash-tool.js +1 -1
- package/dist/src/public/tools/define-glob-tool.js +1 -1
- package/dist/src/public/tools/define-grep-tool.js +1 -1
- package/dist/src/public/tools/define-read-file-tool.js +1 -1
- package/dist/src/public/tools/define-write-file-tool.js +1 -1
- package/dist/src/public/tools/index.d.ts +2 -1
- package/dist/src/public/tools/internal.d.ts +4 -0
- package/dist/src/public/tools/internal.js +1 -1
- package/dist/src/runtime/framework-tools/bash.js +1 -1
- package/dist/src/runtime/framework-tools/connection-search.js +1 -1
- package/dist/src/runtime/framework-tools/connection-tools.js +1 -1
- package/dist/src/runtime/framework-tools/file-state.d.ts +2 -2
- package/dist/src/runtime/framework-tools/file-state.js +1 -1
- package/dist/src/runtime/framework-tools/glob.js +1 -1
- package/dist/src/runtime/framework-tools/grep.js +1 -1
- package/dist/src/runtime/framework-tools/read-file.js +2 -2
- package/dist/src/runtime/framework-tools/todo.js +1 -1
- package/dist/src/runtime/framework-tools/write-file.js +1 -1
- package/dist/src/runtime/governance/auth/oidc.js +1 -1
- package/dist/src/runtime/governance/auth/token-claims.d.ts +2 -0
- package/dist/src/runtime/governance/auth/token-claims.js +1 -1
- package/dist/src/runtime/governance/auth/types.d.ts +6 -0
- package/dist/src/runtime/types.d.ts +2 -2
- package/dist/src/shared/sandbox-session.d.ts +0 -17
- package/package.json +3 -3
- package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime/manager.js +0 -1
- package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime/worker-source.js +0 -1153
- package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime-assets.js +0 -1
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/approval-continuation.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/approval-response.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/code-mode-tool.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/continuation-capability.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/errors.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/fetch-policy.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/host-interrupt.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/interrupt-continuation.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/options.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/run-code-mode.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/runtime/max-workers.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/serialization.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/source-cache.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/telemetry.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/tool-invocation.js +0 -0
- /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/tool-prompt.js +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AshContext } from "#context/container.js";
|
|
2
2
|
import { ContextKey } from "#context/key.js";
|
|
3
3
|
/**
|
|
4
4
|
* Per-file fingerprint stored after a successful `read_file` call. Used by
|
|
@@ -59,4 +59,4 @@ export declare function setReadFileStamp(ctx: AshContext, targetKey: string, sta
|
|
|
59
59
|
* tool's `onCompact` hook and by authored `defineReadFileTool()` replacements
|
|
60
60
|
* that keep the default compaction behavior.
|
|
61
61
|
*/
|
|
62
|
-
export declare function clearReadFileState(
|
|
62
|
+
export declare function clearReadFileState(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{posix}from"node:path";import{createHash}from"node:crypto";import{ContextKey}from"#context/key.js";const ReadFileStateKey=new ContextKey(`ash.readFile`);function normalizeModelPath(t){return posix.normalize(t)}function buildReadFileTargetKey(e){return e}function createReadFileStamp(e){let n=createHash(`sha256`).update(e.content,`utf8`).digest(`hex`);return{byteLength:Buffer.byteLength(e.content,`utf8`),contentHash:n,filePath:e.filePath}}function setReadFileStamp(e,t,n){let r=e.ensure(ReadFileStateKey,()=>({byTarget:{}}));e.set(ReadFileStateKey,{byTarget:{...r.byTarget,[t]:n}})}function clearReadFileState(
|
|
1
|
+
import{posix}from"node:path";import{createHash}from"node:crypto";import{loadContext}from"#context/container.js";import{ContextKey}from"#context/key.js";const ReadFileStateKey=new ContextKey(`ash.readFile`);function normalizeModelPath(t){return posix.normalize(t)}function buildReadFileTargetKey(e){return e}function createReadFileStamp(e){let n=createHash(`sha256`).update(e.content,`utf8`).digest(`hex`);return{byteLength:Buffer.byteLength(e.content,`utf8`),contentHash:n,filePath:e.filePath}}function setReadFileStamp(e,t,n){let r=e.ensure(ReadFileStateKey,()=>({byTarget:{}}));e.set(ReadFileStateKey,{byTarget:{...r.byTarget,[t]:n}})}function clearReadFileState(){loadContext().set(ReadFileStateKey,{byTarget:{}})}export{ReadFileStateKey,buildReadFileTargetKey,clearReadFileState,createReadFileStamp,normalizeModelPath,setReadFileStamp};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{executeGlobOnSandbox}from"#execution/sandbox/glob-tool.js";const GLOB_INPUT_SCHEMA={additionalProperties:!1,properties:{limit:{description:`Maximum number of results to return. Defaults to 100.`,maximum:1e3,minimum:1,type:`integer`},path:{description:`The directory to search in. Defaults to /workspace. Must be an absolute path. Omit to use the default.`,type:`string`},pattern:{description:`The glob pattern to match files against (e.g. "**/*.ts", "src/**/*.js").`,type:`string`}},required:[`pattern`],type:`object`};async function executeGlob(e){return executeGlobOnSandbox(e)}const GLOB_TOOL_DEFINITION={description:[`Fast file pattern matching tool that works with any codebase size.`,``,`Usage:`,`- Supports glob patterns like "**/*.js" or "src/**/*.ts".`,`- Returns matching file paths.`,`- Use this tool when you need to find files by name patterns.`,`- If you are unsure of the correct file path, use the glob tool to look up filenames by glob pattern.`,`- Use the grep tool instead if you need to search file contents.`,`- Call this tool in parallel when you know there are multiple patterns to search for.`].join(`
|
|
1
|
+
import{requireSandboxSession}from"#execution/sandbox/require-sandbox.js";import{executeGlobOnSandbox}from"#execution/sandbox/glob-tool.js";const GLOB_INPUT_SCHEMA={additionalProperties:!1,properties:{limit:{description:`Maximum number of results to return. Defaults to 100.`,maximum:1e3,minimum:1,type:`integer`},path:{description:`The directory to search in. Defaults to /workspace. Must be an absolute path. Omit to use the default.`,type:`string`},pattern:{description:`The glob pattern to match files against (e.g. "**/*.ts", "src/**/*.js").`,type:`string`}},required:[`pattern`],type:`object`};async function executeGlob(e){return executeGlobOnSandbox(await requireSandboxSession(),e)}const GLOB_TOOL_DEFINITION={description:[`Fast file pattern matching tool that works with any codebase size.`,``,`Usage:`,`- Supports glob patterns like "**/*.js" or "src/**/*.ts".`,`- Returns matching file paths.`,`- Use this tool when you need to find files by name patterns.`,`- If you are unsure of the correct file path, use the glob tool to look up filenames by glob pattern.`,`- Use the grep tool instead if you need to search file contents.`,`- Call this tool in parallel when you know there are multiple patterns to search for.`].join(`
|
|
2
2
|
`),execute:executeGlob,inputSchema:GLOB_INPUT_SCHEMA,logicalPath:`ash:framework/glob`,name:`glob`,sourceId:`ash:glob-tool`,sourceKind:`module`};export{GLOB_INPUT_SCHEMA,GLOB_TOOL_DEFINITION};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{executeGrepOnSandbox}from"#execution/sandbox/grep-tool.js";const GREP_INPUT_SCHEMA={additionalProperties:!1,properties:{context:{description:`Number of surrounding context lines to include before and after each match. Defaults to 0.`,minimum:0,type:`integer`},glob:{description:`Filter files by glob pattern (e.g. "*.ts", "*.{ts,tsx}").`,type:`string`},ignoreCase:{description:`Perform case-insensitive search. Defaults to false.`,type:`boolean`},limit:{description:`Maximum number of matches to return per file. Defaults to 100.`,maximum:1e3,minimum:1,type:`integer`},literal:{description:`Treat the pattern as a literal string instead of a regular expression. Defaults to false.`,type:`boolean`},path:{description:`The directory or file to search in. Defaults to /workspace. Must be an absolute path. Omit to use the default.`,type:`string`},pattern:{description:`The regex pattern to search for in file contents (e.g. "log.*Error", "function\\s+\\w+").`,type:`string`}},required:[`pattern`],type:`object`};async function executeGrep(e){return executeGrepOnSandbox(e)}const GREP_TOOL_DEFINITION={description:[`Fast content search tool that works with any codebase size.`,``,`Usage:`,`- Searches file contents using regular expressions.`,`- Supports full regex syntax (e.g. "log.*Error", "function\\s+\\w+").`,`- Filter files by pattern with the glob parameter (e.g. "*.js", "*.{ts,tsx}").`,`- Returns matching lines with file paths and line numbers.`,`- Use this tool when you need to find files containing specific patterns.`,`- Use the glob tool instead if you only need to find files by name.`,`- Call this tool in parallel when you have multiple independent searches.`,`- Any line longer than 2000 characters is truncated.`].join(`
|
|
1
|
+
import{requireSandboxSession}from"#execution/sandbox/require-sandbox.js";import{executeGrepOnSandbox}from"#execution/sandbox/grep-tool.js";const GREP_INPUT_SCHEMA={additionalProperties:!1,properties:{context:{description:`Number of surrounding context lines to include before and after each match. Defaults to 0.`,minimum:0,type:`integer`},glob:{description:`Filter files by glob pattern (e.g. "*.ts", "*.{ts,tsx}").`,type:`string`},ignoreCase:{description:`Perform case-insensitive search. Defaults to false.`,type:`boolean`},limit:{description:`Maximum number of matches to return per file. Defaults to 100.`,maximum:1e3,minimum:1,type:`integer`},literal:{description:`Treat the pattern as a literal string instead of a regular expression. Defaults to false.`,type:`boolean`},path:{description:`The directory or file to search in. Defaults to /workspace. Must be an absolute path. Omit to use the default.`,type:`string`},pattern:{description:`The regex pattern to search for in file contents (e.g. "log.*Error", "function\\s+\\w+").`,type:`string`}},required:[`pattern`],type:`object`};async function executeGrep(e){return executeGrepOnSandbox(await requireSandboxSession(),e)}const GREP_TOOL_DEFINITION={description:[`Fast content search tool that works with any codebase size.`,``,`Usage:`,`- Searches file contents using regular expressions.`,`- Supports full regex syntax (e.g. "log.*Error", "function\\s+\\w+").`,`- Filter files by pattern with the glob parameter (e.g. "*.js", "*.{ts,tsx}").`,`- Returns matching lines with file paths and line numbers.`,`- Use this tool when you need to find files containing specific patterns.`,`- Use the glob tool instead if you only need to find files by name.`,`- Call this tool in parallel when you have multiple independent searches.`,`- Any line longer than 2000 characters is truncated.`].join(`
|
|
2
2
|
`),execute:executeGrep,inputSchema:GREP_INPUT_SCHEMA,logicalPath:`ash:framework/grep`,name:`grep`,sourceId:`ash:grep-tool`,sourceKind:`module`};export{GREP_INPUT_SCHEMA,GREP_TOOL_DEFINITION};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{clearReadFileState}from"#runtime/framework-tools/file-state.js";import{executeReadFileOnSandbox}from"#execution/sandbox/read-file-tool.js";const READ_FILE_INPUT_SCHEMA={additionalProperties:!1,properties:{filePath:{description:`The absolute path to the file to read.`,type:`string`},limit:{description:`Maximum number of lines to return. Defaults to 2000.`,minimum:1,type:`integer`},offset:{description:`1-based line number to start from. Defaults to 1.`,minimum:1,type:`integer`}},required:[`filePath`],type:`object`};async function executeReadFile(e){return executeReadFileOnSandbox(e)}const READ_FILE_TOOL_DEFINITION={description:[`Read a file from the local filesystem. If the path does not exist, an error is returned.`,``,`Usage:`,`- The filePath parameter should be an absolute path.`,`- By default, this tool returns up to 2000 lines from the start of the file.`,`- The offset parameter is the line number to start from (1-indexed).`,`- To read later sections, call this tool again with a larger offset.`,`- Use the grep tool to find specific content in large files or files with long lines.`,`- If you are unsure of the correct file path, use the glob tool to look up filenames by glob pattern.`,'- Contents are returned with each line prefixed by its line number as `<line>: <content>`. For example, if a file has contents "foo\\n", you will receive "1: foo\\n".',`- Any line longer than 2000 characters is truncated.`,`- Call this tool in parallel when you know there are multiple files you want to read.`,`- Avoid tiny repeated slices (30 line chunks). If you need more context, read a larger window.`].join(`
|
|
2
|
-
`),execute:executeReadFile,inputSchema:READ_FILE_INPUT_SCHEMA,logicalPath:`ash:framework/read-file`,name:`read_file`,onCompact(
|
|
1
|
+
import{clearReadFileState}from"#runtime/framework-tools/file-state.js";import{requireSandboxSession}from"#execution/sandbox/require-sandbox.js";import{executeReadFileOnSandbox}from"#execution/sandbox/read-file-tool.js";const READ_FILE_INPUT_SCHEMA={additionalProperties:!1,properties:{filePath:{description:`The absolute path to the file to read.`,type:`string`},limit:{description:`Maximum number of lines to return. Defaults to 2000.`,minimum:1,type:`integer`},offset:{description:`1-based line number to start from. Defaults to 1.`,minimum:1,type:`integer`}},required:[`filePath`],type:`object`};async function executeReadFile(e){return executeReadFileOnSandbox(await requireSandboxSession(),e)}const READ_FILE_TOOL_DEFINITION={description:[`Read a file from the local filesystem. If the path does not exist, an error is returned.`,``,`Usage:`,`- The filePath parameter should be an absolute path.`,`- By default, this tool returns up to 2000 lines from the start of the file.`,`- The offset parameter is the line number to start from (1-indexed).`,`- To read later sections, call this tool again with a larger offset.`,`- Use the grep tool to find specific content in large files or files with long lines.`,`- If you are unsure of the correct file path, use the glob tool to look up filenames by glob pattern.`,'- Contents are returned with each line prefixed by its line number as `<line>: <content>`. For example, if a file has contents "foo\\n", you will receive "1: foo\\n".',`- Any line longer than 2000 characters is truncated.`,`- Call this tool in parallel when you know there are multiple files you want to read.`,`- Avoid tiny repeated slices (30 line chunks). If you need more context, read a larger window.`].join(`
|
|
2
|
+
`),execute:executeReadFile,inputSchema:READ_FILE_INPUT_SCHEMA,logicalPath:`ash:framework/read-file`,name:`read_file`,onCompact(){return clearReadFileState(),{}},sourceId:`ash:read-file-tool`,sourceKind:`module`};export{READ_FILE_INPUT_SCHEMA,READ_FILE_TOOL_DEFINITION};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import{loadContext}from"#context/container.js";import{ContextKey}from"#context/key.js";const TodoStateKey=new ContextKey(`ash.todo`);function formatTodoSummary(e){return e.items.length===0?void 0:`[Your task list was preserved across context compaction]\n${e.items.map(e=>`- [${e.status===`completed`?`x`:e.status===`cancelled`?`-`:` `}] [${e.priority}] ${e.content}`).join(`
|
|
2
2
|
`)}`}function formatTodoResult(e){let{items:t}=e,n={cancelled:0,completed:0,in_progress:0,pending:0,total:t.length};for(let e of t)n[e.status]++;return{counts:n,todos:t}}function executeTodoTool(t){let r=loadContext(),{todos:i}=t??{};if(i!==void 0){let e={items:[...i]};return r.set(TodoStateKey,e),formatTodoResult(e)}return formatTodoResult(r.ensure(TodoStateKey,()=>({items:[]})))}const TODO_TOOL_DEFINITION={description:[`Use this tool to create and manage a structured task list for the current session.`,`This helps you track progress, organize complex tasks, and demonstrate thoroughness.`,``,`When to use:`,`- Complex multistep tasks requiring 3 or more distinct steps`,`- When the user provides multiple tasks or a numbered list`,`- After receiving new instructions, to capture requirements`,`- After completing a task, to mark it complete and add follow-ups`,``,`When NOT to use:`,`- Single, straightforward tasks that need no tracking`,`- Purely conversational or informational requests`,``,`Usage:`,"- Call with `todos` to replace the entire list (full replacement write)","- Call without `todos` to read the current list",`- Both return the full current list with status counts`,`- Mark tasks in_progress when you start, completed when done`,`- Only have ONE task in_progress at a time`].join(`
|
|
3
|
-
`),execute:async e=>executeTodoTool(e??{}),inputSchema:{additionalProperties:!1,properties:{todos:{description:`The updated todo list. Omit to read the current list without modifying it.`,items:{additionalProperties:!1,properties:{content:{description:`Brief description of the task.`,type:`string`},priority:{description:`Priority level of the task.`,enum:[`high`,`medium`,`low`],type:`string`},status:{description:`Current status of the task.`,enum:[`pending`,`in_progress`,`completed`,`cancelled`],type:`string`}},required:[`content`,`status`,`priority`],type:`object`},type:`array`}},type:`object`},logicalPath:`ash:framework/todo`,name:`todo`,onCompact(
|
|
3
|
+
`),execute:async e=>executeTodoTool(e??{}),inputSchema:{additionalProperties:!1,properties:{todos:{description:`The updated todo list. Omit to read the current list without modifying it.`,items:{additionalProperties:!1,properties:{content:{description:`Brief description of the task.`,type:`string`},priority:{description:`Priority level of the task.`,enum:[`high`,`medium`,`low`],type:`string`},status:{description:`Current status of the task.`,enum:[`pending`,`in_progress`,`completed`,`cancelled`],type:`string`}},required:[`content`,`status`,`priority`],type:`object`},type:`array`}},type:`object`},logicalPath:`ash:framework/todo`,name:`todo`,onCompact(){let t=loadContext().get(TodoStateKey);if(t===void 0||t.items.length===0)return{};let r=formatTodoSummary(t);return r===void 0?{}:{messages:[{content:r,role:`user`}]}},sourceId:`ash:todo-tool`,sourceKind:`module`};export{TODO_TOOL_DEFINITION,TodoStateKey,executeTodoTool};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{executeWriteFileOnSandbox}from"#execution/sandbox/write-file-tool.js";const WRITE_FILE_INPUT_SCHEMA={additionalProperties:!1,properties:{content:{description:`Complete replacement file contents.`,type:`string`},filePath:{description:`The absolute path to the file to write (must be absolute, not relative).`,type:`string`}},required:[`filePath`,`content`],type:`object`};async function executeWriteFile(e){return executeWriteFileOnSandbox(e)}const WRITE_FILE_TOOL_DEFINITION={description:[`Writes a file to the local filesystem.`,``,`Usage:`,`- This tool will overwrite the existing file if there is one at the provided path.`,`- If this is an existing file, you MUST use the read_file tool first to read the file's contents. This tool will fail if you did not read the file first.`,`- ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.`,`- NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.`,`- Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked.`].join(`
|
|
1
|
+
import{requireSandboxSession}from"#execution/sandbox/require-sandbox.js";import{executeWriteFileOnSandbox}from"#execution/sandbox/write-file-tool.js";const WRITE_FILE_INPUT_SCHEMA={additionalProperties:!1,properties:{content:{description:`Complete replacement file contents.`,type:`string`},filePath:{description:`The absolute path to the file to write (must be absolute, not relative).`,type:`string`}},required:[`filePath`,`content`],type:`object`};async function executeWriteFile(e){return executeWriteFileOnSandbox(await requireSandboxSession(),e)}const WRITE_FILE_TOOL_DEFINITION={description:[`Writes a file to the local filesystem.`,``,`Usage:`,`- This tool will overwrite the existing file if there is one at the provided path.`,`- If this is an existing file, you MUST use the read_file tool first to read the file's contents. This tool will fail if you did not read the file first.`,`- ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.`,`- NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.`,`- Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked.`].join(`
|
|
2
2
|
`),execute:executeWriteFile,inputSchema:WRITE_FILE_INPUT_SCHEMA,logicalPath:`ash:framework/write-file`,name:`write_file`,sourceId:`ash:write-file-tool`,sourceKind:`module`};export{WRITE_FILE_INPUT_SCHEMA,WRITE_FILE_TOOL_DEFINITION};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z}from"#compiled/zod/index.js";import{createRemoteJWKSet,jwtVerify}from"#compiled/jose/index.js";import{areTokenClaimMatchersSatisfied,createJwtAuthenticatedCallerPrincipal}from"#runtime/governance/auth/token-claims.js";const oidcDiscoveryDocumentSchema=z.object({issuer:z.string().optional(),jwks_uri:z.string().url()}).passthrough(),oidcDiscoveryDocumentCache=new Map,oidcJwksCache=new Map;async function authenticateOidcStrategy(e){let t;try{t=await getOidcRemoteJwks(e.strategy)}catch(e){return{kind:`misconfigured`,message:`Failed to load OIDC discovery metadata. ${e instanceof Error?e.message:`Unknown discovery failure.`}`}}try{let a=await jwtVerify(e.token,t,{audience:[...e.strategy.audiences],clockTolerance:e.strategy.clockSkewSeconds,issuer:e.strategy.issuer});if(typeof a.payload.sub!=`string`||a.payload.sub.length===0)return{kind:`not-authenticated`};let o=e.strategy.acceptCurrentVercelProject&&
|
|
1
|
+
import{z}from"#compiled/zod/index.js";import{createRemoteJWKSet,jwtVerify}from"#compiled/jose/index.js";import{areTokenClaimMatchersSatisfied,createJwtAuthenticatedCallerPrincipal}from"#runtime/governance/auth/token-claims.js";const oidcDiscoveryDocumentSchema=z.object({issuer:z.string().optional(),jwks_uri:z.string().url()}).passthrough(),oidcDiscoveryDocumentCache=new Map,oidcJwksCache=new Map;async function authenticateOidcStrategy(e){let t;try{t=await getOidcRemoteJwks(e.strategy)}catch(e){return{kind:`misconfigured`,message:`Failed to load OIDC discovery metadata. ${e instanceof Error?e.message:`Unknown discovery failure.`}`}}try{let a=await jwtVerify(e.token,t,{audience:[...e.strategy.audiences],clockTolerance:e.strategy.clockSkewSeconds,issuer:e.strategy.issuer});if(e.strategy.acceptCurrentVercelProject&&e.strategy.issuer.startsWith(`https://oidc.vercel.com/`)&&a.payload.external_sub!==void 0)return typeof a.payload.external_sub!=`string`||a.payload.external_sub.length===0||!satisfiesCurrentVercelProjectConstraint({payload:a.payload})||!satisfiesCurrentVercelEnvironmentConstraint({payload:a.payload})?{kind:`caller-not-allowed`}:{kind:`authenticated`,principal:createJwtAuthenticatedCallerPrincipal({authenticator:`oidc`,issuerClaims:[`external_iss`,`connector_id`],payload:a.payload,principalType:`user`,subjectClaim:`external_sub`})};if(typeof a.payload.sub!=`string`||a.payload.sub.length===0)return{kind:`not-authenticated`};let o=e.strategy.acceptCurrentVercelProject&&isCurrentVercelProjectToken({issuer:e.strategy.issuer,payload:a.payload}),s=o&&isCurrentVercelEnvironmentToken({payload:a.payload});return!o&&!areTokenClaimMatchersSatisfied(a.payload,e.strategy)?{kind:`caller-not-allowed`}:{kind:`authenticated`,principal:createJwtAuthenticatedCallerPrincipal({authenticator:`oidc`,payload:a.payload,principalType:s?`runtime`:`service`})}}catch{return{kind:`not-authenticated`}}}async function getOidcRemoteJwks(e){let n=await getOidcDiscoveryDocument(e.discoveryUrl),r=oidcJwksCache.get(n.jwks_uri);if(r!==void 0)return r;let i=createRemoteJWKSet(new URL(n.jwks_uri));return oidcJwksCache.set(n.jwks_uri,i),i}async function getOidcDiscoveryDocument(e){let t=oidcDiscoveryDocumentCache.get(e);if(t!==void 0)return await t;let n=fetch(e,{headers:{accept:`application/json`}}).then(async e=>{if(!e.ok)throw Error(`Discovery route returned HTTP ${e.status}.`);return oidcDiscoveryDocumentSchema.parse(await e.json())}).catch(t=>{throw oidcDiscoveryDocumentCache.delete(e),t});return oidcDiscoveryDocumentCache.set(e,n),await n}function isCurrentVercelProjectToken(e){if(!e.issuer.startsWith(`https://oidc.vercel.com`))return!1;let t=process.env.VERCEL_PROJECT_ID?.trim();return t===void 0||t.length===0?!1:typeof e.payload.project_id==`string`&&e.payload.project_id===t}function satisfiesCurrentVercelProjectConstraint(e){let t=process.env.VERCEL_PROJECT_ID?.trim();return t===void 0||t.length===0?!0:typeof e.payload.project_id==`string`&&e.payload.project_id===t}function isCurrentVercelEnvironmentToken(e){let t=getCurrentVercelEnvironment();return t===void 0||t.length===0?!1:typeof e.payload.environment==`string`&&e.payload.environment===t}function satisfiesCurrentVercelEnvironmentConstraint(e){let t=getCurrentVercelEnvironment();return t===void 0||t.length===0?!0:typeof e.payload.environment==`string`&&e.payload.environment===t}function getCurrentVercelEnvironment(){return process.env.VERCEL_TARGET_ENV?.trim()||process.env.VERCEL_ENV?.trim()||void 0}export{authenticateOidcStrategy};
|
|
@@ -10,6 +10,8 @@ export declare function areTokenClaimMatchersSatisfied(payload: JWTPayload, matc
|
|
|
10
10
|
*/
|
|
11
11
|
export declare function createJwtAuthenticatedCallerPrincipal(input: {
|
|
12
12
|
readonly authenticator: AuthenticatedCallerPrincipal["authenticator"];
|
|
13
|
+
readonly issuerClaims?: readonly string[];
|
|
13
14
|
readonly payload: JWTPayload;
|
|
14
15
|
readonly principalType: AuthenticatedCallerPrincipal["principalType"];
|
|
16
|
+
readonly subjectClaim?: string;
|
|
15
17
|
}): AuthenticatedCallerPrincipal;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const STANDARD_PROJECTED_CLAIM_KEYS=new Set([`aud`,`exp`,`iat`,`iss`,`jti`,`nbf`,`sub`]);function normalizeJwtClaims(e){let t={};for(let[n,r]of Object.entries(e)){if(typeof r==`string`){t[n]=r;continue}Array.isArray(r)&&r.every(e=>typeof e==`string`)&&(t[n]=Object.freeze([...r]))}return Object.freeze(t)}function createJwtAttributeProjection(t){let n=normalizeJwtClaims(t);return Object.freeze(Object.fromEntries(Object.entries(n).filter(([t])=>!STANDARD_PROJECTED_CLAIM_KEYS.has(t))))}function areTokenClaimMatchersSatisfied(e,t){let n=normalizeJwtClaims(e);if(t.subjects!==void 0){let n=typeof e.sub==`string`?e.sub:null;if(n===null||!t.subjects.some(e=>matchesWildcardPattern(e,n)))return!1}return t.claims===void 0?!0:Object.entries(t.claims).every(([e,t])=>{let r=n[e];return r===void 0?!1:typeof r==`string`?t.includes(r):r.some(e=>t.includes(e))})}function createJwtAuthenticatedCallerPrincipal(e){let t=
|
|
1
|
+
const STANDARD_PROJECTED_CLAIM_KEYS=new Set([`aud`,`exp`,`iat`,`iss`,`jti`,`nbf`,`sub`]);function normalizeJwtClaims(e){let t={};for(let[n,r]of Object.entries(e)){if(typeof r==`string`){t[n]=r;continue}Array.isArray(r)&&r.every(e=>typeof e==`string`)&&(t[n]=Object.freeze([...r]))}return Object.freeze(t)}function createJwtAttributeProjection(t){let n=normalizeJwtClaims(t);return Object.freeze(Object.fromEntries(Object.entries(n).filter(([t])=>!STANDARD_PROJECTED_CLAIM_KEYS.has(t))))}function areTokenClaimMatchersSatisfied(e,t){let n=normalizeJwtClaims(e);if(t.subjects!==void 0){let n=typeof e.sub==`string`?e.sub:null;if(n===null||!t.subjects.some(e=>matchesWildcardPattern(e,n)))return!1}return t.claims===void 0?!0:Object.entries(t.claims).every(([e,t])=>{let r=n[e];return r===void 0?!1:typeof r==`string`?t.includes(r):r.some(e=>t.includes(e))})}function createJwtAuthenticatedCallerPrincipal(e){let t=readFirstStringClaim(e.payload,[...e.issuerClaims??[],`iss`]),n=e.subjectClaim??`sub`,r=readFirstStringClaim(e.payload,[n]);if(t===void 0||r===void 0)throw Error(`Expected verified JWT payloads to include string iss and ${n} claims.`);let i=normalizeJwtClaims(e.payload);return{attributes:createJwtAttributeProjection(e.payload),authenticator:e.authenticator,claims:i,issuer:t,principalId:`${t}:${r}`,principalType:e.principalType,subject:r}}function readFirstStringClaim(e,t){for(let n of t){let t=e[n];if(typeof t==`string`&&t.length>0)return t}}function matchesWildcardPattern(e,t){if(!e.includes(`*`))return e===t;let n=e.replaceAll(/[.+?^${}()|[\]\\]/g,`\\$&`).replaceAll(`*`,`.*`);return RegExp(`^${n}$`).test(t)}export{areTokenClaimMatchersSatisfied,createJwtAuthenticatedCallerPrincipal};
|
|
@@ -67,6 +67,12 @@ export interface ResolvedOidcAuthStrategy extends ResolvedTokenClaimMatchers {
|
|
|
67
67
|
* `principalType: "runtime"`; other current-project tokens are
|
|
68
68
|
* tagged `"service"`.
|
|
69
69
|
*
|
|
70
|
+
* Vercel OIDC tokens with an `external_sub` claim are user tokens.
|
|
71
|
+
* They must satisfy the current project/environment constraints when
|
|
72
|
+
* those environment variables are configured, and then authenticate as
|
|
73
|
+
* `principalType: "user"` with `external_sub` as their subject and
|
|
74
|
+
* `external_iss` / `connector_id` as their issuer when present.
|
|
75
|
+
*
|
|
70
76
|
* Set exclusively by `verifyVercelOidc`. The generic public
|
|
71
77
|
* `verifyOidc` always passes `false`.
|
|
72
78
|
*/
|
|
@@ -7,7 +7,7 @@ import type { ChannelMethod, RouteContext } from "#public/definitions/channel.js
|
|
|
7
7
|
import type { RouteHandler } from "#channel/routes.js";
|
|
8
8
|
import type { OutboundAuthFn } from "#public/agents/auth.js";
|
|
9
9
|
import type { LifecycleHooks, StreamEventHook } from "#public/definitions/hook.js";
|
|
10
|
-
import type {
|
|
10
|
+
import type { CompactionInput, CompactionHookResult, NeedsApprovalContext, ToolModelOutput, ToolRetentionPolicy } from "#public/definitions/tool.js";
|
|
11
11
|
import type { AuthorizationDefinition, HeadersDefinition, ToolFilterDefinition } from "#runtime/connections/types.js";
|
|
12
12
|
import type { CompiledWorkspaceResourceRoot } from "#compiler/manifest.js";
|
|
13
13
|
import type { WorkspaceRuntimeSpec } from "#runtime/workspace/types.js";
|
|
@@ -137,7 +137,7 @@ export type ResolvedToolDefinition = Readonly<Optional<InternalToolDefinitionWit
|
|
|
137
137
|
* resolved tool that declares it after the harness compacts message
|
|
138
138
|
* history. See `packages/ash/src/execution/tool-compaction.ts`.
|
|
139
139
|
*/
|
|
140
|
-
readonly onCompact?: (input:
|
|
140
|
+
readonly onCompact?: (input: CompactionInput, ctx: unknown) => CompactionHookResult | Promise<CompactionHookResult> | void | Promise<void>;
|
|
141
141
|
/**
|
|
142
142
|
* Optional projection that controls what the model sees as the tool
|
|
143
143
|
* result. The full `execute` return is still visible to channel event
|
|
@@ -19,11 +19,6 @@ export type SandboxSpawnOptions = Parameters<AiSdkSandbox["spawn"]>[0];
|
|
|
19
19
|
* Mirrors the AI SDK `Experimental_SandboxProcess` type.
|
|
20
20
|
*/
|
|
21
21
|
export type SandboxProcess = Awaited<ReturnType<AiSdkSandbox["spawn"]>>;
|
|
22
|
-
/**
|
|
23
|
-
* @deprecated Use {@link SandboxRunOptions} instead. Kept as an alias
|
|
24
|
-
* for source compatibility; will be removed in a future release.
|
|
25
|
-
*/
|
|
26
|
-
export type SandboxRunCommandOptions = SandboxRunOptions;
|
|
27
22
|
/**
|
|
28
23
|
* Options for reading one file as a stream of bytes.
|
|
29
24
|
*/
|
|
@@ -67,8 +62,6 @@ export type SandboxWriteTextFileOptions = Parameters<AiSdkSandbox["writeTextFile
|
|
|
67
62
|
* Relative paths resolve from `/workspace`, the live working directory
|
|
68
63
|
* for every backend. Absolute paths pass through unchanged.
|
|
69
64
|
*
|
|
70
|
-
* `runCommand` is preserved as a deprecated alias for `run`. It emits a
|
|
71
|
-
* one-time warning per session when called.
|
|
72
65
|
*/
|
|
73
66
|
export interface SandboxSession extends Pick<AiSdkSandbox, "run" | "spawn" | "readFile" | "readBinaryFile" | "readTextFile" | "writeFile" | "writeBinaryFile" | "writeTextFile"> {
|
|
74
67
|
/**
|
|
@@ -90,16 +83,6 @@ export interface SandboxSession extends Pick<AiSdkSandbox, "run" | "spawn" | "re
|
|
|
90
83
|
* The read and write methods already apply this internally.
|
|
91
84
|
*/
|
|
92
85
|
resolvePath(path: string): string;
|
|
93
|
-
/**
|
|
94
|
-
* @deprecated Use {@link SandboxSession.run} instead. This alias wraps
|
|
95
|
-
* `run` and emits a one-time deprecation warning per session on call.
|
|
96
|
-
*
|
|
97
|
-
* Marked optional on the public type so authored code that constructs
|
|
98
|
-
* its own session-like fixtures isn't forced to mock the deprecated
|
|
99
|
-
* path. Runtime sessions built through `buildSandboxSession` always
|
|
100
|
-
* provide it.
|
|
101
|
-
*/
|
|
102
|
-
runCommand?: AiSdkSandbox["run"];
|
|
103
86
|
}
|
|
104
87
|
/**
|
|
105
88
|
* Internal sandbox session, used to construct the public {@link SandboxSession}.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "experimental-ash",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.0",
|
|
4
4
|
"bin": {
|
|
5
5
|
"ash": "./bin/ash.js",
|
|
6
6
|
"experimental-ash": "./bin/ash.js"
|
|
@@ -172,7 +172,7 @@
|
|
|
172
172
|
"access": "public"
|
|
173
173
|
},
|
|
174
174
|
"dependencies": {
|
|
175
|
-
"experimental-ai-sdk-code-mode": "1.0.
|
|
175
|
+
"experimental-ai-sdk-code-mode": "1.0.10",
|
|
176
176
|
"nitro": "3.0.260522-beta",
|
|
177
177
|
"quickjs-emscripten": "0.32.0"
|
|
178
178
|
},
|
|
@@ -190,7 +190,7 @@
|
|
|
190
190
|
"@types/react": "19.2.15",
|
|
191
191
|
"@types/react-test-renderer": "19.1.0",
|
|
192
192
|
"@vercel/oidc": "3.4.1",
|
|
193
|
-
"@vercel/sandbox": "2.0.
|
|
193
|
+
"@vercel/sandbox": "2.0.1",
|
|
194
194
|
"@workflow/core": "5.0.0-beta.7",
|
|
195
195
|
"@workflow/errors": "5.0.0-beta.4",
|
|
196
196
|
"@workflow/world-local": "5.0.0-beta.6",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{CodeModeAbortedError,CodeModeBridgeLimitError,CodeModeConcurrencyError,CodeModeDetachedBridgeRequestError,CodeModeProtocolError,CodeModeTimeoutError,CodeModeToolApprovalDeniedError,deserializeError,serializeBridgeErrorForGuest,serializeError}from"../errors.js";import{assertCodeModeApprovalResponse}from"../approval-response.js";import{signCodeModeContinuation,verifyCodeModeContinuation}from"../continuation-capability.js";import{executeHostFetch}from"../fetch-policy.js";import{normalizeOptions}from"../options.js";import{toJsonPayload}from"../serialization.js";import{assertSourceSize,transformSource}from"../source-cache.js";import{addTelemetryEvent,endTelemetrySpan,recordTelemetryError,startTelemetrySpan}from"../telemetry.js";import{invokeHostTool}from"../tool-invocation.js";import{getMaxWorkers}from"./max-workers.js";import{INLINE_CODE_MODE_WORKER_SOURCE}from"./worker-source.js";import{randomBytes}from"node:crypto";import{Worker}from"node:worker_threads";let activeInvocations=0,invocationCounter=0;const idleWorkers=[];function getCodeModeWorkerUrl(){return getDefaultCodeModeWorkerUrl()}function getDefaultCodeModeWorkerUrl(){return new URL(`./worker.js`,import.meta.url)}async function runManagedCodeMode(t){let r=normalizeOptions(t.options),i=getMaxWorkers({memoryLimitBytes:r.memoryLimitBytes,activeWorkers:activeInvocations});if(activeInvocations>=i)throw new CodeModeConcurrencyError(i);activeInvocations++;let a=!0;try{if(t.toolExecutionOptions?.abortSignal?.aborted)throw new CodeModeAbortedError;assertSourceSize(t.js,r.maxSourceBytes);let n=transformSource(t.js);assertContinuationInput({js:n,continuation:t.continuation,approvalResponse:t.approvalResponse,interruptResolution:t.interruptResolution});let o=startWorkerRun({...t,js:n,normalizedOptions:r,maxWorkers:i});return a=!1,o.accountingDone.then(()=>releaseInvocationSlot(r.memoryLimitBytes),()=>releaseInvocationSlot(r.memoryLimitBytes)),await o.result}finally{a&&releaseInvocationSlot(r.memoryLimitBytes)}}function assertContinuationInput({js:e,continuation:t,approvalResponse:n,interruptResolution:r}){if(n!==void 0&&assertCodeModeApprovalResponse(n),n!==void 0&&r!==void 0)throw new CodeModeProtocolError(`A code-mode continuation cannot be resumed with both an approval response and a generic interrupt resolution.`,{approvalId:n.approvalId,interruptId:r.interruptId});if(t===void 0){if(n!==void 0||r!==void 0)throw new CodeModeProtocolError(`A code-mode continuation response was provided without continuation state.`,{hasApprovalResponse:n!==void 0,hasInterruptResolution:r!==void 0});return}if(verifyCodeModeContinuation(t),t.version!==1)throw new CodeModeProtocolError(`Unsupported code-mode continuation version.`,{version:t.version});if(t.js!==e)throw new CodeModeProtocolError(`Code mode continuation source does not match the resumed source.`,{continuationSourceBytes:byteLength(t.js),resumedSourceBytes:byteLength(e)});if(typeof t.outerToolCallId!=`string`)throw new CodeModeProtocolError(`Code mode continuation outerToolCallId must be a string.`,{outerToolCallId:t.outerToolCallId});if(assertDeterminismState(t.determinism),assertContinuationLedgerShape(t),n!==void 0){let e=t.ledger.filter(e=>e.kind===`tool`&&e.status===`approval-required`&&e.approvalId===n.approvalId);if(e.length!==1)throw new CodeModeProtocolError(`Approval response does not match exactly one pending continuation ledger entry.`,{approvalId:n.approvalId,matches:e.length})}if(r!==void 0){let e=t.ledger.filter(e=>e.kind===`tool`&&e.status===`interrupted`&&e.interruptId===r.interruptId);if(e.length!==1)throw new CodeModeProtocolError(`Interrupt resolution does not match exactly one pending continuation ledger entry.`,{interruptId:r.interruptId,matches:e.length})}}function startWorkerRun({js:n,tools:s,toolExecutionOptions:u,options:f,continuation:m,approvalResponse:g,interruptResolution:_,normalizedOptions:v,maxWorkers:y}){let b=`code-mode-${++invocationCounter}`,x=acquireWorker(y),S=x.worker,C=u?.abortSignal,w=new AbortController,T=getMaxNestedToolCounter(m?.ledger??[]),E,D=!1,O=!1,k=!1,A=!1,j=0,M=0,N,P=new Set,F=cloneLedger(m?.ledger??[]),I=m?.determinism??createDeterminismState(),L=u?.context??u?.experimental_context,R=u?.experimental_context??u?.context,z={toolCallId:u?.toolCallId??m?.outerToolCallId??b,messages:u?.messages??[],abortSignal:w.signal,...R===void 0?{}:{experimental_context:R},...L===void 0?{}:{context:L}},B=Date.now(),V={invocationId:b,outerToolCallId:z.toolCallId,status:`completed`,startedAtMs:B,completedAtMs:B,durationMs:0,bridgeRequests:[]},H=!1,U=startTelemetrySpan(f?.telemetry,`ai.code_mode.execute`,{"code_mode.invocation.id":b,"code_mode.outer_tool_call.id":z.toolCallId,"code_mode.continuation":m!==void 0,"code_mode.fetch.enabled":v.fetchEnabled,"code_mode.max_workers":y,...f?.telemetry?.recordInputs===!1?{}:{"code_mode.source.bytes":byteLength(n)}}),emitNestedToolCall=async e=>{await emitLifecycleHook(`onNestedToolCall`,e)},emitNestedToolResult=async e=>{await emitLifecycleHook(`onNestedToolResult`,e)},emitInterrupt=async e=>{await emitLifecycleHook(`onInterrupt`,{invocationId:b,outerToolCallId:z.toolCallId,interrupt:e})},emitLifecycleHook=async(e,t)=>{let n=f?.lifecycle,r=n?.[e];if(r!==void 0)try{await r(t)}catch(r){try{await n?.onHookError?.(r,{hook:e,event:t})}catch{}}},emitFetchRequest=async e=>{await emitLifecycleHook(`onFetchRequest`,e)},emitFetchResult=async e=>{await emitLifecycleHook(`onFetchResult`,e)},emitTrace=async e=>{await emitLifecycleHook(`onTrace`,e)},W,finishTrace=(e,t={})=>{if(H)return W??Promise.resolve();H=!0;let n=Date.now();return V.status=e,V.completedAtMs=n,V.durationMs=Math.max(0,n-V.startedAtMs),t.interruptedBy!==void 0&&(V.interruptedBy=t.interruptedBy,addTelemetryEvent(U,`code_mode.interrupt`,{"code_mode.interrupt.type":t.interruptedBy})),t.error!==void 0&&(V.error=serializeError(t.error),recordTelemetryError(U,t.error)),U?.setAttributes?.({"code_mode.status":e,"code_mode.duration_ms":V.durationMs,"code_mode.bridge_requests.count":V.bridgeRequests.length,"code_mode.bridge_requests.replayed_count":V.bridgeRequests.filter(e=>e.replayed).length}),endTelemetrySpan(U),W=emitTrace(cloneTrace(V)),W},makeToolCallEvent=({bridgeIndex:e,toolName:t,input:n,inputJson:r,toolCallId:i,replayed:a,startedAtMs:o})=>({invocationId:b,outerToolCallId:z.toolCallId,bridgeIndex:e,toolName:t,input:n,inputBytes:byteLength(r),toolCallId:i,replayed:a,startedAtMs:o}),pushToolTrace=e=>{let t={kind:`tool`,bridgeIndex:e.bridgeIndex,toolName:e.toolName,toolCallId:e.toolCallId,status:e.status,replayed:e.replayed,startedAtMs:e.startedAtMs,completedAtMs:e.completedAtMs,durationMs:e.durationMs,inputBytes:e.inputBytes,...e.status===`fulfilled`?{outputBytes:e.outputBytes}:{},...e.status===`rejected`?{error:toTraceError(e.error)}:{},...e.status===`interrupted`?{interruptType:e.interrupt.type}:{}};return V.bridgeRequests.push(t),t},makeFetchRequestEvent=({bridgeIndex:e,inputJson:t,request:n,replayed:r,startedAtMs:i})=>({invocationId:b,outerToolCallId:z.toolCallId,bridgeIndex:e,url:n.url,method:n.method??`GET`,inputBytes:byteLength(t),replayed:r,startedAtMs:i}),pushFetchTrace=e=>{let t={kind:`fetch`,bridgeIndex:e.bridgeIndex,url:e.url,method:e.method,status:e.status,replayed:e.replayed,startedAtMs:e.startedAtMs,completedAtMs:e.completedAtMs,durationMs:e.durationMs,inputBytes:e.inputBytes,...e.status===`fulfilled`?{outputBytes:e.outputBytes}:{},...e.status===`rejected`?{error:toTraceError(e.error)}:{}};return V.bridgeRequests.push(t),t},finishToolEvent=async e=>{pushToolTrace(e),addTelemetryEvent(U,`code_mode.nested_tool.result`,{"code_mode.bridge.index":e.bridgeIndex,"code_mode.tool.name":e.toolName,"code_mode.tool_call.id":e.toolCallId,"code_mode.status":e.status,"code_mode.replayed":e.replayed,...e.status===`fulfilled`&&f?.telemetry?.recordOutputs!==!1?{"code_mode.tool.output.bytes":e.outputBytes}:{}}),await emitNestedToolResult(e)},finishFetchEvent=async e=>{pushFetchTrace(e),addTelemetryEvent(U,`code_mode.fetch.result`,{"code_mode.bridge.index":e.bridgeIndex,"code_mode.fetch.url":e.url,"code_mode.fetch.method":e.method,"code_mode.status":e.status,"code_mode.replayed":e.replayed,...e.status===`fulfilled`&&f?.telemetry?.recordOutputs!==!1?{"code_mode.fetch.output.bytes":e.outputBytes}:{}}),await emitFetchResult(e)},startNestedToolSpan=e=>startTelemetrySpan(f?.telemetry,`ai.code_mode.nested_tool`,{"code_mode.invocation.id":b,"code_mode.outer_tool_call.id":z.toolCallId,"code_mode.bridge.index":e.bridgeIndex,"code_mode.tool.name":e.toolName,"code_mode.tool_call.id":e.toolCallId,"code_mode.replayed":e.replayed,...f?.telemetry?.recordInputs===!1?{}:{"code_mode.tool.input.bytes":e.inputBytes}}),startFetchSpan=e=>startTelemetrySpan(f?.telemetry,`ai.code_mode.fetch`,{"code_mode.invocation.id":b,"code_mode.outer_tool_call.id":z.toolCallId,"code_mode.bridge.index":e.bridgeIndex,"code_mode.fetch.url":e.url,"code_mode.fetch.method":e.method,"code_mode.replayed":e.replayed,...f?.telemetry?.recordInputs===!1?{}:{"code_mode.fetch.input.bytes":e.inputBytes}}),G,K,q=new Promise((e,t)=>{G=e,K=t}),J,Y=new Promise(e=>{J=e}),abortInvocation=e=>{w.signal.aborted||w.abort(e)},cleanupWorker=e=>{A||(A=!0,clearTimeout(X),C?.removeEventListener(`abort`,onAbort),S.off(`message`,onMessage),S.off(`error`,onError),S.off(`exit`,onExit),e?releaseWorker(x):destroyWorker(x))},settleAccountingIfDone=()=>{!O&&D&&M===0&&(O=!0,J())},settleCaller=e=>{if(!D){D=!0,settleAccountingIfDone();try{e()}catch(e){K(e)}finally{settleAccountingIfDone()}}},failTerminal=e=>{k||(k=!0,abortInvocation(e),cleanupWorker(!1),(async()=>{await finishTrace(`failed`,{error:e}),settleCaller(()=>K(e))})())},onAbort=()=>{failTerminal(new CodeModeAbortedError)},X=setTimeout(()=>{failTerminal(new CodeModeTimeoutError(v.timeoutMs))},v.timeoutMs),onMessage=e=>{if(e.invocationId!==b){failTerminal(new CodeModeProtocolError(`Worker message invocationId mismatch: expected ${b}, received ${e.invocationId}.`,{expectedInvocationId:b,receivedInvocationId:e.invocationId,messageType:e.type}));return}if(e.type===`result`){if(E!==void 0){failTerminal(new CodeModeProtocolError(`Worker sent duplicate result for invocation ${b}.`,{invocationId:b}));return}E=e;return}if(e.type===`ready`){handleReadyMessage(e);return}if(e.type===`tool-request`){let t=markWorkerRequest(e);t!==void 0&&handleToolRequest(e,t);return}if(e.type===`fetch-request`){let t=markWorkerRequest(e);t!==void 0&&handleFetchRequest(e,t)}},onError=e=>{failTerminal(e)},onExit=e=>{!k&&e!==0&&failTerminal(Error(`Code mode worker exited with code ${e}.`))};S.on(`message`,onMessage),S.on(`error`,onError),S.on(`exit`,onExit),C?.addEventListener(`abort`,onAbort,{once:!0}),C?.aborted&&onAbort();let Z={type:`run`,invocationId:b,js:n,determinism:I,options:{timeoutMs:v.timeoutMs,memoryLimitBytes:v.memoryLimitBytes,maxStackSizeBytes:v.maxStackSizeBytes,maxResultBytes:v.maxResultBytes,fetchEnabled:v.fetchEnabled}};if(!k)try{S.postMessage(Z)}catch(e){failTerminal(e)}return{result:q,accountingDone:Y};async function handleToolRequest(e,t){let n=F[t-1],r=fromJsonPayload(e.inputJson);try{if(n!==void 0){if(assertReplayEntryMatches(n,{kind:`tool`,name:e.toolName,inputJson:e.inputJson}),n.kind!==`tool`)throw new CodeModeProtocolError(`Continuation replay expected a tool ledger entry.`,{invocationId:b,bridgeIndex:t,kind:n.kind});if(n.status===`fulfilled`){let i=Date.now(),a=makeToolCallEvent({bridgeIndex:t,toolName:e.toolName,input:r,inputJson:e.inputJson,toolCallId:n.toolCallId,replayed:!0,startedAtMs:i});await emitNestedToolCall(a);let o=Date.now();await finishToolEvent({...a,status:`fulfilled`,completedAtMs:o,durationMs:o-i,outputBytes:byteLength(n.valueJson),output:fromJsonPayload(n.valueJson)}),postBridgeResponse({type:`bridge-response`,invocationId:b,requestId:e.requestId,success:!0,dateNowMs:n.dateNowMs,valueJson:n.valueJson});return}if(n.status===`rejected`){let i=Date.now(),a=makeToolCallEvent({bridgeIndex:t,toolName:e.toolName,input:r,inputJson:e.inputJson,toolCallId:n.toolCallId,replayed:!0,startedAtMs:i});await emitNestedToolCall(a);let o=Date.now();await finishToolEvent({...a,status:`rejected`,completedAtMs:o,durationMs:o-i,error:n.error}),postBridgeResponse({type:`bridge-response`,invocationId:b,requestId:e.requestId,success:!1,dateNowMs:n.dateNowMs,error:n.error});return}if(n.status===`approval-required`){if(g?.approvalId===n.approvalId&&g.approved===!0){let a=Date.now(),o=makeToolCallEvent({bridgeIndex:t,toolName:e.toolName,input:r,inputJson:e.inputJson,toolCallId:n.toolCallId,replayed:!1,startedAtMs:a});await emitNestedToolCall(o);let c=startNestedToolSpan(o),l=await invokeHostTool({toolName:e.toolName,inputJson:e.inputJson,tools:s,baseExecutionOptions:z,codeModeOptions:f??{},maxToolInputBytes:v.maxToolInputBytes,maxToolOutputBytes:v.maxToolOutputBytes,toolCallId:n.toolCallId,skipApproval:!0}).catch(e=>{throw recordTelemetryError(c,e),e}).finally(()=>endTelemetrySpan(c));if(l.type===`approval-required`)throw new CodeModeProtocolError(`Approved continuation for ${e.toolName} requested approval again.`,{invocationId:b,requestId:e.requestId,toolName:e.toolName,approvalId:n.approvalId});if(l.type===`interrupted`){let r=`${n.toolCallId}:interrupt`;F[t-1]={kind:`tool`,name:e.toolName,inputJson:e.inputJson,toolCallId:n.toolCallId,interruptId:r,interruptPayload:l.payload,status:`interrupted`},requestInterrupt(t-1);return}let u=Date.now();F[t-1]={kind:`tool`,name:e.toolName,inputJson:e.inputJson,toolCallId:n.toolCallId,status:`fulfilled`,dateNowMs:u,valueJson:l.valueJson},await finishToolEvent({...o,status:`fulfilled`,completedAtMs:u,durationMs:u-a,outputBytes:byteLength(l.valueJson),output:fromJsonPayload(l.valueJson)}),postBridgeResponse({type:`bridge-response`,invocationId:b,requestId:e.requestId,success:!0,dateNowMs:u,valueJson:l.valueJson});return}if(g?.approvalId===n.approvalId&&g.approved===!1){let i=new CodeModeToolApprovalDeniedError(n.name,n.approvalInput,n.toolCallId,g.reason),a=serializeError(i),s=serializeBridgeErrorForGuest(i,`tool`),u=Date.now();F[t-1]={kind:`tool`,name:e.toolName,inputJson:e.inputJson,toolCallId:n.toolCallId,status:`rejected`,dateNowMs:u,error:s},await finishToolEvent({invocationId:b,outerToolCallId:z.toolCallId,bridgeIndex:t,toolName:e.toolName,input:r,inputBytes:byteLength(e.inputJson),toolCallId:n.toolCallId,replayed:!1,startedAtMs:u,status:`rejected`,completedAtMs:u,durationMs:0,error:a}),postBridgeResponse({type:`bridge-response`,invocationId:b,requestId:e.requestId,success:!1,dateNowMs:u,error:s});return}requestInterrupt(t-1);return}if(n.status===`interrupted`){if(_?.interruptId===n.interruptId){let i={interruptId:n.interruptId,payload:n.interruptPayload,resolution:_.resolution},a=Date.now(),o=makeToolCallEvent({bridgeIndex:t,toolName:e.toolName,input:r,inputJson:e.inputJson,toolCallId:n.toolCallId,replayed:!1,startedAtMs:a});await emitNestedToolCall(o);let c=startNestedToolSpan(o),l=await invokeHostTool({toolName:e.toolName,inputJson:e.inputJson,tools:s,baseExecutionOptions:z,codeModeOptions:f??{},maxToolInputBytes:v.maxToolInputBytes,maxToolOutputBytes:v.maxToolOutputBytes,toolCallId:n.toolCallId,codeModeInterrupt:i,skipApproval:!0}).catch(e=>{throw recordTelemetryError(c,e),e}).finally(()=>endTelemetrySpan(c));if(l.type===`approval-required`){F[t-1]={kind:`tool`,name:e.toolName,inputJson:e.inputJson,toolCallId:n.toolCallId,approvalId:createApprovalId(n.toolCallId),approvalInput:l.input,status:`approval-required`},requestInterrupt(t-1);return}if(l.type===`interrupted`){F[t-1]={kind:`tool`,name:e.toolName,inputJson:e.inputJson,toolCallId:n.toolCallId,interruptId:`${n.toolCallId}:interrupt`,interruptPayload:l.payload,status:`interrupted`},requestInterrupt(t-1);return}let u=Date.now();F[t-1]={kind:`tool`,name:e.toolName,inputJson:e.inputJson,toolCallId:n.toolCallId,status:`fulfilled`,dateNowMs:u,valueJson:l.valueJson},await finishToolEvent({...o,status:`fulfilled`,completedAtMs:u,durationMs:u-a,outputBytes:byteLength(l.valueJson),output:fromJsonPayload(l.valueJson)}),postBridgeResponse({type:`bridge-response`,invocationId:b,requestId:e.requestId,success:!0,dateNowMs:u,valueJson:l.valueJson});return}if(_!==void 0&&_.interruptId!==n.interruptId)throw new CodeModeProtocolError(`Interrupt resolution ${_.interruptId} does not match pending code-mode interrupt ${n.interruptId}.`,{expectedInterruptId:n.interruptId,receivedInterruptId:_.interruptId});requestInterrupt(t-1);return}return}let a=`${z.toolCallId}:tool-${++T}`,u=Date.now(),d=makeToolCallEvent({bridgeIndex:t,toolName:e.toolName,input:r,inputJson:e.inputJson,toolCallId:a,replayed:!1,startedAtMs:u});await emitNestedToolCall(d);let p=startNestedToolSpan(d),m=await invokeHostTool({toolName:e.toolName,inputJson:e.inputJson,tools:s,baseExecutionOptions:z,codeModeOptions:f??{},maxToolInputBytes:v.maxToolInputBytes,maxToolOutputBytes:v.maxToolOutputBytes,toolCallId:a}).catch(e=>{throw recordTelemetryError(p,e),e}).finally(()=>endTelemetrySpan(p));if(m.type===`approval-required`){F[t-1]={kind:`tool`,name:e.toolName,inputJson:e.inputJson,toolCallId:a,approvalId:createApprovalId(a),approvalInput:m.input,status:`approval-required`},requestInterrupt(t-1);return}if(m.type===`interrupted`){F[t-1]={kind:`tool`,name:e.toolName,inputJson:e.inputJson,toolCallId:a,interruptId:`${a}:interrupt`,interruptPayload:m.payload,status:`interrupted`},requestInterrupt(t-1);return}let h=Date.now();F[t-1]={kind:`tool`,name:e.toolName,inputJson:e.inputJson,toolCallId:a,status:`fulfilled`,dateNowMs:h,valueJson:m.valueJson},await finishToolEvent({...d,status:`fulfilled`,completedAtMs:h,durationMs:h-u,outputBytes:byteLength(m.valueJson),output:fromJsonPayload(m.valueJson)}),postBridgeResponse({type:`bridge-response`,invocationId:b,requestId:e.requestId,success:!0,dateNowMs:h,valueJson:m.valueJson})}catch(a){if(a instanceof CodeModeProtocolError){failTerminal(a);return}let o=serializeError(a),s=serializeBridgeErrorForGuest(a,`tool`),u=Date.now(),d=n?.kind===`tool`?n.toolCallId:`${z.toolCallId}:tool-${T}`;n?.kind===`tool`&&(n.status===`approval-required`||n.status===`interrupted`)&&(n.status===`approval-required`&&g?.approvalId===n.approvalId&&g.approved===!0||n.status===`interrupted`&&_?.interruptId===n.interruptId)?F[t-1]={kind:`tool`,name:e.toolName,inputJson:e.inputJson,toolCallId:n.toolCallId,status:`rejected`,dateNowMs:u,error:s}:n===void 0&&(F[t-1]={kind:`tool`,name:e.toolName,inputJson:e.inputJson,toolCallId:d,status:`rejected`,dateNowMs:u,error:s}),await finishToolEvent({invocationId:b,outerToolCallId:z.toolCallId,bridgeIndex:t,toolName:e.toolName,input:r,inputBytes:byteLength(e.inputJson),toolCallId:d,replayed:!1,startedAtMs:u,status:`rejected`,completedAtMs:u,durationMs:0,error:o}),postBridgeResponse({type:`bridge-response`,invocationId:b,requestId:e.requestId,success:!1,dateNowMs:u,error:s})}finally{M--,settleInterruptIfReady(),settleAccountingIfDone()}}async function handleFetchRequest(e,t){let n=JSON.stringify(e.request),r=F[t-1];try{if(r!==void 0){if(assertReplayEntryMatches(r,{kind:`fetch`,name:e.request.url,inputJson:n}),r.kind!==`fetch`)throw new CodeModeProtocolError(`Continuation replay expected a fetch ledger entry.`,{invocationId:b,bridgeIndex:t,kind:r.kind});if(r.status===`fulfilled`){let i=Date.now(),a=makeFetchRequestEvent({bridgeIndex:t,inputJson:n,request:e.request,replayed:!0,startedAtMs:i});await emitFetchRequest(a);let o=Date.now();await finishFetchEvent({...a,status:`fulfilled`,completedAtMs:o,durationMs:o-i,outputBytes:byteLength(r.valueJson)}),postBridgeResponse({type:`bridge-response`,invocationId:b,requestId:e.requestId,success:!0,dateNowMs:r.dateNowMs,valueJson:r.valueJson});return}if(r.status===`rejected`){let i=Date.now(),a=makeFetchRequestEvent({bridgeIndex:t,inputJson:n,request:e.request,replayed:!0,startedAtMs:i});await emitFetchRequest(a);let o=Date.now();await finishFetchEvent({...a,status:`rejected`,completedAtMs:o,durationMs:o-i,error:r.error}),postBridgeResponse({type:`bridge-response`,invocationId:b,requestId:e.requestId,success:!1,dateNowMs:r.dateNowMs,error:r.error});return}throw new CodeModeProtocolError(`Continuation ledger entry for fetch cannot be interrupted.`,{invocationId:b,requestId:e.requestId})}let a=Date.now(),o=makeFetchRequestEvent({bridgeIndex:t,inputJson:n,request:e.request,replayed:!1,startedAtMs:a});await emitFetchRequest(o);let s=startFetchSpan(o),c=toJsonPayload(await executeHostFetch({request:e.request,fetch:v.fetch,policy:v.fetchPolicy,signal:w.signal}).catch(e=>{throw recordTelemetryError(s,e),e}).finally(()=>endTelemetrySpan(s)),v.maxResultBytes,`fetch response`),l=Date.now();F[t-1]={kind:`fetch`,name:e.request.url,inputJson:n,status:`fulfilled`,dateNowMs:l,valueJson:c},await finishFetchEvent({...o,status:`fulfilled`,completedAtMs:l,durationMs:l-a,outputBytes:byteLength(c)}),postBridgeResponse({type:`bridge-response`,invocationId:b,requestId:e.requestId,success:!0,dateNowMs:l,valueJson:c})}catch(a){if(a instanceof CodeModeProtocolError){failTerminal(a);return}let o=serializeError(a),s=serializeBridgeErrorForGuest(a,`fetch`),u=Date.now();r===void 0&&(F[t-1]={kind:`fetch`,name:e.request.url,inputJson:n,status:`rejected`,dateNowMs:u,error:s}),await finishFetchEvent({invocationId:b,outerToolCallId:z.toolCallId,bridgeIndex:t,url:e.request.url,method:e.request.method??`GET`,inputBytes:byteLength(n),replayed:!1,startedAtMs:u,status:`rejected`,completedAtMs:u,durationMs:0,error:o}),postBridgeResponse({type:`bridge-response`,invocationId:b,requestId:e.requestId,success:!1,dateNowMs:u,error:s})}finally{M--,settleInterruptIfReady(),settleAccountingIfDone()}}function markWorkerRequest(e){if(!k&&N===void 0){if(E!==void 0){failTerminal(new CodeModeProtocolError(`Worker sent ${e.type} after result for invocation ${b}.`,{invocationId:b,requestId:e.requestId,messageType:e.type}));return}if(P.has(e.requestId)){failTerminal(new CodeModeProtocolError(`Worker reused requestId ${e.requestId} for invocation ${b}.`,{invocationId:b,requestId:e.requestId,messageType:e.type}));return}if(P.add(e.requestId),j>=v.maxBridgeRequests){let n=new CodeModeBridgeLimitError(`Code mode exceeded the maxBridgeRequests limit (${v.maxBridgeRequests}).`,{invocationId:b,requestId:e.requestId,maxBridgeRequests:v.maxBridgeRequests});postBridgeResponse({type:`bridge-response`,invocationId:b,requestId:e.requestId,success:!1,dateNowMs:Date.now(),error:serializeBridgeErrorForGuest(n,`bridge`)});return}if(M>=v.maxInFlightBridgeRequests){let n=new CodeModeBridgeLimitError(`Code mode exceeded the maxInFlightBridgeRequests limit (${v.maxInFlightBridgeRequests}).`,{invocationId:b,requestId:e.requestId,maxInFlightBridgeRequests:v.maxInFlightBridgeRequests});postBridgeResponse({type:`bridge-response`,invocationId:b,requestId:e.requestId,success:!1,dateNowMs:Date.now(),error:serializeBridgeErrorForGuest(n,`bridge`)});return}return j++,M++,j}}function postBridgeResponse(e){if(!(k||A))try{S.postMessage(e)}catch(e){failTerminal(e)}}function requestInterrupt(e){N??=e}function settleInterruptIfReady(){if(N===void 0||k||M>0)return;let e=N,t=F[e];if(t===void 0||t.kind!==`tool`){failTerminal(new CodeModeProtocolError(`Code mode interruption references a missing tool ledger entry.`,{invocationId:b,interruptEntryIndex:N}));return}if(t.status!==`approval-required`&&t.status!==`interrupted`){failTerminal(new CodeModeProtocolError(`Code mode interruption references a non-pending ledger entry.`,{invocationId:b,interruptEntryIndex:N,status:t.status}));return}let r=signCodeModeContinuation({version:1,js:n,outerToolCallId:z.toolCallId,determinism:{...I},ledger:cloneLedger(F)}),a=t.status===`approval-required`?createApprovalInterrupt(t,r):createGenericInterrupt(t,r);k=!0,abortInvocation(a),cleanupWorker(!1),(async()=>{let n=Date.now(),r=makeToolCallEvent({bridgeIndex:e+1,toolName:t.name,input:fromJsonPayload(t.inputJson),inputJson:t.inputJson,toolCallId:t.toolCallId,replayed:!1,startedAtMs:n});t.status===`interrupted`?await finishToolEvent({...r,status:`interrupted`,completedAtMs:n,durationMs:0,interrupt:a}):await finishToolEvent({...r,status:`approval-required`,completedAtMs:n,durationMs:0,approvalId:t.approvalId}),await emitInterrupt(a),await finishTrace(`interrupted`,{interruptedBy:a.type}),settleCaller(()=>G(a))})()}function createApprovalInterrupt(e,t){return{type:`code-mode-approval-required`,approvalId:e.approvalId,toolCallId:e.toolCallId,toolName:e.name,input:e.approvalInput,continuation:t}}function createGenericInterrupt(e,t){let n={type:`code-mode-interrupt`,interruptId:e.interruptId,kind:e.interruptPayload.kind,toolCallId:e.toolCallId,toolName:e.name,input:fromJsonPayload(e.inputJson),payload:structuredClone(e.interruptPayload)},r={type:`code-mode-pending-continuation`,version:1,outerToolCallId:t.outerToolCallId,interruptId:e.interruptId,requestMessages:[],continuation:t,interrupt:n};return{...n,pendingContinuation:r}}async function handleReadyMessage(e){if(k)return;if(N!==void 0){settleInterruptIfReady();return}if(E===void 0){failTerminal(new CodeModeProtocolError(`Code mode worker became ready without a result for ${e.invocationId}.`,{invocationId:e.invocationId}));return}let t=E;if(t.invocationId!==e.invocationId){failTerminal(new CodeModeProtocolError(`Worker result/ready invocationId mismatch: result was ${t.invocationId}, ready was ${e.invocationId}.`,{resultInvocationId:t.invocationId,readyInvocationId:e.invocationId}));return}if(k=!0,M>0){let e=t.success?new CodeModeDetachedBridgeRequestError(`Code mode returned while ${M} bridge request(s) were still in flight.`,{invocationId:b,inFlightBridgeRequests:M,totalBridgeRequests:j}):deserializeResultError(t);abortInvocation(e),cleanupWorker(!1),await finishTrace(`failed`,{error:e}),settleCaller(()=>K(e));return}if(m!==void 0&&j<F.length){let e=new CodeModeProtocolError(`Code mode continuation returned before replaying the full bridge ledger.`,{invocationId:b,replayedBridgeRequests:j,ledgerEntries:F.length,nextLedgerEntry:F[j]});abortInvocation(e),cleanupWorker(!1),await finishTrace(`failed`,{error:e}),settleCaller(()=>K(e));return}t.success?await finishTrace(`completed`):await finishTrace(`failed`,{error:deserializeResultError(t)}),cleanupWorker(!0),settleCaller(()=>settleWithResultMessage(t,G,K))}}function acquireWorker(e){let t=idleWorkers.pop();for(;t?.destroyed;)t=idleWorkers.pop();return t??=createWorker(),t.worker.removeAllListeners(`exit`),t.worker.ref(),trimIdleWorkers(Math.max(0,e-activeInvocations)),t}function createWorker(){return{worker:new Worker(getInlineWorkerSource(),{eval:!0}),destroyed:!1}}function getInlineWorkerSource(){return INLINE_CODE_MODE_WORKER_SOURCE.replace(`__CODE_MODE_REQUIRE_BASE_URL__`,JSON.stringify(import.meta.url))}function releaseWorker(e){e.destroyed||(e.worker.once(`exit`,()=>{e.destroyed=!0;let t=idleWorkers.indexOf(e);t!==-1&&idleWorkers.splice(t,1)}),e.worker.unref(),idleWorkers.push(e))}function destroyWorker(e){e.destroyed||(e.destroyed=!0,e.worker.removeAllListeners(),e.worker.terminate())}function trimIdleWorkers(e){for(;idleWorkers.length>e;){let e=idleWorkers.pop();e!==void 0&&destroyWorker(e)}}function releaseInvocationSlot(e){activeInvocations=Math.max(0,activeInvocations-1);let t=getMaxWorkers({memoryLimitBytes:e,activeWorkers:activeInvocations});trimIdleWorkers(Math.max(0,t-activeInvocations))}function deserializeResultError(e){return deserializeError(e.error??{name:`Error`,message:`Unknown worker error.`})}function settleWithResultMessage(e,t,n){if(!e.success){n(deserializeResultError(e));return}t(e.valueJson===``||e.valueJson===void 0?void 0:JSON.parse(e.valueJson))}function fromJsonPayload(e){return e===``?void 0:JSON.parse(e)}function cloneLedger(e){return e.map(e=>{switch(e.status){case`fulfilled`:return{...e};case`rejected`:return{...e,error:{...e.error}};case`approval-required`:return{...e,approvalInput:structuredClone(e.approvalInput)};case`interrupted`:return{...e,interruptPayload:structuredClone(e.interruptPayload)};default:return e}})}function assertReplayEntryMatches(e,t){if(e.kind!==t.kind||e.name!==t.name||e.inputJson!==t.inputJson)throw new CodeModeProtocolError(`Code mode continuation replay diverged from the recorded bridge ledger.`,{expected:{kind:e.kind,name:e.name,inputJson:e.inputJson},received:t})}function assertDeterminismState(e){if(!Number.isFinite(e.dateNowMs)||!Number.isInteger(e.dateNowMs))throw new CodeModeProtocolError(`Code mode continuation determinism dateNowMs must be an integer.`,{dateNowMs:e.dateNowMs});if(!/^[0-9a-f]{32}$/i.test(e.randomSeed))throw new CodeModeProtocolError(`Code mode continuation determinism randomSeed must be a 128-bit hex string.`,{randomSeed:e.randomSeed})}function assertContinuationLedgerShape(e){let t=new Set;for(let[n,r]of e.ledger.entries()){if(r.kind!==`tool`&&r.kind!==`fetch`)throw new CodeModeProtocolError(`Code mode continuation ledger entry has an unknown kind.`,{index:n,kind:r.kind});if(typeof r.name!=`string`)throw new CodeModeProtocolError(`Code mode continuation ledger entry name must be a string.`,{index:n,name:r.name});if(assertJsonPayload(r.inputJson,`ledger[${n}].inputJson`),r.kind===`fetch`){if(r.status===`fulfilled`){assertFiniteDateNow(r.dateNowMs,n),assertJsonPayload(r.valueJson,`ledger[${n}].valueJson`);continue}if(r.status===`rejected`){assertFiniteDateNow(r.dateNowMs,n),assertSerializableError(r.error,n);continue}throw new CodeModeProtocolError(`Fetch continuation ledger entry cannot be pending.`,{index:n,status:r.status})}if(typeof r.toolCallId!=`string`||!r.toolCallId.startsWith(`${e.outerToolCallId}:tool-`))throw new CodeModeProtocolError(`Tool continuation ledger entry has an unexpected toolCallId.`,{index:n,toolCallId:r.toolCallId,outerToolCallId:e.outerToolCallId});if(t.has(r.toolCallId))throw new CodeModeProtocolError(`Tool continuation ledger contains a duplicate toolCallId.`,{index:n,toolCallId:r.toolCallId});switch(t.add(r.toolCallId),r.status){case`fulfilled`:assertFiniteDateNow(r.dateNowMs,n),assertJsonPayload(r.valueJson,`ledger[${n}].valueJson`);break;case`rejected`:assertFiniteDateNow(r.dateNowMs,n),assertSerializableError(r.error,n);break;case`approval-required`:if(typeof r.approvalId!=`string`||!r.approvalId.startsWith(`${r.toolCallId}:approval-`))throw new CodeModeProtocolError(`Approval continuation ledger entry has an unexpected approvalId.`,{index:n,toolCallId:r.toolCallId,approvalId:r.approvalId});break;case`interrupted`:if(r.interruptId!==`${r.toolCallId}:interrupt`)throw new CodeModeProtocolError(`Generic interruption ledger entry has an unexpected interruptId.`,{index:n,toolCallId:r.toolCallId,interruptId:r.interruptId});if(typeof r.interruptPayload!=`object`||r.interruptPayload===null||Array.isArray(r.interruptPayload)||typeof r.interruptPayload.kind!=`string`||r.interruptPayload.kind.length===0)throw new CodeModeProtocolError(`Generic interruption ledger entry payload must include a string kind.`,{index:n,interruptPayload:r.interruptPayload});break;default:throw new CodeModeProtocolError(`Tool continuation ledger entry has an unknown status.`,{index:n,status:r.status})}}}function assertJsonPayload(e,t){if(typeof e!=`string`)throw new CodeModeProtocolError(`${t} must be a string.`,{value:e});if(e!==``)try{JSON.parse(e)}catch(e){throw new CodeModeProtocolError(`${t} must be valid JSON.`,{cause:e instanceof Error?e.message:String(e)})}}function assertFiniteDateNow(e,t){if(!Number.isFinite(e)||!Number.isInteger(e))throw new CodeModeProtocolError(`Continuation ledger dateNowMs must be an integer.`,{index:t,dateNowMs:e})}function assertSerializableError(e,t){let n=e;if(typeof e!=`object`||!e||Array.isArray(e)||typeof n.name!=`string`||typeof n.message!=`string`)throw new CodeModeProtocolError(`Rejected continuation ledger entry has an invalid serialized error.`,{index:t,error:e})}function getMaxNestedToolCounter(e){let t=0;for(let n of e){if(n.kind!==`tool`)continue;let e=/:tool-(\d+)$/.exec(n.toolCallId);e&&(t=Math.max(t,Number(e[1])))}return t}function createDeterminismState(){return{dateNowMs:Date.now(),randomSeed:randomBytes(16).toString(`hex`)}}function createApprovalId(e){return`${e}:approval-${randomBytes(16).toString(`hex`)}`}function byteLength(e){return new TextEncoder().encode(e).byteLength}function toTraceError(e){return isSerializableError(e)?{name:e.name,message:e.message,...e.stack===void 0?{}:{stack:e.stack},...e.code===void 0?{}:{code:e.code},...e.details===void 0?{}:{details:e.details}}:serializeError(e)}function isSerializableError(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=e;return typeof t.name==`string`&&typeof t.message==`string`&&(t.stack===void 0||typeof t.stack==`string`)&&(t.code===void 0||typeof t.code==`string`)}function cloneTrace(e){return{...e,bridgeRequests:e.bridgeRequests.map(e=>({...e,...e.error===void 0?{}:{error:{...e.error}}})),...e.error===void 0?{}:{error:{...e.error}}}}export{getCodeModeWorkerUrl,getDefaultCodeModeWorkerUrl,runManagedCodeMode};
|