gemi 0.94.0 → 0.95.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.
- package/dist/ai/FallbackProvider.d.ts +154 -0
- package/dist/ai/FallbackProvider.d.ts.map +1 -0
- package/dist/ai/index.d.ts +2 -0
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +12 -12
- package/dist/ai/index.js.map +4 -3
- package/dist/{chunk-bk8wjf00.js → chunk-fyxp4bn0.js} +1 -1
- package/dist/{chunk-r7qzdmew.js → chunk-mf936r5e.js} +2 -2
- package/dist/{chunk-r7qzdmew.js.map → chunk-mf936r5e.js.map} +1 -1
- package/dist/{chunk-sh6pjjgc.js → chunk-nfhy3sp8.js} +1 -1
- package/dist/server/index.js +1 -1
- package/package.json +1 -1
- /package/dist/{chunk-bk8wjf00.js.map → chunk-fyxp4bn0.js.map} +0 -0
- /package/dist/{chunk-sh6pjjgc.js.map → chunk-nfhy3sp8.js.map} +0 -0
package/dist/ai/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Ab as f9,Bb as F$,Cb as C$,Db as Y3,zb as O}from"../chunk-wc46df4w.js";import{Me as X3,Pe as V3,cf as H6,df as Y6,ef as n,ff as WQ,tf as H3,vf as t,wf as gQ}from"../chunk-mym0zxxp.js";import{Af as hQ,xf as G3,zf as fQ}from"../chunk-9xf2fx98.js";import{Ef as NQ}from"../chunk-eqtsfvvd.js";import{Hg as y9}from"../chunk-7hfv5n00.js";import"../chunk-qxda7pzm.js";import"../chunk-kzh8bkg5.js";import"../chunk-j2nx0dtq.js";class I extends Error{status;body;requestId;constructor(Q,$,Z){super(`Provider request failed with status ${Q}: ${P3($)}`);this.name="ProviderHttpError",this.status=Q,this.body=$,this.requestId=Z}}class GQ extends Error{timeoutMs;constructor(Q){super(`Provider request timed out after ${Q}ms`);this.name="ProviderTimeoutError",this.timeoutMs=Q}}function P3(Q){let $=h9(Q);if($?.message)return $.message;if(typeof Q==="string")return Q.slice(0,500);return"no error body"}function h9(Q){if(!Q||typeof Q!=="object")return null;let $=Q,J=$.error&&typeof $.error==="object"?$.error:Q;if(typeof J.message!=="string"&&typeof J.code!=="string"&&typeof J.type!=="string")return null;let W=J.innererror?.code??J.code;return{message:J.message,type:J.type,code:W,param:J.param}}function T(Q){if(!Q||typeof Q!=="object")return{};let{status:$,requestId:Z}=Q;return{...typeof $==="number"&&$>=100&&$<=599?{status:$}:{},...typeof Z==="string"&&Z?{requestId:Z}:{}}}function _(Q){if(Q instanceof GQ)return{code:"provider_error",message:Q.message,retryable:!0};if(_3(Q))return{code:"aborted",message:"The request was aborted.",retryable:!1};if(Q instanceof I)return j3(Q.status,h9(Q.body),Q.message);if(Q instanceof TypeError)return{code:"provider_error",message:`Could not reach the provider: ${Q.message}`,retryable:!0};if(Q instanceof Error)return{code:"provider_error",message:Q.message,retryable:!1};return{code:"unknown",message:String(Q),retryable:!1}}function j3(Q,$,Z){let J=$?.message??Z,W=($?.code??"").toLowerCase(),X=($?.type??"").toLowerCase(),G=`${W} ${X} ${J}`.toLowerCase();if(Q===429){let Y=W==="insufficient_quota"||G.includes("quota");return{code:"rate_limited",message:J,retryable:!Y}}if(Q>=500||Q===408||Q===409)return{code:"provider_error",message:J,retryable:!0};if(O3(G))return{code:"context_length_exceeded",message:J,retryable:!1};if(N3(G))return{code:"content_filtered",message:J,retryable:!1};if($?.param?.startsWith("tools")||G.includes("invalid schema for function"))return{code:"invalid_tool_input",message:J,retryable:!1};return{code:"provider_error",message:J,retryable:!1}}function O3(Q){return Q.includes("context_length_exceeded")||Q.includes("maximum context length")||Q.includes("context window")||Q.includes("reduce the length")}function N3(Q){return Q.includes("content_filter")||Q.includes("content_policy_violation")||Q.includes("responsibleaipolicyviolation")||Q.includes("content management policy")}function _3(Q){if(!Q||typeof Q!=="object")return!1;let $=Q;return $.name==="AbortError"||$.code==="ABORT_ERR"}class q extends Error{constructor(){super("The run was stopped");this.name="RunAborted"}}function f(Q,$){if($.aborted)return Promise.reject(new q);return new Promise((Z,J)=>{let W=()=>J(new q);$.addEventListener("abort",W,{once:!0}),Q.then(Z,J).finally(()=>$.removeEventListener("abort",W))})}function v(){return{inputTokens:0,outputTokens:0,totalTokens:0}}function E(Q,$){if(!$)return Q;let Z={inputTokens:Q.inputTokens+($.inputTokens??0),outputTokens:Q.outputTokens+($.outputTokens??0),totalTokens:Q.totalTokens+($.totalTokens??0)};if($.reasoningTokens!==void 0||Q.reasoningTokens!==void 0)Z.reasoningTokens=(Q.reasoningTokens??0)+($.reasoningTokens??0);if($.cachedInputTokens!==void 0||Q.cachedInputTokens!==void 0)Z.cachedInputTokens=(Q.cachedInputTokens??0)+($.cachedInputTokens??0);if($.imageInputTokens!==void 0||Q.imageInputTokens!==void 0)Z.imageInputTokens=(Q.imageInputTokens??0)+($.imageInputTokens??0);if($.imageOutputTokens!==void 0||Q.imageOutputTokens!==void 0)Z.imageOutputTokens=(Q.imageOutputTokens??0)+($.imageOutputTokens??0);return Z}function VQ(Q){if(!Q.trim())return{};try{return JSON.parse(Q)}catch{}let $=[],Z=!1,J=!1;for(let G of Q){if(Z){if(J)J=!1;else if(G==="\\")J=!0;else if(G==='"')Z=!1;continue}if(G==='"')Z=!0;else if(G==="{")$.push("}");else if(G==="[")$.push("]");else if(G==="}"||G==="]")$.pop()}let W=Q;if(Z)W+='"';W=W.replace(/[,:]\s*$/,"");let X=$.reverse().join("");try{return JSON.parse(W+X)}catch{try{return JSON.parse(W.replace(/,?\s*"[^"]*"\s*$/,"")+X)}catch{return{}}}}function HQ(Q){return{name:"output",schema:Q.toJSONSchema(),strict:n(Q)}}function YQ(Q,$){let Z=Q.safeParse(VQ($));if(Z.ok===!0)return{ok:!0,value:Z.value};return{ok:!1,error:{code:"invalid_output",message:`The model's structured answer did not match the output schema: ${Z.errors.join(", ")}`,retryable:!0}}}function KQ(Q){if(Q.length>0)Q[0];return Q}function s(Q,$,Z){let J=Q.content[Q.content.length-1];if(J&&J.type===$){J.text=(J.text??"")+Z;return}Q.content.push($==="text"?{type:"text",text:Z}:{type:"reasoning",text:Z})}function zQ(Q,$,Z){let J=Q.content[Q.content.length-1];if(J&&J.type==="reasoning"&&J.id===$){J.text=(J.text??"")+Z;return}Q.content.push($?{type:"reasoning",id:$,text:Z}:{type:"reasoning",text:Z})}function q3(Q){return yQ(Q)}async function yQ(Q,$={}){let Z=`gen_${crypto.randomUUID()}`,J=await S3(Q);if($.settled?.(J),!J.ok){if(Q.logErrors!==!1&&J.error.code!=="aborted")M3(Z,J.error,$.origin);if(Q.throwOnError)throw new a({runId:Z,messages:J.messages,finishReason:J.finishReason,usage:J.usage,error:J.error})}return J}function M3(Q,$,Z){let J=`[gemi/ai] generate() failed (${$.code}${$.status!==void 0?` ${$.status}`:""}): ${$.message}`,W={...Z,generateId:Q,error:$},X=!1;try{t.error(J,W),X=!0}catch{}if(!X||Bun.env.NODE_ENV==="development")console.error(J,W)}async function S3(Q){let $=Q.messages??[];if($.length===0&&!Q.prompt)throw Error("generate() was given neither a `prompt` nor `messages`, so there is nothing to send the model.");let Z=[...$];if(Q.prompt)Z.push({id:`msg_${crypto.randomUUID()}`,role:"user",content:[{type:"text",text:Q.prompt}],createdAt:new Date().toISOString()});let J={id:`msg_${crypto.randomUUID()}`,role:"assistant",content:[],createdAt:new Date().toISOString()},W=Q.signal??new AbortController().signal,X=v(),G="stop",Y,V={},H="";try{let D=Q.provider.stream({messages:[...Z],systemPrompt:Q.instructions?.trim()?Q.instructions:void 0,output:HQ(Q.output),reasoning:Q.reasoning,maxOutputTokens:Q.maxOutputTokens,temperature:Q.temperature,signal:Q.signal})[Symbol.asyncIterator]();try{for(;;){let F=await f(Promise.resolve(D.next()),W);if(F.done)break;let U=F.value;switch(U.type){case"output-delta":H+=U.delta;break;case"text-delta":s(J,"text",U.delta);break;case"reasoning-delta":zQ(J,U.id,U.delta);break;case"finish":if(X=E(X,U.usage),!Y)G=U.reason;break;case"error":G="error",Y=U.error,V=T(U);break}}}finally{if(W.aborted)Promise.resolve(D.return?.()).catch(()=>{})}}catch(B){if(B instanceof q||W.aborted)G="aborted",Y=R3(W);else G="error",Y=Q.provider.normalizeError(B),V=T(B)}let K=!1,z;if(!Y)if(G==="length")Y={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(!H.trim())Y={code:"invalid_output",message:"The model finished without giving a structured answer.",retryable:!0};else{let B=YQ(Q.output,H);if(B.ok===!0)K=!0,z=B.value;else Y=B.error}if(K)J.content.push({type:"output",value:z});else if(H)s(J,"text",H);for(let B of J.content)if((B.type==="text"||B.type==="reasoning")&&typeof B.text==="string")B.text=KQ(B.text);if(J.finishReason=G,J.usage=X,Z.push(J),K)return{ok:!0,output:z,messages:Z,usage:X,finishReason:G};return{ok:!1,error:{...Y,...V},messages:Z,usage:X,finishReason:G}}function R3(Q){return Q.reason?.name==="TimeoutError"?{code:"timeout",message:"The generation timed out.",retryable:!0}:{code:"aborted",message:"The generation was stopped.",retryable:!1}}import{createHmac as k3,hkdfSync as T3,randomBytes as g9,timingSafeEqual as A3}from"crypto";class r{spent=new Map;sweepAt=1024;async consume(Q,$){return this.consumeSync(Q,$)}consumeSync(Q,$,Z=Date.now()){if(this.spent.size>=this.sweepAt)this.sweep(Z);let J=this.spent.get(Q);if(J!==void 0&&J>Z)return!1;return this.spent.set(Q,$),!0}get size(){return this.spent.size}sweep(Q){for(let[$,Z]of this.spent)if(Z<=Q)this.spent.delete($);this.sweepAt=Math.max(1024,this.spent.size*2)}}class uQ{injectedClient;prefix;constructor(Q={}){this.injectedClient=Q.client,this.prefix=Q.prefix??"gemi:ai:nonce"}async consume(Q,$){let Z=Math.max(1,Math.ceil($-Date.now()));return await this.client.send("SET",[`${this.prefix}:${Q}`,"1","PX",String(Z),"NX"])==="OK"}get client(){if(this.injectedClient)return this.injectedClient;let Q=y9(),$=Q.bound(gQ)?Q.make(gQ).client:void 0;if(!$)throw Error("RedisNonceStore could not reach the Redis client. Register RedisServiceProvider on your application, or pass a client: new RedisNonceStore({ client }).");return $}}var m=new r;var cQ="agt2",UQ="agt1",u9=[cQ,UQ],mQ=86400000,x3=Date.now()+mQ;function c9(Q){return Q<=x3}var m9="gemi.ai.pending-call.v1",p9="gemi.ai.nested-run.v1",E3="gemi.ai.signing",BQ=new Map;function FQ(Q,$){let Z=pQ($),J=`${Q}\x00${Z}`,W=BQ.get(J);if(!W){if(W=Buffer.from(T3("sha256",Z,E3,Q,32)),BQ.size>64)BQ.clear();BQ.set(J,W)}return W}function pQ(Q){let $=Q??process.env.SECRET;if(!$)throw Error("Signing a pending tool call needs an app secret. Set SECRET in the environment.");return $}function A(Q){if(Q===null||typeof Q!=="object")return JSON.stringify(Q)??"null";if(Array.isArray(Q))return`[${Q.map(A).join(",")}]`;let $=Q;return`{${Object.keys($).filter((J)=>$[J]!==void 0).sort().map((J)=>`${JSON.stringify(J)}:${A($[J])}`).join(",")}}`}function b3(Q){return Q.map(($)=>`${$.length}:${$}`).join("")}function p(Q,$){return k3("sha256",Q).update(b3($)).digest()}function d9(Q,$){let Z=Buffer.from(Q.split(".")[4],"base64url");return Z.length===$.length&&A3(Z,$)}function l9(Q){return A(Q??null)}function i9(Q,$,Z){return[cQ,Q.runId,Q.toolCallId,Q.name,Q.kind,$,String(Z),A(Q.input),A(Q.path??[]),l9(Q.subject)]}function w3(Q,$,Z){let J=[UQ,Q.runId,Q.toolCallId,Q.name,Q.kind,$,String(Z),A(Q.input)];if(Q.path&&Q.path.length>0)J.push(A(Q.path));return J}var o9=(Q)=>Buffer.from(Q,"utf8").toString("base64url"),I3=(Q)=>Buffer.from(Q,"base64url").toString("utf8");function n9(Q,$={}){let Z=FQ(m9,$.secret),W=($.now??Date.now())+($.ttlMs??mQ),X=g9(12).toString("base64url"),G=p(Z,i9(Q,X,W)).toString("base64url");return[cQ,o9(Q.runId),X,W.toString(36),G].join(".")}function dQ(Q){return CQ(Q,u9)}function CQ(Q,$){let Z=Q.split(".");if(Z.length!==5||!$.includes(Z[0]))return null;let J=Number.parseInt(Z[3],36);if(!Number.isFinite(J))return null;try{return{runId:I3(Z[1]),nonce:Z[2],expiresAt:J,version:Z[0]}}catch{return null}}function s9(Q,$,Z={}){let J=CQ(Q,u9);if(!J)return{ok:!1,reason:"malformed"};if(J.version===UQ&&!c9(J.expiresAt))return{ok:!1,reason:"forged"};let W=J.version===UQ?p(pQ(Z.secret),w3($,J.nonce,J.expiresAt)):p(FQ(m9,Z.secret),i9($,J.nonce,J.expiresAt));if(!d9(Q,W))return{ok:!1,reason:"forged"};if((Z.now??Date.now())>J.expiresAt)return{ok:!1,reason:"expired"};return{ok:!0,runId:J.runId,nonce:J.nonce,expiresAt:J.expiresAt}}var lQ="agn2",DQ="agn1",t9=[lQ,DQ];function a9(Q,$,Z){return[...r9(Q,$,Z,lQ),l9(Q.subject)]}function r9(Q,$,Z,J=DQ){return[J,Q.runId,A(Q.path),Q.nestedRunId,$,String(Z),A([...Q.open].sort()),A(Q.input)]}function e9(Q,$={}){let Z=FQ(p9,$.secret),W=($.now??Date.now())+($.ttlMs??mQ),X=g9(12).toString("base64url"),G=p(Z,a9(Q,X,W)).toString("base64url");return[lQ,o9(Q.runId),X,W.toString(36),G].join(".")}function Q$(Q,$,Z={}){let J=CQ(Q,t9);if(!J)return{ok:!1,reason:"malformed"};if(J.version===DQ&&!c9(J.expiresAt))return{ok:!1,reason:"forged"};let W={...$,runId:J.runId},X=J.version===DQ?p(pQ(Z.secret),r9(W,J.nonce,J.expiresAt)):p(FQ(p9,Z.secret),a9(W,J.nonce,J.expiresAt));if(!d9(Q,X))return{ok:!1,reason:"forged"};if((Z.now??Date.now())>J.expiresAt)return{ok:!1,reason:"expired"};return{ok:!0,runId:J.runId,nonce:J.nonce,expiresAt:J.expiresAt}}function $$(Q,$){return J$($,dQ(Q))}function Z$(Q,$){return J$($,CQ(Q,t9))}async function J$(Q,$){if(!$)return!1;return Q.consume($.nonce,$.expiresAt)}class e extends O{id;code="attachment_not_found";constructor(Q){super(`No attachment ${Q}.`);this.id=Q;this.name="AttachmentNotFoundError"}}class d extends O{code="invalid_attachment_scope";constructor(Q){super(Q);this.name="InvalidAttachmentScopeError"}}function iQ(Q){if(!Q||typeof Q.key!=="string"||Q.key.length===0)throw new d("An attachment scope needs a non-empty key. Return `null` from `attachmentScope()` for a request that has no subject \u2014 an empty key is a bucket every caller shares.");return Q}var x="gemi_att_";function oQ(){return`${x}${crypto.randomUUID()}`}class QQ{store;storage;scope;constructor(Q,$,Z){this.store=Q;this.storage=$;this.scope=Z;iQ(Z)}async get(Q){let $=await this.store.find(this.scope,Q);if(!$||$.scopeKey!==this.scope.key)throw new e(Q);return $}async read(Q){return await this.readRecord(Q,await this.get(Q))}async readRecord(Q,$){if(!$.objectName)throw new e(Q);return await this.storage.read({name:$.objectName})}async file(Q){let $=await this.get(Q),J=(await this.readRecord(Q,$)).body,W=J instanceof Blob?J:J?await new Response(J).blob():new Blob([]);return new File([W],$.name,{type:$.mimeType})}async put(Q,$={}){let Z=oQ(),J=$.mimeType??Q.type??"",W=$.name??(Q instanceof File?Q.name:Z),X=await this.storage.put({name:nQ(Z,W),body:Q,contentType:J||void 0}),G={id:Z,scopeKey:this.scope.key,objectName:X,name:W,mimeType:J||"application/octet-stream",size:Q.size,createdAt:new Date().toISOString(),destination:$.fileId?"both":"storage",...$.fileId?{fileId:$.fileId}:{}};return await this.store.put(this.scope,G),G}}function nQ(Q,$){let Z=/\.([A-Za-z0-9]{1,8})$/.exec($);return`attachments/${Q}${Z?`.${Z[1].toLowerCase()}`:""}`}class LQ{rows=new Map;async put(Q,$){iQ(Q),this.rows.set($.id,{...$,scopeKey:Q.key})}async find(Q,$){iQ(Q);let Z=this.rows.get($);if(!Z||Z.scopeKey!==Q.key)return null;return Z}get size(){return this.rows.size}}var PQ=new LQ;var sQ=new TextEncoder;function W$(Q){return`id: ${Q.seq}
|
|
2
|
+
import{Ab as y9,Bb as L$,Cb as j$,Db as B3,zb as S}from"../chunk-wc46df4w.js";import{Me as H3,Pe as K3,cf as F6,df as C6,ef as s,ff as GQ,tf as z3,vf as a,wf as uQ}from"../chunk-mym0zxxp.js";import{Af as yQ,xf as Y3,zf as hQ}from"../chunk-9xf2fx98.js";import{Ef as qQ}from"../chunk-eqtsfvvd.js";import{Hg as u9}from"../chunk-7hfv5n00.js";import"../chunk-qxda7pzm.js";import"../chunk-kzh8bkg5.js";import"../chunk-j2nx0dtq.js";class v extends Error{status;body;requestId;constructor(Q,$,Z){super(`Provider request failed with status ${Q}: ${N3($)}`);this.name="ProviderHttpError",this.status=Q,this.body=$,this.requestId=Z}}class HQ extends Error{timeoutMs;constructor(Q){super(`Provider request timed out after ${Q}ms`);this.name="ProviderTimeoutError",this.timeoutMs=Q}}function N3(Q){let $=g9(Q);if($?.message)return $.message;if(typeof Q==="string")return Q.slice(0,500);return"no error body"}function g9(Q){if(!Q||typeof Q!=="object")return null;let $=Q,J=$.error&&typeof $.error==="object"?$.error:Q;if(typeof J.message!=="string"&&typeof J.code!=="string"&&typeof J.type!=="string")return null;let W=J.innererror?.code??J.code;return{message:J.message,type:J.type,code:W,param:J.param}}function T(Q){if(!Q||typeof Q!=="object")return{};let{status:$,requestId:Z}=Q;return{...typeof $==="number"&&$>=100&&$<=599?{status:$}:{},...typeof Z==="string"&&Z?{requestId:Z}:{}}}function R(Q){if(Q instanceof HQ)return{code:"provider_error",message:Q.message,retryable:!0};if(S3(Q))return{code:"aborted",message:"The request was aborted.",retryable:!1};if(Q instanceof v)return _3(Q.status,g9(Q.body),Q.message);if(Q instanceof TypeError)return{code:"provider_error",message:`Could not reach the provider: ${Q.message}`,retryable:!0};if(Q instanceof Error)return{code:"provider_error",message:Q.message,retryable:!1};return{code:"unknown",message:String(Q),retryable:!1}}function _3(Q,$,Z){let J=$?.message??Z,W=($?.code??"").toLowerCase(),X=($?.type??"").toLowerCase(),G=`${W} ${X} ${J}`.toLowerCase();if(Q===429){let H=W==="insufficient_quota"||G.includes("quota");return{code:"rate_limited",message:J,retryable:!H}}if(Q>=500||Q===408||Q===409)return{code:"provider_error",message:J,retryable:!0};if(q3(G))return{code:"context_length_exceeded",message:J,retryable:!1};if(M3(G))return{code:"content_filtered",message:J,retryable:!1};if($?.param?.startsWith("tools")||G.includes("invalid schema for function"))return{code:"invalid_tool_input",message:J,retryable:!1};return{code:"provider_error",message:J,retryable:!1}}function q3(Q){return Q.includes("context_length_exceeded")||Q.includes("maximum context length")||Q.includes("context window")||Q.includes("reduce the length")}function M3(Q){return Q.includes("content_filter")||Q.includes("content_policy_violation")||Q.includes("responsibleaipolicyviolation")||Q.includes("content management policy")}function S3(Q){if(!Q||typeof Q!=="object")return!1;let $=Q;return $.name==="AbortError"||$.code==="ABORT_ERR"}class A extends Error{constructor(){super("The run was stopped");this.name="RunAborted"}}function f(Q,$){if($.aborted)return Promise.reject(new A);return new Promise((Z,J)=>{let W=()=>J(new A);$.addEventListener("abort",W,{once:!0}),Q.then(Z,J).finally(()=>$.removeEventListener("abort",W))})}function q(){return{inputTokens:0,outputTokens:0,totalTokens:0}}function M(Q,$){if(!$)return Q;let Z={inputTokens:Q.inputTokens+($.inputTokens??0),outputTokens:Q.outputTokens+($.outputTokens??0),totalTokens:Q.totalTokens+($.totalTokens??0)};if($.reasoningTokens!==void 0||Q.reasoningTokens!==void 0)Z.reasoningTokens=(Q.reasoningTokens??0)+($.reasoningTokens??0);if($.cachedInputTokens!==void 0||Q.cachedInputTokens!==void 0)Z.cachedInputTokens=(Q.cachedInputTokens??0)+($.cachedInputTokens??0);if($.imageInputTokens!==void 0||Q.imageInputTokens!==void 0)Z.imageInputTokens=(Q.imageInputTokens??0)+($.imageInputTokens??0);if($.imageOutputTokens!==void 0||Q.imageOutputTokens!==void 0)Z.imageOutputTokens=(Q.imageOutputTokens??0)+($.imageOutputTokens??0);return Z}function YQ(Q){if(!Q.trim())return{};try{return JSON.parse(Q)}catch{}let $=[],Z=!1,J=!1;for(let G of Q){if(Z){if(J)J=!1;else if(G==="\\")J=!0;else if(G==='"')Z=!1;continue}if(G==='"')Z=!0;else if(G==="{")$.push("}");else if(G==="[")$.push("]");else if(G==="}"||G==="]")$.pop()}let W=Q;if(Z)W+='"';W=W.replace(/[,:]\s*$/,"");let X=$.reverse().join("");try{return JSON.parse(W+X)}catch{try{return JSON.parse(W.replace(/,?\s*"[^"]*"\s*$/,"")+X)}catch{return{}}}}function KQ(Q){return{name:"output",schema:Q.toJSONSchema(),strict:s(Q)}}function zQ(Q,$){let Z=Q.safeParse(YQ($));if(Z.ok===!0)return{ok:!0,value:Z.value};return{ok:!1,error:{code:"invalid_output",message:`The model's structured answer did not match the output schema: ${Z.errors.join(", ")}`,retryable:!0}}}function BQ(Q){if(Q.length>0)Q[0];return Q}function t(Q,$,Z){let J=Q.content[Q.content.length-1];if(J&&J.type===$){J.text=(J.text??"")+Z;return}Q.content.push($==="text"?{type:"text",text:Z}:{type:"reasoning",text:Z})}function DQ(Q,$,Z){let J=Q.content[Q.content.length-1];if(J&&J.type==="reasoning"&&J.id===$){J.text=(J.text??"")+Z;return}Q.content.push($?{type:"reasoning",id:$,text:Z}:{type:"reasoning",text:Z})}function R3(Q){return gQ(Q)}async function gQ(Q,$={}){let Z=`gen_${crypto.randomUUID()}`,J=await T3(Q);if($.settled?.(J),!J.ok){if(Q.logErrors!==!1&&J.error.code!=="aborted")k3(Z,J.error,$.origin);if(Q.throwOnError)throw new r({runId:Z,messages:J.messages,finishReason:J.finishReason,usage:J.usage,error:J.error})}return J}function k3(Q,$,Z){let J=`[gemi/ai] generate() failed (${$.code}${$.status!==void 0?` ${$.status}`:""}): ${$.message}`,W={...Z,generateId:Q,error:$},X=!1;try{a.error(J,W),X=!0}catch{}if(!X||Bun.env.NODE_ENV==="development")console.error(J,W)}async function T3(Q){let $=Q.messages??[];if($.length===0&&!Q.prompt)throw Error("generate() was given neither a `prompt` nor `messages`, so there is nothing to send the model.");let Z=[...$];if(Q.prompt)Z.push({id:`msg_${crypto.randomUUID()}`,role:"user",content:[{type:"text",text:Q.prompt}],createdAt:new Date().toISOString()});let J={id:`msg_${crypto.randomUUID()}`,role:"assistant",content:[],createdAt:new Date().toISOString()},W=Q.signal??new AbortController().signal,X=q(),G="stop",H,V={},Y="";try{let U=Q.provider.stream({messages:[...Z],systemPrompt:Q.instructions?.trim()?Q.instructions:void 0,output:KQ(Q.output),reasoning:Q.reasoning,maxOutputTokens:Q.maxOutputTokens,temperature:Q.temperature,signal:Q.signal})[Symbol.asyncIterator]();try{for(;;){let F=await f(Promise.resolve(U.next()),W);if(F.done)break;let D=F.value;switch(D.type){case"output-delta":Y+=D.delta;break;case"text-delta":t(J,"text",D.delta);break;case"reasoning-delta":DQ(J,D.id,D.delta);break;case"finish":if(X=M(X,D.usage),!H)G=D.reason;break;case"error":G="error",H=D.error,V=T(D);break}}}finally{if(W.aborted)Promise.resolve(U.return?.()).catch(()=>{})}}catch(B){if(B instanceof A||W.aborted)G="aborted",H=A3(W);else G="error",H=Q.provider.normalizeError(B),V=T(B)}let K=!1,z;if(!H)if(G==="length")H={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(!Y.trim())H={code:"invalid_output",message:"The model finished without giving a structured answer.",retryable:!0};else{let B=zQ(Q.output,Y);if(B.ok===!0)K=!0,z=B.value;else H=B.error}if(K)J.content.push({type:"output",value:z});else if(Y)t(J,"text",Y);for(let B of J.content)if((B.type==="text"||B.type==="reasoning")&&typeof B.text==="string")B.text=BQ(B.text);if(J.finishReason=G,J.usage=X,Z.push(J),K)return{ok:!0,output:z,messages:Z,usage:X,finishReason:G};return{ok:!1,error:{...H,...V},messages:Z,usage:X,finishReason:G}}function A3(Q){return Q.reason?.name==="TimeoutError"?{code:"timeout",message:"The generation timed out.",retryable:!0}:{code:"aborted",message:"The generation was stopped.",retryable:!1}}import{createHmac as E3,hkdfSync as x3,randomBytes as c9,timingSafeEqual as w3}from"crypto";class e{spent=new Map;sweepAt=1024;async consume(Q,$){return this.consumeSync(Q,$)}consumeSync(Q,$,Z=Date.now()){if(this.spent.size>=this.sweepAt)this.sweep(Z);let J=this.spent.get(Q);if(J!==void 0&&J>Z)return!1;return this.spent.set(Q,$),!0}get size(){return this.spent.size}sweep(Q){for(let[$,Z]of this.spent)if(Z<=Q)this.spent.delete($);this.sweepAt=Math.max(1024,this.spent.size*2)}}class cQ{injectedClient;prefix;constructor(Q={}){this.injectedClient=Q.client,this.prefix=Q.prefix??"gemi:ai:nonce"}async consume(Q,$){let Z=Math.max(1,Math.ceil($-Date.now()));return await this.client.send("SET",[`${this.prefix}:${Q}`,"1","PX",String(Z),"NX"])==="OK"}get client(){if(this.injectedClient)return this.injectedClient;let Q=u9(),$=Q.bound(uQ)?Q.make(uQ).client:void 0;if(!$)throw Error("RedisNonceStore could not reach the Redis client. Register RedisServiceProvider on your application, or pass a client: new RedisNonceStore({ client }).");return $}}var p=new e;var pQ="agt2",FQ="agt1",p9=[pQ,FQ],mQ=86400000,b3=Date.now()+mQ;function m9(Q){return Q<=b3}var d9="gemi.ai.pending-call.v1",l9="gemi.ai.nested-run.v1",I3="gemi.ai.signing",UQ=new Map;function LQ(Q,$){let Z=dQ($),J=`${Q}\x00${Z}`,W=UQ.get(J);if(!W){if(W=Buffer.from(x3("sha256",Z,I3,Q,32)),UQ.size>64)UQ.clear();UQ.set(J,W)}return W}function dQ(Q){let $=Q??process.env.SECRET;if(!$)throw Error("Signing a pending tool call needs an app secret. Set SECRET in the environment.");return $}function b(Q){if(Q===null||typeof Q!=="object")return JSON.stringify(Q)??"null";if(Array.isArray(Q))return`[${Q.map(b).join(",")}]`;let $=Q;return`{${Object.keys($).filter((J)=>$[J]!==void 0).sort().map((J)=>`${JSON.stringify(J)}:${b($[J])}`).join(",")}}`}function v3(Q){return Q.map(($)=>`${$.length}:${$}`).join("")}function m(Q,$){return E3("sha256",Q).update(v3($)).digest()}function i9(Q,$){let Z=Buffer.from(Q.split(".")[4],"base64url");return Z.length===$.length&&w3(Z,$)}function o9(Q){return b(Q??null)}function n9(Q,$,Z){return[pQ,Q.runId,Q.toolCallId,Q.name,Q.kind,$,String(Z),b(Q.input),b(Q.path??[]),o9(Q.subject)]}function f3(Q,$,Z){let J=[FQ,Q.runId,Q.toolCallId,Q.name,Q.kind,$,String(Z),b(Q.input)];if(Q.path&&Q.path.length>0)J.push(b(Q.path));return J}var s9=(Q)=>Buffer.from(Q,"utf8").toString("base64url"),h3=(Q)=>Buffer.from(Q,"base64url").toString("utf8");function t9(Q,$={}){let Z=LQ(d9,$.secret),W=($.now??Date.now())+($.ttlMs??mQ),X=c9(12).toString("base64url"),G=m(Z,n9(Q,X,W)).toString("base64url");return[pQ,s9(Q.runId),X,W.toString(36),G].join(".")}function lQ(Q){return jQ(Q,p9)}function jQ(Q,$){let Z=Q.split(".");if(Z.length!==5||!$.includes(Z[0]))return null;let J=Number.parseInt(Z[3],36);if(!Number.isFinite(J))return null;try{return{runId:h3(Z[1]),nonce:Z[2],expiresAt:J,version:Z[0]}}catch{return null}}function a9(Q,$,Z={}){let J=jQ(Q,p9);if(!J)return{ok:!1,reason:"malformed"};if(J.version===FQ&&!m9(J.expiresAt))return{ok:!1,reason:"forged"};let W=J.version===FQ?m(dQ(Z.secret),f3($,J.nonce,J.expiresAt)):m(LQ(d9,Z.secret),n9($,J.nonce,J.expiresAt));if(!i9(Q,W))return{ok:!1,reason:"forged"};if((Z.now??Date.now())>J.expiresAt)return{ok:!1,reason:"expired"};return{ok:!0,runId:J.runId,nonce:J.nonce,expiresAt:J.expiresAt}}var iQ="agn2",CQ="agn1",r9=[iQ,CQ];function e9(Q,$,Z){return[...Q$(Q,$,Z,iQ),o9(Q.subject)]}function Q$(Q,$,Z,J=CQ){return[J,Q.runId,b(Q.path),Q.nestedRunId,$,String(Z),b([...Q.open].sort()),b(Q.input)]}function $$(Q,$={}){let Z=LQ(l9,$.secret),W=($.now??Date.now())+($.ttlMs??mQ),X=c9(12).toString("base64url"),G=m(Z,e9(Q,X,W)).toString("base64url");return[iQ,s9(Q.runId),X,W.toString(36),G].join(".")}function Z$(Q,$,Z={}){let J=jQ(Q,r9);if(!J)return{ok:!1,reason:"malformed"};if(J.version===CQ&&!m9(J.expiresAt))return{ok:!1,reason:"forged"};let W={...$,runId:J.runId},X=J.version===CQ?m(dQ(Z.secret),Q$(W,J.nonce,J.expiresAt)):m(LQ(l9,Z.secret),e9(W,J.nonce,J.expiresAt));if(!i9(Q,X))return{ok:!1,reason:"forged"};if((Z.now??Date.now())>J.expiresAt)return{ok:!1,reason:"expired"};return{ok:!0,runId:J.runId,nonce:J.nonce,expiresAt:J.expiresAt}}function J$(Q,$){return X$($,lQ(Q))}function W$(Q,$){return X$($,jQ(Q,r9))}async function X$(Q,$){if(!$)return!1;return Q.consume($.nonce,$.expiresAt)}class QQ extends S{id;code="attachment_not_found";constructor(Q){super(`No attachment ${Q}.`);this.id=Q;this.name="AttachmentNotFoundError"}}class d extends S{code="invalid_attachment_scope";constructor(Q){super(Q);this.name="InvalidAttachmentScopeError"}}function oQ(Q){if(!Q||typeof Q.key!=="string"||Q.key.length===0)throw new d("An attachment scope needs a non-empty key. Return `null` from `attachmentScope()` for a request that has no subject \u2014 an empty key is a bucket every caller shares.");return Q}var I="gemi_att_";function nQ(){return`${I}${crypto.randomUUID()}`}class $Q{store;storage;scope;constructor(Q,$,Z){this.store=Q;this.storage=$;this.scope=Z;oQ(Z)}async get(Q){let $=await this.store.find(this.scope,Q);if(!$||$.scopeKey!==this.scope.key)throw new QQ(Q);return $}async read(Q){return await this.readRecord(Q,await this.get(Q))}async readRecord(Q,$){if(!$.objectName)throw new QQ(Q);return await this.storage.read({name:$.objectName})}async file(Q){let $=await this.get(Q),J=(await this.readRecord(Q,$)).body,W=J instanceof Blob?J:J?await new Response(J).blob():new Blob([]);return new File([W],$.name,{type:$.mimeType})}async put(Q,$={}){let Z=nQ(),J=$.mimeType??Q.type??"",W=$.name??(Q instanceof File?Q.name:Z),X=await this.storage.put({name:sQ(Z,W),body:Q,contentType:J||void 0}),G={id:Z,scopeKey:this.scope.key,objectName:X,name:W,mimeType:J||"application/octet-stream",size:Q.size,createdAt:new Date().toISOString(),destination:$.fileId?"both":"storage",...$.fileId?{fileId:$.fileId}:{}};return await this.store.put(this.scope,G),G}}function sQ(Q,$){let Z=/\.([A-Za-z0-9]{1,8})$/.exec($);return`attachments/${Q}${Z?`.${Z[1].toLowerCase()}`:""}`}class PQ{rows=new Map;async put(Q,$){oQ(Q),this.rows.set($.id,{...$,scopeKey:Q.key})}async find(Q,$){oQ(Q);let Z=this.rows.get($);if(!Z||Z.scopeKey!==Q.key)return null;return Z}get size(){return this.rows.size}}var OQ=new PQ;var tQ=new TextEncoder;function G$(Q){return`id: ${Q.seq}
|
|
3
3
|
data: ${JSON.stringify(Q.event)}
|
|
4
4
|
|
|
5
|
-
`}var
|
|
5
|
+
`}var y3=5000,g3=`: keepalive
|
|
6
6
|
|
|
7
|
-
`;function
|
|
8
|
-
${await
|
|
7
|
+
`;function aQ(Q,$=y3){let Z=null,J=!1,W=()=>{if(J)return;if(Z!==null)clearTimeout(Z);Z=setTimeout(()=>{if(Z=null,J)return;try{Q.enqueue(tQ.encode(g3))}catch{X();return}W()},$)},X=()=>{if(J=!0,Z!==null)clearTimeout(Z);Z=null};return W(),{touch:W,stop:X}}function u3(){return{"Content-Type":"text/event-stream","Cache-Control":"no-store, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}}function V$(Q,$=200){let Z=Q[Symbol.asyncIterator](),J=-1,W,X=new ReadableStream({start(G){W=aQ(G)},async pull(G){try{let H=await Z.next();if(H.done){W.stop(),G.close();return}J=H.value.seq,G.enqueue(tQ.encode(G$(H.value))),W.touch()}catch(H){let V={type:"error",error:p3(H)};W.stop(),G.enqueue(tQ.encode(G$({seq:J+1,event:V}))),G.close()}},cancel(G){W.stop(),Z.return?.(G)}});return new Response(X,{status:$,headers:u3()})}var c3=new Set(["frame_cursor_evicted","live_run_not_found"]);function p3(Q){let $=Q&&typeof Q==="object"?Q.code:void 0;if(Q instanceof Error&&typeof $==="string"&&c3.has($))return{code:"unknown",message:Q.message,retryable:!1};return console.error("[gemi/ai] agent stream failed",Q),{code:"unknown",message:"The run's stream failed.",retryable:!1}}class h extends Error{pending;path;nested;constructor(Q){super(`A nested agent run is waiting on the user for ${Q.pending.length} tool call(s).`);this.name="PendingEscalation",this.pending=Q.pending,this.path=Q.path,this.nested=Q.nested}}class y{name;description;inputSchema;outputSchema;requiresApproval;deferred;answeredBy;timeoutMs;execute;constructor(Q){this.name=Q.name,this.description=Q.description,this.inputSchema=Q.inputSchema,this.outputSchema=Q.outputSchema,this.requiresApproval=Q.requiresApproval===!0,this.deferred=Q.deferred===!0,this.answeredBy=Q.answeredBy==="client"?"client":"server",this.execute=Q.execute??void 0,this.timeoutMs=Q.timeoutMs}static create(Q){if(typeof Q.inputSchema!=="function")X9(Q.inputSchema,`The tool "${Q.name}"`,"inputSchema");if(Q.timeoutMs!==void 0)Q9(Q.timeoutMs,`The tool "${Q.name}"`,"timeoutMs");return new y(Q)}static ask(Q){return y.create({name:Q.name,description:Q.description,inputSchema:J9,outputSchema:Q.outputSchema,answeredBy:"client"})}}var J9={toJSONSchema:()=>({type:"object",properties:{question:{type:"string",description:"What to ask the user"}},required:["question"],additionalProperties:!1}),parse(Q){let $=J9.safeParse(Q);if($.ok===!1)throw Error($.errors.join(", "));return $.value},safeParse(Q){if(typeof Q!=="object"||Q===null||typeof Q.question!=="string")return{ok:!1,errors:["question: expected a string"]};return{ok:!0,value:{question:Q.question}}}};class MQ{name;description;tools;deferred;constructor(Q){this.name=Q.name,this.description=Q.description,this.tools=Q.tools,this.deferred=Q.deferred===!0}static create(Q){return new MQ(Q)}}class W9{name;description;instructions;files;constructor(Q){this.name=Q.name,this.description=Q.description,this.instructions=Q.instructions,this.files=Q.files}static create(Q){return new W9(Q)}}var ZQ="skills",m3="Instructions this agent can load on demand. Load the relevant one before acting in the area it covers.";function X9(Q,$,Z){let J=Q?.toJSONSchema?.();if(J?.type==="object")return;let W=!J?"no JSON Schema":J.anyOf?"a union (`anyOf`) \u2014 `s.union(...)`":J.type!==void 0?`a schema of type ${JSON.stringify(J.type)}`:"an unconstrained schema (`s.json()`)";throw Error(`${$} declares an \`${Z}\` whose root is ${W}, 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 Q9(Q,$,Z){if(typeof Q==="number"&&Q>0)return;throw Error(`${$} sets \`${Z}\` to ${String(Q)}, but it has to be a positive number of milliseconds. Use \`null\` for no limit.`)}function H$(Q){if(Q===void 0)return;if(Q===null||!Number.isFinite(Q))return null;return Q}var d3=2147483647;function Y$(Q,$){if(Q===null||Q>d3)return()=>{};let Z=setTimeout($,Q);return()=>clearTimeout(Z)}function rQ(Q){if(Q<1000)return`${Q}ms`;if(Q<60000)return`${+(Q/1000).toFixed(1)}s`;return`${+(Q/60000).toFixed(1)}m`}var G9={type:"object",properties:{},required:[],additionalProperties:!1},V9=600000;class r extends Error{code;retryable;status;requestId;toolCallId;runId;result;constructor(Q){super(Q.error.message);this.name="AgentRunError",this.code=Q.error.code,this.retryable=Q.error.retryable,this.status=Q.error.status,this.requestId=Q.error.requestId,this.toolCallId=Q.error.toolCallId,this.runId=Q.runId,this.result=Q}}var l3=8,i3=3;class H9{name;tools;skills;provider;output;instructions;maxSteps;maxDepth;reasoning;maxRunDurationMs;config;constructor(Q){this.name=Q.name,this.instructions=Q.instructions,this.provider=Q.provider,this.tools=Q.tools??[],this.skills=Q.skills??[],this.output=Q.output,this.maxSteps=Q.maxSteps??l3,this.maxDepth=Q.maxDepth??i3,this.reasoning=Q.reasoning;let $=H$(Q.maxRunDurationMs);this.maxRunDurationMs=$===void 0?V9:$;let{registry:Z,providerTools:J}=o3(this.tools,this.skills);this.config={name:this.name,instructions:this.instructions,provider:this.provider,registry:Z,providerTools:J,output:Q.output,maxSteps:this.maxSteps,maxDepth:this.maxDepth,reasoning:this.reasoning,maxOutputTokens:Q.maxOutputTokens,temperature:Q.temperature,logErrors:Q.logErrors??!0,maxRunDurationMs:$}}static create(Q){if(Q.output)X9(Q.output,`The agent "${Q.name}"`,"output");if(Q.maxRunDurationMs!=null)Q9(Q.maxRunDurationMs,`The agent "${Q.name}"`,"maxRunDurationMs");return new H9(Q)}stream(Q){let $={...this.config,provider:Q.provider??this.config.provider,maxSteps:Q.maxSteps??this.config.maxSteps,reasoning:Q.reasoning??this.config.reasoning,maxOutputTokens:Q.maxOutputTokens??this.config.maxOutputTokens,temperature:Q.temperature??this.config.temperature,maxRunDurationMs:Q.maxRunDurationMs!==void 0?H$(Q.maxRunDurationMs):this.config.maxRunDurationMs};if(Q.maxRunDurationMs!=null)Q9(Q.maxRunDurationMs,`Agent.stream for "${this.name}"`,"maxRunDurationMs");return new O$($,Q)}}function $9(Q){let $=Q.inputSchema;return{name:Q.tool.name,description:Q.tool.description,parameters:$?$.toJSONSchema():G9,strict:$?s($):!0,deferred:Q.deferred}}function eQ(Q){return typeof Q.inputSchema==="function"?void 0:Q.inputSchema}function o3(Q,$){let Z=new Map,J=[],W=(X)=>{if(Z.has(X.tool.name))throw Error(`Two tools are named "${X.tool.name}". Tool names are global within an agent \u2014 the client discriminates a tool part by name alone.`);Z.set(X.tool.name,X)};for(let X of Q){if(X instanceof MQ){if(X.name===ZQ)throw Error(`"${ZQ}" 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.`);let H=[];for(let V of X.tools){let Y={tool:V,namespace:X.name,deferred:X.deferred||V.deferred,inputSchema:eQ(V)};W(Y),H.push($9(Y))}J.push({name:X.name,description:X.description,tools:H});continue}let G={tool:X,deferred:X.deferred,inputSchema:eQ(X)};W(G),J.push($9(G))}if($.length>0){let X=[];for(let G of $){let H=n3(G);W({tool:H,namespace:ZQ,deferred:!1,inputSchema:eQ(H)}),X.push({name:G.name,description:G.description,parameters:G9,strict:!0,deferred:!1})}J.push({name:ZQ,description:m3,tools:X})}return{registry:Z,providerTools:J}}function n3(Q){return y.create({name:Q.name,description:Q.description,inputSchema:{toJSONSchema:()=>G9,parse:()=>({}),safeParse:()=>({ok:!0,value:{}})},execute:async()=>{let Z=[typeof Q.instructions==="function"?await Q.instructions():Q.instructions];for(let J of Q.files??[])Z.push(`--- ${J} ---
|
|
8
|
+
${await s3(J)}`);return Z.join(`
|
|
9
9
|
|
|
10
|
-
`)}})}async function
|
|
11
|
-
data: ${JSON.stringify(
|
|
10
|
+
`)}})}async function s3(Q){try{return await Bun.file(Q).text()}catch($){return`(could not be read: ${$.message})`}}function t3(Q){return typeof Q==="object"&&Q!==null&&typeof Q.next==="function"&&Symbol.asyncIterator in Q}function K$(Q,$){let Z=[...Q],J=new Map(Z.map((W,X)=>[W.id,X]));for(let W of $){let X=J.get(W.id);if(X===void 0)J.set(W.id,Z.length),Z.push(W);else Z[X]=W}return Z}function NQ(Q){let $=new Set;for(let J of Q)for(let W of J.content)if(W.type==="tool-result")$.add(W.toolCallId);let Z=new Set;for(let J of Q)for(let W of J.content)if(W.type==="tool-call"&&!$.has(W.toolCallId))Z.add(W.toolCallId);return Z}function z$(Q){for(let $=Q.length-1;$>=0;$--){let Z=Q[$].content;for(let J=Z.length-1;J>=0;J--){let W=Z[J];if(W.type==="output"&&W.partial!==!0)return W.value}}return}function B$(Q,$){return $===void 0?`"${Q}"`:`"${Q}" labelled "${$}"`}function P$(Q){return Q.content.map(($)=>$.type==="text"?$.text:`<${$.type}>`).join("")}function a3(Q){if(Q.prompt!==void 0)return`user:${Q.prompt}`;let $=Q.messages?.[0];return $?`${$.role}:${P$($)}`:null}function _Q(Q){let $=new Set;for(let Z of Q)for(let J of Z.content){if(J.type!=="tool-call")continue;for(let W of J.attachments??[])if("shown"in W&&W.shown)$.add(W.shown.messageId)}return $}var D$=1;function r3(Q,$,Z){let J=Z.mimeType||$.type||"";if(J&&Q.attachment.mimeType!==J)return`was ${JSON.stringify(Q.attachment.mimeType)} on the turn that escalated and is ${JSON.stringify(J)} on the replay`;let W=Boolean(Z.showModel);if(W!==Boolean(Q.shown))return W?"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 e3(Q,$,Z){if(Q.agent!==$.name||Q.label!==Z.label)return`was ${B$(Q.agent,Q.label)} on the turn that escalated and is ${B$($.name,Z.label)} on the replay`;let J=a3(Z),W=Q.messages[0],X=W?`${W.role}:${P$(W)}`:null;if(J!==null&&X!==null&&J!==X)return`was started with ${JSON.stringify(X)} on the turn that escalated and with ${JSON.stringify(J)} on the replay`;return null}function U$(Q,$){let Z=Q??[];if(Z.length<$.length)return null;for(let J=0;J<$.length;J++)if(Z[J]!==$[J])return null;return Z.slice($.length)}class Z9{read;create;fill;index=0;replayable;constructor(Q,$,Z){this.read=Q;this.create=$;this.fill=Z;this.replayable=Q()?.length??0}next(){let Q=this.index++;return{at:Q,recorded:Q<this.replayable?this.read()?.[Q]:void 0,write:($)=>{let Z=this.read()??this.create();if(this.fill)for(let J=Z.length;J<Q;J++)Z[J]=this.fill();Z[Q]=$}}}}class O${runId;config;params;context;controller=new AbortController;buffer=[];waiters=new Set;seq=0;ended=!1;history=[];produced=[];current=null;outputTruncated=!1;amended=new Map;unreported=new Set;usage=q();finishReason="stop";failure;output;stopReason;timedOutAfter;cancelDeadline=()=>{};settled;depth;maxDepth;chain;signingRunId;pathPrefix;onPending;nestedSettling=new Set;shownQueue=new Map;constructor(Q,$){this.config=Q,this.params=$,this.context=$.context??{},this.runId=$.runId??`run_${crypto.randomUUID()}`,this.history=[...$.messages];let Z=$.nesting;if(this.depth=Z?.depth??0,this.maxDepth=Z?.maxDepth??Q.maxDepth,this.chain=Z?.chain??[Q.name],this.signingRunId=Z?.signingRunId??this.runId,this.pathPrefix=Z?.signingPath??[],this.onPending=Z?.onPending??"escalate",$.signal)if($.signal.aborted)this.controller.abort();else $.signal.addEventListener("abort",()=>this.stop(),{once:!0});let J=Q.maxRunDurationMs!==void 0?Q.maxRunDurationMs:Z?null:V9;this.cancelDeadline=Y$(J,()=>this.expire(J)),this.settled=this.execute(),qQ.getStore()?.waitUntil(this.settled)}emit(Q){if(this.ended)return;this.buffer.push({seq:++this.seq,event:Q}),this.wake()}wake(){let Q=[...this.waiters];this.waiters.clear();for(let $ of Q)$()}nextFrame(){return new Promise((Q)=>this.waiters.add(Q))}async*frames(Q=0){let $=Q>0?Q-1:0;for(;;){while($<this.buffer.length)yield this.buffer[$++];if(this.ended)return;await this.nextFrame()}}async*[Symbol.asyncIterator](){for await(let Q of this.frames())yield Q.event}toResponse(Q){let $=this.frames(Q?.from),Z=new TextEncoder,J=!1,W,X=new ReadableStream({start:async(G)=>{W=aQ(G);try{for await(let H of $){if(J)break;G.enqueue(Z.encode(`id: ${H.seq}
|
|
11
|
+
data: ${JSON.stringify(H.event)}
|
|
12
12
|
|
|
13
|
-
`)),W.touch()}}catch{}W.stop();try{G.close()}catch{}},cancel:()=>{J=!0,W.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(Q){if(!Q?.throwOnError)return this.settled;return this.settled.then(($)=>{if($.error)throw new
|
|
13
|
+
`)),W.touch()}}catch{}W.stop();try{G.close()}catch{}},cancel:()=>{J=!0,W.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(Q){if(!Q?.throwOnError)return this.settled;return this.settled.then(($)=>{if($.error)throw new r({...$,error:$.error});return $})}stop(Q){if(this.ended||this.controller.signal.aborted)return;this.stopReason=Q?.reason,this.controller.abort()}expire(Q){if(this.ended||this.controller.signal.aborted)return;this.timedOutAfter=Q,this.stopReason=`The run reached its time limit of ${rQ(Q)} 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{let $=await this.resolveToolSchemas(),Z=$?[]:await this.ingestTurn();if($)this.fail($),this.finishReason="error";else if(Z.length>0)this.finishReason="awaiting-input",this.emit({type:"awaiting-input",runId:this.runId,pending:Z});else await this.loop()}catch($){if($ instanceof A||this.controller.signal.aborted)await this.finalizeAborted();else this.fail(this.config.provider.normalizeError($),T($)),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();let Q=this.finishReason==="error"?this.failure:void 0;if(Q&&this.config.logErrors)this.logFailure(Q);return{runId:this.runId,messages:this.produced,finishReason:this.finishReason,usage:this.usage,output:this.output,...Q?{error:Q}:{}}}async resolveToolSchemas(){let Q=[...this.config.registry.values()].filter((V)=>!V.inputSchema);if(Q.length===0)return;let $={context:this.context,body:this.params.body??{},runId:this.runId,threadId:this.params.threadId,signal:this.controller.signal},Z=new Map,J=await Promise.all(Q.map(async(V)=>{try{let Y=V.tool.inputSchema,K=await Y($);X9(K,`The tool "${V.tool.name}"`,"inputSchema"),Z.set(V.tool.name,K);return}catch(Y){return`"${V.tool.name}": ${Y instanceof Error?Y.message:String(Y)}`}}));if(this.controller.signal.aborted)throw new A;let W=J.filter((V)=>V!==void 0);if(W.length>0)return{code:"tool_error",message:`Could not resolve the input schema of ${W.join("; ")}`,retryable:!1};let X=new Map;for(let[V,Y]of this.config.registry)X.set(V,Z.has(V)?{...Y,inputSchema:Z.get(V)}:Y);let G=(V)=>Z.has(V.name)?$9(X.get(V.name)):V,H=this.config.providerTools.map((V)=>("tools"in V)?{...V,tools:V.tools.map(G)}:G(V));this.config={...this.config,registry:X,providerTools:H};return}fail(Q,$={}){let Z={...Q,...$};this.failure=Z,this.emit({type:"error",error:this.redact(Z,{source:"run",failure:Z})})}redact(Q,$){let Z=L$(this.params.redactError,Q,$,(J)=>this.writeLog(`[gemi/ai] agent "${this.config.name}" redactError threw`,{error:J}));return j$(Z,Q),Z}logFailure(Q){let $=`[gemi/ai] agent "${this.config.name}" run failed (${Q.code}${Q.status!==void 0?` ${Q.status}`:""}): ${Q.message}`;this.writeLog($,{error:Q})}logToolFailure(Q,$){let Z=$ instanceof Error?$.message:String($);this.writeLog(`[gemi/ai] agent "${this.config.name}" tool "${String(Q.name)}" threw: ${Z}`,{toolCallId:Q.toolCallId,error:$})}writeLog(Q,$){let Z={agent:this.config.name,runId:this.runId,...this.params.threadId?{threadId:this.params.threadId}:{},...this.depth>0?{chain:this.chain}:{},...$},J=!1;try{a.error(Q,Z),J=!0}catch{}if(!J||Bun.env.NODE_ENV==="development")console.error(Q,Z)}async loop(){let Q=Math.max(1,this.config.maxSteps);for(let $=1;$<=Q;$++){let Z=this.startMessage(),J=await this.runStep(Z);if(J.error){this.fail(J.error,J.detail),await this.finalizeMessage("error"),this.finishReason="error";return}let W=Z.content.filter((G)=>G.type==="tool-call");if(W.length===0){this.finishReason=J.reason,await this.finalizeMessage(J.reason);return}let X=await this.runTools(Z,W,$);if(X.length>0){this.finishReason="awaiting-input",await this.finalizeMessage("awaiting-input"),this.emit({type:"awaiting-input",runId:this.runId,pending:X});return}if($===Q){this.finishReason="max-steps",await this.finalizeMessage("max-steps");return}await this.finalizeMessage(J.reason)}}startMessage(){let Q={id:`msg_${crypto.randomUUID()}`,role:"assistant",content:[],createdAt:new Date().toISOString()};return this.current=Q,this.history.push(Q),this.produced.push(Q),this.emit({type:"message-start",messageId:Q.id,role:"assistant"}),Q}async finalizeMessage(Q){let $=this.current;if(!$)return;this.current=null;let Z=this.outputTruncated;if(this.outputTruncated=!1,$.finishReason=Q,Z)$.outputTruncated=!0;for(let J of $.content)if(J.type==="text"||J.type==="reasoning"){if(typeof J.text==="string")J.text=BQ(J.text)}this.emit({type:"message-end",messageId:$.id,finishReason:Q,...Z?{outputTruncated:!0}:{},...$.usage?{usage:$.usage}:{}}),await this.report($),await this.reportDeferred()}async report(Q){if(!this.params.onMessage)return;try{await this.params.onMessage(Q)}catch{}}async runStep(Q){let $=this.controller.signal,Z=this.config.provider,J={reason:"stop"},W=new Map,X="",H=Z.stream({messages:this.historyForProvider(Q),systemPrompt:await this.systemPrompt(),tools:this.config.providerTools.length>0?this.config.providerTools:void 0,output:this.config.output?KQ(this.config.output):void 0,reasoning:this.config.reasoning,maxOutputTokens:this.config.maxOutputTokens,temperature:this.config.temperature,signal:$})[Symbol.asyncIterator]();for(;;){let Y=await f(Promise.resolve(H.next()),$);if(Y.done)break;let K=Y.value;switch(K.type){case"text-delta":{t(Q,"text",K.delta),this.emit({type:"text-delta",messageId:Q.id,delta:K.delta});break}case"reasoning-delta":{DQ(Q,K.id,K.delta),this.emit({type:"reasoning-delta",messageId:Q.id,delta:K.delta,id:K.id});break}case"output-delta":{X+=K.delta,this.emit({type:"output-delta",messageId:Q.id,delta:K.delta,snapshot:YQ(X)});break}case"tool-search":{this.emit({type:"tool-search",loaded:K.loaded});break}case"tool-call-delta":{let z=W.get(K.toolCallId)??{name:K.name,args:""};z.args+=K.argsDelta,z.name=K.name||z.name,W.set(K.toolCallId,z),this.emit({type:"tool-call",messageId:Q.id,part:{type:"tool-call",toolCallId:K.toolCallId,name:z.name,input:YQ(z.args),partial:!0}});break}case"tool-call":{W.delete(K.toolCallId);let z={type:"tool-call",toolCallId:K.toolCallId,name:K.name,input:C$(K.args)};Q.content.push(z),this.emit({type:"tool-call",messageId:Q.id,part:z});break}case"finish":{if(this.usage=M(this.usage,K.usage),Q.usage=M(Q.usage??q(),K.usage),!J.error)J={reason:K.reason};break}case"error":{J={reason:"error",error:K.error,detail:T(K)};break}case"file-rejected":{this.markFileRejected(K.fileId,K.message,T(K));break}}}for(let[Y,K]of W){let z={type:"tool-call",toolCallId:Y,name:K.name,input:C$(K.args)};Q.content.push(z),this.emit({type:"tool-call",messageId:Q.id,part:z})}let V=J.reason==="length";if(V)this.outputTruncated=!0;if(this.config.output&&X&&!J.error&&!V){let Y=zQ(this.config.output,X);if(Y.ok===!0)this.output=Y.value,Q.content.push({type:"output",value:Y.value});else this.emit({type:"error",error:Y.error})}return J}async systemPrompt(){let Q=[this.config.instructions,this.params.instructions].filter(($)=>Boolean($&&$.trim()));return Q.length>0?Q.join(`
|
|
14
14
|
|
|
15
|
-
`):void 0}async runTools(Q,$,Z){let J=[],W=[];for(let X of $){let G=this.config.registry.get(String(X.name));if(!G){this.addResult(Q,{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 Y=G.inputSchema.safeParse(X.input);if(Y.ok===!1){this.addResult(Q,{type:"tool-result",toolCallId:X.toolCallId,name:X.name,status:"error",error:{code:"invalid_tool_input",message:`Invalid arguments for "${String(X.name)}": ${Y.errors.join(", ")}`,toolCallId:X.toolCallId,retryable:!0}});continue}X.input=Y.value;let V=U$(G.tool);if(V){if(this.onPending==="deny"){this.addResult(Q,this.deniedByPolicy(X));continue}J.push({toolCallId:X.toolCallId,name:X.name,input:Y.value,kind:V,signature:n9(this.claimsFor(X.toolCallId,String(X.name),V,Y.value)),...this.pathPrefix.length>0?{path:[...this.pathPrefix]}:{}});continue}W.push(this.executeTool(G,Q.id,X,Y.value,Z).then(async(H)=>{this.addResult(Q,H),await this.settleShown(X.toolCallId)}).catch((H)=>{if(H instanceof h){if(this.onPending==="deny"){this.addResult(Q,this.deniedByPolicy(X));return}J.push(...H.pending);return}}))}return await f(Promise.all(W).then(()=>{return}),this.controller.signal),J}claimsFor(Q,$,Z,J){return{runId:this.signingRunId,toolCallId:Q,name:$,kind:Z,input:J,path:this.pathPrefix.length>0?[...this.pathPrefix]:void 0,subject:this.params.subject??null}}deniedByPolicy(Q){return{type:"tool-result",toolCallId:Q.toolCallId,name:Q.name,status:"denied",cause:"refused",reason:`"${String(Q.name)}" needs the user, and this run was started with onPending: "deny". Answer from what you already have.`}}async executeTool(Q,$,Z,J,W,X){let G=Q.tool.timeoutMs;if(G===void 0)return this.runToolBody(Q,$,Z,J,W,X,this.controller.signal,()=>!1);let Y=new AbortController,V=this.controller.signal,H=()=>Y.abort(V.reason);if(V.aborted)H();else V.addEventListener("abort",H,{once:!0});let K=!1,z=this.runToolBody(Q,$,Z,J,W,X,Y.signal,()=>K),B=()=>{},D=new Promise((F)=>{B=V$(G,()=>{let U=`"${String(Z.name)}" did not finish within ${aQ(G)} (timeoutMs: ${G}) and was cancelled.`;Y.abort(new DOMException(U,"TimeoutError")),F({type:"tool-result",toolCallId:Z.toolCallId,name:Z.name,status:"error",error:{code:"timeout",message:U,toolCallId:Z.toolCallId,retryable:!0}})})});z.catch(()=>{});try{return await Promise.race([z,D])}finally{K=!0,B()}}async runToolBody(Q,$,Z,J,W,X,G,Y){let V=this.toolFiles(Z,G),H={context:this.context,body:this.params.body??{},runId:this.runId,threadId:this.params.threadId,toolCallId:Z.toolCallId,signal:G,step:W,depth:this.depth,resumed:X!==void 0,attachments:V.attachments,generateImage:V.generateImage,editImage:V.editImage,turn:this.toolTurn($),runAgent:this.nestedRunner($,Z,G,X),generate:(K)=>this.generateForTool(K,G,Z.toolCallId)};try{let K=Q.tool.execute(J,H),z;if(o3(K)){let B=await K.next();while(!B.done){if(Y())throw K.return(void 0).catch(()=>{}),new q;this.emit({type:"tool-progress",toolCallId:Z.toolCallId,data:B.value}),B=await K.next()}z=B.value}else z=await K;return{type:"tool-result",toolCallId:Z.toolCallId,name:Z.name,status:"ok",output:z}}catch(K){if(K instanceof q||this.controller.signal.aborted)throw new q;if(K instanceof h)throw K;let z=K instanceof O;if(!z&&this.config.logErrors)this.logToolFailure(Z,K);let B={code:"tool_error",message:K instanceof Error?K.message:String(K),toolCallId:Z.toolCallId,retryable:z?K.retryable:!0};return{type:"tool-result",toolCallId:Z.toolCallId,name:Z.name,status:"error",error:this.redact(B,{source:"tool",toolName:String(Z.name),cause:K})}}}async generateForTool(Q,$,Z){let J=this.controller.signal;return yQ({...Q,signal:Q.signal?AbortSignal.any([$,Q.signal]):$},{origin:{agent:this.config.name,runId:this.runId,...this.params.threadId?{threadId:this.params.threadId}:{},toolCallId:Z},settled:(W)=>{if(this.usage=E(this.usage,W.usage),J.aborted)throw new q}})}nestedRunner(Q,$,Z,J){let W=new $9(()=>$.nested,()=>$.nested=[]);return async(X,G={})=>{let{at:Y,recorded:V,write:H}=W.next();if(V){let K=t3(V,X,G);if(K)throw new O(`Nested run ${Y} of "${String($.name)}" ${K}. `+"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(V.finishReason!=="awaiting-input")return{runId:V.runId,agent:V.agent,messages:V.messages,finishReason:V.finishReason??"stop",usage:V.usage??v(),output:Y$(V.messages),nested:V}}return this.runNested(Q,$,Z,X,G,H,V,J?.answers??[])}}async runNested(Q,$,Z,J,W,X,G,Y){let V=[...this.chain,J.name];if(this.chain.includes(J.name))throw new O(`"${J.name}" is already running further up this chain: ${V.join(" -> ")}. An agent cannot run itself, directly or through another agent.`);let H=this.depth+1;if(H>this.maxDepth)throw new O(`Nested agent runs are ${this.maxDepth} deep at most and this one would be ${H}: ${V.join(" -> ")}. Raise maxDepth on the agent at the root of the run if the tree is meant to be this deep.`);let K=W.label,z=[...this.pathPrefix,$.toolCallId],B=this.onPending==="deny"?"deny":W.onPending??"escalate",D=G!==void 0,F=D?jQ(G.messages):new Set,U=D?Y.filter((P)=>{let w=B$(P.path,z);if(w===null)return!1;return F.has(w.length>0?w[0]:P.toolCallId)}):[],L=J.stream({messages:D?G.messages:W.messages??[],turn:D?{toolResults:U}:W.prompt?{text:W.prompt}:void 0,context:this.context,attachments:this.params.attachments,body:this.params.body,signal:Z,threadId:this.params.threadId,redactError:this.params.redactError,nonces:this.params.nonces,subject:this.params.subject,instructions:W.instructions,maxOutputTokens:W.maxOutputTokens,temperature:W.temperature,runId:D?G.runId:void 0,nesting:{depth:H,maxDepth:this.maxDepth,chain:V,signingRunId:this.signingRunId,signingPath:z,onPending:B}}),C=[],R=(async()=>{for await(let P of L){if(P.type==="awaiting-input")C=P.pending;this.emit({type:"nested-event",toolCallId:$.toolCallId,runId:L.runId,agent:J.name,label:K,event:P})}})(),j=(async()=>{let P=await L.result();await R;let w=D?H$(G.messages,P.messages):H$(W.messages??[],P.messages),XQ={runId:L.runId,agent:J.name,label:K,messages:w,finishReason:P.finishReason,usage:D?E(G.usage??v(),P.usage):P.usage,...P.finishReason==="awaiting-input"?{signature:e9({runId:this.signingRunId,path:z,nestedRunId:L.runId,open:[...jQ(w)],input:$.input,subject:this.params.subject??null})}:{}};return X(XQ),this.usage=E(this.usage,P.usage),{result:P,record:XQ}})(),b=j.then(()=>{return},()=>{return});this.nestedSettling.add(b);let k,N;try{({result:k,record:N}=await j)}finally{this.nestedSettling.delete(b)}if(this.controller.signal.aborted)throw new q;if(k.finishReason==="awaiting-input"){if(C.length===0)throw new O(`"${J.name}" ended awaiting input but asked nothing, so there is no question to escalate.`);throw this.emit({type:"tool-call",messageId:Q,part:$,resent:!0}),new h({pending:C,path:z,nested:N})}return{runId:N.runId,agent:J.name,messages:N.messages,finishReason:k.finishReason,usage:N.usage??v(),output:k.output??Y$(N.messages),...k.error?{error:k.error}:{},nested:N}}addResult(Q,$){Q.content.push($),this.emit({type:"tool-result",messageId:Q.id,part:$})}toolFiles(Q,$){let Z=this.params.attachments??null,J=new $9(()=>Q.attachments,()=>Q.attachments=[],()=>({failed:!0})),W=()=>{if(!Z)throw new d("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 Z},X=async(H,K,z)=>{let B=W(),D=K.mimeType||H.type||"",F=K.name??(H instanceof File?H.name:"attachment"),U;if(K.showModel){let C=this.config.provider;if(!C.capabilities.fileInput)throw new O(`"${String(Q.name)}" asked to show a file to ${C.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.`);U=await C.upload(new File([H],F,{type:D||void 0}))}return{attachment:await B.put(H,{name:F,mimeType:D,fileId:U}),...z?{generated:z}:{},...U?{shown:{fileId:U,messageId:`msg_${crypto.randomUUID()}`,createdAt:new Date().toISOString()}}:{}}},G=(H,K,z)=>{let B=H.generated?"image":"put";if(B===K)return;throw new O(`Attachment ${z} of "${String(Q.name)}" was ${B==="image"?"a generated image":"a stored file"} on the first attempt and is ${K==="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.`)},Y=async(H,K,z)=>{let{at:B,recorded:D,write:F}=J.next();if(D&&"attachment"in D){if(G(D,"image",B),D.shown)this.queueShown(Q.toolCallId,D);return{attachment:D.attachment,size:D.generated.size,mimeType:D.attachment.mimeType,usage:D.generated.usage}}let U=await z();this.usage=E(this.usage,U.usage);let L=U.mimeType==="image/jpeg"?"jpg":"png",C=await X(U.image,{name:K.name??`${H.name}.${L}`,mimeType:U.mimeType,...K.showModel?{showModel:!0}:{}},{size:U.size,usage:U.usage});if(F(C),C.shown)this.queueShown(Q.toolCallId,C);return{attachment:C.attachment,size:U.size,mimeType:U.mimeType,usage:U.usage}},V=async(H)=>typeof H==="string"?await W().file(H):H;return{generateImage:(H,K)=>Y(H,K,()=>H.generate({...K,signal:$})),editImage:(H,K)=>Y(H,K,async()=>{let{images:z,mask:B,...D}=K;return await H.edit({...D,images:await Promise.all(z.map(V)),...B?{mask:await V(B)}:{},signal:$})}),attachments:{get:(H)=>W().get(H),read:(H)=>W().read(H),file:(H)=>W().file(H),put:async(H,K={})=>{let{at:z,recorded:B,write:D}=J.next();if(B&&"attachment"in B){G(B,"put",z);let U=s3(B,H,K);if(U)throw new O(`Attachment ${z} of "${String(Q.name)}" ${U}. `+"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(B.shown)this.queueShown(Q.toolCallId,B);return B.attachment}let F=await X(H,K);if(D(F),F.shown)this.queueShown(Q.toolCallId,F);return F.attachment}}}}toolTurn(Q){let $=this.history.findIndex((X)=>X.id===Q),Z=OQ(this.history),J;for(let X=$-1;X>=0;X--){let G=this.history[X];if(G.role!=="user"||Z.has(G.id))continue;J=G;break}let W=[];for(let X of J?.content??[]){if(X.type!=="file")continue;let G=X.attachmentId;if(typeof G!=="string"||!G.startsWith(x))continue;if(!W.includes(G))W.push(G)}return Object.freeze({attachments:Object.freeze(W)})}queueShown(Q,$){let Z=$.shown;if(!Z)return;let J=this.shownQueue.get(Q)??[];if(J.some((W)=>W.id===Z.messageId))return;J.push({id:Z.messageId,role:"user",content:[{type:"file",fileId:Z.fileId,name:$.attachment.name,mimeType:$.attachment.mimeType,attachmentId:$.attachment.id}],createdAt:Z.createdAt,finishReason:"stop"}),this.shownQueue.set(Q,J)}async settleShown(Q){let $=this.shownQueue.get(Q);if(!$||$.length===0)return;if(this.shownQueue.delete(Q),this.ended||this.controller.signal.aborted)return;for(let Z of $){if(this.history.some((J)=>J.id===Z.id))continue;this.history.push(Z),this.produced.push(Z),this.emit({type:"message",message:Z}),this.unreported.add(Z)}}historyForProvider(Q){let $=this.history.filter((X)=>X!==Q),Z=OQ($),J=[];for(let X of $){if(!Z.has(X.id))continue;for(let G of X.content)if(G.type==="file")J.push(G)}if(J.length<=z$)return $;let W=new Set(J.slice(0,J.length-z$));return $.map((X)=>{if(!X.content.some((G)=>G.type==="file"&&W.has(G)))return X;return{...X,content:X.content.map((G)=>G.type==="file"&&W.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 Q=this.params.turn,$=this.openCalls(),Z=[];if($.length>0){let J=new Set,W=new Set,X=new Map;for(let G of Q?.toolResults??[]){let Y=`${(G.path??[]).join("/")}#${G.toolCallId}`;if(W.has(Y))continue;W.add(Y);let V=(B)=>this.emit({type:"error",error:{code:"invalid_tool_result",message:B,toolCallId:G.toolCallId,retryable:!1}}),H=B$(G.path,this.pathPrefix);if(H===null){V(`The answer for "${G.toolCallId}" is addressed to a tool call this run is not inside.`);continue}if(H.length>0){let B=H[0],D=$.find((L)=>L.call.toolCallId===B);if(!D){V(`No pending tool call with id "${B}" to deliver a nested answer to.`);continue}let F=this.parkedBelow(D.call,H,G.toolCallId);if(F.ok===!1){let L=`The answer for "${G.toolCallId}" is addressed under "${B}", which`;V(F.reason==="unparked"?`${L} has no sub-agent run waiting on that question.`:F.reason==="expired"?`${L} parked a sub-agent run that has since expired. Ask again.`:`${L} carries a record of a parked sub-agent run the server did not sign.`);continue}let U=X.get(B);if(!U){if(!await this.spend(Z$,F.signature)){V(`The answer for "${G.toolCallId}" is addressed under "${B}", which has already been re-entered on that record. Ask again.`);continue}U=[],X.set(B,U),J.add(B)}U.push(G);continue}let K=$.find((B)=>B.call.toolCallId===G.toolCallId);if(!K){V(`No pending tool call with id "${G.toolCallId}".`);continue}let z=await this.resolveAnswer(K,G,Z);if(z===null)continue;if(J.add(G.toolCallId),z!=="open")this.attachToHistory(K,z),await this.settleShown(G.toolCallId)}for(let[G,Y]of X){let V=$.find((K)=>K.call.toolCallId===G),H=await this.reenter(V,Y,Z);if(H)this.attachToHistory(V,H),await this.settleShown(G)}for(let G of $){if(J.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(Q&&(Q.text||Q.files&&Q.files.length>0)){let J={id:`msg_${crypto.randomUUID()}`,role:"user",content:[...Q.text?[{type:"text",text:Q.text}]:[],...(Q.files??[]).map((W)=>({type:"file",...W.fileId?{fileId:W.fileId}:{},name:W.name,mimeType:W.mimeType,...W.attachmentId?{attachmentId:W.attachmentId}:{}}))],createdAt:new Date().toISOString(),finishReason:"stop"};this.history.push(J),this.produced.push(J),await this.report(J)}return Z}parkedBelow(Q,$,Z){let J=$.length>1?$[1]:Z,W=[...this.pathPrefix,Q.toolCallId],X=(Q.nested??[]).find((Y)=>Y.finishReason==="awaiting-input"&&jQ(Y.messages).has(J));if(!X)return{ok:!1,reason:"unparked"};if(typeof X.signature!=="string")return{ok:!1,reason:"unsigned"};let G=Q$(X.signature,{path:W,nestedRunId:X.runId,open:[...jQ(X.messages)],input:Q.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(Q,$,Z){let J=String(Q.call.name),W=this.config.registry.get(J);if(!W||!W.tool.execute)return{type:"tool-result",toolCallId:Q.call.toolCallId,name:Q.call.name,status:"error",error:{code:"invalid_tool_result",message:`The tool "${J}" no longer exists, so the sub-agent's question cannot be delivered.`,toolCallId:Q.call.toolCallId,retryable:!1}};let X=W.inputSchema.safeParse(Q.call.input);if(X.ok===!1)return{type:"tool-result",toolCallId:Q.call.toolCallId,name:Q.call.name,status:"error",error:{code:"invalid_tool_input",message:`Invalid arguments for "${J}": ${X.errors.join(", ")}`,toolCallId:Q.call.toolCallId,retryable:!0}};let G=this.amendCall(Q);G.input=X.value;try{return await f(this.executeTool(W,Q.message.id,G,X.value,0,{answers:$}),this.controller.signal)}catch(Y){if(Y instanceof h)return Z.push(...Y.pending),null;throw Y}}amendCall(Q){let $=this.amend(Q.message),Z=$.content.indexOf(Q.call),J={...Q.call,nested:(Q.call.nested??[]).map((W)=>({...W})),...Q.call.attachments?{attachments:Q.call.attachments.map((W)=>({...W}))}:{}};if(Z>=0)$.content[Z]=J;return this.unreported.add($),J}openCalls(){let Q=new Set;for(let Z of this.history)for(let J of Z.content)if(J.type==="tool-result")Q.add(J.toolCallId);let $=[];for(let Z of this.history)for(let J of Z.content)if(J.type==="tool-call"&&!Q.has(J.toolCallId))$.push({message:Z,call:J});return $}async spend(Q,$){try{return await Q($,this.params.nonces??m)}catch(Z){return this.writeLog(`[gemi/ai] agent "${this.config.name}" could not spend a nonce`,{error:Z}),!1}}async resolveAnswer(Q,$,Z){let J=Q.call,W=String(J.name),X=this.config.registry.get(W),G=(K)=>{return this.emit({type:"error",error:{code:"invalid_tool_result",message:K,toolCallId:J.toolCallId,retryable:!1}}),null};if(!X)return G(`The tool "${W}" no longer exists, so its answer cannot be checked.`);let Y=U$(X.tool);if(!Y)return G(`"${W}" is a server tool with no pending question.`);if(typeof $.signature!=="string"||$.signature.length===0)return G(`The answer for "${W}" carried no signature.`);let V=dQ($.signature);if(!V)return G(`The signature for "${W}" is malformed.`);let H=s9($.signature,{...this.claimsFor(J.toolCallId,W,Y,J.input),runId:V.runId});if(H.ok===!1)return G(H.reason==="expired"?`The approval for "${W}" has expired. Ask again.`:`The answer for "${W}" does not match the call the server made.`);if(!await this.spend($$,$.signature))return G(`The answer for "${W}" has already been used. Ask again.`);if("approve"in $){if(Y!=="approval")return G(`"${W}" is answered by the client, not approved.`);if($.approve===!0){let K=this.amendCall(Q);try{return await f(this.executeTool(X,Q.message.id,K,K.input,0),this.controller.signal)}catch(z){if(z instanceof h)return Z.push(...z.pending),"open";throw z}}return{type:"tool-result",toolCallId:J.toolCallId,name:J.name,status:"denied",cause:"refused",reason:$.reason}}if("output"in $){if(Y==="approval")return G(`"${W}" is approved, not answered: the server produces its result.`);let K=X.tool.outputSchema,z=K?K.safeParse($.output):{ok:!0,value:$.output};if(z.ok===!1)return{type:"tool-result",toolCallId:J.toolCallId,name:J.name,status:"error",error:{code:"invalid_tool_result",message:`The answer for "${W}" did not match its output schema: ${z.errors.join(", ")}`,toolCallId:J.toolCallId,retryable:!0}};return{type:"tool-result",toolCallId:J.toolCallId,name:J.name,status:"ok",output:z.value}}return G(`The answer for "${W}" carried neither an approval nor an output.`)}attachToHistory(Q,$){let Z=this.amend(Q.message);Z.content.push($),this.unreported.add(Z),this.emit({type:"tool-result",messageId:Z.id,part:$})}markFileRejected(Q,$,Z){for(let G of this.history){if(!G.content.some((H)=>H.type==="file"&&H.fileId===Q&&!H.providerRejected))continue;let V=this.produced.includes(G)?G:this.amend(G);if(V.content=V.content.map((H)=>H.type==="file"&&H.fileId===Q&&!H.providerRejected?{...H,providerRejected:!0}:H),V!==this.current)this.unreported.add(V)}if(!this.config.logErrors)return;let J=`[gemi/ai] agent "${this.config.name}": the provider refused file ${Q}${Z.status!==void 0?` (${Z.status})`:""}; it was left out of the request and will not be sent again: ${$}`,W={agent:this.config.name,runId:this.runId,...this.params.threadId?{threadId:this.params.threadId}:{},fileId:Q,...Z},X=!1;try{t.warning(J,W),X=!0}catch{}if(!X||Bun.env.NODE_ENV==="development")console.warn(J,W)}amend(Q){let $=this.amended.get(Q.id);if($)return $;let Z={...Q,content:[...Q.content]},J=this.history.indexOf(Q);if(J>=0)this.history[J]=Z;return this.produced.push(Z),this.amended.set(Q.id,Z),Z}async reportDeferred(){let Q=[...this.unreported];this.unreported.clear();for(let $ of Q)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 Q=this.current;if(Q){let $=new Set(Q.content.filter((Z)=>Z.type==="tool-result").map((Z)=>Z.toolCallId));for(let Z of[...Q.content]){if(Z.type!=="tool-call"||$.has(Z.toolCallId))continue;delete Z.partial,this.addResult(Q,{type:"tool-result",toolCallId:Z.toolCallId,name:Z.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 ${aQ(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 U$(Q){if(Q.answeredBy==="client")return Q.inputSchema===Z9?"question":"client";return Q.requiresApproval?"approval":null}function D$(Q){if(!Q||!Q.trim())return{};try{return JSON.parse(Q)}catch{return Q}}function a3(Q,$){return Q.descriptors($).map((Z)=>y.create({name:Z.name,description:Z.description,inputSchema:Z.inputSchema,requiresApproval:Z.requiresApproval,execute:(J,W)=>{let X=NQ.getStore()?.req;if(!X)throw new O(`"${Z.name}" calls an api route as the user who started this run, and this run was not started inside a request. Run it from an AgentController, or give this agent tools that do not go through the MCP registry.`);return Q.execute({kind:"local",req:X},Z.name,J,W)}}))}function r3(Q){if(Q==="auto")return;let $=/^(\d+)x(\d+)$/.exec(Q);if(!$)throw Error(`An image size is "WIDTHxHEIGHT" or "auto"; got ${JSON.stringify(Q)}.`);let Z=Number($[1]),J=Number($[2]);if(Z%16!==0||J%16!==0)throw Error(`Image size ${Q} is not supported: width and height must both be divisible by 16.`);if(Math.max(Z/J,J/Z)>3)throw Error(`Image size ${Q} is not supported: the maximum aspect ratio is 3:1, either way up.`)}function j$(Q,$){if(Q.size!==void 0)try{r3(Q.size)}catch(Z){throw Error(`${$}: ${Z.message}`)}if(Q.background==="transparent"&&Q.format==="jpeg")throw Error(`${$}: a transparent background needs "png"; JPEG has no alpha channel.`);if(Q.compression!==void 0){let Z=Q.compression;if(!Number.isInteger(Z)||Z<0||Z>100)throw Error(`${$}: compression is an integer from 0 to 100; got ${Z}.`)}}function O$(Q,$){if(Q instanceof File)return Q;let Z=Q.type||"image/png",J=Z==="image/jpeg"?"jpg":Z.split("/")[1]??"png";return new File([Q],`${$}.${J}`,{type:Z})}class H9{name;provider;settings;constructor(Q){let{name:$,provider:Z,...J}=Q;j$(J,`ImageModel "${$}"`),this.name=$,this.provider=Z,this.settings=J}static create(Q){return new H9(Q)}async generate(Q){let $=this.merge(Q);return N$(await this.provider.generate({prompt:Q.prompt,...$,signal:Q.signal}))}async edit(Q){let $=this.merge(Q);return N$(await this.provider.edit({prompt:Q.prompt,...$,images:Q.images.map((Z,J)=>O$(Z,`image-${J}`)),...Q.mask?{mask:O$(Q.mask,"mask")}:{},signal:Q.signal}))}merge(Q){let $={...this.settings,...Q.size!==void 0?{size:Q.size}:{},...Q.quality!==void 0?{quality:Q.quality}:{},...Q.background!==void 0?{background:Q.background}:{},...Q.format!==void 0?{format:Q.format}:{},...Q.compression!==void 0?{compression:Q.compression}:{}};return j$($,`ImageModel "${this.name}"`),$}}function N$(Q){return{image:new Blob([Q.bytes],{type:Q.mimeType}),mimeType:Q.mimeType,size:Q.size,usage:Q.usage}}function g(Q){return typeof process>"u"?void 0:process.env?.[Q]}var e3="preview";function _$(Q){let $=Q.trim().replace(/\/+$/,"");if(!$)return"";return`${$.replace(/\/openai(?:\/v1)?$/i,"")}/openai`}function QZ(Q){return/^\d{4}-\d{2}-\d{2}/.test(Q)?"":"/v1"}function qQ(Q,$={}){return{base:(Q.baseURL??g("OPENAI_BASE_URL")??"https://api.openai.com/v1").replace(/\/+$/,""),query:"",headers:async()=>{let J=Q.apiKey??g("OPENAI_API_KEY");return{...J?{authorization:`Bearer ${J}`}:{},...Q.headers}},timeoutMs:Q.timeoutMs??$.timeoutMs??120000,maxRetries:Q.maxRetries??2}}function $Z(Q){let $=Q.baseURL??Q.endpoint??g("AZURE_OPENAI_ENDPOINT");if($)return _$($);let Z=Q.resourceName??g("AZURE_OPENAI_RESOURCE_NAME")??g("AZURE_RESOURCE_NAME");return Z?_$(`https://${Z.trim()}.cognitiveservices.azure.com`):""}function MQ(Q,$={}){let Z=Q.apiVersion??g("AZURE_OPENAI_API_VERSION")??e3;return{base:`${$Z(Q)}${QZ(Z)}`,query:`?api-version=${encodeURIComponent(Z)}`,headers:async()=>{if(Q.getToken)return{authorization:`Bearer ${await Q.getToken()}`,...Q.headers};let J=Q.apiKey??g("AZURE_OPENAI_API_KEY");return{...J?{"api-key":J}:{},...Q.headers}},timeoutMs:Q.timeoutMs??$.timeoutMs??120000,maxRetries:Q.maxRetries??2}}var ZZ=500,M$=20000;function JZ(Q,$){if(!Q)return;let Z=Q.trim();if(/^\d+(\.\d+)?$/.test(Z))return Math.max(0,Number(Z)*1000);let J=Date.parse(Z);if(Number.isNaN(J))return;return Math.max(0,J-$)}function q$(Q,$){let Z=Math.min(M$,ZZ*2**Q);return Math.round(Z*(0.5+$()*0.5))}function WZ(Q){return Q===429||Q===408||Q===409||Q>=500}function XZ(Q,$){return WZ(Q)&&_($).retryable}function S$(Q){return Q.reason??new DOMException("The operation was aborted.","AbortError")}function GZ(Q,$){return new Promise((Z,J)=>{let W=setTimeout(Z,Q);$?.addEventListener("abort",()=>{clearTimeout(W),J(S$($))},{once:!0})})}async function ZQ(Q,$,Z){let J=Z.fetchImpl??((K,z)=>fetch(K,z)),W=Z.sleep??GZ,X=Z.random??Math.random,G=Z.now??Date.now,Y=Math.max(0,Z.maxRetries),V=async(K)=>{let z=Z.signal;if(!z)return await W(K);z.throwIfAborted();let B;try{await Promise.race([W(K,z),new Promise((D,F)=>{B=()=>F(S$(z)),z.addEventListener("abort",B,{once:!0})})])}finally{if(B)z.removeEventListener("abort",B)}},H;for(let K=0;K<=Y;K++){Z.signal?.throwIfAborted();let z=new AbortController,B=()=>z.abort(Z.signal?.reason);Z.signal?.addEventListener("abort",B,{once:!0});let D=!1,F=Z.timeoutMs>0?setTimeout(()=>{D=!0,z.abort()},Z.timeoutMs):void 0,U;try{U=await J(Q,{...$,signal:z.signal})}catch(j){if(F!==void 0)clearTimeout(F);if(Z.signal?.removeEventListener("abort",B),Z.signal?.aborted)throw j;if(H=D?new GQ(Z.timeoutMs):j,D&&Z.retryTimeouts===!1)throw H;if(K===Y)throw H;await V(q$(K,X));continue}if(F!==void 0)clearTimeout(F);if(U.ok)return U;Z.signal?.removeEventListener("abort",B);let L=await VZ(U),C=new I(U.status,L,U.headers.get("x-request-id")??void 0);if(K===Y||!XZ(U.status,C))throw C;let R=JZ(U.headers.get("retry-after"),G());await V(R===void 0?q$(K,X):Math.min(R,M$)),H=C}throw H??Error("Provider request failed with no response.")}async function VZ(Q){let $;try{$=await Q.text()}catch{return null}try{return JSON.parse($)}catch{return $}}var Y9=300000;function K9(Q){return{generationsUrl:`${Q.base}/images/generations${Q.query}`,editsUrl:`${Q.base}/images/edits${Q.query}`,headers:Q.headers,timeoutMs:Q.timeoutMs,maxRetries:Q.maxRetries}}class SQ extends Error{code;retryable;constructor(Q,$={}){super(Q.message,$);this.name="ImageRequestError",this.code=Q.code,this.retryable=Q.retryable}}var HZ={png:"image/png",jpeg:"image/jpeg"};function YZ(Q){let $=Number(Q?.input_tokens??0),Z=Number(Q?.output_tokens??0),J={inputTokens:$,outputTokens:Z,totalTokens:Number(Q?.total_tokens??$+Z)},W=Q?.input_tokens_details?.image_tokens;if(typeof W==="number")J.imageInputTokens=W;let X=Q?.output_tokens_details?.image_tokens;if(typeof X==="number")J.imageOutputTokens=X;return J}function KZ(Q){let $=atob(Q),Z=new Uint8Array($.length);for(let J=0;J<$.length;J++)Z[J]=$.charCodeAt(J);return Z}function zZ(Q){let Z=Q?.data?.[0]?.b64_json;if(typeof Z!=="string"||Z.length===0)throw new SQ({code:"provider_error",message:"The provider answered an image call with no base64 image data.",retryable:!1});let J=typeof Q.output_format==="string"?Q.output_format:"png";return{bytes:KZ(Z),mimeType:HZ[J]??`image/${J}`,size:typeof Q.size==="string"?Q.size:"",...typeof Q.background==="string"?{background:Q.background}:{},usage:YZ(Q.usage)}}async function R$(Q,$,Z,J){let W;try{W=await ZQ(Q,$,{maxRetries:Z.maxRetries,timeoutMs:Z.timeoutMs,retryTimeouts:!1,signal:J.signal,fetchImpl:Z.fetchImpl})}catch(X){if(J.signal?.aborted)throw X;throw new SQ(_(X),{cause:X})}return zZ(await W.json())}async function k$(Q,$,Z={}){return await R$(Q.generationsUrl,{method:"POST",headers:{...await Q.headers(),"content-type":"application/json"},body:JSON.stringify($)},Q,Z)}async function T$(Q,$,Z={}){return await R$(Q.editsUrl,{method:"POST",headers:await Q.headers(),body:$},Q,Z)}class RQ{static models(){return[]}modelName(){return this.model}async generate(Q){return await k$(this.endpoint(),this.body(Q),{signal:Q.signal})}async edit(Q){let $=new FormData;for(let[Z,J]of Object.entries(this.body(Q)))if(J!==void 0)$.set(Z,String(J));for(let Z of Q.images)$.append("image[]",Z,Z.name);if(Q.mask)$.set("mask",Q.mask,Q.mask.name);return await T$(this.endpoint(),$,{signal:Q.signal})}body(Q){return{model:this.modelName(),prompt:Q.prompt,...Q.size?{size:Q.size}:{},...Q.quality?{quality:Q.quality}:{},...Q.background?{background:Q.background}:{},...Q.format?{output_format:Q.format}:{},...Q.compression!==void 0?{output_compression:Q.compression}:{}}}normalizeError(Q){return _(Q)}}var A$=["gpt-image-2","gpt-image-1.5","gpt-image-1"];class z9 extends RQ{model;config;constructor(Q,$={}){super();this.model=Q,this.config=$}static model(Q,$){return new z9(Q,$)}static models(){return A$}endpoint(){return K9(qQ(this.config,{timeoutMs:Y9}))}}class B9 extends RQ{model;config;constructor(Q,$={}){super();this.model=Q,this.config=$}static model(Q,$){return new B9(Q,$)}static models(){return A$}modelName(){return this.config.deployment??this.model}endpoint(){return K9(MQ(this.config,{timeoutMs:Y9}))}}var b$=3;function U9(Q){let $=new Map;for(let Z of Q)for(let J of Z.content??[]){if(J.type!=="file"||!J.fileId||$.has(J.fileId))continue;$.set(J.fileId,{name:J.name,mimeType:J.mimeType})}return $}function w$(Q,$,Z=new Map){if(!($ instanceof I))return[];if($.status!==400&&$.status!==404)return[];let J=UZ($.body);if(!J)return[];let W=BZ(Q.input);if(W.length===0)return[];let X=/^input\[(\d+)\]\.content\[(\d+)\]\.file_id$/.exec(J.param??"");if(X){let H=Q.input[Number(X[1])],K=F9(H)[Number(X[2])],z=K&&typeof K.file_id==="string"?K.file_id:void 0;if(z)return[z]}let G=J.message??"",Y=E$(W.map((H)=>H.fileId).filter((H)=>DZ(G,H)));if(Y.length>0)return Y;let V=/Expected (image type|context stuffing file type) to be a supported format:.*but got \.([a-z0-9]+)\.?\s*$/is.exec(G);if(V){let H=V[1].toLowerCase()==="image type"?"input_image":"input_file",K=V[2].toLowerCase(),z=E$(W.filter((D)=>D.type===H).map((D)=>D.fileId)),B=z.filter((D)=>(Z.get(D)?.name??"").trim().toLowerCase().endsWith(`.${K}`));if(B.length===1)return B;if(B.length===0&&z.length===1)return z}return[]}function I$(Q,$,Z=new Map){return{...Q,input:Q.input.map((J)=>{let W=F9(J);if(!W.some((X)=>x$(X,$)))return J;return{...J,content:W.map((X)=>x$(X,$)?{type:"input_text",text:D9(Z.get(String(X.file_id))?.name)}:X)}})}}function D9(Q){return`[${Q?`attachment ${JSON.stringify(Q)}`:"an attachment"} could not be read by the provider and is not shown to you. Tell the user if it matters to the answer; uploading it again may help.]`}function x$(Q,$){return typeof Q.file_id==="string"&&$.has(Q.file_id)}function F9(Q){let $=Q?.content;return Array.isArray($)?$:[]}function BZ(Q){let $=[];for(let Z of Q)for(let J of F9(Z))if(typeof J.file_id==="string"&&J.file_id)$.push({type:String(J.type),fileId:J.file_id});return $}function UZ(Q){if(!Q||typeof Q!=="object")return null;let $=Q,Z=$.error&&typeof $.error==="object"?$.error:Q;return{message:typeof Z.message==="string"?Z.message:void 0,param:typeof Z.param==="string"?Z.param:void 0}}function DZ(Q,$){let Z=$.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^A-Za-z0-9_-])${Z}($|[^A-Za-z0-9_-])`).test(Q)}function E$(Q){return[...new Set(Q)]}async function*FZ(Q){let $="",Z="",J=[],W,X=()=>{if(J.length===0&&!Z)return null;let V={event:Z,data:J.join(`
|
|
16
|
-
`),id:W};return Z="",J=[],W=void 0,V.data?V:null},G=(V)=>{let
|
|
17
|
-
`);while(
|
|
18
|
-
`)}}if($.length>0){let V=G($);if(V)yield V}let Y=X();if(Y)yield Y}async function*v$(Q,$={}){let Z=new Map,J=new Set,W=!1;for await(let X of FZ(Q)){if(X.data==="[DONE]")break;let G;try{G=JSON.parse(X.data)}catch{continue}switch(typeof G.type==="string"?G.type:X.event){case"response.output_text.delta":{let V=String(G.delta??"");if(!V)break;yield $.structuredOutput?{type:"output-delta",delta:V}:{type:"text-delta",delta:V};break}case"response.reasoning_summary_text.delta":case"response.reasoning_text.delta":{let V=String(G.delta??"");if(!V)break;yield{type:"reasoning-delta",delta:V,id:G.item_id};break}case"response.output_item.added":{let V=G.item;if(!V)break;if(V.type==="function_call"){let H=String(V.id??G.item_id??V.call_id??"");Z.set(H,{callId:String(V.call_id??H),name:String(V.name??""),namespace:typeof V.namespace==="string"&&V.namespace?V.namespace:void 0,done:!1})}break}case"response.function_call_arguments.delta":{let V=Z.get(String(G.item_id??""));if(!V)break;let H=String(G.delta??"");if(!H)break;yield{type:"tool-call-delta",toolCallId:V.callId,name:V.name,argsDelta:H,...V.namespace?{namespace:V.namespace}:{}};break}case"response.function_call_arguments.done":{let V=String(G.item_id??""),H=Z.get(V);if(!H)break;H.done=!0,yield{type:"tool-call",toolCallId:H.callId,name:H.name,args:String(G.arguments??""),...H.namespace?{namespace:H.namespace}:{}};break}case"response.output_item.done":{let V=G.item;if(!V)break;if(V.type==="function_call"){let H=String(V.id??G.item_id??V.call_id??""),K=Z.get(H);if(K?.done)break;let z=(typeof V.namespace==="string"?V.namespace:"")||K?.namespace;if(yield{type:"tool-call",toolCallId:String(V.call_id??H),name:String(V.name??K?.name??""),args:String(V.arguments??""),...z?{namespace:z}:{}},K)K.done=!0;break}if(V.type==="tool_search_call"||V.type==="tool_search_output"){let H=CZ(V);if(H.loaded.length===0&&H.namespaces.length===0)break;let K=String(V.tool_search_call_id??V.id??"");if(J.has(K))break;J.add(K),yield{type:"tool-search",...H}}break}case"response.refusal.done":{yield{type:"error",error:{code:"content_filtered",message:String(G.refusal??"The model refused to answer."),retryable:!1}};break}case"response.completed":{W=!0,yield{type:"finish",reason:"stop",usage:C9(G.response?.usage)};break}case"response.incomplete":{W=!0;let V=C9(G.response?.usage),H=G.response?.incomplete_details?.reason;if(H==="content_filter"){yield{type:"error",error:{code:"content_filtered",message:LZ(G.response?.content_filters),retryable:!1}},yield{type:"finish",reason:"error",usage:V};break}yield{type:"finish",reason:H==="max_output_tokens"?"length":"stop",usage:V};break}case"response.failed":case"error":{W=!0;let V=G.response?.error??G.error??G;yield{type:"error",error:PZ(V)},yield{type:"finish",reason:"error",usage:C9(G.response?.usage)};break}}if(W)return}if(!W)yield{type:"error",error:{code:"provider_error",message:"The provider stream ended without a terminal event.",retryable:!0}},yield{type:"finish",reason:"error",usage:l()}}function CZ(Q){let $=[],Z=[];return f$(Q.results??Q.tools??Q.loaded??Q.output,$,Z,0),{loaded:L9($),namespaces:L9(Z)}}function f$(Q,$,Z,J){if(!Array.isArray(Q)||J>4)return;for(let W of Q){if(typeof W==="string"){$.push(W);continue}if(!W||typeof W!=="object")continue;let X=W,G=typeof X.name==="string"?X.name:typeof X.tool_name==="string"?X.tool_name:"",Y=X.tools??X.functions;if(Array.isArray(Y)){if(G)Z.push(G);f$(Y,$,Z,J+1);continue}if(G)$.push(G)}}function L9(Q){return Q.filter(($,Z)=>Q.indexOf($)===Z)}function LZ(Q){if(!Array.isArray(Q))return"The provider's content filter blocked this request.";let Z=[];for(let J of Q){if(!J||typeof J!=="object")continue;let W=J,X=W.content_filter_results;if(!X||typeof X!=="object")continue;for(let[G,Y]of Object.entries(X))if(Y&&typeof Y==="object"&&Y.filtered===!0)Z.push(`${G} (${String(W.source_type??"unknown")})`)}return Z.length===0?"The provider's content filter blocked this request.":`The provider's content filter blocked this request. Categories: ${L9(Z).join(", ")}.`}function PZ(Q){let $=typeof Q?.message==="string"?Q.message:"The provider stream failed.",Z=String(Q?.code??"").toLowerCase();if(Z==="rate_limit_exceeded")return{code:"rate_limited",message:$,retryable:!0};if(Z==="context_length_exceeded")return{code:"context_length_exceeded",message:$,retryable:!1};if(Z.includes("content_filter"))return{code:"content_filtered",message:$,retryable:!1};return{code:"provider_error",message:$,retryable:!0}}function l(){return{inputTokens:0,outputTokens:0,totalTokens:0}}function C9(Q){if(!Q)return l();let $=Number(Q.input_tokens??0),Z=Number(Q.output_tokens??0),J={inputTokens:$,outputTokens:Z,totalTokens:Number(Q.total_tokens??$+Z)},W=Q.output_tokens_details?.reasoning_tokens;if(typeof W==="number")J.reasoningTokens=W;let X=Q.input_tokens_details?.cached_tokens;if(typeof X==="number")J.cachedInputTokens=X;return J}async function*h$(Q){if(!Q)return;let $=Q.getReader(),Z=new TextDecoder;try{while(!0){let{done:W,value:X}=await $.read();if(W)break;if(X)yield Z.decode(X,{stream:!0})}let J=Z.decode();if(J)yield J}finally{$.releaseLock()}}function P9(Q){return{responsesUrl:`${Q.base}/responses${Q.query}`,filesUrl:`${Q.base}/files${Q.query}`,headers:Q.headers,timeoutMs:Q.timeoutMs,maxRetries:Q.maxRetries}}async function*j9(Q,$,Z){let J,W=$,X=new Set;for(let G=0;J===void 0;G++)try{J=await ZQ(Q.responsesUrl,{method:"POST",headers:{...await Q.headers(),"content-type":"application/json"},body:JSON.stringify(W)},{maxRetries:Q.maxRetries,timeoutMs:Q.timeoutMs,signal:Z.signal,fetchImpl:Q.fetchImpl})}catch(Y){let V=G<b$?w$(W,Y,Z.files).filter((K)=>!X.has(K)):[];if(V.length>0){let K=_(Y).message;for(let z of V)X.add(z),yield{type:"file-rejected",fileId:z,message:K,...T(Y)};W=I$(W,new Set(V),Z.files);continue}let H=_(Y);if(H.code!=="aborted")yield{type:"error",error:H,...T(Y)};yield{type:"finish",reason:H.code==="aborted"?"aborted":"error",usage:l()};return}try{yield*v$(h$(J.body),{structuredOutput:Z.structuredOutput})}catch(G){let Y=_(G);if(Y.code==="aborted"){yield{type:"finish",reason:"aborted",usage:l()};return}yield{type:"error",error:Y},yield{type:"finish",reason:"error",usage:l()}}}async function O9(Q,$,Z="user_data"){let J=new FormData;J.set("purpose",Z),J.set("file",$);let X=await(await ZQ(Q.filesUrl,{method:"POST",headers:await Q.headers(),body:J},{maxRetries:Q.maxRetries,timeoutMs:Q.timeoutMs,fetchImpl:Q.fetchImpl})).json();if(!X?.id)throw Error("The provider accepted the upload but returned no file id.");return X.id}function N9(Q){let $=jZ(Q);if($.startsWith("gpt-3.5")||$.startsWith("text-")||$.startsWith("davinci"))return{reasoning:!1,structuredOutput:!1,fileInput:!1,parallelToolCalls:!0,toolSearch:!1};let Z=OZ($);if(Z?.kind==="o")return{reasoning:!0,structuredOutput:!0,fileInput:!0,parallelToolCalls:Z.major>1,toolSearch:y$(Z)};if(Z?.kind==="gpt")return{reasoning:Z.major>=5,structuredOutput:Z.major>4||$.startsWith("gpt-4o")||$.startsWith("gpt-4.1"),fileInput:Z.major>4||$.startsWith("gpt-4o")||$.startsWith("gpt-4.1"),parallelToolCalls:!0,toolSearch:y$(Z)};return{reasoning:!0,structuredOutput:!0,fileInput:!0,parallelToolCalls:!0,toolSearch:!0}}function y$(Q){if(Q.kind==="o")return Q.major>=5;return Q.major>5||Q.major===5&&Q.minor>=2}function jZ(Q){return Q.trim().toLowerCase()}function OZ(Q){let $=/^gpt-(\d+)(?:\.(\d+))?/.exec(Q);if($?.[1])return{kind:"gpt",major:Number($[1]),minor:Number($[2]??0)};let Z=/^o(\d+)(?:[-.]|$)/.exec(Q);if(Z?.[1])return{kind:"o",major:Number(Z[1]),minor:0};return null}function q9(Q,$){let{capabilities:Z}=$,J={model:$.model,input:NZ(Q.messages,Z),stream:!0};if(Q.systemPrompt)J.instructions=Q.systemPrompt;let W=xZ(Q.tools,Z);if(W.length>0){if(J.tools=W,!Z.parallelToolCalls)J.parallel_tool_calls=!1}if(Q.output)J.text={format:{type:"json_schema",name:Q.output.name,schema:Q.output.schema,strict:Q.output.strict}};if(Q.reasoning&&Z.reasoning)J.reasoning=Q.reasoning==="none"?{effort:"none"}:{effort:Q.reasoning,summary:"auto"};if(typeof Q.temperature==="number")J.temperature=Q.temperature;if(typeof Q.maxOutputTokens==="number")J.max_output_tokens=Q.maxOutputTokens;return J}function NZ(Q,$){let Z=[];for(let J of Q){let W=J.role,X=[],G=()=>{if(X.length===0)return;Z.push({type:"message",role:W,content:X}),X=[]};for(let Y of J.content??[])switch(Y.type){case"text":{if(!Y.text)break;X.push(i(W,Y.text));break}case"output":{if(Y.partial)break;X.push(i(W,JSON.stringify(Y.value)));break}case"file":{if(W==="assistant")break;let V=MZ(Y);if(!$.fileInput){if(V)X.push(i(W,_9(Y,!1)));break}if(Y.fileId?.startsWith(x))throw Error(`FilePart.fileId holds a gemi attachment id (${Y.fileId}). That field is the *provider's* file id, from \`fileId\` on the upload response; the \`attachmentId\` goes in \`FilePart.attachmentId\`, is shown to the model as text, and is resolved by a tool through \`ctx.attachments\`.`);if(!Y.fileId&&!V)throw Error("FilePart.fileId is empty and there is no `attachmentId` either. `fileId` is the *provider's* file id and `attachmentId` is gemi's (`gemi_att_\u2026`), both from the upload response; an upload always answers at least one, so a part with neither was built from something other than that answer.");if(Y.providerRejected){if(V)X.push(i(W,_9(Y,!1)));X.push(i(W,D9(Y.name)));break}if(V)X.push(i(W,_9(Y,!!Y.fileId)));if(Y.fileId)X.push(SZ(Y));break}case"reasoning":{G();let V=TZ(Y);if(V)Z.push(V);break}case"tool-call":{if(Y.partial)break;G(),Z.push({type:"function_call",call_id:Y.toolCallId,name:String(Y.name),arguments:JSON.stringify(Y.input??{})});break}case"tool-result":{G(),Z.push({type:"function_call_output",call_id:Y.toolCallId,output:AZ(Y)});break}}G()}return qZ(Z)}var _Z="No result was recorded for this tool call. Assume it did not complete.";function qZ(Q){let $=new Set,Z=new Set,J=[];for(let X of Q){if(X.type==="function_call"){let G=String(X.call_id);if($.has(G))continue;$.add(G)}else if(X.type==="function_call_output"){let G=String(X.call_id);if(!$.has(G)||Z.has(G))continue;Z.add(G)}J.push(X)}if(Z.size===$.size)return J;let W=[];for(let X of J){if(W.push(X),X.type!=="function_call")continue;let G=String(X.call_id);if(Z.has(G))continue;Z.add(G),W.push({type:"function_call_output",call_id:G,output:_Z})}return W}function i(Q,$){return{type:Q==="assistant"?"output_text":"input_text",text:$}}function MZ(Q){let $=Q.attachmentId;return typeof $==="string"&&$.startsWith(x)?$:void 0}function _9(Q,$){let Z=[`id=${JSON.stringify(Q.attachmentId)}`];if(Q.name)Z.push(`name=${JSON.stringify(Q.name)}`);if(Q.mimeType)Z.push(`mimeType=${JSON.stringify(Q.mimeType)}`);let J=`attachment ${Z.join(" ")}`;return $?`[${J}]`:`[${J} \u2014 its contents are not shown to you; a tool can read the file by this id]`}function SZ(Q){let $=Q.mimeType?.trim().toLowerCase()??"";return{type:($?$.startsWith("image/")&&$!=="image/svg+xml":RZ(Q.name))?"input_image":"input_file",file_id:Q.fileId}}function RZ(Q){let $=/\.([a-z0-9]+)$/.exec(Q?.trim().toLowerCase()??"");return $?.[1]!==void 0&&kZ.has($[1])}var kZ=new Set(["jpeg","jpg","png","gif","webp"]);function TZ(Q){if(!Q.id)return null;let $={type:"reasoning",id:Q.id};return $.summary=Q.text?[{type:"summary_text",text:Q.text}]:[],$}function AZ(Q){if(Q.status==="ok")return typeof Q.output==="string"?Q.output:JSON.stringify(Q.output??null);if(Q.status==="denied"){let $=Q.reason?` Reason given: ${Q.reason}`:"";if(Q.cause==="stopped")return`The run was stopped before this tool call could complete, so it did not run.${$}`;if(Q.cause==="interrupted")return`The run was interrupted (the server stopped) while this tool call was in progress, so its result was lost. It may have run in part or in full: check its effects before repeating it.${$}`;return`The user declined this tool call, so it did not run.${$}`}return`The tool call failed and produced no result. Error (${Q.error?.code??"unknown"}): ${Q.error?.message??"no message"}`}function g$(Q){return Array.isArray(Q.tools)}function xZ(Q,$){if(!Q||Q.length===0)return[];if(!$.toolSearch){let W=[];for(let X of Q)if(g$(X))for(let G of X.tools)W.push(kQ(G,!1));else W.push(kQ(X,!1));return W}let Z=[],J=!1;for(let W of Q)if(g$(W)){let X=W.tools.map((G)=>{if(G.deferred)J=!0;return kQ(G,!0)});Z.push({type:"namespace",name:W.name,description:W.description,tools:X})}else{if(W.deferred)J=!0;Z.push(kQ(W,!0))}if(J)Z.push({type:"tool_search"});return Z}function kQ(Q,$){let Z={type:"function",name:Q.name,description:Q.description,parameters:Q.parameters,strict:Q.strict};if($&&Q.deferred)Z.defer_loading=!0;return Z}class TQ{static models(){return[]}normalizeError(Q){return _(Q)}}var u$=["gpt-5.5","gpt-5.4","gpt-5.4-mini","gpt-5.4-nano","gpt-5.2","gpt-5.1","gpt-5","gpt-5-mini","gpt-5-nano","gpt-4.1","gpt-4.1-mini","gpt-4.1-nano","gpt-4o","gpt-4o-mini","o4-mini","o3","o3-mini"];class M9 extends TQ{model;capabilities;config;constructor(Q,$={}){super();this.model=Q,this.capabilities=N9(Q),this.config=$}static model(Q,$){return new M9(Q,$)}static models(){return u$}stream(Q){let $=q9(Q,{model:this.model,capabilities:this.capabilities});return j9(this.endpoint(),$,{signal:Q.signal,structuredOutput:Boolean(Q.output),files:U9(Q.messages)})}upload(Q){return O9(this.endpoint(),Q)}endpoint(){return P9(qQ(this.config))}}class S9 extends TQ{model;capabilities;config;constructor(Q,$={}){super();this.model=Q,this.capabilities=N9(Q),this.config=$}static model(Q,$){return new S9(Q,$)}static models(){return u$}stream(Q){let $=q9(Q,{model:this.deployment(),capabilities:this.capabilities});return j9(this.endpoint(),$,{signal:Q.signal,structuredOutput:Boolean(Q.output),files:U9(Q.messages)})}upload(Q){return O9(this.endpoint(),Q,"assistants")}deployment(){return this.config.deployment??this.model}endpoint(){return P9(MQ(this.config))}}class o extends Error{runId;requested;oldest;code="frame_cursor_evicted";constructor(Q,$,Z){super(`Frame ${$} of run ${Q} has been evicted; the oldest frame still buffered is ${Z}. Reload the thread instead of resuming.`);this.runId=Q;this.requested=$;this.oldest=Z}}class JQ extends Error{runId;code="live_run_not_found";constructor(Q){super(`No live run ${Q} in this process.`);this.runId=Q}}class AQ{ttlMs;maxFrames;maxAgeMs;runs=new Map;byThread=new Map;byClientRun=new Map;constructor(Q={}){this.ttlMs=Q.ttlMs??60000,this.maxFrames=Q.maxFrames??4096,this.maxAgeMs=Q.maxAgeMs===void 0?3600000:Q.maxAgeMs}register(Q,$={}){let Z={run:Q,threadId:$.threadId,owner:$.owner??null,clientRunId:$.clientRunId,frames:[],lastSeq:-1,lostBefore:0,ended:!1,evicted:!1,evictAt:null,expireAt:null,wake:new Set,version:0};if(this.runs.set(Q.runId,Z),$.threadId)this.byThread.set($.threadId,Q.runId);if($.clientRunId)this.byClientRun.set($.clientRunId,Q.runId);return this.scheduleExpiry(Z,$.maxRunDurationMs),this.pump(Z,$)}findByClientRunId(Q){let $=this.byClientRun.get(Q);return $&&this.runs.has($)?$:null}async find(Q){let $=this.byThread.get(Q.threadId);if(!$)return null;let Z=this.runs.get($);if(!Z)return null;return{runId:$,seq:Z.lastSeq}}get(Q){return this.runs.get(Q)?.run??null}ownerOf(Q){return this.runs.get(Q)?.owner??null}mayAccess(Q,$){let Z=this.ownerOf(Q);return Z===null||Z===$}isRunning(Q){let $=this.runs.get(Q);return!!$&&!$.ended&&!$.evicted}replay(Q,$){let Z=this.runs.get(Q);if(!Z)throw new JQ(Q);if($!==void 0&&$<Z.lostBefore)throw new o(Q,$,Z.lostBefore);let J=Z.frames[0]?.seq;return this.drain(Z,Q,$??J??Z.lastSeq+1)}clear(){for(let Q of this.runs.values()){if(Q.evictAt)clearTimeout(Q.evictAt);if(Q.expireAt)clearTimeout(Q.expireAt);Q.ended=!0,this.notify(Q)}this.runs.clear(),this.byThread.clear(),this.byClientRun.clear()}get size(){return this.runs.size}async pump(Q,$){let Z=Promise.resolve();try{for await(let J of Q.run.frames()){if(Q.evicted){let X=$.onEvent;if(X)Z=Z.then(()=>X(J.event)).catch((G)=>R9($,G));continue}if(Q.frames.push(J),Q.lastSeq=J.seq,Q.frames.length>this.maxFrames){let X=Q.frames.shift();if(X)Q.lostBefore=X.seq+1}this.notify(Q);let W=$.onEvent;if(W)Z=Z.then(()=>W(J.event)).catch((X)=>R9($,X))}}catch(J){R9($,J)}finally{if(Q.ended=!0,Q.expireAt)clearTimeout(Q.expireAt),Q.expireAt=null;this.notify(Q),this.scheduleEviction(Q),await Z}}async*drain(Q,$,Z){let J=Z;while(!0){let W=Q.version;for(;;){if(J<Q.lostBefore)throw new o($,J,Q.lostBefore);let X=Q.frames,G=X[0]?.seq;if(G===void 0)break;let Y=Math.max(0,J-G);if(Y>=X.length)break;let V=X[Y];yield V,J=V.seq+1}if(Q.ended&&J>Q.lastSeq||Q.evicted)return;await this.wait(Q,W)}}wait(Q,$){if(Q.version!==$)return Promise.resolve();return new Promise((Z)=>Q.wake.add(Z))}notify(Q){Q.version++;let $=Array.from(Q.wake);Q.wake.clear();for(let Z of $)Z()}scheduleEviction(Q){if(Q.evictAt)return;let $=setTimeout(()=>{let Z=Q.run.runId;if(!Q.ended)Q.evicted=!0,Q.frames=[];if(this.runs.get(Z)===Q)this.runs.delete(Z);if(Q.threadId&&this.byThread.get(Q.threadId)===Z)this.byThread.delete(Q.threadId);if(Q.clientRunId&&this.byClientRun.get(Q.clientRunId)===Z)this.byClientRun.delete(Q.clientRunId);this.notify(Q)},this.ttlMs);$.unref?.(),Q.evictAt=$}scheduleExpiry(Q,$){if(this.maxAgeMs===null||$===null)return;let Z=$===void 0?this.maxAgeMs:Math.max(this.maxAgeMs,$+this.ttlMs);if(!Number.isFinite(Z)||Z>2147483647)return;let J=setTimeout(()=>{if(Q.expireAt=null,Q.ended)return;try{Q.run.stop({reason:`The run was still going ${Math.round(Z/1000)}s after it started, past the live-run registry's age limit.`})}catch{}this.scheduleEviction(Q)},Z);J.unref?.(),Q.expireAt=J}}var k9=new AQ;function R9(Q,$){try{Q.onInternalError?.($)}catch{}}class xQ{maxEntries;records=new Map;constructor(Q=1e5){this.maxEntries=Q}async record(Q,$){if(this.records.has(Q))return;this.records.set(Q,{...$});while(this.records.size>this.maxEntries){let Z=this.records.keys().next().value;if(Z===void 0)break;this.records.delete(Z)}}async get(Q){let $=this.records.get(Q);return $?{...$}:null}}var T9=new xQ;class EQ{ttlMs;clientOwnedIds;threads=new Map;lastSweep=0;constructor(Q={}){this.ttlMs=Q.ttlMs??86400000,this.clientOwnedIds=Q.clientOwnedIds??!1}async createThread(Q){let $=crypto.randomUUID();return this.threads.set($,{messages:[],touchedAt:Date.now()}),this.sweep(),{threadId:$}}async loadThread(Q){this.sweep();let $=this.threads.get(Q);if(!$)return this.clientOwnedIds?[]:null;return $.touchedAt=Date.now(),$.messages.slice()}async appendMessages(Q,$){this.sweep();let Z=this.threads.get(Q);if(!Z){if(!this.clientOwnedIds)throw Error(`Thread ${Q} does not exist here, or has expired.`);Z={messages:[],touchedAt:Date.now()},this.threads.set(Q,Z)}for(let J of $){let W=Z.messages.findIndex((X)=>X.id===J.id);if(W===-1)Z.messages.push(J);else Z.messages[W]=J}Z.touchedAt=Date.now()}async removeMessages(Q,$){this.sweep();let Z=this.threads.get(Q);if(!Z)return;let J=new Set($);Z.messages=Z.messages.filter((W)=>!J.has(W.id)),Z.touchedAt=Date.now()}delete(Q){this.threads.delete(Q)}get size(){return this.threads.size}sweep(Q=Date.now()){if(Q-this.lastSweep<60000)return;this.lastSweep=Q;for(let[$,Z]of this.threads)if(Q-Z.touchedAt>this.ttlMs)this.threads.delete($)}}var A9=new EQ;function d$(Q={}){return{messages:Q.messages?[...Q.messages]:[],pending:Q.pending?[...Q.pending]:[],error:null,threadId:Q.threadId,seq:Q.seq??-1,cursorRunId:Q.cursorRunId,runMessageIds:[],loadedTools:[]}}function l$(Q,$,Z=new Date().toISOString()){if(!($.event.type==="run-start"&&$.event.runId!==Q.cursorRunId)&&$.seq<=Q.seq)return Q;return{...i$(Q,$.event,Z),seq:$.seq}}function i$(Q,$,Z){switch($.type){case"run-start":return{...Q,runId:$.runId,cursorRunId:$.runId,threadId:$.threadId??Q.threadId,runMessageIds:[],loadedTools:[],finishReason:void 0,usage:void 0};case"message-start":return u(Q,$.messageId,Z,(J)=>({...J,role:$.role}));case"text-delta":if(m$(Q,$.messageId))return Q;return u(Q,$.messageId,Z,(J)=>({...J,content:vZ(J.content,$.delta)}));case"reasoning-delta":if(m$(Q,$.messageId))return Q;return u(Q,$.messageId,Z,(J)=>({...J,content:fZ(J.content,$.delta,$.id)}));case"output-delta":return u(Q,$.messageId,Z,(J)=>({...J,content:p$(J.content,{type:"output",value:$.snapshot,partial:!0},(W)=>W.type==="output")}));case"tool-call":return u(Q,$.messageId,Z,(J)=>{let W=J.content.findIndex((z)=>z.type==="tool-call"&&z.toolCallId===$.part.toolCallId),X=W===-1?void 0:J.content[W],G=$.part.progress??X?.progress,Y=$.part.nested??X?.nested,V=$.part.attachments??X?.attachments,H={...$.part,...G?{progress:G}:{},...Y?{nested:Y}:{},...V?{attachments:V}:{}},K=J.content.slice();if(W===-1)K.push(H);else K[W]=H;return{...J,content:K}});case"tool-search":{let J=$.loaded.filter((W)=>!Q.loadedTools.includes(W));if(J.length===0)return Q;return{...Q,loadedTools:[...Q.loadedTools,...J]}}case"tool-progress":return c$(Q,$.toolCallId,(J)=>({...J,progress:[...J.progress??[],$.data]}));case"nested-event":{let J=$;return c$(Q,$.toolCallId,(W)=>{let X=W.nested??[],G=X.findIndex((K)=>K.runId===J.runId),Y=X[G]??{runId:J.runId,agent:J.agent,messages:[]},V=wZ(Y,J,Z),H=G===-1?[...X,V]:X.map((K,z)=>z===G?V:K);return{...W,nested:H}})}case"tool-result":{let J=u(Q,$.messageId,Z,(W)=>({...W,content:p$(W.content,$.part,(X)=>X.type==="tool-result"&&X.toolCallId===$.part.toolCallId)}));return{...J,pending:J.pending.filter((W)=>W.toolCallId!==$.part.toolCallId)}}case"message":{let J=Q.messages.findIndex((G)=>G.id===$.message.id),W=Q.messages.slice();if(J===-1)W.push($.message);else W[J]=$.message;let X=Q.runMessageIds.includes($.message.id)?Q.runMessageIds:[...Q.runMessageIds,$.message.id];return{...Q,messages:W,runMessageIds:X}}case"awaiting-input":return{...Q,runId:$.runId,pending:[...$.pending]};case"message-end":return u(Q,$.messageId,Z,(J)=>({...J,finishReason:$.finishReason,...$.outputTruncated?{outputTruncated:!0}:{},...$.usage?{usage:$.usage}:{},content:$.outputTruncated||$.finishReason==="length"?J.content.filter((W)=>!(W.type==="output"&&W.partial)):J.content.map((W)=>W.type==="output"&&W.partial?{...W,partial:!1}:W)}));case"usage":return{...Q,usage:$.usage};case"error":return{...Q,error:$.error,pending:[]};case"run-end":return{...Q,runId:void 0,finishReason:$.finishReason,messages:o$(Q,$.finishReason)};default:return Q}}function o$(Q,$){return Q.messages.map((Z)=>Z.role==="assistant"&&Q.runMessageIds.includes(Z.id)?EZ(Z,$):Z)}function EZ(Q,$){let Z=Q.content.map((W)=>W.type==="tool-call"&&W.nested?.some((X)=>X.finishReason===void 0)?{...W,nested:W.nested.map((X)=>X.finishReason===void 0?bZ(X,$):X)}:W);if(Q.finishReason===void 0)return{...Q,finishReason:$,content:Z};return Z.some((W,X)=>W!==Q.content[X])?{...Q,content:Z}:Q}function bZ(Q,$){let Z={messages:Q.messages,pending:[],error:null,seq:-1,runMessageIds:Q.messages.map((J)=>J.id),loadedTools:[]};return{...Q,finishReason:$,messages:o$(Z,$)}}function c$(Q,$,Z){for(let J=Q.messages.length-1;J>=0;J--){let W=Q.messages[J],X=W.content.findIndex((H)=>H.type==="tool-call"&&H.toolCallId===$);if(X===-1)continue;if(W.finishReason!==void 0&&!IZ(Q,W,$))return Q;let G=W.content.slice();G[X]=Z(G[X]);let Y=Q.messages.slice();Y[J]={...W,content:G};let V=Q.runMessageIds.includes(W.id)?Q.runMessageIds:[...Q.runMessageIds,W.id];return{...Q,runMessageIds:V,messages:Y}}return Q}function wZ(Q,$,Z){let J={messages:Q.messages,pending:[],error:null,seq:-1,runMessageIds:Q.messages.map((X)=>X.id),loadedTools:[],finishReason:Q.finishReason},W=i$(J,$.event,Z);return{...Q,...$.label!==void 0?{label:$.label}:{},messages:W.messages,...W.finishReason!==void 0?{finishReason:W.finishReason}:{},...W.usage!==void 0?{usage:W.usage}:{}}}function IZ(Q,$,Z){if($.finishReason!=="awaiting-input")return!1;return!Q.messages.some((J)=>J.content.some((W)=>W.type==="tool-result"&&W.toolCallId===Z))}function m$(Q,$){let Z=Q.messages.find((J)=>J.id===$);return Z!==void 0&&Z.finishReason!==void 0}function u(Q,$,Z,J){let W=Q.messages.findIndex((Y)=>Y.id===$),X=Q.runMessageIds.includes($)?Q.runMessageIds:[...Q.runMessageIds,$];if(W===-1){let Y={id:$,role:"assistant",content:[],createdAt:Z};return{...Q,runMessageIds:X,messages:[...Q.messages,J(Y)]}}let G=Q.messages.slice();return G[W]=J(G[W]),{...Q,runMessageIds:X,messages:G}}function vZ(Q,$){let Z=Q[Q.length-1];if(Z&&Z.type==="text")return[...Q.slice(0,-1),{type:"text",text:Z.text+$}];return[...Q,{type:"text",text:$}]}function fZ(Q,$,Z){let J=Q[Q.length-1];if(J&&J.type==="reasoning"&&J.id===Z)return[...Q.slice(0,-1),{...J,text:(J.text??"")+$}];return[...Q,Z?{type:"reasoning",id:Z,text:$}:{type:"reasoning",text:$}]}function p$(Q,$,Z){let J=Q.findIndex(Z);if(J===-1)return[...Q,$];let W=Q.slice();return W[J]=$,W}class E9{store;threadId;report;chain=Promise.resolve();done=new Set;closed=!1;state;runId;constructor(Q,$,Z,J){this.store=Q;this.threadId=$;this.report=J;this.state=d$({messages:Z})}finish(Q){if(this.closed)return;this.done.add(Q.id),this.write(()=>[x9(Q)])}frame(Q){if(this.closed)return;let $=Q.event;if($.type==="run-start")this.runId=$.runId;switch(this.state=l$(this.state,Q),$.type){case"message":this.write(()=>[x9($.message)]);return;case"tool-call":if($.part.partial)return;this.checkpoint($.messageId);return;case"message-start":case"tool-result":this.checkpoint($.messageId);return;default:return}}close(Q=[]){this.closed=!0;for(let $ of Q)this.done.add($.id)}settled(){return this.chain}checkpoint(Q){if(this.done.has(Q))return;let $=this.state.messages.find((J)=>J.id===Q);if(!$)return;let Z=this.runId;this.write(()=>{let J=x9($);if(J.finishReason===void 0&&Z)J.runId=Z;return[J]})}write(Q){let $;try{$=Q()}catch(Z){this.report(Z);return}this.chain=this.chain.then(()=>this.store.appendMessages(this.threadId,$)).catch((Z)=>this.report(Z))}}function x9(Q){return structuredClone(Q)}async function n$(Q,$){let Z=[],J=null,W=Q.slice();for(let X=0;X<W.length;X++){let G=W[X];if(G.role!=="assistant"||G.finishReason!==void 0)continue;if(G.runId&&await $(G.runId))continue;J??=new Set(Q.flatMap((H)=>H.content.flatMap((K)=>K.type==="tool-result"?[K.toolCallId]:[])));let Y=G.content.map((H)=>H.type==="tool-call"?s$(H):H);for(let H of G.content){if(H.type!=="tool-call"||J.has(H.toolCallId))continue;let K={type:"tool-result",toolCallId:H.toolCallId,name:H.name,status:"denied",cause:"interrupted"};Y.push(K)}let V={...G,content:Y,finishReason:"interrupted"};W[X]=V,Z.push(V)}return{messages:W,settled:Z}}function s$(Q){let{partial:$,...Z}=Q;if(!Z.nested?.some((J)=>J.finishReason===void 0))return Z;return{...Z,nested:Z.nested.map(hZ)}}function hZ(Q){if(Q.finishReason!==void 0)return Q;return{...Q,finishReason:"interrupted",messages:Q.messages.map(($)=>$.role==="assistant"&&$.finishReason===void 0?{...$,finishReason:"interrupted",content:$.content.map((Z)=>Z.type==="tool-call"?s$(Z):Z)}:$)}}var yZ=X3,bQ=new Map,t$=new WeakMap,wQ=new Map,gZ=4194304,uZ=1000,cZ=5,a$=65536,K3=()=>{};class z3{byKey=new Map;take(Q,$,Z){let J=this.byKey.get(Q);if(!J?.has($)&&(J?.size??0)>=Z)return null;if(!J)J=new Map,this.byKey.set(Q,J);J.set($,(J.get($)??0)+1);let W=!1;return()=>{if(W)return;W=!0;let X=this.byKey.get(Q),G=(X?.get($)??1)-1;if(!X)return;if(G>0)X.set($,G);else if(X.delete($),X.size===0)this.byKey.delete(Q)}}}var r$=new WeakMap;function mZ(Q){let $=r$.get(Q);if(!$)$=new z3,r$.set(Q,$);return $}class B3 extends yZ{static kind="agent-controller";store=A9;liveRuns=k9;attachments=PQ;attachmentStorage=H3;fileOwners=T9;nonces=m;requireKnownFiles=!1;hookHoldMs=30000;instructions(Q,$){}context(Q,$){return{}}requireThread=!1;maxBodyBytes=gZ;maxHistoryMessages=uZ;maxConcurrentRuns=cZ;runLimitKey(Q,$){return $.owner}authorizeRequest(Q,$){}runOwner(Q){let $=Q.ctx?.()?.user,Z=$?.id??$?.publicId;if(Z!==void 0&&Z!==null&&String(Z)!=="")return`user:${String(Z)}`;return null}async stream(Q=new WQ){let $=await b9(Q,this.maxBodyBytes);if($.error)return IQ($);let Z=$.body,J=typeof Z.threadId==="string"?Z.threadId:void 0,W=tZ(Z);if(W.error)return IQ({body:{},error:W.error});let X=W.turn,G=J!==void 0&&Z.regenerate===!0,Y=typeof Z.clientRunId==="string"?Z.clientRunId:void 0,V=U3(Z);if(this.requireThread&&!J)return M(400,{code:"thread_required",message:"This agent takes a turn only on a thread: send a threadId."});if(G&&!this.store.removeMessages)return M(501,{code:"regenerate_unsupported",message:"This agent's store cannot remove messages, so a thread's answer cannot be regenerated. Implement `removeMessages` on the AgentStore."});if(!J&&Array.isArray(Z.messages)&&Z.messages.length>this.maxHistoryMessages)return v9(413,"history_too_long",`The conversation has ${Z.messages.length} messages; this agent takes at most ${this.maxHistoryMessages}.`);let H=await this.runOwner(Q),K=Y?{cancelled:!1,owner:H}:null;if(K)wQ.set(Y,K);let z=null,B=[],D=async()=>{try{return await F()}finally{if(J&&B.length>0&&z===null)await this.store.appendMessages(J,B).catch((U)=>this.reportHookFailure(U))}},F=async()=>{let U;if(J){let S=await this.store.loadThread(J);if(!S)return M(404,{code:"thread_not_found",message:`Thread ${J} does not exist here, or has expired.`});if(U=await this.settleThread(J,S,{write:!0}),G){let c=Q6(U);if(!c)return M(409,{code:"nothing_to_regenerate",message:`Thread ${J} has no user turn to answer again.`});B=U.slice(c.index),await this.store.removeMessages(J,B.map((L3)=>L3.id)),U=U.slice(0,c.index),X=c.turn}}else U=Array.isArray(Z.messages)?Z.messages:[],V6(this.nonces);let L=await this.instructions(Q,{body:V})||void 0,C=await this.context(Q,{body:V}),R=await this.attachmentsFor(Q,J,{body:V});if(K?.cancelled)return Z3();let j=J?new E9(this.store,J,U,(S)=>this.reportHookFailure(S)):null,b=`run_${crypto.randomUUID()}`,k={req:Q,runId:b,threadId:J},N=this.agent.stream({runId:b,messages:U,turn:X,threadId:J,...j?{onMessage:(S)=>j.finish(S)}:{},instructions:L,context:C,attachments:R,body:V,redactError:(S,c)=>this.redactError(S,c,k),nonces:this.nonces,subject:H}),P=this.liveRuns.register(N,{threadId:J,owner:H,clientRunId:Y,onEvent:(S)=>this.dispatchEvent(S,k),onInternalError:(S)=>this.reportHookFailure(S),maxRunDurationMs:this.agent.maxRunDurationMs});if(z=N,j)this.follow(N,j);let{stored:w,hooks:XQ}=this.persistRun(N,k,P,j);return t$.set(N,w),Q.ctx?.()?.waitUntil(XQ),N.toResponse()};try{await this.authorizeRequest(Q,{route:"stream",threadId:J,body:V});let U=await this.foreignFile([...X?.files??[],...J?[]:Z6(Z.messages)],H);if(U)return U;if(K?.cancelled)return Z3();let L=await this.runLimitKey(Q,{owner:H,threadId:J}),C=L===null?K3:mZ(this.liveRuns).take(L,J?`thread:${J}`:`run:${crypto.randomUUID()}`,this.maxConcurrentRuns);if(!C)return v9(429,"too_many_runs",`You already have ${this.maxConcurrentRuns} conversations answering. Wait for one to finish, or stop it, and send again.`);try{return J?await this.withThread(J,H,D):await D()}finally{let R=z;if(R)R.result().then(C,C);else C()}}finally{if(K&&wQ.get(Y)===K)wQ.delete(Y)}}async withThread(Q,$,Z){let J=bQ.get(Q)??Promise.resolve(),W,X=new Promise((Y)=>{W=Y}),G=J.then(()=>X);bQ.set(Q,G),await J;try{let Y=await this.liveRuns.find({threadId:Q});if(Y&&this.liveRuns.isRunning(Y.runId)&&!this.liveRuns.mayAccess(Y.runId,$))return vQ();let V=Y?this.liveRuns.get(Y.runId):null;if(V)V.stop({reason:"superseded by a later turn on this thread"}),await t$.get(V);return await Z()}finally{if(W(),bQ.get(Q)===G)bQ.delete(Q)}}async attach(Q=new WQ){let $=await b9(Q,a$);if($.error)return IQ($);let Z=$.body,J=typeof Z.threadId==="string"?Z.threadId:eZ(Q,"threadId");if(!J)return M(400,{code:"invalid_request",message:"attach needs a threadId: it is the handle that survives a refresh."});await this.authorizeRequest(Q,{route:"attach",threadId:J});let W=await this.liveRuns.find({threadId:J});if(W&&!this.liveRuns.mayAccess(W.runId,await this.runOwner(Q)))return vQ();if(!W)return M(404,{code:"no_live_run",message:`No run in progress for thread ${J} in this process.`});let X=typeof Z.runId==="string"?Z.runId:void 0,G=X&&X!==W.runId?void 0:rZ(Q,Z);try{return X$(this.liveRuns.replay(W.runId,G))}catch(Y){if(Y instanceof o)return M(410,{code:Y.code,message:Y.message,oldestSeq:Y.oldest});if(Y instanceof JQ)return M(404,{code:Y.code,message:Y.message});throw Y}}async stop(Q=new WQ){let $=await b9(Q,a$);if($.error)return IQ($);let Z=$.body;await this.authorizeRequest(Q,{route:"stop",threadId:typeof Z.threadId==="string"?Z.threadId:void 0});let J=await this.runOwner(Q),W=typeof Z.runId==="string"?Z.runId:void 0;if(!W&&typeof Z.clientRunId==="string"){if(W=this.liveRuns.findByClientRunId(Z.clientRunId)??void 0,!W){let G=wQ.get(Z.clientRunId);if(G){if(G.owner!==null&&G.owner!==J)return vQ();return G.cancelled=!0,{stopped:!0}}}}if(!W&&typeof Z.threadId==="string")W=(await this.liveRuns.find({threadId:Z.threadId}))?.runId;let X=W?this.liveRuns.get(W):null;if(!X)return{stopped:!1};if(!this.liveRuns.mayAccess(X.runId,J))return vQ();return X.stop({reason:typeof Z.reason==="string"?Z.reason:void 0}),{stopped:!0}}attachmentScope(Q,$,Z){let J=Q.ctx()?.user,W=J?.id??J?.publicId;if(W!==void 0&&W!==null&&String(W)!=="")return{key:`user:${String(W)}`};if($)return{key:`thread:${$}`};return null}attachmentLimits(Q){return null}attachmentDestination(Q,$){return"both"}async attachmentsFor(Q,$,Z={body:{}}){let J=await this.attachmentScope(Q,$,Z);if(!J)return null;return new QQ(this.attachments,this.attachmentStorage,J)}async upload(Q=new WQ){let $=await Q.rawRequest.formData(),Z=$.get("file");if(!(Z instanceof Blob))throw Error("upload expects a multipart body with a `file` field.");let J=Z instanceof File&&Z.name?Z.name:"upload",W=Z.type||"application/octet-stream",X=dZ($.get("body")),G=$.get("threadId");await this.authorizeRequest(Q,{route:"upload",threadId:typeof G==="string"&&G.length>0?G:void 0,body:X});let Y=iZ(await this.attachmentLimits(Q),Z,J,W);if(Y)throw new D3(Y.code,Y.message);let V=typeof G==="string"&&G.length>0&&await this.store.loadThread(G)!==null?G:void 0,H=await this.runOwner(Q),K=(j)=>this.fileOwners.record(j,{owner:H,name:J,mimeType:W,size:Z.size,createdAt:new Date().toISOString()}),z=await this.attachmentDestination(Z,Q),B=J6(z,$.get("destination")),D=await this.attachmentScope(Q,V,{body:X}),F=B!=="provider"&&!D;if(F){if(B==="storage")throw Error('This upload was routed to storage, but `attachmentScope()` returned null for the request, so there is no subject to file the attachment under. Guard the route (`this.agent(Chat).middleware({ upload: "auth" })`), send a `threadId` with the upload, or override `attachmentScope()`.');W6()}if(B==="provider"||!D){let j=await e$(this.agent.provider,Z);await K(j);let b={fileId:j,name:J,mimeType:W,size:Z.size,destination:"provider"};if(F)b.downgraded="no_scope";return b}let U=oQ(),L=await this.attachmentStorage.put({name:nQ(U,J),body:Z,contentType:W}),C=B==="both"?await e$(this.agent.provider,Z):void 0;if(C)await K(C);let R={id:U,scopeKey:D.key,fileId:C,objectName:L,name:J,mimeType:W,size:Z.size,createdAt:new Date().toISOString(),destination:B};return await this.attachments.put(D,R),{fileId:C,attachmentId:U,name:J,mimeType:W,size:Z.size,destination:B}}async foreignFile(Q,$){let Z=new Set(Q.map((J)=>J.fileId).filter((J)=>typeof J==="string"));for(let J of Z){let W=await this.fileOwners.get(J);if(W?W.owner!==null&&W.owner!==$:this.requireKnownFiles)return $6()}return null}onMessage(Q,$){}onToolCall(Q,$){}onAwaitingInput(Q,$){}redactError(Q,$,Z){return f9(Q,$)}onError(Q,$){}onStreamComplete(Q,$){}reportHookFailure(Q){console.error("[gemi/ai] agent controller hook failed",Q)}async dispatchEvent(Q,$){switch(Q.type){case"tool-call":if(!Q.part.partial&&!Q.resent)await this.onToolCall({toolCallId:Q.part.toolCallId,name:String(Q.part.name),input:Q.part.input},$);return;case"awaiting-input":await this.onAwaitingInput(Q.pending,$);return;case"error":await this.onError(Y3(Q.error),$);return;default:return}}async readThread(Q){let $=await this.store.loadThread(Q);return $?await this.settleThread(Q,$,{write:!1}):null}isRunLive(Q,$){return this.liveRuns.get(Q)!==null}async settleThread(Q,$,{write:Z}){let{messages:J,settled:W}=await n$($,(X)=>this.isRunLive(X,Q));if(Z&&W.length>0)try{await this.store.appendMessages(Q,W)}catch(X){this.reportHookFailure(X)}return J}follow(Q,$){(async()=>{try{for await(let Z of Q.frames())$.frame(Z)}catch(Z){this.reportHookFailure(Z)}})()}persistRun(Q,$,Z,J=null){let W=Promise.resolve(),X=(async()=>{let Y;try{Y=await Q.result()}catch(H){J?.close(),await J?.settled(),W=this.safely(()=>this.onError({code:"unknown",message:H instanceof Error?H.message:String(H),retryable:!1},$));return}let V=Y.messages;if(J?.close(V),await J?.settled(),$.threadId&&V.length>0)try{await this.store.appendMessages($.threadId,V)}catch(H){this.reportHookFailure(H)}W=this.notifyRun(Y,V,$)})(),G=X.then(()=>G6(Promise.all([W,Z]).then(()=>{}),this.hookHoldMs));return{stored:X,hooks:G}}async notifyRun(Q,$,Z){for(let J of $)await this.safely(()=>this.onMessage(J,Z));await this.safely(()=>this.onStreamComplete(Q,Z))}async safely(Q){try{await Q()}catch($){this.reportHookFailure($)}}}var w9=["turn","clientRunId","threadId","messages","regenerate"],pZ=["text","files","toolResults"];function U3(Q,$=C3(Q)?w9:[...w9,...pZ]){let Z={};for(let[J,W]of Object.entries(Q)){if($.includes(J))continue;Object.defineProperty(Z,J,{value:W,writable:!0,enumerable:!0,configurable:!0})}return Z}function dZ(Q){if(Q===null)return{};let $;if(typeof Q==="string")try{$=JSON.parse(Q)}catch{throw new I9("The upload's `body` field is not valid JSON.")}if($===null||typeof $!=="object"||Array.isArray($))throw new I9("The upload's `body` field must be a JSON object.");return U3($,w9)}class I9 extends fQ{constructor(Q){super(Q);this.name="InvalidUploadError",this.payload={api:{status:400,data:{error:{code:"invalid_request",message:Q}}},view:{}}}}async function e$(Q,$){try{return await Q.upload($)}catch(Z){if(Z instanceof I&&lZ.has(Z.status))throw new F3(_(Z).message);throw Z}}var lZ=new Set([400,413,415,422]);class D3 extends fQ{constructor(Q,$){super($);this.name="LimitedUploadError",this.payload={api:{status:422,data:{error:{code:Q,message:$}}},view:{}}}}function iZ(Q,$,Z,J){if(!Q)return null;let{maxBytes:W,accept:X}=Q;if(typeof W==="number"&&$.size>W)return{code:"file_too_large",message:`${JSON.stringify(Z)} is ${Q3($.size)}; the limit is ${Q3(W)}.`};if(X&&X.length>0&&!X.some((G)=>oZ(G,Z,J)))return{code:"unsupported_file_type",message:`${JSON.stringify(Z)} is not a type this chat accepts. Accepted: ${X.join(", ")}.`};return null}function oZ(Q,$,Z){let J=Q.trim().toLowerCase();if(!J)return!1;if(J.startsWith("."))return $.toLowerCase().endsWith(J);let W=Z.toLowerCase().split(";")[0].trim();if(J.endsWith("/*"))return W.startsWith(J.slice(0,-1));return W===J}function Q3(Q){if(Q<1024)return`${Q} B`;let $=["KB","MB","GB"],Z=Q/1024,J=0;while(Z>=1024&&J<$.length-1)Z/=1024,J++;return`${Math.round(Z*10)/10} ${$[J]}`}class F3 extends fQ{constructor(Q){super(Q);this.name="RejectedUploadError";let $=/(unsupported|invalid) (extension|file type|format|mime)|supported (extensions|formats?)/i.test(Q)?"unsupported_file_type":"file_rejected";this.payload={api:{status:422,data:{error:{code:$,message:Q}}},view:{}}}}async function b9(Q,$){let Z=Q?.rawRequest;if(!Z||Z.method==="GET"||Z.method==="HEAD"||!Z.body)return{body:{}};if(!nZ(Z.headers.get("Content-Type")))return{body:{},status:415,code:"unsupported_media_type",error:"The request body must be sent as application/json."};let J=Number(Z.headers.get("Content-Length"));if(Number.isFinite(J)&&J>$)return $3($);let W;try{let G=await sZ(Z,$);if(G===null)return $3($);W=G}catch{return{body:{},error:"The request body could not be read."}}if(!W.trim())return{body:{}};let X;try{X=JSON.parse(W)}catch{return{body:{},error:"The request body is not valid JSON."}}if(X===null||typeof X!=="object"||Array.isArray(X))return{body:{},error:"The request body must be a JSON object."};return{body:X}}function nZ(Q){return V3(Q)==="application/json"}async function sZ(Q,$){if(!Number.isFinite($)||!Q.body)return await Q.text();let Z=Q.body.getReader(),J=[],W=0;for(;;){let{done:Y,value:V}=await Z.read();if(Y)break;if(W+=V.byteLength,W>$)return await Z.cancel().catch(K3),null;J.push(V)}let X=new Uint8Array(W),G=0;for(let Y of J)X.set(Y,G),G+=Y.byteLength;return new TextDecoder().decode(X)}function $3(Q){return{body:{},status:413,code:"body_too_large",error:`The request body is larger than this agent accepts (${Q} bytes).`}}function v9(Q,$,Z){return M(Q,{...hQ(G3(Q),Z,Q),code:$})}function IQ(Q){if(Q.status===413)return v9(413,Q.code??"body_too_large",Q.error??"");return M(Q.status??400,{code:Q.code??"invalid_request",message:Q.error})}function C3(Q){return Boolean(Q.turn)&&typeof Q.turn==="object"}function tZ(Q){let $=C3(Q)?Q.turn:Q,Z={};if(typeof $.text==="string")Z.text=$.text;if(Array.isArray($.files)){let J=aZ($.files);if(typeof J==="string")return{error:J};Z.files=J}if(Array.isArray($.toolResults))Z.toolResults=$.toolResults;return Object.keys(Z).length>0?{turn:Z}:{}}function aZ(Q){let $=[];for(let[Z,J]of Q.entries()){let W=`turn.files[${Z}]`;if(!J||typeof J!=="object"||Array.isArray(J))return`${W} must be an object.`;let X={};for(let K of["fileId","attachmentId","name","mimeType"]){let z=J[K];if(z===void 0||z===null||z==="")continue;if(typeof z!=="string")return`${W}.${K} must be a string.`;X[K]=z}let{fileId:G,attachmentId:Y,name:V,mimeType:H}=X;if(G?.startsWith(x))return`${W}.fileId holds a gemi attachment id (${G}). \`fileId\` is the provider's id from the upload response; put this one in \`attachmentId\`.`;if(Y!==void 0&&!Y.startsWith(x))return`${W}.attachmentId is not a gemi attachment id: it must start with "${x}".`;if(!G&&!Y)return`${W} has neither a \`fileId\` nor an \`attachmentId\`. Send the ids the upload response answered.`;$.push({...G?{fileId:G}:{},...Y?{attachmentId:Y}:{},...V!==void 0?{name:V}:{},...H!==void 0?{mimeType:H}:{}})}return $}function rZ(Q,$){if(typeof $.from==="number"&&Number.isFinite($.from))return Math.max(0,Math.floor($.from));if(typeof $.cursor==="number"&&Number.isFinite($.cursor)){let J=Math.floor($.cursor);if(J>=0)return J+1;return}let Z=Q?.rawRequest?.headers?.get("Last-Event-ID");if(Z){let J=Number.parseInt(Z,10);if(Number.isFinite(J))return Math.max(0,J+1)}return}function eZ(Q,$){let Z=Q?.search?.get($);return typeof Z==="string"?Z:void 0}function Q6(Q){let $=OQ(Q);for(let Z=Q.length-1;Z>=0;Z--){let J=Q[Z];if(J.role!=="user"||$.has(J.id))continue;let W="",X=[];for(let G of J.content){if(G.type==="text")W+=G.text;if(G.type==="file")X.push({...G.fileId?{fileId:G.fileId}:{},...G.attachmentId?{attachmentId:G.attachmentId}:{},...G.name?{name:G.name}:{},...G.mimeType?{mimeType:G.mimeType}:{}})}if(!W&&X.length===0)continue;return{index:Z,turn:{...W?{text:W}:{},...X.length>0?{files:X}:{}}}}return null}function Z3(){return M(409,{code:"stopped",message:"The turn was stopped before it started."})}function vQ(){return M(403,hQ("permission","This run belongs to someone else.",403))}function $6(){return M(403,hQ("permission","A file in this turn was uploaded by someone else.",403))}function Z6(Q){if(!Array.isArray(Q))return[];let $=[];for(let Z of Q){let J=Z?.content;if(!Array.isArray(J))continue;for(let W of J)if(W&&typeof W==="object"&&typeof W.fileId==="string")$.push({fileId:W.fileId})}return $}function M(Q,$){return new Response(JSON.stringify({error:$}),{status:Q,headers:{"Content-Type":"application/json"}})}function J6(Q,$){if(typeof $!=="string"||$.length===0)return Q;if($!=="both"&&$!=="provider"&&$!=="storage")throw Error(`Unknown attachment destination "${$}". Expected "both", "provider" or "storage".`);if($===Q||Q==="both"&&$==="storage")return $;if(Q==="both"&&$==="provider")throw Error('This upload asked for the "provider" destination under a "both" policy. A client may ask for "storage", which keeps a file away from the model provider, but it may not ask the server to stop keeping its own copy while the vendor still gets the file \u2014 that is the app\'s retention decision. Change `attachmentDestination()` if this file should not be kept.');throw Error(`This upload asked for the "${$}" destination, but the server's policy for it is "${Q}", and a client hint may only ask for "storage" under a "both" policy. Change \`attachmentDestination()\` if the file really should go there.`)}var J3=!1;function W6(){if(J3)return;J3=!0,console.warn("[gemi/ai] An upload had no attachment scope, so its bytes were sent to the model provider only and no attachment id was minted \u2014 a tool cannot forward this file. Guard the route with auth, send a `threadId` with the upload, or override `attachmentScope()`.")}var X6=2147483647;function G6(Q,$){let Z=Q.then(()=>{},()=>{});if(!($<=X6))return Z;let J,W=new Promise((X)=>{J=setTimeout(X,$)});return Promise.race([Z,W]).finally(()=>clearTimeout(J))}var W3=!1;function V6(Q){if(W3||Bun.env.NODE_ENV!=="production")return;if(!(Q instanceof r))return;W3=!0,console.warn("[gemi/ai] A stateless agent chat is spending approval nonces in process memory. With more than one instance a replayed approval is accepted once per instance. Set `nonces = new RedisNonceStore()` (or your own NonceStore) on the AgentController.")}export{a3 as toAgentTools,n as supportsStrict,Y6 as s,f9 as redactError,k9 as liveRuns,q3 as generate,m as defaultNonceStore,T9 as defaultFileOwners,PQ as defaultAttachmentStore,A9 as defaultAgentStore,_Q as ToolNamespace,O as ToolError,J9 as Skill,QQ as ScopedAttachments,$Q as SKILLS_NAMESPACE,uQ as RedisNonceStore,h as PendingEscalation,M9 as OpenAIProvider,z9 as OpenAIImageProvider,r as MemoryNonceStore,AQ as MemoryLiveRuns,xQ as MemoryFileOwners,LQ as MemoryAttachmentStore,EQ as MemoryAgentStore,JQ as LiveRunNotFoundError,H6 as JSONSchemaError,d as InvalidAttachmentScopeError,SQ as ImageRequestError,RQ as ImageProvider,H9 as ImageModel,o as FrameCursorEvictedError,G9 as DEFAULT_MAX_RUN_DURATION_MS,S9 as AzureOpenAIProvider,B9 as AzureOpenAIImageProvider,e as AttachmentNotFoundError,y as AgentTool,a as AgentRunError,TQ as AgentProvider,B3 as AgentController,V9 as Agent};
|
|
15
|
+
`):void 0}async runTools(Q,$,Z){let J=[],W=[];for(let X of $){let G=this.config.registry.get(String(X.name));if(!G){this.addResult(Q,{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 H=G.inputSchema.safeParse(X.input);if(H.ok===!1){this.addResult(Q,{type:"tool-result",toolCallId:X.toolCallId,name:X.name,status:"error",error:{code:"invalid_tool_input",message:`Invalid arguments for "${String(X.name)}": ${H.errors.join(", ")}`,toolCallId:X.toolCallId,retryable:!0}});continue}X.input=H.value;let V=F$(G.tool);if(V){if(this.onPending==="deny"){this.addResult(Q,this.deniedByPolicy(X));continue}J.push({toolCallId:X.toolCallId,name:X.name,input:H.value,kind:V,signature:t9(this.claimsFor(X.toolCallId,String(X.name),V,H.value)),...this.pathPrefix.length>0?{path:[...this.pathPrefix]}:{}});continue}W.push(this.executeTool(G,Q.id,X,H.value,Z).then(async(Y)=>{this.addResult(Q,Y),await this.settleShown(X.toolCallId)}).catch((Y)=>{if(Y instanceof h){if(this.onPending==="deny"){this.addResult(Q,this.deniedByPolicy(X));return}J.push(...Y.pending);return}}))}return await f(Promise.all(W).then(()=>{return}),this.controller.signal),J}claimsFor(Q,$,Z,J){return{runId:this.signingRunId,toolCallId:Q,name:$,kind:Z,input:J,path:this.pathPrefix.length>0?[...this.pathPrefix]:void 0,subject:this.params.subject??null}}deniedByPolicy(Q){return{type:"tool-result",toolCallId:Q.toolCallId,name:Q.name,status:"denied",cause:"refused",reason:`"${String(Q.name)}" needs the user, and this run was started with onPending: "deny". Answer from what you already have.`}}async executeTool(Q,$,Z,J,W,X){let G=Q.tool.timeoutMs;if(G===void 0)return this.runToolBody(Q,$,Z,J,W,X,this.controller.signal,()=>!1);let H=new AbortController,V=this.controller.signal,Y=()=>H.abort(V.reason);if(V.aborted)Y();else V.addEventListener("abort",Y,{once:!0});let K=!1,z=this.runToolBody(Q,$,Z,J,W,X,H.signal,()=>K),B=()=>{},U=new Promise((F)=>{B=Y$(G,()=>{let D=`"${String(Z.name)}" did not finish within ${rQ(G)} (timeoutMs: ${G}) and was cancelled.`;H.abort(new DOMException(D,"TimeoutError")),F({type:"tool-result",toolCallId:Z.toolCallId,name:Z.name,status:"error",error:{code:"timeout",message:D,toolCallId:Z.toolCallId,retryable:!0}})})});z.catch(()=>{});try{return await Promise.race([z,U])}finally{K=!0,B()}}async runToolBody(Q,$,Z,J,W,X,G,H){let V=this.toolFiles(Z,G),Y={context:this.context,body:this.params.body??{},runId:this.runId,threadId:this.params.threadId,toolCallId:Z.toolCallId,signal:G,step:W,depth:this.depth,resumed:X!==void 0,attachments:V.attachments,generateImage:V.generateImage,editImage:V.editImage,turn:this.toolTurn($),runAgent:this.nestedRunner($,Z,G,X),generate:(K)=>this.generateForTool(K,G,Z.toolCallId)};try{let K=Q.tool.execute(J,Y),z;if(t3(K)){let B=await K.next();while(!B.done){if(H())throw K.return(void 0).catch(()=>{}),new A;this.emit({type:"tool-progress",toolCallId:Z.toolCallId,data:B.value}),B=await K.next()}z=B.value}else z=await K;return{type:"tool-result",toolCallId:Z.toolCallId,name:Z.name,status:"ok",output:z}}catch(K){if(K instanceof A||this.controller.signal.aborted)throw new A;if(K instanceof h)throw K;let z=K instanceof S;if(!z&&this.config.logErrors)this.logToolFailure(Z,K);let B={code:"tool_error",message:K instanceof Error?K.message:String(K),toolCallId:Z.toolCallId,retryable:z?K.retryable:!0};return{type:"tool-result",toolCallId:Z.toolCallId,name:Z.name,status:"error",error:this.redact(B,{source:"tool",toolName:String(Z.name),cause:K})}}}async generateForTool(Q,$,Z){let J=this.controller.signal;return gQ({...Q,signal:Q.signal?AbortSignal.any([$,Q.signal]):$},{origin:{agent:this.config.name,runId:this.runId,...this.params.threadId?{threadId:this.params.threadId}:{},toolCallId:Z},settled:(W)=>{if(this.usage=M(this.usage,W.usage),J.aborted)throw new A}})}nestedRunner(Q,$,Z,J){let W=new Z9(()=>$.nested,()=>$.nested=[]);return async(X,G={})=>{let{at:H,recorded:V,write:Y}=W.next();if(V){let K=e3(V,X,G);if(K)throw new S(`Nested run ${H} of "${String($.name)}" ${K}. `+"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(V.finishReason!=="awaiting-input")return{runId:V.runId,agent:V.agent,messages:V.messages,finishReason:V.finishReason??"stop",usage:V.usage??q(),output:z$(V.messages),nested:V}}return this.runNested(Q,$,Z,X,G,Y,V,J?.answers??[])}}async runNested(Q,$,Z,J,W,X,G,H){let V=[...this.chain,J.name];if(this.chain.includes(J.name))throw new S(`"${J.name}" is already running further up this chain: ${V.join(" -> ")}. An agent cannot run itself, directly or through another agent.`);let Y=this.depth+1;if(Y>this.maxDepth)throw new S(`Nested agent runs are ${this.maxDepth} deep at most and this one would be ${Y}: ${V.join(" -> ")}. Raise maxDepth on the agent at the root of the run if the tree is meant to be this deep.`);let K=W.label,z=[...this.pathPrefix,$.toolCallId],B=this.onPending==="deny"?"deny":W.onPending??"escalate",U=G!==void 0,F=U?NQ(G.messages):new Set,D=U?H.filter((j)=>{let O=U$(j.path,z);if(O===null)return!1;return F.has(O.length>0?O[0]:j.toolCallId)}):[],P=J.stream({messages:U?G.messages:W.messages??[],turn:U?{toolResults:D}:W.prompt?{text:W.prompt}:void 0,context:this.context,attachments:this.params.attachments,body:this.params.body,signal:Z,threadId:this.params.threadId,redactError:this.params.redactError,nonces:this.params.nonces,subject:this.params.subject,instructions:W.instructions,maxOutputTokens:W.maxOutputTokens,temperature:W.temperature,runId:U?G.runId:void 0,nesting:{depth:Y,maxDepth:this.maxDepth,chain:V,signingRunId:this.signingRunId,signingPath:z,onPending:B}}),L=[],_=(async()=>{for await(let j of P){if(j.type==="awaiting-input")L=j.pending;this.emit({type:"nested-event",toolCallId:$.toolCallId,runId:P.runId,agent:J.name,label:K,event:j})}})(),N=(async()=>{let j=await P.result();await _;let O=U?K$(G.messages,j.messages):K$(W.messages??[],j.messages),VQ={runId:P.runId,agent:J.name,label:K,messages:O,finishReason:j.finishReason,usage:U?M(G.usage??q(),j.usage):j.usage,...j.finishReason==="awaiting-input"?{signature:$$({runId:this.signingRunId,path:z,nestedRunId:P.runId,open:[...NQ(O)],input:$.input,subject:this.params.subject??null})}:{}};return X(VQ),this.usage=M(this.usage,j.usage),{result:j,record:VQ}})(),w=N.then(()=>{return},()=>{return});this.nestedSettling.add(w);let k,C;try{({result:k,record:C}=await N)}finally{this.nestedSettling.delete(w)}if(this.controller.signal.aborted)throw new A;if(k.finishReason==="awaiting-input"){if(L.length===0)throw new S(`"${J.name}" ended awaiting input but asked nothing, so there is no question to escalate.`);throw this.emit({type:"tool-call",messageId:Q,part:$,resent:!0}),new h({pending:L,path:z,nested:C})}return{runId:C.runId,agent:J.name,messages:C.messages,finishReason:k.finishReason,usage:C.usage??q(),output:k.output??z$(C.messages),...k.error?{error:k.error}:{},nested:C}}addResult(Q,$){Q.content.push($),this.emit({type:"tool-result",messageId:Q.id,part:$})}toolFiles(Q,$){let Z=this.params.attachments??null,J=new Z9(()=>Q.attachments,()=>Q.attachments=[],()=>({failed:!0})),W=()=>{if(!Z)throw new d("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 Z},X=async(Y,K,z)=>{let B=W(),U=K.mimeType||Y.type||"",F=K.name??(Y instanceof File?Y.name:"attachment"),D;if(K.showModel){let L=this.config.provider;if(!L.capabilities.fileInput)throw new S(`"${String(Q.name)}" asked to show a file to ${L.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 L.upload(new File([Y],F,{type:U||void 0}))}return{attachment:await B.put(Y,{name:F,mimeType:U,fileId:D}),...z?{generated:z}:{},...D?{shown:{fileId:D,messageId:`msg_${crypto.randomUUID()}`,createdAt:new Date().toISOString()}}:{}}},G=(Y,K,z)=>{let B=Y.generated?"image":"put";if(B===K)return;throw new S(`Attachment ${z} of "${String(Q.name)}" was ${B==="image"?"a generated image":"a stored file"} on the first attempt and is ${K==="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.`)},H=async(Y,K,z)=>{let{at:B,recorded:U,write:F}=J.next();if(U&&"attachment"in U){if(G(U,"image",B),U.shown)this.queueShown(Q.toolCallId,U);return{attachment:U.attachment,size:U.generated.size,mimeType:U.attachment.mimeType,usage:U.generated.usage}}let D=await z();this.usage=M(this.usage,D.usage);let P=D.mimeType==="image/jpeg"?"jpg":"png",L=await X(D.image,{name:K.name??`${Y.name}.${P}`,mimeType:D.mimeType,...K.showModel?{showModel:!0}:{}},{size:D.size,usage:D.usage});if(F(L),L.shown)this.queueShown(Q.toolCallId,L);return{attachment:L.attachment,size:D.size,mimeType:D.mimeType,usage:D.usage}},V=async(Y)=>typeof Y==="string"?await W().file(Y):Y;return{generateImage:(Y,K)=>H(Y,K,()=>Y.generate({...K,signal:$})),editImage:(Y,K)=>H(Y,K,async()=>{let{images:z,mask:B,...U}=K;return await Y.edit({...U,images:await Promise.all(z.map(V)),...B?{mask:await V(B)}:{},signal:$})}),attachments:{get:(Y)=>W().get(Y),read:(Y)=>W().read(Y),file:(Y)=>W().file(Y),put:async(Y,K={})=>{let{at:z,recorded:B,write:U}=J.next();if(B&&"attachment"in B){G(B,"put",z);let D=r3(B,Y,K);if(D)throw new S(`Attachment ${z} of "${String(Q.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(B.shown)this.queueShown(Q.toolCallId,B);return B.attachment}let F=await X(Y,K);if(U(F),F.shown)this.queueShown(Q.toolCallId,F);return F.attachment}}}}toolTurn(Q){let $=this.history.findIndex((X)=>X.id===Q),Z=_Q(this.history),J;for(let X=$-1;X>=0;X--){let G=this.history[X];if(G.role!=="user"||Z.has(G.id))continue;J=G;break}let W=[];for(let X of J?.content??[]){if(X.type!=="file")continue;let G=X.attachmentId;if(typeof G!=="string"||!G.startsWith(I))continue;if(!W.includes(G))W.push(G)}return Object.freeze({attachments:Object.freeze(W)})}queueShown(Q,$){let Z=$.shown;if(!Z)return;let J=this.shownQueue.get(Q)??[];if(J.some((W)=>W.id===Z.messageId))return;J.push({id:Z.messageId,role:"user",content:[{type:"file",fileId:Z.fileId,name:$.attachment.name,mimeType:$.attachment.mimeType,attachmentId:$.attachment.id}],createdAt:Z.createdAt,finishReason:"stop"}),this.shownQueue.set(Q,J)}async settleShown(Q){let $=this.shownQueue.get(Q);if(!$||$.length===0)return;if(this.shownQueue.delete(Q),this.ended||this.controller.signal.aborted)return;for(let Z of $){if(this.history.some((J)=>J.id===Z.id))continue;this.history.push(Z),this.produced.push(Z),this.emit({type:"message",message:Z}),this.unreported.add(Z)}}historyForProvider(Q){let $=this.history.filter((X)=>X!==Q),Z=_Q($),J=[];for(let X of $){if(!Z.has(X.id))continue;for(let G of X.content)if(G.type==="file")J.push(G)}if(J.length<=D$)return $;let W=new Set(J.slice(0,J.length-D$));return $.map((X)=>{if(!X.content.some((G)=>G.type==="file"&&W.has(G)))return X;return{...X,content:X.content.map((G)=>G.type==="file"&&W.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 Q=this.params.turn,$=this.openCalls(),Z=[];if($.length>0){let J=new Set,W=new Set,X=new Map;for(let G of Q?.toolResults??[]){let H=`${(G.path??[]).join("/")}#${G.toolCallId}`;if(W.has(H))continue;W.add(H);let V=(B)=>this.emit({type:"error",error:{code:"invalid_tool_result",message:B,toolCallId:G.toolCallId,retryable:!1}}),Y=U$(G.path,this.pathPrefix);if(Y===null){V(`The answer for "${G.toolCallId}" is addressed to a tool call this run is not inside.`);continue}if(Y.length>0){let B=Y[0],U=$.find((P)=>P.call.toolCallId===B);if(!U){V(`No pending tool call with id "${B}" to deliver a nested answer to.`);continue}let F=this.parkedBelow(U.call,Y,G.toolCallId);if(F.ok===!1){let P=`The answer for "${G.toolCallId}" is addressed under "${B}", which`;V(F.reason==="unparked"?`${P} has no sub-agent run waiting on that question.`:F.reason==="expired"?`${P} parked a sub-agent run that has since expired. Ask again.`:`${P} carries a record of a parked sub-agent run the server did not sign.`);continue}let D=X.get(B);if(!D){if(!await this.spend(W$,F.signature)){V(`The answer for "${G.toolCallId}" is addressed under "${B}", which has already been re-entered on that record. Ask again.`);continue}D=[],X.set(B,D),J.add(B)}D.push(G);continue}let K=$.find((B)=>B.call.toolCallId===G.toolCallId);if(!K){V(`No pending tool call with id "${G.toolCallId}".`);continue}let z=await this.resolveAnswer(K,G,Z);if(z===null)continue;if(J.add(G.toolCallId),z!=="open")this.attachToHistory(K,z),await this.settleShown(G.toolCallId)}for(let[G,H]of X){let V=$.find((K)=>K.call.toolCallId===G),Y=await this.reenter(V,H,Z);if(Y)this.attachToHistory(V,Y),await this.settleShown(G)}for(let G of $){if(J.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(Q&&(Q.text||Q.files&&Q.files.length>0)){let J={id:`msg_${crypto.randomUUID()}`,role:"user",content:[...Q.text?[{type:"text",text:Q.text}]:[],...(Q.files??[]).map((W)=>({type:"file",...W.fileId?{fileId:W.fileId}:{},name:W.name,mimeType:W.mimeType,...W.attachmentId?{attachmentId:W.attachmentId}:{}}))],createdAt:new Date().toISOString(),finishReason:"stop"};this.history.push(J),this.produced.push(J),await this.report(J)}return Z}parkedBelow(Q,$,Z){let J=$.length>1?$[1]:Z,W=[...this.pathPrefix,Q.toolCallId],X=(Q.nested??[]).find((H)=>H.finishReason==="awaiting-input"&&NQ(H.messages).has(J));if(!X)return{ok:!1,reason:"unparked"};if(typeof X.signature!=="string")return{ok:!1,reason:"unsigned"};let G=Z$(X.signature,{path:W,nestedRunId:X.runId,open:[...NQ(X.messages)],input:Q.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(Q,$,Z){let J=String(Q.call.name),W=this.config.registry.get(J);if(!W||!W.tool.execute)return{type:"tool-result",toolCallId:Q.call.toolCallId,name:Q.call.name,status:"error",error:{code:"invalid_tool_result",message:`The tool "${J}" no longer exists, so the sub-agent's question cannot be delivered.`,toolCallId:Q.call.toolCallId,retryable:!1}};let X=W.inputSchema.safeParse(Q.call.input);if(X.ok===!1)return{type:"tool-result",toolCallId:Q.call.toolCallId,name:Q.call.name,status:"error",error:{code:"invalid_tool_input",message:`Invalid arguments for "${J}": ${X.errors.join(", ")}`,toolCallId:Q.call.toolCallId,retryable:!0}};let G=this.amendCall(Q);G.input=X.value;try{return await f(this.executeTool(W,Q.message.id,G,X.value,0,{answers:$}),this.controller.signal)}catch(H){if(H instanceof h)return Z.push(...H.pending),null;throw H}}amendCall(Q){let $=this.amend(Q.message),Z=$.content.indexOf(Q.call),J={...Q.call,nested:(Q.call.nested??[]).map((W)=>({...W})),...Q.call.attachments?{attachments:Q.call.attachments.map((W)=>({...W}))}:{}};if(Z>=0)$.content[Z]=J;return this.unreported.add($),J}openCalls(){let Q=new Set;for(let Z of this.history)for(let J of Z.content)if(J.type==="tool-result")Q.add(J.toolCallId);let $=[];for(let Z of this.history)for(let J of Z.content)if(J.type==="tool-call"&&!Q.has(J.toolCallId))$.push({message:Z,call:J});return $}async spend(Q,$){try{return await Q($,this.params.nonces??p)}catch(Z){return this.writeLog(`[gemi/ai] agent "${this.config.name}" could not spend a nonce`,{error:Z}),!1}}async resolveAnswer(Q,$,Z){let J=Q.call,W=String(J.name),X=this.config.registry.get(W),G=(K)=>{return this.emit({type:"error",error:{code:"invalid_tool_result",message:K,toolCallId:J.toolCallId,retryable:!1}}),null};if(!X)return G(`The tool "${W}" no longer exists, so its answer cannot be checked.`);let H=F$(X.tool);if(!H)return G(`"${W}" is a server tool with no pending question.`);if(typeof $.signature!=="string"||$.signature.length===0)return G(`The answer for "${W}" carried no signature.`);let V=lQ($.signature);if(!V)return G(`The signature for "${W}" is malformed.`);let Y=a9($.signature,{...this.claimsFor(J.toolCallId,W,H,J.input),runId:V.runId});if(Y.ok===!1)return G(Y.reason==="expired"?`The approval for "${W}" has expired. Ask again.`:`The answer for "${W}" does not match the call the server made.`);if(!await this.spend(J$,$.signature))return G(`The answer for "${W}" has already been used. Ask again.`);if("approve"in $){if(H!=="approval")return G(`"${W}" is answered by the client, not approved.`);if($.approve===!0){let K=this.amendCall(Q);try{return await f(this.executeTool(X,Q.message.id,K,K.input,0),this.controller.signal)}catch(z){if(z instanceof h)return Z.push(...z.pending),"open";throw z}}return{type:"tool-result",toolCallId:J.toolCallId,name:J.name,status:"denied",cause:"refused",reason:$.reason}}if("output"in $){if(H==="approval")return G(`"${W}" is approved, not answered: the server produces its result.`);let K=X.tool.outputSchema,z=K?K.safeParse($.output):{ok:!0,value:$.output};if(z.ok===!1)return{type:"tool-result",toolCallId:J.toolCallId,name:J.name,status:"error",error:{code:"invalid_tool_result",message:`The answer for "${W}" did not match its output schema: ${z.errors.join(", ")}`,toolCallId:J.toolCallId,retryable:!0}};return{type:"tool-result",toolCallId:J.toolCallId,name:J.name,status:"ok",output:z.value}}return G(`The answer for "${W}" carried neither an approval nor an output.`)}attachToHistory(Q,$){let Z=this.amend(Q.message);Z.content.push($),this.unreported.add(Z),this.emit({type:"tool-result",messageId:Z.id,part:$})}markFileRejected(Q,$,Z){for(let G of this.history){if(!G.content.some((Y)=>Y.type==="file"&&Y.fileId===Q&&!Y.providerRejected))continue;let V=this.produced.includes(G)?G:this.amend(G);if(V.content=V.content.map((Y)=>Y.type==="file"&&Y.fileId===Q&&!Y.providerRejected?{...Y,providerRejected:!0}:Y),V!==this.current)this.unreported.add(V)}if(!this.config.logErrors)return;let J=`[gemi/ai] agent "${this.config.name}": the provider refused file ${Q}${Z.status!==void 0?` (${Z.status})`:""}; it was left out of the request and will not be sent again: ${$}`,W={agent:this.config.name,runId:this.runId,...this.params.threadId?{threadId:this.params.threadId}:{},fileId:Q,...Z},X=!1;try{a.warning(J,W),X=!0}catch{}if(!X||Bun.env.NODE_ENV==="development")console.warn(J,W)}amend(Q){let $=this.amended.get(Q.id);if($)return $;let Z={...Q,content:[...Q.content]},J=this.history.indexOf(Q);if(J>=0)this.history[J]=Z;return this.produced.push(Z),this.amended.set(Q.id,Z),Z}async reportDeferred(){let Q=[...this.unreported];this.unreported.clear();for(let $ of Q)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 Q=this.current;if(Q){let $=new Set(Q.content.filter((Z)=>Z.type==="tool-result").map((Z)=>Z.toolCallId));for(let Z of[...Q.content]){if(Z.type!=="tool-call"||$.has(Z.toolCallId))continue;delete Z.partial,this.addResult(Q,{type:"tool-result",toolCallId:Z.toolCallId,name:Z.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 ${rQ(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 F$(Q){if(Q.answeredBy==="client")return Q.inputSchema===J9?"question":"client";return Q.requiresApproval?"approval":null}function C$(Q){if(!Q||!Q.trim())return{};try{return JSON.parse(Q)}catch{return Q}}function QZ(Q,$){return Q.descriptors($).map((Z)=>y.create({name:Z.name,description:Z.description,inputSchema:Z.inputSchema,requiresApproval:Z.requiresApproval,execute:(J,W)=>{let X=qQ.getStore()?.req;if(!X)throw new S(`"${Z.name}" calls an api route as the user who started this run, and this run was not started inside a request. Run it from an AgentController, or give this agent tools that do not go through the MCP registry.`);return Q.execute({kind:"local",req:X},Z.name,J,W)}}))}function $Z(Q){if(Q==="auto")return;let $=/^(\d+)x(\d+)$/.exec(Q);if(!$)throw Error(`An image size is "WIDTHxHEIGHT" or "auto"; got ${JSON.stringify(Q)}.`);let Z=Number($[1]),J=Number($[2]);if(Z%16!==0||J%16!==0)throw Error(`Image size ${Q} is not supported: width and height must both be divisible by 16.`);if(Math.max(Z/J,J/Z)>3)throw Error(`Image size ${Q} is not supported: the maximum aspect ratio is 3:1, either way up.`)}function N$(Q,$){if(Q.size!==void 0)try{$Z(Q.size)}catch(Z){throw Error(`${$}: ${Z.message}`)}if(Q.background==="transparent"&&Q.format==="jpeg")throw Error(`${$}: a transparent background needs "png"; JPEG has no alpha channel.`);if(Q.compression!==void 0){let Z=Q.compression;if(!Number.isInteger(Z)||Z<0||Z>100)throw Error(`${$}: compression is an integer from 0 to 100; got ${Z}.`)}}function _$(Q,$){if(Q instanceof File)return Q;let Z=Q.type||"image/png",J=Z==="image/jpeg"?"jpg":Z.split("/")[1]??"png";return new File([Q],`${$}.${J}`,{type:Z})}class Y9{name;provider;settings;constructor(Q){let{name:$,provider:Z,...J}=Q;N$(J,`ImageModel "${$}"`),this.name=$,this.provider=Z,this.settings=J}static create(Q){return new Y9(Q)}async generate(Q){let $=this.merge(Q);return q$(await this.provider.generate({prompt:Q.prompt,...$,signal:Q.signal}))}async edit(Q){let $=this.merge(Q);return q$(await this.provider.edit({prompt:Q.prompt,...$,images:Q.images.map((Z,J)=>_$(Z,`image-${J}`)),...Q.mask?{mask:_$(Q.mask,"mask")}:{},signal:Q.signal}))}merge(Q){let $={...this.settings,...Q.size!==void 0?{size:Q.size}:{},...Q.quality!==void 0?{quality:Q.quality}:{},...Q.background!==void 0?{background:Q.background}:{},...Q.format!==void 0?{format:Q.format}:{},...Q.compression!==void 0?{compression:Q.compression}:{}};return N$($,`ImageModel "${this.name}"`),$}}function q$(Q){return{image:new Blob([Q.bytes],{type:Q.mimeType}),mimeType:Q.mimeType,size:Q.size,usage:Q.usage}}function g(Q){return typeof process>"u"?void 0:process.env?.[Q]}var ZZ="preview";function M$(Q){let $=Q.trim().replace(/\/+$/,"");if(!$)return"";return`${$.replace(/\/openai(?:\/v1)?$/i,"")}/openai`}function JZ(Q){return/^\d{4}-\d{2}-\d{2}/.test(Q)?"":"/v1"}function SQ(Q,$={}){return{base:(Q.baseURL??g("OPENAI_BASE_URL")??"https://api.openai.com/v1").replace(/\/+$/,""),query:"",headers:async()=>{let J=Q.apiKey??g("OPENAI_API_KEY");return{...J?{authorization:`Bearer ${J}`}:{},...Q.headers}},timeoutMs:Q.timeoutMs??$.timeoutMs??120000,maxRetries:Q.maxRetries??2}}function WZ(Q){let $=Q.baseURL??Q.endpoint??g("AZURE_OPENAI_ENDPOINT");if($)return M$($);let Z=Q.resourceName??g("AZURE_OPENAI_RESOURCE_NAME")??g("AZURE_RESOURCE_NAME");return Z?M$(`https://${Z.trim()}.cognitiveservices.azure.com`):""}function RQ(Q,$={}){let Z=Q.apiVersion??g("AZURE_OPENAI_API_VERSION")??ZZ;return{base:`${WZ(Q)}${JZ(Z)}`,query:`?api-version=${encodeURIComponent(Z)}`,headers:async()=>{if(Q.getToken)return{authorization:`Bearer ${await Q.getToken()}`,...Q.headers};let J=Q.apiKey??g("AZURE_OPENAI_API_KEY");return{...J?{"api-key":J}:{},...Q.headers}},timeoutMs:Q.timeoutMs??$.timeoutMs??120000,maxRetries:Q.maxRetries??2}}var XZ=500,R$=20000;function GZ(Q,$){if(!Q)return;let Z=Q.trim();if(/^\d+(\.\d+)?$/.test(Z))return Math.max(0,Number(Z)*1000);let J=Date.parse(Z);if(Number.isNaN(J))return;return Math.max(0,J-$)}function S$(Q,$){let Z=Math.min(R$,XZ*2**Q);return Math.round(Z*(0.5+$()*0.5))}function VZ(Q){return Q===429||Q===408||Q===409||Q>=500}function HZ(Q,$){return VZ(Q)&&R($).retryable}function k$(Q){return Q.reason??new DOMException("The operation was aborted.","AbortError")}function YZ(Q,$){return new Promise((Z,J)=>{let W=setTimeout(Z,Q);$?.addEventListener("abort",()=>{clearTimeout(W),J(k$($))},{once:!0})})}async function JQ(Q,$,Z){let J=Z.fetchImpl??((K,z)=>fetch(K,z)),W=Z.sleep??YZ,X=Z.random??Math.random,G=Z.now??Date.now,H=Math.max(0,Z.maxRetries),V=async(K)=>{let z=Z.signal;if(!z)return await W(K);z.throwIfAborted();let B;try{await Promise.race([W(K,z),new Promise((U,F)=>{B=()=>F(k$(z)),z.addEventListener("abort",B,{once:!0})})])}finally{if(B)z.removeEventListener("abort",B)}},Y;for(let K=0;K<=H;K++){Z.signal?.throwIfAborted();let z=new AbortController,B=()=>z.abort(Z.signal?.reason);Z.signal?.addEventListener("abort",B,{once:!0});let U=!1,F=Z.timeoutMs>0?setTimeout(()=>{U=!0,z.abort()},Z.timeoutMs):void 0,D;try{D=await J(Q,{...$,signal:z.signal})}catch(N){if(F!==void 0)clearTimeout(F);if(Z.signal?.removeEventListener("abort",B),Z.signal?.aborted)throw N;if(Y=U?new HQ(Z.timeoutMs):N,U&&Z.retryTimeouts===!1)throw Y;if(K===H)throw Y;await V(S$(K,X));continue}if(F!==void 0)clearTimeout(F);if(D.ok)return D;Z.signal?.removeEventListener("abort",B);let P=await KZ(D),L=new v(D.status,P,D.headers.get("x-request-id")??void 0);if(K===H||!HZ(D.status,L))throw L;let _=GZ(D.headers.get("retry-after"),G());await V(_===void 0?S$(K,X):Math.min(_,R$)),Y=L}throw Y??Error("Provider request failed with no response.")}async function KZ(Q){let $;try{$=await Q.text()}catch{return null}try{return JSON.parse($)}catch{return $}}var K9=300000;function z9(Q){return{generationsUrl:`${Q.base}/images/generations${Q.query}`,editsUrl:`${Q.base}/images/edits${Q.query}`,headers:Q.headers,timeoutMs:Q.timeoutMs,maxRetries:Q.maxRetries}}class kQ extends Error{code;retryable;constructor(Q,$={}){super(Q.message,$);this.name="ImageRequestError",this.code=Q.code,this.retryable=Q.retryable}}var zZ={png:"image/png",jpeg:"image/jpeg"};function BZ(Q){let $=Number(Q?.input_tokens??0),Z=Number(Q?.output_tokens??0),J={inputTokens:$,outputTokens:Z,totalTokens:Number(Q?.total_tokens??$+Z)},W=Q?.input_tokens_details?.image_tokens;if(typeof W==="number")J.imageInputTokens=W;let X=Q?.output_tokens_details?.image_tokens;if(typeof X==="number")J.imageOutputTokens=X;return J}function DZ(Q){let $=atob(Q),Z=new Uint8Array($.length);for(let J=0;J<$.length;J++)Z[J]=$.charCodeAt(J);return Z}function UZ(Q){let Z=Q?.data?.[0]?.b64_json;if(typeof Z!=="string"||Z.length===0)throw new kQ({code:"provider_error",message:"The provider answered an image call with no base64 image data.",retryable:!1});let J=typeof Q.output_format==="string"?Q.output_format:"png";return{bytes:DZ(Z),mimeType:zZ[J]??`image/${J}`,size:typeof Q.size==="string"?Q.size:"",...typeof Q.background==="string"?{background:Q.background}:{},usage:BZ(Q.usage)}}async function T$(Q,$,Z,J){let W;try{W=await JQ(Q,$,{maxRetries:Z.maxRetries,timeoutMs:Z.timeoutMs,retryTimeouts:!1,signal:J.signal,fetchImpl:Z.fetchImpl})}catch(X){if(J.signal?.aborted)throw X;throw new kQ(R(X),{cause:X})}return UZ(await W.json())}async function A$(Q,$,Z={}){return await T$(Q.generationsUrl,{method:"POST",headers:{...await Q.headers(),"content-type":"application/json"},body:JSON.stringify($)},Q,Z)}async function E$(Q,$,Z={}){return await T$(Q.editsUrl,{method:"POST",headers:await Q.headers(),body:$},Q,Z)}class TQ{static models(){return[]}modelName(){return this.model}async generate(Q){return await A$(this.endpoint(),this.body(Q),{signal:Q.signal})}async edit(Q){let $=new FormData;for(let[Z,J]of Object.entries(this.body(Q)))if(J!==void 0)$.set(Z,String(J));for(let Z of Q.images)$.append("image[]",Z,Z.name);if(Q.mask)$.set("mask",Q.mask,Q.mask.name);return await E$(this.endpoint(),$,{signal:Q.signal})}body(Q){return{model:this.modelName(),prompt:Q.prompt,...Q.size?{size:Q.size}:{},...Q.quality?{quality:Q.quality}:{},...Q.background?{background:Q.background}:{},...Q.format?{output_format:Q.format}:{},...Q.compression!==void 0?{output_compression:Q.compression}:{}}}normalizeError(Q){return R(Q)}}var x$=["gpt-image-2","gpt-image-1.5","gpt-image-1"];class B9 extends TQ{model;config;constructor(Q,$={}){super();this.model=Q,this.config=$}static model(Q,$){return new B9(Q,$)}static models(){return x$}endpoint(){return z9(SQ(this.config,{timeoutMs:K9}))}}class D9 extends TQ{model;config;constructor(Q,$={}){super();this.model=Q,this.config=$}static model(Q,$){return new D9(Q,$)}static models(){return x$}modelName(){return this.config.deployment??this.model}endpoint(){return z9(RQ(this.config,{timeoutMs:K9}))}}var I$=3;function U9(Q){let $=new Map;for(let Z of Q)for(let J of Z.content??[]){if(J.type!=="file"||!J.fileId||$.has(J.fileId))continue;$.set(J.fileId,{name:J.name,mimeType:J.mimeType})}return $}function v$(Q,$,Z=new Map){if(!($ instanceof v))return[];if($.status!==400&&$.status!==404)return[];let J=CZ($.body);if(!J)return[];let W=FZ(Q.input);if(W.length===0)return[];let X=/^input\[(\d+)\]\.content\[(\d+)\]\.file_id$/.exec(J.param??"");if(X){let Y=Q.input[Number(X[1])],K=C9(Y)[Number(X[2])],z=K&&typeof K.file_id==="string"?K.file_id:void 0;if(z)return[z]}let G=J.message??"",H=b$(W.map((Y)=>Y.fileId).filter((Y)=>LZ(G,Y)));if(H.length>0)return H;let V=/Expected (image type|context stuffing file type) to be a supported format:.*but got \.([a-z0-9]+)\.?\s*$/is.exec(G);if(V){let Y=V[1].toLowerCase()==="image type"?"input_image":"input_file",K=V[2].toLowerCase(),z=b$(W.filter((U)=>U.type===Y).map((U)=>U.fileId)),B=z.filter((U)=>(Z.get(U)?.name??"").trim().toLowerCase().endsWith(`.${K}`));if(B.length===1)return B;if(B.length===0&&z.length===1)return z}return[]}function f$(Q,$,Z=new Map){return{...Q,input:Q.input.map((J)=>{let W=C9(J);if(!W.some((X)=>w$(X,$)))return J;return{...J,content:W.map((X)=>w$(X,$)?{type:"input_text",text:F9(Z.get(String(X.file_id))?.name)}:X)}})}}function F9(Q){return`[${Q?`attachment ${JSON.stringify(Q)}`:"an attachment"} could not be read by the provider and is not shown to you. Tell the user if it matters to the answer; uploading it again may help.]`}function w$(Q,$){return typeof Q.file_id==="string"&&$.has(Q.file_id)}function C9(Q){let $=Q?.content;return Array.isArray($)?$:[]}function FZ(Q){let $=[];for(let Z of Q)for(let J of C9(Z))if(typeof J.file_id==="string"&&J.file_id)$.push({type:String(J.type),fileId:J.file_id});return $}function CZ(Q){if(!Q||typeof Q!=="object")return null;let $=Q,Z=$.error&&typeof $.error==="object"?$.error:Q;return{message:typeof Z.message==="string"?Z.message:void 0,param:typeof Z.param==="string"?Z.param:void 0}}function LZ(Q,$){let Z=$.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^A-Za-z0-9_-])${Z}($|[^A-Za-z0-9_-])`).test(Q)}function b$(Q){return[...new Set(Q)]}async function*jZ(Q){let $="",Z="",J=[],W,X=()=>{if(J.length===0&&!Z)return null;let V={event:Z,data:J.join(`
|
|
16
|
+
`),id:W};return Z="",J=[],W=void 0,V.data?V:null},G=(V)=>{let Y=V.endsWith("\r")?V.slice(0,-1):V;if(Y==="")return X();if(Y.startsWith(":"))return null;let K=Y.indexOf(":"),z=K===-1?Y:Y.slice(0,K),B=K===-1?"":Y.slice(K+1);if(B.startsWith(" "))B=B.slice(1);if(z==="event")Z=B;else if(z==="data")J.push(B);else if(z==="id")W=B;return null};for await(let V of Q){$+=V;let Y=$.indexOf(`
|
|
17
|
+
`);while(Y!==-1){let K=$.slice(0,Y);$=$.slice(Y+1);let z=G(K);if(z)yield z;Y=$.indexOf(`
|
|
18
|
+
`)}}if($.length>0){let V=G($);if(V)yield V}let H=X();if(H)yield H}async function*h$(Q,$={}){let Z=new Map,J=new Set,W=!1;for await(let X of jZ(Q)){if(X.data==="[DONE]")break;let G;try{G=JSON.parse(X.data)}catch{continue}switch(typeof G.type==="string"?G.type:X.event){case"response.output_text.delta":{let V=String(G.delta??"");if(!V)break;yield $.structuredOutput?{type:"output-delta",delta:V}:{type:"text-delta",delta:V};break}case"response.reasoning_summary_text.delta":case"response.reasoning_text.delta":{let V=String(G.delta??"");if(!V)break;yield{type:"reasoning-delta",delta:V,id:G.item_id};break}case"response.output_item.added":{let V=G.item;if(!V)break;if(V.type==="function_call"){let Y=String(V.id??G.item_id??V.call_id??"");Z.set(Y,{callId:String(V.call_id??Y),name:String(V.name??""),namespace:typeof V.namespace==="string"&&V.namespace?V.namespace:void 0,done:!1})}break}case"response.function_call_arguments.delta":{let V=Z.get(String(G.item_id??""));if(!V)break;let Y=String(G.delta??"");if(!Y)break;yield{type:"tool-call-delta",toolCallId:V.callId,name:V.name,argsDelta:Y,...V.namespace?{namespace:V.namespace}:{}};break}case"response.function_call_arguments.done":{let V=String(G.item_id??""),Y=Z.get(V);if(!Y)break;Y.done=!0,yield{type:"tool-call",toolCallId:Y.callId,name:Y.name,args:String(G.arguments??""),...Y.namespace?{namespace:Y.namespace}:{}};break}case"response.output_item.done":{let V=G.item;if(!V)break;if(V.type==="function_call"){let Y=String(V.id??G.item_id??V.call_id??""),K=Z.get(Y);if(K?.done)break;let z=(typeof V.namespace==="string"?V.namespace:"")||K?.namespace;if(yield{type:"tool-call",toolCallId:String(V.call_id??Y),name:String(V.name??K?.name??""),args:String(V.arguments??""),...z?{namespace:z}:{}},K)K.done=!0;break}if(V.type==="tool_search_call"||V.type==="tool_search_output"){let Y=PZ(V);if(Y.loaded.length===0&&Y.namespaces.length===0)break;let K=String(V.tool_search_call_id??V.id??"");if(J.has(K))break;J.add(K),yield{type:"tool-search",...Y}}break}case"response.refusal.done":{yield{type:"error",error:{code:"content_filtered",message:String(G.refusal??"The model refused to answer."),retryable:!1}};break}case"response.completed":{W=!0,yield{type:"finish",reason:"stop",usage:L9(G.response?.usage)};break}case"response.incomplete":{W=!0;let V=L9(G.response?.usage),Y=G.response?.incomplete_details?.reason;if(Y==="content_filter"){yield{type:"error",error:{code:"content_filtered",message:OZ(G.response?.content_filters),retryable:!1}},yield{type:"finish",reason:"error",usage:V};break}yield{type:"finish",reason:Y==="max_output_tokens"?"length":"stop",usage:V};break}case"response.failed":case"error":{W=!0;let V=G.response?.error??G.error??G;yield{type:"error",error:NZ(V)},yield{type:"finish",reason:"error",usage:L9(G.response?.usage)};break}}if(W)return}if(!W)yield{type:"error",error:{code:"provider_error",message:"The provider stream ended without a terminal event.",retryable:!0}},yield{type:"finish",reason:"error",usage:l()}}function PZ(Q){let $=[],Z=[];return y$(Q.results??Q.tools??Q.loaded??Q.output,$,Z,0),{loaded:j9($),namespaces:j9(Z)}}function y$(Q,$,Z,J){if(!Array.isArray(Q)||J>4)return;for(let W of Q){if(typeof W==="string"){$.push(W);continue}if(!W||typeof W!=="object")continue;let X=W,G=typeof X.name==="string"?X.name:typeof X.tool_name==="string"?X.tool_name:"",H=X.tools??X.functions;if(Array.isArray(H)){if(G)Z.push(G);y$(H,$,Z,J+1);continue}if(G)$.push(G)}}function j9(Q){return Q.filter(($,Z)=>Q.indexOf($)===Z)}function OZ(Q){if(!Array.isArray(Q))return"The provider's content filter blocked this request.";let Z=[];for(let J of Q){if(!J||typeof J!=="object")continue;let W=J,X=W.content_filter_results;if(!X||typeof X!=="object")continue;for(let[G,H]of Object.entries(X))if(H&&typeof H==="object"&&H.filtered===!0)Z.push(`${G} (${String(W.source_type??"unknown")})`)}return Z.length===0?"The provider's content filter blocked this request.":`The provider's content filter blocked this request. Categories: ${j9(Z).join(", ")}.`}function NZ(Q){let $=typeof Q?.message==="string"?Q.message:"The provider stream failed.",Z=String(Q?.code??"").toLowerCase();if(Z==="rate_limit_exceeded")return{code:"rate_limited",message:$,retryable:!0};if(Z==="context_length_exceeded")return{code:"context_length_exceeded",message:$,retryable:!1};if(Z.includes("content_filter"))return{code:"content_filtered",message:$,retryable:!1};return{code:"provider_error",message:$,retryable:!0}}function l(){return{inputTokens:0,outputTokens:0,totalTokens:0}}function L9(Q){if(!Q)return l();let $=Number(Q.input_tokens??0),Z=Number(Q.output_tokens??0),J={inputTokens:$,outputTokens:Z,totalTokens:Number(Q.total_tokens??$+Z)},W=Q.output_tokens_details?.reasoning_tokens;if(typeof W==="number")J.reasoningTokens=W;let X=Q.input_tokens_details?.cached_tokens;if(typeof X==="number")J.cachedInputTokens=X;return J}async function*g$(Q){if(!Q)return;let $=Q.getReader(),Z=new TextDecoder;try{while(!0){let{done:W,value:X}=await $.read();if(W)break;if(X)yield Z.decode(X,{stream:!0})}let J=Z.decode();if(J)yield J}finally{$.releaseLock()}}function P9(Q){return{responsesUrl:`${Q.base}/responses${Q.query}`,filesUrl:`${Q.base}/files${Q.query}`,headers:Q.headers,timeoutMs:Q.timeoutMs,maxRetries:Q.maxRetries}}async function*O9(Q,$,Z){let J,W=$,X=new Set;for(let G=0;J===void 0;G++)try{J=await JQ(Q.responsesUrl,{method:"POST",headers:{...await Q.headers(),"content-type":"application/json"},body:JSON.stringify(W)},{maxRetries:Q.maxRetries,timeoutMs:Q.timeoutMs,signal:Z.signal,fetchImpl:Q.fetchImpl})}catch(H){let V=G<I$?v$(W,H,Z.files).filter((K)=>!X.has(K)):[];if(V.length>0){let K=R(H).message;for(let z of V)X.add(z),yield{type:"file-rejected",fileId:z,message:K,...T(H)};W=f$(W,new Set(V),Z.files);continue}let Y=R(H);if(Y.code!=="aborted")yield{type:"error",error:Y,...T(H)};yield{type:"finish",reason:Y.code==="aborted"?"aborted":"error",usage:l()};return}try{yield*h$(g$(J.body),{structuredOutput:Z.structuredOutput})}catch(G){let H=R(G);if(H.code==="aborted"){yield{type:"finish",reason:"aborted",usage:l()};return}yield{type:"error",error:H},yield{type:"finish",reason:"error",usage:l()}}}async function N9(Q,$,Z="user_data"){let J=new FormData;J.set("purpose",Z),J.set("file",$);let X=await(await JQ(Q.filesUrl,{method:"POST",headers:await Q.headers(),body:J},{maxRetries:Q.maxRetries,timeoutMs:Q.timeoutMs,fetchImpl:Q.fetchImpl})).json();if(!X?.id)throw Error("The provider accepted the upload but returned no file id.");return X.id}function _9(Q){let $=_Z(Q);if($.startsWith("gpt-3.5")||$.startsWith("text-")||$.startsWith("davinci"))return{reasoning:!1,structuredOutput:!1,fileInput:!1,parallelToolCalls:!0,toolSearch:!1};let Z=qZ($);if(Z?.kind==="o")return{reasoning:!0,structuredOutput:!0,fileInput:!0,parallelToolCalls:Z.major>1,toolSearch:u$(Z)};if(Z?.kind==="gpt")return{reasoning:Z.major>=5,structuredOutput:Z.major>4||$.startsWith("gpt-4o")||$.startsWith("gpt-4.1"),fileInput:Z.major>4||$.startsWith("gpt-4o")||$.startsWith("gpt-4.1"),parallelToolCalls:!0,toolSearch:u$(Z)};return{reasoning:!0,structuredOutput:!0,fileInput:!0,parallelToolCalls:!0,toolSearch:!0}}function u$(Q){if(Q.kind==="o")return Q.major>=5;return Q.major>5||Q.major===5&&Q.minor>=2}function _Z(Q){return Q.trim().toLowerCase()}function qZ(Q){let $=/^gpt-(\d+)(?:\.(\d+))?/.exec(Q);if($?.[1])return{kind:"gpt",major:Number($[1]),minor:Number($[2]??0)};let Z=/^o(\d+)(?:[-.]|$)/.exec(Q);if(Z?.[1])return{kind:"o",major:Number(Z[1]),minor:0};return null}function M9(Q,$){let{capabilities:Z}=$,J={model:$.model,input:MZ(Q.messages,Z),stream:!0};if(Q.systemPrompt)J.instructions=Q.systemPrompt;let W=bZ(Q.tools,Z);if(W.length>0){if(J.tools=W,!Z.parallelToolCalls)J.parallel_tool_calls=!1}if(Q.output)J.text={format:{type:"json_schema",name:Q.output.name,schema:Q.output.schema,strict:Q.output.strict}};if(Q.reasoning&&Z.reasoning)J.reasoning=Q.reasoning==="none"?{effort:"none"}:{effort:Q.reasoning,summary:"auto"};if(typeof Q.temperature==="number")J.temperature=Q.temperature;if(typeof Q.maxOutputTokens==="number")J.max_output_tokens=Q.maxOutputTokens;return J}function MZ(Q,$){let Z=[];for(let J of Q){let W=J.role,X=[],G=()=>{if(X.length===0)return;Z.push({type:"message",role:W,content:X}),X=[]};for(let H of J.content??[])switch(H.type){case"text":{if(!H.text)break;X.push(i(W,H.text));break}case"output":{if(H.partial)break;X.push(i(W,JSON.stringify(H.value)));break}case"file":{if(W==="assistant")break;let V=kZ(H);if(!$.fileInput){if(V)X.push(i(W,q9(H,!1)));break}if(H.fileId?.startsWith(I))throw Error(`FilePart.fileId holds a gemi attachment id (${H.fileId}). That field is the *provider's* file id, from \`fileId\` on the upload response; the \`attachmentId\` goes in \`FilePart.attachmentId\`, is shown to the model as text, and is resolved by a tool through \`ctx.attachments\`.`);if(!H.fileId&&!V)throw Error("FilePart.fileId is empty and there is no `attachmentId` either. `fileId` is the *provider's* file id and `attachmentId` is gemi's (`gemi_att_\u2026`), both from the upload response; an upload always answers at least one, so a part with neither was built from something other than that answer.");if(H.providerRejected){if(V)X.push(i(W,q9(H,!1)));X.push(i(W,F9(H.name)));break}if(V)X.push(i(W,q9(H,!!H.fileId)));if(H.fileId)X.push(TZ(H));break}case"reasoning":{G();let V=xZ(H);if(V)Z.push(V);break}case"tool-call":{if(H.partial)break;G(),Z.push({type:"function_call",call_id:H.toolCallId,name:String(H.name),arguments:JSON.stringify(H.input??{})});break}case"tool-result":{G(),Z.push({type:"function_call_output",call_id:H.toolCallId,output:wZ(H)});break}}G()}return RZ(Z)}var SZ="No result was recorded for this tool call. Assume it did not complete.";function RZ(Q){let $=new Set,Z=new Set,J=[];for(let X of Q){if(X.type==="function_call"){let G=String(X.call_id);if($.has(G))continue;$.add(G)}else if(X.type==="function_call_output"){let G=String(X.call_id);if(!$.has(G)||Z.has(G))continue;Z.add(G)}J.push(X)}if(Z.size===$.size)return J;let W=[];for(let X of J){if(W.push(X),X.type!=="function_call")continue;let G=String(X.call_id);if(Z.has(G))continue;Z.add(G),W.push({type:"function_call_output",call_id:G,output:SZ})}return W}function i(Q,$){return{type:Q==="assistant"?"output_text":"input_text",text:$}}function kZ(Q){let $=Q.attachmentId;return typeof $==="string"&&$.startsWith(I)?$:void 0}function q9(Q,$){let Z=[`id=${JSON.stringify(Q.attachmentId)}`];if(Q.name)Z.push(`name=${JSON.stringify(Q.name)}`);if(Q.mimeType)Z.push(`mimeType=${JSON.stringify(Q.mimeType)}`);let J=`attachment ${Z.join(" ")}`;return $?`[${J}]`:`[${J} \u2014 its contents are not shown to you; a tool can read the file by this id]`}function TZ(Q){let $=Q.mimeType?.trim().toLowerCase()??"";return{type:($?$.startsWith("image/")&&$!=="image/svg+xml":AZ(Q.name))?"input_image":"input_file",file_id:Q.fileId}}function AZ(Q){let $=/\.([a-z0-9]+)$/.exec(Q?.trim().toLowerCase()??"");return $?.[1]!==void 0&&EZ.has($[1])}var EZ=new Set(["jpeg","jpg","png","gif","webp"]);function xZ(Q){if(!Q.id)return null;let $={type:"reasoning",id:Q.id};return $.summary=Q.text?[{type:"summary_text",text:Q.text}]:[],$}function wZ(Q){if(Q.status==="ok")return typeof Q.output==="string"?Q.output:JSON.stringify(Q.output??null);if(Q.status==="denied"){let $=Q.reason?` Reason given: ${Q.reason}`:"";if(Q.cause==="stopped")return`The run was stopped before this tool call could complete, so it did not run.${$}`;if(Q.cause==="interrupted")return`The run was interrupted (the server stopped) while this tool call was in progress, so its result was lost. It may have run in part or in full: check its effects before repeating it.${$}`;return`The user declined this tool call, so it did not run.${$}`}return`The tool call failed and produced no result. Error (${Q.error?.code??"unknown"}): ${Q.error?.message??"no message"}`}function c$(Q){return Array.isArray(Q.tools)}function bZ(Q,$){if(!Q||Q.length===0)return[];if(!$.toolSearch){let W=[];for(let X of Q)if(c$(X))for(let G of X.tools)W.push(AQ(G,!1));else W.push(AQ(X,!1));return W}let Z=[],J=!1;for(let W of Q)if(c$(W)){let X=W.tools.map((G)=>{if(G.deferred)J=!0;return AQ(G,!0)});Z.push({type:"namespace",name:W.name,description:W.description,tools:X})}else{if(W.deferred)J=!0;Z.push(AQ(W,!0))}if(J)Z.push({type:"tool_search"});return Z}function AQ(Q,$){let Z={type:"function",name:Q.name,description:Q.description,parameters:Q.parameters,strict:Q.strict};if($&&Q.deferred)Z.defer_loading=!0;return Z}class o{static models(){return[]}normalizeError(Q){return R(Q)}}var p$=["gpt-5.5","gpt-5.4","gpt-5.4-mini","gpt-5.4-nano","gpt-5.2","gpt-5.1","gpt-5","gpt-5-mini","gpt-5-nano","gpt-4.1","gpt-4.1-mini","gpt-4.1-nano","gpt-4o","gpt-4o-mini","o4-mini","o3","o3-mini"];class S9 extends o{model;capabilities;config;constructor(Q,$={}){super();this.model=Q,this.capabilities=_9(Q),this.config=$}static model(Q,$){return new S9(Q,$)}static models(){return p$}stream(Q){let $=M9(Q,{model:this.model,capabilities:this.capabilities});return O9(this.endpoint(),$,{signal:Q.signal,structuredOutput:Boolean(Q.output),files:U9(Q.messages)})}upload(Q){return N9(this.endpoint(),Q)}endpoint(){return P9(SQ(this.config))}}class R9 extends o{model;capabilities;config;constructor(Q,$={}){super();this.model=Q,this.capabilities=_9(Q),this.config=$}static model(Q,$){return new R9(Q,$)}static models(){return p$}stream(Q){let $=M9(Q,{model:this.deployment(),capabilities:this.capabilities});return O9(this.endpoint(),$,{signal:Q.signal,structuredOutput:Boolean(Q.output),files:U9(Q.messages)})}upload(Q){return N9(this.endpoint(),Q,"assistants")}deployment(){return this.config.deployment??this.model}endpoint(){return P9(RQ(this.config))}}function IZ(Q){switch(Q.type){case"text-delta":case"reasoning-delta":case"tool-call-delta":case"tool-call":case"tool-search":case"output-delta":return!0;default:return!1}}var m$=Symbol("timed-out");class WQ extends o{model;capabilities;entries;options;constructor(Q,$={}){super();if(Q.length===0)throw Error("FallbackProvider needs at least one provider.");for(let Z of Q)if(Z.timeoutMs!==void 0&&!(Z.timeoutMs>0))throw Error(`FallbackProvider: timeoutMs for ${Z.provider.model} must be a positive number, got ${Z.timeoutMs}.`);this.entries=[...Q],this.options=$,this.model=Q[0].provider.model,this.capabilities=vZ(Q.map((Z)=>Z.provider.capabilities))}static chain(Q,$){return new WQ(Q,$)}from(Q){if(!Number.isInteger(Q)||Q<0||Q>=this.entries.length)throw RangeError(`FallbackProvider.from(${Q}): the chain has ${this.entries.length} entries.`);return new WQ(this.entries.slice(Q),this.options)}leg(Q){let $=this.from(Q).entries[0];return new WQ([$],this.options)}upload(Q){return this.entries[0].provider.upload(Q)}normalizeError(Q){return this.entries[0].provider.normalizeError(Q)}stream(Q){return this.run(Q)}async*run(Q){let $,Z=Q.signal;for(let J=0;J<this.entries.length;J++){let W=this.entries[J],X=J===this.entries.length-1,G=J+1,H=W.provider.model,V=new AbortController,Y=()=>V.abort(Z?.reason);if(Z?.aborted)V.abort(Z.reason);else Z?.addEventListener("abort",Y,{once:!0});let K=[],z=!1,B=!1,U,F,D=!1,P,L=!1,_=(C)=>{let j=$?M(M(q(),$),C.usage):C.usage;return $=void 0,{...C,usage:j}};try{P=W.provider.stream({...Q,...W.reasoning!==void 0?{reasoning:W.reasoning}:{},signal:V.signal})[Symbol.asyncIterator]();let C=!0;for(;;){let j=C&&W.timeoutMs!==void 0?await fZ(P.next(),W.timeoutMs):await P.next();if(j===m$){D=!0,F={error:{code:"provider_error",message:`${H} sent nothing within ${W.timeoutMs}ms.`,retryable:!0}};break}if(C=!1,j.done){L=!0;break}let O=j.value;if(z){if(O.type==="finish")U=M(U??q(),O.usage),B=!0,yield _(O);else{if(O.type==="error")F={error:O.error};yield O}continue}if(IZ(O)){z=!0,yield*K.splice(0),yield O;continue}if(O.type==="error")F={error:O.error,...O.status!==void 0?{status:O.status}:{},...O.requestId!==void 0?{requestId:O.requestId}:{}};else if(O.type==="finish"){if(U=M(U??q(),O.usage),O.reason==="error"&&!F)F={error:{code:"provider_error",message:`${H} ended the call with an error and did not say which.`,retryable:!1}}}K.push(O)}}catch(C){let j=W.provider.normalizeError(C);if(z){if(j.code!=="aborted")yield{type:"error",error:j,...T(C)};this.report({index:J,model:H,attempt:G,usage:U,outcome:k9(j),error:j}),yield _({type:"finish",reason:j.code==="aborted"?"aborted":"error",usage:q()});return}F={error:j,...T(C)}}finally{if(Z?.removeEventListener("abort",Y),!L)V.abort(),P?.return?.()?.catch(()=>{})}if(z){if(!B&&$)yield{type:"finish",reason:F?"error":"stop",usage:$},$=void 0;this.report({index:J,model:H,attempt:G,usage:U,outcome:F?k9(F.error):"ok",...F?{error:F.error}:{}});return}if(Z?.aborted){this.report({index:J,model:H,attempt:G,usage:U,outcome:"aborted"}),yield _({type:"finish",reason:"aborted",usage:U??q()});return}if(!F){this.report({index:J,model:H,attempt:G,usage:U,outcome:"ok"});for(let C of K)yield C.type==="finish"?_(C):C;return}let N=!X&&F.error.code!=="aborted"&&this.shouldFallBack(F.error,{index:J,model:H,timedOut:D,...F.status!==void 0?{status:F.status}:{},...F.requestId!==void 0?{requestId:F.requestId}:{}});if(this.report({index:J,model:H,attempt:G,usage:U,outcome:N?"fallback":k9(F.error),error:F.error}),N){if(U)$=M($??q(),U);continue}let w=!1,k;for(let C of K){if(C.type==="finish"){k=C;continue}if(C.type==="error")w=!0;yield C}if(!w&&F.error.code!=="aborted")yield{type:"error",error:F.error,...F.status!==void 0?{status:F.status}:{},...F.requestId!==void 0?{requestId:F.requestId}:{}};yield _({type:"finish",reason:F.error.code==="aborted"?"aborted":k?.reason??"error",usage:U??q()});return}}shouldFallBack(Q,$){let Z=this.options.fallbackOn??((J)=>J.retryable);try{return Z(Q,$)}catch{return!1}}report(Q){if(Q.usage===void 0)delete Q.usage;try{this.options.onUsage?.(Q)}catch{}}}function k9(Q){return Q.code==="aborted"?"aborted":"failed"}function vZ(Q){return{reasoning:Q.every(($)=>$.reasoning),structuredOutput:Q.every(($)=>$.structuredOutput),fileInput:Q.every(($)=>$.fileInput),parallelToolCalls:Q.every(($)=>$.parallelToolCalls),toolSearch:Q.every(($)=>$.toolSearch)}}function fZ(Q,$){let Z,J=new Promise((W)=>{Z=setTimeout(()=>W(m$),$)});return Promise.race([Q,J]).finally(()=>clearTimeout(Z))}async function hZ(Q,$,Z={}){let J=Z.samples??1;if(!Number.isInteger(J)||J<1)throw RangeError(`evalChain: samples must be a positive integer, got ${J}.`);let W=[];for(let X=0;X<Q.entries.length;X++){let G=Q.leg(X),H={index:X,model:G.model,results:[],errors:[]};for(let V=0;V<J;V++)try{H.results.push(await $(G,{index:X,sample:V}))}catch(Y){H.errors.push({sample:V,error:Y})}W.push(H)}return W}class n extends Error{runId;requested;oldest;code="frame_cursor_evicted";constructor(Q,$,Z){super(`Frame ${$} of run ${Q} has been evicted; the oldest frame still buffered is ${Z}. Reload the thread instead of resuming.`);this.runId=Q;this.requested=$;this.oldest=Z}}class XQ extends Error{runId;code="live_run_not_found";constructor(Q){super(`No live run ${Q} in this process.`);this.runId=Q}}class EQ{ttlMs;maxFrames;maxAgeMs;runs=new Map;byThread=new Map;byClientRun=new Map;constructor(Q={}){this.ttlMs=Q.ttlMs??60000,this.maxFrames=Q.maxFrames??4096,this.maxAgeMs=Q.maxAgeMs===void 0?3600000:Q.maxAgeMs}register(Q,$={}){let Z={run:Q,threadId:$.threadId,owner:$.owner??null,clientRunId:$.clientRunId,frames:[],lastSeq:-1,lostBefore:0,ended:!1,evicted:!1,evictAt:null,expireAt:null,wake:new Set,version:0};if(this.runs.set(Q.runId,Z),$.threadId)this.byThread.set($.threadId,Q.runId);if($.clientRunId)this.byClientRun.set($.clientRunId,Q.runId);return this.scheduleExpiry(Z,$.maxRunDurationMs),this.pump(Z,$)}findByClientRunId(Q){let $=this.byClientRun.get(Q);return $&&this.runs.has($)?$:null}async find(Q){let $=this.byThread.get(Q.threadId);if(!$)return null;let Z=this.runs.get($);if(!Z)return null;return{runId:$,seq:Z.lastSeq}}get(Q){return this.runs.get(Q)?.run??null}ownerOf(Q){return this.runs.get(Q)?.owner??null}mayAccess(Q,$){let Z=this.ownerOf(Q);return Z===null||Z===$}isRunning(Q){let $=this.runs.get(Q);return!!$&&!$.ended&&!$.evicted}replay(Q,$){let Z=this.runs.get(Q);if(!Z)throw new XQ(Q);if($!==void 0&&$<Z.lostBefore)throw new n(Q,$,Z.lostBefore);let J=Z.frames[0]?.seq;return this.drain(Z,Q,$??J??Z.lastSeq+1)}clear(){for(let Q of this.runs.values()){if(Q.evictAt)clearTimeout(Q.evictAt);if(Q.expireAt)clearTimeout(Q.expireAt);Q.ended=!0,this.notify(Q)}this.runs.clear(),this.byThread.clear(),this.byClientRun.clear()}get size(){return this.runs.size}async pump(Q,$){let Z=Promise.resolve();try{for await(let J of Q.run.frames()){if(Q.evicted){let X=$.onEvent;if(X)Z=Z.then(()=>X(J.event)).catch((G)=>T9($,G));continue}if(Q.frames.push(J),Q.lastSeq=J.seq,Q.frames.length>this.maxFrames){let X=Q.frames.shift();if(X)Q.lostBefore=X.seq+1}this.notify(Q);let W=$.onEvent;if(W)Z=Z.then(()=>W(J.event)).catch((X)=>T9($,X))}}catch(J){T9($,J)}finally{if(Q.ended=!0,Q.expireAt)clearTimeout(Q.expireAt),Q.expireAt=null;this.notify(Q),this.scheduleEviction(Q),await Z}}async*drain(Q,$,Z){let J=Z;while(!0){let W=Q.version;for(;;){if(J<Q.lostBefore)throw new n($,J,Q.lostBefore);let X=Q.frames,G=X[0]?.seq;if(G===void 0)break;let H=Math.max(0,J-G);if(H>=X.length)break;let V=X[H];yield V,J=V.seq+1}if(Q.ended&&J>Q.lastSeq||Q.evicted)return;await this.wait(Q,W)}}wait(Q,$){if(Q.version!==$)return Promise.resolve();return new Promise((Z)=>Q.wake.add(Z))}notify(Q){Q.version++;let $=Array.from(Q.wake);Q.wake.clear();for(let Z of $)Z()}scheduleEviction(Q){if(Q.evictAt)return;let $=setTimeout(()=>{let Z=Q.run.runId;if(!Q.ended)Q.evicted=!0,Q.frames=[];if(this.runs.get(Z)===Q)this.runs.delete(Z);if(Q.threadId&&this.byThread.get(Q.threadId)===Z)this.byThread.delete(Q.threadId);if(Q.clientRunId&&this.byClientRun.get(Q.clientRunId)===Z)this.byClientRun.delete(Q.clientRunId);this.notify(Q)},this.ttlMs);$.unref?.(),Q.evictAt=$}scheduleExpiry(Q,$){if(this.maxAgeMs===null||$===null)return;let Z=$===void 0?this.maxAgeMs:Math.max(this.maxAgeMs,$+this.ttlMs);if(!Number.isFinite(Z)||Z>2147483647)return;let J=setTimeout(()=>{if(Q.expireAt=null,Q.ended)return;try{Q.run.stop({reason:`The run was still going ${Math.round(Z/1000)}s after it started, past the live-run registry's age limit.`})}catch{}this.scheduleEviction(Q)},Z);J.unref?.(),Q.expireAt=J}}var A9=new EQ;function T9(Q,$){try{Q.onInternalError?.($)}catch{}}class xQ{maxEntries;records=new Map;constructor(Q=1e5){this.maxEntries=Q}async record(Q,$){if(this.records.has(Q))return;this.records.set(Q,{...$});while(this.records.size>this.maxEntries){let Z=this.records.keys().next().value;if(Z===void 0)break;this.records.delete(Z)}}async get(Q){let $=this.records.get(Q);return $?{...$}:null}}var E9=new xQ;class wQ{ttlMs;clientOwnedIds;threads=new Map;lastSweep=0;constructor(Q={}){this.ttlMs=Q.ttlMs??86400000,this.clientOwnedIds=Q.clientOwnedIds??!1}async createThread(Q){let $=crypto.randomUUID();return this.threads.set($,{messages:[],touchedAt:Date.now()}),this.sweep(),{threadId:$}}async loadThread(Q){this.sweep();let $=this.threads.get(Q);if(!$)return this.clientOwnedIds?[]:null;return $.touchedAt=Date.now(),$.messages.slice()}async appendMessages(Q,$){this.sweep();let Z=this.threads.get(Q);if(!Z){if(!this.clientOwnedIds)throw Error(`Thread ${Q} does not exist here, or has expired.`);Z={messages:[],touchedAt:Date.now()},this.threads.set(Q,Z)}for(let J of $){let W=Z.messages.findIndex((X)=>X.id===J.id);if(W===-1)Z.messages.push(J);else Z.messages[W]=J}Z.touchedAt=Date.now()}async removeMessages(Q,$){this.sweep();let Z=this.threads.get(Q);if(!Z)return;let J=new Set($);Z.messages=Z.messages.filter((W)=>!J.has(W.id)),Z.touchedAt=Date.now()}delete(Q){this.threads.delete(Q)}get size(){return this.threads.size}sweep(Q=Date.now()){if(Q-this.lastSweep<60000)return;this.lastSweep=Q;for(let[$,Z]of this.threads)if(Q-Z.touchedAt>this.ttlMs)this.threads.delete($)}}var x9=new wQ;function o$(Q={}){return{messages:Q.messages?[...Q.messages]:[],pending:Q.pending?[...Q.pending]:[],error:null,threadId:Q.threadId,seq:Q.seq??-1,cursorRunId:Q.cursorRunId,runMessageIds:[],loadedTools:[]}}function n$(Q,$,Z=new Date().toISOString()){if(!($.event.type==="run-start"&&$.event.runId!==Q.cursorRunId)&&$.seq<=Q.seq)return Q;return{...s$(Q,$.event,Z),seq:$.seq}}function s$(Q,$,Z){switch($.type){case"run-start":return{...Q,runId:$.runId,cursorRunId:$.runId,threadId:$.threadId??Q.threadId,runMessageIds:[],loadedTools:[],finishReason:void 0,usage:void 0};case"message-start":return u(Q,$.messageId,Z,(J)=>({...J,role:$.role}));case"text-delta":if(l$(Q,$.messageId))return Q;return u(Q,$.messageId,Z,(J)=>({...J,content:pZ(J.content,$.delta)}));case"reasoning-delta":if(l$(Q,$.messageId))return Q;return u(Q,$.messageId,Z,(J)=>({...J,content:mZ(J.content,$.delta,$.id)}));case"output-delta":return u(Q,$.messageId,Z,(J)=>({...J,content:i$(J.content,{type:"output",value:$.snapshot,partial:!0},(W)=>W.type==="output")}));case"tool-call":return u(Q,$.messageId,Z,(J)=>{let W=J.content.findIndex((z)=>z.type==="tool-call"&&z.toolCallId===$.part.toolCallId),X=W===-1?void 0:J.content[W],G=$.part.progress??X?.progress,H=$.part.nested??X?.nested,V=$.part.attachments??X?.attachments,Y={...$.part,...G?{progress:G}:{},...H?{nested:H}:{},...V?{attachments:V}:{}},K=J.content.slice();if(W===-1)K.push(Y);else K[W]=Y;return{...J,content:K}});case"tool-search":{let J=$.loaded.filter((W)=>!Q.loadedTools.includes(W));if(J.length===0)return Q;return{...Q,loadedTools:[...Q.loadedTools,...J]}}case"tool-progress":return d$(Q,$.toolCallId,(J)=>({...J,progress:[...J.progress??[],$.data]}));case"nested-event":{let J=$;return d$(Q,$.toolCallId,(W)=>{let X=W.nested??[],G=X.findIndex((K)=>K.runId===J.runId),H=X[G]??{runId:J.runId,agent:J.agent,messages:[]},V=uZ(H,J,Z),Y=G===-1?[...X,V]:X.map((K,z)=>z===G?V:K);return{...W,nested:Y}})}case"tool-result":{let J=u(Q,$.messageId,Z,(W)=>({...W,content:i$(W.content,$.part,(X)=>X.type==="tool-result"&&X.toolCallId===$.part.toolCallId)}));return{...J,pending:J.pending.filter((W)=>W.toolCallId!==$.part.toolCallId)}}case"message":{let J=Q.messages.findIndex((G)=>G.id===$.message.id),W=Q.messages.slice();if(J===-1)W.push($.message);else W[J]=$.message;let X=Q.runMessageIds.includes($.message.id)?Q.runMessageIds:[...Q.runMessageIds,$.message.id];return{...Q,messages:W,runMessageIds:X}}case"awaiting-input":return{...Q,runId:$.runId,pending:[...$.pending]};case"message-end":return u(Q,$.messageId,Z,(J)=>({...J,finishReason:$.finishReason,...$.outputTruncated?{outputTruncated:!0}:{},...$.usage?{usage:$.usage}:{},content:$.outputTruncated||$.finishReason==="length"?J.content.filter((W)=>!(W.type==="output"&&W.partial)):J.content.map((W)=>W.type==="output"&&W.partial?{...W,partial:!1}:W)}));case"usage":return{...Q,usage:$.usage};case"error":return{...Q,error:$.error,pending:[]};case"run-end":return{...Q,runId:void 0,finishReason:$.finishReason,messages:t$(Q,$.finishReason)};default:return Q}}function t$(Q,$){return Q.messages.map((Z)=>Z.role==="assistant"&&Q.runMessageIds.includes(Z.id)?yZ(Z,$):Z)}function yZ(Q,$){let Z=Q.content.map((W)=>W.type==="tool-call"&&W.nested?.some((X)=>X.finishReason===void 0)?{...W,nested:W.nested.map((X)=>X.finishReason===void 0?gZ(X,$):X)}:W);if(Q.finishReason===void 0)return{...Q,finishReason:$,content:Z};return Z.some((W,X)=>W!==Q.content[X])?{...Q,content:Z}:Q}function gZ(Q,$){let Z={messages:Q.messages,pending:[],error:null,seq:-1,runMessageIds:Q.messages.map((J)=>J.id),loadedTools:[]};return{...Q,finishReason:$,messages:t$(Z,$)}}function d$(Q,$,Z){for(let J=Q.messages.length-1;J>=0;J--){let W=Q.messages[J],X=W.content.findIndex((Y)=>Y.type==="tool-call"&&Y.toolCallId===$);if(X===-1)continue;if(W.finishReason!==void 0&&!cZ(Q,W,$))return Q;let G=W.content.slice();G[X]=Z(G[X]);let H=Q.messages.slice();H[J]={...W,content:G};let V=Q.runMessageIds.includes(W.id)?Q.runMessageIds:[...Q.runMessageIds,W.id];return{...Q,runMessageIds:V,messages:H}}return Q}function uZ(Q,$,Z){let J={messages:Q.messages,pending:[],error:null,seq:-1,runMessageIds:Q.messages.map((X)=>X.id),loadedTools:[],finishReason:Q.finishReason},W=s$(J,$.event,Z);return{...Q,...$.label!==void 0?{label:$.label}:{},messages:W.messages,...W.finishReason!==void 0?{finishReason:W.finishReason}:{},...W.usage!==void 0?{usage:W.usage}:{}}}function cZ(Q,$,Z){if($.finishReason!=="awaiting-input")return!1;return!Q.messages.some((J)=>J.content.some((W)=>W.type==="tool-result"&&W.toolCallId===Z))}function l$(Q,$){let Z=Q.messages.find((J)=>J.id===$);return Z!==void 0&&Z.finishReason!==void 0}function u(Q,$,Z,J){let W=Q.messages.findIndex((H)=>H.id===$),X=Q.runMessageIds.includes($)?Q.runMessageIds:[...Q.runMessageIds,$];if(W===-1){let H={id:$,role:"assistant",content:[],createdAt:Z};return{...Q,runMessageIds:X,messages:[...Q.messages,J(H)]}}let G=Q.messages.slice();return G[W]=J(G[W]),{...Q,runMessageIds:X,messages:G}}function pZ(Q,$){let Z=Q[Q.length-1];if(Z&&Z.type==="text")return[...Q.slice(0,-1),{type:"text",text:Z.text+$}];return[...Q,{type:"text",text:$}]}function mZ(Q,$,Z){let J=Q[Q.length-1];if(J&&J.type==="reasoning"&&J.id===Z)return[...Q.slice(0,-1),{...J,text:(J.text??"")+$}];return[...Q,Z?{type:"reasoning",id:Z,text:$}:{type:"reasoning",text:$}]}function i$(Q,$,Z){let J=Q.findIndex(Z);if(J===-1)return[...Q,$];let W=Q.slice();return W[J]=$,W}class b9{store;threadId;report;chain=Promise.resolve();done=new Set;closed=!1;state;runId;constructor(Q,$,Z,J){this.store=Q;this.threadId=$;this.report=J;this.state=o$({messages:Z})}finish(Q){if(this.closed)return;this.done.add(Q.id),this.write(()=>[w9(Q)])}frame(Q){if(this.closed)return;let $=Q.event;if($.type==="run-start")this.runId=$.runId;switch(this.state=n$(this.state,Q),$.type){case"message":this.write(()=>[w9($.message)]);return;case"tool-call":if($.part.partial)return;this.checkpoint($.messageId);return;case"message-start":case"tool-result":this.checkpoint($.messageId);return;default:return}}close(Q=[]){this.closed=!0;for(let $ of Q)this.done.add($.id)}settled(){return this.chain}checkpoint(Q){if(this.done.has(Q))return;let $=this.state.messages.find((J)=>J.id===Q);if(!$)return;let Z=this.runId;this.write(()=>{let J=w9($);if(J.finishReason===void 0&&Z)J.runId=Z;return[J]})}write(Q){let $;try{$=Q()}catch(Z){this.report(Z);return}this.chain=this.chain.then(()=>this.store.appendMessages(this.threadId,$)).catch((Z)=>this.report(Z))}}function w9(Q){return structuredClone(Q)}async function a$(Q,$){let Z=[],J=null,W=Q.slice();for(let X=0;X<W.length;X++){let G=W[X];if(G.role!=="assistant"||G.finishReason!==void 0)continue;if(G.runId&&await $(G.runId))continue;J??=new Set(Q.flatMap((Y)=>Y.content.flatMap((K)=>K.type==="tool-result"?[K.toolCallId]:[])));let H=G.content.map((Y)=>Y.type==="tool-call"?r$(Y):Y);for(let Y of G.content){if(Y.type!=="tool-call"||J.has(Y.toolCallId))continue;let K={type:"tool-result",toolCallId:Y.toolCallId,name:Y.name,status:"denied",cause:"interrupted"};H.push(K)}let V={...G,content:H,finishReason:"interrupted"};W[X]=V,Z.push(V)}return{messages:W,settled:Z}}function r$(Q){let{partial:$,...Z}=Q;if(!Z.nested?.some((J)=>J.finishReason===void 0))return Z;return{...Z,nested:Z.nested.map(dZ)}}function dZ(Q){if(Q.finishReason!==void 0)return Q;return{...Q,finishReason:"interrupted",messages:Q.messages.map(($)=>$.role==="assistant"&&$.finishReason===void 0?{...$,finishReason:"interrupted",content:$.content.map((Z)=>Z.type==="tool-call"?r$(Z):Z)}:$)}}var lZ=H3,bQ=new Map,e$=new WeakMap,IQ=new Map,iZ=4194304,oZ=1000,nZ=5,Q3=65536,D3=()=>{};class U3{byKey=new Map;take(Q,$,Z){let J=this.byKey.get(Q);if(!J?.has($)&&(J?.size??0)>=Z)return null;if(!J)J=new Map,this.byKey.set(Q,J);J.set($,(J.get($)??0)+1);let W=!1;return()=>{if(W)return;W=!0;let X=this.byKey.get(Q),G=(X?.get($)??1)-1;if(!X)return;if(G>0)X.set($,G);else if(X.delete($),X.size===0)this.byKey.delete(Q)}}}var $3=new WeakMap;function sZ(Q){let $=$3.get(Q);if(!$)$=new U3,$3.set(Q,$);return $}class F3 extends lZ{static kind="agent-controller";store=x9;liveRuns=A9;attachments=OQ;attachmentStorage=z3;fileOwners=E9;nonces=p;requireKnownFiles=!1;hookHoldMs=30000;instructions(Q,$){}context(Q,$){return{}}requireThread=!1;maxBodyBytes=iZ;maxHistoryMessages=oZ;maxConcurrentRuns=nZ;runLimitKey(Q,$){return $.owner}authorizeRequest(Q,$){}runOwner(Q){let $=Q.ctx?.()?.user,Z=$?.id??$?.publicId;if(Z!==void 0&&Z!==null&&String(Z)!=="")return`user:${String(Z)}`;return null}async stream(Q=new GQ){let $=await I9(Q,this.maxBodyBytes);if($.error)return vQ($);let Z=$.body,J=typeof Z.threadId==="string"?Z.threadId:void 0,W=J6(Z);if(W.error)return vQ({body:{},error:W.error});let X=W.turn,G=J!==void 0&&Z.regenerate===!0,H=typeof Z.clientRunId==="string"?Z.clientRunId:void 0,V=C3(Z);if(this.requireThread&&!J)return E(400,{code:"thread_required",message:"This agent takes a turn only on a thread: send a threadId."});if(G&&!this.store.removeMessages)return E(501,{code:"regenerate_unsupported",message:"This agent's store cannot remove messages, so a thread's answer cannot be regenerated. Implement `removeMessages` on the AgentStore."});if(!J&&Array.isArray(Z.messages)&&Z.messages.length>this.maxHistoryMessages)return h9(413,"history_too_long",`The conversation has ${Z.messages.length} messages; this agent takes at most ${this.maxHistoryMessages}.`);let Y=await this.runOwner(Q),K=H?{cancelled:!1,owner:Y}:null;if(K)IQ.set(H,K);let z=null,B=[],U=async()=>{try{return await F()}finally{if(J&&B.length>0&&z===null)await this.store.appendMessages(J,B).catch((D)=>this.reportHookFailure(D))}},F=async()=>{let D;if(J){let x=await this.store.loadThread(J);if(!x)return E(404,{code:"thread_not_found",message:`Thread ${J} does not exist here, or has expired.`});if(D=await this.settleThread(J,x,{write:!0}),G){let c=V6(D);if(!c)return E(409,{code:"nothing_to_regenerate",message:`Thread ${J} has no user turn to answer again.`});B=D.slice(c.index),await this.store.removeMessages(J,B.map((O3)=>O3.id)),D=D.slice(0,c.index),X=c.turn}}else D=Array.isArray(Z.messages)?Z.messages:[],U6(this.nonces);let P=await this.instructions(Q,{body:V})||void 0,L=await this.context(Q,{body:V}),_=await this.attachmentsFor(Q,J,{body:V});if(K?.cancelled)return X3();let N=J?new b9(this.store,J,D,(x)=>this.reportHookFailure(x)):null,w=`run_${crypto.randomUUID()}`,k={req:Q,runId:w,threadId:J},C=this.agent.stream({runId:w,messages:D,turn:X,threadId:J,...N?{onMessage:(x)=>N.finish(x)}:{},instructions:P,context:L,attachments:_,body:V,redactError:(x,c)=>this.redactError(x,c,k),nonces:this.nonces,subject:Y}),j=this.liveRuns.register(C,{threadId:J,owner:Y,clientRunId:H,onEvent:(x)=>this.dispatchEvent(x,k),onInternalError:(x)=>this.reportHookFailure(x),maxRunDurationMs:this.agent.maxRunDurationMs});if(z=C,N)this.follow(C,N);let{stored:O,hooks:VQ}=this.persistRun(C,k,j,N);return e$.set(C,O),Q.ctx?.()?.waitUntil(VQ),C.toResponse()};try{await this.authorizeRequest(Q,{route:"stream",threadId:J,body:V});let D=await this.foreignFile([...X?.files??[],...J?[]:Y6(Z.messages)],Y);if(D)return D;if(K?.cancelled)return X3();let P=await this.runLimitKey(Q,{owner:Y,threadId:J}),L=P===null?D3:sZ(this.liveRuns).take(P,J?`thread:${J}`:`run:${crypto.randomUUID()}`,this.maxConcurrentRuns);if(!L)return h9(429,"too_many_runs",`You already have ${this.maxConcurrentRuns} conversations answering. Wait for one to finish, or stop it, and send again.`);try{return J?await this.withThread(J,Y,U):await U()}finally{let _=z;if(_)_.result().then(L,L);else L()}}finally{if(K&&IQ.get(H)===K)IQ.delete(H)}}async withThread(Q,$,Z){let J=bQ.get(Q)??Promise.resolve(),W,X=new Promise((H)=>{W=H}),G=J.then(()=>X);bQ.set(Q,G),await J;try{let H=await this.liveRuns.find({threadId:Q});if(H&&this.liveRuns.isRunning(H.runId)&&!this.liveRuns.mayAccess(H.runId,$))return fQ();let V=H?this.liveRuns.get(H.runId):null;if(V)V.stop({reason:"superseded by a later turn on this thread"}),await e$.get(V);return await Z()}finally{if(W(),bQ.get(Q)===G)bQ.delete(Q)}}async attach(Q=new GQ){let $=await I9(Q,Q3);if($.error)return vQ($);let Z=$.body,J=typeof Z.threadId==="string"?Z.threadId:G6(Q,"threadId");if(!J)return E(400,{code:"invalid_request",message:"attach needs a threadId: it is the handle that survives a refresh."});await this.authorizeRequest(Q,{route:"attach",threadId:J});let W=await this.liveRuns.find({threadId:J});if(W&&!this.liveRuns.mayAccess(W.runId,await this.runOwner(Q)))return fQ();if(!W)return E(404,{code:"no_live_run",message:`No run in progress for thread ${J} in this process.`});let X=typeof Z.runId==="string"?Z.runId:void 0,G=X&&X!==W.runId?void 0:X6(Q,Z);try{return V$(this.liveRuns.replay(W.runId,G))}catch(H){if(H instanceof n)return E(410,{code:H.code,message:H.message,oldestSeq:H.oldest});if(H instanceof XQ)return E(404,{code:H.code,message:H.message});throw H}}async stop(Q=new GQ){let $=await I9(Q,Q3);if($.error)return vQ($);let Z=$.body;await this.authorizeRequest(Q,{route:"stop",threadId:typeof Z.threadId==="string"?Z.threadId:void 0});let J=await this.runOwner(Q),W=typeof Z.runId==="string"?Z.runId:void 0;if(!W&&typeof Z.clientRunId==="string"){if(W=this.liveRuns.findByClientRunId(Z.clientRunId)??void 0,!W){let G=IQ.get(Z.clientRunId);if(G){if(G.owner!==null&&G.owner!==J)return fQ();return G.cancelled=!0,{stopped:!0}}}}if(!W&&typeof Z.threadId==="string")W=(await this.liveRuns.find({threadId:Z.threadId}))?.runId;let X=W?this.liveRuns.get(W):null;if(!X)return{stopped:!1};if(!this.liveRuns.mayAccess(X.runId,J))return fQ();return X.stop({reason:typeof Z.reason==="string"?Z.reason:void 0}),{stopped:!0}}attachmentScope(Q,$,Z){let J=Q.ctx()?.user,W=J?.id??J?.publicId;if(W!==void 0&&W!==null&&String(W)!=="")return{key:`user:${String(W)}`};if($)return{key:`thread:${$}`};return null}attachmentLimits(Q){return null}attachmentDestination(Q,$){return"both"}async attachmentsFor(Q,$,Z={body:{}}){let J=await this.attachmentScope(Q,$,Z);if(!J)return null;return new $Q(this.attachments,this.attachmentStorage,J)}async upload(Q=new GQ){let $=await Q.rawRequest.formData(),Z=$.get("file");if(!(Z instanceof Blob))throw Error("upload expects a multipart body with a `file` field.");let J=Z instanceof File&&Z.name?Z.name:"upload",W=Z.type||"application/octet-stream",X=aZ($.get("body")),G=$.get("threadId");await this.authorizeRequest(Q,{route:"upload",threadId:typeof G==="string"&&G.length>0?G:void 0,body:X});let H=eZ(await this.attachmentLimits(Q),Z,J,W);if(H)throw new L3(H.code,H.message);let V=typeof G==="string"&&G.length>0&&await this.store.loadThread(G)!==null?G:void 0,Y=await this.runOwner(Q),K=(N)=>this.fileOwners.record(N,{owner:Y,name:J,mimeType:W,size:Z.size,createdAt:new Date().toISOString()}),z=await this.attachmentDestination(Z,Q),B=K6(z,$.get("destination")),U=await this.attachmentScope(Q,V,{body:X}),F=B!=="provider"&&!U;if(F){if(B==="storage")throw Error('This upload was routed to storage, but `attachmentScope()` returned null for the request, so there is no subject to file the attachment under. Guard the route (`this.agent(Chat).middleware({ upload: "auth" })`), send a `threadId` with the upload, or override `attachmentScope()`.');z6()}if(B==="provider"||!U){let N=await Z3(this.agent.provider,Z);await K(N);let w={fileId:N,name:J,mimeType:W,size:Z.size,destination:"provider"};if(F)w.downgraded="no_scope";return w}let D=nQ(),P=await this.attachmentStorage.put({name:sQ(D,J),body:Z,contentType:W}),L=B==="both"?await Z3(this.agent.provider,Z):void 0;if(L)await K(L);let _={id:D,scopeKey:U.key,fileId:L,objectName:P,name:J,mimeType:W,size:Z.size,createdAt:new Date().toISOString(),destination:B};return await this.attachments.put(U,_),{fileId:L,attachmentId:D,name:J,mimeType:W,size:Z.size,destination:B}}async foreignFile(Q,$){let Z=new Set(Q.map((J)=>J.fileId).filter((J)=>typeof J==="string"));for(let J of Z){let W=await this.fileOwners.get(J);if(W?W.owner!==null&&W.owner!==$:this.requireKnownFiles)return H6()}return null}onMessage(Q,$){}onToolCall(Q,$){}onAwaitingInput(Q,$){}redactError(Q,$,Z){return y9(Q,$)}onError(Q,$){}onStreamComplete(Q,$){}reportHookFailure(Q){console.error("[gemi/ai] agent controller hook failed",Q)}async dispatchEvent(Q,$){switch(Q.type){case"tool-call":if(!Q.part.partial&&!Q.resent)await this.onToolCall({toolCallId:Q.part.toolCallId,name:String(Q.part.name),input:Q.part.input},$);return;case"awaiting-input":await this.onAwaitingInput(Q.pending,$);return;case"error":await this.onError(B3(Q.error),$);return;default:return}}async readThread(Q){let $=await this.store.loadThread(Q);return $?await this.settleThread(Q,$,{write:!1}):null}isRunLive(Q,$){return this.liveRuns.get(Q)!==null}async settleThread(Q,$,{write:Z}){let{messages:J,settled:W}=await a$($,(X)=>this.isRunLive(X,Q));if(Z&&W.length>0)try{await this.store.appendMessages(Q,W)}catch(X){this.reportHookFailure(X)}return J}follow(Q,$){(async()=>{try{for await(let Z of Q.frames())$.frame(Z)}catch(Z){this.reportHookFailure(Z)}})()}persistRun(Q,$,Z,J=null){let W=Promise.resolve(),X=(async()=>{let H;try{H=await Q.result()}catch(Y){J?.close(),await J?.settled(),W=this.safely(()=>this.onError({code:"unknown",message:Y instanceof Error?Y.message:String(Y),retryable:!1},$));return}let V=H.messages;if(J?.close(V),await J?.settled(),$.threadId&&V.length>0)try{await this.store.appendMessages($.threadId,V)}catch(Y){this.reportHookFailure(Y)}W=this.notifyRun(H,V,$)})(),G=X.then(()=>D6(Promise.all([W,Z]).then(()=>{}),this.hookHoldMs));return{stored:X,hooks:G}}async notifyRun(Q,$,Z){for(let J of $)await this.safely(()=>this.onMessage(J,Z));await this.safely(()=>this.onStreamComplete(Q,Z))}async safely(Q){try{await Q()}catch($){this.reportHookFailure($)}}}var v9=["turn","clientRunId","threadId","messages","regenerate"],tZ=["text","files","toolResults"];function C3(Q,$=P3(Q)?v9:[...v9,...tZ]){let Z={};for(let[J,W]of Object.entries(Q)){if($.includes(J))continue;Object.defineProperty(Z,J,{value:W,writable:!0,enumerable:!0,configurable:!0})}return Z}function aZ(Q){if(Q===null)return{};let $;if(typeof Q==="string")try{$=JSON.parse(Q)}catch{throw new f9("The upload's `body` field is not valid JSON.")}if($===null||typeof $!=="object"||Array.isArray($))throw new f9("The upload's `body` field must be a JSON object.");return C3($,v9)}class f9 extends hQ{constructor(Q){super(Q);this.name="InvalidUploadError",this.payload={api:{status:400,data:{error:{code:"invalid_request",message:Q}}},view:{}}}}async function Z3(Q,$){try{return await Q.upload($)}catch(Z){if(Z instanceof v&&rZ.has(Z.status))throw new j3(R(Z).message);throw Z}}var rZ=new Set([400,413,415,422]);class L3 extends hQ{constructor(Q,$){super($);this.name="LimitedUploadError",this.payload={api:{status:422,data:{error:{code:Q,message:$}}},view:{}}}}function eZ(Q,$,Z,J){if(!Q)return null;let{maxBytes:W,accept:X}=Q;if(typeof W==="number"&&$.size>W)return{code:"file_too_large",message:`${JSON.stringify(Z)} is ${J3($.size)}; the limit is ${J3(W)}.`};if(X&&X.length>0&&!X.some((G)=>Q6(G,Z,J)))return{code:"unsupported_file_type",message:`${JSON.stringify(Z)} is not a type this chat accepts. Accepted: ${X.join(", ")}.`};return null}function Q6(Q,$,Z){let J=Q.trim().toLowerCase();if(!J)return!1;if(J.startsWith("."))return $.toLowerCase().endsWith(J);let W=Z.toLowerCase().split(";")[0].trim();if(J.endsWith("/*"))return W.startsWith(J.slice(0,-1));return W===J}function J3(Q){if(Q<1024)return`${Q} B`;let $=["KB","MB","GB"],Z=Q/1024,J=0;while(Z>=1024&&J<$.length-1)Z/=1024,J++;return`${Math.round(Z*10)/10} ${$[J]}`}class j3 extends hQ{constructor(Q){super(Q);this.name="RejectedUploadError";let $=/(unsupported|invalid) (extension|file type|format|mime)|supported (extensions|formats?)/i.test(Q)?"unsupported_file_type":"file_rejected";this.payload={api:{status:422,data:{error:{code:$,message:Q}}},view:{}}}}async function I9(Q,$){let Z=Q?.rawRequest;if(!Z||Z.method==="GET"||Z.method==="HEAD"||!Z.body)return{body:{}};if(!$6(Z.headers.get("Content-Type")))return{body:{},status:415,code:"unsupported_media_type",error:"The request body must be sent as application/json."};let J=Number(Z.headers.get("Content-Length"));if(Number.isFinite(J)&&J>$)return W3($);let W;try{let G=await Z6(Z,$);if(G===null)return W3($);W=G}catch{return{body:{},error:"The request body could not be read."}}if(!W.trim())return{body:{}};let X;try{X=JSON.parse(W)}catch{return{body:{},error:"The request body is not valid JSON."}}if(X===null||typeof X!=="object"||Array.isArray(X))return{body:{},error:"The request body must be a JSON object."};return{body:X}}function $6(Q){return K3(Q)==="application/json"}async function Z6(Q,$){if(!Number.isFinite($)||!Q.body)return await Q.text();let Z=Q.body.getReader(),J=[],W=0;for(;;){let{done:H,value:V}=await Z.read();if(H)break;if(W+=V.byteLength,W>$)return await Z.cancel().catch(D3),null;J.push(V)}let X=new Uint8Array(W),G=0;for(let H of J)X.set(H,G),G+=H.byteLength;return new TextDecoder().decode(X)}function W3(Q){return{body:{},status:413,code:"body_too_large",error:`The request body is larger than this agent accepts (${Q} bytes).`}}function h9(Q,$,Z){return E(Q,{...yQ(Y3(Q),Z,Q),code:$})}function vQ(Q){if(Q.status===413)return h9(413,Q.code??"body_too_large",Q.error??"");return E(Q.status??400,{code:Q.code??"invalid_request",message:Q.error})}function P3(Q){return Boolean(Q.turn)&&typeof Q.turn==="object"}function J6(Q){let $=P3(Q)?Q.turn:Q,Z={};if(typeof $.text==="string")Z.text=$.text;if(Array.isArray($.files)){let J=W6($.files);if(typeof J==="string")return{error:J};Z.files=J}if(Array.isArray($.toolResults))Z.toolResults=$.toolResults;return Object.keys(Z).length>0?{turn:Z}:{}}function W6(Q){let $=[];for(let[Z,J]of Q.entries()){let W=`turn.files[${Z}]`;if(!J||typeof J!=="object"||Array.isArray(J))return`${W} must be an object.`;let X={};for(let K of["fileId","attachmentId","name","mimeType"]){let z=J[K];if(z===void 0||z===null||z==="")continue;if(typeof z!=="string")return`${W}.${K} must be a string.`;X[K]=z}let{fileId:G,attachmentId:H,name:V,mimeType:Y}=X;if(G?.startsWith(I))return`${W}.fileId holds a gemi attachment id (${G}). \`fileId\` is the provider's id from the upload response; put this one in \`attachmentId\`.`;if(H!==void 0&&!H.startsWith(I))return`${W}.attachmentId is not a gemi attachment id: it must start with "${I}".`;if(!G&&!H)return`${W} has neither a \`fileId\` nor an \`attachmentId\`. Send the ids the upload response answered.`;$.push({...G?{fileId:G}:{},...H?{attachmentId:H}:{},...V!==void 0?{name:V}:{},...Y!==void 0?{mimeType:Y}:{}})}return $}function X6(Q,$){if(typeof $.from==="number"&&Number.isFinite($.from))return Math.max(0,Math.floor($.from));if(typeof $.cursor==="number"&&Number.isFinite($.cursor)){let J=Math.floor($.cursor);if(J>=0)return J+1;return}let Z=Q?.rawRequest?.headers?.get("Last-Event-ID");if(Z){let J=Number.parseInt(Z,10);if(Number.isFinite(J))return Math.max(0,J+1)}return}function G6(Q,$){let Z=Q?.search?.get($);return typeof Z==="string"?Z:void 0}function V6(Q){let $=_Q(Q);for(let Z=Q.length-1;Z>=0;Z--){let J=Q[Z];if(J.role!=="user"||$.has(J.id))continue;let W="",X=[];for(let G of J.content){if(G.type==="text")W+=G.text;if(G.type==="file")X.push({...G.fileId?{fileId:G.fileId}:{},...G.attachmentId?{attachmentId:G.attachmentId}:{},...G.name?{name:G.name}:{},...G.mimeType?{mimeType:G.mimeType}:{}})}if(!W&&X.length===0)continue;return{index:Z,turn:{...W?{text:W}:{},...X.length>0?{files:X}:{}}}}return null}function X3(){return E(409,{code:"stopped",message:"The turn was stopped before it started."})}function fQ(){return E(403,yQ("permission","This run belongs to someone else.",403))}function H6(){return E(403,yQ("permission","A file in this turn was uploaded by someone else.",403))}function Y6(Q){if(!Array.isArray(Q))return[];let $=[];for(let Z of Q){let J=Z?.content;if(!Array.isArray(J))continue;for(let W of J)if(W&&typeof W==="object"&&typeof W.fileId==="string")$.push({fileId:W.fileId})}return $}function E(Q,$){return new Response(JSON.stringify({error:$}),{status:Q,headers:{"Content-Type":"application/json"}})}function K6(Q,$){if(typeof $!=="string"||$.length===0)return Q;if($!=="both"&&$!=="provider"&&$!=="storage")throw Error(`Unknown attachment destination "${$}". Expected "both", "provider" or "storage".`);if($===Q||Q==="both"&&$==="storage")return $;if(Q==="both"&&$==="provider")throw Error('This upload asked for the "provider" destination under a "both" policy. A client may ask for "storage", which keeps a file away from the model provider, but it may not ask the server to stop keeping its own copy while the vendor still gets the file \u2014 that is the app\'s retention decision. Change `attachmentDestination()` if this file should not be kept.');throw Error(`This upload asked for the "${$}" destination, but the server's policy for it is "${Q}", and a client hint may only ask for "storage" under a "both" policy. Change \`attachmentDestination()\` if the file really should go there.`)}var G3=!1;function z6(){if(G3)return;G3=!0,console.warn("[gemi/ai] An upload had no attachment scope, so its bytes were sent to the model provider only and no attachment id was minted \u2014 a tool cannot forward this file. Guard the route with auth, send a `threadId` with the upload, or override `attachmentScope()`.")}var B6=2147483647;function D6(Q,$){let Z=Q.then(()=>{},()=>{});if(!($<=B6))return Z;let J,W=new Promise((X)=>{J=setTimeout(X,$)});return Promise.race([Z,W]).finally(()=>clearTimeout(J))}var V3=!1;function U6(Q){if(V3||Bun.env.NODE_ENV!=="production")return;if(!(Q instanceof e))return;V3=!0,console.warn("[gemi/ai] A stateless agent chat is spending approval nonces in process memory. With more than one instance a replayed approval is accepted once per instance. Set `nonces = new RedisNonceStore()` (or your own NonceStore) on the AgentController.")}export{QZ as toAgentTools,s as supportsStrict,C6 as s,y9 as redactError,A9 as liveRuns,R3 as generate,hZ as evalChain,p as defaultNonceStore,E9 as defaultFileOwners,OQ as defaultAttachmentStore,x9 as defaultAgentStore,MQ as ToolNamespace,S as ToolError,W9 as Skill,$Q as ScopedAttachments,ZQ as SKILLS_NAMESPACE,cQ as RedisNonceStore,h as PendingEscalation,S9 as OpenAIProvider,B9 as OpenAIImageProvider,e as MemoryNonceStore,EQ as MemoryLiveRuns,xQ as MemoryFileOwners,PQ as MemoryAttachmentStore,wQ as MemoryAgentStore,XQ as LiveRunNotFoundError,F6 as JSONSchemaError,d as InvalidAttachmentScopeError,kQ as ImageRequestError,TQ as ImageProvider,Y9 as ImageModel,n as FrameCursorEvictedError,WQ as FallbackProvider,V9 as DEFAULT_MAX_RUN_DURATION_MS,R9 as AzureOpenAIProvider,D9 as AzureOpenAIImageProvider,QQ as AttachmentNotFoundError,y as AgentTool,r as AgentRunError,o as AgentProvider,F3 as AgentController,H9 as Agent};
|
|
19
19
|
|
|
20
|
-
//# debugId=
|
|
20
|
+
//# debugId=F8A17A337CFBCBA164756E2164756E21
|