eve 0.54.3 → 0.54.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/src/cli/commands/init-agent-workspace.js +1 -1
- package/dist/src/cli/commands/init-project.d.ts +46 -0
- package/dist/src/cli/commands/init-project.js +1 -0
- package/dist/src/cli/commands/init-self-modification.d.ts +7 -0
- package/dist/src/cli/commands/init-self-modification.js +1 -0
- package/dist/src/cli/commands/init-target.js +2 -2
- package/dist/src/cli/commands/init-telemetry.d.ts +6 -0
- package/dist/src/cli/commands/init-telemetry.js +1 -0
- package/dist/src/cli/commands/init.d.ts +3 -0
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/telemetry/index.d.ts +1 -1
- package/dist/src/compiled/.vendor-stamp.json +6 -6
- package/dist/src/compiled/@ai-sdk/anthropic/index.js +2 -2
- package/dist/src/compiled/@ai-sdk/google/index.js +7 -7
- package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
- package/dist/src/compiled/@ai-sdk/openai/index.js +4 -4
- package/dist/src/compiled/@opentelemetry/api/index.d.ts +2 -0
- package/dist/src/compiled/@workflow/core/events-consumer.d.ts +26 -0
- package/dist/src/compiled/@workflow/core/flushable-stream.d.ts +41 -0
- package/dist/src/compiled/@workflow/core/index.js +2 -2
- package/dist/src/compiled/@workflow/core/replay-divergence.d.ts +25 -0
- package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +75 -1
- package/dist/src/compiled/@workflow/core/runtime/quickjs-entrypoint.d.ts +30 -8
- package/dist/src/compiled/@workflow/core/runtime/quickjs-log-view.d.ts +129 -0
- package/dist/src/compiled/@workflow/core/runtime/step-executor.d.ts +2 -21
- package/dist/src/compiled/@workflow/core/runtime/suspension-handler.d.ts +0 -22
- package/dist/src/compiled/@workflow/core/runtime.js +3 -3
- package/dist/src/compiled/@workflow/core/serialization.d.ts +2 -2
- package/dist/src/compiled/@workflow/core/step/context-storage.d.ts +2 -0
- package/dist/src/compiled/@workflow/core/telemetry/semantic-conventions.d.ts +36 -0
- package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/workflow.js +1 -1
- package/dist/src/compiled/@workflow/world/analytics.d.ts +23 -23
- package/dist/src/compiled/@workflow/world/events.d.ts +4 -2
- package/dist/src/compiled/@workflow/world/queue.d.ts +84 -0
- package/dist/src/compiled/@workflow/world-local/index.js +5 -5
- package/dist/src/compiled/@workflow/world-vercel/index.js +18 -13
- package/dist/src/compiled/_chunks/workflow/attribute-changes-BAcgmlXp.js +20 -0
- package/dist/src/compiled/_chunks/workflow/coerce-ro2dOxbr.js +1 -0
- package/dist/src/compiled/_chunks/workflow/dist-KPieTJHT.js +25 -0
- package/dist/src/compiled/_chunks/workflow/dist-PLkAQ-U7.js +2 -0
- package/dist/src/compiled/_chunks/workflow/frames-BvATzM2t.js +3 -0
- package/dist/src/compiled/_chunks/workflow/{functions-C02-JHBK.js → functions-wMCGZAVk.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/resume-hook-BEHe0Uut.js +1 -0
- package/dist/src/compiled/_chunks/workflow/run-ChHLjaCt.js +1 -0
- package/dist/src/compiled/_chunks/workflow/schemas-DR7NTzNe.js +50 -0
- package/dist/src/compiled/_chunks/workflow/sleep-BB2HuVie.js +1 -0
- package/dist/src/compiled/_chunks/workflow/{wrapper-BxECO5nh.js → wrapper-CKui_eTd.js} +2 -2
- package/dist/src/compiled/_chunks/workflow/ws-transport-CVezyWwZ.js +1 -0
- package/dist/src/compiler/extension-compatibility.d.ts +10 -10
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/context/dynamic-model-lifecycle.d.ts +0 -6
- package/dist/src/context/dynamic-model-lifecycle.js +1 -1
- package/dist/src/context/dynamic-resolve-context.js +1 -1
- package/dist/src/context/effective-model.d.ts +5 -0
- package/dist/src/context/effective-model.js +1 -0
- package/dist/src/context/keys.d.ts +2 -0
- package/dist/src/context/keys.js +1 -1
- package/dist/src/dynamic/definition.d.ts +4 -0
- package/dist/src/eve-channel/index.js +1 -1
- package/dist/src/eve-channel/types.d.ts +9 -7
- package/dist/src/execution/eve-workflow-attributes.d.ts +1 -1
- package/dist/src/execution/run-session-limits.js +1 -1
- package/dist/src/execution/session.js +1 -1
- package/dist/src/execution/tools/sleep-workflow.js +1 -1
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/tool-loop.js +2 -2
- package/dist/src/instrumentation/parent-lineage.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/vercel/build-agent-workspace.js +1 -1
- package/dist/src/internal/vercel/vercel-services-config.js +1 -1
- package/dist/src/protocol/baggage.d.ts +6 -0
- package/dist/src/protocol/baggage.js +1 -1
- package/dist/src/protocol/traceparent.d.ts +13 -0
- package/dist/src/protocol/traceparent.js +1 -1
- package/dist/src/public/models/openai/chatgpt/codex-app-server.d.ts +41 -0
- package/dist/src/public/models/openai/chatgpt/codex-app-server.js +1 -0
- package/dist/src/public/models/openai/chatgpt/credential-store.d.ts +5 -1
- package/dist/src/public/models/openai/chatgpt/credential-store.js +1 -1
- package/dist/src/public/models/openai/chatgpt/token-broker.d.ts +7 -7
- package/dist/src/public/models/openai/chatgpt/token-broker.js +1 -1
- package/dist/src/public/models/openai/chatgpt/token.d.ts +13 -0
- package/dist/src/public/models/openai/chatgpt/token.js +1 -0
- package/dist/src/public/models/openai/chatgpt/transport.d.ts +2 -1
- package/dist/src/public/models/openai/index.d.ts +3 -2
- package/dist/src/public/vercel/index.d.ts +50 -0
- package/dist/src/public/vercel/index.js +1 -0
- package/dist/src/self-modification/setup.js +7 -2
- package/dist/src/setup/flows/chatgpt-auth.d.ts +2 -1
- package/dist/src/setup/flows/chatgpt-auth.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/subagents/remote-dispatch.d.ts +3 -1
- package/dist/src/subagents/remote-dispatch.js +1 -1
- package/dist/src/tracing/agent-otel-attributes.js +1 -1
- package/dist/src/tracing/agent-otel-runtime-context.js +1 -1
- package/docs/agent-config.md +3 -3
- package/docs/guides/deployment/vercel.mdx +52 -1
- package/docs/guides/dynamic-capabilities.md +19 -7
- package/docs/guides/instrumentation-providers.md +1 -1
- package/docs/guides/instrumentation.md +16 -6
- package/docs/guides/remote-agents.md +5 -5
- package/docs/reference/cli.md +2 -2
- package/docs/reference/telemetry.md +1 -1
- package/docs/reference/typescript-api.md +11 -8
- package/package.json +12 -6
- package/dist/src/compiled/_chunks/workflow/attribute-changes-C6H-fRVP.js +0 -20
- package/dist/src/compiled/_chunks/workflow/dist-DDeH-1ER.js +0 -40
- package/dist/src/compiled/_chunks/workflow/dist-DhncQSl7.js +0 -74
- package/dist/src/compiled/_chunks/workflow/frames-DsEqSDes.js +0 -3
- package/dist/src/compiled/_chunks/workflow/resume-hook-BRDLAb67.js +0 -1
- package/dist/src/compiled/_chunks/workflow/run-BM2OFphk.js +0 -1
- package/dist/src/compiled/_chunks/workflow/sleep-6cG0F99-.js +0 -1
- package/dist/src/compiled/_chunks/workflow/ws-transport-DuK82LLz.js +0 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** A route accepted by eve's Vercel configuration composer. */
|
|
2
|
+
export interface EveVercelRouteConfig {
|
|
3
|
+
readonly destination?: string | {
|
|
4
|
+
readonly service?: string;
|
|
5
|
+
readonly type?: string;
|
|
6
|
+
};
|
|
7
|
+
readonly handle?: string;
|
|
8
|
+
readonly src?: string;
|
|
9
|
+
readonly transforms?: readonly Record<string, unknown>[];
|
|
10
|
+
readonly [key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
/** A service accepted by eve's Vercel configuration composer. */
|
|
13
|
+
export interface EveVercelServiceConfig {
|
|
14
|
+
readonly buildCommand?: string;
|
|
15
|
+
readonly entrypoint?: string;
|
|
16
|
+
readonly framework?: string;
|
|
17
|
+
readonly mount?: string | {
|
|
18
|
+
readonly path?: string;
|
|
19
|
+
readonly subdomain?: string;
|
|
20
|
+
};
|
|
21
|
+
readonly routes?: readonly EveVercelRouteConfig[];
|
|
22
|
+
readonly root?: string;
|
|
23
|
+
readonly type?: string;
|
|
24
|
+
readonly [key: string]: unknown;
|
|
25
|
+
}
|
|
26
|
+
/** The portion of a programmatic Vercel configuration composed by eve. */
|
|
27
|
+
export interface EveVercelConfig {
|
|
28
|
+
readonly experimentalServices?: unknown;
|
|
29
|
+
readonly experimentalServicesV2?: unknown;
|
|
30
|
+
readonly routes?: readonly EveVercelRouteConfig[];
|
|
31
|
+
readonly services?: Readonly<Record<string, EveVercelServiceConfig>> | readonly (EveVercelServiceConfig & {
|
|
32
|
+
readonly name: string;
|
|
33
|
+
})[];
|
|
34
|
+
readonly [key: string]: unknown;
|
|
35
|
+
}
|
|
36
|
+
/** Options for composing an eve workspace into a programmatic Vercel configuration. */
|
|
37
|
+
export interface WithEveOptions {
|
|
38
|
+
/** Eve workspace root. Defaults to the directory evaluating `vercel.ts`. */
|
|
39
|
+
readonly root?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Add a hostless eve workspace's generated agent services and transport routes to `vercel.ts`.
|
|
43
|
+
*
|
|
44
|
+
* The returned object is a plain Vercel configuration. Vercel resolves it before independently
|
|
45
|
+
* building the authored services and each generated eve agent service.
|
|
46
|
+
*/
|
|
47
|
+
export declare function withEve<TConfig extends EveVercelConfig>(config: TConfig, options?: WithEveOptions): Promise<Omit<TConfig, "routes" | "services"> & {
|
|
48
|
+
readonly routes: readonly EveVercelRouteConfig[];
|
|
49
|
+
readonly services: Readonly<Record<string, EveVercelServiceConfig>>;
|
|
50
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{mkdir}from"node:fs/promises";import{join,resolve}from"node:path";import{resolveEveProjectContext}from"#internal/project-context.js";import{createServiceConfigRecord}from"#internal/vercel/vercel-services-config.js";import{createEveServiceName,createEveServiceRouteSrc}from"#internal/vercel/eve-service-contribution.js";import{assembleEveVercelServices}from"#internal/vercel/assemble-eve-services.js";import{quoteVercelShellArgument,toVercelRelativePath}from"#internal/vercel/build-command.js";import{resolveEveBinaryPath}from"#shared/resolve-eve-binary.js";function toInternalConfig(e){return e}function assertComposableConfig(e,t){if(e.experimentalServices!==void 0||e.experimentalServicesV2!==void 0)throw Error(`withEve cannot compose experimentalServices or experimentalServicesV2. Remove the obsolete field and define authored services under services.`);let n=toInternalConfig(e),r=createServiceConfigRecord(n.services);for(let n of t){let t=createEveServiceName(n);if(Object.hasOwn(r,t))throw Error(`Vercel service key ${JSON.stringify(t)} conflicts with the service generated for eve workspace agent ${JSON.stringify(n)}. Remove or rename the authored service; withEve owns this key.`);let i=createEveServiceRouteSrc(`/${n}`);if(e.routes?.some(e=>e.src===i))throw Error(`Vercel route ${JSON.stringify(i)} conflicts with the transport route generated for eve workspace agent ${JSON.stringify(n)}. Remove the authored route; withEve adds it automatically.`)}}async function withEve(e,t={}){let n=resolve(t.root??process.cwd()),r=await resolveEveProjectContext(n);if(r.kind!==`workspace`||r.workspace.root!==n)throw Error(`withEve must run at an eve workspace root; received ${n}.`);let{workspace:i}=r;if(i.members.length===0)throw Error(`withEve found no workspace agents under ${join(n,`agents`)}. Add an agent or remove withEve from vercel.ts.`);let a=i.members.map(e=>e.name),o=new Set(a.map(createEveServiceName));assertComposableConfig(e,a);let s=join(n,`.vercel`,`output`),c=toInternalConfig(e),l=assembleEveVercelServices({agents:i.members.map(e=>({agent:{appRoot:e.appRoot,buildCommand:`node ${quoteVercelShellArgument(toVercelRelativePath(e.appRoot,resolveEveBinaryPath(e.appRoot)))} build`,name:e.name,publicRoutePrefix:`/${e.name}`,workspaceMember:!0},target:{hostOutputDirectory:s,projectRoot:n}})),routes:c.routes,services:createServiceConfigRecord(c.services)});await Promise.all(l.rootDirectories.map(e=>mkdir(e,{recursive:!0})));let u=Object.fromEntries(Object.entries(l.services).map(([e,t])=>{if(!o.has(e))return[e,t];let{routePrefix:n,...r}=t;return[e,r]}));return{...e,routes:l.routes,services:u}}export{withEve};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import{SELF_MODIFICATION_CONFIG_PATH}from"./git-workspace.js";import{createHash}from"node:crypto";import{readFile,writeFile}from"node:fs/promises";import{join,relative}from"node:path";import{discoverAgent}from"#discover/discover-agent.js";import{execFile}from"node:child_process";import{promisify}from"node:util";import{stripLogicalPathExtension}from"#discover/filesystem.js";const runFile=promisify(execFile);function connectorName(e,t){return`selfmod-${e}-${t}`.toLowerCase().replaceAll(/[^a-z0-9-]/gu,`-`)}function renderSelfModificationConfig(e){if(e===void 0)return`import { defineSelfModificationConfig } from "eve/self-modification/config";
|
|
2
2
|
|
|
3
|
-
export default defineSelfModificationConfig({
|
|
3
|
+
export default defineSelfModificationConfig({
|
|
4
|
+
local: { enabled: true },
|
|
5
|
+
});
|
|
4
6
|
`;let t=[...new Set(e.channelNames)].filter(e=>e!==`eve`).sort(),n=(e.vercelBackend?t:[]).map(e=>` case ${JSON.stringify(`channel:${e}`)}:
|
|
5
7
|
// Authorize trusted principals for this channel before returning true.
|
|
6
8
|
return false;`).join(`
|
|
@@ -38,6 +40,9 @@ ${r} default:
|
|
|
38
40
|
},
|
|
39
41
|
},
|
|
40
42
|
});
|
|
41
|
-
`;return`// eve-self-modification: generated-v1 digest:${createHash(`sha256`).update(i).digest(`hex`)}\n${i}`}function classifySelfModificationConfig(e){if(e===void 0)return`missing`;if(e===renderSelfModificationConfig()
|
|
43
|
+
`;return`// eve-self-modification: generated-v1 digest:${createHash(`sha256`).update(i).digest(`hex`)}\n${i}`}function classifySelfModificationConfig(e){if(e===void 0)return`missing`;if(e===renderSelfModificationConfig()||e===`import { defineSelfModificationConfig } from "eve/self-modification/config";
|
|
44
|
+
|
|
45
|
+
export default defineSelfModificationConfig({});
|
|
46
|
+
`)return`local`;let[t,...n]=e.split(`
|
|
42
47
|
`);return/^\/\/ eve-self-modification: generated-v1 digest:([a-f0-9]{64})$/u.exec(t??``)?.[1]===createHash(`sha256`).update(n.join(`
|
|
43
48
|
`)).digest(`hex`)?`generated`:`authored`}function parseGitHubRemote(e){let t=e.trim().match(/^(?:https?:\/\/github\.com\/|git@github\.com:|ssh:\/\/git@github\.com\/)([^/]+)\/([^/]+?)(?:\.git)?$/u);return t?.[1]===void 0||t[2]===void 0?void 0:{owner:t[1],repo:t[2]}}function defaultSelfModificationSetupOperations(e){let t=join(e,SELF_MODIFICATION_CONFIG_PATH);return{async detectChannelNames(){return(await discoverAgent({appRoot:e,agentRoot:join(e,`agent`)})).manifest.channels.map(e=>stripLogicalPathExtension(e.logicalPath).replace(/^channels\//,``))},async detectGitRepository(){let t=await gitOutput(e,[`config`,`--get`,`remote.origin.url`]),n=t===void 0?void 0:parseGitHubRemote(t),r=await gitOutput(e,[`symbolic-ref`,`--quiet`,`--short`,`refs/remotes/origin/HEAD`]),i=await gitOutput(e,[`rev-parse`,`--show-toplevel`]);return{...n,branch:r?.replace(/^origin\//u,``),directory:i===void 0?void 0:repositoryRelativeDirectory(i,e),remoteKind:t===void 0?`missing`:n===void 0?`other`:`github`}},async readConfig(){try{return await readFile(t,`utf8`)}catch(e){if(e.code===`ENOENT`)return;throw e}},writeConfig:e=>writeFile(t,e,`utf8`),async findOrCreateConnector(t){let n=await vercel(e,[`connect`,`list`,`-F`,`json`]);if(!n.ok)throw Error(`Vercel Connect requires an authenticated Vercel CLI linked to this project.`);let r=parseConnectors(n.stdout),i=`github/${t}`,a=r.find(e=>e.uid===i);if(a!==void 0){if(a.type!==`github`)throw Error(`The existing connector ${i} is not a GitHub connector.`);return a.uid}let o=await vercel(e,[`connect`,`create`,`github`,`--name`,t,`-F`,`json`]),s=o.ok?parseCreatedConnector(o.stdout):void 0;if(s===void 0||!s.startsWith(`github/`))throw Error(`Could not create a GitHub Vercel Connect connector.`);return s},async attachConnector(t){let n=await readLinkedProject(e);if(n===void 0)throw Error("Vercel Connect requires this directory to be linked to a Vercel project. Run `vercel link` and retry.");if(!(await vercel(e,[`connect`,`attach`,t,`--project`,n.projectId,`--environment`,`production`,`--yes`])).ok)throw Error(`Could not attach ${t} to the linked Vercel project for Production.`)}}}function parseCreatedConnector(e){try{let t=JSON.parse(e);return typeof t.uid==`string`?t.uid:void 0}catch{return}}function parseConnectors(e){try{let t=JSON.parse(e);return(Array.isArray(t.connectors)?t.connectors:[t]).flatMap(e=>typeof e==`object`&&e&&typeof e.uid==`string`&&typeof e.type==`string`?[{uid:e.uid,type:e.type}]:[])}catch{return[]}}async function vercel(e,t){try{return{ok:!0,stdout:(await runFile(`vercel`,t,{cwd:e})).stdout}}catch{return{ok:!1,stdout:``}}}async function readLinkedProject(e){try{let t=JSON.parse(await readFile(join(e,`.vercel`,`project.json`),`utf8`));return typeof t.projectId==`string`?{projectId:t.projectId}:void 0}catch{return}}function repositoryRelativeDirectory(e,t,n=relative){return n(e,t).replaceAll(`\\`,`/`)||`.`}function repositoryPartError(e){return/^[A-Za-z0-9_.-]+$/u.test(e)?void 0:`Enter a valid GitHub owner or repository name.`}function directoryError(e){return e===`.`||e.length>0&&!e.startsWith(`/`)&&!e.includes(`\\`)&&e.split(`/`).every(e=>e!==``&&e!==`.`&&e!==`..`)?void 0:`Enter a safe repository-relative directory or ".".`}function gitRefError(e){return/^[A-Za-z0-9][A-Za-z0-9._/-]*$/u.test(e)&&!e.endsWith(`.`)&&!e.endsWith(`/`)&&!e.includes(`..`)&&!e.includes(`//`)&&!e.includes(`@{`)?void 0:`Enter a valid branch name.`}async function gitOutput(e,t){try{return(await runFile(`git`,t,{cwd:e})).stdout.trim()||void 0}catch{return}}export{classifySelfModificationConfig,connectorName,defaultSelfModificationSetupOperations,directoryError,gitRefError,parseGitHubRemote,renderSelfModificationConfig,repositoryPartError,repositoryRelativeDirectory};
|
|
@@ -3,12 +3,13 @@ import { type CodexTokenBroker } from "#public/models/openai/chatgpt/token-broke
|
|
|
3
3
|
interface ChatGptAuthOptions {
|
|
4
4
|
readonly signal?: AbortSignal;
|
|
5
5
|
readonly broker?: CodexTokenBroker;
|
|
6
|
+
readonly codexLogin?: (signal?: AbortSignal) => Promise<void>;
|
|
6
7
|
readonly store?: ChatGptCredentialStore;
|
|
7
8
|
readonly fetch?: typeof fetch;
|
|
8
9
|
readonly open?: (url: string) => void;
|
|
9
10
|
readonly log?: (message: string) => void;
|
|
10
11
|
readonly headless?: boolean;
|
|
11
12
|
}
|
|
12
|
-
/** Signs in
|
|
13
|
+
/** Signs in through the credential owner selected by the ChatGPT auth facade. */
|
|
13
14
|
export declare function ensureChatGptAuth(options?: ChatGptAuthOptions): Promise<void>;
|
|
14
15
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash,randomBytes}from"node:crypto";import{createServer}from"node:http";import{WizardCancelledError}from"#setup/step.js";import{isErrnoCode,isObject}from"#shared/guards.js";import{setTimeout as setTimeout$1}from"node:timers/promises";import{getDefaultCodexTokenBroker}from"#public/models/openai/chatgpt/token-broker.js";import{ChatGptInvalidStoredSessionError,getDefaultChatGptCredentialStore}from"#public/models/openai/chatgpt/credential-store.js";import{CHATGPT_CLIENT_ID,CHATGPT_ISSUER,readChatGptAuthResponse,requestChatGptTokens}from"#public/models/openai/chatgpt/oauth.js";import{openUrl}from"#setup/primitives/open-url.js";const REDIRECT_URI=`http://localhost:1455/auth/callback`;async function ensureChatGptAuth(e={}){let t=e.broker??getDefaultCodexTokenBroker(),n=e.store??getDefaultChatGptCredentialStore();
|
|
1
|
+
import{createHash,randomBytes}from"node:crypto";import{createServer}from"node:http";import{spawn}from"node:child_process";import{WizardCancelledError}from"#setup/step.js";import{createProcessOutputBuffer}from"#setup/primitives/process-output.js";import{isErrnoCode,isObject}from"#shared/guards.js";import{setTimeout as setTimeout$1}from"node:timers/promises";import{getDefaultCodexTokenBroker}from"#public/models/openai/chatgpt/token-broker.js";import{ChatGptInvalidStoredSessionError,getDefaultChatGptCredentialStore}from"#public/models/openai/chatgpt/credential-store.js";import{CHATGPT_CLIENT_ID,CHATGPT_ISSUER,readChatGptAuthResponse,requestChatGptTokens}from"#public/models/openai/chatgpt/oauth.js";import{openUrl}from"#setup/primitives/open-url.js";const REDIRECT_URI=`http://localhost:1455/auth/callback`;async function ensureChatGptAuth(e={}){let t=e.broker??getDefaultCodexTokenBroker(),n=e.store??getDefaultChatGptCredentialStore();e.signal?.throwIfAborted();let r=await t.refreshState();if(r.kind===`ready`)return;let i=t.credentialOwner();if(i===void 0)throw Error(`ChatGPT credential owner could not be resolved.`);if(i===`codex`){if(r.kind===`unavailable`)throw Error(r.reason);try{let n=e.log??(e=>process.stdout.write(`${e}\n`));await(e.codexLogin??(e=>loginWithCodex(e,n)))(e.signal),await assertChatGptAuthReady(t,`Codex login completed without a usable ChatGPT session.`);return}catch(e){if(!isErrnoCode(e,`ENOENT`))throw e;let n=await t.refreshState();if(t.credentialOwner()!==`eve`)throw e;if(n.kind===`ready`)return;if(n.kind===`unavailable`)throw Error(n.reason)}}try{await n.read()}catch(e){if(!(e instanceof ChatGptInvalidStoredSessionError))throw e}await signInWithOwnedCredentials(e,t,n)}async function signInWithOwnedCredentials(e,t,n){let r=new AbortController,cancel=()=>r.abort(new WizardCancelledError);process.once(`SIGINT`,cancel);let i=setTimeout(()=>r.abort(Error(`ChatGPT sign-in timed out. Retry from /model.`)),3e5),a=AbortSignal.any([r.signal,...e.signal?[e.signal]:[]]),o=e.log??(e=>process.stdout.write(`${e}\n`)),s=e.open??openUrl;try{let r=e.headless??!!(process.env.SSH_CONNECTION||process.env.SSH_TTY)?await deviceLogin({...e,signal:a,log:o,open:s}):await browserLogin({...e,signal:a,log:o,open:s});a.throwIfAborted(),await n.update(async()=>(a.throwIfAborted(),r),{replace:!0}),await assertChatGptAuthReady(t,`ChatGPT sign-in could not be verified. Retry from /model.`),o(`ChatGPT subscription connected.`)}catch(e){throw a.throwIfAborted(),e}finally{clearTimeout(i),process.removeListener(`SIGINT`,cancel)}}async function assertChatGptAuthReady(e,t){if((await e.refreshState()).kind!==`ready`)throw Error(t)}async function loginWithCodex(e,t){let n=spawn(`codex`,[`login`],{stdio:[`ignore`,`pipe`,`pipe`],...e!==void 0&&{signal:e}}),r=createProcessOutputBuffer(({text:e})=>t(e));n.stdout.on(`data`,e=>r.write(`stdout`,e)),n.stderr.on(`data`,e=>r.write(`stderr`,e));try{await new Promise((e,t)=>{n.once(`error`,t),n.once(`close`,(n,r)=>{n===0?e():t(Error(`codex login failed (${r??n??`unknown`}).`))})})}finally{r.flush()}}async function browserLogin(e){let t=randomBytes(32).toString(`base64url`),n=randomBytes(32).toString(`base64url`),r=new URL(`${CHATGPT_ISSUER}/oauth/authorize`);r.search=new URLSearchParams({response_type:`code`,client_id:CHATGPT_CLIENT_ID,redirect_uri:REDIRECT_URI,scope:`openid profile email offline_access`,code_challenge:createHash(`sha256`).update(t).digest(`base64url`),code_challenge_method:`S256`,id_token_add_organizations:`true`,codex_cli_simplified_flow:`true`,state:n,originator:`eve`}).toString();let i=Promise.withResolvers();i.promise.catch(()=>{});let a=createServer({requestTimeout:1e4,headersTimeout:1e4,maxHeaderSize:8192},(e,t)=>{let r=URL.parse(e.url??``,REDIRECT_URI);if(t.setHeader(`content-type`,`text/plain; charset=utf-8`),t.setHeader(`cache-control`,`no-store`),e.method!==`GET`||r?.pathname!==`/auth/callback`){t.writeHead(404).end(`Not found.`);return}if(r.searchParams.get(`state`)!==n){t.writeHead(400).end(`This sign-in belongs to another attempt. Return to eve and use its sign-in link.`);return}if(r.searchParams.has(`error`)){t.writeHead(400).end(`ChatGPT sign-in was declined. Return to eve to retry.`),i.reject(Error(`ChatGPT sign-in was declined. Retry from /model.`));return}let a=r.searchParams.get(`code`);if(!a){t.writeHead(400).end(`Missing authorization code.`);return}t.end(`Authorization received. Return to eve to finish connecting your ChatGPT subscription.`),i.resolve(a)});a.maxConnections=10;let abort=()=>i.reject(e.signal.reason);e.signal.addEventListener(`abort`,abort,{once:!0});try{e.signal.throwIfAborted();try{await new Promise((e,t)=>{a.once(`error`,t),a.listen(1455,`127.0.0.1`,e)})}catch(t){if(!isErrnoCode(t,`EADDRINUSE`))throw Error(`Could not start ChatGPT sign-in on localhost:1455. Free the port and retry from /model.`);return e.log(`Local sign-in port is in use. Continuing with a device code.`),await deviceLogin(e)}e.signal.throwIfAborted(),e.log(`Sign in to ChatGPT in your browser:\n${r.href}\nWaiting for sign-in. Press Ctrl+C to cancel.`),e.open(r.href);let n=await i.promise;return await requestChatGptTokens({grant_type:`authorization_code`,code:n,code_verifier:t,redirect_uri:REDIRECT_URI},e)}finally{e.signal.removeEventListener(`abort`,abort),a.closeAllConnections(),await new Promise(e=>a.close(()=>e()))}}async function deviceLogin(e){let t=await deviceRequest(`usercode`,{client_id:CHATGPT_CLIENT_ID},e);if(!t.ok)throw Error(`ChatGPT device sign-in is unavailable (HTTP ${t.status}). Enable device code authorization in ChatGPT Settings > Security, then retry from /model.`);let n=await readChatGptAuthResponse(t);if(!isObject(n)||typeof n.device_auth_id!=`string`||!n.device_auth_id||typeof n.user_code!=`string`||!/^[A-Z0-9-]{4,32}$/iu.test(n.user_code))throw Error(`ChatGPT returned an invalid device code. Retry from /model.`);let r=Math.min(30,Math.max(1,Number(n.interval)||5))*1e3,i=`${CHATGPT_ISSUER}/codex/device`;for(e.log(`Open ${i} and enter code: ${n.user_code}\nIf prompted, enable device code authorization in ChatGPT Settings > Security.\nWaiting for sign-in. Press Ctrl+C to cancel.`),e.open(i);;){await setTimeout$1(r+1e3,void 0,{signal:e.signal});let t=await deviceRequest(`token`,{device_auth_id:n.device_auth_id,user_code:n.user_code},e);if(t.status===403||t.status===404)continue;if(!t.ok)throw Error(`ChatGPT device sign-in failed (HTTP ${t.status}). Retry from /model.`);let i=await readChatGptAuthResponse(t);if(!isObject(i)||typeof i.authorization_code!=`string`||!i.authorization_code||typeof i.code_verifier!=`string`||!i.code_verifier)throw Error(`ChatGPT returned an invalid device authorization. Retry from /model.`);return requestChatGptTokens({grant_type:`authorization_code`,code:i.authorization_code,code_verifier:i.code_verifier,redirect_uri:`${CHATGPT_ISSUER}/deviceauth/callback`},e)}}async function deviceRequest(e,t,n){try{return await(n.fetch??fetch)(`${CHATGPT_ISSUER}/api/accounts/deviceauth/${e}`,{method:`POST`,headers:{"content-type":`application/json`,"user-agent":`eve`},body:JSON.stringify(t),redirect:`error`,signal:AbortSignal.any([n.signal,AbortSignal.timeout(3e4)])})}catch{throw n.signal.throwIfAborted(),Error(`Could not reach ChatGPT device sign-in. Check your connection and retry from /model.`)}}export{ensureChatGptAuth};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.93`,DEFAULT_CONNECT_PACKAGE_VERSION=`1.0.0`,DEFAULT_ZOD_PACKAGE_VERSION=`4.5.4`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.54.
|
|
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){
|
|
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};
|
package/docs/agent-config.md
CHANGED
|
@@ -87,9 +87,9 @@ export default defineAgent({
|
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
Handlers receive the shared [dynamic resolver
|
|
90
|
-
context](./guides/dynamic-capabilities)
|
|
91
|
-
`
|
|
92
|
-
|
|
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
|
-
|
|
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
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
:
|
|
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
|
|
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`
|
|
59
|
+
In the provider layout, eve stamps each span with `gen_ai.conversation.id`, which stays fixed across local and remote activations, including independent remote root workflows. Query this attribute to find the conversation's exported, retained traces; it does not grant access or control trace parenting. On Vercel, `vercel.session_id` identifies the verified root session, while `agent.run.id` identifies the current agent run. See [Query exported traces](#query-exported-traces) for the cross-backend workflow.
|
|
60
60
|
|
|
61
61
|
You are responsible for ensuring any observability or eval provider is approved for the data exported to it.
|
|
62
62
|
|
|
@@ -193,7 +193,14 @@ the failure outcome, error status, and error type. The initiating turn can
|
|
|
193
193
|
finish or be cancelled while the action remains open. Ending the session closes
|
|
194
194
|
an action whose task never reported a terminal result.
|
|
195
195
|
|
|
196
|
-
Schema v4 removes the session-long `agent.session` root
|
|
196
|
+
Schema v4 removes the session-long `agent.session` root. Every run-associated
|
|
197
|
+
eve span carries `agent.trace.schema.version=4`, `agent.run.id`, and
|
|
198
|
+
`gen_ai.conversation.id`; the pre-session `agent.channel.request` span is the
|
|
199
|
+
exception. Vercel deployments additionally carry
|
|
200
|
+
`vercel.session_id`, which stays fixed to the root session across local and
|
|
201
|
+
trusted remote subagents. Remote lineage is accepted only when the receiver's
|
|
202
|
+
`trustedForwarders` predicate approves the authenticated caller. Child
|
|
203
|
+
activation roots carry `agent.parent_run.id` and `agent.parent_call.id`.
|
|
197
204
|
Only activations use the `invoke_agent` operation. A workflow tool invocation
|
|
198
205
|
that coordinates at least one nested agent uses `invoke_workflow`, with its
|
|
199
206
|
path-derived tool name in `gen_ai.workflow.name`. Durable workflow tools without
|
|
@@ -207,8 +214,10 @@ A conversation remains durable state; `gen_ai.conversation.id` joins the activat
|
|
|
207
214
|
|
|
208
215
|
Each activation owns a fresh trace identity, including local and remote
|
|
209
216
|
subagents. The first child activation links to its caller with
|
|
210
|
-
`eve.link.type=agent.dispatch`;
|
|
211
|
-
|
|
217
|
+
`eve.link.type=agent.dispatch`; remote dispatch preserves that caller separately
|
|
218
|
+
in W3C `tracestate` while HTTP intermediaries update `traceparent`. Older peers
|
|
219
|
+
fall back to the incoming transport context. Later turns do not reuse the
|
|
220
|
+
original caller link.
|
|
212
221
|
Conversation baggage is independent of execution lineage and trace-policy
|
|
213
222
|
ceilings, which remain in force across the boundary.
|
|
214
223
|
|
|
@@ -259,7 +268,8 @@ This workflow applies to schema v4 from the [instrumentation provider layout](./
|
|
|
259
268
|
| Agent activations | `agent.trace.schema.version=4` and `gen_ai.operation.name=invoke_agent` |
|
|
260
269
|
| One logical conversation | `gen_ai.conversation.id=<conversation ID>` |
|
|
261
270
|
| One turn | Both `gen_ai.conversation.id` and `agent.turn.id` |
|
|
262
|
-
| One Vercel
|
|
271
|
+
| One Vercel root session | `vercel.session_id=<root session ID>` |
|
|
272
|
+
| One agent run | `agent.run.id=<run ID>` |
|
|
263
273
|
| Delegated dispatches | `agent.invocation.role=caller` |
|
|
264
274
|
|
|
265
275
|
Start with an activation filter for latency, failure, or turn-count dashboards. Every activation is a trace root. Within a conversation, group by trace ID, order activations by `agent.turn.sequence` or start time, and open the selected trace ID. Child activations link to their caller with `eve.link.type=agent.dispatch`; remote workflows keep their own execution lineage, so use conversation IDs and caller links for cross-deployment correlation.
|
|
@@ -288,7 +298,7 @@ invoke_agent support session=S, turn=turn_1, conversation=S
|
|
|
288
298
|
|
|
289
299
|
The conversation filter finds all three retained traces. eve initializes the conversation ID once and carries it through the existing parent context for local dispatch and `eve.conversation.id` baggage for remote dispatch. Remote session creation does not carry execution lineage or add authorization requirements for tracing. Existing authentication, principal forwarding, and root-session limits remain unchanged.
|
|
290
300
|
|
|
291
|
-
|
|
301
|
+
Remote dispatch records the caller's span ID in eve's W3C `tracestate` entry because HTTP intermediaries may advance `traceparent` to their own request span. The receiver combines that prior parent with the current trace identity for the causal link and retains the transport context for `channel.request`; adopting either as the child's parent would instead keep both in the same trace. Resolved trace-policy decisions and trusted remote content ceilings continue across this boundary independently of correlation, and an unsampled caller cannot be widened into a sampled child. No synthetic session span is needed.
|
|
292
302
|
|
|
293
303
|
Activation duration is elapsed time for that activation, including waits inside it, not the lifetime of the conversation or CPU time. Idle time between ended activations is not part of their durations. For token totals, choose one level: filter to `chat` model spans and sum `gen_ai.usage.*`, or filter to activations and sum their `agent.usage.input_tokens` and `agent.usage.output_tokens`. Exclude caller summaries from the activation total. Query cache usage on model spans. Do not add model, step, activation, and caller counters together.
|
|
294
304
|
|
|
@@ -139,16 +139,16 @@ Identity forwarding does not make a persistent session private to one caller. Co
|
|
|
139
139
|
|
|
140
140
|
Forwarding is explicit on both sides. The receiver names which forwarders it trusts with `eveChannel({ trustedForwarders })` (see [Auth & route protection](./auth-and-route-protection#accepting-forwarded-identity-from-another-deployment)); a receiver that refuses the forwarder — or has no `trustedForwarders` at all — rejects with a 403 and the dispatch fails.
|
|
141
141
|
|
|
142
|
-
Remote tracing uses
|
|
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
|
|
150
|
-
|
|
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
|
|
package/docs/reference/cli.md
CHANGED
|
@@ -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`.
|
|
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
|
|
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
|
|
15
|
+
- The command you ran, its outcome, and setup or onboarding steps when applicable. When setup or onboarding fails, eve sends a bounded category describing the failed step. It does not send the underlying error.
|
|
16
16
|
- For `eve dev`, whether you connected to a local or remote agent and whether the UI was interactive or headless.
|
|
17
17
|
- Random identifiers for the CLI session, installation, and project, plus whether the installation and project identifiers are ephemeral or persistent.
|
|
18
18
|
|
|
@@ -186,26 +186,29 @@ Pass another bare OpenAI model slug to override the default. `experimental_chatg
|
|
|
186
186
|
|
|
187
187
|
`chatgpt()` uses stateless requests (`store: false`). eve retains reasoning summaries and encrypted reasoning in session history and replays them after tool calls and on later turns. You do not need to configure `reasoning.encrypted_content` explicitly.
|
|
188
188
|
|
|
189
|
-
|
|
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.
|
|
193
|
-
3.
|
|
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
|
-
|
|
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
|
-
|
|
197
|
+
For the eve-owned fallback, eve stores your refresh token and account details in your operating system's credential store through [just-secrets](https://github.com/vercel-labs/just-secrets): the login Keychain on macOS, Credential Manager on Windows, or Secret Service on Linux. Access tokens stay in process memory; a new eve process refreshes the saved session when it first needs a token. The fallback login is separate from Codex and is never written to your project.
|
|
198
|
+
|
|
199
|
+
If you previously used eve's `~/.eve/auth/chatgpt.json` file, sign in once through the eve-owned fallback after upgrading. A successful save removes the old plaintext session file. eve does not fall back to file storage if the OS credential store is unavailable.
|
|
198
200
|
|
|
199
201
|
Linux, including WSL, requires `/usr/bin/secret-tool` (commonly provided by `libsecret-tools`), a session D-Bus, and an unlocked Secret Service keyring. On macOS, unlock your login keychain and allow credential access if prompted. On Windows, PowerShell and Credential Manager must be available in your user session. OS credential storage protects secrets at rest; it does not guarantee isolation from malicious processes running as your OS user.
|
|
200
202
|
|
|
201
|
-
|
|
203
|
+
For the eve-owned fallback, SSH sessions or a busy localhost port 1455 use a device code. Open the displayed link in a browser and enter the code. Device sign-in requires enabling device code authorization in **ChatGPT Settings → Security**, or having a workspace admin enable it in workspace permissions. Sign-in times out after five minutes; press **Ctrl+C** to cancel sooner. Device sign-in still requires an available OS credential store; use an API-key model in headless environments without one.
|
|
202
204
|
|
|
203
205
|
ChatGPT subscription credentials are local user credentials. `eve deploy` blocks agents whose active model is `chatgpt()` because those credentials are not uploaded to a deployment. Use an environment branch with a deployable model, or switch to an AI Gateway model before deploying.
|
|
204
206
|
|
|
205
207
|
Troubleshooting:
|
|
206
208
|
|
|
207
|
-
- **`chatgpt-sub login`**: open `/model` and select **Provider** → **ChatGPT subscription** to sign in again.
|
|
208
|
-
- **`chatgpt-sub unavailable
|
|
209
|
+
- **`chatgpt-sub login`**: open `/model` and select **Provider** → **ChatGPT subscription** to sign in again. eve launches `codex login` when Codex is available, or its direct sign-in flow when it is not.
|
|
210
|
+
- **`chatgpt-sub unavailable` with Codex installed**: update or restart Codex and retry. eve does not mask app-server failures by switching to a different saved session.
|
|
211
|
+
- **`chatgpt-sub unavailable` without Codex**: follow the reported OS credential-store recovery steps, or check your network connection if token refresh failed. Retry from `/model`. If eve reports an invalid stored session, sign in again to replace it.
|
|
209
212
|
- **Model rejected by the backend**: model availability depends on the signed-in ChatGPT account. Pick another supported OpenAI model.
|
|
210
213
|
- **Device sign-in unavailable**: enable device code authorization in ChatGPT security settings, or sign in from a local terminal with port 1455 available.
|
|
211
214
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eve",
|
|
3
|
-
"version": "0.54.
|
|
3
|
+
"version": "0.54.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
|
|
6
6
|
"keywords": [
|
|
@@ -86,6 +86,12 @@
|
|
|
86
86
|
"import": "./dist/src/public/next/index.js",
|
|
87
87
|
"default": "./dist/src/public/next/index.js"
|
|
88
88
|
},
|
|
89
|
+
"./vercel": {
|
|
90
|
+
"eve-source": "./src/public/vercel/index.ts",
|
|
91
|
+
"types": "./dist/src/public/vercel/index.d.ts",
|
|
92
|
+
"import": "./dist/src/public/vercel/index.js",
|
|
93
|
+
"default": "./dist/src/public/vercel/index.js"
|
|
94
|
+
},
|
|
89
95
|
"./nuxt": {
|
|
90
96
|
"types": "./dist/src/public/nuxt/index.d.ts",
|
|
91
97
|
"import": "./dist/src/public/nuxt/index.js",
|
|
@@ -471,14 +477,14 @@
|
|
|
471
477
|
"@vercel/sandbox": "3.2.1",
|
|
472
478
|
"@vercel/sandbox-drives": "npm:@vercel/sandbox@3.1.0-beta.1",
|
|
473
479
|
"@vercel/sdk": "1.28.8",
|
|
474
|
-
"@workflow/builders": "5.0.0-beta.
|
|
475
|
-
"@workflow/core": "5.0.0-beta.
|
|
480
|
+
"@workflow/builders": "5.0.0-beta.51",
|
|
481
|
+
"@workflow/core": "5.0.0-beta.51",
|
|
476
482
|
"@workflow/errors": "5.0.0-beta.21",
|
|
477
483
|
"@workflow/serde": "5.0.0-beta.2",
|
|
478
484
|
"@workflow/utils": "5.0.0-beta.10",
|
|
479
|
-
"@workflow/world": "5.0.0-beta.
|
|
480
|
-
"@workflow/world-local": "5.0.0-beta.
|
|
481
|
-
"@workflow/world-vercel": "5.0.0-beta.
|
|
485
|
+
"@workflow/world": "5.0.0-beta.35",
|
|
486
|
+
"@workflow/world-local": "5.0.0-beta.44",
|
|
487
|
+
"@workflow/world-vercel": "5.0.0-beta.46",
|
|
482
488
|
"ai": "^7.0.93",
|
|
483
489
|
"autoevals": "0.0.132",
|
|
484
490
|
"chat": "4.34.0",
|