eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
1 lines • 4.13 kB
JavaScript
import{markMockModel}from"#internal/mock-model-identity.js";import{MockLanguageModelV3}from"ai/test";import{AGENTS_SNIPPET_LABEL}from"#subagents/handles/prompt.js";import{isPendingApprovalsSnippet}from"#harness/hitl/approval-prompt.js";const RESPONSE_TIMESTAMP=Date.parse(`2026-01-01T00:00:00.000Z`);function mockModel(e={}){let t=normalizeOptions(e),n=normalizeResponder(t.respond),r=t.modelId??`model`;return markMockModel(new MockLanguageModelV3({modelId:r,provider:t.provider??`eve-mock`,doGenerate:async e=>createGenerateResult(await n(createRequest(e)),e,r),doStream:async e=>createStreamResult(createGenerateResult(await n(createRequest(e)),e,r))}))}function normalizeOptions(e){return typeof e==`string`||typeof e==`function`?{respond:e}:e}function normalizeResponder(e){if(typeof e==`function`)return e;let t=e??`Mock response`;return()=>t}function createRequest(e){let t=e.prompt.map(e=>({role:e.role,text:extractMessageText(e)})),n=t.filter(e=>e.role===`user`).map(e=>e.text).filter(e=>!isFrameworkScaffolding(e));return{lastUserMessage:n.at(-1)??null,messages:t,toolResults:extractToolResults(e),tools:extractTools(e),userMessageCount:n.length,userMessages:n}}function isFrameworkScaffolding(e){let t=e.trim();return t.startsWith(AGENTS_SNIPPET_LABEL)||isPendingApprovalsSnippet(t)}function extractMessageText(e){return typeof e.content==`string`?e.content:e.content.flatMap(e=>{switch(e.type){case`reasoning`:case`text`:return[e.text];case`tool-result`:return[formatValue(normalizeToolOutput(e.output))];default:return[]}}).join(``)}function extractTools(e){return(e.tools??[]).map(e=>e.type===`function`?{description:e.description,inputSchema:e.inputSchema,name:e.name}:{name:e.name})}function extractToolResults(e){return e.prompt.flatMap(e=>typeof e.content==`string`?[]:e.content.flatMap(e=>e.type===`tool-result`?[{id:e.toolCallId,isError:e.output.type===`error-json`||e.output.type===`error-text`||e.output.type===`execution-denied`,name:e.toolName,output:normalizeToolOutput(e.output)}]:[]))}function normalizeToolOutput(e){switch(e.type){case`error-json`:case`error-text`:case`json`:case`text`:return e.value;case`execution-denied`:return e.reason??`Tool execution denied`;case`content`:return e.value}}function createGenerateResult(e,t,n){let r=typeof e==`string`?{text:e}:e,i=r.toolCalls??[];if(!(`text`in r)&&i.length===0)throw Error(`mockModel responders must return text or at least one item in "toolCalls".`);let a=[];r.text!==void 0&&a.push({text:r.text,type:`text`});for(let[e,n]of i.entries())a.push({input:JSON.stringify(n.input??{}),toolCallId:n.id??`mock-tool-call-${countUserMessages(t)}-${countToolResults(t)}-${e+1}`,toolName:n.name,type:`tool-call`});let o=t.prompt.map(e=>extractMessageText(e)).join(` `),s=[r.text??``,...i.map(e=>formatValue(e.input??{}))].join(` `),c=r.usage?.inputTokens??estimateTokens(o),l=r.usage?.outputTokens??estimateTokens(s);return{content:a,finishReason:{raw:void 0,unified:i.length>0?`tool-calls`:`stop`},response:{id:`mock-response-${countUserMessages(t)}-${countToolResults(t)}`,modelId:n,timestamp:new Date(RESPONSE_TIMESTAMP)},usage:{inputTokens:{cacheRead:0,cacheWrite:0,noCache:c,total:c},outputTokens:{reasoning:0,text:l,total:l}},warnings:[]}}function createStreamResult(e){let t=[{type:`stream-start`,warnings:e.warnings}];e.response!==void 0&&t.push({...e.response,type:`response-metadata`});let n=0;for(let r of e.content){if(r.type===`text`){let e=`mock-text-${n}`;n+=1,t.push({id:e,type:`text-start`}),r.text.length>0&&t.push({delta:r.text,id:e,type:`text-delta`}),t.push({id:e,type:`text-end`});continue}r.type===`tool-call`&&t.push(r)}return t.push({finishReason:e.finishReason,type:`finish`,usage:e.usage}),{stream:new ReadableStream({start(e){for(let n of t)e.enqueue(n);e.close()}})}}function countUserMessages(e){return e.prompt.filter(e=>e.role===`user`).length}function countToolResults(e){return extractToolResults(e).length}function estimateTokens(e){return Math.max(1,Math.ceil(e.trim().length/4))}function formatValue(e){if(typeof e==`string`)return e;try{return JSON.stringify(e)??String(e)}catch{return String(e)}}export{mockModel};