gemi 0.163.3 → 0.165.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/ai/client/index.d.ts +1 -0
  2. package/dist/ai/client/index.d.ts.map +1 -1
  3. package/dist/ai/client/index.js +49 -4
  4. package/dist/ai/client/index.js.map +1 -1
  5. package/dist/ai/client/reducer.d.ts +13 -0
  6. package/dist/ai/client/reducer.d.ts.map +1 -1
  7. package/dist/ai/index.js +2 -2
  8. package/dist/ai/index.js.map +3 -3
  9. package/dist/ai/types.d.ts +16 -0
  10. package/dist/ai/types.d.ts.map +1 -1
  11. package/dist/ai/useChat.d.ts +15 -1
  12. package/dist/ai/useChat.d.ts.map +1 -1
  13. package/dist/{chunk-1kt3p3dg.js → chunk-3q6adj7c.js} +10 -10
  14. package/dist/{chunk-1kt3p3dg.js.map → chunk-3q6adj7c.js.map} +3 -3
  15. package/dist/{chunk-s8kenmvr.js → chunk-7d0n00an.js} +1 -1
  16. package/dist/{chunk-n8j5hn90.js → chunk-bs0setym.js} +2 -2
  17. package/dist/{chunk-n8j5hn90.js.map → chunk-bs0setym.js.map} +1 -1
  18. package/dist/{chunk-y4bjsyt4.js → chunk-pq86vmxv.js} +4 -4
  19. package/dist/{chunk-y4bjsyt4.js.map → chunk-pq86vmxv.js.map} +3 -3
  20. package/dist/chunk-sk22zf9e.js +24 -0
  21. package/dist/{chunk-qze2eh68.js.map → chunk-sk22zf9e.js.map} +4 -4
  22. package/dist/{chunk-0e1e64h1.js → chunk-w4227psm.js} +1 -1
  23. package/dist/chunks/{RealtimeClient-b6NvkUAQ.js → RealtimeClient-BX_HwEBK.js} +2 -2
  24. package/dist/chunks/{RealtimeClient-b6NvkUAQ.js.map → RealtimeClient-BX_HwEBK.js.map} +1 -1
  25. package/dist/chunks/{ThemeProvider-CkuoNG4Q.js → ThemeProvider-D4mhhONE.js} +78 -22
  26. package/dist/chunks/ThemeProvider-D4mhhONE.js.map +1 -0
  27. package/dist/chunks/{fetchFileRequest-DVWwtyWu.js → fetchFileRequest-C3wMigR3.js} +2 -2
  28. package/dist/chunks/{fetchFileRequest-DVWwtyWu.js.map → fetchFileRequest-C3wMigR3.js.map} +1 -1
  29. package/dist/chunks/{live-CpXfJmRN.js → live-CJOuf1Gu.js} +3 -3
  30. package/dist/chunks/{live-CpXfJmRN.js.map → live-CJOuf1Gu.js.map} +1 -1
  31. package/dist/chunks/{mutationExtras-BNFui6Pt.js → mutationExtras-DpB8MtNs.js} +2 -2
  32. package/dist/chunks/{mutationExtras-BNFui6Pt.js.map → mutationExtras-DpB8MtNs.js.map} +1 -1
  33. package/dist/client/ClientRouter.d.ts.map +1 -1
  34. package/dist/client/ClientRouterContext.d.ts.map +1 -1
  35. package/dist/client/ServerDataProvider.d.ts +6 -0
  36. package/dist/client/ServerDataProvider.d.ts.map +1 -1
  37. package/dist/client/chunkLoadRecovery.d.ts +56 -8
  38. package/dist/client/chunkLoadRecovery.d.ts.map +1 -1
  39. package/dist/client/helpers/loadRoutePayload.d.ts +8 -0
  40. package/dist/client/helpers/loadRoutePayload.d.ts.map +1 -1
  41. package/dist/client/index.d.ts +1 -1
  42. package/dist/client/index.d.ts.map +1 -1
  43. package/dist/client/index.js +23 -9
  44. package/dist/client/index.js.map +1 -1
  45. package/dist/facades/index.js +1 -1
  46. package/dist/http/index.js +1 -1
  47. package/dist/i18n/index.js +1 -1
  48. package/dist/kernel/index.js +1 -1
  49. package/dist/server/httpProd.d.ts.map +1 -1
  50. package/dist/server/index.js +1 -1
  51. package/dist/services/index.js +1 -1
  52. package/dist/services/router/ViewRouteDispatcher.d.ts.map +1 -1
  53. package/dist/testing/index.js +2 -2
  54. package/package.json +1 -1
  55. package/dist/chunk-qze2eh68.js +0 -24
  56. package/dist/chunks/ThemeProvider-CkuoNG4Q.js.map +0 -1
  57. /package/dist/{chunk-s8kenmvr.js.map → chunk-7d0n00an.js.map} +0 -0
  58. /package/dist/{chunk-0e1e64h1.js.map → chunk-w4227psm.js.map} +0 -0
@@ -17,14 +17,14 @@ ${j}`:j}),K)H.push(K);return H}function T9(Z,$,Q,B){if(Z.role==="system")return"
17
17
  `)}`:""}function S9(Z,$,Q){switch(Z.type){case"text":return QZ(Z.text??"",$);case"file":return`[file: ${Z.name??Z.mimeType??Z.fileId??"attachment"}]`;case"tool-call":{if(Q.has(Z.toolCallId))return`[loaded the skill "${String(Z.name)}"]`;return`[called ${Z.namespace?`${Z.namespace}.${String(Z.name)}`:String(Z.name)}(${QZ(H0(Z.input),Math.min($,1000))})]`}case"tool-result":{if(Q.has(Z.toolCallId))return"";let B=Z.status==="ok"?H0(Z.output):Z.status==="error"?`error: ${Z.error?.message??""}`:Z.status==="running"?`a background job (${Z.job?.id??"unknown"}) that was still running`:`${Z.status}${Z.reason?`: ${Z.reason}`:""}`;return`[${String(Z.name)} returned: ${QZ(B,Math.min($,2000))}]`}case"output":return`[structured answer: ${QZ(H0(Z.value),Math.min($,2000))}]`;default:return""}}function H0(Z){if(typeof Z==="string")return Z;try{return JSON.stringify(Z)??""}catch{return String(Z)}}function QZ(Z,$){return Z.length<=$?Z:`${Z.slice(0,$)}\u2026[cut]`}function y(Z){return typeof Z==="number"&&Number.isFinite(Z)&&Z>0?Math.floor(Z):void 0}function A9(Z,$){let Q=["0"],B="";for(let J=0;J<$;J++){let X;try{X=JSON.stringify(Z[J])??""}catch{X=String(Z[J]?.id)}B=x4(`${B}|${x4(X)}`),Q.push(B)}return Q}function x4(Z){let $=3735928559,Q=1103547991;for(let B=0;B<Z.length;B++){let J=Z.charCodeAt(B);$=Math.imul($^J,2654435761),Q=Math.imul(Q^J,1597334677)}return $=Math.imul($^$>>>16,2246822507)^Math.imul(Q^Q>>>13,3266489909),Q=Math.imul(Q^Q>>>16,2246822507)^Math.imul($^$>>>13,3266489909),(4294967296*(2097151&Q)+($>>>0)).toString(36)}class n extends Error{pending;path;nested;constructor(Z){super(`A nested agent run is waiting on the user for ${Z.pending.length} tool call(s).`);this.name="PendingEscalation",this.pending=Z.pending,this.path=Z.path,this.nested=Z.nested}}class b{name;description;inputSchema;outputSchema;requiresApproval;approvalPredicate;deferred;answeredBy;endsRun;timeoutMs;async;execute;constructor(Z){if(this.name=Z.name,this.description=Z.description,this.inputSchema=Z.inputSchema,this.outputSchema=Z.outputSchema,this.requiresApproval=Z.requiresApproval===!0||typeof Z.requiresApproval==="function",typeof Z.requiresApproval==="function")this.approvalPredicate=Z.requiresApproval;if(this.deferred=Z.deferred===!0,this.answeredBy=Z.answeredBy==="client"?"client":"server",this.execute=Z.execute??void 0,this.timeoutMs=Z.timeoutMs,this.async=Z.async,Z.endsRun)this.endsRun=Z.endsRun}static create(Z){if(typeof Z.inputSchema!=="function")U0(Z.inputSchema,`The tool "${Z.name}"`,"inputSchema");if(Z.timeoutMs!==void 0)kZ(Z.timeoutMs,`The tool "${Z.name}"`,"timeoutMs");if(Z.async?.deadlineMs!==void 0)kZ(Z.async.deadlineMs,`The tool "${Z.name}"`,"async.deadlineMs");if(Z.requiresApproval!==void 0&&typeof Z.requiresApproval!=="boolean"&&typeof Z.requiresApproval!=="function")throw Error(`The tool "${Z.name}" has a requiresApproval that is neither a boolean nor a function.`);if(Z.endsRun!==void 0&&typeof Z.endsRun!=="boolean"&&typeof Z.endsRun!=="function")throw Error(`The tool "${Z.name}" has an endsRun that is neither a boolean nor a function.`);if(Z.endsRun&&Z.answeredBy==="client")throw Error(`The tool "${Z.name}" is answered by the client and cannot set \`endsRun\`: its answer arrives on a later turn.`);if(Z.async&&Z.answeredBy==="client")throw Error(`The tool "${Z.name}" is answered by the client and cannot be \`async\`: background jobs are for tools the server runs.`);return new b(Z)}static ask(Z){return b.create({name:Z.name,description:Z.description,inputSchema:F0,outputSchema:Z.outputSchema,answeredBy:"client"})}}var F0={toJSONSchema:()=>({type:"object",properties:{question:{type:"string",description:"What to ask the user"}},required:["question"],additionalProperties:!1}),parse(Z){let $=F0.safeParse(Z);if($.ok===!1)throw Error($.errors.join(", "));return $.value},safeParse(Z){if(typeof Z!=="object"||Z===null||typeof Z.question!=="string")return{ok:!1,errors:["question: expected a string"]};return{ok:!0,value:{question:Z.question}}}};class D0{name;description;tools;deferred;constructor(Z){this.name=Z.name,this.description=Z.description,this.tools=Z.tools,this.deferred=Z.deferred===!0}static create(Z){return new D0(Z)}}class t4{name;description;instructions;files;constructor(Z){this.name=Z.name,this.description=Z.description,this.instructions=Z.instructions,this.files=Z.files}static create(Z){return new t4(Z)}}var f="skills",s4="Instructions this agent can load on demand. Load the relevant one before acting in the area it covers.";function U0(Z,$,Q){let B=Z?.toJSONSchema?.();if(B?.type==="object")return;let J=!B?"no JSON Schema":B.anyOf?"a union (`anyOf`) \u2014 `s.union(...)`":B.type!==void 0?`a schema of type ${JSON.stringify(B.type)}`:"an unconstrained schema (`s.json()`)";throw Error(`${$} declares an \`${Q}\` whose root is ${J}, but the provider only accepts an object there (OpenAI rejects \`anyOf\` or a non-object at the root of tool parameters and structured output). Wrap it in an object, e.g. \`s.object({ value: s.union([...]) })\`, and read \`.value\` off the result.`)}function kZ(Z,$,Q){if(typeof Z==="number"&&Z>0)return;throw Error(`${$} sets \`${Q}\` to ${String(Z)}, but it has to be a positive number of milliseconds. Use \`null\` for no limit.`)}function b4(Z){if(Z===void 0)return;if(Z===null||!Number.isFinite(Z))return null;return Z}var k9=2147483647;function h4(Z,$){if(Z===null||Z>k9)return()=>{};let Q=setTimeout($,Z);return()=>clearTimeout(Q)}function q0(Z){if(Z<1000)return`${Z}ms`;if(Z<60000)return`${+(Z/1000).toFixed(1)}s`;return`${+(Z/60000).toFixed(1)}m`}var j0={type:"object",properties:{},required:[],additionalProperties:!1},a4=600000;class EZ extends Error{code;retryable;status;requestId;toolCallId;runId;result;rejected;constructor(Z,$){super(Z.error.message);if($?.rejected)this.rejected=$.rejected;this.name="AgentRunError",this.code=Z.error.code,this.retryable=Z.error.retryable,this.status=Z.error.status,this.requestId=Z.error.requestId,this.toolCallId=Z.error.toolCallId,this.runId=Z.runId,this.result=Z}}var E9=8,v9=3;class P0{name;tools;skills;provider;output;instructions;maxSteps;maxDepth;reasoning;maxRunDurationMs;jobs;memory;config;constructor(Z){this.name=Z.name,this.instructions=Z.instructions,this.provider=Z.provider,this.tools=Z.tools??[],this.skills=Z.skills??[],this.output=Z.output,this.maxSteps=Z.maxSteps??E9,this.maxDepth=Z.maxDepth??v9,this.reasoning=Z.reasoning,this.jobs=Z.jobs??{},this.memory=Z.memory?Z.memory:void 0;let $=b4(Z.maxRunDurationMs);this.maxRunDurationMs=$===void 0?a4:$;let{registry:Q,providerTools:B}=w9(this.tools,this.skills,this.memory);this.config={name:this.name,memory:this.memory,instructions:this.instructions,provider:this.provider,registry:Q,providerTools:B,output:Z.output,maxSteps:this.maxSteps,maxDepth:this.maxDepth,reasoning:this.reasoning,maxOutputTokens:Z.maxOutputTokens,temperature:Z.temperature,logErrors:Z.logErrors??!0,maxRunDurationMs:$,contextWindow:Z.contextWindow,prepareStep:Z.prepareStep?[Z.prepareStep]:[]}}static withContext(){return f9}static create(Z){if(Z.output)U0(Z.output,`The agent "${Z.name}"`,"output");if(Z.maxRunDurationMs!=null)kZ(Z.maxRunDurationMs,`The agent "${Z.name}"`,"maxRunDurationMs");let $=Z.jobs?.contextBlock;if($&&$.max!==void 0&&!(Number.isInteger($.max)&&$.max>0))throw Error(`The agent "${Z.name}" sets \`jobs.contextBlock.max\` to ${String($.max)}, but it has to be a whole number above 0. Use \`contextBlock: false\` for no block.`);if(Z.memory)s0(Z.name,Z.memory);return new P0(Z)}stream(Z){let $={...this.config,provider:Z.provider??this.config.provider,maxSteps:Z.maxSteps??this.config.maxSteps,reasoning:Z.reasoning??this.config.reasoning,maxOutputTokens:Z.maxOutputTokens??this.config.maxOutputTokens,temperature:Z.temperature??this.config.temperature,maxRunDurationMs:Z.maxRunDurationMs!==void 0?b4(Z.maxRunDurationMs):this.config.maxRunDurationMs,contextWindow:Z.contextWindow===!1?void 0:Z.contextWindow??this.config.contextWindow,prepareStep:Z.prepareStep?[...this.config.prepareStep,Z.prepareStep]:this.config.prepareStep};if(Z.maxRunDurationMs!=null)kZ(Z.maxRunDurationMs,`Agent.stream for "${this.name}"`,"maxRunDurationMs");if(Z.memory?.maxTokens!==void 0){if(!(Number.isInteger(Z.memory.maxTokens)&&Z.memory.maxTokens>=0))throw Error(`Agent.stream for "${this.name}" sets \`memory.maxTokens\` to ${String(Z.memory.maxTokens)}, but it has to be a whole number of at least 0.`)}if(Z.skills&&Z.skills.length>0)$=y9($,Z.skills,`Agent.stream for "${this.name}"`);return new Z7($,Z)}}var f9={tool:(Z)=>b.create(Z),ask:(Z)=>b.ask(Z),agent:(Z)=>P0.create(Z)};function JZ(Z){let $=Z.inputSchema;return{name:Z.tool.name,description:Z.tool.description,parameters:$?$.toJSONSchema():j0,strict:$?VZ($):!0,deferred:Z.deferred}}function AZ(Z){return typeof Z.inputSchema==="function"?void 0:Z.inputSchema}function w9(Z,$,Q){let B=new Map,J=[],X=(z)=>{if(B.has(z.tool.name))throw Error(`Two tools are named "${z.tool.name}". Tool names are global within an agent \u2014 the client discriminates a tool part by name alone.`);B.set(z.tool.name,z)};for(let z of Z){if(z instanceof D0){if(z.name===f)throw Error(`"${f}" is reserved for the namespace skills are lowered into. Rename the namespace \u2014 silently shadowing it would make every skill unreachable with no error to read.`);if(Q&&z.name===h)throw Error(`"${h}" is reserved for the namespace the memory tools are lowered into. Rename the namespace.`);let V=[];for(let H of z.tools){let K={tool:H,namespace:z.name,deferred:z.deferred||H.deferred,inputSchema:AZ(H)};X(K),V.push(JZ(K))}J.push({name:z.name,description:z.description,tools:V});continue}let W={tool:z,deferred:z.deferred,inputSchema:AZ(z)};X(W),J.push(JZ(W))}if($.length>0){let z=[];for(let W of $){let V=r4(W);X(V.resolved),z.push(V.spec)}J.push({name:f,description:s4,tools:z})}let G=Q?b9(Q):[];if(G.length>0){let z=[];for(let W of G){if(B.has(W.name))throw Error(`The tool "${W.name}" clashes with the built-in memory tool of that name, which this agent gets because it declares \`memory\`. Rename the tool, or turn the built-in one off with \`memory.tools\`.`);let V={tool:W,namespace:h,deferred:!1,inputSchema:AZ(W)};X(V),z.push(JZ(V))}J.push({name:h,description:t0,tools:z})}return{registry:B,providerTools:J}}function b9(Z){let $=a0(Z),Q=Object.keys(Z.scopes),B=Q.filter((G)=>Z.scopes[G].write!==!1),J=[...new Set(B.flatMap((G)=>Z.scopes[G].kinds??["fact","preference","note"]))],X=[];if($.remember&&B.length>0)X.push(b.create({name:"remember",description:r0,inputSchema:e("remember",{scopes:B,descriptions:"",kinds:J}),requiresApproval:$.remember.requiresApproval,execute:(G,z)=>PZ(z.memory).remember(G)}));if($.forget&&B.length>0)X.push(b.create({name:"forget",description:e0,inputSchema:e("forget",{scopes:B,descriptions:"",kinds:J}),requiresApproval:$.forget.requiresApproval,execute:(G,z)=>PZ(z.memory).forget(G)}));if($.recall)X.push(b.create({name:"recall",description:Z4,inputSchema:e("recall",{scopes:Q,descriptions:"",kinds:J}),execute:(G,z)=>PZ(z.memory).recall(G)}));return X}var h9=/^[a-zA-Z0-9_-]{1,64}$/;function r4(Z){if(typeof Z.name!=="string"||!h9.test(Z.name))throw Error(`The skill name ${JSON.stringify(Z.name)} is not one a provider accepts: use 1 to 64 letters, digits, "_" or "-" (a pack slug with a "." or a space has to be mapped first).`);let $=g9(Z);return{resolved:{tool:$,namespace:f,deferred:!1,inputSchema:AZ($)},spec:{name:Z.name,description:Z.description,parameters:j0,strict:!0,deferred:!1}}}function y9(Z,$,Q){let B=new Map(Z.registry),J=[];for(let z of $){let W=B.get(z.name);if(W){let H=W.namespace===f?Z.registry.has(z.name)?"a skill the agent declares":"another skill of this run":"a tool of the agent";throw Error(`${Q} is given the skill "${z.name}", but that name is already ${H}. Tool and skill names are global within a run: the client discriminates a tool part by name alone. Rename the skill.`)}let V=r4(z);B.set(z.name,V.resolved),J.push(V.spec)}let X=[...Z.providerTools],G=X.findIndex((z)=>("tools"in z)&&z.name===f);if(G>=0){let z=X[G];X[G]={...z,tools:[...z.tools,...J]}}else{let z=X.findIndex((W)=>("tools"in W)&&W.name===h);X.splice(z>=0?z:X.length,0,{name:f,description:s4,tools:J})}return{...Z,registry:B,providerTools:X}}function g9(Z){return b.create({name:Z.name,description:Z.description,inputSchema:{toJSONSchema:()=>j0,parse:()=>({}),safeParse:()=>({ok:!0,value:{}})},execute:async()=>{let Q=[typeof Z.instructions==="function"?await Z.instructions():Z.instructions];for(let B of Z.files??[])Q.push(`--- ${B} ---
18
18
  ${await u9(B)}`);return Q.join(`
19
19
 
20
- `)}})}async function u9(Z){try{return await Bun.file(Z).text()}catch($){return`(could not be read: ${$.message})`}}function c9(Z){return typeof Z==="object"&&Z!==null&&typeof Z.next==="function"&&Symbol.asyncIterator in Z}function y4(Z,$){let Q=[...Z],B=new Map(Q.map((J,X)=>[J.id,X]));for(let J of $){let X=B.get(J.id);if(X===void 0)B.set(J.id,Q.length),Q.push(J);else Q[X]=J}return Q}function SZ(Z){let $=new Set;for(let B of Z)for(let J of B.content)if(J.type==="tool-result")$.add(J.toolCallId);let Q=new Set;for(let B of Z)for(let J of B.content)if(J.type==="tool-call"&&!$.has(J.toolCallId))Q.add(J.toolCallId);return Q}function g4(Z){for(let $=Z.length-1;$>=0;$--){let Q=Z[$].content;for(let B=Q.length-1;B>=0;B--){let J=Q[B];if(J.type==="output"&&J.partial!==!0)return J.value}}return}function u4(Z,$){return $===void 0?`"${Z}"`:`"${Z}" labelled "${$}"`}function e4(Z){return Z.content.map(($)=>$.type==="text"?$.text:`<${$.type}>`).join("")}function d9(Z){if(Z.prompt!==void 0)return`user:${Z.prompt}`;let $=Z.messages?.[0];return $?`${$.role}:${e4($)}`:null}var c4=1;function p9(Z,$,Q){let B=Q.mimeType||$.type||"";if(B&&Z.attachment.mimeType!==B)return`was ${JSON.stringify(Z.attachment.mimeType)} on the turn that escalated and is ${JSON.stringify(B)} on the replay`;let J=Boolean(Q.showModel);if(J!==Boolean(Z.shown))return J?"was stored without showModel on the turn that escalated and asks for showModel on the replay":"was stored with showModel on the turn that escalated and asks for a plain put on the replay";return null}function l9(Z,$,Q){if(Z.agent!==$.name||Z.label!==Q.label)return`was ${u4(Z.agent,Z.label)} on the turn that escalated and is ${u4($.name,Q.label)} on the replay`;let B=d9(Q),J=Z.messages[0],X=J?`${J.role}:${e4(J)}`:null;if(B!==null&&X!==null&&B!==X)return`was started with ${JSON.stringify(X)} on the turn that escalated and with ${JSON.stringify(B)} on the replay`;return null}function d4(Z,$){let Q=Z??[];if(Q.length<$.length)return null;for(let B=0;B<$.length;B++)if(Q[B]!==$[B])return null;return Q.slice($.length)}class K0{read;create;fill;index=0;replayable;constructor(Z,$,Q){this.read=Z;this.create=$;this.fill=Q;this.replayable=Z()?.length??0}next(){let Z=this.index++;return{at:Z,recorded:Z<this.replayable?this.read()?.[Z]:void 0,write:($)=>{let Q=this.read()??this.create();if(this.fill)for(let B=Q.length;B<Z;B++)Q[B]=this.fill();Q[Z]=$}}}}class Z7{runId;config;params;context;controller=new AbortController;buffer=[];waiters=new Set;seq=0;ended=!1;history=[];compactMemo=new Map;lastStep;produced=[];current=null;outputTruncated=!1;amended=new Map;unreported=new Set;usage=I();finishReason="stop";failure;output;stopReason;timedOutAfter;cancelDeadline=()=>{};settled;meter;depth;maxDepth;chain;signingRunId;pathPrefix;onPending;nestedSettling=new Set;shownQueue=new Map;memory;memoryBlock=null;constructor(Z,$){this.config=Z,this.params=$,this.context=$.context??{},this.runId=$.runId??`run_${crypto.randomUUID()}`,this.history=[...$.messages];let Q=$.nesting;if(this.depth=Q?.depth??0,this.maxDepth=Q?.maxDepth??Z.maxDepth,this.chain=Q?.chain??[Z.name],this.signingRunId=Q?.signingRunId??this.runId,this.pathPrefix=Q?.signingPath??[],this.onPending=Q?.onPending??"escalate",this.memory=new LZ({options:Z.memory,scopes:$.memory?.scopes,agent:Z.name,runId:this.runId,threadId:$.threadId,writes:Q?.memoryWrites}),$.signal)if($.signal.aborted)this.controller.abort();else $.signal.addEventListener("abort",()=>this.stop(),{once:!0});let B=Z.maxRunDurationMs!==void 0?Z.maxRunDurationMs:Q?null:a4;this.cancelDeadline=h4(B,()=>this.expire(B));let J=dZ();this.meter=J.meter,this.settled=J.run(()=>this.execute()),this.settled.then(J.close,J.close),m4.getStore()?.waitUntil(this.settled)}emit(Z){if(this.ended)return;this.buffer.push({seq:++this.seq,event:Z}),this.wake()}wake(){let Z=[...this.waiters];this.waiters.clear();for(let $ of Z)$()}nextFrame(){return new Promise((Z)=>this.waiters.add(Z))}async*frames(Z=0){let $=Z>0?Z-1:0;for(;;){while($<this.buffer.length)yield this.buffer[$++];if(this.ended)return;await this.nextFrame()}}async*[Symbol.asyncIterator](){for await(let Z of this.frames())yield Z.event}toResponse(Z){let $=this.frames(Z?.from),Q=new TextEncoder,B=!1,J,X=new ReadableStream({start:async(G)=>{J=i4(G);try{for await(let z of $){if(B)break;G.enqueue(Q.encode(`id: ${z.seq}
20
+ `)}})}async function u9(Z){try{return await Bun.file(Z).text()}catch($){return`(could not be read: ${$.message})`}}function c9(Z){return typeof Z==="object"&&Z!==null&&typeof Z.next==="function"&&Symbol.asyncIterator in Z}function y4(Z,$){let Q=[...Z],B=new Map(Q.map((J,X)=>[J.id,X]));for(let J of $){let X=B.get(J.id);if(X===void 0)B.set(J.id,Q.length),Q.push(J);else Q[X]=J}return Q}function SZ(Z){let $=new Set;for(let B of Z)for(let J of B.content)if(J.type==="tool-result")$.add(J.toolCallId);let Q=new Set;for(let B of Z)for(let J of B.content)if(J.type==="tool-call"&&!$.has(J.toolCallId))Q.add(J.toolCallId);return Q}function g4(Z){for(let $=Z.length-1;$>=0;$--){let Q=Z[$].content;for(let B=Q.length-1;B>=0;B--){let J=Q[B];if(J.type==="output"&&J.partial!==!0)return J.value}}return}function u4(Z,$){return $===void 0?`"${Z}"`:`"${Z}" labelled "${$}"`}function e4(Z){return Z.content.map(($)=>$.type==="text"?$.text:`<${$.type}>`).join("")}function d9(Z){if(Z.prompt!==void 0)return`user:${Z.prompt}`;let $=Z.messages?.[0];return $?`${$.role}:${e4($)}`:null}var c4=1;function p9(Z,$,Q){let B=Q.mimeType||$.type||"";if(B&&Z.attachment.mimeType!==B)return`was ${JSON.stringify(Z.attachment.mimeType)} on the turn that escalated and is ${JSON.stringify(B)} on the replay`;let J=Boolean(Q.showModel);if(J!==Boolean(Z.shown))return J?"was stored without showModel on the turn that escalated and asks for showModel on the replay":"was stored with showModel on the turn that escalated and asks for a plain put on the replay";return null}function l9(Z,$,Q){if(Z.agent!==$.name||Z.label!==Q.label)return`was ${u4(Z.agent,Z.label)} on the turn that escalated and is ${u4($.name,Q.label)} on the replay`;let B=d9(Q),J=Z.messages[0],X=J?`${J.role}:${e4(J)}`:null;if(B!==null&&X!==null&&B!==X)return`was started with ${JSON.stringify(X)} on the turn that escalated and with ${JSON.stringify(B)} on the replay`;return null}function d4(Z,$){let Q=Z??[];if(Q.length<$.length)return null;for(let B=0;B<$.length;B++)if(Q[B]!==$[B])return null;return Q.slice($.length)}class K0{read;create;fill;index=0;replayable;constructor(Z,$,Q){this.read=Z;this.create=$;this.fill=Q;this.replayable=Z()?.length??0}next(){let Z=this.index++;return{at:Z,recorded:Z<this.replayable?this.read()?.[Z]:void 0,write:($)=>{let Q=this.read()??this.create();if(this.fill)for(let B=Q.length;B<Z;B++)Q[B]=this.fill();Q[Z]=$}}}}class Z7{runId;config;params;context;controller=new AbortController;buffer=[];waiters=new Set;seq=0;ended=!1;history=[];compactMemo=new Map;lastStep;produced=[];current=null;outputTruncated=!1;amended=new Map;unreported=new Set;usage=I();finishReason="stop";failure;output;stopReason;timedOutAfter;cancelDeadline=()=>{};settled;meter;depth;maxDepth;chain;signingRunId;pathPrefix;onPending;openedWith=0;nestedSettling=new Set;shownQueue=new Map;memory;memoryBlock=null;constructor(Z,$){this.config=Z,this.params=$,this.context=$.context??{},this.runId=$.runId??`run_${crypto.randomUUID()}`,this.history=[...$.messages];let Q=$.nesting;if(this.depth=Q?.depth??0,this.maxDepth=Q?.maxDepth??Z.maxDepth,this.chain=Q?.chain??[Z.name],this.signingRunId=Q?.signingRunId??this.runId,this.pathPrefix=Q?.signingPath??[],this.onPending=Q?.onPending??"escalate",this.memory=new LZ({options:Z.memory,scopes:$.memory?.scopes,agent:Z.name,runId:this.runId,threadId:$.threadId,writes:Q?.memoryWrites}),$.signal)if($.signal.aborted)this.controller.abort();else $.signal.addEventListener("abort",()=>this.stop(),{once:!0});let B=Z.maxRunDurationMs!==void 0?Z.maxRunDurationMs:Q?null:a4;this.cancelDeadline=h4(B,()=>this.expire(B));let J=dZ();this.meter=J.meter,this.settled=J.run(()=>this.execute()),this.settled.then(J.close,J.close),m4.getStore()?.waitUntil(this.settled)}emit(Z){if(this.ended)return;this.buffer.push({seq:++this.seq,event:Z}),this.wake()}wake(){let Z=[...this.waiters];this.waiters.clear();for(let $ of Z)$()}nextFrame(){return new Promise((Z)=>this.waiters.add(Z))}async*frames(Z=0){let $=Z>0?Z-1:0;for(;;){while($<this.buffer.length)yield this.buffer[$++];if(this.ended)return;await this.nextFrame()}}async*[Symbol.asyncIterator](){for await(let Z of this.frames())yield Z.event}toResponse(Z){let $=this.frames(Z?.from),Q=new TextEncoder,B=!1,J,X=new ReadableStream({start:async(G)=>{J=i4(G);try{for await(let z of $){if(B)break;G.enqueue(Q.encode(`id: ${z.seq}
21
21
  data: ${JSON.stringify(z.event)}
22
22
 
23
- `)),J.touch()}}catch{}J.stop();try{G.close()}catch{}},cancel:()=>{B=!0,J.stop()}});return new Response(X,{headers:{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}})}result(Z){if(!Z?.throwOnError)return this.settled;return this.settled.then(($)=>{if($.error)throw new EZ({...$,error:$.error});return $})}stop(Z){if(this.ended||this.controller.signal.aborted)return;this.stopReason=Z?.reason,this.controller.abort()}expire(Z){if(this.ended||this.controller.signal.aborted)return;this.timedOutAfter=Z,this.stopReason=`The run reached its time limit of ${q0(Z)} and was stopped.`,this.controller.abort(new DOMException(this.stopReason,"TimeoutError"))}async execute(){this.emit({type:"run-start",runId:this.runId,threadId:this.params.threadId});try{await this.prepareMemory();let $=await this.resolveToolSchemas(),Q=$?[]:await this.ingestTurn();if($)this.fail($),this.finishReason="error";else if(Q.length>0)this.finishReason="awaiting-input",this.emit({type:"awaiting-input",runId:this.runId,pending:Q});else await this.loop()}catch($){if($ instanceof S||this.controller.signal.aborted)await this.finalizeAborted();else this.fail(this.config.provider.normalizeError($),d($)),await this.finalizeMessage("error"),this.finishReason="error"}this.cancelDeadline(),this.emit({type:"usage",usage:this.usage}),this.emit({type:"run-end",runId:this.runId,finishReason:this.finishReason}),this.ended=!0,this.wake(),this.precompact();let Z=this.finishReason==="error"?this.failure:void 0;if(Z&&this.config.logErrors)this.logFailure(Z);return{runId:this.runId,messages:this.produced,finishReason:this.finishReason,usage:this.usage,metered:this.meter.totals(),output:this.output,...Z?{error:Z}:{}}}async resolveToolSchemas(){let Z=[...this.config.registry.values()].filter((W)=>!W.inputSchema);if(Z.length===0)return;let $={context:this.context,body:this.params.body??{},runId:this.runId,threadId:this.params.threadId,signal:this.controller.signal},Q=new Map,B=await Promise.all(Z.map(async(W)=>{try{let V=W.tool.inputSchema,H=await V($);U0(H,`The tool "${W.tool.name}"`,"inputSchema"),Q.set(W.tool.name,H);return}catch(V){return`"${W.tool.name}": ${V instanceof Error?V.message:String(V)}`}}));if(this.controller.signal.aborted)throw new S;let J=B.filter((W)=>W!==void 0);if(J.length>0)return{code:"tool_error",message:`Could not resolve the input schema of ${J.join("; ")}`,retryable:!1};let X=new Map;for(let[W,V]of this.config.registry)X.set(W,Q.has(W)?{...V,inputSchema:Q.get(W)}:V);let G=(W)=>Q.has(W.name)?JZ(X.get(W.name)):W,z=this.config.providerTools.map((W)=>("tools"in W)?{...W,tools:W.tools.map(G)}:G(W));this.config={...this.config,registry:X,providerTools:z};return}async prepareMemory(){let Z=this.config.memory;if(!Z)return;let $=this.memory,Q=$.writableLabels(),B=$.toolKinds(),J=(W)=>W==="recall"?$.labels.length>0:Q.length>0&&B.length>0,X=new Map;for(let[W,V]of this.config.registry){if(V.namespace!==h){X.set(W,V);continue}if(!J(W))continue;let H=W==="recall"?$.labels:Q,K=e(W,{scopes:H,descriptions:$.describeScopes(H),kinds:B});X.set(W,{...V,inputSchema:K})}let G=this.config.providerTools.flatMap((W)=>{if(!("tools"in W)||W.name!==h)return[W];let V=W.tools.filter((H)=>X.has(H.name)).map((H)=>JZ(X.get(H.name)));return V.length>0?[{...W,tools:V}]:[]});this.config={...this.config,registry:X,providerTools:G};let z=this.params.memory?.maxTokens??Z.maxTokens??u0;try{this.memoryBlock=await $.block({maxTokens:z,recall:X.has("recall"),tools:X.has("remember")||X.has("forget")})}catch(W){let V=W instanceof Error?W.message:String(W);this.writeLog(`[gemi/ai] agent "${this.config.name}": the memory store could not be read, so this run has no <memory> block: ${V}`,{error:W})}if(this.controller.signal.aborted)throw new S}fail(Z,$={}){let Q={...Z,...$};this.failure=Q,this.emit({type:"error",error:this.redact(Q,{source:"run",failure:Q})})}redact(Z,$){let Q=k0(this.params.redactError,Z,$,(B)=>this.writeLog(`[gemi/ai] agent "${this.config.name}" redactError threw`,{error:B}));return v0(Q,Z),Q}logFailure(Z){let $=`[gemi/ai] agent "${this.config.name}" run failed (${Z.code}${Z.status!==void 0?` ${Z.status}`:""}): ${Z.message}`;this.writeLog($,{error:Z})}logToolFailure(Z,$){let Q=$ instanceof Error?$.message:String($);this.writeLog(`[gemi/ai] agent "${this.config.name}" tool "${String(Z.name)}" threw: ${Q}`,{toolCallId:Z.toolCallId,error:$})}writeLog(Z,$){let Q={agent:this.config.name,runId:this.runId,...this.params.threadId?{threadId:this.params.threadId}:{},...this.depth>0?{chain:this.chain}:{},...$},B=!1;try{XZ.error(Z,Q),B=!0}catch{}if(!B||Bun.env.NODE_ENV==="development")console.error(Z,Q)}async loop(){let Z=Math.max(1,this.config.maxSteps);for(let $=1;$<=Z;$++){let Q=this.startMessage(),B=await this.runStep(Q,$);if(this.lastStep={reason:B.reason,usage:Q.usage},B.error){this.fail(B.error,B.detail),await this.finalizeMessage("error"),this.finishReason="error";return}let J=Q.content.filter((z)=>z.type==="tool-call");if(J.length===0){this.finishReason=B.reason,await this.finalizeMessage(B.reason);return}let X=await this.runTools(Q,J,$);if(X.length>0){this.finishReason="awaiting-input",await this.finalizeMessage("awaiting-input"),this.emit({type:"awaiting-input",runId:this.runId,pending:X});return}let G=await this.closingText(Q,J,$);if(G!==null){if(this.finishReason="stop",await this.finalizeMessage(B.reason),G){let z=this.startMessage();l(z,"text",G),this.emit({type:"text-delta",messageId:z.id,delta:G}),await this.finalizeMessage("stop")}return}if($===Z){this.finishReason="max-steps",await this.finalizeMessage("max-steps");return}await this.finalizeMessage(B.reason)}}startMessage(){let Z={id:`msg_${crypto.randomUUID()}`,role:"assistant",content:[],createdAt:new Date().toISOString()};return this.current=Z,this.history.push(Z),this.produced.push(Z),this.emit({type:"message-start",messageId:Z.id,role:"assistant"}),Z}async finalizeMessage(Z){let $=this.current;if(!$)return;this.current=null;let Q=this.outputTruncated;if(this.outputTruncated=!1,$.finishReason=Z,Q)$.outputTruncated=!0;for(let B of $.content)if(B.type==="text"||B.type==="reasoning"){if(typeof B.text==="string")B.text=KZ(B.text)}this.emit({type:"message-end",messageId:$.id,finishReason:Z,...Q?{outputTruncated:!0}:{},...$.usage?{usage:$.usage}:{}}),await this.report($),await this.reportDeferred()}async report(Z){if(!this.params.onMessage)return;try{await this.params.onMessage(Z)}catch{}}async runStep(Z,$){let Q=this.controller.signal,B=this.config.provider,J=await this.prepareRequest(Z,$);if("error"in J)return{reason:"error",error:J.error};let X={reason:"stop"},G=new Map,z=[],W=()=>{if(z.length===0)return{};let q=z;return z=[],{toolSearches:q}},V="",K=B.stream({messages:J.messages,systemPrompt:J.instructions,tools:this.config.providerTools.length>0?this.config.providerTools:void 0,output:this.config.output?YZ(this.config.output):void 0,reasoning:J.reasoning,maxOutputTokens:J.maxOutputTokens,temperature:this.config.temperature,signal:Q})[Symbol.asyncIterator]();for(;;){let q=await w(Promise.resolve(K.next()),Q);if(q.done)break;let F=q.value;switch(F.type){case"text-delta":{l(Z,"text",F.delta),this.emit({type:"text-delta",messageId:Z.id,delta:F.delta});break}case"reasoning-delta":{FZ(Z,F.id,F.delta),this.emit({type:"reasoning-delta",messageId:Z.id,delta:F.delta,id:F.id});break}case"output-delta":{V+=F.delta,this.emit({type:"output-delta",messageId:Z.id,delta:F.delta,snapshot:HZ(V)});break}case"tool-search":{z.push({namespaces:F.namespaces,loaded:F.loaded,...F.arguments!==void 0?{arguments:F.arguments}:{}}),this.emit({type:"tool-search",loaded:F.loaded});break}case"tool-call-delta":{let D=G.get(F.toolCallId)??{name:F.name,args:""};D.args+=F.argsDelta,D.name=F.name||D.name,D.namespace=F.namespace||D.namespace,G.set(F.toolCallId,D),this.emit({type:"tool-call",messageId:Z.id,part:{type:"tool-call",toolCallId:F.toolCallId,name:D.name,input:HZ(D.args),partial:!0,...D.namespace?{namespace:D.namespace}:{}}});break}case"tool-call":{let D=F.namespace||G.get(F.toolCallId)?.namespace||(this.config.registry.get(F.name)?.namespace===f?f:void 0);G.delete(F.toolCallId);let U={type:"tool-call",toolCallId:F.toolCallId,name:F.name,input:l4(F.args),...D?{namespace:D}:{},...W()};Z.content.push(U),this.emit({type:"tool-call",messageId:Z.id,part:U});break}case"finish":{if(this.usage=R(this.usage,F.usage),s(F.model??B.model,F.usage),Z.usage=R(Z.usage??I(),F.usage),!X.error)X={reason:F.reason};break}case"error":{X={reason:"error",error:F.error,detail:d(F)};break}case"file-rejected":{this.markFileRejected(F.fileId,F.message,d(F));break}}}for(let[q,F]of G){let D={type:"tool-call",toolCallId:q,name:F.name,input:l4(F.args),...F.namespace?{namespace:F.namespace}:{},...W()};Z.content.push(D),this.emit({type:"tool-call",messageId:Z.id,part:D})}let Y=X.reason==="length";if(Y)this.outputTruncated=!0;if(this.config.output&&V&&!X.error&&!Y){let q=qZ(this.config.output,V);if(q.ok===!0)this.output=q.value,Z.content.push({type:"output",value:q.value});else this.emit({type:"error",error:q.error})}return X}compactJobParams(Z,$){let Q=this.config.contextWindow;if(!Q?.compact||!this.params.threadId||this.depth!==0)return;let B=Q.compact===!0?{}:Q.compact;return{history:Z,stored:this.history.filter((J)=>J!==$),window:Q,compact:B,threadId:this.params.threadId,provider:this.config.provider,store:B.store||this.params.summaryStore||S4,skills:this.skillNames()}}skillNames(){let Z=new Set;for(let[$,Q]of this.config.registry)if(Q.namespace===f)Z.add($);return Z}precompact(){let Z=this.config.contextWindow;if(!Z?.compact||Z.compact!==!0&&Z.compact.background===!1)return;try{let $=this.compactJobParams(this.historyForProvider(void 0),void 0);if($)E4($)}catch{}}async prepareRequest(Z,$){let Q=this.historyForProvider(Z),B=this.config.contextWindow,J=this.compactJobParams(Q,Z),X=!B?Q:J?await k4({...J,signal:this.controller.signal,onUsage:(V)=>{this.usage=R(this.usage,V)},memo:this.compactMemo}):$Z(Q,B).messages,G=await this.systemPrompt(),z=this.config.reasoning,W=this.config.maxOutputTokens;for(let V of this.config.prepareStep){let H;try{H=await V({step:$,messages:[...X],history:[...Q],instructions:G,reasoning:z,maxOutputTokens:W,body:this.params.body??{},usage:this.usage,...this.lastStep?.usage?{lastStepUsage:this.lastStep.usage}:{},...this.lastStep?{lastFinishReason:this.lastStep.reason}:{},runId:this.runId,threadId:this.params.threadId,agent:this.config.name,depth:this.depth,context:this.context,signal:this.controller.signal})}catch(K){if(K instanceof S||this.controller.signal.aborted)throw K;return{error:{code:"unknown",message:`prepareStep threw: ${K instanceof Error?K.message:String(K)}`,retryable:!1}}}if(!H)continue;if(H.messages!==void 0){if(!Array.isArray(H.messages))return{error:{code:"unknown",message:"prepareStep answered `messages` that is not an array.",retryable:!1}};X=H.messages}if(H.instructions!==void 0)G=H.instructions||void 0;if(H.reasoning!==void 0)z=H.reasoning;if(H.maxOutputTokens!==void 0)W=H.maxOutputTokens}return{messages:X,instructions:G,reasoning:z,maxOutputTokens:W}}async systemPrompt(){let Z=[this.config.instructions,this.params.instructions,this.memoryBlock].filter(($)=>Boolean($&&$.trim()));return Z.length>0?Z.join(`
23
+ `)),J.touch()}}catch{}J.stop();try{G.close()}catch{}},cancel:()=>{B=!0,J.stop()}});return new Response(X,{headers:{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}})}result(Z){if(!Z?.throwOnError)return this.settled;return this.settled.then(($)=>{if($.error)throw new EZ({...$,error:$.error});return $})}stop(Z){if(this.ended||this.controller.signal.aborted)return;this.stopReason=Z?.reason,this.controller.abort()}expire(Z){if(this.ended||this.controller.signal.aborted)return;this.timedOutAfter=Z,this.stopReason=`The run reached its time limit of ${q0(Z)} and was stopped.`,this.controller.abort(new DOMException(this.stopReason,"TimeoutError"))}async execute(){this.emit({type:"run-start",runId:this.runId,threadId:this.params.threadId});try{await this.prepareMemory();let $=await this.resolveToolSchemas(),Q=$?[]:await this.ingestTurn();if($)this.fail($),this.finishReason="error";else if(Q.length>0)this.finishReason="awaiting-input",this.emit({type:"awaiting-input",runId:this.runId,pending:Q});else if(this.answersOnlyStale())this.fail({code:"invalid_tool_result",message:"The tool calls this turn answers are no longer waiting for an answer: an earlier turn answered or refused them.",retryable:!1}),this.finishReason="error";else await this.loop()}catch($){if($ instanceof S||this.controller.signal.aborted)await this.finalizeAborted();else this.fail(this.config.provider.normalizeError($),d($)),await this.finalizeMessage("error"),this.finishReason="error"}this.cancelDeadline(),this.emit({type:"usage",usage:this.usage}),this.emit({type:"run-end",runId:this.runId,finishReason:this.finishReason}),this.ended=!0,this.wake(),this.precompact();let Z=this.finishReason==="error"?this.failure:void 0;if(Z&&this.config.logErrors)this.logFailure(Z);return{runId:this.runId,messages:this.produced,finishReason:this.finishReason,usage:this.usage,metered:this.meter.totals(),output:this.output,...Z?{error:Z}:{}}}async resolveToolSchemas(){let Z=[...this.config.registry.values()].filter((W)=>!W.inputSchema);if(Z.length===0)return;let $={context:this.context,body:this.params.body??{},runId:this.runId,threadId:this.params.threadId,signal:this.controller.signal},Q=new Map,B=await Promise.all(Z.map(async(W)=>{try{let V=W.tool.inputSchema,H=await V($);U0(H,`The tool "${W.tool.name}"`,"inputSchema"),Q.set(W.tool.name,H);return}catch(V){return`"${W.tool.name}": ${V instanceof Error?V.message:String(V)}`}}));if(this.controller.signal.aborted)throw new S;let J=B.filter((W)=>W!==void 0);if(J.length>0)return{code:"tool_error",message:`Could not resolve the input schema of ${J.join("; ")}`,retryable:!1};let X=new Map;for(let[W,V]of this.config.registry)X.set(W,Q.has(W)?{...V,inputSchema:Q.get(W)}:V);let G=(W)=>Q.has(W.name)?JZ(X.get(W.name)):W,z=this.config.providerTools.map((W)=>("tools"in W)?{...W,tools:W.tools.map(G)}:G(W));this.config={...this.config,registry:X,providerTools:z};return}async prepareMemory(){let Z=this.config.memory;if(!Z)return;let $=this.memory,Q=$.writableLabels(),B=$.toolKinds(),J=(W)=>W==="recall"?$.labels.length>0:Q.length>0&&B.length>0,X=new Map;for(let[W,V]of this.config.registry){if(V.namespace!==h){X.set(W,V);continue}if(!J(W))continue;let H=W==="recall"?$.labels:Q,K=e(W,{scopes:H,descriptions:$.describeScopes(H),kinds:B});X.set(W,{...V,inputSchema:K})}let G=this.config.providerTools.flatMap((W)=>{if(!("tools"in W)||W.name!==h)return[W];let V=W.tools.filter((H)=>X.has(H.name)).map((H)=>JZ(X.get(H.name)));return V.length>0?[{...W,tools:V}]:[]});this.config={...this.config,registry:X,providerTools:G};let z=this.params.memory?.maxTokens??Z.maxTokens??u0;try{this.memoryBlock=await $.block({maxTokens:z,recall:X.has("recall"),tools:X.has("remember")||X.has("forget")})}catch(W){let V=W instanceof Error?W.message:String(W);this.writeLog(`[gemi/ai] agent "${this.config.name}": the memory store could not be read, so this run has no <memory> block: ${V}`,{error:W})}if(this.controller.signal.aborted)throw new S}fail(Z,$={}){let Q={...Z,...$};this.failure=Q,this.emit({type:"error",error:this.redact(Q,{source:"run",failure:Q})})}redact(Z,$){let Q=k0(this.params.redactError,Z,$,(B)=>this.writeLog(`[gemi/ai] agent "${this.config.name}" redactError threw`,{error:B}));return v0(Q,Z),Q}logFailure(Z){let $=`[gemi/ai] agent "${this.config.name}" run failed (${Z.code}${Z.status!==void 0?` ${Z.status}`:""}): ${Z.message}`;this.writeLog($,{error:Z})}logToolFailure(Z,$){let Q=$ instanceof Error?$.message:String($);this.writeLog(`[gemi/ai] agent "${this.config.name}" tool "${String(Z.name)}" threw: ${Q}`,{toolCallId:Z.toolCallId,error:$})}writeLog(Z,$){let Q={agent:this.config.name,runId:this.runId,...this.params.threadId?{threadId:this.params.threadId}:{},...this.depth>0?{chain:this.chain}:{},...$},B=!1;try{XZ.error(Z,Q),B=!0}catch{}if(!B||Bun.env.NODE_ENV==="development")console.error(Z,Q)}async loop(){let Z=Math.max(1,this.config.maxSteps);for(let $=1;$<=Z;$++){let Q=this.startMessage(),B=await this.runStep(Q,$);if(this.lastStep={reason:B.reason,usage:Q.usage},B.error){this.fail(B.error,B.detail),await this.finalizeMessage("error"),this.finishReason="error";return}let J=Q.content.filter((z)=>z.type==="tool-call");if(J.length===0){this.finishReason=B.reason,await this.finalizeMessage(B.reason);return}let X=await this.runTools(Q,J,$);if(X.length>0){if(this.finishReason="awaiting-input",this.depth===0)Q.pending=X;await this.finalizeMessage("awaiting-input"),this.emit({type:"awaiting-input",runId:this.runId,pending:X});return}let G=await this.closingText(Q,J,$);if(G!==null){if(this.finishReason="stop",await this.finalizeMessage(B.reason),G){let z=this.startMessage();l(z,"text",G),this.emit({type:"text-delta",messageId:z.id,delta:G}),await this.finalizeMessage("stop")}return}if($===Z){this.finishReason="max-steps",await this.finalizeMessage("max-steps");return}await this.finalizeMessage(B.reason)}}startMessage(){let Z={id:`msg_${crypto.randomUUID()}`,role:"assistant",content:[],createdAt:new Date().toISOString()};return this.current=Z,this.history.push(Z),this.produced.push(Z),this.emit({type:"message-start",messageId:Z.id,role:"assistant"}),Z}async finalizeMessage(Z){let $=this.current;if(!$)return;this.current=null;let Q=this.outputTruncated;if(this.outputTruncated=!1,$.finishReason=Z,Q)$.outputTruncated=!0;for(let B of $.content)if(B.type==="text"||B.type==="reasoning"){if(typeof B.text==="string")B.text=KZ(B.text)}this.emit({type:"message-end",messageId:$.id,finishReason:Z,...Q?{outputTruncated:!0}:{},...$.usage?{usage:$.usage}:{}}),await this.report($),await this.reportDeferred()}async report(Z){if(!this.params.onMessage)return;try{await this.params.onMessage(Z)}catch{}}async runStep(Z,$){let Q=this.controller.signal,B=this.config.provider,J=await this.prepareRequest(Z,$);if("error"in J)return{reason:"error",error:J.error};let X={reason:"stop"},G=new Map,z=[],W=()=>{if(z.length===0)return{};let q=z;return z=[],{toolSearches:q}},V="",K=B.stream({messages:J.messages,systemPrompt:J.instructions,tools:this.config.providerTools.length>0?this.config.providerTools:void 0,output:this.config.output?YZ(this.config.output):void 0,reasoning:J.reasoning,maxOutputTokens:J.maxOutputTokens,temperature:this.config.temperature,signal:Q})[Symbol.asyncIterator]();for(;;){let q=await w(Promise.resolve(K.next()),Q);if(q.done)break;let F=q.value;switch(F.type){case"text-delta":{l(Z,"text",F.delta),this.emit({type:"text-delta",messageId:Z.id,delta:F.delta});break}case"reasoning-delta":{FZ(Z,F.id,F.delta),this.emit({type:"reasoning-delta",messageId:Z.id,delta:F.delta,id:F.id});break}case"output-delta":{V+=F.delta,this.emit({type:"output-delta",messageId:Z.id,delta:F.delta,snapshot:HZ(V)});break}case"tool-search":{z.push({namespaces:F.namespaces,loaded:F.loaded,...F.arguments!==void 0?{arguments:F.arguments}:{}}),this.emit({type:"tool-search",loaded:F.loaded});break}case"tool-call-delta":{let D=G.get(F.toolCallId)??{name:F.name,args:""};D.args+=F.argsDelta,D.name=F.name||D.name,D.namespace=F.namespace||D.namespace,G.set(F.toolCallId,D),this.emit({type:"tool-call",messageId:Z.id,part:{type:"tool-call",toolCallId:F.toolCallId,name:D.name,input:HZ(D.args),partial:!0,...D.namespace?{namespace:D.namespace}:{}}});break}case"tool-call":{let D=F.namespace||G.get(F.toolCallId)?.namespace||(this.config.registry.get(F.name)?.namespace===f?f:void 0);G.delete(F.toolCallId);let U={type:"tool-call",toolCallId:F.toolCallId,name:F.name,input:l4(F.args),...D?{namespace:D}:{},...W()};Z.content.push(U),this.emit({type:"tool-call",messageId:Z.id,part:U});break}case"finish":{if(this.usage=R(this.usage,F.usage),s(F.model??B.model,F.usage),Z.usage=R(Z.usage??I(),F.usage),!X.error)X={reason:F.reason};break}case"error":{X={reason:"error",error:F.error,detail:d(F)};break}case"file-rejected":{this.markFileRejected(F.fileId,F.message,d(F));break}}}for(let[q,F]of G){let D={type:"tool-call",toolCallId:q,name:F.name,input:l4(F.args),...F.namespace?{namespace:F.namespace}:{},...W()};Z.content.push(D),this.emit({type:"tool-call",messageId:Z.id,part:D})}let Y=X.reason==="length";if(Y)this.outputTruncated=!0;if(this.config.output&&V&&!X.error&&!Y){let q=qZ(this.config.output,V);if(q.ok===!0)this.output=q.value,Z.content.push({type:"output",value:q.value});else this.emit({type:"error",error:q.error})}return X}compactJobParams(Z,$){let Q=this.config.contextWindow;if(!Q?.compact||!this.params.threadId||this.depth!==0)return;let B=Q.compact===!0?{}:Q.compact;return{history:Z,stored:this.history.filter((J)=>J!==$),window:Q,compact:B,threadId:this.params.threadId,provider:this.config.provider,store:B.store||this.params.summaryStore||S4,skills:this.skillNames()}}skillNames(){let Z=new Set;for(let[$,Q]of this.config.registry)if(Q.namespace===f)Z.add($);return Z}precompact(){let Z=this.config.contextWindow;if(!Z?.compact||Z.compact!==!0&&Z.compact.background===!1)return;try{let $=this.compactJobParams(this.historyForProvider(void 0),void 0);if($)E4($)}catch{}}async prepareRequest(Z,$){let Q=this.historyForProvider(Z),B=this.config.contextWindow,J=this.compactJobParams(Q,Z),X=!B?Q:J?await k4({...J,signal:this.controller.signal,onUsage:(V)=>{this.usage=R(this.usage,V)},memo:this.compactMemo}):$Z(Q,B).messages,G=await this.systemPrompt(),z=this.config.reasoning,W=this.config.maxOutputTokens;for(let V of this.config.prepareStep){let H;try{H=await V({step:$,messages:[...X],history:[...Q],instructions:G,reasoning:z,maxOutputTokens:W,body:this.params.body??{},usage:this.usage,...this.lastStep?.usage?{lastStepUsage:this.lastStep.usage}:{},...this.lastStep?{lastFinishReason:this.lastStep.reason}:{},runId:this.runId,threadId:this.params.threadId,agent:this.config.name,depth:this.depth,context:this.context,signal:this.controller.signal})}catch(K){if(K instanceof S||this.controller.signal.aborted)throw K;return{error:{code:"unknown",message:`prepareStep threw: ${K instanceof Error?K.message:String(K)}`,retryable:!1}}}if(!H)continue;if(H.messages!==void 0){if(!Array.isArray(H.messages))return{error:{code:"unknown",message:"prepareStep answered `messages` that is not an array.",retryable:!1}};X=H.messages}if(H.instructions!==void 0)G=H.instructions||void 0;if(H.reasoning!==void 0)z=H.reasoning;if(H.maxOutputTokens!==void 0)W=H.maxOutputTokens}return{messages:X,instructions:G,reasoning:z,maxOutputTokens:W}}async systemPrompt(){let Z=[this.config.instructions,this.params.instructions,this.memoryBlock].filter(($)=>Boolean($&&$.trim()));return Z.length>0?Z.join(`
24
24
 
25
25
  `):void 0}async runTools(Z,$,Q){let B=[],J=[];for(let X of $){let G=this.config.registry.get(String(X.name));if(!G){this.addResult(Z,{type:"tool-result",toolCallId:X.toolCallId,name:X.name,status:"error",error:{code:"tool_error",message:`There is no tool named "${String(X.name)}".`,toolCallId:X.toolCallId,retryable:!0}});continue}let z=G.inputSchema.safeParse(X.input);if(z.ok===!1){this.addResult(Z,{type:"tool-result",toolCallId:X.toolCallId,name:X.name,status:"error",error:{code:"invalid_tool_input",message:`Invalid arguments for "${String(X.name)}": ${z.errors.join(", ")}`,toolCallId:X.toolCallId,retryable:!0}});continue}X.input=z.value;let W=p4(G.tool);if(W==="approval"&&G.tool.approvalPredicate&&!await this.asksApproval(G.tool,X,z.value,Q))W=null;if(W){if(this.onPending==="deny"){this.addResult(Z,this.deniedByPolicy(X));continue}B.push({toolCallId:X.toolCallId,name:X.name,input:z.value,kind:W,signature:H4(this.claimsFor(X.toolCallId,String(X.name),W,z.value)),...this.pathPrefix.length>0?{path:[...this.pathPrefix]}:{}});continue}J.push(this.executeTool(G,Z.id,X,z.value,Q).then(async(V)=>{this.addResult(Z,V),await this.settleShown(X.toolCallId)}).catch((V)=>{if(V instanceof n){if(this.onPending==="deny"){this.addResult(Z,this.deniedByPolicy(X));return}B.push(...V.pending);return}}))}return await w(Promise.all(J).then(()=>{return}),this.controller.signal),B}async closingText(Z,$,Q){let B=[];for(let J of $){let X=this.config.registry.get(String(J.name))?.tool;if(!X?.endsRun)return null;let G=Z.content.find((W)=>W.type==="tool-result"&&W.toolCallId===J.toolCallId);if(G?.status!=="ok")return null;let z=!0;if(typeof X.endsRun==="function"){let W={input:J.input,context:this.context,body:this.params.body??{},runId:this.runId,threadId:this.params.threadId,toolCallId:J.toolCallId,step:Q,depth:this.depth,signal:this.controller.signal};try{z=await w(Promise.resolve().then(()=>X.endsRun(G.output,W)),this.controller.signal)}catch(V){if(V instanceof S)throw V;return this.writeLog(`[gemi/ai] agent "${this.config.name}": the endsRun of "${X.name}" threw, so the run carries on`,{error:V,toolCallId:J.toolCallId}),null}}if(typeof z==="string"){if(z)B.push(z)}else if(z!==!0)return null}return B.join(`
26
26
 
27
- `)}async asksApproval(Z,$,Q,B){let J={context:this.context,body:this.params.body??{},runId:this.runId,threadId:this.params.threadId,toolCallId:$.toolCallId,step:B,depth:this.depth,signal:this.controller.signal};try{return await w(Promise.resolve().then(()=>Z.approvalPredicate(Q,J)),this.controller.signal)!==!1}catch(X){if(X instanceof S)throw X;return this.writeLog(`[gemi/ai] agent "${this.config.name}": the requiresApproval of "${Z.name}" threw, so the call asks the user`,{error:X,toolCallId:$.toolCallId}),!0}}claimsFor(Z,$,Q,B){return{runId:this.signingRunId,toolCallId:Z,name:$,kind:Q,input:B,path:this.pathPrefix.length>0?[...this.pathPrefix]:void 0,subject:this.params.subject??null}}deniedByPolicy(Z){return{type:"tool-result",toolCallId:Z.toolCallId,name:Z.name,status:"denied",cause:"refused",reason:`"${String(Z.name)}" needs the user, and this run was started with onPending: "deny". Answer from what you already have.`}}async executeTool(Z,$,Q,B,J,X){let G=Z.tool.timeoutMs;if(G===void 0)return this.runToolBody(Z,$,Q,B,J,X,this.controller.signal,()=>!1);let z=new AbortController,W=this.controller.signal,V=()=>z.abort(W.reason);if(W.aborted)V();else W.addEventListener("abort",V,{once:!0});let H=!1,K=this.runToolBody(Z,$,Q,B,J,X,z.signal,()=>H),Y=()=>{},q=new Promise((F)=>{Y=h4(G,()=>{let D=`"${String(Q.name)}" did not finish within ${q0(G)} (timeoutMs: ${G}) and was cancelled.`;z.abort(new DOMException(D,"TimeoutError")),F({type:"tool-result",toolCallId:Q.toolCallId,name:Q.name,status:"error",error:{code:"timeout",message:D,toolCallId:Q.toolCallId,retryable:!0}})})});K.catch(()=>{});try{return await Promise.race([K,q])}finally{H=!0,Y()}}async runToolBody(Z,$,Q,B,J,X,G,z){let W=this.toolFiles(Q,G),V={context:this.context,body:this.params.body??{},runId:this.runId,threadId:this.params.threadId,toolCallId:Q.toolCallId,signal:G,step:J,depth:this.depth,resumed:X!==void 0,attachments:W.attachments,generateImage:W.generateImage,editImage:W.editImage,turn:this.toolTurn($),runAgent:this.nestedRunner($,Q,G,X),generate:(H)=>this.generateForTool(H,G,Q.toolCallId),jobs:o4({jobs:this.depth===0?this.params.jobs:void 0,threadId:this.params.threadId,runId:this.runId,toolCallId:Q.toolCallId,toolName:String(Q.name),depth:this.depth,async:Z.tool.async,attachments:this.params.attachments??null}),memory:this.memory.handle({messageId:$}),meter:this.meter};try{let H=Z.tool.execute(B,V),K;if(c9(H)){let Y=await H.next();while(!Y.done){if(z())throw H.return(void 0).catch(()=>{}),new S;this.emit({type:"tool-progress",toolCallId:Q.toolCallId,data:Y.value}),Y=await H.next()}K=Y.value}else K=await H;if(n4(K)){if(K.toolCallId!==Q.toolCallId)throw new P(`"${String(Q.name)}" returned the handle of a job another tool call started. Return the handle from this call's own ctx.jobs.`,{retryable:!1});return{type:"tool-result",toolCallId:Q.toolCallId,name:Q.name,status:"running",job:{id:K.id,...K.summary!==void 0?{summary:K.summary}:{}}}}return{type:"tool-result",toolCallId:Q.toolCallId,name:Q.name,status:"ok",output:K}}catch(H){if(H instanceof S||this.controller.signal.aborted)throw new S;if(H instanceof n)throw H;let K=H instanceof P;if(!K&&this.config.logErrors)this.logToolFailure(Q,H);let Y={code:"tool_error",message:H instanceof Error?H.message:String(H),toolCallId:Q.toolCallId,retryable:K?H.retryable:!0};return{type:"tool-result",toolCallId:Q.toolCallId,name:Q.name,status:"error",error:this.redact(Y,{source:"tool",toolName:String(Q.name),cause:H})}}}async generateForTool(Z,$,Q){let B=this.controller.signal;return GZ({...Z,signal:Z.signal?AbortSignal.any([$,Z.signal]):$},{origin:{agent:this.config.name,runId:this.runId,...this.params.threadId?{threadId:this.params.threadId}:{},toolCallId:Q},settled:(J)=>{if(this.usage=R(this.usage,J.usage),B.aborted)throw new S}})}nestedRunner(Z,$,Q,B){let J=new K0(()=>$.nested,()=>$.nested=[]);return async(X,G={})=>{let{at:z,recorded:W,write:V}=J.next();if(W){let H=l9(W,X,G);if(H)throw new P(`Nested run ${z} of "${String($.name)}" ${H}. `+"runAgent is memoized by call index, so a body whose runAgent calls depend on a condition that changed between turns cannot be resumed \u2014 the answer would be paired with a different sub-run. "+"Make the sequence of runAgent calls, and what each one is asked, the same every time this tool runs, or branch on ctx.resumed.");if(W.finishReason!=="awaiting-input")return{runId:W.runId,agent:W.agent,messages:W.messages,finishReason:W.finishReason??"stop",usage:W.usage??I(),output:g4(W.messages),nested:W}}return this.runNested(Z,$,Q,X,G,V,W,B?.answers??[])}}async runNested(Z,$,Q,B,J,X,G,z){let W=[...this.chain,B.name];if(this.chain.includes(B.name))throw new P(`"${B.name}" is already running further up this chain: ${W.join(" -> ")}. An agent cannot run itself, directly or through another agent.`);let V=this.depth+1;if(V>this.maxDepth)throw new P(`Nested agent runs are ${this.maxDepth} deep at most and this one would be ${V}: ${W.join(" -> ")}. Raise maxDepth on the agent at the root of the run if the tree is meant to be this deep.`);let H=J.label,K=[...this.pathPrefix,$.toolCallId],Y=this.onPending==="deny"?"deny":J.onPending??"escalate",q=G!==void 0,F=q?SZ(G.messages):new Set,D=q?z.filter((O)=>{let k=d4(O.path,K);if(k===null)return!1;return F.has(k.length>0?k[0]:O.toolCallId)}):[],U=B.stream({messages:q?G.messages:J.messages??[],turn:q?{toolResults:D}:J.prompt?{text:J.prompt}:void 0,context:J.context??this.context,attachments:this.params.attachments,body:this.params.body,signal:Q,threadId:this.params.threadId,redactError:this.params.redactError,nonces:this.params.nonces,receipts:this.params.receipts,subject:this.params.subject,...this.params.memory?{memory:{scopes:this.params.memory.scopes}}:{},instructions:J.instructions,maxOutputTokens:J.maxOutputTokens,temperature:J.temperature,runId:q?G.runId:void 0,nesting:{depth:V,maxDepth:this.maxDepth,chain:W,signingRunId:this.signingRunId,signingPath:K,onPending:Y,memoryWrites:this.memory.writes}}),j=[],C=(O)=>this.emit({type:"nested-event",toolCallId:$.toolCallId,runId:U.runId,agent:B.name,label:H,event:O}),L=(async()=>{for await(let O of U){if(O.type==="awaiting-input")j=O.pending;if(C(O),O.type==="run-start"&&!q)for(let k of J.messages??[])C({type:"message",message:k});if(O.type==="error")this.emit({type:"error",error:O.error,nested:{toolCallId:$.toolCallId,runId:U.runId,agent:B.name}})}})(),M=(async()=>{let O=await U.result();await L;let k=q?y4(G.messages,O.messages):y4(J.messages??[],O.messages),t={runId:U.runId,agent:B.name,label:H,messages:k,finishReason:O.finishReason,usage:q?R(G.usage??I(),O.usage):O.usage,...O.finishReason==="awaiting-input"?{signature:D4({runId:this.signingRunId,path:K,nestedRunId:U.runId,open:[...SZ(k)],input:$.input,subject:this.params.subject??null})}:{}};return X(t),this.usage=R(this.usage,O.usage),{result:O,record:t}})(),N=M.then(()=>{return},()=>{return});this.nestedSettling.add(N);let v,T;try{({result:v,record:T}=await M)}finally{this.nestedSettling.delete(N)}if(this.controller.signal.aborted)throw new S;if(v.finishReason==="awaiting-input"){if(j.length===0)throw new P(`"${B.name}" ended awaiting input but asked nothing, so there is no question to escalate.`);throw this.emit({type:"tool-call",messageId:Z,part:$,resent:!0}),new n({pending:j,path:K,nested:T})}return{runId:T.runId,agent:B.name,messages:T.messages,finishReason:v.finishReason,usage:T.usage??I(),output:v.output??g4(T.messages),...v.error?{error:v.error}:{},nested:T}}addResult(Z,$){Z.content.push($),this.emit({type:"tool-result",messageId:Z.id,part:$})}toolFiles(Z,$){let Q=this.params.attachments??null,B=new K0(()=>Z.attachments,()=>Z.attachments=[],()=>({failed:!0})),J=()=>{if(!Q)throw new m("This request has no attachment scope, so a tool cannot store or read files on it. `attachmentScope()` returned null \u2014 put the chat route behind authentication, send a `threadId`, or override `attachmentScope()` on the controller.");return Q},X=async(V,H,K)=>{let Y=J(),q=H.mimeType||V.type||"",F=H.name??(V instanceof File?V.name:"attachment"),D;if(H.showModel){let j=this.config.provider;if(!j.capabilities.fileInput)throw new P(`"${String(Z.name)}" asked to show a file to ${j.model}, which does not accept file input. Drop \`showModel\` for this provider, or run this agent on a model that takes files \u2014 \`capabilities.fileInput\` is what says which do.`);D=await j.upload(new File([V],F,{type:q||void 0}))}return{attachment:await Y.put(V,{name:F,mimeType:q,fileId:D}),...K?{generated:K}:{},...D?{shown:{fileId:D,messageId:`msg_${crypto.randomUUID()}`,createdAt:new Date().toISOString()}}:{}}},G=(V,H,K)=>{let Y=V.generated?"image":"put";if(Y===H)return;throw new P(`Attachment ${K} of "${String(Z.name)}" was ${Y==="image"?"a generated image":"a stored file"} on the first attempt and is ${H==="image"?"a generated image":"a stored file"} now. ctx.attachments.put, ctx.generateImage and ctx.editImage share one memo indexed by call order within a tool call, so the sequence has to be the same every time this tool runs. Branch on ctx.resumed if it cannot be.`)},z=async(V,H,K)=>{let{at:Y,recorded:q,write:F}=B.next();if(q&&"attachment"in q){if(G(q,"image",Y),q.shown)this.queueShown(Z.toolCallId,q);return{attachment:q.attachment,size:q.generated.size,mimeType:q.attachment.mimeType,usage:q.generated.usage}}let D=await K();this.usage=R(this.usage,D.usage);let U=D.mimeType==="image/jpeg"?"jpg":"png",j=await X(D.image,{name:H.name??`${V.name}.${U}`,mimeType:D.mimeType,...H.showModel?{showModel:!0}:{}},{size:D.size,usage:D.usage});if(F(j),j.shown)this.queueShown(Z.toolCallId,j);return{attachment:j.attachment,size:D.size,mimeType:D.mimeType,usage:D.usage}},W=async(V)=>typeof V==="string"?await J().file(V):V;return{generateImage:(V,H)=>z(V,H,()=>V.generate({...H,signal:$})),editImage:(V,H)=>z(V,H,async()=>{let{images:K,mask:Y,...q}=H;return await V.edit({...q,images:await Promise.all(K.map(W)),...Y?{mask:await W(Y)}:{},signal:$})}),attachments:{get:(V)=>J().get(V),read:(V)=>J().read(V),file:(V)=>J().file(V),put:async(V,H={})=>{let{at:K,recorded:Y,write:q}=B.next();if(Y&&"attachment"in Y){G(Y,"put",K);let D=p9(Y,V,H);if(D)throw new P(`Attachment ${K} of "${String(Z.name)}" ${D}. `+"ctx.attachments.put is memoized by call index within a tool call, so a body whose put calls depend on a condition that changed between turns cannot be replayed \u2014 the model would be shown a file under an id that names different bytes. "+"Make the sequence of put calls the same every time this tool runs, or branch on ctx.resumed.");if(Y.shown)this.queueShown(Z.toolCallId,Y);return Y.attachment}let F=await X(V,H);if(q(F),F.shown)this.queueShown(Z.toolCallId,F);return F.attachment}}}}toolTurn(Z){let $=this.history.findIndex((X)=>X.id===Z),Q=IZ(this.history),B;for(let X=$-1;X>=0;X--){let G=this.history[X];if(G.role!=="user"||Q.has(G.id))continue;B=G;break}let J=[];for(let X of B?.content??[]){if(X.type!=="file")continue;let G=X.attachmentId;if(typeof G!=="string"||!G.startsWith(mZ))continue;if(!J.includes(G))J.push(G)}return Object.freeze({attachments:Object.freeze(J)})}queueShown(Z,$){let Q=$.shown;if(!Q)return;let B=this.shownQueue.get(Z)??[];if(B.some((J)=>J.id===Q.messageId))return;B.push({id:Q.messageId,role:"user",content:[{type:"file",fileId:Q.fileId,name:$.attachment.name,mimeType:$.attachment.mimeType,attachmentId:$.attachment.id}],createdAt:Q.createdAt,finishReason:"stop"}),this.shownQueue.set(Z,B)}async settleShown(Z){let $=this.shownQueue.get(Z);if(!$||$.length===0)return;if(this.shownQueue.delete(Z),this.ended||this.controller.signal.aborted)return;for(let Q of $){if(this.history.some((B)=>B.id===Q.id))continue;this.history.push(Q),this.produced.push(Q),this.emit({type:"message",message:Q}),this.unreported.add(Q)}}historyForProvider(Z){let $=this.history.filter((X)=>X!==Z),Q=IZ($),B=[];for(let X of $){if(!Q.has(X.id))continue;for(let G of X.content)if(G.type==="file")B.push(G)}if(B.length<=c4)return $;let J=new Set(B.slice(0,B.length-c4));return $.map((X)=>{if(!X.content.some((G)=>G.type==="file"&&J.has(G)))return X;return{...X,content:X.content.map((G)=>G.type==="file"&&J.has(G)?{type:"text",text:`[A ${G.mimeType||"file"} produced by a tool (attachment ${G.attachmentId}) was attached here and has been dropped from this request: only the most recent tool-produced file is kept attached, to keep the context bounded. Call the tool again if you need to look at it.]`}:G)}})}async ingestTurn(){let Z=this.params.turn,$=this.openCalls(),Q=[];if($.length>0){let B=new Set,J=new Set,X=new Map;for(let G of Z?.toolResults??[]){let z=`${(G.path??[]).join("/")}#${G.toolCallId}`;if(J.has(z))continue;J.add(z);let W=(Y)=>this.emit({type:"error",error:{code:"invalid_tool_result",message:Y,toolCallId:G.toolCallId,retryable:!1}}),V=d4(G.path,this.pathPrefix);if(V===null){W(`The answer for "${G.toolCallId}" is addressed to a tool call this run is not inside.`);continue}if(V.length>0){let Y=V[0],q=$.find((U)=>U.call.toolCallId===Y);if(!q){W(`No pending tool call with id "${Y}" to deliver a nested answer to.`);continue}let F=this.parkedBelow(q.call,V,G.toolCallId);if(F.ok===!1){let U=`The answer for "${G.toolCallId}" is addressed under "${Y}", which`;W(F.reason==="unparked"?`${U} has no sub-agent run waiting on that question.`:F.reason==="expired"?`${U} parked a sub-agent run that has since expired. Ask again.`:`${U} carries a record of a parked sub-agent run the server did not sign.`);continue}let D=X.get(Y);if(!D){if(!await this.spend(L4,F.signature)){W(`The answer for "${G.toolCallId}" is addressed under "${Y}", which has already been re-entered on that record. Ask again.`);continue}D=[],X.set(Y,D),B.add(Y)}D.push(G);continue}let H=$.find((Y)=>Y.call.toolCallId===G.toolCallId);if(!H){W(`No pending tool call with id "${G.toolCallId}".`);continue}let K=await this.resolveAnswer(H,G,Q);if(K===null)continue;if(B.add(G.toolCallId),K!=="open")this.attachToHistory(H,K),await this.settleShown(G.toolCallId)}for(let[G,z]of X){let W=$.find((H)=>H.call.toolCallId===G),V=await this.reenter(W,z,Q);if(V)this.attachToHistory(W,V),await this.settleShown(G)}for(let G of $){if(B.has(G.call.toolCallId))continue;this.attachToHistory(G,{type:"tool-result",toolCallId:G.call.toolCallId,name:G.call.name,status:"denied",cause:"refused"})}await this.reportDeferred()}if(Z&&(Z.text||Z.files&&Z.files.length>0)){let B={id:`msg_${crypto.randomUUID()}`,role:"user",content:[...Z.text?[{type:"text",text:Z.text}]:[],...(Z.files??[]).map((J)=>({type:"file",...J.fileId?{fileId:J.fileId}:{},name:J.name,mimeType:J.mimeType,...J.attachmentId?{attachmentId:J.attachmentId}:{}}))],createdAt:new Date().toISOString(),finishReason:"stop"};if(this.history.push(B),this.produced.push(B),this.depth>0)this.emit({type:"message",message:B});else if(Z.localId)this.emit({type:"message-id",localId:Z.localId,messageId:B.id,message:B});if(await this.report(B),this.params.onTurn)try{await this.params.onTurn(B)}catch{}}return Q}parkedBelow(Z,$,Q){let B=$.length>1?$[1]:Q,J=[...this.pathPrefix,Z.toolCallId],X=(Z.nested??[]).find((z)=>z.finishReason==="awaiting-input"&&SZ(z.messages).has(B));if(!X)return{ok:!1,reason:"unparked"};if(typeof X.signature!=="string")return{ok:!1,reason:"unsigned"};let G=U4(X.signature,{path:J,nestedRunId:X.runId,open:[...SZ(X.messages)],input:Z.input,subject:this.params.subject??null});if(G.ok===!1)return{ok:!1,reason:G.reason==="expired"?"expired":"unsigned"};return{ok:!0,signature:X.signature}}async reenter(Z,$,Q){let B=String(Z.call.name),J=this.config.registry.get(B);if(!J||!J.tool.execute)return{type:"tool-result",toolCallId:Z.call.toolCallId,name:Z.call.name,status:"error",error:{code:"invalid_tool_result",message:`The tool "${B}" no longer exists, so the sub-agent's question cannot be delivered.`,toolCallId:Z.call.toolCallId,retryable:!1}};let X=J.inputSchema.safeParse(Z.call.input);if(X.ok===!1)return{type:"tool-result",toolCallId:Z.call.toolCallId,name:Z.call.name,status:"error",error:{code:"invalid_tool_input",message:`Invalid arguments for "${B}": ${X.errors.join(", ")}`,toolCallId:Z.call.toolCallId,retryable:!0}};let G=this.amendCall(Z);G.input=X.value;try{return await w(this.executeTool(J,Z.message.id,G,X.value,0,{answers:$}),this.controller.signal)}catch(z){if(z instanceof n)return Q.push(...z.pending),null;throw z}}amendCall(Z){let $=this.amend(Z.message),Q=$.content.indexOf(Z.call),B={...Z.call,nested:(Z.call.nested??[]).map((J)=>({...J})),...Z.call.attachments?{attachments:Z.call.attachments.map((J)=>({...J}))}:{}};if(Q>=0)$.content[Q]=B;return this.unreported.add($),B}openCalls(){let Z=new Set;for(let Q of this.history)for(let B of Q.content)if(B.type==="tool-result")Z.add(B.toolCallId);let $=[];for(let Q of this.history)for(let B of Q.content)if(B.type==="tool-call"&&!Z.has(B.toolCallId))$.push({message:Q,call:B});return $}async spend(Z,$){try{return await Z($,this.params.nonces??yZ)}catch(Q){return this.writeLog(`[gemi/ai] agent "${this.config.name}" could not spend a nonce`,{error:Q}),!1}}async recordReceipt(Z,$){let Q=await $;try{await Z.store.complete(Z.id,Q,Z.expiresAt)}catch(B){this.writeLog(`[gemi/ai] agent "${this.config.name}" could not record a tool receipt`,{error:B})}return Q}async resolveAnswer(Z,$,Q){let B=Z.call,J=String(B.name),X=this.config.registry.get(J),G=(K)=>{return this.emit({type:"error",error:{code:"invalid_tool_result",message:K,toolCallId:B.toolCallId,retryable:!1}}),null};if(!X)return G(`The tool "${J}" no longer exists, so its answer cannot be checked.`);let z=p4(X.tool);if(!z)return G(`"${J}" is a server tool with no pending question.`);if(typeof $.signature!=="string"||$.signature.length===0)return G(`The answer for "${J}" carried no signature.`);let W=z0($.signature);if(!W)return G(`The signature for "${J}" is malformed.`);let V=Y4($.signature,{...this.claimsFor(B.toolCallId,J,z,B.input),runId:W.runId});if(V.ok===!1)return G(V.reason==="expired"?`The approval for "${J}" has expired. Ask again.`:`The answer for "${J}" does not match the call the server made.`);let H;if(this.params.receipts&&z==="approval"&&"approve"in $&&$.approve===!0){let K=this.params.receipts,Y=j4(this.config.name,{...this.claimsFor(B.toolCallId,J,z,B.input),runId:W.runId}),q;try{q=await K.claim(Y,W.expiresAt)}catch(F){return this.writeLog(`[gemi/ai] agent "${this.config.name}" could not claim a tool receipt`,{error:F}),G(`The approval for "${J}" could not be checked. Ask again.`)}if(q.status==="replay")return{...q.result,toolCallId:B.toolCallId,name:B.name};if(q.status==="blocked")return{type:"tool-result",toolCallId:B.toolCallId,name:B.name,status:"error",error:{code:"tool_error",message:`"${J}" was already approved and started, and its result is not recorded yet: it is still running, or it stopped before finishing. It was not run again.`,toolCallId:B.toolCallId,retryable:!1}};H={store:K,id:Y,expiresAt:W.expiresAt}}if(!await this.spend(P4,$.signature))return await H?.store.release(H.id).catch((K)=>{this.writeLog(`[gemi/ai] agent "${this.config.name}" could not release a tool receipt`,{error:K})}),G(`The answer for "${J}" has already been used. Ask again.`);if("approve"in $){if(z!=="approval")return G(`"${J}" is answered by the client, not approved.`);if($.approve===!0){let K=this.amendCall(Z),Y=this.executeTool(X,Z.message.id,K,K.input,0);try{return await w(H?this.recordReceipt(H,Y):Y,this.controller.signal)}catch(q){if(q instanceof n)return Q.push(...q.pending),"open";throw q}}return{type:"tool-result",toolCallId:B.toolCallId,name:B.name,status:"denied",cause:"refused",reason:$.reason}}if("output"in $){if(z==="approval")return G(`"${J}" is approved, not answered: the server produces its result.`);let K=X.tool.outputSchema,Y=K?K.safeParse($.output):{ok:!0,value:$.output};if(Y.ok===!1)return{type:"tool-result",toolCallId:B.toolCallId,name:B.name,status:"error",error:{code:"invalid_tool_result",message:`The answer for "${J}" did not match its output schema: ${Y.errors.join(", ")}`,toolCallId:B.toolCallId,retryable:!0}};return{type:"tool-result",toolCallId:B.toolCallId,name:B.name,status:"ok",output:Y.value}}return G(`The answer for "${J}" carried neither an approval nor an output.`)}attachToHistory(Z,$){let Q=this.amend(Z.message);Q.content.push($),this.unreported.add(Q),this.emit({type:"tool-result",messageId:Q.id,part:$})}markFileRejected(Z,$,Q){for(let G of this.history){if(!G.content.some((V)=>V.type==="file"&&V.fileId===Z&&!V.providerRejected))continue;let W=this.produced.includes(G)?G:this.amend(G);if(W.content=W.content.map((V)=>V.type==="file"&&V.fileId===Z&&!V.providerRejected?{...V,providerRejected:!0}:V),W!==this.current)this.unreported.add(W)}if(!this.config.logErrors)return;let B=`[gemi/ai] agent "${this.config.name}": the provider refused file ${Z}${Q.status!==void 0?` (${Q.status})`:""}; it was left out of the request and will not be sent again: ${$}`,J={agent:this.config.name,runId:this.runId,...this.params.threadId?{threadId:this.params.threadId}:{},fileId:Z,...Q},X=!1;try{XZ.warning(B,J),X=!0}catch{}if(!X||Bun.env.NODE_ENV==="development")console.warn(B,J)}amend(Z){let $=this.amended.get(Z.id);if($)return $;let Q={...Z,content:[...Z.content]},B=this.history.indexOf(Z);if(B>=0)this.history[B]=Q;return this.produced.push(Q),this.amended.set(Z.id,Q),Q}async reportDeferred(){let Z=[...this.unreported];this.unreported.clear();for(let $ of Z)await this.report($)}async finalizeAborted(){if(this.nestedSettling.size>0)await Promise.all([...this.nestedSettling]);for(let $ of this.openCalls()){if($.message===this.current)continue;this.attachToHistory($,{type:"tool-result",toolCallId:$.call.toolCallId,name:$.call.name,status:"denied",cause:"stopped",reason:this.stopReason})}await this.reportDeferred();let Z=this.current;if(Z){let $=new Set(Z.content.filter((Q)=>Q.type==="tool-result").map((Q)=>Q.toolCallId));for(let Q of[...Z.content]){if(Q.type!=="tool-call"||$.has(Q.toolCallId))continue;delete Q.partial,this.addResult(Z,{type:"tool-result",toolCallId:Q.toolCallId,name:Q.name,status:"denied",cause:"stopped",reason:this.stopReason})}}if(this.timedOutAfter!==void 0){this.fail({code:"timeout",message:`The run did not finish within its time limit of ${q0(this.timedOutAfter)} (maxRunDurationMs: ${this.timedOutAfter}) and was stopped.`,retryable:!0}),this.finishReason="error",await this.finalizeMessage("error");return}this.finishReason="aborted",await this.finalizeMessage("aborted")}}function p4(Z){if(Z.answeredBy==="client")return Z.inputSchema===F0?"question":"client";return Z.requiresApproval?"approval":null}function l4(Z){if(!Z||!Z.trim())return{};try{return JSON.parse(Z)}catch{return Z}}function w4(Z){return GZ(Z)}async function GZ(Z,$={}){let Q=`gen_${crypto.randomUUID()}`,B=await i9(Z);if($.settled?.(B),!B.ok){if(Z.logErrors!==!1&&B.error.code!=="aborted")a9(Q,B.error,$.origin);if(Z.throwOnError)throw new EZ({runId:Q,messages:B.messages,finishReason:B.finishReason,usage:B.usage,error:B.error},B.rejected?{rejected:B.rejected}:void 0)}return B}var m9=30000;async function i9(Z){if(Z.timeoutMs===void 0)return $7(Z,Z.signal);let $=new AbortController,Q=setTimeout(()=>$.abort(new DOMException("The operation timed out.","TimeoutError")),Z.timeoutMs);try{return await $7(Z,Q7(Z.signal,$.signal))}finally{clearTimeout(Q)}}async function $7(Z,$){let Q=Z.validate,B=Math.max(1,Math.floor(Z.attempts??(Q?3:1))),J=Z.feedback??s9,X=Z.onInvalidOutput??"continue",G=Z.retryErrors??!0,z=Z.messages??[],W=Z.prompt,V="",H=I(),K=[],Y,q,F=(D)=>({...D,usage:H,attempts:K.length,attemptLog:K,...!D.ok&&Y?{rejected:Y}:{}});for(let D=1;D<=B;D++){if(D>1&&$?.aborted)return F({ok:!1,error:B7($),messages:q.messages,usage:H,finishReason:"aborted"});let U=Date.now(),j=Z.attemptTimeoutMs!==void 0?new AbortController:void 0,C=j&&setTimeout(()=>j.abort(new DOMException("The attempt took too long.","TimeoutError")),Z.attemptTimeoutMs),L;try{L=await r9({...Z,messages:z,prompt:V?[W,V].filter(Boolean).join(`
27
+ `)}async asksApproval(Z,$,Q,B){let J={context:this.context,body:this.params.body??{},runId:this.runId,threadId:this.params.threadId,toolCallId:$.toolCallId,step:B,depth:this.depth,signal:this.controller.signal};try{return await w(Promise.resolve().then(()=>Z.approvalPredicate(Q,J)),this.controller.signal)!==!1}catch(X){if(X instanceof S)throw X;return this.writeLog(`[gemi/ai] agent "${this.config.name}": the requiresApproval of "${Z.name}" threw, so the call asks the user`,{error:X,toolCallId:$.toolCallId}),!0}}claimsFor(Z,$,Q,B){return{runId:this.signingRunId,toolCallId:Z,name:$,kind:Q,input:B,path:this.pathPrefix.length>0?[...this.pathPrefix]:void 0,subject:this.params.subject??null}}deniedByPolicy(Z){return{type:"tool-result",toolCallId:Z.toolCallId,name:Z.name,status:"denied",cause:"refused",reason:`"${String(Z.name)}" needs the user, and this run was started with onPending: "deny". Answer from what you already have.`}}async executeTool(Z,$,Q,B,J,X){let G=Z.tool.timeoutMs;if(G===void 0)return this.runToolBody(Z,$,Q,B,J,X,this.controller.signal,()=>!1);let z=new AbortController,W=this.controller.signal,V=()=>z.abort(W.reason);if(W.aborted)V();else W.addEventListener("abort",V,{once:!0});let H=!1,K=this.runToolBody(Z,$,Q,B,J,X,z.signal,()=>H),Y=()=>{},q=new Promise((F)=>{Y=h4(G,()=>{let D=`"${String(Q.name)}" did not finish within ${q0(G)} (timeoutMs: ${G}) and was cancelled.`;z.abort(new DOMException(D,"TimeoutError")),F({type:"tool-result",toolCallId:Q.toolCallId,name:Q.name,status:"error",error:{code:"timeout",message:D,toolCallId:Q.toolCallId,retryable:!0}})})});K.catch(()=>{});try{return await Promise.race([K,q])}finally{H=!0,Y()}}async runToolBody(Z,$,Q,B,J,X,G,z){let W=this.toolFiles(Q,G),V={context:this.context,body:this.params.body??{},runId:this.runId,threadId:this.params.threadId,toolCallId:Q.toolCallId,signal:G,step:J,depth:this.depth,resumed:X!==void 0,attachments:W.attachments,generateImage:W.generateImage,editImage:W.editImage,turn:this.toolTurn($),runAgent:this.nestedRunner($,Q,G,X),generate:(H)=>this.generateForTool(H,G,Q.toolCallId),jobs:o4({jobs:this.depth===0?this.params.jobs:void 0,threadId:this.params.threadId,runId:this.runId,toolCallId:Q.toolCallId,toolName:String(Q.name),depth:this.depth,async:Z.tool.async,attachments:this.params.attachments??null}),memory:this.memory.handle({messageId:$}),meter:this.meter};try{let H=Z.tool.execute(B,V),K;if(c9(H)){let Y=await H.next();while(!Y.done){if(z())throw H.return(void 0).catch(()=>{}),new S;this.emit({type:"tool-progress",toolCallId:Q.toolCallId,data:Y.value}),Y=await H.next()}K=Y.value}else K=await H;if(n4(K)){if(K.toolCallId!==Q.toolCallId)throw new P(`"${String(Q.name)}" returned the handle of a job another tool call started. Return the handle from this call's own ctx.jobs.`,{retryable:!1});return{type:"tool-result",toolCallId:Q.toolCallId,name:Q.name,status:"running",job:{id:K.id,...K.summary!==void 0?{summary:K.summary}:{}}}}return{type:"tool-result",toolCallId:Q.toolCallId,name:Q.name,status:"ok",output:K}}catch(H){if(H instanceof S||this.controller.signal.aborted)throw new S;if(H instanceof n)throw H;let K=H instanceof P;if(!K&&this.config.logErrors)this.logToolFailure(Q,H);let Y={code:"tool_error",message:H instanceof Error?H.message:String(H),toolCallId:Q.toolCallId,retryable:K?H.retryable:!0};return{type:"tool-result",toolCallId:Q.toolCallId,name:Q.name,status:"error",error:this.redact(Y,{source:"tool",toolName:String(Q.name),cause:H})}}}async generateForTool(Z,$,Q){let B=this.controller.signal;return GZ({...Z,signal:Z.signal?AbortSignal.any([$,Z.signal]):$},{origin:{agent:this.config.name,runId:this.runId,...this.params.threadId?{threadId:this.params.threadId}:{},toolCallId:Q},settled:(J)=>{if(this.usage=R(this.usage,J.usage),B.aborted)throw new S}})}nestedRunner(Z,$,Q,B){let J=new K0(()=>$.nested,()=>$.nested=[]);return async(X,G={})=>{let{at:z,recorded:W,write:V}=J.next();if(W){let H=l9(W,X,G);if(H)throw new P(`Nested run ${z} of "${String($.name)}" ${H}. `+"runAgent is memoized by call index, so a body whose runAgent calls depend on a condition that changed between turns cannot be resumed \u2014 the answer would be paired with a different sub-run. "+"Make the sequence of runAgent calls, and what each one is asked, the same every time this tool runs, or branch on ctx.resumed.");if(W.finishReason!=="awaiting-input")return{runId:W.runId,agent:W.agent,messages:W.messages,finishReason:W.finishReason??"stop",usage:W.usage??I(),output:g4(W.messages),nested:W}}return this.runNested(Z,$,Q,X,G,V,W,B?.answers??[])}}async runNested(Z,$,Q,B,J,X,G,z){let W=[...this.chain,B.name];if(this.chain.includes(B.name))throw new P(`"${B.name}" is already running further up this chain: ${W.join(" -> ")}. An agent cannot run itself, directly or through another agent.`);let V=this.depth+1;if(V>this.maxDepth)throw new P(`Nested agent runs are ${this.maxDepth} deep at most and this one would be ${V}: ${W.join(" -> ")}. Raise maxDepth on the agent at the root of the run if the tree is meant to be this deep.`);let H=J.label,K=[...this.pathPrefix,$.toolCallId],Y=this.onPending==="deny"?"deny":J.onPending??"escalate",q=G!==void 0,F=q?SZ(G.messages):new Set,D=q?z.filter((O)=>{let k=d4(O.path,K);if(k===null)return!1;return F.has(k.length>0?k[0]:O.toolCallId)}):[],U=B.stream({messages:q?G.messages:J.messages??[],turn:q?{toolResults:D}:J.prompt?{text:J.prompt}:void 0,context:J.context??this.context,attachments:this.params.attachments,body:this.params.body,signal:Q,threadId:this.params.threadId,redactError:this.params.redactError,nonces:this.params.nonces,receipts:this.params.receipts,subject:this.params.subject,...this.params.memory?{memory:{scopes:this.params.memory.scopes}}:{},instructions:J.instructions,maxOutputTokens:J.maxOutputTokens,temperature:J.temperature,runId:q?G.runId:void 0,nesting:{depth:V,maxDepth:this.maxDepth,chain:W,signingRunId:this.signingRunId,signingPath:K,onPending:Y,memoryWrites:this.memory.writes}}),j=[],C=(O)=>this.emit({type:"nested-event",toolCallId:$.toolCallId,runId:U.runId,agent:B.name,label:H,event:O}),L=(async()=>{for await(let O of U){if(O.type==="awaiting-input")j=O.pending;if(C(O),O.type==="run-start"&&!q)for(let k of J.messages??[])C({type:"message",message:k});if(O.type==="error")this.emit({type:"error",error:O.error,nested:{toolCallId:$.toolCallId,runId:U.runId,agent:B.name}})}})(),M=(async()=>{let O=await U.result();await L;let k=q?y4(G.messages,O.messages):y4(J.messages??[],O.messages),t={runId:U.runId,agent:B.name,label:H,messages:k,finishReason:O.finishReason,usage:q?R(G.usage??I(),O.usage):O.usage,...O.finishReason==="awaiting-input"?{signature:D4({runId:this.signingRunId,path:K,nestedRunId:U.runId,open:[...SZ(k)],input:$.input,subject:this.params.subject??null})}:{}};return X(t),this.usage=R(this.usage,O.usage),{result:O,record:t}})(),N=M.then(()=>{return},()=>{return});this.nestedSettling.add(N);let v,T;try{({result:v,record:T}=await M)}finally{this.nestedSettling.delete(N)}if(this.controller.signal.aborted)throw new S;if(v.finishReason==="awaiting-input"){if(j.length===0)throw new P(`"${B.name}" ended awaiting input but asked nothing, so there is no question to escalate.`);throw this.emit({type:"tool-call",messageId:Z,part:$,resent:!0}),new n({pending:j,path:K,nested:T})}return{runId:T.runId,agent:B.name,messages:T.messages,finishReason:v.finishReason,usage:T.usage??I(),output:v.output??g4(T.messages),...v.error?{error:v.error}:{},nested:T}}addResult(Z,$){Z.content.push($),this.emit({type:"tool-result",messageId:Z.id,part:$})}toolFiles(Z,$){let Q=this.params.attachments??null,B=new K0(()=>Z.attachments,()=>Z.attachments=[],()=>({failed:!0})),J=()=>{if(!Q)throw new m("This request has no attachment scope, so a tool cannot store or read files on it. `attachmentScope()` returned null \u2014 put the chat route behind authentication, send a `threadId`, or override `attachmentScope()` on the controller.");return Q},X=async(V,H,K)=>{let Y=J(),q=H.mimeType||V.type||"",F=H.name??(V instanceof File?V.name:"attachment"),D;if(H.showModel){let j=this.config.provider;if(!j.capabilities.fileInput)throw new P(`"${String(Z.name)}" asked to show a file to ${j.model}, which does not accept file input. Drop \`showModel\` for this provider, or run this agent on a model that takes files \u2014 \`capabilities.fileInput\` is what says which do.`);D=await j.upload(new File([V],F,{type:q||void 0}))}return{attachment:await Y.put(V,{name:F,mimeType:q,fileId:D}),...K?{generated:K}:{},...D?{shown:{fileId:D,messageId:`msg_${crypto.randomUUID()}`,createdAt:new Date().toISOString()}}:{}}},G=(V,H,K)=>{let Y=V.generated?"image":"put";if(Y===H)return;throw new P(`Attachment ${K} of "${String(Z.name)}" was ${Y==="image"?"a generated image":"a stored file"} on the first attempt and is ${H==="image"?"a generated image":"a stored file"} now. ctx.attachments.put, ctx.generateImage and ctx.editImage share one memo indexed by call order within a tool call, so the sequence has to be the same every time this tool runs. Branch on ctx.resumed if it cannot be.`)},z=async(V,H,K)=>{let{at:Y,recorded:q,write:F}=B.next();if(q&&"attachment"in q){if(G(q,"image",Y),q.shown)this.queueShown(Z.toolCallId,q);return{attachment:q.attachment,size:q.generated.size,mimeType:q.attachment.mimeType,usage:q.generated.usage}}let D=await K();this.usage=R(this.usage,D.usage);let U=D.mimeType==="image/jpeg"?"jpg":"png",j=await X(D.image,{name:H.name??`${V.name}.${U}`,mimeType:D.mimeType,...H.showModel?{showModel:!0}:{}},{size:D.size,usage:D.usage});if(F(j),j.shown)this.queueShown(Z.toolCallId,j);return{attachment:j.attachment,size:D.size,mimeType:D.mimeType,usage:D.usage}},W=async(V)=>typeof V==="string"?await J().file(V):V;return{generateImage:(V,H)=>z(V,H,()=>V.generate({...H,signal:$})),editImage:(V,H)=>z(V,H,async()=>{let{images:K,mask:Y,...q}=H;return await V.edit({...q,images:await Promise.all(K.map(W)),...Y?{mask:await W(Y)}:{},signal:$})}),attachments:{get:(V)=>J().get(V),read:(V)=>J().read(V),file:(V)=>J().file(V),put:async(V,H={})=>{let{at:K,recorded:Y,write:q}=B.next();if(Y&&"attachment"in Y){G(Y,"put",K);let D=p9(Y,V,H);if(D)throw new P(`Attachment ${K} of "${String(Z.name)}" ${D}. `+"ctx.attachments.put is memoized by call index within a tool call, so a body whose put calls depend on a condition that changed between turns cannot be replayed \u2014 the model would be shown a file under an id that names different bytes. "+"Make the sequence of put calls the same every time this tool runs, or branch on ctx.resumed.");if(Y.shown)this.queueShown(Z.toolCallId,Y);return Y.attachment}let F=await X(V,H);if(q(F),F.shown)this.queueShown(Z.toolCallId,F);return F.attachment}}}}toolTurn(Z){let $=this.history.findIndex((X)=>X.id===Z),Q=IZ(this.history),B;for(let X=$-1;X>=0;X--){let G=this.history[X];if(G.role!=="user"||Q.has(G.id))continue;B=G;break}let J=[];for(let X of B?.content??[]){if(X.type!=="file")continue;let G=X.attachmentId;if(typeof G!=="string"||!G.startsWith(mZ))continue;if(!J.includes(G))J.push(G)}return Object.freeze({attachments:Object.freeze(J)})}queueShown(Z,$){let Q=$.shown;if(!Q)return;let B=this.shownQueue.get(Z)??[];if(B.some((J)=>J.id===Q.messageId))return;B.push({id:Q.messageId,role:"user",content:[{type:"file",fileId:Q.fileId,name:$.attachment.name,mimeType:$.attachment.mimeType,attachmentId:$.attachment.id}],createdAt:Q.createdAt,finishReason:"stop"}),this.shownQueue.set(Z,B)}async settleShown(Z){let $=this.shownQueue.get(Z);if(!$||$.length===0)return;if(this.shownQueue.delete(Z),this.ended||this.controller.signal.aborted)return;for(let Q of $){if(this.history.some((B)=>B.id===Q.id))continue;this.history.push(Q),this.produced.push(Q),this.emit({type:"message",message:Q}),this.unreported.add(Q)}}historyForProvider(Z){let $=this.history.filter((X)=>X!==Z),Q=IZ($),B=[];for(let X of $){if(!Q.has(X.id))continue;for(let G of X.content)if(G.type==="file")B.push(G)}if(B.length<=c4)return $;let J=new Set(B.slice(0,B.length-c4));return $.map((X)=>{if(!X.content.some((G)=>G.type==="file"&&J.has(G)))return X;return{...X,content:X.content.map((G)=>G.type==="file"&&J.has(G)?{type:"text",text:`[A ${G.mimeType||"file"} produced by a tool (attachment ${G.attachmentId}) was attached here and has been dropped from this request: only the most recent tool-produced file is kept attached, to keep the context bounded. Call the tool again if you need to look at it.]`}:G)}})}async ingestTurn(){let Z=this.params.turn,$=this.openCalls();this.openedWith=$.length;let Q=[];if($.length>0){let B=new Set,J=new Set,X=new Map;for(let G of Z?.toolResults??[]){let z=`${(G.path??[]).join("/")}#${G.toolCallId}`;if(J.has(z))continue;J.add(z);let W=(Y)=>this.emit({type:"error",error:{code:"invalid_tool_result",message:Y,toolCallId:G.toolCallId,retryable:!1}}),V=d4(G.path,this.pathPrefix);if(V===null){W(`The answer for "${G.toolCallId}" is addressed to a tool call this run is not inside.`);continue}if(V.length>0){let Y=V[0],q=$.find((U)=>U.call.toolCallId===Y);if(!q){W(`No pending tool call with id "${Y}" to deliver a nested answer to.`);continue}let F=this.parkedBelow(q.call,V,G.toolCallId);if(F.ok===!1){let U=`The answer for "${G.toolCallId}" is addressed under "${Y}", which`;W(F.reason==="unparked"?`${U} has no sub-agent run waiting on that question.`:F.reason==="expired"?`${U} parked a sub-agent run that has since expired. Ask again.`:`${U} carries a record of a parked sub-agent run the server did not sign.`);continue}let D=X.get(Y);if(!D){if(!await this.spend(L4,F.signature)){W(`The answer for "${G.toolCallId}" is addressed under "${Y}", which has already been re-entered on that record. Ask again.`);continue}D=[],X.set(Y,D),B.add(Y)}D.push(G);continue}let H=$.find((Y)=>Y.call.toolCallId===G.toolCallId);if(!H){W(`No pending tool call with id "${G.toolCallId}".`);continue}let K=await this.resolveAnswer(H,G,Q);if(K===null)continue;if(B.add(G.toolCallId),K!=="open")this.attachToHistory(H,K),await this.settleShown(G.toolCallId)}for(let[G,z]of X){let W=$.find((H)=>H.call.toolCallId===G),V=await this.reenter(W,z,Q);if(V)this.attachToHistory(W,V),await this.settleShown(G)}for(let G of $){if(B.has(G.call.toolCallId))continue;this.attachToHistory(G,{type:"tool-result",toolCallId:G.call.toolCallId,name:G.call.name,status:"denied",cause:"refused"})}if(this.depth===0)this.restatePending($,Q);await this.reportDeferred()}if(Z&&(Z.text||Z.files&&Z.files.length>0)){let B={id:`msg_${crypto.randomUUID()}`,role:"user",content:[...Z.text?[{type:"text",text:Z.text}]:[],...(Z.files??[]).map((J)=>({type:"file",...J.fileId?{fileId:J.fileId}:{},name:J.name,mimeType:J.mimeType,...J.attachmentId?{attachmentId:J.attachmentId}:{}}))],createdAt:new Date().toISOString(),finishReason:"stop"};if(this.history.push(B),this.produced.push(B),this.depth>0)this.emit({type:"message",message:B});else if(Z.localId)this.emit({type:"message-id",localId:Z.localId,messageId:B.id,message:B});if(await this.report(B),this.params.onTurn)try{await this.params.onTurn(B)}catch{}}return Q}parkedBelow(Z,$,Q){let B=$.length>1?$[1]:Q,J=[...this.pathPrefix,Z.toolCallId],X=(Z.nested??[]).find((z)=>z.finishReason==="awaiting-input"&&SZ(z.messages).has(B));if(!X)return{ok:!1,reason:"unparked"};if(typeof X.signature!=="string")return{ok:!1,reason:"unsigned"};let G=U4(X.signature,{path:J,nestedRunId:X.runId,open:[...SZ(X.messages)],input:Z.input,subject:this.params.subject??null});if(G.ok===!1)return{ok:!1,reason:G.reason==="expired"?"expired":"unsigned"};return{ok:!0,signature:X.signature}}async reenter(Z,$,Q){let B=String(Z.call.name),J=this.config.registry.get(B);if(!J||!J.tool.execute)return{type:"tool-result",toolCallId:Z.call.toolCallId,name:Z.call.name,status:"error",error:{code:"invalid_tool_result",message:`The tool "${B}" no longer exists, so the sub-agent's question cannot be delivered.`,toolCallId:Z.call.toolCallId,retryable:!1}};let X=J.inputSchema.safeParse(Z.call.input);if(X.ok===!1)return{type:"tool-result",toolCallId:Z.call.toolCallId,name:Z.call.name,status:"error",error:{code:"invalid_tool_input",message:`Invalid arguments for "${B}": ${X.errors.join(", ")}`,toolCallId:Z.call.toolCallId,retryable:!0}};let G=this.amendCall(Z);G.input=X.value;try{return await w(this.executeTool(J,Z.message.id,G,X.value,0,{answers:$}),this.controller.signal)}catch(z){if(z instanceof n)return Q.push(...z.pending),null;throw z}}amendCall(Z){let $=this.amend(Z.message),Q=$.content.indexOf(Z.call),B={...Z.call,nested:(Z.call.nested??[]).map((J)=>({...J})),...Z.call.attachments?{attachments:Z.call.attachments.map((J)=>({...J}))}:{}};if(Q>=0)$.content[Q]=B;return this.unreported.add($),B}answersOnlyStale(){let Z=this.params.turn;if(!Z?.toolResults?.length||Z.text||Z.files?.length)return!1;return this.openedWith===0}restatePending(Z,$){let Q=new Map;for(let B of Z){let J=Q.get(B.message);if(!J)Q.set(B.message,J=new Set);J.add(B.call.toolCallId)}for(let[B,J]of Q){let X=$.filter((z)=>J.has(z.path?.[0]??z.toolCallId));if(X.length===0&&B.pending===void 0)continue;let G=this.amend(B);if(X.length>0)G.pending=X;else delete G.pending;this.unreported.add(G)}}openCalls(){let Z=new Set;for(let Q of this.history)for(let B of Q.content)if(B.type==="tool-result")Z.add(B.toolCallId);let $=[];for(let Q of this.history)for(let B of Q.content)if(B.type==="tool-call"&&!Z.has(B.toolCallId))$.push({message:Q,call:B});return $}async spend(Z,$){try{return await Z($,this.params.nonces??yZ)}catch(Q){return this.writeLog(`[gemi/ai] agent "${this.config.name}" could not spend a nonce`,{error:Q}),!1}}async recordReceipt(Z,$){let Q=await $;try{await Z.store.complete(Z.id,Q,Z.expiresAt)}catch(B){this.writeLog(`[gemi/ai] agent "${this.config.name}" could not record a tool receipt`,{error:B})}return Q}async resolveAnswer(Z,$,Q){let B=Z.call,J=String(B.name),X=this.config.registry.get(J),G=(K)=>{return this.emit({type:"error",error:{code:"invalid_tool_result",message:K,toolCallId:B.toolCallId,retryable:!1}}),null};if(!X)return G(`The tool "${J}" no longer exists, so its answer cannot be checked.`);let z=p4(X.tool);if(!z)return G(`"${J}" is a server tool with no pending question.`);if(typeof $.signature!=="string"||$.signature.length===0)return G(`The answer for "${J}" carried no signature.`);let W=z0($.signature);if(!W)return G(`The signature for "${J}" is malformed.`);let V=Y4($.signature,{...this.claimsFor(B.toolCallId,J,z,B.input),runId:W.runId});if(V.ok===!1)return G(V.reason==="expired"?`The approval for "${J}" has expired. Ask again.`:`The answer for "${J}" does not match the call the server made.`);let H;if(this.params.receipts&&z==="approval"&&"approve"in $&&$.approve===!0){let K=this.params.receipts,Y=j4(this.config.name,{...this.claimsFor(B.toolCallId,J,z,B.input),runId:W.runId}),q;try{q=await K.claim(Y,W.expiresAt)}catch(F){return this.writeLog(`[gemi/ai] agent "${this.config.name}" could not claim a tool receipt`,{error:F}),G(`The approval for "${J}" could not be checked. Ask again.`)}if(q.status==="replay")return{...q.result,toolCallId:B.toolCallId,name:B.name};if(q.status==="blocked")return{type:"tool-result",toolCallId:B.toolCallId,name:B.name,status:"error",error:{code:"tool_error",message:`"${J}" was already approved and started, and its result is not recorded yet: it is still running, or it stopped before finishing. It was not run again.`,toolCallId:B.toolCallId,retryable:!1}};H={store:K,id:Y,expiresAt:W.expiresAt}}if(!await this.spend(P4,$.signature))return await H?.store.release(H.id).catch((K)=>{this.writeLog(`[gemi/ai] agent "${this.config.name}" could not release a tool receipt`,{error:K})}),G(`The answer for "${J}" has already been used. Ask again.`);if("approve"in $){if(z!=="approval")return G(`"${J}" is answered by the client, not approved.`);if($.approve===!0){let K=this.amendCall(Z),Y=this.executeTool(X,Z.message.id,K,K.input,0);try{return await w(H?this.recordReceipt(H,Y):Y,this.controller.signal)}catch(q){if(q instanceof n)return Q.push(...q.pending),"open";throw q}}return{type:"tool-result",toolCallId:B.toolCallId,name:B.name,status:"denied",cause:"refused",reason:$.reason}}if("output"in $){if(z==="approval")return G(`"${J}" is approved, not answered: the server produces its result.`);let K=X.tool.outputSchema,Y=K?K.safeParse($.output):{ok:!0,value:$.output};if(Y.ok===!1)return{type:"tool-result",toolCallId:B.toolCallId,name:B.name,status:"error",error:{code:"invalid_tool_result",message:`The answer for "${J}" did not match its output schema: ${Y.errors.join(", ")}`,toolCallId:B.toolCallId,retryable:!0}};return{type:"tool-result",toolCallId:B.toolCallId,name:B.name,status:"ok",output:Y.value}}return G(`The answer for "${J}" carried neither an approval nor an output.`)}attachToHistory(Z,$){let Q=this.amend(Z.message);Q.content.push($),this.unreported.add(Q),this.emit({type:"tool-result",messageId:Q.id,part:$})}markFileRejected(Z,$,Q){for(let G of this.history){if(!G.content.some((V)=>V.type==="file"&&V.fileId===Z&&!V.providerRejected))continue;let W=this.produced.includes(G)?G:this.amend(G);if(W.content=W.content.map((V)=>V.type==="file"&&V.fileId===Z&&!V.providerRejected?{...V,providerRejected:!0}:V),W!==this.current)this.unreported.add(W)}if(!this.config.logErrors)return;let B=`[gemi/ai] agent "${this.config.name}": the provider refused file ${Z}${Q.status!==void 0?` (${Q.status})`:""}; it was left out of the request and will not be sent again: ${$}`,J={agent:this.config.name,runId:this.runId,...this.params.threadId?{threadId:this.params.threadId}:{},fileId:Z,...Q},X=!1;try{XZ.warning(B,J),X=!0}catch{}if(!X||Bun.env.NODE_ENV==="development")console.warn(B,J)}amend(Z){let $=this.amended.get(Z.id);if($)return $;let Q={...Z,content:[...Z.content]},B=this.history.indexOf(Z);if(B>=0)this.history[B]=Q;return this.produced.push(Q),this.amended.set(Z.id,Q),Q}async reportDeferred(){let Z=[...this.unreported];this.unreported.clear();for(let $ of Z)await this.report($)}async finalizeAborted(){if(this.nestedSettling.size>0)await Promise.all([...this.nestedSettling]);for(let $ of this.openCalls()){if($.message===this.current)continue;this.attachToHistory($,{type:"tool-result",toolCallId:$.call.toolCallId,name:$.call.name,status:"denied",cause:"stopped",reason:this.stopReason})}await this.reportDeferred();let Z=this.current;if(Z){let $=new Set(Z.content.filter((Q)=>Q.type==="tool-result").map((Q)=>Q.toolCallId));for(let Q of[...Z.content]){if(Q.type!=="tool-call"||$.has(Q.toolCallId))continue;delete Q.partial,this.addResult(Z,{type:"tool-result",toolCallId:Q.toolCallId,name:Q.name,status:"denied",cause:"stopped",reason:this.stopReason})}}if(this.timedOutAfter!==void 0){this.fail({code:"timeout",message:`The run did not finish within its time limit of ${q0(this.timedOutAfter)} (maxRunDurationMs: ${this.timedOutAfter}) and was stopped.`,retryable:!0}),this.finishReason="error",await this.finalizeMessage("error");return}this.finishReason="aborted",await this.finalizeMessage("aborted")}}function p4(Z){if(Z.answeredBy==="client")return Z.inputSchema===F0?"question":"client";return Z.requiresApproval?"approval":null}function l4(Z){if(!Z||!Z.trim())return{};try{return JSON.parse(Z)}catch{return Z}}function w4(Z){return GZ(Z)}async function GZ(Z,$={}){let Q=`gen_${crypto.randomUUID()}`,B=await i9(Z);if($.settled?.(B),!B.ok){if(Z.logErrors!==!1&&B.error.code!=="aborted")a9(Q,B.error,$.origin);if(Z.throwOnError)throw new EZ({runId:Q,messages:B.messages,finishReason:B.finishReason,usage:B.usage,error:B.error},B.rejected?{rejected:B.rejected}:void 0)}return B}var m9=30000;async function i9(Z){if(Z.timeoutMs===void 0)return $7(Z,Z.signal);let $=new AbortController,Q=setTimeout(()=>$.abort(new DOMException("The operation timed out.","TimeoutError")),Z.timeoutMs);try{return await $7(Z,Q7(Z.signal,$.signal))}finally{clearTimeout(Q)}}async function $7(Z,$){let Q=Z.validate,B=Math.max(1,Math.floor(Z.attempts??(Q?3:1))),J=Z.feedback??s9,X=Z.onInvalidOutput??"continue",G=Z.retryErrors??!0,z=Z.messages??[],W=Z.prompt,V="",H=I(),K=[],Y,q,F=(D)=>({...D,usage:H,attempts:K.length,attemptLog:K,...!D.ok&&Y?{rejected:Y}:{}});for(let D=1;D<=B;D++){if(D>1&&$?.aborted)return F({ok:!1,error:B7($),messages:q.messages,usage:H,finishReason:"aborted"});let U=Date.now(),j=Z.attemptTimeoutMs!==void 0?new AbortController:void 0,C=j&&setTimeout(()=>j.abort(new DOMException("The attempt took too long.","TimeoutError")),Z.attemptTimeoutMs),L;try{L=await r9({...Z,messages:z,prompt:V?[W,V].filter(Boolean).join(`
28
28
 
29
29
  `):W,signal:Q7($,j?.signal)})}finally{clearTimeout(C)}q=L,H=R(H,L.usage);let M={attempt:D,outcome:"passed",durationMs:Date.now()-U,usage:L.usage,finishReason:L.finishReason},N=(E)=>{Object.assign(M,E),K.push(M),Z.onAttempt?.(M)},v=D<B;if(!L.ok){let{error:E}=L,wZ=!!j?.signal.aborted&&!$?.aborted,bZ=E.code==="invalid_output"&&L.finishReason==="length";if(wZ||bZ||E.code==="invalid_output"){let zZ=wZ?"timeout":bZ?"cut_off":"invalid_output",N0=wZ?[`The answer took longer than ${Math.round(Z.attemptTimeoutMs/1000)} seconds and was stopped before it finished.`]:bZ?[E.message]:[`The output does not match the output schema: ${E.message}`];N({outcome:zZ,problems:N0,error:E});let R0=zZ!=="invalid_output"||X==="restart";if(!v||zZ==="invalid_output"&&X==="fail")return F(L);let _0=J(N0,{attempt:D,attempts:B,cause:zZ,restart:R0});if(R0)V=_0;else z=L.messages,W=_0,V="";continue}if(N({outcome:"error",error:E}),v&&G&&E.retryable&&!$?.aborted&&!j?.signal.aborted){if(E.retryAfter)await o9(Math.min(E.retryAfter,m9),$);continue}return F(L)}if(!Q)return N({}),F(L);let T=t9(await Q(L.output,{attempt:D,attempts:B,messages:L.messages,signal:$??n9}));if(T.ok===!0)return N({}),F({...L,output:T.value===L0?L.output:T.value});let O=T.problems.length>0?T.problems:["The answer was rejected."];if(Y={output:L.output,problems:O},N({outcome:"rejected",problems:O}),!v||T.retry===!1)return F({ok:!1,error:{code:"invalid_output",message:T.retry===!1?`The answer was rejected:
30
30
  ${vZ(O)}`:`The answer was rejected ${D===1?"once":`${D} times`}. The last attempt's problems:
@@ -38,4 +38,4 @@ ${vZ(Z)}
38
38
  Correct these problems and give the whole answer again.`}function a9(Z,$,Q){let B=`[gemi/ai] generate() failed (${$.code}${$.status!==void 0?` ${$.status}`:""}): ${$.message}`,J={...Q,generateId:Z,error:$},X=!1;try{XZ.error(B,J),X=!0}catch{}if(!X||Bun.env.NODE_ENV==="development")console.error(B,J)}async function r9(Z){let $=Z.messages??[];if($.length===0&&!Z.prompt)throw Error("generate() was given neither a `prompt` nor `messages`, so there is nothing to send the model.");let Q=[...$];if(Z.prompt)Q.push({id:`msg_${crypto.randomUUID()}`,role:"user",content:[{type:"text",text:Z.prompt}],createdAt:new Date().toISOString()});let B={id:`msg_${crypto.randomUUID()}`,role:"assistant",content:[],createdAt:new Date().toISOString()},J=Z.signal??new AbortController().signal,X=I(),G="stop",z,W={},V="";try{let q=Z.provider.stream({messages:[...Q],systemPrompt:Z.instructions?.trim()?Z.instructions:void 0,output:YZ(Z.output),reasoning:Z.reasoning,maxOutputTokens:Z.maxOutputTokens,temperature:Z.temperature,signal:Z.signal})[Symbol.asyncIterator]();try{for(;;){let F=await w(Promise.resolve(q.next()),J);if(F.done)break;let D=F.value;switch(D.type){case"output-delta":V+=D.delta;break;case"text-delta":l(B,"text",D.delta);break;case"reasoning-delta":FZ(B,D.id,D.delta);break;case"finish":if(X=R(X,D.usage),s(D.model??Z.provider.model,D.usage),!z)G=D.reason;break;case"error":G="error",z=D.error,W=d(D);break}}}finally{if(J.aborted)Promise.resolve(q.return?.()).catch(()=>{})}}catch(Y){if(Y instanceof S||J.aborted)G="aborted",z=B7(J);else G="error",z=Z.provider.normalizeError(Y),W=d(Y)}let H=!1,K;if(!z)if(G==="length")z={code:"invalid_output",message:"The model ran out of output tokens before finishing its structured answer, so it was cut off. Raise maxOutputTokens, or ask for a shorter answer.",retryable:!0};else if(!V.trim())z={code:"invalid_output",message:"The model finished without giving a structured answer.",retryable:!0};else{let Y=qZ(Z.output,V);if(Y.ok===!0)H=!0,K=Y.value;else z=Y.error}if(H)B.content.push({type:"output",value:K});else if(V)l(B,"text",V);for(let Y of B.content)if((Y.type==="text"||Y.type==="reasoning")&&typeof Y.text==="string")Y.text=KZ(Y.text);if(B.finishReason=G,B.usage=X,Q.push(B),H)return{ok:!0,output:K,messages:Q,usage:X,finishReason:G};return{ok:!1,error:{...z,...W},messages:Q,usage:X,finishReason:G}}function B7(Z){return Z.reason?.name==="TimeoutError"?{code:"timeout",message:"The generation timed out.",retryable:!0}:{code:"aborted",message:"The generation was stopped.",retryable:!1}}var V7=Symbol.for("gemi.ai.JobHandle");class H7{id;toolCallId;summary;deadlineAt;[V7]=!0;constructor(Z,$,Q,B){this.id=Z;this.toolCallId=$;this.summary=Q;this.deadlineAt=B}}function n4(Z){return typeof Z==="object"&&Z!==null&&Z[V7]===!0}class C0 extends P{code="jobs_require_thread";constructor(Z){super(Z,{retryable:!1});this.name="JobsRequireThreadError"}}var o=new nZ,e9=["running","ok","error"],O0={get store(){return o},use(Z){o=Z},get(Z){return o.get(Z)},async settle(Z,$){return fZ(o,Z,$)},async fail(Z,$){return fZ(o,Z,{error:$})},async sweep(Z={}){let $=o,Q=Z.limit??100,B=await Z$($),J=0;for(let X of await $.overdue(B,Q))if(await $$($,X))J++;return J}};async function Z$(Z){return Z.now?await Z.now():Date.now()}function $$(Z,$){return Z.transition($.id,["running"],{state:"error",error:{code:"timeout",message:`The background job for "${$.toolName}" did not finish before its deadline, so it was given up on. Its result, if it ever arrives, is ignored.`,toolCallId:$.toolCallId,retryable:!0}})}async function fZ(Z,$,Q){let B=await Z.get($);if(!B||B.state!=="running")return!1;let J=Q.usage?R(B.usage??I(),Q.usage):void 0;if("error"in Q)return Z.transition($,["running"],{state:"error",error:Q$(B,Q.error),...J?{usage:J}:{}});return Z.transition($,["running"],{state:"ok",output:Y7(Q.output,B),...J?{usage:J}:{}})}function Q$(Z,$){if(typeof $==="string")return{code:"tool_error",message:$,toolCallId:Z.toolCallId,retryable:!0};if($ instanceof Error){let Q={code:"tool_error",message:$.message,toolCallId:Z.toolCallId,retryable:$ instanceof P?$.retryable:!0};if(!($ instanceof P))console.error(`The background job ${Z.job??"(tracked)"} for "${Z.toolName}" failed.`,$);return DZ(Q,{source:"tool",toolName:Z.toolName,cause:$})}return{code:$.code??"tool_error",message:String($.message),toolCallId:Z.toolCallId,retryable:$.retryable??!0}}function Y7(Z,$){if(Z===void 0)return null;try{return JSON.parse(JSON.stringify(Z))}catch(Q){throw Error(`The output of the background job for "${$.toolName}" is not JSON: ${String(Q)}`)}}var B$=3600000;function o4(Z){let $=null,Q=(B,J,X={})=>{if(Z.async===void 0)throw new P(`"${Z.toolName}" called ctx.jobs, but the tool does not declare \`async\`. Add \`async: { deadlineMs }\` to its definition.`,{retryable:!1});if(!Z.jobs||!Z.threadId)throw new C0(`"${Z.toolName}" can only run in the background on a conversation the server keeps (a turn with a threadId), and this one has none.`);if(Z.depth>0)throw new C0(`"${Z.toolName}" can only run in the background from the top-level agent, not from a sub-agent.`);if($)throw new P(`"${Z.toolName}" started a background job already: a tool call has at most one.`,{retryable:!1});let G=X.deadlineMs??Z.async.deadlineMs??B$;if(!Number.isFinite(G)||G<=0)throw new P(`A job's deadlineMs must be a positive number; got ${G}.`);let{jobs:z,threadId:W}=Z;return $=(async()=>{let V=O0.store,H=(await V.listForThread(W,{limit:50})).find((q)=>q.toolCallId===Z.toolCallId);if(H)return J7(H);let K=async()=>{let q=await V.create({id:`ajob_${crypto.randomUUID()}`,threadId:W,runId:Z.runId,toolCallId:Z.toolCallId,toolName:Z.toolName,owner:z.owner,job:B?B.name:null,...X.summary!==void 0?{summary:Y7(X.summary,Z)}:{},attachmentScope:Z.attachments?.scopeKey??null,deadlineMs:G});if(B)try{await J$(B,{jobId:q.id,args:J})}catch(F){if(V.transaction)throw F;throw await V.transition(q.id,["running"],{state:"error",error:{code:"tool_error",message:`The background job for "${Z.toolName}" could not be queued.`,toolCallId:Z.toolCallId,retryable:!0}}).catch(()=>{}),F}return q},Y=V.transaction?await V.transaction(K):await K();return J7(Y)})(),$};return{start:(B,J,X)=>Q(B,J,X),track:(B)=>Q(null,void 0,B)}}function J7(Z){return new H7(Z.id,Z.toolCallId,Z.summary,Z.deadlineAt)}function J$(Z,$){if(Z.name==="unset"||!Z.name)throw Error("Cannot start an AgentJob with no `static name`.");return WZ(z7).push(Z,JSON.stringify([$]))}class X$ extends W7{attachments=w0;attachmentStorage=G7;constructor(){super();let Z=this.run;this.run=($)=>this.$runEnvelope($,Z)}onDeadletter(Z,...$){let Q=$[0];if(!Q?.jobId)return;fZ(O0.store,Q.jobId,{error:Z}).catch((B)=>{console.error(`Could not record the failure of background job ${Q.jobId}.`,B)})}async $runEnvelope(Z,$){let Q=O0.store,B=await Q.get(Z.jobId);if(!B||B.state!=="running")return;let J=new q7(B,this),X;try{X=await $.call(this,Z.args,J)}catch(G){throw await X7(Q,B.id,J.usage),G}if(this.$outcome)return await X7(Q,B.id,J.usage),X;return await fZ(Q,B.id,{output:X,usage:J.usage}),X}}async function X7(Z,$,Q){if(Q.totalTokens===0&&Q.inputTokens===0&&Q.outputTokens===0)return;let B=await Z.get($);if(!B)return;await Z.transition($,e9,{usage:R(B.usage??I(),Q)}).catch(()=>{})}class q7{id;threadId;toolCallId;toolName;owner;summary;signal=new AbortController().signal;usage=I();attachments;constructor(Z,$){this.id=Z.id,this.threadId=Z.threadId,this.toolCallId=Z.toolCallId,this.toolName=Z.toolName,this.owner=Z.owner,this.summary=Z.summary;let Q=Z.attachmentScope?new iZ($.attachments,$.attachmentStorage,{key:Z.attachmentScope}):null,B=()=>{if(!Q)throw new m("The run that started this job had no attachment scope, so the job cannot store or read files. See `attachmentScope()` on the controller.");return Q};this.attachments={put:(J,X={})=>B().put(J,X),get:(J)=>B().get(J),read:(J)=>B().read(J),file:(J)=>B().file(J)}}generate(Z){return GZ(Z,{origin:{threadId:this.threadId,toolCallId:this.toolCallId,jobId:this.id},settled:($)=>{this.usage=R(this.usage,$.usage)}})}async generateImage(Z,$){let{name:Q,...B}=$,J=await Z.generate({...B,signal:this.signal});return this.park(Z,J,Q)}async editImage(Z,$){let{name:Q,images:B,mask:J,...X}=$,G=async(W)=>typeof W==="string"?await this.attachments.file(W):W,z=await Z.edit({...X,images:await Promise.all(B.map(G)),...J?{mask:await G(J)}:{},signal:this.signal});return this.park(Z,z,Q)}async park(Z,$,Q){this.usage=R(this.usage,$.usage);let B=$.mimeType==="image/jpeg"?"jpg":"png";return{attachment:await this.attachments.put($.image,{name:Q??`${Z.name}.${B}`,mimeType:$.mimeType}),size:$.size,mimeType:$.mimeType,usage:$.usage}}}
39
39
  export{M0 as Yb,K7 as Zb,F7 as _b,yZ as $b,ZZ as ac,A as bc,Y$ as cc,I as dc,R as ec,dZ as fc,s as gc,L7 as hc,D$ as ic,U$ as jc,P as kc,DZ as lc,P$ as mc,pZ as nc,m as oc,mZ as pc,O7 as qc,iZ as rc,N7 as sc,f0 as tc,w0 as uc,nZ as vc,H7 as wc,n4 as xc,C0 as yc,O0 as zc,Z$ as Ac,$$ as Bc,B$ as Cc,o4 as Dc,X$ as Ec,u0 as Fc,p0 as Gc,E7 as Hc,v7 as Ic,UZ as Jc,i as Kc,Z0 as Lc,u as Mc,$0 as Nc,h7 as Oc,h as Pc,h$ as Qc,O4 as Rc,N4 as Sc,d as Tc,d$ as Uc,IZ as Vc,MZ as Wc,l$ as Xc,Q9 as Yc,J9 as Zc,X9 as _c,$Z as $c,V9 as ad,q9 as bd,F9 as cd,D9 as dd,T4 as ed,j9 as fd,S4 as gd,s$ as hd,a$ as id,n as jd,b as kd,D0 as ld,t4 as md,f as nd,a4 as od,EZ as pd,P0 as qd,w4 as rd,GZ as sd};
40
40
 
41
- //# debugId=58507F6B0CA2807F64756E2164756E21
41
+ //# debugId=EB8EAF5B59887B8564756E2164756E21