experimental-ash 0.57.0 → 0.58.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 (30) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/docs/public/subagents.mdx +49 -8
  3. package/dist/docs/public/tools.mdx +8 -2
  4. package/dist/src/cli/commands/channels.d.ts +3 -3
  5. package/dist/src/cli/commands/channels.js +1 -1
  6. package/dist/src/context/providers/sandbox.js +1 -1
  7. package/dist/src/execution/delegated-parent-result.d.ts +1 -1
  8. package/dist/src/execution/next-driver-action.d.ts +1 -1
  9. package/dist/src/execution/node-step.js +1 -1
  10. package/dist/src/execution/session-callback-step.d.ts +1 -1
  11. package/dist/src/execution/session.d.ts +4 -2
  12. package/dist/src/execution/session.js +3 -1
  13. package/dist/src/execution/subagent-tool.js +1 -1
  14. package/dist/src/execution/workflow-entry.d.ts +1 -1
  15. package/dist/src/execution/workflow-steps.d.ts +1 -1
  16. package/dist/src/execution/workflow-steps.js +1 -1
  17. package/dist/src/harness/code-mode.js +1 -1
  18. package/dist/src/harness/tool-loop.js +1 -1
  19. package/dist/src/harness/types.d.ts +1 -1
  20. package/dist/src/internal/application/package.js +1 -1
  21. package/dist/src/packages/ash-scaffold/src/channels.js +1 -1
  22. package/dist/src/packages/ash-scaffold/src/steps/index.js +1 -1
  23. package/dist/src/packages/ash-scaffold/src/steps/project-resolution.js +1 -0
  24. package/dist/src/packages/ash-scaffold/src/steps/run-add-to-agent.js +2 -2
  25. package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
  26. package/dist/src/runtime/resolve-agent-graph.js +1 -1
  27. package/dist/src/runtime/session-callback-route.js +1 -1
  28. package/dist/src/runtime/subagents/registry.d.ts +6 -0
  29. package/dist/src/runtime/subagents/registry.js +1 -1
  30. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # experimental-ash
2
2
 
3
+ ## 0.58.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 6544348: Add built-in `agent` tool that runs the current agent as a subagent with a focused task. Self-delegated children share the parent's Vercel Sandbox so file writes are visible to the parent. The tool accepts `message` and optional `outputSchema` for structured output.
8
+
9
+ ### Patch Changes
10
+
11
+ - 0fd74c8: Refresh the composed system prompt between turns in `ash dev` so edits to authored markdown, including `instructions.md`, apply to existing development sessions after HMR rebuilds.
12
+ - 4a84d65: Refactored onboarding/channel setup state so Vercel project resolution and AI Gateway readiness are tracked separately while preserving existing create and `ash channels add` behavior.
13
+
3
14
  ## 0.57.0
4
15
 
5
16
  ### Minor Changes
@@ -3,9 +3,15 @@ title: "Subagents"
3
3
  description: "Delegate specialized work to child agents with their own prompts, tools, and sandbox."
4
4
  ---
5
5
 
6
- Subagents let the root agent delegate specialized work to local child agents.
6
+ Subagents let an agent delegate specialized work to child agents.
7
7
 
8
- Use them when the task deserves its own prompt, tools, sandbox, and local runtime context.
8
+ There are two kinds of delegation:
9
+
10
+ - **Built-in `agent` tool** — every agent gets this automatically. It runs a copy of the current
11
+ agent as a subagent with a focused task. The child shares the parent's sandbox filesystem but
12
+ gets fresh session state. Use this when the task doesn't need a different prompt or tool surface.
13
+ - **Declared subagents** — authored under `agent/subagents/<id>/` with their own prompt, tools,
14
+ skills, and sandbox. Use these when the child needs a clearly different identity.
9
15
 
10
16
  A subagent is just an agent that lives under `agent/subagents/<id>/`. It is authored with the same
11
17
  `defineAgent` helper as the root agent — the location under `subagents/` is what makes it a
@@ -21,6 +27,37 @@ subagent.
21
27
  stream, and do not commit unless the user asks.
22
28
  </CopyPrompt>
23
29
 
30
+ ## The Built-in `agent` Tool
31
+
32
+ Every agent gets a built-in `agent` tool. The model calls it to delegate a subtask to a copy of
33
+ itself — same tools, connections, and instructions, fresh conversation history.
34
+
35
+ ```ts
36
+ {
37
+ message: string;
38
+ outputSchema?: object;
39
+ }
40
+ ```
41
+
42
+ The child shares the parent's sandbox filesystem. File writes from the child are immediately
43
+ visible to the parent. This makes it natural for the model to split work across multiple parallel
44
+ calls — for example, fixing different files concurrently.
45
+
46
+ Session state (`defineState`) is **not** shared. Each child gets its own fresh state. Auth,
47
+ connections, and the full tool surface are inherited, but conversation history and durable state
48
+ start empty.
49
+
50
+ If a declared subagent calls `agent`, the child is a copy of that subagent (not the root agent).
51
+ Every node self-delegates to itself.
52
+
53
+ An authored tool at `agent/tools/agent.ts` takes priority over the built-in.
54
+
55
+ ## Declared Subagents
56
+
57
+ A declared subagent is an agent that lives under `agent/subagents/<id>/`. It is authored with the same
58
+ `defineAgent` helper as the root agent — the location under `subagents/` is what makes it a
59
+ subagent.
60
+
24
61
  ## What A Local Subagent Looks Like
25
62
 
26
63
  ```text
@@ -115,9 +152,9 @@ When `outputSchema` is provided, the subagent runs in task mode and must produce
115
152
  matching the given JSON Schema via the `final_output` tool. The structured output becomes the tool
116
153
  result returned to the parent.
117
154
 
118
- ## What The Subagent Gets
155
+ ## What A Declared Subagent Gets
119
156
 
120
- Subagent execution gets:
157
+ Declared subagent execution gets:
121
158
 
122
159
  - its own instructions prompt
123
160
  - its own tools
@@ -125,10 +162,11 @@ Subagent execution gets:
125
162
  - its own `skills/` set (independent of the parent's skills)
126
163
  - immediate parent lineage in `ctx.session.parent`, including the parent subagent tool `callId`
127
164
 
128
- Skills and sandboxes do not cross the parent/child boundary. The subagent only sees skills
129
- authored under `agent/subagents/<id>/skills/`; skills under the root `agent/skills/` are not
130
- available inside the subagent's turns. If two subagents need the same procedure, duplicate the
131
- markdown under each subagent's `skills/` (or, for typed code reuse, share helpers via `lib/`).
165
+ Skills and sandboxes do not cross the parent/child boundary for declared subagents. The subagent
166
+ only sees skills authored under `agent/subagents/<id>/skills/`; skills under the root
167
+ `agent/skills/` are not available inside the subagent's turns. If two subagents need the same
168
+ procedure, duplicate the markdown under each subagent's `skills/` (or, for typed code reuse, share
169
+ helpers via `lib/`).
132
170
 
133
171
  The subagent's sandbox follows the same rule: it does not inherit from the parent, since different
134
172
  agents generally have different skills and sharing a filesystem would be confusing. Each subagent
@@ -137,6 +175,9 @@ gets the framework default sandbox unless it authors its own override at
137
175
  `workspace/` folder). A subagent can also author only `subagents/<name>/sandbox/workspace/` to seed
138
176
  files without overriding the definition.
139
177
 
178
+ The built-in `agent` tool is different: its children share the parent's sandbox because they are
179
+ copies of the same agent working on the same codebase.
180
+
140
181
  ## Stream Behavior
141
182
 
142
183
  Delegated local subagents now create their own public child session and stream.
@@ -119,8 +119,14 @@ That means tools are:
119
119
  ## Customizing Framework Tools
120
120
 
121
121
  Every Ash agent gets a small set of framework-provided tools by default:
122
- `bash`, `read_file`, `write_file`, `todo`, `web_fetch`, `web_search`, and, when the agent has skills,
123
- `load_skill`.
122
+ `bash`, `read_file`, `write_file`, `todo`, `web_fetch`, `web_search`, `agent`, and, when the agent
123
+ has skills, `load_skill`.
124
+
125
+ `agent` runs a copy of the current agent as a subagent with a focused task. The child gets the same
126
+ tools, connections, and instructions but a fresh conversation history. The child shares the parent's
127
+ sandbox filesystem — file writes from the child are visible to the parent. Session state
128
+ (`defineState`) is isolated: the child gets fresh state, not the parent's values. See
129
+ [Subagents](./subagents.mdx) for more on delegation.
124
130
 
125
131
  `load_skill` loads on-demand skill instructions into the current turn. It does not add a new
126
132
  execution surface by itself; executable behavior still comes from the tools the agent already has.
@@ -1,4 +1,4 @@
1
- import { type DeployProjectOptions, type RunAddToAgentOptions } from "@vercel/ash-scaffold/steps";
1
+ import { type AddToAgentState, type DeployProjectOptions, type RunAddToAgentOptions } from "@vercel/ash-scaffold/steps";
2
2
  import { type ChannelAddPrompter } from "@vercel/ash-scaffold/cli";
3
3
  import { type DeploymentInfo } from "@vercel/ash-scaffold/primitives";
4
4
  export interface CliLogger {
@@ -13,8 +13,8 @@ export interface AddChannelCommandOptions {
13
13
  export interface ChannelsAddDependencies {
14
14
  createPrompter?: () => ChannelAddPrompter;
15
15
  detectDeployment(projectPath: string): Promise<DeploymentInfo>;
16
- deployProject(options: DeployProjectOptions): Promise<void>;
17
- runAddToAgent(options: RunAddToAgentOptions): Promise<void>;
16
+ deployProject(options: DeployProjectOptions): Promise<AddToAgentState>;
17
+ runAddToAgent(options: RunAddToAgentOptions): Promise<AddToAgentState>;
18
18
  }
19
19
  export declare function runChannelsAddCommand(logger: CliLogger, appRoot: string, args: {
20
20
  kind?: string;
@@ -1 +1 @@
1
- import{assertCanAddSelectedChannels,inspectExistingChannelRegistrations}from"./channel-add-conflicts.js";import{isAshProject}from"../../packages/ash-scaffold/src/project.js";import{listAuthoredChannels}from"../../packages/ash-scaffold/src/channels.js";import"../../packages/ash-scaffold/src/index.js";import{detectDeployment}from"../../packages/ash-scaffold/src/primitives/detect-deployment.js";import{createAddToAgentState,deployProject,runAddToAgent}from"../../packages/ash-scaffold/src/steps/run-add-to-agent.js";import"../../packages/ash-scaffold/src/steps/index.js";import{ChannelAddCancelledError,createChannelAddPrompter}from"../../packages/ash-scaffold/src/cli/channel-add-prompter.js";import"../../packages/ash-scaffold/src/cli/index.js";import"../../packages/ash-scaffold/src/primitives/index.js";const NOT_AN_AGENT_MESSAGE="No Ash agent in this directory. Run `pnpm create experimental-ash-agent`, then run this command from inside the new project.",KNOWN_CHANNEL_KINDS=[`slack`,`web`];function isChannelKind(e){return KNOWN_CHANNEL_KINDS.includes(e)}function parseChannelKind(e){if(!isChannelKind(e))throw Error(`Unknown channel kind "${e}". Known: ${KNOWN_CHANNEL_KINDS.join(`, `)}.`);return e}const defaultChannelsAddDependencies={detectDeployment,deployProject,runAddToAgent};async function runAddChannelsFlow(n,r,i,o){if(r===void 0&&(i.yes||!process.stdin.isTTY||!process.stdout.isTTY))throw Error(`Pass a channel kind: \`ash channels add <${KNOWN_CHANNEL_KINDS.join(`|`)}>\`.`);let s=o.createPrompter?.()??createChannelAddPrompter();s.intro(`Add channels to your Ash agent`),s.log.message(`Checking the current Vercel project...`);let c=createAddToAgentState(await o.detectDeployment(n)),l;function inspectRegistrations(){return l===void 0&&(s.log.message(`Inspecting existing channel registrations...`),l=inspectExistingChannelRegistrations(n)),l}let u=r===void 0?(await inspectRegistrations()).disabledChannelReasons:void 0;await o.runAddToAgent({prompter:s,projectPath:n,state:c,presetChannels:r===void 0?void 0:[r],presetCreateSlackbot:i.yes?!0:void 0,disabledChannelReasons:u,force:i.force,validateSelectedChannels:async t=>{!t.includes(`web`)&&!t.includes(`slack`)||assertCanAddSelectedChannels(t,await inspectRegistrations())}}),await o.deployProject({prompter:s,projectPath:n,vercelProjectId:c.vercelProjectId,state:c}),s.outro(c.channels.length===0?`No channels added.`:`Channels added.`)}async function runChannelsAddCommand(e,t,r,i=defaultChannelsAddDependencies){if(!await isAshProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}try{await runAddChannelsFlow(t,r.kind===void 0?void 0:parseChannelKind(r.kind),r.options,i)}catch(t){if(t instanceof ChannelAddCancelledError)return;e.error(t instanceof Error?t.message:String(t)),process.exitCode=1}}async function runChannelsListCommand(e,t,i){if(!await isAshProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}let a=await listAuthoredChannels(t);if(i.json){e.log(JSON.stringify({channels:a},null,2));return}if(a.length===0){e.log("No channels defined. Run `ash channels add` to add one.");return}for(let t of a)e.log(t)}export{runChannelsAddCommand,runChannelsListCommand};
1
+ import{assertCanAddSelectedChannels,inspectExistingChannelRegistrations}from"./channel-add-conflicts.js";import{isAshProject}from"../../packages/ash-scaffold/src/project.js";import{listAuthoredChannels}from"../../packages/ash-scaffold/src/channels.js";import"../../packages/ash-scaffold/src/index.js";import{detectDeployment}from"../../packages/ash-scaffold/src/primitives/detect-deployment.js";import{createAddToAgentState,deployProject,runAddToAgent}from"../../packages/ash-scaffold/src/steps/run-add-to-agent.js";import"../../packages/ash-scaffold/src/steps/index.js";import{ChannelAddCancelledError,createChannelAddPrompter}from"../../packages/ash-scaffold/src/cli/channel-add-prompter.js";import"../../packages/ash-scaffold/src/cli/index.js";import"../../packages/ash-scaffold/src/primitives/index.js";const NOT_AN_AGENT_MESSAGE="No Ash agent in this directory. Run `pnpm create experimental-ash-agent`, then run this command from inside the new project.",KNOWN_CHANNEL_KINDS=[`slack`,`web`];function isChannelKind(e){return KNOWN_CHANNEL_KINDS.includes(e)}function parseChannelKind(e){if(!isChannelKind(e))throw Error(`Unknown channel kind "${e}". Known: ${KNOWN_CHANNEL_KINDS.join(`, `)}.`);return e}const defaultChannelsAddDependencies={detectDeployment,deployProject,runAddToAgent};async function runAddChannelsFlow(n,r,i,o){if(r===void 0&&(i.yes||!process.stdin.isTTY||!process.stdout.isTTY))throw Error(`Pass a channel kind: \`ash channels add <${KNOWN_CHANNEL_KINDS.join(`|`)}>\`.`);let s=o.createPrompter?.()??createChannelAddPrompter();s.intro(`Add channels to your Ash agent`),s.log.message(`Checking the current Vercel project...`);let c=createAddToAgentState(await o.detectDeployment(n)),l;function inspectRegistrations(){return l===void 0&&(s.log.message(`Inspecting existing channel registrations...`),l=inspectExistingChannelRegistrations(n)),l}let u=r===void 0?(await inspectRegistrations()).disabledChannelReasons:void 0;c=await o.runAddToAgent({prompter:s,projectPath:n,state:c,presetChannels:r===void 0?void 0:[r],presetCreateSlackbot:i.yes?!0:void 0,disabledChannelReasons:u,force:i.force,validateSelectedChannels:async t=>{!t.includes(`web`)&&!t.includes(`slack`)||assertCanAddSelectedChannels(t,await inspectRegistrations())}}),c=await o.deployProject({prompter:s,projectPath:n,state:c}),s.outro(c.channels.length===0?`No channels added.`:`Channels added.`)}async function runChannelsAddCommand(e,t,r,i=defaultChannelsAddDependencies){if(!await isAshProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}try{await runAddChannelsFlow(t,r.kind===void 0?void 0:parseChannelKind(r.kind),r.options,i)}catch(t){if(t instanceof ChannelAddCancelledError)return;e.error(t instanceof Error?t.message:String(t)),process.exitCode=1}}async function runChannelsListCommand(e,t,i){if(!await isAshProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}let a=await listAuthoredChannels(t);if(i.json){e.log(JSON.stringify({channels:a},null,2));return}if(a.length===0){e.log("No channels defined. Run `ash channels add` to add one.");return}for(let t of a)e.log(t)}export{runChannelsAddCommand,runChannelsListCommand};
@@ -1 +1 @@
1
- import{getAdapterKind}from"#channel/adapter.js";import{SandboxKey,SessionIdKey}from"#context/keys.js";import{contextStorage}from"#context/container.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{getActiveRuntimeNode}from"#context/node.js";import{ensureSandboxAccess}from"#execution/sandbox/ensure.js";const sandboxProvider={key:SandboxKey,async create(e,t){let r=e.get(BundleKey);if(r===void 0)return;let i=getActiveRuntimeNode(e),a=i.sandboxRegistry,o=e.require(SessionIdKey);return{value:await ensureSandboxAccess({compiledArtifactsSource:r.compiledArtifactsSource,nodeId:i.nodeId,registry:a,runOnSession:async t=>await contextStorage.run(e,t),sessionId:o,state:t.sandboxState??null,tags:{agent:resolveTagAgentName({bundle:r,node:i}),channel:resolveTagChannelKind(e.get(ChannelKey)),sessionId:o}})}},async commit(e,t){let n=await e.captureState();return{...t,sandboxState:n}}};function resolveTagAgentName(e){let t=e.node,n=e.bundle;return t.agent?.config?.name??n.resolvedAgent?.config?.name??t.nodeId??`unknown`}function resolveTagChannelKind(t){return t===void 0?`unknown`:getAdapterKind(t)}export{sandboxProvider};
1
+ import{getAdapterKind}from"#channel/adapter.js";import{SandboxKey,SessionIdKey}from"#context/keys.js";import{contextStorage}from"#context/container.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{getActiveRuntimeNode}from"#context/node.js";import{ensureSandboxAccess}from"#execution/sandbox/ensure.js";const sandboxProvider={key:SandboxKey,async create(e,t){let r=e.get(BundleKey);if(r===void 0)return;let i=getActiveRuntimeNode(e),a=i.sandboxRegistry,o=e.require(SessionIdKey),s=e.get(ChannelKey),c=s?.state,l=c?.sandboxSessionId??o,u=c?.parentSandboxState;return{value:await ensureSandboxAccess({compiledArtifactsSource:r.compiledArtifactsSource,nodeId:i.nodeId,registry:a,runOnSession:async t=>await contextStorage.run(e,t),sessionId:l,state:t.sandboxState??u??null,tags:{agent:resolveTagAgentName({bundle:r,node:i}),channel:resolveTagChannelKind(s),sessionId:o}})}},async commit(e,t){let n=await e.captureState();return{...t,sandboxState:n}}};function resolveTagAgentName(e){let t=e.node,n=e.bundle;return t.agent?.config?.name??n.resolvedAgent?.config?.name??t.nodeId??`unknown`}function resolveTagChannelKind(t){return t===void 0?`unknown`:getAdapterKind(t)}export{sandboxProvider};
@@ -9,6 +9,6 @@ import type { RuntimeSubagentResultActionResult } from "#runtime/actions/types.j
9
9
  * Builds the success-shaped {@link RuntimeSubagentResultActionResult}.
10
10
  * Returns `undefined` for root sessions (no parent to notify).
11
11
  */
12
- export declare function createDelegatedSubagentSuccessResult(serializedContext: Record<string, unknown>, output: string): RuntimeSubagentResultActionResult | undefined;
12
+ export declare function createDelegatedSubagentSuccessResult(serializedContext: Record<string, unknown>, output: unknown): RuntimeSubagentResultActionResult | undefined;
13
13
  /** Failure-path mirror of {@link createDelegatedSubagentSuccessResult}. */
14
14
  export declare function createDelegatedSubagentErrorResult(serializedContext: Record<string, unknown>, error: unknown): RuntimeSubagentResultActionResult | undefined;
@@ -15,7 +15,7 @@ import type { DurableSessionState } from "#execution/durable-session-store.js";
15
15
  /** Discriminated union the driver workflow body dispatches on. */
16
16
  export type NextDriverAction = {
17
17
  readonly kind: "done";
18
- readonly output: string;
18
+ readonly output: unknown;
19
19
  readonly isError?: boolean;
20
20
  readonly sessionState: DurableSessionState;
21
21
  readonly serializedContext: Record<string, unknown>;
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{jsonSchema}from"ai";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{createToolLoopHarness}from"#harness/tool-loop.js";import{resolveCodeModeEnabled}from"#shared/code-mode.js";import{resolveRuntimeModelReference}from"#runtime/agent/resolve-model.js";import{findRegisteredRuntimeTool}from"#runtime/tools/registry.js";import{createToolCompactionHandler}from"#execution/tool-compaction.js";const log=createLogger(`execution.node-step`);function createExecutionNodeStep(e){let t=createRuntimeModelResolver(e.compiledArtifactsSource),n=createNodeHarnessTools({node:e.node}),r=createToolCompactionHandler(collectResolvedTools(e.node));return createToolLoopHarness({capabilities:e.capabilities,codeMode:resolveCodeModeEnabled(e.node.agent.config?.experimental?.codeMode),handleEvent:e.handleEvent,mode:e.mode,onCompaction:r,resolveModel:t,runtimeIdentity:buildRuntimeIdentity(e.node),tools:n})}function buildRuntimeIdentity(e){let t=resolveInstalledPackageInfo(),r={agentId:e.turnAgent.id,agentName:e.agent.config?.name,ashVersion:t.version,modelId:e.turnAgent.model.id},i=process.env.VERCEL_GIT_COMMIT_SHA?.trim(),a=process.env.VERCEL_GIT_COMMIT_REF?.trim(),o=process.env.VERCEL_DEPLOYMENT_CREATED_AT?.trim();return i||a||o?{...r,build:{deployedAt:o||void 0,gitBranch:a||void 0,gitSha:i||void 0}}:r}function createRuntimeModelResolver(e){return t=>resolveRuntimeModelReference(t,{compiledArtifactsSource:e})}function collectResolvedTools(e){return[...e.toolRegistry.toolsByName.values()].map(e=>e.definition)}function createNodeHarnessTools(e){let t=new Map;for(let n of e.node.turnAgent.tools){let r=resolveHarnessToolDefinition({node:e.node,tool:n});r!==null&&t.set(n.name,r)}return t}function resolveHarnessToolDefinition(e){if(e.tool.kind===`subagent`)return{description:e.tool.description??``,inputSchema:jsonSchema(e.tool.inputSchema??{}),name:e.tool.name,outputSchema:e.tool.outputSchema===void 0?void 0:jsonSchema(e.tool.outputSchema),runtimeAction:{kind:`subagent-call`,nodeId:e.tool.nodeId,subagentName:e.tool.name}};if(e.tool.kind===`remote`)return{description:e.tool.description??``,inputSchema:jsonSchema(e.tool.inputSchema??{}),name:e.tool.name,outputSchema:e.tool.outputSchema===void 0?void 0:jsonSchema(e.tool.outputSchema),runtimeAction:{kind:`remote-agent-call`,nodeId:e.tool.nodeId,remoteAgentName:e.tool.name,subagentName:e.tool.name}};let n=findRegisteredRuntimeTool(e.node.toolRegistry,e.tool.name);if(n===null)return log.warn(`declared tool is not registered — omitting from toolset`,{toolName:e.tool.name,nodeId:e.node.nodeId}),null;let i=n.definition,a=i.sourceId.startsWith(`ash:`),o=i.execute;return{approvalKey:i.approvalKey,description:i.description,execute:o===void 0?void 0:a?o:e=>o(e,buildCallbackContext()),inputSchema:i.inputStandardSchema??jsonSchema(i.inputSchema??{}),name:i.name,needsApproval:i.needsApproval,outputSchema:i.outputStandardSchema??maybeJsonSchema(i.outputSchema),toModelOutput:i.toModelOutput}}function maybeJsonSchema(e){return e===void 0?void 0:jsonSchema(e)}export{createExecutionNodeStep,createNodeHarnessTools};
1
+ import{createLogger}from"#internal/logging.js";import{jsonSchema}from"ai";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{createToolLoopHarness}from"#harness/tool-loop.js";import{resolveCodeModeEnabled}from"#shared/code-mode.js";import{resolveRuntimeModelReference}from"#runtime/agent/resolve-model.js";import{findRegisteredRuntimeTool}from"#runtime/tools/registry.js";import{SUBAGENT_TOOL_INPUT_SCHEMA}from"#runtime/subagents/registry.js";import{createToolCompactionHandler}from"#execution/tool-compaction.js";const log=createLogger(`execution.node-step`);function createExecutionNodeStep(e){let t=createRuntimeModelResolver(e.compiledArtifactsSource),n=createNodeHarnessTools({node:e.node}),r=createToolCompactionHandler(collectResolvedTools(e.node));return createToolLoopHarness({capabilities:e.capabilities,codeMode:resolveCodeModeEnabled(e.node.agent.config?.experimental?.codeMode),handleEvent:e.handleEvent,mode:e.mode,onCompaction:r,resolveModel:t,runtimeIdentity:buildRuntimeIdentity(e.node),tools:n})}function buildRuntimeIdentity(e){let t=resolveInstalledPackageInfo(),r={agentId:e.turnAgent.id,agentName:e.agent.config?.name,ashVersion:t.version,modelId:e.turnAgent.model.id},i=process.env.VERCEL_GIT_COMMIT_SHA?.trim(),a=process.env.VERCEL_GIT_COMMIT_REF?.trim(),o=process.env.VERCEL_DEPLOYMENT_CREATED_AT?.trim();return i||a||o?{...r,build:{deployedAt:o||void 0,gitBranch:a||void 0,gitSha:i||void 0}}:r}function createRuntimeModelResolver(e){return t=>resolveRuntimeModelReference(t,{compiledArtifactsSource:e})}function collectResolvedTools(e){return[...e.toolRegistry.toolsByName.values()].map(e=>e.definition)}function createNodeHarnessTools(e){let n=new Map;for(let t of e.node.turnAgent.tools){let r=resolveHarnessToolDefinition({node:e.node,tool:t});r!==null&&n.set(t.name,r)}return n.has(`agent`)||n.set(`agent`,{description:`Run a copy of this agent as a subagent with a focused task. The child agent has the same tools and instructions but a fresh conversation history.`,inputSchema:jsonSchema(SUBAGENT_TOOL_INPUT_SCHEMA),name:`agent`,runtimeAction:{kind:`subagent-call`,nodeId:e.node.nodeId,subagentName:`agent`}}),n}function resolveHarnessToolDefinition(e){if(e.tool.kind===`subagent`)return{description:e.tool.description??``,inputSchema:jsonSchema(e.tool.inputSchema??{}),name:e.tool.name,outputSchema:e.tool.outputSchema===void 0?void 0:jsonSchema(e.tool.outputSchema),runtimeAction:{kind:`subagent-call`,nodeId:e.tool.nodeId,subagentName:e.tool.name}};if(e.tool.kind===`remote`)return{description:e.tool.description??``,inputSchema:jsonSchema(e.tool.inputSchema??{}),name:e.tool.name,outputSchema:e.tool.outputSchema===void 0?void 0:jsonSchema(e.tool.outputSchema),runtimeAction:{kind:`remote-agent-call`,nodeId:e.tool.nodeId,remoteAgentName:e.tool.name,subagentName:e.tool.name}};let n=findRegisteredRuntimeTool(e.node.toolRegistry,e.tool.name);if(n===null)return log.warn(`declared tool is not registered — omitting from toolset`,{toolName:e.tool.name,nodeId:e.node.nodeId}),null;let i=n.definition,a=i.sourceId.startsWith(`ash:`),o=i.execute;return{approvalKey:i.approvalKey,description:i.description,execute:o===void 0?void 0:a?o:e=>o(e,buildCallbackContext()),inputSchema:i.inputStandardSchema??jsonSchema(i.inputSchema??{}),name:i.name,needsApproval:i.needsApproval,outputSchema:i.outputStandardSchema??maybeJsonSchema(i.outputSchema),toModelOutput:i.toModelOutput}}function maybeJsonSchema(e){return e===void 0?void 0:jsonSchema(e)}export{createExecutionNodeStep,createNodeHarnessTools};
@@ -10,7 +10,7 @@
10
10
  */
11
11
  export declare function fireSessionCallbackStep(input: {
12
12
  readonly error?: unknown;
13
- readonly output?: string;
13
+ readonly output?: unknown;
14
14
  readonly serializedContext: Record<string, unknown>;
15
15
  readonly status: "completed" | "failed";
16
16
  }): Promise<void>;
@@ -41,12 +41,14 @@ export interface CreateSessionInput {
41
41
  export declare function createSession(input: CreateSessionInput): HarnessSession;
42
42
  /**
43
43
  * Refreshes a session with the latest `turnAgent` — replaces model/tool
44
- * metadata and recalculates compaction thresholds; preserves history,
45
- * state, and the session-start `agent.system` prompt.
44
+ * metadata and recalculates compaction thresholds; preserves history and
45
+ * state. Production callers keep the session-start `agent.system` prompt,
46
+ * while dev HMR callers can opt into refreshing it from authored source.
46
47
  */
47
48
  export declare function refreshSessionFromTurnAgent(input: {
48
49
  readonly session: HarnessSession;
49
50
  readonly turnAgent: RuntimeTurnAgent;
51
+ readonly refreshSystemPrompt?: boolean;
50
52
  readonly compactionOverrides?: {
51
53
  readonly thresholdPercent?: number;
52
54
  };
@@ -1,3 +1,5 @@
1
1
  function createCompactionConfig(e={}){let t=e.thresholdPercent??.9,n={recentWindowSize:10,threshold:e.contextWindowTokens===void 0?1e5:Math.max(1,Math.floor(e.contextWindowTokens*t))};return e.lastKnownInputTokens===void 0?n:{...n,lastKnownInputTokens:e.lastKnownInputTokens,lastKnownPromptMessageCount:e.lastKnownPromptMessageCount}}function createSession(e){let{turnAgent:t}=e,n=createSessionToolDefinitions(t),r={agent:{compactionModelReference:t.compactionModel,modelReference:t.model,system:t.instructions.join(`
2
2
 
3
- `),tools:n},compaction:createCompactionConfig({contextWindowTokens:t.model.contextWindowTokens,thresholdPercent:e.compactionOverrides?.thresholdPercent}),continuationToken:e.continuationToken,history:[],sessionId:e.sessionId};return e.rootSessionId!==void 0&&(r.rootSessionId=e.rootSessionId),e.outputSchema!==void 0&&(r.outputSchema=e.outputSchema),r}function refreshSessionFromTurnAgent(e){return{...e.session,agent:{compactionModelReference:e.turnAgent.compactionModel,modelReference:e.turnAgent.model,system:e.session.agent.system,tools:createSessionToolDefinitions(e.turnAgent)},compaction:createCompactionConfig({contextWindowTokens:e.turnAgent.model.contextWindowTokens,lastKnownInputTokens:e.session.compaction.lastKnownInputTokens,lastKnownPromptMessageCount:e.session.compaction.lastKnownPromptMessageCount,thresholdPercent:e.compactionOverrides?.thresholdPercent})}}function mintSubagentContinuationToken(e){return`subagent:${e??crypto.randomUUID()}`}function projectToDurableSession(e){let t={agent:{system:e.agent.system},continuationToken:e.continuationToken,history:e.history,sessionId:e.sessionId};return(e.compaction.lastKnownInputTokens!==void 0||e.compaction.lastKnownPromptMessageCount!==void 0)&&(t.compaction={lastKnownInputTokens:e.compaction.lastKnownInputTokens,lastKnownPromptMessageCount:e.compaction.lastKnownPromptMessageCount}),e.rootSessionId!==void 0&&(t.rootSessionId=e.rootSessionId),e.outputSchema!==void 0&&(t.outputSchema=e.outputSchema),e.sandboxState!==void 0&&(t.sandboxState=e.sandboxState),e.state!==void 0&&(t.state=e.state),t}function hydrateDurableSession(e){let{durable:t,turnAgent:n}=e,r=createSessionToolDefinitions(n),i={agent:{compactionModelReference:n.compactionModel,modelReference:n.model,system:t.agent.system,tools:r},compaction:createCompactionConfig({contextWindowTokens:n.model.contextWindowTokens,lastKnownInputTokens:t.compaction?.lastKnownInputTokens,lastKnownPromptMessageCount:t.compaction?.lastKnownPromptMessageCount,thresholdPercent:e.compactionOverrides?.thresholdPercent}),continuationToken:t.continuationToken,history:t.history,sessionId:t.sessionId};return t.rootSessionId!==void 0&&(i.rootSessionId=t.rootSessionId),t.outputSchema!==void 0&&(i.outputSchema=t.outputSchema),t.sandboxState!==void 0&&(i.sandboxState=t.sandboxState),t.state!==void 0&&(i.state=t.state),i}function createSessionToolDefinitions(e){return e.tools.map(e=>({description:e.description??``,inputSchema:e.inputSchema,name:e.name,outputSchema:e.outputSchema}))}export{createCompactionConfig,createSession,hydrateDurableSession,mintSubagentContinuationToken,projectToDurableSession,refreshSessionFromTurnAgent};
3
+ `),tools:n},compaction:createCompactionConfig({contextWindowTokens:t.model.contextWindowTokens,thresholdPercent:e.compactionOverrides?.thresholdPercent}),continuationToken:e.continuationToken,history:[],sessionId:e.sessionId};return e.rootSessionId!==void 0&&(r.rootSessionId=e.rootSessionId),e.outputSchema!==void 0&&(r.outputSchema=e.outputSchema),r}function refreshSessionFromTurnAgent(e){return{...e.session,agent:{compactionModelReference:e.turnAgent.compactionModel,modelReference:e.turnAgent.model,system:e.refreshSystemPrompt===!0?e.turnAgent.instructions.join(`
4
+
5
+ `):e.session.agent.system,tools:createSessionToolDefinitions(e.turnAgent)},compaction:createCompactionConfig({contextWindowTokens:e.turnAgent.model.contextWindowTokens,lastKnownInputTokens:e.session.compaction.lastKnownInputTokens,lastKnownPromptMessageCount:e.session.compaction.lastKnownPromptMessageCount,thresholdPercent:e.compactionOverrides?.thresholdPercent})}}function mintSubagentContinuationToken(e){return`subagent:${e??crypto.randomUUID()}`}function projectToDurableSession(e){let t={agent:{system:e.agent.system},continuationToken:e.continuationToken,history:e.history,sessionId:e.sessionId};return(e.compaction.lastKnownInputTokens!==void 0||e.compaction.lastKnownPromptMessageCount!==void 0)&&(t.compaction={lastKnownInputTokens:e.compaction.lastKnownInputTokens,lastKnownPromptMessageCount:e.compaction.lastKnownPromptMessageCount}),e.rootSessionId!==void 0&&(t.rootSessionId=e.rootSessionId),e.outputSchema!==void 0&&(t.outputSchema=e.outputSchema),e.sandboxState!==void 0&&(t.sandboxState=e.sandboxState),e.state!==void 0&&(t.state=e.state),t}function hydrateDurableSession(e){let{durable:t,turnAgent:n}=e,r=createSessionToolDefinitions(n),i={agent:{compactionModelReference:n.compactionModel,modelReference:n.model,system:t.agent.system,tools:r},compaction:createCompactionConfig({contextWindowTokens:n.model.contextWindowTokens,lastKnownInputTokens:t.compaction?.lastKnownInputTokens,lastKnownPromptMessageCount:t.compaction?.lastKnownPromptMessageCount,thresholdPercent:e.compactionOverrides?.thresholdPercent}),continuationToken:t.continuationToken,history:t.history,sessionId:t.sessionId};return t.rootSessionId!==void 0&&(i.rootSessionId=t.rootSessionId),t.outputSchema!==void 0&&(i.outputSchema=t.outputSchema),t.sandboxState!==void 0&&(i.sandboxState=t.sandboxState),t.state!==void 0&&(i.state=t.state),i}function createSessionToolDefinitions(e){return e.tools.map(e=>({description:e.description??``,inputSchema:e.inputSchema,name:e.name,outputSchema:e.outputSchema}))}export{createCompactionConfig,createSession,hydrateDurableSession,mintSubagentContinuationToken,projectToDurableSession,refreshSessionFromTurnAgent};
@@ -1 +1 @@
1
- import{mintSubagentContinuationToken}from"#execution/session.js";import{SUBAGENT_ADAPTER_KIND}from"#execution/subagent-adapter.js";import{formatSubagentInvocation}from"#execution/subagent-invocation.js";function buildSubagentRunInput(n){let{action:r,auth:i,batchEvent:a,capabilities:o,channelMetadata:s,initiatorAuth:c,session:l}=n,u=mintSubagentContinuationToken(`${l.sessionId}:${r.callId}`),d=l.rootSessionId??l.sessionId;return{childContinuationToken:u,runInput:{adapter:{kind:SUBAGENT_ADAPTER_KIND,state:{callId:r.callId,parentContinuationToken:l.continuationToken,parentSessionId:l.sessionId,subagentName:r.subagentName}},auth:i,capabilities:o,channelMetadata:s,continuationToken:u,initiatorAuth:c,input:{message:formatSubagentCallInputMessage(r),outputSchema:r.input.outputSchema},mode:`task`,parent:{callId:r.callId,rootSessionId:d,sessionId:l.sessionId,turn:{id:a.turnId,sequence:a.sequence}}}}}function formatSubagentCallInputMessage(e){let{message:t}=e.input;return formatSubagentInvocation({description:e.description,message:t,name:e.subagentName}).message}export{buildSubagentRunInput};
1
+ import{mintSubagentContinuationToken}from"#execution/session.js";import{SUBAGENT_ADAPTER_KIND}from"#execution/subagent-adapter.js";import{formatSubagentInvocation}from"#execution/subagent-invocation.js";function buildSubagentRunInput(n){let{action:r,auth:i,batchEvent:a,capabilities:o,channelMetadata:s,initiatorAuth:c,session:l}=n,u=mintSubagentContinuationToken(`${l.sessionId}:${r.callId}`),d=l.rootSessionId??l.sessionId;return{childContinuationToken:u,runInput:{adapter:{kind:SUBAGENT_ADAPTER_KIND,state:{callId:r.callId,parentContinuationToken:l.continuationToken,parentSessionId:l.sessionId,subagentName:r.subagentName,...r.subagentName===`agent`&&l.sandboxState?{parentSandboxState:l.sandboxState,sandboxSessionId:l.sessionId}:{}}},auth:i,capabilities:o,channelMetadata:s,continuationToken:u,initiatorAuth:c,input:{message:formatSubagentCallInputMessage(r),outputSchema:r.input.outputSchema},mode:`task`,parent:{callId:r.callId,rootSessionId:d,sessionId:l.sessionId,turn:{id:a.turnId,sequence:a.sequence}}}}}function formatSubagentCallInputMessage(e){let{message:t}=e.input;return formatSubagentInvocation({description:e.description,message:t,name:e.subagentName}).message}export{buildSubagentRunInput};
@@ -9,7 +9,7 @@ export interface WorkflowEntryInput {
9
9
  readonly serializedContext: Record<string, unknown>;
10
10
  }
11
11
  export interface WorkflowEntryResult {
12
- readonly output: string;
12
+ readonly output: unknown;
13
13
  }
14
14
  /**
15
15
  * Long-lived workflow entrypoint. Handles both root sessions and
@@ -15,7 +15,7 @@ import { type TurnWorkflowInput } from "#execution/turn-workflow.js";
15
15
  */
16
16
  export type DurableStepResult = {
17
17
  readonly action: "continue" | "done";
18
- readonly output?: string;
18
+ readonly output?: unknown;
19
19
  readonly isError?: boolean;
20
20
  readonly serializedContext: Record<string, unknown>;
21
21
  readonly sessionState: DurableSessionState;
@@ -1 +1 @@
1
- import{createLogger,formatError}from"#internal/logging.js";import{callAdapterEventHandler,defaultDeliverResult}from"#channel/adapter.js";import{AuthKey,CapabilitiesKey,ContinuationTokenKey,ModeKey}from"#context/keys.js";import{createAuthorizationCompletedEvent,createSessionFailedEvent,encodeMessageStreamEvent,timestampHandleMessageStreamEvent}from"#protocol/message.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{createDurableSessionState,readDurableSession}from"#execution/durable-session-store.js";import{hydrateDurableSession,refreshSessionFromTurnAgent}from"#execution/session.js";import{buildTurnAttributes,readRootSessionId}from"#execution/ash-workflow-attributes.js";import{setAshAttributes}from"#runtime/attributes/emit.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{getPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{createWorkflowRuntime,startWorkflowPreferLatest}from"#execution/workflow-runtime.js";import{getHarnessEmissionState}from"#harness/emission.js";import{upsertProxyInputRequests}from"#harness/proxy-input-requests.js";import{setChannelContext}from"#execution/channel-context.js";import{coalesceTurnInputs}from"#harness/messages.js";import{dispatchStreamEventHooks}from"#context/hook-lifecycle.js";import{dispatchDynamicInstructionEvent}from"#context/dynamic-instruction-lifecycle.js";import{dispatchDynamicSkillEvent}from"#context/dynamic-skill-lifecycle.js";import{dispatchDynamicToolEvent}from"#context/dynamic-tool-lifecycle.js";import{runStep,withContextScope}from"#context/run-step.js";import{hasPendingInputBatch}from"#harness/input-requests.js";import{getRuntimeActionRequestKey}from"#runtime/actions/keys.js";import{CallbackBaseUrlKey,PendingAuthorizationResultKey,getPendingAuthorization}from"#harness/authorization.js";import{createExecutionNodeStep}from"#execution/node-step.js";import{emitProxiedInputRequest,routeDeliverPayload}from"#execution/subagent-hitl-proxy.js";import{turnWorkflow}from"#execution/turn-workflow.js";async function turnStep(e){"use step";await setAshAttributes(buildTurnAttributes({parentSessionId:e.sessionState.sessionId,rootSessionId:readRootSessionId(e.serializedContext)??e.sessionState.sessionId}));let t=await readDurableSession(e.sessionState),o=await deserializeContext(e.serializedContext),l=o.require(ChannelKey),f=o.require(BundleKey),p=hydrateDurableSession({compactionOverrides:{thresholdPercent:f.resolvedAgent.config.compaction?.thresholdPercent},durable:t,turnAgent:f.turnAgent});try{let{getWorkflowMetadata:e}=await import(`#compiled/@workflow/core/index.js`),t=e();typeof t.url==`string`&&o.set(CallbackBaseUrlKey,t.url.replace(/\/$/,``))}catch{}let m=getPendingAuthorization(t.state),h;if(m&&e.input?.kind===`deliver`){let t=[],n=[];for(let r of e.input.payloads){let e=r.authorizationCallback;if(e){let n=m.challenges.find(t=>t.name===e.connectionName);n&&t.push({name:n.name,state:n.state,callback:e.request,hookUrl:n.hookUrl})}else n.push(r)}t.length>0&&(o.set(PendingAuthorizationResultKey,t),h=t.map(e=>e.name),e=n.length>0?{...e,input:{...e.input,payloads:n}}:{...e,input:void 0})}e.input?.kind===`deliver`&&e.input.auth!==void 0&&o.set(AuthKey,e.input.auth??null);let g=buildAdapterContext(l,o),_;if(e.input?.kind===`deliver`){let t=[];for(let n of e.input.payloads){let e=l.deliver?await l.deliver(n,g):defaultDeliverResult(n);e!=null&&t.push(e)}_=t.length===0?void 0:t.reduce(coalesceTurnInputs)}else e.input?.kind===`runtime-action-result`&&(_={runtimeActionResults:e.input.results});if(e.input?.kind===`deliver`&&setChannelContext(o,{...l,state:{...g.state}}),e.input?.kind===`deliver`&&_===void 0){let t=reconcileSessionContinuationToken(o,p),n=serializeContext(o),r=t===p?e.sessionState:createDurableSessionState({session:t});return{action:`park`,...derivePendingState(t),serializedContext:n,sessionState:r}}let v=e.parentWritable.getWriter(),y=f.hookRegistry,b=f.resolvedAgent.dynamicInstructionsResolvers??[],x=f.resolvedAgent.dynamicSkillResolvers??[],S=f.resolvedAgent.dynamicToolResolvers??[],emit=async e=>{let t=await callAdapterEventHandler(l,e,g);return setChannelContext(o,{...l,state:{...g.state}}),await v.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(t))),t},handleEvent=async(e,t)=>{let n=await emit(e);await dispatchStreamEventHooks({ctx:o,registry:y,event:n}),await dispatchDynamicToolEvent({ctx:o,resolvers:S,event:n,messages:t??[]}),await dispatchDynamicSkillEvent({ctx:o,resolvers:x,event:n,messages:t??[]}),await dispatchDynamicInstructionEvent({ctx:o,resolvers:b,event:n,messages:t??[]})},C=o.require(ModeKey),w=await runStep(o,p,async e=>{let t=resolveEffectiveOutputSchema({agentOutputSchema:f.turnAgent.outputSchema,input:_,mode:C,session:e});if(h){let e=getHarnessEmissionState(t.state);for(let t of h)await handleEvent(createAuthorizationCompletedEvent({name:t,outcome:`authorized`,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId}))}let n=o.get(CapabilitiesKey);return(async(e,t)=>{let r=refreshSessionFromTurnAgent({compactionOverrides:{thresholdPercent:f.resolvedAgent.config.compaction?.thresholdPercent},session:e,turnAgent:f.turnAgent});return createExecutionNodeStep({capabilities:n,compiledArtifactsSource:f.compiledArtifactsSource,createRuntime:createWorkflowRuntime,handleEvent,mode:C,node:f.graph.root})(r,t)})(t,_)}),T=reconcileSessionContinuationToken(o,w.session),E=serializeContext(o);w={...w,session:T};let D=createDurableSessionState({session:w.session});return w.next!==null&&typeof w.next==`object`&&`done`in w.next?(await v.close(),{action:`done`,output:w.next.output,isError:w.next.isError,serializedContext:E,sessionState:D}):w.next===null?(v.releaseLock(),{action:`park`,...derivePendingState(w.session),serializedContext:E,sessionState:D}):(v.releaseLock(),{action:`continue`,serializedContext:E,sessionState:D})}function derivePendingState(e){let t=getPendingRuntimeActionBatch(e.state),n=getPendingAuthorization(e.state),r={authorizationNames:n?.challenges.map(e=>e.name),hasPendingAuthorization:n!==void 0,hasPendingInputBatch:hasPendingInputBatch(e.state)};return t===void 0?r:{...r,pendingRuntimeActionKeys:t.actions.map(e=>getRuntimeActionRequestKey(e))}}function reconcileSessionContinuationToken(e,t){let n=e.get(ContinuationTokenKey);return n===void 0||n===t.continuationToken?t:{...t,continuationToken:n}}function resolveEffectiveOutputSchema(e){let{agentOutputSchema:t,input:n,mode:r,session:i}=e;return n?.outputSchema===void 0?r===`task`&&i.outputSchema===void 0&&t!==void 0?{...i,outputSchema:t}:i:{...i,outputSchema:n.outputSchema}}const log=createLogger(`execution.workflow-entry`);async function emitTerminalSessionFailureStep(e){"use step";let r=formatError(e.error),i=typeof r.name==`string`?r.name:`WORKFLOW_EXECUTION_FAILED`,a=typeof r.message==`string`?r.message:String(e.error),o=e.serializedContext[`ash.sessionId`]??``;log.error(`workflow loop threw — emitting terminal session.failed`,{sessionId:o,errorId:typeof r.errorId==`string`?r.errorId:void 0,code:i,message:a,detail:typeof r.detail==`string`?r.detail:void 0});let s=createSessionFailedEvent({code:i,details:r,message:a,sessionId:o});try{let t=await deserializeContext(e.serializedContext),r=t.get(ChannelKey);r!==void 0&&await callAdapterEventHandler(r,s,buildAdapterContext(r,t))}catch(e){log.error(`adapter failed to handle terminal session.failed event`,{errorId:typeof r.errorId==`string`?r.errorId:void 0,sessionId:o,error:e})}try{let t=e.parentWritable.getWriter();try{await t.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(s)))}finally{t.releaseLock()}}catch(e){log.error(`failed to write terminal session.failed event to durable stream`,{errorId:typeof r.errorId==`string`?r.errorId:void 0,sessionId:o,error:e})}}async function runProxyInputRequestStep(e){"use step";let t=await readDurableSession(e.sessionState),r=await deserializeContext(e.serializedContext),i=r.require(ChannelKey),a=buildAdapterContext(i,r),o=r.require(ModeKey),c=r.require(BundleKey),l=hydrateDurableSession({compactionOverrides:{thresholdPercent:c.resolvedAgent.config.compaction?.thresholdPercent},durable:t,turnAgent:c.turnAgent}),u=e.parentWritable.getWriter(),d;try{let emit=async e=>{let t=await callAdapterEventHandler(i,e,a);await u.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(t)))};d=await withContextScope(r,l,async t=>{let n=await emitProxiedInputRequest({emit,hookPayload:e.hookPayload,mode:o,session:t});return{result:n.entries,session:n.session}})}finally{u.releaseLock()}return setChannelContext(r,{...i,state:{...a.state}}),{serializedContext:serializeContext(r),sessionState:createDurableSessionState({session:reconcileSessionContinuationToken(r,upsertProxyInputRequests({entries:d.result,forChildContinuationToken:e.hookPayload.childContinuationToken,session:d.session}))})}}async function routeProxiedDeliverStep(e){"use step";let t=await readDurableSession(e.sessionState),n=routeDeliverPayload({payload:e.payload,state:t.state}),{resumeHook:r}=await import(`#compiled/@workflow/core/runtime.js`);for(let t of n.forChildren)await r(t.childContinuationToken,{auth:e.auth,kind:`deliver`,payloads:[t.payload]});return{remainder:n.forSelf}}async function dispatchTurnStep(e){"use step";return{runId:(await startWorkflowPreferLatest(turnWorkflow,[e])).runId}}export{dispatchTurnStep,emitTerminalSessionFailureStep,reconcileSessionContinuationToken,resolveEffectiveOutputSchema,routeProxiedDeliverStep,runProxyInputRequestStep,turnStep};
1
+ import{createLogger,formatError}from"#internal/logging.js";import{callAdapterEventHandler,defaultDeliverResult}from"#channel/adapter.js";import{AuthKey,CapabilitiesKey,ContinuationTokenKey,ModeKey}from"#context/keys.js";import{createAuthorizationCompletedEvent,createSessionFailedEvent,encodeMessageStreamEvent,timestampHandleMessageStreamEvent}from"#protocol/message.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{createDurableSessionState,readDurableSession}from"#execution/durable-session-store.js";import{hydrateDurableSession,refreshSessionFromTurnAgent}from"#execution/session.js";import{buildTurnAttributes,readRootSessionId}from"#execution/ash-workflow-attributes.js";import{setAshAttributes}from"#runtime/attributes/emit.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{getPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{createWorkflowRuntime,startWorkflowPreferLatest}from"#execution/workflow-runtime.js";import{getHarnessEmissionState}from"#harness/emission.js";import{upsertProxyInputRequests}from"#harness/proxy-input-requests.js";import{setChannelContext}from"#execution/channel-context.js";import{coalesceTurnInputs}from"#harness/messages.js";import{dispatchStreamEventHooks}from"#context/hook-lifecycle.js";import{dispatchDynamicInstructionEvent}from"#context/dynamic-instruction-lifecycle.js";import{dispatchDynamicSkillEvent}from"#context/dynamic-skill-lifecycle.js";import{dispatchDynamicToolEvent}from"#context/dynamic-tool-lifecycle.js";import{runStep,withContextScope}from"#context/run-step.js";import{hasPendingInputBatch}from"#harness/input-requests.js";import{getRuntimeActionRequestKey}from"#runtime/actions/keys.js";import{CallbackBaseUrlKey,PendingAuthorizationResultKey,getPendingAuthorization}from"#harness/authorization.js";import{createExecutionNodeStep}from"#execution/node-step.js";import{emitProxiedInputRequest,routeDeliverPayload}from"#execution/subagent-hitl-proxy.js";import{turnWorkflow}from"#execution/turn-workflow.js";async function turnStep(e){"use step";await setAshAttributes(buildTurnAttributes({parentSessionId:e.sessionState.sessionId,rootSessionId:readRootSessionId(e.serializedContext)??e.sessionState.sessionId}));let t=await readDurableSession(e.sessionState),o=await deserializeContext(e.serializedContext),l=o.require(ChannelKey),f=o.require(BundleKey),p=hydrateDurableSession({compactionOverrides:{thresholdPercent:f.resolvedAgent.config.compaction?.thresholdPercent},durable:t,turnAgent:f.turnAgent});try{let{getWorkflowMetadata:e}=await import(`#compiled/@workflow/core/index.js`),t=e();typeof t.url==`string`&&o.set(CallbackBaseUrlKey,t.url.replace(/\/$/,``))}catch{}let m=getPendingAuthorization(t.state),h;if(m&&e.input?.kind===`deliver`){let t=[],n=[];for(let r of e.input.payloads){let e=r.authorizationCallback;if(e){let n=m.challenges.find(t=>t.name===e.connectionName);n&&t.push({name:n.name,state:n.state,callback:e.request,hookUrl:n.hookUrl})}else n.push(r)}t.length>0&&(o.set(PendingAuthorizationResultKey,t),h=t.map(e=>e.name),e=n.length>0?{...e,input:{...e.input,payloads:n}}:{...e,input:void 0})}e.input?.kind===`deliver`&&e.input.auth!==void 0&&o.set(AuthKey,e.input.auth??null);let g=buildAdapterContext(l,o),_;if(e.input?.kind===`deliver`){let t=[];for(let n of e.input.payloads){let e=l.deliver?await l.deliver(n,g):defaultDeliverResult(n);e!=null&&t.push(e)}_=t.length===0?void 0:t.reduce(coalesceTurnInputs)}else e.input?.kind===`runtime-action-result`&&(_={runtimeActionResults:e.input.results});if(e.input?.kind===`deliver`&&setChannelContext(o,{...l,state:{...g.state}}),e.input?.kind===`deliver`&&_===void 0){let t=reconcileSessionContinuationToken(o,p),n=serializeContext(o),r=t===p?e.sessionState:createDurableSessionState({session:t});return{action:`park`,...derivePendingState(t),serializedContext:n,sessionState:r}}let v=e.parentWritable.getWriter(),y=f.hookRegistry,b=f.resolvedAgent.dynamicInstructionsResolvers??[],x=f.resolvedAgent.dynamicSkillResolvers??[],S=f.resolvedAgent.dynamicToolResolvers??[],emit=async e=>{let t=await callAdapterEventHandler(l,e,g);return setChannelContext(o,{...l,state:{...g.state}}),await v.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(t))),t},handleEvent=async(e,t)=>{let n=await emit(e);await dispatchStreamEventHooks({ctx:o,registry:y,event:n}),await dispatchDynamicToolEvent({ctx:o,resolvers:S,event:n,messages:t??[]}),await dispatchDynamicSkillEvent({ctx:o,resolvers:x,event:n,messages:t??[]}),await dispatchDynamicInstructionEvent({ctx:o,resolvers:b,event:n,messages:t??[]})},C=o.require(ModeKey),w=await runStep(o,p,async e=>{let t=resolveEffectiveOutputSchema({agentOutputSchema:f.turnAgent.outputSchema,input:_,mode:C,session:e});if(h){let e=getHarnessEmissionState(t.state);for(let t of h)await handleEvent(createAuthorizationCompletedEvent({name:t,outcome:`authorized`,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId}))}let n=o.get(CapabilitiesKey);return(async(e,t)=>{let r=refreshSessionFromTurnAgent({compactionOverrides:{thresholdPercent:f.resolvedAgent.config.compaction?.thresholdPercent},refreshSystemPrompt:shouldRefreshSystemPromptFromTurnAgent(f.compiledArtifactsSource),session:e,turnAgent:f.turnAgent});return createExecutionNodeStep({capabilities:n,compiledArtifactsSource:f.compiledArtifactsSource,createRuntime:createWorkflowRuntime,handleEvent,mode:C,node:f.graph.root})(r,t)})(t,_)}),T=reconcileSessionContinuationToken(o,w.session),E=serializeContext(o);w={...w,session:T};let D=createDurableSessionState({session:w.session});return w.next!==null&&typeof w.next==`object`&&`done`in w.next?(await v.close(),{action:`done`,output:w.next.output,isError:w.next.isError,serializedContext:E,sessionState:D}):w.next===null?(v.releaseLock(),{action:`park`,...derivePendingState(w.session),serializedContext:E,sessionState:D}):(v.releaseLock(),{action:`continue`,serializedContext:E,sessionState:D})}function shouldRefreshSystemPromptFromTurnAgent(e){return e.kind===`disk`&&e.moduleMapLoaderPath!==void 0}function derivePendingState(e){let t=getPendingRuntimeActionBatch(e.state),n=getPendingAuthorization(e.state),r={authorizationNames:n?.challenges.map(e=>e.name),hasPendingAuthorization:n!==void 0,hasPendingInputBatch:hasPendingInputBatch(e.state)};return t===void 0?r:{...r,pendingRuntimeActionKeys:t.actions.map(e=>getRuntimeActionRequestKey(e))}}function reconcileSessionContinuationToken(e,t){let n=e.get(ContinuationTokenKey);return n===void 0||n===t.continuationToken?t:{...t,continuationToken:n}}function resolveEffectiveOutputSchema(e){let{agentOutputSchema:t,input:n,mode:r,session:i}=e;return n?.outputSchema===void 0?r===`task`&&i.outputSchema===void 0&&t!==void 0?{...i,outputSchema:t}:i:{...i,outputSchema:n.outputSchema}}const log=createLogger(`execution.workflow-entry`);async function emitTerminalSessionFailureStep(e){"use step";let r=formatError(e.error),i=typeof r.name==`string`?r.name:`WORKFLOW_EXECUTION_FAILED`,a=typeof r.message==`string`?r.message:String(e.error),o=e.serializedContext[`ash.sessionId`]??``;log.error(`workflow loop threw — emitting terminal session.failed`,{sessionId:o,errorId:typeof r.errorId==`string`?r.errorId:void 0,code:i,message:a,detail:typeof r.detail==`string`?r.detail:void 0});let s=createSessionFailedEvent({code:i,details:r,message:a,sessionId:o});try{let t=await deserializeContext(e.serializedContext),r=t.get(ChannelKey);r!==void 0&&await callAdapterEventHandler(r,s,buildAdapterContext(r,t))}catch(e){log.error(`adapter failed to handle terminal session.failed event`,{errorId:typeof r.errorId==`string`?r.errorId:void 0,sessionId:o,error:e})}try{let t=e.parentWritable.getWriter();try{await t.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(s)))}finally{t.releaseLock()}}catch(e){log.error(`failed to write terminal session.failed event to durable stream`,{errorId:typeof r.errorId==`string`?r.errorId:void 0,sessionId:o,error:e})}}async function runProxyInputRequestStep(e){"use step";let t=await readDurableSession(e.sessionState),r=await deserializeContext(e.serializedContext),i=r.require(ChannelKey),a=buildAdapterContext(i,r),o=r.require(ModeKey),c=r.require(BundleKey),l=hydrateDurableSession({compactionOverrides:{thresholdPercent:c.resolvedAgent.config.compaction?.thresholdPercent},durable:t,turnAgent:c.turnAgent}),u=e.parentWritable.getWriter(),d;try{let emit=async e=>{let t=await callAdapterEventHandler(i,e,a);await u.write(encodeMessageStreamEvent(timestampHandleMessageStreamEvent(t)))};d=await withContextScope(r,l,async t=>{let n=await emitProxiedInputRequest({emit,hookPayload:e.hookPayload,mode:o,session:t});return{result:n.entries,session:n.session}})}finally{u.releaseLock()}return setChannelContext(r,{...i,state:{...a.state}}),{serializedContext:serializeContext(r),sessionState:createDurableSessionState({session:reconcileSessionContinuationToken(r,upsertProxyInputRequests({entries:d.result,forChildContinuationToken:e.hookPayload.childContinuationToken,session:d.session}))})}}async function routeProxiedDeliverStep(e){"use step";let t=await readDurableSession(e.sessionState),n=routeDeliverPayload({payload:e.payload,state:t.state}),{resumeHook:r}=await import(`#compiled/@workflow/core/runtime.js`);for(let t of n.forChildren)await r(t.childContinuationToken,{auth:e.auth,kind:`deliver`,payloads:[t.payload]});return{remainder:n.forSelf}}async function dispatchTurnStep(e){"use step";return{runId:(await startWorkflowPreferLatest(turnWorkflow,[e])).runId}}export{dispatchTurnStep,emitTerminalSessionFailureStep,reconcileSessionContinuationToken,resolveEffectiveOutputSchema,routeProxiedDeliverStep,runProxyInputRequestStep,turnStep};
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import"ai";import{contextStorage}from"#context/container.js";import{CODE_MODE_TOOL_NAME,loadCodeModeModule}from"#shared/code-mode.js";import{isAuthorizationSignal}from"#harness/authorization.js";import{CODE_MODE_CONNECTION_AUTH_INTERRUPT_KIND,markCodeModeToolExecutionOptions,toCodeModeConnectionAuthArgs}from"#runtime/framework-tools/code-mode-connection-auth.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{buildToolSet}from"#harness/tools.js";const log=createLogger(`harness.code-mode`);function createAshCodeModeOptions(e={}){let t={approval:{mode:`interrupt`}};return e.lifecycle!==void 0&&(t.lifecycle=e.lifecycle),t}async function applyCodeModeToToolSet(e){let t={},i={};for(let[n,r]of Object.entries(e.tools)){if(isDirectTool(r,e.harnessTools.get(n))){i[n]=r;continue}r.outputSchema===void 0&&log.warn(`code-mode host tool has no outputSchema`,{toolName:n}),t[n]=wrapHostToolForCodeMode(r)}if(Object.keys(t).length>0){let{createCodeModeTool:a}=await loadCodeModeModule();i[CODE_MODE_TOOL_NAME]=a(t,createAshCodeModeOptions({lifecycle:e.lifecycle}))}return{hostTools:t,modelTools:i}}async function buildCodeModeHostTools(e){let n=buildToolSet({approvedTools:e.approvedTools,capabilities:e.capabilities,tools:e.tools}),r=contextStorage.getStore();if(r!==void 0){let e=buildDynamicTools(r);for(let t of e)n[t.name]??={description:t.description,inputSchema:t.inputSchema,execute:t.execute,outputSchema:t.outputSchema}}return(await applyCodeModeToToolSet({harnessTools:e.tools,tools:n})).hostTools}function isDirectTool(e,t){return e.execute===void 0||t?.runtimeAction!==void 0}function wrapHostToolForCodeMode(e){let n=e.execute;if(n===void 0)return e;let o=e.needsApproval,s=contextStorage.getStore(),invoke=async(e,t)=>{let o=await resolveExecuteOutput(n(e,markCodeModeToolExecutionOptions(t)));if(isAuthorizationSignal(o)){let{requestCodeModeInterrupt:t}=await loadCodeModeModule(),n=o.challenges[0]?.name;n&&t({args:toCodeModeConnectionAuthArgs(e),challenges:o.challenges,connectionName:n,kind:CODE_MODE_CONNECTION_AUTH_INTERRUPT_KIND,toolName:``})}return o},c=typeof o==`function`?(...e)=>s===void 0?o(...e):contextStorage.run(s,()=>o(...e)):o,l={...e,execute:(e,n)=>s===void 0?invoke(e,n):contextStorage.run(s,invoke,e,n)};return c!==void 0&&(l.needsApproval=c),l}async function resolveExecuteOutput(e){if(isAsyncIterable(e)){let t;for await(let n of e)t=n;return t}return await e}function isAsyncIterable(e){return typeof e==`object`&&!!e&&Symbol.asyncIterator in e&&typeof e[Symbol.asyncIterator]==`function`}export{applyCodeModeToToolSet,buildCodeModeHostTools,createAshCodeModeOptions};
1
+ import"ai";import{contextStorage}from"#context/container.js";import{CODE_MODE_TOOL_NAME,loadCodeModeModule}from"#shared/code-mode.js";import{isAuthorizationSignal}from"#harness/authorization.js";import{CODE_MODE_CONNECTION_AUTH_INTERRUPT_KIND,markCodeModeToolExecutionOptions,toCodeModeConnectionAuthArgs}from"#runtime/framework-tools/code-mode-connection-auth.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{buildToolSet}from"#harness/tools.js";function createAshCodeModeOptions(e={}){let t={approval:{mode:`interrupt`}};return e.lifecycle!==void 0&&(t.lifecycle=e.lifecycle),t}async function applyCodeModeToToolSet(e){let r={},i={};for(let[t,n]of Object.entries(e.tools)){if(isDirectTool(n,e.harnessTools.get(t))){i[t]=n;continue}r[t]=wrapHostToolForCodeMode(n)}if(Object.keys(r).length>0){let{createCodeModeTool:a}=await loadCodeModeModule();i[CODE_MODE_TOOL_NAME]=a(r,createAshCodeModeOptions({lifecycle:e.lifecycle}))}return{hostTools:r,modelTools:i}}async function buildCodeModeHostTools(t){let n=buildToolSet({approvedTools:t.approvedTools,capabilities:t.capabilities,tools:t.tools}),r=contextStorage.getStore();if(r!==void 0){let e=buildDynamicTools(r);for(let t of e)n[t.name]??={description:t.description,inputSchema:t.inputSchema,execute:t.execute,outputSchema:t.outputSchema}}return(await applyCodeModeToToolSet({harnessTools:t.tools,tools:n})).hostTools}function isDirectTool(e,t){return e.execute===void 0||t?.runtimeAction!==void 0}function wrapHostToolForCodeMode(t){let o=t.execute;if(o===void 0)return t;let s=t.needsApproval,c=contextStorage.getStore(),invoke=async(e,t)=>{let s=await resolveExecuteOutput(o(e,markCodeModeToolExecutionOptions(t)));if(isAuthorizationSignal(s)){let{requestCodeModeInterrupt:t}=await loadCodeModeModule(),r=s.challenges[0]?.name;r&&t({args:toCodeModeConnectionAuthArgs(e),challenges:s.challenges,connectionName:r,kind:CODE_MODE_CONNECTION_AUTH_INTERRUPT_KIND,toolName:``})}return s},l=typeof s==`function`?(...t)=>c===void 0?s(...t):contextStorage.run(c,()=>s(...t)):s,u={...t,execute:(t,n)=>c===void 0?invoke(t,n):contextStorage.run(c,invoke,t,n)};return l!==void 0&&(u.needsApproval=l),u}async function resolveExecuteOutput(e){if(isAsyncIterable(e)){let t;for await(let n of e)t=n;return t}return await e}function isAsyncIterable(e){return typeof e==`object`&&!!e&&Symbol.asyncIterator in e&&typeof e[Symbol.asyncIterator]==`function`}export{applyCodeModeToToolSet,buildCodeModeHostTools,createAshCodeModeOptions};
@@ -1 +1 @@
1
- import{createErrorId,createLogger,formatError,logError,recordErrorOnSpan}from"#internal/logging.js";import{createAuthorizationRequiredEvent,createCompactionCompletedEvent,createCompactionRequestedEvent,createInputRequestedEvent,createResultCompletedEvent}from"#protocol/message.js";import{toErrorMessage}from"#shared/errors.js";import{ToolLoopAgent,isStepCount}from"ai";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{contextStorage}from"#context/container.js";import{setAshAttributes}from"#runtime/attributes/emit.js";import{createRuntimeActionRequestFromToolCall,resolvePendingRuntimeActions,setPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{advanceStep,emitFailedStep,emitRecoverableFailedTurn,emitStepStarted,emitStreamContent,emitTurnEpilogue,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{CODE_MODE_TOOL_NAME,loadCodeModeModule}from"#shared/code-mode.js";import{resolveAssistantStepText}from"#harness/messages.js";import{buildDynamicInstructionMessages}from"#context/dynamic-instruction-lifecycle.js";import{PendingSkillAnnouncementKey}from"#context/dynamic-skill-lifecycle.js";import{consumeDeferredStepInput,getApprovedTools,hasDeferredStepInput,hasStepInput,resolvePendingInput,setPendingInputBatch}from"#harness/input-requests.js";import{isAuthorizationSignal,setPendingAuthorization}from"#harness/authorization.js";import{isCodeModeConnectionAuthInterrupt}from"#runtime/framework-tools/code-mode-connection-auth.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{buildToolSetWithProviderTools}from"#harness/tools.js";import{ASK_QUESTION_TOOL_NAME}from"#runtime/framework-tools/ask-question.js";import{WEB_SEARCH_TOOL_DEFINITION}from"#runtime/framework-tools/web-search.js";import{extractQuestionInputRequests,extractToolApprovalInputRequests}from"#harness/input-extraction.js";import{applyLastToolCacheBreakpoint,applySystemCacheBreakpoint,detectPromptCachePath,getAnthropicCacheMarker}from"#harness/prompt-cache.js";import{resolveFrameworkToolFromUpstreamType,resolveGatewayPinForWebSearchBackend,resolveWebSearchBackend}from"#harness/provider-tools.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{hydrateSandboxAttachments,stageAttachmentsToSandbox}from"#harness/attachment-staging.js";import{applyCodeModeToToolSet,buildCodeModeHostTools,createAshCodeModeOptions}from"#harness/code-mode.js";import{createCodeModeLifecycle}from"#harness/code-mode-lifecycle.js";import{clearPendingCodeModeApproval,getPendingCodeModeApproval,replaceCodeModeApprovalInterruptResult,setPendingCodeModeApproval}from"#harness/code-mode-approval.js";import{compactMessages,getInputTokenCount,resolveCompactionModel,shouldCompact}from"#harness/compaction.js";import{accumulateTurnUsage,getTurnUsageState,setTurnUsageState}from"#harness/turn-tag-state.js";import{buildTelemetryRuntimeContext}from"#harness/instrumentation-runtime-context.js";import{getInstrumentationConfig}from"#harness/instrumentation-config.js";import{clearPendingCodeModeConnectionAuth,getPendingCodeModeConnectionAuth,setPendingCodeModeConnectionAuth}from"#harness/code-mode-connection-auth-state.js";import{classifyModelCallError,extractModelCallErrorDetails,extractUnsupportedProviderToolTypes,summarizeKnownModelCallConfigError,summarizeKnownModelCallRequestError}from"#harness/model-call-error.js";import{extractWorkflowStreamWriteErrorDetails}from"#harness/workflow-stream-error.js";import{ensureOtelIntegration}from"#harness/otel-integration.js";import{buildStepHooks,emitStepActions,isInvalidToolCall}from"#harness/step-hooks.js";import{pruneToolResults}from"#harness/tool-result-pruning.js";import{FINAL_OUTPUT_TOOL_NAME,buildFinalOutputTool}from"#runtime/framework-tools/final-output.js";const environment=process.env.NODE_ENV??`unknown`,ashVersion=resolveInstalledPackageInfo().version,log=createLogger(`harness.tool-loop`);function logToolExecutionError(e){e.toolOutput.type===`tool-error`&&logError(log,`tool execution failed`,e.toolOutput.error,{toolName:e.toolCall.toolName,toolCallId:e.toolCall.toolCallId})}function enrichTelemetry(e,t,n){if(e===void 0)return;let r={};for(let e of Object.keys(n??{}))r[e]=!0;return{functionId:e.functionId??t,includeRuntimeContext:r,isEnabled:!0,recordInputs:e.recordInputs??!0,recordOutputs:e.recordOutputs??!0}}function resolveGatewayPinForStep(e){if(e.cachePath.kind!==`gateway-auto`||e.tools[WEB_SEARCH_TOOL_DEFINITION.name]===void 0)return;let t=resolveWebSearchBackend(e.modelReference);return t===null?void 0:resolveGatewayPinForWebSearchBackend(t)??void 0}function buildGatewayAttributionHeaders(e,t){if(typeof e!=`string`)return;let n=t?.agentName??t?.agentId,r=process.env.VERCEL_PROJECT_PRODUCTION_URL||process.env.VERCEL_URL,i=r?`https://${r}`:void 0;if(!n&&!i)return;let a={};return n&&(a[`x-title`]=n),i&&(a[`http-referer`]=i),a}const TURN_TRACE_STATE_KEY=`ash.harness.turnTrace`;function getTurnTraceState(e){return e.state?.[TURN_TRACE_STATE_KEY]}function setTurnTraceState(e,t){let n={traceId:t.traceId,spanId:t.spanId,traceFlags:t.traceFlags};return{...e,state:{...e.state,[TURN_TRACE_STATE_KEY]:n}}}function resolveStepOtelContext(e,t,n){if(t)return trace.setSpan(context.active(),t);if(e){let e=getTurnTraceState(n);if(e){let t=trace.wrapSpanContext({traceId:e.traceId,spanId:e.spanId,traceFlags:e.traceFlags});return trace.setSpan(context.active(),t)}}}function createToolLoopHarness(t){let n=t.handleEvent,a=getInstrumentationConfig();a!==void 0&&ensureOtelIntegration();let o=a===void 0?void 0:trace.getTracer(`ash`),s=t.runtimeIdentity?.agentName;async function runStep(e,t){let n;if(o&&hasStepInput(t)){let t=a?.functionId??s,r={"ash.version":ashVersion,"ash.environment":environment,"ash.session.id":e.sessionId};t&&(r[`ai.telemetry.functionId`]=t),n=o.startSpan(`ai.ash.turn`,{attributes:r})}let r=resolveStepOtelContext(o,n,e),executeStep=()=>executeStepBody(e,t,n);try{return r?await context.with(r,executeStep):await executeStep()}finally{n?.end()}}async function executeStepBody(o,c,l){let p=o;l&&(p=setTurnTraceState(p,l.spanContext()));let _=getHarnessEmissionState(p.state),y=consumeDeferredStepInput({input:c,session:p});p=y.session;let b=await resolvePendingRuntimeActions({emit:n,session:p,stepInput:y.input});if(b.outcome===`unresolved`)return{next:null,session:b.session};p=b.session;let T=resolvePendingInput({history:b.messages,resolveApprovalKey:resolveApprovalKeyFromTools(t.tools),session:p,stepInput:y.input});if(T.outcome===`unresolved`)return{next:null,session:T.session};n&&hasStepInput(c)&&(_=await emitTurnPreamble(n,c??{},_,t.runtimeIdentity),p=setHarnessEmissionState(p,_),l&&l.setAttribute(`ash.turn.id`,_.turnId)),p=T.session;let k=T.messages;if(y.input?.context!==void 0)for(let e of y.input.context)k.push({content:e,role:`user`});if(y.input?.message!==void 0&&!T.deferredMessage){let e=await stageAttachmentsToSandbox(y.input.message);k.push({content:e,role:`user`})}let A=await t.resolveModel(p.agent.modelReference),j=detectPromptCachePath(A),M=j.kind===`anthropic-direct`?getAnthropicCacheMarker():void 0,N=buildGatewayAttributionHeaders(A,t.runtimeIdentity);({messages:k,session:p}=await maybeCompact({emit:n,emissionState:_,headers:N,messages:k,model:A,onCompaction:t.onCompaction,resolveModel:t.resolveModel,session:p,telemetry:enrichTelemetry(a,s)??void 0}));let P=getApprovedTools(p),F=contextStorage.getStore(),I=await hydrateSandboxAttachments(k),L=[],R=[];for(let e of I)e.role===`system`?L.push(e):R.push(e);if(F!==void 0){L.push(...buildDynamicInstructionMessages(F));let e=F.get(PendingSkillAnnouncementKey);e!==void 0&&e.length>0&&L.push({role:`system`,content:e})}let z=R,prepareModelCallInput=e=>{let t=e?[{role:`system`,content:e}]:[],n=p.agent.system?[{role:`system`,content:p.agent.system}]:[],r=L.length>0||t.length>0?[...t,...n,...L]:void 0,i=r!==void 0&&M?applySystemCacheBreakpoint(r,M):r??p.agent.system??void 0;return{instructions:i,telemetryRuntimeContext:buildTelemetryRuntimeContext({ashVersion,authored:a,emissionState:_,environment,modelInput:{instructions:i,messages:z},session:p})}},runOneModelCall=async e=>{let{instructions:i,telemetryRuntimeContext:o}=e.preparedInput??prepareModelCallInput(e.extraSystemNote),c=t.codeMode===!0,l=await buildToolSetWithProviderTools({approvedTools:P,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,modelReference:p.agent.modelReference,tools:t.tools});if(F!==void 0){let e=buildDynamicTools(F);for(let t of e)l[t.name]??={description:t.description,inputSchema:t.inputSchema,execute:t.execute,outputSchema:t.outputSchema}}p.outputSchema!==void 0&&(l[FINAL_OUTPUT_TOOL_NAME]=buildFinalOutputTool(p.outputSchema));let u=c?(await applyCodeModeToToolSet({harnessTools:t.tools,lifecycle:n===void 0?void 0:createCodeModeLifecycle({emit:n,emissionState:_,tools:t.tools}),tools:l})).modelTools:l,m=M?applyLastToolCacheBreakpoint(u,M):u,h=resolveGatewayPinForStep({cachePath:j,modelReference:p.agent.modelReference,tools:m}),g=buildStepHooks({cachePath:j,emit:n,emissionState:_,emitStepStarted:e.suppressStepStartedEmission!==!0,gatewayPinProvider:h,marker:M,session:p}),v=new ToolLoopAgent({headers:N,instructions:i,model:A,onToolExecutionEnd:logToolExecutionError,onError(e){logError(log,`tool-loop stream error`,e.error)},onStepFinish:g.onStepFinish,prepareStep:g.prepareStep,runtimeContext:o,stopWhen:isStepCount(1),telemetry:enrichTelemetry(a,s,o),tools:m});return runModelCallWithRetries(async()=>{if(n){let e=await v.stream({messages:z}),{inlineActionResultCallIds:r,inlineToolResultParts:i}=await emitStreamContent(n,_,e.fullStream),a=await g.stepResult;return await emitStepActions(n,_,a,{excludedActionToolNames:new Set([ASK_QUESTION_TOOL_NAME,CODE_MODE_TOOL_NAME,FINAL_OUTPUT_TOOL_NAME]),inlineActionResultCallIds:r,tools:t.tools}),i.length>0?{content:a.content,finishReason:a.finishReason,response:{...a.response,messages:[{role:`tool`,content:[...i]},...a.response.messages]},text:a.text,toolCalls:a.toolCalls,toolResults:a.toolResults,usage:a.usage}:a}return await v.generate({messages:z}),await g.stepResult},{sessionId:p.sessionId,turnId:_.turnId})},B=prepareModelCallInput();n&&await emitStepStarted(n,_,k);let V=await continuePendingCodeModeConnectionAuth({capabilities:t.capabilities,config:t,emit:n,emissionState:_,messages:k,runStep,session:p});if(V!==null)return V;let H=await continuePendingCodeModeApproval({capabilities:t.capabilities,config:t,emit:n,emissionState:_,messages:k,runStep,session:p});if(H!==null)return H;let U;try{U=await runOneModelCall({preparedInput:B,suppressStepStartedEmission:!0})}catch(t){let r=await attemptUnsupportedProviderToolRecovery({error:t,runOneModelCall,sessionId:p.sessionId,turnId:_.turnId});if(r.outcome===`recovered`)U=r.result;else{let t=r.error;if(l&&recordErrorOnSpan(l,t),!n)throw t;let a=extractWorkflowStreamWriteErrorDetails(t);if(a!==null){let r=createErrorId();return log.error(`workflow stream write failed — parking session for retry by the user`,{...a,errorId:r,error:t,sessionId:p.sessionId,turnId:_.turnId}),_=await emitRecoverableFailedTurn(n,_,{code:`WORKFLOW_STREAM_WRITE_FAILED`,details:{...a,errorId:r},message:toErrorMessage(t)}),{next:null,session:setHarnessEmissionState(p,_)}}let o=classifyModelCallError(t),s=createErrorId(),c=o===`terminal`?summarizeKnownModelCallConfigError(t):null,d=c===null?summarizeKnownModelCallRequestError(t):null,f=c?.message??d?.message??toErrorMessage(t),m=extractModelCallErrorDetails(t),h=buildModelCallFailureDetails({configSummary:c,error:t,errorId:s,modelCallDetails:m,requestSummary:d}),g=buildModelCallFailureLogFields({error:t,errorId:s,modelCallDetails:m,requestSummary:d,sessionId:p.sessionId,turnId:_.turnId});return o===`terminal`?(c===null?log.error(d?.message??`model call failed terminally`,g):log.error(`${c.name}: ${c.message}`,{errorId:s,sessionId:p.sessionId,turnId:_.turnId}),await emitFailedStep(n,_,{code:`MODEL_CALL_FAILED`,details:h,message:f,sessionId:p.sessionId}),{next:{done:!0,output:``},session:p}):(log.error(d?.message??`model call failed — parking session for retry by the user`,g),_=await emitRecoverableFailedTurn(n,_,{code:`MODEL_CALL_FAILED`,details:h,message:f}),{next:null,session:setHarnessEmissionState(p,_)})}}let W=accumulateTurnUsage({previous:getTurnUsageState(p.state),turnId:_.turnId,usage:U.usage??{}});p=setTurnUsageState(p,W);let G;try{G=formatLanguageModelGatewayId(A)}catch{G=void 0}return await setAshAttributes({"$ash.model":G,"$ash.input_tokens":W.inputTokens,"$ash.output_tokens":W.outputTokens,"$ash.cache_read_tokens":W.cacheReadTokens,"$ash.tool_count":t.tools.size}),handleStepResult({config:t,emit:n,emissionState:_,promptMessages:k,result:U,runStep,session:p})}return runStep}function buildModelCallFailureDetails(e){let{configSummary:t,error:r,errorId:i,modelCallDetails:a,requestSummary:o}=e;return t===null?o===null?{...formatError(r,i),...a}:{errorId:i,message:toErrorMessage(r),name:o.name,...a}:{errorId:i,message:t.message,name:t.name,...a}}function buildModelCallFailureLogFields(e){let t={errorId:e.errorId,sessionId:e.sessionId,turnId:e.turnId};return e.requestSummary===null?{...t,error:e.error}:{...t,details:e.modelCallDetails}}async function attemptUnsupportedProviderToolRecovery(e){let t=extractUnsupportedProviderToolTypes(e.error);if(t.length===0)return{outcome:`failed`,error:e.error};let n=[];for(let e of t){let t=resolveFrameworkToolFromUpstreamType(e);t!==null&&!n.includes(t)&&n.push(t)}if(n.length===0)return{outcome:`failed`,error:e.error};log.warn(`disabling unsupported provider tool(s); retrying step once`,{disabled:n,sessionId:e.sessionId,turnId:e.turnId,upstreamTypes:t});try{return{outcome:`recovered`,result:await e.runOneModelCall({disabledProviderTools:new Set(n),extraSystemNote:buildDisabledToolNote(n),suppressStepStartedEmission:!0})}}catch(e){return{outcome:`failed`,error:e}}}function buildDisabledToolNote(e){let t=e.join(`, `);return`The following ${e.length===1?`tool is`:`tools are`} not available with the current model and has been removed: ${t}. Proceed using the remaining tools or your training knowledge.`}async function handleStepResult(e){let{config:t,emit:n,promptMessages:r,result:i,runStep:o}=e,{emissionState:s,session:l}=e,u=i.response.messages,d=resolveAssistantStepText(u,i.text),f={...l,compaction:createNextCompactionConfig(l.compaction,r,i)};if(t.codeMode===!0){let{getCodeModeInterrupt:e,isCodeModeApprovalInterrupt:a}=await loadCodeModeModule(),o=e(i);if(o!==void 0){if(isCodeModeConnectionAuthInterrupt(o))return parkOnCodeModeConnectionAuth({baseSession:f,config:t,emit:n,emissionState:s,interrupt:o,promptMessages:r,responseMessages:u});if(a(o))return parkOnCodeModeApproval({baseSession:f,config:t,emit:n,emissionState:s,interrupt:o,promptMessages:r,responseMessages:u})}}let p=extractToolApprovalInputRequests({content:i.content??[]}),m=new Set(p.map(e=>e.action.callId)),h=extractQuestionInputRequests({toolCalls:i.toolCalls,excludedCallIds:m}),g=[...p,...h],v=(i.toolCalls??[]).filter(e=>!isInvalidToolCall(e)).filter(e=>t.tools.get(e.toolName)?.runtimeAction!==void 0).map(e=>createRuntimeActionRequestFromToolCall({toolCall:e,tools:t.tools}));if(v.length>0)return{next:null,session:setHarnessEmissionState(setPendingRuntimeActionBatch({actions:v,event:{sequence:s.sequence,stepIndex:s.stepIndex,turnId:s.turnId},responseMessages:u,session:{...f,history:[...r]}}),s)};if(g.length>0){let e=setPendingInputBatch({requests:g,responseMessages:u,session:{...f,history:[...r]}});return n&&(await n(createInputRequestedEvent({requests:g,sequence:s.sequence,stepIndex:s.stepIndex,turnId:s.turnId})),t.mode===`conversation`&&(s=await emitTurnEpilogue(n,s,t.mode),e=setHarnessEmissionState(e,s))),{next:null,session:e}}let x=(i.toolResults??[]).find(e=>isAuthorizationSignal(e.output));if(x&&isAuthorizationSignal(x.output)){let{challenges:e}=x.output;if(n)for(let t of e)await n(createAuthorizationRequiredEvent({authorization:t.challenge,name:t.name,description:t.challenge.instructions??`Authorization required for ${t.name}`,webhookUrl:t.hookUrl,sequence:s.sequence,stepIndex:s.stepIndex,turnId:s.turnId}));return{next:null,session:setHarnessEmissionState({...f,history:[...r],state:setPendingAuthorization(f.state,{challenges:e})},s)}}let S=pruneToolResults(r),C=S!==r,w=f.compaction;C&&w.lastKnownInputTokens!==void 0&&(w={recentWindowSize:w.recentWindowSize,threshold:w.threshold});let E=[...S,...u],D={...f,compaction:w,history:E},O=!(D.outputSchema!==void 0&&extractFinalOutput(i)!==void 0)&&(u.at(-1)?.role===`tool`||hasDeferredStepInput(D));return!O&&D.outputSchema===void 0&&d===null&&log.warn(`model completed terminal step without visible assistant text`,{finishReason:i.finishReason,mode:t.mode,responseMessageCount:u.length,responseMessageRoles:u.map(e=>e.role),sequence:s.sequence,sessionId:l.sessionId,stepIndex:s.stepIndex,turnId:s.turnId}),O?(n&&(s=advanceStep(s),D=setHarnessEmissionState(D,s)),{next:o,session:D}):t.mode===`task`?finishTaskTurn({emissionState:s,emit:n,prunedHistory:S,result:i,schema:D.outputSchema,session:D,stepOutput:d}):finishConversationTurn({emissionState:s,emit:n,prunedHistory:S,result:i,schema:D.outputSchema,session:D})}const OUTPUT_SCHEMA_NOT_FULFILLED={code:`OUTPUT_SCHEMA_NOT_FULFILLED`,message:`The agent could not produce a result matching the requested schema.`};function extractFinalOutput(e){return(e.toolCalls??[]).find(e=>e.toolName===FINAL_OUTPUT_TOOL_NAME)?.input}function persistStructuredAssistantTurn(e,t,n){return{...e,history:[...t,{content:JSON.stringify(n),role:`assistant`}],outputSchema:void 0}}async function emitStructuredResult(e,t,n,r){return await e(createResultCompletedEvent({result:n,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),emitTurnEpilogue(e,t,r)}async function finishTaskTurn(e){let{emit:t,prunedHistory:n,result:r,schema:i,stepOutput:a}=e,{emissionState:o,session:s}=e;if(i===void 0)return t&&(o=await emitTurnEpilogue(t,o,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:a??``},session:s};let c=extractFinalOutput(r);return c===void 0?(t&&await emitFailedStep(t,o,{...OUTPUT_SCHEMA_NOT_FULFILLED,sessionId:s.sessionId}),{next:{done:!0,isError:!0,output:OUTPUT_SCHEMA_NOT_FULFILLED.message},session:s}):(s=persistStructuredAssistantTurn(s,n,c),t&&(o=await emitStructuredResult(t,o,c,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:JSON.stringify(c)},session:s})}async function finishConversationTurn(e){let{emit:t,prunedHistory:n,result:r,schema:i}=e,{emissionState:a,session:o}=e;if(i===void 0)return t&&(a=await emitTurnEpilogue(t,a,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o};let s=extractFinalOutput(r);return s===void 0?(t&&(a=await emitRecoverableFailedTurn(t,a,OUTPUT_SCHEMA_NOT_FULFILLED),o=setHarnessEmissionState(o,a)),{next:null,session:o}):(o=persistStructuredAssistantTurn(o,n,s),t&&(a=await emitStructuredResult(t,a,s,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o})}async function continuePendingCodeModeApproval(e){let t=getPendingCodeModeApproval(e.session.state);if(t===void 0)return null;let{continueCodeModeApproval:n,getCodeModeApprovalResponse:i,isCodeModeApprovalInterrupt:a,unwrapCodeModeResult:o}=await loadCodeModeModule(),s=i([...e.messages],t.interrupt);if(s===void 0)return{next:null,session:e.session};let c=await buildCodeModeHostTools({approvedTools:getApprovedTools(e.session),capabilities:e.capabilities,tools:e.config.tools}),l;try{l=await n({approvalResponse:s,interrupt:t.interrupt,options:createAshCodeModeOptions({lifecycle:e.emit===void 0?void 0:createCodeModeLifecycle({emit:e.emit,emissionState:e.emissionState,skipReplayed:!0,tools:e.config.tools})}),tools:c})}catch(e){logError(log,`code-mode approval continuation failed`,e),l={error:`code_mode_continuation_failed`,message:toErrorMessage(e),retryable:!1}}let d=o(l),f=d.status===`interrupted`?d.interrupt:d.output,p=replaceCodeModeApprovalInterruptResult([...e.session.history,...t.responseMessages],t.interrupt,f),m=clearPendingCodeModeApproval({...e.session,history:p});if(d.status===`interrupted`){if(isCodeModeConnectionAuthInterrupt(d.interrupt)){let t=e.session.history.length,n=p.slice(0,t),r=p.slice(t);return m={...m,history:n},parkOnCodeModeConnectionAuth({baseSession:m,config:e.config,emit:e.emit,emissionState:e.emissionState,interrupt:d.interrupt,promptMessages:n,responseMessages:r})}if(a(d.interrupt)){let t=e.session.history.length,n=p.slice(0,t),r=p.slice(t);return m={...m,history:n},parkOnCodeModeApproval({baseSession:m,config:e.config,emit:e.emit,emissionState:e.emissionState,interrupt:d.interrupt,promptMessages:n,responseMessages:r})}}return{next:e.runStep,session:m}}async function parkOnCodeModeConnectionAuth(e){let t=[...e.interrupt.payload.challenges??[]];if(e.emit)for(let n of t)await e.emit(createAuthorizationRequiredEvent({authorization:n.challenge,name:n.name,description:n.challenge.instructions??`Authorization required for ${n.name}`,webhookUrl:n.hookUrl,sequence:e.emissionState.sequence,stepIndex:e.emissionState.stepIndex,turnId:e.emissionState.turnId}));return{next:null,session:setPendingCodeModeConnectionAuth({interrupt:e.interrupt,responseMessages:e.responseMessages,session:{...e.baseSession,history:[...e.promptMessages],state:setPendingAuthorization(e.baseSession.state,{challenges:t})}})}}async function continuePendingCodeModeConnectionAuth(e){let t=getPendingCodeModeConnectionAuth(e.session.state);if(t===void 0)return null;let{continueCodeModeInterrupt:n,isCodeModeApprovalInterrupt:i,replaceCodeModeInterruptResult:a,unwrapCodeModeResult:o}=await loadCodeModeModule(),s=await buildCodeModeHostTools({approvedTools:getApprovedTools(e.session),capabilities:e.capabilities,tools:e.config.tools}),c=e.emit===void 0?void 0:createCodeModeLifecycle({emit:e.emit,emissionState:e.emissionState,skipReplayed:!0,tools:e.config.tools}),l;try{l=await n({interrupt:t.interrupt,resolution:{status:`authorized`},tools:s,options:createAshCodeModeOptions({lifecycle:c})})}catch(e){logError(log,`code-mode interrupt continuation failed`,e),l={error:`code_mode_continuation_failed`,message:toErrorMessage(e),retryable:!1}}let d=o(l),f=d.status===`interrupted`?d.interrupt:d.output,p=a([...e.session.history,...t.responseMessages],t.interrupt.pendingContinuation,f),m=clearPendingCodeModeConnectionAuth({...e.session,history:p});if(d.status===`interrupted`){if(isCodeModeConnectionAuthInterrupt(d.interrupt)){let t=e.session.history.length,n=p.slice(0,t),r=p.slice(t);return m={...m,history:n},parkOnCodeModeConnectionAuth({baseSession:m,config:e.config,emit:e.emit,emissionState:e.emissionState,interrupt:d.interrupt,promptMessages:n,responseMessages:r})}if(i(d.interrupt)){let t=e.session.history.length,n=p.slice(0,t),r=p.slice(t);return m={...m,history:n},parkOnCodeModeApproval({baseSession:m,config:e.config,emit:e.emit,emissionState:e.emissionState,interrupt:d.interrupt,promptMessages:n,responseMessages:r})}}return{next:e.runStep,session:m}}async function parkOnCodeModeApproval(e){let{toCodeModeApprovalMessages:t}=await loadCodeModeModule(),n=t(e.interrupt),r=extractToolApprovalInputRequests({content:extractAssistantContent(n)}),i=setPendingInputBatch({requests:r,responseMessages:n,session:setPendingCodeModeApproval({interrupt:e.interrupt,responseMessages:e.responseMessages,session:{...e.baseSession,history:[...e.promptMessages]}})});if(e.emit&&(await e.emit(createInputRequestedEvent({requests:r,sequence:e.emissionState.sequence,stepIndex:e.emissionState.stepIndex,turnId:e.emissionState.turnId})),e.config.mode===`conversation`)){let t=await emitTurnEpilogue(e.emit,e.emissionState,e.config.mode);i=setHarnessEmissionState(i,t)}return{next:null,session:i}}function extractAssistantContent(e){let t=[];for(let n of e)n.role===`assistant`&&Array.isArray(n.content)&&t.push(...n.content);return t}function createNextCompactionConfig(e,t,n){let r={recentWindowSize:e.recentWindowSize,threshold:e.threshold};return n.usage?.inputTokens!==void 0&&(r.lastKnownInputTokens=n.usage.inputTokens,r.lastKnownPromptMessageCount=t.length),r}async function maybeCompact(e){let{emit:t,emissionState:n}=e,r=e.messages,i=e.session;if(!shouldCompact(r,i.compaction))return{messages:r,session:i};let a=await resolveCompactionModel({compactionModelReference:i.agent.compactionModelReference,model:e.model,modelReference:i.agent.modelReference,resolveModel:e.resolveModel});if(t&&await t(createCompactionRequestedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId,usageInputTokens:getInputTokenCount(r,i.compaction)})),r=await compactMessages(r,a.model,i.compaction,a.providerOptions,e.telemetry,e.headers),e.onCompaction){let t=await e.onCompaction(i);i=t.session;for(let e of t.messages)r.push(e)}return t&&await t(createCompactionCompletedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId})),{messages:r,session:i}}function resolveApprovalKeyFromTools(e){return t=>{let n=e.get(t.action.toolName);if(n?.approvalKey!==void 0)return n.approvalKey(t.action.input)}}async function runModelCallWithRetries(e,t){for(let n=1;;n++)try{return await e()}catch(e){if(n===3||classifyModelCallError(e)!==`retry`)throw e;let r=500*2**(n-1)+Math.floor(Math.random()*250);log.warn(`model call failed transiently — retrying`,{attempt:n,delayMs:r,sessionId:t.sessionId,turnId:t.turnId,error:e}),await new Promise(e=>setTimeout(e,r))}}export{createToolLoopHarness};
1
+ import{createErrorId,createLogger,formatError,logError,recordErrorOnSpan}from"#internal/logging.js";import{createAuthorizationRequiredEvent,createCompactionCompletedEvent,createCompactionRequestedEvent,createInputRequestedEvent,createResultCompletedEvent}from"#protocol/message.js";import{toErrorMessage}from"#shared/errors.js";import{ToolLoopAgent,isStepCount}from"ai";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{contextStorage}from"#context/container.js";import{setAshAttributes}from"#runtime/attributes/emit.js";import{createRuntimeActionRequestFromToolCall,resolvePendingRuntimeActions,setPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{advanceStep,emitFailedStep,emitRecoverableFailedTurn,emitStepStarted,emitStreamContent,emitTurnEpilogue,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{CODE_MODE_TOOL_NAME,loadCodeModeModule}from"#shared/code-mode.js";import{resolveAssistantStepText}from"#harness/messages.js";import{buildDynamicInstructionMessages}from"#context/dynamic-instruction-lifecycle.js";import{PendingSkillAnnouncementKey}from"#context/dynamic-skill-lifecycle.js";import{consumeDeferredStepInput,getApprovedTools,hasDeferredStepInput,hasStepInput,resolvePendingInput,setPendingInputBatch}from"#harness/input-requests.js";import{isAuthorizationSignal,setPendingAuthorization}from"#harness/authorization.js";import{isCodeModeConnectionAuthInterrupt}from"#runtime/framework-tools/code-mode-connection-auth.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{buildToolSetWithProviderTools}from"#harness/tools.js";import{ASK_QUESTION_TOOL_NAME}from"#runtime/framework-tools/ask-question.js";import{WEB_SEARCH_TOOL_DEFINITION}from"#runtime/framework-tools/web-search.js";import{extractQuestionInputRequests,extractToolApprovalInputRequests}from"#harness/input-extraction.js";import{applyLastToolCacheBreakpoint,applySystemCacheBreakpoint,detectPromptCachePath,getAnthropicCacheMarker}from"#harness/prompt-cache.js";import{resolveFrameworkToolFromUpstreamType,resolveGatewayPinForWebSearchBackend,resolveWebSearchBackend}from"#harness/provider-tools.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{hydrateSandboxAttachments,stageAttachmentsToSandbox}from"#harness/attachment-staging.js";import{applyCodeModeToToolSet,buildCodeModeHostTools,createAshCodeModeOptions}from"#harness/code-mode.js";import{createCodeModeLifecycle}from"#harness/code-mode-lifecycle.js";import{clearPendingCodeModeApproval,getPendingCodeModeApproval,replaceCodeModeApprovalInterruptResult,setPendingCodeModeApproval}from"#harness/code-mode-approval.js";import{compactMessages,getInputTokenCount,resolveCompactionModel,shouldCompact}from"#harness/compaction.js";import{accumulateTurnUsage,getTurnUsageState,setTurnUsageState}from"#harness/turn-tag-state.js";import{buildTelemetryRuntimeContext}from"#harness/instrumentation-runtime-context.js";import{getInstrumentationConfig}from"#harness/instrumentation-config.js";import{clearPendingCodeModeConnectionAuth,getPendingCodeModeConnectionAuth,setPendingCodeModeConnectionAuth}from"#harness/code-mode-connection-auth-state.js";import{classifyModelCallError,extractModelCallErrorDetails,extractUnsupportedProviderToolTypes,summarizeKnownModelCallConfigError,summarizeKnownModelCallRequestError}from"#harness/model-call-error.js";import{extractWorkflowStreamWriteErrorDetails}from"#harness/workflow-stream-error.js";import{ensureOtelIntegration}from"#harness/otel-integration.js";import{buildStepHooks,emitStepActions,isInvalidToolCall}from"#harness/step-hooks.js";import{pruneToolResults}from"#harness/tool-result-pruning.js";import{FINAL_OUTPUT_TOOL_NAME,buildFinalOutputTool}from"#runtime/framework-tools/final-output.js";const environment=process.env.NODE_ENV??`unknown`,ashVersion=resolveInstalledPackageInfo().version,log=createLogger(`harness.tool-loop`);function logToolExecutionError(e){e.toolOutput.type===`tool-error`&&logError(log,`tool execution failed`,e.toolOutput.error,{toolName:e.toolCall.toolName,toolCallId:e.toolCall.toolCallId})}function enrichTelemetry(e,t,n){if(e===void 0)return;let r={};for(let e of Object.keys(n??{}))r[e]=!0;return{functionId:e.functionId??t,includeRuntimeContext:r,isEnabled:!0,recordInputs:e.recordInputs??!0,recordOutputs:e.recordOutputs??!0}}function resolveGatewayPinForStep(e){if(e.cachePath.kind!==`gateway-auto`||e.tools[WEB_SEARCH_TOOL_DEFINITION.name]===void 0)return;let t=resolveWebSearchBackend(e.modelReference);return t===null?void 0:resolveGatewayPinForWebSearchBackend(t)??void 0}function buildGatewayAttributionHeaders(e,t){if(typeof e!=`string`)return;let n=t?.agentName??t?.agentId,r=process.env.VERCEL_PROJECT_PRODUCTION_URL||process.env.VERCEL_URL,i=r?`https://${r}`:void 0;if(!n&&!i)return;let a={};return n&&(a[`x-title`]=n),i&&(a[`http-referer`]=i),a}const TURN_TRACE_STATE_KEY=`ash.harness.turnTrace`;function getTurnTraceState(e){return e.state?.[TURN_TRACE_STATE_KEY]}function setTurnTraceState(e,t){let n={traceId:t.traceId,spanId:t.spanId,traceFlags:t.traceFlags};return{...e,state:{...e.state,[TURN_TRACE_STATE_KEY]:n}}}function resolveStepOtelContext(e,t,n){if(t)return trace.setSpan(context.active(),t);if(e){let e=getTurnTraceState(n);if(e){let t=trace.wrapSpanContext({traceId:e.traceId,spanId:e.spanId,traceFlags:e.traceFlags});return trace.setSpan(context.active(),t)}}}function createToolLoopHarness(t){let n=t.handleEvent,a=getInstrumentationConfig();a!==void 0&&ensureOtelIntegration();let o=a===void 0?void 0:trace.getTracer(`ash`),s=t.runtimeIdentity?.agentName;async function runStep(e,t){let n;if(o&&hasStepInput(t)){let t=a?.functionId??s,r={"ash.version":ashVersion,"ash.environment":environment,"ash.session.id":e.sessionId};t&&(r[`ai.telemetry.functionId`]=t),n=o.startSpan(`ai.ash.turn`,{attributes:r})}let r=resolveStepOtelContext(o,n,e),executeStep=()=>executeStepBody(e,t,n);try{return r?await context.with(r,executeStep):await executeStep()}finally{n?.end()}}async function executeStepBody(o,c,l){let p=o;l&&(p=setTurnTraceState(p,l.spanContext()));let _=getHarnessEmissionState(p.state),y=consumeDeferredStepInput({input:c,session:p});p=y.session;let b=await resolvePendingRuntimeActions({emit:n,session:p,stepInput:y.input});if(b.outcome===`unresolved`)return{next:null,session:b.session};p=b.session;let T=resolvePendingInput({history:b.messages,resolveApprovalKey:resolveApprovalKeyFromTools(t.tools),session:p,stepInput:y.input});if(T.outcome===`unresolved`)return{next:null,session:T.session};n&&hasStepInput(c)&&(_=await emitTurnPreamble(n,c??{},_,t.runtimeIdentity),p=setHarnessEmissionState(p,_),l&&l.setAttribute(`ash.turn.id`,_.turnId)),p=T.session;let k=T.messages;if(y.input?.context!==void 0)for(let e of y.input.context)k.push({content:e,role:`user`});if(y.input?.message!==void 0&&!T.deferredMessage){let e=await stageAttachmentsToSandbox(y.input.message);k.push({content:e,role:`user`})}let A=await t.resolveModel(p.agent.modelReference),j=detectPromptCachePath(A),M=j.kind===`anthropic-direct`?getAnthropicCacheMarker():void 0,N=buildGatewayAttributionHeaders(A,t.runtimeIdentity);({messages:k,session:p}=await maybeCompact({emit:n,emissionState:_,headers:N,messages:k,model:A,onCompaction:t.onCompaction,resolveModel:t.resolveModel,session:p,telemetry:enrichTelemetry(a,s)??void 0}));let P=getApprovedTools(p),F=contextStorage.getStore(),I=await hydrateSandboxAttachments(k),L=[],R=[];for(let e of I)e.role===`system`?L.push(e):R.push(e);if(F!==void 0){L.push(...buildDynamicInstructionMessages(F));let e=F.get(PendingSkillAnnouncementKey);e!==void 0&&e.length>0&&L.push({role:`system`,content:e})}let z=R,prepareModelCallInput=e=>{let t=e?[{role:`system`,content:e}]:[],n=p.agent.system?[{role:`system`,content:p.agent.system}]:[],r=L.length>0||t.length>0?[...t,...n,...L]:void 0,i=r!==void 0&&M?applySystemCacheBreakpoint(r,M):r??p.agent.system??void 0;return{instructions:i,telemetryRuntimeContext:buildTelemetryRuntimeContext({ashVersion,authored:a,emissionState:_,environment,modelInput:{instructions:i,messages:z},session:p})}},runOneModelCall=async e=>{let{instructions:i,telemetryRuntimeContext:o}=e.preparedInput??prepareModelCallInput(e.extraSystemNote),c=t.codeMode===!0,l=await buildToolSetWithProviderTools({approvedTools:P,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,modelReference:p.agent.modelReference,tools:t.tools});if(F!==void 0){let e=buildDynamicTools(F);for(let t of e)l[t.name]??={description:t.description,inputSchema:t.inputSchema,execute:t.execute,outputSchema:t.outputSchema}}p.outputSchema!==void 0&&(l[FINAL_OUTPUT_TOOL_NAME]=buildFinalOutputTool(p.outputSchema));let u=c?(await applyCodeModeToToolSet({harnessTools:t.tools,lifecycle:n===void 0?void 0:createCodeModeLifecycle({emit:n,emissionState:_,tools:t.tools}),tools:l})).modelTools:l,m=M?applyLastToolCacheBreakpoint(u,M):u,h=resolveGatewayPinForStep({cachePath:j,modelReference:p.agent.modelReference,tools:m}),g=buildStepHooks({cachePath:j,emit:n,emissionState:_,emitStepStarted:e.suppressStepStartedEmission!==!0,gatewayPinProvider:h,marker:M,session:p}),v=new ToolLoopAgent({headers:N,instructions:i,model:A,onToolExecutionEnd:logToolExecutionError,onError(e){logError(log,`tool-loop stream error`,e.error)},onStepFinish:g.onStepFinish,prepareStep:g.prepareStep,runtimeContext:o,stopWhen:isStepCount(1),telemetry:enrichTelemetry(a,s,o),tools:m});return runModelCallWithRetries(async()=>{if(n){let e=await v.stream({messages:z}),{inlineActionResultCallIds:r,inlineToolResultParts:i}=await emitStreamContent(n,_,e.fullStream),a=await g.stepResult;return await emitStepActions(n,_,a,{excludedActionToolNames:new Set([ASK_QUESTION_TOOL_NAME,CODE_MODE_TOOL_NAME,FINAL_OUTPUT_TOOL_NAME]),inlineActionResultCallIds:r,tools:t.tools}),i.length>0?{content:a.content,finishReason:a.finishReason,response:{...a.response,messages:[{role:`tool`,content:[...i]},...a.response.messages]},text:a.text,toolCalls:a.toolCalls,toolResults:a.toolResults,usage:a.usage}:a}return await v.generate({messages:z}),await g.stepResult},{sessionId:p.sessionId,turnId:_.turnId})},B=prepareModelCallInput();n&&await emitStepStarted(n,_,k);let V=await continuePendingCodeModeConnectionAuth({capabilities:t.capabilities,config:t,emit:n,emissionState:_,messages:k,runStep,session:p});if(V!==null)return V;let H=await continuePendingCodeModeApproval({capabilities:t.capabilities,config:t,emit:n,emissionState:_,messages:k,runStep,session:p});if(H!==null)return H;let U;try{U=await runOneModelCall({preparedInput:B,suppressStepStartedEmission:!0})}catch(t){let r=await attemptUnsupportedProviderToolRecovery({error:t,runOneModelCall,sessionId:p.sessionId,turnId:_.turnId});if(r.outcome===`recovered`)U=r.result;else{let t=r.error;if(l&&recordErrorOnSpan(l,t),!n)throw t;let a=extractWorkflowStreamWriteErrorDetails(t);if(a!==null){let r=createErrorId();return log.error(`workflow stream write failed — parking session for retry by the user`,{...a,errorId:r,error:t,sessionId:p.sessionId,turnId:_.turnId}),_=await emitRecoverableFailedTurn(n,_,{code:`WORKFLOW_STREAM_WRITE_FAILED`,details:{...a,errorId:r},message:toErrorMessage(t)}),{next:null,session:setHarnessEmissionState(p,_)}}let o=classifyModelCallError(t),s=createErrorId(),c=o===`terminal`?summarizeKnownModelCallConfigError(t):null,d=c===null?summarizeKnownModelCallRequestError(t):null,f=c?.message??d?.message??toErrorMessage(t),m=extractModelCallErrorDetails(t),h=buildModelCallFailureDetails({configSummary:c,error:t,errorId:s,modelCallDetails:m,requestSummary:d}),g=buildModelCallFailureLogFields({error:t,errorId:s,modelCallDetails:m,requestSummary:d,sessionId:p.sessionId,turnId:_.turnId});return o===`terminal`?(c===null?log.error(d?.message??`model call failed terminally`,g):log.error(`${c.name}: ${c.message}`,{errorId:s,sessionId:p.sessionId,turnId:_.turnId}),await emitFailedStep(n,_,{code:`MODEL_CALL_FAILED`,details:h,message:f,sessionId:p.sessionId}),{next:{done:!0,output:``},session:p}):(log.error(d?.message??`model call failed — parking session for retry by the user`,g),_=await emitRecoverableFailedTurn(n,_,{code:`MODEL_CALL_FAILED`,details:h,message:f}),{next:null,session:setHarnessEmissionState(p,_)})}}let W=accumulateTurnUsage({previous:getTurnUsageState(p.state),turnId:_.turnId,usage:U.usage??{}});p=setTurnUsageState(p,W);let G;try{G=formatLanguageModelGatewayId(A)}catch{G=void 0}return await setAshAttributes({"$ash.model":G,"$ash.input_tokens":W.inputTokens,"$ash.output_tokens":W.outputTokens,"$ash.cache_read_tokens":W.cacheReadTokens,"$ash.tool_count":t.tools.size}),handleStepResult({config:t,emit:n,emissionState:_,promptMessages:k,result:U,runStep,session:p})}return runStep}function buildModelCallFailureDetails(e){let{configSummary:t,error:r,errorId:i,modelCallDetails:a,requestSummary:o}=e;return t===null?o===null?{...formatError(r,i),...a}:{errorId:i,message:toErrorMessage(r),name:o.name,...a}:{errorId:i,message:t.message,name:t.name,...a}}function buildModelCallFailureLogFields(e){let t={errorId:e.errorId,sessionId:e.sessionId,turnId:e.turnId};return e.requestSummary===null?{...t,error:e.error}:{...t,details:e.modelCallDetails}}async function attemptUnsupportedProviderToolRecovery(e){let t=extractUnsupportedProviderToolTypes(e.error);if(t.length===0)return{outcome:`failed`,error:e.error};let n=[];for(let e of t){let t=resolveFrameworkToolFromUpstreamType(e);t!==null&&!n.includes(t)&&n.push(t)}if(n.length===0)return{outcome:`failed`,error:e.error};log.warn(`disabling unsupported provider tool(s); retrying step once`,{disabled:n,sessionId:e.sessionId,turnId:e.turnId,upstreamTypes:t});try{return{outcome:`recovered`,result:await e.runOneModelCall({disabledProviderTools:new Set(n),extraSystemNote:buildDisabledToolNote(n),suppressStepStartedEmission:!0})}}catch(e){return{outcome:`failed`,error:e}}}function buildDisabledToolNote(e){let t=e.join(`, `);return`The following ${e.length===1?`tool is`:`tools are`} not available with the current model and has been removed: ${t}. Proceed using the remaining tools or your training knowledge.`}async function handleStepResult(e){let{config:t,emit:n,promptMessages:r,result:i,runStep:o}=e,{emissionState:s,session:l}=e,u=i.response.messages,d=resolveAssistantStepText(u,i.text),f={...l,compaction:createNextCompactionConfig(l.compaction,r,i)};if(t.codeMode===!0){let{getCodeModeInterrupt:e,isCodeModeApprovalInterrupt:a}=await loadCodeModeModule(),o=e(i);if(o!==void 0){if(isCodeModeConnectionAuthInterrupt(o))return parkOnCodeModeConnectionAuth({baseSession:f,config:t,emit:n,emissionState:s,interrupt:o,promptMessages:r,responseMessages:u});if(a(o))return parkOnCodeModeApproval({baseSession:f,config:t,emit:n,emissionState:s,interrupt:o,promptMessages:r,responseMessages:u})}}let p=extractToolApprovalInputRequests({content:i.content??[]}),m=new Set(p.map(e=>e.action.callId)),h=extractQuestionInputRequests({toolCalls:i.toolCalls,excludedCallIds:m}),g=[...p,...h],v=(i.toolCalls??[]).filter(e=>!isInvalidToolCall(e)).filter(e=>t.tools.get(e.toolName)?.runtimeAction!==void 0).map(e=>createRuntimeActionRequestFromToolCall({toolCall:e,tools:t.tools}));if(v.length>0)return{next:null,session:setHarnessEmissionState(setPendingRuntimeActionBatch({actions:v,event:{sequence:s.sequence,stepIndex:s.stepIndex,turnId:s.turnId},responseMessages:u,session:{...f,history:[...r]}}),s)};if(g.length>0){let e=setPendingInputBatch({requests:g,responseMessages:u,session:{...f,history:[...r]}});return n&&(await n(createInputRequestedEvent({requests:g,sequence:s.sequence,stepIndex:s.stepIndex,turnId:s.turnId})),t.mode===`conversation`&&(s=await emitTurnEpilogue(n,s,t.mode),e=setHarnessEmissionState(e,s))),{next:null,session:e}}let x=(i.toolResults??[]).find(e=>isAuthorizationSignal(e.output));if(x&&isAuthorizationSignal(x.output)){let{challenges:e}=x.output;if(n)for(let t of e)await n(createAuthorizationRequiredEvent({authorization:t.challenge,name:t.name,description:t.challenge.instructions??`Authorization required for ${t.name}`,webhookUrl:t.hookUrl,sequence:s.sequence,stepIndex:s.stepIndex,turnId:s.turnId}));return{next:null,session:setHarnessEmissionState({...f,history:[...r],state:setPendingAuthorization(f.state,{challenges:e})},s)}}let S=pruneToolResults(r),C=S!==r,w=f.compaction;C&&w.lastKnownInputTokens!==void 0&&(w={recentWindowSize:w.recentWindowSize,threshold:w.threshold});let E=[...S,...u],D={...f,compaction:w,history:E},O=!(D.outputSchema!==void 0&&extractFinalOutput(i)!==void 0)&&(u.at(-1)?.role===`tool`||hasDeferredStepInput(D));return!O&&D.outputSchema===void 0&&d===null&&log.warn(`model completed terminal step without visible assistant text`,{finishReason:i.finishReason,mode:t.mode,responseMessageCount:u.length,responseMessageRoles:u.map(e=>e.role),sequence:s.sequence,sessionId:l.sessionId,stepIndex:s.stepIndex,turnId:s.turnId}),O?(n&&(s=advanceStep(s),D=setHarnessEmissionState(D,s)),{next:o,session:D}):t.mode===`task`?finishTaskTurn({emissionState:s,emit:n,prunedHistory:S,result:i,schema:D.outputSchema,session:D,stepOutput:d}):finishConversationTurn({emissionState:s,emit:n,prunedHistory:S,result:i,schema:D.outputSchema,session:D})}const OUTPUT_SCHEMA_NOT_FULFILLED={code:`OUTPUT_SCHEMA_NOT_FULFILLED`,message:`The agent could not produce a result matching the requested schema.`};function extractFinalOutput(e){return(e.toolCalls??[]).find(e=>e.toolName===FINAL_OUTPUT_TOOL_NAME)?.input}function persistStructuredAssistantTurn(e,t,n){return{...e,history:[...t,{content:JSON.stringify(n),role:`assistant`}],outputSchema:void 0}}async function emitStructuredResult(e,t,n,r){return await e(createResultCompletedEvent({result:n,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),emitTurnEpilogue(e,t,r)}async function finishTaskTurn(e){let{emit:t,prunedHistory:n,result:r,schema:i,stepOutput:a}=e,{emissionState:o,session:s}=e;if(i===void 0)return t&&(o=await emitTurnEpilogue(t,o,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:a??``},session:s};let c=extractFinalOutput(r);return c===void 0?(t&&await emitFailedStep(t,o,{...OUTPUT_SCHEMA_NOT_FULFILLED,sessionId:s.sessionId}),{next:{done:!0,isError:!0,output:OUTPUT_SCHEMA_NOT_FULFILLED.message},session:s}):(s=persistStructuredAssistantTurn(s,n,c),t&&(o=await emitStructuredResult(t,o,c,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:c},session:s})}async function finishConversationTurn(e){let{emit:t,prunedHistory:n,result:r,schema:i}=e,{emissionState:a,session:o}=e;if(i===void 0)return t&&(a=await emitTurnEpilogue(t,a,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o};let s=extractFinalOutput(r);return s===void 0?(t&&(a=await emitRecoverableFailedTurn(t,a,OUTPUT_SCHEMA_NOT_FULFILLED),o=setHarnessEmissionState(o,a)),{next:null,session:o}):(o=persistStructuredAssistantTurn(o,n,s),t&&(a=await emitStructuredResult(t,a,s,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o})}async function continuePendingCodeModeApproval(e){let t=getPendingCodeModeApproval(e.session.state);if(t===void 0)return null;let{continueCodeModeApproval:n,getCodeModeApprovalResponse:i,isCodeModeApprovalInterrupt:a,unwrapCodeModeResult:o}=await loadCodeModeModule(),s=i([...e.messages],t.interrupt);if(s===void 0)return{next:null,session:e.session};let c=await buildCodeModeHostTools({approvedTools:getApprovedTools(e.session),capabilities:e.capabilities,tools:e.config.tools}),l;try{l=await n({approvalResponse:s,interrupt:t.interrupt,options:createAshCodeModeOptions({lifecycle:e.emit===void 0?void 0:createCodeModeLifecycle({emit:e.emit,emissionState:e.emissionState,skipReplayed:!0,tools:e.config.tools})}),tools:c})}catch(e){logError(log,`code-mode approval continuation failed`,e),l={error:`code_mode_continuation_failed`,message:toErrorMessage(e),retryable:!1}}let d=o(l),f=d.status===`interrupted`?d.interrupt:d.output,p=replaceCodeModeApprovalInterruptResult([...e.session.history,...t.responseMessages],t.interrupt,f),m=clearPendingCodeModeApproval({...e.session,history:p});if(d.status===`interrupted`){if(isCodeModeConnectionAuthInterrupt(d.interrupt)){let t=e.session.history.length,n=p.slice(0,t),r=p.slice(t);return m={...m,history:n},parkOnCodeModeConnectionAuth({baseSession:m,config:e.config,emit:e.emit,emissionState:e.emissionState,interrupt:d.interrupt,promptMessages:n,responseMessages:r})}if(a(d.interrupt)){let t=e.session.history.length,n=p.slice(0,t),r=p.slice(t);return m={...m,history:n},parkOnCodeModeApproval({baseSession:m,config:e.config,emit:e.emit,emissionState:e.emissionState,interrupt:d.interrupt,promptMessages:n,responseMessages:r})}}return{next:e.runStep,session:m}}async function parkOnCodeModeConnectionAuth(e){let t=[...e.interrupt.payload.challenges??[]];if(e.emit)for(let n of t)await e.emit(createAuthorizationRequiredEvent({authorization:n.challenge,name:n.name,description:n.challenge.instructions??`Authorization required for ${n.name}`,webhookUrl:n.hookUrl,sequence:e.emissionState.sequence,stepIndex:e.emissionState.stepIndex,turnId:e.emissionState.turnId}));return{next:null,session:setPendingCodeModeConnectionAuth({interrupt:e.interrupt,responseMessages:e.responseMessages,session:{...e.baseSession,history:[...e.promptMessages],state:setPendingAuthorization(e.baseSession.state,{challenges:t})}})}}async function continuePendingCodeModeConnectionAuth(e){let t=getPendingCodeModeConnectionAuth(e.session.state);if(t===void 0)return null;let{continueCodeModeInterrupt:n,isCodeModeApprovalInterrupt:i,replaceCodeModeInterruptResult:a,unwrapCodeModeResult:o}=await loadCodeModeModule(),s=await buildCodeModeHostTools({approvedTools:getApprovedTools(e.session),capabilities:e.capabilities,tools:e.config.tools}),c=e.emit===void 0?void 0:createCodeModeLifecycle({emit:e.emit,emissionState:e.emissionState,skipReplayed:!0,tools:e.config.tools}),l;try{l=await n({interrupt:t.interrupt,resolution:{status:`authorized`},tools:s,options:createAshCodeModeOptions({lifecycle:c})})}catch(e){logError(log,`code-mode interrupt continuation failed`,e),l={error:`code_mode_continuation_failed`,message:toErrorMessage(e),retryable:!1}}let d=o(l),f=d.status===`interrupted`?d.interrupt:d.output,p=a([...e.session.history,...t.responseMessages],t.interrupt.pendingContinuation,f),m=clearPendingCodeModeConnectionAuth({...e.session,history:p});if(d.status===`interrupted`){if(isCodeModeConnectionAuthInterrupt(d.interrupt)){let t=e.session.history.length,n=p.slice(0,t),r=p.slice(t);return m={...m,history:n},parkOnCodeModeConnectionAuth({baseSession:m,config:e.config,emit:e.emit,emissionState:e.emissionState,interrupt:d.interrupt,promptMessages:n,responseMessages:r})}if(i(d.interrupt)){let t=e.session.history.length,n=p.slice(0,t),r=p.slice(t);return m={...m,history:n},parkOnCodeModeApproval({baseSession:m,config:e.config,emit:e.emit,emissionState:e.emissionState,interrupt:d.interrupt,promptMessages:n,responseMessages:r})}}return{next:e.runStep,session:m}}async function parkOnCodeModeApproval(e){let{toCodeModeApprovalMessages:t}=await loadCodeModeModule(),n=t(e.interrupt),r=extractToolApprovalInputRequests({content:extractAssistantContent(n)}),i=setPendingInputBatch({requests:r,responseMessages:n,session:setPendingCodeModeApproval({interrupt:e.interrupt,responseMessages:e.responseMessages,session:{...e.baseSession,history:[...e.promptMessages]}})});if(e.emit&&(await e.emit(createInputRequestedEvent({requests:r,sequence:e.emissionState.sequence,stepIndex:e.emissionState.stepIndex,turnId:e.emissionState.turnId})),e.config.mode===`conversation`)){let t=await emitTurnEpilogue(e.emit,e.emissionState,e.config.mode);i=setHarnessEmissionState(i,t)}return{next:null,session:i}}function extractAssistantContent(e){let t=[];for(let n of e)n.role===`assistant`&&Array.isArray(n.content)&&t.push(...n.content);return t}function createNextCompactionConfig(e,t,n){let r={recentWindowSize:e.recentWindowSize,threshold:e.threshold};return n.usage?.inputTokens!==void 0&&(r.lastKnownInputTokens=n.usage.inputTokens,r.lastKnownPromptMessageCount=t.length),r}async function maybeCompact(e){let{emit:t,emissionState:n}=e,r=e.messages,i=e.session;if(!shouldCompact(r,i.compaction))return{messages:r,session:i};let a=await resolveCompactionModel({compactionModelReference:i.agent.compactionModelReference,model:e.model,modelReference:i.agent.modelReference,resolveModel:e.resolveModel});if(t&&await t(createCompactionRequestedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId,usageInputTokens:getInputTokenCount(r,i.compaction)})),r=await compactMessages(r,a.model,i.compaction,a.providerOptions,e.telemetry,e.headers),e.onCompaction){let t=await e.onCompaction(i);i=t.session;for(let e of t.messages)r.push(e)}return t&&await t(createCompactionCompletedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId})),{messages:r,session:i}}function resolveApprovalKeyFromTools(e){return t=>{let n=e.get(t.action.toolName);if(n?.approvalKey!==void 0)return n.approvalKey(t.action.input)}}async function runModelCallWithRetries(e,t){for(let n=1;;n++)try{return await e()}catch(e){if(n===3||classifyModelCallError(e)!==`retry`)throw e;let r=500*2**(n-1)+Math.floor(Math.random()*250);log.warn(`model call failed transiently — retrying`,{attempt:n,delayMs:r,sessionId:t.sessionId,turnId:t.turnId,error:e}),await new Promise(e=>setTimeout(e,r))}}export{createToolLoopHarness};
@@ -114,7 +114,7 @@ export interface StepInput {
114
114
  */
115
115
  export interface StepDone {
116
116
  readonly done: true;
117
- readonly output: string;
117
+ readonly output: unknown;
118
118
  /**
119
119
  * Marks a terminal turn that failed (e.g. a task-mode turn that could not
120
120
  * fulfil its output schema). For a delegated subagent this routes the result
@@ -1 +1 @@
1
- import{createRequire}from"node:module";import{basename,dirname,join}from"node:path";import{existsSync,readFileSync,realpathSync}from"node:fs";import{ASH_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const WORKFLOW_MODULE_ALIASES={"workflow/api":`src/compiled/@workflow/core/runtime.js`,"workflow/errors":`src/compiled/@workflow/errors/index.js`,"workflow/internal/private":`src/compiled/@workflow/core/private.js`,"workflow/runtime":`src/compiled/@workflow/core/runtime.js`};function resolveFallbackPackageVersion(){return`0.57.0`}const FALLBACK_PACKAGE_INFO={name:ASH_PACKAGE_NAME,version:resolveFallbackPackageVersion()};function resolveCurrentModulePath(){return typeof __filename==`string`?__filename:resolveCurrentModulePathFromStack()}function resolveCurrentModulePathFromStack(){let e=Error.prepareStackTrace;try{Error.prepareStackTrace=(e,t)=>t;let e=Error().stack?.[0]?.getFileName();if(typeof e!=`string`||e.length===0)throw Error(`Failed to resolve the current module path from the stack trace.`);return e.startsWith(`file:`)?fileURLToPath(e):e}finally{Error.prepareStackTrace=e}}const require=createRequire(resolveCurrentModulePath());function isBuildOutputPackageRoot(e){return basename(e)===`dist`&&existsSync(join(dirname(e),`package.json`))}function resolvePackageBuildRoot(){let e=dirname(realpathSync(resolveCurrentModulePath()));for(;;){if(isBuildOutputPackageRoot(e))return e;let t=dirname(e);if(t===e)return null;e=t}}function findNearestPackageRoot(e){let t=e;for(;;){if(existsSync(join(t,`package.json`))&&!isBuildOutputPackageRoot(t))return t;let r=dirname(t);if(r===t)throw Error(`Failed to resolve package root from "${e}".`);t=r}}function resolvePackageRoot(){return findNearestPackageRoot(dirname(realpathSync(resolveCurrentModulePath())))}function tryResolvePackageRoot(){try{return resolvePackageRoot()}catch{return}}function rewriteSourceFilePathForBuild(e){return e.replace(/\.[cm]?tsx?$/,`.js`)}function resolvePackageSourceFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),e):join(t,rewriteSourceFilePathForBuild(e))}function resolvePackageSourceDirectoryPath(e){let t=resolvePackageBuildRoot();return join(t===null?resolvePackageRoot():t,e)}function resolvePackageCompiledFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),`.generated`,`compiled`,e.replace(/^src\/compiled\//,``)):join(t,e)}function normalizeInstalledPackageInfo(e){let t=e;if(!(typeof t.name!=`string`||typeof t.version!=`string`))return{name:t.name,version:t.version}}function tryReadInstalledPackageInfo(e,t){let n=normalizeInstalledPackageInfo(JSON.parse(readFileSync(e,`utf8`)));if(n?.name===t)return n}function resolveInstalledPackageInfo(){if(cachedPackageInfo)return cachedPackageInfo;let e=tryResolvePackageRoot(),t=e===void 0?void 0:tryReadInstalledPackageInfo(join(e,`package.json`),ASH_PACKAGE_NAME);if(t)return cachedPackageInfo=t,cachedPackageInfo;try{let e=tryReadInstalledPackageInfo(require.resolve(`${ASH_PACKAGE_NAME}/package.json`),ASH_PACKAGE_NAME);if(e)return cachedPackageInfo=e,cachedPackageInfo}catch{}return cachedPackageInfo={...FALLBACK_PACKAGE_INFO},cachedPackageInfo}function resolveWorkflowModulePath(e){if(e===`workflow`)return resolvePackageSourceFilePath(`src/internal/workflow/index.ts`);if(e===`workflow/internal/builtins`)return resolvePackageSourceFilePath(`src/internal/workflow/builtins.ts`);let t=WORKFLOW_MODULE_ALIASES[e];return t===void 0?require.resolve(e):resolvePackageCompiledFilePath(t)}export{resolveInstalledPackageInfo,resolvePackageRoot,resolvePackageSourceDirectoryPath,resolvePackageSourceFilePath,resolveWorkflowModulePath};
1
+ import{createRequire}from"node:module";import{basename,dirname,join}from"node:path";import{existsSync,readFileSync,realpathSync}from"node:fs";import{ASH_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const WORKFLOW_MODULE_ALIASES={"workflow/api":`src/compiled/@workflow/core/runtime.js`,"workflow/errors":`src/compiled/@workflow/errors/index.js`,"workflow/internal/private":`src/compiled/@workflow/core/private.js`,"workflow/runtime":`src/compiled/@workflow/core/runtime.js`};function resolveFallbackPackageVersion(){return`0.58.0`}const FALLBACK_PACKAGE_INFO={name:ASH_PACKAGE_NAME,version:resolveFallbackPackageVersion()};function resolveCurrentModulePath(){return typeof __filename==`string`?__filename:resolveCurrentModulePathFromStack()}function resolveCurrentModulePathFromStack(){let e=Error.prepareStackTrace;try{Error.prepareStackTrace=(e,t)=>t;let e=Error().stack?.[0]?.getFileName();if(typeof e!=`string`||e.length===0)throw Error(`Failed to resolve the current module path from the stack trace.`);return e.startsWith(`file:`)?fileURLToPath(e):e}finally{Error.prepareStackTrace=e}}const require=createRequire(resolveCurrentModulePath());function isBuildOutputPackageRoot(e){return basename(e)===`dist`&&existsSync(join(dirname(e),`package.json`))}function resolvePackageBuildRoot(){let e=dirname(realpathSync(resolveCurrentModulePath()));for(;;){if(isBuildOutputPackageRoot(e))return e;let t=dirname(e);if(t===e)return null;e=t}}function findNearestPackageRoot(e){let t=e;for(;;){if(existsSync(join(t,`package.json`))&&!isBuildOutputPackageRoot(t))return t;let r=dirname(t);if(r===t)throw Error(`Failed to resolve package root from "${e}".`);t=r}}function resolvePackageRoot(){return findNearestPackageRoot(dirname(realpathSync(resolveCurrentModulePath())))}function tryResolvePackageRoot(){try{return resolvePackageRoot()}catch{return}}function rewriteSourceFilePathForBuild(e){return e.replace(/\.[cm]?tsx?$/,`.js`)}function resolvePackageSourceFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),e):join(t,rewriteSourceFilePathForBuild(e))}function resolvePackageSourceDirectoryPath(e){let t=resolvePackageBuildRoot();return join(t===null?resolvePackageRoot():t,e)}function resolvePackageCompiledFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),`.generated`,`compiled`,e.replace(/^src\/compiled\//,``)):join(t,e)}function normalizeInstalledPackageInfo(e){let t=e;if(!(typeof t.name!=`string`||typeof t.version!=`string`))return{name:t.name,version:t.version}}function tryReadInstalledPackageInfo(e,t){let n=normalizeInstalledPackageInfo(JSON.parse(readFileSync(e,`utf8`)));if(n?.name===t)return n}function resolveInstalledPackageInfo(){if(cachedPackageInfo)return cachedPackageInfo;let e=tryResolvePackageRoot(),t=e===void 0?void 0:tryReadInstalledPackageInfo(join(e,`package.json`),ASH_PACKAGE_NAME);if(t)return cachedPackageInfo=t,cachedPackageInfo;try{let e=tryReadInstalledPackageInfo(require.resolve(`${ASH_PACKAGE_NAME}/package.json`),ASH_PACKAGE_NAME);if(e)return cachedPackageInfo=e,cachedPackageInfo}catch{}return cachedPackageInfo={...FALLBACK_PACKAGE_INFO},cachedPackageInfo}function resolveWorkflowModulePath(e){if(e===`workflow`)return resolvePackageSourceFilePath(`src/internal/workflow/index.ts`);if(e===`workflow/internal/builtins`)return resolvePackageSourceFilePath(`src/internal/workflow/builtins.ts`);let t=WORKFLOW_MODULE_ALIASES[e];return t===void 0?require.resolve(e):resolvePackageCompiledFilePath(t)}export{resolveInstalledPackageInfo,resolvePackageRoot,resolvePackageSourceDirectoryPath,resolvePackageSourceFilePath,resolveWorkflowModulePath};
@@ -1,4 +1,4 @@
1
- import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"./files.js";import{PNPM_WORKSPACE_PATH,ensurePnpmWorkspacePolicy}from"./pnpm-workspace.js";import{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"./web-template.js";import"./project.js";import{patchPackageJson}from"./package-json.js";import{basename,join,resolve}from"node:path";import{readFile,readdir,writeFile}from"node:fs/promises";const SLACK_CHANNEL_DEFAULT_ROUTE=`/ash/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`],WEB_VERCEL_JSON_PATH=`vercel.json`,WEB_VERCEL_JSON_SCHEMA=`https://openapi.vercel.sh/vercel.json`,WEB_DEFAULT_VERCEL_SERVICES={web:{entrypoint:`.`,framework:`nextjs`,routePrefix:`/`},ash:{buildCommand:`ash build`,entrypoint:`.`,framework:`ash`,routePrefix:`/_ash_internal/ash`}};function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readDependencyVersion(e,t){let n=JSON.parse(await readFile(e,`utf8`));if(!isJsonObject(n)||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,t){if(!await pathExists(e))return!1;let r=JSON.parse(await readFile(e,`utf8`));return isJsonObject(r)&&packageJsonHasDependency(r,t)}async function ensurePackageDependency(e,t,r){return!await pathExists(e)||await readDependencyVersion(e,t)===r?[]:(await patchPackageJson(e,{dependencies:{[t]:r}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{ashPackageVersion:e?.ashPackageVersion??`0.57.0`,aiPackageVersion:e?.aiPackageVersion??`7.0.0-canary.159`,nextPackageVersion:e?.nextPackageVersion??`16.2.6`,reactPackageVersion:e?.reactPackageVersion??`19.2.6`,reactDomPackageVersion:e?.reactDomPackageVersion??`19.2.6`,streamdownPackageVersion:e?.streamdownPackageVersion??`2.5.0`,zodPackageVersion:e?.zodPackageVersion??`4.4.3`,tsgoPackageVersion:e?.tsgoPackageVersion??`7.0.0-dev.20260523.1`,typesNodePackageVersion:e?.typesNodePackageVersion??`25.9.1`,typesReactPackageVersion:e?.typesReactPackageVersion??`19.2.15`,typesReactDomPackageVersion:e?.typesReactDomPackageVersion??`19.2.3`}}function formatAshDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}async function patchWebPackageJson(e,t){if(!await pathExists(e))return[];assertStampedVersion(`ashPackageVersion`,t.ashPackageVersion),assertStampedVersion(`aiPackageVersion`,t.aiPackageVersion),assertStampedVersion(`nextPackageVersion`,t.nextPackageVersion),assertStampedVersion(`reactPackageVersion`,t.reactPackageVersion),assertStampedVersion(`reactDomPackageVersion`,t.reactDomPackageVersion),assertStampedVersion(`streamdownPackageVersion`,t.streamdownPackageVersion),assertStampedVersion(`zodPackageVersion`,t.zodPackageVersion),assertStampedVersion(`tsgoPackageVersion`,t.tsgoPackageVersion),assertStampedVersion(`typesNodePackageVersion`,t.typesNodePackageVersion),assertStampedVersion(`typesReactPackageVersion`,t.typesReactPackageVersion),assertStampedVersion(`typesReactDomPackageVersion`,t.typesReactDomPackageVersion);let r={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:t.aiPackageVersion,"experimental-ash":formatAshDependencySpecifier(t.ashPackageVersion),next:t.nextPackageVersion,react:t.reactPackageVersion,"react-dom":t.reactDomPackageVersion,streamdown:t.streamdownPackageVersion,zod:t.zodPackageVersion},i={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":t.typesNodePackageVersion,"@types/react":t.typesReactPackageVersion,"@types/react-dom":t.typesReactDomPackageVersion,"@typescript/native-preview":t.tsgoPackageVersion},a=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts;return await patchPackageJson(e,{dependencies:r,devDependencies:i,scripts:a}),[{path:e,dependencies:Object.keys(r),devDependencies:Object.keys(i),scripts:Object.keys(a)}]}function normalizeSlackConnectorSlug(e){return toSlackConnectorSlug((e.trim().replace(/^@/,``).split(`/`).at(-1)??``).toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/[^a-z0-9]+$/,``).slice(0,100).replace(/[^a-z0-9]+$/,``)||`my-agent`)}async function deriveSlackConnectorSlug(e,t){if(t!==void 0&&t.length>0&&t!==`.`)return normalizeSlackConnectorSlug(t);try{let t=await readFile(join(e,`package.json`),`utf8`),n=JSON.parse(t);if(typeof n.name==`string`&&n.name.length>0)return normalizeSlackConnectorSlug(n.name)}catch{}return normalizeSlackConnectorSlug(basename(resolve(e))||`my-agent`)}function buildSlackTemplate(e){return`import { connectSlackCredentials } from "@vercel/connect/ash";
1
+ import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"./files.js";import{PNPM_WORKSPACE_PATH,ensurePnpmWorkspacePolicy}from"./pnpm-workspace.js";import{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"./web-template.js";import"./project.js";import{patchPackageJson}from"./package-json.js";import{basename,join,resolve}from"node:path";import{readFile,readdir,writeFile}from"node:fs/promises";const SLACK_CHANNEL_DEFAULT_ROUTE=`/ash/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`],WEB_VERCEL_JSON_PATH=`vercel.json`,WEB_VERCEL_JSON_SCHEMA=`https://openapi.vercel.sh/vercel.json`,WEB_DEFAULT_VERCEL_SERVICES={web:{entrypoint:`.`,framework:`nextjs`,routePrefix:`/`},ash:{buildCommand:`ash build`,entrypoint:`.`,framework:`ash`,routePrefix:`/_ash_internal/ash`}};function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readDependencyVersion(e,t){let n=JSON.parse(await readFile(e,`utf8`));if(!isJsonObject(n)||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,t){if(!await pathExists(e))return!1;let r=JSON.parse(await readFile(e,`utf8`));return isJsonObject(r)&&packageJsonHasDependency(r,t)}async function ensurePackageDependency(e,t,r){return!await pathExists(e)||await readDependencyVersion(e,t)===r?[]:(await patchPackageJson(e,{dependencies:{[t]:r}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{ashPackageVersion:e?.ashPackageVersion??`0.58.0`,aiPackageVersion:e?.aiPackageVersion??`7.0.0-canary.159`,nextPackageVersion:e?.nextPackageVersion??`16.2.6`,reactPackageVersion:e?.reactPackageVersion??`19.2.6`,reactDomPackageVersion:e?.reactDomPackageVersion??`19.2.6`,streamdownPackageVersion:e?.streamdownPackageVersion??`2.5.0`,zodPackageVersion:e?.zodPackageVersion??`4.4.3`,tsgoPackageVersion:e?.tsgoPackageVersion??`7.0.0-dev.20260523.1`,typesNodePackageVersion:e?.typesNodePackageVersion??`25.9.1`,typesReactPackageVersion:e?.typesReactPackageVersion??`19.2.15`,typesReactDomPackageVersion:e?.typesReactDomPackageVersion??`19.2.3`}}function formatAshDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}async function patchWebPackageJson(e,t){if(!await pathExists(e))return[];assertStampedVersion(`ashPackageVersion`,t.ashPackageVersion),assertStampedVersion(`aiPackageVersion`,t.aiPackageVersion),assertStampedVersion(`nextPackageVersion`,t.nextPackageVersion),assertStampedVersion(`reactPackageVersion`,t.reactPackageVersion),assertStampedVersion(`reactDomPackageVersion`,t.reactDomPackageVersion),assertStampedVersion(`streamdownPackageVersion`,t.streamdownPackageVersion),assertStampedVersion(`zodPackageVersion`,t.zodPackageVersion),assertStampedVersion(`tsgoPackageVersion`,t.tsgoPackageVersion),assertStampedVersion(`typesNodePackageVersion`,t.typesNodePackageVersion),assertStampedVersion(`typesReactPackageVersion`,t.typesReactPackageVersion),assertStampedVersion(`typesReactDomPackageVersion`,t.typesReactDomPackageVersion);let r={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:t.aiPackageVersion,"experimental-ash":formatAshDependencySpecifier(t.ashPackageVersion),next:t.nextPackageVersion,react:t.reactPackageVersion,"react-dom":t.reactDomPackageVersion,streamdown:t.streamdownPackageVersion,zod:t.zodPackageVersion},i={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":t.typesNodePackageVersion,"@types/react":t.typesReactPackageVersion,"@types/react-dom":t.typesReactDomPackageVersion,"@typescript/native-preview":t.tsgoPackageVersion},a=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts;return await patchPackageJson(e,{dependencies:r,devDependencies:i,scripts:a}),[{path:e,dependencies:Object.keys(r),devDependencies:Object.keys(i),scripts:Object.keys(a)}]}function normalizeSlackConnectorSlug(e){return toSlackConnectorSlug((e.trim().replace(/^@/,``).split(`/`).at(-1)??``).toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/[^a-z0-9]+$/,``).slice(0,100).replace(/[^a-z0-9]+$/,``)||`my-agent`)}async function deriveSlackConnectorSlug(e,t){if(t!==void 0&&t.length>0&&t!==`.`)return normalizeSlackConnectorSlug(t);try{let t=await readFile(join(e,`package.json`),`utf8`),n=JSON.parse(t);if(typeof n.name==`string`&&n.name.length>0)return normalizeSlackConnectorSlug(n.name)}catch{}return normalizeSlackConnectorSlug(basename(resolve(e))||`my-agent`)}function buildSlackTemplate(e){return`import { connectSlackCredentials } from "@vercel/connect/ash";
2
2
  import { slackChannel } from "experimental-ash/channels/slack";
3
3
 
4
4
  export default slackChannel({
@@ -1 +1 @@
1
- import"./deploy-to-vercel.js";import"./run-add-to-agent.js";export{};
1
+ import"./deploy-to-vercel.js";import"./project-resolution.js";import"./run-add-to-agent.js";export{};
@@ -0,0 +1 @@
1
+ function projectResolutionFromDeployment(e){return e.state===`unlinked`||e.projectId===void 0?{kind:`unresolved`}:e.state===`deployed`&&e.productionUrl!==void 0?{kind:`deployed`,projectId:e.projectId,productionUrl:e.productionUrl}:{kind:`linked`,projectId:e.projectId}}function mergeProjectResolution(e,t){return t.kind===`unresolved`||e.kind===`deployed`&&e.projectId===t.projectId?e:t}function projectResolutionFromDeployResult(e,t){return e.kind===`unresolved`||!t.deployed||t.productionUrl===void 0?e:{kind:`deployed`,projectId:e.projectId,productionUrl:t.productionUrl}}function isProjectResolved(e){return e.kind!==`unresolved`}export{isProjectResolved,mergeProjectResolution,projectResolutionFromDeployResult,projectResolutionFromDeployment};
@@ -1,2 +1,2 @@
1
- import{deriveSlackConnectorSlug,ensureChannel}from"../channels.js";import{HumanActionRequiredError}from"../human-action.js";import{createPromptCommandOutput}from"../cli/command-output.js";import{runVercel}from"../primitives/run-vercel.js";import{detectDeployment}from"../primitives/detect-deployment.js";import{deployToVercel}from"./deploy-to-vercel.js";import"../cli/channel-setup-prompter.js";import{runPnpmInstall}from"../primitives/run-pnpm.js";import{reconcileSlackUid,setupSlackbot}from"./setup-slackbot.js";const CHANNEL_OPTIONS=[{value:`web`,label:`Web Chat`},{value:`slack`,label:`Slack`,hint:`creates slackbot and deploys to Vercel`}];function selectableChannels(e){return CHANNEL_OPTIONS.map(t=>{let n=e?.[t.value];return n===void 0?t:{...t,disabled:!0,disabledReason:n}})}function createAddToAgentState(e={state:`unlinked`}){return{channels:[],webScaffolded:!1,slackScaffolded:!1,deploymentDependenciesInstalled:!1,projectLinked:e.state!==`unlinked`,vercelProjectId:e.projectId,deployed:e.state===`deployed`,deploymentPending:!1,productionUrl:e.productionUrl,slackbotCreated:!1,slackbotAttached:!1,slackConnectorUid:void 0,slackWorkspaceUrl:void 0,slackWorkspaceName:void 0}}function recordScaffoldedChannel(e,t){e.channels.includes(t)||(e.channels.push(t),e.deploymentPending=!0)}function warnOverwrittenFiles(e,t){for(let n of t??[])e.log.warning(`Overwrote ${n}`)}async function promptCreateSlackbot(e){return await e.select({message:`Do you want to create your slackbot?`,options:[{value:`yes`,label:`Yes`,hint:`connects Slack, then deploys`},{value:`no`,label:`No`}]})===`yes`}async function installDeploymentDependencies(e,t,n){if(!n.deploymentDependenciesInstalled){if(e.log.message(`Installing project dependencies before deployment (pnpm install)...`),!await runPnpmInstall(t,{onOutput:createPromptCommandOutput(e.log)}))throw Error(`Dependency installation failed. Deployment did not start.`);n.deploymentDependenciesInstalled=!0}}async function linkProjectForSlackbot(e){if(e.state.projectLinked)return;let t;if(e.linkProjectForSlackbot!==void 0)t=await e.linkProjectForSlackbot();else if(e.headless)throw new HumanActionRequiredError({kind:`vercel-link`,command:`vercel link`,reason:`Slack needs this directory linked to a Vercel project.`});else e.prompter.log.message(`Linking this directory to a Vercel project...`),t=await runVercel([`link`],{cwd:e.projectPath});if(!t)throw Error(`Vercel project linking failed. Slackbot creation did not start.`);e.state.projectLinked=!0;let r=await detectDeployment(e.projectPath);e.state.vercelProjectId=r.projectId??e.state.vercelProjectId,e.state.productionUrl=r.productionUrl??e.state.productionUrl,e.state.deployed=e.state.deployed||r.state===`deployed`}async function scaffoldSlackChannel(e,n){let{prompter:r,projectPath:i,state:a}=e;if(!a.slackScaffolded){r.log.message(`Scaffolding Slack channel files...`);let o=await ensureChannel({projectRoot:i,kind:`slack`,slackConnectorSlug:n,force:e.force});warnOverwrittenFiles(r,o.filesOverwritten),o.action===`created`||o.action===`overwritten`?r.log.success(`Scaffolded channel: slack`):r.log.info(`Channel "slack" already exists. Skipping file creation.`),a.slackScaffolded=!0}recordScaffoldedChannel(a,`slack`)}async function linkProjectForDeployment(e){let{prompter:t,projectPath:a,state:o}=e;if(o.projectLinked)return;let s=e.vercelProjectId??o.vercelProjectId,c=createPromptCommandOutput(t.log);if(s===void 0){if(e.headless)throw new HumanActionRequiredError({kind:`vercel-link`,command:`vercel link`,reason:`Deployment needs this directory linked to a Vercel project.`});if(t.log.message(`Linking this directory to a Vercel project before deployment...`),!await runVercel([`link`],{cwd:a,onOutput:c}))throw Error(`Vercel project linking failed. Deployment did not start.`)}else{if(t.log.message(`Linking this directory to Vercel project "${s}" before deployment...`),!await runVercel([`link`,`--project`,s,`--yes`],{cwd:a,onOutput:c}))throw Error(`Vercel project linking failed. Deployment did not start.`);o.vercelProjectId=s}o.projectLinked=!0}async function deployProject(e){let{prompter:t,projectPath:n,state:r}=e;if(!r.deploymentPending)return;await linkProjectForDeployment(e),await installDeploymentDependencies(t,n,r);let i=await deployToVercel(t,n,{presetDeploy:!0});if(r.deployed=i.deployed,r.productionUrl=i.productionUrl??r.productionUrl,!r.deployed)throw Error(`Deployment failed after channel setup.`);r.deploymentPending=!1}async function reconcilePreparedSlackChannel(e,t,n,r){let i=n.slackConnectorUid;if(i===void 0)throw Error(`Slack connector UID was not resolved. Slack deployment did not start.`);if(!await reconcileSlackUid(e,t,{kind:`attached`,created:!0,attached:!0,connectorUid:i},r))throw Error(`Slack connector UID update is required before deployment.`)}function recordAttachedSlackbot(e,t){e.slackbotCreated=!0,e.slackbotAttached=!0,e.slackConnectorUid=t.connectorUid,e.slackWorkspaceUrl=t.workspaceUrl,e.slackWorkspaceName=t.workspaceName}async function runAddToAgentOnce(n,r){let{prompter:i,projectPath:a,projectName:o,state:s}=n;if(n.headless&&r.includes(`slack`))throw Error(`Slack setup is interactive. Run the guided create flow with -i, or add Slack from the onboarding steps after headless scaffolding.`);if(r.includes(`web`))if(s.webScaffolded)recordScaffoldedChannel(s,`web`);else{i.log.message(`Scaffolding Web Chat channel files...`);let e=await ensureChannel({projectRoot:a,kind:`web`,force:n.force,webPackageVersions:n.webPackageVersions,configureVercelServices:n.configureVercelServices});warnOverwrittenFiles(i,e.filesOverwritten),e.action===`created`||e.action===`overwritten`?(i.log.success(`Scaffolded channel: web`),s.webScaffolded=!0,recordScaffoldedChannel(s,`web`)):i.log.info(`Next.js project detected. Skipping Web Chat scaffolding.`)}if(r.includes(`slack`)){let t=await deriveSlackConnectorSlug(a,o);if(s.slackbotCreated){if(!s.slackbotAttached)throw Error(`Slackbot provisioning did not attach this project. Slack channel was not added.`);s.deploymentPending&&(await scaffoldSlackChannel(n,t),await reconcilePreparedSlackChannel(i,a,s,`slack/${t}`))}else if(n.presetCreateSlackbot??await promptCreateSlackbot(i)){await linkProjectForSlackbot(n);let e=await setupSlackbot(i,a,{presetCreate:!0,slackbotName:t});if(!e.created)throw Error(`Slackbot creation failed.`);if(e.kind!==`attached`)throw Error(`Slackbot provisioning did not attach this project. Slack channel was not added.`);recordAttachedSlackbot(s,e),await scaffoldSlackChannel(n,t),await reconcilePreparedSlackChannel(i,a,s,`slack/${t}`)}else i.log.info(`Slack channel was not added because Slackbot setup was skipped.`)}}async function runAddToAgent(e){for(;;){let t=e.presetChannels??await e.prompter.multiselect({message:`Add to agent`,options:selectableChannels(e.disabledChannelReasons),required:!1});await e.validateSelectedChannels?.(t);try{await runAddToAgentOnce(e,t);return}catch(t){if(t instanceof Error&&(t.name===`WizardCancelledError`||t.name===`ChannelAddCancelledError`))throw t;let n=t instanceof Error?t.message:String(t),r=n.split(`
2
- `)[0]?.trim()??n;if(e.prompter.log.error(r),e.presetChannels!==void 0)throw t}}}export{createAddToAgentState,deployProject,runAddToAgent};
1
+ import{deriveSlackConnectorSlug,ensureChannel}from"../channels.js";import{HumanActionRequiredError}from"../human-action.js";import{createPromptCommandOutput}from"../cli/command-output.js";import{runVercel}from"../primitives/run-vercel.js";import{detectDeployment}from"../primitives/detect-deployment.js";import{deployToVercel}from"./deploy-to-vercel.js";import"../cli/channel-setup-prompter.js";import{runPnpmInstall}from"../primitives/run-pnpm.js";import{isProjectResolved,mergeProjectResolution,projectResolutionFromDeployResult,projectResolutionFromDeployment}from"./project-resolution.js";import{reconcileSlackUid,setupSlackbot}from"./setup-slackbot.js";const CHANNEL_OPTIONS=[{value:`web`,label:`Web Chat`},{value:`slack`,label:`Slack`,hint:`creates slackbot and deploys to Vercel`}];function selectableChannels(e){return CHANNEL_OPTIONS.map(t=>{let n=e?.[t.value];return n===void 0?t:{...t,disabled:!0,disabledReason:n}})}function cloneProjectResolution(e){switch(e.kind){case`unresolved`:return{kind:`unresolved`};case`linked`:return{kind:`linked`,projectId:e.projectId};case`deployed`:return{kind:`deployed`,projectId:e.projectId,productionUrl:e.productionUrl}}}function cloneAddToAgentState(e){return{channels:[...e.channels],webScaffolded:e.webScaffolded,slackScaffolded:e.slackScaffolded,deploymentDependenciesInstalled:e.deploymentDependenciesInstalled,project:cloneProjectResolution(e.project),deploymentPending:e.deploymentPending,slackbotCreated:e.slackbotCreated,slackbotAttached:e.slackbotAttached,slackConnectorUid:e.slackConnectorUid,slackWorkspaceUrl:e.slackWorkspaceUrl,slackWorkspaceName:e.slackWorkspaceName}}function createAddToAgentState(e={state:`unlinked`}){return{channels:[],webScaffolded:!1,slackScaffolded:!1,deploymentDependenciesInstalled:!1,project:projectResolutionFromDeployment(e),deploymentPending:!1,slackbotCreated:!1,slackbotAttached:!1,slackConnectorUid:void 0,slackWorkspaceUrl:void 0,slackWorkspaceName:void 0}}function recordScaffoldedChannel(e,t){e.channels.includes(t)||(e.channels.push(t),e.deploymentPending=!0)}function warnOverwrittenFiles(e,t){for(let n of t??[])e.log.warning(`Overwrote ${n}`)}async function promptCreateSlackbot(e){return await e.select({message:`Do you want to create your slackbot?`,options:[{value:`yes`,label:`Yes`,hint:`connects Slack, then deploys`},{value:`no`,label:`No`}]})===`yes`}async function installDeploymentDependencies(e,t,n){if(!n.deploymentDependenciesInstalled){if(e.log.message(`Installing project dependencies before deployment (pnpm install)...`),!await runPnpmInstall(t,{onOutput:createPromptCommandOutput(e.log)}))throw Error(`Dependency installation failed. Deployment did not start.`);n.deploymentDependenciesInstalled=!0}}async function linkProjectForSlackbot(e){if(isProjectResolved(e.state.project))return;let t;if(e.linkProjectForSlackbot!==void 0)t=await e.linkProjectForSlackbot();else if(e.headless)throw new HumanActionRequiredError({kind:`vercel-link`,command:`vercel link`,reason:`Slack needs this directory linked to a Vercel project.`});else{if(e.prompter.log.message(`Linking this directory to a Vercel project...`),!await runVercel([`link`],{cwd:e.projectPath}))throw Error(`Vercel project linking failed. Slackbot creation did not start.`);t=projectResolutionFromDeployment(await detectDeployment(e.projectPath))}if(e.state.project=mergeProjectResolution(e.state.project,t),!isProjectResolved(e.state.project))throw Error(`Vercel project linking failed. Slackbot creation did not start.`)}async function scaffoldSlackChannel(e,n){let{prompter:r,projectPath:i,state:a}=e;if(!a.slackScaffolded){r.log.message(`Scaffolding Slack channel files...`);let o=await ensureChannel({projectRoot:i,kind:`slack`,slackConnectorSlug:n,force:e.force});warnOverwrittenFiles(r,o.filesOverwritten),o.action===`created`||o.action===`overwritten`?r.log.success(`Scaffolded channel: slack`):r.log.info(`Channel "slack" already exists. Skipping file creation.`),a.slackScaffolded=!0}recordScaffoldedChannel(a,`slack`)}async function linkProjectForDeployment(e){let{prompter:t,projectPath:o,state:s}=e;if(isProjectResolved(s.project))return;let c=createPromptCommandOutput(t.log);if(e.headless)throw new HumanActionRequiredError({kind:`vercel-link`,command:`vercel link`,reason:`Deployment needs this directory linked to a Vercel project.`});if(t.log.message(`Linking this directory to a Vercel project before deployment...`),!await runVercel([`link`],{cwd:o,onOutput:c}))throw Error(`Vercel project linking failed. Deployment did not start.`);let l=await detectDeployment(o);if(s.project=mergeProjectResolution(s.project,projectResolutionFromDeployment(l)),!isProjectResolved(s.project))throw Error(`Vercel project linking failed. Deployment did not start.`)}async function deployProject(e){let t=cloneAddToAgentState(e.state),n={...e,state:t},{prompter:r,projectPath:i}=e;if(!t.deploymentPending)return t;await linkProjectForDeployment(n),await installDeploymentDependencies(r,i,t);let a=await deployToVercel(r,i,{presetDeploy:!0});if(t.project=projectResolutionFromDeployResult(t.project,a),!a.deployed)throw Error(`Deployment failed after channel setup.`);return t.deploymentPending=!1,t}async function reconcilePreparedSlackChannel(e,t,n,r){let i=n.slackConnectorUid;if(i===void 0)throw Error(`Slack connector UID was not resolved. Slack deployment did not start.`);if(!await reconcileSlackUid(e,t,{kind:`attached`,created:!0,attached:!0,connectorUid:i},r))throw Error(`Slack connector UID update is required before deployment.`)}function recordAttachedSlackbot(e,t){e.slackbotCreated=!0,e.slackbotAttached=!0,e.slackConnectorUid=t.connectorUid,e.slackWorkspaceUrl=t.workspaceUrl,e.slackWorkspaceName=t.workspaceName}async function runAddToAgentOnce(n,r){let{prompter:i,projectPath:a,projectName:o,state:s}=n;if(n.headless&&r.includes(`slack`))throw Error(`Slack setup is interactive. Run the guided create flow with -i, or add Slack from the onboarding steps after headless scaffolding.`);if(r.includes(`web`))if(s.webScaffolded)recordScaffoldedChannel(s,`web`);else{i.log.message(`Scaffolding Web Chat channel files...`);let e=await ensureChannel({projectRoot:a,kind:`web`,force:n.force,webPackageVersions:n.webPackageVersions,configureVercelServices:n.configureVercelServices});warnOverwrittenFiles(i,e.filesOverwritten),e.action===`created`||e.action===`overwritten`?(i.log.success(`Scaffolded channel: web`),s.webScaffolded=!0,recordScaffoldedChannel(s,`web`)):i.log.info(`Next.js project detected. Skipping Web Chat scaffolding.`)}if(r.includes(`slack`)){let t=await deriveSlackConnectorSlug(a,o);if(s.slackbotCreated){if(!s.slackbotAttached)throw Error(`Slackbot provisioning did not attach this project. Slack channel was not added.`);s.deploymentPending&&(await scaffoldSlackChannel(n,t),await reconcilePreparedSlackChannel(i,a,s,`slack/${t}`))}else if(n.presetCreateSlackbot??await promptCreateSlackbot(i)){await linkProjectForSlackbot(n);let e=await setupSlackbot(i,a,{presetCreate:!0,slackbotName:t});if(!e.created)throw Error(`Slackbot creation failed.`);if(e.kind!==`attached`)throw Error(`Slackbot provisioning did not attach this project. Slack channel was not added.`);recordAttachedSlackbot(s,e),await scaffoldSlackChannel(n,t),await reconcilePreparedSlackChannel(i,a,s,`slack/${t}`)}else i.log.info(`Slack channel was not added because Slackbot setup was skipped.`)}}async function runAddToAgent(e){let t=cloneAddToAgentState(e.state),n={...e,state:t};for(;;){let r=e.presetChannels??await e.prompter.multiselect({message:`Add to agent`,options:selectableChannels(e.disabledChannelReasons),required:!1});await e.validateSelectedChannels?.(r);try{return await runAddToAgentOnce(n,r),t}catch(t){if(t instanceof Error&&(t.name===`WizardCancelledError`||t.name===`ChannelAddCancelledError`))throw t;let n=t instanceof Error?t.message:String(t),r=n.split(`
2
+ `)[0]?.trim()??n;if(e.prompter.log.error(r),e.presetChannels!==void 0)throw t}}}export{cloneAddToAgentState,createAddToAgentState,deployProject,runAddToAgent};
@@ -1,5 +1,5 @@
1
1
  import{z}from"#compiled/zod/index.js";import{CODE_MODE_TOOL_NAME}from"#shared/code-mode.js";import{FINAL_OUTPUT_TOOL_NAME}from"#runtime/framework-tools/final-output.js";import{MockLanguageModelV3}from"ai/test";import{BOOTSTRAP_RUNTIME_MODEL_ID,BOOTSTRAP_RUNTIME_SYSTEM_PROMPT}from"#runtime/agent/bootstrap.js";import{createBootstrapGenerateResult,createBootstrapStreamResult,estimateTokenCount,getLastUserPromptText,getPromptContentText,getPromptText}from"#runtime/agent/bootstrap-model-utils.js";import{findRelevantSkill,getActivatedSkillIds,getAvailableSkills}from"#runtime/agent/mock-model-skill-selection.js";import{createJsonSchemaSample}from"#runtime/agent/mock-structured-output.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";const authoredRuntimeModelMocks=new Map,bootstrapWeatherPayloadSchema=z.object({city:z.string(),condition:z.string(),summary:z.string(),temperatureF:z.number().finite()}).strict(),ASH_MOCK_AUTHORED_MODELS_ENV=`ASH_MOCK_AUTHORED_MODELS`;function shouldMockAuthoredRuntimeModels(){return process.env.ASH_MOCK_AUTHORED_MODELS===`1`||process.env.NODE_ENV===`test`}function createMockAuthoredRuntimeModel(e){let t=authoredRuntimeModelMocks.get(e.id);if(t!==void 0)return t;let n=new MockLanguageModelV3({modelId:e.id,provider:`ash-runtime-mock`,doGenerate:async t=>createMockModelResult(t,e.id),doStream:async t=>createBootstrapStreamResult(createMockModelResult(t,e.id))});return authoredRuntimeModelMocks.set(e.id,n),n}function createMockModelResult(e,t){let n=getLastAuthoredToolResult(e.prompt);if(n!==null){let r=createFollowUpToolCallResult({modelId:t,options:e,result:n});if(r!==null)return r}else{let n=createSkillLoadResult(e.prompt,t)??createAuthoredToolCallResult(e,t);if(n!==null)return n}let r=createFinalOutputResult(e,t);if(r!==null)return r;let i=n===null?createAssistantMessage(e.prompt):formatToolResultReply(n,e.prompt);return createBootstrapGenerateResult({inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(i),text:i})}function createFinalOutputResult(e,t){let r=getAvailableTools(e).find(e=>e.name===FINAL_OUTPUT_TOOL_NAME);if(r===void 0)return null;let i=createJsonSchemaSample(r.inputSchema);return createToolCallGenerateResult({input:i,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:t,outputTokens:estimateTokenCount(JSON.stringify(i)),toolCallId:createToolCallId(FINAL_OUTPUT_TOOL_NAME),toolName:FINAL_OUTPUT_TOOL_NAME})}function resolveMockAuthoredRuntimeModel(e){return!shouldMockAuthoredRuntimeModels()||e.id===BOOTSTRAP_RUNTIME_MODEL_ID?null:createMockAuthoredRuntimeModel(e)}function createSkillLoadResult(e,t){let n=getLastUserPromptText(e);if(n===null||getActivatedSkillIds(e).length>0)return null;let r=findRelevantSkill(getAvailableSkills(e),n);return r===null?null:createToolCallGenerateResult({input:{skill:r.name},inputTokens:estimateTokenCount(getPromptText(e)),modelId:t,outputTokens:estimateTokenCount(r.name),toolCallId:`call_load_skill`,toolName:LOAD_SKILL_TOOL_NAME})}function createAuthoredToolCallResult(e,n){let r=getLastUserPromptText(e.prompt);if(r===null)return null;let i=findRelevantTool(getAvailableTools(e),r);if(i===null)return null;let a=resolveWeatherCity(r),o=createAuthoredToolInput(i,r,a);if(i.name===CODE_MODE_TOOL_NAME){let t=findRelevantCodeModeHostTool(i.description,r);if(t===null)return null;let o=`return await tools${formatCodeModeToolAccess(t)}({ city: ${JSON.stringify(a)} });`;return createToolCallGenerateResult({input:{js:o},inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:n,outputTokens:estimateTokenCount(o),toolCallId:createToolCallId(i.name),toolName:i.name})}return createToolCallGenerateResult({input:o,inputTokens:estimateTokenCount(getPromptText(e.prompt)),modelId:n,outputTokens:estimateTokenCount(Object.values(o).join(` `)),toolCallId:createToolCallId(i.name),toolName:i.name})}function createFollowUpToolCallResult(e){let t=findNextExplicitToolAfterResult({previousToolName:e.result.toolName,prompt:e.options.prompt,tools:getAvailableTools(e.options)});if(t===null)return null;let n=createFollowUpToolInput(e.result.output);return n===null?null:createToolCallGenerateResult({input:n,inputTokens:estimateTokenCount(getPromptText(e.options.prompt)),modelId:e.modelId,outputTokens:estimateTokenCount(Object.values(n).join(` `)),toolCallId:createToolCallId(t.name),toolName:t.name})}function createAuthoredToolInput(e,t,n){let r=getToolInputPropertyNames(e.inputSchema);return r.includes(`topic`)||/\btopic\b/u.test(normalizeText(t))?{topic:resolveLookupTopic(t)}:r.length===1&&r[0]===`message`?{message:t}:{city:n}}function createAssistantMessage(e){let t=getLastUserPromptText(e)??`Hello from Ash`,n=getSystemPromptLabels(e),r=resolveSystemProbe(e);return n.length>0?r===null?`Bootstrap reply [${n.join(`, `)}]: ${t}`:`Bootstrap reply [${n.join(`, `)}; probe=${r}]: ${t}`:r===null?`Bootstrap reply: ${t}`:`Bootstrap reply [probe=${r}]: ${t}`}function formatToolResultReply(e,t){if(e.isError)return`Local weather tool failed: ${formatToolOutput(e.output)}`;if(isWeatherPayload(e.output))return`Used local weather tool for ${e.output.city}: ${e.output.condition}, ${e.output.temperatureF}F. ${e.output.summary}`;let n=getLastUserPromptText(t)??`Hello from Ash`;return`Used ${e.toolName} for "${n}": ${formatToolOutput(e.output)}`}function createToolCallGenerateResult(e){return{content:[{input:JSON.stringify(e.input),toolCallId:e.toolCallId,toolName:e.toolName,type:`tool-call`}],finishReason:{raw:void 0,unified:`tool-calls`},response:{id:`bootstrap-response`,modelId:e.modelId,timestamp:new Date(`2026-03-16T00:00:00.000Z`)},usage:{inputTokens:{cacheRead:0,cacheWrite:0,noCache:e.inputTokens,total:e.inputTokens},outputTokens:{reasoning:0,text:e.outputTokens,total:e.outputTokens}},warnings:[]}}function getAvailableTools(e){return(e.tools??[]).flatMap(e=>e.type===`function`?[{description:e.description,inputSchema:`inputSchema`in e?e.inputSchema:void 0,name:e.name,outputSchema:`outputSchema`in e?e.outputSchema:void 0}]:[])}function getLastAuthoredToolResult(e){for(let t of[...e].reverse()){if(t.role===`user`)return null;if(!(t.role!==`tool`&&t.role!==`assistant`)){for(let e of[...t.content].reverse())if(!(typeof e==`string`||e.type!==`tool-result`)&&e.toolName!==LOAD_SKILL_TOOL_NAME)return{isError:e.output.type===`error-json`||e.output.type===`error-text`||e.output.type===`execution-denied`,output:e.output.type===`execution-denied`?{reason:e.output.reason??null,type:e.output.type}:e.output.value,toolCallId:e.toolCallId,toolName:e.toolName}}}return null}function findNextExplicitToolAfterResult(e){let t=getLastUserPromptText(e.prompt);if(t===null)return null;let n=normalizeText(t),r=n.indexOf(normalizeText(e.previousToolName));return r<0?null:e.tools.filter(t=>t.name!==e.previousToolName).flatMap(e=>{let t=n.indexOf(normalizeText(e.name),r+1);return t<0?[]:[{index:t,tool:e}]}).sort((e,t)=>e.index-t.index)[0]?.tool??null}function createFollowUpToolInput(e){return isRecord(e)&&typeof e.stepKey==`string`?{stepKey:e.stepKey}:null}function getSystemPromptLabels(e){let t=e.filter(e=>e.role===`system`);if(t.length===0)return[];let n=t.flatMap(e=>{let t=getPromptContentText(e.content);if(t.startsWith(`Available skills
2
2
  `))return[];let n=t.split(`
3
- `).map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of n){if(e===BOOTSTRAP_RUNTIME_SYSTEM_PROMPT||e===`Available skills`)continue;let t=/^System \((.+)\)$/.exec(e);if(t?.[1]){r.push(t[1]);continue}let n=/^Skill \((.+)\)$/.exec(e);n?.[1]&&r.push(n[1])}if(r.length>0)return r;let i=n.find(e=>e!==BOOTSTRAP_RUNTIME_SYSTEM_PROMPT&&e!==`Available skills`);return i===void 0?[]:[i]});return[...new Set(n)]}function getToolInputPropertyNames(e){return!isRecord(e)||!isRecord(e.properties)?[]:Object.keys(e.properties)}function findRelevantTool(e,t){let n=normalizeText(t),r=e.find(e=>n.includes(normalizeText(e.name)));return r===void 0?/\b(forecast|temperature|weather|wind|rain|snow)\b/u.test(n)?e.find(e=>/\b(forecast|temperature|weather|wind|rain|snow)\b/u.test(normalizeText(`${e.name} ${e.description??``}`)))??null:null:r}function findRelevantCodeModeHostTool(e,t){return e===void 0?null:findRelevantTool(parseCodeModeHostTools(e),t)?.name??null}function parseCodeModeHostTools(e){let t=[],n;for(let r of e.split(`
3
+ `).map(e=>e.trim()).filter(e=>e.length>0),r=[];for(let e of n){if(e===BOOTSTRAP_RUNTIME_SYSTEM_PROMPT||e===`Available skills`)continue;let t=/^System \((.+)\)$/.exec(e);if(t?.[1]){r.push(t[1]);continue}let n=/^Skill \((.+)\)$/.exec(e);n?.[1]&&r.push(n[1])}if(r.length>0)return r;let i=n.find(e=>e!==BOOTSTRAP_RUNTIME_SYSTEM_PROMPT&&e!==`Available skills`);return i===void 0?[]:[i]});return[...new Set(n)]}function getToolInputPropertyNames(e){return!isRecord(e)||!isRecord(e.properties)?[]:Object.keys(e.properties)}function findRelevantTool(e,t){let n=normalizeText(t),r=e.find(e=>e.name!==`agent`&&n.includes(normalizeText(e.name)));return r===void 0?/\b(forecast|temperature|weather|wind|rain|snow)\b/u.test(n)?e.find(e=>/\b(forecast|temperature|weather|wind|rain|snow)\b/u.test(normalizeText(`${e.name} ${e.description??``}`)))??null:null:r}function findRelevantCodeModeHostTool(e,t){return e===void 0?null:findRelevantTool(parseCodeModeHostTools(e),t)?.name??null}function parseCodeModeHostTools(e){let t=[],n;for(let r of e.split(`
4
4
  `)){let e=/^\s*\/\*\*\s*(.*?)\s*\*\/\s*$/u.exec(r);if(e?.[1]!==void 0){n=e[1];continue}let i=/^\s*(?:([$A-Z_a-z][$\w]*)|(["'])(.*?)\2)\s*:\s*\(input:/u.exec(r),a=i?.[1]??i?.[3];a!==void 0&&(t.push({description:n,name:a}),n=void 0)}return t}function formatCodeModeToolAccess(e){return/^[$A-Z_a-z][$\w]*$/u.test(e)?`.${e}`:`[${JSON.stringify(e)}]`}function normalizeText(e){return e.toLowerCase().replace(/[^a-z0-9]+/gu,` `).trim()}function createToolCallId(e){return`call_${e.toLowerCase().replace(/[^a-z0-9]+/gu,`_`).replace(/^_+|_+$/gu,``)||`tool`}`}function resolveSystemProbe(e){let t=e.filter(e=>e.role===`system`).map(e=>getPromptContentText(e.content)).join(`
5
5
  `);return/hmr-probe:\s*([^\n]+)/iu.exec(t)?.[1]?.trim()||null}function resolveWeatherCity(e){let t=/"city"\s*:\s*"([^"]+)"/u.exec(e);return t?.[1]?t[1].trim():(/\b(?:in|for)\s+([A-Za-z][A-Za-z\s.-]*?)(?:[?.!,]|$)/u.exec(e)??/\b([A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)\b/u.exec(e))?.[1]?.trim()||`Brooklyn`}function resolveLookupTopic(e){return/\btopic\s+['"]?([A-Za-z0-9_.-]+)['"]?/u.exec(e)?.[1]??`demo`}function isWeatherPayload(e){return bootstrapWeatherPayloadSchema.safeParse(e).success}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function formatToolOutput(e){if(typeof e==`string`)return e;try{return JSON.stringify(e)}catch{return String(e)}}export{ASH_MOCK_AUTHORED_MODELS_ENV,createMockAuthoredRuntimeModel,resolveMockAuthoredRuntimeModel,shouldMockAuthoredRuntimeModels};
@@ -1 +1 @@
1
- import{expectObjectRecord}from"#internal/authored-module.js";import{ROOT_COMPILED_AGENT_NODE_ID}from"#compiler/manifest.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{CODE_MODE_TOOL_NAME}from"#shared/code-mode.js";import{createRuntimeToolRegistry}from"#runtime/tools/registry.js";import{getAllFrameworkChannelNames,getFrameworkChannelDefinitions}from"#runtime/framework-channels/index.js";import{resolveAgent}from"#runtime/resolve-agent.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{createResolvedRuntimeTurnAgent}from"#runtime/agent/bootstrap.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{createConnectionSearchResolver}from"#runtime/framework-tools/connection-search-dynamic.js";import{getAllFrameworkToolNames,getFrameworkToolDefinitions}from"#runtime/framework-tools/index.js";import{createRuntimeHookRegistry}from"#runtime/hooks/registry.js";import{createRuntimeSandboxRegistry}from"#runtime/sandbox/registry.js";import{createRuntimeSubagentRegistry}from"#runtime/subagents/registry.js";var ResolveRuntimeAgentGraphError=class extends Error{logicalPath;nodeId;sourceId;constructor(e,t={}){super(e),this.name=`ResolveRuntimeAgentGraphError`,t.logicalPath!==void 0&&(this.logicalPath=t.logicalPath),t.nodeId!==void 0&&(this.nodeId=t.nodeId),t.sourceId!==void 0&&(this.sourceId=t.sourceId)}};async function resolveRuntimeAgentGraph(e){let n=new Map,r=createChildNodeIdsByParentNodeId(e.manifest),i=new Map(e.manifest.subagents.map(e=>[e.nodeId,e]));return{nodesByNodeId:n,root:await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:r,manifest:e.manifest,moduleMap:e.moduleMap,nodeId:ROOT_COMPILED_AGENT_NODE_ID,nodesByNodeId:n,subagentNodesById:i})}}async function resolveRuntimeAgentNode(e){let t=toRuntimeNodeId(e.nodeId);if(e.nodesByNodeId.has(t))throw new ResolveRuntimeAgentGraphError(`Found multiple runtime agent nodes for node id "${t}".`,{nodeId:t,sourceId:e.sourceId});let n=await resolveAgent({manifest:e.manifest,moduleMap:e.moduleMap,nodeId:e.nodeId}),a=n.connections.length>0,o=getFrameworkToolDefinitions({hasConnections:a}),s=new Set(o.map(e=>e.name)),c=getAllFrameworkToolNames(),l=new Set(n.tools.map(e=>e.name));for(let r of n.disabledFrameworkTools)if(!c.has(r))throw new ResolveRuntimeAgentGraphError(`agent/tools/${r}.ts exports disableTool() but "${r}" is not a framework tool. Rename the file to one of: ${[...c].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let u=new Set(n.disabledFrameworkTools),d=await createRuntimeToolRegistry({tools:[...o.filter(e=>!l.has(e.name)&&!u.has(e.name)),...n.tools]},{reservedToolNames:[CODE_MODE_TOOL_NAME,...s.has(LOAD_SKILL_TOOL_NAME)||l.has(LOAD_SKILL_TOOL_NAME)?[]:[LOAD_SKILL_TOOL_NAME]]}),f=new Set(n.channels.map(e=>e.name)),p=getAllFrameworkChannelNames();for(let r of n.disabledFrameworkChannels)if(!p.has(r))throw new ResolveRuntimeAgentGraphError(`agent/channels/${r}.ts exports disableRoute() but "${r}" is not a framework channel. Rename the file to one of: ${[...p].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let m=new Set(n.disabledFrameworkChannels),h=[...getFrameworkChannelDefinitions().filter(e=>!f.has(e.name)&&!m.has(e.name)),...n.channels],g=createRuntimeSandboxRegistry({authoredSandbox:n.sandbox,workspaceResourceRoot:n.workspaceResourceRoot}),_=createRuntimeSubagentRegistry({reservedToolNames:[LOAD_SKILL_TOOL_NAME,...d.preparedTools.map(e=>e.name)],subagents:await resolveRuntimeSubagents({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.manifest,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,parentNodeId:e.nodeId,subagentNodesById:e.subagentNodesById})}),v=a?{...n,dynamicToolResolvers:[...n.dynamicToolResolvers,createConnectionSearchResolver()]}:n,y={agent:v,channels:h,hookRegistry:createRuntimeHookRegistry(v.hooks),nodeId:t,sandboxRegistry:g,sourceId:e.sourceId,subagentRegistry:_,toolRegistry:d,turnAgent:createResolvedRuntimeTurnAgent({agent:v,nodeId:t,tools:[...d.preparedTools,..._.preparedTools]})};return e.nodesByNodeId.set(t,y),y}async function resolveRuntimeSubagents(e){let t=[],n=e.childNodeIdsByParentNodeId.get(e.parentNodeId)??[];for(let r of n){let n=e.subagentNodesById.get(r);if(n===void 0)throw new ResolveRuntimeAgentGraphError(`Missing compiled subagent node "${r}" while resolving runtime subagents.`,{nodeId:toRuntimeNodeId(e.parentNodeId),sourceId:r});t.push(await resolveRuntimeSubagent({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,sourceRef:n,subagentNodesById:e.subagentNodesById}))}for(let n of e.manifest.remoteAgents)t.push(await resolveRuntimeRemoteAgent({moduleMap:e.moduleMap,nodeScopeId:e.parentNodeId,sourceRef:n}));return t}async function resolveRuntimeSubagent(e){let t={description:e.sourceRef.description,kind:`subagent`,logicalPath:e.sourceRef.logicalPath,name:e.sourceRef.name,nodeId:toRuntimeNodeId(e.sourceRef.nodeId),sourceId:e.sourceRef.sourceId,sourceKind:`module`};return await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.sourceRef.agent,moduleMap:e.moduleMap,nodeId:e.sourceRef.nodeId,nodesByNodeId:e.nodesByNodeId,sourceId:e.sourceRef.sourceId,subagentNodesById:e.subagentNodesById}),t}async function resolveRuntimeRemoteAgent(t){let n=expectObjectRecord(await loadResolvedModuleExport({definition:t.sourceRef,kindLabel:`remote agent`,moduleMap:t.moduleMap,nodeId:t.nodeScopeId}),`Expected remote agent source "${t.sourceRef.logicalPath}" to export an object.`),r={description:t.sourceRef.description,kind:`remote`,logicalPath:t.sourceRef.logicalPath,name:t.sourceRef.name,nodeId:toRuntimeNodeId(t.sourceRef.nodeId),outputSchema:t.sourceRef.outputSchema,path:t.sourceRef.path,sourceId:t.sourceRef.sourceId,sourceKind:`module`,url:t.sourceRef.url};typeof n.auth==`function`&&(r.auth=n.auth);let i=resolveRemoteAgentHeaders(n.headers);return i!==void 0&&(r.headers=i),r}function resolveRemoteAgentHeaders(e){if(e===void 0)return;if(typeof e==`function`)return e;if(typeof e!=`object`||!e||Array.isArray(e))return;let t={};for(let[n,r]of Object.entries(e))typeof r==`string`&&(t[n]=r);return t}function createChildNodeIdsByParentNodeId(e){let t=new Map;for(let n of e.subagentEdges){let e=t.get(n.parentNodeId);if(e===void 0){t.set(n.parentNodeId,[n.childNodeId]);continue}e.push(n.childNodeId)}return t}function toRuntimeNodeId(e){return e===ROOT_COMPILED_AGENT_NODE_ID?ROOT_RUNTIME_AGENT_NODE_ID:e}export{resolveRuntimeAgentGraph};
1
+ import{expectObjectRecord}from"#internal/authored-module.js";import{ROOT_COMPILED_AGENT_NODE_ID}from"#compiler/manifest.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{CODE_MODE_TOOL_NAME}from"#shared/code-mode.js";import{createRuntimeToolRegistry}from"#runtime/tools/registry.js";import{createRuntimeSubagentRegistry}from"#runtime/subagents/registry.js";import{getAllFrameworkChannelNames,getFrameworkChannelDefinitions}from"#runtime/framework-channels/index.js";import{resolveAgent}from"#runtime/resolve-agent.js";import{loadResolvedModuleExport}from"#runtime/resolve-helpers.js";import{createResolvedRuntimeTurnAgent}from"#runtime/agent/bootstrap.js";import{LOAD_SKILL_TOOL_NAME}from"#runtime/skills/fragment-context.js";import{createConnectionSearchResolver}from"#runtime/framework-tools/connection-search-dynamic.js";import{getAllFrameworkToolNames,getFrameworkToolDefinitions}from"#runtime/framework-tools/index.js";import{createRuntimeHookRegistry}from"#runtime/hooks/registry.js";import{createRuntimeSandboxRegistry}from"#runtime/sandbox/registry.js";var ResolveRuntimeAgentGraphError=class extends Error{logicalPath;nodeId;sourceId;constructor(e,t={}){super(e),this.name=`ResolveRuntimeAgentGraphError`,t.logicalPath!==void 0&&(this.logicalPath=t.logicalPath),t.nodeId!==void 0&&(this.nodeId=t.nodeId),t.sourceId!==void 0&&(this.sourceId=t.sourceId)}};async function resolveRuntimeAgentGraph(e){let n=new Map,r=createChildNodeIdsByParentNodeId(e.manifest),i=new Map(e.manifest.subagents.map(e=>[e.nodeId,e]));return{nodesByNodeId:n,root:await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:r,manifest:e.manifest,moduleMap:e.moduleMap,nodeId:ROOT_COMPILED_AGENT_NODE_ID,nodesByNodeId:n,subagentNodesById:i})}}async function resolveRuntimeAgentNode(e){let t=toRuntimeNodeId(e.nodeId);if(e.nodesByNodeId.has(t))throw new ResolveRuntimeAgentGraphError(`Found multiple runtime agent nodes for node id "${t}".`,{nodeId:t,sourceId:e.sourceId});let n=await resolveAgent({manifest:e.manifest,moduleMap:e.moduleMap,nodeId:e.nodeId}),a=n.connections.length>0,o=getFrameworkToolDefinitions({hasConnections:a}),s=new Set(o.map(e=>e.name)),c=getAllFrameworkToolNames(),l=new Set(n.tools.map(e=>e.name));for(let r of n.disabledFrameworkTools)if(!c.has(r))throw new ResolveRuntimeAgentGraphError(`agent/tools/${r}.ts exports disableTool() but "${r}" is not a framework tool. Rename the file to one of: ${[...c].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let u=new Set(n.disabledFrameworkTools),d=await createRuntimeToolRegistry({tools:[...o.filter(e=>!l.has(e.name)&&!u.has(e.name)),...n.tools]},{reservedToolNames:[CODE_MODE_TOOL_NAME,...s.has(LOAD_SKILL_TOOL_NAME)||l.has(LOAD_SKILL_TOOL_NAME)?[]:[LOAD_SKILL_TOOL_NAME]]}),f=new Set(n.channels.map(e=>e.name)),p=getAllFrameworkChannelNames();for(let r of n.disabledFrameworkChannels)if(!p.has(r))throw new ResolveRuntimeAgentGraphError(`agent/channels/${r}.ts exports disableRoute() but "${r}" is not a framework channel. Rename the file to one of: ${[...p].sort().join(`, `)}.`,{nodeId:t,sourceId:e.sourceId});let m=new Set(n.disabledFrameworkChannels),h=[...getFrameworkChannelDefinitions().filter(e=>!f.has(e.name)&&!m.has(e.name)),...n.channels],g=createRuntimeSandboxRegistry({authoredSandbox:n.sandbox,workspaceResourceRoot:n.workspaceResourceRoot}),_=createRuntimeSubagentRegistry({reservedToolNames:[LOAD_SKILL_TOOL_NAME,...d.preparedTools.map(e=>e.name)],subagents:await resolveRuntimeSubagents({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.manifest,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,parentNodeId:e.nodeId,subagentNodesById:e.subagentNodesById})}),v=a?{...n,dynamicToolResolvers:[...n.dynamicToolResolvers,createConnectionSearchResolver()]}:n,y={agent:v,channels:h,hookRegistry:createRuntimeHookRegistry(v.hooks),nodeId:t,sandboxRegistry:g,sourceId:e.sourceId,subagentRegistry:_,toolRegistry:d,turnAgent:createResolvedRuntimeTurnAgent({agent:v,nodeId:t,tools:[...d.preparedTools,..._.preparedTools]})};return e.nodesByNodeId.set(t,y),y}async function resolveRuntimeSubagents(e){let t=[],n=e.childNodeIdsByParentNodeId.get(e.parentNodeId)??[];for(let r of n){let n=e.subagentNodesById.get(r);if(n===void 0)throw new ResolveRuntimeAgentGraphError(`Missing compiled subagent node "${r}" while resolving runtime subagents.`,{nodeId:toRuntimeNodeId(e.parentNodeId),sourceId:r});t.push(await resolveRuntimeSubagent({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,moduleMap:e.moduleMap,nodesByNodeId:e.nodesByNodeId,sourceRef:n,subagentNodesById:e.subagentNodesById}))}for(let n of e.manifest.remoteAgents)t.push(await resolveRuntimeRemoteAgent({moduleMap:e.moduleMap,nodeScopeId:e.parentNodeId,sourceRef:n}));return t}async function resolveRuntimeSubagent(e){let t={description:e.sourceRef.description,kind:`subagent`,logicalPath:e.sourceRef.logicalPath,name:e.sourceRef.name,nodeId:toRuntimeNodeId(e.sourceRef.nodeId),sourceId:e.sourceRef.sourceId,sourceKind:`module`};return await resolveRuntimeAgentNode({childNodeIdsByParentNodeId:e.childNodeIdsByParentNodeId,manifest:e.sourceRef.agent,moduleMap:e.moduleMap,nodeId:e.sourceRef.nodeId,nodesByNodeId:e.nodesByNodeId,sourceId:e.sourceRef.sourceId,subagentNodesById:e.subagentNodesById}),t}async function resolveRuntimeRemoteAgent(t){let n=expectObjectRecord(await loadResolvedModuleExport({definition:t.sourceRef,kindLabel:`remote agent`,moduleMap:t.moduleMap,nodeId:t.nodeScopeId}),`Expected remote agent source "${t.sourceRef.logicalPath}" to export an object.`),r={description:t.sourceRef.description,kind:`remote`,logicalPath:t.sourceRef.logicalPath,name:t.sourceRef.name,nodeId:toRuntimeNodeId(t.sourceRef.nodeId),outputSchema:t.sourceRef.outputSchema,path:t.sourceRef.path,sourceId:t.sourceRef.sourceId,sourceKind:`module`,url:t.sourceRef.url};typeof n.auth==`function`&&(r.auth=n.auth);let i=resolveRemoteAgentHeaders(n.headers);return i!==void 0&&(r.headers=i),r}function resolveRemoteAgentHeaders(e){if(e===void 0)return;if(typeof e==`function`)return e;if(typeof e!=`object`||!e||Array.isArray(e))return;let t={};for(let[n,r]of Object.entries(e))typeof r==`string`&&(t[n]=r);return t}function createChildNodeIdsByParentNodeId(e){let t=new Map;for(let n of e.subagentEdges){let e=t.get(n.parentNodeId);if(e===void 0){t.set(n.parentNodeId,[n.childNodeId]);continue}e.push(n.childNodeId)}return t}function toRuntimeNodeId(e){return e===ROOT_COMPILED_AGENT_NODE_ID?ROOT_RUNTIME_AGENT_NODE_ID:e}export{resolveRuntimeAgentGraph};
@@ -1 +1 @@
1
- import{ASH_CALLBACK_ROUTE_PATTERN}from"#protocol/routes.js";import{resumeHook}from"#compiled/@workflow/core/runtime.js";const HTTP_SESSION_CALLBACK_CHANNEL_NAME_PREFIX=`ash/v1/callback`,HANDLED_METHODS=[`POST`];function getSessionCallbackChannelDefinitions(){return HANDLED_METHODS.map(e=>buildCallbackChannelDefinition(e))}function getSessionCallbackChannelNames(){return new Set(HANDLED_METHODS.map(channelNameForMethod))}function buildCallbackChannelDefinition(t){let n=channelNameForMethod(t);return{name:n,method:t,urlPath:ASH_CALLBACK_ROUTE_PATTERN,fetch:handleSessionCallbackRequest,logicalPath:`framework://channels/${n}`,sourceId:`ash:framework:session-callback-${t.toLowerCase()}`,sourceKind:`module`}}function channelNameForMethod(e){return`${HTTP_SESSION_CALLBACK_CHANNEL_NAME_PREFIX}/${e.toLowerCase()}`}async function handleSessionCallbackRequest(e,n){let r=n.params.token;if(typeof r!=`string`||r.length===0)return Response.json({error:`Missing callback token.`,ok:!1},{status:400});let i;try{i=await e.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}let a=projectSessionCallbackResult(i);if(a instanceof Response)return a;try{await resumeHook(r,{kind:`runtime-action-result`,results:[a]})}catch{return Response.json({error:`Session callback not pending.`,ok:!1},{status:404})}return Response.json({ok:!0},{status:202})}function projectSessionCallbackResult(e){if(typeof e!=`object`||!e)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let t=e;return typeof t.callId!=`string`||t.callId.length===0?Response.json({error:`Missing callback callId.`,ok:!1},{status:400}):typeof t.subagentName!=`string`||t.subagentName.length===0?Response.json({error:`Missing callback subagentName.`,ok:!1},{status:400}):t.kind===`session.completed`?{callId:t.callId,kind:`subagent-result`,output:typeof t.output==`string`?t.output:``,subagentName:t.subagentName}:t.kind===`session.failed`?{callId:t.callId,isError:!0,kind:`subagent-result`,output:t.error===void 0?{code:`REMOTE_AGENT_FAILED`,message:`Remote agent failed.`}:t.error,subagentName:t.subagentName}:Response.json({error:`Unsupported callback kind.`,ok:!1},{status:400})}export{HTTP_SESSION_CALLBACK_CHANNEL_NAME_PREFIX,getSessionCallbackChannelDefinitions,getSessionCallbackChannelNames,handleSessionCallbackRequest};
1
+ import{ASH_CALLBACK_ROUTE_PATTERN}from"#protocol/routes.js";import{resumeHook}from"#compiled/@workflow/core/runtime.js";const HTTP_SESSION_CALLBACK_CHANNEL_NAME_PREFIX=`ash/v1/callback`,HANDLED_METHODS=[`POST`];function getSessionCallbackChannelDefinitions(){return HANDLED_METHODS.map(e=>buildCallbackChannelDefinition(e))}function getSessionCallbackChannelNames(){return new Set(HANDLED_METHODS.map(channelNameForMethod))}function buildCallbackChannelDefinition(t){let n=channelNameForMethod(t);return{name:n,method:t,urlPath:ASH_CALLBACK_ROUTE_PATTERN,fetch:handleSessionCallbackRequest,logicalPath:`framework://channels/${n}`,sourceId:`ash:framework:session-callback-${t.toLowerCase()}`,sourceKind:`module`}}function channelNameForMethod(e){return`${HTTP_SESSION_CALLBACK_CHANNEL_NAME_PREFIX}/${e.toLowerCase()}`}async function handleSessionCallbackRequest(e,n){let r=n.params.token;if(typeof r!=`string`||r.length===0)return Response.json({error:`Missing callback token.`,ok:!1},{status:400});let i;try{i=await e.json()}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}let a=projectSessionCallbackResult(i);if(a instanceof Response)return a;try{await resumeHook(r,{kind:`runtime-action-result`,results:[a]})}catch{return Response.json({error:`Session callback not pending.`,ok:!1},{status:404})}return Response.json({ok:!0},{status:202})}function projectSessionCallbackResult(e){if(typeof e!=`object`||!e)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let t=e;return typeof t.callId!=`string`||t.callId.length===0?Response.json({error:`Missing callback callId.`,ok:!1},{status:400}):typeof t.subagentName!=`string`||t.subagentName.length===0?Response.json({error:`Missing callback subagentName.`,ok:!1},{status:400}):t.kind===`session.completed`?{callId:t.callId,kind:`subagent-result`,output:t.output??``,subagentName:t.subagentName}:t.kind===`session.failed`?{callId:t.callId,isError:!0,kind:`subagent-result`,output:t.error===void 0?{code:`REMOTE_AGENT_FAILED`,message:`Remote agent failed.`}:t.error,subagentName:t.subagentName}:Response.json({error:`Unsupported callback kind.`,ok:!1},{status:400})}export{HTTP_SESSION_CALLBACK_CHANNEL_NAME_PREFIX,getSessionCallbackChannelDefinitions,getSessionCallbackChannelNames,handleSessionCallbackRequest};
@@ -1,3 +1,4 @@
1
+ import type { JsonObject } from "#shared/json.js";
1
2
  import type { PreparedRuntimeDelegationTool } from "#runtime/sessions/turn.js";
2
3
  import type { ResolvedRuntimeDelegationNode } from "#runtime/types.js";
3
4
  /**
@@ -15,6 +16,11 @@ export interface RuntimeSubagentRegistry {
15
16
  readonly subagentsByName: ReadonlyMap<string, RuntimeRegisteredSubagent>;
16
17
  readonly subagentsByNodeId: ReadonlyMap<string, RuntimeRegisteredSubagent>;
17
18
  }
19
+ /**
20
+ * Stable JSON Schema lowered onto every subagent tool. Subagents always
21
+ * accept one free-form `message` string from the parent agent.
22
+ */
23
+ export declare const SUBAGENT_TOOL_INPUT_SCHEMA: JsonObject;
18
24
  /**
19
25
  * Builds the runtime-owned registry for the resolved subagents visible from one
20
26
  * runtime agent node.
@@ -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.`}),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
+ 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{SUBAGENT_TOOL_INPUT_SCHEMA,createRuntimeSubagentRegistry};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "experimental-ash",
3
- "version": "0.57.0",
3
+ "version": "0.58.0",
4
4
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
5
5
  "keywords": [
6
6
  "agent-framework",