eve 0.30.6 → 0.30.7

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 (94) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/src/cli/commands/trace-detail.d.ts +53 -0
  3. package/dist/src/cli/commands/trace-detail.js +1 -0
  4. package/dist/src/cli/commands/trace.d.ts +4 -1
  5. package/dist/src/cli/commands/trace.js +4 -4
  6. package/dist/src/cli/dev/tui/terminal-renderer.js +2 -2
  7. package/dist/src/cli/dev/tui/traces/trace-content.d.ts +3 -3
  8. package/dist/src/cli/dev/tui/traces/trace-content.js +1 -1
  9. package/dist/src/cli/dev/tui/traces/trace-view.js +1 -1
  10. package/dist/src/cli/run.js +1 -1
  11. package/dist/src/compiler/extension-compatibility.d.ts +10 -10
  12. package/dist/src/compiler/extension-compatibility.js +1 -1
  13. package/dist/src/context/dynamic-subagent-lifecycle.d.ts +2 -0
  14. package/dist/src/context/dynamic-subagent-lifecycle.js +1 -1
  15. package/dist/src/execution/agent-continuation-bundle.d.ts +13 -0
  16. package/dist/src/execution/agent-continuation-bundle.js +1 -0
  17. package/dist/src/execution/agent-handle-dispatch.d.ts +32 -4
  18. package/dist/src/execution/agent-handle-dispatch.js +1 -1
  19. package/dist/src/execution/cancel-descendant-turns-step.js +1 -1
  20. package/dist/src/execution/delegated-parent-notification.d.ts +30 -4
  21. package/dist/src/execution/delegated-parent-notification.js +1 -1
  22. package/dist/src/execution/delegated-parent-result.js +1 -1
  23. package/dist/src/execution/dispatch-action-failures.d.ts +8 -0
  24. package/dist/src/execution/dispatch-action-failures.js +1 -0
  25. package/dist/src/execution/dispatch-runtime-actions-step.d.ts +8 -7
  26. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  27. package/dist/src/execution/dispatch-start-operation.d.ts +15 -0
  28. package/dist/src/execution/dispatch-start-operation.js +1 -0
  29. package/dist/src/execution/forward-turn-cancellation-step.js +1 -1
  30. package/dist/src/execution/next-driver-action.d.ts +12 -0
  31. package/dist/src/execution/node-step.d.ts +1 -1
  32. package/dist/src/execution/node-step.js +1 -1
  33. package/dist/src/execution/parked-delivery-wait.d.ts +35 -0
  34. package/dist/src/execution/parked-delivery-wait.js +1 -0
  35. package/dist/src/execution/remote-agent-dispatch.d.ts +42 -0
  36. package/dist/src/execution/remote-agent-dispatch.js +1 -1
  37. package/dist/src/execution/sandbox/prewarm.js +1 -1
  38. package/dist/src/execution/session-timeout-steps.js +1 -1
  39. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  40. package/dist/src/execution/subagent-invocation.d.ts +3 -0
  41. package/dist/src/execution/subagent-invocation.js +1 -1
  42. package/dist/src/execution/subagent-tool.d.ts +7 -0
  43. package/dist/src/execution/subagent-tool.js +1 -1
  44. package/dist/src/execution/terminate-child-sessions-step.d.ts +15 -0
  45. package/dist/src/execution/terminate-child-sessions-step.js +1 -0
  46. package/dist/src/execution/turn-control-protocol.js +1 -1
  47. package/dist/src/execution/turn-execution-cursor.d.ts +3 -0
  48. package/dist/src/execution/turn-workflow.js +1 -1
  49. package/dist/src/execution/workflow-entry.js +1 -1
  50. package/dist/src/execution/workflow-runtime.js +1 -1
  51. package/dist/src/execution/workflow-steps.d.ts +8 -1
  52. package/dist/src/execution/workflow-steps.js +1 -1
  53. package/dist/src/harness/agent-handle-errors.d.ts +0 -2
  54. package/dist/src/harness/agent-handle-errors.js +1 -1
  55. package/dist/src/harness/handles/transitions.d.ts +16 -1
  56. package/dist/src/harness/handles/transitions.js +1 -1
  57. package/dist/src/harness/messages.d.ts +4 -2
  58. package/dist/src/harness/messages.js +1 -1
  59. package/dist/src/harness/runtime-actions.js +1 -1
  60. package/dist/src/harness/tool-loop.js +2 -2
  61. package/dist/src/harness/turn-tag-state.d.ts +16 -0
  62. package/dist/src/harness/turn-tag-state.js +1 -1
  63. package/dist/src/harness/types.d.ts +7 -2
  64. package/dist/src/internal/application/package.js +1 -1
  65. package/dist/src/packages/eve-catalog/src/index.js +1 -1
  66. package/dist/src/public/channels/eve.js +1 -1
  67. package/dist/src/runtime/actions/types.d.ts +11 -2
  68. package/dist/src/runtime/actions/types.js +1 -1
  69. package/dist/src/runtime/agent/bootstrap.js +1 -1
  70. package/dist/src/runtime/framework-tools/agent.d.ts +16 -0
  71. package/dist/src/runtime/framework-tools/agent.js +1 -1
  72. package/dist/src/runtime/prompt/compose.d.ts +7 -0
  73. package/dist/src/runtime/prompt/compose.js +1 -1
  74. package/dist/src/runtime/resolve-agent-graph.js +1 -1
  75. package/dist/src/runtime/session-callback-route.js +1 -1
  76. package/dist/src/runtime/sessions/compiled-agent-cache.js +1 -1
  77. package/dist/src/runtime/subagents/registry.d.ts +20 -1
  78. package/dist/src/runtime/subagents/registry.js +1 -1
  79. package/dist/src/setup/integrations/github/connect.d.ts +28 -0
  80. package/dist/src/setup/integrations/github/connect.js +1 -0
  81. package/dist/src/setup/integrations/github/setup.d.ts +15 -0
  82. package/dist/src/setup/integrations/github/setup.js +15 -0
  83. package/dist/src/setup/integrations/registry.js +1 -1
  84. package/dist/src/setup/scaffold/create/project.js +1 -1
  85. package/dist/src/tracing/local-trace-reader.d.ts +10 -0
  86. package/dist/src/tracing/local-trace-reader.js +1 -1
  87. package/docs/channels/github.mdx +11 -16
  88. package/docs/concepts/security-model.md +1 -0
  89. package/docs/guides/state.md +1 -0
  90. package/docs/reference/cli.md +4 -0
  91. package/docs/schedules.mdx +1 -0
  92. package/docs/subagents.mdx +28 -1
  93. package/docs/tools/human-in-the-loop.md +1 -0
  94. package/package.json +1 -1
@@ -7,15 +7,25 @@
7
7
  * span. Parsing is defensive end to end — malformed or oversized segments
8
8
  * are skipped so a partial write never breaks a view.
9
9
  */
10
+ export interface LocalTraceSpanEvent {
11
+ readonly attributes: Readonly<Record<string, unknown>>;
12
+ readonly name: string;
13
+ readonly timeNs: bigint;
14
+ }
10
15
  export interface LocalTraceSpan {
11
16
  readonly attributes: Readonly<Record<string, unknown>>;
12
17
  readonly endTimeNs: bigint;
18
+ readonly events: readonly LocalTraceSpanEvent[];
19
+ /** OTLP span kind (1 internal … 5 consumer); undefined when absent. */
20
+ readonly kind?: number;
13
21
  readonly name: string;
14
22
  readonly parentSpanId?: string;
15
23
  readonly scope?: string;
16
24
  readonly spanId: string;
17
25
  readonly startTimeNs: bigint;
18
26
  readonly statusCode: number;
27
+ /** Message carried by an ERROR status, when the span recorded one. */
28
+ readonly statusMessage?: string;
19
29
  readonly traceId: string;
20
30
  }
21
31
  export interface LocalTrace {
@@ -1 +1 @@
1
- import{readFile,readdir,stat}from"node:fs/promises";import{join}from"node:path";import{resolveLocalTraceSchemaDirectory,resolveLocalTraceSegmentsDirectory}from"#tracing/local-trace-span-processor.js";const TRACE_ID_PATTERN=/^[0-9a-f]{32}$/u,SPAN_FILE_PATTERN=/^[0-9a-f]{16}\.otlp\.json$/u;async function listLocalTraceIds(e){let n;try{n=await readdir(resolveLocalTraceSchemaDirectory(e),{withFileTypes:!0})}catch(e){if(isMissing(e))return[];throw e}return n.filter(e=>e.isDirectory()&&TRACE_ID_PATTERN.test(e.name)).map(e=>e.name)}async function readLocalTraceActivityMs(e,t){try{return(await stat(resolveLocalTraceSegmentsDirectory(e,t))).mtimeMs}catch(e){if(isMissing(e))return;throw e}}async function listLocalTraceSegments(e,n){let r;try{r=await readdir(resolveLocalTraceSegmentsDirectory(e,n),{withFileTypes:!0})}catch(e){if(isMissing(e))return;throw e}return r.filter(e=>e.isFile()&&SPAN_FILE_PATTERN.test(e.name)).map(e=>e.name).sort((e,t)=>e.localeCompare(t))}async function readLocalTraceSegment(t,i,o){let s=join(resolveLocalTraceSegmentsDirectory(t,i),o),c;try{if((await stat(s)).size>8388608)return[];c=await readFile(s,`utf8`)}catch{return[]}return parseLocalTraceSegment(c,i)}async function listLocalTraces(e){let t=[];for(let n of await listLocalTraceIds(e)){let r=await readLocalTrace(e,n).catch(()=>void 0);r!==void 0&&t.push(r)}return t.sort((e,t)=>e.startTimeNs===t.startTimeNs?e.traceId.localeCompare(t.traceId):e.startTimeNs>t.startTimeNs?-1:1)}async function readLocalTrace(e,t){let n=await listLocalTraceSegments(e,t);if(n===void 0)return;let r=new Map;for(let i of n)for(let n of await readLocalTraceSegment(e,t,i))r.has(n.spanId)||r.set(n.spanId,n);if(r.size!==0)return assembleLocalTrace(t,[...r.values()])}function compareLocalTraceSpans(e,t){return e.startTimeNs===t.startTimeNs?e.endTimeNs===t.endTimeNs?e.name.localeCompare(t.name)||e.spanId.localeCompare(t.spanId):e.endTimeNs<t.endTimeNs?-1:1:e.startTimeNs<t.startTimeNs?-1:1}function assembleLocalTrace(e,t){let n=[...t].sort(compareLocalTraceSpans),r=n.map(e=>e.attributes),i=distinctAttributes(r,`agent.session.id`);return{agentName:firstAttribute(r,`agent.name`),endTimeNs:n.reduce((e,t)=>t.endTimeNs>e?t.endTimeNs:e,0n),sessionId:i[0],sessionIds:i,spans:n,startTimeNs:n.reduce((e,t)=>t.startTimeNs<e?t.startTimeNs:e,n[0].startTimeNs),traceId:e,window:firstNumberAttribute(r,`agent.session.window`)}}function describeLocalTraceSpan(e){let t=[],n=stringSpanAttribute(e,`agent.turn.id`),r=valueSpanAttribute(e,`agent.step.index`),i=valueSpanAttribute(e,`agent.step.attempt`),a=stringSpanAttribute(e,`agent.action.kind`),o=stringSpanAttribute(e,`agent.action.name`),s=stringSpanAttribute(e,`agent.model.id`)??stringSpanAttribute(e,`gen_ai.request.model`);return e.name===`agent.turn`&&n!==void 0&&t.push(n),e.name===`agent.step`&&r!==void 0&&t.push(`step ${String(r)}${i===void 0?``:`, attempt ${String(i)}`}`),e.name===`agent.action`&&o!==void 0&&t.push(`${a??`action`}: ${o}`),s!==void 0&&e.name.includes(`do`)&&t.push(`model ${s}`),t}function parseLocalTraceSegment(e,t){try{let n=JSON.parse(e);if(!isRecord(n)||!Array.isArray(n.resourceSpans))return[];let r=[];for(let e of n.resourceSpans)if(!(!isRecord(e)||!Array.isArray(e.scopeSpans)))for(let n of e.scopeSpans){if(!isRecord(n)||!Array.isArray(n.spans))continue;let e=isRecord(n.scope)&&typeof n.scope.name==`string`?n.scope.name:void 0;for(let i of n.spans){let n=parseLocalTraceSpan(i,t,e);n!==void 0&&r.push(n)}}return r}catch{return[]}}function parseLocalTraceSpan(e,t,n){if(!isRecord(e)||e.traceId!==t||typeof e.spanId!=`string`||!/^[0-9a-f]{16}$/u.test(e.spanId)||typeof e.name!=`string`)return;let r=parseNanos(e.startTimeUnixNano),i=parseNanos(e.endTimeUnixNano);if(!(r===void 0||i===void 0||i<r))return{attributes:parseAttributes(e.attributes),endTimeNs:i,name:e.name,parentSpanId:typeof e.parentSpanId==`string`&&/^[0-9a-f]{16}$/u.test(e.parentSpanId)?e.parentSpanId:void 0,scope:n,spanId:e.spanId,startTimeNs:r,statusCode:parseStatusCode(e.status),traceId:t}}function parseAttributes(e){if(!Array.isArray(e))return{};let t={};for(let n of e){if(!isRecord(n)||typeof n.key!=`string`||!isRecord(n.value))continue;let e=parseAnyValue(n.value);e!==void 0&&(t[n.key]=e)}return t}function parseAnyValue(e){for(let t of[`stringValue`,`boolValue`,`intValue`,`doubleValue`])if(t in e)return e[t];if(isRecord(e.arrayValue)&&Array.isArray(e.arrayValue.values))return e.arrayValue.values.filter(isRecord).map(e=>parseAnyValue(e))}function parseNanos(e){if(!(typeof e!=`string`&&typeof e!=`number`))try{let t=BigInt(e);return t>=0n&&t<=18446744073709551615n?t:void 0}catch{return}}function parseStatusCode(e){return isRecord(e)?typeof e.code==`number`?e.code:e.code===`STATUS_CODE_ERROR`?2:0:0}function firstAttribute(e,t){for(let n of e){let e=n[t];if(typeof e==`string`&&e.length>0)return e}}function firstNumberAttribute(e,t){for(let n of e){let e=n[t];if(typeof e==`number`)return e;if(typeof e==`bigint`)return Number(e)}}function distinctAttributes(e,t){let n=new Set;for(let r of e){let e=r[t];typeof e==`string`&&e.length>0&&n.add(e)}return[...n]}function stringSpanAttribute(e,t){let n=e.attributes[t];return typeof n==`string`?n:void 0}function valueSpanAttribute(e,t){let n=e.attributes[t];return typeof n==`string`||typeof n==`number`?n:void 0}function isMissing(e){return e.code===`ENOENT`}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{assembleLocalTrace,compareLocalTraceSpans,describeLocalTraceSpan,listLocalTraceIds,listLocalTraceSegments,listLocalTraces,parseLocalTraceSegment,readLocalTraceActivityMs,readLocalTraceSegment};
1
+ import{readFile,readdir,stat}from"node:fs/promises";import{join}from"node:path";import{resolveLocalTraceSchemaDirectory,resolveLocalTraceSegmentsDirectory}from"#tracing/local-trace-span-processor.js";const TRACE_ID_PATTERN=/^[0-9a-f]{32}$/u,SPAN_FILE_PATTERN=/^[0-9a-f]{16}\.otlp\.json$/u;async function listLocalTraceIds(e){let n;try{n=await readdir(resolveLocalTraceSchemaDirectory(e),{withFileTypes:!0})}catch(e){if(isMissing(e))return[];throw e}return n.filter(e=>e.isDirectory()&&TRACE_ID_PATTERN.test(e.name)).map(e=>e.name)}async function readLocalTraceActivityMs(e,t){try{return(await stat(resolveLocalTraceSegmentsDirectory(e,t))).mtimeMs}catch(e){if(isMissing(e))return;throw e}}async function listLocalTraceSegments(e,n){let r;try{r=await readdir(resolveLocalTraceSegmentsDirectory(e,n),{withFileTypes:!0})}catch(e){if(isMissing(e))return;throw e}return r.filter(e=>e.isFile()&&SPAN_FILE_PATTERN.test(e.name)).map(e=>e.name).sort((e,t)=>e.localeCompare(t))}async function readLocalTraceSegment(t,i,o){let s=join(resolveLocalTraceSegmentsDirectory(t,i),o),c;try{if((await stat(s)).size>8388608)return[];c=await readFile(s,`utf8`)}catch{return[]}return parseLocalTraceSegment(c,i)}async function listLocalTraces(e){let t=[];for(let n of await listLocalTraceIds(e)){let r=await readLocalTrace(e,n).catch(()=>void 0);r!==void 0&&t.push(r)}return t.sort((e,t)=>e.startTimeNs===t.startTimeNs?e.traceId.localeCompare(t.traceId):e.startTimeNs>t.startTimeNs?-1:1)}async function readLocalTrace(e,t){let n=await listLocalTraceSegments(e,t);if(n===void 0)return;let r=new Map;for(let i of n)for(let n of await readLocalTraceSegment(e,t,i))r.has(n.spanId)||r.set(n.spanId,n);if(r.size!==0)return assembleLocalTrace(t,[...r.values()])}function compareLocalTraceSpans(e,t){return e.startTimeNs===t.startTimeNs?e.endTimeNs===t.endTimeNs?e.name.localeCompare(t.name)||e.spanId.localeCompare(t.spanId):e.endTimeNs<t.endTimeNs?-1:1:e.startTimeNs<t.startTimeNs?-1:1}function assembleLocalTrace(e,t){let n=[...t].sort(compareLocalTraceSpans),r=n.map(e=>e.attributes),i=distinctAttributes(r,`agent.session.id`);return{agentName:firstAttribute(r,`agent.name`),endTimeNs:n.reduce((e,t)=>t.endTimeNs>e?t.endTimeNs:e,0n),sessionId:i[0],sessionIds:i,spans:n,startTimeNs:n.reduce((e,t)=>t.startTimeNs<e?t.startTimeNs:e,n[0].startTimeNs),traceId:e,window:firstNumberAttribute(r,`agent.session.window`)}}function describeLocalTraceSpan(e){let t=[],n=stringSpanAttribute(e,`agent.turn.id`),r=valueSpanAttribute(e,`agent.step.index`),i=valueSpanAttribute(e,`agent.step.attempt`),a=stringSpanAttribute(e,`agent.action.kind`),o=stringSpanAttribute(e,`agent.action.name`),s=stringSpanAttribute(e,`agent.model.id`)??stringSpanAttribute(e,`gen_ai.request.model`);return e.name===`agent.turn`&&n!==void 0&&t.push(n),e.name===`agent.step`&&r!==void 0&&t.push(`step ${String(r)}${i===void 0?``:`, attempt ${String(i)}`}`),e.name===`agent.action`&&o!==void 0&&t.push(`${a??`action`}: ${o}`),s!==void 0&&e.name.includes(`do`)&&t.push(`model ${s}`),t}function parseLocalTraceSegment(e,t){try{let n=JSON.parse(e);if(!isRecord(n)||!Array.isArray(n.resourceSpans))return[];let r=[];for(let e of n.resourceSpans)if(!(!isRecord(e)||!Array.isArray(e.scopeSpans)))for(let n of e.scopeSpans){if(!isRecord(n)||!Array.isArray(n.spans))continue;let e=isRecord(n.scope)&&typeof n.scope.name==`string`?n.scope.name:void 0;for(let i of n.spans){let n=parseLocalTraceSpan(i,t,e);n!==void 0&&r.push(n)}}return r}catch{return[]}}function parseLocalTraceSpan(e,t,n){if(!isRecord(e)||e.traceId!==t||typeof e.spanId!=`string`||!/^[0-9a-f]{16}$/u.test(e.spanId)||typeof e.name!=`string`)return;let r=parseNanos(e.startTimeUnixNano),i=parseNanos(e.endTimeUnixNano);if(!(r===void 0||i===void 0||i<r))return{attributes:parseAttributes(e.attributes),endTimeNs:i,events:parseEvents(e.events),kind:typeof e.kind==`number`?e.kind:void 0,name:e.name,parentSpanId:typeof e.parentSpanId==`string`&&/^[0-9a-f]{16}$/u.test(e.parentSpanId)?e.parentSpanId:void 0,scope:n,spanId:e.spanId,startTimeNs:r,statusCode:parseStatusCode(e.status),statusMessage:parseStatusMessage(e.status),traceId:t}}function parseEvents(e){if(!Array.isArray(e))return[];let t=[];for(let n of e){if(!isRecord(n)||typeof n.name!=`string`)continue;let e=parseNanos(n.timeUnixNano);e!==void 0&&t.push({attributes:parseAttributes(n.attributes),name:n.name,timeNs:e})}return t.sort((e,t)=>e.timeNs===t.timeNs?e.name.localeCompare(t.name):e.timeNs<t.timeNs?-1:1)}function parseAttributes(e){if(!Array.isArray(e))return{};let t={};for(let n of e){if(!isRecord(n)||typeof n.key!=`string`||!isRecord(n.value))continue;let e=parseAnyValue(n.value);e!==void 0&&(t[n.key]=e)}return t}function parseAnyValue(e){for(let t of[`stringValue`,`boolValue`,`intValue`,`doubleValue`])if(t in e)return e[t];if(isRecord(e.arrayValue)&&Array.isArray(e.arrayValue.values))return e.arrayValue.values.filter(isRecord).map(e=>parseAnyValue(e))}function parseNanos(e){if(!(typeof e!=`string`&&typeof e!=`number`))try{let t=BigInt(e);return t>=0n&&t<=18446744073709551615n?t:void 0}catch{return}}function parseStatusCode(e){return isRecord(e)?typeof e.code==`number`?e.code:e.code===`STATUS_CODE_ERROR`?2:0:0}function parseStatusMessage(e){if(!(!isRecord(e)||typeof e.message!=`string`))return e.message.length===0?void 0:e.message}function firstAttribute(e,t){for(let n of e){let e=n[t];if(typeof e==`string`&&e.length>0)return e}}function firstNumberAttribute(e,t){for(let n of e){let e=n[t];if(typeof e==`number`)return e;if(typeof e==`bigint`)return Number(e)}}function distinctAttributes(e,t){let n=new Set;for(let r of e){let e=r[t];typeof e==`string`&&e.length>0&&n.add(e)}return[...n]}function stringSpanAttribute(e,t){let n=e.attributes[t];return typeof n==`string`?n:void 0}function valueSpanAttribute(e,t){let n=e.attributes[t];return typeof n==`string`||typeof n==`number`?n:void 0}function isMissing(e){return e.code===`ENOENT`}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}export{assembleLocalTrace,compareLocalTraceSpans,describeLocalTraceSpan,listLocalTraceIds,listLocalTraceSegments,listLocalTraces,parseLocalTraceSegment,readLocalTraceActivityMs,readLocalTraceSegment};
@@ -1,29 +1,24 @@
1
1
  ---
2
2
  title: "GitHub"
3
- description: "Reach your agent from GitHub App webhooks, with @mention dispatch, PR diff context, sandbox checkout, and Vercel Connect credentials."
3
+ description: "Reach your agent from GitHub App webhooks, with comment invocation, PR diff context, sandbox checkout, and Vercel Connect credentials."
4
4
  type: integration
5
5
  ---
6
6
 
7
- The GitHub channel lets the agent work directly on a repository. Someone `@mentions` it in an issue, PR, or review comment, and the agent answers right there in the thread, with the PR diff already in context and the repo checked out into the sandbox. It takes GitHub App webhooks at `/eve/v1/github`, checks the signature, derives auth from whoever triggered the event, and replies on the native surface. Credentials can run through [Vercel Connect](../guides/auth-and-route-protection), which manages the GitHub App, the installation token, and inbound webhook verification, so there's no app private key or webhook secret for you to hold. See [Channels](./overview) for the contract this builds on.
7
+ The GitHub channel lets the agent work directly on a repository. Add its invocation token, such as `@my-agent`, to a new issue, PR, or review comment and the agent answers in that thread, with the PR diff already in context and the repo checked out into the sandbox. The token is an eve convention: GitHub may not autocomplete it or render it as a linked mention. The channel takes GitHub App webhooks at `/eve/v1/github`, checks the signature, derives auth from whoever triggered the event, and replies on the native surface. Credentials can run through [Vercel Connect](../guides/auth-and-route-protection), which manages the GitHub App, the installation token, and inbound webhook verification, so there's no app private key or webhook secret for you to hold. See [Channels](./overview) for the contract this builds on.
8
8
 
9
- ## Set up Connect
9
+ ## Guided Connect setup
10
10
 
11
- Create a GitHub Connect client and copy its UID (e.g. `github/my-agent`), then attach this project as the trigger destination at eve's GitHub route:
11
+ Run the registry setup from the agent directory:
12
12
 
13
13
  ```bash
14
- npm install -g vercel@latest
15
- vercel connect create github --triggers
16
- vercel connect detach <uid> --yes
17
- vercel connect attach <uid> --triggers --trigger-path /eve/v1/github --yes
14
+ eve add channel/github
18
15
  ```
19
16
 
20
- The `create` step provisions the GitHub App and a trigger destination at the default Connect path. `detach` then `attach --trigger-path /eve/v1/github` re-points the trigger at the eve GitHub route, since eve does not serve the default Connect path. `--triggers` makes Connect receive the App's webhooks, verify them, and forward them to your deployment. During registration, subscribe to `issue_comment` and `pull_request_review_comment` for mention-driven turns — the managed App defaults to `pull_request` only — and add `issues`, `pull_request`, `check_suite`, `check_run`, or `workflow_run` if you wire up their opt-in hooks. You can also create the client from the [Connect dashboard](https://vercel.com/d?to=/%5Bteam%5D/~/connect&title=Go+to+Connect).
17
+ The flow checks that the Vercel CLI is authenticated, creates or links a Vercel project when needed, provisions an app-scoped GitHub Connect client, and replaces its default trigger with `/eve/v1/github`. It then installs `@vercel/connect` and writes `agent/channels/github.ts` with the connector UID.
21
18
 
22
- ## Add the channel
19
+ Vercel Connect creates the GitHub App, receives and verifies its webhooks, and forwards them to the deployed agent. After deploying, open the GitHub App in the Connect dashboard and install it in the organization or account where you want to use it. Add the generated invocation token (for example, `@my-agent`) to a new issue, pull request, or review comment to start a conversation. GitHub may not autocomplete the token or render it as a linked mention.
23
20
 
24
- ```bash
25
- npm install @vercel/connect
26
- ```
21
+ The generated channel uses Connect-managed credentials:
27
22
 
28
23
  ```ts title="agent/channels/github.ts"
29
24
  import { connectGitHubCredentials } from "@vercel/connect/eve";
@@ -65,7 +60,7 @@ GITHUB_APP_SLUG=... # supplies botName when it is not set in config
65
60
 
66
61
  `appId`/`privateKey`/`webhookSecret` also take a lazy resolver function if you'd rather fetch them on demand.
67
62
 
68
- Point the GitHub App webhook URL at `https://<deployment>/eve/v1/github`. For mention-driven turns, subscribe to `issue_comment` and `pull_request_review_comment`; add `issues`, `pull_request`, `check_suite`, `check_run`, or `workflow_run` if you wire up their opt-in hooks. A comment that `@mention`s `botName` starts a turn.
63
+ Point the GitHub App webhook URL at `https://<deployment>/eve/v1/github`. For comment-invoked turns, subscribe to `issue_comment` and `pull_request_review_comment`; add `issues`, `pull_request`, `check_suite`, `check_run`, or `workflow_run` if you wire up their opt-in hooks. After installing the App for the repository, a new comment that includes `@botName` starts a turn. This is a text invocation token, not a GitHub-native mention: GitHub may display the App as `botName[bot]`, but it may not autocomplete or link `@botName`.
69
64
 
70
65
  ## How the channel handles messages
71
66
 
@@ -78,7 +73,7 @@ import { defaultGitHubAuth, githubChannel } from "eve/channels/github";
78
73
 
79
74
  export default githubChannel({
80
75
  botName: "my-agent",
81
- // Replaces the @mention gate. ctx.conversation.kind is "issue", "pull_request", or "review_thread".
76
+ // Replaces the default invocation-token gate. ctx.conversation.kind is "issue", "pull_request", or "review_thread".
82
77
  onComment: (ctx, comment) => ({ auth: defaultGitHubAuth(ctx) }),
83
78
  // Opt in; no default dispatch on these events.
84
79
  onIssue: (ctx, issue) => (issue.action === "opened" ? { auth: defaultGitHubAuth(ctx) } : null),
@@ -108,7 +103,7 @@ GitHub comments have no interactive button or card affordance. A human-in-the-lo
108
103
 
109
104
  ### Proactive sessions
110
105
 
111
- Start a session without an inbound mention through `receive(github, { message, target, auth })` from a schedule `run` handler, or `args.receive(github, ...)` from another channel. The target requires `owner`, `repo`, and exactly one of `issueNumber` or `pullRequestNumber`.
106
+ Start a session without an inbound comment invocation through `receive(github, { message, target, auth })` from a schedule `run` handler, or `args.receive(github, ...)` from another channel. The target requires `owner`, `repo`, and exactly one of `issueNumber` or `pullRequestNumber`.
112
107
 
113
108
  ### Attachments
114
109
 
@@ -103,3 +103,4 @@ Before exposing an agent to real traffic:
103
103
  - [Sandbox](../sandbox): backends, network policy, and brokering config
104
104
  - [Execution model and durability](./execution-model-and-durability): how durable sessions run
105
105
  - [Connections](../connections): static-token and OAuth connections
106
+ - [Responsible use](../responsible-use): deployer responsibilities and safeguards to review before production
@@ -76,3 +76,4 @@ Every [subagent](../subagents) starts with its own fresh state, whether it's a b
76
76
  - Read state inside dynamic resolvers → [Dynamic capabilities](./dynamic-capabilities)
77
77
  - How step durability works → [Execution model & durability](../concepts/execution-model-and-durability)
78
78
  - The `ctx` accessors available alongside state → [TypeScript API](../reference/typescript-api)
79
+ - Tenant-scoped long-term memory in your own store → [Multi-tenant memory](../patterns/multi-tenant-memory)
@@ -254,10 +254,14 @@ eve traces ls # list traces, most recent first
254
254
  eve traces ls --json # emit machine-readable trace summaries
255
255
  eve traces # show the most recent span tree
256
256
  eve traces <trace> # show one span tree
257
+ eve traces --verbose # expand every span with all attributes and events
258
+ eve traces --json # dump the full trace as JSON
257
259
  ```
258
260
 
259
261
  Reads the immutable OTLP/JSON segments under `.eve/traces/v1`, so `eve dev` need not be running. Accepts a full trace id, an `agent.session.id`, or an unambiguous prefix of either. Malformed segments are skipped without hiding valid spans from the same trace.
260
262
 
263
+ Span rows carry inline metrics when the span recorded them — `↑input`/`↓output` token counts, gateway cost, and the tool name for `ai.toolCall` 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.
264
+
261
265
  A subagent keeps its own session id but records into the trace its parent had open at dispatch, so delegated work appears under the session that caused it, tagged with `agent.root.session.id`. Either session id resolves to that trace. A remote agent traces under its own deployment and is not recorded here.
262
266
 
263
267
  A session long enough to outgrow one trace — far longer than anything you will drive locally — continues into a new one. Each is a session window, numbered from zero on `agent.session.window`; passing a session id shows every window it produced, oldest first, and a trace id shows just that window.
@@ -116,3 +116,4 @@ The gotcha is custom hosting. If you adapt the generated output to a process man
116
116
 
117
117
  - [Channels](./channels/overview): deliver schedule output to users.
118
118
  - [Sessions, runs & streaming](./concepts/sessions-runs-and-streaming): inspect a schedule run.
119
+ - [Dynamic scheduling](./patterns/dynamic-scheduling): manage schedule rows in your own store behind one dispatcher schedule.
@@ -12,10 +12,13 @@ The root session receives `agent` by default. The model calls it to delegate a t
12
12
  ```ts
13
13
  {
14
14
  message: string; // everything the child needs; it does not see the parent's history
15
+ agentId?: string; // only with experimental.subagentPersistentSessions: continue an existing child
15
16
  outputSchema?: object; // when set, the child runs in task mode and returns structured output
16
17
  }
17
18
  ```
18
19
 
20
+ The `agentId` field exists only when the agent opts into [agent messaging](#agent-messaging); without the opt-in the schema is `{ message, outputSchema? }`.
21
+
19
22
  The copy uses the root's instructions, connections, auth, and sandbox. It receives the same tools except for the root-only `agent` and `Workflow`, and starts with fresh conversation history and fresh state. Its file writes are immediately visible to the root. To run independent tasks in parallel, emit multiple `agent` calls in one response; eve runs the batch concurrently and returns every result before the root continues. Give parallel children non-overlapping write scopes.
20
23
 
21
24
  `agent` is intentionally root-only. Copies created by it cannot call `agent`, and declared subagents never receive the built-in tool. If a stale or forced recursive call reaches execution, eve rejects it instead of starting another child session.
@@ -144,7 +147,7 @@ The root built-in `agent` tool is the exception. Its children share the root's s
144
147
 
145
148
  ## What the parent sees
146
149
 
147
- eve lowers every subagent visible to the current agent (the root built-in copy, declared, or [remote](./guides/remote-agents)) into a model-visible tool with the same `{ message, outputSchema? }` shape. The parent packs `message` with everything the child needs, since the child never sees the parent's history. Set `outputSchema` to run the child in task mode, returning structured output as the tool result.
150
+ eve lowers every subagent visible to the current agent (the root built-in copy, declared, or [remote](./guides/remote-agents)) into a model-visible tool with the same `{ message, outputSchema? }` shape — plus `agentId` when the agent opts into [agent messaging](#agent-messaging). The parent packs `message` with everything the child needs, since the child never sees the parent's history. Set `outputSchema` to run the child in task mode, returning structured output as the tool result; this works the same with or without agent messaging.
148
151
 
149
152
  Declared subagents can call nested subagents defined under their own directories. eve does not apply a separate depth limit; nesting ends where the authored directory tree ends. The built-in `agent` follows the stricter root-only rule above, so `limits.maxSubagentDepth` no longer exists.
150
153
 
@@ -155,6 +158,7 @@ A declared subagent's tool name is the bare path-derived name, with no prefix. `
155
158
  ```ts
156
159
  {
157
160
  message: string; // all context the child needs; it never sees the parent's history
161
+ agentId?: string; // only with experimental.subagentPersistentSessions: continue an existing child
158
162
  outputSchema?: object; // when set, the child runs in task mode and returns structured output
159
163
  }
160
164
  ```
@@ -169,6 +173,29 @@ Cancelling a parent turn also requests cancellation of every active child it sta
169
173
 
170
174
  Subagent model calls automatically retry classified transient provider failures, including overload errors delivered after a stream starts. eve makes at most three fresh model-call attempts, repeating only the current uncommitted call so completed earlier steps, tool results, and sandbox work remain available to the child. Other recoverable task errors fall back to Workflow's durable step retry from the last committed session snapshot. Exhausting the transient model-call attempts or the dedicated empty-response reissue returns one failed task result instead of stacking both retry budgets; terminal errors fail immediately.
171
175
 
176
+ ## Agent messaging
177
+
178
+ Agent messaging is experimental and off by default. Opt in per agent in `agent.ts`:
179
+
180
+ ```ts title="agent/agent.ts"
181
+ import { defineAgent } from "eve";
182
+
183
+ export default defineAgent({
184
+ experimental: {
185
+ subagentPersistentSessions: true,
186
+ },
187
+ model: "anthropic/claude-sonnet-4.5",
188
+ });
189
+ ```
190
+
191
+ Without the opt-in, delegated children run as one-shot tasks: they answer once and terminate, and the subagent tool schema carries no `agentId` field.
192
+
193
+ With it enabled, a child parks after answering instead of terminating, keeping its session and conversation history alive. A failed child turn can also leave the child parked — its latest status shows the error and the parent may message it again. Pass a parked child's `agentId` to the same subagent tool with a new `message` to continue that session. Omitting `agentId` (or passing an empty string or `null`) always starts a new child, and an `agentId` that matches no known agent falls back to starting a new child rather than failing. Passing a known `agentId` through a different subagent tool fails with `AGENT_MISMATCH`, and messaging a child that is still starting or working on its previous request fails with `AGENT_BUSY` — wait for its result before continuing it.
194
+
195
+ On every model call, eve injects a system message containing an `<agents>` block listing the currently parked (resumable) children — each entry carries the `agentId`, name, and latest status. It is a per-call injection, not part of the conversation history: it always reflects the current state, never accumulates stale copies, and children that are starting or running do not appear until they park again.
196
+
197
+ The parent holds agent handles only for its session lifetime. When the parent session ends, eve terminates its local children. Remote children are not terminated on parent shutdown — that is a known gap: a parked remote child stays alive on its own deployment until that deployment's own lifecycle ends it. For [remote agents](./guides/remote-agents), both deployments must run the same eve version to use agent messaging.
198
+
172
199
  ## When to split
173
200
 
174
201
  Split out a subagent when the task needs a different prompt or specialist role, a narrower tool surface, or its own runtime context. Don't reach for one when a [skill](./skills) would do. If the agent can keep its identity and needs only an optional procedure, a skill is the lighter choice.
@@ -125,3 +125,4 @@ From your own frontend, read the pending request off the latest message and answ
125
125
  - [Default harness](/docs/concepts/default-harness): the built-in tools, including `ask_question`
126
126
  - [Sessions, runs & streaming](/docs/concepts/sessions-runs-and-streaming): the event and resume contract behind the pause
127
127
  - [Building a frontend](/docs/guides/frontend/overview): render and answer requests from your own UI
128
+ - [Multi-tenant approvals](/docs/patterns/multi-tenant-approvals): resolve per-tenant approval policy for authored and connection tools
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve",
3
- "version": "0.30.6",
3
+ "version": "0.30.7",
4
4
  "private": false,
5
5
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
6
6
  "keywords": [