@north-light/cli 0.3.588 → 0.3.590

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 (80) hide show
  1. package/dist/api/client.d.ts +4 -1
  2. package/dist/api/client.js +1 -1
  3. package/dist/api/contract.d.ts +1 -1
  4. package/dist/api/contract.js +1 -1
  5. package/dist/api/dto/docs.d.ts +5 -0
  6. package/dist/api/dto/settings.d.ts +21 -0
  7. package/dist/build-root.d.ts +2 -0
  8. package/dist/build-root.js +1 -1
  9. package/dist/cli.js +8 -8
  10. package/dist/clients/attach/viewer.js +505 -505
  11. package/dist/commands/pkg/app-installs.d.ts +53 -0
  12. package/dist/commands/pkg/app-installs.js +2 -0
  13. package/dist/commands/pkg/market-inspect.js +1 -1
  14. package/dist/commands/pkg/market-manage.js +1 -1
  15. package/dist/commands/pkg/plugin-inspect.js +1 -1
  16. package/dist/commands/pkg/plugin-manage.js +13 -13
  17. package/dist/core/canvas/schema-pg/011-package-revision.sql +12 -0
  18. package/dist/core/canvas/schema-version.d.ts +1 -1
  19. package/dist/core/canvas/schema-version.js +1 -1
  20. package/dist/core/config.d.ts +1 -0
  21. package/dist/core/config.js +1 -1
  22. package/dist/core/graph/names.js +8 -8
  23. package/dist/core/graph/package-docs.d.ts +6 -15
  24. package/dist/core/graph/package-docs.js +8 -6
  25. package/dist/core/graph/package-publish.d.ts +35 -5
  26. package/dist/core/graph/package-publish.js +3 -3
  27. package/dist/core/graph/package-reconcile.d.ts +20 -1
  28. package/dist/core/graph/package-reconcile.js +3 -1
  29. package/dist/core/import/export/dump.js +4 -3
  30. package/dist/core/import/load/stores.js +2 -2
  31. package/dist/core/installed-plugins.js +1 -1
  32. package/dist/core/packages/directory-sync.d.ts +41 -0
  33. package/dist/core/packages/directory-sync.js +6 -0
  34. package/dist/core/packages/eligibility.d.ts +16 -0
  35. package/dist/core/packages/eligibility.js +4 -0
  36. package/dist/core/packages/launch-kinds.d.ts +6 -0
  37. package/dist/core/packages/launch-kinds.js +2 -0
  38. package/dist/core/packages/source-url.d.ts +3 -0
  39. package/dist/core/packages/source-url.js +1 -0
  40. package/dist/core/permissions/ceiling.d.ts +9 -2
  41. package/dist/core/permissions/ceiling.js +11 -12
  42. package/dist/core/permissions/evaluator.js +2 -2
  43. package/dist/core/runtime/launch-config-worker.js +1 -1
  44. package/dist/core/runtime/launch-target.d.ts +6 -2
  45. package/dist/core/runtime/launch-target.js +1 -1
  46. package/dist/core/runtime/launch.d.ts +8 -1
  47. package/dist/core/runtime/launch.js +2 -2
  48. package/dist/core/runtime/promote.js +1 -1
  49. package/dist/core/runtime/recycle.js +1 -1
  50. package/dist/core/runtime/reset.js +1 -1
  51. package/dist/core/runtime/runner/blaxel/runner.js +3 -3
  52. package/dist/core/runtime/runner/types.d.ts +7 -1
  53. package/dist/core/runtime/spawn.js +2 -2
  54. package/dist/core/runtime/view-socket.d.ts +2 -1
  55. package/dist/core/runtime/view-socket.js +2 -1
  56. package/dist/core/runtime/warm-pool.js +1 -1
  57. package/dist/core/scoped-state/legacy-profiles.js +1 -1
  58. package/dist/core/scoped-state/migrate-app-installs.d.ts +13 -0
  59. package/dist/core/scoped-state/migrate-app-installs.js +1 -0
  60. package/dist/core/scoped-state/person-rows.js +4 -6
  61. package/dist/core/scoped-state/person-store.d.ts +23 -0
  62. package/dist/core/scoped-state/person-store.js +1 -1
  63. package/dist/daemon/api/bridge.js +3 -3
  64. package/dist/daemon/api/handlers/execution-start.d.ts +2 -0
  65. package/dist/daemon/api/handlers/execution-start.js +2 -2
  66. package/dist/daemon/api/handlers/nodes.js +1 -1
  67. package/dist/daemon/api/handlers/package-docs.d.ts +1 -1
  68. package/dist/daemon/api/handlers/package-docs.js +1 -1
  69. package/dist/daemon/api/handlers/settings.d.ts +4 -1
  70. package/dist/daemon/api/handlers/settings.js +1 -1
  71. package/dist/daemon/crtrd.js +19 -19
  72. package/dist/daemon/reconcilers/node-lifecycle/remote-wake.d.ts +2 -1
  73. package/dist/daemon/reconcilers/node-lifecycle/remote-wake.js +1 -1
  74. package/package.json +2 -2
  75. package/packages/crouter-identity/package.json +1 -1
  76. package/runtime.lock.json +13 -13
  77. package/dist/core/graph/package-kinds.d.ts +0 -22
  78. package/dist/core/graph/package-kinds.js +0 -1
  79. package/dist/core/scoped-state/materialized-plugins.d.ts +0 -20
  80. package/dist/core/scoped-state/materialized-plugins.js +0 -1
@@ -1 +1 @@
1
- var $e=Object.defineProperty;var s=(e,n)=>$e(e,"name",{value:n,configurable:!0});import{envProfileId as Ne}from"../../../shared/env.js";import{pausedCanvasProfiles as Ce}from"../../../core/profiles/manifest.js";import{existsSync as C,realpathSync as ee,statSync as ne}from"node:fs";import{isAbsolute as x,resolve as D}from"node:path";import{appendSituationalContext as Ee,formatSituationalProse as Te}from"../../../core/runtime/situational-context.js";import{closeNode as Pe}from"../../../core/runtime/close.js";import{reviveNode as De}from"../../../core/runtime/revive.js";import{nowIso as K}from"../../../core/fs-utils.js";import{appPaidLaunch as Le,assertLaunchModelRegistered as V,forkNode as je,resolveForkSource as te,spawnChildPrepared as Me}from"../../../core/runtime/spawn.js";import{forkSourceNode as ie,newNodeId as re}from"../../../core/runtime/nodes.js";import{abandonCreateRequest as oe,childrenOf as Ge,completeCreateRequest as ae,findCreateRequest as de,getNode as R,recordCreateRequestNode as Fe,reserveCreateRequest as se,reserveCreateRequestNode as Be,listNodes as xe,recordRespawnAttempt as Ke,subscribersOf as Ve,subscriptionsOf as le,updateNode as E}from"../../../core/canvas/canvas.js";import{armControllerWait as We}from"../../../core/canvas/waits.js";import{withCanvasWrite as W}from"../../../core/canvas/db.js";import{markNodeRead as ze}from"../../../core/canvas/recovery.js";import{nodeObject as Je}from"../../../core/graph/objects.js";import{recordActedOn as Ue}from"../../../core/graph/edges.js";import{publish as Ye}from"../../../core/graph/events.js";import{readerFor as He}from"../reader.js";import{relocateSessionCwd as Qe,unbindSession as Xe}from"../../../core/canvas/sessions.js";import{ticketCountsForNodes as Ze}from"../../../core/canvas/attention.js";import{isSafeNodeId as qe}from"../../../core/canvas/paths.js";import{contextDir as ce,nodeAgentDir as z}from"../../../core/canvas/node-agent-paths.js";import{checkCronBirth as en,cronRefusalError as nn}from"../../cron/authority.js";import{cronBirthPlacement as tn}from"../../cron/armed-context.js";import{existsBeneath as rn,isAbsentOrRefused as on,isBeneathRefusal as an,readdirBeneath as dn}from"../../../core/spaces/open-beneath.js";import{readNodeMessagesPage as sn,readNodeSession as ln,readNodeSnapshot as cn,transcriptMarkdown as un}from"../../../core/runtime/node-read.js";import{assembleNodeSubject as fn}from"../../../core/substrate/subject.js";import{reviveAll as pn}from"../../../core/runtime/revive-all.js";import{promoteAsync as mn,requestYieldAsync as wn,reshapeNodeAsync as J}from"../../../core/runtime/promote.js";import{recycleNode as hn}from"../../../core/runtime/recycle.js";import{relaunchRoot as yn}from"../../../core/runtime/reset.js";import{assertReopenGate as _n}from"../../../core/runtime/reopen.js";import{requireCurrentExecution as gn}from"./broker-recovery.js";import{readOutputRequest as bn}from"../../../core/runtime/output-result.js";import{writeYieldMessage as vn,readGoal as kn,captureGoalIfAbsent as Sn}from"../../../core/runtime/kickoff.js";import{ensureRoadmap as Rn,hasRoadmap as In}from"../../../core/runtime/roadmap.js";import{renameWindow as On}from"../../../core/runtime/placement.js";import{buildLaunchSpecAsync as An,explicitModelIntent as $n,normalizeModel as Nn,readMergedLaunchConfigAsync as ue}from"../../../core/runtime/launch.js";import{modelRequestFromConfig as Cn}from"../../../core/model-routes.js";import{persistDormantModel as En,setModelLive as Tn}from"../../../core/runtime/model-swap.js";import{waitForBrokerViewSocket as fe}from"../../../core/runtime/view-socket.js";import{BrokerUnreachableError as Pn}from"../../../core/runtime/broker-request.js";import{boundFleet as L}from"../../../core/runtime/fleet.js";import{admitLegacyStructuredOutput as Dn}from"../../structured-requests/sidecar.js";import{assertOutputSchemaAccepted as Ln}from"../../../core/runtime/structured-output.js";import{OUTCOME_PAYLOAD_MAX_BYTES as pe}from"../../../core/canvas/types.js";import{HUMAN_ACTION_NAME_PATTERN as jn}from"../../../core/human/action-binding.js";import{resolveHumanAction as Mn}from"../../../core/human-actions.js";import{parseDurationMs as Gn}from"../../../core/wake.js";import{claimWarmNode as Fn,refillWarmPool as me,resumeWarmClaim as Bn,warmPoolEnabled as xn}from"../../../core/runtime/warm-pool.js";import{assertLaunchKind as U,isLaunchKind as Kn,resolveLaunchTarget as Vn}from"../../../core/runtime/launch-target.js";import{fullName as Wn}from"../../../core/canvas/labels.js";import{reportsForNode as we}from"./reports.js";import{requireUsableProfile as zn}from"./profiles.js";import{assertProfileActive as Jn,loadExactProfileManifest as Un}from"../../../core/profiles/manifest.js";import{getCron as he}from"../../../core/canvas/crons.js";import{cronWakeOrigin as Yn}from"../../../core/runtime/bearings.js";import{boundDaemonControl as Hn}from"../../control.js";import{notFound as T,usage as w}from"../../../core/errors.js";import{assertScope as Qn,validateScopes as ye}from"../../../core/scopes.js";import{scopeAllowed as O}from"../../../shared/env.js";import{toCloseResultDTO as Xn,toNodeDetailDTO as Y,toNodeSummaryDTO as Zn,toReviveResultDTO as qn}from"../map.js";import{ApiError as p}from"../../../api/index.js";import{InputError as y}from"../../../core/io.js";import{runsOnBlaxel as et}from"../environment-of.js";import{actsAsPerson as j,canReadNode as $,mayOnNode as nt,readableNodeIds as tt,resolvedScopes as it}from"../router.js";import{forwardVerb as rt,queryWithoutMachine as ot,relayError as at,unknownError as dt,withMachine as st}from"../../peer/forward.js";import{fileRoot as lt}from"../../../core/spaces/file-root.js";import{activeGrant as ct,payerOfGrant as ut}from"../../../core/grants/mirror.js";import{nodeTerminalGrant as ft}from"../../../core/grants/terminal.js";import{appRungForGrant as pt}from"../../../core/llm/app-rungs.js";import{APP_FAMILY as mt}from"../../../core/model-routes.js";import{listProfileEnvNames as wt}from"../../../core/profiles/env-store.js";import{hasConfiguredProviderCredential as ht,NO_PROVIDER_CREDENTIAL_MESSAGE as _e}from"../../../core/runtime/provider-credential-gate.js";import{filterAsync as yt,mapAsync as ge}from"../../../core/async-array.js";async function m(e){const n=await R(e);if(n===null)throw T(`unknown node: ${e}`,{received:e});return n}s(m,"requireMeta");async function H(e){return{subscribesTo:await le(e),subscribers:await Ve(e),children:await Ge(e)}}s(H,"edgesFor");async function b(e){const n=await m(e);return await Y(n,await H(e))}s(b,"detailOf");async function _t(e){let n=(await we(e)).length;try{n+=dn(await z(e),await ce(e)).length}catch(t){if(!on(t))throw t}return n}s(_t,"countFiles");function gt(e){if(typeof e!="object"||e===null)throw w("a node create requires a JSON body");const n=e;if(n.kind!==void 0&&(typeof n.kind!="string"||n.kind.trim()===""))throw w("kind must be a non-empty string when provided");if(n.description!==void 0&&(typeof n.description!="string"||n.description.trim()===""))throw w("description must be a non-empty string when provided");if(n.creator!==void 0&&(typeof n.creator!="string"||n.creator.trim()===""))throw w("creator must be a non-empty node id when provided");if(n.scopes!==void 0&&ye(n.scopes),n.isolated!==void 0&&typeof n.isolated!="boolean")throw new p(400,"invalid_request","isolated must be a boolean",{param:"isolated"});const t=n.root_lifecycle;if(t!==void 0&&t!=="resident"&&t!=="terminal")throw w("root_lifecycle must be 'resident' or 'terminal'");if(n.request_key!==void 0&&(typeof n.request_key!="string"||n.request_key.trim()===""||n.request_key.length>128))throw w("request_key must be a non-empty string of at most 128 characters when provided");return n}s(gt,"parseCreateBody");function bt(e){if(e===void 0)return;const n=Gn(e),t=n===null?null:new Date(Date.now()+n);if(n===null||!Number.isFinite(n)||n<=0||t===null||!Number.isFinite(t.getTime()))throw new p(422,"invalid_deadline","`deadline` must be a positive representable duration");return t.toISOString()}s(bt,"parseDeadline");function vt(e){if(e!==void 0){if(typeof e!="object"||e===null||Array.isArray(e))throw new p(400,"invalid_request","`outcome_delivery` must be an object");if(typeof e.action!="string"||!jn.test(e.action))throw new p(400,"invalid_request","`outcome_delivery.action` must be a declared action name");if(e.payload!==void 0){let n;try{n=JSON.stringify(e.payload)}catch{throw new p(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable")}if(n===void 0)throw new p(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable");if(Buffer.byteLength(n,"utf8")>pe)throw new p(413,"payload_too_large",`serialized payload exceeds ${pe} bytes`)}return e}}s(vt,"parseOutcomeDelivery");function kt(e,n){const t=Mn(e.action,n);if(!("kind"in t))return{actionName:e.action,argv:t.argv,cwd:t.cwd,configOrigin:t.configOrigin,...e.payload===void 0?{}:{payload:e.payload}};throw t.kind==="unknown_action"?new p(422,"unknown_action",`no action named ${e.action} is declared from ${n}`):new p(422,"invalid_action",`${e.action} is declared in ${t.configOrigin} but unusable: ${t.reason}`,{reason:t.reason,configOrigin:t.configOrigin})}s(kt,"resolveOutcomeDelivery");function St(e,n,t){const r={kind:e.kind,cwd:t,prompt:e.prompt??""};return e.mode!==void 0&&(r.mode=e.mode),e.name!==void 0&&(r.name=e.name),e.description!==void 0&&(r.description=e.description),n!==void 0&&(r.parent=n),e.creator!==void 0&&(r.creator=e.creator),e.scopes!==void 0&&(r.scopes=e.scopes),e.isolated!==void 0&&(r.isolated=e.isolated),e.root===!0&&(r.root=!0),e.root_lifecycle!==void 0&&(r.rootLifecycle=e.root_lifecycle),(e.worktree===!0||typeof e.worktree=="string")&&(r.worktree=!0),typeof e.worktree=="string"&&(r.worktreeBase=e.worktree),e.worktree!==void 0&&(r.worktreeCwd=D(e.pin_cwd??e.cwd??t)),e.fork_from!==void 0&&(r.forkFrom=e.fork_from),e.model!==void 0&&(r.model=e.model),e.profile!==void 0&&(r.profile=e.profile),e.situational_context!==void 0&&(r.situationalContext=e.situational_context),e.node_id!==void 0&&(r.nodeId=e.node_id),r}s(St,"buildRecipe");function Rt(e,n,t){return!xn()||e.prefer_warm!==!0||e.root!==!0||e.parent!=null||e.root_lifecycle==="terminal"||(e.prompt??"")!==""||e.model!==void 0||e.fork_from!==void 0||e.worktree!==void 0||e.node_id!==void 0||e.scopes!==void 0||e.isolated!==void 0?null:{kind:e.kind,mode:e.mode??"base",cwd:n,profileId:t,model:e.model??null,situationalContext:e.situational_context??null,name:e.name??null,creator:e.creator??null}}s(Rt,"warmRequestFor");import{resolveCreateKind as Nr}from"../../../core/runtime/launch-target.js";function be(e){const n=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return Cn(e.model,n,e.modelExact===!0)}s(be,"requestFromLaunch");function It(e,n){if(n===null)return e;if(e.scopes===void 0)return{...e,scopes:[...n]};const t=e.scopes.filter(r=>!O(n,r));if(t.length===0)return e;throw new p(403,"scope_denied",`scopes exceed the bearer token's ceiling: ${t.join(", ")}`,{scopes:t,ceiling:n})}s(It,"withinCeiling");async function ve(e,n,t){const r=(await An(n.kind,n.mode,{lifecycle:n.lifecycle,hasManager:e.parent!==null,model:n.model,modelOverride:!0,cwd:e.cwd,profileId:e.profile_id??null})).launch;await V(be(r),{cwd:e.cwd,profileId:e.profile_id??null},t)}s(ve,"assertNodeModelChangeRegistered");async function ke(e,n){const t=e.principal;if(t.class!=="broker"&&t.class!=="cron")return;const r=lt({app:t.app,resolved:await it(t),launched:t.scopes},n,"read");if("root"in r)return;const i="missing"in r?r.missing:null;throw new p(403,"scope_missing",i?`the child's directory ${n} needs missing scope ${i}`:`no permission of this run names the child's directory ${n}`,void 0,void 0,i?{scope:i}:void 0)}s(ke,"assertCallerReaches");const Q=new Map;async function Ot(e,n={},t={}){const r=It(gt(e.body),e.ceiling);if(e.principal.class==="broker"){const d=e.principal;if(r.prefer_warm===!0&&d.app!=="app:terminal"&&(r.prefer_warm=!1),r.parent!=null){const o=await m(r.parent);if(o.grantee!==d.app)throw new p(403,"other_app_run","cannot create a child under another app's node");if(!await $(d,o.grantee??"app:terminal",r.parent))throw T(`unknown node: ${r.parent}`,{received:r.parent})}if(r.creator!==void 0&&r.creator!==d.node)throw new p(403,"other_app_run","cannot create for another node");if(r.fork_from!==void 0){let o=null;try{o=await ie(await te(r.fork_from))}catch{}if(o?.grantee!==d.app||!await $(d,o.grantee,o.node_id))throw new p(403,"other_app_run","cannot fork another app's conversation")}r.creator=d.node}if(e.principal.class==="person"&&e.principal.sub!==void 0){const d=r.fork_from===void 0?null:await ie(await te(r.fork_from)).catch(()=>null);for(const o of[r.parent,r.creator,d?.node_id])if(o!=null&&await R(o)!==null&&!await nt(e.principal,"edit",o))throw T(`unknown node: ${o}`,{received:o})}if(e.principal.class==="cron"){const d=e.principal;for(const l of["parent","creator","fork_from","node_id"])if(r[l]!=null)throw new p(403,"permission_error",`a cron cannot set ${l} on a node it starts`);r.prefer_warm=!1,r.node_id=await re(),d.isolated&&(r.isolated=!0,r.cwd=await z(r.node_id,d.app));const o=await en({grantee:d.app,sub:d.sub,grant_id:d.grant,scopes:d.scopes,from_exec:d.from_exec},{profile:r.profile,cwd:r.cwd,pin_cwd:r.pin_cwd,kind:r.kind,model:r.model,mode:r.mode});if(!o.allowed)throw nn(o);if(r.scopes!==void 0){const l=r.scopes.find(f=>!O(o.effectiveScopes,f)||!O(d.scopes,f));if(l!==void 0)throw new p(403,"scope_missing",`scope ${l} is not held by this cron`,void 0,void 0,{scope:l})}else d.scopes!==null&&(r.scopes=[...d.scopes])}r.creator!==void 0&&Qn(await m(r.creator),"crtr:act");const i=r.request_key?.trim();if(i===void 0||r.node_id!==void 0&&qe(r.node_id)&&await R(r.node_id)!==null&&(await de(i))?.nodeId!==r.node_id)return M(e,r,n,t);const a=Q.get(i);if(a!==void 0)return a;const u=$t(e,r,i,n,t);Q.set(i,u);try{return await u}finally{Q.delete(i)}}s(Ot,"handleCreate");const Se="create_request_in_progress";async function At(e,n,t){const r=Date.now()+1e4;for(;t!==null;){const i=await R(t);if(i!==null){if(!j(e.principal)&&!await $(e.principal,i.grantee??"app:terminal",t))throw new p(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:await b(t)}}if(Date.now()>=r||(await de(n))?.nodeId!==t)break;await new Promise(a=>setTimeout(a,100))}throw new p(409,Se,"another create with this request_key is in progress; retry it")}s(At,"awaitForeignCreate");async function $t(e,n,t,r,i){const a=await se(t);if(a.nodeId!==null&&await R(a.nodeId)!==null){if(a.state!=="warm_claimed"){const u=await R(a.nodeId);if(!j(e.principal)&&!await $(e.principal,u.grantee??"app:terminal",a.nodeId))throw new p(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:await b(a.nodeId)}}return M(e,n,r,i,a)}try{return await M(e,n,r,i,a)}catch(u){if(u instanceof p&&u.code===Se)throw u;const d=await se(t);throw(d.nodeId===null||await R(d.nodeId)===null)&&await oe(t,d.nodeId),u}}s($t,"handleKeyedCreateRequest");async function M(e,n,t,r,i=void 0){const a=r.deadlineAt??bt(n.deadline),u=vt(n.outcome_delivery),d=e.principal.class==="cron"?await tn({grantee:e.principal.app,sub:e.principal.sub,grant_id:e.principal.grant,scopes:e.principal.scopes,cron_id:e.principal.cron,origin_run_id:e.principal.origin_run,isolated:e.principal.isolated,creator:e.principal.kind==="exec"?null:(await he(e.principal.cron))?.created_by??null},n.node_id):null;d!==null&&(n.root=d.root===!0);const o=d?.parent??n.parent??void 0;if(o==null&&n.root!==!0)throw w("a node create requires a parent (or root: true for an independent root)");let l=null;if(n.output_schema!==void 0){try{l=JSON.parse(n.output_schema)}catch{throw w("output_schema must be a JSON schema string")}if(l===null||typeof l!="object"||Array.isArray(l))throw w("output_schema must be a JSON schema object");await Ln(l)}const{profileId:f,kind:h,cwd:c,launch:S}=await Vn(n,{validateKind:Ae});if(n.pin_cwd!==void 0&&n.pin_cwd!==""&&n.worktree===void 0&&n.isolated!==!0&&!C(c)&&!await et(f))throw new y({error:"cwd_missing",message:`cwd is not an existing directory: ${c}`,received:c,field:"cwd",next:"Pass an existing directory with --cwd."});await ke(e,c),n.worktree!==void 0&&await ke(e,D(n.pin_cwd??n.cwd??c));const _={...n,kind:h},v=u===void 0?void 0:kt(u,c),Z=("grant"in e.principal?e.principal.grant:null)??(o==null?null:(await R(o))?.grant_id??null);if(await V(be(await Le(S,Z,n.model)),{cwd:c,profileId:f},t.modelRegistry),await ut(Z)!=="app"&&!await ht(f===null?[]:await wt(f)))throw new p(412,"no_provider_credential",_e,{error:"no_provider_credential",message:_e,next:"The person running this runtime logs a provider in with `crtr sys setup`, or stores a provider key on the profile."});let F=null;{const A=i===void 0||i.nodeId===null||i.state==="warm_claimed"?Rt(_,c,f):null,B=l===null&&r.beforeBrokerLaunch===void 0?void 0:async g=>{l!==null&&await Dn(g,"terminal",l),r.beforeBrokerLaunch?.(g)};if(i?.state==="warm_claimed"&&i.nodeId!==null){const g=A===null?null:await Bn(A,i.nodeId,B);if(g===null)throw await oe(i.requestKey,i.nodeId),new p(503,"create_resume_failed",`could not resume warm claim ${i.nodeId}; retry the create`);return await ae(i.requestKey,g),{status:201,body:await b(g)}}if(A!==null){const g=await Fn(A,{...a===void 0?{}:{deadlineAt:a},...v===void 0?{}:{outcomeDelivery:v},...i===void 0?{}:{requestKey:i.requestKey}},B);if(g!==null)return i!==void 0&&await ae(i.requestKey,g),me(A),{status:201,body:await b(g)};F=A}const P=i?.nodeId??n.node_id??(i===void 0?void 0:await re());if(i!==void 0&&i.nodeId===null){const g=await Be(i.requestKey,P);if(g!==P)return await At(e,i.requestKey,g)}const I=St(P===void 0?_:{..._,node_id:P},o,c);d!==null&&(d.rootLifecycle!==void 0&&(I.rootLifecycle=d.rootLifecycle),d.scopes!==void 0&&_.scopes===void 0&&(I.scopes=d.scopes),d.run!==void 0&&(I.run=d.run),d.withinCreate!==void 0&&(I.withinCreate=d.withinCreate)),a!==void 0&&(I.deadlineAt=a),v!==void 0&&(I.outcomeDelivery=v),I.readiness=n.root===!0?"await":"launch";const q=await Me(I,B,()=>{F!==null&&me(F)});return i!==void 0&&await Fe(i.requestKey,q.node.node_id),{status:201,body:await b(q.node.node_id)}}}s(M,"handleCreateRequest");function k(e,n){const t=e.query.getAll(n);if(t.length>1)throw w(`${n} must appear at most once`);return t[0]}s(k,"singleQueryValue");function X(e,n){if(e!==void 0){if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;throw w(`${n} must be true or false`)}}s(X,"optionalBoolean");function G(e,n,t){if(e!==void 0){if(t.includes(e))return e;throw w(`${n} must be one of: ${t.join(", ")}`)}}s(G,"oneOf");function Nt(e){const n=new Set(["status","lifecycle","kind","mode","profile_id","profile_prefix","parent","top_level","under","under_inclusive","hanging","include"]);for(const[_]of e.query)if(!n.has(_))throw w(`unknown nodes query parameter: ${_}`);const t=G(k(e,"status"),"status",["active","idle","done","dead","canceled"]),r=G(k(e,"lifecycle"),"lifecycle",["terminal","resident"]),i=k(e,"kind"),a=G(k(e,"mode"),"mode",["base","orchestrator"]),u=k(e,"profile_id"),d=k(e,"profile_prefix"),o=k(e,"parent"),l=X(k(e,"top_level"),"top_level"),f=k(e,"under"),h=X(k(e,"under_inclusive"),"under_inclusive"),c=X(k(e,"hanging"),"hanging"),S=G(k(e,"include"),"include",["activity"]);if(o!==void 0&&l===!0)throw w("parent and top_level=true cannot be combined");return{...t!==void 0?{status:t}:{},...r!==void 0?{lifecycle:r}:{},...i!==void 0?{kind:i}:{},...a!==void 0?{mode:a}:{},...u!==void 0?{profile_id:u}:{},...d!==void 0?{profile_prefix:d}:{},...o!==void 0?{parent:o}:{},...l!==void 0?{top_level:l}:{},...f!==void 0?{under:f}:{},...h!==void 0?{under_inclusive:h}:{},...c!==void 0?{hanging:c}:{},...S!==void 0?{include:S}:{}}}s(Nt,"parseListQuery");async function Ct(e){const n=Nt(e);let t=await xe({...n.status!==void 0?{status:n.status}:{},...n.lifecycle!==void 0?{lifecycle:n.lifecycle}:{},...n.kind!==void 0?{kind:n.kind}:{},...n.mode!==void 0?{mode:n.mode}:{},...n.profile_id!==void 0?{profileId:n.profile_id}:{},...n.profile_prefix!==void 0?{profilePrefix:n.profile_prefix}:{},...n.parent!==void 0?{parent:n.parent}:{},...n.top_level===!0?{topLevel:!0}:{},...n.under!==void 0?{under:n.under}:{},...n.under_inclusive===!0?{underInclusive:!0}:{},...n.hanging===!0?{hanging:!0}:{}});const r=await tt(e.principal);r!==null&&(t=t.filter(d=>r.has(d.node_id)));const i=n.include==="activity"?await Ze(t.map(d=>d.node_id)):null,a=t.length>0?Ce():new Set;return{status:200,body:await ge(t,async d=>{const o=await Zn(d,d.profile_id!==null&&a.has(d.profile_id));if(i!==null){const l=await we(d.node_id);o.activity={latest_report:l[0]??null,final_report:d.final_report===null?null:l.find(f=>f.name===d.final_report)??null,pending_human_count:i[d.node_id]??0}}return o})}}s(Ct,"handleList");async function Et(e){const n=e.params.id,t=await rt(e,n,{method:"GET",path:`/v1/nodes/${encodeURIComponent(n)}`,query:ot(e)});if(t.kind==="unknown")throw dt(n,t.unreachable);if(t.kind==="remote"){if(t.status>=400)throw at(t.status,t.body);return{status:t.status,body:st(t.body,t.machine)}}return await m(n),{status:200,body:await b(n)}}s(Et,"handleDetail");async function Tt(e){const n=e.params.id;await m(n);const t=await cn(n);return{status:200,body:{node_id:n,snapshot:{messages:t.snapshot.messages,...t.snapshot.messageIds===void 0?{}:{messageIds:t.snapshot.messageIds},messageVisibility:t.snapshot.messageVisibility,turnVisibility:t.snapshot.turnVisibility,stats:t.snapshot.stats,state:t.snapshot.state,display:t.snapshot.display,...t.snapshot.queued===void 0?{}:{queued:t.snapshot.queued},...t.snapshot.toolGroupSummaries===void 0?{}:{toolGroupSummaries:t.snapshot.toolGroupSummaries},...t.snapshot.turnReplies===void 0?{}:{turnReplies:t.snapshot.turnReplies},...t.snapshot.workingActivity===void 0?{}:{workingActivity:t.snapshot.workingActivity}},commands:t.commands.map(i=>({name:i.name,description:i.description,source:i.source})),captured_at:K()}}}s(Tt,"handleSnapshot");async function Pt(e){const n=e.params.id,t=await fn(n);if(t===null)throw T(`unknown node: ${n}`,{received:n});return{status:200,body:t}}s(Pt,"handleSubject");function Dt(e){for(const[a]of e.query)if(a!=="cursor"&&a!=="limit")throw w(`unknown messages query parameter: ${a}`);const n=e.query.getAll("cursor"),t=e.query.getAll("limit");if(n.length>1)throw w("cursor must appear at most once");if(t.length>1)throw w("limit must appear at most once");if(t.length===0)return n.length===0?{}:{cursor:n[0]};const r=t[0],i=Number(r);if(!Number.isSafeInteger(i)||r==="")throw w("limit must be an integer from 1 through 500");return n.length===0?{limit:i}:{cursor:n[0],limit:i}}s(Dt,"parseMessagesQuery");async function Lt(e){const n=e.params.id,t=await sn(n,Dt(e));return{status:200,body:{node_id:n,messages:t.messages,...t.messageIds===void 0?{}:{message_ids:t.messageIds},message_visibility:t.messageVisibility,next_cursor:t.nextCursor,captured_at:K()}}}s(Lt,"handleMessages");async function jt(e){const n=e.params.id;await m(n);const t=await ln(n);return{status:200,body:{node_id:n,session_file:t.sessionFile,session_jsonl:t.sessionJsonl,system_prompt:t.systemPrompt,captured_at:K()}}}s(jt,"handleSession");async function Mt(e){const n=e.params.id;return await m(n),{status:200,body:{node_id:n,markdown:await un(n)}}}s(Mt,"handleTranscript");async function Gt(e){const n=e.params.id;await m(n);const t=s(async(i,a)=>({node_id:i,label:(await R(i))?.name??i,dir:await ce(i),self:a,files:await _t(i)}),"root"),r=await yt([await t(n,!0),...await ge(await le(n),async i=>await t(i.node_id,!1))],async i=>await Ft(i.node_id,i.dir)||i.files>0);return{status:200,body:{node_id:n,roots:r}}}s(Gt,"handleContext");async function Ft(e,n){try{return rn(await z(e),n)}catch(t){if(an(t))return!1;throw t}}s(Ft,"hasDir");async function Bt(e){const n=await m(e.params.id),t=e.principal.class==="broker"?e.principal.scopes:e.ceiling,r=t===null?void 0:n.scopes==null?[...t]:[...new Set([...n.scopes.filter(a=>O(t,a)),...t.filter(a=>O(n.scopes,a))])],i=await je(n.node_id,r,e.principal.class==="broker"?e.principal.node:void 0);return{status:201,body:await b(i.node.node_id)}}s(Bt,"handleFork");const xt=1e4;async function Kt(e){const n=e.params.id;await m(n);const t=e.body,r=t?.resume??!0,i=t?.reopen??!1;await _n(n,i,e.principal.class==="broker"?e.principal.node:null);const a=!r&&t?.cron_id!==void 0?await he(t.cron_id):null,u=await De(n,{resume:r,capacity:"refuse",...a!==null?{wakeReason:await Yn(a,"schedule_revive")}:{}});u.outcome!=="already-live"&&await Ke(n,{failures:0,notBefore:null});const d=(await R(n))?.status??"active",o=(u.launch??L().get(n)?.handle)?.exited,l=u.outcome!=="frozen"&&await fe(n,o,xt);return{status:200,body:qn(n,u,d,l)}}s(Kt,"handleRevive");async function Vt(e){const n=e.params.id;return{status:200,body:{newNodeId:(await yn(n))?.newNodeId??null}}}s(Vt,"handleRelaunchRoot");async function Wt(e){const n=e.params.id;await m(n);const t=e.body;if(t?.caller_pid!==void 0&&(!Number.isInteger(t.caller_pid)||t.caller_pid<=0))throw w("caller_pid must be a positive integer when provided");const r=Hn(),i=new Promise(u=>{e.res.once("close",()=>u())}),a=await Pe(n,{teardownAfter:i,rootEvent:t?.finish===!0?"finish":"cancel",callerPid:t?.caller_pid,...e.principal.class==="broker"?{closer:e.principal.node}:{},...r===null?{}:{registerDetached:r.registerDetached}});return{status:200,body:Xn(a)}}s(Wt,"handleClose");async function zt(e){if(!j(e.principal))throw new p(403,"permission_error","only the person marks a conversation read");const n=e.params.id;return await m(n),await ze(n),{status:204}}s(zt,"handleMarkRead");async function Jt(e){const n=e.params.id;await m(n);const t=await hn(n);return{status:200,body:{recycled:t.recycled,finalized:t.finalized,new_root:t.newRoot,delivered:t.delivered}}}s(Jt,"handleRecycle");async function Ut(e){const n=e.params.id;return await m(n),await J(n,{lifecycle:"terminal"}),await N(e,n,["lifecycle"]),{status:200,body:await b(n)}}s(Ut,"handleDemote");async function Yt(e,n={}){const t=e.params.id,r=await m(t),i=e.body??{};i.kind!==void 0&&await U(i.kind,r.cwd,r.profile_id??null),i.model!==void 0&&await ve(r,{kind:i.kind??r.kind,mode:"orchestrator",lifecycle:i.resident===!0?"resident":r.lifecycle,model:i.model},n.modelRegistry);const a=await mn(t,{...i.kind!==void 0?{kind:i.kind}:{},...i.resident===!0?{resident:!0}:{},...i.model!==void 0?{model:i.model}:{}});await N(e,t,["mode",...i.kind!==void 0?["kind"]:[],...i.resident===!0?["lifecycle"]:[],...i.model!==void 0?["model"]:[]]);const u=await Y(a.meta,await H(t));return u.roadmap_written=a.roadmapWritten,u.roadmap_ref=a.roadmapRef,u.goal_path=a.goalPath,{status:200,body:u}}s(Yt,"handlePromote");async function Ht(e){const n=e.params.id;return await m(n),{status:200,body:{request:await bn(n)}}}s(Ht,"handleBrokerStructuredRequest");async function Qt(e){const n=e.params.id,t=e.body??{};if(await gn(n,t.expected_execution_id),typeof t.text!="string")throw new p(400,"invalid_request","text must be a string");return await m(n),{status:200,body:{captured:await Sn(n,t.text)}}}s(Qt,"handleBrokerGoal");async function Xt(e,n={}){const t=e.params.id,r=await m(t),i=e.body??{};i.kind!==void 0&&await U(i.kind,r.cwd,r.profile_id??null),i.model!==void 0&&await ve(r,{kind:i.kind??r.kind,mode:i.promote===!0?"orchestrator":r.mode,lifecycle:r.lifecycle,model:i.model},n.modelRegistry);const a=i.note??"Refresh: continue against your roadmap or goal.";await vn(t,a);const u=await wn(t,{...i.promote===!0?{promote:!0}:{},...i.kind!==void 0?{kind:i.kind}:{},...i.model!==void 0?{model:i.model}:{}});return{status:200,body:await Y(u.meta,await H(t))}}s(Xt,"handleYield");async function Zt(e){const n=e.params.id;await m(n);const t=e.body;if(t===void 0||typeof t.controller!="string"||t.controller.trim()==="")throw w("a wait requires a controller node id");const r=await R(t.controller);if(r===null)throw T(`unknown controller: ${t.controller}`,{received:t.controller});if(r.status!=="active"&&r.status!=="idle")throw new p(422,"unprocessable",`controller ${t.controller} is ${r.status}`);return await We(n,t.controller),{status:200,body:await b(n)}}s(Zt,"handleWait");async function qt(e){const n=e.principal,t=await pn(n.class==="broker"?async i=>i.grantee===n.app&&await $(n,i.grantee,i.node_id):n.class==="person"&&!j(n)?async i=>await $(n,i.grantee??"app:terminal",i.node_id):void 0);return{status:200,body:{revived:[...t.revived],failed:[...t.failed],frozen:[...t.frozen]}}}s(qt,"handleReviveAll");const ei=new Set(["interrupt","steer","after-turn","next-turn"]);function ni(e){if(e===null)return null;const n=s(r=>{throw new y({error:"invalid_listen",message:r,received:e,field:"listen",next:'Send an object mapping levels "1".."10" to interrupt|steer|after-turn|next-turn (e.g. {"3":"next-turn"}), or null to reset to the global default.'})},"bad");if(typeof e!="object"||Array.isArray(e))return n("listen must be an object or null");const t=Object.entries(e);if(t.length===0)return n("listen must name at least one level");for(const[r,i]of t)/^(?:[1-9]|10)$/.test(r)||n(`listen level must be 1..10: ${r}`),(typeof i!="string"||!ei.has(i))&&n(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(i)}`);return JSON.stringify(Object.fromEntries(t))}s(ni,"listenJson");async function N(e,n,t,r){t.length===0&&r===void 0||await W(async i=>{if(r?.(i),t.length===0)return;const a=await Je(i,n),u=await He(i,e),d=u.class==="person"?u.person:u.class==="app"?u.app:u.node;await Ue(i,d,a),await Ye(i,{event:"configured",object:a,actor:d,attrs:{changed:t.join(",")}})})}s(N,"recordConfigured");function Re(e){const n=L().get(e);if(n===void 0)return!1;try{return process.kill(n.pid,"SIGTERM"),!0}catch{return!1}}s(Re,"restartLiveBroker");function Ie(e,n){try{return ee(e)===ee(n)}catch{return!1}}s(Ie,"sameDirectory");async function ti(e,n={}){const t=e.params.id,r=e.body;let i;if(r===void 0)i={};else if(typeof r=="object"&&r!==null&&!Array.isArray(r))i=r;else throw new y({error:"cwd_invalid",message:"cwd repair requires a non-null object with a non-empty cwd string",received:r,field:"cwd",next:"Send a config patch with a non-empty absolute cwd string."});if(i.profile!==void 0){if(typeof i.profile!="string"||i.profile==="")throw new y({error:"profile_invalid",message:"profile must be a non-empty profile id or name",received:i.profile,field:"profile",next:"Send a profile id or exact name."});if(Object.keys(i).some(h=>h!=="profile"&&h!=="restart"&&i[h]!==void 0))throw new y({error:"profile_not_exclusive",message:"profile can only be combined with restart",field:"profile",next:"Send profile (and optionally restart) alone."});const o=await m(t),l=await zn(e,i.profile);Jn(l.profileId);const f=Un(l.profileId).manifest.grantee??"app:terminal";if(f!==(o.grantee??"app:terminal"))throw new y({error:"profile_grantee_mismatch",message:`profile ${l.profileId} belongs to ${f}, node ${t} to ${o.grantee}`,received:i.profile,field:"profile",next:"Pick a profile owned by the same app as the node."});return(o.profile_id??null)!==l.profileId&&(Kn(o.kind)?(await U(o.kind,o.cwd,l.profileId),await J(t,{profileId:l.profileId})):await E(t,{profile_id:l.profileId}),await N(e,t,["profile"])),i.restart===!0&&Re(t),{status:200,body:await b(t)}}if(Object.prototype.hasOwnProperty.call(i,"cwd")){const o=i.cwd;if(typeof o!="string"||o==="")throw new y({error:"cwd_invalid",message:"cwd must be a non-empty string",received:o,field:"cwd",next:"Send a non-empty absolute cwd string."});if(Object.keys(i).some(c=>c!=="cwd"&&c!=="keep_session"&&c!=="restart"&&i[c]!==void 0))throw new y({error:"cwd_not_exclusive",message:"cwd repair cannot be combined with another config field",received:i,field:"cwd",next:"Send cwd as the only config field."});const l=await m(t),f=C(l.cwd);if(i.keep_session===!0||f&&x(o)&&C(o)&&Ie(l.cwd,o)){if(!x(o))throw new y({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${o}`,received:o,field:"cwd",next:"Send an absolute path."});const c=D(o);let S=!1;try{S=ne(c).isDirectory()}catch{}if(!S)throw new y({error:"cwd_missing",message:`cwd is not an existing directory: ${c}`,received:o,field:"cwd",next:"Send an existing absolute directory."});if(f&&!Ie(l.cwd,c))throw new y({error:"cwd_not_same_directory",message:`${c} is not the same directory as the recorded ${l.cwd}; --keep-session only relocates an alias`,received:o,field:"cwd",next:"Drop --keep-session to repair a gone cwd, or pass the real path of the recorded directory."});if(l.managed_worktree?.state==="open")throw new y({error:"cwd_node_managed_worktree_open",message:`${t} owns an open managed worktree and cannot relocate its cwd`,received:o,field:"cwd",next:"Reconcile the managed worktree first."});const _=l.cwd;return _!==c&&(await W(async v=>{await E(t,{cwd:c}),await v.prepare("UPDATE crons SET cwd = ? WHERE anchor_node = ? AND cwd = ?").run(c,t,_),await Qe(t,_,c)}),await N(e,t,["cwd"])),i.restart===!0&&Re(t),{status:200,body:await b(t)}}if(await L().has(t)){const c=`${t} cannot repair its cwd while its broker is live`;throw new p(409,"cwd_node_live",c,{error:"cwd_node_live",message:c,received:o,field:"cwd",next:"Let the node become dormant, then retry the cwd repair."})}if(l.fork_from!=null)throw new y({error:"cwd_node_forked",message:`${t} is a fork and cannot repair its cwd; recorded cwd: ${l.cwd}`,received:o,field:"cwd",next:`Restore ${l.cwd}, then revive the fork normally.`});if(l.managed_worktree?.state==="open")throw new y({error:"cwd_node_managed_worktree_open",message:`${t} owns an open managed worktree and cannot repair its cwd`,received:o,field:"cwd",next:"Restore or reconcile the recorded checkout, then use the managed-worktree close or abandon flow."});if(C(l.cwd))throw new y({error:"cwd_still_present",message:`${t} recorded cwd still exists: ${l.cwd}; cwd repair is not a relocation command`,received:o,field:"cwd",next:"This command only repairs a node whose recorded cwd is gone."});if(!x(o))throw new y({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${o}`,received:o,field:"cwd",next:"Send an absolute path."});const h=D(o);if(!C(h))throw new y({error:"cwd_missing",message:`cwd does not exist: ${h}`,received:o,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."});try{if(!ne(h).isDirectory())throw new y({error:"cwd_not_a_directory",message:`cwd is not a directory: ${h}`,received:o,field:"cwd",next:"Send an existing absolute directory."})}catch(c){throw c instanceof y?c:new y({error:"cwd_missing",message:`cwd does not exist: ${h}`,received:o,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."})}return await W(async()=>{await E(t,{cwd:h}),await Xe(t)}),await N(e,t,["cwd"]),{status:200,body:await b(t)}}let a=await m(t);const u=i.listen===void 0?void 0:ni(i.listen);if(i.scopes!==void 0){const o=ye(i.scopes),l=a.grantee==="app:terminal"?await ft(a):a.grant_id?await ct(a.grant_id):null;if(!o.every(f=>O(a.scopes,f)&&l!==null&&O(l.resolved,f)))throw new y({error:"unknown_scope",message:"scopes may only narrow the node's current effective set",received:o,field:"scopes",next:"Send only scopes the node currently holds."});if(o.includes("crtr:act")&&!O(o,"crtr:llm"))throw new p(400,"invalid_scope","crtr:act requires crtr:llm");a=await E(t,{scopes:o})}if(i.situational_context!==void 0&&await Ee(t,Te(i.situational_context)),i.model!==void 0){const o=(await ue(a.cwd,a.profile_id??null)).modelLadders,l=$n(i.model,o),f=await pt(a.grant_id,i.model,l===void 0),h=f?{family:mt,strength:f.strength}:l,c=f?f.model:Nn(i.model,o);await V({kind:"concrete",spec:c},{cwd:a.cwd,profileId:a.profile_id??null},n.modelRegistry);const S=L();let _=!1;if(await S.isClaimed(t)&&await fe(t,S.get(t)?.handle.exited)&&(_=await Tn(t,c,h).then(()=>!0,v=>{if(v instanceof Pn)return!1;throw v})),!_){if(await S.isClaimed(t)){const v=`${t}'s broker did not accept the model switch; the model was not changed`;throw new p(409,"broker_not_ready",v,{error:"broker_not_ready",message:v,received:i.model,field:"model",next:"Check the node with `crtr node show`, then retry the model change."})}if(!c.includes("/"))throw w(`model must resolve to a provider/id spec: ${i.model}`);await En(t,c,h)}a=await m(t)}if(i.kind!==void 0||i.mode!==void 0||i.lifecycle!==void 0){i.kind!==void 0&&await Ae(i.kind);const o=i.kind??a.kind,l=i.mode??a.mode,f=i.lifecycle??a.lifecycle;let h;l==="orchestrator"&&!await In(t)&&(h=s(async()=>{const c=await kn(t);await Rn(t,c!==null&&c.trim()!==""?{goal:c.trim()}:{})},"beforePersist")),a=await J(t,{...i.kind!==void 0?{kind:o}:{},...i.mode!==void 0?{mode:l}:{},...i.lifecycle!==void 0?{lifecycle:f}:{}},h)}i.name!==void 0&&(a=await E(t,{name:i.name}),a.window&&On(a.window,Wn(a)));const d=["scopes","situational_context","model","kind","mode","lifecycle","name","listen"].filter(o=>i[o]!==void 0);return await N(e,t,d,u===void 0?void 0:async o=>{await o.prepare("UPDATE objects SET listen_json = ? WHERE id = ? AND type = 'node'").run(u,t)}),{status:200,body:await b(t)}}s(ti,"handleConfig");async function Oe(){return(await ue(process.cwd(),Ne()||null)).kinds}s(Oe,"daemonKinds");async function Ae(e){const n=Object.keys(await Oe());if(!n.includes(e))throw w(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${n.sort().join(", ")}.`})}s(Ae,"assertKindServer");async function ii(){const e=await Oe();return{status:200,body:{kinds:Object.keys(e).sort().map(t=>({kind:t,when_to_use:e[t]?.whenToUse??null,available_to:e[t]?.availableTo??null}))}}}s(ii,"handleListKinds");const Or=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:Ot},{method:"GET",pattern:"/v1/nodes",handler:Ct},{method:"GET",pattern:"/v1/kinds",handler:s(()=>ii(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:qt},{method:"GET",pattern:"/v1/nodes/:id",handler:Et},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:Tt},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:Pt},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:Lt},{method:"GET",pattern:"/v1/nodes/:id/session",handler:jt},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:Mt},{method:"GET",pattern:"/v1/nodes/:id/context",handler:Gt},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:Bt},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:Kt},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:Vt},{method:"POST",pattern:"/v1/nodes/:id/close",handler:Wt},{method:"POST",pattern:"/v1/nodes/:id/read",handler:zt},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:Jt},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:Ut},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:Yt},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Xt},{method:"GET",pattern:"/v1/nodes/:id/broker/structured-request",handler:Ht},{method:"POST",pattern:"/v1/nodes/:id/broker/goal",handler:Qt},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Zt},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:ti}];export{ti as handleConfig,Ot as handleCreate,Bt as handleFork,Ct as handleList,Yt as handlePromote,Xt as handleYield,Or as nodeRoutes,Nr as resolveCreateKind};
1
+ var $e=Object.defineProperty;var s=(e,n)=>$e(e,"name",{value:n,configurable:!0});import{envProfileId as Ne}from"../../../shared/env.js";import{pausedCanvasProfiles as Ce}from"../../../core/profiles/manifest.js";import{existsSync as C,realpathSync as ee,statSync as ne}from"node:fs";import{isAbsolute as K,resolve as D}from"node:path";import{appendSituationalContext as Ee,formatSituationalProse as Te}from"../../../core/runtime/situational-context.js";import{closeNode as Pe}from"../../../core/runtime/close.js";import{reviveNode as De}from"../../../core/runtime/revive.js";import{nowIso as x}from"../../../core/fs-utils.js";import{appPaidLaunch as Le,assertLaunchModelRegistered as V,forkNode as je,resolveForkSource as te,spawnChildPrepared as Me}from"../../../core/runtime/spawn.js";import{forkSourceNode as ie,newNodeId as re}from"../../../core/runtime/nodes.js";import{abandonCreateRequest as oe,childrenOf as Ge,completeCreateRequest as ae,findCreateRequest as de,getNode as R,recordCreateRequestNode as Fe,reserveCreateRequest as se,reserveCreateRequestNode as Be,listNodes as Ke,recordRespawnAttempt as xe,subscribersOf as Ve,subscriptionsOf as le,updateNode as E}from"../../../core/canvas/canvas.js";import{armControllerWait as We}from"../../../core/canvas/waits.js";import{withCanvasWrite as W}from"../../../core/canvas/db.js";import{markNodeRead as ze}from"../../../core/canvas/recovery.js";import{nodeObject as Je}from"../../../core/graph/objects.js";import{recordActedOn as Ue}from"../../../core/graph/edges.js";import{publish as Ye}from"../../../core/graph/events.js";import{readerFor as He}from"../reader.js";import{relocateSessionCwd as Qe,unbindSession as Xe}from"../../../core/canvas/sessions.js";import{ticketCountsForNodes as Ze}from"../../../core/canvas/attention.js";import{isSafeNodeId as qe}from"../../../core/canvas/paths.js";import{contextDir as ce,nodeAgentDir as z}from"../../../core/canvas/node-agent-paths.js";import{checkCronBirth as en,cronRefusalError as nn}from"../../cron/authority.js";import{cronBirthPlacement as tn}from"../../cron/armed-context.js";import{existsBeneath as rn,isAbsentOrRefused as on,isBeneathRefusal as an,readdirBeneath as dn}from"../../../core/spaces/open-beneath.js";import{readNodeMessagesPage as sn,readNodeSession as ln,readNodeSnapshot as cn,transcriptMarkdown as un}from"../../../core/runtime/node-read.js";import{assembleNodeSubject as fn}from"../../../core/substrate/subject.js";import{reviveAll as pn}from"../../../core/runtime/revive-all.js";import{promoteAsync as mn,requestYieldAsync as wn,reshapeNodeAsync as J}from"../../../core/runtime/promote.js";import{recycleNode as hn}from"../../../core/runtime/recycle.js";import{relaunchRoot as yn}from"../../../core/runtime/reset.js";import{assertReopenGate as _n}from"../../../core/runtime/reopen.js";import{requireCurrentExecution as gn}from"./broker-recovery.js";import{readOutputRequest as bn}from"../../../core/runtime/output-result.js";import{writeYieldMessage as vn,readGoal as kn,captureGoalIfAbsent as Sn}from"../../../core/runtime/kickoff.js";import{ensureRoadmap as Rn,hasRoadmap as In}from"../../../core/runtime/roadmap.js";import{renameWindow as On}from"../../../core/runtime/placement.js";import{buildLaunchSpecAsync as An,explicitModelIntent as $n,normalizeModel as Nn,readMergedLaunchConfigAsync as ue}from"../../../core/runtime/launch.js";import{modelRequestFromConfig as Cn}from"../../../core/model-routes.js";import{persistDormantModel as En,setModelLive as Tn}from"../../../core/runtime/model-swap.js";import{waitForBrokerViewSocket as fe}from"../../../core/runtime/view-socket.js";import{BrokerUnreachableError as Pn}from"../../../core/runtime/broker-request.js";import{boundFleet as L}from"../../../core/runtime/fleet.js";import{admitLegacyStructuredOutput as Dn}from"../../structured-requests/sidecar.js";import{assertOutputSchemaAccepted as Ln}from"../../../core/runtime/structured-output.js";import{OUTCOME_PAYLOAD_MAX_BYTES as pe}from"../../../core/canvas/types.js";import{HUMAN_ACTION_NAME_PATTERN as jn}from"../../../core/human/action-binding.js";import{resolveHumanAction as Mn}from"../../../core/human-actions.js";import{parseDurationMs as Gn}from"../../../core/wake.js";import{claimWarmNode as Fn,refillWarmPool as me,resumeWarmClaim as Bn,warmPoolEnabled as Kn}from"../../../core/runtime/warm-pool.js";import{assertLaunchKind as U,isLaunchKind as xn,resolveLaunchTarget as Vn}from"../../../core/runtime/launch-target.js";import{fullName as Wn}from"../../../core/canvas/labels.js";import{reportsForNode as we}from"./reports.js";import{requireUsableProfile as zn}from"./profiles.js";import{assertProfileActive as Jn,loadExactProfileManifest as Un}from"../../../core/profiles/manifest.js";import{getCron as he}from"../../../core/canvas/crons.js";import{cronWakeOrigin as Yn}from"../../../core/runtime/bearings.js";import{boundDaemonControl as Hn}from"../../control.js";import{notFound as T,usage as w}from"../../../core/errors.js";import{assertScope as Qn,validateScopes as ye}from"../../../core/scopes.js";import{scopeAllowed as O}from"../../../shared/env.js";import{toCloseResultDTO as Xn,toNodeDetailDTO as Y,toNodeSummaryDTO as Zn,toReviveResultDTO as qn}from"../map.js";import{ApiError as p}from"../../../api/index.js";import{InputError as y}from"../../../core/io.js";import{runsOnBlaxel as et}from"../environment-of.js";import{actsAsPerson as j,canReadNode as $,mayOnNode as nt,readableNodeIds as tt,resolvedScopes as it}from"../router.js";import{forwardVerb as rt,queryWithoutMachine as ot,relayError as at,unknownError as dt,withMachine as st}from"../../peer/forward.js";import{fileRoot as lt}from"../../../core/spaces/file-root.js";import{activeGrant as ct,payerOfGrant as ut}from"../../../core/grants/mirror.js";import{nodeTerminalGrant as ft}from"../../../core/grants/terminal.js";import{appRungForGrant as pt}from"../../../core/llm/app-rungs.js";import{APP_FAMILY as mt}from"../../../core/model-routes.js";import{listProfileEnvNames as wt}from"../../../core/profiles/env-store.js";import{hasConfiguredProviderCredential as ht,NO_PROVIDER_CREDENTIAL_MESSAGE as _e}from"../../../core/runtime/provider-credential-gate.js";import{filterAsync as yt,mapAsync as ge}from"../../../core/async-array.js";async function m(e){const n=await R(e);if(n===null)throw T(`unknown node: ${e}`,{received:e});return n}s(m,"requireMeta");async function H(e){return{subscribesTo:await le(e),subscribers:await Ve(e),children:await Ge(e)}}s(H,"edgesFor");async function b(e){const n=await m(e);return await Y(n,await H(e))}s(b,"detailOf");async function _t(e){let n=(await we(e)).length;try{n+=dn(await z(e),await ce(e)).length}catch(t){if(!on(t))throw t}return n}s(_t,"countFiles");function gt(e){if(typeof e!="object"||e===null)throw w("a node create requires a JSON body");const n=e;if(n.kind!==void 0&&(typeof n.kind!="string"||n.kind.trim()===""))throw w("kind must be a non-empty string when provided");if(n.description!==void 0&&(typeof n.description!="string"||n.description.trim()===""))throw w("description must be a non-empty string when provided");if(n.creator!==void 0&&(typeof n.creator!="string"||n.creator.trim()===""))throw w("creator must be a non-empty node id when provided");if(n.scopes!==void 0&&ye(n.scopes),n.isolated!==void 0&&typeof n.isolated!="boolean")throw new p(400,"invalid_request","isolated must be a boolean",{param:"isolated"});const t=n.root_lifecycle;if(t!==void 0&&t!=="resident"&&t!=="terminal")throw w("root_lifecycle must be 'resident' or 'terminal'");if(n.request_key!==void 0&&(typeof n.request_key!="string"||n.request_key.trim()===""||n.request_key.length>128))throw w("request_key must be a non-empty string of at most 128 characters when provided");return n}s(gt,"parseCreateBody");function bt(e){if(e===void 0)return;const n=Gn(e),t=n===null?null:new Date(Date.now()+n);if(n===null||!Number.isFinite(n)||n<=0||t===null||!Number.isFinite(t.getTime()))throw new p(422,"invalid_deadline","`deadline` must be a positive representable duration");return t.toISOString()}s(bt,"parseDeadline");function vt(e){if(e!==void 0){if(typeof e!="object"||e===null||Array.isArray(e))throw new p(400,"invalid_request","`outcome_delivery` must be an object");if(typeof e.action!="string"||!jn.test(e.action))throw new p(400,"invalid_request","`outcome_delivery.action` must be a declared action name");if(e.payload!==void 0){let n;try{n=JSON.stringify(e.payload)}catch{throw new p(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable")}if(n===void 0)throw new p(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable");if(Buffer.byteLength(n,"utf8")>pe)throw new p(413,"payload_too_large",`serialized payload exceeds ${pe} bytes`)}return e}}s(vt,"parseOutcomeDelivery");function kt(e,n){const t=Mn(e.action,n);if(!("kind"in t))return{actionName:e.action,argv:t.argv,cwd:t.cwd,configOrigin:t.configOrigin,...e.payload===void 0?{}:{payload:e.payload}};throw t.kind==="unknown_action"?new p(422,"unknown_action",`no action named ${e.action} is declared from ${n}`):new p(422,"invalid_action",`${e.action} is declared in ${t.configOrigin} but unusable: ${t.reason}`,{reason:t.reason,configOrigin:t.configOrigin})}s(kt,"resolveOutcomeDelivery");function St(e,n,t){const r={kind:e.kind,cwd:t,prompt:e.prompt??""};return e.mode!==void 0&&(r.mode=e.mode),e.name!==void 0&&(r.name=e.name),e.description!==void 0&&(r.description=e.description),n!==void 0&&(r.parent=n),e.creator!==void 0&&(r.creator=e.creator),e.scopes!==void 0&&(r.scopes=e.scopes),e.isolated!==void 0&&(r.isolated=e.isolated),e.root===!0&&(r.root=!0),e.root_lifecycle!==void 0&&(r.rootLifecycle=e.root_lifecycle),(e.worktree===!0||typeof e.worktree=="string")&&(r.worktree=!0),typeof e.worktree=="string"&&(r.worktreeBase=e.worktree),e.worktree!==void 0&&(r.worktreeCwd=D(e.pin_cwd??e.cwd??t)),e.fork_from!==void 0&&(r.forkFrom=e.fork_from),e.model!==void 0&&(r.model=e.model),e.profile!==void 0&&(r.profile=e.profile),e.situational_context!==void 0&&(r.situationalContext=e.situational_context),e.node_id!==void 0&&(r.nodeId=e.node_id),r}s(St,"buildRecipe");function Rt(e,n,t){return!Kn()||e.prefer_warm!==!0||e.root!==!0||e.parent!=null||e.root_lifecycle==="terminal"||(e.prompt??"")!==""||e.model!==void 0||e.fork_from!==void 0||e.worktree!==void 0||e.node_id!==void 0||e.scopes!==void 0||e.isolated!==void 0?null:{kind:e.kind,mode:e.mode??"base",cwd:n,profileId:t,model:e.model??null,situationalContext:e.situational_context??null,name:e.name??null,creator:e.creator??null}}s(Rt,"warmRequestFor");import{resolveCreateKind as Nr}from"../../../core/runtime/launch-target.js";function be(e){const n=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return Cn(e.model,n,e.modelExact===!0)}s(be,"requestFromLaunch");function It(e,n){if(n===null)return e;if(e.scopes===void 0)return{...e,scopes:[...n]};const t=e.scopes.filter(r=>!O(n,r));if(t.length===0)return e;throw new p(403,"scope_denied",`scopes exceed the bearer token's ceiling: ${t.join(", ")}`,{scopes:t,ceiling:n})}s(It,"withinCeiling");async function ve(e,n,t){const r=(await An(n.kind,n.mode,{lifecycle:n.lifecycle,hasManager:e.parent!==null,model:n.model,modelOverride:!0,cwd:e.cwd,profileId:e.profile_id??null,app:e.grantee??"app:terminal"})).launch;await V(be(r),{cwd:e.cwd,profileId:e.profile_id??null},t)}s(ve,"assertNodeModelChangeRegistered");async function ke(e,n){const t=e.principal;if(t.class!=="broker"&&t.class!=="cron")return;const r=lt({app:t.app,resolved:await it(t),launched:t.scopes},n,"read");if("root"in r)return;const i="missing"in r?r.missing:null;throw new p(403,"scope_missing",i?`the child's directory ${n} needs missing scope ${i}`:`no permission of this run names the child's directory ${n}`,void 0,void 0,i?{scope:i}:void 0)}s(ke,"assertCallerReaches");const Q=new Map;async function Ot(e,n={},t={}){const r=It(gt(e.body),e.ceiling);if(e.principal.class==="broker"){const d=e.principal;if(r.prefer_warm===!0&&d.app!=="app:terminal"&&(r.prefer_warm=!1),r.parent!=null){const o=await m(r.parent);if(o.grantee!==d.app)throw new p(403,"other_app_run","cannot create a child under another app's node");if(!await $(d,o.grantee??"app:terminal",r.parent))throw T(`unknown node: ${r.parent}`,{received:r.parent})}if(r.creator!==void 0&&r.creator!==d.node)throw new p(403,"other_app_run","cannot create for another node");if(r.fork_from!==void 0){let o=null;try{o=await ie(await te(r.fork_from))}catch{}if(o?.grantee!==d.app||!await $(d,o.grantee,o.node_id))throw new p(403,"other_app_run","cannot fork another app's conversation")}r.creator=d.node}if(e.principal.class==="person"&&e.principal.sub!==void 0){const d=r.fork_from===void 0?null:await ie(await te(r.fork_from)).catch(()=>null);for(const o of[r.parent,r.creator,d?.node_id])if(o!=null&&await R(o)!==null&&!await nt(e.principal,"edit",o))throw T(`unknown node: ${o}`,{received:o})}if(e.principal.class==="cron"){const d=e.principal;for(const l of["parent","creator","fork_from","node_id"])if(r[l]!=null)throw new p(403,"permission_error",`a cron cannot set ${l} on a node it starts`);r.prefer_warm=!1,r.node_id=await re(),d.isolated&&(r.isolated=!0,r.cwd=await z(r.node_id,d.app));const o=await en({grantee:d.app,sub:d.sub,grant_id:d.grant,scopes:d.scopes,from_exec:d.from_exec},{profile:r.profile,cwd:r.cwd,pin_cwd:r.pin_cwd,kind:r.kind,model:r.model,mode:r.mode});if(!o.allowed)throw nn(o);if(r.scopes!==void 0){const l=r.scopes.find(f=>!O(o.effectiveScopes,f)||!O(d.scopes,f));if(l!==void 0)throw new p(403,"scope_missing",`scope ${l} is not held by this cron`,void 0,void 0,{scope:l})}else d.scopes!==null&&(r.scopes=[...d.scopes])}r.creator!==void 0&&Qn(await m(r.creator),"crtr:act");const i=r.request_key?.trim();if(i===void 0||r.node_id!==void 0&&qe(r.node_id)&&await R(r.node_id)!==null&&(await de(i))?.nodeId!==r.node_id)return M(e,r,n,t);const a=Q.get(i);if(a!==void 0)return a;const u=$t(e,r,i,n,t);Q.set(i,u);try{return await u}finally{Q.delete(i)}}s(Ot,"handleCreate");const Se="create_request_in_progress";async function At(e,n,t){const r=Date.now()+1e4;for(;t!==null;){const i=await R(t);if(i!==null){if(!j(e.principal)&&!await $(e.principal,i.grantee??"app:terminal",t))throw new p(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:await b(t)}}if(Date.now()>=r||(await de(n))?.nodeId!==t)break;await new Promise(a=>setTimeout(a,100))}throw new p(409,Se,"another create with this request_key is in progress; retry it")}s(At,"awaitForeignCreate");async function $t(e,n,t,r,i){const a=await se(t);if(a.nodeId!==null&&await R(a.nodeId)!==null){if(a.state!=="warm_claimed"){const u=await R(a.nodeId);if(!j(e.principal)&&!await $(e.principal,u.grantee??"app:terminal",a.nodeId))throw new p(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:await b(a.nodeId)}}return M(e,n,r,i,a)}try{return await M(e,n,r,i,a)}catch(u){if(u instanceof p&&u.code===Se)throw u;const d=await se(t);throw(d.nodeId===null||await R(d.nodeId)===null)&&await oe(t,d.nodeId),u}}s($t,"handleKeyedCreateRequest");async function M(e,n,t,r,i=void 0){const a=r.deadlineAt??bt(n.deadline),u=vt(n.outcome_delivery),d=e.principal.class==="cron"?await tn({grantee:e.principal.app,sub:e.principal.sub,grant_id:e.principal.grant,scopes:e.principal.scopes,cron_id:e.principal.cron,origin_run_id:e.principal.origin_run,isolated:e.principal.isolated,creator:e.principal.kind==="exec"?null:(await he(e.principal.cron))?.created_by??null},n.node_id):null;d!==null&&(n.root=d.root===!0);const o=d?.parent??n.parent??void 0;if(o==null&&n.root!==!0)throw w("a node create requires a parent (or root: true for an independent root)");let l=null;if(n.output_schema!==void 0){try{l=JSON.parse(n.output_schema)}catch{throw w("output_schema must be a JSON schema string")}if(l===null||typeof l!="object"||Array.isArray(l))throw w("output_schema must be a JSON schema object");await Ln(l)}const{profileId:f,kind:h,cwd:c,launch:S}=await Vn(n,{validateKind:Ae,...e.principal.class==="broker"||e.principal.class==="cron"?{app:e.principal.app}:{}});if(n.pin_cwd!==void 0&&n.pin_cwd!==""&&n.worktree===void 0&&n.isolated!==!0&&!C(c)&&!await et(f))throw new y({error:"cwd_missing",message:`cwd is not an existing directory: ${c}`,received:c,field:"cwd",next:"Pass an existing directory with --cwd."});await ke(e,c),n.worktree!==void 0&&await ke(e,D(n.pin_cwd??n.cwd??c));const _={...n,kind:h},v=u===void 0?void 0:kt(u,c),Z=("grant"in e.principal?e.principal.grant:null)??(o==null?null:(await R(o))?.grant_id??null);if(await V(be(await Le(S,Z,n.model)),{cwd:c,profileId:f},t.modelRegistry),await ut(Z)!=="app"&&!await ht(f===null?[]:await wt(f)))throw new p(412,"no_provider_credential",_e,{error:"no_provider_credential",message:_e,next:"The person running this runtime logs a provider in with `crtr sys setup`, or stores a provider key on the profile."});let F=null;{const A=i===void 0||i.nodeId===null||i.state==="warm_claimed"?Rt(_,c,f):null,B=l===null&&r.beforeBrokerLaunch===void 0?void 0:async g=>{l!==null&&await Dn(g,"terminal",l),r.beforeBrokerLaunch?.(g)};if(i?.state==="warm_claimed"&&i.nodeId!==null){const g=A===null?null:await Bn(A,i.nodeId,B);if(g===null)throw await oe(i.requestKey,i.nodeId),new p(503,"create_resume_failed",`could not resume warm claim ${i.nodeId}; retry the create`);return await ae(i.requestKey,g),{status:201,body:await b(g)}}if(A!==null){const g=await Fn(A,{...a===void 0?{}:{deadlineAt:a},...v===void 0?{}:{outcomeDelivery:v},...i===void 0?{}:{requestKey:i.requestKey}},B);if(g!==null)return i!==void 0&&await ae(i.requestKey,g),me(A),{status:201,body:await b(g)};F=A}const P=i?.nodeId??n.node_id??(i===void 0?void 0:await re());if(i!==void 0&&i.nodeId===null){const g=await Be(i.requestKey,P);if(g!==P)return await At(e,i.requestKey,g)}const I=St(P===void 0?_:{..._,node_id:P},o,c);d!==null&&(d.rootLifecycle!==void 0&&(I.rootLifecycle=d.rootLifecycle),d.scopes!==void 0&&_.scopes===void 0&&(I.scopes=d.scopes),d.run!==void 0&&(I.run=d.run),d.withinCreate!==void 0&&(I.withinCreate=d.withinCreate)),a!==void 0&&(I.deadlineAt=a),v!==void 0&&(I.outcomeDelivery=v),I.readiness=n.root===!0?"await":"launch";const q=await Me(I,B,()=>{F!==null&&me(F)});return i!==void 0&&await Fe(i.requestKey,q.node.node_id),{status:201,body:await b(q.node.node_id)}}}s(M,"handleCreateRequest");function k(e,n){const t=e.query.getAll(n);if(t.length>1)throw w(`${n} must appear at most once`);return t[0]}s(k,"singleQueryValue");function X(e,n){if(e!==void 0){if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;throw w(`${n} must be true or false`)}}s(X,"optionalBoolean");function G(e,n,t){if(e!==void 0){if(t.includes(e))return e;throw w(`${n} must be one of: ${t.join(", ")}`)}}s(G,"oneOf");function Nt(e){const n=new Set(["status","lifecycle","kind","mode","profile_id","profile_prefix","parent","top_level","under","under_inclusive","hanging","include"]);for(const[_]of e.query)if(!n.has(_))throw w(`unknown nodes query parameter: ${_}`);const t=G(k(e,"status"),"status",["active","idle","done","dead","canceled"]),r=G(k(e,"lifecycle"),"lifecycle",["terminal","resident"]),i=k(e,"kind"),a=G(k(e,"mode"),"mode",["base","orchestrator"]),u=k(e,"profile_id"),d=k(e,"profile_prefix"),o=k(e,"parent"),l=X(k(e,"top_level"),"top_level"),f=k(e,"under"),h=X(k(e,"under_inclusive"),"under_inclusive"),c=X(k(e,"hanging"),"hanging"),S=G(k(e,"include"),"include",["activity"]);if(o!==void 0&&l===!0)throw w("parent and top_level=true cannot be combined");return{...t!==void 0?{status:t}:{},...r!==void 0?{lifecycle:r}:{},...i!==void 0?{kind:i}:{},...a!==void 0?{mode:a}:{},...u!==void 0?{profile_id:u}:{},...d!==void 0?{profile_prefix:d}:{},...o!==void 0?{parent:o}:{},...l!==void 0?{top_level:l}:{},...f!==void 0?{under:f}:{},...h!==void 0?{under_inclusive:h}:{},...c!==void 0?{hanging:c}:{},...S!==void 0?{include:S}:{}}}s(Nt,"parseListQuery");async function Ct(e){const n=Nt(e);let t=await Ke({...n.status!==void 0?{status:n.status}:{},...n.lifecycle!==void 0?{lifecycle:n.lifecycle}:{},...n.kind!==void 0?{kind:n.kind}:{},...n.mode!==void 0?{mode:n.mode}:{},...n.profile_id!==void 0?{profileId:n.profile_id}:{},...n.profile_prefix!==void 0?{profilePrefix:n.profile_prefix}:{},...n.parent!==void 0?{parent:n.parent}:{},...n.top_level===!0?{topLevel:!0}:{},...n.under!==void 0?{under:n.under}:{},...n.under_inclusive===!0?{underInclusive:!0}:{},...n.hanging===!0?{hanging:!0}:{}});const r=await tt(e.principal);r!==null&&(t=t.filter(d=>r.has(d.node_id)));const i=n.include==="activity"?await Ze(t.map(d=>d.node_id)):null,a=t.length>0?Ce():new Set;return{status:200,body:await ge(t,async d=>{const o=await Zn(d,d.profile_id!==null&&a.has(d.profile_id));if(i!==null){const l=await we(d.node_id);o.activity={latest_report:l[0]??null,final_report:d.final_report===null?null:l.find(f=>f.name===d.final_report)??null,pending_human_count:i[d.node_id]??0}}return o})}}s(Ct,"handleList");async function Et(e){const n=e.params.id,t=await rt(e,n,{method:"GET",path:`/v1/nodes/${encodeURIComponent(n)}`,query:ot(e)});if(t.kind==="unknown")throw dt(n,t.unreachable);if(t.kind==="remote"){if(t.status>=400)throw at(t.status,t.body);return{status:t.status,body:st(t.body,t.machine)}}return await m(n),{status:200,body:await b(n)}}s(Et,"handleDetail");async function Tt(e){const n=e.params.id;await m(n);const t=await cn(n);return{status:200,body:{node_id:n,snapshot:{messages:t.snapshot.messages,...t.snapshot.messageIds===void 0?{}:{messageIds:t.snapshot.messageIds},messageVisibility:t.snapshot.messageVisibility,turnVisibility:t.snapshot.turnVisibility,stats:t.snapshot.stats,state:t.snapshot.state,display:t.snapshot.display,...t.snapshot.queued===void 0?{}:{queued:t.snapshot.queued},...t.snapshot.toolGroupSummaries===void 0?{}:{toolGroupSummaries:t.snapshot.toolGroupSummaries},...t.snapshot.turnReplies===void 0?{}:{turnReplies:t.snapshot.turnReplies},...t.snapshot.workingActivity===void 0?{}:{workingActivity:t.snapshot.workingActivity}},commands:t.commands.map(i=>({name:i.name,description:i.description,source:i.source})),captured_at:x()}}}s(Tt,"handleSnapshot");async function Pt(e){const n=e.params.id,t=await fn(n);if(t===null)throw T(`unknown node: ${n}`,{received:n});return{status:200,body:t}}s(Pt,"handleSubject");function Dt(e){for(const[a]of e.query)if(a!=="cursor"&&a!=="limit")throw w(`unknown messages query parameter: ${a}`);const n=e.query.getAll("cursor"),t=e.query.getAll("limit");if(n.length>1)throw w("cursor must appear at most once");if(t.length>1)throw w("limit must appear at most once");if(t.length===0)return n.length===0?{}:{cursor:n[0]};const r=t[0],i=Number(r);if(!Number.isSafeInteger(i)||r==="")throw w("limit must be an integer from 1 through 500");return n.length===0?{limit:i}:{cursor:n[0],limit:i}}s(Dt,"parseMessagesQuery");async function Lt(e){const n=e.params.id,t=await sn(n,Dt(e));return{status:200,body:{node_id:n,messages:t.messages,...t.messageIds===void 0?{}:{message_ids:t.messageIds},message_visibility:t.messageVisibility,next_cursor:t.nextCursor,captured_at:x()}}}s(Lt,"handleMessages");async function jt(e){const n=e.params.id;await m(n);const t=await ln(n);return{status:200,body:{node_id:n,session_file:t.sessionFile,session_jsonl:t.sessionJsonl,system_prompt:t.systemPrompt,captured_at:x()}}}s(jt,"handleSession");async function Mt(e){const n=e.params.id;return await m(n),{status:200,body:{node_id:n,markdown:await un(n)}}}s(Mt,"handleTranscript");async function Gt(e){const n=e.params.id;await m(n);const t=s(async(i,a)=>({node_id:i,label:(await R(i))?.name??i,dir:await ce(i),self:a,files:await _t(i)}),"root"),r=await yt([await t(n,!0),...await ge(await le(n),async i=>await t(i.node_id,!1))],async i=>await Ft(i.node_id,i.dir)||i.files>0);return{status:200,body:{node_id:n,roots:r}}}s(Gt,"handleContext");async function Ft(e,n){try{return rn(await z(e),n)}catch(t){if(an(t))return!1;throw t}}s(Ft,"hasDir");async function Bt(e){const n=await m(e.params.id),t=e.principal.class==="broker"?e.principal.scopes:e.ceiling,r=t===null?void 0:n.scopes==null?[...t]:[...new Set([...n.scopes.filter(a=>O(t,a)),...t.filter(a=>O(n.scopes,a))])],i=await je(n.node_id,r,e.principal.class==="broker"?e.principal.node:void 0);return{status:201,body:await b(i.node.node_id)}}s(Bt,"handleFork");const Kt=1e4;async function xt(e){const n=e.params.id;await m(n);const t=e.body,r=t?.resume??!0,i=t?.reopen??!1;await _n(n,i,e.principal.class==="broker"?e.principal.node:null);const a=!r&&t?.cron_id!==void 0?await he(t.cron_id):null,u=await De(n,{resume:r,capacity:"refuse",...a!==null?{wakeReason:await Yn(a,"schedule_revive")}:{}});u.outcome!=="already-live"&&await xe(n,{failures:0,notBefore:null});const d=(await R(n))?.status??"active",o=(u.launch??L().get(n)?.handle)?.exited,l=u.outcome!=="frozen"&&await fe(n,o,Kt);return{status:200,body:qn(n,u,d,l)}}s(xt,"handleRevive");async function Vt(e){const n=e.params.id;return{status:200,body:{newNodeId:(await yn(n))?.newNodeId??null}}}s(Vt,"handleRelaunchRoot");async function Wt(e){const n=e.params.id;await m(n);const t=e.body;if(t?.caller_pid!==void 0&&(!Number.isInteger(t.caller_pid)||t.caller_pid<=0))throw w("caller_pid must be a positive integer when provided");const r=Hn(),i=new Promise(u=>{e.res.once("close",()=>u())}),a=await Pe(n,{teardownAfter:i,rootEvent:t?.finish===!0?"finish":"cancel",callerPid:t?.caller_pid,...e.principal.class==="broker"?{closer:e.principal.node}:{},...r===null?{}:{registerDetached:r.registerDetached}});return{status:200,body:Xn(a)}}s(Wt,"handleClose");async function zt(e){if(!j(e.principal))throw new p(403,"permission_error","only the person marks a conversation read");const n=e.params.id;return await m(n),await ze(n),{status:204}}s(zt,"handleMarkRead");async function Jt(e){const n=e.params.id;await m(n);const t=await hn(n);return{status:200,body:{recycled:t.recycled,finalized:t.finalized,new_root:t.newRoot,delivered:t.delivered}}}s(Jt,"handleRecycle");async function Ut(e){const n=e.params.id;return await m(n),await J(n,{lifecycle:"terminal"}),await N(e,n,["lifecycle"]),{status:200,body:await b(n)}}s(Ut,"handleDemote");async function Yt(e,n={}){const t=e.params.id,r=await m(t),i=e.body??{};i.kind!==void 0&&await U(i.kind,r.cwd,r.profile_id??null),i.model!==void 0&&await ve(r,{kind:i.kind??r.kind,mode:"orchestrator",lifecycle:i.resident===!0?"resident":r.lifecycle,model:i.model},n.modelRegistry);const a=await mn(t,{...i.kind!==void 0?{kind:i.kind}:{},...i.resident===!0?{resident:!0}:{},...i.model!==void 0?{model:i.model}:{}});await N(e,t,["mode",...i.kind!==void 0?["kind"]:[],...i.resident===!0?["lifecycle"]:[],...i.model!==void 0?["model"]:[]]);const u=await Y(a.meta,await H(t));return u.roadmap_written=a.roadmapWritten,u.roadmap_ref=a.roadmapRef,u.goal_path=a.goalPath,{status:200,body:u}}s(Yt,"handlePromote");async function Ht(e){const n=e.params.id;return await m(n),{status:200,body:{request:await bn(n)}}}s(Ht,"handleBrokerStructuredRequest");async function Qt(e){const n=e.params.id,t=e.body??{};if(await gn(n,t.expected_execution_id),typeof t.text!="string")throw new p(400,"invalid_request","text must be a string");return await m(n),{status:200,body:{captured:await Sn(n,t.text)}}}s(Qt,"handleBrokerGoal");async function Xt(e,n={}){const t=e.params.id,r=await m(t),i=e.body??{};i.kind!==void 0&&await U(i.kind,r.cwd,r.profile_id??null),i.model!==void 0&&await ve(r,{kind:i.kind??r.kind,mode:i.promote===!0?"orchestrator":r.mode,lifecycle:r.lifecycle,model:i.model},n.modelRegistry);const a=i.note??"Refresh: continue against your roadmap or goal.";await vn(t,a);const u=await wn(t,{...i.promote===!0?{promote:!0}:{},...i.kind!==void 0?{kind:i.kind}:{},...i.model!==void 0?{model:i.model}:{}});return{status:200,body:await Y(u.meta,await H(t))}}s(Xt,"handleYield");async function Zt(e){const n=e.params.id;await m(n);const t=e.body;if(t===void 0||typeof t.controller!="string"||t.controller.trim()==="")throw w("a wait requires a controller node id");const r=await R(t.controller);if(r===null)throw T(`unknown controller: ${t.controller}`,{received:t.controller});if(r.status!=="active"&&r.status!=="idle")throw new p(422,"unprocessable",`controller ${t.controller} is ${r.status}`);return await We(n,t.controller),{status:200,body:await b(n)}}s(Zt,"handleWait");async function qt(e){const n=e.principal,t=await pn(n.class==="broker"?async i=>i.grantee===n.app&&await $(n,i.grantee,i.node_id):n.class==="person"&&!j(n)?async i=>await $(n,i.grantee??"app:terminal",i.node_id):void 0);return{status:200,body:{revived:[...t.revived],failed:[...t.failed],frozen:[...t.frozen]}}}s(qt,"handleReviveAll");const ei=new Set(["interrupt","steer","after-turn","next-turn"]);function ni(e){if(e===null)return null;const n=s(r=>{throw new y({error:"invalid_listen",message:r,received:e,field:"listen",next:'Send an object mapping levels "1".."10" to interrupt|steer|after-turn|next-turn (e.g. {"3":"next-turn"}), or null to reset to the global default.'})},"bad");if(typeof e!="object"||Array.isArray(e))return n("listen must be an object or null");const t=Object.entries(e);if(t.length===0)return n("listen must name at least one level");for(const[r,i]of t)/^(?:[1-9]|10)$/.test(r)||n(`listen level must be 1..10: ${r}`),(typeof i!="string"||!ei.has(i))&&n(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(i)}`);return JSON.stringify(Object.fromEntries(t))}s(ni,"listenJson");async function N(e,n,t,r){t.length===0&&r===void 0||await W(async i=>{if(r?.(i),t.length===0)return;const a=await Je(i,n),u=await He(i,e),d=u.class==="person"?u.person:u.class==="app"?u.app:u.node;await Ue(i,d,a),await Ye(i,{event:"configured",object:a,actor:d,attrs:{changed:t.join(",")}})})}s(N,"recordConfigured");function Re(e){const n=L().get(e);if(n===void 0)return!1;try{return process.kill(n.pid,"SIGTERM"),!0}catch{return!1}}s(Re,"restartLiveBroker");function Ie(e,n){try{return ee(e)===ee(n)}catch{return!1}}s(Ie,"sameDirectory");async function ti(e,n={}){const t=e.params.id,r=e.body;let i;if(r===void 0)i={};else if(typeof r=="object"&&r!==null&&!Array.isArray(r))i=r;else throw new y({error:"cwd_invalid",message:"cwd repair requires a non-null object with a non-empty cwd string",received:r,field:"cwd",next:"Send a config patch with a non-empty absolute cwd string."});if(i.profile!==void 0){if(typeof i.profile!="string"||i.profile==="")throw new y({error:"profile_invalid",message:"profile must be a non-empty profile id or name",received:i.profile,field:"profile",next:"Send a profile id or exact name."});if(Object.keys(i).some(h=>h!=="profile"&&h!=="restart"&&i[h]!==void 0))throw new y({error:"profile_not_exclusive",message:"profile can only be combined with restart",field:"profile",next:"Send profile (and optionally restart) alone."});const o=await m(t),l=await zn(e,i.profile);Jn(l.profileId);const f=Un(l.profileId).manifest.grantee??"app:terminal";if(f!==(o.grantee??"app:terminal"))throw new y({error:"profile_grantee_mismatch",message:`profile ${l.profileId} belongs to ${f}, node ${t} to ${o.grantee}`,received:i.profile,field:"profile",next:"Pick a profile owned by the same app as the node."});return(o.profile_id??null)!==l.profileId&&(xn(o.kind)?(await U(o.kind,o.cwd,l.profileId),await J(t,{profileId:l.profileId})):await E(t,{profile_id:l.profileId}),await N(e,t,["profile"])),i.restart===!0&&Re(t),{status:200,body:await b(t)}}if(Object.prototype.hasOwnProperty.call(i,"cwd")){const o=i.cwd;if(typeof o!="string"||o==="")throw new y({error:"cwd_invalid",message:"cwd must be a non-empty string",received:o,field:"cwd",next:"Send a non-empty absolute cwd string."});if(Object.keys(i).some(c=>c!=="cwd"&&c!=="keep_session"&&c!=="restart"&&i[c]!==void 0))throw new y({error:"cwd_not_exclusive",message:"cwd repair cannot be combined with another config field",received:i,field:"cwd",next:"Send cwd as the only config field."});const l=await m(t),f=C(l.cwd);if(i.keep_session===!0||f&&K(o)&&C(o)&&Ie(l.cwd,o)){if(!K(o))throw new y({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${o}`,received:o,field:"cwd",next:"Send an absolute path."});const c=D(o);let S=!1;try{S=ne(c).isDirectory()}catch{}if(!S)throw new y({error:"cwd_missing",message:`cwd is not an existing directory: ${c}`,received:o,field:"cwd",next:"Send an existing absolute directory."});if(f&&!Ie(l.cwd,c))throw new y({error:"cwd_not_same_directory",message:`${c} is not the same directory as the recorded ${l.cwd}; --keep-session only relocates an alias`,received:o,field:"cwd",next:"Drop --keep-session to repair a gone cwd, or pass the real path of the recorded directory."});if(l.managed_worktree?.state==="open")throw new y({error:"cwd_node_managed_worktree_open",message:`${t} owns an open managed worktree and cannot relocate its cwd`,received:o,field:"cwd",next:"Reconcile the managed worktree first."});const _=l.cwd;return _!==c&&(await W(async v=>{await E(t,{cwd:c}),await v.prepare("UPDATE crons SET cwd = ? WHERE anchor_node = ? AND cwd = ?").run(c,t,_),await Qe(t,_,c)}),await N(e,t,["cwd"])),i.restart===!0&&Re(t),{status:200,body:await b(t)}}if(await L().has(t)){const c=`${t} cannot repair its cwd while its broker is live`;throw new p(409,"cwd_node_live",c,{error:"cwd_node_live",message:c,received:o,field:"cwd",next:"Let the node become dormant, then retry the cwd repair."})}if(l.fork_from!=null)throw new y({error:"cwd_node_forked",message:`${t} is a fork and cannot repair its cwd; recorded cwd: ${l.cwd}`,received:o,field:"cwd",next:`Restore ${l.cwd}, then revive the fork normally.`});if(l.managed_worktree?.state==="open")throw new y({error:"cwd_node_managed_worktree_open",message:`${t} owns an open managed worktree and cannot repair its cwd`,received:o,field:"cwd",next:"Restore or reconcile the recorded checkout, then use the managed-worktree close or abandon flow."});if(C(l.cwd))throw new y({error:"cwd_still_present",message:`${t} recorded cwd still exists: ${l.cwd}; cwd repair is not a relocation command`,received:o,field:"cwd",next:"This command only repairs a node whose recorded cwd is gone."});if(!K(o))throw new y({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${o}`,received:o,field:"cwd",next:"Send an absolute path."});const h=D(o);if(!C(h))throw new y({error:"cwd_missing",message:`cwd does not exist: ${h}`,received:o,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."});try{if(!ne(h).isDirectory())throw new y({error:"cwd_not_a_directory",message:`cwd is not a directory: ${h}`,received:o,field:"cwd",next:"Send an existing absolute directory."})}catch(c){throw c instanceof y?c:new y({error:"cwd_missing",message:`cwd does not exist: ${h}`,received:o,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."})}return await W(async()=>{await E(t,{cwd:h}),await Xe(t)}),await N(e,t,["cwd"]),{status:200,body:await b(t)}}let a=await m(t);const u=i.listen===void 0?void 0:ni(i.listen);if(i.scopes!==void 0){const o=ye(i.scopes),l=a.grantee==="app:terminal"?await ft(a):a.grant_id?await ct(a.grant_id):null;if(!o.every(f=>O(a.scopes,f)&&l!==null&&O(l.resolved,f)))throw new y({error:"unknown_scope",message:"scopes may only narrow the node's current effective set",received:o,field:"scopes",next:"Send only scopes the node currently holds."});if(o.includes("crtr:act")&&!O(o,"crtr:llm"))throw new p(400,"invalid_scope","crtr:act requires crtr:llm");a=await E(t,{scopes:o})}if(i.situational_context!==void 0&&await Ee(t,Te(i.situational_context)),i.model!==void 0){const o=(await ue(a.cwd,a.profile_id??null,a.grantee??"app:terminal")).modelLadders,l=$n(i.model,o),f=await pt(a.grant_id,i.model,l===void 0),h=f?{family:mt,strength:f.strength}:l,c=f?f.model:Nn(i.model,o);await V({kind:"concrete",spec:c},{cwd:a.cwd,profileId:a.profile_id??null},n.modelRegistry);const S=L();let _=!1;if(await S.isClaimed(t)&&await fe(t,S.get(t)?.handle.exited)&&(_=await Tn(t,c,h).then(()=>!0,v=>{if(v instanceof Pn)return!1;throw v})),!_){if(await S.isClaimed(t)){const v=`${t}'s broker did not accept the model switch; the model was not changed`;throw new p(409,"broker_not_ready",v,{error:"broker_not_ready",message:v,received:i.model,field:"model",next:"Check the node with `crtr node show`, then retry the model change."})}if(!c.includes("/"))throw w(`model must resolve to a provider/id spec: ${i.model}`);await En(t,c,h)}a=await m(t)}if(i.kind!==void 0||i.mode!==void 0||i.lifecycle!==void 0){i.kind!==void 0&&await Ae(i.kind,a.grantee??"app:terminal");const o=i.kind??a.kind,l=i.mode??a.mode,f=i.lifecycle??a.lifecycle;let h;l==="orchestrator"&&!await In(t)&&(h=s(async()=>{const c=await kn(t);await Rn(t,c!==null&&c.trim()!==""?{goal:c.trim()}:{})},"beforePersist")),a=await J(t,{...i.kind!==void 0?{kind:o}:{},...i.mode!==void 0?{mode:l}:{},...i.lifecycle!==void 0?{lifecycle:f}:{}},h)}i.name!==void 0&&(a=await E(t,{name:i.name}),a.window&&On(a.window,Wn(a)));const d=["scopes","situational_context","model","kind","mode","lifecycle","name","listen"].filter(o=>i[o]!==void 0);return await N(e,t,d,u===void 0?void 0:async o=>{await o.prepare("UPDATE objects SET listen_json = ? WHERE id = ? AND type = 'node'").run(u,t)}),{status:200,body:await b(t)}}s(ti,"handleConfig");async function Oe(e="app:terminal"){return(await ue(process.cwd(),Ne()||null,e)).kinds}s(Oe,"daemonKinds");async function Ae(e,n="app:terminal"){const t=Object.keys(await Oe(n));if(!t.includes(e))throw w(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${t.sort().join(", ")}.`})}s(Ae,"assertKindServer");async function ii(){const e=await Oe();return{status:200,body:{kinds:Object.keys(e).sort().map(t=>({kind:t,when_to_use:e[t]?.whenToUse??null,available_to:e[t]?.availableTo??null}))}}}s(ii,"handleListKinds");const Or=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:Ot},{method:"GET",pattern:"/v1/nodes",handler:Ct},{method:"GET",pattern:"/v1/kinds",handler:s(()=>ii(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:qt},{method:"GET",pattern:"/v1/nodes/:id",handler:Et},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:Tt},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:Pt},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:Lt},{method:"GET",pattern:"/v1/nodes/:id/session",handler:jt},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:Mt},{method:"GET",pattern:"/v1/nodes/:id/context",handler:Gt},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:Bt},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:xt},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:Vt},{method:"POST",pattern:"/v1/nodes/:id/close",handler:Wt},{method:"POST",pattern:"/v1/nodes/:id/read",handler:zt},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:Jt},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:Ut},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:Yt},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Xt},{method:"GET",pattern:"/v1/nodes/:id/broker/structured-request",handler:Ht},{method:"POST",pattern:"/v1/nodes/:id/broker/goal",handler:Qt},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Zt},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:ti}];export{ti as handleConfig,Ot as handleCreate,Bt as handleFork,Ct as handleList,Yt as handlePromote,Xt as handleYield,Or as nodeRoutes,Nr as resolveCreateKind};
@@ -1,2 +1,2 @@
1
- import type { RouteTable } from '../router.js';
1
+ import { type RouteTable } from '../router.js';
2
2
  export declare const packageDocRoutes: RouteTable;
@@ -1 +1 @@
1
- var o=Object.defineProperty;var a=(e,t)=>o(e,"name",{value:t,configurable:!0});import{withCanvasWrite as d}from"../../../core/canvas/db.js";import{isCloudRole as i}from"../../../core/canvas/person-state.js";import{reconcilePackages as n}from"../../../core/graph/package-reconcile.js";const r=a(()=>({created:0,updated:0,deleted:0,conflicts:[],invalid:[],quarantined:[],kinds:{applied:[],refused:[],invalid:[]},tokens:{granted:[],revoked:[]}}),"EMPTY_REPORT"),m=[{method:"POST",pattern:"/v1/documents/reconcile-packages",handler:a(async()=>({status:200,body:i()?r():await d(async e=>await n(e))}),"handler")}];export{m as packageDocRoutes};
1
+ var c=Object.defineProperty;var d=(i,e)=>c(i,"name",{value:e,configurable:!0});import{withCanvasWrite as f}from"../../../core/canvas/db.js";import{isCloudRole as m}from"../../../core/canvas/person-state.js";import{personIdAsync as k}from"../../../core/canvas/person.js";import{reconcilePackages as g}from"../../../core/graph/package-reconcile.js";import{syncInstall as h}from"../../../core/packages/directory-sync.js";import{normalizeSourceUrl as b}from"../../../core/packages/source-url.js";import{loadPersonSettings as v}from"../../../core/scoped-state/person-rows.js";import{ApiError as p}from"../../../api/errors.js";import{appOf as w}from"../router.js";const y=d(()=>({created:0,updated:0,deleted:0,conflicts:[],invalid:[],quarantined:[],kinds:{applied:[],refused:[],invalid:[]},tokens:{granted:[],revoked:[]}}),"EMPTY_REPORT");async function _(i){const e=y(),t=i.body?.plugins,l=(await v(await k())).apps[w(i.principal)??"app:terminal"];if(l===void 0)return e;for(const[n,s]of Object.entries(l.plugins)){if(s.enabled===!1||s.source_marketplace===void 0||t!==void 0&&!t.includes(n))continue;const u=l.marketplaces[s.source_marketplace]?.url;if(u===void 0)continue;const{out:o,published:r}=await h(n,b(u));if(r!==void 0){e.created+=r.created,e.deleted+=r.deleted,e.invalid.push(...r.invalid);for(const a of r.kinds.refused)e.kinds.refused.push({plugin:n,kind:a.kind,code:"kind_owned",message:a.message})}if(o.ok){e.updated+="pkg"in o?1:0;continue}if(o.reason==="name_taken"){const a=`plugin ${n} is already provided by ${o.holder??"another marketplace"}`;if(t!==void 0)throw new p(409,"name_taken",a,{plugin:n,holder:o.holder??null});e.conflicts.push({plugin:n,message:a})}else if(o.reason==="not_found"){const a=`the directory does not list plugin ${n} in marketplace ${s.source_marketplace}`;if(t!==void 0)throw new p(404,"not_found",a,{plugin:n});(e.unavailable??=[]).push({plugin:n,reason:"not_found"})}else(e.unavailable??=[]).push({plugin:n,reason:o.reason==="unavailable"?"directory_unreachable":"not_public"})}return e}d(_,"resolveApp");const j=[{method:"POST",pattern:"/v1/documents/reconcile-packages",handler:d(async i=>({status:200,body:m()?await _(i):await f(async e=>await g(e))}),"handler")}];export{j as packageDocRoutes};
@@ -1,2 +1,5 @@
1
- import { type RouteTable } from '../router.js';
1
+ import { type SettingsOp } from '../../../core/scoped-state/person-store.js';
2
+ import { type RequestContext, type RouteTable } from '../router.js';
3
+ /** On an unsandboxed host every node's CLI loads the person's settings through its relay at startup, as the person's terminal does, so any node reads them. Only the terminal app's node writes them, and a node of any app (the terminal's included) writes only its own app's plugin installs. */
4
+ export declare function requireWriter(ctx: RequestContext, ops: readonly SettingsOp[]): void;
2
5
  export declare const settingsRoutes: RouteTable;
@@ -1 +1 @@
1
- var a=Object.defineProperty;var n=(t,r)=>a(t,"name",{value:r,configurable:!0});import{ApiError as o}from"../../../api/errors.js";import{personIdAsync as i}from"../../../core/canvas/person.js";import{SettingsRevisionConflictError as p,currentSnapshot as l,personHasSnapshot as c}from"../../../core/scoped-state/person-store.js";import{loadPersonSettings as f,rowsTransport as h}from"../../../core/scoped-state/person-rows.js";import{ownerOnly as u}from"../router.js";const m=new Set(["settings.replace","state.write","profile.insert","profile.update","profile.delete","defaults.replace"]);function w(t){const r=t?.ops;if(!Array.isArray(r)||r.length===0)throw new o(400,"invalid_request","ops must be a non-empty array");for(const e of r)if(e===null||typeof e!="object"||!m.has(e.op))throw new o(400,"invalid_request",`unknown settings op: ${String(e?.op)}`);return r}n(w,"parseOps");function d(t){if(t.principal.class==="broker"&&t.principal.app!=="app:terminal")throw new o(403,"permission_error","only the person's terminal nodes change the person's settings")}n(d,"requireTerminalWriter");async function y(){const t=await i();return{status:200,body:{person:t,snapshot:c()?l():await f(t)}}}n(y,"handleGet");async function g(t){d(t);const r=w(t.body),e=await i();try{return{status:200,body:{person:e,snapshot:await h(e,r)}}}catch(s){throw s instanceof p?new o(409,"conflict",s.message):s}}n(g,"handlePut");const q=u([{method:"GET",pattern:"/v1/settings",handler:y},{method:"PUT",pattern:"/v1/settings",handler:g}]);export{q as settingsRoutes};
1
+ var i=Object.defineProperty;var s=(r,e)=>i(r,"name",{value:e,configurable:!0});import{ApiError as o}from"../../../api/errors.js";import{personIdAsync as p}from"../../../core/canvas/person.js";import{isCloudRole as a}from"../../../core/canvas/person-state.js";import{SettingsRevisionConflictError as l,currentSnapshot as c,personHasSnapshot as f}from"../../../core/scoped-state/person-store.js";import{loadPersonSettings as w,rowsTransport as u}from"../../../core/scoped-state/person-rows.js";import{ownerOnly as h}from"../router.js";const g=new Set(["settings.replace","app-plugins.replace","state.write","profile.insert","profile.update","profile.delete","defaults.replace"]);function m(r){const e=r?.ops;if(!Array.isArray(e)||e.length===0)throw new o(400,"invalid_request","ops must be a non-empty array");for(const n of e)if(n===null||typeof n!="object"||!g.has(n.op))throw new o(400,"invalid_request",`unknown settings op: ${String(n?.op)}`);return e}s(m,"parseOps");function d(r,e){if(a()){for(const t of e)if(t.op==="settings.replace"&&("plugins"in t.raw||"marketplaces"in t.raw))throw new o(400,"invalid_request","plugin and marketplace installs are written with app-plugins.replace, not settings.replace")}const{principal:n}=r;if(n.class==="broker")for(const t of e){if(t.op==="settings.replace"&&t.owner.startsWith("app:"))throw new o(403,"permission_error","an app's plugin installs are written with app-plugins.replace, not settings.replace");if(t.op==="app-plugins.replace"){if(t.app!==n.app)throw new o(403,"permission_error",`a node of ${n.app} changes only its own app's plugin installs, not ${t.app}'s`)}else if(n.app!=="app:terminal")throw new o(403,"permission_error","only the person's terminal nodes change the person's settings")}}s(d,"requireWriter");async function y(){const r=await p();return{status:200,body:{person:r,snapshot:f()?c():await w(r)}}}s(y,"handleGet");async function S(r){const e=m(r.body);d(r,e);const n=await p();try{return{status:200,body:{person:n,snapshot:await u(n,e)}}}catch(t){throw t instanceof l?new o(409,"conflict",t.message):t}}s(S,"handlePut");const E=h([{method:"GET",pattern:"/v1/settings",handler:y},{method:"PUT",pattern:"/v1/settings",handler:S}]);export{d as requireWriter,E as settingsRoutes};
@@ -1,19 +1,19 @@
1
- var rr=Object.defineProperty;var s=(e,l)=>rr(e,"name",{value:l,configurable:!0});import{applyBootSettings as tr}from"./boot-settings.js";import{startPeerOutbox as nr}from"./peer/outbox.js";import{reportMachineStatus as or}from"../core/peer/directory.js";import{createPeerRelay as ir}from"./peer/relay-service.js";import{writeFileSync as ar,readFileSync as sr,rmSync as cr,mkdirSync as ye,existsSync as k,unlinkSync as _e,chmodSync as be}from"node:fs";import{createServer as J}from"node:http";import{dirname as lr}from"node:path";import{envCrtrdTcp as ke,envDocumentPort as dr}from"../shared/env.js";import{openCanvasConversationStore as mr,serveCanvasConversationStore as pr}from"../core/canvas/sessions.js";import{installConversationStore as fr}from"../core/conversation-store/index.js";import{pollRunObservers as ur}from"./runs/observer.js";import{randomBytes as Re}from"node:crypto";import{apiSocketPath as Pe,crtrHome as hr}from"../core/canvas/paths.js";import{activeAppUsers as wr}from"../core/spaces/users.js";import{ensureAppSpace as vr,ensureUserFiles as gr}from"../core/spaces/space.js";import{LAUNCHER_SOCKET as T}from"../launcher/spec.js";import{launcherRequest as $}from"../launcher/client.js";import{installLauncherEventSink as Sr}from"./launcher-events.js";import{initializeEmptyLayout as yr,layoutNeedsMigration as _r,socketDir as Ee}from"../core/layout.js";import{migrateLooseKeys as br}from"../core/layout-migrate/loose-keys.js";import{relocateProfileFolders as kr}from"../core/profiles/relocate.js";import{getNode as Rr,listNodesForSupervision as Ie,listParkedResidentsWithWakeMail as Pr,setFrozen as xe}from"../core/canvas/index.js";import{createApiServer as Er,closeServer as Te}from"./api/server.js";import{Router as Ir}from"./api/router.js";import{healthRoutes as xr}from"./api/handlers/health.js";import{createDocumentListener as Tr}from"./api/document-listener.js";import{documentSecret as Dr}from"./api/document-secret.js";import{createAppListener as Cr}from"./api/app-listener.js";import{registerMachineEnvironment as Lr}from"../core/environments.js";import{registerBlaxelRunnerFromEnv as $r}from"../core/secrets/blaxel-register.js";import{markCloudRole as Ar,resolvePerson as Nr,retireLocalPerson as Mr,setPersonId as Gr}from"../core/canvas/person.js";import{backfillNodeApps as De,runPermissionsBoot as Or}from"../core/permissions/boot.js";import{startRunNotices as Fr}from"./run-notices.js";import{startGrantEffects as Br}from"./reconcilers/grant-effects.js";import{createGrantSync as Hr,GRANT_SYNC_INTERVAL_S as jr}from"../core/grants/sync.js";import{sweepSandboxes as zr}from"../core/grants/on-sync.js";import{rebuildCronExecutions as Ur}from"./cron/run-socket.js";import{hasSyncedGrants as qr}from"../core/grants/mirror.js";import{readConfig as se}from"../core/config.js";import{reconcileUndeliveredTickets as Wr}from"./human/sweep.js";import{resetHandedOffDeliveries as Jr}from"../core/canvas/deliveries.js";import{resetHandedOffDaemonActions as Kr}from"../core/canvas/daemon-actions.js";import{sweepReviews as Vr}from"./review/sweep.js";import{pidfilePath as ce}from"./pidfile.js";import{rendererWarning as Yr}from"../core/runtime/package-health.js";import{DEFAULT_INTERVAL_MS as Qr}from"./supervise-cadence.js";import{createResumeDetector as Xr}from"./resume-detector.js";import{setFatalFaultAnnouncer as Zr}from"../core/canvas/recovery.js";import{BrokerSupervisionReconciler as et}from"./reconcilers/broker-supervision.js";import{ControllerDeathReconciler as rt}from"./reconcilers/controller-death.js";import{NodeLifecycleReconciler as tt}from"./reconcilers/node-lifecycle/tick.js";import{NodeDeadlineReconciler as nt}from"./reconcilers/node-deadline.js";import{CronLaneReconciler as ot}from"./reconcilers/cron-lane.js";import{DeliveryLaneReconciler as it}from"./reconcilers/delivery-lane.js";import{ActionLaneReconciler as at}from"./reconcilers/action-lane.js";import{endLiveExecution as st,migrateLegacyExecutionIdentities as ct}from"../core/canvas/executions.js";import{revokePriorEpochNodeTokens as lt}from"../core/canvas/node-tokens.js";import{PendingReviewSubmitReconciler as dt}from"./reconcilers/pending-review-submit.js";import{StorageMaintenanceReconciler as mt}from"./reconcilers/storage-maintenance.js";import{StorageDueWorkReconciler as pt}from"./reconcilers/storage-due-work.js";import{PurgeDueWorkReconciler as ft}from"./reconcilers/purge-due-work.js";import{assertLedgerEnv as ut}from"../core/ledger/rates.js";import{LedgerSandboxReconciler as ht}from"./reconcilers/ledger-sandbox.js";import{LedgerStorageReconciler as wt}from"./reconcilers/ledger-storage.js";import{LedgerR2Reconciler as vt}from"./reconcilers/ledger-r2.js";import{ImportLaneReconciler as gt}from"./reconcilers/import-lane.js";import{BashDeadlineReconciler as St}from"./reconcilers/bash-deadline.js";import{FaultRetryBackstopReconciler as yt}from"./reconcilers/fault-retry-backstop.js";import{StructuredRequestReconciler as _t}from"./reconcilers/structured-request-lane.js";import{RecipeImageReconciler as bt,subscribeImageBuilt as kt}from"./reconcilers/recipe-image.js";import{reconcileStructuredRequestSidecars as Rt}from"./structured-requests/boot.js";import{captureLivenessSnapshot as Ce,capturePidCommand as Pt,captureTeardownSnapshot as Le,isPidAlive as Et,isAnyPidAlive as $e,killProcessTreePids as Ae}from"../core/canvas/pid.js";import{bindFleet as It,boundFleet as xt}from"../core/runtime/fleet.js";import{bindDaemonControl as Tt,clearDaemonControl as Dt}from"./control.js";import{execDaemon as Ct,spawnDaemon as Lt}from"./manage.js";import{reconcileAndMigrateBoot as $t}from"../core/canvas/boot.js";import{resolveInstallId as At}from"../core/canvas/install-id.js";import{setInstallId as Nt}from"../core/runtime/nodes.js";import{claimDaemonOwnership as Mt,daemonOwnershipApplies as Gt,daemonOwnershipClaimed as Ot,releaseDaemonOwnership as Ne}from"../core/canvas/daemon-owner.js";import{canvasDatabaseUrl as Ft,closeAllDbs as le,openDb as Me,withCanvasWrite as Ge}from"../core/canvas/db.js";import{importSqliteCanvasIfPresent as Bt}from"../core/canvas/import-sqlite.js";import{ensurePostgres as Ht,ensurePostgresHealthy as jt,stopPostgres as zt,withPostgresStartLock as Ut}from"./postgres/index.js";import{brokerSignalBus as F}from"./broker-signals/bus.js";import{brokerSignalStreams as qt}from"./api/handlers/broker-signals.js";import{setRequestsStartRunObservers as Wt}from"./api/handlers/broker-ops.js";import{reconcilePackages as Jt}from"../core/graph/package-reconcile.js";import{publish as Kt,readBuiltinSnapshot as Vt}from"../core/graph/package-publish.js";import{startRepoSync as Yt}from"../core/graph/repo-sync/index.js";import{prewarmRecentRecipes as Qt,reapStaleSpares as Xt}from"../core/runtime/warm-pool.js";import{DaemonFleet as Zt}from"./fleet.js";import{copyNodeFilesToRows as en}from"../core/runtime/first-boot-rows.js";import{BOOT_MIGRATIONS as rn}from"./boot-migrations.js";import{emitEvent as m}from"../core/events/emit.js";import{operationIdContext as _}from"../core/events/operation-id.js";import{bindDaemonEventSource as tn}from"../core/events/source.js";import{activateCanvasImport as nn,MigrationBlockedError as on,runForcedCanvasImport as an}from"../migrations/activation.js";import{adoptInstallPerson as sn,convertLegacyScopedStore as cn,personStoresCopied as ln}from"../core/scoped-state/migrate.js";import{readLegacyUserSnapshot as dn}from"../core/scoped-state/legacy-profiles.js";import{heldPersons as Oe,installPreludeSnapshot as mn}from"../core/scoped-state/person-store.js";import{loadPersonSettings as Fe}from"../core/scoped-state/person-rows.js";import{userScopeRoot as Be}from"../core/scope.js";import{brokerCommandDeclaresCanvasHome as de}from"../core/runtime/broker-ownership.js";import{brokerCommandDeclaresCanvasHome as Bi}from"../core/runtime/broker-ownership.js";function me(e){return/ --epoch (\S+) /.exec(e)?.[1]??null}s(me,"brokerCommandEpoch");const pn=5e3,He=150;async function fn(e){const l=Ce();if(l===null)throw m({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness"}}),new Error("prior-epoch broker census could not capture the process table");const u=hr(),f=[];for(const[n,d]of l.processes){const y=d.command;if(d.zombie||!y.includes("broker-cli.js")||!de(y,u)||me(y)===e)continue;const b=y.trim().split(/\s+/).at(-1)??"";b===""||b.endsWith("broker-cli.js")||f.push({pid:n,nodeId:b})}let v=0;const a=[];for(const n of f){const d=Pt(n.pid);if(d===null||!d.includes("broker-cli.js")||!de(d,u)||me(d)===e||d.trim().split(/\s+/).at(-1)!==n.nodeId)continue;const y=Le(n.pid,null);if(!y.reused){try{process.platform==="linux"&&k(T)?await $({operation:"stop",pid:n.pid}):process.kill(n.pid,"SIGTERM")}catch{continue}v++,a.push({pid:n.pid,snap:y})}}const h=Date.now()+pn;for(;Date.now()<h&&a.some(n=>$e(n.snap.tree.length>0?n.snap.tree:[n.pid]));)await new Promise(n=>setTimeout(n,He));let g=0;for(const n of a){const d=n.snap.tree.length>0?n.snap.tree:[n.pid];$e(d)&&(process.platform==="linux"&&k(T)?await $({operation:"stop",pid:n.pid}):Ae(d,"SIGKILL",n.snap.identities),g++)}g>0&&await new Promise(n=>setTimeout(n,He));const p=Ce();if(p===null)throw m({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness",stage:"final"}}),new Error("prior-epoch broker census could not capture the final process table");const c=[];for(const[n,d]of p.processes){const y=d.command;d.zombie||!y.includes("broker-cli.js")||de(y,u)&&me(y)!==e&&c.push(n)}if(c.length>0)throw new Error(`prior-epoch broker census could not prove termination of pid(s): ${c.join(", ")}`);m({level:"info",event:"daemon.census.completed",fields:{prior_epoch_brokers:f.length,sigtermed:v,sigkilled:g}})}s(fn,"reapPriorEpochBrokers");const un=5e3;async function hn(e){const l=Array.from(e.entries());if(l.length===0)return;for(const[a]of l){const h=(await Rr(a))?.status;(h==="active"||h==="idle")&&await xe(a,new Date().toISOString())}const u=l.map(([,a])=>({pid:a.pid,snap:Le(a.pid,null),exited:a.handle.exited}));for(const a of u)if(!a.snap.reused)try{process.platform==="linux"&&k(T)?await $({operation:"stop",pid:a.pid}):process.kill(a.pid,"SIGTERM")}catch{}const f=new Promise(a=>{setTimeout(a,un).unref()});await Promise.allSettled(u.map(a=>Promise.race([a.exited.then(()=>{}),f])));const v=[];for(const a of u)Et(a.pid)&&(process.platform==="linux"&&k(T)?await $({operation:"stop",pid:a.pid}):Ae(a.snap.tree.length>0?a.snap.tree:[a.pid],"SIGKILL",a.snap.identities),v.push(a));await Promise.all(v.map(a=>a.exited));for(const[a]of l)await st(a,{reason:"daemon-teardown"});m({level:"info",event:"daemon.fleet_teardown.completed",fields:{brokers:u.length,sigkilled:v.length}})}s(hn,"teardownFleet");function je(){ye(lr(ce()),{recursive:!0}),ar(ce(),String(process.pid),"utf8")}s(je,"writePidfile");function ze(e){return typeof e=="object"&&e!==null&&e.code==="ENOENT"}s(ze,"isMissingPathError");function Ue(e){const l=ce();let u;try{u=sr(l,"utf8")}catch(f){if(ze(f))return;throw f}if(u.trim()!==String(e))throw new Error(`daemon readiness mirror does not name this invocation (expected pid ${e})`);try{cr(l)}catch(f){if(ze(f))return;throw f}}s(Ue,"removeOwnedPidfileMirror");const wn={acceptsDetachedWork:s(()=>!0,"acceptsDetachedWork"),registerDetached:s(e=>{e.catch(()=>{})},"registerDetached")},K=new et;Zr(e=>K.handleFatalFault(e,!1));const vn=new rt,gn=new tt,Sn=new nt,yn=new ot,_n=new it,bn=new at,kn=new dt,Rn=new mt,Pn=new pt,En=new ft,In=new ht,xn=new wt,Tn=new vt,Dn=new gt,Cn=new St,Ln=new yt,$n=new _t,An=new bt;async function Nn(e=Date.now(),l=wn){const u=xt(),f=await K.runFleetPreamble(u);let v,a;try{const g=await Ie();v=g.filter(c=>c.status==="active"||c.status==="idle"),a=g.filter(c=>c.status==="done"||c.status==="canceled"||c.status==="dead");const p=new Set(a.map(c=>c.node_id));a.push(...(await Pr()).filter(c=>!p.has(c.node_id)))}catch(g){m({level:"error",event:"canvas.node_list.failed",error:g});return}await K.run(e,{rows:v,fleet:u,lifecycle:l}),await vn.run(e,{rows:v});const h=await gn.run(e,{rows:[...v,...a],fleet:u});await Sn.run(e),await $n.run(e),await An.run(e,{lifecycle:l}),await yn.run(e,{lifecycle:l}),await _n.run(e,{lifecycle:l}),await bn.run(e,{lifecycle:l}),await kn.run(e,{lifecycle:l}),await Rn.run(e,{lifecycle:l,fleet:u}),Pn.run(e,{lifecycle:l}),En.run(e,{lifecycle:l}),In.run(e,{lifecycle:l}),xn.run(e,{lifecycle:l}),Tn.run(e,{lifecycle:l}),Dn.run(e,{lifecycle:l}),await ur(),Ln.run(e,{fleet:u,lifecycle:l}),await Cn.run(e,{rows:v}),K.warnIfSaturated({fleet:u,lifecycle:l,thresholds:f,frozen:h})}s(Nn,"superviseTick");function V(e){return e===void 0||e==="reconcile"}s(V,"roleRunsLanes");function A(e){return e===void 0||e==="api"}s(A,"roleServesRequests");const Mn=66e4;function Gn(e){const l=new Ir().registerAll(xr(()=>null).filter(n=>n.pattern==="/healthz")),u=s((n,d)=>{const y=(n.url??"/").split("?")[0];if((n.method??"GET").toUpperCase()==="GET"&&y==="/healthz"){l.handle(n,d,null,{class:"person"});return}d.writeHead(404,{"content-type":"application/json; charset=utf-8"}),d.end(JSON.stringify({error:{code:"not_found",message:"this process serves only /healthz",origin:"runtime"}}))},"handler"),f=Pe();k(f)&&_e(f);const v=J(u),a=new Promise((n,d)=>{v.once("error",d),v.listen(f,()=>{v.off("error",d),be(f,384),n()})});let h,g=null;const p=e.tcp??ke()??se("user").api.tcp;if(p!==void 0&&p!==""){const n=/^(.*):(\d+)$/.exec(p.trim());if(n===null||Number(n[2])>65535)throw new Error(`invalid reconcile probe TCP address: ${p}`);const d=J(u);d.on("error",y=>m({event:"api.server.failed",level:"error",error:y})),d.listen(Number(n[2]),n[1]===""?"0.0.0.0":n[1],()=>{g=`${n[1]===""?"0.0.0.0":n[1]}:${n[2]}`}),h=d}let c=!1;return{ready:a,tcpAddress:s(()=>g,"tcpAddress"),async close(n={}){if(!c){c=!0,await Promise.all([Te(v,new Set,n.graceMs),h===void 0?Promise.resolve():Te(h,new Set,n.graceMs)]);try{k(f)&&_e(f)}catch{}}}}}s(Gn,"createProbeServer");const On="daemon is draining for shutdown and admits no new work";async function Fn(e){ye(Ee(),{recursive:!0,mode:493}),process.platform==="linux"&&be(Ee(),493);const l=Pe();if(k(l))throw new Error(`layout refusal cannot bind occupied socket: ${l}`);const u=J((p,c)=>{if(p.method==="GET"&&p.url==="/healthz"){c.writeHead(200,{"content-type":"application/json; charset=utf-8"}),c.end(JSON.stringify({ok:!1,daemon_up:!0,store_accessible:!1,brokers_reconciled:!1,startup_phase:"blocked",startup_blocked:"layout_migration_required"}));return}c.writeHead(503,{"content-type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:{code:"layout_migration_required",message:"run crtr sys migrate while the runtime is offline",type:"server_error",origin:"runtime",retryable:!1}}))});await new Promise((p,c)=>{u.once("error",c),u.listen(l,()=>{u.off("error",c),p()})});let f;const v=e.tcp??ke();if(v){const p=/^(.*):(\d+)$/.exec(v);if(!p||Number(p[2])>65535)throw new Error(`invalid refusal TCP address: ${v}`);const c=J(u.listeners("request")[0]);await new Promise((n,d)=>{c.once("error",d),c.listen(Number(p[2]),p[1],()=>{c.off("error",d),n()})}),f=c}je();let a;const h=s(()=>(a??=(async()=>{u.closeAllConnections(),f?.closeAllConnections(),await Promise.all([u,f].filter(p=>p!==void 0).map(p=>new Promise((c,n)=>p.close(d=>d?n(d):c())))),Ue(process.pid),process.off("SIGINT",g),process.off("SIGTERM",g)})(),a),"cleanup"),g=s(()=>{h().then(()=>process.exit(0),p=>{process.stderr.write(`[crtrd] layout refusal cleanup failed: ${String(p)}
2
- `),process.exit(1)})},"onSignal");return process.on("SIGINT",g),process.on("SIGTERM",g),h}s(Fn,"serveLayoutRefusal");async function Bn(e={}){if(e.role==="machine")return(await import("./machine-daemon.js")).runMachineDaemon();if(_r())return Fn(e);yr();const l=s(t=>{process.stderr.write(`[crtrd] ${t}
3
- `)},"logPostgres"),u=!!process.env.CRTR_TEST_PG_URL,f=Gt(e.role);Wt(V(e.role));const v=s(async()=>f?await Mt(Re(16).toString("hex")):{claimed:!0,claim:{pid:process.pid,pid_identity:"",token:Re(16).toString("hex")}},"claimOwnership"),{database:a,ownership:h}=u?{database:{url:await Ft()},ownership:await v()}:await Ut(async()=>({database:await Ht({log:l,startLockHeld:!0}),ownership:await v()}));if(!h.claimed){if(h.reason==="incumbent_alive")process.stderr.write(`[crtrd] already running (pid ${h.incumbentPid??"?"})
4
- `);else{const t=[h.incumbentPid!==void 0?`pid ${h.incumbentPid}`:void 0,h.verdict!==void 0?`verdict ${h.verdict}`:void 0].filter(w=>w!==void 0),o=t.length>0?` (${t.join(", ")})`:"";process.stderr.write(`[crtrd] claim lost: ${h.reason}${o}
5
- `),h.reason==="own_identity_indeterminate"&&process.stderr.write("[crtrd] cannot read its own process identity. crouter needs /proc on Linux, or the `ps` command elsewhere (Debian/Ubuntu: apt-get install procps).\n"),(h.reason==="own_identity_indeterminate"||h.reason==="incumbent_malformed")&&(process.exitCode=1)}return async()=>{}}const g=h.claim;let p=null,c=null,n=null,d,y="";try{f&&await fn(g.token);for(const r of kr())process.stderr.write(`[crtrd] ${r}
6
- `);for(const r of await br())process.stderr.write(`[crtrd] ${r}
7
- `);await Me(),await Bt(a.url,l);const t=e.role===void 0&&!await ln();let o=null;t&&(cn({kind:"user",root:Be()}),o=dn(Be())),e.role===void 0&&mn(o??{profiles:[],defaults:{},settings:{},state:{}}),await F.listen(a.url);const w=s(r=>{Fe(r).catch(i=>m({level:"error",event:"daemon.settings.reload_failed",error:i}))},"reloadPerson");if(d=await F.subscribe(r=>{Oe().includes(r)&&w(r)},{kinds:["settings"],onListenStart:s(()=>{for(const r of Oe())w(r)},"onListenStart")}),e.role!==void 0&&Ar(),e.role!==void 0){let r;try{r=Vt()}catch(P){m({level:"error",event:"daemon.packages.snapshot_failed",error:P})}const i=await Ge(async P=>(await De(P),r===void 0?void 0:await Kt(P,r,"release")));for(const P of i?.invalid??[])process.stderr.write(`[crtrd] package file is not a document: ${P.path}: ${P.error}
8
- `)}else{const r=await Ge(async i=>(await De(i),await Jt(i)));for(const i of r.conflicts)process.stderr.write(`[crtrd] plugin documents not reconciled: ${i.message}
9
- `);for(const i of r.invalid)process.stderr.write(`[crtrd] package file is not a document: ${i.path}: ${i.error}
10
- `);for(const i of r.quarantined)process.stderr.write(`[crtrd] plugin "${i.name}" has a damaged ${i.file} (${i.reason}); ${i.movedTo!==void 0?`moved to ${i.movedTo}`:"left in place and skipped"}
11
- `);for(const i of r.kinds.refused)process.stderr.write(`[crtrd] plugin "${i.plugin}" kind ${i.kind} not registered: ${i.message}
12
- `);for(const i of r.kinds.invalid)process.stderr.write(`[crtrd] plugin "${i.plugin}" declares invalid object kinds or scopes; no kinds registered and no app token: ${i.error}
13
- `)}if(y=await At(),Nt(y),e.role===void 0&&(p=await Nr(),p!==null)){if(Gr(p.id),await sn(p.id),process.platform==="darwin"){const{readConfig:r,updateConfig:i}=await import("../core/config.js");if(r("user").paths?.user_files===void 0){const{homedir:P}=await import("node:os");await i("user",Se=>{Se.paths??={},Se.paths.user_files??=P()})}}c=await Mr(),c.joinedFrom!==null&&await Fe(c.person),await tr(),n=await Or()}if(process.platform==="linux"&&k(T)&&(Sr(),await $({operation:"users.sync",users:await wr()})),f){await lt(g.token);const r=await en();Object.values(r).some(i=>i>0)&&process.stderr.write(`[crtrd] node files copied into rows: ${JSON.stringify(r)}
14
- `)}}catch(t){await F.close();try{if(f){const{released:o}=await Ne(g);if(!o)throw new Error("daemon ownership claim was not released")}await le()}catch(o){throw new AggregateError([t,o],"daemon startup failed and cleanup also failed")}throw t}let b=!0,Y,B=Promise.resolve(),Q=!1,H,X,Z,D;const j=new Set;let ee=!1,pe=!1,E,C,re,z=!1,U,N,M,G,te,ne,oe;const qe=Xr();let I,S={phase:"initializing",message:"daemon startup is running the canvas import and normal services are unavailable",blockerPaths:[]},L="initial startup activation",We=null;function Je(){return S.phase==="ready"?null:{phase:S.phase,message:S.message,blockerPaths:S.blockerPaths}}s(Je,"startupBlock");function R(t){j.add(t),t.finally(()=>{j.delete(t)}).catch(()=>{})}s(R,"registerDetached");const fe={acceptsDetachedWork:s(()=>b,"acceptsDetachedWork"),registerDetached:R};V(e.role)&&await Yt(fe,Me);async function Ke(){try{b=!1,qt.close(),X?.(),X=void 0,Z?.(),d?.(),Z=void 0,ne?.(),ne=void 0,await F.close(),H!==void 0&&(clearInterval(H),H=void 0),M!==void 0&&(clearInterval(M),M=void 0),oe?.(),oe=void 0;let t;do t=B,await t;while(t!==B);for(;j.size>0;)await Promise.allSettled([...j]);if(D!==void 0&&(f&&await hn(D),await D.exitsSettled(),D.dispose()),re!==void 0&&await re.close(),C!==void 0&&!z&&(z=!0,await C.close()),te?.(),te=void 0,G!==void 0){const o=G;G=void 0,await o.stop()}if(N!==void 0){const o=N;N=void 0,await o.close()}if(U!==void 0){const o=U;U=void 0,await o.close()}if(ee||(Ue(process.pid),ee=!0),ee&&!pe){if(f){const{released:o}=await Ne(g);if(!o)throw new Error("daemon ownership claim was not released")}pe=!0,await le()}}finally{Dt(),process.off("SIGINT",we),process.off("SIGTERM",ve),process.off("exit",ge)}}s(Ke,"cleanupAttempt");const q=1e3;let ue=!1;function Ve(){return ue?{graceMs:q}:(ue=!0,_.fresh(()=>{m({level:"info",event:"daemon.handover.armed",fields:{pid:process.pid,grace_ms:q}})}),setTimeout(()=>{Ye()},q),{graceMs:q})}s(Ve,"requestHandover");async function Ye(){try{await x()}catch(t){const o=t instanceof Error?t.stack??t.message:String(t);process.stderr.write(`[crtrd] handover cleanup failed:
15
- ${o}
16
- `),process.exit(1)}try{process.platform==="linux"&&k(T)&&(await $({operation:"daemon.handover"}),process.exit(0)),process.pid===1&&await Ct();const t=await Lt({waitForJoinLock:!0});_.fresh(()=>{m({level:"info",event:"daemon.handover.completed",fields:{predecessor_pid:process.pid,successor_pid:t.pid??t.existing_pid??null,spawned:t.started}})})}catch(t){_.fresh(()=>{m({level:"error",event:"daemon.handover.successor_failed",error:t})});const o=t instanceof Error?t.message:String(t);process.stderr.write(`[crtrd] handover successor failed to start: ${o}
17
- `),process.exit(1)}process.exit(0)}s(Ye,"performHandover");function x(){if(E!==void 0)return E;const t=Ke();return E=t,t.then(()=>{E===t&&(E=void 0)},()=>{E===t&&(E=void 0)}),t}s(x,"requestCleanup");async function Qe(){S={phase:"initializing",message:On,blockerPaths:[]},C!==void 0&&!z&&(z=!0,await C.close({graceMs:Mn}))}s(Qe,"drainApi");async function he(t){try{t==="SIGTERM"&&e.role==="api"&&await Qe(),await x(),await zt({claimed:s(async()=>{try{return f&&await Ot()}finally{await le()}},"claimed")}),process.exit(0)}catch(o){process.exitCode=1;const w=o instanceof Error?o.stack??`${o.name}: ${o.message}`:String(o);process.stderr.write(`[crtrd] ${t} cleanup failed:
18
- ${w}
19
- `),process.exit(1)}}s(he,"handleSignal");function we(){he("SIGINT")}s(we,"onSigint");function ve(){he("SIGTERM")}s(ve,"onSigterm");function ge(){x().catch(()=>{})}s(ge,"onExit");async function ie(t){b&&(B=B.then(t).then(()=>{},o=>{_.fresh(()=>{m({level:"error",event:"daemon.lane_job.failed",error:o})})}))}s(ie,"enqueue");async function W(){!b||Q||(qe.check()&&I&&(m({level:"info",event:"daemon.resume.detected"}),R(I().catch(()=>{}))),Q=!0,await ie(async()=>{if(Q=!1,!!b)try{u||await jt({log:l}),await Nn(Date.now(),fe)}catch(t){_.fresh(()=>{m({level:"error",event:"daemon.tick.failed",error:t})})}}))}s(W,"enqueueTick");let O=null;async function Xe(){if(O!==null)throw{status:500,code:"admission_failed",message:`daemon admission previously failed: ${O instanceof Error?O.message:String(O)}`};if(S.phase==="ready")return{admitted:!1,already_admitted:!0,startup_phase:"ready"};if(S.phase!=="prepared"&&S.phase!=="recovering")throw{status:409,code:"not_prepared",message:S.message};const t=S.phase==="prepared";try{return await ae(),S={phase:"ready",message:"",blockerPaths:[]},t?{admitted:!0,already_admitted:!1,startup_phase:"ready"}:{admitted:!1,already_admitted:!0,startup_phase:"ready"}}catch(o){throw O=o,{status:500,code:"admission_failed",message:`daemon admission failed: ${o instanceof Error?o.message:String(o)}`}}}s(Xe,"admitStartup");async function Ze(t){if(L!==null)throw{status:409,code:"migration_in_progress",message:`the canvas import is already running (${L})`};L="repair";try{const o=await an({dryRun:t.dryRun});if(t.dryRun||o.pending||S.phase!=="blocked")return{result:o,resumed:!1};if(e.prepare)return S={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]},{result:o,resumed:!1};try{return await ae(),S={phase:"ready",message:"",blockerPaths:[]},{result:o,resumed:!0}}catch(w){const r=w instanceof Error?w.message:String(w);return setTimeout(()=>{x().catch(()=>{})},1e3),{result:o,resumed:!1,resumeError:r}}}finally{L=null}}s(Ze,"repairMigrations");async function er(){Y=e.intervalMs??Qr;const t=g.token;D=new Zt({epoch:t,enqueue:ie}),It(D),S={phase:"recovering",message:"daemon startup recovery is running and normal services are unavailable",blockerPaths:[]},_.fresh(()=>{m({level:"info",event:"daemon.started",fields:{pid:process.pid,interval_ms:Y}})});const o=y;_.fresh(()=>{m({level:"info",event:"daemon.install_id.resolved",fields:{install_id:o}})});const w=await Lr(o);if(_.fresh(()=>{m({level:"info",event:"daemon.environment.registered",fields:{environment_id:w.environmentId,created:w.created}})}),_.fresh(()=>{let r;try{r=Yr()}catch{return}r!==null&&m({level:"warn",event:"daemon.startup.warning",fields:{stage:"termrender",warning:r.slice(0,2048)}})}),ut(),e.role!==void 0&&!process.env.CRTR_DIRECTORY_URL)throw new Error("CRTR_DIRECTORY_URL must be set on a cloud role (--role api|reconcile): it names the directory this deployment mints tokens against");if(e.role!==void 0&&$r(),!V(e.role)){S={phase:"ready",message:"",blockerPaths:[]};return}if(await _.fresh(async()=>{await Vr(),await Wr(),await Jr(Date.now()),await Kr(Date.now())}),await _.fresh(async()=>{const{reconcile:r,migrated:i}=await $t(ct);r.changed&&m({level:"info",event:"daemon.boot_change.reconciled",fields:{cleared_count:r.cleared.length,same_boot_proven:r.sameBootProven}}),i.length>0&&m({level:"info",event:"daemon.pid_identity.migrated",fields:{migrated_count:i.length}})}),await _.fresh(async()=>{for(const r of await Ie())r.status!=="active"||r.pi_pid!=null||r.frozen_at!=null||r.respawn_not_before!=null||(await xe(r.node_id,new Date().toISOString()),m({level:"warn",event:"daemon.startup.launch_debt_recorded",node_id:r.node_id}))}),await _.fresh(async()=>{await Rt();for(const r of rn){const i=await r.apply();i.changed&&m({level:"info",event:"daemon.boot_migration.applied",fields:{migration:r.id,...i.summary}})}}),R(Ur()),I){const r=s(()=>{R(I().catch(()=>{})),R(or().then(i=>G?.observe(i)).then(()=>{},i=>{m({level:"warn",event:"daemon.peer.status_failed",error:i})}))},"refresh");R(zr().then(({completion:i})=>i).catch(i=>{m({level:"error",event:"daemon.grants.sweep_failed",error:i})})),r(),M=setInterval(r,jr*1e3),M.unref(),oe=nr({joined:!0,register:R})}await ie(async()=>{await Xt(),await Qt()}),H=setInterval(()=>{W().catch(r=>m({level:"error",event:"daemon.tick.failed",error:r}))},Y),X=await kt(()=>{W().catch(r=>m({level:"error",event:"daemon.tick.failed",error:r}))}),Z=await F.subscribe(()=>{W().catch(r=>m({level:"error",event:"daemon.tick.failed",error:r}))},{kinds:["spend_limits"]}),await W(),e.role===void 0&&import("../commands/sys/import/move.js").then(({settleMoveAtDaemonStart:r})=>r(()=>!b,i=>m({level:"warn",event:"daemon.move.settle_failed",error:i}))).catch(r=>m({level:"warn",event:"daemon.move.settle_failed",error:r}))}s(er,"completeStartup");function ae(){return We??=er().catch(t=>{throw S={phase:"initializing",message:"daemon startup recovery failed and normal services are unavailable",blockerPaths:[]},t})}s(ae,"resumeStartup");try{process.on("SIGINT",we),process.on("SIGTERM",ve),process.on("exit",ge),tn(),p!==null&&m({level:"info",event:"daemon.person.resolved",fields:{person_id:p.id,source:p.source}}),n!==null&&m({level:"info",event:"daemon.permissions.boot",fields:{...n}}),c!==null&&m({level:"info",event:"daemon.person.retired",fields:{person_id:c.person,joined_from:c.joinedFrom,retired:c.retired,columns:c.columns}}),A(e.role)?U=await pr():fr(mr());const t=g.token;Tt({epoch:t,requestHandover:Ve,registerDetached:R,startupBlock:Je,admitStartup:Xe,repairMigrations:Ze}),je(),C=A(e.role)?Er({tcp:e.tcp}):Gn(e),await C.ready;const o=dr()??se("user").document_port;if(A(e.role)){const r=Tr(o,Dr());try{await r.ready,re=r}catch(i){m({level:"warn",event:"daemon.document_listener.bind_failed",fields:{port:o,error:i instanceof Error?i.message:String(i)}})}}const w=se("user").runtime;if(w?.issuer&&(I=Hr(w.issuer,R),w.unsandboxed===!0&&(G=ir({syncGrants:I}))),A(e.role)&&(te=await Fr()),ne=await Br({serves:A(e.role),runsLanes:V(e.role)}),w?.unsandboxed===!0&&w.listener!==void 0&&m({level:"warn",event:"daemon.app_listener.refused_unsandboxed",fields:{reason:"runtime.unsandboxed is set; runtime.listener is ignored"}}),A(e.role)&&w!==void 0&&w.listener!==void 0&&w.unsandboxed!==!0&&(N=await Cr(w,async()=>await qr(w.issuer.replace(/\/$/,"")),I),await N.ready),e.role===void 0)try{await nn()}catch(r){if(L=null,r instanceof on)return S={phase:"blocked",message:r.message,blockerPaths:r.blockerPaths},x;throw r}process.platform==="linux"&&k(T)&&(gr(),await vr("app:terminal"));try{e.prepare?S={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]}:(await ae(),S={phase:"ready",message:"",blockerPaths:[]})}finally{L=null}return x}catch(t){try{await x()}catch(o){throw new AggregateError([t,o],"daemon startup failed and cleanup also failed")}throw t}}s(Bn,"runDaemon");var Gi=Bn;export{Mn as API_DRAIN_GRACE_MS,Bi as brokerCommandDeclaresCanvasHome,me as brokerCommandEpoch,Gi as default,V as roleRunsLanes,A as roleServesRequests,Bn as runDaemon,Nn as superviseTick,hn as teardownFleet};
1
+ var nr=Object.defineProperty;var a=(e,l)=>nr(e,"name",{value:l,configurable:!0});import{applyBootSettings as or}from"./boot-settings.js";import{startPeerOutbox as ir}from"./peer/outbox.js";import{reportMachineStatus as ar}from"../core/peer/directory.js";import{createPeerRelay as sr}from"./peer/relay-service.js";import{writeFileSync as cr,readFileSync as lr,rmSync as dr,mkdirSync as be,existsSync as P,unlinkSync as ke,chmodSync as Re}from"node:fs";import{createServer as V}from"node:http";import{dirname as mr}from"node:path";import{envCrtrdTcp as Pe,envDocumentPort as pr}from"../shared/env.js";import{openCanvasConversationStore as fr,serveCanvasConversationStore as ur}from"../core/canvas/sessions.js";import{installConversationStore as wr}from"../core/conversation-store/index.js";import{pollRunObservers as hr}from"./runs/observer.js";import{randomBytes as Ee}from"node:crypto";import{apiSocketPath as Ie,crtrHome as vr}from"../core/canvas/paths.js";import{activeAppUsers as gr}from"../core/spaces/users.js";import{ensureAppSpace as Sr,ensureUserFiles as yr}from"../core/spaces/space.js";import{LAUNCHER_SOCKET as T}from"../launcher/spec.js";import{launcherRequest as A}from"../launcher/client.js";import{installLauncherEventSink as _r}from"./launcher-events.js";import{initializeEmptyLayout as br,layoutNeedsMigration as kr,socketDir as xe}from"../core/layout.js";import{migrateLooseKeys as Rr}from"../core/layout-migrate/loose-keys.js";import{relocateProfileFolders as Pr}from"../core/profiles/relocate.js";import{getNode as Er,listNodesForSupervision as Te,listParkedResidentsWithWakeMail as Ir,setFrozen as De}from"../core/canvas/index.js";import{createApiServer as xr,closeServer as Ce}from"./api/server.js";import{Router as Tr}from"./api/router.js";import{healthRoutes as Dr}from"./api/handlers/health.js";import{createDocumentListener as Cr}from"./api/document-listener.js";import{documentSecret as Lr}from"./api/document-secret.js";import{createAppListener as $r}from"./api/app-listener.js";import{registerMachineEnvironment as Ar}from"../core/environments.js";import{registerBlaxelRunnerFromEnv as Nr}from"../core/secrets/blaxel-register.js";import{markCloudRole as Mr,resolvePerson as Gr,retireLocalPerson as Or,setPersonId as Fr}from"../core/canvas/person.js";import{backfillNodeApps as Le,runPermissionsBoot as Br}from"../core/permissions/boot.js";import{startRunNotices as Hr}from"./run-notices.js";import{startGrantEffects as jr}from"./reconcilers/grant-effects.js";import{syncPackages as zr}from"../core/packages/directory-sync.js";import{createGrantSync as Ur,GRANT_SYNC_INTERVAL_S as $e}from"../core/grants/sync.js";import{sweepSandboxes as qr}from"../core/grants/on-sync.js";import{rebuildCronExecutions as Wr}from"./cron/run-socket.js";import{hasSyncedGrants as Jr}from"../core/grants/mirror.js";import{readConfig as le}from"../core/config.js";import{reconcileUndeliveredTickets as Kr}from"./human/sweep.js";import{resetHandedOffDeliveries as Vr}from"../core/canvas/deliveries.js";import{resetHandedOffDaemonActions as Yr}from"../core/canvas/daemon-actions.js";import{sweepReviews as Qr}from"./review/sweep.js";import{pidfilePath as de}from"./pidfile.js";import{rendererWarning as Xr}from"../core/runtime/package-health.js";import{DEFAULT_INTERVAL_MS as Zr}from"./supervise-cadence.js";import{createResumeDetector as et}from"./resume-detector.js";import{setFatalFaultAnnouncer as rt}from"../core/canvas/recovery.js";import{BrokerSupervisionReconciler as tt}from"./reconcilers/broker-supervision.js";import{ControllerDeathReconciler as nt}from"./reconcilers/controller-death.js";import{NodeLifecycleReconciler as ot}from"./reconcilers/node-lifecycle/tick.js";import{NodeDeadlineReconciler as it}from"./reconcilers/node-deadline.js";import{CronLaneReconciler as at}from"./reconcilers/cron-lane.js";import{DeliveryLaneReconciler as st}from"./reconcilers/delivery-lane.js";import{ActionLaneReconciler as ct}from"./reconcilers/action-lane.js";import{endLiveExecution as lt,migrateLegacyExecutionIdentities as dt}from"../core/canvas/executions.js";import{revokePriorEpochNodeTokens as mt}from"../core/canvas/node-tokens.js";import{PendingReviewSubmitReconciler as pt}from"./reconcilers/pending-review-submit.js";import{StorageMaintenanceReconciler as ft}from"./reconcilers/storage-maintenance.js";import{StorageDueWorkReconciler as ut}from"./reconcilers/storage-due-work.js";import{PurgeDueWorkReconciler as wt}from"./reconcilers/purge-due-work.js";import{assertLedgerEnv as ht}from"../core/ledger/rates.js";import{LedgerSandboxReconciler as vt}from"./reconcilers/ledger-sandbox.js";import{LedgerStorageReconciler as gt}from"./reconcilers/ledger-storage.js";import{LedgerR2Reconciler as St}from"./reconcilers/ledger-r2.js";import{ImportLaneReconciler as yt}from"./reconcilers/import-lane.js";import{BashDeadlineReconciler as _t}from"./reconcilers/bash-deadline.js";import{FaultRetryBackstopReconciler as bt}from"./reconcilers/fault-retry-backstop.js";import{StructuredRequestReconciler as kt}from"./reconcilers/structured-request-lane.js";import{RecipeImageReconciler as Rt,subscribeImageBuilt as Pt}from"./reconcilers/recipe-image.js";import{reconcileStructuredRequestSidecars as Et}from"./structured-requests/boot.js";import{captureLivenessSnapshot as Ae,capturePidCommand as It,captureTeardownSnapshot as Ne,isPidAlive as xt,isAnyPidAlive as Me,killProcessTreePids as Ge}from"../core/canvas/pid.js";import{bindFleet as Tt,boundFleet as Dt}from"../core/runtime/fleet.js";import{bindDaemonControl as Ct,clearDaemonControl as Lt}from"./control.js";import{execDaemon as $t,spawnDaemon as At}from"./manage.js";import{reconcileAndMigrateBoot as Nt}from"../core/canvas/boot.js";import{resolveInstallId as Mt}from"../core/canvas/install-id.js";import{setInstallId as Gt}from"../core/runtime/nodes.js";import{claimDaemonOwnership as Ot,daemonOwnershipApplies as Ft,daemonOwnershipClaimed as Bt,releaseDaemonOwnership as Oe}from"../core/canvas/daemon-owner.js";import{canvasDatabaseUrl as Ht,closeAllDbs as me,openDb as Fe,withCanvasWrite as pe}from"../core/canvas/db.js";import{importSqliteCanvasIfPresent as jt}from"../core/canvas/import-sqlite.js";import{ensurePostgres as zt,ensurePostgresHealthy as Ut,stopPostgres as qt,withPostgresStartLock as Wt}from"./postgres/index.js";import{brokerSignalBus as H}from"./broker-signals/bus.js";import{brokerSignalStreams as Jt}from"./api/handlers/broker-signals.js";import{setRequestsStartRunObservers as Kt}from"./api/handlers/broker-ops.js";import{reconcilePackages as Vt}from"../core/graph/package-reconcile.js";import{migrateAppInstalls as Yt}from"../core/scoped-state/migrate-app-installs.js";import{publish as Qt,readBuiltinSnapshot as Xt}from"../core/graph/package-publish.js";import{startRepoSync as Zt}from"../core/graph/repo-sync/index.js";import{prewarmRecentRecipes as en,reapStaleSpares as rn}from"../core/runtime/warm-pool.js";import{DaemonFleet as tn}from"./fleet.js";import{copyNodeFilesToRows as nn}from"../core/runtime/first-boot-rows.js";import{BOOT_MIGRATIONS as on}from"./boot-migrations.js";import{emitEvent as d}from"../core/events/emit.js";import{operationIdContext as _}from"../core/events/operation-id.js";import{bindDaemonEventSource as an}from"../core/events/source.js";import{activateCanvasImport as sn,MigrationBlockedError as cn,runForcedCanvasImport as ln}from"../migrations/activation.js";import{adoptInstallPerson as dn,convertLegacyScopedStore as mn,personStoresCopied as pn}from"../core/scoped-state/migrate.js";import{readLegacyUserSnapshot as fn}from"../core/scoped-state/legacy-profiles.js";import{heldPersons as Be,installPreludeSnapshot as un}from"../core/scoped-state/person-store.js";import{loadPersonSettings as He}from"../core/scoped-state/person-rows.js";import{userScopeRoot as je}from"../core/scope.js";import{brokerCommandDeclaresCanvasHome as fe}from"../core/runtime/broker-ownership.js";import{brokerCommandDeclaresCanvasHome as qi}from"../core/runtime/broker-ownership.js";function ue(e){return/ --epoch (\S+) /.exec(e)?.[1]??null}a(ue,"brokerCommandEpoch");const wn=5e3,ze=150;async function hn(e){const l=Ae();if(l===null)throw d({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness"}}),new Error("prior-epoch broker census could not capture the process table");const u=vr(),f=[];for(const[n,m]of l.processes){const y=m.command;if(m.zombie||!y.includes("broker-cli.js")||!fe(y,u)||ue(y)===e)continue;const k=y.trim().split(/\s+/).at(-1)??"";k===""||k.endsWith("broker-cli.js")||f.push({pid:n,nodeId:k})}let v=0;const s=[];for(const n of f){const m=It(n.pid);if(m===null||!m.includes("broker-cli.js")||!fe(m,u)||ue(m)===e||m.trim().split(/\s+/).at(-1)!==n.nodeId)continue;const y=Ne(n.pid,null);if(!y.reused){try{process.platform==="linux"&&P(T)?await A({operation:"stop",pid:n.pid}):process.kill(n.pid,"SIGTERM")}catch{continue}v++,s.push({pid:n.pid,snap:y})}}const w=Date.now()+wn;for(;Date.now()<w&&s.some(n=>Me(n.snap.tree.length>0?n.snap.tree:[n.pid]));)await new Promise(n=>setTimeout(n,ze));let g=0;for(const n of s){const m=n.snap.tree.length>0?n.snap.tree:[n.pid];Me(m)&&(process.platform==="linux"&&P(T)?await A({operation:"stop",pid:n.pid}):Ge(m,"SIGKILL",n.snap.identities),g++)}g>0&&await new Promise(n=>setTimeout(n,ze));const p=Ae();if(p===null)throw d({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness",stage:"final"}}),new Error("prior-epoch broker census could not capture the final process table");const c=[];for(const[n,m]of p.processes){const y=m.command;m.zombie||!y.includes("broker-cli.js")||fe(y,u)&&ue(y)!==e&&c.push(n)}if(c.length>0)throw new Error(`prior-epoch broker census could not prove termination of pid(s): ${c.join(", ")}`);d({level:"info",event:"daemon.census.completed",fields:{prior_epoch_brokers:f.length,sigtermed:v,sigkilled:g}})}a(hn,"reapPriorEpochBrokers");const vn=5e3;async function gn(e){const l=Array.from(e.entries());if(l.length===0)return;for(const[s]of l){const w=(await Er(s))?.status;(w==="active"||w==="idle")&&await De(s,new Date().toISOString())}const u=l.map(([,s])=>({pid:s.pid,snap:Ne(s.pid,null),exited:s.handle.exited}));for(const s of u)if(!s.snap.reused)try{process.platform==="linux"&&P(T)?await A({operation:"stop",pid:s.pid}):process.kill(s.pid,"SIGTERM")}catch{}const f=new Promise(s=>{setTimeout(s,vn).unref()});await Promise.allSettled(u.map(s=>Promise.race([s.exited.then(()=>{}),f])));const v=[];for(const s of u)xt(s.pid)&&(process.platform==="linux"&&P(T)?await A({operation:"stop",pid:s.pid}):Ge(s.snap.tree.length>0?s.snap.tree:[s.pid],"SIGKILL",s.snap.identities),v.push(s));await Promise.all(v.map(s=>s.exited));for(const[s]of l)await lt(s,{reason:"daemon-teardown"});d({level:"info",event:"daemon.fleet_teardown.completed",fields:{brokers:u.length,sigkilled:v.length}})}a(gn,"teardownFleet");function Ue(){be(mr(de()),{recursive:!0}),cr(de(),String(process.pid),"utf8")}a(Ue,"writePidfile");function qe(e){return typeof e=="object"&&e!==null&&e.code==="ENOENT"}a(qe,"isMissingPathError");function We(e){const l=de();let u;try{u=lr(l,"utf8")}catch(f){if(qe(f))return;throw f}if(u.trim()!==String(e))throw new Error(`daemon readiness mirror does not name this invocation (expected pid ${e})`);try{dr(l)}catch(f){if(qe(f))return;throw f}}a(We,"removeOwnedPidfileMirror");const Sn={acceptsDetachedWork:a(()=>!0,"acceptsDetachedWork"),registerDetached:a(e=>{e.catch(()=>{})},"registerDetached")},Y=new tt;rt(e=>Y.handleFatalFault(e,!1));const yn=new nt,_n=new ot,bn=new it,kn=new at,Rn=new st,Pn=new ct,En=new pt,In=new ft,xn=new ut,Tn=new wt,Dn=new vt,Cn=new gt,Ln=new St,$n=new yt,An=new _t,Nn=new bt,Mn=new kt,Gn=new Rt;async function On(e=Date.now(),l=Sn){const u=Dt(),f=await Y.runFleetPreamble(u);let v,s;try{const g=await Te();v=g.filter(c=>c.status==="active"||c.status==="idle"),s=g.filter(c=>c.status==="done"||c.status==="canceled"||c.status==="dead");const p=new Set(s.map(c=>c.node_id));s.push(...(await Ir()).filter(c=>!p.has(c.node_id)))}catch(g){d({level:"error",event:"canvas.node_list.failed",error:g});return}await Y.run(e,{rows:v,fleet:u,lifecycle:l}),await yn.run(e,{rows:v});const w=await _n.run(e,{rows:[...v,...s],fleet:u});await bn.run(e),await Mn.run(e),await Gn.run(e,{lifecycle:l}),await kn.run(e,{lifecycle:l}),await Rn.run(e,{lifecycle:l}),await Pn.run(e,{lifecycle:l}),await En.run(e,{lifecycle:l}),await In.run(e,{lifecycle:l,fleet:u}),xn.run(e,{lifecycle:l}),Tn.run(e,{lifecycle:l}),Dn.run(e,{lifecycle:l}),Cn.run(e,{lifecycle:l}),Ln.run(e,{lifecycle:l}),$n.run(e,{lifecycle:l}),await hr(),Nn.run(e,{fleet:u,lifecycle:l}),await An.run(e,{rows:v}),Y.warnIfSaturated({fleet:u,lifecycle:l,thresholds:f,frozen:w})}a(On,"superviseTick");function Q(e){return e===void 0||e==="reconcile"}a(Q,"roleRunsLanes");function N(e){return e===void 0||e==="api"}a(N,"roleServesRequests");const Fn=66e4;function Bn(e){const l=new Tr().registerAll(Dr(()=>null).filter(n=>n.pattern==="/healthz")),u=a((n,m)=>{const y=(n.url??"/").split("?")[0];if((n.method??"GET").toUpperCase()==="GET"&&y==="/healthz"){l.handle(n,m,null,{class:"person"});return}m.writeHead(404,{"content-type":"application/json; charset=utf-8"}),m.end(JSON.stringify({error:{code:"not_found",message:"this process serves only /healthz",origin:"runtime"}}))},"handler"),f=Ie();P(f)&&ke(f);const v=V(u),s=new Promise((n,m)=>{v.once("error",m),v.listen(f,()=>{v.off("error",m),Re(f,384),n()})});let w,g=null;const p=e.tcp??Pe()??le("user").api.tcp;if(p!==void 0&&p!==""){const n=/^(.*):(\d+)$/.exec(p.trim());if(n===null||Number(n[2])>65535)throw new Error(`invalid reconcile probe TCP address: ${p}`);const m=V(u);m.on("error",y=>d({event:"api.server.failed",level:"error",error:y})),m.listen(Number(n[2]),n[1]===""?"0.0.0.0":n[1],()=>{g=`${n[1]===""?"0.0.0.0":n[1]}:${n[2]}`}),w=m}let c=!1;return{ready:s,tcpAddress:a(()=>g,"tcpAddress"),async close(n={}){if(!c){c=!0,await Promise.all([Ce(v,new Set,n.graceMs),w===void 0?Promise.resolve():Ce(w,new Set,n.graceMs)]);try{P(f)&&ke(f)}catch{}}}}}a(Bn,"createProbeServer");const Hn="daemon is draining for shutdown and admits no new work";async function jn(e){be(xe(),{recursive:!0,mode:493}),process.platform==="linux"&&Re(xe(),493);const l=Ie();if(P(l))throw new Error(`layout refusal cannot bind occupied socket: ${l}`);const u=V((p,c)=>{if(p.method==="GET"&&p.url==="/healthz"){c.writeHead(200,{"content-type":"application/json; charset=utf-8"}),c.end(JSON.stringify({ok:!1,daemon_up:!0,store_accessible:!1,brokers_reconciled:!1,startup_phase:"blocked",startup_blocked:"layout_migration_required"}));return}c.writeHead(503,{"content-type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:{code:"layout_migration_required",message:"run crtr sys migrate while the runtime is offline",type:"server_error",origin:"runtime",retryable:!1}}))});await new Promise((p,c)=>{u.once("error",c),u.listen(l,()=>{u.off("error",c),p()})});let f;const v=e.tcp??Pe();if(v){const p=/^(.*):(\d+)$/.exec(v);if(!p||Number(p[2])>65535)throw new Error(`invalid refusal TCP address: ${v}`);const c=V(u.listeners("request")[0]);await new Promise((n,m)=>{c.once("error",m),c.listen(Number(p[2]),p[1],()=>{c.off("error",m),n()})}),f=c}Ue();let s;const w=a(()=>(s??=(async()=>{u.closeAllConnections(),f?.closeAllConnections(),await Promise.all([u,f].filter(p=>p!==void 0).map(p=>new Promise((c,n)=>p.close(m=>m?n(m):c())))),We(process.pid),process.off("SIGINT",g),process.off("SIGTERM",g)})(),s),"cleanup"),g=a(()=>{w().then(()=>process.exit(0),p=>{process.stderr.write(`[crtrd] layout refusal cleanup failed: ${String(p)}
2
+ `),process.exit(1)})},"onSignal");return process.on("SIGINT",g),process.on("SIGTERM",g),w}a(jn,"serveLayoutRefusal");async function zn(e={}){if(e.role==="machine")return(await import("./machine-daemon.js")).runMachineDaemon();if(kr())return jn(e);br();const l=a(t=>{process.stderr.write(`[crtrd] ${t}
3
+ `)},"logPostgres"),u=!!process.env.CRTR_TEST_PG_URL,f=Ft(e.role);Kt(Q(e.role));const v=a(async()=>f?await Ot(Ee(16).toString("hex")):{claimed:!0,claim:{pid:process.pid,pid_identity:"",token:Ee(16).toString("hex")}},"claimOwnership"),{database:s,ownership:w}=u?{database:{url:await Ht()},ownership:await v()}:await Wt(async()=>({database:await zt({log:l,startLockHeld:!0}),ownership:await v()}));if(!w.claimed){if(w.reason==="incumbent_alive")process.stderr.write(`[crtrd] already running (pid ${w.incumbentPid??"?"})
4
+ `);else{const t=[w.incumbentPid!==void 0?`pid ${w.incumbentPid}`:void 0,w.verdict!==void 0?`verdict ${w.verdict}`:void 0].filter(h=>h!==void 0),i=t.length>0?` (${t.join(", ")})`:"";process.stderr.write(`[crtrd] claim lost: ${w.reason}${i}
5
+ `),w.reason==="own_identity_indeterminate"&&process.stderr.write("[crtrd] cannot read its own process identity. crouter needs /proc on Linux, or the `ps` command elsewhere (Debian/Ubuntu: apt-get install procps).\n"),(w.reason==="own_identity_indeterminate"||w.reason==="incumbent_malformed")&&(process.exitCode=1)}return async()=>{}}const g=w.claim;let p=null,c=null,n=null,m,y="";try{f&&await hn(g.token);for(const r of Pr())process.stderr.write(`[crtrd] ${r}
6
+ `);for(const r of await Rr())process.stderr.write(`[crtrd] ${r}
7
+ `);await Fe(),await jt(s.url,l);const t=e.role===void 0&&!await pn();let i=null;t&&(mn({kind:"user",root:je()}),i=fn(je())),e.role===void 0&&un(i??{profiles:[],defaults:{},settings:{},state:{},apps:{}}),await H.listen(s.url);const h=a(r=>{He(r).catch(o=>d({level:"error",event:"daemon.settings.reload_failed",error:o}))},"reloadPerson");if(m=await H.subscribe(r=>{Be().includes(r)&&h(r)},{kinds:["settings"],onListenStart:a(()=>{for(const r of Be())h(r)},"onListenStart")}),e.role!==void 0&&Mr(),e.role!==void 0){let r;try{r=Xt()}catch(b){d({level:"error",event:"daemon.packages.snapshot_failed",error:b})}const o=await pe(async b=>(await Le(b),r===void 0?void 0:await Qt(b,r,"release"))),$=await pe(async b=>await Yt(b));$.alreadyDone||d({level:"info",event:"daemon.packages.install_migration_done",fields:{moved:$.moved,discarded:$.discarded,people:$.people}});for(const b of o?.invalid??[])process.stderr.write(`[crtrd] package file is not a document: ${b.path}: ${b.error}
8
+ `)}else{const r=await pe(async o=>(await Le(o),await Vt(o)));for(const o of r.conflicts)process.stderr.write(`[crtrd] plugin documents not reconciled: ${o.message}
9
+ `);for(const o of r.invalid)process.stderr.write(`[crtrd] package file is not a document: ${o.path}: ${o.error}
10
+ `);for(const o of r.quarantined)process.stderr.write(`[crtrd] plugin "${o.name}" has a damaged ${o.file} (${o.reason}); ${o.movedTo!==void 0?`moved to ${o.movedTo}`:"left in place and skipped"}
11
+ `);for(const o of r.kinds.refused)process.stderr.write(`[crtrd] plugin "${o.plugin}" kind ${o.kind} not registered: ${o.message}
12
+ `);for(const o of r.kinds.invalid)process.stderr.write(`[crtrd] plugin "${o.plugin}" declares invalid object kinds or scopes; no kinds registered and no app token: ${o.error}
13
+ `)}if(y=await Mt(),Gt(y),e.role===void 0&&(p=await Gr(),p!==null)){if(Fr(p.id),await dn(p.id),process.platform==="darwin"){const{readConfig:r,updateConfig:o}=await import("../core/config.js");if(r("user").paths?.user_files===void 0){const{homedir:$}=await import("node:os");await o("user",b=>{b.paths??={},b.paths.user_files??=$()})}}c=await Or(),c.joinedFrom!==null&&await He(c.person),await or(),n=await Br()}if(process.platform==="linux"&&P(T)&&(_r(),await A({operation:"users.sync",users:await gr()})),f){await mt(g.token);const r=await nn();Object.values(r).some(o=>o>0)&&process.stderr.write(`[crtrd] node files copied into rows: ${JSON.stringify(r)}
14
+ `)}}catch(t){await H.close();try{if(f){const{released:i}=await Oe(g);if(!i)throw new Error("daemon ownership claim was not released")}await me()}catch(i){throw new AggregateError([t,i],"daemon startup failed and cleanup also failed")}throw t}let k=!0,X,j=Promise.resolve(),Z=!1,z,ee,re,D;const U=new Set;let te=!1,we=!1,E,C,ne,q=!1,W,M,G,O,F,oe,ie,ae;const Je=et();let I,S={phase:"initializing",message:"daemon startup is running the canvas import and normal services are unavailable",blockerPaths:[]},L="initial startup activation",Ke=null;function Ve(){return S.phase==="ready"?null:{phase:S.phase,message:S.message,blockerPaths:S.blockerPaths}}a(Ve,"startupBlock");function R(t){U.add(t),t.finally(()=>{U.delete(t)}).catch(()=>{})}a(R,"registerDetached");const he={acceptsDetachedWork:a(()=>k,"acceptsDetachedWork"),registerDetached:R};Q(e.role)&&await Zt(he,Fe);async function Ye(){try{k=!1,Jt.close(),ee?.(),ee=void 0,re?.(),m?.(),re=void 0,ie?.(),ie=void 0,await H.close(),z!==void 0&&(clearInterval(z),z=void 0),G!==void 0&&(clearInterval(G),G=void 0),O!==void 0&&(clearInterval(O),O=void 0),ae?.(),ae=void 0;let t;do t=j,await t;while(t!==j);for(;U.size>0;)await Promise.allSettled([...U]);if(D!==void 0&&(f&&await gn(D),await D.exitsSettled(),D.dispose()),ne!==void 0&&await ne.close(),C!==void 0&&!q&&(q=!0,await C.close()),oe?.(),oe=void 0,F!==void 0){const i=F;F=void 0,await i.stop()}if(M!==void 0){const i=M;M=void 0,await i.close()}if(W!==void 0){const i=W;W=void 0,await i.close()}if(te||(We(process.pid),te=!0),te&&!we){if(f){const{released:i}=await Oe(g);if(!i)throw new Error("daemon ownership claim was not released")}we=!0,await me()}}finally{Lt(),process.off("SIGINT",Se),process.off("SIGTERM",ye),process.off("exit",_e)}}a(Ye,"cleanupAttempt");const J=1e3;let ve=!1;function Qe(){return ve?{graceMs:J}:(ve=!0,_.fresh(()=>{d({level:"info",event:"daemon.handover.armed",fields:{pid:process.pid,grace_ms:J}})}),setTimeout(()=>{Xe()},J),{graceMs:J})}a(Qe,"requestHandover");async function Xe(){try{await x()}catch(t){const i=t instanceof Error?t.stack??t.message:String(t);process.stderr.write(`[crtrd] handover cleanup failed:
15
+ ${i}
16
+ `),process.exit(1)}try{process.platform==="linux"&&P(T)&&(await A({operation:"daemon.handover"}),process.exit(0)),process.pid===1&&await $t();const t=await At({waitForJoinLock:!0});_.fresh(()=>{d({level:"info",event:"daemon.handover.completed",fields:{predecessor_pid:process.pid,successor_pid:t.pid??t.existing_pid??null,spawned:t.started}})})}catch(t){_.fresh(()=>{d({level:"error",event:"daemon.handover.successor_failed",error:t})});const i=t instanceof Error?t.message:String(t);process.stderr.write(`[crtrd] handover successor failed to start: ${i}
17
+ `),process.exit(1)}process.exit(0)}a(Xe,"performHandover");function x(){if(E!==void 0)return E;const t=Ye();return E=t,t.then(()=>{E===t&&(E=void 0)},()=>{E===t&&(E=void 0)}),t}a(x,"requestCleanup");async function Ze(){S={phase:"initializing",message:Hn,blockerPaths:[]},C!==void 0&&!q&&(q=!0,await C.close({graceMs:Fn}))}a(Ze,"drainApi");async function ge(t){try{t==="SIGTERM"&&e.role==="api"&&await Ze(),await x(),await qt({claimed:a(async()=>{try{return f&&await Bt()}finally{await me()}},"claimed")}),process.exit(0)}catch(i){process.exitCode=1;const h=i instanceof Error?i.stack??`${i.name}: ${i.message}`:String(i);process.stderr.write(`[crtrd] ${t} cleanup failed:
18
+ ${h}
19
+ `),process.exit(1)}}a(ge,"handleSignal");function Se(){ge("SIGINT")}a(Se,"onSigint");function ye(){ge("SIGTERM")}a(ye,"onSigterm");function _e(){x().catch(()=>{})}a(_e,"onExit");async function se(t){k&&(j=j.then(t).then(()=>{},i=>{_.fresh(()=>{d({level:"error",event:"daemon.lane_job.failed",error:i})})}))}a(se,"enqueue");async function K(){!k||Z||(Je.check()&&I&&(d({level:"info",event:"daemon.resume.detected"}),R(I().catch(()=>{}))),Z=!0,await se(async()=>{if(Z=!1,!!k)try{u||await Ut({log:l}),await On(Date.now(),he)}catch(t){_.fresh(()=>{d({level:"error",event:"daemon.tick.failed",error:t})})}}))}a(K,"enqueueTick");let B=null;async function er(){if(B!==null)throw{status:500,code:"admission_failed",message:`daemon admission previously failed: ${B instanceof Error?B.message:String(B)}`};if(S.phase==="ready")return{admitted:!1,already_admitted:!0,startup_phase:"ready"};if(S.phase!=="prepared"&&S.phase!=="recovering")throw{status:409,code:"not_prepared",message:S.message};const t=S.phase==="prepared";try{return await ce(),S={phase:"ready",message:"",blockerPaths:[]},t?{admitted:!0,already_admitted:!1,startup_phase:"ready"}:{admitted:!1,already_admitted:!0,startup_phase:"ready"}}catch(i){throw B=i,{status:500,code:"admission_failed",message:`daemon admission failed: ${i instanceof Error?i.message:String(i)}`}}}a(er,"admitStartup");async function rr(t){if(L!==null)throw{status:409,code:"migration_in_progress",message:`the canvas import is already running (${L})`};L="repair";try{const i=await ln({dryRun:t.dryRun});if(t.dryRun||i.pending||S.phase!=="blocked")return{result:i,resumed:!1};if(e.prepare)return S={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]},{result:i,resumed:!1};try{return await ce(),S={phase:"ready",message:"",blockerPaths:[]},{result:i,resumed:!0}}catch(h){const r=h instanceof Error?h.message:String(h);return setTimeout(()=>{x().catch(()=>{})},1e3),{result:i,resumed:!1,resumeError:r}}}finally{L=null}}a(rr,"repairMigrations");async function tr(){X=e.intervalMs??Zr;const t=g.token;D=new tn({epoch:t,enqueue:se}),Tt(D),S={phase:"recovering",message:"daemon startup recovery is running and normal services are unavailable",blockerPaths:[]},_.fresh(()=>{d({level:"info",event:"daemon.started",fields:{pid:process.pid,interval_ms:X}})});const i=y;_.fresh(()=>{d({level:"info",event:"daemon.install_id.resolved",fields:{install_id:i}})});const h=await Ar(i);if(_.fresh(()=>{d({level:"info",event:"daemon.environment.registered",fields:{environment_id:h.environmentId,created:h.created}})}),_.fresh(()=>{let r;try{r=Xr()}catch{return}r!==null&&d({level:"warn",event:"daemon.startup.warning",fields:{stage:"termrender",warning:r.slice(0,2048)}})}),ht(),e.role!==void 0&&!process.env.CRTR_DIRECTORY_URL)throw new Error("CRTR_DIRECTORY_URL must be set on a cloud role (--role api|reconcile): it names the directory this deployment mints tokens against");if(e.role!==void 0&&Nr(),!Q(e.role)){S={phase:"ready",message:"",blockerPaths:[]};return}if(await _.fresh(async()=>{await Qr(),await Kr(),await Vr(Date.now()),await Yr(Date.now())}),await _.fresh(async()=>{const{reconcile:r,migrated:o}=await Nt(dt);r.changed&&d({level:"info",event:"daemon.boot_change.reconciled",fields:{cleared_count:r.cleared.length,same_boot_proven:r.sameBootProven}}),o.length>0&&d({level:"info",event:"daemon.pid_identity.migrated",fields:{migrated_count:o.length}})}),await _.fresh(async()=>{for(const r of await Te())r.status!=="active"||r.pi_pid!=null||r.frozen_at!=null||r.respawn_not_before!=null||(await De(r.node_id,new Date().toISOString()),d({level:"warn",event:"daemon.startup.launch_debt_recorded",node_id:r.node_id}))}),await _.fresh(async()=>{await Et();for(const r of on){const o=await r.apply();o.changed&&d({level:"info",event:"daemon.boot_migration.applied",fields:{migration:r.id,...o.summary}})}}),R(Wr()),I){const r=a(()=>{R(I().catch(()=>{})),R(ar().then(o=>F?.observe(o)).then(()=>{},o=>{d({level:"warn",event:"daemon.peer.status_failed",error:o})}))},"refresh");R(qr().then(({completion:o})=>o).catch(o=>{d({level:"error",event:"daemon.grants.sweep_failed",error:o})})),r(),G=setInterval(r,$e*1e3),G.unref(),ae=ir({joined:!0,register:R})}await se(async()=>{await rn(),await en()}),z=setInterval(()=>{K().catch(r=>d({level:"error",event:"daemon.tick.failed",error:r}))},X),ee=await Pt(()=>{K().catch(r=>d({level:"error",event:"daemon.tick.failed",error:r}))}),re=await H.subscribe(()=>{K().catch(r=>d({level:"error",event:"daemon.tick.failed",error:r}))},{kinds:["spend_limits"]}),await K(),e.role===void 0&&import("../commands/sys/import/move.js").then(({settleMoveAtDaemonStart:r})=>r(()=>!k,o=>d({level:"warn",event:"daemon.move.settle_failed",error:o}))).catch(r=>d({level:"warn",event:"daemon.move.settle_failed",error:r}))}a(tr,"completeStartup");function ce(){return Ke??=tr().catch(t=>{throw S={phase:"initializing",message:"daemon startup recovery failed and normal services are unavailable",blockerPaths:[]},t})}a(ce,"resumeStartup");try{process.on("SIGINT",Se),process.on("SIGTERM",ye),process.on("exit",_e),an(),p!==null&&d({level:"info",event:"daemon.person.resolved",fields:{person_id:p.id,source:p.source}}),n!==null&&d({level:"info",event:"daemon.permissions.boot",fields:{...n}}),c!==null&&d({level:"info",event:"daemon.person.retired",fields:{person_id:c.person,joined_from:c.joinedFrom,retired:c.retired,columns:c.columns}}),N(e.role)?W=await ur():wr(fr());const t=g.token;Ct({epoch:t,requestHandover:Qe,registerDetached:R,startupBlock:Ve,admitStartup:er,repairMigrations:rr}),Ue(),C=N(e.role)?xr({tcp:e.tcp}):Bn(e),await C.ready;const i=pr()??le("user").document_port;if(N(e.role)){const r=Cr(i,Lr());try{await r.ready,ne=r}catch(o){d({level:"warn",event:"daemon.document_listener.bind_failed",fields:{port:i,error:o instanceof Error?o.message:String(o)}})}}const h=le("user").runtime;if(h?.issuer&&(I=Ur(h.issuer,R),h.unsandboxed===!0&&(F=sr({syncGrants:I}))),e.role==="api"){const r=a(()=>R(zr().catch(o=>{d({level:"error",event:"daemon.packages.sync_failed",error:o})})),"packageTick");r(),O=setInterval(r,$e*1e3),O.unref()}if(N(e.role)&&(oe=await Hr()),ie=await jr({serves:N(e.role),runsLanes:Q(e.role)}),h?.unsandboxed===!0&&h.listener!==void 0&&d({level:"warn",event:"daemon.app_listener.refused_unsandboxed",fields:{reason:"runtime.unsandboxed is set; runtime.listener is ignored"}}),N(e.role)&&h!==void 0&&h.listener!==void 0&&h.unsandboxed!==!0&&(M=await $r(h,async()=>await Jr(h.issuer.replace(/\/$/,"")),I),await M.ready),e.role===void 0)try{await sn()}catch(r){if(L=null,r instanceof cn)return S={phase:"blocked",message:r.message,blockerPaths:r.blockerPaths},x;throw r}process.platform==="linux"&&P(T)&&(yr(),await Sr("app:terminal"));try{e.prepare?S={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]}:(await ce(),S={phase:"ready",message:"",blockerPaths:[]})}finally{L=null}return x}catch(t){try{await x()}catch(i){throw new AggregateError([t,i],"daemon startup failed and cleanup also failed")}throw t}}a(zn,"runDaemon");var ji=zn;export{Fn as API_DRAIN_GRACE_MS,qi as brokerCommandDeclaresCanvasHome,ue as brokerCommandEpoch,ji as default,Q as roleRunsLanes,N as roleServesRequests,zn as runDaemon,On as superviseTick,gn as teardownFleet};
@@ -26,7 +26,8 @@ export declare function imageForWake(environmentId: string): Promise<Environment
26
26
  * a new attempt on the accepted one. `lost` means no broker answered: the execution is ended and the caller starts a new attempt. */
27
27
  export declare function wakeResident(execution: Execution): Promise<'woken' | 'lost'>;
28
28
  /** A `running` remote execution is live while its runner reports the broker process running, frozen or not. When the runner
29
- * reports it gone (or ended non-zero), that exact execution is ended; a runner that cannot tell leaves it as it is. */
29
+ * reports it gone (or ended non-zero), that exact execution is ended; a runner that cannot tell leaves it as it is. An idle
30
+ * execution is asked without touching its workload (`RunnerStatusOptions.idle`), so a frozen sandbox is not woken by the question. */
30
31
  export declare function endRemoteExecutionIfGone(execution: Execution): Promise<boolean>;
31
32
  /** The recovery table for a `launching` Blaxel execution found by a claim after its starter is gone. */
32
33
  export declare function recoverLaunching(nodeId: string, now: number): Promise<void>;
@@ -1 +1 @@
1
- var f=Object.defineProperty;var a=(e,t)=>f(e,"name",{value:t,configurable:!0});import{liveExecutionForNode as m,endExecution as l,recordExecutionAwake as p,endLaunchingExecution as s,requestExecutionStop as w}from"../../../core/canvas/executions.js";import{openDb as h}from"../../../core/canvas/db.js";import{isCloudRole as _}from"../../../core/canvas/person-state.js";import{emitEvent as u}from"../../../core/events/emit.js";import{findRefusal as x,refusalError as E,refusedMark as g,writeCharge as v}from"../../../core/ledger/index.js";import{transition as c}from"../../../core/runtime/lifecycle.js";import{runnerForExecution as d}from"../../../core/runtime/runner/index.js";import{machineEnvironmentOfProfile as b}from"../../../core/runtime/runner/machine/environment.js";import{startCandidateOf as k}from"../../../core/runtime/start-check.js";import{settleSandboxBeforeWake as y}from"../ledger-sandbox.js";import{crtrVersion as I}from"../../../shared/crtr-version.js";import{resolveEnvironmentImage as S}from"../recipe-image.js";const L=45*6e4,A=12e4,D=a(()=>I(),"acceptedRelease");async function G(e){return e===null||!_()?null:await b(e)}a(G,"remoteMachineEnvironmentOf");async function q(e){const t=await k(e);if(t===null)return;const n={scope:"call",payer:t.payer,funding:"bill",sub:t.sub,grantee:t.grantee,provider:"blaxel"},r=await x(n),o=await h();if(r===null){await o.prepare("UPDATE nodes SET spend_refusal = NULL WHERE node_id = ? AND spend_refusal IS NOT NULL").run(e.node_id);return}throw await o.prepare("UPDATE nodes SET spend_refusal = ? WHERE node_id = ?").run(JSON.stringify({limit:r.limit.id,usd:r.usd,reset_at:r.reset_at,at:new Date().toISOString()}),e.node_id),await v({id:`refused:sandbox:${e.node_id}:${r.limit.id}:${r.month}`,kind:"sandbox",what:"wake",usd:null,payer:n.payer,funding:"bill",sub:n.sub,grantee:n.grantee,node:e.node_id,run:e.run_id??null,provider:"blaxel",refused:g(r)}),E(r)}a(q,"checkBilledWake");class J extends Error{static{a(this,"EnvironmentImagePending")}environmentId;imageError;constructor(t,n){super(`environment ${t} has no built image yet${n===null?"":` (${n})`}; the wake waits for the build.`),this.environmentId=t,this.imageError=n,this.name="EnvironmentImagePending"}}async function V(e){return await S(e)}a(V,"imageForWake");async function j(e){return e.release!==D()&&await w(e.nodeId,{afterTurn:!1,reason:"release"}),await d(e.runner).wake(e)==="no_broker"?(await l(e.executionId,{reason:"lost"}),"lost"):(await y(e.executionId,Date.now()),await p(e.executionId),"woken")}a(j,"wakeResident");async function z(e){const t=await d(e.runner).status(e);if(t.state!=="gone"&&t.state!=="failed")return!1;const n=await l(e.executionId,{reason:"lost"});return n&&u({level:"warn",event:"execution.lost",node_id:e.nodeId}),n}a(z,"endRemoteExecutionIfGone");async function K(e,t){const n=await m(e);if(n===null||n.state!=="launching"||n.runner==="process")return;const r=d(n.runner),o=t-Date.parse(n.startedAt),i=await r.status(n);if(i.state!=="unknown"){if(i.state==="running"){if(o<=L||!await s(n.executionId,{reason:"launch_timeout"}))return;await r.stop(n,{reason:"launch_timeout"}),await c(e,"crash",{reason:"launch_failed",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",message:"the sandbox launch did not report within the launch deadline"}}}),u({level:"warn",event:"execution.launch_timeout",node_id:e});return}if(i.state==="failed"){if(!await s(n.executionId,{reason:"launch_failed"}))return;await c(e,"crash",{reason:"launch_failed",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",message:`the sandbox start script failed: ${i.reason}`}}});return}if(o>A){if(!await s(n.executionId,{reason:"launch_lost"}))return;u({level:"warn",event:"execution.launch_lost",node_id:e})}}}a(K,"recoverLaunching");export{J as EnvironmentImagePending,L as LAUNCH_DEADLINE_MS,A as LAUNCH_LOST_GRACE_MS,D as acceptedRelease,q as checkBilledWake,z as endRemoteExecutionIfGone,V as imageForWake,K as recoverLaunching,G as remoteMachineEnvironmentOf,j as wakeResident};
1
+ var f=Object.defineProperty;var a=(e,t)=>f(e,"name",{value:t,configurable:!0});import{liveExecutionForNode as m,endExecution as d,recordExecutionAwake as p,endLaunchingExecution as s,requestExecutionStop as w}from"../../../core/canvas/executions.js";import{openDb as h}from"../../../core/canvas/db.js";import{isCloudRole as _}from"../../../core/canvas/person-state.js";import{emitEvent as u}from"../../../core/events/emit.js";import{findRefusal as x,refusalError as E,refusedMark as g,writeCharge as v}from"../../../core/ledger/index.js";import{transition as c}from"../../../core/runtime/lifecycle.js";import{runnerForExecution as l}from"../../../core/runtime/runner/index.js";import{machineEnvironmentOfProfile as b}from"../../../core/runtime/runner/machine/environment.js";import{startCandidateOf as k}from"../../../core/runtime/start-check.js";import{settleSandboxBeforeWake as y}from"../ledger-sandbox.js";import{crtrVersion as I}from"../../../shared/crtr-version.js";import{resolveEnvironmentImage as S}from"../recipe-image.js";const A=45*6e4,L=12e4,D=a(()=>I(),"acceptedRelease");async function G(e){return e===null||!_()?null:await b(e)}a(G,"remoteMachineEnvironmentOf");async function q(e){const t=await k(e);if(t===null)return;const n={scope:"call",payer:t.payer,funding:"bill",sub:t.sub,grantee:t.grantee,provider:"blaxel"},r=await x(n),o=await h();if(r===null){await o.prepare("UPDATE nodes SET spend_refusal = NULL WHERE node_id = ? AND spend_refusal IS NOT NULL").run(e.node_id);return}throw await o.prepare("UPDATE nodes SET spend_refusal = ? WHERE node_id = ?").run(JSON.stringify({limit:r.limit.id,usd:r.usd,reset_at:r.reset_at,at:new Date().toISOString()}),e.node_id),await v({id:`refused:sandbox:${e.node_id}:${r.limit.id}:${r.month}`,kind:"sandbox",what:"wake",usd:null,payer:n.payer,funding:"bill",sub:n.sub,grantee:n.grantee,node:e.node_id,run:e.run_id??null,provider:"blaxel",refused:g(r)}),E(r)}a(q,"checkBilledWake");class J extends Error{static{a(this,"EnvironmentImagePending")}environmentId;imageError;constructor(t,n){super(`environment ${t} has no built image yet${n===null?"":` (${n})`}; the wake waits for the build.`),this.environmentId=t,this.imageError=n,this.name="EnvironmentImagePending"}}async function V(e){return await S(e)}a(V,"imageForWake");async function j(e){return e.release!==D()&&await w(e.nodeId,{afterTurn:!1,reason:"release"}),await l(e.runner).wake(e)==="no_broker"?(await d(e.executionId,{reason:"lost"}),"lost"):(await y(e.executionId,Date.now()),await p(e.executionId),"woken")}a(j,"wakeResident");async function z(e){const t=await l(e.runner).status(e,{idle:e.idleAt!==null});if(t.state!=="gone"&&t.state!=="failed")return!1;const n=await d(e.executionId,{reason:"lost"});return n&&u({level:"warn",event:"execution.lost",node_id:e.nodeId}),n}a(z,"endRemoteExecutionIfGone");async function K(e,t){const n=await m(e);if(n===null||n.state!=="launching"||n.runner==="process")return;const r=l(n.runner),o=t-Date.parse(n.startedAt),i=await r.status(n);if(i.state!=="unknown"){if(i.state==="running"){if(o<=A||!await s(n.executionId,{reason:"launch_timeout"}))return;await r.stop(n,{reason:"launch_timeout"}),await c(e,"crash",{reason:"launch_failed",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",message:"the sandbox launch did not report within the launch deadline"}}}),u({level:"warn",event:"execution.launch_timeout",node_id:e});return}if(i.state==="failed"){if(!await s(n.executionId,{reason:"launch_failed"}))return;await c(e,"crash",{reason:"launch_failed",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",message:`the sandbox start script failed: ${i.reason}`}}});return}if(o>L){if(!await s(n.executionId,{reason:"launch_lost"}))return;u({level:"warn",event:"execution.launch_lost",node_id:e})}}}a(K,"recoverLaunching");export{J as EnvironmentImagePending,A as LAUNCH_DEADLINE_MS,L as LAUNCH_LOST_GRACE_MS,D as acceptedRelease,q as checkBilledWake,z as endRemoteExecutionIfGone,V as imageForWake,K as recoverLaunching,G as remoteMachineEnvironmentOf,j as wakeResident};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.588",
3
+ "version": "0.3.590",
4
4
  "description": "crtr — agent runtime with memory, plugins, and marketplaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -145,7 +145,7 @@
145
145
  },
146
146
  "license": "UNLICENSED",
147
147
  "dependencies": {
148
- "@north-light/identity": "0.3.588",
148
+ "@north-light/identity": "0.3.590",
149
149
  "@earendil-works/chord": "1.1.0",
150
150
  "@earendil-works/pi-agent-core": "1.1.0",
151
151
  "@earendil-works/pi-ai": "1.1.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/identity",
3
- "version": "0.3.588",
3
+ "version": "0.3.590",
4
4
  "description": "Northlight access-token verification and scope rules",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",