eve 0.74.0 → 0.75.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/src/channel/auth/result.d.ts +4 -0
  3. package/dist/src/channel/auth/result.js +1 -0
  4. package/dist/src/channel/types.d.ts +14 -2
  5. package/dist/src/chunks/{use-eve-agent-mP0M7SrL.js → use-eve-agent-B2Kne9z6.js} +7 -2
  6. package/dist/src/chunks/{use-eve-agent-DOOXadF0.js → use-eve-agent-DK_T88EP.js} +7 -2
  7. package/dist/src/cli/commands/deploy.js +1 -1
  8. package/dist/src/cli/commands/integration-connect.d.ts +2 -0
  9. package/dist/src/cli/commands/integration-connect.js +1 -1
  10. package/dist/src/cli/commands/integration-setup.js +1 -1
  11. package/dist/src/cli/commands/link.d.ts +2 -1
  12. package/dist/src/cli/commands/link.js +1 -1
  13. package/dist/src/cli/commands/registry-declared-setups.d.ts +19 -0
  14. package/dist/src/cli/commands/registry-declared-setups.js +1 -1
  15. package/dist/src/cli/commands/registry-recovery.d.ts +3 -1
  16. package/dist/src/cli/commands/registry-recovery.js +1 -1
  17. package/dist/src/cli/commands/registry.d.ts +12 -4
  18. package/dist/src/cli/commands/registry.js +1 -1
  19. package/dist/src/cli/commands/vercel-non-interactive.d.ts +6 -4
  20. package/dist/src/cli/commands/vercel-non-interactive.js +1 -1
  21. package/dist/src/cli/dev/tui/registry-result-message.js +1 -1
  22. package/dist/src/cli/dev/tui/setup-commands.d.ts +2 -0
  23. package/dist/src/cli/dev/tui/setup-commands.js +2 -2
  24. package/dist/src/client/index.d.ts +1 -0
  25. package/dist/src/client/session.d.ts +1 -1
  26. package/dist/src/client/session.js +1 -1
  27. package/dist/src/client/sessions.d.ts +1 -1
  28. package/dist/src/client/types.d.ts +6 -0
  29. package/dist/src/compiled/.vendor-stamp.json +8 -8
  30. package/dist/src/compiled/@eve/catalog/index.js +1 -1
  31. package/dist/src/compiled/@workflow/core/global.d.ts +10 -0
  32. package/dist/src/compiled/@workflow/core/index.js +1 -1
  33. package/dist/src/compiled/@workflow/core/private.d.ts +11 -0
  34. package/dist/src/compiled/@workflow/core/private.js +1 -1
  35. package/dist/src/compiled/@workflow/core/runtime/constants.d.ts +36 -8
  36. package/dist/src/compiled/@workflow/core/runtime/helpers.js +1 -1
  37. package/dist/src/compiled/@workflow/core/runtime/lifecycle-hooks.d.ts +10 -6
  38. package/dist/src/compiled/@workflow/core/runtime/out-of-band-observation.d.ts +159 -0
  39. package/dist/src/compiled/@workflow/core/runtime/vm-mode.d.ts +28 -4
  40. package/dist/src/compiled/@workflow/core/runtime.js +4 -4
  41. package/dist/src/compiled/@workflow/core/serialization.js +1 -1
  42. package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
  43. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  44. package/dist/src/compiled/@workflow/world-local/index.js +5 -5
  45. package/dist/src/compiled/@workflow/world-vercel/index.js +4 -4
  46. package/dist/src/compiled/_chunks/workflow/{attribute-changes-CSqvJx6j.js → attribute-changes-BW-kbMMn.js} +1 -1
  47. package/dist/src/compiled/_chunks/workflow/dist-CyBgVS7g.js +1 -0
  48. package/dist/src/compiled/_chunks/workflow/{helpers-BXCuoPUb.js → helpers-DlLD3ov_.js} +1 -1
  49. package/dist/src/compiled/_chunks/workflow/private-tQUuwBoQ.js +1 -0
  50. package/dist/src/compiled/_chunks/workflow/{resume-hook-CvENCrxc.js → resume-hook-DMsV_b4n.js} +1 -1
  51. package/dist/src/compiled/_chunks/workflow/{run-8pLWuR2U.js → run-DzdAqdb1.js} +1 -1
  52. package/dist/src/compiled/_chunks/workflow/{serialization-vDozzDhh.js → serialization-DPdYS_w2.js} +2 -2
  53. package/dist/src/compiled/_chunks/workflow/sleep-BY6leHh8.js +1 -0
  54. package/dist/src/compiled/_chunks/workflow/{token-BKeK6DmC.js → token-D5ugC3PI.js} +1 -1
  55. package/dist/src/compiled/_chunks/workflow/{token-util-CddTZ_ef.js → token-util-Bla5Z0G9.js} +1 -1
  56. package/dist/src/compiled/_chunks/workflow/undici-D-ILjOKD.js +95 -0
  57. package/dist/src/compiled/_chunks/workflow/{wait-until-A344L2AG.js → wait-until-xbRRDuUf.js} +1 -1
  58. package/dist/src/compiler/extension-compatibility.d.ts +18 -12
  59. package/dist/src/compiler/extension-compatibility.js +1 -1
  60. package/dist/src/context/dynamic-connection-lifecycle.d.ts +6 -0
  61. package/dist/src/context/dynamic-connection-lifecycle.js +1 -1
  62. package/dist/src/context/keys.d.ts +4 -1
  63. package/dist/src/context/keys.js +1 -1
  64. package/dist/src/context/providers/sandbox.js +1 -1
  65. package/dist/src/context/providers/tool-stubs-key.d.ts +8 -0
  66. package/dist/src/context/providers/tool-stubs-key.js +1 -0
  67. package/dist/src/context/providers/tool-stubs.d.ts +10 -0
  68. package/dist/src/context/providers/tool-stubs.js +1 -0
  69. package/dist/src/context/run-step.js +1 -1
  70. package/dist/src/evals/index.d.ts +1 -0
  71. package/dist/src/evals/runner/execute-task.js +1 -1
  72. package/dist/src/evals/session-manager.d.ts +2 -0
  73. package/dist/src/evals/session-manager.js +1 -1
  74. package/dist/src/eve-channel/create-request.d.ts +2 -0
  75. package/dist/src/eve-channel/index.js +1 -1
  76. package/dist/src/eve-channel/request.js +1 -1
  77. package/dist/src/execution/agent-sessions/context.d.ts +2 -0
  78. package/dist/src/execution/agent-sessions/context.js +1 -1
  79. package/dist/src/execution/agent-sessions/steps.js +1 -1
  80. package/dist/src/execution/cancelled-model-call-batch.js +1 -1
  81. package/dist/src/execution/dynamic-connection-recovery.d.ts +14 -0
  82. package/dist/src/execution/dynamic-connection-recovery.js +1 -0
  83. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  84. package/dist/src/execution/forward-session-input.js +1 -1
  85. package/dist/src/execution/legacy-session/authorization.js +1 -1
  86. package/dist/src/execution/legacy-session/completion-step.js +1 -1
  87. package/dist/src/execution/legacy-session/inbox.js +1 -1
  88. package/dist/src/execution/legacy-session/interrupt-step.js +1 -1
  89. package/dist/src/execution/ndjson-stream.d.ts +6 -6
  90. package/dist/src/execution/ndjson-stream.js +3 -3
  91. package/dist/src/execution/proxied-deliver-step.js +1 -1
  92. package/dist/src/execution/runtime-context.js +1 -1
  93. package/dist/src/execution/sandbox/bindings/docker.js +1 -1
  94. package/dist/src/execution/sandbox/bindings/just-bash-runtime.js +1 -1
  95. package/dist/src/execution/sandbox/bindings/just-bash.js +1 -1
  96. package/dist/src/execution/sandbox/bindings/microsandbox-lifecycle.js +1 -1
  97. package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
  98. package/dist/src/execution/sandbox/ensure.d.ts +3 -1
  99. package/dist/src/execution/sandbox/ensure.js +1 -1
  100. package/dist/src/execution/session/active-turn.js +1 -1
  101. package/dist/src/execution/session/admission.js +1 -1
  102. package/dist/src/execution/session/checkpoint-migrations.js +1 -1
  103. package/dist/src/execution/session/end-sandbox-step.d.ts +12 -0
  104. package/dist/src/execution/session/end-sandbox-step.js +1 -0
  105. package/dist/src/execution/session/finalization.js +1 -1
  106. package/dist/src/execution/session/handoff-steps.js +1 -1
  107. package/dist/src/execution/session/handoff.d.ts +1 -1
  108. package/dist/src/execution/session/handoff.js +1 -1
  109. package/dist/src/execution/session/program.js +1 -1
  110. package/dist/src/execution/session/timeout-steps.js +1 -1
  111. package/dist/src/execution/session/turn-step.js +1 -1
  112. package/dist/src/execution/session-inbox/inbox.d.ts +6 -1
  113. package/dist/src/execution/session-inbox/inbox.js +1 -1
  114. package/dist/src/execution/session-inbox/release-step.js +1 -1
  115. package/dist/src/execution/session-inbox/resume.d.ts +2 -1
  116. package/dist/src/execution/session-inbox/resume.js +1 -1
  117. package/dist/src/execution/session-workflow-tool-run.js +1 -1
  118. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  119. package/dist/src/execution/tasks/model-step.js +1 -1
  120. package/dist/src/execution/tasks/steps.js +1 -1
  121. package/dist/src/execution/tasks/table.d.ts +7 -1
  122. package/dist/src/execution/tasks/table.js +1 -1
  123. package/dist/src/execution/tool-stubs/playback.d.ts +11 -0
  124. package/dist/src/execution/tool-stubs/playback.js +1 -0
  125. package/dist/src/execution/tool-stubs/steps.d.ts +18 -0
  126. package/dist/src/execution/tool-stubs/steps.js +1 -0
  127. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  128. package/dist/src/execution/tools/connection-tools.d.ts +0 -6
  129. package/dist/src/execution/tools/connection-tools.js +2 -2
  130. package/dist/src/execution/tools/workflow/authorization-completion.js +1 -1
  131. package/dist/src/execution/tools/workflow/body.js +1 -1
  132. package/dist/src/execution/tools/workflow/serve.js +1 -1
  133. package/dist/src/execution/tools/workflow/withdraw-step.js +1 -1
  134. package/dist/src/execution/workflow-runtime.js +1 -1
  135. package/dist/src/execution/workflow-webhook-route.js +1 -1
  136. package/dist/src/harness/compaction/engine.d.ts +8 -19
  137. package/dist/src/harness/compaction/engine.js +1 -1
  138. package/dist/src/harness/compaction/step.d.ts +7 -1
  139. package/dist/src/harness/compaction/step.js +1 -1
  140. package/dist/src/harness/coordination.js +1 -1
  141. package/dist/src/harness/emission.js +1 -1
  142. package/dist/src/harness/hitl/approved-calls.d.ts +2 -0
  143. package/dist/src/harness/hitl/approved-calls.js +1 -1
  144. package/dist/src/harness/hitl/index.d.ts +9 -1
  145. package/dist/src/harness/hitl/index.js +1 -1
  146. package/dist/src/harness/hitl/intake.js +1 -1
  147. package/dist/src/harness/model-call/call.d.ts +2 -3
  148. package/dist/src/harness/model-call/call.js +1 -1
  149. package/dist/src/harness/model-call/model.d.ts +4 -5
  150. package/dist/src/harness/model-call/model.js +1 -1
  151. package/dist/src/harness/model-call/request.d.ts +1 -2
  152. package/dist/src/harness/model-call/request.js +1 -1
  153. package/dist/src/harness/model-call/retry.d.ts +1 -1
  154. package/dist/src/harness/model-call/retry.js +1 -1
  155. package/dist/src/harness/model-call/run.js +1 -1
  156. package/dist/src/harness/model-call/tools.d.ts +3 -4
  157. package/dist/src/harness/model-call/tools.js +1 -1
  158. package/dist/src/harness/model-call/usage.js +1 -1
  159. package/dist/src/harness/model-profile.d.ts +23 -0
  160. package/dist/src/harness/model-profile.js +1 -0
  161. package/dist/src/harness/prompt-cache.d.ts +5 -53
  162. package/dist/src/harness/prompt-cache.js +1 -1
  163. package/dist/src/harness/provider-safety.d.ts +3 -5
  164. package/dist/src/harness/provider-safety.js +1 -1
  165. package/dist/src/harness/provider-tools.d.ts +5 -13
  166. package/dist/src/harness/provider-tools.js +1 -1
  167. package/dist/src/harness/proxy-input-requests.d.ts +17 -6
  168. package/dist/src/harness/proxy-input-requests.js +1 -1
  169. package/dist/src/harness/session-machine/current.d.ts +4 -0
  170. package/dist/src/harness/session-machine/current.js +1 -1
  171. package/dist/src/harness/step/after-model.js +1 -1
  172. package/dist/src/harness/step/context.d.ts +7 -2
  173. package/dist/src/harness/step/context.js +1 -1
  174. package/dist/src/harness/step-hooks.d.ts +2 -3
  175. package/dist/src/harness/step-hooks.js +1 -1
  176. package/dist/src/harness/tool-call-io.js +1 -1
  177. package/dist/src/harness/tool-loop.js +1 -1
  178. package/dist/src/harness/tools.d.ts +2 -3
  179. package/dist/src/harness/tools.js +1 -1
  180. package/dist/src/harness/turn-tag-state.d.ts +12 -0
  181. package/dist/src/harness/turn-tag-state.js +1 -1
  182. package/dist/src/internal/application/package.js +1 -1
  183. package/dist/src/internal/gateway.d.ts +0 -13
  184. package/dist/src/internal/gateway.js +1 -1
  185. package/dist/src/internal/invocation/workflow-execution.js +1 -1
  186. package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
  187. package/dist/src/internal/workflow/cancel-expired-development-run.js +1 -1
  188. package/dist/src/protocol/routes.d.ts +4 -0
  189. package/dist/src/protocol/routes.js +1 -1
  190. package/dist/src/public/channels/auth.d.ts +21 -4
  191. package/dist/src/public/channels/auth.js +1 -1
  192. package/dist/src/public/channels/mcp.js +1 -1
  193. package/dist/src/public/schedules/providers/in-memory.js +1 -1
  194. package/dist/src/public/schedules/providers/vercel.js +1 -1
  195. package/dist/src/public/schedules/subscription.d.ts +0 -1
  196. package/dist/src/sandbox/state.d.ts +1 -0
  197. package/dist/src/self-modification/extension/subagents/agent/instructions.js +1 -1
  198. package/dist/src/self-modification/extension/subagents/agent/tools/registry_add.js +1 -1
  199. package/dist/src/setup/flows/registry-session.d.ts +10 -2
  200. package/dist/src/setup/flows/registry-session.js +1 -1
  201. package/dist/src/setup/flows/registry.d.ts +2 -0
  202. package/dist/src/setup/flows/registry.js +1 -1
  203. package/dist/src/setup/integrations/shared/prerequisite.d.ts +8 -0
  204. package/dist/src/setup/integrations/shared/prerequisite.js +1 -1
  205. package/dist/src/setup/registry-setup-client.js +1 -1
  206. package/dist/src/setup/scaffold/create/project.js +1 -1
  207. package/dist/src/setup/scaffold/create/web-template.d.ts +3 -2
  208. package/dist/src/setup/scaffold/create/web-template.js +383 -411
  209. package/dist/src/setup/scaffold/index.js +1 -1
  210. package/dist/src/setup/vercel-project.d.ts +2 -3
  211. package/dist/src/setup/vercel-project.js +0 -0
  212. package/dist/src/shared/sandbox-provider.d.ts +9 -2
  213. package/dist/src/subagents/adapter.d.ts +3 -2
  214. package/dist/src/subagents/adapter.js +1 -1
  215. package/dist/src/subagents/callback-route.js +1 -1
  216. package/dist/src/subagents/hitl-proxy.d.ts +4 -3
  217. package/dist/src/subagents/hitl-proxy.js +1 -1
  218. package/dist/src/subagents/parent-notification.js +1 -1
  219. package/dist/src/svelte/index.js +1 -1
  220. package/dist/src/svelte/use-eve-agent.js +1 -1
  221. package/dist/src/tool-stubs/execute.d.ts +13 -0
  222. package/dist/src/tool-stubs/execute.js +1 -0
  223. package/dist/src/tool-stubs/output.d.ts +4 -0
  224. package/dist/src/tool-stubs/output.js +1 -0
  225. package/dist/src/tool-stubs/playback.d.ts +15 -0
  226. package/dist/src/tool-stubs/playback.js +1 -0
  227. package/dist/src/tool-stubs/rules.d.ts +3 -0
  228. package/dist/src/tool-stubs/rules.js +1 -0
  229. package/dist/src/tool-stubs/schema.d.ts +4 -0
  230. package/dist/src/tool-stubs/schema.js +1 -0
  231. package/dist/src/tool-stubs/target.d.ts +8 -0
  232. package/dist/src/tool-stubs/target.js +1 -0
  233. package/dist/src/tool-stubs/types.d.ts +56 -0
  234. package/dist/src/tool-stubs/types.js +1 -0
  235. package/dist/src/tool-stubs/validate-targets.d.ts +6 -0
  236. package/dist/src/tool-stubs/validate-targets.js +1 -0
  237. package/dist/src/tools/provided/ask-question-workflow.js +1 -1
  238. package/dist/src/tools/provided/sleep-workflow.js +1 -1
  239. package/dist/src/vue/index.js +1 -1
  240. package/dist/src/vue/use-eve-agent.js +1 -1
  241. package/docs/concepts/sessions-runs-and-streaming.md +2 -2
  242. package/docs/evals/meta.json +10 -1
  243. package/docs/evals/overview.mdx +2 -0
  244. package/docs/evals/tool-stubs.mdx +257 -0
  245. package/docs/extensions.md +1 -1
  246. package/docs/guides/auth-and-route-protection.md +25 -0
  247. package/docs/guides/dynamic-capabilities.md +10 -3
  248. package/docs/guides/frontend/nextjs.mdx +17 -4
  249. package/docs/sandbox/index.mdx +10 -2
  250. package/docs/subagents/index.mdx +1 -1
  251. package/docs/tools/human-in-the-loop.md +1 -1
  252. package/docs/tools/overview.mdx +8 -4
  253. package/docs/tools/workflows.mdx +15 -7
  254. package/package.json +6 -6
  255. package/dist/src/compiled/_chunks/workflow/dist-DmXynLVH.js +0 -1
  256. package/dist/src/compiled/_chunks/workflow/private-Dlf90Zvn.js +0 -1
  257. package/dist/src/compiled/_chunks/workflow/signal-exit-iIdjQcCK.js +0 -95
  258. package/dist/src/compiled/_chunks/workflow/sleep-BMqbraZM.js +0 -1
@@ -1 +1 @@
1
- import{WriteFileExistsError}from"./files.js";import{CURRENT_DIRECTORY_PROJECT_NAME,byokProviderEnvVar,isEveProject,scaffoldBaseProject}from"./create/project.js";import{scaffoldExtensionProject}from"./create/extension.js";import{DEFAULT_SLACK_CONNECTOR_SLUG,SLACK_CHANNEL_DEFAULT_ROUTE,deriveSlackConnectorSlug,ensureChannel,hasVercelHostFramework,isNextJsProject,listAuthoredChannels,normalizeSlackConnectorSlug,resolveVercelHostFrameworkPreset}from"./update/channels.js";import{SCAFFOLDABLE_CHANNELS}from"./channels-catalog.js";import{CONNECTION_CATALOG,CUSTOM_CONNECTION_SLUG,SUPPORTED_PROTOCOLS,catalogSlugs,effectiveProtocols,endpointForProtocol,getCatalogEntry,isValidConnectionSlug}from"./connections/catalog.js";import{ensureConnection,ensureConnectionDependencies,listAuthoredConnections}from"./update/connections.js";import{ensurePackageDependencies}from"./update/dependencies.js";import{HumanActionRequiredError}from"../human-action.js";export{CONNECTION_CATALOG,CURRENT_DIRECTORY_PROJECT_NAME,CUSTOM_CONNECTION_SLUG,DEFAULT_SLACK_CONNECTOR_SLUG,HumanActionRequiredError,SCAFFOLDABLE_CHANNELS,SLACK_CHANNEL_DEFAULT_ROUTE,SUPPORTED_PROTOCOLS,WriteFileExistsError,byokProviderEnvVar,catalogSlugs,deriveSlackConnectorSlug,effectiveProtocols,endpointForProtocol,ensureChannel,ensureConnection,ensureConnectionDependencies,ensurePackageDependencies,getCatalogEntry,hasVercelHostFramework,isEveProject,isNextJsProject,isValidConnectionSlug,listAuthoredChannels,listAuthoredConnections,normalizeSlackConnectorSlug,resolveVercelHostFrameworkPreset,scaffoldBaseProject,scaffoldExtensionProject};
1
+ import{HumanActionRequiredError}from"../human-action.js";import{WriteFileExistsError}from"./files.js";import{CURRENT_DIRECTORY_PROJECT_NAME,byokProviderEnvVar,isEveProject,scaffoldBaseProject}from"./create/project.js";import{scaffoldExtensionProject}from"./create/extension.js";import{DEFAULT_SLACK_CONNECTOR_SLUG,SLACK_CHANNEL_DEFAULT_ROUTE,deriveSlackConnectorSlug,ensureChannel,hasVercelHostFramework,isNextJsProject,listAuthoredChannels,normalizeSlackConnectorSlug,resolveVercelHostFrameworkPreset}from"./update/channels.js";import{SCAFFOLDABLE_CHANNELS}from"./channels-catalog.js";import{CONNECTION_CATALOG,CUSTOM_CONNECTION_SLUG,SUPPORTED_PROTOCOLS,catalogSlugs,effectiveProtocols,endpointForProtocol,getCatalogEntry,isValidConnectionSlug}from"./connections/catalog.js";import{ensureConnection,ensureConnectionDependencies,listAuthoredConnections}from"./update/connections.js";import{ensurePackageDependencies}from"./update/dependencies.js";export{CONNECTION_CATALOG,CURRENT_DIRECTORY_PROJECT_NAME,CUSTOM_CONNECTION_SLUG,DEFAULT_SLACK_CONNECTOR_SLUG,HumanActionRequiredError,SCAFFOLDABLE_CHANNELS,SLACK_CHANNEL_DEFAULT_ROUTE,SUPPORTED_PROTOCOLS,WriteFileExistsError,byokProviderEnvVar,catalogSlugs,deriveSlackConnectorSlug,effectiveProtocols,endpointForProtocol,ensureChannel,ensureConnection,ensureConnectionDependencies,ensurePackageDependencies,getCatalogEntry,hasVercelHostFramework,isEveProject,isNextJsProject,isValidConnectionSlug,listAuthoredChannels,listAuthoredConnections,normalizeSlackConnectorSlug,resolveVercelHostFrameworkPreset,scaffoldBaseProject,scaffoldExtensionProject};
@@ -20,7 +20,7 @@ interface PickTeamOptions extends VercelProjectOperationOptions {
20
20
  selectMessage?: (currentTeam: string) => string;
21
21
  }
22
22
  export interface LinkProjectOperationOptions extends CreatedProjectFrameworkOptions {
23
- /** Configure 100% trace sampling when creating a Vercel project. */
23
+ /** Configure 100% trace sampling when creating a Vercel project. Defaults to true. */
24
24
  traceSampling?: boolean;
25
25
  }
26
26
  export declare function unresolvedProject(): ProjectResolution;
@@ -31,8 +31,7 @@ export declare function assertNewProjectNameAvailable(projectRoot: string, team:
31
31
  * The Vercel auth state, read-only. `cli-missing` (ENOENT) and `unavailable` (a
32
32
  * transient network/API fault) are each kept distinct from `logged-out` so a
33
33
  * caller never tells the user to log in when the real cause is a missing CLI or
34
- * an unreachable network. `logged-out` is claimed only from the explicit
35
- * not-authenticated diagnostic.
34
+ * an unreachable network.
36
35
  */
37
36
  export type VercelAuthStatus = "authenticated" | "logged-out" | "cli-missing" | "unavailable";
38
37
  export declare function getVercelAuthStatus(projectRoot: string, options?: VercelProjectOperationOptions): Promise<VercelAuthStatus>;
Binary file
@@ -73,10 +73,17 @@ export interface SandboxProviderSessionContext {
73
73
  export interface SandboxProviderHandle<Session extends SandboxSession = SandboxSession> {
74
74
  readonly sandbox: Session;
75
75
  onRuntimeShutdown(): Promise<void>;
76
- onSessionDelete(options?: SandboxDeleteOptions): Promise<void>;
77
- onSessionStop(): Promise<void>;
76
+ onSandboxDelete(options?: SandboxDeleteOptions): Promise<void>;
77
+ onSandboxStop(): Promise<void>;
78
78
  }
79
79
  export interface SandboxProviderImplementation<OpenOptions extends object | undefined, PreparedArtifact extends SandboxPreparedArtifact, SessionState, Session extends SandboxSession = SandboxSession> {
80
+ /**
81
+ * Permanently releases resources owned by a durable session after its terminal outcome.
82
+ * Implementations must be idempotent because the cleanup step may retry.
83
+ */
84
+ onSessionEnd?(context: SandboxProviderSessionContext, artifact: Readonly<PreparedArtifact>, state: Readonly<SessionState>, options: {
85
+ readonly reason: "completed" | "expired" | "failed";
86
+ }): Promise<void>;
80
87
  prepare(context: SandboxProviderPrepareContext): Promise<PreparedArtifact>;
81
88
  resume(context: SandboxProviderSessionContext, artifact: Readonly<PreparedArtifact>, state: Readonly<SessionState>): Promise<SandboxProviderHandle<Session>>;
82
89
  start(context: SandboxProviderSessionContext, options: Readonly<OpenOptions> | undefined, artifact: Readonly<PreparedArtifact>): Promise<{
@@ -3,7 +3,8 @@ import type { ChannelAdapter } from "#channel/adapter.js";
3
3
  * Framework adapter that bridges a child subagent session to its
4
4
  * parent.
5
5
  *
6
- * It proxies child `input.requested` events upward so the parent channel
7
- * can render HITL prompts and route responses back down to the child.
6
+ * It proxies child `input.requested` events upward so the parent channel can
7
+ * render HITL prompts and route responses back down to the child, and the
8
+ * `input.resolved` of requests only the child can close.
8
9
  */
9
10
  export declare const SUBAGENT_ADAPTER: ChannelAdapter;
@@ -1 +1 @@
1
- import{createErrorId,createLogger}from"#internal/logging.js";import{ContinuationTokenKey,SessionIdKey,SessionInboxKey}from"#context/keys.js";import{SUBAGENT_ADAPTER_KIND,isSubagentAdapterState}from"#subagents/adapter-state.js";const log=createLogger(`execution.subagent-adapter`),SUBAGENT_ADAPTER={kind:SUBAGENT_ADAPTER_KIND,async"approval.candidate"(e,t){await forwardSubagentAuthorizationEvent({data:e,type:`approval.candidate`},t)},async"approval.settled"(e,t){await forwardSubagentAuthorizationEvent({data:e,type:`approval.settled`},t)},async"authorization.required"(e,t){await forwardSubagentAuthorizationEvent({data:e,type:`authorization.required`},t)},async"authorization.completed"(e,t){await forwardSubagentAuthorizationEvent({data:e,type:`authorization.completed`},t)},async"input.requested"(e,t){let n=t.state;isSubagentAdapterState(n)&&await forwardSubagentInputRequestStep({hookPayload:{callId:n.callId,childContinuationToken:t.ctx.require(ContinuationTokenKey),childSessionId:t.ctx.require(SessionIdKey),childSessionInbox:t.ctx.get(SessionInboxKey),inputSource:t.inputSource,event:{requests:e.requests,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},kind:`subagent-input-request`,subagentName:n.subagentName},parentContinuationToken:n.parentContinuationToken})}};async function forwardSubagentAuthorizationEvent(e,t){let n=t.state;isSubagentAdapterState(n)&&await forwardSubagentAuthorizationEventStep({hookPayload:{callId:n.callId,childSessionId:t.ctx.require(SessionIdKey),event:e,kind:`subagent-authorization-event`,subagentName:n.subagentName},parentContinuationToken:n.parentContinuationToken})}async function forwardSubagentAuthorizationEventStep(e){"use step";try{await resumeParentHook(e.parentContinuationToken,e.hookPayload)}catch(t){let n=createErrorId();throw log.warn(`failed to forward subagent authorization event to parent`,{callId:e.hookPayload.callId,childSessionId:e.hookPayload.childSessionId,errorId:n,eventType:e.hookPayload.event.type,parentContinuationToken:e.parentContinuationToken,subagentName:e.hookPayload.subagentName,error:t}),t}}async function forwardSubagentInputRequestStep(e){"use step";try{await resumeParentHook(e.parentContinuationToken,e.hookPayload)}catch(t){let n=createErrorId();throw log.warn(`failed to forward proxied HITL batch to parent`,{callId:e.hookPayload.callId,childContinuationToken:e.hookPayload.childContinuationToken,childSessionId:e.hookPayload.childSessionId,errorId:n,parentContinuationToken:e.parentContinuationToken,subagentName:e.hookPayload.subagentName,error:t}),t}}async function resumeParentHook(e,t){let{resumeHook:n}=await import(`#internal/workflow/runtime.js`);await n(e,t)}export{SUBAGENT_ADAPTER};
1
+ import{createErrorId,createLogger}from"#internal/logging.js";import{ContinuationTokenKey,SessionIdKey,SessionInboxKey}from"#context/keys.js";import{resolvedForParent}from"#harness/proxy-input-requests.js";import{SUBAGENT_ADAPTER_KIND,isSubagentAdapterState}from"#subagents/adapter-state.js";const log=createLogger(`execution.subagent-adapter`),SUBAGENT_ADAPTER={kind:SUBAGENT_ADAPTER_KIND,async"approval.candidate"(e,t){await forwardSubagentAuthorizationEvent({data:e,type:`approval.candidate`},t)},async"approval.settled"(e,t){await forwardSubagentAuthorizationEvent({data:e,type:`approval.settled`},t)},async"authorization.required"(e,t){await forwardSubagentAuthorizationEvent({data:e,type:`authorization.required`},t)},async"authorization.completed"(e,t){await forwardSubagentAuthorizationEvent({data:e,type:`authorization.completed`},t)},async"input.resolved"(e,t){let n=resolvedForParent(e);n!==void 0&&await forwardSubagentAuthorizationEvent({data:n,type:`input.resolved`},t)},async"input.requested"(e,t){let n=t.state;isSubagentAdapterState(n)&&await forwardSubagentInputRequestStep({hookPayload:{callId:n.callId,childContinuationToken:t.ctx.require(ContinuationTokenKey),childSessionId:t.ctx.require(SessionIdKey),childSessionInbox:t.ctx.get(SessionInboxKey),inputSource:t.inputSource,event:{requests:e.requests,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},kind:`subagent-input-request`,subagentName:n.subagentName},parentContinuationToken:n.parentContinuationToken})}};async function forwardSubagentAuthorizationEvent(e,t){let n=t.state;isSubagentAdapterState(n)&&await forwardSubagentAuthorizationEventStep({hookPayload:{callId:n.callId,childSessionId:t.ctx.require(SessionIdKey),event:e,kind:`subagent-authorization-event`,subagentName:n.subagentName},parentContinuationToken:n.parentContinuationToken})}async function forwardSubagentAuthorizationEventStep(e){"use step";try{await resumeParentHook(e.parentContinuationToken,e.hookPayload)}catch(t){let n=createErrorId();throw log.warn(`failed to forward subagent authorization event to parent`,{callId:e.hookPayload.callId,childSessionId:e.hookPayload.childSessionId,errorId:n,eventType:e.hookPayload.event.type,parentContinuationToken:e.parentContinuationToken,subagentName:e.hookPayload.subagentName,error:t}),t}}async function forwardSubagentInputRequestStep(e){"use step";try{await resumeParentHook(e.parentContinuationToken,e.hookPayload)}catch(t){let n=createErrorId();throw log.warn(`failed to forward proxied HITL batch to parent`,{callId:e.hookPayload.callId,childContinuationToken:e.hookPayload.childContinuationToken,childSessionId:e.hookPayload.childSessionId,errorId:n,parentContinuationToken:e.parentContinuationToken,subagentName:e.hookPayload.subagentName,error:t}),t}}async function resumeParentHook(e,t){let{resumeHook:n}=await import(`#internal/workflow/runtime.js`);await n(e,t)}export{SUBAGENT_ADAPTER};
@@ -1 +1 @@
1
- import{z}from"#compiled/zod/index.js";import{inputRequestSchema}from"#shared/input.js";import{jsonValueSchema}from"#shared/json-schemas.js";import{renameLegacyTaskCallback}from"#execution/legacy-remote-agent/protocol.js";import{resumeHook}from"#internal/workflow/runtime.js";import{agentTurnOutcomeWithCostSchema}from"#shared/agent-turn-outcome.js";const sessionInputCallbackSchema=z.object({callId:z.string().min(1),childContinuationToken:z.string().min(1),childSessionId:z.string().min(1),childSessionInbox:z.object({sessionId:z.string().min(1)}).strict().optional(),inputSource:z.string().min(1).optional(),remote:z.object({name:z.string().min(1),url:z.string().url(),forwardPrincipal:z.boolean().optional(),sessionId:z.string().min(1),resolverId:z.string().min(1).optional()}).strict().optional(),kind:z.literal(`subagent-input-request`),subagentName:z.string().min(1),event:z.object({requests:z.array(inputRequestSchema).min(1),sequence:z.number(),stepIndex:z.number(),taskId:z.string().optional(),turnId:z.string()})}),sessionAuthorizationCallbackSchema=z.object({callId:z.string().min(1),childSessionId:z.string().min(1),kind:z.literal(`subagent-authorization-event`),subagentName:z.string().min(1),event:z.discriminatedUnion(`type`,[z.object({type:z.literal(`approval.candidate`),data:z.object({candidateId:z.string(),outcome:z.enum([`pending`,`rejected`,`failed`,`timed-out`,`stale`]),requestId:z.string(),responderPrincipalId:z.string(),reason:z.string().optional(),sequence:z.number(),stepIndex:z.number(),turnId:z.string()}).passthrough()}),z.object({type:z.literal(`approval.settled`),data:z.object({outcome:z.enum([`approved`,`cancelled`]),requestId:z.string(),responderPrincipalId:z.string(),sequence:z.number(),stepIndex:z.number(),turnId:z.string()}).passthrough()}),z.object({type:z.literal(`authorization.required`),data:z.object({description:z.string(),name:z.string(),sequence:z.number(),stepIndex:z.number(),turnId:z.string(),webhookUrl:z.string().optional(),attemptId:z.string().optional(),taskId:z.string().optional(),principalId:z.string().optional()}).passthrough()}),z.object({type:z.literal(`authorization.completed`),data:z.object({name:z.string(),outcome:z.enum([`authorized`,`declined`,`failed`,`timed-out`]),sequence:z.number(),stepIndex:z.number(),turnId:z.string(),attemptId:z.string().optional(),taskId:z.string().optional(),principalId:z.string().optional()}).passthrough()})])}),sessionResultCallbackSchema=z.discriminatedUnion(`kind`,[z.object({callId:z.string().min(1),kind:z.literal(`turn.completed`),outcome:agentTurnOutcomeWithCostSchema,output:jsonValueSchema.optional(),subagentName:z.string().min(1)}),z.object({callId:z.string().min(1),error:jsonValueSchema,kind:z.literal(`turn.failed`),outcome:agentTurnOutcomeWithCostSchema,subagentName:z.string().min(1)})]);async function handleSessionCallbackRequest(e,t){let n=t.params.token;if(typeof n!=`string`||n.length===0)return Response.json({error:`Missing callback token.`,ok:!1},{status:400});let r;try{r=renameLegacyTaskCallback(await e.json())}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}let i=callbackKind(r),a=i===`subagent-input-request`?sessionInputCallbackSchema.safeParse(r):i===`subagent-authorization-event`?sessionAuthorizationCallbackSchema.safeParse(r):void 0;if(a!==void 0&&!a.success)return Response.json({error:`Invalid session input callback.`,ok:!1},{status:400});let o=a===void 0?projectSessionCallbackResult(r):void 0;if(o instanceof Response)return o;try{await resumeHook(n,a?.success?a.data:{kind:`runtime-action-result`,results:[o]})}catch{return Response.json({error:`Session callback not pending.`,ok:!1},{status:404})}return Response.json({ok:!0},{status:202})}function callbackKind(e){if(typeof e==`object`&&e)return Reflect.get(e,`kind`)}function projectSessionCallbackResult(e){if(typeof e!=`object`||!e)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let t=callbackKind(e);if(t!==`turn.completed`&&t!==`turn.failed`)return Response.json({error:`Unsupported callback kind.`,ok:!1},{status:400});let n=sessionResultCallbackSchema.safeParse(e);if(!n.success)return Response.json({error:`Invalid session result callback.`,ok:!1},{status:400});let r=n.data;return r.kind===`turn.completed`?{callId:r.callId,kind:`subagent-result`,origin:`child`,outcome:r.outcome,output:r.output??``,subagentName:r.subagentName,usage:r.outcome.usageDelta}:{callId:r.callId,isError:!0,kind:`subagent-result`,origin:`child`,outcome:r.outcome,output:r.error,subagentName:r.subagentName}}export{handleSessionCallbackRequest};
1
+ import{z}from"#compiled/zod/index.js";import{inputRequestSchema,inputResponseSchema}from"#shared/input.js";import{jsonValueSchema}from"#shared/json-schemas.js";import{resumeHook}from"#internal/workflow/runtime.js";import{renameLegacyTaskCallback}from"#execution/legacy-remote-agent/protocol.js";import{agentTurnOutcomeWithCostSchema}from"#shared/agent-turn-outcome.js";const sessionInputCallbackSchema=z.object({callId:z.string().min(1),childContinuationToken:z.string().min(1),childSessionId:z.string().min(1),childSessionInbox:z.object({sessionId:z.string().min(1)}).strict().optional(),inputSource:z.string().min(1).optional(),remote:z.object({name:z.string().min(1),url:z.string().url(),forwardPrincipal:z.boolean().optional(),sessionId:z.string().min(1),resolverId:z.string().min(1).optional()}).strict().optional(),kind:z.literal(`subagent-input-request`),subagentName:z.string().min(1),event:z.object({requests:z.array(inputRequestSchema).min(1),sequence:z.number(),stepIndex:z.number(),taskId:z.string().optional(),turnId:z.string()})}),sessionAuthorizationCallbackSchema=z.object({callId:z.string().min(1),childSessionId:z.string().min(1),kind:z.literal(`subagent-authorization-event`),subagentName:z.string().min(1),event:z.discriminatedUnion(`type`,[z.object({type:z.literal(`approval.candidate`),data:z.object({candidateId:z.string(),outcome:z.enum([`pending`,`rejected`,`failed`,`timed-out`,`stale`]),requestId:z.string(),responderPrincipalId:z.string(),reason:z.string().optional(),sequence:z.number(),stepIndex:z.number(),turnId:z.string()}).passthrough()}),z.object({type:z.literal(`approval.settled`),data:z.object({outcome:z.enum([`approved`,`cancelled`]),requestId:z.string(),responderPrincipalId:z.string(),sequence:z.number(),stepIndex:z.number(),turnId:z.string()}).passthrough()}),z.object({type:z.literal(`input.resolved`),data:z.object({resolutions:z.array(z.object({kind:z.enum([`question`,`session-limit`,`tool-approval`]),outcome:z.enum([`answered`,`approved`,`cancelled`,`denied`,`ignored`,`invalid`]),requestId:z.string(),response:inputResponseSchema.optional()}).passthrough()),sequence:z.number(),stepIndex:z.number(),turnId:z.string()}).passthrough()}),z.object({type:z.literal(`authorization.required`),data:z.object({description:z.string(),name:z.string(),sequence:z.number(),stepIndex:z.number(),turnId:z.string(),webhookUrl:z.string().optional(),attemptId:z.string().optional(),taskId:z.string().optional(),principalId:z.string().optional()}).passthrough()}),z.object({type:z.literal(`authorization.completed`),data:z.object({name:z.string(),outcome:z.enum([`authorized`,`declined`,`failed`,`timed-out`]),sequence:z.number(),stepIndex:z.number(),turnId:z.string(),attemptId:z.string().optional(),taskId:z.string().optional(),principalId:z.string().optional()}).passthrough()})])}),sessionResultCallbackSchema=z.discriminatedUnion(`kind`,[z.object({callId:z.string().min(1),kind:z.literal(`turn.completed`),outcome:agentTurnOutcomeWithCostSchema,output:jsonValueSchema.optional(),subagentName:z.string().min(1)}),z.object({callId:z.string().min(1),error:jsonValueSchema,kind:z.literal(`turn.failed`),outcome:agentTurnOutcomeWithCostSchema,subagentName:z.string().min(1)})]);async function handleSessionCallbackRequest(e,t){let n=t.params.token;if(typeof n!=`string`||n.length===0)return Response.json({error:`Missing callback token.`,ok:!1},{status:400});let r;try{r=renameLegacyTaskCallback(await e.json())}catch{return Response.json({error:`Invalid JSON body.`,ok:!1},{status:400})}let i=callbackKind(r),a=i===`subagent-input-request`?sessionInputCallbackSchema.safeParse(r):i===`subagent-authorization-event`?sessionAuthorizationCallbackSchema.safeParse(r):void 0;if(a!==void 0&&!a.success)return Response.json({error:`Invalid session input callback.`,ok:!1},{status:400});let o=a===void 0?projectSessionCallbackResult(r):void 0;if(o instanceof Response)return o;try{await resumeHook(n,a?.success?a.data:{kind:`runtime-action-result`,results:[o]})}catch{return Response.json({error:`Session callback not pending.`,ok:!1},{status:404})}return Response.json({ok:!0},{status:202})}function callbackKind(e){if(typeof e==`object`&&e)return Reflect.get(e,`kind`)}function projectSessionCallbackResult(e){if(typeof e!=`object`||!e)return Response.json({error:`Expected a JSON object.`,ok:!1},{status:400});let t=callbackKind(e);if(t!==`turn.completed`&&t!==`turn.failed`)return Response.json({error:`Unsupported callback kind.`,ok:!1},{status:400});let n=sessionResultCallbackSchema.safeParse(e);if(!n.success)return Response.json({error:`Invalid session result callback.`,ok:!1},{status:400});let r=n.data;return r.kind===`turn.completed`?{callId:r.callId,kind:`subagent-result`,origin:`child`,outcome:r.outcome,output:r.output??``,subagentName:r.subagentName,usage:r.outcome.usageDelta}:{callId:r.callId,isError:!0,kind:`subagent-result`,origin:`child`,outcome:r.outcome,output:r.error,subagentName:r.subagentName}}export{handleSessionCallbackRequest};
@@ -45,9 +45,10 @@ export interface RoutedDeliverPayload {
45
45
  /**
46
46
  * Splits a deliver payload into parent-local and proxied-child buckets.
47
47
  *
48
- * With `resolveMessage`, a plain-text message is also resolved against pending
49
- * `ctx.ask()` questions: when exactly one question is pending, a matching option or
50
- * permitted free text answers it and consumes the message along with its
48
+ * With `resolveMessage`, a plain-text message is also resolved against the
49
+ * first open request when a child asked it, whether a `ctx.ask()` question, a
50
+ * tool approval, or a session-limit prompt: a matching option or permitted free
51
+ * text answers that one request, and the message is consumed along with its
51
52
  * `context`. Otherwise the message stays with the parent.
52
53
  */
53
54
  export declare function routeDeliverPayload(input: {
@@ -1 +1 @@
1
- import{inputTextKey,readAnswerText}from"#internal/input-text.js";import{firstOpenInput}from"#harness/open-input-request.js";import{resolveTextToResponse}from"#channel/resolve-text.js";import{storedProjection}from"#harness/session-machine/view.js";import{getProxyInputRequests}from"#harness/proxy-input-requests.js";import{resolveInputOutcome}from"#harness/input-request-resolution.js";import{SESSION_LIMIT_STOP_OPTION_ID}from"#harness/hitl/budget-request.js";const CONSUMED_MESSAGE_KEYS=new Set([`context`,`message`,inputTextKey]);function routeDeliverPayload(e){let t=getProxyInputRequests(e.state),routable=(t,n)=>n!==void 0&&e.allowRoute?.(t,n)!==!1,n=resolveMessageAgainstQuestions({enabled:e.resolveMessage===!0,entries:t,payload:e.payload,routable,state:e.state}),[r]=n.responses,i=[...e.payload.inputResponses??[],...n.responses],a=new Map,o=[],s,bucketFor=e=>{let t=JSON.stringify([e.childContinuationToken,e.childSessionInbox?.sessionId??``,e.remote?.sessionId??``,e.event.sequence,e.event.stepIndex,e.event.turnId,e.inputSource??null]),n=a.get(t);if(n!==void 0)return n;let r={childContinuationToken:e.childContinuationToken,remote:e.remote,event:e.event,parentRequestIds:[],responses:[],routes:[],...e.childSessionInbox!==void 0&&{childSessionInbox:e.childSessionInbox},...e.workflowAsk!==void 0&&{workflowAsk:e.workflowAsk}};return a.set(t,r),r},c=new Set;for(let e of i){let n=t.get(e.requestId);if(n===void 0||!routable(e.requestId,n)){o.push(e);continue}if(c.has(e.requestId))continue;c.add(e.requestId),n.kind===`session-limit`&&e.optionId===SESSION_LIMIT_STOP_OPTION_ID&&(s={kind:`cancel-turn`});let r=bucketFor(n);r.parentRequestIds.push(e.requestId),r.responses.push(e),r.routes.push(n)}let l=[...a.values()].map(({workflowAsk:n,remote:i,childContinuationToken:a,childSessionInbox:o,event:s,parentRequestIds:c,responses:l,routes:u})=>{let d=new Set(c),f=new Set(d);for(let e of u)if(e.batch!==void 0&&batchResolves({batch:e.batch,childContinuationToken:a,entries:t,responseIds:d}))for(let t of e.batch.requestIds)f.add(t);return{childContinuationToken:a,payload:{inputResponses:l},resolved:{event:s,resolutions:resolveRetiredRequests({entries:t,responses:l,retireRequestIds:f})},...o!==void 0&&{childSessionInbox:o},...r!==void 0&&l.includes(r)&&{message:e.payload.message},...n!==void 0&&{workflowAsk:n},...i!==void 0&&{remote:i},...u[0]?.inputSource!==void 0&&{inputSource:u[0].inputSource}}}),u={};for(let[t,r]of Object.entries(e.payload))t!==`inputResponses`&&r!==void 0&&(n.consumed&&CONSUMED_MESSAGE_KEYS.has(t)||(u[t]=r));return o.length>0&&(u.inputResponses=o),{forChildren:l,forSelf:Object.keys(u).length>0?u:void 0,parentAction:s}}function resolveRetiredRequests(e){let t=new Map(e.responses.map(e=>[e.requestId,e])),n=[];for(let r of e.retireRequestIds){let i=e.entries.get(r);i!==void 0&&n.push(toInputResolution(r,i,t.get(r)))}return n}function toInputResolution(e,t,n){let r=resolveInputOutcome(t.kind,n),i={kind:t.kind,outcome:r,requestId:e};return n===void 0?i:{...i,response:n}}function resolveMessageAgainstQuestions(e){let t={consumed:!1,responses:[]};if(!e.enabled||(e.payload.inputResponses?.length??0)>0)return t;let n=readAnswerText(e.payload);if(n===void 0)return t;let answered=t=>{let n=e.entries.get(t);return n!==void 0&&!e.routable(t,n)},r=firstOpenInput(storedProjection(e.state),answered)?.request.requestId??[...e.entries.keys()].find(e=>!answered(e)),i=r===void 0?void 0:e.entries.get(r);if(r===void 0||i?.kind!==`question`)return t;let a=i.workflowAsk?.question??i.question,o=a===void 0?void 0:resolveTextToResponse(n,{requestId:r,...a});return o===void 0?t:{consumed:!0,responses:[o]}}function batchResolves(e){return e.batch.approvalRequestIds.length===0||e.batch.approvalRequestIds.every(t=>{let n=e.entries.get(t);return n===void 0||!sameBatch(n,e)||e.responseIds.has(t)})}function sameBatch(e,t){return e.childContinuationToken===t.childContinuationToken&&e.batch?.requestIds.length===t.batch.requestIds.length&&e.batch.requestIds.every((e,n)=>e===t.batch.requestIds[n])}export{routeDeliverPayload};
1
+ import{inputTextKey,readAnswerText}from"#internal/input-text.js";import{firstOpenInput}from"#harness/open-input-request.js";import{resolveTextToResponse}from"#channel/resolve-text.js";import{storedProjection}from"#harness/session-machine/view.js";import{getProxyInputRequests,resolvedByChild}from"#harness/proxy-input-requests.js";import{resolveInputOutcome}from"#harness/input-request-resolution.js";import{SESSION_LIMIT_STOP_OPTION_ID}from"#harness/hitl/budget-request.js";const CONSUMED_MESSAGE_KEYS=new Set([`context`,`message`,inputTextKey]);function routeDeliverPayload(e){let t=getProxyInputRequests(e.state),routable=(t,n)=>n!==void 0&&e.allowRoute?.(t,n)!==!1,n=resolveMessageAgainstFirstRequest({enabled:e.resolveMessage===!0,entries:t,payload:e.payload,routable,state:e.state}),[r]=n.responses,i=[...e.payload.inputResponses??[],...n.responses],a=new Map,o=[],s,bucketFor=e=>{let t=JSON.stringify([e.childContinuationToken,e.childSessionInbox?.sessionId??``,e.remote?.sessionId??``,e.event.sequence,e.event.stepIndex,e.event.turnId,e.inputSource??null]),n=a.get(t);if(n!==void 0)return n;let r={childContinuationToken:e.childContinuationToken,remote:e.remote,event:e.event,parentRequestIds:[],responses:[],routes:[],...e.childSessionInbox!==void 0&&{childSessionInbox:e.childSessionInbox},...e.workflowAsk!==void 0&&{workflowAsk:e.workflowAsk}};return a.set(t,r),r},c=new Set;for(let e of i){let n=t.get(e.requestId);if(n===void 0||!routable(e.requestId,n)){o.push(e);continue}if(c.has(e.requestId))continue;c.add(e.requestId),n.kind===`session-limit`&&e.optionId===SESSION_LIMIT_STOP_OPTION_ID&&(s={kind:`cancel-turn`});let r=bucketFor(n);r.parentRequestIds.push(e.requestId),r.responses.push(e),r.routes.push(n)}let l=[...a.values()].map(({workflowAsk:n,remote:i,childContinuationToken:a,childSessionInbox:o,event:s,parentRequestIds:c,responses:l,routes:u})=>{let d=new Set(c),decided=e=>{let n=t.get(e)?.kind;return n===void 0||!resolvedByChild(n)},f=new Set([...d].filter(decided));for(let e of u)if(e.batch!==void 0&&batchResolves({batch:e.batch,childContinuationToken:a,entries:t,responseIds:d}))for(let t of e.batch.requestIds)decided(t)&&f.add(t);return{childContinuationToken:a,payload:{inputResponses:l},resolved:{event:s,resolutions:resolveRetiredRequests({entries:t,responses:l,retireRequestIds:f})},...o!==void 0&&{childSessionInbox:o},...r!==void 0&&l.includes(r)&&{message:e.payload.message},...n!==void 0&&{workflowAsk:n},...i!==void 0&&{remote:i},...u[0]?.inputSource!==void 0&&{inputSource:u[0].inputSource}}}),u={};for(let[t,r]of Object.entries(e.payload))t!==`inputResponses`&&r!==void 0&&(n.consumed&&CONSUMED_MESSAGE_KEYS.has(t)||(u[t]=r));return o.length>0&&(u.inputResponses=o),{forChildren:l,forSelf:Object.keys(u).length>0?u:void 0,parentAction:s}}function resolveRetiredRequests(e){let t=new Map(e.responses.map(e=>[e.requestId,e])),n=[];for(let r of e.retireRequestIds){let i=e.entries.get(r);i!==void 0&&n.push(toInputResolution(r,i,t.get(r)))}return n}function toInputResolution(e,t,n){let r=resolveInputOutcome(t.kind,n),i={kind:t.kind,outcome:r,requestId:e};return n===void 0?i:{...i,response:n}}function resolveMessageAgainstFirstRequest(e){let t={consumed:!1,responses:[]};if(!e.enabled||(e.payload.inputResponses?.length??0)>0)return t;let n=readAnswerText(e.payload);if(n===void 0)return t;let answered=t=>{let n=e.entries.get(t);return n!==void 0&&!e.routable(t,n)},r=firstOpenInput(storedProjection(e.state),answered)?.request.requestId??[...e.entries.keys()].find(e=>!answered(e)),i=r===void 0?void 0:e.entries.get(r)?.reply;if(r===void 0||i===void 0)return t;let a=resolveTextToResponse(n,{requestId:r,...i});return a===void 0?t:{consumed:!0,responses:[a]}}function batchResolves(e){return e.batch.approvalRequestIds.length===0||e.batch.approvalRequestIds.every(t=>{let n=e.entries.get(t);return n===void 0||!sameBatch(n,e)||e.responseIds.has(t)})}function sameBatch(e,t){return e.childContinuationToken===t.childContinuationToken&&e.batch?.requestIds.length===t.batch.requestIds.length&&e.batch.requestIds.every((e,n)=>e===t.batch.requestIds[n])}export{routeDeliverPayload};
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{SessionCallbackKey}from"#context/keys.js";import{toErrorMessage}from"#shared/errors.js";import{parseJsonValue}from"#shared/json.js";import{ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{parseSessionCallback}from"#channel/session-callback.js";import{deserializeContext}from"#context/serialize.js";import{postSessionCallbackRequest}from"#execution/session-callback-request.js";import{HookNotFoundError}from"#compiled/@workflow/errors/index.js";import{resumeHook}from"#internal/workflow/runtime.js";import{SUBAGENT_ADAPTER_KIND,isSubagentAdapterState}from"#subagents/adapter-state.js";const log=createLogger(`execution.delegated-parent-notification`),SUBAGENT_EXECUTION_FAILED=`SUBAGENT_EXECUTION_FAILED`,ZERO_TOKEN_USAGE={cacheReadTokens:0,cacheWriteTokens:0,inputTokens:0,outputTokens:0};async function notifyTurnCallerStep(e){"use step";if(e.caller===void 0)return;let t=createSettledTurnResult({caller:e.caller,lifecycle:e.lifecycle,sessionId:e.sessionId,settled:e.settled});if(e.caller.replyTo.kind===`callback`){await postSettledTurnCallback({result:t,sessionId:e.sessionId,url:e.caller.replyTo.url});return}await resumeSettledTurnHook(e.caller.replyTo.token,t)}async function notifyCancelledTaskCallerStep(e){"use step";let t=e.usage??ZERO_TOKEN_USAGE,n={code:SUBAGENT_EXECUTION_FAILED,message:`The agent invocation was cancelled.`},r={callId:e.caller.callId,isError:!0,kind:`subagent-result`,origin:`child`,outcome:{kind:`parked`,result:{kind:`cancelled`},usageDelta:t},output:n,subagentName:e.caller.subagentName},i=e.usage===void 0?r:{...r,usage:e.usage};if(e.caller.replyTo.kind===`callback`){await postSettledTurnCallback({result:i,sessionId:e.sessionId,url:e.caller.replyTo.url});return}await resumeSettledTurnHook(e.caller.replyTo.token,i)}function createSettledTurnResult(e){let t=e.settled.usage??ZERO_TOKEN_USAGE;if(e.settled.isError===!0){let n={code:SUBAGENT_EXECUTION_FAILED,message:toErrorMessage(e.settled.output)};return{callId:e.caller.callId,isError:!0,kind:`subagent-result`,origin:`child`,outcome:{kind:e.lifecycle,result:{error:n,kind:`failed`},usageDelta:t},output:n,subagentName:e.caller.subagentName}}let n=parseJsonValue(e.settled.output),r={callId:e.caller.callId,kind:`subagent-result`,origin:`child`,outcome:{kind:e.lifecycle,result:{kind:`succeeded`,output:n},usageDelta:t},output:n,subagentName:e.caller.subagentName};return e.settled.usage===void 0?r:{...r,usage:e.settled.usage}}async function resolveInitialTurnCallerStep(e){"use step";let t=e.serializedContext[SessionCallbackKey.name];if(t!==void 0){let e=parseSessionCallback(t);if(!e.ok)throw Error(`Serialized session callback is invalid.`,{cause:e.cause});return{callId:e.callback.callId,replyTo:{kind:`callback`,token:e.callback.token,url:e.callback.url},subagentName:e.callback.subagentName}}let n=(await deserializeContext(e.serializedContext)).get(ChannelKey);if(n?.kind===SUBAGENT_ADAPTER_KIND&&isSubagentAdapterState(n.state))return{callId:n.state.callId,replyTo:{kind:`hook`,token:n.state.parentContinuationToken},subagentName:n.state.subagentName}}function bindTurnCallerContext(e,t){if(e===void 0)return t;if(e.replyTo.kind===`callback`){let n={callId:e.callId,subagentName:e.subagentName,token:e.replyTo.token,url:e.replyTo.url};return{...t,[SessionCallbackKey.name]:n}}let n=t[ChannelKey.name];if(typeof n!=`object`||!n||Reflect.get(n,`kind`)!==SUBAGENT_ADAPTER_KIND||!isSubagentAdapterState(Reflect.get(n,`state`)))throw Error(`Delegated local turn is missing its subagent adapter binding.`);let r={...Reflect.get(n,`state`),callId:e.callId,parentContinuationToken:e.replyTo.token,subagentName:e.subagentName};return{...t,[ChannelKey.name]:{...n,state:r}}}async function postSettledTurnCallback(e){let{sessionId:t}=e;if(e.result.isError===!0){await postCallbackPayload({payload:{callId:e.result.callId,error:e.result.output,kind:`turn.failed`,outcome:e.result.outcome,sessionId:t,subagentName:e.result.subagentName},url:e.url});return}await postCallbackPayload({payload:{callId:e.result.callId,kind:`turn.completed`,outcome:e.result.outcome,output:e.result.output,sessionId:t,subagentName:e.result.subagentName},url:e.url})}async function postCallbackPayload(e){let t=await postSessionCallbackRequest({body:e.payload,url:e.url});if(!t.ok)throw Error(`Turn callback failed with HTTP ${t.status}.`)}async function resumeSettledTurnHook(e,t){try{await resumeHook(e,{kind:`runtime-action-result`,results:[t]})}catch(n){if(!HookNotFoundError.is(n))throw n;log.warn(`turn caller hook no longer exists`,{callId:t.callId,callerToken:e})}}export{bindTurnCallerContext,notifyCancelledTaskCallerStep,notifyTurnCallerStep,resolveInitialTurnCallerStep};
1
+ import{createLogger}from"#internal/logging.js";import{SessionCallbackKey}from"#context/keys.js";import{toErrorMessage}from"#shared/errors.js";import{parseJsonValue}from"#shared/json.js";import{ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{resumeHook}from"#internal/workflow/runtime.js";import{parseSessionCallback}from"#channel/session-callback.js";import{deserializeContext}from"#context/serialize.js";import{postSessionCallbackRequest}from"#execution/session-callback-request.js";import{HookNotFoundError}from"#compiled/@workflow/errors/index.js";import{SUBAGENT_ADAPTER_KIND,isSubagentAdapterState}from"#subagents/adapter-state.js";const log=createLogger(`execution.delegated-parent-notification`),SUBAGENT_EXECUTION_FAILED=`SUBAGENT_EXECUTION_FAILED`,ZERO_TOKEN_USAGE={cacheReadTokens:0,cacheWriteTokens:0,inputTokens:0,outputTokens:0};async function notifyTurnCallerStep(e){"use step";if(e.caller===void 0)return;let t=createSettledTurnResult({caller:e.caller,lifecycle:e.lifecycle,sessionId:e.sessionId,settled:e.settled});if(e.caller.replyTo.kind===`callback`){await postSettledTurnCallback({result:t,sessionId:e.sessionId,url:e.caller.replyTo.url});return}await resumeSettledTurnHook(e.caller.replyTo.token,t)}async function notifyCancelledTaskCallerStep(e){"use step";let t=e.usage??ZERO_TOKEN_USAGE,n={code:SUBAGENT_EXECUTION_FAILED,message:`The agent invocation was cancelled.`},r={callId:e.caller.callId,isError:!0,kind:`subagent-result`,origin:`child`,outcome:{kind:`parked`,result:{kind:`cancelled`},usageDelta:t},output:n,subagentName:e.caller.subagentName},i=e.usage===void 0?r:{...r,usage:e.usage};if(e.caller.replyTo.kind===`callback`){await postSettledTurnCallback({result:i,sessionId:e.sessionId,url:e.caller.replyTo.url});return}await resumeSettledTurnHook(e.caller.replyTo.token,i)}function createSettledTurnResult(e){let t=e.settled.usage??ZERO_TOKEN_USAGE;if(e.settled.isError===!0){let n={code:SUBAGENT_EXECUTION_FAILED,message:toErrorMessage(e.settled.output)};return{callId:e.caller.callId,isError:!0,kind:`subagent-result`,origin:`child`,outcome:{kind:e.lifecycle,result:{error:n,kind:`failed`},usageDelta:t},output:n,subagentName:e.caller.subagentName}}let n=parseJsonValue(e.settled.output),r={callId:e.caller.callId,kind:`subagent-result`,origin:`child`,outcome:{kind:e.lifecycle,result:{kind:`succeeded`,output:n},usageDelta:t},output:n,subagentName:e.caller.subagentName};return e.settled.usage===void 0?r:{...r,usage:e.settled.usage}}async function resolveInitialTurnCallerStep(e){"use step";let t=e.serializedContext[SessionCallbackKey.name];if(t!==void 0){let e=parseSessionCallback(t);if(!e.ok)throw Error(`Serialized session callback is invalid.`,{cause:e.cause});return{callId:e.callback.callId,replyTo:{kind:`callback`,token:e.callback.token,url:e.callback.url},subagentName:e.callback.subagentName}}let n=(await deserializeContext(e.serializedContext)).get(ChannelKey);if(n?.kind===SUBAGENT_ADAPTER_KIND&&isSubagentAdapterState(n.state))return{callId:n.state.callId,replyTo:{kind:`hook`,token:n.state.parentContinuationToken},subagentName:n.state.subagentName}}function bindTurnCallerContext(e,t){if(e===void 0)return t;if(e.replyTo.kind===`callback`){let n={callId:e.callId,subagentName:e.subagentName,token:e.replyTo.token,url:e.replyTo.url};return{...t,[SessionCallbackKey.name]:n}}let n=t[ChannelKey.name];if(typeof n!=`object`||!n||Reflect.get(n,`kind`)!==SUBAGENT_ADAPTER_KIND||!isSubagentAdapterState(Reflect.get(n,`state`)))throw Error(`Delegated local turn is missing its subagent adapter binding.`);let r={...Reflect.get(n,`state`),callId:e.callId,parentContinuationToken:e.replyTo.token,subagentName:e.subagentName};return{...t,[ChannelKey.name]:{...n,state:r}}}async function postSettledTurnCallback(e){let{sessionId:t}=e;if(e.result.isError===!0){await postCallbackPayload({payload:{callId:e.result.callId,error:e.result.output,kind:`turn.failed`,outcome:e.result.outcome,sessionId:t,subagentName:e.result.subagentName},url:e.url});return}await postCallbackPayload({payload:{callId:e.result.callId,kind:`turn.completed`,outcome:e.result.outcome,output:e.result.output,sessionId:t,subagentName:e.result.subagentName},url:e.url})}async function postCallbackPayload(e){let t=await postSessionCallbackRequest({body:e.payload,url:e.url});if(!t.ok)throw Error(`Turn callback failed with HTTP ${t.status}.`)}async function resumeSettledTurnHook(e,t){try{await resumeHook(e,{kind:`runtime-action-result`,results:[t]})}catch(n){if(!HookNotFoundError.is(n))throw n;log.warn(`turn caller hook no longer exists`,{callId:t.callId,callerToken:e})}}export{bindTurnCallerContext,notifyCancelledTaskCallerStep,notifyTurnCallerStep,resolveInitialTurnCallerStep};
@@ -1,4 +1,4 @@
1
- import { a as conversationProjection, i as openConversationInputs, n as conversationReducer, o as callStatus, r as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-mP0M7SrL.js";
1
+ import { a as conversationProjection, i as openConversationInputs, n as conversationReducer, o as callStatus, r as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-B2Kne9z6.js";
2
2
 
3
3
  //#region src/client/tool-call-state.ts
4
4
  function toolCallState(conversation, callId, options = {}) {
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-mP0M7SrL.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-B2Kne9z6.js";
2
2
 
3
3
  export { useEveAgent };
@@ -0,0 +1,13 @@
1
+ import type { StubResult } from "#tool-stubs/types.js";
2
+ import type { ToolExecuteOptions } from "#tools/definition.js";
3
+ /** Tool inputs and approvals have already been checked before a stub can replace execution. */
4
+ export declare function executeWithToolStub(tool: string, input: unknown, options: ToolExecuteOptions, execute: () => unknown): unknown;
5
+ /** The connection wrapper checks operation inputs and approvals before requesting a stub. */
6
+ export declare function connectionToolStub(tool: string, input: unknown, callId: string): Promise<StubResult>;
7
+ /** Record errors converting stub responses so eval verification can detect them. */
8
+ export declare function recordToolStubFailure(tool: string, callId: string | undefined, turnId?: string): Promise<void>;
9
+ /** Record stub failures even when the caller recovers with fallback output. */
10
+ export declare function observeToolOutput<T>(tool: string, calls: readonly {
11
+ readonly callId: string;
12
+ readonly turnId?: string;
13
+ }[], project: () => T | Promise<T>, recover?: (error: unknown) => T): Promise<T>;
@@ -0,0 +1 @@
1
+ import{contextStorage}from"#context/container.js";import{SessionKey,ToolStubsKey}from"#context/keys.js";import{ToolStubPlaybackKey}from"#context/providers/tool-stubs-key.js";import{findStubTarget,stubCallId}from"#tool-stubs/target.js";import{isAsyncIterable}from"#shared/async-iterable.js";import{toolStubOutput}from"#tool-stubs/output.js";function executeWithToolStub(e,t,n,r){let i=contextStubCall(e,t,n.toolCallId);return i===void 0?r():executeStubbedTool(i.playback,i.call,n,r)}async function*executeStubbedTool(e,t,n,r){n.abortSignal?.throwIfAborted();let i=await e.call(t);if(i.kind===`error`)throw Error(i.error);if(i.kind===`stub`){yield toolStubOutput(i.outcome);return}let a=await r();isAsyncIterable(a)?yield*a:yield a}async function connectionToolStub(e,t,n){let r=contextStubCall(e,t,n);return r===void 0?{kind:`real`}:await r.playback.call(r.call)}function contextStubCall(e,t,n){let r=contextStorage.getStore();if(r===void 0)return;let i=findStubTarget(r.get(ToolStubsKey),e);if(i===void 0)return;let a=r.require(SessionKey);return{playback:r.require(ToolStubPlaybackKey),call:{tool:i.tool,input:t,callId:stubCallId(a.sessionId,a.turn.id,n)}}}async function recordToolStubFailure(e,t,n){let r=contextStorage.getStore(),i=r?.get(ToolStubsKey);if(i===void 0||t===void 0||e!==`connection_execute`&&findStubTarget(i,e)===void 0)return;let a=r.require(SessionKey);await r.require(ToolStubPlaybackKey).fail(stubCallId(a.sessionId,n??a.turn.id,t),`Stubbed tool "${e}" failed during output processing.`)}async function observeToolOutput(e,t,n,r){try{return await n()}catch(n){try{for(let n of t)await recordToolStubFailure(e,n.callId,n.turnId)}catch(e){throw AggregateError([n,e],`Tool output processing and failure reporting failed.`,{cause:n})}if(r!==void 0)return r(n);throw n}}export{connectionToolStub,executeWithToolStub,observeToolOutput,recordToolStubFailure};
@@ -0,0 +1,4 @@
1
+ import type { JsonValue } from "#shared/json.js";
2
+ import type { ToolStubOutcome } from "#tool-stubs/types.js";
3
+ /** Throws at the tool boundary, after the outcome has been recorded for replay. */
4
+ export declare function toolStubOutput(outcome: ToolStubOutcome): JsonValue;
@@ -0,0 +1 @@
1
+ function toolStubOutput(e){if(e.throw!==void 0){let t=Error(e.throw.message);throw t.name=e.throw.name??`Error`,t}return e.response}export{toolStubOutput};
@@ -0,0 +1,15 @@
1
+ import type { StubCall, StubResult, ToolStub } from "#tool-stubs/types.js";
2
+ /**
3
+ * Selects stub outcomes and advances their sequences.
4
+ * The surrounding workflow orders calls and restores progress on replay.
5
+ */
6
+ export declare class StubPlayback {
7
+ private readonly rules;
8
+ private readonly results;
9
+ private readonly positions;
10
+ constructor(rules: readonly ToolStub[]);
11
+ get matchedRuleCount(): number;
12
+ call(call: StubCall): StubResult;
13
+ private record;
14
+ fail(callId: string, error: string): StubResult;
15
+ }
@@ -0,0 +1 @@
1
+ import{isObject}from"#shared/guards.js";import{createStubValidator}from"#tool-stubs/schema.js";var StubPlayback=class{rules;results=new Map;positions=new Map;constructor(e){this.rules=e.map(e=>({...e,constraints:Object.entries(e.match??{}).map(([t,n])=>{try{return{property:t,validator:createStubValidator(n)}}catch(n){throw Error(`Could not create validator for matcher "${t}" in tool stub "${e.id}".`,{cause:n})}})}))}get matchedRuleCount(){return this.positions.size}call(e){let t=this.results.get(e.callId);if(t!==void 0)return t;if(this.results.size>=1e4)return{kind:`error`,error:`Tool stub session exceeded 10,000 calls. Start a new eval session.`};let n=this.rules.filter(t=>t.tool===e.tool);if(e.persistent&&n.some(e=>e.constraints.length>0))return this.record(e,{kind:`error`,error:`Persistent tool "${e.tool}" requires an unconditional stub.`});let r=n.find(t=>t.constraints.every(({property:t,validator:n})=>isObject(e.input)&&Object.hasOwn(e.input,t)&&n.validate(e.input[t]).valid));if(r===void 0)return this.record(e,{kind:`real`});let i=r.outcomes??[r.outcome],a=Math.min(this.positions.get(r.id)??0,i.length-1);return this.positions.set(r.id,a+1),this.record(e,{kind:`stub`,ruleId:r.id,position:a,outcome:i[a]})}record(e,t){return this.results.set(e.callId,t),t}fail(e,t){return this.results.get(e)?.kind===`stub`?{kind:`error`,error:t}:{kind:`real`}}};export{StubPlayback};
@@ -0,0 +1,3 @@
1
+ import type { ToolStub } from "#tool-stubs/types.js";
2
+ /** Validates stubs before creating the session. */
3
+ export declare function parseToolStubs(value: unknown): readonly ToolStub[];
@@ -0,0 +1 @@
1
+ import{z}from"#compiled/zod/index.js";import{parseJsonValue}from"#shared/json.js";import{createStubValidator,validateStubConstraint}from"#tool-stubs/schema.js";const ruleSchema=z.strictObject({id:z.string().min(1),tool:z.string().min(1),match:z.record(z.string(),z.union([z.boolean(),z.record(z.string(),z.json())])).optional()}),outcomeSchema=z.union([z.strictObject({response:z.json()}),z.strictObject({throw:z.strictObject({message:z.string(),name:z.string().min(1).optional()})})]),toolStubsSchema=z.array(z.union([ruleSchema.extend({outcome:outcomeSchema}),ruleSchema.extend({outcomes:z.tuple([outcomeSchema]).rest(outcomeSchema)})])).max(100);function parseToolStubs(e){boundStubConfiguration(e);let t=toolStubsSchema.parse(parseJsonValue(e)),n=new Set;for(let e of t){if(n.has(e.id))throw Error(`Duplicate tool stub id "${e.id}".`);if(n.add(e.id),[`connection_execute`,`connection_search`].includes(e.tool.split(`/`).at(-1)))throw Error(`Cannot stub connection_execute or connection_search. Stub a specific connection operation, such as linear__list_issues.`);for(let[t,n]of Object.entries(e.match??{})){validateStubConstraint(n,e.id,t);try{createStubValidator(n)}catch(n){throw Error(`Could not create matcher "${t}" in tool stub "${e.id}".`,{cause:n})}}}return t}function boundStubConfiguration(e){let t=[{value:e,depth:0}],n=0,r=0;for(;t.length>0;){let e=t.pop();if(++n>2e4||e.depth>32)throw Error(`Tool stubs exceed the size or nesting limit.`);if(typeof e.value==`string`&&(r+=e.value.length),e.value!==null&&typeof e.value==`object`)for(let[n,i]of Object.entries(e.value)){if(n===`__proto__`)throw Error(`Tool stubs cannot contain prototype keys.`);r+=n.length,t.push({value:i,depth:e.depth+1})}if(r>1e6)throw Error(`Tool stubs exceed the size or nesting limit.`)}}export{parseToolStubs};
@@ -0,0 +1,4 @@
1
+ import { Validator } from "#compiled/@cfworker/json-schema/index.js";
2
+ import type { JsonObject } from "#shared/json.js";
3
+ export declare function validateStubConstraint(value: unknown, ruleId: string, property: string): void;
4
+ export declare function createStubValidator(value: JsonObject | boolean): Validator;
@@ -0,0 +1 @@
1
+ import{Validator}from"#compiled/@cfworker/json-schema/index.js";const schema={$ref:`#`},schemaList={type:`array`,minItems:1,items:schema},propertyName={type:`string`,not:{enum:Object.getOwnPropertyNames(Object.prototype)}},schemaMap={type:`object`,propertyNames:propertyName,additionalProperties:schema},strings={type:`array`,uniqueItems:!0,items:propertyName},nonnegativeInteger={type:`integer`,minimum:0},jsonType={enum:[`array`,`boolean`,`integer`,`null`,`number`,`object`,`string`]},constraintSchema=new Validator({anyOf:[{type:`boolean`},{type:`object`,additionalProperties:!1,properties:{type:{anyOf:[jsonType,{type:`array`,minItems:1,uniqueItems:!0,items:jsonType}]},const:{type:[`string`,`number`,`boolean`,`null`]},enum:{type:`array`,minItems:1,uniqueItems:!0,items:{type:[`string`,`number`,`boolean`,`null`]}},title:{type:`string`},description:{type:`string`},default:!0,minimum:{type:`number`},maximum:{type:`number`},exclusiveMinimum:{type:`number`},exclusiveMaximum:{type:`number`},minLength:nonnegativeInteger,maxLength:nonnegativeInteger,pattern:{type:`string`,format:`regex`},minItems:nonnegativeInteger,maxItems:nonnegativeInteger,items:schema,prefixItems:schemaList,contains:schema,minProperties:nonnegativeInteger,maxProperties:nonnegativeInteger,properties:schemaMap,propertyNames:schema,required:strings,additionalProperties:schema,allOf:schemaList,anyOf:schemaList,oneOf:schemaList,not:schema,if:schema,then:schema,else:schema}}]},`2020-12`);function validateStubConstraint(e,t,n){let r=constraintSchema.validate(e);if(!r.valid){let e=r.errors.at(-1),i=e.keyword===`false`?`Unsupported JSON Schema keyword.`:e.error;throw Error(`Invalid matcher "${n}" in tool stub "${t}" at ${e.instanceLocation}: ${i}`)}}function createStubValidator(e){return new Validator(structuredClone(e),`2020-12`)}export{createStubValidator,validateStubConstraint};
@@ -0,0 +1,8 @@
1
+ import type { StubScope } from "#tool-stubs/types.js";
2
+ /** Qualify names for stub matching without changing the names sent to the model. */
3
+ export declare function stubToolPath(scope: StubScope | undefined, tool: string): string;
4
+ export declare function findStubTarget(scope: StubScope | undefined, tool: string): {
5
+ scope: StubScope;
6
+ tool: string;
7
+ } | undefined;
8
+ export declare function stubCallId(sessionId: string, turnId: string, callId: string): string;
@@ -0,0 +1 @@
1
+ function stubToolPath(e,t){return e?.agentPath===void 0?t:`${e.agentPath}/${t}`}function findStubTarget(e,t){if(e!==void 0)return t=stubToolPath(e,t),e.rules.some(e=>e.tool===t)?{scope:e,tool:t}:void 0}function stubCallId(e,t,n){return`${e}:${t}:${n}`}export{findStubTarget,stubCallId,stubToolPath};
@@ -0,0 +1,56 @@
1
+ import type { JsonObject, JsonValue } from "#shared/json.js";
2
+ /** Return JSON or immediately throw an error for a matching tool call. */
3
+ export type ToolStubOutcome = {
4
+ readonly response: JsonValue;
5
+ readonly throw?: never;
6
+ } | {
7
+ readonly response?: never;
8
+ readonly throw: {
9
+ readonly message: string;
10
+ /** Defaults to Error. Sets the name, not a custom JavaScript class. */
11
+ readonly name?: string;
12
+ };
13
+ };
14
+ /** Stub outcomes selected by tool name and input fields. */
15
+ export type ToolStub = {
16
+ readonly id: string;
17
+ /** Use list_tasks for a root tool or researcher/list_tasks for a local subagent's tool. */
18
+ readonly tool: string;
19
+ /** Each named input property must exist and satisfy its JSON Schema. */
20
+ readonly match?: Readonly<Record<string, JsonObject | boolean>>;
21
+ } & ({
22
+ readonly outcome: ToolStubOutcome;
23
+ readonly outcomes?: never;
24
+ } | {
25
+ readonly outcome?: never;
26
+ readonly outcomes: readonly [ToolStubOutcome, ...ToolStubOutcome[]];
27
+ });
28
+ export interface StubCall {
29
+ /** Combines the session, turn, and tool call IDs. */
30
+ readonly callId: string;
31
+ readonly tool: string;
32
+ readonly input: unknown;
33
+ readonly persistent?: boolean;
34
+ }
35
+ export type StubResult = {
36
+ readonly kind: "real";
37
+ } | {
38
+ readonly kind: "error";
39
+ readonly error: string;
40
+ } | {
41
+ readonly kind: "stub";
42
+ readonly ruleId: string;
43
+ readonly position: number;
44
+ readonly outcome: ToolStubOutcome;
45
+ };
46
+ /** Rules and workflow routing set by the server after it authorizes tool stubs. */
47
+ export interface StubScope {
48
+ readonly token: string;
49
+ readonly rules: readonly ToolStub[];
50
+ readonly rootSessionId?: string;
51
+ readonly agentPath?: string;
52
+ }
53
+ export declare const STUB_CONTEXT_KEY = "eve.toolStubs";
54
+ export declare const STUB_MATCHES_NAMESPACE = "eve.tool-stubs.matches";
55
+ export declare const STUB_FAILURE_NAMESPACE = "eve.tool-stubs.failure";
56
+ export declare const stubResponseNamespace: (callId: string) => string;
@@ -0,0 +1 @@
1
+ const STUB_CONTEXT_KEY=`eve.toolStubs`,STUB_MATCHES_NAMESPACE=`eve.tool-stubs.matches`,STUB_FAILURE_NAMESPACE=`eve.tool-stubs.failure`,stubResponseNamespace=e=>`eve.tool-stubs.${e}`;export{STUB_CONTEXT_KEY,STUB_FAILURE_NAMESPACE,STUB_MATCHES_NAMESPACE,stubResponseNamespace};
@@ -0,0 +1,6 @@
1
+ import type { ResolvedAgentGraphBundle } from "#runtime/graph.js";
2
+ import type { ToolStub } from "#tool-stubs/types.js";
3
+ export declare class InvalidToolStubTargetError extends Error {
4
+ }
5
+ /** Check compiled tools without running dynamic resolvers or contacting connections. */
6
+ export declare function validateToolStubTargets(rules: readonly ToolStub[], graph: ResolvedAgentGraphBundle): void;
@@ -0,0 +1 @@
1
+ var InvalidToolStubTargetError=class extends Error{};function validateToolStubTargets(e,t){for(let n of e)if(!hasToolPath(t,n.tool.split(`/`)))throw new InvalidToolStubTargetError(`Tool stub "${n.id}" names an unknown or unsupported tool path "${n.tool}".`)}function hasToolPath(e,t){if(t.some(e=>e.length===0))return!1;let n=e.root;for(let[r,i]of t.entries()){let a=n.turnAgent.tools.find(e=>e.name===i);if(r===t.length-1)return a===void 0?n.agent.dynamicToolResolvers.some(e=>e.slug!==`connection_tools`&&(e.extensionNamespace===void 0||i.startsWith(`${e.extensionNamespace}__`)))||n.subagentRegistry.dynamicResolvers.some(e=>e.name===i)||i.includes(`__`)&&((n.agent.dynamicConnectionResolvers?.length??0)>0||n.agent.connections.some(e=>i.startsWith(`${e.connectionName}__`))):a.behavior?.handling?.kind!==`provider-tool`;if(a===void 0)return n.subagentRegistry.dynamicResolvers.some(e=>e.name===i);let o=a.behavior?.handling;if(o?.kind!==`dispatch`||o.target.kind!==`subagent-call`&&o.target.kind!==`self-agent-call`)return!1;n=e.nodesByNodeId.get(o.target.nodeId)}return!1}export{InvalidToolStubTargetError,validateToolStubTargets};
@@ -1 +1 @@
1
- async function executeAskQuestionTool(e,t){"use workflow";return toAskQuestionOutput(await t.ask(toAskQuestionRequest(e)))}function toAskQuestionRequest(e){let t=e.options?.map(e=>({description:e.description,id:e.label,label:e.label}));return{allowFreeform:!0,display:t===void 0?`text`:`select`,prompt:e.question,...t!==void 0&&{options:t}}}function toAskQuestionOutput(e){switch(e.status){case`answered`:return{answer:e.optionId??e.text??``,status:`answered`};case`cancelled`:return{interrupted:!0};case`unavailable`:return{status:`unavailable`}}}executeAskQuestionTool.workflowId=`workflow//eve@0.74.0//executeAskQuestionTool`;export{executeAskQuestionTool,toAskQuestionOutput,toAskQuestionRequest};
1
+ async function executeAskQuestionTool(e,t){"use workflow";return toAskQuestionOutput(await t.ask(toAskQuestionRequest(e)))}function toAskQuestionRequest(e){let t=e.options?.map(e=>({description:e.description,id:e.label,label:e.label}));return{allowFreeform:!0,display:t===void 0?`text`:`select`,prompt:e.question,...t!==void 0&&{options:t}}}function toAskQuestionOutput(e){switch(e.status){case`answered`:return{answer:e.optionId??e.text??``,status:`answered`};case`cancelled`:return{interrupted:!0};case`unavailable`:return{status:`unavailable`}}}executeAskQuestionTool.workflowId=`workflow//eve@0.75.1//executeAskQuestionTool`;export{executeAskQuestionTool,toAskQuestionOutput,toAskQuestionRequest};
@@ -1 +1 @@
1
- import{sleep}from"#compiled/@workflow/core/index.js";async function executeSleepTool(e,t){"use workflow";let n=new Promise(e=>t.abortSignal.addEventListener(`abort`,()=>e(`interrupted`),{once:!0})),r=sleep(Math.ceil(e.seconds*1e3)).then(()=>`elapsed`);return await Promise.race([r,n])===`elapsed`?{waitedSeconds:e.seconds}:{interrupted:!0}}executeSleepTool.workflowId=`workflow//eve@0.74.0//executeSleepTool`;export{executeSleepTool};
1
+ import{sleep}from"#compiled/@workflow/core/index.js";async function executeSleepTool(e,t){"use workflow";let n=new Promise(e=>t.abortSignal.addEventListener(`abort`,()=>e(`interrupted`),{once:!0})),r=sleep(Math.ceil(e.seconds*1e3)).then(()=>`elapsed`);return await Promise.race([r,n])===`elapsed`?{waitedSeconds:e.seconds}:{interrupted:!0}}executeSleepTool.workflowId=`workflow//eve@0.75.1//executeSleepTool`;export{executeSleepTool};
@@ -1,4 +1,4 @@
1
- import { a as conversationProjection, i as openConversationInputs, n as conversationReducer, o as callStatus, r as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-DOOXadF0.js";
1
+ import { a as conversationProjection, i as openConversationInputs, n as conversationReducer, o as callStatus, r as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-DK_T88EP.js";
2
2
 
3
3
  //#region src/client/tool-call-state.ts
4
4
  function toolCallState(conversation, callId, options = {}) {
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-DOOXadF0.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-DK_T88EP.js";
2
2
 
3
3
  export { useEveAgent };
@@ -123,7 +123,7 @@ Note: consider the privacy, confidentiality, and user-experience implications fo
123
123
 
124
124
  A delegated subagent publishes progress on its own child-session stream. When a subagent tool call or a workflow tool's `ctx.agent` opens a session, the parent emits `agent.started` with the call's `callId` and `turnId`, its `taskId` when the call runs as a task, the child's `sessionId`, and a `streamPath` that a client follows with `session.agent(started).stream()`. A subagent tool call is a [task](#task-events) whose `task.started` has `kind: "agent"`: its `task.started` and `task.settled` carry the call, and `task.settled.data.output` is the child's reply. A call that fails before the child session opens has no `agent.started`. A settled call does not end the child session; later calls with the same `taskId` reach it.
125
125
 
126
- A question or sign-in from inside a running call does not end the turn. This covers a workflow tool's `ctx.ask()`, including the built-in `ask_question` tool, and a delegated subagent's question or sign-in. The stream emits `input.requested` or `authorization.required`, then `turn.waiting` with `on: "input"` and the open turn's `turnId`. After the answer or sign-in, the turn resumes with the next `step.started` for the same `turnId`, and only `turn.completed`, `turn.failed`, or `turn.cancelled` ends it. When you answer a question that belongs to a workflow tool or a subagent, the session you answer on emits `input.resolved` for it as it routes the answer down. While other relayed questions are still pending, it then emits `turn.waiting` with `on: "input"` again. If the workflow tool run that relayed a question or approval ends before anyone answers, that session emits `input.resolved` with `outcome: "cancelled"` for it. This covers the run's own `ctx.ask()` questions and requests from sessions it opened with `ctx.agent`. A cancelled turn does the same for every question or approval the session relays. A sign-in or tool approval the turn raises itself holds it the same way, also with `on: "input"`. A message from the same person steers the turn and cancels the request: a sign-in reports `authorization.completed` with `outcome: "declined"`, and an approval reports `input.resolved` with `outcome: "ignored"`. Messages from other people wait until the turn ends. Cancelling the turn ends both: a held sign-in reports `authorization.completed` with `outcome: "declined"`, and a held approval reports `input.resolved` with `outcome: "cancelled"`.
126
+ A question or sign-in from inside a running call does not end the turn. This covers a workflow tool's `ctx.ask()`, including the built-in `ask_question` tool, and a delegated subagent's question or sign-in. The stream emits `input.requested` or `authorization.required`, then `turn.waiting` with `on: "input"` and the open turn's `turnId`. After the answer or sign-in, the turn resumes with the next `step.started` for the same `turnId`, and only `turn.completed`, `turn.failed`, or `turn.cancelled` ends it. When you answer a question that belongs to a workflow tool or a subagent, the session you answer on emits `input.resolved` for it as it routes the answer down. A subagent's tool approval instead stays open until the subagent resolves it, and the session relays that subagent's `input.resolved`. While other relayed questions are still pending, it then emits `turn.waiting` with `on: "input"` again. If the workflow tool run that relayed a question or approval ends before anyone answers, that session emits `input.resolved` with `outcome: "cancelled"` for it. This covers the run's own `ctx.ask()` questions and requests from sessions it opened with `ctx.agent`. A cancelled turn does the same for every question or approval the session relays. A sign-in or tool approval the turn raises itself holds it the same way, also with `on: "input"`. A message from the same person steers the turn and cancels the request: a sign-in reports `authorization.completed` with `outcome: "declined"`, and an approval reports `input.resolved` with `outcome: "ignored"`. Messages from other people wait until the turn ends. Cancelling the turn ends both: a held sign-in reports `authorization.completed` with `outcome: "declined"`, and a held approval reports `input.resolved` with `outcome: "cancelled"`.
127
127
 
128
128
  ### Task events
129
129
 
@@ -219,7 +219,7 @@ Message sends default to `"steer"`. Before assistant output begins, eve interrup
219
219
 
220
220
  If the session is waiting on a human-in-the-loop approval, respond with the channel’s Approve or Cancel controls. Text that doesn't match an option doesn't approve the call. From the person the turn serves, it steers the turn and cancels the approval, even when sent with `turnPolicy: "queue"`, since the turn can't end until that person acts; from anyone else, it waits until the turn ends. If they had already approved some calls in the batch, those calls still run. Cancelling the turn withdraws the approval, and a later answer to it approves nothing.
221
221
 
222
- A pending `ctx.ask()` question from a tool, such as `ask_question`, can be answered with plain text. When it is the only pending question, a message that matches an option answers it, and so does any message when the question allows free text. The stream records that message as `message.received`, carrying its delivery id, just before the `input.resolved` it produces. Otherwise eve does not guess which question the text addresses: the message follows the normal `turnPolicy`. A steering message withdraws the questions of the `execute` workflow tool calls the turn waits on, which resolve as `cancelled`; a task's questions stay open. Questions from subagents always need a structured response. Use structured responses to target requests unambiguously.
222
+ A pending prompt, whether a `ctx.ask()` question from a tool such as `ask_question`, a tool approval, or a session-limit prompt, can be answered with plain text, including prompts proxied from a subagent. A message answers the first open prompt, as described in [Several requests at once](/docs/human-in-the-loop#several-requests-at-once): a reply that matches one of its options, such as `approve` or `continue`, answers it as if the sender had pressed that option, and so does any message when the prompt allows free text. Send one message per prompt to answer several. The stream records a message that answers a question as `message.received`, carrying its delivery id, just before the `input.resolved` it produces. A message that doesn't answer the first open prompt follows the normal `turnPolicy`. A steering message withdraws the questions of the `execute` workflow tool calls the turn waits on, which resolve as `cancelled`; a task's questions stay open. Use structured responses to target requests unambiguously.
223
223
 
224
224
  A structured response matches any currently pending request by ID, not only the newest batch. It becomes stale only after that request was answered, cleared, or cancelled. eve delivers a stale response to the model as a new user message, and the model decides whether the old selection still matters. A stale approval never authorizes the earlier tool call; the model must request the action and approval again if they are still needed.
225
225
 
@@ -1,5 +1,14 @@
1
1
  {
2
2
  "title": "Evals",
3
3
  "defaultOpen": false,
4
- "pages": ["overview", "cases", "assertions", "judge", "targets", "reporters", "running"]
4
+ "pages": [
5
+ "overview",
6
+ "cases",
7
+ "assertions",
8
+ "tool-stubs",
9
+ "judge",
10
+ "targets",
11
+ "reporters",
12
+ "running"
13
+ ]
5
14
  }
@@ -7,6 +7,8 @@ An eval is a scored check that runs your agent against real sessions and grades
7
7
 
8
8
  Evals exercise the same HTTP surface your users hit. The runner boots (or targets) a real agent server, drives sessions through the [TypeScript client](../guides/client/overview) protocol, and grades what comes back, so a passing eval means the agent booted, accepted a request, and produced the result you asserted.
9
9
 
10
+ Define [tool stubs](./tool-stubs) in your eval to control tool results, then assert on the agent's tool calls and responses.
11
+
10
12
  ## `defineEval`
11
13
 
12
14
  eve discovers evals under the app-root `evals/` directory, in `.eval.ts` files. Each file is one eval by default. A file can also default-export an array to fan out over a dataset (see [Cases](./cases)). The file path is the eval's identity, so you don't author an `id` or `name`. Directories group related evals (`evals/weather/brooklyn-forecast.eval.ts` becomes id `weather/brooklyn-forecast`).