eve 0.30.6 → 0.30.8

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 (141) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/src/chunks/{use-eve-agent-BXMIf5fR.js → use-eve-agent-Bx-ONuyb.js} +22 -0
  3. package/dist/src/chunks/{use-eve-agent-k-XHfrJT.js → use-eve-agent-DDoDDmJ2.js} +22 -0
  4. package/dist/src/cli/commands/registry-metadata.d.ts +15 -0
  5. package/dist/src/cli/commands/registry-metadata.js +1 -0
  6. package/dist/src/cli/commands/registry-package.d.ts +46 -0
  7. package/dist/src/cli/commands/registry-package.js +1 -0
  8. package/dist/src/cli/commands/registry.d.ts +1 -1
  9. package/dist/src/cli/commands/registry.js +4 -4
  10. package/dist/src/cli/commands/trace-detail.d.ts +53 -0
  11. package/dist/src/cli/commands/trace-detail.js +1 -0
  12. package/dist/src/cli/commands/trace.d.ts +4 -1
  13. package/dist/src/cli/commands/trace.js +4 -4
  14. package/dist/src/cli/dev/tui/traces/trace-content.d.ts +3 -3
  15. package/dist/src/cli/dev/tui/traces/trace-content.js +1 -1
  16. package/dist/src/cli/dev/tui/traces/trace-view.js +1 -1
  17. package/dist/src/cli/run.js +1 -1
  18. package/dist/src/client/index.d.ts +1 -1
  19. package/dist/src/client/message-reducer-types.d.ts +3 -0
  20. package/dist/src/client/message-reducer.js +1 -1
  21. package/dist/src/compiler/extension-compatibility.d.ts +10 -10
  22. package/dist/src/compiler/extension-compatibility.js +1 -1
  23. package/dist/src/context/dynamic-subagent-lifecycle.d.ts +2 -0
  24. package/dist/src/context/dynamic-subagent-lifecycle.js +1 -1
  25. package/dist/src/execution/agent-continuation-bundle.d.ts +13 -0
  26. package/dist/src/execution/agent-continuation-bundle.js +1 -0
  27. package/dist/src/execution/agent-handle-dispatch.d.ts +32 -4
  28. package/dist/src/execution/agent-handle-dispatch.js +1 -1
  29. package/dist/src/execution/cancel-descendant-turns-step.js +1 -1
  30. package/dist/src/execution/delegated-parent-notification.d.ts +30 -4
  31. package/dist/src/execution/delegated-parent-notification.js +1 -1
  32. package/dist/src/execution/delegated-parent-result.js +1 -1
  33. package/dist/src/execution/dispatch-action-failures.d.ts +8 -0
  34. package/dist/src/execution/dispatch-action-failures.js +1 -0
  35. package/dist/src/execution/dispatch-runtime-actions-step.d.ts +8 -7
  36. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  37. package/dist/src/execution/dispatch-start-operation.d.ts +15 -0
  38. package/dist/src/execution/dispatch-start-operation.js +1 -0
  39. package/dist/src/execution/forward-turn-cancellation-step.js +1 -1
  40. package/dist/src/execution/next-driver-action.d.ts +12 -0
  41. package/dist/src/execution/node-step.d.ts +1 -1
  42. package/dist/src/execution/node-step.js +1 -1
  43. package/dist/src/execution/parked-delivery-wait.d.ts +35 -0
  44. package/dist/src/execution/parked-delivery-wait.js +1 -0
  45. package/dist/src/execution/remote-agent-dispatch.d.ts +42 -0
  46. package/dist/src/execution/remote-agent-dispatch.js +1 -1
  47. package/dist/src/execution/sandbox/prewarm.js +1 -1
  48. package/dist/src/execution/session-timeout-steps.js +1 -1
  49. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  50. package/dist/src/execution/subagent-invocation.d.ts +3 -0
  51. package/dist/src/execution/subagent-invocation.js +1 -1
  52. package/dist/src/execution/subagent-tool.d.ts +7 -0
  53. package/dist/src/execution/subagent-tool.js +1 -1
  54. package/dist/src/execution/terminate-child-sessions-step.d.ts +15 -0
  55. package/dist/src/execution/terminate-child-sessions-step.js +1 -0
  56. package/dist/src/execution/tool-auth.d.ts +1 -1
  57. package/dist/src/execution/tool-auth.js +1 -1
  58. package/dist/src/execution/turn-control-protocol.js +1 -1
  59. package/dist/src/execution/turn-execution-cursor.d.ts +3 -0
  60. package/dist/src/execution/turn-workflow.js +1 -1
  61. package/dist/src/execution/workflow-entry.js +1 -1
  62. package/dist/src/execution/workflow-runtime.js +1 -1
  63. package/dist/src/execution/workflow-steps.d.ts +8 -1
  64. package/dist/src/execution/workflow-steps.js +1 -1
  65. package/dist/src/harness/agent-handle-errors.d.ts +0 -2
  66. package/dist/src/harness/agent-handle-errors.js +1 -1
  67. package/dist/src/harness/emission-state.d.ts +25 -0
  68. package/dist/src/harness/emission-state.js +1 -0
  69. package/dist/src/harness/emission.d.ts +4 -36
  70. package/dist/src/harness/emission.js +1 -1
  71. package/dist/src/harness/handles/transitions.d.ts +16 -1
  72. package/dist/src/harness/handles/transitions.js +1 -1
  73. package/dist/src/harness/messages.d.ts +4 -2
  74. package/dist/src/harness/messages.js +1 -1
  75. package/dist/src/harness/ordered-stream-emitter.d.ts +3 -2
  76. package/dist/src/harness/ordered-stream-emitter.js +1 -1
  77. package/dist/src/harness/runtime-actions.js +1 -1
  78. package/dist/src/harness/tool-loop.js +2 -2
  79. package/dist/src/harness/tools.d.ts +1 -1
  80. package/dist/src/harness/tools.js +1 -1
  81. package/dist/src/harness/turn-tag-state.d.ts +16 -0
  82. package/dist/src/harness/turn-tag-state.js +1 -1
  83. package/dist/src/harness/types.d.ts +7 -2
  84. package/dist/src/internal/application/package.js +1 -1
  85. package/dist/src/packages/eve-catalog/src/index.js +1 -1
  86. package/dist/src/protocol/message.d.ts +23 -3
  87. package/dist/src/protocol/message.js +2 -2
  88. package/dist/src/public/channels/discord/discordChannel.d.ts +1 -0
  89. package/dist/src/public/channels/eve.js +1 -1
  90. package/dist/src/public/channels/github/githubChannel.d.ts +1 -0
  91. package/dist/src/public/channels/linear/linearChannel.d.ts +1 -0
  92. package/dist/src/public/channels/slack/slackChannel.d.ts +1 -0
  93. package/dist/src/public/channels/teams/teamsChannel.d.ts +1 -0
  94. package/dist/src/public/channels/telegram/telegramChannel.d.ts +1 -0
  95. package/dist/src/public/channels/twilio/twilioChannel.d.ts +1 -0
  96. package/dist/src/public/definitions/channel.d.ts +1 -0
  97. package/dist/src/public/definitions/channel.js +1 -1
  98. package/dist/src/public/definitions/hook.d.ts +1 -0
  99. package/dist/src/public/definitions/tool.d.ts +5 -5
  100. package/dist/src/runtime/actions/types.d.ts +11 -2
  101. package/dist/src/runtime/actions/types.js +1 -1
  102. package/dist/src/runtime/agent/bootstrap.js +1 -1
  103. package/dist/src/runtime/framework-tools/agent.d.ts +16 -0
  104. package/dist/src/runtime/framework-tools/agent.js +1 -1
  105. package/dist/src/runtime/prompt/compose.d.ts +7 -0
  106. package/dist/src/runtime/prompt/compose.js +1 -1
  107. package/dist/src/runtime/resolve-agent-graph.js +1 -1
  108. package/dist/src/runtime/session-callback-route.js +1 -1
  109. package/dist/src/runtime/sessions/compiled-agent-cache.js +1 -1
  110. package/dist/src/runtime/subagents/registry.d.ts +20 -1
  111. package/dist/src/runtime/subagents/registry.js +1 -1
  112. package/dist/src/setup/integrations/github/connect.d.ts +28 -0
  113. package/dist/src/setup/integrations/github/connect.js +1 -0
  114. package/dist/src/setup/integrations/github/setup.d.ts +15 -0
  115. package/dist/src/setup/integrations/github/setup.js +15 -0
  116. package/dist/src/setup/integrations/linear/setup.js +1 -1
  117. package/dist/src/setup/integrations/registry.js +1 -1
  118. package/dist/src/setup/scaffold/create/project.js +1 -1
  119. package/dist/src/shared/async-iterable.d.ts +2 -0
  120. package/dist/src/shared/async-iterable.js +1 -0
  121. package/dist/src/shared/tool-definition.d.ts +1 -1
  122. package/dist/src/svelte/index.js +1 -1
  123. package/dist/src/svelte/use-eve-agent.js +1 -1
  124. package/dist/src/tracing/local-trace-reader.d.ts +10 -0
  125. package/dist/src/tracing/local-trace-reader.js +1 -1
  126. package/dist/src/vue/index.js +1 -1
  127. package/dist/src/vue/use-eve-agent.js +1 -1
  128. package/docs/channels/github.mdx +11 -16
  129. package/docs/channels/linear.mdx +4 -2
  130. package/docs/concepts/security-model.md +1 -0
  131. package/docs/concepts/sessions-runs-and-streaming.md +3 -0
  132. package/docs/guides/client/streaming.mdx +1 -0
  133. package/docs/guides/hooks.md +1 -1
  134. package/docs/guides/state.md +1 -0
  135. package/docs/install-integrations.mdx +4 -2
  136. package/docs/reference/cli.md +8 -1
  137. package/docs/schedules.mdx +1 -0
  138. package/docs/subagents.mdx +28 -1
  139. package/docs/tools/human-in-the-loop.md +1 -0
  140. package/docs/tools/overview.mdx +26 -2
  141. package/package.json +1 -1
@@ -0,0 +1,28 @@
1
+ import { type ChannelSetupLog } from "#setup/cli/index.js";
2
+ import type { VercelProjectReference } from "#setup/project-resolution.js";
3
+ import { runVercel, runVercelCaptureStdout } from "#setup/primitives/run-vercel.js";
4
+ export declare const GITHUB_TRIGGER_PATH = "/eve/v1/github";
5
+ /** Identity of the GitHub connector provisioned for an agent channel. */
6
+ export interface GitHubConnectorRef {
7
+ /** GitHub's actual @mention handle, without the `[bot]` suffix. */
8
+ appSlug: string;
9
+ id: string;
10
+ uid: string;
11
+ }
12
+ /** Effects used to provision a GitHub Connect connector. */
13
+ export interface ProvisionGitHubConnectorDeps {
14
+ runVercel: typeof runVercel;
15
+ runVercelCaptureStdout: typeof runVercelCaptureStdout;
16
+ }
17
+ /** Parses `vercel connect create -F json` output for an app-scoped GitHub connector. */
18
+ export declare function parseCreatedGitHubConnector(stdout: string): Omit<GitHubConnectorRef, "appSlug"> | undefined;
19
+ /** Creates a GitHub connector and routes its verified webhooks to eve. */
20
+ export declare function provisionGitHubConnector(input: {
21
+ events: readonly string[];
22
+ log: ChannelSetupLog;
23
+ project: VercelProjectReference;
24
+ projectRoot: string;
25
+ slug: string;
26
+ signal?: AbortSignal;
27
+ deps?: ProvisionGitHubConnectorDeps;
28
+ }): Promise<GitHubConnectorRef>;
@@ -0,0 +1 @@
1
+ import{array,literal,object,string}from"../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/schemas.js";import"../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js";import{runVercel,runVercelCaptureStdout}from"#setup/primitives/run-vercel.js";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";import{replaceConnectTrigger}from"#setup/connect-provisioning.js";const GITHUB_TRIGGER_PATH=`/eve/v1/github`,GitHubConnectorRefSchema=object({id:string().min(1),uid:string().min(1),supportedSubjectTypes:array(string()).refine(e=>e.includes(`app`))}),GitHubConnectorDetailsSchema=object({data:object({appSlug:string().min(1)}),id:string().min(1),type:literal(`github`),uid:string().min(1)});function parseCreatedGitHubConnector(e){try{let t=GitHubConnectorRefSchema.safeParse(JSON.parse(e));return t.success?{id:t.data.id,uid:t.data.uid}:void 0}catch{return}}function parseGitHubConnectorDetails(e,t){try{let n=GitHubConnectorDetailsSchema.safeParse(JSON.parse(e));return!n.success||n.data.id!==t.id||n.data.uid!==t.uid?void 0:{...t,appSlug:n.data.data.appSlug}}catch{return}}async function provisionGitHubConnector(e){let t=e.deps??{runVercel,runVercelCaptureStdout},n=createPromptCommandOutput(e.log),r=await withPhase(e.log,`Creating GitHub connector...`,()=>t.runVercelCaptureStdout([`connect`,`create`,`github`,`--name`,e.slug,`--triggers`,...e.events.flatMap(e=>[`--trigger-event`,e]),`-F`,`json`,`--scope`,e.project.orgId],{cwd:e.projectRoot,nonInteractive:!0,onOutput:n,signal:e.signal}));if(e.signal?.throwIfAborted(),!r.ok){let e=[r.stderr,r.stdout].find(e=>e!==void 0&&e.trim().length>0);throw Error(e?`GitHub connector creation failed:\n${e}`:`GitHub connector creation failed.`)}let i=parseCreatedGitHubConnector(r.stdout);if(i===void 0)throw Error(`Vercel returned an invalid GitHub connector.`);let a=await withPhase(e.log,`Reading GitHub App details...`,()=>t.runVercelCaptureStdout([`api`,`/v1/connect/connectors/${encodeURIComponent(i.id)}`,`--scope`,e.project.orgId,`--raw`],{cwd:e.projectRoot,nonInteractive:!0,onOutput:n,signal:e.signal}));if(e.signal?.throwIfAborted(),!a.ok)throw Error(`Could not read the created GitHub connector.`);let o=parseGitHubConnectorDetails(a.stdout,i);if(o===void 0)throw Error(`Vercel returned invalid details for the GitHub connector.`);let s=await withPhase(e.log,`Connecting GitHub webhooks...`,()=>replaceConnectTrigger({connectorUid:o.uid,projectRoot:e.projectRoot,projectId:e.project.projectId,orgId:e.project.orgId,environment:`production`,triggerPath:GITHUB_TRIGGER_PATH,onOutput:n,signal:e.signal,deps:t}));if(e.signal?.throwIfAborted(),s.state!==`attached`)throw Error(`GitHub connector was created, but its trigger could not be attached. Run \`vercel connect attach ${o.uid} --project ${e.project.projectId} --environment production --triggers --trigger-path ${GITHUB_TRIGGER_PATH} --yes --scope ${e.project.orgId}\`.`);return o}export{GITHUB_TRIGGER_PATH,parseCreatedGitHubConnector,provisionGitHubConnector};
@@ -0,0 +1,15 @@
1
+ import { ensureVercelProject } from "#setup/flows/ensure-vercel-project.js";
2
+ import { deriveSlackConnectorSlug } from "#setup/scaffold/index.js";
3
+ import { writeTextFile } from "#setup/scaffold/files.js";
4
+ import type { IntegrationSetupContext, IntegrationSetupResult, SetupIntegration } from "../types.js";
5
+ import { provisionGitHubConnector } from "./connect.js";
6
+ export interface GitHubSetupDeps {
7
+ deriveConnectorSlug: typeof deriveSlackConnectorSlug;
8
+ ensureVercelProject: typeof ensureVercelProject;
9
+ provisionConnector: typeof provisionGitHubConnector;
10
+ writeTextFile: typeof writeTextFile;
11
+ }
12
+ /** Runs guided GitHub App connector and channel setup. */
13
+ export declare function setupGitHub(context: IntegrationSetupContext, deps?: GitHubSetupDeps): Promise<IntegrationSetupResult>;
14
+ /** GitHub App setup registration. */
15
+ export declare const GITHUB_SETUP: SetupIntegration;
@@ -0,0 +1,15 @@
1
+ import{provisionGitHubConnector}from"./connect.js";import{join}from"node:path";import{deriveSlackConnectorSlug}from"#setup/scaffold/index.js";import{WizardCancelledError}from"#setup/step.js";import{ensureVercelProject}from"#setup/flows/ensure-vercel-project.js";import{writeTextFile}from"#setup/scaffold/files.js";const defaultDeps={deriveConnectorSlug:deriveSlackConnectorSlug,ensureVercelProject,provisionConnector:provisionGitHubConnector,writeTextFile},githubEventsQuestion={key:`github-events`,message:`What should this GitHub App respond to?`,options:[{id:`issue_comment`,label:`New issue and PR comments`,value:`issue_comment`,hint:"Reply when a new timeline comment includes `@<bot-name>`."},{id:`pull_request_review_comment`,label:`New inline PR review comments`,value:`pull_request_review_comment`,hint:"Reply when a new inline review comment includes `@<bot-name>`."},{id:`issues`,label:`New issues`,value:`issues`,hint:`Add comments to new issues.`},{id:`pull_request`,label:`New PRs`,value:`pull_request`,hint:`Add comments to new pull requests.`}],recommended:[`issue_comment`,`pull_request_review_comment`],requireSelection:!0};function connectTemplate(e,t,n){let r=[n.includes(`issues`)?` onIssue(ctx, issue) {
2
+ if (issue.action !== "opened") return null;
3
+ return { auth: defaultGitHubAuth(ctx) };
4
+ },`:void 0,n.includes(`pull_request`)?` onPullRequest(ctx, pullRequest) {
5
+ if (pullRequest.action !== "opened") return null;
6
+ return { auth: defaultGitHubAuth(ctx) };
7
+ },`:void 0].filter(e=>e!==void 0),i=r.length>0?`, defaultGitHubAuth`:``,a=r.length>0?`\n${r.join(`
8
+ `)}`:``;return`import { connectGitHubCredentials } from "@vercel/connect/eve";
9
+ import { githubChannel${i} } from "eve/channels/github";
10
+
11
+ export default githubChannel({
12
+ botName: ${JSON.stringify(t)},
13
+ credentials: connectGitHubCredentials(${JSON.stringify(e)}),${a}
14
+ });
15
+ `}async function setupGitHub(e,n=defaultDeps){if(e.environment.vercel.kind===`unavailable`)throw Error("GitHub setup requires an authenticated Vercel CLI. Run `vercel login`, then retry.");try{e.ui.prompter.log.info(`GitHub App`),e.ui.prompter.log.info(`Vercel Connect creates a GitHub App and routes verified webhooks to your deployed agent.`);let r=await e.ui.asker.askMany(githubEventsQuestion),i=await n.ensureVercelProject({appRoot:e.appRoot,prompter:e.ui.prompter,signal:e.signal}),a=await n.provisionConnector({log:e.ui.prompter.log,events:r,project:i,projectRoot:e.appRoot,slug:await n.deriveConnectorSlug(e.appRoot),signal:e.signal});return await n.writeTextFile(join(e.appRoot,`agent/channels/github.ts`),connectTemplate(a.uid,a.appSlug,r),{force:e.force}),e.ui.nextSteps([`Deploy the agent, then open the GitHub App in Vercel Connect and install it in the organization or account where you want to use it.`,`Add @${a.appSlug} to a new issue, pull request, or review comment to invoke the agent. GitHub may not autocomplete or render the token as a linked mention.`]),{kind:`done`,facts:[{label:`Vercel Connect`,value:`https://vercel.com/d?to=/%5Bteam%5D/~/connect&title=Open+Vercel+Connect`,kind:`url`}]}}catch(e){if(e instanceof WizardCancelledError)return{kind:`cancelled`};throw e}}const GITHUB_SETUP={kind:`github`,label:`GitHub`,hint:`Respond to issues, pull requests, and comments`,setup:setupGitHub};export{GITHUB_SETUP,setupGitHub};
@@ -4,4 +4,4 @@ import { linearChannel } from "eve/channels/linear";
4
4
  export default linearChannel({
5
5
  credentials: connectLinearCredentials(${JSON.stringify(e)}),
6
6
  });
7
- `}async function chooseConnector(e,t,n){let r=linearSafeConnectorSlug(await t.deriveConnectorSlug(e.appRoot)),i=linearSafeConnectorSlug(await e.ui.asker.ask(text({key:`linear.connector-name`,message:`Name your Linear agent`,recommended:r,validate:e=>e.trim().length===0?`A Linear agent name is required.`:null}))),a=await t.findConnector({project:n,projectRoot:e.appRoot,slug:i,signal:e.signal});if(a!==void 0){let r=await e.ui.asker.ask(select({key:`linear.existing-connector`,message:`A Linear connector named "${i}" already exists. What would you like to do?`,options:[{id:`reuse`,label:`Reuse existing connector`,value:`reuse`},{id:`new`,label:`Create a new connector`,value:`new`},{id:`exit`,label:`Exit setup`,value:`exit`}],recommended:`reuse`}));if(r===`exit`)return;if(r===`reuse`)return await t.attachConnector({connector:a,log:e.ui.prompter.log,project:n,projectRoot:e.appRoot,signal:e.signal}),a}let o=a===void 0?i:linearSafeConnectorSlug(await e.ui.asker.ask(text({key:`linear.new-connector-name`,message:`Name the new Linear agent`,recommended:`${i}-2`,validate:e=>e.trim().length===0?`A Linear agent name is required.`:null})));return t.provisionConnector({log:e.ui.prompter.log,project:n,projectRoot:e.appRoot,slug:o,signal:e.signal})}async function setupLinear(e,t=defaultDeps){if(e.environment.vercel.kind===`unavailable`)throw Error("Linear setup requires an authenticated Vercel CLI. Run `vercel login`, then retry.");try{let n=await chooseConnector(e,t,await t.ensureVercelProject({appRoot:e.appRoot,prompter:e.ui.prompter,signal:e.signal}));return n===void 0?{kind:`cancelled`}:(await t.writeTextFile(join(e.appRoot,`agent/channels/linear.ts`),connectTemplate(n.uid),{force:e.force}),e.ui.nextSteps([`Deploy the agent, then open the Linear app in Vercel Connect and install it in the workspace where you want to delegate issues and comments.`,`In Linear, delegate an issue or mention the agent in an Agent Session to start a conversation.`]),{kind:`done`,facts:[{label:`Vercel Connect`,value:`https://vercel.com/d?to=/%5Bteam%5D/~/connect&title=Open+Vercel+Connect`,kind:`url`}]})}catch(e){if(e instanceof WizardCancelledError)return{kind:`cancelled`};throw e}}const LINEAR_SETUP={kind:`linear`,label:`Linear Agent`,hint:`Delegate Linear issues and comments`,setup:setupLinear};export{LINEAR_SETUP,linearSafeConnectorSlug,setupLinear};
7
+ `}async function chooseConnector(e,t,n){let r=linearSafeConnectorSlug(await t.deriveConnectorSlug(e.appRoot)),i=linearSafeConnectorSlug(await e.ui.asker.ask(text({key:`linear.connector-name`,message:`Name your Linear agent`,recommended:r,validate:e=>e.trim().length===0?`A Linear agent name is required.`:null}))),a=await t.findConnector({project:n,projectRoot:e.appRoot,slug:i,signal:e.signal});if(a!==void 0){let r=await e.ui.asker.ask(select({key:`linear.existing-connector`,message:`A Linear connector named "${i}" already exists. What would you like to do?`,options:[{id:`reuse`,label:`Reuse existing connector`,value:`reuse`},{id:`new`,label:`Create a new connector`,value:`new`},{id:`exit`,label:`Exit setup`,value:`exit`}],recommended:`reuse`}));if(r===`exit`)return;if(r===`reuse`)return await t.attachConnector({connector:a,log:e.ui.prompter.log,project:n,projectRoot:e.appRoot,signal:e.signal}),a}let o=a===void 0?i:linearSafeConnectorSlug(await e.ui.asker.ask(text({key:`linear.new-connector-name`,message:`Name the new Linear agent`,recommended:`${i}-2`,validate:e=>e.trim().length===0?`A Linear agent name is required.`:null})));return t.provisionConnector({log:e.ui.prompter.log,project:n,projectRoot:e.appRoot,slug:o,signal:e.signal})}async function setupLinear(e,t=defaultDeps){if(e.environment.vercel.kind===`unavailable`)throw Error("Linear setup requires an authenticated Vercel CLI. Run `vercel login`, then retry.");try{let n=await chooseConnector(e,t,await t.ensureVercelProject({appRoot:e.appRoot,prompter:e.ui.prompter,signal:e.signal}));return n===void 0?{kind:`cancelled`}:(await t.writeTextFile(join(e.appRoot,`agent/channels/linear.ts`),connectTemplate(n.uid),{force:e.force}),{kind:`done`,facts:[{label:`Vercel Connect`,value:`https://vercel.com/d?to=/%5Bteam%5D/~/connect&title=Open+Vercel+Connect`,kind:`url`},{label:`Next step`,value:`Deploy the agent, then open the Linear app in Vercel Connect and install it in the workspace where you want to delegate issues and comments.`},{label:`In Linear`,value:`Delegate an issue or mention the agent in an Agent Session to start a conversation.`}]})}catch(e){if(e instanceof WizardCancelledError)return{kind:`cancelled`};throw e}}const LINEAR_SETUP={kind:`linear`,label:`Linear Agent`,hint:`Delegate Linear issues and comments`,setup:setupLinear};export{LINEAR_SETUP,linearSafeConnectorSlug,setupLinear};
@@ -1 +1 @@
1
- import{DISCORD_SETUP}from"./discord/setup.js";import{LINEAR_SETUP}from"./linear/setup.js";import{PHOTON_SETUP}from"./photon/setup.js";import{SLACK_SETUP}from"./slack/setup.js";import{WEB_SETUP}from"./web/setup.js";import{createIntegrationSetupUi}from"./shared/ui.js";const SETUP_INTEGRATIONS=[WEB_SETUP,SLACK_SETUP,DISCORD_SETUP,LINEAR_SETUP,PHOTON_SETUP];function setupIntegration(e){let t=SETUP_INTEGRATIONS.find(t=>t.kind===e);if(t===void 0)throw Error(`Integration setup "${e}" is not available in this version of eve. Upgrade eve and try again.`);return t}export{SETUP_INTEGRATIONS,createIntegrationSetupUi,setupIntegration};
1
+ import{DISCORD_SETUP}from"./discord/setup.js";import{GITHUB_SETUP}from"./github/setup.js";import{LINEAR_SETUP}from"./linear/setup.js";import{PHOTON_SETUP}from"./photon/setup.js";import{SLACK_SETUP}from"./slack/setup.js";import{WEB_SETUP}from"./web/setup.js";import{createIntegrationSetupUi}from"./shared/ui.js";const SETUP_INTEGRATIONS=[WEB_SETUP,SLACK_SETUP,DISCORD_SETUP,GITHUB_SETUP,LINEAR_SETUP,PHOTON_SETUP];function setupIntegration(e){let t=SETUP_INTEGRATIONS.find(t=>t.kind===e);if(t===void 0)throw Error(`Integration setup "${e}" is not available in this version of eve. Upgrade eve and try again.`);return t}export{SETUP_INTEGRATIONS,createIntegrationSetupUi,setupIntegration};
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.38`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.3`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.30.6`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
1
+ import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.38`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.3`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.30.8`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
2
2
 
3
3
  export default defineAgent({
4
4
  model: "__EVE_INIT_MODEL__",
@@ -0,0 +1,2 @@
1
+ /** Returns whether a value can produce values asynchronously. */
2
+ export declare function isAsyncIterable<T = unknown>(value: unknown): value is AsyncIterable<T>;
@@ -0,0 +1 @@
1
+ function isAsyncIterable(e){return typeof e==`object`&&!!e&&Symbol.asyncIterator in e&&typeof e[Symbol.asyncIterator]==`function`}export{isAsyncIterable};
@@ -6,7 +6,7 @@ import type { JsonObject } from "#shared/json.js";
6
6
  * function. These are the same options the SDK passes to every tool call.
7
7
  */
8
8
  export type ToolExecuteOptions = Omit<ToolExecutionOptions<unknown>, "context">;
9
- export type ToolExecuteFn<TInput = unknown, TOutput = unknown> = (input: TInput, options: ToolExecuteOptions) => Promise<TOutput> | TOutput;
9
+ export type ToolExecuteFn<TInput = unknown, TOutput = unknown> = (input: TInput, options: ToolExecuteOptions) => Promise<TOutput> | TOutput | AsyncIterable<TOutput>;
10
10
  interface ToolDefinitionBase {
11
11
  readonly description: string;
12
12
  }
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-BXMIf5fR.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-Bx-ONuyb.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-BXMIf5fR.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-Bx-ONuyb.js";
2
2
 
3
3
  export { useEveAgent };
@@ -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,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-k-XHfrJT.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-DDoDDmJ2.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-k-XHfrJT.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-DDoDDmJ2.js";
2
2
 
3
3
  export { useEveAgent };
@@ -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
 
@@ -11,10 +11,12 @@ The Linear channel uses Linear's Agent Session surface rather than ordinary comm
11
11
  Run the registry setup from the agent directory:
12
12
 
13
13
  ```bash
14
- eve add channel/linear-agent
14
+ eve add linear
15
15
  ```
16
16
 
17
- The flow checks that the Vercel CLI is authenticated, creates or links a Vercel project when needed, provisions an app-scoped Linear Connect client, and replaces its default trigger with `/eve/v1/linear`. It then installs `@vercel/connect` and writes `agent/channels/linear.ts` with the connector UID.
17
+ Select **Linear Channel** in the component checklist. **Linear MCP** is also selected by default if you want the agent to search and update Linear through MCP. Run `eve add channel/linear-agent` instead to install only the channel directly.
18
+
19
+ The flow checks that the Vercel CLI is authenticated, creates or links a Vercel project when needed, reuses a compatible existing connector when available or provisions an app-scoped Linear Connect client, and replaces its default trigger with `/eve/v1/linear`. It then installs `@vercel/connect` and writes `agent/channels/linear.ts` with the connector UID.
18
20
 
19
21
  Vercel Connect creates the Linear app with the `app:assignable` and `app:mentionable` scopes required for Agent Sessions, receives and verifies `AgentSessionEvent` webhooks, and forwards them to the deployed agent. After deploying, open the Linear app in the Connect dashboard and install it in the workspace where you want to delegate work. Then delegate an issue or mention the agent in a Linear Agent Session.
20
22
 
@@ -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
@@ -47,6 +47,7 @@ The stream is newline-delimited JSON (NDJSON), one event per line:
47
47
  | `message.received` | An inbound user message was accepted; carries flattened text plus structured text/file parts. |
48
48
  | `step.started` | A model step began. |
49
49
  | `actions.requested` | The model requested one or more actions, including tool calls; calls stream before execution. |
50
+ | `action.partial` | A locally executed tool generator yielded a preliminary output snapshot. |
50
51
  | `action.result` | A tool call returned. |
51
52
  | `input.requested` | The run paused for human input ([HITL](/docs/human-in-the-loop) approval or `ask_question`); carries `requests`. |
52
53
  | `subagent.called` | A subagent was delegated; carries `childSessionId` to attach to. |
@@ -71,6 +72,8 @@ The stream is newline-delimited JSON (NDJSON), one event per line:
71
72
 
72
73
  `reasoning.appended` and `message.appended` stream incremental output as it arrives. When the durable stream writer is busy, eve may coalesce adjacent deltas of the same type; the text remains in source order, and any other event forms an ordering barrier. Each append carries both the new delta and the cumulative text for the current block. The finalized block shows up on `message.completed` and `reasoning.completed`, which is the compatibility path for clients that don't render incremental streaming.
73
74
 
75
+ `action.partial` carries one complete preliminary output snapshot from an authored async-generator tool. A later partial for the same `callId` replaces it, and `action.result` is the final snapshot. When the durable writer is busy, eve may keep only the newest adjacent partial for a call. Treat partials as last-write-wins: a durable step can retry and replay overlapping event runs. Provider-executed tool progress and MCP progress notifications are not projected as `action.partial` events.
76
+
74
77
  Note: consider the privacy, confidentiality, and user-experience implications for displaying, storing, or transmitting reasoning events in your application.
75
78
 
76
79
  `message.completed` can fire more than once in a turn: the agent often emits interim assistant text before a tool call. To tell tool-call narration from a terminal reply, check `message.completed.data.finishReason`. `step.completed.data.finishReason` mirrors the step outcome, and usage lives on `step.completed`.
@@ -99,6 +99,7 @@ The most common UI events are:
99
99
  | `reasoning.appended` | Render reasoning deltas when the model provides them. |
100
100
  | `message.appended` | Render assistant text deltas. |
101
101
  | `actions.requested` | Show tool calls as the model requests them, before execution. |
102
+ | `action.partial` | Update a generator tool's provisional output snapshot. |
102
103
  | `action.result` | Show tool call results. |
103
104
  | `input.requested` | Pause the UI for approval or a question answer. |
104
105
  | `result.completed` | Read structured output from an [output schema](./output-schema). |
@@ -26,7 +26,7 @@ The slug is the path-relative basename. `agent/hooks/audit.ts` becomes `"audit"`
26
26
 
27
27
  `defineHook`, `HookDefinition`, and `HookContext` live on `eve/hooks`.
28
28
 
29
- A hook file declares stream-event subscribers under the `events` map, keyed by event type, with `*` matching every event. Subscribe to any event in the runtime stream vocabulary documented in [Sessions, runs and streaming](../concepts/sessions-runs-and-streaming), including the lifecycle events `session.started`, `turn.completed`, `message.completed`, and `action.result`. Handlers are observe-only. They cannot inject model context. To contribute runtime model messages, use `defineDynamic` and `defineInstructions` in `agent/instructions/`.
29
+ A hook file declares stream-event subscribers under the `events` map, keyed by event type, with `*` matching every event. Subscribe to any event in the runtime stream vocabulary documented in [Sessions, runs and streaming](../concepts/sessions-runs-and-streaming), including the lifecycle events `session.started`, `turn.completed`, `message.completed`, `action.partial`, and `action.result`. Handlers are observe-only. They cannot inject model context. To contribute runtime model messages, use `defineDynamic` and `defineInstructions` in `agent/instructions/`.
30
30
 
31
31
  ## Hook structure and context
32
32
 
@@ -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)
@@ -12,13 +12,15 @@ Run `eve add` from an eve agent project. This installs the integration's depende
12
12
 
13
13
  ```bash
14
14
  eve add extension/agent-browser
15
- eve add connection/linear
15
+ eve add linear
16
16
  eve add instrumentation/braintrust
17
17
  ```
18
18
 
19
19
  Extensions may create a mount under `agent/extensions/`. Connections write their initial definition under `agent/connections/` and install `@vercel/connect` when required. Instrumentation providers write `agent/instrumentation.ts`; because an agent has one instrumentation file, compose multiple exporters there by hand. Configure generated files and required environment variables before running your agent.
20
20
 
21
- When an official item has an interactive setup flow, eve asks whether to run it after installation. Run the printed `eve add <item> --skip-install` command to resume a skipped or cancelled setup later.
21
+ Some integrations package several independently installable components. For example, `eve add linear` lets you choose the Linear Channel, Linear MCP, or both; both are selected by default. The specific `eve add channel/linear-agent` and `eve add connection/linear` commands remain available.
22
+
23
+ When an official item declares an interactive setup flow or flows, eve asks whether to run them after installation and runs multiple flows in declaration order. Run the printed `eve add <item> --skip-install` command to resume a skipped or cancelled setup later; it reruns the selected components' declared flows from the beginning.
22
24
 
23
25
  ## Find an integration
24
26
 
@@ -87,6 +87,7 @@ Commands for installing and discovering [shadcn registry](https://ui.shadcn.com/
87
87
 
88
88
  ```bash
89
89
  eve add extension/agent-browser
90
+ eve add linear
90
91
  eve add channel/slack --skip-install
91
92
  eve add https://example.com/r/my-extension.json --overwrite
92
93
  eve registry add @acme=https://example.com/r/{name}.json
@@ -97,7 +98,9 @@ eve registry view @acme/my-extension
97
98
  eve add @acme/my-extension
98
99
  ```
99
100
 
100
- `eve add` asks before running setup declared by an official item and prints the matching `eve add <item> --skip-install` command when setup is skipped or cancelled. `--skip-install` reruns setup without reinstalling the item.
101
+ `eve add` asks before running setup declared by an official item and runs multiple declared flows in declaration order. Product-level packages can offer independently installable components: `eve add linear` lets you select the Linear Channel, Linear MCP, or both, with both selected by default. `--yes` installs a package's default components.
102
+
103
+ When setup is skipped or cancelled, eve prints the matching `eve add <item> --skip-install` command. `--skip-install` reruns the selected components' declared flows from the beginning without reinstalling them.
101
104
 
102
105
  `eve registry add` records configured sources in `package.json#registries`. `eve registry list` aggregates the official catalog and all configured sources by default. `eve registry search` also includes [skills.sh](https://skills.sh), available without configuration at `@skills`, and groups results by source with each source's available result count. Search returns up to 10 matches per source by default; pass `--limit <count>` to request between 1 and 100. Either command can browse one supplied URL or namespace. Official and other universal items with explicit file targets do not require shadcn project configuration.
103
106
 
@@ -254,10 +257,14 @@ eve traces ls # list traces, most recent first
254
257
  eve traces ls --json # emit machine-readable trace summaries
255
258
  eve traces # show the most recent span tree
256
259
  eve traces <trace> # show one span tree
260
+ eve traces --verbose # expand every span with all attributes and events
261
+ eve traces --json # dump the full trace as JSON
257
262
  ```
258
263
 
259
264
  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
265
 
266
+ 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.
267
+
261
268
  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
269
 
263
270
  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
@@ -28,10 +28,34 @@ A tool definition needs:
28
28
  - a filename slug under `agent/tools/`, the model-facing name.
29
29
  - a `description`: what the tool does, written for the model.
30
30
  - an `inputSchema`: a Zod schema (or any Standard Schema, or a plain JSON Schema object). Required. For no input, pass `z.object({})`. Zod and Standard Schema infer the `input` type in `execute`. Plain JSON Schema types it as `Record<string, unknown>`.
31
- - an `execute(input, ctx)`: the implementation. May be sync or async.
31
+ - an `execute(input, ctx)`: the implementation. May be sync, async, or an async generator.
32
32
 
33
33
  When a tool returns structured data, add an optional `outputSchema`. With Zod or Standard Schema it also types the `execute` return.
34
34
 
35
+ ### Stream preliminary tool results
36
+
37
+ An async generator lets a long-running tool stream complete output snapshots
38
+ before it finishes. Each `yield` replaces the previous snapshot; the final
39
+ yield is the normal tool result the model receives:
40
+
41
+ ```ts title="agent/tools/build_report.ts"
42
+ export default defineTool({
43
+ description: "Build a project report.",
44
+ inputSchema: z.object({ project: z.string() }),
45
+ async *execute({ project }) {
46
+ yield { phase: "collecting", report: null };
47
+ const report = await buildReport(project);
48
+ yield { phase: "complete", report };
49
+ },
50
+ });
51
+ ```
52
+
53
+ eve publishes every earlier yield as an `action.partial` stream event. The
54
+ snapshot is visible to channels, hooks, and clients but never enters model
55
+ history or `toModelOutput`; only the final yield does. Treat snapshots as
56
+ last-write-wins by tool call id, not append-only progress. The durable runtime
57
+ can retry a step and replay overlapping snapshots.
58
+
35
59
  ### The `ctx` parameter
36
60
 
37
61
  `execute` gets a `ctx` carrying the runtime accessors:
@@ -78,7 +102,7 @@ toModelOutput(output) {
78
102
  },
79
103
  ```
80
104
 
81
- `toModelOutput` receives the full, typed `execute` return and only affects the model. Channel event handlers and hooks still get the full output on `action.result`, so a channel can render rich platform output (Slack Block Kit, say) the model never sees. Return `{ type: "text", value }` for a summary, or `{ type: "json", value }` for a smaller object.
105
+ `toModelOutput` receives the final, typed `execute` return and only affects the model. Channel event handlers and hooks still get the full output on `action.result`, so a channel can render rich platform output (Slack Block Kit, say) the model never sees. Return `{ type: "text", value }` for a summary, or `{ type: "json", value }` for a smaller object.
82
106
 
83
107
  Tool outputs must be JSON-serializable. Return plain objects, arrays, strings, numbers, booleans, or `null`; convert values like `Date`, `Map`, `Set`, `NaN`, and cyclic objects before returning them from `execute` or from a `{ type: "json" }` `toModelOutput`.
84
108
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve",
3
- "version": "0.30.6",
3
+ "version": "0.30.8",
4
4
  "private": false,
5
5
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
6
6
  "keywords": [