@north-light/crouter 0.3.355 → 0.3.357
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.
- package/dist/api/dto/delivery.d.ts +13 -3
- package/dist/api/dto/objects.d.ts +24 -22
- package/dist/api/dto/objects.js +1 -1
- package/dist/clients/attach/session/document-links.js +1 -1
- package/dist/clients/attach/viewer.js +829 -755
- package/dist/commands/canvas/list.js +3 -3
- package/dist/commands/canvas/read.d.ts +2 -4
- package/dist/commands/canvas/read.js +3 -5
- package/dist/commands/canvas/search.js +1 -1
- package/dist/commands/sys/context/admin/actions.js +1 -1
- package/dist/commands/sys/sync-deps.js +1 -1
- package/dist/commands/sys/sync-shared.js +1 -1
- package/dist/core/canvas/daemon-actions.d.ts +43 -0
- package/dist/core/canvas/daemon-actions.js +26 -0
- package/dist/core/canvas/deliveries.d.ts +1 -0
- package/dist/core/canvas/deliveries.js +1 -1
- package/dist/core/canvas/migrations.js +106 -46
- package/dist/core/feed/messages.d.ts +2 -20
- package/dist/core/feed/messages.js +6 -10
- package/dist/core/graph/events.d.ts +10 -5
- package/dist/core/graph/events.js +5 -5
- package/dist/core/graph/jobs.js +2 -2
- package/dist/core/graph/kinds/document.d.ts +19 -0
- package/dist/core/graph/kinds/document.js +5 -0
- package/dist/core/graph/kinds/dto.d.ts +5 -0
- package/dist/core/graph/kinds/dto.js +1 -0
- package/dist/core/graph/kinds/job.d.ts +2 -0
- package/dist/core/graph/kinds/job.js +2 -0
- package/dist/core/graph/kinds/kind.d.ts +39 -0
- package/dist/core/graph/kinds/kind.js +1 -0
- package/dist/core/graph/kinds/node.d.ts +2 -0
- package/dist/core/graph/kinds/node.js +4 -0
- package/dist/core/graph/kinds/owner.d.ts +2 -0
- package/dist/core/graph/kinds/owner.js +2 -0
- package/dist/core/graph/kinds/registry.d.ts +8 -0
- package/dist/core/graph/kinds/registry.js +1 -0
- package/dist/core/graph/kinds/render.d.ts +9 -0
- package/dist/core/graph/kinds/render.js +1 -0
- package/dist/core/graph/objects.d.ts +5 -4
- package/dist/core/graph/objects.js +5 -5
- package/dist/core/graph/types.d.ts +6 -5
- package/dist/core/providers/errors.d.ts +97 -0
- package/dist/core/providers/errors.js +1 -0
- package/dist/core/runtime/broker-protocol.d.ts +2 -7
- package/dist/daemon/api/app-listener.js +12 -12
- package/dist/daemon/api/handlers/human-requests.js +1 -1
- package/dist/daemon/api/handlers/objects.js +2 -5
- package/dist/daemon/api/handlers/providers.d.ts +69 -0
- package/dist/daemon/api/handlers/providers.js +1 -0
- package/dist/daemon/api/operations.js +1 -1
- package/dist/daemon/api/server.js +1 -1
- package/dist/daemon/cron/settle.js +1 -1
- package/dist/daemon/cron/sinks.d.ts +3 -3
- package/dist/daemon/cron/sinks.js +2 -2
- package/dist/daemon/crtrd.js +6 -6
- package/dist/daemon/human/finish.js +6 -6
- package/dist/daemon/human/settle.d.ts +2 -3
- package/dist/daemon/human/settle.js +1 -1
- package/dist/daemon/reconcilers/action-lane.d.ts +8 -0
- package/dist/daemon/reconcilers/action-lane.js +1 -0
- package/dist/daemon/reconcilers/delivery-lane.d.ts +1 -1
- package/dist/daemon/reconcilers/delivery-lane.js +1 -1
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +11 -11
package/dist/daemon/crtrd.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
var ve=Object.defineProperty;var a=(t,n)=>ve(t,"name",{value:n,configurable:!0});import{writeFileSync as ge,readFileSync as we,rmSync as ye,mkdirSync as V,existsSync as b,chmodSync as Se}from"node:fs";import{createServer as Q}from"node:http";import{dirname as _e}from"node:path";import{envCrtrdTcp as be}from"../shared/env.js";import{serveCanvasConversationStore as ke}from"../core/canvas/sessions.js";import{pollRunObservers as Ee}from"./runs/observer.js";import{randomBytes as Pe}from"node:crypto";import{apiSocketPath as Ie,crtrHome as Re}from"../core/canvas/paths.js";import{activeAppUsers as Te}from"../core/spaces/users.js";import{ensureAppSpace as xe,ensureUserFiles as De}from"../core/spaces/space.js";import{LAUNCHER_SOCKET as E}from"../launcher/spec.js";import{launcherRequest as R}from"../launcher/client.js";import{initializeEmptyLayout as Ce,layoutNeedsMigration as Ae,socketDir as Y}from"../core/layout.js";import{listNodesForSupervision as Le}from"../core/canvas/index.js";import{createApiServer as $e}from"./api/server.js";import{createAppListener as Me}from"./api/app-listener.js";import{installLocalTerminalGrant as Ne}from"../core/grants/local.js";import{createGrantSync as Ge,GRANT_SYNC_INTERVAL_S as Oe}from"../core/grants/sync.js";import{runRemovalCascades as Fe}from"../core/grants/remove.js";import{sweepSandboxes as je}from"../core/grants/on-sync.js";import{hasSyncedGrants as He}from"../core/grants/mirror.js";import{readConfig as Be}from"../core/config.js";import{reconcileUndeliveredTickets as ze}from"./human/sweep.js";import{resetHandedOffDeliveries as We}from"../core/canvas/deliveries.js";import{sweepReviews as qe}from"./review/sweep.js";import{pidfilePath as G}from"./pidfile.js";import{rendererWarning as Ue}from"../core/runtime/package-health.js";import{DEFAULT_INTERVAL_MS as Ke}from"./supervise-cadence.js";import{BrokerSupervisionReconciler as Je}from"./reconcilers/broker-supervision.js";import{ControllerDeathReconciler as Ve}from"./reconcilers/controller-death.js";import{NodeLifecycleReconciler as Qe}from"./reconcilers/node-lifecycle/tick.js";import{NodeDeadlineReconciler as Ye}from"./reconcilers/node-deadline.js";import{CronLaneReconciler as Xe}from"./reconcilers/cron-lane.js";import{DeliveryLaneReconciler as Ze}from"./reconcilers/delivery-lane.js";import{migrateLegacyExecutionIdentities as er}from"../core/canvas/executions.js";import{revokePriorEpochNodeTokens as rr}from"../core/canvas/node-tokens.js";import{PendingReviewSubmitReconciler as tr}from"./reconcilers/pending-review-submit.js";import{StorageMaintenanceReconciler as nr}from"./reconcilers/storage-maintenance.js";import{StorageDueWorkReconciler as or}from"./reconcilers/storage-due-work.js";import{BashDeadlineReconciler as ir}from"./reconcilers/bash-deadline.js";import{captureLivenessSnapshot as X,capturePidCommand as ar,captureTeardownSnapshot as Z,isPidAlive as sr,isAnyPidAlive as ee,killProcessTreePids as re}from"../core/canvas/pid.js";import{bindFleet as cr,boundFleet as lr}from"../core/runtime/fleet.js";import{bindDaemonControl as dr,clearDaemonControl as pr}from"./control.js";import{execDaemon as mr,spawnDaemon as fr}from"./manage.js";import{reconcileAndMigrateBoot as ur}from"../core/canvas/boot.js";import{resolveInstallId as hr}from"../core/canvas/install-id.js";import{setInstallId as vr}from"../core/runtime/nodes.js";import{claimDaemonOwnership as gr,releaseDaemonOwnership as te}from"../core/canvas/daemon-owner.js";import{migrate as wr,openDb as ne,withCanvasWrite as yr}from"../core/canvas/db.js";import{reconcilePackageDocuments as Sr}from"../core/graph/package-docs.js";import{startRepoSync as _r}from"../core/graph/repo-sync/index.js";import{prewarmRecentRecipes as br,reapStaleSpares as kr}from"../core/runtime/warm-pool.js";import{DaemonFleet as Er}from"./fleet.js";import{BOOT_MIGRATIONS as Pr}from"./boot-migrations.js";import{applyJoinedOwner as Ir}from"./joined-owner.js";import{emitEvent as h}from"../core/events/emit.js";import{operationIdContext as _}from"../core/events/operation-id.js";import{bindDaemonEventSource as Rr}from"../core/events/source.js";import{activateCanvasImport as Tr,MigrationBlockedError as xr,runForcedCanvasImport as Dr}from"../migrations/activation.js";import{convertLegacyProviderStore as Cr,convertLegacyScopedStore as Ar}from"../core/scoped-state/migrate.js";import{userScopeRoot as Lr}from"../core/scope.js";import{secretsDir as $r}from"../core/layout.js";function O(t,n){return t.includes(` --canvas-home ${n} `)}a(O,"brokerCommandDeclaresCanvasHome");function F(t){return/ --epoch (\S+) /.exec(t)?.[1]??null}a(F,"brokerCommandEpoch");const Mr=5e3,oe=150;async function Nr(t){const n=X();if(n===null)throw h({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness"}}),new Error("prior-epoch broker census could not capture the process table");const s=Re(),m=[];for(const[i,p]of n.processes){const g=p.command;if(p.zombie||!g.includes("broker-cli.js")||!O(g,s)||F(g)===t)continue;const y=g.trim().split(/\s+/).at(-1)??"";y===""||y.endsWith("broker-cli.js")||m.push({pid:i,nodeId:y})}let f=0;const o=[];for(const i of m){const p=ar(i.pid);if(p===null||!p.includes("broker-cli.js")||!O(p,s)||F(p)===t||p.trim().split(/\s+/).at(-1)!==i.nodeId)continue;const g=Z(i.pid,null);if(!g.reused){try{process.platform==="linux"&&b(E)?await R({operation:"stop",pid:i.pid}):process.kill(i.pid,"SIGTERM")}catch{continue}f++,o.push({pid:i.pid,snap:g})}}const w=Date.now()+Mr;for(;Date.now()<w&&o.some(i=>ee(i.snap.tree.length>0?i.snap.tree:[i.pid]));)await new Promise(i=>setTimeout(i,oe));let v=0;for(const i of o){const p=i.snap.tree.length>0?i.snap.tree:[i.pid];ee(p)&&(process.platform==="linux"&&b(E)?await R({operation:"stop",pid:i.pid}):re(p,"SIGKILL",i.snap.identities),v++)}v>0&&await new Promise(i=>setTimeout(i,oe));const c=X();if(c===null)throw h({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness",stage:"final"}}),new Error("prior-epoch broker census could not capture the final process table");const d=[];for(const[i,p]of c.processes){const g=p.command;p.zombie||!g.includes("broker-cli.js")||O(g,s)&&F(g)!==t&&d.push(i)}if(d.length>0)throw new Error(`prior-epoch broker census could not prove termination of pid(s): ${d.join(", ")}`);h({level:"info",event:"daemon.census.completed",fields:{prior_epoch_brokers:m.length,sigtermed:f,sigkilled:v}})}a(Nr,"reapPriorEpochBrokers");const Gr=5e3;async function Or(t){const n=Array.from(t.entries());if(n.length===0)return;const s=n.map(([,o])=>({pid:o.pid,snap:Z(o.pid,null),exited:o.handle.exited}));for(const o of s)if(!o.snap.reused)try{process.platform==="linux"&&b(E)?await R({operation:"stop",pid:o.pid}):process.kill(o.pid,"SIGTERM")}catch{}const m=new Promise(o=>{setTimeout(o,Gr).unref()});await Promise.allSettled(s.map(o=>Promise.race([o.exited.then(()=>{}),m])));const f=[];for(const o of s)sr(o.pid)&&(process.platform==="linux"&&b(E)?await R({operation:"stop",pid:o.pid}):re(o.snap.tree.length>0?o.snap.tree:[o.pid],"SIGKILL",o.snap.identities),f.push(o));await Promise.all(f.map(o=>o.exited)),h({level:"info",event:"daemon.fleet_teardown.completed",fields:{brokers:s.length,sigkilled:f.length}})}a(Or,"teardownFleet");function ie(){V(_e(G()),{recursive:!0}),ge(G(),String(process.pid),"utf8")}a(ie,"writePidfile");function ae(t){return typeof t=="object"&&t!==null&&t.code==="ENOENT"}a(ae,"isMissingPathError");function se(t){const n=G();let s;try{s=we(n,"utf8")}catch(m){if(ae(m))return;throw m}if(s.trim()!==String(t))throw new Error(`daemon readiness mirror does not name this invocation (expected pid ${t})`);try{ye(n)}catch(m){if(ae(m))return;throw m}}a(se,"removeOwnedPidfileMirror");const Fr={acceptsDetachedWork:a(()=>!0,"acceptsDetachedWork"),registerDetached:a(t=>{t.catch(()=>{})},"registerDetached")},j=new Je,jr=new Ve,Hr=new Qe,Br=new Ye,zr=new Xe,Wr=new Ze,qr=new tr,Ur=new nr,Kr=new or,Jr=new ir;async function Vr(t=Date.now(),n=Fr){const s=lr(),m=await j.runFleetPreamble(s);let f,o;try{const v=Le();f=v.filter(c=>c.status==="active"||c.status==="idle"),o=v.filter(c=>c.status==="done"||c.status==="canceled"||c.status==="dead")}catch(v){h({level:"error",event:"canvas.node_list.failed",error:v});return}await j.run(t,{rows:f,fleet:s,lifecycle:n}),jr.run(t,{rows:f});const w=await Hr.run(t,{rows:[...f,...o],fleet:s});Br.run(t),zr.run(t,{lifecycle:n}),Wr.run(t,{lifecycle:n}),qr.run(t,{lifecycle:n}),Ur.run(t,{lifecycle:n,fleet:s}),Kr.run(t,{lifecycle:n}),Ee(),await Jr.run(t,{rows:f}),j.warnIfSaturated({fleet:s,lifecycle:n,thresholds:m,frozen:w})}a(Vr,"superviseTick");async function Qr(t){V(Y(),{recursive:!0,mode:493}),process.platform==="linux"&&Se(Y(),493);const n=Ie();if(b(n))throw new Error(`layout refusal cannot bind occupied socket: ${n}`);const s=Q((c,d)=>{if(c.method==="GET"&&c.url==="/healthz"){d.writeHead(200,{"content-type":"application/json; charset=utf-8"}),d.end(JSON.stringify({ok:!1,daemon_up:!0,store_accessible:!1,brokers_reconciled:!1,startup_phase:"blocked",startup_blocked:"layout_migration_required"}));return}d.writeHead(503,{"content-type":"application/json; charset=utf-8"}),d.end(JSON.stringify({error:{code:"layout_migration_required",message:"run crtr sys migrate while the runtime is offline",type:"server_error",origin:"runtime",retryable:!1}}))});await new Promise((c,d)=>{s.once("error",d),s.listen(n,()=>{s.off("error",d),c()})});let m;const f=t.tcp??be();if(f){const c=/^(.*):(\d+)$/.exec(f);if(!c||Number(c[2])>65535)throw new Error(`invalid refusal TCP address: ${f}`);const d=Q(s.listeners("request")[0]);await new Promise((i,p)=>{d.once("error",p),d.listen(Number(c[2]),c[1],()=>{d.off("error",p),i()})}),m=d}ie();let o;const w=a(()=>(o??=(async()=>{s.closeAllConnections(),m?.closeAllConnections(),await Promise.all([s,m].filter(c=>c!==void 0).map(c=>new Promise((d,i)=>c.close(p=>p?i(p):d())))),se(process.pid),process.off("SIGINT",v),process.off("SIGTERM",v)})(),o),"cleanup"),v=a(()=>{w().then(()=>process.exit(0),c=>{process.stderr.write(`[crtrd] layout refusal cleanup failed: ${String(c)}
|
|
2
|
-
`),process.exit(1)})},"onSignal");return process.on("SIGINT",v),process.on("SIGTERM",v),w}a(
|
|
1
|
+
var ve=Object.defineProperty;var a=(t,n)=>ve(t,"name",{value:n,configurable:!0});import{writeFileSync as ge,readFileSync as we,rmSync as ye,mkdirSync as V,existsSync as b,chmodSync as Se}from"node:fs";import{createServer as Q}from"node:http";import{dirname as _e}from"node:path";import{envCrtrdTcp as be}from"../shared/env.js";import{serveCanvasConversationStore as ke}from"../core/canvas/sessions.js";import{pollRunObservers as Ee}from"./runs/observer.js";import{randomBytes as Pe}from"node:crypto";import{apiSocketPath as Ie,crtrHome as Re}from"../core/canvas/paths.js";import{activeAppUsers as Te}from"../core/spaces/users.js";import{ensureAppSpace as xe,ensureUserFiles as De}from"../core/spaces/space.js";import{LAUNCHER_SOCKET as E}from"../launcher/spec.js";import{launcherRequest as R}from"../launcher/client.js";import{initializeEmptyLayout as Ce,layoutNeedsMigration as Ae,socketDir as Y}from"../core/layout.js";import{listNodesForSupervision as Le}from"../core/canvas/index.js";import{createApiServer as $e}from"./api/server.js";import{createAppListener as Me}from"./api/app-listener.js";import{installLocalTerminalGrant as Ne}from"../core/grants/local.js";import{createGrantSync as Ge,GRANT_SYNC_INTERVAL_S as Oe}from"../core/grants/sync.js";import{runRemovalCascades as Fe}from"../core/grants/remove.js";import{sweepSandboxes as He}from"../core/grants/on-sync.js";import{hasSyncedGrants as je}from"../core/grants/mirror.js";import{readConfig as Be}from"../core/config.js";import{reconcileUndeliveredTickets as ze}from"./human/sweep.js";import{resetHandedOffDeliveries as We}from"../core/canvas/deliveries.js";import{resetHandedOffDaemonActions as qe}from"../core/canvas/daemon-actions.js";import{sweepReviews as Ue}from"./review/sweep.js";import{pidfilePath as G}from"./pidfile.js";import{rendererWarning as Ke}from"../core/runtime/package-health.js";import{DEFAULT_INTERVAL_MS as Je}from"./supervise-cadence.js";import{BrokerSupervisionReconciler as Ve}from"./reconcilers/broker-supervision.js";import{ControllerDeathReconciler as Qe}from"./reconcilers/controller-death.js";import{NodeLifecycleReconciler as Ye}from"./reconcilers/node-lifecycle/tick.js";import{NodeDeadlineReconciler as Xe}from"./reconcilers/node-deadline.js";import{CronLaneReconciler as Ze}from"./reconcilers/cron-lane.js";import{DeliveryLaneReconciler as er}from"./reconcilers/delivery-lane.js";import{ActionLaneReconciler as rr}from"./reconcilers/action-lane.js";import{migrateLegacyExecutionIdentities as tr}from"../core/canvas/executions.js";import{revokePriorEpochNodeTokens as nr}from"../core/canvas/node-tokens.js";import{PendingReviewSubmitReconciler as or}from"./reconcilers/pending-review-submit.js";import{StorageMaintenanceReconciler as ir}from"./reconcilers/storage-maintenance.js";import{StorageDueWorkReconciler as ar}from"./reconcilers/storage-due-work.js";import{BashDeadlineReconciler as sr}from"./reconcilers/bash-deadline.js";import{captureLivenessSnapshot as X,capturePidCommand as cr,captureTeardownSnapshot as Z,isPidAlive as lr,isAnyPidAlive as ee,killProcessTreePids as re}from"../core/canvas/pid.js";import{bindFleet as dr,boundFleet as pr}from"../core/runtime/fleet.js";import{bindDaemonControl as mr,clearDaemonControl as fr}from"./control.js";import{execDaemon as ur,spawnDaemon as hr}from"./manage.js";import{reconcileAndMigrateBoot as vr}from"../core/canvas/boot.js";import{resolveInstallId as gr}from"../core/canvas/install-id.js";import{setInstallId as wr}from"../core/runtime/nodes.js";import{claimDaemonOwnership as yr,releaseDaemonOwnership as te}from"../core/canvas/daemon-owner.js";import{migrate as Sr,openDb as ne,withCanvasWrite as _r}from"../core/canvas/db.js";import{reconcilePackageDocuments as br}from"../core/graph/package-docs.js";import{startRepoSync as kr}from"../core/graph/repo-sync/index.js";import{prewarmRecentRecipes as Er,reapStaleSpares as Pr}from"../core/runtime/warm-pool.js";import{DaemonFleet as Ir}from"./fleet.js";import{BOOT_MIGRATIONS as Rr}from"./boot-migrations.js";import{applyJoinedOwner as Tr}from"./joined-owner.js";import{emitEvent as h}from"../core/events/emit.js";import{operationIdContext as _}from"../core/events/operation-id.js";import{bindDaemonEventSource as xr}from"../core/events/source.js";import{activateCanvasImport as Dr,MigrationBlockedError as Cr,runForcedCanvasImport as Ar}from"../migrations/activation.js";import{convertLegacyProviderStore as Lr,convertLegacyScopedStore as $r}from"../core/scoped-state/migrate.js";import{userScopeRoot as Mr}from"../core/scope.js";import{secretsDir as Nr}from"../core/layout.js";function O(t,n){return t.includes(` --canvas-home ${n} `)}a(O,"brokerCommandDeclaresCanvasHome");function F(t){return/ --epoch (\S+) /.exec(t)?.[1]??null}a(F,"brokerCommandEpoch");const Gr=5e3,oe=150;async function Or(t){const n=X();if(n===null)throw h({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness"}}),new Error("prior-epoch broker census could not capture the process table");const s=Re(),m=[];for(const[i,p]of n.processes){const g=p.command;if(p.zombie||!g.includes("broker-cli.js")||!O(g,s)||F(g)===t)continue;const y=g.trim().split(/\s+/).at(-1)??"";y===""||y.endsWith("broker-cli.js")||m.push({pid:i,nodeId:y})}let f=0;const o=[];for(const i of m){const p=cr(i.pid);if(p===null||!p.includes("broker-cli.js")||!O(p,s)||F(p)===t||p.trim().split(/\s+/).at(-1)!==i.nodeId)continue;const g=Z(i.pid,null);if(!g.reused){try{process.platform==="linux"&&b(E)?await R({operation:"stop",pid:i.pid}):process.kill(i.pid,"SIGTERM")}catch{continue}f++,o.push({pid:i.pid,snap:g})}}const w=Date.now()+Gr;for(;Date.now()<w&&o.some(i=>ee(i.snap.tree.length>0?i.snap.tree:[i.pid]));)await new Promise(i=>setTimeout(i,oe));let v=0;for(const i of o){const p=i.snap.tree.length>0?i.snap.tree:[i.pid];ee(p)&&(process.platform==="linux"&&b(E)?await R({operation:"stop",pid:i.pid}):re(p,"SIGKILL",i.snap.identities),v++)}v>0&&await new Promise(i=>setTimeout(i,oe));const c=X();if(c===null)throw h({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness",stage:"final"}}),new Error("prior-epoch broker census could not capture the final process table");const d=[];for(const[i,p]of c.processes){const g=p.command;p.zombie||!g.includes("broker-cli.js")||O(g,s)&&F(g)!==t&&d.push(i)}if(d.length>0)throw new Error(`prior-epoch broker census could not prove termination of pid(s): ${d.join(", ")}`);h({level:"info",event:"daemon.census.completed",fields:{prior_epoch_brokers:m.length,sigtermed:f,sigkilled:v}})}a(Or,"reapPriorEpochBrokers");const Fr=5e3;async function Hr(t){const n=Array.from(t.entries());if(n.length===0)return;const s=n.map(([,o])=>({pid:o.pid,snap:Z(o.pid,null),exited:o.handle.exited}));for(const o of s)if(!o.snap.reused)try{process.platform==="linux"&&b(E)?await R({operation:"stop",pid:o.pid}):process.kill(o.pid,"SIGTERM")}catch{}const m=new Promise(o=>{setTimeout(o,Fr).unref()});await Promise.allSettled(s.map(o=>Promise.race([o.exited.then(()=>{}),m])));const f=[];for(const o of s)lr(o.pid)&&(process.platform==="linux"&&b(E)?await R({operation:"stop",pid:o.pid}):re(o.snap.tree.length>0?o.snap.tree:[o.pid],"SIGKILL",o.snap.identities),f.push(o));await Promise.all(f.map(o=>o.exited)),h({level:"info",event:"daemon.fleet_teardown.completed",fields:{brokers:s.length,sigkilled:f.length}})}a(Hr,"teardownFleet");function ie(){V(_e(G()),{recursive:!0}),ge(G(),String(process.pid),"utf8")}a(ie,"writePidfile");function ae(t){return typeof t=="object"&&t!==null&&t.code==="ENOENT"}a(ae,"isMissingPathError");function se(t){const n=G();let s;try{s=we(n,"utf8")}catch(m){if(ae(m))return;throw m}if(s.trim()!==String(t))throw new Error(`daemon readiness mirror does not name this invocation (expected pid ${t})`);try{ye(n)}catch(m){if(ae(m))return;throw m}}a(se,"removeOwnedPidfileMirror");const jr={acceptsDetachedWork:a(()=>!0,"acceptsDetachedWork"),registerDetached:a(t=>{t.catch(()=>{})},"registerDetached")},H=new Ve,Br=new Qe,zr=new Ye,Wr=new Xe,qr=new Ze,Ur=new er,Kr=new rr,Jr=new or,Vr=new ir,Qr=new ar,Yr=new sr;async function Xr(t=Date.now(),n=jr){const s=pr(),m=await H.runFleetPreamble(s);let f,o;try{const v=Le();f=v.filter(c=>c.status==="active"||c.status==="idle"),o=v.filter(c=>c.status==="done"||c.status==="canceled"||c.status==="dead")}catch(v){h({level:"error",event:"canvas.node_list.failed",error:v});return}await H.run(t,{rows:f,fleet:s,lifecycle:n}),Br.run(t,{rows:f});const w=await zr.run(t,{rows:[...f,...o],fleet:s});Wr.run(t),qr.run(t,{lifecycle:n}),Ur.run(t,{lifecycle:n}),Kr.run(t,{lifecycle:n}),Jr.run(t,{lifecycle:n}),Vr.run(t,{lifecycle:n,fleet:s}),Qr.run(t,{lifecycle:n}),Ee(),await Yr.run(t,{rows:f}),H.warnIfSaturated({fleet:s,lifecycle:n,thresholds:m,frozen:w})}a(Xr,"superviseTick");async function Zr(t){V(Y(),{recursive:!0,mode:493}),process.platform==="linux"&&Se(Y(),493);const n=Ie();if(b(n))throw new Error(`layout refusal cannot bind occupied socket: ${n}`);const s=Q((c,d)=>{if(c.method==="GET"&&c.url==="/healthz"){d.writeHead(200,{"content-type":"application/json; charset=utf-8"}),d.end(JSON.stringify({ok:!1,daemon_up:!0,store_accessible:!1,brokers_reconciled:!1,startup_phase:"blocked",startup_blocked:"layout_migration_required"}));return}d.writeHead(503,{"content-type":"application/json; charset=utf-8"}),d.end(JSON.stringify({error:{code:"layout_migration_required",message:"run crtr sys migrate while the runtime is offline",type:"server_error",origin:"runtime",retryable:!1}}))});await new Promise((c,d)=>{s.once("error",d),s.listen(n,()=>{s.off("error",d),c()})});let m;const f=t.tcp??be();if(f){const c=/^(.*):(\d+)$/.exec(f);if(!c||Number(c[2])>65535)throw new Error(`invalid refusal TCP address: ${f}`);const d=Q(s.listeners("request")[0]);await new Promise((i,p)=>{d.once("error",p),d.listen(Number(c[2]),c[1],()=>{d.off("error",p),i()})}),m=d}ie();let o;const w=a(()=>(o??=(async()=>{s.closeAllConnections(),m?.closeAllConnections(),await Promise.all([s,m].filter(c=>c!==void 0).map(c=>new Promise((d,i)=>c.close(p=>p?i(p):d())))),se(process.pid),process.off("SIGINT",v),process.off("SIGTERM",v)})(),o),"cleanup"),v=a(()=>{w().then(()=>process.exit(0),c=>{process.stderr.write(`[crtrd] layout refusal cleanup failed: ${String(c)}
|
|
2
|
+
`),process.exit(1)})},"onSignal");return process.on("SIGINT",v),process.on("SIGTERM",v),w}a(Zr,"serveLayoutRefusal");async function et(t={}){if(Ae())return Zr(t);Ce();const n=yr(Pe(16).toString("hex"));if(!n.claimed){if(n.reason==="incumbent_alive")process.stderr.write(`[crtrd] already running (pid ${n.incumbentPid??"?"})
|
|
3
3
|
`);else{const e=[n.incumbentPid!==void 0?`pid ${n.incumbentPid}`:void 0,n.verdict!==void 0?`verdict ${n.verdict}`:void 0].filter(l=>l!==void 0),r=e.length>0?` (${e.join(", ")})`:"";process.stderr.write(`[crtrd] claim lost: ${n.reason}${r}
|
|
4
|
-
`)}return async()=>{}}const s=n.claim;let m=null;try{await
|
|
4
|
+
`)}return async()=>{}}const s=n.claim;let m=null;try{await Or(s.token),$r({kind:"user",root:Mr()}),await Lr(Nr()),Sr(ne());const e=_r(r=>br(r));for(const r of e.conflicts)process.stderr.write(`[crtrd] plugin documents not reconciled: ${r.message}
|
|
5
5
|
`);for(const r of e.invalid)process.stderr.write(`[crtrd] package file is not a document: ${r.path}: ${r.error}
|
|
6
|
-
`);m=
|
|
6
|
+
`);m=Tr(),process.platform==="linux"&&b(E)&&await R({operation:"users.sync",users:Te()}),nr(s.token)}catch(e){try{const{released:r}=te(s);if(!r)throw new Error("daemon ownership claim was not released")}catch(r){throw new AggregateError([e,r],"daemon startup failed and cleanup also failed")}throw e}let f=!0,o,w=Promise.resolve(),v=!1,c,d;const i=new Set;let p=!1,g=!1,y,C,j=!1,A,T,x,L,u={phase:"initializing",message:"daemon startup is running the canvas import and normal services are unavailable",blockerPaths:[]},P="initial startup activation",ce=null;function le(){return u.phase==="ready"?null:{phase:u.phase,message:u.message,blockerPaths:u.blockerPaths}}a(le,"startupBlock");function I(e){i.add(e),e.finally(()=>{i.delete(e)}).catch(()=>{})}a(I,"registerDetached");const B={acceptsDetachedWork:a(()=>f,"acceptsDetachedWork"),registerDetached:I};kr(B,ne);async function de(){try{f=!1,c!==void 0&&(clearInterval(c),c=void 0),x!==void 0&&(clearInterval(x),x=void 0);let e;do e=w,await e;while(e!==w);for(;i.size>0;)await Promise.allSettled([...i]);if(d!==void 0&&(await Hr(d),d.dispose()),C!==void 0&&!j&&(j=!0,await C.close()),T!==void 0){const r=T;T=void 0,await r.close()}if(A!==void 0){const r=A;A=void 0,await r.close()}if(p||(se(process.pid),p=!0),p&&!g){const{released:r}=te(s);if(!r)throw new Error("daemon ownership claim was not released");g=!0}}finally{fr(),process.off("SIGINT",q),process.off("SIGTERM",U),process.off("exit",K)}}a(de,"cleanupAttempt");const $=1e3;let z=!1;function pe(){return z?{graceMs:$}:(z=!0,_.fresh(()=>{h({level:"info",event:"daemon.handover.armed",fields:{pid:process.pid,grace_ms:$}})}),setTimeout(()=>{me()},$),{graceMs:$})}a(pe,"requestHandover");async function me(){try{await k()}catch(e){const r=e instanceof Error?e.stack??e.message:String(e);process.stderr.write(`[crtrd] handover cleanup failed:
|
|
7
7
|
${r}
|
|
8
|
-
`),process.exit(1)}try{process.platform==="linux"&&b(E)&&(await R({operation:"daemon.handover"}),process.exit(0)),process.pid===1&&await
|
|
8
|
+
`),process.exit(1)}try{process.platform==="linux"&&b(E)&&(await R({operation:"daemon.handover"}),process.exit(0)),process.pid===1&&await ur();const e=await hr();_.fresh(()=>{h({level:"info",event:"daemon.handover.completed",fields:{predecessor_pid:process.pid,successor_pid:e.pid??e.existing_pid??null,spawned:e.started}})})}catch(e){_.fresh(()=>{h({level:"error",event:"daemon.handover.successor_failed",error:e})});const r=e instanceof Error?e.message:String(e);process.stderr.write(`[crtrd] handover successor failed to start: ${r}
|
|
9
9
|
`),process.exit(1)}process.exit(0)}a(me,"performHandover");function k(){if(y!==void 0)return y;const e=de();return y=e,e.then(()=>{y===e&&(y=void 0)},()=>{y===e&&(y=void 0)}),e}a(k,"requestCleanup");async function W(e){try{await k(),process.exit(0)}catch(r){process.exitCode=1;const l=r instanceof Error?r.stack??`${r.name}: ${r.message}`:String(r);process.stderr.write(`[crtrd] ${e} cleanup failed:
|
|
10
10
|
${l}
|
|
11
|
-
`),process.exit(1)}}a(W,"handleSignal");function q(){W("SIGINT")}a(q,"onSigint");function U(){W("SIGTERM")}a(U,"onSigterm");function K(){k().catch(()=>{})}a(K,"onExit");function M(e){f&&(w=w.then(e).then(()=>{},r=>{_.fresh(()=>{h({level:"error",event:"daemon.lane_job.failed",error:r})})}))}a(M,"enqueue");function J(){!f||v||(v=!0,M(async()=>{if(v=!1,!!f)try{await
|
|
11
|
+
`),process.exit(1)}}a(W,"handleSignal");function q(){W("SIGINT")}a(q,"onSigint");function U(){W("SIGTERM")}a(U,"onSigterm");function K(){k().catch(()=>{})}a(K,"onExit");function M(e){f&&(w=w.then(e).then(()=>{},r=>{_.fresh(()=>{h({level:"error",event:"daemon.lane_job.failed",error:r})})}))}a(M,"enqueue");function J(){!f||v||(v=!0,M(async()=>{if(v=!1,!!f)try{await Xr(Date.now(),B)}catch(e){_.fresh(()=>{h({level:"error",event:"daemon.tick.failed",error:e})})}}))}a(J,"enqueueTick");let D=null;async function fe(){if(D!==null)throw{status:500,code:"admission_failed",message:`daemon admission previously failed: ${D instanceof Error?D.message:String(D)}`};if(u.phase==="ready")return{admitted:!1,already_admitted:!0,startup_phase:"ready"};if(u.phase!=="prepared"&&u.phase!=="recovering")throw{status:409,code:"not_prepared",message:u.message};const e=u.phase==="prepared";try{return await N(),u={phase:"ready",message:"",blockerPaths:[]},e?{admitted:!0,already_admitted:!1,startup_phase:"ready"}:{admitted:!1,already_admitted:!0,startup_phase:"ready"}}catch(r){throw D=r,{status:500,code:"admission_failed",message:`daemon admission failed: ${r instanceof Error?r.message:String(r)}`}}}a(fe,"admitStartup");async function ue(e){if(P!==null)throw{status:409,code:"migration_in_progress",message:`the canvas import is already running (${P})`};P="repair";try{const r=await Ar({dryRun:e.dryRun});if(e.dryRun||r.pending||u.phase!=="blocked")return{result:r,resumed:!1};if(t.prepare)return u={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]},{result:r,resumed:!1};try{return await N(),u={phase:"ready",message:"",blockerPaths:[]},{result:r,resumed:!0}}catch(l){const S=l instanceof Error?l.message:String(l);return setTimeout(()=>{k().catch(()=>{})},1e3),{result:r,resumed:!1,resumeError:S}}}finally{P=null}}a(ue,"repairMigrations");async function he(){o=t.intervalMs??Je;const e=s.token;d=new Ir({epoch:e,enqueue:M}),dr(d),u={phase:"recovering",message:"daemon startup recovery is running and normal services are unavailable",blockerPaths:[]},_.fresh(()=>{h({level:"info",event:"daemon.started",fields:{pid:process.pid,interval_ms:o}})});const r=gr();if(wr(r),_.fresh(()=>{h({level:"info",event:"daemon.install_id.resolved",fields:{install_id:r}})}),_.fresh(()=>{let l;try{l=Ke()}catch{return}l!==null&&h({level:"warn",event:"daemon.startup.warning",fields:{stage:"termrender",warning:l.slice(0,2048)}})}),await _.fresh(async()=>{await Ue(),await ze(),We(Date.now()),qe(Date.now())}),_.fresh(()=>{const{reconcile:l,migrated:S}=vr(tr);l.changed&&h({level:"info",event:"daemon.boot_change.reconciled",fields:{cleared_count:l.cleared.length,same_boot_proven:l.sameBootProven}}),S.length>0&&h({level:"info",event:"daemon.pid_identity.migrated",fields:{migrated_count:S.length}})}),_.fresh(()=>{for(const l of Rr){const S=l.apply();S.changed&&h({level:"info",event:"daemon.boot_migration.applied",fields:{migration:l.id,...S.summary}})}}),L){const l=a(()=>{I(L().catch(()=>{}))},"refresh");I(Fe().catch(()=>{})),I(He().then(({completion:S})=>S).catch(S=>{h({level:"error",event:"daemon.grants.sweep_failed",error:S})})),l(),x=setInterval(l,Oe*1e3),x.unref()}M(()=>{Pr(),Er()}),c=setInterval(J,o),J()}a(he,"completeStartup");function N(){return ce??=he().catch(e=>{throw u={phase:"initializing",message:"daemon startup recovery failed and normal services are unavailable",blockerPaths:[]},e})}a(N,"resumeStartup");try{process.on("SIGINT",q),process.on("SIGTERM",U),process.on("exit",K),xr(),m!==null&&h({level:"info",event:"daemon.joined_owner.applied",fields:{owner:m.owner,rows:m.rows}}),A=await ke();const e=s.token;mr({epoch:e,requestHandover:pe,registerDetached:I,startupBlock:le,admitStartup:fe,repairMigrations:ue}),ie(),C=$e({tcp:t.tcp}),await C.ready;const r=Be("user").runtime;r?.issuer?L=Ge(r.issuer,I):Ne(),r!==void 0&&(T=Me(r,()=>je(r.issuer.replace(/\/$/,"")),L),await T.ready);try{await Dr()}catch(l){if(P=null,l instanceof Cr)return u={phase:"blocked",message:l.message,blockerPaths:l.blockerPaths},k;throw l}process.platform==="linux"&&b(E)&&(De(),await xe("app:terminal"));try{t.prepare?u={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]}:(await N(),u={phase:"ready",message:"",blockerPaths:[]})}finally{P=null}return k}catch(e){try{await k()}catch(r){throw new AggregateError([e,r],"daemon startup failed and cleanup also failed")}throw e}}a(et,"runDaemon");var fn=et;export{O as brokerCommandDeclaresCanvasHome,F as brokerCommandEpoch,fn as default,et as runDaemon,Xr as superviseTick};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
var _=Object.defineProperty;var
|
|
2
|
-
`)[0]??"";return
|
|
1
|
+
var _=Object.defineProperty;var r=(t,e)=>_(t,"name",{value:e,configurable:!0});import{getRequest as y,getRequestByInboxTicket as b,presentationDir as q}from"../../core/human/requests.js";import{buildPageSummary as v}from"../../core/human/summary.js";import{validateFinalPageResponses as $}from"../../core/human/tickets.js";import{composeHumanCompletion as j}from"../../core/human/completion.js";import{describePageAnswer as k}from"../../core/human/answer.js";import{renderAnswerText as S}from"../../core/human/answer-text.js";import{readPageFeedback as T}from"../../core/human/feedback.js";import{pageDocumentSha256 as A}from"../../core/human/feedback-companion.js";import{pagePath as N}from"../../core/human/convention.js";import{retireCompanion as f}from"../companion-retire.js";import{settleHumanRequest as h}from"./settle.js";function d(t){const e=y(t)??b(t);if(e===null||e.kind!=="page")throw new Error(`unknown page request: ${t}`);return e}r(d,"requestForTicket");function c(t){try{const e=JSON.parse(t.specification_json);if(typeof e!="object"||e===null)throw new Error("not an object");return e}catch(e){throw new Error(`corrupt page specification: ${t.request_id}`,{cause:e})}}r(c,"manifest");function u(t,e){if(t.action_json!==null)try{const n=JSON.parse(t.action_json);if(n.schema!=="crtr.human-action-binding/v1"||!Array.isArray(n.argv)||typeof n.cwd!="string")throw new Error("invalid binding");return{adapter:{adapter:"subprocess",argv:n.argv,cwd:n.cwd,node_id:t.requester_node_id,...n.app?{app:n.app}:{}},bodyJson:j({requestId:t.request_id,result:e,binding:n,source:c(t).source??{}})}}catch(n){throw new Error(`corrupt frozen completion action: ${t.request_id}`,{cause:n})}}r(u,"completionAction");function O(t,e=80){const n=t.split(`
|
|
2
|
+
`)[0]??"";return n.length>e?`${n.slice(0,e-1)}\u2026`:n}r(O,"firstLine");function x(t){try{return c(t).title}catch{return}}r(x,"pageTitle");function w(t){let e;try{const n=T(t.request_dir);if(n.companionNodeId===void 0)return"";e=[],n.firstCommentedSha256!==void 0&&A(t.request_dir)!==n.firstCommentedSha256&&e.push(`The page changed during feedback: the person commented on it and its companion conversation (node ${n.companionNodeId}) revised it in place. Reread the final page at ${N(q(t),c(t).dialect)} before interpreting this outcome.`);const o=n.comments.filter(i=>i.status==="open");if(o.length>0){const i=o.map(s=>[...s.quote.split(`
|
|
3
3
|
`).map(a=>`> ${a}`),s.note].join(`
|
|
4
|
-
`));
|
|
4
|
+
`));e.push([`Feedback left unresolved at settlement \u2014 the companion conversation (node ${n.companionNodeId}) had not dealt with these items:`,...i].join(`
|
|
5
5
|
|
|
6
|
-
`))}}catch{return""}return
|
|
6
|
+
`))}}catch{return""}return e.length===0?"":`
|
|
7
7
|
|
|
8
|
-
${
|
|
8
|
+
${e.join(`
|
|
9
9
|
|
|
10
|
-
`)}`}
|
|
10
|
+
`)}`}r(w,"feedbackAddendum");function E(t,e){const n=k(c(t),e.responses,{completedAt:e.completedAt});return S(n)+w(t)}r(E,"answerBody");function J(t,e,n){const o=x(t),i=o===void 0?`the human interaction ${t.request_id}`:`\u201C${o}\u201D`,s=n!==void 0&&n!==""?n:"no reason was given";return(e?`The user dismissed ${i} without answering \u2014 a deliberate \u201Cno, I'm not answering this.\u201D Treat it as a rejection: no response will arrive, no partial answer exists, and the same ask must not be raised again.`:`${o===void 0?`The human interaction ${t.request_id}`:`The page \u201C${o}\u201D`} was canceled \u2014 ${s}. No response will arrive, and any partial answers the user had entered were discarded unsent.`)+w(t)}r(J,"cancelBody");function g(t,e,n,o){if(t.requester_node_id!==null)return{label:O(n),disposition:e,body_json:{body:n,result:o}}}r(g,"notification");function l(t){return t.companion_node_id===null?void 0:{retire:r(async(e,n)=>{await f(e,n)},"retire")}}r(l,"retire");async function Q(t,e,n={}){return(await P(t,e,n)).result}r(Q,"resolvePageTicket");async function P(t,e,n={}){const o=d(t),i=c(o),s=$(i,e),a={schema:"crtr.page-response/v1",kind:"page",responses:s,summary:v(i,s),completedAt:n.completedAt??new Date().toISOString(),...n.actor===void 0?{}:{actor:n.actor}},m=await h({request_id:o.request_id,outcome:"answered",result_json:JSON.stringify(a),notification:r(p=>g(p,"human-answer",E(p,a),a),"notification"),...u(o,a)===void 0?{}:{completion_action:u(o,a)},...l(o)===void 0?{}:{post_commit:l(o)}});if(m.outcome==="already_settled"){if(m.request.result_json===null)throw new Error(`settled page request lacks a result: ${o.request_id}`);return{outcome:"already_settled",result:JSON.parse(m.request.result_json)}}return{outcome:"settled",result:a}}r(P,"answerPageTicket");async function U(t,e){const n=d(t),i={schema:"humanloop.cancel/v1",kind:"canceled",canceledAt:new Date().toISOString(),...e.reason===void 0?{}:{reason:e.reason},...e.actor===void 0?{}:{actor:e.actor},...e.disposition===void 0?{}:{disposition:e.disposition}},s=await h({request_id:n.request_id,outcome:e.disposition==="dismissed"?"dismissed":"canceled",result_json:JSON.stringify(i),notification:r(a=>g(a,"human-canceled",J(a,e.disposition==="dismissed",e.reason),i),"notification"),...u(n,i)===void 0?{}:{completion_action:u(n,i)},...l(n)===void 0?{}:{post_commit:l(n)}});if(s.outcome==="already_settled"){if(s.request.result_json===null)throw new Error(`settled page request lacks a result: ${n.request_id}`);return{outcome:"already_settled",result:JSON.parse(s.request.result_json)}}return{outcome:"settled",result:i}}r(U,"cancelHumanTicket");async function V(t){return d(t).state==="settled"}r(V,"deliverTerminalResult");async function W(t,e){const n=d(t);n.companion_node_id!==null&&await f(n.companion_node_id,e)}r(W,"settleFeedbackCompanion");export{P as answerPageTicket,U as cancelHumanTicket,V as deliverTerminalResult,Q as resolvePageTicket,W as settleFeedbackCompanion};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type DaemonActionAdapter } from '../../core/canvas/daemon-actions.js';
|
|
2
2
|
import { type HumanRequestOutcome, type HumanRequestRecord } from '../../core/human/requests.js';
|
|
3
3
|
interface SettlementNotification {
|
|
4
4
|
label: string;
|
|
@@ -13,8 +13,7 @@ export interface SettleHumanRequestInput {
|
|
|
13
13
|
settled_at?: string;
|
|
14
14
|
notification?: SettlementNotification | ((request: HumanRequestRecord) => SettlementNotification | undefined);
|
|
15
15
|
completion_action?: {
|
|
16
|
-
|
|
17
|
-
adapter: ExternalActionAdapter;
|
|
16
|
+
adapter: DaemonActionAdapter;
|
|
18
17
|
bodyJson: unknown;
|
|
19
18
|
};
|
|
20
19
|
post_commit?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var u=Object.defineProperty;var d=(e,o)=>u(e,"name",{value:o,configurable:!0});import{withCanvasWrite as m}from"../../core/canvas/db.js";import{enqueueDaemonAction as f}from"../../core/canvas/daemon-actions.js";import{cancelDelivery as p,enqueueNodeMail as w}from"../../core/feed/messages.js";import{getRequest as l,markCompanionRetired as y,markProjected as q,markProjectionError as h,setSettlementDeliveryMarksLocked as j,settleRequestLocked as v}from"../../core/human/requests.js";import{appendQuestionAnswered as k}from"../../core/runs/questions.js";async function R(e){const o=m(i=>{const _=e.settled_at??new Date().toISOString(),t=v(i,{request_id:e.request_id,outcome:e.outcome,result_json:e.result_json,settled_at:_});if(t===null){const c=l(e.request_id);if(c===null)throw new Error(`human request disappeared while settling: ${e.request_id}`);return{outcome:"already_settled",request:c}}const n=typeof e.notification=="function"?e.notification(t):e.notification;if(t.requester_node_id!==null&&n===void 0)throw new Error(`request ${t.request_id} needs a requester notification`);if(t.action_json!==null&&t.kind==="page"&&e.completion_action===void 0)throw new Error(`request ${t.request_id} needs its frozen completion action`);if(t.kind==="review"&&t.projected_at===null&&e.post_commit?.project===void 0)throw new Error(`review ${t.request_id} needs a projection effect`);if(t.companion_node_id!==null&&t.companion_retired_at===null&&e.post_commit?.retire===void 0)throw new Error(`request ${t.request_id} needs a companion retirement effect`);let a=null,s=null;if(t.requester_node_id!==null){if(n===void 0)throw new Error(`request ${t.request_id} needs a requester notification`);a=w(t.requester_node_id,{kind:"completed",label:n.label,senderName:"crtrd",...n.body_ref===void 0?{}:{bodyRef:n.body_ref},...n.body_json===void 0?{}:{bodyJson:n.body_json},disposition:n.disposition==="human-answer"?"human-answer":"human-canceled",urgency:"normal",wake:1}).deliveryId}t.action_json!==null&&e.completion_action!==void 0&&t.kind==="page"&&(s=f({adapter:e.completion_action.adapter,bodyJson:e.completion_action.bodyJson,idempotencyKey:`human-action:${t.inbox_ticket_id}`})),t.submit_note_delivery_id!==null&&p(t.submit_note_delivery_id),j(i,t.request_id,{settlement_delivery_id:a,action_delivery_id:s});const r=l(t.request_id);if(r===null)throw new Error(`settled human request disappeared: ${t.request_id}`);return k(i,r),{outcome:"settled",request:r}});return o.outcome==="settled"&&e.post_commit!==void 0&&await b(o.request,e.post_commit),o}d(R,"settleHumanRequest");async function b(e,o){if(e.kind==="review"&&e.projected_at===null&&o.project!==void 0)try{await o.project(e),q(e.request_id,new Date().toISOString())}catch(i){h(e.request_id,i instanceof Error?i.message:String(i))}if(e.companion_node_id!==null&&e.companion_retired_at===null&&o.retire!==void 0)try{await o.retire(e.companion_node_id,e.outcome==="canceled"||e.outcome==="dismissed"?"canceled":"approved"),y(e.request_id,new Date().toISOString())}catch{}}d(b,"projectAndRetire");export{b as projectAndRetire,R as settleHumanRequest};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DetachedWorkLifecycle } from './broker-supervision.js';
|
|
2
|
+
export interface ActionLaneContext {
|
|
3
|
+
lifecycle: DetachedWorkLifecycle;
|
|
4
|
+
}
|
|
5
|
+
/** The daemon lane for one-shot obligations with no publishing object: cron spawn/human sinks and human completion actions. */
|
|
6
|
+
export declare class ActionLaneReconciler {
|
|
7
|
+
run(now: number, ctx: ActionLaneContext): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var p=Object.defineProperty;var d=(n,r)=>p(n,"name",{value:r,configurable:!0});import{rmSync as h}from"node:fs";import{claimDaemonAction as y,dueDaemonActions as g,settleDaemonAction as I}from"../../core/canvas/daemon-actions.js";import{getNode as _}from"../../core/canvas/canvas.js";import{emitEvent as c}from"../../core/events/emit.js";import{operationIdContext as l}from"../../core/events/operation-id.js";import{createPageRequest as v,getRequest as u}from"../../core/human/requests.js";import{synthesizedPageDocument as w,writeSynthesizedPage as k}from"../../core/human/page-synth.js";import{preparePage as $}from"../../core/human/page-authoring.js";import{resolvePageComponents as q}from"../../core/config.js";import{spawnChild as b}from"../../core/runtime/spawn.js";import{runDelivery as D}from"../delivery/run-delivery.js";import{deliveryDaemonInstanceId as f}from"./delivery-lane.js";function s(n,r,e){I(n.actionId,n.attempts,r,e,Date.now())}d(s,"settle");function a(n,r,e){s(n,r,{state:"permanent_failed",failure:{kind:"spawn_error",message:e}})}d(a,"failed");async function N(n,r,e){const t=_(e.nodeId);if(t!==null){if(t.frozen_at!==null||t.pi_session_id!==null||t.status==="idle"||t.status==="done"||t.status==="canceled"){s(n,r,{state:"acknowledged"});return}a(n,r,t.status==="dead"?`cron spawn ${e.nodeId} recorded a failed birth`:`cron spawn ${e.nodeId} found an incomplete birth`);return}try{await b({nodeId:e.nodeId,kind:e.kind,cwd:e.cwd,prompt:e.prompt,...e.root?{root:!0,rootLifecycle:e.rootLifecycle}:{parent:e.parent},readiness:"launch",profile:e.profile,wakeOrigin:e.wakeOrigin}),s(n,r,{state:"acknowledged"})}catch(o){a(n,r,`cron spawn ${e.nodeId} failed: ${o instanceof Error?o.message:String(o)}`),l.fresh(()=>c({level:"error",event:"delivery.cron_spawn_failed",node_id:e.nodeId,error:o,fields:{action_id:n.actionId}}))}}d(N,"deliverSpawn");function P(n,r){const e=k(w(n.title,n.summary,r,!1));try{return $({sourceFile:e.path,source:{sessionName:n.sessionName,...n.profileName===null?{}:{profileName:n.profileName}},productKinds:q(),delivery:{placement:"inline",inbox:!0,reply:!1}})}finally{h(e.dir,{recursive:!0,force:!0})}}d(P,"preparedCronPage");function S(n,r,e){if(u(e.requestId)!==null){s(n,r,{state:"acknowledged"});return}const t=n.body,o=typeof t?.stdout=="string"?t.stdout:null;if(o===null){a(n,r,`cron human ${e.requestId} has no frozen stdout`);return}try{v({request_id:e.requestId,prepared:P(e,o)}),s(n,r,{state:"acknowledged"})}catch(i){a(n,r,`cron human ${e.requestId} failed: ${i instanceof Error?i.message:String(i)}`)}}d(S,"deliverHuman");async function z(n,r){const e=n.adapter;if(n.body===null){a(n,r,`daemon action ${n.actionId} has no body`);return}if(e.adapter==="subprocess"){let t=e.node_id;if(t===void 0){const o=n.idempotencyKey;if(!o.startsWith("human-action:"))throw new Error(`daemon action ${n.actionId} has no originating app`);const i=u(o.slice(13));if(!i)throw new Error(`daemon action ${n.actionId} has no originating human request`);t=i.requester_node_id}await D({argv:e.argv,cwd:e.cwd,document:n.body,attempt:n.attempts,nodeId:t,...e.app?{app:e.app}:{}},o=>s(n,r,o));return}if(e.adapter==="cron_spawn"){await N(n,r,e);return}if(e.adapter==="cron_human"){S(n,r,e);return}a(n,r,`daemon action ${n.actionId} has unknown adapter ${String(e.adapter)}`)}d(z,"deliverAction");class G{static{d(this,"ActionLaneReconciler")}run(r,e){if(!e.lifecycle.acceptsDetachedWork())return;let t;try{t=g(r)}catch(o){l.fresh(()=>c({level:"error",event:"daemon_action.scan_failed",error:o}));return}for(const o of t)try{const i=y(o.actionId,r,f);if(i===null)continue;e.lifecycle.registerDetached(z(i,f).catch(m=>{l.fresh(()=>c({level:"error",event:"daemon_action.failed",error:m,fields:{action_id:i.actionId}}))}))}catch(i){l.fresh(()=>c({level:"error",event:"daemon_action.claim_failed",error:i,fields:{action_id:o.actionId}}))}}}export{G as ActionLaneReconciler};
|
|
@@ -3,7 +3,7 @@ export declare const deliveryDaemonInstanceId: `${string}-${string}-${string}-${
|
|
|
3
3
|
export interface DeliveryLaneContext {
|
|
4
4
|
lifecycle: DetachedWorkLifecycle;
|
|
5
5
|
}
|
|
6
|
-
/** The
|
|
6
|
+
/** The daemon lane for node-outcome external actions. Node-inbox rows are claimed by their destination. */
|
|
7
7
|
export declare class DeliveryLaneReconciler {
|
|
8
8
|
run(now: number, ctx: DeliveryLaneContext): void;
|
|
9
9
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var m=Object.defineProperty;var o=(e,t)=>m(e,"name",{value:t,configurable:!0});import{randomUUID as v}from"node:crypto";import{claimExternalActionDelivery as y,dueExternalActionDeliveries as u,messageBodyForDelivery as h,settleDelivery as c}from"../../core/canvas/deliveries.js";import{emitEvent as d}from"../../core/events/emit.js";import{operationIdContext as l}from"../../core/events/operation-id.js";import{runDelivery as I}from"../delivery/run-delivery.js";const s=v();function p(e,t,r){c(e.deliveryId,e.attempts,t,{state:"permanent_failed",failure:{kind:"spawn_error",message:r}},Date.now())}o(p,"failed");async function D(e,t){const r=e.adapter;if(r===null||r.adapter!=="subprocess"){p(e,t,`delivery ${e.deliveryId} has no subprocess adapter`);return}const n=h(e.deliveryId);if(n===null){p(e,t,`delivery ${e.deliveryId} has no message body`);return}let a=r.node_id;if(a===void 0){const i=e.idempotencyKey;if(!i?.startsWith("node-outcome:"))throw new Error(`delivery ${e.deliveryId} has no originating app`);a=i.slice(13)}await I({argv:r.argv,cwd:r.cwd,document:n,attempt:e.attempts,nodeId:a,...r.app?{app:r.app}:{}},i=>{c(e.deliveryId,e.attempts,t,i,Date.now())})}o(D,"deliverExternal");class k{static{o(this,"DeliveryLaneReconciler")}run(t,r){if(!r.lifecycle.acceptsDetachedWork())return;let n;try{n=u(t)}catch(a){l.fresh(()=>d({level:"error",event:"delivery.scan_failed",error:a}));return}for(const a of n)try{const i=y(a.deliveryId,t,s);if(i===null)continue;r.lifecycle.registerDetached(D(i,s).catch(f=>{l.fresh(()=>d({level:"error",event:"delivery.failed",error:f,fields:{delivery_id:i.deliveryId}}))}))}catch(i){l.fresh(()=>d({level:"error",event:"delivery.claim_failed",error:i,fields:{delivery_id:a.deliveryId}}))}}}export{k as DeliveryLaneReconciler,s as deliveryDaemonInstanceId};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/crouter",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.357",
|
|
4
4
|
"description": "crtr — agent runtime with memory, plugins, and marketplaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -131,7 +131,7 @@
|
|
|
131
131
|
"@earendil-works/pi-ai": "0.87.1",
|
|
132
132
|
"@earendil-works/pi-coding-agent": "0.87.1",
|
|
133
133
|
"@earendil-works/pi-tui": "0.87.1",
|
|
134
|
-
"@north-light/crouter-identity": "^0.3.
|
|
134
|
+
"@north-light/crouter-identity": "^0.3.357",
|
|
135
135
|
"cron-parser": "^5.6.0",
|
|
136
136
|
"esbuild": "^0.27.7",
|
|
137
137
|
"jose": "^6.2.12",
|
package/runtime.lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/crouter",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.357",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@north-light/crouter",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.357",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "GPL-3.0-only",
|
|
12
12
|
"workspaces": [
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@earendil-works/pi-ai": "0.87.1",
|
|
19
19
|
"@earendil-works/pi-coding-agent": "0.87.1",
|
|
20
20
|
"@earendil-works/pi-tui": "0.87.1",
|
|
21
|
-
"@north-light/crouter-identity": "^0.3.
|
|
21
|
+
"@north-light/crouter-identity": "^0.3.357",
|
|
22
22
|
"cron-parser": "^5.6.0",
|
|
23
23
|
"esbuild": "^0.27.7",
|
|
24
24
|
"jose": "^6.2.12",
|
|
@@ -10885,17 +10885,17 @@
|
|
|
10885
10885
|
},
|
|
10886
10886
|
"packages/crouter-api": {
|
|
10887
10887
|
"name": "@north-light/crouter-api",
|
|
10888
|
-
"version": "0.3.
|
|
10888
|
+
"version": "0.3.357",
|
|
10889
10889
|
"license": "GPL-3.0-only"
|
|
10890
10890
|
},
|
|
10891
10891
|
"packages/crouter-env-docker": {
|
|
10892
10892
|
"name": "@north-light/crouter-env-docker",
|
|
10893
|
-
"version": "0.3.
|
|
10893
|
+
"version": "0.3.357",
|
|
10894
10894
|
"license": "GPL-3.0-only"
|
|
10895
10895
|
},
|
|
10896
10896
|
"packages/crouter-identity": {
|
|
10897
10897
|
"name": "@north-light/crouter-identity",
|
|
10898
|
-
"version": "0.3.
|
|
10898
|
+
"version": "0.3.357",
|
|
10899
10899
|
"license": "GPL-3.0-only",
|
|
10900
10900
|
"dependencies": {
|
|
10901
10901
|
"jose": "^6.2.1"
|
|
@@ -10903,19 +10903,19 @@
|
|
|
10903
10903
|
},
|
|
10904
10904
|
"packages/crouter-plugin": {
|
|
10905
10905
|
"name": "@north-light/crouter-plugin",
|
|
10906
|
-
"version": "0.3.
|
|
10906
|
+
"version": "0.3.357",
|
|
10907
10907
|
"license": "GPL-3.0-only",
|
|
10908
10908
|
"dependencies": {
|
|
10909
|
-
"@north-light/crouter-api": "^0.3.
|
|
10909
|
+
"@north-light/crouter-api": "^0.3.357"
|
|
10910
10910
|
}
|
|
10911
10911
|
},
|
|
10912
10912
|
"packages/crouter-sdk": {
|
|
10913
10913
|
"name": "@north-light/crouter-sdk",
|
|
10914
|
-
"version": "0.3.
|
|
10914
|
+
"version": "0.3.357",
|
|
10915
10915
|
"license": "GPL-3.0-only",
|
|
10916
10916
|
"dependencies": {
|
|
10917
|
-
"@north-light/crouter-api": "^0.3.
|
|
10918
|
-
"@north-light/crouter-identity": "^0.3.
|
|
10917
|
+
"@north-light/crouter-api": "^0.3.357",
|
|
10918
|
+
"@north-light/crouter-identity": "^0.3.357",
|
|
10919
10919
|
"jose": "^6.2.1"
|
|
10920
10920
|
}
|
|
10921
10921
|
}
|