eve 0.54.2 → 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 (146) hide show
  1. package/CHANGELOG.md +22 -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/dev/tui/setup-commands.js +1 -1
  13. package/dist/src/cli/telemetry/index.d.ts +1 -1
  14. package/dist/src/compiled/.vendor-stamp.json +8 -6
  15. package/dist/src/compiled/@ai-sdk/anthropic/index.js +2 -2
  16. package/dist/src/compiled/@ai-sdk/google/index.js +7 -7
  17. package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
  18. package/dist/src/compiled/@ai-sdk/openai/index.js +4 -4
  19. package/dist/src/compiled/@opentelemetry/api/index.d.ts +2 -0
  20. package/dist/src/compiled/@workflow/core/events-consumer.d.ts +26 -0
  21. package/dist/src/compiled/@workflow/core/flushable-stream.d.ts +41 -0
  22. package/dist/src/compiled/@workflow/core/index.js +2 -2
  23. package/dist/src/compiled/@workflow/core/replay-divergence.d.ts +25 -0
  24. package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +75 -1
  25. package/dist/src/compiled/@workflow/core/runtime/quickjs-entrypoint.d.ts +30 -8
  26. package/dist/src/compiled/@workflow/core/runtime/quickjs-log-view.d.ts +129 -0
  27. package/dist/src/compiled/@workflow/core/runtime/step-executor.d.ts +2 -21
  28. package/dist/src/compiled/@workflow/core/runtime/suspension-handler.d.ts +0 -22
  29. package/dist/src/compiled/@workflow/core/runtime.js +3 -3
  30. package/dist/src/compiled/@workflow/core/serialization.d.ts +2 -2
  31. package/dist/src/compiled/@workflow/core/step/context-storage.d.ts +2 -0
  32. package/dist/src/compiled/@workflow/core/telemetry/semantic-conventions.d.ts +36 -0
  33. package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
  34. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  35. package/dist/src/compiled/@workflow/world/analytics.d.ts +23 -23
  36. package/dist/src/compiled/@workflow/world/events.d.ts +4 -2
  37. package/dist/src/compiled/@workflow/world/queue.d.ts +84 -0
  38. package/dist/src/compiled/@workflow/world-local/index.js +5 -5
  39. package/dist/src/compiled/@workflow/world-vercel/index.js +18 -13
  40. package/dist/src/compiled/_chunks/workflow/attribute-changes-BAcgmlXp.js +20 -0
  41. package/dist/src/compiled/_chunks/workflow/coerce-ro2dOxbr.js +1 -0
  42. package/dist/src/compiled/_chunks/workflow/dist-KPieTJHT.js +25 -0
  43. package/dist/src/compiled/_chunks/workflow/dist-PLkAQ-U7.js +2 -0
  44. package/dist/src/compiled/_chunks/workflow/frames-BvATzM2t.js +3 -0
  45. package/dist/src/compiled/_chunks/workflow/{functions-C02-JHBK.js → functions-wMCGZAVk.js} +1 -1
  46. package/dist/src/compiled/_chunks/workflow/resume-hook-BEHe0Uut.js +1 -0
  47. package/dist/src/compiled/_chunks/workflow/run-ChHLjaCt.js +1 -0
  48. package/dist/src/compiled/_chunks/workflow/schemas-DR7NTzNe.js +50 -0
  49. package/dist/src/compiled/_chunks/workflow/sleep-BB2HuVie.js +1 -0
  50. package/dist/src/compiled/_chunks/workflow/{wrapper-BxECO5nh.js → wrapper-CKui_eTd.js} +2 -2
  51. package/dist/src/compiled/_chunks/workflow/ws-transport-CVezyWwZ.js +1 -0
  52. package/dist/src/compiled/just-secrets/LICENSE +21 -0
  53. package/dist/src/compiled/just-secrets/index.d.ts +20 -0
  54. package/dist/src/compiled/just-secrets/index.js +2 -0
  55. package/dist/src/compiled/just-secrets/windows.ps1 +138 -0
  56. package/dist/src/compiler/extension-compatibility.d.ts +12 -12
  57. package/dist/src/compiler/extension-compatibility.js +1 -1
  58. package/dist/src/compiler/normalize-manifest-helpers.d.ts +2 -1
  59. package/dist/src/compiler/normalize-manifest-helpers.js +1 -1
  60. package/dist/src/compiler/normalize-manifest.js +1 -1
  61. package/dist/src/compiler/resolve-workspace-subagent.d.ts +13 -0
  62. package/dist/src/compiler/resolve-workspace-subagent.js +1 -0
  63. package/dist/src/context/dynamic-model-lifecycle.d.ts +0 -6
  64. package/dist/src/context/dynamic-model-lifecycle.js +1 -1
  65. package/dist/src/context/dynamic-resolve-context.js +1 -1
  66. package/dist/src/context/effective-model.d.ts +5 -0
  67. package/dist/src/context/effective-model.js +1 -0
  68. package/dist/src/context/keys.d.ts +2 -0
  69. package/dist/src/context/keys.js +1 -1
  70. package/dist/src/dynamic/definition.d.ts +4 -0
  71. package/dist/src/eve-channel/index.js +1 -1
  72. package/dist/src/eve-channel/types.d.ts +9 -7
  73. package/dist/src/execution/durable-session-migrations/snapshot.d.ts +0 -16
  74. package/dist/src/execution/durable-session-migrations/snapshot.js +1 -1
  75. package/dist/src/execution/eve-workflow-attributes.d.ts +1 -1
  76. package/dist/src/execution/run-session-limits.js +1 -1
  77. package/dist/src/execution/session.js +1 -1
  78. package/dist/src/execution/tools/sleep-workflow.js +1 -1
  79. package/dist/src/execution/workflow-steps.js +1 -1
  80. package/dist/src/harness/compaction.js +1 -1
  81. package/dist/src/harness/messages.d.ts +1 -1
  82. package/dist/src/harness/messages.js +1 -1
  83. package/dist/src/harness/step-hooks.d.ts +16 -10
  84. package/dist/src/harness/step-hooks.js +1 -1
  85. package/dist/src/harness/tool-loop.js +2 -2
  86. package/dist/src/instrumentation/parent-lineage.js +1 -1
  87. package/dist/src/internal/application/package.js +1 -1
  88. package/dist/src/internal/nitro/routes/index.d.ts +6 -0
  89. package/dist/src/internal/nitro/routes/index.js +7 -7
  90. package/dist/src/internal/vercel/assemble-eve-services.js +1 -1
  91. package/dist/src/internal/vercel/build-agent-workspace.js +1 -1
  92. package/dist/src/internal/vercel/build-multi-agent-landing-page.d.ts +3 -0
  93. package/dist/src/internal/vercel/build-multi-agent-landing-page.js +1 -0
  94. package/dist/src/internal/vercel/eve-service-contribution.d.ts +4 -0
  95. package/dist/src/internal/vercel/eve-service-contribution.js +1 -1
  96. package/dist/src/internal/vercel/vercel-services-config.js +1 -1
  97. package/dist/src/protocol/baggage.d.ts +6 -0
  98. package/dist/src/protocol/baggage.js +1 -1
  99. package/dist/src/protocol/traceparent.d.ts +13 -0
  100. package/dist/src/protocol/traceparent.js +1 -1
  101. package/dist/src/public/definitions/workspace-agent.d.ts +25 -0
  102. package/dist/src/public/definitions/workspace-agent.js +1 -0
  103. package/dist/src/public/index.d.ts +1 -0
  104. package/dist/src/public/index.js +1 -1
  105. package/dist/src/public/models/openai/chatgpt/codex-app-server.d.ts +41 -0
  106. package/dist/src/public/models/openai/chatgpt/codex-app-server.js +1 -0
  107. package/dist/src/public/models/openai/chatgpt/credential-store.d.ts +26 -4
  108. package/dist/src/public/models/openai/chatgpt/credential-store.js +1 -1
  109. package/dist/src/public/models/openai/chatgpt/oauth.d.ts +6 -4
  110. package/dist/src/public/models/openai/chatgpt/token-broker.d.ts +7 -7
  111. package/dist/src/public/models/openai/chatgpt/token-broker.js +1 -1
  112. package/dist/src/public/models/openai/chatgpt/token.d.ts +13 -0
  113. package/dist/src/public/models/openai/chatgpt/token.js +1 -0
  114. package/dist/src/public/models/openai/chatgpt/transport.d.ts +2 -1
  115. package/dist/src/public/models/openai/index.d.ts +3 -2
  116. package/dist/src/public/vercel/index.d.ts +50 -0
  117. package/dist/src/public/vercel/index.js +1 -0
  118. package/dist/src/self-modification/setup.js +7 -2
  119. package/dist/src/setup/flows/chatgpt-auth.d.ts +2 -1
  120. package/dist/src/setup/flows/chatgpt-auth.js +1 -1
  121. package/dist/src/setup/flows/model.d.ts +0 -2
  122. package/dist/src/setup/flows/model.js +1 -1
  123. package/dist/src/setup/scaffold/create/project.js +1 -1
  124. package/dist/src/subagents/remote-dispatch.d.ts +3 -1
  125. package/dist/src/subagents/remote-dispatch.js +1 -1
  126. package/dist/src/tracing/agent-otel-attributes.js +1 -1
  127. package/dist/src/tracing/agent-otel-runtime-context.js +1 -1
  128. package/docs/agent-config.md +3 -3
  129. package/docs/guides/deployment/vercel.mdx +52 -1
  130. package/docs/guides/dynamic-capabilities.md +19 -7
  131. package/docs/guides/instrumentation-providers.md +1 -1
  132. package/docs/guides/instrumentation.md +25 -6
  133. package/docs/guides/remote-agents.md +5 -5
  134. package/docs/reference/cli.md +2 -2
  135. package/docs/reference/telemetry.md +1 -1
  136. package/docs/reference/typescript-api.md +14 -7
  137. package/docs/subagents/index.mdx +31 -0
  138. package/package.json +13 -6
  139. package/dist/src/compiled/_chunks/workflow/attribute-changes-C6H-fRVP.js +0 -20
  140. package/dist/src/compiled/_chunks/workflow/dist-DDeH-1ER.js +0 -40
  141. package/dist/src/compiled/_chunks/workflow/dist-DhncQSl7.js +0 -74
  142. package/dist/src/compiled/_chunks/workflow/frames-DsEqSDes.js +0 -3
  143. package/dist/src/compiled/_chunks/workflow/resume-hook-BRDLAb67.js +0 -1
  144. package/dist/src/compiled/_chunks/workflow/run-BM2OFphk.js +0 -1
  145. package/dist/src/compiled/_chunks/workflow/sleep-6cG0F99-.js +0 -1
  146. package/dist/src/compiled/_chunks/workflow/ws-transport-DuK82LLz.js +0 -1
@@ -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{createChatGptCredentialStore}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();if(e.signal?.throwIfAborted(),(await t.refreshState()).kind===`ready`)return;let n=new AbortController,cancel=()=>n.abort(new WizardCancelledError);process.once(`SIGINT`,cancel);let r=setTimeout(()=>n.abort(Error(`ChatGPT sign-in timed out. Retry from /model.`)),3e5),i=AbortSignal.any([n.signal,...e.signal?[e.signal]:[]]),a=e.log??(e=>process.stdout.write(`${e}\n`)),o=e.open??openUrl;try{let n=e.headless??!!(process.env.SSH_CONNECTION||process.env.SSH_TTY)?await deviceLogin({...e,signal:i,log:a,open:o}):await browserLogin({...e,signal:i,log:a,open:o});if(i.throwIfAborted(),await(e.store??createChatGptCredentialStore()).update(async()=>(i.throwIfAborted(),n)),(await t.refreshState()).kind!==`ready`)throw Error(`ChatGPT sign-in could not be verified. Retry from /model.`);a(`ChatGPT subscription connected.`)}catch(e){throw i.throwIfAborted(),e}finally{clearTimeout(r),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};
@@ -120,8 +120,6 @@ export declare function runModelFlow(input: {
120
120
  initialStep?: "provider";
121
121
  onScreen?: (screen: "model_provider" | "model_settings") => void;
122
122
  signal?: AbortSignal;
123
- /** Gives ChatGPT sign-in exclusive terminal ownership. */
124
- withExclusiveTerminal?: <T>(task: () => Promise<T>) => Promise<T>;
125
123
  /** Live ChatGPT identity shown in this configuration flow only. */
126
124
  chatGptAccountLabel?: string;
127
125
  deps?: Partial<ModelFlowDeps>;
@@ -1 +1 @@
1
- import{AI_GATEWAY_API_KEY_ENV_VAR}from"../ai-gateway-api-key.js";import{withSpinner}from"../with-spinner.js";import{gatewayModelCapabilities}from"../boxes/model-capabilities.js";import{fetchGatewayCatalog,modelOptionsFromCatalog}from"../boxes/select-model.js";import{ensureChatGptAuth}from"./chatgpt-auth.js";import{WizardCancelledError}from"../step.js";import{changeAgentModelSettings,formatApplyModelSettingsOutcome}from"./model-source-change.js";import{runProviderFlow}from"./provider.js";import pc from"#compiled/picocolors/index.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";import{inspectApplication}from"#services/inspect-application.js";import{readProviderSelection,resolveAvailableProviders,writeProviderSelection}from"#setup/provider-settings.js";import{formatModelSummary}from"#shared/model-summary.js";import{readGatewayServiceTier}from"#shared/gateway-service-tier.js";import{DEFAULT_CHATGPT_MODEL_SELECTION,isChatGptModelRouting,parseChatGptModelSelection}from"#shared/chatgpt-model.js";const MODEL_MENU_MESSAGE=``;function providerSelectionHint(e,t){return e===`chatgpt`?t===void 0?`ChatGPT subscription`:`ChatGPT subscription (${t})`:e===`ai-gateway-project`?`AI Gateway via Project`:`AI Gateway via ${AI_GATEWAY_API_KEY_ENV_VAR}`}function modelListRows(e){return modelOptionsFromCatalog(e).map(e=>{let t={value:e.value,label:e.value};return e.featured===!0&&(t.featured=!0),t})}function formatModelDraftHint(e,t,n){let r={model:e};return t!==null&&(r.reasoning=t),n.kind===`priority`&&(r.fastGlyph=`↯`),formatModelSummary(r)}function modelMenuRows(e,t,n,r,i,a,o,s,c){let l;s||c?(l={value:`model`,label:`Change model`,description:s?`The model, its reasoning effort, and the Gateway service tier`:`Reasoning and service tier; the model itself is an SDK model call in agent.ts`},e!==null&&(l.hint=formatModelDraftHint(e,t,n))):l={value:`model`,label:`Change model`,disabled:!0,description:`Set via an SDK model call in agent.ts; edit the source to change it`};let u;return u=o?.kind===`external`&&!isChatGptModelRouting(o)?{disabled:!0,value:`provider`,label:`Change provider`,description:`Disabled in external endpoint mode`}:i?{value:`provider`,label:`Change provider`,hint:providerSelectionHint(r,a),description:`How your agent reaches the model provider`}:{value:`provider`,label:pc.bold(`Configure model access`),hint:pc.yellow(`Not configured`),description:`How your agent reaches the model provider`,accent:`warning`},[l,u,{value:`done`,label:`Done`}]}async function runModelFlow(e){let{appRoot:t,prompter:n,signal:r}=e,i=e.environmentRoot??t,a={readCurrentModel:readCurrentAgentModel,applySettings:changeAgentModelSettings,resolveAvailableProviders,readProviderSelection,runProviderFlow,ensureChatGptAuth,writeProviderSelection,...e.deps},o=a.selectModel?.fetchModels??fetchGatewayCatalog,[s,c,l,u]=await withSpinner(n,`Checking the project…`,()=>Promise.all([a.readCurrentModel(t),a.resolveAvailableProviders(i,r===void 0?{env:process.env}:{signal:r,env:process.env}),a.readProviderSelection(i),o(r).catch(()=>void 0)]));r?.throwIfAborted();let{id:d,routing:f,serviceTier:p,editable:m,settingsEditable:h}=s,g=s.reasoning===`provider-default`?null:s.reasoning,_=l??(c.includes(`ai-gateway-key`)?`ai-gateway-key`:`ai-gateway-project`),v=c.includes(_),y,b={model:{kind:`keep`},reasoning:{kind:`keep`},gatewayServiceTier:{kind:`keep`}},x,S,C=!1,w=!1,T=!1,E=f?.kind===`external`&&!isChatGptModelRouting(f),D=E?{tone:`warning`,text:"`agent.ts` specifies the model provider directly. Model, provider, and service-tier changes stay source-owned; reasoning remains configurable here."}:void 0,O=!v&&f?.kind!==`external`?`provider`:m||h?`model`:`provider`,k=f?.kind!==`external`&&(e.initialStep===`provider`||!v);for(;;){let t;if(k)k=!1,t=`provider`;else try{t=await n.select({message:``,options:modelMenuRows(d,g,isChatGptModelRouting(f)?{kind:`standard`}:p,_,v,e.chatGptAccountLabel,f,m,h),hintLayout:`stacked`,initialValue:O,notices:D===void 0?[]:[D]})}catch(e){if(!(e instanceof WizardCancelledError))throw e;if(hasModelSettingsChanges(b))return{kind:`cancelled`,discardedDraft:!0};break}if(t===`done`){w=!0,T=!0;break}if(t===`model`){e.onScreen?.(`model_settings`);let t=a.pickModelSettings;if(t===void 0)throw Error(`runModelFlow requires a pickModelSettings dep to open the model screen.`);let n=await t({model:m?{kind:`pick`,options:modelListRows(u),current:d}:{kind:`fixed`,current:d,reason:`Set via an SDK model call in agent.ts; edit the source to change it`},reasoning:g,serviceTier:isChatGptModelRouting(f)?{kind:`standard`}:p,settingsEditable:h,externalRouting:E,capabilitiesFor:e=>gatewayModelCapabilities(u,e)});if(r?.throwIfAborted(),n===void 0){O=`model`;continue}n.model!==void 0&&(d=n.model,f=routingForModelSelection(n.model),b.model={kind:`set`,value:n.model}),n.reasoning!==void 0&&(g=n.reasoning==="default"?null:n.reasoning,b.reasoning=g===null?{kind:`remove`}:{kind:`set`,value:g}),n.serviceTier!==void 0&&!isChatGptModelRouting(f)&&(p=n.serviceTier===`priority`?{kind:`priority`}:{kind:`standard`},b.gatewayServiceTier=n.serviceTier===`priority`?{kind:`set`,value:`priority`}:{kind:`remove`}),O=`done`;continue}e.onScreen?.(`model_provider`);let o=await a.runProviderFlow({appRoot:i,prompter:n,signal:r,availableProviders:c,selectedProvider:_});if(o.kind===`cancelled`){if(r?.aborted)return{kind:`cancelled`};O=`provider`;continue}if(o.kind===`external-provider`){if(r?.aborted)return{kind:`cancelled`};O=`done`;continue}y=o.kind,y===`chatgpt`?(C=!0,isChatGptModelRouting(f)||(b.model={kind:`set`,value:DEFAULT_CHATGPT_MODEL_SELECTION},b.gatewayServiceTier={kind:`remove`})):isChatGptModelRouting(f)&&(b.model={kind:`set`,value:DEFAULT_AGENT_MODEL_ID}),T=!0;break}let A=b.model.kind===`set`&&parseChatGptModelSelection(b.model.value)!==void 0;if(T&&A&&(b.gatewayServiceTier={kind:`remove`},C=!0),T&&C&&await authenticateChatGpt(a,e.withExclusiveTerminal,r),T&&hasModelSettingsChanges(b)&&(x=await a.applySettings({appRoot:t,patch:b})),T&&y!==void 0&&x?.kind!==`rejected`&&(await a.writeProviderSelection(i,y),S=y),x!==void 0&&S===void 0&&r?.throwIfAborted(),x===void 0&&S===void 0&&!C)return w?{kind:`done`,accessChanged:!1}:{kind:`cancelled`};let j={kind:`done`,accessChanged:x?.kind===`changed`||S!==void 0||C};return x===void 0?C&&(j.modelMessage=`ChatGPT login ready.`):j.modelMessage=formatApplyModelSettingsOutcome(x),S!==void 0&&(j.providerSelection=S),j}function routingForModelSelection(e){return parseChatGptModelSelection(e)===void 0?{kind:`gateway`,target:e.split(`/`)[0]??``}:{kind:`external`,provider:`codex`}}async function authenticateChatGpt(e,t,n){let authenticate=()=>e.ensureChatGptAuth({signal:n});await(t===void 0?authenticate():t(authenticate))}function hasModelSettingsChanges(e){return e.model.kind!==`keep`||e.reasoning.kind!==`keep`||e.gatewayServiceTier.kind!==`keep`}async function readCurrentAgentModel(e){try{let{compiledState:t}=await inspectApplication(e),n=t?.manifest.config,r=n?.model,i=isChatGptModelRouting(r?.routing);return{id:i&&r!==void 0?`chatgpt/${r.id}`:r?.id??null,routing:r?.routing??null,reasoning:n?.reasoning??null,serviceTier:readGatewayServiceTier(r?.providerOptions),editable:r!==void 0&&(r.source===void 0||i),settingsEditable:n?.source!==void 0}}catch{return{id:null,routing:null,reasoning:null,serviceTier:{kind:`standard`},editable:!1,settingsEditable:!1}}}async function modelChangeRefusalForUneditableModel(e){let{editable:t,routing:n}=await readCurrentAgentModel(e);return t?null:`Model is set via ${n?.kind===`external`?`the external provider \`${n.provider}\``:`an SDK model call`} in agent.ts, not a string literal; /model can't rewrite it. Edit \`model\` in agent.ts.`}export{MODEL_MENU_MESSAGE,modelChangeRefusalForUneditableModel,runModelFlow};
1
+ import{AI_GATEWAY_API_KEY_ENV_VAR}from"../ai-gateway-api-key.js";import{withSpinner}from"../with-spinner.js";import{gatewayModelCapabilities}from"../boxes/model-capabilities.js";import{fetchGatewayCatalog,modelOptionsFromCatalog}from"../boxes/select-model.js";import{ensureChatGptAuth}from"./chatgpt-auth.js";import{WizardCancelledError}from"../step.js";import{changeAgentModelSettings,formatApplyModelSettingsOutcome}from"./model-source-change.js";import{runProviderFlow}from"./provider.js";import pc from"#compiled/picocolors/index.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";import{inspectApplication}from"#services/inspect-application.js";import{readProviderSelection,resolveAvailableProviders,writeProviderSelection}from"#setup/provider-settings.js";import{formatModelSummary}from"#shared/model-summary.js";import{readGatewayServiceTier}from"#shared/gateway-service-tier.js";import{DEFAULT_CHATGPT_MODEL_SELECTION,isChatGptModelRouting,parseChatGptModelSelection}from"#shared/chatgpt-model.js";const MODEL_MENU_MESSAGE=``;function providerSelectionHint(e,t){return e===`chatgpt`?t===void 0?`ChatGPT subscription`:`ChatGPT subscription (${t})`:e===`ai-gateway-project`?`AI Gateway via Project`:`AI Gateway via ${AI_GATEWAY_API_KEY_ENV_VAR}`}function modelListRows(e){return modelOptionsFromCatalog(e).map(e=>{let t={value:e.value,label:e.value};return e.featured===!0&&(t.featured=!0),t})}function formatModelDraftHint(e,t,n){let r={model:e};return t!==null&&(r.reasoning=t),n.kind===`priority`&&(r.fastGlyph=`↯`),formatModelSummary(r)}function modelMenuRows(e,t,n,r,i,a,o,s,c){let l;s||c?(l={value:`model`,label:`Change model`,description:s?`The model, its reasoning effort, and the Gateway service tier`:`Reasoning and service tier; the model itself is an SDK model call in agent.ts`},e!==null&&(l.hint=formatModelDraftHint(e,t,n))):l={value:`model`,label:`Change model`,disabled:!0,description:`Set via an SDK model call in agent.ts; edit the source to change it`};let u;return u=o?.kind===`external`&&!isChatGptModelRouting(o)?{disabled:!0,value:`provider`,label:`Change provider`,description:`Disabled in external endpoint mode`}:i?{value:`provider`,label:`Change provider`,hint:providerSelectionHint(r,a),description:`How your agent reaches the model provider`}:{value:`provider`,label:pc.bold(`Configure model access`),hint:pc.yellow(`Not configured`),description:`How your agent reaches the model provider`,accent:`warning`},[l,u,{value:`done`,label:`Done`}]}async function runModelFlow(e){let{appRoot:t,prompter:n,signal:r}=e,i=e.environmentRoot??t,a={readCurrentModel:readCurrentAgentModel,applySettings:changeAgentModelSettings,resolveAvailableProviders,readProviderSelection,runProviderFlow,ensureChatGptAuth,writeProviderSelection,...e.deps},o=a.selectModel?.fetchModels??fetchGatewayCatalog,[s,c,l,u]=await withSpinner(n,`Checking the project…`,()=>Promise.all([a.readCurrentModel(t),a.resolveAvailableProviders(i,r===void 0?{env:process.env}:{signal:r,env:process.env}),a.readProviderSelection(i),o(r).catch(()=>void 0)]));r?.throwIfAborted();let{id:d,routing:f,serviceTier:p,editable:m,settingsEditable:h}=s,g=s.reasoning===`provider-default`?null:s.reasoning,_=l??(c.includes(`ai-gateway-key`)?`ai-gateway-key`:`ai-gateway-project`),v=c.includes(_),y,b={model:{kind:`keep`},reasoning:{kind:`keep`},gatewayServiceTier:{kind:`keep`}},x,S,C=!1,w=!1,T=!1,E=f?.kind===`external`&&!isChatGptModelRouting(f),D=E?{tone:`warning`,text:"`agent.ts` specifies the model provider directly. Model, provider, and service-tier changes stay source-owned; reasoning remains configurable here."}:void 0,O=!v&&f?.kind!==`external`?`provider`:m||h?`model`:`provider`,k=f?.kind!==`external`&&(e.initialStep===`provider`||!v);for(;;){let t;if(k)k=!1,t=`provider`;else try{t=await n.select({message:``,options:modelMenuRows(d,g,isChatGptModelRouting(f)?{kind:`standard`}:p,_,v,e.chatGptAccountLabel,f,m,h),hintLayout:`stacked`,initialValue:O,notices:D===void 0?[]:[D]})}catch(e){if(!(e instanceof WizardCancelledError))throw e;if(hasModelSettingsChanges(b))return{kind:`cancelled`,discardedDraft:!0};break}if(t===`done`){w=!0,T=!0;break}if(t===`model`){e.onScreen?.(`model_settings`);let t=a.pickModelSettings;if(t===void 0)throw Error(`runModelFlow requires a pickModelSettings dep to open the model screen.`);let n=await t({model:m?{kind:`pick`,options:modelListRows(u),current:d}:{kind:`fixed`,current:d,reason:`Set via an SDK model call in agent.ts; edit the source to change it`},reasoning:g,serviceTier:isChatGptModelRouting(f)?{kind:`standard`}:p,settingsEditable:h,externalRouting:E,capabilitiesFor:e=>gatewayModelCapabilities(u,e)});if(r?.throwIfAborted(),n===void 0){O=`model`;continue}n.model!==void 0&&(d=n.model,f=routingForModelSelection(n.model),b.model={kind:`set`,value:n.model}),n.reasoning!==void 0&&(g=n.reasoning==="default"?null:n.reasoning,b.reasoning=g===null?{kind:`remove`}:{kind:`set`,value:g}),n.serviceTier!==void 0&&!isChatGptModelRouting(f)&&(p=n.serviceTier===`priority`?{kind:`priority`}:{kind:`standard`},b.gatewayServiceTier=n.serviceTier===`priority`?{kind:`set`,value:`priority`}:{kind:`remove`}),O=`done`;continue}e.onScreen?.(`model_provider`);let o=await a.runProviderFlow({appRoot:i,prompter:n,signal:r,availableProviders:c,selectedProvider:_});if(o.kind===`cancelled`){if(r?.aborted)return{kind:`cancelled`};O=`provider`;continue}if(o.kind===`external-provider`){if(r?.aborted)return{kind:`cancelled`};O=`done`;continue}y=o.kind,y===`chatgpt`?(C=!0,isChatGptModelRouting(f)||(b.model={kind:`set`,value:DEFAULT_CHATGPT_MODEL_SELECTION},b.gatewayServiceTier={kind:`remove`})):isChatGptModelRouting(f)&&(b.model={kind:`set`,value:DEFAULT_AGENT_MODEL_ID}),T=!0;break}let A=b.model.kind===`set`&&parseChatGptModelSelection(b.model.value)!==void 0;if(T&&A&&(b.gatewayServiceTier={kind:`remove`},C=!0),T&&C&&await authenticateChatGpt(a,n,r),T&&hasModelSettingsChanges(b)&&(x=await a.applySettings({appRoot:t,patch:b})),T&&y!==void 0&&x?.kind!==`rejected`&&(await a.writeProviderSelection(i,y),S=y),x!==void 0&&S===void 0&&r?.throwIfAborted(),x===void 0&&S===void 0&&!C)return w?{kind:`done`,accessChanged:!1}:{kind:`cancelled`};let j={kind:`done`,accessChanged:x?.kind===`changed`||S!==void 0||C};return x===void 0?C&&(j.modelMessage=`ChatGPT login ready.`):j.modelMessage=formatApplyModelSettingsOutcome(x),S!==void 0&&(j.providerSelection=S),j}function routingForModelSelection(e){return parseChatGptModelSelection(e)===void 0?{kind:`gateway`,target:e.split(`/`)[0]??``}:{kind:`external`,provider:`codex`}}async function authenticateChatGpt(e,t,n){let r=t.log.spinner?.(`Waiting for ChatGPT sign-in in your browser…`,{kind:`external-action`,emphasis:`browser`});try{await e.ensureChatGptAuth({signal:n,log:e=>t.log.info(e)})}finally{r?.stop()}}function hasModelSettingsChanges(e){return e.model.kind!==`keep`||e.reasoning.kind!==`keep`||e.gatewayServiceTier.kind!==`keep`}async function readCurrentAgentModel(e){try{let{compiledState:t}=await inspectApplication(e),n=t?.manifest.config,r=n?.model,i=isChatGptModelRouting(r?.routing);return{id:i&&r!==void 0?`chatgpt/${r.id}`:r?.id??null,routing:r?.routing??null,reasoning:n?.reasoning??null,serviceTier:readGatewayServiceTier(r?.providerOptions),editable:r!==void 0&&(r.source===void 0||i),settingsEditable:n?.source!==void 0}}catch{return{id:null,routing:null,reasoning:null,serviceTier:{kind:`standard`},editable:!1,settingsEditable:!1}}}async function modelChangeRefusalForUneditableModel(e){let{editable:t,routing:n}=await readCurrentAgentModel(e);return t?null:`Model is set via ${n?.kind===`external`?`the external provider \`${n.provider}\``:`an SDK model call`} in agent.ts, not a string literal; /model can't rewrite it. Edit \`model\` in agent.ts.`}export{MODEL_MENU_MESSAGE,modelChangeRefusalForUneditableModel,runModelFlow};
@@ -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.2`,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
 
@@ -154,6 +154,15 @@ Every memory span includes `gen_ai.operation.name` and `gen_ai.memory.store.id`.
154
154
 
155
155
  `gen_ai.memory.records` contains recalled record content only when `recordInputs` is enabled. eve classifies recalled records as input content because they become part of the model context. eve does not set `gen_ai.memory.query.text` because a memory provider receives structured conversation messages, not a standalone search-query string. The `agent.memory.slot` and `agent.memory.phase` attributes identify the eve slot and lifecycle boundary without adding either to the span name.
156
156
 
157
+ Messages in `gen_ai.input.messages` include a `kind` for user-role entries.
158
+ New human input uses `user`; framework-authored input uses namespaced kinds
159
+ such as `context.instruction` and `execution.background_task`. When resuming
160
+ history saved before eve 0.54, entries without a kind use `legacy.unknown`:
161
+ the old format did not reliably distinguish human input from framework input.
162
+ Their content and metadata remain unchanged, and already classified entries
163
+ retain their kind. Unknown legacy entries are not replayed as the latest human
164
+ request after compaction.
165
+
157
166
  ## Agent trace contract
158
167
 
159
168
  The provider layout and zero-config local tracing emit the following spans.
@@ -184,7 +193,14 @@ the failure outcome, error status, and error type. The initiating turn can
184
193
  finish or be cancelled while the action remains open. Ending the session closes
185
194
  an action whose task never reported a terminal result.
186
195
 
187
- 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`.
188
204
  Only activations use the `invoke_agent` operation. A workflow tool invocation
189
205
  that coordinates at least one nested agent uses `invoke_workflow`, with its
190
206
  path-derived tool name in `gen_ai.workflow.name`. Durable workflow tools without
@@ -198,8 +214,10 @@ A conversation remains durable state; `gen_ai.conversation.id` joins the activat
198
214
 
199
215
  Each activation owns a fresh trace identity, including local and remote
200
216
  subagents. The first child activation links to its caller with
201
- `eve.link.type=agent.dispatch`; incoming `traceparent` provides that link, not
202
- 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.
203
221
  Conversation baggage is independent of execution lineage and trace-policy
204
222
  ceilings, which remain in force across the boundary.
205
223
 
@@ -250,7 +268,8 @@ This workflow applies to schema v4 from the [instrumentation provider layout](./
250
268
  | Agent activations | `agent.trace.schema.version=4` and `gen_ai.operation.name=invoke_agent` |
251
269
  | One logical conversation | `gen_ai.conversation.id=<conversation ID>` |
252
270
  | One turn | Both `gen_ai.conversation.id` and `agent.turn.id` |
253
- | 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>` |
254
273
  | Delegated dispatches | `agent.invocation.role=caller` |
255
274
 
256
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.
@@ -279,7 +298,7 @@ invoke_agent support session=S, turn=turn_1, conversation=S
279
298
 
280
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.
281
300
 
282
- `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.
283
302
 
284
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.
285
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,22 +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 this session in `~/.eve/auth/chatgpt.json` with owner-only file permissions on Unix. It is separate from any Codex login and is never written to your project. Keep this file private. To remove the local eve login, stop your eve processes and delete the file. Existing Codex users must sign in once through eve after upgrading.
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
- 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.
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.
200
+
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.
202
+
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.
198
204
 
199
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.
200
206
 
201
207
  Troubleshooting:
202
208
 
203
- - **`chatgpt-sub login`**: open `/model` and select **Provider** → **ChatGPT subscription** to sign in again. The running dev session picks up the new login.
204
- - **`chatgpt-sub unavailable`**: check your network connection and retry from `/model`. If eve reports an invalid credential file, remove `~/.eve/auth/chatgpt.json` and sign in again.
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.
205
212
  - **Model rejected by the backend**: model availability depends on the signed-in ChatGPT account. Pick another supported OpenAI model.
206
213
  - **Device sign-in unavailable**: enable device code authorization in ChatGPT security settings, or sign in from a local terminal with port 1455 available.
207
214
 
@@ -67,6 +67,37 @@ export default defineAgent({
67
67
 
68
68
  A mounted extension can also contribute declared subagents from `extension/subagents/`. The mount namespace prefixes the subagent visible to the consuming agent node: mounting an extension as `crm` exposes its `reviewer` subagent as `crm__reviewer`. The contributed subagent keeps its own isolated tools, connections, skills, hooks, instructions, sandbox, and nested subagents, and its modules can read configuration from the extension handle. See [Extensions](./extensions#add-a-subagent) for the authoring and override behavior.
69
69
 
70
+ ### Vercel workspace peers
71
+
72
+ In a Vercel agent workspace, expose one other workspace member as a remote subagent with `defineWorkspaceAgent`. Create an ordinary file under the caller's `agent/subagents/` directory. Its filename gives the model-visible tool name; `name` identifies the peer under `agents/`.
73
+
74
+ ```ts title="agents/foreman/agent/subagents/research.ts"
75
+ import { defineWorkspaceAgent } from "eve";
76
+
77
+ export default defineWorkspaceAgent({
78
+ name: "research",
79
+ });
80
+ ```
81
+
82
+ The helper uses the peer's root `defineAgent({ description })` value as the model-visible tool description. Pass `description` to override it for this caller. When `transport` is omitted, eve selects the built-in transport for the runtime environment. Vercel deployments route through the current deployment and authenticate with the caller's Vercel OIDC token. Outside Vercel, provide an explicit transport with `url` and optional `auth` or `headers`:
83
+
84
+ ```ts title="agents/foreman/agent/subagents/research.ts"
85
+ import { defineWorkspaceAgent } from "eve";
86
+ import { bearer } from "eve/agents/auth";
87
+
88
+ export default defineWorkspaceAgent({
89
+ name: "research",
90
+ transport: {
91
+ url: () => process.env.RESEARCH_AGENT_URL!,
92
+ auth: bearer(() => process.env.RESEARCH_AGENT_TOKEN!),
93
+ },
94
+ });
95
+ ```
96
+
97
+ An explicit transport replaces the environment default completely. The receiving peer must still accept the transport's credentials through its channel authentication policy. Set `forwardPrincipal: true` only when the peer trusts the caller to forward user identity, as described in [Remote agents](./guides/remote-agents#forward-the-callers-identity).
98
+
99
+ Use the peer's directory name under `agents/`. eve requires an exact workspace-member match, so add another declared subagent file for each additional peer. `eve dev` does not provide local workspace routing; configure an explicit transport to target a separately running peer.
100
+
70
101
  ### Conditional availability
71
102
 
72
103
  To expose a declared subagent only for certain sessions or turns, export