@north-light/cli 0.3.533 → 0.3.535
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/crons.d.ts +1 -1
- package/dist/api/dto/nodes.d.ts +2 -0
- package/dist/builtin-memory/crouter-sdk/release-notes.md +6 -1
- package/dist/builtin-memory/northlight-apps/providers/README.md +1 -1
- package/dist/builtin-memory/northlight-apps/providers/sms.md +1 -1
- package/dist/clients/attach/viewer.js +2 -2
- package/dist/commands/api-client.d.ts +1 -0
- package/dist/commands/api-client.js +1 -1
- package/dist/commands/canvas.js +1 -1
- package/dist/commands/node/inspect.js +9 -9
- package/dist/core/bash-jobs.d.ts +4 -0
- package/dist/core/bash-jobs.js +8 -8
- package/dist/core/canvas/canvas.d.ts +16 -2
- package/dist/core/canvas/canvas.js +20 -20
- package/dist/core/canvas/recovery.js +1 -1
- package/dist/core/canvas/remote-canvas-source.d.ts +1 -0
- package/dist/core/canvas/remote-canvas-source.js +1 -1
- package/dist/core/canvas/source.d.ts +4 -0
- package/dist/core/canvas/source.js +1 -1
- package/dist/core/canvas/tree.d.ts +2 -0
- package/dist/core/canvas/tree.js +12 -5
- package/dist/core/graph/documents.js +7 -7
- package/dist/core/graph/watches.d.ts +0 -2
- package/dist/core/graph/watches.js +7 -12
- package/dist/core/runs/questions.d.ts +2 -0
- package/dist/core/runs/questions.js +1 -1
- package/dist/core/runtime/broker/fault-retry.d.ts +6 -0
- package/dist/core/runtime/broker/fault-retry.js +1 -1
- package/dist/core/runtime/launch.js +2 -2
- package/dist/core/worktree.js +8 -8
- package/dist/daemon/api/handlers/crons.js +1 -1
- package/dist/daemon/api/handlers/docs.js +1 -1
- package/dist/daemon/api/handlers/nodes.js +1 -1
- package/dist/daemon/api/handlers/objects.js +3 -3
- package/dist/daemon/api/handlers/questions.js +1 -1
- package/dist/daemon/cron/ended.d.ts +3 -0
- package/dist/daemon/cron/ended.js +2 -2
- package/dist/daemon/cron/narrowed.d.ts +5 -0
- package/dist/daemon/cron/narrowed.js +2 -0
- package/dist/daemon/cron/settle.js +1 -1
- package/dist/daemon/reconcilers/bash-deadline.d.ts +6 -0
- package/dist/daemon/reconcilers/bash-deadline.js +3 -2
- package/dist/daemon/runs/observer.d.ts +2 -0
- package/dist/daemon/runs/observer.js +2 -2
- package/docs/apps/providers/README.md +1 -1
- package/docs/apps/providers/sms.md +1 -1
- package/docs/sdk/release-notes.md +6 -1
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +12 -12
- package/dist/core/canvas/nav-model.d.ts +0 -44
- package/dist/core/canvas/nav-model.js +0 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
var Z=Object.defineProperty;var i=(e,n)=>Z(e,"name",{value:n,configurable:!0});import{envNodeId as U}from"../../shared/env.js";import{rmdirSync as ee,rmSync as ne,statSync as te}from"node:fs";import{dirname as ae,join as
|
|
1
|
+
var Z=Object.defineProperty;var i=(e,n)=>Z(e,"name",{value:n,configurable:!0});import{envNodeId as U}from"../../shared/env.js";import{rmdirSync as ee,rmSync as ne,statSync as te}from"node:fs";import{dirname as ae,join as I,resolve as ie}from"node:path";import{removeTreeBeneath as j}from"../spaces/open-beneath.js";import{emitEvent as oe}from"../events/emit.js";import{withCanvasWrite as p,openDb as s}from"./db.js";import{conversationStore as re,ConversationNotFoundError as se}from"../conversation-store/index.js";import{hasUnseenWakeMail as de,UNSEEN_WAKE_MAIL_SQL as ue}from"./deliveries.js";import{isAppRun as W}from"./app-run.js";import{registerOutcomeAction as b}from"./outcome-actions.js";import{publish as le}from"../graph/events.js";import{nodeObject as ce}from"../graph/objects.js";import{findNodeBySessionFileSql as _e}from"./sessions.js";import{hydrateFault as pe}from"./recovery.js";import{hasUnreconciledWorktree as fe,openWorktree as Ee,readWorktree as we,worktreeFromRow as ye}from"./worktrees.js";import{isPidAlive as me,isPidPresent as F,recordedPidLiveness as Ne}from"./pid.js";import{ensureHome as Re,jobDir as Se,nodeDir as he,nodeRunDir as H}from"./paths.js";import{appForNode as Oe,ensureNodeDirs as Te,nodeAgentDir as Le}from"./node-agent-paths.js";import{appSpace as C}from"../layout.js";import{createObject as De,getById as M,ownerForGrantee as h,setObjectKind as ge,setObjectName as Ae}from"../graph/objects.js";import{deleteNodeWithOwned as ve}from"../graph/deletion.js";import{SUBTREE_ALL_IDS_SQL as ke,SUBTREE_IDS_SQL as xe}from"./tree.js";import{filterAsync as y,mapAsync as O}from"../async-array.js";function E(e,n){if(e==null)return null;const t=JSON.stringify(e);if(t===void 0)throw new TypeError(`${n} must be JSON-serializable`);return t}i(E,"jsonValue");async function ln(e,n){if((await e.prepare("SELECT deleting_at FROM nodes WHERE node_id = ?").get(n))?.deleting_at)throw new Error("run is deleting")}i(ln,"assertRunNotDeleting");async function Ue(e,n){const t=await h(n,e.grantee??"app:terminal");await De(n,{id:e.node_id,type:"node",kind:e.kind,owner:t.id,privacy:"public",name:e.name,preview:""}),await n.prepare(`INSERT INTO nodes (node_id, description, title, icon, cycles, mode, lifecycle, cwd, host_kind, profile_id, parent, spawned_by, creator, fork_from, fork_source_file, created, passive_default, cycle_pending, model_override, persona_ack_json, review_binding_json, launch_config_json, scopes_json, isolated, status, intent, final_report, finalized_at, deadline_at, "window", tmux_session, pane, sub, grant_id, client_id, metadata_json, run_id, event_cursor, usage_json, deleting_at) VALUES (${Array(40).fill("?").join(", ")})`).run(e.node_id,e.description??null,e.title??null,e.icon??null,e.cycles??null,e.mode,e.lifecycle,e.cwd,e.host_kind??null,e.profile_id??null,e.parent??null,e.spawned_by??null,e.creator??null,e.fork_from??null,e.fork_source_file??null,e.created,e.passive_default===!0?1:0,e.cycle_pending===!0?1:0,e.model_override??null,E(e.persona_ack,"persona_ack"),E(e.review_binding,"review_binding"),E(e.launch,"launch"),E(e.scopes,"scopes"),e.isolated===!0?1:0,e.status??"active",e.intent??null,e.final_report??null,e.finalized_at??null,e.deadline_at??null,e.window??null,e.tmux_session??null,e.pane??null,e.sub??null,e.grant_id??null,e.client_id??null,e.metadata_json??null,e.run_id??null,e.event_cursor??null,e.usage_json??null,e.deleting_at??null)}i(Ue,"seedRow");function P(e){if(e.fault_id==null)return null;const n=Object.entries(e).filter(([t])=>t.startsWith("fault_")).map(([t,a])=>[t==="fault_id"?t:t.slice(6),a]);return pe(Object.fromEntries(n))}i(P,"faultFrom");function f(e){const n={node_id:e.node_id,name:e.name,description:e.description??void 0,cycles:e.cycles??void 0,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind??null,profile_id:e.profile_id??null,scopes:e.scopes_json==null?null:JSON.parse(e.scopes_json),isolated:e.isolated===1,grantee:e.grantee,sub:e.sub??null,grant_id:e.grant_id??null,client_id:e.client_id??null,metadata_json:e.metadata_json??null,run_id:e.run_id??null,event_cursor:e.event_cursor??null,last_activity_at:e.last_activity_at??null,usage_json:e.usage_json??null,last_turn_error_json:e.last_turn_error_json??null,deleting_at:e.deleting_at??null,parent:e.parent??null,created:e.created,intent:e.intent??null,frozen_at:e.frozen_at??null,respawn_failures:e.respawn_failures??0,respawn_not_before:e.respawn_not_before??null,launched_at:e.launched_at??null,last_settled_at:e.last_settled_at??null,terminal_reason:e.terminal_reason??null,final_report:e.final_report??null,finalized_at:e.finalized_at??null,outcome_kind:e.outcome_kind??null,outcome_reason:e.outcome_reason??null,outcome_at:e.outcome_at??null,outcome_revision:e.outcome_revision??0,outcome_detail_json:e.outcome_detail_json??null,deadline_at:e.deadline_at??null,telemetry_tokens_in:e.telemetry_tokens_in??null,telemetry_context_tokens:e.telemetry_context_tokens??null,telemetry_last_activity:e.telemetry_last_activity??null,telemetry_updated_at:e.telemetry_updated_at??null,pi_pid:e.pi_pid??null,pi_pid_identity:e.pi_pid_identity??null,window:e.window??null,tmux_session:e.tmux_session??null,pane:e.pane??null,fault:null,streaming:!1},t=F(n.pi_pid),a=P(e);return n.fault=a?.link==="pi\u2192provider"&&a.retry.by==="daemon"&&a.retry.disposition==="auto"&&!t?null:a,n.streaming=e.turn_open_at!==null&&e.turn_closed_at===null&&t,n}i(f,"rowFrom");async function $(e,n){return n??=await we(e.node_id),{...f(e),title:e.title??void 0,icon:e.icon??void 0,spawned_by:e.spawned_by??null,creator:e.creator??null,fork_from:e.fork_from??null,fork_source_file:e.fork_source_file??null,passive_default:e.passive_default===1,cycle_pending:e.cycle_pending===1,model_override:e.model_override??null,scopes:e.scopes_json==null?null:JSON.parse(e.scopes_json),persona_ack:e.persona_ack_json==null?void 0:JSON.parse(e.persona_ack_json),review_binding:e.review_binding_json==null?void 0:JSON.parse(e.review_binding_json),launch:e.launch_config_json==null?void 0:JSON.parse(e.launch_config_json),pi_session_id:e.pi_session_id??null,pi_session_file:e.pi_session_file??null,...n===null?{}:{managed_worktree:n}}}i($,"metaFrom");async function cn(e,n={}){return Re(),await p(async t=>{await Ue(e,t),e.managed_worktree!==void 0&&e.managed_worktree!==null&&await Ee(e.node_id,e.managed_worktree,t),n.outcomeDelivery!==void 0&&await b(t,e.node_id,n.outcomeDelivery),await n.withinCreate?.(t,e)}),await Te(e.node_id),await N(e.node_id)}i(cn,"createNode");async function N(e){const n=await(await s()).prepare("SELECT * FROM node_rows WHERE node_id = ?").get(e);return n===void 0?null:await $(n)}i(N,"getNode");const Ie=1440*60*1e3;function q(e){return{requestKey:e.request_key,nodeId:e.node_id,state:e.state}}i(q,"createRequestRecord");async function _n(e){const n=await(await s()).prepareUncached("SELECT request_key, node_id, state FROM create_requests WHERE request_key = ?").get(e);return n===void 0?null:q(n)}i(_n,"findCreateRequest");async function pn(e){return await p(async n=>{const t=Date.now();await n.prepareUncached("DELETE FROM create_requests WHERE expires_at <= ?").run(t);const a=await n.prepareUncached("SELECT request_key, node_id, state FROM create_requests WHERE request_key = ?").get(e);return a!==void 0?q(a):(await n.prepareUncached("INSERT INTO create_requests (request_key, node_id, expires_at, state) VALUES (?, NULL, ?, 'reserved')").run(e,t+Ie),{requestKey:e,nodeId:null,state:"reserved"})})}i(pn,"reserveCreateRequest");async function fn(e=Date.now()){return Number((await(await s()).prepareUncached("DELETE FROM create_requests WHERE expires_at <= ?").run(e)).changes)}i(fn,"pruneExpiredCreateRequests");async function En(e,n){await(await s()).prepareUncached("UPDATE create_requests SET node_id = ?, state = 'complete' WHERE request_key = ?").run(n,e)}i(En,"recordCreateRequestNode");async function wn(e,n){await(await s()).prepareUncached("UPDATE create_requests SET node_id = ?, state = 'reserved' WHERE request_key = ?").run(n,e)}i(wn,"reserveCreateRequestNode");async function yn(e,n){await(await s()).prepareUncached("UPDATE create_requests SET state = 'complete' WHERE request_key = ? AND node_id = ?").run(e,n)}i(yn,"completeCreateRequest");async function mn(e,n){await p(async t=>{if(n===null){await t.prepareUncached("DELETE FROM create_requests WHERE request_key = ? AND node_id IS NULL").run(e);return}await t.prepareUncached("DELETE FROM create_requests WHERE request_key = ? AND node_id = ?").run(e,n)})}i(mn,"abandonCreateRequest");function Nn(e){return ie(e)}i(Nn,"canonicalSessionFile");async function Rn(e){const n=await _e(e);return n===null?null:await N(n)}i(Rn,"findNodeBySessionFile");async function Sn(e){const n=await(await s()).prepare("SELECT * FROM node_rows WHERE node_id = ?").get(e);return n?f(n):null}i(Sn,"getRow");async function hn(e){const n=await(await s()).prepare("SELECT * FROM node_rows WHERE pane = ?").get(e);return n?f(n):null}i(hn,"getRowByPane");async function On(e){return(await(await s()).prepare(`SELECT * FROM node_rows
|
|
2
2
|
WHERE deadline_at IS NOT NULL AND outcome_at IS NULL
|
|
3
3
|
AND deadline_at <= ? AND status IN ('active','idle') AND kind != 'human'
|
|
4
|
-
ORDER BY deadline_at, created, node_id`).all(e)).map(f)}i(
|
|
5
|
-
WHERE profile_id = ? AND deadline_at IS NOT NULL AND status IN ('active', 'idle')`).all(e),o=t.prepare("UPDATE nodes SET deadline_at = ? WHERE node_id = ? AND deadline_at = ?");let r=0;for(const d of a){const
|
|
6
|
-
WHERE o.type = 'node' AND i.scheme = 'local-user' AND i.external_id = 'user:local'`,r=await e.prepareUncached(`${a} LIMIT 1`).get()!==void 0?Number((await e.prepareUncached(`UPDATE objects SET owner = ? WHERE id IN (${a})`).run((await
|
|
4
|
+
ORDER BY deadline_at, created, node_id`).all(e)).map(f)}i(On,"dueNodeDeadlines");async function Tn(e,n){return Number((await(await s()).prepare("UPDATE nodes SET deadline_at = ? WHERE node_id = ?").run(n,e)).changes)===1}i(Tn,"setNodeDeadline");async function Ln(e,n){return!Number.isFinite(n)||n<=0?0:await p(async t=>{const a=await t.prepare(`SELECT node_id, deadline_at FROM nodes
|
|
5
|
+
WHERE profile_id = ? AND deadline_at IS NOT NULL AND status IN ('active', 'idle')`).all(e),o=t.prepare("UPDATE nodes SET deadline_at = ? WHERE node_id = ? AND deadline_at = ?");let r=0;for(const d of a){const l=Date.parse(d.deadline_at);Number.isNaN(l)||(r+=Number((await o.run(new Date(l+n).toISOString(),d.node_id,d.deadline_at)).changes))}return r})}i(Ln,"shiftProfileNodeDeadlines");async function Dn(e,n,t){const a=`SELECT o.id FROM objects o JOIN identities i ON i.object = o.owner JOIN nodes n ON n.node_id = o.id
|
|
6
|
+
WHERE o.type = 'node' AND i.scheme = 'local-user' AND i.external_id = 'user:local'`,r=await e.prepareUncached(`${a} LIMIT 1`).get()!==void 0?Number((await e.prepareUncached(`UPDATE objects SET owner = ? WHERE id IN (${a})`).run((await h(e,"app:terminal")).id)).changes):0,d=`SELECT o.id FROM objects o JOIN peer_stubs s ON s.object = o.id JOIN identities i ON i.object = o.owner
|
|
7
7
|
WHERE o.type = 'node' AND o.reception = 2 AND s.envelope_json ->> 'app' IS NULL
|
|
8
|
-
AND i.scheme = 'app' AND i.external_id = 'app:terminal'`,
|
|
8
|
+
AND i.scheme = 'app' AND i.external_id = 'app:terminal'`,l=await e.prepareUncached(`${d} LIMIT 1`).get()!==void 0?Number((await e.prepareUncached(`UPDATE objects SET owner = ? WHERE id IN (${d})`).run((await h(e,"user:local")).id)).changes):0;return Number((await e.prepare("UPDATE nodes SET sub = ? WHERE sub = 'user:local'").run(n)).changes)+r+l+Number((await e.prepare(`UPDATE nodes SET sub = ? WHERE sub IS NULL AND node_id IN (
|
|
9
9
|
SELECT o.id FROM objects o JOIN identities i ON i.object = o.owner
|
|
10
|
-
WHERE o.type = 'node' AND i.scheme = 'app' AND i.external_id = 'app:terminal')`).run(n)).changes)+Number((await e.prepare("UPDATE nodes SET grant_id = NULL WHERE grant_id = ?").run(t)).changes)}i(
|
|
10
|
+
WHERE o.type = 'node' AND i.scheme = 'app' AND i.external_id = 'app:terminal')`).run(n)).changes)+Number((await e.prepare("UPDATE nodes SET grant_id = NULL WHERE grant_id = ?").run(t)).changes)}i(Dn,"rewriteLocalNodeIdentity");function T(e,n){if(e==null)return null;if(typeof e=="string"||typeof e=="number"||typeof e=="bigint"||e instanceof Uint8Array)return e;throw new TypeError(`${n} must be a SQLite scalar`)}i(T,"sqlInput");async function gn(e,n){const t=[],a=i((r,d=r)=>{Object.prototype.hasOwnProperty.call(n,r)&&t.push([d,T(n[r],r)])},"add");if(a("description"),a("title"),a("icon"),a("cycles"),a("mode"),a("lifecycle"),a("cwd"),a("host_kind"),a("profile_id"),a("parent"),a("spawned_by"),a("creator"),a("fork_from"),a("fork_source_file"),a("model_override"),Object.prototype.hasOwnProperty.call(n,"passive_default")&&t.push(["passive_default",n.passive_default===!0?1:0]),Object.prototype.hasOwnProperty.call(n,"cycle_pending")&&t.push(["cycle_pending",n.cycle_pending===!0?1:0]),Object.prototype.hasOwnProperty.call(n,"persona_ack")&&t.push(["persona_ack_json",E(n.persona_ack,"persona_ack")]),Object.prototype.hasOwnProperty.call(n,"review_binding")&&t.push(["review_binding_json",E(n.review_binding,"review_binding")]),Object.prototype.hasOwnProperty.call(n,"isolated"))throw new TypeError("isolated cannot change after node creation");Object.prototype.hasOwnProperty.call(n,"scopes")&&t.push(["scopes_json",E(n.scopes,"scopes")]),Object.prototype.hasOwnProperty.call(n,"launch")&&t.push(["launch_config_json",E(n.launch,"launch")]);const o=i(r=>Object.prototype.hasOwnProperty.call(n,r),"has");return await p(async r=>{const d=await M(r,e);if(d===null||d.type!=="node")throw new Error(`unknown node: ${e}`);if(o("name")&&await Ae(r,d,T(n.name,"name")),o("kind")&&await ge(r,d,T(n.kind,"kind")),t.length===0)return;if((await r.prepareUncached(`UPDATE nodes SET ${t.map(([u])=>`${u} = ?`).join(", ")} WHERE node_id = ?`).run(...t.map(([,u])=>u),e)).changes!==1)throw new Error(`unknown node: ${e}`)}),await N(e)}i(gn,"updateNode");async function An(e,n){await(await s()).prepare("UPDATE nodes SET status = ? WHERE node_id = ?").run(n,e)}i(An,"setStatus");async function vn(e,n){await(await s()).prepare("UPDATE nodes SET intent = ? WHERE node_id = ?").run(n??null,e)}i(vn,"setIntent");async function kn(e,n,t={}){if(t.outcome===void 0){const o=[],r=[];Object.prototype.hasOwnProperty.call(n,"status")&&(o.push("status = ?"),r.push(n.status??null)),Object.prototype.hasOwnProperty.call(n,"intent")&&(o.push("intent = ?"),r.push(n.intent??null)),Object.prototype.hasOwnProperty.call(n,"terminal_reason")&&(o.push("terminal_reason = ?"),r.push(n.terminal_reason??null));const d=["node_id = ?"];r.push(e),t.fromStatuses!==void 0&&(d.push(`status IN (${t.fromStatuses.map(()=>"?").join(", ")})`),r.push(...t.fromStatuses)),t.requireNoFinalReport===!0&&d.push("final_report IS NULL");const l=await(await s()).prepareUncached(`UPDATE nodes SET ${o.join(", ")} WHERE ${d.join(" AND ")}`).run(...r);return Number(l.changes)}const a=t.outcome;return await p(async o=>{const r=[],d=[];Object.prototype.hasOwnProperty.call(n,"status")&&(r.push("status = ?"),d.push(n.status??null)),Object.prototype.hasOwnProperty.call(n,"intent")&&(r.push("intent = ?"),d.push(n.intent??null)),Object.prototype.hasOwnProperty.call(n,"terminal_reason")&&(r.push("terminal_reason = ?"),d.push(n.terminal_reason??null));const l=i((m,c)=>a.supersede===!0?"?":`CASE WHEN outcome_at IS NULL THEN ? ELSE ${c} END`,"outcomeValue");r.push(`outcome_kind = ${l(a.kind,"outcome_kind")}`,`outcome_reason = ${l(a.reason,"outcome_reason")}`,`outcome_detail_json = ${l(a.detailJson,"outcome_detail_json")}`,`outcome_revision = ${a.supersede===!0?"outcome_revision + 1":"CASE WHEN outcome_at IS NULL THEN outcome_revision + 1 ELSE outcome_revision END"}`,`outcome_at = ${l(a.at,"outcome_at")}`),d.push(a.kind,a.reason,a.detailJson,a.at);const u=["node_id = ?"];d.push(e),t.fromStatuses!==void 0&&(u.push(`status IN (${t.fromStatuses.map(()=>"?").join(", ")})`),d.push(...t.fromStatuses)),t.requireNoFinalReport===!0&&u.push("final_report IS NULL");const _=await o.prepareUncached(`UPDATE nodes SET ${r.join(", ")} WHERE ${u.join(" AND ")}`).run(...d);if(Number(_.changes)===0)return 0;const S=await o.prepare("SELECT outcome_at FROM nodes WHERE node_id = ?").get(e);return(a.supersede===!0||S.outcome_at===a.at)&&a.documentJson!==null&&a.documentJson!==void 0&&await le(o,{event:"outcome",object:await ce(o,e),actor:null,attrs:{revision:Number((await o.prepare("SELECT outcome_revision FROM nodes WHERE node_id = ?").get(e)).outcome_revision)},messageBody:JSON.parse(a.documentJson)}),Number(_.changes)})}i(kn,"transitionStatusIntent");async function xn(e){return(await(await s()).prepare("SELECT final_report FROM nodes WHERE node_id = ?").get(e))?.final_report??null}i(xn,"getFinalReport");async function Un(e,n){return(await(await s()).prepare("UPDATE nodes SET final_report = NULL, finalized_at = NULL WHERE node_id = ? AND final_report = ?").run(e,n)).changes>0}i(Un,"clearFinalReportIfMatches");async function In(e,n){await(await s()).prepare('UPDATE nodes SET tmux_session = ?, "window" = ?, pane = ? WHERE node_id = ?').run(n.tmux_session??null,n.window??null,n.pane??null,e)}i(In,"setPresence");async function jn(e,n){await(await s()).prepare("UPDATE nodes SET launched_at = ?, frozen_at = NULL, respawn_not_before = NULL WHERE node_id = ?").run(n,e)}i(jn,"recordLaunch");async function Wn(e,n){await(await s()).prepare("UPDATE nodes SET last_settled_at = ? WHERE node_id = ?").run(n,e)}i(Wn,"recordSettledTurn");async function bn(e,n){await(await s()).prepare("UPDATE nodes SET frozen_at = ? WHERE node_id = ?").run(n,e)}i(bn,"setFrozen");async function Fn(e){await(await s()).prepare("UPDATE nodes SET frozen_at = NULL WHERE node_id = ?").run(e)}i(Fn,"clearFrozen");async function Hn(e,n){await(await s()).prepare("UPDATE nodes SET respawn_failures = ?, respawn_not_before = ? WHERE node_id = ?").run(n.failures,n.notBefore,e)}i(Hn,"recordRespawnAttempt");const w="node_id NOT IN (SELECT node_id FROM warm_pool)",B=["state","cleanup_state","path","branch","repo_root","base_ref","base_sha","created_at","closed_at","next_attempt_at","attempts","quarantined","sweep_reason","sweep_detail","sweep_last_at","sweep_observed_json","abandoned_json","land_intent_json","disposal_json"];function je(e){return e.worktree_state===null?null:ye(Object.fromEntries(B.map(n=>[n,e[`worktree_${n}`]])))}i(je,"worktreeFromProjection");async function Cn(e){const n=B.map(a=>`w.${a} AS worktree_${a}`).join(", "),t=await(await s()).prepareUncached(`SELECT n.*, ${n} FROM node_rows n LEFT JOIN worktrees w ON w.node_id = n.node_id WHERE n.profile_id = ? ORDER BY n.created`).all(e);return await O(t,async a=>await $(a,je(a)))}i(Cn,"listNodesByProfile");async function Mn(){return(await(await s()).prepare(`SELECT
|
|
11
11
|
node_id, name, description, kind, mode, lifecycle, status, cwd, profile_id,
|
|
12
12
|
grantee, parent, created, frozen_at, terminal_reason, final_report,
|
|
13
13
|
telemetry_tokens_in, telemetry_updated_at, pi_pid, turn_open_at, turn_closed_at,
|
|
@@ -15,13 +15,13 @@ var Z=Object.defineProperty;var i=(e,n)=>Z(e,"name",{value:n,configurable:!0});i
|
|
|
15
15
|
fault_operation_id, fault_anchor_entry_id, fault_retry_disposition,
|
|
16
16
|
fault_retry_by, fault_retry_attempt, fault_retry_max, fault_retry_next_at,
|
|
17
17
|
fault_provider_error_json
|
|
18
|
-
FROM node_rows WHERE ${w} ORDER BY created`).all()).map(f)}i(
|
|
18
|
+
FROM node_rows WHERE ${w} ORDER BY created`).all()).map(f)}i(Mn,"browseNodes");async function Pn(e,n){await(await s()).prepare(`UPDATE nodes
|
|
19
19
|
SET telemetry_tokens_in = ?,
|
|
20
20
|
telemetry_context_tokens = COALESCE(?, telemetry_context_tokens),
|
|
21
21
|
telemetry_last_activity = COALESCE(?, telemetry_last_activity),
|
|
22
22
|
telemetry_updated_at = ?
|
|
23
23
|
WHERE node_id = ?
|
|
24
|
-
AND (telemetry_updated_at IS NULL OR telemetry_updated_at < ?)`).run(n.tokensIn,n.contextTokens,n.lastActivity,n.updatedAt,e,n.updatedAt)}i(
|
|
24
|
+
AND (telemetry_updated_at IS NULL OR telemetry_updated_at < ?)`).run(n.tokensIn,n.contextTokens,n.lastActivity,n.updatedAt,e,n.updatedAt)}i(Pn,"updateNodeTelemetry");async function $n(){return(await(await s()).prepare(`SELECT
|
|
25
25
|
node_id, name, description, cycles, kind, status, frozen_at,
|
|
26
26
|
telemetry_context_tokens, telemetry_last_activity,
|
|
27
27
|
pi_pid, turn_open_at, turn_closed_at,
|
|
@@ -29,14 +29,14 @@ var Z=Object.defineProperty;var i=(e,n)=>Z(e,"name",{value:n,configurable:!0});i
|
|
|
29
29
|
fault_operation_id, fault_anchor_entry_id, fault_retry_disposition,
|
|
30
30
|
fault_retry_by, fault_retry_attempt, fault_retry_max, fault_retry_next_at,
|
|
31
31
|
fault_provider_error_json
|
|
32
|
-
FROM node_rows WHERE ${w} ORDER BY created`).all()).map(n=>{const t=n.pi_pid??null,a=F(t),o=P(n);return{node_id:n.node_id,name:n.name,description:n.description??null,cycles:n.cycles??null,kind:n.kind,status:n.status,frozen_at:n.frozen_at??null,pi_pid:t,telemetry_context_tokens:n.telemetry_context_tokens??null,telemetry_last_activity:n.telemetry_last_activity??null,fault:o?.link==="pi\u2192provider"&&o.retry.by==="daemon"&&o.retry.disposition==="auto"&&!a?null:o,streaming:n.turn_open_at!==null&&n.turn_closed_at===null&&a}})}i(
|
|
32
|
+
FROM node_rows WHERE ${w} ORDER BY created`).all()).map(n=>{const t=n.pi_pid??null,a=F(t),o=P(n);return{node_id:n.node_id,name:n.name,description:n.description??null,cycles:n.cycles??null,kind:n.kind,status:n.status,frozen_at:n.frozen_at??null,pi_pid:t,telemetry_context_tokens:n.telemetry_context_tokens??null,telemetry_last_activity:n.telemetry_last_activity??null,fault:o?.link==="pi\u2192provider"&&o.retry.by==="daemon"&&o.retry.disposition==="auto"&&!a?null:o,streaming:n.turn_open_at!==null&&n.turn_closed_at===null&&a}})}i($n,"graphNodes");async function We(e){const n=[w],t=[];if(e?.under!==void 0&&(e.underInclusive===!0?(n.push(`(node_id IN (${ke}) OR node_id = ?)`),t.push(e.under,e.under,e.under)):(n.push(`node_id IN (${xe})`),t.push(e.under,e.under))),e?.lifecycle!==void 0&&(n.push("lifecycle = ?"),t.push(e.lifecycle)),e?.kind!==void 0&&(n.push("kind = ?"),t.push(e.kind)),e?.mode!==void 0&&(n.push("mode = ?"),t.push(e.mode)),e?.profileId!==void 0&&(n.push("profile_id = ?"),t.push(e.profileId)),e?.profilePrefix!==void 0&&(n.push("profile_id LIKE ? ESCAPE '\\'"),t.push(`${e.profilePrefix.replace(/[\\%_]/g,o=>`\\${o}`)}%`)),e?.parent!==void 0&&(n.push("parent = ?"),t.push(e.parent)),e?.topLevel===!0&&n.push("parent IS NULL"),e?.hanging===!0&&n.push("parent IS NOT NULL AND parent NOT IN (SELECT node_id FROM node_rows)"),e?.status!==void 0){const o=Array.isArray(e.status)?e.status:[e.status];n.push(`status IN (${o.map(()=>"?").join(",")})`),t.push(...o)}return e?.withRecordedPid===!0&&n.push("pi_pid IS NOT NULL"),e?.withRecordedPidOrFrozen===!0&&n.push("(pi_pid IS NOT NULL OR frozen_at IS NOT NULL)"),(await(await s()).prepareUncached(`SELECT * FROM node_rows WHERE ${n.join(" AND ")} ORDER BY created`).all(...t)).map(f)}i(We,"listNodes");const be=`SELECT
|
|
33
33
|
node_id, created, launched_at, last_settled_at, finalized_at,
|
|
34
34
|
outcome_at, last_activity_at, pane, "window", tmux_session
|
|
35
35
|
FROM nodes
|
|
36
36
|
WHERE ${w}
|
|
37
37
|
AND status IN ('done', 'canceled', 'dead')
|
|
38
38
|
AND (pane IS NOT NULL OR "window" IS NOT NULL OR tmux_session IS NOT NULL)
|
|
39
|
-
ORDER BY created`;async function
|
|
39
|
+
ORDER BY created`;async function qn(){return await(await s()).prepare(be).all()}i(qn,"listTerminalPlacementResidue");const Fe=`WITH candidates AS MATERIALIZED (
|
|
40
40
|
SELECT node_id FROM nodes WHERE status IN ('active', 'idle')
|
|
41
41
|
UNION
|
|
42
42
|
SELECT node_id FROM nodes
|
|
@@ -50,19 +50,19 @@ var Z=Object.defineProperty;var i=(e,n)=>Z(e,"name",{value:n,configurable:!0});i
|
|
|
50
50
|
AND v.node_id NOT IN (SELECT node_id FROM warm_pool)
|
|
51
51
|
AND v.kind != 'human'
|
|
52
52
|
AND (v.status IN ('active', 'idle') OR (v.status IN ('done', 'canceled', 'dead') AND (v.pi_pid IS NOT NULL OR v.frozen_at IS NOT NULL)))
|
|
53
|
-
ORDER BY v.created`;async function
|
|
54
|
-
WHERE ${
|
|
55
|
-
AND EXISTS (SELECT 1 FROM deliveries d WHERE d.destination_id = v.node_id AND ${
|
|
56
|
-
ORDER BY v.created`).all()).map(f)}i(
|
|
53
|
+
ORDER BY v.created`;async function Bn(){return(await(await s()).prepare(Fe).all()).map(f)}i(Bn,"listNodesForSupervision");const He=i(e=>`(${e}.status = 'done' AND ${e}.intent = 'parked' AND ${e}.lifecycle = 'resident' AND ${e}.final_report IS NULL AND ${e}.deleting_at IS NULL)`,"PARKED_RESIDENT_SQL");async function zn(){return(await(await s()).prepare(`SELECT v.* FROM node_rows v
|
|
54
|
+
WHERE ${He("v")}
|
|
55
|
+
AND EXISTS (SELECT 1 FROM deliveries d WHERE d.destination_id = v.node_id AND ${ue("d")}) AND v.kind != 'human' AND v.node_id NOT IN (SELECT node_id FROM warm_pool)
|
|
56
|
+
ORDER BY v.created`).all()).map(f)}i(zn,"listParkedResidentsWithWakeMail");async function Jn(){return await(await s()).prepare(`SELECT node_id, name, created, grantee FROM node_rows WHERE ${w} ORDER BY created`).all()}i(Jn,"listNodeIdentities");async function Yn(e,n){await(await s()).prepare("INSERT INTO warm_pool (node_id, recipe_key, created) VALUES (?, ?, ?) ON CONFLICT (node_id) DO UPDATE SET recipe_key = excluded.recipe_key, created = excluded.created").run(e,n,new Date().toISOString())}i(Yn,"registerWarmSpare");async function Qn(e){return(await(await s()).prepare("DELETE FROM warm_pool WHERE node_id = ?").run(e)).changes>0}i(Qn,"unregisterWarmSpare");async function L(e,n){const t=`SELECT w.node_id AS node_id, w.recipe_key AS recipe_key, w.created AS created,
|
|
57
57
|
n.status AS status, n.pi_pid AS pi_pid, n.pi_pid_identity AS pi_pid_identity
|
|
58
|
-
FROM warm_pool w JOIN node_rows n ON n.node_id = w.node_id`+(n===void 0?"":" WHERE w.recipe_key = ?")+" ORDER BY w.created";return(n===void 0?await e.prepareUncached(t).all():await e.prepareUncached(t).all(n)).map(o=>({node_id:o.node_id,recipe_key:o.recipe_key,created:o.created,status:o.status,pi_pid:o.pi_pid??null,pi_pid_identity:o.pi_pid_identity??null}))}i(L,"warmSpareRowsFor");async function
|
|
59
|
-
FROM node_rows WHERE ${w} ORDER BY created`).all()).map(e=>({node_id:e.node_id,name:e.name,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind??null,parent:e.parent??null,created:e.created,description:e.description??null}))}i(
|
|
58
|
+
FROM warm_pool w JOIN node_rows n ON n.node_id = w.node_id`+(n===void 0?"":" WHERE w.recipe_key = ?")+" ORDER BY w.created";return(n===void 0?await e.prepareUncached(t).all():await e.prepareUncached(t).all(n)).map(o=>({node_id:o.node_id,recipe_key:o.recipe_key,created:o.created,status:o.status,pi_pid:o.pi_pid??null,pi_pid_identity:o.pi_pid_identity??null}))}i(L,"warmSpareRowsFor");async function Vn(){return await L(await s())}i(Vn,"listWarmSpares");async function Kn(e){return await(await s()).prepare("SELECT 1 FROM warm_pool WHERE node_id = ?").get(e)!==void 0}i(Kn,"isWarmSpare");function z(e){return e.status!=="active"&&e.status!=="idle"?!1:Ne(e.pi_pid,e.pi_pid_identity)==="alive"}i(z,"spareIsClaimable");async function Gn(e,n,t={}){return await p(async a=>{const o=(await L(a,e)).find(z);return o===void 0||t.requestKey!==void 0&&(await a.prepareUncached("UPDATE create_requests SET node_id = ?, state = 'warm_claimed' WHERE request_key = ? AND node_id IS NULL").run(o.node_id,t.requestKey)).changes===0||(await a.prepare("DELETE FROM warm_pool WHERE node_id = ?").run(o.node_id)).changes===0?null:(await a.prepare("UPDATE nodes SET created = ?, deadline_at = ? WHERE node_id = ?").run(n,t.deadlineAt??null,o.node_id),t.outcomeDelivery!==void 0&&await b(a,o.node_id,t.outcomeDelivery),o.node_id)})}i(Gn,"claimWarmSpare");async function Xn(e){return(await L(await s(),e)).filter(z).length}i(Xn,"warmSpareCount");async function Zn(e){return(await(await s()).prepare("SELECT node_id FROM nodes WHERE parent = ? ORDER BY created").all(e)).map(n=>n.node_id)}i(Zn,"childrenOf");async function et(){return(await(await s()).prepareUncached(`SELECT node_id, name, kind, mode, lifecycle, status, cwd, host_kind, parent, created, description
|
|
59
|
+
FROM node_rows WHERE ${w} ORDER BY created`).all()).map(e=>({node_id:e.node_id,name:e.name,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind??null,parent:e.parent??null,created:e.created,description:e.description??null}))}i(et,"rosterNodes");async function nt(e){return(await(await s()).prepareUncached(`SELECT * FROM node_rows
|
|
60
60
|
WHERE parent IS NULL AND kind != 'human'
|
|
61
61
|
AND status IN ('active','idle') AND cwd = ?
|
|
62
62
|
AND ${w}
|
|
63
|
-
ORDER BY created DESC`).all(e)).map(f)}i(
|
|
64
|
-
AND NOT EXISTS (SELECT 1 FROM sessions s WHERE s.node_id = n.node_id) LIMIT 1`);for(const o of e)if(!(await t.get(o)!==void 0||await a.get(o)!==void 0))try{await re().delete(o)}catch(r){if(!(r instanceof se))throw r}}i(g,"deleteNodeConversations");async function A(e,n){const t=await M(e,n);return t===null||t.deleted_at!==null?!1:(await ve(e,t),!0)}i(A,"deleteNodeObject");async function v(e){return{nodeId:e,app:await N(e)===null?null:await
|
|
63
|
+
ORDER BY created DESC`).all(e)).map(f)}i(nt,"listResumableRoots");export*from"./tree.js";async function tt(e,n,t){return await p(async a=>{const o=await a.prepare("SELECT status, final_report, frozen_at FROM nodes WHERE node_id = ?").get(e);return o===void 0?{kind:"missing"}:n(o)?{kind:"terminal",status:o.status,final_report:o.final_report}:{kind:"ran",result:await t()}})}i(tt,"withFreshTerminalGuard");async function R(e){return await fe(e)}i(R,"hasUnreconciledManagedWorktree");async function J(e,n={}){return!["done","dead","canceled"].includes(e.status)||e.pi_pid!==null||e.frozen_at!==null||await R(e.node_id)||e.node_id===U()||W(e)?!1:n.pastTtl===!0||!["crashed","stranded",null].includes(e.terminal_reason??null)}i(J,"isCollectible");async function D(e){if(e.length===0)return[];const n=e.map(()=>"?").join(",");return(await(await s()).prepareUncached(`SELECT DISTINCT session_id FROM sessions WHERE node_id IN (${n}) AND session_id IS NOT NULL`).all(...e)).map(({session_id:a})=>a)}i(D,"nodeConversationIds");async function g(e){const n=await s(),t=n.prepare("SELECT 1 FROM sessions WHERE session_id = ? LIMIT 1"),a=n.prepare(`SELECT 1 FROM nodes n WHERE n.fork_source_file LIKE '%\\_' || ? || '.jsonl' ESCAPE '\\'
|
|
64
|
+
AND NOT EXISTS (SELECT 1 FROM sessions s WHERE s.node_id = n.node_id) LIMIT 1`);for(const o of e)if(!(await t.get(o)!==void 0||await a.get(o)!==void 0))try{await re().delete(o)}catch(r){if(!(r instanceof se))throw r}}i(g,"deleteNodeConversations");async function A(e,n){const t=await M(e,n);return t===null||t.deleted_at!==null?!1:(await ve(e,t),!0)}i(A,"deleteNodeObject");async function v(e){return{nodeId:e,app:await N(e)===null?null:await Oe(e)}}i(v,"nodeFiles");async function Y({nodeId:e,app:n}){n!==null&&j(C(n).nodes,await Le(e,n)),j(ae(H(e)),H(e))}i(Y,"removeNodeAppTrees");function Q({nodeId:e}){return[he(e)]}i(Q,"nodeOwnedDirs");function V({nodeId:e,app:n}){if(n!==null)try{ee(I(C(n).conversations,e))}catch(t){if(!["ENOENT","ENOTEMPTY"].includes(t.code??""))throw t}}i(V,"removeNodeConversationDir");async function k(e){await Y(e);for(const n of Q(e))ne(n,{recursive:!0,force:!0});V(e)}i(k,"removeNodeFiles");async function at(e){if(await R(e))return{deleted:!1};const n=await v(e),t=await D([e]),a=await p(async o=>(await A(o,e),{deleted:!0}));return await g(t),await k(n),a}i(at,"deleteNode");async function it(e){const n=[...new Set(e)];if(n.length===0)return[];const t=await y(n,R);if(t.length>0)throw new Error(`refusing to delete nodes with unreconciled managed worktrees: ${t.join(", ")}`);const a=await O(n,v),o=await D(n),r=n.map(()=>"?").join(","),d=(await(await s()).prepareUncached(`SELECT node_id FROM nodes WHERE node_id IN (${r}) ORDER BY created`).all(...n)).map(({node_id:u})=>u),l=await y(d,async u=>await p(async _=>await A(_,u)));await g(o);for(const u of l){const _=a[n.indexOf(u)];await x(_,async()=>await k(_))}return l}i(it,"deleteNodes");async function ot(e){const n=e.dryRun??!1,t=e.includeStale??!1,a=Date.now()-e.ttlDays*864e5,o=new Date(a).toISOString(),r=U()??"",d=await s(),l=i(c=>X(c)<a,"quiet"),u=i(c=>({node_id:c.node_id,status:c.status,created:c.created}),"toPruned"),_=(await y((await d.prepare(`SELECT * FROM node_rows
|
|
65
65
|
WHERE status IN ('dead', 'done', 'canceled') AND created < ?
|
|
66
|
-
ORDER BY created`).all(o)).map(f),async
|
|
66
|
+
ORDER BY created`).all(o)).map(f),async c=>await J(c,{pastTtl:!0})&&l(c)&&!await e.held(c.node_id))).map(u),S=t?(await y((await d.prepare(`SELECT * FROM node_rows
|
|
67
67
|
WHERE status IN ('active', 'idle') AND created < ?
|
|
68
|
-
ORDER BY created`).all(o)).map(f),async
|
|
68
|
+
ORDER BY created`).all(o)).map(f),async c=>c.node_id!==r&&!me(c.pi_pid??null)&&(c.frozen_at??null)===null&&(c.respawn_not_before??null)===null&&c.intent!=="idle-release"&&!W(c)&&!await de(c.node_id)&&!await R(c.node_id)&&l(c)&&!await e.held(c.node_id))).map(u):[],m=await K([..._,...S]);return n||m.length===0?{pruned:m,dryRun:n}:(await G(m,e.removeDirs),{pruned:m,dryRun:n})}i(ot,"pruneNodes");async function K(e){const t=(await s()).prepare("SELECT node_id FROM nodes WHERE run_id = ? AND node_id != ?"),a=new Set(e.map(o=>o.node_id));return await y(e,async o=>(await t.all(o.node_id,o.node_id)).every(r=>a.has(r.node_id)))}i(K,"retainRunRootsWithMembers");async function G(e,n){if(e.length===0)return;const t=await O(e,async o=>await v(o.node_id)),a=await D(e.map(o=>o.node_id));for(const o of e)await p(async r=>await A(r,o.node_id));if(await g(a),n!==void 0){for(const o of t)await x(o,async()=>{await Y(o),V(o)});n(t.flatMap(Q));return}for(const o of t)await x(o,async()=>await k(o))}i(G,"deletePrunedNodes");async function x(e,n){try{n()}catch(t){oe({level:"error",event:"canvas.node_files.remove_failed",error:t,fields:{node_id:e.nodeId}})}}i(x,"eachNodeBestEffort");function X(e){let n=0;for(const t of[e.created,e.launched_at,e.last_settled_at,e.finalized_at,e.outcome_at,e.last_activity_at]){if(t==null)continue;const a=Date.parse(t);Number.isFinite(a)&&a>n&&(n=a)}try{const t=te(I(Se(e.node_id),"telemetry.json"),{throwIfNoEntry:!1});t!==void 0&&t.mtimeMs>n&&(n=t.mtimeMs)}catch{}return n}i(X,"lastActivityMs");async function rt(e){const n=e.dryRun??!1,t=await We(),a=await y(t,async u=>await J(u)&&!await e.held(u.node_id)),o=t.length-a.length,r=Math.max(0,e.maxNodes-o),d=a.map(u=>({row:u,recency:X(u)})).sort((u,_)=>_.recency-u.recency).slice(r).map(({row:u})=>({node_id:u.node_id,status:u.status,created:u.created})),l=await K(d);return n||l.length===0?{pruned:l,dryRun:n}:(await G(l),{pruned:l,dryRun:n})}i(rt,"pruneToLimit");export{He as PARKED_RESIDENT_SQL,mn as abandonCreateRequest,ln as assertRunNotDeleting,Mn as browseNodes,Nn as canonicalSessionFile,Zn as childrenOf,Gn as claimWarmSpare,Un as clearFinalReportIfMatches,Fn as clearFrozen,yn as completeCreateRequest,cn as createNode,at as deleteNode,it as deleteNodes,On as dueNodeDeadlines,_n as findCreateRequest,Rn as findNodeBySessionFile,xn as getFinalReport,N as getNode,Sn as getRow,hn as getRowByPane,$n as graphNodes,J as isCollectible,Kn as isWarmSpare,X as lastActivityMs,Jn as listNodeIdentities,We as listNodes,Cn as listNodesByProfile,Bn as listNodesForSupervision,zn as listParkedResidentsWithWakeMail,nt as listResumableRoots,qn as listTerminalPlacementResidue,Vn as listWarmSpares,v as nodeFiles,Fe as nodesForSupervisionSql,fn as pruneExpiredCreateRequests,ot as pruneNodes,rt as pruneToLimit,En as recordCreateRequestNode,jn as recordLaunch,Hn as recordRespawnAttempt,Wn as recordSettledTurn,Yn as registerWarmSpare,k as removeNodeFiles,pn as reserveCreateRequest,wn as reserveCreateRequestNode,Dn as rewriteLocalNodeIdentity,et as rosterNodes,bn as setFrozen,vn as setIntent,Tn as setNodeDeadline,In as setPresence,An as setStatus,Ln as shiftProfileNodeDeadlines,be as terminalPlacementResidueSql,kn as transitionStatusIntent,Qn as unregisterWarmSpare,gn as updateNode,Pn as updateNodeTelemetry,Xn as warmSpareCount,tt as withFreshTerminalGuard};
|
|
@@ -23,4 +23,4 @@ CREATE TABLE IF NOT EXISTS node_faults (
|
|
|
23
23
|
);
|
|
24
24
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_node_faults_active ON node_faults(node_id) WHERE active = 1;
|
|
25
25
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_node_faults_episode ON node_faults(node_id) WHERE episode_state IS NOT NULL;
|
|
26
|
-
`)}o(me,"createFaultTable");function g(e,t){return typeof t=="string"&&e.includes(t)}o(g,"contains");function b(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(b,"isRecord");function K(e){if(!b(e)||typeof e.provider!="string"||e.provider===""||typeof e.model!="string"||e.model==="")return;const t=typeof e.status=="number"&&Number.isFinite(e.status)?e.status:void 0,n=typeof e.code=="string"||typeof e.code=="number"?e.code:void 0,r=typeof e.errno=="string"?e.errno:void 0,i=typeof e.body=="string"?e.body:void 0,s=le(e.ratelimit),d=Array.isArray(e.causes)?e.causes.flatMap(a=>{if(!b(a))return[];const E={...typeof a.message=="string"?{message:a.message}:{},...typeof a.status=="number"&&Number.isFinite(a.status)?{status:a.status}:{},...typeof a.code=="string"||typeof a.code=="number"?{code:a.code}:{},...typeof a.errno=="string"?{errno:a.errno}:{},...typeof a.body=="string"?{body:a.body}:{}};return Object.keys(E).length===0?[]:[E]}):void 0;return{provider:e.provider,model:e.model,...t===void 0?{}:{status:t},...n===void 0?{}:{code:n},...r===void 0?{}:{errno:r},...i===void 0?{}:{body:i},...d===void 0||d.length===0?{}:{causes:d},...s===void 0?{}:{ratelimit:s}}}o(K,"parseProviderError");function Y(e){try{const t=JSON.parse(e);if(!g(fe,t.link)||typeof t.op!="string"||t.op===""||!g(ye,t.kind)||typeof t.message!="string"||typeof t.since!="string")return null;const n=B(t.operation_id);if(!b(t.retry)||!g(Te,t.retry.disposition)||t.retry.by!==void 0&&!g(Ne,t.retry.by)||t.retry.attempt!==void 0&&typeof t.retry.attempt!="number"||t.retry.max!==void 0&&typeof t.retry.max!="number"||t.retry.nextAt!==void 0&&typeof t.retry.nextAt!="string"||t.anchorEntryId!==void 0&&(typeof t.anchorEntryId!="string"||t.anchorEntryId===""))return null;const r=t.providerError===void 0?void 0:K(t.providerError);return t.providerError!==void 0&&r===void 0?null:{link:t.link,op:t.op,kind:t.kind,retry:{disposition:t.retry.disposition,...t.retry.by===void 0?{}:{by:t.retry.by},...t.retry.attempt===void 0?{}:{attempt:t.retry.attempt},...t.retry.max===void 0?{}:{max:t.retry.max},...t.retry.nextAt===void 0?{}:{nextAt:t.retry.nextAt}},message:t.message,since:t.since,operation_id:n,...t.anchorEntryId===void 0?{}:{anchorEntryId:t.anchorEntryId},...r===void 0?{}:{providerError:r}}}catch{return null}}o(Y,"parseLegacyFault");function Ae(e){const t=_e(e);try{return ue(t)}catch{return t}}o(Ae,"canonicalPath");function Se(e){try{const t=JSON.parse(e);if(!g(ge,t.state)||typeof t.sessionFile!="string"||t.sessionFile==="")return null;const n=JSON.stringify(t.fault),r=Y(n);if(r===null||r.link!=="pi\u2192provider"||r.retry.disposition!=="auto"||r.retry.by!=="daemon")return null;const i=t.anchorEntryId;return i!==null&&typeof i!="string"||(r.anchorEntryId??null)!==i?null:{state:t.state,sessionFile:Ae(t.sessionFile),fault:r}}catch{return null}}o(Se,"parseLegacyEpisode");function G(e){return e!==void 0?B(e):j.current()??j.fresh(n=>n)}o(G,"resolveOperationId");function xe(e){return e.slice(0,Ee)}o(xe,"clampMessage");function w(e){return e.link==="pi\u2192provider"&&e.retry.disposition==="auto"&&e.retry.by==="daemon"?3:e.retry.disposition==="fatal"?2:1}o(w,"faultPriority");function q(e){return{link:e.link,op:e.op,kind:e.kind,message:e.message,since:e.since,operationId:e.operation_id,anchorEntryId:e.anchorEntryId??null,retryDisposition:e.retry.disposition,retryBy:e.retry.by??null,retryAttempt:e.retry.attempt??null,retryMax:e.retry.max??null,retryNextAt:e.retry.nextAt??null,providerError:e.providerError===void 0?null:JSON.stringify(e.providerError)}}o(q,"encodeFault");function H(e){const t=e.provider_error_json,n=typeof t=="string"?K(JSON.parse(t)):void 0;if(typeof t=="string"&&n===void 0)throw new Error(`invalid provider error on stored fault ${e.fault_id}`);const r={disposition:e.retry_disposition,...e.retry_by===null?{}:{by:e.retry_by},...e.retry_attempt===null?{}:{attempt:e.retry_attempt},...e.retry_max===null?{}:{max:e.retry_max},...e.retry_next_at===null?{}:{nextAt:e.retry_next_at}};return{faultId:e.fault_id,link:e.link,op:e.op,kind:e.kind,message:e.message,since:e.since,operation_id:e.operation_id,retry:r,...e.anchor_entry_id===null?{}:{anchorEntryId:e.anchor_entry_id},...n===void 0?{}:{providerError:n},...typeof e.notified_since=="string"?{notifiedSince:e.notified_since}:{}}}o(H,"hydrateFault");async function L(e,t){const n=await e.prepare("SELECT * FROM node_faults WHERE node_id = ? AND active = 1").get(t);return n===void 0?null:H(n)}o(L,"activeFault");function V(e){if(!g(J,e.link))throw new Error(`fault link is not durable: ${e.link}`);return{link:e.link,op:e.op,kind:e.kind,retry:e.retry,message:xe(e.message),since:e.since??u(),operation_id:G(e.operation_id),...typeof e.anchorEntryId=="string"&&e.anchorEntryId!==""?{anchorEntryId:e.anchorEntryId}:{},...e.providerError===void 0?{}:{providerError:e.providerError}}}o(V,"storedFault");function Q(e,t){$({level:t.retry.disposition==="fatal"?"error":"warn",event:"fault.recorded",operation_id:t.operation_id,node_id:e,error_class:X(t),fields:{link:t.link,op:t.op,kind:t.kind,retry:t.retry,message:t.message,...t.anchorEntryId===void 0?{}:{anchor_entry_id:t.anchorEntryId},...t.providerError===void 0?{}:{provider_error:t.providerError}}})}o(Q,"emitRecordedFault");const z="INSERT INTO node_faults (fault_id, node_id, link, op, kind, message, since, operation_id, anchor_entry_id, retry_disposition, retry_by, retry_attempt, retry_max, retry_next_at, provider_error_json, active, episode_state, episode_binding_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";function Z(e,t,n,r,i){const s=q(n),d=u();return[e,t,s.link,s.op,s.kind,s.message,s.since,s.operationId,s.anchorEntryId,s.retryDisposition,s.retryBy,s.retryAttempt,s.retryMax,s.retryNextAt,s.providerError,r?1:0,i?.state??null,i?.bindingId??null,d,d]}o(Z,"faultInsertParams");async function ee(e,t,n,r,i){const s=I();return await e.prepare(z).run(...Z(s,t,n,r,i)),{...n,faultId:s}}o(ee,"insertFault");async function te(e,t,n,r){const i=q(n);return await e.prepare("UPDATE node_faults SET link = ?, op = ?, kind = ?, message = ?, since = ?, operation_id = ?, anchor_entry_id = ?, retry_disposition = ?, retry_by = ?, retry_attempt = ?, retry_max = ?, retry_next_at = ?, provider_error_json = ?, episode_state = COALESCE(?, episode_state), episode_binding_id = COALESCE(?, episode_binding_id), updated_at = ? WHERE fault_id = ?").run(i.link,i.op,i.kind,i.message,i.since,i.operationId,i.anchorEntryId,i.retryDisposition,i.retryBy,i.retryAttempt,i.retryMax,i.retryNextAt,i.providerError,r?.state??null,r?.bindingId??null,u(),t),{...n,faultId:t}}o(te,"updateFault");async function D(e,t){await e.prepare("DELETE FROM node_faults WHERE fault_id = ? AND active = 0 AND episode_state IS NULL").run(t)}o(D,"deleteIfUnretained");async function ne(e,t,n,r){const i=await L(e,t);if(i===null){const s=await e.prepare("SELECT fault_id, link, kind, since, operation_id FROM node_faults WHERE node_id = ? AND active = 0 AND episode_state IS NOT NULL").get(t);return s!==void 0&&s.link===n.link&&s.kind===n.kind&&s.since===n.since&&s.operation_id===n.operation_id?(await e.prepare("UPDATE node_faults SET active = 1, updated_at = ? WHERE fault_id = ?").run(u(),s.fault_id),await te(e,s.fault_id,n)):await ee(e,t,n,!0,r)}if(i.link===n.link&&i.kind===n.kind){const s=n.retry.disposition==="auto"?{...i.retry,...n.retry}:n.retry,d=i.retry.disposition===n.retry.disposition&&(n.retry.disposition!=="fatal"||i.message===n.message),a=d?i.since:n.since,E=await te(e,i.faultId,{...n,since:a,anchorEntryId:i.anchorEntryId??n.anchorEntryId,retry:s},r);return d||await e.prepare("UPDATE node_faults SET notified_since = NULL WHERE fault_id = ?").run(i.faultId),E}return i.link!==n.link&&w(i)>w(n)?null:(await e.prepare("UPDATE node_faults SET active = 0, updated_at = ? WHERE fault_id = ?").run(u(),i.faultId),await D(e,i.faultId),await ee(e,t,n,!0,r))}o(ne,"replaceActiveFault");async function m(e,t,n){return(await e.prepare("SELECT binding_id FROM sessions WHERE node_id = ? AND session_id = ? AND unbound_at IS NULL").get(t,n))?.binding_id??null}o(m,"liveBinding");async function Xe(e,t){return await l(async n=>{const r=u();return(await n.prepare("UPDATE executions SET turn_progress_at = ? WHERE execution_id = ? AND state != 'exited' AND turn_open_at IS NOT NULL AND turn_closed_at IS NULL").run(r,e)).changes>0?!0:(await n.prepare("UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = NULL, turn_end_reason = NULL WHERE execution_id = ? AND state != 'exited'").run(r,r,e)).changes>0})}o(Xe,"openTurn");async function $e(e){return(await(await p()).prepare("UPDATE executions SET turn_progress_at = ? WHERE execution_id = ? AND state != 'exited' AND turn_open_at IS NOT NULL AND turn_closed_at IS NULL").run(u(),e)).changes>0}o($e,"recordTurnProgress");async function je(e,t){return await l(async n=>{const r=u(),i=(await n.prepare("UPDATE executions SET turn_closed_at = ?, turn_end_reason = ? WHERE execution_id = ? AND state != 'exited' AND turn_open_at IS NOT NULL AND turn_closed_at IS NULL").run(r,t.endReason,e)).changes>0;if(i&&t.endReason==="settled"){const s="(SELECT node_id FROM executions WHERE execution_id = ?)";t.viewerPresent===!0?await n.prepare(`UPDATE nodes SET reply_at = ?, read_at = ? WHERE node_id = ${s}`).run(r,r,e):await n.prepare(`UPDATE nodes SET reply_at = ? WHERE node_id = ${s}`).run(r,e)}return i})}o(je,"closeTurn");async function Be(e){return(await(await p()).prepare("UPDATE nodes SET read_at = ? WHERE node_id = ?").run(u(),e)).changes>0}o(Be,"markNodeRead");async function Je(e,t){if(!Number.isInteger(t.consecutivePasses)||t.consecutivePasses<1||t.routes.length===0||!t.routes.every(n=>n!==""))throw new Error("invalid transport-poison verdict");return(await(await p()).prepare("UPDATE executions SET exit_diagnostic_json = ? WHERE execution_id = ? AND state != 'exited'").run(JSON.stringify({schema:"crtr.execution-exit-diagnostic/v1",transport_poison:{consecutive_passes:t.consecutivePasses,routes:t.routes}}),e)).changes>0}o(Je,"recordTransportPoisonVerdict");async function Ke(e){const t=await(await p()).prepare("SELECT exit_diagnostic_json FROM executions WHERE node_id = ? ORDER BY seq DESC LIMIT 1").get(e);if(t===void 0||t.exit_diagnostic_json===null)return null;try{const n=JSON.parse(t.exit_diagnostic_json),r=n.transport_poison;return n.schema!=="crtr.execution-exit-diagnostic/v1"||r===void 0||!Number.isInteger(r.consecutive_passes)||r.consecutive_passes<1||!Array.isArray(r.routes)||r.routes.length===0||!r.routes.every(i=>typeof i=="string"&&i!=="")?null:{consecutivePasses:r.consecutive_passes,routes:r.routes}}catch{return null}}o(Ke,"readTransportPoisonVerdict");async function Ye(e){const t=await(await p()).prepare("SELECT turn_open_at, turn_closed_at, turn_progress_at FROM executions WHERE node_id = ? AND state != 'exited'").get(e);return t===void 0?null:{busy:t.turn_open_at!==null&&t.turn_closed_at===null,progressAt:t.turn_progress_at}}o(Ye,"readLiveTurn");async function Ge(e){const t=await p(),n=await t.prepare("SELECT turn_closed_at, turn_progress_at FROM executions WHERE node_id = ? AND turn_open_at IS NOT NULL ORDER BY seq DESC LIMIT 1").get(e);if(n===void 0)return null;const r=await t.prepare("SELECT turn_end_reason FROM executions WHERE node_id = ? ORDER BY seq DESC LIMIT 1").get(e);return{interrupted:n.turn_closed_at===null||r?.turn_end_reason==="teardown-aborted",progressAt:n.turn_progress_at}}o(Ge,"readInterruptedTurn");async function qe(e){return await(await p()).prepare("SELECT 1 FROM executions WHERE node_id = ? AND turn_open_at IS NOT NULL LIMIT 1").get(e)!==void 0}o(qe,"hasAdmittedTurn");async function Ve(e,t){const n=V(t);return Q(e,n),await l(async r=>await ne(r,e,n))}o(Ve,"recordFault");async function Qe(e){return await l(async t=>(await t.prepare("UPDATE node_faults SET notified_since = since, updated_at = ? WHERE fault_id = ?").run(u(),e)).changes>0)}o(Qe,"markFaultNotified");function Re(e){return e.link==="pi\u2192provider"&&e.retry.disposition==="fatal"&&e.notifiedSince!==e.since}o(Re,"isUnnotifiedFatalProviderFault");async function ze(){return(await(await p()).prepare("SELECT f.node_id FROM node_faults f JOIN nodes n ON n.node_id = f.node_id WHERE f.active = 1 AND f.link = 'pi\u2192provider' AND f.retry_disposition = 'fatal' AND (f.notified_since IS NULL OR f.notified_since != f.since) AND n.status IN ('active', 'idle')").all()).map(e=>e.node_id)}o(ze,"listUnnotifiedFatalFaultNodes");let W=null;function Ze(e){W=e}o(Ze,"setFatalFaultAnnouncer");async function et(e,t){const n=await L(await p(),e);return n===null||t?.link!==void 0&&n.link!==t.link?!1:await l(async r=>{const i=await L(r,e);if(i===null||t?.link!==void 0&&i.link!==t.link)return!1;W!==null&&Re(i)&&await W(e);const s=await r.prepare("SELECT episode_state FROM node_faults WHERE fault_id = ?").get(i.faultId);await r.prepare("UPDATE node_faults SET active = 0, updated_at = ? WHERE fault_id = ?").run(u(),i.faultId),s.episode_state==="pending"&&t?.preserveEpisode!==!0&&await r.prepare("UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE fault_id = ?").run(u(),i.faultId),await D(r,i.faultId);const d=G();return $({level:"info",event:"fault.cleared",operation_id:d,node_id:e,error_class:X(i),fields:{cleared_fault_operation_id:i.operation_id,link:i.link,op:i.op,kind:i.kind,retry:i.retry,message:i.message,since:i.since,...i.anchorEntryId===void 0?{}:{anchor_entry_id:i.anchorEntryId}}}),!0})}o(et,"clearFault");async function re(e){return await L(await p(),e)}o(re,"readFault");async function tt(e,t){const n=V(t.input);if(n.link!=="pi\u2192provider"||n.retry.disposition!=="auto"||n.retry.by!=="daemon")throw new Error("provider retry episode requires an automatic daemon provider fault");return Q(e,n),await l(async r=>{const i=await m(r,e,t.sessionId);if(i===null)return null;const s=await L(r,e);if(s!==null&&(s.link!==n.link||s.kind!==n.kind)&&w(s)>w(n))return null;const d=await r.prepare("SELECT fault_id FROM node_faults WHERE node_id = ? AND episode_state IS NOT NULL").all(e);await r.prepare("UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE node_id = ? AND episode_state IS NOT NULL").run(u(),e);for(const E of d)await D(r,E.fault_id);const a=await ne(r,e,n,{state:"pending",bindingId:i});return a===null?null:(await r.prepare("UPDATE node_faults SET episode_state = ?, episode_binding_id = ?, updated_at = ? WHERE fault_id = ?").run("pending",i,u(),a.faultId),a)})}o(tt,"recordPendingEpisode");async function nt(e,t){return await l(async n=>{if(await n.prepare("SELECT 1 FROM nodes WHERE node_id = ? AND intent = 'refresh'").get(e)!==void 0)return!1;const r=await m(n,e,t.sessionId);return r===null?!1:(await n.prepare("UPDATE node_faults SET episode_state = 'admitted', retry_disposition = ?, retry_by = ?, retry_attempt = ?, retry_max = ?, retry_next_at = ?, updated_at = ? WHERE node_id = ? AND fault_id = ? AND episode_state = 'pending' AND episode_binding_id = ?").run(t.retry.disposition,t.retry.by??null,t.retry.attempt??null,t.retry.max??null,t.retry.nextAt??null,u(),e,t.faultId,r)).changes>0})}o(nt,"admitEpisode");async function rt(e,t){return await l(async n=>{const r=await m(n,e,t.sessionId);return r===null?!1:(await n.prepare("UPDATE node_faults SET episode_state = 'pending', updated_at = ? WHERE node_id = ? AND episode_state = 'admitted' AND episode_binding_id = ?").run(u(),e,r)).changes>0})}o(rt,"reopenEpisode");async function it(e,t){return await l(async n=>{const r=await m(n,e,t.sessionId);return r===null?!1:(await n.prepare("UPDATE node_faults SET episode_state = 'invalidated', updated_at = ? WHERE node_id = ? AND episode_state != 'invalidated' AND episode_state IS NOT NULL AND episode_binding_id = ?").run(u(),e,r)).changes>0})}o(it,"invalidateEpisode");async function ot(e,t){return await l(async n=>{const r=await m(n,e,t.sessionId);if(r===null)return!1;const i=await n.prepare("SELECT fault_id FROM node_faults WHERE node_id = ? AND episode_binding_id = ? AND episode_state IS NOT NULL").all(e,r);if(i.length===0)return!1;await n.prepare("UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE node_id = ? AND episode_binding_id = ? AND episode_state IS NOT NULL").run(u(),e,r);for(const s of i)await D(n,s.fault_id);return!0})}o(ot,"clearEpisode");async function st(e){const t=await(await p()).prepare("SELECT f.*, s.session_id FROM node_faults f JOIN sessions s ON s.binding_id = f.episode_binding_id WHERE f.node_id = ? AND f.episode_state IS NOT NULL").get(e);return t===void 0?null:{state:t.episode_state,sessionId:t.session_id,fault:H(t)}}o(st,"readEpisode");async function at(){return(await(await p()).prepare("SELECT f.*, s.session_id AS bound_session_id FROM node_faults f JOIN sessions s ON s.binding_id = f.episode_binding_id WHERE f.active = 1 AND f.episode_state = 'pending' AND s.unbound_at IS NULL AND s.session_id IS NOT NULL AND f.link = 'pi\u2192provider' AND f.retry_disposition = 'auto' AND f.retry_by = 'daemon' AND f.kind IN ('connection', 'rate-limit', 'overloaded')").all()).map(t=>({nodeId:t.node_id,sessionId:t.bound_session_id,fault:H(t),updatedAt:t.updated_at}))}o(at,"listPendingProviderRetries");async function dt(e){const t=await re(e)===null;return{async explanation(){if(!t)return null;const n=await re(e);if(n===null||n.link!=="crtr\u2192pi"||n.retry.disposition!=="fatal")return null;const r=n.op.trim(),i=n.message.trim();return r===""||i===""?null:`${r}: ${i}`}}}o(dt,"beginBootFaultAttempt");function ie(e,t){try{return ce(e).mtime.toISOString()}catch{return t}}o(ie,"markerMtime");function P(e,t){if(!f(e))return null;try{return de(e,"utf8")}catch(n){if(!t)return null;throw new Error(`cannot import recovery input ${e}: ${n.message}`)}}o(P,"legacyFile");function Ie(e,t){return _(e,"SELECT execution_id, started_at FROM executions WHERE node_id = ? ORDER BY rowid DESC LIMIT 1").get(t)??null}o(Ie,"latestExecution");function we(e,t){const r=C(e,"nodes").has("launched_at")?_(e,"SELECT COALESCE(launched_at, created) AS started_at FROM nodes WHERE node_id = ?").get(t):_(e,"SELECT created AS started_at FROM nodes WHERE node_id = ?").get(t);if(r===void 0)throw new Error(`cannot import recovery witness for unknown node ${t}`);const i=I();return _(e,"INSERT INTO executions (execution_id, node_id, daemon_epoch, pid, process_identity, state, started_at, ended_at, exit_reason) VALUES (?, ?, NULL, NULL, NULL, 'exited', ?, ?, 'pre-consolidation')").run(i,t,r.started_at,r.started_at),{execution_id:i,started_at:r.started_at}}o(we,"syntheticExecution");function oe(e,t,n,r,i){const s=I();return _(e,z).run(...Z(s,t,n,r,i)),{...n,faultId:s}}o(oe,"insertMigratedFault");function De(e,t,n,r){const i=_(e,"SELECT binding_id, node_id FROM sessions WHERE transcript_path = ? AND unbound_at IS NULL").get(n);if(i!==void 0){if(i.node_id!==t)throw new Error(`cannot import provider retry ${r}: transcript is live-owned by ${i.node_id}`);return i.binding_id}const s=_(e,"SELECT binding_id FROM sessions WHERE node_id = ? AND transcript_path = ? ORDER BY rowid DESC LIMIT 1").get(t,n);if(s!==void 0)return s.binding_id;const d=_(e,"SELECT created FROM nodes WHERE node_id = ?").get(t);if(d===void 0)throw new Error(`cannot import provider retry ${r}: unknown node ${t}`);const a=I();return _(e,"INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at, unbound_at) VALUES (?, NULL, ?, ?, NULL, NULL, ?, ?, ?)").run(a,t,n,d.created,d.created,u()),a}o(De,"migrationBinding");function ut(e){e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'node_faults'").get()!==void 0&&(C(e,"node_faults").has("notified_since")||e.exec("ALTER TABLE node_faults ADD COLUMN notified_since TEXT"))}o(ut,"addFaultNotifiedSince");function ct(e){if(Le(e),me(e),!f(F()))return;const t=ae(F(),{withFileTypes:!0}).filter(r=>r.isDirectory()).sort((r,i)=>r.name.localeCompare(i.name)),n=_(e,"SELECT 1 FROM nodes WHERE node_id = ?");for(const r of t){const i=r.name,s=pe(i),d=N(s,"busy"),a=N(s,"clean-abort"),E=N(s,"transport-poison.json"),U=N(s,"fault"),A=N(s,"provider-retry"),O=f(d),h=f(a);if(!O&&!h&&!f(E)&&!f(U)&&!f(A)||!f(N(F(),i,"meta.json"))&&n.get(i)===void 0)continue;const k=P(E,!1),S=P(U,!0),x=P(A,!0);if(!O&&!h&&k===null&&S===null&&x===null)continue;let y=Ie(e,i);if(y===null&&(y=we(e,i)),O){const c=ie(d,y.started_at);_(e,"UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = NULL, turn_end_reason = NULL WHERE execution_id = ?").run(c,c,y.execution_id)}else if(h){const c=ie(a,y.started_at);_(e,"UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = ?, turn_end_reason = 'teardown-aborted' WHERE execution_id = ?").run(c,c,c,y.execution_id)}if(k!==null)try{const c=JSON.parse(k);Number.isInteger(c.consecutivePasses)&&c.consecutivePasses>=1&&Array.isArray(c.routes)&&c.routes.length>0&&c.routes.every(M=>typeof M=="string"&&M!=="")&&_(e,"UPDATE executions SET exit_diagnostic_json = ? WHERE execution_id = ?").run(JSON.stringify({schema:"crtr.execution-exit-diagnostic/v1",transport_poison:{consecutive_passes:c.consecutivePasses,routes:c.routes}}),y.execution_id)}catch{}const R=S===null?null:Y(S);if(S!==null&&R===null)throw new Error(`cannot import recovery fault ${U}`);const T=x===null?null:Se(x);if(x!==null&&T===null)throw new Error(`cannot import provider retry ${A}`);let v=R===null||R.link==="broker\u2194crtrd"?null:oe(e,i,R,!0);if(T!==null){const c=De(e,i,T.sessionFile,A);v!==null&&v.since===T.fault.since?_(e,"UPDATE node_faults SET episode_state = ?, episode_binding_id = ?, updated_at = ? WHERE fault_id = ?").run(T.state,c,u(),v.faultId):oe(e,i,T.fault,!1,{state:T.state,bindingId:c})}}}o(ct,"migrateRecoveryWitnesses");export{Me as FAULT_QUIET_MS,ut as addFaultNotifiedSince,nt as admitEpisode,dt as beginBootFaultAttempt,ot as clearEpisode,et as clearFault,je as closeTurn,qe as hasAdmittedTurn,H as hydrateFault,it as invalidateEpisode,at as listPendingProviderRetries,ze as listUnnotifiedFatalFaultNodes,Qe as markFaultNotified,Be as markNodeRead,ct as migrateRecoveryWitnesses,Xe as openTurn,K as parseProviderError,st as readEpisode,re as readFault,Ge as readInterruptedTurn,Ye as readLiveTurn,Ke as readTransportPoisonVerdict,Ve as recordFault,tt as recordPendingEpisode,Je as recordTransportPoisonVerdict,$e as recordTurnProgress,rt as reopenEpisode,Ze as setFatalFaultAnnouncer};
|
|
26
|
+
`)}o(me,"createFaultTable");function g(e,t){return typeof t=="string"&&e.includes(t)}o(g,"contains");function b(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(b,"isRecord");function K(e){if(!b(e)||typeof e.provider!="string"||e.provider===""||typeof e.model!="string"||e.model==="")return;const t=typeof e.status=="number"&&Number.isFinite(e.status)?e.status:void 0,n=typeof e.code=="string"||typeof e.code=="number"?e.code:void 0,r=typeof e.errno=="string"?e.errno:void 0,i=typeof e.body=="string"?e.body:void 0,s=le(e.ratelimit),d=Array.isArray(e.causes)?e.causes.flatMap(a=>{if(!b(a))return[];const E={...typeof a.message=="string"?{message:a.message}:{},...typeof a.status=="number"&&Number.isFinite(a.status)?{status:a.status}:{},...typeof a.code=="string"||typeof a.code=="number"?{code:a.code}:{},...typeof a.errno=="string"?{errno:a.errno}:{},...typeof a.body=="string"?{body:a.body}:{}};return Object.keys(E).length===0?[]:[E]}):void 0;return{provider:e.provider,model:e.model,...t===void 0?{}:{status:t},...n===void 0?{}:{code:n},...r===void 0?{}:{errno:r},...i===void 0?{}:{body:i},...d===void 0||d.length===0?{}:{causes:d},...s===void 0?{}:{ratelimit:s}}}o(K,"parseProviderError");function Y(e){try{const t=JSON.parse(e);if(!g(fe,t.link)||typeof t.op!="string"||t.op===""||!g(ye,t.kind)||typeof t.message!="string"||typeof t.since!="string")return null;const n=B(t.operation_id);if(!b(t.retry)||!g(Te,t.retry.disposition)||t.retry.by!==void 0&&!g(Ne,t.retry.by)||t.retry.attempt!==void 0&&typeof t.retry.attempt!="number"||t.retry.max!==void 0&&typeof t.retry.max!="number"||t.retry.nextAt!==void 0&&typeof t.retry.nextAt!="string"||t.anchorEntryId!==void 0&&(typeof t.anchorEntryId!="string"||t.anchorEntryId===""))return null;const r=t.providerError===void 0?void 0:K(t.providerError);return t.providerError!==void 0&&r===void 0?null:{link:t.link,op:t.op,kind:t.kind,retry:{disposition:t.retry.disposition,...t.retry.by===void 0?{}:{by:t.retry.by},...t.retry.attempt===void 0?{}:{attempt:t.retry.attempt},...t.retry.max===void 0?{}:{max:t.retry.max},...t.retry.nextAt===void 0?{}:{nextAt:t.retry.nextAt}},message:t.message,since:t.since,operation_id:n,...t.anchorEntryId===void 0?{}:{anchorEntryId:t.anchorEntryId},...r===void 0?{}:{providerError:r}}}catch{return null}}o(Y,"parseLegacyFault");function Ae(e){const t=_e(e);try{return ue(t)}catch{return t}}o(Ae,"canonicalPath");function Se(e){try{const t=JSON.parse(e);if(!g(ge,t.state)||typeof t.sessionFile!="string"||t.sessionFile==="")return null;const n=JSON.stringify(t.fault),r=Y(n);if(r===null||r.link!=="pi\u2192provider"||r.retry.disposition!=="auto"||r.retry.by!=="daemon")return null;const i=t.anchorEntryId;return i!==null&&typeof i!="string"||(r.anchorEntryId??null)!==i?null:{state:t.state,sessionFile:Ae(t.sessionFile),fault:r}}catch{return null}}o(Se,"parseLegacyEpisode");function G(e){return e!==void 0?B(e):j.current()??j.fresh(n=>n)}o(G,"resolveOperationId");function xe(e){return e.slice(0,Ee)}o(xe,"clampMessage");function w(e){return e.link==="pi\u2192provider"&&e.retry.disposition==="auto"&&e.retry.by==="daemon"?3:e.retry.disposition==="fatal"?2:1}o(w,"faultPriority");function q(e){return{link:e.link,op:e.op,kind:e.kind,message:e.message,since:e.since,operationId:e.operation_id,anchorEntryId:e.anchorEntryId??null,retryDisposition:e.retry.disposition,retryBy:e.retry.by??null,retryAttempt:e.retry.attempt??null,retryMax:e.retry.max??null,retryNextAt:e.retry.nextAt??null,providerError:e.providerError===void 0?null:JSON.stringify(e.providerError)}}o(q,"encodeFault");function H(e){const t=e.provider_error_json,n=typeof t=="string"?K(JSON.parse(t)):void 0;if(typeof t=="string"&&n===void 0)throw new Error(`invalid provider error on stored fault ${e.fault_id}`);const r={disposition:e.retry_disposition,...e.retry_by===null?{}:{by:e.retry_by},...e.retry_attempt===null?{}:{attempt:e.retry_attempt},...e.retry_max===null?{}:{max:e.retry_max},...e.retry_next_at===null?{}:{nextAt:e.retry_next_at}};return{faultId:e.fault_id,link:e.link,op:e.op,kind:e.kind,message:e.message,since:e.since,operation_id:e.operation_id,retry:r,...e.anchor_entry_id===null?{}:{anchorEntryId:e.anchor_entry_id},...n===void 0?{}:{providerError:n},...typeof e.notified_since=="string"?{notifiedSince:e.notified_since}:{}}}o(H,"hydrateFault");async function L(e,t){const n=await e.prepare("SELECT * FROM node_faults WHERE node_id = ? AND active = 1").get(t);return n===void 0?null:H(n)}o(L,"activeFault");function V(e){if(!g(J,e.link))throw new Error(`fault link is not durable: ${e.link}`);return{link:e.link,op:e.op,kind:e.kind,retry:e.retry,message:xe(e.message),since:e.since??u(),operation_id:G(e.operation_id),...typeof e.anchorEntryId=="string"&&e.anchorEntryId!==""?{anchorEntryId:e.anchorEntryId}:{},...e.providerError===void 0?{}:{providerError:e.providerError}}}o(V,"storedFault");function Q(e,t){$({level:t.retry.disposition==="fatal"?"error":"warn",event:"fault.recorded",operation_id:t.operation_id,node_id:e,error_class:X(t),fields:{link:t.link,op:t.op,kind:t.kind,retry:t.retry,message:t.message,...t.anchorEntryId===void 0?{}:{anchor_entry_id:t.anchorEntryId},...t.providerError===void 0?{}:{provider_error:t.providerError}}})}o(Q,"emitRecordedFault");const z="INSERT INTO node_faults (fault_id, node_id, link, op, kind, message, since, operation_id, anchor_entry_id, retry_disposition, retry_by, retry_attempt, retry_max, retry_next_at, provider_error_json, active, episode_state, episode_binding_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";function Z(e,t,n,r,i){const s=q(n),d=u();return[e,t,s.link,s.op,s.kind,s.message,s.since,s.operationId,s.anchorEntryId,s.retryDisposition,s.retryBy,s.retryAttempt,s.retryMax,s.retryNextAt,s.providerError,r?1:0,i?.state??null,i?.bindingId??null,d,d]}o(Z,"faultInsertParams");async function ee(e,t,n,r,i){const s=I();return await e.prepare(z).run(...Z(s,t,n,r,i)),{...n,faultId:s}}o(ee,"insertFault");async function te(e,t,n,r){const i=q(n);return await e.prepare("UPDATE node_faults SET link = ?, op = ?, kind = ?, message = ?, since = ?, operation_id = ?, anchor_entry_id = ?, retry_disposition = ?, retry_by = ?, retry_attempt = ?, retry_max = ?, retry_next_at = ?, provider_error_json = ?, episode_state = COALESCE(?, episode_state), episode_binding_id = COALESCE(?, episode_binding_id), updated_at = ? WHERE fault_id = ?").run(i.link,i.op,i.kind,i.message,i.since,i.operationId,i.anchorEntryId,i.retryDisposition,i.retryBy,i.retryAttempt,i.retryMax,i.retryNextAt,i.providerError,r?.state??null,r?.bindingId??null,u(),t),{...n,faultId:t}}o(te,"updateFault");async function D(e,t){await e.prepare("DELETE FROM node_faults WHERE fault_id = ? AND active = 0 AND episode_state IS NULL").run(t)}o(D,"deleteIfUnretained");async function ne(e,t,n,r){const i=await L(e,t);if(i===null){const s=await e.prepare("SELECT fault_id, link, kind, since, operation_id FROM node_faults WHERE node_id = ? AND active = 0 AND episode_state IS NOT NULL").get(t);return s!==void 0&&s.link===n.link&&s.kind===n.kind&&s.since===n.since&&s.operation_id===n.operation_id?(await e.prepare("UPDATE node_faults SET active = 1, updated_at = ? WHERE fault_id = ?").run(u(),s.fault_id),await te(e,s.fault_id,n)):await ee(e,t,n,!0,r)}if(i.link===n.link&&i.kind===n.kind){const s=n.retry.disposition==="auto"?{...i.retry,...n.retry}:n.retry,d=i.retry.disposition===n.retry.disposition&&(n.retry.disposition!=="fatal"||i.message===n.message),a=d?i.since:n.since,E=await te(e,i.faultId,{...n,since:a,anchorEntryId:n.anchorEntryId??i.anchorEntryId,retry:s},r);return d||await e.prepare("UPDATE node_faults SET notified_since = NULL WHERE fault_id = ?").run(i.faultId),E}return i.link!==n.link&&w(i)>w(n)?null:(await e.prepare("UPDATE node_faults SET active = 0, updated_at = ? WHERE fault_id = ?").run(u(),i.faultId),await D(e,i.faultId),await ee(e,t,n,!0,r))}o(ne,"replaceActiveFault");async function m(e,t,n){return(await e.prepare("SELECT binding_id FROM sessions WHERE node_id = ? AND session_id = ? AND unbound_at IS NULL").get(t,n))?.binding_id??null}o(m,"liveBinding");async function Xe(e,t){return await l(async n=>{const r=u();return(await n.prepare("UPDATE executions SET turn_progress_at = ? WHERE execution_id = ? AND state != 'exited' AND turn_open_at IS NOT NULL AND turn_closed_at IS NULL").run(r,e)).changes>0?!0:(await n.prepare("UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = NULL, turn_end_reason = NULL WHERE execution_id = ? AND state != 'exited'").run(r,r,e)).changes>0})}o(Xe,"openTurn");async function $e(e){return(await(await p()).prepare("UPDATE executions SET turn_progress_at = ? WHERE execution_id = ? AND state != 'exited' AND turn_open_at IS NOT NULL AND turn_closed_at IS NULL").run(u(),e)).changes>0}o($e,"recordTurnProgress");async function je(e,t){return await l(async n=>{const r=u(),i=(await n.prepare("UPDATE executions SET turn_closed_at = ?, turn_end_reason = ? WHERE execution_id = ? AND state != 'exited' AND turn_open_at IS NOT NULL AND turn_closed_at IS NULL").run(r,t.endReason,e)).changes>0;if(i&&t.endReason==="settled"){const s="(SELECT node_id FROM executions WHERE execution_id = ?)";t.viewerPresent===!0?await n.prepare(`UPDATE nodes SET reply_at = ?, read_at = ? WHERE node_id = ${s}`).run(r,r,e):await n.prepare(`UPDATE nodes SET reply_at = ? WHERE node_id = ${s}`).run(r,e)}return i})}o(je,"closeTurn");async function Be(e){return(await(await p()).prepare("UPDATE nodes SET read_at = ? WHERE node_id = ?").run(u(),e)).changes>0}o(Be,"markNodeRead");async function Je(e,t){if(!Number.isInteger(t.consecutivePasses)||t.consecutivePasses<1||t.routes.length===0||!t.routes.every(n=>n!==""))throw new Error("invalid transport-poison verdict");return(await(await p()).prepare("UPDATE executions SET exit_diagnostic_json = ? WHERE execution_id = ? AND state != 'exited'").run(JSON.stringify({schema:"crtr.execution-exit-diagnostic/v1",transport_poison:{consecutive_passes:t.consecutivePasses,routes:t.routes}}),e)).changes>0}o(Je,"recordTransportPoisonVerdict");async function Ke(e){const t=await(await p()).prepare("SELECT exit_diagnostic_json FROM executions WHERE node_id = ? ORDER BY seq DESC LIMIT 1").get(e);if(t===void 0||t.exit_diagnostic_json===null)return null;try{const n=JSON.parse(t.exit_diagnostic_json),r=n.transport_poison;return n.schema!=="crtr.execution-exit-diagnostic/v1"||r===void 0||!Number.isInteger(r.consecutive_passes)||r.consecutive_passes<1||!Array.isArray(r.routes)||r.routes.length===0||!r.routes.every(i=>typeof i=="string"&&i!=="")?null:{consecutivePasses:r.consecutive_passes,routes:r.routes}}catch{return null}}o(Ke,"readTransportPoisonVerdict");async function Ye(e){const t=await(await p()).prepare("SELECT turn_open_at, turn_closed_at, turn_progress_at FROM executions WHERE node_id = ? AND state != 'exited'").get(e);return t===void 0?null:{busy:t.turn_open_at!==null&&t.turn_closed_at===null,progressAt:t.turn_progress_at}}o(Ye,"readLiveTurn");async function Ge(e){const t=await p(),n=await t.prepare("SELECT turn_closed_at, turn_progress_at FROM executions WHERE node_id = ? AND turn_open_at IS NOT NULL ORDER BY seq DESC LIMIT 1").get(e);if(n===void 0)return null;const r=await t.prepare("SELECT turn_end_reason FROM executions WHERE node_id = ? ORDER BY seq DESC LIMIT 1").get(e);return{interrupted:n.turn_closed_at===null||r?.turn_end_reason==="teardown-aborted",progressAt:n.turn_progress_at}}o(Ge,"readInterruptedTurn");async function qe(e){return await(await p()).prepare("SELECT 1 FROM executions WHERE node_id = ? AND turn_open_at IS NOT NULL LIMIT 1").get(e)!==void 0}o(qe,"hasAdmittedTurn");async function Ve(e,t){const n=V(t);return Q(e,n),await l(async r=>await ne(r,e,n))}o(Ve,"recordFault");async function Qe(e){return await l(async t=>(await t.prepare("UPDATE node_faults SET notified_since = since, updated_at = ? WHERE fault_id = ?").run(u(),e)).changes>0)}o(Qe,"markFaultNotified");function Re(e){return e.link==="pi\u2192provider"&&e.retry.disposition==="fatal"&&e.notifiedSince!==e.since}o(Re,"isUnnotifiedFatalProviderFault");async function ze(){return(await(await p()).prepare("SELECT f.node_id FROM node_faults f JOIN nodes n ON n.node_id = f.node_id WHERE f.active = 1 AND f.link = 'pi\u2192provider' AND f.retry_disposition = 'fatal' AND (f.notified_since IS NULL OR f.notified_since != f.since) AND n.status IN ('active', 'idle')").all()).map(e=>e.node_id)}o(ze,"listUnnotifiedFatalFaultNodes");let W=null;function Ze(e){W=e}o(Ze,"setFatalFaultAnnouncer");async function et(e,t){const n=await L(await p(),e);return n===null||t?.link!==void 0&&n.link!==t.link?!1:await l(async r=>{const i=await L(r,e);if(i===null||t?.link!==void 0&&i.link!==t.link)return!1;W!==null&&Re(i)&&await W(e);const s=await r.prepare("SELECT episode_state FROM node_faults WHERE fault_id = ?").get(i.faultId);await r.prepare("UPDATE node_faults SET active = 0, updated_at = ? WHERE fault_id = ?").run(u(),i.faultId),s.episode_state==="pending"&&t?.preserveEpisode!==!0&&await r.prepare("UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE fault_id = ?").run(u(),i.faultId),await D(r,i.faultId);const d=G();return $({level:"info",event:"fault.cleared",operation_id:d,node_id:e,error_class:X(i),fields:{cleared_fault_operation_id:i.operation_id,link:i.link,op:i.op,kind:i.kind,retry:i.retry,message:i.message,since:i.since,...i.anchorEntryId===void 0?{}:{anchor_entry_id:i.anchorEntryId}}}),!0})}o(et,"clearFault");async function re(e){return await L(await p(),e)}o(re,"readFault");async function tt(e,t){const n=V(t.input);if(n.link!=="pi\u2192provider"||n.retry.disposition!=="auto"||n.retry.by!=="daemon")throw new Error("provider retry episode requires an automatic daemon provider fault");return Q(e,n),await l(async r=>{const i=await m(r,e,t.sessionId);if(i===null)return null;const s=await L(r,e);if(s!==null&&(s.link!==n.link||s.kind!==n.kind)&&w(s)>w(n))return null;const d=await r.prepare("SELECT fault_id FROM node_faults WHERE node_id = ? AND episode_state IS NOT NULL").all(e);await r.prepare("UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE node_id = ? AND episode_state IS NOT NULL").run(u(),e);for(const E of d)await D(r,E.fault_id);const a=await ne(r,e,n,{state:"pending",bindingId:i});return a===null?null:(await r.prepare("UPDATE node_faults SET episode_state = ?, episode_binding_id = ?, updated_at = ? WHERE fault_id = ?").run("pending",i,u(),a.faultId),a)})}o(tt,"recordPendingEpisode");async function nt(e,t){return await l(async n=>{if(await n.prepare("SELECT 1 FROM nodes WHERE node_id = ? AND intent = 'refresh'").get(e)!==void 0)return!1;const r=await m(n,e,t.sessionId);return r===null?!1:(await n.prepare("UPDATE node_faults SET episode_state = 'admitted', retry_disposition = ?, retry_by = ?, retry_attempt = ?, retry_max = ?, retry_next_at = ?, updated_at = ? WHERE node_id = ? AND fault_id = ? AND episode_state = 'pending' AND episode_binding_id = ?").run(t.retry.disposition,t.retry.by??null,t.retry.attempt??null,t.retry.max??null,t.retry.nextAt??null,u(),e,t.faultId,r)).changes>0})}o(nt,"admitEpisode");async function rt(e,t){return await l(async n=>{const r=await m(n,e,t.sessionId);return r===null?!1:(await n.prepare("UPDATE node_faults SET episode_state = 'pending', updated_at = ? WHERE node_id = ? AND episode_state = 'admitted' AND episode_binding_id = ?").run(u(),e,r)).changes>0})}o(rt,"reopenEpisode");async function it(e,t){return await l(async n=>{const r=await m(n,e,t.sessionId);return r===null?!1:(await n.prepare("UPDATE node_faults SET episode_state = 'invalidated', updated_at = ? WHERE node_id = ? AND episode_state != 'invalidated' AND episode_state IS NOT NULL AND episode_binding_id = ?").run(u(),e,r)).changes>0})}o(it,"invalidateEpisode");async function ot(e,t){return await l(async n=>{const r=await m(n,e,t.sessionId);if(r===null)return!1;const i=await n.prepare("SELECT fault_id FROM node_faults WHERE node_id = ? AND episode_binding_id = ? AND episode_state IS NOT NULL").all(e,r);if(i.length===0)return!1;await n.prepare("UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE node_id = ? AND episode_binding_id = ? AND episode_state IS NOT NULL").run(u(),e,r);for(const s of i)await D(n,s.fault_id);return!0})}o(ot,"clearEpisode");async function st(e){const t=await(await p()).prepare("SELECT f.*, s.session_id FROM node_faults f JOIN sessions s ON s.binding_id = f.episode_binding_id WHERE f.node_id = ? AND f.episode_state IS NOT NULL").get(e);return t===void 0?null:{state:t.episode_state,sessionId:t.session_id,fault:H(t)}}o(st,"readEpisode");async function at(){return(await(await p()).prepare("SELECT f.*, s.session_id AS bound_session_id FROM node_faults f JOIN sessions s ON s.binding_id = f.episode_binding_id WHERE f.active = 1 AND f.episode_state = 'pending' AND s.unbound_at IS NULL AND s.session_id IS NOT NULL AND f.link = 'pi\u2192provider' AND f.retry_disposition = 'auto' AND f.retry_by = 'daemon' AND f.kind IN ('connection', 'rate-limit', 'overloaded')").all()).map(t=>({nodeId:t.node_id,sessionId:t.bound_session_id,fault:H(t),updatedAt:t.updated_at}))}o(at,"listPendingProviderRetries");async function dt(e){const t=await re(e)===null;return{async explanation(){if(!t)return null;const n=await re(e);if(n===null||n.link!=="crtr\u2192pi"||n.retry.disposition!=="fatal")return null;const r=n.op.trim(),i=n.message.trim();return r===""||i===""?null:`${r}: ${i}`}}}o(dt,"beginBootFaultAttempt");function ie(e,t){try{return ce(e).mtime.toISOString()}catch{return t}}o(ie,"markerMtime");function P(e,t){if(!f(e))return null;try{return de(e,"utf8")}catch(n){if(!t)return null;throw new Error(`cannot import recovery input ${e}: ${n.message}`)}}o(P,"legacyFile");function Ie(e,t){return _(e,"SELECT execution_id, started_at FROM executions WHERE node_id = ? ORDER BY rowid DESC LIMIT 1").get(t)??null}o(Ie,"latestExecution");function we(e,t){const r=C(e,"nodes").has("launched_at")?_(e,"SELECT COALESCE(launched_at, created) AS started_at FROM nodes WHERE node_id = ?").get(t):_(e,"SELECT created AS started_at FROM nodes WHERE node_id = ?").get(t);if(r===void 0)throw new Error(`cannot import recovery witness for unknown node ${t}`);const i=I();return _(e,"INSERT INTO executions (execution_id, node_id, daemon_epoch, pid, process_identity, state, started_at, ended_at, exit_reason) VALUES (?, ?, NULL, NULL, NULL, 'exited', ?, ?, 'pre-consolidation')").run(i,t,r.started_at,r.started_at),{execution_id:i,started_at:r.started_at}}o(we,"syntheticExecution");function oe(e,t,n,r,i){const s=I();return _(e,z).run(...Z(s,t,n,r,i)),{...n,faultId:s}}o(oe,"insertMigratedFault");function De(e,t,n,r){const i=_(e,"SELECT binding_id, node_id FROM sessions WHERE transcript_path = ? AND unbound_at IS NULL").get(n);if(i!==void 0){if(i.node_id!==t)throw new Error(`cannot import provider retry ${r}: transcript is live-owned by ${i.node_id}`);return i.binding_id}const s=_(e,"SELECT binding_id FROM sessions WHERE node_id = ? AND transcript_path = ? ORDER BY rowid DESC LIMIT 1").get(t,n);if(s!==void 0)return s.binding_id;const d=_(e,"SELECT created FROM nodes WHERE node_id = ?").get(t);if(d===void 0)throw new Error(`cannot import provider retry ${r}: unknown node ${t}`);const a=I();return _(e,"INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at, unbound_at) VALUES (?, NULL, ?, ?, NULL, NULL, ?, ?, ?)").run(a,t,n,d.created,d.created,u()),a}o(De,"migrationBinding");function ut(e){e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'node_faults'").get()!==void 0&&(C(e,"node_faults").has("notified_since")||e.exec("ALTER TABLE node_faults ADD COLUMN notified_since TEXT"))}o(ut,"addFaultNotifiedSince");function ct(e){if(Le(e),me(e),!f(F()))return;const t=ae(F(),{withFileTypes:!0}).filter(r=>r.isDirectory()).sort((r,i)=>r.name.localeCompare(i.name)),n=_(e,"SELECT 1 FROM nodes WHERE node_id = ?");for(const r of t){const i=r.name,s=pe(i),d=N(s,"busy"),a=N(s,"clean-abort"),E=N(s,"transport-poison.json"),U=N(s,"fault"),A=N(s,"provider-retry"),O=f(d),h=f(a);if(!O&&!h&&!f(E)&&!f(U)&&!f(A)||!f(N(F(),i,"meta.json"))&&n.get(i)===void 0)continue;const k=P(E,!1),S=P(U,!0),x=P(A,!0);if(!O&&!h&&k===null&&S===null&&x===null)continue;let y=Ie(e,i);if(y===null&&(y=we(e,i)),O){const c=ie(d,y.started_at);_(e,"UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = NULL, turn_end_reason = NULL WHERE execution_id = ?").run(c,c,y.execution_id)}else if(h){const c=ie(a,y.started_at);_(e,"UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = ?, turn_end_reason = 'teardown-aborted' WHERE execution_id = ?").run(c,c,c,y.execution_id)}if(k!==null)try{const c=JSON.parse(k);Number.isInteger(c.consecutivePasses)&&c.consecutivePasses>=1&&Array.isArray(c.routes)&&c.routes.length>0&&c.routes.every(M=>typeof M=="string"&&M!=="")&&_(e,"UPDATE executions SET exit_diagnostic_json = ? WHERE execution_id = ?").run(JSON.stringify({schema:"crtr.execution-exit-diagnostic/v1",transport_poison:{consecutive_passes:c.consecutivePasses,routes:c.routes}}),y.execution_id)}catch{}const R=S===null?null:Y(S);if(S!==null&&R===null)throw new Error(`cannot import recovery fault ${U}`);const T=x===null?null:Se(x);if(x!==null&&T===null)throw new Error(`cannot import provider retry ${A}`);let v=R===null||R.link==="broker\u2194crtrd"?null:oe(e,i,R,!0);if(T!==null){const c=De(e,i,T.sessionFile,A);v!==null&&v.since===T.fault.since?_(e,"UPDATE node_faults SET episode_state = ?, episode_binding_id = ?, updated_at = ? WHERE fault_id = ?").run(T.state,c,u(),v.faultId):oe(e,i,T.fault,!1,{state:T.state,bindingId:c})}}}o(ct,"migrateRecoveryWitnesses");export{Me as FAULT_QUIET_MS,ut as addFaultNotifiedSince,nt as admitEpisode,dt as beginBootFaultAttempt,ot as clearEpisode,et as clearFault,je as closeTurn,qe as hasAdmittedTurn,H as hydrateFault,it as invalidateEpisode,at as listPendingProviderRetries,ze as listUnnotifiedFatalFaultNodes,Qe as markFaultNotified,Be as markNodeRead,ct as migrateRecoveryWitnesses,Xe as openTurn,K as parseProviderError,st as readEpisode,re as readFault,Ge as readInterruptedTurn,Ye as readLiveTurn,Ke as readTransportPoisonVerdict,Ve as recordFault,tt as recordPendingEpisode,Je as recordTransportPoisonVerdict,$e as recordTurnProgress,rt as reopenEpisode,Ze as setFatalFaultAnnouncer};
|
|
@@ -60,6 +60,7 @@ export declare class RemoteCanvasSource implements CanvasSource {
|
|
|
60
60
|
getRow(id: string): Promise<NodeRow | null>;
|
|
61
61
|
listNodes(filter?: {
|
|
62
62
|
status?: NodeStatus | NodeStatus[];
|
|
63
|
+
under?: string;
|
|
63
64
|
}): Promise<NodeRow[]>;
|
|
64
65
|
subscriptionsOf(id: string): Promise<SubscriptionRef[]>;
|
|
65
66
|
subscribersOf(id: string): Promise<SubscriptionRef[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var y=Object.defineProperty;var u=(s,e)=>y(s,"name",{value:e,configurable:!0});import{createRemoteExec as h}from"./remote-transport.js";const d=1e3;function r(s){return typeof s=="object"&&s!==null&&!Array.isArray(s)}u(r,"isPlainObject");function w(s){if(!r(s))return!1;const e=s.node;if(!r(e)||typeof e.node_id!="string"||!Array.isArray(s.reports)||!Array.isArray(s.managers))return!1;const t=s.artifacts;if(!r(t)||typeof t.report!="number"||typeof t.doc!="number"||typeof t.roadmap!="number"||typeof s.pending_crons!="number")return!1;const o=s.paths;if(!r(o)||typeof o.context_dir!="string"||"session_file"in o&&o.session_file!==null&&typeof o.session_file!="string"||typeof s.follow_up!="string")return!1;const n=s.fault;if(n!=null){if(!r(n)||typeof n.link!="string"||typeof n.kind!="string"||typeof n.since!="string")return!1;const i=n.retry;if(!r(i)||typeof i.disposition!="string")return!1}return!0}u(w,"isValidShowResponse");function p(s){return r(s)&&typeof s.node_id=="string"&&typeof s.name=="string"&&typeof s.kind=="string"&&typeof s.status=="string"&&typeof s.active=="boolean"}u(p,"isValidNeighborEntry");function g(s){return r(s)&&typeof s.from_id=="string"&&typeof s.to_id=="string"&&typeof s.active=="boolean"&&typeof s.created=="string"}u(g,"isValidRosterEdge");function _(s){return r(s)?typeof s.node_id=="string"&&typeof s.name=="string"&&typeof s.kind=="string"&&typeof s.mode=="string"&&typeof s.lifecycle=="string"&&typeof s.status=="string"&&typeof s.cwd=="string"&&typeof s.created=="string":!1}u(_,"isValidNodeRow");class v{static{u(this,"RemoteCanvasSource")}previewEndpoint;relayToken;exec;nodeCache=new Map;rosterCache=new Map;topologyCache=null;viewCache=new Map;constructor(e,t){this.previewEndpoint=e,this.relayToken=t,this.exec=h(e,t)}async execJson(e){let t;try{t=await this.exec("crtr",["--json",...e])}catch{return null}if(!t.ok||t.exitCode!==void 0&&t.exitCode!==0)return null;try{return JSON.parse(t.stdout.trim())}catch{return null}}async fetchShow(e){const t=this.nodeCache.get(e);if(t&&Date.now()-t.at<d)return t.value;const o=await this.execJson(["node","inspect","show",e]),n=w(o)?{...o,fault:o.fault??null,reports:o.reports.filter(p),managers:o.managers.filter(p)}:null;return this.nodeCache.set(e,{value:n,at:Date.now()}),n}topology(){if(this.topologyCache!==null&&Date.now()-this.topologyCache.at<d)return this.topologyCache.value;const e=this.loadTopology();return this.topologyCache={value:e,at:Date.now()},e}async loadTopology(){const e=await this.exec("crtr",["--json","canvas","roster"]);if(!e.ok||e.exitCode!==void 0&&e.exitCode!==0)throw new Error("remote canvas topology is unavailable");let t;try{t=JSON.parse(e.stdout.trim())}catch{throw new Error("remote canvas topology is invalid")}if(!r(t)||!Array.isArray(t.edges)||!t.edges.every(g))throw new Error("remote canvas topology is invalid");const o=t.edges,n={subscriptions:new Map,subscribers:new Map};for(const i of o){const a={node_id:i.to_id,active:i.active,created:i.created},c={node_id:i.from_id,active:i.active,created:i.created},l=n.subscriptions.get(i.from_id);l===void 0?n.subscriptions.set(i.from_id,[a]):l.push(a);const f=n.subscribers.get(i.to_id);f===void 0?n.subscribers.set(i.to_id,[c]):f.push(c)}return n}async rawShow(e){return this.fetchShow(e)}async getNode(e){return(await this.fetchShow(e))?.node??null}async getRow(e){const t=(await this.fetchShow(e))?.node;return t?{node_id:t.node_id,name:t.name,kind:t.kind,mode:t.mode,lifecycle:t.lifecycle,status:t.status,cwd:t.cwd,host_kind:t.host_kind??null,profile_id:t.profile_id??null,scopes:t.scopes??null,isolated:t.isolated===!0,parent:t.parent??null,created:t.created,intent:t.intent??null,frozen_at:t.frozen_at??null,terminal_reason:t.terminal_reason??null,pi_pid:t.pi_pid??null,pi_pid_identity:t.pi_pid_identity??null,window:t.window??null,tmux_session:t.tmux_session??null,pane:t.pane??null,fault:t.fault??null,streaming:t.streaming===!0}:null}async listNodes(e){const t=JSON.stringify(e?.status??null),o=this.rosterCache.get(t);if(o&&Date.now()-o.at<d)return o.value;const n=["node","inspect","list"];e?.status&&n.push("--status",(Array.isArray(e.status)?e.status:[e.status]).join(","));const i=await this.execJson(n),c=(r(i)&&Array.isArray(i.nodes)?i.nodes:[]).filter(_).map(l=>({...l,isolated:l.isolated===!0}));return this.rosterCache.set(t,{value:c,at:Date.now()}),c}async subscriptionsOf(e){return(await this.topology()).subscriptions.get(e)??[]}async subscribersOf(e){return(await this.topology()).subscribers.get(e)??[]}async view(e){const t=this.viewCache.get(e);if(t&&Date.now()-t.at<d)return t.value;const o=new Set([e]),n=[],i=(await this.subscriptionsOf(e)).map(a=>a.node_id);for(;i.length>0;){const a=i.shift();if(!o.has(a)){o.add(a),n.push(a);for(const c of await this.subscriptionsOf(a))o.has(c.node_id)||i.push(c.node_id)}}return this.viewCache.set(e,{value:n,at:Date.now()}),n}async ticketCountsForNodes(e){if(e.length===0)return{};const t=await this.execJson(["canvas","attention","map","--nodes",e.join(",")]);return r(t)&&r(t.counts)?t.counts:{}}async ticketCountsForView(e){const t=await this.execJson(["canvas","attention","map","--view",e]);return r(t)&&r(t.counts)?t.counts:{}}async hasActiveLiveSubscription(e){const t=(await this.subscriptionsOf(e)).filter(o=>o.active);for(const o of t){const n=await this.getRow(o.node_id);if(n&&(n.status==="active"||n.status==="idle"))return!0}return!1}}export{v as RemoteCanvasSource};
|
|
1
|
+
var y=Object.defineProperty;var u=(s,e)=>y(s,"name",{value:e,configurable:!0});import{createRemoteExec as h}from"./remote-transport.js";const d=1e3;function r(s){return typeof s=="object"&&s!==null&&!Array.isArray(s)}u(r,"isPlainObject");function w(s){if(!r(s))return!1;const e=s.node;if(!r(e)||typeof e.node_id!="string"||!Array.isArray(s.reports)||!Array.isArray(s.managers))return!1;const t=s.artifacts;if(!r(t)||typeof t.report!="number"||typeof t.doc!="number"||typeof t.roadmap!="number"||typeof s.pending_crons!="number")return!1;const o=s.paths;if(!r(o)||typeof o.context_dir!="string"||"session_file"in o&&o.session_file!==null&&typeof o.session_file!="string"||typeof s.follow_up!="string")return!1;const n=s.fault;if(n!=null){if(!r(n)||typeof n.link!="string"||typeof n.kind!="string"||typeof n.since!="string")return!1;const i=n.retry;if(!r(i)||typeof i.disposition!="string")return!1}return!0}u(w,"isValidShowResponse");function p(s){return r(s)&&typeof s.node_id=="string"&&typeof s.name=="string"&&typeof s.kind=="string"&&typeof s.status=="string"&&typeof s.active=="boolean"}u(p,"isValidNeighborEntry");function g(s){return r(s)&&typeof s.from_id=="string"&&typeof s.to_id=="string"&&typeof s.active=="boolean"&&typeof s.created=="string"}u(g,"isValidRosterEdge");function _(s){return r(s)?typeof s.node_id=="string"&&typeof s.name=="string"&&typeof s.kind=="string"&&typeof s.mode=="string"&&typeof s.lifecycle=="string"&&typeof s.status=="string"&&typeof s.cwd=="string"&&typeof s.created=="string":!1}u(_,"isValidNodeRow");class v{static{u(this,"RemoteCanvasSource")}previewEndpoint;relayToken;exec;nodeCache=new Map;rosterCache=new Map;topologyCache=null;viewCache=new Map;constructor(e,t){this.previewEndpoint=e,this.relayToken=t,this.exec=h(e,t)}async execJson(e){let t;try{t=await this.exec("crtr",["--json",...e])}catch{return null}if(!t.ok||t.exitCode!==void 0&&t.exitCode!==0)return null;try{return JSON.parse(t.stdout.trim())}catch{return null}}async fetchShow(e){const t=this.nodeCache.get(e);if(t&&Date.now()-t.at<d)return t.value;const o=await this.execJson(["node","inspect","show",e]),n=w(o)?{...o,fault:o.fault??null,reports:o.reports.filter(p),managers:o.managers.filter(p)}:null;return this.nodeCache.set(e,{value:n,at:Date.now()}),n}topology(){if(this.topologyCache!==null&&Date.now()-this.topologyCache.at<d)return this.topologyCache.value;const e=this.loadTopology();return this.topologyCache={value:e,at:Date.now()},e}async loadTopology(){const e=await this.exec("crtr",["--json","canvas","roster"]);if(!e.ok||e.exitCode!==void 0&&e.exitCode!==0)throw new Error("remote canvas topology is unavailable");let t;try{t=JSON.parse(e.stdout.trim())}catch{throw new Error("remote canvas topology is invalid")}if(!r(t)||!Array.isArray(t.edges)||!t.edges.every(g))throw new Error("remote canvas topology is invalid");const o=t.edges,n={subscriptions:new Map,subscribers:new Map};for(const i of o){const a={node_id:i.to_id,active:i.active,created:i.created},c={node_id:i.from_id,active:i.active,created:i.created},l=n.subscriptions.get(i.from_id);l===void 0?n.subscriptions.set(i.from_id,[a]):l.push(a);const f=n.subscribers.get(i.to_id);f===void 0?n.subscribers.set(i.to_id,[c]):f.push(c)}return n}async rawShow(e){return this.fetchShow(e)}async getNode(e){return(await this.fetchShow(e))?.node??null}async getRow(e){const t=(await this.fetchShow(e))?.node;return t?{node_id:t.node_id,name:t.name,kind:t.kind,mode:t.mode,lifecycle:t.lifecycle,status:t.status,cwd:t.cwd,host_kind:t.host_kind??null,profile_id:t.profile_id??null,scopes:t.scopes??null,isolated:t.isolated===!0,parent:t.parent??null,created:t.created,intent:t.intent??null,frozen_at:t.frozen_at??null,terminal_reason:t.terminal_reason??null,pi_pid:t.pi_pid??null,pi_pid_identity:t.pi_pid_identity??null,window:t.window??null,tmux_session:t.tmux_session??null,pane:t.pane??null,fault:t.fault??null,streaming:t.streaming===!0}:null}async listNodes(e){const t=JSON.stringify([e?.status??null,e?.under??null]),o=this.rosterCache.get(t);if(o&&Date.now()-o.at<d)return o.value;const n=["node","inspect","list"];e?.status&&n.push("--status",(Array.isArray(e.status)?e.status:[e.status]).join(",")),e?.under&&n.push("--under",e.under);const i=await this.execJson(n),c=(r(i)&&Array.isArray(i.nodes)?i.nodes:[]).filter(_).map(l=>({...l,isolated:l.isolated===!0}));return this.rosterCache.set(t,{value:c,at:Date.now()}),c}async subscriptionsOf(e){return(await this.topology()).subscriptions.get(e)??[]}async subscribersOf(e){return(await this.topology()).subscribers.get(e)??[]}async view(e){const t=this.viewCache.get(e);if(t&&Date.now()-t.at<d)return t.value;const o=new Set([e]),n=[],i=(await this.subscriptionsOf(e)).map(a=>a.node_id);for(;i.length>0;){const a=i.shift();if(!o.has(a)){o.add(a),n.push(a);for(const c of await this.subscriptionsOf(a))o.has(c.node_id)||i.push(c.node_id)}}return this.viewCache.set(e,{value:n,at:Date.now()}),n}async ticketCountsForNodes(e){if(e.length===0)return{};const t=await this.execJson(["canvas","attention","map","--nodes",e.join(",")]);return r(t)&&r(t.counts)?t.counts:{}}async ticketCountsForView(e){const t=await this.execJson(["canvas","attention","map","--view",e]);return r(t)&&r(t.counts)?t.counts:{}}async hasActiveLiveSubscription(e){const t=(await this.subscriptionsOf(e)).filter(o=>o.active);for(const o of t){const n=await this.getRow(o.node_id);if(n&&(n.status==="active"||n.status==="idle"))return!0}return!1}}export{v as RemoteCanvasSource};
|
|
@@ -4,8 +4,11 @@ import type { RosterDTO } from '../../api/dto/canvas.js';
|
|
|
4
4
|
export interface CanvasSource {
|
|
5
5
|
getNode(nodeId: string): Promise<NodeMeta | null>;
|
|
6
6
|
getRow(nodeId: string): Promise<NodeRow | null>;
|
|
7
|
+
/** `under` restricts to the nodes below that node, excluding it. */
|
|
8
|
+
/** `under` scopes to that node plus every node below it (human ask nodes included), one query. */
|
|
7
9
|
listNodes(filter?: {
|
|
8
10
|
status?: NodeStatus | NodeStatus[];
|
|
11
|
+
under?: string;
|
|
9
12
|
}): Promise<NodeRow[]>;
|
|
10
13
|
/** Optional one-request browse projection. Other listNodes callers keep their full rows. */
|
|
11
14
|
browseSnapshot?(): Promise<NodeRow[]>;
|
|
@@ -29,6 +32,7 @@ export declare class LocalCanvasSource implements CanvasSource {
|
|
|
29
32
|
getRow(nodeId: string): Promise<NodeRow | null>;
|
|
30
33
|
listNodes(filter?: {
|
|
31
34
|
status?: NodeStatus | NodeStatus[];
|
|
35
|
+
under?: string;
|
|
32
36
|
}): Promise<NodeRow[]>;
|
|
33
37
|
subscriptionsOf(subscriber: string): Promise<SubscriptionRef[]>;
|
|
34
38
|
subscribersOf(publisher: string): Promise<SubscriptionRef[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var u=Object.defineProperty;var
|
|
1
|
+
var u=Object.defineProperty;var s=(t,e)=>u(t,"name",{value:e,configurable:!0});import{getNode as v,getRow as m,listNodes as d,subscriptionsOf as w,subscribersOf as p,view as a,hasActiveLiveSubscription as f}from"./canvas.js";import{ticketCountsForNodes as l}from"./attention.js";import{readState as y}from"../config.js";import{resolveRemoteCanvasTarget as C}from"../remote-canvas-target.js";import{RemoteCanvasSource as N}from"./remote-canvas-source.js";import{isSandboxedNode as b}from"../../shared/env.js";import{ownerOnly as h}from"../errors.js";class S{static{s(this,"LocalCanvasSource")}async getNode(e){return await v(e)}async getRow(e){return await m(e)}async listNodes(e){const{under:r,...n}=e??{};return await d(r===void 0?n:{...n,under:r,underInclusive:!0})}async subscriptionsOf(e){return await w(e)}async subscribersOf(e){return await p(e)}async view(e){return await a(e)}async ticketCountsForNodes(e){return await l([...e])}async ticketCountsForView(e){return this.ticketCountsForNodes([e,...await a(e)])}async hasActiveLiveSubscription(e){return await f(e)}}const o=new S;function T(t,e=b()){const r=t?.scope??"user";if(e){if(t?.canvasName!==void 0)throw h("--canvas selects the person's remote canvas targets, which an app's node cannot reach","Omit --canvas; this node reads its own runtime's canvas.");return o}const n=t?.canvasName??y(r).activeCanvas??null;if(!n)return o;const{previewEndpoint:i,relayToken:c}=C(n,r);return new N(i,c)}s(T,"resolveCanvasSource");export{S as LocalCanvasSource,o as localCanvasSource,T as resolveCanvasSource};
|
|
@@ -20,6 +20,8 @@ export declare function setSubscriptionActive(subscriber: string, publisher: str
|
|
|
20
20
|
export declare function subscribersOf(publisher: string): Promise<SubscriptionRef[]>;
|
|
21
21
|
/** The nodes `subscriber` watches in the tree — its reports. */
|
|
22
22
|
export declare function subscriptionsOf(subscriber: string): Promise<SubscriptionRef[]>;
|
|
23
|
+
export declare const SUBTREE_IDS_SQL: string;
|
|
24
|
+
export declare const SUBTREE_ALL_IDS_SQL: string;
|
|
23
25
|
/** Every node below `root` in the tree, excluding root. */
|
|
24
26
|
export declare function view(root: string): Promise<string[]>;
|
|
25
27
|
/** Stop-guard primitive: does this node hold an active tree subscription to a live node —
|
package/dist/core/canvas/tree.js
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
var
|
|
1
|
+
var O=Object.defineProperty;var i=(o,t)=>O(o,"name",{value:t,configurable:!0});import{openDb as c,withCanvasWrite as d}from"./db.js";import{getById as m,nodeObject as r}from"../graph/objects.js";import{recordWatch as y,unwatch as I,configFromJson as N,configToJson as b}from"../graph/watches.js";import{publish as T}from"../graph/events.js";import{DEFAULT_LISTEN as v}from"../graph/types.js";const D=["spawn","job-start","ask"],S="('spawn','job-start','ask')",R=[{threshold:3,delivery:"next-turn"}];function l(o){const t=o.find(a=>a.threshold<=7);return t!==void 0&&t.delivery!=="next-turn"}i(l,"wakesAtSeven");async function w(o,t,...a){const e=await o.prepareUncached(`SELECT wo.id AS from_id, oo.id AS to_id, ws.config_json, ws.created_at,
|
|
2
2
|
wo.listen_json, wn.status AS from_status, onode.status AS to_status
|
|
3
3
|
FROM watches w
|
|
4
4
|
JOIN objects wo ON wo.id = w.watcher AND wo.type = 'node'
|
|
5
5
|
JOIN objects oo ON oo.id = w.object AND oo.type = 'node'
|
|
6
|
-
JOIN watch_subscriptions ws ON ws.watch = w.watch_id AND ws.started_by IN ${
|
|
6
|
+
JOIN watch_subscriptions ws ON ws.watch = w.watch_id AND ws.started_by IN ${S}
|
|
7
7
|
JOIN nodes wn ON wn.node_id = wo.id
|
|
8
8
|
JOIN nodes onode ON onode.node_id = oo.id
|
|
9
9
|
WHERE w.in_tree = 1 ${t}
|
|
10
|
-
ORDER BY ws.created_at, ws.seq`).all(...a),s=new Map;for(const
|
|
11
|
-
WHERE started_by IN ${
|
|
12
|
-
AND watch IN (SELECT watch_id FROM watches WHERE watcher = ? AND object = ?)`).run(a?null:
|
|
10
|
+
ORDER BY ws.created_at, ws.seq`).all(...a),s=new Map;for(const n of e){const u=n.config_json,_=n.listen_json,f=u!=null?N(u):_!=null?N(_):v,p=`${n.from_id}\0${n.to_id}`,E=s.get(p);if(E){E.active||=l(f);continue}s.set(p,{from_id:n.from_id,to_id:n.to_id,active:l(f),created:n.created_at,from_status:n.from_status??null,to_status:n.to_status??null})}return[...s.values()]}i(w,"treeEdges");async function F(){return(await w(await c(),"")).map(({from_id:o,to_id:t,active:a,created:e})=>({from_id:o,to_id:t,active:a,created:e}))}i(F,"rosterEdges");async function W(o,t,a=!0){await d(async e=>{const s=await r(e,o),n=await r(e,t);await y(e,s,n,"ask"),await j(o,t,a),await T(e,{event:"watched",object:n,actor:s,attrs:{}})})}i(W,"subscribe");async function M(o,t){await d(async a=>{const e=await r(a,o),s=await r(a,t);for(const n of D)await I(a,e,s,{startedBy:n})})}i(M,"unsubscribe");async function j(o,t,a){await d(async e=>{await e.prepareUncached(`UPDATE watch_subscriptions SET config_json = ?
|
|
11
|
+
WHERE started_by IN ${S}
|
|
12
|
+
AND watch IN (SELECT watch_id FROM watches WHERE watcher = ? AND object = ?)`).run(a?null:b(R),(await r(e,o)).id,(await r(e,t)).id)})}i(j,"setSubscriptionActive");async function $(o){return(await w(await c(),"AND oo.id = ?",o)).map(t=>({node_id:t.from_id,active:t.active,created:t.created}))}i($,"subscribersOf");async function B(o){return(await w(await c(),"AND wo.id = ?",o)).map(t=>({node_id:t.to_id,active:t.active,created:t.created}))}i(B,"subscriptionsOf");function h(o){return`WITH RECURSIVE walk(id) AS (
|
|
13
|
+
SELECT CAST(? AS text)
|
|
14
|
+
UNION
|
|
15
|
+
SELECT w.object FROM walk
|
|
16
|
+
JOIN watches w ON w.watcher = walk.id AND w.in_tree = 1
|
|
17
|
+
${o?`JOIN objects oo ON oo.id = w.object AND oo.type = 'node' AND oo.kind IS DISTINCT FROM 'human'
|
|
18
|
+
JOIN nodes onode ON onode.node_id = oo.id`:"JOIN nodes onode ON onode.node_id = w.object"}
|
|
19
|
+
) SELECT id FROM walk WHERE id != ?`}i(h,"subtreeSql");const H=h(!0),L=h(!1);async function P(o){const t=await c(),a=await m(t,o);return a?.type!=="node"?[]:(await t.prepareUncached(L).all(a.id,a.id)).map(e=>e.id)}i(P,"view");const A=new Set(["active","idle"]);async function Q(o){return(await w(await c(),"AND wo.id = ?",o)).some(t=>t.active&&A.has(t.to_status??""))}i(Q,"hasActiveLiveSubscription");async function V(o){return(await w(await c(),"AND oo.id = ?",o)).some(t=>t.active&&A.has(t.from_status??""))}i(V,"hasLiveSubscriber");export{L as SUBTREE_ALL_IDS_SQL,H as SUBTREE_IDS_SQL,Q as hasActiveLiveSubscription,V as hasLiveSubscriber,F as rosterEdges,j as setSubscriptionActive,W as subscribe,$ as subscribersOf,B as subscriptionsOf,M as unsubscribe,P as view};
|