eve 0.54.3 → 0.54.4

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 (114) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/src/cli/commands/init-agent-workspace.js +1 -1
  3. package/dist/src/cli/commands/init-project.d.ts +46 -0
  4. package/dist/src/cli/commands/init-project.js +1 -0
  5. package/dist/src/cli/commands/init-self-modification.d.ts +7 -0
  6. package/dist/src/cli/commands/init-self-modification.js +1 -0
  7. package/dist/src/cli/commands/init-target.js +2 -2
  8. package/dist/src/cli/commands/init-telemetry.d.ts +6 -0
  9. package/dist/src/cli/commands/init-telemetry.js +1 -0
  10. package/dist/src/cli/commands/init.d.ts +3 -0
  11. package/dist/src/cli/commands/init.js +1 -1
  12. package/dist/src/cli/telemetry/index.d.ts +1 -1
  13. package/dist/src/compiled/.vendor-stamp.json +6 -6
  14. package/dist/src/compiled/@ai-sdk/anthropic/index.js +2 -2
  15. package/dist/src/compiled/@ai-sdk/google/index.js +7 -7
  16. package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
  17. package/dist/src/compiled/@ai-sdk/openai/index.js +4 -4
  18. package/dist/src/compiled/@opentelemetry/api/index.d.ts +2 -0
  19. package/dist/src/compiled/@workflow/core/events-consumer.d.ts +26 -0
  20. package/dist/src/compiled/@workflow/core/flushable-stream.d.ts +41 -0
  21. package/dist/src/compiled/@workflow/core/index.js +2 -2
  22. package/dist/src/compiled/@workflow/core/replay-divergence.d.ts +25 -0
  23. package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +75 -1
  24. package/dist/src/compiled/@workflow/core/runtime/quickjs-entrypoint.d.ts +30 -8
  25. package/dist/src/compiled/@workflow/core/runtime/quickjs-log-view.d.ts +129 -0
  26. package/dist/src/compiled/@workflow/core/runtime/step-executor.d.ts +2 -21
  27. package/dist/src/compiled/@workflow/core/runtime/suspension-handler.d.ts +0 -22
  28. package/dist/src/compiled/@workflow/core/runtime.js +3 -3
  29. package/dist/src/compiled/@workflow/core/serialization.d.ts +2 -2
  30. package/dist/src/compiled/@workflow/core/step/context-storage.d.ts +2 -0
  31. package/dist/src/compiled/@workflow/core/telemetry/semantic-conventions.d.ts +36 -0
  32. package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
  33. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  34. package/dist/src/compiled/@workflow/world/analytics.d.ts +23 -23
  35. package/dist/src/compiled/@workflow/world/events.d.ts +4 -2
  36. package/dist/src/compiled/@workflow/world/queue.d.ts +84 -0
  37. package/dist/src/compiled/@workflow/world-local/index.js +5 -5
  38. package/dist/src/compiled/@workflow/world-vercel/index.js +18 -13
  39. package/dist/src/compiled/_chunks/workflow/attribute-changes-BAcgmlXp.js +20 -0
  40. package/dist/src/compiled/_chunks/workflow/coerce-ro2dOxbr.js +1 -0
  41. package/dist/src/compiled/_chunks/workflow/dist-KPieTJHT.js +25 -0
  42. package/dist/src/compiled/_chunks/workflow/dist-PLkAQ-U7.js +2 -0
  43. package/dist/src/compiled/_chunks/workflow/frames-BvATzM2t.js +3 -0
  44. package/dist/src/compiled/_chunks/workflow/{functions-C02-JHBK.js → functions-wMCGZAVk.js} +1 -1
  45. package/dist/src/compiled/_chunks/workflow/resume-hook-BEHe0Uut.js +1 -0
  46. package/dist/src/compiled/_chunks/workflow/run-ChHLjaCt.js +1 -0
  47. package/dist/src/compiled/_chunks/workflow/schemas-DR7NTzNe.js +50 -0
  48. package/dist/src/compiled/_chunks/workflow/sleep-BB2HuVie.js +1 -0
  49. package/dist/src/compiled/_chunks/workflow/{wrapper-BxECO5nh.js → wrapper-CKui_eTd.js} +2 -2
  50. package/dist/src/compiled/_chunks/workflow/ws-transport-CVezyWwZ.js +1 -0
  51. package/dist/src/compiler/extension-compatibility.d.ts +10 -10
  52. package/dist/src/compiler/extension-compatibility.js +1 -1
  53. package/dist/src/context/dynamic-model-lifecycle.d.ts +0 -6
  54. package/dist/src/context/dynamic-model-lifecycle.js +1 -1
  55. package/dist/src/context/dynamic-resolve-context.js +1 -1
  56. package/dist/src/context/effective-model.d.ts +5 -0
  57. package/dist/src/context/effective-model.js +1 -0
  58. package/dist/src/context/keys.d.ts +2 -0
  59. package/dist/src/context/keys.js +1 -1
  60. package/dist/src/dynamic/definition.d.ts +4 -0
  61. package/dist/src/eve-channel/index.js +1 -1
  62. package/dist/src/eve-channel/types.d.ts +9 -7
  63. package/dist/src/execution/eve-workflow-attributes.d.ts +1 -1
  64. package/dist/src/execution/run-session-limits.js +1 -1
  65. package/dist/src/execution/session.js +1 -1
  66. package/dist/src/execution/tools/sleep-workflow.js +1 -1
  67. package/dist/src/execution/workflow-steps.js +1 -1
  68. package/dist/src/harness/tool-loop.js +2 -2
  69. package/dist/src/instrumentation/parent-lineage.js +1 -1
  70. package/dist/src/internal/application/package.js +1 -1
  71. package/dist/src/internal/vercel/build-agent-workspace.js +1 -1
  72. package/dist/src/internal/vercel/vercel-services-config.js +1 -1
  73. package/dist/src/protocol/baggage.d.ts +6 -0
  74. package/dist/src/protocol/baggage.js +1 -1
  75. package/dist/src/protocol/traceparent.d.ts +13 -0
  76. package/dist/src/protocol/traceparent.js +1 -1
  77. package/dist/src/public/models/openai/chatgpt/codex-app-server.d.ts +41 -0
  78. package/dist/src/public/models/openai/chatgpt/codex-app-server.js +1 -0
  79. package/dist/src/public/models/openai/chatgpt/credential-store.d.ts +5 -1
  80. package/dist/src/public/models/openai/chatgpt/credential-store.js +1 -1
  81. package/dist/src/public/models/openai/chatgpt/token-broker.d.ts +7 -7
  82. package/dist/src/public/models/openai/chatgpt/token-broker.js +1 -1
  83. package/dist/src/public/models/openai/chatgpt/token.d.ts +13 -0
  84. package/dist/src/public/models/openai/chatgpt/token.js +1 -0
  85. package/dist/src/public/models/openai/chatgpt/transport.d.ts +2 -1
  86. package/dist/src/public/models/openai/index.d.ts +3 -2
  87. package/dist/src/public/vercel/index.d.ts +50 -0
  88. package/dist/src/public/vercel/index.js +1 -0
  89. package/dist/src/self-modification/setup.js +7 -2
  90. package/dist/src/setup/flows/chatgpt-auth.d.ts +2 -1
  91. package/dist/src/setup/flows/chatgpt-auth.js +1 -1
  92. package/dist/src/setup/scaffold/create/project.js +1 -1
  93. package/dist/src/subagents/remote-dispatch.d.ts +3 -1
  94. package/dist/src/subagents/remote-dispatch.js +1 -1
  95. package/dist/src/tracing/agent-otel-attributes.js +1 -1
  96. package/dist/src/tracing/agent-otel-runtime-context.js +1 -1
  97. package/docs/agent-config.md +3 -3
  98. package/docs/guides/deployment/vercel.mdx +52 -1
  99. package/docs/guides/dynamic-capabilities.md +19 -7
  100. package/docs/guides/instrumentation-providers.md +1 -1
  101. package/docs/guides/instrumentation.md +16 -6
  102. package/docs/guides/remote-agents.md +5 -5
  103. package/docs/reference/cli.md +2 -2
  104. package/docs/reference/telemetry.md +1 -1
  105. package/docs/reference/typescript-api.md +11 -8
  106. package/package.json +12 -6
  107. package/dist/src/compiled/_chunks/workflow/attribute-changes-C6H-fRVP.js +0 -20
  108. package/dist/src/compiled/_chunks/workflow/dist-DDeH-1ER.js +0 -40
  109. package/dist/src/compiled/_chunks/workflow/dist-DhncQSl7.js +0 -74
  110. package/dist/src/compiled/_chunks/workflow/frames-DsEqSDes.js +0 -3
  111. package/dist/src/compiled/_chunks/workflow/resume-hook-BRDLAb67.js +0 -1
  112. package/dist/src/compiled/_chunks/workflow/run-BM2OFphk.js +0 -1
  113. package/dist/src/compiled/_chunks/workflow/sleep-6cG0F99-.js +0 -1
  114. package/dist/src/compiled/_chunks/workflow/ws-transport-DuK82LLz.js +0 -1
@@ -0,0 +1,50 @@
1
+ /** A route accepted by eve's Vercel configuration composer. */
2
+ export interface EveVercelRouteConfig {
3
+ readonly destination?: string | {
4
+ readonly service?: string;
5
+ readonly type?: string;
6
+ };
7
+ readonly handle?: string;
8
+ readonly src?: string;
9
+ readonly transforms?: readonly Record<string, unknown>[];
10
+ readonly [key: string]: unknown;
11
+ }
12
+ /** A service accepted by eve's Vercel configuration composer. */
13
+ export interface EveVercelServiceConfig {
14
+ readonly buildCommand?: string;
15
+ readonly entrypoint?: string;
16
+ readonly framework?: string;
17
+ readonly mount?: string | {
18
+ readonly path?: string;
19
+ readonly subdomain?: string;
20
+ };
21
+ readonly routes?: readonly EveVercelRouteConfig[];
22
+ readonly root?: string;
23
+ readonly type?: string;
24
+ readonly [key: string]: unknown;
25
+ }
26
+ /** The portion of a programmatic Vercel configuration composed by eve. */
27
+ export interface EveVercelConfig {
28
+ readonly experimentalServices?: unknown;
29
+ readonly experimentalServicesV2?: unknown;
30
+ readonly routes?: readonly EveVercelRouteConfig[];
31
+ readonly services?: Readonly<Record<string, EveVercelServiceConfig>> | readonly (EveVercelServiceConfig & {
32
+ readonly name: string;
33
+ })[];
34
+ readonly [key: string]: unknown;
35
+ }
36
+ /** Options for composing an eve workspace into a programmatic Vercel configuration. */
37
+ export interface WithEveOptions {
38
+ /** Eve workspace root. Defaults to the directory evaluating `vercel.ts`. */
39
+ readonly root?: string;
40
+ }
41
+ /**
42
+ * Add a hostless eve workspace's generated agent services and transport routes to `vercel.ts`.
43
+ *
44
+ * The returned object is a plain Vercel configuration. Vercel resolves it before independently
45
+ * building the authored services and each generated eve agent service.
46
+ */
47
+ export declare function withEve<TConfig extends EveVercelConfig>(config: TConfig, options?: WithEveOptions): Promise<Omit<TConfig, "routes" | "services"> & {
48
+ readonly routes: readonly EveVercelRouteConfig[];
49
+ readonly services: Readonly<Record<string, EveVercelServiceConfig>>;
50
+ }>;
@@ -0,0 +1 @@
1
+ import{mkdir}from"node:fs/promises";import{join,resolve}from"node:path";import{resolveEveProjectContext}from"#internal/project-context.js";import{createServiceConfigRecord}from"#internal/vercel/vercel-services-config.js";import{createEveServiceName,createEveServiceRouteSrc}from"#internal/vercel/eve-service-contribution.js";import{assembleEveVercelServices}from"#internal/vercel/assemble-eve-services.js";import{quoteVercelShellArgument,toVercelRelativePath}from"#internal/vercel/build-command.js";import{resolveEveBinaryPath}from"#shared/resolve-eve-binary.js";function toInternalConfig(e){return e}function assertComposableConfig(e,t){if(e.experimentalServices!==void 0||e.experimentalServicesV2!==void 0)throw Error(`withEve cannot compose experimentalServices or experimentalServicesV2. Remove the obsolete field and define authored services under services.`);let n=toInternalConfig(e),r=createServiceConfigRecord(n.services);for(let n of t){let t=createEveServiceName(n);if(Object.hasOwn(r,t))throw Error(`Vercel service key ${JSON.stringify(t)} conflicts with the service generated for eve workspace agent ${JSON.stringify(n)}. Remove or rename the authored service; withEve owns this key.`);let i=createEveServiceRouteSrc(`/${n}`);if(e.routes?.some(e=>e.src===i))throw Error(`Vercel route ${JSON.stringify(i)} conflicts with the transport route generated for eve workspace agent ${JSON.stringify(n)}. Remove the authored route; withEve adds it automatically.`)}}async function withEve(e,t={}){let n=resolve(t.root??process.cwd()),r=await resolveEveProjectContext(n);if(r.kind!==`workspace`||r.workspace.root!==n)throw Error(`withEve must run at an eve workspace root; received ${n}.`);let{workspace:i}=r;if(i.members.length===0)throw Error(`withEve found no workspace agents under ${join(n,`agents`)}. Add an agent or remove withEve from vercel.ts.`);let a=i.members.map(e=>e.name),o=new Set(a.map(createEveServiceName));assertComposableConfig(e,a);let s=join(n,`.vercel`,`output`),c=toInternalConfig(e),l=assembleEveVercelServices({agents:i.members.map(e=>({agent:{appRoot:e.appRoot,buildCommand:`node ${quoteVercelShellArgument(toVercelRelativePath(e.appRoot,resolveEveBinaryPath(e.appRoot)))} build`,name:e.name,publicRoutePrefix:`/${e.name}`,workspaceMember:!0},target:{hostOutputDirectory:s,projectRoot:n}})),routes:c.routes,services:createServiceConfigRecord(c.services)});await Promise.all(l.rootDirectories.map(e=>mkdir(e,{recursive:!0})));let u=Object.fromEntries(Object.entries(l.services).map(([e,t])=>{if(!o.has(e))return[e,t];let{routePrefix:n,...r}=t;return[e,r]}));return{...e,routes:l.routes,services:u}}export{withEve};
@@ -1,6 +1,8 @@
1
1
  import{SELF_MODIFICATION_CONFIG_PATH}from"./git-workspace.js";import{createHash}from"node:crypto";import{readFile,writeFile}from"node:fs/promises";import{join,relative}from"node:path";import{discoverAgent}from"#discover/discover-agent.js";import{execFile}from"node:child_process";import{promisify}from"node:util";import{stripLogicalPathExtension}from"#discover/filesystem.js";const runFile=promisify(execFile);function connectorName(e,t){return`selfmod-${e}-${t}`.toLowerCase().replaceAll(/[^a-z0-9-]/gu,`-`)}function renderSelfModificationConfig(e){if(e===void 0)return`import { defineSelfModificationConfig } from "eve/self-modification/config";
2
2
 
3
- export default defineSelfModificationConfig({});
3
+ export default defineSelfModificationConfig({
4
+ local: { enabled: true },
5
+ });
4
6
  `;let t=[...new Set(e.channelNames)].filter(e=>e!==`eve`).sort(),n=(e.vercelBackend?t:[]).map(e=>` case ${JSON.stringify(`channel:${e}`)}:
5
7
  // Authorize trusted principals for this channel before returning true.
6
8
  return false;`).join(`
@@ -38,6 +40,9 @@ ${r} default:
38
40
  },
39
41
  },
40
42
  });
41
- `;return`// eve-self-modification: generated-v1 digest:${createHash(`sha256`).update(i).digest(`hex`)}\n${i}`}function classifySelfModificationConfig(e){if(e===void 0)return`missing`;if(e===renderSelfModificationConfig())return`local`;let[t,...n]=e.split(`
43
+ `;return`// eve-self-modification: generated-v1 digest:${createHash(`sha256`).update(i).digest(`hex`)}\n${i}`}function classifySelfModificationConfig(e){if(e===void 0)return`missing`;if(e===renderSelfModificationConfig()||e===`import { defineSelfModificationConfig } from "eve/self-modification/config";
44
+
45
+ export default defineSelfModificationConfig({});
46
+ `)return`local`;let[t,...n]=e.split(`
42
47
  `);return/^\/\/ eve-self-modification: generated-v1 digest:([a-f0-9]{64})$/u.exec(t??``)?.[1]===createHash(`sha256`).update(n.join(`
43
48
  `)).digest(`hex`)?`generated`:`authored`}function parseGitHubRemote(e){let t=e.trim().match(/^(?:https?:\/\/github\.com\/|git@github\.com:|ssh:\/\/git@github\.com\/)([^/]+)\/([^/]+?)(?:\.git)?$/u);return t?.[1]===void 0||t[2]===void 0?void 0:{owner:t[1],repo:t[2]}}function defaultSelfModificationSetupOperations(e){let t=join(e,SELF_MODIFICATION_CONFIG_PATH);return{async detectChannelNames(){return(await discoverAgent({appRoot:e,agentRoot:join(e,`agent`)})).manifest.channels.map(e=>stripLogicalPathExtension(e.logicalPath).replace(/^channels\//,``))},async detectGitRepository(){let t=await gitOutput(e,[`config`,`--get`,`remote.origin.url`]),n=t===void 0?void 0:parseGitHubRemote(t),r=await gitOutput(e,[`symbolic-ref`,`--quiet`,`--short`,`refs/remotes/origin/HEAD`]),i=await gitOutput(e,[`rev-parse`,`--show-toplevel`]);return{...n,branch:r?.replace(/^origin\//u,``),directory:i===void 0?void 0:repositoryRelativeDirectory(i,e),remoteKind:t===void 0?`missing`:n===void 0?`other`:`github`}},async readConfig(){try{return await readFile(t,`utf8`)}catch(e){if(e.code===`ENOENT`)return;throw e}},writeConfig:e=>writeFile(t,e,`utf8`),async findOrCreateConnector(t){let n=await vercel(e,[`connect`,`list`,`-F`,`json`]);if(!n.ok)throw Error(`Vercel Connect requires an authenticated Vercel CLI linked to this project.`);let r=parseConnectors(n.stdout),i=`github/${t}`,a=r.find(e=>e.uid===i);if(a!==void 0){if(a.type!==`github`)throw Error(`The existing connector ${i} is not a GitHub connector.`);return a.uid}let o=await vercel(e,[`connect`,`create`,`github`,`--name`,t,`-F`,`json`]),s=o.ok?parseCreatedConnector(o.stdout):void 0;if(s===void 0||!s.startsWith(`github/`))throw Error(`Could not create a GitHub Vercel Connect connector.`);return s},async attachConnector(t){let n=await readLinkedProject(e);if(n===void 0)throw Error("Vercel Connect requires this directory to be linked to a Vercel project. Run `vercel link` and retry.");if(!(await vercel(e,[`connect`,`attach`,t,`--project`,n.projectId,`--environment`,`production`,`--yes`])).ok)throw Error(`Could not attach ${t} to the linked Vercel project for Production.`)}}}function parseCreatedConnector(e){try{let t=JSON.parse(e);return typeof t.uid==`string`?t.uid:void 0}catch{return}}function parseConnectors(e){try{let t=JSON.parse(e);return(Array.isArray(t.connectors)?t.connectors:[t]).flatMap(e=>typeof e==`object`&&e&&typeof e.uid==`string`&&typeof e.type==`string`?[{uid:e.uid,type:e.type}]:[])}catch{return[]}}async function vercel(e,t){try{return{ok:!0,stdout:(await runFile(`vercel`,t,{cwd:e})).stdout}}catch{return{ok:!1,stdout:``}}}async function readLinkedProject(e){try{let t=JSON.parse(await readFile(join(e,`.vercel`,`project.json`),`utf8`));return typeof t.projectId==`string`?{projectId:t.projectId}:void 0}catch{return}}function repositoryRelativeDirectory(e,t,n=relative){return n(e,t).replaceAll(`\\`,`/`)||`.`}function repositoryPartError(e){return/^[A-Za-z0-9_.-]+$/u.test(e)?void 0:`Enter a valid GitHub owner or repository name.`}function directoryError(e){return e===`.`||e.length>0&&!e.startsWith(`/`)&&!e.includes(`\\`)&&e.split(`/`).every(e=>e!==``&&e!==`.`&&e!==`..`)?void 0:`Enter a safe repository-relative directory or ".".`}function gitRefError(e){return/^[A-Za-z0-9][A-Za-z0-9._/-]*$/u.test(e)&&!e.endsWith(`.`)&&!e.endsWith(`/`)&&!e.includes(`..`)&&!e.includes(`//`)&&!e.includes(`@{`)?void 0:`Enter a valid branch name.`}async function gitOutput(e,t){try{return(await runFile(`git`,t,{cwd:e})).stdout.trim()||void 0}catch{return}}export{classifySelfModificationConfig,connectorName,defaultSelfModificationSetupOperations,directoryError,gitRefError,parseGitHubRemote,renderSelfModificationConfig,repositoryPartError,repositoryRelativeDirectory};
@@ -3,12 +3,13 @@ import { type CodexTokenBroker } from "#public/models/openai/chatgpt/token-broke
3
3
  interface ChatGptAuthOptions {
4
4
  readonly signal?: AbortSignal;
5
5
  readonly broker?: CodexTokenBroker;
6
+ readonly codexLogin?: (signal?: AbortSignal) => Promise<void>;
6
7
  readonly store?: ChatGptCredentialStore;
7
8
  readonly fetch?: typeof fetch;
8
9
  readonly open?: (url: string) => void;
9
10
  readonly log?: (message: string) => void;
10
11
  readonly headless?: boolean;
11
12
  }
12
- /** Signs in directly with OpenAI; credentials belong to eve, independently of Codex. */
13
+ /** Signs in through the credential owner selected by the ChatGPT auth facade. */
13
14
  export declare function ensureChatGptAuth(options?: ChatGptAuthOptions): Promise<void>;
14
15
  export {};
@@ -1 +1 @@
1
- import{createHash,randomBytes}from"node:crypto";import{createServer}from"node:http";import{WizardCancelledError}from"#setup/step.js";import{isErrnoCode,isObject}from"#shared/guards.js";import{setTimeout as setTimeout$1}from"node:timers/promises";import{getDefaultCodexTokenBroker}from"#public/models/openai/chatgpt/token-broker.js";import{ChatGptInvalidStoredSessionError,getDefaultChatGptCredentialStore}from"#public/models/openai/chatgpt/credential-store.js";import{CHATGPT_CLIENT_ID,CHATGPT_ISSUER,readChatGptAuthResponse,requestChatGptTokens}from"#public/models/openai/chatgpt/oauth.js";import{openUrl}from"#setup/primitives/open-url.js";const REDIRECT_URI=`http://localhost:1455/auth/callback`;async function ensureChatGptAuth(e={}){let t=e.broker??getDefaultCodexTokenBroker(),n=e.store??getDefaultChatGptCredentialStore();if(e.signal?.throwIfAborted(),(await t.refreshState()).kind===`ready`)return;try{await n.read()}catch(e){if(!(e instanceof ChatGptInvalidStoredSessionError))throw e}let r=new AbortController,cancel=()=>r.abort(new WizardCancelledError);process.once(`SIGINT`,cancel);let i=setTimeout(()=>r.abort(Error(`ChatGPT sign-in timed out. Retry from /model.`)),3e5),a=AbortSignal.any([r.signal,...e.signal?[e.signal]:[]]),o=e.log??(e=>process.stdout.write(`${e}\n`)),s=e.open??openUrl;try{let r=e.headless??!!(process.env.SSH_CONNECTION||process.env.SSH_TTY)?await deviceLogin({...e,signal:a,log:o,open:s}):await browserLogin({...e,signal:a,log:o,open:s});if(a.throwIfAborted(),await n.update(async()=>(a.throwIfAborted(),r),{replace:!0}),(await t.refreshState()).kind!==`ready`)throw Error(`ChatGPT sign-in could not be verified. Retry from /model.`);o(`ChatGPT subscription connected.`)}catch(e){throw a.throwIfAborted(),e}finally{clearTimeout(i),process.removeListener(`SIGINT`,cancel)}}async function browserLogin(e){let t=randomBytes(32).toString(`base64url`),n=randomBytes(32).toString(`base64url`),r=new URL(`${CHATGPT_ISSUER}/oauth/authorize`);r.search=new URLSearchParams({response_type:`code`,client_id:CHATGPT_CLIENT_ID,redirect_uri:REDIRECT_URI,scope:`openid profile email offline_access`,code_challenge:createHash(`sha256`).update(t).digest(`base64url`),code_challenge_method:`S256`,id_token_add_organizations:`true`,codex_cli_simplified_flow:`true`,state:n,originator:`eve`}).toString();let i=Promise.withResolvers();i.promise.catch(()=>{});let a=createServer({requestTimeout:1e4,headersTimeout:1e4,maxHeaderSize:8192},(e,t)=>{let r=URL.parse(e.url??``,REDIRECT_URI);if(t.setHeader(`content-type`,`text/plain; charset=utf-8`),t.setHeader(`cache-control`,`no-store`),e.method!==`GET`||r?.pathname!==`/auth/callback`){t.writeHead(404).end(`Not found.`);return}if(r.searchParams.get(`state`)!==n){t.writeHead(400).end(`This sign-in belongs to another attempt. Return to eve and use its sign-in link.`);return}if(r.searchParams.has(`error`)){t.writeHead(400).end(`ChatGPT sign-in was declined. Return to eve to retry.`),i.reject(Error(`ChatGPT sign-in was declined. Retry from /model.`));return}let a=r.searchParams.get(`code`);if(!a){t.writeHead(400).end(`Missing authorization code.`);return}t.end(`Authorization received. Return to eve to finish connecting your ChatGPT subscription.`),i.resolve(a)});a.maxConnections=10;let abort=()=>i.reject(e.signal.reason);e.signal.addEventListener(`abort`,abort,{once:!0});try{e.signal.throwIfAborted();try{await new Promise((e,t)=>{a.once(`error`,t),a.listen(1455,`127.0.0.1`,e)})}catch(t){if(!isErrnoCode(t,`EADDRINUSE`))throw Error(`Could not start ChatGPT sign-in on localhost:1455. Free the port and retry from /model.`);return e.log(`Local sign-in port is in use. Continuing with a device code.`),await deviceLogin(e)}e.signal.throwIfAborted(),e.log(`Sign in to ChatGPT in your browser:\n${r.href}\nWaiting for sign-in. Press Ctrl+C to cancel.`),e.open(r.href);let n=await i.promise;return await requestChatGptTokens({grant_type:`authorization_code`,code:n,code_verifier:t,redirect_uri:REDIRECT_URI},e)}finally{e.signal.removeEventListener(`abort`,abort),a.closeAllConnections(),await new Promise(e=>a.close(()=>e()))}}async function deviceLogin(e){let t=await deviceRequest(`usercode`,{client_id:CHATGPT_CLIENT_ID},e);if(!t.ok)throw Error(`ChatGPT device sign-in is unavailable (HTTP ${t.status}). Enable device code authorization in ChatGPT Settings > Security, then retry from /model.`);let n=await readChatGptAuthResponse(t);if(!isObject(n)||typeof n.device_auth_id!=`string`||!n.device_auth_id||typeof n.user_code!=`string`||!/^[A-Z0-9-]{4,32}$/iu.test(n.user_code))throw Error(`ChatGPT returned an invalid device code. Retry from /model.`);let r=Math.min(30,Math.max(1,Number(n.interval)||5))*1e3,i=`${CHATGPT_ISSUER}/codex/device`;for(e.log(`Open ${i} and enter code: ${n.user_code}\nIf prompted, enable device code authorization in ChatGPT Settings > Security.\nWaiting for sign-in. Press Ctrl+C to cancel.`),e.open(i);;){await setTimeout$1(r+1e3,void 0,{signal:e.signal});let t=await deviceRequest(`token`,{device_auth_id:n.device_auth_id,user_code:n.user_code},e);if(t.status===403||t.status===404)continue;if(!t.ok)throw Error(`ChatGPT device sign-in failed (HTTP ${t.status}). Retry from /model.`);let i=await readChatGptAuthResponse(t);if(!isObject(i)||typeof i.authorization_code!=`string`||!i.authorization_code||typeof i.code_verifier!=`string`||!i.code_verifier)throw Error(`ChatGPT returned an invalid device authorization. Retry from /model.`);return requestChatGptTokens({grant_type:`authorization_code`,code:i.authorization_code,code_verifier:i.code_verifier,redirect_uri:`${CHATGPT_ISSUER}/deviceauth/callback`},e)}}async function deviceRequest(e,t,n){try{return await(n.fetch??fetch)(`${CHATGPT_ISSUER}/api/accounts/deviceauth/${e}`,{method:`POST`,headers:{"content-type":`application/json`,"user-agent":`eve`},body:JSON.stringify(t),redirect:`error`,signal:AbortSignal.any([n.signal,AbortSignal.timeout(3e4)])})}catch{throw n.signal.throwIfAborted(),Error(`Could not reach ChatGPT device sign-in. Check your connection and retry from /model.`)}}export{ensureChatGptAuth};
1
+ import{createHash,randomBytes}from"node:crypto";import{createServer}from"node:http";import{spawn}from"node:child_process";import{WizardCancelledError}from"#setup/step.js";import{createProcessOutputBuffer}from"#setup/primitives/process-output.js";import{isErrnoCode,isObject}from"#shared/guards.js";import{setTimeout as setTimeout$1}from"node:timers/promises";import{getDefaultCodexTokenBroker}from"#public/models/openai/chatgpt/token-broker.js";import{ChatGptInvalidStoredSessionError,getDefaultChatGptCredentialStore}from"#public/models/openai/chatgpt/credential-store.js";import{CHATGPT_CLIENT_ID,CHATGPT_ISSUER,readChatGptAuthResponse,requestChatGptTokens}from"#public/models/openai/chatgpt/oauth.js";import{openUrl}from"#setup/primitives/open-url.js";const REDIRECT_URI=`http://localhost:1455/auth/callback`;async function ensureChatGptAuth(e={}){let t=e.broker??getDefaultCodexTokenBroker(),n=e.store??getDefaultChatGptCredentialStore();e.signal?.throwIfAborted();let r=await t.refreshState();if(r.kind===`ready`)return;let i=t.credentialOwner();if(i===void 0)throw Error(`ChatGPT credential owner could not be resolved.`);if(i===`codex`){if(r.kind===`unavailable`)throw Error(r.reason);try{let n=e.log??(e=>process.stdout.write(`${e}\n`));await(e.codexLogin??(e=>loginWithCodex(e,n)))(e.signal),await assertChatGptAuthReady(t,`Codex login completed without a usable ChatGPT session.`);return}catch(e){if(!isErrnoCode(e,`ENOENT`))throw e;let n=await t.refreshState();if(t.credentialOwner()!==`eve`)throw e;if(n.kind===`ready`)return;if(n.kind===`unavailable`)throw Error(n.reason)}}try{await n.read()}catch(e){if(!(e instanceof ChatGptInvalidStoredSessionError))throw e}await signInWithOwnedCredentials(e,t,n)}async function signInWithOwnedCredentials(e,t,n){let r=new AbortController,cancel=()=>r.abort(new WizardCancelledError);process.once(`SIGINT`,cancel);let i=setTimeout(()=>r.abort(Error(`ChatGPT sign-in timed out. Retry from /model.`)),3e5),a=AbortSignal.any([r.signal,...e.signal?[e.signal]:[]]),o=e.log??(e=>process.stdout.write(`${e}\n`)),s=e.open??openUrl;try{let r=e.headless??!!(process.env.SSH_CONNECTION||process.env.SSH_TTY)?await deviceLogin({...e,signal:a,log:o,open:s}):await browserLogin({...e,signal:a,log:o,open:s});a.throwIfAborted(),await n.update(async()=>(a.throwIfAborted(),r),{replace:!0}),await assertChatGptAuthReady(t,`ChatGPT sign-in could not be verified. Retry from /model.`),o(`ChatGPT subscription connected.`)}catch(e){throw a.throwIfAborted(),e}finally{clearTimeout(i),process.removeListener(`SIGINT`,cancel)}}async function assertChatGptAuthReady(e,t){if((await e.refreshState()).kind!==`ready`)throw Error(t)}async function loginWithCodex(e,t){let n=spawn(`codex`,[`login`],{stdio:[`ignore`,`pipe`,`pipe`],...e!==void 0&&{signal:e}}),r=createProcessOutputBuffer(({text:e})=>t(e));n.stdout.on(`data`,e=>r.write(`stdout`,e)),n.stderr.on(`data`,e=>r.write(`stderr`,e));try{await new Promise((e,t)=>{n.once(`error`,t),n.once(`close`,(n,r)=>{n===0?e():t(Error(`codex login failed (${r??n??`unknown`}).`))})})}finally{r.flush()}}async function browserLogin(e){let t=randomBytes(32).toString(`base64url`),n=randomBytes(32).toString(`base64url`),r=new URL(`${CHATGPT_ISSUER}/oauth/authorize`);r.search=new URLSearchParams({response_type:`code`,client_id:CHATGPT_CLIENT_ID,redirect_uri:REDIRECT_URI,scope:`openid profile email offline_access`,code_challenge:createHash(`sha256`).update(t).digest(`base64url`),code_challenge_method:`S256`,id_token_add_organizations:`true`,codex_cli_simplified_flow:`true`,state:n,originator:`eve`}).toString();let i=Promise.withResolvers();i.promise.catch(()=>{});let a=createServer({requestTimeout:1e4,headersTimeout:1e4,maxHeaderSize:8192},(e,t)=>{let r=URL.parse(e.url??``,REDIRECT_URI);if(t.setHeader(`content-type`,`text/plain; charset=utf-8`),t.setHeader(`cache-control`,`no-store`),e.method!==`GET`||r?.pathname!==`/auth/callback`){t.writeHead(404).end(`Not found.`);return}if(r.searchParams.get(`state`)!==n){t.writeHead(400).end(`This sign-in belongs to another attempt. Return to eve and use its sign-in link.`);return}if(r.searchParams.has(`error`)){t.writeHead(400).end(`ChatGPT sign-in was declined. Return to eve to retry.`),i.reject(Error(`ChatGPT sign-in was declined. Retry from /model.`));return}let a=r.searchParams.get(`code`);if(!a){t.writeHead(400).end(`Missing authorization code.`);return}t.end(`Authorization received. Return to eve to finish connecting your ChatGPT subscription.`),i.resolve(a)});a.maxConnections=10;let abort=()=>i.reject(e.signal.reason);e.signal.addEventListener(`abort`,abort,{once:!0});try{e.signal.throwIfAborted();try{await new Promise((e,t)=>{a.once(`error`,t),a.listen(1455,`127.0.0.1`,e)})}catch(t){if(!isErrnoCode(t,`EADDRINUSE`))throw Error(`Could not start ChatGPT sign-in on localhost:1455. Free the port and retry from /model.`);return e.log(`Local sign-in port is in use. Continuing with a device code.`),await deviceLogin(e)}e.signal.throwIfAborted(),e.log(`Sign in to ChatGPT in your browser:\n${r.href}\nWaiting for sign-in. Press Ctrl+C to cancel.`),e.open(r.href);let n=await i.promise;return await requestChatGptTokens({grant_type:`authorization_code`,code:n,code_verifier:t,redirect_uri:REDIRECT_URI},e)}finally{e.signal.removeEventListener(`abort`,abort),a.closeAllConnections(),await new Promise(e=>a.close(()=>e()))}}async function deviceLogin(e){let t=await deviceRequest(`usercode`,{client_id:CHATGPT_CLIENT_ID},e);if(!t.ok)throw Error(`ChatGPT device sign-in is unavailable (HTTP ${t.status}). Enable device code authorization in ChatGPT Settings > Security, then retry from /model.`);let n=await readChatGptAuthResponse(t);if(!isObject(n)||typeof n.device_auth_id!=`string`||!n.device_auth_id||typeof n.user_code!=`string`||!/^[A-Z0-9-]{4,32}$/iu.test(n.user_code))throw Error(`ChatGPT returned an invalid device code. Retry from /model.`);let r=Math.min(30,Math.max(1,Number(n.interval)||5))*1e3,i=`${CHATGPT_ISSUER}/codex/device`;for(e.log(`Open ${i} and enter code: ${n.user_code}\nIf prompted, enable device code authorization in ChatGPT Settings > Security.\nWaiting for sign-in. Press Ctrl+C to cancel.`),e.open(i);;){await setTimeout$1(r+1e3,void 0,{signal:e.signal});let t=await deviceRequest(`token`,{device_auth_id:n.device_auth_id,user_code:n.user_code},e);if(t.status===403||t.status===404)continue;if(!t.ok)throw Error(`ChatGPT device sign-in failed (HTTP ${t.status}). Retry from /model.`);let i=await readChatGptAuthResponse(t);if(!isObject(i)||typeof i.authorization_code!=`string`||!i.authorization_code||typeof i.code_verifier!=`string`||!i.code_verifier)throw Error(`ChatGPT returned an invalid device authorization. Retry from /model.`);return requestChatGptTokens({grant_type:`authorization_code`,code:i.authorization_code,code_verifier:i.code_verifier,redirect_uri:`${CHATGPT_ISSUER}/deviceauth/callback`},e)}}async function deviceRequest(e,t,n){try{return await(n.fetch??fetch)(`${CHATGPT_ISSUER}/api/accounts/deviceauth/${e}`,{method:`POST`,headers:{"content-type":`application/json`,"user-agent":`eve`},body:JSON.stringify(t),redirect:`error`,signal:AbortSignal.any([n.signal,AbortSignal.timeout(3e4)])})}catch{throw n.signal.throwIfAborted(),Error(`Could not reach ChatGPT device sign-in. Check your connection and retry from /model.`)}}export{ensureChatGptAuth};
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.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.93`,DEFAULT_CONNECT_PACKAGE_VERSION=`1.0.0`,DEFAULT_ZOD_PACKAGE_VERSION=`4.5.4`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.54.3`,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,t){return{"agent/agent.ts":renderAgentTemplate(e,t),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderAgentTemplate(e,t){let n=parseChatGptModelSelection(e);return n===void 0?BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t)):`import { defineAgent } from "eve";\nimport { chatgpt } from "eve/models/openai";\n\nexport default defineAgent({\n model: chatgpt(${JSON.stringify(n)}),\n${reasoningTemplateLine(t)}});\n`}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,t){return e===BASE_AGENT_TEMPLATE&&parseChatGptModelSelection(t.model)!==void 0?renderAgentTemplate(t.model,t.reasoning):e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t.reasoning)).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{parseChatGptModelSelection}from"../../../shared/chatgpt-model.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.93`,DEFAULT_CONNECT_PACKAGE_VERSION=`1.0.0`,DEFAULT_ZOD_PACKAGE_VERSION=`4.5.4`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.54.4`,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,t){return{"agent/agent.ts":renderAgentTemplate(e,t),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderAgentTemplate(e,t){let n=parseChatGptModelSelection(e);return n===void 0?BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t)):`import { defineAgent } from "eve";\nimport { chatgpt } from "eve/models/openai";\n\nexport default defineAgent({\n model: chatgpt(${JSON.stringify(n)}),\n${reasoningTemplateLine(t)}});\n`}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,t){return e===BASE_AGENT_TEMPLATE&&parseChatGptModelSelection(t.model)!==void 0?renderAgentTemplate(t.model,t.reasoning):e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t.reasoning)).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__",
@@ -27,7 +27,9 @@ export declare function startRemoteAgentSession(input: {
27
27
  * created instead of starting a second one.
28
28
  */
29
29
  readonly operationId?: string;
30
- readonly parent?: Omit<SubagentParentContext, "lineage">;
30
+ readonly parent?: Omit<SubagentParentContext, "lineage"> & {
31
+ readonly lineage?: SubagentParentContext["lineage"];
32
+ };
31
33
  readonly remote: ResolvedRuntimeRemoteAgentNode;
32
34
  readonly session: HarnessSession;
33
35
  readonly taskId?: string;
@@ -1 +1 @@
1
- import{z}from"#compiled/zod/index.js";import{createEveCallbackRoutePath,createEveSessionCancelRoutePath,createEveSessionResetRoutePath,createEveSessionRoutePath}from"#protocol/routes.js";import{expectFunction,expectObjectRecord}from"#internal/authored-module.js";import{CancelTurnResponseSchema}from"#protocol/cancel-turn.js";import{ResetResponseSchema}from"#protocol/reset-session.js";import{formatTraceparent}from"#protocol/traceparent.js";import{writeForwardedAudienceBaggage}from"#protocol/baggage.js";import{writeConversationBaggage}from"#tracing/conversation-context.js";import{decisionToTraceContentCeiling}from"#shared/forwarded-trace-policy.js";import{createWorkflowCallbackUrl}from"#execution/workflow-callback-url.js";import{readTaskIdFromInboxToken}from"#tasks/task-inbox-token.js";import{formatSubagentInput,normalizeRequestedOutputSchema}from"#subagents/invocation.js";import{AgentHandleError}from"#protocol/agent-handle-error.js";import{createRemoteAgentRouteUrl}from"#subagents/remote-route-url.js";const CreateSessionResponseSchema=z.object({ok:z.literal(!0),sessionId:z.string().min(1),status:z.literal(`accepted`)});var RemoteAgentCancelRequestError=class extends Error{retryable;constructor(e,t){super(e),this.name=`RemoteAgentCancelRequestError`,this.retryable=t.retryable}};async function startRemoteAgentSession(e){let t=e.parent?.continuationToken??e.session.continuationToken;if(!t)throw Error(`Cannot dispatch remote agent without a parent continuation token.`);if(!e.callbackBaseUrl)throw Error(`Cannot dispatch remote agent without a callback base URL.`);let n=buildForwardedPrincipalField(e),r={capabilities:{},callback:{callId:e.action.callId,subagentName:e.action.remoteAgentName,taskId:e.taskId??readTaskIdFromInboxToken(t),token:t,url:createWorkflowCallbackUrl(e.callbackBaseUrl,createEveCallbackRoutePath(t))},message:formatRemoteAgentCallInputMessage({action:e.action,remote:e.remote}),mode:`conversation`,outputSchema:normalizeRequestedOutputSchema(e.action.input.outputSchema)??e.remote.outputSchema};e.activityObserver!==void 0&&(r.activityObserver=e.activityObserver),n!==void 0&&(r.forwardedPrincipal=n),e.operationId!==void 0&&(r.operationId=e.operationId);let i=await resolveRemoteAgentRequestHeaders(e.remote),a=formatTraceparent(e.parent?.traceContext);a!==void 0&&setHeader(i,`traceparent`,a);let o=writeForwardedAudienceBaggage(readHeader(i,`baggage`),buildForwardedTraceAssertion({forwardedPrincipal:n,originAudience:e.originAudience,parentTraceContext:e.parent?.traceContext,traceparent:a}));setHeader(i,`baggage`,writeConversationBaggage(o,e.parent?.conversationId));let s=await fetch(createRemoteAgentSessionUrl(e.remote),{body:JSON.stringify(r),headers:{"content-type":`application/json`,...i},method:`POST`});if(!s.ok)throw Error(`Remote agent "${e.action.remoteAgentName}" create-session request failed with HTTP ${s.status}.`);let c;try{c=await s.json()}catch{throw Error(`Remote agent "${e.action.remoteAgentName}" create-session response was not valid JSON.`)}let l=CreateSessionResponseSchema.safeParse(c);if(!l.success)throw Error(`Remote agent "${e.action.remoteAgentName}" create-session response was invalid.`);return{sessionId:l.data.sessionId}}function buildForwardedTraceAssertion(e){let t=decisionToTraceContentCeiling(e.parentTraceContext?.decision);if(e.forwardedPrincipal!==void 0&&e.parentTraceContext!==void 0&&(e.parentTraceContext.traceFlags&1)==1&&e.traceparent!==void 0&&t!==void 0)return{ceiling:t,originAudience:e.originAudience??`unknown`}}async function continueRemoteAgentSession(e){let t=buildForwardedPrincipalField(e),n={activityObserver:e.activityObserver,callback:e.callback,message:e.message,outputSchema:e.outputSchema};t!==void 0&&(n.forwardedPrincipal=t);let r=await fetch(createRemoteAgentContinueUrl(e.remote,e.sessionId),{body:JSON.stringify(n),headers:{"content-type":`application/json`,...await resolveRemoteAgentRequestHeaders(e.remote)},method:`POST`});if(!r.ok){let n=await readRemoteAgentErrorCode(r),i=r.status===404||n===AgentHandleError.SessionNotResumable.code,a=r.status===400&&t!==void 0?` The receiver may support forwarded principals only on session creation; upgrade it before retrying.`:``;throw new RemoteAgentContinueRequestError(`Remote agent "${e.remote.name}" continue-session request failed${i?` permanently`:``} with HTTP ${r.status}.${a}`,{deliveryAmbiguous:isAmbiguousRemoteContinueStatus(r.status),retryable:!i})}}var RemoteAgentContinueRequestError=class extends Error{deliveryAmbiguous;retryable;constructor(e,t){super(e),this.name=`RemoteAgentContinueRequestError`,this.deliveryAmbiguous=t.deliveryAmbiguous,this.retryable=t.retryable}};function isRetryableRemoteAgentContinueError(e){return!(e instanceof RemoteAgentContinueRequestError)||e.retryable}function isAmbiguousRemoteAgentContinueError(e){return!(e instanceof RemoteAgentContinueRequestError)||e.deliveryAmbiguous}function isAmbiguousRemoteContinueStatus(e){return e===408||e===425||e>=500}async function readRemoteAgentErrorCode(e){let t;try{t=await e.json()}catch{return}if(typeof t!=`object`||!t)return;let n=Reflect.get(t,`code`);return typeof n==`string`?n:void 0}function buildForwardedPrincipalField(e){if(e.remote.forwardPrincipal!==!0||e.auth===null||e.auth===void 0)return;let t={current:e.auth};return e.initiatorAuth!==null&&e.initiatorAuth!==void 0&&(t.initiator=e.initiatorAuth),t}async function cancelRemoteAgentTurn(e){let t=e.headers??await resolveRemoteAgentRequestHeaders(e.remote),n=await fetch(createRemoteAgentCancelTurnUrl(e.remote,e.sessionId),{body:e.turnId===void 0&&e.taskId===void 0?void 0:JSON.stringify({taskId:e.taskId,turnId:e.turnId}),headers:t,method:`POST`});if(!n.ok)throw new RemoteAgentCancelRequestError(`Remote agent "${e.remote.name}" cancel-turn request failed with HTTP ${n.status}.`,{retryable:isRetryableRemoteCancelStatus(n.status)});let r;try{r=await n.json()}catch{throw new RemoteAgentCancelRequestError(`Remote agent "${e.remote.name}" cancel-turn response was not valid JSON.`,{retryable:!1})}let i=CancelTurnResponseSchema.safeParse(r);if(!i.success||i.data.status===`accepted`&&i.data.sessionId!==e.sessionId)throw new RemoteAgentCancelRequestError(`Remote agent "${e.remote.name}" cancel-turn response was invalid.`,{retryable:!1});return i.data.status===`accepted`?{sessionId:i.data.sessionId,status:`accepted`}:{status:`no_active_turn`}}function readHeader(e,t){let n=Object.keys(e).find(e=>e.toLowerCase()===t);return n===void 0?void 0:e[n]}function setHeader(e,t,n){for(let n of Object.keys(e))n.toLowerCase()===t&&delete e[n];n!==void 0&&(e[t]=n)}async function resetRemoteAgentSession(e){let t=e.headers??await resolveRemoteAgentRequestHeaders(e.remote),n=await fetch(createRemoteAgentRouteUrl(e.remote.url,createEveSessionResetRoutePath(e.sessionId)),{body:JSON.stringify({reason:`Parent session ended`}),headers:{"content-type":`application/json`,...t},method:`POST`});if(!n.ok)throw Error(`Remote agent "${e.remote.name}" reset-session request failed with HTTP ${n.status}.`);let r=ResetResponseSchema.safeParse(await n.json());if(!r.success||r.data.status===`reset`&&r.data.previousSessionId!==e.sessionId)throw Error(`Remote agent "${e.remote.name}" reset-session response was invalid.`);return r.data}function isRetryableRemoteAgentCancelError(e){return!(e instanceof RemoteAgentCancelRequestError)||e.retryable}function resolveRemoteAgentForAction(e){let t=e.registry.get(e.nodeId)?.definition;if(e.dynamicRemoteAgent!==void 0){if(t===void 0)throw Error(`Missing remote agent "${e.remoteAgentName}" in runtime registry.`);let n=resolveDynamicRemoteAgentCredentials(e.dynamicRemoteAgent),r=e.dynamicRemoteAgent,i={description:r.description,kind:`remote`,logicalPath:t.logicalPath,name:e.remoteAgentName,nodeId:e.nodeId,outputSchema:r.outputSchema,path:r.path,sourceId:t.sourceId,sourceKind:`module`,url:r.url};return r.forwardPrincipal!==void 0&&(i.forwardPrincipal=r.forwardPrincipal),n.auth!==void 0&&(i.auth=n.auth),n.headers!==void 0&&(i.headers=n.headers),i}if(t?.kind!==`remote`)throw Error(`Missing remote agent "${e.remoteAgentName}" in runtime registry.`);return t}async function resolveRemoteAgentStreamHeaders(e){if(e.resolverId===void 0)return{};let t=new Set([e.bundle.graph.root,...e.bundle.graph.nodesByNodeId.values()]);for(let n of t){let t=n.subagentRegistry.subagentsByNodeId.get(e.resolverId)?.definition;if(t!==void 0){if(t.kind!==`remote`||t.name!==e.name||t.url!==e.url)throw Error(`Remote child stream resolver does not match the authored remote agent.`);return await resolveRemoteAgentRequestHeaders(t)}}return await resolveRemoteAgentRequestHeaders(resolveDynamicRemoteAgentCredentials({credentialsStepId:e.resolverId,description:``,path:``,url:e.url}))}function resolveDynamicRemoteAgentCredentials(e){if(e.credentialsStepId===void 0)return{};let t=getStepRegistry().get(e.credentialsStepId);if(t===void 0)throw Error(`Dynamic remote subagent credentials function "${e.credentialsStepId}" is not registered.`);let n=expectObjectRecord(t(),`Dynamic remote subagent credentials are invalid.`),r={};return n.auth!==void 0&&(r.auth=expectFunction(n.auth,`Dynamic remote subagent auth is invalid.`)),n.headers!==void 0&&(r.headers=resolveDynamicRemoteAgentHeaders(n.headers)),r}function resolveDynamicRemoteAgentHeaders(e){if(typeof e==`function`)return e;let t=expectObjectRecord(e,`Dynamic remote subagent headers are invalid.`);for(let e of Object.values(t))if(typeof e!=`string`)throw Error(`Dynamic remote subagent headers are invalid.`);return t}function getStepRegistry(){let e=Symbol.for(`@workflow/core//registeredSteps`),t=globalThis,n=t[e];return n===void 0&&(n=new Map,t[e]=n),n}function createRemoteAgentSessionUrl(e){return createRemoteAgentRouteUrl(e.url,e.path)}function createRemoteAgentCancelTurnUrl(e,t){return createRemoteAgentRouteUrl(e.url,createEveSessionCancelRoutePath(t))}function createRemoteAgentContinueUrl(e,t){return createRemoteAgentRouteUrl(e.url,createEveSessionRoutePath(t))}function isRetryableRemoteCancelStatus(e){return e===408||e===425||e===429||e>=500}async function resolveRemoteAgentRequestHeaders(e){let t={};return e.headers!==void 0&&Object.assign(t,typeof e.headers==`function`?await e.headers():e.headers),e.auth!==void 0&&Object.assign(t,(await e.auth()).headers),t}function formatRemoteAgentCallInputMessage(e){let t=typeof e.action.input.message==`string`?e.action.input.message:``;return formatSubagentInput({description:e.remote.description,message:t,name:e.action.remoteAgentName,type:`remote`}).message}export{RemoteAgentContinueRequestError,cancelRemoteAgentTurn,continueRemoteAgentSession,isAmbiguousRemoteAgentContinueError,isRetryableRemoteAgentCancelError,isRetryableRemoteAgentContinueError,resetRemoteAgentSession,resolveRemoteAgentForAction,resolveRemoteAgentStreamHeaders,startRemoteAgentSession};
1
+ import{z}from"#compiled/zod/index.js";import{createEveCallbackRoutePath,createEveSessionCancelRoutePath,createEveSessionResetRoutePath,createEveSessionRoutePath}from"#protocol/routes.js";import{expectFunction,expectObjectRecord}from"#internal/authored-module.js";import{CancelTurnResponseSchema}from"#protocol/cancel-turn.js";import{ResetResponseSchema}from"#protocol/reset-session.js";import{formatTraceparent,writeAgentDispatchTracestate}from"#protocol/traceparent.js";import{writeForwardedAudienceBaggage,writeForwardedParentSessionBaggage}from"#protocol/baggage.js";import{writeConversationBaggage}from"#tracing/conversation-context.js";import{decisionToTraceContentCeiling}from"#shared/forwarded-trace-policy.js";import{createWorkflowCallbackUrl}from"#execution/workflow-callback-url.js";import{readTaskIdFromInboxToken}from"#tasks/task-inbox-token.js";import{formatSubagentInput,normalizeRequestedOutputSchema}from"#subagents/invocation.js";import{AgentHandleError}from"#protocol/agent-handle-error.js";import{createRemoteAgentRouteUrl}from"#subagents/remote-route-url.js";const CreateSessionResponseSchema=z.object({ok:z.literal(!0),sessionId:z.string().min(1),status:z.literal(`accepted`)});var RemoteAgentCancelRequestError=class extends Error{retryable;constructor(e,t){super(e),this.name=`RemoteAgentCancelRequestError`,this.retryable=t.retryable}};async function startRemoteAgentSession(e){let t=e.parent?.continuationToken??e.session.continuationToken;if(!t)throw Error(`Cannot dispatch remote agent without a parent continuation token.`);if(!e.callbackBaseUrl)throw Error(`Cannot dispatch remote agent without a callback base URL.`);let n=buildForwardedPrincipalField(e),r={capabilities:{},callback:{callId:e.action.callId,subagentName:e.action.remoteAgentName,taskId:e.taskId??readTaskIdFromInboxToken(t),token:t,url:createWorkflowCallbackUrl(e.callbackBaseUrl,createEveCallbackRoutePath(t))},message:formatRemoteAgentCallInputMessage({action:e.action,remote:e.remote}),mode:`conversation`,outputSchema:normalizeRequestedOutputSchema(e.action.input.outputSchema)??e.remote.outputSchema};e.activityObserver!==void 0&&(r.activityObserver=e.activityObserver),n!==void 0&&(r.forwardedPrincipal=n),e.operationId!==void 0&&(r.operationId=e.operationId);let i=await resolveRemoteAgentRequestHeaders(e.remote),a=formatTraceparent(e.parent?.traceContext);a!==void 0&&setHeader(i,`traceparent`,a),setHeader(i,`tracestate`,writeAgentDispatchTracestate(readHeader(i,`tracestate`),e.parent?.traceContext));let o=writeForwardedAudienceBaggage(readHeader(i,`baggage`),buildForwardedTraceAssertion({forwardedPrincipal:n,originAudience:e.originAudience,parentTraceContext:e.parent?.traceContext,traceparent:a})),s=writeConversationBaggage(o,e.parent?.conversationId);setHeader(i,`baggage`,writeForwardedParentSessionBaggage(s,e.parent?.lineage));let c=await fetch(createRemoteAgentSessionUrl(e.remote),{body:JSON.stringify(r),headers:{"content-type":`application/json`,...i},method:`POST`});if(!c.ok)throw Error(`Remote agent "${e.action.remoteAgentName}" create-session request failed with HTTP ${c.status}.`);let l;try{l=await c.json()}catch{throw Error(`Remote agent "${e.action.remoteAgentName}" create-session response was not valid JSON.`)}let u=CreateSessionResponseSchema.safeParse(l);if(!u.success)throw Error(`Remote agent "${e.action.remoteAgentName}" create-session response was invalid.`);return{sessionId:u.data.sessionId}}function buildForwardedTraceAssertion(e){let t=decisionToTraceContentCeiling(e.parentTraceContext?.decision);if(e.forwardedPrincipal!==void 0&&e.parentTraceContext!==void 0&&(e.parentTraceContext.traceFlags&1)==1&&e.traceparent!==void 0&&t!==void 0)return{ceiling:t,originAudience:e.originAudience??`unknown`}}async function continueRemoteAgentSession(e){let t=buildForwardedPrincipalField(e),n={activityObserver:e.activityObserver,callback:e.callback,message:e.message,outputSchema:e.outputSchema};t!==void 0&&(n.forwardedPrincipal=t);let r=await fetch(createRemoteAgentContinueUrl(e.remote,e.sessionId),{body:JSON.stringify(n),headers:{"content-type":`application/json`,...await resolveRemoteAgentRequestHeaders(e.remote)},method:`POST`});if(!r.ok){let n=await readRemoteAgentErrorCode(r),i=r.status===404||n===AgentHandleError.SessionNotResumable.code,a=r.status===400&&t!==void 0?` The receiver may support forwarded principals only on session creation; upgrade it before retrying.`:``;throw new RemoteAgentContinueRequestError(`Remote agent "${e.remote.name}" continue-session request failed${i?` permanently`:``} with HTTP ${r.status}.${a}`,{deliveryAmbiguous:isAmbiguousRemoteContinueStatus(r.status),retryable:!i})}}var RemoteAgentContinueRequestError=class extends Error{deliveryAmbiguous;retryable;constructor(e,t){super(e),this.name=`RemoteAgentContinueRequestError`,this.deliveryAmbiguous=t.deliveryAmbiguous,this.retryable=t.retryable}};function isRetryableRemoteAgentContinueError(e){return!(e instanceof RemoteAgentContinueRequestError)||e.retryable}function isAmbiguousRemoteAgentContinueError(e){return!(e instanceof RemoteAgentContinueRequestError)||e.deliveryAmbiguous}function isAmbiguousRemoteContinueStatus(e){return e===408||e===425||e>=500}async function readRemoteAgentErrorCode(e){let t;try{t=await e.json()}catch{return}if(typeof t!=`object`||!t)return;let n=Reflect.get(t,`code`);return typeof n==`string`?n:void 0}function buildForwardedPrincipalField(e){if(e.remote.forwardPrincipal!==!0||e.auth===null||e.auth===void 0)return;let t={current:e.auth};return e.initiatorAuth!==null&&e.initiatorAuth!==void 0&&(t.initiator=e.initiatorAuth),t}async function cancelRemoteAgentTurn(e){let t=e.headers??await resolveRemoteAgentRequestHeaders(e.remote),n=await fetch(createRemoteAgentCancelTurnUrl(e.remote,e.sessionId),{body:e.turnId===void 0&&e.taskId===void 0?void 0:JSON.stringify({taskId:e.taskId,turnId:e.turnId}),headers:t,method:`POST`});if(!n.ok)throw new RemoteAgentCancelRequestError(`Remote agent "${e.remote.name}" cancel-turn request failed with HTTP ${n.status}.`,{retryable:isRetryableRemoteCancelStatus(n.status)});let r;try{r=await n.json()}catch{throw new RemoteAgentCancelRequestError(`Remote agent "${e.remote.name}" cancel-turn response was not valid JSON.`,{retryable:!1})}let i=CancelTurnResponseSchema.safeParse(r);if(!i.success||i.data.status===`accepted`&&i.data.sessionId!==e.sessionId)throw new RemoteAgentCancelRequestError(`Remote agent "${e.remote.name}" cancel-turn response was invalid.`,{retryable:!1});return i.data.status===`accepted`?{sessionId:i.data.sessionId,status:`accepted`}:{status:`no_active_turn`}}function readHeader(e,t){let n=Object.keys(e).find(e=>e.toLowerCase()===t);return n===void 0?void 0:e[n]}function setHeader(e,t,n){for(let n of Object.keys(e))n.toLowerCase()===t&&delete e[n];n!==void 0&&(e[t]=n)}async function resetRemoteAgentSession(e){let t=e.headers??await resolveRemoteAgentRequestHeaders(e.remote),n=await fetch(createRemoteAgentRouteUrl(e.remote.url,createEveSessionResetRoutePath(e.sessionId)),{body:JSON.stringify({reason:`Parent session ended`}),headers:{"content-type":`application/json`,...t},method:`POST`});if(!n.ok)throw Error(`Remote agent "${e.remote.name}" reset-session request failed with HTTP ${n.status}.`);let r=ResetResponseSchema.safeParse(await n.json());if(!r.success||r.data.status===`reset`&&r.data.previousSessionId!==e.sessionId)throw Error(`Remote agent "${e.remote.name}" reset-session response was invalid.`);return r.data}function isRetryableRemoteAgentCancelError(e){return!(e instanceof RemoteAgentCancelRequestError)||e.retryable}function resolveRemoteAgentForAction(e){let t=e.registry.get(e.nodeId)?.definition;if(e.dynamicRemoteAgent!==void 0){if(t===void 0)throw Error(`Missing remote agent "${e.remoteAgentName}" in runtime registry.`);let n=resolveDynamicRemoteAgentCredentials(e.dynamicRemoteAgent),r=e.dynamicRemoteAgent,i={description:r.description,kind:`remote`,logicalPath:t.logicalPath,name:e.remoteAgentName,nodeId:e.nodeId,outputSchema:r.outputSchema,path:r.path,sourceId:t.sourceId,sourceKind:`module`,url:r.url};return r.forwardPrincipal!==void 0&&(i.forwardPrincipal=r.forwardPrincipal),n.auth!==void 0&&(i.auth=n.auth),n.headers!==void 0&&(i.headers=n.headers),i}if(t?.kind!==`remote`)throw Error(`Missing remote agent "${e.remoteAgentName}" in runtime registry.`);return t}async function resolveRemoteAgentStreamHeaders(e){if(e.resolverId===void 0)return{};let t=new Set([e.bundle.graph.root,...e.bundle.graph.nodesByNodeId.values()]);for(let n of t){let t=n.subagentRegistry.subagentsByNodeId.get(e.resolverId)?.definition;if(t!==void 0){if(t.kind!==`remote`||t.name!==e.name||t.url!==e.url)throw Error(`Remote child stream resolver does not match the authored remote agent.`);return await resolveRemoteAgentRequestHeaders(t)}}return await resolveRemoteAgentRequestHeaders(resolveDynamicRemoteAgentCredentials({credentialsStepId:e.resolverId,description:``,path:``,url:e.url}))}function resolveDynamicRemoteAgentCredentials(e){if(e.credentialsStepId===void 0)return{};let t=getStepRegistry().get(e.credentialsStepId);if(t===void 0)throw Error(`Dynamic remote subagent credentials function "${e.credentialsStepId}" is not registered.`);let n=expectObjectRecord(t(),`Dynamic remote subagent credentials are invalid.`),r={};return n.auth!==void 0&&(r.auth=expectFunction(n.auth,`Dynamic remote subagent auth is invalid.`)),n.headers!==void 0&&(r.headers=resolveDynamicRemoteAgentHeaders(n.headers)),r}function resolveDynamicRemoteAgentHeaders(e){if(typeof e==`function`)return e;let t=expectObjectRecord(e,`Dynamic remote subagent headers are invalid.`);for(let e of Object.values(t))if(typeof e!=`string`)throw Error(`Dynamic remote subagent headers are invalid.`);return t}function getStepRegistry(){let e=Symbol.for(`@workflow/core//registeredSteps`),t=globalThis,n=t[e];return n===void 0&&(n=new Map,t[e]=n),n}function createRemoteAgentSessionUrl(e){return createRemoteAgentRouteUrl(e.url,e.path)}function createRemoteAgentCancelTurnUrl(e,t){return createRemoteAgentRouteUrl(e.url,createEveSessionCancelRoutePath(t))}function createRemoteAgentContinueUrl(e,t){return createRemoteAgentRouteUrl(e.url,createEveSessionRoutePath(t))}function isRetryableRemoteCancelStatus(e){return e===408||e===425||e===429||e>=500}async function resolveRemoteAgentRequestHeaders(e){let t={};return e.headers!==void 0&&Object.assign(t,typeof e.headers==`function`?await e.headers():e.headers),e.auth!==void 0&&Object.assign(t,(await e.auth()).headers),t}function formatRemoteAgentCallInputMessage(e){let t=typeof e.action.input.message==`string`?e.action.input.message:``;return formatSubagentInput({description:e.remote.description,message:t,name:e.action.remoteAgentName,type:`remote`}).message}export{RemoteAgentContinueRequestError,cancelRemoteAgentTurn,continueRemoteAgentSession,isAmbiguousRemoteAgentContinueError,isRetryableRemoteAgentCancelError,isRetryableRemoteAgentContinueError,resetRemoteAgentSession,resolveRemoteAgentForAction,resolveRemoteAgentStreamHeaders,startRemoteAgentSession};
@@ -1 +1 @@
1
- import{AGENT_TRACE_SCHEMA_VERSION}from"#tracing/agent-span-contract.js";import{resolveConversationId}from"#tracing/conversation-context.js";function agentTraceIdentityAttributes(e){return{"agent.trace.schema.version":AGENT_TRACE_SCHEMA_VERSION,"gen_ai.conversation.id":resolveConversationId(e.rootSessionId),...process.env.VERCEL_ENV===void 0?void 0:{"vercel.session_id":e.sessionId}}}export{agentTraceIdentityAttributes};
1
+ import{AGENT_TRACE_SCHEMA_VERSION}from"#tracing/agent-span-contract.js";import{resolveConversationId}from"#tracing/conversation-context.js";function agentTraceIdentityAttributes(e){let t=resolveConversationId(e.rootSessionId),n={"agent.run.id":e.sessionId,"agent.trace.schema.version":AGENT_TRACE_SCHEMA_VERSION,"gen_ai.conversation.id":t};return process.env.VERCEL_ENV!==void 0&&(n[`vercel.session_id`]=e.rootSessionId),n}export{agentTraceIdentityAttributes};
@@ -1 +1 @@
1
- import{agentInvocationSpanName}from"#tracing/agent-span-contract.js";import{agentSpanNamingAttributes}from"#tracing/agent-span-naming.js";import{agentTraceIdentityAttributes}from"#tracing/agent-otel-attributes.js";function agentActivationAttributes(e){return{"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.name":e.agentName,...agentPrincipalAttributes(e.turn),"agent.channel.delivery.id":e.turn.channelDelivery?.deliveryId,"agent.channel.delivery.input":e.turn.channelDelivery?.inputAttribute,"agent.channel.kind":e.turn.channelDelivery?.channelKind,"agent.channel.name":e.turn.channelDelivery?.channelName,"agent.channel.request.id":e.turn.channelDelivery?.requestId,"agent.subagent.name":e.turn.subagentName,"agent.turn.id":e.turnId,"agent.turn.sequence":e.turn.sequence,"gen_ai.agent.name":e.agentName,"gen_ai.operation.name":`invoke_agent`,...agentSpanNamingAttributes(agentInvocationSpanName(e.agentName),`invoke_agent`),...agentTraceIdentityAttributes({rootSessionId:e.turn.rootSessionId,sessionId:e.sessionId})}}function agentPrincipalAttributes(e){let t={};return setOptionalAttribute(t,`agent.principal.current.id`,e.currentPrincipal?.id),setOptionalAttribute(t,`agent.principal.current.type`,e.currentPrincipal?.type),setOptionalAttribute(t,`agent.principal.initiator.id`,e.initiatorPrincipal?.id),setOptionalAttribute(t,`agent.principal.initiator.type`,e.initiatorPrincipal?.type),t}function runtimeContextAttributes(e){let t={};if(e===void 0)return t;for(let[n,r]of Object.entries(e))flattenContextAttribute(t,`ai.settings.context.${n}`,r);return t}function flattenContextAttribute(e,t,n){if(n!=null){if(typeof n==`string`||typeof n==`number`||typeof n==`boolean`){e[t]=n;return}if(Array.isArray(n)){let r=n.filter(e=>typeof e==`string`||typeof e==`number`||typeof e==`boolean`);if(r.length!==n.length||new Set(r.map(e=>typeof e)).size!==1)return;e[t]=r;return}if(typeof n==`object`)for(let[r,i]of Object.entries(n))flattenContextAttribute(e,`${t}.${r}`,i)}}function setOptionalAttribute(e,t,n){n!==void 0&&(e[t]=n)}export{agentActivationAttributes,agentPrincipalAttributes,runtimeContextAttributes};
1
+ import{agentInvocationSpanName}from"#tracing/agent-span-contract.js";import{agentSpanNamingAttributes}from"#tracing/agent-span-naming.js";import{agentTraceIdentityAttributes}from"#tracing/agent-otel-attributes.js";function agentActivationAttributes(e){return{"agent.framework.name":`eve`,"agent.framework.version":e.frameworkVersion,"agent.name":e.agentName,...agentPrincipalAttributes(e.turn),"agent.channel.delivery.id":e.turn.channelDelivery?.deliveryId,"agent.channel.delivery.input":e.turn.channelDelivery?.inputAttribute,"agent.channel.kind":e.turn.channelDelivery?.channelKind,"agent.channel.name":e.turn.channelDelivery?.channelName,"agent.channel.request.id":e.turn.channelDelivery?.requestId,"agent.parent_call.id":e.turn.parentLineage?.callId,"agent.parent_run.id":e.turn.parentLineage?.sessionId,"agent.subagent.name":e.turn.subagentName,"agent.turn.id":e.turnId,"agent.turn.sequence":e.turn.sequence,"gen_ai.agent.name":e.agentName,"gen_ai.operation.name":`invoke_agent`,...agentSpanNamingAttributes(agentInvocationSpanName(e.agentName),`invoke_agent`),...agentTraceIdentityAttributes({rootSessionId:e.turn.rootSessionId,sessionId:e.sessionId})}}function agentPrincipalAttributes(e){let t={};return setOptionalAttribute(t,`agent.principal.current.id`,e.currentPrincipal?.id),setOptionalAttribute(t,`agent.principal.current.type`,e.currentPrincipal?.type),setOptionalAttribute(t,`agent.principal.initiator.id`,e.initiatorPrincipal?.id),setOptionalAttribute(t,`agent.principal.initiator.type`,e.initiatorPrincipal?.type),t}function runtimeContextAttributes(e){let t={};if(e===void 0)return t;for(let[n,r]of Object.entries(e))flattenContextAttribute(t,`ai.settings.context.${n}`,r);return t}function flattenContextAttribute(e,t,n){if(n!=null){if(typeof n==`string`||typeof n==`number`||typeof n==`boolean`){e[t]=n;return}if(Array.isArray(n)){let r=n.filter(e=>typeof e==`string`||typeof e==`number`||typeof e==`boolean`);if(r.length!==n.length||new Set(r.map(e=>typeof e)).size!==1)return;e[t]=r;return}if(typeof n==`object`)for(let[r,i]of Object.entries(n))flattenContextAttribute(e,`${t}.${r}`,i)}}function setOptionalAttribute(e,t,n){n!==void 0&&(e[t]=n)}export{agentActivationAttributes,agentPrincipalAttributes,runtimeContextAttributes};
@@ -87,9 +87,9 @@ export default defineAgent({
87
87
  ```
88
88
 
89
89
  Handlers receive the shared [dynamic resolver
90
- context](./guides/dynamic-capabilities) (`ctx.session`, `ctx.channel`,
91
- `ctx.messages`) and return a gateway model id, an AI SDK `LanguageModel`, a
92
- selection object. Returning `null` or `undefined` fails the turn.
90
+ context](./guides/dynamic-capabilities) and return a gateway model id, an AI
91
+ SDK `LanguageModel`, or a selection object. Returning `null` or `undefined`
92
+ fails the turn.
93
93
 
94
94
  - **Scopes.** `session.started` (once per session), `turn.started` (once per
95
95
  turn), `step.started` (every model step). Precedence: step > turn >
@@ -67,7 +67,58 @@ In an eve workspace, eve discovers direct `agents/<name>/` children that contain
67
67
 
68
68
  Create this layout with `eve init my-project --agents support,research`, or add one agent to an existing workspace with `eve init billing`.
69
69
 
70
- With no authored `vercel.json#services`, `eve build` derives the complete Vercel Services graph on every build. If `vercel.json` declares `services`, that authored graph is authoritative instead; use `vercel build` to build and validate the complete project. This supports heterogeneous projects with frontends, private APIs, bindings, and other non-eve services without generated configuration files.
70
+ For an agent-only workspace, run `eve build`. eve owns the Vercel Build Output and generates one independently built service and a `/<name>/eve/v1/*` transport route for each workspace member.
71
+
72
+ ### Compose agents with other Vercel services
73
+
74
+ Use Vercel's programmatic configuration when a workspace also deploys a frontend, private API, or another non-eve service. Replace `vercel.json` with a root `vercel.ts` and compose the authored graph with `withEve`:
75
+
76
+ ```typescript title="vercel.ts"
77
+ import { withEve } from "eve/vercel";
78
+
79
+ export default await withEve({
80
+ services: {
81
+ web: {
82
+ framework: "nextjs",
83
+ root: "apps/web",
84
+ },
85
+ },
86
+ routes: [
87
+ {
88
+ src: "^(.*)$",
89
+ destination: { type: "service", service: "web" },
90
+ },
91
+ ],
92
+ });
93
+ ```
94
+
95
+ Vercel evaluates `vercel.ts` before resolving the service graph. `withEve` discovers direct workspace members, adds their services and transport routes, and returns a plain Vercel configuration. Vercel can then build `web` and every eve agent independently. The frontend does not need `withEve` in its framework configuration or a build script that builds the agents.
96
+
97
+ Generated transport routes are inserted before a filesystem handler or, when no filesystem handler exists, before authored routes. `withEve` throws instead of overwriting an authored service key or exact transport route that belongs to a generated agent. Remove the authored route, and remove or rename the authored service; `withEve` adds both automatically. Names in the array form of `services` must also be unique. Other service names, routes, bindings, and Cron Jobs remain authored in `vercel.ts`.
98
+
99
+ Custom agent channel endpoints are not published automatically. Expose one explicitly by routing it to the generated service:
100
+
101
+ ```typescript title="vercel.ts"
102
+ import { withEve } from "eve/vercel";
103
+
104
+ export default await withEve({
105
+ services: {
106
+ web: { framework: "nextjs", root: "apps/web" },
107
+ },
108
+ routes: [
109
+ {
110
+ src: "^/webhooks/github$",
111
+ destination: { type: "service", service: "eve-triage" },
112
+ },
113
+ {
114
+ src: "^(.*)$",
115
+ destination: { type: "service", service: "web" },
116
+ },
117
+ ],
118
+ });
119
+ ```
120
+
121
+ A Vercel project can use only one configuration source, so remove `vercel.json` when adopting `vercel.ts`. Keep `eve` in the root package dependencies so Vercel can import `eve/vercel` while evaluating the configuration. Pass `{ root: "/absolute/workspace/path" }` as the second argument only when `vercel.ts` is evaluated from somewhere other than the workspace root.
71
122
 
72
123
  An authored eve service routed at `/eve/v1` already uses the protocol path; callbacks remain at `/eve/v1/callback/*`. A named mount such as `/support` adds that mount before the protocol path, giving `/support/eve/v1/callback/*`.
73
124
 
@@ -68,22 +68,34 @@ availability depends on the caller, tenant, environment, or a feature flag.
68
68
  Return the child definition to configure and expose it. Return `null` to omit
69
69
  it from the parent's model-visible tools.
70
70
 
71
+ The example below exposes a finance subagent to enterprise callers and gives
72
+ it the model that the parent would use at that point:
73
+
71
74
  ```ts title="agent/subagents/finance/agent.ts"
72
75
  import { defineAgent, defineDynamic } from "eve";
73
76
 
74
77
  export default defineDynamic({
75
78
  events: {
76
- "session.started": (_event, ctx) =>
77
- ctx.session.auth.current?.attributes.plan === "enterprise"
78
- ? defineAgent({
79
- description: "Analyze financial and accounting data.",
80
- model: "openai/gpt-5.5",
81
- })
82
- : null,
79
+ "session.started": (_event, ctx) => {
80
+ if (ctx.session.auth.current?.attributes.plan !== "enterprise") {
81
+ return null;
82
+ }
83
+
84
+ return defineAgent({
85
+ description: "Analyze financial and accounting data.",
86
+ model: ctx.model ? ctx.model.id : "openai/gpt-5.5-mini",
87
+ });
88
+ },
83
89
  },
84
90
  });
85
91
  ```
86
92
 
93
+ `ctx.model` is the parent's effective model when the resolver runs. In this
94
+ example, this dynamic subagent uses the parent's effective model when it is
95
+ available falls back to `openai/gpt-5.5-mini` if the parent has not selected
96
+ one yet. The returned child config snapshots the model ID; a later parent
97
+ model change does not retarget the child.
98
+
87
99
  eve always compiles the subagent's filesystem resources, including its
88
100
  instructions, tools, skills, connections, sandbox, and nested subagents. It
89
101
  does not compile an agent config or placeholder model for a dynamic subagent.
@@ -153,7 +153,7 @@ export default otelIntegration({
153
153
  });
154
154
  ```
155
155
 
156
- Custom destinations receive the schema v4 agent trace contract. Follow [Query exported traces](./instrumentation#query-exported-traces) to find activations and join sessions across traces.
156
+ Custom destinations receive the schema v4 agent trace contract. Follow [Query exported traces](./instrumentation#query-exported-traces) to find activations and sessions across traces.
157
157
 
158
158
  Add `agent/instrumentation/otel.ts` when you need process-wide settings or want to control which content eve writes to OpenTelemetry spans:
159
159
 
@@ -56,7 +56,7 @@ Three more fields control what eve and the AI SDK record inside those spans (see
56
56
 
57
57
  eve records metadata without model, tool, or memory-record content by default. Enable either content category only after reviewing the exporter and its data-retention path.
58
58
 
59
- In the provider layout, eve stamps each span with `gen_ai.conversation.id`, which stays fixed across local and remote activations, including independent remote root workflows. Query this attribute to find the conversation's exported, retained traces; it does not grant access or control trace parenting. On Vercel, `vercel.session_id` additionally identifies the current Workflow run. See [Query exported traces](#query-exported-traces) for the cross-backend workflow.
59
+ In the provider layout, eve stamps each span with `gen_ai.conversation.id`, which stays fixed across local and remote activations, including independent remote root workflows. Query this attribute to find the conversation's exported, retained traces; it does not grant access or control trace parenting. On Vercel, `vercel.session_id` identifies the verified root session, while `agent.run.id` identifies the current agent run. See [Query exported traces](#query-exported-traces) for the cross-backend workflow.
60
60
 
61
61
  You are responsible for ensuring any observability or eval provider is approved for the data exported to it.
62
62
 
@@ -193,7 +193,14 @@ the failure outcome, error status, and error type. The initiating turn can
193
193
  finish or be cancelled while the action remains open. Ending the session closes
194
194
  an action whose task never reported a terminal result.
195
195
 
196
- Schema v4 removes the session-long `agent.session` root and duplicate agent session and lineage attributes. Every eve span carries `agent.trace.schema.version=4` and `gen_ai.conversation.id`; Vercel deployments additionally carry `vercel.session_id`.
196
+ Schema v4 removes the session-long `agent.session` root. Every run-associated
197
+ eve span carries `agent.trace.schema.version=4`, `agent.run.id`, and
198
+ `gen_ai.conversation.id`; the pre-session `agent.channel.request` span is the
199
+ exception. Vercel deployments additionally carry
200
+ `vercel.session_id`, which stays fixed to the root session across local and
201
+ trusted remote subagents. Remote lineage is accepted only when the receiver's
202
+ `trustedForwarders` predicate approves the authenticated caller. Child
203
+ activation roots carry `agent.parent_run.id` and `agent.parent_call.id`.
197
204
  Only activations use the `invoke_agent` operation. A workflow tool invocation
198
205
  that coordinates at least one nested agent uses `invoke_workflow`, with its
199
206
  path-derived tool name in `gen_ai.workflow.name`. Durable workflow tools without
@@ -207,8 +214,10 @@ A conversation remains durable state; `gen_ai.conversation.id` joins the activat
207
214
 
208
215
  Each activation owns a fresh trace identity, including local and remote
209
216
  subagents. The first child activation links to its caller with
210
- `eve.link.type=agent.dispatch`; incoming `traceparent` provides that link, not
211
- the child trace ID. Later turns do not reuse the original caller link.
217
+ `eve.link.type=agent.dispatch`; remote dispatch preserves that caller separately
218
+ in W3C `tracestate` while HTTP intermediaries update `traceparent`. Older peers
219
+ fall back to the incoming transport context. Later turns do not reuse the
220
+ original caller link.
212
221
  Conversation baggage is independent of execution lineage and trace-policy
213
222
  ceilings, which remain in force across the boundary.
214
223
 
@@ -259,7 +268,8 @@ This workflow applies to schema v4 from the [instrumentation provider layout](./
259
268
  | Agent activations | `agent.trace.schema.version=4` and `gen_ai.operation.name=invoke_agent` |
260
269
  | One logical conversation | `gen_ai.conversation.id=<conversation ID>` |
261
270
  | One turn | Both `gen_ai.conversation.id` and `agent.turn.id` |
262
- | One Vercel Workflow run | `vercel.session_id=<session ID>` |
271
+ | One Vercel root session | `vercel.session_id=<root session ID>` |
272
+ | One agent run | `agent.run.id=<run ID>` |
263
273
  | Delegated dispatches | `agent.invocation.role=caller` |
264
274
 
265
275
  Start with an activation filter for latency, failure, or turn-count dashboards. Every activation is a trace root. Within a conversation, group by trace ID, order activations by `agent.turn.sequence` or start time, and open the selected trace ID. Child activations link to their caller with `eve.link.type=agent.dispatch`; remote workflows keep their own execution lineage, so use conversation IDs and caller links for cross-deployment correlation.
@@ -288,7 +298,7 @@ invoke_agent support session=S, turn=turn_1, conversation=S
288
298
 
289
299
  The conversation filter finds all three retained traces. eve initializes the conversation ID once and carries it through the existing parent context for local dispatch and `eve.conversation.id` baggage for remote dispatch. Remote session creation does not carry execution lineage or add authorization requirements for tracing. Existing authentication, principal forwarding, and root-session limits remain unchanged.
290
300
 
291
- `traceparent` carries the caller's trace and span IDs for the causal link; adopting it as the child's parent would instead keep both in the same trace. Resolved trace-policy decisions and trusted remote content ceilings continue across this boundary independently of correlation, and an unsampled caller cannot be widened into a sampled child. No synthetic session span is needed.
301
+ Remote dispatch records the caller's span ID in eve's W3C `tracestate` entry because HTTP intermediaries may advance `traceparent` to their own request span. The receiver combines that prior parent with the current trace identity for the causal link and retains the transport context for `channel.request`; adopting either as the child's parent would instead keep both in the same trace. Resolved trace-policy decisions and trusted remote content ceilings continue across this boundary independently of correlation, and an unsampled caller cannot be widened into a sampled child. No synthetic session span is needed.
292
302
 
293
303
  Activation duration is elapsed time for that activation, including waits inside it, not the lifetime of the conversation or CPU time. Idle time between ended activations is not part of their durations. For token totals, choose one level: filter to `chat` model spans and sum `gen_ai.usage.*`, or filter to activations and sum their `agent.usage.input_tokens` and `agent.usage.output_tokens`. Exclude caller summaries from the activation total. Query cache usage on model spans. Do not add model, step, activation, and caller counters together.
294
304
 
@@ -139,16 +139,16 @@ Identity forwarding does not make a persistent session private to one caller. Co
139
139
 
140
140
  Forwarding is explicit on both sides. The receiver names which forwarders it trusts with `eveChannel({ trustedForwarders })` (see [Auth & route protection](./auth-and-route-protection#accepting-forwarded-identity-from-another-deployment)); a receiver that refuses the forwarder — or has no `trustedForwarders` at all — rejects with a 403 and the dispatch fails.
141
141
 
142
- Remote tracing uses ordinary `traceparent` propagation. Trace context is not an authorization grant: it cannot assert eve parent lineage, change `rootSessionId`, or remove the normal root-session token cap.
142
+ Remote tracing uses [W3C Trace Context](https://www.w3.org/TR/trace-context/). `traceparent` identifies the immediate HTTP parent, while eve's `eve=<caller-span-id>` vendor entry in `tracestate` preserves the dispatching caller when an intermediary advances `traceparent` to its own request span. The receiver uses the eve entry for the child's `agent.dispatch` link and the transport context for request correlation. Older senders and missing or malformed eve entries fall back to `traceparent`. Trace context is not an authorization grant: it cannot assert eve parent lineage, change `rootSessionId`, or remove the normal root-session token cap.
143
143
 
144
144
  eve also carries the original `gen_ai.conversation.id` in `eve.conversation.id` baggage so you can find related traces across local and remote agents. This observability identifier does not require principal forwarding or shared execution lineage; it grants no session access and does not change trace-content policy. Session execution establishes this ID even without an instrumentation runtime. Only session-create requests with a callback may supply this baggage; top-level requests ignore it and establish their own conversation ID. Callback metadata is caller-supplied correlation, not verified identity.
145
145
 
146
- eve replaces configured `traceparent` and conversation baggage only when it has a framework value to send. Incoming baggage has an 8 KiB limit; the audience and conversation readers share whitespace, percent-decoding, and duplicate-key validation. Conversation IDs are limited to 1 KiB and exclude control characters and line separators. If adding an audience assertion or conversation ID would exceed 8 KiB, eve rejects the dispatch before sending a request instead of dropping the member. Reduce `remote.headers.baggage` to leave room for these framework values.
146
+ eve replaces configured `traceparent` and conversation baggage only when it has a framework value to send. It replaces its own `tracestate` entry while preserving other valid vendor entries; without a valid caller context, eve removes only its entry. Incoming baggage has an 8 KiB limit; the audience and conversation readers share whitespace, percent-decoding, and duplicate-key validation. Conversation IDs are limited to 1 KiB and exclude control characters and line separators. If adding an audience assertion or conversation ID would exceed 8 KiB, eve rejects the dispatch before sending a request instead of dropping the member. Reduce `remote.headers.baggage` to leave room for these framework values.
147
147
 
148
148
  In the [provider trace contract](./instrumentation#agent-trace-contract), each
149
- child activation starts a separate trace. The first activation uses the incoming
150
- `traceparent` as an `agent.dispatch` span link rather than adopting the caller's
151
- trace ID.
149
+ child activation starts a separate trace. The first activation uses the
150
+ caller preserved in W3C `tracestate`, falling back to incoming `traceparent`,
151
+ as an `agent.dispatch` span link rather than adopting the caller's trace ID.
152
152
 
153
153
  > ⚠️ **Upgrade both deployments before resuming persistent remote sessions.** A sender with continuation forwarding includes `forwardedPrincipal` on each authenticated follow-up. A receiver that supports forwarding only on session creation rejects that continuation with HTTP 400. eve does not retry without the field because that would run the follow-up as the transport service principal and silently change caller authority. The parent retains the child handle after this failure, so you can retry the same session after upgrading the receiver.
154
154
 
@@ -56,7 +56,7 @@ Creates a new agent app or adds an agent to an existing app. Always installs dep
56
56
 
57
57
  Coding-agent launches and non-interactive terminals cannot answer the location prompt and fail before writing. Pass a new directory name, such as `eve init my-agent`, in those environments.
58
58
 
59
- After scaffolding, a human terminal usually continues into `eve dev`. If a coding-agent REPL is on `PATH`, the handoff menu can open it instead or exit without starting either process. Coding-agent launches print the next steps instead of opening the TUI, so the session does not get stuck. Fresh projects use the parent workspace's package manager when there is one; otherwise they use the manager that launched `eve init`.
59
+ After scaffolding, a human terminal usually continues into `eve dev`. Enable the self-modification subagent to edit your agent from the dev session. Otherwise, if a coding-agent REPL is on `PATH`, you can launch it to make changes instead of opening the TUI. Fresh projects use the parent workspace's package manager when there is one; otherwise they use the manager that launched `eve init`.
60
60
 
61
61
  | Flag | Type | Default | Description |
62
62
  | ---------------------- | ------ | -------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
@@ -308,7 +308,7 @@ Reads the immutable OTLP/JSON segments under `.eve/traces/v1`, so `eve dev` need
308
308
 
309
309
  Span rows carry inline metrics when the span recorded them — `↑input`/`↓output` token counts, gateway cost, and the tool name for `execute_tool` spans — and the header aggregates models, token totals, cost, and error count across the trace's step spans. `--verbose` expands each span under its tree row: status (with the error message on failures), timing, ids, every attribute (prompts, responses, and tool payloads as transcripts or pretty-printed JSON), and every span event with its offset from span start. `--json` prints the same records as JSON, one object per selected trace.
310
310
 
311
- Every subagent activation starts its own trace. The first child's `invoke_agent` root links to the dispatching caller with `eve.link.type=agent.dispatch`; remote agents carry that caller context over `traceparent`. Later turns also start fresh traces without repeating the initial caller link. All related sessions retain the same `gen_ai.conversation.id`, and `agent.subagent.name` labels the child invocation.
311
+ Every subagent activation starts its own trace. The first child's `invoke_agent` root links to the dispatching caller with `eve.link.type=agent.dispatch`; remote agents preserve that caller in W3C `tracestate` even when HTTP `traceparent` advances through platform ingress. Later turns also start fresh traces without repeating the initial caller link. All related sessions retain the same `gen_ai.conversation.id`, and `agent.subagent.name` labels the child invocation.
312
312
 
313
313
  Each `agent()` call inside an authored workflow has its own `agent.action` caller span, including sequential, parallel, and background calls. A workflow tool that coordinates one of those calls has an enclosing `invoke_workflow <tool>` span; a workflow tool without agent calls remains `agent.action`. The tool also keeps its `execute_tool <tool>` span. Only agent execution uses `invoke_agent`.
314
314
 
@@ -12,7 +12,7 @@ eve collects usage data from its CLI to help improve its commands and developmen
12
12
  eve sends the following information to Vercel:
13
13
 
14
14
  - The eve version, operating system, CPU architecture, and whether stdin is a terminal.
15
- - The command you ran, its outcome, and setup or onboarding steps when applicable. When setup or onboarding fails, eve sends a bounded failure category such as target resolution, scaffolding, package-manager startup, workspace probing, dependency installation, Git initialization, handoff, or onboarding. It does not send the underlying error.
15
+ - The command you ran, its outcome, and setup or onboarding steps when applicable. When setup or onboarding fails, eve sends a bounded category describing the failed step. It does not send the underlying error.
16
16
  - For `eve dev`, whether you connected to a local or remote agent and whether the UI was interactive or headless.
17
17
  - Random identifiers for the CLI session, installation, and project, plus whether the installation and project identifiers are ephemeral or persistent.
18
18
 
@@ -186,26 +186,29 @@ Pass another bare OpenAI model slug to override the default. `experimental_chatg
186
186
 
187
187
  `chatgpt()` uses stateless requests (`store: false`). eve retains reasoning summaries and encrypted reasoning in session history and replays them after tool calls and on later turns. You do not need to configure `reasoning.encrypted_content` explicitly.
188
188
 
189
- Sign in directly from eve; the Codex CLI is not required:
189
+ eve uses one local authentication path with two credential owners:
190
190
 
191
191
  1. Run `eve dev`, open `/model`, and select **Provider** → **ChatGPT subscription**.
192
- 2. Complete sign-in in the browser. If the browser does not open, use the URL printed in the terminal.
193
- 3. Return to eve after the terminal confirms that your subscription is connected. Normal token expiry is refreshed automatically.
192
+ 2. If `codex` is on `PATH`, eve uses `codex app-server` and launches `codex login` when sign-in is needed. Codex owns credential storage and refresh.
193
+ 3. If the Codex binary is not found, eve falls back to direct browser sign-in and owns the saved session and refresh. If the browser does not open, use the URL printed in the terminal.
194
194
 
195
- eve stores your refresh token and account details in your operating system's credential store through [just-secrets](https://github.com/vercel-labs/just-secrets): the login Keychain on macOS, Credential Manager on Windows, or Secret Service on Linux. Access tokens stay in process memory; a new eve process refreshes the saved session when it first needs a token. The login is separate from Codex and is never written to your project.
195
+ When Codex is available, eve asks app-server for tokens and does not read or write Codex login files. App-server errors other than a missing binary are reported instead of silently switching credential owners.
196
196
 
197
- If you previously signed in through Codex or used eve's `~/.eve/auth/chatgpt.json` file, sign in once through eve after upgrading. eve removes the old plaintext file after successfully saving the new session. It does not fall back to file storage if the OS credential store is unavailable.
197
+ For the eve-owned fallback, eve stores your refresh token and account details in your operating system's credential store through [just-secrets](https://github.com/vercel-labs/just-secrets): the login Keychain on macOS, Credential Manager on Windows, or Secret Service on Linux. Access tokens stay in process memory; a new eve process refreshes the saved session when it first needs a token. The fallback login is separate from Codex and is never written to your project.
198
+
199
+ If you previously used eve's `~/.eve/auth/chatgpt.json` file, sign in once through the eve-owned fallback after upgrading. A successful save removes the old plaintext session file. eve does not fall back to file storage if the OS credential store is unavailable.
198
200
 
199
201
  Linux, including WSL, requires `/usr/bin/secret-tool` (commonly provided by `libsecret-tools`), a session D-Bus, and an unlocked Secret Service keyring. On macOS, unlock your login keychain and allow credential access if prompted. On Windows, PowerShell and Credential Manager must be available in your user session. OS credential storage protects secrets at rest; it does not guarantee isolation from malicious processes running as your OS user.
200
202
 
201
- Over SSH, or if localhost port 1455 is occupied, eve shows a device code instead. Open the displayed link in a browser and enter the code. Device sign-in requires enabling device code authorization in **ChatGPT Settings → Security**, or having a workspace admin enable it in workspace permissions. Sign-in times out after five minutes; press **Ctrl+C** to cancel sooner. Device sign-in still requires an available OS credential store; use an API-key model in headless environments without one.
203
+ For the eve-owned fallback, SSH sessions or a busy localhost port 1455 use a device code. Open the displayed link in a browser and enter the code. Device sign-in requires enabling device code authorization in **ChatGPT Settings → Security**, or having a workspace admin enable it in workspace permissions. Sign-in times out after five minutes; press **Ctrl+C** to cancel sooner. Device sign-in still requires an available OS credential store; use an API-key model in headless environments without one.
202
204
 
203
205
  ChatGPT subscription credentials are local user credentials. `eve deploy` blocks agents whose active model is `chatgpt()` because those credentials are not uploaded to a deployment. Use an environment branch with a deployable model, or switch to an AI Gateway model before deploying.
204
206
 
205
207
  Troubleshooting:
206
208
 
207
- - **`chatgpt-sub login`**: open `/model` and select **Provider** → **ChatGPT subscription** to sign in again. The running dev session picks up the new login.
208
- - **`chatgpt-sub unavailable`**: follow the reported OS credential-store recovery steps, or check your network connection if token refresh failed. Retry from `/model`. If eve reports an invalid stored session, sign in again to replace it.
209
+ - **`chatgpt-sub login`**: open `/model` and select **Provider** → **ChatGPT subscription** to sign in again. eve launches `codex login` when Codex is available, or its direct sign-in flow when it is not.
210
+ - **`chatgpt-sub unavailable` with Codex installed**: update or restart Codex and retry. eve does not mask app-server failures by switching to a different saved session.
211
+ - **`chatgpt-sub unavailable` without Codex**: follow the reported OS credential-store recovery steps, or check your network connection if token refresh failed. Retry from `/model`. If eve reports an invalid stored session, sign in again to replace it.
209
212
  - **Model rejected by the backend**: model availability depends on the signed-in ChatGPT account. Pick another supported OpenAI model.
210
213
  - **Device sign-in unavailable**: enable device code authorization in ChatGPT security settings, or sign in from a local terminal with port 1455 available.
211
214
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve",
3
- "version": "0.54.3",
3
+ "version": "0.54.4",
4
4
  "private": false,
5
5
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
6
6
  "keywords": [
@@ -86,6 +86,12 @@
86
86
  "import": "./dist/src/public/next/index.js",
87
87
  "default": "./dist/src/public/next/index.js"
88
88
  },
89
+ "./vercel": {
90
+ "eve-source": "./src/public/vercel/index.ts",
91
+ "types": "./dist/src/public/vercel/index.d.ts",
92
+ "import": "./dist/src/public/vercel/index.js",
93
+ "default": "./dist/src/public/vercel/index.js"
94
+ },
89
95
  "./nuxt": {
90
96
  "types": "./dist/src/public/nuxt/index.d.ts",
91
97
  "import": "./dist/src/public/nuxt/index.js",
@@ -471,14 +477,14 @@
471
477
  "@vercel/sandbox": "3.2.1",
472
478
  "@vercel/sandbox-drives": "npm:@vercel/sandbox@3.1.0-beta.1",
473
479
  "@vercel/sdk": "1.28.8",
474
- "@workflow/builders": "5.0.0-beta.50",
475
- "@workflow/core": "5.0.0-beta.50",
480
+ "@workflow/builders": "5.0.0-beta.51",
481
+ "@workflow/core": "5.0.0-beta.51",
476
482
  "@workflow/errors": "5.0.0-beta.21",
477
483
  "@workflow/serde": "5.0.0-beta.2",
478
484
  "@workflow/utils": "5.0.0-beta.10",
479
- "@workflow/world": "5.0.0-beta.34",
480
- "@workflow/world-local": "5.0.0-beta.43",
481
- "@workflow/world-vercel": "5.0.0-beta.45",
485
+ "@workflow/world": "5.0.0-beta.35",
486
+ "@workflow/world-local": "5.0.0-beta.44",
487
+ "@workflow/world-vercel": "5.0.0-beta.46",
482
488
  "ai": "^7.0.93",
483
489
  "autoevals": "0.0.132",
484
490
  "chat": "4.34.0",