eve 0.24.4 → 0.24.6

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 (161) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/src/channel/cancel.d.ts +8 -0
  3. package/dist/src/channel/cancel.js +1 -0
  4. package/dist/src/channel/routes.d.ts +25 -4
  5. package/dist/src/channel/session.d.ts +10 -1
  6. package/dist/src/channel/session.js +1 -1
  7. package/dist/src/channel/types.d.ts +21 -0
  8. package/dist/src/chunks/{use-eve-agent-Dwa2j1wE.js → use-eve-agent-6BO9gFVq.js} +61 -6
  9. package/dist/src/chunks/{use-eve-agent-BP9FpQsJ.js → use-eve-agent-B1MJNRE-.js} +61 -6
  10. package/dist/src/cli/commands/build.d.ts +14 -0
  11. package/dist/src/cli/commands/build.js +1 -0
  12. package/dist/src/cli/commands/channels.js +1 -1
  13. package/dist/src/cli/commands/link.d.ts +6 -5
  14. package/dist/src/cli/commands/link.js +1 -1
  15. package/dist/src/cli/run.d.ts +3 -2
  16. package/dist/src/cli/run.js +1 -1
  17. package/dist/src/client/index.d.ts +1 -1
  18. package/dist/src/client/ndjson.js +1 -1
  19. package/dist/src/client/open-stream.d.ts +3 -2
  20. package/dist/src/client/open-stream.js +1 -1
  21. package/dist/src/client/session.d.ts +19 -3
  22. package/dist/src/client/session.js +1 -1
  23. package/dist/src/client/types.d.ts +8 -0
  24. package/dist/src/compiled/.vendor-stamp.json +5 -5
  25. package/dist/src/compiled/@workflow/core/index.js +2 -2
  26. package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +55 -0
  27. package/dist/src/compiled/@workflow/core/runtime/run-id-time.d.ts +9 -0
  28. package/dist/src/compiled/@workflow/core/runtime/step-executor.d.ts +2 -0
  29. package/dist/src/compiled/@workflow/core/runtime/step-latency.d.ts +70 -4
  30. package/dist/src/compiled/@workflow/core/runtime/suspension-handler.d.ts +10 -1
  31. package/dist/src/compiled/@workflow/core/runtime.js +3 -3
  32. package/dist/src/compiled/@workflow/core/step/context-storage.d.ts +6 -0
  33. package/dist/src/compiled/@workflow/core/telemetry/semantic-conventions.d.ts +25 -0
  34. package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
  35. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  36. package/dist/src/compiled/@workflow/errors/index.d.ts +16 -0
  37. package/dist/src/compiled/@workflow/errors/index.js +1 -1
  38. package/dist/src/compiled/@workflow/world/attributes.d.ts +7 -0
  39. package/dist/src/compiled/@workflow/world/events.d.ts +16 -0
  40. package/dist/src/compiled/@workflow/world/index.d.ts +1 -1
  41. package/dist/src/compiled/@workflow/world-local/index.js +3 -3
  42. package/dist/src/compiled/@workflow/world-vercel/index.js +16 -16
  43. package/dist/src/compiled/_chunks/workflow/attribute-changes-DXbmITuI.js +20 -0
  44. package/dist/src/compiled/_chunks/workflow/{dist-DpDDcpTl.js → dist-BYo8Gno2.js} +1 -1
  45. package/dist/src/compiled/_chunks/workflow/{dist-Blxnyb7-.js → dist-CSfKNxQW.js} +1 -1
  46. package/dist/src/compiled/_chunks/workflow/resume-hook-DvvgYsRt.js +1 -0
  47. package/dist/src/compiled/_chunks/workflow/run-BdvQmV5a.js +1 -0
  48. package/dist/src/compiled/_chunks/workflow/run-id-BdE0MZz9.js +1 -0
  49. package/dist/src/compiled/_chunks/workflow/sleep-DzxrwWTs.js +1 -0
  50. package/dist/src/evals/assertions/run.d.ts +3 -3
  51. package/dist/src/evals/context.js +1 -1
  52. package/dist/src/evals/index.d.ts +2 -1
  53. package/dist/src/evals/match.d.ts +4 -0
  54. package/dist/src/evals/match.js +1 -1
  55. package/dist/src/evals/runner/derive-run-facts.js +1 -1
  56. package/dist/src/evals/session.d.ts +10 -2
  57. package/dist/src/evals/session.js +1 -1
  58. package/dist/src/evals/target.js +1 -1
  59. package/dist/src/evals/types.d.ts +52 -2
  60. package/dist/src/execution/cancel-descendant-turns-step.d.ts +6 -0
  61. package/dist/src/execution/cancel-descendant-turns-step.js +1 -0
  62. package/dist/src/execution/create-session-step.js +1 -1
  63. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  64. package/dist/src/execution/dispatch-workflow-runtime-actions-step.js +1 -1
  65. package/dist/src/execution/node-step.js +1 -1
  66. package/dist/src/execution/remote-agent-dispatch.d.ts +6 -0
  67. package/dist/src/execution/remote-agent-dispatch.js +1 -1
  68. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  69. package/dist/src/execution/subagent-event-proxy-step.js +1 -1
  70. package/dist/src/execution/turn-cancellation-control.d.ts +0 -13
  71. package/dist/src/execution/turn-cancellation-control.js +1 -1
  72. package/dist/src/execution/turn-cancellation-token.d.ts +9 -0
  73. package/dist/src/execution/turn-cancellation-token.js +1 -0
  74. package/dist/src/execution/turn-workflow.js +1 -1
  75. package/dist/src/execution/workflow-runtime.d.ts +3 -1
  76. package/dist/src/execution/workflow-runtime.js +1 -1
  77. package/dist/src/execution/workflow-steps.js +1 -1
  78. package/dist/src/harness/advertised-tools.js +1 -1
  79. package/dist/src/harness/execute-tool.d.ts +0 -1
  80. package/dist/src/harness/runtime-actions.d.ts +16 -12
  81. package/dist/src/harness/runtime-actions.js +1 -1
  82. package/dist/src/internal/application/build-profile.d.ts +64 -0
  83. package/dist/src/internal/application/build-profile.js +1 -0
  84. package/dist/src/internal/application/package.js +1 -1
  85. package/dist/src/internal/authored-module-loader.d.ts +10 -0
  86. package/dist/src/internal/authored-module-loader.js +2 -2
  87. package/dist/src/internal/authored-module-map-loader.js +1 -1
  88. package/dist/src/internal/materialized-authored-modules.d.ts +2 -4
  89. package/dist/src/internal/materialized-authored-modules.js +1 -1
  90. package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
  91. package/dist/src/internal/nitro/host/build-application.js +1 -1
  92. package/dist/src/internal/nitro/host/types.d.ts +2 -0
  93. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.js +1 -1
  94. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.d.ts +7 -1
  95. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
  96. package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
  97. package/dist/src/internal/nitro/routes/channel-route-context.d.ts +3 -0
  98. package/dist/src/internal/nitro/routes/channel-route-context.js +1 -1
  99. package/dist/src/internal/nitro/routes/runtime-stack.js +1 -1
  100. package/dist/src/internal/nitro/routes/schedule-task.js +1 -1
  101. package/dist/src/protocol/cancel-turn.d.ts +11 -0
  102. package/dist/src/protocol/cancel-turn.js +1 -0
  103. package/dist/src/protocol/routes.d.ts +10 -0
  104. package/dist/src/protocol/routes.js +1 -1
  105. package/dist/src/public/channels/eve.d.ts +2 -1
  106. package/dist/src/public/channels/eve.js +1 -1
  107. package/dist/src/public/channels/index.d.ts +1 -1
  108. package/dist/src/public/channels/linear/api.d.ts +0 -1
  109. package/dist/src/public/channels/linear/api.js +17 -22
  110. package/dist/src/public/channels/linear/linearChannel.js +1 -1
  111. package/dist/src/public/definitions/channel.d.ts +21 -11
  112. package/dist/src/public/next/index.js +1 -1
  113. package/dist/src/public/next/resolve-eve-binary.d.ts +12 -0
  114. package/dist/src/public/next/resolve-eve-binary.js +1 -0
  115. package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
  116. package/dist/src/runtime/framework-tools/agent.d.ts +13 -0
  117. package/dist/src/runtime/framework-tools/agent.js +1 -0
  118. package/dist/src/runtime/framework-tools/index.d.ts +7 -2
  119. package/dist/src/runtime/framework-tools/index.js +1 -1
  120. package/dist/src/runtime/resolve-agent-graph.js +1 -1
  121. package/dist/src/runtime/types.d.ts +2 -1
  122. package/dist/src/setup/boxes/reconcile-host-framework-preset.d.ts +26 -0
  123. package/dist/src/setup/boxes/reconcile-host-framework-preset.js +1 -0
  124. package/dist/src/setup/boxes/resolve-provisioning.js +1 -1
  125. package/dist/src/setup/index.js +1 -1
  126. package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
  127. package/dist/src/setup/scaffold/create/project.js +2 -2
  128. package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
  129. package/dist/src/setup/scaffold/create/web-template.js +1 -0
  130. package/dist/src/setup/scaffold/index.d.ts +1 -1
  131. package/dist/src/setup/scaffold/index.js +1 -1
  132. package/dist/src/setup/scaffold/update/channels.d.ts +7 -1
  133. package/dist/src/setup/scaffold/update/channels.js +2 -2
  134. package/dist/src/setup/scaffold/update/connections.js +3 -3
  135. package/dist/src/setup/vercel-project-framework.d.ts +12 -0
  136. package/dist/src/setup/vercel-project-framework.js +1 -1
  137. package/dist/src/svelte/index.js +1 -1
  138. package/dist/src/svelte/use-eve-agent.js +1 -1
  139. package/dist/src/vue/index.js +1 -1
  140. package/dist/src/vue/use-eve-agent.js +1 -1
  141. package/docs/channels/custom.mdx +32 -2
  142. package/docs/channels/eve.mdx +11 -1
  143. package/docs/concepts/default-harness.md +2 -0
  144. package/docs/concepts/sessions-runs-and-streaming.md +13 -0
  145. package/docs/evals/assertions.mdx +2 -2
  146. package/docs/evals/cases.mdx +31 -0
  147. package/docs/evals/overview.mdx +1 -1
  148. package/docs/evals/targets.mdx +2 -1
  149. package/docs/guides/client/continuations.mdx +2 -0
  150. package/docs/guides/client/streaming.mdx +17 -1
  151. package/docs/guides/frontend/overview.mdx +4 -2
  152. package/docs/guides/frontend/use-eve-agent-svelte.mdx +2 -2
  153. package/docs/guides/frontend/use-eve-agent-vue.mdx +2 -2
  154. package/docs/guides/remote-agents.md +2 -0
  155. package/docs/reference/cli.md +15 -2
  156. package/docs/subagents.mdx +10 -0
  157. package/package.json +7 -7
  158. package/dist/src/compiled/_chunks/workflow/attribute-changes-MGTOG_uX.js +0 -20
  159. package/dist/src/compiled/_chunks/workflow/resume-hook-DHP5ql3-.js +0 -1
  160. package/dist/src/compiled/_chunks/workflow/run-D8hv1ptT.js +0 -1
  161. package/dist/src/compiled/_chunks/workflow/sleep-uA9pS-PT.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # eve
2
2
 
3
+ ## 0.24.6
4
+
5
+ ### Patch Changes
6
+
7
+ - 3029647: Update the generated Web Chat template for Next.js 16.3 preview type declarations.
8
+ - b97f1d1: Custom channel routes can now cancel a session's in-flight turn: route handlers receive a `cancel({ continuationToken, turnId? })` helper addressed by the channel-local continuation token, and `Session` handles returned by `send()` and `getSession()` expose `cancel({ turnId? })` for session-id-addressed cancellation. `ClientSession.cancel()` accepts the same optional `turnId` stale-request guard.
9
+
10
+ ## 0.24.5
11
+
12
+ ### Patch Changes
13
+
14
+ - bfbbe92: Add `eve build --profile <path>` for a machine-readable build-timing and final-output-size report. Profile collection is best-effort, so reporting failures do not fail an otherwise successful build.
15
+ - dab9889: Allow agents to remove the root-only built-in `agent` delegation tool with `disableTool()` from `agent/tools/agent.ts`.
16
+ - e1cb505: Retry transient network failures while reopening client session streams so active turns remain attached.
17
+ - 2568387: Cancel active local, nested, and remote subagent turns when their parent turn is cancelled. Client and eval sessions can now cancel active turns directly, and eval live-turn handles can wait for typed mid-turn events before cancellation or settlement.
18
+ - 20cd9a1: Added `POST /eve/v1/session/:sessionId/cancel` to the eve HTTP channel for requesting cancellation of an in-flight turn. The optional `{ turnId }` body limits the request to the turn the caller observed; the response reports `"accepted"` when a cancellation hook accepts it or the benign `"no_active_turn"` when no resumable target exists.
19
+ - 02698fd: Fix Vercel deploys for the Next.js web channel. `eve` no longer scaffolds a
20
+ `vercel.json` `experimentalServices` block, which the Vercel platform now
21
+ rejects (it requires the `services` key and a stricter schema). For Next.js the
22
+ block was also redundant — `withEve()` generates the eve service and
23
+ `/eve/v1/*` routes into the Build Output at build time — so the scaffold now
24
+ writes a minimal `vercel.json`.
25
+ - e45a066: `eve link` now lets you create a Vercel project or link an existing one, matching the project setup available through `/model` usage.
26
+ - 5f8818b: `eve channels add web` now updates the Vercel Framework Preset when adding a
27
+ Next.js web channel to an already-linked eve project to prevent deployment
28
+ failures.
29
+ - 887908c: Bundle authored modules in each development generation as one shared graph, avoiding repeated parsing and emission of dependencies for every tool.
30
+ - 376a82f: Report the root-only `agent` action alongside other framework tools in agent info, including whether it is active, disabled, or replaced.
31
+ - 4f2863d: Update the bundled Workflow runtime dependencies to their latest 5.0 beta releases.
32
+ - d9d3226: Fix `withEve` producing a broken Vercel build command in npm workspaces, where the `eve` module is located in the workspace root.
33
+
3
34
  ## 0.24.4
4
35
 
5
36
  ### Patch Changes
@@ -0,0 +1,8 @@
1
+ import type { CancelFn } from "#channel/routes.js";
2
+ import type { Runtime } from "#channel/types.js";
3
+ /**
4
+ * Builds the route-handler `cancel` helper for one channel. Resolves the
5
+ * channel-local continuation token to its owning session without delivering
6
+ * input, then delegates to the runtime's session-id-addressed cancellation.
7
+ */
8
+ export declare function createCancelFn(runtime: Runtime, channelName: string): CancelFn;
@@ -0,0 +1 @@
1
+ function createCancelFn(e,t){return async n=>{let r=`${t}:${n.continuationToken}`,i=await e.resolveSession(r);return i===void 0?{status:`no_active_turn`}:await e.cancelTurn({sessionId:i.sessionId,turnId:n.turnId})}}export{createCancelFn};
@@ -1,6 +1,6 @@
1
1
  import type { UserContent } from "ai";
2
2
  import type { CrossChannelReceiveFn } from "#channel/cross-channel-receive.js";
3
- import type { SessionAuthContext, SessionCallback } from "#channel/types.js";
3
+ import type { CancelTurnResult, SessionAuthContext, SessionCallback } from "#channel/types.js";
4
4
  import type { InputResponse } from "#runtime/input/types.js";
5
5
  import type { Session } from "#channel/session.js";
6
6
  import type { RunMode } from "#shared/run-mode.js";
@@ -9,13 +9,15 @@ import type { ChannelMethod } from "#public/definitions/channel.js";
9
9
  type WebSocketHeaders = Headers | readonly (readonly [string, string])[] | Record<string, string>;
10
10
  /**
11
11
  * Second argument passed to every route handler. `send` starts or continues a
12
- * session on this channel; `getSession` looks one up by id; `receive` hands
13
- * inbound work to a different channel; `params` contains the matched path
14
- * parameters; `waitUntil` keeps background work alive past the response;
12
+ * session on this channel; `cancel` stops the active turn on a session
13
+ * addressed by continuation token; `getSession` looks one up by id; `receive`
14
+ * hands inbound work to a different channel; `params` contains the matched
15
+ * path parameters; `waitUntil` keeps background work alive past the response;
15
16
  * `requestIp` is the client IP, or `null` when the host cannot provide it.
16
17
  */
17
18
  export interface RouteHandlerArgs<TState = undefined> {
18
19
  send: SendFn<TState>;
20
+ cancel: CancelFn;
19
21
  getSession: GetSessionFn;
20
22
  /**
21
23
  * Starts a session on a different channel to hand off inbound work (e.g. an
@@ -78,6 +80,25 @@ export type SendOptions<TState = undefined> = [TState] extends [undefined] ? Bas
78
80
  * stream from within a route handler.
79
81
  */
80
82
  export type GetSessionFn = (sessionId: string) => Session;
83
+ /**
84
+ * Options for {@link CancelFn}. `continuationToken` is the channel-local raw
85
+ * token, exactly as passed to {@link SendFn}. `turnId` limits the request to
86
+ * the turn the caller observed; a stale guard is consumed as a benign no-op.
87
+ */
88
+ export interface CancelOptions {
89
+ readonly continuationToken: string;
90
+ readonly turnId?: string;
91
+ }
92
+ /**
93
+ * Requests cancellation of the active turn on the session that owns the
94
+ * continuation token. Never starts a session, sends input, or clears history.
95
+ *
96
+ * Both statuses are successful: `"accepted"` means the request was consumed,
97
+ * and `"no_active_turn"` covers an unknown token and a session with nothing
98
+ * to cancel. Confirmation is `turn.cancelled` followed by `session.waiting`
99
+ * on the event stream.
100
+ */
101
+ export type CancelFn = (options: CancelOptions) => Promise<CancelTurnResult>;
81
102
  export type RouteHandler<TState = undefined> = (req: Request, args: RouteHandlerArgs<TState>) => Promise<Response>;
82
103
  /**
83
104
  * A connected WebSocket peer passed to every {@link WebSocketRouteHooks}
@@ -1,6 +1,6 @@
1
1
  import type { ContextAccessor } from "#context/key.js";
2
2
  import type { HandleMessageStreamEvent } from "#protocol/message.js";
3
- import type { Runtime } from "#channel/types.js";
3
+ import type { CancelTurnResult, Runtime } from "#channel/types.js";
4
4
  import type { SessionAuth } from "#context/keys.js";
5
5
  /**
6
6
  * Result of starting or delivering to a session. Exposes the session
@@ -14,6 +14,15 @@ import type { SessionAuth } from "#context/keys.js";
14
14
  export interface Session {
15
15
  readonly id: string;
16
16
  readonly continuationToken: string;
17
+ /**
18
+ * Requests cancellation of this session's in-flight turn. `turnId` limits
19
+ * the request to the turn the caller observed. Both statuses are
20
+ * successful; confirmation is `turn.cancelled` followed by
21
+ * `session.waiting` on the event stream.
22
+ */
23
+ cancel(options?: {
24
+ turnId?: string;
25
+ }): Promise<CancelTurnResult>;
17
26
  /**
18
27
  * Opens the durable event stream. Negative start indexes read relative to
19
28
  * the current tail (`-1` starts at the latest event).
@@ -1 +1 @@
1
- import{AuthKey,ContinuationTokenKey,InitiatorAuthKey,SessionIdKey}from"#context/keys.js";function createSession(e,t,n){return{id:e,continuationToken:t,async getEventStream(t){return n.getEventStream(e,t)}}}function createGetSessionFn(e){return t=>createSession(t,``,e)}function buildSessionHandle(i){return{get id(){return i.get(SessionIdKey)??``},get continuationToken(){return i.get(ContinuationTokenKey)??``},get auth(){return{current:i.get(AuthKey)??null,initiator:i.get(InitiatorAuthKey)??null}},setContinuationToken(e){let n=i.get(ContinuationTokenKey)??``,r=namespaceContinuationToken(n,e);n!==r&&i.set(ContinuationTokenKey,r)}}}function namespaceContinuationToken(e,t){let n=e.indexOf(`:`);if(n<=0)throw Error(`Cannot set session continuation token without an existing namespaced continuation token. Start the session with a placeholder continuationToken.`);return`${e.slice(0,n+1)}${t}`}export{buildSessionHandle,createGetSessionFn,createSession};
1
+ import{AuthKey,ContinuationTokenKey,InitiatorAuthKey,SessionIdKey}from"#context/keys.js";function createSession(e,t,n){return{id:e,continuationToken:t,async cancel(t){return n.cancelTurn({sessionId:e,turnId:t?.turnId})},async getEventStream(t){return n.getEventStream(e,t)}}}function createGetSessionFn(e){return t=>createSession(t,``,e)}function buildSessionHandle(i){return{get id(){return i.get(SessionIdKey)??``},get continuationToken(){return i.get(ContinuationTokenKey)??``},get auth(){return{current:i.get(AuthKey)??null,initiator:i.get(InitiatorAuthKey)??null}},setContinuationToken(e){let n=i.get(ContinuationTokenKey)??``,r=namespaceContinuationToken(n,e);n!==r&&i.set(ContinuationTokenKey,r)}}}function namespaceContinuationToken(e,t){let n=e.indexOf(`:`);if(n<=0)throw Error(`Cannot set session continuation token without an existing namespaced continuation token. Start the session with a placeholder continuationToken.`);return`${e.slice(0,n+1)}${t}`}export{buildSessionHandle,createGetSessionFn,createSession};
@@ -1,5 +1,6 @@
1
1
  import type { UserContent } from "ai";
2
2
  import type { HandleMessageStreamEvent } from "#protocol/message.js";
3
+ import type { CancelTurnStatus } from "#protocol/cancel-turn.js";
3
4
  import type { RunMode } from "#shared/run-mode.js";
4
5
  import type { RuntimeActionResult } from "#runtime/actions/types.js";
5
6
  import type { InputRequest, InputResponse } from "#runtime/input/types.js";
@@ -10,6 +11,16 @@ export type { ContextAccessor } from "#context/key.js";
10
11
  export type { ChannelInstrumentationProjection } from "#channel/instrumentation.js";
11
12
  import type { ChannelInstrumentationProjection } from "#channel/instrumentation.js";
12
13
  export type RunSessionLimits = Pick<AgentLimitsDefinition, "maxInputTokensPerSession" | "maxOutputTokensPerSession">;
14
+ /** Identifies the session turn to cancel. */
15
+ export interface CancelTurnInput {
16
+ readonly sessionId: string;
17
+ /** Limits the request to the turn the caller observed. */
18
+ readonly turnId?: string;
19
+ }
20
+ /** Result of requesting turn cancellation. Both statuses are successful. */
21
+ export interface CancelTurnResult {
22
+ readonly status: CancelTurnStatus;
23
+ }
13
24
  /**
14
25
  * Identifies one turn within a session.
15
26
  *
@@ -314,12 +325,22 @@ export interface Runtime {
314
325
  * completion.
315
326
  */
316
327
  run(input: RunInput): Promise<RunHandle>;
328
+ /** Requests cancellation of a session's in-flight turn. */
329
+ cancelTurn(input: CancelTurnInput): Promise<CancelTurnResult>;
317
330
  /**
318
331
  * Delivers a follow-up message to a parked session.
319
332
  */
320
333
  deliver(input: DeliverInput): Promise<{
321
334
  sessionId: string;
322
335
  }>;
336
+ /**
337
+ * Resolves the session that currently owns a continuation token without
338
+ * delivering input or starting a run. Returns `undefined` when no session
339
+ * owns the token.
340
+ */
341
+ resolveSession(continuationToken: string): Promise<{
342
+ sessionId: string;
343
+ } | undefined>;
323
344
  /**
324
345
  * Returns a readable stream of lifecycle events for an existing session.
325
346
  *
@@ -8,6 +8,7 @@ const EVE_INFO_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/info`;
8
8
  const EVE_CREATE_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session`;
9
9
  const EVE_CONTINUE_SESSION_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId`;
10
10
  const EVE_MESSAGE_STREAM_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId/stream`;
11
+ const EVE_CANCEL_TURN_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId/cancel`;
11
12
  const EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/dev/schedules/:scheduleId`;
12
13
  const EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/dev/runtime-artifacts`;
13
14
  const EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH = `${EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}/rebuild`;
@@ -19,6 +20,9 @@ function createEveMessageStreamRoutePath(sessionId) {
19
20
  function createEveContinueSessionRoutePath(sessionId) {
20
21
  return `${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(sessionId)}`;
21
22
  }
23
+ function createEveCancelTurnRoutePath(sessionId) {
24
+ return `${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(sessionId)}/cancel`;
25
+ }
22
26
 
23
27
  //#endregion
24
28
  //#region src/client/agent-info-error.ts
@@ -290,6 +294,14 @@ function isCurrentTurnBoundaryEvent(event) {
290
294
  return event.type === "session.completed" || event.type === "session.failed" || event.type === "session.waiting";
291
295
  }
292
296
 
297
+ //#endregion
298
+ //#region src/protocol/cancel-turn.ts
299
+ const CancelTurnResponseSchema = z.object({
300
+ ok: z.literal(true),
301
+ sessionId: z.string().min(1),
302
+ status: z.enum(["accepted", "no_active_turn"])
303
+ });
304
+
293
305
  //#endregion
294
306
  //#region src/shared/json.ts
295
307
  const INVALID_JSON_VALUE_CANDIDATE = Symbol("invalid-json-value-candidate");
@@ -442,7 +454,7 @@ function isStreamDisconnectError(error) {
442
454
  if (error instanceof DOMException) return error.name === "AbortError";
443
455
  if (!(error instanceof Error)) return false;
444
456
  const errorCode = "code" in error && typeof error.code === "string" ? error.code : void 0;
445
- return error.name === "AbortError" || error.message === "terminated" || errorCode === "UND_ERR_SOCKET" || /abort|cancel|disconnect|premature close|socket|terminated/i.test(error.message);
457
+ return error.name === "AbortError" || error.message === "terminated" || errorCode === "UND_ERR_SOCKET" || error instanceof TypeError && /^(?:failed to fetch|fetch failed)$/i.test(error.message) || /abort|cancel|disconnect|premature close|socket|terminated/i.test(error.message);
446
458
  }
447
459
  async function* readNdjsonStream(body) {
448
460
  const reader = body.getReader();
@@ -548,11 +560,18 @@ async function openStreamBody(input) {
548
560
  for (let attempt = 0; attempt < STREAM_OPEN_RETRY_ATTEMPTS; attempt += 1) {
549
561
  const url = createClientUrl(input.host, createEveMessageStreamRoutePath(input.sessionId), input.startIndex !== 0 ? { startIndex: String(input.startIndex) } : void 0);
550
562
  const headers = await input.resolveHeaders();
551
- const response = await fetch(url, {
552
- headers,
553
- redirect: input.redirect,
554
- signal: input.signal ?? null
555
- });
563
+ let response;
564
+ try {
565
+ response = await fetch(url, {
566
+ headers,
567
+ redirect: input.redirect,
568
+ signal: input.signal ?? null
569
+ });
570
+ } catch (error) {
571
+ if (input.signal?.aborted || !isStreamDisconnectError(error) || attempt === STREAM_OPEN_RETRY_ATTEMPTS - 1) throw error;
572
+ await sleep$1(STREAM_OPEN_RETRY_DELAY_MS);
573
+ continue;
574
+ }
556
575
  if (response.ok) {
557
576
  if (!response.body) throw new ClientError(response.status, "Response body is null.", response.headers);
558
577
  return response.body;
@@ -587,12 +606,42 @@ var ClientSession = class {
587
606
  const payload = normalizeSendTurnInput(input);
588
607
  const state = this.#state;
589
608
  const { continuationToken, sessionId } = await this.#postTurn(payload, state);
609
+ if (this.#state === state) this.#state = {
610
+ ...state,
611
+ sessionId
612
+ };
590
613
  return new MessageResponse({
591
614
  continuationToken,
592
615
  createStream: () => this.#createEventStream(sessionId, continuationToken, state, payload),
593
616
  sessionId
594
617
  });
595
618
  }
619
+ async cancel(options) {
620
+ const sessionId = this.#state.sessionId;
621
+ if (!sessionId) throw new Error("Session has no session ID. Send a message first.");
622
+ const url = createClientUrl(this.#context.host, createEveCancelTurnRoutePath(sessionId));
623
+ const headers = await this.#context.resolveHeaders();
624
+ headers.set("content-type", "application/json");
625
+ const response = await fetch(url, withRedirectPolicy$1({
626
+ headers,
627
+ method: "POST",
628
+ body: options ? JSON.stringify(options) : void 0
629
+ }, this.#context.redirect));
630
+ const body = await response.text();
631
+ if (!response.ok) throw new ClientError(response.status, body, response.headers);
632
+ let payload;
633
+ try {
634
+ payload = JSON.parse(body);
635
+ } catch {
636
+ throw new Error(`Cancel route returned invalid JSON (${response.status}).`);
637
+ }
638
+ const result = CancelTurnResponseSchema.safeParse(payload);
639
+ if (!result.success || result.data.sessionId !== sessionId) throw new Error(`Cancel route returned an invalid response (${response.status}).`);
640
+ return {
641
+ sessionId: result.data.sessionId,
642
+ status: result.data.status
643
+ };
644
+ }
596
645
  stream(options) {
597
646
  const sessionId = this.#state.sessionId;
598
647
  if (!sessionId) throw new Error("Session has no session ID. Send a message first.");
@@ -746,6 +795,12 @@ function createHandleMessageBody(input) {
746
795
  if (input.session.continuationToken !== void 0 && body.message === void 0 && body.inputResponses === void 0) return null;
747
796
  return body;
748
797
  }
798
+ function withRedirectPolicy$1(init, redirect) {
799
+ return redirect === void 0 ? init : {
800
+ ...init,
801
+ redirect
802
+ };
803
+ }
749
804
 
750
805
  //#endregion
751
806
  //#region src/client/types.ts
@@ -8,6 +8,7 @@ const EVE_INFO_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/info`;
8
8
  const EVE_CREATE_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session`;
9
9
  const EVE_CONTINUE_SESSION_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId`;
10
10
  const EVE_MESSAGE_STREAM_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId/stream`;
11
+ const EVE_CANCEL_TURN_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId/cancel`;
11
12
  const EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/dev/schedules/:scheduleId`;
12
13
  const EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/dev/runtime-artifacts`;
13
14
  const EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH = `${EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}/rebuild`;
@@ -19,6 +20,9 @@ function createEveMessageStreamRoutePath(sessionId) {
19
20
  function createEveContinueSessionRoutePath(sessionId) {
20
21
  return `${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(sessionId)}`;
21
22
  }
23
+ function createEveCancelTurnRoutePath(sessionId) {
24
+ return `${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(sessionId)}/cancel`;
25
+ }
22
26
 
23
27
  //#endregion
24
28
  //#region src/client/agent-info-error.ts
@@ -290,6 +294,14 @@ function isCurrentTurnBoundaryEvent(event) {
290
294
  return event.type === "session.completed" || event.type === "session.failed" || event.type === "session.waiting";
291
295
  }
292
296
 
297
+ //#endregion
298
+ //#region src/protocol/cancel-turn.ts
299
+ const CancelTurnResponseSchema = z.object({
300
+ ok: z.literal(true),
301
+ sessionId: z.string().min(1),
302
+ status: z.enum(["accepted", "no_active_turn"])
303
+ });
304
+
293
305
  //#endregion
294
306
  //#region src/shared/json.ts
295
307
  const INVALID_JSON_VALUE_CANDIDATE = Symbol("invalid-json-value-candidate");
@@ -442,7 +454,7 @@ function isStreamDisconnectError(error) {
442
454
  if (error instanceof DOMException) return error.name === "AbortError";
443
455
  if (!(error instanceof Error)) return false;
444
456
  const errorCode = "code" in error && typeof error.code === "string" ? error.code : void 0;
445
- return error.name === "AbortError" || error.message === "terminated" || errorCode === "UND_ERR_SOCKET" || /abort|cancel|disconnect|premature close|socket|terminated/i.test(error.message);
457
+ return error.name === "AbortError" || error.message === "terminated" || errorCode === "UND_ERR_SOCKET" || error instanceof TypeError && /^(?:failed to fetch|fetch failed)$/i.test(error.message) || /abort|cancel|disconnect|premature close|socket|terminated/i.test(error.message);
446
458
  }
447
459
  async function* readNdjsonStream(body) {
448
460
  const reader = body.getReader();
@@ -548,11 +560,18 @@ async function openStreamBody(input) {
548
560
  for (let attempt = 0; attempt < STREAM_OPEN_RETRY_ATTEMPTS; attempt += 1) {
549
561
  const url = createClientUrl(input.host, createEveMessageStreamRoutePath(input.sessionId), input.startIndex !== 0 ? { startIndex: String(input.startIndex) } : void 0);
550
562
  const headers = await input.resolveHeaders();
551
- const response = await fetch(url, {
552
- headers,
553
- redirect: input.redirect,
554
- signal: input.signal ?? null
555
- });
563
+ let response;
564
+ try {
565
+ response = await fetch(url, {
566
+ headers,
567
+ redirect: input.redirect,
568
+ signal: input.signal ?? null
569
+ });
570
+ } catch (error) {
571
+ if (input.signal?.aborted || !isStreamDisconnectError(error) || attempt === STREAM_OPEN_RETRY_ATTEMPTS - 1) throw error;
572
+ await sleep$1(STREAM_OPEN_RETRY_DELAY_MS);
573
+ continue;
574
+ }
556
575
  if (response.ok) {
557
576
  if (!response.body) throw new ClientError(response.status, "Response body is null.", response.headers);
558
577
  return response.body;
@@ -587,12 +606,42 @@ var ClientSession = class {
587
606
  const payload = normalizeSendTurnInput(input);
588
607
  const state = this.#state;
589
608
  const { continuationToken, sessionId } = await this.#postTurn(payload, state);
609
+ if (this.#state === state) this.#state = {
610
+ ...state,
611
+ sessionId
612
+ };
590
613
  return new MessageResponse({
591
614
  continuationToken,
592
615
  createStream: () => this.#createEventStream(sessionId, continuationToken, state, payload),
593
616
  sessionId
594
617
  });
595
618
  }
619
+ async cancel(options) {
620
+ const sessionId = this.#state.sessionId;
621
+ if (!sessionId) throw new Error("Session has no session ID. Send a message first.");
622
+ const url = createClientUrl(this.#context.host, createEveCancelTurnRoutePath(sessionId));
623
+ const headers = await this.#context.resolveHeaders();
624
+ headers.set("content-type", "application/json");
625
+ const response = await fetch(url, withRedirectPolicy$1({
626
+ headers,
627
+ method: "POST",
628
+ body: options ? JSON.stringify(options) : void 0
629
+ }, this.#context.redirect));
630
+ const body = await response.text();
631
+ if (!response.ok) throw new ClientError(response.status, body, response.headers);
632
+ let payload;
633
+ try {
634
+ payload = JSON.parse(body);
635
+ } catch {
636
+ throw new Error(`Cancel route returned invalid JSON (${response.status}).`);
637
+ }
638
+ const result = CancelTurnResponseSchema.safeParse(payload);
639
+ if (!result.success || result.data.sessionId !== sessionId) throw new Error(`Cancel route returned an invalid response (${response.status}).`);
640
+ return {
641
+ sessionId: result.data.sessionId,
642
+ status: result.data.status
643
+ };
644
+ }
596
645
  stream(options) {
597
646
  const sessionId = this.#state.sessionId;
598
647
  if (!sessionId) throw new Error("Session has no session ID. Send a message first.");
@@ -746,6 +795,12 @@ function createHandleMessageBody(input) {
746
795
  if (input.session.continuationToken !== void 0 && body.message === void 0 && body.inputResponses === void 0) return null;
747
796
  return body;
748
797
  }
798
+ function withRedirectPolicy$1(init, redirect) {
799
+ return redirect === void 0 ? init : {
800
+ ...init,
801
+ redirect
802
+ };
803
+ }
749
804
 
750
805
  //#endregion
751
806
  //#region src/client/types.ts
@@ -0,0 +1,14 @@
1
+ import type { Command } from "#compiled/commander/index.js";
2
+ import type { ApplicationBuildOptions } from "#internal/nitro/host/types.js";
3
+ export type BuildHost = (appRoot: string, options: ApplicationBuildOptions) => Promise<string>;
4
+ interface BuildCommandLogger {
5
+ log(message: string): void;
6
+ }
7
+ /** Registers the production application build command. */
8
+ export declare function registerBuildCommand(input: {
9
+ readonly appRoot: string;
10
+ readonly buildHost?: BuildHost;
11
+ readonly logger: BuildCommandLogger;
12
+ readonly program: Command;
13
+ }): void;
14
+ export {};
@@ -0,0 +1 @@
1
+ import{resolve}from"node:path";import{resolveInternalVercelServiceOutput}from"#cli/vercel-service-output.js";import{createCliTheme,renderCliTaggedLine}from"#cli/ui/output.js";function registerBuildCommand(t){let n=createCliTheme();t.program.command(`build`).description(`Build the current eve application.`).option(`--profile <path>`,`Write best-effort timing and output-size profile JSON to a file`).option(`--skip-sandbox-prewarm`,`Skip sandbox template prewarm for a Vercel build; output may not be deployable`).action(async e=>{let{loadDevelopmentEnvironmentFiles:r}=await import(`#cli/dev/environment.js`);r(t.appRoot);let i=t.buildHost??(await import(`#internal/nitro/host.js`)).buildApplication,a=e.profile===void 0?void 0:resolve(t.appRoot,e.profile),o={skipVercelSandboxPrewarm:e.skipSandboxPrewarm===!0,vercelServiceOutput:resolveInternalVercelServiceOutput(t.appRoot)};a!==void 0&&(o.profileOutputPath=a);let s=await i(t.appRoot,o);t.logger.log(renderCliTaggedLine(n,{message:`built output at ${s}`,tag:`build`,tone:`success`}))})}export{registerBuildCommand};
@@ -1 +1 @@
1
- import{assertCanAddSelectedChannels,inspectExistingChannelRegistrations}from"./channel-add-conflicts.js";import{NOT_AN_AGENT_MESSAGE}from"./preconditions.js";import{isEveProject,listAuthoredChannels}from"#setup/scaffold/index.js";import{interactiveAsker}from"#setup/ask.js";import{addChannels}from"#setup/boxes/add-channels.js";import{deployProject}from"#setup/boxes/deploy-project.js";import{selectChannels}from"#setup/boxes/select-channels.js";import{detectDeployment,projectResolutionFromDeployment}from"#setup/project-resolution.js";import{createPrompter}from"#setup/prompter.js";import{runInteractive}from"#setup/runner.js";import{createDefaultSetupState,snapshotSetupState}from"#setup/state.js";const KNOWN_CHANNEL_KINDS=[`slack`,`web`];function isChannelKind(e){return KNOWN_CHANNEL_KINDS.includes(e)}function parseChannelKind(e){if(!isChannelKind(e))throw Error(`Unknown channel kind "${e}". Known: ${KNOWN_CHANNEL_KINDS.join(`, `)}.`);return e}const defaultChannelsAddDependencies={detectDeployment};async function runAddChannelsFlow(n,r,i,s){if(r===void 0&&(i.yes||!process.stdin.isTTY||!process.stdout.isTTY))throw Error(`Pass a channel kind: \`eve channels add <${KNOWN_CHANNEL_KINDS.join(`|`)}>\`.`);let c=s.createPrompter?.()??createPrompter();c.intro(`Add channels to your eve agent`),c.log.message(`Checking the current Vercel project...`);let l={...createDefaultSetupState(),project:projectResolutionFromDeployment(await s.detectDeployment(n)),projectPath:{kind:`resolved`,inPlace:!0,path:n}},u;function inspectRegistrations(){return u===void 0&&(c.log.message(`Inspecting existing channel registrations...`),u=inspectExistingChannelRegistrations(n)),u}let d=r===void 0?(await inspectRegistrations()).disabledChannelReasons:void 0,f=await runInteractive([selectChannels({asker:interactiveAsker(c),variant:`channels-add`,presetChannels:r===void 0?void 0:[r],disabledChannelReasons:d,validateSelection:async t=>{!t.includes(`web`)&&!t.includes(`slack`)||assertCanAddSelectedChannels(t,await inspectRegistrations())}}),addChannels({asker:interactiveAsker(c),prompter:c,presetCreateSlackbot:i.yes?!0:void 0,force:i.force,configureVercelServices:!0,ensureLinkedProject:`interactive-vercel-link`,deps:s.addChannelsDeps}),deployProject({prompter:c,ensureLinkedProject:`interactive-vercel-link`,deps:s.deployProjectDeps})],l,{write:e=>c.log.message(e)},{snapshot:snapshotSetupState});f.kind!==`cancelled`&&c.outro(f.state.channels.length===0?`No channels added.`:`Channels added.`)}async function runChannelsAddCommand(e,t,i,a=defaultChannelsAddDependencies){if(!await isEveProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}try{await runAddChannelsFlow(t,i.kind===void 0?void 0:parseChannelKind(i.kind),i.options,a)}catch(t){e.error(t instanceof Error?t.message:String(t)),process.exitCode=1}}async function runChannelsListCommand(e,t,a){if(!await isEveProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}let o=await listAuthoredChannels(t);if(a.json){e.log(JSON.stringify({channels:o},null,2));return}if(o.length===0){e.log("No channels defined. Run `eve channels add` to add one.");return}for(let t of o)e.log(t)}export{runChannelsAddCommand,runChannelsListCommand};
1
+ import{assertCanAddSelectedChannels,inspectExistingChannelRegistrations}from"./channel-add-conflicts.js";import{NOT_AN_AGENT_MESSAGE}from"./preconditions.js";import{isEveProject,listAuthoredChannels}from"#setup/scaffold/index.js";import{interactiveAsker}from"#setup/ask.js";import{addChannels}from"#setup/boxes/add-channels.js";import{deployProject}from"#setup/boxes/deploy-project.js";import{reconcileHostFrameworkPreset}from"#setup/boxes/reconcile-host-framework-preset.js";import{selectChannels}from"#setup/boxes/select-channels.js";import{detectDeployment,projectResolutionFromDeployment}from"#setup/project-resolution.js";import{createPrompter}from"#setup/prompter.js";import{runInteractive}from"#setup/runner.js";import{createDefaultSetupState,snapshotSetupState}from"#setup/state.js";const KNOWN_CHANNEL_KINDS=[`slack`,`web`];function isChannelKind(e){return KNOWN_CHANNEL_KINDS.includes(e)}function parseChannelKind(e){if(!isChannelKind(e))throw Error(`Unknown channel kind "${e}". Known: ${KNOWN_CHANNEL_KINDS.join(`, `)}.`);return e}const defaultChannelsAddDependencies={detectDeployment};async function runAddChannelsFlow(n,r,i,s){if(r===void 0&&(i.yes||!process.stdin.isTTY||!process.stdout.isTTY))throw Error(`Pass a channel kind: \`eve channels add <${KNOWN_CHANNEL_KINDS.join(`|`)}>\`.`);let c=s.createPrompter?.()??createPrompter();c.intro(`Add channels to your eve agent`),c.log.message(`Checking the current Vercel project...`);let l={...createDefaultSetupState(),project:projectResolutionFromDeployment(await s.detectDeployment(n)),projectPath:{kind:`resolved`,inPlace:!0,path:n}},u;function inspectRegistrations(){return u===void 0&&(c.log.message(`Inspecting existing channel registrations...`),u=inspectExistingChannelRegistrations(n)),u}let d=r===void 0?(await inspectRegistrations()).disabledChannelReasons:void 0,f=await runInteractive([selectChannels({asker:interactiveAsker(c),variant:`channels-add`,presetChannels:r===void 0?void 0:[r],disabledChannelReasons:d,validateSelection:async t=>{!t.includes(`web`)&&!t.includes(`slack`)||assertCanAddSelectedChannels(t,await inspectRegistrations())}}),addChannels({asker:interactiveAsker(c),prompter:c,presetCreateSlackbot:i.yes?!0:void 0,force:i.force,configureVercelServices:!0,ensureLinkedProject:`interactive-vercel-link`,deps:s.addChannelsDeps}),reconcileHostFrameworkPreset({prompter:c}),deployProject({prompter:c,ensureLinkedProject:`interactive-vercel-link`,deps:s.deployProjectDeps})],l,{write:e=>c.log.message(e)},{snapshot:snapshotSetupState});f.kind!==`cancelled`&&c.outro(f.state.channels.length===0?`No channels added.`:`Channels added.`)}async function runChannelsAddCommand(e,t,i,a=defaultChannelsAddDependencies){if(!await isEveProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}try{await runAddChannelsFlow(t,i.kind===void 0?void 0:parseChannelKind(i.kind),i.options,a)}catch(t){e.error(t instanceof Error?t.message:String(t)),process.exitCode=1}}async function runChannelsListCommand(e,t,a){if(!await isEveProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}let o=await listAuthoredChannels(t);if(a.json){e.log(JSON.stringify({channels:o},null,2));return}if(o.length===0){e.log("No channels defined. Run `eve channels add` to add one.");return}for(let t of o)e.log(t)}export{runChannelsAddCommand,runChannelsListCommand};
@@ -12,10 +12,11 @@ export interface LinkCommandDependencies {
12
12
  flowDeps?: Partial<LinkFlowDeps>;
13
13
  }
14
14
  /**
15
- * `eve link`: pick a Vercel team and project (re-linking when one is already
16
- * linked), run `vercel link` for the selected project, then pull env so the AI Gateway
17
- * credential lands in `.env.local`. The flow itself is {@link runLinkFlow}, shared with the dev
18
- * TUI `/model` menu's provider row. Interactive only: the pickers are the point of the command,
19
- * so a non-TTY run refuses with guidance instead of guessing a project.
15
+ * `eve link`: pick a Vercel team, then create or select a project (re-linking
16
+ * when one is already linked), run `vercel link` for the resolved project,
17
+ * then pull env so the AI Gateway credential lands in `.env.local`. The flow
18
+ * itself is {@link runLinkFlow}, shared with the dev TUI `/model` menu's
19
+ * provider row. Interactive only: the pickers are the point of the command, so
20
+ * a non-TTY run refuses with guidance instead of guessing a project.
20
21
  */
21
22
  export declare function runLinkCommand(logger: LinkCliLogger, appRoot: string, dependencies?: LinkCommandDependencies): Promise<void>;
@@ -1 +1 @@
1
- import{NOT_AN_AGENT_MESSAGE,hasInteractiveTerminal}from"./preconditions.js";import{isEveProject}from"#setup/scaffold/index.js";import{createPrompter}from"#setup/prompter.js";import{runLinkFlow}from"#setup/flows/link.js";const defaultDependencies={isEveProject,hasInteractiveTerminal};async function runLinkCommand(t,n,r=defaultDependencies){if(!await r.isEveProject(n)){t.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}if(!r.hasInteractiveTerminal()){t.error("`eve link` needs an interactive terminal to pick the team and project. In CI, run `vercel link --project <name> --yes --non-interactive` instead."),process.exitCode=1;return}let i=r.createPrompter?.()??createPrompter();i.intro(`Link your eve agent to Vercel`);try{let e=await runLinkFlow({appRoot:n,prompter:i,deps:r.flowDeps});i.outro(e.kind===`cancelled`?`Cancelled.`:`Project linked.`)}catch(e){t.error(e instanceof Error?e.message:String(e)),process.exitCode=1}}export{runLinkCommand};
1
+ import{NOT_AN_AGENT_MESSAGE,hasInteractiveTerminal}from"./preconditions.js";import{isEveProject}from"#setup/scaffold/index.js";import{createPrompter}from"#setup/prompter.js";import{runLinkFlow}from"#setup/flows/link.js";const defaultDependencies={isEveProject,hasInteractiveTerminal};async function runLinkCommand(t,n,r=defaultDependencies){if(!await r.isEveProject(n)){t.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}if(!r.hasInteractiveTerminal()){t.error("`eve link` needs an interactive terminal to pick the team and project. In CI, run `vercel link --project <name> --yes --non-interactive` instead."),process.exitCode=1;return}let i=r.createPrompter?.()??createPrompter();i.intro(`Link your eve agent to Vercel`);try{let e=await runLinkFlow({appRoot:n,prompter:i,projectSelection:`create-or-link`,deps:r.flowDeps});i.outro(e.kind===`cancelled`?`Cancelled.`:`Project linked.`)}catch(e){t.error(e instanceof Error?e.message:String(e)),process.exitCode=1}}export{runLinkCommand};
@@ -1,6 +1,7 @@
1
+ import { type BuildHost } from "#cli/commands/build.js";
1
2
  import { resolveDevUiMode, resolveTuiDisplayOptions } from "#cli/dev/ui-options.js";
2
3
  import type { RunDevelopmentTuiInput } from "#cli/dev/tui/tui.js";
3
- import type { ApplicationBuildOptions, DevelopmentServer, DevelopmentServerOptions, ProductionServerHandle } from "#internal/nitro/host/types.js";
4
+ import type { DevelopmentServer, DevelopmentServerOptions, ProductionServerHandle } from "#internal/nitro/host/types.js";
4
5
  export { resolveDevUiMode, resolveTuiDisplayOptions };
5
6
  interface CliLogger {
6
7
  error(message: string): void;
@@ -12,7 +13,7 @@ interface CliRuntimeDependencies {
12
13
  readonly appRoot: string;
13
14
  readonly serverUrl: string;
14
15
  }): Promise<boolean>;
15
- buildHost(appRoot: string, options: ApplicationBuildOptions): Promise<string>;
16
+ buildHost: BuildHost;
16
17
  printApplicationInfo(logger: CliLogger, appRoot: string, options?: {
17
18
  json?: boolean;
18
19
  }): Promise<void>;
@@ -1,3 +1,3 @@
1
- import{createLogger}from"#internal/logging.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{createCliTheme,renderCliTaggedLine}from"#cli/ui/output.js";import{isCodingAgentLaunch}from"#cli/agent-detection.js";import{eveCliBanner}from"#cli/banner.js";import{startCliLiveRow}from"#cli/ui/live-row.js";import{devBootPhase}from"#internal/dev-boot-progress.js";import{Command,CommanderError,InvalidArgumentError}from"#compiled/commander/index.js";import{resolveApplicationRoot}from"#internal/application/paths.js";import{resolveInternalVercelServiceOutput}from"#cli/vercel-service-output.js";import{registerProjectCommands}from"#cli/commands/register-project-commands.js";import{resolveDevUiMode,resolveTuiDisplayOptions}from"#cli/dev/ui-options.js";import{parseDevelopmentHeaderOption,resolveDevelopmentUrlTarget}from"#cli/dev/url-target.js";import{LOG_DISPLAY_MODES,parseLogDisplayMode}from"#cli/dev/tui/log-display-mode.js";import{resolveTuiTitle}from"#cli/dev/tui/target.js";import{parseDevelopmentServerUrl}from"#cli/dev/url.js";const devBootLog=createLogger(`dev.boot`);function createDevBootProgressReporter(e){return t=>{switch(t.type){case`phase-started`:e?.update(`Building your agent`,t.phase),devBootLog.debug(t.phase);return;case`phase-finished`:devBootLog.debug(`${t.phase} finished`,{ms:t.elapsedMs});return;case`before-first-paint`:e?.stop();return;default:return t}}}async function loadBuildHost(){return(await import(`#internal/nitro/host.js`)).buildApplication}async function loadPrintApplicationInfo(){return(await import(`#cli/commands/info.js`)).printApplicationInfo}async function loadRunDevelopmentTui(){return(await import(`#cli/dev/tui/tui.js`)).runDevelopmentTui}async function loadRunEvalCommand(){return(await import(`#evals/cli/eval.js`)).runEvalCommand}async function loadStartHost(){return(await import(`#internal/nitro/host.js`)).createDevelopmentServer}const loadIsActiveDevelopmentServerForApp=async()=>(await import(`#internal/nitro/host.js`)).isActiveDevelopmentServerForApp;async function loadStartProductionHost(){return(await import(`#internal/nitro/host.js`)).startProductionServer}function shouldPrintCliBootBanner(e){return e.name()===`info`||e.name()===`dev`||e.name()===`init`}async function waitForShutdownSignal(e){await new Promise((t,n)=>{let r=!1,cleanup=()=>{process.off(`SIGINT`,handleSignal),process.off(`SIGTERM`,handleSignal)},handleSignal=()=>{r||(r=!0,cleanup(),e.close().then(t,n))};process.once(`SIGINT`,handleSignal),process.once(`SIGTERM`,handleSignal)})}async function waitForProductionServer(e){await Promise.race([e.wait(),waitForShutdownSignal({close:()=>e.close()})])}function parsePortOption(e){if(!/^-?\d+$/.test(e))throw new InvalidArgumentError(`Expected a numeric port, received "${e}".`);let t=Number(e);if(t<0||t>65535)throw new InvalidArgumentError(`Expected a port between 0 and 65535, received "${e}".`);return t}const DISPLAY_MODES=new Set([`full`,`collapsed`,`auto-collapsed`,`hidden`]),STATS_MODES=new Set([`tokens`,`tokensPerSecond`]);function parseDisplayMode(e){if(!DISPLAY_MODES.has(e))throw new InvalidArgumentError(`Expected one of ${[...DISPLAY_MODES].join(`, `)}, received "${e}".`);return e}function parseStatsMode(e){if(!STATS_MODES.has(e))throw new InvalidArgumentError(`Expected one of ${[...STATS_MODES].join(`, `)}, received "${e}".`);return e}function parseLogsMode(e){let t=parseLogDisplayMode(e);if(t===void 0)throw new InvalidArgumentError(`Expected one of ${LOG_DISPLAY_MODES.join(`, `)}, received "${e}".`);return t}function parseContextSizeOption(e){let t=Number(e);if(!Number.isFinite(t)||t<=0)throw new InvalidArgumentError(`Expected a positive number, received "${e}".`);return t}function hasInteractiveTerminal(){return!!(process.stdin.isTTY&&process.stdout.isTTY)}function createCliProgram(e,i){let c=resolveApplicationRoot(),m=resolveInstalledPackageInfo().version,h=new Command,_=createCliTheme();h.name(`eve`).description(`Build and run an eve application.`).version(m).showHelpAfterError().exitOverride().hook(`preAction`,(t,n)=>{shouldPrintCliBootBanner(n)&&e.log(eveCliBanner())}).configureOutput({writeErr:t=>{e.error(t.trimEnd())},writeOut:t=>{e.log(t.trimEnd())}});let v=h.command(`channels`).description(`Manage user-authored channels in the current project.`);v.command(`add [kind]`).description(`Add channels interactively, or scaffold a channel kind (slack | web).`).option(`-f, --force`,`Overwrite existing channel files`).option(`-y, --yes`,`Assume yes for confirmations; requires an explicit channel kind`).action(async(t,n)=>{let{runChannelsAddCommand:r}=await import(`#cli/commands/channels.js`);await r(e,c,{kind:t,options:n})}),v.command(`list`).description(`List user-authored channels in the current project.`).option(`--json`,`Output as JSON`).action(async t=>{let{runChannelsListCommand:n}=await import(`#cli/commands/channels.js`);await n(e,c,t)});let y=h.command(`extension`).description(`Create and build reusable eve extension packages.`);return y.command(`init [target]`).description(`Create a new eve extension package.`).option(`-y, --yes`,`Accepted for compatibility; has no effect`).action(async(t,n)=>{n.yes&&e.error(`warning: --yes has no effect for eve extension init.`);let{runExtensionInitCommand:r}=await import(`#cli/commands/extension-init.js`);await r(e,c,t)}),y.command(`build`).description(`Build the current package as an eve extension.`).action(async()=>{let{loadDevelopmentEnvironmentFiles:t}=await import(`#cli/dev/environment.js`);t(c);let{runExtensionBuildCommand:n}=await import(`#cli/commands/extension-build.js`);await n(e,c)}),h.command(`init [target]`).description(`Create a new eve agent, or add one to an existing project directory.`).option(`--channel-web-nextjs`,`Add the Web Chat application (Next.js)`).option(`-y, --yes`,`Accepted for compatibility; has no effect`).action(async(t,n)=>{n.yes&&e.error(`warning: --yes has no effect for eve init.`);let{runInitCommand:r}=await import(`#cli/commands/init.js`);await r(e,c,t,{channelWebNextjs:n.channelWebNextjs})}),registerProjectCommands({program:h,logger:e,appRoot:c}),h.command(`build`).description(`Build the current eve application.`).option(`--skip-sandbox-prewarm`,`Skip Vercel sandbox template prewarm; output may not be deployable`).action(async t=>{let{loadDevelopmentEnvironmentFiles:n}=await import(`#cli/dev/environment.js`);n(c);let a=await(i.buildHost??await loadBuildHost())(c,{skipVercelSandboxPrewarm:t.skipSandboxPrewarm===!0,vercelServiceOutput:resolveInternalVercelServiceOutput(c)});e.log(renderCliTaggedLine(_,{message:`built output at ${a}`,tag:`build`,tone:`success`}))}),h.command(`start`).description(`Start a built eve application.`).option(`--host <host>`,`Host interface to bind`).option(`--port <port>`,`Port to listen on (defaults to $PORT, then 3000)`,parsePortOption).action(async t=>{let{loadDevelopmentEnvironmentFiles:n}=await import(`#cli/dev/environment.js`);n(c);let a=await(i.startProductionHost??await loadStartProductionHost())(c,{host:t.host,port:t.port});e.log(renderCliTaggedLine(_,{message:`server listening at ${a.url}`,tag:`start`,tone:`success`})),await waitForProductionServer(a)}),h.command(`dev`).description(`Start the eve development server or connect to an existing URL.`).argument(`[url]`,`Connect to an existing server URL`,parseDevelopmentServerUrl).option(`--host <host>`,`Host interface to bind`).option(`--port <port>`,`Port to listen on (defaults to $PORT, then 2000)`,parsePortOption).option(`-u, --url <url>`,`Connect to an existing server URL`,parseDevelopmentServerUrl).option(`-H, --header <header>`,`Request header for a URL target, in "Name: value" form (repeatable)`,parseDevelopmentHeaderOption).option(`--no-ui`,`Start the server without an interactive UI`).option(`--name <name>`,`Title shown in the terminal UI (defaults to the app folder name)`).option(`--input <text>`,`Pre-fill the prompt input, or start onboarding with /model`).option(`--tools <mode>`,`How tool calls render: full | collapsed | auto-collapsed | hidden`,parseDisplayMode).option(`--reasoning <mode>`,`How reasoning renders: full | collapsed | auto-collapsed | hidden`,parseDisplayMode).option(`--subagents <mode>`,`How subagent sections render: full | collapsed | auto-collapsed | hidden`,parseDisplayMode).option(`--connection-auth <mode>`,`How connection authorization renders: full | collapsed | auto-collapsed | hidden`,parseDisplayMode).option(`--assistant-response-stats <mode>`,`Assistant header statistic: tokens | tokensPerSecond`,parseStatsMode).option(`--context-size <tokens>`,`Model context window size, shown as a usage percentage`,parseContextSizeOption).option(`--logs <mode>`,`Which server/agent logs to show: all | stderr | sandbox | none`,parseLogsMode).addHelpText(`after`,`
1
+ import{createLogger}from"#internal/logging.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{createCliTheme,renderCliTaggedLine}from"#cli/ui/output.js";import{isCodingAgentLaunch}from"#cli/agent-detection.js";import{eveCliBanner}from"#cli/banner.js";import{startCliLiveRow}from"#cli/ui/live-row.js";import{devBootPhase}from"#internal/dev-boot-progress.js";import{Command,CommanderError,InvalidArgumentError}from"#compiled/commander/index.js";import{registerBuildCommand}from"#cli/commands/build.js";import{resolveApplicationRoot}from"#internal/application/paths.js";import{registerProjectCommands}from"#cli/commands/register-project-commands.js";import{resolveDevUiMode,resolveTuiDisplayOptions}from"#cli/dev/ui-options.js";import{parseDevelopmentHeaderOption,resolveDevelopmentUrlTarget}from"#cli/dev/url-target.js";import{LOG_DISPLAY_MODES,parseLogDisplayMode}from"#cli/dev/tui/log-display-mode.js";import{resolveTuiTitle}from"#cli/dev/tui/target.js";import{parseDevelopmentServerUrl}from"#cli/dev/url.js";const devBootLog=createLogger(`dev.boot`);function createDevBootProgressReporter(e){return t=>{switch(t.type){case`phase-started`:e?.update(`Building your agent`,t.phase),devBootLog.debug(t.phase);return;case`phase-finished`:devBootLog.debug(`${t.phase} finished`,{ms:t.elapsedMs});return;case`before-first-paint`:e?.stop();return;default:return t}}}async function loadPrintApplicationInfo(){return(await import(`#cli/commands/info.js`)).printApplicationInfo}async function loadRunDevelopmentTui(){return(await import(`#cli/dev/tui/tui.js`)).runDevelopmentTui}async function loadRunEvalCommand(){return(await import(`#evals/cli/eval.js`)).runEvalCommand}async function loadStartHost(){return(await import(`#internal/nitro/host.js`)).createDevelopmentServer}const loadIsActiveDevelopmentServerForApp=async()=>(await import(`#internal/nitro/host.js`)).isActiveDevelopmentServerForApp;async function loadStartProductionHost(){return(await import(`#internal/nitro/host.js`)).startProductionServer}function shouldPrintCliBootBanner(e){return e.name()===`info`||e.name()===`dev`||e.name()===`init`}async function waitForShutdownSignal(e){await new Promise((t,n)=>{let r=!1,cleanup=()=>{process.off(`SIGINT`,handleSignal),process.off(`SIGTERM`,handleSignal)},handleSignal=()=>{r||(r=!0,cleanup(),e.close().then(t,n))};process.once(`SIGINT`,handleSignal),process.once(`SIGTERM`,handleSignal)})}async function waitForProductionServer(e){await Promise.race([e.wait(),waitForShutdownSignal({close:()=>e.close()})])}function parsePortOption(e){if(!/^-?\d+$/.test(e))throw new InvalidArgumentError(`Expected a numeric port, received "${e}".`);let t=Number(e);if(t<0||t>65535)throw new InvalidArgumentError(`Expected a port between 0 and 65535, received "${e}".`);return t}const DISPLAY_MODES=new Set([`full`,`collapsed`,`auto-collapsed`,`hidden`]),STATS_MODES=new Set([`tokens`,`tokensPerSecond`]);function parseDisplayMode(e){if(!DISPLAY_MODES.has(e))throw new InvalidArgumentError(`Expected one of ${[...DISPLAY_MODES].join(`, `)}, received "${e}".`);return e}function parseStatsMode(e){if(!STATS_MODES.has(e))throw new InvalidArgumentError(`Expected one of ${[...STATS_MODES].join(`, `)}, received "${e}".`);return e}function parseLogsMode(e){let t=parseLogDisplayMode(e);if(t===void 0)throw new InvalidArgumentError(`Expected one of ${LOG_DISPLAY_MODES.join(`, `)}, received "${e}".`);return t}function parseContextSizeOption(e){let t=Number(e);if(!Number.isFinite(t)||t<=0)throw new InvalidArgumentError(`Expected a positive number, received "${e}".`);return t}function hasInteractiveTerminal(){return!!(process.stdin.isTTY&&process.stdout.isTTY)}function createCliProgram(e,i){let c=resolveApplicationRoot(),m=resolveInstalledPackageInfo().version,h=new Command,_=createCliTheme();h.name(`eve`).description(`Build and run an eve application.`).version(m).showHelpAfterError().exitOverride().hook(`preAction`,(t,n)=>{shouldPrintCliBootBanner(n)&&e.log(eveCliBanner())}).configureOutput({writeErr:t=>{e.error(t.trimEnd())},writeOut:t=>{e.log(t.trimEnd())}});let v=h.command(`channels`).description(`Manage user-authored channels in the current project.`);v.command(`add [kind]`).description(`Add channels interactively, or scaffold a channel kind (slack | web).`).option(`-f, --force`,`Overwrite existing channel files`).option(`-y, --yes`,`Assume yes for confirmations; requires an explicit channel kind`).action(async(t,n)=>{let{runChannelsAddCommand:r}=await import(`#cli/commands/channels.js`);await r(e,c,{kind:t,options:n})}),v.command(`list`).description(`List user-authored channels in the current project.`).option(`--json`,`Output as JSON`).action(async t=>{let{runChannelsListCommand:n}=await import(`#cli/commands/channels.js`);await n(e,c,t)});let y=h.command(`extension`).description(`Create and build reusable eve extension packages.`);return y.command(`init [target]`).description(`Create a new eve extension package.`).option(`-y, --yes`,`Accepted for compatibility; has no effect`).action(async(t,n)=>{n.yes&&e.error(`warning: --yes has no effect for eve extension init.`);let{runExtensionInitCommand:r}=await import(`#cli/commands/extension-init.js`);await r(e,c,t)}),y.command(`build`).description(`Build the current package as an eve extension.`).action(async()=>{let{loadDevelopmentEnvironmentFiles:t}=await import(`#cli/dev/environment.js`);t(c);let{runExtensionBuildCommand:n}=await import(`#cli/commands/extension-build.js`);await n(e,c)}),h.command(`init [target]`).description(`Create a new eve agent, or add one to an existing project directory.`).option(`--channel-web-nextjs`,`Add the Web Chat application (Next.js)`).option(`-y, --yes`,`Accepted for compatibility; has no effect`).action(async(t,n)=>{n.yes&&e.error(`warning: --yes has no effect for eve init.`);let{runInitCommand:r}=await import(`#cli/commands/init.js`);await r(e,c,t,{channelWebNextjs:n.channelWebNextjs})}),registerProjectCommands({program:h,logger:e,appRoot:c}),registerBuildCommand({appRoot:c,buildHost:i.buildHost,logger:e,program:h}),h.command(`start`).description(`Start a built eve application.`).option(`--host <host>`,`Host interface to bind`).option(`--port <port>`,`Port to listen on (defaults to $PORT, then 3000)`,parsePortOption).action(async t=>{let{loadDevelopmentEnvironmentFiles:n}=await import(`#cli/dev/environment.js`);n(c);let a=await(i.startProductionHost??await loadStartProductionHost())(c,{host:t.host,port:t.port});e.log(renderCliTaggedLine(_,{message:`server listening at ${a.url}`,tag:`start`,tone:`success`})),await waitForProductionServer(a)}),h.command(`dev`).description(`Start the eve development server or connect to an existing URL.`).argument(`[url]`,`Connect to an existing server URL`,parseDevelopmentServerUrl).option(`--host <host>`,`Host interface to bind`).option(`--port <port>`,`Port to listen on (defaults to $PORT, then 2000)`,parsePortOption).option(`-u, --url <url>`,`Connect to an existing server URL`,parseDevelopmentServerUrl).option(`-H, --header <header>`,`Request header for a URL target, in "Name: value" form (repeatable)`,parseDevelopmentHeaderOption).option(`--no-ui`,`Start the server without an interactive UI`).option(`--name <name>`,`Title shown in the terminal UI (defaults to the app folder name)`).option(`--input <text>`,`Pre-fill the prompt input, or start onboarding with /model`).option(`--tools <mode>`,`How tool calls render: full | collapsed | auto-collapsed | hidden`,parseDisplayMode).option(`--reasoning <mode>`,`How reasoning renders: full | collapsed | auto-collapsed | hidden`,parseDisplayMode).option(`--subagents <mode>`,`How subagent sections render: full | collapsed | auto-collapsed | hidden`,parseDisplayMode).option(`--connection-auth <mode>`,`How connection authorization renders: full | collapsed | auto-collapsed | hidden`,parseDisplayMode).option(`--assistant-response-stats <mode>`,`Assistant header statistic: tokens | tokensPerSecond`,parseStatsMode).option(`--context-size <tokens>`,`Model context window size, shown as a usage percentage`,parseContextSizeOption).option(`--logs <mode>`,`Which server/agent logs to show: all | stderr | sandbox | none`,parseLogsMode).addHelpText(`after`,`
2
2
  You can also pass a bare URL, for example: eve dev https://example.com
3
3
  `).action(async(t,n)=>{let a=resolveDevelopmentUrlTarget(n,t),s=a?.serverUrl,u=hasInteractiveTerminal(),d=resolveDevUiMode({options:n,interactive:u});if(n.input!==void 0&&d===`headless`)throw new InvalidArgumentError(`--input requires the interactive UI.`);let f=!1;s!==void 0&&(f=await(i.isActiveDevelopmentServerForApp??await loadIsActiveDevelopmentServerForApp())({appRoot:c,serverUrl:s}));let runInteractiveUi=async(e,t)=>{let r=await devBootPhase(`loading interactive UI`,async()=>i.runDevelopmentTui??await loadRunDevelopmentTui(),t),o=resolveTuiDisplayOptions(n),l=s===void 0||f?{kind:`local`,serverUrl:e.serverUrl,workspaceRoot:e.appRoot??c}:{kind:`remote`,serverUrl:e.serverUrl,workspaceRoot:c},u=resolveTuiTitle({name:n.name,target:l});u!==void 0&&(o.name=u);let d={target:l,initialInput:n.input,onBootProgress:t,...o};a?.headers===void 0?await r(d):await r({...d,headers:a.headers})};if(s){let{loadDevelopmentEnvironmentFiles:t}=await import(`#cli/dev/environment.js`);if(t(c),e.log(`↗ ${f?`local`:`remote`} mode targeting ${_.info(new URL(s).host)}`),d===`headless`){e.log(renderCliTaggedLine(_,{message:`Interactive UI disabled because the current terminal is not a TTY.`,tag:`dev`,tone:`warning`}));return}e.log(``),await runInteractiveUi({serverUrl:s});return}d===`tui`&&e.log(``);let p=d===`tui`?startCliLiveRow(e):void 0,m=createDevBootProgressReporter(p);p?.update(`Building your agent`);let h=!1,g,closeServer=async()=>{h||g===void 0||(h=!0,await g.close())};try{g=(i.startHost??await loadStartHost())(c,{existing:d===`tui`?`attach-if-unconfigured`:`reject`,host:n.host,onBootProgress:m,port:n.port});let t=await g.start();if(d!==`tui`&&e.log(renderCliTaggedLine(_,{message:`server listening at ${t.url}`,tag:`dev`,tone:`success`})),d===`headless`)return n.ui!==!1&&!u&&e.log(renderCliTaggedLine(_,{message:`Interactive UI disabled because the current terminal is not a TTY.`,tag:`dev`,tone:`warning`})),await waitForShutdownSignal({close:closeServer});await runInteractiveUi({appRoot:t.appRoot,serverUrl:t.url},m)}finally{p?.stop(),await closeServer()}}),h.command(`info`).description(`Print resolved application information.`).option(`--json`,`Output as JSON`).action(async t=>{await(i.printApplicationInfo??await loadPrintApplicationInfo())(e,c,t)}),h.command(`eval`).description(`Run evals against an eve agent.`).argument(`[evalIds...]`,`Eval ids (or directory prefixes) to run (all discovered evals when omitted)`).option(`--url <url>`,`Remote agent URL (skip local host startup)`,parseDevelopmentServerUrl).option(`--tag <tag...>`,`Run only evals carrying a tag`).option(`--strict`,`Fail the exit code when any score falls below its threshold`).option(`--list`,`Print discovered evals without running them`).option(`--timeout <ms>`,`Per-eval timeout in milliseconds`).option(`--max-concurrency <n>`,`Max concurrent eval executions`).option(`--json`,`Output results as JSON`).option(`--junit <path>`,`Write JUnit XML results to a file`).option(`--skip-report`,`Skip eval-defined reporters (e.g. Braintrust)`).option(`--verbose`,`Stream per-eval t.log lines to stdout`).action(async(t,n)=>{await(i.runEvalCommand??await loadRunEvalCommand())(t,n,e)}),h}async function runCli(e=process.argv.slice(2),t=console,n={}){let r=createCliProgram(t,n),a=e.length===0?[`dev`]:e;try{await r.parseAsync(a,{from:`user`})}catch(e){if(e instanceof CommanderError){if(e.exitCode===0)return;let r=await(n.isCodingAgentLaunch??isCodingAgentLaunch)();if(a[0]===`init`&&r){let{initAgentInstructions:e}=await import(`#cli/commands/agent-instructions.js`);t.log(e())}throw Error(e.message)}throw e}}export{resolveDevUiMode,resolveTuiDisplayOptions,runCli};
@@ -7,7 +7,7 @@ export { createDataUrlFilePart, createTextWithFileContent } from "#client/file-p
7
7
  export { MessageResponse } from "#client/message-response.js";
8
8
  export { ClientSession } from "#client/session.js";
9
9
  export type { EveAgentStoreCallbacks, EveAgentStoreInit, EveAgentStoreSnapshot, EveAgentStoreStatus, PrepareSend, } from "#client/eve-agent-store.js";
10
- export type { AgentInfoEntry, AgentInfoChannelEntry, AgentInfoChannels, AgentInfoConnectionEntry, AgentInfoDynamicResolverEntry, AgentInfoFrameworkChannelEntry, AgentInfoFrameworkToolEntry, AgentInfoHookEntry, AgentInfoInstructions, AgentInfoInstructionsEntry, AgentInfoResult, AgentInfoSandboxEntry, AgentInfoScheduleEntry, AgentInfoSkillEntry, AgentInfoSource, AgentInfoSubagentEntry, AgentInfoToolEntry, AgentInfoTools, ClientAuth, ClientOptions, ClientRedirectPolicy, HeadersValue, HealthResult, MessageResult, SendTurnInput, SendTurnPayload, SessionState, StreamOptions, TokenValue, } from "#client/types.js";
10
+ export type { AgentInfoEntry, AgentInfoChannelEntry, AgentInfoChannels, AgentInfoConnectionEntry, AgentInfoDynamicResolverEntry, AgentInfoFrameworkChannelEntry, AgentInfoFrameworkToolEntry, AgentInfoHookEntry, AgentInfoInstructions, AgentInfoInstructionsEntry, AgentInfoResult, AgentInfoSandboxEntry, AgentInfoScheduleEntry, AgentInfoSkillEntry, AgentInfoSource, AgentInfoSubagentEntry, AgentInfoToolEntry, AgentInfoTools, CancelSessionResult, ClientAuth, ClientOptions, ClientRedirectPolicy, HeadersValue, HealthResult, MessageResult, SendTurnInput, SendTurnPayload, SessionState, StreamOptions, TokenValue, } from "#client/types.js";
11
11
  export type { EveAgentReducer, EveAgentReducerEvent, ClientInputRespondedEvent, ClientMessageFailedEvent, ClientMessageSubmittedEvent, } from "#client/reducer.js";
12
12
  export type { EveAuthorizationChallenge, EveAuthorizationOutcome, EveAuthorizationPart, EveMessageData, EveDynamicToolPart, EveMessageInputRequest, EveMessage, EveMessageMetadata, EveMessagePart, EveMessageToolMetadata, } from "#client/message-reducer.js";
13
13
  export type { ActionResultStreamEvent, ActionsRequestedStreamEvent, AssistantStepFinishReason, AuthorizationOutcome, CompactionCompletedStreamEvent, CompactionRequestedStreamEvent, AuthorizationCompletedStreamEvent, ConnectionAuthorizationOutcome, AuthorizationRequiredStreamEvent, HandleMessageStreamEvent, InputRequestedStreamEvent, MessageAppendedStreamEvent, MessageCompletedStreamEvent, MessageReceivedPart, MessageReceivedStreamEvent, ReasoningAppendedStreamEvent, ReasoningCompletedStreamEvent, ResultCompletedStreamEvent, SessionCompletedStreamEvent, SessionFailedStreamEvent, SessionStartedStreamEvent, SessionWaitingStreamEvent, StepCompletedStreamEvent, StepFailedStreamEvent, StepStartedStreamEvent, SubagentCalledStreamEvent, SubagentChildEventStreamEvent, SubagentCompletedStreamEvent, SubagentStartedStreamEvent, TurnCancelledStreamEvent, TurnCompletedStreamEvent, TurnFailedStreamEvent, TurnStartedStreamEvent, TurnFailureStreamEvent, } from "#protocol/message.js";
@@ -1,3 +1,3 @@
1
- function isStreamDisconnectError(e){if(e instanceof DOMException)return e.name===`AbortError`;if(!(e instanceof Error))return!1;let t=`code`in e&&typeof e.code==`string`?e.code:void 0;return e.name===`AbortError`||e.message===`terminated`||t===`UND_ERR_SOCKET`||/abort|cancel|disconnect|premature close|socket|terminated/i.test(e.message)}async function*readNdjsonStream(e){let t=e.getReader(),n=new TextDecoder,r=``,i=!1;try{for(;;){let e=await t.read();if(e.done){i=!0,r+=n.decode();break}e.value&&(r+=n.decode(e.value,{stream:!0}));let a=r.indexOf(`
1
+ function isStreamDisconnectError(e){if(e instanceof DOMException)return e.name===`AbortError`;if(!(e instanceof Error))return!1;let t=`code`in e&&typeof e.code==`string`?e.code:void 0;return e.name===`AbortError`||e.message===`terminated`||t===`UND_ERR_SOCKET`||e instanceof TypeError&&/^(?:failed to fetch|fetch failed)$/i.test(e.message)||/abort|cancel|disconnect|premature close|socket|terminated/i.test(e.message)}async function*readNdjsonStream(e){let t=e.getReader(),n=new TextDecoder,r=``,i=!1;try{for(;;){let e=await t.read();if(e.done){i=!0,r+=n.decode();break}e.value&&(r+=n.decode(e.value,{stream:!0}));let a=r.indexOf(`
2
2
  `);for(;a!==-1;){let e=r.slice(0,a).trim();r=r.slice(a+1),e.length>0&&(yield JSON.parse(e)),a=r.indexOf(`
3
3
  `)}}let e=r.trim();e.length>0&&(yield JSON.parse(e))}finally{i||await t.cancel().catch(()=>{}),t.releaseLock()}}export{isStreamDisconnectError,readNdjsonStream};
@@ -19,8 +19,9 @@ type OpenStreamBodyInput = Omit<OpenStreamInput, "maxReconnectAttempts">;
19
19
  */
20
20
  export declare function openStreamIterable(input: OpenStreamInput): AsyncGenerator<HandleMessageStreamEvent>;
21
21
  /**
22
- * Opens one stream response body, retrying the short propagation window where
23
- * a just-acknowledged session may not yet be readable from the stream route.
22
+ * Opens one stream response body, retrying transient network errors and the
23
+ * short propagation window where a just-acknowledged session may not yet be
24
+ * readable from the stream route.
24
25
  */
25
26
  export declare function openStreamBody(input: OpenStreamBodyInput): Promise<ReadableStream<Uint8Array>>;
26
27
  export {};
@@ -1 +1 @@
1
- import{createEveMessageStreamRoutePath}from"#protocol/routes.js";import{ClientError}from"#client/client-error.js";import{createClientUrl}from"#client/url.js";import{isStreamDisconnectError,readNdjsonStream}from"#client/ndjson.js";const STREAM_OPEN_RETRYABLE_STATUS=new Set([404,409,425,500,502,503,504]);async function*openStreamIterable(e){let t=e.startIndex,n=e.startIndex<0?0:e.maxReconnectAttempts;for(;;){let a=await openStreamBody({...e,startIndex:t}),o=!1;try{for await(let e of readNdjsonStream(a))t+=1,yield e}catch(e){if(!isStreamDisconnectError(e))throw e;o=!0}if(!o||e.signal?.aborted||n<=0)return;--n}}async function openStreamBody(r){let i,o,s;for(let c=0;c<12;c+=1){let l=createClientUrl(r.host,createEveMessageStreamRoutePath(r.sessionId),r.startIndex===0?void 0:{startIndex:String(r.startIndex)}),u=await r.resolveHeaders(),d=await fetch(l,{headers:u,redirect:r.redirect,signal:r.signal??null});if(d.ok){if(!d.body)throw new ClientError(d.status,`Response body is null.`,d.headers);return d.body}if(i=d.status,o=await d.text(),s=d.headers,!STREAM_OPEN_RETRYABLE_STATUS.has(d.status))throw new ClientError(d.status,o,d.headers);c<11&&await sleep(250)}throw new ClientError(i??0,o??`Failed to open message stream.`,s)}async function sleep(e){await new Promise(t=>setTimeout(t,e))}export{openStreamBody,openStreamIterable};
1
+ import{createEveMessageStreamRoutePath}from"#protocol/routes.js";import{ClientError}from"#client/client-error.js";import{createClientUrl}from"#client/url.js";import{isStreamDisconnectError,readNdjsonStream}from"#client/ndjson.js";const STREAM_OPEN_RETRYABLE_STATUS=new Set([404,409,425,500,502,503,504]);async function*openStreamIterable(e){let t=e.startIndex,n=e.startIndex<0?0:e.maxReconnectAttempts;for(;;){let i=await openStreamBody({...e,startIndex:t}),a=!1;try{for await(let e of readNdjsonStream(i))t+=1,yield e}catch(e){if(!isStreamDisconnectError(e))throw e;a=!0}if(!a||e.signal?.aborted||n<=0)return;--n}}async function openStreamBody(r){let a,o,s;for(let c=0;c<12;c+=1){let l=createClientUrl(r.host,createEveMessageStreamRoutePath(r.sessionId),r.startIndex===0?void 0:{startIndex:String(r.startIndex)}),u=await r.resolveHeaders(),d;try{d=await fetch(l,{headers:u,redirect:r.redirect,signal:r.signal??null})}catch(e){if(r.signal?.aborted||!isStreamDisconnectError(e)||c===11)throw e;await sleep(250);continue}if(d.ok){if(!d.body)throw new ClientError(d.status,`Response body is null.`,d.headers);return d.body}if(a=d.status,o=await d.text(),s=d.headers,!STREAM_OPEN_RETRYABLE_STATUS.has(d.status))throw new ClientError(d.status,o,d.headers);c<11&&await sleep(250)}throw new ClientError(a??0,o??`Failed to open message stream.`,s)}async function sleep(e){await new Promise(t=>setTimeout(t,e))}export{openStreamBody,openStreamIterable};