eve 0.66.0 → 0.66.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/src/channel/forwarded-principal.d.ts +26 -6
  3. package/dist/src/channel/forwarded-principal.js +1 -1
  4. package/dist/src/chunks/{use-eve-agent-BUeSjwIk.js → use-eve-agent-Di1u2zKu.js} +24 -4
  5. package/dist/src/chunks/{use-eve-agent-ydPlURM4.js → use-eve-agent-PbSMyJ6e.js} +24 -4
  6. package/dist/src/cli/commands/deploy.d.ts +3 -1
  7. package/dist/src/cli/commands/deploy.js +1 -1
  8. package/dist/src/cli/commands/extension-build.js +1 -1
  9. package/dist/src/cli/commands/integration-connect.js +1 -1
  10. package/dist/src/cli/commands/register-project-commands.js +1 -1
  11. package/dist/src/cli/commands/registry-project.d.ts +2 -1
  12. package/dist/src/cli/commands/registry-project.js +2 -2
  13. package/dist/src/cli/commands/registry.js +1 -1
  14. package/dist/src/cli/commands/trace-detail.d.ts +5 -25
  15. package/dist/src/cli/commands/trace-detail.js +1 -1
  16. package/dist/src/cli/commands/trace.js +2 -2
  17. package/dist/src/cli/commands/vercel-non-interactive.d.ts +7 -0
  18. package/dist/src/cli/commands/vercel-non-interactive.js +1 -1
  19. package/dist/src/cli/dev/run-interactive-ui.js +1 -1
  20. package/dist/src/cli/dev/tui/argument-typeahead.d.ts +1 -1
  21. package/dist/src/cli/dev/tui/argument-typeahead.js +1 -1
  22. package/dist/src/cli/dev/tui/prompt-command-handler.js +1 -1
  23. package/dist/src/cli/dev/tui/prompt-commands.js +1 -1
  24. package/dist/src/cli/dev/tui/registry-result-message.js +1 -1
  25. package/dist/src/cli/dev/tui/remote-auth.js +1 -1
  26. package/dist/src/cli/dev/tui/runner.d.ts +2 -2
  27. package/dist/src/cli/dev/tui/runner.js +1 -1
  28. package/dist/src/cli/dev/tui/setup-commands.d.ts +3 -1
  29. package/dist/src/cli/dev/tui/setup-commands.js +1 -1
  30. package/dist/src/cli/dev/tui/setup-panel.d.ts +14 -0
  31. package/dist/src/cli/dev/tui/setup-panel.js +4 -4
  32. package/dist/src/cli/dev/tui/subagent-pump.d.ts +2 -10
  33. package/dist/src/cli/dev/tui/subagent-pump.js +1 -1
  34. package/dist/src/cli/dev/tui/terminal-renderer.d.ts +2 -2
  35. package/dist/src/cli/dev/tui/terminal-renderer.js +10 -10
  36. package/dist/src/cli/dev/tui/traces/trace-conversation.js +1 -1
  37. package/dist/src/cli/dev/tui/tui.js +1 -1
  38. package/dist/src/client/client-error.js +1 -1
  39. package/dist/src/client/open-stream.d.ts +3 -2
  40. package/dist/src/client/open-stream.js +1 -1
  41. package/dist/src/client/session.d.ts +16 -1
  42. package/dist/src/client/session.js +1 -1
  43. package/dist/src/compiled/.vendor-stamp.json +1 -1
  44. package/dist/src/discover/filesystem.d.ts +2 -0
  45. package/dist/src/discover/filesystem.js +1 -1
  46. package/dist/src/discover/grammar.d.ts +4 -2
  47. package/dist/src/discover/grammar.js +1 -1
  48. package/dist/src/discover/sandbox.js +1 -1
  49. package/dist/src/evals/session.d.ts +3 -2
  50. package/dist/src/evals/session.js +1 -1
  51. package/dist/src/evals/types.d.ts +8 -2
  52. package/dist/src/eve-channel/index.js +1 -1
  53. package/dist/src/eve-channel/types.d.ts +12 -4
  54. package/dist/src/execution/cancel-indexed-session-tasks-step.js +1 -1
  55. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  56. package/dist/src/execution/proxied-deliver-step.js +1 -1
  57. package/dist/src/execution/route-child-delivery.js +2 -2
  58. package/dist/src/execution/session/admission.js +1 -1
  59. package/dist/src/execution/session/finalization.js +1 -1
  60. package/dist/src/execution/session/handoff-steps.js +1 -1
  61. package/dist/src/execution/session/input-queue.d.ts +12 -10
  62. package/dist/src/execution/session/input-queue.js +1 -1
  63. package/dist/src/execution/session/next-input.js +1 -1
  64. package/dist/src/execution/session/program.js +1 -1
  65. package/dist/src/execution/session/turn-step-result.d.ts +3 -1
  66. package/dist/src/execution/session/turn-step-result.js +1 -1
  67. package/dist/src/execution/session/turn-step-types.d.ts +7 -2
  68. package/dist/src/execution/session/turn-step.js +1 -1
  69. package/dist/src/execution/session/turn.js +1 -1
  70. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  71. package/dist/src/execution/tasks/parent/control-shared.js +1 -1
  72. package/dist/src/execution/tasks/parent/dispatch.js +1 -1
  73. package/dist/src/execution/tasks/parent/hitl-proxy-steps.d.ts +1 -0
  74. package/dist/src/execution/tasks/parent/hitl-proxy-steps.js +1 -1
  75. package/dist/src/execution/tasks/parent/tool-execution.js +1 -1
  76. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  77. package/dist/src/execution/tools/ask-question-workflow.js +1 -1
  78. package/dist/src/execution/tools/sleep-workflow.js +1 -1
  79. package/dist/src/execution/tools/subagent/accept-event-step.js +1 -1
  80. package/dist/src/execution/tools/subagent/invoke-preparation.js +1 -1
  81. package/dist/src/execution/tools/subagent/invoke-step.js +1 -1
  82. package/dist/src/execution/tools/subagent/task-cancel.d.ts +1 -1
  83. package/dist/src/execution/tools/subagent/task-cancel.js +1 -1
  84. package/dist/src/harness/session-limit-enforcement.js +1 -1
  85. package/dist/src/harness/tool-loop.js +2 -2
  86. package/dist/src/harness/turn-tag-state.d.ts +2 -2
  87. package/dist/src/harness/workflow-tool-runs.d.ts +33 -5
  88. package/dist/src/harness/workflow-tool-runs.js +1 -1
  89. package/dist/src/internal/application/package.js +1 -1
  90. package/dist/src/internal/instrumentation-layout.js +1 -1
  91. package/dist/src/internal/model-auth/vercel-cli.d.ts +2 -0
  92. package/dist/src/internal/model-auth/vercel-cli.js +1 -1
  93. package/dist/src/internal/nitro/host/build-extension.js +1 -1
  94. package/dist/src/internal/nitro/host/extension-build-lock.d.ts +9 -0
  95. package/dist/src/internal/nitro/host/extension-build-lock.js +1 -0
  96. package/dist/src/internal/nitro/host/extension-capability-requirements.d.ts +1 -0
  97. package/dist/src/internal/nitro/host/extension-capability-requirements.js +1 -1
  98. package/dist/src/internal/nitro/host/extension-declarations.js +1 -1
  99. package/dist/src/internal/nitro/host/extension-distribution.js +1 -1
  100. package/dist/src/internal/nitro/host/extension-state-usage.d.ts +2 -2
  101. package/dist/src/internal/nitro/host/extension-state-usage.js +1 -1
  102. package/dist/src/internal/nitro/host/prepare-application-host.d.ts +5 -4
  103. package/dist/src/internal/nitro/host/prepare-application-host.js +1 -1
  104. package/dist/src/internal/nitro/host/types.d.ts +2 -2
  105. package/dist/src/internal/nitro/host/workspace-extensions.d.ts +31 -0
  106. package/dist/src/internal/nitro/host/workspace-extensions.js +1 -0
  107. package/dist/src/public/next/index.d.ts +10 -7
  108. package/dist/src/public/next/index.js +1 -1
  109. package/dist/src/public/next/server.d.ts +3 -0
  110. package/dist/src/public/next/server.js +2 -2
  111. package/dist/src/self-modification/extension/local-only.d.ts +5 -0
  112. package/dist/src/self-modification/extension/local-only.js +1 -0
  113. package/dist/src/self-modification/extension/subagents/agent/instructions.js +6 -6
  114. package/dist/src/self-modification/extension/subagents/agent/skills/trace_analysis.d.ts +10 -0
  115. package/dist/src/self-modification/extension/subagents/agent/skills/trace_analysis.js +19 -0
  116. package/dist/src/self-modification/extension/subagents/agent/tools/inspect_trace.d.ts +128 -0
  117. package/dist/src/self-modification/extension/subagents/agent/tools/inspect_trace.js +1 -0
  118. package/dist/src/self-modification/extension/subagents/agent/tools/inspect_trace_spans.d.ts +80 -0
  119. package/dist/src/self-modification/extension/subagents/agent/tools/inspect_trace_spans.js +1 -0
  120. package/dist/src/self-modification/extension/subagents/agent/tools/registry_add.js +1 -1
  121. package/dist/src/self-modification/extension/subagents/agent/tools/search_traces.d.ts +53 -0
  122. package/dist/src/self-modification/extension/subagents/agent/tools/search_traces.js +1 -0
  123. package/dist/src/self-modification/extension/trace-inspection.d.ts +15 -0
  124. package/dist/src/self-modification/extension/trace-inspection.js +1 -0
  125. package/dist/src/self-modification/sandbox.js +1 -1
  126. package/dist/src/setup/ask.d.ts +2 -0
  127. package/dist/src/setup/ask.js +1 -1
  128. package/dist/src/setup/boxes/link-project.d.ts +2 -0
  129. package/dist/src/setup/boxes/link-project.js +1 -1
  130. package/dist/src/setup/cli/option-row.d.ts +3 -1
  131. package/dist/src/setup/cli/option-row.js +1 -1
  132. package/dist/src/setup/flows/deploy.d.ts +1 -0
  133. package/dist/src/setup/flows/deploy.js +1 -1
  134. package/dist/src/setup/flows/install-vercel-cli.js +1 -1
  135. package/dist/src/setup/flows/login.js +1 -1
  136. package/dist/src/setup/flows/model-login-connection.js +1 -1
  137. package/dist/src/setup/flows/model-login.d.ts +4 -0
  138. package/dist/src/setup/flows/model-login.js +1 -1
  139. package/dist/src/setup/flows/vercel-model-login.js +1 -1
  140. package/dist/src/setup/integrations/runner.js +1 -1
  141. package/dist/src/setup/integrations/web/setup.d.ts +15 -10
  142. package/dist/src/setup/integrations/web/setup.js +30 -1
  143. package/dist/src/setup/scaffold/create/project.js +2 -2
  144. package/dist/src/setup/scaffold/create/web-template.d.ts +7 -3
  145. package/dist/src/setup/scaffold/create/web-template.js +39 -20
  146. package/dist/src/setup/scaffold/update/channels.js +2 -2
  147. package/dist/src/setup/slackbot.js +1 -1
  148. package/dist/src/setup/vercel-project.d.ts +2 -0
  149. package/dist/src/setup/vercel-project.js +0 -0
  150. package/dist/src/setup/vercel-trace-sampling.d.ts +3 -0
  151. package/dist/src/setup/vercel-trace-sampling.js +1 -0
  152. package/dist/src/subagents/parent-notification.d.ts +1 -1
  153. package/dist/src/subagents/remote-dispatch.d.ts +1 -0
  154. package/dist/src/subagents/remote-dispatch.js +1 -1
  155. package/dist/src/svelte/index.js +1 -1
  156. package/dist/src/svelte/use-eve-agent.js +1 -1
  157. package/dist/src/tasks/delivery-context.js +2 -2
  158. package/dist/src/tasks/notification.d.ts +6 -0
  159. package/dist/src/tasks/notification.js +1 -1
  160. package/dist/src/tracing/agent-trace-context-store.js +1 -1
  161. package/dist/src/tracing/local-trace-analysis.d.ts +51 -0
  162. package/dist/src/tracing/local-trace-analysis.js +1 -0
  163. package/dist/src/tracing/local-trace-discovery-index.d.ts +15 -0
  164. package/dist/src/tracing/local-trace-discovery-index.js +1 -0
  165. package/dist/src/tracing/local-trace-operations.d.ts +13 -0
  166. package/dist/src/tracing/local-trace-operations.js +1 -0
  167. package/dist/src/tracing/local-trace-query.d.ts +17 -0
  168. package/dist/src/tracing/local-trace-query.js +1 -0
  169. package/dist/src/tracing/local-trace-span-processor.js +1 -1
  170. package/dist/src/tracing/local-trace-summary.d.ts +31 -0
  171. package/dist/src/tracing/local-trace-summary.js +1 -0
  172. package/dist/src/vue/index.js +1 -1
  173. package/dist/src/vue/use-eve-agent.js +1 -1
  174. package/docs/concepts/project-structure.mdx +2 -4
  175. package/docs/concepts/sessions-runs-and-streaming.md +2 -2
  176. package/docs/evals/cases.mdx +1 -0
  177. package/docs/extensions.md +3 -1
  178. package/docs/guides/auth-and-route-protection.md +33 -1
  179. package/docs/guides/client/streaming.mdx +26 -0
  180. package/docs/guides/deployment/vercel.mdx +5 -5
  181. package/docs/guides/frontend/nextjs.mdx +20 -7
  182. package/docs/guides/frontend/overview.mdx +1 -1
  183. package/docs/guides/instrumentation/agent-runs.mdx +4 -4
  184. package/docs/guides/remote-agents.md +3 -1
  185. package/docs/install-integrations.mdx +1 -1
  186. package/docs/reference/agent-files.md +16 -0
  187. package/docs/reference/cli.md +1 -1
  188. package/docs/subagents/index.mdx +8 -2
  189. package/package.json +1 -1
  190. package/dist/src/internal/nitro/host/dev-workspace-extensions.d.ts +0 -18
  191. package/dist/src/internal/nitro/host/dev-workspace-extensions.js +0 -1
  192. package/dist/src/tasks/session-task-cohorts.d.ts +0 -7
  193. package/dist/src/tasks/session-task-cohorts.js +0 -1
@@ -0,0 +1,51 @@
1
+ import type { LocalTraceSpan } from "#tracing/local-trace-reader.js";
2
+ import { type LocalTraceSummary } from "#tracing/local-trace-summary.js";
3
+ export interface TraceAnalysisSelector {
4
+ readonly excludeSessionId?: string;
5
+ readonly fromMs?: number;
6
+ readonly sessionId?: string;
7
+ readonly toMs?: number;
8
+ readonly turnId?: string;
9
+ }
10
+ export interface TraceTokenUsage {
11
+ readonly inputTokens?: number;
12
+ readonly outputTokens?: number;
13
+ readonly cacheReadTokens?: number;
14
+ readonly cacheWriteTokens?: number;
15
+ }
16
+ export interface TraceTimelineRecord {
17
+ readonly actionDurationMs?: number;
18
+ readonly actionName?: string;
19
+ readonly callId?: string;
20
+ readonly category: "model" | "other" | "tool";
21
+ readonly durationMs: number;
22
+ readonly endOffsetMs: number;
23
+ readonly error?: string;
24
+ readonly model?: string;
25
+ readonly outcome: "completed" | "failed";
26
+ readonly parentSpanId?: string;
27
+ readonly sessionId?: string;
28
+ readonly spanId: string;
29
+ readonly startOffsetMs: number;
30
+ readonly toolName?: string;
31
+ readonly turnId?: string;
32
+ readonly usage?: TraceTokenUsage;
33
+ }
34
+ export interface TraceAnalysis {
35
+ readonly summary: LocalTraceSummary;
36
+ readonly groups: readonly TraceAnalysisGroup[];
37
+ /** Accumulated operation time, not elapsed time; parallel calls can overlap. */
38
+ readonly modelWorkMs: number;
39
+ readonly toolWorkMs: number;
40
+ readonly records: readonly TraceTimelineRecord[];
41
+ }
42
+ export interface TraceAnalysisGroup {
43
+ readonly modelWorkMs: number;
44
+ readonly modelCalls: number;
45
+ readonly sessionId?: string;
46
+ readonly toolWorkMs: number;
47
+ readonly toolCalls: number;
48
+ readonly turnId?: string;
49
+ }
50
+ /** Builds the detailed timeline only when inspection, rather than search, needs it. */
51
+ export declare function analyzeLocalTrace(traceId: string, spans: readonly LocalTraceSpan[], selector?: TraceAnalysisSelector): TraceAnalysis;
@@ -0,0 +1 @@
1
+ import{summarizeLocalTrace}from"#tracing/local-trace-summary.js";import{localTraceOperations,traceModelName,traceSessionId,traceStringAttribute,traceToolName,uniqueLocalTraceSpans}from"#tracing/local-trace-operations.js";function analyzeLocalTrace(e,t,n={}){let r=uniqueLocalTraceSpans(t),i=new Map(localTraceOperations(r).map(({span:e})=>[e.spanId,e])),a=r.filter(e=>matches(i.get(e.spanId)??e,n)),o=a.reduce((e,t)=>t.startTimeNs<e?t.startTimeNs:e,a[0]?.startTimeNs??0n),s=localTraceOperations(a).map(e=>recordFor(e,o)).sort((e,t)=>e.startOffsetMs-t.startOffsetMs||e.endOffsetMs-t.endOffsetMs||e.spanId.localeCompare(t.spanId));return{summary:summarizeLocalTrace(e,a),groups:groups(s),modelWorkMs:sum(s,`model`),toolWorkMs:sum(s,`tool`),records:s}}function matches(e,t){let n=traceSessionId(e),r=traceStringAttribute(e,`agent.turn.id`);if(t.excludeSessionId!==void 0&&n===t.excludeSessionId||t.sessionId!==void 0&&n!==t.sessionId||t.turnId!==void 0&&r!==t.turnId)return!1;let i=Number(e.startTimeNs/1000000n);return(t.fromMs===void 0||i>=t.fromMs)&&(t.toMs===void 0||i<=t.toMs)}function recordFor(e,t){let{span:n,category:r}=e,i={category:r,durationMs:Number(n.endTimeNs-n.startTimeNs)/1e6,endOffsetMs:Number(n.endTimeNs-t)/1e6,outcome:n.statusCode===2?`failed`:`completed`,spanId:n.spanId,startOffsetMs:Number(n.startTimeNs-t)/1e6},a=traceStringAttribute(n,`agent.action.call_id`),o=traceModelName(n),s=traceSessionId(n),c=traceToolName(n),l=traceStringAttribute(n,`agent.turn.id`);if(a!==void 0&&(i.callId=a),n.statusMessage!==void 0&&(i.error=n.statusMessage),o!==void 0&&(i.model=o),n.parentSpanId!==void 0&&(i.parentSpanId=n.parentSpanId),s!==void 0&&(i.sessionId=s),c!==void 0&&r===`tool`&&(i.toolName=c),c!==void 0&&r===`other`&&(i.actionName=c),l!==void 0&&(i.turnId=l),e.actionDurationMs!==void 0&&(i.actionDurationMs=e.actionDurationMs),r===`model`){let e={};for(let[t,r]of Object.entries({inputTokens:`agent.usage.input_tokens`,outputTokens:`agent.usage.output_tokens`,cacheReadTokens:`agent.usage.cache_read_tokens`,cacheWriteTokens:`agent.usage.cache_write_tokens`})){let i=n.attributes[r];typeof i==`number`&&Number.isFinite(i)&&i>=0&&(e[t]=i)}Object.keys(e).length>0&&(i.usage=e)}return i}function groups(e){let t=new Map;for(let n of e){let e=JSON.stringify([n.sessionId,n.turnId]),r=t.get(e);r===void 0&&(r={modelCalls:0,modelWorkMs:0,toolCalls:0,toolWorkMs:0},n.sessionId!==void 0&&(r.sessionId=n.sessionId),n.turnId!==void 0&&(r.turnId=n.turnId),t.set(e,r)),n.category===`model`&&(r.modelCalls+=1,r.modelWorkMs+=n.durationMs),n.category===`tool`&&(r.toolCalls+=1,r.toolWorkMs+=n.durationMs)}return[...t.values()]}function sum(e,t){return e.reduce((e,n)=>e+(n.category===t?n.durationMs:0),0)}export{analyzeLocalTrace};
@@ -0,0 +1,15 @@
1
+ /** A path-safe, non-reversible key for one recorded conversation identifier. */
2
+ export declare function localTraceConversationIndexKey(conversationId: string): string;
3
+ /** Marker path relative to one trace directory. */
4
+ export declare function localTraceConversationMarker(conversationId: string): string;
5
+ /** Marker proving that a trace was written by an index-aware writer. */
6
+ export declare function localTraceIndexedMarker(): string;
7
+ /**
8
+ * Records conversation membership without rewriting shared state. Empty marker
9
+ * creation is idempotent, so overlapping dev workers cannot lose each other's
10
+ * conversation entries.
11
+ */
12
+ export declare function indexLocalTraceConversation(input: {
13
+ readonly conversationId: string;
14
+ readonly traceDirectory: string;
15
+ }): Promise<void>;
@@ -0,0 +1 @@
1
+ import{createHash}from"node:crypto";import{mkdir,writeFile}from"node:fs/promises";import{join}from"node:path";const INDEX_DIRECTORY=`index/v1`,CONVERSATIONS_DIRECTORY=`${INDEX_DIRECTORY}/conversations`,INDEXED_MARKER=`${INDEX_DIRECTORY}/indexed`;function localTraceConversationIndexKey(e){return createHash(`sha256`).update(e).digest(`hex`)}function localTraceConversationMarker(e){return`${CONVERSATIONS_DIRECTORY}/${localTraceConversationIndexKey(e)}`}function localTraceIndexedMarker(){return INDEXED_MARKER}async function indexLocalTraceConversation(e){let t=join(e.traceDirectory,localTraceConversationMarker(e.conversationId));await mkdir(join(e.traceDirectory,CONVERSATIONS_DIRECTORY),{recursive:!0}),await createMarker(t),await createMarker(join(e.traceDirectory,INDEXED_MARKER))}async function createMarker(e){try{await writeFile(e,``,{flag:`wx`})}catch(e){if(!isAlreadyPresent(e))throw e}}function isAlreadyPresent(e){return e instanceof Error&&`code`in e&&e.code===`EEXIST`}export{indexLocalTraceConversation,localTraceConversationIndexKey,localTraceConversationMarker,localTraceIndexedMarker};
@@ -0,0 +1,13 @@
1
+ import type { LocalTraceSpan } from "#tracing/local-trace-reader.js";
2
+ export interface LocalTraceOperation {
3
+ readonly span: LocalTraceSpan;
4
+ readonly category: "model" | "other" | "tool";
5
+ readonly actionDurationMs?: number;
6
+ }
7
+ export declare function uniqueLocalTraceSpans(spans: readonly LocalTraceSpan[]): LocalTraceSpan[];
8
+ /** Pairs action wrappers with execution spans without constructing a sorted timeline. */
9
+ export declare function localTraceOperations(spans: readonly LocalTraceSpan[]): LocalTraceOperation[];
10
+ export declare function traceModelName(span: LocalTraceSpan): string | undefined;
11
+ export declare function traceToolName(span: LocalTraceSpan): string | undefined;
12
+ export declare function traceSessionId(span: LocalTraceSpan): string | undefined;
13
+ export declare function traceStringAttribute(span: LocalTraceSpan, key: string): string | undefined;
@@ -0,0 +1 @@
1
+ function uniqueLocalTraceSpans(e){let t=new Map;for(let n of e)t.has(n.spanId)||t.set(n.spanId,n);return[...t.values()]}function localTraceOperations(e){let t=new Map(e.map(e=>[e.spanId,e])),n=new Set,r=[];for(let i of e){let e=categoryFor(i);if(e===void 0)continue;let a=i.parentSpanId===void 0?void 0:t.get(i.parentSpanId);i.attributes[`gen_ai.operation.name`]===`execute_tool`&&a?.name===`agent.action`&&traceToolName(a)===traceToolName(i)?(n.add(a.spanId),r.push({category:e,span:{...i,attributes:{...a.attributes,...i.attributes},parentSpanId:a.parentSpanId,statusCode:a.statusCode===2?a.statusCode:i.statusCode,statusMessage:a.statusCode===2?a.statusMessage:i.statusMessage},...a.attributes[`agent.action.kind`]===`subagent-call`?{actionDurationMs:Number(a.endTimeNs-a.startTimeNs)/1e6}:{}})):r.push({category:e,span:i})}return r.filter(({span:e})=>!n.has(e.spanId))}function categoryFor(e){if(e.attributes[`gen_ai.operation.name`]===`chat`)return`model`;if(e.attributes[`gen_ai.operation.name`]===`execute_tool`)return`tool`;if(e.name===`agent.action`)return e.attributes[`agent.action.kind`]===`tool-call`?`tool`:`other`}function traceModelName(e){return traceStringAttribute(e,`agent.model.id`)??traceStringAttribute(e,`gen_ai.request.model`)}function traceToolName(e){return traceStringAttribute(e,`gen_ai.tool.name`)??traceStringAttribute(e,`agent.action.name`)}function traceSessionId(e){return traceStringAttribute(e,`agent.run.id`)??traceStringAttribute(e,`agent.session.id`)}function traceStringAttribute(e,t){let n=e.attributes[t];return typeof n==`string`&&n.length>0?n:void 0}export{localTraceOperations,traceModelName,traceSessionId,traceStringAttribute,traceToolName,uniqueLocalTraceSpans};
@@ -0,0 +1,17 @@
1
+ import type { LocalTraceSummary } from "#tracing/local-trace-summary.js";
2
+ export type LocalTraceSortBy = "duration" | "failures" | "inputTokens" | "latest";
3
+ export interface LocalTraceQueryFilter {
4
+ readonly agentName?: string;
5
+ /** Selects traces containing error spans, not necessarily failed activations. */
6
+ readonly failedOnly?: boolean;
7
+ readonly sessionId?: string;
8
+ readonly toolName?: string;
9
+ }
10
+ /** Filters whole traces without restricting their totals to matching spans. */
11
+ export declare function queryLocalTraceSummaries(summaries: readonly LocalTraceSummary[], options: LocalTraceQueryFilter & {
12
+ readonly limit: number;
13
+ readonly sortBy: LocalTraceSortBy;
14
+ }): {
15
+ readonly matches: readonly LocalTraceSummary[];
16
+ readonly truncated: boolean;
17
+ };
@@ -0,0 +1 @@
1
+ function queryLocalTraceSummaries(e,t){let n=e.filter(e=>matchesFilter(e,t));return n.sort((e,n)=>compareSummaries(e,n,t.sortBy)),{matches:n.slice(0,t.limit),truncated:n.length>t.limit}}function matchesFilter(e,t){return(t.agentName===void 0||e.agentNames.includes(t.agentName))&&(t.sessionId===void 0||e.sessionIds.includes(t.sessionId))&&(t.toolName===void 0||e.toolNames.includes(t.toolName))&&(t.failedOnly!==!0||e.errorSpanCount>0)}function compareSummaries(e,t,n){return(n===`duration`?t.durationMs-e.durationMs:n===`failures`?t.errorSpanCount-e.errorSpanCount:n===`inputTokens`?t.inputTokens-e.inputTokens:Date.parse(t.startedAt)-Date.parse(e.startedAt))||e.traceId.localeCompare(t.traceId)}export{queryLocalTraceSummaries};
@@ -1 +1 @@
1
- import{mkdir}from"node:fs/promises";import{createLogger,formatError}from"#internal/logging.js";import{join}from"node:path";import{atomicWriteFile}from"#shared/atomic-write-file.js";import{JsonTraceSerializer}from"#compiled/@opentelemetry/otlp-transformer/index.js";const log=createLogger(`harness.local-trace-span-processor`);function resolveLocalTraceStoreDirectory(e){return join(e,`.eve`,`traces`)}function resolveLocalTraceSchemaDirectory(e){return join(resolveLocalTraceStoreDirectory(e),`v1`)}function resolveLocalTraceSegmentsDirectory(e,t){return join(resolveLocalTraceSchemaDirectory(e),t,`segments`)}var LocalTraceSpanProcessor=class{#e;#t=Promise.resolve();#n=!1;constructor(e){this.#e=e}forceFlush(){return this.#t}onStart(){}onEnd(e){if(!isReadableSpan(e))return;let{spanId:t,traceId:n}=e.spanContext();if(!isHexId(n,32)||!isHexId(t,16))return;let r=JsonTraceSerializer.serializeRequest([e]);r!==void 0&&(this.#t=this.#t.then(async()=>{let e=resolveLocalTraceSegmentsDirectory(this.#e,n);await mkdir(e,{recursive:!0}),await atomicWriteFile(join(e,`${t}.otlp.json`),r)}).catch(e=>{this.#n||(this.#n=!0,log.warn(`local trace persistence failed`,{error:formatError(e)}))}))}shutdown(){return this.forceFlush()}};function isReadableSpan(e){return typeof e==`object`&&!!e&&`attributes`in e&&`spanContext`in e&&typeof e.spanContext==`function`}function isHexId(e,t){return e.length===t&&/^[0-9a-f]+$/u.test(e)}export{LocalTraceSpanProcessor,resolveLocalTraceSchemaDirectory,resolveLocalTraceSegmentsDirectory};
1
+ import{mkdir}from"node:fs/promises";import{createLogger,formatError}from"#internal/logging.js";import{join}from"node:path";import{atomicWriteFile}from"#shared/atomic-write-file.js";import{indexLocalTraceConversation}from"#tracing/local-trace-discovery-index.js";import{JsonTraceSerializer}from"#compiled/@opentelemetry/otlp-transformer/index.js";const log=createLogger(`harness.local-trace-span-processor`);function resolveLocalTraceStoreDirectory(e){return join(e,`.eve`,`traces`)}function resolveLocalTraceSchemaDirectory(e){return join(resolveLocalTraceStoreDirectory(e),`v1`)}function resolveLocalTraceDirectory(e,t){return join(resolveLocalTraceSchemaDirectory(e),t)}function resolveLocalTraceSegmentsDirectory(e,t){return join(resolveLocalTraceDirectory(e,t),`segments`)}var LocalTraceSpanProcessor=class{#e;#t=Promise.resolve();#n=!1;constructor(e){this.#e=e}forceFlush(){return this.#t}onStart(){}onEnd(e){if(!isReadableSpan(e))return;let{spanId:t,traceId:n}=e.spanContext();if(!isHexId(n,32)||!isHexId(t,16))return;let r=JsonTraceSerializer.serializeRequest([e]);if(r===void 0)return;let i=e.attributes[`gen_ai.conversation.id`],a=typeof i==`string`&&i.length>0?i:void 0;this.#t=this.#t.then(async()=>{let e=resolveLocalTraceDirectory(this.#e,n),i=resolveLocalTraceSegmentsDirectory(this.#e,n);await mkdir(i,{recursive:!0}),await atomicWriteFile(join(i,`${t}.otlp.json`),r),a!==void 0&&await indexLocalTraceConversation({conversationId:a,traceDirectory:e})}).catch(e=>{this.#n||(this.#n=!0,log.warn(`local trace persistence failed`,{error:formatError(e)}))})}shutdown(){return this.forceFlush()}};function isReadableSpan(e){return typeof e==`object`&&!!e&&`attributes`in e&&`spanContext`in e&&typeof e.spanContext==`function`}function isHexId(e,t){return e.length===t&&/^[0-9a-f]+$/u.test(e)}export{LocalTraceSpanProcessor,resolveLocalTraceSchemaDirectory,resolveLocalTraceSegmentsDirectory};
@@ -0,0 +1,31 @@
1
+ import type { LocalTraceSpan } from "#tracing/local-trace-reader.js";
2
+ /** Structural metadata and totals for one retained trace, not its final outcome. */
3
+ export interface LocalTraceSummary {
4
+ readonly traceId: string;
5
+ readonly startedAt: string;
6
+ /** Elapsed time from the earliest span start to the latest span end. */
7
+ readonly durationMs: number;
8
+ readonly spanCount: number;
9
+ readonly agentNames: readonly string[];
10
+ readonly conversationIds: readonly string[];
11
+ readonly sessionIds: readonly string[];
12
+ readonly models: readonly string[];
13
+ readonly toolNames: readonly string[];
14
+ readonly modelCalls: number;
15
+ readonly toolCalls: number;
16
+ /** Error-bearing spans; one failure can be recorded on multiple ancestors. */
17
+ readonly errorSpanCount: number;
18
+ readonly inputTokens: number;
19
+ readonly outputTokens: number;
20
+ readonly cacheReadTokens: number;
21
+ readonly cacheWriteTokens: number;
22
+ /** Total gateway cost in USD; undefined when no step reported cost. */
23
+ readonly costUsd?: number;
24
+ }
25
+ /**
26
+ * Only agent.step spans contribute usage: model spans repeat the same counters.
27
+ * Operation counts collapse action/execution pairs, but error counts retain all
28
+ * error-bearing spans so summaries agree with the raw trace tree.
29
+ */
30
+ export declare function summarizeLocalTrace(traceId: string, spans: readonly LocalTraceSpan[]): LocalTraceSummary;
31
+ export declare function localTraceSpanCostUsd(span: LocalTraceSpan): number | undefined;
@@ -0,0 +1 @@
1
+ import{AGENT_USAGE_ATTRIBUTES}from"#tracing/agent-span-contract.js";import{localTraceOperations,traceModelName,traceSessionId,traceStringAttribute,traceToolName,uniqueLocalTraceSpans}from"#tracing/local-trace-operations.js";function summarizeLocalTrace(e,t){let n=uniqueLocalTraceSpans(t),r=new Set,i=new Set,a=new Set,o=new Set,s=n[0]?.startTimeNs??0n,c=s,l=0,u=0,d,f=0,p=0,m=0;for(let e of n){if(e.startTimeNs<s&&(s=e.startTimeNs),e.endTimeNs>c&&(c=e.endTimeNs),add(r,traceModelName(e)),add(i,traceStringAttribute(e,`agent.name`)),add(a,traceStringAttribute(e,`gen_ai.conversation.id`)),add(o,traceSessionId(e)),e.statusCode===2&&(f+=1),e.name!==`agent.step`)continue;p+=numberAttribute(e,`agent.usage.input_tokens`)??0,m+=numberAttribute(e,`agent.usage.output_tokens`)??0,l+=numberAttribute(e,AGENT_USAGE_ATTRIBUTES.cacheReadTokens)??numberAttribute(e,`gen_ai.usage.cache_read.input_tokens`)??0,u+=numberAttribute(e,AGENT_USAGE_ATTRIBUTES.cacheWriteTokens)??numberAttribute(e,`gen_ai.usage.cache_creation.input_tokens`)??0;let t=localTraceSpanCostUsd(e);t!==void 0&&(d=(d??0)+t)}let h=new Set,g=0,_=0;for(let e of localTraceOperations(n))e.category===`model`&&(g+=1),e.category===`tool`&&(_+=1,add(h,traceToolName(e.span)));return{traceId:e,startedAt:new Date(Number(s/1000000n)).toISOString(),durationMs:Number(c-s)/1e6,spanCount:n.length,agentNames:[...i].sort(),conversationIds:[...a].sort(),sessionIds:[...o].sort(),models:[...r].sort(),toolNames:[...h].sort(),modelCalls:g,toolCalls:_,errorSpanCount:f,cacheReadTokens:l,cacheWriteTokens:u,costUsd:d,inputTokens:p,outputTokens:m}}function localTraceSpanCostUsd(e){return numberAttribute(e,`gen_ai.usage.gateway_cost`)??numberAttribute(e,`gen_ai.usage.cost`)}function numberAttribute(e,t){let n=e.attributes[t];if(typeof n==`number`)return Number.isFinite(n)&&n>=0?n:void 0;if(typeof n==`string`&&n.trim()!==``){let e=Number(n);return Number.isFinite(e)&&e>=0?e:void 0}}function add(e,t){t!==void 0&&e.add(t)}export{localTraceSpanCostUsd,summarizeLocalTrace};
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-BUeSjwIk.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-Di1u2zKu.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-BUeSjwIk.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-Di1u2zKu.js";
2
2
 
3
3
  export { useEveAgent };
@@ -74,14 +74,12 @@ Use separate packages or projects when agents need independent dependencies or r
74
74
 
75
75
  Choose how the frontend and agents run together independently of how many agents you have:
76
76
 
77
- - **Add agents to a Next.js application:** use [`eve/next`](/docs/guides/frontend/nextjs) in `next.config.ts`. Next.js owns the application lifecycle; the integration starts agent processes and proxies requests locally, and contributes separate agent services on Vercel. A root Next.js app can sit beside either `agent/` or `agents/`; workspace members are discovered automatically.
77
+ - **Add agents to a Next.js application:** use [`eve/next`](/docs/guides/frontend/nextjs) in `next.config.ts`. Next.js owns the application lifecycle; the integration starts agent processes and proxies requests locally, and contributes separate agent services on Vercel. A root Next.js app can sit beside either `agent/` or `agents/`; workspace members are discovered automatically. A peer app such as `apps/web/` can select its eve project with `eveRoot: "../.."`.
78
78
  - **Add a frontend to an agent workspace:** keep the frontend as a peer application, for example under `apps/web/`. On Vercel, use [`eve/vercel` in root `vercel.ts`](/docs/guides/deployment/vercel#compose-agents-with-other-vercel-services) to contribute the agents alongside the frontend service. For [self-hosting](/docs/guides/deployment/self-hosting#run-workspace-members), run the services with your process manager and configure a reverse proxy. The frontend does not need `eve/next`.
79
79
 
80
80
  `apps/web/` is an organizational convention, not an eve filesystem slot. Deployment configuration owns peer services; eve discovers only the agents. Both Vercel integrations deploy the services together, not as independent releases.
81
81
 
82
- The generated Web Chat installer does not support agent workspaces. Create the frontend and its agent-selection UI yourself, using the [React chat example](/docs/guides/frontend/overview#basic-chat-react). Develop a peer Next.js frontend with `next dev` separately from the agents. For an authored Vercel service graph, use `vercel dev --local` to run the composition without linking a Vercel project.
83
-
84
- For a single `agent/` project, `eve add channel/web` currently generates a root Next.js app using `eve/next`. `eve/vercel` currently requires an `agents/` workspace; it cannot compose a standalone root `agent/`.
82
+ Run `eve add channel/web` from a standalone agent or select a workspace agent with `--agent <name>`. The installer creates a Next.js frontend under `apps/web/`. Choose **Vercel** to configure separate Vercel services and run them with `pnpm dev:services`, or **Other** to let Next.js host the agents and run the application with `pnpm dev:web`. Use `pnpm dev` or `pnpm dev:eve` when you only want one agent and the eve terminal UI.
85
83
 
86
84
  ## Add a second root agent
87
85
 
@@ -79,7 +79,7 @@ The stream is newline-delimited JSON (NDJSON), one event per line:
79
79
  | `action.result` | A tool call returned. |
80
80
  | `input.requested` | The run paused for human input ([HITL](/docs/human-in-the-loop) approval or a `ctx.ask()` question); carries `requests`. |
81
81
  | `input.resolved` | The server accepted terminal human-input outcomes; carries `resolutions` with responses when provided. |
82
- | `subagent.called` | A subagent was delegated; carries `childSessionId` to attach to. |
82
+ | `subagent.called` | A subagent was delegated; carries `childSessionId` and the `childStreamPath` that `session.streamSubagent()` follows. |
83
83
  | `subagent.completed` | The parent recorded a successful subagent invocation result; carries the actual output. |
84
84
  | `reasoning.appended` | A reasoning text delta. |
85
85
  | `reasoning.completed` | The finalized reasoning block. |
@@ -119,7 +119,7 @@ Note: consider the privacy, confidentiality, and user-experience implications fo
119
119
 
120
120
  When a task explicitly requires conditional delivery and there is nothing new to report, the agent can finish with exactly `<eve-empty-delivery/>`. eve emits `message.completed` with `message: null` for that intentional silence. The marker must be the entire response, apart from surrounding whitespace; the HTML-escaped form `&lt;eve-empty-delivery/&gt;` is also accepted. A response that quotes the marker in prose or code is delivered normally.
121
121
 
122
- A delegated subagent publishes progress on its own child-session stream. The parent emits `subagent.called` with a `childSessionId`, which a client uses to attach. Both blocking and background calls emit `subagent.completed` with the actual output after the parent records a successful outcome. A background working receipt is an `action.result` tool output; it does not emit completion. Older streams can contain receipt-bearing completion events marked by `data.backgroundTask`; those are admission only. Completion does not mean that the reusable child session has ended. Background task terminal outcomes also arrive as task-triggered `message.received` notifications with `data.kind: "execution.background_task"`. The default frontend reducer retains these events in `events` but does not project their runtime-authored text as participant messages.
122
+ A delegated subagent publishes progress on its own child-session stream. The parent emits `subagent.called` with a `childSessionId` and a `childStreamPath`, which a client follows with `session.streamSubagent()`. Both blocking and background calls emit `subagent.completed` with the actual output after the parent records a successful outcome. A background working receipt is an `action.result` tool output; it does not emit completion. Older streams can contain receipt-bearing completion events marked by `data.backgroundTask`; those are admission only. Completion does not mean that the reusable child session has ended. Background task terminal outcomes also arrive as task-triggered `message.received` notifications with `data.kind: "execution.background_task"`. The default frontend reducer retains these events in `events` but does not project their runtime-authored text as participant messages.
123
123
 
124
124
  `step.failed` and `turn.failed` carry `{ code, message, details? }` for the failed fragment or turn, and `session.failed` is the terminal session-level variant. `turn.cancelled` is not a failure: the cancelled turn ends without any failure event, `session.waiting` follows, and the session accepts the next message normally. Whatever the turn streamed before cancellation stays on the stream. Durable history keeps the accepted user input and previously settled work, but discards incomplete assistant output and unfinished tool state. When a turn requested an output schema, the finalized payload lands on `result.completed` as `data.result` before the turn boundary. `authorization.required` carries the sign-in challenge (`data.authorization` may include `url`, `userCode`, `expiresAt`, `instructions`), and `authorization.completed` carries `data.outcome` (`"authorized" | "declined" | "failed" | "timed-out"`).
125
125
 
@@ -111,6 +111,7 @@ Every `t.session()` or `t.send()` creates a new independent conversation. Contin
111
111
  - `session.start(message, options?)` starts a text turn and returns as soon as the server accepts it. The live turn exposes `.session`, `.sessionId`, `.waitForEvent(...)`, `.cancel()`, and `.result()`.
112
112
  - `session.cancel()` requests cooperative cancellation of that session's active turn. Both `accepted` and `no_active_turn` are successful outcomes.
113
113
  - `session.sendFile(text, path, mediaType?)` attaches a local file as a data URL.
114
+ - `session.streamSubagent(called, options?)` follows a delegated child's stream through the parent with the eval client's credentials. Pass a `subagent.called` event from that session. It also reaches children on another deployment, which `t.target.watchTurn(...)` cannot address.
114
115
  - `session.requireInputRequest(filter?)` records a gate, requires exactly one pending request, and returns it. Filters match tool name, action input, prompt, display, and option ids.
115
116
  - `session.respond(responses, options?)` answers specific pending input requests and sends them as the next turn. `session.startRespond(...)` returns a live turn for the same operation.
116
117
  - `session.respondAll(optionId)` answers every pending input request with the same option and sends the responses as the next turn.
@@ -273,7 +273,9 @@ The mount is intentionally per agent. Each consumer chooses its own mount namesp
273
273
 
274
274
  When `eve dev` starts a consuming agent, it builds mounted, source-backed extensions found inside the same workspace before compiling the agent. It watches the extension source and relevant package and TypeScript configuration, then rebuilds only the affected extension. If an extension edit fails to build, the previous successful development generation keeps running.
275
275
 
276
- Production `eve build` expects the extension distribution to exist already. Keep `eve extension build` in the extension package's `build` and `prepare` scripts, as the scaffold does, and run workspace builds in dependency order so extensions build before their consuming agents.
276
+ Production builds build the same extensions from source. `eve build` builds each mounted, source-backed workspace extension before it compiles the agent, and `withEve` does the same for its agents during `next build`. Production builds therefore do not depend on the extension package's `prepare` script, which package managers skip for no-op installs and with `--ignore-scripts`. eve skips an extension whose distribution was built by the same eve version and is newer than the extension's source, `package.json`, and TypeScript configuration.
277
+
278
+ If an extension fails to build, the agent build stops with an error that names the extension package and its directory. Fix the reported error, or run `eve extension build` in that package directory to build it on its own.
277
279
 
278
280
  ### Override a contribution
279
281
 
@@ -239,9 +239,41 @@ export default eveChannel({
239
239
 
240
240
  `trustedForwarders` authorizes the verified forwarder to supply eve delegation context: principal identity, parent session lineage, and, with principal forwarding, trace-content constraints. Match it precisely: `() => true` grants this authority to every caller that passes route auth, including preview deployments accepted by `vercelOidc()`. The framework default channel rejects forwarded principals and ignores the other context.
241
241
 
242
+ ### Limiting what a forwarder may assert
243
+
244
+ A forwarder accepted on its identity alone can assert any principal, including identities your tools trust directly, such as a Slack user or an app principal. When a forwarder should speak only for its own users, check what it asserts with the predicate's second argument:
245
+
246
+ ```ts title="agent/channels/eve.ts"
247
+ import { eveChannel } from "eve/channels/eve";
248
+ import { vercelOidc, vercelSubject } from "eve/channels/auth";
249
+ import type { SessionAuthContext } from "eve/context";
250
+
251
+ const router = vercelSubject({ teamSlug: "acme", projectName: "router" });
252
+
253
+ /** The router forwards only users signed in through its own identity provider. */
254
+ function isRouterUser(context: SessionAuthContext): boolean {
255
+ return (
256
+ context.authenticator === "router-sso" &&
257
+ context.issuer === "router" &&
258
+ context.principalType === "user"
259
+ );
260
+ }
261
+
262
+ export default eveChannel({
263
+ auth: [vercelOidc()],
264
+ trustedForwarders: (forwarder, assertion) =>
265
+ forwarder.subject === router &&
266
+ assertion.principal !== undefined &&
267
+ isRouterUser(assertion.principal.current) &&
268
+ isRouterUser(assertion.principal.initiator),
269
+ });
270
+ ```
271
+
272
+ `assertion.principal` holds the `current` and `initiator` contexts the forwarder asserts, already stamped with `eve:forwarded-by`. `initiator` equals `current` when the sender omits it. `initiator` takes effect only on session creation; on continuation the predicate still sees the asserted `initiator`, but the session keeps its original initiator, so checking it does not constrain that pinned value. Attributes are asserted too, so check any attribute your tools trust. `assertion.principal` is absent when the predicate decides parent session lineage for a request that forwards no principal; a predicate that requires it accepts that forwarder's lineage only alongside a principal it accepts. The `ForwardedAssertion` and `TrustedForwarders` types are exported from `eve/channels/eve` for named predicates.
273
+
242
274
  When the predicate accepts a create request, `ctx.session.auth.current` and `.initiator` carry the forwarded user exactly as if they had called your deployment directly. On continuation, only `auth.current` is replaced; `auth.initiator` remains the session creator. User-scoped connections, local subagents, and further `forwardPrincipal` hops therefore see the active turn's caller.
243
275
 
244
- The forwarder is recorded on accepted contexts as the `eve:forwarded-by` attribute (always overwritten by the receiver, so a forwarder cannot falsify it). Forwarded identity rejections fail loud: a forwarded body without `trustedForwarders` configured or with a forwarder the predicate refuses is a `403`, and a malformed payload is a `400`. Only principal metadata is ever accepted — tokens and credentials never cross the hop.
276
+ The forwarder is recorded on accepted contexts as the `eve:forwarded-by` attribute (always overwritten by the receiver, so a forwarder cannot falsify it). Forwarded identity rejections fail loud: a forwarded body without `trustedForwarders` configured, or with a forwarder or assertion the predicate refuses, is a `403`, and a malformed payload is a `400`. Only principal metadata is ever accepted — tokens and credentials never cross the hop.
245
277
 
246
278
  Trusted parent session lineage populates `ctx.session.parent` and preserves the root session across the delegation chain. Untrusted lineage is ignored, and accepted lineage does not remove the normal root-session token cap.
247
279
 
@@ -241,6 +241,32 @@ Unlike `stream()`, `snapshot()` does not advance the originating
241
241
  `ClientSession`. Its returned cursor contains the fixed session ID and the exact
242
242
  stream index after the captured prefix.
243
243
 
244
+ ## Follow a subagent
245
+
246
+ A delegated subagent reports its progress on its own child session. The parent stream announces each dispatch with a `subagent.called` event. Pass that event to `streamSubagent()` on the parent's session handle to follow the child:
247
+
248
+ ```ts
249
+ import { isCurrentTurnBoundaryEvent } from "eve/client";
250
+
251
+ const session = client.sessions.attach(parentSessionId);
252
+ const { events } = await session.snapshot();
253
+ const called = events.find((event) => event.type === "subagent.called");
254
+
255
+ if (called?.type === "subagent.called") {
256
+ for await (const event of session.streamSubagent(called)) {
257
+ console.log(called.data.name, event.type);
258
+ if (isCurrentTurnBoundaryEvent(event)) break;
259
+ }
260
+ }
261
+ ```
262
+
263
+ `streamSubagent()` reads the event's `childStreamPath` with the parent session's host and credentials, so the same client works for local and [remote](../remote-agents) children:
264
+
265
+ - A local child's path is its own session stream route on the same deployment. The channel's usual session authorization applies.
266
+ - A remote child's path is a proxy route on the parent deployment. The parent checks that the child belongs to this session, then relays the remote child's stream with the remote agent's authored `auth` and `headers`. The client never needs the remote URL or its credentials.
267
+
268
+ The child has its own cursor, starting at `0`, and reading it never advances the parent's `streamIndex`. Pass `startIndex` to resume, `follow: false` for a bounded read, and `signal` to detach. A child parks after answering and can be continued later, so stop at a turn boundary with `isCurrentTurnBoundaryEvent` when you only need the current turn. Passing a `subagent.called` event from a different session throws.
269
+
244
270
  ## Abort a request
245
271
 
246
272
  Pass an `AbortSignal` to cancel the POST or stream. Aborting is local transport cancellation: turns are resumable across disconnects, so detaching never stops server-side work. Use `session.cancel()` to stop the active turn, or `session.cancel({ tasks: true })` to also stop background tasks owned by the session. Cancellation is asynchronous; watch the stream for `turn.cancelled` followed by `session.waiting`, and inspect task state in a later turn to confirm task cancellation.
@@ -57,9 +57,7 @@ A Next.js-centered project uses [`withEve` in `next.config.ts`](../frontend/next
57
57
 
58
58
  Use `withEve` from `eve/vercel` when the agents and other applications are peer services. The helper contributes workspace agents to a Vercel service graph; it does not manage or require a particular frontend framework. Unlike `eve/next`, this keeps the project lifecycle separate from Next.js. Both integrations deploy the agent services together in one Vercel project.
59
59
 
60
- `eve/vercel` currently requires an `agents/` workspace, even if it has only one member. It does not support a standalone root `agent/`.
61
-
62
- For a workspace with a peer Next.js frontend under `apps/web/`, replace `vercel.json` with a root `vercel.ts`. The frontend uses an ordinary Next.js config without `eve/next`:
60
+ For a standalone agent or workspace with a peer Next.js frontend under `apps/web/`, replace `vercel.json` with a root `vercel.ts`. The frontend uses an ordinary Next.js config without `eve/next`:
63
61
 
64
62
  ```typescript title="vercel.ts"
65
63
  import { withEve } from "eve/vercel";
@@ -82,9 +80,9 @@ export default await withEve({
82
80
 
83
81
  Vercel evaluates `vercel.ts` before resolving the service graph. `withEve` adds the root agent, or every direct workspace member, as an independently built service and returns a plain Vercel configuration. Named workspace agents mount at `/eve/<name>/v1/*`; a root agent mounts at `/eve/v1/*`. Vercel then builds the frontend and each eve agent separately. The frontend does not need `withEve` in its framework configuration or a build script that builds the agents.
84
82
 
85
- The Web Chat installer does not support agent workspaces. Create the frontend using the [React chat example](../frontend/overview#basic-chat-react), and configure authentication for every exposed agent. To self-host the same source layout, replace Vercel composition with your own [process and proxy configuration](./self-hosting#run-workspace-members).
83
+ The Web Chat installer can generate this composition for a standalone agent or a selected workspace agent. Configure authentication for every exposed agent. To self-host the same source layout, replace Vercel composition with your own [process and proxy configuration](./self-hosting#run-workspace-members).
86
84
 
87
- Run Vercel CLI 59.16.0 or newer with `vercel dev --local` to start the complete service graph locally. Named agents use the same `/eve/<name>/v1/*` routes in development, and default `defineWorkspaceAgent` transports can call peers without deployment credentials. Run `eve dev` instead when you only need one agent and the eve terminal UI.
85
+ Run Vercel CLI 59.16.0 or newer with `vercel dev` to start the complete service graph locally. A generated Vercel Web Chat project exposes this as `pnpm dev:services`; the first run links the directory when needed and linked projects load their development environment and settings. Use `pnpm dev` or `pnpm dev:eve` when you want one agent and the eve terminal UI, or `pnpm dev:web` when you want the frontend without its agent services. Named agents use the same `/eve/<name>/v1/*` routes in development, and default `defineWorkspaceAgent` transports can call peers without deployment credentials.
88
86
 
89
87
  Generated transport routes are inserted before a filesystem handler or, when no filesystem handler exists, before authored routes. `withEve` throws instead of overwriting an authored service key or exact transport route that belongs to a generated agent. Remove the authored route, and remove or rename the authored service; `withEve` adds both automatically. Names in the array form of `services` must also be unique. Other service names, routes, bindings, and Cron Jobs remain authored in `vercel.ts`.
90
88
 
@@ -124,6 +122,8 @@ eve deploy
124
122
 
125
123
  `eve deploy` installs dependencies, runs `vercel deploy --prod`, and pulls the project environment after deployment. You can also push to a Git-connected Vercel project. Hosted Vercel builds set `VERCEL`, so `eve build` writes the deployment bundle under `.vercel/output`.
126
124
 
125
+ When `eve deploy` creates a new Vercel project, it configures trace sampling so traces appear in Agent Runs automatically. See [Agent Runs](../../observability/agent-runs) for details. Pass `--no-trace-sampling` to skip this setting.
126
+
127
127
  For non-interactive use, confirm the production deploy up front. `--project` links first, so a new project needs no separate `eve link`:
128
128
 
129
129
  ```bash
@@ -80,13 +80,26 @@ Generated agent services build with `EVE_PUBLIC_ROUTE_PREFIX` set to the agent's
80
80
 
81
81
  All fields are optional.
82
82
 
83
- | Option | Type | Default | Purpose |
84
- | -------------------- | --------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
85
- | `eveRoot` | `string` | Next.js app root | Path to one unnamed eve app root, relative to `process.cwd()` unless absolute. Do not combine with `agents`. |
86
- | `agents` | `Record<string, ...>` | inferred for a workspace | Named eve agents to mount under `/eve/<name>/v1/*`. `withEve()` discovers project-level `agents/<name>/` members when neither `agents` nor `eveRoot` is set; otherwise each value is a root string or `{ root, buildCommand?, servicePrefix? }`. |
87
- | `eveBuildCommand` | `string` | generated | Build command for generated eve Vercel services. In multi-agent mode this is the default for agents without their own `buildCommand`. |
88
- | `servicePrefix` | `string` | `"/_eve_internal/eve"` | Private route namespace for legacy manual Vercel service configs and non-Vercel production proxying. Named agents derive unique defaults from this prefix. |
89
- | `devServerTimeoutMs` | `number` | `180000` | Maximum time to wait for each eve development server to become available. |
83
+ | Option | Type | Default | Purpose |
84
+ | -------------------- | --------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
85
+ | `eveRoot` | `string` | Next.js app root | Eve project root, relative to the Next.js app root unless absolute. It may contain either one `agent/` or an `agents/` workspace. Do not combine with `agents`. |
86
+ | `agents` | `Record<string, ...>` | inferred for a workspace | Named eve agents to mount under `/eve/<name>/v1/*`. `withEve()` discovers project-level `agents/<name>/` members when `agents` and `eveRoot` are unset; otherwise each value is a root string or `{ root, buildCommand?, servicePrefix? }`. |
87
+ | `eveBuildCommand` | `string` | generated | Build command for generated eve Vercel services. In multi-agent mode this is the default for agents without their own `buildCommand`. |
88
+ | `servicePrefix` | `string` | `"/_eve_internal/eve"` | Private route namespace for legacy manual Vercel service configs and non-Vercel production proxying. Named agents derive unique defaults from this prefix. |
89
+ | `devServerTimeoutMs` | `number` | `180000` | Maximum time to wait for each eve development server to become available. |
90
+
91
+ When the Next.js app is a peer of an eve project, select its root without repeating every agent path. The root may contain either one `agent/` or an `agents/` workspace:
92
+
93
+ ```ts title="apps/web/next.config.ts"
94
+ import type { NextConfig } from "next";
95
+ import { withEve } from "eve/next";
96
+
97
+ const nextConfig: NextConfig = {};
98
+
99
+ export default withEve(nextConfig, {
100
+ eveRoot: "../..",
101
+ });
102
+ ```
90
103
 
91
104
  For slow cold starts, increase the development timeout:
92
105
 
@@ -172,7 +172,7 @@ supplied `session` remains externally owned and is never replaced by prewarming
172
172
 
173
173
  `data.messages` are eve-owned `EveMessage[]`. Common text, reasoning, file, and dynamic-tool parts follow the [AI SDK `UIMessage`](https://ai-sdk.dev/docs/reference/ai-sdk-core/ui-message) rendering convention, but the types are not interchangeable. eve also exposes authorization and HITL metadata, and a file part's URL can be absent. Adapt those parts before passing messages to an API typed as `UIMessage[]`.
174
174
 
175
- When the root agent delegates, its stream emits `subagent.called` with the child's `childSessionId`, then `subagent.completed` when the parent records a successful result, for both blocking and background invocations. A background working receipt appears in `action.result`, without a completion event. The child session can remain available for reuse. Task notifications wake the parent with completion, failure, or cancellation. Detailed child progress lives on the child session's stream instead of being flattened into the root `data.messages`. Use the lower-level [TypeScript client](../client/overview#sessions) to attach to that ID when your UI needs live subagent activity. See [What the parent sees](../../subagents#what-the-parent-sees) for the complete contract.
175
+ When the root agent delegates, its stream emits `subagent.called` with the child's `childSessionId`, then `subagent.completed` when the parent records a successful result, for both blocking and background invocations. A background working receipt appears in `action.result`, without a completion event. The child session can remain available for reuse. Task notifications wake the parent with completion, failure, or cancellation. Detailed child progress lives on the child session's stream instead of being flattened into the root `data.messages`. When your UI needs live subagent activity, attach a [client session](../client/overview#sessions) to the parent and pass the `subagent.called` event from `events` to [`streamSubagent()`](../client/streaming#follow-a-subagent). It follows local and remote children through the parent, so the browser never calls a remote deployment directly. See [What the parent sees](../../subagents#what-the-parent-sees) for the complete contract.
176
176
 
177
177
  ## Sending and streaming
178
178
 
@@ -28,10 +28,10 @@ Omitting `agent/instrumentation/agent-runs.ts` preserves that default. Export
28
28
 
29
29
  ## Enable tracing on Vercel
30
30
 
31
- New eve deployments automatically sample 100% of requests. Existing eve
32
- deployments need a sampling rule configured for the Vercel project to collect
33
- traces. To enable tracing for an existing deployment, select your team and
34
- project, then open
31
+ When `eve deploy` creates a new Vercel project, it configures 100% trace
32
+ sampling for all environments. Existing Vercel projects need a sampling rule
33
+ configured to collect traces. To enable tracing for an existing project, select
34
+ your team and project, then open
35
35
  [**Settings → Tracing**](https://vercel.com/d?to=%2F%5Bteam%5D%2F%5Bproject%5D%2Fsettings%2Ftracing&title=Go+to+Tracing+settings):
36
36
 
37
37
  1. Select **Add Sampling Rule**.
@@ -138,7 +138,7 @@ This makes caller authority turn-scoped even when the remote child session is pe
138
138
 
139
139
  Identity forwarding does not make a persistent session private to one caller. Conversation history, tool outputs, and other child-session state still persist. If those values must not be visible across users, give each user a distinct child session or enforce that ownership at the application boundary.
140
140
 
141
- Forwarding identity is explicit on both sides. The receiver names which deployments it trusts with `eveChannel({ trustedForwarders })` (see [Auth & route protection](./auth-and-route-protection#accepting-forwarded-identity-from-another-deployment)); refusing the forwarder rejects a forwarded principal with a 403. The same trust decision covers parent session lineage and, with principal forwarding, trace-content constraints.
141
+ Forwarding identity is explicit on both sides. The receiver names which deployments it trusts with `eveChannel({ trustedForwarders })` and can limit each one to the principals it may assert (see [Auth & route protection](./auth-and-route-protection#accepting-forwarded-identity-from-another-deployment)); refusing the forwarder or what it asserts rejects a forwarded principal with a 403. The same trust decision covers parent session lineage and, with principal forwarding, trace-content constraints.
142
142
 
143
143
  ## Trace propagation
144
144
 
@@ -192,6 +192,8 @@ A remote subagent runs as a durable background task in its own deployment:
192
192
 
193
193
  The parent stream carries the same `subagent.called`, `action.result`, and `subagent.completed` events as local delegation. For a remote call, `subagent.called.data.remote.url` records the target.
194
194
 
195
+ Clients follow a remote child through the parent. [`session.streamSubagent()`](./client/streaming#follow-a-subagent) reads `subagent.called.data.childStreamPath`, a route on the parent deployment. The parent verifies that the child belongs to that session, resolves the remote agent's `auth` and `headers`, and relays the child's stream. A browser never calls the remote deployment or holds its credentials; it only needs access to the parent session.
196
+
195
197
  An admitted task survives cancellation of the turn that started it; background work that has not yet been admitted is rejected with the cancelled step. Use `task_cancel` to stop an admitted task. eve resolves the remote's `headers` and `auth` again for every cancellation attempt, so rotating credentials work the same way as they do for session creation. Cancellation always uses the standard eve cancel path on `url`, even when `path` customizes only the create-session endpoint. The remote child reports `turn.cancelled` → `session.waiting` on its own stream; an older or unreachable remote is logged but cannot turn the parent's cancellation into a failure.
196
198
 
197
199
  You can also steer a running remote background child by calling its subagent tool with the same `agentId` and an updated `message`. eve cancels the old task and requests cancellation of the remote turn before continuing the same remote session under a new task ID. The remote must support the standard eve cancellation and session-message routes. See [Agent messaging](../subagents#agent-messaging) for the shared steering contract.
@@ -19,7 +19,7 @@ eve add memory/file
19
19
 
20
20
  If an item is not found, `eve add` searches the available catalogs and prints close matches without installing anything.
21
21
 
22
- Web Chat installs a project-level Next.js application. It cannot be added to an eve agent workspace; eve rejects the installation before writing files. See [Project Structure](./concepts/project-structure) for browser-app placement and [Next.js](./guides/frontend/nextjs) for manual integration.
22
+ Web Chat installs a shared Next.js application at `apps/web` for either a standalone agent or a selected member of an agent workspace. Choose **Vercel services** (recommended) to deploy Web Chat and agents as separate services, or **Next.js** to serve Web Chat and route agent requests through one Next.js app. Existing authored Next.js or Vercel configuration is preserved, and eve stops with manual composition guidance instead of overwriting it. See [Project Structure](./concepts/project-structure) for browser-app placement and [Next.js](./guides/frontend/nextjs) for Next.js-owned integration.
23
23
 
24
24
  If you do not know an item name yet, run `eve add` without an argument. Its help output shows how to search the registry with `eve registry search <query>`.
25
25
 
@@ -64,6 +64,22 @@ Paths below are relative to the agent directory. Root agents can use every path;
64
64
  | `schedules/` | Recurring jobs | No | `defineSchedule` modules or Markdown prompts with `cron` frontmatter; recursive nesting is supported. |
65
65
  | `subagents/` | Specialist child agents | Yes | Local directories or remote-agent definitions; nested subagents are supported. |
66
66
 
67
+ ## Colocated tests
68
+
69
+ eve ignores JavaScript and TypeScript modules named `*.test.*` or `*.spec.*`,
70
+ along with `__tests__/` directories, during automatic discovery and when choosing
71
+ extension runtime entries.
72
+
73
+ ```text
74
+ agent/tools/
75
+ ├── get_weather.ts # registered as get_weather
76
+ ├── get_weather.test.ts # excluded from discovery
77
+ └── __tests__/ # excluded from discovery
78
+ └── fixtures.json
79
+ ```
80
+
81
+ Explicit imports, sandbox workspace files, and packaged skill resources are unaffected.
82
+
67
83
  ## Files available in the sandbox
68
84
 
69
85
  Agent source files are not automatically available to shell commands. Put files to copy into the sandbox's `/workspace/` under `agent/sandbox/workspace/`. Skill runtime files are seeded separately under `$HOME/.agents/skills/`, with `/workspace/skills/` as a fallback. See [Sandboxes](/docs/sandbox) and [Skills](/docs/skills).
@@ -311,7 +311,7 @@ eve traces --json # dump the full trace as JSON
311
311
 
312
312
  Reads the immutable OTLP/JSON segments under `.eve/traces/v1`, so `eve dev` need not be running. Accepts a full trace id, a `gen_ai.conversation.id`, or an unambiguous prefix of either. Malformed segments are skipped without hiding valid spans from the same trace.
313
313
 
314
- Span rows carry inline metrics when the span recorded them — `↑input`/`↓output` token counts, gateway cost, and the tool name for `execute_tool` spans — and the header aggregates models, token totals, cost, and error count across the trace's step spans. `--verbose` expands each span under its tree row: status (with the error message on failures), timing, ids, every attribute (prompts, responses, and tool payloads as transcripts or pretty-printed JSON), and every span event with its offset from span start. `--json` prints the same records as JSON, one object per selected trace.
314
+ Span rows carry inline metrics when the span recorded them — `↑input`/`↓output` token counts, gateway cost, and the tool name for `execute_tool` spans. The header lists models across the trace, sums token usage and cost from step spans, and counts all error-bearing spans. `--verbose` expands each span under its tree row: status (with the error message on failures), timing, ids, every attribute (prompts, responses, and tool payloads as transcripts or pretty-printed JSON), and every span event with its offset from span start. `--json` prints the same records as JSON, one object per selected trace.
315
315
 
316
316
  Every subagent activation starts its own trace. The first child's `invoke_agent` root links to the dispatching caller with `eve.link.type=agent.dispatch`; remote agents preserve that caller in W3C `tracestate` even when HTTP `traceparent` advances through platform ingress. Later turns also start fresh traces without repeating the initial caller link. All related sessions retain the same `gen_ai.conversation.id`, and `agent.subagent.name` labels the child invocation.
317
317
 
@@ -9,6 +9,12 @@ Use a subagent to run independent work in parallel, narrow the available tools,
9
9
  - Use a [declared local subagent](#declared-subagents) for a specialist with its own directory and authored capabilities, rather than inheriting the root's.
10
10
  - Use a [remote agent](./guides/remote-agents) to delegate to a separately deployed eve agent, with its own configuration and authentication.
11
11
 
12
+ A subagent can finish a model turn while background tasks started in that turn are still running.
13
+ That turn yields; its interim reply does not complete the caller's delegated task. Background work started by an earlier turn does not hold the reply, and a turn that ends with an error always answers the caller. If the child session expires, resets, or closes before replying, the delegated task fails and reports the usage accumulated since its previous settlement.
14
+ After the nested tasks finish, the subagent resumes and returns its final result to
15
+ the caller. This applies to root-agent copies, declared local subagents, and remote
16
+ subagents. The subagent session remains available for later calls.
17
+
12
18
  ## Completion batching
13
19
 
14
20
  Overlapping background work owned by a session forms a cohort. Tasks launched in
@@ -99,7 +105,7 @@ The parent can alternatively export `disableTool()` from a same-named tool path,
99
105
 
100
106
  Every declared local or remote subagent runs as a durable background task: the call returns `{ status: "working", taskId, agentId }` immediately, then task notifications wake the parent with completion, failure, or cancellation. Human input requests surface separately on the parent session.
101
107
 
102
- `task_cancel` is available to sessions that own background tasks, including a child that starts nested background work.
108
+ `task_cancel` is available to sessions that own background tasks, including a child that starts nested background work. Cancelling a delegated agent task also requests cancellation of its child's nested background tasks, even after that child's model turn has yielded. The child does not start another model turn for notifications from that cancelled work. This applies to self, local, and remote delegation. The calling model receives the cancellation receipt in the `task_cancel` result; a later report of that same outcome does not start another model turn.
103
109
 
104
110
  A mounted extension can also contribute declared subagents from `extension/subagents/`. The mount namespace prefixes the subagent visible to the consuming agent node: mounting an extension as `crm` exposes its `reviewer` subagent as `crm__reviewer`. The contributed subagent keeps its own isolated tools, connections, skills, hooks, instructions, sandbox, and nested subagents, and its modules can read configuration from the extension handle. See [Extensions](./extensions#add-a-subagent) for the authoring and override behavior.
105
111
 
@@ -253,7 +259,7 @@ By default, a subagent named `researcher` collides with an authored tool named `
253
259
 
254
260
  Do not rely on subagent delegation by itself as an approval boundary. Put sensitive tools behind `approval`, connection approval, route/session authorization, or other controls wherever those tools can be called.
255
261
 
256
- Each delegated subagent spins up its own child session and stream. The parent stream carries the control-plane events `subagent.called` and `subagent.completed`, plus interactive `input.requested`, `authorization.required`, and `authorization.completed` events proxied from descendants so the root channel can prompt the user. To follow the child's other progress, read `subagent.called.data.childSessionId` and subscribe at `GET /eve/v1/session/:childSessionId/stream`.
262
+ Each delegated subagent spins up its own child session and stream. The parent stream carries the control-plane events `subagent.called` and `subagent.completed`, plus interactive `input.requested`, `authorization.required`, and `authorization.completed` events proxied from descendants so the root channel can prompt the user. To follow the child's other progress, pass the `subagent.called` event to [`session.streamSubagent()`](./guides/client/streaming#follow-a-subagent) on a client session attached to the parent. It reads `subagent.called.data.childStreamPath`: the child's own session stream for a local child, or a parent-origin proxy for a remote child, which the parent authenticates to the remote deployment.
257
263
 
258
264
  Both blocking and background invocations emit `subagent.called` after dispatch and `subagent.completed` after the parent records successful completion. Completion carries the actual output and identifies the same invocation by `callId`; the child session can remain available for reuse. A background working receipt is returned as an `action.result` tool output and does not emit completion. Background completion events do not wait for the cohort report. Failure and cancellation are not successful completion; task notifications retain those outcomes.
259
265
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve",
3
- "version": "0.66.0",
3
+ "version": "0.66.2",
4
4
  "private": false,
5
5
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
6
6
  "keywords": [
@@ -1,18 +0,0 @@
1
- import { type ExtensionBuildConfig } from "#internal/nitro/host/build-extension.js";
2
- /** Build inputs retained with a prepared dev host for path-scoped extension HMR. */
3
- export interface DevelopmentWorkspaceExtension {
4
- readonly config: ExtensionBuildConfig;
5
- /** Canonical package root, with workspace links resolved. */
6
- readonly packageRoot: string;
7
- /** Non-source inputs that affect publisher output, such as tsconfig files. */
8
- readonly buildConfigPaths: readonly string[];
9
- }
10
- /**
11
- * Builds mounted source-backed workspace extensions before the consuming agent
12
- * compiles and returns the inputs needed to scope the next development rebuild.
13
- */
14
- export declare function prepareDevelopmentWorkspaceExtensions(input: {
15
- readonly appRoot: string;
16
- readonly changedPaths?: readonly string[];
17
- readonly previousExtensions?: readonly DevelopmentWorkspaceExtension[];
18
- }): Promise<readonly DevelopmentWorkspaceExtension[]>;