eve 0.54.2 → 0.54.3
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.
- package/CHANGELOG.md +9 -0
- package/dist/src/cli/dev/tui/setup-commands.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +3 -1
- package/dist/src/compiled/just-secrets/LICENSE +21 -0
- package/dist/src/compiled/just-secrets/index.d.ts +20 -0
- package/dist/src/compiled/just-secrets/index.js +2 -0
- package/dist/src/compiled/just-secrets/windows.ps1 +138 -0
- package/dist/src/compiler/extension-compatibility.d.ts +6 -6
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/normalize-manifest-helpers.d.ts +2 -1
- package/dist/src/compiler/normalize-manifest-helpers.js +1 -1
- package/dist/src/compiler/normalize-manifest.js +1 -1
- package/dist/src/compiler/resolve-workspace-subagent.d.ts +13 -0
- package/dist/src/compiler/resolve-workspace-subagent.js +1 -0
- package/dist/src/execution/durable-session-migrations/snapshot.d.ts +0 -16
- package/dist/src/execution/durable-session-migrations/snapshot.js +1 -1
- package/dist/src/execution/tools/sleep-workflow.js +1 -1
- package/dist/src/harness/compaction.js +1 -1
- package/dist/src/harness/messages.d.ts +1 -1
- package/dist/src/harness/messages.js +1 -1
- package/dist/src/harness/step-hooks.d.ts +16 -10
- package/dist/src/harness/step-hooks.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/nitro/routes/index.d.ts +6 -0
- package/dist/src/internal/nitro/routes/index.js +7 -7
- package/dist/src/internal/vercel/assemble-eve-services.js +1 -1
- package/dist/src/internal/vercel/build-agent-workspace.js +1 -1
- package/dist/src/internal/vercel/build-multi-agent-landing-page.d.ts +3 -0
- package/dist/src/internal/vercel/build-multi-agent-landing-page.js +1 -0
- package/dist/src/internal/vercel/eve-service-contribution.d.ts +4 -0
- package/dist/src/internal/vercel/eve-service-contribution.js +1 -1
- package/dist/src/public/definitions/workspace-agent.d.ts +25 -0
- package/dist/src/public/definitions/workspace-agent.js +1 -0
- package/dist/src/public/index.d.ts +1 -0
- package/dist/src/public/index.js +1 -1
- package/dist/src/public/models/openai/chatgpt/credential-store.d.ts +22 -4
- package/dist/src/public/models/openai/chatgpt/credential-store.js +1 -1
- package/dist/src/public/models/openai/chatgpt/oauth.d.ts +6 -4
- package/dist/src/public/models/openai/chatgpt/token-broker.js +1 -1
- package/dist/src/setup/flows/chatgpt-auth.js +1 -1
- package/dist/src/setup/flows/model.d.ts +0 -2
- package/dist/src/setup/flows/model.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/docs/guides/instrumentation.md +9 -0
- package/docs/reference/typescript-api.md +7 -3
- package/docs/subagents/index.mdx +31 -0
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{getDefaultChatGptCredentialStore}from"./credential-store.js";import{CHATGPT_LOGIN_HINT,ChatGptSignInRequiredError,requestChatGptTokens}from"./oauth.js";function createCodexTokenBroker(e={}){let t=e.store??getDefaultChatGptCredentialStore(),n=e.now??Date.now,r={kind:`checking`},i,a;return{getToken(e){return getToken(e.reason)},async refreshState(){i=void 0;try{await getToken(`request`)}catch{}return r},state(){return r}};function getToken(e){let t=e===`rejected`;if(!t&&i!==void 0&&isFresh(i,n()))return Promise.resolve(i);if(a!==void 0&&(!t||a.forced))return a.promise;let r=a?.promise,o=(r===void 0?resolveToken(t):r.catch(()=>void 0).then(()=>resolveToken(t))).finally(()=>{a?.promise===o&&(a=void 0)});return a={forced:t,promise:o},o}async function resolveToken(a){try{let o=await t.read();if(!o)throw i=void 0,a?new ChatGptSignInRequiredError:(r={kind:`signed-out`},Error(`ChatGPT subscription is not signed in. ${CHATGPT_LOGIN_HINT}`));let s=tokenFrom(o)?.token;(a||!isFresh(tokenFrom(o),n()))&&(o=await t.update(async t=>{if(!t)throw new ChatGptSignInRequiredError;return`accessToken`in t&&isFresh(tokenFrom(t),n())&&(!a||tokenFrom(t)?.token!==s)?t:requestChatGptTokens({grant_type:`refresh_token`,refresh_token:t.refreshToken},{fetch:e.fetch,previous:t,now:n})}));let c=tokenFrom(o);if(!c)throw Error(`ChatGPT access token is unavailable. ${CHATGPT_LOGIN_HINT}`);return i=c,r=readyState(c),c}catch(e){throw i=void 0,e instanceof ChatGptSignInRequiredError?r={kind:`reauth-required`}:r.kind!==`signed-out`&&(r={kind:`unavailable`,reason:e instanceof Error?e.message:String(e)}),e}}}let defaultBroker;function getDefaultCodexTokenBroker(){return defaultBroker??=createCodexTokenBroker(),defaultBroker}function tokenFrom(e){if(`accessToken`in e)return{token:e.accessToken,expiresAt:e.expiresAt,...e.accountId&&{accountId:e.accountId},...e.accountLabel&&{accountLabel:e.accountLabel}}}function readyState(e){return{kind:`ready`,...e.accountLabel!==void 0&&{accountLabel:e.accountLabel}}}function isFresh(e,t){return e!==void 0&&(e.expiresAt===void 0||e.expiresAt-3e5>t)}export{createCodexTokenBroker,getDefaultCodexTokenBroker};
|
|
@@ -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{
|
|
1
|
+
import{createHash,randomBytes}from"node:crypto";import{createServer}from"node:http";import{WizardCancelledError}from"#setup/step.js";import{isErrnoCode,isObject}from"#shared/guards.js";import{setTimeout as setTimeout$1}from"node:timers/promises";import{getDefaultCodexTokenBroker}from"#public/models/openai/chatgpt/token-broker.js";import{ChatGptInvalidStoredSessionError,getDefaultChatGptCredentialStore}from"#public/models/openai/chatgpt/credential-store.js";import{CHATGPT_CLIENT_ID,CHATGPT_ISSUER,readChatGptAuthResponse,requestChatGptTokens}from"#public/models/openai/chatgpt/oauth.js";import{openUrl}from"#setup/primitives/open-url.js";const REDIRECT_URI=`http://localhost:1455/auth/callback`;async function ensureChatGptAuth(e={}){let t=e.broker??getDefaultCodexTokenBroker(),n=e.store??getDefaultChatGptCredentialStore();if(e.signal?.throwIfAborted(),(await t.refreshState()).kind===`ready`)return;try{await n.read()}catch(e){if(!(e instanceof ChatGptInvalidStoredSessionError))throw e}let r=new AbortController,cancel=()=>r.abort(new WizardCancelledError);process.once(`SIGINT`,cancel);let i=setTimeout(()=>r.abort(Error(`ChatGPT sign-in timed out. Retry from /model.`)),3e5),a=AbortSignal.any([r.signal,...e.signal?[e.signal]:[]]),o=e.log??(e=>process.stdout.write(`${e}\n`)),s=e.open??openUrl;try{let r=e.headless??!!(process.env.SSH_CONNECTION||process.env.SSH_TTY)?await deviceLogin({...e,signal:a,log:o,open:s}):await browserLogin({...e,signal:a,log:o,open:s});if(a.throwIfAborted(),await n.update(async()=>(a.throwIfAborted(),r),{replace:!0}),(await t.refreshState()).kind!==`ready`)throw Error(`ChatGPT sign-in could not be verified. Retry from /model.`);o(`ChatGPT subscription connected.`)}catch(e){throw a.throwIfAborted(),e}finally{clearTimeout(i),process.removeListener(`SIGINT`,cancel)}}async function browserLogin(e){let t=randomBytes(32).toString(`base64url`),n=randomBytes(32).toString(`base64url`),r=new URL(`${CHATGPT_ISSUER}/oauth/authorize`);r.search=new URLSearchParams({response_type:`code`,client_id:CHATGPT_CLIENT_ID,redirect_uri:REDIRECT_URI,scope:`openid profile email offline_access`,code_challenge:createHash(`sha256`).update(t).digest(`base64url`),code_challenge_method:`S256`,id_token_add_organizations:`true`,codex_cli_simplified_flow:`true`,state:n,originator:`eve`}).toString();let i=Promise.withResolvers();i.promise.catch(()=>{});let a=createServer({requestTimeout:1e4,headersTimeout:1e4,maxHeaderSize:8192},(e,t)=>{let r=URL.parse(e.url??``,REDIRECT_URI);if(t.setHeader(`content-type`,`text/plain; charset=utf-8`),t.setHeader(`cache-control`,`no-store`),e.method!==`GET`||r?.pathname!==`/auth/callback`){t.writeHead(404).end(`Not found.`);return}if(r.searchParams.get(`state`)!==n){t.writeHead(400).end(`This sign-in belongs to another attempt. Return to eve and use its sign-in link.`);return}if(r.searchParams.has(`error`)){t.writeHead(400).end(`ChatGPT sign-in was declined. Return to eve to retry.`),i.reject(Error(`ChatGPT sign-in was declined. Retry from /model.`));return}let a=r.searchParams.get(`code`);if(!a){t.writeHead(400).end(`Missing authorization code.`);return}t.end(`Authorization received. Return to eve to finish connecting your ChatGPT subscription.`),i.resolve(a)});a.maxConnections=10;let abort=()=>i.reject(e.signal.reason);e.signal.addEventListener(`abort`,abort,{once:!0});try{e.signal.throwIfAborted();try{await new Promise((e,t)=>{a.once(`error`,t),a.listen(1455,`127.0.0.1`,e)})}catch(t){if(!isErrnoCode(t,`EADDRINUSE`))throw Error(`Could not start ChatGPT sign-in on localhost:1455. Free the port and retry from /model.`);return e.log(`Local sign-in port is in use. Continuing with a device code.`),await deviceLogin(e)}e.signal.throwIfAborted(),e.log(`Sign in to ChatGPT in your browser:\n${r.href}\nWaiting for sign-in. Press Ctrl+C to cancel.`),e.open(r.href);let n=await i.promise;return await requestChatGptTokens({grant_type:`authorization_code`,code:n,code_verifier:t,redirect_uri:REDIRECT_URI},e)}finally{e.signal.removeEventListener(`abort`,abort),a.closeAllConnections(),await new Promise(e=>a.close(()=>e()))}}async function deviceLogin(e){let t=await deviceRequest(`usercode`,{client_id:CHATGPT_CLIENT_ID},e);if(!t.ok)throw Error(`ChatGPT device sign-in is unavailable (HTTP ${t.status}). Enable device code authorization in ChatGPT Settings > Security, then retry from /model.`);let n=await readChatGptAuthResponse(t);if(!isObject(n)||typeof n.device_auth_id!=`string`||!n.device_auth_id||typeof n.user_code!=`string`||!/^[A-Z0-9-]{4,32}$/iu.test(n.user_code))throw Error(`ChatGPT returned an invalid device code. Retry from /model.`);let r=Math.min(30,Math.max(1,Number(n.interval)||5))*1e3,i=`${CHATGPT_ISSUER}/codex/device`;for(e.log(`Open ${i} and enter code: ${n.user_code}\nIf prompted, enable device code authorization in ChatGPT Settings > Security.\nWaiting for sign-in. Press Ctrl+C to cancel.`),e.open(i);;){await setTimeout$1(r+1e3,void 0,{signal:e.signal});let t=await deviceRequest(`token`,{device_auth_id:n.device_auth_id,user_code:n.user_code},e);if(t.status===403||t.status===404)continue;if(!t.ok)throw Error(`ChatGPT device sign-in failed (HTTP ${t.status}). Retry from /model.`);let i=await readChatGptAuthResponse(t);if(!isObject(i)||typeof i.authorization_code!=`string`||!i.authorization_code||typeof i.code_verifier!=`string`||!i.code_verifier)throw Error(`ChatGPT returned an invalid device authorization. Retry from /model.`);return requestChatGptTokens({grant_type:`authorization_code`,code:i.authorization_code,code_verifier:i.code_verifier,redirect_uri:`${CHATGPT_ISSUER}/deviceauth/callback`},e)}}async function deviceRequest(e,t,n){try{return await(n.fetch??fetch)(`${CHATGPT_ISSUER}/api/accounts/deviceauth/${e}`,{method:`POST`,headers:{"content-type":`application/json`,"user-agent":`eve`},body:JSON.stringify(t),redirect:`error`,signal:AbortSignal.any([n.signal,AbortSignal.timeout(3e4)])})}catch{throw n.signal.throwIfAborted(),Error(`Could not reach ChatGPT device sign-in. Check your connection and retry from /model.`)}}export{ensureChatGptAuth};
|
|
@@ -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,
|
|
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.
|
|
1
|
+
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.93`,DEFAULT_CONNECT_PACKAGE_VERSION=`1.0.0`,DEFAULT_ZOD_PACKAGE_VERSION=`4.5.4`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.54.3`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e,t){return{"agent/agent.ts":renderAgentTemplate(e,t),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderAgentTemplate(e,t){let n=parseChatGptModelSelection(e);return n===void 0?BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t)):`import { defineAgent } from "eve";\nimport { chatgpt } from "eve/models/openai";\n\nexport default defineAgent({\n model: chatgpt(${JSON.stringify(n)}),\n${reasoningTemplateLine(t)}});\n`}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,t){return e===BASE_AGENT_TEMPLATE&&parseChatGptModelSelection(t.model)!==void 0?renderAgentTemplate(t.model,t.reasoning):e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t.reasoning)).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
|
|
2
2
|
|
|
3
3
|
export default defineAgent({
|
|
4
4
|
model: "__EVE_INIT_MODEL__",
|
|
@@ -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.
|
|
@@ -192,16 +192,20 @@ Sign in directly from eve; the Codex CLI is not required:
|
|
|
192
192
|
2. Complete sign-in in the browser. If the browser does not open, use the URL printed in the terminal.
|
|
193
193
|
3. Return to eve after the terminal confirms that your subscription is connected. Normal token expiry is refreshed automatically.
|
|
194
194
|
|
|
195
|
-
eve stores
|
|
195
|
+
eve stores your refresh token and account details in your operating system's credential store through [just-secrets](https://github.com/vercel-labs/just-secrets): the login Keychain on macOS, Credential Manager on Windows, or Secret Service on Linux. Access tokens stay in process memory; a new eve process refreshes the saved session when it first needs a token. The login is separate from Codex and is never written to your project.
|
|
196
196
|
|
|
197
|
-
|
|
197
|
+
If you previously signed in through Codex or used eve's `~/.eve/auth/chatgpt.json` file, sign in once through eve after upgrading. eve removes the old plaintext file after successfully saving the new session. It does not fall back to file storage if the OS credential store is unavailable.
|
|
198
|
+
|
|
199
|
+
Linux, including WSL, requires `/usr/bin/secret-tool` (commonly provided by `libsecret-tools`), a session D-Bus, and an unlocked Secret Service keyring. On macOS, unlock your login keychain and allow credential access if prompted. On Windows, PowerShell and Credential Manager must be available in your user session. OS credential storage protects secrets at rest; it does not guarantee isolation from malicious processes running as your OS user.
|
|
200
|
+
|
|
201
|
+
Over SSH, or if localhost port 1455 is occupied, eve shows a device code instead. Open the displayed link in a browser and enter the code. Device sign-in requires enabling device code authorization in **ChatGPT Settings → Security**, or having a workspace admin enable it in workspace permissions. Sign-in times out after five minutes; press **Ctrl+C** to cancel sooner. Device sign-in still requires an available OS credential store; use an API-key model in headless environments without one.
|
|
198
202
|
|
|
199
203
|
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
204
|
|
|
201
205
|
Troubleshooting:
|
|
202
206
|
|
|
203
207
|
- **`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
|
|
208
|
+
- **`chatgpt-sub unavailable`**: follow the reported OS credential-store recovery steps, or check your network connection if token refresh failed. Retry from `/model`. If eve reports an invalid stored session, sign in again to replace it.
|
|
205
209
|
- **Model rejected by the backend**: model availability depends on the signed-in ChatGPT account. Pick another supported OpenAI model.
|
|
206
210
|
- **Device sign-in unavailable**: enable device code authorization in ChatGPT security settings, or sign in from a local terminal with port 1455 available.
|
|
207
211
|
|
package/docs/subagents/index.mdx
CHANGED
|
@@ -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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eve",
|
|
3
|
-
"version": "0.54.
|
|
3
|
+
"version": "0.54.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
|
|
6
6
|
"keywords": [
|
|
@@ -493,6 +493,7 @@
|
|
|
493
493
|
"jose": "6.2.3",
|
|
494
494
|
"jsonc-parser": "3.3.1",
|
|
495
495
|
"just-bash": "3.1.0",
|
|
496
|
+
"just-secrets": "0.0.2",
|
|
496
497
|
"marked": "17.0.6",
|
|
497
498
|
"microsandbox": "0.5.5",
|
|
498
499
|
"next": "16.3.4",
|