eve 0.52.1 → 0.52.3

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 (240) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/src/channel/types.d.ts +1 -0
  3. package/dist/src/chunks/{use-eve-agent-CxkGSusZ.js → use-eve-agent-BR8EpIOX.js} +46 -19
  4. package/dist/src/chunks/{use-eve-agent-Crmh_YB-.js → use-eve-agent-XnfjQt1Z.js} +46 -19
  5. package/dist/src/cli/commands/deploy.js +1 -1
  6. package/dist/src/cli/commands/extension-init.d.ts +2 -1
  7. package/dist/src/cli/commands/extension-init.js +1 -1
  8. package/dist/src/cli/commands/init.d.ts +2 -13
  9. package/dist/src/cli/commands/init.js +1 -1
  10. package/dist/src/cli/dev/run-interactive-ui.d.ts +3 -0
  11. package/dist/src/cli/dev/run-interactive-ui.js +1 -1
  12. package/dist/src/cli/dev/tui/prompt-command-handler.js +1 -1
  13. package/dist/src/cli/dev/tui/runner.d.ts +6 -0
  14. package/dist/src/cli/dev/tui/runner.js +1 -1
  15. package/dist/src/cli/dev/tui/setup-commands.d.ts +5 -3
  16. package/dist/src/cli/dev/tui/setup-commands.js +2 -2
  17. package/dist/src/cli/dev/tui/status-line.js +1 -1
  18. package/dist/src/cli/dev/tui/subagent-pump.js +1 -1
  19. package/dist/src/cli/dev/tui/tui.d.ts +4 -0
  20. package/dist/src/cli/dev/tui/tui.js +1 -1
  21. package/dist/src/cli/run.d.ts +1 -1
  22. package/dist/src/cli/run.js +2 -2
  23. package/dist/src/cli/telemetry/index.d.ts +15 -0
  24. package/dist/src/cli/telemetry/index.js +2 -2
  25. package/dist/src/client/eve-agent-store.js +1 -1
  26. package/dist/src/client/ndjson.js +1 -1
  27. package/dist/src/client/session.js +1 -1
  28. package/dist/src/compiled/.vendor-stamp.json +1 -1
  29. package/dist/src/compiler/compile-from-memory.d.ts +1 -0
  30. package/dist/src/compiler/compile-from-memory.js +1 -1
  31. package/dist/src/compiler/default-tool-policy.d.ts +6 -0
  32. package/dist/src/compiler/default-tool-policy.js +1 -0
  33. package/dist/src/compiler/extension-compatibility.d.ts +18 -18
  34. package/dist/src/compiler/extension-compatibility.js +1 -1
  35. package/dist/src/compiler/manifest.js +1 -1
  36. package/dist/src/compiler/normalize-agent-config.js +1 -1
  37. package/dist/src/compiler/normalize-manifest.js +1 -1
  38. package/dist/src/context/build-dynamic-tools.d.ts +2 -1
  39. package/dist/src/context/build-dynamic-tools.js +1 -1
  40. package/dist/src/context/dynamic-tool-lifecycle.d.ts +3 -3
  41. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  42. package/dist/src/context/dynamic-tool-metadata.d.ts +1 -1
  43. package/dist/src/context/hook-lifecycle.js +1 -1
  44. package/dist/src/context/keys.d.ts +2 -0
  45. package/dist/src/context/keys.js +1 -1
  46. package/dist/src/evals/cli/eval.js +1 -1
  47. package/dist/src/eve-channel/index.js +1 -1
  48. package/dist/src/execution/activity-events.d.ts +1 -0
  49. package/dist/src/execution/activity-events.js +1 -1
  50. package/dist/src/execution/node-step.js +1 -1
  51. package/dist/src/execution/sandbox/prewarm.js +1 -1
  52. package/dist/src/execution/session-activity-projection.js +1 -1
  53. package/dist/src/execution/session-activity.js +1 -1
  54. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  55. package/dist/src/execution/tasks/parent/dispatch.js +1 -1
  56. package/dist/src/execution/tasks/parent/task-cancel.d.ts +2 -2
  57. package/dist/src/execution/tasks/parent/task-cancel.js +1 -1
  58. package/dist/src/execution/tasks/parent/tool-execution.js +1 -1
  59. package/dist/src/execution/tools/sleep-workflow.js +1 -1
  60. package/dist/src/execution/workflow-runtime.js +1 -1
  61. package/dist/src/execution/workflow-steps.js +1 -1
  62. package/dist/src/execution/workflow-webhook-route.js +1 -1
  63. package/dist/src/framework/sources/registry.js +1 -1
  64. package/dist/src/harness/action-presentation.d.ts +13 -0
  65. package/dist/src/harness/action-presentation.js +1 -0
  66. package/dist/src/harness/approval-delivery-coordinator.js +1 -1
  67. package/dist/src/harness/compaction-prompt.d.ts +1 -0
  68. package/dist/src/harness/compaction-prompt.js +1 -1
  69. package/dist/src/harness/compaction.js +1 -1
  70. package/dist/src/harness/coordination.js +1 -1
  71. package/dist/src/harness/emission.d.ts +1 -6
  72. package/dist/src/harness/emission.js +1 -1
  73. package/dist/src/harness/execute-tool.d.ts +2 -1
  74. package/dist/src/harness/finish-reason.d.ts +3 -0
  75. package/dist/src/harness/finish-reason.js +1 -0
  76. package/dist/src/harness/provider-tool-schemas.d.ts +1 -0
  77. package/dist/src/harness/provider-tool-schemas.js +1 -1
  78. package/dist/src/harness/step-hooks.js +1 -1
  79. package/dist/src/harness/stream-actions.d.ts +2 -2
  80. package/dist/src/harness/stream-actions.js +1 -1
  81. package/dist/src/harness/tool-call-input-errors.d.ts +4 -3
  82. package/dist/src/harness/tool-call-input-errors.js +1 -1
  83. package/dist/src/harness/tool-loop.js +2 -2
  84. package/dist/src/harness/tool-presentation.d.ts +5 -0
  85. package/dist/src/harness/tool-presentation.js +1 -0
  86. package/dist/src/harness/turn-client-context.d.ts +1 -0
  87. package/dist/src/harness/workflow-lifecycle.d.ts +2 -3
  88. package/dist/src/harness/workflow-lifecycle.js +1 -1
  89. package/dist/src/internal/application/compiled-artifacts.d.ts +3 -0
  90. package/dist/src/internal/application/compiled-artifacts.js +1 -1
  91. package/dist/src/internal/application/package.js +1 -1
  92. package/dist/src/internal/authored-definition/core.js +1 -1
  93. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  94. package/dist/src/internal/authored-module-conditions.d.ts +2 -0
  95. package/dist/src/internal/authored-module-conditions.js +1 -0
  96. package/dist/src/internal/authored-module-loader.d.ts +3 -0
  97. package/dist/src/internal/authored-module-loader.js +3 -3
  98. package/dist/src/internal/authored-module-map-loader.d.ts +3 -1
  99. package/dist/src/internal/authored-module-map-loader.js +1 -1
  100. package/dist/src/internal/authored-runtime-modules.d.ts +2 -0
  101. package/dist/src/internal/authored-runtime-modules.js +1 -1
  102. package/dist/src/internal/bundler/nitro-rolldown.d.ts +1 -0
  103. package/dist/src/internal/bundler/nitro-rolldown.js +1 -1
  104. package/dist/src/internal/nitro/development-generation.d.ts +2 -0
  105. package/dist/src/internal/nitro/development-generation.js +1 -1
  106. package/dist/src/internal/nitro/host/configure-nitro-routes.js +1 -1
  107. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  108. package/dist/src/internal/nitro/host/prepare-application-host.js +1 -1
  109. package/dist/src/internal/nitro/routes/channel-request-instrumentation.js +1 -1
  110. package/dist/src/internal/node-esm-compat-banner.d.ts +19 -6
  111. package/dist/src/internal/node-esm-compat-banner.js +2 -2
  112. package/dist/src/internal/workflow-bundle/builder-support.d.ts +5 -0
  113. package/dist/src/internal/workflow-bundle/builder.js +2 -2
  114. package/dist/src/internal/workflow-bundle/dynamic-tool-transform.d.ts +1 -1
  115. package/dist/src/internal/workflow-bundle/dynamic-tool-transform.js +1 -1
  116. package/dist/src/internal/workflow-bundle/workflow-core-shim.js +1 -1
  117. package/dist/src/protocol/activity.d.ts +6 -0
  118. package/dist/src/protocol/activity.js +1 -1
  119. package/dist/src/protocol/message.d.ts +13 -1
  120. package/dist/src/protocol/message.js +1 -1
  121. package/dist/src/public/channels/slack/activity-plan.js +1 -1
  122. package/dist/src/public/channels/slack/activity.js +2 -2
  123. package/dist/src/public/channels/slack/connections.d.ts +2 -2
  124. package/dist/src/public/channels/slack/connections.js +1 -1
  125. package/dist/src/public/memory/file/backends/default.js +1 -1
  126. package/dist/src/public/models/openai/chatgpt/credential-store.d.ts +6 -0
  127. package/dist/src/public/models/openai/chatgpt/credential-store.js +1 -0
  128. package/dist/src/public/models/openai/chatgpt/model.d.ts +1 -1
  129. package/dist/src/public/models/openai/chatgpt/oauth.d.ts +20 -0
  130. package/dist/src/public/models/openai/chatgpt/oauth.js +1 -0
  131. package/dist/src/public/models/openai/chatgpt/token-broker.d.ts +4 -3
  132. package/dist/src/public/models/openai/chatgpt/token-broker.js +1 -1
  133. package/dist/src/public/models/openai/chatgpt/transport.d.ts +1 -2
  134. package/dist/src/public/models/openai/index.d.ts +3 -4
  135. package/dist/src/public/tools/agent.d.ts +1 -0
  136. package/dist/src/public/tools/agent.js +1 -0
  137. package/dist/src/public/tools/ask-question.d.ts +1 -0
  138. package/dist/src/public/tools/ask-question.js +1 -0
  139. package/dist/src/public/tools/connection-search.d.ts +1 -0
  140. package/dist/src/public/tools/connection-search.js +1 -0
  141. package/dist/src/public/tools/index.d.ts +1 -1
  142. package/dist/src/public/tools/task-cancel.d.ts +1 -0
  143. package/dist/src/public/tools/task-cancel.js +1 -0
  144. package/dist/src/public/tools/task-update.d.ts +1 -0
  145. package/dist/src/public/tools/task-update.js +1 -0
  146. package/dist/src/runtime/connections/openapi-schema.js +1 -1
  147. package/dist/src/runtime/prompt/compose.js +1 -1
  148. package/dist/src/runtime/resolve-agent.js +1 -1
  149. package/dist/src/runtime/resolve-tool.js +1 -1
  150. package/dist/src/runtime/subagents/dynamic-agent-config.js +1 -1
  151. package/dist/src/runtime/types.d.ts +2 -0
  152. package/dist/src/self-modification/agent.js +1 -1
  153. package/dist/src/self-modification/extension/instructions.d.ts +1 -3
  154. package/dist/src/self-modification/extension/instructions.js +4 -2
  155. package/dist/src/self-modification/filesystem.js +1 -1
  156. package/dist/src/setup/flows/chatgpt-auth.d.ts +14 -2
  157. package/dist/src/setup/flows/chatgpt-auth.js +1 -1
  158. package/dist/src/setup/flows/model.d.ts +3 -2
  159. package/dist/src/setup/flows/model.js +1 -1
  160. package/dist/src/setup/flows/provider.js +1 -1
  161. package/dist/src/setup/flows/registry.d.ts +4 -0
  162. package/dist/src/setup/flows/registry.js +1 -1
  163. package/dist/src/setup/integrations/file-memory/vercel.d.ts +2 -2
  164. package/dist/src/setup/integrations/file-memory/vercel.js +1 -1
  165. package/dist/src/setup/scaffold/create/project.js +1 -1
  166. package/dist/src/shared/agent-definition.d.ts +7 -0
  167. package/dist/src/shared/boundary-hook-error.d.ts +4 -0
  168. package/dist/src/shared/boundary-hook-error.js +1 -0
  169. package/dist/src/{execution/activity-text.d.ts → shared/presentation-text.d.ts} +1 -1
  170. package/dist/src/shared/presentation-text.js +1 -0
  171. package/dist/src/svelte/index.js +1 -1
  172. package/dist/src/svelte/use-eve-agent.js +1 -1
  173. package/dist/src/tools/definition.d.ts +29 -0
  174. package/dist/src/tools/definition.js +1 -1
  175. package/dist/src/tools/durable-callbacks.d.ts +40 -9
  176. package/dist/src/tools/durable-callbacks.js +1 -1
  177. package/dist/src/tools/dynamic.d.ts +4 -1
  178. package/dist/src/tools/framework/agent-contract.js +1 -1
  179. package/dist/src/tools/provided/bash.js +1 -1
  180. package/dist/src/tools/provided/glob.js +1 -1
  181. package/dist/src/tools/provided/grep.js +1 -1
  182. package/dist/src/tools/provided/load-skill.js +1 -1
  183. package/dist/src/tools/provided/read-file.js +1 -1
  184. package/dist/src/tools/provided/web-fetch.js +1 -1
  185. package/dist/src/tools/provided/write-file.js +1 -1
  186. package/dist/src/tools/tool-label.d.ts +1 -0
  187. package/dist/src/tools/tool-label.js +1 -0
  188. package/dist/src/tracing/agent-action-instrumentation.js +1 -1
  189. package/dist/src/tracing/agent-approval-instrumentation.js +1 -1
  190. package/dist/src/tracing/agent-channel-delivery-instrumentation.js +1 -1
  191. package/dist/src/tracing/agent-otel-provider.js +2 -2
  192. package/dist/src/tracing/agent-otel-session-context.js +1 -1
  193. package/dist/src/tracing/agent-otel-usage.d.ts +10 -0
  194. package/dist/src/tracing/agent-otel-usage.js +1 -1
  195. package/dist/src/tracing/agent-span-naming.d.ts +1 -0
  196. package/dist/src/tracing/agent-span-naming.js +1 -0
  197. package/dist/src/tracing/agent-tool-instrumentation.js +1 -1
  198. package/dist/src/vue/index.js +1 -1
  199. package/dist/src/vue/use-eve-agent.js +1 -1
  200. package/docs/channels/slack.mdx +2 -0
  201. package/docs/concepts/built-in-tools.md +397 -68
  202. package/docs/concepts/default-harness.md +6 -0
  203. package/docs/concepts/sessions-runs-and-streaming.md +4 -0
  204. package/docs/connections/openapi.mdx +4 -0
  205. package/docs/connections/overview.mdx +1 -1
  206. package/docs/evals/running.mdx +2 -0
  207. package/docs/guides/client/continuations.mdx +11 -0
  208. package/docs/guides/client/streaming.mdx +7 -1
  209. package/docs/guides/dynamic-capabilities.md +5 -5
  210. package/docs/guides/frontend/overview.mdx +1 -1
  211. package/docs/guides/hooks.md +1 -1
  212. package/docs/guides/instrumentation.md +40 -1
  213. package/docs/guides/remote-agents.md +2 -0
  214. package/docs/instructions.mdx +1 -1
  215. package/docs/memory/custom-provider.md +4 -1
  216. package/docs/memory/file.md +25 -12
  217. package/docs/memory/overview.mdx +45 -13
  218. package/docs/reference/cli.md +6 -0
  219. package/docs/reference/telemetry.md +2 -2
  220. package/docs/reference/typescript-api.md +13 -9
  221. package/docs/sandbox.mdx +14 -2
  222. package/docs/subagents/index.mdx +8 -4
  223. package/docs/tools/overview.mdx +44 -2
  224. package/docs/tools/workflows.mdx +9 -1
  225. package/docs/tutorial/connect-a-warehouse.mdx +49 -26
  226. package/docs/tutorial/first-agent.mdx +20 -19
  227. package/docs/tutorial/guard-the-spend.mdx +4 -4
  228. package/docs/tutorial/how-it-runs.mdx +2 -3
  229. package/docs/tutorial/meta.json +2 -2
  230. package/docs/tutorial/query-sample-data.mdx +30 -19
  231. package/docs/tutorial/remember-definitions.mdx +5 -5
  232. package/docs/tutorial/run-analysis.mdx +155 -18
  233. package/docs/tutorial/ship-it.mdx +71 -81
  234. package/docs/tutorial/team-playbooks.mdx +10 -10
  235. package/package.json +32 -7
  236. package/dist/src/execution/activity-text.js +0 -1
  237. package/dist/src/internal/workflow-bundle/authored-workflow-modules.d.ts +0 -9
  238. package/dist/src/internal/workflow-bundle/authored-workflow-modules.js +0 -1
  239. package/dist/src/public/models/openai/chatgpt/codex-app-server.d.ts +0 -40
  240. package/dist/src/public/models/openai/chatgpt/codex-app-server.js +0 -1
@@ -141,6 +141,8 @@ export type ResolvedToolDefinition = Readonly<Omit<Optional<InternalToolDefiniti
141
141
  * rehydrated before entering this runtime-owned definition.
142
142
  */
143
143
  readonly inputSchema: ToolSchema | null;
144
+ /** Presentation projected from tool lifecycle values. */
145
+ readonly label?: import("#tools/definition.js").InternalToolLabelDefinition;
144
146
  /**
145
147
  * Optional validated runtime output schema.
146
148
  */
@@ -1 +1 @@
1
- import{defineAgent,defineDynamic}from"#public/index.js";const DEFAULT_SELF_MODIFICATION_MODEL=`anthropic/claude-sonnet-5`;function defineSelfModificationAgent(e={}){let t=e.model??`anthropic/claude-sonnet-5`;return defineDynamic({events:{"session.started":()=>process.env.EVE_DEV===`1`?defineAgent({description:`Delegate here when the developer asks to change this eve agent or its authored source. Describe the requested behavior change without guessing source paths or passing runtime skill paths under $HOME/.agents or /workspace/skills; the subagent discovers authored files under its /source mount. Treat requests for persistent changes to future behavior or capabilities as source-modification requests, even when the developer does not mention files or source code. Infer persistence from the request and conversation rather than waiting for phrases such as “modify your source.” For example, asking the agent to stop always doing something, add a capability, or change future responses calls for inspecting and editing the authored source instead of providing a one-turn workaround. Also delegate questions about which integrations, channels, connections, or capabilities are available to add: the subagent searches the eve registry and reports exact item addresses instead of guessing them. Resolve short follow-ups such as “yes” or “do it” against the preceding conversation. Source edits do not affect the caller’s current turn. After this subagent reports changes, do not invoke edited tools or attempt runtime verification until a new user turn. If whether the requested change should persist is genuinely ambiguous, ask one concise clarifying question.`,model:t}):null}})}var agent_default=defineSelfModificationAgent();export{DEFAULT_SELF_MODIFICATION_MODEL,agent_default as default,defineSelfModificationAgent};
1
+ import{defineAgent,defineDynamic}from"#public/index.js";const DEFAULT_SELF_MODIFICATION_MODEL=`anthropic/claude-sonnet-5`;function defineSelfModificationAgent(e={}){let t=e.model??`anthropic/claude-sonnet-5`;return defineDynamic({events:{"session.started":()=>process.env.EVE_DEV===`1`?defineAgent({description:`Delegate here when the developer asks to change this eve agent or its authored source. Describe the requested behavior change without guessing source paths or passing runtime skill paths under $HOME/.agents or /workspace/skills; the subagent discovers authored files under its /source mount. Treat requests for persistent changes to future behavior or capabilities as source-modification requests, even when the developer does not mention files or source code. Infer persistence from the request and conversation rather than waiting for phrases such as “modify your source.” For example, asking the agent to stop always doing something, add a capability, or change future responses calls for inspecting and editing the authored source instead of providing a one-turn workaround. Also delegate questions about which integrations, channels, connections, or capabilities are available to add: the subagent searches the eve registry and reports exact item addresses instead of guessing them. Delegate requests to investigate, diagnose, or optimize the agent's behavior from local traces to this subagent: it can inspect the invoking session's trace and make persistent source changes when warranted. Resolve short follow-ups such as “yes” or “do it” against the preceding conversation. Source edits do not affect the caller’s current turn. After this subagent reports changes, do not invoke edited tools or attempt runtime verification until a new user turn. If whether the requested change should persist is genuinely ambiguous, ask one concise clarifying question.`,model:t}):null}})}var agent_default=defineSelfModificationAgent();export{DEFAULT_SELF_MODIFICATION_MODEL,agent_default as default,defineSelfModificationAgent};
@@ -1,4 +1,2 @@
1
- declare const _default: {
2
- markdown: string;
3
- };
1
+ declare const _default: import("eve/instructions").DynamicSentinel<import("eve/instructions").DynamicInstructionsResult>;
4
2
  export default _default;
@@ -1,4 +1,4 @@
1
- import{defineInstructions}from"eve/instructions";var instructions_default=defineInstructions({markdown:`You are an expert coding assistant operating inside of an eve agent. You help users by reading files, editing code, and writing new files that shape the behavior of the agent itself.
1
+ import{defineDynamic,defineInstructions}from"eve/instructions";const instructions=`You are an expert coding assistant operating inside of an eve agent. You help users by reading files, editing code, and writing new files that shape the behavior of the agent itself.
2
2
 
3
3
  The source code of the eve agent is mounted read-write at /source. Use bash only for read-only discovery and available validation commands. Never modify source files with bash, sed, awk, redirection, or scripting. /source is the authored agent directory.
4
4
 
@@ -20,4 +20,6 @@ The eve framework documentation is mounted read-only at /eve-docs. Read the eve
20
20
 
21
21
  You cannot access application files outside the authored agent directory or run host binaries such as git, node, pnpm, or tsc.
22
22
 
23
- Treat a successful file-edit tool result as confirmation; do not reread a file solely to verify that the edit succeeded. Do not approximate unavailable build or test commands with broad source searches.`});export{instructions_default as default};
23
+ Treat a successful file-edit tool result as confirmation; do not reread a file solely to verify that the edit succeeded. Do not approximate unavailable build or test commands with broad source searches.
24
+
25
+ Local trace segments are mounted read-only at /traces when available. Inspect other traces only when the user asks about another session or broader behavior.`;function readTrace(e){return e.data?.trace}var instructions_default=defineDynamic({events:{"session.started":e=>{let t=readTrace(e);if(t===void 0)return defineInstructions({markdown:instructions});let n=(t.traceFlags&1)==1?`If local segments were captured,`:`This trace was not sampled, so local segments may be absent. If any are present,`;return defineInstructions({markdown:`${instructions}\n\nThe invoking trace has ID ${t.traceId}. ${n} inspect them at /traces/${t.traceId}.`})}}});export{instructions_default as default};
@@ -1 +1 @@
1
- import{resolve}from"node:path";async function createSelfModificationFilesystem(e){let{MountableFs:t,OverlayFs:n,ReadWriteFs:r}=e.justBash;return await e.defaultFilesystem.mkdir(`/source`,{recursive:!0}),new t({base:e.defaultFilesystem,mounts:[{filesystem:new r({allowSymlinks:!1,maxFileReadSize:2**53-1,root:resolve(e.appRoot,`agent`)}),mountPoint:`/source`},{filesystem:new n({mountPoint:`/`,readOnly:!0,root:resolve(e.appRoot,`node_modules/eve/docs`)}),mountPoint:`/eve-docs`}]})}export{createSelfModificationFilesystem};
1
+ import{mkdir}from"node:fs/promises";import{resolve}from"node:path";async function createSelfModificationFilesystem(e){let{MountableFs:t,OverlayFs:n,ReadWriteFs:r}=e.justBash,i=resolve(e.appRoot,`.eve/traces/v1`);return await Promise.all([e.defaultFilesystem.mkdir(`/source`,{recursive:!0}),mkdir(i,{recursive:!0})]),new t({base:e.defaultFilesystem,mounts:[{filesystem:new r({allowSymlinks:!1,maxFileReadSize:2**53-1,root:resolve(e.appRoot,`agent`)}),mountPoint:`/source`},{filesystem:new n({mountPoint:`/`,readOnly:!0,root:i}),mountPoint:`/traces`},{filesystem:new n({mountPoint:`/`,readOnly:!0,root:resolve(e.appRoot,`node_modules/eve/docs`)}),mountPoint:`/eve-docs`}]})}export{createSelfModificationFilesystem};
@@ -1,2 +1,14 @@
1
- /** Ensures Codex owns a usable ChatGPT login before setup authors `chatgpt()`. */
2
- export declare function ensureChatGptAuth(): Promise<void>;
1
+ import { type ChatGptCredentialStore } from "#public/models/openai/chatgpt/credential-store.js";
2
+ import { type CodexTokenBroker } from "#public/models/openai/chatgpt/token-broker.js";
3
+ interface ChatGptAuthOptions {
4
+ readonly signal?: AbortSignal;
5
+ readonly broker?: CodexTokenBroker;
6
+ readonly store?: ChatGptCredentialStore;
7
+ readonly fetch?: typeof fetch;
8
+ readonly open?: (url: string) => void;
9
+ readonly log?: (message: string) => void;
10
+ readonly headless?: boolean;
11
+ }
12
+ /** Signs in directly with OpenAI; credentials belong to eve, independently of Codex. */
13
+ export declare function ensureChatGptAuth(options?: ChatGptAuthOptions): Promise<void>;
14
+ export {};
@@ -1 +1 @@
1
- import{spawn}from"node:child_process";import{getDefaultCodexTokenBroker}from"#public/models/openai/chatgpt/token-broker.js";async function ensureChatGptAuth(){if((await getDefaultCodexTokenBroker().refreshState()).kind===`ready`)return;let e=spawn(`codex`,[`login`],{stdio:`inherit`});if(await new Promise((t,n)=>{e.once(`error`,n),e.once(`exit`,(e,r)=>{e===0?t():n(Error(`codex login failed (${r??e??`unknown`}).`))})}),(await getDefaultCodexTokenBroker().refreshState()).kind!==`ready`)throw Error(`Codex login completed without a usable ChatGPT session.`)}export{ensureChatGptAuth};
1
+ import{createHash,randomBytes}from"node:crypto";import{createServer}from"node:http";import{WizardCancelledError}from"#setup/step.js";import{isErrnoCode,isObject}from"#shared/guards.js";import{setTimeout as setTimeout$1}from"node:timers/promises";import{getDefaultCodexTokenBroker}from"#public/models/openai/chatgpt/token-broker.js";import{createChatGptCredentialStore}from"#public/models/openai/chatgpt/credential-store.js";import{CHATGPT_CLIENT_ID,CHATGPT_ISSUER,readChatGptAuthResponse,requestChatGptTokens}from"#public/models/openai/chatgpt/oauth.js";import{openUrl}from"#setup/primitives/open-url.js";const REDIRECT_URI=`http://localhost:1455/auth/callback`;async function ensureChatGptAuth(e={}){let t=e.broker??getDefaultCodexTokenBroker();if(e.signal?.throwIfAborted(),(await t.refreshState()).kind===`ready`)return;let n=new AbortController,cancel=()=>n.abort(new WizardCancelledError);process.once(`SIGINT`,cancel);let r=setTimeout(()=>n.abort(Error(`ChatGPT sign-in timed out. Retry from /model.`)),3e5),i=AbortSignal.any([n.signal,...e.signal?[e.signal]:[]]),a=e.log??(e=>process.stdout.write(`${e}\n`)),o=e.open??openUrl;try{let n=e.headless??!!(process.env.SSH_CONNECTION||process.env.SSH_TTY)?await deviceLogin({...e,signal:i,log:a,open:o}):await browserLogin({...e,signal:i,log:a,open:o});if(i.throwIfAborted(),await(e.store??createChatGptCredentialStore()).update(async()=>(i.throwIfAborted(),n)),(await t.refreshState()).kind!==`ready`)throw Error(`ChatGPT sign-in could not be verified. Retry from /model.`);a(`ChatGPT subscription connected.`)}catch(e){throw i.throwIfAborted(),e}finally{clearTimeout(r),process.removeListener(`SIGINT`,cancel)}}async function browserLogin(e){let t=randomBytes(32).toString(`base64url`),n=randomBytes(32).toString(`base64url`),r=new URL(`${CHATGPT_ISSUER}/oauth/authorize`);r.search=new URLSearchParams({response_type:`code`,client_id:CHATGPT_CLIENT_ID,redirect_uri:REDIRECT_URI,scope:`openid profile email offline_access`,code_challenge:createHash(`sha256`).update(t).digest(`base64url`),code_challenge_method:`S256`,id_token_add_organizations:`true`,codex_cli_simplified_flow:`true`,state:n,originator:`eve`}).toString();let i=Promise.withResolvers();i.promise.catch(()=>{});let a=createServer({requestTimeout:1e4,headersTimeout:1e4,maxHeaderSize:8192},(e,t)=>{let r=URL.parse(e.url??``,REDIRECT_URI);if(t.setHeader(`content-type`,`text/plain; charset=utf-8`),t.setHeader(`cache-control`,`no-store`),e.method!==`GET`||r?.pathname!==`/auth/callback`){t.writeHead(404).end(`Not found.`);return}if(r.searchParams.get(`state`)!==n){t.writeHead(400).end(`This sign-in belongs to another attempt. Return to eve and use its sign-in link.`);return}if(r.searchParams.has(`error`)){t.writeHead(400).end(`ChatGPT sign-in was declined. Return to eve to retry.`),i.reject(Error(`ChatGPT sign-in was declined. Retry from /model.`));return}let a=r.searchParams.get(`code`);if(!a){t.writeHead(400).end(`Missing authorization code.`);return}t.end(`Authorization received. Return to eve to finish connecting your ChatGPT subscription.`),i.resolve(a)});a.maxConnections=10;let abort=()=>i.reject(e.signal.reason);e.signal.addEventListener(`abort`,abort,{once:!0});try{e.signal.throwIfAborted();try{await new Promise((e,t)=>{a.once(`error`,t),a.listen(1455,`127.0.0.1`,e)})}catch(t){if(!isErrnoCode(t,`EADDRINUSE`))throw Error(`Could not start ChatGPT sign-in on localhost:1455. Free the port and retry from /model.`);return e.log(`Local sign-in port is in use. Continuing with a device code.`),await deviceLogin(e)}e.signal.throwIfAborted(),e.log(`Sign in to ChatGPT in your browser:\n${r.href}\nWaiting for sign-in. Press Ctrl+C to cancel.`),e.open(r.href);let n=await i.promise;return await requestChatGptTokens({grant_type:`authorization_code`,code:n,code_verifier:t,redirect_uri:REDIRECT_URI},e)}finally{e.signal.removeEventListener(`abort`,abort),a.closeAllConnections(),await new Promise(e=>a.close(()=>e()))}}async function deviceLogin(e){let t=await deviceRequest(`usercode`,{client_id:CHATGPT_CLIENT_ID},e);if(!t.ok)throw Error(`ChatGPT device sign-in is unavailable (HTTP ${t.status}). Enable device code authorization in ChatGPT Settings > Security, then retry from /model.`);let n=await readChatGptAuthResponse(t);if(!isObject(n)||typeof n.device_auth_id!=`string`||!n.device_auth_id||typeof n.user_code!=`string`||!/^[A-Z0-9-]{4,32}$/iu.test(n.user_code))throw Error(`ChatGPT returned an invalid device code. Retry from /model.`);let r=Math.min(30,Math.max(1,Number(n.interval)||5))*1e3,i=`${CHATGPT_ISSUER}/codex/device`;for(e.log(`Open ${i} and enter code: ${n.user_code}\nIf prompted, enable device code authorization in ChatGPT Settings > Security.\nWaiting for sign-in. Press Ctrl+C to cancel.`),e.open(i);;){await setTimeout$1(r+1e3,void 0,{signal:e.signal});let t=await deviceRequest(`token`,{device_auth_id:n.device_auth_id,user_code:n.user_code},e);if(t.status===403||t.status===404)continue;if(!t.ok)throw Error(`ChatGPT device sign-in failed (HTTP ${t.status}). Retry from /model.`);let i=await readChatGptAuthResponse(t);if(!isObject(i)||typeof i.authorization_code!=`string`||!i.authorization_code||typeof i.code_verifier!=`string`||!i.code_verifier)throw Error(`ChatGPT returned an invalid device authorization. Retry from /model.`);return requestChatGptTokens({grant_type:`authorization_code`,code:i.authorization_code,code_verifier:i.code_verifier,redirect_uri:`${CHATGPT_ISSUER}/deviceauth/callback`},e)}}async function deviceRequest(e,t,n){try{return await(n.fetch??fetch)(`${CHATGPT_ISSUER}/api/accounts/deviceauth/${e}`,{method:`POST`,headers:{"content-type":`application/json`,"user-agent":`eve`},body:JSON.stringify(t),redirect:`error`,signal:AbortSignal.any([n.signal,AbortSignal.timeout(3e4)])})}catch{throw n.signal.throwIfAborted(),Error(`Could not reach ChatGPT device sign-in. Check your connection and retry from /model.`)}}export{ensureChatGptAuth};
@@ -83,7 +83,7 @@ export interface ModelFlowDeps {
83
83
  readProviderSelection: typeof readProviderSelection;
84
84
  /** The provider sub-flow behind the menu's provider row. */
85
85
  runProviderFlow: typeof runProviderFlow;
86
- /** Ensures Codex owns a usable login before selecting ChatGPT. */
86
+ /** Ensures eve has a usable ChatGPT login before selecting the subscription. */
87
87
  ensureChatGptAuth: typeof ensureChatGptAuth;
88
88
  writeProviderSelection: typeof writeProviderSelection;
89
89
  }
@@ -118,8 +118,9 @@ export declare function runModelFlow(input: {
118
118
  prompter: Prompter;
119
119
  /** Opens provider setup before the root menu when runtime evidence requires it. */
120
120
  initialStep?: "provider";
121
+ onScreen?: (screen: "model_provider" | "model_settings") => void;
121
122
  signal?: AbortSignal;
122
- /** Gives Codex uncontested inherited stdio while it performs login. */
123
+ /** Gives ChatGPT sign-in exclusive terminal ownership. */
123
124
  withExclusiveTerminal?: <T>(task: () => Promise<T>) => Promise<T>;
124
125
  /** Live ChatGPT identity shown in this configuration flow only. */
125
126
  chatGptAccountLabel?: string;
@@ -1 +1 @@
1
- import{AI_GATEWAY_API_KEY_ENV_VAR}from"../ai-gateway-api-key.js";import{withSpinner}from"../with-spinner.js";import{gatewayModelCapabilities}from"../boxes/model-capabilities.js";import{fetchGatewayCatalog,modelOptionsFromCatalog}from"../boxes/select-model.js";import{ensureChatGptAuth}from"./chatgpt-auth.js";import{WizardCancelledError}from"../step.js";import{changeAgentModelSettings,formatApplyModelSettingsOutcome}from"./model-source-change.js";import{runProviderFlow}from"./provider.js";import pc from"#compiled/picocolors/index.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";import{inspectApplication}from"#services/inspect-application.js";import{readProviderSelection,resolveAvailableProviders,writeProviderSelection}from"#setup/provider-settings.js";import{formatModelSummary}from"#shared/model-summary.js";import{readGatewayServiceTier}from"#shared/gateway-service-tier.js";import{DEFAULT_CHATGPT_MODEL_SELECTION,isChatGptModelRouting,parseChatGptModelSelection}from"#shared/chatgpt-model.js";const MODEL_MENU_MESSAGE=``;function providerSelectionHint(e,t){return e===`chatgpt`?t===void 0?`ChatGPT subscription`:`ChatGPT subscription (${t})`:e===`ai-gateway-project`?`AI Gateway via Project`:`AI Gateway via ${AI_GATEWAY_API_KEY_ENV_VAR}`}function modelListRows(e){return modelOptionsFromCatalog(e).map(e=>{let t={value:e.value,label:e.value};return e.featured===!0&&(t.featured=!0),t})}function formatModelDraftHint(e,t,n){let r={model:e};return t!==null&&(r.reasoning=t),n.kind===`priority`&&(r.fastGlyph=`↯`),formatModelSummary(r)}function modelMenuRows(e,t,n,r,i,a,o,s,c){let l;s||c?(l={value:`model`,label:`Change model`,description:s?`The model, its reasoning effort, and the Gateway service tier`:`Reasoning and service tier; the model itself is an SDK model call in agent.ts`},e!==null&&(l.hint=formatModelDraftHint(e,t,n))):l={value:`model`,label:`Change model`,disabled:!0,description:`Set via an SDK model call in agent.ts; edit the source to change it`};let u;return u=o?.kind===`external`&&!isChatGptModelRouting(o)?{disabled:!0,value:`provider`,label:`Change provider`,description:`Disabled in external endpoint mode`}:i?{value:`provider`,label:`Change provider`,hint:providerSelectionHint(r,a),description:`How your agent reaches the model provider`}:{value:`provider`,label:pc.bold(`Configure model access`),hint:pc.yellow(`Not configured`),description:`How your agent reaches the model provider`,accent:`warning`},[l,u,{value:`done`,label:`Done`}]}async function runModelFlow(e){let{appRoot:t,prompter:n,signal:r}=e,i=e.environmentRoot??t,a={readCurrentModel:readCurrentAgentModel,applySettings:changeAgentModelSettings,resolveAvailableProviders,readProviderSelection,runProviderFlow,ensureChatGptAuth,writeProviderSelection,...e.deps},o=a.selectModel?.fetchModels??fetchGatewayCatalog,[s,c,l,u]=await withSpinner(n,`Checking the project…`,()=>Promise.all([a.readCurrentModel(t),a.resolveAvailableProviders(i,r===void 0?{env:process.env}:{signal:r,env:process.env}),a.readProviderSelection(i),o(r).catch(()=>void 0)]));r?.throwIfAborted();let{id:d,routing:f,serviceTier:p,editable:m,settingsEditable:h}=s,g=s.reasoning===`provider-default`?null:s.reasoning,_=l??(c.includes(`ai-gateway-key`)?`ai-gateway-key`:`ai-gateway-project`),v=c.includes(_),y,b={model:{kind:`keep`},reasoning:{kind:`keep`},gatewayServiceTier:{kind:`keep`}},x,S,C=!1,w=!1,T=!1,E=f?.kind===`external`&&!isChatGptModelRouting(f),D=E?{tone:`warning`,text:"`agent.ts` specifies the model provider directly. Model, provider, and service-tier changes stay source-owned; reasoning remains configurable here."}:void 0,O=!v&&f?.kind!==`external`?`provider`:m||h?`model`:`provider`,k=f?.kind!==`external`&&(e.initialStep===`provider`||!v);for(;;){let t;if(k)k=!1,t=`provider`;else try{t=await n.select({message:``,options:modelMenuRows(d,g,isChatGptModelRouting(f)?{kind:`standard`}:p,_,v,e.chatGptAccountLabel,f,m,h),hintLayout:`stacked`,initialValue:O,notices:D===void 0?[]:[D]})}catch(e){if(!(e instanceof WizardCancelledError))throw e;if(hasModelSettingsChanges(b))return{kind:`cancelled`,discardedDraft:!0};break}if(t===`done`){w=!0,T=!0;break}if(t===`model`){let e=a.pickModelSettings;if(e===void 0)throw Error(`runModelFlow requires a pickModelSettings dep to open the model screen.`);let t=await e({model:m?{kind:`pick`,options:modelListRows(u),current:d}:{kind:`fixed`,current:d,reason:`Set via an SDK model call in agent.ts; edit the source to change it`},reasoning:g,serviceTier:isChatGptModelRouting(f)?{kind:`standard`}:p,settingsEditable:h,externalRouting:E,capabilitiesFor:e=>gatewayModelCapabilities(u,e)});if(r?.throwIfAborted(),t===void 0){O=`model`;continue}t.model!==void 0&&(d=t.model,f=routingForModelSelection(t.model),b.model={kind:`set`,value:t.model}),t.reasoning!==void 0&&(g=t.reasoning==="default"?null:t.reasoning,b.reasoning=g===null?{kind:`remove`}:{kind:`set`,value:g}),t.serviceTier!==void 0&&!isChatGptModelRouting(f)&&(p=t.serviceTier===`priority`?{kind:`priority`}:{kind:`standard`},b.gatewayServiceTier=t.serviceTier===`priority`?{kind:`set`,value:`priority`}:{kind:`remove`}),O=`done`;continue}let o=await a.runProviderFlow({appRoot:i,prompter:n,signal:r,availableProviders:c,selectedProvider:_});if(o.kind===`cancelled`){if(r?.aborted)return{kind:`cancelled`};O=`provider`;continue}if(o.kind===`external-provider`){if(r?.aborted)return{kind:`cancelled`};O=`done`;continue}y=o.kind,y===`chatgpt`?(C=!0,isChatGptModelRouting(f)||(b.model={kind:`set`,value:DEFAULT_CHATGPT_MODEL_SELECTION},b.gatewayServiceTier={kind:`remove`})):isChatGptModelRouting(f)&&(b.model={kind:`set`,value:DEFAULT_AGENT_MODEL_ID}),T=!0;break}let A=b.model.kind===`set`&&parseChatGptModelSelection(b.model.value)!==void 0;if(T&&A&&(b.gatewayServiceTier={kind:`remove`},C=!0),T&&C&&await authenticateChatGpt(a,e.withExclusiveTerminal),T&&hasModelSettingsChanges(b)&&(x=await a.applySettings({appRoot:t,patch:b})),T&&y!==void 0&&x?.kind!==`rejected`&&(await a.writeProviderSelection(i,y),S=y),x!==void 0&&S===void 0&&r?.throwIfAborted(),x===void 0&&S===void 0&&!C)return w?{kind:`done`,accessChanged:!1}:{kind:`cancelled`};let j={kind:`done`,accessChanged:x?.kind===`changed`||S!==void 0||C};return x===void 0?C&&(j.modelMessage=`ChatGPT login ready.`):j.modelMessage=formatApplyModelSettingsOutcome(x),S!==void 0&&(j.providerSelection=S),j}function routingForModelSelection(e){return parseChatGptModelSelection(e)===void 0?{kind:`gateway`,target:e.split(`/`)[0]??``}:{kind:`external`,provider:`codex`}}async function authenticateChatGpt(e,t){let authenticate=()=>e.ensureChatGptAuth();await(t===void 0?authenticate():t(authenticate))}function hasModelSettingsChanges(e){return e.model.kind!==`keep`||e.reasoning.kind!==`keep`||e.gatewayServiceTier.kind!==`keep`}async function readCurrentAgentModel(e){try{let{compiledState:t}=await inspectApplication(e),n=t?.manifest.config,r=n?.model,i=isChatGptModelRouting(r?.routing);return{id:i&&r!==void 0?`chatgpt/${r.id}`:r?.id??null,routing:r?.routing??null,reasoning:n?.reasoning??null,serviceTier:readGatewayServiceTier(r?.providerOptions),editable:r!==void 0&&(r.source===void 0||i),settingsEditable:n?.source!==void 0}}catch{return{id:null,routing:null,reasoning:null,serviceTier:{kind:`standard`},editable:!1,settingsEditable:!1}}}async function modelChangeRefusalForUneditableModel(e){let{editable:t,routing:n}=await readCurrentAgentModel(e);return t?null:`Model is set via ${n?.kind===`external`?`the external provider \`${n.provider}\``:`an SDK model call`} in agent.ts, not a string literal; /model can't rewrite it. Edit \`model\` in agent.ts.`}export{MODEL_MENU_MESSAGE,modelChangeRefusalForUneditableModel,runModelFlow};
1
+ import{AI_GATEWAY_API_KEY_ENV_VAR}from"../ai-gateway-api-key.js";import{withSpinner}from"../with-spinner.js";import{gatewayModelCapabilities}from"../boxes/model-capabilities.js";import{fetchGatewayCatalog,modelOptionsFromCatalog}from"../boxes/select-model.js";import{ensureChatGptAuth}from"./chatgpt-auth.js";import{WizardCancelledError}from"../step.js";import{changeAgentModelSettings,formatApplyModelSettingsOutcome}from"./model-source-change.js";import{runProviderFlow}from"./provider.js";import pc from"#compiled/picocolors/index.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";import{inspectApplication}from"#services/inspect-application.js";import{readProviderSelection,resolveAvailableProviders,writeProviderSelection}from"#setup/provider-settings.js";import{formatModelSummary}from"#shared/model-summary.js";import{readGatewayServiceTier}from"#shared/gateway-service-tier.js";import{DEFAULT_CHATGPT_MODEL_SELECTION,isChatGptModelRouting,parseChatGptModelSelection}from"#shared/chatgpt-model.js";const MODEL_MENU_MESSAGE=``;function providerSelectionHint(e,t){return e===`chatgpt`?t===void 0?`ChatGPT subscription`:`ChatGPT subscription (${t})`:e===`ai-gateway-project`?`AI Gateway via Project`:`AI Gateway via ${AI_GATEWAY_API_KEY_ENV_VAR}`}function modelListRows(e){return modelOptionsFromCatalog(e).map(e=>{let t={value:e.value,label:e.value};return e.featured===!0&&(t.featured=!0),t})}function formatModelDraftHint(e,t,n){let r={model:e};return t!==null&&(r.reasoning=t),n.kind===`priority`&&(r.fastGlyph=`↯`),formatModelSummary(r)}function modelMenuRows(e,t,n,r,i,a,o,s,c){let l;s||c?(l={value:`model`,label:`Change model`,description:s?`The model, its reasoning effort, and the Gateway service tier`:`Reasoning and service tier; the model itself is an SDK model call in agent.ts`},e!==null&&(l.hint=formatModelDraftHint(e,t,n))):l={value:`model`,label:`Change model`,disabled:!0,description:`Set via an SDK model call in agent.ts; edit the source to change it`};let u;return u=o?.kind===`external`&&!isChatGptModelRouting(o)?{disabled:!0,value:`provider`,label:`Change provider`,description:`Disabled in external endpoint mode`}:i?{value:`provider`,label:`Change provider`,hint:providerSelectionHint(r,a),description:`How your agent reaches the model provider`}:{value:`provider`,label:pc.bold(`Configure model access`),hint:pc.yellow(`Not configured`),description:`How your agent reaches the model provider`,accent:`warning`},[l,u,{value:`done`,label:`Done`}]}async function runModelFlow(e){let{appRoot:t,prompter:n,signal:r}=e,i=e.environmentRoot??t,a={readCurrentModel:readCurrentAgentModel,applySettings:changeAgentModelSettings,resolveAvailableProviders,readProviderSelection,runProviderFlow,ensureChatGptAuth,writeProviderSelection,...e.deps},o=a.selectModel?.fetchModels??fetchGatewayCatalog,[s,c,l,u]=await withSpinner(n,`Checking the project…`,()=>Promise.all([a.readCurrentModel(t),a.resolveAvailableProviders(i,r===void 0?{env:process.env}:{signal:r,env:process.env}),a.readProviderSelection(i),o(r).catch(()=>void 0)]));r?.throwIfAborted();let{id:d,routing:f,serviceTier:p,editable:m,settingsEditable:h}=s,g=s.reasoning===`provider-default`?null:s.reasoning,_=l??(c.includes(`ai-gateway-key`)?`ai-gateway-key`:`ai-gateway-project`),v=c.includes(_),y,b={model:{kind:`keep`},reasoning:{kind:`keep`},gatewayServiceTier:{kind:`keep`}},x,S,C=!1,w=!1,T=!1,E=f?.kind===`external`&&!isChatGptModelRouting(f),D=E?{tone:`warning`,text:"`agent.ts` specifies the model provider directly. Model, provider, and service-tier changes stay source-owned; reasoning remains configurable here."}:void 0,O=!v&&f?.kind!==`external`?`provider`:m||h?`model`:`provider`,k=f?.kind!==`external`&&(e.initialStep===`provider`||!v);for(;;){let t;if(k)k=!1,t=`provider`;else try{t=await n.select({message:``,options:modelMenuRows(d,g,isChatGptModelRouting(f)?{kind:`standard`}:p,_,v,e.chatGptAccountLabel,f,m,h),hintLayout:`stacked`,initialValue:O,notices:D===void 0?[]:[D]})}catch(e){if(!(e instanceof WizardCancelledError))throw e;if(hasModelSettingsChanges(b))return{kind:`cancelled`,discardedDraft:!0};break}if(t===`done`){w=!0,T=!0;break}if(t===`model`){e.onScreen?.(`model_settings`);let t=a.pickModelSettings;if(t===void 0)throw Error(`runModelFlow requires a pickModelSettings dep to open the model screen.`);let n=await t({model:m?{kind:`pick`,options:modelListRows(u),current:d}:{kind:`fixed`,current:d,reason:`Set via an SDK model call in agent.ts; edit the source to change it`},reasoning:g,serviceTier:isChatGptModelRouting(f)?{kind:`standard`}:p,settingsEditable:h,externalRouting:E,capabilitiesFor:e=>gatewayModelCapabilities(u,e)});if(r?.throwIfAborted(),n===void 0){O=`model`;continue}n.model!==void 0&&(d=n.model,f=routingForModelSelection(n.model),b.model={kind:`set`,value:n.model}),n.reasoning!==void 0&&(g=n.reasoning==="default"?null:n.reasoning,b.reasoning=g===null?{kind:`remove`}:{kind:`set`,value:g}),n.serviceTier!==void 0&&!isChatGptModelRouting(f)&&(p=n.serviceTier===`priority`?{kind:`priority`}:{kind:`standard`},b.gatewayServiceTier=n.serviceTier===`priority`?{kind:`set`,value:`priority`}:{kind:`remove`}),O=`done`;continue}e.onScreen?.(`model_provider`);let o=await a.runProviderFlow({appRoot:i,prompter:n,signal:r,availableProviders:c,selectedProvider:_});if(o.kind===`cancelled`){if(r?.aborted)return{kind:`cancelled`};O=`provider`;continue}if(o.kind===`external-provider`){if(r?.aborted)return{kind:`cancelled`};O=`done`;continue}y=o.kind,y===`chatgpt`?(C=!0,isChatGptModelRouting(f)||(b.model={kind:`set`,value:DEFAULT_CHATGPT_MODEL_SELECTION},b.gatewayServiceTier={kind:`remove`})):isChatGptModelRouting(f)&&(b.model={kind:`set`,value:DEFAULT_AGENT_MODEL_ID}),T=!0;break}let A=b.model.kind===`set`&&parseChatGptModelSelection(b.model.value)!==void 0;if(T&&A&&(b.gatewayServiceTier={kind:`remove`},C=!0),T&&C&&await authenticateChatGpt(a,e.withExclusiveTerminal,r),T&&hasModelSettingsChanges(b)&&(x=await a.applySettings({appRoot:t,patch:b})),T&&y!==void 0&&x?.kind!==`rejected`&&(await a.writeProviderSelection(i,y),S=y),x!==void 0&&S===void 0&&r?.throwIfAborted(),x===void 0&&S===void 0&&!C)return w?{kind:`done`,accessChanged:!1}:{kind:`cancelled`};let j={kind:`done`,accessChanged:x?.kind===`changed`||S!==void 0||C};return x===void 0?C&&(j.modelMessage=`ChatGPT login ready.`):j.modelMessage=formatApplyModelSettingsOutcome(x),S!==void 0&&(j.providerSelection=S),j}function routingForModelSelection(e){return parseChatGptModelSelection(e)===void 0?{kind:`gateway`,target:e.split(`/`)[0]??``}:{kind:`external`,provider:`codex`}}async function authenticateChatGpt(e,t,n){let authenticate=()=>e.ensureChatGptAuth({signal:n});await(t===void 0?authenticate():t(authenticate))}function hasModelSettingsChanges(e){return e.model.kind!==`keep`||e.reasoning.kind!==`keep`||e.gatewayServiceTier.kind!==`keep`}async function readCurrentAgentModel(e){try{let{compiledState:t}=await inspectApplication(e),n=t?.manifest.config,r=n?.model,i=isChatGptModelRouting(r?.routing);return{id:i&&r!==void 0?`chatgpt/${r.id}`:r?.id??null,routing:r?.routing??null,reasoning:n?.reasoning??null,serviceTier:readGatewayServiceTier(r?.providerOptions),editable:r!==void 0&&(r.source===void 0||i),settingsEditable:n?.source!==void 0}}catch{return{id:null,routing:null,reasoning:null,serviceTier:{kind:`standard`},editable:!1,settingsEditable:!1}}}async function modelChangeRefusalForUneditableModel(e){let{editable:t,routing:n}=await readCurrentAgentModel(e);return t?null:`Model is set via ${n?.kind===`external`?`the external provider \`${n.provider}\``:`an SDK model call`} in agent.ts, not a string literal; /model can't rewrite it. Edit \`model\` in agent.ts.`}export{MODEL_MENU_MESSAGE,modelChangeRefusalForUneditableModel,runModelFlow};
@@ -1,4 +1,4 @@
1
1
  import{appendEnv}from"../append-env.js";import{AI_GATEWAY_API_KEY_ENV_FILE,AI_GATEWAY_API_KEY_ENV_VAR,writeAiGatewayApiKey}from"../ai-gateway-api-key.js";import{withSpinner}from"../with-spinner.js";import{getVercelAuthStatus,vercelAuthBlockerReason}from"../vercel-project.js";import{WizardCancelledError}from"../step.js";import{runLinkFlow}from"./link.js";import{validateGatewayApiKey}from"../validate-gateway-key.js";import{HumanActionRequiredError}from"#setup/human-action.js";const PROVIDER_QUESTION=`Which model provider do you want to use?`,EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE=`Using another model provider`,EXTERNAL_PROVIDER_INSTRUCTIONS=[`Set your provider's API key in ${AI_GATEWAY_API_KEY_ENV_FILE} — e.g. ANTHROPIC_API_KEY or OPENAI_API_KEY.`,'In agent/agent.ts, set `model` to a provider-authored model — e.g. `anthropic("claude-opus-4.8")` from `@ai-sdk/anthropic`.',`See https://eve.dev/docs/agent-config for details.`,"A running `eve dev` reloads env files automatically — no restart needed."];function projectConnectionOption(e,t){let n={value:`ai-gateway-project`,label:`AI Gateway via Project`,hint:`Authenticates with AI Gateway automatically
2
- in a new or existing project. No keys to manage.`};if(e===`unavailable`)return{...n,hint:`Couldn't reach Vercel — select to retry`};if(t&&e===`logged-out`)return{...n,hint:`Log in to Vercel — select to retry`};if(t&&e===`cli-missing`)return{...n,hint:`Install the Vercel CLI — select to retry`};let r=e===void 0?void 0:vercelAuthBlockerReason(e);return r===void 0?n:{...n,disabled:!0,disabledReason:r,disabledReasonTone:`warning`}}function providerOptions(e,t,n,r){let i=projectConnectionOption(e,r);n&&t===`ai-gateway-project`&&e!==`unavailable`&&(!r||e!==`logged-out`&&e!==`cli-missing`)&&(i={...i,checked:!0,hint:`Current`});let a={value:`ai-gateway-key`,label:`AI Gateway via ${AI_GATEWAY_API_KEY_ENV_VAR}`,hint:`⎿ type your key`};return n&&t===`ai-gateway-key`&&(a={...a,checked:!0,hint:`Current`}),[i,a,{value:`chatgpt`,label:`ChatGPT subscription`,hint:n&&t===`chatgpt`?`Current`:`Authenticate through the Codex CLI`,checked:n&&t===`chatgpt`||void 0},{value:`external`,label:`Other providers`,hint:`Connect directly to a model provider
2
+ in a new or existing project. No keys to manage.`};if(e===`unavailable`)return{...n,hint:`Couldn't reach Vercel — select to retry`};if(t&&e===`logged-out`)return{...n,hint:`Log in to Vercel — select to retry`};if(t&&e===`cli-missing`)return{...n,hint:`Install the Vercel CLI — select to retry`};let r=e===void 0?void 0:vercelAuthBlockerReason(e);return r===void 0?n:{...n,disabled:!0,disabledReason:r,disabledReasonTone:`warning`}}function providerOptions(e,t,n,r){let i=projectConnectionOption(e,r);n&&t===`ai-gateway-project`&&e!==`unavailable`&&(!r||e!==`logged-out`&&e!==`cli-missing`)&&(i={...i,checked:!0,hint:`Current`});let a={value:`ai-gateway-key`,label:`AI Gateway via ${AI_GATEWAY_API_KEY_ENV_VAR}`,hint:`⎿ type your key`};return n&&t===`ai-gateway-key`&&(a={...a,checked:!0,hint:`Current`}),[i,a,{value:`chatgpt`,label:`ChatGPT subscription`,hint:n&&t===`chatgpt`?`Current`:`Sign in with your ChatGPT account`,checked:n&&t===`chatgpt`||void 0},{value:`external`,label:`Other providers`,hint:`Connect directly to a model provider
3
3
  via OPENAI_API_KEY or ANTHROPIC_API_KEY.`}]}async function selectProvider(e){let t={message:PROVIDER_QUESTION,options:e.options,initialValue:e.initialValue,validateInlineKey:e.validateInlineKey};if(e.picker===void 0)throw Error(`The provider flow requires the Dev TUI provider picker.`);let n=await e.picker(t);if(n===void 0)throw new WizardCancelledError;return n}async function runProviderFlow(e){let{appRoot:t,prompter:n,signal:r}=e,i={getVercelAuthStatus,runLinkFlow,appendEnv,validateGatewayApiKey,...e.deps},a,{availableProviders:o,selectedProvider:s}=e,c=s,l;try{for(;;){let u=await selectProvider({picker:e.picker,options:providerOptions(a,s,e.selectionExplicit!==!1,e.recoverHumanAction!==void 0),initialValue:c,validateInlineKey:(e,t)=>i.validateGatewayApiKey(e,r===void 0?t:AbortSignal.any([r,t]))});if(u.kind===`external`)return n.acknowledge?await n.acknowledge({message:EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE,lines:EXTERNAL_PROVIDER_INSTRUCTIONS}):n.note(EXTERNAL_PROVIDER_INSTRUCTIONS.join(`
4
4
  `),EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE),{kind:`external-provider`};if(u.kind===`chatgpt`)return u;if(u.kind===`ai-gateway-key`){l=u;break}if(s!==`ai-gateway-project`&&o.includes(`ai-gateway-project`))return u;for(;;){let o=await withSpinner(n,`Checking your Vercel login…`,()=>i.getVercelAuthStatus(t,{signal:r}));if(r?.throwIfAborted(),a=o,o===`authenticated`)break;let s=o===`cli-missing`?`vercel-cli-missing`:o===`logged-out`?`vercel-login`:void 0;if(s===void 0||e.recoverHumanAction===void 0){c=o===`unavailable`?`ai-gateway-project`:`ai-gateway-key`;break}if(await e.recoverHumanAction(new HumanActionRequiredError({kind:s,command:o===`cli-missing`?`npm i -g vercel@latest`:`vercel login`,reason:o===`cli-missing`?`AI Gateway via Project requires the Vercel CLI.`:`AI Gateway via Project requires a Vercel login.`}))===`cancel`){c=`ai-gateway-project`;break}}if(a===`authenticated`)for(;;)try{let e=await i.runLinkFlow({appRoot:t,prompter:n,signal:r,projectSelection:`create-or-link`});return e.kind===`cancelled`?e:{kind:`ai-gateway-project`}}catch(t){if(!(t instanceof HumanActionRequiredError)||e.recoverHumanAction===void 0)throw t;if(await e.recoverHumanAction(t)===`cancel`){c=`ai-gateway-key`;break}}}}catch(e){if(e instanceof WizardCancelledError)return{kind:`cancelled`};throw e}let u=l.key.trim(),d=l.validation;r?.throwIfAborted(),d.kind===`inconclusive`&&n.log.warning(`Couldn't reach the gateway to validate (${d.message}). Saving the key anyway.`);let f=await writeAiGatewayApiKey({projectRoot:t,apiKey:u,appendEnv:i.appendEnv});return n.log.success(`${f.envKey} set.`),{kind:`ai-gateway-key`}}export{EXTERNAL_PROVIDER_INSTRUCTIONS,EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE,PROVIDER_QUESTION,runProviderFlow};
@@ -35,6 +35,10 @@ export declare function runRegistryFlow(input: {
35
35
  /** Registry item supplied by `/add <item>`, confirmed and installed directly. */
36
36
  initialAddress?: string;
37
37
  plannerContext?: RegistryPlannerContext;
38
+ onScreen?: (input: {
39
+ screen: "registry_channels" | "registry_integrations" | "registry_review" | "registry_install";
40
+ registrySelectedCount?: number;
41
+ }) => void;
38
42
  onItemStart?: (item: Item, index: number, total: number) => void;
39
43
  /** Gives each installation its own cancellation boundary without ending the batch. */
40
44
  runItem?<T>(task: (signal?: AbortSignal) => Promise<T>): Promise<T>;
@@ -1,2 +1,2 @@
1
- import{createRegistrySession}from"./registry-session.js";import{PlannerNavigationError}from"#setup/prompter.js";import{WizardCancelledError}from"#setup/step.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{withSpinner}from"#setup/with-spinner.js";const PLANNER_STEPS=[`Channels`,`Integrations`,`Review`];var RegistryFlowFailedError=class extends Error{completed;constructor(e,t){super(e instanceof Error?e.message:String(e),{cause:e}),this.name=`RegistryFlowFailedError`,this.completed=t}};const SECTIONS={channels:{title:`Where should people reach your agent?`,description:`You can add more later with /add.`,featured:[`channel/web`,`channel/slack`,`channel/github`,`channel/linear-agent`,`channel/photon-imessage`],includes:e=>e.name.startsWith(`channel/`)},integrations:{title:`What should your agent be able to work with?`,featured:[`extension/github-tools`,`connection/linear`,`connection/notion`,`connection/vercel`,`extension/agent-browser`,`experimental/self-modification`],includes:e=>!e.name.startsWith(`channel/`)}};function label(e){return e.title??e.name.split(`/`).at(-1)??e.name}function isPlannerItem(e,t){return t.name.includes(`/`)&&SECTIONS[e].includes(t)}function orderedSectionItems(e,t){let n=t.filter(t=>isPlannerItem(e,t)),r=SECTIONS[e].featured.map(e=>n.find(t=>t.name===e)).filter(e=>e!==void 0),i=new Set(r.map(e=>e.address));return[...r,...n.filter(e=>!i.has(e.address))]}function plannerLabel(e){return e.name===`connection/linear`?`Linear MCP`:label(e)}function sectionRows(e,t){return orderedSectionItems(e,t).map(e=>({value:e.address,label:plannerLabel(e),hint:e.description}))}function selectedInSection(e,t,n){return t.filter(t=>isPlannerItem(e,t)&&n.has(t.address)).map(e=>e.address)}function plannerNavigation(e,t){let n=(t.plannerContext?.prefixSteps??[]).map(e=>({label:e.label,complete:e.complete}));return{kind:`planner`,activeStep:n.length+e,firstNavigableStep:n.length,steps:[...n,...PLANNER_STEPS.map((e,n)=>{if(n===2)return{label:e};let r=selectedInSection(n===0?`channels`:`integrations`,t.catalog,t.selected).length;return r===0?{label:e}:{label:e,count:r}})]}}function replaceSectionSelection(e){for(let t of e.catalog)isPlannerItem(e.section,t)&&e.selected.delete(t.address);for(let t of e.addresses)e.selected.add(t)}async function editSection(e){let{section:t,catalog:n,prompter:r,selected:i}=e,a={message:SECTIONS[t].title,multiple:!0,search:!0,placeholder:t===`channels`?`Search channels`:`Search integrations`,navigation:plannerNavigation(t===`channels`?0:1,e),initialValues:selectedInSection(t,n,i),options:sectionRows(t,n)};t===`channels`&&(a.description=SECTIONS.channels.description),e.notices!==void 0&&(a.notices=e.notices);try{return replaceSectionSelection({section:t,catalog:n,selected:i,addresses:await r.select(a)}),`forward`}catch(e){if(!(e instanceof PlannerNavigationError))throw e;return replaceSectionSelection({section:t,catalog:n,selected:i,addresses:e.values.map(e=>{if(typeof e!=`string`)throw Error(`Registry planner returned a non-string item.`);return e})}),e.direction}}async function editPlan(e){let t=`channels`,n=e.notices;for(;;){if(t!==`review`){try{let r=await editSection({...e,section:t,notices:n});n=void 0,r===`back`?t===`integrations`&&(t=`channels`):t=t===`channels`?`integrations`:`review`}catch(e){if(!(e instanceof WizardCancelledError))throw e;return`cancelled`}continue}try{let t=e.selected.size>0,r=[...e.selected].map(t=>{let n=e.itemsByAddress.get(t);if(n===void 0)throw Error(`Registry item "${t}" is no longer available.`);return n}),i=r.filter(e=>e.name.startsWith(`channel/`)),a=r.filter(e=>!e.name.startsWith(`channel/`)),o=[...i.length===0?[]:[{label:`Channels`,value:i.map(label).join(`, `)}],...a.length===0?[]:[{label:`Integrations`,value:a.map(label).join(`, `)}]],s={message:e.plannerContext?.reviewMessage??`Review additions`,metadata:[...e.plannerContext?.reviewMetadata??[],...o],navigation:plannerNavigation(2,e),options:[{value:`install`,label:t?e.plannerContext?.primaryActionLabel??`Install and set up`:e.plannerContext?.emptyActionLabel??`Finish without adding`},{value:`back`,label:`Back`}]};t||(s.description=`No channels or integrations selected.`),n!==void 0&&(s.notices=n);let c=await e.prompter.select(s);if(n=void 0,c===`install`)return`install`}catch(e){if(e instanceof PlannerNavigationError&&e.direction===`back`){t=`integrations`;continue}if(!(e instanceof WizardCancelledError))throw e;return`cancelled`}t=`integrations`}}function hasSettledOutcomes(e){return e!==void 0&&(e.items.length>0||e.failures.length>0||e.outcomes!==void 0)}async function runRegistryFlow(e){let t;try{let n=e.initialAddress?.trim(),r;if(n!==void 0&&n!==``){if(await e.prompter.select({message:`Add ${n}?`,options:[{value:`install`,label:`Install and set up`},{value:`cancel`,label:`Cancel`}]})===`cancel`)return{kind:`cancelled`};r=[{address:n,name:n,source:`Registry`}]}else{let t=e.deps?.browseRegistryCatalog??(await import(`#cli/commands/registry.js`)).browseRegistryCatalog,n=await withSpinner(e.prompter,`Loading registry…`,()=>t(e.appRoot)),i=[...n.items],a=new Set,o=n.errors.map(e=>({tone:`warning`,text:`${e.registry}: ${e.message}`})),s=new Map(i.map(e=>[e.address,e]));if(await editPlan({prompter:e.prompter,catalog:i,itemsByAddress:s,selected:a,notices:o,plannerContext:e.plannerContext})!==`install`)return{kind:`cancelled`};r=[...a].map(e=>{let t=s.get(e);if(t===void 0)throw Error(`Registry item "${e}" is no longer available.`);return t})}let i=e.deps?.installRegistryItem??(await import(`#cli/commands/registry.js`)).installRegistryItem,a=e.deps?.detectDeployment??(await import(`#setup/project-resolution.js`)).detectDeployment,o=e.deps?.runDeployFlow??(await import(`./deploy.js`)).runDeployFlow;t=createRegistrySession({detectDeployment:a,runDeployFlow:o});let s=t;for(let[t,n]of r.entries()){e.signal?.throwIfAborted(),e.onItemStart?.(n,t,r.length);try{let install=(t=e.signal)=>i(e.appRoot,n.address,{silent:!0,prompter:e.prompter,signal:t}),run=()=>e.runItem===void 0?install():e.runItem(install),t=await(e.prompter.withExclusiveTerminal?.(run)??run());s.add(label(n),t.output,t.setup)}catch(t){if(e.signal?.throwIfAborted(),t instanceof WizardCancelledError){s.addCancellation(label(n));continue}if(t instanceof HumanActionRequiredError)throw t;let r=(t instanceof Error?t.message:String(t)).trim()||`Installation failed.`,i=r.split(`
1
+ import{createRegistrySession}from"./registry-session.js";import{PlannerNavigationError}from"#setup/prompter.js";import{WizardCancelledError}from"#setup/step.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{withSpinner}from"#setup/with-spinner.js";const PLANNER_STEPS=[`Channels`,`Integrations`,`Review`];var RegistryFlowFailedError=class extends Error{completed;constructor(e,t){super(e instanceof Error?e.message:String(e),{cause:e}),this.name=`RegistryFlowFailedError`,this.completed=t}};const SECTIONS={channels:{title:`Where should people reach your agent?`,description:`You can add more later with /add.`,featured:[`channel/web`,`channel/slack`,`channel/github`,`channel/linear-agent`,`channel/photon-imessage`],includes:e=>e.name.startsWith(`channel/`)},integrations:{title:`What should your agent be able to work with?`,featured:[`extension/github-tools`,`connection/linear`,`connection/notion`,`connection/vercel`,`extension/agent-browser`,`experimental/self-modification`],includes:e=>!e.name.startsWith(`channel/`)}};function label(e){return e.title??e.name.split(`/`).at(-1)??e.name}function isPlannerItem(e,t){return t.name.includes(`/`)&&SECTIONS[e].includes(t)}function orderedSectionItems(e,t){let n=t.filter(t=>isPlannerItem(e,t)),r=SECTIONS[e].featured.map(e=>n.find(t=>t.name===e)).filter(e=>e!==void 0),i=new Set(r.map(e=>e.address));return[...r,...n.filter(e=>!i.has(e.address))]}function plannerLabel(e){return e.name===`connection/linear`?`Linear MCP`:label(e)}function sectionRows(e,t){return orderedSectionItems(e,t).map(e=>({value:e.address,label:plannerLabel(e),hint:e.description}))}function selectedInSection(e,t,n){return t.filter(t=>isPlannerItem(e,t)&&n.has(t.address)).map(e=>e.address)}function plannerNavigation(e,t){let n=(t.plannerContext?.prefixSteps??[]).map(e=>({label:e.label,complete:e.complete}));return{kind:`planner`,activeStep:n.length+e,firstNavigableStep:n.length,steps:[...n,...PLANNER_STEPS.map((e,n)=>{if(n===2)return{label:e};let r=selectedInSection(n===0?`channels`:`integrations`,t.catalog,t.selected).length;return r===0?{label:e}:{label:e,count:r}})]}}function replaceSectionSelection(e){for(let t of e.catalog)isPlannerItem(e.section,t)&&e.selected.delete(t.address);for(let t of e.addresses)e.selected.add(t)}async function editSection(e){let{section:t,catalog:n,prompter:r,selected:i}=e,a={message:SECTIONS[t].title,multiple:!0,search:!0,placeholder:t===`channels`?`Search channels`:`Search integrations`,navigation:plannerNavigation(t===`channels`?0:1,e),initialValues:selectedInSection(t,n,i),options:sectionRows(t,n)};t===`channels`&&(a.description=SECTIONS.channels.description),e.notices!==void 0&&(a.notices=e.notices);try{return replaceSectionSelection({section:t,catalog:n,selected:i,addresses:await r.select(a)}),`forward`}catch(e){if(!(e instanceof PlannerNavigationError))throw e;return replaceSectionSelection({section:t,catalog:n,selected:i,addresses:e.values.map(e=>{if(typeof e!=`string`)throw Error(`Registry planner returned a non-string item.`);return e})}),e.direction}}async function editPlan(e){let t=`channels`,n=e.notices;for(;;){if(t!==`review`){e.onScreen?.({screen:t===`channels`?`registry_channels`:`registry_integrations`});try{let r=await editSection({...e,section:t,notices:n});n=void 0,r===`back`?t===`integrations`&&(t=`channels`):t=t===`channels`?`integrations`:`review`}catch(e){if(!(e instanceof WizardCancelledError))throw e;return`cancelled`}continue}try{e.onScreen?.({screen:`registry_review`,registrySelectedCount:e.selected.size});let t=e.selected.size>0,r=[...e.selected].map(t=>{let n=e.itemsByAddress.get(t);if(n===void 0)throw Error(`Registry item "${t}" is no longer available.`);return n}),i=r.filter(e=>e.name.startsWith(`channel/`)),a=r.filter(e=>!e.name.startsWith(`channel/`)),o=[...i.length===0?[]:[{label:`Channels`,value:i.map(label).join(`, `)}],...a.length===0?[]:[{label:`Integrations`,value:a.map(label).join(`, `)}]],s={message:e.plannerContext?.reviewMessage??`Review additions`,metadata:[...e.plannerContext?.reviewMetadata??[],...o],navigation:plannerNavigation(2,e),options:[{value:`install`,label:t?e.plannerContext?.primaryActionLabel??`Install and set up`:e.plannerContext?.emptyActionLabel??`Finish without adding`},{value:`back`,label:`Back`}]};t||(s.description=`No channels or integrations selected.`),n!==void 0&&(s.notices=n);let c=await e.prompter.select(s);if(n=void 0,c===`install`)return`install`}catch(e){if(e instanceof PlannerNavigationError&&e.direction===`back`){t=`integrations`;continue}if(!(e instanceof WizardCancelledError))throw e;return`cancelled`}t=`integrations`}}function hasSettledOutcomes(e){return e!==void 0&&(e.items.length>0||e.failures.length>0||e.outcomes!==void 0)}async function runRegistryFlow(e){let t;try{let n=e.initialAddress?.trim(),r;if(n!==void 0&&n!==``){if(await e.prompter.select({message:`Add ${n}?`,options:[{value:`install`,label:`Install and set up`},{value:`cancel`,label:`Cancel`}]})===`cancel`)return{kind:`cancelled`};r=[{address:n,name:n,source:`Registry`}]}else{let t=e.deps?.browseRegistryCatalog??(await import(`#cli/commands/registry.js`)).browseRegistryCatalog,n=await withSpinner(e.prompter,`Loading registry…`,()=>t(e.appRoot)),i=[...n.items],a=new Set,o=n.errors.map(e=>({tone:`warning`,text:`${e.registry}: ${e.message}`})),s=new Map(i.map(e=>[e.address,e]));if(await editPlan({prompter:e.prompter,catalog:i,itemsByAddress:s,selected:a,notices:o,plannerContext:e.plannerContext,onScreen:e.onScreen})!==`install`)return{kind:`cancelled`};r=[...a].map(e=>{let t=s.get(e);if(t===void 0)throw Error(`Registry item "${e}" is no longer available.`);return t})}let i=e.deps?.installRegistryItem??(await import(`#cli/commands/registry.js`)).installRegistryItem,a=e.deps?.detectDeployment??(await import(`#setup/project-resolution.js`)).detectDeployment,o=e.deps?.runDeployFlow??(await import(`./deploy.js`)).runDeployFlow;t=createRegistrySession({detectDeployment:a,runDeployFlow:o}),e.onScreen?.({screen:`registry_install`});let s=t;for(let[t,n]of r.entries()){e.signal?.throwIfAborted(),e.onItemStart?.(n,t,r.length);try{let install=(t=e.signal)=>i(e.appRoot,n.address,{silent:!0,prompter:e.prompter,signal:t}),run=()=>e.runItem===void 0?install():e.runItem(install),t=await(e.prompter.withExclusiveTerminal?.(run)??run());s.add(label(n),t.output,t.setup)}catch(t){if(e.signal?.throwIfAborted(),t instanceof WizardCancelledError){s.addCancellation(label(n));continue}if(t instanceof HumanActionRequiredError)throw t;let r=(t instanceof Error?t.message:String(t)).trim()||`Installation failed.`,i=r.split(`
2
2
  `).find(e=>e.trim()!==``);s.addFailure(label(n),r);let a={message:`Couldn't add ${label(n)}`,options:[{value:`skip`,label:`Skip ${label(n)}`},{value:`cancel`,label:`Cancel setup`}]};if(i!==void 0&&(a.description=i),await e.prompter.select(a)===`cancel`)return{kind:`done`,result:{...s.result(),cancelled:!0}}}}return{kind:`done`,result:await s.continueAfterInstall({appRoot:e.appRoot,prompter:e.prompter,signal:e.signal})}}catch(e){if(e instanceof WizardCancelledError){let e=t?.result();return hasSettledOutcomes(e)?{kind:`done`,result:{...e,cancelled:!0}}:{kind:`cancelled`}}let n=t?.result();throw hasSettledOutcomes(n)?new RegistryFlowFailedError(e,n):e}}export{RegistryFlowFailedError,runRegistryFlow};
@@ -2,7 +2,7 @@ import { z } from "#compiled/zod/index.js";
2
2
  import { type ChannelSetupLog } from "#setup/cli/index.js";
3
3
  import type { VercelProjectReference } from "#setup/project-resolution.js";
4
4
  import { type RunVercelOptions } from "#setup/primitives/run-vercel.js";
5
- export declare const FILE_MEMORY_BLOB_PREFIX = "EVE_MEMORY_";
5
+ export declare const FILE_MEMORY_BLOB_PREFIX = "EVE_MEMORY_BLOB";
6
6
  export declare const FILE_MEMORY_BLOB_ENVIRONMENTS: readonly ["production", "preview", "development"];
7
7
  declare const ProjectSchema: z.ZodObject<{
8
8
  id: z.ZodString;
@@ -52,7 +52,7 @@ export interface FileMemoryVercelClient {
52
52
  environments: readonly string[];
53
53
  prefix: string;
54
54
  projectId: string;
55
- storeName: string;
55
+ storeId: string;
56
56
  }): Promise<void>;
57
57
  getConnections(storeId: string): Promise<readonly BlobStoreConnection[]>;
58
58
  getProject(): Promise<VercelProjectConfiguration>;
@@ -1 +1 @@
1
- import{readFile}from"node:fs/promises";import{z}from"#compiled/zod/index.js";import{join}from"node:path";import{captureVercel}from"#setup/primitives/run-vercel.js";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";const FILE_MEMORY_BLOB_PREFIX=`EVE_MEMORY_`,FILE_MEMORY_BLOB_ENVIRONMENTS=[`production`,`preview`,`development`],ProjectSchema=z.object({id:z.string().min(1),name:z.string().min(1),resourceConfig:z.object({functionDefaultRegions:z.array(z.string().min(1)).optional()}).optional(),defaultResourceConfig:z.object({functionDefaultRegions:z.array(z.string().min(1)).optional()}).optional()}).passthrough(),StoreReferenceSchema=z.object({id:z.string().min(1),name:z.string().min(1),projects:z.array(z.object({id:z.string().min(1),name:z.string().min(1)}).passthrough()).default([]),region:z.string().min(1).optional()}).passthrough(),StoreSchema=z.object({access:z.enum([`private`,`public`]),id:z.string().min(1),name:z.string().min(1),region:z.string().min(1),type:z.string().optional()}).passthrough(),StoreConnectionSchema=z.object({envVarEnvironments:z.array(z.string()).default([]),envVarPrefix:z.string().nullish(),id:z.string().optional(),projectId:z.string().min(1)}).passthrough();function parseJson(e,t,n){try{return t.parse(JSON.parse(e))}catch{throw Error(`Vercel returned invalid ${n} data. Upgrade the Vercel CLI and try again.`)}}function commandFailure(e,t){let n=[t.failure.stderr,t.failure.stdout,t.failure.message].find(e=>e.trim().length>0);return Error(n===void 0?`${e} failed.`:`${e} failed: ${n.trim()}`)}function createFileMemoryVercelClient(e){let t={cwd:e.appRoot,nonInteractive:!0,onOutput:e.onOutput,signal:e.signal},n=[`--scope`,e.project.orgId];async function captureJson(n,r,i,a){let o=await captureVercel(n,{...t,stdin:a});if(e.signal?.throwIfAborted(),!o.ok)throw commandFailure(i,o);return parseJson(o.stdout,r,i.toLowerCase())}async function captureMutation(n,r){let i=await captureVercel(n,t);if(e.signal?.throwIfAborted(),!i.ok)throw commandFailure(r,i)}return{async createStore({name:e,region:t}){return(await captureJson([`api`,`/v1/storage/stores/blob`,`-X`,`POST`,`--input`,`-`,`--raw`,...n],z.object({store:StoreSchema}),`Vercel Blob store creation`,JSON.stringify({access:`private`,name:e,region:t}))).store},async connectStore({environments:e,prefix:t,projectId:r,storeName:i}){await captureMutation([`integration-resource`,`connect`,i,r,`--prefix`,t,...e.flatMap(e=>[`--environment`,e]),`--yes`,...n],`Vercel Blob project connection`)},async getConnections(e){return(await captureJson([`api`,`/v1/storage/stores/${encodeURIComponent(e)}/connections`,`--raw`,...n],z.object({connections:z.array(StoreConnectionSchema)}),`Vercel Blob connections lookup`)).connections},async getProject(){return await captureJson([`api`,`/v9/projects/${encodeURIComponent(e.project.projectId)}?teamId=${encodeURIComponent(e.project.orgId)}`,`--raw`,...n],ProjectSchema,`Vercel project lookup`)},async getStore(e){return(await captureJson([`api`,`/v1/storage/stores/${encodeURIComponent(e)}`,`--raw`,...n],z.object({store:StoreSchema}),`Vercel Blob store lookup`)).store},async listStores(){return(await captureJson([`blob`,`list-stores`,`--all`,`--json`,...n],z.object({stores:z.array(StoreReferenceSchema)}),`Vercel Blob stores lookup`)).stores},async pullEnvironment(){await captureMutation([`env`,`pull`,`.env.local`,`--yes`,`--project`,e.project.projectId,...n],`Vercel environment pull`)}}}function resolveFileMemoryRegion(e){return e.localRegions?.[0]??e.project.resourceConfig?.functionDefaultRegions?.[0]??e.project.defaultResourceConfig?.functionDefaultRegions?.[0]??`iad1`}function fileMemoryStoreName(e,t){let n=e.toLowerCase().replace(/[^a-z0-9]+/gu,`-`).replace(/^-+|-+$/gu,``)||`project`,r=t.toLowerCase().replace(/[^a-z0-9]+/gu,``).slice(-8)||`memory`,i=12+r.length;return`eve-memory-${n.slice(0,64-i).replace(/-+$/gu,``)}-${r}`}async function readLocalRegions(e){try{let t=await readFile(join(e,`vercel.json`),`utf8`),n=z.object({regions:z.array(z.string().min(1)).optional()}).safeParse(JSON.parse(t));if(!n.success)throw Error("vercel.json has an invalid `regions` value.");return n.data.regions}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e instanceof SyntaxError?Error(`vercel.json contains invalid JSON.`):e}}function hasProject(e,t){return e.projects.some(e=>e.id===t)}function exactConnection(e,t){return e.projectId===t&&e.envVarPrefix===`EVE_MEMORY_`}function isEveMemoryConnection(e,t){return e.projectId===t&&e.envVarPrefix?.startsWith(`EVE_MEMORY_`)===!0}function assertPrivateBlobStore(e){if(e.type!==void 0&&e.type!==`blob`)throw Error(`Vercel resource "${e.name}" uses the eve file-memory prefix but is not a Blob store. Disconnect that binding before retrying.`);if(e.access!==`private`)throw Error(`Vercel Blob store "${e.name}" is public. Disconnect an eve-prefixed binding or choose a private store before retrying; eve will not replace it automatically.`)}function assertCompleteConnection(e,t){if(FILE_MEMORY_BLOB_ENVIRONMENTS.filter(t=>!e.envVarEnvironments.includes(t)).length>0)throw Error(`Vercel Blob store "${t}" has an incomplete ${FILE_MEMORY_BLOB_PREFIX} connection. Reconnect it for production, preview, and development before retrying; eve will not disconnect or replace it automatically.`)}async function inspectStore(e,t){let[n,r]=await Promise.all([t.getStore(e.id),t.getConnections(e.id)]);return{connections:r,store:n}}async function prepareFileMemoryBlob(e){let t=e.client??createFileMemoryVercelClient({appRoot:e.appRoot,project:e.project,signal:e.signal}),[n,r,i]=await Promise.all([t.getProject(),e.localRegions?.()??readLocalRegions(e.appRoot),t.listStores()]);if(e.signal?.throwIfAborted(),n.id!==e.project.projectId)throw Error(`Vercel returned project "${n.id}" while file-memory setup expected "${e.project.projectId}". Relink the project and retry.`);let a=resolveFileMemoryRegion({localRegions:r,project:n}),o=fileMemoryStoreName(n.name,n.id),s=i.filter(t=>t.name===o||hasProject(t,e.project.projectId)),c=await Promise.all(s.map(async e=>await inspectStore(e,t))),l=c.flatMap(t=>t.connections.filter(t=>exactConnection(t,e.project.projectId)).map(e=>({candidate:t,connection:e})));if(l.length>1)throw Error(`Multiple Vercel Blob connections target project "${n.name}" with prefix ${FILE_MEMORY_BLOB_PREFIX}. Disconnect the extra binding before retrying.`);if(l.length===1){let t=l[0];if(t===void 0)throw Error(`Expected an eve file-memory Blob store.`);let{candidate:r,connection:i}=t;assertPrivateBlobStore(r.store),assertCompleteConnection(i,r.store.name);let o=r.store.region===a?void 0:`The existing file-memory store remains in ${r.store.region}; the project now prefers ${a}. eve preserved the store to avoid memory loss.`;return{action:`reuse`,project:e.project,projectName:n.name,region:r.store.region,regionWarning:o,storeId:r.store.id,storeName:r.store.name}}let u=c.find(({connections:t})=>t.some(t=>isEveMemoryConnection(t,e.project.projectId)));if(u!==void 0)throw Error(`Vercel resource "${u.store.name}" has an incompatible eve file-memory prefix. Disconnect it before retrying; eve will not change an ambiguous binding automatically.`);let d=c.filter(({store:e})=>e.name===o);if(d.length>1)throw Error(`Multiple Vercel Blob stores match the expected file-memory name "${o}". Rename or remove the duplicate before retrying.`);if(d.length===1){let t=d[0];if(t===void 0)throw Error(`Expected a file-memory Blob store candidate.`);if(assertPrivateBlobStore(t.store),t.store.region!==a)throw Error(`Unconnected Vercel Blob store "${o}" is in ${t.store.region}, but project "${n.name}" uses ${a}. Rename that store or connect it manually; eve will not replace it automatically.`);if(t.connections.length>0)throw Error(`Vercel Blob store "${o}" already has a project connection, so eve cannot safely adopt it. Disconnect it or choose a different store before retrying.`);return{action:`repair`,project:e.project,projectName:n.name,region:a,storeId:t.store.id,storeName:o}}return{action:`create`,project:e.project,projectName:n.name,region:a,storeName:o}}async function verifyFileMemoryBlob(e,t,n){let[r,i]=await Promise.all([n.getStore(t),n.getConnections(t)]);if(assertPrivateBlobStore(r),r.name!==e.storeName)throw Error(`Vercel connected an unexpected Blob store named "${r.name}".`);if(r.region!==e.region)throw Error(`Vercel Blob store "${r.name}" is in ${r.region}, but setup expected ${e.region}.`);let a=i.filter(t=>exactConnection(t,e.project.projectId));if(a.length!==1)throw Error(`Vercel Blob store "${r.name}" does not have exactly one ${FILE_MEMORY_BLOB_PREFIX} connection to project "${e.projectName}".`);let o=a[0];if(o===void 0)throw Error(`Expected a verified eve file-memory connection.`);return assertCompleteConnection(o,r.name),r}async function applyFileMemoryBlob(e){let t=createPromptCommandOutput(e.log),n=e.client??createFileMemoryVercelClient({appRoot:e.appRoot,onOutput:t,project:e.plan.project,signal:e.signal}),r=e.plan.storeId;if(e.plan.action===`create`){let t=await withPhase(e.log,`Creating private Vercel Blob store...`,async()=>await n.createStore({name:e.plan.storeName,region:e.plan.region}));if(assertPrivateBlobStore(t),t.name!==e.plan.storeName||t.region!==e.plan.region)throw Error(`Vercel created Blob store "${t.name}" in ${t.region}, but setup expected "${e.plan.storeName}" in ${e.plan.region}.`);r=t.id}if(r===void 0)throw Error(`File-memory Blob setup did not resolve a store ID.`);e.plan.action!==`reuse`&&await withPhase(e.log,`Connecting file memory to the Vercel project...`,async()=>await n.connectStore({environments:FILE_MEMORY_BLOB_ENVIRONMENTS,prefix:FILE_MEMORY_BLOB_PREFIX,projectId:e.plan.project.projectId,storeName:e.plan.storeName})),await withPhase(e.log,`Pulling Vercel environment variables...`,async()=>await n.pullEnvironment());let i=await withPhase(e.log,`Verifying file-memory storage...`,async()=>await verifyFileMemoryBlob(e.plan,r,n));return{action:e.plan.action,store:i}}export{FILE_MEMORY_BLOB_ENVIRONMENTS,FILE_MEMORY_BLOB_PREFIX,applyFileMemoryBlob,createFileMemoryVercelClient,fileMemoryStoreName,prepareFileMemoryBlob,resolveFileMemoryRegion};
1
+ import{readFile}from"node:fs/promises";import{z}from"#compiled/zod/index.js";import{join}from"node:path";import{captureVercel}from"#setup/primitives/run-vercel.js";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";const FILE_MEMORY_BLOB_PREFIX=`EVE_MEMORY_BLOB`,FILE_MEMORY_BLOB_ENVIRONMENTS=[`production`,`preview`,`development`],ProjectSchema=z.object({id:z.string().min(1),name:z.string().min(1),resourceConfig:z.object({functionDefaultRegions:z.array(z.string().min(1)).optional()}).optional(),defaultResourceConfig:z.object({functionDefaultRegions:z.array(z.string().min(1)).optional()}).optional()}).passthrough(),StoreReferenceSchema=z.object({id:z.string().min(1),name:z.string().min(1),projects:z.array(z.object({id:z.string().min(1),name:z.string().min(1)}).passthrough()).default([]),region:z.string().min(1).optional()}).passthrough(),StoreSchema=z.object({access:z.enum([`private`,`public`]),id:z.string().min(1),name:z.string().min(1),region:z.string().min(1),type:z.string().optional()}).passthrough(),StoreConnectionSchema=z.object({envVarEnvironments:z.array(z.string()).default([]),envVarPrefix:z.string().nullish(),id:z.string().optional(),projectId:z.string().min(1)}).passthrough();function parseJson(e,t,n){try{return t.parse(JSON.parse(e))}catch{throw Error(`Vercel returned invalid ${n} data. Upgrade the Vercel CLI and try again.`)}}function commandFailure(e,t){let n=[t.failure.stderr,t.failure.stdout,t.failure.message].find(e=>e.trim().length>0);return Error(n===void 0?`${e} failed.`:`${e} failed: ${n.trim()}`)}function createFileMemoryVercelClient(e){let t={cwd:e.appRoot,nonInteractive:!0,onOutput:e.onOutput,signal:e.signal},n=[`--scope`,e.project.orgId];async function captureJson(n,r,i,a){let o=await captureVercel(n,{...t,stdin:a});if(e.signal?.throwIfAborted(),!o.ok)throw commandFailure(i,o);return parseJson(o.stdout,r,i.toLowerCase())}async function captureMutation(n,r,i){let a=await captureVercel(n,{...t,stdin:i});if(e.signal?.throwIfAborted(),!a.ok)throw commandFailure(r,a)}return{async createStore({name:e,region:t}){return(await captureJson([`api`,`/v1/storage/stores/blob`,`-X`,`POST`,`--input`,`-`,`--raw`,...n],z.object({store:StoreSchema}),`Vercel Blob store creation`,JSON.stringify({access:`private`,name:e,region:t}))).store},async connectStore({environments:e,prefix:t,projectId:r,storeId:i}){await captureMutation([`api`,`/v1/storage/stores/${encodeURIComponent(i)}/connections`,`-X`,`POST`,`--header`,`x-vercel-use-oidc: 1`,`--input`,`-`,...n],`Vercel Blob project connection`,JSON.stringify({envVarEnvironments:e,envVarPrefix:t,projectId:r,skipReadWriteToken:!0}))},async getConnections(e){return(await captureJson([`api`,`/v1/storage/stores/${encodeURIComponent(e)}/connections`,`--raw`,...n],z.object({connections:z.array(StoreConnectionSchema)}),`Vercel Blob connections lookup`)).connections},async getProject(){return await captureJson([`api`,`/v9/projects/${encodeURIComponent(e.project.projectId)}?teamId=${encodeURIComponent(e.project.orgId)}`,`--raw`,...n],ProjectSchema,`Vercel project lookup`)},async getStore(e){return(await captureJson([`api`,`/v1/storage/stores/${encodeURIComponent(e)}`,`--raw`,...n],z.object({store:StoreSchema}),`Vercel Blob store lookup`)).store},async listStores(){return(await captureJson([`blob`,`list-stores`,`--all`,`--json`,...n],z.object({stores:z.array(StoreReferenceSchema)}),`Vercel Blob stores lookup`)).stores},async pullEnvironment(){await captureMutation([`env`,`pull`,`.env.local`,`--yes`,`--project`,e.project.projectId,...n],`Vercel environment pull`)}}}function resolveFileMemoryRegion(e){return e.localRegions?.[0]??e.project.resourceConfig?.functionDefaultRegions?.[0]??e.project.defaultResourceConfig?.functionDefaultRegions?.[0]??`iad1`}function fileMemoryStoreName(e,t){let n=e.toLowerCase().replace(/[^a-z0-9]+/gu,`-`).replace(/^-+|-+$/gu,``)||`project`,r=t.toLowerCase().replace(/[^a-z0-9]+/gu,``).slice(-8)||`memory`,i=12+r.length;return`eve-memory-${n.slice(0,64-i).replace(/-+$/gu,``)}-${r}`}async function readLocalRegions(e){try{let t=await readFile(join(e,`vercel.json`),`utf8`),n=z.object({regions:z.array(z.string().min(1)).optional()}).safeParse(JSON.parse(t));if(!n.success)throw Error("vercel.json has an invalid `regions` value.");return n.data.regions}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e instanceof SyntaxError?Error(`vercel.json contains invalid JSON.`):e}}function hasProject(e,t){return e.projects.some(e=>e.id===t)}function exactConnection(e,t){return e.projectId===t&&e.envVarPrefix===`EVE_MEMORY_BLOB`}function isEveMemoryConnection(e,t){return e.projectId===t&&e.envVarPrefix?.startsWith(`EVE_MEMORY_`)===!0}function assertPrivateBlobStore(e){if(e.type!==void 0&&e.type!==`blob`)throw Error(`Vercel resource "${e.name}" uses the eve file-memory prefix but is not a Blob store. Disconnect that binding before retrying.`);if(e.access!==`private`)throw Error(`Vercel Blob store "${e.name}" is public. Disconnect an eve-prefixed binding or choose a private store before retrying; eve will not replace it automatically.`)}function assertCompleteConnection(e,t){if(FILE_MEMORY_BLOB_ENVIRONMENTS.filter(t=>!e.envVarEnvironments.includes(t)).length>0)throw Error(`Vercel Blob store "${t}" has an incomplete ${FILE_MEMORY_BLOB_PREFIX} connection. Reconnect it for production, preview, and development before retrying; eve will not disconnect or replace it automatically.`)}async function inspectStore(e,t){let[n,r]=await Promise.all([t.getStore(e.id),t.getConnections(e.id)]);return{connections:r,store:n}}async function prepareFileMemoryBlob(e){let t=e.client??createFileMemoryVercelClient({appRoot:e.appRoot,project:e.project,signal:e.signal}),[n,r,i]=await Promise.all([t.getProject(),e.localRegions?.()??readLocalRegions(e.appRoot),t.listStores()]);if(e.signal?.throwIfAborted(),n.id!==e.project.projectId)throw Error(`Vercel returned project "${n.id}" while file-memory setup expected "${e.project.projectId}". Relink the project and retry.`);let a=resolveFileMemoryRegion({localRegions:r,project:n}),o=fileMemoryStoreName(n.name,n.id),s=i.filter(t=>t.name===o||hasProject(t,e.project.projectId)),c=await Promise.all(s.map(async e=>await inspectStore(e,t))),l=c.flatMap(t=>t.connections.filter(t=>exactConnection(t,e.project.projectId)).map(e=>({candidate:t,connection:e})));if(l.length>1)throw Error(`Multiple Vercel Blob connections target project "${n.name}" with prefix ${FILE_MEMORY_BLOB_PREFIX}. Disconnect the extra binding before retrying.`);if(l.length===1){let t=l[0];if(t===void 0)throw Error(`Expected an eve file-memory Blob store.`);let{candidate:r,connection:i}=t;assertPrivateBlobStore(r.store),assertCompleteConnection(i,r.store.name);let o=r.store.region===a?void 0:`The existing file-memory store remains in ${r.store.region}; the project now prefers ${a}. eve preserved the store to avoid memory loss.`;return{action:`reuse`,project:e.project,projectName:n.name,region:r.store.region,regionWarning:o,storeId:r.store.id,storeName:r.store.name}}let u=c.find(({connections:t})=>t.some(t=>isEveMemoryConnection(t,e.project.projectId)));if(u!==void 0)throw Error(`Vercel resource "${u.store.name}" has an incompatible eve file-memory prefix. Disconnect it before retrying; eve will not change an ambiguous binding automatically.`);let d=c.filter(({store:e})=>e.name===o);if(d.length>1)throw Error(`Multiple Vercel Blob stores match the expected file-memory name "${o}". Rename or remove the duplicate before retrying.`);if(d.length===1){let t=d[0];if(t===void 0)throw Error(`Expected a file-memory Blob store candidate.`);if(assertPrivateBlobStore(t.store),t.store.region!==a)throw Error(`Unconnected Vercel Blob store "${o}" is in ${t.store.region}, but project "${n.name}" uses ${a}. Rename that store or connect it manually; eve will not replace it automatically.`);if(t.connections.length>0)throw Error(`Vercel Blob store "${o}" already has a project connection, so eve cannot safely adopt it. Disconnect it or choose a different store before retrying.`);return{action:`repair`,project:e.project,projectName:n.name,region:a,storeId:t.store.id,storeName:o}}return{action:`create`,project:e.project,projectName:n.name,region:a,storeName:o}}async function verifyFileMemoryBlob(e,t,n){let[r,i]=await Promise.all([n.getStore(t),n.getConnections(t)]);if(assertPrivateBlobStore(r),r.name!==e.storeName)throw Error(`Vercel connected an unexpected Blob store named "${r.name}".`);if(r.region!==e.region)throw Error(`Vercel Blob store "${r.name}" is in ${r.region}, but setup expected ${e.region}.`);let a=i.filter(t=>exactConnection(t,e.project.projectId));if(a.length!==1)throw Error(`Vercel Blob store "${r.name}" does not have exactly one ${FILE_MEMORY_BLOB_PREFIX} connection to project "${e.projectName}".`);let o=a[0];if(o===void 0)throw Error(`Expected a verified eve file-memory connection.`);return assertCompleteConnection(o,r.name),r}async function applyFileMemoryBlob(e){let t=createPromptCommandOutput(e.log),n=e.client??createFileMemoryVercelClient({appRoot:e.appRoot,onOutput:t,project:e.plan.project,signal:e.signal}),r=e.plan.storeId;if(e.plan.action===`create`){let t=await withPhase(e.log,`Creating private Vercel Blob store...`,async()=>await n.createStore({name:e.plan.storeName,region:e.plan.region}));if(assertPrivateBlobStore(t),t.name!==e.plan.storeName||t.region!==e.plan.region)throw Error(`Vercel created Blob store "${t.name}" in ${t.region}, but setup expected "${e.plan.storeName}" in ${e.plan.region}.`);r=t.id}if(r===void 0)throw Error(`File-memory Blob setup did not resolve a store ID.`);e.plan.action!==`reuse`&&await withPhase(e.log,`Connecting file memory to the Vercel project...`,async()=>await n.connectStore({environments:FILE_MEMORY_BLOB_ENVIRONMENTS,prefix:FILE_MEMORY_BLOB_PREFIX,projectId:e.plan.project.projectId,storeId:r})),await withPhase(e.log,`Pulling Vercel environment variables...`,async()=>await n.pullEnvironment());let i=await withPhase(e.log,`Verifying file-memory storage...`,async()=>await verifyFileMemoryBlob(e.plan,r,n));return{action:e.plan.action,store:i}}export{FILE_MEMORY_BLOB_ENVIRONMENTS,FILE_MEMORY_BLOB_PREFIX,applyFileMemoryBlob,createFileMemoryVercelClient,fileMemoryStoreName,prepareFileMemoryBlob,resolveFileMemoryRegion};
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.82`,DEFAULT_CONNECT_PACKAGE_VERSION=`1.0.0`,DEFAULT_ZOD_PACKAGE_VERSION=`4.5.4`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.52.1`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e,t){return{"agent/agent.ts":renderAgentTemplate(e,t),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderAgentTemplate(e,t){let n=parseChatGptModelSelection(e);return n===void 0?BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t)):`import { defineAgent } from "eve";\nimport { chatgpt } from "eve/models/openai";\n\nexport default defineAgent({\n model: chatgpt(${JSON.stringify(n)}),\n${reasoningTemplateLine(t)}});\n`}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,t){return e===BASE_AGENT_TEMPLATE&&parseChatGptModelSelection(t.model)!==void 0?renderAgentTemplate(t.model,t.reasoning):e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t.reasoning)).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
1
+ import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.82`,DEFAULT_CONNECT_PACKAGE_VERSION=`1.0.0`,DEFAULT_ZOD_PACKAGE_VERSION=`4.5.4`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.52.3`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e,t){return{"agent/agent.ts":renderAgentTemplate(e,t),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderAgentTemplate(e,t){let n=parseChatGptModelSelection(e);return n===void 0?BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t)):`import { defineAgent } from "eve";\nimport { chatgpt } from "eve/models/openai";\n\nexport default defineAgent({\n model: chatgpt(${JSON.stringify(n)}),\n${reasoningTemplateLine(t)}});\n`}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,t){return e===BASE_AGENT_TEMPLATE&&parseChatGptModelSelection(t.model)!==void 0?renderAgentTemplate(t.model,t.reasoning):e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t.reasoning)).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
2
2
 
3
3
  export default defineAgent({
4
4
  model: "__EVE_INIT_MODEL__",
@@ -244,6 +244,7 @@ export type InternalAgentDefinition = {
244
244
  description?: string;
245
245
  build?: AgentBuildDefinition;
246
246
  compaction?: InternalAgentCompactionDefinition;
247
+ defaultTools?: boolean;
247
248
  experimental?: AgentExperimentalDefinition;
248
249
  model: InternalAgentModelDefinition;
249
250
  outputSchema?: JsonObject;
@@ -267,6 +268,12 @@ type PublicAgentDefinitionBase = {
267
268
  readonly description?: string;
268
269
  readonly build?: AgentBuildDefinition;
269
270
  readonly compaction?: PublicAgentCompactionDefinition;
271
+ /**
272
+ * Whether eve automatically adds its optional default tools. Defaults to `true`.
273
+ * Required connection tooling and tools authored under `agent/tools/` remain
274
+ * available when this is `false`.
275
+ */
276
+ readonly defaultTools?: boolean;
270
277
  /**
271
278
  * Experimental, opt-in capabilities. Unstable, see
272
279
  * {@link AgentExperimentalDefinition}.
@@ -0,0 +1,4 @@
1
+ /** Distinguishes authored admission failures from failed runtime lifecycle work. */
2
+ export declare class BoundaryHookError extends Error {
3
+ constructor(cause: unknown);
4
+ }
@@ -0,0 +1 @@
1
+ import{toErrorMessage}from"#shared/errors.js";var BoundaryHookError=class extends Error{constructor(e){super(toErrorMessage(e),{cause:e}),this.name=`BoundaryHookError`}};export{BoundaryHookError};
@@ -1,3 +1,3 @@
1
1
  export declare const MAX_ACTIVITY_TEXT_LENGTH = 500;
2
2
  /** Normalizes bounded untrusted presentation text before it reaches a renderer. */
3
- export declare function normalizeActivityText(text: string): string;
3
+ export declare function normalizePresentationText(text: string): string;
@@ -0,0 +1 @@
1
+ const MAX_ACTIVITY_TEXT_LENGTH=500;function normalizePresentationText(e){return e.replace(/\p{Cc}/gu,` `).replace(/\s+/g,` `).trim().slice(0,500)}export{MAX_ACTIVITY_TEXT_LENGTH,normalizePresentationText};
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-Crmh_YB-.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-XnfjQt1Z.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-Crmh_YB-.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-XnfjQt1Z.js";
2
2
 
3
3
  export { useEveAgent };
@@ -19,6 +19,14 @@ interface ToolDefinitionBase {
19
19
  readonly description: string;
20
20
  readonly execution?: ToolExecution;
21
21
  }
22
+ export interface ToolLabelDefinition<TInput = unknown, TOutput = unknown> {
23
+ /** Returns the presentation-safe label when one action invocation starts. */
24
+ start(input: Readonly<TInput>): string;
25
+ /** Projects one preliminary output snapshot into presentation-safe label text. */
26
+ delta?(input: Readonly<TInput>, partial: Readonly<TOutput>): string;
27
+ /** Projects a successful final output into presentation-safe settlement text. */
28
+ complete?(input: Readonly<TInput>, output: Readonly<TOutput>): string;
29
+ }
22
30
  /**
23
31
  * Internal/compiled tool definition shape. Carries `name` because the
24
32
  * compiler stamps a path-derived identifier onto every tool entry.
@@ -26,7 +34,13 @@ interface ToolDefinitionBase {
26
34
  * Authored public definitions (see {@link PublicToolDefinition}) do not
27
35
  * carry `name`; identity comes from the file path.
28
36
  */
37
+ export interface InternalToolLabelDefinition {
38
+ readonly complete?: (input: unknown, output: unknown) => string;
39
+ readonly delta?: (input: unknown, partial: unknown) => string;
40
+ readonly start?: (input: unknown) => string;
41
+ }
29
42
  export interface InternalToolDefinition extends ToolDefinitionBase {
43
+ label?: InternalToolLabelDefinition;
30
44
  name: string;
31
45
  inputSchema: JsonObject | null;
32
46
  outputSchema?: JsonObject;
@@ -38,12 +52,15 @@ export type PublicToolOutputSchema<TOutput = unknown> = StandardJSONSchemaV1<unk
38
52
  * file path at compile time, so `name` is intentionally absent here.
39
53
  */
40
54
  export interface PublicToolDefinition<TInput = unknown, TOutput = unknown> extends ToolDefinitionBase {
55
+ label?: ToolLabelDefinition<TInput, TOutput>;
41
56
  inputSchema: PublicToolInputSchema<TInput>;
42
57
  /**
43
58
  * Optional schema describing the value returned by the tool executor.
44
59
  * The AI SDK can use this for tool result typing.
45
60
  */
46
61
  outputSchema?: PublicToolOutputSchema<TOutput>;
62
+ /** Derives the input-scoped key recorded when this tool is approved. */
63
+ approvalKey?: (input: Readonly<ApprovalContextInput<TInput>>) => string;
47
64
  }
48
65
  export interface InternalToolDefinitionWithExecuteFn<TInput = unknown, TOutput = unknown> extends InternalToolDefinition {
49
66
  execute: ToolExecuteFn<TInput, TOutput>;
@@ -178,7 +195,9 @@ export declare function defineTool<TSchema extends StandardSchemaV1<unknown, unk
178
195
  inputSchema: TSchema;
179
196
  outputSchema?: PublicToolDefinition<unknown, TaskReceipt>["outputSchema"];
180
197
  execute(input: StandardSchemaV1.InferOutput<TSchema>, ctx: ToolContext, task: TaskExec): TReturn;
198
+ label?: BackgroundToolDefinition<StandardSchemaV1.InferOutput<TSchema>, BackgroundToolOutputFromExecuteReturn<TReturn>>["label"];
181
199
  approval?: BackgroundToolDefinition<StandardSchemaV1.InferOutput<TSchema>, unknown>["approval"];
200
+ approvalKey?: BackgroundToolDefinition<StandardSchemaV1.InferOutput<TSchema>, unknown>["approvalKey"];
182
201
  toModelOutput?: BackgroundToolDefinition<unknown, BackgroundToolOutputFromExecuteReturn<TReturn>>["toModelOutput"];
183
202
  }): BackgroundToolDefinitionWithExecuteReturn<StandardSchemaV1.InferOutput<TSchema>, BackgroundToolOutputFromExecuteReturn<TReturn>, TReturn>;
184
203
  export declare function defineTool<TInputSchema extends StandardSchemaV1<unknown, unknown> | StandardJSONSchemaV1<unknown, unknown>, TOutputSchema extends StandardJSONSchemaV1<unknown, unknown>, TReturn extends Promise<StandardJSONSchemaV1.InferOutput<TOutputSchema>> | StandardJSONSchemaV1.InferOutput<TOutputSchema> | AsyncIterable<StandardJSONSchemaV1.InferOutput<TOutputSchema>>>(definition: {
@@ -186,7 +205,9 @@ export declare function defineTool<TInputSchema extends StandardSchemaV1<unknown
186
205
  inputSchema: TInputSchema;
187
206
  outputSchema: TOutputSchema;
188
207
  execute(input: StandardSchemaV1.InferOutput<TInputSchema>, ctx: ToolContext): TReturn;
208
+ label?: ToolDefinition<StandardSchemaV1.InferOutput<TInputSchema>, StandardJSONSchemaV1.InferOutput<TOutputSchema>>["label"];
189
209
  approval?: ToolDefinition<StandardSchemaV1.InferOutput<TInputSchema>, unknown>["approval"];
210
+ approvalKey?: ToolDefinition<StandardSchemaV1.InferOutput<TInputSchema>, unknown>["approvalKey"];
190
211
  toModelOutput?: ToolDefinition<unknown, StandardJSONSchemaV1.InferOutput<TOutputSchema>>["toModelOutput"];
191
212
  }): ToolDefinitionWithExecuteReturn<StandardSchemaV1.InferOutput<TInputSchema>, StandardJSONSchemaV1.InferOutput<TOutputSchema>, TReturn>;
192
213
  export declare function defineTool<TSchema extends StandardSchemaV1<unknown, unknown> | StandardJSONSchemaV1<unknown, unknown>, TReturn>(definition: {
@@ -194,7 +215,9 @@ export declare function defineTool<TSchema extends StandardSchemaV1<unknown, unk
194
215
  inputSchema: TSchema;
195
216
  outputSchema?: JsonObject;
196
217
  execute(input: StandardSchemaV1.InferOutput<TSchema>, ctx: ToolContext): TReturn;
218
+ label?: ToolDefinition<StandardSchemaV1.InferOutput<TSchema>, ToolOutputFromExecuteReturn<TReturn>>["label"];
197
219
  approval?: ToolDefinition<StandardSchemaV1.InferOutput<TSchema>, unknown>["approval"];
220
+ approvalKey?: ToolDefinition<StandardSchemaV1.InferOutput<TSchema>, unknown>["approvalKey"];
198
221
  toModelOutput?: ToolDefinition<unknown, ToolOutputFromExecuteReturn<TReturn>>["toModelOutput"];
199
222
  }): ToolDefinitionWithExecuteReturn<StandardSchemaV1.InferOutput<TSchema>, ToolOutputFromExecuteReturn<TReturn>, TReturn>;
200
223
  export declare function defineTool<TOutputSchema extends StandardJSONSchemaV1<unknown, unknown>, TReturn extends Promise<StandardJSONSchemaV1.InferOutput<TOutputSchema>> | StandardJSONSchemaV1.InferOutput<TOutputSchema> | AsyncIterable<StandardJSONSchemaV1.InferOutput<TOutputSchema>>>(definition: {
@@ -202,7 +225,9 @@ export declare function defineTool<TOutputSchema extends StandardJSONSchemaV1<un
202
225
  inputSchema: JsonObject;
203
226
  outputSchema: TOutputSchema;
204
227
  execute(input: Record<string, unknown>, ctx: ToolContext): TReturn;
228
+ label?: ToolDefinition<Record<string, unknown>, StandardJSONSchemaV1.InferOutput<TOutputSchema>>["label"];
205
229
  approval?: ToolDefinition<Record<string, unknown>, unknown>["approval"];
230
+ approvalKey?: ToolDefinition<Record<string, unknown>, unknown>["approvalKey"];
206
231
  toModelOutput?: ToolDefinition<unknown, StandardJSONSchemaV1.InferOutput<TOutputSchema>>["toModelOutput"];
207
232
  }): ToolDefinitionWithExecuteReturn<Record<string, unknown>, StandardJSONSchemaV1.InferOutput<TOutputSchema>, TReturn>;
208
233
  export declare function defineTool<TReturn>(definition: {
@@ -210,14 +235,18 @@ export declare function defineTool<TReturn>(definition: {
210
235
  inputSchema: JsonObject;
211
236
  outputSchema?: JsonObject;
212
237
  execute(input: Record<string, unknown>, ctx: ToolContext): TReturn;
238
+ label?: ToolDefinition<Record<string, unknown>, ToolOutputFromExecuteReturn<TReturn>>["label"];
213
239
  approval?: ToolDefinition<Record<string, unknown>, unknown>["approval"];
240
+ approvalKey?: ToolDefinition<Record<string, unknown>, unknown>["approvalKey"];
214
241
  toModelOutput?: ToolDefinition<unknown, ToolOutputFromExecuteReturn<TReturn>>["toModelOutput"];
215
242
  }): ToolDefinitionWithExecuteReturn<Record<string, unknown>, ToolOutputFromExecuteReturn<TReturn>, TReturn>;
216
243
  export declare function defineTool<TInput = unknown, TOutput = unknown>(definition: ToolDefinition<TInput, TOutput>): ToolDefinition<TInput, TOutput>;
217
244
  export declare function stampToolDefinition<T extends {
218
245
  readonly description: string;
219
246
  readonly execute: (...args: never[]) => unknown;
247
+ readonly label?: ToolLabelDefinition;
220
248
  readonly approval?: Approval<never>;
249
+ readonly approvalKey?: (...args: never[]) => unknown;
221
250
  readonly toModelOutput?: (...args: never[]) => unknown;
222
251
  }>(definition: T, definer: "defineTool" | "defineWorkflowTool"): T;
223
252
  /**
@@ -1 +1 @@
1
- import{collectDurableDynamicToolCallbacks,stampDurableDynamicToolCallbacks}from"#tools/durable-callbacks.js";import{TOOL_BRAND}from"#tools/dynamic.js";import{stampDefinitionKey}from"#internal/authored-definition/source-identity.js";function defineTool(e){return stampToolDefinition(e,`defineTool`)}function stampToolDefinition(e,t){if(e.auth!==void 0)throw Error(`${t}: The "auth" field is no longer supported. Pass auth providers inline to ctx.getToken(provider) or ctx.requireAuth(provider).`);return Object.assign(e,{[TOOL_BRAND]:!0}),stampDurableDynamicToolCallbacks(e,collectDurableDynamicToolCallbacks({approval:e.approval,execute:e.execute,toModelOutput:e.toModelOutput})),stampDefinitionKey(e,`tool:${e.description}`),e}const DISABLED_TOOL_SENTINEL_KIND=`eve:disabled-tool`;function disableTool(){return{kind:DISABLED_TOOL_SENTINEL_KIND}}function isDisabledToolSentinel(e){return typeof e==`object`&&!!e&&e.kind===DISABLED_TOOL_SENTINEL_KIND}export{defineTool,disableTool,isDisabledToolSentinel,stampToolDefinition};
1
+ import{collectDurableDynamicToolCallbacks,stampDurableDynamicToolCallbacks}from"#tools/durable-callbacks.js";import{TOOL_BRAND}from"#tools/dynamic.js";import{stampDefinitionKey}from"#internal/authored-definition/source-identity.js";function defineTool(e){return stampToolDefinition(e,`defineTool`)}function stampToolDefinition(e,t){if(e.auth!==void 0)throw Error(`${t}: The "auth" field is no longer supported. Pass auth providers inline to ctx.getToken(provider) or ctx.requireAuth(provider).`);return Object.assign(e,{[TOOL_BRAND]:!0}),stampDurableDynamicToolCallbacks(e,collectDurableDynamicToolCallbacks({label:e.label,approval:e.approval,approvalKey:e.approvalKey,execute:e.execute,toModelOutput:e.toModelOutput})),stampDefinitionKey(e,`tool:${e.description}`),e}const DISABLED_TOOL_SENTINEL_KIND=`eve:disabled-tool`;function disableTool(){return{kind:DISABLED_TOOL_SENTINEL_KIND}}function isDisabledToolSentinel(e){return typeof e==`object`&&!!e&&e.kind===DISABLED_TOOL_SENTINEL_KIND}export{defineTool,disableTool,isDisabledToolSentinel,stampToolDefinition};
@@ -1,10 +1,11 @@
1
1
  import type { Approval } from "#approval/definition.js";
2
2
  import type { JsonObject } from "#shared/json.js";
3
- export type DurableDynamicCallbackPhase = "approvalRequest" | "approvalResponse" | "execute" | "toModelOutput";
3
+ export type DurableDynamicCallbackPhase = "labelComplete" | "labelDelta" | "labelStart" | "approvalKey" | "approvalRequest" | "approvalResponse" | "execute" | "toModelOutput";
4
4
  export type DurableDynamicCallbackFn = (closure: JsonObject, ...args: never[]) => unknown;
5
5
  /**
6
6
  * Persisted binding for one callback phase. Identity is
7
- * `(toolName, phase)` — carried by the surrounding metadata — so only the
7
+ * session, lifecycle scope, resolver, entry, tool name, and phase — carried
8
+ * by the surrounding context and metadata — so only the
8
9
  * snapshotted closure values persist.
9
10
  */
10
11
  export interface DurableDynamicCallbackReference {
@@ -13,6 +14,12 @@ export interface DurableDynamicCallbackReference {
13
14
  }
14
15
  export interface DurableDynamicToolCallbacks {
15
16
  readonly execute: DurableDynamicCallbackReference;
17
+ readonly label?: {
18
+ readonly complete?: DurableDynamicCallbackReference;
19
+ readonly delta?: DurableDynamicCallbackReference;
20
+ readonly start?: DurableDynamicCallbackReference;
21
+ };
22
+ readonly approvalKey?: DurableDynamicCallbackReference;
16
23
  readonly approvalRequest?: DurableDynamicCallbackReference;
17
24
  readonly approvalResponse?: DurableDynamicCallbackReference;
18
25
  readonly toModelOutput?: DurableDynamicCallbackReference;
@@ -24,35 +31,59 @@ export interface StampedDurableDynamicCallback {
24
31
  }
25
32
  export type LiveDurableDynamicToolCallbacks = Partial<{
26
33
  execute: StampedDurableDynamicCallback;
34
+ label: {
35
+ readonly complete?: StampedDurableDynamicCallback;
36
+ readonly delta?: StampedDurableDynamicCallback;
37
+ readonly start?: StampedDurableDynamicCallback;
38
+ };
39
+ approvalKey: StampedDurableDynamicCallback;
27
40
  approvalRequest: StampedDurableDynamicCallback;
28
41
  approvalResponse: StampedDurableDynamicCallback;
29
42
  toModelOutput: StampedDurableDynamicCallback;
30
43
  }>;
31
44
  export declare const DURABLE_DYNAMIC_TOOL_CALLBACKS: unique symbol;
32
- /**
33
- * Binds the current implementation of one tool callback phase. Re-resolution
34
- * replaces the binding, so replay after a redeploy runs the latest code.
35
- */
45
+ export type DynamicToolCallbackScope = "session" | "turn" | "step";
46
+ export interface DynamicToolCallbackOwner {
47
+ readonly sessionId: string;
48
+ readonly scope: DynamicToolCallbackScope;
49
+ readonly resolverSlug: string;
50
+ readonly entryKey: string;
51
+ readonly name: string;
52
+ }
53
+ /** Re-resolution updates only the same session's resolver and lifecycle scope. */
36
54
  export declare function registerDurableDynamicCallback(input: {
37
55
  readonly callback: DurableDynamicCallbackFn;
38
56
  readonly phase: DurableDynamicCallbackPhase;
39
- readonly toolName: string;
57
+ readonly owner: DynamicToolCallbackOwner;
58
+ }): void;
59
+ export declare function lookupDurableDynamicCallback(owner: DynamicToolCallbackOwner, phase: DurableDynamicCallbackPhase): DurableDynamicCallbackFn | undefined;
60
+ /** Discards completed sessions or a resolver's previous result before replacement. */
61
+ export declare function clearDurableDynamicCallbacks(sessionId: string, resolver?: {
62
+ readonly scope: DynamicToolCallbackScope;
63
+ readonly resolverSlug: string;
40
64
  }): void;
41
- export declare function lookupDurableDynamicCallback(toolName: string, phase: DurableDynamicCallbackPhase): DurableDynamicCallbackFn | undefined;
42
65
  /** Invokes a registered callback with its snapshotted closure and live arguments. */
43
66
  export declare function callDurableDynamicCallback(callback: DurableDynamicCallbackFn, closure: JsonObject, ...args: unknown[]): unknown;
44
67
  /** True when any persisted callback of these tools has no registered binding. */
45
68
  export declare function hasUnregisteredDurableDynamicCallbacks(metadata: readonly {
46
69
  callbacks: DurableDynamicToolCallbacks;
47
70
  name: string;
48
- }[]): boolean;
71
+ resolverSlug: string;
72
+ entryKey: string;
73
+ }[], scope: Pick<DynamicToolCallbackOwner, "sessionId" | "scope">): boolean;
49
74
  /** Marks a live callback with the descriptor needed to register it at resolve time. */
50
75
  export declare function stampDurableDynamicCallback<TCallback extends (...args: never[]) => unknown>(callback: TCallback, descriptor: StampedDurableDynamicCallback): TCallback;
51
76
  export declare function readDurableDynamicCallback(callback: unknown): StampedDurableDynamicCallback | undefined;
52
77
  /** Copies phase-specific callback descriptors onto a branded tool definition. */
53
78
  export declare function stampDurableDynamicToolCallbacks(definition: object, callbacks: LiveDurableDynamicToolCallbacks): void;
54
79
  export declare function collectDurableDynamicToolCallbacks(input: {
80
+ readonly label?: {
81
+ readonly complete?: (...args: never[]) => unknown;
82
+ readonly delta?: (...args: never[]) => unknown;
83
+ readonly start?: (...args: never[]) => unknown;
84
+ };
55
85
  readonly approval?: Approval<never>;
86
+ readonly approvalKey?: (...args: never[]) => unknown;
56
87
  readonly execute: (...args: never[]) => unknown;
57
88
  readonly toModelOutput?: (...args: never[]) => unknown;
58
89
  }): LiveDurableDynamicToolCallbacks;
@@ -1 +1 @@
1
- import{resolveApprovalPolicy}from"#approval/definition.js";const STAMPED_CALLBACK=Symbol.for(`eve:durable-dynamic-callback`),DURABLE_DYNAMIC_TOOL_CALLBACKS=Symbol.for(`eve:durable-dynamic-tool-callbacks`),REGISTRY=Symbol.for(`eve:dynamic-tool-callbacks`);function getRegistry(){let e=globalThis,t=e[REGISTRY];if(t!==void 0)return t;let n=new Map;return e[REGISTRY]=n,n}function registerDurableDynamicCallback(e){let t=getRegistry(),n=t.get(e.toolName);n===void 0&&(n=new Map,t.set(e.toolName,n)),n.set(e.phase,e.callback)}function lookupDurableDynamicCallback(e,t){return getRegistry().get(e)?.get(t)}function callDurableDynamicCallback(e,t,...n){return e(t,...n)}function hasUnregisteredDurableDynamicCallbacks(e){return e.some(e=>Object.keys(e.callbacks).some(t=>lookupDurableDynamicCallback(e.name,t)===void 0))}function stampDurableDynamicCallback(e,t){return Object.defineProperty(e,STAMPED_CALLBACK,{configurable:!0,value:t}),e}function readDurableDynamicCallback(e){if(typeof e==`function`)return Reflect.get(e,STAMPED_CALLBACK)}function stampDurableDynamicToolCallbacks(e,t){Object.defineProperty(e,DURABLE_DYNAMIC_TOOL_CALLBACKS,{configurable:!0,value:t})}function collectDurableDynamicToolCallbacks(e){let t=e.approval===void 0?void 0:readDurableDynamicCallback(resolveApprovalPolicy(e.approval)),n=e.approval===void 0||typeof e.approval==`function`?void 0:readDurableDynamicCallback(e.approval.response),r=readDurableDynamicCallback(e.execute),i=readDurableDynamicCallback(e.toModelOutput),a={};return r!==void 0&&(a.execute=r),t!==void 0&&(a.approvalRequest=t),n!==void 0&&(a.approvalResponse=n),i!==void 0&&(a.toModelOutput=i),a}function readDurableDynamicToolCallbacks(e){return e[DURABLE_DYNAMIC_TOOL_CALLBACKS]}export{DURABLE_DYNAMIC_TOOL_CALLBACKS,callDurableDynamicCallback,collectDurableDynamicToolCallbacks,hasUnregisteredDurableDynamicCallbacks,lookupDurableDynamicCallback,readDurableDynamicCallback,readDurableDynamicToolCallbacks,registerDurableDynamicCallback,stampDurableDynamicCallback,stampDurableDynamicToolCallbacks};
1
+ import{resolveApprovalPolicy}from"#approval/definition.js";const STAMPED_CALLBACK=Symbol.for(`eve:durable-dynamic-callback`),DURABLE_DYNAMIC_TOOL_CALLBACKS=Symbol.for(`eve:durable-dynamic-tool-callbacks`),REGISTRY=Symbol.for(`eve:scoped-dynamic-tool-callbacks`);function getRegistry(){let e=globalThis;return e[REGISTRY]??=new Map}function getSessionBindings(e){let t=getRegistry(),n=t.get(e);return n!==void 0&&(t.delete(e),t.set(e,n)),n}function callbackKey(e,t){return JSON.stringify([e.scope,e.resolverSlug,e.entryKey,e.name,t])}function registerDurableDynamicCallback(e){let t=getRegistry(),n=getSessionBindings(e.owner.sessionId);n===void 0&&(n=new Map,t.set(e.owner.sessionId,n),t.size>1024&&t.delete(t.keys().next().value)),n.set(callbackKey(e.owner,e.phase),e.callback)}function lookupDurableDynamicCallback(e,t){return getSessionBindings(e.sessionId)?.get(callbackKey(e,t))}function clearDurableDynamicCallbacks(e,t){if(t===void 0){getRegistry().delete(e);return}let n=getSessionBindings(e);if(n===void 0)return;let r=JSON.stringify([t.scope,t.resolverSlug]).slice(0,-1)+`,`;for(let e of n.keys())e.startsWith(r)&&n.delete(e)}function callDurableDynamicCallback(e,t,...n){return e(t,...n)}function hasUnregisteredDurableDynamicCallbacks(e,t){return e.some(e=>durableCallbackPhases(e.callbacks).some(n=>lookupDurableDynamicCallback({...e,...t},n)===void 0))}function durableCallbackPhases(e){return[[`execute`,e.execute],[`labelComplete`,e.label?.complete],[`labelDelta`,e.label?.delta],[`labelStart`,e.label?.start],[`approvalKey`,e.approvalKey],[`approvalRequest`,e.approvalRequest],[`approvalResponse`,e.approvalResponse],[`toModelOutput`,e.toModelOutput]].flatMap(([e,t])=>t===void 0?[]:[e])}function stampDurableDynamicCallback(e,t){return Object.defineProperty(e,STAMPED_CALLBACK,{configurable:!0,value:t}),e}function readDurableDynamicCallback(e){if(typeof e==`function`)return Reflect.get(e,STAMPED_CALLBACK)}function stampDurableDynamicToolCallbacks(e,t){Object.defineProperty(e,DURABLE_DYNAMIC_TOOL_CALLBACKS,{configurable:!0,value:t})}function collectDurableDynamicToolCallbacks(e){let t=readDurableDynamicCallback(e.label?.complete),n=readDurableDynamicCallback(e.label?.delta),r=readDurableDynamicCallback(e.label?.start),i=e.approval===void 0?void 0:readDurableDynamicCallback(resolveApprovalPolicy(e.approval)),a=e.approval===void 0||typeof e.approval==`function`?void 0:readDurableDynamicCallback(e.approval.response),o=readDurableDynamicCallback(e.approvalKey),s=readDurableDynamicCallback(e.execute),c=readDurableDynamicCallback(e.toModelOutput),l={};return s!==void 0&&(l.execute=s),(t!==void 0||n!==void 0||r!==void 0)&&(l.label={complete:t,delta:n,start:r}),o!==void 0&&(l.approvalKey=o),i!==void 0&&(l.approvalRequest=i),a!==void 0&&(l.approvalResponse=a),c!==void 0&&(l.toModelOutput=c),l}function readDurableDynamicToolCallbacks(e){return e[DURABLE_DYNAMIC_TOOL_CALLBACKS]}export{DURABLE_DYNAMIC_TOOL_CALLBACKS,callDurableDynamicCallback,clearDurableDynamicCallbacks,collectDurableDynamicToolCallbacks,hasUnregisteredDurableDynamicCallbacks,lookupDurableDynamicCallback,readDurableDynamicCallback,readDurableDynamicToolCallbacks,registerDurableDynamicCallback,stampDurableDynamicCallback,stampDurableDynamicToolCallbacks};