@north-light/cli 0.3.550 → 0.3.552

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 (103) hide show
  1. package/dist/api/client.d.ts +11 -0
  2. package/dist/api/client.js +3 -3
  3. package/dist/api/contract.d.ts +1 -1
  4. package/dist/api/contract.js +1 -1
  5. package/dist/api/dto/charges.d.ts +122 -0
  6. package/dist/api/dto/charges.js +0 -0
  7. package/dist/api/dto/usage.d.ts +3 -3
  8. package/dist/api/index.d.ts +1 -0
  9. package/dist/api/index.js +1 -1
  10. package/dist/api/routes.d.ts +3 -0
  11. package/dist/api/routes.js +1 -1
  12. package/dist/builtin-memory/crouter-sdk/release-notes.md +10 -0
  13. package/dist/clients/attach/viewer.js +50 -50
  14. package/dist/commands/sys/spend.d.ts +1 -0
  15. package/dist/commands/sys/spend.js +3 -0
  16. package/dist/commands/sys.js +1 -1
  17. package/dist/core/canvas/canvas.js +4 -4
  18. package/dist/core/canvas/export-sqlite.js +2 -2
  19. package/dist/core/canvas/import-sqlite.js +1 -1
  20. package/dist/core/canvas/person.js +7 -16
  21. package/dist/core/canvas/schema-pg.sql +61 -0
  22. package/dist/core/canvas/types.d.ts +4 -0
  23. package/dist/core/config.js +1 -1
  24. package/dist/core/grants/mirror.d.ts +2 -1
  25. package/dist/core/grants/mirror.js +2 -2
  26. package/dist/core/ledger/backfill.d.ts +12 -0
  27. package/dist/core/ledger/backfill.js +22 -0
  28. package/dist/core/ledger/charges.d.ts +18 -0
  29. package/dist/core/ledger/charges.js +1 -0
  30. package/dist/core/ledger/check.d.ts +44 -0
  31. package/dist/core/ledger/check.js +7 -0
  32. package/dist/core/ledger/index.d.ts +9 -0
  33. package/dist/core/ledger/index.js +1 -0
  34. package/dist/core/ledger/limits.d.ts +15 -0
  35. package/dist/core/ledger/limits.js +3 -0
  36. package/dist/core/ledger/months.d.ts +6 -0
  37. package/dist/core/ledger/months.js +1 -0
  38. package/dist/core/ledger/payer.d.ts +34 -0
  39. package/dist/core/ledger/payer.js +1 -0
  40. package/dist/core/ledger/read.d.ts +44 -0
  41. package/dist/core/ledger/read.js +3 -0
  42. package/dist/core/ledger/totals.d.ts +19 -0
  43. package/dist/core/ledger/totals.js +4 -0
  44. package/dist/core/ledger/types.d.ts +66 -0
  45. package/dist/core/ledger/types.js +0 -0
  46. package/dist/core/llm/run.d.ts +17 -5
  47. package/dist/core/llm/run.js +2 -2
  48. package/dist/core/providers/call.d.ts +7 -1
  49. package/dist/core/providers/call.js +1 -1
  50. package/dist/core/providers/errors.js +1 -1
  51. package/dist/core/providers/receipts.d.ts +7 -1
  52. package/dist/core/providers/receipts.js +1 -3
  53. package/dist/core/runs/operations.d.ts +1 -0
  54. package/dist/core/runs/operations.js +7 -7
  55. package/dist/core/runtime/broker/cli-relay.js +1 -1
  56. package/dist/core/runtime/broker/model-adapter.js +2 -2
  57. package/dist/core/runtime/broker/turn-cause.d.ts +7 -0
  58. package/dist/core/runtime/broker/turn-cause.js +1 -0
  59. package/dist/core/runtime/broker.js +1 -1
  60. package/dist/core/runtime/nodes.d.ts +2 -0
  61. package/dist/core/runtime/nodes.js +1 -1
  62. package/dist/core/runtime/recycle.js +1 -1
  63. package/dist/core/runtime/reset.js +1 -1
  64. package/dist/core/runtime/revive.js +2 -2
  65. package/dist/core/runtime/spawn.d.ts +2 -0
  66. package/dist/core/runtime/spawn.js +2 -2
  67. package/dist/core/runtime/start-check.d.ts +15 -0
  68. package/dist/core/runtime/start-check.js +1 -0
  69. package/dist/core/runtime/warm-pool.js +1 -1
  70. package/dist/core/user-settings.d.ts +4 -0
  71. package/dist/core/user-settings.js +1 -1
  72. package/dist/daemon/api/app-listener.js +13 -13
  73. package/dist/daemon/api/handlers/bash-jobs.js +1 -1
  74. package/dist/daemon/api/handlers/charges.d.ts +3 -0
  75. package/dist/daemon/api/handlers/charges.js +1 -0
  76. package/dist/daemon/api/handlers/llm.d.ts +9 -5
  77. package/dist/daemon/api/handlers/llm.js +3 -3
  78. package/dist/daemon/api/handlers/messages.js +2 -2
  79. package/dist/daemon/api/handlers/providers.d.ts +2 -0
  80. package/dist/daemon/api/handlers/providers.js +1 -1
  81. package/dist/daemon/api/handlers/run-routes.js +1 -1
  82. package/dist/daemon/api/handlers/runs.d.ts +1 -1
  83. package/dist/daemon/api/handlers/runs.js +1 -1
  84. package/dist/daemon/api/operations.js +1 -1
  85. package/dist/daemon/api/router.d.ts +8 -0
  86. package/dist/daemon/api/router.js +1 -1
  87. package/dist/daemon/api/server.js +1 -1
  88. package/dist/daemon/cron/authority.d.ts +1 -1
  89. package/dist/daemon/cron-run.js +2 -2
  90. package/dist/daemon/crtrd.js +10 -10
  91. package/dist/daemon/fleet.js +4 -4
  92. package/dist/daemon/reconcilers/action-lane.js +1 -1
  93. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +2 -0
  94. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  95. package/dist/doc-editor/editor.css +1 -1
  96. package/dist/doc-editor/editor.js +16 -16
  97. package/dist/types.d.ts +4 -0
  98. package/docs/sdk/release-notes.md +10 -0
  99. package/package.json +2 -2
  100. package/packages/crouter-identity/package.json +1 -1
  101. package/runtime.lock.json +13 -13
  102. package/dist/core/usage/ledger.d.ts +0 -49
  103. package/dist/core/usage/ledger.js +0 -10
@@ -1 +1 @@
1
- var te=Object.defineProperty;var v=(e,r)=>te(e,"name",{value:r,configurable:!0});import{validateDeclaredResult as U}from"../../api/command-manifest/result.js";import{callerAllows as oe,requireGroup as ie}from"../../daemon/api/handlers/providers.js";import{terminalGrant as ne}from"../grants/mirror.js";import{UNCAPPED_GRANTEE as se}from"../usage/ledger.js";import{listInstalledPlugins as ae}from"../resolver.js";import{ProviderError as l}from"./errors.js";import{resolveProviderRef as de}from"./roots.js";import{providerToolPath as ue}from"../plugin-objects-manifest.js";import{ensureProviderBundle as le,refreshProviderBundle as pe,resolveProviderBundle as B,unavailableProviderError as ce}from"./bundles.js";import{prepareFileCall as fe,resignForRetry as z,resolveFileResult as Q}from"./files.js";import{consumeApproval as me,requireProviderApproval as ve}from"./approval.js";import{outboundToken as ge}from"./mint.js";import{discardFile as he}from"./token-cache.js";import{registerProviderCall as we}from"./inflight.js";import{buildRequestPlan as be}from"../command-plugins/transport/http-plan.js";import{newTraceId as ye}from"../../shared/traceparent.js";import{sendProviderRequest as _e,ProviderTransportError as Ae}from"./request.js";import{acceptProviderReceipt as je}from"./receipts.js";import{writeProviderAudit as ke}from"./audit.js";import{selectDevice as Pe,sendDeviceCall as qe,deviceFailure as Ee,deviceUnreachable as V,DEFAULT_DEVICE_REQUEST_MS as $e}from"./device.js";import{isLibsSearch as K,wantsBundling as Ce,callLibsSearch as Re,bundleExec as Ie,mapLibOutcome as Se,reportLibCalls as Te}from"./device-libs.js";import{directoryIssuer as Ne,ownMachineId as De}from"../peer/directory.js";import{formatCrtrCaller as W}from"../command-plugins/caller-header.js";import{getNode as Fe}from"../canvas/canvas.js";import{envelopeForProviderCaller as Me}from"../peer/envelope.js";function X(e){const r=[],n=v((c,t,o)=>{const s=[...t,c.name],a=o||c.tier==="hidden";if(c.kind==="branch"){for(const g of c.children)n(g,s,a);return}const j=ue(e.roots.length,s);r.push({tool:j,leaf:c,hidden:a})},"walk");for(const c of e.roots)n(c,[],!1);return r}v(X,"providerLeaves");function Y(e){if(e.kind!=="branch")return null;const r=[];for(const h of e.children)if(h.kind==="branch"){const _=Y(h);_&&r.push(_)}else if("group"in h&&h.group){const{kind:_,name:d,description:A,whenToUse:w,tier:b,summary:k,params:P,output:i,effects:p,group:m}=h;r.push({kind:_,name:d,description:A,whenToUse:w,...b===void 0?{}:{tier:b},summary:k,params:P,output:i,effects:p,group:m})}if(r.length===0)return null;const{kind:n,name:c,description:t,whenToUse:o,tier:s,summary:a,model:j,rootEntry:g}=e;return{kind:n,name:c,description:t,whenToUse:o,...s===void 0?{}:{tier:s},summary:a,...j===void 0?{}:{model:j},...g===void 0?{}:{rootEntry:g},children:r}}v(Y,"providerHelpBranch");async function hr(e,r){const n=await B(r),c=X(n.commands),t=ae("user").find(o=>o.name===r)?.manifest.description??r;return{provider:r,status:"available",major:n.major,display_name:t,transport:n.transport.kind,groups:n.provider.groups.filter(o=>oe(e,`${r}:${o.group}`)).map(o=>({group:o.group,leaves:c.filter(({leaf:s,hidden:a})=>!a&&s.group===o.group).map(({tool:s,leaf:a})=>({tool:s,description:a.description,summary:a.summary,params:a.params,output:a.output}))})),commands:n.commands.roots.flatMap(o=>{const s=Y(o);return s?[s]:[]})}}v(hr,"providerTools");async function Oe(e){return await je(e.headers["crtr-receipt"],e)}v(Oe,"onProviderResponse");async function Ue(e){if(e.class==="person"){const r=(await ne())?.sub;if(!r)throw new l("grant_revoked","This machine has no active Northlight grant for your terminal. Run `crtr sys join` again from /account/machines.");return{sub:r,grantee:r}}if(!e.sub||!e.grantee)throw new l("grant_revoked","the caller has no active grant");return{sub:e.sub,grantee:e.grantee}}v(Ue,"identity");function Be(e,r){return[`${e.id}:${r.group}`]}v(Be,"callScope");function Le(e,r){const n=X(e.commands).find(c=>c.tool===r);if(!n)throw new l("not_found",`tool "${r}" is not in provider "${e.id}"`,{param:"tool"});if(!n.leaf.group)throw new l("not_found",`tool "${r}" has no group`,{param:"tool"});return n.leaf}v(Le,"leafFor");function L(e){if(!e||typeof e!="object"||Array.isArray(e))return{};const r=e.error;return!r||typeof r!="object"||Array.isArray(r)?{}:r}v(L,"errorBody");function Je(e){const r=Array.isArray(e)?e[0]:e;if(!r)return;const n=Number(r);if(Number.isFinite(n)&&n>=0)return n;const c=Date.parse(r);return Number.isFinite(c)?Math.max(0,Math.ceil((c-Date.now())/1e3)):void 0}v(Je,"retryAfter");function N(e,r,n,c=!1){const t=L(r),o=typeof t.code=="string"?t.code:void 0,s=typeof t.message=="string"?t.message:`provider answered HTTP ${e}`,a=typeof t.field=="string"?t.field:void 0,g={origin:"provider",details:{code:o??null,message:s,...a?{field:a}:{},...typeof t.next=="string"?{next:t.next}:{},...t.received!==void 0?{received:t.received}:{},status:e},...a?{param:a}:{}};return e===429?new l("provider_rate_limited",s,{...g,retry_after_s:Je(n["retry-after"])}):e===401||e>=500?new l("provider_unavailable",s,g):e===403&&o==="provider_refused"?new l("provider_refused",s,g):e===403&&o==="approval_required"?new l("provider_error",c?"provider asked for approval again":"provider approval question is invalid",{...g,status:e}):new l("provider_error",s,{...g,status:e})}v(N,"mapProviderResponse");function Z(e,r){return JSON.stringify({major:e.major,endpoint:e.transport.kind==="http"?e.transport.endpoint:null,baseUrl:e.commands.baseUrl??null,rest:r.rest,params:r.params,output:r.output})}v(Z,"approvalShape");async function He(e){const r=e.origin!==void 0?W({node:e.origin.node??void 0,run:e.origin.run??void 0,machine:e.origin.machine}):W({node:e.node_id??void 0,run:e.run_id??void 0,profile:e.node_id?(await Fe(e.node_id))?.profile_id??void 0:void 0,machine:Ne()!==null?De():void 0});return r===""?{}:{"Crtr-Caller":r}}v(He,"crtrCallerHeader");async function wr(e,r,n){const c=de(r.provider);if(c===null)throw new l("not_found",`provider "${r.provider}" is not available`,{param:"provider"});const t={...r,provider:c},o=new AbortController,s=v(()=>o.abort(n.signal.reason),"abort");n.signal.aborted?s():n.signal.addEventListener("abort",s,{once:!0});let a=n.requestId;const j=n.traceId??ye(),g=we({request_id:a,run_id:e.run_id,node_id:e.node_id,controller:o});let h,_,d,A,w,b,k,P="allowed";try{try{await le(t.provider)}catch{throw ce(t.provider)}let i=await B(t.provider,t.version),p=!1,m,D,q,J=!1,H=!1,F,x=0;for(;;){const y=Le(i,t.tool);if(d=`${i.id}:${y.group}`,ie(e,i.id,y.group),i.transport.kind!=="machine"&&t.machine!==void 0)throw new l("invalid_argument",`provider "${i.id}" is not served by a device, so it takes no machine`,{param:"machine"});i.transport.kind==="machine"&&F===void 0&&(F=await Pe(t.machine,void 0,{newest:K(i.major,t.tool)}),x=Date.now()+(i.commands.timeouts?.requestMs??$e));let M=null;if(t.approval&&!J){const u=await me(e,t,Z(i,y));q=u.option,M=u.prepared,k=t.approval,a=u.requestId,J=!0}const C={params:y.params.filter(u=>"type"in u&&u.type==="file").map(u=>u.name),output:y.output.find(u=>u.type==="file")?.name??null},G=JSON.stringify(C);if(D!==void 0&&D!==G)throw new l("provider_bad_response","the refreshed manifest changed the tool file contract",{origin:"provider",details:{status:409,message:"manifest_stale changed the tool file contract"}});D=G,M&&(m=await z(e,C,t.arguments,M,{signal:o.signal})),m??=await fe(e,C,t.arguments,{signal:o.signal});const{sub:O,grantee:R}=await Ue(e);if(i.transport.kind==="machine"){const u=await xe(e,i,t,y,m,{sub:O,requestId:a,deadlineAt:x,signal:o.signal,machine:F});return b=u.responder,h=u.cleanup,{status:200,body:u.result}}const E=await ge({audience:i.transport.endpoint,sub:O,grantee:R,initiating_app:R,scope:Be(i,y)},{signal:o.signal});A=E.jti;const ee={registration:{name:i.id,endpoint:i.transport.endpoint},...i.commands.baseUrl?{baseUrl:i.commands.baseUrl}:{},...i.commands.timeouts?{timeouts:i.commands.timeouts}:{},params:y.params,rest:y.rest,output:y.output,commandPath:[i.id,...t.tool.split(" ")]},re=be(ee,m.arguments,void 0,{authorization:`Bearer ${E.access_token}`,requestId:a,traceId:j,fileMode:"pass-through",extraHeaders:{...e.run_id?{"Crtr-Run-Id":e.run_id}:{},...await He(e),...q?{"Crtr-Approval":q}:{},...m.headers}});_??=Date.now()+(i.commands.timeouts?.requestMs??3e4);let f;try{if(f=await _e(re,{connectMs:i.commands.timeouts?.connectMs,requestMs:i.commands.timeouts?.requestMs,deadlineAt:_,signal:o.signal}),o.signal.aborted)throw o.signal.reason??new Error("provider call aborted")}catch(u){throw o.signal.aborted?o.signal.reason??u:u instanceof Ae?new l("provider_unavailable",u.message,{origin:"provider",details:{status:null,code:u.kind}}):u}if(w??=await Oe({provider:i.id,tool:t.tool,request_id:a,run_id:e.run_id,sub:O,grantee:R,payer:E.payer,ledger_grantee:e.class==="person"?se:R,jti:E.jti,status:f.status,headers:f.headers}),b=f.headers["crtr-responder"],f.status===401&&he(E.key),f.status>=200&&f.status<300){const u=f.body;if(!u||typeof u!="object"||Array.isArray(u))throw new l("provider_bad_response","provider result is not a JSON object",{origin:"provider",details:{status:f.status,message:"provider result is not a JSON object"}});let S;try{S=await Q(e,m,u,{signal:o.signal})}catch($){throw $ instanceof l&&$.code==="provider_error"?new l("provider_bad_response",$.message,{origin:"provider",details:{status:f.status,message:$.message}}):$}h=S.cleanup;const T=U(y.output,S.result);if(T)throw new l("provider_bad_response",`provider result has an invalid output field "${T.field}"`,{origin:"provider",param:T.field,details:{status:f.status,...T}});if(o.signal.aborted)throw o.signal.reason??new Error("provider call aborted");return{status:200,body:S.result}}const I=L(f.body);if(f.status===403&&I.code==="approval_required"&&!q&&!H){H=!0;const u=await ve(e,t,a,I.question,o.signal,Z(i,y),m);if(k=u.questionId,q=u.option,m=await z(e,C,t.arguments,m,{signal:o.signal}),_=void 0,o.signal.aborted)throw new l("user_denied","the approval wait was canceled");continue}if(f.status===403&&I.code==="approval_required"&&q)throw N(f.status,f.body,f.headers,!0);if(f.status!==401&&I.manifest_stale===!0&&!p){p=!0,await pe(i.id,{conditional:!1,...t.version===void 0?{}:{version:t.version}}),i=await B(i.id,t.version);continue}throw N(f.status,f.body,f.headers,!!q)}}catch(i){throw i instanceof l&&i.question_id&&(k=i.question_id),b===void 0&&i instanceof l&&typeof i.responder=="string"&&(b=i.responder),P=`refused:${i instanceof l?i.code:"server_error"}`,await h?.(),i}finally{try{await ke({request_id:a,caller:e,provider:t.provider,tool:t.tool,scope_checked:d,outcome:P,jti:A,receipt_id:w,responder:b,question_id:k})}finally{g()}n.signal.removeEventListener("abort",s)}}v(wr,"callProvider");async function xe(e,r,n,c,t,o){const{machine:s}=o,a=await Me(e,o.sub),j={machine:s,envelope:a,signal:o.signal,deadlineAt:o.deadlineAt,mapFailure:N};if(K(r.major,n.tool)){const p=await Re(j,t.arguments,r.major),m=U(c.output,p);if(m)throw new l("provider_bad_response",`the libraries result has an invalid output field "${m.field}"`,{origin:"provider",param:m.field,details:{status:200,...m}});return{result:p,responder:void 0,cleanup:void 0}}let g=t.arguments,h=null,_="";if(Ce(r.major,n.tool,t.arguments)){const p=await Ie(j,t.arguments,r.major);if(o.deadlineAt-Date.now()<=0)throw V(s,"timeout","");p!==null&&(g=p.arguments,h=p.services,_=p.release)}const d=await qe(s,{tool:n.tool,arguments:g,version:r.major,requestId:o.requestId,runId:e.run_id,deadlineAt:o.deadlineAt,upload:t.upload===null?null:{id:t.upload.upload_id,link:t.upload.upload_link}},a,o.signal);if(o.signal.aborted)throw o.signal.reason??new Error("provider call aborted");if("unreachable"in d)throw V(s,d.unreachable.reason,d.unreachable.message);const A=d.headers["crtr-responder"],w=L(d.body);if(d.status<200||d.status>=300){const p=Ee(s,d.status,typeof w.code=="string"?w.code:void 0,typeof w.message=="string"?w.message:void 0,d.body),m=p===null&&d.status>=500&&typeof w.code=="string"?new l("provider_error",typeof w.message=="string"?w.message:`the device answered HTTP ${d.status}`,{origin:"runtime",status:d.status,details:{code:w.code,status:d.status}}):null;throw Object.assign(p??m??N(d.status,d.body,d.headers),{responder:A})}const b=d.body&&typeof d.body=="object"&&!Array.isArray(d.body)?d.body.result:void 0;if(!b||typeof b!="object"||Array.isArray(b))throw Object.assign(new l("provider_bad_response","the device result is not a JSON object",{origin:"provider",details:{status:d.status,message:"the device result is not a JSON object"}}),{responder:A});let k=b;if(h!==null){const p=Se(k,h);if(Te(s,a,_,p.calls),"error"in p)throw Object.assign(p.error,{responder:A});k=p.result}let P;try{P=await Q(e,t,k,{signal:o.signal})}catch(p){throw p instanceof l&&p.code==="provider_error"?Object.assign(new l("provider_bad_response",p.message,{origin:"provider",details:{status:d.status,message:p.message}}),{responder:A}):p}const i=U(c.output,P.result);if(i)throw await P.cleanup?.(),Object.assign(new l("provider_bad_response",`the device result has an invalid output field "${i.field}"`,{origin:"provider",param:i.field,details:{status:d.status,...i}}),{responder:A});return{result:P.result,responder:A,cleanup:P.cleanup}}v(xe,"callDevice");export{wr as callProvider,He as crtrCallerHeader,N as mapProviderResponse,Oe as onProviderResponse,X as providerLeaves,hr as providerTools};
1
+ var ie=Object.defineProperty;var g=(e,r)=>ie(e,"name",{value:r,configurable:!0});import{validateDeclaredResult as J}from"../../api/command-manifest/result.js";import{callerAllows as ae,requireGroup as se}from"../../daemon/api/handlers/providers.js";import{terminalGrant as de}from"../grants/mirror.js";import{findRefusal as ue,payerOf as le,refusalError as pe,refusedMark as ce,writeCharge as fe}from"../ledger/index.js";import{listInstalledPlugins as me}from"../resolver.js";import{ProviderError as l}from"./errors.js";import{resolveProviderRef as ge}from"./roots.js";import{providerToolPath as ve}from"../plugin-objects-manifest.js";import{ensureProviderBundle as he,refreshProviderBundle as we,resolveProviderBundle as H,unavailableProviderError as ye}from"./bundles.js";import{prepareFileCall as be,resignForRetry as K,resolveFileResult as W}from"./files.js";import{consumeApproval as _e,requireProviderApproval as Ae}from"./approval.js";import{outboundToken as je}from"./mint.js";import{discardFile as ke}from"./token-cache.js";import{registerProviderCall as Pe}from"./inflight.js";import{buildRequestPlan as $e}from"../command-plugins/transport/http-plan.js";import{newTraceId as qe}from"../../shared/traceparent.js";import{sendProviderRequest as Ce,ProviderTransportError as Ee}from"./request.js";import{acceptProviderReceipt as Re}from"./receipts.js";import{writeProviderAudit as Ie}from"./audit.js";import{selectDevice as Te,sendDeviceCall as Me,deviceFailure as Se,deviceUnreachable as X,DEFAULT_DEVICE_REQUEST_MS as Be}from"./device.js";import{isLibsSearch as Y,wantsBundling as Ne,callLibsSearch as Oe,bundleExec as Fe,mapLibOutcome as De,reportLibCalls as Ue}from"./device-libs.js";import{directoryIssuer as Le,ownMachineId as Je}from"../peer/directory.js";import{formatCrtrCaller as Z}from"../command-plugins/caller-header.js";import{getNode as He}from"../canvas/canvas.js";import{envelopeForProviderCaller as Ge}from"../peer/envelope.js";const xe="app:terminal";function ee(e){const r=[],i=g((c,t,n)=>{const a=[...t,c.name],s=n||c.tier==="hidden";if(c.kind==="branch"){for(const v of c.children)i(v,a,s);return}const j=ve(e.roots.length,a);r.push({tool:j,leaf:c,hidden:s})},"walk");for(const c of e.roots)i(c,[],!1);return r}g(ee,"providerLeaves");function re(e){if(e.kind!=="branch")return null;const r=[];for(const h of e.children)if(h.kind==="branch"){const _=re(h);_&&r.push(_)}else if("group"in h&&h.group){const{kind:_,name:d,description:A,whenToUse:w,tier:y,summary:k,params:P,output:o,effects:p,group:m}=h;r.push({kind:_,name:d,description:A,whenToUse:w,...y===void 0?{}:{tier:y},summary:k,params:P,output:o,effects:p,group:m})}if(r.length===0)return null;const{kind:i,name:c,description:t,whenToUse:n,tier:a,summary:s,model:j,rootEntry:v}=e;return{kind:i,name:c,description:t,whenToUse:n,...a===void 0?{}:{tier:a},summary:s,...j===void 0?{}:{model:j},...v===void 0?{}:{rootEntry:v},children:r}}g(re,"providerHelpBranch");async function Pr(e,r){const i=await H(r),c=ee(i.commands),t=me("user").find(n=>n.name===r)?.manifest.description??r;return{provider:r,status:"available",major:i.major,display_name:t,transport:i.transport.kind,groups:i.provider.groups.filter(n=>ae(e,`${r}:${n.group}`)).map(n=>({group:n.group,leaves:c.filter(({leaf:a,hidden:s})=>!s&&a.group===n.group).map(({tool:a,leaf:s})=>({tool:a,description:s.description,summary:s.summary,params:s.params,output:s.output}))})),commands:i.commands.roots.flatMap(n=>{const a=re(n);return a?[a]:[]})}}g(Pr,"providerTools");async function ze(e){return await Re(e.headers["crtr-receipt"],e)}g(ze,"onProviderResponse");async function Qe(e){if(e.class==="person"){const r=(await de())?.sub;if(!r)throw new l("grant_revoked","This machine has no active Northlight grant for your terminal. Run `crtr sys join` again from /account/machines.");return{sub:r,grantee:r}}if(!e.sub||!e.grantee)throw new l("grant_revoked","the caller has no active grant");return{sub:e.sub,grantee:e.grantee}}g(Qe,"identity");function Ve(e,r){return[`${e.id}:${r.group}`]}g(Ve,"callScope");function Ke(e,r){const i=ee(e.commands).find(c=>c.tool===r);if(!i)throw new l("not_found",`tool "${r}" is not in provider "${e.id}"`,{param:"tool"});if(!i.leaf.group)throw new l("not_found",`tool "${r}" has no group`,{param:"tool"});return i.leaf}g(Ke,"leafFor");function G(e){if(!e||typeof e!="object"||Array.isArray(e))return{};const r=e.error;return!r||typeof r!="object"||Array.isArray(r)?{}:r}g(G,"errorBody");function We(e){const r=Array.isArray(e)?e[0]:e;if(!r)return;const i=Number(r);if(Number.isFinite(i)&&i>=0)return i;const c=Date.parse(r);return Number.isFinite(c)?Math.max(0,Math.ceil((c-Date.now())/1e3)):void 0}g(We,"retryAfter");function N(e,r,i,c=!1){const t=G(r),n=typeof t.code=="string"?t.code:void 0,a=typeof t.message=="string"?t.message:`provider answered HTTP ${e}`,s=typeof t.field=="string"?t.field:void 0,v={origin:"provider",details:{code:n??null,message:a,...s?{field:s}:{},...typeof t.next=="string"?{next:t.next}:{},...t.received!==void 0?{received:t.received}:{},status:e},...s?{param:s}:{}};return e===429?new l("provider_rate_limited",a,{...v,retry_after_s:We(i["retry-after"])}):e===401||e>=500?new l("provider_unavailable",a,v):e===403&&n==="provider_refused"?new l("provider_refused",a,v):e===403&&n==="approval_required"?new l("provider_error",c?"provider asked for approval again":"provider approval question is invalid",{...v,status:e}):new l("provider_error",a,{...v,status:e})}g(N,"mapProviderResponse");function te(e,r){return JSON.stringify({major:e.major,endpoint:e.transport.kind==="http"?e.transport.endpoint:null,baseUrl:e.commands.baseUrl??null,rest:r.rest,params:r.params,output:r.output})}g(te,"approvalShape");async function Xe(e){const r=e.origin!==void 0?Z({node:e.origin.node??void 0,run:e.origin.run??void 0,machine:e.origin.machine}):Z({node:e.node_id??void 0,run:e.run_id??void 0,profile:e.node_id?(await He(e.node_id))?.profile_id??void 0:void 0,machine:Le()!==null?Je():void 0});return r===""?{}:{"Crtr-Caller":r}}g(Xe,"crtrCallerHeader");async function $r(e,r,i){const c=ge(r.provider);if(c===null)throw new l("not_found",`provider "${r.provider}" is not available`,{param:"provider"});const t={...r,provider:c},n=new AbortController,a=g(()=>n.abort(i.signal.reason),"abort");i.signal.aborted?a():i.signal.addEventListener("abort",a,{once:!0});let s=i.requestId;const j=i.traceId??qe(),v=Pe({request_id:s,run_id:e.run_id,node_id:e.node_id,controller:n});let h,_,d,A,w,y,k,P="allowed";try{try{await he(t.provider)}catch{throw ye(t.provider)}let o=await H(t.provider,t.version),p=!1,m,O,$,x=!1,z=!1,F,Q=0;for(;;){const b=Ke(o,t.tool);if(d=`${o.id}:${b.group}`,se(e,o.id,b.group),o.transport.kind!=="machine"&&t.machine!==void 0)throw new l("invalid_argument",`provider "${o.id}" is not served by a device, so it takes no machine`,{param:"machine"});o.transport.kind==="machine"&&F===void 0&&(F=await Te(t.machine,void 0,{newest:Y(o.major,t.tool)}),Q=Date.now()+(o.commands.timeouts?.requestMs??Be));let D=null;if(t.approval&&!x){const u=await _e(e,t,te(o,b));$=u.option,D=u.prepared,k=t.approval,s=u.requestId,x=!0}const I={params:b.params.filter(u=>"type"in u&&u.type==="file").map(u=>u.name),output:b.output.find(u=>u.type==="file")?.name??null},V=JSON.stringify(I);if(O!==void 0&&O!==V)throw new l("provider_bad_response","the refreshed manifest changed the tool file contract",{origin:"provider",details:{status:409,message:"manifest_stale changed the tool file contract"}});O=V,D&&(m=await K(e,I,t.arguments,D,{signal:n.signal})),m??=await be(e,I,t.arguments,{signal:n.signal});const{sub:q,grantee:T}=await Qe(e);if(o.transport.kind==="machine"){const u=await Ye(e,o,t,b,m,{sub:q,requestId:s,deadlineAt:Q,signal:n.signal,machine:F});return y=u.responder,h=u.cleanup,{status:200,body:u.result}}const C=await je({audience:o.transport.endpoint,sub:q,grantee:T,initiating_app:T,scope:Ve(o,b)},{signal:n.signal});A=C.jti;const U=e.class==="person"?xe:T,E=le({call:"tool",tokenPayer:C.payer,sub:q}),L=await ue({scope:"call",payer:E.payer,funding:E.funding,sub:q,grantee:U,provider:`app:${o.id}`});if(L!==null)throw await fe({request:s,kind:"tool",what:`${o.id}:${t.tool}`,usd:0,payer:E.payer,funding:E.funding,sub:q,grantee:U,node:e.node_id,run:e.run_id,provider:`app:${o.id}`,causedBy:i.causedBy??null,refused:ce(L)}),pe(L);const oe={registration:{name:o.id,endpoint:o.transport.endpoint},...o.commands.baseUrl?{baseUrl:o.commands.baseUrl}:{},...o.commands.timeouts?{timeouts:o.commands.timeouts}:{},params:b.params,rest:b.rest,output:b.output,commandPath:[o.id,...t.tool.split(" ")]},ne=$e(oe,m.arguments,void 0,{authorization:`Bearer ${C.access_token}`,requestId:s,traceId:j,fileMode:"pass-through",extraHeaders:{...i.causedBy?{"Crtr-Caused-By":i.causedBy}:{},...e.run_id?{"Crtr-Run-Id":e.run_id}:{},...await Xe(e),...$?{"Crtr-Approval":$}:{},...m.headers}});_??=Date.now()+(o.commands.timeouts?.requestMs??3e4);let f;try{if(f=await Ce(ne,{connectMs:o.commands.timeouts?.connectMs,requestMs:o.commands.timeouts?.requestMs,deadlineAt:_,signal:n.signal}),n.signal.aborted)throw n.signal.reason??new Error("provider call aborted")}catch(u){throw n.signal.aborted?n.signal.reason??u:u instanceof Ee?new l("provider_unavailable",u.message,{origin:"provider",details:{status:null,code:u.kind}}):u}if(w??=await ze({provider:o.id,tool:t.tool,request_id:s,run_id:e.run_id,sub:q,grantee:T,payer:C.payer,ledger_grantee:U,funding:E.funding,node_id:e.node_id,caused_by:i.causedBy??null,jti:C.jti,status:f.status,headers:f.headers}),y=f.headers["crtr-responder"],f.status===401&&ke(C.key),f.status>=200&&f.status<300){const u=f.body;if(!u||typeof u!="object"||Array.isArray(u))throw new l("provider_bad_response","provider result is not a JSON object",{origin:"provider",details:{status:f.status,message:"provider result is not a JSON object"}});let S;try{S=await W(e,m,u,{signal:n.signal})}catch(R){throw R instanceof l&&R.code==="provider_error"?new l("provider_bad_response",R.message,{origin:"provider",details:{status:f.status,message:R.message}}):R}h=S.cleanup;const B=J(b.output,S.result);if(B)throw new l("provider_bad_response",`provider result has an invalid output field "${B.field}"`,{origin:"provider",param:B.field,details:{status:f.status,...B}});if(n.signal.aborted)throw n.signal.reason??new Error("provider call aborted");return{status:200,body:S.result}}const M=G(f.body);if(f.status===403&&M.code==="approval_required"&&!$&&!z){z=!0;const u=await Ae(e,t,s,M.question,n.signal,te(o,b),m);if(k=u.questionId,$=u.option,m=await K(e,I,t.arguments,m,{signal:n.signal}),_=void 0,n.signal.aborted)throw new l("user_denied","the approval wait was canceled");continue}if(f.status===403&&M.code==="approval_required"&&$)throw N(f.status,f.body,f.headers,!0);if(f.status!==401&&M.manifest_stale===!0&&!p){p=!0,await we(o.id,{conditional:!1,...t.version===void 0?{}:{version:t.version}}),o=await H(o.id,t.version);continue}throw N(f.status,f.body,f.headers,!!$)}}catch(o){throw o instanceof l&&o.question_id&&(k=o.question_id),y===void 0&&o instanceof l&&typeof o.responder=="string"&&(y=o.responder),P=`refused:${o instanceof l?o.code:"server_error"}`,await h?.(),o}finally{try{await Ie({request_id:s,caller:e,provider:t.provider,tool:t.tool,scope_checked:d,outcome:P,jti:A,receipt_id:w,responder:y,question_id:k})}finally{v()}i.signal.removeEventListener("abort",a)}}g($r,"callProvider");async function Ye(e,r,i,c,t,n){const{machine:a}=n,s=await Ge(e,n.sub),j={machine:a,envelope:s,signal:n.signal,deadlineAt:n.deadlineAt,mapFailure:N};if(Y(r.major,i.tool)){const p=await Oe(j,t.arguments,r.major),m=J(c.output,p);if(m)throw new l("provider_bad_response",`the libraries result has an invalid output field "${m.field}"`,{origin:"provider",param:m.field,details:{status:200,...m}});return{result:p,responder:void 0,cleanup:void 0}}let v=t.arguments,h=null,_="";if(Ne(r.major,i.tool,t.arguments)){const p=await Fe(j,t.arguments,r.major);if(n.deadlineAt-Date.now()<=0)throw X(a,"timeout","");p!==null&&(v=p.arguments,h=p.services,_=p.release)}const d=await Me(a,{tool:i.tool,arguments:v,version:r.major,requestId:n.requestId,runId:e.run_id,deadlineAt:n.deadlineAt,upload:t.upload===null?null:{id:t.upload.upload_id,link:t.upload.upload_link}},s,n.signal);if(n.signal.aborted)throw n.signal.reason??new Error("provider call aborted");if("unreachable"in d)throw X(a,d.unreachable.reason,d.unreachable.message);const A=d.headers["crtr-responder"],w=G(d.body);if(d.status<200||d.status>=300){const p=Se(a,d.status,typeof w.code=="string"?w.code:void 0,typeof w.message=="string"?w.message:void 0,d.body),m=p===null&&d.status>=500&&typeof w.code=="string"?new l("provider_error",typeof w.message=="string"?w.message:`the device answered HTTP ${d.status}`,{origin:"runtime",status:d.status,details:{code:w.code,status:d.status}}):null;throw Object.assign(p??m??N(d.status,d.body,d.headers),{responder:A})}const y=d.body&&typeof d.body=="object"&&!Array.isArray(d.body)?d.body.result:void 0;if(!y||typeof y!="object"||Array.isArray(y))throw Object.assign(new l("provider_bad_response","the device result is not a JSON object",{origin:"provider",details:{status:d.status,message:"the device result is not a JSON object"}}),{responder:A});let k=y;if(h!==null){const p=De(k,h);if(Ue(a,s,_,p.calls),"error"in p)throw Object.assign(p.error,{responder:A});k=p.result}let P;try{P=await W(e,t,k,{signal:n.signal})}catch(p){throw p instanceof l&&p.code==="provider_error"?Object.assign(new l("provider_bad_response",p.message,{origin:"provider",details:{status:d.status,message:p.message}}),{responder:A}):p}const o=J(c.output,P.result);if(o)throw await P.cleanup?.(),Object.assign(new l("provider_bad_response",`the device result has an invalid output field "${o.field}"`,{origin:"provider",param:o.field,details:{status:d.status,...o}}),{responder:A});return{result:P.result,responder:A,cleanup:P.cleanup}}g(Ye,"callDevice");export{$r as callProvider,Xe as crtrCallerHeader,N as mapProviderResponse,ze as onProviderResponse,ee as providerLeaves,Pr as providerTools};
@@ -1 +1 @@
1
- var m=Object.defineProperty;var _=(t,i)=>m(t,"name",{value:i,configurable:!0});import{RunError as d}from"../runs/operations.js";import{errorCodes as r}from"../../api/error-codes.js";const g={provider_error:{type:"invalid_request_error",status:400,retryable:!1},provider_rate_limited:r.provider_rate_limited,provider_unavailable:r.provider_unavailable,provider_refused:r.provider_refused,provider_not_connected:r.provider_not_connected,provider_version_retired:r.provider_version_retired,storage_unavailable:r.storage_unavailable,approval_pending:{...r.approval_pending,user_action:"answer_question"},user_denied:r.user_denied},b={unauthorized:r.unauthorized,grant_revoked:r.grant_revoked,machine_revoked:r.machine_revoked,scope_missing:r.scope_missing,permission_error:r.permission_error,invalid_request:r.invalid_request,not_found:r.not_found,not_implemented:r.not_implemented,runtime_starting:r.runtime_starting,server_error:r.server_error,provider_bad_response:r.provider_bad_response,invalid_argument:r.invalid_argument,machine_required:r.machine_required,device_offline:r.device_offline,device_timeout:r.device_timeout,device_disconnected:r.device_disconnected,peer_version_too_old:r.peer_version_too_old,outcome_unknown:{type:"invalid_request_error",status:409,retryable:!1},wrong_site:{type:"invalid_request_error",status:409,retryable:!1},site_signed_out:{type:"invalid_request_error",status:409,retryable:!1},js_exception:{type:"invalid_request_error",status:409,retryable:!1},lib_broken:{type:"server_error",status:502,retryable:!1}};function a(t,i){return g[t]??b[t]??(Object.prototype.hasOwnProperty.call(r,t)?r[t]:void 0)??{type:i===401?"authentication_error":i===403?"permission_error":i===429?"rate_limit_error":i>=500?"server_error":"invalid_request_error",status:i,retryable:i>=500}}_(a,"codeRow");class u extends d{static{_(this,"ProviderError")}origin;type;retry_after_s;question_id;user_action;run_id;constructor(i,o,n={}){const e=a(i,n.status??500);super(n.status??e.status,i,o,n.param,n.details,n.scope,e.retryable),this.type=e.type,this.origin=n.origin??"runtime",n.cause!==void 0&&(this.cause=n.cause),n.retry_after_s!==void 0&&(this.retry_after_s=n.retry_after_s),n.question_id!==void 0&&(this.question_id=n.question_id),n.run_id!==void 0&&(this.run_id=n.run_id),e.user_action!==void 0&&(this.user_action=e.user_action)}}function R(t){return new u("scope_missing",`missing scope ${t}`,{scope:t})}_(R,"scopeMissing");function q(t){if(!(t instanceof Error))return null;const{status:i,code:o,details:n,retryable:e}=t;return typeof i!="number"||typeof o!="string"||i<400||i>599?null:new d(i,o,t.message,void 0,n,void 0,typeof e=="boolean"?e:a(o,i).retryable)}_(q,"shaped");function h(t){if(t.code==="unauthorized"||t.code==="grant_revoked")return"reconnect";if(t.code==="scope_missing"&&t.scope)return`grant_scope:${t.scope}`}_(h,"directoryAction");function w(t,i,o,n){const e=t instanceof d?t:q(t)??new u("server_error","provider request failed"),s=e instanceof u?e:null,v=a(e.code,e.status),c=s?.run_id??n,p=s?.user_action??(e.code==="cap_exhausted"?"raise_cap":o?h(e):void 0),l=e.code==="cap_exhausted"?e.details?.reset_at:void 0,y={code:e.code,message:e.message,...e.details===void 0?{}:{details:e.details},type:s?.type??v.type,...e.param?{param:e.param}:{},origin:s?.origin??"runtime",retryable:e.retryable,...s?.retry_after_s===void 0?{}:{retry_after_s:s.retry_after_s},...typeof l=="string"?{reset_at:l}:{},request_id:i,...c?{run_id:c}:{},...s?.question_id?{question_id:s.question_id}:{},...p?{user_action:p}:{},...e.scope?{scope:e.scope}:{}},f={"Request-Id":i};return s?.retry_after_s!==void 0&&(f["Retry-After"]=String(s.retry_after_s)),{status:e.status,body:{error:y},headers:f}}_(w,"providerErrorBody");export{g as PROVIDER_CODES,u as ProviderError,a as codeRow,w as providerErrorBody,R as scopeMissing};
1
+ var g=Object.defineProperty;var d=(t,i)=>g(t,"name",{value:i,configurable:!0});import{RunError as _}from"../runs/operations.js";import{errorCodes as r}from"../../api/error-codes.js";const b={provider_error:{type:"invalid_request_error",status:400,retryable:!1},provider_rate_limited:r.provider_rate_limited,provider_unavailable:r.provider_unavailable,provider_refused:r.provider_refused,provider_not_connected:r.provider_not_connected,provider_version_retired:r.provider_version_retired,storage_unavailable:r.storage_unavailable,approval_pending:{...r.approval_pending,user_action:"answer_question"},user_denied:r.user_denied},q={unauthorized:r.unauthorized,grant_revoked:r.grant_revoked,machine_revoked:r.machine_revoked,scope_missing:r.scope_missing,permission_error:r.permission_error,invalid_request:r.invalid_request,not_found:r.not_found,not_implemented:r.not_implemented,runtime_starting:r.runtime_starting,server_error:r.server_error,provider_bad_response:r.provider_bad_response,invalid_argument:r.invalid_argument,machine_required:r.machine_required,device_offline:r.device_offline,device_timeout:r.device_timeout,device_disconnected:r.device_disconnected,peer_version_too_old:r.peer_version_too_old,outcome_unknown:{type:"invalid_request_error",status:409,retryable:!1},wrong_site:{type:"invalid_request_error",status:409,retryable:!1},site_signed_out:{type:"invalid_request_error",status:409,retryable:!1},js_exception:{type:"invalid_request_error",status:409,retryable:!1},lib_broken:{type:"server_error",status:502,retryable:!1}};function a(t,i){return b[t]??q[t]??(Object.prototype.hasOwnProperty.call(r,t)?r[t]:void 0)??{type:i===401?"authentication_error":i===403?"permission_error":i===429?"rate_limit_error":i>=500?"server_error":"invalid_request_error",status:i,retryable:i>=500}}d(a,"codeRow");class u extends _{static{d(this,"ProviderError")}origin;type;retry_after_s;question_id;user_action;run_id;constructor(i,o,n={}){const e=a(i,n.status??500);super(n.status??e.status,i,o,n.param,n.details,n.scope,e.retryable),this.type=e.type,this.origin=n.origin??"runtime",n.cause!==void 0&&(this.cause=n.cause),n.retry_after_s!==void 0&&(this.retry_after_s=n.retry_after_s),n.question_id!==void 0&&(this.question_id=n.question_id),n.run_id!==void 0&&(this.run_id=n.run_id),e.user_action!==void 0&&(this.user_action=e.user_action)}}function w(t){return new u("scope_missing",`missing scope ${t}`,{scope:t})}d(w,"scopeMissing");function h(t){if(!(t instanceof Error))return null;const{status:i,code:o,details:n,retryable:e}=t;return typeof i!="number"||typeof o!="string"||i<400||i>599?null:new _(i,o,t.message,void 0,n,void 0,typeof e=="boolean"?e:a(o,i).retryable)}d(h,"shaped");function x(t){if(t.code==="unauthorized"||t.code==="grant_revoked")return"reconnect";if(t.code==="scope_missing"&&t.scope)return`grant_scope:${t.scope}`}d(x,"directoryAction");function O(t,i,o,n){const e=t instanceof _?t:h(t)??new u("server_error","provider request failed"),s=e instanceof u?e:null,y=a(e.code,e.status),c=s?.run_id??n,p=e.details?.user_action,l=s?.user_action??(e.code==="cap_exhausted"?typeof p=="string"?p:void 0:o?x(e):void 0),f=e.code==="cap_exhausted"?e.details?.reset_at:void 0,m={code:e.code,message:e.message,...e.details===void 0?{}:{details:e.details},type:s?.type??y.type,...e.param?{param:e.param}:{},origin:s?.origin??"runtime",retryable:e.retryable,...s?.retry_after_s===void 0?{}:{retry_after_s:s.retry_after_s},...typeof f=="string"?{reset_at:f}:{},request_id:i,...c?{run_id:c}:{},...s?.question_id?{question_id:s.question_id}:{},...l?{user_action:l}:{},...e.scope?{scope:e.scope}:{}},v={"Request-Id":i};return s?.retry_after_s!==void 0&&(v["Retry-After"]=String(s.retry_after_s)),{status:e.status,body:{error:m},headers:v}}d(O,"providerErrorBody");export{b as PROVIDER_CODES,u as ProviderError,a as codeRow,O as providerErrorBody,w as scopeMissing};
@@ -1,3 +1,4 @@
1
+ import type { Funding } from '../ledger/types.js';
1
2
  type ReceiptCall = {
2
3
  provider: string;
3
4
  tool: string;
@@ -7,8 +8,13 @@ type ReceiptCall = {
7
8
  run_id: string | null;
8
9
  /** The outbound token's `payer` claim: the principal the directory charges (an app, or the user). */
9
10
  payer: string;
10
- /** Whose month the receipt adds to when it differs from the receipt's grantee (the person's calls count under `app:terminal`). */
11
+ /** The app the charge is attributed to when it differs from the receipt's grantee (the person's calls count under `app:terminal`). */
11
12
  ledger_grantee?: string;
13
+ /** `bill` or `endpoint`, from `payerOf` on the token's payer. */
14
+ funding: Funding;
15
+ /** The calling node and the call's `Crtr-Caused-By`; null when none. */
16
+ node_id: string | null;
17
+ caused_by: string | null;
12
18
  };
13
19
  /**
14
20
  * A provider's informational receipts must belong to the call that carried them. The header is one
@@ -1,3 +1 @@
1
- var p=Object.defineProperty;var a=(t,r)=>p(t,"name",{value:r,configurable:!0});import{withCanvasWrite as _}from"../canvas/db.js";import{addUsage as f}from"../usage/ledger.js";const g=8,y=65536;function c(t,r){if(!t||typeof t!="object"||Array.isArray(t))return!1;const e=t;return typeof e.receipt_id=="string"&&!!e.receipt_id&&e.receipt_id.length<=256&&e.provider===`app:${r.provider}`&&e.tool===r.tool&&e.request_id===r.request_id&&e.sub===r.sub&&e.grantee===r.grantee&&e.payer===r.payer&&(e.run_id??null)===r.run_id&&typeof e.unit=="string"&&!!e.unit&&typeof e.units=="number"&&Number.isFinite(e.units)&&e.units>=0&&typeof e.time=="string"&&Number.isFinite(Date.parse(e.time))&&typeof e.usd_equivalent=="number"&&Number.isFinite(e.usd_equivalent)&&e.usd_equivalent>=0}a(c,"belongsToCall");async function N(t,r){const e=Array.isArray(t)?t[0]:t;if(!e||e.length>y)return;let n;try{n=JSON.parse(e)}catch{return}if(Array.isArray(n)&&n.length>g)return;const o=(Array.isArray(n)?n:[n]).filter(i=>c(i,r));if(o.length)return await _(async i=>{for(const s of o){if(!(await i.prepare(`INSERT INTO provider_receipts
2
- (provider, receipt_id, grantee, run_id, usd_equivalent, received_at) VALUES (?, ?, ?, ?, ?, ?)
3
- ON CONFLICT DO NOTHING`).run(r.provider,s.receipt_id,r.grantee,r.run_id,s.usd_equivalent,new Date().toISOString())).changes||(await f(i,{grantee:r.ledger_grantee??r.grantee,payer:r.payer.startsWith("app:")?"app":"user",source:`provider:${r.provider}`,served_model:"",input_tokens:0,output_tokens:0,cached_tokens:0,usd_equivalent:s.usd_equivalent}),!r.run_id))continue;const d=await i.prepare("SELECT usage_json FROM nodes WHERE node_id = ? AND run_id = ?").get(r.run_id,r.run_id);if(!d)continue;const u=d.usage_json?JSON.parse(d.usage_json):{};u.cost_usd=(typeof u.cost_usd=="number"?u.cost_usd:0)+s.usd_equivalent,await i.prepare("UPDATE nodes SET usage_json = ? WHERE node_id = ?").run(JSON.stringify(u),r.run_id)}}),o[0].receipt_id}a(N,"acceptProviderReceipt");export{N as acceptProviderReceipt};
1
+ var a=Object.defineProperty;var p=(t,e)=>a(t,"name",{value:e,configurable:!0});import{withCanvasWrite as f}from"../canvas/db.js";import{receiptChargeId as g,writeCharge as y}from"../ledger/index.js";const A=8,E=65536;function b(t,e){if(!t||typeof t!="object"||Array.isArray(t))return!1;const r=t;return typeof r.receipt_id=="string"&&!!r.receipt_id&&r.receipt_id.length<=256&&r.provider===`app:${e.provider}`&&r.tool===e.tool&&r.request_id===e.request_id&&r.sub===e.sub&&r.grantee===e.grantee&&r.payer===e.payer&&(r.run_id??null)===e.run_id&&typeof r.unit=="string"&&!!r.unit&&typeof r.units=="number"&&Number.isFinite(r.units)&&r.units>=0&&typeof r.time=="string"&&Number.isFinite(Date.parse(r.time))&&typeof r.usd_equivalent=="number"&&Number.isFinite(r.usd_equivalent)&&r.usd_equivalent>=0}p(b,"belongsToCall");async function h(t,e){const r=Array.isArray(t)?t[0]:t;if(!r||r.length>E)return;let n;try{n=JSON.parse(r)}catch{return}if(Array.isArray(n)&&n.length>A)return;const o=(Array.isArray(n)?n:[n]).filter(u=>b(u,e));if(o.length)return await f(async u=>{for(const i of o){const{written:_}=await y({id:g(e.provider,i.receipt_id),request:e.request_id,kind:"tool",what:`${e.provider}:${e.tool}`,units:{units:i.units,unit:i.unit},usd:i.usd_equivalent,payer:e.payer,funding:e.funding,sub:e.sub,grantee:e.ledger_grantee??e.grantee,node:e.node_id,run:e.run_id,provider:`app:${e.provider}`,causedBy:e.caused_by,vendorRef:i.receipt_id});if(!_||!e.run_id)continue;const d=await u.prepare("SELECT usage_json FROM nodes WHERE node_id = ? AND run_id = ?").get(e.run_id,e.run_id);if(!d)continue;const s=d.usage_json?JSON.parse(d.usage_json):{};s.cost_usd=(typeof s.cost_usd=="number"?s.cost_usd:0)+i.usd_equivalent,await u.prepare("UPDATE nodes SET usage_json = ? WHERE node_id = ?").run(JSON.stringify(s),e.run_id)}}),o[0].receipt_id}p(h,"acceptProviderReceipt");export{h as acceptProviderReceipt};
@@ -46,6 +46,7 @@ export declare function startRun(principal: AppPrincipal, input: {
46
46
  deadline?: string;
47
47
  output_schema?: Record<string, unknown>;
48
48
  message?: string;
49
+ causedBy?: string;
49
50
  }, idempotencyKey?: string, resolveAttachments?: AttachmentResolver): Promise<Record<string, unknown>>;
50
51
  export declare function listRuns(grantee: string | null, options: {
51
52
  status?: string;
@@ -1,14 +1,14 @@
1
- var Oe=Object.defineProperty;var u=(e,t)=>Oe(e,"name",{value:t,configurable:!0});import{coveredByAny as be}from"../../shared/env.js";import{createHash as G}from"node:crypto";import{ApiError as De}from"../../api/errors.js";import{CrtrError as Me}from"../errors.js";import{isAbsolute as z,relative as Ie,resolve as Ae,sep as Te,join as Le}from"node:path";import{SessionManager as Ce}from"@earendil-works/pi-coding-agent";import{covers as U}from"@north-light/identity";import{openDb as P,withCanvasWrite as W}from"../canvas/db.js";import{deleteNodeWithOwned as ke}from"../graph/deletion.js";import{getById as xe}from"../graph/objects.js";import{repairRunConversations as Q}from"../canvas/sessions.js";import{getNode as v,nodeFiles as We,removeNodeFiles as Fe,updateNode as qe}from"../canvas/canvas.js";import{fullName as He}from"../canvas/labels.js";import{renameWindow as Ue}from"../runtime/placement.js";import{liveExecutionForNode as V}from"../canvas/executions.js";import{conversationStore as Z,isConversationNotFound as Pe}from"../conversation-store/index.js";import{PARKED_RESIDENT_SQL as $e}from"../canvas/canvas.js";import{WAKE_MAIL_SQL as Be}from"../canvas/deliveries.js";import{enqueueNodeMail as je}from"../feed/messages.js";import{newestReportBody as Je}from"../feed/reports.js";import{ensureAppProfile as Ye,loadExactProfileManifest as Xe}from"../profiles/manifest.js";import{stopNodeSandboxes as K}from"../spaces/stop.js";import{BrokerUnreachableError as Ge}from"../runtime/broker-request.js";import{interruptLive as ze}from"../runtime/interactive-deliver.js";import{isBrokerLive as ee}from"../runtime/model-swap.js";import{newNodeId as Qe}from"../runtime/nodes.js";import{reviveNode as $}from"../runtime/revive.js";import{spawnChildPrepared as Ve}from"../runtime/spawn.js";import{isPortableModelToken as Ze}from"../runtime/launch.js";import{parseDurationMs as Ke}from"../wake.js";import{expandModelCandidates as et,parseModelSpec as tt}from"../model-routes.js";import{payerOfGrant as B}from"../grants/mirror.js";import{isolatedBrokerLauncherAvailable as nt}from"../runtime/host.js";import{resolveRunKind as st,resolveRunModel as at}from"../runtime/launch-target.js";import{cycleAwareMessages as it}from"../runtime/session-cycles.js";import{originFor as te}from"../runtime/stamp/protocol.js";import{readOutputRequest as rt,readOutputResult as ne}from"../runtime/structured-output.js";import{admitLegacyStructuredOutput as se}from"../../daemon/structured-requests/sidecar.js";import{runSchemaRepromptPending as ot}from"../runtime/stop-guard.js";import{toRunOutcomeDTO as dt}from"../../daemon/api/map.js";import{openAssistantMessageStartSequence as ct}from"../../daemon/runs/observer.js";import{closeNode as ae}from"../runtime/close.js";import{parseScope as ut}from"@north-light/identity";import{appendRunEvent as ie,subscribeRunEvents as mt}from"./events.js";import{runActivity as lt}from"./activity.js";import{cancelOpenQuestions as re,openNoticeIds as pt,openQuestionIds as oe}from"./questions.js";import{appSpace as j}from"../layout.js";import{ensureAppSpace as _t}from"../spaces/space.js";import{assertUploadsUsable as de,resolveStorageUrls as ft}from"../storage/attachments.js";import{storageClient as wt,storageConfig as gt}from"../storage/client.js";import{deleteUploadRow as Et,insertUploadUses as ce,releaseRunUploads as yt}from"../storage/tables.js";import{abortProviderCalls as ue}from"../providers/inflight.js";import{filterAsync as me,mapAsync as L}from"../async-array.js";const le=u((e,t,a)=>ft(t,e,a),"defaultResolver"),ht=3e3;class S extends Error{static{u(this,"RunError")}status;code;param;details;scope;retryable;constructor(t,a,n,o,m,r,i=t===503){super(n),this.status=t,this.code=a,this.param=o,this.details=m,this.scope=r,this.retryable=i}}const h=u((e,t)=>new S(400,"invalid_request",e,t),"invalid"),J=u(()=>new S(404,"not_found","run not found"),"missing"),Y=u(()=>({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}),"usage"),D=u(async()=>await P(),"db");async function F(e,t,a=!1){const n=await v(e);if(!n||n.parent!==null||n.run_id!==e||n.grantee!==t||!a&&n.deleting_at)throw J();return n}u(F,"ownedRun");const pe=["waiting_on_user","idle","settled"];async function T(e){if(e.status==="canceled"||e.status==="dead"||e.status==="done"&&e.intent!=="parked")return"settled";const t=await(await D()).prepare(`SELECT 1 FROM node_rows n WHERE n.run_id = ? AND n.status = 'active' AND
1
+ var Oe=Object.defineProperty;var u=(e,t)=>Oe(e,"name",{value:t,configurable:!0});import{coveredByAny as be}from"../../shared/env.js";import{createHash as G}from"node:crypto";import{ApiError as De}from"../../api/errors.js";import{CrtrError as Me}from"../errors.js";import{isAbsolute as z,relative as Ie,resolve as Ae,sep as Te,join as Le}from"node:path";import{SessionManager as Ce}from"@earendil-works/pi-coding-agent";import{covers as U}from"@north-light/identity";import{openDb as B,withCanvasWrite as W}from"../canvas/db.js";import{deleteNodeWithOwned as ke}from"../graph/deletion.js";import{getById as xe}from"../graph/objects.js";import{repairRunConversations as Q}from"../canvas/sessions.js";import{getNode as O,nodeFiles as We,removeNodeFiles as Fe,updateNode as qe}from"../canvas/canvas.js";import{fullName as He}from"../canvas/labels.js";import{renameWindow as Ue}from"../runtime/placement.js";import{liveExecutionForNode as V}from"../canvas/executions.js";import{conversationStore as Z,isConversationNotFound as Be}from"../conversation-store/index.js";import{PARKED_RESIDENT_SQL as Pe}from"../canvas/canvas.js";import{WAKE_MAIL_SQL as $e}from"../canvas/deliveries.js";import{enqueueNodeMail as je}from"../feed/messages.js";import{newestReportBody as Je}from"../feed/reports.js";import{ensureAppProfile as Ye,loadExactProfileManifest as Xe}from"../profiles/manifest.js";import{stopNodeSandboxes as K}from"../spaces/stop.js";import{BrokerUnreachableError as Ge}from"../runtime/broker-request.js";import{interruptLive as ze}from"../runtime/interactive-deliver.js";import{isBrokerLive as ee}from"../runtime/model-swap.js";import{newNodeId as Qe}from"../runtime/nodes.js";import{reviveNode as P}from"../runtime/revive.js";import{spawnChildPrepared as Ve}from"../runtime/spawn.js";import{isPortableModelToken as Ze}from"../runtime/launch.js";import{parseDurationMs as Ke}from"../wake.js";import{expandModelCandidates as et,parseModelSpec as tt}from"../model-routes.js";import{payerOfGrant as $}from"../grants/mirror.js";import{isolatedBrokerLauncherAvailable as nt}from"../runtime/host.js";import{resolveRunKind as st,resolveRunModel as at}from"../runtime/launch-target.js";import{cycleAwareMessages as it}from"../runtime/session-cycles.js";import{originFor as te}from"../runtime/stamp/protocol.js";import{readOutputRequest as rt,readOutputResult as ne}from"../runtime/structured-output.js";import{admitLegacyStructuredOutput as se}from"../../daemon/structured-requests/sidecar.js";import{runSchemaRepromptPending as ot}from"../runtime/stop-guard.js";import{toRunOutcomeDTO as dt}from"../../daemon/api/map.js";import{openAssistantMessageStartSequence as ct}from"../../daemon/runs/observer.js";import{closeNode as ae}from"../runtime/close.js";import{parseScope as ut}from"@north-light/identity";import{appendRunEvent as ie,subscribeRunEvents as mt}from"./events.js";import{runActivity as lt}from"./activity.js";import{cancelOpenQuestions as re,openNoticeIds as pt,openQuestionIds as oe}from"./questions.js";import{appSpace as j}from"../layout.js";import{ensureAppSpace as _t}from"../spaces/space.js";import{assertUploadsUsable as de,resolveStorageUrls as ft}from"../storage/attachments.js";import{storageClient as wt,storageConfig as gt}from"../storage/client.js";import{deleteUploadRow as Et,insertUploadUses as ce,releaseRunUploads as yt}from"../storage/tables.js";import{abortProviderCalls as ue}from"../providers/inflight.js";import{filterAsync as me,mapAsync as k}from"../async-array.js";const le=u((e,t,s)=>ft(t,e,s),"defaultResolver"),ht=3e3;class N extends Error{static{u(this,"RunError")}status;code;param;details;scope;retryable;constructor(t,s,n,d,l,i,r=t===503){super(n),this.status=t,this.code=s,this.param=d,this.details=l,this.scope=i,this.retryable=r}}const S=u((e,t)=>new N(400,"invalid_request",e,t),"invalid"),J=u(()=>new N(404,"not_found","run not found"),"missing"),Y=u(()=>({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}),"usage"),I=u(async()=>await B(),"db");async function F(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 J();return n}u(F,"ownedRun");const pe=["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 I()).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),a=!e.last_settled_at&&e.status!=="done";return t||a||await ot(e)?"running":(await oe(e.node_id)).length?"waiting_on_user":await(await D()).prepare(`SELECT 1 FROM deliveries d JOIN nodes n ON n.node_id = d.destination_id
7
- WHERE n.run_id = ? AND ${Be("d","'armed', 'pending'")}
8
- AND (n.status IN ('active', 'idle') OR ${$e("n")}) LIMIT 1`).get(e.node_id)?"running":"idle"}u(T,"runStatus");async function On(e){const t=await v(e);return t!==null&&await T(t)==="running"}u(On,"runIsRunning");async function C(e){await Q(e.node_id),e=await v(e.node_id)??e;const t=await T(e),a=t==="settled"?[]:await oe(e.node_id),n=await Je(e.node_id)||void 0,o=t==="settled"?dt(e):null,m=o?.kind==="result"?ne(e.node_id,e.grantee):void 0;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}:{},pending_question_ids:a,open_notice_ids:t==="settled"?[]:await pt(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(Y())),payer:await B(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 lt(e.node_id,t)}}u(C,"runObject");const X=864e5,_e=255;function bn(e){if(e!==void 0){if(typeof e!="string"||!e.length||e.length>_e)throw h(`Idempotency-Key must be 1-${_e} characters`);return e}}u(bn,"idempotencyKeyOf");async function q(e,t,a,n){n??=await P();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)>=X)){if(o.body_hash!==a)throw new S(409,"idempotency_conflict","key used with a different request");return{run_id:o.run_id,response:JSON.parse(o.response_json)}}}u(q,"findIdempotent");async function fe(e,t,a,n,o,m,r){await e.prepare("DELETE FROM idempotency_keys WHERE grantee = ? AND key = ? AND created_at <= ?").run(t,a,new Date(Date.now()-X).toISOString()),await e.prepare("INSERT INTO idempotency_keys (grantee, key, body_hash, run_id, response_json, created_at) VALUES (?, ?, ?, ?, ?, ?)").run(t,a,n,o,JSON.stringify(m),r)}u(fe,"recordIdempotent");async function Dn(e=Date.now()){return Number((await(await P()).prepare("DELETE FROM idempotency_keys WHERE created_at <= ?").run(new Date(e-X).toISOString())).changes)}u(Dn,"pruneExpiredIdempotencyKeys");async function we(e,t,a,n,o){const m=n.text;let r=0;return{messageId:(await je(t,{kind:"message",label:m.slice(0,120),senderNodeId:"human",senderName:a,bodyJson:o?{body:m}:{body:m,start_turn:!1},urgency:o?"normal":"deferred",wake:o?1:0,withinEnqueue:u(async(c,f)=>{n.uses.length&&(await de(a,n.uses,c),await ce(n.uses.map(({upload_id:y,path:g})=>({upload_id:y,path:g,run_id:t})),c)),r=(await ie(c,t,t,"node.message.accepted",{message_id:f,start_turn:o})).sequence_number},"withinEnqueue")})).messageId,sequence:r}}u(we,"acceptRunMessage");class ge extends Error{static{u(this,"IdempotentReplay")}winner;constructor(t){super("idempotent replay"),this.winner=t}}const Rt=1440*60*1e3;function Ee(e){const t=typeof e=="string"?Ke(e):null;if(t===null||!Number.isSafeInteger(t))throw h(`deadline '${String(e)}' is not a duration; use one or more <int>[smhd] parts such as 10m or 1h30m`,"deadline");if(t<=0)throw h("deadline must be greater than zero","deadline");if(t>Rt)throw h("deadline must be at most 24h","deadline");return t}u(Ee,"parseRunDeadlineMs");async function Mn(e,t,a,n=le){if(t.isolated&&!nt())throw new S(503,"isolated_unavailable","isolated runs require the Linux root launcher","isolated");t.deadline!==void 0&&Ee(t.deadline);const o=G("sha256").update(JSON.stringify(t)).digest("hex");if(a){const s=await q(e.grantee,a,o);if(s){const l=await F(s.run_id,e.grantee);return!l.pi_pid&&await T(l)==="running"&&(t.output_schema!==void 0&&!l.outcome_at&&rt(l.node_id).state==="absent"&&ne(l.node_id,l.grantee)===void 0&&await se(l.node_id,"terminal",t.output_schema),await $(l.node_id,{resume:!0,capacity:"freeze"})),s.response}}await _t(e.grantee);const m=t.profile===void 0?Ye(e.grantee):Xe(t.profile),r=m.manifest.grantee??"app:terminal";if(r!==e.grantee){const s=`crtr:memory:rw:${r}:profile:${m.profileId}`;if(!e.resolved.some(l=>U(l,s))||t.scopes!==null&&!t.scopes.some(l=>U(l,s)))throw new S(403,"scope_missing",`missing scope ${s}`,"profile",void 0,s)}if(t.model!==void 0){const s=t.model;if(Ze(s)){if(s.includes("/")&&await B(e.grant)!=="app"){const l=s.lastIndexOf("/"),E=s.slice(0,l),N=s.slice(l+1);if(["ultra","strong","medium","light"].includes(N)&&et({kind:"logical",family:E,strength:N,spec:s},j(e.grantee).files,m.profileId).every(R=>R.family!==E))throw h(`model '${s}' names a model family that is not configured in this daemon`,"model")}}else if(tt(s)===void 0)throw h(`model '${s}' is not a strength (ultra, strong, medium, light), a family/strength, or a provider/model id`,"model")}const i=await Qe(),c=Le(j(e.grantee).nodes,i);if(t.isolated&&t.cwd!==void 0){const s=Ie(c,Ae(t.cwd));if(!z(t.cwd)||s===".."||s.startsWith(`..${Te}`)||z(s))throw h("cwd must be inside the isolated root node folder","cwd")}const f=await n(i,e.grantee,t.prompt),y=f.text;let g;try{g=t.message===void 0?void 0:await n(i,e.grantee,t.message)}catch(s){throw f.cleanup(),s}const w=await B(e.grant);let d;try{const s=at(m,t.model);await Ve({kind:st(m),mode:"base",root:!0,rootLifecycle:"resident",readiness:"launch",cwd:t.isolated?t.cwd??c:j(e.grantee).files,profile:m.profileId,prompt:y,nodeId:i,isolated:t.isolated??!1,...s===void 0?{}:{model:s},...t.deadline===void 0?{}:{deadlineAt:new Date(Date.now()+Ee(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:i,event_cursor:1,usage_json:JSON.stringify(Y())},withinCreate:u(async(l,E)=>{if(a){const R=await q(e.grantee,a,o,l);if(R)throw new ge(R)}const N=f.uses;if(N.length&&(await de(e.grantee,N,l),await ce(N.map(({upload_id:R,path:M})=>({upload_id:R,path:M,run_id:i})),l)),d={run_id:i,node_id:i,grantee:e.grantee,grant:e.grant,rev:e.rev,scopes:t.scopes,payer:w,status:"running",created_at:E.created,metadata:t.metadata,sequence_number:0},await ie(l,i,i,"run.started",{scopes:t.scopes,payer:w,usage:Y()}),g){const R=await we(l,i,e.grantee,g,!1);d.message={run_id:i,message_id:R.messageId,sequence_number:R.sequence}}a&&await fe(l,e.grantee,a,o,i,d,E.created)},"withinCreate")},t.output_schema===void 0?void 0:async l=>{await se(l,"terminal",t.output_schema)})}catch(s){if(await v(i)||(f.cleanup(),g?.cleanup()),s instanceof ge)return s.winner.response;if(t.model!==void 0&&s instanceof Me&&s.code==="usage")throw h(s.message,"model");if(s instanceof De&&(s.code==="isolated_run"||s.code==="invalid_request")){const l=s.details&&typeof s.details=="object"&&"param"in s.details&&typeof s.details.param=="string"?s.details.param:void 0;throw new S(s.status,s.code,s.message,l)}throw s}if(!d)throw new Error("run creation did not commit");return d}u(Mn,"startRun");async function In(e,t){let a;if(t.after)try{const i=JSON.parse(Buffer.from(t.after,"base64url").toString());if(!i||typeof i!="object"||!("activity"in i)||typeof i.activity!="string"||!("id"in i)||typeof i.id!="string")throw new Error("invalid cursor");a={activity:i.activity,id:i.id}}catch{throw h("invalid list cursor","after")}const n=await(await D()).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 ot(e)?"running":(await oe(e.node_id)).length?"waiting_on_user":await(await I()).prepare(`SELECT 1 FROM deliveries d JOIN nodes n ON n.node_id = d.destination_id
7
+ WHERE n.run_id = ? AND ${$e("d","'armed', 'pending'")}
8
+ AND (n.status IN ('active', 'idle') OR ${Pe("n")}) LIMIT 1`).get(e.node_id)?"running":"idle"}u(C,"runStatus");async function On(e){const t=await O(e);return t!==null&&await C(t)==="running"}u(On,"runIsRunning");async function x(e){await Q(e.node_id),e=await O(e.node_id)??e;const t=await C(e),s=t==="settled"?[]:await oe(e.node_id),n=await Je(e.node_id)||void 0,d=t==="settled"?dt(e):null,l=d?.kind==="result"?ne(e.node_id,e.grantee):void 0;return{run_id:e.node_id,name:e.name,status:t,...d?{outcome:d}:{},...l===void 0?{}:{result:l},...n!==void 0?{last_report:n}:{},pending_question_ids:s,open_notice_ids:t==="settled"?[]:await pt(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(Y())),payer:await $(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 lt(e.node_id,t)}}u(x,"runObject");const X=864e5,_e=255;function bn(e){if(e!==void 0){if(typeof e!="string"||!e.length||e.length>_e)throw S(`Idempotency-Key must be 1-${_e} characters`);return e}}u(bn,"idempotencyKeyOf");async function q(e,t,s,n){n??=await B();const d=await n.prepare("SELECT body_hash, run_id, response_json, created_at FROM idempotency_keys WHERE grantee = ? AND key = ?").get(e,t);if(!(!d||Date.now()-Date.parse(d.created_at)>=X)){if(d.body_hash!==s)throw new N(409,"idempotency_conflict","key used with a different request");return{run_id:d.run_id,response:JSON.parse(d.response_json)}}}u(q,"findIdempotent");async function fe(e,t,s,n,d,l,i){await e.prepare("DELETE FROM idempotency_keys WHERE grantee = ? AND key = ? AND created_at <= ?").run(t,s,new Date(Date.now()-X).toISOString()),await e.prepare("INSERT INTO idempotency_keys (grantee, key, body_hash, run_id, response_json, created_at) VALUES (?, ?, ?, ?, ?, ?)").run(t,s,n,d,JSON.stringify(l),i)}u(fe,"recordIdempotent");async function Dn(e=Date.now()){return Number((await(await B()).prepare("DELETE FROM idempotency_keys WHERE created_at <= ?").run(new Date(e-X).toISOString())).changes)}u(Dn,"pruneExpiredIdempotencyKeys");async function we(e,t,s,n,d){const l=n.text;let i=0;return{messageId:(await je(t,{kind:"message",label:l.slice(0,120),senderNodeId:"human",senderName:s,bodyJson:d?{body:l}:{body:l,start_turn:!1},urgency:d?"normal":"deferred",wake:d?1:0,withinEnqueue:u(async(c,m)=>{n.uses.length&&(await de(s,n.uses,c),await ce(n.uses.map(({upload_id:h,path:E})=>({upload_id:h,path:E,run_id:t})),c)),i=(await ie(c,t,t,"node.message.accepted",{message_id:m,start_turn:d})).sequence_number},"withinEnqueue")})).messageId,sequence:i}}u(we,"acceptRunMessage");class ge extends Error{static{u(this,"IdempotentReplay")}winner;constructor(t){super("idempotent replay"),this.winner=t}}const Rt=1440*60*1e3;function Ee(e){const t=typeof e=="string"?Ke(e):null;if(t===null||!Number.isSafeInteger(t))throw S(`deadline '${String(e)}' is not a duration; use one or more <int>[smhd] parts such as 10m or 1h30m`,"deadline");if(t<=0)throw S("deadline must be greater than zero","deadline");if(t>Rt)throw S("deadline must be at most 24h","deadline");return t}u(Ee,"parseRunDeadlineMs");async function Mn(e,t,s,n=le){if(t.isolated&&!nt())throw new N(503,"isolated_unavailable","isolated runs require the Linux root launcher","isolated");t.deadline!==void 0&&Ee(t.deadline);const{causedBy:d,...l}=t,i=G("sha256").update(JSON.stringify(l)).digest("hex");if(s){const a=await q(e.grantee,s,i);if(a){const p=await F(a.run_id,e.grantee);return!p.pi_pid&&await C(p)==="running"&&(t.output_schema!==void 0&&!p.outcome_at&&rt(p.node_id).state==="absent"&&ne(p.node_id,p.grantee)===void 0&&await se(p.node_id,"terminal",t.output_schema),await P(p.node_id,{resume:!0,capacity:"freeze"})),a.response}}await _t(e.grantee);const r=t.profile===void 0?Ye(e.grantee):Xe(t.profile),c=r.manifest.grantee??"app:terminal";if(c!==e.grantee){const a=`crtr:memory:rw:${c}:profile:${r.profileId}`;if(!e.resolved.some(p=>U(p,a))||t.scopes!==null&&!t.scopes.some(p=>U(p,a)))throw new N(403,"scope_missing",`missing scope ${a}`,"profile",void 0,a)}if(t.model!==void 0){const a=t.model;if(Ze(a)){if(a.includes("/")&&await $(e.grant)!=="app"){const p=a.lastIndexOf("/"),D=a.slice(0,p),v=a.slice(p+1);if(["ultra","strong","medium","light"].includes(v)&&et({kind:"logical",family:D,strength:v,spec:a},j(e.grantee).files,r.profileId).every(R=>R.family!==D))throw S(`model '${a}' names a model family that is not configured in this daemon`,"model")}}else if(tt(a)===void 0)throw S(`model '${a}' is not a strength (ultra, strong, medium, light), a family/strength, or a provider/model id`,"model")}const m=await Qe(),h=Le(j(e.grantee).nodes,m);if(t.isolated&&t.cwd!==void 0){const a=Ie(h,Ae(t.cwd));if(!z(t.cwd)||a===".."||a.startsWith(`..${Te}`)||z(a))throw S("cwd must be inside the isolated root node folder","cwd")}const E=await n(m,e.grantee,t.prompt),g=E.text;let o;try{o=t.message===void 0?void 0:await n(m,e.grantee,t.message)}catch(a){throw E.cleanup(),a}const _=await $(e.grant);let y;try{const a=at(r,t.model);await Ve({kind:st(r),mode:"base",root:!0,rootLifecycle:"resident",readiness:"launch",cwd:t.isolated?t.cwd??h:j(e.grantee).files,profile:r.profileId,prompt:g,nodeId:m,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()+Ee(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:m,event_cursor:1,usage_json:JSON.stringify(Y())},withinCreate:u(async(p,D)=>{if(s){const R=await q(e.grantee,s,i,p);if(R)throw new ge(R)}const v=E.uses;if(v.length&&(await de(e.grantee,v,p),await ce(v.map(({upload_id:R,path:A})=>({upload_id:R,path:A,run_id:m})),p)),y={run_id:m,node_id:m,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 ie(p,m,m,"run.started",{scopes:t.scopes,payer:_,usage:Y()}),o){const R=await we(p,m,e.grantee,o,!1);y.message={run_id:m,message_id:R.messageId,sequence_number:R.sequence}}s&&await fe(p,e.grantee,s,i,m,y,D.created)},"withinCreate")},t.output_schema===void 0?void 0:async p=>{await se(p,"terminal",t.output_schema)})}catch(a){if(await O(m)||(E.cleanup(),o?.cleanup()),a instanceof ge)return a.winner.response;if(t.model!==void 0&&a instanceof Me&&a.code==="usage")throw S(a.message,"model");if(a instanceof De&&(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 N(a.status,a.code,a.message,p)}throw a}if(!y)throw new Error("run creation did not commit");return y}u(Mn,"startRun");async function In(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 S("invalid list cursor","after")}const n=await(await I()).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 = ?"}
10
- ORDER BY activity DESC, node_id DESC`).all(...e===null?[]:[e]),o=await me(await L((await me(n,async({node_id:i})=>!t.visible||await t.visible(i))).filter(({activity:i,node_id:c})=>!a||i<a.activity||i===a.activity&&c<a.id),async i=>({root:await v(i.node_id),activity:i.activity})),async({root:i})=>!t.status||await T(i)===t.status),m=o.slice(0,t.limit),r=m.at(-1);return{runs:await L(m,async({root:i})=>await C(i)),next:o.length>t.limit&&r?Buffer.from(JSON.stringify({activity:r.activity,id:r.root.node_id})).toString("base64url"):null}}u(In,"listRuns");async function An(e,t,a){const n=await F(e,t),o=u(async()=>await C(await F(e,t)),"read");return!a||pe.includes(await T(n))?await o():new Promise((m,r)=>{let i=u(()=>{},"unsubscribe");const c=u(()=>{clearTimeout(d),clearInterval(w),i()},"settle"),f=u(async()=>{c();try{m(await o())}catch(s){r(s)}},"finish"),y=u(async()=>{pe.includes(String((await o()).status))&&await f()},"check"),g=u(()=>{y().catch(s=>{c(),r(s)})},"run"),w=setInterval(g,250),d=setTimeout(()=>{f()},a*1e3);mt(e,g).then(s=>{i=s},s=>{c(),r(s)})})}u(An,"waitRun");async function Tn(e,t,a=le,n=!0,o){const m=e.status==="canceled"||e.outcome_reason==="closed",r=e.grantee??"app:terminal",i=G("sha256").update(JSON.stringify(["run.message",e.node_id,t,n])).digest("hex"),c=u(async w=>{const d=await v(e.node_id),s=await(await D()).prepare("SELECT 1 FROM deliveries WHERE message_id = ? AND state = 'pending' AND canceled_at IS NULL").get(String(w.message_id));return d&&!m&&n&&!d.pi_pid&&s&&await $(e.node_id,{resume:!0,capacity:"freeze"}),w},"replay");if(o){const w=await q(r,o,i);if(w)return c(w.response)}if(m)throw new S(409,"run_settled","canceled run cannot receive a message");const f=await a(e.node_id,r,t),y=n&&e.final_report&&!e.pi_pid?(await import("../runtime/reopen.js")).commitReopenResident:void 0;let g;try{g=await W(async w=>{if(o){const l=await q(r,o,i,w);if(l)return{replayed:l.response}}await y?.(e.node_id);const d=await we(w,e.node_id,r,f,n),s={run_id:e.node_id,message_id:d.messageId,sequence_number:d.sequence};return o&&await fe(w,r,o,i,e.node_id,s,new Date().toISOString()),{result:s}})}catch(w){throw f.cleanup(),w}return"replayed"in g?(f.cleanup(),c(g.replayed)):(n&&!e.pi_pid&&await $(e.node_id,{resume:!0,capacity:"freeze"}),g.result)}u(Tn,"messageRun");async function St(e){const t=u(()=>new S(503,"service_unavailable",`node ${e} broker was unavailable before the interrupt reached it`),"unavailable");for(let a=0;a<2;a++){const n=await v(e);if(!n)throw J();if(!ee(n)){if(n.streaming)throw t();return}const o=(await V(e))?.executionId;try{await ze(e)==="turn"&&ue({nodes:[e]});return}catch(m){if(!(m instanceof Ge))throw m;const r=await v(e);if(!r)throw J();if(!r.streaming)return;if(a===0&&ee(r)&&(await V(e))?.executionId!==o)continue;throw t()}}throw t()}u(St,"interruptNode");async function Ln(e,t="stop"){const a=t==="stop"?(await(await D()).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(a.map(n=>St(n))),await C(await v(e.node_id)??e)}u(Ln,"interruptRun");async function Cn(e,t={}){const a=(await(await D()).prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(r=>r.node_id);ue({run:e.node_id});const n=[];if(await T(e)!=="settled")n.push(...(await ae(e.node_id,{preserveEmpty:!0,stopReason:"run_canceled"})).closed);else for(const r of a){if(r===e.node_id)continue;const i=await v(r);i&&i.status!=="done"&&i.status!=="canceled"&&i.status!=="dead"&&n.push(...(await ae(r,{preserveEmpty:!0,stopReason:"run_canceled"})).closed)}if(await re({run_id:e.node_id},"the run was canceled"),(await Promise.all([...new Set([e.node_id,...n])].map(r=>K(r,"run_canceled")))).some(r=>!r.confirmed))throw new S(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const m=await v(e.node_id);return await C(m??e)}u(Cn,"cancelRun");const ye=200;async function kn(e,t){if(typeof t!="string"||!t.trim())throw h("name is required","name");const a=t.trim();if(a.length>ye)throw h(`name exceeds ${ye} characters`,"name");const n=await qe(e.node_id,{name:a});return n.window&&Ue(n.window,He(n)),await C(n)}u(kn,"renameRun");async function xn(e,t={config:gt,client:wt}){await re({run_id:e.node_id},"the run was deleted");const a=await W(async c=>(await c.prepare("UPDATE nodes SET deleting_at = COALESCE(deleting_at, ?) WHERE node_id = ?").run(new Date().toISOString(),e.node_id),(await c.prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(f=>f.node_id)));if((await Promise.all(a.map(c=>K(c,"run_deleted",{deleting:!0})))).some(c=>!c.confirmed))throw new S(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const o=await L(a,async c=>{const f=await We(c);if(f.app===null)throw new Error(`run node missing during deletion: ${c}`);return f}),m=await(await D()).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:c}of m)try{await Z().delete(c)}catch(f){if(!Pe(f))throw f}const r=await W(async c=>{for(const w of a){const d=await xe(c,w);d!==null&&d.deleted_at===null&&await ke(c,d)}const f=await yt([e.node_id],c);await c.prepare("DELETE FROM run_events WHERE run_id = ?").run(e.node_id),await c.prepare("DELETE FROM idempotency_keys WHERE run_id = ?").run(e.node_id);const y=a.map(()=>"?").join(","),g=await c.prepareUncached(`SELECT message_id FROM messages WHERE sender_node_id IN (${y}) UNION SELECT message_id FROM deliveries WHERE destination_id IN (${y})`).all(...a,...a);await c.prepareUncached(`DELETE FROM deliveries WHERE destination_id IN (${y})`).run(...a);for(const{message_id:w}of g)await c.prepare("DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)").run(w,w);return f});for(const c of o)await Fe(c);const{notifyRunDeleted:i}=await import("./events.js");return i(e.node_id),{uploads_pending:await Nt(r,t)}}u(xn,"deleteRun");async function Nt(e,t){if(!e.length||!t.config())return e.length;let a;try{a=t.client()}catch{return e.length}const n=new Set,o=e.map(r=>a.deleteUpload(r).then(async()=>{await Et(r),n.add(r)},()=>{}));let m;return await Promise.race([Promise.all(o),new Promise(r=>{m=setTimeout(r,t.budgetMs??ht),m.unref?.()})]),clearTimeout(m),e.length-n.size}u(Nt,"deleteReleasedUploads");async function Wn(e,t,a){await F(e,t),await Q(e);const n=await W(async d=>{const s=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),l=new Map;for(const k of s)l.set(k.node_id,(await d.prepare("SELECT session_id FROM sessions WHERE node_id = ? GROUP BY session_id ORDER BY min(created_at)").all(k.node_id)).map(x=>x.session_id));const N=(await d.prepare("SELECT event_cursor FROM nodes WHERE node_id = ?").get(e)).event_cursor-1,R=await d.prepare(`SELECT node_id, sequence_number FROM run_events
10
+ ORDER BY activity DESC, node_id DESC`).all(...e===null?[]:[e]),d=await me(await k((await me(n,async({node_id:r})=>!t.visible||await t.visible(r))).filter(({activity:r,node_id:c})=>!s||r<s.activity||r===s.activity&&c<s.id),async r=>({root:await O(r.node_id),activity:r.activity})),async({root:r})=>!t.status||await C(r)===t.status),l=d.slice(0,t.limit),i=l.at(-1);return{runs:await k(l,async({root:r})=>await x(r)),next:d.length>t.limit&&i?Buffer.from(JSON.stringify({activity:i.activity,id:i.root.node_id})).toString("base64url"):null}}u(In,"listRuns");async function An(e,t,s){const n=await F(e,t),d=u(async()=>await x(await F(e,t)),"read");return!s||pe.includes(await C(n))?await d():new Promise((l,i)=>{let r=u(()=>{},"unsubscribe");const c=u(()=>{clearTimeout(o),clearInterval(g),r()},"settle"),m=u(async()=>{c();try{l(await d())}catch(_){i(_)}},"finish"),h=u(async()=>{pe.includes(String((await d()).status))&&await m()},"check"),E=u(()=>{h().catch(_=>{c(),i(_)})},"run"),g=setInterval(E,250),o=setTimeout(()=>{m()},s*1e3);mt(e,E).then(_=>{r=_},_=>{c(),i(_)})})}u(An,"waitRun");async function Tn(e,t,s=le,n=!0,d){const l=e.status==="canceled"||e.outcome_reason==="closed",i=e.grantee??"app:terminal",r=G("sha256").update(JSON.stringify(["run.message",e.node_id,t,n])).digest("hex"),c=u(async g=>{const o=await O(e.node_id),_=await(await I()).prepare("SELECT 1 FROM deliveries WHERE message_id = ? AND state = 'pending' AND canceled_at IS NULL").get(String(g.message_id));return o&&!l&&n&&!o.pi_pid&&_&&await P(e.node_id,{resume:!0,capacity:"freeze"}),g},"replay");if(d){const g=await q(i,d,r);if(g)return c(g.response)}if(l)throw new N(409,"run_settled","canceled run cannot receive a message");const m=await s(e.node_id,i,t),h=n&&e.final_report&&!e.pi_pid?(await import("../runtime/reopen.js")).commitReopenResident:void 0;let E;try{E=await W(async g=>{if(d){const y=await q(i,d,r,g);if(y)return{replayed:y.response}}await h?.(e.node_id);const o=await we(g,e.node_id,i,m,n),_={run_id:e.node_id,message_id:o.messageId,sequence_number:o.sequence};return d&&await fe(g,i,d,r,e.node_id,_,new Date().toISOString()),{result:_}})}catch(g){throw m.cleanup(),g}return"replayed"in E?(m.cleanup(),c(E.replayed)):(n&&!e.pi_pid&&await P(e.node_id,{resume:!0,capacity:"freeze"}),E.result)}u(Tn,"messageRun");async function St(e){const t=u(()=>new N(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 J();if(!ee(n)){if(n.streaming)throw t();return}const d=(await V(e))?.executionId;try{await ze(e)==="turn"&&ue({nodes:[e]});return}catch(l){if(!(l instanceof Ge))throw l;const i=await O(e);if(!i)throw J();if(!i.streaming)return;if(s===0&&ee(i)&&(await V(e))?.executionId!==d)continue;throw t()}}throw t()}u(St,"interruptNode");async function Ln(e,t="stop"){const s=t==="stop"?(await(await I()).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=>St(n))),await x(await O(e.node_id)??e)}u(Ln,"interruptRun");async function Cn(e,t={}){const s=(await(await I()).prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(i=>i.node_id);ue({run:e.node_id});const n=[];if(await C(e)!=="settled")n.push(...(await ae(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 ae(i,{preserveEmpty:!0,stopReason:"run_canceled"})).closed)}if(await re({run_id:e.node_id},"the run was canceled"),(await Promise.all([...new Set([e.node_id,...n])].map(i=>K(i,"run_canceled")))).some(i=>!i.confirmed))throw new N(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const l=await O(e.node_id);return await x(l??e)}u(Cn,"cancelRun");const ye=200;async function kn(e,t){if(typeof t!="string"||!t.trim())throw S("name is required","name");const s=t.trim();if(s.length>ye)throw S(`name exceeds ${ye} characters`,"name");const n=await qe(e.node_id,{name:s});return n.window&&Ue(n.window,He(n)),await x(n)}u(kn,"renameRun");async function xn(e,t={config:gt,client:wt}){await re({run_id:e.node_id},"the run was deleted");const s=await W(async c=>(await c.prepare("UPDATE nodes SET deleting_at = COALESCE(deleting_at, ?) WHERE node_id = ?").run(new Date().toISOString(),e.node_id),(await c.prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(m=>m.node_id)));if((await Promise.all(s.map(c=>K(c,"run_deleted",{deleting:!0})))).some(c=>!c.confirmed))throw new N(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const d=await k(s,async c=>{const m=await We(c);if(m.app===null)throw new Error(`run node missing during deletion: ${c}`);return m}),l=await(await I()).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:c}of l)try{await Z().delete(c)}catch(m){if(!Be(m))throw m}const i=await W(async c=>{for(const g of s){const o=await xe(c,g);o!==null&&o.deleted_at===null&&await ke(c,o)}const m=await yt([e.node_id],c);await c.prepare("DELETE FROM run_events WHERE run_id = ?").run(e.node_id),await c.prepare("DELETE FROM idempotency_keys WHERE run_id = ?").run(e.node_id);const h=s.map(()=>"?").join(","),E=await c.prepareUncached(`SELECT message_id FROM messages WHERE sender_node_id IN (${h}) UNION SELECT message_id FROM deliveries WHERE destination_id IN (${h})`).all(...s,...s);await c.prepareUncached(`DELETE FROM deliveries WHERE destination_id IN (${h})`).run(...s);for(const{message_id:g}of E)await c.prepare("DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)").run(g,g);return m});for(const c of d)await Fe(c);const{notifyRunDeleted:r}=await import("./events.js");return r(e.node_id),{uploads_pending:await Nt(i,t)}}u(xn,"deleteRun");async function Nt(e,t){if(!e.length||!t.config())return e.length;let s;try{s=t.client()}catch{return e.length}const n=new Set,d=e.map(i=>s.deleteUpload(i).then(async()=>{await Et(i),n.add(i)},()=>{}));let l;return await Promise.race([Promise.all(d),new Promise(i=>{l=setTimeout(i,t.budgetMs??ht),l.unref?.()})]),clearTimeout(l),e.length-n.size}u(Nt,"deleteReleasedUploads");async function Wn(e,t,s){await F(e,t),await Q(e);const n=await W(async o=>{const _=await o.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),y=new Map;for(const R of _)y.set(R.node_id,(await o.prepare("SELECT session_id FROM sessions WHERE node_id = ? GROUP BY session_id ORDER BY min(created_at)").all(R.node_id)).map(A=>A.session_id));const p=(await o.prepare("SELECT event_cursor FROM nodes WHERE node_id = ?").get(e)).event_cursor-1,D=await o.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
- ORDER BY sequence_number`).all(e,N),M=await d.prepare(`SELECT node_id, sequence_number, type, body_json FROM run_events
12
+ ORDER BY sequence_number`).all(e,p),v=await o.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,N);return{nodes:s,sessionIds:l,latestSequence:N,completed:R,deltas:M}}),{nodes:o,sessionIds:m,latestSequence:r,completed:i,deltas:c}=n,f=await L(o,async d=>({node_id:d.node_id,parent_node_id:d.parent,conversations:await L(m.get(d.node_id)??[],async s=>{const{header:l,entries:E}=await Z().read(s);if(a==="entries")return{conversation_id:s,header:l,entries:E};const N=Ce.inMemory(l.cwd,void 0,[l,...E]),R=it(N)??[],M=new Map(E.map((_,O)=>[_.id,O])),k=E.filter(_=>_.type==="custom"&&_.customType==="crtr-system-prompt").map(_=>({id:_.id,message:{role:"custom",customType:"crtr-system-prompt",data:"data"in _?_.data:void 0,timestamp:_.timestamp}})),x=E.filter(_=>_.type==="custom_message"&&_.customType==="app_message").map(_=>({id:_.id,message:{role:"custom",customType:"app_message",content:"content"in _?_.content:"",timestamp:_.timestamp}})),he=d.node_id===e?E.find(_=>{if(_.type!=="message"||_.message.role!=="user")return!1;const O=te(E,_.message.timestamp);return O?.type==="runtime"&&O.kind==="kickoff"})?.id:void 0,Re=[...R.filter(({id:_})=>!x.some(O=>O.id===_)),...k,...x].sort((_,O)=>(M.get(_.id)??Number.MAX_SAFE_INTEGER)-(M.get(O.id)??Number.MAX_SAFE_INTEGER)).map(({id:_,message:O})=>{const p=O,I=p.usage,H=p.role==="user"?te(E,Number(p.timestamp)):null,Se=H?.type==="human"||_===he,A=p.role==="toolResult"?"tool_result":p.role==="bashExecution"?"bash_execution":p.role==="compactionSummary"?"compaction_summary":p.role==="branchSummary"?"branch_summary":p.role==="custom"&&p.customType==="crtr-system-prompt"?"system":p.role==="user"?Se?"user":"custom":p.role,Ne=A==="custom"?p.role==="custom"?p.customType:H?.type==="runtime"?H.kind:"unknown":void 0,ve=A==="system"&&p.customType==="crtr-system-prompt"?[{type:"text",text:p.data?.text??""}]:typeof p.content=="string"?[{type:"text",text:p.content}]:Array.isArray(p.content)?p.content.map(b=>b.type==="toolCall"?{type:"tool_call",tool_call_id:b.id,name:b.name,arguments:b.arguments}:b.type==="image"?{type:"image",mime_type:b.mimeType}:b.type==="thinking"?{type:"thinking",text:b.thinking}:b):[];return{entry_id:_,role:A,...A==="custom"?{custom_type:Ne}:{},time:typeof p.timestamp=="string"?p.timestamp:new Date(Number(p.timestamp??Date.now())).toISOString(),content:ve,...A==="assistant"?{model:p.model,provider:p.provider,stop_reason:p.stopReason,...p.errorMessage?{error_message:p.errorMessage}:{},...I?{usage:{input_tokens:I.input??0,output_tokens:I.output??0,cache_read_tokens:I.cacheRead??0,cache_write_tokens:I.cacheWrite??0,cost_usd:I.cost?.total??0}}:{}}:{},...A==="tool_result"?{tool_call_id:p.toolCallId,tool_name:p.toolName,is_error:p.isError}:{}}})??[];return{conversation_id:s,messages:Re}})})),y=new Map(f.map(d=>[d.node_id,ct(d.node_id)]));for(const d of i){const s=y.get(d.node_id);s!=null&&d.sequence_number>=s&&y.set(d.node_id,null)}const g=new Map;for(const d of c){const s=y.get(d.node_id);if(s==null||d.sequence_number<s)continue;const l=JSON.parse(d.body_json),E=g.get(d.node_id)??{thinking:"",text:""};d.type==="node.thinking.delta"?E.thinking+=l.delta:E.text+=l.delta,g.set(d.node_id,E)}const w=f.map(d=>({...d,in_progress_message:y.get(d.node_id)==null?null:g.get(d.node_id)??{thinking:"",text:""}}));return{run_id:e,latest_sequence:r,nodes:w}}u(Wn,"traceRun");function Fn(e,t,a){if(t===void 0){if(!e.some(n=>U(n,"crtr:llm")))throw new S(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 h("scopes must be a list of scope strings","scopes");for(const n of t){try{ut(n)}catch{throw h(`invalid scope ${n}`,"scopes")}if(/^crtr:files:(?:read|rw):app:/.test(n)&&n.split(":")[4]===a.slice(4))throw h(`own-app files cannot narrow a run: ${n}`,"scopes");if(!(/^crtr:memory:(?:read|rw):app:/.test(n)&&n.split(":")[4]===a.slice(4))&&!be(e,n))throw new S(403,"scope_missing",`missing scope ${n}`,void 0,void 0,n)}if(!t.includes("crtr:llm"))throw new S(403,"scope_missing","missing scope crtr:llm",void 0,void 0,"crtr:llm");return t}u(Fn,"requestedScopes");export{X as IDEMPOTENCY_WINDOW_MS,Rt as RUN_DEADLINE_MAX_MS,ht as RUN_DELETE_STORAGE_BUDGET_MS,ye as RUN_NAME_MAX,S as RunError,Cn as cancelRun,xn as deleteRun,bn as idempotencyKeyOf,Ln as interruptRun,In as listRuns,Tn as messageRun,F as ownedRun,Ee as parseRunDeadlineMs,Dn as pruneExpiredIdempotencyKeys,kn as renameRun,Fn as requestedScopes,On as runIsRunning,C as runObject,Mn as startRun,Wn as traceRun,An as waitRun};
14
+ ORDER BY sequence_number`).all(e,p);return{nodes:_,sessionIds:y,latestSequence:p,completed:D,deltas:v}}),{nodes:d,sessionIds:l,latestSequence:i,completed:r,deltas:c}=n,m=await k(d,async o=>({node_id:o.node_id,parent_node_id:o.parent,conversations:await k(l.get(o.node_id)??[],async _=>{const{header:y,entries:a}=await Z().read(_);if(s==="entries")return{conversation_id:_,header:y,entries:a};const p=Ce.inMemory(y.cwd,void 0,[y,...a]),D=it(p)??[],v=new Map(a.map((w,b)=>[w.id,b])),R=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}})),A=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}})),he=o.node_id===e?a.find(w=>{if(w.type!=="message"||w.message.role!=="user")return!1;const b=te(a,w.message.timestamp);return b?.type==="runtime"&&b.kind==="kickoff"})?.id:void 0,Re=[...D.filter(({id:w})=>!A.some(b=>b.id===w)),...R,...A].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,H=f.role==="user"?te(a,Number(f.timestamp)):null,Se=H?.type==="human"||w===he,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"?Se?"user":"custom":f.role,Ne=L==="custom"?f.role==="custom"?f.customType:H?.type==="runtime"?H.kind:"unknown":void 0,ve=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:Ne}:{},time:typeof f.timestamp=="string"?f.timestamp:new Date(Number(f.timestamp??Date.now())).toISOString(),content:ve,...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:Re}})})),h=new Map(m.map(o=>[o.node_id,ct(o.node_id)]));for(const o of r){const _=h.get(o.node_id);_!=null&&o.sequence_number>=_&&h.set(o.node_id,null)}const E=new Map;for(const o of c){const _=h.get(o.node_id);if(_==null||o.sequence_number<_)continue;const y=JSON.parse(o.body_json),a=E.get(o.node_id)??{thinking:"",text:""};o.type==="node.thinking.delta"?a.thinking+=y.delta:a.text+=y.delta,E.set(o.node_id,a)}const g=m.map(o=>({...o,in_progress_message:h.get(o.node_id)==null?null:E.get(o.node_id)??{thinking:"",text:""}}));return{run_id:e,latest_sequence:i,nodes:g}}u(Wn,"traceRun");function Fn(e,t,s){if(t===void 0){if(!e.some(n=>U(n,"crtr:llm")))throw new N(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 S("scopes must be a list of scope strings","scopes");for(const n of t){try{ut(n)}catch{throw S(`invalid scope ${n}`,"scopes")}if(/^crtr:files:(?:read|rw):app:/.test(n)&&n.split(":")[4]===s.slice(4))throw S(`own-app files cannot narrow a run: ${n}`,"scopes");if(!(/^crtr:memory:(?:read|rw):app:/.test(n)&&n.split(":")[4]===s.slice(4))&&!be(e,n))throw new N(403,"scope_missing",`missing scope ${n}`,void 0,void 0,n)}if(!t.includes("crtr:llm"))throw new N(403,"scope_missing","missing scope crtr:llm",void 0,void 0,"crtr:llm");return t}u(Fn,"requestedScopes");export{X as IDEMPOTENCY_WINDOW_MS,Rt as RUN_DEADLINE_MAX_MS,ht as RUN_DELETE_STORAGE_BUDGET_MS,ye as RUN_NAME_MAX,N as RunError,Cn as cancelRun,xn as deleteRun,bn as idempotencyKeyOf,Ln as interruptRun,In as listRuns,Tn as messageRun,F as ownedRun,Ee as parseRunDeadlineMs,Dn as pruneExpiredIdempotencyKeys,kn as renameRun,Fn as requestedScopes,On as runIsRunning,x as runObject,Mn as startRun,Wn as traceRun,An as waitRun};
@@ -1 +1 @@
1
- var E=Object.defineProperty;var p=(a,n)=>E(a,"name",{value:n,configurable:!0});import{createServer as y,request as u}from"node:http";import{chmodSync as S,existsSync as h,rmSync as w,unlinkSync as f}from"node:fs";import{join as l}from"node:path";import{apiSocketPath as _,BROKER_RELEASED_MARKER as k,BROKER_RELAY_GENERATION as v,nodeRunDir as R}from"../../canvas/paths.js";import{writeFileBeneath as A}from"../../spaces/open-beneath.js";async function I(a,n){const r=l(R(a),"cli.sock"),t=y((o,e)=>{const m={...o.headers,authorization:`Bearer ${n}`};delete m.connection;const i=u({socketPath:_(),path:o.url,method:o.method,headers:m},s=>{e.writeHead(s.statusCode??502,s.headers),s.pipe(e)});i.on("error",s=>{e.headersSent||e.writeHead(503,{"content-type":"application/json"}),e.end(JSON.stringify({error:{code:"daemon_unavailable",message:s.message}}))}),o.pipe(i),e.on("close",()=>i.destroy())});h(r)&&f(r),await new Promise((o,e)=>{t.once("error",e),t.listen(r,()=>{t.off("error",e),o()})}),S(r,384);const c=R(a),d=process.env.CRTR_EXECUTION_ID;if(!d)throw new Error("broker relay has no execution id");return A(c,l(c,v),d,{atomic:!0}),w(l(c,k),{force:!0}),{path:r,close(){t.closeAllConnections(),t.close(),h(r)&&f(r)}}}p(I,"serveCliRelay");export{I as serveCliRelay};
1
+ var R=Object.defineProperty;var p=(n,c)=>R(n,"name",{value:c,configurable:!0});import{createServer as E,request as S}from"node:http";import{chmodSync as w,existsSync as u,rmSync as _,unlinkSync as h}from"node:fs";import{join as m}from"node:path";import{apiSocketPath as B,BROKER_RELEASED_MARKER as C,BROKER_RELAY_GENERATION as k,nodeRunDir as y}from"../../canvas/paths.js";import{writeFileBeneath as v}from"../../spaces/open-beneath.js";import{currentCausedBy as A}from"./turn-cause.js";async function P(n,c){const r=m(y(n),"cli.sock"),o=E((t,e)=>{const a={...t.headers,authorization:`Bearer ${c}`},l=A();l!==void 0&&a["crtr-caused-by"]===void 0&&(a["crtr-caused-by"]=l),delete a.connection;const d=S({socketPath:B(),path:t.url,method:t.method,headers:a},s=>{e.writeHead(s.statusCode??502,s.headers),s.pipe(e)});d.on("error",s=>{e.headersSent||e.writeHead(503,{"content-type":"application/json"}),e.end(JSON.stringify({error:{code:"daemon_unavailable",message:s.message}}))}),t.pipe(d),e.on("close",()=>d.destroy())});u(r)&&h(r),await new Promise((t,e)=>{o.once("error",e),o.listen(r,()=>{o.off("error",e),t()})}),w(r,384);const i=y(n),f=process.env.CRTR_EXECUTION_ID;if(!f)throw new Error("broker relay has no execution id");return v(i,m(i,k),f,{atomic:!0}),_(m(i,C),{force:!0}),{path:r,close(){o.closeAllConnections(),o.close(),u(r)&&h(r)}}}p(P,"serveCliRelay");export{P as serveCliRelay};
@@ -1,2 +1,2 @@
1
- var W=Object.defineProperty;var d=(e,t)=>W(e,"name",{value:t,configurable:!0});import{setTimeout as j}from"node:timers/promises";import{createAssistantMessageEventStream as J,getCurrentSystemPrompt as Y,getCurrentTools as z}from"@earendil-works/pi-ai";import{socketFetch as X}from"../../../api/node-transport.js";import{apiSocketPath as G}from"../../canvas/paths.js";import{currentNodeToken as H}from"./node-token.js";import{envModelExact as C,envModelIntent as K}from"../../../shared/env.js";import{MODEL_CONTEXT_BODY_MAX_BYTES as E}from"../../llm/body-limits.js";import{modelRequestFromConfig as V}from"../../model-routes.js";import{parseProviderRateLimit as Q,providerFailureDiagnostic as b}from"../../provider-failure.js";import{UPSTREAM_MODEL_UNAVAILABLE as R}from"../../fault-classifier.js";function me(e,t){e.checkAuth=async n=>e.getProvider(n)?{type:"api_key"}:void 0,e.getAvailable=async n=>e.getModels(n),e.getAvailableSnapshot=()=>e.getModels(),e.streamSimple=(n,c,r)=>ne(n,c,r,t)}d(me,"configureBrokerModelRuntime");const Z=300,N="crtr:llm-refusal";class k extends Error{static{d(this,"LlmRefusalError")}retryAt;rateLimit;code;status;constructor(t,n,c,r,o){super(t),this.retryAt=n,this.rateLimit=c,this.code=r,this.status=o}}class S extends Error{static{d(this,"UpstreamModelUnavailableError")}}function D(e,t){const n=e===void 0?"the request body":`the request body (${e} bytes)`;return new Error(`request_too_large: ${n} exceeds the ${t}-byte model request limit; compact the conversation to shrink the context`)}d(D,"contextTooLargeError");function A(e){const t=e.details?.rate_limit;if(!t||typeof t!="object")return;const n=Q(t);if(n===void 0)return;const{provider:c,model:r}=t;return typeof c=="string"&&c!==""&&typeof r=="string"&&r!==""?{...n,model:`${c}/${r}`}:n}d(A,"refusalRateLimit");function he(e){for(const t of e.diagnostics??[]){if(t.type!==N)continue;const n=t.details?.retryAt;if(typeof n=="number"&&Number.isFinite(n)&&n>0)return n}}d(he,"refusalRetryAt");class q extends Error{static{d(this,"ContentFilteredError")}}function B(e){return typeof e=="string"?e:e.map(t=>t.type==="text"?{type:"text",text:t.text}:{type:"image_url",image_url:{url:`data:${t.mimeType};base64,${t.data}`}})}d(B,"wireContent");function ee(e){const t=d(r=>r.role==="assistant"&&(r.stopReason==="error"||r.stopReason==="aborted"),"incomplete"),n=e.some(t)?e.filter(r=>!t(r)):e;let c=n.length;for(;c>0&&n[c-1]?.role==="assistant";)c--;return c===n.length?n:n.slice(0,c)}d(ee,"wireHistory");function te(e,t,n,c){const r=[],o=Y(t.messages),a=z(t.messages);o?r.push({role:"system",content:o}):t.systemPrompt&&r.push({role:"system",content:t.systemPrompt});for(const p of ee(t.messages))p.role==="user"?r.push({role:"user",content:B(p.content)}):p.role==="toolResult"?r.push({role:"tool",content:B(p.content),tool_call_id:p.toolCallId}):p.role==="assistant"&&r.push({role:"assistant",content:p.content.filter(u=>u.type==="text").map(u=>u.text).join("")||null,tool_calls:p.content.filter(u=>u.type==="toolCall").map(u=>({id:u.id,type:"function",function:{name:u.name,arguments:JSON.stringify(u.arguments)}}))});const x=`${e.provider}/${e.id}`,_=c??K();return{model:V(x,_,C())?.kind==="logical"?_:x,model_policy:C()?"exact":"substitute",stream:!0,messages:r,...a.length?{tools:a.map(p=>({type:"function",function:{name:p.name,description:p.description,parameters:p.parameters}}))}:{},...n.reasoning?{reasoning_effort:n.reasoning}:{},...n.temperature!==void 0?{temperature:n.temperature}:{},...n.maxTokens!==void 0?{max_tokens:n.maxTokens}:{}}}d(te,"requestBody");function L(e,t){if(typeof t!="string")return!1;const n=t.indexOf("/");return n<1||n===t.length-1?!1:(e.provider=t.slice(0,n),e.model=t.slice(n+1),!0)}d(L,"applyServedModel");function F(e){if(e.details?.served_model!==void 0)return e.details.served_model;const t=e.details?.rate_limit;return typeof t?.provider=="string"&&typeof t.model=="string"?`${t.provider}/${t.model}`:void 0}d(F,"refusalRoute");function P(e){if(!e||typeof e!="object"||!("error"in e))throw new Error("llm returned an invalid response");const t=e.error;if(!t||typeof t.message!="string")throw new Error("llm returned an invalid refusal");return t}d(P,"parseRefusal");function ne(e,t,n={},c){const r=J(),o={role:"assistant",content:[],api:e.api,provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"pending",timestamp:Date.now()};return(async()=>{const a=H();if(!a)throw new Error("llm requires a node token");const x=JSON.stringify(te(e,t,n,c)),_=Buffer.byteLength(x);if(_>E)throw D(_,E);let p=0;for(;;){n.signal?.throwIfAborted();const u=await X(G())("http://localhost/v1/llm",{method:"POST",headers:{authorization:`Bearer ${a}`,"content-type":"application/json"},body:x,signal:n.signal});if(!u.ok){const l=P(await u.json());if(u.status===413||l.code==="payload_too_large")throw D(_,E);if(L(o,F(l)),l.retryable!==!0)throw new k(l.message,void 0,A(l),l.code,u.status);const s=l.retry_after_s;if(typeof s!="number"||!Number.isFinite(s)||s<=0)throw l.code===R?new S(l.message):new Error(l.message);const m=Z-p;if(s>m){const f=Date.now()+s*1e3;throw new k(`${l.message} (retry after ${s}s, at ${new Date(f).toISOString()})`,f,A(l))}await j(s*1e3,void 0,{signal:n.signal}),p+=s;continue}if(!u.body)throw new Error("llm returned no stream");r.push({type:"start",partial:o});const U=u.body.getReader(),I=new TextDecoder;let g="",w="stop",M,T=!1,O=!1;const $=d(l=>{const s=JSON.parse(l);if(s.error){const i=P(s);throw L(o,F(i)),i.retryable!==!0?new k(i.message,void 0,A(i),i.code):i.code===R?new S(i.message):new Error(i.message)}if(s.served_model){if(O=!0,s.served_model.indexOf("/")<1)throw new Error("llm returned an invalid served_model");L(o,s.served_model)}const m=s.choices?.[0],f=m?.delta;if(f?.reasoning_content){const i=o.content.findIndex(v=>v.type==="thinking"),h=i<0?{type:"thinking",thinking:""}:o.content[i],y=i<0?o.content.push(h)-1:i;if(i<0&&r.push({type:"thinking_start",contentIndex:y,partial:o}),h.type!=="thinking")throw new Error("invalid thinking block");h.thinking+=f.reasoning_content,r.push({type:"thinking_delta",contentIndex:y,delta:f.reasoning_content,partial:o})}if(f?.content){const i=o.content.findIndex(v=>v.type==="text"),h=i<0?{type:"text",text:""}:o.content[i],y=i<0?o.content.push(h)-1:i;if(i<0&&r.push({type:"text_start",contentIndex:y,partial:o}),h.type!=="text")throw new Error("invalid text block");h.text+=f.content,r.push({type:"text_delta",contentIndex:y,delta:f.content,partial:o})}for(const i of f?.tool_calls??[]){const h={type:"toolCall",id:i.id,name:i.function.name,arguments:JSON.parse(i.function.arguments)},y=o.content.push(h)-1;r.push({type:"toolcall_start",contentIndex:y,partial:o}),r.push({type:"toolcall_end",contentIndex:y,toolCall:h,partial:o})}m?.finish_reason&&(w=m.finish_reason),m?.message?.refusal&&(M=m.message.refusal),s.usage&&(T=!0,o.usage={input:s.usage.prompt_tokens,output:s.usage.completion_tokens,cacheRead:s.usage.cache_read_tokens,cacheWrite:s.usage.cache_write_tokens,totalTokens:s.usage.total_tokens,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:typeof s.usage.usd_equivalent=="number"&&Number.isFinite(s.usage.usd_equivalent)?s.usage.usd_equivalent:0}})},"apply");for(;;){const{value:l,done:s}=await U.read();if(s)break;g+=I.decode(l,{stream:!0});let m;for(;(m=g.indexOf(`
2
- `))>=0;){const f=g.slice(0,m).trim();g=g.slice(m+1),f&&$(f)}}if(g+=I.decode(),g.trim()&&$(g.trim()),!T||!O)throw new Error("llm stream ended without usage or served_model");for(const[l,s]of o.content.entries())s.type==="text"&&r.push({type:"text_end",contentIndex:l,content:s.text,partial:o}),s.type==="thinking"&&r.push({type:"thinking_end",contentIndex:l,content:s.thinking,partial:o});if(w==="content_filter")throw new q(M??"Content filtered");if(!["stop","tool_calls","length"].includes(w))throw new Error(`llm returned unknown finish reason: ${w}`);o.stopReason=w==="tool_calls"?"toolUse":w==="length"?"length":"stop",r.push({type:"done",reason:o.stopReason,message:o}),r.end();return}})().catch(a=>{o.stopReason=n.signal?.aborted?"aborted":"error",o.errorMessage=a instanceof Error?a.message:String(a),a instanceof k&&(o.diagnostics=[{type:N,timestamp:Date.now(),...a.retryAt!==void 0?{details:{retryAt:a.retryAt}}:{}},...a.rateLimit!==void 0?[b({status:429,ratelimit:a.rateLimit})]:[],...a.rateLimit===void 0&&a.code==="cap_exhausted"?[b({status:a.status??402,code:a.code})]:[]]),a instanceof S&&(o.diagnostics=[b({status:503,code:R})]),a instanceof q&&o.stopReason==="error"&&(o.rawStopReason="content_filter"),r.push({type:"error",reason:o.stopReason,error:o}),r.end()}),r}d(ne,"streamBrokerModel");export{Z as LLM_BROKER_RETRY_WINDOW_S,N as LLM_REFUSAL_DIAGNOSTIC,me as configureBrokerModelRuntime,he as refusalRetryAt,te as requestBody,ne as streamBrokerModel,ee as wireHistory};
1
+ var W=Object.defineProperty;var c=(e,t)=>W(e,"name",{value:t,configurable:!0});import{setTimeout as j}from"node:timers/promises";import{createAssistantMessageEventStream as J,getCurrentSystemPrompt as Y,getCurrentTools as z}from"@earendil-works/pi-ai";import{socketFetch as H}from"../../../api/node-transport.js";import{apiSocketPath as X}from"../../canvas/paths.js";import{currentNodeToken as G}from"./node-token.js";import{currentCausedBy as K}from"./turn-cause.js";import{envModelExact as C,envModelIntent as V}from"../../../shared/env.js";import{MODEL_CONTEXT_BODY_MAX_BYTES as b}from"../../llm/body-limits.js";import{modelRequestFromConfig as Q}from"../../model-routes.js";import{parseProviderRateLimit as Z,providerFailureDiagnostic as E}from"../../provider-failure.js";import{UPSTREAM_MODEL_UNAVAILABLE as R}from"../../fault-classifier.js";function ye(e,t){e.checkAuth=async n=>e.getProvider(n)?{type:"api_key"}:void 0,e.getAvailable=async n=>e.getModels(n),e.getAvailableSnapshot=()=>e.getModels(),e.streamSimple=(n,d,r)=>re(n,d,r,t)}c(ye,"configureBrokerModelRuntime");const ee=300,B="crtr:llm-refusal";class k extends Error{static{c(this,"LlmRefusalError")}retryAt;rateLimit;code;status;constructor(t,n,d,r,o){super(t),this.retryAt=n,this.rateLimit=d,this.code=r,this.status=o}}class S extends Error{static{c(this,"UpstreamModelUnavailableError")}}function N(e,t){const n=e===void 0?"the request body":`the request body (${e} bytes)`;return new Error(`request_too_large: ${n} exceeds the ${t}-byte model request limit; compact the conversation to shrink the context`)}c(N,"contextTooLargeError");function A(e){const t=e.details?.rate_limit;if(!t||typeof t!="object")return;const n=Z(t);if(n===void 0)return;const{provider:d,model:r}=t;return typeof d=="string"&&d!==""&&typeof r=="string"&&r!==""?{...n,model:`${d}/${r}`}:n}c(A,"refusalRateLimit");function _e(e){for(const t of e.diagnostics??[]){if(t.type!==B)continue;const n=t.details?.retryAt;if(typeof n=="number"&&Number.isFinite(n)&&n>0)return n}}c(_e,"refusalRetryAt");class D extends Error{static{c(this,"ContentFilteredError")}}function q(e){return typeof e=="string"?e:e.map(t=>t.type==="text"?{type:"text",text:t.text}:{type:"image_url",image_url:{url:`data:${t.mimeType};base64,${t.data}`}})}c(q,"wireContent");function te(e){const t=c(r=>r.role==="assistant"&&(r.stopReason==="error"||r.stopReason==="aborted"),"incomplete"),n=e.some(t)?e.filter(r=>!t(r)):e;let d=n.length;for(;d>0&&n[d-1]?.role==="assistant";)d--;return d===n.length?n:n.slice(0,d)}c(te,"wireHistory");function ne(e,t,n,d){const r=[],o=Y(t.messages),a=z(t.messages);o?r.push({role:"system",content:o}):t.systemPrompt&&r.push({role:"system",content:t.systemPrompt});for(const p of te(t.messages))p.role==="user"?r.push({role:"user",content:q(p.content)}):p.role==="toolResult"?r.push({role:"tool",content:q(p.content),tool_call_id:p.toolCallId}):p.role==="assistant"&&r.push({role:"assistant",content:p.content.filter(u=>u.type==="text").map(u=>u.text).join("")||null,tool_calls:p.content.filter(u=>u.type==="toolCall").map(u=>({id:u.id,type:"function",function:{name:u.name,arguments:JSON.stringify(u.arguments)}}))});const x=`${e.provider}/${e.id}`,_=d??V();return{model:Q(x,_,C())?.kind==="logical"?_:x,model_policy:C()?"exact":"substitute",stream:!0,messages:r,...a.length?{tools:a.map(p=>({type:"function",function:{name:p.name,description:p.description,parameters:p.parameters}}))}:{},...n.reasoning?{reasoning_effort:n.reasoning}:{},...n.temperature!==void 0?{temperature:n.temperature}:{},...n.maxTokens!==void 0?{max_tokens:n.maxTokens}:{}}}c(ne,"requestBody");function L(e,t){if(typeof t!="string")return!1;const n=t.indexOf("/");return n<1||n===t.length-1?!1:(e.provider=t.slice(0,n),e.model=t.slice(n+1),!0)}c(L,"applyServedModel");function F(e){if(e.details?.served_model!==void 0)return e.details.served_model;const t=e.details?.rate_limit;return typeof t?.provider=="string"&&typeof t.model=="string"?`${t.provider}/${t.model}`:void 0}c(F,"refusalRoute");function P(e){if(!e||typeof e!="object"||!("error"in e))throw new Error("llm returned an invalid response");const t=e.error;if(!t||typeof t.message!="string")throw new Error("llm returned an invalid refusal");return t}c(P,"parseRefusal");function oe(){const e=K();return e===void 0?{}:{"crtr-caused-by":e}}c(oe,"causedByHeader");function re(e,t,n={},d){const r=J(),o={role:"assistant",content:[],api:e.api,provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"pending",timestamp:Date.now()};return(async()=>{const a=G();if(!a)throw new Error("llm requires a node token");const x=JSON.stringify(ne(e,t,n,d)),_=Buffer.byteLength(x);if(_>b)throw N(_,b);let p=0;for(;;){n.signal?.throwIfAborted();const u=await H(X())("http://localhost/v1/llm",{method:"POST",headers:{authorization:`Bearer ${a}`,"content-type":"application/json",...oe()},body:x,signal:n.signal});if(!u.ok){const l=P(await u.json());if(u.status===413||l.code==="payload_too_large")throw N(_,b);if(L(o,F(l)),l.retryable!==!0)throw new k(l.message,void 0,A(l),l.code,u.status);const s=l.retry_after_s;if(typeof s!="number"||!Number.isFinite(s)||s<=0)throw l.code===R?new S(l.message):new Error(l.message);const m=ee-p;if(s>m){const f=Date.now()+s*1e3;throw new k(`${l.message} (retry after ${s}s, at ${new Date(f).toISOString()})`,f,A(l))}await j(s*1e3,void 0,{signal:n.signal}),p+=s;continue}if(!u.body)throw new Error("llm returned no stream");r.push({type:"start",partial:o});const U=u.body.getReader(),I=new TextDecoder;let g="",w="stop",M,T=!1,O=!1;const $=c(l=>{const s=JSON.parse(l);if(s.error){const i=P(s);throw L(o,F(i)),i.retryable!==!0?new k(i.message,void 0,A(i),i.code):i.code===R?new S(i.message):new Error(i.message)}if(s.served_model){if(O=!0,s.served_model.indexOf("/")<1)throw new Error("llm returned an invalid served_model");L(o,s.served_model)}const m=s.choices?.[0],f=m?.delta;if(f?.reasoning_content){const i=o.content.findIndex(v=>v.type==="thinking"),h=i<0?{type:"thinking",thinking:""}:o.content[i],y=i<0?o.content.push(h)-1:i;if(i<0&&r.push({type:"thinking_start",contentIndex:y,partial:o}),h.type!=="thinking")throw new Error("invalid thinking block");h.thinking+=f.reasoning_content,r.push({type:"thinking_delta",contentIndex:y,delta:f.reasoning_content,partial:o})}if(f?.content){const i=o.content.findIndex(v=>v.type==="text"),h=i<0?{type:"text",text:""}:o.content[i],y=i<0?o.content.push(h)-1:i;if(i<0&&r.push({type:"text_start",contentIndex:y,partial:o}),h.type!=="text")throw new Error("invalid text block");h.text+=f.content,r.push({type:"text_delta",contentIndex:y,delta:f.content,partial:o})}for(const i of f?.tool_calls??[]){const h={type:"toolCall",id:i.id,name:i.function.name,arguments:JSON.parse(i.function.arguments)},y=o.content.push(h)-1;r.push({type:"toolcall_start",contentIndex:y,partial:o}),r.push({type:"toolcall_end",contentIndex:y,toolCall:h,partial:o})}m?.finish_reason&&(w=m.finish_reason),m?.message?.refusal&&(M=m.message.refusal),s.usage&&(T=!0,o.usage={input:s.usage.prompt_tokens,output:s.usage.completion_tokens,cacheRead:s.usage.cache_read_tokens,cacheWrite:s.usage.cache_write_tokens,totalTokens:s.usage.total_tokens,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:typeof s.usage.usd_equivalent=="number"&&Number.isFinite(s.usage.usd_equivalent)?s.usage.usd_equivalent:0}})},"apply");for(;;){const{value:l,done:s}=await U.read();if(s)break;g+=I.decode(l,{stream:!0});let m;for(;(m=g.indexOf(`
2
+ `))>=0;){const f=g.slice(0,m).trim();g=g.slice(m+1),f&&$(f)}}if(g+=I.decode(),g.trim()&&$(g.trim()),!T||!O)throw new Error("llm stream ended without usage or served_model");for(const[l,s]of o.content.entries())s.type==="text"&&r.push({type:"text_end",contentIndex:l,content:s.text,partial:o}),s.type==="thinking"&&r.push({type:"thinking_end",contentIndex:l,content:s.thinking,partial:o});if(w==="content_filter")throw new D(M??"Content filtered");if(!["stop","tool_calls","length"].includes(w))throw new Error(`llm returned unknown finish reason: ${w}`);o.stopReason=w==="tool_calls"?"toolUse":w==="length"?"length":"stop",r.push({type:"done",reason:o.stopReason,message:o}),r.end();return}})().catch(a=>{o.stopReason=n.signal?.aborted?"aborted":"error",o.errorMessage=a instanceof Error?a.message:String(a),a instanceof k&&(o.diagnostics=[{type:B,timestamp:Date.now(),...a.retryAt!==void 0?{details:{retryAt:a.retryAt}}:{}},...a.rateLimit!==void 0?[E({status:429,ratelimit:a.rateLimit})]:[],...a.rateLimit===void 0&&a.code==="cap_exhausted"?[E({status:a.status??402,code:a.code})]:[]]),a instanceof S&&(o.diagnostics=[E({status:503,code:R})]),a instanceof D&&o.stopReason==="error"&&(o.rawStopReason="content_filter"),r.push({type:"error",reason:o.stopReason,error:o}),r.end()}),r}c(re,"streamBrokerModel");export{ee as LLM_BROKER_RETRY_WINDOW_S,B as LLM_REFUSAL_DIAGNOSTIC,ye as configureBrokerModelRuntime,_e as refusalRetryAt,ne as requestBody,re as streamBrokerModel,te as wireHistory};
@@ -0,0 +1,7 @@
1
+ import type { BrokerSession } from './read-ops.js';
2
+ export declare function setTurnCauseSource(source: () => BrokerSession): void;
3
+ type Branch = ReturnType<BrokerSession['sessionManager']['getBranch']>;
4
+ export declare function turnCauseOf(branch: Branch): string | undefined;
5
+ /** `message:<id>` of the turn running now, or undefined. */
6
+ export declare function currentCausedBy(): string | undefined;
7
+ export {};
@@ -0,0 +1 @@
1
+ var f=Object.defineProperty;var r=(s,e)=>f(s,"name",{value:e,configurable:!0});let u;function c(s){u=s}r(c,"setTurnCauseSource");function a(s){let e=[],t;for(const n of s)if(n.type==="custom"&&n.customType==="crtr-turn-input"){const i=n.data?.message_ids;Array.isArray(i)&&e.push(...i.filter(o=>typeof o=="string"))}else(n.type==="message"&&n.message.role==="user"||n.type==="custom_message")&&(e.length>0?(t=e[0],e=[]):t=void 0);return t===void 0?void 0:`message:${t}`}r(a,"turnCauseOf");function p(){return u===void 0?void 0:a(u().sessionManager.getBranch())}r(p,"currentCausedBy");export{p as currentCausedBy,c as setTurnCauseSource,a as turnCauseOf};
@@ -1 +1 @@
1
- var Pe=Object.defineProperty;var n=(t,o)=>Pe(t,"name",{value:o,configurable:!0});import{envInboxBetweenTurns as Oe,envModelIntent as Ie,envNodeCwd as De,envNodeId as Ne,envProfileId as Fe,envScopes as Le,isSandboxedNode as $e,scopeAllowed as Be}from"../../shared/env.js";import{createServer as Ue}from"node:net";import{existsSync as ye,readFileSync as Ge,unlinkSync as be}from"node:fs";import{join as Te}from"node:path";import{randomUUID as x}from"node:crypto";import{mark as Ke}from"../timing.js";import{SUBMIT_RESULT_TOOL as je}from"./structured-output.js";import{installSessionManagerStorePatch as We}from"../conversation-store/index.js";import{getAgentDir as Y,ModelRegistry as qe,ModelRuntime as Ve}from"@earendil-works/pi-coding-agent";import{nodeRunDir as Xe,viewSocketPath as He}from"../canvas/paths.js";import{bindBrokerEventSource as Ye}from"../events/source.js";import{emitEvent as T,flushBrokerLog as ze}from"../events/emit.js";import{operationIdContext as Je}from"../events/operation-id.js";import{findMissingPackagePaths as Qe}from"./package-health.js";import{installBrokerConfigSnapshot as Ze}from"../config.js";import{FRONT_DOOR_ENV as en}from"./front-door.js";import{CANVAS_EXTENSIONS as re,piInvocationToSdkConfig as nn}from"./launch.js";import{assertEngineVersion as tn,loadBrokerEngine as rn}from"./broker-sdk.js";import{initCrtrTheme as on}from"./crtr-theme.js";import{resolveBundledPiPackageDir as sn}from"./pi-cli.js";import{captureSessionChatCapabilities as an}from"./command-surface.js";import{InMemoryCredentialStore as dn}from"@earendil-works/pi-ai";import{configureBrokerModelRuntime as ln}from"./broker/model-adapter.js";import{mutateBrokerFault as z,recordBrokerTurn as Re}from"./broker/daemon-ops.js";import{modelRequestFromConfig as cn,expandModelCandidates as mn,parseModelSpec as un,unregisteredConcreteModel as fn}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as pn}from"./stream-watchdog.js";import{probeOnline as gn}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as vn,cycleAwareMessages as hn,endedByAbort as wn}from"./session-cycles.js";import{turnErrorOf as Sn}from"../llm/refusal.js";import{projectTranscript as _n}from"./session-visibility.js";import{currentTurnVisibility as yn}from"./turn-visibility.js";import{isUnknownModel as oe}from"./model-selection.js";import{BrokerClientRegistry as bn}from"./broker/client-registry.js";import{ToolGroupTracker as Tn}from"./broker/tool-groups.js";import{TurnReplyTracker as Rn}from"./broker/turn-replies.js";import{onNodeNamed as kn}from"./broker/node-named.js";import{FaultRetry as En,willDaemonRetry as Mn}from"./broker/fault-retry.js";import{RunTurnEnds as xn}from"./broker/run-turn-end.js";import{createTurnAdmissionGate as Cn}from"./broker/turn-admission.js";import{BROKER_IDLE_TURN_START as An,BROKER_RUN_TURN_BUSY as Pn}from"./broker/held-deferred-inbox.js";import{prependRunDeferredMail as On,settleRunDeferredMail as In}from"./broker/run-deferred-mail.js";import{createRunTurnQueue as Dn}from"./broker/run-turn-queue.js";import{EventProjection as Nn}from"./broker/event-projection.js";import{createFrameDispatchContext as Fn,handleFrame as Ln}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as $n,installAdvertisedCommandInvocationContract as Bn}from"./advertised-command-invocation.js";import{RebindDriver as Un}from"./broker/rebind.js";import{beginRuntimeTeardown as Gn}from"./broker/extension-abort.js";import{receiveNodeToken as Kn}from"./broker/node-token.js";import{serveCliRelay as jn}from"./broker/cli-relay.js";import{decodeKickoffOrigin as Wn,KICKOFF_ORIGIN_ENV as qn}from"./stamp/protocol.js";import{announceMessageOrigin as Vn}from"./stamp/channel.js";import{brokerExtensionState as Xn,commitBrokerModel as Hn}from"./broker/daemon-ops.js";import{composerNames as Yn}from"./broker/frame-memory-refs.js";import{FrameOverflowError as zn,normalizeSnapshotTail as Jn}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as ur,REVIEW_BOUNDARY_NAVIGATION_CODE as fr}from"./broker/frame-replies.js";function ie(t){return new qe(t.modelRuntime)}n(ie,"registryOf");function B(t,o){if(t==null||oe(t))return null;const s=o!==void 0&&o!==""&&o!=="off"?`:${o}`:"";return`${t.provider}/${t.id}${s}`}n(B,"formatModelSpec");function Qn(t,o){const s=B(t,void 0);return s===null?null:`${s}:${o===void 0||o===""?"off":o}`}n(Qn,"formatExactModelSpec");const Zn=12e4;let J=null;import{brokerSignalClient as Q}from"./broker/signal-stream.js";function et(){Q().stop();const t=J;if(J=null,t!==null)try{t.dispose()}catch{}}n(et,"disposeActiveSession");function nt(t,o){const s=Be(o,"crtr:act")?void 0:["bash"],m=t!==void 0&&t.length>0?[...new Set([...t,je])]:t===void 0?void 0:[...t];return{...m!==void 0?{tools:m}:{},...s!==void 0?{excludeTools:s}:{}}}n(nt,"brokerToolOptions");async function lr(t,o=process.hrtime.bigint(),s=new Date().toISOString()){Ye(t);const m=await Kn(),i=await jn(t,m);process.env.CRTR_API_SOCKET=i.path,Je.fresh(()=>{T({level:"info",event:"broker.startup.cli_entry",ts:s,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),T({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const a=new Set;let l=null;const d=n((e,r=null)=>{a.has(e)||(a.add(e),Ke(e,{duration_ms:Number(process.hrtime.bigint()-o)/1e6}),T({level:"info",event:e,duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:l,model:r}}))},"emitStartupMilestone");process.env[en]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX,We(t);const p=await rn();tn(p.VERSION),l=p.VERSION;const S=Xe(t),k=Te(S,"broker-launch.json"),_=JSON.parse(Ge(k,"utf8"));if($e()){if(!_.configSnapshot)throw new Error("broker launch is missing its config snapshot");Ze(_.configSnapshot)}const f=nn(_);f.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const y=await Yn(t);let b,C;const V=n(e=>{b!==void 0?b(e):C??=e},"onSignal");process.on("SIGTERM",()=>V("SIGTERM")),process.on("SIGINT",()=>V("SIGINT"));let{session:U,services:A,resuming:ae,runtime:G}=await it(p,f);d("broker.startup.session_built");const E=(await Xn(t)).node.review_binding?.review_id,R=Oe();J=U;const D=gn;try{process.env.PI_PACKAGE_DIR=sn(),on(A.settingsManager.getTheme(),Y(),!1)}catch(e){T({level:"error",event:"broker.theme.initialization_failed",error:e})}try{for(const e of Qe(Y()))T({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:e.source,resolved_path:e.resolved}})}catch{}const K=He(t),g=new bn(t),X=new Map,O=new Tn(t,e=>g.broadcast(e)),j=new Rn(t,e=>g.broadcast(e));kn(e=>g.broadcast({type:"node_named",...e}));let N=!1,de=!1,H,le,u,W;const Z=new xn;let F,ce=n(()=>{},"notifyTurnAccepted"),me=n(()=>{},"resetFrameState");const ee=Cn();let ue=n(()=>0,"pendingPromptDispatches"),fe;const L=Dn({runNode:R,session:n(()=>u.session(),"session"),isReplacing:n(()=>u.isReplacing(),"isReplacing"),pendingRebind:n(()=>u.pendingRebind(),"pendingRebind"),isAgentRunActive:n(()=>u.isAgentRunActive(),"isAgentRunActive"),pendingDispatches:n(()=>ue(),"pendingDispatches"),turnAdmission:ee,prependDeferred:n(e=>On(t,e),"prependDeferred"),onError:n(e=>T({level:"error",event:"broker.inbox.idle_prompt_failed",error:e}),"onError")}),pe=L.drain;f.firstPrompt!==void 0&&f.firstPrompt!==""&&L.holdForKickoff(),globalThis[An]=L.start,globalThis[Pn]=L.busy,u=new Un({nodeId:t,cfg:f,session:U,services:A,runtime:G,registry:g,toolGroups:O,turnReplies:j,transcriptMessages:n(e=>se(e,E)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages,"transcriptMessages"),uiContext:n(()=>le,"uiContext"),faultRetry:n(()=>W,"faultRetry"),projection:n(()=>F,"projection"),setActiveSession:n(e=>{if(J=e,fe?.(),R){let r="stop",c,v=!1;fe=e.subscribe(h=>{if(h.type==="agent_start"&&(r="stop",c=void 0,v=!1,Z.started()),h.type==="agent_end"){const w=[...h.messages??[]].reverse().find($=>$.role==="assistant");w&&(r=w.stopReason,c=wn(w)?void 0:Sn(w),v=w.role==="assistant"&&Mn(w,e.model?.contextWindow))}h.type==="agent_settled"&&(Z.settled(e.sessionManager,{stop_reason:r,...c?{error:c}:{}},v),In(t,e).catch(w=>{T({level:"error",event:"broker.run_deferred_mail.settle_failed",error:w})}),queueMicrotask(()=>{u.session()===e&&pe()}))})}},"setActiveSession"),disposeAndExit:n((e,r)=>q(e,r),"disposeAndExit"),onSessionRebind:n(()=>{me()},"onSessionRebind"),onReplacementIdle:n(()=>{R&&pe()},"onReplacementIdle"),reWelcomeAll:n(()=>ne(),"reWelcomeAll")});const ge=n(async(e,r=!1)=>{const c=u.session(),v=B(c.model,c.thinkingLevel);if(v===null)return null;const h=await Hn(t,{spec:v,...e!==void 0?{intent:e}:{},userSelected:r});return r&&(f.model=h.modelOverride,e!==void 0?(process.env.CRTR_MODEL_INTENT=`${e.family}/${e.strength}`,delete process.env.CRTR_MODEL_EXACT,f.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",f.modelExact=!0)),h.modelOverride},"persistModelChoice"),ve=n(async(e=!0,r,c=!1)=>{const v=u.session(),h=B(v.model,v.thinkingLevel),w=e?await ge(r,c):h;g.broadcast({type:"model_changed",model:oe(v.model)?void 0:v.model,spec:w})},"broadcastModelChanged");W=new En({nodeId:t,cfg:f,retryProbe:D,currentSession:n(()=>u.session(),"currentSession"),currentServices:n(()=>u.services(),"currentServices"),installedGeneration:n(()=>u.installedGeneration(),"installedGeneration"),registryOf:ie,formatModelSpec:B,broadcastModelChanged:ve,turnAdmission:ee,reWelcomeAll:n(()=>ne(),"reWelcomeAll"),...R?{turnEnds:Z}:{}});const he=n(()=>{W.rearmIfStranded().catch(e=>{T({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry re-arm failed: ${e instanceof Error?e.message:String(e)}`}})})},"rearmStrandedRetry");Q().subscribe("resync",he),Q().subscribe("fault-retry",he),F=new Nn({registry:g,faultRetry:W,installedGeneration:n(()=>u.installedGeneration(),"installedGeneration"),currentSession:n(()=>u.session(),"currentSession"),notifyTurnAccepted:n(()=>ce(),"notifyTurnAccepted"),emitStartupMilestone:d,formatModelSpec:B});const Ee=n(e=>{const r=u.session(),c=se(r,E),v=Jn(e.snapshotTail),h=c===void 0||v===void 0?c:c.slice(-v),w=h?.map(({message:I})=>I)??r.sessionManager.buildSessionContext().messages,$=O.summaries(),_e=h!==void 0&&v!==void 0?tt(w):void 0,Ae=_e===void 0?$:Object.fromEntries(Object.entries($).filter(([I])=>_e.has(I)));return{messages:w,...h===void 0?{}:{messageIds:h.map(({id:I})=>I)},messageVisibility:h?.map(({visibility:I})=>I)??w.map(()=>"visible"),turnVisibility:yn(),stats:r.getSessionStats(),state:{model:oe(r.model)?void 0:r.model,thinkingLevel:r.thinkingLevel,isStreaming:r.isStreaming,isCompacting:r.isCompacting,steeringMode:r.steeringMode,followUpMode:r.followUpMode,sessionFile:r.sessionFile,sessionId:r.sessionId,sessionName:r.sessionName,autoCompactionEnabled:r.autoCompactionEnabled,messageCount:r.messages.length,pendingMessageCount:r.pendingMessageCount},display:{...g.displaySnapshot()},toolGroupSummaries:Ae,turnReplies:j.snapshot(),workingActivity:F.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),we=n(e=>{const r=e.role==="controller"?X.values().next().value:void 0;g.sendFrame(e,{type:"welcome",snapshot:Ee(e),role:e.role,pending_dialog:r!==void 0?r.request:null,agentDir:Y()},!0)},"sendWelcome"),Me=n(e=>{const r=[...X.values()];for(let c=1;c<r.length;c++)g.sendFrame(e,r[c].request)},"replayExtraPendingDialogsTo"),ne=n(()=>{try{const e=u.session();j.seed(se(e,E)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages)}catch(e){T({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply reseed failed: ${String(e)}`}})}g.forEachHelloed(we)},"reWelcomeAll"),Se=n(async e=>{if(!N){N=!0,Q().stop(),O.persistPendingSummary(),F.dispose(),et();try{H?.close()}catch{}i.close(),g.dispose();try{ye(K)&&be(K)}catch{}g.clearAttachState(),await ze(),process.exit(e)}},"completeExit"),q=n((e,r=0)=>{if(N)return;const c=e==="shutdown-hook"||e==="shutdown-after-settle";if(c&&O.finishOpenToolGroup(!0),c&&(O.hasSummaryTasks()||j.hasTasks())){if(de)return;de=!0,Promise.allSettled([O.waitForSummaryTasks(),j.waitForTasks()]).finally(()=>Se(r));return}Se(r)},"disposeAndExit");le=st({writable:n(()=>g.writableClients(),"writable"),forward:n((e,r)=>g.sendFrame(e,r),"forward"),pending:X,broadcast:n(e=>g.broadcastUi(e),"broadcast"),onKnownStreamWait:n(e=>F.knownStreamWait(e),"onKnownStreamWait")}),u.setRebindSession(),await u.enqueueRebind(U,A),d("broker.startup.extensions_bound");const M=Fn({nodeId:t,registry:g,toolGroups:O,projection:F,rebind:u,boundaryReviewId:E,pendingDialogs:X,sendWelcome:we,replayExtraPendingDialogsTo:Me,reWelcomeAll:ne,disposeAndExit:q,persistModelChoice:ge,broadcastModelChanged:ve,registryOf:ie,formatModelSpec:B,formatExactModelSpec:Qn,turnAdmission:ee,memoryInventory:y,runNode:R,onKickoffAdmitted:L.releaseKickoff});ce=M.notifyTurnAccepted,me=M.resetForSession,ue=M.pendingPromptDispatches;const xe=2500;let te=!1;const Ce=n(async e=>{if(N||te)return;if(te=!0,u.isAgentRunActive()||u.session().isStreaming||M.pendingPromptDispatches()>0){const c=Date.now()+xe;for(;M.pendingPromptDispatches()>0&&!u.session().isStreaming&&Date.now()<c;)await new Promise(v=>setTimeout(v,25));if(u.session().isStreaming){const v=c-Date.now();if(v>0){let h;try{Gn(),await Promise.race([u.session().abort().then(()=>!0,()=>!1),new Promise($=>{h=setTimeout(()=>$(!1),v)})])&&await Re(t,{event:"closed",end_reason:"teardown-aborted"})}finally{h!==void 0&&clearTimeout(h)}}}else(M.pendingPromptDispatches()>0||u.isAgentRunActive())&&await Re(t,{event:"interrupted"})}q(e)},"abortAndExit");if(b=n(e=>{Ce(e)},"signalTeardown"),C!==void 0){b(C);return}try{ye(K)&&be(K)}catch{}H=Ue(e=>{const r=g.create(e);e.on("data",v=>{let h;try{h=r.decoder.push(v)}catch(w){w instanceof zn?(g.sendFrame(r,{type:"error",code:"frame_overflow",message:w.message}),g.dropClient(r,`frame overflow: ${w.message}`)):g.dropClient(r,`decoder error: ${String(w)}`);return}for(const w of h)try{Ln(M,r,w)}catch{}});const c=n(()=>{g.removeClient(r)},"drop");e.on("close",c),e.on("error",()=>{})}),H.on("error",e=>{N||(T({level:"error",event:"broker.socket.failed",error:e}),q("socket-error",1))}),H.listen(K,async()=>{Promise.all([z(t,{op:"clear",link:"viewer\u2194broker"}),z(t,{op:"clear",link:"relay\u2194broker"})]).catch(r=>T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let e;try{e=await W.recoverOnStartup()}catch(r){T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"recovery_startup"}}),q("recovery-startup-failed",1);return}if(!(N||te))if(e!=="retry-armed"&&f.firstPrompt!==void 0&&f.firstPrompt!==""){const r=Wn(process.env[qn]);r!==null&&Vn(f.firstPrompt,r);const c=process.env.CRTR_KICKOFF_MESSAGE_IDS;M.kickoff(f.firstPrompt,c?JSON.parse(c):[])}else L.releaseKickoff()}),g.persistAttachState()}n(lr,"runBroker");function tt(t){const o=new Set;for(const s of t)if(!(s.role!=="assistant"||!Array.isArray(s.content)))for(const m of s.content)m!==null&&typeof m=="object"&&m.type==="toolCall"&&typeof m.id=="string"&&o.add(m.id);return o}n(tt,"toolCallIds");function se(t,o){const s=t.sessionManager,m=hn(s);return m!==void 0&&$n(m.map(({message:i})=>i)),m===void 0?void 0:_n(m,{boundaryReviewId:o,sessionEntries:s.getEntries?.()})}n(se,"snapshotMessages");function ke(){const t=Ne();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}n(ke,"currentBrokerNodeId");async function rt(t,o){const s=cn(o.model,Ie(),o.modelExact===!0);if(s===void 0)return;const m=ie(t),i={cwd:De()??o.cwd,profileId:Fe()},a=fn(s,m,i);if(a!==void 0)throw await z(ke(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const l=mn(s,i.cwd,i.profileId),d=un(s.spec);for(const p of l){const S=m.find(p.providerId,p.modelId);if(S===void 0)continue;const _=d?.providerId===p.providerId&&d.modelId===p.modelId?d.thinkingLevel??(p.thinkingLevel===void 0?void 0:"off"):p.thinkingLevel;return{model:S,thinkingLevel:_}}if(o.modelExact===!0){const p=l.map(S=>`'${S.providerId}/${S.modelId}' unregistered`).join("; ");throw await z(ke(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${o.model}' is unavailable \u2014 refusing to substitute (${p})`}}),new Error(`[broker] FATAL: exact-consult model '${o.model}' is unavailable`)}T({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:l.map(p=>({provider:p.providerId,model:p.modelId,reason:"unregistered"})).slice(0,16)}})}n(rt,"resolveLaunchModel");function ot(t){let o=!0;return{runtime:new Proxy(t,{get(m,i,a){return o&&i==="getAvailableSnapshot"?()=>[]:o&&i==="getAvailable"?async()=>[]:o&&i==="getModel"?()=>{}:Reflect.get(m,i,a)}}),reveal:n(()=>{o=!1},"reveal")}}n(ot,"modelLessRegistry");async function it(t,o){const s=Y(),m=n(async _=>{const f=await Ve.create({credentials:new dn,modelsPath:Te(_.agentDir,"models.json")});ln(f);const y=await t.createAgentSessionServices({cwd:_.cwd,agentDir:_.agentDir,modelRuntime:f,resourceLoaderOptions:{additionalExtensionPaths:o.extensionPaths,appendSystemPrompt:o.appendSystemPromptPath!==void 0?[o.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:n(P=>({...P,extensions:P.extensions.filter(E=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(E.path))}),"extensionsOverride")}}),b=y.resourceLoader.getExtensions();if(o.extensionPaths.some(P=>re.includes(P))){const P=new Set(b.extensions.map(R=>R.path)),E=re.filter(R=>!P.has(R));if(E.length>0){const R=b.errors.filter(D=>re.includes(D.path)).map(D=>`${D.path}: ${D.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${E.join(", ")}${R===""?"":` (${R})`}`)}}y.settingsManager.getRetryEnabled=()=>!1;const C=await rt(y,o),V=C?.model,U=C?.thinkingLevel,A=C===void 0?ot(y.modelRuntime):void 0,ae=A!==void 0?{...y,modelRuntime:A.runtime}:y,G=await t.createAgentSessionFromServices({services:ae,sessionManager:_.sessionManager,model:V,thinkingLevel:U,...nt(o.tools,Le()),sessionStartEvent:_.sessionStartEvent});return Bn(G.session),an(G.session),A?.reveal(),{...G,services:y}},"buildForManager"),i=o.resumeSessionPath,a=o.forkFrom!==void 0&&o.forkFrom!=="";if(!a&&(i===void 0||i==="")&&o.resumeSessionId!==void 0&&o.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${o.resumeSessionId}' (pi_session_file was never captured for this node)`);const l=!a&&i!==void 0&&i!=="",d=l&&o.newCycle===!0,p=l&&!d;let S;if(a)S=await t.SessionManager.forkFrom(o.forkFrom,o.cwd);else if(p||d){if(S=await t.SessionManager.open(i),d){const _=S.getLeafId();S.resetLeaf(),S.appendCustomEntry(vn,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:_})}}else S=await t.SessionManager.create(o.cwd);if(t.createAgentSessionRuntime!==void 0){const _=n(async y=>{const b=await m({cwd:y.cwd,agentDir:y.agentDir,sessionManager:y.sessionManager,sessionStartEvent:y.sessionStartEvent});return{...b,diagnostics:b.services.diagnostics??[]}},"factory"),f=await t.createAgentSessionRuntime(_,{cwd:o.cwd,agentDir:s,sessionManager:S});return{session:f.session,services:f.services,resuming:p,runtime:f}}const k=await m({cwd:o.cwd,agentDir:s,sessionManager:S});return{session:k.session,services:k.services,resuming:p,runtime:void 0}}n(it,"buildBrokerSession");function st(t){const o=n((i,a,l,d)=>{if(d?.signal?.aborted)return Promise.resolve(i);const p=t.writable();return p.length===0?Promise.resolve(i):new Promise(S=>{let k;const _=n(()=>{k!==void 0&&clearTimeout(k),d?.signal?.removeEventListener("abort",f),t.pending.delete(a.id)},"cleanup"),f=n(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(i)},"onAbort");d?.signal?.addEventListener("abort",f,{once:!0});const y=d?.timeout!==void 0?d.timeout:Zn;k=setTimeout(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(i)},y),typeof k.unref=="function"&&k.unref(),t.pending.set(a.id,{request:a,resolve:n(b=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(l(b))},"resolve")});for(const b of p)t.forward(b,a)})},"dialogPromise"),s=n(()=>{},"noop");return{[pn]:t.onKnownStreamWait??(i=>()=>{}),get theme(){const i=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(i==null)throw new Error("Theme not initialized. Call initTheme() first.");return i},select:n((i,a,l)=>o(void 0,{type:"extension_ui_request",id:x(),method:"select",title:i,options:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"select"),confirm:n((i,a,l)=>o(!1,{type:"extension_ui_request",id:x(),method:"confirm",title:i,message:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?!1:"confirmed"in d?d.confirmed:!1,l),"confirm"),input:n((i,a,l)=>o(void 0,{type:"extension_ui_request",id:x(),method:"input",title:i,placeholder:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"input"),editor:n((i,a)=>o(void 0,{type:"extension_ui_request",id:x(),method:"editor",title:i,prefill:a},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0),"editor"),setStatus:n((i,a)=>t.broadcast({type:"extension_ui_request",id:x(),method:"setStatus",statusKey:i,statusText:a}),"setStatus"),setWidget:n((i,a,l)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:x(),method:"setWidget",widgetKey:i,widgetLines:a,widgetPlacement:l?.placement})},"setWidget"),setTitle:n(i=>t.broadcast({type:"extension_ui_request",id:x(),method:"setTitle",title:i}),"setTitle"),notify:n((i,a)=>{const l=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:x(),method:"notify",message:i,notifyType:l})},"notify"),onTerminalInput:n(()=>s,"onTerminalInput"),setWorkingMessage:s,setWorkingVisible:s,setWorkingIndicator:s,setHiddenThinkingLabel:s,setFooter:s,setHeader:s,custom:n(()=>Promise.resolve(void 0),"custom"),pasteToEditor:s,setEditorText:s,getEditorText:n(()=>"","getEditorText"),addAutocompleteProvider:s,setEditorComponent:s,getEditorComponent:n(()=>{},"getEditorComponent"),getAllThemes:n(()=>[],"getAllThemes"),getTheme:n(()=>{},"getTheme"),setTheme:s,getToolsExpanded:n(()=>!1,"getToolsExpanded"),setToolsExpanded:s}}n(st,"makeBrokerUiContext");export{fr as REVIEW_BOUNDARY_NAVIGATION_CODE,ur as ReviewBoundaryNavigationError,nt as brokerToolOptions,it as buildBrokerSession,et as disposeActiveSession,st as makeBrokerUiContext,lr as runBroker,se as snapshotMessages};
1
+ var Pe=Object.defineProperty;var n=(t,o)=>Pe(t,"name",{value:o,configurable:!0});import{envInboxBetweenTurns as Oe,envModelIntent as Ie,envNodeCwd as De,envNodeId as Ne,envProfileId as Fe,envScopes as Le,isSandboxedNode as $e,scopeAllowed as Be}from"../../shared/env.js";import{createServer as Ue}from"node:net";import{existsSync as ye,readFileSync as Ge,unlinkSync as be}from"node:fs";import{join as Te}from"node:path";import{randomUUID as M}from"node:crypto";import{mark as Ke}from"../timing.js";import{SUBMIT_RESULT_TOOL as je}from"./structured-output.js";import{installSessionManagerStorePatch as We}from"../conversation-store/index.js";import{getAgentDir as Y,ModelRegistry as qe,ModelRuntime as Ve}from"@earendil-works/pi-coding-agent";import{nodeRunDir as Xe,viewSocketPath as He}from"../canvas/paths.js";import{bindBrokerEventSource as Ye}from"../events/source.js";import{emitEvent as T,flushBrokerLog as ze}from"../events/emit.js";import{operationIdContext as Je}from"../events/operation-id.js";import{findMissingPackagePaths as Qe}from"./package-health.js";import{installBrokerConfigSnapshot as Ze}from"../config.js";import{FRONT_DOOR_ENV as en}from"./front-door.js";import{CANVAS_EXTENSIONS as re,piInvocationToSdkConfig as nn}from"./launch.js";import{assertEngineVersion as tn,loadBrokerEngine as rn}from"./broker-sdk.js";import{initCrtrTheme as on}from"./crtr-theme.js";import{resolveBundledPiPackageDir as sn}from"./pi-cli.js";import{captureSessionChatCapabilities as an}from"./command-surface.js";import{InMemoryCredentialStore as dn}from"@earendil-works/pi-ai";import{configureBrokerModelRuntime as ln}from"./broker/model-adapter.js";import{mutateBrokerFault as z,recordBrokerTurn as Re}from"./broker/daemon-ops.js";import{modelRequestFromConfig as cn,expandModelCandidates as mn,parseModelSpec as un,unregisteredConcreteModel as fn}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as pn}from"./stream-watchdog.js";import{probeOnline as gn}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as vn,cycleAwareMessages as hn,endedByAbort as wn}from"./session-cycles.js";import{turnErrorOf as Sn}from"../llm/refusal.js";import{projectTranscript as _n}from"./session-visibility.js";import{currentTurnVisibility as yn}from"./turn-visibility.js";import{isUnknownModel as oe}from"./model-selection.js";import{BrokerClientRegistry as bn}from"./broker/client-registry.js";import{ToolGroupTracker as Tn}from"./broker/tool-groups.js";import{TurnReplyTracker as Rn}from"./broker/turn-replies.js";import{onNodeNamed as kn}from"./broker/node-named.js";import{FaultRetry as En,willDaemonRetry as Cn}from"./broker/fault-retry.js";import{RunTurnEnds as Mn}from"./broker/run-turn-end.js";import{createTurnAdmissionGate as xn}from"./broker/turn-admission.js";import{BROKER_IDLE_TURN_START as An,BROKER_RUN_TURN_BUSY as Pn}from"./broker/held-deferred-inbox.js";import{prependRunDeferredMail as On,settleRunDeferredMail as In}from"./broker/run-deferred-mail.js";import{createRunTurnQueue as Dn}from"./broker/run-turn-queue.js";import{EventProjection as Nn}from"./broker/event-projection.js";import{createFrameDispatchContext as Fn,handleFrame as Ln}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as $n,installAdvertisedCommandInvocationContract as Bn}from"./advertised-command-invocation.js";import{RebindDriver as Un}from"./broker/rebind.js";import{beginRuntimeTeardown as Gn}from"./broker/extension-abort.js";import{receiveNodeToken as Kn}from"./broker/node-token.js";import{serveCliRelay as jn}from"./broker/cli-relay.js";import{setTurnCauseSource as Wn}from"./broker/turn-cause.js";import{decodeKickoffOrigin as qn,KICKOFF_ORIGIN_ENV as Vn}from"./stamp/protocol.js";import{announceMessageOrigin as Xn}from"./stamp/channel.js";import{brokerExtensionState as Hn,commitBrokerModel as Yn}from"./broker/daemon-ops.js";import{composerNames as zn}from"./broker/frame-memory-refs.js";import{FrameOverflowError as Jn,normalizeSnapshotTail as Qn}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as pr,REVIEW_BOUNDARY_NAVIGATION_CODE as gr}from"./broker/frame-replies.js";function se(t){return new qe(t.modelRuntime)}n(se,"registryOf");function B(t,o){if(t==null||oe(t))return null;const i=o!==void 0&&o!==""&&o!=="off"?`:${o}`:"";return`${t.provider}/${t.id}${i}`}n(B,"formatModelSpec");function Zn(t,o){const i=B(t,void 0);return i===null?null:`${i}:${o===void 0||o===""?"off":o}`}n(Zn,"formatExactModelSpec");const et=12e4;let J=null;import{brokerSignalClient as Q}from"./broker/signal-stream.js";function nt(){Q().stop();const t=J;if(J=null,t!==null)try{t.dispose()}catch{}}n(nt,"disposeActiveSession");function tt(t,o){const i=Be(o,"crtr:act")?void 0:["bash"],u=t!==void 0&&t.length>0?[...new Set([...t,je])]:t===void 0?void 0:[...t];return{...u!==void 0?{tools:u}:{},...i!==void 0?{excludeTools:i}:{}}}n(tt,"brokerToolOptions");async function mr(t,o=process.hrtime.bigint(),i=new Date().toISOString()){Ye(t);const u=await Kn(),s=await jn(t,u);process.env.CRTR_API_SOCKET=s.path,Je.fresh(()=>{T({level:"info",event:"broker.startup.cli_entry",ts:i,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),T({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const a=new Set;let l=null;const d=n((e,r=null)=>{a.has(e)||(a.add(e),Ke(e,{duration_ms:Number(process.hrtime.bigint()-o)/1e6}),T({level:"info",event:e,duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:l,model:r}}))},"emitStartupMilestone");process.env[en]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX,We(t);const p=await rn();tn(p.VERSION),l=p.VERSION;const S=Xe(t),k=Te(S,"broker-launch.json"),_=JSON.parse(Ge(k,"utf8"));if($e()){if(!_.configSnapshot)throw new Error("broker launch is missing its config snapshot");Ze(_.configSnapshot)}const f=nn(_);f.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const y=await zn(t);let b,x;const V=n(e=>{b!==void 0?b(e):x??=e},"onSignal");process.on("SIGTERM",()=>V("SIGTERM")),process.on("SIGINT",()=>V("SIGINT"));let{session:U,services:A,resuming:ae,runtime:G}=await it(p,f);d("broker.startup.session_built");const E=(await Hn(t)).node.review_binding?.review_id,R=Oe();J=U;const D=gn;try{process.env.PI_PACKAGE_DIR=sn(),on(A.settingsManager.getTheme(),Y(),!1)}catch(e){T({level:"error",event:"broker.theme.initialization_failed",error:e})}try{for(const e of Qe(Y()))T({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:e.source,resolved_path:e.resolved}})}catch{}const K=He(t),g=new bn(t),X=new Map,O=new Tn(t,e=>g.broadcast(e)),j=new Rn(t,e=>g.broadcast(e));kn(e=>g.broadcast({type:"node_named",...e}));let N=!1,de=!1,H,le,m,W;const Z=new Mn;let F,ce=n(()=>{},"notifyTurnAccepted"),me=n(()=>{},"resetFrameState");const ee=xn();let ue=n(()=>0,"pendingPromptDispatches"),fe;const L=Dn({runNode:R,session:n(()=>m.session(),"session"),isReplacing:n(()=>m.isReplacing(),"isReplacing"),pendingRebind:n(()=>m.pendingRebind(),"pendingRebind"),isAgentRunActive:n(()=>m.isAgentRunActive(),"isAgentRunActive"),pendingDispatches:n(()=>ue(),"pendingDispatches"),turnAdmission:ee,prependDeferred:n(e=>On(t,e),"prependDeferred"),onError:n(e=>T({level:"error",event:"broker.inbox.idle_prompt_failed",error:e}),"onError")});Wn(()=>m.session());const pe=L.drain;f.firstPrompt!==void 0&&f.firstPrompt!==""&&L.holdForKickoff(),globalThis[An]=L.start,globalThis[Pn]=L.busy,m=new Un({nodeId:t,cfg:f,session:U,services:A,runtime:G,registry:g,toolGroups:O,turnReplies:j,transcriptMessages:n(e=>ie(e,E)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages,"transcriptMessages"),uiContext:n(()=>le,"uiContext"),faultRetry:n(()=>W,"faultRetry"),projection:n(()=>F,"projection"),setActiveSession:n(e=>{if(J=e,fe?.(),R){let r="stop",c,v=!1;fe=e.subscribe(h=>{if(h.type==="agent_start"&&(r="stop",c=void 0,v=!1,Z.started()),h.type==="agent_end"){const w=[...h.messages??[]].reverse().find($=>$.role==="assistant");w&&(r=w.stopReason,c=wn(w)?void 0:Sn(w),v=w.role==="assistant"&&Cn(w,e.model?.contextWindow))}h.type==="agent_settled"&&(Z.settled(e.sessionManager,{stop_reason:r,...c?{error:c}:{}},v),In(t,e).catch(w=>{T({level:"error",event:"broker.run_deferred_mail.settle_failed",error:w})}),queueMicrotask(()=>{m.session()===e&&pe()}))})}},"setActiveSession"),disposeAndExit:n((e,r)=>q(e,r),"disposeAndExit"),onSessionRebind:n(()=>{me()},"onSessionRebind"),onReplacementIdle:n(()=>{R&&pe()},"onReplacementIdle"),reWelcomeAll:n(()=>ne(),"reWelcomeAll")});const ge=n(async(e,r=!1)=>{const c=m.session(),v=B(c.model,c.thinkingLevel);if(v===null)return null;const h=await Yn(t,{spec:v,...e!==void 0?{intent:e}:{},userSelected:r});return r&&(f.model=h.modelOverride,e!==void 0?(process.env.CRTR_MODEL_INTENT=`${e.family}/${e.strength}`,delete process.env.CRTR_MODEL_EXACT,f.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",f.modelExact=!0)),h.modelOverride},"persistModelChoice"),ve=n(async(e=!0,r,c=!1)=>{const v=m.session(),h=B(v.model,v.thinkingLevel),w=e?await ge(r,c):h;g.broadcast({type:"model_changed",model:oe(v.model)?void 0:v.model,spec:w})},"broadcastModelChanged");W=new En({nodeId:t,cfg:f,retryProbe:D,currentSession:n(()=>m.session(),"currentSession"),currentServices:n(()=>m.services(),"currentServices"),installedGeneration:n(()=>m.installedGeneration(),"installedGeneration"),registryOf:se,formatModelSpec:B,broadcastModelChanged:ve,turnAdmission:ee,reWelcomeAll:n(()=>ne(),"reWelcomeAll"),...R?{turnEnds:Z}:{}});const he=n(()=>{W.rearmIfStranded().catch(e=>{T({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry re-arm failed: ${e instanceof Error?e.message:String(e)}`}})})},"rearmStrandedRetry");Q().subscribe("resync",he),Q().subscribe("fault-retry",he),F=new Nn({registry:g,faultRetry:W,installedGeneration:n(()=>m.installedGeneration(),"installedGeneration"),currentSession:n(()=>m.session(),"currentSession"),notifyTurnAccepted:n(()=>ce(),"notifyTurnAccepted"),emitStartupMilestone:d,formatModelSpec:B});const Ee=n(e=>{const r=m.session(),c=ie(r,E),v=Qn(e.snapshotTail),h=c===void 0||v===void 0?c:c.slice(-v),w=h?.map(({message:I})=>I)??r.sessionManager.buildSessionContext().messages,$=O.summaries(),_e=h!==void 0&&v!==void 0?rt(w):void 0,Ae=_e===void 0?$:Object.fromEntries(Object.entries($).filter(([I])=>_e.has(I)));return{messages:w,...h===void 0?{}:{messageIds:h.map(({id:I})=>I)},messageVisibility:h?.map(({visibility:I})=>I)??w.map(()=>"visible"),turnVisibility:yn(),stats:r.getSessionStats(),state:{model:oe(r.model)?void 0:r.model,thinkingLevel:r.thinkingLevel,isStreaming:r.isStreaming,isCompacting:r.isCompacting,steeringMode:r.steeringMode,followUpMode:r.followUpMode,sessionFile:r.sessionFile,sessionId:r.sessionId,sessionName:r.sessionName,autoCompactionEnabled:r.autoCompactionEnabled,messageCount:r.messages.length,pendingMessageCount:r.pendingMessageCount},display:{...g.displaySnapshot()},toolGroupSummaries:Ae,turnReplies:j.snapshot(),workingActivity:F.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),we=n(e=>{const r=e.role==="controller"?X.values().next().value:void 0;g.sendFrame(e,{type:"welcome",snapshot:Ee(e),role:e.role,pending_dialog:r!==void 0?r.request:null,agentDir:Y()},!0)},"sendWelcome"),Ce=n(e=>{const r=[...X.values()];for(let c=1;c<r.length;c++)g.sendFrame(e,r[c].request)},"replayExtraPendingDialogsTo"),ne=n(()=>{try{const e=m.session();j.seed(ie(e,E)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages)}catch(e){T({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply reseed failed: ${String(e)}`}})}g.forEachHelloed(we)},"reWelcomeAll"),Se=n(async e=>{if(!N){N=!0,Q().stop(),O.persistPendingSummary(),F.dispose(),nt();try{H?.close()}catch{}s.close(),g.dispose();try{ye(K)&&be(K)}catch{}g.clearAttachState(),await ze(),process.exit(e)}},"completeExit"),q=n((e,r=0)=>{if(N)return;const c=e==="shutdown-hook"||e==="shutdown-after-settle";if(c&&O.finishOpenToolGroup(!0),c&&(O.hasSummaryTasks()||j.hasTasks())){if(de)return;de=!0,Promise.allSettled([O.waitForSummaryTasks(),j.waitForTasks()]).finally(()=>Se(r));return}Se(r)},"disposeAndExit");le=at({writable:n(()=>g.writableClients(),"writable"),forward:n((e,r)=>g.sendFrame(e,r),"forward"),pending:X,broadcast:n(e=>g.broadcastUi(e),"broadcast"),onKnownStreamWait:n(e=>F.knownStreamWait(e),"onKnownStreamWait")}),m.setRebindSession(),await m.enqueueRebind(U,A),d("broker.startup.extensions_bound");const C=Fn({nodeId:t,registry:g,toolGroups:O,projection:F,rebind:m,boundaryReviewId:E,pendingDialogs:X,sendWelcome:we,replayExtraPendingDialogsTo:Ce,reWelcomeAll:ne,disposeAndExit:q,persistModelChoice:ge,broadcastModelChanged:ve,registryOf:se,formatModelSpec:B,formatExactModelSpec:Zn,turnAdmission:ee,memoryInventory:y,runNode:R,onKickoffAdmitted:L.releaseKickoff});ce=C.notifyTurnAccepted,me=C.resetForSession,ue=C.pendingPromptDispatches;const Me=2500;let te=!1;const xe=n(async e=>{if(N||te)return;if(te=!0,m.isAgentRunActive()||m.session().isStreaming||C.pendingPromptDispatches()>0){const c=Date.now()+Me;for(;C.pendingPromptDispatches()>0&&!m.session().isStreaming&&Date.now()<c;)await new Promise(v=>setTimeout(v,25));if(m.session().isStreaming){const v=c-Date.now();if(v>0){let h;try{Gn(),await Promise.race([m.session().abort().then(()=>!0,()=>!1),new Promise($=>{h=setTimeout(()=>$(!1),v)})])&&await Re(t,{event:"closed",end_reason:"teardown-aborted"})}finally{h!==void 0&&clearTimeout(h)}}}else(C.pendingPromptDispatches()>0||m.isAgentRunActive())&&await Re(t,{event:"interrupted"})}q(e)},"abortAndExit");if(b=n(e=>{xe(e)},"signalTeardown"),x!==void 0){b(x);return}try{ye(K)&&be(K)}catch{}H=Ue(e=>{const r=g.create(e);e.on("data",v=>{let h;try{h=r.decoder.push(v)}catch(w){w instanceof Jn?(g.sendFrame(r,{type:"error",code:"frame_overflow",message:w.message}),g.dropClient(r,`frame overflow: ${w.message}`)):g.dropClient(r,`decoder error: ${String(w)}`);return}for(const w of h)try{Ln(C,r,w)}catch{}});const c=n(()=>{g.removeClient(r)},"drop");e.on("close",c),e.on("error",()=>{})}),H.on("error",e=>{N||(T({level:"error",event:"broker.socket.failed",error:e}),q("socket-error",1))}),H.listen(K,async()=>{Promise.all([z(t,{op:"clear",link:"viewer\u2194broker"}),z(t,{op:"clear",link:"relay\u2194broker"})]).catch(r=>T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let e;try{e=await W.recoverOnStartup()}catch(r){T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"recovery_startup"}}),q("recovery-startup-failed",1);return}if(!(N||te))if(e!=="retry-armed"&&f.firstPrompt!==void 0&&f.firstPrompt!==""){const r=qn(process.env[Vn]);r!==null&&Xn(f.firstPrompt,r);const c=process.env.CRTR_KICKOFF_MESSAGE_IDS;C.kickoff(f.firstPrompt,c?JSON.parse(c):[])}else L.releaseKickoff()}),g.persistAttachState()}n(mr,"runBroker");function rt(t){const o=new Set;for(const i of t)if(!(i.role!=="assistant"||!Array.isArray(i.content)))for(const u of i.content)u!==null&&typeof u=="object"&&u.type==="toolCall"&&typeof u.id=="string"&&o.add(u.id);return o}n(rt,"toolCallIds");function ie(t,o){const i=t.sessionManager,u=hn(i);return u!==void 0&&$n(u.map(({message:s})=>s)),u===void 0?void 0:_n(u,{boundaryReviewId:o,sessionEntries:i.getEntries?.()})}n(ie,"snapshotMessages");function ke(){const t=Ne();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}n(ke,"currentBrokerNodeId");async function ot(t,o){const i=cn(o.model,Ie(),o.modelExact===!0);if(i===void 0)return;const u=se(t),s={cwd:De()??o.cwd,profileId:Fe()},a=fn(i,u,s);if(a!==void 0)throw await z(ke(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const l=mn(i,s.cwd,s.profileId),d=un(i.spec);for(const p of l){const S=u.find(p.providerId,p.modelId);if(S===void 0)continue;const _=d?.providerId===p.providerId&&d.modelId===p.modelId?d.thinkingLevel??(p.thinkingLevel===void 0?void 0:"off"):p.thinkingLevel;return{model:S,thinkingLevel:_}}if(o.modelExact===!0){const p=l.map(S=>`'${S.providerId}/${S.modelId}' unregistered`).join("; ");throw await z(ke(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${o.model}' is unavailable \u2014 refusing to substitute (${p})`}}),new Error(`[broker] FATAL: exact-consult model '${o.model}' is unavailable`)}T({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:l.map(p=>({provider:p.providerId,model:p.modelId,reason:"unregistered"})).slice(0,16)}})}n(ot,"resolveLaunchModel");function st(t){let o=!0;return{runtime:new Proxy(t,{get(u,s,a){return o&&s==="getAvailableSnapshot"?()=>[]:o&&s==="getAvailable"?async()=>[]:o&&s==="getModel"?()=>{}:Reflect.get(u,s,a)}}),reveal:n(()=>{o=!1},"reveal")}}n(st,"modelLessRegistry");async function it(t,o){const i=Y(),u=n(async _=>{const f=await Ve.create({credentials:new dn,modelsPath:Te(_.agentDir,"models.json")});ln(f);const y=await t.createAgentSessionServices({cwd:_.cwd,agentDir:_.agentDir,modelRuntime:f,resourceLoaderOptions:{additionalExtensionPaths:o.extensionPaths,appendSystemPrompt:o.appendSystemPromptPath!==void 0?[o.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:n(P=>({...P,extensions:P.extensions.filter(E=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(E.path))}),"extensionsOverride")}}),b=y.resourceLoader.getExtensions();if(o.extensionPaths.some(P=>re.includes(P))){const P=new Set(b.extensions.map(R=>R.path)),E=re.filter(R=>!P.has(R));if(E.length>0){const R=b.errors.filter(D=>re.includes(D.path)).map(D=>`${D.path}: ${D.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${E.join(", ")}${R===""?"":` (${R})`}`)}}y.settingsManager.getRetryEnabled=()=>!1;const x=await ot(y,o),V=x?.model,U=x?.thinkingLevel,A=x===void 0?st(y.modelRuntime):void 0,ae=A!==void 0?{...y,modelRuntime:A.runtime}:y,G=await t.createAgentSessionFromServices({services:ae,sessionManager:_.sessionManager,model:V,thinkingLevel:U,...tt(o.tools,Le()),sessionStartEvent:_.sessionStartEvent});return Bn(G.session),an(G.session),A?.reveal(),{...G,services:y}},"buildForManager"),s=o.resumeSessionPath,a=o.forkFrom!==void 0&&o.forkFrom!=="";if(!a&&(s===void 0||s==="")&&o.resumeSessionId!==void 0&&o.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${o.resumeSessionId}' (pi_session_file was never captured for this node)`);const l=!a&&s!==void 0&&s!=="",d=l&&o.newCycle===!0,p=l&&!d;let S;if(a)S=await t.SessionManager.forkFrom(o.forkFrom,o.cwd);else if(p||d){if(S=await t.SessionManager.open(s),d){const _=S.getLeafId();S.resetLeaf(),S.appendCustomEntry(vn,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:_})}}else S=await t.SessionManager.create(o.cwd);if(t.createAgentSessionRuntime!==void 0){const _=n(async y=>{const b=await u({cwd:y.cwd,agentDir:y.agentDir,sessionManager:y.sessionManager,sessionStartEvent:y.sessionStartEvent});return{...b,diagnostics:b.services.diagnostics??[]}},"factory"),f=await t.createAgentSessionRuntime(_,{cwd:o.cwd,agentDir:i,sessionManager:S});return{session:f.session,services:f.services,resuming:p,runtime:f}}const k=await u({cwd:o.cwd,agentDir:i,sessionManager:S});return{session:k.session,services:k.services,resuming:p,runtime:void 0}}n(it,"buildBrokerSession");function at(t){const o=n((s,a,l,d)=>{if(d?.signal?.aborted)return Promise.resolve(s);const p=t.writable();return p.length===0?Promise.resolve(s):new Promise(S=>{let k;const _=n(()=>{k!==void 0&&clearTimeout(k),d?.signal?.removeEventListener("abort",f),t.pending.delete(a.id)},"cleanup"),f=n(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(s)},"onAbort");d?.signal?.addEventListener("abort",f,{once:!0});const y=d?.timeout!==void 0?d.timeout:et;k=setTimeout(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(s)},y),typeof k.unref=="function"&&k.unref(),t.pending.set(a.id,{request:a,resolve:n(b=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(l(b))},"resolve")});for(const b of p)t.forward(b,a)})},"dialogPromise"),i=n(()=>{},"noop");return{[pn]:t.onKnownStreamWait??(s=>()=>{}),get theme(){const s=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(s==null)throw new Error("Theme not initialized. Call initTheme() first.");return s},select:n((s,a,l)=>o(void 0,{type:"extension_ui_request",id:M(),method:"select",title:s,options:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"select"),confirm:n((s,a,l)=>o(!1,{type:"extension_ui_request",id:M(),method:"confirm",title:s,message:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?!1:"confirmed"in d?d.confirmed:!1,l),"confirm"),input:n((s,a,l)=>o(void 0,{type:"extension_ui_request",id:M(),method:"input",title:s,placeholder:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"input"),editor:n((s,a)=>o(void 0,{type:"extension_ui_request",id:M(),method:"editor",title:s,prefill:a},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0),"editor"),setStatus:n((s,a)=>t.broadcast({type:"extension_ui_request",id:M(),method:"setStatus",statusKey:s,statusText:a}),"setStatus"),setWidget:n((s,a,l)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:M(),method:"setWidget",widgetKey:s,widgetLines:a,widgetPlacement:l?.placement})},"setWidget"),setTitle:n(s=>t.broadcast({type:"extension_ui_request",id:M(),method:"setTitle",title:s}),"setTitle"),notify:n((s,a)=>{const l=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:M(),method:"notify",message:s,notifyType:l})},"notify"),onTerminalInput:n(()=>i,"onTerminalInput"),setWorkingMessage:i,setWorkingVisible:i,setWorkingIndicator:i,setHiddenThinkingLabel:i,setFooter:i,setHeader:i,custom:n(()=>Promise.resolve(void 0),"custom"),pasteToEditor:i,setEditorText:i,getEditorText:n(()=>"","getEditorText"),addAutocompleteProvider:i,setEditorComponent:i,getEditorComponent:n(()=>{},"getEditorComponent"),getAllThemes:n(()=>[],"getAllThemes"),getTheme:n(()=>{},"getTheme"),setTheme:i,getToolsExpanded:n(()=>!1,"getToolsExpanded"),setToolsExpanded:i}}n(at,"makeBrokerUiContext");export{gr as REVIEW_BOUNDARY_NAVIGATION_CODE,pr as ReviewBoundaryNavigationError,tt as brokerToolOptions,it as buildBrokerSession,nt as disposeActiveSession,at as makeBrokerUiContext,mr as runBroker,ie as snapshotMessages};
@@ -110,6 +110,8 @@ export interface SpawnNodeOpts {
110
110
  isolated?: boolean;
111
111
  /** Run identity set on an app root; managed children inherit it. */
112
112
  run?: Pick<NodeMeta, 'grantee' | 'sub' | 'grant_id' | 'client_id' | 'metadata_json' | 'run_id' | 'event_cursor' | 'usage_json'>;
113
+ /** What caused this run, stored on its root node (`run.start`'s `Crtr-Caused-By`). */
114
+ causedBy?: string;
113
115
  /** Additional rows committed atomically with the newborn node. */
114
116
  withinCreate?: (db: CanvasDb, row: NodeMeta) => Promise<void> | void;
115
117
  /** Managed worktree already created for this node, if any. */