eve 0.66.0 → 0.66.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/src/channel/forwarded-principal.d.ts +26 -6
  3. package/dist/src/channel/forwarded-principal.js +1 -1
  4. package/dist/src/chunks/{use-eve-agent-BUeSjwIk.js → use-eve-agent-Di1u2zKu.js} +24 -4
  5. package/dist/src/chunks/{use-eve-agent-ydPlURM4.js → use-eve-agent-PbSMyJ6e.js} +24 -4
  6. package/dist/src/cli/commands/extension-build.js +1 -1
  7. package/dist/src/cli/commands/registry-project.d.ts +2 -1
  8. package/dist/src/cli/commands/registry-project.js +2 -2
  9. package/dist/src/cli/commands/registry.js +1 -1
  10. package/dist/src/cli/commands/trace-detail.d.ts +5 -25
  11. package/dist/src/cli/commands/trace-detail.js +1 -1
  12. package/dist/src/cli/commands/trace.js +2 -2
  13. package/dist/src/cli/dev/run-interactive-ui.js +1 -1
  14. package/dist/src/cli/dev/tui/argument-typeahead.d.ts +1 -1
  15. package/dist/src/cli/dev/tui/argument-typeahead.js +1 -1
  16. package/dist/src/cli/dev/tui/prompt-command-handler.js +1 -1
  17. package/dist/src/cli/dev/tui/prompt-commands.js +1 -1
  18. package/dist/src/cli/dev/tui/registry-result-message.js +1 -1
  19. package/dist/src/cli/dev/tui/runner.d.ts +2 -2
  20. package/dist/src/cli/dev/tui/setup-commands.d.ts +3 -1
  21. package/dist/src/cli/dev/tui/setup-commands.js +1 -1
  22. package/dist/src/cli/dev/tui/setup-panel.d.ts +14 -0
  23. package/dist/src/cli/dev/tui/setup-panel.js +4 -4
  24. package/dist/src/cli/dev/tui/subagent-pump.d.ts +2 -10
  25. package/dist/src/cli/dev/tui/subagent-pump.js +1 -1
  26. package/dist/src/cli/dev/tui/terminal-renderer.d.ts +2 -2
  27. package/dist/src/cli/dev/tui/terminal-renderer.js +10 -10
  28. package/dist/src/cli/dev/tui/traces/trace-conversation.js +1 -1
  29. package/dist/src/cli/dev/tui/tui.js +1 -1
  30. package/dist/src/client/client-error.js +1 -1
  31. package/dist/src/client/open-stream.d.ts +3 -2
  32. package/dist/src/client/open-stream.js +1 -1
  33. package/dist/src/client/session.d.ts +16 -1
  34. package/dist/src/client/session.js +1 -1
  35. package/dist/src/compiled/.vendor-stamp.json +1 -1
  36. package/dist/src/evals/session.d.ts +3 -2
  37. package/dist/src/evals/session.js +1 -1
  38. package/dist/src/evals/types.d.ts +8 -2
  39. package/dist/src/eve-channel/index.js +1 -1
  40. package/dist/src/eve-channel/types.d.ts +12 -4
  41. package/dist/src/execution/cancel-indexed-session-tasks-step.js +1 -1
  42. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  43. package/dist/src/execution/proxied-deliver-step.js +1 -1
  44. package/dist/src/execution/route-child-delivery.js +2 -2
  45. package/dist/src/execution/session/admission.js +1 -1
  46. package/dist/src/execution/session/finalization.js +1 -1
  47. package/dist/src/execution/session/handoff-steps.js +1 -1
  48. package/dist/src/execution/session/input-queue.d.ts +12 -10
  49. package/dist/src/execution/session/input-queue.js +1 -1
  50. package/dist/src/execution/session/next-input.js +1 -1
  51. package/dist/src/execution/session/program.js +1 -1
  52. package/dist/src/execution/session/turn-step-result.d.ts +3 -1
  53. package/dist/src/execution/session/turn-step-result.js +1 -1
  54. package/dist/src/execution/session/turn-step-types.d.ts +7 -2
  55. package/dist/src/execution/session/turn-step.js +1 -1
  56. package/dist/src/execution/session/turn.js +1 -1
  57. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  58. package/dist/src/execution/tasks/parent/control-shared.js +1 -1
  59. package/dist/src/execution/tasks/parent/dispatch.js +1 -1
  60. package/dist/src/execution/tasks/parent/hitl-proxy-steps.d.ts +1 -0
  61. package/dist/src/execution/tasks/parent/hitl-proxy-steps.js +1 -1
  62. package/dist/src/execution/tasks/parent/tool-execution.js +1 -1
  63. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  64. package/dist/src/execution/tools/ask-question-workflow.js +1 -1
  65. package/dist/src/execution/tools/sleep-workflow.js +1 -1
  66. package/dist/src/execution/tools/subagent/accept-event-step.js +1 -1
  67. package/dist/src/execution/tools/subagent/invoke-preparation.js +1 -1
  68. package/dist/src/execution/tools/subagent/invoke-step.js +1 -1
  69. package/dist/src/execution/tools/subagent/task-cancel.d.ts +1 -1
  70. package/dist/src/execution/tools/subagent/task-cancel.js +1 -1
  71. package/dist/src/harness/session-limit-enforcement.js +1 -1
  72. package/dist/src/harness/tool-loop.js +2 -2
  73. package/dist/src/harness/turn-tag-state.d.ts +2 -2
  74. package/dist/src/harness/workflow-tool-runs.d.ts +33 -5
  75. package/dist/src/harness/workflow-tool-runs.js +1 -1
  76. package/dist/src/internal/application/package.js +1 -1
  77. package/dist/src/internal/nitro/host/build-extension.js +1 -1
  78. package/dist/src/internal/nitro/host/extension-build-lock.d.ts +9 -0
  79. package/dist/src/internal/nitro/host/extension-build-lock.js +1 -0
  80. package/dist/src/internal/nitro/host/prepare-application-host.d.ts +5 -4
  81. package/dist/src/internal/nitro/host/prepare-application-host.js +1 -1
  82. package/dist/src/internal/nitro/host/types.d.ts +2 -2
  83. package/dist/src/internal/nitro/host/workspace-extensions.d.ts +31 -0
  84. package/dist/src/internal/nitro/host/workspace-extensions.js +1 -0
  85. package/dist/src/public/next/index.d.ts +10 -7
  86. package/dist/src/public/next/index.js +1 -1
  87. package/dist/src/public/next/server.d.ts +3 -0
  88. package/dist/src/public/next/server.js +2 -2
  89. package/dist/src/self-modification/extension/local-only.d.ts +5 -0
  90. package/dist/src/self-modification/extension/local-only.js +1 -0
  91. package/dist/src/self-modification/extension/subagents/agent/instructions.js +6 -6
  92. package/dist/src/self-modification/extension/subagents/agent/skills/trace_analysis.d.ts +10 -0
  93. package/dist/src/self-modification/extension/subagents/agent/skills/trace_analysis.js +19 -0
  94. package/dist/src/self-modification/extension/subagents/agent/tools/inspect_trace.d.ts +128 -0
  95. package/dist/src/self-modification/extension/subagents/agent/tools/inspect_trace.js +1 -0
  96. package/dist/src/self-modification/extension/subagents/agent/tools/inspect_trace_spans.d.ts +80 -0
  97. package/dist/src/self-modification/extension/subagents/agent/tools/inspect_trace_spans.js +1 -0
  98. package/dist/src/self-modification/extension/subagents/agent/tools/registry_add.js +1 -1
  99. package/dist/src/self-modification/extension/subagents/agent/tools/search_traces.d.ts +53 -0
  100. package/dist/src/self-modification/extension/subagents/agent/tools/search_traces.js +1 -0
  101. package/dist/src/self-modification/extension/trace-inspection.d.ts +15 -0
  102. package/dist/src/self-modification/extension/trace-inspection.js +1 -0
  103. package/dist/src/self-modification/sandbox.js +1 -1
  104. package/dist/src/setup/ask.d.ts +2 -0
  105. package/dist/src/setup/ask.js +1 -1
  106. package/dist/src/setup/cli/option-row.d.ts +3 -1
  107. package/dist/src/setup/cli/option-row.js +1 -1
  108. package/dist/src/setup/flows/model-login.d.ts +4 -0
  109. package/dist/src/setup/flows/model-login.js +1 -1
  110. package/dist/src/setup/integrations/web/setup.d.ts +15 -10
  111. package/dist/src/setup/integrations/web/setup.js +30 -1
  112. package/dist/src/setup/scaffold/create/project.js +2 -2
  113. package/dist/src/setup/scaffold/create/web-template.d.ts +7 -3
  114. package/dist/src/setup/scaffold/create/web-template.js +39 -20
  115. package/dist/src/setup/scaffold/update/channels.js +2 -2
  116. package/dist/src/subagents/parent-notification.d.ts +1 -1
  117. package/dist/src/subagents/remote-dispatch.d.ts +1 -0
  118. package/dist/src/subagents/remote-dispatch.js +1 -1
  119. package/dist/src/svelte/index.js +1 -1
  120. package/dist/src/svelte/use-eve-agent.js +1 -1
  121. package/dist/src/tasks/delivery-context.js +2 -2
  122. package/dist/src/tasks/notification.d.ts +6 -0
  123. package/dist/src/tasks/notification.js +1 -1
  124. package/dist/src/tracing/agent-trace-context-store.js +1 -1
  125. package/dist/src/tracing/local-trace-analysis.d.ts +51 -0
  126. package/dist/src/tracing/local-trace-analysis.js +1 -0
  127. package/dist/src/tracing/local-trace-discovery-index.d.ts +15 -0
  128. package/dist/src/tracing/local-trace-discovery-index.js +1 -0
  129. package/dist/src/tracing/local-trace-operations.d.ts +13 -0
  130. package/dist/src/tracing/local-trace-operations.js +1 -0
  131. package/dist/src/tracing/local-trace-query.d.ts +17 -0
  132. package/dist/src/tracing/local-trace-query.js +1 -0
  133. package/dist/src/tracing/local-trace-span-processor.js +1 -1
  134. package/dist/src/tracing/local-trace-summary.d.ts +31 -0
  135. package/dist/src/tracing/local-trace-summary.js +1 -0
  136. package/dist/src/vue/index.js +1 -1
  137. package/dist/src/vue/use-eve-agent.js +1 -1
  138. package/docs/concepts/project-structure.mdx +2 -4
  139. package/docs/concepts/sessions-runs-and-streaming.md +2 -2
  140. package/docs/evals/cases.mdx +1 -0
  141. package/docs/extensions.md +3 -1
  142. package/docs/guides/auth-and-route-protection.md +33 -1
  143. package/docs/guides/client/streaming.mdx +26 -0
  144. package/docs/guides/deployment/vercel.mdx +3 -5
  145. package/docs/guides/frontend/nextjs.mdx +20 -7
  146. package/docs/guides/frontend/overview.mdx +1 -1
  147. package/docs/guides/remote-agents.md +3 -1
  148. package/docs/install-integrations.mdx +1 -1
  149. package/docs/reference/cli.md +1 -1
  150. package/docs/subagents/index.mdx +8 -2
  151. package/package.json +1 -1
  152. package/dist/src/internal/nitro/host/dev-workspace-extensions.d.ts +0 -18
  153. package/dist/src/internal/nitro/host/dev-workspace-extensions.js +0 -1
  154. package/dist/src/tasks/session-task-cohorts.d.ts +0 -7
  155. package/dist/src/tasks/session-task-cohorts.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # eve
2
2
 
3
+ ## 0.66.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 055f1d1: `eve build` and `withEve` during `next build` now build mounted, source-backed workspace extensions before compiling the agent, as `eve dev` already does. Production builds no longer fail when a package manager skips the extension's `prepare` script, such as on a no-op install with a restored `node_modules` cache. An extension whose distribution is already current is not rebuilt, and a failed extension build names the package and the command to run.
8
+ - faacecf: Follow a delegated child's activity from a client with `session.streamSubagent(called, options?)`. Pass a `subagent.called` event from that session. The client reads its `childStreamPath` with the session's host and credentials, so a remote child streams through the parent deployment's proxy route, and the child's cursor stays separate from the parent's. Eval sessions expose the same method with the eval client's credentials.
9
+ - a490d88: `eveChannel({ trustedForwarders })` now receives what the forwarder asserts as a second argument. `assertion.principal` holds the stamped `current` and `initiator` contexts the forwarder asserts, so a receiver can limit a trusted forwarder to the identities it may speak for instead of accepting any principal it asserts.
10
+ - 6e568dc: Allow Web Chat to scaffold as a peer application for standalone agents and agent workspaces, with explicit Next.js or Vercel services hosting. `withEve()` from `eve/next` can discover either project layout from an explicit `eveRoot`, so the peer application does not need to repeat agent paths.
11
+ - d8ddf0d: Add bounded, conversation-scoped trace analysis to self-modification, with filtered search, compact timelines, and batched span payload inspection.
12
+ - d6fc658: Keep a delegated agent task open when its model turn yields while background work started in that turn is still running. Deliver the final result after that work finishes, including usage accumulated across the yielded turns, instead of reporting the interim reply as completion.
13
+
14
+ Propagate task cancellation to a yielded child's nested background work for self, local, and remote delegation, without waking the cancelled child on its nested task notifications. Preserve cancellation across replay and session handoff.
15
+
16
+ Fail an unanswered delegated task when its yielded child session ends, and preserve the unreported usage in that terminal result.
17
+ - 650b309: Use a quieter selected-row treatment and temporary drawer for interactive setup flows in the development TUI. `/add`, `/login`, and `/deploy` now emphasize the focused option with type weight instead of a caret, keep controls below the drawer, and `/login` supports inline connection completion such as `/login openai-api-key`.
18
+ - d6fc658: Keep durable MCP invocations open for pending background subagents so clients receive the delegated result.
19
+
3
20
  ## 0.66.0
4
21
 
5
22
  ### Minor Changes
@@ -17,11 +17,31 @@ export interface ForwardedPrincipal {
17
17
  readonly initiator?: SessionAuthContext;
18
18
  }
19
19
  /**
20
- * Authorizes which transport-authenticated forwarders may assert a forwarded
21
- * principal. Receives the *verified* route-auth principal (who is asserting),
22
- * never the forwarded identity (what is asserted).
20
+ * What a forwarder asks the receiving deployment to adopt, passed to
21
+ * {@link TrustedForwarders} next to the verified forwarder.
23
22
  */
24
- export type TrustedForwarders = (forwarder: SessionAuthContext) => boolean | Promise<boolean>;
23
+ export interface ForwardedAssertion {
24
+ /**
25
+ * The session principals the forwarder asserts, present when it forwards a
26
+ * principal and absent when only remote parent lineage is being trusted.
27
+ * Both contexts are already stamped with {@link FORWARDED_BY_ATTRIBUTE}, and
28
+ * `initiator` is `current` when the sender omitted it. `initiator` takes
29
+ * effect only on session creation: continuation requests install only
30
+ * `current`, so there `initiator` is the asserted value, not the session's
31
+ * pinned initiator.
32
+ */
33
+ readonly principal?: {
34
+ readonly current: SessionAuthContext;
35
+ readonly initiator: SessionAuthContext;
36
+ };
37
+ }
38
+ /**
39
+ * Authorizes a transport-authenticated forwarder to supply eve delegation
40
+ * context. Receives the *verified* route-auth principal (who is asserting) and
41
+ * the principals it asserts, so a receiver can limit each forwarder to the
42
+ * identities it may speak for.
43
+ */
44
+ export type TrustedForwarders = (forwarder: SessionAuthContext, assertion: ForwardedAssertion) => boolean | Promise<boolean>;
25
45
  export type ForwardedPrincipalParseResult = {
26
46
  readonly forwardedPrincipal: ForwardedPrincipal;
27
47
  readonly ok: true;
@@ -48,8 +68,8 @@ export type ResolvedForwardedPrincipal = {
48
68
  * Gates the `forwardedPrincipal` body field and resolves the
49
69
  * effective session principals. Returns the failure `Response` on rejection:
50
70
  * 403 when the channel accepts no forwarded principal or the predicate
51
- * refuses the forwarder, 400 on a malformed payload, 500 when the authored
52
- * predicate throws. Accepted contexts are stamped with
71
+ * refuses the forwarder or what it asserts, 400 on a malformed payload, 500
72
+ * when the authored predicate throws. Accepted contexts are stamped with
53
73
  * {@link FORWARDED_BY_ATTRIBUTE} before they are returned, so a custom
54
74
  * `onMessage` always sees the transport forwarder on the replaced principal.
55
75
  */
@@ -1 +1 @@
1
- import{z}from"#compiled/zod/index.js";import{createLogger,logError}from"#internal/logging.js";const log=createLogger(`channel.forwarded-principal`),FORWARDED_BY_ATTRIBUTE=`eve:forwarded-by`,attributeValueSchema=z.union([z.string(),z.array(z.string()).readonly()]),forwardedPrincipalContextSchema=z.object({attributes:z.record(z.string(),attributeValueSchema).readonly(),authenticator:z.string().min(1),issuer:z.string().min(1).optional(),principalId:z.string().min(1),principalType:z.string().min(1),subject:z.string().min(1).optional()}).strict(),forwardedPrincipalSchema=z.object({current:forwardedPrincipalContextSchema,initiator:forwardedPrincipalContextSchema.optional()}).strict();async function resolveForwardedPrincipal(e){let t=e.payload.forwardedPrincipal;if(t===void 0)return{accepted:!1,auth:e.forwarder};if(e.trustedForwarders===void 0)return Response.json({error:`This deployment does not accept a forwarded principal.`,ok:!1},{status:403});let n=parseForwardedPrincipal(t);if(!n.ok)return Response.json({error:n.message,ok:!1},{status:400});let r;try{r=await e.trustedForwarders(e.forwarder)}catch(t){let n=logError(log,`trustedForwarders handler failed`,t,{forwarder:e.forwarder.principalId});return Response.json({error:`trustedForwarders handler failed.`,errorId:n,ok:!1},{status:500})}if(!r)return Response.json({error:`Caller is not authorized to assert a forwarded principal.`,ok:!1},{status:403});let i=stampForwardedBy(n.forwardedPrincipal.current,e.forwarder.principalId);return{accepted:!0,auth:i,initiatorAuth:n.forwardedPrincipal.initiator===void 0?i:stampForwardedBy(n.forwardedPrincipal.initiator,e.forwarder.principalId)}}function parseForwardedPrincipal(e){let t=forwardedPrincipalSchema.safeParse(e);if(t.success){let e=toSessionAuthContext(t.data.current);return{forwardedPrincipal:t.data.initiator===void 0?{current:e}:{current:e,initiator:toSessionAuthContext(t.data.initiator)},ok:!0}}return{cause:t.error,message:formatForwardedPrincipalParseError(t.error),ok:!1}}function stampForwardedBy(e,t){return{...e,attributes:{...e.attributes,[FORWARDED_BY_ATTRIBUTE]:t}}}function toSessionAuthContext(e){let t={attributes:e.attributes,authenticator:e.authenticator,principalId:e.principalId,principalType:e.principalType};return e.issuer!==void 0&&(t.issuer=e.issuer),e.subject!==void 0&&(t.subject=e.subject),t}function formatForwardedPrincipalParseError(e){return`Invalid forwardedPrincipal metadata: ${e.issues.map(e=>`${e.path.length===0?`forwardedPrincipal`:`forwardedPrincipal.${e.path.join(`.`)}`}: ${e.message}`).join(`; `)}`}export{FORWARDED_BY_ATTRIBUTE,parseForwardedPrincipal,resolveForwardedPrincipal,stampForwardedBy};
1
+ import{z}from"#compiled/zod/index.js";import{createLogger,logError}from"#internal/logging.js";const log=createLogger(`channel.forwarded-principal`),FORWARDED_BY_ATTRIBUTE=`eve:forwarded-by`,attributeValueSchema=z.union([z.string(),z.array(z.string()).readonly()]),forwardedPrincipalContextSchema=z.object({attributes:z.record(z.string(),attributeValueSchema).readonly(),authenticator:z.string().min(1),issuer:z.string().min(1).optional(),principalId:z.string().min(1),principalType:z.string().min(1),subject:z.string().min(1).optional()}).strict(),forwardedPrincipalSchema=z.object({current:forwardedPrincipalContextSchema,initiator:forwardedPrincipalContextSchema.optional()}).strict();async function resolveForwardedPrincipal(e){let t=e.payload.forwardedPrincipal;if(t===void 0)return{accepted:!1,auth:e.forwarder};if(e.trustedForwarders===void 0)return Response.json({error:`This deployment does not accept a forwarded principal.`,ok:!1},{status:403});let n=parseForwardedPrincipal(t);if(!n.ok)return Response.json({error:n.message,ok:!1},{status:400});let r=stampForwardedBy(n.forwardedPrincipal.current,e.forwarder.principalId),i=n.forwardedPrincipal.initiator===void 0?r:stampForwardedBy(n.forwardedPrincipal.initiator,e.forwarder.principalId),a;try{a=await e.trustedForwarders(e.forwarder,{principal:{current:r,initiator:i}})}catch(t){let n=logError(log,`trustedForwarders handler failed`,t,{forwarder:e.forwarder.principalId});return Response.json({error:`trustedForwarders handler failed.`,errorId:n,ok:!1},{status:500})}return a?{accepted:!0,auth:r,initiatorAuth:i}:Response.json({error:`Caller is not authorized to assert a forwarded principal.`,ok:!1},{status:403})}function parseForwardedPrincipal(e){let t=forwardedPrincipalSchema.safeParse(e);if(t.success){let e=toSessionAuthContext(t.data.current);return{forwardedPrincipal:t.data.initiator===void 0?{current:e}:{current:e,initiator:toSessionAuthContext(t.data.initiator)},ok:!0}}return{cause:t.error,message:formatForwardedPrincipalParseError(t.error),ok:!1}}function stampForwardedBy(e,t){return{...e,attributes:{...e.attributes,[FORWARDED_BY_ATTRIBUTE]:t}}}function toSessionAuthContext(e){let t={attributes:e.attributes,authenticator:e.authenticator,principalId:e.principalId,principalType:e.principalType};return e.issuer!==void 0&&(t.issuer=e.issuer),e.subject!==void 0&&(t.subject=e.subject),t}function formatForwardedPrincipalParseError(e){return`Invalid forwardedPrincipal metadata: ${e.issues.map(e=>`${e.path.length===0?`forwardedPrincipal`:`forwardedPrincipal.${e.path.join(`.`)}`}: ${e.message}`).join(`; `)}`}export{FORWARDED_BY_ATTRIBUTE,parseForwardedPrincipal,resolveForwardedPrincipal,stampForwardedBy};
@@ -546,6 +546,8 @@ var ClientError = class extends Error {
546
546
  body;
547
547
  headers;
548
548
  constructor(status, body, headers) {
549
+ const normalizedHeaders = Object.freeze(Object.fromEntries(new Headers(headers).entries()));
550
+ const contentType = normalizedHeaders["content-type"]?.toLowerCase();
549
551
  let message = body || `Server returned ${status}.`;
550
552
  let code;
551
553
  try {
@@ -554,13 +556,15 @@ var ClientError = class extends Error {
554
556
  if (typeof parsed.error === "string") message = parsed.error;
555
557
  if (typeof parsed.code === "string") code = parsed.code;
556
558
  }
557
- } catch {}
559
+ } catch {
560
+ if (contentType?.includes("text/html")) message = `Server returned ${status} with an HTML response. Check the eve route and development server configuration.`;
561
+ }
558
562
  super(message);
559
563
  this.name = "ClientError";
560
564
  this.code = code;
561
565
  this.status = status;
562
566
  this.body = body;
563
- this.headers = Object.freeze(Object.fromEntries(new Headers(headers).entries()));
567
+ this.headers = normalizedHeaders;
564
568
  }
565
569
  };
566
570
 
@@ -1184,7 +1188,7 @@ async function openStreamBody(input) {
1184
1188
  if (input.requestTailIndex === true) searchParams.includeTailIndex = "1";
1185
1189
  for (let attempt = 0; attempt < openRetryPolicy.maxAttempts; attempt += 1) {
1186
1190
  input.signal?.throwIfAborted();
1187
- const url = createClientUrl(input.host, createEveSessionStreamRoutePath(input.sessionId), Object.keys(searchParams).length > 0 ? searchParams : void 0);
1191
+ const url = createClientUrl(input.host, input.path, Object.keys(searchParams).length > 0 ? searchParams : void 0);
1188
1192
  const headers = await input.resolveHeaders();
1189
1193
  input.signal?.throwIfAborted();
1190
1194
  const connectionController = new AbortController();
@@ -1809,6 +1813,22 @@ var ClientSession = class ClientSession {
1809
1813
  if (options?.follow === false && (options.startIndex ?? this.#state.streamIndex) < 0) throw new Error("stream({ follow: false }) requires a nonnegative startIndex; a tail-relative cursor cannot be bounded.");
1810
1814
  return this.#streamAndAdvance(options);
1811
1815
  }
1816
+ streamSubagent(called, options) {
1817
+ if (called.data.sessionId !== this.#state.sessionId) throw new Error(`streamSubagent() requires a subagent.called event from session ${this.#state.sessionId}, but it came from session ${called.data.sessionId}.`);
1818
+ if (typeof called.data.childStreamPath !== "string") throw new Error(`streamSubagent() requires a subagent.called event with childStreamPath, but call ${called.data.callId} has none. The event was recorded by an older eve version.`);
1819
+ const startIndex = options?.startIndex ?? 0;
1820
+ if (options?.follow === false && startIndex < 0) throw new Error("streamSubagent({ follow: false }) requires a nonnegative startIndex; a tail-relative cursor cannot be bounded.");
1821
+ return followStreamIterable({
1822
+ follow: options?.follow,
1823
+ host: this.#context.host,
1824
+ path: called.data.childStreamPath,
1825
+ redirect: this.#context.redirect,
1826
+ resolveHeaders: () => this.#context.resolveHeaders(),
1827
+ signal: options?.signal,
1828
+ startIndex,
1829
+ streamReconnectPolicy: options?.streamReconnectPolicy
1830
+ });
1831
+ }
1812
1832
  [followSession](options) {
1813
1833
  return this.#streamAndAdvance({
1814
1834
  ...options,
@@ -1888,8 +1908,8 @@ var ClientSession = class ClientSession {
1888
1908
  host: this.#context.host,
1889
1909
  keepAlive: input.keepAlive,
1890
1910
  resolveHeaders: () => this.#context.resolveHeaders(input.resolveHeaders?.() ?? input.headers),
1911
+ path: createEveSessionStreamRoutePath(this.#state.sessionId),
1891
1912
  redirect: this.#context.redirect,
1892
- sessionId: this.#state.sessionId,
1893
1913
  signal: input.signal,
1894
1914
  startIndex: input.startIndex,
1895
1915
  streamReconnectPolicy: input.streamReconnectPolicy,
@@ -547,6 +547,8 @@ var ClientError = class extends Error {
547
547
  body;
548
548
  headers;
549
549
  constructor(status, body, headers) {
550
+ const normalizedHeaders = Object.freeze(Object.fromEntries(new Headers(headers).entries()));
551
+ const contentType = normalizedHeaders["content-type"]?.toLowerCase();
550
552
  let message = body || `Server returned ${status}.`;
551
553
  let code;
552
554
  try {
@@ -555,13 +557,15 @@ var ClientError = class extends Error {
555
557
  if (typeof parsed.error === "string") message = parsed.error;
556
558
  if (typeof parsed.code === "string") code = parsed.code;
557
559
  }
558
- } catch {}
560
+ } catch {
561
+ if (contentType?.includes("text/html")) message = `Server returned ${status} with an HTML response. Check the eve route and development server configuration.`;
562
+ }
559
563
  super(message);
560
564
  this.name = "ClientError";
561
565
  this.code = code;
562
566
  this.status = status;
563
567
  this.body = body;
564
- this.headers = Object.freeze(Object.fromEntries(new Headers(headers).entries()));
568
+ this.headers = normalizedHeaders;
565
569
  }
566
570
  };
567
571
 
@@ -1185,7 +1189,7 @@ async function openStreamBody(input) {
1185
1189
  if (input.requestTailIndex === true) searchParams.includeTailIndex = "1";
1186
1190
  for (let attempt = 0; attempt < openRetryPolicy.maxAttempts; attempt += 1) {
1187
1191
  input.signal?.throwIfAborted();
1188
- const url = createClientUrl(input.host, createEveSessionStreamRoutePath(input.sessionId), Object.keys(searchParams).length > 0 ? searchParams : void 0);
1192
+ const url = createClientUrl(input.host, input.path, Object.keys(searchParams).length > 0 ? searchParams : void 0);
1189
1193
  const headers = await input.resolveHeaders();
1190
1194
  input.signal?.throwIfAborted();
1191
1195
  const connectionController = new AbortController();
@@ -1810,6 +1814,22 @@ var ClientSession = class ClientSession {
1810
1814
  if (options?.follow === false && (options.startIndex ?? this.#state.streamIndex) < 0) throw new Error("stream({ follow: false }) requires a nonnegative startIndex; a tail-relative cursor cannot be bounded.");
1811
1815
  return this.#streamAndAdvance(options);
1812
1816
  }
1817
+ streamSubagent(called, options) {
1818
+ if (called.data.sessionId !== this.#state.sessionId) throw new Error(`streamSubagent() requires a subagent.called event from session ${this.#state.sessionId}, but it came from session ${called.data.sessionId}.`);
1819
+ if (typeof called.data.childStreamPath !== "string") throw new Error(`streamSubagent() requires a subagent.called event with childStreamPath, but call ${called.data.callId} has none. The event was recorded by an older eve version.`);
1820
+ const startIndex = options?.startIndex ?? 0;
1821
+ if (options?.follow === false && startIndex < 0) throw new Error("streamSubagent({ follow: false }) requires a nonnegative startIndex; a tail-relative cursor cannot be bounded.");
1822
+ return followStreamIterable({
1823
+ follow: options?.follow,
1824
+ host: this.#context.host,
1825
+ path: called.data.childStreamPath,
1826
+ redirect: this.#context.redirect,
1827
+ resolveHeaders: () => this.#context.resolveHeaders(),
1828
+ signal: options?.signal,
1829
+ startIndex,
1830
+ streamReconnectPolicy: options?.streamReconnectPolicy
1831
+ });
1832
+ }
1813
1833
  [followSession](options) {
1814
1834
  return this.#streamAndAdvance({
1815
1835
  ...options,
@@ -1889,8 +1909,8 @@ var ClientSession = class ClientSession {
1889
1909
  host: this.#context.host,
1890
1910
  keepAlive: input.keepAlive,
1891
1911
  resolveHeaders: () => this.#context.resolveHeaders(input.resolveHeaders?.() ?? input.headers),
1912
+ path: createEveSessionStreamRoutePath(this.#state.sessionId),
1892
1913
  redirect: this.#context.redirect,
1893
- sessionId: this.#state.sessionId,
1894
1914
  signal: input.signal,
1895
1915
  startIndex: input.startIndex,
1896
1916
  streamReconnectPolicy: input.streamReconnectPolicy,
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import pc from"#compiled/picocolors/index.js";import{createCliTheme,renderCliTaggedLine}from"#cli/ui/output.js";import{buildExtensionPackage,tryReadExtensionBuildConfig}from"#internal/nitro/host/build-extension.js";const buildLog=createLogger(`extension-build`);async function runExtensionBuildCommand(e,t){let n=await tryReadExtensionBuildConfig(t);if(n===null)throw Error('This package is not an eve extension. Add `"eve": { "extension": { "source": "./extension", "dist": "./dist/extension" } }` to package.json, or run `eve build` for an agent app.');buildLog.debug(`building extension package`,{packageName:n.packageName,sourceRoot:n.sourceRoot});let r=await buildExtensionPackage(t,n),i=createCliTheme();e.log(renderCliTaggedLine(i,{message:`built extension ${pc.bold(n.packageName)} at ${r}`,tag:`build`,tone:`success`}))}export{runExtensionBuildCommand};
1
+ import{createLogger}from"#internal/logging.js";import pc from"#compiled/picocolors/index.js";import{createCliTheme,renderCliTaggedLine}from"#cli/ui/output.js";import{buildExtensionPackage,tryReadExtensionBuildConfig}from"#internal/nitro/host/build-extension.js";import{withExtensionBuildLock}from"#internal/nitro/host/extension-build-lock.js";const buildLog=createLogger(`extension-build`);async function runExtensionBuildCommand(e,t){let n=await tryReadExtensionBuildConfig(t);if(n===null)throw Error('This package is not an eve extension. Add `"eve": { "extension": { "source": "./extension", "dist": "./dist/extension" } }` to package.json, or run `eve build` for an agent app.');buildLog.debug(`building extension package`,{packageName:n.packageName,sourceRoot:n.sourceRoot});let r=await withExtensionBuildLock(t,async()=>await buildExtensionPackage(t,n)),i=createCliTheme();e.log(renderCliTaggedLine(i,{message:`built extension ${pc.bold(n.packageName)} at ${r}`,tag:`build`,tone:`success`}))}export{runExtensionBuildCommand};
@@ -4,7 +4,8 @@ export interface AddRegistryMappingsResult {
4
4
  skippedBuiltIn: string[];
5
5
  skippedExisting: string[];
6
6
  }
7
- export declare function assertCanInstallWebChat(appRoot: string): Promise<void>;
7
+ /** Resolves and prepares the root package that owns Web Chat. */
8
+ export declare function prepareWebChatProjectRoot(appRoot: string): Promise<string>;
8
9
  /** Reads registry namespace mappings from package.json. */
9
10
  export declare function readRegistryConfig(appRoot: string): Promise<RegistryConfig>;
10
11
  export declare function addWebRegistryTsconfig(source: string, path: string): string;
@@ -1,2 +1,2 @@
1
- import{readFile,writeFile}from"node:fs/promises";import{join}from"node:path";import{resolveEveProjectContext}from"#internal/project-context.js";import{applyEdits,modify,parse}from"#compiled/jsonc-parser/index.js";import{WEB_APP_TEMPLATE_FILES}from"#setup/scaffold/create/web-template.js";function errorMessage(e){return e instanceof Error?e.message:String(e)}function isRegistrySource(e){return typeof e==`string`?!0:typeof e!=`object`||!e||!(`url`in e)?!1:typeof e.url==`string`}function parseRegistries(e,t){if(t===void 0)return{};if(typeof t!=`object`||!t||Array.isArray(t))throw Error(`${e} has an invalid registries field.`);let n={};for(let[r,i]of Object.entries(t)){if(!r.startsWith(`@`)||!isRegistrySource(i))throw Error(`${e} has an invalid registry entry for ${r}.`);n[r]=i}return n}async function readRegistryPackage(e){let t=await resolveEveProjectContext(e),n=join(t.environmentRoot,`package.json`),r;try{r=JSON.parse(await readFile(n,`utf8`))}catch(e){throw Error(`Could not read ${n}: ${errorMessage(e)}`)}if(typeof r!=`object`||!r||Array.isArray(r))throw Error(`${n} must contain a JSON object.`);let i=r;return{path:n,document:i,config:{registries:parseRegistries(n,i.registries)}}}function parseRegistryMapping(e){let t=e.indexOf(`=`),n=t===-1?e:e.slice(0,t),r=t===-1?``:e.slice(t+1);if(!n.startsWith(`@`))throw Error(`Registry namespaces must start with @: ${n}`);if(!r.includes(`{name}`))throw Error(`Pass a registry URL containing {name}, for example ${n}=https://example.com/r/{name}.json.`);return{namespace:n,url:r}}async function assertCanInstallWebChat(e){if((await resolveEveProjectContext(e)).kind!==`standalone`)throw Error(`Web Chat installs a project-level Next.js application and cannot currently be added to a top-level agents/ workspace. Configure a root Next.js app with withEve({ agents }) instead.`)}async function readRegistryConfig(e){return(await readRegistryPackage(e)).config}const JSONC_FORMATTING={insertSpaces:!0,tabSize:2,eol:`
2
- `};function setJsoncValue(e,t,n){return applyEdits(e,modify(e,t,n,{formattingOptions:JSONC_FORMATTING}))}function addWebRegistryTsconfig(e,t){let n=[],r=parse(e,n,{allowTrailingComma:!0});if(n.length>0||typeof r!=`object`||!r||Array.isArray(r))throw Error(`Could not add Web Chat because ${t} is not a valid JSON object.`);let i=r,a=JSON.parse(WEB_APP_TEMPLATE_FILES[`tsconfig.json`]),o=i.compilerOptions?.paths?.[`@/*`];if(o!==void 0&&(!Array.isArray(o)||!o.includes(`./*`)))throw Error(`Could not add Web Chat because ${t} already defines @/* without mapping it to ./*.`);let s=e;for(let[e,t]of Object.entries(a.compilerOptions))e!==`paths`&&e!==`plugins`&&i.compilerOptions?.[e]===void 0&&(s=setJsoncValue(s,[`compilerOptions`,e],t));o===void 0&&(s=setJsoncValue(s,[`compilerOptions`,`paths`,`@/*`],[`./*`]));let c=i.compilerOptions?.plugins??[];return c.some(e=>typeof e==`object`&&!!e&&`name`in e&&e.name===`next`)||(s=setJsoncValue(s,[`compilerOptions`,`plugins`],[...c,{name:`next`}])),s=setJsoncValue(s,[`include`],[...new Set([...i.include??[],...a.include])]),s=setJsoncValue(s,[`exclude`],[...new Set([...i.exclude??[],...a.exclude])]),s}async function prepareWebRegistryProject(e){let t=join(e,`tsconfig.json`),n;try{n=await readFile(t,`utf8`)}catch(e){throw Error(`Could not add Web Chat because ${t} could not be read: ${errorMessage(e)}`)}let r=addWebRegistryTsconfig(n,t);r!==n&&await writeFile(t,r,`utf8`)}async function addRegistryMappings(e,t){if(t.length===0)throw Error(`Pass at least one registry to add.`);let n=await readRegistryPackage(e),r=t.map(parseRegistryMapping),i={...n.config.registries},a={added:[],skippedBuiltIn:[],skippedExisting:[]};for(let e of r)e.namespace===`@shadcn`||e.namespace===`@skills`?a.skippedBuiltIn.push(e.namespace):i[e.namespace]===void 0?(i[e.namespace]=e.url,a.added.push(e.namespace)):a.skippedExisting.push(e.namespace);return a.added.length>0&&await writeFile(n.path,`${JSON.stringify({...n.document,registries:i},null,2)}\n`,`utf8`),a}export{addRegistryMappings,addWebRegistryTsconfig,assertCanInstallWebChat,prepareWebRegistryProject,readRegistryConfig};
1
+ import{readFile,writeFile}from"node:fs/promises";import{join}from"node:path";import{resolveEveProjectContext}from"#internal/project-context.js";import{applyEdits,modify,parse}from"#compiled/jsonc-parser/index.js";import{WEB_APP_TEMPLATE_FILES}from"#setup/scaffold/create/web-template.js";function errorMessage(e){return e instanceof Error?e.message:String(e)}function isRegistrySource(e){return typeof e==`string`?!0:typeof e!=`object`||!e||!(`url`in e)?!1:typeof e.url==`string`}function parseRegistries(e,t){if(t===void 0)return{};if(typeof t!=`object`||!t||Array.isArray(t))throw Error(`${e} has an invalid registries field.`);let n={};for(let[r,i]of Object.entries(t)){if(!r.startsWith(`@`)||!isRegistrySource(i))throw Error(`${e} has an invalid registry entry for ${r}.`);n[r]=i}return n}async function readRegistryPackage(e){let t=await resolveEveProjectContext(e),n=join(t.environmentRoot,`package.json`),r;try{r=JSON.parse(await readFile(n,`utf8`))}catch(e){throw Error(`Could not read ${n}: ${errorMessage(e)}`)}if(typeof r!=`object`||!r||Array.isArray(r))throw Error(`${n} must contain a JSON object.`);let i=r;return{path:n,document:i,config:{registries:parseRegistries(n,i.registries)}}}function parseRegistryMapping(e){let t=e.indexOf(`=`),n=t===-1?e:e.slice(0,t),r=t===-1?``:e.slice(t+1);if(!n.startsWith(`@`))throw Error(`Registry namespaces must start with @: ${n}`);if(!r.includes(`{name}`))throw Error(`Pass a registry URL containing {name}, for example ${n}=https://example.com/r/{name}.json.`);return{namespace:n,url:r}}async function prepareWebChatProjectRoot(e){let t=await resolveEveProjectContext(e);if(t.kind===`workspace`)throw Error(`Web Chat setup requires a selected workspace agent.`);let n=t.environmentRoot,r=join(n,`package.json`),i=await readFile(r,`utf8`),a=JSON.parse(i),o={...a.scripts};return o[`dev:web`]??=`next dev apps/web`,o[`build:web`]??=`next build apps/web`,await writeFile(r,`${JSON.stringify({...a,scripts:o},null,2)}\n`,`utf8`),n}async function readRegistryConfig(e){return(await readRegistryPackage(e)).config}const JSONC_FORMATTING={insertSpaces:!0,tabSize:2,eol:`
2
+ `};function setJsoncValue(e,t,n){return applyEdits(e,modify(e,t,n,{formattingOptions:JSONC_FORMATTING}))}function addWebRegistryTsconfig(e,t){let n=[],r=parse(e,n,{allowTrailingComma:!0});if(n.length>0||typeof r!=`object`||!r||Array.isArray(r))throw Error(`Could not add Web Chat because ${t} is not a valid JSON object.`);let i=r,a=JSON.parse(WEB_APP_TEMPLATE_FILES[`tsconfig.json`]),o=i.compilerOptions?.paths?.[`@/*`];if(o!==void 0&&(!Array.isArray(o)||!o.includes(`./*`)))throw Error(`Could not add Web Chat because ${t} already defines @/* without mapping it to ./*.`);let s=e;for(let[e,t]of Object.entries(a.compilerOptions))e!==`paths`&&e!==`plugins`&&i.compilerOptions?.[e]===void 0&&(s=setJsoncValue(s,[`compilerOptions`,e],t));o===void 0&&(s=setJsoncValue(s,[`compilerOptions`,`paths`,`@/*`],[`./*`]));let c=i.compilerOptions?.plugins??[];return c.some(e=>typeof e==`object`&&!!e&&`name`in e&&e.name===`next`)||(s=setJsoncValue(s,[`compilerOptions`,`plugins`],[...c,{name:`next`}])),s=setJsoncValue(s,[`include`],[...new Set([...i.include??[],...a.include])]),s=setJsoncValue(s,[`exclude`],[...new Set([...i.exclude??[],...a.exclude])]),s}async function prepareWebRegistryProject(e){let t=join(e,`apps`,`web`,`tsconfig.json`),n;try{n=await readFile(t,`utf8`)}catch(e){if(e.code===`ENOENT`)return;throw Error(`Could not add Web Chat because ${t} could not be read: ${errorMessage(e)}`)}let r=addWebRegistryTsconfig(n,t);r!==n&&await writeFile(t,r,`utf8`)}async function addRegistryMappings(e,t){if(t.length===0)throw Error(`Pass at least one registry to add.`);let n=await readRegistryPackage(e),r=t.map(parseRegistryMapping),i={...n.config.registries},a={added:[],skippedBuiltIn:[],skippedExisting:[]};for(let e of r)e.namespace===`@shadcn`||e.namespace===`@skills`?a.skippedBuiltIn.push(e.namespace):i[e.namespace]===void 0?(i[e.namespace]=e.url,a.added.push(e.namespace)):a.skippedExisting.push(e.namespace);return a.added.length>0&&await writeFile(n.path,`${JSON.stringify({...n.document,registries:i},null,2)}\n`,`utf8`),a}export{addRegistryMappings,addWebRegistryTsconfig,prepareWebChatProjectRoot,prepareWebRegistryProject,readRegistryConfig};
@@ -1 +1 @@
1
- import{hasInteractiveTerminal}from"./preconditions.js";import{serializeHeadlessSetupEvent}from"./setup-headless.js";import{assertCanInstallWebChat,prepareWebRegistryProject,readRegistryConfig}from"./registry-project.js";import{errorMessage,reportRegistryCompletion,resolveRegistryItemForAdd,runRegistryAction,setupReminder,setupResumeCommand}from"./registry-recovery.js";import{runRegistryAddCommand}from"./registry-add-command.js";import{runDeclaredSetups}from"./registry-declared-setups.js";import{installRegistryItemTransaction}from"./registry-install-transaction.js";import{eveMetadataFromRegistryItem,parseOfficialRegistrySearchMetadata}from"./registry-metadata.js";import{prepareDeclaredPnpmBuildPolicy}from"./registry-pnpm-build-policy-flow.js";import{printRegistrySearchResults,registryViewText}from"./registry-presentation.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{createPrompter}from"#setup/prompter.js";import{WizardCancelledError}from"#setup/step.js";import{addRegistryItems,getRegistryItems,searchRegistries}from"#compiled/shadcn-registry/index.js";import semver from"#compiled/semver/index.js";const defaultAddCommandDependencies={createPrompter,hasInteractiveTerminal,loadSetupCommandRunner:async()=>(await import(`./registry-setup-command.js`)).runRegistrySetupCommand,prepareWebRegistryProject};function resolveOfficialRegistryUrl(e=process.env.EVE_DEV_OFFICIAL_REGISTRY_URL){if(e===void 0)return`https://eve.dev/r`;let t;try{t=new URL(e)}catch{throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must be an HTTP(S) URL.`)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must be an HTTP(S) URL.`);if(t.username!==``||t.password!==``)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must not include credentials.`);if(t.search!==``||t.hash!==``)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must not include a query or fragment.`);return t.pathname=t.pathname.replace(/\/+$/,``),t.toString().replace(/\/$/,``)}const OFFICIAL_REGISTRY=resolveOfficialRegistryUrl(),OFFICIAL_CATALOG=`${OFFICIAL_REGISTRY}/registry.json`,SKILLS_REGISTRY=`@skills`;function itemAddress(e){return e.startsWith(`@`)||/^https?:\/\//.test(e)?e:`${OFFICIAL_REGISTRY}/${e}.json`}async function installOfficialRegistryItem(e,t,n={}){let r=await readEveRegistryConfig(e);await addRegistryItems([itemAddress(t)],{config:r,cwd:e,overwrite:n.overwrite})}function assertCompatibleEveVersion(e){if(e===void 0)return;let t=resolveInstalledPackageInfo().version;if(semver.validRange(e)===null)throw Error(`Registry item has an invalid eve version requirement: ${e}.`);if(!semver.subset(t,e))throw Error(`This registry item requires eve ${e}, but this project is using eve ${t}. Upgrade eve and run the command again.`)}function isOfficialItemAddress(e){return e.startsWith(`${OFFICIAL_REGISTRY}/`)}function withBuiltInRegistries(e){return{...e,registries:{[SKILLS_REGISTRY]:`https://www.skills.sh/r/{name}?agent=eve`,...e.registries}}}async function readEveRegistryConfig(e){return withBuiltInRegistries(await readRegistryConfig(e))}function configuredRegistrySources(e){return Object.keys(e.registries??{})}function validateRegistrySource(e){if(e!==void 0&&!e.startsWith(`@`)&&!/^https?:\/\//.test(e))throw Error(`Registry sources must be a namespace or URL: ${e}`)}async function loadOfficialSearchMetadata(){let e=await fetch(OFFICIAL_CATALOG);if(!e.ok)throw Error(`Could not read the eve registry (${e.status}).`);return parseOfficialRegistrySearchMetadata(await e.json())}function searchItemAddress(e){return e.registry===OFFICIAL_CATALOG?e.name:e.addCommandArgument}function enrichSearchItem(e,t){let n=searchItemAddress(e);return{item:e,address:n,...t.get(n)}}function registrySourceLabel(e){return e===OFFICIAL_CATALOG?`eve`:e===SKILLS_REGISTRY?`skills.sh`:e}function searchPresentationSections(e,t,n){return e.flatMap(e=>{let r=t.get(e);return r===void 0?[]:[{label:registrySourceLabel(e),items:r.items.map(e=>enrichSearchItem(e,n)),total:r.pagination.total}]})}async function printAddSuggestions(e,t,n){try{let r=n.split(`/`).at(-1)||n,{resultsBySource:i,sources:a,metadataByAddress:o}=await searchRegistryCatalog(t,{limit:5,query:r}),s=searchPresentationSections(a,i,o);if(s.every(e=>e.items.length===0))return;e.log(`Did you mean?`),printRegistrySearchResults(e,{query:r,sections:s})}catch{}}async function searchRegistryCatalog(e,t){validateRegistrySource(t.source);let n=await readEveRegistryConfig(e),r=t.source?[t.source]:[OFFICIAL_CATALOG,...configuredRegistrySources(n).filter(e=>t.query!==void 0||e!==SKILLS_REGISTRY)],i=await Promise.all(r.map(async e=>{try{return{result:await searchRegistries([e],{config:n,limit:t.limit??100,query:t.query}),source:e}}catch(t){return{error:t,source:e}}})),a=[],o=new Map;for(let e of i)if(`error`in e)a.push({message:errorMessage(e.error),registry:e.source});else{let t=e.result.errors??[];if(a.push(...t),t.length===0){let t=e.result.items.filter(t=>t.registry===e.source);o.set(e.source,{...e.result,items:t,pagination:{...e.result.pagination,total:e.result.items.length===t.length?e.result.pagination.total:0}})}}let s=new Map(a.map(e=>[`${e.registry}\0${e.message}`,e])),c=o.has(OFFICIAL_CATALOG)?await loadOfficialSearchMetadata():new Map,l=o.get(OFFICIAL_CATALOG);if(l!==void 0){let e=l.items.filter(e=>c.get(searchItemAddress(e))?.hidden!==!0);l.items=e,l.pagination={...l.pagination,total:e.length},l.items.sort((e,t)=>{let rank=e=>c.get(searchItemAddress(e))?.implementation===`native`?0:1;return rank(e)-rank(t)})}let u=[...o.values()];return{config:n,result:{items:u.flatMap(e=>e.items),pagination:{hasMore:u.some(e=>e.pagination.hasMore),limit:t.limit??100,offset:0,total:u.reduce((e,t)=>e+t.pagination.total,0)},...s.size>0?{errors:[...s.values()]}:{}},resultsBySource:o,sources:r,metadataByAddress:c}}async function browseRegistryCatalog(e,t={}){let{result:n}=await searchRegistryCatalog(e,t);return{items:n.items.map(e=>{let t={address:e.registry===OFFICIAL_CATALOG?e.name:e.addCommandArgument,name:e.name,source:e.registry===OFFICIAL_CATALOG?`Vercel`:e.registry};return e.title!==void 0&&(t.title=e.title),e.type!==void 0&&(t.type=e.type),e.description!==void 0&&(t.description=e.description),t}),total:n.pagination.total,errors:n.errors??[]}}async function browseRegistryItems(e,t,n,r,i={}){let{result:a,resultsBySource:o,sources:s,metadataByAddress:c}=await searchRegistryCatalog(t,{limit:i.limit,query:n,source:r}),l=a.errors??[];if(i.json||o.size>0){let t=a.items.map(e=>({...e,...c.get(searchItemAddress(e))})),r={query:n,sections:searchPresentationSections(s,o,c)};i.json&&(r.json={...a,items:t}),printRegistrySearchResults(e,r)}for(let t of l)e.error(`${t.registry}: ${t.message}`);l.length>0&&(process.exitCode=1)}async function getRegistryItemManifest(e,t){let n=await readEveRegistryConfig(e),r=await getRegistryItems([itemAddress(t)],{config:n});return r.length===1?r[0]:r}async function installRegistryItem(e,t,n={},r=defaultAddCommandDependencies){let i,a=[],o={error:e=>{i=e},log:e=>a.push(e)},s=process.exitCode,c=await runAddCommand(o,e,t,{...n,yes:n.prompter===void 0||n.yes,setupAuthorized:n.prompter!==void 0},r);if(process.exitCode=s,i!==void 0)throw Error(i);if(c===!1)throw new WizardCancelledError;let l={output:a};return c!==void 0&&(l.setup=c),l}async function runAddCommand(e,t,n,r,i=defaultAddCommandDependencies){return runRegistryAction(e,t,async()=>{let a=itemAddress(n);a===itemAddress(`channel/web`)&&await assertCanInstallWebChat(t);let o=await readEveRegistryConfig(t);if(r.skipInstall===!0){if(r.overwrite===!0)throw Error(`--overwrite cannot be used with --skip-install.`);if(r.skipSetup===!0)throw Error(`--skip-install cannot be used with --skip-setup.`);if(!isOfficialItemAddress(a))throw Error(`Setup flows are currently supported only for official eve registry items.`)}let s=await resolveRegistryItemForAdd(e,async()=>(await getRegistryItems([a],{config:o}))[0],()=>printAddSuggestions(e,t,n));if(!s.found)return;let c=s.item,l=isOfficialItemAddress(a)?eveMetadataFromRegistryItem(c):void 0;if(assertCompatibleEveVersion(l?.requires),r.skipInstall===!0){if(l?.setup===void 0)throw Error(`Registry item "${n}" does not declare a setup flow.`);let a=await runDeclaredSetups({logger:e,appRoot:t,item:n,setups:l.setup,options:r,dependencies:i,cancelledReminder:setupReminder(n,`cancelled`),resumeCommand:setupResumeCommand(n)});return reportRegistryCompletion(e,n,a,r)}if(!await prepareDeclaredPnpmBuildPolicy({logger:e,appRoot:t,item:n,policies:l?.install?.pnpm?.buildScripts,options:r}))return!1;if(a===itemAddress(`channel/web`)&&await(i.prepareWebRegistryProject??prepareWebRegistryProject)(t),await installRegistryItemTransaction({appRoot:t,item:n,registryItem:c,nonInteractive:r.nonInteractive,logger:e,install:async()=>{await addRegistryItems([a],{config:o,cwd:t,overwrite:r.overwrite,silent:r.silent})}}),l?.setup===void 0)return reportRegistryCompletion(e,n,{facts:[]},r);let u=i.hasInteractiveTerminal?.()??defaultAddCommandDependencies.hasInteractiveTerminal();if(r.nonInteractive&&e.log(serializeHeadlessSetupEvent({version:1,type:`progress`,message:r.skipInstall?`Setup ${n}`:`Installed ${n}`})),r.skipSetup===!0){if(r.nonInteractive)return reportRegistryCompletion(e,n,{facts:[]},r);e.log(setupReminder(n,`skipped`));return}if(!r.nonInteractive&&!r.yes&&!u&&r.setupAuthorized!==!0){e.log(setupReminder(n,`skipped`));return}if(!r.nonInteractive&&!r.yes&&r.setupAuthorized!==!0)try{if(await(r.prompter??i.createPrompter?.()??defaultAddCommandDependencies.createPrompter()).select({message:`Set up ${n} now?`,initialValue:`yes`,options:[{value:`yes`,label:`Yes`},{value:`no`,label:`No`}]})===`no`){e.log(setupReminder(n,`skipped`));return}}catch(t){if(!(t instanceof WizardCancelledError))throw t;e.log(setupReminder(n,`cancelled`));return}let d=await runDeclaredSetups({logger:e,appRoot:t,item:n,setups:l.setup,options:{...r,force:r.overwrite},dependencies:i,cancelledReminder:setupReminder(n,`cancelled`),resumeCommand:setupResumeCommand(n)});return reportRegistryCompletion(e,n,d,r)})}async function runRegistryListCommand(e,t,n,r={}){await runRegistryAction(e,t,()=>browseRegistryItems(e,t,void 0,n,r))}async function runRegistrySearchCommand(e,t,n,r,i={}){await runRegistryAction(e,t,()=>browseRegistryItems(e,t,n,r,{...i,limit:i.limit??10}))}async function runRegistryViewCommand(e,t,n,r={}){await runRegistryAction(e,t,async()=>{let i=await readEveRegistryConfig(t),a=await getRegistryItems([itemAddress(n)],{config:i}),o=a.length===1?a[0]:a;e.log(r.json?JSON.stringify(o,null,2):registryViewText(n,o))})}export{browseRegistryCatalog,getRegistryItemManifest,installOfficialRegistryItem,installRegistryItem,resolveOfficialRegistryUrl,runAddCommand,runRegistryAddCommand,runRegistryListCommand,runRegistrySearchCommand,runRegistryViewCommand};
1
+ import{hasInteractiveTerminal}from"./preconditions.js";import{serializeHeadlessSetupEvent}from"./setup-headless.js";import{prepareWebChatProjectRoot,prepareWebRegistryProject,readRegistryConfig}from"./registry-project.js";import{errorMessage,reportRegistryCompletion,resolveRegistryItemForAdd,runRegistryAction,setupReminder,setupResumeCommand}from"./registry-recovery.js";import{runRegistryAddCommand}from"./registry-add-command.js";import{runDeclaredSetups}from"./registry-declared-setups.js";import{installRegistryItemTransaction}from"./registry-install-transaction.js";import{eveMetadataFromRegistryItem,parseOfficialRegistrySearchMetadata}from"./registry-metadata.js";import{prepareDeclaredPnpmBuildPolicy}from"./registry-pnpm-build-policy-flow.js";import{printRegistrySearchResults,registryViewText}from"./registry-presentation.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{createPrompter}from"#setup/prompter.js";import{WizardCancelledError}from"#setup/step.js";import{addRegistryItems,getRegistryItems,searchRegistries}from"#compiled/shadcn-registry/index.js";import semver from"#compiled/semver/index.js";const defaultAddCommandDependencies={createPrompter,hasInteractiveTerminal,loadSetupCommandRunner:async()=>(await import(`./registry-setup-command.js`)).runRegistrySetupCommand,prepareWebRegistryProject};function resolveOfficialRegistryUrl(e=process.env.EVE_DEV_OFFICIAL_REGISTRY_URL){if(e===void 0)return`https://eve.dev/r`;let t;try{t=new URL(e)}catch{throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must be an HTTP(S) URL.`)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must be an HTTP(S) URL.`);if(t.username!==``||t.password!==``)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must not include credentials.`);if(t.search!==``||t.hash!==``)throw Error(`EVE_DEV_OFFICIAL_REGISTRY_URL must not include a query or fragment.`);return t.pathname=t.pathname.replace(/\/+$/,``),t.toString().replace(/\/$/,``)}const OFFICIAL_REGISTRY=resolveOfficialRegistryUrl(),OFFICIAL_CATALOG=`${OFFICIAL_REGISTRY}/registry.json`,SKILLS_REGISTRY=`@skills`;function itemAddress(e){return e.startsWith(`@`)||/^https?:\/\//.test(e)?e:`${OFFICIAL_REGISTRY}/${e}.json`}async function installOfficialRegistryItem(e,t,n={}){let r=await readEveRegistryConfig(e);await addRegistryItems([itemAddress(t)],{config:r,cwd:e,overwrite:n.overwrite})}function assertCompatibleEveVersion(e){if(e===void 0)return;let t=resolveInstalledPackageInfo().version;if(semver.validRange(e)===null)throw Error(`Registry item has an invalid eve version requirement: ${e}.`);if(!semver.subset(t,e))throw Error(`This registry item requires eve ${e}, but this project is using eve ${t}. Upgrade eve and run the command again.`)}function isOfficialItemAddress(e){return e.startsWith(`${OFFICIAL_REGISTRY}/`)}function withBuiltInRegistries(e){return{...e,registries:{[SKILLS_REGISTRY]:`https://www.skills.sh/r/{name}?agent=eve`,...e.registries}}}async function readEveRegistryConfig(e){return withBuiltInRegistries(await readRegistryConfig(e))}function configuredRegistrySources(e){return Object.keys(e.registries??{})}function validateRegistrySource(e){if(e!==void 0&&!e.startsWith(`@`)&&!/^https?:\/\//.test(e))throw Error(`Registry sources must be a namespace or URL: ${e}`)}async function loadOfficialSearchMetadata(){let e=await fetch(OFFICIAL_CATALOG);if(!e.ok)throw Error(`Could not read the eve registry (${e.status}).`);return parseOfficialRegistrySearchMetadata(await e.json())}function searchItemAddress(e){return e.registry===OFFICIAL_CATALOG?e.name:e.addCommandArgument}function enrichSearchItem(e,t){let n=searchItemAddress(e);return{item:e,address:n,...t.get(n)}}function registrySourceLabel(e){return e===OFFICIAL_CATALOG?`eve`:e===SKILLS_REGISTRY?`skills.sh`:e}function searchPresentationSections(e,t,n){return e.flatMap(e=>{let r=t.get(e);return r===void 0?[]:[{label:registrySourceLabel(e),items:r.items.map(e=>enrichSearchItem(e,n)),total:r.pagination.total}]})}async function printAddSuggestions(e,t,n){try{let r=n.split(`/`).at(-1)||n,{resultsBySource:i,sources:a,metadataByAddress:o}=await searchRegistryCatalog(t,{limit:5,query:r}),s=searchPresentationSections(a,i,o);if(s.every(e=>e.items.length===0))return;e.log(`Did you mean?`),printRegistrySearchResults(e,{query:r,sections:s})}catch{}}async function searchRegistryCatalog(e,t){validateRegistrySource(t.source);let n=await readEveRegistryConfig(e),r=t.source?[t.source]:[OFFICIAL_CATALOG,...configuredRegistrySources(n).filter(e=>t.query!==void 0||e!==SKILLS_REGISTRY)],i=await Promise.all(r.map(async e=>{try{return{result:await searchRegistries([e],{config:n,limit:t.limit??100,query:t.query}),source:e}}catch(t){return{error:t,source:e}}})),a=[],o=new Map;for(let e of i)if(`error`in e)a.push({message:errorMessage(e.error),registry:e.source});else{let t=e.result.errors??[];if(a.push(...t),t.length===0){let t=e.result.items.filter(t=>t.registry===e.source);o.set(e.source,{...e.result,items:t,pagination:{...e.result.pagination,total:e.result.items.length===t.length?e.result.pagination.total:0}})}}let s=new Map(a.map(e=>[`${e.registry}\0${e.message}`,e])),c=o.has(OFFICIAL_CATALOG)?await loadOfficialSearchMetadata():new Map,l=o.get(OFFICIAL_CATALOG);if(l!==void 0){let e=l.items.filter(e=>c.get(searchItemAddress(e))?.hidden!==!0);l.items=e,l.pagination={...l.pagination,total:e.length},l.items.sort((e,t)=>{let rank=e=>c.get(searchItemAddress(e))?.implementation===`native`?0:1;return rank(e)-rank(t)})}let u=[...o.values()];return{config:n,result:{items:u.flatMap(e=>e.items),pagination:{hasMore:u.some(e=>e.pagination.hasMore),limit:t.limit??100,offset:0,total:u.reduce((e,t)=>e+t.pagination.total,0)},...s.size>0?{errors:[...s.values()]}:{}},resultsBySource:o,sources:r,metadataByAddress:c}}async function browseRegistryCatalog(e,t={}){let{result:n}=await searchRegistryCatalog(e,t);return{items:n.items.map(e=>{let t={address:e.registry===OFFICIAL_CATALOG?e.name:e.addCommandArgument,name:e.name,source:e.registry===OFFICIAL_CATALOG?`Vercel`:e.registry};return e.title!==void 0&&(t.title=e.title),e.type!==void 0&&(t.type=e.type),e.description!==void 0&&(t.description=e.description),t}),total:n.pagination.total,errors:n.errors??[]}}async function browseRegistryItems(e,t,n,r,i={}){let{result:a,resultsBySource:o,sources:s,metadataByAddress:c}=await searchRegistryCatalog(t,{limit:i.limit,query:n,source:r}),l=a.errors??[];if(i.json||o.size>0){let t=a.items.map(e=>({...e,...c.get(searchItemAddress(e))})),r={query:n,sections:searchPresentationSections(s,o,c)};i.json&&(r.json={...a,items:t}),printRegistrySearchResults(e,r)}for(let t of l)e.error(`${t.registry}: ${t.message}`);l.length>0&&(process.exitCode=1)}async function getRegistryItemManifest(e,t){let n=await readEveRegistryConfig(e),r=await getRegistryItems([itemAddress(t)],{config:n});return r.length===1?r[0]:r}async function installRegistryItem(e,t,n={},r=defaultAddCommandDependencies){let i,a=[],o={error:e=>{i=e},log:e=>a.push(e)},s=process.exitCode,c=await runAddCommand(o,e,t,{...n,yes:n.prompter===void 0||n.yes,setupAuthorized:n.prompter!==void 0},r);if(process.exitCode=s,i!==void 0)throw Error(i);if(c===!1)throw new WizardCancelledError;let l={output:a};return c!==void 0&&(l.setup=c),l}async function runAddCommand(e,t,n,r,i=defaultAddCommandDependencies){return runRegistryAction(e,t,async()=>{let a=itemAddress(n),o=a===itemAddress(`channel/web`)?await prepareWebChatProjectRoot(t):t,s=await readEveRegistryConfig(t);if(r.skipInstall===!0){if(r.overwrite===!0)throw Error(`--overwrite cannot be used with --skip-install.`);if(r.skipSetup===!0)throw Error(`--skip-install cannot be used with --skip-setup.`);if(!isOfficialItemAddress(a))throw Error(`Setup flows are currently supported only for official eve registry items.`)}let c=await resolveRegistryItemForAdd(e,async()=>(await getRegistryItems([a],{config:s}))[0],()=>printAddSuggestions(e,t,n));if(!c.found)return;let l=c.item,u=isOfficialItemAddress(a)?eveMetadataFromRegistryItem(l):void 0;if(assertCompatibleEveVersion(u?.requires),r.skipInstall===!0){if(u?.setup===void 0)throw Error(`Registry item "${n}" does not declare a setup flow.`);let a=await runDeclaredSetups({logger:e,appRoot:t,item:n,setups:u.setup,options:r,dependencies:i,cancelledReminder:setupReminder(n,`cancelled`),resumeCommand:setupResumeCommand(n)});return reportRegistryCompletion(e,n,a,r)}if(!await prepareDeclaredPnpmBuildPolicy({logger:e,appRoot:o,item:n,policies:u?.install?.pnpm?.buildScripts,options:r}))return!1;if(a===itemAddress(`channel/web`)&&await(i.prepareWebRegistryProject??prepareWebRegistryProject)(o),await installRegistryItemTransaction({appRoot:o,item:n,registryItem:l,nonInteractive:r.nonInteractive,logger:e,install:async()=>{await addRegistryItems([a],{config:s,cwd:o,overwrite:r.overwrite,silent:r.silent})}}),u?.setup===void 0)return reportRegistryCompletion(e,n,{facts:[]},r);let d=i.hasInteractiveTerminal?.()??defaultAddCommandDependencies.hasInteractiveTerminal();if(r.nonInteractive&&e.log(serializeHeadlessSetupEvent({version:1,type:`progress`,message:r.skipInstall?`Setup ${n}`:`Installed ${n}`})),r.skipSetup===!0){if(r.nonInteractive)return reportRegistryCompletion(e,n,{facts:[]},r);e.log(setupReminder(n,`skipped`));return}if(!r.nonInteractive&&!r.yes&&!d&&r.setupAuthorized!==!0){e.log(setupReminder(n,`skipped`));return}if(!r.nonInteractive&&!r.yes&&r.setupAuthorized!==!0)try{if(await(r.prompter??i.createPrompter?.()??defaultAddCommandDependencies.createPrompter()).select({message:`Set up ${n} now?`,initialValue:`yes`,options:[{value:`yes`,label:`Yes`},{value:`no`,label:`No`}]})===`no`){e.log(setupReminder(n,`skipped`));return}}catch(t){if(!(t instanceof WizardCancelledError))throw t;e.log(setupReminder(n,`cancelled`));return}let f=await runDeclaredSetups({logger:e,appRoot:t,item:n,setups:u.setup,options:{...r,force:r.overwrite},dependencies:i,cancelledReminder:setupReminder(n,`cancelled`),resumeCommand:setupResumeCommand(n)});return reportRegistryCompletion(e,n,f,r)})}async function runRegistryListCommand(e,t,n,r={}){await runRegistryAction(e,t,()=>browseRegistryItems(e,t,void 0,n,r))}async function runRegistrySearchCommand(e,t,n,r,i={}){await runRegistryAction(e,t,()=>browseRegistryItems(e,t,n,r,{...i,limit:i.limit??10}))}async function runRegistryViewCommand(e,t,n,r={}){await runRegistryAction(e,t,async()=>{let i=await readEveRegistryConfig(t),a=await getRegistryItems([itemAddress(n)],{config:i}),o=a.length===1?a[0]:a;e.log(r.json?JSON.stringify(o,null,2):registryViewText(n,o))})}export{browseRegistryCatalog,getRegistryItemManifest,installOfficialRegistryItem,installRegistryItem,resolveOfficialRegistryUrl,runAddCommand,runRegistryAddCommand,runRegistryListCommand,runRegistrySearchCommand,runRegistryViewCommand};
@@ -1,23 +1,10 @@
1
1
  /**
2
- * Span-level detail rendering and trace-level usage aggregation for
3
- * `eve traces`. Kept separate from the command module: the tree renderer
4
- * stays compact while these helpers answer "what does this span carry" —
5
- * inline metric chips for tree rows, the `--verbose` per-span block, and
6
- * the usage/cost totals summarized in the trace header.
2
+ * Span-level detail rendering for `eve traces`. Kept separate from the command
3
+ * module: the tree renderer stays compact while these helpers answer "what
4
+ * does this span carry" — inline metric chips and the `--verbose` per-span block.
7
5
  */
8
6
  import type { LocalTraceSpan } from "#tracing/local-trace-reader.js";
9
- /** Usage and cost totals aggregated over a trace's `agent.step` spans. */
10
- export interface LocalTraceSummary {
11
- readonly cacheReadTokens: number;
12
- readonly cacheWriteTokens: number;
13
- /** Total gateway cost in USD; undefined when no span reported cost. */
14
- readonly costUsd?: number;
15
- readonly errorCount: number;
16
- readonly inputTokens: number;
17
- /** Distinct model ids seen on any span, first-seen order. */
18
- readonly models: readonly string[];
19
- readonly outputTokens: number;
20
- }
7
+ import { type LocalTraceSummary } from "#tracing/local-trace-summary.js";
21
8
  /**
22
9
  * Compact metrics for one tree row: token chips (`↑1.4K`/`↓213`), cost
23
10
  * (`$0.0031`). Only chips whose attributes the span actually carries — rows
@@ -26,15 +13,8 @@ export interface LocalTraceSummary {
26
13
  * Raw values: callers sanitize for their output surface.
27
14
  */
28
15
  export declare function spanMetricChips(span: LocalTraceSpan): string[];
29
- /**
30
- * Aggregates usage, cost, models, and errors across one trace. Only
31
- * `agent.step` spans contribute usage: model spans carry the same counters
32
- * and a subagent's totals already appear as its own step spans in the same
33
- * trace, so summing anything else would double-count.
34
- */
35
- export declare function summarizeLocalTrace(spans: readonly LocalTraceSpan[]): LocalTraceSummary;
36
16
  /** One-line `Tokens` header value: `↑1.2K in · ↓340 out · 1.1K cached`. */
37
- export declare function formatTokenSummary(summary: LocalTraceSummary): string;
17
+ export declare function formatTokenSummary(summary: Pick<LocalTraceSummary, "inputTokens" | "outputTokens" | "cacheReadTokens" | "cacheWriteTokens">): string;
38
18
  /** Formats a USD cost: `$1.50` at scale, `$0.0031` for typical spans. */
39
19
  export declare function formatCostUsd(costUsd: number): string;
40
20
  /**
@@ -1 +1 @@
1
- import{sanitizeForTerminal}from"#cli/ui/output.js";import{formatElapsed}from"#cli/format-elapsed.js";import{formatCompactTokenCount}from"#cli/dev/tui/stream-format.js";import{formatAttributeContent}from"#cli/dev/tui/traces/trace-content.js";import{AGENT_USAGE_ATTRIBUTES}from"#tracing/agent-span-contract.js";function spanMetricChips(e){let t=[],n=numberAttribute(e,`agent.usage.input_tokens`),r=numberAttribute(e,`agent.usage.output_tokens`);n!==void 0&&t.push(`↑${formatCompactTokenCount(n)}`),r!==void 0&&t.push(`↓${formatCompactTokenCount(r)}`);let i=spanCostUsd(e);return i!==void 0&&t.push(formatCostUsd(i)),t}function summarizeLocalTrace(e){let t=[],n=0,r=0,i,a=0,o=0,s=0;for(let c of e){let e=stringAttribute(c,`agent.model.id`)??stringAttribute(c,`gen_ai.request.model`);if(e!==void 0&&!t.includes(e)&&t.push(e),c.statusCode===2&&(a+=1),c.name!==`agent.step`)continue;o+=numberAttribute(c,`agent.usage.input_tokens`)??0,s+=numberAttribute(c,`agent.usage.output_tokens`)??0,n+=numberAttribute(c,AGENT_USAGE_ATTRIBUTES.cacheReadTokens)??numberAttribute(c,`gen_ai.usage.cache_read.input_tokens`)??0,r+=numberAttribute(c,AGENT_USAGE_ATTRIBUTES.cacheWriteTokens)??numberAttribute(c,`gen_ai.usage.cache_write.input_tokens`)??numberAttribute(c,`gen_ai.usage.cache_creation.input_tokens`)??0;let l=spanCostUsd(c);l!==void 0&&(i=(i??0)+l)}return{cacheReadTokens:n,cacheWriteTokens:r,costUsd:i,errorCount:a,inputTokens:o,models:t,outputTokens:s}}function formatTokenSummary(e){let t=[`↑${formatCompactTokenCount(e.inputTokens)} in`,`↓${formatCompactTokenCount(e.outputTokens)} out`];return e.cacheReadTokens>0&&t.push(`${formatCompactTokenCount(e.cacheReadTokens)} cached`),e.cacheWriteTokens>0&&t.push(`${formatCompactTokenCount(e.cacheWriteTokens)} cache write`),t.join(` · `)}function formatCostUsd(e){return e>=1?`$${e.toFixed(2)}`:`$${e.toFixed(4)}`}function renderSpanDetailTree(e,t){let n=spanDetailEntries(e,t.width-t.margin.length-3),r=[];return n.forEach((e,r)=>{let i=r===n.length-1&&!t.childrenFollow;emit(e,t.margin,i?`└─ `:`├─ `)}),r;function emit(e,n,i){r.push(t.mute(`${n}${i}${e.head}`));let a=`${n}${i===`└─ `?` `:`│ `}`;for(let n of e.lines)r.push(t.mute(`${a} ${n}`));e.entries.forEach((t,n)=>{emit(t,a,n===e.entries.length-1?`└─ `:`├─ `)})}}function spanDetailEntries(e,t){let dim=e=>e,n=Math.max(40,t),r=[],push=(e,t=[],n=[])=>{r.push({entries:n,head:e,lines:t})},i=e.statusCode===2;push(`status: ${i&&e.statusMessage!==void 0?`ERROR — ${sanitizeForTerminal(e.statusMessage)}`:i?`ERROR`:`ok`}`),push(`duration: ${formatElapsed(durationMs(e.startTimeNs,e.endTimeNs))}`),push(`started: ${new Date(Number(e.startTimeNs/1000000n)).toISOString()}`),push(`span: ${e.spanId}`),e.parentSpanId!==void 0&&push(`parent: ${e.parentSpanId}`),e.scope!==void 0&&push(`scope: ${sanitizeForTerminal(e.scope)}`),e.kind!==void 0&&e.kind!==1&&push(`kind: ${spanKind(e.kind)}`);for(let t of Object.keys(e.attributes).sort()){let r=formatAttributeContent(t,e.attributes[t],dim,n-2),i=sanitizeForTerminal(t);r.length===1?push(`${i}: ${r[0]}`):push(`${i}:`,r)}return e.events.length>0&&push(`events:`,[],e.events.map(t=>{let r=Math.max(0,durationMs(e.startTimeNs,t.timeNs)),i=[];for(let e of Object.keys(t.attributes).sort()){let r=formatAttributeContent(e,t.attributes[e],dim,n-6),a=sanitizeForTerminal(e);r.length===1?i.push(`${a}: ${r[0]}`):i.push(`${a}:`,...r.map(e=>` ${e}`))}return{entries:[],head:`${sanitizeForTerminal(t.name)} +${formatElapsed(r)}`,lines:i}})),r}function spanCostUsd(e){return numberAttribute(e,`gen_ai.usage.gateway_cost`)??numberAttribute(e,`gen_ai.usage.cost`)}function spanKind(e){switch(e){case 2:return`server`;case 3:return`client`;case 4:return`producer`;case 5:return`consumer`;default:return`unknown (${e})`}}function numberAttribute(e,t){let n=e.attributes[t];if(typeof n==`number`)return n;if(typeof n==`string`&&n!==``){let e=Number(n);return Number.isFinite(e)?e:void 0}}function stringAttribute(e,t){let n=e.attributes[t];return typeof n==`string`&&n.length>0?n:void 0}function durationMs(e,t){return Number(t-e)/1e6}export{formatCostUsd,formatTokenSummary,renderSpanDetailTree,spanMetricChips,summarizeLocalTrace};
1
+ import{sanitizeForTerminal}from"#cli/ui/output.js";import{formatElapsed}from"#cli/format-elapsed.js";import{formatCompactTokenCount}from"#cli/dev/tui/stream-format.js";import{formatAttributeContent}from"#cli/dev/tui/traces/trace-content.js";import{localTraceSpanCostUsd}from"#tracing/local-trace-summary.js";function spanMetricChips(e){let t=[],n=numberAttribute(e,`agent.usage.input_tokens`),r=numberAttribute(e,`agent.usage.output_tokens`);n!==void 0&&t.push(`↑${formatCompactTokenCount(n)}`),r!==void 0&&t.push(`↓${formatCompactTokenCount(r)}`);let i=localTraceSpanCostUsd(e);return i!==void 0&&t.push(formatCostUsd(i)),t}function formatTokenSummary(e){let t=[`↑${formatCompactTokenCount(e.inputTokens)} in`,`↓${formatCompactTokenCount(e.outputTokens)} out`];return e.cacheReadTokens>0&&t.push(`${formatCompactTokenCount(e.cacheReadTokens)} cached`),e.cacheWriteTokens>0&&t.push(`${formatCompactTokenCount(e.cacheWriteTokens)} cache write`),t.join(` · `)}function formatCostUsd(e){return e>=1?`$${e.toFixed(2)}`:`$${e.toFixed(4)}`}function renderSpanDetailTree(e,t){let n=spanDetailEntries(e,t.width-t.margin.length-3),r=[];return n.forEach((e,r)=>{let i=r===n.length-1&&!t.childrenFollow;emit(e,t.margin,i?`└─ `:`├─ `)}),r;function emit(e,n,i){r.push(t.mute(`${n}${i}${e.head}`));let a=`${n}${i===`└─ `?` `:`│ `}`;for(let n of e.lines)r.push(t.mute(`${a} ${n}`));e.entries.forEach((t,n)=>{emit(t,a,n===e.entries.length-1?`└─ `:`├─ `)})}}function spanDetailEntries(e,t){let dim=e=>e,n=Math.max(40,t),r=[],push=(e,t=[],n=[])=>{r.push({entries:n,head:e,lines:t})},i=e.statusCode===2;push(`status: ${i&&e.statusMessage!==void 0?`ERROR — ${sanitizeForTerminal(e.statusMessage)}`:i?`ERROR`:`ok`}`),push(`duration: ${formatElapsed(durationMs(e.startTimeNs,e.endTimeNs))}`),push(`started: ${new Date(Number(e.startTimeNs/1000000n)).toISOString()}`),push(`span: ${e.spanId}`),e.parentSpanId!==void 0&&push(`parent: ${e.parentSpanId}`),e.scope!==void 0&&push(`scope: ${sanitizeForTerminal(e.scope)}`),e.kind!==void 0&&e.kind!==1&&push(`kind: ${spanKind(e.kind)}`);for(let t of Object.keys(e.attributes).sort()){let r=formatAttributeContent(t,e.attributes[t],dim,n-2),i=sanitizeForTerminal(t);r.length===1?push(`${i}: ${r[0]}`):push(`${i}:`,r)}return e.events.length>0&&push(`events:`,[],e.events.map(t=>{let r=Math.max(0,durationMs(e.startTimeNs,t.timeNs)),i=[];for(let e of Object.keys(t.attributes).sort()){let r=formatAttributeContent(e,t.attributes[e],dim,n-6),a=sanitizeForTerminal(e);r.length===1?i.push(`${a}: ${r[0]}`):i.push(`${a}:`,...r.map(e=>` ${e}`))}return{entries:[],head:`${sanitizeForTerminal(t.name)} +${formatElapsed(r)}`,lines:i}})),r}function spanKind(e){switch(e){case 2:return`server`;case 3:return`client`;case 4:return`producer`;case 5:return`consumer`;default:return`unknown (${e})`}}function numberAttribute(e,t){let n=e.attributes[t];if(typeof n==`number`)return n;if(typeof n==`string`&&n!==``){let e=Number(n);return Number.isFinite(e)?e:void 0}}function durationMs(e,t){return Number(t-e)/1e6}export{formatCostUsd,formatTokenSummary,renderSpanDetailTree,spanMetricChips};
@@ -1,8 +1,8 @@
1
- import{basename}from"node:path";import{createCliTheme,renderCliSection,sanitizeForTerminal}from"#cli/ui/output.js";import{formatElapsed}from"#cli/format-elapsed.js";import{formatCostUsd,formatTokenSummary,renderSpanDetailTree,spanMetricChips,summarizeLocalTrace}from"#cli/commands/trace-detail.js";import{compareLocalTraceSpans,describeLocalTraceSpan,listLocalTraces}from"#tracing/local-trace-reader.js";const TRACE_DISPLAY_DIRECTORY=`.eve/traces/v1`;function resolveLocalTraces(e,t){let n=t.replaceAll(`\\`,`/`),r=basename(n),i=n===r?[n]:[n,r],a=e.find(e=>i.includes(e.traceId));if(a!==void 0)return[a];let o=e.filter(e=>e.conversationIds.some(e=>i.includes(e)));if(o.length>0)return orderWindows(o);let s=e.filter(e=>i.some(t=>e.traceId.startsWith(t)||e.conversationIds.some(e=>e.startsWith(t))));if(s.length===0)throw Error(`No local trace matches "${sanitizeForTerminal(t)}". Run \`eve traces ls\` to list traces.`);if(s.length===1)return s;if(new Set(s.map(e=>e.conversationId??e.traceId)).size>1)throw ambiguousTraceError(s,t);return orderWindows(s)}function orderWindows(e){return[...e].sort((e,t)=>e.startTimeNs===t.startTimeNs?e.traceId.localeCompare(t.traceId):e.startTimeNs<t.startTimeNs?-1:1)}async function runTraceListCommand(e,t,n={}){let r=await listLocalTraces(t);if(n.json===!0){e.log(JSON.stringify(r.map(e=>({agentName:e.agentName??null,durationMs:durationMs(e.startTimeNs,e.endTimeNs),conversationId:e.conversationId??null,spanCount:e.spans.length,startedAt:toDate(e.startTimeNs).toISOString(),traceId:e.traceId})),null,2));return}if(r.length===0){e.log(`No local traces found under ${TRACE_DISPLAY_DIRECTORY}.`);return}let i=r.map(e=>[e.traceId,sanitizeForTerminal(e.conversationId??`unknown`),sanitizeForTerminal(e.agentName??`unknown`),toDate(e.startTimeNs).toISOString(),formatElapsed(durationMs(e.startTimeNs,e.endTimeNs)),String(e.spans.length)]),a=[`TRACE`,`CONVERSATION`,`AGENT`,`STARTED`,`DURATION`,`SPANS`],o=a.map((e,t)=>Math.max(e.length,...i.map(e=>e[t].length)));e.log([a,...i].map(e=>e.map((e,t)=>e.padEnd(o[t])).join(` `).trimEnd()).join(`
1
+ import{basename}from"node:path";import{createCliTheme,renderCliSection,sanitizeForTerminal}from"#cli/ui/output.js";import{formatElapsed}from"#cli/format-elapsed.js";import{summarizeLocalTrace}from"#tracing/local-trace-summary.js";import{formatCostUsd,formatTokenSummary,renderSpanDetailTree,spanMetricChips}from"#cli/commands/trace-detail.js";import{compareLocalTraceSpans,describeLocalTraceSpan,listLocalTraces}from"#tracing/local-trace-reader.js";const TRACE_DISPLAY_DIRECTORY=`.eve/traces/v1`;function resolveLocalTraces(e,t){let n=t.replaceAll(`\\`,`/`),r=basename(n),i=n===r?[n]:[n,r],a=e.find(e=>i.includes(e.traceId));if(a!==void 0)return[a];let o=e.filter(e=>e.conversationIds.some(e=>i.includes(e)));if(o.length>0)return orderWindows(o);let s=e.filter(e=>i.some(t=>e.traceId.startsWith(t)||e.conversationIds.some(e=>e.startsWith(t))));if(s.length===0)throw Error(`No local trace matches "${sanitizeForTerminal(t)}". Run \`eve traces ls\` to list traces.`);if(s.length===1)return s;if(new Set(s.map(e=>e.conversationId??e.traceId)).size>1)throw ambiguousTraceError(s,t);return orderWindows(s)}function orderWindows(e){return[...e].sort((e,t)=>e.startTimeNs===t.startTimeNs?e.traceId.localeCompare(t.traceId):e.startTimeNs<t.startTimeNs?-1:1)}async function runTraceListCommand(e,t,n={}){let r=await listLocalTraces(t);if(n.json===!0){e.log(JSON.stringify(r.map(e=>({agentName:e.agentName??null,durationMs:durationMs(e.startTimeNs,e.endTimeNs),conversationId:e.conversationId??null,spanCount:e.spans.length,startedAt:toDate(e.startTimeNs).toISOString(),traceId:e.traceId})),null,2));return}if(r.length===0){e.log(`No local traces found under ${TRACE_DISPLAY_DIRECTORY}.`);return}let i=r.map(e=>[e.traceId,sanitizeForTerminal(e.conversationId??`unknown`),sanitizeForTerminal(e.agentName??`unknown`),toDate(e.startTimeNs).toISOString(),formatElapsed(durationMs(e.startTimeNs,e.endTimeNs)),String(e.spans.length)]),a=[`TRACE`,`CONVERSATION`,`AGENT`,`STARTED`,`DURATION`,`SPANS`],o=a.map((e,t)=>Math.max(e.length,...i.map(e=>e[t].length)));e.log([a,...i].map(e=>e.map((e,t)=>e.padEnd(o[t])).join(` `).trimEnd()).join(`
2
2
  `))}async function runTraceShowCommand(e,t,n,r={}){let i=await listLocalTraces(t);if(i.length===0){let t=`No local traces found under ${TRACE_DISPLAY_DIRECTORY}.`;if(n!==void 0)throw Error(t);e.log(t);return}let a=n===void 0?[i[0]]:resolveLocalTraces(i,n);if(r.json===!0){e.log(JSON.stringify(a.map(serializeTraceForJson),null,2));return}let o=createCliTheme();e.log(a.map(e=>[renderCliSection(o,{rows:traceHeaderRows(e),title:`Trace`}),`${o.accent(`Spans`)}\n${renderSpanTree(e.spans,{dim:o.muted,verbose:r.verbose===!0})}`].join(`
3
3
 
4
4
  `)).join(`
5
5
 
6
- `))}function traceHeaderRows(e){let t=summarizeLocalTrace(e.spans);return[{label:`Trace ID`,value:e.traceId},{label:`Conversation ID`,value:e.conversationId??`unknown`},{label:`Agent`,value:e.agentName??`unknown`},{label:`Started`,value:toDate(e.startTimeNs).toISOString()},{label:`Duration`,value:formatElapsed(durationMs(e.startTimeNs,e.endTimeNs))},{label:`Spans`,value:String(e.spans.length)},...t.models.length===0?[]:[{label:`Models`,value:t.models.join(`, `)}],...t.inputTokens===0&&t.outputTokens===0?[]:[{label:`Tokens`,value:formatTokenSummary(t)}],...t.costUsd===void 0?[]:[{label:`Cost`,value:formatCostUsd(t.costUsd)}],...t.errorCount===0?[]:[{label:`Errors`,value:`${t.errorCount} span${t.errorCount===1?``:`s`}`}]]}function serializeTraceForJson(e){return{agentName:e.agentName??null,durationMs:durationMs(e.startTimeNs,e.endTimeNs),conversationId:e.conversationId??null,conversationIds:e.conversationIds,spanCount:e.spans.length,spans:e.spans.map(e=>({attributes:e.attributes,durationMs:durationMs(e.startTimeNs,e.endTimeNs),endTimeNs:e.endTimeNs.toString(),events:e.events.map(e=>({attributes:e.attributes,name:e.name,timeNs:e.timeNs.toString()})),kind:e.kind??null,name:e.name,parentSpanId:e.parentSpanId??null,scope:e.scope??null,spanId:e.spanId,startTimeNs:e.startTimeNs.toString(),statusCode:e.statusCode,statusMessage:e.statusMessage??null})),startedAt:toDate(e.startTimeNs).toISOString(),traceId:e.traceId}}function renderSpanTree(e,t={}){let n=new Map(e.map(e=>[e.spanId,e])),r=new Map,i=[];for(let t of e)if(t.parentSpanId===void 0||!n.has(t.parentSpanId))i.push(t);else{let e=r.get(t.parentSpanId)??[];e.push(t),r.set(t.parentSpanId,e)}i.sort(compareLocalTraceSpans);for(let e of r.values())e.sort(compareLocalTraceSpans);let a=subtreeExtents(e,r),o=terminalWidth(),s=[],c=new Set,l=t.dim??(e=>e),render=(e,n,i)=>{if(c.has(e.spanId))return;c.add(e.spanId);let u=`${n}${i}`;s.push(`${u===``?``:l(u)}${spanLabel(e,a.get(e.spanId))}`);let d=`${n}${i===``?``:i===`└─ `?` `:`│ `}`,f=r.get(e.spanId)??[];if(t.verbose===!0)for(let t of renderSpanDetailTree(e,{childrenFollow:f.length>0,margin:d,mute:l,width:o}))s.push(t);f.forEach((e,t)=>{let n=t===f.length-1;render(e,d,n?`└─ `:`├─ `)})};for(let e of i)render(e,``,``);for(let t of[...e].sort(compareLocalTraceSpans))c.has(t.spanId)||render(t,``,``);return s.join(`
6
+ `))}function traceHeaderRows(e){let t=summarizeLocalTrace(e.traceId,e.spans);return[{label:`Trace ID`,value:e.traceId},{label:`Conversation ID`,value:e.conversationId??`unknown`},{label:`Agent`,value:e.agentName??`unknown`},{label:`Started`,value:t.startedAt},{label:`Duration`,value:formatElapsed(t.durationMs)},{label:`Spans`,value:String(t.spanCount)},...t.models.length===0?[]:[{label:`Models`,value:t.models.join(`, `)}],...t.inputTokens===0&&t.outputTokens===0?[]:[{label:`Tokens`,value:formatTokenSummary(t)}],...t.costUsd===void 0?[]:[{label:`Cost`,value:formatCostUsd(t.costUsd)}],...t.errorSpanCount===0?[]:[{label:`Errors`,value:`${t.errorSpanCount} span${t.errorSpanCount===1?``:`s`}`}]]}function serializeTraceForJson(e){return{agentName:e.agentName??null,durationMs:durationMs(e.startTimeNs,e.endTimeNs),conversationId:e.conversationId??null,conversationIds:e.conversationIds,spanCount:e.spans.length,spans:e.spans.map(e=>({attributes:e.attributes,durationMs:durationMs(e.startTimeNs,e.endTimeNs),endTimeNs:e.endTimeNs.toString(),events:e.events.map(e=>({attributes:e.attributes,name:e.name,timeNs:e.timeNs.toString()})),kind:e.kind??null,name:e.name,parentSpanId:e.parentSpanId??null,scope:e.scope??null,spanId:e.spanId,startTimeNs:e.startTimeNs.toString(),statusCode:e.statusCode,statusMessage:e.statusMessage??null})),startedAt:toDate(e.startTimeNs).toISOString(),traceId:e.traceId}}function renderSpanTree(e,t={}){let n=new Map(e.map(e=>[e.spanId,e])),r=new Map,i=[];for(let t of e)if(t.parentSpanId===void 0||!n.has(t.parentSpanId))i.push(t);else{let e=r.get(t.parentSpanId)??[];e.push(t),r.set(t.parentSpanId,e)}i.sort(compareLocalTraceSpans);for(let e of r.values())e.sort(compareLocalTraceSpans);let a=subtreeExtents(e,r),o=terminalWidth(),s=[],c=new Set,l=t.dim??(e=>e),render=(e,n,i)=>{if(c.has(e.spanId))return;c.add(e.spanId);let u=`${n}${i}`;s.push(`${u===``?``:l(u)}${spanLabel(e,a.get(e.spanId))}`);let d=`${n}${i===``?``:i===`└─ `?` `:`│ `}`,f=r.get(e.spanId)??[];if(t.verbose===!0)for(let t of renderSpanDetailTree(e,{childrenFollow:f.length>0,margin:d,mute:l,width:o}))s.push(t);f.forEach((e,t)=>{let n=t===f.length-1;render(e,d,n?`└─ `:`├─ `)})};for(let e of i)render(e,``,``);for(let t of[...e].sort(compareLocalTraceSpans))c.has(t.spanId)||render(t,``,``);return s.join(`
7
7
  `)}function subtreeExtents(e,t){let n=new Map,r=new Set,visit=e=>{let i=n.get(e.spanId);if(i!==void 0)return i;if(r.has(e.spanId))return{endTimeNs:e.endTimeNs,startTimeNs:e.startTimeNs};r.add(e.spanId);let a=e.endTimeNs,o=e.startTimeNs;for(let n of t.get(e.spanId)??[]){let e=visit(n);e.startTimeNs<o&&(o=e.startTimeNs),e.endTimeNs>a&&(a=e.endTimeNs)}r.delete(e.spanId);let s={endTimeNs:a,startTimeNs:o};return n.set(e.spanId,s),s};for(let t of e)visit(t);return n}function spanLabel(e,t){let n=describeLocalTraceSpan(e).map(sanitizeForTerminal),r=n.length===0?``:` [${n.join(`, `)}]`,i=spanMetricChips(e).map(sanitizeForTerminal),a=i.length===0?``:` ${i.join(` `)}`,o=e.statusCode===2?` ERROR`:``,s=durationMs(e.startTimeNs,e.endTimeNs),c=s===0&&t!==void 0?durationMs(t.startTimeNs,t.endTimeNs):s;return`${sanitizeForTerminal(e.name)}${r} ${formatElapsed(c)}${a}${o}`}function terminalWidth(){let e=process.stdout.columns;return typeof e==`number`&&e>=40?e:100}function durationMs(e,t){return Number(t-e)/1e6}function toDate(e){return new Date(Number(e/1000000n))}function ambiguousTraceError(e,t){return Error([`"${sanitizeForTerminal(t)}" matches ${e.length} local traces:`,...e.map(e=>` ${e.traceId} ${sanitizeForTerminal(e.conversationId??`unknown conversation`)}`),`Pass a longer prefix or the full trace/conversation id.`].join(`
8
8
  `))}export{resolveLocalTraces,runTraceListCommand,runTraceShowCommand};
@@ -1 +1 @@
1
- import{resolveTuiDisplayOptions}from"./ui-options.js";import{resolveTuiTitle}from"./tui/target.js";import{randomUUID}from"node:crypto";import{findEveProjectContext}from"#internal/project-context.js";import{devBootPhase}from"#internal/dev-boot-progress.js";import{resumeDevelopmentRuntimeArtifacts,suspendDevelopmentRuntimeArtifacts}from"#services/dev-client/runtime-artifacts.js";async function runInteractiveDevelopmentUi(e){let t=await devBootPhase(`loading interactive UI`,async()=>e.runDevelopmentTui??(await import(`#cli/dev/tui/tui.js`)).runDevelopmentTui,e.report),n=e.server.appRoot??e.applicationRoot,r=await findEveProjectContext(n),i=r?.environmentRoot??n,a=r?.kind===`workspace-member`?r.member.appRoot:void 0,o=e.remoteTarget===void 0||e.existingLocalServer?{kind:`local`,serverUrl:e.server.serverUrl,workspaceRoot:i,agentRoot:a}:{kind:`remote`,serverUrl:e.server.serverUrl,workspaceRoot:i,agentRoot:a},s=resolveTuiDisplayOptions(e.options),c=resolveTuiTitle({name:e.options.name,target:o});c!==void 0&&(s.name=c);let l={target:o,initialInput:e.options.input,onboard:e.options.onboard,onBootProgress:e.report,onOnboardingStep:e.onOnboardingStep,onOnboardingTerminal:e.onOnboardingTerminal,lifecycle:e.lifecycle,...s};e.startup!==void 0&&(l.startup=e.startup),o.kind===`local`&&(l.withExclusiveTerminal=async t=>{let n=randomUUID();if(!await suspendDevelopmentRuntimeArtifacts({leaseId:n,serverUrl:e.server.serverUrl}))throw Error(`Could not pause the development server for setup.`);let r;try{r={ok:!0,value:await t()}}catch(e){r={error:e,ok:!1}}let i={leaseId:n,serverUrl:e.server.serverUrl,silent:!0};if(await resumeDevelopmentRuntimeArtifacts(i)===void 0&&await resumeDevelopmentRuntimeArtifacts(i)===void 0)throw Error(`Could not resume the eve development server after setup. Restart eve dev before making further source changes.`,r.ok?void 0:{cause:r.error});if(!r.ok)throw r.error;return r.value}),e.remoteTarget?.headers===void 0?await t(l):await t({...l,headers:e.remoteTarget.headers})}export{runInteractiveDevelopmentUi};
1
+ import{resolveTuiDisplayOptions}from"./ui-options.js";import{resolveTuiTitle}from"./tui/target.js";import{randomUUID}from"node:crypto";import{findEveProjectContext}from"#internal/project-context.js";import{devBootPhase}from"#internal/dev-boot-progress.js";import{resumeDevelopmentRuntimeArtifacts,suspendDevelopmentRuntimeArtifacts}from"#services/dev-client/runtime-artifacts.js";async function runInteractiveDevelopmentUi(e){let t=await devBootPhase(`loading interactive UI`,async()=>e.runDevelopmentTui??(await import(`#cli/dev/tui/tui.js`)).runDevelopmentTui,e.report),n=await findEveProjectContext(e.applicationRoot),r=n?.environmentRoot??e.server.appRoot??e.applicationRoot,i=n?.kind===`workspace-member`?n.member.appRoot:void 0,a=e.remoteTarget===void 0||e.existingLocalServer?{kind:`local`,serverUrl:e.server.serverUrl,workspaceRoot:r,agentRoot:i}:{kind:`remote`,serverUrl:e.server.serverUrl,workspaceRoot:r,agentRoot:i},o=resolveTuiDisplayOptions(e.options),s=resolveTuiTitle({name:e.options.name,target:a});s!==void 0&&(o.name=s);let c={target:a,initialInput:e.options.input,onboard:e.options.onboard,onBootProgress:e.report,onOnboardingStep:e.onOnboardingStep,onOnboardingTerminal:e.onOnboardingTerminal,lifecycle:e.lifecycle,...o};e.startup!==void 0&&(c.startup=e.startup),a.kind===`local`&&(c.withExclusiveTerminal=async t=>{let n=randomUUID();if(!await suspendDevelopmentRuntimeArtifacts({leaseId:n,serverUrl:e.server.serverUrl}))throw Error(`Could not pause the development server for setup.`);let r;try{r={ok:!0,value:await t()}}catch(e){r={error:e,ok:!1}}let i={leaseId:n,serverUrl:e.server.serverUrl,silent:!0};if(await resumeDevelopmentRuntimeArtifacts(i)===void 0&&await resumeDevelopmentRuntimeArtifacts(i)===void 0)throw Error(`Could not resume the eve development server after setup. Restart eve dev before making further source changes.`,r.ok?void 0:{cause:r.error});if(!r.ok)throw r.error;return r.value}),e.remoteTarget?.headers===void 0?await t(c):await t({...c,headers:e.remoteTarget.headers})}export{runInteractiveDevelopmentUi};
@@ -6,7 +6,7 @@ export interface PromptArgumentSuggestion {
6
6
  /** Follow-up values available after selecting this exact value. */
7
7
  readonly next?: readonly PromptArgumentSuggestion[];
8
8
  }
9
- export type ArgumentTypeaheadCommand = "model" | "add";
9
+ export type ArgumentTypeaheadCommand = "model" | "add" | "login";
10
10
  export interface ArgumentTypeaheadQuery {
11
11
  readonly command: ArgumentTypeaheadCommand;
12
12
  readonly argument: string;
@@ -1,2 +1,2 @@
1
- import{sanitizeForTerminal}from"#cli/ui/output.js";import{sliceVisible,visibleLength}from"#cli/ui/terminal-text.js";const ARGUMENT_LIMIT={add:1,model:2};function isArgumentTypeaheadCommand(e){return e===`model`||e===`add`}function argumentTypeaheadLoadingLabel(e){return e===`model`?`models`:`registry`}function argumentTypeaheadQuery(e){if(!e.startsWith(`/`))return;let t=e.indexOf(` `);if(t<0)return;let n=e.slice(1,t);if(!isArgumentTypeaheadCommand(n))return;let r=[],i=t;for(;i<e.length;){for(;e[i]===` `;)i+=1;if(i===e.length)break;let t=i;for(;i<e.length&&e[i]!==` `;)i+=1;r.push({value:e.slice(t,i),start:t})}let a=r.length+ +!!e.endsWith(` `);if(e.slice(t).includes(`
1
+ import{sanitizeForTerminal}from"#cli/ui/output.js";import{sliceVisible,visibleLength}from"#cli/ui/terminal-text.js";const ARGUMENT_LIMIT={add:1,login:1,model:2};function isArgumentTypeaheadCommand(e){return e===`model`||e===`add`||e===`login`}function argumentTypeaheadLoadingLabel(e){return e===`model`?`models`:e===`add`?`registry`:`connections`}function argumentTypeaheadQuery(e){if(!e.startsWith(`/`))return;let t=e.indexOf(` `);if(t<0)return;let n=e.slice(1,t);if(!isArgumentTypeaheadCommand(n))return;let r=[],i=t;for(;i<e.length;){for(;e[i]===` `;)i+=1;if(i===e.length)break;let t=i;for(;i<e.length&&e[i]!==` `;)i+=1;r.push({value:e.slice(t,i),start:t})}let a=r.length+ +!!e.endsWith(` `);if(e.slice(t).includes(`
2
2
  `)||a>ARGUMENT_LIMIT[n])return;let o=r.at(-1),s=r.map(e=>e.value);return!e.endsWith(` `)&&o!==void 0&&s.pop(),{command:n,argument:e.endsWith(` `)?``:o?.value??``,completed:s,argumentStart:e.endsWith(` `)?e.length:o?.start??e.length}}function sanitizeSuggestion(e){let t={value:sanitizeForTerminal(e.value),label:sanitizeForTerminal(e.label)};return e.hint!==void 0&&(t.hint=sanitizeForTerminal(e.hint)),e.next!==void 0&&(t.next=e.next.map(sanitizeSuggestion)),t}function argumentTypeaheadFor(e,t,n){let r=t.map(sanitizeSuggestion),i=e.completed.length===0?r:r.find(t=>t.value===e.completed[0])?.next??[],a=e.argument.toLowerCase(),o=i.filter(e=>e.value.toLowerCase().includes(a)||e.label.toLowerCase().includes(a)||(e.hint?.toLowerCase().includes(a)??!1)),s=n?.suggestions[n.selectedIndex],c=s===void 0?-1:o.findIndex(e=>e.value===s.value);return{...e,suggestions:o,selectedIndex:c>=0?c:0}}function moveArgumentTypeaheadSelection(e,t){return e.suggestions.length===0?e:{...e,selectedIndex:(e.selectedIndex+t+e.suggestions.length)%e.suggestions.length}}function selectedArgumentSuggestion(e){return e.suggestions[e.selectedIndex]}function argumentTypeaheadCompletion(e,t){return`/${e.command} ${[...e.completed,t.value].join(` `)}`}function renderArgumentSuggestions(e,t,n){let r=t.colors,i=Math.min(8,e.suggestions.length),a=Math.max(0,Math.min(e.selectedIndex-Math.floor(i/2),e.suggestions.length-i));return e.suggestions.slice(a,a+i).map((t,i)=>{let o=a+i===e.selectedIndex?r.bold(t.value):r.dim(t.value),s=`${` `.repeat(e.argumentStart+2)}${o}`;return visibleLength(s)>n?sliceVisible(s,n):s})}export{argumentTypeaheadCompletion,argumentTypeaheadFor,argumentTypeaheadLoadingLabel,argumentTypeaheadQuery,isArgumentTypeaheadCommand,moveArgumentTypeaheadSelection,renderArgumentSuggestions,selectedArgumentSuggestion};
@@ -1 +1 @@
1
- import{isPromptCommandAvailableFor}from"./prompt-commands.js";import{toErrorMessage}from"#shared/errors.js";function createPromptCommandHandler(e){return{async handle(t,n){let{target:r}=e;if(r.kind===`remote`&&!isPromptCommandAvailableFor(t.name,`remote`))return{message:`/${t.name} needs eve dev running the local server (it is not available with --url).`};if(t.name===`model`){if(t.argument.length===0)return{message:`Choose a model from the inline /model suggestions.`};if(r.kind!==`local`)return{message:`/model needs eve dev running the local server (it is not available with --url).`};let n=r.agentRoot??r.workspaceRoot;try{let{modelChangeRefusalForUneditableModel:r}=await import(`#setup/flows/model.js`),{changeAgentModel:i,changeAgentModelSettings:a,formatApplyModelOutcome:o,formatApplyModelSettingsOutcome:s}=await import(`#setup/flows/model-source-change.js`),[c,l,...u]=t.argument.split(/\s+/u);if(c===void 0||u.length>0||l!==void 0&&![`default`,`none`,`minimal`,`low`,`medium`,`high`,`xhigh`].includes(l))return{message:"Use `/model provider/model [default|none|minimal|low|medium|high|xhigh]`."};let d=await(e.modelChangeRefusal??r)(n);return d===null?l===void 0?{message:o(await(e.applyModel??i)({appRoot:n,slug:c}))}:{message:s(await a({appRoot:n,patch:{model:{kind:`set`,value:c},reasoning:l==="default"?{kind:`remove`}:{kind:`set`,value:l},gatewayServiceTier:{kind:`keep`}}}))}:{message:d}}catch(e){return{message:`Couldn't change the model: ${toErrorMessage(e)}`}}}if(t.name===`add`&&t.argument.length===0)return{message:`Choose an integration from the inline /add suggestions.`};let i=n.renderer.setupFlow;if(i===void 0)return{message:`/${t.name} is not supported by this renderer.`};let a;try{a=await import(`./setup-commands.js`)}catch(e){return{message:`/${t.name} failed: ${toErrorMessage(e)}`}}let{runTuiSetupCommand:o,SETUP_FLOW_CONFIG:s}=a,c=s[t.name];i.begin(c.title,c.indicator);let l=!0;try{let a={command:t.name,appRoot:r.workspaceRoot,renderer:i,withExclusiveTerminal:n.withExclusiveTerminal,chatGptAccountLabel:n.chatGptAccountLabel};r.agentRoot!==void 0&&(a.agentRoot=r.agentRoot),n.initialModelStep!==void 0&&(a.initialModelStep=n.initialModelStep),n.onOnboardingScreen!==void 0&&(a.onOnboardingScreen=n.onOnboardingScreen),t.name===`add`&&(a.initialRegistryAddress=t.argument),e.flows!==void 0&&(a.flows=e.flows);let s=await o(a);l=s.preserveFlowDiagnostics;let{preserveFlowDiagnostics:c,partial:u,...d}=s;return n.settleOutcome===void 0?d:await n.settleOutcome(d)}finally{i.end({preserveDiagnostics:l})}}}}export{createPromptCommandHandler};
1
+ import{isPromptCommandAvailableFor}from"./prompt-commands.js";import{toErrorMessage}from"#shared/errors.js";const LOGIN_CONNECTIONS={vercel:`vercel`,chatgpt:`chatgpt`,"vercel-api-key":`ai-gateway-key`,"openai-api-key":`openai`,"anthropic-api-key":`anthropic`};function createPromptCommandHandler(e){return{async handle(t,n){let{target:r}=e;if(r.kind===`remote`&&!isPromptCommandAvailableFor(t.name,`remote`))return{message:`/${t.name} needs eve dev running the local server (it is not available with --url).`};if(t.name===`model`){if(t.argument.length===0)return{message:`Choose a model from the inline /model suggestions.`};if(r.kind!==`local`)return{message:`/model needs eve dev running the local server (it is not available with --url).`};let n=r.agentRoot??r.workspaceRoot;try{let{modelChangeRefusalForUneditableModel:r}=await import(`#setup/flows/model.js`),{changeAgentModel:i,changeAgentModelSettings:a,formatApplyModelOutcome:o,formatApplyModelSettingsOutcome:s}=await import(`#setup/flows/model-source-change.js`),[c,l,...u]=t.argument.split(/\s+/u);if(c===void 0||u.length>0||l!==void 0&&![`default`,`none`,`minimal`,`low`,`medium`,`high`,`xhigh`].includes(l))return{message:"Use `/model provider/model [default|none|minimal|low|medium|high|xhigh]`."};let d=await(e.modelChangeRefusal??r)(n);return d===null?l===void 0?{message:o(await(e.applyModel??i)({appRoot:n,slug:c}))}:{message:s(await a({appRoot:n,patch:{model:{kind:`set`,value:c},reasoning:l==="default"?{kind:`remove`}:{kind:`set`,value:l},gatewayServiceTier:{kind:`keep`}}}))}:{message:d}}catch(e){return{message:`Couldn't change the model: ${toErrorMessage(e)}`}}}if(t.name===`add`&&t.argument.length===0)return{message:`Choose an integration from the inline /add suggestions.`};let i=t.name===`login`&&t.argument.length>0?LOGIN_CONNECTIONS[t.argument]:void 0;if(t.name===`login`&&t.argument.length>0&&i===void 0)return{message:"Use `/login vercel|chatgpt|vercel-api-key|openai-api-key|anthropic-api-key`."};let a=n.renderer.setupFlow;if(a===void 0)return{message:`/${t.name} is not supported by this renderer.`};let o;try{o=await import(`./setup-commands.js`)}catch(e){return{message:`/${t.name} failed: ${toErrorMessage(e)}`}}let{runTuiSetupCommand:s,SETUP_FLOW_CONFIG:c}=o,l=c[t.name];a.begin(l.title,l.indicator);let u=!0;try{let o={command:t.name,appRoot:r.workspaceRoot,renderer:a,withExclusiveTerminal:n.withExclusiveTerminal,chatGptAccountLabel:n.chatGptAccountLabel};r.agentRoot!==void 0&&(o.agentRoot=r.agentRoot),n.initialModelStep!==void 0&&(o.initialModelStep=n.initialModelStep),n.onOnboardingScreen!==void 0&&(o.onOnboardingScreen=n.onOnboardingScreen),t.name===`add`&&(o.initialRegistryAddress=t.argument),i!==void 0&&(o.initialLoginConnection=i),e.flows!==void 0&&(o.flows=e.flows);let c=await s(o);u=c.preserveFlowDiagnostics;let{preserveFlowDiagnostics:l,partial:d,...f}=c;return n.settleOutcome===void 0?f:await n.settleOutcome(f)}finally{a.end({preserveDiagnostics:u})}}}}export{createPromptCommandHandler};
@@ -1,2 +1,2 @@
1
- const PROMPT_COMMAND_DEFINITIONS=[{name:`model`,aliases:[],description:`Choose a model, speed, and reasoning`,argumentHint:`[provider/model]`,takesArgument:!0,build:e=>({type:`extension`,name:`model`,argument:e}),targets:[`local`]},{name:`reset`,aliases:[],description:`Start a fresh session`,takesArgument:!1,build:()=>({type:`reset`}),targets:[`local`,`remote`]},{name:`clear`,aliases:[`new`],description:`Clear the current session context`,takesArgument:!1,build:()=>({type:`clear`}),targets:[`local`,`remote`]},{name:`compact`,aliases:[],description:`Compact the current session context`,takesArgument:!1,build:()=>({type:`compact`}),targets:[`local`,`remote`]},{name:`cancel`,aliases:[],description:`Cancel the running turn`,takesArgument:!1,build:()=>({type:`cancel`}),targets:[`local`,`remote`]},{name:`login`,aliases:[],description:`Connect a model provider`,takesArgument:!1,build:()=>({type:`extension`,name:`login`,argument:``}),targets:[`local`]},{name:`add`,aliases:[],description:`Add an integration from the registry`,takesArgument:!0,build:e=>({type:`extension`,name:`add`,argument:e}),targets:[`local`]},{name:`deploy`,aliases:[],description:`Deploy the agent to Vercel`,takesArgument:!1,build:()=>({type:`extension`,name:`deploy`,argument:``}),targets:[`local`]},{name:`traces`,aliases:[],description:`Open the local trace viewer`,argumentHint:`[trace]`,takesArgument:!0,build:e=>({type:`traces`,argument:e}),targets:[`local`]},{name:`loglevel`,aliases:[],description:`Show or hide captured stdout/stderr/sandbox logs`,argumentHint:`[all|stderr|sandbox|none]`,takesArgument:!0,build:e=>({type:`loglevel`,argument:e}),targets:[`local`,`remote`]},{name:`info`,aliases:[],description:`Show application and messaging information`,takesArgument:!1,build:()=>({type:`info`}),targets:[`local`]},{name:`help`,aliases:[],description:`Show available commands`,takesArgument:!1,build:()=>({type:`help`}),targets:[`local`,`remote`]},{name:`exit`,aliases:[`quit`],description:`Quit the TUI`,takesArgument:!1,build:()=>({type:`exit`}),targets:[`local`,`remote`]}],PROMPT_COMMANDS=PROMPT_COMMAND_DEFINITIONS;function promptCommandsFor(e){let t=PROMPT_COMMAND_DEFINITIONS.filter(t=>t.targets.some(t=>t===e));return e===`remote`?[...t.filter(e=>e.name===`help`),...t.filter(e=>e.name!==`help`)]:t}function isPromptCommandAvailableFor(e,t){return(PROMPT_COMMAND_DEFINITIONS.find(t=>t.name===e)?.targets)?.includes(t)??!1}function parsePromptCommand(e){let t=e.trim();if(!t.startsWith(`/`))return null;for(let e of PROMPT_COMMANDS)for(let n of[e.name,...e.aliases]){let r=`/${n}`;if(t===r)return e.build(``);if(e.takesArgument&&t.startsWith(`${r} `))return e.build(t.slice(r.length).trim())}return null}function isPromptControlCommand(e){return parsePromptCommand(e)!==null}function formatPromptCommandHelp(e=PROMPT_COMMANDS){let t=e.map(e=>{let t=e.argumentHint===void 0?``:` ${e.argumentHint}`,n=e.aliases.map(e=>` (/${e})`).join(``);return{invocation:`/${e.name}${t}${n}`,description:e.description}}),n=Math.max(...t.map(e=>e.invocation.length))+2;return t.map(e=>e.invocation.padEnd(n)+e.description).join(`
1
+ const PROMPT_COMMAND_DEFINITIONS=[{name:`model`,aliases:[],description:`Choose a model, speed, and reasoning`,argumentHint:`[provider/model]`,takesArgument:!0,build:e=>({type:`extension`,name:`model`,argument:e}),targets:[`local`]},{name:`reset`,aliases:[],description:`Start a fresh session`,takesArgument:!1,build:()=>({type:`reset`}),targets:[`local`,`remote`]},{name:`clear`,aliases:[`new`],description:`Clear the current session context`,takesArgument:!1,build:()=>({type:`clear`}),targets:[`local`,`remote`]},{name:`compact`,aliases:[],description:`Compact the current session context`,takesArgument:!1,build:()=>({type:`compact`}),targets:[`local`,`remote`]},{name:`cancel`,aliases:[],description:`Cancel the running turn`,takesArgument:!1,build:()=>({type:`cancel`}),targets:[`local`,`remote`]},{name:`login`,aliases:[],description:`Connect a model provider`,argumentHint:`[connection]`,takesArgument:!0,build:e=>({type:`extension`,name:`login`,argument:e}),targets:[`local`]},{name:`add`,aliases:[],description:`Add an integration from the registry`,takesArgument:!0,build:e=>({type:`extension`,name:`add`,argument:e}),targets:[`local`]},{name:`deploy`,aliases:[],description:`Deploy the agent to Vercel`,takesArgument:!1,build:()=>({type:`extension`,name:`deploy`,argument:``}),targets:[`local`]},{name:`traces`,aliases:[],description:`Open the local trace viewer`,argumentHint:`[trace]`,takesArgument:!0,build:e=>({type:`traces`,argument:e}),targets:[`local`]},{name:`loglevel`,aliases:[],description:`Show or hide captured stdout/stderr/sandbox logs`,argumentHint:`[all|stderr|sandbox|none]`,takesArgument:!0,build:e=>({type:`loglevel`,argument:e}),targets:[`local`,`remote`]},{name:`info`,aliases:[],description:`Show application and messaging information`,takesArgument:!1,build:()=>({type:`info`}),targets:[`local`]},{name:`help`,aliases:[],description:`Show available commands`,takesArgument:!1,build:()=>({type:`help`}),targets:[`local`,`remote`]},{name:`exit`,aliases:[`quit`],description:`Quit the TUI`,takesArgument:!1,build:()=>({type:`exit`}),targets:[`local`,`remote`]}],PROMPT_COMMANDS=PROMPT_COMMAND_DEFINITIONS;function promptCommandsFor(e){let t=PROMPT_COMMAND_DEFINITIONS.filter(t=>t.targets.some(t=>t===e));return e===`remote`?[...t.filter(e=>e.name===`help`),...t.filter(e=>e.name!==`help`)]:t}function isPromptCommandAvailableFor(e,t){return(PROMPT_COMMAND_DEFINITIONS.find(t=>t.name===e)?.targets)?.includes(t)??!1}function parsePromptCommand(e){let t=e.trim();if(!t.startsWith(`/`))return null;for(let e of PROMPT_COMMANDS)for(let n of[e.name,...e.aliases]){let r=`/${n}`;if(t===r)return e.build(``);if(e.takesArgument&&t.startsWith(`${r} `))return e.build(t.slice(r.length).trim())}return null}function isPromptControlCommand(e){return parsePromptCommand(e)!==null}function formatPromptCommandHelp(e=PROMPT_COMMANDS){let t=e.map(e=>{let t=e.argumentHint===void 0?``:` ${e.argumentHint}`,n=e.aliases.map(e=>` (/${e})`).join(``);return{invocation:`/${e.name}${t}${n}`,description:e.description}}),n=Math.max(...t.map(e=>e.invocation.length))+2;return t.map(e=>e.invocation.padEnd(n)+e.description).join(`
2
2
  `)}export{PROMPT_COMMANDS,formatPromptCommandHelp,isPromptCommandAvailableFor,isPromptControlCommand,parsePromptCommand,promptCommandsFor};
@@ -1,4 +1,4 @@
1
1
  function registryItemProgress(e){return(t,n,r)=>{e.setNavigation?.(void 0),e.replaceContent?.(),e.setStatus(`Adding ${t.title??t.name} · ${n+1} of ${r}`)}}function registryResultTone(e){if(e.failures.length>0&&e.items.length===0)return`error`;if(!e.outcomes?.some(e=>e.kind===`cancelled`))return e.items.length>0?`success`:void 0}function joinedTitles(e){return e.length===0?``:e.length===1?e[0]:e.length===2?`${e[0]} and ${e[1]}`:`${e.slice(0,-1).join(`, `)}, and ${e.at(-1)}`}function formatFailureMessage(e){return e.replace(" Try again with `",`
2
2
  Try again with \``)}function resultHeadline(e,t){let n=e.filter(e=>e.kind===`failed`).length,r=e.filter(e=>e.kind===`cancelled`).length;if(n===0&&r===0)return`Added ${joinedTitles(t)}`;let i=e.length-n-r,a=[i>0?`${i} added`:void 0,n>0?`${n} failed`:void 0,r>0?`${r} cancelled`:void 0].filter(e=>e!==void 0);return`${e.length} ${e.length===1?`addition`:`additions`}: ${a.join(`, `)}`}function formatRegistrySessionResult(e){let t=e.outcomes??[...e.items.map(e=>({kind:`installed`,...e})),...e.failures.map(e=>({kind:`failed`,...e}))],n=[resultHeadline(t,e.items.map(e=>e.title))];for(let e of t){let t=e.kind===`installed`?`✓`:e.kind===`failed`?`⨯`:`–`;if(n.push(``,` ${t} ${e.title}`),e.kind===`cancelled`){n.push(` Cancelled.`);continue}if(e.kind===`failed`){n.push(...formatFailureMessage(e.message).split(`
3
- `).map(e=>` ${e}`));continue}if(e.facts.length===0&&e.output.length===0){n.push(` Installed.`);continue}let r=Math.max(0,...e.facts.map(e=>e.label.length));for(let t of e.facts)n.push(` ${t.label.padEnd(r)} ${t.value}`);for(let t of e.output)n.push(` ${t}`)}return e.cancelled===!0&&n.push(``,`Setup stopped before the remaining selections were added.`),n.join(`
3
+ `).map(e=>` ${e}`));continue}if(e.facts.length===0&&e.output.length===0){n.push(` Installed.`);continue}let r=e.facts.filter(e=>e.label.length>0),i=Math.max(0,...r.map(e=>e.label.length));for(let t of e.facts)n.push(t.label.length===0?` ${t.value}`:` ${t.label.padEnd(i)} ${t.value}`);for(let t of e.output)n.push(` ${t}`)}return e.cancelled===!0&&n.push(``,`Setup stopped before the remaining selections were added.`),n.join(`
4
4
  `)}export{formatRegistrySessionResult,registryItemProgress,registryResultTone};
@@ -370,8 +370,8 @@ export type EveTUIRunnerOptions = TuiDisplayOptions & {
370
370
  promptCommandHandler?: PromptCommandHandler;
371
371
  /** Commands shown in discovery for this local or remote session. */
372
372
  availablePromptCommands?: readonly PromptCommandSpec[];
373
- /** Catalog entries available to inline `/model` and `/add` completion. */
374
- argumentSuggestions?: (command: "model" | "add") => Promise<readonly PromptArgumentSuggestion[]>;
373
+ /** Catalog entries available to inline `/model`, `/add`, and `/login` completion. */
374
+ argumentSuggestions?: (command: "model" | "add" | "login") => Promise<readonly PromptArgumentSuggestion[]>;
375
375
  /** Gives setup subprocesses exclusive terminal and development-host ownership. */
376
376
  withExclusiveTerminal?: <T>(task: () => Promise<T>) => Promise<T>;
377
377
  /** Remote target and mutable OIDC token source, when connected through `--url`. */
@@ -1,4 +1,4 @@
1
- import type { ModelAccessChange } from "#shared/model-connection.js";
1
+ import type { ModelAccessChange, ModelConnectionSelection } from "#shared/model-connection.js";
2
2
  import { runModelLogin } from "#setup/flows/model-login.js";
3
3
  import { runDeployFlow } from "#setup/flows/deploy.js";
4
4
  import { runInstallVercelCliFlow } from "#setup/flows/install-vercel-cli.js";
@@ -43,6 +43,8 @@ export interface TuiSetupCommandInput {
43
43
  renderer: TuiSetupCommandRenderer;
44
44
  /** Initial model-flow step authorized by the runner's boot evidence. */
45
45
  initialModelStep?: "provider";
46
+ /** Connection selected through `/login <connection>`. */
47
+ initialLoginConnection?: ModelConnectionSelection;
46
48
  /** Registry address supplied by `/add <item>`, confirmed and installed directly. */
47
49
  initialRegistryAddress?: string;
48
50
  /** Presentation and navigation supplied by an enclosing setup journey. */
@@ -1 +1 @@
1
- import{formatRegistrySessionResult,registryItemProgress,registryResultTone}from"./registry-result-message.js";import{createTuiPrompter}from"./tui-prompter.js";import{runDeployFlow}from"#setup/flows/deploy.js";import{WizardCancelledError}from"#setup/step.js";import{runModelLogin}from"#setup/flows/model-login.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{runInstallVercelCliFlow}from"#setup/flows/install-vercel-cli.js";import{RegistryFlowFailedError,runRegistryFlow}from"#setup/flows/registry.js";const SETUP_FLOW_CONFIG={login:{title:`Connecting your model`,indicator:`pulse`},add:{title:`Add to your agent`,indicator:`pulse`},deploy:{title:`Deploy to Vercel`,indicator:`spinner`}};function muteableRenderer(e,t,n){return{readSelect:n=>t()?Promise.resolve(void 0):e.readSelect(n),readEditableSelect:n=>t()?Promise.resolve(void 0):e.readEditableSelect(n),readProviderPicker:n=>t()?Promise.resolve(void 0):e.readProviderPicker(n),readText:n=>t()?Promise.resolve(void 0):e.readText(n),readAcknowledge:n=>t()?Promise.resolve():e.readAcknowledge(n),readChoice:n=>t()?{choice:Promise.resolve(void 0),close:()=>{}}:e.readChoice(n),setNavigation:n=>{t()||e.setNavigation?.(n)},setStatus:n=>{t()||e.setStatus(n)},renderLine:(n,r)=>{(!t()||r===`warning`||r===`error`)&&e.renderLine(n,r)},replaceContent:n=>{t()||e.replaceContent?.(n)},renderOutput:n=>{t()||e.renderOutput(n)},withInheritedStdio:t=>e.withInheritedStdio(t),withExclusiveTerminal:e=>n?.(e)??e()}}function cancelledSetupResult(){return{message:``,cancelled:!0,preserveFlowDiagnostics:!1}}async function runTuiSetupCommand(e){let{command:t}=e,n=!1,r=new AbortController,i=muteableRenderer(e.renderer,()=>n,e.withExclusiveTerminal),a=(e.createPrompter??createTuiPrompter)(i),cancelActiveRegistryItem,runRegistryItem=async e=>{let t=new AbortController;cancelActiveRegistryItem=()=>t.abort(new WizardCancelledError);try{return await e(AbortSignal.any([r.signal,t.signal]))}finally{cancelActiveRegistryItem=void 0}},o=e.renderer.waitForInterrupt(),s=executeSetupCommand(e,a,i,r.signal,runRegistryItem),c=s.then(e=>({kind:`outcome`,value:e}));try{for(;;){let i=!1;try{let e=await Promise.race([c,o.promise.then(e=>({kind:`interrupt`,interrupt:e}))]);if(e.kind===`outcome`)return e.value;if(t===`add`&&e.interrupt===`escape`&&cancelActiveRegistryItem!==void 0)cancelActiveRegistryItem(),i=!0;else{n=!0,r.abort(new WizardCancelledError);let e=await s;return e.partial===!0?e:{...e,...cancelledSetupResult(),tone:void 0}}}finally{o.dispose()}i&&(o=e.renderer.waitForInterrupt())}}finally{e.renderer.setStatus(void 0)}}async function executeSetupCommand(e,t,n,r,i){let{command:a,appRoot:o}=e,s={runInstallVercelCliFlow,runRegistryFlow,runDeployFlow,...e.flows};try{switch(a){case`login`:{let n=await(s.runModelLogin??runModelLogin)({appRoot:o,agentRoot:e.agentRoot,prompter:t,signal:r,automatic:e.initialModelStep===`provider`,withConnectionUpdate:e.withExclusiveTerminal});return n.kind===`cancelled`?{message:`Connect a model with /login when you’re ready.`,cancelled:!0,preserveFlowDiagnostics:!1}:{message:`Connected. Start chatting · /add to extend your agent`,effect:{kind:`model-access-changed`,reload:n.reload,...n.model&&{model:n.model}},preserveFlowDiagnostics:!1}}case`add`:{let a=await s.runRegistryFlow({appRoot:o,installRoot:e.agentRoot,prompter:t,signal:r,initialAddress:e.initialRegistryAddress,onScreen:e.onOnboardingScreen,onItemStart:registryItemProgress(n),runItem:i});if(a.kind===`cancelled`)return cancelledSetupResult();let c=a.result,l=registryResultTone(c),u=c.items.length>0||c.failures.length>0||c.outcomes!==void 0?formatRegistrySessionResult(c):`No integrations selected.`,d={message:l===`error`?`/add failed — ${u}`:u,preserveFlowDiagnostics:!0};return c.cancelled===!0?(d.partial=!0,d.tone=`error`):l!==void 0&&(d.tone=l),c.deployed===`production`&&(d.effect={kind:`deployed`}),d}case`deploy`:{let e=await s.runDeployFlow({appRoot:o,prompter:t,interactive:!0,signal:r});return e.kind===`cancelled`?cancelledSetupResult():e.kind===`needs-link`?{message:`Not linked to a Vercel project. Run eve deploy in an interactive terminal to link it.`,preserveFlowDiagnostics:!0}:e.kind===`local-model`?{message:`ChatGPT subscription models are local-only. Switch to an AI Gateway or server-authenticated model before deploying.`,preserveFlowDiagnostics:!0}:{message:e.productionUrl===void 0?`Deployed.`:`Deployed: ${e.productionUrl}`,preserveFlowDiagnostics:!0,effect:{kind:`deployed`}}}}}catch(e){if(e instanceof WizardCancelledError)return cancelledSetupResult();let n=e instanceof RegistryFlowFailedError?e.cause:e,i=await vercelCliUpgradeOutcome(n,a,s,{appRoot:o,prompter:t,signal:r});if(i!==void 0)return withRegistryResults(i,e);let c=vercelActionOutcome(n,a);return c===void 0?e instanceof RegistryFlowFailedError?{message:`${formatRegistrySessionResult(e.completed)}\n\n${e.message}`,partial:!0,tone:`error`,preserveFlowDiagnostics:!0}:{message:`/${a} failed: ${e instanceof Error?e.message:String(e)}`,tone:`error`,preserveFlowDiagnostics:!0}:withRegistryResults(c,e)}}function withRegistryResults(e,t){return t instanceof RegistryFlowFailedError?{...e,message:`${formatRegistrySessionResult(t.completed)}\n\n${e.message}`,partial:!0,tone:`error`,preserveFlowDiagnostics:!0}:e}async function vercelCliUpgradeOutcome(e,t,n,r){if(!(e instanceof HumanActionRequiredError)||e.action.kind!==`vercel-cli-upgrade`)return;let i;try{i=await r.prompter.select({message:`Your Vercel CLI needs an update to list your teams. Upgrade now?`,options:[{value:`upgrade`,label:`Upgrade Vercel CLI`,description:`Run the Vercel CLI's native upgrader`},{value:`later`,label:`Not now`}],initialValue:`upgrade`})}catch{i=`later`}if(i===`later`)return{message:`The Vercel CLI needs an update — run \`vercel upgrade\`, then retry /${t}.`,tone:`error`,preserveFlowDiagnostics:!0};let a;try{a=await n.runInstallVercelCliFlow({appRoot:r.appRoot,prompter:r.prompter,signal:r.signal,upgrade:!0})}catch(e){return{message:vercelCliUpgradeFailureMessage(t,errorMessage(e)),tone:`error`,preserveFlowDiagnostics:!0}}switch(a.kind){case`installed`:return{message:`Upgraded the Vercel CLI. Retry /${t}.`,tone:`error`,preserveFlowDiagnostics:!1};case`failed`:return{message:vercelCliUpgradeFailureMessage(t,a.reason),tone:`error`,preserveFlowDiagnostics:!0};case`cancelled`:return{message:`Vercel CLI upgrade cancelled — run \`vercel upgrade\`, then retry /${t}.`,tone:`error`,preserveFlowDiagnostics:!0};case`already`:return{message:`The Vercel CLI is already up to date. Retry /${t}.`,tone:`error`,preserveFlowDiagnostics:!1}}}function errorMessage(e){let t=(e instanceof Error?e.message:String(e)).replace(/\s+/gu,` `).trim();return t.length<=240?t:`${t.slice(0,239)}…`}function vercelCliUpgradeFailureMessage(e,t){return`Couldn't upgrade the Vercel CLI${t===void 0||t===``?``:` (${t})`} — run \`vercel upgrade\`, then retry /${e}.`}function vercelActionOutcome(e,t){if(!(e instanceof HumanActionRequiredError))return;let n=vercelActionMessage(e.action.kind,t);return n===void 0?void 0:{message:n,tone:`error`,preserveFlowDiagnostics:!0}}function vercelActionMessage(e,t){switch(e){case`vercel-login`:return`You're not logged in to Vercel — run /deploy to connect your Vercel account, then retry /${t}.`;case`vercel-forbidden`:return`Vercel denied access to that team — check your team access and SSO, then retry /${t}.`;case`vercel-cli-missing`:return`The Vercel CLI isn't installed — run /deploy to install it, then retry /${t}.`;case`vercel-cli-upgrade`:return`The Vercel CLI needs an update — run \`vercel upgrade\`, then retry /${t}.`;default:return}}export{SETUP_FLOW_CONFIG,runTuiSetupCommand};
1
+ import{formatRegistrySessionResult,registryItemProgress,registryResultTone}from"./registry-result-message.js";import{createTuiPrompter}from"./tui-prompter.js";import{runDeployFlow}from"#setup/flows/deploy.js";import{WizardCancelledError}from"#setup/step.js";import{runModelLogin}from"#setup/flows/model-login.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{runInstallVercelCliFlow}from"#setup/flows/install-vercel-cli.js";import{RegistryFlowFailedError,runRegistryFlow}from"#setup/flows/registry.js";const SETUP_FLOW_CONFIG={login:{title:``,indicator:`pulse`},add:{title:``,indicator:`pulse`},deploy:{title:``,indicator:`spinner`}};function muteableRenderer(e,t,n){return{readSelect:n=>t()?Promise.resolve(void 0):e.readSelect(n),readEditableSelect:n=>t()?Promise.resolve(void 0):e.readEditableSelect(n),readProviderPicker:n=>t()?Promise.resolve(void 0):e.readProviderPicker(n),readText:n=>t()?Promise.resolve(void 0):e.readText(n),readAcknowledge:n=>t()?Promise.resolve():e.readAcknowledge(n),readChoice:n=>t()?{choice:Promise.resolve(void 0),close:()=>{}}:e.readChoice(n),setNavigation:n=>{t()||e.setNavigation?.(n)},setStatus:n=>{t()||e.setStatus(n)},renderLine:(n,r)=>{(!t()||r===`warning`||r===`error`)&&e.renderLine(n,r)},replaceContent:n=>{t()||e.replaceContent?.(n)},renderOutput:n=>{t()||e.renderOutput(n)},withInheritedStdio:t=>e.withInheritedStdio(t),withExclusiveTerminal:e=>n?.(e)??e()}}function cancelledSetupResult(){return{message:``,cancelled:!0,preserveFlowDiagnostics:!1}}async function runTuiSetupCommand(e){let{command:t}=e,n=!1,r=new AbortController,i=muteableRenderer(e.renderer,()=>n,e.withExclusiveTerminal),a=(e.createPrompter??createTuiPrompter)(i),cancelActiveRegistryItem,runRegistryItem=async e=>{let t=new AbortController;cancelActiveRegistryItem=()=>t.abort(new WizardCancelledError);try{return await e(AbortSignal.any([r.signal,t.signal]))}finally{cancelActiveRegistryItem=void 0}},o=e.renderer.waitForInterrupt(),s=executeSetupCommand(e,a,i,r.signal,runRegistryItem),c=s.then(e=>({kind:`outcome`,value:e}));try{for(;;){let i=!1;try{let e=await Promise.race([c,o.promise.then(e=>({kind:`interrupt`,interrupt:e}))]);if(e.kind===`outcome`)return e.value;if(t===`add`&&e.interrupt===`escape`&&cancelActiveRegistryItem!==void 0)cancelActiveRegistryItem(),i=!0;else{n=!0,r.abort(new WizardCancelledError);let e=await s;return e.partial===!0?e:{...e,...cancelledSetupResult(),tone:void 0}}}finally{o.dispose()}i&&(o=e.renderer.waitForInterrupt())}}finally{e.renderer.setStatus(void 0)}}async function executeSetupCommand(e,t,n,r,i){let{command:a,appRoot:o}=e,s={runInstallVercelCliFlow,runRegistryFlow,runDeployFlow,...e.flows};try{switch(a){case`login`:{let n=await(s.runModelLogin??runModelLogin)({appRoot:o,agentRoot:e.agentRoot,prompter:t,signal:r,automatic:e.initialModelStep===`provider`,selected:e.initialLoginConnection,connectionMessage:``,withConnectionUpdate:e.withExclusiveTerminal});return n.kind===`cancelled`?{message:`Connect a model with /login when you’re ready.`,cancelled:!0,preserveFlowDiagnostics:!1}:{message:`Connected. Start chatting · /add to extend your agent`,effect:{kind:`model-access-changed`,reload:n.reload,...n.model&&{model:n.model}},preserveFlowDiagnostics:!1}}case`add`:{let a=await s.runRegistryFlow({appRoot:o,installRoot:e.agentRoot,prompter:t,signal:r,initialAddress:e.initialRegistryAddress,onScreen:e.onOnboardingScreen,onItemStart:registryItemProgress(n),runItem:i});if(a.kind===`cancelled`)return cancelledSetupResult();let c=a.result,l=registryResultTone(c),u=c.items.length>0||c.failures.length>0||c.outcomes!==void 0?formatRegistrySessionResult(c):`No integrations selected.`,d={message:l===`error`?`/add failed — ${u}`:u,preserveFlowDiagnostics:!0};return c.cancelled===!0?(d.partial=!0,d.tone=`error`):l!==void 0&&(d.tone=l),c.deployed===`production`&&(d.effect={kind:`deployed`}),d}case`deploy`:{let e=await s.runDeployFlow({appRoot:o,prompter:t,interactive:!0,signal:r});return e.kind===`cancelled`?cancelledSetupResult():e.kind===`needs-link`?{message:`Not linked to a Vercel project. Run eve deploy in an interactive terminal to link it.`,preserveFlowDiagnostics:!0}:e.kind===`local-model`?{message:`ChatGPT subscription models are local-only. Switch to an AI Gateway or server-authenticated model before deploying.`,preserveFlowDiagnostics:!0}:{message:e.productionUrl===void 0?`Deployed.`:`Deployed: ${e.productionUrl}`,preserveFlowDiagnostics:!0,effect:{kind:`deployed`}}}}}catch(e){if(e instanceof WizardCancelledError)return cancelledSetupResult();let n=e instanceof RegistryFlowFailedError?e.cause:e,i=await vercelCliUpgradeOutcome(n,a,s,{appRoot:o,prompter:t,signal:r});if(i!==void 0)return withRegistryResults(i,e);let c=vercelActionOutcome(n,a);return c===void 0?e instanceof RegistryFlowFailedError?{message:`${formatRegistrySessionResult(e.completed)}\n\n${e.message}`,partial:!0,tone:`error`,preserveFlowDiagnostics:!0}:{message:`/${a} failed: ${e instanceof Error?e.message:String(e)}`,tone:`error`,preserveFlowDiagnostics:!0}:withRegistryResults(c,e)}}function withRegistryResults(e,t){return t instanceof RegistryFlowFailedError?{...e,message:`${formatRegistrySessionResult(t.completed)}\n\n${e.message}`,partial:!0,tone:`error`,preserveFlowDiagnostics:!0}:e}async function vercelCliUpgradeOutcome(e,t,n,r){if(!(e instanceof HumanActionRequiredError)||e.action.kind!==`vercel-cli-upgrade`)return;let i;try{i=await r.prompter.select({message:`Your Vercel CLI needs an update to list your teams. Upgrade now?`,options:[{value:`upgrade`,label:`Upgrade Vercel CLI`,description:`Run the Vercel CLI's native upgrader`},{value:`later`,label:`Not now`}],initialValue:`upgrade`})}catch{i=`later`}if(i===`later`)return{message:`The Vercel CLI needs an update — run \`vercel upgrade\`, then retry /${t}.`,tone:`error`,preserveFlowDiagnostics:!0};let a;try{a=await n.runInstallVercelCliFlow({appRoot:r.appRoot,prompter:r.prompter,signal:r.signal,upgrade:!0})}catch(e){return{message:vercelCliUpgradeFailureMessage(t,errorMessage(e)),tone:`error`,preserveFlowDiagnostics:!0}}switch(a.kind){case`installed`:return{message:`Upgraded the Vercel CLI. Retry /${t}.`,tone:`error`,preserveFlowDiagnostics:!1};case`failed`:return{message:vercelCliUpgradeFailureMessage(t,a.reason),tone:`error`,preserveFlowDiagnostics:!0};case`cancelled`:return{message:`Vercel CLI upgrade cancelled — run \`vercel upgrade\`, then retry /${t}.`,tone:`error`,preserveFlowDiagnostics:!0};case`already`:return{message:`The Vercel CLI is already up to date. Retry /${t}.`,tone:`error`,preserveFlowDiagnostics:!1}}}function errorMessage(e){let t=(e instanceof Error?e.message:String(e)).replace(/\s+/gu,` `).trim();return t.length<=240?t:`${t.slice(0,239)}…`}function vercelCliUpgradeFailureMessage(e,t){return`Couldn't upgrade the Vercel CLI${t===void 0||t===``?``:` (${t})`} — run \`vercel upgrade\`, then retry /${e}.`}function vercelActionOutcome(e,t){if(!(e instanceof HumanActionRequiredError))return;let n=vercelActionMessage(e.action.kind,t);return n===void 0?void 0:{message:n,tone:`error`,preserveFlowDiagnostics:!0}}function vercelActionMessage(e,t){switch(e){case`vercel-login`:return`You're not logged in to Vercel — run /deploy to connect your Vercel account, then retry /${t}.`;case`vercel-forbidden`:return`Vercel denied access to that team — check your team access and SSO, then retry /${t}.`;case`vercel-cli-missing`:return`The Vercel CLI isn't installed — run /deploy to install it, then retry /${t}.`;case`vercel-cli-upgrade`:return`The Vercel CLI needs an update — run \`vercel upgrade\`, then retry /${t}.`;default:return}}export{SETUP_FLOW_CONFIG,runTuiSetupCommand};