experimental-ash 0.35.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/docs/internals/context.md +6 -5
  3. package/dist/docs/internals/core-beliefs.md +2 -2
  4. package/dist/docs/internals/hooks.md +16 -11
  5. package/dist/docs/internals/mechanical-invariants.md +4 -4
  6. package/dist/docs/internals/testing.md +1 -1
  7. package/dist/docs/public/README.md +1 -1
  8. package/dist/docs/public/auth-and-route-protection.md +4 -4
  9. package/dist/docs/public/channels/{README.md → index.md} +2 -2
  10. package/dist/docs/public/channels/slack.md +3 -3
  11. package/dist/docs/public/cli-build-and-debugging.md +1 -1
  12. package/dist/docs/public/faqs.md +4 -5
  13. package/dist/docs/public/hooks.md +18 -23
  14. package/dist/docs/public/meta.json +4 -4
  15. package/dist/docs/public/sandbox.md +9 -11
  16. package/dist/docs/public/schedules.md +1 -1
  17. package/dist/docs/public/session-context.md +25 -27
  18. package/dist/docs/public/skills.md +3 -4
  19. package/dist/docs/public/subagents.md +1 -1
  20. package/dist/docs/public/tools.md +13 -17
  21. package/dist/docs/public/typescript-api.md +10 -11
  22. package/dist/src/channel/session.d.ts +3 -29
  23. package/dist/src/channel/session.js +1 -1
  24. package/dist/src/context/build-callback-context.d.ts +8 -0
  25. package/dist/src/context/build-callback-context.js +1 -0
  26. package/dist/src/context/hook-lifecycle.js +1 -1
  27. package/dist/src/execution/node-step.js +1 -1
  28. package/dist/src/execution/sandbox/bash-tool.d.ts +2 -1
  29. package/dist/src/execution/sandbox/bash-tool.js +1 -1
  30. package/dist/src/execution/sandbox/glob-tool.d.ts +2 -1
  31. package/dist/src/execution/sandbox/glob-tool.js +3 -3
  32. package/dist/src/execution/sandbox/grep-tool.d.ts +2 -1
  33. package/dist/src/execution/sandbox/grep-tool.js +3 -3
  34. package/dist/src/execution/sandbox/read-file-tool.d.ts +2 -1
  35. package/dist/src/execution/sandbox/read-file-tool.js +1 -1
  36. package/dist/src/execution/sandbox/write-file-tool.d.ts +2 -1
  37. package/dist/src/execution/sandbox/write-file-tool.js +1 -1
  38. package/dist/src/execution/tool-compaction.js +1 -1
  39. package/dist/src/harness/code-mode-approval.js +1 -1
  40. package/dist/src/harness/code-mode.js +1 -1
  41. package/dist/src/harness/tool-loop.js +1 -1
  42. package/dist/src/internal/application/package.js +1 -1
  43. package/dist/src/internal/workflow-bundle/builder.js +2 -2
  44. package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/index.js +1 -1
  45. package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime/manager.js +1 -0
  46. package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime/worker-source.js +408 -0
  47. package/dist/src/packages/ash-scaffold/src/channels.js +2 -12
  48. package/dist/src/packages/ash-scaffold/src/pnpm-workspace.js +11 -0
  49. package/dist/src/packages/ash-scaffold/src/project.js +1 -1
  50. package/dist/src/public/context/index.d.ts +3 -2
  51. package/dist/src/public/context/index.js +1 -1
  52. package/dist/src/public/definitions/callback-context.d.ts +22 -0
  53. package/dist/src/public/definitions/callback-context.js +1 -0
  54. package/dist/src/public/definitions/hook.d.ts +9 -49
  55. package/dist/src/public/definitions/tool.d.ts +14 -15
  56. package/dist/src/public/hooks/index.d.ts +1 -1
  57. package/dist/src/public/sandbox/index.d.ts +0 -1
  58. package/dist/src/public/sandbox/index.js +1 -1
  59. package/dist/src/public/skills/index.d.ts +0 -1
  60. package/dist/src/public/skills/index.js +1 -1
  61. package/dist/src/public/tools/defaults.js +1 -1
  62. package/dist/src/public/tools/define-bash-tool.js +1 -1
  63. package/dist/src/public/tools/define-glob-tool.js +1 -1
  64. package/dist/src/public/tools/define-grep-tool.js +1 -1
  65. package/dist/src/public/tools/define-read-file-tool.js +1 -1
  66. package/dist/src/public/tools/define-write-file-tool.js +1 -1
  67. package/dist/src/public/tools/index.d.ts +2 -1
  68. package/dist/src/public/tools/internal.d.ts +4 -0
  69. package/dist/src/public/tools/internal.js +1 -1
  70. package/dist/src/runtime/framework-tools/bash.js +1 -1
  71. package/dist/src/runtime/framework-tools/connection-search.js +1 -1
  72. package/dist/src/runtime/framework-tools/connection-tools.js +1 -1
  73. package/dist/src/runtime/framework-tools/file-state.d.ts +2 -2
  74. package/dist/src/runtime/framework-tools/file-state.js +1 -1
  75. package/dist/src/runtime/framework-tools/glob.js +1 -1
  76. package/dist/src/runtime/framework-tools/grep.js +1 -1
  77. package/dist/src/runtime/framework-tools/read-file.js +2 -2
  78. package/dist/src/runtime/framework-tools/todo.js +1 -1
  79. package/dist/src/runtime/framework-tools/write-file.js +1 -1
  80. package/dist/src/runtime/types.d.ts +2 -2
  81. package/package.json +2 -2
  82. package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime/manager.js +0 -1
  83. package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime/worker-source.js +0 -1153
  84. package/dist/src/node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/runtime-assets.js +0 -1
  85. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/approval-continuation.js +0 -0
  86. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/approval-response.js +0 -0
  87. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/code-mode-tool.js +0 -0
  88. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/continuation-capability.js +0 -0
  89. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/errors.js +0 -0
  90. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/fetch-policy.js +0 -0
  91. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/host-interrupt.js +0 -0
  92. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/interrupt-continuation.js +0 -0
  93. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/options.js +0 -0
  94. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/run-code-mode.js +0 -0
  95. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/runtime/max-workers.js +0 -0
  96. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/serialization.js +0 -0
  97. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/source-cache.js +0 -0
  98. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/telemetry.js +0 -0
  99. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/tool-invocation.js +0 -0
  100. /package/dist/src/node_modules/.pnpm/{experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_ → experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_}/node_modules/experimental-ai-sdk-code-mode/dist/tool-prompt.js +0 -0
@@ -13,7 +13,6 @@ back.
13
13
  `agent/tools/get_weather.ts`
14
14
 
15
15
  ```ts
16
- import { getSession } from "experimental-ash/context";
17
16
  import { defineTool } from "experimental-ash/tools";
18
17
  import { z } from "zod";
19
18
 
@@ -22,12 +21,10 @@ export default defineTool({
22
21
  inputSchema: z.object({
23
22
  city: z.string(),
24
23
  }),
25
- async execute(input) {
26
- const session = getSession();
27
-
24
+ async execute(input, ctx) {
28
25
  return {
29
26
  city: input.city,
30
- sessionId: session.sessionId,
27
+ sessionId: ctx.session.id,
31
28
  temperatureF: 72,
32
29
  };
33
30
  },
@@ -40,17 +37,17 @@ There is no `name` override and no compile-time normalization — if you want a
40
37
  identifier, name the file in snake_case.
41
38
 
42
39
  `defineTool`, `disableTool`, `defineBashTool`, `defineReadFileTool`, and `defineWriteFileTool` live on the `experimental-ash/tools` subpath.
43
- Runtime context helpers (`getSession`, `defineState`) live on `experimental-ash/context`.
44
- `getSandbox` lives on `experimental-ash/sandbox` and `getSkill` lives on `experimental-ash/skills`.
40
+ `defineState` lives on `experimental-ash/context`. Session metadata, sandbox access, and skill access
41
+ are available through the `ctx` parameter passed to `execute`.
45
42
 
46
43
  ## What A Tool Definition Needs
47
44
 
48
45
  - a filename slug under `agent/tools/` (this is the model-facing tool name)
49
46
  - `description`
50
47
  - `inputSchema` — a Zod schema (or any Standard Schema). Required, matching the AI SDK's `Tool` contract. For a tool with no input, pass `z.object({})`.
51
- - `execute(input, options?)` — the tool's implementation. `options` provides `toolCallId`, `messages`, and `abortSignal` from the AI SDK.
48
+ - `execute(input, ctx)` — the tool's implementation. `ctx` provides session metadata, sandbox access, and skill access.
52
49
 
53
- The AI SDK uses `inputSchema` to validate and transform model input (including Zod defaults) and to type `execute(input)`.
50
+ The AI SDK uses `inputSchema` to validate and transform model input (including Zod defaults) and to type the `input` parameter in `execute(input, ctx)`.
54
51
 
55
52
  ## Schemas
56
53
 
@@ -75,14 +72,13 @@ export default defineTool({
75
72
 
76
73
  ## Runtime Helpers Inside Tools
77
74
 
78
- Tools are the most common place to use Ash's runtime helpers:
75
+ The `ctx` parameter passed to `execute` is the primary way to access runtime state:
79
76
 
80
- - `getSession()` for session, turn, auth, and parent lineage data
81
- - `getSandbox()` for the live sandbox handle
82
- - `getSkill(identifier)` for reading skill metadata and packaged skill files
77
+ - `ctx.session` for session metadata, turn, auth, and parent lineage data
78
+ - `ctx.getSandbox()` for the live sandbox handle
79
+ - `ctx.getSkill(identifier)` for reading skill metadata and packaged skill files
83
80
 
84
- Those APIs only work inside active authored runtime execution. They throw during top-level module
85
- evaluation.
81
+ These are available inside `execute` and other active authored runtime execution contexts.
86
82
 
87
83
  ## When A Tool Runs
88
84
 
@@ -131,9 +127,9 @@ import { bash } from "experimental-ash/tools/defaults";
131
127
 
132
128
  export default defineTool({
133
129
  ...bash,
134
- async execute(input) {
130
+ async execute(input, ctx) {
135
131
  console.log("[bash]", input);
136
- return bash.execute(input);
132
+ return bash.execute(input, ctx);
137
133
  },
138
134
  });
139
135
  ```
@@ -50,11 +50,12 @@ Most apps use `defineAgent`, `defineTool`, and `defineSandbox` the most.
50
50
 
51
51
  ## Runtime Helpers
52
52
 
53
- Each runtime accessor lives on the subpath that owns its concern:
53
+ Session metadata, sandbox access, and skill access are available through the `ctx` parameter
54
+ passed to tool `execute`, hook handlers, and channel event handlers:
54
55
 
55
- - `getSession()` - current session, turn, auth, and optional parent lineage (`experimental-ash/context`)
56
- - `getSandbox()` - live sandbox handle for the current agent (`experimental-ash/sandbox`)
57
- - `getSkill(identifier)` - handle for a named skill visible to the current agent (`experimental-ash/skills`)
56
+ - `ctx.session` - current session, turn, auth, and optional parent lineage
57
+ - `ctx.getSandbox()` - live sandbox handle for the current agent
58
+ - `ctx.getSkill(identifier)` - handle for a named skill visible to the current agent
58
59
  - `defineState(name, initial)` - typed durable state with `get()` and `update()` (`experimental-ash/context`)
59
60
 
60
61
  Related exported types by subpath:
@@ -154,7 +155,7 @@ Channel types exported from `experimental-ash/channels`:
154
155
  - `POST` - route helper for POST endpoints
155
156
  - `GET` - route helper for GET endpoints
156
157
  - `Session` - session handle returned by `send()`
157
- - `SessionHandle` - read-only session handle from `getSession()`
158
+ - `SessionHandle` - read-only session handle available as `ctx.session`
158
159
  - `SendOptions` - options for `send(message, options)`
159
160
 
160
161
  `RunMode` is explicit: `"conversation"` sessions may wait for follow-up input, while `"task"`
@@ -199,14 +200,12 @@ Event handlers on the channel config receive typed event data:
199
200
  ### Typed Tool
200
201
 
201
202
  ```ts
202
- import { getSession } from "experimental-ash/context";
203
203
  import { defineTool } from "experimental-ash/tools";
204
204
  ```
205
205
 
206
206
  ### Sandbox Access
207
207
 
208
208
  ```ts
209
- import { getSandbox } from "experimental-ash/sandbox";
210
209
  import { defineTool } from "experimental-ash/tools";
211
210
  import { defineBashTool } from "experimental-ash/tools";
212
211
  ```
@@ -214,7 +213,7 @@ import { defineBashTool } from "experimental-ash/tools";
214
213
  ### Skill Access
215
214
 
216
215
  ```ts
217
- import { defineSkill, getSkill } from "experimental-ash/skills";
216
+ import { defineSkill } from "experimental-ash/skills";
218
217
  ```
219
218
 
220
219
  ### Wrapping Or Disabling A Framework Default
@@ -254,9 +253,9 @@ import { Braintrust } from "experimental-ash/evals/reporters";
254
253
  - `defineChannel` and channel factories -> [Channels](./channels/README.md)
255
254
  - `defineTool`, `disableTool`, `defineBashTool`, `defineReadFileTool`, `defineWriteFileTool`, and `experimental-ash/tools/defaults` -> [Tools](./tools.md)
256
255
  - `defineHook`, `HookContext`, and lifecycle/event types -> [Hooks](./hooks.md)
257
- - `defineSandbox` and `getSandbox` -> [Sandboxes](./sandbox.md)
258
- - `defineSkill` and `getSkill` -> [Skills](./skills.md)
259
- - `getSession` -> [Session Context](./session-context.md)
256
+ - `defineSandbox` and `ctx.getSandbox()` -> [Sandboxes](./sandbox.md)
257
+ - `defineSkill` and `ctx.getSkill()` -> [Skills](./skills.md)
258
+ - `ctx.session` -> [Session Context](./session-context.md)
260
259
  - subagents (authored with `defineAgent` under `subagents/<id>/agent.ts`) -> [Subagents](./subagents.md)
261
260
  - `defineSchedule` -> [Schedules](./schedules.md)
262
261
  - `defineEvalSuite`, loaders, reporters, and scorers -> [Evals](./evals.md)
@@ -1,6 +1,7 @@
1
1
  import type { ContextAccessor } from "#context/key.js";
2
2
  import type { HandleMessageStreamEvent } from "#protocol/message.js";
3
- import type { Runtime, SessionAuthContext } from "#channel/types.js";
3
+ import type { Runtime } from "#channel/types.js";
4
+ import type { SessionAuth } from "#context/keys.js";
4
5
  export interface Session {
5
6
  readonly id: string;
6
7
  readonly continuationToken: string;
@@ -18,35 +19,8 @@ export interface Session {
18
19
  */
19
20
  export interface SessionHandle {
20
21
  readonly id: string;
21
- /**
22
- * Runtime-scoped continuation token (`<channelName>:<channel-local-token>`).
23
- */
24
22
  readonly continuationToken: string;
25
- readonly auth: SessionAuthContext | null;
26
- readonly initiatorAuth: SessionAuthContext | null;
27
- /**
28
- * Re-key the session under a new continuation token.
29
- *
30
- * Use this when the channel's resume address depends on data
31
- * produced during the turn (e.g. Slack auto-anchoring its first
32
- * post adopts the post's `ts` as the thread root). Pass the
33
- * channel-local raw token, matching the token shape accepted by
34
- * route `send()`; the session handle preserves the current channel
35
- * namespace before writing to runtime context.
36
- *
37
- * Effects:
38
- *
39
- * - Updates `ContinuationTokenKey` in the active context to the
40
- * runtime-scoped token (`<channelName>:<rawToken>`).
41
- * - Causes the workflow runtime to dispose its current park hook
42
- * and register a new one at the new token at the next step
43
- * boundary, so follow-up `deliver` calls keyed under the new
44
- * token resume the same session.
45
- * - Idempotent — calling with the current token is a no-op.
46
- *
47
- * The session must already have a namespaced placeholder
48
- * continuation token so the handle can preserve the channel name.
49
- */
23
+ readonly auth: SessionAuth;
50
24
  setContinuationToken(rawToken: string): void;
51
25
  }
52
26
  export declare function createSession(id: string, continuationToken: string, runtime: Runtime): Session;
@@ -1 +1 @@
1
- import{AuthKey,ContinuationTokenKey,InitiatorAuthKey,SessionIdKey}from"#context/keys.js";function createSession(e,t,n){return{id:e,continuationToken:t,async getEventStream(t){return n.getEventStream(e,t)}}}function createGetSessionFn(e){return t=>createSession(t,``,e)}function buildSessionHandle(i){return{get id(){return i.get(SessionIdKey)??``},get continuationToken(){return i.get(ContinuationTokenKey)??``},get auth(){return i.get(AuthKey)??null},get initiatorAuth(){return i.get(InitiatorAuthKey)??null},setContinuationToken(e){let n=i.get(ContinuationTokenKey)??``,r=namespaceContinuationToken(n,e);n!==r&&i.set(ContinuationTokenKey,r)}}}function namespaceContinuationToken(e,t){let n=e.indexOf(`:`);if(n<=0)throw Error(`Cannot set session continuation token without an existing namespaced continuation token. Start the session with a placeholder continuationToken.`);return`${e.slice(0,n+1)}${t}`}export{buildSessionHandle,createGetSessionFn,createSession};
1
+ import{AuthKey,ContinuationTokenKey,InitiatorAuthKey,SessionIdKey}from"#context/keys.js";function createSession(e,t,n){return{id:e,continuationToken:t,async getEventStream(t){return n.getEventStream(e,t)}}}function createGetSessionFn(e){return t=>createSession(t,``,e)}function buildSessionHandle(i){return{get id(){return i.get(SessionIdKey)??``},get continuationToken(){return i.get(ContinuationTokenKey)??``},get auth(){return{current:i.get(AuthKey)??null,initiator:i.get(InitiatorAuthKey)??null}},setContinuationToken(e){let n=i.get(ContinuationTokenKey)??``,r=namespaceContinuationToken(n,e);n!==r&&i.set(ContinuationTokenKey,r)}}}function namespaceContinuationToken(e,t){let n=e.indexOf(`:`);if(n<=0)throw Error(`Cannot set session continuation token without an existing namespaced continuation token. Start the session with a placeholder continuationToken.`);return`${e.slice(0,n+1)}${t}`}export{buildSessionHandle,createGetSessionFn,createSession};
@@ -0,0 +1,8 @@
1
+ import type { AshCallbackContext } from "#public/definitions/callback-context.js";
2
+ /**
3
+ * Builds an {@link AshCallbackContext} from the active ALS scope.
4
+ *
5
+ * Must be called inside a harness step (active `contextStorage.run`).
6
+ * Throws when called outside an ALS scope.
7
+ */
8
+ export declare function buildCallbackContext(): AshCallbackContext;
@@ -0,0 +1 @@
1
+ import{SandboxKey,SessionKey}from"#context/keys.js";import{createSandboxSkillHandle}from"#runtime/skills/sandbox-access.js";import{loadContext}from"#context/container.js";function buildCallbackContext(){let r=loadContext(),i=r.require(SessionKey);return{session:{id:i.sessionId,auth:i.auth,turn:i.turn,parent:i.parent},getSandbox(){let t=r.get(SandboxKey);if(t===void 0)throw Error(`Ash sandbox runtime access is unavailable in the current async context. Call ctx.getSandbox() only from authored runtime functions such as tools, hooks, and channel events.`);return t.get().then(e=>{if(e===null)throw Error(`The sandbox is not available in the current authored runtime context.`);return e})},getSkill(t){let n=r.get(SandboxKey);if(n===void 0)throw Error(`Ash sandbox runtime access is unavailable in the current async context. Call ctx.getSkill() only from authored runtime functions such as tools, hooks, and channel events.`);return createSandboxSkillHandle(n,t)}}}export{buildCallbackContext};
@@ -1 +1 @@
1
- import{ContinuationTokenKey,SandboxKey,SessionIdKey,SessionPreparedKey}from"./keys.js";import{createLogger}from"#internal/logging.js";import{toErrorMessage}from"#shared/errors.js";import{normalizeSkillPackage,writeSkillPackageToSandbox}from"#shared/skill-package.js";import{getAdapterKind}from"#channel/adapter.js";import{emitRecoverableFailedTurn,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{formatAvailableSkillsSection}from"#execution/skills/instructions.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";const log=createLogger(`hooks.lifecycle`);async function dispatchHookLifecycle(e){let{ctx:t,registry:n,emit:i}=e,o=getHarnessEmissionState(e.session.state),s=`turn_${o.sequence}`,c=o.sequence,l=buildHookContext(t),u={session:{sessionId:e.session.sessionId},turn:{sequence:c,turnId:s}},d=[],f=e.session;if(n.session.length>0&&t.get(SessionPreparedKey)!==!0){t.set(SessionPreparedKey,!0);let e=[];for(let r of n.session){let n=await r.handler(u,l);n?.modelContext!==void 0&&n.modelContext.length>0&&d.push(...n.modelContext),e.push(...normalizeLifecycleSkillResults(t,n))}f=await materializeLifecycleSkills(t,f,e)}let p=!1,m=o;try{let e=[];for(let r of n.turn){let n=await r.handler(u,l);n?.modelContext!==void 0&&n.modelContext.length>0&&d.push(...n.modelContext),e.push(...normalizeLifecycleSkillResults(t,n))}f=await materializeLifecycleSkills(t,f,e)}catch(t){let n=toErrorMessage(t);try{p||=(m=await emitTurnPreamble(i,{message:e.input.message},o,e.runtimeIdentity),!0);let t=await emitRecoverableFailedTurn(i,m,{code:`HOOK_TURN_FAILED`,message:n});return{kind:`turn-failed`,message:n,nextSession:setHarnessEmissionState(f,t)}}catch(e){throw log.error(`Event hook threw while emitting the turn.failed cascade for a lifecycle.turn failure — escalating to session.failed.`,{error:toErrorMessage(e)}),e}}let h=e.input.modelContext??[],g=h.length===0?d:[...h,...d];return{kind:`proceed`,input:g.length>0?{...e.input,modelContext:g}:e.input,nextSession:f}}function normalizeLifecycleSkillResults(e,t){if(t?.skills===void 0||t.skills.length===0)return[];let n=new Set(e.require(BundleKey).resolvedAgent.skills.map(e=>e.name)),r=new Map;for(let e of t.skills){let t=normalizeSkillPackage(e);if(n.has(t.name))throw Error(`Hook-contributed skill "${t.name}" conflicts with an authored skill.`);r.set(t.name,t)}return[...r.values()]}async function materializeLifecycleSkills(e,n,r){if(r.length===0)return n;let i=new Map(r.map(e=>[e.name,e])),a=await e.require(SandboxKey).get();if(a===null)throw Error(`Dynamic skills require a sandbox for the current agent.`);for(let e of i.values())await writeSkillPackageToSandbox({sandbox:a,skill:e});let o=formatAvailableSkillsSection([...i.values()]);return o===null?n:{...n,history:[...n.history,{role:`system`,content:o}]}}async function dispatchStreamEventHooks(e){let t=e.registry.streamEventsByType.get(e.event.type)??[],n=e.registry.streamEventsWildcard;if(t.length===0&&n.length===0)return;let r=buildHookContext(e.ctx);for(let n of t)await n.handler(e.event,r);for(let t of n)await t.handler(e.event,r)}function buildHookContext(t){let r=t.require(BundleKey),i=t.get(ChannelKey),a=t.get(ContinuationTokenKey),o=i===void 0?void 0:getAdapterKind(i);return{agent:{name:r.resolvedAgent.config.name??`agent`,nodeId:r.nodeId},channel:{kind:o,continuationToken:a},session:{sessionId:t.get(SessionIdKey)??``},ash:t}}async function runHookLifecycleStep(e,t){let n=await dispatchHookLifecycle(e);return n.kind===`turn-failed`?{next:e.mode===`conversation`?null:{done:!0,output:n.message},session:n.nextSession}:t(n.nextSession,n.input)}export{dispatchHookLifecycle,dispatchStreamEventHooks,runHookLifecycleStep};
1
+ import{ContinuationTokenKey,SandboxKey,SessionPreparedKey}from"./keys.js";import{createLogger}from"#internal/logging.js";import{toErrorMessage}from"#shared/errors.js";import{normalizeSkillPackage,writeSkillPackageToSandbox}from"#shared/skill-package.js";import{getAdapterKind}from"#channel/adapter.js";import{emitRecoverableFailedTurn,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{formatAvailableSkillsSection}from"#execution/skills/instructions.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";const log=createLogger(`hooks.lifecycle`);async function dispatchHookLifecycle(e){let{ctx:t,registry:r,emit:a}=e,o=getHarnessEmissionState(e.session.state),s=buildHookContext(t),c=[],l=e.session;if(r.session.length>0&&t.get(SessionPreparedKey)!==!0){t.set(SessionPreparedKey,!0);let e=[];for(let n of r.session){let r=await n.handler(s);r?.modelContext!==void 0&&r.modelContext.length>0&&c.push(...r.modelContext),e.push(...normalizeLifecycleSkillResults(t,r))}l=await materializeLifecycleSkills(t,l,e)}let u=!1,d=o;try{let e=[];for(let n of r.turn){let r=await n.handler(s);r?.modelContext!==void 0&&r.modelContext.length>0&&c.push(...r.modelContext),e.push(...normalizeLifecycleSkillResults(t,r))}l=await materializeLifecycleSkills(t,l,e)}catch(t){let n=toErrorMessage(t);try{u||=(d=await emitTurnPreamble(a,{message:e.input.message},o,e.runtimeIdentity),!0);let t=await emitRecoverableFailedTurn(a,d,{code:`HOOK_TURN_FAILED`,message:n});return{kind:`turn-failed`,message:n,nextSession:setHarnessEmissionState(l,t)}}catch(e){throw log.error(`Event hook threw while emitting the turn.failed cascade for a lifecycle.turn failure — escalating to session.failed.`,{error:toErrorMessage(e)}),e}}let f=e.input.modelContext??[],p=f.length===0?c:[...f,...c];return{kind:`proceed`,input:p.length>0?{...e.input,modelContext:p}:e.input,nextSession:l}}function normalizeLifecycleSkillResults(e,t){if(t?.skills===void 0||t.skills.length===0)return[];let n=new Set(e.require(BundleKey).resolvedAgent.skills.map(e=>e.name)),r=new Map;for(let e of t.skills){let t=normalizeSkillPackage(e);if(n.has(t.name))throw Error(`Hook-contributed skill "${t.name}" conflicts with an authored skill.`);r.set(t.name,t)}return[...r.values()]}async function materializeLifecycleSkills(e,n,r){if(r.length===0)return n;let i=new Map(r.map(e=>[e.name,e])),a=await e.require(SandboxKey).get();if(a===null)throw Error(`Dynamic skills require a sandbox for the current agent.`);for(let e of i.values())await writeSkillPackageToSandbox({sandbox:a,skill:e});let s=formatAvailableSkillsSection([...i.values()]);return s===null?n:{...n,history:[...n.history,{role:`system`,content:s}]}}async function dispatchStreamEventHooks(e){let t=e.registry.streamEventsByType.get(e.event.type)??[],n=e.registry.streamEventsWildcard;if(t.length===0&&n.length===0)return;let r=buildHookContext(e.ctx);for(let n of t)await n.handler(e.event,r);for(let t of n)await t.handler(e.event,r)}function buildHookContext(t){let n=t.require(BundleKey),r=t.get(ChannelKey),i=t.get(ContinuationTokenKey),a=r===void 0?void 0:getAdapterKind(r);return{...buildCallbackContext(),agent:{name:n.resolvedAgent.config.name??`agent`,nodeId:n.nodeId},channel:{kind:a,continuationToken:i}}}async function runHookLifecycleStep(e,t){let n=await dispatchHookLifecycle(e);return n.kind===`turn-failed`?{next:e.mode===`conversation`?null:{done:!0,output:n.message},session:n.nextSession}:t(n.nextSession,n.input)}export{dispatchHookLifecycle,dispatchStreamEventHooks,runHookLifecycleStep};
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{jsonSchema}from"ai";import{createToolLoopHarness}from"#harness/tool-loop.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}),i=collectResolvedTools(e.node),a=createToolCompactionHandler(i),s=collectRetentionPolicies(i);return createToolLoopHarness({capabilities:e.capabilities,emit:e.emit,mode:e.mode,onCompaction:a,resolveModel:t,retentionPolicies:s,runtimeIdentity:buildRuntimeIdentity(e.node),tools:n})}function buildRuntimeIdentity(e){let n=resolveInstalledPackageInfo(),r={agentId:e.turnAgent.id,agentName:e.agent.config?.name,ashVersion:n.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 collectRetentionPolicies(e){let t=new Map;for(let n of e){let e=n.retentionPolicy;e===void 0||e===`auto`||t.set(n.name,e)}return t}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,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,runtimeAction:{kind:`remote-agent-call`,nodeId:e.tool.nodeId,remoteAgentName:e.tool.name,subagentName:e.tool.name}};let t=findRegisteredRuntimeTool(e.node.toolRegistry,e.tool.name);if(t===null)return log.warn(`declared tool is not registered — omitting from toolset`,{toolName:e.tool.name,nodeId:e.node.nodeId}),null;let r=t.definition;return{approvalKey:r.approvalKey,description:r.description,execute:r.execute,inputSchema:r.inputStandardSchema??jsonSchema(r.inputSchema??{}),name:r.name,needsApproval:r.needsApproval,toModelOutput:r.toModelOutput}}export{createExecutionNodeStep,createNodeHarnessTools};
1
+ import{createLogger}from"#internal/logging.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{jsonSchema}from"ai";import{createToolLoopHarness}from"#harness/tool-loop.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=collectResolvedTools(e.node),a=createToolCompactionHandler(r),o=collectRetentionPolicies(r);return createToolLoopHarness({capabilities:e.capabilities,emit:e.emit,mode:e.mode,onCompaction:a,resolveModel:t,retentionPolicies:o,runtimeIdentity:buildRuntimeIdentity(e.node),tools:n})}function buildRuntimeIdentity(e){let n=resolveInstalledPackageInfo(),r={agentId:e.turnAgent.id,agentName:e.agent.config?.name,ashVersion:n.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 collectRetentionPolicies(e){let t=new Map;for(let n of e){let e=n.retentionPolicy;e===void 0||e===`auto`||t.set(n.name,e)}return t}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,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,runtimeAction:{kind:`remote-agent-call`,nodeId:e.tool.nodeId,remoteAgentName:e.tool.name,subagentName:e.tool.name}};let t=findRegisteredRuntimeTool(e.node.toolRegistry,e.tool.name);if(t===null)return log.warn(`declared tool is not registered — omitting from toolset`,{toolName:e.tool.name,nodeId:e.node.nodeId}),null;let i=t.definition,a=i.sourceId.startsWith(`ash:`),s=i.execute;return{approvalKey:i.approvalKey,description:i.description,execute:s===void 0?void 0:a?s:e=>s(e,buildCallbackContext()),inputSchema:i.inputStandardSchema??jsonSchema(i.inputSchema??{}),name:i.name,needsApproval:i.needsApproval,toModelOutput:i.toModelOutput}}export{createExecutionNodeStep,createNodeHarnessTools};
@@ -1,3 +1,4 @@
1
+ import type { SandboxSession } from "#shared/sandbox-session.js";
1
2
  /**
2
3
  * Typed input accepted by {@link executeBashOnSandbox}.
3
4
  */
@@ -26,4 +27,4 @@ export interface BashResult {
26
27
  * `defineBashTool`. Centralizing the executor here keeps the error
27
28
  * messages and result shape identical across all bash-style tools.
28
29
  */
29
- export declare function executeBashOnSandbox(args: BashInput): Promise<BashResult>;
30
+ export declare function executeBashOnSandbox(sandbox: SandboxSession, args: BashInput): Promise<BashResult>;
@@ -1 +1 @@
1
- import{requireSandboxSession}from"#execution/sandbox/require-sandbox.js";import{truncateTail}from"#execution/sandbox/truncate-output.js";async function executeBashOnSandbox(e){let t=await(await requireSandboxSession()).run({command:e.command}),n=truncateTail(t.stdout),r=truncateTail(t.stderr),i=n.truncated||r.truncated,a=n.output;n.truncated&&(a=`[stdout truncated: showing last ${n.outputLines} of ${n.totalLines} lines]\n`+a);let o=r.output;return r.truncated&&(o=`[stderr truncated: showing last ${r.outputLines} of ${r.totalLines} lines]\n`+o),{exitCode:t.exitCode,stderr:o,stdout:a,truncated:i}}export{executeBashOnSandbox};
1
+ import{truncateTail}from"#execution/sandbox/truncate-output.js";async function executeBashOnSandbox(e,t){let n=await e.run({command:t.command}),r=truncateTail(n.stdout),i=truncateTail(n.stderr),a=r.truncated||i.truncated,o=r.output;r.truncated&&(o=`[stdout truncated: showing last ${r.outputLines} of ${r.totalLines} lines]\n`+o);let s=i.output;return i.truncated&&(s=`[stderr truncated: showing last ${i.outputLines} of ${i.totalLines} lines]\n`+s),{exitCode:n.exitCode,stderr:s,stdout:o,truncated:a}}export{executeBashOnSandbox};
@@ -1,3 +1,4 @@
1
+ import type { SandboxSession } from "#shared/sandbox-session.js";
1
2
  /**
2
3
  * Typed input accepted by {@link executeGlobOnSandbox}.
3
4
  */
@@ -18,4 +19,4 @@ export interface GlobResult {
18
19
  /**
19
20
  * Searches for files matching a glob pattern inside the sandbox.
20
21
  */
21
- export declare function executeGlobOnSandbox(args: GlobInput): Promise<GlobResult>;
22
+ export declare function executeGlobOnSandbox(sandbox: SandboxSession, args: GlobInput): Promise<GlobResult>;
@@ -1,3 +1,3 @@
1
- import{requireSandboxSession,validateAbsoluteFilePath}from"#execution/sandbox/require-sandbox.js";import{MAX_OUTPUT_BYTES}from"#execution/sandbox/truncate-output.js";import{shellQuote}from"#execution/sandbox/shell-quote.js";import{normalizeModelPath}from"#runtime/framework-tools/file-state.js";import{ripgrepIsAvailable}from"#execution/sandbox/ripgrep-probe.js";async function executeGlobOnSandbox(r){let a=r.path??`/workspace`;validateAbsoluteFilePath(a);let o=normalizeModelPath(a),s=Math.min(Math.max(1,r.limit??100),1e3),c=await requireSandboxSession(),l=await ripgrepIsAvailable(c)?buildRipgrepCommand({normalizedPath:o,pattern:r.pattern}):buildPosixFindCommand({normalizedPath:o,pattern:r.pattern}),u=await c.run({command:l});if(u.exitCode!==0&&u.exitCode!==1)throw buildGlobExecutionError(l,u.exitCode,u.stderr);let d=u.stdout.split(`
2
- `).filter(e=>e.length>0),f=d.length>s,p=f?d.slice(0,s):d,m=[],h=0,g=!1;for(let e of p){let t=normalizeModelPath(e),r=Buffer.byteLength(t,`utf8`)+1;if(h+r>MAX_OUTPUT_BYTES&&m.length>0){g=!0;break}m.push(t),h+=r}if(m.length===0)return{content:`No files found`,count:0,path:o,truncated:!1};let _=f||g,v=[...m];return _&&(v.push(``),v.push(`(Results truncated: showing first ${m.length} results out of more. Use a more specific path or pattern to narrow results.)`)),{content:v.join(`
3
- `),count:m.length,path:o,truncated:_}}function buildRipgrepCommand(e){return[`rg --files --hidden`,`--glob '!.git/*'`,`--glob ${shellQuote(e.pattern)}`,`-- ${shellQuote(e.normalizedPath)}`].join(` `)}function buildPosixFindCommand(e){let t=translateGlobToFindPattern(e.pattern),n=t.includes(`/`)?`-path ${shellQuote(`*/${t}`)}`:`-name ${shellQuote(t)}`;return[`find ${shellQuote(e.normalizedPath)}`,`-type f`,`-not -path '*/.git/*'`,n].join(` `)}function translateGlobToFindPattern(e){let t=e.replaceAll(`**`,`*`);for(;t.startsWith(`*/`);)t=t.slice(2);return t}function buildGlobExecutionError(e,t,n){let r=n.trim(),i=r.length>0?r:`no stderr output`;return Error(`glob failed (exit ${t}): ${i}\nCommand: ${e}`)}export{executeGlobOnSandbox};
1
+ import{MAX_OUTPUT_BYTES}from"#execution/sandbox/truncate-output.js";import{shellQuote}from"#execution/sandbox/shell-quote.js";import{normalizeModelPath}from"#runtime/framework-tools/file-state.js";import{validateAbsoluteFilePath}from"#execution/sandbox/require-sandbox.js";import{ripgrepIsAvailable}from"#execution/sandbox/ripgrep-probe.js";async function executeGlobOnSandbox(t,a){let o=a.path??`/workspace`;validateAbsoluteFilePath(o);let s=normalizeModelPath(o),c=Math.min(Math.max(1,a.limit??100),1e3),l=await ripgrepIsAvailable(t)?buildRipgrepCommand({normalizedPath:s,pattern:a.pattern}):buildPosixFindCommand({normalizedPath:s,pattern:a.pattern}),u=await t.run({command:l});if(u.exitCode!==0&&u.exitCode!==1)throw buildGlobExecutionError(l,u.exitCode,u.stderr);let d=u.stdout.split(`
2
+ `).filter(e=>e.length>0),f=d.length>c,p=f?d.slice(0,c):d,m=[],h=0,g=!1;for(let t of p){let r=normalizeModelPath(t),i=Buffer.byteLength(r,`utf8`)+1;if(h+i>MAX_OUTPUT_BYTES&&m.length>0){g=!0;break}m.push(r),h+=i}if(m.length===0)return{content:`No files found`,count:0,path:s,truncated:!1};let _=f||g,v=[...m];return _&&(v.push(``),v.push(`(Results truncated: showing first ${m.length} results out of more. Use a more specific path or pattern to narrow results.)`)),{content:v.join(`
3
+ `),count:m.length,path:s,truncated:_}}function buildRipgrepCommand(e){return[`rg --files --hidden`,`--glob '!.git/*'`,`--glob ${shellQuote(e.pattern)}`,`-- ${shellQuote(e.normalizedPath)}`].join(` `)}function buildPosixFindCommand(e){let n=translateGlobToFindPattern(e.pattern),r=n.includes(`/`)?`-path ${shellQuote(`*/${n}`)}`:`-name ${shellQuote(n)}`;return[`find ${shellQuote(e.normalizedPath)}`,`-type f`,`-not -path '*/.git/*'`,r].join(` `)}function translateGlobToFindPattern(e){let t=e.replaceAll(`**`,`*`);for(;t.startsWith(`*/`);)t=t.slice(2);return t}function buildGlobExecutionError(e,t,n){let r=n.trim(),i=r.length>0?r:`no stderr output`;return Error(`glob failed (exit ${t}): ${i}\nCommand: ${e}`)}export{executeGlobOnSandbox};
@@ -1,3 +1,4 @@
1
+ import type { SandboxSession } from "#shared/sandbox-session.js";
1
2
  /**
2
3
  * Typed input accepted by {@link executeGrepOnSandbox}.
3
4
  */
@@ -22,4 +23,4 @@ export interface GrepResult {
22
23
  /**
23
24
  * Searches file contents for a pattern inside the sandbox.
24
25
  */
25
- export declare function executeGrepOnSandbox(args: GrepInput): Promise<GrepResult>;
26
+ export declare function executeGrepOnSandbox(sandbox: SandboxSession, args: GrepInput): Promise<GrepResult>;
@@ -1,3 +1,3 @@
1
- import{requireSandboxSession,validateAbsoluteFilePath}from"#execution/sandbox/require-sandbox.js";import{MAX_OUTPUT_BYTES,capLineLength}from"#execution/sandbox/truncate-output.js";import{shellQuote}from"#execution/sandbox/shell-quote.js";import{normalizeModelPath}from"#runtime/framework-tools/file-state.js";import{ripgrepIsAvailable}from"#execution/sandbox/ripgrep-probe.js";async function executeGrepOnSandbox(n){let r=n.path??`/workspace`;validateAbsoluteFilePath(r);let i=normalizeModelPath(r),s=Math.min(Math.max(1,n.limit??100),1e3),c=n.context!==void 0&&n.context>0?n.context:0,l=await requireSandboxSession(),u=await ripgrepIsAvailable(l)?buildRipgrepCommand({contextLines:c,effectiveLimit:s,glob:n.glob,ignoreCase:n.ignoreCase??!1,literal:n.literal??!1,normalizedPath:i,pattern:n.pattern}):buildPosixGrepCommand({contextLines:c,effectiveLimit:s,glob:n.glob,ignoreCase:n.ignoreCase??!1,literal:n.literal??!1,normalizedPath:i,pattern:n.pattern}),d=await l.run({command:u});if(d.exitCode!==0&&d.exitCode!==1)throw buildGrepExecutionError(u,d.exitCode,d.stderr);let f=d.stdout;return f.trim().length===0?{content:`No matches found`,matchCount:0,path:i,truncated:!1}:processOutput({effectiveLimit:s,normalizedPath:i,stdout:f})}function buildRipgrepCommand(e){let t=[`rg`,`--line-number`,`--color=never`,`--hidden`,`--glob '!.git/*'`];return e.ignoreCase&&t.push(`--ignore-case`),e.literal&&t.push(`--fixed-strings`),e.glob!==void 0&&t.push(`--glob ${shellQuote(e.glob)}`),e.contextLines>0&&t.push(`--context ${e.contextLines}`),t.push(`--max-count ${e.effectiveLimit}`),t.push(`--`),t.push(shellQuote(e.pattern)),t.push(shellQuote(e.normalizedPath)),t.join(` `)}function buildPosixGrepCommand(e){let t=[`grep`,`-r`,`-n`,`--color=never`,`--exclude-dir=.git`];return e.ignoreCase&&t.push(`-i`),e.literal?t.push(`-F`):t.push(`-E`),e.glob!==void 0&&t.push(`--include=${shellQuote(e.glob)}`),e.contextLines>0&&t.push(`-C ${e.contextLines}`),t.push(`-m ${e.effectiveLimit}`),t.push(`--`),t.push(shellQuote(e.pattern)),t.push(shellQuote(e.normalizedPath)),t.join(` `)}function processOutput(e){let t=e.stdout.split(`
2
- `),i=[],a=0,o=0,s=!1;for(let e of t){if(e.length===0&&t.indexOf(e)===t.length-1)continue;e!==`--`&&e.length>0&&/^.+:\d+:/.test(e)&&o++;let c=capLineLength(e),l=Buffer.byteLength(c,`utf8`)+1;if(a+l>MAX_OUTPUT_BYTES&&i.length>0){s=!0;break}i.push(c),a+=l}let c=s||o>=e.effectiveLimit,l=i.join(`
3
- `);if(c){let t=[];o>=e.effectiveLimit&&t.push(`Match limit reached (${e.effectiveLimit}). Use a larger limit or more specific pattern.`),s&&t.push(`Output truncated due to size. Use a more specific path or pattern.`),l+=`\n\n[${t.join(` `)}]`}return{content:l,matchCount:o,path:e.normalizedPath,truncated:c}}function buildGrepExecutionError(e,t,n){let r=n.trim(),i=r.length>0?r:`no stderr output`;return Error(`grep failed (exit ${t}): ${i}\nCommand: ${e}`)}export{executeGrepOnSandbox};
1
+ import{MAX_OUTPUT_BYTES,capLineLength}from"#execution/sandbox/truncate-output.js";import{shellQuote}from"#execution/sandbox/shell-quote.js";import{normalizeModelPath}from"#runtime/framework-tools/file-state.js";import{validateAbsoluteFilePath}from"#execution/sandbox/require-sandbox.js";import{ripgrepIsAvailable}from"#execution/sandbox/ripgrep-probe.js";async function executeGrepOnSandbox(e,t){let n=t.path??`/workspace`;validateAbsoluteFilePath(n);let o=normalizeModelPath(n),s=Math.min(Math.max(1,t.limit??100),1e3),c=t.context!==void 0&&t.context>0?t.context:0,l=await ripgrepIsAvailable(e)?buildRipgrepCommand({contextLines:c,effectiveLimit:s,glob:t.glob,ignoreCase:t.ignoreCase??!1,literal:t.literal??!1,normalizedPath:o,pattern:t.pattern}):buildPosixGrepCommand({contextLines:c,effectiveLimit:s,glob:t.glob,ignoreCase:t.ignoreCase??!1,literal:t.literal??!1,normalizedPath:o,pattern:t.pattern}),u=await e.run({command:l});if(u.exitCode!==0&&u.exitCode!==1)throw buildGrepExecutionError(l,u.exitCode,u.stderr);let d=u.stdout;return d.trim().length===0?{content:`No matches found`,matchCount:0,path:o,truncated:!1}:processOutput({effectiveLimit:s,normalizedPath:o,stdout:d})}function buildRipgrepCommand(e){let t=[`rg`,`--line-number`,`--color=never`,`--hidden`,`--glob '!.git/*'`];return e.ignoreCase&&t.push(`--ignore-case`),e.literal&&t.push(`--fixed-strings`),e.glob!==void 0&&t.push(`--glob ${shellQuote(e.glob)}`),e.contextLines>0&&t.push(`--context ${e.contextLines}`),t.push(`--max-count ${e.effectiveLimit}`),t.push(`--`),t.push(shellQuote(e.pattern)),t.push(shellQuote(e.normalizedPath)),t.join(` `)}function buildPosixGrepCommand(e){let t=[`grep`,`-r`,`-n`,`--color=never`,`--exclude-dir=.git`];return e.ignoreCase&&t.push(`-i`),e.literal?t.push(`-F`):t.push(`-E`),e.glob!==void 0&&t.push(`--include=${shellQuote(e.glob)}`),e.contextLines>0&&t.push(`-C ${e.contextLines}`),t.push(`-m ${e.effectiveLimit}`),t.push(`--`),t.push(shellQuote(e.pattern)),t.push(shellQuote(e.normalizedPath)),t.join(` `)}function processOutput(n){let r=n.stdout.split(`
2
+ `),i=[],a=0,o=0,s=!1;for(let n of r){if(n.length===0&&r.indexOf(n)===r.length-1)continue;n!==`--`&&n.length>0&&/^.+:\d+:/.test(n)&&o++;let c=capLineLength(n),l=Buffer.byteLength(c,`utf8`)+1;if(a+l>MAX_OUTPUT_BYTES&&i.length>0){s=!0;break}i.push(c),a+=l}let c=s||o>=n.effectiveLimit,l=i.join(`
3
+ `);if(c){let e=[];o>=n.effectiveLimit&&e.push(`Match limit reached (${n.effectiveLimit}). Use a larger limit or more specific pattern.`),s&&e.push(`Output truncated due to size. Use a more specific path or pattern.`),l+=`\n\n[${e.join(` `)}]`}return{content:l,matchCount:o,path:n.normalizedPath,truncated:c}}function buildGrepExecutionError(e,t,n){let r=n.trim(),i=r.length>0?r:`no stderr output`;return Error(`grep failed (exit ${t}): ${i}\nCommand: ${e}`)}export{executeGrepOnSandbox};
@@ -1,3 +1,4 @@
1
+ import type { SandboxSession } from "#shared/sandbox-session.js";
1
2
  /**
2
3
  * Typed input accepted by {@link executeReadFileOnSandbox}.
3
4
  */
@@ -24,4 +25,4 @@ export interface ReadFileResult {
24
25
  * Used by the framework `read_file` tool and by author tools constructed
25
26
  * via `defineReadFileTool`.
26
27
  */
27
- export declare function executeReadFileOnSandbox(args: ReadFileInput): Promise<ReadFileResult>;
28
+ export declare function executeReadFileOnSandbox(sandbox: SandboxSession, args: ReadFileInput): Promise<ReadFileResult>;
@@ -1,3 +1,3 @@
1
- import{loadContext}from"#context/container.js";import{requireSandboxSession,validateAbsoluteFilePath}from"#execution/sandbox/require-sandbox.js";import{MAX_OUTPUT_BYTES,capLineLength}from"#execution/sandbox/truncate-output.js";import{buildReadFileTargetKey,createReadFileStamp,normalizeModelPath,setReadFileStamp}from"#runtime/framework-tools/file-state.js";async function executeReadFileOnSandbox(r){let{filePath:i,offset:a,limit:o}=r;validateAbsoluteFilePath(i);let s=await requireSandboxSession(),c=normalizeModelPath(i),l=a??1,u=o??2e3;if(l<1)throw Error(`offset must be >= 1. Received: ${l}.`);let d=await s.readTextFile({path:i});if(d===null)throw Error(`File not found: ${i}. Verify the path exists and is accessible in the sandbox.`);if(d.includes(`\0`))throw Error(`File "${i}" contains NUL bytes and appears to be a binary file. read_file only supports text files.`);let f=d.split(`
1
+ import{loadContext}from"#context/container.js";import{MAX_OUTPUT_BYTES,capLineLength}from"#execution/sandbox/truncate-output.js";import{buildReadFileTargetKey,createReadFileStamp,normalizeModelPath,setReadFileStamp}from"#runtime/framework-tools/file-state.js";import{validateAbsoluteFilePath}from"#execution/sandbox/require-sandbox.js";async function executeReadFileOnSandbox(r,i){let{filePath:a,offset:o,limit:s}=i;validateAbsoluteFilePath(a);let c=normalizeModelPath(a),l=o??1,u=s??2e3;if(l<1)throw Error(`offset must be >= 1. Received: ${l}.`);let d=await r.readTextFile({path:a});if(d===null)throw Error(`File not found: ${a}. Verify the path exists and is accessible in the sandbox.`);if(d.includes(`\0`))throw Error(`File "${a}" contains NUL bytes and appears to be a binary file. read_file only supports text files.`);let f=d.split(`
2
2
  `),p=f.length>0&&f[f.length-1]===``?f.length-1:f.length;if(p===0){if(l>1)throw Error(`offset ${l} is past the end of the file (0 lines). Use the default offset to read an empty file.`);return{content:``,path:c,totalLines:0,truncated:!1}}if(l>p)throw Error(`offset ${l} is past the end of the file (${p} lines).`);let m=createReadFileStamp({content:d,filePath:c}),h=buildReadFileTargetKey(c);setReadFileStamp(loadContext(),h,m);let g=l-1,_=Math.min(g+u,p),v=f.slice(g,_),y=[],b=0,x=!1;for(let e=0;e<v.length;e++){let t=`${l+e}: ${capLineLength(v[e]??``)}`,n=Buffer.byteLength(t,`utf8`)+1;if(b+n>MAX_OUTPUT_BYTES&&y.length>0){x=!0;break}y.push(t),b+=n}let S=y.join(`
3
3
  `),C=l+y.length-1;return C<p||x?{content:S,nextOffset:C+1,path:c,totalLines:p,truncated:!0}:{content:S,path:c,totalLines:p,truncated:!1}}export{executeReadFileOnSandbox};
@@ -1,3 +1,4 @@
1
+ import type { SandboxSession } from "#shared/sandbox-session.js";
1
2
  /**
2
3
  * Typed input accepted by {@link executeWriteFileOnSandbox}.
3
4
  */
@@ -19,4 +20,4 @@ export interface WriteFileResult {
19
20
  * Used by the framework `write_file` tool and by author tools
20
21
  * constructed via `defineWriteFileTool`.
21
22
  */
22
- export declare function executeWriteFileOnSandbox(args: WriteFileInput): Promise<WriteFileResult>;
23
+ export declare function executeWriteFileOnSandbox(sandbox: SandboxSession, args: WriteFileInput): Promise<WriteFileResult>;
@@ -1 +1 @@
1
- import{loadContext}from"#context/container.js";import{requireSandboxSession,validateAbsoluteFilePath}from"#execution/sandbox/require-sandbox.js";import{ReadFileStateKey,buildReadFileTargetKey,createReadFileStamp,normalizeModelPath,setReadFileStamp}from"#runtime/framework-tools/file-state.js";async function executeWriteFileOnSandbox(e){let{filePath:t,content:n}=e;validateAbsoluteFilePath(t);let r=await requireSandboxSession(),i=loadContext(),a=normalizeModelPath(t),o=buildReadFileTargetKey(a),s=await r.readTextFile({path:t});if(s===null)return await r.writeTextFile({content:n,path:t}),setReadFileStamp(i,o,createReadFileStamp({content:n,filePath:a})),{existed:!1,path:a};let c=i.ensure(ReadFileStateKey,()=>({byTarget:{}})).byTarget[o];if(c===void 0)throw Error(`You must read file ${t} before overwriting it. Use the read_file tool first.`);let l=createReadFileStamp({content:s,filePath:a});if(l.contentHash!==c.contentHash||l.byteLength!==c.byteLength)throw Error(`File ${t} has been modified since it was last read. Please read the file again before modifying it.`);return await r.writeTextFile({content:n,path:t}),setReadFileStamp(i,o,createReadFileStamp({content:n,filePath:a})),{existed:!0,path:a}}export{executeWriteFileOnSandbox};
1
+ import{loadContext}from"#context/container.js";import{ReadFileStateKey,buildReadFileTargetKey,createReadFileStamp,normalizeModelPath,setReadFileStamp}from"#runtime/framework-tools/file-state.js";import{validateAbsoluteFilePath}from"#execution/sandbox/require-sandbox.js";async function executeWriteFileOnSandbox(e,t){let{filePath:n,content:r}=t;validateAbsoluteFilePath(n);let i=loadContext(),a=normalizeModelPath(n),o=buildReadFileTargetKey(a),s=await e.readTextFile({path:n});if(s===null)return await e.writeTextFile({content:r,path:n}),setReadFileStamp(i,o,createReadFileStamp({content:r,filePath:a})),{existed:!1,path:a};let c=i.ensure(ReadFileStateKey,()=>({byTarget:{}})).byTarget[o];if(c===void 0)throw Error(`You must read file ${n} before overwriting it. Use the read_file tool first.`);let l=createReadFileStamp({content:s,filePath:a});if(l.contentHash!==c.contentHash||l.byteLength!==c.byteLength)throw Error(`File ${n} has been modified since it was last read. Please read the file again before modifying it.`);return await e.writeTextFile({content:r,path:n}),setReadFileStamp(i,o,createReadFileStamp({content:r,filePath:a})),{existed:!0,path:a}}export{executeWriteFileOnSandbox};
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{loadContext}from"#context/container.js";const log=createLogger(`execution.tool-compaction`);function createToolCompactionHandler(e){let n=e.filter(e=>e.onCompact!==void 0);return async e=>{if(n.length===0)return{messages:[],session:e};let r=loadContext(),i=new AbortController().signal,a=[],o=e.state??{},s=!1;for(let t of n){let n=t.onCompact;if(n===void 0)continue;let c;try{c=await n({ctx:r,session:e,signal:i})??{}}catch(e){log.warn(`compaction hook for tool "${t.name}" threw and was skipped`,{toolName:t.name,error:e});continue}c.messages!==void 0&&c.messages.length>0&&a.push(...c.messages),c.sessionPatch!==void 0&&(o={...o,...c.sessionPatch},s=!0)}return{messages:a,session:s?{...e,state:o}:e}}}export{createToolCompactionHandler};
1
+ import{createLogger}from"#internal/logging.js";import{buildCallbackContext}from"#context/build-callback-context.js";const log=createLogger(`execution.tool-compaction`);function createToolCompactionHandler(e){let n=e.filter(e=>e.onCompact!==void 0);return async e=>{if(n.length===0)return{messages:[],session:e};let r=buildCallbackContext(),i=new AbortController().signal,a=[],o=e.state??{},s=!1;for(let t of n){let n=t.onCompact;if(n===void 0)continue;let c;try{c=await n({history:e.history,signal:i},r)??{}}catch(e){log.warn(`compaction hook for tool "${t.name}" threw and was skipped`,{toolName:t.name,error:e});continue}c.messages!==void 0&&c.messages.length>0&&a.push(...c.messages),c.sessionPatch!==void 0&&(o={...o,...c.sessionPatch},s=!0)}return{messages:a,session:s?{...e,state:o}:e}}}export{createToolCompactionHandler};
@@ -1 +1 @@
1
- import{CodeModeProtocolError}from"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/errors.js";import{isCodeModeApprovalInterrupt}from"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/approval-continuation.js";import"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/index.js";const PENDING_CODE_MODE_APPROVAL_KEY=`ash.harness.pendingCodeModeApproval`;function getPendingCodeModeApproval(e){let r=e?.[PENDING_CODE_MODE_APPROVAL_KEY];if(isRecord(r)&&!(!isCodeModeApprovalInterrupt(r.interrupt)||!Array.isArray(r.responseMessages)))return{interrupt:r.interrupt,responseMessages:r.responseMessages}}function setPendingCodeModeApproval(e){return{...e.session,state:{...e.session.state,[PENDING_CODE_MODE_APPROVAL_KEY]:{interrupt:e.interrupt,responseMessages:e.responseMessages}}}}function clearPendingCodeModeApproval(e){if(e.state?.[PENDING_CODE_MODE_APPROVAL_KEY]===void 0)return e;let t={...e.state};return delete t[PENDING_CODE_MODE_APPROVAL_KEY],{...e,state:Object.keys(t).length>0?t:void 0}}function replaceCodeModeApprovalInterruptResult(t,n,r){let i=0,a=toModelToolOutput(r),o=t.map(t=>{let r=t;if(!Array.isArray(r.content))return t;let o=!1,s=r.content.map(t=>{if(!isRecord(t)||t.type!==`tool-result`||t.toolCallId!==n.continuation.outerToolCallId)return t;if(!toolResultOutputContainsApprovalInterrupt(t.output,n.approvalId))throw new CodeModeProtocolError(`Outer code_mode tool result ${n.continuation.outerToolCallId} does not contain pending approval ${n.approvalId}.`,{approvalId:n.approvalId,outerToolCallId:n.continuation.outerToolCallId});return i++,o=!0,{...t,output:a}});return o?{...t,content:s}:t});if(i!==1)throw new CodeModeProtocolError(`Expected one outer code_mode approval result replacement for ${n.approvalId}, found ${i}.`,{approvalId:n.approvalId,outerToolCallId:n.continuation.outerToolCallId,replacements:i});return o}function splitCodeModeOuterResponseMessages(e){let t=e.messages.findIndex(t=>messageContainsToolResult(t,e.outerToolCallId));if(t<0)return{promptMessages:e.messages,responseMessages:[]};let n=t-1,r=n>=0&&messageContainsToolCall(e.messages[n],e.outerToolCallId)?n:t;return{promptMessages:e.messages.slice(0,r),responseMessages:e.messages.slice(r)}}function messageContainsToolCall(e,t){return e?.role!==`assistant`||!Array.isArray(e.content)?!1:e.content.some(e=>typeof e==`object`&&!!e&&`type`in e&&e.type===`tool-call`&&`toolCallId`in e&&e.toolCallId===t)}function messageContainsToolResult(e,t){return e?.role!==`tool`||!Array.isArray(e.content)?!1:e.content.some(e=>e.type===`tool-result`&&`toolCallId`in e&&e.toolCallId===t)}function toolResultOutputContainsApprovalInterrupt(e,t){return readApprovalInterruptValue(e)?.approvalId===t}function readApprovalInterruptValue(e){if(isCodeModeApprovalInterrupt(e))return e;if(isRecord(e)&&(e.type===`json`||e.type===`text`)&&Object.hasOwn(e,`value`))return readApprovalInterruptValue(e.value)}function toModelToolOutput(e){return typeof e==`string`?{type:`text`,value:e}:{type:`json`,value:e===void 0?null:e}}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{clearPendingCodeModeApproval,getPendingCodeModeApproval,replaceCodeModeApprovalInterruptResult,setPendingCodeModeApproval,splitCodeModeOuterResponseMessages};
1
+ import{CodeModeProtocolError}from"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/errors.js";import{isCodeModeApprovalInterrupt}from"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/approval-continuation.js";import"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/index.js";const PENDING_CODE_MODE_APPROVAL_KEY=`ash.harness.pendingCodeModeApproval`;function getPendingCodeModeApproval(e){let r=e?.[PENDING_CODE_MODE_APPROVAL_KEY];if(isRecord(r)&&!(!isCodeModeApprovalInterrupt(r.interrupt)||!Array.isArray(r.responseMessages)))return{interrupt:r.interrupt,responseMessages:r.responseMessages}}function setPendingCodeModeApproval(e){return{...e.session,state:{...e.session.state,[PENDING_CODE_MODE_APPROVAL_KEY]:{interrupt:e.interrupt,responseMessages:e.responseMessages}}}}function clearPendingCodeModeApproval(e){if(e.state?.[PENDING_CODE_MODE_APPROVAL_KEY]===void 0)return e;let t={...e.state};return delete t[PENDING_CODE_MODE_APPROVAL_KEY],{...e,state:Object.keys(t).length>0?t:void 0}}function replaceCodeModeApprovalInterruptResult(t,n,r){let i=0,a=toModelToolOutput(r),o=t.map(t=>{let r=t;if(!Array.isArray(r.content))return t;let o=!1,s=r.content.map(t=>{if(!isRecord(t)||t.type!==`tool-result`||t.toolCallId!==n.continuation.outerToolCallId)return t;if(!toolResultOutputContainsApprovalInterrupt(t.output,n.approvalId))throw new CodeModeProtocolError(`Outer code_mode tool result ${n.continuation.outerToolCallId} does not contain pending approval ${n.approvalId}.`,{approvalId:n.approvalId,outerToolCallId:n.continuation.outerToolCallId});return i++,o=!0,{...t,output:a}});return o?{...t,content:s}:t});if(i!==1)throw new CodeModeProtocolError(`Expected one outer code_mode approval result replacement for ${n.approvalId}, found ${i}.`,{approvalId:n.approvalId,outerToolCallId:n.continuation.outerToolCallId,replacements:i});return o}function splitCodeModeOuterResponseMessages(e){let t=e.messages.findIndex(t=>messageContainsToolResult(t,e.outerToolCallId));if(t<0)return{promptMessages:e.messages,responseMessages:[]};let n=t-1,r=n>=0&&messageContainsToolCall(e.messages[n],e.outerToolCallId)?n:t;return{promptMessages:e.messages.slice(0,r),responseMessages:e.messages.slice(r)}}function messageContainsToolCall(e,t){return e?.role!==`assistant`||!Array.isArray(e.content)?!1:e.content.some(e=>typeof e==`object`&&!!e&&`type`in e&&e.type===`tool-call`&&`toolCallId`in e&&e.toolCallId===t)}function messageContainsToolResult(e,t){return e?.role!==`tool`||!Array.isArray(e.content)?!1:e.content.some(e=>e.type===`tool-result`&&`toolCallId`in e&&e.toolCallId===t)}function toolResultOutputContainsApprovalInterrupt(e,t){return readApprovalInterruptValue(e)?.approvalId===t}function readApprovalInterruptValue(e){if(isCodeModeApprovalInterrupt(e))return e;if(isRecord(e)&&(e.type===`json`||e.type===`text`)&&Object.hasOwn(e,`value`))return readApprovalInterruptValue(e.value)}function toModelToolOutput(e){return typeof e==`string`?{type:`text`,value:e}:{type:`json`,value:e===void 0?null:e}}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{clearPendingCodeModeApproval,getPendingCodeModeApproval,replaceCodeModeApprovalInterruptResult,setPendingCodeModeApproval,splitCodeModeOuterResponseMessages};
@@ -1 +1 @@
1
- import{createCodeModeTool}from"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/code-mode-tool.js";import"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/index.js";import"ai";import{markCodeModeToolExecutionOptions}from"#runtime/framework-tools/code-mode-connection-auth.js";import{resolveConnectionToolsFromState}from"#runtime/framework-tools/connection-tools.js";import{CODE_MODE_TOOL_NAME}from"#shared/code-mode.js";import{buildToolSet}from"#harness/tools.js";function isCodeModeEnabled(e=process.env){return e.CODE_MODE===`1`}function createAshCodeModeOptions(e={}){let t={approval:{mode:`interrupt`}};return e.lifecycle!==void 0&&(t.lifecycle=e.lifecycle),t}function applyCodeModeToToolSet(t){let n={},i={};for(let[e,r]of Object.entries(t.tools)){if(isDirectTool(r,t.harnessTools.get(e))){i[e]=r;continue}n[e]=wrapHostToolForCodeMode(r)}return Object.keys(n).length>0&&(i[CODE_MODE_TOOL_NAME]=createCodeModeTool(n,createAshCodeModeOptions({lifecycle:t.lifecycle}))),{hostTools:n,modelTools:i}}async function buildCodeModeHostTools(e){let t=buildToolSet({approvedTools:e.approvedTools,capabilities:e.capabilities,tools:e.tools});if(e.registry!==void 0&&e.discovered!==void 0){let r=await resolveConnectionToolsFromState(e.registry,e.discovered,{approvedTools:e.approvedTools,authMode:`code-mode`,codeModeMetadataOnlyConnectionNames:e.codeModeMetadataOnlyConnectionNames,existingToolNames:new Set(Object.keys(t))});Object.assign(t,r)}return applyCodeModeToToolSet({harnessTools:e.tools,tools:t}).hostTools}function isDirectTool(e,t){return e.execute===void 0||t?.runtimeAction!==void 0}function wrapHostToolForCodeMode(e){let n=e.execute,r=e.toModelOutput;return n===void 0?e:{...e,execute:async(e,i)=>{let a=await resolveExecuteOutput(n(e,markCodeModeToolExecutionOptions(i)));if(r===void 0)return a;let o=await r({output:a});return isModelOutput(o)?o.value:o}}}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`}function isModelOutput(e){if(typeof e!=`object`||!e)return!1;let t=e;return(t.type===`json`||t.type===`text`)&&Object.hasOwn(t,`value`)}export{applyCodeModeToToolSet,buildCodeModeHostTools,createAshCodeModeOptions,isCodeModeEnabled};
1
+ import{createCodeModeTool}from"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/code-mode-tool.js";import"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/index.js";import"ai";import{markCodeModeToolExecutionOptions}from"#runtime/framework-tools/code-mode-connection-auth.js";import{resolveConnectionToolsFromState}from"#runtime/framework-tools/connection-tools.js";import{CODE_MODE_TOOL_NAME}from"#shared/code-mode.js";import{buildToolSet}from"#harness/tools.js";function isCodeModeEnabled(e=process.env){return e.CODE_MODE===`1`}function createAshCodeModeOptions(e={}){let t={approval:{mode:`interrupt`}};return e.lifecycle!==void 0&&(t.lifecycle=e.lifecycle),t}function applyCodeModeToToolSet(t){let n={},i={};for(let[e,r]of Object.entries(t.tools)){if(isDirectTool(r,t.harnessTools.get(e))){i[e]=r;continue}n[e]=wrapHostToolForCodeMode(r)}return Object.keys(n).length>0&&(i[CODE_MODE_TOOL_NAME]=createCodeModeTool(n,createAshCodeModeOptions({lifecycle:t.lifecycle}))),{hostTools:n,modelTools:i}}async function buildCodeModeHostTools(e){let t=buildToolSet({approvedTools:e.approvedTools,capabilities:e.capabilities,tools:e.tools});if(e.registry!==void 0&&e.discovered!==void 0){let r=await resolveConnectionToolsFromState(e.registry,e.discovered,{approvedTools:e.approvedTools,authMode:`code-mode`,codeModeMetadataOnlyConnectionNames:e.codeModeMetadataOnlyConnectionNames,existingToolNames:new Set(Object.keys(t))});Object.assign(t,r)}return applyCodeModeToToolSet({harnessTools:e.tools,tools:t}).hostTools}function isDirectTool(e,t){return e.execute===void 0||t?.runtimeAction!==void 0}function wrapHostToolForCodeMode(e){let n=e.execute,r=e.toModelOutput;return n===void 0?e:{...e,execute:async(e,i)=>{let a=await resolveExecuteOutput(n(e,markCodeModeToolExecutionOptions(i)));if(r===void 0)return a;let o=await r({output:a});return isModelOutput(o)?o.value:o}}}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`}function isModelOutput(e){if(typeof e!=`object`||!e)return!1;let t=e;return(t.type===`json`||t.type===`text`)&&Object.hasOwn(t,`value`)}export{applyCodeModeToToolSet,buildCodeModeHostTools,createAshCodeModeOptions,isCodeModeEnabled};
@@ -1 +1 @@
1
- import{continueCodeModeApproval,getCodeModeApprovalResponse,isCodeModeApprovalInterrupt,toCodeModeApprovalMessages}from"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/approval-continuation.js";import{continueCodeModeInterrupt,getCodeModeInterrupt,replaceCodeModeInterruptResult,unwrapCodeModeResult}from"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/interrupt-continuation.js";import"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.9_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/index.js";import{createErrorId,createLogger,formatError,logError,recordErrorOnSpan}from"#internal/logging.js";import{createAuthorizationRequiredEvent,createCompactionCompletedEvent,createCompactionRequestedEvent,createInputRequestedEvent}from"#protocol/message.js";import{toErrorMessage}from"#shared/errors.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import"#shared/json.js";import{contextStorage}from"#context/container.js";import{advanceStep,emitFailedStep,emitRecoverableFailedTurn,emitStreamContent,emitTurnEpilogue,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{ConnectionRegistryKey,DiscoveredConnectionToolsKey}from"#runtime/framework-tools/connection-search.js";import{ToolLoopAgent,isStepCount}from"ai";import{createRuntimeActionRequestFromToolCall,resolvePendingRuntimeActions,setPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{resolveAssistantStepText}from"#harness/messages.js";import{consumeDeferredStepInput,getApprovedTools,hasDeferredStepInput,hasStepInput,resolvePendingInput,setPendingInputBatch}from"#harness/input-requests.js";import{getHookUrl,isAuthorizationSignal,setPendingAuthorization}from"#harness/authorization.js";import{isCodeModeConnectionAuthInterrupt}from"#runtime/framework-tools/code-mode-connection-auth.js";import{resolveConnectionToolsFromState}from"#runtime/framework-tools/connection-tools.js";import{CODE_MODE_TOOL_NAME}from"#shared/code-mode.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,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{resolveConnectionPrincipal}from"#runtime/connections/principal.js";import{supportsInteractiveAuthorization}from"#runtime/connections/types.js";import{hydrateSandboxAttachments,stageAttachmentsToSandbox}from"#harness/attachment-staging.js";import{applyCodeModeToToolSet,buildCodeModeHostTools,createAshCodeModeOptions,isCodeModeEnabled}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{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{ensureOtelIntegration}from"#harness/otel-integration.js";import{buildStepHooks,emitStepActions,isInvalidToolCall}from"#harness/step-hooks.js";import{pruneToolResults}from"#harness/tool-result-pruning.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){if(e!==void 0)return{functionId:e.functionId??t,isEnabled:!0,recordInputs:e.recordInputs??!0,recordOutputs:e.recordOutputs??!0}}function buildTelemetryRuntimeContext(e,t){if(e!==void 0)return{...e.metadata,"ash.continuation_token":t.continuationToken,"ash.environment":environment,"ash.session.id":t.sessionId,"ash.version":ashVersion}}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(e){let t=e.emit,n=getInstrumentationConfig();n!==void 0&&ensureOtelIntegration();let r=n===void 0?void 0:trace.getTracer(`ash`),i=e.runtimeIdentity?.agentName;async function runStep(e,t){let a;if(r&&hasStepInput(t)){let t=n?.functionId??i,o={"ash.version":ashVersion,"ash.environment":environment,"ash.session.id":e.sessionId,"ash.continuation_token":e.continuationToken};t&&(o[`ai.telemetry.functionId`]=t),a=r.startSpan(`ai.ash.turn`,{attributes:o})}let o=resolveStepOtelContext(r,a,e),executeStep=()=>executeStepBody(e,t,a);try{return o?await context.with(o,executeStep):await executeStep()}finally{a?.end()}}async function executeStepBody(r,a,o){let s=r;o&&(s=setTurnTraceState(s,o.spanContext()));let l=getHarnessEmissionState(s.state),u=consumeDeferredStepInput({input:a,session:s});s=u.session;let p=await resolvePendingRuntimeActions({emit:t,session:s,stepInput:u.input});if(p.outcome===`unresolved`)return{next:null,session:p.session};s=p.session;let m=resolvePendingInput({history:p.messages,resolveApprovalKey:resolveApprovalKeyFromTools(e.tools),session:s,stepInput:u.input});if(m.outcome===`unresolved`)return{next:null,session:m.session};t&&hasStepInput(a)&&(l=await emitTurnPreamble(t,a??{},l,e.runtimeIdentity),s=setHarnessEmissionState(s,l),o&&o.setAttribute(`ash.turn.id`,l.turnId)),s=m.session;let h=m.messages,g=await continuePendingCodeModeConnectionAuth({capabilities:e.capabilities,config:e,emit:t,emissionState:l,messages:h,runStep,session:s});if(g!==null)return g;let v=await continuePendingCodeModeApproval({capabilities:e.capabilities,config:e,emit:t,emissionState:l,messages:h,runStep,session:s});if(v!==null)return v;if(u.input?.message!==void 0&&!m.deferredMessage){let e=await stageAttachmentsToSandbox(u.input.message);h.push({content:e,role:`user`})}let y=await e.resolveModel(s.agent.modelReference),x=detectPromptCachePath(y),T=x.kind===`anthropic-direct`?getAnthropicCacheMarker():void 0,A=buildGatewayAttributionHeaders(y,e.runtimeIdentity);({messages:h,session:s}=await maybeCompact({emit:t,emissionState:l,headers:A,messages:h,model:y,onCompaction:e.onCompaction,resolveModel:e.resolveModel,session:s,telemetry:enrichTelemetry(n,i)??void 0}));let j=getApprovedTools(s),M=contextStorage.getStore(),N=M?.get(ConnectionRegistryKey),P=M?.get(DiscoveredConnectionToolsKey),F=await hydrateSandboxAttachments(h),I=u.input?.modelContext,L=[],R=[];for(let e of F)e.role===`system`?L.push(e):R.push(e);if(I!==void 0)for(let e of I)e.role===`system`?L.push(e):R.push(e);let z=R,runOneModelCall=async r=>{let a=isCodeModeEnabled(),o=await buildToolSetWithProviderTools({approvedTools:j,capabilities:e.capabilities,disabledProviderTools:r.disabledProviderTools,modelReference:s.agent.modelReference,tools:e.tools});if(N!==void 0&&P!==void 0){let e=await resolveConnectionToolsFromState(N,P,{approvedTools:j,authMode:a?`code-mode`:`direct`,existingToolNames:new Set(Object.keys(o))});Object.assign(o,e)}let c=a?applyCodeModeToToolSet({harnessTools:e.tools,lifecycle:t===void 0?void 0:createCodeModeLifecycle({emit:t,emissionState:l,tools:e.tools}),tools:o}).modelTools:o,u=T?applyLastToolCacheBreakpoint(c,T):c,f=resolveGatewayPinForStep({cachePath:x,modelReference:s.agent.modelReference,tools:u}),p=r.extraSystemNote?[{role:`system`,content:r.extraSystemNote}]:[],m=s.agent.system?[{role:`system`,content:s.agent.system}]:[],h=L.length>0||p.length>0?[...p,...m,...L]:s.agent.system||void 0,g=buildStepHooks({cachePath:x,emit:t,emissionState:l,emitStepStarted:r.suppressStepStartedEmission!==!0,gatewayPinProvider:f,marker:T,session:s}),_=new ToolLoopAgent({headers:A,instructions:h,model:y,onToolExecutionEnd:logToolExecutionError,onError(e){logError(log,`tool-loop stream error`,e.error)},onStepFinish:g.onStepFinish,prepareStep:g.prepareStep,runtimeContext:buildTelemetryRuntimeContext(n,s),stopWhen:isStepCount(1),telemetry:enrichTelemetry(n,i),tools:u});return runModelCallWithRetries(async()=>{if(t){let n=await _.stream({messages:z}),{inlineActionResultCallIds:r,inlineToolResultParts:i}=await emitStreamContent(t,l,n.fullStream),a=await g.stepResult;return await emitStepActions(t,l,a,{excludedActionToolNames:new Set([ASK_QUESTION_TOOL_NAME,CODE_MODE_TOOL_NAME]),inlineActionResultCallIds:r,tools:e.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 _.generate({messages:z}),await g.stepResult},{sessionId:s.sessionId,turnId:l.turnId})},B;try{B=await runOneModelCall({})}catch(e){let n=await attemptUnsupportedProviderToolRecovery({error:e,runOneModelCall,sessionId:s.sessionId,turnId:l.turnId});if(n.outcome===`recovered`)B=n.result;else{let e=n.error;if(o&&recordErrorOnSpan(o,e),!t)throw e;let r=classifyModelCallError(e),i=createErrorId(),a=r===`terminal`?summarizeKnownModelCallConfigError(e):null,u=a===null?summarizeKnownModelCallRequestError(e):null,d=a?.message??u?.message??toErrorMessage(e),p=extractModelCallErrorDetails(e),m=buildModelCallFailureDetails({configSummary:a,error:e,errorId:i,modelCallDetails:p,requestSummary:u}),h=buildModelCallFailureLogFields({error:e,errorId:i,modelCallDetails:p,requestSummary:u,sessionId:s.sessionId,turnId:l.turnId});return r===`terminal`?(a===null?log.error(u?.message??`model call failed terminally`,h):log.error(`${a.name}: ${a.message}`,{errorId:i,sessionId:s.sessionId,turnId:l.turnId}),await emitFailedStep(t,l,{code:`MODEL_CALL_FAILED`,details:m,message:d,sessionId:s.sessionId}),{next:{done:!0,output:``},session:s}):(log.error(u?.message??`model call failed — parking session for retry by the user`,h),l=await emitRecoverableFailedTurn(t,l,{code:`MODEL_CALL_FAILED`,details:m,message:d}),{next:null,session:setHarnessEmissionState(s,l)})}}return handleStepResult({config:e,emit:t,emissionState:l,promptMessages:h,result:B,runStep,session:s})}return runStep}function buildModelCallFailureDetails(e){let{configSummary:t,error:n,errorId:r,modelCallDetails:i,requestSummary:a}=e;return t===null?a===null?{...formatError(n,r),...i}:{errorId:r,message:toErrorMessage(n),name:a.name,...i}:{errorId:r,message:t.message,name:t.name,...i}}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:r,promptMessages:i,result:o,runStep:s}=e,{emissionState:c,session:l}=e,u=o.response.messages,d=resolveAssistantStepText(u,o.text),f={...l,compaction:createNextCompactionConfig(l.compaction,i,o)},m=getCodeModeInterrupt(o);if(m!==void 0){if(isCodeModeConnectionAuthInterrupt(m))return parkOnCodeModeConnectionAuth({baseSession:f,config:t,emit:r,emissionState:c,interrupt:m,promptMessages:i,responseMessages:u});if(isCodeModeApprovalInterrupt(m))return parkOnCodeModeApproval({baseSession:f,config:t,emit:r,emissionState:c,interrupt:m,promptMessages:i,responseMessages:u})}let h=extractToolApprovalInputRequests({content:o.content??[]}),_=new Set(h.map(e=>e.action.callId)),v=extractQuestionInputRequests({toolCalls:o.toolCalls,excludedCallIds:_}),y=[...h,...v],b=(o.toolCalls??[]).filter(e=>!isInvalidToolCall(e)).filter(e=>t.tools.get(e.toolName)?.runtimeAction!==void 0).map(e=>createRuntimeActionRequestFromToolCall({toolCall:e,tools:t.tools}));if(b.length>0)return{next:null,session:setPendingRuntimeActionBatch({actions:b,event:{sequence:c.sequence,stepIndex:c.stepIndex,turnId:c.turnId},responseMessages:u,session:{...f,history:[...i]}})};if(y.length>0){let e=setPendingInputBatch({requests:y,responseMessages:u,session:{...f,history:[...i]}});return r&&(await r(createInputRequestedEvent({requests:y,sequence:c.sequence,stepIndex:c.stepIndex,turnId:c.turnId})),t.mode===`conversation`&&(c=await emitTurnEpilogue(r,c,t.mode),e=setHarnessEmissionState(e,c))),{next:null,session:e}}let S=(o.toolResults??[]).find(e=>isAuthorizationSignal(e.output));if(S&&isAuthorizationSignal(S.output)){let{challenges:e}=S.output;if(r)for(let t of e)await r(createAuthorizationRequiredEvent({authorization:t.challenge,name:t.name,description:t.challenge.instructions??`Authorization required for ${t.name}`,webhookUrl:t.hookUrl,sequence:c.sequence,stepIndex:c.stepIndex,turnId:c.turnId}));return{next:null,session:setHarnessEmissionState({...f,history:[...i],state:setPendingAuthorization(f.state,{challenges:e})},c)}}let C=pruneToolResults(i,t.retentionPolicies),w=C!==i,E=f.compaction;w&&E.lastKnownInputTokens!==void 0&&(E={recentWindowSize:E.recentWindowSize,threshold:E.threshold});let D=[...C,...u],O={...f,compaction:E,history:D},k=u.at(-1)?.role===`tool`||hasDeferredStepInput(O);return r&&(c=k?advanceStep(c):await emitTurnEpilogue(r,c,t.mode),O=setHarnessEmissionState(O,c)),k?{next:s,session:O}:{next:t.mode===`task`?{done:!0,output:d??``}:null,session:O}}async function continuePendingCodeModeApproval(r){let i=getPendingCodeModeApproval(r.session.state);if(i===void 0)return null;let a=getCodeModeApprovalResponse([...r.messages],i.interrupt);if(a===void 0)return{next:null,session:r.session};let o=contextStorage.getStore(),c=await buildCodeModeHostTools({approvedTools:getApprovedTools(r.session),capabilities:r.capabilities,discovered:o?.get(DiscoveredConnectionToolsKey),registry:o?.get(ConnectionRegistryKey),tools:r.config.tools}),l;try{l=await continueCodeModeApproval({approvalResponse:a,interrupt:i.interrupt,options:createAshCodeModeOptions({lifecycle:r.emit===void 0?void 0:createCodeModeLifecycle({emit:r.emit,emissionState:r.emissionState,skipReplayed:!0,tools:r.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 u=unwrapCodeModeResult(l),f=u.status===`interrupted`?u.interrupt:u.output,p=replaceCodeModeApprovalInterruptResult([...r.session.history,...i.responseMessages],i.interrupt,f),m=clearPendingCodeModeApproval({...r.session,history:p});if(u.status===`interrupted`){if(isCodeModeConnectionAuthInterrupt(u.interrupt)){let e=r.session.history.length,t=p.slice(0,e),n=p.slice(e);return m={...m,history:t},parkOnCodeModeConnectionAuth({baseSession:m,config:r.config,emit:r.emit,emissionState:r.emissionState,interrupt:u.interrupt,promptMessages:t,responseMessages:n})}if(isCodeModeApprovalInterrupt(u.interrupt)){let e=r.session.history.length,t=p.slice(0,e),n=p.slice(e);return m={...m,history:t},parkOnCodeModeApproval({baseSession:m,config:r.config,emit:r.emit,emissionState:r.emissionState,interrupt:u.interrupt,promptMessages:t,responseMessages:n})}}return{next:r.runStep,session:m}}async function parkOnCodeModeConnectionAuth(e){let{connectionName:t}=e.interrupt.payload,n=(contextStorage.getStore()?.get(ConnectionRegistryKey))?.getConnections().find(e=>e.connectionName===t),r=n?.authorization&&supportsInteractiveAuthorization(n.authorization)?n.authorization:void 0,i=[];if(r){let e=getHookUrl(t);if(e){let a=resolveConnectionPrincipal(t,r),{challenge:o,state:s}=await r.startAuthorization({callbackUrl:e,connection:{url:n?.url??``},principal:a});i.push({name:t,challenge:o,hookUrl:e,state:s})}}if(e.emit)for(let t of i)await e.emit(createAuthorizationRequiredEvent({authorization:t.challenge,name:t.name,description:t.challenge.instructions??`Authorization required for ${t.name}`,webhookUrl:t.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:i})}})}}async function continuePendingCodeModeConnectionAuth(e){let t=getPendingCodeModeConnectionAuth(e.session.state);if(t===void 0)return null;let r=contextStorage.getStore(),a=new Set,{connectionName:c}=t.interrupt.payload;a.add(c);let l=await buildCodeModeHostTools({approvedTools:getApprovedTools(e.session),capabilities:e.capabilities,codeModeMetadataOnlyConnectionNames:a,discovered:r?.get(DiscoveredConnectionToolsKey),registry:r?.get(ConnectionRegistryKey),tools:e.config.tools}),u=e.emit===void 0?void 0:createCodeModeLifecycle({emit:e.emit,emissionState:e.emissionState,skipReplayed:!0,tools:e.config.tools}),f;try{f=await continueCodeModeInterrupt({interrupt:t.interrupt,resolution:{status:`authorized`},tools:l,options:createAshCodeModeOptions({lifecycle:u})})}catch(e){logError(log,`code-mode interrupt continuation failed`,e),f={error:`code_mode_continuation_failed`,message:toErrorMessage(e),retryable:!1}}let p=unwrapCodeModeResult(f),m=p.status===`interrupted`?p.interrupt:p.output,h=replaceCodeModeInterruptResult([...e.session.history,...t.responseMessages],t.interrupt.pendingContinuation,m),g=clearPendingCodeModeConnectionAuth({...e.session,history:h});if(p.status===`interrupted`){if(isCodeModeConnectionAuthInterrupt(p.interrupt)){let t=e.session.history.length,n=h.slice(0,t),r=h.slice(t);return g={...g,history:n},parkOnCodeModeConnectionAuth({baseSession:g,config:e.config,emit:e.emit,emissionState:e.emissionState,interrupt:p.interrupt,promptMessages:n,responseMessages:r})}if(isCodeModeApprovalInterrupt(p.interrupt)){let t=e.session.history.length,n=h.slice(0,t),r=h.slice(t);return g={...g,history:n},parkOnCodeModeApproval({baseSession:g,config:e.config,emit:e.emit,emissionState:e.emissionState,interrupt:p.interrupt,promptMessages:n,responseMessages:r})}}return{next:e.runStep,session:g}}async function parkOnCodeModeApproval(e){let t=toCodeModeApprovalMessages(e.interrupt),n=extractToolApprovalInputRequests({content:extractAssistantContent(t)}),i=setPendingInputBatch({requests:n,responseMessages:t,session:setPendingCodeModeApproval({interrupt:e.interrupt,responseMessages:e.responseMessages,session:{...e.baseSession,history:[...e.promptMessages]}})});if(e.emit&&(await e.emit(createInputRequestedEvent({requests:n,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{continueCodeModeApproval,getCodeModeApprovalResponse,isCodeModeApprovalInterrupt,toCodeModeApprovalMessages}from"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/approval-continuation.js";import{continueCodeModeInterrupt,getCodeModeInterrupt,replaceCodeModeInterruptResult,unwrapCodeModeResult}from"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/interrupt-continuation.js";import"../node_modules/.pnpm/experimental-ai-sdk-code-mode@1.0.10_ai@7.0.0-canary.154_zod@4.4.3_/node_modules/experimental-ai-sdk-code-mode/dist/index.js";import{createErrorId,createLogger,formatError,logError,recordErrorOnSpan}from"#internal/logging.js";import{createAuthorizationRequiredEvent,createCompactionCompletedEvent,createCompactionRequestedEvent,createInputRequestedEvent}from"#protocol/message.js";import{toErrorMessage}from"#shared/errors.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import"#shared/json.js";import{contextStorage}from"#context/container.js";import{advanceStep,emitFailedStep,emitRecoverableFailedTurn,emitStreamContent,emitTurnEpilogue,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{ConnectionRegistryKey,DiscoveredConnectionToolsKey}from"#runtime/framework-tools/connection-search.js";import{ToolLoopAgent,isStepCount}from"ai";import{createRuntimeActionRequestFromToolCall,resolvePendingRuntimeActions,setPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{resolveAssistantStepText}from"#harness/messages.js";import{consumeDeferredStepInput,getApprovedTools,hasDeferredStepInput,hasStepInput,resolvePendingInput,setPendingInputBatch}from"#harness/input-requests.js";import{getHookUrl,isAuthorizationSignal,setPendingAuthorization}from"#harness/authorization.js";import{isCodeModeConnectionAuthInterrupt}from"#runtime/framework-tools/code-mode-connection-auth.js";import{resolveConnectionToolsFromState}from"#runtime/framework-tools/connection-tools.js";import{CODE_MODE_TOOL_NAME}from"#shared/code-mode.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,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{resolveConnectionPrincipal}from"#runtime/connections/principal.js";import{supportsInteractiveAuthorization}from"#runtime/connections/types.js";import{hydrateSandboxAttachments,stageAttachmentsToSandbox}from"#harness/attachment-staging.js";import{applyCodeModeToToolSet,buildCodeModeHostTools,createAshCodeModeOptions,isCodeModeEnabled}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{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{ensureOtelIntegration}from"#harness/otel-integration.js";import{buildStepHooks,emitStepActions,isInvalidToolCall}from"#harness/step-hooks.js";import{pruneToolResults}from"#harness/tool-result-pruning.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){if(e!==void 0)return{functionId:e.functionId??t,isEnabled:!0,recordInputs:e.recordInputs??!0,recordOutputs:e.recordOutputs??!0}}function buildTelemetryRuntimeContext(e,t){if(e!==void 0)return{...e.metadata,"ash.continuation_token":t.continuationToken,"ash.environment":environment,"ash.session.id":t.sessionId,"ash.version":ashVersion}}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(e){let t=e.emit,n=getInstrumentationConfig();n!==void 0&&ensureOtelIntegration();let r=n===void 0?void 0:trace.getTracer(`ash`),i=e.runtimeIdentity?.agentName;async function runStep(e,t){let a;if(r&&hasStepInput(t)){let t=n?.functionId??i,o={"ash.version":ashVersion,"ash.environment":environment,"ash.session.id":e.sessionId,"ash.continuation_token":e.continuationToken};t&&(o[`ai.telemetry.functionId`]=t),a=r.startSpan(`ai.ash.turn`,{attributes:o})}let o=resolveStepOtelContext(r,a,e),executeStep=()=>executeStepBody(e,t,a);try{return o?await context.with(o,executeStep):await executeStep()}finally{a?.end()}}async function executeStepBody(r,a,o){let s=r;o&&(s=setTurnTraceState(s,o.spanContext()));let l=getHarnessEmissionState(s.state),u=consumeDeferredStepInput({input:a,session:s});s=u.session;let p=await resolvePendingRuntimeActions({emit:t,session:s,stepInput:u.input});if(p.outcome===`unresolved`)return{next:null,session:p.session};s=p.session;let m=resolvePendingInput({history:p.messages,resolveApprovalKey:resolveApprovalKeyFromTools(e.tools),session:s,stepInput:u.input});if(m.outcome===`unresolved`)return{next:null,session:m.session};t&&hasStepInput(a)&&(l=await emitTurnPreamble(t,a??{},l,e.runtimeIdentity),s=setHarnessEmissionState(s,l),o&&o.setAttribute(`ash.turn.id`,l.turnId)),s=m.session;let h=m.messages,g=await continuePendingCodeModeConnectionAuth({capabilities:e.capabilities,config:e,emit:t,emissionState:l,messages:h,runStep,session:s});if(g!==null)return g;let v=await continuePendingCodeModeApproval({capabilities:e.capabilities,config:e,emit:t,emissionState:l,messages:h,runStep,session:s});if(v!==null)return v;if(u.input?.message!==void 0&&!m.deferredMessage){let e=await stageAttachmentsToSandbox(u.input.message);h.push({content:e,role:`user`})}let y=await e.resolveModel(s.agent.modelReference),x=detectPromptCachePath(y),T=x.kind===`anthropic-direct`?getAnthropicCacheMarker():void 0,A=buildGatewayAttributionHeaders(y,e.runtimeIdentity);({messages:h,session:s}=await maybeCompact({emit:t,emissionState:l,headers:A,messages:h,model:y,onCompaction:e.onCompaction,resolveModel:e.resolveModel,session:s,telemetry:enrichTelemetry(n,i)??void 0}));let j=getApprovedTools(s),M=contextStorage.getStore(),N=M?.get(ConnectionRegistryKey),P=M?.get(DiscoveredConnectionToolsKey),F=await hydrateSandboxAttachments(h),I=u.input?.modelContext,L=[],R=[];for(let e of F)e.role===`system`?L.push(e):R.push(e);if(I!==void 0)for(let e of I)e.role===`system`?L.push(e):R.push(e);let z=R,runOneModelCall=async r=>{let a=isCodeModeEnabled(),o=await buildToolSetWithProviderTools({approvedTools:j,capabilities:e.capabilities,disabledProviderTools:r.disabledProviderTools,modelReference:s.agent.modelReference,tools:e.tools});if(N!==void 0&&P!==void 0){let e=await resolveConnectionToolsFromState(N,P,{approvedTools:j,authMode:a?`code-mode`:`direct`,existingToolNames:new Set(Object.keys(o))});Object.assign(o,e)}let c=a?applyCodeModeToToolSet({harnessTools:e.tools,lifecycle:t===void 0?void 0:createCodeModeLifecycle({emit:t,emissionState:l,tools:e.tools}),tools:o}).modelTools:o,u=T?applyLastToolCacheBreakpoint(c,T):c,f=resolveGatewayPinForStep({cachePath:x,modelReference:s.agent.modelReference,tools:u}),p=r.extraSystemNote?[{role:`system`,content:r.extraSystemNote}]:[],m=s.agent.system?[{role:`system`,content:s.agent.system}]:[],h=L.length>0||p.length>0?[...p,...m,...L]:s.agent.system||void 0,g=buildStepHooks({cachePath:x,emit:t,emissionState:l,emitStepStarted:r.suppressStepStartedEmission!==!0,gatewayPinProvider:f,marker:T,session:s}),_=new ToolLoopAgent({headers:A,instructions:h,model:y,onToolExecutionEnd:logToolExecutionError,onError(e){logError(log,`tool-loop stream error`,e.error)},onStepFinish:g.onStepFinish,prepareStep:g.prepareStep,runtimeContext:buildTelemetryRuntimeContext(n,s),stopWhen:isStepCount(1),telemetry:enrichTelemetry(n,i),tools:u});return runModelCallWithRetries(async()=>{if(t){let n=await _.stream({messages:z}),{inlineActionResultCallIds:r,inlineToolResultParts:i}=await emitStreamContent(t,l,n.fullStream),a=await g.stepResult;return await emitStepActions(t,l,a,{excludedActionToolNames:new Set([ASK_QUESTION_TOOL_NAME,CODE_MODE_TOOL_NAME]),inlineActionResultCallIds:r,tools:e.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 _.generate({messages:z}),await g.stepResult},{sessionId:s.sessionId,turnId:l.turnId})},B;try{B=await runOneModelCall({})}catch(e){let n=await attemptUnsupportedProviderToolRecovery({error:e,runOneModelCall,sessionId:s.sessionId,turnId:l.turnId});if(n.outcome===`recovered`)B=n.result;else{let e=n.error;if(o&&recordErrorOnSpan(o,e),!t)throw e;let r=classifyModelCallError(e),i=createErrorId(),a=r===`terminal`?summarizeKnownModelCallConfigError(e):null,u=a===null?summarizeKnownModelCallRequestError(e):null,d=a?.message??u?.message??toErrorMessage(e),p=extractModelCallErrorDetails(e),m=buildModelCallFailureDetails({configSummary:a,error:e,errorId:i,modelCallDetails:p,requestSummary:u}),h=buildModelCallFailureLogFields({error:e,errorId:i,modelCallDetails:p,requestSummary:u,sessionId:s.sessionId,turnId:l.turnId});return r===`terminal`?(a===null?log.error(u?.message??`model call failed terminally`,h):log.error(`${a.name}: ${a.message}`,{errorId:i,sessionId:s.sessionId,turnId:l.turnId}),await emitFailedStep(t,l,{code:`MODEL_CALL_FAILED`,details:m,message:d,sessionId:s.sessionId}),{next:{done:!0,output:``},session:s}):(log.error(u?.message??`model call failed — parking session for retry by the user`,h),l=await emitRecoverableFailedTurn(t,l,{code:`MODEL_CALL_FAILED`,details:m,message:d}),{next:null,session:setHarnessEmissionState(s,l)})}}return handleStepResult({config:e,emit:t,emissionState:l,promptMessages:h,result:B,runStep,session:s})}return runStep}function buildModelCallFailureDetails(e){let{configSummary:t,error:n,errorId:r,modelCallDetails:i,requestSummary:a}=e;return t===null?a===null?{...formatError(n,r),...i}:{errorId:r,message:toErrorMessage(n),name:a.name,...i}:{errorId:r,message:t.message,name:t.name,...i}}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:r,promptMessages:i,result:o,runStep:s}=e,{emissionState:c,session:l}=e,u=o.response.messages,d=resolveAssistantStepText(u,o.text),f={...l,compaction:createNextCompactionConfig(l.compaction,i,o)},m=getCodeModeInterrupt(o);if(m!==void 0){if(isCodeModeConnectionAuthInterrupt(m))return parkOnCodeModeConnectionAuth({baseSession:f,config:t,emit:r,emissionState:c,interrupt:m,promptMessages:i,responseMessages:u});if(isCodeModeApprovalInterrupt(m))return parkOnCodeModeApproval({baseSession:f,config:t,emit:r,emissionState:c,interrupt:m,promptMessages:i,responseMessages:u})}let h=extractToolApprovalInputRequests({content:o.content??[]}),_=new Set(h.map(e=>e.action.callId)),v=extractQuestionInputRequests({toolCalls:o.toolCalls,excludedCallIds:_}),y=[...h,...v],b=(o.toolCalls??[]).filter(e=>!isInvalidToolCall(e)).filter(e=>t.tools.get(e.toolName)?.runtimeAction!==void 0).map(e=>createRuntimeActionRequestFromToolCall({toolCall:e,tools:t.tools}));if(b.length>0)return{next:null,session:setHarnessEmissionState(setPendingRuntimeActionBatch({actions:b,event:{sequence:c.sequence,stepIndex:c.stepIndex,turnId:c.turnId},responseMessages:u,session:{...f,history:[...i]}}),c)};if(y.length>0){let e=setPendingInputBatch({requests:y,responseMessages:u,session:{...f,history:[...i]}});return r&&(await r(createInputRequestedEvent({requests:y,sequence:c.sequence,stepIndex:c.stepIndex,turnId:c.turnId})),t.mode===`conversation`&&(c=await emitTurnEpilogue(r,c,t.mode),e=setHarnessEmissionState(e,c))),{next:null,session:e}}let S=(o.toolResults??[]).find(e=>isAuthorizationSignal(e.output));if(S&&isAuthorizationSignal(S.output)){let{challenges:e}=S.output;if(r)for(let t of e)await r(createAuthorizationRequiredEvent({authorization:t.challenge,name:t.name,description:t.challenge.instructions??`Authorization required for ${t.name}`,webhookUrl:t.hookUrl,sequence:c.sequence,stepIndex:c.stepIndex,turnId:c.turnId}));return{next:null,session:setHarnessEmissionState({...f,history:[...i],state:setPendingAuthorization(f.state,{challenges:e})},c)}}let C=pruneToolResults(i,t.retentionPolicies),w=C!==i,E=f.compaction;w&&E.lastKnownInputTokens!==void 0&&(E={recentWindowSize:E.recentWindowSize,threshold:E.threshold});let D=[...C,...u],O={...f,compaction:E,history:D},k=u.at(-1)?.role===`tool`||hasDeferredStepInput(O);return r&&(c=k?advanceStep(c):await emitTurnEpilogue(r,c,t.mode),O=setHarnessEmissionState(O,c)),k?{next:s,session:O}:{next:t.mode===`task`?{done:!0,output:d??``}:null,session:O}}async function continuePendingCodeModeApproval(r){let i=getPendingCodeModeApproval(r.session.state);if(i===void 0)return null;let a=getCodeModeApprovalResponse([...r.messages],i.interrupt);if(a===void 0)return{next:null,session:r.session};let o=contextStorage.getStore(),c=await buildCodeModeHostTools({approvedTools:getApprovedTools(r.session),capabilities:r.capabilities,discovered:o?.get(DiscoveredConnectionToolsKey),registry:o?.get(ConnectionRegistryKey),tools:r.config.tools}),l;try{l=await continueCodeModeApproval({approvalResponse:a,interrupt:i.interrupt,options:createAshCodeModeOptions({lifecycle:r.emit===void 0?void 0:createCodeModeLifecycle({emit:r.emit,emissionState:r.emissionState,skipReplayed:!0,tools:r.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 u=unwrapCodeModeResult(l),f=u.status===`interrupted`?u.interrupt:u.output,p=replaceCodeModeApprovalInterruptResult([...r.session.history,...i.responseMessages],i.interrupt,f),m=clearPendingCodeModeApproval({...r.session,history:p});if(u.status===`interrupted`){if(isCodeModeConnectionAuthInterrupt(u.interrupt)){let e=r.session.history.length,t=p.slice(0,e),n=p.slice(e);return m={...m,history:t},parkOnCodeModeConnectionAuth({baseSession:m,config:r.config,emit:r.emit,emissionState:r.emissionState,interrupt:u.interrupt,promptMessages:t,responseMessages:n})}if(isCodeModeApprovalInterrupt(u.interrupt)){let e=r.session.history.length,t=p.slice(0,e),n=p.slice(e);return m={...m,history:t},parkOnCodeModeApproval({baseSession:m,config:r.config,emit:r.emit,emissionState:r.emissionState,interrupt:u.interrupt,promptMessages:t,responseMessages:n})}}return{next:r.runStep,session:m}}async function parkOnCodeModeConnectionAuth(e){let{connectionName:t}=e.interrupt.payload,n=(contextStorage.getStore()?.get(ConnectionRegistryKey))?.getConnections().find(e=>e.connectionName===t),r=n?.authorization&&supportsInteractiveAuthorization(n.authorization)?n.authorization:void 0,i=[];if(r){let e=getHookUrl(t);if(e){let a=resolveConnectionPrincipal(t,r),{challenge:o,state:s}=await r.startAuthorization({callbackUrl:e,connection:{url:n?.url??``},principal:a});i.push({name:t,challenge:o,hookUrl:e,state:s})}}if(e.emit)for(let t of i)await e.emit(createAuthorizationRequiredEvent({authorization:t.challenge,name:t.name,description:t.challenge.instructions??`Authorization required for ${t.name}`,webhookUrl:t.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:i})}})}}async function continuePendingCodeModeConnectionAuth(e){let t=getPendingCodeModeConnectionAuth(e.session.state);if(t===void 0)return null;let r=contextStorage.getStore(),a=new Set,{connectionName:c}=t.interrupt.payload;a.add(c);let l=await buildCodeModeHostTools({approvedTools:getApprovedTools(e.session),capabilities:e.capabilities,codeModeMetadataOnlyConnectionNames:a,discovered:r?.get(DiscoveredConnectionToolsKey),registry:r?.get(ConnectionRegistryKey),tools:e.config.tools}),u=e.emit===void 0?void 0:createCodeModeLifecycle({emit:e.emit,emissionState:e.emissionState,skipReplayed:!0,tools:e.config.tools}),f;try{f=await continueCodeModeInterrupt({interrupt:t.interrupt,resolution:{status:`authorized`},tools:l,options:createAshCodeModeOptions({lifecycle:u})})}catch(e){logError(log,`code-mode interrupt continuation failed`,e),f={error:`code_mode_continuation_failed`,message:toErrorMessage(e),retryable:!1}}let p=unwrapCodeModeResult(f),m=p.status===`interrupted`?p.interrupt:p.output,h=replaceCodeModeInterruptResult([...e.session.history,...t.responseMessages],t.interrupt.pendingContinuation,m),g=clearPendingCodeModeConnectionAuth({...e.session,history:h});if(p.status===`interrupted`){if(isCodeModeConnectionAuthInterrupt(p.interrupt)){let t=e.session.history.length,n=h.slice(0,t),r=h.slice(t);return g={...g,history:n},parkOnCodeModeConnectionAuth({baseSession:g,config:e.config,emit:e.emit,emissionState:e.emissionState,interrupt:p.interrupt,promptMessages:n,responseMessages:r})}if(isCodeModeApprovalInterrupt(p.interrupt)){let t=e.session.history.length,n=h.slice(0,t),r=h.slice(t);return g={...g,history:n},parkOnCodeModeApproval({baseSession:g,config:e.config,emit:e.emit,emissionState:e.emissionState,interrupt:p.interrupt,promptMessages:n,responseMessages:r})}}return{next:e.runStep,session:g}}async function parkOnCodeModeApproval(e){let t=toCodeModeApprovalMessages(e.interrupt),n=extractToolApprovalInputRequests({content:extractAssistantContent(t)}),i=setPendingInputBatch({requests:n,responseMessages:t,session:setPendingCodeModeApproval({interrupt:e.interrupt,responseMessages:e.responseMessages,session:{...e.baseSession,history:[...e.promptMessages]}})});if(e.emit&&(await e.emit(createInputRequestedEvent({requests:n,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 +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.35.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.36.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};