eve 0.6.0-beta.13 → 0.6.0-beta.14
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 +10 -0
- package/README.md +1 -1
- package/dist/src/cli/dev/change-agent-model.d.ts +27 -0
- package/dist/src/cli/dev/change-agent-model.js +1 -0
- package/dist/src/cli/dev/tui/runner.d.ts +38 -2
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/tui.d.ts +6 -0
- package/dist/src/cli/dev/tui/tui.js +1 -1
- package/dist/src/cli/run.d.ts +1 -0
- package/dist/src/cli/run.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +1 -1
- package/dist/src/compiled/just-bash/index.d.ts +4 -4
- package/dist/src/compiler/normalize-agent-config.js +1 -1
- package/dist/src/compiler/normalize-manifest.js +1 -1
- package/dist/src/compiler/workspace-resources.js +1 -1
- package/dist/src/execution/sandbox/bash-tool.d.ts +6 -6
- package/dist/src/execution/sandbox/bash-tool.js +1 -1
- package/dist/src/execution/sandbox/bindings/local.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/public/tools/define-bash-tool.d.ts +3 -3
- package/dist/src/public/tools/define-bash-tool.js +1 -1
- package/dist/src/public/tools/index.d.ts +1 -1
- package/dist/src/public/tools/index.js +1 -1
- package/dist/src/runtime/framework-tools/bash.d.ts +3 -3
- package/dist/src/runtime/framework-tools/bash.js +1 -1
- package/dist/src/runtime/governance/auth/http-basic.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/update/channels.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# eve
|
|
2
2
|
|
|
3
|
+
## 0.6.0-beta.14
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 9d806d0: Add a `/model` command to the `eve dev` TUI. Run it bare to pick from a list (the running model flagged, a catalog-validated shortlist, and a freeform entry), or `/model <provider/model-id>` to set one directly. The pick rewrites `agent.ts`, and the dev server's HMR watcher applies it on the next prompt.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- c99668f: Correct the public bash tool helper export from `defineBeveTool` to `defineBashTool`.
|
|
12
|
+
|
|
3
13
|
## 0.6.0-beta.13
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ Every authored directory has a typed helper. Import each from the matching subpa
|
|
|
45
45
|
| ------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | ------------------------------------------------ |
|
|
46
46
|
| `defineAgent(...)` | `eve` | `agent.ts`, `subagents/<id>/agent.ts` |
|
|
47
47
|
| `defineInstructions(...)` | `eve/instructions` | `instructions.ts` (or `instructions.md`) |
|
|
48
|
-
| `defineTool(...)`, `
|
|
48
|
+
| `defineTool(...)`, `defineBashTool(...)`, `defineReadFileTool(...)`, `defineWriteFileTool(...)`, `disableTool(...)` | `eve/tools` | `tools/<name>.ts` |
|
|
49
49
|
| `defineSkill(...)`, `getSkill(...)` | `eve/skills` | `skills/<name>.ts` (or `skills/<name>.md`) |
|
|
50
50
|
| `defineHook(...)` | `eve/hooks` | `hooks/<slug>.ts` |
|
|
51
51
|
| `defineChannel(...)`, `POST`, `GET` | `eve/channels` | `channels/<name>.ts` |
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Applies a `/model <slug>` change to the local agent's authored source.
|
|
3
|
+
*
|
|
4
|
+
* This is the caller layer for the static source-change registry: it
|
|
5
|
+
* validates the slug against the AI Gateway model catalog, then edits
|
|
6
|
+
* `agent.ts` via {@link createStaticSourceChange}. Returns a human-readable
|
|
7
|
+
* line for the TUI to surface; activation is the dev server's HMR watcher.
|
|
8
|
+
*/
|
|
9
|
+
export declare function changeAgentModel(input: {
|
|
10
|
+
readonly appRoot: string;
|
|
11
|
+
readonly slug: string;
|
|
12
|
+
}): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Validates the curated seed against the AI Gateway catalog. Run once at dev
|
|
15
|
+
* startup so the picker only offers models the gateway actually has. Keeps the
|
|
16
|
+
* full seed when the catalog is unreachable, so offline dev isn't blocked.
|
|
17
|
+
*/
|
|
18
|
+
export declare function hydrateCuratedModels(appRoot: string): Promise<readonly string[]>;
|
|
19
|
+
/**
|
|
20
|
+
* Picker rows for a bare `/model`: the model the runtime is serving first
|
|
21
|
+
* (flagged), then the hydrated curated set, deduped. The TUI renders these as a
|
|
22
|
+
* select list with a freeform "type your own" row appended.
|
|
23
|
+
*/
|
|
24
|
+
export declare function listAgentModelChoices(appRoot: string, curated: readonly string[]): Promise<ReadonlyArray<{
|
|
25
|
+
readonly id: string;
|
|
26
|
+
readonly label: string;
|
|
27
|
+
}>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{join}from"node:path";import{discoverAgent}from"#discover/discover-agent.js";import{inspectApplication}from"#services/inspect-application.js";import{createCompiledRuntimeModelCatalogLoader}from"#compiler/model-catalog.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{createStaticSourceChange}from"#source-change/static-source-change.js";async function changeAgentModel(n){let{appRoot:r,slug:i}=n,a=await validateModelSlug(r,i);if(a!==null)return a;let{manifest:o}=await discoverAgent({agentRoot:join(r,`agent`),appRoot:r}),s=await createStaticSourceChange(o).updateModelName(i);return s.kind===`bail`?`Couldn't edit ${s.at.logicalPath}: ${s.reason}. Change \`model\` by hand.`:s.from===s.to?`Model is already \`${s.to}\`.`:`Model → \`${s.to}\` · live on your next prompt.`}async function validateModelSlug(e,t){if(!t.includes(`/`))return`\`${t}\` isn't a provider/model id (e.g. anthropic/claude-sonnet-4.6).`;let n=createCompiledRuntimeModelCatalogLoader(e);try{if(await n.getModelLimits(formatLanguageModelGatewayId(t))===null)return`I couldn't confirm \`${t}\` in the AI Gateway model catalog, so I didn't change agent.ts.`}catch{return null}return null}const CURATED_MODELS=[`anthropic/claude-opus-4.8`,`anthropic/claude-opus-4.7`,`anthropic/claude-sonnet-4.7`,`anthropic/claude-sonnet-4.6`,`openai/gpt-5.4-mini`];async function hydrateCuratedModels(e){let t=createCompiledRuntimeModelCatalogLoader(e),n=[];for(let e of CURATED_MODELS)try{await t.getModelLimits(formatLanguageModelGatewayId(e))!==null&&n.push(e)}catch{n.push(e)}return n}async function listAgentModelChoices(e,t){let n=await readRuntimeModel(e),r=[];n!==null&&r.push(n);for(let e of t)r.includes(e)||r.push(e);return r.map(e=>({id:e,label:e===n?`${e} (current)`:e}))}async function readRuntimeModel(e){try{let{compiledState:t}=await inspectApplication(e);return t?.manifest.config.model.id??null}catch{return null}}export{changeAgentModel,hydrateCuratedModels,listAgentModelChoices};
|
|
@@ -114,8 +114,8 @@ export type AgentTUIRenderer = {
|
|
|
114
114
|
*/
|
|
115
115
|
renderAgentHeader?(header: AgentTUIAgentHeader): void;
|
|
116
116
|
/**
|
|
117
|
-
* Commits a single
|
|
118
|
-
*
|
|
117
|
+
* Commits a single informational line to the transcript. Used for session
|
|
118
|
+
* recovery and slash-command results. Optional.
|
|
119
119
|
*/
|
|
120
120
|
renderNotice?(text: string): void;
|
|
121
121
|
readPrompt?(options?: AgentTUISessionOptions): Promise<string | undefined>;
|
|
@@ -166,6 +166,22 @@ export type AgentTUIRenderer = {
|
|
|
166
166
|
*/
|
|
167
167
|
shutdown?(): void;
|
|
168
168
|
};
|
|
169
|
+
/**
|
|
170
|
+
* The `/model` command behavior the TUI drives. The `eve dev` glue binds it
|
|
171
|
+
* to the local application root.
|
|
172
|
+
*/
|
|
173
|
+
export interface ModelCommand {
|
|
174
|
+
/**
|
|
175
|
+
* Picker rows for a bare `/model`: the current model followed by a curated
|
|
176
|
+
* set. Freeform entry covers models outside the list.
|
|
177
|
+
*/
|
|
178
|
+
listChoices(): Promise<ReadonlyArray<{
|
|
179
|
+
readonly id: string;
|
|
180
|
+
readonly label: string;
|
|
181
|
+
}>>;
|
|
182
|
+
/** Applies a chosen model id to the authored source and returns a result line. */
|
|
183
|
+
apply(slug: string): Promise<string>;
|
|
184
|
+
}
|
|
169
185
|
export type EveTUIRunnerOptions = TuiDisplayOptions & {
|
|
170
186
|
session: ClientSession;
|
|
171
187
|
/**
|
|
@@ -194,12 +210,32 @@ export type EveTUIRunnerOptions = TuiDisplayOptions & {
|
|
|
194
210
|
* artifacts; input-response resumes keep the current session.
|
|
195
211
|
*/
|
|
196
212
|
serverUrl?: string;
|
|
213
|
+
/**
|
|
214
|
+
* Backs `/model` for local development sessions. Remote sessions omit it
|
|
215
|
+
* because editing local source would not affect the connected server.
|
|
216
|
+
*/
|
|
217
|
+
modelCommand?: ModelCommand;
|
|
197
218
|
};
|
|
198
219
|
export declare class EveTUIRunner {
|
|
199
220
|
#private;
|
|
200
221
|
constructor(options: EveTUIRunnerOptions);
|
|
201
222
|
run(): Promise<void>;
|
|
202
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Recognizes the slash commands the prompt accepts. `/new` clears the
|
|
226
|
+
* session and transcript; `/exit` (and `/quit`) terminate the TUI like
|
|
227
|
+
* Ctrl+C; `/model <slug>` edits the agent's model. Anything else is a normal
|
|
228
|
+
* message.
|
|
229
|
+
*/
|
|
230
|
+
export type PromptCommand = {
|
|
231
|
+
type: "new";
|
|
232
|
+
} | {
|
|
233
|
+
type: "exit";
|
|
234
|
+
} | {
|
|
235
|
+
type: "model";
|
|
236
|
+
slug: string;
|
|
237
|
+
};
|
|
238
|
+
export declare function parsePromptCommand(prompt: string): PromptCommand | null;
|
|
203
239
|
type SubagentChildStep = {
|
|
204
240
|
reasoning: string;
|
|
205
241
|
message: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{failureKey,formatFailureDetail,formatFailureMessage,isAbortLikeError,isInterruptedError}from"./errors.js";import{TerminalRenderer}from"./terminal-renderer.js";import{toErrorMessage}from"#shared/errors.js";import{createDevelopmentRuntimeArtifactSessionRefresher}from"#services/dev-client.js";import{isCurrentTurnBoundaryEvent}from"#client/index.js";var EveTUIRunner=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u;#d;#f;#p;#m=new Map;#h=new Map;#g=new Map;#_=new Map;#v=new Set;#y=!1;constructor(e){this.#e=e.session,e.client!==void 0&&(this.#t=e.client),this.#n=createRenderer(e),this.#r=e.name??`Eve`,this.#i=e.tools??`full`,this.#a=e.reasoning??`full`,this.#o=e.subagents??`full`,this.#s=e.connectionAuth??`full`,this.#c=e.assistantResponseStats??`tokensPerSecond`,this.#l=e.contextSize,this.#u=e.formatTransportError??toErrorMessage,e.serverUrl!==void 0&&(this.#f=e.serverUrl,this.#d=createDevelopmentRuntimeArtifactSessionRefresher({serverUrl:e.serverUrl}))}async#b(){if(!this.#n.renderAgentHeader)return;let e=this.#f;if(e===void 0)return;let t;try{t=await this.#t?.info()}catch{t=void 0}this.#p=t;let n={name:this.#r,serverUrl:e};t!==void 0&&(n.info=t),this.#n.renderAgentHeader(n)}async run(){let e=this.#r,t,n,r=!1,a=!1;for(await this.#b();;){if(!a){if(t==null){if(!this.#n.readPrompt){if(r)return;throw Error(`No prompt was provided and the renderer does not support prompt input.`)}try{t=await this.#S({title:e})}catch(e){if(isInterruptedError(e))return;throw e}if(t==null)return}let o=parsePromptCommand(t);if(o===`exit`){this.#n.shutdown?.();return}if(o===`new`){this.#x(),n=void 0,a=!1,t=void 0,this.#n.reset?.();continue}r=!0}let o=await this.#C({prompt:a?void 0:t,inputResponses:n});try{await this.#n.renderStream(o,{title:e,submittedPrompt:t,continueSession:!!this.#n.readPrompt,tools:this.#i,reasoning:this.#a,subagents:this.#o,connectionAuth:this.#s,assistantResponseStats:this.#c,contextSize:this.#l});let r=o.turnState?.pendingApprovals??[],i=o.turnState?.pendingQuestions??[];if(r.length>0||i.length>0){let o=[];if(r.length>0){if(!this.#n.readToolApproval)throw Error(`Tool approval was requested, but the renderer does not support tool approval input.`);for(let t of r){let n=await this.#n.readToolApproval(t,{title:e});o.push({requestId:t.approvalId,optionId:n.approved?`approve`:`deny`}),this.#m.delete(t.approvalId)}}if(i.length>0){if(!this.#n.readInputQuestion)throw Error(`An interactive question was requested, but the renderer does not support input questions.`);for(let t of i){let n=toAgentTUIInputQuestion(t),r=await this.#n.readInputQuestion(n,{title:e});if(r===void 0)continue;let i={requestId:t.requestId};r.optionId!==void 0&&(i.optionId=r.optionId),r.text!==void 0&&(i.text=r.text),o.push(i),this.#m.delete(t.requestId)}}a=!0,n=o,t=void 0;continue}o.turnState&&o.turnState.boundaryEvent===void 0&&(this.#y=!0)}catch(e){if(isInterruptedError(e))return;throw e}a=!1,n=void 0,t=void 0,this.#y&&(this.#y=!1,this.#x(),this.#n.renderNotice?.(`Session ended — started a new session. Earlier context was cleared.`))}}#x(){for(let e of this.#g.values())e.abort();this.#g.clear(),this.#h.clear(),this.#m.clear(),this.#_.clear(),this.#v.clear(),this.#t&&(this.#e=this.#t.session()),this.#d?.clear()}async#S(e){if(!this.#n.readPrompt)return;let t=this.#n.readPrompt(e),n=this.#t,r=this.#d;if(n===void 0||r===void 0)return await t;let i=!1,a=!1,o,refresh=async()=>{if(!(i||a)){a=!0;try{this.#e=await r.refreshIdle({createSession:()=>n.session(),onRuntimeArtifactsChanged:()=>this.#w(),session:this.#e})}finally{a=!1}}},startRefresh=()=>{if(i||a)return;let e=refresh().finally(()=>{o===e&&(o=void 0)});o=e};startRefresh();let s=setInterval(()=>{startRefresh()},500);s.unref?.();try{return await t}finally{i=!0,clearInterval(s),await o}}async#C(e){let t={};e.prompt!==void 0&&(t.message=e.prompt),e.inputResponses!==void 0&&e.inputResponses.length>0&&(t.inputResponses=e.inputResponses);let n;try{let e=this.#t;e!==void 0&&this.#d!==void 0&&(this.#e=await this.#d.refresh({createSession:()=>e.session(),inputResponses:t.inputResponses,message:t.message,onRuntimeArtifactsChanged:()=>this.#w(),session:this.#e})),n=await this.#e.send(t)}catch(e){if(isInterruptedError(e))throw e;return this.#y=!0,{events:errorOnlyTUIStream({errorText:this.#u(e)}),turnState:createTurnState()}}let r=createTurnState();return{events:eveEventsToTUIStream({events:n,pendingInputRequests:this.#m,subagentRuns:this.#h,turnState:r,onSubagentCalled:e=>this.#O(e),onSubagentCompleted:e=>this.#A(e),onConnectionAuthRequired:e=>this.#T(e),onConnectionAuthCompleted:e=>this.#E(e),onTerminalFailure:()=>{this.#y=!0}}),turnState:r}}async#w(){let e=this.#p,t;try{t=await this.#t?.info()}catch{t=void 0}t!==void 0&&(this.#p=t,this.#f!==void 0&&this.#n.renderAgentHeader?.({info:t,name:this.#r,serverUrl:this.#f})),(!this.#n.renderAgentHeader||t===void 0)&&this.#n.renderNotice?.(formatAgentUpdateNotice(e,t))}#T(e){let t={name:e.data.name,description:e.data.description,state:`required`};e.data.authorization!==void 0&&(t.challenge=e.data.authorization),e.data.webhookUrl!==void 0&&(t.webhookUrl=e.data.webhookUrl),this.#_.set(e.data.name,t),this.#D(t)}#E(e){let t=this.#_.get(e.data.name)??{name:e.data.name,description:``,state:e.data.outcome};t.state=e.data.outcome,e.data.reason!==void 0&&(t.reason=e.data.reason),this.#_.set(e.data.name,t),this.#v.delete(e.data.name),this.#D(t),this.#n.setConnectionAuthPendingCount?.(this.#v.size)}#D(e){let t={name:e.name,description:e.description,state:e.state};e.challenge!==void 0&&(t.challenge=e.challenge),e.reason!==void 0&&(t.reason=e.reason),this.#n.upsertConnectionAuth?.(t)}#O(e){let t=e.data.callId;if(this.#g.has(t))return;let n=this.#t;if(!n)return;let i=new AbortController;this.#g.set(t,i),(async()=>{try{let r=n.session({sessionId:e.data.childSessionId,streamIndex:0}).stream({signal:i.signal});for await(let e of r)if(i.signal.aborted||(this.#j(t,e),isCurrentTurnBoundaryEvent(e)))break}catch(e){if(!isAbortLikeError(e)){let n=toErrorMessage(e),r=this.#h.get(t);if(r){let{key:e,step:i}=openCurrentSubagentSection(r);i.message=i.message?`${i.message}\n\nstream error: ${n}`:`stream error: ${n}`,i.finalized=!0,r.currentSectionKey=null,this.#n.upsertSubagentStep?.({callId:t,subagentName:r.name,sectionKey:e,reasoning:i.reasoning,message:i.message,finalized:!0})}}}finally{this.#g.delete(t)}})()}#k(e,t,n){let r=t.tools.get(n.childCallId),i=r??{toolName:n.toolName,input:n.input,status:n.status};if(r){let e={"approval-requested":0,executing:1,done:2,failed:2};e[n.status]>e[r.status]&&(r.status=n.status),r.input=n.input}else t.tools.set(n.childCallId,i);this.#n.markChildToolCallId?.(n.childCallId),this.#n.upsertSubagentTool?.({callId:e,subagentName:t.name,childCallId:n.childCallId,toolName:i.toolName,input:i.input,status:i.status})}#A(e){let t=this.#h.get(e);if(t){for(let[n,r]of t.steps)r.finalized||(r.finalized=!0,this.#n.upsertSubagentStep?.({callId:e,subagentName:t.name,sectionKey:n,reasoning:r.reasoning,message:r.message,finalized:!0}));t.currentSectionKey=null}}#j(e,t){let n=this.#h.get(e);if(!n)return;let r=this.#n,emit=(t,i)=>{r.upsertSubagentStep?.({callId:e,subagentName:n.name,sectionKey:t,reasoning:i.reasoning,message:i.message,finalized:i.finalized})},finalizeCurrent=()=>{if(n.currentSectionKey===null)return;let e=n.steps.get(n.currentSectionKey);e&&(e.finalized=!0,emit(n.currentSectionKey,e)),n.currentSectionKey=null};switch(t.type){case`reasoning.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.reasoning+=t.data.reasoningDelta,emit(e,r);break}case`reasoning.completed`:break;case`message.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.message+=t.data.messageDelta,emit(e,r);break}case`message.completed`:{let{key:e,step:r}=openCurrentSubagentSection(n);t.data.message!==null&&r.message.length===0&&(r.message=t.data.message),r.finalized=!0,emit(e,r),n.currentSectionKey=null;break}case`step.completed`:finalizeCurrent();break;case`actions.requested`:finalizeCurrent();for(let r of t.data.actions)r.kind===`tool-call`&&this.#k(e,n,{childCallId:r.callId,toolName:r.toolName,input:r.input,status:`executing`});break;case`input.requested`:finalizeCurrent();for(let r of t.data.requests)r.action.kind===`tool-call`&&this.#k(e,n,{childCallId:r.action.callId,toolName:r.action.toolName,input:r.action.input,status:`approval-requested`});break;case`action.result`:{let i=t.data.result;if(i.kind!==`tool-result`)break;let a=n.tools.get(i.callId);if(!a)break;t.data.status===`failed`?(a.status=`failed`,a.errorText=formatActionResultError(t)):(a.status=`done`,a.output=i.output);let o={callId:e,subagentName:n.name,childCallId:i.callId,toolName:a.toolName,input:a.input,status:a.status};a.output!==void 0&&(o.output=a.output),a.errorText!==void 0&&(o.errorText=a.errorText),r.upsertSubagentTool?.(o);break}default:break}}};function createRenderer(e){return e.renderer?e.renderer:new TerminalRenderer({tools:e.tools,reasoning:e.reasoning,subagents:e.subagents,connectionAuth:e.connectionAuth,assistantResponseStats:e.assistantResponseStats,contextSize:e.contextSize,logs:e.logs,input:e.userInput,output:e.screen})}function formatAgentUpdateNotice(e,t){let n=e?.agent.model.id,r=t?.agent.model.id;return n!==void 0&&r!==void 0&&n!==r?`Agent updated: Model ${n} -> ${r}`:`Agent updated.`}async function*eveEventsToTUIStream(e){let{events:t,pendingInputRequests:n,subagentRuns:r,turnState:i,onSubagentCalled:a,onSubagentCompleted:o,onConnectionAuthRequired:s,onConnectionAuthCompleted:c,onTerminalFailure:l}=e,u=new Map,d=new Map,f=0,p=new Set,m=new Set,h=new Set,g=new Set,_=!1,v=!1,y;for await(let e of t)if(!(v&&isPostTurnVisibleEvent(e)))switch(e.type){case`session.started`:case`turn.started`:case`message.received`:break;case`step.started`:f+=1,yield{type:`step-start`};break;case`step.completed`:{let t=e;y=t.data.usage,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`step-finish`,usage:t.data.usage};break}case`message.appended`:{let t=e,n=textPartId(t.data.turnId,t.data.stepIndex),r=partStateFor(u,n),i=t.data.messageSoFar;if(r.completed){if(r.text.startsWith(i)||f<=r.completedEpoch)break;r.generation+=1,r.text=``,r.completed=!1}if(!i.startsWith(r.text)||i.length<=r.text.length)break;let a=i.slice(r.text.length);r.text=i,yield{type:`assistant-delta`,id:partGenerationId(n,r.generation),delta:a};break}case`message.completed`:{let t=textPartId(e.data.turnId,e.data.stepIndex),n=partStateFor(u,t),r=e.data.message;if(n.completed){if(r===null||r===n.text||f<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=f,yield{type:`assistant-complete`,id:partGenerationId(t,n.generation),text:r};break}let i=partGenerationId(t,n.generation);if(r!==null){if(n.text.length===0)n.text=r,n.completed=!0,n.completedEpoch=f,yield{type:`assistant-complete`,id:i,text:r};else if(r.startsWith(n.text)){let e=r.slice(n.text.length);e.length>0&&(yield{type:`assistant-delta`,id:i,delta:e}),n.text=r,n.completed=!0,n.completedEpoch=f,yield{type:`assistant-complete`,id:i}}}else n.text.length>0&&(n.completed=!0,n.completedEpoch=f,yield{type:`assistant-complete`,id:i});break}case`reasoning.appended`:{let t=e,n=reasoningPartId(t.data.turnId,t.data.stepIndex),r=partStateFor(d,n),i=t.data.reasoningSoFar;if(r.completed){if(r.text.startsWith(i)||f<=r.completedEpoch)break;r.generation+=1,r.text=``,r.completed=!1}if(!i.startsWith(r.text)||i.length<=r.text.length)break;let a=i.slice(r.text.length);r.text=i,yield{type:`reasoning-delta`,id:partGenerationId(n,r.generation),delta:a};break}case`reasoning.completed`:{let t=reasoningPartId(e.data.turnId,e.data.stepIndex),n=partStateFor(d,t),r=e.data.reasoning;if(n.completed){if(r.length===0||r===n.text||n.text.startsWith(r)||f<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=f;let e=partGenerationId(t,n.generation);yield{type:`reasoning-delta`,id:e,delta:r},yield{type:`reasoning-complete`,id:e};break}let i=partGenerationId(t,n.generation);if(n.text.length===0&&r.length>0)n.text=r,yield{type:`reasoning-delta`,id:i,delta:r};else if(r.length>0&&!r.startsWith(n.text))break;n.completed=!0,n.completedEpoch=f,yield{type:`reasoning-complete`,id:i};break}case`actions.requested`:{let t=e.data,n=t.actions.filter(e=>e.kind===`tool-call`);if(n.length===0)break;let r=toolBatchKey(`actions.requested`,t.turnId,t.stepIndex,n);if(h.has(r)){for(let e of n)p.has(e.callId)||m.add(e.callId);break}h.add(r);for(let e of n)p.has(e.callId)||(p.add(e.callId),yield{type:`tool-call`,toolCallId:e.callId,toolName:e.toolName,input:e.input});break}case`input.requested`:{let t=e.data,r=t.requests.filter(e=>e.action.kind===`tool-call`);if(r.length===0)break;let a=inputRequestBatchKey(t.turnId,t.stepIndex,r);if(h.has(a)){for(let e of r)p.has(e.action.callId)||m.add(e.action.callId);break}h.add(a);for(let e of r){let t=e.action.callId;if(p.has(t)||(p.add(t),yield{type:`tool-call`,toolCallId:t,toolName:e.action.toolName,input:e.action.input}),n.set(e.requestId,e),isQuestionRequest(e)){upsertPendingQuestion(i,e);continue}upsertPendingApproval(i,e),yield{type:`tool-approval-request`,approvalId:e.requestId,toolCallId:t}}break}case`action.result`:{let t=e;if(t.data.result.kind!==`tool-result`)break;let n=t.data.result.callId;if(m.has(n)||!p.has(n))break;t.data.status===`failed`?yield{type:`tool-error`,toolCallId:n,errorText:formatActionResultError(t)}:yield{type:`tool-result`,toolCallId:n,output:t.data.result.output};break}case`step.failed`:case`turn.failed`:{let t=toFailureEvent(e,g);t&&(yield t);break}case`session.failed`:{i.sawSessionFailure=!0,l?.(e);let t=toFailureEvent(e,g);t&&(yield t),i.boundaryEvent=e.type,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`finish`,usage:y},_=!0;return}case`session.waiting`:case`session.completed`:i.boundaryEvent=e.type,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`finish`,usage:y},_=!0;return;case`turn.completed`:v=!0,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f);break;case`subagent.called`:{let t=e;if(!r.has(t.data.callId))r.set(t.data.callId,{name:t.data.name,steps:new Map,currentSectionKey:null,nextSectionKey:0,tools:new Map});else{let e=r.get(t.data.callId);e&&(e.name=t.data.name)}a?.(t);break}case`subagent.started`:case`subagent.event`:break;case`subagent.completed`:o?.(e.data.callId);break;case`authorization.required`:s?.(e);break;case`authorization.completed`:c?.(e);break;default:break}_||(yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`finish`,usage:y})}async function*errorOnlyTUIStream(e){yield{type:`error`,errorText:e.errorText},yield{type:`finish`}}function createTurnState(){return{pendingApprovals:[],pendingQuestions:[],sawSessionFailure:!1}}function upsertPendingApproval(e,t){let n=toAgentTUIToolApprovalRequest(t),r=e.pendingApprovals.findIndex(e=>e.approvalId===n.approvalId);r===-1?e.pendingApprovals.push(n):e.pendingApprovals[r]=n}function toAgentTUIToolApprovalRequest(e){return{approvalId:e.requestId,toolCallId:e.action.callId,toolName:e.action.toolName,input:e.action.input}}function upsertPendingQuestion(e,t){let n=e.pendingQuestions.findIndex(e=>e.requestId===t.requestId);n===-1?e.pendingQuestions.push(t):e.pendingQuestions[n]=t}function textPartId(e,t){return`text:${e}:${t}`}function reasoningPartId(e,t){return`reasoning:${e}:${t}`}function partStateFor(e,t){let n=e.get(t);return n===void 0&&(n={generation:0,text:``,completed:!1,completedEpoch:0},e.set(t,n)),n}function partGenerationId(e,t){return t===0?e:`${e}#${t}`}function*closeOpenParts(e,t,n){for(let[r,i]of e)i.completed||i.text.length===0||(i.completed=!0,i.completedEpoch=n,yield{type:t,id:partGenerationId(r,i.generation)})}function isPostTurnVisibleEvent(e){switch(e.type){case`action.result`:case`actions.requested`:case`authorization.completed`:case`authorization.required`:case`input.requested`:case`message.appended`:case`message.completed`:case`reasoning.appended`:case`reasoning.completed`:case`result.completed`:case`step.completed`:case`step.failed`:case`step.started`:case`subagent.called`:case`subagent.completed`:case`subagent.event`:case`subagent.started`:case`turn.completed`:case`turn.failed`:return!0;default:return!1}}function toolBatchKey(e,t,n,r){return`${e}:${t}:${String(n)}:${stableStringify(r.map(e=>({input:e.input,toolName:e.toolName})))}`}function inputRequestBatchKey(e,t,n){return toolBatchKey(`input.requested`,e,t,n.map(e=>({input:e.action.input,toolName:e.action.toolName})))}function stableStringify(e){return JSON.stringify(toStableJson(e))??`undefined`}function toStableJson(e,t=new WeakSet){if(typeof e!=`object`||!e)return e;if(t.has(e))return`[Circular]`;if(t.add(e),Array.isArray(e))return e.map(e=>toStableJson(e,t));let n=e,r={};for(let e of Object.keys(n).sort())r[e]=toStableJson(n[e],t);return r}function formatActionResultError(e){if(e.data.error?.message)return e.data.error.message;let t=e.data.result.output;if(typeof t==`string`)return t;try{return JSON.stringify(t)}catch{return`Tool execution failed.`}}function toFailureEvent(r,i){let a=failureKey(r);if(i.has(a))return;i.add(a);let o={type:`error`,errorText:formatFailureMessage(r)},s=formatFailureDetail(r);return s!==void 0&&(o.detail=s),o}function isQuestionRequest(e){return e.display===`select`||e.display===`text`?!0:e.display===`confirmation`?!1:e.options!==void 0&&e.options.length>0}function toAgentTUIInputQuestion(e){let t=e.display===`text`?`text`:e.display===`select`||e.options!==void 0&&e.options.length>0?`select`:`text`,n={requestId:e.requestId,prompt:e.prompt,display:t};return e.options!==void 0&&(n.options=e.options.map(e=>{let t={id:e.id,label:e.label};return e.description!==void 0&&(t.description=e.description),e.style!==void 0&&(t.style=e.style),t})),e.allowFreeform!==void 0&&(n.allowFreeform=e.allowFreeform),n}function parsePromptCommand(e){let t=e.trim();return t===`/new`?`new`:t===`/exit`||t===`/quit`?`exit`:null}function openCurrentSubagentSection(e){e.currentSectionKey===null&&(e.currentSectionKey=e.nextSectionKey++,e.steps.set(e.currentSectionKey,{reasoning:``,message:``,finalized:!1}));let t=e.steps.get(e.currentSectionKey);if(!t)throw Error(`invariant: subagent section state missing for current key`);return{key:e.currentSectionKey,step:t}}export{EveTUIRunner};
|
|
1
|
+
import{failureKey,formatFailureDetail,formatFailureMessage,isAbortLikeError,isInterruptedError}from"./errors.js";import{TerminalRenderer}from"./terminal-renderer.js";import{toErrorMessage}from"#shared/errors.js";import{createDevelopmentRuntimeArtifactSessionRefresher}from"#services/dev-client.js";import{isCurrentTurnBoundaryEvent}from"#client/index.js";var EveTUIRunner=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u;#d;#f;#p;#m=0;#h;#g=new Map;#_=new Map;#v=new Map;#y=new Map;#b=new Set;#x=!1;constructor(e){this.#e=e.session,e.client!==void 0&&(this.#t=e.client),this.#n=createRenderer(e),this.#r=e.name??`Eve`,this.#i=e.tools??`full`,this.#a=e.reasoning??`full`,this.#o=e.subagents??`full`,this.#s=e.connectionAuth??`full`,this.#c=e.assistantResponseStats??`tokensPerSecond`,this.#l=e.contextSize,this.#u=e.formatTransportError??toErrorMessage,e.serverUrl!==void 0&&(this.#f=e.serverUrl,this.#d=createDevelopmentRuntimeArtifactSessionRefresher({serverUrl:e.serverUrl})),e.modelCommand!==void 0&&(this.#p=e.modelCommand)}async#S(){if(!this.#n.renderAgentHeader)return;let e=this.#f;if(e===void 0)return;let t;try{t=await this.#t?.info()}catch{t=void 0}this.#h=t;let n={name:this.#r,serverUrl:e};t!==void 0&&(n.info=t),this.#n.renderAgentHeader(n)}async run(){let e=this.#r,t,n,r=!1,a=!1;for(await this.#S();;){if(!a){if(t==null){if(!this.#n.readPrompt){if(r)return;throw Error(`No prompt was provided and the renderer does not support prompt input.`)}try{t=await this.#E({title:e})}catch(e){if(isInterruptedError(e))return;throw e}if(t==null)return}let o=parsePromptCommand(t);if(o?.type===`exit`){this.#n.shutdown?.();return}if(o?.type===`new`){this.#C(),n=void 0,a=!1,t=void 0,this.#n.reset?.();continue}if(o?.type===`model`){try{await this.#w(o.slug)}catch(e){if(isInterruptedError(e))return;throw e}t=void 0,a=!1;continue}r=!0}let o=await this.#D({prompt:a?void 0:t,inputResponses:n});try{await this.#n.renderStream(o,{title:e,submittedPrompt:t,continueSession:!!this.#n.readPrompt,tools:this.#i,reasoning:this.#a,subagents:this.#o,connectionAuth:this.#s,assistantResponseStats:this.#c,contextSize:this.#l});let r=o.turnState?.pendingApprovals??[],i=o.turnState?.pendingQuestions??[];if(r.length>0||i.length>0){let o=[];if(r.length>0){if(!this.#n.readToolApproval)throw Error(`Tool approval was requested, but the renderer does not support tool approval input.`);for(let t of r){let n=await this.#n.readToolApproval(t,{title:e});o.push({requestId:t.approvalId,optionId:n.approved?`approve`:`deny`}),this.#g.delete(t.approvalId)}}if(i.length>0){if(!this.#n.readInputQuestion)throw Error(`An interactive question was requested, but the renderer does not support input questions.`);for(let t of i){let n=toAgentTUIInputQuestion(t),r=await this.#n.readInputQuestion(n,{title:e});if(r===void 0)continue;let i={requestId:t.requestId};r.optionId!==void 0&&(i.optionId=r.optionId),r.text!==void 0&&(i.text=r.text),o.push(i),this.#g.delete(t.requestId)}}a=!0,n=o,t=void 0;continue}o.turnState&&o.turnState.boundaryEvent===void 0&&(this.#x=!0)}catch(e){if(isInterruptedError(e))return;throw e}a=!1,n=void 0,t=void 0,this.#x&&(this.#x=!1,this.#C(),this.#n.renderNotice?.(`Session ended — started a new session. Earlier context was cleared.`))}}#C(){for(let e of this.#v.values())e.abort();this.#v.clear(),this.#_.clear(),this.#g.clear(),this.#y.clear(),this.#b.clear(),this.#t&&(this.#e=this.#t.session()),this.#d?.clear()}async#w(e){let t=this.#p;if(t===void 0){this.#n.renderNotice?.(`Changing the model isn't available in this session.`);return}let n=e;if(n.length===0){let e=await this.#T(t);if(e===void 0)return;n=e}try{this.#n.renderNotice?.(await t.apply(n))}catch(e){this.#n.renderNotice?.(`Couldn't change the model: ${toErrorMessage(e)}`)}}async#T(e){if(this.#n.readInputQuestion===void 0){this.#n.renderNotice?.(`Usage: /model <provider/model-id>`);return}let t=await e.listChoices();this.#m+=1;let n={requestId:`model-command-${this.#m}`,prompt:`Select a model`,display:`select`,options:t.map(e=>({id:e.id,label:e.label})),allowFreeform:!0},r=await this.#n.readInputQuestion(n,{title:this.#r});return r?.text??r?.optionId}async#E(e){if(!this.#n.readPrompt)return;let t=this.#n.readPrompt(e),n=this.#t,r=this.#d;if(n===void 0||r===void 0)return await t;let i=!1,a=!1,o,refresh=async()=>{if(!(i||a)){a=!0;try{this.#e=await r.refreshIdle({createSession:()=>n.session(),onRuntimeArtifactsChanged:()=>this.#O(),session:this.#e})}finally{a=!1}}},startRefresh=()=>{if(i||a)return;let e=refresh().finally(()=>{o===e&&(o=void 0)});o=e};startRefresh();let s=setInterval(()=>{startRefresh()},500);s.unref?.();try{return await t}finally{i=!0,clearInterval(s),await o}}async#D(e){let t={};e.prompt!==void 0&&(t.message=e.prompt),e.inputResponses!==void 0&&e.inputResponses.length>0&&(t.inputResponses=e.inputResponses);let n;try{let e=this.#t;e!==void 0&&this.#d!==void 0&&(this.#e=await this.#d.refresh({createSession:()=>e.session(),inputResponses:t.inputResponses,message:t.message,onRuntimeArtifactsChanged:()=>this.#O(),session:this.#e})),n=await this.#e.send(t)}catch(e){if(isInterruptedError(e))throw e;return this.#x=!0,{events:errorOnlyTUIStream({errorText:this.#u(e)}),turnState:createTurnState()}}let r=createTurnState();return{events:eveEventsToTUIStream({events:n,pendingInputRequests:this.#g,subagentRuns:this.#_,turnState:r,onSubagentCalled:e=>this.#M(e),onSubagentCompleted:e=>this.#P(e),onConnectionAuthRequired:e=>this.#k(e),onConnectionAuthCompleted:e=>this.#A(e),onTerminalFailure:()=>{this.#x=!0}}),turnState:r}}async#O(){let e=this.#h,t;try{t=await this.#t?.info()}catch{t=void 0}t!==void 0&&(this.#h=t,this.#f!==void 0&&this.#n.renderAgentHeader?.({info:t,name:this.#r,serverUrl:this.#f})),(!this.#n.renderAgentHeader||t===void 0)&&this.#n.renderNotice?.(formatAgentUpdateNotice(e,t))}#k(e){let t={name:e.data.name,description:e.data.description,state:`required`};e.data.authorization!==void 0&&(t.challenge=e.data.authorization),e.data.webhookUrl!==void 0&&(t.webhookUrl=e.data.webhookUrl),this.#y.set(e.data.name,t),this.#j(t)}#A(e){let t=this.#y.get(e.data.name)??{name:e.data.name,description:``,state:e.data.outcome};t.state=e.data.outcome,e.data.reason!==void 0&&(t.reason=e.data.reason),this.#y.set(e.data.name,t),this.#b.delete(e.data.name),this.#j(t),this.#n.setConnectionAuthPendingCount?.(this.#b.size)}#j(e){let t={name:e.name,description:e.description,state:e.state};e.challenge!==void 0&&(t.challenge=e.challenge),e.reason!==void 0&&(t.reason=e.reason),this.#n.upsertConnectionAuth?.(t)}#M(e){let t=e.data.callId;if(this.#v.has(t))return;let n=this.#t;if(!n)return;let i=new AbortController;this.#v.set(t,i),(async()=>{try{let r=n.session({sessionId:e.data.childSessionId,streamIndex:0}).stream({signal:i.signal});for await(let e of r)if(i.signal.aborted||(this.#F(t,e),isCurrentTurnBoundaryEvent(e)))break}catch(e){if(!isAbortLikeError(e)){let n=toErrorMessage(e),r=this.#_.get(t);if(r){let{key:e,step:i}=openCurrentSubagentSection(r);i.message=i.message?`${i.message}\n\nstream error: ${n}`:`stream error: ${n}`,i.finalized=!0,r.currentSectionKey=null,this.#n.upsertSubagentStep?.({callId:t,subagentName:r.name,sectionKey:e,reasoning:i.reasoning,message:i.message,finalized:!0})}}}finally{this.#v.delete(t)}})()}#N(e,t,n){let r=t.tools.get(n.childCallId),i=r??{toolName:n.toolName,input:n.input,status:n.status};if(r){let e={"approval-requested":0,executing:1,done:2,failed:2};e[n.status]>e[r.status]&&(r.status=n.status),r.input=n.input}else t.tools.set(n.childCallId,i);this.#n.markChildToolCallId?.(n.childCallId),this.#n.upsertSubagentTool?.({callId:e,subagentName:t.name,childCallId:n.childCallId,toolName:i.toolName,input:i.input,status:i.status})}#P(e){let t=this.#_.get(e);if(t){for(let[n,r]of t.steps)r.finalized||(r.finalized=!0,this.#n.upsertSubagentStep?.({callId:e,subagentName:t.name,sectionKey:n,reasoning:r.reasoning,message:r.message,finalized:!0}));t.currentSectionKey=null}}#F(e,t){let n=this.#_.get(e);if(!n)return;let r=this.#n,emit=(t,i)=>{r.upsertSubagentStep?.({callId:e,subagentName:n.name,sectionKey:t,reasoning:i.reasoning,message:i.message,finalized:i.finalized})},finalizeCurrent=()=>{if(n.currentSectionKey===null)return;let e=n.steps.get(n.currentSectionKey);e&&(e.finalized=!0,emit(n.currentSectionKey,e)),n.currentSectionKey=null};switch(t.type){case`reasoning.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.reasoning+=t.data.reasoningDelta,emit(e,r);break}case`reasoning.completed`:break;case`message.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.message+=t.data.messageDelta,emit(e,r);break}case`message.completed`:{let{key:e,step:r}=openCurrentSubagentSection(n);t.data.message!==null&&r.message.length===0&&(r.message=t.data.message),r.finalized=!0,emit(e,r),n.currentSectionKey=null;break}case`step.completed`:finalizeCurrent();break;case`actions.requested`:finalizeCurrent();for(let r of t.data.actions)r.kind===`tool-call`&&this.#N(e,n,{childCallId:r.callId,toolName:r.toolName,input:r.input,status:`executing`});break;case`input.requested`:finalizeCurrent();for(let r of t.data.requests)r.action.kind===`tool-call`&&this.#N(e,n,{childCallId:r.action.callId,toolName:r.action.toolName,input:r.action.input,status:`approval-requested`});break;case`action.result`:{let i=t.data.result;if(i.kind!==`tool-result`)break;let a=n.tools.get(i.callId);if(!a)break;t.data.status===`failed`?(a.status=`failed`,a.errorText=formatActionResultError(t)):(a.status=`done`,a.output=i.output);let o={callId:e,subagentName:n.name,childCallId:i.callId,toolName:a.toolName,input:a.input,status:a.status};a.output!==void 0&&(o.output=a.output),a.errorText!==void 0&&(o.errorText=a.errorText),r.upsertSubagentTool?.(o);break}default:break}}};function createRenderer(e){return e.renderer?e.renderer:new TerminalRenderer({tools:e.tools,reasoning:e.reasoning,subagents:e.subagents,connectionAuth:e.connectionAuth,assistantResponseStats:e.assistantResponseStats,contextSize:e.contextSize,logs:e.logs,input:e.userInput,output:e.screen})}function formatAgentUpdateNotice(e,t){let n=e?.agent.model.id,r=t?.agent.model.id;return n!==void 0&&r!==void 0&&n!==r?`Agent updated: Model ${n} -> ${r}`:`Agent updated.`}async function*eveEventsToTUIStream(e){let{events:t,pendingInputRequests:n,subagentRuns:r,turnState:i,onSubagentCalled:a,onSubagentCompleted:o,onConnectionAuthRequired:s,onConnectionAuthCompleted:c,onTerminalFailure:l}=e,u=new Map,d=new Map,f=0,p=new Set,m=new Set,h=new Set,g=new Set,_=!1,v=!1,y;for await(let e of t)if(!(v&&isPostTurnVisibleEvent(e)))switch(e.type){case`session.started`:case`turn.started`:case`message.received`:break;case`step.started`:f+=1,yield{type:`step-start`};break;case`step.completed`:{let t=e;y=t.data.usage,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`step-finish`,usage:t.data.usage};break}case`message.appended`:{let t=e,n=textPartId(t.data.turnId,t.data.stepIndex),r=partStateFor(u,n),i=t.data.messageSoFar;if(r.completed){if(r.text.startsWith(i)||f<=r.completedEpoch)break;r.generation+=1,r.text=``,r.completed=!1}if(!i.startsWith(r.text)||i.length<=r.text.length)break;let a=i.slice(r.text.length);r.text=i,yield{type:`assistant-delta`,id:partGenerationId(n,r.generation),delta:a};break}case`message.completed`:{let t=textPartId(e.data.turnId,e.data.stepIndex),n=partStateFor(u,t),r=e.data.message;if(n.completed){if(r===null||r===n.text||f<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=f,yield{type:`assistant-complete`,id:partGenerationId(t,n.generation),text:r};break}let i=partGenerationId(t,n.generation);if(r!==null){if(n.text.length===0)n.text=r,n.completed=!0,n.completedEpoch=f,yield{type:`assistant-complete`,id:i,text:r};else if(r.startsWith(n.text)){let e=r.slice(n.text.length);e.length>0&&(yield{type:`assistant-delta`,id:i,delta:e}),n.text=r,n.completed=!0,n.completedEpoch=f,yield{type:`assistant-complete`,id:i}}}else n.text.length>0&&(n.completed=!0,n.completedEpoch=f,yield{type:`assistant-complete`,id:i});break}case`reasoning.appended`:{let t=e,n=reasoningPartId(t.data.turnId,t.data.stepIndex),r=partStateFor(d,n),i=t.data.reasoningSoFar;if(r.completed){if(r.text.startsWith(i)||f<=r.completedEpoch)break;r.generation+=1,r.text=``,r.completed=!1}if(!i.startsWith(r.text)||i.length<=r.text.length)break;let a=i.slice(r.text.length);r.text=i,yield{type:`reasoning-delta`,id:partGenerationId(n,r.generation),delta:a};break}case`reasoning.completed`:{let t=reasoningPartId(e.data.turnId,e.data.stepIndex),n=partStateFor(d,t),r=e.data.reasoning;if(n.completed){if(r.length===0||r===n.text||n.text.startsWith(r)||f<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=f;let e=partGenerationId(t,n.generation);yield{type:`reasoning-delta`,id:e,delta:r},yield{type:`reasoning-complete`,id:e};break}let i=partGenerationId(t,n.generation);if(n.text.length===0&&r.length>0)n.text=r,yield{type:`reasoning-delta`,id:i,delta:r};else if(r.length>0&&!r.startsWith(n.text))break;n.completed=!0,n.completedEpoch=f,yield{type:`reasoning-complete`,id:i};break}case`actions.requested`:{let t=e.data,n=t.actions.filter(e=>e.kind===`tool-call`);if(n.length===0)break;let r=toolBatchKey(`actions.requested`,t.turnId,t.stepIndex,n);if(h.has(r)){for(let e of n)p.has(e.callId)||m.add(e.callId);break}h.add(r);for(let e of n)p.has(e.callId)||(p.add(e.callId),yield{type:`tool-call`,toolCallId:e.callId,toolName:e.toolName,input:e.input});break}case`input.requested`:{let t=e.data,r=t.requests.filter(e=>e.action.kind===`tool-call`);if(r.length===0)break;let a=inputRequestBatchKey(t.turnId,t.stepIndex,r);if(h.has(a)){for(let e of r)p.has(e.action.callId)||m.add(e.action.callId);break}h.add(a);for(let e of r){let t=e.action.callId;if(p.has(t)||(p.add(t),yield{type:`tool-call`,toolCallId:t,toolName:e.action.toolName,input:e.action.input}),n.set(e.requestId,e),isQuestionRequest(e)){upsertPendingQuestion(i,e);continue}upsertPendingApproval(i,e),yield{type:`tool-approval-request`,approvalId:e.requestId,toolCallId:t}}break}case`action.result`:{let t=e;if(t.data.result.kind!==`tool-result`)break;let n=t.data.result.callId;if(m.has(n)||!p.has(n))break;t.data.status===`failed`?yield{type:`tool-error`,toolCallId:n,errorText:formatActionResultError(t)}:yield{type:`tool-result`,toolCallId:n,output:t.data.result.output};break}case`step.failed`:case`turn.failed`:{let t=toFailureEvent(e,g);t&&(yield t);break}case`session.failed`:{i.sawSessionFailure=!0,l?.(e);let t=toFailureEvent(e,g);t&&(yield t),i.boundaryEvent=e.type,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`finish`,usage:y},_=!0;return}case`session.waiting`:case`session.completed`:i.boundaryEvent=e.type,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`finish`,usage:y},_=!0;return;case`turn.completed`:v=!0,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f);break;case`subagent.called`:{let t=e;if(!r.has(t.data.callId))r.set(t.data.callId,{name:t.data.name,steps:new Map,currentSectionKey:null,nextSectionKey:0,tools:new Map});else{let e=r.get(t.data.callId);e&&(e.name=t.data.name)}a?.(t);break}case`subagent.started`:case`subagent.event`:break;case`subagent.completed`:o?.(e.data.callId);break;case`authorization.required`:s?.(e);break;case`authorization.completed`:c?.(e);break;default:break}_||(yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`finish`,usage:y})}async function*errorOnlyTUIStream(e){yield{type:`error`,errorText:e.errorText},yield{type:`finish`}}function createTurnState(){return{pendingApprovals:[],pendingQuestions:[],sawSessionFailure:!1}}function upsertPendingApproval(e,t){let n=toAgentTUIToolApprovalRequest(t),r=e.pendingApprovals.findIndex(e=>e.approvalId===n.approvalId);r===-1?e.pendingApprovals.push(n):e.pendingApprovals[r]=n}function toAgentTUIToolApprovalRequest(e){return{approvalId:e.requestId,toolCallId:e.action.callId,toolName:e.action.toolName,input:e.action.input}}function upsertPendingQuestion(e,t){let n=e.pendingQuestions.findIndex(e=>e.requestId===t.requestId);n===-1?e.pendingQuestions.push(t):e.pendingQuestions[n]=t}function textPartId(e,t){return`text:${e}:${t}`}function reasoningPartId(e,t){return`reasoning:${e}:${t}`}function partStateFor(e,t){let n=e.get(t);return n===void 0&&(n={generation:0,text:``,completed:!1,completedEpoch:0},e.set(t,n)),n}function partGenerationId(e,t){return t===0?e:`${e}#${t}`}function*closeOpenParts(e,t,n){for(let[r,i]of e)i.completed||i.text.length===0||(i.completed=!0,i.completedEpoch=n,yield{type:t,id:partGenerationId(r,i.generation)})}function isPostTurnVisibleEvent(e){switch(e.type){case`action.result`:case`actions.requested`:case`authorization.completed`:case`authorization.required`:case`input.requested`:case`message.appended`:case`message.completed`:case`reasoning.appended`:case`reasoning.completed`:case`result.completed`:case`step.completed`:case`step.failed`:case`step.started`:case`subagent.called`:case`subagent.completed`:case`subagent.event`:case`subagent.started`:case`turn.completed`:case`turn.failed`:return!0;default:return!1}}function toolBatchKey(e,t,n,r){return`${e}:${t}:${String(n)}:${stableStringify(r.map(e=>({input:e.input,toolName:e.toolName})))}`}function inputRequestBatchKey(e,t,n){return toolBatchKey(`input.requested`,e,t,n.map(e=>({input:e.action.input,toolName:e.action.toolName})))}function stableStringify(e){return JSON.stringify(toStableJson(e))??`undefined`}function toStableJson(e,t=new WeakSet){if(typeof e!=`object`||!e)return e;if(t.has(e))return`[Circular]`;if(t.add(e),Array.isArray(e))return e.map(e=>toStableJson(e,t));let n=e,r={};for(let e of Object.keys(n).sort())r[e]=toStableJson(n[e],t);return r}function formatActionResultError(e){if(e.data.error?.message)return e.data.error.message;let t=e.data.result.output;if(typeof t==`string`)return t;try{return JSON.stringify(t)}catch{return`Tool execution failed.`}}function toFailureEvent(r,i){let a=failureKey(r);if(i.has(a))return;i.add(a);let o={type:`error`,errorText:formatFailureMessage(r)},s=formatFailureDetail(r);return s!==void 0&&(o.detail=s),o}function isQuestionRequest(e){return e.display===`select`||e.display===`text`?!0:e.display===`confirmation`?!1:e.options!==void 0&&e.options.length>0}function toAgentTUIInputQuestion(e){let t=e.display===`text`?`text`:e.display===`select`||e.options!==void 0&&e.options.length>0?`select`:`text`,n={requestId:e.requestId,prompt:e.prompt,display:t};return e.options!==void 0&&(n.options=e.options.map(e=>{let t={id:e.id,label:e.label};return e.description!==void 0&&(t.description=e.description),e.style!==void 0&&(t.style=e.style),t})),e.allowFreeform!==void 0&&(n.allowFreeform=e.allowFreeform),n}function parsePromptCommand(e){let t=e.trim();return t===`/new`?{type:`new`}:t===`/exit`||t===`/quit`?{type:`exit`}:t===`/model`||t.startsWith(`/model `)?{type:`model`,slug:t.slice(6).trim()}:null}function openCurrentSubagentSection(e){e.currentSectionKey===null&&(e.currentSectionKey=e.nextSectionKey++,e.steps.set(e.currentSectionKey,{reasoning:``,message:``,finalized:!1}));let t=e.steps.get(e.currentSectionKey);if(!t)throw Error(`invariant: subagent section state missing for current key`);return{key:e.currentSectionKey,step:t}}export{EveTUIRunner,parsePromptCommand};
|
|
@@ -9,6 +9,12 @@ export interface RunDevelopmentTuiInput extends TuiDisplayOptions {
|
|
|
9
9
|
* server started by `eve dev`, or a remote `--url` target.
|
|
10
10
|
*/
|
|
11
11
|
readonly serverUrl: string;
|
|
12
|
+
/**
|
|
13
|
+
* Absolute application root. When present and the server is a local dev
|
|
14
|
+
* server, enables the TUI's `/model` command to edit local agent source.
|
|
15
|
+
* Omitted for remote (`--url`) targets.
|
|
16
|
+
*/
|
|
17
|
+
readonly appRoot?: string;
|
|
12
18
|
}
|
|
13
19
|
/**
|
|
14
20
|
* Builds the client options the `eve dev` TUI connects with, matching the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EveTUIRunner}from"./runner.js";import{toErrorMessage}from"#shared/errors.js";import{isLocalDevelopmentServerUrl,resolveDevelopmentClientHeaders,resolveDevelopmentOidcToken}from"#services/dev-client/request-headers.js";import{formatVercelAuthChallengeMessage,isVercelAuthChallenge}from"#services/dev-client/vercel-auth-error.js";import{Client}from"#client/index.js";function resolveDevTuiClientOptions(e){let t={headers:()=>resolveDevelopmentClientHeaders({serverUrl:e}),host:e};return isLocalDevelopmentServerUrl(e)?t:{...t,auth:{bearer:resolveDevelopmentOidcToken}}}async function runDevelopmentTui(n){let{serverUrl:r,...
|
|
1
|
+
import{EveTUIRunner}from"./runner.js";import{toErrorMessage}from"#shared/errors.js";import{isLocalDevelopmentServerUrl,resolveDevelopmentClientHeaders,resolveDevelopmentOidcToken}from"#services/dev-client/request-headers.js";import{formatVercelAuthChallengeMessage,isVercelAuthChallenge}from"#services/dev-client/vercel-auth-error.js";import{Client}from"#client/index.js";import{changeAgentModel,hydrateCuratedModels,listAgentModelChoices}from"#cli/dev/change-agent-model.js";function resolveDevTuiClientOptions(e){let t={headers:()=>resolveDevelopmentClientHeaders({serverUrl:e}),host:e};return isLocalDevelopmentServerUrl(e)?t:{...t,auth:{bearer:resolveDevelopmentOidcToken}}}async function runDevelopmentTui(n){let{serverUrl:r,appRoot:i,...a}=n,o=new Client(resolveDevTuiClientOptions(r)),s={...a,session:o.session(),client:o,serverUrl:r,formatTransportError:e=>isVercelAuthChallenge(e)?formatVercelAuthChallengeMessage({serverUrl:r}):toErrorMessage(e)};if(i!==void 0&&isLocalDevelopmentServerUrl(r)){let e=await hydrateCuratedModels(i);s.modelCommand={listChoices:()=>listAgentModelChoices(i,e),apply:e=>changeAgentModel({appRoot:i,slug:e})}}await new EveTUIRunner(s).run()}export{resolveDevTuiClientOptions,runDevelopmentTui};
|
package/dist/src/cli/run.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ interface CliRuntimeDependencies {
|
|
|
37
37
|
}): Promise<void>;
|
|
38
38
|
runDevelopmentTui(input: {
|
|
39
39
|
serverUrl: string;
|
|
40
|
+
appRoot?: string;
|
|
40
41
|
} & TuiDisplayOptions): Promise<void>;
|
|
41
42
|
runEvalCommand(evalIds: readonly string[], options: EvalCliOptions, logger: CliLogger): Promise<void>;
|
|
42
43
|
startHost(appRoot: string, options?: {
|
package/dist/src/cli/run.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import{basename}from"node:path";import{createCliTheme,renderCliTaggedLine}from"#cli/ui/output.js";import{Command,CommanderError,InvalidArgumentError}from"#compiled/commander/index.js";import{resolveApplicationRoot}from"#internal/application/paths.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{parseDevelopmentServerUrl}from"#cli/dev/url.js";async function loadBuildHost(){return(await import(`#internal/nitro/host.js`)).buildApplication}async function loadPrintApplicationInfo(){return(await import(`#cli/commands/info.js`)).printApplicationInfo}async function loadRunDevelopmentRepl(){return(await import(`#cli/dev/repl/repl.js`)).runDevelopmentRepl}async function loadRunDevelopmentTui(){return(await import(`#cli/dev/tui/tui.js`)).runDevelopmentTui}async function loadRunEvalCommand(){return(await import(`#evals/cli/eval.js`)).runEvalCommand}async function loadStartHost(){return(await import(`#internal/nitro/host.js`)).startDevelopmentServer}async function loadStartProductionHost(){return(await import(`#internal/nitro/host.js`)).startProductionServer}function shouldPrintCliBootBanner(e){return e.name()===`info`||e.name()===`dev`}async function waitForShutdownSignal(e){await new Promise((t,n)=>{let r=!1,cleanup=()=>{process.off(`SIGINT`,handleSignal),process.off(`SIGTERM`,handleSignal)},handleSignal=()=>{r||(r=!0,cleanup(),e.close().then(t,n))};process.once(`SIGINT`,handleSignal),process.once(`SIGTERM`,handleSignal)})}async function waitForProductionServer(e){await Promise.race([e.wait(),waitForShutdownSignal({close:()=>e.close()})])}function parsePortOption(e){if(!/^-?\d+$/.test(e))throw new InvalidArgumentError(`Expected a numeric port, received "${e}".`);let t=Number(e);if(t<0||t>65535)throw new InvalidArgumentError(`Expected a port between 0 and 65535, received "${e}".`);return t}const DISPLAY_MODES=new Set([`full`,`collapsed`,`auto-collapsed`,`hidden`]),STATS_MODES=new Set([`tokens`,`tokensPerSecond`]),LOG_MODES=new Set([`all`,`stderr`,`none`]);function parseDisplayMode(e){if(!DISPLAY_MODES.has(e))throw new InvalidArgumentError(`Expected one of ${[...DISPLAY_MODES].join(`, `)}, received "${e}".`);return e}function parseStatsMode(e){if(!STATS_MODES.has(e))throw new InvalidArgumentError(`Expected one of ${[...STATS_MODES].join(`, `)}, received "${e}".`);return e}function parseLogsMode(e){if(!LOG_MODES.has(e))throw new InvalidArgumentError(`Expected one of ${[...LOG_MODES].join(`, `)}, received "${e}".`);return e}function parseContextSizeOption(e){let t=Number(e);if(!Number.isFinite(t)||t<=0)throw new InvalidArgumentError(`Expected a positive number, received "${e}".`);return t}function resolveDevUiMode(e){return e.options.ui===!1||!e.interactive?`headless`:e.options.repl===!0?`repl`:`tui`}function resolveTuiTitle(t){if(t.name!==void 0&&t.name.length>0)return t.name;if(t.remoteServerUrl!==void 0)try{return new URL(t.remoteServerUrl).host}catch{return}let n=humanizeProjectName(basename(t.appRoot));return n.length>0?n:void 0}function humanizeProjectName(e){return e.replace(/[-_.]+/gu,` `).trim().split(/\s+/u).filter(e=>e.length>0).map(e=>e[0].toUpperCase()+e.slice(1)).join(` `)}function resolveTuiDisplayOptions(e){let t={reasoning:e.reasoning??`full`,tools:e.tools??`auto-collapsed`};return e.subagents!==void 0&&(t.subagents=e.subagents),e.connectionAuth!==void 0&&(t.connectionAuth=e.connectionAuth),e.assistantResponseStats!==void 0&&(t.assistantResponseStats=e.assistantResponseStats),e.contextSize!==void 0&&(t.contextSize=e.contextSize),e.logs!==void 0&&(t.logs=e.logs),t}function hasInteractiveTerminal(){return!!(process.stdin.isTTY&&process.stdout.isTTY)}function rewriteDeprecatedReplFlag(e){return e[0]===`dev`?e.map(e=>e===`--no-repl`?`--no-ui`:e):[...e]}function rewriteDevelopmentUrlShorthand(e){let t=e[1];return e[0]!==`dev`||e.length!==2||t===void 0||t.startsWith(`-`)?[...e]:[`dev`,`--url`,t]}function resolveRemoteDevelopmentServerUrl(e){if(e.url){if(e.host!==void 0)throw new InvalidArgumentError(`The --host option cannot be used with --url.`);if(e.port!==void 0)throw new InvalidArgumentError(`The --port option cannot be used with --url.`);if(e.ui===!1)throw new InvalidArgumentError(`The --no-ui option cannot be used with --url.`);return e.url}}function createCliProgram(e,i){let a=resolveApplicationRoot(),l=resolveInstalledPackageInfo().version,u=new Command,d=createCliTheme();u.name(`eve`).description(`Build and run an Eve application.`).version(l).showHelpAfterError().exitOverride().hook(`preAction`,(t,n)=>{shouldPrintCliBootBanner(n)&&e.log(`Eve (v${l})`)}).configureOutput({writeErr:t=>{e.error(t.trimEnd())},writeOut:t=>{e.log(t.trimEnd())}});let f=u.command(`channels`).description(`Manage user-authored channels in the current project.`);return f.command(`add [kind]`).description(`Add channels interactively, or scaffold a channel kind (slack | web).`).option(`-f, --force`,`Overwrite existing channel files`).option(`-y, --yes`,`Assume yes for confirmations; requires an explicit channel kind`).action(async(t,n)=>{let{runChannelsAddCommand:r}=await import(`#cli/commands/channels.js`);await r(e,a,{kind:t,options:n})}),f.command(`list`).description(`List user-authored channels in the current project.`).option(`--json`,`Output as JSON`).action(async t=>{let{runChannelsListCommand:n}=await import(`#cli/commands/channels.js`);await n(e,a,t)}),u.command(`setup`).description(`Create or set up an Eve agent in the current directory (unified flow).`).action(async()=>{let{runSetupCommand:t}=await import(`#cli/commands/setup.js`);await t(e,a,{})}),u.command(`build`).description(`Build the current Eve application.`).action(async()=>{let{loadDevelopmentEnvironmentFiles:t}=await import(`#cli/dev/environment.js`);t(a);let r=await(i.buildHost??await loadBuildHost())(a);e.log(renderCliTaggedLine(d,{message:`built output at ${r}`,tag:`build`,tone:`success`}))}),u.command(`start`).description(`Start a built Eve application.`).option(`--host <host>`,`Host interface to bind`).option(`--port <port>`,`Port to listen on (defaults to $PORT, then 3000)`,parsePortOption).action(async t=>{let{loadDevelopmentEnvironmentFiles:r}=await import(`#cli/dev/environment.js`);r(a);let o=await(i.startProductionHost??await loadStartProductionHost())(a,{host:t.host,port:t.port});e.log(renderCliTaggedLine(d,{message:`server listening at ${o.url}`,tag:`start`,tone:`success`})),await waitForProductionServer(o)}),u.command(`dev`).description(`Start the Eve development server or connect to an existing URL.`).option(`--host <host>`,`Host interface to bind`).option(`--port <port>`,`Port to listen on (defaults to $PORT, then 3000)`,parsePortOption).option(`-u, --url <url>`,`Connect to an existing server URL`,parseDevelopmentServerUrl).option(`--repl`,`Use the classic line-based REPL instead of the default terminal UI`).option(`--no-ui`,`Start the server without an interactive UI`).option(`--name <name>`,`Title shown in the terminal UI (defaults to the app folder name)`).option(`--tools <mode>`,`How tool calls render: full | collapsed | auto-collapsed | hidden`,parseDisplayMode).option(`--reasoning <mode>`,`How reasoning renders: full | collapsed | auto-collapsed | hidden`,parseDisplayMode).option(`--subagents <mode>`,`How subagent sections render: full | collapsed | auto-collapsed | hidden`,parseDisplayMode).option(`--connection-auth <mode>`,`How connection authorization renders: full | collapsed | auto-collapsed | hidden`,parseDisplayMode).option(`--assistant-response-stats <mode>`,`Assistant header statistic: tokens | tokensPerSecond`,parseStatsMode).option(`--context-size <tokens>`,`Model context window size, shown as a usage percentage`,parseContextSizeOption).option(`--logs <mode>`,`Which server/agent logs to show: all | stderr | none`,parseLogsMode).addHelpText(`after`,`
|
|
2
2
|
You can also pass a bare URL as the only argument, for example: eve dev https://example.com
|
|
3
|
-
`).action(async t=>{let r=resolveRemoteDevelopmentServerUrl(t),{loadDevelopmentEnvironmentFiles:o}=await import(`#cli/dev/environment.js`);o(a);let runInteractiveUi=async(n,o)=>{if(e.log(``),o===`repl`){await(i.runDevelopmentRepl??await loadRunDevelopmentRepl())({serverUrl:n});return}let s=i.runDevelopmentTui??await loadRunDevelopmentTui(),c=resolveTuiDisplayOptions(t),l=resolveTuiTitle({name:t.name,remoteServerUrl:r,appRoot:a});l!==void 0&&(c.name=l),await s({serverUrl:n,...c})};if(r){e.log(renderCliTaggedLine(d,{message:`connecting to ${r}`,tag:`dev`,tone:`info`}));let i=resolveDevUiMode({options:t,interactive:hasInteractiveTerminal()});if(i===`headless`){e.log(renderCliTaggedLine(d,{message:`Interactive UI disabled because the current terminal is not a TTY.`,tag:`dev`,tone:`warning`}));return}await runInteractiveUi(r,i);return}let s=await(i.startHost??await loadStartHost())(a,{host:t.host,port:t.port}),c=!1,closeServer=async()=>{c||(c=!0,await s.close())};try{e.log(renderCliTaggedLine(d,{message:`server listening at ${s.url}`,tag:`dev`,tone:`success`}));let r=hasInteractiveTerminal(),i=resolveDevUiMode({options:t,interactive:r});if(i===`headless`)return t.ui!==!1&&!r&&e.log(renderCliTaggedLine(d,{message:`Interactive UI disabled because the current terminal is not a TTY.`,tag:`dev`,tone:`warning`})),await waitForShutdownSignal({close:closeServer});await runInteractiveUi(s.url,i)}finally{await closeServer()}}),u.command(`info`).description(`Print resolved application information.`).option(`--json`,`Output as JSON`).action(async t=>{await(i.printApplicationInfo??await loadPrintApplicationInfo())(e,a,t)}),u.command(`eval`).description(`Run evals against an Eve agent.`).argument(`[evalIds...]`,`Eval ids to run (all discovered evals when omitted)`).option(`--url <url>`,`Remote agent URL (skip local host startup)`).option(`--mock-models`,`Boot the local dev target with deterministic mock models`).option(`--tag <tag...>`,`Run only cases (or evals) carrying a tag`).option(`--case <id...>`,`Run only specific case ids`).option(`--strict`,`Fail the exit code when any score falls below its threshold`).option(`--no-skips`,`Treat unmet eval requirements as failures`).option(`--list`,`Print discovered evals and cases without running them`).option(`--timeout <ms>`,`Per-case timeout in milliseconds`).option(`--max-concurrency <n>`,`Max concurrent case executions per eval`).option(`--json`,`Output results as JSON`).option(`--junit <path>`,`Write JUnit XML results to a file`).option(`--skip-report`,`Skip eval-defined reporters (e.g. Braintrust)`).option(`--verbose`,`Stream per-case ctx.log lines to stdout`).action(async(t,n)=>{await(i.runEvalCommand??await loadRunEvalCommand())(t,n,e)}),u}async function runCli(e=process.argv.slice(2),t=console,n={}){let r=createCliProgram(t,n),a=e.length===0?[`dev`]:rewriteDevelopmentUrlShorthand(rewriteDeprecatedReplFlag(e));try{await r.parseAsync(a,{from:`user`})}catch(e){if(e instanceof CommanderError){if(e.exitCode===0)return;throw Error(e.message)}throw e}}export{resolveDevUiMode,resolveTuiDisplayOptions,resolveTuiTitle,rewriteDeprecatedReplFlag,runCli};
|
|
3
|
+
`).action(async t=>{let r=resolveRemoteDevelopmentServerUrl(t),{loadDevelopmentEnvironmentFiles:o}=await import(`#cli/dev/environment.js`);o(a);let runInteractiveUi=async(n,o)=>{if(e.log(``),o===`repl`){await(i.runDevelopmentRepl??await loadRunDevelopmentRepl())({serverUrl:n});return}let s=i.runDevelopmentTui??await loadRunDevelopmentTui(),c=resolveTuiDisplayOptions(t),l=resolveTuiTitle({name:t.name,remoteServerUrl:r,appRoot:a});l!==void 0&&(c.name=l),await s(r===void 0?{serverUrl:n,appRoot:a,...c}:{serverUrl:n,...c})};if(r){e.log(renderCliTaggedLine(d,{message:`connecting to ${r}`,tag:`dev`,tone:`info`}));let i=resolveDevUiMode({options:t,interactive:hasInteractiveTerminal()});if(i===`headless`){e.log(renderCliTaggedLine(d,{message:`Interactive UI disabled because the current terminal is not a TTY.`,tag:`dev`,tone:`warning`}));return}await runInteractiveUi(r,i);return}let s=await(i.startHost??await loadStartHost())(a,{host:t.host,port:t.port}),c=!1,closeServer=async()=>{c||(c=!0,await s.close())};try{e.log(renderCliTaggedLine(d,{message:`server listening at ${s.url}`,tag:`dev`,tone:`success`}));let r=hasInteractiveTerminal(),i=resolveDevUiMode({options:t,interactive:r});if(i===`headless`)return t.ui!==!1&&!r&&e.log(renderCliTaggedLine(d,{message:`Interactive UI disabled because the current terminal is not a TTY.`,tag:`dev`,tone:`warning`})),await waitForShutdownSignal({close:closeServer});await runInteractiveUi(s.url,i)}finally{await closeServer()}}),u.command(`info`).description(`Print resolved application information.`).option(`--json`,`Output as JSON`).action(async t=>{await(i.printApplicationInfo??await loadPrintApplicationInfo())(e,a,t)}),u.command(`eval`).description(`Run evals against an Eve agent.`).argument(`[evalIds...]`,`Eval ids to run (all discovered evals when omitted)`).option(`--url <url>`,`Remote agent URL (skip local host startup)`).option(`--mock-models`,`Boot the local dev target with deterministic mock models`).option(`--tag <tag...>`,`Run only cases (or evals) carrying a tag`).option(`--case <id...>`,`Run only specific case ids`).option(`--strict`,`Fail the exit code when any score falls below its threshold`).option(`--no-skips`,`Treat unmet eval requirements as failures`).option(`--list`,`Print discovered evals and cases without running them`).option(`--timeout <ms>`,`Per-case timeout in milliseconds`).option(`--max-concurrency <n>`,`Max concurrent case executions per eval`).option(`--json`,`Output results as JSON`).option(`--junit <path>`,`Write JUnit XML results to a file`).option(`--skip-report`,`Skip eval-defined reporters (e.g. Braintrust)`).option(`--verbose`,`Stream per-case ctx.log lines to stdout`).action(async(t,n)=>{await(i.runEvalCommand??await loadRunEvalCommand())(t,n,e)}),u}async function runCli(e=process.argv.slice(2),t=console,n={}){let r=createCliProgram(t,n),a=e.length===0?[`dev`]:rewriteDevelopmentUrlShorthand(rewriteDeprecatedReplFlag(e));try{await r.parseAsync(a,{from:`user`})}catch(e){if(e instanceof CommanderError){if(e.exitCode===0)return;throw Error(e.message)}throw e}}export{resolveDevUiMode,resolveTuiDisplayOptions,resolveTuiTitle,rewriteDeprecatedReplFlag,runCli};
|
|
@@ -30,23 +30,23 @@ export interface IFileSystem {
|
|
|
30
30
|
writeFile(path: string, content: InitialFileContent): Promise<void>;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export interface
|
|
33
|
+
export interface BashOptions {
|
|
34
34
|
cwd: string;
|
|
35
35
|
env?: Readonly<Record<string, string>> | undefined;
|
|
36
36
|
fs: IFileSystem;
|
|
37
37
|
network?: NetworkConfig | undefined;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
export interface
|
|
40
|
+
export interface BashExecResult {
|
|
41
41
|
exitCode: number;
|
|
42
42
|
stderr: string;
|
|
43
43
|
stdout: string;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
export declare class Bash {
|
|
47
|
-
constructor(options:
|
|
47
|
+
constructor(options: BashOptions);
|
|
48
48
|
dispose?(): Promise<void> | void;
|
|
49
|
-
exec(command: string): Promise<
|
|
49
|
+
exec(command: string): Promise<BashExecResult>;
|
|
50
50
|
getEnv(): Record<string, string>;
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isAbsolute,join,relative,resolve}from"node:path";import{toErrorMessage}from"#shared/errors.js";import{normalizeJsonSchemaDefinition}from"#shared/json-schema.js";import{normalizeLogicalPath}from"#discover/filesystem.js";import{normalizeAgentDefinition}from"#internal/authored-definition/core.js";import{
|
|
1
|
+
import{isAbsolute,join,relative,resolve}from"node:path";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{toErrorMessage}from"#shared/errors.js";import{normalizeJsonSchemaDefinition}from"#shared/json-schema.js";import{normalizeLogicalPath}from"#discover/filesystem.js";import{normalizeAgentDefinition}from"#internal/authored-definition/core.js";import{parseJsonObject}from"#shared/json.js";import{loadModuleBackedDefinition}from"#compiler/normalize-helpers.js";async function compileAgentConfig(e,t){let n=e.configModule,r=n===void 0?void 0:formatAgentConfigModulePath(e,n),i=normalizeAgentDefinition(n===void 0?{model:`anthropic/claude-sonnet-4.6`}:await loadModuleBackedDefinition({agentRoot:e.agentRoot,displayPath:r,kind:`agent config`,source:n}),n===void 0?`Expected the default agent config to match the public Eve shape.`:`Expected the agent config export "${n.exportName??`default`}" from "${r}" to match the public Eve shape.`),a=await normalizeAuthoredModelReference({modelCatalog:t.modelCatalog,purpose:`the primary compaction trigger model`,contextWindowTokens:i.modelContextWindowTokens,providerOptions:i.modelOptions?.providerOptions,source:n,sourcePath:r,value:i.model}),o={},s={compaction:o,model:a,name:e.agentId};return i.description!==void 0&&(s.description=i.description),i.experimental?.codeMode!==void 0&&(s.experimental={codeMode:i.experimental.codeMode}),i.build!==void 0&&(s.build={externalDependencies:i.build.externalDependencies===void 0?void 0:[...i.build.externalDependencies]}),i.outputSchema!==void 0&&(s.outputSchema=normalizeJsonSchemaDefinition(i.outputSchema,`output`)),n!==void 0&&(s.source={exportName:n.exportName,sourceKind:`module`,logicalPath:n.logicalPath,sourceId:n.sourceId}),i.compaction?.model!==void 0&&(o.model=await normalizeAuthoredModelReference({modelCatalog:t.modelCatalog,purpose:`the compaction summary model`,contextWindowTokens:i.compaction.modelContextWindowTokens,providerOptions:i.modelOptions?.providerOptions,source:n,sourcePath:r,value:i.compaction.model})),i.compaction?.thresholdPercent!==void 0&&(o.thresholdPercent=i.compaction.thresholdPercent),s}async function normalizeAuthoredModelReference(e){if(typeof e.value==`string`)return await withCompiledRuntimeModelLimits({id:formatLanguageModelGatewayId(e.value),providerOptions:parseProviderOptionsRecord(e.providerOptions)},e);let t=e.source;if(t===void 0)throw Error(`Expected ${e.purpose} to provide a valid AI SDK language model reference.`);let n=e.value,r=n.specificationVersion;if(r!==`v2`&&r!==`v3`&&r!==`v4`||typeof n.provider!=`string`||typeof n.modelId!=`string`||typeof n.doGenerate!=`function`||typeof n.doStream!=`function`)throw Error(`Expected the authored agent config export "${t.exportName??`default`}" from "${e.sourcePath??t.logicalPath}" to provide a valid AI SDK language model.`);let a={id:formatLanguageModelGatewayId(n),source:{exportName:t.exportName,sourceKind:`module`,logicalPath:t.logicalPath,sourceId:t.sourceId},providerOptions:parseProviderOptionsRecord(e.providerOptions)};if(e.contextWindowTokens===void 0){let t=await e.modelCatalog.getByProviderModelId(n.provider,n.modelId);if(t)return{...a,id:t.slug,contextWindowTokens:t.limits.contextWindowTokens}}return await withCompiledRuntimeModelLimits(a,e)}function formatAgentConfigModulePath(e,r){let i=join(e.agentRoot,r.logicalPath);return normalizeLogicalPath(relative(resolveTopLevelAgentRoot(e),i))}function resolveTopLevelAgentRoot(e){let t=resolve(e.appRoot),n=resolve(t,`agent`);return isPathInsideOrEqual(n,resolve(e.agentRoot))?n:t}function isPathInsideOrEqual(t,r){let i=relative(t,r);return i===``||!i.startsWith(`..`)&&!isAbsolute(i)}async function withCompiledRuntimeModelLimits(e,t){if(t.contextWindowTokens!==void 0)return{...e,contextWindowTokens:t.contextWindowTokens};let n;try{n=await t.modelCatalog.getModelLimits(e.id)}catch(n){throw Error(`Failed to load AI Gateway model metadata for ${t.purpose} "${e.id}". ${toErrorMessage(n)}`)}if(n===null)throw Error(`Cannot compile agent compaction because ${t.purpose} "${e.id}" does not have known AI Gateway context window metadata.`);return{...e,contextWindowTokens:n.contextWindowTokens}}function parseProviderOptionsRecord(e){if(e===void 0)return;let t={};for(let[n,r]of Object.entries(e))t[n]=parseJsonObject(r);return t}export{compileAgentConfig};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{compileChannelDefinition}from"#compiler/normalize-channel.js";import{
|
|
1
|
+
import{compileChannelDefinition}from"#compiler/normalize-channel.js";import{createCompiledRuntimeModelCatalogLoader}from"#compiler/model-catalog.js";import{ROOT_COMPILED_AGENT_NODE_ID,createCompiledAgentManifest,createCompiledAgentNodeManifest}from"#compiler/manifest.js";import{compileAgentConfig}from"#compiler/normalize-agent-config.js";import{compileConnectionDefinition}from"#compiler/normalize-connection.js";import{compileHookEntry}from"#compiler/normalize-hook.js";import{compileSandboxDefinition}from"#compiler/normalize-sandbox.js";import{compileInstructionsEntry}from"#compiler/normalize-instructions.js";import{compileScheduleDefinition}from"#compiler/normalize-schedule.js";import{compileSkillSource}from"#compiler/normalize-skill.js";import{compileSubagentGraph}from"#compiler/normalize-subagent.js";import{compileToolEntry}from"#compiler/normalize-tool.js";async function compileAgentManifest(e){let i={modelCatalog:createCompiledRuntimeModelCatalogLoader(e.appRoot)},[a,o]=await Promise.all([compileAgentNodeManifest(e,i),compileSubagentGraph({appRoot:e.appRoot,compileAgentNodeManifest,context:i,parentNodeId:ROOT_COMPILED_AGENT_NODE_ID,subagents:e.subagents})]);return createCompiledAgentManifest({...a,remoteAgents:o.remoteAgents,subagentEdges:o.edges,subagents:o.nodes})}async function compileAgentNodeManifest(t,n){let r=await Promise.all(t.tools.map(e=>compileToolEntry(t.agentRoot,e))),s=[],c=[],l=[],u=!1;for(let e of r)e.kind===`tool`?s.push(e.definition):e.kind===`dynamic-tool`?c.push(e.definition):e.kind===`enable-workflow`?u=!0:l.push(e.name);let d=(await Promise.all(t.channels.map(n=>compileChannelDefinition(t.agentRoot,n)))).flat(),f=await Promise.all(t.skills.map(e=>compileSkillSource(t.agentRoot,e))),p=[],m=[];for(let e of f)e.kind===`skill`?p.push(e.definition):m.push(e.definition);let h=await Promise.all(t.instructions.map(e=>compileInstructionsEntry(t.agentRoot,e))),g=[],_=[];for(let e of h)e.kind===`instructions`?g.push(e.definition):_.push(e.definition);let v=g.length===0?void 0:g.length===1?g[0]:{name:`instructions`,logicalPath:`instructions`,markdown:g.map(e=>e.markdown).join(`
|
|
2
2
|
|
|
3
3
|
`),sourceId:g[0].sourceId,sourceKind:`module`};return createCompiledAgentNodeManifest({agentRoot:t.agentRoot,appRoot:t.appRoot,channels:d,config:await compileAgentConfig(t,n),connections:await Promise.all(t.connections.map(e=>compileConnectionDefinition(t.agentRoot,e))),diagnosticsSummary:t.diagnosticsSummary,disabledFrameworkTools:l,workflowEnabled:u,dynamicSkills:m,dynamicTools:c,hooks:t.hooks.map(e=>compileHookEntry(e)),sandbox:t.sandbox===null?null:await compileSandboxDefinition(t.agentRoot,t.sandbox),sandboxWorkspaces:t.sandboxWorkspaces.map(e=>({logicalPath:e.logicalPath,rootEntries:[...e.rootEntries],sourceId:e.sourceId,sourcePath:e.sourcePath})),schedules:await Promise.all(t.schedules.map(e=>compileScheduleDefinition(t.agentRoot,e))),dynamicInstructions:_,skills:p,instructions:v,tools:s})}export{compileAgentManifest};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{join,posix}from"node:path";import{createHash}from"node:crypto";import{cp,mkdir,readFile,readdir,rm}from"node:fs/promises";import{normalizeLogicalPath}from"#discover/filesystem.js";import{ROOT_COMPILED_AGENT_NODE_ID,deriveResourceRootEntries}from"#compiler/manifest.js";import{normalizeSkillPackage,writeSkillPackageDirectory}from"#shared/skill-package.js";const RESOURCES_DIRECTORY=`workspace-resources`;async function materializeWorkspaceResources(t){let n=join(t.compileDirectoryPath,RESOURCES_DIRECTORY);await rm(n,{force:!0,recursive:!0});let r=await materializeNode({nodeId:ROOT_COMPILED_AGENT_NODE_ID,resourcesRoot:n,manifest:t.manifest}),i=await Promise.all(t.manifest.subagents.map(async e=>({...e,agent:await materializeNode({nodeId:e.nodeId,resourcesRoot:n,manifest:e.agent})})));return{...r,kind:t.manifest.kind,subagentEdges:t.manifest.subagentEdges,subagents:i,version:t.manifest.version}}function createResourceRoot(t,n,r){return{contentHash:r,logicalPath:normalizeLogicalPath(join(RESOURCES_DIRECTORY,n)),rootEntries:deriveResourceRootEntries({sandboxWorkspaces:t.sandboxWorkspaces,skills:t.skills})}}async function materializeNode(t){for(let e of t.manifest.sandboxWorkspaces)if(e.rootEntries.some(e=>e===`skills/`||e===`skills`))throw Error(`Sandbox workspace "${e.logicalPath}" cannot define "skills" because Eve manages that workspace entry.`);let n=join(t.resourcesRoot,t.nodeId);await mkdir(n,{recursive:!0});for(let e of t.manifest.sandboxWorkspaces)await cp(e.sourcePath,n,{recursive:!0});for(let e of t.manifest.skills)await materializeSkill({nodeRoot:n,skill:e});let a=await
|
|
1
|
+
import{join,posix}from"node:path";import{createHash}from"node:crypto";import{cp,mkdir,readFile,readdir,rm}from"node:fs/promises";import{normalizeLogicalPath}from"#discover/filesystem.js";import{ROOT_COMPILED_AGENT_NODE_ID,deriveResourceRootEntries}from"#compiler/manifest.js";import{normalizeSkillPackage,writeSkillPackageDirectory}from"#shared/skill-package.js";const RESOURCES_DIRECTORY=`workspace-resources`;async function materializeWorkspaceResources(t){let n=join(t.compileDirectoryPath,RESOURCES_DIRECTORY);await rm(n,{force:!0,recursive:!0});let r=await materializeNode({nodeId:ROOT_COMPILED_AGENT_NODE_ID,resourcesRoot:n,manifest:t.manifest}),i=await Promise.all(t.manifest.subagents.map(async e=>({...e,agent:await materializeNode({nodeId:e.nodeId,resourcesRoot:n,manifest:e.agent})})));return{...r,kind:t.manifest.kind,subagentEdges:t.manifest.subagentEdges,subagents:i,version:t.manifest.version}}function createResourceRoot(t,n,r){return{contentHash:r,logicalPath:normalizeLogicalPath(join(RESOURCES_DIRECTORY,n)),rootEntries:deriveResourceRootEntries({sandboxWorkspaces:t.sandboxWorkspaces,skills:t.skills})}}async function materializeNode(t){for(let e of t.manifest.sandboxWorkspaces)if(e.rootEntries.some(e=>e===`skills/`||e===`skills`))throw Error(`Sandbox workspace "${e.logicalPath}" cannot define "skills" because Eve manages that workspace entry.`);let n=join(t.resourcesRoot,t.nodeId);await mkdir(n,{recursive:!0});for(let e of t.manifest.sandboxWorkspaces)await cp(e.sourcePath,n,{recursive:!0});for(let e of t.manifest.skills)await materializeSkill({nodeRoot:n,skill:e});let a=await hashWorkspaceResourceRoot(n);return{...t.manifest,skills:t.manifest.skills.map(stripSkillPackageFiles),workspaceResourceRoot:createResourceRoot(t.manifest,t.nodeId,a)}}async function materializeSkill(t){let n=join(t.nodeRoot,`skills`,t.skill.name);if(t.skill.sourceKind===`skill-package`){await cp(t.skill.rootPath,n,{recursive:!0});return}await writeSkillPackageDirectory({rootPath:t.nodeRoot,skill:normalizeSkillPackage(t.skill)})}function stripSkillPackageFiles(e){let{files:t,...n}=e;return n}async function hashWorkspaceResourceRoot(e){let t=await listWorkspaceResourceFiles({logicalDirectoryPath:`.`,sourceDirectoryPath:e});t.sort((e,t)=>e.logicalPath.localeCompare(t.logicalPath));let r=createHash(`sha256`);r.update(`eve-workspace-resource-root-v1\0`);for(let e of t){let t=await readFile(e.sourcePath);r.update(e.logicalPath),r.update(`\0`),r.update(String(t.byteLength)),r.update(`\0`),r.update(t),r.update(`\0`)}return r.digest(`hex`)}async function listWorkspaceResourceFiles(n){let r=[],i=await readdir(n.sourceDirectoryPath,{withFileTypes:!0});for(let a of i){if(!a.isDirectory()&&!a.isFile())continue;let i=join(n.sourceDirectoryPath,a.name),o=posix.join(n.logicalDirectoryPath,a.name);if(a.isDirectory()){r.push(...await listWorkspaceResourceFiles({logicalDirectoryPath:o,sourceDirectoryPath:i}));continue}r.push({logicalPath:o,sourcePath:i})}return r}export{materializeWorkspaceResources};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import type { SandboxSession } from "#shared/sandbox-session.js";
|
|
2
2
|
/**
|
|
3
|
-
* Typed input accepted by {@link
|
|
3
|
+
* Typed input accepted by {@link executeBashOnSandbox}.
|
|
4
4
|
*/
|
|
5
|
-
export interface
|
|
5
|
+
export interface BashInput {
|
|
6
6
|
readonly command: string;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
* Structured result returned from {@link
|
|
9
|
+
* Structured result returned from {@link executeBashOnSandbox}.
|
|
10
10
|
*/
|
|
11
|
-
export interface
|
|
11
|
+
export interface BashResult {
|
|
12
12
|
readonly exitCode: number;
|
|
13
13
|
readonly stderr: string;
|
|
14
14
|
readonly stdout: string;
|
|
@@ -24,7 +24,7 @@ export interface BeveResult {
|
|
|
24
24
|
* {@link MAX_OUTPUT_LINES} / {@link MAX_OUTPUT_BYTES} limits.
|
|
25
25
|
*
|
|
26
26
|
* Used by the framework `bash` tool and by author tools constructed via
|
|
27
|
-
* `
|
|
27
|
+
* `defineBashTool`. Centralizing the executor here keeps the error
|
|
28
28
|
* messages and result shape identical across all bash-style tools.
|
|
29
29
|
*/
|
|
30
|
-
export declare function
|
|
30
|
+
export declare function executeBashOnSandbox(sandbox: SandboxSession, args: BashInput): Promise<BashResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{truncateTail}from"#execution/sandbox/truncate-output.js";async function
|
|
1
|
+
import{truncateTail}from"#execution/sandbox/truncate-output.js";async function executeBashOnSandbox(e,t){let n=await e.run({command:t.command}),r=truncateTail(n.stdout),i=truncateTail(n.stderr),a=r.truncated||i.truncated,o=r.output;r.truncated&&(o=`[stdout truncated: showing last ${r.outputLines} of ${r.totalLines} lines]\n`+o);let s=i.output;return i.truncated&&(s=`[stderr truncated: showing last ${i.outputLines} of ${i.totalLines} lines]\n`+s),{exitCode:n.exitCode,stderr:s,stdout:o,truncated:a}}export{executeBashOnSandbox};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dirname,join}from"node:path";import"node:fs";import{resolveSandboxCacheDirectory}from"#internal/application/paths.js";import{randomUUID}from"node:crypto";import{access,cp,mkdir,readFile,readdir,rename,rm,stat,utimes,writeFile}from"node:fs/promises";import{shellQuote}from"#execution/sandbox/shell-quote.js";import{SandboxTemplateNotProvisionedError}from"#public/definitions/sandbox-backend.js";import{WORKSPACE_ROOT}from"#runtime/workspace/types.js";import{buildSandboxSession}from"#execution/sandbox/session.js";import{bufferToStream,streamToBuffer}from"#execution/sandbox/stream-utils.js";function createLocalSandboxBackend(t={}){return{name:`local`,async prewarm(t){let i=resolveTemplateRootPath(resolveSandboxCacheDirectory(t.runtimeContext.appRoot),t.templateKey);if(await doesPathExist(i))return await touchDirectory(i),{reused:!0};let a=`${i}.${randomUUID()}.tmp`,s=!1,c=await
|
|
1
|
+
import{dirname,join}from"node:path";import"node:fs";import{resolveSandboxCacheDirectory}from"#internal/application/paths.js";import{randomUUID}from"node:crypto";import{access,cp,mkdir,readFile,readdir,rename,rm,stat,utimes,writeFile}from"node:fs/promises";import{shellQuote}from"#execution/sandbox/shell-quote.js";import{SandboxTemplateNotProvisionedError}from"#public/definitions/sandbox-backend.js";import{WORKSPACE_ROOT}from"#runtime/workspace/types.js";import{buildSandboxSession}from"#execution/sandbox/session.js";import{bufferToStream,streamToBuffer}from"#execution/sandbox/stream-utils.js";function createLocalSandboxBackend(t={}){return{name:`local`,async prewarm(t){let i=resolveTemplateRootPath(resolveSandboxCacheDirectory(t.runtimeContext.appRoot),t.templateKey);if(await doesPathExist(i))return await touchDirectory(i),{reused:!0};let a=`${i}.${randomUUID()}.tmp`,s=!1,c=await createBashSandbox({rootPath:a,sessionKey:t.templateKey}),u=buildSandboxSession(createLocalInternalSandboxSession(c),localSetNetworkPolicyUnsupported);try{t.bootstrap!==void 0&&await t.bootstrap({use:async()=>u});for(let e of t.seedFiles)typeof e.content==`string`?await u.writeTextFile({content:e.content,path:e.path}):await u.writeBinaryFile({content:e.content,path:e.path});if(await c.captureState()===null)throw Error(`Failed to capture local sandbox template state for "${t.templateKey}".`);await mkdir(dirname(i),{recursive:!0});try{await rename(a,i),s=!0}catch(e){if(await doesPathExist(i))return{reused:!0};throw e}}finally{await c.dispose(),s||await rm(a,{force:!0,recursive:!0}).catch(()=>{})}return{reused:!1}},async create(e){let t=resolveSandboxCacheDirectory(e.runtimeContext.appRoot),r=getLocalRootPath(e.existingMetadata)??resolveSessionRootPath(t,e.sessionKey);if(!await doesPathExist(r))if(e.templateKey===null)await mkdir(r,{recursive:!0});else{let n=resolveTemplateRootPath(t,e.templateKey);if(!await doesPathExist(n))throw new SandboxTemplateNotProvisionedError({backendName:`local`,templateKey:e.templateKey});await copyDirectoryAtomically(n,r)}return createHandle(await createBashSandbox({rootPath:r,sessionKey:e.sessionKey}))}}}function pruneLocalSandboxTemplatesInBackground(e){pruneLocalSandboxTemplates({appRoot:e}).catch(e=>{console.warn(`[eve:dev] failed to prune stale local sandbox templates: ${errorMessage(e)}`)})}async function pruneLocalSandboxTemplates(e){let r=resolveTemplatesDirectory(resolveSandboxCacheDirectory(e.appRoot)),i=e.now??Date.now(),a=e.recentWindowMs??9e5,o=e.retainCount??5,s;try{s=await readdir(r,{withFileTypes:!0})}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e}let l=(await Promise.all(s.filter(e=>e.isDirectory()).map(async e=>{let n=join(r,e.name);return{isTemporary:e.name.endsWith(`.tmp`),mtimeMs:(await stat(n)).mtimeMs,path:n}}))).sort((e,t)=>t.mtimeMs-e.mtimeMs),d=l.filter(e=>!e.isTemporary);await Promise.all([...d.map(async(e,t)=>{t<o||i-e.mtimeMs<=a||await rm(e.path,{force:!0,recursive:!0})}),...l.filter(e=>e.isTemporary).map(async e=>{i-e.mtimeMs<=a||await rm(e.path,{force:!0,recursive:!0})})])}async function copyDirectoryAtomically(t,n){let i=`${n}.${randomUUID()}.tmp`;await rm(i,{force:!0,recursive:!0}),await mkdir(dirname(n),{recursive:!0});try{await cp(t,i,{recursive:!0}),await rename(i,n)}catch(e){if(await rm(i,{force:!0,recursive:!0}).catch(()=>{}),await doesPathExist(n))return;throw e}}async function createBashSandbox(t){let{ReadWriteFs:n,Sandbox:r}=await import(`#compiled/just-bash/index.js`),i=resolveLocalSandboxFilesystemRootPath(t.rootPath),a=resolveLocalSandboxMetadataPath(t.rootPath),s=await readLocalMetadata(a);await mkdir(i,{recursive:!0});let c=new n({allowSymlinks:!0,maxFileReadSize:2**53-1,root:i});await ensureLocalSandboxDirectories(c);let l=await r.create({cwd:WORKSPACE_ROOT,env:s?.env,fs:c,network:{dangerouslyAllowFullInternetAccess:!0}});return{async captureState(){return await writeLocalMetadata(a,{env:{...l.bashEnvInstance.getEnv()},version:1}),{rootPath:t.rootPath}},async dispose(){await l.stop()},async readFileBytes(e){let t;try{t=await c.readFileBuffer(e)}catch{return null}return Buffer.from(t)},async removePath(e){await c.rm(e.path,{force:e.force,recursive:e.recursive})},rootPath:t.rootPath,sessionKey:t.sessionKey,async spawn(e){if(e.abortSignal?.aborted)throw new DOMException(`The operation was aborted.`,`AbortError`);let t=e.workingDirectory===void 0?e.command:`( cd ${shellQuote(e.workingDirectory)} && ${e.command} )`;return adaptJustBashCommandToSandboxProcess(await l.runCommand({args:[t],cmd:`eval`,detached:!0,env:e.env,signal:e.abortSignal}))},async writeFiles(t){for(let n of t){let t=dirname(n.path);await c.mkdir(t,{recursive:!0}),await c.writeFile(n.path,n.content)}}}}function adaptJustBashCommandToSandboxProcess(e){let t=new TextEncoder,n,r,i=!1,a,o=new ReadableStream({start(e){n=e}}),s=new ReadableStream({start(e){r=e}});return(async()=>{try{for await(let i of e.logs()){let e=t.encode(i.data);i.type===`stdout`?n?.enqueue(e):r?.enqueue(e)}}catch(e){a=e,n?.error(e),r?.error(e)}finally{i=!0,a===void 0&&(n?.close(),r?.close())}})(),{stdout:o,stderr:s,async wait(){let t=await e.wait();for(;!i;)await new Promise(e=>setTimeout(e,0));if(a!==void 0)throw a;return{exitCode:t.exitCode}},async kill(){await e.kill()}}}async function localSetNetworkPolicyUnsupported(){throw Error(`setNetworkPolicy() is not supported on the local sandbox backend. just-bash applies its network policy only at sandbox creation (no run-time update) and does not run git or other binaries. Use the Vercel backend for credential brokering and egress control.`)}function createHandle(e){let t=buildSandboxSession(createLocalInternalSandboxSession(e),localSetNetworkPolicyUnsupported);return{session:t,useSessionFn:async()=>t,async captureState(){return{backendName:`local`,metadata:await e.captureState()??{},sessionKey:e.sessionKey}},async dispose(){await e.dispose()}}}function createLocalInternalSandboxSession(e){return{id:e.sessionKey,resolvePath:resolveLocalPath,async spawn(t){return await e.spawn(t)},async readFile(t){let n=await e.readFileBytes(t.path);return n===null?null:bufferToStream(n)},async removePath(t){await e.removePath(t)},async writeFile(t){let n=await streamToBuffer(t.content);await e.writeFiles([{content:n,path:t.path}])}}}function resolveLocalPath(e){return e.startsWith(`/`)?e:`${WORKSPACE_ROOT}/${e}`}function resolveTemplateRootPath(e,n){return join(resolveTemplatesDirectory(e),n)}function resolveTemplatesDirectory(e){return join(e,`local`,`templates`)}function resolveSessionRootPath(e,n){return join(e,`local`,`sessions`,n)}function resolveLocalSandboxFilesystemRootPath(e){return join(e,`fs`)}function resolveLocalSandboxMetadataPath(e){return join(e,`metadata.json`)}async function ensureLocalSandboxDirectories(e){await e.mkdir(WORKSPACE_ROOT,{recursive:!0})}async function readLocalMetadata(e){if(!await doesPathExist(e))return null;let t=JSON.parse(await readFile(e,`utf8`));return t.version!==1||!isStringRecord(t.env)?null:{env:t.env,version:1}}async function writeLocalMetadata(t,n){await mkdir(dirname(t),{recursive:!0}),await writeFile(t,`${JSON.stringify(n,null,2)}\n`)}function getLocalRootPath(e){let t=e?.rootPath;return typeof t==`string`?t:void 0}function isStringRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)&&Object.values(e).every(e=>typeof e==`string`)}async function doesPathExist(e){try{return await access(e),!0}catch{return!1}}async function touchDirectory(e){let t=new Date;await utimes(e,t,t)}function errorMessage(e){return e instanceof Error?e.message:String(e)}export{createLocalSandboxBackend,pruneLocalSandboxTemplates,pruneLocalSandboxTemplatesInBackground};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createErrorId,createLogger,formatError,logError,recordErrorOnSpan}from"#internal/logging.js";import{createAuthorizationRequiredEvent,createCompactionCompletedEvent,createCompactionRequestedEvent,createInputRequestedEvent,createResultCompletedEvent}from"#protocol/message.js";import{toErrorMessage}from"#shared/errors.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{contextStorage,loadContext}from"#context/container.js";import{ToolLoopAgent,isStepCount}from"ai";import{setEveAttributes}from"#runtime/attributes/emit.js";import{isCodeModeRuntimeActionInterrupt}from"#harness/code-mode-runtime-action-state.js";import{clearPendingCodeModeInterrupt,getPendingCodeModeInterrupt,setPendingCodeModeInterrupt}from"#harness/code-mode-interrupt-state.js";import{createRuntimeActionRequestFromToolCall,resolvePendingRuntimeActions,setPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{advanceStep,emitFailedStep,emitRecoverableFailedTurn,emitStepStarted,emitStreamContent,emitTurnEpilogue,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{CODE_MODE_TOOL_NAME,loadCodeModeModule}from"#shared/code-mode.js";import{resolveAssistantStepText}from"#harness/messages.js";import{buildDynamicInstructionMessages}from"#context/dynamic-instruction-lifecycle.js";import{PendingSkillAnnouncementKey}from"#context/dynamic-skill-lifecycle.js";import{consumeDeferredStepInput,getApprovedTools,hasDeferredStepInput,hasStepInput,resolvePendingInput,setPendingInputBatch}from"#harness/input-requests.js";import{isAuthorizationSignal,setPendingAuthorization}from"#harness/authorization.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{isCodeModeConnectionAuthInterrupt}from"#runtime/framework-tools/code-mode-connection-auth.js";import{isSandboxEnabled,selectSandboxSurfaces}from"#harness/sandbox-surface.js";import{buildToolSetWithProviderTools}from"#harness/tools.js";import{ASK_QUESTION_TOOL_NAME}from"#runtime/framework-tools/ask-question.js";import{WEB_SEARCH_TOOL_DEFINITION}from"#runtime/framework-tools/web-search.js";import{extractQuestionInputRequests,extractToolApprovalInputRequests}from"#harness/input-extraction.js";import{applyLastToolCacheBreakpoint,applySystemCacheBreakpoint,detectPromptCachePath,getAnthropicCacheMarker}from"#harness/prompt-cache.js";import{resolveFrameworkToolFromUpstreamType,resolveGatewayPinForWebSearchBackend,resolveWebSearchBackend}from"#harness/provider-tools.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{hydrateSandboxAttachments,stageAttachmentsToSandbox}from"#harness/attachment-staging.js";import{applySandboxToolSet,buildSandboxHostTools,createEveCodeModeOptions}from"#harness/code-mode.js";import{createCodeModeLifecycle}from"#harness/code-mode-lifecycle.js";import{compactMessages,getInputTokenCount,resolveCompactionModel,shouldCompact}from"#harness/compaction.js";import{accumulateTurnUsage,getTurnUsageState,setTurnUsageState}from"#harness/turn-tag-state.js";import{buildTelemetryRuntimeContext}from"#harness/instrumentation-runtime-context.js";import{getInstrumentationConfig}from"#harness/instrumentation-config.js";import{readToolInterrupt}from"#harness/tool-interrupts.js";import{EmptyModelResponseError,classifyModelCallError,extractModelCallErrorDetails,extractUnsupportedProviderToolTypes,isNoOutputGeneratedError,summarizeKnownModelCallConfigError,summarizeKnownModelCallRequestError}from"#harness/model-call-error.js";import{extractWorkflowStreamWriteErrorDetails}from"#harness/workflow-stream-error.js";import{ensureOtelIntegration}from"#harness/otel-integration.js";import{buildStepHooks,emitStepActions,isInvalidToolCall}from"#harness/step-hooks.js";import{pruneToolResults}from"#harness/tool-result-pruning.js";import{FINAL_OUTPUT_TOOL_NAME,buildFinalOutputTool}from"#runtime/framework-tools/final-output.js";const environment=process.env.NODE_ENV??`unknown`,eveVersion=resolveInstalledPackageInfo().version,log=createLogger(`harness.tool-loop`);function logToolExecutionError(e){e.toolOutput.type===`tool-error`&&logError(log,`tool execution failed`,e.toolOutput.error,{toolName:e.toolCall.toolName,toolCallId:e.toolCall.toolCallId})}function enrichTelemetry(e,t,n){if(e===void 0)return;let r={};for(let e of Object.keys(n??{}))r[e]=!0;return{functionId:e.functionId??t,includeRuntimeContext:r,isEnabled:!0,recordInputs:e.recordInputs??!0,recordOutputs:e.recordOutputs??!0}}function resolveGatewayPinForStep(e){if(e.cachePath.kind!==`gateway-auto`||e.tools[WEB_SEARCH_TOOL_DEFINITION.name]===void 0)return;let t=resolveWebSearchBackend(e.modelReference);return t===null?void 0:resolveGatewayPinForWebSearchBackend(t)??void 0}function buildGatewayAttributionHeaders(e,t){if(typeof e!=`string`)return;let n=t?.agentName??t?.agentId,r=process.env.VERCEL_PROJECT_PRODUCTION_URL||process.env.VERCEL_URL,i=r?`https://${r}`:void 0;if(!n&&!i)return;let a={};return n&&(a[`x-title`]=n),i&&(a[`http-referer`]=i),a}const TURN_TRACE_STATE_KEY=`eve.harness.turnTrace`;function getTurnTraceState(e){return e.state?.[TURN_TRACE_STATE_KEY]}function setTurnTraceState(e,t){let n={traceId:t.traceId,spanId:t.spanId,traceFlags:t.traceFlags};return{...e,state:{...e.state,[TURN_TRACE_STATE_KEY]:n}}}function resolveStepOtelContext(e,t,n){if(t)return trace.setSpan(context.active(),t);if(e){let e=getTurnTraceState(n);if(e){let t=trace.wrapSpanContext({traceId:e.traceId,spanId:e.spanId,traceFlags:e.traceFlags});return trace.setSpan(context.active(),t)}}}function createToolLoopHarness(t){let n=t.handleEvent,a=getInstrumentationConfig();a!==void 0&&ensureOtelIntegration();let o=a===void 0?void 0:trace.getTracer(`eve`),s=t.runtimeIdentity?.agentName;async function runStep(e,t){let n;if(o&&hasStepInput(t)){let t=a?.functionId??s,r={"eve.version":eveVersion,"eve.environment":environment,"eve.session.id":e.sessionId};t&&(r[`ai.telemetry.functionId`]=t),n=o.startSpan(`ai.eve.turn`,{attributes:r})}let r=resolveStepOtelContext(o,n,e),executeStep=()=>executeStepBody(e,t,n);try{return r?await context.with(r,executeStep):await executeStep()}finally{n?.end()}}async function executeStepBody(o,c,l){let d=o;l&&(d=setTurnTraceState(d,l.spanContext()));let m=getHarnessEmissionState(d.state),v=consumeDeferredStepInput({input:c,session:d});d=v.session;let y=await resolvePendingRuntimeActions({emit:n,session:d,stepInput:v.input});if(y.outcome===`unresolved`)return{next:null,session:y.session};d=y.session;let b=resolvePendingInput({history:y.messages,resolveApprovalKey:resolveApprovalKeyFromTools(t.tools),session:d,stepInput:v.input});if(b.outcome===`unresolved`)return{next:null,session:b.session};n&&hasStepInput(c)&&(m=await emitTurnPreamble(n,c??{},m,t.runtimeIdentity),d=setHarnessEmissionState(d,m),l&&l.setAttribute(`eve.turn.id`,m.turnId)),d=b.session;let x=b.messages;if(v.input?.context!==void 0)for(let e of v.input.context)x.push({content:e,role:`user`});if(v.input?.message!==void 0&&!b.deferredMessage){let e=await stageAttachmentsToSandbox(v.input.message);x.push({content:e,role:`user`})}let S=await t.resolveModel(d.agent.modelReference),w=detectPromptCachePath(S),T=w.kind===`anthropic-direct`?getAnthropicCacheMarker():void 0,O=buildGatewayAttributionHeaders(S,t.runtimeIdentity);({messages:x,session:d}=await maybeCompact({emit:n,emissionState:m,headers:O,messages:x,model:S,onCompaction:t.onCompaction,resolveModel:t.resolveModel,session:d,telemetry:enrichTelemetry(a,s)??void 0}));let k=getApprovedTools(d),A=contextStorage.getStore(),j=await hydrateSandboxAttachments(x),M=[],N=[];for(let e of j)e.role===`system`?M.push(e):N.push(e);if(A!==void 0){M.push(...buildDynamicInstructionMessages(A));let e=A.get(PendingSkillAnnouncementKey);e!==void 0&&e.length>0&&M.push({role:`system`,content:e})}let P=N,prepareModelCallInput=e=>{let t=e?[{role:`system`,content:e}]:[],n=d.agent.system?[{role:`system`,content:d.agent.system}]:[],r=M.length>0||t.length>0?[...t,...n,...M]:void 0,i=r!==void 0&&T?applySystemCacheBreakpoint(r,T):r??d.agent.system??void 0;return{instructions:i,telemetryRuntimeContext:buildTelemetryRuntimeContext({eveVersion,authored:a,emissionState:m,environment,modelInput:{instructions:i,messages:P},session:d})}},runOneModelCall=async e=>{let{instructions:i,telemetryRuntimeContext:o={}}=e.preparedInput??prepareModelCallInput(e.extraSystemNote);e.retryReason&&(o[`eve.retry.reason`]=e.retryReason);let c=e.trailingUserNote?[...P,{role:`user`,content:e.trailingUserNote}]:P,l=selectSandboxSurfaces(t),u=await buildToolSetWithProviderTools({approvedTools:k,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,modelReference:d.agent.modelReference,tools:t.tools});if(A!==void 0){let e=buildDynamicTools(A);for(let t of e)u[t.name]??={description:t.description,inputSchema:t.inputSchema,execute:t.execute,outputSchema:t.outputSchema}}d.outputSchema!==void 0&&(u[FINAL_OUTPUT_TOOL_NAME]=buildFinalOutputTool(d.outputSchema));let f=l.length>0?(await applySandboxToolSet({harnessTools:t.tools,lifecycle:n===void 0?void 0:createCodeModeLifecycle({emit:n,emissionState:m,tools:t.tools}),tools:u,surfaces:l})).modelTools:u,p=T?applyLastToolCacheBreakpoint(f,T):f,_=resolveGatewayPinForStep({cachePath:w,modelReference:d.agent.modelReference,tools:p}),v=buildStepHooks({cachePath:w,emit:n,emissionState:m,emitStepStarted:e.suppressStepStartedEmission!==!0,gatewayPinProvider:_,marker:T,session:d}),y=new ToolLoopAgent({headers:O,instructions:i,model:S,onToolExecutionEnd:logToolExecutionError,onError(e){logError(log,`tool-loop stream error`,e.error)},onStepFinish:v.onStepFinish,prepareStep:v.prepareStep,runtimeContext:o,stopWhen:isStepCount(1),telemetry:enrichTelemetry(a,s,o),tools:p}),executeModelCall=async()=>{if(n){let e=await y.stream({messages:c}),{inlineActionResultCallIds:r,inlineToolResultParts:i}=await emitStreamContent(n,m,e.fullStream),a=await v.stepResult;if(isEmptyModelResponse(a))throw new EmptyModelResponseError;return await emitStepActions(n,m,a,{excludedActionToolNames:new Set([ASK_QUESTION_TOOL_NAME,CODE_MODE_TOOL_NAME,FINAL_OUTPUT_TOOL_NAME]),inlineActionResultCallIds:r,tools:t.tools}),i.length>0?{content:a.content,finishReason:a.finishReason,response:{...a.response,messages:[{role:`tool`,content:[...i]},...a.response.messages]},text:a.text,toolCalls:a.toolCalls,toolResults:a.toolResults,usage:a.usage}:a}await y.generate({messages:c});let e=await v.stepResult;if(isEmptyModelResponse(e))throw new EmptyModelResponseError;return e};return runModelCallWithRetries(()=>executeModelCall().catch(rethrowNoOutputAsEmptyResponse),{sessionId:d.sessionId,turnId:m.turnId})},F=prepareModelCallInput();n&&await emitStepStarted(n,m,x);let I=await continuePendingCodeModeInterrupt({capabilities:t.capabilities,childResults:v.input?.runtimeActionResults,config:t,emit:n,emissionState:m,messages:x,runStep,session:d});if(I!==null)return I;let L;try{L=await runOneModelCall({preparedInput:F,suppressStepStartedEmission:!0})}catch(r){let a=await runModelCallRecoveryPipeline({error:r,stages:[e=>attemptUnsupportedProviderToolRecovery({error:e.error,runOneModelCall,sessionId:d.sessionId,turnId:m.turnId}),e=>attemptEmptyResponseRecovery({error:e.error,retryCallOptions:e.retryCallOptions,runOneModelCall,sessionId:d.sessionId,turnId:m.turnId})]});if(a.outcome===`recovered`)L=a.result;else{let r=a.error;if(l&&recordErrorOnSpan(l,r),!n)throw r;let o=extractWorkflowStreamWriteErrorDetails(r);if(o!==null){let t=createErrorId();return log.error(`workflow stream write failed — parking session for retry by the user`,{...o,errorId:t,error:r,sessionId:d.sessionId,turnId:m.turnId}),m=await emitRecoverableFailedTurn(n,m,{code:`WORKFLOW_STREAM_WRITE_FAILED`,details:{...o,errorId:t},message:toErrorMessage(r)}),{next:null,session:setHarnessEmissionState(d,m)}}let s=classifyModelCallError(r),c=createErrorId(),f=s===`terminal`?summarizeKnownModelCallConfigError(r):null,p=f===null?summarizeKnownModelCallRequestError(r):null,h=f?.message??p?.message??toErrorMessage(r),g=extractModelCallErrorDetails(r),_=buildModelCallFailureDetails({configSummary:f,error:r,errorId:c,modelCallDetails:g,requestSummary:p}),v=buildModelCallFailureLogFields({error:r,errorId:c,modelCallDetails:g,requestSummary:p,sessionId:d.sessionId,turnId:m.turnId});return s===`terminal`?(f===null?log.error(p?.message??`model call failed terminally`,v):log.error(`${f.name}: ${f.message}`,{errorId:c,sessionId:d.sessionId,turnId:m.turnId}),await emitFailedStep(n,m,{code:`MODEL_CALL_FAILED`,details:_,message:h,sessionId:d.sessionId}),{next:{done:!0,output:``},session:d}):t.mode===`task`?(log.error(p?.message??`model call failed; failing the task run`,v),await emitFailedStep(n,m,{code:`MODEL_CALL_FAILED`,details:_,message:h,sessionId:d.sessionId}),{next:{done:!0,isError:!0,output:h},session:d}):(log.error(p?.message??`model call failed — parking session for retry by the user`,v),m=await emitRecoverableFailedTurn(n,m,{code:`MODEL_CALL_FAILED`,details:_,message:h}),{next:null,session:setHarnessEmissionState(d,m)})}}let R=accumulateTurnUsage({previous:getTurnUsageState(d.state),turnId:m.turnId,usage:L.usage??{}});d=setTurnUsageState(d,R);let z;try{z=formatLanguageModelGatewayId(S)}catch{z=void 0}return await setEveAttributes({"$eve.model":z,"$eve.input_tokens":R.inputTokens,"$eve.output_tokens":R.outputTokens,"$eve.cache_read_tokens":R.cacheReadTokens,"$eve.tool_count":t.tools.size}),handleStepResult({config:t,emit:n,emissionState:m,promptMessages:x,result:L,runStep,session:d})}return runStep}function buildModelCallFailureDetails(e){let{configSummary:t,error:r,errorId:i,modelCallDetails:a,requestSummary:o}=e;return t===null?o===null?{...formatError(r,i),...a}:{errorId:i,message:toErrorMessage(r),name:o.name,...a}:{errorId:i,message:t.message,name:t.name,...a}}function buildModelCallFailureLogFields(e){let t={errorId:e.errorId,sessionId:e.sessionId,turnId:e.turnId};return e.requestSummary===null?{...t,error:e.error}:{...t,details:e.modelCallDetails}}async function runModelCallRecoveryPipeline(e){let t=e.error,n;for(let r of e.stages){let e=await r({error:t,retryCallOptions:n});if(e.outcome===`recovered`)return e;e.outcome===`failed`&&(t=e.error,n=e.retryCallOptions)}return{outcome:`failed`,error:t}}async function attemptUnsupportedProviderToolRecovery(e){let t=extractUnsupportedProviderToolTypes(e.error);if(t.length===0)return{outcome:`skipped`};let n=[];for(let e of t){let t=resolveFrameworkToolFromUpstreamType(e);t!==null&&!n.includes(t)&&n.push(t)}if(n.length===0)return{outcome:`skipped`};log.warn(`disabling unsupported provider tool(s); retrying step once`,{disabled:n,sessionId:e.sessionId,turnId:e.turnId,upstreamTypes:t});let r={disabledProviderTools:new Set(n),extraSystemNote:buildDisabledToolNote(n)};try{return{outcome:`recovered`,result:await e.runOneModelCall({...r,suppressStepStartedEmission:!0})}}catch(e){return{outcome:`failed`,error:e,retryCallOptions:r}}}function buildDisabledToolNote(e){let t=e.join(`, `);return`The following ${e.length===1?`tool is`:`tools are`} not available with the current model and has been removed: ${t}. Proceed using the remaining tools or your training knowledge.`}function isEmptyModelResponse(e){return e.finishReason===`other`&&e.toolCalls.length===0&&resolveAssistantStepText(e.response.messages,e.text)===null}function rethrowNoOutputAsEmptyResponse(e){throw isNoOutputGeneratedError(e)?new EmptyModelResponseError({cause:e}):e}async function attemptEmptyResponseRecovery(e){if(!(e.error instanceof EmptyModelResponseError))return{outcome:`skipped`};log.warn(`empty model response; reissuing the model call once`,{sessionId:e.sessionId,turnId:e.turnId});try{return{outcome:`recovered`,result:await e.runOneModelCall({...e.retryCallOptions,retryReason:`empty-response`,suppressStepStartedEmission:!0,trailingUserNote:`Your previous reply was not delivered. Answer now from the tool results above; do not re-run tools or mention this notice.`})}}catch(t){return{outcome:`failed`,error:t,retryCallOptions:e.retryCallOptions}}}async function handleStepResult(e){let{config:t,emit:n,promptMessages:r,result:i,runStep:o}=e,{emissionState:s,session:l}=e,u=i.response.messages,d=resolveAssistantStepText(u,i.text),f={...l,compaction:createNextCompactionConfig(l.compaction,r,i)};if(isSandboxEnabled(t)){let{getCodeModeInterrupt:e}=await loadCodeModeModule(),a=e(i);if(a!==void 0)return parkOnCodeModeInterrupt({baseSession:f,config:t,emit:n,emissionState:s,interrupt:a,promptMessages:r,responseMessages:u})}let p=extractToolApprovalInputRequests({content:i.content??[]}),h=new Set(p.map(e=>e.action.callId)),g=extractQuestionInputRequests({toolCalls:i.toolCalls,excludedCallIds:h}),_=[...p,...g],v=(i.toolCalls??[]).filter(e=>!isInvalidToolCall(e)).filter(e=>t.tools.get(e.toolName)?.runtimeAction!==void 0).map(e=>createRuntimeActionRequestFromToolCall({toolCall:e,tools:t.tools}));if(v.length>0)return{next:null,session:setHarnessEmissionState(setPendingRuntimeActionBatch({actions:v,event:{sequence:s.sequence,stepIndex:s.stepIndex,turnId:s.turnId},responseMessages:u,session:{...f,history:[...r]}}),s)};if(_.length>0){let e=setPendingInputBatch({requests:_,responseMessages:u,session:{...f,history:[...r]}});return n&&(await n(createInputRequestedEvent({requests:_,sequence:s.sequence,stepIndex:s.stepIndex,turnId:s.turnId})),t.mode===`conversation`&&(s=await emitTurnEpilogue(n,s,t.mode),e=setHarnessEmissionState(e,s))),{next:null,session:e}}let y=(i.toolResults??[]).find(e=>isAuthorizationSignal(e.output));if(y&&isAuthorizationSignal(y.output)){let{challenges:e}=readToolInterrupt(loadContext(),y.toolCallId)??y.output;if(n)for(let t of e)await n(createAuthorizationRequiredEvent({authorization:t.challenge,name:t.name,description:t.challenge.instructions??`Authorization required for ${t.name}`,webhookUrl:t.hookUrl,sequence:s.sequence,stepIndex:s.stepIndex,turnId:s.turnId}));return{next:null,session:setHarnessEmissionState({...f,history:[...r],state:setPendingAuthorization(f.state,{challenges:e})},s)}}let b=pruneToolResults(r),x=b!==r,C=f.compaction;x&&C.lastKnownInputTokens!==void 0&&(C={recentWindowSize:C.recentWindowSize,threshold:C.threshold});let E=[...b,...u],D={...f,compaction:C,history:E};return!(D.outputSchema!==void 0&&extractFinalOutput(i)!==void 0)&&(u.at(-1)?.role===`tool`||hasDeferredStepInput(D))?(n&&(s=advanceStep(s),D=setHarnessEmissionState(D,s)),{next:o,session:D}):t.mode===`task`?finishTaskTurn({emissionState:s,emit:n,prunedHistory:b,result:i,schema:D.outputSchema,session:D,stepOutput:d}):finishConversationTurn({emissionState:s,emit:n,prunedHistory:b,result:i,schema:D.outputSchema,session:D})}const OUTPUT_SCHEMA_NOT_FULFILLED={code:`OUTPUT_SCHEMA_NOT_FULFILLED`,message:`The agent could not produce a result matching the requested schema.`};function extractFinalOutput(e){return(e.toolCalls??[]).find(e=>e.toolName===FINAL_OUTPUT_TOOL_NAME)?.input}function persistStructuredAssistantTurn(e,t,n){return{...e,history:[...t,{content:JSON.stringify(n),role:`assistant`}],outputSchema:void 0}}async function emitStructuredResult(e,t,n,r){return await e(createResultCompletedEvent({result:n,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),emitTurnEpilogue(e,t,r)}async function finishTaskTurn(e){let{emit:t,prunedHistory:n,result:r,schema:i,stepOutput:a}=e,{emissionState:o,session:s}=e;if(i===void 0)return t&&(o=await emitTurnEpilogue(t,o,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:a??``},session:s};let c=extractFinalOutput(r);return c===void 0?(t&&await emitFailedStep(t,o,{...OUTPUT_SCHEMA_NOT_FULFILLED,sessionId:s.sessionId}),{next:{done:!0,isError:!0,output:OUTPUT_SCHEMA_NOT_FULFILLED.message},session:s}):(s=persistStructuredAssistantTurn(s,n,c),t&&(o=await emitStructuredResult(t,o,c,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:c},session:s})}async function finishConversationTurn(e){let{emit:t,prunedHistory:n,result:r,schema:i}=e,{emissionState:a,session:o}=e;if(i===void 0)return t&&(a=await emitTurnEpilogue(t,a,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o};let s=extractFinalOutput(r);return s===void 0?(t&&(a=await emitRecoverableFailedTurn(t,a,OUTPUT_SCHEMA_NOT_FULFILLED),o=setHarnessEmissionState(o,a)),{next:null,session:o}):(o=persistStructuredAssistantTurn(o,n,s),t&&(a=await emitStructuredResult(t,a,s,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o})}async function continuePendingCodeModeInterrupt(e){let t=getPendingCodeModeInterrupt(e.session.state);if(t===void 0)return null;let{continueCodeModeApproval:n,continueCodeModeInterrupt:i,getCodeModeApprovalResponse:a,isCodeModeApprovalInterrupt:o,replaceCodeModeInterruptResult:s,unwrapCodeModeResult:c}=await loadCodeModeModule(),l=t.interrupt,d=o(l)?a([...e.messages],l):void 0;if(o(l)&&d===void 0)return{next:null,session:e.session};let f=createEveCodeModeOptions({lifecycle:e.emit===void 0?void 0:createCodeModeLifecycle({emit:e.emit,emissionState:e.emissionState,skipReplayed:!0,tools:e.config.tools})}),p;try{let t=await buildSandboxHostTools({approvedTools:getApprovedTools(e.session),capabilities:e.capabilities,tools:e.config.tools});if(o(l)&&d!==void 0)p=await n({approvalResponse:d,interrupt:l,options:f,tools:t});else if(isCodeModeConnectionAuthInterrupt(l))p=await i({interrupt:l,resolution:{status:`authorized`},tools:t,options:f});else if(isCodeModeRuntimeActionInterrupt(l)){let n=e.childResults??[],r=l,a=0;for(;;){p=await i({interrupt:r,resolution:n[a]?.output,tools:t,options:f});let e=c(p);if(e.status!==`interrupted`||!isCodeModeRuntimeActionInterrupt(e.interrupt)||a+1>=n.length)break;a++,r=e.interrupt}}else throw Error(`Unsupported code-mode interrupt kind "${l.payload.kind}".`)}catch(e){logError(log,`code-mode interrupt continuation failed`,e),p={error:`code_mode_continuation_failed`,message:toErrorMessage(e),retryable:!1}}let m=c(p),h=m.status===`interrupted`?m.interrupt:m.output,g=[...e.session.history,...t.responseMessages],_=isCodeModeRuntimeActionInterrupt(l)?replaceCodeModeToolResult(g,l.outerToolCallId,h):s(g,l,h),x=clearPendingCodeModeInterrupt({...e.session,history:_});if(m.status===`interrupted`){let t=e.session.history.length,n=_.slice(0,t),r=_.slice(t);return x={...x,history:n},parkOnCodeModeInterrupt({baseSession:x,config:e.config,emit:e.emit,emissionState:e.emissionState,interrupt:m.interrupt,promptMessages:n,responseMessages:r})}return{next:e.runStep,session:x}}function replaceCodeModeToolResult(e,t,n){if(t===void 0)return[...e];let r=typeof n==`string`?{type:`text`,value:n}:{type:`json`,value:n};return e.map(e=>{if(e.role!==`tool`)return e;let n=e.content.map(e=>e.type!==`tool-result`||e.toolCallId!==t?e:{...e,output:r});return{...e,content:n}})}async function parkOnCodeModeInterrupt(e){let{isCodeModeApprovalInterrupt:t,toCodeModeApprovalMessages:n}=await loadCodeModeModule(),r=e.interrupt,i={...e.baseSession,history:[...e.promptMessages]};if(isCodeModeConnectionAuthInterrupt(r)){let t=[...r.payload.challenges??[]];if(e.emit)for(let n of t)await e.emit(createAuthorizationRequiredEvent({authorization:n.challenge,name:n.name,description:n.challenge.instructions??`Authorization required for ${n.name}`,webhookUrl:n.hookUrl,sequence:e.emissionState.sequence,stepIndex:e.emissionState.stepIndex,turnId:e.emissionState.turnId}));return{next:null,session:setPendingCodeModeInterrupt({interrupt:r,responseMessages:e.responseMessages,session:{...i,state:setPendingAuthorization(i.state,{challenges:t})}})}}if(t(r)){let t=n(r),a=extractToolApprovalInputRequests({content:extractAssistantContent(t)}),o=setPendingInputBatch({requests:a,responseMessages:t,session:setPendingCodeModeInterrupt({interrupt:r,responseMessages:e.responseMessages,session:i})});if(e.emit&&(await e.emit(createInputRequestedEvent({requests:a,sequence:e.emissionState.sequence,stepIndex:e.emissionState.stepIndex,turnId:e.emissionState.turnId})),e.config.mode===`conversation`)){let t=await emitTurnEpilogue(e.emit,e.emissionState,e.config.mode);o=setHarnessEmissionState(o,t)}return{next:null,session:o}}return{next:null,session:setHarnessEmissionState(setPendingCodeModeInterrupt({interrupt:r,responseMessages:e.responseMessages,session:i}),e.emissionState)}}function extractAssistantContent(e){let t=[];for(let n of e)n.role===`assistant`&&Array.isArray(n.content)&&t.push(...n.content);return t}function createNextCompactionConfig(e,t,n){let r={recentWindowSize:e.recentWindowSize,threshold:e.threshold};return n.usage?.inputTokens!==void 0&&(r.lastKnownInputTokens=n.usage.inputTokens,r.lastKnownPromptMessageCount=t.length),r}async function maybeCompact(e){let{emit:t,emissionState:n}=e,r=e.messages,i=e.session;if(!shouldCompact(r,i.compaction))return{messages:r,session:i};let a=await resolveCompactionModel({compactionModelReference:i.agent.compactionModelReference,model:e.model,modelReference:i.agent.modelReference,resolveModel:e.resolveModel});if(t&&await t(createCompactionRequestedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId,usageInputTokens:getInputTokenCount(r,i.compaction)})),r=await compactMessages(r,a.model,i.compaction,a.providerOptions,e.telemetry,e.headers),e.onCompaction)for(let t of e.onCompaction())r.push(t);return t&&await t(createCompactionCompletedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId})),{messages:r,session:i}}function resolveApprovalKeyFromTools(e){return t=>{let n=e.get(t.action.toolName);if(n?.approvalKey!==void 0)return n.approvalKey(t.action.input)}}async function runModelCallWithRetries(e,t){for(let n=1;;n++)try{return await e()}catch(e){if(n===3||classifyModelCallError(e)!==`retry`)throw e;let r=500*2**(n-1)+Math.floor(Math.random()*250);log.warn(`model call failed transiently — retrying`,{attempt:n,delayMs:r,sessionId:t.sessionId,turnId:t.turnId,error:e}),await new Promise(e=>setTimeout(e,r))}}export{createToolLoopHarness};
|
|
1
|
+
import{createErrorId,createLogger,formatError,logError,recordErrorOnSpan}from"#internal/logging.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{createAuthorizationRequiredEvent,createCompactionCompletedEvent,createCompactionRequestedEvent,createInputRequestedEvent,createResultCompletedEvent}from"#protocol/message.js";import{toErrorMessage}from"#shared/errors.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{contextStorage,loadContext}from"#context/container.js";import{ToolLoopAgent,isStepCount}from"ai";import{setEveAttributes}from"#runtime/attributes/emit.js";import{isCodeModeRuntimeActionInterrupt}from"#harness/code-mode-runtime-action-state.js";import{clearPendingCodeModeInterrupt,getPendingCodeModeInterrupt,setPendingCodeModeInterrupt}from"#harness/code-mode-interrupt-state.js";import{createRuntimeActionRequestFromToolCall,resolvePendingRuntimeActions,setPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{advanceStep,emitFailedStep,emitRecoverableFailedTurn,emitStepStarted,emitStreamContent,emitTurnEpilogue,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{CODE_MODE_TOOL_NAME,loadCodeModeModule}from"#shared/code-mode.js";import{resolveAssistantStepText}from"#harness/messages.js";import{buildDynamicInstructionMessages}from"#context/dynamic-instruction-lifecycle.js";import{PendingSkillAnnouncementKey}from"#context/dynamic-skill-lifecycle.js";import{consumeDeferredStepInput,getApprovedTools,hasDeferredStepInput,hasStepInput,resolvePendingInput,setPendingInputBatch}from"#harness/input-requests.js";import{isAuthorizationSignal,setPendingAuthorization}from"#harness/authorization.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{isCodeModeConnectionAuthInterrupt}from"#runtime/framework-tools/code-mode-connection-auth.js";import{isSandboxEnabled,selectSandboxSurfaces}from"#harness/sandbox-surface.js";import{buildToolSetWithProviderTools}from"#harness/tools.js";import{ASK_QUESTION_TOOL_NAME}from"#runtime/framework-tools/ask-question.js";import{WEB_SEARCH_TOOL_DEFINITION}from"#runtime/framework-tools/web-search.js";import{extractQuestionInputRequests,extractToolApprovalInputRequests}from"#harness/input-extraction.js";import{applyLastToolCacheBreakpoint,applySystemCacheBreakpoint,detectPromptCachePath,getAnthropicCacheMarker}from"#harness/prompt-cache.js";import{resolveFrameworkToolFromUpstreamType,resolveGatewayPinForWebSearchBackend,resolveWebSearchBackend}from"#harness/provider-tools.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{hydrateSandboxAttachments,stageAttachmentsToSandbox}from"#harness/attachment-staging.js";import{applySandboxToolSet,buildSandboxHostTools,createEveCodeModeOptions}from"#harness/code-mode.js";import{createCodeModeLifecycle}from"#harness/code-mode-lifecycle.js";import{compactMessages,getInputTokenCount,resolveCompactionModel,shouldCompact}from"#harness/compaction.js";import{accumulateTurnUsage,getTurnUsageState,setTurnUsageState}from"#harness/turn-tag-state.js";import{buildTelemetryRuntimeContext}from"#harness/instrumentation-runtime-context.js";import{getInstrumentationConfig}from"#harness/instrumentation-config.js";import{readToolInterrupt}from"#harness/tool-interrupts.js";import{EmptyModelResponseError,classifyModelCallError,extractModelCallErrorDetails,extractUnsupportedProviderToolTypes,isNoOutputGeneratedError,summarizeKnownModelCallConfigError,summarizeKnownModelCallRequestError}from"#harness/model-call-error.js";import{extractWorkflowStreamWriteErrorDetails}from"#harness/workflow-stream-error.js";import{ensureOtelIntegration}from"#harness/otel-integration.js";import{buildStepHooks,emitStepActions,isInvalidToolCall}from"#harness/step-hooks.js";import{pruneToolResults}from"#harness/tool-result-pruning.js";import{FINAL_OUTPUT_TOOL_NAME,buildFinalOutputTool}from"#runtime/framework-tools/final-output.js";const environment=process.env.NODE_ENV??`unknown`,eveVersion=resolveInstalledPackageInfo().version,log=createLogger(`harness.tool-loop`);function logToolExecutionError(e){e.toolOutput.type===`tool-error`&&logError(log,`tool execution failed`,e.toolOutput.error,{toolName:e.toolCall.toolName,toolCallId:e.toolCall.toolCallId})}function enrichTelemetry(e,t,n){if(e===void 0)return;let r={};for(let e of Object.keys(n??{}))r[e]=!0;return{functionId:e.functionId??t,includeRuntimeContext:r,isEnabled:!0,recordInputs:e.recordInputs??!0,recordOutputs:e.recordOutputs??!0}}function resolveGatewayPinForStep(e){if(e.cachePath.kind!==`gateway-auto`||e.tools[WEB_SEARCH_TOOL_DEFINITION.name]===void 0)return;let t=resolveWebSearchBackend(e.modelReference);return t===null?void 0:resolveGatewayPinForWebSearchBackend(t)??void 0}function buildGatewayAttributionHeaders(e,t){if(typeof e!=`string`)return;let n=t?.agentName??t?.agentId,r=process.env.VERCEL_PROJECT_PRODUCTION_URL||process.env.VERCEL_URL,i=r?`https://${r}`:void 0;if(!n&&!i)return;let a={};return n&&(a[`x-title`]=n),i&&(a[`http-referer`]=i),a}const TURN_TRACE_STATE_KEY=`eve.harness.turnTrace`;function getTurnTraceState(e){return e.state?.[TURN_TRACE_STATE_KEY]}function setTurnTraceState(e,t){let n={traceId:t.traceId,spanId:t.spanId,traceFlags:t.traceFlags};return{...e,state:{...e.state,[TURN_TRACE_STATE_KEY]:n}}}function resolveStepOtelContext(e,t,n){if(t)return trace.setSpan(context.active(),t);if(e){let e=getTurnTraceState(n);if(e){let t=trace.wrapSpanContext({traceId:e.traceId,spanId:e.spanId,traceFlags:e.traceFlags});return trace.setSpan(context.active(),t)}}}function createToolLoopHarness(t){let n=t.handleEvent,o=getInstrumentationConfig();o!==void 0&&ensureOtelIntegration();let s=o===void 0?void 0:trace.getTracer(`eve`),c=t.runtimeIdentity?.agentName;async function runStep(e,t){let n;if(s&&hasStepInput(t)){let t=o?.functionId??c,r={"eve.version":eveVersion,"eve.environment":environment,"eve.session.id":e.sessionId};t&&(r[`ai.telemetry.functionId`]=t),n=s.startSpan(`ai.eve.turn`,{attributes:r})}let r=resolveStepOtelContext(s,n,e),executeStep=()=>executeStepBody(e,t,n);try{return r?await context.with(r,executeStep):await executeStep()}finally{n?.end()}}async function executeStepBody(s,l,u){let f=s;u&&(f=setTurnTraceState(f,u.spanContext()));let m=getHarnessEmissionState(f.state),v=consumeDeferredStepInput({input:l,session:f});f=v.session;let y=await resolvePendingRuntimeActions({emit:n,session:f,stepInput:v.input});if(y.outcome===`unresolved`)return{next:null,session:y.session};f=y.session;let b=resolvePendingInput({history:y.messages,resolveApprovalKey:resolveApprovalKeyFromTools(t.tools),session:f,stepInput:v.input});if(b.outcome===`unresolved`)return{next:null,session:b.session};n&&hasStepInput(l)&&(m=await emitTurnPreamble(n,l??{},m,t.runtimeIdentity),f=setHarnessEmissionState(f,m),u&&u.setAttribute(`eve.turn.id`,m.turnId)),f=b.session;let x=b.messages;if(v.input?.context!==void 0)for(let e of v.input.context)x.push({content:e,role:`user`});if(v.input?.message!==void 0&&!b.deferredMessage){let e=await stageAttachmentsToSandbox(v.input.message);x.push({content:e,role:`user`})}let S=await t.resolveModel(f.agent.modelReference),w=detectPromptCachePath(S),T=w.kind===`anthropic-direct`?getAnthropicCacheMarker():void 0,O=buildGatewayAttributionHeaders(S,t.runtimeIdentity);({messages:x,session:f}=await maybeCompact({emit:n,emissionState:m,headers:O,messages:x,model:S,onCompaction:t.onCompaction,resolveModel:t.resolveModel,session:f,telemetry:enrichTelemetry(o,c)??void 0}));let k=getApprovedTools(f),A=contextStorage.getStore(),j=await hydrateSandboxAttachments(x),M=[],N=[];for(let e of j)e.role===`system`?M.push(e):N.push(e);if(A!==void 0){M.push(...buildDynamicInstructionMessages(A));let e=A.get(PendingSkillAnnouncementKey);e!==void 0&&e.length>0&&M.push({role:`system`,content:e})}let P=N,prepareModelCallInput=e=>{let t=e?[{role:`system`,content:e}]:[],n=f.agent.system?[{role:`system`,content:f.agent.system}]:[],r=M.length>0||t.length>0?[...t,...n,...M]:void 0,i=r!==void 0&&T?applySystemCacheBreakpoint(r,T):r??f.agent.system??void 0;return{instructions:i,telemetryRuntimeContext:buildTelemetryRuntimeContext({eveVersion,authored:o,emissionState:m,environment,modelInput:{instructions:i,messages:P},session:f})}},runOneModelCall=async e=>{let{instructions:i,telemetryRuntimeContext:a={}}=e.preparedInput??prepareModelCallInput(e.extraSystemNote);e.retryReason&&(a[`eve.retry.reason`]=e.retryReason);let s=e.trailingUserNote?[...P,{role:`user`,content:e.trailingUserNote}]:P,l=selectSandboxSurfaces(t),u=await buildToolSetWithProviderTools({approvedTools:k,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,modelReference:f.agent.modelReference,tools:t.tools});if(A!==void 0){let e=buildDynamicTools(A);for(let t of e)u[t.name]??={description:t.description,inputSchema:t.inputSchema,execute:t.execute,outputSchema:t.outputSchema}}f.outputSchema!==void 0&&(u[FINAL_OUTPUT_TOOL_NAME]=buildFinalOutputTool(f.outputSchema));let d=l.length>0?(await applySandboxToolSet({harnessTools:t.tools,lifecycle:n===void 0?void 0:createCodeModeLifecycle({emit:n,emissionState:m,tools:t.tools}),tools:u,surfaces:l})).modelTools:u,p=T?applyLastToolCacheBreakpoint(d,T):d,_=resolveGatewayPinForStep({cachePath:w,modelReference:f.agent.modelReference,tools:p}),v=buildStepHooks({cachePath:w,emit:n,emissionState:m,emitStepStarted:e.suppressStepStartedEmission!==!0,gatewayPinProvider:_,marker:T,session:f}),y=new ToolLoopAgent({headers:O,instructions:i,model:S,onToolExecutionEnd:logToolExecutionError,onError(e){logError(log,`tool-loop stream error`,e.error)},onStepFinish:v.onStepFinish,prepareStep:v.prepareStep,runtimeContext:a,stopWhen:isStepCount(1),telemetry:enrichTelemetry(o,c,a),tools:p}),executeModelCall=async()=>{if(n){let e=await y.stream({messages:s}),{inlineActionResultCallIds:r,inlineToolResultParts:i}=await emitStreamContent(n,m,e.fullStream),a=await v.stepResult;if(isEmptyModelResponse(a))throw new EmptyModelResponseError;return await emitStepActions(n,m,a,{excludedActionToolNames:new Set([ASK_QUESTION_TOOL_NAME,CODE_MODE_TOOL_NAME,FINAL_OUTPUT_TOOL_NAME]),inlineActionResultCallIds:r,tools:t.tools}),i.length>0?{content:a.content,finishReason:a.finishReason,response:{...a.response,messages:[{role:`tool`,content:[...i]},...a.response.messages]},text:a.text,toolCalls:a.toolCalls,toolResults:a.toolResults,usage:a.usage}:a}await y.generate({messages:s});let e=await v.stepResult;if(isEmptyModelResponse(e))throw new EmptyModelResponseError;return e};return runModelCallWithRetries(()=>executeModelCall().catch(rethrowNoOutputAsEmptyResponse),{sessionId:f.sessionId,turnId:m.turnId})},F=prepareModelCallInput();n&&await emitStepStarted(n,m,x);let I=await continuePendingCodeModeInterrupt({capabilities:t.capabilities,childResults:v.input?.runtimeActionResults,config:t,emit:n,emissionState:m,messages:x,runStep,session:f});if(I!==null)return I;let L;try{L=await runOneModelCall({preparedInput:F,suppressStepStartedEmission:!0})}catch(r){let a=await runModelCallRecoveryPipeline({error:r,stages:[e=>attemptUnsupportedProviderToolRecovery({error:e.error,runOneModelCall,sessionId:f.sessionId,turnId:m.turnId}),e=>attemptEmptyResponseRecovery({error:e.error,retryCallOptions:e.retryCallOptions,runOneModelCall,sessionId:f.sessionId,turnId:m.turnId})]});if(a.outcome===`recovered`)L=a.result;else{let r=a.error;if(u&&recordErrorOnSpan(u,r),!n)throw r;let o=extractWorkflowStreamWriteErrorDetails(r);if(o!==null){let t=createErrorId();return log.error(`workflow stream write failed — parking session for retry by the user`,{...o,errorId:t,error:r,sessionId:f.sessionId,turnId:m.turnId}),m=await emitRecoverableFailedTurn(n,m,{code:`WORKFLOW_STREAM_WRITE_FAILED`,details:{...o,errorId:t},message:toErrorMessage(r)}),{next:null,session:setHarnessEmissionState(f,m)}}let s=classifyModelCallError(r),c=createErrorId(),l=s===`terminal`?summarizeKnownModelCallConfigError(r):null,p=l===null?summarizeKnownModelCallRequestError(r):null,h=l?.message??p?.message??toErrorMessage(r),g=extractModelCallErrorDetails(r),_=buildModelCallFailureDetails({configSummary:l,error:r,errorId:c,modelCallDetails:g,requestSummary:p}),v=buildModelCallFailureLogFields({error:r,errorId:c,modelCallDetails:g,requestSummary:p,sessionId:f.sessionId,turnId:m.turnId});return s===`terminal`?(l===null?log.error(p?.message??`model call failed terminally`,v):log.error(`${l.name}: ${l.message}`,{errorId:c,sessionId:f.sessionId,turnId:m.turnId}),await emitFailedStep(n,m,{code:`MODEL_CALL_FAILED`,details:_,message:h,sessionId:f.sessionId}),{next:{done:!0,output:``},session:f}):t.mode===`task`?(log.error(p?.message??`model call failed; failing the task run`,v),await emitFailedStep(n,m,{code:`MODEL_CALL_FAILED`,details:_,message:h,sessionId:f.sessionId}),{next:{done:!0,isError:!0,output:h},session:f}):(log.error(p?.message??`model call failed — parking session for retry by the user`,v),m=await emitRecoverableFailedTurn(n,m,{code:`MODEL_CALL_FAILED`,details:_,message:h}),{next:null,session:setHarnessEmissionState(f,m)})}}let R=accumulateTurnUsage({previous:getTurnUsageState(f.state),turnId:m.turnId,usage:L.usage??{}});f=setTurnUsageState(f,R);let z;try{z=formatLanguageModelGatewayId(S)}catch{z=void 0}return await setEveAttributes({"$eve.model":z,"$eve.input_tokens":R.inputTokens,"$eve.output_tokens":R.outputTokens,"$eve.cache_read_tokens":R.cacheReadTokens,"$eve.tool_count":t.tools.size}),handleStepResult({config:t,emit:n,emissionState:m,promptMessages:x,result:L,runStep,session:f})}return runStep}function buildModelCallFailureDetails(e){let{configSummary:t,error:r,errorId:i,modelCallDetails:a,requestSummary:o}=e;return t===null?o===null?{...formatError(r,i),...a}:{errorId:i,message:toErrorMessage(r),name:o.name,...a}:{errorId:i,message:t.message,name:t.name,...a}}function buildModelCallFailureLogFields(e){let t={errorId:e.errorId,sessionId:e.sessionId,turnId:e.turnId};return e.requestSummary===null?{...t,error:e.error}:{...t,details:e.modelCallDetails}}async function runModelCallRecoveryPipeline(e){let t=e.error,n;for(let r of e.stages){let e=await r({error:t,retryCallOptions:n});if(e.outcome===`recovered`)return e;e.outcome===`failed`&&(t=e.error,n=e.retryCallOptions)}return{outcome:`failed`,error:t}}async function attemptUnsupportedProviderToolRecovery(e){let t=extractUnsupportedProviderToolTypes(e.error);if(t.length===0)return{outcome:`skipped`};let n=[];for(let e of t){let t=resolveFrameworkToolFromUpstreamType(e);t!==null&&!n.includes(t)&&n.push(t)}if(n.length===0)return{outcome:`skipped`};log.warn(`disabling unsupported provider tool(s); retrying step once`,{disabled:n,sessionId:e.sessionId,turnId:e.turnId,upstreamTypes:t});let r={disabledProviderTools:new Set(n),extraSystemNote:buildDisabledToolNote(n)};try{return{outcome:`recovered`,result:await e.runOneModelCall({...r,suppressStepStartedEmission:!0})}}catch(e){return{outcome:`failed`,error:e,retryCallOptions:r}}}function buildDisabledToolNote(e){let t=e.join(`, `);return`The following ${e.length===1?`tool is`:`tools are`} not available with the current model and has been removed: ${t}. Proceed using the remaining tools or your training knowledge.`}function isEmptyModelResponse(e){return e.finishReason===`other`&&e.toolCalls.length===0&&resolveAssistantStepText(e.response.messages,e.text)===null}function rethrowNoOutputAsEmptyResponse(e){throw isNoOutputGeneratedError(e)?new EmptyModelResponseError({cause:e}):e}async function attemptEmptyResponseRecovery(e){if(!(e.error instanceof EmptyModelResponseError))return{outcome:`skipped`};log.warn(`empty model response; reissuing the model call once`,{sessionId:e.sessionId,turnId:e.turnId});try{return{outcome:`recovered`,result:await e.runOneModelCall({...e.retryCallOptions,retryReason:`empty-response`,suppressStepStartedEmission:!0,trailingUserNote:`Your previous reply was not delivered. Answer now from the tool results above; do not re-run tools or mention this notice.`})}}catch(t){return{outcome:`failed`,error:t,retryCallOptions:e.retryCallOptions}}}async function handleStepResult(e){let{config:t,emit:n,promptMessages:r,result:i,runStep:a}=e,{emissionState:s,session:c}=e,u=i.response.messages,d=resolveAssistantStepText(u,i.text),f={...c,compaction:createNextCompactionConfig(c.compaction,r,i)};if(isSandboxEnabled(t)){let{getCodeModeInterrupt:e}=await loadCodeModeModule(),a=e(i);if(a!==void 0)return parkOnCodeModeInterrupt({baseSession:f,config:t,emit:n,emissionState:s,interrupt:a,promptMessages:r,responseMessages:u})}let p=extractToolApprovalInputRequests({content:i.content??[]}),h=new Set(p.map(e=>e.action.callId)),g=extractQuestionInputRequests({toolCalls:i.toolCalls,excludedCallIds:h}),_=[...p,...g],v=(i.toolCalls??[]).filter(e=>!isInvalidToolCall(e)).filter(e=>t.tools.get(e.toolName)?.runtimeAction!==void 0).map(e=>createRuntimeActionRequestFromToolCall({toolCall:e,tools:t.tools}));if(v.length>0)return{next:null,session:setHarnessEmissionState(setPendingRuntimeActionBatch({actions:v,event:{sequence:s.sequence,stepIndex:s.stepIndex,turnId:s.turnId},responseMessages:u,session:{...f,history:[...r]}}),s)};if(_.length>0){let e=setPendingInputBatch({requests:_,responseMessages:u,session:{...f,history:[...r]}});return n&&(await n(createInputRequestedEvent({requests:_,sequence:s.sequence,stepIndex:s.stepIndex,turnId:s.turnId})),t.mode===`conversation`&&(s=await emitTurnEpilogue(n,s,t.mode),e=setHarnessEmissionState(e,s))),{next:null,session:e}}let y=(i.toolResults??[]).find(e=>isAuthorizationSignal(e.output));if(y&&isAuthorizationSignal(y.output)){let{challenges:e}=readToolInterrupt(loadContext(),y.toolCallId)??y.output;if(n)for(let t of e)await n(createAuthorizationRequiredEvent({authorization:t.challenge,name:t.name,description:t.challenge.instructions??`Authorization required for ${t.name}`,webhookUrl:t.hookUrl,sequence:s.sequence,stepIndex:s.stepIndex,turnId:s.turnId}));return{next:null,session:setHarnessEmissionState({...f,history:[...r],state:setPendingAuthorization(f.state,{challenges:e})},s)}}let b=pruneToolResults(r),x=b!==r,C=f.compaction;x&&C.lastKnownInputTokens!==void 0&&(C={recentWindowSize:C.recentWindowSize,threshold:C.threshold});let E=[...b,...u],D={...f,compaction:C,history:E};return!(D.outputSchema!==void 0&&extractFinalOutput(i)!==void 0)&&(u.at(-1)?.role===`tool`||hasDeferredStepInput(D))?(n&&(s=advanceStep(s),D=setHarnessEmissionState(D,s)),{next:a,session:D}):t.mode===`task`?finishTaskTurn({emissionState:s,emit:n,prunedHistory:b,result:i,schema:D.outputSchema,session:D,stepOutput:d}):finishConversationTurn({emissionState:s,emit:n,prunedHistory:b,result:i,schema:D.outputSchema,session:D})}const OUTPUT_SCHEMA_NOT_FULFILLED={code:`OUTPUT_SCHEMA_NOT_FULFILLED`,message:`The agent could not produce a result matching the requested schema.`};function extractFinalOutput(e){return(e.toolCalls??[]).find(e=>e.toolName===FINAL_OUTPUT_TOOL_NAME)?.input}function persistStructuredAssistantTurn(e,t,n){return{...e,history:[...t,{content:JSON.stringify(n),role:`assistant`}],outputSchema:void 0}}async function emitStructuredResult(e,t,n,r){return await e(createResultCompletedEvent({result:n,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),emitTurnEpilogue(e,t,r)}async function finishTaskTurn(e){let{emit:t,prunedHistory:n,result:r,schema:i,stepOutput:a}=e,{emissionState:o,session:s}=e;if(i===void 0)return t&&(o=await emitTurnEpilogue(t,o,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:a??``},session:s};let c=extractFinalOutput(r);return c===void 0?(t&&await emitFailedStep(t,o,{...OUTPUT_SCHEMA_NOT_FULFILLED,sessionId:s.sessionId}),{next:{done:!0,isError:!0,output:OUTPUT_SCHEMA_NOT_FULFILLED.message},session:s}):(s=persistStructuredAssistantTurn(s,n,c),t&&(o=await emitStructuredResult(t,o,c,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:c},session:s})}async function finishConversationTurn(e){let{emit:t,prunedHistory:n,result:r,schema:i}=e,{emissionState:a,session:o}=e;if(i===void 0)return t&&(a=await emitTurnEpilogue(t,a,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o};let s=extractFinalOutput(r);return s===void 0?(t&&(a=await emitRecoverableFailedTurn(t,a,OUTPUT_SCHEMA_NOT_FULFILLED),o=setHarnessEmissionState(o,a)),{next:null,session:o}):(o=persistStructuredAssistantTurn(o,n,s),t&&(a=await emitStructuredResult(t,a,s,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o})}async function continuePendingCodeModeInterrupt(e){let t=getPendingCodeModeInterrupt(e.session.state);if(t===void 0)return null;let{continueCodeModeApproval:n,continueCodeModeInterrupt:i,getCodeModeApprovalResponse:a,isCodeModeApprovalInterrupt:o,replaceCodeModeInterruptResult:s,unwrapCodeModeResult:c}=await loadCodeModeModule(),l=t.interrupt,u=o(l)?a([...e.messages],l):void 0;if(o(l)&&u===void 0)return{next:null,session:e.session};let f=createEveCodeModeOptions({lifecycle:e.emit===void 0?void 0:createCodeModeLifecycle({emit:e.emit,emissionState:e.emissionState,skipReplayed:!0,tools:e.config.tools})}),p;try{let t=await buildSandboxHostTools({approvedTools:getApprovedTools(e.session),capabilities:e.capabilities,tools:e.config.tools});if(o(l)&&u!==void 0)p=await n({approvalResponse:u,interrupt:l,options:f,tools:t});else if(isCodeModeConnectionAuthInterrupt(l))p=await i({interrupt:l,resolution:{status:`authorized`},tools:t,options:f});else if(isCodeModeRuntimeActionInterrupt(l)){let n=e.childResults??[],r=l,a=0;for(;;){p=await i({interrupt:r,resolution:n[a]?.output,tools:t,options:f});let e=c(p);if(e.status!==`interrupted`||!isCodeModeRuntimeActionInterrupt(e.interrupt)||a+1>=n.length)break;a++,r=e.interrupt}}else throw Error(`Unsupported code-mode interrupt kind "${l.payload.kind}".`)}catch(e){logError(log,`code-mode interrupt continuation failed`,e),p={error:`code_mode_continuation_failed`,message:toErrorMessage(e),retryable:!1}}let m=c(p),h=m.status===`interrupted`?m.interrupt:m.output,g=[...e.session.history,...t.responseMessages],_=isCodeModeRuntimeActionInterrupt(l)?replaceCodeModeToolResult(g,l.outerToolCallId,h):s(g,l,h),x=clearPendingCodeModeInterrupt({...e.session,history:_});if(m.status===`interrupted`){let t=e.session.history.length,n=_.slice(0,t),r=_.slice(t);return x={...x,history:n},parkOnCodeModeInterrupt({baseSession:x,config:e.config,emit:e.emit,emissionState:e.emissionState,interrupt:m.interrupt,promptMessages:n,responseMessages:r})}return{next:e.runStep,session:x}}function replaceCodeModeToolResult(e,t,n){if(t===void 0)return[...e];let r=typeof n==`string`?{type:`text`,value:n}:{type:`json`,value:n};return e.map(e=>{if(e.role!==`tool`)return e;let n=e.content.map(e=>e.type!==`tool-result`||e.toolCallId!==t?e:{...e,output:r});return{...e,content:n}})}async function parkOnCodeModeInterrupt(e){let{isCodeModeApprovalInterrupt:t,toCodeModeApprovalMessages:n}=await loadCodeModeModule(),r=e.interrupt,i={...e.baseSession,history:[...e.promptMessages]};if(isCodeModeConnectionAuthInterrupt(r)){let t=[...r.payload.challenges??[]];if(e.emit)for(let n of t)await e.emit(createAuthorizationRequiredEvent({authorization:n.challenge,name:n.name,description:n.challenge.instructions??`Authorization required for ${n.name}`,webhookUrl:n.hookUrl,sequence:e.emissionState.sequence,stepIndex:e.emissionState.stepIndex,turnId:e.emissionState.turnId}));return{next:null,session:setPendingCodeModeInterrupt({interrupt:r,responseMessages:e.responseMessages,session:{...i,state:setPendingAuthorization(i.state,{challenges:t})}})}}if(t(r)){let t=n(r),a=extractToolApprovalInputRequests({content:extractAssistantContent(t)}),o=setPendingInputBatch({requests:a,responseMessages:t,session:setPendingCodeModeInterrupt({interrupt:r,responseMessages:e.responseMessages,session:i})});if(e.emit&&(await e.emit(createInputRequestedEvent({requests:a,sequence:e.emissionState.sequence,stepIndex:e.emissionState.stepIndex,turnId:e.emissionState.turnId})),e.config.mode===`conversation`)){let t=await emitTurnEpilogue(e.emit,e.emissionState,e.config.mode);o=setHarnessEmissionState(o,t)}return{next:null,session:o}}return{next:null,session:setHarnessEmissionState(setPendingCodeModeInterrupt({interrupt:r,responseMessages:e.responseMessages,session:i}),e.emissionState)}}function extractAssistantContent(e){let t=[];for(let n of e)n.role===`assistant`&&Array.isArray(n.content)&&t.push(...n.content);return t}function createNextCompactionConfig(e,t,n){let r={recentWindowSize:e.recentWindowSize,threshold:e.threshold};return n.usage?.inputTokens!==void 0&&(r.lastKnownInputTokens=n.usage.inputTokens,r.lastKnownPromptMessageCount=t.length),r}async function maybeCompact(e){let{emit:t,emissionState:n}=e,r=e.messages,i=e.session;if(!shouldCompact(r,i.compaction))return{messages:r,session:i};let o=await resolveCompactionModel({compactionModelReference:i.agent.compactionModelReference,model:e.model,modelReference:i.agent.modelReference,resolveModel:e.resolveModel});if(t&&await t(createCompactionRequestedEvent({modelId:formatLanguageModelGatewayId(o.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId,usageInputTokens:getInputTokenCount(r,i.compaction)})),r=await compactMessages(r,o.model,i.compaction,o.providerOptions,e.telemetry,e.headers),e.onCompaction)for(let t of e.onCompaction())r.push(t);return t&&await t(createCompactionCompletedEvent({modelId:formatLanguageModelGatewayId(o.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId})),{messages:r,session:i}}function resolveApprovalKeyFromTools(e){return t=>{let n=e.get(t.action.toolName);if(n?.approvalKey!==void 0)return n.approvalKey(t.action.input)}}async function runModelCallWithRetries(e,t){for(let n=1;;n++)try{return await e()}catch(e){if(n===3||classifyModelCallError(e)!==`retry`)throw e;let r=500*2**(n-1)+Math.floor(Math.random()*250);log.warn(`model call failed transiently — retrying`,{attempt:n,delayMs:r,sessionId:t.sessionId,turnId:t.turnId,error:e}),await new Promise(e=>setTimeout(e,r))}}export{createToolLoopHarness};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire}from"node:module";import{basename,dirname,join}from"node:path";import{existsSync,readFileSync,realpathSync}from"node:fs";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const WORKFLOW_MODULE_ALIASES={"workflow/api":`src/compiled/@workflow/core/runtime.js`,"workflow/errors":`src/compiled/@workflow/errors/index.js`,"workflow/internal/private":`src/compiled/@workflow/core/private.js`,"workflow/runtime":`src/compiled/@workflow/core/runtime.js`};function resolveFallbackPackageVersion(){return`0.6.0-beta.
|
|
1
|
+
import{createRequire}from"node:module";import{basename,dirname,join}from"node:path";import{existsSync,readFileSync,realpathSync}from"node:fs";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const WORKFLOW_MODULE_ALIASES={"workflow/api":`src/compiled/@workflow/core/runtime.js`,"workflow/errors":`src/compiled/@workflow/errors/index.js`,"workflow/internal/private":`src/compiled/@workflow/core/private.js`,"workflow/runtime":`src/compiled/@workflow/core/runtime.js`};function resolveFallbackPackageVersion(){return`0.6.0-beta.14`}const FALLBACK_PACKAGE_INFO={name:EVE_PACKAGE_NAME,version:resolveFallbackPackageVersion()};function resolveCurrentModulePath(){return typeof __filename==`string`?__filename:resolveCurrentModulePathFromStack()}function resolveCurrentModulePathFromStack(){let e=Error.prepareStackTrace;try{Error.prepareStackTrace=(e,t)=>t;let e=Error().stack?.[0]?.getFileName();if(typeof e!=`string`||e.length===0)throw Error(`Failed to resolve the current module path from the stack trace.`);return e.startsWith(`file:`)?fileURLToPath(e):e}finally{Error.prepareStackTrace=e}}const require=createRequire(resolveCurrentModulePath());function isBuildOutputPackageRoot(e){return basename(e)===`dist`&&existsSync(join(dirname(e),`package.json`))}function resolvePackageBuildRoot(){let e=dirname(realpathSync(resolveCurrentModulePath()));for(;;){if(isBuildOutputPackageRoot(e))return e;let t=dirname(e);if(t===e)return null;e=t}}function findNearestPackageRoot(e){let t=e;for(;;){if(existsSync(join(t,`package.json`))&&!isBuildOutputPackageRoot(t))return t;let r=dirname(t);if(r===t)throw Error(`Failed to resolve package root from "${e}".`);t=r}}function resolvePackageRoot(){return findNearestPackageRoot(dirname(realpathSync(resolveCurrentModulePath())))}function tryResolvePackageRoot(){try{return resolvePackageRoot()}catch{return}}function rewriteSourceFilePathForBuild(e){return e.replace(/\.[cm]?tsx?$/,`.js`)}function resolvePackageSourceFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),e):join(t,rewriteSourceFilePathForBuild(e))}function resolvePackageSourceDirectoryPath(e){let t=resolvePackageBuildRoot();return join(t===null?resolvePackageRoot():t,e)}function resolvePackageDependencyPath(e){return require.resolve(e)}function resolvePackageCompiledFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),`.generated`,`compiled`,e.replace(/^src\/compiled\//,``)):join(t,e)}function normalizeInstalledPackageInfo(e){let t=e;if(!(typeof t.name!=`string`||typeof t.version!=`string`))return{name:t.name,version:t.version}}function tryReadInstalledPackageInfo(e,t){let n=normalizeInstalledPackageInfo(JSON.parse(readFileSync(e,`utf8`)));if(n?.name===t)return n}function resolveInstalledPackageInfo(){if(cachedPackageInfo)return cachedPackageInfo;let e=tryResolvePackageRoot(),t=e===void 0?void 0:tryReadInstalledPackageInfo(join(e,`package.json`),EVE_PACKAGE_NAME);if(t)return cachedPackageInfo=t,cachedPackageInfo;try{let e=tryReadInstalledPackageInfo(require.resolve(`${EVE_PACKAGE_NAME}/package.json`),EVE_PACKAGE_NAME);if(e)return cachedPackageInfo=e,cachedPackageInfo}catch{}return cachedPackageInfo={...FALLBACK_PACKAGE_INFO},cachedPackageInfo}function resolveWorkflowModulePath(e){if(e===`workflow`)return resolvePackageSourceFilePath(`src/internal/workflow/index.ts`);if(e===`workflow/internal/builtins`)return resolvePackageSourceFilePath(`src/internal/workflow/builtins.ts`);let t=WORKFLOW_MODULE_ALIASES[e];return t===void 0?require.resolve(e):resolvePackageCompiledFilePath(t)}export{resolveInstalledPackageInfo,resolvePackageDependencyPath,resolvePackageRoot,resolvePackageSourceDirectoryPath,resolvePackageSourceFilePath,resolveWorkflowModulePath};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ToolDefinition } from "#public/definitions/tool.js";
|
|
2
2
|
/**
|
|
3
|
-
* Input shape accepted by {@link
|
|
3
|
+
* Input shape accepted by {@link defineBashTool}.
|
|
4
4
|
*/
|
|
5
|
-
export interface
|
|
5
|
+
export interface DefineBashToolInput {
|
|
6
6
|
/**
|
|
7
7
|
* Optional model-facing description. Defaults to a generic
|
|
8
8
|
* "Execute a shell command in the workspace sandbox." line.
|
|
@@ -18,4 +18,4 @@ export interface DefineBeveToolInput {
|
|
|
18
18
|
* The tool's runtime name comes from the authored file's slug (for
|
|
19
19
|
* example `agent/tools/run_shell.ts` becomes a tool named `run_shell`).
|
|
20
20
|
*/
|
|
21
|
-
export declare function
|
|
21
|
+
export declare function defineBashTool(input?: DefineBashToolInput): ToolDefinition;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{BASH_INPUT_SCHEMA,BASH_OUTPUT_SCHEMA}from"#runtime/framework-tools/bash.js";import{
|
|
1
|
+
import{BASH_INPUT_SCHEMA,BASH_OUTPUT_SCHEMA}from"#runtime/framework-tools/bash.js";import{executeBashOnSandbox}from"#execution/sandbox/bash-tool.js";function defineBashTool(n={}){return{description:n.description??`Execute a shell command in the workspace sandbox.`,async execute(e,t){return executeBashOnSandbox(await t.getSandbox(),e)},inputSchema:BASH_INPUT_SCHEMA,outputSchema:BASH_OUTPUT_SCHEMA}}export{defineBashTool};
|
|
@@ -5,7 +5,7 @@ export { type DisabledToolSentinel, type EnableWorkflowToolSentinel, defineDynam
|
|
|
5
5
|
export type { DynamicToolEntry, DynamicEvents, DynamicToolEvents, DynamicResolveContext, DynamicSentinel, DynamicToolSet, DynamicToolResult, } from "#shared/dynamic-tool-definition.js";
|
|
6
6
|
export { type SessionContext } from "#public/definitions/callback-context.js";
|
|
7
7
|
export { toolResultFrom, type MatchedConnectionResult, type MatchedToolResult, type ToolResultFromFn, } from "#public/tool-result-narrowing.js";
|
|
8
|
-
export { type
|
|
8
|
+
export { type DefineBashToolInput, defineBashTool } from "#public/tools/define-bash-tool.js";
|
|
9
9
|
export { type DefineGlobToolInput, defineGlobTool } from "#public/tools/define-glob-tool.js";
|
|
10
10
|
export { type DefineGrepToolInput, defineGrepTool } from "#public/tools/define-grep-tool.js";
|
|
11
11
|
export { type DefineReadFileToolInput, defineReadFileTool, } from "#public/tools/define-read-file-tool.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ExperimentalWorkflow,defineDynamic,defineTool,disableTool,isDisabledToolSentinel,isEnableWorkflowToolSentinel}from"#public/definitions/tool.js";import{toolResultFrom}from"#public/tool-result-narrowing.js";import{
|
|
1
|
+
import{ExperimentalWorkflow,defineDynamic,defineTool,disableTool,isDisabledToolSentinel,isEnableWorkflowToolSentinel}from"#public/definitions/tool.js";import{toolResultFrom}from"#public/tool-result-narrowing.js";import{defineBashTool}from"#public/tools/define-bash-tool.js";import{defineGlobTool}from"#public/tools/define-glob-tool.js";import{defineGrepTool}from"#public/tools/define-grep-tool.js";import{defineReadFileTool}from"#public/tools/define-read-file-tool.js";import{defineWriteFileTool}from"#public/tools/define-write-file-tool.js";export{ExperimentalWorkflow,defineBashTool,defineDynamic,defineGlobTool,defineGrepTool,defineReadFileTool,defineTool,defineWriteFileTool,disableTool,isDisabledToolSentinel,isEnableWorkflowToolSentinel,toolResultFrom};
|
|
@@ -2,16 +2,16 @@ import type { JsonObject } from "#shared/json.js";
|
|
|
2
2
|
import type { ResolvedToolDefinition } from "#runtime/types.js";
|
|
3
3
|
/**
|
|
4
4
|
* Shared input schema used by the framework `bash` tool and any author tool
|
|
5
|
-
* constructed via {@link
|
|
5
|
+
* constructed via {@link defineBashTool}.
|
|
6
6
|
*
|
|
7
|
-
* Exported so the public `
|
|
7
|
+
* Exported so the public `defineBashTool` factory and the framework
|
|
8
8
|
* `BASH_TOOL_DEFINITION` use the exact same schema object — keeping model
|
|
9
9
|
* input contracts in sync without duplication.
|
|
10
10
|
*/
|
|
11
11
|
export declare const BASH_INPUT_SCHEMA: JsonObject;
|
|
12
12
|
/**
|
|
13
13
|
* Shared output schema used by the framework `bash` tool and any author tool
|
|
14
|
-
* constructed via {@link
|
|
14
|
+
* constructed via {@link defineBashTool}.
|
|
15
15
|
*/
|
|
16
16
|
export declare const BASH_OUTPUT_SCHEMA: JsonObject;
|
|
17
17
|
export declare const BASH_TOOL_DEFINITION: ResolvedToolDefinition;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{requireSandboxSession}from"#execution/sandbox/require-sandbox.js";import{
|
|
1
|
+
import{requireSandboxSession}from"#execution/sandbox/require-sandbox.js";import{executeBashOnSandbox}from"#execution/sandbox/bash-tool.js";const BASH_INPUT_SCHEMA={additionalProperties:!1,properties:{command:{description:`The shell command to execute.`,type:`string`}},required:[`command`],type:`object`},BASH_OUTPUT_SCHEMA={additionalProperties:!1,properties:{exitCode:{type:`number`},stderr:{type:`string`},stdout:{type:`string`},truncated:{type:`boolean`}},required:[`exitCode`,`stderr`,`stdout`,`truncated`],type:`object`};async function executeBash(e){return executeBashOnSandbox(await requireSandboxSession(),e)}const BASH_TOOL_DEFINITION={description:`Execute a shell command in the shared workspace environment.`,execute:executeBash,inputSchema:BASH_INPUT_SCHEMA,logicalPath:`eve:framework/bash`,name:`bash`,outputSchema:BASH_OUTPUT_SCHEMA,sourceId:`eve:bash-tool`,sourceKind:`module`};export{BASH_INPUT_SCHEMA,BASH_OUTPUT_SCHEMA,BASH_TOOL_DEFINITION};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash,timingSafeEqual}from"node:crypto";function authenticateHttpBasicStrategy(e){let t=parseBasicAuthorizationHeader(e.authorization);return t===null||t.username!==e.strategy.username||!timingSafeStringEquals(t.password,e.strategy.password)?{kind:`not-authenticated`}:{kind:`authenticated`,principal:{attributes:Object.freeze({}),authenticator:`http-basic`,claims:Object.freeze({}),principalId:e.strategy.username,principalType:`user`}}}function parseBasicAuthorizationHeader(e){let t=/^Basic\s+(.+)$/i.exec(e);if(t===null)return null;let n=t[1];if(n===void 0)return null;let r;try{r=Buffer.from(n,`base64`).toString(`utf8`)}catch{return null}let i=r.indexOf(`:`);return i===-1?null:{password:r.slice(i+1),username:r.slice(0,i)}}function timingSafeStringEquals(e,n){return timingSafeEqual(
|
|
1
|
+
import{createHash,timingSafeEqual}from"node:crypto";function authenticateHttpBasicStrategy(e){let t=parseBasicAuthorizationHeader(e.authorization);return t===null||t.username!==e.strategy.username||!timingSafeStringEquals(t.password,e.strategy.password)?{kind:`not-authenticated`}:{kind:`authenticated`,principal:{attributes:Object.freeze({}),authenticator:`http-basic`,claims:Object.freeze({}),principalId:e.strategy.username,principalType:`user`}}}function parseBasicAuthorizationHeader(e){let t=/^Basic\s+(.+)$/i.exec(e);if(t===null)return null;let n=t[1];if(n===void 0)return null;let r;try{r=Buffer.from(n,`base64`).toString(`utf8`)}catch{return null}let i=r.indexOf(`:`);return i===-1?null:{password:r.slice(i+1),username:r.slice(0,i)}}function timingSafeStringEquals(e,n){return timingSafeEqual(hashString(e),hashString(n))}function hashString(t){return createHash(`sha256`).update(t,`utf8`).digest()}export{authenticateHttpBasicStrategy};
|
|
@@ -77,4 +77,4 @@ export default defineAgent({
|
|
|
77
77
|
export default defineAgent({
|
|
78
78
|
model: "__EVE_INIT_MODEL__",
|
|
79
79
|
});
|
|
80
|
-
`,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate(e)}}function assertStampedVersion(e,t){if(t.startsWith(`__`))throw Error(`Scaffold received unstamped version token (${e}=${t}). Build eve before using its dist entrypoint.`)}async function assertCanCreateInPlace(e,n){if(!await pathExists(e))return;let r=(await readdir(e)).filter(e=>!ALLOWED_CREATE_IN_PLACE_ENTRIES.has(e));if(r.length>0&&!n){let e=r.slice(0,5).join(`, `),t=r.length>5?`, and ${r.length-5} more`:``;throw Error(`Cannot create project in current directory because it is not empty. Found: ${e}${t}. Pass --yes with --in-place to overwrite Eve scaffold files.`)}}async function scaffoldBaseProject(e){let r=resolve(e.targetDirectory??process.cwd(),e.projectName),i=e.projectName===`.`,a=e.overwriteExisting??!1,s=e.byokProvider??!1;if(i)await assertCanCreateInPlace(r,a);else if(await pathExists(r))throw Error(`Cannot create project because "${r}" already exists.`);let u={appName:basename(r),model:e.model,evePackageVersion:e.evePackageVersion??`0.6.0-beta.
|
|
80
|
+
`,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate(e)}}function assertStampedVersion(e,t){if(t.startsWith(`__`))throw Error(`Scaffold received unstamped version token (${e}=${t}). Build eve before using its dist entrypoint.`)}async function assertCanCreateInPlace(e,n){if(!await pathExists(e))return;let r=(await readdir(e)).filter(e=>!ALLOWED_CREATE_IN_PLACE_ENTRIES.has(e));if(r.length>0&&!n){let e=r.slice(0,5).join(`, `),t=r.length>5?`, and ${r.length-5} more`:``;throw Error(`Cannot create project in current directory because it is not empty. Found: ${e}${t}. Pass --yes with --in-place to overwrite Eve scaffold files.`)}}async function scaffoldBaseProject(e){let r=resolve(e.targetDirectory??process.cwd(),e.projectName),i=e.projectName===`.`,a=e.overwriteExisting??!1,s=e.byokProvider??!1;if(i)await assertCanCreateInPlace(r,a);else if(await pathExists(r))throw Error(`Cannot create project because "${r}" already exists.`);let u={appName:basename(r),model:e.model,evePackageVersion:e.evePackageVersion??`0.6.0-beta.14`,aiPackageVersion:e.aiPackageVersion??`7.0.0-canary.171`,zodPackageVersion:e.zodPackageVersion??`4.4.3`,tsgoPackageVersion:e.tsgoPackageVersion??`7.0.0-dev.20260523.1`,typesNodePackageVersion:e.typesNodePackageVersion??`25.9.1`};assertStampedVersion(`evePackageVersion`,u.evePackageVersion),assertStampedVersion(`aiPackageVersion`,u.aiPackageVersion),assertStampedVersion(`zodPackageVersion`,u.zodPackageVersion),assertStampedVersion(`tsgoPackageVersion`,u.tsgoPackageVersion),s&&assertStampedVersion(`typesNodePackageVersion`,u.typesNodePackageVersion),await mkdir(r,{recursive:!0});for(let[o,c]of Object.entries(templateFiles(s))){let s=`${r}/${o}`,l=await pathExists(s);await writeTextFile(s,renderTemplate(c,u),{force:i&&a}),l&&await e.onOverwriteFile?.(s)}return r}async function isEveProject(t){for(let n of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)try{return await stat(join(t,`agent`,`agent${n}`)),!0}catch{}return!1}export{CURRENT_DIRECTORY_PROJECT_NAME,byokProviderEnvVar,isEveProject,modelProviderSlug,scaffoldBaseProject};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"../files.js";import{PNPM_WORKSPACE_PATH,ensurePnpmWorkspacePolicy}from"./pnpm-workspace.js";import{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"../create/web-template.js";import"../create/project.js";import{patchPackageJson}from"./package-json.js";import{basename,join,resolve}from"node:path";import{readFile,readdir,writeFile}from"node:fs/promises";const SLACK_CHANNEL_DEFAULT_ROUTE=`/eve/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,WEB_VERCEL_JSON_PATH=`vercel.json`,WEB_VERCEL_JSON_SCHEMA=`https://openapi.vercel.sh/vercel.json`,WEB_COMPETING_NEXT_CONFIG_PATHS=[`next.config.js`,`next.config.mjs`,WEB_NEXT_CONFIG_PATH,`next.config.mts`].filter(e=>e!==WEB_NEXT_CONFIG_PATH),WEB_DEFAULT_VERCEL_SERVICES={web:{entrypoint:`.`,framework:`nextjs`,routePrefix:`/`},eve:{buildCommand:`eve build`,entrypoint:`.`,framework:`eve`,routePrefix:`/_eve_internal/eve`}};function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readDependencyVersion(e,t){let n=JSON.parse(await readFile(e,`utf8`));if(!isJsonObject(n)||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,t){if(!await pathExists(e))return!1;let r=JSON.parse(await readFile(e,`utf8`));return isJsonObject(r)&&packageJsonHasDependency(r,t)}async function ensurePackageDependency(e,t,r){return!await pathExists(e)||await readDependencyVersion(e,t)===r?[]:(await patchPackageJson(e,{dependencies:{[t]:r}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{evePackageVersion:e?.evePackageVersion??`0.6.0-beta.
|
|
1
|
+
import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"../files.js";import{PNPM_WORKSPACE_PATH,ensurePnpmWorkspacePolicy}from"./pnpm-workspace.js";import{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"../create/web-template.js";import"../create/project.js";import{patchPackageJson}from"./package-json.js";import{basename,join,resolve}from"node:path";import{readFile,readdir,writeFile}from"node:fs/promises";const SLACK_CHANNEL_DEFAULT_ROUTE=`/eve/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,WEB_VERCEL_JSON_PATH=`vercel.json`,WEB_VERCEL_JSON_SCHEMA=`https://openapi.vercel.sh/vercel.json`,WEB_COMPETING_NEXT_CONFIG_PATHS=[`next.config.js`,`next.config.mjs`,WEB_NEXT_CONFIG_PATH,`next.config.mts`].filter(e=>e!==WEB_NEXT_CONFIG_PATH),WEB_DEFAULT_VERCEL_SERVICES={web:{entrypoint:`.`,framework:`nextjs`,routePrefix:`/`},eve:{buildCommand:`eve build`,entrypoint:`.`,framework:`eve`,routePrefix:`/_eve_internal/eve`}};function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readDependencyVersion(e,t){let n=JSON.parse(await readFile(e,`utf8`));if(!isJsonObject(n)||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,t){if(!await pathExists(e))return!1;let r=JSON.parse(await readFile(e,`utf8`));return isJsonObject(r)&&packageJsonHasDependency(r,t)}async function ensurePackageDependency(e,t,r){return!await pathExists(e)||await readDependencyVersion(e,t)===r?[]:(await patchPackageJson(e,{dependencies:{[t]:r}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{evePackageVersion:e?.evePackageVersion??`0.6.0-beta.14`,aiPackageVersion:e?.aiPackageVersion??`7.0.0-canary.171`,nextPackageVersion:e?.nextPackageVersion??`16.2.6`,reactPackageVersion:e?.reactPackageVersion??`19.2.6`,reactDomPackageVersion:e?.reactDomPackageVersion??`19.2.6`,streamdownPackageVersion:e?.streamdownPackageVersion??`2.5.0`,zodPackageVersion:e?.zodPackageVersion??`4.4.3`,tsgoPackageVersion:e?.tsgoPackageVersion??`7.0.0-dev.20260523.1`,typesNodePackageVersion:e?.typesNodePackageVersion??`25.9.1`,typesReactPackageVersion:e?.typesReactPackageVersion??`19.2.15`,typesReactDomPackageVersion:e?.typesReactDomPackageVersion??`19.2.3`}}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}async function patchWebPackageJson(e,t){if(!await pathExists(e))return[];assertStampedVersion(`evePackageVersion`,t.evePackageVersion),assertStampedVersion(`aiPackageVersion`,t.aiPackageVersion),assertStampedVersion(`nextPackageVersion`,t.nextPackageVersion),assertStampedVersion(`reactPackageVersion`,t.reactPackageVersion),assertStampedVersion(`reactDomPackageVersion`,t.reactDomPackageVersion),assertStampedVersion(`streamdownPackageVersion`,t.streamdownPackageVersion),assertStampedVersion(`zodPackageVersion`,t.zodPackageVersion),assertStampedVersion(`tsgoPackageVersion`,t.tsgoPackageVersion),assertStampedVersion(`typesNodePackageVersion`,t.typesNodePackageVersion),assertStampedVersion(`typesReactPackageVersion`,t.typesReactPackageVersion),assertStampedVersion(`typesReactDomPackageVersion`,t.typesReactDomPackageVersion);let r={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:t.aiPackageVersion,eve:formatEveDependencySpecifier(t.evePackageVersion),next:t.nextPackageVersion,react:t.reactPackageVersion,"react-dom":t.reactDomPackageVersion,streamdown:t.streamdownPackageVersion,zod:t.zodPackageVersion},i={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":t.typesNodePackageVersion,"@types/react":t.typesReactPackageVersion,"@types/react-dom":t.typesReactDomPackageVersion,"@typescript/native-preview":t.tsgoPackageVersion},a=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts;return await patchPackageJson(e,{dependencies:r,devDependencies:i,scripts:a}),[{path:e,dependencies:Object.keys(r),devDependencies:Object.keys(i),scripts:Object.keys(a)}]}function normalizeSlackConnectorSlug(e){return toSlackConnectorSlug((e.trim().replace(/^@/,``).split(`/`).at(-1)??``).toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/[^a-z0-9]+$/,``).slice(0,100).replace(/[^a-z0-9]+$/,``)||`my-agent`)}async function deriveSlackConnectorSlug(e,t){if(t!==void 0&&t.length>0&&t!==`.`)return normalizeSlackConnectorSlug(t);try{let t=await readFile(join(e,`package.json`),`utf8`),n=JSON.parse(t);if(typeof n.name==`string`&&n.name.length>0)return normalizeSlackConnectorSlug(n.name)}catch{}return normalizeSlackConnectorSlug(basename(resolve(e))||`my-agent`)}function buildSlackTemplate(e){return`import { connectSlackCredentials } from "@vercel/connect/eve";
|
|
2
2
|
import { slackChannel } from "eve/channels/slack";
|
|
3
3
|
|
|
4
4
|
export default slackChannel({
|