@north-light/cli 0.3.570 → 0.3.572

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 (51) hide show
  1. package/bin/runtime-selector.mjs +15 -0
  2. package/dist/api/contract.d.ts +1 -1
  3. package/dist/api/contract.js +1 -1
  4. package/dist/api/dto/broker-ops.d.ts +3 -0
  5. package/dist/api/dto/recovery.d.ts +7 -0
  6. package/dist/api/errors.d.ts +3 -0
  7. package/dist/api/errors.js +1 -1
  8. package/dist/builtin-memory/crouter-sdk/release-notes.md +7 -0
  9. package/dist/commands/dashboard.js +3 -1
  10. package/dist/core/auth-file.d.ts +2 -0
  11. package/dist/core/auth-file.js +1 -1
  12. package/dist/core/canvas/recovery.d.ts +3 -0
  13. package/dist/core/canvas/recovery.js +2 -2
  14. package/dist/core/canvas/schema-pg/008-import.sql +126 -0
  15. package/dist/core/canvas/schema-version.d.ts +1 -1
  16. package/dist/core/canvas/schema-version.js +1 -1
  17. package/dist/core/command.d.ts +2 -3
  18. package/dist/core/command.js +6 -6
  19. package/dist/core/llm/run.js +2 -2
  20. package/dist/core/model-auth/readiness.js +1 -1
  21. package/dist/core/providers/files.js +1 -1
  22. package/dist/core/runs/operations.js +6 -6
  23. package/dist/core/runtime/blaxel-environment.d.ts +2 -0
  24. package/dist/core/runtime/blaxel-environment.js +1 -0
  25. package/dist/core/runtime/broker/fault-retry.d.ts +4 -0
  26. package/dist/core/runtime/broker/fault-retry.js +1 -1
  27. package/dist/core/runtime/broker/rebind.d.ts +1 -0
  28. package/dist/core/runtime/broker/rebind.js +1 -1
  29. package/dist/core/runtime/nodes.js +1 -1
  30. package/dist/core/runtime/revive.js +2 -2
  31. package/dist/core/runtime/spawn.js +2 -2
  32. package/dist/core/runtime/warm-pool.js +1 -1
  33. package/dist/core/spaces/process.js +1 -1
  34. package/dist/core/spaces/space.d.ts +2 -1
  35. package/dist/core/spaces/space.js +2 -2
  36. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  37. package/dist/daemon/api/handlers/modelauth.js +1 -1
  38. package/dist/daemon/reconcilers/action-lane.js +1 -1
  39. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  40. package/dist/daemon/reconcilers/node-lifecycle/launch-failure.d.ts +1 -0
  41. package/dist/daemon/reconcilers/node-lifecycle/launch-failure.js +1 -0
  42. package/dist/daemon/reconcilers/node-lifecycle/node-person.d.ts +9 -0
  43. package/dist/daemon/reconcilers/node-lifecycle/node-person.js +1 -0
  44. package/dist/daemon/reconcilers/node-lifecycle/remote-wake.d.ts +0 -2
  45. package/dist/daemon/reconcilers/node-lifecycle/remote-wake.js +1 -1
  46. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  47. package/dist/pi-extensions/canvas-inbox-watcher.js +2 -2
  48. package/docs/sdk/release-notes.md +7 -0
  49. package/package.json +8 -3
  50. package/packages/crouter-identity/package.json +1 -1
  51. package/runtime.lock.json +17 -13
@@ -1,3 +1,3 @@
1
- var Ae=Object.defineProperty;var c=(e,t)=>Ae(e,"name",{value:t,configurable:!0});import{randomUUID as Re}from"node:crypto";import{streamSimple as $e}from"@earendil-works/pi-ai/compat";import{probeRouteAvailability as Ie}from"../model-routes-pool.js";import{APP_FAMILY as Ce,expandModelCandidates as ue,parseModelSpec as fe}from"../model-routes.js";import{readMergedLaunchConfig as me}from"../config.js";import{openModelRegistry as Oe}from"../runtime/model-registry.js";import{MAX_RATE_LIMIT_COOLDOWN_MS as pe,coolingUntilFor as he,isManagedProvider as K,markSubscriptionRateLimited as Se,markSubscriptionSuccess as Le,readSubscriptionPool as Ee,retryAfterMsFromHeaders as z,retryAfterMsFromError as Fe,refreshSubscriptionCredential as Ne,subscriptionNeedsSuccessWrite as De}from"../subscription-state.js";import{classifyRateLimit as Pe,describeRateLimitScope as _e,rateLimitHeaders as Te}from"../rate-limit-scope.js";import{RunError as s}from"../runs/operations.js";import{recognizeProviderError as re}from"../provider-error-recognition.js";import{isSafetyRefusal as Je}from"./refusal.js";import{findRefusal as We,payerOf as ge,refusalError as Ue,refusedMark as Be,writeCharge as ye}from"../ledger/index.js";import{personIdAsync as He}from"../canvas/person.js";import{getNode as we}from"../canvas/canvas.js";import{outboundToken as Ke}from"../providers/mint.js";import{discardFile as ze}from"../providers/token-cache.js";import{ProviderError as Xe}from"../providers/errors.js";import{appCandidates as Ge}from"./app-rungs.js";function Ye(e){return typeof e=="string"||e===null||Array.isArray(e)&&e.every(t=>t&&typeof t=="object"&&(t.type==="text"&&typeof t.text=="string"||t.type==="image_url"&&typeof t.image_url?.url=="string"&&/^data:image\/(png|jpeg|gif|webp);base64,[A-Za-z0-9+/]+={0,2}$/.test(t.image_url.url)))}c(Ye,"validContent");function be(e){return Array.isArray(e)?e.map(t=>{if(t.type==="text")return t;const[,n,i]=/^data:(image\/(?:png|jpeg|gif|webp));base64,(.*)$/.exec(t.image_url.url);return{type:"image",mimeType:n,data:i}}):e??""}c(be,"imageContent");function Ze(e,t){const n=(e instanceof Error?e.message:String(e)).split("; stack=",1)[0],i=re({message:n}).kind;return i!=="connection"&&i!=="connection-only"?e:new s(503,"upstream_model_unavailable",n.slice(0,500),void 0,{served_model:t})}c(Ze,"refreshFailure");function Mt(e){if(!e||typeof e!="object"||Array.isArray(e))throw new s(400,"invalid_request","body must be an object");const t=e;if(!Array.isArray(t.messages)||!t.messages.every(n=>n&&typeof n=="object"&&["system","user","assistant","tool"].includes(n.role)&&Ye(n.content)))throw new s(400,"invalid_request","messages must be chat messages","messages");if(t.messages.some(n=>["system","assistant"].includes(n.role)&&typeof n.content!="string"&&n.content!==null))throw new s(400,"invalid_request","system and assistant content must be text","messages");if(t.model!==void 0&&typeof t.model!="string")throw new s(400,"invalid_request","model must be a string","model");if(t.model_policy!==void 0&&!["exact","substitute"].includes(t.model_policy))throw new s(400,"invalid_request","invalid model_policy","model_policy");if(t.payer!==void 0&&!["user","app"].includes(t.payer))throw new s(400,"invalid_request","invalid payer","payer");if(t.reasoning_effort!==void 0&&!["minimal","low","medium","high","xhigh","max"].includes(t.reasoning_effort))throw new s(400,"invalid_request","invalid reasoning_effort","reasoning_effort");if(t.stream!==void 0&&typeof t.stream!="boolean")throw new s(400,"invalid_request","stream must be boolean","stream");if(t.tools!==void 0&&(!Array.isArray(t.tools)||!t.tools.every(n=>n?.type==="function"&&typeof n.function?.name=="string"&&n.function.name.length>0&&(n.function.description===void 0||typeof n.function.description=="string")&&(n.function.parameters===void 0||n.function.parameters!==null&&typeof n.function.parameters=="object"&&!Array.isArray(n.function.parameters)&&n.function.parameters.type==="object"))))throw new s(400,"invalid_request","invalid tools","tools");if(t.tool_choice!==void 0&&t.tool_choice!=="auto"&&t.tool_choice!=="none"&&t.tool_choice!=="required"&&(typeof t.tool_choice!="object"||t.tool_choice===null||t.tool_choice.type!=="function"||typeof t.tool_choice.function?.name!="string"))throw new s(400,"invalid_request","invalid tool_choice","tool_choice");if(t.messages.some(n=>n.role==="assistant"&&n.tool_calls!==void 0&&(!Array.isArray(n.tool_calls)||!n.tool_calls.every(i=>i&&typeof i.id=="string"&&typeof i.function?.name=="string"&&typeof i.function.arguments=="string"&&Qe(i.function.arguments)))))throw new s(400,"invalid_request","invalid assistant tool_calls","messages");if(t.stop!==void 0&&!(typeof t.stop=="string"||Array.isArray(t.stop)&&t.stop.every(n=>typeof n=="string")))throw new s(400,"invalid_request","invalid stop","stop");if(t.seed!==void 0&&!Number.isSafeInteger(t.seed))throw new s(400,"invalid_request","invalid seed","seed");for(const[n,i]of[["temperature",t.temperature],["top_p",t.top_p],["max_tokens",t.max_tokens]])if(i!==void 0&&(typeof i!="number"||!Number.isFinite(i)||n==="temperature"&&(i<0||i>2)||n==="top_p"&&(i<0||i>1)||n==="max_tokens"&&(!Number.isSafeInteger(i)||i<1)))throw new s(400,"invalid_request",`invalid ${n}`,n);if(t.response_format!==void 0){const n=t.response_format;if(!n||typeof n!="object"||Array.isArray(n)||!["text","json_object","json_schema"].includes(n.type)||n.type==="json_schema"&&(typeof n.json_schema?.name!="string"||!n.json_schema.name||!n.json_schema.schema||typeof n.json_schema.schema!="object"||Array.isArray(n.json_schema.schema)))throw new s(400,"invalid_request","invalid response_format","response_format")}if(t.metadata!==void 0&&Buffer.byteLength(JSON.stringify(t.metadata)??"")>4096)throw new s(400,"invalid_request","metadata exceeds 4 KB","metadata");return t}c(Mt,"parseLlmRequest");function Qe(e){try{const t=JSON.parse(e);return t!==null&&typeof t=="object"&&!Array.isArray(t)}catch{return!1}}c(Qe,"isJsonObject");function Ve(e){const t=Date.now(),n=e.messages.map(r=>r.role==="system"?{role:"system",content:r.content??"",timestamp:t}:r.role==="tool"?{role:"toolResult",toolCallId:r.tool_call_id??"",toolName:"",content:typeof r.content=="string"||r.content===null?[{type:"text",text:r.content??""}]:be(r.content),isError:!1,timestamp:t}:r.role==="assistant"?{role:"assistant",content:[...r.content?[{type:"text",text:r.content}]:[],...(r.tool_calls??[]).map(_=>({type:"toolCall",id:_.id,name:_.function.name,arguments:JSON.parse(_.function.arguments)}))],api:"openai-completions",provider:"openai",model:e.model??"",usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:t}:{role:"user",content:be(r.content),timestamp:t}),i=n.findIndex(r=>r.role!=="system"),d=n.slice(0,i<0?n.length:i).map(r=>r.content),y=d.join(`
1
+ var Oe=Object.defineProperty;var c=(e,t)=>Oe(e,"name",{value:t,configurable:!0});import{randomUUID as Se}from"node:crypto";import{streamSimple as Le}from"@earendil-works/pi-ai/compat";import{probeRouteAvailability as Ee}from"../model-routes-pool.js";import{APP_FAMILY as Fe,expandModelCandidates as _e,parseModelSpec as ye}from"../model-routes.js";import{readMergedLaunchConfig as ge}from"../config.js";import{openModelRegistry as Ne}from"../runtime/model-registry.js";import{MAX_RATE_LIMIT_COOLDOWN_MS as we,coolingUntilFor as be,isManagedProvider as Y,markSubscriptionRateLimited as De,markSubscriptionSuccess as Pe,readSubscriptionPool as Te,retryAfterMsFromHeaders as Z,retryAfterMsFromError as Je,refreshSubscriptionCredential as Ke,subscriptionNeedsSuccessWrite as We}from"../subscription-state.js";import{classifyRateLimit as Ue,describeRateLimitScope as ve,rateLimitHeaders as Be}from"../rate-limit-scope.js";import{RunError as s}from"../runs/operations.js";import{recognizeProviderError as le}from"../provider-error-recognition.js";import{isSafetyRefusal as He}from"./refusal.js";import{findRefusal as ze,payerOf as ke,refusalError as Xe,refusedMark as Ge,writeCharge as xe}from"../ledger/index.js";import{storedApiKey as Ye}from"../auth-file.js";import{personIdAsync as Ze}from"../canvas/person.js";import{getNode as qe}from"../canvas/canvas.js";import{outboundToken as Qe}from"../providers/mint.js";import{discardFile as Ve}from"../providers/token-cache.js";import{ProviderError as et}from"../providers/errors.js";import{appCandidates as tt}from"./app-rungs.js";function nt(e){return typeof e=="string"||e===null||Array.isArray(e)&&e.every(t=>t&&typeof t=="object"&&(t.type==="text"&&typeof t.text=="string"||t.type==="image_url"&&typeof t.image_url?.url=="string"&&/^data:image\/(png|jpeg|gif|webp);base64,[A-Za-z0-9+/]+={0,2}$/.test(t.image_url.url)))}c(nt,"validContent");function Ae(e){return Array.isArray(e)?e.map(t=>{if(t.type==="text")return t;const[,o,i]=/^data:(image\/(?:png|jpeg|gif|webp));base64,(.*)$/.exec(t.image_url.url);return{type:"image",mimeType:o,data:i}}):e??""}c(Ae,"imageContent");function ot(e,t){const o=(e instanceof Error?e.message:String(e)).split("; stack=",1)[0],i=le({message:o}).kind;return i!=="connection"&&i!=="connection-only"?e:new s(503,"upstream_model_unavailable",o.slice(0,500),void 0,{served_model:t})}c(ot,"refreshFailure");function Ot(e){if(!e||typeof e!="object"||Array.isArray(e))throw new s(400,"invalid_request","body must be an object");const t=e;if(!Array.isArray(t.messages)||!t.messages.every(o=>o&&typeof o=="object"&&["system","user","assistant","tool"].includes(o.role)&&nt(o.content)))throw new s(400,"invalid_request","messages must be chat messages","messages");if(t.messages.some(o=>["system","assistant"].includes(o.role)&&typeof o.content!="string"&&o.content!==null))throw new s(400,"invalid_request","system and assistant content must be text","messages");if(t.model!==void 0&&typeof t.model!="string")throw new s(400,"invalid_request","model must be a string","model");if(t.model_policy!==void 0&&!["exact","substitute"].includes(t.model_policy))throw new s(400,"invalid_request","invalid model_policy","model_policy");if(t.payer!==void 0&&!["user","app"].includes(t.payer))throw new s(400,"invalid_request","invalid payer","payer");if(t.reasoning_effort!==void 0&&!["minimal","low","medium","high","xhigh","max"].includes(t.reasoning_effort))throw new s(400,"invalid_request","invalid reasoning_effort","reasoning_effort");if(t.stream!==void 0&&typeof t.stream!="boolean")throw new s(400,"invalid_request","stream must be boolean","stream");if(t.tools!==void 0&&(!Array.isArray(t.tools)||!t.tools.every(o=>o?.type==="function"&&typeof o.function?.name=="string"&&o.function.name.length>0&&(o.function.description===void 0||typeof o.function.description=="string")&&(o.function.parameters===void 0||o.function.parameters!==null&&typeof o.function.parameters=="object"&&!Array.isArray(o.function.parameters)&&o.function.parameters.type==="object"))))throw new s(400,"invalid_request","invalid tools","tools");if(t.tool_choice!==void 0&&t.tool_choice!=="auto"&&t.tool_choice!=="none"&&t.tool_choice!=="required"&&(typeof t.tool_choice!="object"||t.tool_choice===null||t.tool_choice.type!=="function"||typeof t.tool_choice.function?.name!="string"))throw new s(400,"invalid_request","invalid tool_choice","tool_choice");if(t.messages.some(o=>o.role==="assistant"&&o.tool_calls!==void 0&&(!Array.isArray(o.tool_calls)||!o.tool_calls.every(i=>i&&typeof i.id=="string"&&typeof i.function?.name=="string"&&typeof i.function.arguments=="string"&&rt(i.function.arguments)))))throw new s(400,"invalid_request","invalid assistant tool_calls","messages");if(t.stop!==void 0&&!(typeof t.stop=="string"||Array.isArray(t.stop)&&t.stop.every(o=>typeof o=="string")))throw new s(400,"invalid_request","invalid stop","stop");if(t.seed!==void 0&&!Number.isSafeInteger(t.seed))throw new s(400,"invalid_request","invalid seed","seed");for(const[o,i]of[["temperature",t.temperature],["top_p",t.top_p],["max_tokens",t.max_tokens]])if(i!==void 0&&(typeof i!="number"||!Number.isFinite(i)||o==="temperature"&&(i<0||i>2)||o==="top_p"&&(i<0||i>1)||o==="max_tokens"&&(!Number.isSafeInteger(i)||i<1)))throw new s(400,"invalid_request",`invalid ${o}`,o);if(t.response_format!==void 0){const o=t.response_format;if(!o||typeof o!="object"||Array.isArray(o)||!["text","json_object","json_schema"].includes(o.type)||o.type==="json_schema"&&(typeof o.json_schema?.name!="string"||!o.json_schema.name||!o.json_schema.schema||typeof o.json_schema.schema!="object"||Array.isArray(o.json_schema.schema)))throw new s(400,"invalid_request","invalid response_format","response_format")}if(t.metadata!==void 0&&Buffer.byteLength(JSON.stringify(t.metadata)??"")>4096)throw new s(400,"invalid_request","metadata exceeds 4 KB","metadata");return t}c(Ot,"parseLlmRequest");function rt(e){try{const t=JSON.parse(e);return t!==null&&typeof t=="object"&&!Array.isArray(t)}catch{return!1}}c(rt,"isJsonObject");function it(e){const t=Date.now(),o=e.messages.map(r=>r.role==="system"?{role:"system",content:r.content??"",timestamp:t}:r.role==="tool"?{role:"toolResult",toolCallId:r.tool_call_id??"",toolName:"",content:typeof r.content=="string"||r.content===null?[{type:"text",text:r.content??""}]:Ae(r.content),isError:!1,timestamp:t}:r.role==="assistant"?{role:"assistant",content:[...r.content?[{type:"text",text:r.content}]:[],...(r.tool_calls??[]).map(h=>({type:"toolCall",id:h.id,name:h.function.name,arguments:JSON.parse(h.function.arguments)}))],api:"openai-completions",provider:"openai",model:e.model??"",usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:t}:{role:"user",content:Ae(r.content),timestamp:t}),i=o.findIndex(r=>r.role!=="system"),l=o.slice(0,i<0?o.length:i).map(r=>r.content),g=l.join(`
2
2
 
3
- `),h=e.tools?.map(({function:r})=>({name:r.name,description:r.description??"",parameters:r.parameters??{type:"object",properties:{}}}));return{...y?{systemPrompt:y}:{},messages:n.slice(d.length),...h?{tools:h}:{}}}c(Ve,"contextOf");function ve(e,t,n,i){const d=c(()=>{const h=me(n,i),r=Object.values({...h.modelRoutes??{},...h.legacyModelRoutes??{}});return r.length?[h.modelLadders.defaultProvider,...h.modelRouting?.familyOrder??[],...r.map(_=>_.family)].find(_=>r.some($=>$.family===_)):h.modelLadders.defaultProvider??"anthropic"},"ownerFamily");if(!e){const h=d();return{kind:"logical",family:h,strength:"strong",spec:`${h}/strong`}}const y=/^([^/]+)\/(ultra|strong|medium|light)$/.exec(e);if(y){if(y[1]===Ce){const h=d();return{kind:"logical",family:h,strength:y[2],spec:`${h}/${y[2]}`}}return{kind:"logical",family:y[1],strength:y[2],spec:e}}return{kind:t==="exact"?"exact":"concrete",spec:e}}c(ve,"requestFor");function et(e,t){const{input:n,output:i,cacheRead:d,cacheWrite:y}=e.cost;return n===0&&i===0&&d===0&&y===0?null:Number.isFinite(t)&&t>=0?t:null}c(et,"usdEquivalent");function tt(e,t){return e.compat?.allowedFallbackModels?.find(i=>i.provider===e.provider&&i.model===t)}c(tt,"allowedFallback");function jt(e){return e?{payer:e.payer??"user",sub:e.sub,grantee:e.grantee,inference_endpoint:e.inference_endpoint??null}:void 0}c(jt,"llmCallerOf");function ot(e){return e instanceof Xe?e.code==="server_error"?new s(503,"upstream_model_unavailable",e.message):new s(404,"model_unavailable",e.message):e}c(ot,"mintFailure");const nt=/\bmodel is not supported when using Codex with a ChatGPT account\b/i;function rt(e,t,n){if(!(e!=="openai-codex"||t===void 0||!nt.test(t)))return new s(404,"model_unavailable",t,void 0,{served_model:n})}c(rt,"codexAccountModelRejection");function it(e){return e.get("request-id")??e.get("x-request-id")}c(it,"vendorRequestId");async function At(e,t,n,i,d,y,h){const r=y?.payer==="app"?y:void 0;if(e.payer==="app"&&!r)throw new s(403,"payer_not_app","this grant is not app-paid");if(e.payer==="user"&&r)throw new s(400,"invalid_request","this grant is app-paid; payer cannot be user","payer");if(r&&!r.inference_endpoint)throw new s(404,"model_unavailable",`${r.grantee} is app-paid but its grant carries no inference endpoint`);const _=r?.inference_endpoint??void 0,$=d===void 0?null:r?.sub??d.sub??await He(),E=await Oe(),ie=c(u=>u.routeId!=="concrete"&&u.routeId!=="exact","configured"),se=c(u=>{const g=E.find(u.providerId,u.modelId);return g!==void 0&&(!e.reasoning_effort||g.reasoning)&&(e.seed===void 0&&e.response_format===void 0||g.api==="openai-completions")&&(e.stop===void 0||["openai-completions","anthropic-messages"].includes(g.api))},"matchesFeatures"),xe=c(async()=>{const u=ve(e.model,e.model_policy,i?.cwd,i?.profileId),g=(await ue(u.kind==="exact"?{kind:"concrete",spec:u.spec}:u,i?.cwd,i?.profileId)).filter(ie);let a;if(u.kind==="logical")a=e.model_policy==="exact"?g.filter(f=>f.family===u.family&&f.strength===u.strength).slice(0,1):g;else{const f=fe(u.spec),A=g.filter(q=>q.providerId===f?.providerId&&q.modelId===f.modelId&&(e.model_policy!=="exact"||q.thinkingLevel===f.thinkingLevel)&&se(q));if(e.model_policy==="exact")a=A.slice(0,1);else if(A.length)a=A;else{const q=me(i?.cwd,i?.profileId),k=[...Object.values(q.modelRoutes??{}).flatMap(v=>Object.entries(v.models)),...[q.modelLadders.anthropic,q.modelLadders.openai].flatMap(v=>Object.entries(v))].find(([,v])=>v===u.spec)?.[0],m=ve(void 0,"substitute",i?.cwd,i?.profileId);a=k&&m.kind==="logical"?(await ue({...m,strength:k,spec:u.spec},i?.cwd,i?.profileId)).filter(v=>ie(v)&&v.strength===k):[]}}return a},"ownerCandidates");let C;if(_?C=Ge(_,e.model,e.model_policy==="exact").flatMap((u,g)=>{const a=fe(u.model);return a?[{routeId:"app",credentialSource:"app",family:"app",strength:u.strength,...a,rank:g}]:[]}):C=await xe(),C=C.filter(se),C.length===0)throw e.model_policy==="exact"?new s(400,"substitution_refused","no eligible model route is configured"):new s(404,"model_unavailable","no eligible model route is configured");const D=`chatcmpl-${Re()}`;let O=1/0,b,X,G;const ae=c(async()=>h??(d?.node?(await we(d.node))?.caused_by??null:null)??(d?.run?(await we(d.run))?.caused_by??null:null),"causeOf");for(const u of C){if(!r&&!(await Ie(u,E)).authenticated)continue;const g=E.find(u.providerId,u.modelId);if(!g)continue;const a=_?{...g,baseUrl:`${_.base_url}/${g.provider}`}:g,f=u.providerId,A=!r&&K(f)?(await Ee(f)).filter(k=>!k.authFailure):[],q=A.filter(k=>he(k,a.id)<=Date.now());if(A.length&&!q.length){const k=Math.min(...A.map(m=>he(m,a.id)));k<O&&(O=k,X=`${a.provider}/${a.id}`);continue}const le=r?[void 0,void 0]:A.length?q:[void 0];for(const[k,m]of le.entries()){const v=Date.now();let de=m?.access;if(m&&m.expires<=Date.now()&&K(f)){const o=E.getProvider(f)?.auth.oauth;if(!o)throw new s(503,"upstream_model_unavailable",`no OAuth refresh for ${f}`,void 0,{served_model:`${a.provider}/${a.id}`});de=(await Ne(f,m.label,async(x,ce)=>{const H=await o.refresh({type:"oauth",refresh:x,access:"",expires:0,...ce?{clientId:ce}:{}},t??new AbortController().signal).catch(je=>{throw Ze(je,`${a.provider}/${a.id}`)}),ne=H.clientId;return{refresh:H.refresh,access:H.access,expires:H.expires,...typeof ne=="string"&&ne?{clientId:ne}:{}}})).access}const ke=Ve(e),S=m||r?void 0:await E.getApiKeyAndHeaders(a);if(S&&!S.ok)continue;const p=`${a.provider}/${a.id}`,L=e.model??p,R=r?ge({call:"model",route:"endpoint",grantee:r.grantee}):$===null?null:ge({call:"model",route:m?"subscription":"key",sub:$});if(d!==void 0&&R!==null){const o=await We({scope:"call",payer:R.payer,funding:R.funding,sub:$,grantee:d.grantee,provider:f});if(o!==null){await ye({request:d.request??D,kind:"model",what:p,usd:null,payer:R.payer,funding:R.funding,sub:$,grantee:d.grantee,node:d.node??null,run:d.run??null,provider:f,causedBy:await ae(),refused:Be(o)}),G??=o;break}}let P;if(r&&_)try{P=await Ke({audience:_.base_url,sub:r.sub,grantee:r.grantee,initiating_app:r.grantee,scope:["crtr:llm"]},{signal:t})}catch(o){throw ot(o)}let j=!1,F,Y=null,M=3e4,I;const Z=[],Q=[],T=[];let l,J;const W=c((o,w=null)=>({id:D,object:"chat.completion.chunk",created:Math.floor(v/1e3),model:p,served_model:p,requested_model:L,substituted:L!==p&&!/^([^/]+)\/(ultra|strong|medium|light)$/.test(L),choices:[{index:0,delta:o,finish_reason:w}]}),"chunk"),U=c(o=>{Z.push(o),n?.(o)},"emit"),qe=$e(a,ke,{apiKey:P?.access_token??de??(S?.ok?S.apiKey:void 0),...S?.ok?{headers:S.headers}:{},signal:t,reasoning:e.reasoning_effort??u.thinkingLevel,...e.temperature!==void 0?{temperature:e.temperature}:{},...e.max_tokens!==void 0?{maxTokens:e.max_tokens}:{},...e.top_p!==void 0?{samplingParams:{top_p:e.top_p}}:{},...e.tool_choice==="none"?{toolChoice:"none"}:{},onPayload:c(o=>{if(!o||typeof o!="object")return;const w=e.tool_choice,x=w==="required"?a.api==="anthropic-messages"?{type:"any"}:"required":typeof w=="object"&&w!==null?a.api==="anthropic-messages"?{type:"tool",name:w.function.name}:w:void 0;return{...o,...x?{tool_choice:x}:{},...e.stop!==void 0?{[a.api==="anthropic-messages"?"stop_sequences":"stop"]:typeof e.stop=="string"?[e.stop]:e.stop}:{},...e.seed!==void 0?{seed:e.seed}:{},...e.response_format!==void 0?{response_format:e.response_format}:{}}},"onPayload"),fetch:c(async(o,w)=>{const x=await fetch(o,w);return F=x.status,Y=it(x.headers)??Y,x.status===429&&(j=!0,I=x.headers,M=z(x.headers)??15e3),x},"fetch"),onResponse:c(o=>{o.status===429&&(j=!0,I=o.headers,M=z(o.headers)??15e3)},"onResponse")});try{for await(const o of qe)o.type==="text_delta"&&(Q.push(o.delta),U(W({content:o.delta}))),o.type==="thinking_delta"&&(T.push(o.delta),U(W({reasoning_content:o.delta}))),o.type==="done"&&(l=o.message),o.type==="error"&&(l=o.error)}catch(o){const w=Fe(o);I===void 0&&o&&typeof o=="object"&&"headers"in o&&Object.keys(Te(o.headers)).length&&(I=o.headers);const x=re({status:o&&typeof o=="object"&&"status"in o?o.status:void 0,message:o instanceof Error?o.message:String(o)});if(r)J=o;else{if(!j&&x.kind!=="rate-limit")throw Z.length?new s(503,"upstream_model_unavailable",o instanceof Error?o.message:String(o),void 0,{served_model:p}):o;j=!0,M=w??M}}if(r){if(F===401){if(P&&ze(P.key),k===0)continue;throw new s(404,"model_unavailable",`${_.base_url} refuses this runtime's tokens`,void 0,{served_model:p})}if(j&&z(I)===void 0)throw new s(503,"upstream_model_unavailable",`${p} was rate-limited without a retry-after`,void 0,{served_model:p});if(!j&&(J!==void 0||F!==void 0&&F>=500))throw new s(503,"upstream_model_unavailable",J instanceof Error?J.message:l?.errorMessage??"inference endpoint failed",void 0,{served_model:p})}if(!j&&l?.stopReason==="error"&&re({message:l.errorMessage}).kind==="rate-limit"&&(j=!0,M=15e3),j){const o=Pe(I,a.id);if(z(I)===void 0&&o.resetAt!==void 0&&(M=Math.max(M,o.resetAt-Date.now())),b={provider:f,model:a.id,...m?{account:m.label}:{},observation:o},console.error(`[llm] 429 from ${p}${m?` account "${m.label}"`:""}: scope=${_e(o.scope)} retry_after_ms=${M} headers=${JSON.stringify(o.headers)}`),m&&K(f)&&await Se(f,m.label,M,v,Date.now(),o.scope),Date.now()+Math.min(M,pe)<O&&(O=Date.now()+Math.min(M,pe),X=p),Q.length||T.length)throw new s(503,"service_unavailable","vendor rate limit after output began",void 0,{served_model:p});if(r)break;continue}const B=Je(l);if(F===400&&e.tool_choice!==void 0&&e.tool_choice!=="auto"&&e.tool_choice!=="none"&&/\btool[_ ]choice\b/i.test(l?.errorMessage??"")&&/not supported|does not support|unsupported|cannot|must be auto/i.test(l?.errorMessage??""))throw new s(400,"invalid_request",l.errorMessage,"tool_choice",{served_model:p});if(l?.stopReason==="error"){const o=rt(a.provider,l.errorMessage,p);if(o)throw o}if(!l||l.stopReason==="error"&&!B||l.stopReason==="aborted")throw new s(503,"upstream_model_unavailable",l?.errorMessage??"model request failed",void 0,{served_model:p});m&&K(f)&&De(m,a.id)&&await Le(f,m.label,v,a.id);const V=l.content.filter(o=>o.type==="toolCall").map(o=>({id:o.id,type:"function",function:{name:o.name,arguments:JSON.stringify(o.arguments)}})),ee=B?"content_filter":l.stopReason==="toolUse"?"tool_calls":l.stopReason==="length"?"length":"stop",te=l.responseModel?tt(a,l.responseModel):void 0,N=te?`${a.provider}/${te.model}`:p,oe={prompt_tokens:l.usage.input,completion_tokens:l.usage.output,total_tokens:l.usage.totalTokens,cache_read_tokens:l.usage.cacheRead,cache_write_tokens:l.usage.cacheWrite,usd_equivalent:et(te??a,l.usage.cost.total),served_model:N};d!==void 0&&R!==null&&await ye({request:d.request??D,kind:"model",what:N,units:{input:l.usage.input,output:l.usage.output,cache_read:l.usage.cacheRead,cache_write:l.usage.cacheWrite},usd:oe.usd_equivalent,payer:R.payer,funding:R.funding,sub:$,grantee:d.grantee,node:d.node??null,run:d.run??null,provider:f,causedBy:await ae(),vendorRef:Y});const Me={id:D,object:"chat.completion",created:Math.floor(v/1e3),model:N,served_model:N,requested_model:L,substituted:L!==N&&!/^([^/]+)\/(ultra|strong|medium|light)$/.test(L),choices:[{index:0,message:{role:"assistant",content:Q.join("")||null,...T.length?{reasoning_content:T.join("")}:{},...V.length?{tool_calls:V}:{},...B?{refusal:l.errorMessage??"Content filtered"}:{}},finish_reason:ee}],usage:oe,...e.metadata!==void 0?{metadata:e.metadata}:{}};for(const[o,w]of V.entries())U(W({tool_calls:[{index:o,...w}]}));return U({...W({},ee),...B?{choices:[{index:0,delta:{},finish_reason:ee,message:{refusal:l.errorMessage??"Content filtered"}}]}:{},usage:oe}),{completion:Me,chunks:Z}}}throw G!==void 0?Ue(G):O!==1/0?new s(429,"all_routes_exhausted","all eligible model routes are rate-limited",void 0,{retry_after_s:Math.max(1,Math.ceil((O-Date.now())/1e3)),served_model:b?`${b.provider}/${b.model}`:X,...b?{rate_limit:{provider:b.provider,model:b.model,...b.account?{account:b.account}:{},scope:_e(b.observation.scope),...b.observation.claim?{claim:b.observation.claim}:{},headers:b.observation.headers}}:{}},void 0,!0):e.model_policy==="exact"?new s(400,"substitution_refused","the requested model is unavailable"):new s(404,"model_unavailable","no usable model route is available")}c(At,"runLlm");export{jt as llmCallerOf,Mt as parseLlmRequest,At as runLlm};
3
+ `),p=e.tools?.map(({function:r})=>({name:r.name,description:r.description??"",parameters:r.parameters??{type:"object",properties:{}}}));return{...g?{systemPrompt:g}:{},messages:o.slice(l.length),...p?{tools:p}:{}}}c(it,"contextOf");function Me(e,t,o,i){const l=c(()=>{const p=ge(o,i),r=Object.values({...p.modelRoutes??{},...p.legacyModelRoutes??{}});return r.length?[p.modelLadders.defaultProvider,...p.modelRouting?.familyOrder??[],...r.map(h=>h.family)].find(h=>r.some($=>$.family===h)):p.modelLadders.defaultProvider??"anthropic"},"ownerFamily");if(!e){const p=l();return{kind:"logical",family:p,strength:"strong",spec:`${p}/strong`}}const g=/^([^/]+)\/(ultra|strong|medium|light)$/.exec(e);if(g){if(g[1]===Fe){const p=l();return{kind:"logical",family:p,strength:g[2],spec:`${p}/${g[2]}`}}return{kind:"logical",family:g[1],strength:g[2],spec:e}}return{kind:t==="exact"?"exact":"concrete",spec:e}}c(Me,"requestFor");function st(e,t){const{input:o,output:i,cacheRead:l,cacheWrite:g}=e.cost;return o===0&&i===0&&l===0&&g===0?null:Number.isFinite(t)&&t>=0?t:null}c(st,"usdEquivalent");function at(e,t){return e.compat?.allowedFallbackModels?.find(i=>i.provider===e.provider&&i.model===t)}c(at,"allowedFallback");function St(e){return e?{payer:e.payer??"user",sub:e.sub,grantee:e.grantee,inference_endpoint:e.inference_endpoint??null}:void 0}c(St,"llmCallerOf");function dt(e){return e instanceof et?e.code==="server_error"?new s(503,"upstream_model_unavailable",e.message):new s(404,"model_unavailable",e.message):e}c(dt,"mintFailure");const lt=/\bmodel is not supported when using Codex with a ChatGPT account\b/i;function ct(e,t,o){if(!(e!=="openai-codex"||t===void 0||!lt.test(t)))return new s(404,"model_unavailable",t,void 0,{served_model:o})}c(ct,"codexAccountModelRejection");function ut(e){return e.get("request-id")??e.get("x-request-id")}c(ut,"vendorRequestId");async function Lt(e,t,o,i,l,g,p){const r=g?.payer==="app"?g:void 0;if(e.payer==="app"&&!r)throw new s(403,"payer_not_app","this grant is not app-paid");if(e.payer==="user"&&r)throw new s(400,"invalid_request","this grant is app-paid; payer cannot be user","payer");if(r&&!r.inference_endpoint)throw new s(404,"model_unavailable",`${r.grantee} is app-paid but its grant carries no inference endpoint`);const h=r?.inference_endpoint??void 0,$=l===void 0?null:r?.sub??l.sub??await Ze(),N=await Ne(),ce=c(u=>u.routeId!=="concrete"&&u.routeId!=="exact","configured"),ue=c(u=>{const _=N.find(u.providerId,u.modelId);return _!==void 0&&(!e.reasoning_effort||_.reasoning)&&(e.seed===void 0&&e.response_format===void 0||_.api==="openai-completions")&&(e.stop===void 0||["openai-completions","anthropic-messages"].includes(_.api))},"matchesFeatures"),je=c(async()=>{const u=Me(e.model,e.model_policy,i?.cwd,i?.profileId),_=(await _e(u.kind==="exact"?{kind:"concrete",spec:u.spec}:u,i?.cwd,i?.profileId)).filter(ce);let a;if(u.kind==="logical")a=e.model_policy==="exact"?_.filter(f=>f.family===u.family&&f.strength===u.strength).slice(0,1):_;else{const f=ye(u.spec),L=_.filter(v=>v.providerId===f?.providerId&&v.modelId===f.modelId&&(e.model_policy!=="exact"||v.thinkingLevel===f.thinkingLevel)&&ue(v));if(e.model_policy==="exact")a=L.slice(0,1);else if(L.length)a=L;else{const v=ge(i?.cwd,i?.profileId),M=[...Object.values(v.modelRoutes??{}).flatMap(x=>Object.entries(x.models)),...[v.modelLadders.anthropic,v.modelLadders.openai].flatMap(x=>Object.entries(x))].find(([,x])=>x===u.spec)?.[0],D=Me(void 0,"substitute",i?.cwd,i?.profileId);a=M&&D.kind==="logical"?(await _e({...D,strength:M,spec:u.spec},i?.cwd,i?.profileId)).filter(x=>ce(x)&&x.strength===M):[]}}return a},"ownerCandidates");let O;if(h?O=tt(h,e.model,e.model_policy==="exact").flatMap((u,_)=>{const a=ye(u.model);return a?[{routeId:"app",credentialSource:"app",family:"app",strength:u.strength,...a,rank:_}]:[]}):O=await je(),O=O.filter(ue),O.length===0)throw e.model_policy==="exact"?new s(400,"substitution_refused","no eligible model route is configured"):new s(404,"model_unavailable","no eligible model route is configured");const J=`chatcmpl-${Se()}`;let S=1/0,b,Q,V;const fe=c(async()=>p??(l?.node?(await qe(l.node))?.caused_by??null:null)??(l?.run?(await qe(l.run))?.caused_by??null:null),"causeOf");for(const u of O){if(!r&&!(await Ee(u,N)).authenticated)continue;const _=N.find(u.providerId,u.modelId);if(!_)continue;const a=h?{..._,baseUrl:`${h.base_url}/${_.provider}`}:_,f=u.providerId,L=!r&&Y(f)?await Te(f):[],v=L.filter(j=>!j.authFailure),ee=v.filter(j=>be(j,a.id)<=Date.now()),M=L.length?await Ye(f):void 0;if(v.length&&!ee.length&&M===void 0){const j=Math.min(...v.map(I=>be(I,a.id)));j<S&&(S=j,Q=`${a.provider}/${a.id}`);continue}const D=r?[void 0,void 0]:v.length||M!==void 0?[...ee,...M!==void 0?["key"]:[]]:[void 0];let x=!1;for(const[j,I]of D.entries()){if(x&&I!=="key")continue;const y=I==="key"?void 0:I,me=I==="key",K=Date.now();let pe=y?.access;if(y&&y.expires<=Date.now()&&Y(f)){const n=N.getProvider(f)?.auth.oauth;if(!n)throw new s(503,"upstream_model_unavailable",`no OAuth refresh for ${f}`,void 0,{served_model:`${a.provider}/${a.id}`});pe=(await Ke(f,y.label,async(k,he)=>{const G=await n.refresh({type:"oauth",refresh:k,access:"",expires:0,...he?{clientId:he}:{}},t??new AbortController().signal).catch(Ce=>{throw ot(Ce,`${a.provider}/${a.id}`)}),de=G.clientId;return{refresh:G.refresh,access:G.access,expires:G.expires,...typeof de=="string"&&de?{clientId:de}:{}}})).access}const Re=it(e),E=y||r||me?void 0:await N.getApiKeyAndHeaders(a);if(E&&!E.ok)continue;const m=`${a.provider}/${a.id}`,F=e.model??m,R=r?ke({call:"model",route:"endpoint",grantee:r.grantee}):$===null?null:ke({call:"model",route:y?"subscription":"key",sub:$});if(l!==void 0&&R!==null){const n=await ze({scope:"call",payer:R.payer,funding:R.funding,sub:$,grantee:l.grantee,provider:f});if(n!==null){if(await xe({request:l.request??J,kind:"model",what:m,usd:null,payer:R.payer,funding:R.funding,sub:$,grantee:l.grantee,node:l.node??null,run:l.run??null,provider:f,causedBy:await fe(),refused:Ge(n)}),V??=n,I!=="key"&&D.includes("key")){x=!0;continue}break}}let W;if(r&&h)try{W=await Qe({audience:h.base_url,sub:r.sub,grantee:r.grantee,initiating_app:r.grantee,scope:["crtr:llm"]},{signal:t})}catch(n){throw dt(n)}let A=!1,P,te=null,q=3e4,C;const ne=[],oe=[],U=[];let d,B;const H=c((n,w=null)=>({id:J,object:"chat.completion.chunk",created:Math.floor(K/1e3),model:m,served_model:m,requested_model:F,substituted:F!==m&&!/^([^/]+)\/(ultra|strong|medium|light)$/.test(F),choices:[{index:0,delta:n,finish_reason:w}]}),"chunk"),z=c(n=>{ne.push(n),o?.(n)},"emit"),$e=Le(a,Re,{apiKey:W?.access_token??pe??(me?M:void 0)??(E?.ok?E.apiKey:void 0),...E?.ok?{headers:E.headers}:{},signal:t,reasoning:e.reasoning_effort??u.thinkingLevel,...e.temperature!==void 0?{temperature:e.temperature}:{},...e.max_tokens!==void 0?{maxTokens:e.max_tokens}:{},...e.top_p!==void 0?{samplingParams:{top_p:e.top_p}}:{},...e.tool_choice==="none"?{toolChoice:"none"}:{},onPayload:c(n=>{if(!n||typeof n!="object")return;const w=e.tool_choice,k=w==="required"?a.api==="anthropic-messages"?{type:"any"}:"required":typeof w=="object"&&w!==null?a.api==="anthropic-messages"?{type:"tool",name:w.function.name}:w:void 0;return{...n,...k?{tool_choice:k}:{},...e.stop!==void 0?{[a.api==="anthropic-messages"?"stop_sequences":"stop"]:typeof e.stop=="string"?[e.stop]:e.stop}:{},...e.seed!==void 0?{seed:e.seed}:{},...e.response_format!==void 0?{response_format:e.response_format}:{}}},"onPayload"),fetch:c(async(n,w)=>{const k=await fetch(n,w);return P=k.status,te=ut(k.headers)??te,k.status===429&&(A=!0,C=k.headers,q=Z(k.headers)??15e3),k},"fetch"),onResponse:c(n=>{n.status===429&&(A=!0,C=n.headers,q=Z(n.headers)??15e3)},"onResponse")});try{for await(const n of $e)n.type==="text_delta"&&(oe.push(n.delta),z(H({content:n.delta}))),n.type==="thinking_delta"&&(U.push(n.delta),z(H({reasoning_content:n.delta}))),n.type==="done"&&(d=n.message),n.type==="error"&&(d=n.error)}catch(n){const w=Je(n);C===void 0&&n&&typeof n=="object"&&"headers"in n&&Object.keys(Be(n.headers)).length&&(C=n.headers);const k=le({status:n&&typeof n=="object"&&"status"in n?n.status:void 0,message:n instanceof Error?n.message:String(n)});if(r)B=n;else{if(!A&&k.kind!=="rate-limit")throw ne.length?new s(503,"upstream_model_unavailable",n instanceof Error?n.message:String(n),void 0,{served_model:m}):n;A=!0,q=w??q}}if(r){if(P===401){if(W&&Ve(W.key),j===0)continue;throw new s(404,"model_unavailable",`${h.base_url} refuses this runtime's tokens`,void 0,{served_model:m})}if(A&&Z(C)===void 0)throw new s(503,"upstream_model_unavailable",`${m} was rate-limited without a retry-after`,void 0,{served_model:m});if(!A&&(B!==void 0||P!==void 0&&P>=500))throw new s(503,"upstream_model_unavailable",B instanceof Error?B.message:d?.errorMessage??"inference endpoint failed",void 0,{served_model:m})}if(!A&&d?.stopReason==="error"&&le({message:d.errorMessage}).kind==="rate-limit"&&(A=!0,q=15e3),A){const n=Ue(C,a.id);if(Z(C)===void 0&&n.resetAt!==void 0&&(q=Math.max(q,n.resetAt-Date.now())),b={provider:f,model:a.id,...y?{account:y.label}:{},observation:n},console.error(`[llm] 429 from ${m}${y?` account "${y.label}"`:""}: scope=${ve(n.scope)} retry_after_ms=${q} headers=${JSON.stringify(n.headers)}`),y&&Y(f)&&await De(f,y.label,q,K,Date.now(),n.scope),Date.now()+Math.min(q,we)<S&&(S=Date.now()+Math.min(q,we),Q=m),oe.length||U.length)throw new s(503,"service_unavailable","vendor rate limit after output began",void 0,{served_model:m});if(r)break;continue}const X=He(d);if(P===400&&e.tool_choice!==void 0&&e.tool_choice!=="auto"&&e.tool_choice!=="none"&&/\btool[_ ]choice\b/i.test(d?.errorMessage??"")&&/not supported|does not support|unsupported|cannot|must be auto/i.test(d?.errorMessage??""))throw new s(400,"invalid_request",d.errorMessage,"tool_choice",{served_model:m});if(d?.stopReason==="error"){const n=ct(a.provider,d.errorMessage,m);if(n)throw n}if(!d||d.stopReason==="error"&&!X||d.stopReason==="aborted")throw new s(503,"upstream_model_unavailable",d?.errorMessage??"model request failed",void 0,{served_model:m});y&&Y(f)&&We(y,a.id)&&await Pe(f,y.label,K,a.id);const re=d.content.filter(n=>n.type==="toolCall").map(n=>({id:n.id,type:"function",function:{name:n.name,arguments:JSON.stringify(n.arguments)}})),ie=X?"content_filter":d.stopReason==="toolUse"?"tool_calls":d.stopReason==="length"?"length":"stop",se=d.responseModel?at(a,d.responseModel):void 0,T=se?`${a.provider}/${se.model}`:m,ae={prompt_tokens:d.usage.input,completion_tokens:d.usage.output,total_tokens:d.usage.totalTokens,cache_read_tokens:d.usage.cacheRead,cache_write_tokens:d.usage.cacheWrite,usd_equivalent:st(se??a,d.usage.cost.total),served_model:T};l!==void 0&&R!==null&&await xe({request:l.request??J,kind:"model",what:T,units:{input:d.usage.input,output:d.usage.output,cache_read:d.usage.cacheRead,cache_write:d.usage.cacheWrite},usd:ae.usd_equivalent,payer:R.payer,funding:R.funding,sub:$,grantee:l.grantee,node:l.node??null,run:l.run??null,provider:f,causedBy:await fe(),vendorRef:te});const Ie={id:J,object:"chat.completion",created:Math.floor(K/1e3),model:T,served_model:T,requested_model:F,substituted:F!==T&&!/^([^/]+)\/(ultra|strong|medium|light)$/.test(F),choices:[{index:0,message:{role:"assistant",content:oe.join("")||null,...U.length?{reasoning_content:U.join("")}:{},...re.length?{tool_calls:re}:{},...X?{refusal:d.errorMessage??"Content filtered"}:{}},finish_reason:ie}],usage:ae,...e.metadata!==void 0?{metadata:e.metadata}:{}};for(const[n,w]of re.entries())z(H({tool_calls:[{index:n,...w}]}));return z({...H({},ie),...X?{choices:[{index:0,delta:{},finish_reason:ie,message:{refusal:d.errorMessage??"Content filtered"}}]}:{},usage:ae}),{completion:Ie,chunks:ne}}}throw V!==void 0?Xe(V):S!==1/0?new s(429,"all_routes_exhausted","all eligible model routes are rate-limited",void 0,{retry_after_s:Math.max(1,Math.ceil((S-Date.now())/1e3)),served_model:b?`${b.provider}/${b.model}`:Q,...b?{rate_limit:{provider:b.provider,model:b.model,...b.account?{account:b.account}:{},scope:ve(b.observation.scope),...b.observation.claim?{claim:b.observation.claim}:{},headers:b.observation.headers}}:{}},void 0,!0):e.model_policy==="exact"?new s(400,"substitution_refused","the requested model is unavailable"):new s(404,"model_unavailable","no usable model route is available")}c(Lt,"runLlm");export{St as llmCallerOf,Ot as parseLlmRequest,Lt as runLlm};
@@ -1 +1 @@
1
- var w=Object.defineProperty;var l=(e,t)=>w(e,"name",{value:t,configurable:!0});import{ApiError as m}from"../../api/index.js";import{PoolCredentialStore as g}from"../pool-credential-store.js";import{resolveLaunchTarget as v}from"../runtime/launch-target.js";import{coolingUntilFor as p,isManagedProvider as y,readSubscriptionPool as _}from"../subscription-state.js";function h(e){const t=e.indexOf("/"),o=t>0?e.slice(0,t):"";if(o==="")throw new m(422,"unresolved_model","the selected launch has no concrete model provider");return o}l(h,"providerFromModel");async function A(e){const o=(await v({root:!0,...e.profile!=null?{profile:e.profile}:{},...e.cwd!=null?{cwd:e.cwd}:{},...e.pin_cwd!=null?{pin_cwd:e.pin_cwd}:{},...e.mode!=null?{mode:e.mode}:{},...e.kind!=null?{kind:e.kind}:{},...e.model!=null?{model:e.model}:{}},{readOnlyProfileSelection:!0})).launch.model;if(o===void 0)throw new m(422,"unresolved_model","the selected launch has no concrete model");const r=h(o);if(y(r)){const a=await _(r);if(a.length>0){const d=a.filter(n=>n.authFailure===void 0);if(d.length===0)return{provider:r,model:o,credential:"unusable",reason:"invalid_grant"};const s=Date.now(),f=d.some(n=>p(n,o)<=s),c=Math.min(...d.map(n=>p(n,o)));return{provider:r,model:o,credential:"ready",...!f&&c>s?{rate_limited_until:new Date(c).toISOString()}:{}}}}const i=await new g().read(r),u=i?.type==="oauth"||i?.type==="api_key"&&!!i.key;return{provider:r,model:o,credential:u?"ready":"missing"}}l(A,"modelAuthReadiness");export{A as modelAuthReadiness};
1
+ var g=Object.defineProperty;var l=(e,n)=>g(e,"name",{value:n,configurable:!0});import{ApiError as m}from"../../api/index.js";import{storedApiKey as p}from"../auth-file.js";import{PoolCredentialStore as v}from"../pool-credential-store.js";import{resolveLaunchTarget as _}from"../runtime/launch-target.js";import{coolingUntilFor as f,isManagedProvider as h,readSubscriptionPool as k}from"../subscription-state.js";function S(e){const n=e.indexOf("/"),o=n>0?e.slice(0,n):"";if(o==="")throw new m(422,"unresolved_model","the selected launch has no concrete model provider");return o}l(S,"providerFromModel");async function O(e){const o=(await _({root:!0,...e.profile!=null?{profile:e.profile}:{},...e.cwd!=null?{cwd:e.cwd}:{},...e.pin_cwd!=null?{pin_cwd:e.pin_cwd}:{},...e.mode!=null?{mode:e.mode}:{},...e.kind!=null?{kind:e.kind}:{},...e.model!=null?{model:e.model}:{}},{readOnlyProfileSelection:!0})).launch.model;if(o===void 0)throw new m(422,"unresolved_model","the selected launch has no concrete model");const t=S(o);if(h(t)){const a=await k(t);if(a.length>0){const d=a.filter(r=>r.authFailure===void 0);if(d.length===0)return await p(t)!==void 0?{provider:t,model:o,credential:"ready"}:{provider:t,model:o,credential:"unusable",reason:"invalid_grant"};const s=Date.now(),w=d.some(r=>f(r,o)<=s),c=Math.min(...d.map(r=>f(r,o))),y=!w&&c>s&&await p(t)===void 0;return{provider:t,model:o,credential:"ready",...y?{rate_limited_until:new Date(c).toISOString()}:{}}}}const i=await new v().read(t),u=i?.type==="oauth"||i?.type==="api_key"&&!!i.key;return{provider:t,model:o,credential:u?"ready":"missing"}}l(O,"modelAuthReadiness");export{O as modelAuthReadiness};
@@ -1 +1 @@
1
- var te=Object.defineProperty;var d=(e,t)=>te(e,"name",{value:t,configurable:!0});import{createHash as oe}from"node:crypto";import{closeSync as D,constants as ne,createWriteStream as ie}from"node:fs";import{basename as re,extname as ae,isAbsolute as se,join as F}from"node:path";import{Transform as de}from"node:stream";import{pipeline as ue}from"node:stream/promises";import{appSpace as I}from"../layout.js";import{RunError as T}from"../runs/operations.js";import{createFileBeneath as ce,existsBeneath as M,openBeneath as le,removeTreeBeneath as N,setModeBeneath as fe,unlinkBeneath as pe,withDirBeneath as he}from"../spaces/open-beneath.js";import{ensureAppSpace as we}from"../spaces/space.js";import{invalidStorageName as H,storageClient as B,StorageRefused as U,UPLOAD_MAX_BYTES as C}from"../storage/client.js";import{contentTypeFor as _e,openCallerFile as me}from"../storage/download.js";import{withCanvasWrite as ge}from"../canvas/db.js";import{deleteUploadUse as ye,getUpload as be,insertUpload as $e,insertUploadUses as Se,setUploadSize as ve,uploadUseAt as Ue}from"../storage/tables.js";import{ProviderError as c}from"./errors.js";const ze=11e4,Ee="app:terminal";function P(e){if(e.class==="person")return e.grantee??Ee;if(!e.grantee)throw new c("server_error","provider caller has no grantee");return e.grantee}d(P,"grantee");function Ae(e){return e.class==="person"?null:{app:P(e),resolved:e.resolved??[],launched:e.class==="broker"?e.nodeScopes:null}}d(Ae,"fileCaller");function y(e){return e instanceof c?e:e instanceof U?new c("storage_unavailable",`storage refused: ${e.message}`):e instanceof T&&e.code==="storage_unavailable"?new c("storage_unavailable",e.message):e}d(y,"storageFailure");const b=d(e=>new c("provider_error",e,{origin:"provider"}),"providerError");function Fe(e,t,n){if(typeof n!="string"||!n||!se(n)||n.includes("\0"))throw new c("invalid_request",`${t} must be an absolute runtime path`,{param:t});let r;try{r=me(Ae(e),n)}catch(i){throw i instanceof T?i.code==="scope_missing"?new c("scope_missing",i.message,{param:t,...i.scope?{scope:i.scope}:{}}):i.code==="not_found"||i.code==="invalid_request"?new c("not_found",`no such file: ${n}`,{param:t}):i:i}try{if(r.size>C)throw new c("invalid_request",`${t} exceeds 100 MiB`,{param:t});const i=re(r.path),o=H(i);if(o)throw new c("invalid_request",`${t}: file name cannot be sent: ${o}`,{param:t});return{param:t,file:r,name:i,mediaType:_e(r.path)}}catch(i){throw D(r.fd),i}}d(Fe,"checkFileArgument");async function Te(e,t){try{const n=await e.createOutbound({name:t.name,size:t.file.size,media_type:t.mediaType});await e.putFileBytes(n.upload_link,t.file.fd,t.file.size,t.mediaType);const r=await e.signOutbound(n.object_id);return{param:t.param,path:t.file.path,name:t.name,object_id:n.object_id,url:r.url}}catch(n){throw y(n)}}d(Te,"copyOutbound");async function k(e,t,n,r){const i=[];try{for(const a of t)n[a]===void 0||n[a]===null||i.push(Fe(e,a,n[a]));if(!i.length)return[];let o;try{o=r()}catch(a){throw y(a)}const l=[];for(const a of i)l.push(await Te(o,a));return l}finally{for(const o of i)D(o.file.fd)}}d(k,"copyArguments");function q(e){const t=H(e);if(t)throw new c("server_error",`file output ${e} cannot name an upload: ${t}`)}d(q,"checkOutputField");async function W(e,t,n){q(t);const r=P(e),i="application/octet-stream";let o;try{o=await n().createResultUpload({name:t,media_type:i,max_size:C})}catch(l){throw y(l)}return await $e({upload_id:o.upload_id,grantee:r,name:t,media_type:i,size:C,created_at:new Date().toISOString()}),{field:t,upload_id:o.upload_id,upload_link:o.upload_link,grantee:r}}d(W,"createResultUpload");function X(e){return e?{"Crtr-Upload-Id":e.upload_id,"Crtr-Upload-Link":e.upload_link}:{}}d(X,"uploadHeaders");function Y(e,t){const n={...e};for(const r of t)n[r.param]=r.url;return n}d(Y,"withUrls");async function Ye(e,t,n,r={}){const i=r.storage??B;t.output&&q(t.output);const o=await k(e,t.params,n,i),l=t.output?await W(e,t.output,i):null;return{arguments:Y(n,o),copies:o,upload:l,headers:X(l)}}d(Ye,"prepareFileCall");async function Ge(e,t,n,r,i={}){const o=i.storage??B,l=[];for(const s of r.copies)try{const p=await o().signOutbound(s.object_id);l.push({...s,url:p.url})}catch(p){if(!(p instanceof U))throw y(p);l.push(...await k(e,[s.param],n,o))}let a=r.upload;if(a)try{const s=await o().signUploadLink(a.upload_id);a={...a,upload_link:s.upload_link}}catch(s){if(!(s instanceof U))throw y(s);s.status===404&&(a=await W(e,t.output??a.field,o))}return{arguments:Y(n,l),copies:l,upload:a,headers:X(a)}}d(Ge,"resignForRetry");const Be=/^[0-9a-f]{64}$/i;function Ce(e,t){if(t===1)return e;const n=ae(e);return n&&n!==e?`${e.slice(0,-n.length)}-${t}${n}`:`${e}-${t}`}d(Ce,"candidate");async function Je(e,t,n,r={}){const i={result:n,file:null,cleanup:d(async()=>{},"cleanup")},o=t.upload;if(!o||!n||typeof n!="object"||Array.isArray(n))return i;const l=n,a=l[o.field];if(a==null)return i;if(typeof a!="object"||Array.isArray(a))throw b(`${o.field} must be {upload_id, size, sha256}`);const s=a;if(typeof s.upload_id!="string"||typeof s.size!="number"||!Number.isSafeInteger(s.size)||s.size<0||typeof s.sha256!="string"||!Be.test(s.sha256))throw b(`${o.field} must be {upload_id, size, sha256}`);if(s.upload_id!==o.upload_id)throw b(`${o.field} names an upload other than Crtr-Upload-Id`);const p=s.size,G=s.sha256.toLowerCase(),z=AbortSignal.timeout(r.budgetMs??ze),O=r.signal?AbortSignal.any([z,r.signal]):z;let h;try{h=await(r.storage??B)().fetchUpload(o.upload_id,O)}catch(_){throw _ instanceof U?b(`${o.field} names an upload with nothing stored`):y(_)}if(h.size===null)throw h.body.destroy(),new c("storage_unavailable",`storage did not say how many bytes ${o.field} holds`);if(h.size!==p)throw h.body.destroy(),b(`${o.field} claims ${p} bytes; storage holds ${h.size}`);const E=o.grantee,$=e.node_id!==null,J=await we(E),f=$?I(E).nodes:I(E).files,A=$?F(f,e.node_id):f,S=$?F(A,"attachments"):f,K={uid:process.getuid?.()??0,gid:J.gid},R=$&&!M(f,A),Q=$&&!R&&!M(f,S);let w=null,v=null,x=!1;const L=d(async()=>{if(!x){if(x=!0,v)try{await ye(v)}catch{}if(w)try{pe(f,w)}catch{}try{R?N(f,A):Q&&N(f,S)}catch{}}},"cleanup");try{he(f,S,()=>{},!0);for(let u=1;;u++){const m=F(S,Ce(o.field,u));if(!await Ue(m))try{ce(f,m,Buffer.alloc(0),432),w=m;break}catch(g){if(g.code!=="EEXIST")throw g}}let _=0;const j=oe("sha256"),V=new de({transform(u,m,g){_+=u.length,j.update(u),g(null,u)}}),Z=le(f,w,ne.O_WRONLY);try{await ue(h.body,V,ie("",{fd:Z,autoClose:!0}),{signal:O})}catch(u){throw z.aborted?new c("storage_unavailable","the file result could not be fetched within 110 s"):u instanceof T?y(u):new c("storage_unavailable",`storage stopped sending ${o.field}: ${u instanceof Error?u.message:String(u)}`)}if(_!==p)throw new c("storage_unavailable",`storage sent ${_} of ${p} bytes of ${o.field}`);if(j.digest("hex")!==G)throw b(`${o.field}: the stored bytes do not match sha256`);fe(f,w,432,K);const ee=w;await ge(async u=>{const m=await be(o.upload_id,u);if(!m||m.delete_pending_since)throw new c("not_found",`${o.field}: the upload was deleted while it was fetched`);if(await ve(o.upload_id,p,u),!e.run_id)return;const g=await u.prepare("SELECT deleting_at FROM nodes WHERE node_id = ?").get(e.run_id);if(!g||g.deleting_at)throw new c("not_found",`run ${e.run_id} was deleted while its file result was fetched`);v={upload_id:o.upload_id,run_id:e.run_id,path:ee},await Se([v],u)})}catch(_){throw h.body.destroy(),await L(),_}return{result:{...l,[o.field]:w},file:{path:w,upload_id:o.upload_id},cleanup:L}}d(Je,"resolveFileResult");export{ze as FILE_RESULT_FETCH_BUDGET_MS,Ye as prepareFileCall,Ge as resignForRetry,Je as resolveFileResult};
1
+ var te=Object.defineProperty;var d=(e,t)=>te(e,"name",{value:t,configurable:!0});import{createHash as oe}from"node:crypto";import{closeSync as D,constants as ne,createWriteStream as ie}from"node:fs";import{basename as re,extname as ae,isAbsolute as se,join as C}from"node:path";import{Transform as de}from"node:stream";import{pipeline as ue}from"node:stream/promises";import{appSpace as I}from"../layout.js";import{RunError as F}from"../runs/operations.js";import{createFileBeneath as le,existsBeneath as M,openBeneath as ce,removeTreeBeneath as N,setModeBeneath as fe,unlinkBeneath as pe,withDirBeneath as he}from"../spaces/open-beneath.js";import{ensureAppSpace as we}from"../spaces/space.js";import{isCloudRole as _e}from"../canvas/person-state.js";import{invalidStorageName as H,storageClient as T,StorageRefused as U,UPLOAD_MAX_BYTES as B}from"../storage/client.js";import{contentTypeFor as me,openCallerFile as ge}from"../storage/download.js";import{withCanvasWrite as ye}from"../canvas/db.js";import{deleteUploadUse as be,getUpload as $e,insertUpload as ve,insertUploadUses as Se,setUploadSize as Ue,uploadUseAt as ze}from"../storage/tables.js";import{ProviderError as u}from"./errors.js";const Ee=11e4,Ae="app:terminal";function P(e){if(e.class==="person")return e.grantee??Ae;if(!e.grantee)throw new u("server_error","provider caller has no grantee");return e.grantee}d(P,"grantee");function Ce(e){return e.class==="person"?null:{app:P(e),resolved:e.resolved??[],launched:e.class==="broker"?e.nodeScopes:null}}d(Ce,"fileCaller");function y(e){return e instanceof u?e:e instanceof U?new u("storage_unavailable",`storage refused: ${e.message}`):e instanceof F&&e.code==="storage_unavailable"?new u("storage_unavailable",e.message):e}d(y,"storageFailure");const b=d(e=>new u("provider_error",e,{origin:"provider"}),"providerError");function Fe(e,t,n){if(typeof n!="string"||!n||!se(n)||n.includes("\0"))throw new u("invalid_request",`${t} must be an absolute runtime path`,{param:t});let r;try{r=ge(Ce(e),n)}catch(i){throw i instanceof F?i.code==="scope_missing"?new u("scope_missing",i.message,{param:t,...i.scope?{scope:i.scope}:{}}):i.code==="not_found"||i.code==="invalid_request"?new u("not_found",`no such file: ${n}`,{param:t}):i:i}try{if(r.size>B)throw new u("invalid_request",`${t} exceeds 100 MiB`,{param:t});const i=re(r.path),o=H(i);if(o)throw new u("invalid_request",`${t}: file name cannot be sent: ${o}`,{param:t});return{param:t,file:r,name:i,mediaType:me(r.path)}}catch(i){throw D(r.fd),i}}d(Fe,"checkFileArgument");async function Te(e,t){try{const n=await e.createOutbound({name:t.name,size:t.file.size,media_type:t.mediaType});await e.putFileBytes(n.upload_link,t.file.fd,t.file.size,t.mediaType);const r=await e.signOutbound(n.object_id);return{param:t.param,path:t.file.path,name:t.name,object_id:n.object_id,url:r.url}}catch(n){throw y(n)}}d(Te,"copyOutbound");async function k(e,t,n,r){const i=[];try{for(const a of t)n[a]===void 0||n[a]===null||i.push(Fe(e,a,n[a]));if(!i.length)return[];let o;try{o=r()}catch(a){throw y(a)}const c=[];for(const a of i)c.push(await Te(o,a));return c}finally{for(const o of i)D(o.file.fd)}}d(k,"copyArguments");function q(e){const t=H(e);if(t)throw new u("server_error",`file output ${e} cannot name an upload: ${t}`)}d(q,"checkOutputField");async function W(e,t,n){q(t);const r=P(e),i="application/octet-stream";let o;try{o=await n().createResultUpload({name:t,media_type:i,max_size:B})}catch(c){throw y(c)}return await ve({upload_id:o.upload_id,grantee:r,name:t,media_type:i,size:B,created_at:new Date().toISOString()}),{field:t,upload_id:o.upload_id,upload_link:o.upload_link,grantee:r}}d(W,"createResultUpload");function X(e){return e?{"Crtr-Upload-Id":e.upload_id,"Crtr-Upload-Link":e.upload_link}:{}}d(X,"uploadHeaders");function Y(e,t){const n={...e};for(const r of t)n[r.param]=r.url;return n}d(Y,"withUrls");async function Je(e,t,n,r={}){const i=r.storage??T;t.output&&q(t.output);const o=await k(e,t.params,n,i),c=t.output?await W(e,t.output,i):null;return{arguments:Y(n,o),copies:o,upload:c,headers:X(c)}}d(Je,"prepareFileCall");async function Ke(e,t,n,r,i={}){const o=i.storage??T,c=[];for(const s of r.copies)try{const p=await o().signOutbound(s.object_id);c.push({...s,url:p.url})}catch(p){if(!(p instanceof U))throw y(p);c.push(...await k(e,[s.param],n,o))}let a=r.upload;if(a)try{const s=await o().signUploadLink(a.upload_id);a={...a,upload_link:s.upload_link}}catch(s){if(!(s instanceof U))throw y(s);s.status===404&&(a=await W(e,t.output??a.field,o))}return{arguments:Y(n,c),copies:c,upload:a,headers:X(a)}}d(Ke,"resignForRetry");const Be=/^[0-9a-f]{64}$/i;function Re(e,t){if(t===1)return e;const n=ae(e);return n&&n!==e?`${e.slice(0,-n.length)}-${t}${n}`:`${e}-${t}`}d(Re,"candidate");async function Qe(e,t,n,r={}){const i={result:n,file:null,cleanup:d(async()=>{},"cleanup")},o=t.upload;if(!o||!n||typeof n!="object"||Array.isArray(n))return i;const c=n,a=c[o.field];if(a==null)return i;if(typeof a!="object"||Array.isArray(a))throw b(`${o.field} must be {upload_id, size, sha256}`);const s=a;if(typeof s.upload_id!="string"||typeof s.size!="number"||!Number.isSafeInteger(s.size)||s.size<0||typeof s.sha256!="string"||!Be.test(s.sha256))throw b(`${o.field} must be {upload_id, size, sha256}`);if(s.upload_id!==o.upload_id)throw b(`${o.field} names an upload other than Crtr-Upload-Id`);const p=s.size,G=s.sha256.toLowerCase(),z=AbortSignal.timeout(r.budgetMs??Ee),R=r.signal?AbortSignal.any([z,r.signal]):z;let h;try{h=await(r.storage??T)().fetchUpload(o.upload_id,R)}catch(_){throw _ instanceof U?b(`${o.field} names an upload with nothing stored`):y(_)}if(h.size===null)throw h.body.destroy(),new u("storage_unavailable",`storage did not say how many bytes ${o.field} holds`);if(h.size!==p)throw h.body.destroy(),b(`${o.field} claims ${p} bytes; storage holds ${h.size}`);if(_e())throw new u("storage_unavailable","a cloud role has no folder to land a file result in");const E=o.grantee,$=e.node_id!==null,J=await we(E),f=$?I(E).nodes:I(E).files,A=$?C(f,e.node_id):f,v=$?C(A,"attachments"):f,K={uid:process.getuid?.()??0,gid:J.gid},O=$&&!M(f,A),Q=$&&!O&&!M(f,v);let w=null,S=null,x=!1;const L=d(async()=>{if(!x){if(x=!0,S)try{await be(S)}catch{}if(w)try{pe(f,w)}catch{}try{O?N(f,A):Q&&N(f,v)}catch{}}},"cleanup");try{he(f,v,()=>{},!0);for(let l=1;;l++){const m=C(v,Re(o.field,l));if(!await ze(m))try{le(f,m,Buffer.alloc(0),432),w=m;break}catch(g){if(g.code!=="EEXIST")throw g}}let _=0;const j=oe("sha256"),V=new de({transform(l,m,g){_+=l.length,j.update(l),g(null,l)}}),Z=ce(f,w,ne.O_WRONLY);try{await ue(h.body,V,ie("",{fd:Z,autoClose:!0}),{signal:R})}catch(l){throw z.aborted?new u("storage_unavailable","the file result could not be fetched within 110 s"):l instanceof F?y(l):new u("storage_unavailable",`storage stopped sending ${o.field}: ${l instanceof Error?l.message:String(l)}`)}if(_!==p)throw new u("storage_unavailable",`storage sent ${_} of ${p} bytes of ${o.field}`);if(j.digest("hex")!==G)throw b(`${o.field}: the stored bytes do not match sha256`);fe(f,w,432,K);const ee=w;await ye(async l=>{const m=await $e(o.upload_id,l);if(!m||m.delete_pending_since)throw new u("not_found",`${o.field}: the upload was deleted while it was fetched`);if(await Ue(o.upload_id,p,l),!e.run_id)return;const g=await l.prepare("SELECT deleting_at FROM nodes WHERE node_id = ?").get(e.run_id);if(!g||g.deleting_at)throw new u("not_found",`run ${e.run_id} was deleted while its file result was fetched`);S={upload_id:o.upload_id,run_id:e.run_id,path:ee},await Se([S],l)})}catch(_){throw h.body.destroy(),await L(),_}return{result:{...c,[o.field]:w},file:{path:w,upload_id:o.upload_id},cleanup:L}}d(Qe,"resolveFileResult");export{Ee as FILE_RESULT_FETCH_BUDGET_MS,Je as prepareFileCall,Ke as resignForRetry,Qe as resolveFileResult};
@@ -1,14 +1,14 @@
1
- var Oe=Object.defineProperty;var c=(e,t)=>Oe(e,"name",{value:t,configurable:!0});import{coveredByAny as De}from"../../shared/env.js";import{createHash as Q}from"node:crypto";import{ApiError as Me}from"../../api/errors.js";import{CrtrError as Ae}from"../errors.js";import{isCloudRole as Ie}from"../canvas/person.js";import{isAbsolute as V,relative as Te,resolve as Le,sep as Ce,join as ke}from"node:path";import{SessionManager as xe}from"@earendil-works/pi-coding-agent";import{covers as P}from"@north-light/identity";import{openDb as B,withCanvasWrite as F}from"../canvas/db.js";import{deleteNodeWithOwned as We}from"../graph/deletion.js";import{getById as Fe}from"../graph/objects.js";import{repairRunConversations as Z}from"../canvas/sessions.js";import{getNode as O,nodeFiles as qe,removeNodeFiles as He,updateNode as Ue}from"../canvas/canvas.js";import{fullName as $e}from"../canvas/labels.js";import{renameWindow as Pe}from"../runtime/placement.js";import{liveExecutionForNode as K}from"../canvas/executions.js";import{conversationStore as ee,isConversationNotFound as Be}from"../conversation-store/index.js";import{PARKED_RESIDENT_SQL as je}from"../canvas/canvas.js";import{WAKE_MAIL_SQL as Je}from"../canvas/deliveries.js";import{readNodeRecap as Ye}from"../canvas/node-recap.js";import{enqueueNodeMail as Ge}from"../feed/messages.js";import{newestReportBody as Xe}from"../feed/reports.js";import{ensureAppProfile as ze,loadExactProfileManifest as Qe}from"../profiles/manifest.js";import{stopNodeSandboxes as te}from"../spaces/stop.js";import{BrokerUnreachableError as Ve}from"../runtime/broker-request.js";import{interruptLive as Ze}from"../runtime/interactive-deliver.js";import{isBrokerLive as ne}from"../runtime/model-swap.js";import{newNodeId as Ke}from"../runtime/nodes.js";import{reviveNode as j}from"../runtime/revive.js";import{spawnChildPrepared as et}from"../runtime/spawn.js";import{isPortableModelToken as tt}from"../runtime/launch.js";import{parseDurationMs as nt}from"../wake.js";import{expandModelCandidates as st,parseModelSpec as at}from"../model-routes.js";import{payerOfGrant as J}from"../grants/mirror.js";import{isolatedBrokerLauncherAvailable as it}from"../runtime/host.js";import{resolveRunKind as rt,resolveRunModel as ot}from"../runtime/launch-target.js";import{cycleAwareMessages as dt}from"../runtime/session-cycles.js";import{originFor as se}from"../runtime/stamp/protocol.js";import{readOutputRequest as ct,readOutputResult as ae}from"../runtime/output-result.js";import{admitLegacyStructuredOutput as ie}from"../../daemon/structured-requests/sidecar.js";import{runSchemaRepromptPending as ut}from"../runtime/stop-guard.js";import{toRunOutcomeDTO as mt}from"../../daemon/api/map.js";import{openAssistantMessageStartSequence as lt}from"../../daemon/runs/observer.js";import{closeNode as re}from"../runtime/close.js";import{parseScope as pt}from"@north-light/identity";import{appendRunEvent as oe,lockRunRoot as ft,subscribeRunEvents as _t}from"./events.js";import{runActivity as wt}from"./activity.js";import{cancelOpenQuestions as de,openNoticeIds as gt,openQuestionIds as ce}from"./questions.js";import{appSpace as Y}from"../layout.js";import{ensureAppSpace as Et}from"../spaces/space.js";import{assertUploadsUsable as ue,resolveStorageUrls as yt}from"../storage/attachments.js";import{storageClient as ht,storageConfig as Rt}from"../storage/client.js";import{deleteUploadRow as St,insertUploadUses as me,releaseRunUploads as Nt,runUsesPath as vt}from"../storage/tables.js";import{abortProviderCalls as le}from"../providers/inflight.js";import{filterAsync as pe,mapAsync as x}from"../async-array.js";const fe=c((e,t,s,n)=>yt(t,e,s,n?{taken:n}:{}),"defaultResolver"),bt=3e3;class R extends Error{static{c(this,"RunError")}status;code;param;details;scope;retryable;constructor(t,s,n,o,m,i,r=t===503){super(n),this.status=t,this.code=s,this.param=o,this.details=m,this.scope=i,this.retryable=r}}const N=c((e,t)=>new R(400,"invalid_request",e,t),"invalid"),G=c(()=>new R(404,"not_found","run not found"),"missing"),X=c(()=>({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}),"usage"),A=c(async()=>await B(),"db");async function q(e,t,s=!1){const n=await O(e);if(!n||n.parent!==null||n.run_id!==e||n.grantee!==t||!s&&n.deleting_at)throw G();return n}c(q,"ownedRun");const _e=["waiting_on_user","idle","settled"];async function C(e){if(e.status==="canceled"||e.status==="dead"||e.status==="done"&&e.intent!=="parked")return"settled";const t=await(await A()).prepare(`SELECT 1 FROM node_rows n WHERE n.run_id = ? AND n.status = 'active' AND
1
+ var Me=Object.defineProperty;var c=(e,t)=>Me(e,"name",{value:t,configurable:!0});import{coveredByAny as Ae}from"../../shared/env.js";import{createHash as Q}from"node:crypto";import{ApiError as Ie}from"../../api/errors.js";import{CrtrError as Te}from"../errors.js";import{isCloudRole as Le}from"../canvas/person.js";import{isAbsolute as V,relative as Ce,resolve as ke,sep as xe,join as We}from"node:path";import{SessionManager as Fe}from"@earendil-works/pi-coding-agent";import{covers as P}from"@north-light/identity";import{openDb as B,withCanvasWrite as F}from"../canvas/db.js";import{deleteNodeWithOwned as qe}from"../graph/deletion.js";import{getById as He}from"../graph/objects.js";import{repairRunConversations as Z}from"../canvas/sessions.js";import{getNode as O,nodeFiles as Ue,removeNodeFiles as $e,updateNode as Pe}from"../canvas/canvas.js";import{fullName as Be}from"../canvas/labels.js";import{renameWindow as je}from"../runtime/placement.js";import{liveExecutionForNode as K}from"../canvas/executions.js";import{conversationStore as ee,isConversationNotFound as Je}from"../conversation-store/index.js";import{PARKED_RESIDENT_SQL as Ye}from"../canvas/canvas.js";import{WAKE_MAIL_SQL as Ge}from"../canvas/deliveries.js";import{readNodeRecap as Xe}from"../canvas/node-recap.js";import{enqueueNodeMail as ze}from"../feed/messages.js";import{newestReportBody as Qe}from"../feed/reports.js";import{ensureAppProfile as te,loadExactProfileManifest as ne}from"../profiles/manifest.js";import{stopNodeSandboxes as se}from"../spaces/stop.js";import{BrokerUnreachableError as Ve}from"../runtime/broker-request.js";import{interruptLive as Ze}from"../runtime/interactive-deliver.js";import{isBrokerLive as ae}from"../runtime/model-swap.js";import{newNodeId as Ke}from"../runtime/nodes.js";import{reviveNode as j}from"../runtime/revive.js";import{spawnChildPrepared as et}from"../runtime/spawn.js";import{isPortableModelToken as tt}from"../runtime/launch.js";import{parseDurationMs as nt}from"../wake.js";import{expandModelCandidates as st,parseModelSpec as at}from"../model-routes.js";import{payerOfGrant as J}from"../grants/mirror.js";import{isolatedBrokerLauncherAvailable as it}from"../runtime/host.js";import{blaxelEnvironmentOf as rt}from"../runtime/blaxel-environment.js";import{resolveRunKind as ot,resolveRunModel as dt}from"../runtime/launch-target.js";import{cycleAwareMessages as ct}from"../runtime/session-cycles.js";import{originFor as ie}from"../runtime/stamp/protocol.js";import{readOutputRequest as ut,readOutputResult as re}from"../runtime/output-result.js";import{admitLegacyStructuredOutput as oe}from"../../daemon/structured-requests/sidecar.js";import{runSchemaRepromptPending as mt}from"../runtime/stop-guard.js";import{toRunOutcomeDTO as lt}from"../../daemon/api/map.js";import{openAssistantMessageStartSequence as pt}from"../../daemon/runs/observer.js";import{closeNode as de}from"../runtime/close.js";import{parseScope as ft}from"@north-light/identity";import{appendRunEvent as ce,lockRunRoot as _t,subscribeRunEvents as wt}from"./events.js";import{runActivity as gt}from"./activity.js";import{cancelOpenQuestions as ue,openNoticeIds as Et,openQuestionIds as me}from"./questions.js";import{appSpace as Y}from"../layout.js";import{ensureAppSpace as yt}from"../spaces/space.js";import{assertUploadsUsable as le,resolveStorageUrls as ht}from"../storage/attachments.js";import{storageClient as Rt,storageConfig as St}from"../storage/client.js";import{deleteUploadRow as Nt,insertUploadUses as pe,releaseRunUploads as vt,runUsesPath as bt}from"../storage/tables.js";import{abortProviderCalls as fe}from"../providers/inflight.js";import{filterAsync as _e,mapAsync as x}from"../async-array.js";const we=c((e,t,s,n)=>ht(t,e,s,n?{taken:n}:{}),"defaultResolver"),Ot=3e3;class R extends Error{static{c(this,"RunError")}status;code;param;details;scope;retryable;constructor(t,s,n,o,m,i,r=t===503){super(n),this.status=t,this.code=s,this.param=o,this.details=m,this.scope=i,this.retryable=r}}const N=c((e,t)=>new R(400,"invalid_request",e,t),"invalid"),G=c(()=>new R(404,"not_found","run not found"),"missing"),X=c(()=>({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}),"usage"),A=c(async()=>await B(),"db");async function q(e,t,s=!1){const n=await O(e);if(!n||n.parent!==null||n.run_id!==e||n.grantee!==t||!s&&n.deleting_at)throw G();return n}c(q,"ownedRun");const ge=["waiting_on_user","idle","settled"];async function C(e){if(e.status==="canceled"||e.status==="dead"||e.status==="done"&&e.intent!=="parked")return"settled";const t=await(await A()).prepare(`SELECT 1 FROM node_rows n WHERE n.run_id = ? AND n.status = 'active' AND
2
2
  (n.last_settled_at IS NULL OR EXISTS (
3
3
  SELECT 1 FROM run_events e WHERE e.run_id = ? AND e.node_id = n.node_id AND e.type = 'node.turn.started'
4
4
  AND e.sequence_number > COALESCE((SELECT MAX(c.sequence_number) FROM run_events c
5
5
  WHERE c.run_id = e.run_id AND c.node_id = e.node_id AND c.type = 'node.turn.completed'), 0)
6
- )) LIMIT 1`).get(e.node_id,e.node_id),s=!e.last_settled_at&&e.status!=="done";return t||s||await ut(e)?"running":(await ce(e.node_id)).length?"waiting_on_user":await(await A()).prepare(`SELECT 1 FROM deliveries d JOIN nodes n ON n.node_id = d.destination_id
7
- WHERE n.run_id = ? AND ${Je("d","'armed', 'pending'")}
8
- AND (n.status IN ('active', 'idle') OR ${je("n")}) LIMIT 1`).get(e.node_id)?"running":"idle"}c(C,"runStatus");async function kn(e){const t=await O(e);return t!==null&&await C(t)==="running"}c(kn,"runIsRunning");async function W(e){await Z(e.node_id),e=await O(e.node_id)??e;const t=await C(e),s=t==="settled"?[]:await ce(e.node_id),n=await Xe(e.node_id)||void 0,o=t==="settled"?await mt(e):null,m=o?.kind==="result"?await ae(e.node_id):void 0,i=Ye(e.node_id);return{run_id:e.node_id,name:e.name,status:t,...o?{outcome:o}:{},...m===void 0?{}:{result:m},...n!==void 0?{last_report:n}:{},...i?{recap:i}:{},pending_question_ids:s,open_notice_ids:t==="settled"?[]:await gt(e.node_id),...e.last_turn_error_json?{last_turn_error:JSON.parse(e.last_turn_error_json)}:{},usage:JSON.parse(e.usage_json??JSON.stringify(X())),payer:await J(e.grant_id),scopes:e.scopes,metadata:e.metadata_json?JSON.parse(e.metadata_json):{},created_at:e.created,...t==="settled"&&e.outcome_at?{settled_at:e.outcome_at}:{},latest_sequence:(e.event_cursor??1)-1,last_activity_at:e.last_activity_at,activity:await wt(e.node_id,t)}}c(W,"runObject");const z=864e5,we=255;function xn(e){if(e!==void 0){if(typeof e!="string"||!e.length||e.length>we)throw N(`Idempotency-Key must be 1-${we} characters`);return e}}c(xn,"idempotencyKeyOf");function Ot(e){if(Ie()){if(!e)throw new R(403,"permission_error","a cloud role serves this call only for a token that names a person");return e}}c(Ot,"cloudPersonScope");function k(e,t){const s=Ot(e);return s===void 0?t:`${s}:${t}`}c(k,"personKey");async function H(e,t,s,n){n&&await n.prepare("SELECT pg_advisory_xact_lock(hashtext(?))").get(`idempotency:${e}:${t}`),n??=await B();const o=await n.prepare("SELECT body_hash, run_id, response_json, created_at FROM idempotency_keys WHERE grantee = ? AND key = ?").get(e,t);if(!(!o||Date.now()-Date.parse(o.created_at)>=z)){if(o.body_hash!==s)throw new R(409,"idempotency_conflict","key used with a different request");return{run_id:o.run_id,response:JSON.parse(o.response_json)}}}c(H,"findIdempotent");async function ge(e,t,s,n,o,m,i){await e.prepare("DELETE FROM idempotency_keys WHERE grantee = ? AND key = ? AND created_at <= ?").run(t,s,new Date(Date.now()-z).toISOString()),await e.prepare("INSERT INTO idempotency_keys (grantee, key, body_hash, run_id, response_json, created_at) VALUES (?, ?, ?, ?, ?, ?)").run(t,s,n,o,JSON.stringify(m),i)}c(ge,"recordIdempotent");async function Wn(e=Date.now()){return Number((await(await B()).prepare("DELETE FROM idempotency_keys WHERE created_at <= ?").run(new Date(e-z).toISOString())).changes)}c(Wn,"pruneExpiredIdempotencyKeys");async function Ee(e,t,s,n,o){const m=n.text;let i=0;return{messageId:(await Ge(t,{kind:"message",label:m.slice(0,120),senderNodeId:"human",senderName:s,bodyJson:o?{body:m}:{body:m,start_turn:!1},urgency:o?"normal":"deferred",wake:o?1:0,withinEnqueue:c(async(u,l)=>{n.uses.length&&(await ue(s,n.uses,u),await me(n.uses.map(({upload_id:g,path:E,blob_key:y})=>({upload_id:g,path:E,blob_key:y,run_id:t})),u)),i=(await oe(u,t,t,"node.message.accepted",{message_id:l,start_turn:o})).sequence_number},"withinEnqueue")})).messageId,sequence:i}}c(Ee,"acceptRunMessage");class ye extends Error{static{c(this,"IdempotentReplay")}winner;constructor(t){super("idempotent replay"),this.winner=t}}const Dt=1440*60*1e3;function he(e){const t=typeof e=="string"?nt(e):null;if(t===null||!Number.isSafeInteger(t))throw N(`deadline '${String(e)}' is not a duration; use one or more <int>[smhd] parts such as 10m or 1h30m`,"deadline");if(t<=0)throw N("deadline must be greater than zero","deadline");if(t>Dt)throw N("deadline must be at most 24h","deadline");return t}c(he,"parseRunDeadlineMs");async function Fn(e,t,s,n=fe){if(t.isolated&&!it())throw new R(503,"isolated_unavailable","isolated runs require the Linux root launcher","isolated");t.deadline!==void 0&&he(t.deadline);const{causedBy:o,...m}=t,i=Q("sha256").update(JSON.stringify(m)).digest("hex");if(s){const a=await H(e.grantee,k(e.sub,s),i);if(a){const p=await q(a.run_id,e.grantee);return!p.pi_pid&&await C(p)==="running"&&(t.output_schema!==void 0&&!p.outcome_at&&await ct(p.node_id)===null&&await ae(p.node_id)===void 0&&await ie(p.node_id,"terminal",t.output_schema),await j(p.node_id,{resume:!0,capacity:"freeze"})),a.response}}await Et(e.grantee);const r=t.profile===void 0?await ze(e.grantee):Qe(t.profile),u=r.manifest.grantee??"app:terminal";if(u!==e.grantee){const a=`crtr:memory:rw:${u}:profile:${r.profileId}`;if(!e.resolved.some(p=>P(p,a))||t.scopes!==null&&!t.scopes.some(p=>P(p,a)))throw new R(403,"scope_missing",`missing scope ${a}`,"profile",void 0,a)}if(t.model!==void 0){const a=t.model;if(tt(a)){if(a.includes("/")&&await J(e.grant)!=="app"){const p=a.lastIndexOf("/"),D=a.slice(0,p),v=a.slice(p+1);if(["ultra","strong","medium","light"].includes(v)&&(await st({kind:"logical",family:D,strength:v,spec:a},Y(e.grantee).files,r.profileId)).every(S=>S.family!==D))throw N(`model '${a}' names a model family that is not configured in this daemon`,"model")}}else if(at(a)===void 0)throw N(`model '${a}' is not a strength (ultra, strong, medium, light), a family/strength, or a provider/model id`,"model")}const l=await Ke(),g=ke(Y(e.grantee).nodes,l);if(t.isolated&&t.cwd!==void 0){const a=Te(g,Le(t.cwd));if(!V(t.cwd)||a===".."||a.startsWith(`..${Ce}`)||V(a))throw N("cwd must be inside the isolated root node folder","cwd")}const E=await n(l,e.grantee,t.prompt),y=E.text,d=t.message===void 0?void 0:await n(l,e.grantee,t.message,E.uses.map(a=>a.path)),_=await J(e.grant);let h;try{const a=ot(r,t.model);await et({kind:rt(r),mode:"base",root:!0,rootLifecycle:"resident",readiness:"launch",cwd:t.isolated?t.cwd??g:Y(e.grantee).files,profile:r.profileId,prompt:y,nodeId:l,isolated:t.isolated??!1,...t.causedBy===void 0?{}:{causedBy:t.causedBy},...a===void 0?{}:{model:a},...t.deadline===void 0?{}:{deadlineAt:new Date(Date.now()+he(t.deadline)).toISOString()},...t.scopes===null?{}:{scopes:t.scopes},run:{grantee:e.grantee,sub:e.sub,grant_id:e.grant,client_id:e.client_id,metadata_json:JSON.stringify(t.metadata),run_id:l,event_cursor:1,usage_json:JSON.stringify(X())},withinCreate:c(async(p,D)=>{if(s){const S=await H(e.grantee,k(e.sub,s),i,p);if(S)throw new ye(S)}const v=E.uses;if(v.length&&(await ue(e.grantee,v,p),await me(v.map(({upload_id:S,path:I,blob_key:U})=>({upload_id:S,path:I,blob_key:U,run_id:l})),p)),h={run_id:l,node_id:l,grantee:e.grantee,grant:e.grant,rev:e.rev,scopes:t.scopes,payer:_,status:"running",created_at:D.created,metadata:t.metadata,sequence_number:0},await oe(p,l,l,"run.started",{scopes:t.scopes,payer:_,usage:X()}),d){const S=await Ee(p,l,e.grantee,d,!1);h.message={run_id:l,message_id:S.messageId,sequence_number:S.sequence}}s&&await ge(p,e.grantee,k(e.sub,s),i,l,h,D.created)},"withinCreate")},t.output_schema===void 0?void 0:async p=>{await ie(p,"terminal",t.output_schema)})}catch(a){if(a instanceof ye)return a.winner.response;if(t.model!==void 0&&a instanceof Ae&&a.code==="usage")throw N(a.message,"model");if(a instanceof Me&&(a.code==="isolated_run"||a.code==="invalid_request")){const p=a.details&&typeof a.details=="object"&&"param"in a.details&&typeof a.details.param=="string"?a.details.param:void 0;throw new R(a.status,a.code,a.message,p)}throw a}if(!h)throw new Error("run creation did not commit");return h}c(Fn,"startRun");async function qn(e,t){let s;if(t.after)try{const r=JSON.parse(Buffer.from(t.after,"base64url").toString());if(!r||typeof r!="object"||!("activity"in r)||typeof r.activity!="string"||!("id"in r)||typeof r.id!="string")throw new Error("invalid cursor");s={activity:r.activity,id:r.id}}catch{throw N("invalid list cursor","after")}const n=await(await A()).prepareUncached(`SELECT node_id, COALESCE(last_activity_at, created) AS activity FROM node_rows
6
+ )) LIMIT 1`).get(e.node_id,e.node_id),s=!e.last_settled_at&&e.status!=="done";return t||s||await mt(e)?"running":(await me(e.node_id)).length?"waiting_on_user":await(await A()).prepare(`SELECT 1 FROM deliveries d JOIN nodes n ON n.node_id = d.destination_id
7
+ WHERE n.run_id = ? AND ${Ge("d","'armed', 'pending'")}
8
+ AND (n.status IN ('active', 'idle') OR ${Ye("n")}) LIMIT 1`).get(e.node_id)?"running":"idle"}c(C,"runStatus");async function Wn(e){const t=await O(e);return t!==null&&await C(t)==="running"}c(Wn,"runIsRunning");async function W(e){await Z(e.node_id),e=await O(e.node_id)??e;const t=await C(e),s=t==="settled"?[]:await me(e.node_id),n=await Qe(e.node_id)||void 0,o=t==="settled"?await lt(e):null,m=o?.kind==="result"?await re(e.node_id):void 0,i=Xe(e.node_id);return{run_id:e.node_id,name:e.name,status:t,...o?{outcome:o}:{},...m===void 0?{}:{result:m},...n!==void 0?{last_report:n}:{},...i?{recap:i}:{},pending_question_ids:s,open_notice_ids:t==="settled"?[]:await Et(e.node_id),...e.last_turn_error_json?{last_turn_error:JSON.parse(e.last_turn_error_json)}:{},usage:JSON.parse(e.usage_json??JSON.stringify(X())),payer:await J(e.grant_id),scopes:e.scopes,metadata:e.metadata_json?JSON.parse(e.metadata_json):{},created_at:e.created,...t==="settled"&&e.outcome_at?{settled_at:e.outcome_at}:{},latest_sequence:(e.event_cursor??1)-1,last_activity_at:e.last_activity_at,activity:await gt(e.node_id,t)}}c(W,"runObject");const z=864e5,Ee=255;function Fn(e){if(e!==void 0){if(typeof e!="string"||!e.length||e.length>Ee)throw N(`Idempotency-Key must be 1-${Ee} characters`);return e}}c(Fn,"idempotencyKeyOf");function Dt(e){if(Le()){if(!e)throw new R(403,"permission_error","a cloud role serves this call only for a token that names a person");return e}}c(Dt,"cloudPersonScope");function k(e,t){const s=Dt(e);return s===void 0?t:`${s}:${t}`}c(k,"personKey");async function H(e,t,s,n){n&&await n.prepare("SELECT pg_advisory_xact_lock(hashtext(?))").get(`idempotency:${e}:${t}`),n??=await B();const o=await n.prepare("SELECT body_hash, run_id, response_json, created_at FROM idempotency_keys WHERE grantee = ? AND key = ?").get(e,t);if(!(!o||Date.now()-Date.parse(o.created_at)>=z)){if(o.body_hash!==s)throw new R(409,"idempotency_conflict","key used with a different request");return{run_id:o.run_id,response:JSON.parse(o.response_json)}}}c(H,"findIdempotent");async function ye(e,t,s,n,o,m,i){await e.prepare("DELETE FROM idempotency_keys WHERE grantee = ? AND key = ? AND created_at <= ?").run(t,s,new Date(Date.now()-z).toISOString()),await e.prepare("INSERT INTO idempotency_keys (grantee, key, body_hash, run_id, response_json, created_at) VALUES (?, ?, ?, ?, ?, ?)").run(t,s,n,o,JSON.stringify(m),i)}c(ye,"recordIdempotent");async function qn(e=Date.now()){return Number((await(await B()).prepare("DELETE FROM idempotency_keys WHERE created_at <= ?").run(new Date(e-z).toISOString())).changes)}c(qn,"pruneExpiredIdempotencyKeys");async function he(e,t,s,n,o){const m=n.text;let i=0;return{messageId:(await ze(t,{kind:"message",label:m.slice(0,120),senderNodeId:"human",senderName:s,bodyJson:o?{body:m}:{body:m,start_turn:!1},urgency:o?"normal":"deferred",wake:o?1:0,withinEnqueue:c(async(u,l)=>{n.uses.length&&(await le(s,n.uses,u),await pe(n.uses.map(({upload_id:g,path:E,blob_key:y})=>({upload_id:g,path:E,blob_key:y,run_id:t})),u)),i=(await ce(u,t,t,"node.message.accepted",{message_id:l,start_turn:o})).sequence_number},"withinEnqueue")})).messageId,sequence:i}}c(he,"acceptRunMessage");class Re extends Error{static{c(this,"IdempotentReplay")}winner;constructor(t){super("idempotent replay"),this.winner=t}}const Mt=1440*60*1e3;function Se(e){const t=typeof e=="string"?nt(e):null;if(t===null||!Number.isSafeInteger(t))throw N(`deadline '${String(e)}' is not a duration; use one or more <int>[smhd] parts such as 10m or 1h30m`,"deadline");if(t<=0)throw N("deadline must be greater than zero","deadline");if(t>Mt)throw N("deadline must be at most 24h","deadline");return t}c(Se,"parseRunDeadlineMs");async function Hn(e,t,s,n=we){if(t.isolated&&!it()&&await rt((t.profile===void 0?await te(e.grantee):ne(t.profile)).profileId)===null)throw new R(503,"isolated_unavailable","isolated runs require the Linux root launcher","isolated");t.deadline!==void 0&&Se(t.deadline);const{causedBy:o,...m}=t,i=Q("sha256").update(JSON.stringify(m)).digest("hex");if(s){const a=await H(e.grantee,k(e.sub,s),i);if(a){const p=await q(a.run_id,e.grantee);return!p.pi_pid&&await C(p)==="running"&&(t.output_schema!==void 0&&!p.outcome_at&&await ut(p.node_id)===null&&await re(p.node_id)===void 0&&await oe(p.node_id,"terminal",t.output_schema),await j(p.node_id,{resume:!0,capacity:"freeze"})),a.response}}await yt(e.grantee);const r=t.profile===void 0?await te(e.grantee):ne(t.profile),u=r.manifest.grantee??"app:terminal";if(u!==e.grantee){const a=`crtr:memory:rw:${u}:profile:${r.profileId}`;if(!e.resolved.some(p=>P(p,a))||t.scopes!==null&&!t.scopes.some(p=>P(p,a)))throw new R(403,"scope_missing",`missing scope ${a}`,"profile",void 0,a)}if(t.model!==void 0){const a=t.model;if(tt(a)){if(a.includes("/")&&await J(e.grant)!=="app"){const p=a.lastIndexOf("/"),D=a.slice(0,p),v=a.slice(p+1);if(["ultra","strong","medium","light"].includes(v)&&(await st({kind:"logical",family:D,strength:v,spec:a},Y(e.grantee).files,r.profileId)).every(S=>S.family!==D))throw N(`model '${a}' names a model family that is not configured in this daemon`,"model")}}else if(at(a)===void 0)throw N(`model '${a}' is not a strength (ultra, strong, medium, light), a family/strength, or a provider/model id`,"model")}const l=await Ke(),g=We(Y(e.grantee).nodes,l);if(t.isolated&&t.cwd!==void 0){const a=Ce(g,ke(t.cwd));if(!V(t.cwd)||a===".."||a.startsWith(`..${xe}`)||V(a))throw N("cwd must be inside the isolated root node folder","cwd")}const E=await n(l,e.grantee,t.prompt),y=E.text,d=t.message===void 0?void 0:await n(l,e.grantee,t.message,E.uses.map(a=>a.path)),_=await J(e.grant);let h;try{const a=dt(r,t.model);await et({kind:ot(r),mode:"base",root:!0,rootLifecycle:"resident",readiness:"launch",cwd:t.isolated?t.cwd??g:Y(e.grantee).files,profile:r.profileId,prompt:y,nodeId:l,isolated:t.isolated??!1,...t.causedBy===void 0?{}:{causedBy:t.causedBy},...a===void 0?{}:{model:a},...t.deadline===void 0?{}:{deadlineAt:new Date(Date.now()+Se(t.deadline)).toISOString()},...t.scopes===null?{}:{scopes:t.scopes},run:{grantee:e.grantee,sub:e.sub,grant_id:e.grant,client_id:e.client_id,metadata_json:JSON.stringify(t.metadata),run_id:l,event_cursor:1,usage_json:JSON.stringify(X())},withinCreate:c(async(p,D)=>{if(s){const S=await H(e.grantee,k(e.sub,s),i,p);if(S)throw new Re(S)}const v=E.uses;if(v.length&&(await le(e.grantee,v,p),await pe(v.map(({upload_id:S,path:I,blob_key:U})=>({upload_id:S,path:I,blob_key:U,run_id:l})),p)),h={run_id:l,node_id:l,grantee:e.grantee,grant:e.grant,rev:e.rev,scopes:t.scopes,payer:_,status:"running",created_at:D.created,metadata:t.metadata,sequence_number:0},await ce(p,l,l,"run.started",{scopes:t.scopes,payer:_,usage:X()}),d){const S=await he(p,l,e.grantee,d,!1);h.message={run_id:l,message_id:S.messageId,sequence_number:S.sequence}}s&&await ye(p,e.grantee,k(e.sub,s),i,l,h,D.created)},"withinCreate")},t.output_schema===void 0?void 0:async p=>{await oe(p,"terminal",t.output_schema)})}catch(a){if(a instanceof Re)return a.winner.response;if(t.model!==void 0&&a instanceof Te&&a.code==="usage")throw N(a.message,"model");if(a instanceof Ie&&(a.code==="isolated_run"||a.code==="invalid_request")){const p=a.details&&typeof a.details=="object"&&"param"in a.details&&typeof a.details.param=="string"?a.details.param:void 0;throw new R(a.status,a.code,a.message,p)}throw a}if(!h)throw new Error("run creation did not commit");return h}c(Hn,"startRun");async function Un(e,t){let s;if(t.after)try{const r=JSON.parse(Buffer.from(t.after,"base64url").toString());if(!r||typeof r!="object"||!("activity"in r)||typeof r.activity!="string"||!("id"in r)||typeof r.id!="string")throw new Error("invalid cursor");s={activity:r.activity,id:r.id}}catch{throw N("invalid list cursor","after")}const n=await(await A()).prepareUncached(`SELECT node_id, COALESCE(last_activity_at, created) AS activity FROM node_rows
9
9
  WHERE run_id = node_id AND deleting_at IS NULL ${e===null?"":"AND grantee = ?"}${t.sub===void 0?"":" AND sub = ?"}
10
- ORDER BY activity DESC, node_id DESC`).all(...e===null?[]:[e],...t.sub===void 0?[]:[t.sub]),o=await pe(await x((await pe(n,async({node_id:r})=>!t.visible||await t.visible(r))).filter(({activity:r,node_id:u})=>!s||r<s.activity||r===s.activity&&u<s.id),async r=>({root:await O(r.node_id),activity:r.activity})),async({root:r})=>!t.status||await C(r)===t.status),m=o.slice(0,t.limit),i=m.at(-1);return{runs:await x(m,async({root:r})=>await W(r)),next:o.length>t.limit&&i?Buffer.from(JSON.stringify({activity:i.activity,id:i.root.node_id})).toString("base64url"):null}}c(qn,"listRuns");async function Hn(e,t,s){const n=await q(e,t),o=c(async()=>await W(await q(e,t)),"read");return!s||_e.includes(await C(n))?await o():new Promise((m,i)=>{let r=c(()=>{},"unsubscribe");const u=c(()=>{clearTimeout(d),clearInterval(y),r()},"settle"),l=c(async()=>{u();try{m(await o())}catch(_){i(_)}},"finish"),g=c(async()=>{_e.includes(String((await o()).status))&&await l()},"check"),E=c(()=>{g().catch(_=>{u(),i(_)})},"run"),y=setInterval(E,250),d=setTimeout(()=>{l()},s*1e3);_t(e,E).then(_=>{r=_},_=>{u(),i(_)})})}c(Hn,"waitRun");const Mt=5;async function Un(e,t,s=fe,n=!0,o){const m=e.status==="canceled"||e.outcome_reason==="closed",i=e.grantee??"app:terminal",r=Q("sha256").update(JSON.stringify(["run.message",e.node_id,t,n])).digest("hex"),u=c(async g=>{const E=await O(e.node_id),y=await(await A()).prepare("SELECT 1 FROM deliveries WHERE message_id = ? AND state = 'pending' AND canceled_at IS NULL").get(String(g.message_id));return E&&!m&&n&&!E.pi_pid&&y&&await j(e.node_id,{resume:!0,capacity:"freeze"}),g},"replay");if(o){const g=await H(i,k(e.sub,o),r);if(g)return u(g.response)}if(m)throw new R(409,"run_settled","canceled run cannot receive a message");const l=n&&e.final_report&&!e.pi_pid?(await import("../runtime/reopen.js")).commitReopenResident:void 0;for(let g=1;;g++){const E=await s(e.node_id,i,t),y=await F(async d=>{if(o){const a=await H(i,k(e.sub,o),r,d);if(a)return{replayed:a.response}}if(E.uses.length){await ft(d,e.node_id);for(const a of E.uses)if(await vt(e.node_id,a.path,d))return"path_taken"}await l?.(e.node_id);const _=await Ee(d,e.node_id,i,E,n),h={run_id:e.node_id,message_id:_.messageId,sequence_number:_.sequence};return o&&await ge(d,i,k(e.sub,o),r,e.node_id,h,new Date().toISOString()),{result:h}});if(y==="path_taken"){if(g>=Mt)throw new R(503,"service_unavailable","attachments of concurrent messages kept taking each other's file names; retry");continue}return"replayed"in y?u(y.replayed):(n&&!e.pi_pid&&await j(e.node_id,{resume:!0,capacity:"freeze"}),y.result)}}c(Un,"messageRun");async function At(e){const t=c(()=>new R(503,"service_unavailable",`node ${e} broker was unavailable before the interrupt reached it`),"unavailable");for(let s=0;s<2;s++){const n=await O(e);if(!n)throw G();if(!ne(n)){if(n.streaming)throw t();return}const o=(await K(e))?.executionId;try{await Ze(e)==="turn"&&le({nodes:[e]});return}catch(m){if(!(m instanceof Ve))throw m;const i=await O(e);if(!i)throw G();if(!i.streaming)return;if(s===0&&ne(i)&&(await K(e))?.executionId!==o)continue;throw t()}}throw t()}c(At,"interruptNode");async function $n(e,t="stop"){const s=t==="stop"?(await(await A()).prepare("SELECT node_id FROM nodes WHERE run_id = ?").all(e.node_id)).map(({node_id:n})=>n):[e.node_id];return await Promise.all(s.map(n=>At(n))),await W(await O(e.node_id)??e)}c($n,"interruptRun");async function Pn(e,t={}){const s=(await(await A()).prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(i=>i.node_id);le({run:e.node_id});const n=[];if(await C(e)!=="settled")n.push(...(await re(e.node_id,{preserveEmpty:!0,stopReason:"run_canceled"})).closed);else for(const i of s){if(i===e.node_id)continue;const r=await O(i);r&&r.status!=="done"&&r.status!=="canceled"&&r.status!=="dead"&&n.push(...(await re(i,{preserveEmpty:!0,stopReason:"run_canceled"})).closed)}if(await de({run_id:e.node_id},"the run was canceled"),(await Promise.all([...new Set([e.node_id,...n])].map(i=>te(i,"run_canceled")))).some(i=>!i.confirmed))throw new R(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const m=await O(e.node_id);return await W(m??e)}c(Pn,"cancelRun");const Re=200;async function Bn(e,t){if(typeof t!="string"||!t.trim())throw N("name is required","name");const s=t.trim();if(s.length>Re)throw N(`name exceeds ${Re} characters`,"name");const n=await Ue(e.node_id,{name:s});return n.window&&Pe(n.window,$e(n)),await W(n)}c(Bn,"renameRun");async function jn(e,t={config:Rt,client:ht}){await de({run_id:e.node_id},"the run was deleted");const s=await F(async u=>(await u.prepare("UPDATE nodes SET deleting_at = COALESCE(deleting_at, ?) WHERE node_id = ?").run(new Date().toISOString(),e.node_id),(await u.prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(l=>l.node_id)));if((await Promise.all(s.map(u=>te(u,"run_deleted",{deleting:!0})))).some(u=>!u.confirmed))throw new R(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const o=await x(s,async u=>{const l=await qe(u);if(l.app===null)throw new Error(`run node missing during deletion: ${u}`);return l}),m=await(await A()).prepare("SELECT DISTINCT session_id FROM sessions WHERE session_id IS NOT NULL AND node_id IN (SELECT node_id FROM nodes WHERE run_id = ?)").all(e.node_id);for(const{session_id:u}of m)try{await ee().delete(u)}catch(l){if(!Be(l))throw l}const i=await F(async u=>{for(const y of s){const d=await Fe(u,y);d!==null&&d.deleted_at===null&&await We(u,d)}const l=await Nt([e.node_id],u);await u.prepare("DELETE FROM run_events WHERE run_id = ?").run(e.node_id),await u.prepare("DELETE FROM idempotency_keys WHERE run_id = ?").run(e.node_id);const g=s.map(()=>"?").join(","),E=await u.prepareUncached(`SELECT message_id FROM messages WHERE sender_node_id IN (${g}) UNION SELECT message_id FROM deliveries WHERE destination_id IN (${g})`).all(...s,...s);await u.prepareUncached(`DELETE FROM deliveries WHERE destination_id IN (${g})`).run(...s);for(const{message_id:y}of E)await u.prepare("DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)").run(y,y);return l});for(const u of o)await He(u);const{notifyRunDeleted:r}=await import("./events.js");return r(e.node_id),{uploads_pending:await It(i,t)}}c(jn,"deleteRun");async function It(e,t){if(!e.length||!t.config())return e.length;let s;try{s=t.client()}catch{return e.length}const n=new Set,o=e.map(i=>s.deleteUpload(i).then(async()=>{await St(i),n.add(i)},()=>{}));let m;return await Promise.race([Promise.all(o),new Promise(i=>{m=setTimeout(i,t.budgetMs??bt),m.unref?.()})]),clearTimeout(m),e.length-n.size}c(It,"deleteReleasedUploads");async function Jn(e,t,s){await q(e,t),await Z(e);const n=await F(async d=>{const _=await d.prepare("SELECT node_id, parent FROM nodes WHERE run_id = ? ORDER BY CASE WHEN node_id = ? THEN 0 ELSE 1 END, created, node_id").all(e,e),h=new Map;for(const S of _)h.set(S.node_id,(await d.prepare("SELECT session_id FROM sessions WHERE node_id = ? GROUP BY session_id ORDER BY min(created_at)").all(S.node_id)).map(I=>I.session_id));const p=(await d.prepare("SELECT event_cursor FROM nodes WHERE node_id = ?").get(e)).event_cursor-1,D=await d.prepare(`SELECT node_id, sequence_number FROM run_events
10
+ ORDER BY activity DESC, node_id DESC`).all(...e===null?[]:[e],...t.sub===void 0?[]:[t.sub]),o=await _e(await x((await _e(n,async({node_id:r})=>!t.visible||await t.visible(r))).filter(({activity:r,node_id:u})=>!s||r<s.activity||r===s.activity&&u<s.id),async r=>({root:await O(r.node_id),activity:r.activity})),async({root:r})=>!t.status||await C(r)===t.status),m=o.slice(0,t.limit),i=m.at(-1);return{runs:await x(m,async({root:r})=>await W(r)),next:o.length>t.limit&&i?Buffer.from(JSON.stringify({activity:i.activity,id:i.root.node_id})).toString("base64url"):null}}c(Un,"listRuns");async function $n(e,t,s){const n=await q(e,t),o=c(async()=>await W(await q(e,t)),"read");return!s||ge.includes(await C(n))?await o():new Promise((m,i)=>{let r=c(()=>{},"unsubscribe");const u=c(()=>{clearTimeout(d),clearInterval(y),r()},"settle"),l=c(async()=>{u();try{m(await o())}catch(_){i(_)}},"finish"),g=c(async()=>{ge.includes(String((await o()).status))&&await l()},"check"),E=c(()=>{g().catch(_=>{u(),i(_)})},"run"),y=setInterval(E,250),d=setTimeout(()=>{l()},s*1e3);wt(e,E).then(_=>{r=_},_=>{u(),i(_)})})}c($n,"waitRun");const At=5;async function Pn(e,t,s=we,n=!0,o){const m=e.status==="canceled"||e.outcome_reason==="closed",i=e.grantee??"app:terminal",r=Q("sha256").update(JSON.stringify(["run.message",e.node_id,t,n])).digest("hex"),u=c(async g=>{const E=await O(e.node_id),y=await(await A()).prepare("SELECT 1 FROM deliveries WHERE message_id = ? AND state = 'pending' AND canceled_at IS NULL").get(String(g.message_id));return E&&!m&&n&&!E.pi_pid&&y&&await j(e.node_id,{resume:!0,capacity:"freeze"}),g},"replay");if(o){const g=await H(i,k(e.sub,o),r);if(g)return u(g.response)}if(m)throw new R(409,"run_settled","canceled run cannot receive a message");const l=n&&e.final_report&&!e.pi_pid?(await import("../runtime/reopen.js")).commitReopenResident:void 0;for(let g=1;;g++){const E=await s(e.node_id,i,t),y=await F(async d=>{if(o){const a=await H(i,k(e.sub,o),r,d);if(a)return{replayed:a.response}}if(E.uses.length){await _t(d,e.node_id);for(const a of E.uses)if(await bt(e.node_id,a.path,d))return"path_taken"}await l?.(e.node_id);const _=await he(d,e.node_id,i,E,n),h={run_id:e.node_id,message_id:_.messageId,sequence_number:_.sequence};return o&&await ye(d,i,k(e.sub,o),r,e.node_id,h,new Date().toISOString()),{result:h}});if(y==="path_taken"){if(g>=At)throw new R(503,"service_unavailable","attachments of concurrent messages kept taking each other's file names; retry");continue}return"replayed"in y?u(y.replayed):(n&&!e.pi_pid&&await j(e.node_id,{resume:!0,capacity:"freeze"}),y.result)}}c(Pn,"messageRun");async function It(e){const t=c(()=>new R(503,"service_unavailable",`node ${e} broker was unavailable before the interrupt reached it`),"unavailable");for(let s=0;s<2;s++){const n=await O(e);if(!n)throw G();if(!ae(n)){if(n.streaming)throw t();return}const o=(await K(e))?.executionId;try{await Ze(e)==="turn"&&fe({nodes:[e]});return}catch(m){if(!(m instanceof Ve))throw m;const i=await O(e);if(!i)throw G();if(!i.streaming)return;if(s===0&&ae(i)&&(await K(e))?.executionId!==o)continue;throw t()}}throw t()}c(It,"interruptNode");async function Bn(e,t="stop"){const s=t==="stop"?(await(await A()).prepare("SELECT node_id FROM nodes WHERE run_id = ?").all(e.node_id)).map(({node_id:n})=>n):[e.node_id];return await Promise.all(s.map(n=>It(n))),await W(await O(e.node_id)??e)}c(Bn,"interruptRun");async function jn(e,t={}){const s=(await(await A()).prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(i=>i.node_id);fe({run:e.node_id});const n=[];if(await C(e)!=="settled")n.push(...(await de(e.node_id,{preserveEmpty:!0,stopReason:"run_canceled"})).closed);else for(const i of s){if(i===e.node_id)continue;const r=await O(i);r&&r.status!=="done"&&r.status!=="canceled"&&r.status!=="dead"&&n.push(...(await de(i,{preserveEmpty:!0,stopReason:"run_canceled"})).closed)}if(await ue({run_id:e.node_id},"the run was canceled"),(await Promise.all([...new Set([e.node_id,...n])].map(i=>se(i,"run_canceled")))).some(i=>!i.confirmed))throw new R(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const m=await O(e.node_id);return await W(m??e)}c(jn,"cancelRun");const Ne=200;async function Jn(e,t){if(typeof t!="string"||!t.trim())throw N("name is required","name");const s=t.trim();if(s.length>Ne)throw N(`name exceeds ${Ne} characters`,"name");const n=await Pe(e.node_id,{name:s});return n.window&&je(n.window,Be(n)),await W(n)}c(Jn,"renameRun");async function Yn(e,t={config:St,client:Rt}){await ue({run_id:e.node_id},"the run was deleted");const s=await F(async u=>(await u.prepare("UPDATE nodes SET deleting_at = COALESCE(deleting_at, ?) WHERE node_id = ?").run(new Date().toISOString(),e.node_id),(await u.prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(l=>l.node_id)));if((await Promise.all(s.map(u=>se(u,"run_deleted",{deleting:!0})))).some(u=>!u.confirmed))throw new R(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const o=await x(s,async u=>{const l=await Ue(u);if(l.app===null)throw new Error(`run node missing during deletion: ${u}`);return l}),m=await(await A()).prepare("SELECT DISTINCT session_id FROM sessions WHERE session_id IS NOT NULL AND node_id IN (SELECT node_id FROM nodes WHERE run_id = ?)").all(e.node_id);for(const{session_id:u}of m)try{await ee().delete(u)}catch(l){if(!Je(l))throw l}const i=await F(async u=>{for(const y of s){const d=await He(u,y);d!==null&&d.deleted_at===null&&await qe(u,d)}const l=await vt([e.node_id],u);await u.prepare("DELETE FROM run_events WHERE run_id = ?").run(e.node_id),await u.prepare("DELETE FROM idempotency_keys WHERE run_id = ?").run(e.node_id);const g=s.map(()=>"?").join(","),E=await u.prepareUncached(`SELECT message_id FROM messages WHERE sender_node_id IN (${g}) UNION SELECT message_id FROM deliveries WHERE destination_id IN (${g})`).all(...s,...s);await u.prepareUncached(`DELETE FROM deliveries WHERE destination_id IN (${g})`).run(...s);for(const{message_id:y}of E)await u.prepare("DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)").run(y,y);return l});for(const u of o)await $e(u);const{notifyRunDeleted:r}=await import("./events.js");return r(e.node_id),{uploads_pending:await Tt(i,t)}}c(Yn,"deleteRun");async function Tt(e,t){if(!e.length||!t.config())return e.length;let s;try{s=t.client()}catch{return e.length}const n=new Set,o=e.map(i=>s.deleteUpload(i).then(async()=>{await Nt(i),n.add(i)},()=>{}));let m;return await Promise.race([Promise.all(o),new Promise(i=>{m=setTimeout(i,t.budgetMs??Ot),m.unref?.()})]),clearTimeout(m),e.length-n.size}c(Tt,"deleteReleasedUploads");async function Gn(e,t,s){await q(e,t),await Z(e);const n=await F(async d=>{const _=await d.prepare("SELECT node_id, parent FROM nodes WHERE run_id = ? ORDER BY CASE WHEN node_id = ? THEN 0 ELSE 1 END, created, node_id").all(e,e),h=new Map;for(const S of _)h.set(S.node_id,(await d.prepare("SELECT session_id FROM sessions WHERE node_id = ? GROUP BY session_id ORDER BY min(created_at)").all(S.node_id)).map(I=>I.session_id));const p=(await d.prepare("SELECT event_cursor FROM nodes WHERE node_id = ?").get(e)).event_cursor-1,D=await d.prepare(`SELECT node_id, sequence_number FROM run_events
11
11
  WHERE run_id = ? AND sequence_number <= ? AND type IN ('node.thinking.done', 'node.output_text.done', 'usage')
12
12
  ORDER BY sequence_number`).all(e,p),v=await d.prepare(`SELECT node_id, sequence_number, type, body_json FROM run_events
13
13
  WHERE run_id = ? AND sequence_number <= ? AND type IN ('node.thinking.delta', 'node.output_text.delta')
14
- ORDER BY sequence_number`).all(e,p);return{nodes:_,sessionIds:h,latestSequence:p,completed:D,deltas:v}}),{nodes:o,sessionIds:m,latestSequence:i,completed:r,deltas:u}=n,l=await x(o,async d=>({node_id:d.node_id,parent_node_id:d.parent,conversations:await x(m.get(d.node_id)??[],async _=>{const{header:h,entries:a}=await ee().read(_);if(s==="entries")return{conversation_id:_,header:h,entries:a};const p=xe.inMemory(h.cwd,void 0,[h,...a]),D=dt(p)??[],v=new Map(a.map((w,b)=>[w.id,b])),S=a.filter(w=>w.type==="custom"&&w.customType==="crtr-system-prompt").map(w=>({id:w.id,message:{role:"custom",customType:"crtr-system-prompt",data:"data"in w?w.data:void 0,timestamp:w.timestamp}})),I=a.filter(w=>w.type==="custom_message"&&w.customType==="app_message").map(w=>({id:w.id,message:{role:"custom",customType:"app_message",content:"content"in w?w.content:"",timestamp:w.timestamp}})),U=d.node_id===e?a.find(w=>{if(w.type!=="message"||w.message.role!=="user")return!1;const b=se(a,w.message.timestamp);return b?.type==="runtime"&&b.kind==="kickoff"})?.id:void 0,Se=[...D.filter(({id:w})=>!I.some(b=>b.id===w)),...S,...I].sort((w,b)=>(v.get(w.id)??Number.MAX_SAFE_INTEGER)-(v.get(b.id)??Number.MAX_SAFE_INTEGER)).map(({id:w,message:b})=>{const f=b,T=f.usage,$=f.role==="user"?se(a,Number(f.timestamp)):null,Ne=$?.type==="human"||w===U,L=f.role==="toolResult"?"tool_result":f.role==="bashExecution"?"bash_execution":f.role==="compactionSummary"?"compaction_summary":f.role==="branchSummary"?"branch_summary":f.role==="custom"&&f.customType==="crtr-system-prompt"?"system":f.role==="user"?Ne?"user":"custom":f.role,ve=L==="custom"?f.role==="custom"?f.customType:$?.type==="runtime"?$.kind:"unknown":void 0,be=L==="system"&&f.customType==="crtr-system-prompt"?[{type:"text",text:f.data?.text??""}]:typeof f.content=="string"?[{type:"text",text:f.content}]:Array.isArray(f.content)?f.content.map(M=>M.type==="toolCall"?{type:"tool_call",tool_call_id:M.id,name:M.name,arguments:M.arguments}:M.type==="image"?{type:"image",mime_type:M.mimeType}:M.type==="thinking"?{type:"thinking",text:M.thinking}:M):[];return{entry_id:w,role:L,...L==="custom"?{custom_type:ve}:{},time:typeof f.timestamp=="string"?f.timestamp:new Date(Number(f.timestamp??Date.now())).toISOString(),content:be,...L==="assistant"?{model:f.model,provider:f.provider,stop_reason:f.stopReason,...f.errorMessage?{error_message:f.errorMessage}:{},...T?{usage:{input_tokens:T.input??0,output_tokens:T.output??0,cache_read_tokens:T.cacheRead??0,cache_write_tokens:T.cacheWrite??0,cost_usd:T.cost?.total??0}}:{}}:{},...L==="tool_result"?{tool_call_id:f.toolCallId,tool_name:f.toolName,is_error:f.isError}:{}}})??[];return{conversation_id:_,messages:Se}})})),g=new Map(await Promise.all(l.map(async d=>[d.node_id,await lt(d.node_id)])));for(const d of r){const _=g.get(d.node_id);_!=null&&d.sequence_number>=_&&g.set(d.node_id,null)}const E=new Map;for(const d of u){const _=g.get(d.node_id);if(_==null||d.sequence_number<_)continue;const h=JSON.parse(d.body_json),a=E.get(d.node_id)??{thinking:"",text:""};d.type==="node.thinking.delta"?a.thinking+=h.delta:a.text+=h.delta,E.set(d.node_id,a)}const y=l.map(d=>({...d,in_progress_message:g.get(d.node_id)==null?null:E.get(d.node_id)??{thinking:"",text:""}}));return{run_id:e,latest_sequence:i,nodes:y}}c(Jn,"traceRun");function Yn(e,t,s){if(t===void 0){if(!e.some(n=>P(n,"crtr:llm")))throw new R(403,"scope_missing","missing scope crtr:llm",void 0,void 0,"crtr:llm");return null}if(!Array.isArray(t)||t.some(n=>typeof n!="string"))throw N("scopes must be a list of scope strings","scopes");for(const n of t){try{pt(n)}catch{throw N(`invalid scope ${n}`,"scopes")}if(/^crtr:files:(?:read|rw):app:/.test(n)&&n.split(":")[4]===s.slice(4))throw N(`own-app files cannot narrow a run: ${n}`,"scopes");if(!(/^crtr:memory:(?:read|rw):app:/.test(n)&&n.split(":")[4]===s.slice(4))&&!De(e,n))throw new R(403,"scope_missing",`missing scope ${n}`,void 0,void 0,n)}if(!t.includes("crtr:llm"))throw new R(403,"scope_missing","missing scope crtr:llm",void 0,void 0,"crtr:llm");return t}c(Yn,"requestedScopes");export{z as IDEMPOTENCY_WINDOW_MS,Dt as RUN_DEADLINE_MAX_MS,bt as RUN_DELETE_STORAGE_BUDGET_MS,Re as RUN_NAME_MAX,R as RunError,Pn as cancelRun,Ot as cloudPersonScope,jn as deleteRun,xn as idempotencyKeyOf,$n as interruptRun,qn as listRuns,Un as messageRun,q as ownedRun,he as parseRunDeadlineMs,Wn as pruneExpiredIdempotencyKeys,Bn as renameRun,Yn as requestedScopes,kn as runIsRunning,W as runObject,Fn as startRun,Jn as traceRun,Hn as waitRun};
14
+ ORDER BY sequence_number`).all(e,p);return{nodes:_,sessionIds:h,latestSequence:p,completed:D,deltas:v}}),{nodes:o,sessionIds:m,latestSequence:i,completed:r,deltas:u}=n,l=await x(o,async d=>({node_id:d.node_id,parent_node_id:d.parent,conversations:await x(m.get(d.node_id)??[],async _=>{const{header:h,entries:a}=await ee().read(_);if(s==="entries")return{conversation_id:_,header:h,entries:a};const p=Fe.inMemory(h.cwd,void 0,[h,...a]),D=ct(p)??[],v=new Map(a.map((w,b)=>[w.id,b])),S=a.filter(w=>w.type==="custom"&&w.customType==="crtr-system-prompt").map(w=>({id:w.id,message:{role:"custom",customType:"crtr-system-prompt",data:"data"in w?w.data:void 0,timestamp:w.timestamp}})),I=a.filter(w=>w.type==="custom_message"&&w.customType==="app_message").map(w=>({id:w.id,message:{role:"custom",customType:"app_message",content:"content"in w?w.content:"",timestamp:w.timestamp}})),U=d.node_id===e?a.find(w=>{if(w.type!=="message"||w.message.role!=="user")return!1;const b=ie(a,w.message.timestamp);return b?.type==="runtime"&&b.kind==="kickoff"})?.id:void 0,ve=[...D.filter(({id:w})=>!I.some(b=>b.id===w)),...S,...I].sort((w,b)=>(v.get(w.id)??Number.MAX_SAFE_INTEGER)-(v.get(b.id)??Number.MAX_SAFE_INTEGER)).map(({id:w,message:b})=>{const f=b,T=f.usage,$=f.role==="user"?ie(a,Number(f.timestamp)):null,be=$?.type==="human"||w===U,L=f.role==="toolResult"?"tool_result":f.role==="bashExecution"?"bash_execution":f.role==="compactionSummary"?"compaction_summary":f.role==="branchSummary"?"branch_summary":f.role==="custom"&&f.customType==="crtr-system-prompt"?"system":f.role==="user"?be?"user":"custom":f.role,Oe=L==="custom"?f.role==="custom"?f.customType:$?.type==="runtime"?$.kind:"unknown":void 0,De=L==="system"&&f.customType==="crtr-system-prompt"?[{type:"text",text:f.data?.text??""}]:typeof f.content=="string"?[{type:"text",text:f.content}]:Array.isArray(f.content)?f.content.map(M=>M.type==="toolCall"?{type:"tool_call",tool_call_id:M.id,name:M.name,arguments:M.arguments}:M.type==="image"?{type:"image",mime_type:M.mimeType}:M.type==="thinking"?{type:"thinking",text:M.thinking}:M):[];return{entry_id:w,role:L,...L==="custom"?{custom_type:Oe}:{},time:typeof f.timestamp=="string"?f.timestamp:new Date(Number(f.timestamp??Date.now())).toISOString(),content:De,...L==="assistant"?{model:f.model,provider:f.provider,stop_reason:f.stopReason,...f.errorMessage?{error_message:f.errorMessage}:{},...T?{usage:{input_tokens:T.input??0,output_tokens:T.output??0,cache_read_tokens:T.cacheRead??0,cache_write_tokens:T.cacheWrite??0,cost_usd:T.cost?.total??0}}:{}}:{},...L==="tool_result"?{tool_call_id:f.toolCallId,tool_name:f.toolName,is_error:f.isError}:{}}})??[];return{conversation_id:_,messages:ve}})})),g=new Map(await Promise.all(l.map(async d=>[d.node_id,await pt(d.node_id)])));for(const d of r){const _=g.get(d.node_id);_!=null&&d.sequence_number>=_&&g.set(d.node_id,null)}const E=new Map;for(const d of u){const _=g.get(d.node_id);if(_==null||d.sequence_number<_)continue;const h=JSON.parse(d.body_json),a=E.get(d.node_id)??{thinking:"",text:""};d.type==="node.thinking.delta"?a.thinking+=h.delta:a.text+=h.delta,E.set(d.node_id,a)}const y=l.map(d=>({...d,in_progress_message:g.get(d.node_id)==null?null:E.get(d.node_id)??{thinking:"",text:""}}));return{run_id:e,latest_sequence:i,nodes:y}}c(Gn,"traceRun");function Xn(e,t,s){if(t===void 0){if(!e.some(n=>P(n,"crtr:llm")))throw new R(403,"scope_missing","missing scope crtr:llm",void 0,void 0,"crtr:llm");return null}if(!Array.isArray(t)||t.some(n=>typeof n!="string"))throw N("scopes must be a list of scope strings","scopes");for(const n of t){try{ft(n)}catch{throw N(`invalid scope ${n}`,"scopes")}if(/^crtr:files:(?:read|rw):app:/.test(n)&&n.split(":")[4]===s.slice(4))throw N(`own-app files cannot narrow a run: ${n}`,"scopes");if(!(/^crtr:memory:(?:read|rw):app:/.test(n)&&n.split(":")[4]===s.slice(4))&&!Ae(e,n))throw new R(403,"scope_missing",`missing scope ${n}`,void 0,void 0,n)}if(!t.includes("crtr:llm"))throw new R(403,"scope_missing","missing scope crtr:llm",void 0,void 0,"crtr:llm");return t}c(Xn,"requestedScopes");export{z as IDEMPOTENCY_WINDOW_MS,Mt as RUN_DEADLINE_MAX_MS,Ot as RUN_DELETE_STORAGE_BUDGET_MS,Ne as RUN_NAME_MAX,R as RunError,jn as cancelRun,Dt as cloudPersonScope,Yn as deleteRun,Fn as idempotencyKeyOf,Bn as interruptRun,Un as listRuns,Pn as messageRun,q as ownedRun,Se as parseRunDeadlineMs,qn as pruneExpiredIdempotencyKeys,Jn as renameRun,Xn as requestedScopes,Wn as runIsRunning,W as runObject,Hn as startRun,Gn as traceRun,$n as waitRun};
@@ -0,0 +1,2 @@
1
+ /** The Blaxel environment the node's profile points at, or null when it runs on a machine. Reads rows only, so it is safe before any environment is registered. A leaf module: the launch and run-start paths import it without pulling in the ledger. */
2
+ export declare function blaxelEnvironmentOf(profileId: string | null): Promise<string | null>;
@@ -0,0 +1 @@
1
+ var o=Object.defineProperty;var t=(e,n)=>o(e,"name",{value:n,configurable:!0});import{openDb as r}from"../canvas/db.js";async function a(e){return e===null?null:(await(await r()).prepare("SELECT e.object AS object FROM profiles p JOIN environments e ON e.object = p.environment_id WHERE p.id = ? AND e.kind = 'blaxel'").get(e))?.object??null}t(a,"blaxelEnvironmentOf");export{a as blaxelEnvironmentOf};
@@ -65,6 +65,10 @@ export declare class FaultRetry {
65
65
  constructor(deps: FaultRetryDeps);
66
66
  clearTimer(): void;
67
67
  reset(): void;
68
+ /** Whether a model fallback has been started and may still prompt a recovery turn. */
69
+ fallbackInFlight(): boolean;
70
+ /** The recorded provider fault is fatal: nothing is armed to re-drive the node. Only meaningful right after `schedule()` armed nothing. */
71
+ faultIsFatal(): Promise<boolean>;
68
72
  /** No recovery turn will follow the settled turn: a run node writes its held-back turn end now. */
69
73
  abandonTurnEnd(): void;
70
74
  private state;
@@ -1 +1 @@
1
- var ce=Object.defineProperty;var m=(r,e)=>ce(r,"name",{value:e,configurable:!0});import{envModelIntent as B,envNodeCwd as j,envProfileId as Y}from"../../../shared/env.js";import{isContextOverflow as q}from"@earendil-works/pi-ai";import{classify as T}from"../../fault-classifier.js";import{isDaemonTransportApiError as V}from"../../../api/errors.js";import{isModelNotFoundError as fe,isProviderUnconfiguredError as pe}from"../fault.js";import{brokerRecovery as he,daemonClient as me,mutateBrokerFault as X,mutateBrokerProviderRetry as I}from"./daemon-ops.js";import{extractCoolingDeadline as ge}from"../managed-provider-cooling.js";import{extractProviderFailureDetails as ye}from"../../provider-failure.js";import{expandModelCandidates as J,modelRequestFromConfig as z}from"../../model-routes.js";import{operationIdContext as H}from"../../events/operation-id.js";import{emitEvent as F}from"../../events/emit.js";import{CONNECTION_FAULT_RECOVERY_BODY as ve,PROVIDER_FAULT_RECOVERY_BODY as we,RUN_CONNECTION_FAULT_RETRY_BODY as Fe,formatCard as K,formatModelFallbackRecovery as be}from"../../../shared/generated-context.js";import{markFatalOnExhaust as Q,nextFaultRetry as C,policyFor as Z}from"../fault-recovery.js";import{parseModelSpec as ee}from"../model-selection.js";import{endedByAbort as te}from"../session-cycles.js";import{isManagedProvider as ke,resolveProviderCandidates as Ie}from"../../subscription-state.js";import{announceMessageOrigin as ne}from"../stamp/channel.js";import{LLM_REFUSAL_DIAGNOSTIC as _e,refusalRetryAt as Ee}from"./model-adapter.js";import{isSafetyRefusal as ie}from"../../llm/refusal.js";const Re=2147483647,re=3e4;function Se(r,e,t){const n=Date.parse(r);return!Number.isFinite(n)||t+e-n>re}m(Se,"runTurnRetryExpired");class _ extends Error{static{m(this,"StaleOutcome")}}const Ae=1e3,Me=3e4;function xe(r,e){return r!=="connection"?we:e?Fe:ve}m(xe,"retryCardBody");function R(r){return{link:r.link,op:r.op,kind:r.kind,retry:r.retry,message:r.message,since:r.since,operation_id:r.operation_id,...r.anchor_entry_id===void 0?{}:{anchorEntryId:r.anchor_entry_id},...r.provider_error===void 0?{}:{providerError:r.provider_error}}}m(R,"policyFault");function se(r){return r instanceof Error?r.message:String(r)}m(se,"errorText");function oe(r){return V(r)||T("pi\u2192provider",r).disposition==="auto"}m(oe,"isTransientRejection");function O(r){return{link:r.link,op:r.op,kind:r.kind,retry:r.retry,message:r.message,...r.operation_id===void 0?{}:{operation_id:r.operation_id},...r.since===void 0?{}:{since:r.since},...r.anchorEntryId===void 0?{}:{anchor_entry_id:r.anchorEntryId},...r.providerError===void 0?{}:{provider_error:r.providerError}}}m(O,"faultInput");function ae(r,e){const t=m(n=>`${n.providerId}/${n.modelId}`===e.modelSpec,"onLiveModel");return(r.find(n=>t(n)&&n.thinkingLevel===e.thinkingLevel)??r.find(t))?.rank}m(ae,"liveRouteRank");function de(r){const e=T("pi\u2192provider",r),t=r.diagnostics?.some(n=>n.type===_e)??!1;return{classified:e,disposition:t?"fatal":e.disposition}}m(de,"settledProviderFault");function Ze(r,e){if(r.stopReason!=="error"||te(r)||ie(r)||q(r,e))return!1;const{classified:t,disposition:n}=de(r);return n==="auto"&&(t.kind==="connection"||t.kind==="rate-limit"||t.kind==="overloaded")}m(Ze,"willDaemonRetry");const Te=/does not support assistant message prefill|conversation must end with a user message/i;function Ce(r,e){return e&&Te.test(r)}m(Ce,"isPrefillRejectionDuringEpisode");class et{static{m(this,"FaultRetry")}deps;timer=null;failedRetryRoutes=new Set;notFoundModels=new Set;providerFallbackInFlight=null;notFoundFallbackInFlight=null;stagedCapacityFailure=null;agentStarts=0;constructor(e){this.deps=e}clearTimer(){this.timer!==null&&(clearTimeout(this.timer),this.timer=null)}reset(){this.clearTimer(),this.deps.turnEnds?.abandon(),this.providerFallbackInFlight=null,this.notFoundFallbackInFlight=null,this.stagedCapacityFailure=null}abandonTurnEnd(){this.deps.turnEnds?.abandon()}state(){return he(this.deps.nodeId)}async recordFault(e){return(await X(this.deps.nodeId,{op:"record",input:e})).fault}async clearFault(e,t=!1){await X(this.deps.nodeId,{op:"clear",...e===void 0?{}:{link:e},...t?{preserve_episode:!0}:{}})}sessionId(e){const t=e.sessionManager.getSessionId?.();return typeof t=="string"&&t!==""?t:null}async clearEpisode(e){const t=this.sessionId(e);t!==null&&await I(this.deps.nodeId,{op:"clear",session_id:t})}onEvent(e){e.type==="agent_start"&&this.agentStarts++,this.maybeSwitchProviderForRetry(e),this.maybeFallbackOnUnusableModel(e)}isActiveAutoFault(e){return e===null||e.retry.disposition!=="auto"||e.retry.by!=="daemon"?!1:e.kind==="connection"||e.kind==="rate-limit"||e.kind==="overloaded"}async publishSettledProviderFault(e){const t={agentEnd:e.stagedProviderAgentEnd,watchdogAbort:e.stagedWatchdogAbort,refreshAbort:e.stagedRefreshAbort,overflowFailure:e.stagedOverflowFailure,capacityFailure:this.stagedCapacityFailure?.generation===e?this.stagedCapacityFailure:null};this.stagedCapacityFailure=null,e.stagedProviderAgentEnd=null,e.stagedWatchdogAbort=!1,e.stagedRefreshAbort=!1,e.stagedOverflowFailure=null;const n=this.agentStarts,i=m(()=>{if(this.deps.installedGeneration()!==e||this.agentStarts!==n)throw new _},"assertCurrent");try{await this.retryWhileDaemonUnreachable("settled turn fault write",()=>this.recordStagedOutcome(e,t,i),i)}catch(s){if(!(s instanceof _))throw s}}async retryWhileDaemonUnreachable(e,t,n){let i=Ae;for(;;){try{await t();return}catch(s){if(!V(s))throw s;F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`${e} waiting for the daemon: ${s.message}`}})}await new Promise(s=>setTimeout(s,i)),i=Math.min(i*2,Me),n()}}async recordStagedOutcome(e,t,n){const{agentEnd:i,watchdogAbort:s,refreshAbort:d,overflowFailure:c,capacityFailure:f}=t,o=e.session,a=m(async b=>{n(),await this.clearEpisode(b)},"clearEpisode"),g=m(async b=>{n(),await this.recordFault(b)},"recordFault"),y=m(async(b,ue)=>{n(),await this.recordPendingProviderFault(b,ue)},"recordPendingProviderFault"),u=await this.state(),p=u.fault,v=u.episode,k=this.sessionId(o),w=this.isActiveAutoFault(p)&&p.link==="pi\u2192provider"?p:v?.state==="admitted"&&v.session_id===k&&this.isActiveAutoFault(v.fault)?v.fault:null,h=w===null?null:{since:w.since,anchorEntryId:w.anchor_entry_id,attempt:w.retry.attempt},l=[...Array.isArray(i?.messages)?i.messages:[]].reverse().find(b=>typeof b=="object"&&b!==null&&b.role==="assistant");if(f!==null||c!==null){await a(o),await g({link:"pi\u2192provider",op:"context overflow recovery",kind:"context-overflow",retry:{disposition:"fatal"},message:f?.errorMessage??c.errorMessage,anchor_entry_id:o.sessionManager.getLeafId?.()??void 0});return}if(s&&l?.stopReason==="aborted"){await y(o,{link:"pi\u2192provider",op:"generation turn",kind:"connection",retry:{disposition:"auto",by:"daemon",...h?.attempt!==void 0?{attempt:h.attempt}:{}},message:typeof l.errorMessage=="string"?l.errorMessage:"engine error (no errorMessage recorded)",...h!==null?{since:h.since}:{},anchor_entry_id:this.retryAnchor(o,h?.anchorEntryId)});return}if(l?.stopReason!=="error"){l!==void 0&&await a(o);return}if(d){await a(o);return}if(ie(l)){await a(o);return}const A=typeof l.errorMessage=="string"?l.errorMessage:"engine error (no errorMessage recorded)";if(te({stopReason:"error",errorMessage:A})){await a(o);return}const E=q(l,o.model?.contextWindow),M=de(l),$=h!==null&&M.disposition!=="auto"&&Ce(A,!0),le=$?{kind:"connection",disposition:"auto"}:M.classified,S=$?"auto":M.disposition,D=ge(l),L=Ee(l),N=ye(l),G=typeof l.provider=="string"&&l.provider!==""?l.provider:o.model?.provider,U=typeof l.model=="string"&&l.model!==""?l.model:o.model?.id,W=N===void 0||G===void 0||U===void 0?void 0:{provider:G,model:U,...N};E&&await a(o);const x={link:"pi\u2192provider",op:"generation turn",kind:E?"context-overflow":le.kind,retry:E?{disposition:"fatal"}:S==="auto"?{disposition:"auto",by:"daemon",...D!==void 0?{nextAt:new Date(D).toISOString()}:{},...h?.attempt!==void 0?{attempt:h.attempt}:{}}:{disposition:S,...L!==void 0?{nextAt:new Date(L).toISOString()}:{}},message:A,...!E&&S==="auto"&&h!==null?{since:h.since}:{},anchor_entry_id:!E&&S==="auto"?this.retryAnchor(o,h?.anchorEntryId):o.sessionManager.getLeafId?.()??void 0,...W===void 0?{}:{provider_error:W}};x.retry.disposition==="auto"?await y(o,x):(await a(o),await g(x))}retryAnchor(e,t){const n=e.sessionManager.getLeafId?.()??void 0;return t!==void 0&&!this.hasProgressPastAnchor(e,t)?t:n}async recoverOnStartup(){const e=this.deps.installedGeneration();if(e===void 0)return"none";const t=(await this.state()).episode,n=this.sessionId(e.session);if(this.deps.cfg.newCycle===!0)return t!==null&&n!==null&&t.session_id===n&&await I(this.deps.nodeId,{op:"invalidate",session_id:n}),"none";if(t===null||n===null||t.session_id!==n)return"none";if(t.state==="admitted")if(t.fault.anchor_entry_id!==void 0&&!this.hasProgressPastAnchor(e.session,t.fault.anchor_entry_id)){if(!(await I(this.deps.nodeId,{op:"reopen",session_id:n})).applied)return"none"}else return await this.clearEpisode(e.session),"none";else if(t.state!=="pending")return"none";await this.recordFault(O(R(t.fault)));const i=await this.schedule();return i==="armed"?"retry-armed":i==="exhausted"?"fatal":"none"}hasProgressPastAnchor(e,t){const n=e.sessionManager.getBranch(),i=n.findIndex(d=>d.id===t);return(i===-1?n:n.slice(i+1)).some(d=>{if(d.type!=="message")return!1;const{message:c}=d;return c.role==="toolResult"?!0:c.role==="assistant"&&Array.isArray(c.content)&&c.content.length>0})}async schedule(){const e=this.deps.installedGeneration(),t=this.deps.currentSession();if(t.isStreaming||this.timer!==null)return this.timer!==null?"armed":"none";if(e===void 0)return this.abandonTurnEnd(),"none";const n=await this.state(),i=n.fault;if(!this.isActiveAutoFault(i)||this.sessionId(t)!==null&&!this.pendingEpisodeMatches(t,i,n))return this.clearTimer(),this.abandonTurnEnd(),"none";const s=Date.now(),d=this.faultRetryDelayMs(i,s);return d!==null&&this.deps.turnEnds?.holding()===!0&&Se(i.since,d,s)?(await this.endRunTurnOnFault(t,i,d),"none"):d!==null?(this.clearAndArmFaultRetry(d,e),this.timer!==null?"armed":"none"):(this.abandonTurnEnd(),i.retry.nextAt!==void 0||this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming?"none":(await this.settleExhausted(t,i),"exhausted"))}async settleExhausted(e,t){await this.recordFault(O(Q(R(t)))),await this.clearEpisode(e)}async endRunTurnOnFault(e,t,n){this.clearTimer(),this.abandonTurnEnd(),F({level:"info",event:"broker.runtime.diagnostic",fields:{message:`run turn completed on provider fault: ${t.kind} retry in ${n}ms is past the ${re}ms turn window (since ${t.since}, attempt ${t.retry.attempt??0})`}}),await this.clearEpisode(e),await this.clearFault("pi\u2192provider")}async rearmIfStranded(){if(this.timer!==null||this.deps.installedGeneration()===void 0)return;const e=this.deps.currentSession();if(e.isStreaming)return;const t=await this.state();!this.isActiveAutoFault(t.fault)||!this.pendingEpisodeMatches(e,t.fault,t)||await this.schedule()}maybeSwitchProviderForRetry(e){if(e.type!=="auto_retry_start")return;const t=T("pi\u2192provider",e.errorMessage??"").kind;if(t!=="rate-limit"&&t!=="connection"||this.providerFallbackInFlight!==null||this.deps.cfg.modelExact===!0)return;const n=this.deps.installedGeneration();if(n===void 0)return;const i=this.deps.currentSession(),s=this.deps.currentServices(),d=this.deps.formatModelSpec(i.model,i.thinkingLevel);if(d===null)return;const c=z(this.deps.cfg.model,B(),!1);if(c===void 0)return;const f=ee(d),o=(async()=>{const a=await J(c,j()??this.deps.cfg.cwd,Y()),g=ae(a,f),y=g===void 0?{route:void 0,capacityExhausted:!1}:await this.nextEligibleFallbackRoute(a.slice(g+1),this.deps.registryOf(s),i.getContextUsage()?.tokens,k=>!this.failedRetryRoutes.has(k.routeId));if(y.route===void 0){y.capacityExhausted&&(this.stageCapacityFailure(n,i),queueMicrotask(()=>{this.deps.installedGeneration()===n&&this.deps.currentSession()===i&&i.abortRetry()}));return}const u=y.route,p=this.deps.registryOf(s).find(u.providerId,u.modelId);if(!p||(await i.setModel(p),this.deps.installedGeneration()!==n||this.deps.currentSession()!==i))return;const v=`${u.providerId}/${u.modelId}`===f.modelSpec?f.thinkingLevel:u.thinkingLevel;i.setThinkingLevel(v??"off"),this.failedRetryRoutes.add(u.routeId),await this.deps.broadcastModelChanged(!1)})().catch(a=>{F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`provider route fallback failed: ${a instanceof Error?a.message:String(a)}`}})}).finally(()=>{this.deps.installedGeneration()===n&&(this.providerFallbackInFlight=null)});this.providerFallbackInFlight=o}maybeFallbackOnUnusableModel(e){if(e.type!=="message_end"||e.message.role!=="assistant"||e.message.stopReason!=="error")return;const t=pe(e.message.errorMessage??"");if(!t&&!fe(e.message.errorMessage??"")||this.deps.cfg.modelExact===!0||this.notFoundFallbackInFlight!==null)return;const n=this.deps.installedGeneration();if(n===void 0)return;const i=this.deps.currentSession(),s=this.deps.currentServices(),d=this.deps.formatModelSpec(i.model,i.thinkingLevel);if(d===null)return;const c=ee(d);this.notFoundModels.add(c.modelSpec);const f=z(this.deps.cfg.model,B(),!1),o=(async()=>{const a=f?await J(f,j()??this.deps.cfg.cwd,Y()):[],g=ae(a,c),y=g===void 0?{route:void 0,capacityExhausted:!1}:await this.nextEligibleFallbackRoute(a.slice(g+1),this.deps.registryOf(s),i.getContextUsage()?.tokens,h=>!this.notFoundModels.has(`${h.providerId}/${h.modelId}`));if(y.route===void 0){y.capacityExhausted&&this.stageCapacityFailure(n,i);return}const u=y.route,p=`${u.providerId}/${u.modelId}${u.thinkingLevel?`:${u.thinkingLevel}`:""}`,v=this.deps.registryOf(s).find(u.providerId,u.modelId);if(v===void 0){F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`${t?"unconfigured-provider":"not_found"} fallback skipped: ${p} is not registered`}});return}if(await i.setModel(v),this.deps.installedGeneration()!==n||this.deps.currentSession()!==i)return;i.setThinkingLevel(u.thinkingLevel??"off"),await this.deps.broadcastModelChanged();const k=this.deps.formatModelSpec(i.model,i.thinkingLevel)??p;if(F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`${t?"unconfigured-provider":"not_found"} fallback: ${d} unavailable \u2192 ${k}; re-driving turn`}}),await i.agent.waitForIdle(),this.deps.installedGeneration()!==n||this.deps.currentSession()!==i)return;t&&await this.clearFault("pi\u2192provider");const w=K("recovery",{},be(d,k,t?"credential":"not-found"));ne(w,{type:"runtime",kind:"recovery"}),await this.deps.turnAdmission.admit(h=>H.fresh(()=>i.prompt(w,{preflightResult:h})))})().catch(a=>{F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`${t?"unconfigured-provider":"not_found"} fallback failed: ${a instanceof Error?a.message:String(a)}`}})}).finally(()=>{this.deps.installedGeneration()===n&&(this.notFoundFallbackInFlight=null)});this.notFoundFallbackInFlight=o}async nextEligibleFallbackRoute(e,t,n,i){let s=0,d=0;for(const c of e){if(!i(c)||Ie([{...c,...await this.routeAvailability(c,t),automaticFallback:!0}]).candidates.length===0)continue;const f=t.find(c.providerId,c.modelId);if(f!==void 0){if(s++,this.targetCannotFitContext(f.contextWindow,n)){d++;continue}return{route:c,capacityExhausted:!1}}}return{route:void 0,capacityExhausted:s>0&&s===d}}async routeAvailability(e,t){const n=t.find(e.providerId,e.modelId);if(n===void 0)return{registered:!1,authenticated:!1};if(!ke(e.providerId))return{registered:!0,authenticated:t.hasConfiguredAuth(n)};const i=await me().getModelAuthReadiness({model:`${e.providerId}/${e.modelId}`}),s=i.rate_limited_until==null?void 0:Date.parse(i.rate_limited_until);return{registered:!0,authenticated:i.credential==="ready",...s!==void 0&&s>Date.now()?{coolingUntil:s}:{}}}targetCannotFitContext(e,t){return Number.isFinite(e)&&Number.isFinite(t)&&e<t}stageCapacityFailure(e,t){const n=t.getContextUsage()?.tokens;this.stagedCapacityFailure={generation:e,errorMessage:Number.isFinite(n)?`All available fallback models have context windows smaller than the current conversation (${n} tokens).`:"All available fallback models have context windows smaller than the current conversation."}}async recordPendingProviderFault(e,t){const n=this.sessionId(e);if(n===null){await this.recordFault(t);return}await I(this.deps.nodeId,{op:"record-pending",session_id:n,input:t})}pendingEpisodeMatches(e,t,n){const i=this.sessionId(e),s=n.episode;return i!==null&&s!==null&&s.state==="pending"&&s.session_id===i&&s.fault.fault_id===t.fault_id}faultRetryDelayMs(e,t){if(e.retry.nextAt!==void 0){const n=Date.parse(e.retry.nextAt)-t;return Number.isFinite(n)?Math.max(0,n):null}return C(R(e),t)?.delayMs??null}clearAndArmFaultRetry(e,t){if(this.deps.installedGeneration()!==t)return;this.clearTimer();const n=Math.min(Math.max(0,e),Re),i=Math.max(0,e-n);this.timer=setTimeout(()=>{if(this.timer=null,this.deps.installedGeneration()===t){if(i>0){this.clearAndArmFaultRetry(i,t);return}this.runFaultRetry().catch(s=>{this.abandonTurnEnd(),F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry fire failed: ${s instanceof Error?s.message:String(s)}`}})})}},n),typeof this.timer.unref=="function"&&this.timer.unref()}async runFaultRetry(){await this.attemptFaultRetry()===void 0&&this.abandonTurnEnd()}async attemptFaultRetry(){const e=this.deps.installedGeneration();if(e===void 0)return;const t=e.session;if(t.isStreaming)return;const n=(await this.state()).fault;if(!this.isActiveAutoFault(n))return;let i=n;if(n.kind==="connection"&&this.deps.turnEnds===void 0){const u=await this.deps.retryProbe();if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming)return;const p=(await this.state()).fault;if(!this.isActiveAutoFault(p)||p.since!==n.since)return;if(!u)return this.clearAndArmFaultRetry(Z(p.kind).baseDelayMs,e),"rearmed";i=p}const s=this.deps.turnEnds!==void 0,d=i.retry.attempt??0,c=Z(i.kind),f=d>=c.max?null:C(R(i),Date.now());if(f===null){await this.settleExhausted(t,i);return}if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t)return;let o,a;const g=await this.deps.turnAdmission.admit(async u=>{const p=(await this.state()).fault;if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming||!this.isActiveAutoFault(p)||p.since!==i.since){u();return}const v=this.sessionId(t);if(v===null){u();return}if(!(await I(this.deps.nodeId,{op:"admit",session_id:v,fault_id:p.fault_id,retry:f.fault.retry})).applied){u();return}const w=i.anchor_entry_id;if(w!==void 0&&(t.sessionManager.getLeafId?.()??null)!==w&&!this.hasProgressPastAnchor(t,w))try{const l=await t.navigateTree(w);if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t){u();return}l.cancelled||this.deps.reWelcomeAll()}catch(l){F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`fault retry rewind skipped: ${l instanceof Error?l.message:String(l)}`}})}const h=K("recovery",s?{attempt:f.attempt}:{attempt:f.attempt,max:f.max},xe(i.kind,s));ne(h,{type:"runtime",kind:"recovery"}),this.deps.turnEnds?.beginRecovery();const P=this.agentStarts;try{await H.fresh(()=>t.prompt(h,{preflightResult:u}))}catch(l){o={error:l,faultId:p.fault_id,startsBefore:P},oe(l)||(a={code:"model_error",message:`recovery prompt rejected: ${se(l)}`});return}finally{this.deps.turnEnds?.recoveryReturned(a)}return"prompted"});if(o===void 0)return g;const y=await this.settleRejectedRecoveryPrompt(e,t,o);if(y==="stale")throw o.error;return y==="rearmed"?"rearmed":void 0}async settleRejectedRecoveryPrompt(e,t,n){const i=this.sessionId(t);if(i===null)return"stale";const s=m(()=>{if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming||this.agentStarts!==n.startsBefore)throw new _},"assertCurrent"),d=se(n.error),c=oe(n.error);try{let f;return await this.retryWhileDaemonUnreachable("rejected recovery prompt settlement",async()=>{s();const{episode:o}=await this.state();if(s(),o===null||o.state!=="admitted"||o.session_id!==i||o.fault.fault_id!==n.faultId)throw new _;const a=R(o.fault),g=c&&this.deps.turnEnds===void 0?C(a,Date.now()):null,y=g===null?Q(c?a:{...a,kind:"other",message:`recovery prompt rejected: ${d}`}):{...a,retry:{...a.retry,nextAt:g.nextAt}};if(s(),!(await I(this.deps.nodeId,{op:"settle-rejected",session_id:i,fault_id:n.faultId,reopen:g!==null,input:O(y)})).applied)throw new _;f=g?.nextAt},s),f===void 0?(F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`recovery prompt rejected, ending the retry episode: ${d}`}}),"ended"):(F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`recovery prompt rejected before any turn started, retrying at ${f}: ${d}`}}),await this.schedule(),"rearmed")}catch(f){if(!(f instanceof _))throw f;return"stale"}}}export{et as FaultRetry,re as RUN_TURN_RETRY_WINDOW_MS,Ce as isPrefillRejectionDuringEpisode,xe as retryCardBody,Se as runTurnRetryExpired,de as settledProviderFault,Ze as willDaemonRetry};
1
+ var ce=Object.defineProperty;var m=(r,e)=>ce(r,"name",{value:e,configurable:!0});import{envModelIntent as B,envNodeCwd as j,envProfileId as Y}from"../../../shared/env.js";import{isContextOverflow as q}from"@earendil-works/pi-ai";import{classify as T}from"../../fault-classifier.js";import{isDaemonTransportApiError as V}from"../../../api/errors.js";import{isModelNotFoundError as fe,isProviderUnconfiguredError as pe}from"../fault.js";import{brokerRecovery as he,daemonClient as me,mutateBrokerFault as X,mutateBrokerProviderRetry as I}from"./daemon-ops.js";import{extractCoolingDeadline as ge}from"../managed-provider-cooling.js";import{extractProviderFailureDetails as ye}from"../../provider-failure.js";import{expandModelCandidates as J,modelRequestFromConfig as z}from"../../model-routes.js";import{operationIdContext as H}from"../../events/operation-id.js";import{emitEvent as F}from"../../events/emit.js";import{CONNECTION_FAULT_RECOVERY_BODY as ve,PROVIDER_FAULT_RECOVERY_BODY as we,RUN_CONNECTION_FAULT_RETRY_BODY as Fe,formatCard as K,formatModelFallbackRecovery as be}from"../../../shared/generated-context.js";import{markFatalOnExhaust as Q,nextFaultRetry as C,policyFor as Z}from"../fault-recovery.js";import{parseModelSpec as ee}from"../model-selection.js";import{endedByAbort as te}from"../session-cycles.js";import{isManagedProvider as ke,resolveProviderCandidates as Ie}from"../../subscription-state.js";import{announceMessageOrigin as ne}from"../stamp/channel.js";import{LLM_REFUSAL_DIAGNOSTIC as _e,refusalRetryAt as Ee}from"./model-adapter.js";import{isSafetyRefusal as ie}from"../../llm/refusal.js";const Re=2147483647,re=3e4;function Se(r,e,t){const n=Date.parse(r);return!Number.isFinite(n)||t+e-n>re}m(Se,"runTurnRetryExpired");class _ extends Error{static{m(this,"StaleOutcome")}}const Ae=1e3,Me=3e4;function xe(r,e){return r!=="connection"?we:e?Fe:ve}m(xe,"retryCardBody");function R(r){return{link:r.link,op:r.op,kind:r.kind,retry:r.retry,message:r.message,since:r.since,operation_id:r.operation_id,...r.anchor_entry_id===void 0?{}:{anchorEntryId:r.anchor_entry_id},...r.provider_error===void 0?{}:{providerError:r.provider_error}}}m(R,"policyFault");function se(r){return r instanceof Error?r.message:String(r)}m(se,"errorText");function oe(r){return V(r)||T("pi\u2192provider",r).disposition==="auto"}m(oe,"isTransientRejection");function O(r){return{link:r.link,op:r.op,kind:r.kind,retry:r.retry,message:r.message,...r.operation_id===void 0?{}:{operation_id:r.operation_id},...r.since===void 0?{}:{since:r.since},...r.anchorEntryId===void 0?{}:{anchor_entry_id:r.anchorEntryId},...r.providerError===void 0?{}:{provider_error:r.providerError}}}m(O,"faultInput");function ae(r,e){const t=m(n=>`${n.providerId}/${n.modelId}`===e.modelSpec,"onLiveModel");return(r.find(n=>t(n)&&n.thinkingLevel===e.thinkingLevel)??r.find(t))?.rank}m(ae,"liveRouteRank");function de(r){const e=T("pi\u2192provider",r),t=r.diagnostics?.some(n=>n.type===_e)??!1;return{classified:e,disposition:t?"fatal":e.disposition}}m(de,"settledProviderFault");function Ze(r,e){if(r.stopReason!=="error"||te(r)||ie(r)||q(r,e))return!1;const{classified:t,disposition:n}=de(r);return n==="auto"&&(t.kind==="connection"||t.kind==="rate-limit"||t.kind==="overloaded")}m(Ze,"willDaemonRetry");const Te=/does not support assistant message prefill|conversation must end with a user message/i;function Ce(r,e){return e&&Te.test(r)}m(Ce,"isPrefillRejectionDuringEpisode");class et{static{m(this,"FaultRetry")}deps;timer=null;failedRetryRoutes=new Set;notFoundModels=new Set;providerFallbackInFlight=null;notFoundFallbackInFlight=null;stagedCapacityFailure=null;agentStarts=0;constructor(e){this.deps=e}clearTimer(){this.timer!==null&&(clearTimeout(this.timer),this.timer=null)}reset(){this.clearTimer(),this.deps.turnEnds?.abandon(),this.providerFallbackInFlight=null,this.notFoundFallbackInFlight=null,this.stagedCapacityFailure=null}fallbackInFlight(){return this.providerFallbackInFlight!==null||this.notFoundFallbackInFlight!==null}async faultIsFatal(){const e=(await this.state()).fault;return e!==null&&e.link==="pi\u2192provider"&&e.retry.disposition==="fatal"}abandonTurnEnd(){this.deps.turnEnds?.abandon()}state(){return he(this.deps.nodeId)}async recordFault(e){return(await X(this.deps.nodeId,{op:"record",input:e})).fault}async clearFault(e,t=!1){await X(this.deps.nodeId,{op:"clear",...e===void 0?{}:{link:e},...t?{preserve_episode:!0}:{}})}sessionId(e){const t=e.sessionManager.getSessionId?.();return typeof t=="string"&&t!==""?t:null}async clearEpisode(e){const t=this.sessionId(e);t!==null&&await I(this.deps.nodeId,{op:"clear",session_id:t})}onEvent(e){e.type==="agent_start"&&this.agentStarts++,this.maybeSwitchProviderForRetry(e),this.maybeFallbackOnUnusableModel(e)}isActiveAutoFault(e){return e===null||e.retry.disposition!=="auto"||e.retry.by!=="daemon"?!1:e.kind==="connection"||e.kind==="rate-limit"||e.kind==="overloaded"}async publishSettledProviderFault(e){const t={agentEnd:e.stagedProviderAgentEnd,watchdogAbort:e.stagedWatchdogAbort,refreshAbort:e.stagedRefreshAbort,overflowFailure:e.stagedOverflowFailure,capacityFailure:this.stagedCapacityFailure?.generation===e?this.stagedCapacityFailure:null};this.stagedCapacityFailure=null,e.stagedProviderAgentEnd=null,e.stagedWatchdogAbort=!1,e.stagedRefreshAbort=!1,e.stagedOverflowFailure=null;const n=this.agentStarts,i=m(()=>{if(this.deps.installedGeneration()!==e||this.agentStarts!==n)throw new _},"assertCurrent");try{await this.retryWhileDaemonUnreachable("settled turn fault write",()=>this.recordStagedOutcome(e,t,i),i)}catch(s){if(!(s instanceof _))throw s}}async retryWhileDaemonUnreachable(e,t,n){let i=Ae;for(;;){try{await t();return}catch(s){if(!V(s))throw s;F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`${e} waiting for the daemon: ${s.message}`}})}await new Promise(s=>setTimeout(s,i)),i=Math.min(i*2,Me),n()}}async recordStagedOutcome(e,t,n){const{agentEnd:i,watchdogAbort:s,refreshAbort:d,overflowFailure:c,capacityFailure:f}=t,o=e.session,a=m(async b=>{n(),await this.clearEpisode(b)},"clearEpisode"),g=m(async b=>{n(),await this.recordFault(b)},"recordFault"),y=m(async(b,ue)=>{n(),await this.recordPendingProviderFault(b,ue)},"recordPendingProviderFault"),u=await this.state(),p=u.fault,v=u.episode,k=this.sessionId(o),w=this.isActiveAutoFault(p)&&p.link==="pi\u2192provider"?p:v?.state==="admitted"&&v.session_id===k&&this.isActiveAutoFault(v.fault)?v.fault:null,h=w===null?null:{since:w.since,anchorEntryId:w.anchor_entry_id,attempt:w.retry.attempt},l=[...Array.isArray(i?.messages)?i.messages:[]].reverse().find(b=>typeof b=="object"&&b!==null&&b.role==="assistant");if(f!==null||c!==null){await a(o),await g({link:"pi\u2192provider",op:"context overflow recovery",kind:"context-overflow",retry:{disposition:"fatal"},message:f?.errorMessage??c.errorMessage,anchor_entry_id:o.sessionManager.getLeafId?.()??void 0});return}if(s&&l?.stopReason==="aborted"){await y(o,{link:"pi\u2192provider",op:"generation turn",kind:"connection",retry:{disposition:"auto",by:"daemon",...h?.attempt!==void 0?{attempt:h.attempt}:{}},message:typeof l.errorMessage=="string"?l.errorMessage:"engine error (no errorMessage recorded)",...h!==null?{since:h.since}:{},anchor_entry_id:this.retryAnchor(o,h?.anchorEntryId)});return}if(l?.stopReason!=="error"){l!==void 0&&await a(o);return}if(d){await a(o);return}if(ie(l)){await a(o);return}const A=typeof l.errorMessage=="string"?l.errorMessage:"engine error (no errorMessage recorded)";if(te({stopReason:"error",errorMessage:A})){await a(o);return}const E=q(l,o.model?.contextWindow),M=de(l),$=h!==null&&M.disposition!=="auto"&&Ce(A,!0),le=$?{kind:"connection",disposition:"auto"}:M.classified,S=$?"auto":M.disposition,D=ge(l),L=Ee(l),N=ye(l),G=typeof l.provider=="string"&&l.provider!==""?l.provider:o.model?.provider,U=typeof l.model=="string"&&l.model!==""?l.model:o.model?.id,W=N===void 0||G===void 0||U===void 0?void 0:{provider:G,model:U,...N};E&&await a(o);const x={link:"pi\u2192provider",op:"generation turn",kind:E?"context-overflow":le.kind,retry:E?{disposition:"fatal"}:S==="auto"?{disposition:"auto",by:"daemon",...D!==void 0?{nextAt:new Date(D).toISOString()}:{},...h?.attempt!==void 0?{attempt:h.attempt}:{}}:{disposition:S,...L!==void 0?{nextAt:new Date(L).toISOString()}:{}},message:A,...!E&&S==="auto"&&h!==null?{since:h.since}:{},anchor_entry_id:!E&&S==="auto"?this.retryAnchor(o,h?.anchorEntryId):o.sessionManager.getLeafId?.()??void 0,...W===void 0?{}:{provider_error:W}};x.retry.disposition==="auto"?await y(o,x):(await a(o),await g(x))}retryAnchor(e,t){const n=e.sessionManager.getLeafId?.()??void 0;return t!==void 0&&!this.hasProgressPastAnchor(e,t)?t:n}async recoverOnStartup(){const e=this.deps.installedGeneration();if(e===void 0)return"none";const t=(await this.state()).episode,n=this.sessionId(e.session);if(this.deps.cfg.newCycle===!0)return t!==null&&n!==null&&t.session_id===n&&await I(this.deps.nodeId,{op:"invalidate",session_id:n}),"none";if(t===null||n===null||t.session_id!==n)return"none";if(t.state==="admitted")if(t.fault.anchor_entry_id!==void 0&&!this.hasProgressPastAnchor(e.session,t.fault.anchor_entry_id)){if(!(await I(this.deps.nodeId,{op:"reopen",session_id:n})).applied)return"none"}else return await this.clearEpisode(e.session),"none";else if(t.state!=="pending")return"none";await this.recordFault(O(R(t.fault)));const i=await this.schedule();return i==="armed"?"retry-armed":i==="exhausted"?"fatal":"none"}hasProgressPastAnchor(e,t){const n=e.sessionManager.getBranch(),i=n.findIndex(d=>d.id===t);return(i===-1?n:n.slice(i+1)).some(d=>{if(d.type!=="message")return!1;const{message:c}=d;return c.role==="toolResult"?!0:c.role==="assistant"&&Array.isArray(c.content)&&c.content.length>0})}async schedule(){const e=this.deps.installedGeneration(),t=this.deps.currentSession();if(t.isStreaming||this.timer!==null)return this.timer!==null?"armed":"none";if(e===void 0)return this.abandonTurnEnd(),"none";const n=await this.state(),i=n.fault;if(!this.isActiveAutoFault(i)||this.sessionId(t)!==null&&!this.pendingEpisodeMatches(t,i,n))return this.clearTimer(),this.abandonTurnEnd(),"none";const s=Date.now(),d=this.faultRetryDelayMs(i,s);return d!==null&&this.deps.turnEnds?.holding()===!0&&Se(i.since,d,s)?(await this.endRunTurnOnFault(t,i,d),"none"):d!==null?(this.clearAndArmFaultRetry(d,e),this.timer!==null?"armed":"none"):(this.abandonTurnEnd(),i.retry.nextAt!==void 0||this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming?"none":(await this.settleExhausted(t,i),"exhausted"))}async settleExhausted(e,t){await this.recordFault(O(Q(R(t)))),await this.clearEpisode(e)}async endRunTurnOnFault(e,t,n){this.clearTimer(),this.abandonTurnEnd(),F({level:"info",event:"broker.runtime.diagnostic",fields:{message:`run turn completed on provider fault: ${t.kind} retry in ${n}ms is past the ${re}ms turn window (since ${t.since}, attempt ${t.retry.attempt??0})`}}),await this.clearEpisode(e),await this.clearFault("pi\u2192provider")}async rearmIfStranded(){if(this.timer!==null||this.deps.installedGeneration()===void 0)return;const e=this.deps.currentSession();if(e.isStreaming)return;const t=await this.state();!this.isActiveAutoFault(t.fault)||!this.pendingEpisodeMatches(e,t.fault,t)||await this.schedule()}maybeSwitchProviderForRetry(e){if(e.type!=="auto_retry_start")return;const t=T("pi\u2192provider",e.errorMessage??"").kind;if(t!=="rate-limit"&&t!=="connection"||this.providerFallbackInFlight!==null||this.deps.cfg.modelExact===!0)return;const n=this.deps.installedGeneration();if(n===void 0)return;const i=this.deps.currentSession(),s=this.deps.currentServices(),d=this.deps.formatModelSpec(i.model,i.thinkingLevel);if(d===null)return;const c=z(this.deps.cfg.model,B(),!1);if(c===void 0)return;const f=ee(d),o=(async()=>{const a=await J(c,j()??this.deps.cfg.cwd,Y()),g=ae(a,f),y=g===void 0?{route:void 0,capacityExhausted:!1}:await this.nextEligibleFallbackRoute(a.slice(g+1),this.deps.registryOf(s),i.getContextUsage()?.tokens,k=>!this.failedRetryRoutes.has(k.routeId));if(y.route===void 0){y.capacityExhausted&&(this.stageCapacityFailure(n,i),queueMicrotask(()=>{this.deps.installedGeneration()===n&&this.deps.currentSession()===i&&i.abortRetry()}));return}const u=y.route,p=this.deps.registryOf(s).find(u.providerId,u.modelId);if(!p||(await i.setModel(p),this.deps.installedGeneration()!==n||this.deps.currentSession()!==i))return;const v=`${u.providerId}/${u.modelId}`===f.modelSpec?f.thinkingLevel:u.thinkingLevel;i.setThinkingLevel(v??"off"),this.failedRetryRoutes.add(u.routeId),await this.deps.broadcastModelChanged(!1)})().catch(a=>{F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`provider route fallback failed: ${a instanceof Error?a.message:String(a)}`}})}).finally(()=>{this.deps.installedGeneration()===n&&(this.providerFallbackInFlight=null)});this.providerFallbackInFlight=o}maybeFallbackOnUnusableModel(e){if(e.type!=="message_end"||e.message.role!=="assistant"||e.message.stopReason!=="error")return;const t=pe(e.message.errorMessage??"");if(!t&&!fe(e.message.errorMessage??"")||this.deps.cfg.modelExact===!0||this.notFoundFallbackInFlight!==null)return;const n=this.deps.installedGeneration();if(n===void 0)return;const i=this.deps.currentSession(),s=this.deps.currentServices(),d=this.deps.formatModelSpec(i.model,i.thinkingLevel);if(d===null)return;const c=ee(d);this.notFoundModels.add(c.modelSpec);const f=z(this.deps.cfg.model,B(),!1),o=(async()=>{const a=f?await J(f,j()??this.deps.cfg.cwd,Y()):[],g=ae(a,c),y=g===void 0?{route:void 0,capacityExhausted:!1}:await this.nextEligibleFallbackRoute(a.slice(g+1),this.deps.registryOf(s),i.getContextUsage()?.tokens,h=>!this.notFoundModels.has(`${h.providerId}/${h.modelId}`));if(y.route===void 0){y.capacityExhausted&&this.stageCapacityFailure(n,i);return}const u=y.route,p=`${u.providerId}/${u.modelId}${u.thinkingLevel?`:${u.thinkingLevel}`:""}`,v=this.deps.registryOf(s).find(u.providerId,u.modelId);if(v===void 0){F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`${t?"unconfigured-provider":"not_found"} fallback skipped: ${p} is not registered`}});return}if(await i.setModel(v),this.deps.installedGeneration()!==n||this.deps.currentSession()!==i)return;i.setThinkingLevel(u.thinkingLevel??"off"),await this.deps.broadcastModelChanged();const k=this.deps.formatModelSpec(i.model,i.thinkingLevel)??p;if(F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`${t?"unconfigured-provider":"not_found"} fallback: ${d} unavailable \u2192 ${k}; re-driving turn`}}),await i.agent.waitForIdle(),this.deps.installedGeneration()!==n||this.deps.currentSession()!==i)return;t&&await this.clearFault("pi\u2192provider");const w=K("recovery",{},be(d,k,t?"credential":"not-found"));ne(w,{type:"runtime",kind:"recovery"}),await this.deps.turnAdmission.admit(h=>H.fresh(()=>i.prompt(w,{preflightResult:h})))})().catch(a=>{F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`${t?"unconfigured-provider":"not_found"} fallback failed: ${a instanceof Error?a.message:String(a)}`}})}).finally(()=>{this.deps.installedGeneration()===n&&(this.notFoundFallbackInFlight=null)});this.notFoundFallbackInFlight=o}async nextEligibleFallbackRoute(e,t,n,i){let s=0,d=0;for(const c of e){if(!i(c)||Ie([{...c,...await this.routeAvailability(c,t),automaticFallback:!0}]).candidates.length===0)continue;const f=t.find(c.providerId,c.modelId);if(f!==void 0){if(s++,this.targetCannotFitContext(f.contextWindow,n)){d++;continue}return{route:c,capacityExhausted:!1}}}return{route:void 0,capacityExhausted:s>0&&s===d}}async routeAvailability(e,t){const n=t.find(e.providerId,e.modelId);if(n===void 0)return{registered:!1,authenticated:!1};if(!ke(e.providerId))return{registered:!0,authenticated:t.hasConfiguredAuth(n)};const i=await me().getModelAuthReadiness({model:`${e.providerId}/${e.modelId}`}),s=i.rate_limited_until==null?void 0:Date.parse(i.rate_limited_until);return{registered:!0,authenticated:i.credential==="ready",...s!==void 0&&s>Date.now()?{coolingUntil:s}:{}}}targetCannotFitContext(e,t){return Number.isFinite(e)&&Number.isFinite(t)&&e<t}stageCapacityFailure(e,t){const n=t.getContextUsage()?.tokens;this.stagedCapacityFailure={generation:e,errorMessage:Number.isFinite(n)?`All available fallback models have context windows smaller than the current conversation (${n} tokens).`:"All available fallback models have context windows smaller than the current conversation."}}async recordPendingProviderFault(e,t){const n=this.sessionId(e);if(n===null){await this.recordFault(t);return}await I(this.deps.nodeId,{op:"record-pending",session_id:n,input:t})}pendingEpisodeMatches(e,t,n){const i=this.sessionId(e),s=n.episode;return i!==null&&s!==null&&s.state==="pending"&&s.session_id===i&&s.fault.fault_id===t.fault_id}faultRetryDelayMs(e,t){if(e.retry.nextAt!==void 0){const n=Date.parse(e.retry.nextAt)-t;return Number.isFinite(n)?Math.max(0,n):null}return C(R(e),t)?.delayMs??null}clearAndArmFaultRetry(e,t){if(this.deps.installedGeneration()!==t)return;this.clearTimer();const n=Math.min(Math.max(0,e),Re),i=Math.max(0,e-n);this.timer=setTimeout(()=>{if(this.timer=null,this.deps.installedGeneration()===t){if(i>0){this.clearAndArmFaultRetry(i,t);return}this.runFaultRetry().catch(s=>{this.abandonTurnEnd(),F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry fire failed: ${s instanceof Error?s.message:String(s)}`}})})}},n),typeof this.timer.unref=="function"&&this.timer.unref()}async runFaultRetry(){await this.attemptFaultRetry()===void 0&&this.abandonTurnEnd()}async attemptFaultRetry(){const e=this.deps.installedGeneration();if(e===void 0)return;const t=e.session;if(t.isStreaming)return;const n=(await this.state()).fault;if(!this.isActiveAutoFault(n))return;let i=n;if(n.kind==="connection"&&this.deps.turnEnds===void 0){const u=await this.deps.retryProbe();if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming)return;const p=(await this.state()).fault;if(!this.isActiveAutoFault(p)||p.since!==n.since)return;if(!u)return this.clearAndArmFaultRetry(Z(p.kind).baseDelayMs,e),"rearmed";i=p}const s=this.deps.turnEnds!==void 0,d=i.retry.attempt??0,c=Z(i.kind),f=d>=c.max?null:C(R(i),Date.now());if(f===null){await this.settleExhausted(t,i);return}if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t)return;let o,a;const g=await this.deps.turnAdmission.admit(async u=>{const p=(await this.state()).fault;if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming||!this.isActiveAutoFault(p)||p.since!==i.since){u();return}const v=this.sessionId(t);if(v===null){u();return}if(!(await I(this.deps.nodeId,{op:"admit",session_id:v,fault_id:p.fault_id,retry:f.fault.retry})).applied){u();return}const w=i.anchor_entry_id;if(w!==void 0&&(t.sessionManager.getLeafId?.()??null)!==w&&!this.hasProgressPastAnchor(t,w))try{const l=await t.navigateTree(w);if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t){u();return}l.cancelled||this.deps.reWelcomeAll()}catch(l){F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`fault retry rewind skipped: ${l instanceof Error?l.message:String(l)}`}})}const h=K("recovery",s?{attempt:f.attempt}:{attempt:f.attempt,max:f.max},xe(i.kind,s));ne(h,{type:"runtime",kind:"recovery"}),this.deps.turnEnds?.beginRecovery();const P=this.agentStarts;try{await H.fresh(()=>t.prompt(h,{preflightResult:u}))}catch(l){o={error:l,faultId:p.fault_id,startsBefore:P},oe(l)||(a={code:"model_error",message:`recovery prompt rejected: ${se(l)}`});return}finally{this.deps.turnEnds?.recoveryReturned(a)}return"prompted"});if(o===void 0)return g;const y=await this.settleRejectedRecoveryPrompt(e,t,o);if(y==="stale")throw o.error;return y==="rearmed"?"rearmed":void 0}async settleRejectedRecoveryPrompt(e,t,n){const i=this.sessionId(t);if(i===null)return"stale";const s=m(()=>{if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming||this.agentStarts!==n.startsBefore)throw new _},"assertCurrent"),d=se(n.error),c=oe(n.error);try{let f;return await this.retryWhileDaemonUnreachable("rejected recovery prompt settlement",async()=>{s();const{episode:o}=await this.state();if(s(),o===null||o.state!=="admitted"||o.session_id!==i||o.fault.fault_id!==n.faultId)throw new _;const a=R(o.fault),g=c&&this.deps.turnEnds===void 0?C(a,Date.now()):null,y=g===null?Q(c?a:{...a,kind:"other",message:`recovery prompt rejected: ${d}`}):{...a,retry:{...a.retry,nextAt:g.nextAt}};if(s(),!(await I(this.deps.nodeId,{op:"settle-rejected",session_id:i,fault_id:n.faultId,reopen:g!==null,input:O(y)})).applied)throw new _;f=g?.nextAt},s),f===void 0?(F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`recovery prompt rejected, ending the retry episode: ${d}`}}),"ended"):(F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`recovery prompt rejected before any turn started, retrying at ${f}: ${d}`}}),await this.schedule(),"rearmed")}catch(f){if(!(f instanceof _))throw f;return"stale"}}}export{et as FaultRetry,re as RUN_TURN_RETRY_WINDOW_MS,Ce as isPrefillRejectionDuringEpisode,xe as retryCardBody,Se as runTurnRetryExpired,de as settledProviderFault,Ze as willDaemonRetry};
@@ -82,6 +82,7 @@ export declare class RebindDriver {
82
82
  private captureSystemPrompt;
83
83
  private executeSubscriptionCallback;
84
84
  private publishAndScheduleProviderRecovery;
85
+ private idleAfterFatalFault;
85
86
  private ackTo;
86
87
  }
87
88
  export {};
@@ -1 +1 @@
1
- var k=Object.defineProperty;var l=(a,e)=>k(a,"name",{value:e,configurable:!0});import{mkdirSync as v,writeFileSync as _}from"node:fs";import{join as I}from"node:path";import{nodeRunJobDir as A}from"../../canvas/paths.js";import{emitEvent as u}from"../../events/emit.js";import{operationIdContext as c}from"../../events/operation-id.js";import{installPersonaTransitionGate as E}from"../broker-persona-guidance.js";import{installRetryCardElision as T}from"./retry-card-elision.js";import{abortSessionFromExtension as w}from"./extension-abort.js";import{brokerRecovery as S,mutateBrokerFault as x,mutateBrokerProviderRetry as P}from"./daemon-ops.js";const f=2,m=3e4,b=Symbol("replacement-deadline-exceeded"),V="(interrupted)",g=Symbol.for("crtr.trailing-thinking-guard");function C(a){for(let e=a.length-1;e>=0;e--){const t=a[e];if(t!==void 0){if(t.type==="text"){if(t.text.trim().length===0)continue;return t}if(t.type==="thinking"){const d=t.thinkingSignature,r=typeof d=="string"&&d.trim().length>0;if(t.redacted!==!0&&t.thinking.trim().length===0&&!r)continue;return t}return t}}}l(C,"lastSerializedBlock");function y(a){return a.map(e=>e.role!=="assistant"||e.stopReason==="error"||e.stopReason==="aborted"||C(e.content)?.type!=="thinking"?e:{...e,content:[...e.content,{type:"text",text:V}]})}l(y,"guardTrailingThinking");function N(a){const e=a.convertToLlm;if(e[g]===!0)return;const t=l(d=>{const r=e(d);return r instanceof Promise?r.then(y):y(r)},"wrapped");t[g]=!0,a.convertToLlm=t}l(N,"installTrailingThinkingGuard");class ${static{l(this,"RebindDriver")}deps;sessionValue;servicesValue;unsubscribe;installed;nextSubscriptionGeneration=0;rebindTail=Promise.resolve();latestRebindRequest=0;replacementTail=Promise.resolve();admittedReplacements=0;rebindsInFlight=0;rebinding;agentRunActiveValue=!1;shutdownRequested=!1;constructor(e){this.deps=e,this.sessionValue=e.session,this.servicesValue=e.services}session(){return this.sessionValue}services(){return this.servicesValue}installedGeneration(){return this.installed}isAgentRunActive(){return this.agentRunActiveValue}isReplacing(){return this.admittedReplacements>0}pendingRebind(){return this.rebinding?.done}requestShutdown(){if(!this.agentRunActiveValue){this.deps.disposeAndExit("shutdown-hook");return}this.shutdownRequested=!0}setRebindSession(){this.deps.runtime?.setRebindSession(e=>this.enqueueRebind(e,this.deps.runtime.services))}enqueueRebind(e,t){const d=++this.latestRebindRequest;if(this.rebindsInFlight++===0){let n;this.rebinding={done:new Promise(o=>{n=o}),resolve:n}}const r=this.rebindTail.then(async()=>{if(d!==this.latestRebindRequest)return;if(this.installed!==void 0){typeof this.sessionValue.sessionFile=="string"&&this.sessionValue.sessionFile!==""&&await P(this.deps.nodeId,{op:"invalidate",session_id:this.sessionValue.sessionManager.getSessionId()});const i=(await S(this.deps.nodeId)).fault;i?.link==="pi\u2192provider"&&i.retry.disposition==="auto"&&i.retry.by==="daemon"&&await x(this.deps.nodeId,{op:"clear",link:"pi\u2192provider",preserve_episode:!0})}this.installed?.executingTools.clear(),this.removeInstalledSubscription(),this.deps.setActiveSession(e),this.deps.projection().reset(),this.deps.faultRetry().reset(),this.agentRunActiveValue=!1,this.deps.onSessionRebind(),this.deps.toolGroups.resetForSession(),this.sessionValue=e,this.servicesValue=t;const n=e.agent;n&&(E(this.deps.nodeId,{agent:n,sessionManager:e.sessionManager}),T(n),n.steeringMode="all",n.followUpMode="all",N(n));const o={id:++this.nextSubscriptionGeneration,session:e,fallback:{blocked:!1},stagedProviderAgentEnd:null,stagedWatchdogAbort:!1,stagedRefreshAbort:!1,stagedOverflowFailure:null,executingTools:new Set};if(this.unsubscribe=this.sessionValue.subscribe(i=>{if(!this.deps.projection().isCurrent(o))return;if(c.current()!==void 0){this.executeSubscriptionCallback(o,i);return}const s=o.fallback;if(i.type==="turn_start"&&s.storedId!==void 0){s.storedId=void 0,s.blocked=!0,c.fresh(()=>{u({level:"warn",event:"broker.turn.fallback_overlap",fields:{generation:o.id,engine_event:i.type}}),this.executeSubscriptionCallback(o,i)});return}if(i.type==="turn_start"&&!s.blocked){c.fresh(R=>{s.storedId=R,this.executeSubscriptionCallback(o,i)});return}const h=s.storedId;if(h!==void 0&&!s.blocked){c.run(h,()=>{this.executeSubscriptionCallback(o,i),i.type==="agent_settled"&&s.storedId===h&&(s.storedId=void 0)});return}this.executeSubscriptionCallback(o,i)}),this.installed=o,await e.bindExtensions({uiContext:this.deps.uiContext(),mode:"rpc",abortHandler:l(()=>w(e,()=>{const i=this.installed;i?.session===e&&(i.stagedRefreshAbort=!0)}),"abortHandler"),shutdownHandler:l(()=>this.requestShutdown(),"shutdownHandler")}),d===this.latestRebindRequest){if(this.deps.cfg.editorName!==void 0&&this.deps.cfg.editorName!=="")try{e.setSessionName(this.deps.cfg.editorName)}catch{}try{this.deps.turnReplies.seed(this.deps.transcriptMessages(e))}catch(i){u({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply seed failed: ${String(i)}`}})}this.deps.projection().rearmIfStreaming(o),this.captureSystemPrompt(e)}}).finally(()=>{--this.rebindsInFlight>0||(this.rebinding?.resolve(),this.rebinding=void 0)});return this.rebindTail=r.catch(()=>{}),r}runReplacement(e,t,d){const r=this.deps.runtime;if(r===void 0){this.deps.registry.sendFrame(e,{type:"error",code:"engine_error",message:"session replacement unsupported at this engine pin"});return}if(this.admittedReplacements>=f){c.fresh(()=>u({level:"warn",event:"broker.session_replacement.rejected",outcome:"skipped",fields:{op:t,reason:"capacity",admitted:f,cap:f}})),this.ackTo(e,t,!1,`session replacement busy (${f} active or queued)`);return}this.admittedReplacements++;const n=this.replacementTail.then(async()=>{try{await c.fresh(async()=>{const o=process.hrtime.bigint();let i;try{const p=new Promise(h=>{i=setTimeout(()=>h(b),m)}),s=await Promise.race([d(r),p]);if(s===b){u({level:"error",event:"broker.session_replacement.timed_out",outcome:"failed",duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{op:t,deadline_ms:m,mutation_outcome:"indeterminate"}}),this.ackTo(e,t,!1,"session replacement timed out; broker restarting because session state is indeterminate"),this.deps.disposeAndExit("session-replacement-timeout",1);return}s.cancelled||this.deps.reWelcomeAll(),this.ackTo(e,t,!s.cancelled,s.cancelled?s.detail??"cancelled by extension":void 0)}catch(p){u({level:"error",event:"broker.session_replacement.failed",outcome:"failed",error:p,fields:{op:t,mutation_outcome:"indeterminate"}}),this.ackTo(e,t,!1,"session replacement failed; broker restarting because session state is indeterminate"),this.deps.disposeAndExit("session-replacement-failed",1)}finally{clearTimeout(i)}})}finally{this.admittedReplacements--,this.admittedReplacements===0&&this.deps.onReplacementIdle?.()}});this.replacementTail=n.catch(()=>{})}removeInstalledSubscription(){this.unsubscribe?.(),this.unsubscribe=void 0,this.installed=void 0}captureSystemPrompt(e){try{const t=A(this.deps.nodeId);v(t,{recursive:!0}),_(I(t,"system-prompt.md"),e.systemPrompt,"utf8")}catch{}}executeSubscriptionCallback(e,t){try{t.type==="agent_start"&&(this.agentRunActiveValue=!0),t.type==="agent_end"&&(e.stagedProviderAgentEnd=t,e.stagedOverflowFailure=null),t.type==="compaction_end"&&t.reason==="overflow"&&t.willRetry===!1&&typeof t.errorMessage=="string"&&(e.stagedOverflowFailure={errorMessage:t.errorMessage}),t.type==="agent_settled"&&(this.agentRunActiveValue=!1,this.publishAndScheduleProviderRecovery(e)),this.deps.toolGroups.observeToolGroupEvent(t),this.deps.turnReplies.observe(t),this.deps.projection().relayEvent(t,e)}catch(d){u({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`event relay threw: ${String(d)}`}})}}async publishAndScheduleProviderRecovery(e){try{if(await this.deps.faultRetry().publishSettledProviderFault(e),this.shutdownRequested){this.deps.disposeAndExit("shutdown-after-settle");return}await this.deps.faultRetry().schedule()}catch(t){this.deps.faultRetry().abandonTurnEnd(),u({level:"error",event:"broker.daemon.operation.failed",node_id:this.deps.nodeId,error:t,fields:{operation:"provider_fault_settlement"}}),this.shutdownRequested&&this.deps.disposeAndExit("shutdown-after-settle")}}ackTo(e,t,d=!0,r,n){this.deps.registry.sendFrame(e,{type:"ack",for:t,ok:d,...r!==void 0?{detail:r}:{},...n!==void 0?{id:n}:{}})}}export{$ as RebindDriver};
1
+ var k=Object.defineProperty;var l=(d,e)=>k(d,"name",{value:e,configurable:!0});import{mkdirSync as v,writeFileSync as I}from"node:fs";import{join as A}from"node:path";import{nodeRunJobDir as _}from"../../canvas/paths.js";import{emitEvent as u}from"../../events/emit.js";import{operationIdContext as c}from"../../events/operation-id.js";import{installPersonaTransitionGate as w}from"../broker-persona-guidance.js";import{installRetryCardElision as E}from"./retry-card-elision.js";import{abortSessionFromExtension as T}from"./extension-abort.js";import{brokerRecovery as S,mutateBrokerFault as x,mutateBrokerProviderRetry as F,postBrokerIdle as P,settleBroker as V}from"./daemon-ops.js";import{brokerSignalClient as C}from"./signal-stream.js";const f=2,m=3e4,b=Symbol("replacement-deadline-exceeded"),N="(interrupted)",g=Symbol.for("crtr.trailing-thinking-guard");function M(d){for(let e=d.length-1;e>=0;e--){const t=d[e];if(t!==void 0){if(t.type==="text"){if(t.text.trim().length===0)continue;return t}if(t.type==="thinking"){const i=t.thinkingSignature,n=typeof i=="string"&&i.trim().length>0;if(t.redacted!==!0&&t.thinking.trim().length===0&&!n)continue;return t}return t}}}l(M,"lastSerializedBlock");function y(d){return d.map(e=>e.role!=="assistant"||e.stopReason==="error"||e.stopReason==="aborted"||M(e.content)?.type!=="thinking"?e:{...e,content:[...e.content,{type:"text",text:N}]})}l(y,"guardTrailingThinking");function q(d){const e=d.convertToLlm;if(e[g]===!0)return;const t=l(i=>{const n=e(i);return n instanceof Promise?n.then(y):y(n)},"wrapped");t[g]=!0,d.convertToLlm=t}l(q,"installTrailingThinkingGuard");class X{static{l(this,"RebindDriver")}deps;sessionValue;servicesValue;unsubscribe;installed;nextSubscriptionGeneration=0;rebindTail=Promise.resolve();latestRebindRequest=0;replacementTail=Promise.resolve();admittedReplacements=0;rebindsInFlight=0;rebinding;agentRunActiveValue=!1;shutdownRequested=!1;constructor(e){this.deps=e,this.sessionValue=e.session,this.servicesValue=e.services}session(){return this.sessionValue}services(){return this.servicesValue}installedGeneration(){return this.installed}isAgentRunActive(){return this.agentRunActiveValue}isReplacing(){return this.admittedReplacements>0}pendingRebind(){return this.rebinding?.done}requestShutdown(){if(!this.agentRunActiveValue){this.deps.disposeAndExit("shutdown-hook");return}this.shutdownRequested=!0}setRebindSession(){this.deps.runtime?.setRebindSession(e=>this.enqueueRebind(e,this.deps.runtime.services))}enqueueRebind(e,t){const i=++this.latestRebindRequest;if(this.rebindsInFlight++===0){let o;this.rebinding={done:new Promise(a=>{o=a}),resolve:o}}const n=this.rebindTail.then(async()=>{if(i!==this.latestRebindRequest)return;if(this.installed!==void 0){typeof this.sessionValue.sessionFile=="string"&&this.sessionValue.sessionFile!==""&&await F(this.deps.nodeId,{op:"invalidate",session_id:this.sessionValue.sessionManager.getSessionId()});const s=(await S(this.deps.nodeId)).fault;s?.link==="pi\u2192provider"&&s.retry.disposition==="auto"&&s.retry.by==="daemon"&&await x(this.deps.nodeId,{op:"clear",link:"pi\u2192provider",preserve_episode:!0})}this.installed?.executingTools.clear(),this.removeInstalledSubscription(),this.deps.setActiveSession(e),this.deps.projection().reset(),this.deps.faultRetry().reset(),this.agentRunActiveValue=!1,this.deps.onSessionRebind(),this.deps.toolGroups.resetForSession(),this.sessionValue=e,this.servicesValue=t;const o=e.agent;o&&(w(this.deps.nodeId,{agent:o,sessionManager:e.sessionManager}),E(o),o.steeringMode="all",o.followUpMode="all",q(o));const a={id:++this.nextSubscriptionGeneration,session:e,fallback:{blocked:!1},stagedProviderAgentEnd:null,stagedWatchdogAbort:!1,stagedRefreshAbort:!1,stagedOverflowFailure:null,executingTools:new Set};if(this.unsubscribe=this.sessionValue.subscribe(s=>{if(!this.deps.projection().isCurrent(a))return;if(c.current()!==void 0){this.executeSubscriptionCallback(a,s);return}const r=a.fallback;if(s.type==="turn_start"&&r.storedId!==void 0){r.storedId=void 0,r.blocked=!0,c.fresh(()=>{u({level:"warn",event:"broker.turn.fallback_overlap",fields:{generation:a.id,engine_event:s.type}}),this.executeSubscriptionCallback(a,s)});return}if(s.type==="turn_start"&&!r.blocked){c.fresh(R=>{r.storedId=R,this.executeSubscriptionCallback(a,s)});return}const h=r.storedId;if(h!==void 0&&!r.blocked){c.run(h,()=>{this.executeSubscriptionCallback(a,s),s.type==="agent_settled"&&r.storedId===h&&(r.storedId=void 0)});return}this.executeSubscriptionCallback(a,s)}),this.installed=a,await e.bindExtensions({uiContext:this.deps.uiContext(),mode:"rpc",abortHandler:l(()=>T(e,()=>{const s=this.installed;s?.session===e&&(s.stagedRefreshAbort=!0)}),"abortHandler"),shutdownHandler:l(()=>this.requestShutdown(),"shutdownHandler")}),i===this.latestRebindRequest){if(this.deps.cfg.editorName!==void 0&&this.deps.cfg.editorName!=="")try{e.setSessionName(this.deps.cfg.editorName)}catch{}try{this.deps.turnReplies.seed(this.deps.transcriptMessages(e))}catch(s){u({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply seed failed: ${String(s)}`}})}this.deps.projection().rearmIfStreaming(a),this.captureSystemPrompt(e)}}).finally(()=>{--this.rebindsInFlight>0||(this.rebinding?.resolve(),this.rebinding=void 0)});return this.rebindTail=n.catch(()=>{}),n}runReplacement(e,t,i){const n=this.deps.runtime;if(n===void 0){this.deps.registry.sendFrame(e,{type:"error",code:"engine_error",message:"session replacement unsupported at this engine pin"});return}if(this.admittedReplacements>=f){c.fresh(()=>u({level:"warn",event:"broker.session_replacement.rejected",outcome:"skipped",fields:{op:t,reason:"capacity",admitted:f,cap:f}})),this.ackTo(e,t,!1,`session replacement busy (${f} active or queued)`);return}this.admittedReplacements++;const o=this.replacementTail.then(async()=>{try{await c.fresh(async()=>{const a=process.hrtime.bigint();let s;try{const p=new Promise(h=>{s=setTimeout(()=>h(b),m)}),r=await Promise.race([i(n),p]);if(r===b){u({level:"error",event:"broker.session_replacement.timed_out",outcome:"failed",duration_ms:Number(process.hrtime.bigint()-a)/1e6,fields:{op:t,deadline_ms:m,mutation_outcome:"indeterminate"}}),this.ackTo(e,t,!1,"session replacement timed out; broker restarting because session state is indeterminate"),this.deps.disposeAndExit("session-replacement-timeout",1);return}r.cancelled||this.deps.reWelcomeAll(),this.ackTo(e,t,!r.cancelled,r.cancelled?r.detail??"cancelled by extension":void 0)}catch(p){u({level:"error",event:"broker.session_replacement.failed",outcome:"failed",error:p,fields:{op:t,mutation_outcome:"indeterminate"}}),this.ackTo(e,t,!1,"session replacement failed; broker restarting because session state is indeterminate"),this.deps.disposeAndExit("session-replacement-failed",1)}finally{clearTimeout(s)}})}finally{this.admittedReplacements--,this.admittedReplacements===0&&this.deps.onReplacementIdle?.()}});this.replacementTail=o.catch(()=>{})}removeInstalledSubscription(){this.unsubscribe?.(),this.unsubscribe=void 0,this.installed=void 0}captureSystemPrompt(e){try{const t=_(this.deps.nodeId);v(t,{recursive:!0}),I(A(t,"system-prompt.md"),e.systemPrompt,"utf8")}catch{}}executeSubscriptionCallback(e,t){try{t.type==="agent_start"&&(this.agentRunActiveValue=!0),t.type==="agent_end"&&(e.stagedProviderAgentEnd=t,e.stagedOverflowFailure=null),t.type==="compaction_end"&&t.reason==="overflow"&&t.willRetry===!1&&typeof t.errorMessage=="string"&&(e.stagedOverflowFailure={errorMessage:t.errorMessage}),t.type==="agent_settled"&&(this.agentRunActiveValue=!1,this.publishAndScheduleProviderRecovery(e)),this.deps.toolGroups.observeToolGroupEvent(t),this.deps.turnReplies.observe(t),this.deps.projection().relayEvent(t,e)}catch(i){u({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`event relay threw: ${String(i)}`}})}}async publishAndScheduleProviderRecovery(e){try{if(await this.deps.faultRetry().publishSettledProviderFault(e),this.shutdownRequested){this.deps.disposeAndExit("shutdown-after-settle");return}const t=this.deps.faultRetry();await t.schedule()!=="armed"&&!t.fallbackInFlight()&&await t.faultIsFatal()&&await this.idleAfterFatalFault(e)}catch(t){this.deps.faultRetry().abandonTurnEnd(),u({level:"error",event:"broker.daemon.operation.failed",node_id:this.deps.nodeId,error:t,fields:{operation:"provider_fault_settlement"}}),this.shutdownRequested&&this.deps.disposeAndExit("shutdown-after-settle")}}async idleAfterFatalFault(e){const t=l(()=>this.installed===e&&!this.agentRunActiveValue&&!e.session.isStreaming,"stillSettled");!t()||(await V(this.deps.nodeId,{stopReason:"error",pushedFinal:!1,faultSettled:!0})).action!=="stay_resident"||!t()||(await P(this.deps.nodeId),C().stop())}ackTo(e,t,i=!0,n,o){this.deps.registry.sendFrame(e,{type:"ack",for:t,ok:i,...n!==void 0?{detail:n}:{},...o!==void 0?{id:o}:{}})}}export{X as RebindDriver};