experimental-ash 0.55.3 → 0.57.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.
Files changed (144) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/LICENSE +202 -0
  3. package/dist/docs/internals/compiler-and-artifacts.md +1 -1
  4. package/dist/docs/internals/context.md +3 -3
  5. package/dist/docs/public/advanced/typescript-api.md +19 -0
  6. package/dist/docs/public/advanced/vercel-deployment.md +2 -1
  7. package/dist/docs/public/channels/github.md +145 -0
  8. package/dist/docs/public/channels/index.md +23 -2
  9. package/dist/docs/public/meta.json +1 -0
  10. package/dist/docs/public/onboarding.md +7 -5
  11. package/dist/docs/public/sandbox.md +18 -3
  12. package/dist/docs/public/subagents.mdx +7 -2
  13. package/dist/docs/public/tools.mdx +10 -2
  14. package/dist/skills/agent/SKILL.md +169 -0
  15. package/dist/skills/agent/references/deployment.md +35 -0
  16. package/dist/skills/agent/references/getting-started.md +58 -0
  17. package/dist/skills/agent/references/project-layout.md +35 -0
  18. package/dist/skills/agent/references/runtime-model.md +24 -0
  19. package/dist/skills/agent/references/skills.md +26 -0
  20. package/dist/skills/agent/scripts/add-to-existing-project.sh +12 -0
  21. package/dist/skills/agent/scripts/bootstrap-from-npm.sh +9 -0
  22. package/dist/skills/agent/scripts/verify-local-agent.sh +16 -0
  23. package/dist/skills/ash-add-agent/SKILL.md +166 -0
  24. package/dist/skills/ash-add-next/SKILL.md +137 -0
  25. package/dist/skills/framework/SKILL.md +93 -0
  26. package/dist/skills/framework/references/architecture.md +14 -0
  27. package/dist/skills/framework/references/discovery-and-compilation.md +15 -0
  28. package/dist/skills/framework/references/quality-gates.md +13 -0
  29. package/dist/skills/framework/references/runtime-model.md +12 -0
  30. package/dist/skills/framework/references/workspace-and-sandbox.md +25 -0
  31. package/dist/skills/framework/scripts/framework-review-checklist.sh +13 -0
  32. package/dist/skills/framework/scripts/run-framework-gates.sh +8 -0
  33. package/dist/src/client/output-schema.js +1 -1
  34. package/dist/src/compiler/compile-from-memory.d.ts +2 -0
  35. package/dist/src/compiler/compile-from-memory.js +1 -1
  36. package/dist/src/compiler/manifest.d.ts +10 -2
  37. package/dist/src/compiler/manifest.js +1 -1
  38. package/dist/src/compiler/normalize-agent-config.js +1 -1
  39. package/dist/src/compiler/normalize-sandbox.js +1 -1
  40. package/dist/src/compiler/normalize-subagent.js +1 -1
  41. package/dist/src/compiler/normalize-tool.js +1 -1
  42. package/dist/src/context/build-dynamic-tools.js +1 -1
  43. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  44. package/dist/src/context/keys.d.ts +1 -0
  45. package/dist/src/execution/node-step.js +1 -1
  46. package/dist/src/execution/remote-agent-dispatch.js +1 -1
  47. package/dist/src/execution/session.js +1 -1
  48. package/dist/src/execution/subagent-tool.js +1 -1
  49. package/dist/src/execution/workflow-entry.js +1 -1
  50. package/dist/src/harness/code-mode.js +1 -1
  51. package/dist/src/harness/execute-tool.d.ts +1 -0
  52. package/dist/src/harness/provider-tools.d.ts +7 -1
  53. package/dist/src/harness/provider-tools.js +1 -1
  54. package/dist/src/harness/tool-loop.js +1 -1
  55. package/dist/src/harness/tools.d.ts +2 -0
  56. package/dist/src/harness/tools.js +1 -1
  57. package/dist/src/internal/application/package.js +1 -1
  58. package/dist/src/internal/authored-definition/sandbox.d.ts +2 -1
  59. package/dist/src/internal/authored-definition/sandbox.js +1 -1
  60. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  61. package/dist/src/packages/ash-scaffold/src/channels.js +2 -2
  62. package/dist/src/packages/ash-scaffold/src/steps/run-add-to-agent.js +1 -1
  63. package/dist/src/packages/ash-scaffold/src/web-template.js +2 -2
  64. package/dist/src/public/channels/github/api.d.ts +166 -0
  65. package/dist/src/public/channels/github/api.js +1 -0
  66. package/dist/src/public/channels/github/auth.d.ts +83 -0
  67. package/dist/src/public/channels/github/auth.js +2 -0
  68. package/dist/src/public/channels/github/binding.d.ts +49 -0
  69. package/dist/src/public/channels/github/binding.js +1 -0
  70. package/dist/src/public/channels/github/checkout.d.ts +48 -0
  71. package/dist/src/public/channels/github/checkout.js +1 -0
  72. package/dist/src/public/channels/github/constants.d.ts +2 -0
  73. package/dist/src/public/channels/github/constants.js +1 -0
  74. package/dist/src/public/channels/github/defaults.d.ts +21 -0
  75. package/dist/src/public/channels/github/defaults.js +3 -0
  76. package/dist/src/public/channels/github/dispatch.d.ts +34 -0
  77. package/dist/src/public/channels/github/dispatch.js +1 -0
  78. package/dist/src/public/channels/github/githubChannel.d.ts +109 -0
  79. package/dist/src/public/channels/github/githubChannel.js +1 -0
  80. package/dist/src/public/channels/github/inbound.d.ts +183 -0
  81. package/dist/src/public/channels/github/inbound.js +2 -0
  82. package/dist/src/public/channels/github/index.d.ts +9 -0
  83. package/dist/src/public/channels/github/index.js +1 -0
  84. package/dist/src/public/channels/github/limits.d.ts +4 -0
  85. package/dist/src/public/channels/github/limits.js +2 -0
  86. package/dist/src/public/channels/github/pr-context.d.ts +45 -0
  87. package/dist/src/public/channels/github/pr-context.js +5 -0
  88. package/dist/src/public/channels/github/state.d.ts +48 -0
  89. package/dist/src/public/channels/github/state.js +1 -0
  90. package/dist/src/public/channels/github/verify.d.ts +35 -0
  91. package/dist/src/public/channels/github/verify.js +1 -0
  92. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  93. package/dist/src/public/definitions/sandbox.d.ts +3 -3
  94. package/dist/src/public/definitions/tool.d.ts +21 -1
  95. package/dist/src/public/sandbox/index.d.ts +1 -1
  96. package/dist/src/public/tools/define-bash-tool.js +1 -1
  97. package/dist/src/public/tools/define-glob-tool.js +1 -1
  98. package/dist/src/public/tools/define-grep-tool.js +1 -1
  99. package/dist/src/public/tools/define-read-file-tool.js +1 -1
  100. package/dist/src/public/tools/define-write-file-tool.js +1 -1
  101. package/dist/src/public/tools/internal.js +1 -1
  102. package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
  103. package/dist/src/runtime/connections/authorization-tokens.d.ts +8 -0
  104. package/dist/src/runtime/connections/authorization-tokens.js +1 -1
  105. package/dist/src/runtime/connections/mcp-client.d.ts +14 -0
  106. package/dist/src/runtime/connections/mcp-client.js +1 -1
  107. package/dist/src/runtime/connections/types.d.ts +1 -0
  108. package/dist/src/runtime/framework-tools/ask-question.d.ts +4 -0
  109. package/dist/src/runtime/framework-tools/ask-question.js +1 -1
  110. package/dist/src/runtime/framework-tools/bash.d.ts +5 -0
  111. package/dist/src/runtime/framework-tools/bash.js +1 -1
  112. package/dist/src/runtime/framework-tools/connection-search-dynamic.d.ts +1 -0
  113. package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -1
  114. package/dist/src/runtime/framework-tools/final-output.js +1 -1
  115. package/dist/src/runtime/framework-tools/glob.d.ts +5 -0
  116. package/dist/src/runtime/framework-tools/glob.js +2 -2
  117. package/dist/src/runtime/framework-tools/grep.d.ts +5 -0
  118. package/dist/src/runtime/framework-tools/grep.js +2 -2
  119. package/dist/src/runtime/framework-tools/read-file.d.ts +5 -0
  120. package/dist/src/runtime/framework-tools/read-file.js +2 -2
  121. package/dist/src/runtime/framework-tools/skill.d.ts +2 -0
  122. package/dist/src/runtime/framework-tools/skill.js +1 -1
  123. package/dist/src/runtime/framework-tools/todo.d.ts +2 -0
  124. package/dist/src/runtime/framework-tools/todo.js +2 -2
  125. package/dist/src/runtime/framework-tools/web-fetch.d.ts +3 -0
  126. package/dist/src/runtime/framework-tools/web-fetch.js +2 -2
  127. package/dist/src/runtime/framework-tools/web-search.d.ts +17 -0
  128. package/dist/src/runtime/framework-tools/web-search.js +1 -1
  129. package/dist/src/runtime/framework-tools/write-file.d.ts +5 -0
  130. package/dist/src/runtime/framework-tools/write-file.js +2 -2
  131. package/dist/src/runtime/resolve-sandbox.js +1 -1
  132. package/dist/src/runtime/resolve-tool.js +1 -1
  133. package/dist/src/runtime/sandbox/keys.js +1 -1
  134. package/dist/src/runtime/sandbox/template-plan.d.ts +5 -0
  135. package/dist/src/runtime/sandbox/template-plan.js +1 -1
  136. package/dist/src/runtime/subagents/registry.js +1 -1
  137. package/dist/src/runtime/tools/registry.js +1 -1
  138. package/dist/src/runtime/types.d.ts +11 -2
  139. package/dist/src/shared/dynamic-tool-definition.d.ts +2 -1
  140. package/dist/src/shared/json-schema.d.ts +3 -1
  141. package/dist/src/shared/json-schema.js +1 -1
  142. package/dist/src/shared/sandbox-definition.d.ts +22 -2
  143. package/dist/src/shared/tool-definition.d.ts +10 -2
  144. package/package.json +25 -1
@@ -1,2 +1,2 @@
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
+ 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`},READ_FILE_OUTPUT_SCHEMA={additionalProperties:!1,properties:{content:{type:`string`},nextOffset:{minimum:1,type:`integer`},path:{type:`string`},totalLines:{minimum:0,type:`integer`},truncated:{type:`boolean`}},required:[`content`,`path`,`totalLines`,`truncated`],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(),{}},outputSchema:READ_FILE_OUTPUT_SCHEMA,sourceId:`ash:read-file-tool`,sourceKind:`module`};export{READ_FILE_INPUT_SCHEMA,READ_FILE_OUTPUT_SCHEMA,READ_FILE_TOOL_DEFINITION};
@@ -1,2 +1,4 @@
1
1
  import type { ResolvedToolDefinition } from "#runtime/types.js";
2
+ import type { JsonObject } from "#shared/json.js";
3
+ export declare const SKILL_OUTPUT_SCHEMA: JsonObject;
2
4
  export declare const SKILL_TOOL_DEFINITION: ResolvedToolDefinition;
@@ -1 +1 @@
1
- import{SandboxKey}from"#context/keys.js";import{loadContext}from"#context/container.js";import{loadSkillFromSandbox}from"#runtime/skills/sandbox-access.js";async function executeLoadSkillTool(t){let n=loadContext().get(SandboxKey);if(n===void 0)throw Error(`The load_skill tool requires sandbox access on the runtime context. Ensure the step is running inside a managed runtime context with sandbox support.`);let{skill:r}=t;return await loadSkillFromSandbox(n,r)}const SKILL_TOOL_DEFINITION={description:[`Load the full instructions for one available skill by name or id.`,`Use this tool when the request clearly matches a listed skill description or when the user explicitly asks for that skill.`,`Loading adds the skill instructions to the current turn.`,`Choose the "skill" value from the Available skills block.`].join(` `),execute:e=>executeLoadSkillTool(e),inputSchema:{additionalProperties:!1,properties:{skill:{description:`Available skill name or id.`,type:`string`}},required:[`skill`],type:`object`},logicalPath:`ash:framework/load-skill`,name:`load_skill`,sourceId:`ash:load-skill-tool`,sourceKind:`module`};export{SKILL_TOOL_DEFINITION};
1
+ import{SandboxKey}from"#context/keys.js";import{loadContext}from"#context/container.js";import{loadSkillFromSandbox}from"#runtime/skills/sandbox-access.js";async function executeLoadSkillTool(t){let n=loadContext().get(SandboxKey);if(n===void 0)throw Error(`The load_skill tool requires sandbox access on the runtime context. Ensure the step is running inside a managed runtime context with sandbox support.`);let{skill:r}=t;return await loadSkillFromSandbox(n,r)}const SKILL_OUTPUT_SCHEMA={type:`string`},SKILL_TOOL_DEFINITION={description:[`Load the full instructions for one available skill by name or id.`,`Use this tool when the request clearly matches a listed skill description or when the user explicitly asks for that skill.`,`Loading adds the skill instructions to the current turn.`,`Choose the "skill" value from the Available skills block.`].join(` `),execute:e=>executeLoadSkillTool(e),inputSchema:{additionalProperties:!1,properties:{skill:{description:`Available skill name or id.`,type:`string`}},required:[`skill`],type:`object`},logicalPath:`ash:framework/load-skill`,name:`load_skill`,outputSchema:SKILL_OUTPUT_SCHEMA,sourceId:`ash:load-skill-tool`,sourceKind:`module`};export{SKILL_OUTPUT_SCHEMA,SKILL_TOOL_DEFINITION};
@@ -1,5 +1,6 @@
1
1
  import { ContextKey } from "#context/key.js";
2
2
  import type { ResolvedToolDefinition } from "#runtime/types.js";
3
+ import type { JsonObject } from "#shared/json.js";
3
4
  /**
4
5
  * Single item in the todo list.
5
6
  */
@@ -34,4 +35,5 @@ export interface TodoToolInput {
34
35
  * the full current state.
35
36
  */
36
37
  export declare function executeTodoTool(input: TodoToolInput): unknown;
38
+ export declare const TODO_OUTPUT_SCHEMA: JsonObject;
37
39
  export declare const TODO_TOOL_DEFINITION: ResolvedToolDefinition;
@@ -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
- `)}`}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(){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};
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_ITEM_SCHEMA={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`},TODO_OUTPUT_SCHEMA={additionalProperties:!1,properties:{counts:{additionalProperties:!1,properties:{cancelled:{minimum:0,type:`integer`},completed:{minimum:0,type:`integer`},in_progress:{minimum:0,type:`integer`},pending:{minimum:0,type:`integer`},total:{minimum:0,type:`integer`}},required:[`cancelled`,`completed`,`in_progress`,`pending`,`total`],type:`object`},todos:{items:TODO_ITEM_SCHEMA,type:`array`}},required:[`counts`,`todos`],type:`object`},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:TODO_ITEM_SCHEMA,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`}]}},outputSchema:TODO_OUTPUT_SCHEMA,sourceId:`ash:todo-tool`,sourceKind:`module`};export{TODO_OUTPUT_SCHEMA,TODO_TOOL_DEFINITION,TodoStateKey,executeTodoTool};
@@ -1,2 +1,5 @@
1
1
  import type { ResolvedToolDefinition } from "#runtime/types.js";
2
+ import type { JsonObject } from "#shared/json.js";
3
+ export declare const WEB_FETCH_INPUT_SCHEMA: JsonObject;
4
+ export declare const WEB_FETCH_OUTPUT_SCHEMA: JsonObject;
2
5
  export declare const WEB_FETCH_TOOL_DEFINITION: ResolvedToolDefinition;
@@ -1,2 +1,2 @@
1
- import{executeWebFetchTool}from"#execution/web-fetch/tool.js";async function executeWebFetch(e){return executeWebFetchTool(e)}const WEB_FETCH_TOOL_DEFINITION={description:[`Fetch a webpage and return its content in the requested format. Use this to retrieve and analyze content from URLs.`,``,`Usage notes:`,`- The URL must be a fully-formed valid URL starting with http:// or https://`,`- HTML responses are automatically converted to markdown or plain text based on the requested format`,`- Format options: "markdown" (default), "text", or "html"`,`- Default timeout is 30 seconds (max 120 seconds)`,`- Maximum response size is 5 MB; content is further capped at the shared tool-output budget (50 KB / 2000 lines)`,`- This tool is read-only and does not modify any files`].join(`
2
- `),execute:executeWebFetch,inputSchema:{additionalProperties:!1,properties:{format:{description:`The format to return the content in (text, markdown, or html). HTML responses are automatically converted to the requested format. Defaults to "markdown".`,enum:[`markdown`,`text`,`html`],type:`string`},timeout:{description:`Optional timeout in seconds. Defaults to 30, max 120.`,type:`number`},url:{description:`The fully-formed URL to fetch content from. Must start with http:// or https://.`,type:`string`}},required:[`url`],type:`object`},logicalPath:`ash:framework/web-fetch`,name:`web_fetch`,sourceId:`ash:web-fetch-tool`,sourceKind:`module`};export{WEB_FETCH_TOOL_DEFINITION};
1
+ import{executeWebFetchTool}from"#execution/web-fetch/tool.js";async function executeWebFetch(e){return executeWebFetchTool(e)}const WEB_FETCH_INPUT_SCHEMA={additionalProperties:!1,properties:{format:{description:`The format to return the content in (text, markdown, or html). HTML responses are automatically converted to the requested format. Defaults to "markdown".`,enum:[`markdown`,`text`,`html`],type:`string`},timeout:{description:`Optional timeout in seconds. Defaults to 30, max 120.`,type:`number`},url:{description:`The fully-formed URL to fetch content from. Must start with http:// or https://.`,type:`string`}},required:[`url`],type:`object`},WEB_FETCH_OUTPUT_SCHEMA={additionalProperties:!1,properties:{content:{type:`string`},contentType:{type:`string`},truncated:{type:`boolean`},url:{type:`string`}},required:[`content`,`contentType`,`url`,`truncated`],type:`object`},WEB_FETCH_TOOL_DEFINITION={description:[`Fetch a webpage and return its content in the requested format. Use this to retrieve and analyze content from URLs.`,``,`Usage notes:`,`- The URL must be a fully-formed valid URL starting with http:// or https://`,`- HTML responses are automatically converted to markdown or plain text based on the requested format`,`- Format options: "markdown" (default), "text", or "html"`,`- Default timeout is 30 seconds (max 120 seconds)`,`- Maximum response size is 5 MB; content is further capped at the shared tool-output budget (50 KB / 2000 lines)`,`- This tool is read-only and does not modify any files`].join(`
2
+ `),execute:executeWebFetch,inputSchema:WEB_FETCH_INPUT_SCHEMA,logicalPath:`ash:framework/web-fetch`,name:`web_fetch`,outputSchema:WEB_FETCH_OUTPUT_SCHEMA,sourceId:`ash:web-fetch-tool`,sourceKind:`module`};export{WEB_FETCH_INPUT_SCHEMA,WEB_FETCH_OUTPUT_SCHEMA,WEB_FETCH_TOOL_DEFINITION};
@@ -1,4 +1,21 @@
1
1
  import type { ResolvedToolDefinition } from "#runtime/types.js";
2
+ import type { JsonObject } from "#shared/json.js";
3
+ /**
4
+ * Output schema for OpenAI's provider-managed `webSearch` tool.
5
+ */
6
+ export declare const WEB_SEARCH_OPENAI_OUTPUT_SCHEMA: JsonObject;
7
+ /**
8
+ * Output schema for Anthropic's stable provider-managed `webSearch_20250305` tool.
9
+ */
10
+ export declare const WEB_SEARCH_ANTHROPIC_OUTPUT_SCHEMA: JsonObject;
11
+ /**
12
+ * Output schema for Google's provider-managed `googleSearch` grounding tool.
13
+ */
14
+ export declare const WEB_SEARCH_GOOGLE_OUTPUT_SCHEMA: JsonObject;
15
+ /**
16
+ * Output schema for AI Gateway's provider-managed `perplexitySearch` tool.
17
+ */
18
+ export declare const WEB_SEARCH_GATEWAY_OUTPUT_SCHEMA: JsonObject;
2
19
  /**
3
20
  * Framework-provided web search tool definition.
4
21
  *
@@ -1 +1 @@
1
- const WEB_SEARCH_TOOL_DEFINITION={description:`Search the web for real-time information. Use this to find up-to-date information about current events, recent developments, or topics that may have changed since the knowledge cutoff.`,inputSchema:null,logicalPath:`ash:framework/web-search`,name:`web_search`,sourceId:`ash:web-search-tool`,sourceKind:`module`};export{WEB_SEARCH_TOOL_DEFINITION};
1
+ const WEB_SEARCH_OPENAI_OUTPUT_SCHEMA={$schema:`http://json-schema.org/draft-07/schema#`,additionalProperties:!1,properties:{action:{oneOf:[{additionalProperties:!1,properties:{queries:{items:{type:`string`},type:`array`},query:{type:`string`},type:{const:`search`,type:`string`}},required:[`type`],type:`object`},{additionalProperties:!1,properties:{type:{const:`openPage`,type:`string`},url:{anyOf:[{type:`string`},{type:`null`}]}},required:[`type`],type:`object`},{additionalProperties:!1,properties:{pattern:{anyOf:[{type:`string`},{type:`null`}]},type:{const:`findInPage`,type:`string`},url:{anyOf:[{type:`string`},{type:`null`}]}},required:[`type`],type:`object`}]},sources:{items:{oneOf:[{additionalProperties:!1,properties:{type:{const:`url`,type:`string`},url:{type:`string`}},required:[`type`,`url`],type:`object`},{additionalProperties:!1,properties:{name:{type:`string`},type:{const:`api`,type:`string`}},required:[`type`,`name`],type:`object`}]},type:`array`}},type:`object`},WEB_SEARCH_ANTHROPIC_OUTPUT_SCHEMA={$schema:`http://json-schema.org/draft-07/schema#`,items:{additionalProperties:!1,properties:{encryptedContent:{type:`string`},pageAge:{anyOf:[{type:`string`},{type:`null`}]},title:{anyOf:[{type:`string`},{type:`null`}]},type:{const:`web_search_result`,type:`string`},url:{type:`string`}},required:[`url`,`title`,`pageAge`,`encryptedContent`,`type`],type:`object`},type:`array`},WEB_SEARCH_GOOGLE_OUTPUT_SCHEMA={$schema:`http://json-schema.org/draft-07/schema#`,additionalProperties:!1,properties:{},type:`object`},WEB_SEARCH_GATEWAY_OUTPUT_SCHEMA={$schema:`http://json-schema.org/draft-07/schema#`,anyOf:[{additionalProperties:!1,properties:{id:{type:`string`},results:{items:{additionalProperties:!1,properties:{date:{type:`string`},lastUpdated:{type:`string`},snippet:{type:`string`},title:{type:`string`},url:{type:`string`}},required:[`title`,`url`,`snippet`],type:`object`},type:`array`}},required:[`results`,`id`],type:`object`},{additionalProperties:!1,properties:{error:{enum:[`api_error`,`rate_limit`,`timeout`,`invalid_input`,`unknown`],type:`string`},message:{type:`string`},statusCode:{type:`number`}},required:[`error`,`message`],type:`object`}]},WEB_SEARCH_TOOL_DEFINITION={description:`Search the web for real-time information. Use this to find up-to-date information about current events, recent developments, or topics that may have changed since the knowledge cutoff.`,inputSchema:null,logicalPath:`ash:framework/web-search`,name:`web_search`,sourceId:`ash:web-search-tool`,sourceKind:`module`};export{WEB_SEARCH_ANTHROPIC_OUTPUT_SCHEMA,WEB_SEARCH_GATEWAY_OUTPUT_SCHEMA,WEB_SEARCH_GOOGLE_OUTPUT_SCHEMA,WEB_SEARCH_OPENAI_OUTPUT_SCHEMA,WEB_SEARCH_TOOL_DEFINITION};
@@ -9,4 +9,9 @@ import type { ResolvedToolDefinition } from "#runtime/types.js";
9
9
  * model input contracts in sync without duplication.
10
10
  */
11
11
  export declare const WRITE_FILE_INPUT_SCHEMA: JsonObject;
12
+ /**
13
+ * Shared output schema used by the framework `write_file` tool and any author
14
+ * tool constructed via {@link defineWriteFileTool}.
15
+ */
16
+ export declare const WRITE_FILE_OUTPUT_SCHEMA: JsonObject;
12
17
  export declare const WRITE_FILE_TOOL_DEFINITION: ResolvedToolDefinition;
@@ -1,2 +1,2 @@
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
- `),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
+ 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`},WRITE_FILE_OUTPUT_SCHEMA={additionalProperties:!1,properties:{existed:{type:`boolean`},path:{type:`string`}},required:[`existed`,`path`],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
+ `),execute:executeWriteFile,inputSchema:WRITE_FILE_INPUT_SCHEMA,logicalPath:`ash:framework/write-file`,name:`write_file`,outputSchema:WRITE_FILE_OUTPUT_SCHEMA,sourceId:`ash:write-file-tool`,sourceKind:`module`};export{WRITE_FILE_INPUT_SCHEMA,WRITE_FILE_OUTPUT_SCHEMA,WRITE_FILE_TOOL_DEFINITION};
@@ -1 +1 @@
1
- import{expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{lazyBackend}from"#execution/sandbox/lazy-backend.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{defaultBackend}from"#public/sandbox/backends/default.js";async function resolveSandboxDefinition(n,i,a){try{let t=expectObjectRecord(await loadResolvedModuleExport({definition:n,kindLabel:`sandbox`,moduleMap:i,nodeId:a}),`Expected the sandbox export "${n.exportName??`default`}" from "${n.logicalPath}" to return an object.`);return{backend:resolveBackend(t.backend,n.logicalPath),bootstrap:t.bootstrap,description:n.description,exportName:n.exportName,logicalPath:n.logicalPath,onSession:t.onSession,sourceId:n.sourceId,sourceKind:`module`}}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to attach the sandbox lifecycle handlers from "${n.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:n.logicalPath,sourceId:n.sourceId})}}function resolveBackend(e,t){if(e===void 0)return defaultBackend();if(typeof e==`function`)return lazyBackend(e);if(typeof e!=`object`||!e)throw new ResolveAgentError(`Sandbox "${t}" exposed a non-object "backend" field. Use vercelBackend(), localBackend(), another factory that returns a SandboxBackend value, or a zero-arg callback returning one.`,{logicalPath:t});let r=e;if(typeof r.name!=`string`||r.name.length===0)throw new ResolveAgentError(`Sandbox "${t}" backend is missing a non-empty string "name" identifier.`,{logicalPath:t});if(typeof r.create!=`function`)throw new ResolveAgentError(`Sandbox "${t}" backend is missing a "create" function.`,{logicalPath:t});return r}export{resolveSandboxDefinition};
1
+ import{expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{lazyBackend}from"#execution/sandbox/lazy-backend.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{defaultBackend}from"#public/sandbox/backends/default.js";async function resolveSandboxDefinition(n,i,a){try{let t=expectObjectRecord(await loadResolvedModuleExport({definition:n,kindLabel:`sandbox`,moduleMap:i,nodeId:a}),`Expected the sandbox export "${n.exportName??`default`}" from "${n.logicalPath}" to return an object.`);return{backend:resolveBackend(t.backend,n.logicalPath),bootstrap:t.bootstrap,description:n.description,exportName:n.exportName,logicalPath:n.logicalPath,onSession:t.onSession,revalidationKey:n.revalidationKey,sourceHash:n.sourceHash,sourceId:n.sourceId,sourceKind:`module`}}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to attach the sandbox lifecycle handlers from "${n.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:n.logicalPath,sourceId:n.sourceId})}}function resolveBackend(e,t){if(e===void 0)return defaultBackend();if(typeof e==`function`)return lazyBackend(e);if(typeof e!=`object`||!e)throw new ResolveAgentError(`Sandbox "${t}" exposed a non-object "backend" field. Use vercelBackend(), localBackend(), another factory that returns a SandboxBackend value, or a zero-arg callback returning one.`,{logicalPath:t});let r=e;if(typeof r.name!=`string`||r.name.length===0)throw new ResolveAgentError(`Sandbox "${t}" backend is missing a non-empty string "name" identifier.`,{logicalPath:t});if(typeof r.create!=`function`)throw new ResolveAgentError(`Sandbox "${t}" backend is missing a "create" function.`,{logicalPath:t});return r}export{resolveSandboxDefinition};
@@ -1 +1 @@
1
- import{expectFunction,expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{registerDefinitionSource,stampDefinitionKey}from"#public/tool-result-narrowing.js";async function resolveToolDefinition(i,a,o){try{let n=expectObjectRecord(await loadResolvedModuleExport({definition:i,kindLabel:`tool`,moduleMap:a,nodeId:o}),describe(i,`to return an object`)),r={kind:`tool`,logicalPath:i.logicalPath,name:i.name},s=`tool-source:${i.sourceId}`;stampDefinitionKey(n,s),registerDefinitionSource(s,r),registerDefinitionSource(`tool:${n.description}`,r);let c=expectFunction(n.execute,describe(i,`to provide an execute function`));return{description:i.description,execute:c,exportName:i.exportName,inputSchema:i.inputSchema,logicalPath:i.logicalPath,name:i.name,sourceId:i.sourceId,sourceKind:`module`,...extractOptionalHooks(n,i)}}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to attach the tool execute function from "${i.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:i.logicalPath,sourceId:i.sourceId})}}function extractOptionalHooks(t,n){let r={};return t.onCompact!==void 0&&(r.onCompact=expectFunction(t.onCompact,describe(n,`to provide an onCompact function`))),t.needsApproval!==void 0&&(r.needsApproval=expectFunction(t.needsApproval,describe(n,`to provide a needsApproval function`))),t.toModelOutput!==void 0&&(r.toModelOutput=expectFunction(t.toModelOutput,describe(n,`to provide a toModelOutput function`))),t.inputSchema!==void 0&&isFlexibleSchema(t.inputSchema)&&(r.inputStandardSchema=t.inputSchema),r}function describe(e,t){return`Expected the tool export "${e.exportName??`default`}" from "${e.logicalPath}" ${t}.`}function isFlexibleSchema(e){return typeof e==`object`&&!!e&&`~standard`in e&&typeof e[`~standard`]==`object`}export{resolveToolDefinition};
1
+ import{expectFunction,expectObjectRecord}from"#internal/authored-module.js";import{toErrorMessage}from"#shared/errors.js";import{ResolveAgentError,loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{registerDefinitionSource,stampDefinitionKey}from"#public/tool-result-narrowing.js";async function resolveToolDefinition(i,a,o){try{let n=expectObjectRecord(await loadResolvedModuleExport({definition:i,kindLabel:`tool`,moduleMap:a,nodeId:o}),describe(i,`to return an object`)),r={kind:`tool`,logicalPath:i.logicalPath,name:i.name},s=`tool-source:${i.sourceId}`;stampDefinitionKey(n,s),registerDefinitionSource(s,r),registerDefinitionSource(`tool:${n.description}`,r);let c=expectFunction(n.execute,describe(i,`to provide an execute function`));return{description:i.description,execute:c,exportName:i.exportName,inputSchema:i.inputSchema,logicalPath:i.logicalPath,name:i.name,outputSchema:i.outputSchema,sourceId:i.sourceId,sourceKind:`module`,...extractOptionalHooks(n,i)}}catch(e){throw e instanceof ResolveAgentError?e:new ResolveAgentError(`Failed to attach the tool execute function from "${i.logicalPath}": ${toErrorMessage(e)}`,{logicalPath:i.logicalPath,sourceId:i.sourceId})}}function extractOptionalHooks(t,n){let r={};return t.onCompact!==void 0&&(r.onCompact=expectFunction(t.onCompact,describe(n,`to provide an onCompact function`))),t.needsApproval!==void 0&&(r.needsApproval=expectFunction(t.needsApproval,describe(n,`to provide a needsApproval function`))),t.toModelOutput!==void 0&&(r.toModelOutput=expectFunction(t.toModelOutput,describe(n,`to provide a toModelOutput function`))),t.inputSchema!==void 0&&isFlexibleSchema(t.inputSchema)&&(r.inputStandardSchema=t.inputSchema),t.outputSchema!==void 0&&isFlexibleSchema(t.outputSchema)&&(r.outputStandardSchema=t.outputSchema),r}function describe(e,t){return`Expected the tool export "${e.exportName??`default`}" from "${e.logicalPath}" ${t}.`}function isFlexibleSchema(e){return typeof e==`object`&&!!e&&`~standard`in e&&typeof e[`~standard`]==`object`}export{resolveToolDefinition};
@@ -1 +1 @@
1
- import{realpath}from"node:fs/promises";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{createHash}from"node:crypto";import{getRuntimeCompiledArtifactsAppRoot,getRuntimeCompiledArtifactsCacheKey}from"#runtime/compiled-artifacts-source.js";import{loadCompileMetadata}from"#runtime/loaders/compile-metadata.js";async function createRuntimeSandboxKeys(e){return{sessionKey:await createRuntimeSandboxSessionKey(e),templateKey:await createRuntimeSandboxTemplateKey(e)}}async function createRuntimeSandboxTemplateKey(e){if(e.templatePlan.kind===`none`)return null;let n=await resolveRuntimeSandboxScope({backendName:e.backendName,compiledArtifactsSource:e.compiledArtifactsSource,scopeKind:e.templatePlan.kind===`source-graph`?`deployment`:`stable`}),r=await resolveRuntimeSandboxVersionHash({compiledArtifactsSource:e.compiledArtifactsSource,nodeId:e.nodeId,sourceId:e.sourceId,templatePlan:e.templatePlan}),i=createStableHash(`${resolveInstalledPackageInfo().version}:3:${r}`).slice(0,20);return sanitizeRuntimeSandboxKey(`ash-sbx-tpl-${e.backendName}-${n}-${i}`)}async function createRuntimeSandboxSessionKey(e){let t=await resolveRuntimeSandboxScope({backendName:e.backendName,compiledArtifactsSource:e.compiledArtifactsSource,scopeKind:`deployment`}),n=sanitizeRuntimeSandboxKey(e.nodeId);return sanitizeRuntimeSandboxKey(`ash-sbx-ses-${e.backendName}-${t}-${e.sessionId}-${n}`)}async function resolveRuntimeSandboxScope(t){if(t.backendName===`vercel`){if(t.scopeKind===`stable`){let e=resolveVercelProjectScope();if(e!==void 0)return createStableHash(e).slice(0,16)}let e=process.env.VERCEL_DEPLOYMENT_ID?.trim();if(e!==void 0&&e.length>0)return createStableHash(e).slice(0,16)}let n=getRuntimeCompiledArtifactsAppRoot(t.compiledArtifactsSource);return n===void 0?createStableHash(getRuntimeCompiledArtifactsCacheKey(t.compiledArtifactsSource)).slice(0,16):createStableHash(await realpath(n)).slice(0,16)}async function resolveRuntimeSandboxVersionHash(e){return e.templatePlan.kind===`workspace-content`?createStableHash(`workspace-content:${e.templatePlan.contentHash??await resolveSourceGraphHash(e.compiledArtifactsSource)}:${e.nodeId}:${e.sourceId}`):createStableHash(`source-graph:${await resolveSourceGraphHash(e.compiledArtifactsSource)}:${e.nodeId}:${e.sourceId}`)}async function resolveSourceGraphHash(e){return(await loadCompileMetadata({compiledArtifactsSource:e}))?.discovery.sourceGraphHash??getRuntimeCompiledArtifactsCacheKey(e)}function resolveVercelProjectScope(){let e=process.env.VERCEL_PROJECT_ID?.trim();if(e===void 0||e.length===0)return;let t=process.env.VERCEL_TEAM_ID?.trim();return t===void 0||t.length===0?`vercel-project:${e}`:`vercel-project:${t}:${e}`}function createStableHash(e){return createHash(`sha256`).update(e).digest(`hex`)}function sanitizeRuntimeSandboxKey(e){return e.replaceAll(/[^a-zA-Z0-9._-]+/g,`-`).slice(0,120)}export{createRuntimeSandboxKeys,createRuntimeSandboxTemplateKey};
1
+ import{realpath}from"node:fs/promises";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{createHash}from"node:crypto";import{getRuntimeCompiledArtifactsAppRoot,getRuntimeCompiledArtifactsCacheKey}from"#runtime/compiled-artifacts-source.js";import{loadCompileMetadata}from"#runtime/loaders/compile-metadata.js";async function createRuntimeSandboxKeys(e){return{sessionKey:await createRuntimeSandboxSessionKey(e),templateKey:await createRuntimeSandboxTemplateKey(e)}}async function createRuntimeSandboxTemplateKey(e){if(e.templatePlan.kind===`none`)return null;let n=await resolveRuntimeSandboxScope({backendName:e.backendName,compiledArtifactsSource:e.compiledArtifactsSource,scopeKind:e.templatePlan.kind===`source-graph`?`deployment`:`stable`}),r=await resolveRuntimeSandboxVersionHash({compiledArtifactsSource:e.compiledArtifactsSource,nodeId:e.nodeId,sourceId:e.sourceId,templatePlan:e.templatePlan}),i=createStableHash(`${resolveInstalledPackageInfo().version}:5:${r}`).slice(0,20);return sanitizeRuntimeSandboxKey(`ash-sbx-tpl-${e.backendName}-${n}-${i}`)}async function createRuntimeSandboxSessionKey(e){let t=await resolveRuntimeSandboxScope({backendName:e.backendName,compiledArtifactsSource:e.compiledArtifactsSource,scopeKind:`deployment`}),n=sanitizeRuntimeSandboxKey(e.nodeId);return sanitizeRuntimeSandboxKey(`ash-sbx-ses-${e.backendName}-${t}-${e.sessionId}-${n}`)}async function resolveRuntimeSandboxScope(t){if(t.backendName===`vercel`){if(t.scopeKind===`stable`){let e=resolveVercelProjectScope();if(e!==void 0)return createStableHash(e).slice(0,16)}let e=process.env.VERCEL_DEPLOYMENT_ID?.trim();if(e!==void 0&&e.length>0)return createStableHash(e).slice(0,16)}let n=getRuntimeCompiledArtifactsAppRoot(t.compiledArtifactsSource);return n===void 0?createStableHash(getRuntimeCompiledArtifactsCacheKey(t.compiledArtifactsSource)).slice(0,16):createStableHash(await realpath(n)).slice(0,16)}async function resolveRuntimeSandboxVersionHash(e){if(e.templatePlan.kind===`bootstrap`){let t=e.templatePlan.contentHash??await resolveSourceGraphHash(e.compiledArtifactsSource);return createStableHash(`bootstrap:${e.templatePlan.revalidationKey??``}:${e.templatePlan.sourceHash}:${t}:${e.nodeId}:${e.sourceId}`)}return e.templatePlan.kind===`workspace-content`?createStableHash(`workspace-content:${e.templatePlan.contentHash??await resolveSourceGraphHash(e.compiledArtifactsSource)}:${e.nodeId}:${e.sourceId}`):createStableHash(`source-graph:${await resolveSourceGraphHash(e.compiledArtifactsSource)}:${e.nodeId}:${e.sourceId}`)}async function resolveSourceGraphHash(e){return(await loadCompileMetadata({compiledArtifactsSource:e}))?.discovery.sourceGraphHash??getRuntimeCompiledArtifactsCacheKey(e)}function resolveVercelProjectScope(){let e=process.env.VERCEL_PROJECT_ID?.trim();if(e===void 0||e.length===0)return;let t=process.env.VERCEL_TEAM_ID?.trim();return t===void 0||t.length===0?`vercel-project:${e}`:`vercel-project:${t}:${e}`}function createStableHash(e){return createHash(`sha256`).update(e).digest(`hex`)}function sanitizeRuntimeSandboxKey(e){return e.replaceAll(/[^a-zA-Z0-9._-]+/g,`-`).slice(0,120)}export{createRuntimeSandboxKeys,createRuntimeSandboxTemplateKey};
@@ -9,6 +9,11 @@ export type RuntimeSandboxTemplatePlan = {
9
9
  } | {
10
10
  readonly contentHash?: string;
11
11
  readonly kind: "workspace-content";
12
+ } | {
13
+ readonly contentHash?: string;
14
+ readonly kind: "bootstrap";
15
+ readonly revalidationKey?: string;
16
+ readonly sourceHash: string;
12
17
  } | {
13
18
  readonly kind: "source-graph";
14
19
  };
@@ -1 +1 @@
1
- function createRuntimeSandboxTemplatePlan(e){return e.definition.bootstrap===void 0?e.workspaceResourceRoot.rootEntries.length===0?{kind:`none`}:{contentHash:e.workspaceResourceRoot.contentHash,kind:`workspace-content`}:{kind:`source-graph`}}export{createRuntimeSandboxTemplatePlan};
1
+ function createRuntimeSandboxTemplatePlan(e){if(e.definition.bootstrap!==void 0){if(e.definition.sourceHash===void 0)throw Error(`Sandbox "${e.definition.logicalPath}" defines bootstrap() but has no compiled sourceHash.`);return{contentHash:e.workspaceResourceRoot.contentHash,kind:`bootstrap`,revalidationKey:e.definition.revalidationKey,sourceHash:e.definition.sourceHash}}return e.workspaceResourceRoot.rootEntries.length===0?{kind:`none`}:{contentHash:e.workspaceResourceRoot.contentHash,kind:`workspace-content`}}export{createRuntimeSandboxTemplatePlan};
@@ -1 +1 @@
1
- import{RuntimeRegistry,RuntimeRegistryError}from"#internal/runtime-registry.js";const SUBAGENT_TOOL_INPUT_SCHEMA=Object.freeze({type:`object`,properties:Object.freeze({message:Object.freeze({type:`string`,description:`The message to send to the subagent. Provide all context the subagent needs to complete the task; the subagent does not see the parent's history.`})}),required:Object.freeze([`message`]),additionalProperties:!1});function createRuntimeSubagentRegistry(t){let n=[],r=new RuntimeRegistry(`subagent`,t.reservedToolNames??[]),i=new Map;for(let e of t.subagents){let t={logicalPath:e.logicalPath,sourceId:e.sourceId};if(i.has(e.nodeId))throw new RuntimeRegistryError(`subagent`,`Found multiple runtime subagents mapped to node id "${e.nodeId}".`,{...t,entryName:e.name});let a=createPreparedRuntimeSubagentTool(e),o={definition:e,prepared:a};r.register(e.name,o,{location:t,duplicateMessage:`Found multiple subagents named "${e.name}". Subagent names must be unique at runtime.`,reservedMessage:`Subagent "${e.name}" collides with another runtime-visible tool name.`}),n.push(a),i.set(e.nodeId,o)}return{preparedTools:n,subagentsByName:r.asMap(),subagentsByNodeId:i}}function createPreparedRuntimeSubagentTool(e){return{description:e.description,inputSchema:SUBAGENT_TOOL_INPUT_SCHEMA,kind:e.kind,logicalPath:e.logicalPath,name:e.name,nodeId:e.nodeId,sourceId:e.sourceId}}export{createRuntimeSubagentRegistry};
1
+ import{RuntimeRegistry,RuntimeRegistryError}from"#internal/runtime-registry.js";const SUBAGENT_TOOL_INPUT_SCHEMA=Object.freeze({type:`object`,properties:Object.freeze({message:Object.freeze({type:`string`,description:`The message to send to the subagent. Provide all context the subagent needs to complete the task; the subagent does not see the parent's history.`}),outputSchema:Object.freeze({type:`object`,description:`When provided, the subagent runs in task mode and must produce structured output matching this JSON Schema. The structured output becomes the tool result.`})}),required:Object.freeze([`message`]),additionalProperties:!1});function createRuntimeSubagentRegistry(t){let n=[],r=new RuntimeRegistry(`subagent`,t.reservedToolNames??[]),i=new Map;for(let e of t.subagents){let t={logicalPath:e.logicalPath,sourceId:e.sourceId};if(i.has(e.nodeId))throw new RuntimeRegistryError(`subagent`,`Found multiple runtime subagents mapped to node id "${e.nodeId}".`,{...t,entryName:e.name});let a=createPreparedRuntimeSubagentTool(e),o={definition:e,prepared:a};r.register(e.name,o,{location:t,duplicateMessage:`Found multiple subagents named "${e.name}". Subagent names must be unique at runtime.`,reservedMessage:`Subagent "${e.name}" collides with another runtime-visible tool name.`}),n.push(a),i.set(e.nodeId,o)}return{preparedTools:n,subagentsByName:r.asMap(),subagentsByNodeId:i}}function createPreparedRuntimeSubagentTool(e){return{description:e.description,inputSchema:SUBAGENT_TOOL_INPUT_SCHEMA,kind:e.kind,logicalPath:e.logicalPath,name:e.name,nodeId:e.nodeId,outputSchema:e.kind===`remote`?e.outputSchema:void 0,sourceId:e.sourceId}}export{createRuntimeSubagentRegistry};
@@ -1 +1 @@
1
- import{RuntimeRegistry}from"#internal/runtime-registry.js";async function createRuntimeToolRegistry(t,n={}){let r=[],i=new RuntimeRegistry(`tool`,n.reservedToolNames??[]);for(let e of t.tools){let t=await createPreparedRuntimeTool(e);i.register(e.name,{definition:e,prepared:t},{location:{logicalPath:e.logicalPath,sourceId:e.sourceId},duplicateMessage:`Found multiple authored tools named "${e.name}". Tool names must be unique at runtime.`,reservedMessage:`Tool "${e.name}" collides with another runtime-visible tool name.`}),r.push(t)}return{preparedTools:r,toolsByName:i.asMap()}}function findRegisteredRuntimeTool(e,t){return e.toolsByName.get(t)??null}async function createPreparedRuntimeTool(e){return{description:e.description,inputSchema:e.inputSchema,kind:`authored-tool`,logicalPath:e.logicalPath,name:e.name,sourceId:e.sourceId}}export{createRuntimeToolRegistry,findRegisteredRuntimeTool};
1
+ import{RuntimeRegistry}from"#internal/runtime-registry.js";async function createRuntimeToolRegistry(t,n={}){let r=[],i=new RuntimeRegistry(`tool`,n.reservedToolNames??[]);for(let e of t.tools){let t=await createPreparedRuntimeTool(e);i.register(e.name,{definition:e,prepared:t},{location:{logicalPath:e.logicalPath,sourceId:e.sourceId},duplicateMessage:`Found multiple authored tools named "${e.name}". Tool names must be unique at runtime.`,reservedMessage:`Tool "${e.name}" collides with another runtime-visible tool name.`}),r.push(t)}return{preparedTools:r,toolsByName:i.asMap()}}function findRegisteredRuntimeTool(e,t){return e.toolsByName.get(t)??null}async function createPreparedRuntimeTool(e){return{description:e.description,inputSchema:e.inputSchema,kind:`authored-tool`,logicalPath:e.logicalPath,name:e.name,outputSchema:e.outputSchema,sourceId:e.sourceId}}export{createRuntimeToolRegistry,findRegisteredRuntimeTool};
@@ -19,7 +19,7 @@ import type { NamedSkillDefinition } from "#shared/skill-definition.js";
19
19
  import type { InternalAgentDefinition } from "#shared/agent-definition.js";
20
20
  import type { InternalToolDefinitionWithExecuteFn } from "#shared/tool-definition.js";
21
21
  import type { SandboxBackend } from "#shared/sandbox-backend.js";
22
- import type { SandboxDefinition } from "#shared/sandbox-definition.js";
22
+ import type { SandboxBootstrapContext, SandboxSessionContext } from "#shared/sandbox-definition.js";
23
23
  /**
24
24
  * Runtime-owned source ref describing one additive config module import.
25
25
  */
@@ -86,7 +86,10 @@ export interface ResolvedConnectionDefinition extends ResolvedModuleSourceRef {
86
86
  * `vercelBackend()` and `localBackend()` based on the current
87
87
  * environment).
88
88
  */
89
- export type ResolvedSandboxDefinition = Readonly<Omit<SandboxDefinition, "backend">> & ResolvedModuleSourceRef & {
89
+ export type ResolvedSandboxDefinition = ResolvedModuleSourceRef & {
90
+ readonly bootstrap?: (input: SandboxBootstrapContext) => Promise<void> | void;
91
+ readonly revalidationKey?: string;
92
+ readonly sourceHash?: string;
90
93
  /**
91
94
  * Resolved backend value. The authored `SandboxDefinition.backend`
92
95
  * accepts either a `SandboxBackend` or a `() => SandboxBackend`; by
@@ -96,6 +99,7 @@ export type ResolvedSandboxDefinition = Readonly<Omit<SandboxDefinition, "backen
96
99
  */
97
100
  readonly backend: SandboxBackend;
98
101
  readonly description?: string;
102
+ readonly onSession?: (input: SandboxSessionContext) => Promise<void> | void;
99
103
  };
100
104
  /**
101
105
  * Runtime-owned authored tool definition resolved from a compiled module map.
@@ -108,6 +112,11 @@ export type ResolvedToolDefinition = Readonly<Optional<InternalToolDefinitionWit
108
112
  * extraction and runtime validation with transforms/defaults.
109
113
  */
110
114
  readonly inputStandardSchema?: FlexibleSchema;
115
+ /**
116
+ * Optional live Standard Schema reattached from the authored module at
117
+ * resolve time for tool output typing/validation.
118
+ */
119
+ readonly outputStandardSchema?: FlexibleSchema;
111
120
  /**
112
121
  * Optional per-tool approval gate. When set, determines whether user
113
122
  * approval is required before executing this tool. See
@@ -1,5 +1,5 @@
1
1
  import type { ModelMessage } from "ai";
2
- import type { PublicToolInputSchema, ToolModelOutput } from "#shared/tool-definition.js";
2
+ import type { PublicToolInputSchema, PublicToolOutputSchema, ToolModelOutput } from "#shared/tool-definition.js";
3
3
  import type { SessionContext } from "#public/definitions/callback-context.js";
4
4
  import type { NeedsApprovalContext } from "#public/definitions/tool.js";
5
5
  import type { SessionAuth } from "#context/keys.js";
@@ -55,6 +55,7 @@ export interface DynamicResolveContext {
55
55
  export interface DynamicToolEntry<TInput = Record<string, unknown>, TOutput = any> {
56
56
  readonly description: string;
57
57
  readonly inputSchema: PublicToolInputSchema<TInput>;
58
+ readonly outputSchema?: PublicToolOutputSchema<TOutput>;
58
59
  execute(input: TInput, ctx: ToolContext): TOutput | Promise<TOutput>;
59
60
  readonly toModelOutput?: (output: TOutput) => ToolModelOutput | Promise<ToolModelOutput>;
60
61
  /**
@@ -1,7 +1,9 @@
1
1
  import type { StandardJSONSchemaV1 } from "#compiled/@standard-schema/spec/index.js";
2
2
  import { type JsonObject } from "#shared/json.js";
3
+ type JsonSchemaDirection = "input" | "output";
3
4
  /**
4
5
  * Normalizes one Standard Schema or JSON Schema definition into plain JSON
5
6
  * Schema data that can cross Ash runtime and client boundaries.
6
7
  */
7
- export declare function normalizeJsonSchemaDefinition(value: StandardJSONSchemaV1 | Record<string, unknown> | unknown): JsonObject;
8
+ export declare function normalizeJsonSchemaDefinition(value: StandardJSONSchemaV1 | Record<string, unknown> | unknown, direction?: JsonSchemaDirection): JsonObject;
9
+ export {};
@@ -1 +1 @@
1
- import{parseJsonObject}from"#shared/json.js";function normalizeJsonSchemaDefinition(t){return isStandardSchema(t)?parseJsonObject(t[`~standard`].jsonSchema.input({target:`draft-07`})):parseJsonObject(t)}function isStandardSchema(e){return typeof e==`object`&&!!e&&`~standard`in e}export{normalizeJsonSchemaDefinition};
1
+ import{parseJsonObject}from"#shared/json.js";function normalizeJsonSchemaDefinition(t,n=`input`){return isStandardSchema(t)?parseJsonObject(t[`~standard`].jsonSchema[n]({target:`draft-07`})):parseJsonObject(t)}function isStandardSchema(e){return typeof e==`object`&&!!e&&`~standard`in e}export{normalizeJsonSchemaDefinition};
@@ -10,6 +10,7 @@ export interface SandboxSessionContext<O = Record<string, never>> {
10
10
  readonly ctx: SessionContext;
11
11
  readonly use: SandboxSessionUseFn<O>;
12
12
  }
13
+ export type SandboxRevalidationKeyFn = () => Promise<string> | string;
13
14
  /**
14
15
  * Public sandbox definition authored in `agent/sandbox.ts` (shorthand)
15
16
  * or `agent/sandbox/sandbox.ts` (folder layout, when paired with an
@@ -23,7 +24,7 @@ export interface SandboxSessionContext<O = Record<string, never>> {
23
24
  * `subagents/<name>/sandbox.ts` (or the folder form) and do not inherit
24
25
  * their parent's sandbox (skill seeds differ per agent).
25
26
  */
26
- export interface SandboxDefinition<BO = Record<string, never>, SO = Record<string, never>> {
27
+ interface SandboxDefinitionBase<BO = Record<string, never>, SO = Record<string, never>> {
27
28
  /**
28
29
  * Backend that runs this sandbox.
29
30
  *
@@ -49,6 +50,25 @@ export interface SandboxDefinition<BO = Record<string, never>, SO = Record<strin
49
50
  * specific backend regardless of environment.
50
51
  */
51
52
  readonly backend: SandboxBackend<BO, SO> | (() => SandboxBackend<BO, SO>);
52
- bootstrap?(input: SandboxBootstrapContext<BO>): Promise<void> | void;
53
+ readonly description?: string;
53
54
  onSession?(input: SandboxSessionContext<SO>): Promise<void> | void;
54
55
  }
56
+ export interface SandboxDefinitionWithBootstrap<BO = Record<string, never>, SO = Record<string, never>> extends SandboxDefinitionBase<BO, SO> {
57
+ bootstrap(input: SandboxBootstrapContext<BO>): Promise<void> | void;
58
+ /**
59
+ * Optional build-time revalidation key for the reusable sandbox
60
+ * snapshot produced by {@link bootstrap}. Ash evaluates this
61
+ * function during compile/build, stores the resolved string in
62
+ * compiled artifacts, and uses that frozen value for both prewarm and
63
+ * runtime session create. Authored sandbox source and
64
+ * framework-managed seed contents are included automatically; provide
65
+ * this key only for external inputs that affect bootstrap output.
66
+ */
67
+ readonly revalidationKey?: SandboxRevalidationKeyFn;
68
+ }
69
+ export interface SandboxDefinitionWithoutBootstrap<BO = Record<string, never>, SO = Record<string, never>> extends SandboxDefinitionBase<BO, SO> {
70
+ bootstrap?: undefined;
71
+ readonly revalidationKey?: never;
72
+ }
73
+ export type SandboxDefinition<BO = Record<string, never>, SO = Record<string, never>> = SandboxDefinitionWithBootstrap<BO, SO> | SandboxDefinitionWithoutBootstrap<BO, SO>;
74
+ export {};
@@ -20,19 +20,27 @@ interface ToolDefinitionBase {
20
20
  export interface InternalToolDefinition extends ToolDefinitionBase {
21
21
  name: string;
22
22
  inputSchema: JsonObject | null;
23
+ outputSchema?: JsonObject;
23
24
  }
24
25
  export type PublicToolInputSchema<TInput = unknown> = StandardJSONSchemaV1<unknown, TInput> | JsonObject;
26
+ export type PublicToolOutputSchema<TOutput = unknown> = StandardJSONSchemaV1<unknown, TOutput> | JsonObject;
25
27
  /**
26
28
  * Authored public tool definition shape. Identity is derived from the
27
29
  * file path at compile time, so `name` is intentionally absent here.
28
30
  */
29
- export interface PublicToolDefinition<TInput = unknown> extends ToolDefinitionBase {
31
+ export interface PublicToolDefinition<TInput = unknown, TOutput = unknown> extends ToolDefinitionBase {
30
32
  inputSchema: PublicToolInputSchema<TInput>;
33
+ /**
34
+ * Optional schema describing the value returned by the tool executor.
35
+ * Code mode uses this to expose typed host-tool return values to the
36
+ * generated program, and the AI SDK can use it for tool result typing.
37
+ */
38
+ outputSchema?: PublicToolOutputSchema<TOutput>;
31
39
  }
32
40
  export interface InternalToolDefinitionWithExecuteFn<TInput = unknown, TOutput = unknown> extends InternalToolDefinition {
33
41
  execute: ToolExecuteFn<TInput, TOutput>;
34
42
  }
35
- export interface PublicToolDefinitionWithExecuteFn<TInput = unknown, TOutput = unknown> extends PublicToolDefinition<TInput> {
43
+ export interface PublicToolDefinitionWithExecuteFn<TInput = unknown, TOutput = unknown> extends PublicToolDefinition<TInput, TOutput> {
36
44
  execute: ToolExecuteFn<TInput, TOutput>;
37
45
  }
38
46
  /**
package/package.json CHANGED
@@ -1,6 +1,25 @@
1
1
  {
2
2
  "name": "experimental-ash",
3
- "version": "0.55.3",
3
+ "version": "0.57.0",
4
+ "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
5
+ "keywords": [
6
+ "agent-framework",
7
+ "agents",
8
+ "ai-agents",
9
+ "ai-sdk",
10
+ "ash",
11
+ "evals",
12
+ "mcp",
13
+ "model-context-protocol",
14
+ "nextjs",
15
+ "observability",
16
+ "react",
17
+ "serverless",
18
+ "tools",
19
+ "vercel",
20
+ "workflow"
21
+ ],
22
+ "license": "Apache-2.0",
4
23
  "bin": {
5
24
  "ash": "./bin/ash.js",
6
25
  "experimental-ash": "./bin/ash.js"
@@ -146,6 +165,11 @@
146
165
  "import": "./dist/src/public/channels/slack/index.js",
147
166
  "default": "./dist/src/public/channels/slack/index.js"
148
167
  },
168
+ "./channels/github": {
169
+ "types": "./dist/src/public/channels/github/index.d.ts",
170
+ "import": "./dist/src/public/channels/github/index.js",
171
+ "default": "./dist/src/public/channels/github/index.js"
172
+ },
149
173
  "./channels/discord": {
150
174
  "types": "./dist/src/public/channels/discord/index.d.ts",
151
175
  "import": "./dist/src/public/channels/discord/index.js",