@alvin0/ai-agent-sdk-core 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/define/session/config.js +1 -1
  3. package/dist/agent/define/session/config.js.map +1 -1
  4. package/dist/agent/define/session/types.d.ts +14 -0
  5. package/dist/agent/define/session/types.d.ts.map +1 -1
  6. package/dist/agent/define/session.d.ts.map +1 -1
  7. package/dist/agent/define/session.js +1 -1
  8. package/dist/agent/define/session.js.map +1 -1
  9. package/dist/agent/loop/events.d.ts +24 -1
  10. package/dist/agent/loop/events.d.ts.map +1 -1
  11. package/dist/agent/loop/run-turn.js +1 -1
  12. package/dist/agent/loop/run-turn.js.map +1 -1
  13. package/dist/agent/loop/schedule.d.ts.map +1 -1
  14. package/dist/agent/loop/schedule.js +1 -1
  15. package/dist/agent/loop/schedule.js.map +1 -1
  16. package/dist/agent/loop/turn/config.js +1 -1
  17. package/dist/agent/loop/turn/config.js.map +1 -1
  18. package/dist/agent/loop/turn/model-request-boundary.js +1 -1
  19. package/dist/agent/loop/turn/model-request-boundary.js.map +1 -1
  20. package/dist/agent/loop/turn/model-round.js +1 -1
  21. package/dist/agent/loop/turn/model-round.js.map +1 -1
  22. package/dist/agent/loop/turn/types.d.ts +35 -2
  23. package/dist/agent/loop/turn/types.d.ts.map +1 -1
  24. package/dist/agent/loop/types.d.ts +16 -0
  25. package/dist/agent/loop/types.d.ts.map +1 -1
  26. package/dist/agent/mode/run-agent.d.ts +9 -0
  27. package/dist/agent/mode/run-agent.d.ts.map +1 -1
  28. package/dist/agent/mode/run-agent.js +2 -2
  29. package/dist/agent/mode/run-agent.js.map +1 -1
  30. package/dist/agent/mode/user-input.d.ts.map +1 -1
  31. package/dist/agent/mode/user-input.js +1 -1
  32. package/dist/agent/mode/user-input.js.map +1 -1
  33. package/dist/agent/team/managed.d.ts.map +1 -1
  34. package/dist/agent/team/managed.js +1 -1
  35. package/dist/agent/team/managed.js.map +1 -1
  36. package/dist/agent/tool/capture.js +1 -1
  37. package/dist/agent/tool/capture.js.map +1 -1
  38. package/dist/agent/tool/definition.d.ts +7 -0
  39. package/dist/agent/tool/definition.d.ts.map +1 -1
  40. package/dist/agent/tool/definition.js.map +1 -1
  41. package/dist/agent.js +1 -1
  42. package/dist/composition/agent/public-event.d.ts +19 -0
  43. package/dist/composition/agent/public-event.d.ts.map +1 -0
  44. package/dist/composition/agent/public-event.js +2 -0
  45. package/dist/composition/agent/public-event.js.map +1 -0
  46. package/dist/composition/agent/session.js +1 -1
  47. package/dist/composition/agent/session.js.map +1 -1
  48. package/dist/composition/agent/types.d.ts +11 -1
  49. package/dist/composition/agent/types.d.ts.map +1 -1
  50. package/dist/index.d.ts +2 -1
  51. package/dist/index.js +1 -1
  52. package/dist/observability/bus.js +1 -1
  53. package/dist/observability/bus.js.map +1 -1
  54. package/dist/primitives/version.d.ts +1 -1
  55. package/dist/primitives/version.js +1 -1
  56. package/dist/primitives/version.js.map +1 -1
  57. package/dist/runtime/registry.js +1 -1
  58. package/dist/runtime/registry.js.map +1 -1
  59. package/dist/runtime/with-retry.d.ts +15 -0
  60. package/dist/runtime/with-retry.d.ts.map +1 -1
  61. package/dist/runtime/with-retry.js +1 -1
  62. package/dist/runtime/with-retry.js.map +1 -1
  63. package/package.json +1 -1
@@ -1,2 +1,2 @@
1
- import{detachedFrozen as e}from"../../primitives/snapshot.js";import{waitForSettlement as t}from"../../async/settlement.js";import{createSpanId as n,createTraceId as r}from"../../observation/context.js";import{createUserMessage as i}from"../../message/message.js";import{authoritativeTokenUsage as a,budgetTokenTotal as o,summarizeModelCallUsage as s}from"../accounting/usage.js";import{ContextSectionRuntime as c}from"../context/section.js";import{deliverQueuedInput as l}from"./turn/model-request-boundary.js";import{AwaitedEventQueue as u}from"./queue.js";import{captureProgramGrants as d}from"../tool/nested.js";import{scheduleToolCalls as ee}from"./schedule.js";import{ProgramResultStore as f}from"../tool/program-results.js";import{positiveFinite as p,resolveBounds as m,snapshotRunTurnOptions as h}from"./turn/config.js";import{codedRuntimeError as g,errorCodeOf as _,messageOf as v,now as y}from"./turn/common.js";import{runHook as te,runOptionalHook as ne}from"./turn/hooks.js";import{emitAssistantContent as b,maintenanceEmitter as x,textOf as S}from"./turn/content.js";import{repeatKey as C,repeatedSuffixCycle as re,toolActionPattern as ie}from"./turn/repetition.js";import{accountingUsageStop as w}from"./turn/usage-stop.js";import{modelRound as T}from"./turn/model-round.js";function E(e){return e.toolChoice===`none`?!1:(e.tools?.names().length??0)>0||(e.nativeTools?.length??0)>0}function D(n){return{async*[Symbol.asyncIterator](){let r=h(n),i=new u,a=new AbortController,o=p(r.teardownTimeoutMs??3e4,`teardownTimeoutMs`),s=O(r,r.signal===void 0?a.signal:AbortSignal.any([r.signal,a.signal]),t=>i.push(e(t))).then(()=>i.close(),e=>i.fail(e));try{for(;;){let e=await i.take();if(e.done)break;yield e.value}await s}finally{if(a.abort(Error(`turn event consumer stopped`)),i.close(),!await t(s,o))throw g(`turn producer ignored cancellation for more than ${o}ms`,`TURN_TEARDOWN_TIMEOUT`,a.signal.reason)}}}}async function O(e,t,u){let p=m(e.bounds),h=p.maxTotalTokens===`auto`?1/0:p.maxTotalTokens,g=p.maxSteps===`auto`?1/0:p.maxSteps,D=e.trace?.traceId??r(),O={traceId:D,spanId:n(),parentSpanId:e.trace?.parentSpanId??null},k=Math.max(1,e.history.entries().filter(e=>e.event.kind===`user`&&e.event.message.source.kind===`user`).length),oe=y(),A=0,j=0,se=[...p.toolBudgetRemindAt].filter(e=>e>0&&e<p.maxToolCalls).sort((e,t)=>t-e),ce=0,le=0,M,ue=!1,de=0,N=0,P=``,F=[],I,L,R,fe=new Map,z=new Set,pe=[],B=x(u,O),me=t=>{let n=i({source:{kind:`app`,producer:`tool-loop-budget-guard`},content:[{type:`text`,text:t}]}),r=M;if(r!==void 0)try{M=e.history.append({kind:`user`,message:n},{op:`replace`,from:r,to:r,targets:[r]}).seq;return}catch{M=void 0}M=e.history.append({kind:`user`,message:n}).seq},V=e.contextSections===void 0||e.contextSections.length===0?void 0:new c({sections:e.contextSections,history:e.history,...e.logger===void 0?{}:{logger:e.logger},guard:(n,r)=>te(n,e,t,r),scope:{agentId:e.trace?.agentId,conversationId:e.trace?.conversationId}}),H=[],U=!1,W=!1,G=E(e),K=e.experimentalPrograms===void 0?void 0:d(e.experimentalPrograms),q=K===void 0?void 0:new f,he=e.outputFormat?.type===`json_schema`&&G,J=e.accounting?.startOperation(`turn`,{data:{turn:k,model:e.config.model}}),Y=!1,X,Z=()=>{if(t.aborted)return{kind:`aborted`};let n=w(e.accounting);if(n!==void 0)return n;if(X!==void 0)return X;let r=o(s(F));return r!==void 0&&r>=h?{kind:`budget-exhausted`,budget:`tokens`,forcedFinalAnswer:!1}:void 0};try{await u({type:`span-start`,trace:O,at:oe,name:`invoke_agent ${e.trace?.agentId??`agent`}`,kind:`invoke_agent`,attributes:{"gen_ai.operation.name":`invoke_agent`,"gen_ai.agent.id":e.trace?.agentId??`agent`,"gen_ai.agent.name":e.trace?.agentName??e.trace?.agentId??`agent`,"gen_ai.request.model":e.config.model,...e.trace?.conversationId===void 0?{}:{"gen_ai.conversation.id":e.trace.conversationId}}}),U=!0,await u({type:`turn-start`,turn:k,trace:O});turnLifecycle:for(;;){for(;I===void 0&&A<g&&!t.aborted&&(I=Z(),I===void 0);){let n=o(s(F));if(p.maxTotalTokens!==`auto`&&n!==void 0){let t=[.5,.75,.9].filter(e=>n>=h*e).length;if(t>de){de=t;let r=Math.max(0,h-n);e.history.append({kind:`user`,message:i({source:{kind:`app`,producer:`tool-loop-token-guard`},content:[{type:`text`,text:`Token budget: ${r} of ${p.maxTotalTokens} aggregate tokens remain. Each request also spends input tokens on the accumulated context. `+(t>=2?`Stop broad exploration. `:`Prioritize outstanding verification and reporting. `)+`Reserve capacity for the required self-check, honest todo reconciliation and substantive final report. State unavailable evidence and unfinished work; do not claim it is verified. No extra model call is allowed after the hard token limit.`}]})})}}!ue&&A>0&&g-A<=2&&(ue=!0,e.history.append({kind:`user`,message:i({source:{kind:`app`,producer:`tool-loop-step-guard`},content:[{type:`text`,text:`${g-A} work steps remain. Finish essential verification, update any task list honestly, and submit the result if required. Summarize findings, evidence, and unfinished work; do not start new exploration.`}]})})),V!==void 0&&(await V.reconcile(A,H,t),H=[]);let r=A+1,a=await T(e,t,u,B,O,k,r,he?`process`:e.outputFormat?.type===`json_schema`?`final`:`standard`);if(A++,a.report!==void 0&&F.push(a.report),a.message===void 0?a.finish.kind===`stop`&&(P=``):(e.history.append({kind:`assistant`,message:a.message,...a.finish.kind===`aborted`?{interrupted:!0}:{},...a.usage===void 0?{}:{usage:a.usage}}),await u({type:`assistant-message`,message:a.message,trace:a.trace}),await b(a,u),P=S(a.message.content)),X=w(e.accounting)??(a.usageRequired?{kind:`error`,failure:{message:`provider usage is required by the configured run policy`,code:`USAGE_REQUIRED`}}:a.usageUnavailable?{kind:`usage-unavailable`,modelCallId:a.report?.modelCallId??`unknown`}:void 0),t.aborted||a.finish.kind===`aborted`){I={kind:`aborted`};break}if(a.finish.kind===`error`&&X!==void 0){I={kind:`error`,failure:a.finish.failure};break}if(a.usageRequired&&(a.calls.length===0||e.tools===void 0)){I=X;break}if(a.finish.kind===`error`&&!a.usageRequired){if(I=Z(),I!==void 0)break;let n=await ne(e.hooks?.onRequestError,[{turn:k,step:r,failure:a.finish.failure,snapshot:e.history.snapshot(),signal:t,...e.logger===void 0?{}:{logger:e.logger},emit:B}],e,t,`onRequestError`),i=w(e.accounting);if(i!==void 0){I=t.aborted?{kind:`aborted`}:i;break}if(n===`retry`&&A<g)continue;I={kind:`error`,failure:a.finish.failure};break}if(a.finish.kind===`max-tokens`&&!a.usageRequired){I={kind:`max-tokens`};break}if(a.calls.length===0&&a.usageUnavailable){I=w(e.accounting)??{kind:`usage-unavailable`,modelCallId:a.report?.modelCallId??`unknown`};break}if(a.calls.length===0&&he){if(I=Z(),I!==void 0)break;e.history.append({kind:`user`,message:i({source:{kind:`app`,producer:`structured-output-finalizer`},content:[{type:`text`,text:`The process phase is complete. Return the final answer now in the requested output format. Do not call tools.`}]})});let n=await T(e,t,u,B,O,k,A+1,`final`);A++,n.report!==void 0&&F.push(n.report),n.message!==void 0&&(e.history.append({kind:`assistant`,message:n.message,...n.usage===void 0?{}:{usage:n.usage}}),await u({type:`assistant-message`,message:n.message,trace:n.trace}),await b(n,u),P=S(n.message.content)),I=n.finish.kind===`aborted`?{kind:`aborted`}:n.finish.kind===`error`?{kind:`error`,failure:n.finish.failure}:n.finish.kind===`max-tokens`?{kind:`max-tokens`}:n.usageRequired?{kind:`error`,failure:{message:`provider usage is required by the configured run policy`,code:`USAGE_REQUIRED`}}:n.usageUnavailable?w(e.accounting)??{kind:`usage-unavailable`,modelCallId:n.report?.modelCallId??`unknown`}:{kind:`completed`};break}if(a.droppedDuplicateCalls!==void 0&&e.history.append({kind:`user`,message:i({source:{kind:`app`,producer:`tool-loop-duplicate-guard`},content:[{type:`text`,text:`You reused the tool-call id ${a.droppedDuplicateCalls.map(e=>`'${e}'`).join(`, `)}. A result pairs to exactly one call, so the repeat was not run and only the first call of that id has a result. Give every call its own id, and call again if you still need what the dropped one would have done.`}]})}),a.calls.length===0||e.tools===void 0){I={kind:`completed`};break}let c=Math.max(0,p.maxToolCalls-j),l=R,d=a.calls.map(e=>{let t=C(e),n=l?.key===t?l.count+1:1;return l={key:t,count:n},n}),f=d.some(e=>e>=p.repeatToolLimit),m=ie(a.calls),_=re([...pe,m],p.maxToolCycleLength),v=_!==void 0&&_.repetitions>=p.toolCycleLimit,y=s(F),x=o(y),E=x!==void 0&&x>=h,D=v||E||a.usageRequired,oe=E?`tokens`:v?`tool-call-cycle`:a.usageRequired?`usage-required`:`tool-calls`,M=p.onExhausted!==`continue`,L=new Set,U=new Set(a.calls.filter((e,t)=>(d[t]??0)>=p.repeatToolLimit).map(e=>String(e.callId))),W=a.calls.filter(t=>!U.has(String(t.callId))&&e.tools?.get(t.toolName)?.budgetExempt!==!0).length,G=f&&!v&&!E&&!a.usageRequired?t=>{let n=fe.get(C(t));if(!(!U.has(String(t.callId))||R?.key!==C(t)||R.succeeded!==!0||n===void 0||n.callId!==R.callId||n.rawArguments!==t.rawArguments||n.definition!==e.tools?.get(t.toolName)||n.result.additionalContext!==void 0||n.result.concludesTurn===!0||e.tools?.get(t.toolName)?.budgetExempt===!0))return L.add(String(t.callId)),ae(n)}:void 0,J=await ee({calls:a.calls,catalog:e.tools,history:e.history,position:{turn:k,step:r,...e.accounting===void 0?{}:{runId:e.accounting.runId},...e.trace?.conversationId===void 0?{}:{conversationId:e.trace.conversationId}},signal:t,parentTrace:O,maxParallel:p.maxParallel,dispatchLimit:D?0:M?c:a.calls.length,declineReason:oe,maxResultBytes:p.maxToolResultBytes,maxResultTokens:p.maxToolResultTokens,resultOverflow:p.toolResultOverflow,...e.spillStore===void 0?{}:{spillStore:e.spillStore},maxDurationMs:p.maxToolDurationMs,teardownTimeoutMs:p.toolTeardownTimeoutMs,...e.logger===void 0?{}:{logger:e.logger},...e.interceptors===void 0?{}:{interceptors:e.interceptors},...e.approvals===void 0?{}:{approvals:e.approvals},...e.accounting===void 0?{}:{accounting:e.accounting},emit:u,...G===void 0?{}:{recover:G},...e.hooks?.checkpoint===void 0?{}:{checkpoint:n=>te(Promise.resolve(e.hooks?.checkpoint?.(n)),e,t,`checkpoint`)}},{admissionLimit:D?0:M?c:`unbounded`,...D||!f?{}:{decline:e=>U.has(String(e.callId))?`repeated-tool-call`:void 0},...K===void 0?{}:{programs:K},...q===void 0?{}:{programResults:q}});V!==void 0&&J.results.length===a.calls.length&&H.push(...a.calls.map((e,t)=>({toolName:e.toolName,rawArguments:e.rawArguments,failed:J.results[t]?.isError??!0}))),j+=J.budgeted;let Y=Math.max(0,p.maxToolCalls-j),ge=se.filter(e=>Y<=e).length;if(ge>ce&&Y>0&&(ce=ge,me(`Tool budget: ${Y} of ${p.maxToolCalls} calls remain in this turn. Stop broad exploration, make the necessary edits, and reserve calls for`+(M?` verification. When the budget runs out no further work call will run, so finish with what you can still verify.`:` verification. Past the budget you are expected to be wrapping up, not opening new lines of work.`))),!M&&Y===0){let e=Math.floor(j/p.maxToolCalls);e>le&&(le=e,me(`Tool budget spent: ${j} calls made against a budget of ${p.maxToolCalls}. Do not start new substantive work. Finish what is in flight, verify what you can, and answer — stating plainly what is unverified or unfinished.`))}await u({type:`step-end`,turn:k,step:r,trace:a.trace}),pe.push(m);let _e=f;for(let t=0;t<a.calls.length;t++){let n=a.calls[t],r=J.results[t];if(n===void 0||r===void 0)continue;N=r.isError?N+1:0;let o=C(n),s=R?.key===o?R.count+1:1;R={key:o,count:s,callId:String(n.callId),succeeded:!r.isError&&r.meta?.declined!==!0&&e.tools?.get(n.toolName)?.budgetExempt!==!0},s===p.repeatToolWarningAt&&e.history.append({kind:`user`,message:i({source:{kind:`app`,producer:`tool-loop-repeat-guard`},content:[{type:`text`,text:`You have called ${n.toolName} with the same arguments ${s} consecutive times. Reassess before repeating it.`}]})}),s>=p.repeatToolLimit&&(_e=!0),!r.isError&&r.meta?.declined!==!0&&e.tools?.get(n.toolName)?.budgetExempt!==!0&&fe.set(o,{callId:String(n.callId),rawArguments:n.rawArguments,definition:e.tools.get(n.toolName),result:r})}if(_?.repetitions===p.toolCycleWarningAt&&e.history.append({kind:`user`,message:i({source:{kind:`app`,producer:`tool-loop-cycle-guard`},content:[{type:`text`,text:`Tool-use pattern repeated ${_.repetitions} times across ${_.period} step(s). Reassess the approach and identify concrete new evidence before continuing.`}]})}),J.concluded){I={kind:`concluded-by-tool`,toolName:J.concludedBy??`unknown`};break}if(t.aborted){I={kind:`aborted`};break}if(a.usageRequired){I=X;break}if(a.usageUnavailable){I=w(e.accounting)??{kind:`usage-unavailable`,modelCallId:a.report?.modelCallId??`unknown`};break}let Q,$=p.maxTotalTokens!==`auto`&&p.finalReportReserveTokens>0&&x!==void 0&&x>=h-p.finalReportReserveTokens,ve=f&&L.size===a.calls.length&&a.calls.every(e=>L.has(String(e.callId))&&!z.has(C(e)))&&J.results.length===a.calls.length&&J.results.every(e=>!e.isError)&&J.dispatched===0&&J.declined===0&&!v&&!E&&!$&&!a.usageRequired&&!a.usageUnavailable&&!t.aborted&&!(M&&W>c)&&N===0&&A<g&&p.onExhausted!==`stop`&&Z()===void 0,ye=f&&[...U].every(e=>L.has(e))&&J.results.length===a.calls.length&&J.dispatched>0&&J.declined===0;if(ve)for(let e of a.calls)z.add(C(e));else E||$?Q=`tokens`:v?Q=`tool-call-cycle`:M&&W>c?Q=`tool-calls`:N>=p.maxConsecutiveToolErrors?Q=`consecutive-tool-errors`:_e&&!ye?Q=`repeated-tool-call`:A>=g&&(Q=`steps`);if(Q===void 0&&ye)for(let e of a.calls)L.has(String(e.callId))&&z.add(C(e));if(Q!==void 0){let n=(Q!==`tokens`||$&&!E)&&p.onExhausted!==`stop`&&Z()===void 0;if(n){let n=await T(e,t,u,B,O,k,A+1,`forced-final`);if(A++,n.report!==void 0&&F.push(n.report),n.message!==void 0&&(e.history.append({kind:`assistant`,message:n.message,...n.usage===void 0?{}:{usage:n.usage}}),await u({type:`assistant-message`,message:n.message,trace:n.trace}),await b(n,u),P=S(n.message.content)),n.finish.kind===`aborted`){I={kind:`aborted`};break}if(n.finish.kind===`error`){I={kind:`error`,failure:n.finish.failure};break}if(n.finish.kind===`max-tokens`){I={kind:`max-tokens`};break}if(n.usageRequired){I={kind:`error`,failure:{message:`provider usage is required by the configured run policy`,code:`USAGE_REQUIRED`}};break}if(n.usageUnavailable){I=w(e.accounting)??{kind:`usage-unavailable`,modelCallId:n.report?.modelCallId??`unknown`};break}}I={kind:`budget-exhausted`,budget:Q,forcedFinalAnswer:n,...Q===`tokens`&&$&&!E?{trigger:`report-reserve`}:{}}}}I===void 0&&(I=t.aborted?{kind:`aborted`}:{kind:`budget-exhausted`,budget:`steps`,forcedFinalAnswer:!1});let n=s(F),r=a(n),c={reason:I,text:P,steps:A,usageReport:n,toolCalls:j,traceId:D,...r===void 0?{}:{usage:r}},d=e.history.entries().length,f=I.kind===`completed`&&A<g&&Z()===void 0;if(await ne(e.hooks?.onTurnEnd,[{outcome:c,snapshot:e.history.snapshot(),canContinue:f}],e,t.aborted?new AbortController().signal:t,`onTurnEnd`),f&&!t.aborted&&(e.history.entries().length>d||l(e.history))){I=void 0;continue turnLifecycle}L=c;break}L.reason.kind===`aborted`&&e.history.append({kind:`user`,message:i({source:{kind:`app`,producer:`turn-interrupted`},content:[{type:`text`,text:`The previous request was interrupted before it finished. Use the next message to determine what to do next.`}]})}),await u({type:`span-end`,trace:O,at:y(),status:L.reason.kind===`error`?`error`:L.reason.kind===`aborted`?`aborted`:`success`,output:{reason:L.reason,text:P},...L.usage===void 0?{}:{usage:L.usage},...L.reason.kind===`error`?{error:{type:`ModelError`,message:L.reason.failure.message,code:L.reason.failure.code}}:{}}),W=!0,J!==void 0&&(e.accounting?.endOperation(J,L.reason.kind===`error`?`error`:L.reason.kind===`aborted`?`aborted`:`success`,{data:{reason:L.reason.kind,steps:A,toolCalls:j}}),Y=!0),await u({type:`turn-end`,outcome:L,trace:O})}catch(n){let r=_(n);throw U&&!W&&await u({type:`span-end`,trace:O,at:y(),status:t.aborted?`aborted`:`error`,error:{type:n instanceof Error?n.name:`RuntimeError`,message:v(n),...r===void 0?{}:{code:r}}}).catch(()=>void 0),J!==void 0&&!Y&&(e.accounting?.endOperation(J,t.aborted?`aborted`:`error`,{error:n}),Y=!0),n}finally{q?.close()}}function ae(t){return e({isError:!1,value:t.result.value,content:[{type:`text`,text:JSON.stringify({status:`duplicate_of`,callId:t.callId,instruction:`This exact call already succeeded in this run. Use the retained result below; do not call it again.`})},...t.result.content],meta:{...t.result.meta,recovered:!0,duplicateOfCallId:t.callId}})}export{D as runTurn};
1
+ import{detachedFrozen as e}from"../../primitives/snapshot.js";import{waitForSettlement as t}from"../../async/settlement.js";import{createSpanId as n,createTraceId as r}from"../../observation/context.js";import{createMessage as i,createUserMessage as a}from"../../message/message.js";import{authoritativeTokenUsage as o,budgetTokenTotal as s,summarizeModelCallUsage as c}from"../accounting/usage.js";import{ContextSectionRuntime as l}from"../context/section.js";import{deliverQueuedInput as ee,hasQueuedInput as te}from"./turn/model-request-boundary.js";import{AwaitedEventQueue as u}from"./queue.js";import{captureProgramGrants as d}from"../tool/nested.js";import{scheduleToolCalls as ne}from"./schedule.js";import{ProgramResultStore as f}from"../tool/program-results.js";import{positiveFinite as p,resolveBounds as m,snapshotRunTurnOptions as h}from"./turn/config.js";import{codedRuntimeError as g,errorCodeOf as _,messageOf as re,now as v}from"./turn/common.js";import{runHook as ie,runOptionalHook as ae}from"./turn/hooks.js";import{emitAssistantContent as oe,maintenanceEmitter as y,textOf as b}from"./turn/content.js";import{repeatKey as x,repeatedSuffixCycle as se,toolActionPattern as ce}from"./turn/repetition.js";import{accountingUsageStop as S}from"./turn/usage-stop.js";import{modelRound as C}from"./turn/model-round.js";function le(e){return e.toolChoice===`none`?!1:(e.tools?.names().length??0)>0||(e.nativeTools?.length??0)>0}function w(n){return{async*[Symbol.asyncIterator](){let r=h(n),i=new u,a=new AbortController,o=p(r.teardownTimeoutMs??3e4,`teardownTimeoutMs`),s=T(r,r.signal===void 0?a.signal:AbortSignal.any([r.signal,a.signal]),t=>i.push(e(t))).then(()=>i.close(),e=>i.fail(e));try{for(;;){let e=await i.take();if(e.done)break;yield e.value}await s}finally{if(a.abort(Error(`turn event consumer stopped`)),i.close(),!await t(s,o))throw g(`turn producer ignored cancellation for more than ${o}ms`,`TURN_TEARDOWN_TIMEOUT`,a.signal.reason)}}}}async function T(e,t,u){let p=m(e.bounds),h=p.maxTotalTokens===`auto`?1/0:p.maxTotalTokens,g=p.maxSteps===`auto`?1/0:p.maxSteps,w=e.trace?.traceId??r(),T={traceId:w,spanId:n(),parentSpanId:e.trace?.parentSpanId??null},E=Math.max(1,e.history.entries().filter(e=>e.event.kind===`user`&&e.event.message.source.kind===`user`).length),de=v(),D=0,O=0,k=()=>D-O,A=()=>({workStep:k()+1,finalizing:R!==void 0}),fe=p.maxTurnDurationMs===`auto`?1/0:p.maxTurnDurationMs,j=Date.now(),M=0,N,P=0,F=0,pe=(e,t)=>{let n=Date.now();N!==void 0&&(M+=n-N),e?P+=t?1:-1:F+=t?1:-1,N=P>0&&F===0?n:void 0},me=()=>{let e=Date.now();return e-j-M-(N===void 0?0:e-N)},he=async(n,r)=>{let i=await ge(await C(e,t,u,Y,T,E,D+1,`forced-final`,A()),`forced-final`);return(e=>!e.usageRequired&&!e.usageUnavailable&&(e.finish.kind===`stop`&&b(e.message?.content??[]).trim()===``||e.finish.kind===`error`&&e.finish.failure.code===`INVALID_TOOL_CALL`))(i)&&!t.aborted&&O<8&&$(i.report)===void 0&&(i.report!==void 0&&G.push(i.report),i.message!==void 0&&e.history.append({kind:`assistant`,message:i.message,...i.usage===void 0?{}:{usage:i.usage}}),e.history.append({kind:`user`,message:a({source:{kind:`app`,producer:`forced-answer-empty`},content:[{type:`text`,text:`Your last reply contained no answer. Tools are disabled now. Write the answer for the user now, in text, from the evidence already gathered, and state what could not be checked.`}]})}),D++,O++,i=await C(e,t,u,Y,T,E,D+1,`forced-final`,A())),D++,i.report!==void 0&&G.push(i.report),i.message===void 0?W=``:(e.history.append({kind:`assistant`,message:i.message,...i.usage===void 0?{}:{usage:i.usage}}),await u({type:`assistant-message`,message:i.message,trace:i.trace}),await oe(i,u),W=b(i.message.content)),t.aborted||i.finish.kind===`aborted`?{kind:`aborted`}:i.finish.kind===`error`&&i.finish.failure.code===`INVALID_TOOL_CALL`?(W=``,{kind:`budget-exhausted`,budget:n,forcedFinalAnswer:!1,...r?{trigger:`report-reserve`}:{}}):i.finish.kind===`error`?{kind:`error`,failure:i.finish.failure}:i.finish.kind===`max-tokens`?{kind:`max-tokens`}:i.usageRequired?{kind:`error`,failure:{message:`provider usage is required by the configured run policy`,code:`USAGE_REQUIRED`}}:i.usageUnavailable?S(e.accounting)??{kind:`usage-unavailable`,modelCallId:i.report?.modelCallId??`unknown`}:{kind:`budget-exhausted`,budget:n,forcedFinalAnswer:W.trim()!==``,...r?{trigger:`report-reserve`}:{}}},ge=async(n,r)=>{let i=n;for(;i.finish.kind===`error`&&!i.usageRequired&&!t.aborted&&!i.usageUnavailable&&O<8&&$(i.report)===void 0&&await ae(e.hooks?.onRequestError,[{turn:E,step:D+1,failure:i.finish.failure,snapshot:e.history.snapshot(),signal:t,...e.logger===void 0?{}:{logger:e.logger},emit:Y}],e,t,`onRequestError`).catch(e=>{if(t.aborted)return`fail`;throw e})===`retry`&&$(i.report)===void 0;)i.report!==void 0&&G.push(i.report),D++,O++,i=await C(e,t,u,Y,T,E,D+1,r,A());return i},I=0,_e=[...p.toolBudgetRemindAt].filter(e=>e>0&&e<p.maxToolCalls).sort((e,t)=>t-e),ve=0,ye=0,L,be=!1,R,z,B,V=``,H,xe=new Set(e.finalize?.tools??[]),Se=0,U=0,W=``,G=[],K,q,J,Ce=new Map,we=new Set,Te=[],Y=y(u,T),Ee=t=>{let n=a({source:{kind:`app`,producer:`tool-loop-budget-guard`},content:[{type:`text`,text:t}]}),r=L;if(r!==void 0)try{L=e.history.append({kind:`user`,message:n},{op:`replace`,from:r,to:r,targets:[r]}).seq;return}catch{L=void 0}L=e.history.append({kind:`user`,message:n}).seq},De=e.contextSections===void 0||e.contextSections.length===0?void 0:new l({sections:e.contextSections,history:e.history,...e.logger===void 0?{}:{logger:e.logger},guard:(n,r)=>ie(n,e,t,r),scope:{agentId:e.trace?.agentId,conversationId:e.trace?.conversationId}}),Oe=[],X=!1,ke=!1,Ae=le(e),je=e.experimentalPrograms===void 0?void 0:d(e.experimentalPrograms),Me=je===void 0?void 0:new f,Ne=e.outputFormat?.type===`json_schema`&&Ae,Z=e.accounting?.startOperation(`turn`,{data:{turn:E,model:e.config.model}}),Pe=!1,Q,$=n=>{if(t.aborted)return{kind:`aborted`};let r=S(e.accounting);if(r!==void 0)return r;if(Q!==void 0)return Q;let i=s(c(n===void 0?G:[...G,n]));return i!==void 0&&i>=h?{kind:`budget-exhausted`,budget:`tokens`,forcedFinalAnswer:!1}:void 0};try{await u({type:`span-start`,trace:T,at:de,name:`invoke_agent ${e.trace?.agentId??`agent`}`,kind:`invoke_agent`,attributes:{"gen_ai.operation.name":`invoke_agent`,"gen_ai.agent.id":e.trace?.agentId??`agent`,"gen_ai.agent.name":e.trace?.agentName??e.trace?.agentId??`agent`,"gen_ai.request.model":e.config.model,...e.trace?.conversationId===void 0?{}:{"gen_ai.conversation.id":e.trace.conversationId}}}),X=!0,await u({type:`turn-start`,turn:E,trace:T});turnLifecycle:for(;;){for(;K===void 0&&k()<(R??g)&&!t.aborted&&(K=$(),K===void 0);){if(D>0&&R===void 0&&me()>=fe){K=p.onExhausted===`stop`?{kind:`budget-exhausted`,budget:`time`,forcedFinalAnswer:!1}:await he(`time`,!1);break}let n=s(c(G));if(p.maxTotalTokens!==`auto`&&n!==void 0){let t=[.5,.75,.9].filter(e=>n>=h*e).length;if(t>Se){Se=t;let r=Math.max(0,h-n);e.history.append({kind:`user`,message:a({source:{kind:`app`,producer:`tool-loop-token-guard`},content:[{type:`text`,text:`Token budget: ${r} of ${p.maxTotalTokens} aggregate tokens remain. Each request also spends input tokens on the accumulated context. `+(t>=2?`Stop broad exploration. `:`Prioritize outstanding verification and reporting. `)+`Reserve capacity for the required self-check, honest todo reconciliation and substantive final report. State unavailable evidence and unfinished work; do not claim it is verified. No extra model call is allowed after the hard token limit.`}]})})}}!be&&R===void 0&&k()>0&&g-k()<=2&&(be=!0,e.history.append({kind:`user`,message:a({source:{kind:`app`,producer:`tool-loop-step-guard`},content:[{type:`text`,text:`${g-k()} work steps remain. Finish essential verification, update any task list honestly, and submit the result if required. Summarize findings, evidence, and unfinished work; do not start new exploration.`}]})})),De!==void 0&&(await De.reconcile(D,Oe,t),Oe=[]);let r=D+1,i=await C(e,t,u,Y,T,E,r,Ne?`process`:e.outputFormat?.type===`json_schema`?`final`:`standard`,A());D++,i.report!==void 0&&G.push(i.report),Q=S(e.accounting)??(i.usageRequired?{kind:`error`,failure:{message:`provider usage is required by the configured run policy`,code:`USAGE_REQUIRED`}}:i.usageUnavailable?{kind:`usage-unavailable`,modelCallId:i.report?.modelCallId??`unknown`}:void 0);let o=async()=>{if(i.message!==void 0){e.history.append({kind:`assistant`,message:i.message,...i.finish.kind===`aborted`?{interrupted:!0}:{},...i.usage===void 0?{}:{usage:i.usage}}),await u({type:`assistant-message`,message:i.message,trace:i.trace}),await oe(i,u);let t=b(i.message.content);(t.trim()!==``||i.finish.kind!==`error`&&i.finish.kind!==`aborted`)&&(W=t)}else i.finish.kind===`stop`&&(W=``)};if(i.finish.kind===`error`&&!i.usageRequired&&Q===void 0&&!t.aborted||await o(),t.aborted||i.finish.kind===`aborted`){K={kind:`aborted`};break}if(i.finish.kind===`error`&&Q!==void 0){K={kind:`error`,failure:i.finish.failure};break}if(i.usageRequired&&(i.calls.length===0||e.tools===void 0)){K=Q;break}if(i.finish.kind===`error`&&!i.usageRequired){if(K=$(),K!==void 0){await o();break}let n=await ae(e.hooks?.onRequestError,[{turn:E,step:r,failure:i.finish.failure,snapshot:e.history.snapshot(),signal:t,...e.logger===void 0?{}:{logger:e.logger},emit:Y}],e,t,`onRequestError`).catch(e=>{if(t.aborted)return`fail`;throw e}),a=S(e.accounting);if(a!==void 0){await o(),K=t.aborted?{kind:`aborted`}:a;break}if(n===`retry`&&!t.aborted&&(O<8&&O++,k()<(R??g)))continue;await o(),K=t.aborted?{kind:`aborted`}:{kind:`error`,failure:i.finish.failure};break}if(i.finish.kind===`max-tokens`&&!i.usageRequired){K={kind:`max-tokens`};break}if(i.calls.length===0&&i.usageUnavailable){K=S(e.accounting)??{kind:`usage-unavailable`,modelCallId:i.report?.modelCallId??`unknown`};break}if(i.calls.length===0&&Ne){if(K=$(),K!==void 0)break;e.history.append({kind:`user`,message:a({source:{kind:`app`,producer:`structured-output-finalizer`},content:[{type:`text`,text:`The process phase is complete. Return the final answer now in the requested output format. Do not call tools.`}]})});let n=await ge(await C(e,t,u,Y,T,E,D+1,`final`,A()),`final`);D++,n.report!==void 0&&G.push(n.report),n.message!==void 0&&(e.history.append({kind:`assistant`,message:n.message,...n.usage===void 0?{}:{usage:n.usage}}),await u({type:`assistant-message`,message:n.message,trace:n.trace}),await oe(n,u),W=b(n.message.content)),K=t.aborted||n.finish.kind===`aborted`?{kind:`aborted`}:n.finish.kind===`error`?{kind:`error`,failure:n.finish.failure}:n.finish.kind===`max-tokens`?{kind:`max-tokens`}:n.usageRequired?{kind:`error`,failure:{message:`provider usage is required by the configured run policy`,code:`USAGE_REQUIRED`}}:n.usageUnavailable?S(e.accounting)??{kind:`usage-unavailable`,modelCallId:n.report?.modelCallId??`unknown`}:{kind:`completed`};break}if(i.droppedDuplicateCalls!==void 0&&e.history.append({kind:`user`,message:a({source:{kind:`app`,producer:`tool-loop-duplicate-guard`},content:[{type:`text`,text:`You reused the tool-call id ${i.droppedDuplicateCalls.map(e=>`'${e}'`).join(`, `)}. A result pairs to exactly one call, so the repeat was not run and only the first call of that id has a result. Give every call its own id, and call again if you still need what the dropped one would have done.`}]})}),i.calls.length===0||e.tools===void 0){K={kind:`completed`};break}let l=Math.max(0,p.maxToolCalls-I),ee=J,te=i.calls.map(e=>{let t=x(e),n=ee?.key===t?ee.count+1:1;return ee={key:t,count:n},n}),d=te.some(e=>e>=p.repeatToolLimit),f=ce(i.calls),m=se([...Te,f],p.maxToolCycleLength),_=m!==void 0&&m.repetitions>=p.toolCycleLimit,re=c(G),v=s(re),y=v!==void 0&&v>=h,le=R===void 0&&me()>=fe,w=_||y||i.usageRequired||R!==void 0||le,de=z!==void 0&&!y?z:y?`tokens`:le?`time`:_?`tool-call-cycle`:i.usageRequired?`usage-required`:`tool-calls`,j=p.onExhausted!==`continue`,M=new Set,N=new Set(i.calls.filter((e,t)=>(te[t]??0)>=p.repeatToolLimit).map(e=>String(e.callId))),P=i.calls.filter(t=>!N.has(String(t.callId))&&e.tools?.get(t.toolName)?.budgetExempt!==!0).length,F=d&&!_&&!y&&!i.usageRequired?t=>{let n=Ce.get(x(t));if(!(!N.has(String(t.callId))||J?.key!==x(t)||J.succeeded!==!0||n===void 0||n.callId!==J.callId||n.rawArguments!==t.rawArguments||n.definition!==e.tools?.get(t.toolName)||n.result.additionalContext!==void 0||n.result.concludesTurn===!0||e.tools?.get(t.toolName)?.budgetExempt===!0))return M.add(String(t.callId)),ue(n)}:void 0,L=await ne({calls:i.calls,catalog:e.tools,history:e.history,position:{turn:E,step:r,...e.accounting===void 0?{}:{runId:e.accounting.runId},...e.trace?.conversationId===void 0?{}:{conversationId:e.trace.conversationId}},signal:t,parentTrace:T,maxParallel:p.maxParallel,dispatchLimit:w?0:j?l:i.calls.length,declineReason:de,maxResultBytes:p.maxToolResultBytes,maxResultTokens:p.maxToolResultTokens,resultOverflow:p.toolResultOverflow,...e.spillStore===void 0?{}:{spillStore:e.spillStore},maxDurationMs:p.maxToolDurationMs,teardownTimeoutMs:p.toolTeardownTimeoutMs,...e.logger===void 0?{}:{logger:e.logger},...e.interceptors===void 0?{}:{interceptors:e.interceptors},...e.approvals===void 0?{}:{approvals:e.approvals},...e.accounting===void 0?{}:{accounting:e.accounting},emit:u,...F===void 0?{}:{recover:F},...e.hooks?.checkpoint===void 0?{}:{checkpoint:n=>ie(Promise.resolve(e.hooks?.checkpoint?.(n)),e,t,`checkpoint`)}},{onToolActivity:pe,admissionLimit:w?0:j?l:`unbounded`,...R===void 0?{}:{restrict:e=>xe.has(e.toolName)?void 0:z??`steps`},...w||!d?{}:{decline:e=>N.has(String(e.callId))?`repeated-tool-call`:void 0},...je===void 0?{}:{programs:je},...Me===void 0?{}:{programResults:Me}});De!==void 0&&L.results.length===i.calls.length&&Oe.push(...i.calls.map((e,t)=>({toolName:e.toolName,rawArguments:e.rawArguments,failed:L.results[t]?.isError??!0}))),I+=L.budgeted;let B=Math.max(0,p.maxToolCalls-I),V=_e.filter(e=>B<=e).length;if(V>ve&&B>0&&(ve=V,Ee(`Tool budget: ${B} of ${p.maxToolCalls} calls remain in this turn. Stop broad exploration, make the necessary edits, and reserve calls for`+(j?` verification. When the budget runs out no further work call will run, so finish with what you can still verify.`:` verification. Past the budget you are expected to be wrapping up, not opening new lines of work.`))),!j&&B===0){let e=Math.floor(I/p.maxToolCalls);e>ye&&(ye=e,Ee(`Tool budget spent: ${I} calls made against a budget of ${p.maxToolCalls}. Do not start new substantive work. Finish what is in flight, verify what you can, and answer — stating plainly what is unverified or unfinished.`))}await u({type:`step-end`,turn:E,step:r,trace:i.trace}),Te.push(f);let H=d;for(let t=0;t<i.calls.length;t++){let n=i.calls[t],r=L.results[t];if(n===void 0||r===void 0)continue;U=r.isError?U+1:0;let o=x(n),s=J?.key===o?J.count+1:1;J={key:o,count:s,callId:String(n.callId),succeeded:!r.isError&&r.meta?.declined!==!0&&e.tools?.get(n.toolName)?.budgetExempt!==!0},s===p.repeatToolWarningAt&&e.history.append({kind:`user`,message:a({source:{kind:`app`,producer:`tool-loop-repeat-guard`},content:[{type:`text`,text:`You have called ${n.toolName} with the same arguments ${s} consecutive times. Reassess before repeating it.`}]})}),s>=p.repeatToolLimit&&(H=!0),!r.isError&&r.meta?.declined!==!0&&e.tools?.get(n.toolName)?.budgetExempt!==!0&&Ce.set(o,{callId:String(n.callId),rawArguments:n.rawArguments,definition:e.tools.get(n.toolName),result:r})}if(m?.repetitions===p.toolCycleWarningAt&&e.history.append({kind:`user`,message:a({source:{kind:`app`,producer:`tool-loop-cycle-guard`},content:[{type:`text`,text:`Tool-use pattern repeated ${m.repetitions} times across ${m.period} step(s). Reassess the approach and identify concrete new evidence before continuing.`}]})}),L.concluded){K={kind:`concluded-by-tool`,toolName:L.concludedBy??`unknown`};break}if(t.aborted){K={kind:`aborted`};break}if(i.usageRequired){K=Q;break}if(i.usageUnavailable){K=S(e.accounting)??{kind:`usage-unavailable`,modelCallId:i.report?.modelCallId??`unknown`};break}let q,X=p.maxTotalTokens!==`auto`&&p.finalReportReserveTokens>0&&v!==void 0&&v>=h-p.finalReportReserveTokens,ke=d&&M.size===i.calls.length&&i.calls.every(e=>M.has(String(e.callId))&&!we.has(x(e)))&&L.results.length===i.calls.length&&L.results.every(e=>!e.isError)&&L.dispatched===0&&L.declined===0&&!_&&!y&&!X&&!i.usageRequired&&!i.usageUnavailable&&!t.aborted&&!(j&&P>l)&&U===0&&k()<g&&p.onExhausted!==`stop`&&$()===void 0,Ae=d&&[...N].every(e=>M.has(e))&&L.results.length===i.calls.length&&L.dispatched>0&&L.declined===0;if(ke)for(let e of i.calls)we.add(x(e));else y||X?q=`tokens`:_?q=`tool-call-cycle`:j&&P>l?q=`tool-calls`:U>=p.maxConsecutiveToolErrors?q=`consecutive-tool-errors`:H&&!Ae?q=`repeated-tool-call`:k()>=g&&(q=`steps`);if(R!==void 0&&(q=y?`tokens`:void 0),q===void 0&&Ae)for(let e of i.calls)M.has(String(e.callId))&&we.add(x(e));q===void 0&&R===void 0&&me()>=fe&&(q=`time`),q!==void 0&&(K=(q!==`tokens`||X&&!y)&&p.onExhausted!==`stop`&&$()===void 0?await he(q,q===`tokens`&&X&&!y):{kind:`budget-exhausted`,budget:q,forcedFinalAnswer:!1,...q===`tokens`&&X&&!y?{trigger:`report-reserve`}:{}})}let n=K?.kind===`budget-exhausted`?K.forcedFinalAnswer:K?.kind===`completed`&&k()>=g;if(R===void 0&&e.finalize!==void 0&&p.finalizeSteps>0&&(K?.kind===`budget-exhausted`||K?.kind===`completed`)&&n&&W.trim()!==``&&!t.aborted&&$()===void 0&&!te(e.history)){let t=e.finalize.prompt({text:W,reason:K});if(t!==void 0){e.history.append({kind:`user`,message:t}),B=K,z=K.kind===`budget-exhausted`?K.budget:`steps`,V=W,H=e.history.messages().findLast(e=>e.role===`assistant`),R=k()+p.finalizeSteps,K=void 0;continue turnLifecycle}}if(K===void 0&&(K=t.aborted?{kind:`aborted`}:{kind:`budget-exhausted`,budget:`steps`,forcedFinalAnswer:!1}),B!==void 0){if(K.kind!==`completed`||W.trim()===``||e.finalize?.confirmed()!==!0){W=V;let t=e.history.messages().findLast(e=>e.role===`assistant`);if(H!==void 0&&t?.id!==H.id){let t=i({role:`assistant`,content:H.content,source:H.source});e.history.append({kind:`assistant`,message:t}),await u({type:`assistant-message`,message:t,trace:T})}}K.kind!==`aborted`&&(K=B)}let r=c(G),l=o(r),d={reason:K,text:W,steps:D,usageReport:r,toolCalls:I,traceId:w,...l===void 0?{}:{usage:l}},f=e.history.entries().length,m=K.kind===`completed`&&k()<g&&$()===void 0;if(await ae(e.hooks?.onTurnEnd,[{outcome:d,snapshot:e.history.snapshot(),canContinue:m}],e,t.aborted?new AbortController().signal:t,`onTurnEnd`),m&&!t.aborted&&(e.history.entries().length>f||ee(e.history))){K=void 0;continue turnLifecycle}q=d;break}q.reason.kind===`aborted`&&e.history.append({kind:`user`,message:a({source:{kind:`app`,producer:`turn-interrupted`},content:[{type:`text`,text:`The previous request was interrupted before it finished. Use the next message to determine what to do next.`}]})}),await u({type:`span-end`,trace:T,at:v(),status:q.reason.kind===`error`?`error`:q.reason.kind===`aborted`?`aborted`:`success`,output:{reason:q.reason,text:W},...q.usage===void 0?{}:{usage:q.usage},...q.reason.kind===`error`?{error:{type:`ModelError`,message:q.reason.failure.message,code:q.reason.failure.code}}:{}}),ke=!0,Z!==void 0&&(e.accounting?.endOperation(Z,q.reason.kind===`error`?`error`:q.reason.kind===`aborted`?`aborted`:`success`,{data:{reason:q.reason.kind,steps:D,toolCalls:I}}),Pe=!0),await u({type:`turn-end`,outcome:q,trace:T})}catch(n){let r=_(n);throw X&&!ke&&await u({type:`span-end`,trace:T,at:v(),status:t.aborted?`aborted`:`error`,error:{type:n instanceof Error?n.name:`RuntimeError`,message:re(n),...r===void 0?{}:{code:r}}}).catch(()=>void 0),Z!==void 0&&!Pe&&(e.accounting?.endOperation(Z,t.aborted?`aborted`:`error`,{error:n}),Pe=!0),n}finally{Me?.close()}}function ue(t){return e({isError:!1,value:t.result.value,content:[{type:`text`,text:JSON.stringify({status:`duplicate_of`,callId:t.callId,instruction:`This exact call already succeeded in this run. Use the retained result below; do not call it again.`})},...t.result.content],meta:{...t.result.meta,recovered:!0,duplicateOfCallId:t.callId}})}export{w as runTurn};
2
2
  //# sourceMappingURL=run-turn.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-turn.js","names":[],"sources":["../../../src/agent/loop/run-turn.ts"],"sourcesContent":["import { createUserMessage } from '../../message/index.ts'\nimport { detachedFrozen } from '../../primitives/index.ts'\nimport type { ModelCallReport } from '../../observation/index.ts'\nimport { waitForSettlement } from '../../async/index.ts'\nimport { authoritativeTokenUsage, budgetTokenTotal, summarizeModelCallUsage } from '../accounting/ledger.ts'\nimport { createSpanId, createTraceId, type TraceRef } from '../trace/trace.ts'\nimport type { ToolDefinition, ToolExecutionResult } from '../tool/definition.ts'\nimport type { AgentEvent, ExhaustedBudget, ToolDeclineReason, TurnHooks, TurnOutcome } from './types.ts'\nimport { AwaitedEventQueue } from './queue.ts'\nimport { scheduleToolCalls } from './schedule.ts'\nimport { captureProgramGrants } from '../tool/nested.ts'\nimport { ProgramResultStore } from '../tool/program-results.ts'\nimport { type RunTurnOptions } from './turn/types.ts'\nimport { resolveBounds, positiveFinite, snapshotRunTurnOptions } from './turn/config.ts'\nimport { codedRuntimeError, messageOf, errorCodeOf, now } from './turn/common.ts'\nimport { deliverQueuedInput } from './turn/model-request-boundary.ts'\nimport { runOptionalHook, runHook } from './turn/hooks.ts'\nimport { maintenanceEmitter, emitAssistantContent, textOf } from './turn/content.ts'\nimport { repeatKey, toolActionPattern, repeatedSuffixCycle } from './turn/repetition.ts'\nimport { modelRound } from './turn/model-round.ts'\nimport { accountingUsageStop } from './turn/usage-stop.ts'\nimport { ContextSectionRuntime } from '../context/section.ts'\nimport type { ContextToolTouch } from '../context/types.ts'\n\nfunction hasCallableTools(options: RunTurnOptions): boolean {\n if (options.toolChoice === 'none') return false\n return (options.tools?.names().length ?? 0) > 0 || (options.nativeTools?.length ?? 0) > 0\n}\n\n/** Run one bounded turn as a backpressured event stream. */\nexport function runTurn(options: RunTurnOptions): AsyncIterable<AgentEvent> {\n return {\n async * [Symbol.asyncIterator]() {\n const invocation = snapshotRunTurnOptions(options)\n const queue = new AwaitedEventQueue<AgentEvent>()\n const consumer = new AbortController()\n const teardownTimeoutMs = positiveFinite(invocation.teardownTimeoutMs ?? 30_000, 'teardownTimeoutMs')\n const signal = invocation.signal === undefined\n ? consumer.signal\n : AbortSignal.any([invocation.signal, consumer.signal])\n const task = driveTurn(invocation, signal, event => queue.push(detachedFrozen(event)))\n .then(() => queue.close(), error => queue.fail(error))\n try {\n while (true) {\n const item = await queue.take()\n if (item.done) break\n yield item.value\n }\n await task\n } finally {\n consumer.abort(new Error('turn event consumer stopped'))\n queue.close()\n if (!await waitForSettlement(task, teardownTimeoutMs)) {\n throw codedRuntimeError(\n `turn producer ignored cancellation for more than ${teardownTimeoutMs}ms`,\n 'TURN_TEARDOWN_TIMEOUT',\n consumer.signal.reason,\n )\n }\n }\n },\n }\n}\n\nasync function driveTurn(\n options: RunTurnOptions,\n signal: AbortSignal,\n emit: (event: AgentEvent) => Promise<void>,\n): Promise<void> {\n const bounds = resolveBounds(options.bounds)\n const maxTotalTokens = bounds.maxTotalTokens === 'auto' ? Infinity : bounds.maxTotalTokens\n // Infinity is local control flow only. Public configuration/events retain\n // the serializable 'auto' value, and all other admission guards still apply.\n const maxSteps = bounds.maxSteps === 'auto' ? Infinity : bounds.maxSteps\n const traceId = options.trace?.traceId ?? createTraceId()\n const root: TraceRef = { traceId, spanId: createSpanId(), parentSpanId: options.trace?.parentSpanId ?? null }\n const turn = Math.max(1, options.history.entries().filter(entry =>\n entry.event.kind === 'user' && entry.event.message.source.kind === 'user').length)\n const startedAt = now()\n let steps = 0\n let toolCalls = 0\n // Descending, so \"how many are below the remainder\" counts the crossings.\n const budgetReminders = [...bounds.toolBudgetRemindAt]\n .filter(threshold => threshold > 0 && threshold < bounds.maxToolCalls)\n .sort((left, right) => right - left)\n let budgetRemindersSent = 0\n /** How many full budgets an unwalled turn has spent and been told about. */\n let overBudgetNoticesSent = 0\n /** Sequence of the budget notice currently on the surface, if any. */\n let budgetNoticeSeq: number | undefined\n let stepReminderSent = false\n let tokenRemindersSent = 0\n let consecutiveErrors = 0\n let text = ''\n const modelCallReports: ModelCallReport[] = []\n let reason: TurnOutcome['reason'] | undefined\n let outcome: TurnOutcome\n /** The immediately preceding call/result, so recovery cannot cross a state-changing call or failure. */\n let lastRepeat: { key: string; count: number; callId: string; succeeded: boolean } | undefined\n /** Successful finalized results, retained only for this turn's exact repeat guard. */\n const successfulCalls = new Map<string, {\n readonly callId: string\n readonly rawArguments: string\n readonly definition: ToolDefinition | undefined\n readonly result: Extract<ToolExecutionResult, { readonly isError: false }>\n }>()\n /** Each exact recovered key gets one ordinary model replan, never a retry loop. */\n const recoveredReplanKeys = new Set<string>()\n const actionSteps: string[] = []\n const emitMaintenance = maintenanceEmitter(emit, root)\n /**\n * Put the current budget notice on the surface, replacing the previous one.\n *\n * One live notice, never a pile of them. Appending each new remainder leaves\n * \"16 calls remain\" and \"6 calls remain\" both readable, and a model that\n * plans against the older number plans against a budget it no longer has.\n * Codex keeps exactly one `<rollout_budget>` fragment for the same reason\n * (`context/rollout_budget.rs`), replacing it as the number moves.\n * @param text - What the model should read now.\n */\n const appendBudgetNotice = (text: string): void => {\n const message = createUserMessage({\n source: { kind: 'app', producer: 'tool-loop-budget-guard' },\n content: [{ type: 'text', text }],\n })\n const previous = budgetNoticeSeq\n // Replacing is best-effort. Compaction can shadow the earlier notice\n // between steps, and a replace whose target is no longer on the surface is\n // rejected — which must cost the model a reminder, never the turn.\n if (previous !== undefined) {\n try {\n budgetNoticeSeq = options.history.append(\n { kind: 'user', message },\n { op: 'replace', from: previous, to: previous, targets: [previous] },\n ).seq\n return\n } catch {\n budgetNoticeSeq = undefined\n }\n }\n budgetNoticeSeq = options.history.append({ kind: 'user', message }).seq\n }\n const contextSections = options.contextSections === undefined || options.contextSections.length === 0\n ? undefined\n : new ContextSectionRuntime({\n sections: options.contextSections,\n history: options.history,\n ...options.logger === undefined ? {} : { logger: options.logger },\n guard: (pending, name) => runHook(pending, options, signal, name),\n scope: { agentId: options.trace?.agentId, conversationId: options.trace?.conversationId },\n })\n /** Tool calls committed since the last section reconcile. */\n let contextTouches: ContextToolTouch[] = []\n let rootStarted = false\n let rootEnded = false\n const callableTools = hasCallableTools(options)\n const programs = options.experimentalPrograms === undefined ? undefined : captureProgramGrants(options.experimentalPrograms)\n // Handles programs retain live for this turn only.\n const programResults = programs === undefined ? undefined : new ProgramResultStore()\n const dedicatedFinalOutput = options.outputFormat?.type === 'json_schema' && callableTools\n const turnOperationId = options.accounting?.startOperation('turn', {\n data: { turn, model: options.config.model },\n })\n let turnOperationEnded = false\n let usageStop: TurnOutcome['reason'] | undefined\n // Shared by retries, hook continuations, and both finalizer paths. Finalizers\n // may have a separate step allowance, never a separate token allowance.\n const admissionStop = (): TurnOutcome['reason'] | undefined => {\n if (signal.aborted) return { kind: 'aborted' }\n const mandatoryStop = accountingUsageStop(options.accounting)\n if (mandatoryStop !== undefined) return mandatoryStop\n if (usageStop !== undefined) return usageStop\n const tokens = budgetTokenTotal(summarizeModelCallUsage(modelCallReports))\n return tokens !== undefined && tokens >= maxTotalTokens\n ? { kind: 'budget-exhausted', budget: 'tokens', forcedFinalAnswer: false }\n : undefined\n }\n\n try {\n await emit({\n type: 'span-start', trace: root, at: startedAt,\n name: `invoke_agent ${options.trace?.agentId ?? 'agent'}`, kind: 'invoke_agent',\n attributes: {\n 'gen_ai.operation.name': 'invoke_agent',\n 'gen_ai.agent.id': options.trace?.agentId ?? 'agent',\n 'gen_ai.agent.name': options.trace?.agentName ?? options.trace?.agentId ?? 'agent',\n 'gen_ai.request.model': options.config.model,\n ...options.trace?.conversationId === undefined\n ? {}\n : { 'gen_ai.conversation.id': options.trace.conversationId },\n },\n })\n rootStarted = true\n await emit({ type: 'turn-start', turn, trace: root })\n\n turnLifecycle: while (true) {\n while (reason === undefined && steps < maxSteps && !signal.aborted) {\n reason = admissionStop()\n if (reason !== undefined) break\n // Auto has no step countdown. Warn from the same usage total as admission,\n // before a hard token stop can leave the agent without a reporting call.\n const usedTokens = budgetTokenTotal(summarizeModelCallUsage(modelCallReports))\n if (bounds.maxTotalTokens !== 'auto' && usedTokens !== undefined) {\n const crossed = [0.5, 0.75, 0.9].filter(ratio => usedTokens >= maxTotalTokens * ratio).length\n if (crossed > tokenRemindersSent) {\n tokenRemindersSent = crossed\n const remaining = Math.max(0, maxTotalTokens - usedTokens)\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'tool-loop-token-guard' },\n content: [{ type: 'text', text: `Token budget: ${remaining} of ${bounds.maxTotalTokens} aggregate tokens remain. Each request also spends input tokens on the accumulated context. `\n + (crossed >= 2 ? 'Stop broad exploration. ' : 'Prioritize outstanding verification and reporting. ')\n + 'Reserve capacity for the required self-check, honest todo reconciliation and substantive final report. State unavailable evidence and unfinished work; do not claim it is verified. No extra model call is allowed after the hard token limit.',\n }],\n }) })\n }\n }\n // Leave time to reconcile a plan and submit a result before the final\n // tools-disabled summary. Tool-call reminders do not cover step limits.\n if (!stepReminderSent && steps > 0 && maxSteps - steps <= 2) {\n stepReminderSent = true\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'tool-loop-step-guard' },\n content: [{ type: 'text', text:\n `${maxSteps - steps} work steps remain. Finish essential verification, update any task list honestly, and submit the result if required. Summarize findings, evidence, and unfinished work; do not start new exploration.`,\n }],\n }) })\n }\n // Recomputed before the request that will read it, so a section reacting to\n // the previous step's tool calls is already on the surface.\n if (contextSections !== undefined) {\n await contextSections.reconcile(steps, contextTouches, signal)\n contextTouches = []\n }\n const step = steps + 1\n const round = await modelRound(\n options, signal, emit, emitMaintenance, root, turn, step,\n dedicatedFinalOutput\n ? 'process'\n : options.outputFormat?.type === 'json_schema' ? 'final' : 'standard',\n )\n steps++\n if (round.report !== undefined) modelCallReports.push(round.report)\n if (round.message !== undefined) {\n options.history.append({\n kind: 'assistant', message: round.message,\n ...round.finish.kind === 'aborted' ? { interrupted: true as const } : {},\n ...round.usage === undefined ? {} : { usage: round.usage },\n })\n await emit({ type: 'assistant-message', message: round.message, trace: round.trace })\n await emitAssistantContent(round, emit)\n text = textOf(round.message.content)\n } else if (round.finish.kind === 'stop') {\n // A successful empty round cannot answer new input with earlier text.\n // Keep earlier text only when a later request fails or is interrupted.\n text = ''\n }\n usageStop = accountingUsageStop(options.accounting) ?? (round.usageRequired\n ? { kind: 'error', failure: { message: 'provider usage is required by the configured run policy', code: 'USAGE_REQUIRED' } }\n : round.usageUnavailable\n ? { kind: 'usage-unavailable', modelCallId: round.report?.modelCallId ?? 'unknown' }\n : undefined)\n if (signal.aborted || round.finish.kind === 'aborted') { reason = { kind: 'aborted' }; break }\n // Pair emitted tool calls with declined results even when policy stops the\n // run; never execute those calls or allow a retry hook to override policy.\n if (round.finish.kind === 'error' && usageStop !== undefined) {\n reason = { kind: 'error', failure: round.finish.failure }\n break\n }\n if (round.usageRequired && (round.calls.length === 0 || options.tools === undefined)) { reason = usageStop; break }\n if (round.finish.kind === 'error' && !round.usageRequired) {\n reason = admissionStop()\n if (reason !== undefined) break\n const decision = await runOptionalHook(options.hooks?.onRequestError, [{\n turn, step, failure: round.finish.failure, snapshot: options.history.snapshot(), signal,\n ...(options.logger === undefined ? {} : { logger: options.logger }),\n emit: emitMaintenance,\n }], options, signal, 'onRequestError')\n const maintenanceStop = accountingUsageStop(options.accounting)\n if (maintenanceStop !== undefined) { reason = signal.aborted ? { kind: 'aborted' } : maintenanceStop; break }\n if (decision === 'retry' && steps < maxSteps) continue\n reason = { kind: 'error', failure: round.finish.failure }\n break\n }\n if (round.finish.kind === 'max-tokens' && !round.usageRequired) { reason = { kind: 'max-tokens' }; break }\n if (round.calls.length === 0 && round.usageUnavailable) {\n reason = accountingUsageStop(options.accounting) ?? { kind: 'usage-unavailable', modelCallId: round.report?.modelCallId ?? 'unknown' }\n break\n }\n if (round.calls.length === 0 && dedicatedFinalOutput) {\n reason = admissionStop()\n if (reason !== undefined) break\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'structured-output-finalizer' },\n content: [{\n type: 'text',\n text: 'The process phase is complete. Return the final answer now in the requested output format. Do not call tools.',\n }],\n }) })\n const final = await modelRound(\n options, signal, emit, emitMaintenance, root, turn, steps + 1, 'final',\n )\n steps++\n if (final.report !== undefined) modelCallReports.push(final.report)\n if (final.message !== undefined) {\n options.history.append({\n kind: 'assistant', message: final.message,\n ...final.usage === undefined ? {} : { usage: final.usage },\n })\n await emit({ type: 'assistant-message', message: final.message, trace: final.trace })\n await emitAssistantContent(final, emit)\n text = textOf(final.message.content)\n }\n if (final.finish.kind === 'aborted') reason = { kind: 'aborted' }\n else if (final.finish.kind === 'error') reason = { kind: 'error', failure: final.finish.failure }\n else if (final.finish.kind === 'max-tokens') reason = { kind: 'max-tokens' }\n else if (final.usageRequired) reason = { kind: 'error', failure: {\n message: 'provider usage is required by the configured run policy',\n code: 'USAGE_REQUIRED',\n } }\n else if (final.usageUnavailable) {\n reason = accountingUsageStop(options.accounting) ?? { kind: 'usage-unavailable', modelCallId: final.report?.modelCallId ?? 'unknown' }\n } else reason = { kind: 'completed' }\n break\n }\n // A provider that repeated an id had the repeat dropped. Saying so is what\n // keeps the model from reading one result for two calls as a tool that\n // silently ignored it.\n if (round.droppedDuplicateCalls !== undefined) {\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'tool-loop-duplicate-guard' },\n content: [{\n type: 'text',\n text: `You reused the tool-call id ${round.droppedDuplicateCalls.map(id => `'${id}'`).join(', ')}.`\n + ' A result pairs to exactly one call, so the repeat was not run and only the first'\n + ' call of that id has a result. Give every call its own id, and call again if you'\n + ' still need what the dropped one would have done.',\n }],\n }) })\n }\n if (round.calls.length === 0 || options.tools === undefined) { reason = { kind: 'completed' }; break }\n\n // Calls the budget does not govern: submitting, asking, delegating. They\n // are dispatched even when the budget is spent, so the model always has a\n // legal way to finish. See `ToolDefinition.budgetExempt`.\n const remaining = Math.max(0, bounds.maxToolCalls - toolCalls)\n let repeatProjection: { key: string; count: number } | undefined = lastRepeat\n const projectedRepeats = round.calls.map(call => {\n const key = repeatKey(call)\n // Count consecutive calls, not lifetime visits to a source or test command.\n // Distinct intervening work may change its result. Alternating loops are\n // handled separately by the step-cycle guard below.\n const count = repeatProjection?.key === key ? repeatProjection.count + 1 : 1\n repeatProjection = { key, count }\n return count\n })\n const repeatedLimitBeforeDispatch = projectedRepeats.some(count => count >= bounds.repeatToolLimit)\n const actionPattern = toolActionPattern(round.calls)\n const projectedCycle = repeatedSuffixCycle(\n [...actionSteps, actionPattern],\n bounds.maxToolCycleLength,\n )\n const cycleLimitBeforeDispatch = projectedCycle !== undefined\n && projectedCycle.repetitions >= bounds.toolCycleLimit\n const currentUsage = summarizeModelCallUsage(modelCallReports)\n const budgetTokens = budgetTokenTotal(currentUsage)\n const tokenLimitBeforeDispatch = budgetTokens !== undefined\n && budgetTokens >= maxTotalTokens\n const guardDeclined = cycleLimitBeforeDispatch || tokenLimitBeforeDispatch || round.usageRequired\n // Name the limit that actually declined the call. Reporting a repeat guard\n // as an empty budget teaches the model the wrong lesson, and it repeats the\n // call on the next turn with the budget it was told it lacked.\n const declineReason: ToolDeclineReason = tokenLimitBeforeDispatch\n ? 'tokens'\n : cycleLimitBeforeDispatch\n ? 'tool-call-cycle'\n : round.usageRequired\n ? 'usage-required'\n : 'tool-calls'\n // `continue` takes the wall down: the budget becomes a notice and the turn\n // is bounded by steps, tokens, and the run-level ledger instead. Guards\n // that mean \"this is not working\" still decline, whatever the setting.\n const budgetIsAWall = bounds.onExhausted !== 'continue'\n const recoveredCallIds = new Set<string>()\n // A round-wide guard must not make an unrelated old success reusable.\n // Recovery is only legal for a call that individually reached the limit and\n // whose successful result is the immediately preceding call in this streak.\n const individuallyRepeatedCallIds = new Set(round.calls\n .filter((_call, index) => (projectedRepeats[index] ?? 0) >= bounds.repeatToolLimit)\n .map(call => String(call.callId)))\n // Only ordinary dispatches request quota: repeated calls are either recovered\n // for free or individually declined. Fresh siblings keep normal admission.\n const budgetedCalls = round.calls.filter(call =>\n !individuallyRepeatedCallIds.has(String(call.callId))\n && options.tools?.get(call.toolName)?.budgetExempt !== true).length\n const recover = repeatedLimitBeforeDispatch && !cycleLimitBeforeDispatch && !tokenLimitBeforeDispatch\n && !round.usageRequired\n ? (call: typeof round.calls[number]): ToolExecutionResult | undefined => {\n const prior = successfulCalls.get(repeatKey(call))\n if (!individuallyRepeatedCallIds.has(String(call.callId))\n || lastRepeat?.key !== repeatKey(call)\n || lastRepeat.succeeded !== true\n || prior === undefined\n || prior.callId !== lastRepeat.callId\n || prior.rawArguments !== call.rawArguments\n || prior.definition !== options.tools?.get(call.toolName)\n || prior.result.additionalContext !== undefined\n || prior.result.concludesTurn === true\n || options.tools?.get(call.toolName)?.budgetExempt === true) return undefined\n recoveredCallIds.add(String(call.callId))\n return duplicateOfResult(prior)\n }\n : undefined\n const scheduled = await scheduleToolCalls({\n calls: round.calls, catalog: options.tools, history: options.history,\n position: { turn, step,\n ...(options.accounting === undefined ? {} : { runId: options.accounting.runId }),\n ...(options.trace?.conversationId === undefined ? {} : { conversationId: options.trace.conversationId }),\n }, signal, parentTrace: root,\n maxParallel: bounds.maxParallel,\n dispatchLimit: guardDeclined ? 0 : budgetIsAWall ? remaining : round.calls.length,\n declineReason,\n maxResultBytes: bounds.maxToolResultBytes,\n maxResultTokens: bounds.maxToolResultTokens,\n resultOverflow: bounds.toolResultOverflow,\n ...options.spillStore === undefined ? {} : { spillStore: options.spillStore },\n maxDurationMs: bounds.maxToolDurationMs,\n teardownTimeoutMs: bounds.toolTeardownTimeoutMs,\n ...(options.logger === undefined ? {} : { logger: options.logger }),\n ...options.interceptors === undefined ? {} : { interceptors: options.interceptors },\n ...options.approvals === undefined ? {} : { approvals: options.approvals },\n ...options.accounting === undefined ? {} : { accounting: options.accounting },\n emit,\n ...recover === undefined ? {} : { recover },\n ...options.hooks?.checkpoint === undefined ? {} : {\n checkpoint: (context: Parameters<NonNullable<TurnHooks['checkpoint']>>[0]) => runHook(\n Promise.resolve(options.hooks?.checkpoint?.(context)), options, signal, 'checkpoint',\n ),\n },\n }, {\n admissionLimit: guardDeclined ? 0 : budgetIsAWall ? remaining : 'unbounded',\n ...guardDeclined || !repeatedLimitBeforeDispatch ? {} : {\n decline: (call: typeof round.calls[number]): ToolDeclineReason | undefined =>\n individuallyRepeatedCallIds.has(String(call.callId)) ? 'repeated-tool-call' : undefined,\n },\n ...programs === undefined ? {} : { programs },\n ...programResults === undefined ? {} : { programResults },\n })\n // Results commit in model order, one per requested call, so the pairing\n // holds for declined calls too. A short result list means a sibling failed\n // its contract and the turn is already unwinding; reporting a guessed\n // outcome would be worse than reporting nothing.\n if (contextSections !== undefined && scheduled.results.length === round.calls.length) {\n contextTouches.push(...round.calls.map((call, index) => ({\n toolName: call.toolName,\n rawArguments: call.rawArguments,\n failed: scheduled.results[index]?.isError ?? true,\n })))\n }\n toolCalls += scheduled.budgeted\n const remainingAfterDispatch = Math.max(0, bounds.maxToolCalls - toolCalls)\n // One reminder per threshold crossed, not one per turn.\n //\n // This was a single boolean: the model was told once, at 25% remaining,\n // and then never again however close it came to the end. A model warned at\n // sixteen calls left and still exploring at four has been told nothing\n // since, and runs into the wall with no notice — which is what produces a\n // red \"no remaining tool-call budget\" where an answer should have been.\n //\n // Codex counts thresholds rather than remembering a flag\n // (`rollout_budget.rs`, `reminder_index`): every threshold now below the\n // remaining budget that has not been reported yet gets reported. Crossing\n // several at once collapses into the one that matters, the lowest.\n const crossed = budgetReminders.filter(threshold => remainingAfterDispatch <= threshold).length\n if (crossed > budgetRemindersSent && remainingAfterDispatch > 0) {\n budgetRemindersSent = crossed\n appendBudgetNotice(\n `Tool budget: ${remainingAfterDispatch} of ${bounds.maxToolCalls} calls remain in this turn.`\n + ' Stop broad exploration, make the necessary edits, and reserve calls for'\n + (budgetIsAWall\n ? ' verification. When the budget runs out no further work call will run, so'\n + ' finish with what you can still verify.'\n : ' verification. Past the budget you are expected to be wrapping up, not'\n + ' opening new lines of work.'),\n )\n }\n // Past the budget with the wall down. The turn is not stopped — the model\n // keeps its tools — but it is told, once per further budget spent, that it\n // is now expected to be finishing. This is the shape of Codex's\n // `budget_limit` goal prompt: no new substantive work, wrap up, name what\n // is left.\n if (!budgetIsAWall && remainingAfterDispatch === 0) {\n const windows = Math.floor(toolCalls / bounds.maxToolCalls)\n if (windows > overBudgetNoticesSent) {\n overBudgetNoticesSent = windows\n appendBudgetNotice(\n `Tool budget spent: ${toolCalls} calls made against a budget of ${bounds.maxToolCalls}.`\n + ' Do not start new substantive work. Finish what is in flight, verify what you'\n + ' can, and answer — stating plainly what is unverified or unfinished.',\n )\n }\n }\n await emit({ type: 'step-end', turn, step, trace: round.trace })\n\n actionSteps.push(actionPattern)\n let repeatedLimit = repeatedLimitBeforeDispatch\n for (let index = 0; index < round.calls.length; index++) {\n const call = round.calls[index]\n const result = scheduled.results[index]\n if (call === undefined || result === undefined) continue\n consecutiveErrors = result.isError ? consecutiveErrors + 1 : 0\n const key = repeatKey(call)\n const count = lastRepeat?.key === key ? lastRepeat.count + 1 : 1\n lastRepeat = {\n key, count, callId: String(call.callId),\n succeeded: !result.isError && result.meta?.declined !== true\n && options.tools?.get(call.toolName)?.budgetExempt !== true,\n }\n if (count === bounds.repeatToolWarningAt) {\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'tool-loop-repeat-guard' },\n content: [{ type: 'text', text: `You have called ${call.toolName} with the same arguments ${count} consecutive times. Reassess before repeating it.` }],\n }) })\n }\n if (count >= bounds.repeatToolLimit) repeatedLimit = true\n if (!result.isError && result.meta?.declined !== true\n && options.tools?.get(call.toolName)?.budgetExempt !== true) {\n successfulCalls.set(key, {\n callId: String(call.callId), rawArguments: call.rawArguments,\n definition: options.tools.get(call.toolName), result,\n })\n }\n }\n if (projectedCycle?.repetitions === bounds.toolCycleWarningAt) {\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'tool-loop-cycle-guard' },\n content: [{\n type: 'text',\n text: `Tool-use pattern repeated ${projectedCycle.repetitions} times across ${projectedCycle.period} step(s). Reassess the approach and identify concrete new evidence before continuing.`,\n }],\n }) })\n }\n if (scheduled.concluded) { reason = { kind: 'concluded-by-tool', toolName: scheduled.concludedBy ?? 'unknown' }; break }\n if (signal.aborted) { reason = { kind: 'aborted' }; break }\n if (round.usageRequired) { reason = usageStop; break }\n if (round.usageUnavailable) {\n reason = accountingUsageStop(options.accounting) ?? { kind: 'usage-unavailable', modelCallId: round.report?.modelCallId ?? 'unknown' }\n break\n }\n let exhausted: ExhaustedBudget | undefined\n const reportReserveReached = bounds.maxTotalTokens !== 'auto'\n && bounds.finalReportReserveTokens > 0 && budgetTokens !== undefined\n && budgetTokens >= maxTotalTokens - bounds.finalReportReserveTokens\n const recoveredOnlyReplan = repeatedLimitBeforeDispatch\n && recoveredCallIds.size === round.calls.length\n && round.calls.every(call => recoveredCallIds.has(String(call.callId))\n && !recoveredReplanKeys.has(repeatKey(call)))\n && scheduled.results.length === round.calls.length\n && scheduled.results.every(result => !result.isError)\n && scheduled.dispatched === 0 && scheduled.declined === 0\n && !cycleLimitBeforeDispatch && !tokenLimitBeforeDispatch && !reportReserveReached\n && !round.usageRequired && !round.usageUnavailable && !signal.aborted\n && !(budgetIsAWall && budgetedCalls > remaining)\n && consecutiveErrors === 0 && steps < maxSteps\n && bounds.onExhausted !== 'stop' && admissionStop() === undefined\n // A repeated call cannot poison new work in the same model batch. Successful\n // recovery alongside a real dispatch is ordinary progress, not an extra pure\n // duplicate replan. The other exhaustion checks below still apply.\n const recoveredWithFreshDispatch = repeatedLimitBeforeDispatch\n && [...individuallyRepeatedCallIds].every(id => recoveredCallIds.has(id))\n && scheduled.results.length === round.calls.length\n && scheduled.dispatched > 0 && scheduled.declined === 0\n if (recoveredOnlyReplan) {\n for (const call of round.calls) recoveredReplanKeys.add(repeatKey(call))\n } else if (tokenLimitBeforeDispatch) exhausted = 'tokens'\n else if (reportReserveReached) exhausted = 'tokens'\n else if (cycleLimitBeforeDispatch) exhausted = 'tool-call-cycle'\n else if (budgetIsAWall && budgetedCalls > remaining) exhausted = 'tool-calls'\n else if (consecutiveErrors >= bounds.maxConsecutiveToolErrors) exhausted = 'consecutive-tool-errors'\n else if (repeatedLimit && !recoveredWithFreshDispatch) exhausted = 'repeated-tool-call'\n else if (steps >= maxSteps) exhausted = 'steps'\n if (exhausted === undefined && recoveredWithFreshDispatch) {\n for (const call of round.calls) {\n if (recoveredCallIds.has(String(call.callId))) recoveredReplanKeys.add(repeatKey(call))\n }\n }\n if (exhausted !== undefined) {\n const forced = (exhausted !== 'tokens' || (reportReserveReached && !tokenLimitBeforeDispatch))\n && bounds.onExhausted !== 'stop'\n && admissionStop() === undefined\n if (forced) {\n const final = await modelRound(\n options, signal, emit, emitMaintenance, root, turn, steps + 1, 'forced-final',\n )\n steps++\n if (final.report !== undefined) modelCallReports.push(final.report)\n if (final.message !== undefined) {\n options.history.append({ kind: 'assistant', message: final.message, ...final.usage === undefined ? {} : { usage: final.usage } })\n await emit({ type: 'assistant-message', message: final.message, trace: final.trace })\n await emitAssistantContent(final, emit)\n text = textOf(final.message.content)\n }\n if (final.finish.kind === 'aborted') {\n reason = { kind: 'aborted' }\n break\n }\n if (final.finish.kind === 'error') {\n reason = { kind: 'error', failure: final.finish.failure }\n break\n }\n if (final.finish.kind === 'max-tokens') {\n reason = { kind: 'max-tokens' }\n break\n }\n if (final.usageRequired) {\n reason = { kind: 'error', failure: {\n message: 'provider usage is required by the configured run policy',\n code: 'USAGE_REQUIRED',\n } }\n break\n }\n if (final.usageUnavailable) {\n reason = accountingUsageStop(options.accounting) ?? { kind: 'usage-unavailable', modelCallId: final.report?.modelCallId ?? 'unknown' }\n break\n }\n }\n reason = { kind: 'budget-exhausted', budget: exhausted, forcedFinalAnswer: forced,\n ...(exhausted === 'tokens' && reportReserveReached && !tokenLimitBeforeDispatch\n ? { trigger: 'report-reserve' as const } : {}),\n }\n }\n }\n\n if (reason === undefined) {\n reason = signal.aborted\n ? { kind: 'aborted' }\n : { kind: 'budget-exhausted', budget: 'steps', forcedFinalAnswer: false }\n }\n const usageReport = summarizeModelCallUsage(modelCallReports)\n const usage = authoritativeTokenUsage(usageReport)\n const candidate: TurnOutcome = {\n reason, text, steps, usageReport, toolCalls, traceId,\n ...usage === undefined ? {} : { usage },\n }\n const entriesBeforeHook = options.history.entries().length\n const canContinue = reason.kind === 'completed'\n && steps < maxSteps\n && admissionStop() === undefined\n await runOptionalHook(options.hooks?.onTurnEnd, [{\n outcome: candidate,\n snapshot: options.history.snapshot(),\n canContinue,\n }], options, signal.aborted ? new AbortController().signal : signal, 'onTurnEnd')\n // Hooks object by appending context rather than by returning a veto. Re-run only\n // a normally completed turn; abort/error/budget outcomes remain terminal.\n // Input the person sent while the final answer was being written is owed an\n // answer too: when nothing else continues the turn, take it and continue.\n if (canContinue\n && !signal.aborted\n && (options.history.entries().length > entriesBeforeHook || deliverQueuedInput(options.history))) {\n reason = undefined\n continue turnLifecycle\n }\n outcome = candidate\n break\n }\n if (outcome.reason.kind === 'aborted') {\n // Without this, the next turn sees an unfinished request and a cancelled\n // tool call, and a model resumes the abandoned work instead of answering\n // the new message (observed live). Codex and Claude Code record the same\n // interruption marker.\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'turn-interrupted' },\n content: [{ type: 'text', text: 'The previous request was interrupted before it finished. Use the next message to determine what to do next.' }],\n }) })\n }\n await emit({\n type: 'span-end', trace: root, at: now(),\n status: outcome.reason.kind === 'error' ? 'error' : outcome.reason.kind === 'aborted' ? 'aborted' : 'success',\n output: { reason: outcome.reason, text },\n ...outcome.usage === undefined ? {} : { usage: outcome.usage },\n ...outcome.reason.kind === 'error' ? { error: { type: 'ModelError', message: outcome.reason.failure.message, code: outcome.reason.failure.code } } : {},\n })\n rootEnded = true\n if (turnOperationId !== undefined) {\n options.accounting?.endOperation(\n turnOperationId,\n outcome.reason.kind === 'error' ? 'error' : outcome.reason.kind === 'aborted' ? 'aborted' : 'success',\n { data: { reason: outcome.reason.kind, steps, toolCalls } },\n )\n turnOperationEnded = true\n }\n await emit({ type: 'turn-end', outcome, trace: root })\n } catch (error: unknown) {\n const code = errorCodeOf(error)\n if (rootStarted && !rootEnded) {\n await emit({\n type: 'span-end', trace: root, at: now(), status: signal.aborted ? 'aborted' : 'error',\n error: {\n type: error instanceof Error ? error.name : 'RuntimeError',\n message: messageOf(error),\n ...code === undefined ? {} : { code },\n },\n }).catch(() => undefined)\n }\n if (turnOperationId !== undefined && !turnOperationEnded) {\n options.accounting?.endOperation(\n turnOperationId,\n signal.aborted ? 'aborted' : 'error',\n { error },\n )\n turnOperationEnded = true\n }\n throw error\n } finally {\n programResults?.close()\n }\n}\n\nfunction duplicateOfResult(prior: {\n readonly callId: string\n readonly result: Extract<ToolExecutionResult, { readonly isError: false }>\n}): ToolExecutionResult {\n return detachedFrozen({\n isError: false,\n // The prior structured value remains the host's canonical result. The\n // header is model-visible so it knows this call was intentionally reused.\n value: prior.result.value,\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n status: 'duplicate_of',\n callId: prior.callId,\n instruction: 'This exact call already succeeded in this run. Use the retained result below; do not call it again.',\n }),\n },\n ...prior.result.content,\n ],\n meta: { ...prior.result.meta, recovered: true, duplicateOfCallId: prior.callId },\n })\n}\n\nexport type { RunTurnOptions } from './turn/types.ts'\n"],"mappings":"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"}
1
+ {"version":3,"file":"run-turn.js","names":[],"sources":["../../../src/agent/loop/run-turn.ts"],"sourcesContent":["import { createMessage, createUserMessage, type Message } from '../../message/index.ts'\nimport { detachedFrozen } from '../../primitives/index.ts'\nimport type { ModelCallReport } from '../../observation/index.ts'\nimport { waitForSettlement } from '../../async/index.ts'\nimport { authoritativeTokenUsage, budgetTokenTotal, summarizeModelCallUsage } from '../accounting/ledger.ts'\nimport { createSpanId, createTraceId, type TraceRef } from '../trace/trace.ts'\nimport type { ToolDefinition, ToolExecutionResult } from '../tool/definition.ts'\nimport type { AgentEvent, ExhaustedBudget, ToolDeclineReason, TurnHooks, TurnOutcome } from './types.ts'\nimport { AwaitedEventQueue } from './queue.ts'\nimport { scheduleToolCalls } from './schedule.ts'\nimport { captureProgramGrants } from '../tool/nested.ts'\nimport { ProgramResultStore } from '../tool/program-results.ts'\nimport { type RunTurnOptions } from './turn/types.ts'\nimport { resolveBounds, positiveFinite, snapshotRunTurnOptions } from './turn/config.ts'\nimport { codedRuntimeError, messageOf, errorCodeOf, now } from './turn/common.ts'\nimport { deliverQueuedInput, hasQueuedInput } from './turn/model-request-boundary.ts'\nimport { runOptionalHook, runHook } from './turn/hooks.ts'\nimport { maintenanceEmitter, emitAssistantContent, textOf } from './turn/content.ts'\nimport { repeatKey, toolActionPattern, repeatedSuffixCycle } from './turn/repetition.ts'\nimport { modelRound } from './turn/model-round.ts'\nimport { accountingUsageStop } from './turn/usage-stop.ts'\nimport { ContextSectionRuntime } from '../context/section.ts'\nimport type { ContextToolTouch } from '../context/types.ts'\n\nfunction hasCallableTools(options: RunTurnOptions): boolean {\n if (options.toolChoice === 'none') return false\n return (options.tools?.names().length ?? 0) > 0 || (options.nativeTools?.length ?? 0) > 0\n}\n\n/** Run one bounded turn as a backpressured event stream. */\nexport function runTurn(options: RunTurnOptions): AsyncIterable<AgentEvent> {\n return {\n async * [Symbol.asyncIterator]() {\n const invocation = snapshotRunTurnOptions(options)\n const queue = new AwaitedEventQueue<AgentEvent>()\n const consumer = new AbortController()\n const teardownTimeoutMs = positiveFinite(invocation.teardownTimeoutMs ?? 30_000, 'teardownTimeoutMs')\n const signal = invocation.signal === undefined\n ? consumer.signal\n : AbortSignal.any([invocation.signal, consumer.signal])\n const task = driveTurn(invocation, signal, event => queue.push(detachedFrozen(event)))\n .then(() => queue.close(), error => queue.fail(error))\n try {\n while (true) {\n const item = await queue.take()\n if (item.done) break\n yield item.value\n }\n await task\n } finally {\n consumer.abort(new Error('turn event consumer stopped'))\n queue.close()\n if (!await waitForSettlement(task, teardownTimeoutMs)) {\n throw codedRuntimeError(\n `turn producer ignored cancellation for more than ${teardownTimeoutMs}ms`,\n 'TURN_TEARDOWN_TIMEOUT',\n consumer.signal.reason,\n )\n }\n }\n },\n }\n}\n\n/** Request retries per turn that do not count against `maxSteps`. */\nconst MAX_FREE_REQUEST_RETRIES = 8\n\nasync function driveTurn(\n options: RunTurnOptions,\n signal: AbortSignal,\n emit: (event: AgentEvent) => Promise<void>,\n): Promise<void> {\n const bounds = resolveBounds(options.bounds)\n const maxTotalTokens = bounds.maxTotalTokens === 'auto' ? Infinity : bounds.maxTotalTokens\n // Infinity is local control flow only. Public configuration/events retain\n // the serializable 'auto' value, and all other admission guards still apply.\n const maxSteps = bounds.maxSteps === 'auto' ? Infinity : bounds.maxSteps\n const traceId = options.trace?.traceId ?? createTraceId()\n const root: TraceRef = { traceId, spanId: createSpanId(), parentSpanId: options.trace?.parentSpanId ?? null }\n const turn = Math.max(1, options.history.entries().filter(entry =>\n entry.event.kind === 'user' && entry.event.message.source.kind === 'user').length)\n const startedAt = now()\n let steps = 0\n /**\n * Rounds the request-error hook asked to retry. Each still gets its own step\n * number, but a provider blip must not spend the work the budget is for:\n * limits compare `workSteps`. Bounded, so a hook that always retries cannot\n * loop forever; past the bound a retry costs a step as it used to.\n */\n let retriedRounds = 0\n const workSteps = (): number => steps - retriedRounds\n const position = () => ({ workStep: workSteps() + 1, finalizing: finalizeUntil !== undefined })\n // Wall-clock budget for the turn's own work. Time spent waiting for a person\n // is not work, so it is not charged.\n const maxTurnDurationMs = bounds.maxTurnDurationMs === 'auto' ? Infinity : bounds.maxTurnDurationMs\n const turnStartedMs = Date.now()\n let personWaitMs = 0\n let waitingSince: number | undefined\n let personCalls = 0\n let workCalls = 0\n const toolActivity = (awaitsPerson: boolean, active: boolean): void => {\n const at = Date.now()\n if (waitingSince !== undefined) personWaitMs += at - waitingSince\n if (awaitsPerson) personCalls += active ? 1 : -1\n else workCalls += active ? 1 : -1\n // Only time spent solely waiting is free; parallel tool work still counts.\n waitingSince = personCalls > 0 && workCalls === 0 ? at : undefined\n }\n const timeSpent = (): number => {\n const at = Date.now()\n return at - turnStartedMs - personWaitMs - (waitingSince === undefined ? 0 : at - waitingSince)\n }\n /**\n * A spent budget ends the turn with an answer, not without one: one\n * tools-off round writes it from the evidence already gathered. That round\n * gets the request-error retry, and one more try if it came back empty,\n * because it is the only thing the person will receive.\n */\n const forceAnswer = async (\n exhausted: ExhaustedBudget,\n reserveTrigger: boolean,\n ): Promise<TurnOutcome['reason']> => {\n let final = await retryFinalRound(await modelRound(\n options, signal, emit, emitMaintenance, root, turn, steps + 1, 'forced-final', position(),\n ), 'forced-final')\n // No answer came back: empty text, or only a call to a tool it cannot use.\n const unanswered = (round: typeof final) => !round.usageRequired && !round.usageUnavailable\n && ((round.finish.kind === 'stop' && textOf(round.message?.content ?? []).trim() === '')\n || (round.finish.kind === 'error' && round.finish.failure.code === 'INVALID_TOOL_CALL'))\n if (unanswered(final) && !signal.aborted && retriedRounds < MAX_FREE_REQUEST_RETRIES\n && admissionStop(final.report) === undefined) {\n if (final.report !== undefined) modelCallReports.push(final.report)\n if (final.message !== undefined) {\n options.history.append({ kind: 'assistant', message: final.message, ...final.usage === undefined ? {} : { usage: final.usage } })\n }\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'forced-answer-empty' },\n content: [{ type: 'text', text: 'Your last reply contained no answer. Tools are disabled now. Write the answer for the user now, in text, from the evidence already gathered, and state what could not be checked.' }],\n }) })\n steps++\n retriedRounds++\n final = await modelRound(options, signal, emit, emitMaintenance, root, turn, steps + 1, 'forced-final', position())\n }\n steps++\n if (final.report !== undefined) modelCallReports.push(final.report)\n if (final.message !== undefined) {\n options.history.append({ kind: 'assistant', message: final.message, ...final.usage === undefined ? {} : { usage: final.usage } })\n await emit({ type: 'assistant-message', message: final.message, trace: final.trace })\n await emitAssistantContent(final, emit)\n text = textOf(final.message.content)\n } else {\n // The forced answer said nothing; an earlier round's narration is not it.\n text = ''\n }\n if (signal.aborted || final.finish.kind === 'aborted') return { kind: 'aborted' }\n // A model that still only reaches for tools has given no answer; that is\n // the budget's stop without one, not a failure of the run.\n if (final.finish.kind === 'error' && final.finish.failure.code === 'INVALID_TOOL_CALL') {\n text = ''\n return { kind: 'budget-exhausted', budget: exhausted, forcedFinalAnswer: false,\n ...(reserveTrigger ? { trigger: 'report-reserve' as const } : {}) }\n }\n if (final.finish.kind === 'error') return { kind: 'error', failure: final.finish.failure }\n if (final.finish.kind === 'max-tokens') return { kind: 'max-tokens' }\n if (final.usageRequired) {\n return { kind: 'error', failure: { message: 'provider usage is required by the configured run policy', code: 'USAGE_REQUIRED' } }\n }\n if (final.usageUnavailable) {\n return accountingUsageStop(options.accounting) ?? { kind: 'usage-unavailable', modelCallId: final.report?.modelCallId ?? 'unknown' }\n }\n return { kind: 'budget-exhausted', budget: exhausted, forcedFinalAnswer: text.trim() !== '',\n ...(reserveTrigger ? { trigger: 'report-reserve' as const } : {}) }\n }\n /**\n * The tools-off rounds that close a turn (the forced answer, the structured\n * output finalizer) are the single call the whole run's evidence depends on.\n * A transient failure there gets the same retry hook as any other request,\n * from the same free-retry allowance; the failed attempt is not kept.\n */\n const retryFinalRound = async (\n first: Awaited<ReturnType<typeof modelRound>>,\n phase: 'final' | 'forced-final',\n ): Promise<Awaited<ReturnType<typeof modelRound>>> => {\n let final = first\n while (final.finish.kind === 'error' && !final.usageRequired && !signal.aborted\n && !final.usageUnavailable && retriedRounds < MAX_FREE_REQUEST_RETRIES\n && admissionStop(final.report) === undefined) {\n const decision = await runOptionalHook(options.hooks?.onRequestError, [{\n turn, step: steps + 1, failure: final.finish.failure, snapshot: options.history.snapshot(), signal,\n ...(options.logger === undefined ? {} : { logger: options.logger }),\n emit: emitMaintenance,\n }], options, signal, 'onRequestError')\n // A hook waiting out a backoff when the person aborts throws the abort;\n // that is a cancelled turn, not a crashed one.\n .catch((error: unknown) => { if (signal.aborted) return 'fail' as const; throw error })\n if (decision !== 'retry' || admissionStop(final.report) !== undefined) break\n if (final.report !== undefined) modelCallReports.push(final.report)\n // The failed attempt keeps its step number; the caller counts the last one.\n steps++\n retriedRounds++\n final = await modelRound(options, signal, emit, emitMaintenance, root, turn, steps + 1, phase, position())\n }\n return final\n }\n let toolCalls = 0\n // Descending, so \"how many are below the remainder\" counts the crossings.\n const budgetReminders = [...bounds.toolBudgetRemindAt]\n .filter(threshold => threshold > 0 && threshold < bounds.maxToolCalls)\n .sort((left, right) => right - left)\n let budgetRemindersSent = 0\n /** How many full budgets an unwalled turn has spent and been told about. */\n let overBudgetNoticesSent = 0\n /** Sequence of the budget notice currently on the surface, if any. */\n let budgetNoticeSeq: number | undefined\n let stepReminderSent = false\n /**\n * After a budget forced the answer, at most one short window in which only\n * budget-exempt tools run; see `TurnBounds.finalizeSteps`.\n */\n let finalizeUntil: number | undefined\n let finalizeReason: ExhaustedBudget | undefined\n /** The forced-answer outcome that opened the window; the turn still ends as it. */\n let finalizeOrigin: Extract<TurnOutcome['reason'], { kind: 'budget-exhausted' } | { kind: 'completed' }> | undefined\n let forcedText = ''\n let forcedMessage: Message | undefined\n const finalizeTools = new Set(options.finalize?.tools ?? [])\n let tokenRemindersSent = 0\n let consecutiveErrors = 0\n let text = ''\n const modelCallReports: ModelCallReport[] = []\n let reason: TurnOutcome['reason'] | undefined\n let outcome: TurnOutcome\n /** The immediately preceding call/result, so recovery cannot cross a state-changing call or failure. */\n let lastRepeat: { key: string; count: number; callId: string; succeeded: boolean } | undefined\n /** Successful finalized results, retained only for this turn's exact repeat guard. */\n const successfulCalls = new Map<string, {\n readonly callId: string\n readonly rawArguments: string\n readonly definition: ToolDefinition | undefined\n readonly result: Extract<ToolExecutionResult, { readonly isError: false }>\n }>()\n /** Each exact recovered key gets one ordinary model replan, never a retry loop. */\n const recoveredReplanKeys = new Set<string>()\n const actionSteps: string[] = []\n const emitMaintenance = maintenanceEmitter(emit, root)\n /**\n * Put the current budget notice on the surface, replacing the previous one.\n *\n * One live notice, never a pile of them. Appending each new remainder leaves\n * \"16 calls remain\" and \"6 calls remain\" both readable, and a model that\n * plans against the older number plans against a budget it no longer has.\n * Codex keeps exactly one `<rollout_budget>` fragment for the same reason\n * (`context/rollout_budget.rs`), replacing it as the number moves.\n * @param text - What the model should read now.\n */\n const appendBudgetNotice = (text: string): void => {\n const message = createUserMessage({\n source: { kind: 'app', producer: 'tool-loop-budget-guard' },\n content: [{ type: 'text', text }],\n })\n const previous = budgetNoticeSeq\n // Replacing is best-effort. Compaction can shadow the earlier notice\n // between steps, and a replace whose target is no longer on the surface is\n // rejected — which must cost the model a reminder, never the turn.\n if (previous !== undefined) {\n try {\n budgetNoticeSeq = options.history.append(\n { kind: 'user', message },\n { op: 'replace', from: previous, to: previous, targets: [previous] },\n ).seq\n return\n } catch {\n budgetNoticeSeq = undefined\n }\n }\n budgetNoticeSeq = options.history.append({ kind: 'user', message }).seq\n }\n const contextSections = options.contextSections === undefined || options.contextSections.length === 0\n ? undefined\n : new ContextSectionRuntime({\n sections: options.contextSections,\n history: options.history,\n ...options.logger === undefined ? {} : { logger: options.logger },\n guard: (pending, name) => runHook(pending, options, signal, name),\n scope: { agentId: options.trace?.agentId, conversationId: options.trace?.conversationId },\n })\n /** Tool calls committed since the last section reconcile. */\n let contextTouches: ContextToolTouch[] = []\n let rootStarted = false\n let rootEnded = false\n const callableTools = hasCallableTools(options)\n const programs = options.experimentalPrograms === undefined ? undefined : captureProgramGrants(options.experimentalPrograms)\n // Handles programs retain live for this turn only.\n const programResults = programs === undefined ? undefined : new ProgramResultStore()\n const dedicatedFinalOutput = options.outputFormat?.type === 'json_schema' && callableTools\n const turnOperationId = options.accounting?.startOperation('turn', {\n data: { turn, model: options.config.model },\n })\n let turnOperationEnded = false\n let usageStop: TurnOutcome['reason'] | undefined\n // Shared by retries, hook continuations, and both finalizer paths. Finalizers\n // may have a separate step allowance, never a separate token allowance.\n const admissionStop = (pendingReport?: ModelCallReport): TurnOutcome['reason'] | undefined => {\n if (signal.aborted) return { kind: 'aborted' }\n const mandatoryStop = accountingUsageStop(options.accounting)\n if (mandatoryStop !== undefined) return mandatoryStop\n if (usageStop !== undefined) return usageStop\n // Finalizer attempts are committed by their caller. Their usage already\n // counts when deciding whether another request may start.\n const tokens = budgetTokenTotal(summarizeModelCallUsage(pendingReport === undefined\n ? modelCallReports : [...modelCallReports, pendingReport]))\n return tokens !== undefined && tokens >= maxTotalTokens\n ? { kind: 'budget-exhausted', budget: 'tokens', forcedFinalAnswer: false }\n : undefined\n }\n\n try {\n await emit({\n type: 'span-start', trace: root, at: startedAt,\n name: `invoke_agent ${options.trace?.agentId ?? 'agent'}`, kind: 'invoke_agent',\n attributes: {\n 'gen_ai.operation.name': 'invoke_agent',\n 'gen_ai.agent.id': options.trace?.agentId ?? 'agent',\n 'gen_ai.agent.name': options.trace?.agentName ?? options.trace?.agentId ?? 'agent',\n 'gen_ai.request.model': options.config.model,\n ...options.trace?.conversationId === undefined\n ? {}\n : { 'gen_ai.conversation.id': options.trace.conversationId },\n },\n })\n rootStarted = true\n await emit({ type: 'turn-start', turn, trace: root })\n\n turnLifecycle: while (true) {\n while (reason === undefined && workSteps() < (finalizeUntil ?? maxSteps) && !signal.aborted) {\n reason = admissionStop()\n if (reason !== undefined) break\n // Out of time before another work round: answer now, from what is known.\n if (steps > 0 && finalizeUntil === undefined && timeSpent() >= maxTurnDurationMs) {\n reason = bounds.onExhausted === 'stop'\n ? { kind: 'budget-exhausted', budget: 'time', forcedFinalAnswer: false }\n : await forceAnswer('time', false)\n break\n }\n // Auto has no step countdown. Warn from the same usage total as admission,\n // before a hard token stop can leave the agent without a reporting call.\n const usedTokens = budgetTokenTotal(summarizeModelCallUsage(modelCallReports))\n if (bounds.maxTotalTokens !== 'auto' && usedTokens !== undefined) {\n const crossed = [0.5, 0.75, 0.9].filter(ratio => usedTokens >= maxTotalTokens * ratio).length\n if (crossed > tokenRemindersSent) {\n tokenRemindersSent = crossed\n const remaining = Math.max(0, maxTotalTokens - usedTokens)\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'tool-loop-token-guard' },\n content: [{ type: 'text', text: `Token budget: ${remaining} of ${bounds.maxTotalTokens} aggregate tokens remain. Each request also spends input tokens on the accumulated context. `\n + (crossed >= 2 ? 'Stop broad exploration. ' : 'Prioritize outstanding verification and reporting. ')\n + 'Reserve capacity for the required self-check, honest todo reconciliation and substantive final report. State unavailable evidence and unfinished work; do not claim it is verified. No extra model call is allowed after the hard token limit.',\n }],\n }) })\n }\n }\n // Leave time to reconcile a plan and submit a result before the final\n // tools-disabled summary. Tool-call reminders do not cover step limits.\n if (!stepReminderSent && finalizeUntil === undefined && workSteps() > 0 && maxSteps - workSteps() <= 2) {\n stepReminderSent = true\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'tool-loop-step-guard' },\n content: [{ type: 'text', text:\n `${maxSteps - workSteps()} work steps remain. Finish essential verification, update any task list honestly, and submit the result if required. Summarize findings, evidence, and unfinished work; do not start new exploration.`,\n }],\n }) })\n }\n // Recomputed before the request that will read it, so a section reacting to\n // the previous step's tool calls is already on the surface.\n if (contextSections !== undefined) {\n await contextSections.reconcile(steps, contextTouches, signal)\n contextTouches = []\n }\n const step = steps + 1\n const round = await modelRound(\n options, signal, emit, emitMaintenance, root, turn, step,\n dedicatedFinalOutput\n ? 'process'\n : options.outputFormat?.type === 'json_schema' ? 'final' : 'standard',\n position(),\n )\n steps++\n if (round.report !== undefined) modelCallReports.push(round.report)\n usageStop = accountingUsageStop(options.accounting) ?? (round.usageRequired\n ? { kind: 'error', failure: { message: 'provider usage is required by the configured run policy', code: 'USAGE_REQUIRED' } }\n : round.usageUnavailable\n ? { kind: 'usage-unavailable', modelCallId: round.report?.modelCallId ?? 'unknown' }\n : undefined)\n const commitRound = async (): Promise<void> => {\n if (round.message !== undefined) {\n options.history.append({\n kind: 'assistant', message: round.message,\n ...round.finish.kind === 'aborted' ? { interrupted: true as const } : {},\n ...round.usage === undefined ? {} : { usage: round.usage },\n })\n await emit({ type: 'assistant-message', message: round.message, trace: round.trace })\n await emitAssistantContent(round, emit)\n // A failed or interrupted round that only began thinking has said\n // nothing new; it must not erase the text an earlier round produced.\n const roundText = textOf(round.message.content)\n if (roundText.trim() !== '' || (round.finish.kind !== 'error' && round.finish.kind !== 'aborted')) text = roundText\n } else if (round.finish.kind === 'stop') {\n // A successful empty round cannot answer new input with earlier text.\n // Keep earlier text only when a later request fails or is interrupted.\n text = ''\n }\n }\n // A failed request the retry hook may repeat is held back: kept in history,\n // its half-written text and cut-off call arguments would be continued from\n // (an answer missing its beginning) or rejected by the provider. It is\n // committed only if the turn ends on it.\n const retryCandidate = round.finish.kind === 'error' && !round.usageRequired\n && usageStop === undefined && !signal.aborted\n if (!retryCandidate) await commitRound()\n if (signal.aborted || round.finish.kind === 'aborted') { reason = { kind: 'aborted' }; break }\n // Pair emitted tool calls with declined results even when policy stops the\n // run; never execute those calls or allow a retry hook to override policy.\n if (round.finish.kind === 'error' && usageStop !== undefined) {\n reason = { kind: 'error', failure: round.finish.failure }\n break\n }\n if (round.usageRequired && (round.calls.length === 0 || options.tools === undefined)) { reason = usageStop; break }\n if (round.finish.kind === 'error' && !round.usageRequired) {\n reason = admissionStop()\n if (reason !== undefined) { await commitRound(); break }\n const decision = await runOptionalHook(options.hooks?.onRequestError, [{\n turn, step, failure: round.finish.failure, snapshot: options.history.snapshot(), signal,\n ...(options.logger === undefined ? {} : { logger: options.logger }),\n emit: emitMaintenance,\n }], options, signal, 'onRequestError')\n // A hook waiting out a backoff when the person aborts throws the abort;\n // that is a cancelled turn, not a crashed one.\n .catch((error: unknown) => { if (signal.aborted) return 'fail' as const; throw error })\n const maintenanceStop = accountingUsageStop(options.accounting)\n if (maintenanceStop !== undefined) { await commitRound(); reason = signal.aborted ? { kind: 'aborted' } : maintenanceStop; break }\n if (decision === 'retry' && !signal.aborted) {\n if (retriedRounds < MAX_FREE_REQUEST_RETRIES) retriedRounds++\n if (workSteps() < (finalizeUntil ?? maxSteps)) continue\n }\n await commitRound()\n reason = signal.aborted ? { kind: 'aborted' } : { kind: 'error', failure: round.finish.failure }\n break\n }\n if (round.finish.kind === 'max-tokens' && !round.usageRequired) { reason = { kind: 'max-tokens' }; break }\n if (round.calls.length === 0 && round.usageUnavailable) {\n reason = accountingUsageStop(options.accounting) ?? { kind: 'usage-unavailable', modelCallId: round.report?.modelCallId ?? 'unknown' }\n break\n }\n if (round.calls.length === 0 && dedicatedFinalOutput) {\n reason = admissionStop()\n if (reason !== undefined) break\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'structured-output-finalizer' },\n content: [{\n type: 'text',\n text: 'The process phase is complete. Return the final answer now in the requested output format. Do not call tools.',\n }],\n }) })\n const final = await retryFinalRound(await modelRound(\n options, signal, emit, emitMaintenance, root, turn, steps + 1, 'final', position(),\n ), 'final')\n steps++\n if (final.report !== undefined) modelCallReports.push(final.report)\n if (final.message !== undefined) {\n options.history.append({\n kind: 'assistant', message: final.message,\n ...final.usage === undefined ? {} : { usage: final.usage },\n })\n await emit({ type: 'assistant-message', message: final.message, trace: final.trace })\n await emitAssistantContent(final, emit)\n text = textOf(final.message.content)\n }\n if (signal.aborted || final.finish.kind === 'aborted') reason = { kind: 'aborted' }\n else if (final.finish.kind === 'error') reason = { kind: 'error', failure: final.finish.failure }\n else if (final.finish.kind === 'max-tokens') reason = { kind: 'max-tokens' }\n else if (final.usageRequired) reason = { kind: 'error', failure: {\n message: 'provider usage is required by the configured run policy',\n code: 'USAGE_REQUIRED',\n } }\n else if (final.usageUnavailable) {\n reason = accountingUsageStop(options.accounting) ?? { kind: 'usage-unavailable', modelCallId: final.report?.modelCallId ?? 'unknown' }\n } else reason = { kind: 'completed' }\n break\n }\n // A provider that repeated an id had the repeat dropped. Saying so is what\n // keeps the model from reading one result for two calls as a tool that\n // silently ignored it.\n if (round.droppedDuplicateCalls !== undefined) {\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'tool-loop-duplicate-guard' },\n content: [{\n type: 'text',\n text: `You reused the tool-call id ${round.droppedDuplicateCalls.map(id => `'${id}'`).join(', ')}.`\n + ' A result pairs to exactly one call, so the repeat was not run and only the first'\n + ' call of that id has a result. Give every call its own id, and call again if you'\n + ' still need what the dropped one would have done.',\n }],\n }) })\n }\n if (round.calls.length === 0 || options.tools === undefined) { reason = { kind: 'completed' }; break }\n\n // Calls the budget does not govern: submitting, asking, delegating. They\n // are dispatched even when the budget is spent, so the model always has a\n // legal way to finish. See `ToolDefinition.budgetExempt`.\n const remaining = Math.max(0, bounds.maxToolCalls - toolCalls)\n let repeatProjection: { key: string; count: number } | undefined = lastRepeat\n const projectedRepeats = round.calls.map(call => {\n const key = repeatKey(call)\n // Count consecutive calls, not lifetime visits to a source or test command.\n // Distinct intervening work may change its result. Alternating loops are\n // handled separately by the step-cycle guard below.\n const count = repeatProjection?.key === key ? repeatProjection.count + 1 : 1\n repeatProjection = { key, count }\n return count\n })\n const repeatedLimitBeforeDispatch = projectedRepeats.some(count => count >= bounds.repeatToolLimit)\n const actionPattern = toolActionPattern(round.calls)\n const projectedCycle = repeatedSuffixCycle(\n [...actionSteps, actionPattern],\n bounds.maxToolCycleLength,\n )\n const cycleLimitBeforeDispatch = projectedCycle !== undefined\n && projectedCycle.repetitions >= bounds.toolCycleLimit\n const currentUsage = summarizeModelCallUsage(modelCallReports)\n const budgetTokens = budgetTokenTotal(currentUsage)\n const tokenLimitBeforeDispatch = budgetTokens !== undefined\n && budgetTokens >= maxTotalTokens\n // A model round that ran past the time budget does not start new work.\n const timeLimitBeforeDispatch = finalizeUntil === undefined && timeSpent() >= maxTurnDurationMs\n const guardDeclined = cycleLimitBeforeDispatch || tokenLimitBeforeDispatch || round.usageRequired\n || finalizeUntil !== undefined || timeLimitBeforeDispatch\n // Name the limit that actually declined the call. Reporting a repeat guard\n // as an empty budget teaches the model the wrong lesson, and it repeats the\n // call on the next turn with the budget it was told it lacked.\n const declineReason: ToolDeclineReason = finalizeReason !== undefined && !tokenLimitBeforeDispatch\n ? finalizeReason\n : tokenLimitBeforeDispatch\n ? 'tokens'\n : timeLimitBeforeDispatch\n ? 'time'\n : cycleLimitBeforeDispatch\n ? 'tool-call-cycle'\n : round.usageRequired\n ? 'usage-required'\n : 'tool-calls'\n // `continue` takes the wall down: the budget becomes a notice and the turn\n // is bounded by steps, tokens, and the run-level ledger instead. Guards\n // that mean \"this is not working\" still decline, whatever the setting.\n const budgetIsAWall = bounds.onExhausted !== 'continue'\n const recoveredCallIds = new Set<string>()\n // A round-wide guard must not make an unrelated old success reusable.\n // Recovery is only legal for a call that individually reached the limit and\n // whose successful result is the immediately preceding call in this streak.\n const individuallyRepeatedCallIds = new Set(round.calls\n .filter((_call, index) => (projectedRepeats[index] ?? 0) >= bounds.repeatToolLimit)\n .map(call => String(call.callId)))\n // Only ordinary dispatches request quota: repeated calls are either recovered\n // for free or individually declined. Fresh siblings keep normal admission.\n const budgetedCalls = round.calls.filter(call =>\n !individuallyRepeatedCallIds.has(String(call.callId))\n && options.tools?.get(call.toolName)?.budgetExempt !== true).length\n const recover = repeatedLimitBeforeDispatch && !cycleLimitBeforeDispatch && !tokenLimitBeforeDispatch\n && !round.usageRequired\n ? (call: typeof round.calls[number]): ToolExecutionResult | undefined => {\n const prior = successfulCalls.get(repeatKey(call))\n if (!individuallyRepeatedCallIds.has(String(call.callId))\n || lastRepeat?.key !== repeatKey(call)\n || lastRepeat.succeeded !== true\n || prior === undefined\n || prior.callId !== lastRepeat.callId\n || prior.rawArguments !== call.rawArguments\n || prior.definition !== options.tools?.get(call.toolName)\n || prior.result.additionalContext !== undefined\n || prior.result.concludesTurn === true\n || options.tools?.get(call.toolName)?.budgetExempt === true) return undefined\n recoveredCallIds.add(String(call.callId))\n return duplicateOfResult(prior)\n }\n : undefined\n const scheduled = await scheduleToolCalls({\n calls: round.calls, catalog: options.tools, history: options.history,\n position: { turn, step,\n ...(options.accounting === undefined ? {} : { runId: options.accounting.runId }),\n ...(options.trace?.conversationId === undefined ? {} : { conversationId: options.trace.conversationId }),\n }, signal, parentTrace: root,\n maxParallel: bounds.maxParallel,\n dispatchLimit: guardDeclined ? 0 : budgetIsAWall ? remaining : round.calls.length,\n declineReason,\n maxResultBytes: bounds.maxToolResultBytes,\n maxResultTokens: bounds.maxToolResultTokens,\n resultOverflow: bounds.toolResultOverflow,\n ...options.spillStore === undefined ? {} : { spillStore: options.spillStore },\n maxDurationMs: bounds.maxToolDurationMs,\n teardownTimeoutMs: bounds.toolTeardownTimeoutMs,\n ...(options.logger === undefined ? {} : { logger: options.logger }),\n ...options.interceptors === undefined ? {} : { interceptors: options.interceptors },\n ...options.approvals === undefined ? {} : { approvals: options.approvals },\n ...options.accounting === undefined ? {} : { accounting: options.accounting },\n emit,\n ...recover === undefined ? {} : { recover },\n ...options.hooks?.checkpoint === undefined ? {} : {\n checkpoint: (context: Parameters<NonNullable<TurnHooks['checkpoint']>>[0]) => runHook(\n Promise.resolve(options.hooks?.checkpoint?.(context)), options, signal, 'checkpoint',\n ),\n },\n }, {\n onToolActivity: toolActivity,\n admissionLimit: guardDeclined ? 0 : budgetIsAWall ? remaining : 'unbounded',\n // In the finalize window even an always-reachable tool (asking a person,\n // messaging a teammate) would start work the spent budget cannot finish.\n ...finalizeUntil === undefined ? {} : {\n restrict: (call: typeof round.calls[number]): ToolDeclineReason | undefined =>\n finalizeTools.has(call.toolName) ? undefined : finalizeReason ?? 'steps',\n },\n ...guardDeclined || !repeatedLimitBeforeDispatch ? {} : {\n decline: (call: typeof round.calls[number]): ToolDeclineReason | undefined =>\n individuallyRepeatedCallIds.has(String(call.callId)) ? 'repeated-tool-call' : undefined,\n },\n ...programs === undefined ? {} : { programs },\n ...programResults === undefined ? {} : { programResults },\n })\n // Results commit in model order, one per requested call, so the pairing\n // holds for declined calls too. A short result list means a sibling failed\n // its contract and the turn is already unwinding; reporting a guessed\n // outcome would be worse than reporting nothing.\n if (contextSections !== undefined && scheduled.results.length === round.calls.length) {\n contextTouches.push(...round.calls.map((call, index) => ({\n toolName: call.toolName,\n rawArguments: call.rawArguments,\n failed: scheduled.results[index]?.isError ?? true,\n })))\n }\n toolCalls += scheduled.budgeted\n const remainingAfterDispatch = Math.max(0, bounds.maxToolCalls - toolCalls)\n // One reminder per threshold crossed, not one per turn.\n //\n // This was a single boolean: the model was told once, at 25% remaining,\n // and then never again however close it came to the end. A model warned at\n // sixteen calls left and still exploring at four has been told nothing\n // since, and runs into the wall with no notice — which is what produces a\n // red \"no remaining tool-call budget\" where an answer should have been.\n //\n // Codex counts thresholds rather than remembering a flag\n // (`rollout_budget.rs`, `reminder_index`): every threshold now below the\n // remaining budget that has not been reported yet gets reported. Crossing\n // several at once collapses into the one that matters, the lowest.\n const crossed = budgetReminders.filter(threshold => remainingAfterDispatch <= threshold).length\n if (crossed > budgetRemindersSent && remainingAfterDispatch > 0) {\n budgetRemindersSent = crossed\n appendBudgetNotice(\n `Tool budget: ${remainingAfterDispatch} of ${bounds.maxToolCalls} calls remain in this turn.`\n + ' Stop broad exploration, make the necessary edits, and reserve calls for'\n + (budgetIsAWall\n ? ' verification. When the budget runs out no further work call will run, so'\n + ' finish with what you can still verify.'\n : ' verification. Past the budget you are expected to be wrapping up, not'\n + ' opening new lines of work.'),\n )\n }\n // Past the budget with the wall down. The turn is not stopped — the model\n // keeps its tools — but it is told, once per further budget spent, that it\n // is now expected to be finishing. This is the shape of Codex's\n // `budget_limit` goal prompt: no new substantive work, wrap up, name what\n // is left.\n if (!budgetIsAWall && remainingAfterDispatch === 0) {\n const windows = Math.floor(toolCalls / bounds.maxToolCalls)\n if (windows > overBudgetNoticesSent) {\n overBudgetNoticesSent = windows\n appendBudgetNotice(\n `Tool budget spent: ${toolCalls} calls made against a budget of ${bounds.maxToolCalls}.`\n + ' Do not start new substantive work. Finish what is in flight, verify what you'\n + ' can, and answer — stating plainly what is unverified or unfinished.',\n )\n }\n }\n await emit({ type: 'step-end', turn, step, trace: round.trace })\n\n actionSteps.push(actionPattern)\n let repeatedLimit = repeatedLimitBeforeDispatch\n for (let index = 0; index < round.calls.length; index++) {\n const call = round.calls[index]\n const result = scheduled.results[index]\n if (call === undefined || result === undefined) continue\n consecutiveErrors = result.isError ? consecutiveErrors + 1 : 0\n const key = repeatKey(call)\n const count = lastRepeat?.key === key ? lastRepeat.count + 1 : 1\n lastRepeat = {\n key, count, callId: String(call.callId),\n succeeded: !result.isError && result.meta?.declined !== true\n && options.tools?.get(call.toolName)?.budgetExempt !== true,\n }\n if (count === bounds.repeatToolWarningAt) {\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'tool-loop-repeat-guard' },\n content: [{ type: 'text', text: `You have called ${call.toolName} with the same arguments ${count} consecutive times. Reassess before repeating it.` }],\n }) })\n }\n if (count >= bounds.repeatToolLimit) repeatedLimit = true\n if (!result.isError && result.meta?.declined !== true\n && options.tools?.get(call.toolName)?.budgetExempt !== true) {\n successfulCalls.set(key, {\n callId: String(call.callId), rawArguments: call.rawArguments,\n definition: options.tools.get(call.toolName), result,\n })\n }\n }\n if (projectedCycle?.repetitions === bounds.toolCycleWarningAt) {\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'tool-loop-cycle-guard' },\n content: [{\n type: 'text',\n text: `Tool-use pattern repeated ${projectedCycle.repetitions} times across ${projectedCycle.period} step(s). Reassess the approach and identify concrete new evidence before continuing.`,\n }],\n }) })\n }\n if (scheduled.concluded) { reason = { kind: 'concluded-by-tool', toolName: scheduled.concludedBy ?? 'unknown' }; break }\n if (signal.aborted) { reason = { kind: 'aborted' }; break }\n if (round.usageRequired) { reason = usageStop; break }\n if (round.usageUnavailable) {\n reason = accountingUsageStop(options.accounting) ?? { kind: 'usage-unavailable', modelCallId: round.report?.modelCallId ?? 'unknown' }\n break\n }\n let exhausted: ExhaustedBudget | undefined\n const reportReserveReached = bounds.maxTotalTokens !== 'auto'\n && bounds.finalReportReserveTokens > 0 && budgetTokens !== undefined\n && budgetTokens >= maxTotalTokens - bounds.finalReportReserveTokens\n const recoveredOnlyReplan = repeatedLimitBeforeDispatch\n && recoveredCallIds.size === round.calls.length\n && round.calls.every(call => recoveredCallIds.has(String(call.callId))\n && !recoveredReplanKeys.has(repeatKey(call)))\n && scheduled.results.length === round.calls.length\n && scheduled.results.every(result => !result.isError)\n && scheduled.dispatched === 0 && scheduled.declined === 0\n && !cycleLimitBeforeDispatch && !tokenLimitBeforeDispatch && !reportReserveReached\n && !round.usageRequired && !round.usageUnavailable && !signal.aborted\n && !(budgetIsAWall && budgetedCalls > remaining)\n && consecutiveErrors === 0 && workSteps() < maxSteps\n && bounds.onExhausted !== 'stop' && admissionStop() === undefined\n // A repeated call cannot poison new work in the same model batch. Successful\n // recovery alongside a real dispatch is ordinary progress, not an extra pure\n // duplicate replan. The other exhaustion checks below still apply.\n const recoveredWithFreshDispatch = repeatedLimitBeforeDispatch\n && [...individuallyRepeatedCallIds].every(id => recoveredCallIds.has(id))\n && scheduled.results.length === round.calls.length\n && scheduled.dispatched > 0 && scheduled.declined === 0\n if (recoveredOnlyReplan) {\n for (const call of round.calls) recoveredReplanKeys.add(repeatKey(call))\n } else if (tokenLimitBeforeDispatch) exhausted = 'tokens'\n else if (reportReserveReached) exhausted = 'tokens'\n else if (cycleLimitBeforeDispatch) exhausted = 'tool-call-cycle'\n else if (budgetIsAWall && budgetedCalls > remaining) exhausted = 'tool-calls'\n else if (consecutiveErrors >= bounds.maxConsecutiveToolErrors) exhausted = 'consecutive-tool-errors'\n else if (repeatedLimit && !recoveredWithFreshDispatch) exhausted = 'repeated-tool-call'\n else if (workSteps() >= maxSteps) exhausted = 'steps'\n // The finalize window has its own end; only the hard token wall stops it early.\n if (finalizeUntil !== undefined) exhausted = tokenLimitBeforeDispatch ? 'tokens' : undefined\n if (exhausted === undefined && recoveredWithFreshDispatch) {\n for (const call of round.calls) {\n if (recoveredCallIds.has(String(call.callId))) recoveredReplanKeys.add(repeatKey(call))\n }\n }\n // Time is checked at every step boundary, not only after tool work.\n if (exhausted === undefined && finalizeUntil === undefined && timeSpent() >= maxTurnDurationMs) exhausted = 'time'\n if (exhausted !== undefined) {\n const forced = (exhausted !== 'tokens' || (reportReserveReached && !tokenLimitBeforeDispatch))\n && bounds.onExhausted !== 'stop'\n && admissionStop() === undefined\n reason = forced\n ? await forceAnswer(exhausted, exhausted === 'tokens' && reportReserveReached && !tokenLimitBeforeDispatch)\n : { kind: 'budget-exhausted', budget: exhausted, forcedFinalAnswer: false,\n ...(exhausted === 'tokens' && reportReserveReached && !tokenLimitBeforeDispatch ? { trigger: 'report-reserve' as const } : {}) }\n }\n }\n\n // The window is for an answer written with no step left to confirm it:\n // either forced by a budget, or written freely on the last work step. Input\n // a person sent meanwhile is not answered in a tool-less window; the turn\n // ends instead and that input gets a turn of its own.\n const finalizable = reason?.kind === 'budget-exhausted'\n ? reason.forcedFinalAnswer\n : reason?.kind === 'completed' && workSteps() >= maxSteps\n if (finalizeUntil === undefined && options.finalize !== undefined && bounds.finalizeSteps > 0\n && (reason?.kind === 'budget-exhausted' || reason?.kind === 'completed') && finalizable\n && text.trim() !== '' && !signal.aborted && admissionStop() === undefined\n && !hasQueuedInput(options.history)) {\n const prompt = options.finalize.prompt({ text, reason })\n if (prompt !== undefined) {\n options.history.append({ kind: 'user', message: prompt })\n finalizeOrigin = reason\n finalizeReason = reason.kind === 'budget-exhausted' ? reason.budget : 'steps'\n forcedText = text\n forcedMessage = options.history.messages().findLast(message => message.role === 'assistant')\n finalizeUntil = workSteps() + bounds.finalizeSteps\n reason = undefined\n continue turnLifecycle\n }\n }\n if (reason === undefined) {\n reason = signal.aborted\n ? { kind: 'aborted' }\n : { kind: 'budget-exhausted', budget: 'steps', forcedFinalAnswer: false }\n }\n // Confirming a forced answer does not un-spend the budget, and a failed or\n // cut-short confirmation does not cost the answer: the turn ends with the\n // stop that opened the window, and with the forced answer unless the window\n // itself ended on a new one. A person's abort stays an abort.\n if (finalizeOrigin !== undefined) {\n const confirmedAnswer = reason.kind === 'completed' && text.trim() !== '' && options.finalize?.confirmed() === true\n if (!confirmedAnswer) {\n text = forcedText\n // The kept answer must also be the last thing said, or the session's\n // message, the stream and a reload would show the window's note instead.\n const last = options.history.messages().findLast(message => message.role === 'assistant')\n if (forcedMessage !== undefined && last?.id !== forcedMessage.id) {\n const restored = createMessage({ role: 'assistant', content: forcedMessage.content, source: forcedMessage.source })\n options.history.append({ kind: 'assistant', message: restored })\n await emit({ type: 'assistant-message', message: restored, trace: root })\n }\n }\n if (reason.kind !== 'aborted') reason = finalizeOrigin\n }\n const usageReport = summarizeModelCallUsage(modelCallReports)\n const usage = authoritativeTokenUsage(usageReport)\n const candidate: TurnOutcome = {\n reason, text, steps, usageReport, toolCalls, traceId,\n ...usage === undefined ? {} : { usage },\n }\n const entriesBeforeHook = options.history.entries().length\n const canContinue = reason.kind === 'completed'\n && workSteps() < maxSteps\n && admissionStop() === undefined\n await runOptionalHook(options.hooks?.onTurnEnd, [{\n outcome: candidate,\n snapshot: options.history.snapshot(),\n canContinue,\n }], options, signal.aborted ? new AbortController().signal : signal, 'onTurnEnd')\n // Hooks object by appending context rather than by returning a veto. Re-run only\n // a normally completed turn; abort/error/budget outcomes remain terminal.\n // Input the person sent while the final answer was being written is owed an\n // answer too: when nothing else continues the turn, take it and continue.\n if (canContinue\n && !signal.aborted\n && (options.history.entries().length > entriesBeforeHook || deliverQueuedInput(options.history))) {\n reason = undefined\n continue turnLifecycle\n }\n outcome = candidate\n break\n }\n if (outcome.reason.kind === 'aborted') {\n // Without this, the next turn sees an unfinished request and a cancelled\n // tool call, and a model resumes the abandoned work instead of answering\n // the new message (observed live). Codex and Claude Code record the same\n // interruption marker.\n options.history.append({ kind: 'user', message: createUserMessage({\n source: { kind: 'app', producer: 'turn-interrupted' },\n content: [{ type: 'text', text: 'The previous request was interrupted before it finished. Use the next message to determine what to do next.' }],\n }) })\n }\n await emit({\n type: 'span-end', trace: root, at: now(),\n status: outcome.reason.kind === 'error' ? 'error' : outcome.reason.kind === 'aborted' ? 'aborted' : 'success',\n output: { reason: outcome.reason, text },\n ...outcome.usage === undefined ? {} : { usage: outcome.usage },\n ...outcome.reason.kind === 'error' ? { error: { type: 'ModelError', message: outcome.reason.failure.message, code: outcome.reason.failure.code } } : {},\n })\n rootEnded = true\n if (turnOperationId !== undefined) {\n options.accounting?.endOperation(\n turnOperationId,\n outcome.reason.kind === 'error' ? 'error' : outcome.reason.kind === 'aborted' ? 'aborted' : 'success',\n { data: { reason: outcome.reason.kind, steps, toolCalls } },\n )\n turnOperationEnded = true\n }\n await emit({ type: 'turn-end', outcome, trace: root })\n } catch (error: unknown) {\n const code = errorCodeOf(error)\n if (rootStarted && !rootEnded) {\n await emit({\n type: 'span-end', trace: root, at: now(), status: signal.aborted ? 'aborted' : 'error',\n error: {\n type: error instanceof Error ? error.name : 'RuntimeError',\n message: messageOf(error),\n ...code === undefined ? {} : { code },\n },\n }).catch(() => undefined)\n }\n if (turnOperationId !== undefined && !turnOperationEnded) {\n options.accounting?.endOperation(\n turnOperationId,\n signal.aborted ? 'aborted' : 'error',\n { error },\n )\n turnOperationEnded = true\n }\n throw error\n } finally {\n programResults?.close()\n }\n}\n\nfunction duplicateOfResult(prior: {\n readonly callId: string\n readonly result: Extract<ToolExecutionResult, { readonly isError: false }>\n}): ToolExecutionResult {\n return detachedFrozen({\n isError: false,\n // The prior structured value remains the host's canonical result. The\n // header is model-visible so it knows this call was intentionally reused.\n value: prior.result.value,\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n status: 'duplicate_of',\n callId: prior.callId,\n instruction: 'This exact call already succeeded in this run. Use the retained result below; do not call it again.',\n }),\n },\n ...prior.result.content,\n ],\n meta: { ...prior.result.meta, recovered: true, duplicateOfCallId: prior.callId },\n })\n}\n\nexport type { RunTurnOptions } from './turn/types.ts'\n"],"mappings":"ozCAwBA,SAAS,GAAiB,EAAkC,CAE1D,OADI,EAAQ,aAAe,OAAe,IAClC,EAAQ,OAAO,MAAM,CAAC,CAAC,QAAU,GAAK,IAAM,EAAQ,aAAa,QAAU,GAAK,CAC1F,CAGA,SAAgB,EAAQ,EAAoD,CAC1E,MAAO,CACL,OAAS,OAAO,gBAAiB,CAC/B,IAAM,EAAa,EAAuB,CAAO,EAC3C,EAAQ,IAAI,EACZ,EAAW,IAAI,gBACf,EAAoB,EAAe,EAAW,mBAAqB,IAAQ,mBAAmB,EAI9F,EAAO,EAAU,EAHR,EAAW,SAAW,IAAA,GACjC,EAAS,OACT,YAAY,IAAI,CAAC,EAAW,OAAQ,EAAS,MAAM,CAAC,EACb,GAAS,EAAM,KAAK,EAAe,CAAK,CAAC,CAAC,CAAC,CACnF,SAAW,EAAM,MAAM,EAAG,GAAS,EAAM,KAAK,CAAK,CAAC,EACvD,GAAI,CACF,OAAa,CACX,IAAM,EAAO,MAAM,EAAM,KAAK,EAC9B,GAAI,EAAK,KAAM,MACf,MAAM,EAAK,KACb,CACA,MAAM,CACR,QAAU,CAGR,GAFA,EAAS,MAAU,MAAM,6BAA6B,CAAC,EACvD,EAAM,MAAM,EACR,CAAC,MAAM,EAAkB,EAAM,CAAiB,EAClD,MAAM,EACJ,oDAAoD,EAAkB,IACtE,wBACA,EAAS,OAAO,MAClB,CAEJ,CACF,CACF,CACF,CAKA,eAAe,EACb,EACA,EACA,EACe,CACf,IAAM,EAAS,EAAc,EAAQ,MAAM,EACrC,EAAiB,EAAO,iBAAmB,OAAS,IAAW,EAAO,eAGtE,EAAW,EAAO,WAAa,OAAS,IAAW,EAAO,SAC1D,EAAU,EAAQ,OAAO,SAAW,EAAc,EAClD,EAAiB,CAAE,UAAS,OAAQ,EAAa,EAAG,aAAc,EAAQ,OAAO,cAAgB,IAAK,EACtG,EAAO,KAAK,IAAI,EAAG,EAAQ,QAAQ,QAAQ,CAAC,CAAC,OAAO,GACxD,EAAM,MAAM,OAAS,QAAU,EAAM,MAAM,QAAQ,OAAO,OAAS,MAAM,CAAC,CAAC,MAAM,EAC7E,GAAY,EAAI,EAClB,EAAQ,EAOR,EAAgB,EACd,MAA0B,EAAQ,EAClC,OAAkB,CAAE,SAAU,EAAU,EAAI,EAAG,WAAY,IAAkB,IAAA,EAAU,GAGvF,GAAoB,EAAO,oBAAsB,OAAS,IAAW,EAAO,kBAC5E,EAAgB,KAAK,IAAI,EAC3B,EAAe,EACf,EACA,EAAc,EACd,EAAY,EACV,IAAgB,EAAuB,IAA0B,CACrE,IAAM,EAAK,KAAK,IAAI,EAChB,IAAiB,IAAA,KAAW,GAAgB,EAAK,GACjD,EAAc,GAAe,EAAS,EAAI,GACzC,GAAa,EAAS,EAAI,GAE/B,EAAe,EAAc,GAAK,IAAc,EAAI,EAAK,IAAA,EAC3D,EACM,OAA0B,CAC9B,IAAM,EAAK,KAAK,IAAI,EACpB,OAAO,EAAK,EAAgB,GAAgB,IAAiB,IAAA,GAAY,EAAI,EAAK,EACpF,EAOM,GAAc,MAClB,EACA,IACmC,CACnC,IAAI,EAAQ,MAAM,GAAgB,MAAM,EACtC,EAAS,EAAQ,EAAM,EAAiB,EAAM,EAAM,EAAQ,EAAG,eAAgB,EAAS,CAC1F,EAAG,cAAc,EA8CjB,OA5CoB,GAAwB,CAAC,EAAM,eAAiB,CAAC,EAAM,mBACpE,EAAM,OAAO,OAAS,QAAU,EAAO,EAAM,SAAS,SAAW,CAAC,CAAC,CAAC,CAAC,KAAK,IAAM,IAC/E,EAAM,OAAO,OAAS,SAAW,EAAM,OAAO,QAAQ,OAAS,qBACnE,CAAW,CAAK,GAAK,CAAC,EAAO,SAAW,EAAgB,GACvD,EAAc,EAAM,MAAM,IAAM,IAAA,KAC/B,EAAM,SAAW,IAAA,IAAW,EAAiB,KAAK,EAAM,MAAM,EAC9D,EAAM,UAAY,IAAA,IACpB,EAAQ,QAAQ,OAAO,CAAE,KAAM,YAAa,QAAS,EAAM,QAAS,GAAG,EAAM,QAAU,IAAA,GAAY,CAAC,EAAI,CAAE,MAAO,EAAM,KAAM,CAAE,CAAC,EAElI,EAAQ,QAAQ,OAAO,CAAE,KAAM,OAAQ,QAAS,EAAkB,CAChE,OAAQ,CAAE,KAAM,MAAO,SAAU,qBAAsB,EACvD,QAAS,CAAC,CAAE,KAAM,OAAQ,KAAM,mLAAoL,CAAC,CACvN,CAAC,CAAE,CAAC,EACJ,IACA,IACA,EAAQ,MAAM,EAAW,EAAS,EAAQ,EAAM,EAAiB,EAAM,EAAM,EAAQ,EAAG,eAAgB,EAAS,CAAC,GAEpH,IACI,EAAM,SAAW,IAAA,IAAW,EAAiB,KAAK,EAAM,MAAM,EAC9D,EAAM,UAAY,IAAA,GAOpB,EAAO,IANP,EAAQ,QAAQ,OAAO,CAAE,KAAM,YAAa,QAAS,EAAM,QAAS,GAAG,EAAM,QAAU,IAAA,GAAY,CAAC,EAAI,CAAE,MAAO,EAAM,KAAM,CAAE,CAAC,EAChI,MAAM,EAAK,CAAE,KAAM,oBAAqB,QAAS,EAAM,QAAS,MAAO,EAAM,KAAM,CAAC,EACpF,MAAM,GAAqB,EAAO,CAAI,EACtC,EAAO,EAAO,EAAM,QAAQ,OAAO,GAKjC,EAAO,SAAW,EAAM,OAAO,OAAS,UAAkB,CAAE,KAAM,SAAU,EAG5E,EAAM,OAAO,OAAS,SAAW,EAAM,OAAO,QAAQ,OAAS,qBACjE,EAAO,GACA,CAAE,KAAM,mBAAoB,OAAQ,EAAW,kBAAmB,GACvE,GAAI,EAAiB,CAAE,QAAS,gBAA0B,EAAI,CAAC,CAAG,GAElE,EAAM,OAAO,OAAS,QAAgB,CAAE,KAAM,QAAS,QAAS,EAAM,OAAO,OAAQ,EACrF,EAAM,OAAO,OAAS,aAAqB,CAAE,KAAM,YAAa,EAChE,EAAM,cACD,CAAE,KAAM,QAAS,QAAS,CAAE,QAAS,0DAA2D,KAAM,gBAAiB,CAAE,EAE9H,EAAM,iBACD,EAAoB,EAAQ,UAAU,GAAK,CAAE,KAAM,oBAAqB,YAAa,EAAM,QAAQ,aAAe,SAAU,EAE9H,CAAE,KAAM,mBAAoB,OAAQ,EAAW,kBAAmB,EAAK,KAAK,IAAM,GACvF,GAAI,EAAiB,CAAE,QAAS,gBAA0B,EAAI,CAAC,CAAG,CACtE,EAOM,GAAkB,MACtB,EACA,IACoD,CACpD,IAAI,EAAQ,EACZ,KAAO,EAAM,OAAO,OAAS,SAAW,CAAC,EAAM,eAAiB,CAAC,EAAO,SACnE,CAAC,EAAM,kBAAoB,EAAgB,GAC3C,EAAc,EAAM,MAAM,IAAM,IAAA,IAS/B,MARmB,GAAgB,EAAQ,OAAO,eAAgB,CAAC,CACrE,OAAM,KAAM,EAAQ,EAAG,QAAS,EAAM,OAAO,QAAS,SAAU,EAAQ,QAAQ,SAAS,EAAG,SAC5F,GAAI,EAAQ,SAAW,IAAA,GAAY,CAAC,EAAI,CAAE,OAAQ,EAAQ,MAAO,EACjE,KAAM,CACR,CAAC,EAAG,EAAS,EAAQ,gBAAgB,CAAC,CAGnC,MAAO,GAAmB,CAAE,GAAI,EAAO,QAAS,MAAO,OAAiB,MAAM,CAAM,CAAC,IACvE,SAAW,EAAc,EAAM,MAAM,IAAM,IAAA,IACxD,EAAM,SAAW,IAAA,IAAW,EAAiB,KAAK,EAAM,MAAM,EAElE,IACA,IACA,EAAQ,MAAM,EAAW,EAAS,EAAQ,EAAM,EAAiB,EAAM,EAAM,EAAQ,EAAG,EAAO,EAAS,CAAC,EAE3G,OAAO,CACT,EACI,EAAY,EAEV,GAAkB,CAAC,GAAG,EAAO,kBAAkB,CAAC,CACnD,OAAO,GAAa,EAAY,GAAK,EAAY,EAAO,YAAY,CAAC,CACrE,MAAM,EAAM,IAAU,EAAQ,CAAI,EACjC,GAAsB,EAEtB,GAAwB,EAExB,EACA,GAAmB,GAKnB,EACA,EAEA,EACA,EAAa,GACb,EACE,GAAgB,IAAI,IAAI,EAAQ,UAAU,OAAS,CAAC,CAAC,EACvD,GAAqB,EACrB,EAAoB,EACpB,EAAO,GACL,EAAsC,CAAC,EACzC,EACA,EAEA,EAEE,GAAkB,IAAI,IAOtB,GAAsB,IAAI,IAC1B,GAAwB,CAAC,EACzB,EAAkB,EAAmB,EAAM,CAAI,EAW/C,GAAsB,GAAuB,CACjD,IAAM,EAAU,EAAkB,CAChC,OAAQ,CAAE,KAAM,MAAO,SAAU,wBAAyB,EAC1D,QAAS,CAAC,CAAE,KAAM,OAAQ,MAAK,CAAC,CAClC,CAAC,EACK,EAAW,EAIjB,GAAI,IAAa,IAAA,GACf,GAAI,CACF,EAAkB,EAAQ,QAAQ,OAChC,CAAE,KAAM,OAAQ,SAAQ,EACxB,CAAE,GAAI,UAAW,KAAM,EAAU,GAAI,EAAU,QAAS,CAAC,CAAQ,CAAE,CACrE,CAAC,CAAC,IACF,MACF,MAAQ,CACN,EAAkB,IAAA,EACpB,CAEF,EAAkB,EAAQ,QAAQ,OAAO,CAAE,KAAM,OAAQ,SAAQ,CAAC,CAAC,CAAC,GACtE,EACM,GAAkB,EAAQ,kBAAoB,IAAA,IAAa,EAAQ,gBAAgB,SAAW,EAChG,IAAA,GACA,IAAI,EAAsB,CAC1B,SAAU,EAAQ,gBAClB,QAAS,EAAQ,QACjB,GAAG,EAAQ,SAAW,IAAA,GAAY,CAAC,EAAI,CAAE,OAAQ,EAAQ,MAAO,EAChE,OAAQ,EAAS,IAAS,GAAQ,EAAS,EAAS,EAAQ,CAAI,EAChE,MAAO,CAAE,QAAS,EAAQ,OAAO,QAAS,eAAgB,EAAQ,OAAO,cAAe,CAC1F,CAAC,EAEC,GAAqC,CAAC,EACtC,EAAc,GACd,GAAY,GACV,GAAgB,GAAiB,CAAO,EACxC,GAAW,EAAQ,uBAAyB,IAAA,GAAY,IAAA,GAAY,EAAqB,EAAQ,oBAAoB,EAErH,GAAiB,KAAa,IAAA,GAAY,IAAA,GAAY,IAAI,EAC1D,GAAuB,EAAQ,cAAc,OAAS,eAAiB,GACvE,EAAkB,EAAQ,YAAY,eAAe,OAAQ,CACjE,KAAM,CAAE,OAAM,MAAO,EAAQ,OAAO,KAAM,CAC5C,CAAC,EACG,GAAqB,GACrB,EAGE,EAAiB,GAAuE,CAC5F,GAAI,EAAO,QAAS,MAAO,CAAE,KAAM,SAAU,EAC7C,IAAM,EAAgB,EAAoB,EAAQ,UAAU,EAC5D,GAAI,IAAkB,IAAA,GAAW,OAAO,EACxC,GAAI,IAAc,IAAA,GAAW,OAAO,EAGpC,IAAM,EAAS,EAAiB,EAAwB,IAAkB,IAAA,GACtE,EAAmB,CAAC,GAAG,EAAkB,CAAa,CAAC,CAAC,EAC5D,OAAO,IAAW,IAAA,IAAa,GAAU,EACrC,CAAE,KAAM,mBAAoB,OAAQ,SAAU,kBAAmB,EAAM,EACvE,IAAA,EACN,EAEA,GAAI,CACJ,MAAM,EAAK,CACT,KAAM,aAAc,MAAO,EAAM,GAAI,GACrC,KAAM,gBAAgB,EAAQ,OAAO,SAAW,UAAW,KAAM,eACjE,WAAY,CACV,wBAAyB,eACzB,kBAAmB,EAAQ,OAAO,SAAW,QAC7C,oBAAqB,EAAQ,OAAO,WAAa,EAAQ,OAAO,SAAW,QAC3E,uBAAwB,EAAQ,OAAO,MACvC,GAAG,EAAQ,OAAO,iBAAmB,IAAA,GACjC,CAAC,EACD,CAAE,yBAA0B,EAAQ,MAAM,cAAe,CAC/D,CACF,CAAC,EACD,EAAc,GACd,MAAM,EAAK,CAAE,KAAM,aAAc,OAAM,MAAO,CAAK,CAAC,EAEpD,cAAe,OAAa,CAC5B,KAAO,IAAW,IAAA,IAAa,EAAU,GAAK,GAAiB,IAAa,CAAC,EAAO,UAClF,EAAS,EAAc,EACnB,IAAW,IAAA,KAF4E,CAI3F,GAAI,EAAQ,GAAK,IAAkB,IAAA,IAAa,GAAU,GAAK,GAAmB,CAChF,EAAS,EAAO,cAAgB,OAC5B,CAAE,KAAM,mBAAoB,OAAQ,OAAQ,kBAAmB,EAAM,EACrE,MAAM,GAAY,OAAQ,EAAK,EACnC,KACF,CAGA,IAAM,EAAa,EAAiB,EAAwB,CAAgB,CAAC,EAC7E,GAAI,EAAO,iBAAmB,QAAU,IAAe,IAAA,GAAW,CAChE,IAAM,EAAU,CAAC,GAAK,IAAM,EAAG,CAAC,CAAC,OAAO,GAAS,GAAc,EAAiB,CAAK,CAAC,CAAC,OACvF,GAAI,EAAU,GAAoB,CAChC,GAAqB,EACrB,IAAM,EAAY,KAAK,IAAI,EAAG,EAAiB,CAAU,EACzD,EAAQ,QAAQ,OAAO,CAAE,KAAM,OAAQ,QAAS,EAAkB,CAChE,OAAQ,CAAE,KAAM,MAAO,SAAU,uBAAwB,EACzD,QAAS,CAAC,CAAE,KAAM,OAAQ,KAAM,iBAAiB,EAAU,MAAM,EAAO,eAAe,+FAClF,GAAW,EAAI,2BAA6B,uDAC7C,gPACJ,CAAC,CACH,CAAC,CAAE,CAAC,CACN,CACF,CAGI,CAAC,IAAoB,IAAkB,IAAA,IAAa,EAAU,EAAI,GAAK,EAAW,EAAU,GAAK,IACnG,GAAmB,GACnB,EAAQ,QAAQ,OAAO,CAAE,KAAM,OAAQ,QAAS,EAAkB,CAChE,OAAQ,CAAE,KAAM,MAAO,SAAU,sBAAuB,EACxD,QAAS,CAAC,CAAE,KAAM,OAAQ,KACxB,GAAG,EAAW,EAAU,EAAE,sMAC5B,CAAC,CACH,CAAC,CAAE,CAAC,GAIF,KAAoB,IAAA,KACtB,MAAM,GAAgB,UAAU,EAAO,GAAgB,CAAM,EAC7D,GAAiB,CAAC,GAEpB,IAAM,EAAO,EAAQ,EACf,EAAQ,MAAM,EAClB,EAAS,EAAQ,EAAM,EAAiB,EAAM,EAAM,EACpD,GACI,UACA,EAAQ,cAAc,OAAS,cAAgB,QAAU,WAC7D,EAAS,CACX,EACA,IACI,EAAM,SAAW,IAAA,IAAW,EAAiB,KAAK,EAAM,MAAM,EAClE,EAAY,EAAoB,EAAQ,UAAU,IAAM,EAAM,cAC1D,CAAE,KAAM,QAAS,QAAS,CAAE,QAAS,0DAA2D,KAAM,gBAAiB,CAAE,EACzH,EAAM,iBACJ,CAAE,KAAM,oBAAqB,YAAa,EAAM,QAAQ,aAAe,SAAU,EACjF,IAAA,IACN,IAAM,EAAc,SAA2B,CAC7C,GAAI,EAAM,UAAY,IAAA,GAAW,CAC/B,EAAQ,QAAQ,OAAO,CACrB,KAAM,YAAa,QAAS,EAAM,QAClC,GAAG,EAAM,OAAO,OAAS,UAAY,CAAE,YAAa,EAAc,EAAI,CAAC,EACvE,GAAG,EAAM,QAAU,IAAA,GAAY,CAAC,EAAI,CAAE,MAAO,EAAM,KAAM,CAC3D,CAAC,EACD,MAAM,EAAK,CAAE,KAAM,oBAAqB,QAAS,EAAM,QAAS,MAAO,EAAM,KAAM,CAAC,EACpF,MAAM,GAAqB,EAAO,CAAI,EAGtC,IAAM,EAAY,EAAO,EAAM,QAAQ,OAAO,GAC1C,EAAU,KAAK,IAAM,IAAO,EAAM,OAAO,OAAS,SAAW,EAAM,OAAO,OAAS,aAAY,EAAO,EAC5G,MAAW,EAAM,OAAO,OAAS,SAG/B,EAAO,GAEX,EAQA,GAHuB,EAAM,OAAO,OAAS,SAAW,CAAC,EAAM,eAC1D,IAAc,IAAA,IAAa,CAAC,EAAO,SACnB,MAAM,EAAY,EACnC,EAAO,SAAW,EAAM,OAAO,OAAS,UAAW,CAAE,EAAS,CAAE,KAAM,SAAU,EAAG,KAAM,CAG7F,GAAI,EAAM,OAAO,OAAS,SAAW,IAAc,IAAA,GAAW,CAC5D,EAAS,CAAE,KAAM,QAAS,QAAS,EAAM,OAAO,OAAQ,EACxD,KACF,CACA,GAAI,EAAM,gBAAkB,EAAM,MAAM,SAAW,GAAK,EAAQ,QAAU,IAAA,IAAY,CAAE,EAAS,EAAW,KAAM,CAClH,GAAI,EAAM,OAAO,OAAS,SAAW,CAAC,EAAM,cAAe,CAEzD,GADA,EAAS,EAAc,EACnB,IAAW,IAAA,GAAW,CAAE,MAAM,EAAY,EAAG,KAAM,CACvD,IAAM,EAAW,MAAM,GAAgB,EAAQ,OAAO,eAAgB,CAAC,CACrE,OAAM,OAAM,QAAS,EAAM,OAAO,QAAS,SAAU,EAAQ,QAAQ,SAAS,EAAG,SACjF,GAAI,EAAQ,SAAW,IAAA,GAAY,CAAC,EAAI,CAAE,OAAQ,EAAQ,MAAO,EACjE,KAAM,CACR,CAAC,EAAG,EAAS,EAAQ,gBAAgB,CAAC,CAGnC,MAAO,GAAmB,CAAE,GAAI,EAAO,QAAS,MAAO,OAAiB,MAAM,CAAM,CAAC,EAClF,EAAkB,EAAoB,EAAQ,UAAU,EAC9D,GAAI,IAAoB,IAAA,GAAW,CAAE,MAAM,EAAY,EAAG,EAAS,EAAO,QAAU,CAAE,KAAM,SAAU,EAAI,EAAiB,KAAM,CACjI,GAAI,IAAa,SAAW,CAAC,EAAO,UAC9B,EAAgB,GAA0B,IAC1C,EAAU,GAAK,GAAiB,IAAW,SAEjD,MAAM,EAAY,EAClB,EAAS,EAAO,QAAU,CAAE,KAAM,SAAU,EAAI,CAAE,KAAM,QAAS,QAAS,EAAM,OAAO,OAAQ,EAC/F,KACF,CACA,GAAI,EAAM,OAAO,OAAS,cAAgB,CAAC,EAAM,cAAe,CAAE,EAAS,CAAE,KAAM,YAAa,EAAG,KAAM,CACzG,GAAI,EAAM,MAAM,SAAW,GAAK,EAAM,iBAAkB,CACtD,EAAS,EAAoB,EAAQ,UAAU,GAAK,CAAE,KAAM,oBAAqB,YAAa,EAAM,QAAQ,aAAe,SAAU,EACrI,KACF,CACA,GAAI,EAAM,MAAM,SAAW,GAAK,GAAsB,CAEpD,GADA,EAAS,EAAc,EACnB,IAAW,IAAA,GAAW,MAC1B,EAAQ,QAAQ,OAAO,CAAE,KAAM,OAAQ,QAAS,EAAkB,CAChE,OAAQ,CAAE,KAAM,MAAO,SAAU,6BAA8B,EAC/D,QAAS,CAAC,CACR,KAAM,OACN,KAAM,+GACR,CAAC,CACH,CAAC,CAAE,CAAC,EACJ,IAAM,EAAQ,MAAM,GAAgB,MAAM,EACxC,EAAS,EAAQ,EAAM,EAAiB,EAAM,EAAM,EAAQ,EAAG,QAAS,EAAS,CACnF,EAAG,OAAO,EACV,IACI,EAAM,SAAW,IAAA,IAAW,EAAiB,KAAK,EAAM,MAAM,EAC9D,EAAM,UAAY,IAAA,KACpB,EAAQ,QAAQ,OAAO,CACrB,KAAM,YAAa,QAAS,EAAM,QAClC,GAAG,EAAM,QAAU,IAAA,GAAY,CAAC,EAAI,CAAE,MAAO,EAAM,KAAM,CAC3D,CAAC,EACD,MAAM,EAAK,CAAE,KAAM,oBAAqB,QAAS,EAAM,QAAS,MAAO,EAAM,KAAM,CAAC,EACpF,MAAM,GAAqB,EAAO,CAAI,EACtC,EAAO,EAAO,EAAM,QAAQ,OAAO,GAErC,AASO,EATH,EAAO,SAAW,EAAM,OAAO,OAAS,UAAoB,CAAE,KAAM,SAAU,EACzE,EAAM,OAAO,OAAS,QAAkB,CAAE,KAAM,QAAS,QAAS,EAAM,OAAO,OAAQ,EACvF,EAAM,OAAO,OAAS,aAAuB,CAAE,KAAM,YAAa,EAClE,EAAM,cAAwB,CAAE,KAAM,QAAS,QAAS,CAC/D,QAAS,0DACT,KAAM,gBACR,CAAE,EACO,EAAM,iBACJ,EAAoB,EAAQ,UAAU,GAAK,CAAE,KAAM,oBAAqB,YAAa,EAAM,QAAQ,aAAe,SAAU,EACvH,CAAE,KAAM,WAAY,EACpC,KACF,CAgBA,GAZI,EAAM,wBAA0B,IAAA,IAClC,EAAQ,QAAQ,OAAO,CAAE,KAAM,OAAQ,QAAS,EAAkB,CAChE,OAAQ,CAAE,KAAM,MAAO,SAAU,2BAA4B,EAC7D,QAAS,CAAC,CACR,KAAM,OACN,KAAM,+BAA+B,EAAM,sBAAsB,IAAI,GAAM,IAAI,EAAG,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,oNAInG,CAAC,CACH,CAAC,CAAE,CAAC,EAEF,EAAM,MAAM,SAAW,GAAK,EAAQ,QAAU,IAAA,GAAW,CAAE,EAAS,CAAE,KAAM,WAAY,EAAG,KAAM,CAKrG,IAAM,EAAY,KAAK,IAAI,EAAG,EAAO,aAAe,CAAS,EACzD,GAA+D,EAC7D,GAAmB,EAAM,MAAM,IAAI,GAAQ,CAC/C,IAAM,EAAM,EAAU,CAAI,EAIpB,EAAQ,IAAkB,MAAQ,EAAM,GAAiB,MAAQ,EAAI,EAE3E,MADA,IAAmB,CAAE,MAAK,OAAM,EACzB,CACT,CAAC,EACK,EAA8B,GAAiB,KAAK,GAAS,GAAS,EAAO,eAAe,EAC5F,EAAgB,GAAkB,EAAM,KAAK,EAC7C,EAAiB,GACrB,CAAC,GAAG,GAAa,CAAa,EAC9B,EAAO,kBACT,EACM,EAA2B,IAAmB,IAAA,IAC/C,EAAe,aAAe,EAAO,eACpC,GAAe,EAAwB,CAAgB,EACvD,EAAe,EAAiB,EAAY,EAC5C,EAA2B,IAAiB,IAAA,IAC7C,GAAgB,EAEf,GAA0B,IAAkB,IAAA,IAAa,GAAU,GAAK,GACxE,EAAgB,GAA4B,GAA4B,EAAM,eAC/E,IAAkB,IAAA,IAAa,GAI9B,GAAmC,IAAmB,IAAA,IAAa,CAAC,EACtE,EACA,EACA,SACA,GACA,OACA,EACE,kBACA,EAAM,cACJ,iBACA,aAIF,EAAgB,EAAO,cAAgB,WACvC,EAAmB,IAAI,IAIvB,EAA8B,IAAI,IAAI,EAAM,MAC/C,QAAQ,EAAO,KAAW,GAAiB,IAAU,IAAM,EAAO,eAAe,CAAC,CAClF,IAAI,GAAQ,OAAO,EAAK,MAAM,CAAC,CAAC,EAG7B,EAAgB,EAAM,MAAM,OAAO,GACvC,CAAC,EAA4B,IAAI,OAAO,EAAK,MAAM,CAAC,GACjD,EAAQ,OAAO,IAAI,EAAK,QAAQ,CAAC,EAAE,eAAiB,EAAI,CAAC,CAAC,OACzD,EAAU,GAA+B,CAAC,GAA4B,CAAC,GACxE,CAAC,EAAM,cACP,GAAsE,CACrE,IAAM,EAAQ,GAAgB,IAAI,EAAU,CAAI,CAAC,EAC7C,MAAC,EAA4B,IAAI,OAAO,EAAK,MAAM,CAAC,GACnD,GAAY,MAAQ,EAAU,CAAI,GAClC,EAAW,YAAc,IACzB,IAAU,IAAA,IACV,EAAM,SAAW,EAAW,QAC5B,EAAM,eAAiB,EAAK,cAC5B,EAAM,aAAe,EAAQ,OAAO,IAAI,EAAK,QAAQ,GACrD,EAAM,OAAO,oBAAsB,IAAA,IACnC,EAAM,OAAO,gBAAkB,IAC/B,EAAQ,OAAO,IAAI,EAAK,QAAQ,CAAC,EAAE,eAAiB,IAEzD,OADA,EAAiB,IAAI,OAAO,EAAK,MAAM,CAAC,EACjC,GAAkB,CAAK,CAChC,EACA,IAAA,GACE,EAAY,MAAM,GAAkB,CACxC,MAAO,EAAM,MAAO,QAAS,EAAQ,MAAO,QAAS,EAAQ,QAC7D,SAAU,CAAE,OAAM,OAChB,GAAI,EAAQ,aAAe,IAAA,GAAY,CAAC,EAAI,CAAE,MAAO,EAAQ,WAAW,KAAM,EAC9E,GAAI,EAAQ,OAAO,iBAAmB,IAAA,GAAY,CAAC,EAAI,CAAE,eAAgB,EAAQ,MAAM,cAAe,CACxG,EAAG,SAAQ,YAAa,EACxB,YAAa,EAAO,YACpB,cAAe,EAAgB,EAAI,EAAgB,EAAY,EAAM,MAAM,OAC3E,iBACA,eAAgB,EAAO,mBACvB,gBAAiB,EAAO,oBACxB,eAAgB,EAAO,mBACvB,GAAG,EAAQ,aAAe,IAAA,GAAY,CAAC,EAAI,CAAE,WAAY,EAAQ,UAAW,EAC5E,cAAe,EAAO,kBACtB,kBAAmB,EAAO,sBAC1B,GAAI,EAAQ,SAAW,IAAA,GAAY,CAAC,EAAI,CAAE,OAAQ,EAAQ,MAAO,EACjE,GAAG,EAAQ,eAAiB,IAAA,GAAY,CAAC,EAAI,CAAE,aAAc,EAAQ,YAAa,EAClF,GAAG,EAAQ,YAAc,IAAA,GAAY,CAAC,EAAI,CAAE,UAAW,EAAQ,SAAU,EACzE,GAAG,EAAQ,aAAe,IAAA,GAAY,CAAC,EAAI,CAAE,WAAY,EAAQ,UAAW,EAC5E,OACA,GAAG,IAAY,IAAA,GAAY,CAAC,EAAI,CAAE,SAAQ,EAC1C,GAAG,EAAQ,OAAO,aAAe,IAAA,GAAY,CAAC,EAAI,CAChD,WAAa,GAAiE,GAC5E,QAAQ,QAAQ,EAAQ,OAAO,aAAa,CAAO,CAAC,EAAG,EAAS,EAAQ,YAC1E,CACF,CACF,EAAG,CACD,eAAgB,GAChB,eAAgB,EAAgB,EAAI,EAAgB,EAAY,YAGhE,GAAG,IAAkB,IAAA,GAAY,CAAC,EAAI,CACpC,SAAW,GACT,GAAc,IAAI,EAAK,QAAQ,EAAI,IAAA,GAAY,GAAkB,OACrE,EACA,GAAG,GAAiB,CAAC,EAA8B,CAAC,EAAI,CACtD,QAAU,GACR,EAA4B,IAAI,OAAO,EAAK,MAAM,CAAC,EAAI,qBAAuB,IAAA,EAClF,EACA,GAAG,KAAa,IAAA,GAAY,CAAC,EAAI,CAAE,WAAS,EAC5C,GAAG,KAAmB,IAAA,GAAY,CAAC,EAAI,CAAE,iBAAe,CAC1D,CAAC,EAKG,KAAoB,IAAA,IAAa,EAAU,QAAQ,SAAW,EAAM,MAAM,QAC5E,GAAe,KAAK,GAAG,EAAM,MAAM,KAAK,EAAM,KAAW,CACvD,SAAU,EAAK,SACf,aAAc,EAAK,aACnB,OAAQ,EAAU,QAAQ,EAAM,EAAE,SAAW,EAC/C,EAAE,CAAC,EAEL,GAAa,EAAU,SACvB,IAAM,EAAyB,KAAK,IAAI,EAAG,EAAO,aAAe,CAAS,EAapE,EAAU,GAAgB,OAAO,GAAa,GAA0B,CAAS,CAAC,CAAC,OAkBzF,GAjBI,EAAU,IAAuB,EAAyB,IAC5D,GAAsB,EACtB,GACE,gBAAgB,EAAuB,MAAM,EAAO,aAAa,sGAE9D,EACC,mHAEA,oGAEN,GAOE,CAAC,GAAiB,IAA2B,EAAG,CAClD,IAAM,EAAU,KAAK,MAAM,EAAY,EAAO,YAAY,EACtD,EAAU,KACZ,GAAwB,EACxB,GACE,sBAAsB,EAAU,kCAAkC,EAAO,aAAa,mJAGxF,EAEJ,CACA,MAAM,EAAK,CAAE,KAAM,WAAY,OAAM,OAAM,MAAO,EAAM,KAAM,CAAC,EAE/D,GAAY,KAAK,CAAa,EAC9B,IAAI,EAAgB,EACpB,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAM,MAAM,OAAQ,IAAS,CACvD,IAAM,EAAO,EAAM,MAAM,GACnB,EAAS,EAAU,QAAQ,GACjC,GAAI,IAAS,IAAA,IAAa,IAAW,IAAA,GAAW,SAChD,EAAoB,EAAO,QAAU,EAAoB,EAAI,EAC7D,IAAM,EAAM,EAAU,CAAI,EACpB,EAAQ,GAAY,MAAQ,EAAM,EAAW,MAAQ,EAAI,EAC/D,EAAa,CACX,MAAK,QAAO,OAAQ,OAAO,EAAK,MAAM,EACtC,UAAW,CAAC,EAAO,SAAW,EAAO,MAAM,WAAa,IACnD,EAAQ,OAAO,IAAI,EAAK,QAAQ,CAAC,EAAE,eAAiB,EAC3D,EACI,IAAU,EAAO,qBACnB,EAAQ,QAAQ,OAAO,CAAE,KAAM,OAAQ,QAAS,EAAkB,CAChE,OAAQ,CAAE,KAAM,MAAO,SAAU,wBAAyB,EAC1D,QAAS,CAAC,CAAE,KAAM,OAAQ,KAAM,mBAAmB,EAAK,SAAS,2BAA2B,EAAM,kDAAmD,CAAC,CACxJ,CAAC,CAAE,CAAC,EAEF,GAAS,EAAO,kBAAiB,EAAgB,IACjD,CAAC,EAAO,SAAW,EAAO,MAAM,WAAa,IAC5C,EAAQ,OAAO,IAAI,EAAK,QAAQ,CAAC,EAAE,eAAiB,IACvD,GAAgB,IAAI,EAAK,CACvB,OAAQ,OAAO,EAAK,MAAM,EAAG,aAAc,EAAK,aAChD,WAAY,EAAQ,MAAM,IAAI,EAAK,QAAQ,EAAG,QAChD,CAAC,CAEL,CAUA,GATI,GAAgB,cAAgB,EAAO,oBACzC,EAAQ,QAAQ,OAAO,CAAE,KAAM,OAAQ,QAAS,EAAkB,CAChE,OAAQ,CAAE,KAAM,MAAO,SAAU,uBAAwB,EACzD,QAAS,CAAC,CACR,KAAM,OACN,KAAM,6BAA6B,EAAe,YAAY,gBAAgB,EAAe,OAAO,sFACtG,CAAC,CACH,CAAC,CAAE,CAAC,EAEF,EAAU,UAAW,CAAE,EAAS,CAAE,KAAM,oBAAqB,SAAU,EAAU,aAAe,SAAU,EAAG,KAAM,CACvH,GAAI,EAAO,QAAS,CAAE,EAAS,CAAE,KAAM,SAAU,EAAG,KAAM,CAC1D,GAAI,EAAM,cAAe,CAAE,EAAS,EAAW,KAAM,CACrD,GAAI,EAAM,iBAAkB,CAC1B,EAAS,EAAoB,EAAQ,UAAU,GAAK,CAAE,KAAM,oBAAqB,YAAa,EAAM,QAAQ,aAAe,SAAU,EACrI,KACF,CACA,IAAI,EACE,EAAuB,EAAO,iBAAmB,QAClD,EAAO,yBAA2B,GAAK,IAAiB,IAAA,IACxD,GAAgB,EAAiB,EAAO,yBACvC,GAAsB,GACvB,EAAiB,OAAS,EAAM,MAAM,QACtC,EAAM,MAAM,MAAM,GAAQ,EAAiB,IAAI,OAAO,EAAK,MAAM,CAAC,GAChE,CAAC,GAAoB,IAAI,EAAU,CAAI,CAAC,CAAC,GAC3C,EAAU,QAAQ,SAAW,EAAM,MAAM,QACzC,EAAU,QAAQ,MAAM,GAAU,CAAC,EAAO,OAAO,GACjD,EAAU,aAAe,GAAK,EAAU,WAAa,GACrD,CAAC,GAA4B,CAAC,GAA4B,CAAC,GAC3D,CAAC,EAAM,eAAiB,CAAC,EAAM,kBAAoB,CAAC,EAAO,SAC3D,EAAE,GAAiB,EAAgB,IACnC,IAAsB,GAAK,EAAU,EAAI,GACzC,EAAO,cAAgB,QAAU,EAAc,IAAM,IAAA,GAIpD,GAA6B,GAC9B,CAAC,GAAG,CAA2B,CAAC,CAAC,MAAM,GAAM,EAAiB,IAAI,CAAE,CAAC,GACrE,EAAU,QAAQ,SAAW,EAAM,MAAM,QACzC,EAAU,WAAa,GAAK,EAAU,WAAa,EACxD,GAAI,GACF,IAAK,IAAM,KAAQ,EAAM,MAAO,GAAoB,IAAI,EAAU,CAAI,CAAC,OAC9D,GACF,EAD4B,EAAY,SAExC,EAA0B,EAAY,kBACtC,GAAiB,EAAgB,EAAW,EAAY,aACxD,GAAqB,EAAO,yBAA0B,EAAY,0BAClE,GAAiB,CAAC,GAA4B,EAAY,qBAC1D,EAAU,GAAK,IAAU,EAAY,SAG9C,GADI,IAAkB,IAAA,KAAW,EAAY,EAA2B,SAAW,IAAA,IAC/E,IAAc,IAAA,IAAa,GACxB,IAAA,IAAM,KAAQ,EAAM,MACnB,EAAiB,IAAI,OAAO,EAAK,MAAM,CAAC,GAAG,GAAoB,IAAI,EAAU,CAAI,CAAC,EAItF,IAAc,IAAA,IAAa,IAAkB,IAAA,IAAa,GAAU,GAAK,KAAmB,EAAY,QACxG,IAAc,IAAA,KAIhB,GAHgB,IAAc,UAAa,GAAwB,CAAC,IAC/D,EAAO,cAAgB,QACvB,EAAc,IAAM,IAAA,GAErB,MAAM,GAAY,EAAW,IAAc,UAAY,GAAwB,CAAC,CAAwB,EACxG,CAAE,KAAM,mBAAoB,OAAQ,EAAW,kBAAmB,GAClE,GAAI,IAAc,UAAY,GAAwB,CAAC,EAA2B,CAAE,QAAS,gBAA0B,EAAI,CAAC,CAAG,EAEvI,CAMA,IAAM,EAAc,GAAQ,OAAS,mBACjC,EAAO,kBACP,GAAQ,OAAS,aAAe,EAAU,GAAK,EACnD,GAAI,IAAkB,IAAA,IAAa,EAAQ,WAAa,IAAA,IAAa,EAAO,cAAgB,IACtF,GAAQ,OAAS,oBAAsB,GAAQ,OAAS,cAAgB,GACzE,EAAK,KAAK,IAAM,IAAM,CAAC,EAAO,SAAW,EAAc,IAAM,IAAA,IAC7D,CAAC,GAAe,EAAQ,OAAO,EAAG,CACrC,IAAM,EAAS,EAAQ,SAAS,OAAO,CAAE,OAAM,QAAO,CAAC,EACvD,GAAI,IAAW,IAAA,GAAW,CACxB,EAAQ,QAAQ,OAAO,CAAE,KAAM,OAAQ,QAAS,CAAO,CAAC,EACxD,EAAiB,EACjB,EAAiB,EAAO,OAAS,mBAAqB,EAAO,OAAS,QACtE,EAAa,EACb,EAAgB,EAAQ,QAAQ,SAAS,CAAC,CAAC,SAAS,GAAW,EAAQ,OAAS,WAAW,EAC3F,EAAgB,EAAU,EAAI,EAAO,cACrC,EAAS,IAAA,GACT,SAAS,aACX,CACF,CAUA,GATI,IAAW,IAAA,KACb,EAAS,EAAO,QACZ,CAAE,KAAM,SAAU,EAClB,CAAE,KAAM,mBAAoB,OAAQ,QAAS,kBAAmB,EAAM,GAMxE,IAAmB,IAAA,GAAW,CAEhC,GADwB,EAAO,OAAS,aAAe,EAAK,KAAK,IAAM,IAAM,EAAQ,UAAU,UAAU,IAAM,GACzF,CACpB,EAAO,EAGP,IAAM,EAAO,EAAQ,QAAQ,SAAS,CAAC,CAAC,SAAS,GAAW,EAAQ,OAAS,WAAW,EACxF,GAAI,IAAkB,IAAA,IAAa,GAAM,KAAO,EAAc,GAAI,CAChE,IAAM,EAAW,EAAc,CAAE,KAAM,YAAa,QAAS,EAAc,QAAS,OAAQ,EAAc,MAAO,CAAC,EAClH,EAAQ,QAAQ,OAAO,CAAE,KAAM,YAAa,QAAS,CAAS,CAAC,EAC/D,MAAM,EAAK,CAAE,KAAM,oBAAqB,QAAS,EAAU,MAAO,CAAK,CAAC,CAC1E,CACF,CACI,EAAO,OAAS,YAAW,EAAS,EAC1C,CACA,IAAM,EAAc,EAAwB,CAAgB,EACtD,EAAQ,EAAwB,CAAW,EAC3C,EAAyB,CAC7B,SAAQ,OAAM,QAAO,cAAa,YAAW,UAC7C,GAAG,IAAU,IAAA,GAAY,CAAC,EAAI,CAAE,OAAM,CACxC,EACM,EAAoB,EAAQ,QAAQ,QAAQ,CAAC,CAAC,OAC9C,EAAc,EAAO,OAAS,aAC/B,EAAU,EAAI,GACd,EAAc,IAAM,IAAA,GAUzB,GATA,MAAM,GAAgB,EAAQ,OAAO,UAAW,CAAC,CAC/C,QAAS,EACT,SAAU,EAAQ,QAAQ,SAAS,EACnC,aACF,CAAC,EAAG,EAAS,EAAO,QAAU,IAAI,gBAAgB,CAAC,CAAC,OAAS,EAAQ,WAAW,EAK5E,GACC,CAAC,EAAO,UACP,EAAQ,QAAQ,QAAQ,CAAC,CAAC,OAAS,GAAqB,GAAmB,EAAQ,OAAO,GAAI,CAClG,EAAS,IAAA,GACT,SAAS,aACX,CACA,EAAU,EACV,KACA,CACI,EAAQ,OAAO,OAAS,WAK1B,EAAQ,QAAQ,OAAO,CAAE,KAAM,OAAQ,QAAS,EAAkB,CAChE,OAAQ,CAAE,KAAM,MAAO,SAAU,kBAAmB,EACpD,QAAS,CAAC,CAAE,KAAM,OAAQ,KAAM,6GAA8G,CAAC,CACjJ,CAAC,CAAE,CAAC,EAEN,MAAM,EAAK,CACT,KAAM,WAAY,MAAO,EAAM,GAAI,EAAI,EACvC,OAAQ,EAAQ,OAAO,OAAS,QAAU,QAAU,EAAQ,OAAO,OAAS,UAAY,UAAY,UACpG,OAAQ,CAAE,OAAQ,EAAQ,OAAQ,MAAK,EACvC,GAAG,EAAQ,QAAU,IAAA,GAAY,CAAC,EAAI,CAAE,MAAO,EAAQ,KAAM,EAC7D,GAAG,EAAQ,OAAO,OAAS,QAAU,CAAE,MAAO,CAAE,KAAM,aAAc,QAAS,EAAQ,OAAO,QAAQ,QAAS,KAAM,EAAQ,OAAO,QAAQ,IAAK,CAAE,EAAI,CAAC,CACxJ,CAAC,EACD,GAAY,GACR,IAAoB,IAAA,KACtB,EAAQ,YAAY,aAClB,EACA,EAAQ,OAAO,OAAS,QAAU,QAAU,EAAQ,OAAO,OAAS,UAAY,UAAY,UAC5F,CAAE,KAAM,CAAE,OAAQ,EAAQ,OAAO,KAAM,QAAO,WAAU,CAAE,CAC5D,EACA,GAAqB,IAEvB,MAAM,EAAK,CAAE,KAAM,WAAY,UAAS,MAAO,CAAK,CAAC,CACrD,OAAS,EAAgB,CACvB,IAAM,EAAO,EAAY,CAAK,EAmB9B,MAlBI,GAAe,CAAC,IAClB,MAAM,EAAK,CACT,KAAM,WAAY,MAAO,EAAM,GAAI,EAAI,EAAG,OAAQ,EAAO,QAAU,UAAY,QAC/E,MAAO,CACL,KAAM,aAAiB,MAAQ,EAAM,KAAO,eAC5C,QAAS,GAAU,CAAK,EACxB,GAAG,IAAS,IAAA,GAAY,CAAC,EAAI,CAAE,MAAK,CACtC,CACF,CAAC,CAAC,CAAC,UAAY,IAAA,EAAS,EAEtB,IAAoB,IAAA,IAAa,CAAC,KACpC,EAAQ,YAAY,aAClB,EACA,EAAO,QAAU,UAAY,QAC7B,CAAE,OAAM,CACV,EACA,GAAqB,IAEjB,CACR,QAAU,CACR,IAAgB,MAAM,CACxB,CACF,CAEA,SAAS,GAAkB,EAGH,CACtB,OAAO,EAAe,CACpB,QAAS,GAGT,MAAO,EAAM,OAAO,MACpB,QAAS,CACP,CACE,KAAM,OACN,KAAM,KAAK,UAAU,CACnB,OAAQ,eACR,OAAQ,EAAM,OACd,YAAa,qGACf,CAAC,CACH,EACA,GAAG,EAAM,OAAO,OAClB,EACA,KAAM,CAAE,GAAG,EAAM,OAAO,KAAM,UAAW,GAAM,kBAAmB,EAAM,MAAO,CACjF,CAAC,CACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"schedule.d.ts","names":[],"sources":["../../../src/agent/loop/schedule.ts"],"mappings":";;;;;;;;;;;UA8BiB;WACN,gBAAgB;WAChB,SAAS;WACT,SAAS;WACT,UAAU;WACV,QAAQ;WACR,SAAS;WACT,aAAa;WACb;;;;;;;WAOA;;WAEA,gBAAgB;;WAEhB;;WAEA,iBAAiB;;WAEjB,aAAa;;WAEb;;WAEA;;WAEA;WACA,wBAAwB;WACxB,YAAY;WACZ,QAAQ,OAAO,eAAe;WAC9B,aAAa;WACb,aAAa;;;;;WAKb,WAAW,MAAM,oBAAoB;;UAE/B;WACN,kBAAkB;WAClB;WACA;WACA;;WAEA;;WAEA;;;iBAkCW,aAAa,SAAS,sBAAsB,QAAQ"}
1
+ {"version":3,"file":"schedule.d.ts","names":[],"sources":["../../../src/agent/loop/schedule.ts"],"mappings":";;;;;;;;;;;UA8BiB;WACN,gBAAgB;WAChB,SAAS;WACT,SAAS;WACT,UAAU;WACV,QAAQ;WACR,SAAS;WACT,aAAa;WACb;;;;;;;WAOA;;WAEA,gBAAgB;;WAEhB;;WAEA,iBAAiB;;WAEjB,aAAa;;WAEb;;WAEA;;WAEA;WACA,wBAAwB;WACxB,YAAY;WACZ,QAAQ,OAAO,eAAe;WAC9B,aAAa;WACb,aAAa;;;;;WAKb,WAAW,MAAM,oBAAoB;;UAE/B;WACN,kBAAkB;WAClB;WACA;WACA;;WAEA;;WAEA;;;iBA4CW,aAAa,SAAS,sBAAsB,QAAQ"}
@@ -1,3 +1,3 @@
1
- import{detachedFrozen as e}from"../../primitives/snapshot.js";import{waitForSettlement as t}from"../../async/settlement.js";import{createSpanId as n}from"../../observation/context.js";import{createToolResultMessage as r,createUserMessage as i}from"../../message/message.js";import{estimateTextBlockTokens as a,previewForSpill as o,truncateMiddleToTokens as s}from"../tool/output-budget.js";import{TOOL_ERROR_CODES as c,ToolError as l,toolErrorDisposition as u}from"../tool/errors.js";import{NESTED_TOOL_ERROR_CODES as d,attachNestedToolPort as f}from"../tool/nested.js";import{authorizeToolCall as p,dispatchAuthorizedToolCall as m,finalizeToolCall as h,prepareToolCall as g,toolFailure as _}from"../tool/pipeline.js";import{createToolAdmission as v}from"./admission.js";import{emitEvent as y,errorCode as b,immutableResult as x,messageOf as S,now as C,raceWithSignal as w,teardownFailure as T,withApprovalEvents as E}from"./tool-call-support.js";import{ProgramRun as D,validPrograms as O}from"./program.js";async function k(e){return await A(e)}async function A(e,t={}){let n=H(e.maxParallel??8,`maxParallel`),r=H(e.maxResultBytes??4194304,`maxResultBytes`),i=H(e.maxDurationMs??6e5,`maxDurationMs`),a=H(e.teardownTimeoutMs??3e4,`teardownTimeoutMs`),o=Object.freeze(e.calls.map(B)),s=v(t.admissionLimit??Math.max(0,e.dispatchLimit??o.length)),c={admission:s,maxDurationMs:i,teardownTimeoutMs:a,maxResultBytes:r,programs:O(t.programs),programResults:t.programResults},l=[],u=0,d=0,f,p=0,m;for(;p<o.length;){let i=o[p];if(i===void 0)break;let a=m??j(e,i);if(m=void 0,a.mode===`exclusive`){let n=await M(e,a,c,t);u+=+!!n.dispatched,d+=+(n.declined===!0);let o=await L(e,n,r);l.push(o),f===void 0&&!o.isError&&o.concludesTurn&&(f=i.toolName),p++;continue}let s=[],h=new AbortController,g={...e,signal:AbortSignal.any([e.signal,h.signal])},_=a;try{for(;p<o.length&&s.length<n&&o[p]!==void 0;){let e=_;if(e.mode!==`parallel`)break;let r=await M(g,e,c,t);u+=+!!r.dispatched,d+=+(r.declined===!0),s.push(r),p++;let i=o[p];i!==void 0&&s.length<n&&(_=j(g,i),_.mode!==`parallel`&&(m=_))}}catch(t){throw h.abort(t),await I(e,s,r),t}if(s.length===0)continue;let v,y=!1;for(let t of s)try{let n=await L(e,t,r);l.push(n),f===void 0&&!n.isError&&n.concludesTurn&&(f=t.call.toolName)}catch(e){y||(v=e),y=!0,h.abort(e)}if(y)throw v}return{results:Object.freeze(l),concluded:f!==void 0,...f===void 0?{}:{concludedBy:f},dispatched:u,budgeted:s.budgeted,declined:d}}function j(e,t){return g({catalog:e.catalog,call:t,position:e.position,signal:e.signal,...e.logger===void 0?{}:{logger:e.logger},...e.interceptors===void 0?{}:{interceptors:e.interceptors},...e.approvals===void 0?{}:{approvals:e.approvals}})}async function M(e,t,r,i){let{maxDurationMs:a,teardownTimeoutMs:o}=r,s=AbortSignal.timeout(a),l=AbortSignal.any([e.signal,s]),u={...t,options:{...t.options,signal:l,teardownTimeoutMs:o},context:{...t.context,signal:l}},f=u.options.call,p={traceId:e.parentTrace.traceId,spanId:n(),parentSpanId:e.parentTrace.spanId},m=!e.signal.aborted&&!l.aborted?e.recover?.(f):void 0;if(e.history.append({kind:`tool-call`,callId:f.callId,name:f.toolName,rawArguments:f.rawArguments}),await y(e,{type:`span-start`,trace:p,at:C(),name:`execute_tool ${f.toolName}`,kind:`execute_tool`,attributes:{"gen_ai.operation.name":`execute_tool`,"gen_ai.tool.name":f.toolName,"gen_ai.tool.call.id":f.callId,...m===void 0?{}:{"sdk.tool.recovered":!0}},input:f.rawArguments}),await y(e,{type:`tool-call`,call:f,trace:p}),e.signal.aborted)return{call:f,trace:p,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,pending:Promise.resolve(_(`the call was cancelled before it started`,c.ABORTED_BEFORE_DISPATCH))};if(l.aborted)return{call:f,trace:p,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,pending:Promise.resolve(V(s,a))};if(m!==void 0)return{call:f,trace:p,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,pending:Promise.resolve(m)};let h=e.catalog.get(f.toolName)?.budgetExempt===!0,g=h?void 0:i.decline?.(f);if(g!==void 0)return{call:f,trace:p,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,declined:!0,pending:Promise.resolve(P(g))};let v=r.programs.get(f.toolName);if(v!==void 0&&(h||t.mode!==`exclusive`))return{call:f,trace:p,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,pending:Promise.resolve(_(`this program tool must be exclusive and must not be budget-exempt`,d.CONFIGURATION))};let b=r.admission.reserve(h);if(b===void 0)return{call:f,trace:p,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,declined:!0,pending:Promise.resolve(P(e.declineReason??`tool-calls`))};try{return await N(e,u,f,p,l,s,b,r,v)}finally{b.release()}}async function N(e,n,r,i,a,o,s,u,d){let{maxDurationMs:h,teardownTimeoutMs:g}=u;if(e.signal.aborted)return{call:r,trace:i,signal:a,deadline:o,teardownTimeoutMs:g,dispatched:!1,pending:Promise.resolve(_(`the call was cancelled before it started`,c.ABORTED_BEFORE_DISPATCH))};let v=p(E(e,n,i)),y;try{y=await w(v,a)}catch(e){if(!a.aborted)throw e;if(!await t(v,g))throw T(r.toolName,`authorization`,g,e);return{call:r,trace:i,signal:a,deadline:o,teardownTimeoutMs:g,dispatched:!1,pending:Promise.resolve(V(o,h))}}if(y.kind===`final`)return{call:r,trace:i,signal:a,deadline:o,teardownTimeoutMs:g,dispatched:!1,pending:Promise.resolve(y.result)};try{let n=Promise.resolve(e.checkpoint?.({kind:`before-tool-dispatch`,call:r,snapshot:e.history.snapshot(),signal:a,...e.logger===void 0?{}:{logger:e.logger}}));try{await w(n,a)}catch(e){if(!a.aborted)throw e;if(!await t(n,g))throw T(r.toolName,`checkpoint`,g,e)}}catch(e){if(e instanceof l&&e.code===c.TEARDOWN_TIMEOUT)throw e;return{call:r,trace:i,signal:a,deadline:o,teardownTimeoutMs:g,dispatched:!1,pending:Promise.resolve(_(`history checkpoint failed: ${S(e)}`,c.CHECKPOINT_FAILED))}}if(a.aborted)return{call:r,trace:i,signal:a,deadline:o,teardownTimeoutMs:g,dispatched:!1,pending:Promise.resolve(V(o,h))};let b=d===void 0?void 0:new D(e,u,d,{call:r,trace:i,signal:a});b!==void 0&&f(y.call,b.port,e=>b.bindExecutionSignal(e)),s.confirm();let x=m(y.call);return x.catch(()=>void 0),{call:r,trace:i,signal:a,deadline:o,teardownTimeoutMs:g,authorized:y.call,dispatched:!0,...b===void 0?{}:{program:b},pending:x}}function P(e){return{isError:!1,value:void 0,content:[{type:`text`,text:F(e)}],meta:{declined:!0,reason:e}}}function F(e){let t=` Answer now from what you already have, and say plainly what is unverified or unfinished.`;switch(e){case`tool-calls`:return`This call was not run: the turn has spent its tool-call budget. Further work calls will not run either, so do not retry it.`+t;case`repeated-tool-call`:return`This call was not run: it repeats a call already made with the same arguments, and repeating it cannot produce a new result. Change approach or finish.`+t;case`tool-call-cycle`:return`This call was not run: the same sequence of calls has repeated several times without progress. Break the cycle rather than re-entering it.`+t;case`tokens`:return`This call was not run: the turn has spent its token budget.`+t;case`consecutive-tool-errors`:return`This call was not run: too many calls in a row have failed. Something in the approach is wrong, not the individual call.`+t;case`steps`:return`This call was not run: the turn has no model steps left.`+t;case`usage-required`:return`This call was not run: the run policy requires provider usage reporting that the last model call did not supply.`+t}}async function I(e,t,n){for(let r of t)try{await L(e,r,n)}catch{}}async function L(e,n,a){let o,s,c=!1;try{let r;try{r=await w(n.pending,n.signal)}catch(e){if(!n.signal.aborted)throw e;if(!await t(n.pending,n.teardownTimeoutMs))throw T(n.call.toolName,`execution`,n.teardownTimeoutMs,e);r=V(n.deadline)}if(n.program!==void 0){if(!await n.program.close(n.teardownTimeoutMs))throw T(n.call.toolName,`nested call`,n.teardownTimeoutMs,void 0);let e=n.program.fatal;if(e!==void 0)throw u(e)===`fatal`?e:l.fatal(S(e),b(e),{cause:e})}let i=r;if(n.authorized!==void 0){let e=h(n.authorized,r);try{i=await w(e,n.signal)}catch(r){if(!n.signal.aborted)throw r;if(!await t(e,n.teardownTimeoutMs))throw T(n.call.toolName,`finalization`,n.teardownTimeoutMs,r);i=V(n.deadline)}}o=x(await R(e,n,i),a)}catch(e){n.program?.abort(e),c=u(e)===`fatal`,s=e,o=x(_(S(e),b(e)),a)}let d=r({callId:n.call.callId,content:[...o.content],isError:o.isError});if(e.history.append({kind:`tool-result`,callId:n.call.callId,message:d,result:o}),await y(e,{type:`tool-result`,call:n.call,result:o,trace:n.trace}),await y(e,{type:`span-end`,trace:n.trace,at:C(),status:o.isError?`error`:`success`,output:o.isError?{error:o.error}:o.value,...o.isError?{error:{type:`ToolError`,message:o.error.message,code:o.error.code}}:{}}),o.additionalContext!==void 0&&e.history.append({kind:`user`,message:i({content:[...o.additionalContext],source:{kind:`app`,producer:`tool:${n.call.toolName}`}})}),c)throw s;return o}async function R(e,t,n){let r=e.maxResultTokens,i=e.catalog.get(t.call.toolName)?.maxOutputTokens,c=r===void 0?i:i===void 0?r:Math.min(r,i);if(c===void 0)return n;let l=a(n.content);if(l<=c)return n;let u=n.content.filter(e=>e.type===`text`);if(u.length===0)return n;let d=u.map(e=>e.text).join(`
1
+ import{detachedFrozen as e}from"../../primitives/snapshot.js";import{waitForSettlement as t}from"../../async/settlement.js";import{createSpanId as n}from"../../observation/context.js";import{createToolResultMessage as r,createUserMessage as i}from"../../message/message.js";import{estimateTextBlockTokens as a,previewForSpill as o,truncateMiddleToTokens as s}from"../tool/output-budget.js";import{TOOL_ERROR_CODES as c,ToolError as l,toolErrorDisposition as u}from"../tool/errors.js";import{NESTED_TOOL_ERROR_CODES as d,attachNestedToolPort as f}from"../tool/nested.js";import{authorizeToolCall as p,dispatchAuthorizedToolCall as m,finalizeToolCall as h,prepareToolCall as g,toolFailure as _}from"../tool/pipeline.js";import{createToolAdmission as v}from"./admission.js";import{emitEvent as y,errorCode as b,immutableResult as x,messageOf as S,now as C,raceWithSignal as w,teardownFailure as T,withApprovalEvents as E}from"./tool-call-support.js";import{ProgramRun as D,validPrograms as O}from"./program.js";async function k(e){return await A(e)}async function A(e,t={}){let n=H(e.maxParallel??8,`maxParallel`),r=H(e.maxResultBytes??4194304,`maxResultBytes`),i=H(e.maxDurationMs??6e5,`maxDurationMs`),a=H(e.teardownTimeoutMs??3e4,`teardownTimeoutMs`),o=Object.freeze(e.calls.map(B)),s=v(t.admissionLimit??Math.max(0,e.dispatchLimit??o.length)),c={admission:s,maxDurationMs:i,teardownTimeoutMs:a,maxResultBytes:r,programs:O(t.programs),programResults:t.programResults},l=[],u=0,d=0,f,p=0,m;for(;p<o.length;){let i=o[p];if(i===void 0)break;let a=m??j(e,i);if(m=void 0,a.mode===`exclusive`){let n=await M(e,a,c,t);u+=+!!n.dispatched,d+=+(n.declined===!0);let o=await L(e,n,r);l.push(o),f===void 0&&!o.isError&&o.concludesTurn&&(f=i.toolName),p++;continue}let s=[],h=new AbortController,g={...e,signal:AbortSignal.any([e.signal,h.signal])},_=a;try{for(;p<o.length&&s.length<n&&o[p]!==void 0;){let e=_;if(e.mode!==`parallel`)break;let r=await M(g,e,c,t);u+=+!!r.dispatched,d+=+(r.declined===!0),s.push(r),p++;let i=o[p];i!==void 0&&s.length<n&&(_=j(g,i),_.mode!==`parallel`&&(m=_))}}catch(t){throw h.abort(t),await I(e,s,r),t}if(s.length===0)continue;let v,y=!1;for(let t of s)try{let n=await L(e,t,r);l.push(n),f===void 0&&!n.isError&&n.concludesTurn&&(f=t.call.toolName)}catch(e){y||(v=e),y=!0,h.abort(e)}if(y)throw v}return{results:Object.freeze(l),concluded:f!==void 0,...f===void 0?{}:{concludedBy:f},dispatched:u,budgeted:s.budgeted,declined:d}}function j(e,t){return g({catalog:e.catalog,call:t,position:e.position,signal:e.signal,...e.logger===void 0?{}:{logger:e.logger},...e.interceptors===void 0?{}:{interceptors:e.interceptors},...e.approvals===void 0?{}:{approvals:e.approvals}})}async function M(e,t,r,i){let{teardownTimeoutMs:a}=r,o=e.catalog.get(t.options.call.toolName),s=o?.awaitsPerson===!0?o.timeoutMs:r.maxDurationMs,l=s===void 0?new AbortController().signal:AbortSignal.timeout(s),u=AbortSignal.any([e.signal,l]),f={...t,options:{...t.options,signal:u,teardownTimeoutMs:a},context:{...t.context,signal:u}},p=f.options.call,m={traceId:e.parentTrace.traceId,spanId:n(),parentSpanId:e.parentTrace.spanId},h=!e.signal.aborted&&!u.aborted?e.recover?.(p):void 0;if(e.history.append({kind:`tool-call`,callId:p.callId,name:p.toolName,rawArguments:p.rawArguments}),await y(e,{type:`span-start`,trace:m,at:C(),name:`execute_tool ${p.toolName}`,kind:`execute_tool`,attributes:{"gen_ai.operation.name":`execute_tool`,"gen_ai.tool.name":p.toolName,"gen_ai.tool.call.id":p.callId,...h===void 0?{}:{"sdk.tool.recovered":!0}},input:p.rawArguments}),await y(e,{type:`tool-call`,call:p,trace:m}),e.signal.aborted)return{call:p,trace:m,signal:u,deadline:l,teardownTimeoutMs:a,dispatched:!1,pending:Promise.resolve(_(`the call was cancelled before it started`,c.ABORTED_BEFORE_DISPATCH))};if(u.aborted)return{call:p,trace:m,signal:u,deadline:l,teardownTimeoutMs:a,dispatched:!1,pending:Promise.resolve(V(l,s))};let g=i.restrict?.(p);if(g!==void 0)return{call:p,trace:m,signal:u,deadline:l,teardownTimeoutMs:a,dispatched:!1,declined:!0,pending:Promise.resolve(P(g))};if(h!==void 0)return{call:p,trace:m,signal:u,deadline:l,teardownTimeoutMs:a,dispatched:!1,recovered:!0,pending:Promise.resolve(h)};let v=e.catalog.get(p.toolName)?.budgetExempt===!0,b=v?void 0:i.decline?.(p);if(b!==void 0)return{call:p,trace:m,signal:u,deadline:l,teardownTimeoutMs:a,dispatched:!1,declined:!0,pending:Promise.resolve(P(b))};let x=r.programs.get(p.toolName);if(x!==void 0&&(v||t.mode!==`exclusive`))return{call:p,trace:m,signal:u,deadline:l,teardownTimeoutMs:a,dispatched:!1,pending:Promise.resolve(_(`this program tool must be exclusive and must not be budget-exempt`,d.CONFIGURATION))};let S=r.admission.reserve(v);if(S===void 0)return{call:p,trace:m,signal:u,deadline:l,teardownTimeoutMs:a,dispatched:!1,declined:!0,pending:Promise.resolve(P(e.declineReason??`tool-calls`))};try{return await N(e,f,p,m,u,l,S,r,x,i)}finally{S.release()}}async function N(e,n,r,i,a,o,s,u,d,h){let{maxDurationMs:g,teardownTimeoutMs:v}=u;if(e.signal.aborted)return{call:r,trace:i,signal:a,deadline:o,teardownTimeoutMs:v,dispatched:!1,pending:Promise.resolve(_(`the call was cancelled before it started`,c.ABORTED_BEFORE_DISPATCH))};let y=p(E(e,n,i)),b;try{b=await w(y,a)}catch(e){if(!a.aborted)throw e;if(!await t(y,v))throw T(r.toolName,`authorization`,v,e);return{call:r,trace:i,signal:a,deadline:o,teardownTimeoutMs:v,dispatched:!1,pending:Promise.resolve(V(o,g))}}if(b.kind===`final`)return{call:r,trace:i,signal:a,deadline:o,teardownTimeoutMs:v,dispatched:!1,pending:Promise.resolve(b.result)};try{let n=Promise.resolve(e.checkpoint?.({kind:`before-tool-dispatch`,call:r,snapshot:e.history.snapshot(),signal:a,...e.logger===void 0?{}:{logger:e.logger}}));try{await w(n,a)}catch(e){if(!a.aborted)throw e;if(!await t(n,v))throw T(r.toolName,`checkpoint`,v,e)}}catch(e){if(e instanceof l&&e.code===c.TEARDOWN_TIMEOUT)throw e;return{call:r,trace:i,signal:a,deadline:o,teardownTimeoutMs:v,dispatched:!1,pending:Promise.resolve(_(`history checkpoint failed: ${S(e)}`,c.CHECKPOINT_FAILED))}}if(a.aborted)return{call:r,trace:i,signal:a,deadline:o,teardownTimeoutMs:v,dispatched:!1,pending:Promise.resolve(V(o,g))};let x=d===void 0?void 0:new D(e,u,d,{call:r,trace:i,signal:a});x!==void 0&&f(b.call,x.port,e=>x.bindExecutionSignal(e)),s.confirm();let C=b.call.tool.awaitsPerson===!0;h.onToolActivity?.(C,!0);let O=m(b.call),k=()=>{h.onToolActivity?.(C,!1)};return O.then(k,k),{call:r,trace:i,signal:a,deadline:o,teardownTimeoutMs:v,authorized:b.call,dispatched:!0,...x===void 0?{}:{program:x},pending:O}}function P(e){return{isError:!1,value:void 0,content:[{type:`text`,text:F(e)}],meta:{declined:!0,reason:e}}}function F(e){let t=` Answer now from what you already have, and say plainly what is unverified or unfinished.`;switch(e){case`tool-calls`:return`This call was not run: the turn has spent its tool-call budget. Further work calls will not run either, so do not retry it.`+t;case`repeated-tool-call`:return`This call was not run: it repeats a call already made with the same arguments, and repeating it cannot produce a new result. Change approach or finish.`+t;case`tool-call-cycle`:return`This call was not run: the same sequence of calls has repeated several times without progress. Break the cycle rather than re-entering it.`+t;case`tokens`:return`This call was not run: the turn has spent its token budget.`+t;case`time`:return`This call was not run: the turn has spent its time budget.`+t;case`consecutive-tool-errors`:return`This call was not run: too many calls in a row have failed. Something in the approach is wrong, not the individual call.`+t;case`steps`:return`This call was not run: the turn has no model steps left.`+t;case`usage-required`:return`This call was not run: the run policy requires provider usage reporting that the last model call did not supply.`+t}}async function I(e,t,n){for(let r of t)try{await L(e,r,n)}catch{}}async function L(e,n,a){let o,s,c=!1;try{let r;try{r=await w(n.pending,n.signal)}catch(e){if(!n.signal.aborted)throw e;if(!await t(n.pending,n.teardownTimeoutMs))throw T(n.call.toolName,`execution`,n.teardownTimeoutMs,e);r=V(n.deadline)}if(n.program!==void 0){if(!await n.program.close(n.teardownTimeoutMs))throw T(n.call.toolName,`nested call`,n.teardownTimeoutMs,void 0);let e=n.program.fatal;if(e!==void 0)throw u(e)===`fatal`?e:l.fatal(S(e),b(e),{cause:e})}let i=r;if(n.authorized!==void 0){let e=h(n.authorized,r);try{i=await w(e,n.signal)}catch(r){if(!n.signal.aborted)throw r;if(!await t(e,n.teardownTimeoutMs))throw T(n.call.toolName,`finalization`,n.teardownTimeoutMs,r);i=V(n.deadline)}}o=x(await R(e,n,i),a)}catch(e){n.program?.abort(e),c=u(e)===`fatal`,s=e,o=x(_(S(e),b(e)),a)}let d=r({callId:n.call.callId,content:[...o.content],isError:o.isError});if(e.history.append({kind:`tool-result`,callId:n.call.callId,message:d,result:o}),await y(e,{type:`tool-result`,call:n.call,result:o,trace:n.trace,...n.declined===!0?{declined:!0}:{},...n.recovered===!0?{recovered:!0}:{},...n.dispatched?{}:{dispatched:!1}}),await y(e,{type:`span-end`,trace:n.trace,at:C(),status:o.isError?`error`:`success`,output:o.isError?{error:o.error}:o.value,...o.isError?{error:{type:`ToolError`,message:o.error.message,code:o.error.code}}:{}}),o.additionalContext!==void 0&&e.history.append({kind:`user`,message:i({content:[...o.additionalContext],source:{kind:`app`,producer:`tool:${n.call.toolName}`}})}),c)throw s;return o}async function R(e,t,n){let r=e.maxResultTokens,i=e.catalog.get(t.call.toolName)?.maxOutputTokens,c=r===void 0?i:i===void 0?r:Math.min(r,i);if(c===void 0)return n;let l=a(n.content);if(l<=c)return n;let u=n.content.filter(e=>e.type===`text`);if(u.length===0)return n;let d=u.map(e=>e.text).join(`
2
2
  `),f=e.resultOverflow??`auto`,p=e.spillStore;if(f!==`truncate`&&p!==void 0)try{let e=await p.save(d,{toolName:t.call.toolName,callId:String(t.call.callId)});return z(n,`${o(d,Math.max(1,Math.floor(c*.75)))}\n\n[Output exceeded this call's budget of ${String(c)} estimated tokens. The full ${String(e.bytes)} bytes are saved. ${e.retrieval}]`,{outputSpilled:{locator:e.locator,bytes:e.bytes,estimatedTokens:l}})}catch{}let m=s(d,c);return z(n,m.text+`\n\n[Output was ${String(m.originalTokens)} estimated tokens, over this call's budget of ${String(c)}. Omitted output does not mean the operation failed. Check an existing receipt or current state; repeat the operation only when the host confirms it is safe.]`,{outputTruncated:{estimatedTokens:m.originalTokens,budget:c}})}function z(e,t,n){let r=!1,i=[];for(let n of e.content){if(n.type!==`text`){i.push(n);continue}r||(r=!0,i.push({type:`text`,text:t}))}return{...e,content:i,meta:{...e.meta,...n}}}function B(t){if(typeof t.callId!=`string`||t.callId.length===0||typeof t.toolName!=`string`||t.toolName.length===0||typeof t.rawArguments!=`string`)throw TypeError(`tool call identity, name, and raw arguments must be strings`);return e(t)}function V(e,t){let n=t===void 0?`configured time limit`:`${t}ms time limit`;return e.aborted?_(`the tool exceeded its ${n}`,c.TIMEOUT):_(`the call was cancelled`,c.ABORTED)}function H(e,t){if(!Number.isInteger(e)||e<1)throw RangeError(`${t} must be a positive integer`);return e}export{k as runToolCalls,A as scheduleToolCalls};
3
3
  //# sourceMappingURL=schedule.js.map