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.
- package/CHANGELOG.md +17 -0
- package/dist/src/channel/forwarded-principal.d.ts +26 -6
- package/dist/src/channel/forwarded-principal.js +1 -1
- package/dist/src/chunks/{use-eve-agent-BUeSjwIk.js → use-eve-agent-Di1u2zKu.js} +24 -4
- package/dist/src/chunks/{use-eve-agent-ydPlURM4.js → use-eve-agent-PbSMyJ6e.js} +24 -4
- package/dist/src/cli/commands/extension-build.js +1 -1
- package/dist/src/cli/commands/registry-project.d.ts +2 -1
- package/dist/src/cli/commands/registry-project.js +2 -2
- package/dist/src/cli/commands/registry.js +1 -1
- package/dist/src/cli/commands/trace-detail.d.ts +5 -25
- package/dist/src/cli/commands/trace-detail.js +1 -1
- package/dist/src/cli/commands/trace.js +2 -2
- package/dist/src/cli/dev/run-interactive-ui.js +1 -1
- package/dist/src/cli/dev/tui/argument-typeahead.d.ts +1 -1
- package/dist/src/cli/dev/tui/argument-typeahead.js +1 -1
- package/dist/src/cli/dev/tui/prompt-command-handler.js +1 -1
- package/dist/src/cli/dev/tui/prompt-commands.js +1 -1
- package/dist/src/cli/dev/tui/registry-result-message.js +1 -1
- package/dist/src/cli/dev/tui/runner.d.ts +2 -2
- package/dist/src/cli/dev/tui/setup-commands.d.ts +3 -1
- package/dist/src/cli/dev/tui/setup-commands.js +1 -1
- package/dist/src/cli/dev/tui/setup-panel.d.ts +14 -0
- package/dist/src/cli/dev/tui/setup-panel.js +4 -4
- package/dist/src/cli/dev/tui/subagent-pump.d.ts +2 -10
- package/dist/src/cli/dev/tui/subagent-pump.js +1 -1
- package/dist/src/cli/dev/tui/terminal-renderer.d.ts +2 -2
- package/dist/src/cli/dev/tui/terminal-renderer.js +10 -10
- package/dist/src/cli/dev/tui/traces/trace-conversation.js +1 -1
- package/dist/src/cli/dev/tui/tui.js +1 -1
- package/dist/src/client/client-error.js +1 -1
- package/dist/src/client/open-stream.d.ts +3 -2
- package/dist/src/client/open-stream.js +1 -1
- package/dist/src/client/session.d.ts +16 -1
- package/dist/src/client/session.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +1 -1
- package/dist/src/evals/session.d.ts +3 -2
- package/dist/src/evals/session.js +1 -1
- package/dist/src/evals/types.d.ts +8 -2
- package/dist/src/eve-channel/index.js +1 -1
- package/dist/src/eve-channel/types.d.ts +12 -4
- package/dist/src/execution/cancel-indexed-session-tasks-step.js +1 -1
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/proxied-deliver-step.js +1 -1
- package/dist/src/execution/route-child-delivery.js +2 -2
- package/dist/src/execution/session/admission.js +1 -1
- package/dist/src/execution/session/finalization.js +1 -1
- package/dist/src/execution/session/handoff-steps.js +1 -1
- package/dist/src/execution/session/input-queue.d.ts +12 -10
- package/dist/src/execution/session/input-queue.js +1 -1
- package/dist/src/execution/session/next-input.js +1 -1
- package/dist/src/execution/session/program.js +1 -1
- package/dist/src/execution/session/turn-step-result.d.ts +3 -1
- package/dist/src/execution/session/turn-step-result.js +1 -1
- package/dist/src/execution/session/turn-step-types.d.ts +7 -2
- package/dist/src/execution/session/turn-step.js +1 -1
- package/dist/src/execution/session/turn.js +1 -1
- package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
- package/dist/src/execution/tasks/parent/control-shared.js +1 -1
- package/dist/src/execution/tasks/parent/dispatch.js +1 -1
- package/dist/src/execution/tasks/parent/hitl-proxy-steps.d.ts +1 -0
- package/dist/src/execution/tasks/parent/hitl-proxy-steps.js +1 -1
- package/dist/src/execution/tasks/parent/tool-execution.js +1 -1
- package/dist/src/execution/tools/agent-router-workflow.js +1 -1
- package/dist/src/execution/tools/ask-question-workflow.js +1 -1
- package/dist/src/execution/tools/sleep-workflow.js +1 -1
- package/dist/src/execution/tools/subagent/accept-event-step.js +1 -1
- package/dist/src/execution/tools/subagent/invoke-preparation.js +1 -1
- package/dist/src/execution/tools/subagent/invoke-step.js +1 -1
- package/dist/src/execution/tools/subagent/task-cancel.d.ts +1 -1
- package/dist/src/execution/tools/subagent/task-cancel.js +1 -1
- package/dist/src/harness/session-limit-enforcement.js +1 -1
- package/dist/src/harness/tool-loop.js +2 -2
- package/dist/src/harness/turn-tag-state.d.ts +2 -2
- package/dist/src/harness/workflow-tool-runs.d.ts +33 -5
- package/dist/src/harness/workflow-tool-runs.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/nitro/host/build-extension.js +1 -1
- package/dist/src/internal/nitro/host/extension-build-lock.d.ts +9 -0
- package/dist/src/internal/nitro/host/extension-build-lock.js +1 -0
- package/dist/src/internal/nitro/host/prepare-application-host.d.ts +5 -4
- package/dist/src/internal/nitro/host/prepare-application-host.js +1 -1
- package/dist/src/internal/nitro/host/types.d.ts +2 -2
- package/dist/src/internal/nitro/host/workspace-extensions.d.ts +31 -0
- package/dist/src/internal/nitro/host/workspace-extensions.js +1 -0
- package/dist/src/public/next/index.d.ts +10 -7
- package/dist/src/public/next/index.js +1 -1
- package/dist/src/public/next/server.d.ts +3 -0
- package/dist/src/public/next/server.js +2 -2
- package/dist/src/self-modification/extension/local-only.d.ts +5 -0
- package/dist/src/self-modification/extension/local-only.js +1 -0
- package/dist/src/self-modification/extension/subagents/agent/instructions.js +6 -6
- package/dist/src/self-modification/extension/subagents/agent/skills/trace_analysis.d.ts +10 -0
- package/dist/src/self-modification/extension/subagents/agent/skills/trace_analysis.js +19 -0
- package/dist/src/self-modification/extension/subagents/agent/tools/inspect_trace.d.ts +128 -0
- package/dist/src/self-modification/extension/subagents/agent/tools/inspect_trace.js +1 -0
- package/dist/src/self-modification/extension/subagents/agent/tools/inspect_trace_spans.d.ts +80 -0
- package/dist/src/self-modification/extension/subagents/agent/tools/inspect_trace_spans.js +1 -0
- package/dist/src/self-modification/extension/subagents/agent/tools/registry_add.js +1 -1
- package/dist/src/self-modification/extension/subagents/agent/tools/search_traces.d.ts +53 -0
- package/dist/src/self-modification/extension/subagents/agent/tools/search_traces.js +1 -0
- package/dist/src/self-modification/extension/trace-inspection.d.ts +15 -0
- package/dist/src/self-modification/extension/trace-inspection.js +1 -0
- package/dist/src/self-modification/sandbox.js +1 -1
- package/dist/src/setup/ask.d.ts +2 -0
- package/dist/src/setup/ask.js +1 -1
- package/dist/src/setup/cli/option-row.d.ts +3 -1
- package/dist/src/setup/cli/option-row.js +1 -1
- package/dist/src/setup/flows/model-login.d.ts +4 -0
- package/dist/src/setup/flows/model-login.js +1 -1
- package/dist/src/setup/integrations/web/setup.d.ts +15 -10
- package/dist/src/setup/integrations/web/setup.js +30 -1
- package/dist/src/setup/scaffold/create/project.js +2 -2
- package/dist/src/setup/scaffold/create/web-template.d.ts +7 -3
- package/dist/src/setup/scaffold/create/web-template.js +39 -20
- package/dist/src/setup/scaffold/update/channels.js +2 -2
- package/dist/src/subagents/parent-notification.d.ts +1 -1
- package/dist/src/subagents/remote-dispatch.d.ts +1 -0
- package/dist/src/subagents/remote-dispatch.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/tasks/delivery-context.js +2 -2
- package/dist/src/tasks/notification.d.ts +6 -0
- package/dist/src/tasks/notification.js +1 -1
- package/dist/src/tracing/agent-trace-context-store.js +1 -1
- package/dist/src/tracing/local-trace-analysis.d.ts +51 -0
- package/dist/src/tracing/local-trace-analysis.js +1 -0
- package/dist/src/tracing/local-trace-discovery-index.d.ts +15 -0
- package/dist/src/tracing/local-trace-discovery-index.js +1 -0
- package/dist/src/tracing/local-trace-operations.d.ts +13 -0
- package/dist/src/tracing/local-trace-operations.js +1 -0
- package/dist/src/tracing/local-trace-query.d.ts +17 -0
- package/dist/src/tracing/local-trace-query.js +1 -0
- package/dist/src/tracing/local-trace-span-processor.js +1 -1
- package/dist/src/tracing/local-trace-summary.d.ts +31 -0
- package/dist/src/tracing/local-trace-summary.js +1 -0
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/concepts/project-structure.mdx +2 -4
- package/docs/concepts/sessions-runs-and-streaming.md +2 -2
- package/docs/evals/cases.mdx +1 -0
- package/docs/extensions.md +3 -1
- package/docs/guides/auth-and-route-protection.md +33 -1
- package/docs/guides/client/streaming.mdx +26 -0
- package/docs/guides/deployment/vercel.mdx +3 -5
- package/docs/guides/frontend/nextjs.mdx +20 -7
- package/docs/guides/frontend/overview.mdx +1 -1
- package/docs/guides/remote-agents.md +3 -1
- package/docs/install-integrations.mdx +1 -1
- package/docs/reference/cli.md +1 -1
- package/docs/subagents/index.mdx +8 -2
- package/package.json +1 -1
- package/dist/src/internal/nitro/host/dev-workspace-extensions.d.ts +0 -18
- package/dist/src/internal/nitro/host/dev-workspace-extensions.js +0 -1
- package/dist/src/tasks/session-task-cohorts.d.ts +0 -7
- 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
|
-
*
|
|
21
|
-
*
|
|
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
|
|
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
|
|
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{
|
|
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 =
|
|
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,
|
|
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 =
|
|
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,
|
|
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
|
-
|
|
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
|
|
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,
|
|
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
|
|
3
|
-
*
|
|
4
|
-
*
|
|
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
|
-
|
|
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{
|
|
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
|
|
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:
|
|
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,
|
|
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`:`
|
|
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(
|
|
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
|
+
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,...
|
|
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
|
|
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
|
|
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};
|