@north-light/cli 0.3.572 → 0.3.574

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.
@@ -1 +1 @@
1
- var Oe=Object.defineProperty;var d=(e,n)=>Oe(e,"name",{value:n,configurable:!0});import{envProfileId as Ae}from"../../../shared/env.js";import{pausedCanvasProfiles as $e}from"../../../core/profiles/manifest.js";import{existsSync as T,realpathSync as ee,statSync as ne}from"node:fs";import{isAbsolute as x,resolve as P}from"node:path";import{appendSituationalContext as Ce,formatSituationalProse as Ee}from"../../../core/runtime/situational-context.js";import{closeNode as Ne}from"../../../core/runtime/close.js";import{reviveNode as Te}from"../../../core/runtime/revive.js";import{nowIso as K}from"../../../core/fs-utils.js";import{appPaidLaunch as Pe,assertLaunchModelRegistered as V,forkNode as De,resolveForkSource as Le,spawnChildPrepared as je}from"../../../core/runtime/spawn.js";import{forkSourceNode as Me,newNodeId as te}from"../../../core/runtime/nodes.js";import{abandonCreateRequest as ie,childrenOf as Ge,completeCreateRequest as re,findCreateRequest as oe,getNode as R,recordCreateRequestNode as Fe,reserveCreateRequest as ae,reserveCreateRequestNode as Be,listNodes as xe,recordRespawnAttempt as Ke,subscribersOf as Ve,subscriptionsOf as de,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 se,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 Cn,readMergedLaunchConfigAsync as le}from"../../../core/runtime/launch.js";import{modelRequestFromConfig as En}from"../../../core/model-routes.js";import{persistDormantModel as Nn,setModelLive as Tn}from"../../../core/runtime/model-swap.js";import{waitForBrokerViewSocket as ce}from"../../../core/runtime/view-socket.js";import{BrokerUnreachableError as Pn}from"../../../core/runtime/broker-request.js";import{boundFleet as D}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 ue}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 fe,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 pe}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 me}from"../../../core/canvas/crons.js";import{cronWakeOrigin as Yn}from"../../../core/runtime/bearings.js";import{boundDaemonControl as Hn}from"../../control.js";import{notFound as L,usage as w}from"../../../core/errors.js";import{assertScope as Qn,validateScopes as we}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{actsAsPerson as j,canReadNode as $,readableNodeIds as et,resolvedScopes as nt}from"../router.js";import{forwardVerb as tt,queryWithoutMachine as it,relayError as rt,unknownError as ot,withMachine as at}from"../../peer/forward.js";import{fileRoot as dt}from"../../../core/spaces/file-root.js";import{activeGrant as st,payerOfGrant as lt,terminalGrant as ct}from"../../../core/grants/mirror.js";import{appRungForGrant as ut}from"../../../core/llm/app-rungs.js";import{APP_FAMILY as ft}from"../../../core/model-routes.js";import{listProfileEnvNames as pt}from"../../../core/profiles/env-store.js";import{hasConfiguredProviderCredential as mt,NO_PROVIDER_CREDENTIAL_MESSAGE as he}from"../../../core/runtime/provider-credential-gate.js";import{filterAsync as wt,mapAsync as ye}from"../../../core/async-array.js";async function m(e){const n=await R(e);if(n===null)throw L(`unknown node: ${e}`,{received:e});return n}d(m,"requireMeta");async function H(e){return{subscribesTo:await de(e),subscribers:await Ve(e),children:await Ge(e)}}d(H,"edgesFor");async function b(e){const n=await m(e);return await Y(n,await H(e))}d(b,"detailOf");async function ht(e){let n=(await pe(e)).length;try{n+=dn(await z(e),await se(e)).length}catch(t){if(!on(t))throw t}return n}d(ht,"countFiles");function yt(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&&we(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}d(yt,"parseCreateBody");function _t(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()}d(_t,"parseDeadline");function gt(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")>ue)throw new p(413,"payload_too_large",`serialized payload exceeds ${ue} bytes`)}return e}}d(gt,"parseOutcomeDelivery");function bt(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})}d(bt,"resolveOutcomeDelivery");function vt(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=P(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}d(vt,"buildRecipe");function kt(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}}d(kt,"warmRequestFor");import{resolveCreateKind as Ir}from"../../../core/runtime/launch-target.js";function _e(e){const n=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return En(e.model,n,e.modelExact===!0)}d(_e,"requestFromLaunch");function St(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})}d(St,"withinCeiling");async function ge(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(_e(r),{cwd:e.cwd,profileId:e.profile_id??null},t)}d(ge,"assertNodeModelChangeRegistered");async function be(e,n){const t=e.principal;if(t.class!=="broker"&&t.class!=="cron")return;const r=dt({app:t.app,resolved:await nt(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)}d(be,"assertCallerReaches");const Q=new Map;async function Rt(e,n={},t={}){const r=St(yt(e.body),e.ceiling);if(e.principal.class==="broker"){const s=e.principal;if(r.prefer_warm===!0&&s.app!=="app:terminal"&&(r.prefer_warm=!1),r.parent!=null){const o=await m(r.parent);if(o.grantee!==s.app)throw new p(403,"other_app_run","cannot create a child under another app's node");if(!await $(s,o.grantee??"app:terminal",r.parent))throw L(`unknown node: ${r.parent}`,{received:r.parent})}if(r.creator!==void 0&&r.creator!==s.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 Me(await Le(r.fork_from))}catch{}if(o?.grantee!==s.app||!await $(s,o.grantee,o.node_id))throw new p(403,"other_app_run","cannot fork another app's conversation")}r.creator=s.node}if(e.principal.class==="cron"){const s=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 te(),s.isolated&&(r.isolated=!0,r.cwd=await z(r.node_id,s.app));const o=await en({grantee:s.app,sub:s.sub,grant_id:s.grant,scopes:s.scopes,from_exec:s.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(s.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 s.scopes!==null&&(r.scopes=[...s.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 oe(i))?.nodeId!==r.node_id)return M(e,r,n,t);const a=Q.get(i);if(a!==void 0)return a;const c=Ot(e,r,i,n,t);Q.set(i,c);try{return await c}finally{Q.delete(i)}}d(Rt,"handleCreate");const ve="create_request_in_progress";async function It(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 oe(n))?.nodeId!==t)break;await new Promise(a=>setTimeout(a,100))}throw new p(409,ve,"another create with this request_key is in progress; retry it")}d(It,"awaitForeignCreate");async function Ot(e,n,t,r,i){const a=await ae(t);if(a.nodeId!==null&&await R(a.nodeId)!==null){if(a.state!=="warm_claimed"){const c=await R(a.nodeId);if(!j(e.principal)&&!await $(e.principal,c.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(c){if(c instanceof p&&c.code===ve)throw c;const s=await ae(t);throw(s.nodeId===null||await R(s.nodeId)===null)&&await ie(t,s.nodeId),c}}d(Ot,"handleKeyedCreateRequest");async function M(e,n,t,r,i=void 0){const a=r.deadlineAt??_t(n.deadline),c=gt(n.outcome_delivery),s=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 me(e.principal.cron))?.created_by??null},n.node_id):null;s!==null&&(n.root=s.root===!0);const o=s?.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:u,launch:S}=await Vn(n,{validateKind:Ie});await be(e,u),n.worktree!==void 0&&await be(e,P(n.pin_cwd??n.cwd??u));const _={...n,kind:h},v=c===void 0?void 0:bt(c,u),Z=("grant"in e.principal?e.principal.grant:null)??(o==null?null:(await R(o))?.grant_id??null);if(await V(_e(await Pe(S,Z,n.model)),{cwd:u,profileId:f},t.modelRegistry),await lt(Z)!=="app"&&!await mt(f===null?[]:await pt(f)))throw new p(412,"no_provider_credential",he,{error:"no_provider_credential",message:he,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"?kt(_,u,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 ie(i.requestKey,i.nodeId),new p(503,"create_resume_failed",`could not resume warm claim ${i.nodeId}; retry the create`);return await re(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 re(i.requestKey,g),fe(A),{status:201,body:await b(g)};F=A}const N=i?.nodeId??n.node_id??(i===void 0?void 0:await te());if(i!==void 0&&i.nodeId===null){const g=await Be(i.requestKey,N);if(g!==N)return await It(e,i.requestKey,g)}const I=vt(N===void 0?_:{..._,node_id:N},o,u);s!==null&&(s.rootLifecycle!==void 0&&(I.rootLifecycle=s.rootLifecycle),s.scopes!==void 0&&_.scopes===void 0&&(I.scopes=s.scopes),s.run!==void 0&&(I.run=s.run),s.withinCreate!==void 0&&(I.withinCreate=s.withinCreate)),a!==void 0&&(I.deadlineAt=a),v!==void 0&&(I.outcomeDelivery=v),I.readiness=n.root===!0?"await":"launch";const q=await je(I,B,()=>{F!==null&&fe(F)});return i!==void 0&&await Fe(i.requestKey,q.node.node_id),{status:201,body:await b(q.node.node_id)}}}d(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]}d(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`)}}d(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(", ")}`)}}d(G,"oneOf");function At(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"]),c=k(e,"profile_id"),s=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"),u=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}:{},...c!==void 0?{profile_id:c}:{},...s!==void 0?{profile_prefix:s}:{},...o!==void 0?{parent:o}:{},...l!==void 0?{top_level:l}:{},...f!==void 0?{under:f}:{},...h!==void 0?{under_inclusive:h}:{},...u!==void 0?{hanging:u}:{},...S!==void 0?{include:S}:{}}}d(At,"parseListQuery");async function $t(e){const n=At(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 et(e.principal);r!==null&&(t=t.filter(s=>r.has(s.node_id)));const i=n.include==="activity"?await Ze(t.map(s=>s.node_id)):null,a=t.length>0?$e():new Set;return{status:200,body:await ye(t,async s=>{const o=await Zn(s,s.profile_id!==null&&a.has(s.profile_id));if(i!==null){const l=await pe(s.node_id);o.activity={latest_report:l[0]??null,final_report:s.final_report===null?null:l.find(f=>f.name===s.final_report)??null,pending_human_count:i[s.node_id]??0}}return o})}}d($t,"handleList");async function Ct(e){const n=e.params.id,t=await tt(e,n,{method:"GET",path:`/v1/nodes/${encodeURIComponent(n)}`,query:it(e)});if(t.kind==="unknown")throw ot(n,t.unreachable);if(t.kind==="remote"){if(t.status>=400)throw rt(t.status,t.body);return{status:t.status,body:at(t.body,t.machine)}}return await m(n),{status:200,body:await b(n)}}d(Ct,"handleDetail");async function Et(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()}}}d(Et,"handleSnapshot");async function Nt(e){const n=e.params.id,t=await fn(n);if(t===null)throw L(`unknown node: ${n}`,{received:n});return{status:200,body:t}}d(Nt,"handleSubject");function Tt(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}}d(Tt,"parseMessagesQuery");async function Pt(e){const n=e.params.id,t=await sn(n,Tt(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()}}}d(Pt,"handleMessages");async function Dt(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()}}}d(Dt,"handleSession");async function Lt(e){const n=e.params.id;return await m(n),{status:200,body:{node_id:n,markdown:await un(n)}}}d(Lt,"handleTranscript");async function jt(e){const n=e.params.id;await m(n);const t=d(async(i,a)=>({node_id:i,label:(await R(i))?.name??i,dir:await se(i),self:a,files:await ht(i)}),"root"),r=await wt([await t(n,!0),...await ye(await de(n),async i=>await t(i.node_id,!1))],async i=>await Mt(i.node_id,i.dir)||i.files>0);return{status:200,body:{node_id:n,roots:r}}}d(jt,"handleContext");async function Mt(e,n){try{return rn(await z(e),n)}catch(t){if(an(t))return!1;throw t}}d(Mt,"hasDir");async function Gt(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 De(n.node_id,r,e.principal.class==="broker"?e.principal.node:void 0);return{status:201,body:await b(i.node.node_id)}}d(Gt,"handleFork");const Ft=1e4;async function Bt(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 me(t.cron_id):null,c=await Te(n,{resume:r,capacity:"refuse",...a!==null?{wakeReason:await Yn(a,"schedule_revive")}:{}});c.outcome!=="already-live"&&await Ke(n,{failures:0,notBefore:null});const s=(await R(n))?.status??"active",o=(c.launch??D().get(n)?.handle)?.exited,l=c.outcome!=="frozen"&&await ce(n,o,Ft);return{status:200,body:qn(n,c,s,l)}}d(Bt,"handleRevive");async function xt(e){const n=e.params.id;return{status:200,body:{newNodeId:(await yn(n))?.newNodeId??null}}}d(xt,"handleRelaunchRoot");async function Kt(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(c=>{e.res.once("close",()=>c())}),a=await Ne(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)}}d(Kt,"handleClose");async function Vt(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}}d(Vt,"handleMarkRead");async function Wt(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}}}d(Wt,"handleRecycle");async function zt(e){const n=e.params.id;return await m(n),await J(n,{lifecycle:"terminal"}),await C(e,n,["lifecycle"]),{status:200,body:await b(n)}}d(zt,"handleDemote");async function Jt(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 ge(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 C(e,t,["mode",...i.kind!==void 0?["kind"]:[],...i.resident===!0?["lifecycle"]:[],...i.model!==void 0?["model"]:[]]);const c=await Y(a.meta,await H(t));return c.roadmap_written=a.roadmapWritten,c.roadmap_ref=a.roadmapRef,c.goal_path=a.goalPath,{status:200,body:c}}d(Jt,"handlePromote");async function Ut(e){const n=e.params.id;return await m(n),{status:200,body:{request:await bn(n)}}}d(Ut,"handleBrokerStructuredRequest");async function Yt(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)}}}d(Yt,"handleBrokerGoal");async function Ht(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 ge(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 c=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(c.meta,await H(t))}}d(Ht,"handleYield");async function Qt(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 L(`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)}}d(Qt,"handleWait");async function Xt(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]}}}d(Xt,"handleReviveAll");const Zt=new Set(["interrupt","steer","after-turn","next-turn"]);function qt(e){if(e===null)return null;const n=d(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"||!Zt.has(i))&&n(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(i)}`);return JSON.stringify(Object.fromEntries(t))}d(qt,"listenJson");async function C(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),c=await He(i,e),s=c.class==="person"?c.person:c.class==="app"?c.app:c.node;await Ue(i,s,a),await Ye(i,{event:"configured",object:a,actor:s,attrs:{changed:t.join(",")}})})}d(C,"recordConfigured");function ke(e){const n=D().get(e);if(n===void 0)return!1;try{return process.kill(n.pid,"SIGTERM"),!0}catch{return!1}}d(ke,"restartLiveBroker");function Se(e,n){try{return ee(e)===ee(n)}catch{return!1}}d(Se,"sameDirectory");async function ei(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 C(e,t,["profile"])),i.restart===!0&&ke(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(u=>u!=="cwd"&&u!=="keep_session"&&u!=="restart"&&i[u]!==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=T(l.cwd);if(i.keep_session===!0||f&&x(o)&&T(o)&&Se(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 u=P(o);let S=!1;try{S=ne(u).isDirectory()}catch{}if(!S)throw new y({error:"cwd_missing",message:`cwd is not an existing directory: ${u}`,received:o,field:"cwd",next:"Send an existing absolute directory."});if(f&&!Se(l.cwd,u))throw new y({error:"cwd_not_same_directory",message:`${u} 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 _!==u&&(await W(async v=>{await E(t,{cwd:u}),await v.prepare("UPDATE crons SET cwd = ? WHERE anchor_node = ? AND cwd = ?").run(u,t,_),await Qe(t,_,u)}),await C(e,t,["cwd"])),i.restart===!0&&ke(t),{status:200,body:await b(t)}}if(await D().has(t)){const u=`${t} cannot repair its cwd while its broker is live`;throw new p(409,"cwd_node_live",u,{error:"cwd_node_live",message:u,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(T(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=P(o);if(!T(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(u){throw u instanceof y?u: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 C(e,t,["cwd"]),{status:200,body:await b(t)}}let a=await m(t);const c=i.listen===void 0?void 0:qt(i.listen);if(i.scopes!==void 0){const o=we(i.scopes),l=a.grantee==="app:terminal"?await ct():a.grant_id?await st(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 Ce(t,Ee(i.situational_context)),i.model!==void 0){const o=(await le(a.cwd,a.profile_id??null)).modelLadders,l=$n(i.model,o),f=await ut(a.grant_id,i.model,l===void 0),h=f?{family:ft,strength:f.strength}:l,u=f?f.model:Cn(i.model,o);await V({kind:"concrete",spec:u},{cwd:a.cwd,profileId:a.profile_id??null},n.modelRegistry);const S=D();let _=!1;if(await S.isClaimed(t)&&await ce(t,S.get(t)?.handle.exited)&&(_=await Tn(t,u,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(!u.includes("/"))throw w(`model must resolve to a provider/id spec: ${i.model}`);await Nn(t,u,h)}a=await m(t)}if(i.kind!==void 0||i.mode!==void 0||i.lifecycle!==void 0){i.kind!==void 0&&await Ie(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=d(async()=>{const u=await kn(t);await Rn(t,u!==null&&u.trim()!==""?{goal:u.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 s=["scopes","situational_context","model","kind","mode","lifecycle","name","listen"].filter(o=>i[o]!==void 0);return await C(e,t,s,c===void 0?void 0:async o=>{await o.prepare("UPDATE objects SET listen_json = ? WHERE id = ? AND type = 'node'").run(c,t)}),{status:200,body:await b(t)}}d(ei,"handleConfig");async function Re(){return(await le(process.cwd(),Ae()||null)).kinds}d(Re,"daemonKinds");async function Ie(e){const n=Object.keys(await Re());if(!n.includes(e))throw w(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${n.sort().join(", ")}.`})}d(Ie,"assertKindServer");async function ni(){const e=await Re();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}))}}}d(ni,"handleListKinds");const kr=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:Rt},{method:"GET",pattern:"/v1/nodes",handler:$t},{method:"GET",pattern:"/v1/kinds",handler:d(()=>ni(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:Xt},{method:"GET",pattern:"/v1/nodes/:id",handler:Ct},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:Et},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:Nt},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:Pt},{method:"GET",pattern:"/v1/nodes/:id/session",handler:Dt},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:Lt},{method:"GET",pattern:"/v1/nodes/:id/context",handler:jt},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:Gt},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:Bt},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:xt},{method:"POST",pattern:"/v1/nodes/:id/close",handler:Kt},{method:"POST",pattern:"/v1/nodes/:id/read",handler:Vt},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:Wt},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:zt},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:Jt},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Ht},{method:"GET",pattern:"/v1/nodes/:id/broker/structured-request",handler:Ut},{method:"POST",pattern:"/v1/nodes/:id/broker/goal",handler:Yt},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Qt},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:ei}];export{ei as handleConfig,Rt as handleCreate,Gt as handleFork,$t as handleList,Jt as handlePromote,Ht as handleYield,kr as nodeRoutes,Ir 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 P,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 C}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 E,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{actsAsPerson as j,canReadNode as $,mayOnNode as et,readableNodeIds as nt,resolvedScopes as tt}from"../router.js";import{forwardVerb as it,queryWithoutMachine as rt,relayError as ot,unknownError as at,withMachine as dt}from"../../peer/forward.js";import{fileRoot as st}from"../../../core/spaces/file-root.js";import{activeGrant as lt,payerOfGrant as ct}from"../../../core/grants/mirror.js";import{nodeTerminalGrant as ut}from"../../../core/grants/terminal.js";import{appRungForGrant as ft}from"../../../core/llm/app-rungs.js";import{APP_FAMILY as pt}from"../../../core/model-routes.js";import{listProfileEnvNames as mt}from"../../../core/profiles/env-store.js";import{hasConfiguredProviderCredential as wt,NO_PROVIDER_CREDENTIAL_MESSAGE as _e}from"../../../core/runtime/provider-credential-gate.js";import{filterAsync as ht,mapAsync as ge}from"../../../core/async-array.js";async function m(e){const n=await R(e);if(n===null)throw E(`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 yt(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(yt,"countFiles");function _t(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(_t,"parseCreateBody");function gt(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(gt,"parseDeadline");function bt(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(bt,"parseOutcomeDelivery");function vt(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(vt,"resolveOutcomeDelivery");function kt(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(kt,"buildRecipe");function St(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(St,"warmRequestFor");import{resolveCreateKind as Ar}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 Rt(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(Rt,"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=st({app:t.app,resolved:await tt(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 It(e,n={},t={}){const r=Rt(_t(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 E(`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 et(e.principal,"edit",o))throw E(`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 c=At(e,r,i,n,t);Q.set(i,c);try{return await c}finally{Q.delete(i)}}s(It,"handleCreate");const Se="create_request_in_progress";async function Ot(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(Ot,"awaitForeignCreate");async function At(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 c=await R(a.nodeId);if(!j(e.principal)&&!await $(e.principal,c.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(c){if(c instanceof p&&c.code===Se)throw c;const d=await se(t);throw(d.nodeId===null||await R(d.nodeId)===null)&&await oe(t,d.nodeId),c}}s(At,"handleKeyedCreateRequest");async function M(e,n,t,r,i=void 0){const a=r.deadlineAt??gt(n.deadline),c=bt(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:u,launch:S}=await Vn(n,{validateKind:Ae});await ke(e,u),n.worktree!==void 0&&await ke(e,D(n.pin_cwd??n.cwd??u));const _={...n,kind:h},v=c===void 0?void 0:vt(c,u),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:u,profileId:f},t.modelRegistry),await ct(Z)!=="app"&&!await wt(f===null?[]:await mt(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"?St(_,u,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 T=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,T);if(g!==T)return await Ot(e,i.requestKey,g)}const I=kt(T===void 0?_:{..._,node_id:T},o,u);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 $t(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"]),c=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"),u=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}:{},...c!==void 0?{profile_id:c}:{},...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}:{},...u!==void 0?{hanging:u}:{},...S!==void 0?{include:S}:{}}}s($t,"parseListQuery");async function Nt(e){const n=$t(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 nt(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(Nt,"handleList");async function Ct(e){const n=e.params.id,t=await it(e,n,{method:"GET",path:`/v1/nodes/${encodeURIComponent(n)}`,query:rt(e)});if(t.kind==="unknown")throw at(n,t.unreachable);if(t.kind==="remote"){if(t.status>=400)throw ot(t.status,t.body);return{status:t.status,body:dt(t.body,t.machine)}}return await m(n),{status:200,body:await b(n)}}s(Ct,"handleDetail");async function Et(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(Et,"handleSnapshot");async function Tt(e){const n=e.params.id,t=await fn(n);if(t===null)throw E(`unknown node: ${n}`,{received:n});return{status:200,body:t}}s(Tt,"handleSubject");function Pt(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(Pt,"parseMessagesQuery");async function Dt(e){const n=e.params.id,t=await sn(n,Pt(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(Dt,"handleMessages");async function Lt(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(Lt,"handleSession");async function jt(e){const n=e.params.id;return await m(n),{status:200,body:{node_id:n,markdown:await un(n)}}}s(jt,"handleTranscript");async function Mt(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 yt(i)}),"root"),r=await ht([await t(n,!0),...await ge(await le(n),async i=>await t(i.node_id,!1))],async i=>await Gt(i.node_id,i.dir)||i.files>0);return{status:200,body:{node_id:n,roots:r}}}s(Mt,"handleContext");async function Gt(e,n){try{return rn(await z(e),n)}catch(t){if(an(t))return!1;throw t}}s(Gt,"hasDir");async function Ft(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(Ft,"handleFork");const Bt=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,c=await De(n,{resume:r,capacity:"refuse",...a!==null?{wakeReason:await Yn(a,"schedule_revive")}:{}});c.outcome!=="already-live"&&await xe(n,{failures:0,notBefore:null});const d=(await R(n))?.status??"active",o=(c.launch??L().get(n)?.handle)?.exited,l=c.outcome!=="frozen"&&await fe(n,o,Bt);return{status:200,body:qn(n,c,d,l)}}s(Kt,"handleRevive");async function xt(e){const n=e.params.id;return{status:200,body:{newNodeId:(await yn(n))?.newNodeId??null}}}s(xt,"handleRelaunchRoot");async function Vt(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(c=>{e.res.once("close",()=>c())}),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(Vt,"handleClose");async function Wt(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(Wt,"handleMarkRead");async function zt(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(zt,"handleRecycle");async function Jt(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(Jt,"handleDemote");async function Ut(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 c=await Y(a.meta,await H(t));return c.roadmap_written=a.roadmapWritten,c.roadmap_ref=a.roadmapRef,c.goal_path=a.goalPath,{status:200,body:c}}s(Ut,"handlePromote");async function Yt(e){const n=e.params.id;return await m(n),{status:200,body:{request:await bn(n)}}}s(Yt,"handleBrokerStructuredRequest");async function Ht(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(Ht,"handleBrokerGoal");async function Qt(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 c=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(c.meta,await H(t))}}s(Qt,"handleYield");async function Xt(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 E(`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(Xt,"handleWait");async function Zt(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(Zt,"handleReviveAll");const qt=new Set(["interrupt","steer","after-turn","next-turn"]);function ei(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"||!qt.has(i))&&n(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(i)}`);return JSON.stringify(Object.fromEntries(t))}s(ei,"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),c=await He(i,e),d=c.class==="person"?c.person:c.class==="app"?c.app:c.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 ni(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 C(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(u=>u!=="cwd"&&u!=="keep_session"&&u!=="restart"&&i[u]!==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=P(l.cwd);if(i.keep_session===!0||f&&K(o)&&P(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 u=D(o);let S=!1;try{S=ne(u).isDirectory()}catch{}if(!S)throw new y({error:"cwd_missing",message:`cwd is not an existing directory: ${u}`,received:o,field:"cwd",next:"Send an existing absolute directory."});if(f&&!Ie(l.cwd,u))throw new y({error:"cwd_not_same_directory",message:`${u} 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 _!==u&&(await W(async v=>{await C(t,{cwd:u}),await v.prepare("UPDATE crons SET cwd = ? WHERE anchor_node = ? AND cwd = ?").run(u,t,_),await Qe(t,_,u)}),await N(e,t,["cwd"])),i.restart===!0&&Re(t),{status:200,body:await b(t)}}if(await L().has(t)){const u=`${t} cannot repair its cwd while its broker is live`;throw new p(409,"cwd_node_live",u,{error:"cwd_node_live",message:u,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(P(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(!P(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(u){throw u instanceof y?u: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 C(t,{cwd:h}),await Xe(t)}),await N(e,t,["cwd"]),{status:200,body:await b(t)}}let a=await m(t);const c=i.listen===void 0?void 0:ei(i.listen);if(i.scopes!==void 0){const o=ye(i.scopes),l=a.grantee==="app:terminal"?await ut(a):a.grant_id?await lt(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 C(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 ft(a.grant_id,i.model,l===void 0),h=f?{family:pt,strength:f.strength}:l,u=f?f.model:Nn(i.model,o);await V({kind:"concrete",spec:u},{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,u,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(!u.includes("/"))throw w(`model must resolve to a provider/id spec: ${i.model}`);await En(t,u,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 u=await kn(t);await Rn(t,u!==null&&u.trim()!==""?{goal:u.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 C(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,c===void 0?void 0:async o=>{await o.prepare("UPDATE objects SET listen_json = ? WHERE id = ? AND type = 'node'").run(c,t)}),{status:200,body:await b(t)}}s(ni,"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 ti(){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(ti,"handleListKinds");const Rr=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:It},{method:"GET",pattern:"/v1/nodes",handler:Nt},{method:"GET",pattern:"/v1/kinds",handler:s(()=>ti(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:Zt},{method:"GET",pattern:"/v1/nodes/:id",handler:Ct},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:Et},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:Tt},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:Dt},{method:"GET",pattern:"/v1/nodes/:id/session",handler:Lt},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:jt},{method:"GET",pattern:"/v1/nodes/:id/context",handler:Mt},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:Ft},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:Kt},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:xt},{method:"POST",pattern:"/v1/nodes/:id/close",handler:Vt},{method:"POST",pattern:"/v1/nodes/:id/read",handler:Wt},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:zt},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:Jt},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:Ut},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Qt},{method:"GET",pattern:"/v1/nodes/:id/broker/structured-request",handler:Yt},{method:"POST",pattern:"/v1/nodes/:id/broker/goal",handler:Ht},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Xt},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:ni}];export{ni as handleConfig,It as handleCreate,Ft as handleFork,Nt as handleList,Ut as handlePromote,Qt as handleYield,Rr as nodeRoutes,Ar as resolveCreateKind};
@@ -1,4 +1,10 @@
1
- import type { RouteTable } from '../router.js';
1
+ import type { RequestContext, RouteTable } from '../router.js';
2
+ /** What a local resolution of `raw` finds: the id of a stub of another machine's object (a stub is never served as the object, however
3
+ * it is named), and whether a live or deleted object is here (an exact answer, with no peer call). */
4
+ export declare function resolvedLocally(raw: string, ctx: RequestContext): Promise<{
5
+ stub: string | null;
6
+ hit: boolean;
7
+ }>;
2
8
  /** How long a merged list waits for any one other machine before it counts as unreachable. */
3
9
  export declare const listBudget: {
4
10
  ms: number;
@@ -1,3 +1,3 @@
1
1
  var Fe=Object.defineProperty;var l=(e,t)=>Fe(e,"name",{value:t,configurable:!0});import{ApiError as y}from"../../../api/errors.js";import{PRIVACY_LEVELS_DTO as Ae}from"../../../api/dto/objects.js";import{openDb as N,withCanvasWrite as v}from"../../../core/canvas/db.js";import{actorOf as ae}from"../../../core/graph/documents.js";import{readerForObject as C,readerFor as We}from"../../../core/graph/reader.js";import{resolveName as Le,stubsNamed as Pe,unwrapRef as ie}from"../../../core/graph/names.js";import{canRead as D,holdsObjectsScope as Ce,spaceOf as De}from"../../../core/graph/access.js";import{customReachable as Me,mayActAs as re}from"../../../core/graph/custom.js";import{customObjectRef as oe,authorizeCustom as se,fenceArgv as J}from"./custom-objects.js";import{edgesOf as Ge}from"../../../core/graph/edges.js";import{publish as B}from"../../../core/graph/events.js";import{objectDTO as Ue}from"../../../core/graph/kinds/dto.js";import{isKind as He,kindNames as ze,kindOf as K}from"../../../core/graph/kinds/registry.js";import{listObjects as Ve,searchObjects as ue}from"../../../core/graph/objects.js";import{checkoutsForCwd as Je}from"../../../core/graph/repo-sync/repos.js";import{recordWatch as M,unwatch as Be,watchersOf as Ke,watchesOf as Ze}from"../../../core/graph/watches.js";import{armObjectWaitForWatch as G,settleObjectWaitForUnwatch as Qe}from"../../../core/graph/object-waits.js";import{readerFor as T,resolveRef as Z,warmReaderRepos as R}from"../reader.js";import{readDelegationFor as ce,runReadLeaf as Ye}from"../../plugin-objects/read-leaf.js";import{invalidRequest as U,isRecord as q}from"./validate.js";import{callerNode as le,callerStub as Q,forwardNamed as Xe,forwardVerb as fe,originates as de,queryWithoutMachine as H,relayError as z,remoteStub as xe,unknownError as we,forwarding as P,withMachine as Y}from"../../peer/forward.js";import{getById as I}from"../../../core/graph/objects.js";import{ensureNodeStub as et,isStub as X,stubOf as tt,withKindDecl as $}from"../../../core/peer/stubs.js";import{isUnreachable as nt}from"../../../core/peer/client.js";import{normalizeMachineId as F}from"../../../core/peer/directory.js";import{mapAsync as at}from"../../../core/async-array.js";const A=l(async e=>async t=>await Je(e,t),"reposFnFor");async function g(e,t){return{...await Ue(e,t),...t.type==="document"?{schema_type:t.schema_type??null}:{}}}l(g,"objectDTO");async function it(e,t){const n=t.filter(r=>r.type==="document").map(r=>r.id),a=new Map;if(n.length===0)return a;const i=await e.prepareUncached(`SELECT object, extensions_json FROM documents WHERE object IN (${n.map(()=>"?").join(", ")})`).all(...n);for(const r of i)r.extensions_json!==null&&a.set(r.object,JSON.parse(r.extensions_json));return a}l(it,"extensionsOf");async function me(e,t){const n=await it(e,t);return await at(t,async a=>({...await g(e,a),...await(await K(e,a.type)).listItem?.(e,a),...a.type==="document"?{extensions:n.get(a.id)??{}}:{}}))}l(me,"listItems");function rt(e){return`no object named ${e} on this runtime; it may be on another runtime, or the name may be misspelled`}l(rt,"remoteMessage");async function pe(e,t,n){try{return await S(e,t,n)}catch(a){if(a instanceof y&&a.code==="not_found"&&!a.details?.deleted)return null;throw a}}l(pe,"ownerFilter");async function S(e,t,n){const a=await Z(e,t,n);if("remote"in a)throw new y(404,"not_found",rt(a.remote),{next:"Check the name with `crtr canvas search`."});if("deleted"in a)throw new y(404,"not_found",`${a.deleted.name} is deleted`,{id:a.deleted.id,deleted:!0});return a}l(S,"liveRef");const O=l(e=>decodeURIComponent(e.params.ref),"refParam"),he=l(e=>{const t=ie(e),n=t.indexOf("/");return n>0?t.slice(0,n):t},"idOf");async function ye(e){const t=await I(await N(),he(e));return t!==null&&await X(await N(),t)?t.id:null}l(ye,"stubIdOf");async function ot(e,t){const n=await ye(e);return n!==null?{stub:n,hit:!0}:(await R(t.principal),await v(async a=>{try{const i=await T(a,t),r=l(async()=>{const s=await Pe(a,i,e);if(s.length>1)throw new y(409,"ambiguous_name",`'${e}' names more than one remote object`,{candidates:s.map(c=>c.id),next:"Read one by its object id."});return{stub:s[0]?.id??null,hit:!1}},"named");let o;try{o=await Z(a,i,e)}catch(s){if(s instanceof y&&s.code==="not_found")return await r();throw s}if("remote"in o)return await r();if("deleted"in o){const s=await r();return s.stub===null?{stub:null,hit:!0}:s}return{stub:await X(a,o)?o.id:null,hit:!0}}catch(i){if(i instanceof y&&i.code==="ambiguous_name")throw i;return{stub:null,hit:!1}}}))}l(ot,"resolvedLocally");async function x(e,t,n){const a=await ot(t,e);if(a.stub!==null)return fe(e,a.stub,n);if(a.hit||!de(e.principal))return{kind:"local"};const i=await fe(e,he(t),n);return i.kind==="local"&&ie(t).includes("/")?Xe(e,n,{method:"GET",path:V(t),query:H(e)}):i}l(x,"forwardRef");const V=l(e=>`/v1/objects/${encodeURIComponent(e)}`,"objectPath");async function be(e,t,n,a,i){const r=t?.object;!r?.id||!r.type||await v(async o=>{const s=await le(o,e);if(s===null)return;const c=await xe(o,r.id,r.type,n,{kind:r.kind??null,name:r.name??r.id,...r.preview===void 0?{}:{preview:r.preview},owner:r.owner??null,...r.kind_decl===void 0?{}:{kind_decl:r.kind_decl},...r.privacy===void 0?{}:{privacy:r.privacy}});await M(o,s,c,a,i===void 0?{}:{patterns:i}),a==="ask"&&await G(o,s,c)})}l(be,"watchRemote");async function st(e){const t=O(e),n=["1","true"].includes(e.query.get("fields")??""),a=await x(e,t,{method:"GET",path:V(t),query:H(e)});if(a.kind==="unknown")return{state:"unknown",ref:t,unreachable:a.unreachable};if(a.kind==="remote"){if(a.status>=400)throw z(a.status,a.body);return await be(e,a.body,a.machine.id,"read"),Y(a.body,a.machine)}const i=l(async s=>{const c=await Q(s,e);return c===null?await T(s,e):await C(s,c,await A(s))},"readerOf");await R(e.principal);const r=await v(async s=>{const c=await i(s),u=await Z(s,c,t);if("remote"in u)return{state:"remote",remote:u.remote};if("deleted"in u)return{state:"deleted",deleted:await g(s,u.deleted)};const f=await ce(s,u);if(f!==null)return{delegate:f,hitId:u.id};const{data:w,text:b}=await(await K(s,u.type)).read(s,c,u,{fields:n,reposFn:await A(s)});return{state:"object",type:u.type,object:await $(s,u,await g(s,u)),text:b,data:w}});if(!("delegate"in r))return r;const o=await Ye(r.delegate,e.principal);return await R(e.principal),await v(async s=>{const c=await i(s),u=await I(s,r.hitId);if(u===null)throw new y(404,"not_found","object not found");if(u.deleted_at!==null)return{state:"deleted",deleted:await g(s,u)};if(!await D(s,c,u))throw new y(404,"not_found","object not found");const{data:f,text:w}=await(await K(s,u.type)).read(s,c,u,{fields:n,reposFn:await A(s)});return await ce(s,u)===null?{state:"object",type:u.type,object:await $(s,u,await g(s,u)),text:w,data:f}:{state:"object",type:u.type,object:await $(s,u,await g(s,u)),text:"markdown"in o?o.markdown:`${w}
2
2
  content unavailable: ${o.unavailable}`,data:{...f,content:"markdown"in o?"live":"unavailable"}}})}l(st,"read");function ee(e,t,n,a){if(e!=null){if(!n.includes(e)){a.push({field:t,problem:`must be one of ${n.join(", ")}`,received:e});return}return e}}l(ee,"oneOf");async function ge(e,t,n){if(t!=null){if(typeof t!="string"||!await He(e,t)){n.push({field:"type",problem:`must be a kind: one of ${(await ze(e)).join(", ")}`,received:t});return}return t}}l(ge,"kindName");function je(e,t,n,a){if(e==null)return a;const i=Number(e);return!Number.isInteger(i)||i<1||i>100?(n.push({field:t,problem:"must be an integer from 1 to 100",received:e}),a):i}l(je,"limitOf");function _e(e,t){if(e==null)return;let n=e;if(typeof e=="string")try{n=JSON.parse(e)}catch{n=null}if(!q(n)||Object.values(n).some(a=>!q(a))){t.push({field:"extensions",problem:'must be an object of objects, e.g. {"firstlight":{"state":"active"}}',received:e});return}return n}l(_e,"extensionsParam");function ke(e,t){if(e!=null){if(typeof e!="string"||e===""){t.push({field:"schema_type",problem:"must be a non-empty string",received:e});return}return e}}l(ke,"schemaTypeParam");async function ve(e){const t=e.query,n=[],a=await ge(await N(),t.get("type"),n),i=ee(t.get("privacy"),"privacy",Ae,n),r=je(t.get("limit"),"limit",n,50),o=t.get("cursor");o!==null&&!/^\d+$/.test(o)&&n.push({field:"cursor",problem:"is not a cursor from a previous page",received:o});const s=t.get("deleted");s!==null&&!["0","1","true","false"].includes(s)&&n.push({field:"deleted",problem:"must be true or false",received:s});const c=t.get("shared");c!==null&&!["0","1","true","false"].includes(c)&&n.push({field:"shared",problem:"must be true or false",received:c});const u=_e(t.get("extensions"),n),f=ke(t.get("schema_type"),n);return n.length>0&&U("object list request",n),await R(e.principal),await v(async w=>{const b=await T(w,e),j={...a?{type:a}:{},...i?{privacy:i}:{},...t.get("kind")!==null?{kind:t.get("kind")}:{},...s==="1"||s==="true"?{deleted:!0}:{},...c==="1"||c==="true"?{shared:!0}:{},...u?{extensions:u}:{},...f?{schemaType:f}:{},...t.get("name")!==null?{namePrefix:t.get("name")}:{}},k=t.get("owner");if(k!==null){const m=await pe(w,b,k);if(m===null)return{items:[],next_cursor:null};j.owner=m}const p=await Ve(w,b,j,{limit:r,after_seq:o===null?0:Number(o)}),d=p.at(-1);return{items:await me(w,p),next_cursor:p.length===r&&d?String(d.seq):null}})}l(ve,"listLocal");const ut={ms:3e4},ct="self",te=l((e,t)=>e.map(n=>({...n,machine:t})),"labelItems");async function Oe(e,t,n,a){const i=P.current;try{const r=await i.call(t.id,{method:"GET",path:"/v1/objects",query:n},await i.envelope(e.principal),a);if(nt(r))return{state:"unreachable",items:[],next:null};if(r.status===426)return{state:"too_old",items:[],next:null};const o=r.body;return r.status!==200||!Array.isArray(o?.items)?{state:"unreachable",items:[],next:null}:{state:"ok",items:te(o.items,t),next:o.next_cursor??null}}catch{return{state:"unreachable",items:[],next:null}}}l(Oe,"remotePage");async function lt(e){const t=new Promise(n=>e.addEventListener("abort",()=>n(null),{once:!0}));return Promise.race([P.current.machines().catch(()=>null),t])}l(lt,"machinesWithin");async function ft(e){const t=e.query.get("machine");if(!de(e.principal)||!P.current.joined()||t===ct)return await ve(Ee(e));const a=P.current.self(),i=t!==null&&F(t)!==a,r=i?null:await ve(Ee(e)),o=new AbortController,s=setTimeout(()=>o.abort(),ut.ms);s.unref?.();try{const c=await lt(o.signal);if(c===null){if(i)throw new y(503,"runtime_unreachable",`The directory did not answer, so ${F(t)} cannot be listed.`,{machine:F(t)});return r}const u=l(d=>({id:d,name:c.find(m=>m.machine_id===d)?.name??d}),"labelOf"),f=u(a),w=c.filter(d=>d.machine_id!==a&&d.kind!=="device"),b=H(e);if(t!==null){if(!i)return{items:te(r.items,f),next_cursor:r.next_cursor,machines:[{machine_id:a,name:f.name,state:"ok",more:r.next_cursor!==null}]};const d=F(t);if(!w.some(L=>L.machine_id===d))throw new y(404,"not_found",`no machine ${d} on your account`,{machine:d});const m=await Oe(e,u(d),b,o.signal);return{items:m.items,next_cursor:m.next,machines:[{machine_id:d,name:u(d).name,state:m.state,more:m.next!==null}]}}const{cursor:j,...k}=b,p=await Promise.all(w.map(d=>Oe(e,u(d.machine_id),k,o.signal)));return{items:[...te(r.items,f),...p.flatMap(d=>d.items)],next_cursor:r.next_cursor,machines:[{machine_id:a,name:f.name,state:"ok",more:r.next_cursor!==null},...w.map((d,m)=>({machine_id:d.machine_id,name:d.name,state:p[m].state,more:p[m].next!==null}))]}}finally{clearTimeout(s)}}l(ft,"list");function Ee(e){const t=new URLSearchParams(e.query);return t.delete("machine"),{...e,query:t}}l(Ee,"withoutMachine");async function dt(e){const t=[],n=q(e.body)?e.body:{};q(e.body)||t.push({field:"body",problem:"must be an object",received:e.body});const a=n.text;(typeof a!="string"||a.trim()==="")&&t.push({field:"text",problem:"is required",received:a});const i=n.grep;if(i!==void 0)if(typeof i!="string")t.push({field:"grep",problem:"must be a regular expression string",received:i});else try{new RegExp(i)}catch(h){t.push({field:"grep",problem:`is not a valid regular expression: ${h.message}`,received:i})}n.body!==void 0&&typeof n.body!="boolean"&&t.push({field:"body",problem:"must be a boolean",received:n.body});const r=await ge(await N(),n.type,t);n.kind!==void 0&&typeof n.kind!="string"&&t.push({field:"kind",problem:"must be a string",received:n.kind}),n.owner!==void 0&&typeof n.owner!="string"&&t.push({field:"owner",problem:"must be a string",received:n.owner});const o=je(n.limit,"limit",t,50),s=_e(n.extensions,t),c=ke(n.schema_type,t);t.length>0&&U("object search request",t),await R(e.principal);const u=await v(async h=>{const _=await T(h,e),$e=typeof n.owner=="string"?await pe(h,_,n.owner):null;return{reader:_,owner:$e}}),{reader:f,owner:w}=u;if(typeof n.owner=="string"&&w===null)return{items:[]};const b={...s?{extensions:s}:{},...c?{schemaType:c}:{},...r?{type:r}:{},...typeof n.kind=="string"?{kind:n.kind}:{},...w?{owner:w}:{}},j=await N(),k=await ue(j,f,{text:a,body:n.body===!0||typeof i=="string",...b}),p=new Set(k.map(h=>h.object.id)),m=(typeof i=="string"?(await ue(j,f,{text:i,grep:!0,...b})).filter(h=>p.has(h.object.id)):k).slice(0,o),L=await me(j,m.map(h=>h.object));return{items:m.map((h,_)=>({object:L[_],...h.line!==void 0?{matches:[{line:h.line,text:h.text??""}]}:{}}))}}l(dt,"search");const Te=["interrupt","steer","after-turn","next-turn"],wt=/^(\*|>|[A-Za-z0-9_-]+)(\.(\*|>|[A-Za-z0-9_-]+))*$/;function mt(e,t){if(e!==void 0){if(!Array.isArray(e)||e.length===0||e.some(n=>typeof n!="string"||!wt.test(n)||n.includes(">")&&!n.endsWith(">"))){t.push({field:"patterns",problem:"must be a non-empty list of event patterns (dot-separated words, `*` for one word, a final `>` for the rest)",received:e});return}return e}}l(mt,"patternsOf");function pt(e,t){if(e===void 0)return;if(!q(e)||Object.keys(e).length===0){t.push({field:"config",problem:"must map levels 1-10 to a delivery",received:e});return}const n=[];for(const[a,i]of Object.entries(e)){const r=Number(a);!Number.isInteger(r)||r<1||r>10?t.push({field:`config.${a}`,problem:"level must be an integer from 1 to 10"}):Te.includes(i)?n.push({threshold:r,delivery:i}):t.push({field:`config.${a}`,problem:`delivery must be one of ${Te.join(", ")}`,received:i})}return n.sort((a,i)=>i.threshold-a.threshold)}l(pt,"configOf");async function Re(e){const t=await ye(e);if(t!==null)throw new y(400,"invalid_request",`${t} lives on another machine; an explicit watcher cannot watch it from here`,{id:t})}l(Re,"refuseStubWatch");async function ne(e,t){const n=await I(e,t)??await(async()=>{const a=await Le(e,await We(e,{class:"person"},async()=>[]),t);return"object"in a?a.object:null})();return n===null||n.deleted_at!==null||!(n.type.includes(".")||n.type==="node")?null:n}l(ne,"findWatcher");const E=l(()=>{throw new y(404,"not_found","watcher not found")},"watcherNotFound");async function qe(e,t,n){if(typeof t!="string"||n===void 0||n===null)return null;if(typeof n!="string")throw new y(400,"invalid_request","invalid watcher_machine");if(await ne(e,t)!==null)return null;const a=P.current;let i;try{i=await a.machines()}catch{throw new y(503,"runtime_unreachable","The directory did not answer, so the watcher machine cannot be checked.")}const r=F(n);return(r===a.self()||!i.some(o=>F(o.machine_id)===r))&&E(),r}l(qe,"remoteWatcherMachine");async function Ne(e,t,n,a){if(t.publishToken||t.principal.class==="anonymous")return E();const i=await T(e,t);if(i.class==="person")return E();let r;try{r=await S(e,i,a)}catch{return E()}const o=r.owner===null?null:await I(e,r.owner);return o===null||!await re(e,i,o)||!await Ce(e,i,"link",n)||(await De(e,n)).id===i.app.id&&!(await D(e,i,n)&&await D(e,await C(e,n),r))?E():(await J(e,t,n),{actor:i.app,object:r})}l(Ne,"linkWatcher");async function Ie(e,t,n){if(t.publishToken)return!0;if(t.principal.class==="anonymous"||!n.type.includes("."))return!1;const a=await T(e,t),i=n.owner===null?null:await I(e,n.owner);return i!==null&&await re(e,a,i)&&await Me(e,a,n)}l(Ie,"ownsWatcher");async function ht(e){const t=O(e),n=q(e.body)?e.body:{};if(typeof n.watcher=="string"&&await Re(t),typeof n.watcher!="string"){const i=await x(e,t,{method:"POST",path:`${V(t)}/watch`,body:e.body});if(i.kind==="unknown")throw we(t,i.unreachable);if(i.kind==="remote"){if(i.status>=400)throw z(i.status,i.body);const r=i.body.patterns;return await be(e,i.body,i.machine.id,"ask",r),Y(i.body,i.machine)}}const a=await qe(await N(),n.watcher,n.watcher_machine);return await yt(e,a)}l(ht,"watch");async function yt(e,t=null){const n=[],a=e.body===void 0?{}:q(e.body)?e.body:(n.push({field:"body",problem:"must be an object"}),{}),i=mt(a.patterns,n),r=pt(a.config,n);return a.filter!==void 0&&!q(a.filter)&&n.push({field:"filter",problem:"must be an object",received:a.filter}),a.watcher!==void 0&&typeof a.watcher!="string"&&n.push({field:"watcher",problem:"must be a custom-object ref",received:a.watcher}),a.watcher_machine!==void 0&&typeof a.watcher_machine!="string"&&n.push({field:"watcher_machine",problem:"must be a machine id",received:a.watcher_machine}),n.length>0&&U("watch request",n),await R(e.principal),await v(async o=>{const s=typeof a.watcher=="string";if((e.publishToken||e.principal.class==="anonymous")&&!s)throw new y(404,"not_found","watcher not found");const c=i??[">"],u={patterns:c,...r?{config:r}:{},...a.filter!==void 0?{filter:a.filter}:{}};if(s){const j=a.watcher,k=t===null?null:await bt(o,e,j,t),p=k??(e.publishToken?await oe(o,j):await ne(o,j));if(p===null)return E();if(k===null&&await Ie(o,e,p)){const L=await se(o,e,p);await J(o,e,p);const h=await C(o,p),_=await S(o,h,O(e));if(!await D(o,h,_))throw new y(404,"not_found","object not found");return await M(o,p,_,"act",u),await G(o,p,_),await B(o,{event:"watched",object:_,actor:L,attrs:{}},await A(o)),{object:await $(o,_,await g(o,_)),patterns:c}}const{actor:d,object:m}=await Ne(o,e,p,O(e));return await M(o,p,m,"act",{...u,linkApp:d}),await G(o,p,m),await B(o,{event:"watched",object:m,actor:d,attrs:{}},await A(o)),{object:await $(o,m,await g(o,m)),patterns:c}}const f=await T(o,e),w=await Q(o,e)??ae(f),b=await S(o,f,O(e));return await M(o,w,b,"ask",u),await G(o,w,b),await B(o,{event:"watched",object:b,actor:w,attrs:{}},await A(o)),{object:await $(o,b,await g(o,b)),patterns:c}})}l(yt,"watchLocal");async function bt(e,t,n,a){return t.publishToken||t.principal.class==="anonymous"?E():await et(e,n,a)}l(bt,"ensureNodeStubFor");async function Se(e,t,n,a){const i=l(async()=>(await e.prepare(`SELECT count(*) AS n FROM watch_subscriptions s JOIN watches w ON w.watch_id = s.watch
3
- WHERE w.watcher = ? AND w.object = ?`).get(t.id,n.id)).n,"count"),r=await i();await Be(e,t,n,a??void 0);const o=await i();return o===0&&await Qe(e,t,n),{object:await g(e,n),removed:r-o}}l(Se,"dropWatch");async function gt(e){const t=O(e);if(e.query.get("watcher")&&await Re(t),!e.query.get("watcher")){const a=await x(e,t,{method:"DELETE",path:`${V(t)}/watch`,query:H(e)});if(a.kind==="unknown")throw we(t,a.unreachable);if(a.kind==="remote"){const i=a.status===404?a.body.error?.details:void 0,r=i?.deleted===!0?i.id:void 0;if(a.status>=400&&r===void 0)throw z(a.status,a.body);const o=r??a.body.object?.id,s=await v(async c=>{const u=await le(c,e),f=o===void 0?null:await I(c,o);return u===null||f===null||!await X(c,f)?null:await Se(c,u,f,e.query.get("pattern"))});if(r!==void 0){if(s===null)throw z(a.status,a.body);return{...s,machine:a.machine}}return Y(a.body,a.machine)}}const n=await qe(await N(),e.query.get("watcher")??void 0,e.query.get("watcher_machine")??void 0);return await jt(e,n)}l(gt,"unwatchRoute");async function jt(e,t=null){const n=e.query.get("pattern"),a=e.query.get("watcher");return await R(e.principal),await v(async i=>{if((e.publishToken||e.principal.class==="anonymous")&&!a)throw new y(404,"not_found","watcher not found");const r=l(async(c,u)=>await Se(i,c,u,n),"drop");if(a){const c=t===null?null:await(async()=>{const f=await I(i,a);return f!==null&&await tt(i,f)!==null?f:null})();if(t!==null&&c===null)return E();const u=c??(e.publishToken?await oe(i,a):await ne(i,a));return u===null?E():c===null&&await Ie(i,e,u)?(await se(i,e,u),await J(i,e,u),await r(u,await S(i,await C(i,u),O(e)))):await r(u,(await Ne(i,e,u,O(e))).object)}const o=await T(i,e),s=await Q(i,e)??ae(o);return await r(s,await S(i,o,O(e)))})}l(jt,"unwatchLocal");async function _t(e){const t=[],n=ee(e.query.get("type"),"type",["acted-on","links-to","watches"],t),a=ee(e.query.get("direction"),"direction",["out","in"],t);return t.length>0&&U("edges request",t),await R(e.principal),await v(async i=>{const r=await T(i,e),o=await S(i,r,O(e)),s=[];if(n!=="watches")for(const c of await Ge(i,r,o,{...n?{type:n}:{},direction:a??"both"}))s.push({type:c.type,src:await g(i,c.src),dst:await g(i,c.dst),...c.written_as?{written_as:c.written_as}:{}});if(n===void 0||n==="watches"){const c=[...a!=="in"?await Ze(i,r,o):[],...a!=="out"?await Ke(i,r,o):[]];for(const u of c)s.push({type:"watches",src:await g(i,u.watcher),dst:await g(i,u.object)})}return{items:s}})}l(_t,"edges");const W=l(e=>async t=>({status:200,body:await e(t)}),"ok"),Zt=[{method:"POST",pattern:"/v1/objects/search",handler:W(dt)},{method:"GET",pattern:"/v1/objects/:ref/edges",handler:W(_t)},{method:"POST",pattern:"/v1/objects/:ref/watch",handler:W(ht)},{method:"DELETE",pattern:"/v1/objects/:ref/watch",handler:W(gt)},{method:"GET",pattern:"/v1/objects/:ref",handler:W(st)},{method:"GET",pattern:"/v1/objects",handler:W(ft)}];export{ut as listBudget,Zt as objectRoutes};
3
+ WHERE w.watcher = ? AND w.object = ?`).get(t.id,n.id)).n,"count"),r=await i();await Be(e,t,n,a??void 0);const o=await i();return o===0&&await Qe(e,t,n),{object:await g(e,n),removed:r-o}}l(Se,"dropWatch");async function gt(e){const t=O(e);if(e.query.get("watcher")&&await Re(t),!e.query.get("watcher")){const a=await x(e,t,{method:"DELETE",path:`${V(t)}/watch`,query:H(e)});if(a.kind==="unknown")throw we(t,a.unreachable);if(a.kind==="remote"){const i=a.status===404?a.body.error?.details:void 0,r=i?.deleted===!0?i.id:void 0;if(a.status>=400&&r===void 0)throw z(a.status,a.body);const o=r??a.body.object?.id,s=await v(async c=>{const u=await le(c,e),f=o===void 0?null:await I(c,o);return u===null||f===null||!await X(c,f)?null:await Se(c,u,f,e.query.get("pattern"))});if(r!==void 0){if(s===null)throw z(a.status,a.body);return{...s,machine:a.machine}}return Y(a.body,a.machine)}}const n=await qe(await N(),e.query.get("watcher")??void 0,e.query.get("watcher_machine")??void 0);return await jt(e,n)}l(gt,"unwatchRoute");async function jt(e,t=null){const n=e.query.get("pattern"),a=e.query.get("watcher");return await R(e.principal),await v(async i=>{if((e.publishToken||e.principal.class==="anonymous")&&!a)throw new y(404,"not_found","watcher not found");const r=l(async(c,u)=>await Se(i,c,u,n),"drop");if(a){const c=t===null?null:await(async()=>{const f=await I(i,a);return f!==null&&await tt(i,f)!==null?f:null})();if(t!==null&&c===null)return E();const u=c??(e.publishToken?await oe(i,a):await ne(i,a));return u===null?E():c===null&&await Ie(i,e,u)?(await se(i,e,u),await J(i,e,u),await r(u,await S(i,await C(i,u),O(e)))):await r(u,(await Ne(i,e,u,O(e))).object)}const o=await T(i,e),s=await Q(i,e)??ae(o);return await r(s,await S(i,o,O(e)))})}l(jt,"unwatchLocal");async function _t(e){const t=[],n=ee(e.query.get("type"),"type",["acted-on","links-to","watches"],t),a=ee(e.query.get("direction"),"direction",["out","in"],t);return t.length>0&&U("edges request",t),await R(e.principal),await v(async i=>{const r=await T(i,e),o=await S(i,r,O(e)),s=[];if(n!=="watches")for(const c of await Ge(i,r,o,{...n?{type:n}:{},direction:a??"both"}))s.push({type:c.type,src:await g(i,c.src),dst:await g(i,c.dst),...c.written_as?{written_as:c.written_as}:{}});if(n===void 0||n==="watches"){const c=[...a!=="in"?await Ze(i,r,o):[],...a!=="out"?await Ke(i,r,o):[]];for(const u of c)s.push({type:"watches",src:await g(i,u.watcher),dst:await g(i,u.object)})}return{items:s}})}l(_t,"edges");const W=l(e=>async t=>({status:200,body:await e(t)}),"ok"),Zt=[{method:"POST",pattern:"/v1/objects/search",handler:W(dt)},{method:"GET",pattern:"/v1/objects/:ref/edges",handler:W(_t)},{method:"POST",pattern:"/v1/objects/:ref/watch",handler:W(ht)},{method:"DELETE",pattern:"/v1/objects/:ref/watch",handler:W(gt)},{method:"GET",pattern:"/v1/objects/:ref",handler:W(st)},{method:"GET",pattern:"/v1/objects",handler:W(ft)}];export{ut as listBudget,Zt as objectRoutes,ot as resolvedLocally};
@@ -9,6 +9,6 @@ export interface BootMigration {
9
9
  * time (idempotent via its own convergence, not a version gate) and must
10
10
  * isolate its own per-item failures — a thrown error here is NOT caught by
11
11
  * the boot sequence and would abort daemon startup. */
12
- apply(): BootMigrationResult;
12
+ apply(): BootMigrationResult | Promise<BootMigrationResult>;
13
13
  }
14
14
  export declare const BOOT_MIGRATIONS: readonly BootMigration[];
@@ -1 +1 @@
1
- var n=Object.defineProperty;var i=(e,r)=>n(e,"name",{value:r,configurable:!0});import{migrateLegacyInboxIdentities as t}from"../core/feed/inbox-migrate.js";const a=[{id:"legacy-inbox-identities",description:"normalize pre-cutover inbox entry/operation ids (UUID-spelled or missing) and cursors (ISO-timestamp boundaries) into canonical 32-lowercase-hex identities the strict inbox reader requires.",apply:i(()=>{const e=t();return{changed:e.nodes>0||e.failures>0,summary:{...e}}},"apply")}];export{a as BOOT_MIGRATIONS};
1
+ var o=Object.defineProperty;var r=(e,t)=>o(e,"name",{value:t,configurable:!0});import{migrateLegacyInboxIdentities as i}from"../core/feed/inbox-migrate.js";import{backfillComputedRev as a}from"../core/grants/mirror.js";import{isCloudRole as s}from"../core/canvas/person-state.js";import{emitEvent as n}from"../core/events/emit.js";const u=[{id:"legacy-inbox-identities",description:"normalize pre-cutover inbox entry/operation ids (UUID-spelled or missing) and cursors (ISO-timestamp boundaries) into canonical 32-lowercase-hex identities the strict inbox reader requires.",apply:r(()=>{const e=i();return{changed:e.nodes>0||e.failures>0,summary:{...e}}},"apply")},{id:"grant-computed-rev",description:"mark grant rows a pre-C-D2 build wrote (scopes computed, computed_rev NULL) as computed for their revision, so the terminal grant reads as active before the first directory sync after an upgrade or rollback (NL-550). A cloud role skips it: the directory owns its shared rows.",apply:r(async()=>{if(s())return{changed:!1,summary:{}};try{const e=await a();return{changed:e>0,summary:{rows:e}}}catch(e){return n({level:"warn",event:"daemon.boot_migration.failed",error:e,fields:{migration:"grant-computed-rev"}}),{changed:!1,summary:{}}}},"apply")}];export{u as BOOT_MIGRATIONS};
@@ -1 +1 @@
1
- var v=Object.defineProperty;var d=(e,r)=>v(e,"name",{value:r,configurable:!0});import{randomUUID as m}from"node:crypto";import{setTimeout as I}from"node:timers/promises";import{CRON_DEATH_POLL_MS as S,CRON_KILL_GRACE_MS as A,EMPTY_STDOUT_SHA256 as f}from"./capture.js";import{cronDaemonInstanceId as C,cronOwnerAlive as L,ensureCronOwnerLease as O}from"./live-runs.js";import{crashedOneShotSummary as y,escalateFailure as H}from"./escalation.js";import{settleRun as h}from"./settle.js";import{runningCrons as M,stopLeasedCronRun as w,setCronState as g,verifyLeasedCronRun as l}from"../../core/canvas/crons.js";import{emitEvent as c}from"../../core/events/emit.js";const i=new Set;async function B(e,r={}){await O();for(const t of await M()){if(t.run_lease_owner===C||i.has(t.cron_id)||t.run_lease_owner!==null&&await L(t.run_lease_owner))continue;if(t.run_pid===null||!l(t)){i.add(t.cron_id),D(t,e,r);continue}const a=t.run_started_at!=null?new Date(t.run_started_at).getTime():e;if(e-a<t.run_timeout_s*1e3)continue;const o={runId:t.run_execution_id??m(),startedAtIso:t.run_started_at??new Date(e).toISOString(),exitCode:-1,timedOut:!0,runTimeoutS:t.run_timeout_s,processErrorMessage:null,stdoutHead:"",stdoutSha256:f,stderrHead:`run timed out after ${t.run_timeout_s}s (recovered stale lease from a prior daemon instance)`};i.add(t.cron_id);const n=(async()=>{await w(t),await x(t),await h(t,{outOfBand:!1,outcome:{kind:"disposed",ctx:o},record:{runId:o.runId,startedAtIso:o.startedAtIso,finishedAtMs:e,durationMs:e-a,exitCode:-1,stdoutHead:null,stderrHead:o.stderrHead},lease:{kind:"clear"}})})().finally(()=>i.delete(t.cron_id));r.register?.(n),n.catch(s=>{c({level:"error",event:"cron.stale_lease.settle_failed",error:s,fields:{cron_id:t.cron_id}})})}}d(B,"recoverStaleCronLeases");async function x(e){if(!await p(e)&&(await w(e,"SIGKILL"),!await p(e)))throw new Error(`cron ${e.cron_id} run ${e.run_pid} survived SIGKILL`)}d(x,"awaitLeasedRunDeath");async function p(e){const r=Date.now()+A;for(;Date.now()<r;){if(!l(e))return!0;await I(S)}return!l(e)}d(p,"pollLeasedRunGone");function D(e,r,t){const a=e.recur==null,o=e.run_started_at!=null?new Date(e.run_started_at).getTime():r,n=e.run_pid===null?"the daemon life that claimed this run ended before its launch pid was recorded \u2014 the command may have started and its outcome is unknown":"the daemon life that owned this run ended before it settled \u2014 the process is gone and its outcome was never observed",s={runId:e.run_execution_id??m(),startedAtIso:e.run_started_at??new Date(r).toISOString(),exitCode:null,timedOut:!1,runTimeoutS:e.run_timeout_s,processErrorMessage:n,stdoutHead:"",stdoutSha256:f,stderrHead:`run outcome unobserved: ${n}`},_=(async()=>{let u=`crashed: ${n}${a?"":" \u2014 the next occurrence is unaffected"}`;a&&(await g(e.cron_id,"paused"),u=e.on_output==="silent"?`crashed: ${n} \u2014 one-shot paused, not re-fired (silent: not escalated)`:`crashed one-shot: ${await H(e,s,y(n))}`),await h(e,{outOfBand:!1,outcome:{kind:"stated",delivered:u,paused:a},record:{runId:s.runId,startedAtIso:s.startedAtIso,finishedAtMs:r,durationMs:Math.max(0,r-o),exitCode:null,stdoutHead:null,stderrHead:s.stderrHead},lease:"release"}),c({level:"warn",event:"cron.run.unobserved",fields:{cron_id:e.cron_id,name:e.name,one_shot:a}})})().finally(()=>i.delete(e.cron_id));t.register?.(_),_.catch(u=>{c({level:"error",event:"cron.crashed_run.settle_failed",error:u,fields:{cron_id:e.cron_id}})})}d(D,"settleCrashedRun");export{B as recoverStaleCronLeases};
1
+ var S=Object.defineProperty;var i=(e,t)=>S(e,"name",{value:t,configurable:!0});import{randomUUID as w}from"node:crypto";import{setTimeout as L}from"node:timers/promises";import{CRON_DEATH_POLL_MS as R,CRON_KILL_GRACE_MS as C,EMPTY_STDOUT_SHA256 as h}from"./capture.js";import{cronDaemonInstanceId as A,cronOwnerAlive as v,ensureCronOwnerLease as O}from"./live-runs.js";import{crashedOneShotSummary as x,escalateFailure as E}from"./escalation.js";import{settleRun as p}from"./settle.js";import{adoptCronRunId as g,getCron as M,runningCrons as D,stopLeasedCronRun as I,setCronState as H,verifyLeasedCronRun as l}from"../../core/canvas/crons.js";import{claimReconcilerLease as T,releaseReconcilerLease as $,renewReconcilerLease as b}from"../../core/canvas/reconciler-leases.js";import{emitEvent as c}from"../../core/events/emit.js";const _="cron-recovery",f=3e4;async function k(e){const t=w();if(await T(_,e,t,f)===void 0)return;let r=!1;const a=i(async()=>{if(r)return!1;try{r=!await b(_,e,t,f)}catch{r=!0}return!r},"holds"),n=setInterval(()=>{a()},f/3);return n.unref(),{holds:a,release:i(async()=>{clearInterval(n),await $(_,e,t)},"release")}}i(k,"claimRecovery");async function G(e){const t=await M(e.cron_id);if(t===null||t.run_state!=="running"||t.run_execution_id!==e.run_execution_id||t.run_started_at!==e.run_started_at||t.run_lease_owner!==e.run_lease_owner||t.run_lease_owner!==null&&await v(t.run_lease_owner))return null;if(t.run_execution_id!==null)return t;const r=w();return await g(t,r)?{...t,run_execution_id:r}:null}i(G,"reverifyAbandoned");async function W(e,t={}){await O();for(const r of await D()){if(r.run_lease_owner===A||r.run_lease_owner!==null&&await v(r.run_lease_owner))continue;const a=r.run_pid===null||!l(r);if(!a&&e-(r.run_started_at!=null?new Date(r.run_started_at).getTime():e)<r.run_timeout_s*1e3)continue;const n=await k(r.cron_id);if(n===void 0)continue;let o;try{o=await G(r)}catch(s){throw await n.release(),s}if(o===null){await n.release();continue}if(a){U(o,e,t,n);continue}K(o,e,t,n)}}i(W,"recoverStaleCronLeases");function K(e,t,r,a){const n=e.run_started_at!=null?new Date(e.run_started_at).getTime():t,o={runId:e.run_execution_id,startedAtIso:e.run_started_at??new Date(t).toISOString(),exitCode:-1,timedOut:!0,runTimeoutS:e.run_timeout_s,processErrorMessage:null,stdoutHead:"",stdoutSha256:h,stderrHead:`run timed out after ${e.run_timeout_s}s (recovered stale lease from a prior daemon instance)`},s=(async()=>{await a.holds()&&(await I(e),await N(e),await a.holds()&&await p(e,{outOfBand:!1,outcome:{kind:"disposed",ctx:o},record:{runId:o.runId,startedAtIso:o.startedAtIso,finishedAtMs:t,durationMs:t-n,exitCode:-1,stdoutHead:null,stderrHead:o.stderrHead},lease:{kind:"clear"}}))})().finally(()=>a.release());r.register?.(s),s.catch(u=>{c({level:"error",event:"cron.stale_lease.settle_failed",error:u,fields:{cron_id:e.cron_id}})})}i(K,"recoverTimedOutRun");async function N(e){if(!await y(e)&&(await I(e,"SIGKILL"),!await y(e)))throw new Error(`cron ${e.cron_id} run ${e.run_pid} survived SIGKILL`)}i(N,"awaitLeasedRunDeath");async function y(e){const t=Date.now()+C;for(;Date.now()<t;){if(!l(e))return!0;await L(R)}return!l(e)}i(y,"pollLeasedRunGone");function U(e,t,r,a){const n=e.recur==null,o=e.run_started_at!=null?new Date(e.run_started_at).getTime():t,s=e.run_pid===null?"the daemon life that claimed this run ended before its launch pid was recorded \u2014 the command may have started and its outcome is unknown":"the daemon life that owned this run ended before it settled \u2014 the process is gone and its outcome was never observed",u={runId:e.run_execution_id,startedAtIso:e.run_started_at??new Date(t).toISOString(),exitCode:null,timedOut:!1,runTimeoutS:e.run_timeout_s,processErrorMessage:s,stdoutHead:"",stdoutSha256:h,stderrHead:`run outcome unobserved: ${s}`},m=(async()=>{let d=`crashed: ${s}${n?"":" \u2014 the next occurrence is unaffected"}`;if(n){if(!await a.holds())return;if(await H(e.cron_id,"paused"),e.on_output==="silent")d=`crashed: ${s} \u2014 one-shot paused, not re-fired (silent: not escalated)`;else{if(!await a.holds())return;d=`crashed one-shot: ${await E(e,u,x(s))}`}}await a.holds()&&(await p(e,{outOfBand:!1,outcome:{kind:"stated",delivered:d,paused:n},record:{runId:u.runId,startedAtIso:u.startedAtIso,finishedAtMs:t,durationMs:Math.max(0,t-o),exitCode:null,stdoutHead:null,stderrHead:u.stderrHead},lease:"release"}),c({level:"warn",event:"cron.run.unobserved",fields:{cron_id:e.cron_id,name:e.name,one_shot:n}}))})().finally(()=>a.release());r.register?.(m),m.catch(d=>{c({level:"error",event:"cron.crashed_run.settle_failed",error:d,fields:{cron_id:e.cron_id}})})}i(U,"settleCrashedRun");export{W as recoverStaleCronLeases};
@@ -1 +1 @@
1
- var p=Object.defineProperty;var c=(e,u)=>p(e,"name",{value:u,configurable:!0});import{consumeCron as w,recordCronRunLocked as _,releaseCronRunLease as y,setCronState as k}from"../../core/canvas/crons.js";import{withCanvasWrite as I}from"../../core/canvas/db.js";import{enqueueDaemonAction as b}from"../../core/canvas/daemon-actions.js";import{enqueueNodeMail as v}from"../../core/feed/messages.js";import{emitEvent as g}from"../../core/events/emit.js";import{narrowedNotice as C}from"./narrowed.js";import{disposeSettledRun as h}from"./disposition.js";function x(e){return typeof e=="object"&&(e.kind==="park"||e.kind==="redue")}c(x,"occurrenceStaysOwed");async function $(e,u){const{outOfBand:t,outcome:d,record:o,lease:s}=u;let i,a,n;if(d.kind==="disposed"){const r=await h(e,d.ctx,t,d.selfCanceled??!1);i=r.delivered,a=r.paused,n=r.obligation}else if(d.kind==="refused"){i=`refused: ${d.reason}`;const r=!t&&d.reason==="scope_narrowed";a=!t&&(e.recur==null||r),a&&await k(e.cron_id,"paused"),r&&(n=await C(e,d.message)),g({level:"warn",event:"cron.fire.refused",fields:{cron_id:e.cron_id,execution_id:o.runId,grant_id:e.grant_id,reason:d.reason,out_of_band:t}})}else i=d.delivered,a=d.paused??!1;const m=await I(async r=>{if(n!==void 0){if(n.kind==="node"){const f=await v(n.destinationNodeId,{kind:"message",label:n.label,senderNodeId:n.senderNodeId,bodyJson:{body:n.stdout},urgency:n.urgency,wake:1,idempotencyKey:o.runId});d.kind!=="refused"&&(i=`delivered: ${f.deliveryId}`)}else if(n.kind==="action"){const f=await b({adapter:n.adapter,bodyJson:n.bodyJson,idempotencyKey:o.runId});d.kind!=="refused"&&(i=`delivered: ${f}`)}}const l={run_id:o.runId,cron_id:e.cron_id,started:o.startedAtIso,finished:new Date(o.finishedAtMs).toISOString(),duration_ms:o.durationMs,exit_code:o.exitCode,stdout_head:o.stdoutHead,stderr_head:o.stderrHead,delivered:i};return await _(r,l),l});return s!=="none"&&await y(e.cron_id,s==="release"?void 0:s),!t&&e.recur==null&&!a&&!x(s)&&await w(e.cron_id),m}c($,"settleRun");export{$ as settleRun};
1
+ var p=Object.defineProperty;var c=(e,u)=>p(e,"name",{value:u,configurable:!0});import{consumeCron as w,recordCronRunLocked as _,releaseCronRunLease as y,setCronState as k}from"../../core/canvas/crons.js";import{withCanvasWrite as I}from"../../core/canvas/db.js";import{enqueueDaemonAction as b}from"../../core/canvas/daemon-actions.js";import{enqueueNodeMail as v}from"../../core/feed/messages.js";import{emitEvent as g}from"../../core/events/emit.js";import{narrowedNotice as C}from"./narrowed.js";import{disposeSettledRun as h}from"./disposition.js";function x(e){return typeof e=="object"&&(e.kind==="park"||e.kind==="redue")}c(x,"occurrenceStaysOwed");async function $(e,u){const{outOfBand:t,outcome:d,record:r,lease:s}=u;let i,a,n;if(d.kind==="disposed"){const o=await h(e,d.ctx,t,d.selfCanceled??!1);i=o.delivered,a=o.paused,n=o.obligation}else if(d.kind==="refused"){i=`refused: ${d.reason}`;const o=!t&&d.reason==="scope_narrowed";a=!t&&(e.recur==null||o),a&&await k(e.cron_id,"paused"),o&&(n=await C(e,d.message)),g({level:"warn",event:"cron.fire.refused",fields:{cron_id:e.cron_id,execution_id:r.runId,grant_id:e.grant_id,reason:d.reason,out_of_band:t}})}else i=d.delivered,a=d.paused??!1;const m=await I(async o=>{if(n!==void 0){if(n.kind==="node"){const f=await v(n.destinationNodeId,{kind:"message",label:n.label,senderNodeId:n.senderNodeId,bodyJson:{body:n.stdout},urgency:n.urgency,wake:1,idempotencyKey:r.runId});d.kind!=="refused"&&(i=`delivered: ${f.deliveryId}`)}else if(n.kind==="action"){const f=await b({adapter:n.adapter,bodyJson:n.bodyJson,idempotencyKey:r.runId});d.kind!=="refused"&&(i=`delivered: ${f}`)}}const l={run_id:r.runId,cron_id:e.cron_id,started:r.startedAtIso,finished:new Date(r.finishedAtMs).toISOString(),duration_ms:r.durationMs,exit_code:r.exitCode,stdout_head:r.stdoutHead,stderr_head:r.stderrHead,delivered:i};return await _(o,l),l});return s!=="none"&&await y(e.cron_id,r.runId,s==="release"?void 0:s),!t&&e.recur==null&&!a&&!x(s)&&await w(e.cron_id),m}c($,"settleRun");export{$ as settleRun};
@@ -1,2 +1,2 @@
1
- var N=Object.defineProperty;var i=(e,t)=>N(e,"name",{value:t,configurable:!0});import{randomUUID as Y}from"node:crypto";import{CRON_OUTPUT_HEAD_BYTES as E,EMPTY_STDOUT_SHA256 as q,formatCronOutputHead as A}from"./cron/capture.js";import{clearLiveRun as g,cronDaemonInstanceId as L,ensureCronOwnerLease as J,registerLiveRun as V}from"./cron/live-runs.js";import{closeCronExecution as X,openCronExecution as z}from"./cron/run-socket.js";import{appProcessSandboxed as G}from"../core/spaces/process.js";import{nodeAgentDir as K}from"../core/canvas/paths.js";import{uidForApp as Q}from"../core/spaces/users.js";import{buildArmedRunContext as W}from"./cron/armed-context.js";import{ensureCronFolder as Z}from"./cron/folders.js";import{checkCronFire as j,cronPrincipalOf as ee}from"./cron/authority.js";import{refusalError as te}from"../core/ledger/index.js";import{startRefusal as re}from"../core/runtime/start-check.js";import{decideHeldSettle as ne,EXIT_HELD as oe,HELD_DELIVERED as ae}from"./cron/held.js";import{settleRun as O}from"./cron/settle.js";import{applyOverlapPolicies as se,expireDueCrons as de}from"./cron/passes.js";import{dueClockCrons as ie,acquireCronRunLease as le,releaseCronRunLease as ue,attachCronRunPid as ce,advanceCron as fe,setCronState as me}from"../core/canvas/crons.js";import{emitEvent as $}from"../core/events/emit.js";import{runAppCommand as pe}from"../core/runtime/run-command.js";import{nextSlotAfter as he}from"../core/wake.js";import{CRON_OUTPUT_HEAD_BYTES as Ye}from"./cron/capture.js";import{cronDaemonInstanceId as Je,markSelfCanceledCronRun as Ve}from"./cron/live-runs.js";import{recoverStaleCronLeases as ze}from"./cron/lease-recovery.js";async function we(e,t){const{runId:a,outOfBand:s,startedAtIso:u,finishedAtMs:c,code:d,timedOut:n,processError:f}=t,_=!s&&!n&&f==null&&d===oe&&!t.wasReplaced&&!t.wasSelfCanceled;let p,r;return t.wasReplaced?(p={kind:"stated",delivered:"replaced (overlap=replace)"},r="release"):_?(p={kind:"stated",delivered:ae},r=await ne(e,u,c)??"release"):(p={kind:"disposed",ctx:{runId:a,startedAtIso:u,exitCode:n?-1:d,timedOut:n,runTimeoutS:e.run_timeout_s,processErrorMessage:f!=null?f.message:null,stdoutHead:t.stdoutHead,stdoutSha256:t.stdoutSha256,stderrHead:t.stderrHead},selfCanceled:t.wasSelfCanceled},r=s?"release":{kind:"clear"}),O(e,{outOfBand:s,outcome:p,record:{runId:a,startedAtIso:u,finishedAtMs:c,durationMs:c-t.startedAtMs,exitCode:n?-1:d,stdoutHead:t.stdoutHead===""?null:t.stdoutHead,stderrHead:f!=null?`run process error: ${f.message}`.slice(0,E):t.stderrHead===""?null:t.stderrHead},lease:r})}i(we,"settleClosedRun");function R(e,t,a,s){const u=Date.now(),c=`${a}: ${s.message}`.slice(0,E);return O(e,{outOfBand:t.outOfBand,outcome:{kind:"disposed",ctx:{runId:t.runId,startedAtIso:t.startedAtIso,exitCode:null,timedOut:!1,runTimeoutS:e.run_timeout_s,processErrorMessage:s.message,stdoutHead:"",stdoutSha256:q,stderrHead:c}},record:{runId:t.runId,startedAtIso:t.startedAtIso,finishedAtMs:u,durationMs:u-t.startedAtMs,exitCode:null,stdoutHead:null,stderrHead:c},lease:"release"})}i(R,"settleUnspawnedRun");async function P(e,t){let a;try{a=he(e.recur,new Date(t))}catch(s){return $({level:"error",event:"cron.recur.unparseable",error:s,fields:{cron_id:e.cron_id,name:e.name,recur:e.recur}}),await me(e.cron_id,"paused"),new Error(`unparseable recurrence ${JSON.stringify(e.recur)}: ${s.message} \u2014 this cron cannot be rescheduled until its recurrence is fixed (\`crtr cron cancel\` and re-arm it), so it has been paused.`)}return await fe(e.cron_id,a),null}i(P,"advanceRecurrence");function Be(e,t){return B(e,t).settled}i(Be,"executeCron");function B(e,t){const{outOfBand:a}=t;let s=i(()=>{},"admit");const u=new Promise(d=>{s=d}),c=new Promise((d,n)=>{let f=!1,_=i(()=>{},"undo");const p=i(r=>{if(_(),!f){n(r);return}f=!1,ue(e.cron_id).then(()=>n(r),m=>{$({level:"error",event:"cron.lease.release_failed",error:m,fields:{cron_id:e.cron_id}}),n(r)})},"fail");(async()=>{const r=Y(),m=Date.now(),C=new Date(m).toISOString(),S={runId:r,outOfBand:a,startedAtIso:C,startedAtMs:m};if(await J(),!await le(e.cron_id,L,C,a,r)){d(null);return}f=!0;let h=await j(ee(e));if(h.allowed){const o=await re({grantee:e.grantee,sub:e.sub,grant_id:e.grant_id});o!==null&&(h={allowed:!1,reason:"limit_reached",message:te(o).message})}if(!h.allowed){try{if(!a&&e.recur!=null){const w=await P(e,m);if(w!==null)throw w}}catch(w){R(e,S,"run could not be armed",w).then(d,n);return}const o=Date.now();O(e,{outOfBand:a,outcome:{kind:"refused",reason:h.reason,message:h.message},record:{runId:r,startedAtIso:C,finishedAtMs:o,durationMs:o-m,exitCode:null,stdoutHead:null,stderrHead:`${h.reason}: ${h.message}`.slice(0,E)},lease:"release"}).then(d,n);return}let M;try{if(e.isolated&&Z(e.grantee,e.cron_id),{env:M}=await W(e,r),!a&&e.recur!=null){const o=await P(e,m);if(o!==null)throw o}}catch(o){R(e,S,"run could not be armed",o).then(d,n);return}let b=null,T=!1;const D={runId:r,replaced:!1,selfCanceled:!1,kill:i(()=>{b!==null?b():T=!0},"kill")};V(e.cron_id,D),_=i(()=>g(e.cron_id,r),"undo"),s();const x=G()?{executionId:r,kind:"cron",cronId:e.cron_id,fromExec:e.armed_from_exec,grantee:e.grantee,sub:e.sub,grantId:e.grant_id,scopes:e.scopes,originRunId:e.origin_run_id,isolated:e.isolated,anchor:e.anchor_node,uid:await Q(e.grantee),rebuilt:!1,refusal:null}:null,I=i(()=>{x!==null&&X(r)},"closeExecution");_=i(()=>{g(e.cron_id,r),I()},"undo"),i(async()=>(x!==null&&await z(x,e.cwd,e.profile),pe({command:e.command,cwd:e.cwd,env:M,app:e.grantee,isolated:e.isolated,principal:{sub:e.sub,grantId:e.grant_id,scopes:e.scopes},...e.isolated?{folder:e.cwd}:{},...x!==null?{cron:{executionId:r,...e.anchor_node===null||e.isolated?{}:{anchorDir:K(e.anchor_node,e.grantee)}}}:e.anchor_node===null||e.isolated?{}:{nodeId:e.anchor_node},timeoutMs:e.run_timeout_s*1e3,headBytes:E})),"launch")().then(async o=>{if(o.pid===null){g(e.cron_id,r),I(),o.completion.then(l=>{R(e,S,"run failed to spawn",l.processError??new Error("bash did not provide a process id")).then(d,n)},n);return}_=i(()=>{g(e.cron_id,r),I(),o.terminate()},"undo");let w=!1;const v=i(()=>{o.completion.then(l=>{const k=D.replaced,U=D.selfCanceled,H=x?.refusal??null;if(g(e.cron_id,r),I(),w){d(null);return}if(H!==null&&!k){const y=Date.now(),F=A(l.stderr,l.stderrTruncated);O(e,{outOfBand:a,outcome:{kind:"refused",reason:H.reason,message:H.message},record:{runId:r,startedAtIso:C,finishedAtMs:y,durationMs:y-m,exitCode:l.exitCode,stdoutHead:A(l.stdout,l.stdoutTruncated)||null,stderrHead:`${H.reason}: ${H.message}
2
- ${F}`.trim().slice(0,E)},lease:"release"}).then(d,n);return}we(e,{runId:r,outOfBand:a,startedAtIso:C,startedAtMs:m,finishedAtMs:Date.now(),code:l.exitCode,timedOut:l.timedOut,processError:l.processError,stdoutHead:A(l.stdout,l.stdoutTruncated),stderrHead:A(l.stderr,l.stderrTruncated),stdoutSha256:l.stdoutSha256,wasReplaced:k,wasSelfCanceled:U}).then(d,n)},n)},"settleCommand");if(!await ce(e.cron_id,L,C,o.pid)&&!D.selfCanceled){w=!0,o.terminate(),v();return}b=o.terminate,T&&o.terminate(),v()},o=>{g(e.cron_id,r),I(),R(e,S,"run failed to spawn",o).then(d,n)}).catch(p)})().catch(p)});return c.then(s,s),{admitted:u,settled:c}}i(B,"startCron");async function Ue(e,t={}){const a=new Date(e).toISOString();await de(a),await se(e,a);const s=[];for(const u of await ie(a)){const{admitted:c,settled:d}=B(u,{outOfBand:!1}),n=d.then(()=>{});n.catch(()=>{}),await c,s.push(n),t.register?.(n)}for(const u of s)u.catch(()=>{});return s}i(Ue,"runDueCrons");export{Ye as CRON_OUTPUT_HEAD_BYTES,Je as cronDaemonInstanceId,Be as executeCron,Ve as markSelfCanceledCronRun,ze as recoverStaleCronLeases,Ue as runDueCrons,B as startCron};
1
+ var N=Object.defineProperty;var i=(e,t)=>N(e,"name",{value:t,configurable:!0});import{randomUUID as Y}from"node:crypto";import{CRON_OUTPUT_HEAD_BYTES as E,EMPTY_STDOUT_SHA256 as q,formatCronOutputHead as A}from"./cron/capture.js";import{clearLiveRun as g,cronDaemonInstanceId as L,ensureCronOwnerLease as J,registerLiveRun as V}from"./cron/live-runs.js";import{closeCronExecution as X,openCronExecution as z}from"./cron/run-socket.js";import{appProcessSandboxed as G}from"../core/spaces/process.js";import{nodeAgentDir as K}from"../core/canvas/paths.js";import{uidForApp as Q}from"../core/spaces/users.js";import{buildArmedRunContext as W}from"./cron/armed-context.js";import{ensureCronFolder as Z}from"./cron/folders.js";import{checkCronFire as j,cronPrincipalOf as ee}from"./cron/authority.js";import{refusalError as te}from"../core/ledger/index.js";import{startRefusal as re}from"../core/runtime/start-check.js";import{decideHeldSettle as ne,EXIT_HELD as oe,HELD_DELIVERED as ae}from"./cron/held.js";import{settleRun as O}from"./cron/settle.js";import{applyOverlapPolicies as se,expireDueCrons as de}from"./cron/passes.js";import{dueClockCrons as ie,acquireCronRunLease as le,releaseCronRunLease as ue,attachCronRunPid as ce,advanceCron as fe,setCronState as me}from"../core/canvas/crons.js";import{emitEvent as $}from"../core/events/emit.js";import{runAppCommand as pe}from"../core/runtime/run-command.js";import{nextSlotAfter as he}from"../core/wake.js";import{CRON_OUTPUT_HEAD_BYTES as Ye}from"./cron/capture.js";import{cronDaemonInstanceId as Je,markSelfCanceledCronRun as Ve}from"./cron/live-runs.js";import{recoverStaleCronLeases as ze}from"./cron/lease-recovery.js";async function we(e,t){const{runId:o,outOfBand:s,startedAtIso:u,finishedAtMs:c,code:d,timedOut:r,processError:m}=t,a=!s&&!r&&m==null&&d===oe&&!t.wasReplaced&&!t.wasSelfCanceled;let p,w;return t.wasReplaced?(p={kind:"stated",delivered:"replaced (overlap=replace)"},w="release"):a?(p={kind:"stated",delivered:ae},w=await ne(e,u,c)??"release"):(p={kind:"disposed",ctx:{runId:o,startedAtIso:u,exitCode:r?-1:d,timedOut:r,runTimeoutS:e.run_timeout_s,processErrorMessage:m!=null?m.message:null,stdoutHead:t.stdoutHead,stdoutSha256:t.stdoutSha256,stderrHead:t.stderrHead},selfCanceled:t.wasSelfCanceled},w=s?"release":{kind:"clear"}),O(e,{outOfBand:s,outcome:p,record:{runId:o,startedAtIso:u,finishedAtMs:c,durationMs:c-t.startedAtMs,exitCode:r?-1:d,stdoutHead:t.stdoutHead===""?null:t.stdoutHead,stderrHead:m!=null?`run process error: ${m.message}`.slice(0,E):t.stderrHead===""?null:t.stderrHead},lease:w})}i(we,"settleClosedRun");function R(e,t,o,s){const u=Date.now(),c=`${o}: ${s.message}`.slice(0,E);return O(e,{outOfBand:t.outOfBand,outcome:{kind:"disposed",ctx:{runId:t.runId,startedAtIso:t.startedAtIso,exitCode:null,timedOut:!1,runTimeoutS:e.run_timeout_s,processErrorMessage:s.message,stdoutHead:"",stdoutSha256:q,stderrHead:c}},record:{runId:t.runId,startedAtIso:t.startedAtIso,finishedAtMs:u,durationMs:u-t.startedAtMs,exitCode:null,stdoutHead:null,stderrHead:c},lease:"release"})}i(R,"settleUnspawnedRun");async function P(e,t){let o;try{o=he(e.recur,new Date(t))}catch(s){return $({level:"error",event:"cron.recur.unparseable",error:s,fields:{cron_id:e.cron_id,name:e.name,recur:e.recur}}),await me(e.cron_id,"paused"),new Error(`unparseable recurrence ${JSON.stringify(e.recur)}: ${s.message} \u2014 this cron cannot be rescheduled until its recurrence is fixed (\`crtr cron cancel\` and re-arm it), so it has been paused.`)}return await fe(e.cron_id,o),null}i(P,"advanceRecurrence");function Be(e,t){return B(e,t).settled}i(Be,"executeCron");function B(e,t){const{outOfBand:o}=t;let s=i(()=>{},"admit");const u=new Promise(d=>{s=d}),c=new Promise((d,r)=>{let m=!1;const a=Y();let p=i(()=>{},"undo");const w=i(f=>{if(p(),!m){r(f);return}m=!1,ue(e.cron_id,a).then(()=>r(f),h=>{$({level:"error",event:"cron.lease.release_failed",error:h,fields:{cron_id:e.cron_id}}),r(f)})},"fail");(async()=>{const f=Date.now(),h=new Date(f).toISOString(),S={runId:a,outOfBand:o,startedAtIso:h,startedAtMs:f};if(await J(),!await le(e.cron_id,L,h,o,a)){d(null);return}m=!0;let _=await j(ee(e));if(_.allowed){const n=await re({grantee:e.grantee,sub:e.sub,grant_id:e.grant_id});n!==null&&(_={allowed:!1,reason:"limit_reached",message:te(n).message})}if(!_.allowed){try{if(!o&&e.recur!=null){const C=await P(e,f);if(C!==null)throw C}}catch(C){R(e,S,"run could not be armed",C).then(d,r);return}const n=Date.now();O(e,{outOfBand:o,outcome:{kind:"refused",reason:_.reason,message:_.message},record:{runId:a,startedAtIso:h,finishedAtMs:n,durationMs:n-f,exitCode:null,stdoutHead:null,stderrHead:`${_.reason}: ${_.message}`.slice(0,E)},lease:"release"}).then(d,r);return}let M;try{if(e.isolated&&Z(e.grantee,e.cron_id),{env:M}=await W(e,a),!o&&e.recur!=null){const n=await P(e,f);if(n!==null)throw n}}catch(n){R(e,S,"run could not be armed",n).then(d,r);return}let b=null,T=!1;const D={runId:a,replaced:!1,selfCanceled:!1,kill:i(()=>{b!==null?b():T=!0},"kill")};V(e.cron_id,D),p=i(()=>g(e.cron_id,a),"undo"),s();const x=G()?{executionId:a,kind:"cron",cronId:e.cron_id,fromExec:e.armed_from_exec,grantee:e.grantee,sub:e.sub,grantId:e.grant_id,scopes:e.scopes,originRunId:e.origin_run_id,isolated:e.isolated,anchor:e.anchor_node,uid:await Q(e.grantee),rebuilt:!1,refusal:null}:null,I=i(()=>{x!==null&&X(a)},"closeExecution");p=i(()=>{g(e.cron_id,a),I()},"undo"),i(async()=>(x!==null&&await z(x,e.cwd,e.profile),pe({command:e.command,cwd:e.cwd,env:M,app:e.grantee,isolated:e.isolated,principal:{sub:e.sub,grantId:e.grant_id,scopes:e.scopes},...e.isolated?{folder:e.cwd}:{},...x!==null?{cron:{executionId:a,...e.anchor_node===null||e.isolated?{}:{anchorDir:K(e.anchor_node,e.grantee)}}}:e.anchor_node===null||e.isolated?{}:{nodeId:e.anchor_node},timeoutMs:e.run_timeout_s*1e3,headBytes:E})),"launch")().then(async n=>{if(n.pid===null){g(e.cron_id,a),I(),n.completion.then(l=>{R(e,S,"run failed to spawn",l.processError??new Error("bash did not provide a process id")).then(d,r)},r);return}p=i(()=>{g(e.cron_id,a),I(),n.terminate()},"undo");let C=!1;const v=i(()=>{n.completion.then(l=>{const k=D.replaced,U=D.selfCanceled,H=x?.refusal??null;if(g(e.cron_id,a),I(),C){d(null);return}if(H!==null&&!k){const y=Date.now(),F=A(l.stderr,l.stderrTruncated);O(e,{outOfBand:o,outcome:{kind:"refused",reason:H.reason,message:H.message},record:{runId:a,startedAtIso:h,finishedAtMs:y,durationMs:y-f,exitCode:l.exitCode,stdoutHead:A(l.stdout,l.stdoutTruncated)||null,stderrHead:`${H.reason}: ${H.message}
2
+ ${F}`.trim().slice(0,E)},lease:"release"}).then(d,r);return}we(e,{runId:a,outOfBand:o,startedAtIso:h,startedAtMs:f,finishedAtMs:Date.now(),code:l.exitCode,timedOut:l.timedOut,processError:l.processError,stdoutHead:A(l.stdout,l.stdoutTruncated),stderrHead:A(l.stderr,l.stderrTruncated),stdoutSha256:l.stdoutSha256,wasReplaced:k,wasSelfCanceled:U}).then(d,r)},r)},"settleCommand");if(!await ce(e.cron_id,L,h,n.pid)&&!D.selfCanceled){C=!0,n.terminate(),v();return}b=n.terminate,T&&n.terminate(),v()},n=>{g(e.cron_id,a),I(),R(e,S,"run failed to spawn",n).then(d,r)}).catch(w)})().catch(w)});return c.then(s,s),{admitted:u,settled:c}}i(B,"startCron");async function Ue(e,t={}){const o=new Date(e).toISOString();await de(o),await se(e,o);const s=[];for(const u of await ie(o)){const{admitted:c,settled:d}=B(u,{outOfBand:!1}),r=d.then(()=>{});r.catch(()=>{}),await c,s.push(r),t.register?.(r)}for(const u of s)u.catch(()=>{});return s}i(Ue,"runDueCrons");export{Ye as CRON_OUTPUT_HEAD_BYTES,Je as cronDaemonInstanceId,Be as executeCron,Ve as markSelfCanceledCronRun,ze as recoverStaleCronLeases,Ue as runDueCrons,B as startCron};
@@ -15,4 +15,4 @@ ${o}
15
15
  `),process.exit(1)}try{process.platform==="linux"&&b(x)&&(await L({operation:"daemon.handover"}),process.exit(0)),process.pid===1&&await It();const r=await xt({waitForJoinLock:!0});_.fresh(()=>{u({level:"info",event:"daemon.handover.completed",fields:{predecessor_pid:process.pid,successor_pid:r.pid??r.existing_pid??null,spawned:r.started}})})}catch(r){_.fresh(()=>{u({level:"error",event:"daemon.handover.successor_failed",error:r})});const o=r instanceof Error?r.message:String(r);process.stderr.write(`[crtrd] handover successor failed to start: ${o}
16
16
  `),process.exit(1)}process.exit(0)}i(Ke,"performHandover");function I(){if(P!==void 0)return P;const r=We();return P=r,r.then(()=>{P===r&&(P=void 0)},()=>{P===r&&(P=void 0)}),r}i(I,"requestCleanup");async function Ve(){S={phase:"initializing",message:Cn,blockerPaths:[]},D!==void 0&&!H&&(H=!0,await D.close({graceMs:Tn}))}i(Ve,"drainApi");async function we(r){try{r==="SIGTERM"&&e.role==="api"&&await Ve(),await I(),await Bt({claimed:i(async()=>{try{return m&&await At()}finally{await le()}},"claimed")}),process.exit(0)}catch(o){process.exitCode=1;const h=o instanceof Error?o.stack??`${o.name}: ${o.message}`:String(o);process.stderr.write(`[crtrd] ${r} cleanup failed:
17
17
  ${h}
18
- `),process.exit(1)}}i(we,"handleSignal");function he(){we("SIGINT")}i(he,"onSigint");function ve(){we("SIGTERM")}i(ve,"onSigterm");function ge(){I().catch(()=>{})}i(ge,"onExit");async function ie(r){k&&(B=B.then(r).then(()=>{},o=>{_.fresh(()=>{u({level:"error",event:"daemon.lane_job.failed",error:o})})}))}i(ie,"enqueue");async function W(){!k||Q||(He.check()&&E&&(u({level:"info",event:"daemon.resume.detected"}),R(E().catch(()=>{}))),Q=!0,await ie(async()=>{if(Q=!1,!!k)try{f||await Ft({log:l}),await xn(Date.now(),fe)}catch(r){_.fresh(()=>{u({level:"error",event:"daemon.tick.failed",error:r})})}}))}i(W,"enqueueTick");let G=null;async function Ye(){if(G!==null)throw{status:500,code:"admission_failed",message:`daemon admission previously failed: ${G instanceof Error?G.message:String(G)}`};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 r=S.phase==="prepared";try{return await ae(),S={phase:"ready",message:"",blockerPaths:[]},r?{admitted:!0,already_admitted:!1,startup_phase:"ready"}:{admitted:!1,already_admitted:!0,startup_phase:"ready"}}catch(o){throw G=o,{status:500,code:"admission_failed",message:`daemon admission failed: ${o instanceof Error?o.message:String(o)}`}}}i(Ye,"admitStartup");async function Qe(r){if(C!==null)throw{status:409,code:"migration_in_progress",message:`the canvas import is already running (${C})`};C="repair";try{const o=await en({dryRun:r.dryRun});if(r.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(h){const s=h instanceof Error?h.message:String(h);return setTimeout(()=>{I().catch(()=>{})},1e3),{result:o,resumed:!1,resumeError:s}}}finally{C=null}}i(Qe,"repairMigrations");async function Xe(){Y=e.intervalMs??Vr;const r=g.token;T=new Kt({epoch:r,enqueue:ie}),kt(T),S={phase:"recovering",message:"daemon startup recovery is running and normal services are unavailable",blockerPaths:[]},_.fresh(()=>{u({level:"info",event:"daemon.started",fields:{pid:process.pid,interval_ms:Y}})});const o=y;_.fresh(()=>{u({level:"info",event:"daemon.install_id.resolved",fields:{install_id:o}})});const h=await Tr(o);if(_.fresh(()=>{u({level:"info",event:"daemon.environment.registered",fields:{environment_id:h.environmentId,created:h.created}})}),_.fresh(()=>{let s;try{s=Kr()}catch{return}s!==null&&u({level:"warn",event:"daemon.startup.warning",fields:{stage:"termrender",warning:s.slice(0,2048)}})}),pt(),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&&Dr(),!V(e.role)){S={phase:"ready",message:"",blockerPaths:[]};return}if(await _.fresh(async()=>{await Jr(),await Ur(),await qr(Date.now()),await Wr(Date.now())}),await _.fresh(async()=>{const{reconcile:s,migrated:t}=await Tt(at);s.changed&&u({level:"info",event:"daemon.boot_change.reconciled",fields:{cleared_count:s.cleared.length,same_boot_proven:s.sameBootProven}}),t.length>0&&u({level:"info",event:"daemon.pid_identity.migrated",fields:{migrated_count:t.length}})}),await _.fresh(async()=>{for(const s of await Ie())s.status!=="active"||s.pi_pid!=null||s.frozen_at!=null||s.respawn_not_before!=null||(await xe(s.node_id,new Date().toISOString()),u({level:"warn",event:"daemon.startup.launch_debt_recorded",node_id:s.node_id}))}),await _.fresh(async()=>{await yt();for(const s of Yt){const t=s.apply();t.changed&&u({level:"info",event:"daemon.boot_migration.applied",fields:{migration:s.id,...t.summary}})}}),R(zr()),E){const s=i(()=>{R(E().catch(()=>{})),R(nr().then(t=>M?.observe(t)).then(()=>{},t=>{u({level:"warn",event:"daemon.peer.status_failed",error:t})}))},"refresh");R(jr().then(({completion:t})=>t).catch(t=>{u({level:"error",event:"daemon.grants.sweep_failed",error:t})})),s(),N=setInterval(s,Br*1e3),N.unref(),oe=tr({joined:!0,register:R})}await ie(async()=>{await Jt(),await Wt()}),j=setInterval(()=>{W().catch(s=>u({level:"error",event:"daemon.tick.failed",error:s}))},Y),X=await St(()=>{W().catch(s=>u({level:"error",event:"daemon.tick.failed",error:s}))}),Z=await F.subscribe(()=>{W().catch(s=>u({level:"error",event:"daemon.tick.failed",error:s}))},{kinds:["spend_limits"]}),await W()}i(Xe,"completeStartup");function ae(){return Ue??=Xe().catch(r=>{throw S={phase:"initializing",message:"daemon startup recovery failed and normal services are unavailable",blockerPaths:[]},r})}i(ae,"resumeStartup");try{process.on("SIGINT",he),process.on("SIGTERM",ve),process.on("exit",ge),Qt(),p!==null&&u({level:"info",event:"daemon.person.resolved",fields:{person_id:p.id,source:p.source}}),n!==null&&u({level:"info",event:"daemon.permissions.boot",fields:{...n}}),c!==null&&u({level:"info",event:"daemon.person.retired",fields:{person_id:c.person,joined_from:c.joinedFrom,retired:c.retired,columns:c.columns}}),$(e.role)&&(U=await dr());const r=g.token;Pt({epoch:r,requestHandover:Je,registerDetached:R,startupBlock:qe,admitStartup:Ye,repairMigrations:Qe}),Be(),D=$(e.role)?kr({tcp:e.tcp}):Dn(e),await D.ready;const o=lr()??se("user").document_port;if($(e.role)){const s=Er(o,Ir());try{await s.ready,re=s}catch(t){u({level:"warn",event:"daemon.document_listener.bind_failed",fields:{port:o,error:t instanceof Error?t.message:String(t)}})}}const h=se("user").runtime;if(h?.issuer&&(E=Fr(h.issuer,R),h.unsandboxed===!0&&(M=or({syncGrants:E}))),$(e.role)&&(te=await Gr()),ne=await Or({serves:$(e.role),runsLanes:V(e.role)}),h?.unsandboxed===!0&&h.listener!==void 0&&u({level:"warn",event:"daemon.app_listener.refused_unsandboxed",fields:{reason:"runtime.unsandboxed is set; runtime.listener is ignored"}}),$(e.role)&&h!==void 0&&h.listener!==void 0&&h.unsandboxed!==!0&&(A=await xr(h,async()=>await Hr(h.issuer.replace(/\/$/,"")),E),await A.ready),e.role===void 0)try{await Xt()}catch(s){if(C=null,s instanceof Zt)return S={phase:"blocked",message:s.message,blockerPaths:s.blockerPaths},I;throw s}process.platform==="linux"&&b(x)&&(wr(),await ur("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{C=null}return I}catch(r){try{await I()}catch(o){throw new AggregateError([r,o],"daemon startup failed and cleanup also failed")}throw r}}i($n,"runDaemon");var Pi=$n;export{Tn as API_DRAIN_GRACE_MS,de as brokerCommandDeclaresCanvasHome,pe as brokerCommandEpoch,Pi as default,V as roleRunsLanes,$ as roleServesRequests,$n as runDaemon,xn as superviseTick,dn as teardownFleet};
18
+ `),process.exit(1)}}i(we,"handleSignal");function he(){we("SIGINT")}i(he,"onSigint");function ve(){we("SIGTERM")}i(ve,"onSigterm");function ge(){I().catch(()=>{})}i(ge,"onExit");async function ie(r){k&&(B=B.then(r).then(()=>{},o=>{_.fresh(()=>{u({level:"error",event:"daemon.lane_job.failed",error:o})})}))}i(ie,"enqueue");async function W(){!k||Q||(He.check()&&E&&(u({level:"info",event:"daemon.resume.detected"}),R(E().catch(()=>{}))),Q=!0,await ie(async()=>{if(Q=!1,!!k)try{f||await Ft({log:l}),await xn(Date.now(),fe)}catch(r){_.fresh(()=>{u({level:"error",event:"daemon.tick.failed",error:r})})}}))}i(W,"enqueueTick");let G=null;async function Ye(){if(G!==null)throw{status:500,code:"admission_failed",message:`daemon admission previously failed: ${G instanceof Error?G.message:String(G)}`};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 r=S.phase==="prepared";try{return await ae(),S={phase:"ready",message:"",blockerPaths:[]},r?{admitted:!0,already_admitted:!1,startup_phase:"ready"}:{admitted:!1,already_admitted:!0,startup_phase:"ready"}}catch(o){throw G=o,{status:500,code:"admission_failed",message:`daemon admission failed: ${o instanceof Error?o.message:String(o)}`}}}i(Ye,"admitStartup");async function Qe(r){if(C!==null)throw{status:409,code:"migration_in_progress",message:`the canvas import is already running (${C})`};C="repair";try{const o=await en({dryRun:r.dryRun});if(r.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(h){const s=h instanceof Error?h.message:String(h);return setTimeout(()=>{I().catch(()=>{})},1e3),{result:o,resumed:!1,resumeError:s}}}finally{C=null}}i(Qe,"repairMigrations");async function Xe(){Y=e.intervalMs??Vr;const r=g.token;T=new Kt({epoch:r,enqueue:ie}),kt(T),S={phase:"recovering",message:"daemon startup recovery is running and normal services are unavailable",blockerPaths:[]},_.fresh(()=>{u({level:"info",event:"daemon.started",fields:{pid:process.pid,interval_ms:Y}})});const o=y;_.fresh(()=>{u({level:"info",event:"daemon.install_id.resolved",fields:{install_id:o}})});const h=await Tr(o);if(_.fresh(()=>{u({level:"info",event:"daemon.environment.registered",fields:{environment_id:h.environmentId,created:h.created}})}),_.fresh(()=>{let s;try{s=Kr()}catch{return}s!==null&&u({level:"warn",event:"daemon.startup.warning",fields:{stage:"termrender",warning:s.slice(0,2048)}})}),pt(),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&&Dr(),!V(e.role)){S={phase:"ready",message:"",blockerPaths:[]};return}if(await _.fresh(async()=>{await Jr(),await Ur(),await qr(Date.now()),await Wr(Date.now())}),await _.fresh(async()=>{const{reconcile:s,migrated:t}=await Tt(at);s.changed&&u({level:"info",event:"daemon.boot_change.reconciled",fields:{cleared_count:s.cleared.length,same_boot_proven:s.sameBootProven}}),t.length>0&&u({level:"info",event:"daemon.pid_identity.migrated",fields:{migrated_count:t.length}})}),await _.fresh(async()=>{for(const s of await Ie())s.status!=="active"||s.pi_pid!=null||s.frozen_at!=null||s.respawn_not_before!=null||(await xe(s.node_id,new Date().toISOString()),u({level:"warn",event:"daemon.startup.launch_debt_recorded",node_id:s.node_id}))}),await _.fresh(async()=>{await yt();for(const s of Yt){const t=await s.apply();t.changed&&u({level:"info",event:"daemon.boot_migration.applied",fields:{migration:s.id,...t.summary}})}}),R(zr()),E){const s=i(()=>{R(E().catch(()=>{})),R(nr().then(t=>M?.observe(t)).then(()=>{},t=>{u({level:"warn",event:"daemon.peer.status_failed",error:t})}))},"refresh");R(jr().then(({completion:t})=>t).catch(t=>{u({level:"error",event:"daemon.grants.sweep_failed",error:t})})),s(),N=setInterval(s,Br*1e3),N.unref(),oe=tr({joined:!0,register:R})}await ie(async()=>{await Jt(),await Wt()}),j=setInterval(()=>{W().catch(s=>u({level:"error",event:"daemon.tick.failed",error:s}))},Y),X=await St(()=>{W().catch(s=>u({level:"error",event:"daemon.tick.failed",error:s}))}),Z=await F.subscribe(()=>{W().catch(s=>u({level:"error",event:"daemon.tick.failed",error:s}))},{kinds:["spend_limits"]}),await W()}i(Xe,"completeStartup");function ae(){return Ue??=Xe().catch(r=>{throw S={phase:"initializing",message:"daemon startup recovery failed and normal services are unavailable",blockerPaths:[]},r})}i(ae,"resumeStartup");try{process.on("SIGINT",he),process.on("SIGTERM",ve),process.on("exit",ge),Qt(),p!==null&&u({level:"info",event:"daemon.person.resolved",fields:{person_id:p.id,source:p.source}}),n!==null&&u({level:"info",event:"daemon.permissions.boot",fields:{...n}}),c!==null&&u({level:"info",event:"daemon.person.retired",fields:{person_id:c.person,joined_from:c.joinedFrom,retired:c.retired,columns:c.columns}}),$(e.role)&&(U=await dr());const r=g.token;Pt({epoch:r,requestHandover:Je,registerDetached:R,startupBlock:qe,admitStartup:Ye,repairMigrations:Qe}),Be(),D=$(e.role)?kr({tcp:e.tcp}):Dn(e),await D.ready;const o=lr()??se("user").document_port;if($(e.role)){const s=Er(o,Ir());try{await s.ready,re=s}catch(t){u({level:"warn",event:"daemon.document_listener.bind_failed",fields:{port:o,error:t instanceof Error?t.message:String(t)}})}}const h=se("user").runtime;if(h?.issuer&&(E=Fr(h.issuer,R),h.unsandboxed===!0&&(M=or({syncGrants:E}))),$(e.role)&&(te=await Gr()),ne=await Or({serves:$(e.role),runsLanes:V(e.role)}),h?.unsandboxed===!0&&h.listener!==void 0&&u({level:"warn",event:"daemon.app_listener.refused_unsandboxed",fields:{reason:"runtime.unsandboxed is set; runtime.listener is ignored"}}),$(e.role)&&h!==void 0&&h.listener!==void 0&&h.unsandboxed!==!0&&(A=await xr(h,async()=>await Hr(h.issuer.replace(/\/$/,"")),E),await A.ready),e.role===void 0)try{await Xt()}catch(s){if(C=null,s instanceof Zt)return S={phase:"blocked",message:s.message,blockerPaths:s.blockerPaths},I;throw s}process.platform==="linux"&&b(x)&&(wr(),await ur("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{C=null}return I}catch(r){try{await I()}catch(o){throw new AggregateError([r,o],"daemon startup failed and cleanup also failed")}throw r}}i($n,"runDaemon");var Pi=$n;export{Tn as API_DRAIN_GRACE_MS,de as brokerCommandDeclaresCanvasHome,pe as brokerCommandEpoch,Pi as default,V as roleRunsLanes,$ as roleServesRequests,$n as runDaemon,xn as superviseTick,dn as teardownFleet};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.572",
3
+ "version": "0.3.574",
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.572",
148
+ "@north-light/identity": "0.3.574",
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.572",
3
+ "version": "0.3.574",
4
4
  "description": "Northlight access-token verification and scope rules",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/runtime.lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.572",
3
+ "version": "0.3.574",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@north-light/cli",
9
- "version": "0.3.572",
9
+ "version": "0.3.574",
10
10
  "hasInstallScript": true,
11
11
  "license": "UNLICENSED",
12
12
  "workspaces": [
@@ -28,7 +28,7 @@
28
28
  "@milkdown/preset-gfm": "^7.22.3",
29
29
  "@milkdown/prose": "^7.22.3",
30
30
  "@milkdown/utils": "^7.22.3",
31
- "@north-light/identity": "0.3.572",
31
+ "@north-light/identity": "0.3.574",
32
32
  "cron-parser": "^5.6.0",
33
33
  "esbuild": "^0.27.7",
34
34
  "jose": "^6.2.12",
@@ -12459,17 +12459,17 @@
12459
12459
  },
12460
12460
  "packages/crouter-api": {
12461
12461
  "name": "@north-light/api",
12462
- "version": "0.3.572",
12462
+ "version": "0.3.574",
12463
12463
  "license": "UNLICENSED"
12464
12464
  },
12465
12465
  "packages/crouter-env-docker": {
12466
12466
  "name": "@north-light/env-docker",
12467
- "version": "0.3.572",
12467
+ "version": "0.3.574",
12468
12468
  "license": "UNLICENSED"
12469
12469
  },
12470
12470
  "packages/crouter-identity": {
12471
12471
  "name": "@north-light/identity",
12472
- "version": "0.3.572",
12472
+ "version": "0.3.574",
12473
12473
  "license": "UNLICENSED",
12474
12474
  "dependencies": {
12475
12475
  "jose": "^6.2.1"
@@ -12477,21 +12477,21 @@
12477
12477
  },
12478
12478
  "packages/crouter-plugin": {
12479
12479
  "name": "@north-light/plugin",
12480
- "version": "0.3.572",
12480
+ "version": "0.3.574",
12481
12481
  "license": "UNLICENSED",
12482
12482
  "dependencies": {
12483
- "@north-light/api": "0.3.572",
12484
- "@north-light/identity": "0.3.572"
12483
+ "@north-light/api": "0.3.574",
12484
+ "@north-light/identity": "0.3.574"
12485
12485
  }
12486
12486
  },
12487
12487
  "packages/crouter-sdk": {
12488
12488
  "name": "@north-light/sdk",
12489
- "version": "0.3.572",
12489
+ "version": "0.3.574",
12490
12490
  "license": "UNLICENSED",
12491
12491
  "dependencies": {
12492
- "@north-light/api": "0.3.572",
12493
- "@north-light/identity": "0.3.572",
12494
- "@north-light/plugin": "0.3.572",
12492
+ "@north-light/api": "0.3.574",
12493
+ "@north-light/identity": "0.3.574",
12494
+ "@north-light/plugin": "0.3.574",
12495
12495
  "jose": "^6.2.1"
12496
12496
  },
12497
12497
  "bin": {