@north-light/crouter 0.3.319 → 0.3.321
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/client.d.ts +2 -1
- package/dist/api/client.js +1 -1
- package/dist/api/dto/broker-ops.d.ts +0 -1
- package/dist/api/dto/node-outcomes.d.ts +6 -0
- package/dist/api/dto/nodes.d.ts +4 -3
- package/dist/api/dto/review-comments.d.ts +8 -0
- package/dist/api/routes.d.ts +1 -0
- package/dist/api/routes.js +1 -1
- package/dist/clients/attach/viewer.js +582 -582
- package/dist/clients/inbox/review/comments-client.d.ts +8 -1
- package/dist/clients/inbox/review/comments-client.js +1 -1
- package/dist/clients/inbox/review/companion-pane.d.ts +17 -0
- package/dist/clients/inbox/review/companion-pane.js +1 -1
- package/dist/clients/inbox/review/document-surface.d.ts +10 -0
- package/dist/clients/inbox/review/document-surface.js +2 -2
- package/dist/clients/inbox/review/frame.js +1 -1
- package/dist/clients/inbox/review/keys.d.ts +2 -0
- package/dist/clients/inbox/review/keys.js +1 -1
- package/dist/commands/human/prompts.js +1 -1
- package/dist/core/canvas/browse/app.js +3 -3
- package/dist/core/canvas/canvas.d.ts +3 -3
- package/dist/core/canvas/canvas.js +17 -14
- package/dist/core/canvas/migrations.js +34 -27
- package/dist/core/canvas/node-sql-migration.d.ts +1 -0
- package/dist/core/canvas/node-sql-migration.js +28 -2
- package/dist/core/canvas/paths.d.ts +4 -0
- package/dist/core/canvas/paths.js +1 -1
- package/dist/core/canvas/recovery.d.ts +1 -0
- package/dist/core/canvas/recovery.js +1 -1
- package/dist/core/canvas/worktrees.d.ts +1 -0
- package/dist/core/canvas/worktrees.js +1 -1
- package/dist/core/human/requests.d.ts +1 -0
- package/dist/core/human/requests.js +17 -13
- package/dist/core/review/fork.d.ts +8 -0
- package/dist/core/review/fork.js +5 -0
- package/dist/core/runtime/broker/extension-abort.d.ts +3 -0
- package/dist/core/runtime/broker/extension-abort.js +1 -1
- package/dist/core/runtime/broker.js +1 -1
- package/dist/core/runtime/spawn.d.ts +5 -1
- package/dist/core/runtime/spawn.js +2 -2
- package/dist/core/runtime/stop-guard.d.ts +1 -3
- package/dist/core/runtime/stop-guard.js +2 -2
- package/dist/core/runtime/stop-signals.d.ts +0 -1
- package/dist/core/runtime/stop-signals.js +1 -1
- package/dist/daemon/api/handlers/broker-ops.js +1 -1
- package/dist/daemon/api/handlers/health.js +14 -1
- package/dist/daemon/api/handlers/inbox.js +1 -1
- package/dist/daemon/api/handlers/review-comments.js +1 -1
- package/dist/daemon/api/map.d.ts +4 -2
- package/dist/daemon/api/map.js +2 -2
- package/dist/daemon/companion-retire.d.ts +3 -1
- package/dist/daemon/companion-retire.js +1 -1
- package/dist/daemon/crtrd.js +7 -7
- package/dist/daemon/human/finish.d.ts +4 -1
- package/dist/daemon/human/finish.js +7 -7
- package/dist/daemon/human/settle.d.ts +8 -6
- package/dist/daemon/human/settle.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
- package/dist/pi-extensions/canvas-inbox-watcher.js +1 -1
- package/dist/pi-extensions/canvas-stophook.js +1 -1
- package/package.json +2 -1
- package/runtime.lock.json +5 -5
- package/scripts/pack-minify.mjs +108 -0
|
@@ -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(ye,"createFaultTable");function y(e,t){return typeof t=="string"&&e.includes(t)}o(y,"contains");function b(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(b,"isRecord");function B(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,r=typeof e.code=="string"||typeof e.code=="number"?e.code:void 0,n=typeof e.errno=="string"?e.errno:void 0,i=typeof e.body=="string"?e.body:void 0,d=Array.isArray(e.causes)?e.causes.flatMap(s=>{if(!b(s))return[];const c={...typeof s.message=="string"?{message:s.message}:{},...typeof s.status=="number"&&Number.isFinite(s.status)?{status:s.status}:{},...typeof s.code=="string"||typeof s.code=="number"?{code:s.code}:{},...typeof s.errno=="string"?{errno:s.errno}:{},...typeof s.body=="string"?{body:s.body}:{}};return Object.keys(c).length===0?[]:[c]}):void 0;return{provider:e.provider,model:e.model,...t===void 0?{}:{status:t},...r===void 0?{}:{code:r},...n===void 0?{}:{errno:n},...i===void 0?{}:{body:i},...d===void 0||d.length===0?{}:{causes:d}}}o(B,"parseProviderError");function K(e){try{const t=JSON.parse(e);if(!y(ce,t.link)||typeof t.op!="string"||t.op===""||!y(pe,t.kind)||typeof t.message!="string"||typeof t.since!="string")return null;const r=X(t.operation_id);if(!b(t.retry)||!y(_e,t.retry.disposition)||t.retry.by!==void 0&&!y(le,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 n=t.providerError===void 0?void 0:B(t.providerError);return t.providerError!==void 0&&n===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:r,...t.anchorEntryId===void 0?{}:{anchorEntryId:t.anchorEntryId},...n===void 0?{}:{providerError:n}}}catch{return null}}o(K,"parseLegacyFault");function Te(e){const t=de(e);try{return oe(t)}catch{return t}}o(Te,"canonicalPath");function ge(e){try{const t=JSON.parse(e);if(!y(Ee,t.state)||typeof t.sessionFile!="string"||t.sessionFile==="")return null;const r=JSON.stringify(t.fault),n=K(r);if(n===null||n.link!=="pi\u2192provider"||n.retry.disposition!=="auto"||n.retry.by!=="daemon")return null;const i=t.anchorEntryId;return i!==null&&typeof i!="string"||(n.anchorEntryId??null)!==i?null:{state:t.state,sessionFile:Te(t.sessionFile),fault:n}}catch{return null}}o(ge,"parseLegacyEpisode");function J(e){return e!==void 0?X(e):M.current()??M.fresh(r=>r)}o(J,"resolveOperationId");function Ne(e){return e.slice(0,ue)}o(Ne,"clampMessage");function A(e){return e.link==="pi\u2192provider"&&e.retry.disposition==="auto"&&e.retry.by==="daemon"?3:e.retry.disposition==="fatal"?2:1}o(A,"faultPriority");function Y(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(Y,"encodeFault");function G(e){const t=e.provider_error_json,r=typeof t=="string"?B(JSON.parse(t)):void 0;if(typeof t=="string"&&r===void 0)throw new Error(`invalid provider error on stored fault ${e.fault_id}`);const n={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:n,...e.anchor_entry_id===null?{}:{anchorEntryId:e.anchor_entry_id},...r===void 0?{}:{providerError:r}}}o(G,"hydrateFault");function I(e,t){const r=e.prepare("SELECT * FROM node_faults WHERE node_id = ? AND active = 1").get(t);return r===void 0?null:G(r)}o(I,"activeFault");function V(e){if(!y(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:Ne(e.message),since:e.since??a(),operation_id:J(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){w({level:t.retry.disposition==="fatal"?"error":"warn",event:"fault.recorded",operation_id:t.operation_id,node_id:e,error_class:P(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");function F(e,t,r,n,i){const d=k(),s=Y(r),c=a();return e.prepare("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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(d,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,n?1:0,i?.state??null,i?.bindingId??null,c,c),{...r,faultId:d}}o(F,"insertFault");function q(e,t,r,n){const i=Y(r);return 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,n?.state??null,n?.bindingId??null,a(),t),{...r,faultId:t}}o(q,"updateFault");function R(e,t){e.prepare("DELETE FROM node_faults WHERE fault_id = ? AND active = 0 AND episode_state IS NULL").run(t)}o(R,"deleteIfUnretained");function z(e,t,r,n){const i=I(e,t);if(i===null){const d=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 d!==void 0&&d.link===r.link&&d.kind===r.kind&&d.since===r.since&&d.operation_id===r.operation_id?(e.prepare("UPDATE node_faults SET active = 1, updated_at = ? WHERE fault_id = ?").run(a(),d.fault_id),q(e,d.fault_id,r)):F(e,t,r,!0,n)}if(i.link===r.link&&i.kind===r.kind){const d={...i.retry,...r.retry};return r.retry.disposition==="fatal"&&!("nextAt"in r.retry)&&delete d.nextAt,q(e,i.faultId,{...r,since:i.since,anchorEntryId:i.anchorEntryId??r.anchorEntryId,retry:d},n)}return A(i)>A(r)?null:(e.prepare("UPDATE node_faults SET active = 0, updated_at = ? WHERE fault_id = ?").run(a(),i.faultId),R(e,i.faultId),F(e,t,r,!0,n))}o(z,"replaceActiveFault");function g(e,t,r){return e.prepare("SELECT binding_id FROM sessions WHERE node_id = ? AND session_id = ? AND unbound_at IS NULL").get(t,r)?.binding_id??null}o(g,"liveBinding");function Ce(e,t){return p(r=>{const n=a();return r.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(n,e).changes>0?!0:r.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(n,n,e).changes>0})}o(Ce,"openTurn");function be(e){return p(t=>t.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(a(),e).changes>0)}o(be,"recordTurnProgress");function Fe(e,t){return p(r=>r.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(a(),t.endReason,e).changes>0)}o(Fe,"closeTurn");function He(e,t){if(!Number.isInteger(t.consecutivePasses)||t.consecutivePasses<1||t.routes.length===0||!t.routes.every(r=>r!==""))throw new Error("invalid transport-poison verdict");return p(r=>r.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(He,"recordTransportPoisonVerdict");function We(e){const t=T().prepare("SELECT exit_diagnostic_json FROM executions WHERE node_id = ? ORDER BY rowid DESC LIMIT 1").get(e);if(t===void 0||t.exit_diagnostic_json===null)return null;try{const r=JSON.parse(t.exit_diagnostic_json),n=r.transport_poison;return r.schema!=="crtr.execution-exit-diagnostic/v1"||n===void 0||!Number.isInteger(n.consecutive_passes)||n.consecutive_passes<1||!Array.isArray(n.routes)||n.routes.length===0||!n.routes.every(i=>typeof i=="string"&&i!=="")?null:{consecutivePasses:n.consecutive_passes,routes:n.routes}}catch{return null}}o(We,"readTransportPoisonVerdict");function Pe(e){const t=T().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(Pe,"readLiveTurn");function we(e){const t=T(),r=t.prepare("SELECT turn_closed_at, turn_progress_at FROM executions WHERE node_id = ? AND turn_open_at IS NOT NULL ORDER BY rowid DESC LIMIT 1").get(e);if(r===void 0)return null;const n=t.prepare("SELECT turn_end_reason FROM executions WHERE node_id = ? ORDER BY rowid DESC LIMIT 1").get(e);return{interrupted:r.turn_closed_at===null||n?.turn_end_reason==="teardown-aborted",progressAt:r.turn_progress_at}}o(we,"readInterruptedTurn");function Me(e,t){const r=V(t);return Q(e,r),p(n=>z(n,e,r))}o(Me,"recordFault");function Xe(e,t){return p(r=>{const n=I(r,e);if(n===null||t?.link!==void 0&&n.link!==t.link)return!1;const i=r.prepare("SELECT episode_state FROM node_faults WHERE fault_id = ?").get(n.faultId);r.prepare("UPDATE node_faults SET active = 0, updated_at = ? WHERE fault_id = ?").run(a(),n.faultId),i.episode_state==="pending"&&t?.preserveEpisode!==!0&&r.prepare("UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE fault_id = ?").run(a(),n.faultId),R(r,n.faultId);const d=J();return w({level:"info",event:"fault.cleared",operation_id:d,node_id:e,error_class:P(n),fields:{cleared_fault_operation_id:n.operation_id,link:n.link,op:n.op,kind:n.kind,retry:n.retry,message:n.message,since:n.since,...n.anchorEntryId===void 0?{}:{anchor_entry_id:n.anchorEntryId}}}),!0})}o(Xe,"clearFault");function Z(e){return I(T(),e)}o(Z,"readFault");function je(e,t){const r=V(t.input);if(r.link!=="pi\u2192provider"||r.retry.disposition!=="auto"||r.retry.by!=="daemon")throw new Error("provider retry episode requires an automatic daemon provider fault");return Q(e,r),p(n=>{const i=g(n,e,t.sessionId);if(i===null)return null;const d=I(n,e);if(d!==null&&(d.link!==r.link||d.kind!==r.kind)&&A(d)>A(r))return null;const s=n.prepare("SELECT fault_id FROM node_faults WHERE node_id = ? AND episode_state IS NOT NULL").all(e);n.prepare("UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE node_id = ? AND episode_state IS NOT NULL").run(a(),e);for(const N of s)R(n,N.fault_id);const c=z(n,e,r,{state:"pending",bindingId:i});return c===null?null:(n.prepare("UPDATE node_faults SET episode_state = ?, episode_binding_id = ?, updated_at = ? WHERE fault_id = ?").run("pending",i,a(),c.faultId),c)})}o(je,"recordPendingEpisode");function $e(e,t){return p(r=>{const n=g(r,e,t.sessionId);return n===null?!1:r.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,a(),e,t.faultId,n).changes>0})}o($e,"admitEpisode");function Be(e,t){return p(r=>{const n=g(r,e,t.sessionId);return n===null?!1:r.prepare("UPDATE node_faults SET episode_state = 'pending', updated_at = ? WHERE node_id = ? AND episode_state = 'admitted' AND episode_binding_id = ?").run(a(),e,n).changes>0})}o(Be,"reopenEpisode");function Ke(e,t){return p(r=>{const n=g(r,e,t.sessionId);return n===null?!1:r.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(a(),e,n).changes>0})}o(Ke,"invalidateEpisode");function Je(e,t){return p(r=>{const n=g(r,e,t.sessionId);if(n===null)return!1;const i=r.prepare("SELECT fault_id FROM node_faults WHERE node_id = ? AND episode_binding_id = ? AND episode_state IS NOT NULL").all(e,n);if(i.length===0)return!1;r.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(a(),e,n);for(const d of i)R(r,d.fault_id);return!0})}o(Je,"clearEpisode");function Ye(e){const t=T().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:G(t)}}o(Ye,"readEpisode");function Ge(e){const t=Z(e)===null;return{explanation(){if(!t)return null;const r=Z(e);if(r===null||r.link!=="crtr\u2192pi"||r.retry.disposition!=="fatal")return null;const n=r.op.trim(),i=r.message.trim();return n===""||i===""?null:`${n}: ${i}`}}}o(Ge,"beginBootFaultAttempt");function ee(e,t){try{return se(e).mtime.toISOString()}catch{return t}}o(ee,"markerMtime");function H(e,t){if(!_(e))return null;try{return ie(e,"utf8")}catch(r){if(!t)return null;throw new Error(`cannot import recovery input ${e}: ${r.message}`)}}o(H,"legacyFile");function Le(e,t){return e.prepare("SELECT execution_id, started_at FROM executions WHERE node_id = ? ORDER BY rowid DESC LIMIT 1").get(t)??null}o(Le,"latestExecution");function me(e,t){const n=$(e,"nodes").has("launched_at")?e.prepare("SELECT COALESCE(launched_at, created) AS started_at FROM nodes WHERE node_id = ?").get(t):e.prepare("SELECT created AS started_at FROM nodes WHERE node_id = ?").get(t);if(n===void 0)throw new Error(`cannot import recovery witness for unknown node ${t}`);const i=k();return e.prepare("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,n.started_at,n.started_at),{execution_id:i,started_at:n.started_at}}o(me,"syntheticExecution");function te(e,t,r,n,i){return F(e,t,r,n,i)}o(te,"insertMigratedFault");function xe(e,t,r,n){const i=e.prepare("SELECT binding_id, node_id FROM sessions WHERE transcript_path = ? AND unbound_at IS NULL").get(r);if(i!==void 0){if(i.node_id!==t)throw new Error(`cannot import provider retry ${n}: transcript is live-owned by ${i.node_id}`);return i.binding_id}const d=e.prepare("SELECT binding_id FROM sessions WHERE node_id = ? AND transcript_path = ? ORDER BY rowid DESC LIMIT 1").get(t,r);if(d!==void 0)return d.binding_id;const s=e.prepare("SELECT created FROM nodes WHERE node_id = ?").get(t);if(s===void 0)throw new Error(`cannot import provider retry ${n}: unknown node ${t}`);const c=k();return e.prepare("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(c,t,r,s.created,s.created,a()),c}o(xe,"migrationBinding");function Ve(e){if(fe(e),ye(e),!_(C()))return;const t=ne(C(),{withFileTypes:!0}).filter(n=>n.isDirectory()).sort((n,i)=>n.name.localeCompare(i.name)),r=e.prepare("SELECT 1 FROM nodes WHERE node_id = ?");for(const n of t){const i=n.name,d=ae(i),s=f(d,"busy"),c=f(d,"clean-abort"),N=f(d,"transport-poison.json"),h=f(d,"fault"),L=f(d,"provider-retry"),D=_(s),U=_(c);if(!D&&!U&&!_(N)&&!_(h)&&!_(L)||!_(f(C(),i,"meta.json"))&&r.get(i)===void 0)continue;const O=H(N,!1),m=H(h,!0),x=H(L,!0);if(!D&&!U&&O===null&&m===null&&x===null)continue;let l=Le(e,i);if(l===null&&(l=me(e,i)),D){const u=ee(s,l.started_at);e.prepare("UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = NULL, turn_end_reason = NULL WHERE execution_id = ?").run(u,u,l.execution_id)}else if(U){const u=ee(c,l.started_at);e.prepare("UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = ?, turn_end_reason = 'teardown-aborted' WHERE execution_id = ?").run(u,u,u,l.execution_id)}if(O!==null)try{const u=JSON.parse(O);Number.isInteger(u.consecutivePasses)&&u.consecutivePasses>=1&&Array.isArray(u.routes)&&u.routes.length>0&&u.routes.every(W=>typeof W=="string"&&W!=="")&&e.prepare("UPDATE executions SET exit_diagnostic_json = ? WHERE execution_id = ?").run(JSON.stringify({schema:"crtr.execution-exit-diagnostic/v1",transport_poison:{consecutive_passes:u.consecutivePasses,routes:u.routes}}),l.execution_id)}catch{}const S=m===null?null:K(m);if(m!==null&&S===null)throw new Error(`cannot import recovery fault ${h}`);const E=x===null?null:ge(x);if(x!==null&&E===null)throw new Error(`cannot import provider retry ${L}`);let v=S===null||S.link==="broker\u2194crtrd"?null:te(e,i,S,!0);if(E!==null){const u=xe(e,i,E.sessionFile,L);v!==null&&v.since===E.fault.since?e.prepare("UPDATE node_faults SET episode_state = ?, episode_binding_id = ?, updated_at = ? WHERE fault_id = ?").run(E.state,u,a(),v.faultId):te(e,i,E.fault,!1,{state:E.state,bindingId:u})}}}o(Ve,"migrateRecoveryWitnesses");export{ke as FAULT_QUIET_MS,$e as admitEpisode,Ge as beginBootFaultAttempt,Je as clearEpisode,Xe as clearFault,Fe as closeTurn,Ke as invalidateEpisode,Ve as migrateRecoveryWitnesses,Ce as openTurn,B as parseProviderError,Ye as readEpisode,Z as readFault,we as readInterruptedTurn,Pe as readLiveTurn,We as readTransportPoisonVerdict,Me as recordFault,je as recordPendingEpisode,He as recordTransportPoisonVerdict,be as recordTurnProgress,Be as reopenEpisode};
|
|
26
|
+
`)}o(ye,"createFaultTable");function y(e,t){return typeof t=="string"&&e.includes(t)}o(y,"contains");function b(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(b,"isRecord");function B(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,r=typeof e.code=="string"||typeof e.code=="number"?e.code:void 0,n=typeof e.errno=="string"?e.errno:void 0,i=typeof e.body=="string"?e.body:void 0,d=Array.isArray(e.causes)?e.causes.flatMap(s=>{if(!b(s))return[];const c={...typeof s.message=="string"?{message:s.message}:{},...typeof s.status=="number"&&Number.isFinite(s.status)?{status:s.status}:{},...typeof s.code=="string"||typeof s.code=="number"?{code:s.code}:{},...typeof s.errno=="string"?{errno:s.errno}:{},...typeof s.body=="string"?{body:s.body}:{}};return Object.keys(c).length===0?[]:[c]}):void 0;return{provider:e.provider,model:e.model,...t===void 0?{}:{status:t},...r===void 0?{}:{code:r},...n===void 0?{}:{errno:n},...i===void 0?{}:{body:i},...d===void 0||d.length===0?{}:{causes:d}}}o(B,"parseProviderError");function K(e){try{const t=JSON.parse(e);if(!y(ce,t.link)||typeof t.op!="string"||t.op===""||!y(pe,t.kind)||typeof t.message!="string"||typeof t.since!="string")return null;const r=X(t.operation_id);if(!b(t.retry)||!y(_e,t.retry.disposition)||t.retry.by!==void 0&&!y(le,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 n=t.providerError===void 0?void 0:B(t.providerError);return t.providerError!==void 0&&n===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:r,...t.anchorEntryId===void 0?{}:{anchorEntryId:t.anchorEntryId},...n===void 0?{}:{providerError:n}}}catch{return null}}o(K,"parseLegacyFault");function Te(e){const t=de(e);try{return oe(t)}catch{return t}}o(Te,"canonicalPath");function ge(e){try{const t=JSON.parse(e);if(!y(Ee,t.state)||typeof t.sessionFile!="string"||t.sessionFile==="")return null;const r=JSON.stringify(t.fault),n=K(r);if(n===null||n.link!=="pi\u2192provider"||n.retry.disposition!=="auto"||n.retry.by!=="daemon")return null;const i=t.anchorEntryId;return i!==null&&typeof i!="string"||(n.anchorEntryId??null)!==i?null:{state:t.state,sessionFile:Te(t.sessionFile),fault:n}}catch{return null}}o(ge,"parseLegacyEpisode");function J(e){return e!==void 0?X(e):M.current()??M.fresh(r=>r)}o(J,"resolveOperationId");function Ne(e){return e.slice(0,ue)}o(Ne,"clampMessage");function A(e){return e.link==="pi\u2192provider"&&e.retry.disposition==="auto"&&e.retry.by==="daemon"?3:e.retry.disposition==="fatal"?2:1}o(A,"faultPriority");function Y(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(Y,"encodeFault");function G(e){const t=e.provider_error_json,r=typeof t=="string"?B(JSON.parse(t)):void 0;if(typeof t=="string"&&r===void 0)throw new Error(`invalid provider error on stored fault ${e.fault_id}`);const n={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:n,...e.anchor_entry_id===null?{}:{anchorEntryId:e.anchor_entry_id},...r===void 0?{}:{providerError:r}}}o(G,"hydrateFault");function I(e,t){const r=e.prepare("SELECT * FROM node_faults WHERE node_id = ? AND active = 1").get(t);return r===void 0?null:G(r)}o(I,"activeFault");function V(e){if(!y(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:Ne(e.message),since:e.since??a(),operation_id:J(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){w({level:t.retry.disposition==="fatal"?"error":"warn",event:"fault.recorded",operation_id:t.operation_id,node_id:e,error_class:P(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");function F(e,t,r,n,i){const d=k(),s=Y(r),c=a();return e.prepare("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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(d,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,n?1:0,i?.state??null,i?.bindingId??null,c,c),{...r,faultId:d}}o(F,"insertFault");function q(e,t,r,n){const i=Y(r);return 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,n?.state??null,n?.bindingId??null,a(),t),{...r,faultId:t}}o(q,"updateFault");function R(e,t){e.prepare("DELETE FROM node_faults WHERE fault_id = ? AND active = 0 AND episode_state IS NULL").run(t)}o(R,"deleteIfUnretained");function z(e,t,r,n){const i=I(e,t);if(i===null){const d=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 d!==void 0&&d.link===r.link&&d.kind===r.kind&&d.since===r.since&&d.operation_id===r.operation_id?(e.prepare("UPDATE node_faults SET active = 1, updated_at = ? WHERE fault_id = ?").run(a(),d.fault_id),q(e,d.fault_id,r)):F(e,t,r,!0,n)}if(i.link===r.link&&i.kind===r.kind){const d={...i.retry,...r.retry};return r.retry.disposition==="fatal"&&!("nextAt"in r.retry)&&delete d.nextAt,q(e,i.faultId,{...r,since:i.since,anchorEntryId:i.anchorEntryId??r.anchorEntryId,retry:d},n)}return A(i)>A(r)?null:(e.prepare("UPDATE node_faults SET active = 0, updated_at = ? WHERE fault_id = ?").run(a(),i.faultId),R(e,i.faultId),F(e,t,r,!0,n))}o(z,"replaceActiveFault");function g(e,t,r){return e.prepare("SELECT binding_id FROM sessions WHERE node_id = ? AND session_id = ? AND unbound_at IS NULL").get(t,r)?.binding_id??null}o(g,"liveBinding");function Ce(e,t){return p(r=>{const n=a();return r.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(n,e).changes>0?!0:r.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(n,n,e).changes>0})}o(Ce,"openTurn");function be(e){return p(t=>t.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(a(),e).changes>0)}o(be,"recordTurnProgress");function Fe(e,t){return p(r=>r.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(a(),t.endReason,e).changes>0)}o(Fe,"closeTurn");function He(e,t){if(!Number.isInteger(t.consecutivePasses)||t.consecutivePasses<1||t.routes.length===0||!t.routes.every(r=>r!==""))throw new Error("invalid transport-poison verdict");return p(r=>r.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(He,"recordTransportPoisonVerdict");function We(e){const t=T().prepare("SELECT exit_diagnostic_json FROM executions WHERE node_id = ? ORDER BY rowid DESC LIMIT 1").get(e);if(t===void 0||t.exit_diagnostic_json===null)return null;try{const r=JSON.parse(t.exit_diagnostic_json),n=r.transport_poison;return r.schema!=="crtr.execution-exit-diagnostic/v1"||n===void 0||!Number.isInteger(n.consecutive_passes)||n.consecutive_passes<1||!Array.isArray(n.routes)||n.routes.length===0||!n.routes.every(i=>typeof i=="string"&&i!=="")?null:{consecutivePasses:n.consecutive_passes,routes:n.routes}}catch{return null}}o(We,"readTransportPoisonVerdict");function Pe(e){const t=T().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(Pe,"readLiveTurn");function we(e){const t=T(),r=t.prepare("SELECT turn_closed_at, turn_progress_at FROM executions WHERE node_id = ? AND turn_open_at IS NOT NULL ORDER BY rowid DESC LIMIT 1").get(e);if(r===void 0)return null;const n=t.prepare("SELECT turn_end_reason FROM executions WHERE node_id = ? ORDER BY rowid DESC LIMIT 1").get(e);return{interrupted:r.turn_closed_at===null||n?.turn_end_reason==="teardown-aborted",progressAt:r.turn_progress_at}}o(we,"readInterruptedTurn");function Me(e,t){const r=V(t);return Q(e,r),p(n=>z(n,e,r))}o(Me,"recordFault");function Xe(e,t){return p(r=>{const n=I(r,e);if(n===null||t?.link!==void 0&&n.link!==t.link)return!1;const i=r.prepare("SELECT episode_state FROM node_faults WHERE fault_id = ?").get(n.faultId);r.prepare("UPDATE node_faults SET active = 0, updated_at = ? WHERE fault_id = ?").run(a(),n.faultId),i.episode_state==="pending"&&t?.preserveEpisode!==!0&&r.prepare("UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE fault_id = ?").run(a(),n.faultId),R(r,n.faultId);const d=J();return w({level:"info",event:"fault.cleared",operation_id:d,node_id:e,error_class:P(n),fields:{cleared_fault_operation_id:n.operation_id,link:n.link,op:n.op,kind:n.kind,retry:n.retry,message:n.message,since:n.since,...n.anchorEntryId===void 0?{}:{anchor_entry_id:n.anchorEntryId}}}),!0})}o(Xe,"clearFault");function Z(e){return I(T(),e)}o(Z,"readFault");function je(e,t){const r=V(t.input);if(r.link!=="pi\u2192provider"||r.retry.disposition!=="auto"||r.retry.by!=="daemon")throw new Error("provider retry episode requires an automatic daemon provider fault");return Q(e,r),p(n=>{const i=g(n,e,t.sessionId);if(i===null)return null;const d=I(n,e);if(d!==null&&(d.link!==r.link||d.kind!==r.kind)&&A(d)>A(r))return null;const s=n.prepare("SELECT fault_id FROM node_faults WHERE node_id = ? AND episode_state IS NOT NULL").all(e);n.prepare("UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE node_id = ? AND episode_state IS NOT NULL").run(a(),e);for(const N of s)R(n,N.fault_id);const c=z(n,e,r,{state:"pending",bindingId:i});return c===null?null:(n.prepare("UPDATE node_faults SET episode_state = ?, episode_binding_id = ?, updated_at = ? WHERE fault_id = ?").run("pending",i,a(),c.faultId),c)})}o(je,"recordPendingEpisode");function $e(e,t){return p(r=>{const n=g(r,e,t.sessionId);return n===null?!1:r.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,a(),e,t.faultId,n).changes>0})}o($e,"admitEpisode");function Be(e,t){return p(r=>{const n=g(r,e,t.sessionId);return n===null?!1:r.prepare("UPDATE node_faults SET episode_state = 'pending', updated_at = ? WHERE node_id = ? AND episode_state = 'admitted' AND episode_binding_id = ?").run(a(),e,n).changes>0})}o(Be,"reopenEpisode");function Ke(e,t){return p(r=>{const n=g(r,e,t.sessionId);return n===null?!1:r.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(a(),e,n).changes>0})}o(Ke,"invalidateEpisode");function Je(e,t){return p(r=>{const n=g(r,e,t.sessionId);if(n===null)return!1;const i=r.prepare("SELECT fault_id FROM node_faults WHERE node_id = ? AND episode_binding_id = ? AND episode_state IS NOT NULL").all(e,n);if(i.length===0)return!1;r.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(a(),e,n);for(const d of i)R(r,d.fault_id);return!0})}o(Je,"clearEpisode");function Ye(e){const t=T().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:G(t)}}o(Ye,"readEpisode");function Ge(e){const t=Z(e)===null;return{explanation(){if(!t)return null;const r=Z(e);if(r===null||r.link!=="crtr\u2192pi"||r.retry.disposition!=="fatal")return null;const n=r.op.trim(),i=r.message.trim();return n===""||i===""?null:`${n}: ${i}`}}}o(Ge,"beginBootFaultAttempt");function ee(e,t){try{return se(e).mtime.toISOString()}catch{return t}}o(ee,"markerMtime");function H(e,t){if(!_(e))return null;try{return ie(e,"utf8")}catch(r){if(!t)return null;throw new Error(`cannot import recovery input ${e}: ${r.message}`)}}o(H,"legacyFile");function Le(e,t){return e.prepare("SELECT execution_id, started_at FROM executions WHERE node_id = ? ORDER BY rowid DESC LIMIT 1").get(t)??null}o(Le,"latestExecution");function me(e,t){const n=$(e,"nodes").has("launched_at")?e.prepare("SELECT COALESCE(launched_at, created) AS started_at FROM nodes WHERE node_id = ?").get(t):e.prepare("SELECT created AS started_at FROM nodes WHERE node_id = ?").get(t);if(n===void 0)throw new Error(`cannot import recovery witness for unknown node ${t}`);const i=k();return e.prepare("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,n.started_at,n.started_at),{execution_id:i,started_at:n.started_at}}o(me,"syntheticExecution");function te(e,t,r,n,i){return F(e,t,r,n,i)}o(te,"insertMigratedFault");function xe(e,t,r,n){const i=e.prepare("SELECT binding_id, node_id FROM sessions WHERE transcript_path = ? AND unbound_at IS NULL").get(r);if(i!==void 0){if(i.node_id!==t)throw new Error(`cannot import provider retry ${n}: transcript is live-owned by ${i.node_id}`);return i.binding_id}const d=e.prepare("SELECT binding_id FROM sessions WHERE node_id = ? AND transcript_path = ? ORDER BY rowid DESC LIMIT 1").get(t,r);if(d!==void 0)return d.binding_id;const s=e.prepare("SELECT created FROM nodes WHERE node_id = ?").get(t);if(s===void 0)throw new Error(`cannot import provider retry ${n}: unknown node ${t}`);const c=k();return e.prepare("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(c,t,r,s.created,s.created,a()),c}o(xe,"migrationBinding");function Ve(e){if(fe(e),ye(e),!_(C()))return;const t=ne(C(),{withFileTypes:!0}).filter(n=>n.isDirectory()).sort((n,i)=>n.name.localeCompare(i.name)),r=e.prepare("SELECT 1 FROM nodes WHERE node_id = ?");for(const n of t){const i=n.name,d=ae(i),s=f(d,"busy"),c=f(d,"clean-abort"),N=f(d,"transport-poison.json"),h=f(d,"fault"),L=f(d,"provider-retry"),D=_(s),U=_(c);if(!D&&!U&&!_(N)&&!_(h)&&!_(L)||!_(f(C(),i,"meta.json"))&&r.get(i)===void 0)continue;const O=H(N,!1),m=H(h,!0),x=H(L,!0);if(!D&&!U&&O===null&&m===null&&x===null)continue;let l=Le(e,i);if(l===null&&(l=me(e,i)),D){const u=ee(s,l.started_at);e.prepare("UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = NULL, turn_end_reason = NULL WHERE execution_id = ?").run(u,u,l.execution_id)}else if(U){const u=ee(c,l.started_at);e.prepare("UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = ?, turn_end_reason = 'teardown-aborted' WHERE execution_id = ?").run(u,u,u,l.execution_id)}if(O!==null)try{const u=JSON.parse(O);Number.isInteger(u.consecutivePasses)&&u.consecutivePasses>=1&&Array.isArray(u.routes)&&u.routes.length>0&&u.routes.every(W=>typeof W=="string"&&W!=="")&&e.prepare("UPDATE executions SET exit_diagnostic_json = ? WHERE execution_id = ?").run(JSON.stringify({schema:"crtr.execution-exit-diagnostic/v1",transport_poison:{consecutive_passes:u.consecutivePasses,routes:u.routes}}),l.execution_id)}catch{}const S=m===null?null:K(m);if(m!==null&&S===null)throw new Error(`cannot import recovery fault ${h}`);const E=x===null?null:ge(x);if(x!==null&&E===null)throw new Error(`cannot import provider retry ${L}`);let v=S===null||S.link==="broker\u2194crtrd"?null:te(e,i,S,!0);if(E!==null){const u=xe(e,i,E.sessionFile,L);v!==null&&v.since===E.fault.since?e.prepare("UPDATE node_faults SET episode_state = ?, episode_binding_id = ?, updated_at = ? WHERE fault_id = ?").run(E.state,u,a(),v.faultId):te(e,i,E.fault,!1,{state:E.state,bindingId:u})}}}o(Ve,"migrateRecoveryWitnesses");export{ke as FAULT_QUIET_MS,$e as admitEpisode,Ge as beginBootFaultAttempt,Je as clearEpisode,Xe as clearFault,Fe as closeTurn,G as hydrateFault,Ke as invalidateEpisode,Ve as migrateRecoveryWitnesses,Ce as openTurn,B as parseProviderError,Ye as readEpisode,Z as readFault,we as readInterruptedTurn,Pe as readLiveTurn,We as readTransportPoisonVerdict,Me as recordFault,je as recordPendingEpisode,He as recordTransportPoisonVerdict,be as recordTurnProgress,Be as reopenEpisode};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DatabaseSync } from 'node:sqlite';
|
|
2
2
|
import type { ManagedWorktree, ManagedWorktreeObservation } from './types.js';
|
|
3
|
+
export declare function worktreeFromRow(row: Record<string, unknown> | undefined): ManagedWorktree | null;
|
|
3
4
|
export declare function readWorktree(nodeId: string): ManagedWorktree | null;
|
|
4
5
|
export declare function openWorktree(nodeId: string, worktree: ManagedWorktree, db?: DatabaseSync): void;
|
|
5
6
|
export declare function closeWorktree(nodeId: string, input: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var p=Object.defineProperty;var n=(e,t)=>p(e,"name",{value:t,configurable:!0});import{openDb as a,withCanvasWrite as _}from"./db.js";function d(e){const t=JSON.stringify(e);if(t===void 0)throw new TypeError("worktree value must be JSON-serializable");return t}n(d,"json");function o(e){if(typeof e=="string")return JSON.parse(e)}n(o,"parse");function l(e){if(e===void 0)return null;const t=o(e.sweep_observed_json),s=e.attempts,r=t===void 0?void 0:{reason:e.sweep_reason,...e.sweep_detail===null?{}:{detail:e.sweep_detail},observed:t,attempts:s,last_attempt:e.sweep_last_at,next_attempt:e.next_attempt_at,...e.quarantined===1?{quarantined:!0}:{}};return{state:e.state,...e.cleanup_state===null?{}:{cleanup:e.cleanup_state},path:e.path,branch:e.branch,repo_root:e.repo_root,base_ref:e.base_ref,base_sha:e.base_sha,created:e.created_at,...e.closed_at===null?{}:{closed:e.closed_at},...o(e.abandoned_json)===void 0?{}:{abandoned:o(e.abandoned_json)},...o(e.land_intent_json)===void 0?{}:{land_intent:o(e.land_intent_json)},...r===void 0?{}:{sweep:r},...o(e.disposal_json)===void 0?{}:{disposal:o(e.disposal_json)}}}n(l,"worktreeFromRow");function i(e){return l(a().prepare("SELECT * FROM worktrees WHERE node_id = ?").get(e))}n(i,"readWorktree");function L(e,t,s=a()){s.prepare("INSERT INTO worktrees (node_id, 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) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL)").run(e,t.state,t.cleanup??null,t.path,t.branch,t.repo_root,t.base_ref,t.base_sha,t.created,t.closed??null)}n(L,"openWorktree");function E(e,t){a().prepare("UPDATE worktrees SET state = 'closed', cleanup_state = ?, closed_at = ?, land_intent_json = NULL, sweep_reason = NULL, sweep_detail = NULL, sweep_last_at = NULL, sweep_observed_json = NULL, next_attempt_at = NULL, attempts = 0, quarantined = 0 WHERE node_id = ?").run(t.cleanup,t.closedAt,e)}n(E,"closeWorktree");function N(e,t){_(s=>{s.prepare("UPDATE nodes SET cwd = ? WHERE node_id = ?").run(t.cwd,e),t.unbindSession&&s.prepare("UPDATE sessions SET unbound_at = ? WHERE node_id = ? AND unbound_at IS NULL").run(t.closedAt,e),s.prepare("UPDATE worktrees SET state = 'closed', cleanup_state = ?, closed_at = ?, land_intent_json = NULL, sweep_reason = NULL, sweep_detail = NULL, sweep_last_at = NULL, sweep_observed_json = NULL, next_attempt_at = NULL, attempts = 0, quarantined = 0 WHERE node_id = ?").run(t.cleanup,t.closedAt,e)})}n(N,"closeWorktreeAndRepoint");function U(e,t){a().prepare("UPDATE worktrees SET state = 'abandoned', abandoned_json = ? WHERE node_id = ? AND abandoned_json IS NULL").run(d(t),e)}n(U,"abandonWorktree");function f(e,t){_(s=>{s.prepare("UPDATE nodes SET cwd = ? WHERE node_id = ?").run(t.cwd,e),s.prepare("UPDATE worktrees SET state = 'abandoned', abandoned_json = ? WHERE node_id = ? AND abandoned_json IS NULL").run(d(t.abandoned),e)})}n(f,"abandonWorktreeAndRepoint");function b(e,t){a().prepare("UPDATE worktrees SET land_intent_json = ? WHERE node_id = ? AND land_intent_json IS NULL").run(d(t),e)}n(b,"recordLandIntent");function A(e,t){a().prepare("UPDATE worktrees SET disposal_json = ? WHERE node_id = ? AND disposal_json IS NULL").run(d(t),e)}n(A,"recordDisposalGrant");function w(e,t){a().prepare("UPDATE worktrees SET sweep_reason = ?, sweep_detail = ?, sweep_observed_json = ?, attempts = ?, sweep_last_at = ?, next_attempt_at = ?, quarantined = ? WHERE node_id = ?").run(t.reason,t.detail??null,d(t.observed),t.attempts,t.lastAttemptAt,t.nextAttemptAt,t.quarantined?1:0,e)}n(w,"recordSweepAttempt");function R(e){a().prepare("UPDATE worktrees SET state = 'closed', cleanup_state = 'complete', sweep_reason = NULL, sweep_detail = NULL, sweep_last_at = NULL, sweep_observed_json = NULL, next_attempt_at = NULL, attempts = 0, quarantined = 0 WHERE node_id = ?").run(e)}n(R,"completeCleanup");function S(e){return a().prepare("SELECT 1 FROM worktrees WHERE node_id = ? AND state != 'abandoned' AND (state = 'open' OR cleanup_state IS NULL OR cleanup_state != 'complete')").get(e)!==void 0}n(S,"hasUnreconciledWorktree");function m(e){return a().prepare("SELECT w.node_id FROM worktrees w JOIN nodes n ON n.node_id = w.node_id WHERE n.status IN ('done', 'dead', 'canceled') AND n.frozen_at IS NULL AND w.state IN ('open', 'closed') AND (w.state = 'open' OR w.cleanup_state IS NULL OR w.cleanup_state != 'complete') AND (w.state = 'closed' OR (n.status = 'done' AND n.final_report IS NOT NULL)) AND (w.next_attempt_at IS NULL OR w.next_attempt_at <= ?) ORDER BY w.next_attempt_at, w.node_id").all(e).map(({node_id:t})=>t)}n(m,"sweepCandidates");function T(){return a().prepare("SELECT node_id FROM worktrees WHERE quarantined = 1 ORDER BY sweep_last_at").all().flatMap(({node_id:e})=>{const t=i(e);return t===null?[]:[{nodeId:e,worktree:t}]})}n(T,"quarantinedWorktrees");export{U as abandonWorktree,f as abandonWorktreeAndRepoint,E as closeWorktree,N as closeWorktreeAndRepoint,R as completeCleanup,S as hasUnreconciledWorktree,L as openWorktree,T as quarantinedWorktrees,i as readWorktree,A as recordDisposalGrant,b as recordLandIntent,w as recordSweepAttempt,m as sweepCandidates,l as worktreeFromRow};
|
|
@@ -97,6 +97,7 @@ export declare function getRequestByCompanion(nodeId: string): HumanRequestRecor
|
|
|
97
97
|
export declare function getRequestByIdempotencyKey(key: string): HumanRequestRecord | null;
|
|
98
98
|
export declare function listOpenInboxRequests(): HumanRequestRecord[];
|
|
99
99
|
export declare function openRequestsByRequester(nodeId: string): HumanRequestRecord[];
|
|
100
|
+
export declare function hasOpenReplyBearingRequestByRequester(nodeId: string): boolean;
|
|
100
101
|
/** Indexed attention projection: only open inbox-listed requests with a reply target keep a node wakeable. */
|
|
101
102
|
export declare function listOpenReplyBearingRequests(): HumanRequestRecord[];
|
|
102
103
|
export declare function listBindingRequests(): HumanRequestRecord[];
|
|
@@ -1,38 +1,42 @@
|
|
|
1
|
-
var
|
|
2
|
-
`),r.syncFile(u),r.syncDirectory(n),r.syncDirectory(s),r.syncDirectory(e),r.syncDirectory(
|
|
1
|
+
var de=Object.defineProperty;var i=(e,t)=>de(e,"name",{value:t,configurable:!0});import{createHash as ue,randomBytes as j}from"node:crypto";import{existsSync as g,mkdirSync as A,readFileSync as V,readdirSync as ce,realpathSync as O,statSync as le,writeFileSync as _e}from"node:fs";import{basename as w,join as c}from"node:path";import{z as d}from"zod";import{crtrHome as z,isSafeNodeId as pe,nodesRoot as N}from"../canvas/paths.js";import{openDb as _,withCanvasWrite as f}from"../canvas/db.js";import{syncDirectory as me,syncFile as fe}from"../fs-utils.js";import{newNodeId as Ee}from"../runtime/nodes.js";import{pageManifestPath as ge,pageModulePath as ye,pagePath as he}from"./convention.js";import{preparePageSource as be}from"./page-authoring.js";import{pageDeliverySchema as qe,validatePageManifest as G}from"./page-schema.js";function Q(e){return e===1||e===!0}i(Q,"bool");function Y(e){return{request_id:e.request_id,kind:e.kind,inbox_ticket_id:e.inbox_ticket_id,request_dir:e.request_dir,presentation_dir:e.presentation_dir,requester_node_id:e.requester_node_id,companion_node_id:e.companion_node_id,idempotency_key:e.idempotency_key,state:e.state,outcome:e.outcome,inbox_listed:Q(e.inbox_listed),settleable:Q(e.settleable),title:e.title,subtitle:e.subtitle,file:e.file,specification_json:e.specification_json,action_json:e.action_json,progress_json:e.progress_json,feedback_json:e.feedback_json,result_json:e.result_json,anchor_base_sha256:e.anchor_base_sha256,anchor_base_bytes:e.anchor_base_bytes===null?null:Buffer.from(e.anchor_base_bytes),created_at:e.created_at,opened_at:e.opened_at,submit_requested_at:e.submit_requested_at,settled_at:e.settled_at,settlement_delivery_id:e.settlement_delivery_id,action_delivery_id:e.action_delivery_id,submit_note_delivery_id:e.submit_note_delivery_id,projected_at:e.projected_at,projection_error:e.projection_error,companion_retired_at:e.companion_retired_at,updated_at:e.updated_at}}i(Y,"recordFromRow");function b(e,t,...r){const s=e.prepare(`SELECT * FROM human_requests WHERE ${t}`).get(...r);return s===void 0?null:Y(s)}i(b,"one");function T(e,t,r=[],s="created_at ASC, request_id ASC"){return e.prepare(`SELECT * FROM human_requests WHERE ${t} ORDER BY ${s}`).all(...r).map(Y)}i(T,"many");function Z(){return c(z(),"requests")}i(Z,"humanRequestsRoot");function C(e){if(!pe(e))throw new TypeError(`request_id must be a safe path segment: ${e}`);const t=Z();return A(t,{recursive:!0,mode:448}),c(O(t),e)}i(C,"requestDir");function P(){return j(32).toString("hex")}i(P,"randomTicketId");function U(e,t){return ue("sha256").update(`${O(e)}\0${t}`,"utf8").digest("hex")}i(U,"legacyTicketId");const Ne={writeFile(e,t){_e(e,t,{flag:"wx",mode:384})},syncFile:fe,syncDirectory:me};function Te(e){return c(e,"revisions")}i(Te,"revisionRoot");function ee(e,t,r=Ne){A(e,{recursive:!0,mode:448});const s=Te(e);A(s,{recursive:!0,mode:448});const n=c(s,j(16).toString("hex"));A(n,{mode:448});const o=he(n,t.manifest.dialect);if(r.writeFile(o,t.document),r.syncFile(o),t.manifest.dialect==="jsx"){const a=ye(n);r.writeFile(a,t.module),r.syncFile(a)}const u=ge(n);return r.writeFile(u,`${JSON.stringify(t.manifest,null,2)}
|
|
2
|
+
`),r.syncFile(u),r.syncDirectory(n),r.syncDirectory(s),r.syncDirectory(e),r.syncDirectory(Z()),n}i(ee,"publishPageRevision");function ze(e){if(e.kind!=="page"||e.presentation_dir===null)throw new Error(`page request has no selected presentation: ${e.request_id}`);return e.presentation_dir}i(ze,"presentationDir");function Ge(e){const t=e.request_id??Ee(),r=C(t),s=ee(r,e.prepared),n=new Date().toISOString(),o=e.prepared.manifest;return f(u=>{u.prepare(`
|
|
3
3
|
INSERT INTO human_requests (
|
|
4
4
|
request_id, kind, inbox_ticket_id, request_dir, presentation_dir, requester_node_id, state, inbox_listed,
|
|
5
5
|
settleable, title, subtitle, specification_json, action_json, created_at, updated_at
|
|
6
6
|
) VALUES (?, 'page', ?, ?, ?, ?, 'open', ?, ?, ?, ?, ?, ?, ?, ?)
|
|
7
|
-
`).run(t,e.inbox_ticket_id??
|
|
7
|
+
`).run(t,e.inbox_ticket_id??P(),r,s,e.requester_node_id??null,o.delivery.inbox?1:0,o.delivery.inbox||o.delivery.reply?1:0,o.title,o.subtitle??null,JSON.stringify(o),e.action_json??null,n,n);const a=b(u,"request_id = ?",t);if(a===null)throw new Error(`page request insert did not produce a row: ${t}`);return a})}i(Ge,"createPageRequest");function Qe(e){return f(t=>{const r=t.prepare(`
|
|
8
8
|
INSERT INTO human_requests (
|
|
9
9
|
request_id, kind, inbox_ticket_id, request_dir, requester_node_id, companion_node_id,
|
|
10
10
|
idempotency_key, state, inbox_listed, settleable, title, subtitle, file,
|
|
11
11
|
specification_json, anchor_base_sha256, anchor_base_bytes, created_at, updated_at
|
|
12
12
|
) VALUES (?, 'review', ?, ?, ?, ?, ?, 'binding', ?, 1, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
13
13
|
ON CONFLICT(idempotency_key) DO NOTHING
|
|
14
|
-
`).run(e.request_id,
|
|
14
|
+
`).run(e.request_id,P(),e.request_dir,e.requester_node_id,e.companion_node_id,e.idempotency_key,e.inbox_listed?1:0,w(e.file),e.subtitle??null,e.file,JSON.stringify(e.specification),e.anchor_base_sha256,e.anchor_base_bytes,e.created_at,e.created_at),s=b(t,"idempotency_key = ?",e.idempotency_key);if(s===null)throw new Error(`review binding insert did not produce a row: ${e.idempotency_key}`);return{request_id:s.request_id,won:r.changes>0}})}i(Qe,"commitBindingRequest");function Ye(e){return b(_(),"request_id = ?",e)}i(Ye,"getRequest");function Ze(e){return b(_(),"inbox_ticket_id = ?",e)}i(Ze,"getRequestByInboxTicket");function et(e){let t=e;try{t=O(e)}catch{}return b(_(),"request_dir = ?",t)}i(et,"getRequestByDirectory");function tt(e){return b(_(),"companion_node_id = ? AND state <> 'binding'",e)}i(tt,"getRequestByCompanion");function nt(e){return b(_(),"idempotency_key = ?",e)}i(nt,"getRequestByIdempotencyKey");function rt(){return T(_(),"state = 'open' AND inbox_listed = 1",[],"created_at DESC, request_id DESC")}i(rt,"listOpenInboxRequests");function Se(e){return T(_(),"state = 'open' AND requester_node_id = ?",[e],"created_at DESC, request_id DESC")}i(Se,"openRequestsByRequester");function it(e){return Se(e).some(t=>t.kind==="review"?!0:JSON.parse(t.specification_json).delivery?.reply===!0)}i(it,"hasOpenReplyBearingRequestByRequester");function st(){return T(_(),"state = 'open' AND inbox_listed = 1 AND requester_node_id IS NOT NULL",[],"created_at DESC, request_id DESC")}i(st,"listOpenReplyBearingRequests");function ot(){return T(_(),"kind = 'review' AND state = 'binding'")}i(ot,"listBindingRequests");function at(){return T(_(),"kind = 'review' AND state = 'open' AND submit_requested_at IS NOT NULL")}i(at,"listSubmitRequestedRequests");function dt(){return T(_(),"kind = 'review' AND state = 'settled' AND projected_at IS NULL")}i(dt,"listUnprojectedReviews");function ut(e={}){const t=["1"],r=[];for(const[s,n]of Object.entries(e))n!==void 0&&(t.push(`${s} = ?`),r.push(n));return T(_(),t.join(" AND "),r)}i(ut,"listRequests");function ct(e,t){return f(r=>r.prepare("UPDATE human_requests SET state = 'open', opened_at = ?, updated_at = ? WHERE request_id = ? AND state = 'binding'").run(t,t,e).changes>0)}i(ct,"openRequest");function lt(e,t,r){return f(s=>s.prepare(`
|
|
15
15
|
UPDATE human_requests SET state = 'settled', outcome = 'canceled', result_json = ?, settled_at = ?, updated_at = ?
|
|
16
16
|
WHERE request_id = ? AND kind = 'review' AND state = 'binding'
|
|
17
|
-
`).run(JSON.stringify({schema:"humanloop.cancel/v1",kind:"canceled",canceledAt:t,reason:r}),t,t,e).changes>0)}i(
|
|
17
|
+
`).run(JSON.stringify({schema:"humanloop.cancel/v1",kind:"canceled",canceledAt:t,reason:r}),t,t,e).changes>0)}i(lt,"cancelBindingRequest");function _t(e,t){return f(r=>r.prepare("UPDATE human_requests SET submit_requested_at = ?, updated_at = ? WHERE request_id = ? AND kind = 'review' AND state = 'open' AND submit_requested_at IS NULL").run(t,t,e).changes>0)}i(_t,"requestSubmit");function pt(e,t){return e.prepare(`
|
|
18
18
|
UPDATE human_requests SET state = 'settled', outcome = ?, result_json = ?, settled_at = ?,
|
|
19
19
|
progress_json = NULL, updated_at = ?
|
|
20
20
|
WHERE request_id = ? AND state = 'open'
|
|
21
|
-
`).run(t.outcome,t.result_json,t.settled_at,t.settled_at,t.request_id).changes===0?null:
|
|
21
|
+
`).run(t.outcome,t.result_json,t.settled_at,t.settled_at,t.request_id).changes===0?null:b(e,"request_id = ?",t.request_id)}i(pt,"settleRequestLocked");function mt(e,t,r){e.prepare("UPDATE human_requests SET settlement_delivery_id = ?, action_delivery_id = ?, updated_at = ? WHERE request_id = ?").run(r.settlement_delivery_id??null,r.action_delivery_id??null,new Date().toISOString(),t)}i(mt,"setSettlementDeliveryMarksLocked");function ft(e,t,r){return e.prepare("UPDATE human_requests SET submit_note_delivery_id = ?, updated_at = ? WHERE request_id = ? AND state = 'open' AND submit_note_delivery_id IS NULL").run(r,new Date().toISOString(),t).changes>0}i(ft,"setSubmitNoteDeliveryLocked");function Et(e,t){return f(r=>r.prepare(`
|
|
22
22
|
UPDATE human_requests SET presentation_dir = ?, specification_json = ?, title = ?, subtitle = ?, inbox_listed = ?, settleable = ?, updated_at = ?
|
|
23
23
|
WHERE request_id = ? AND kind = 'page' AND state = 'open'
|
|
24
|
-
`).run(t.presentation_dir,t.specification_json,t.title,t.subtitle,t.inbox_listed?1:0,t.settleable?1:0,new Date().toISOString(),e).changes>0)}i(
|
|
24
|
+
`).run(t.presentation_dir,t.specification_json,t.title,t.subtitle,t.inbox_listed?1:0,t.settleable?1:0,new Date().toISOString(),e).changes>0)}i(Et,"revisePageRequest");function gt(e,t){return f(r=>r.prepare(`
|
|
25
25
|
UPDATE human_requests SET progress_json = ?, updated_at = ?
|
|
26
26
|
WHERE inbox_ticket_id = ? AND kind = 'page' AND state = 'open' AND settleable = 1
|
|
27
|
-
`).run(JSON.stringify({kind:"page",responses:t,savedAt:new Date().toISOString()}),new Date().toISOString(),e).changes>0)}i(
|
|
27
|
+
`).run(JSON.stringify({kind:"page",responses:t,savedAt:new Date().toISOString()}),new Date().toISOString(),e).changes>0)}i(gt,"writeProgress");function yt(e,t){f(r=>r.prepare("UPDATE human_requests SET projected_at = ?, projection_error = NULL, updated_at = ? WHERE request_id = ?").run(t,t,e))}i(yt,"markProjected");function ht(e,t){f(r=>r.prepare("UPDATE human_requests SET projection_error = ?, updated_at = ? WHERE request_id = ? AND projected_at IS NULL").run(t,new Date().toISOString(),e))}i(ht,"markProjectionError");function bt(e,t){f(r=>r.prepare("UPDATE human_requests SET companion_retired_at = ?, updated_at = ? WHERE request_id = ? AND companion_retired_at IS NULL").run(t,t,e))}i(bt,"markCompanionRetired");function qt(e){const t=_().prepare("SELECT anchor_base_bytes, anchor_base_sha256 FROM human_requests WHERE request_id = ?").get(e);return t===void 0||t.anchor_base_bytes===null||t.anchor_base_sha256===null?null:{bytes:Buffer.from(t.anchor_base_bytes),sha256:t.anchor_base_sha256}}i(qt,"readAnchorBase");function Nt(e,t,r,s){e.prepare("UPDATE human_requests SET anchor_base_bytes = ?, anchor_base_sha256 = ?, updated_at = ? WHERE request_id = ?").run(r,s,new Date().toISOString(),t)}i(Nt,"replaceAnchorBaseLocked");function ve(e){if(typeof e!="object"||e===null)throw new Error("result is not an object");const t=e;return t.kind==="canceled"?{outcome:t.disposition==="dismissed"?"dismissed":"canceled",settledAt:String(t.canceledAt)}:{outcome:"answered",settledAt:String(t.completedAt)}}i(ve,"legacyPageResult");function R(e){try{return JSON.parse(V(e,"utf8"))}catch(t){throw new Error(`corrupt required input: ${e}`,{cause:t})}}i(R,"readJson");function H(){return j(16).toString("hex")}i(H,"migrationId");function Re(e){return Number(e.prepare("SELECT COALESCE(MAX(seq), 0) AS seq FROM messages").get().seq)+1}i(Re,"nextMessageSeq");function Ae(e,t,r,s){return(s==="page"?e.prepare(`SELECT d.delivery_id FROM deliveries d JOIN messages m ON m.message_id = d.message_id
|
|
28
28
|
WHERE d.destination_kind = 'node_inbox' AND d.destination_id = ? AND m.sender_node_id = ?
|
|
29
29
|
AND m.disposition IN ('human-answer', 'human-canceled') LIMIT 1`).get(r,t):e.prepare(`SELECT d.delivery_id FROM deliveries d JOIN messages m ON m.message_id = d.message_id
|
|
30
|
-
WHERE d.destination_kind = 'node_inbox' AND d.destination_id = ? AND m.body_json LIKE ? LIMIT 1`).get(r,`%"review_id":"${t}"%`))?.delivery_id??null}i(
|
|
30
|
+
WHERE d.destination_kind = 'node_inbox' AND d.destination_id = ? AND m.body_json LIKE ? LIMIT 1`).get(r,`%"review_id":"${t}"%`))?.delivery_id??null}i(Ae,"importedTerminalDelivery");function te(e,t,r){if(t===null||r===null)return!1;const s=e.prepare("SELECT status, final_report FROM nodes WHERE node_id = ?").get(t);return s?.status==="canceled"||r==="approved"&&s?.status==="done"&&s.final_report!==null}i(te,"companionRetirementProven");function ne(e){if(typeof e!="object"||e===null)return"no reason was given";const t=e.reason;return typeof t=="string"&&t!==""?t:"no reason was given"}i(ne,"migratedCancellationReason");function De(e,t){const r=e.outcome==="canceled"||e.outcome==="dismissed";return[e.kind==="review"?r?`Review ${e.requestId} was canceled \u2014 ${ne(t)}.`:`Review ${e.requestId} was approved by the user.`:r?`Human request ${e.requestId} was canceled \u2014 ${ne(t)}.`:`Human request ${e.requestId} was answered.`,...e.kind==="review"?[`The review result is at ${e.requestDir}/result.json.`]:[],`Result:
|
|
31
|
+
${JSON.stringify(t,null,2)}`].join(`
|
|
32
|
+
|
|
33
|
+
`)}i(De,"migratedTerminalBody");function ke(e,t){const r=H(),s=H(),n=Date.parse(t.settledAt),o=Number.isFinite(n)?n:0,u=t.outcome==="answered"||t.outcome==="approved"?"human-answer":"human-canceled",a=JSON.parse(t.resultJson),l=De(t,a);return e.prepare(`INSERT INTO messages
|
|
31
34
|
(message_id, seq, operation_id, created_at, sender_node_id, sender_name, kind, label, body_ref, body_json, disposition)
|
|
32
|
-
VALUES (?, ?, ?, ?, NULL, 'crtrd', 'completed', ?, NULL, ?, ?)`).run(r,
|
|
35
|
+
VALUES (?, ?, ?, ?, NULL, 'crtrd', 'completed', ?, NULL, ?, ?)`).run(r,Re(e),H(),t.settledAt,l.split(`
|
|
36
|
+
`,1)[0],JSON.stringify({body:l,result:a}),u),e.prepare(`INSERT INTO deliveries
|
|
33
37
|
(delivery_id, message_id, destination_kind, destination_id, urgency, wake, state, attempts, created_at, updated_at)
|
|
34
|
-
VALUES (?, ?, 'node_inbox', ?, 'normal', 1, 'pending', 0, ?, ?)`).run(s,r,t.requesterNodeId,o,o),s}i(
|
|
35
|
-
`}i(
|
|
38
|
+
VALUES (?, ?, 'node_inbox', ?, 'normal', 1, 'pending', 0, ?, ?)`).run(s,r,t.requesterNodeId,o,o),s}i(ke,"createMigratedTerminalDelivery");function re(e,t){if(t.requesterNodeId===null||t.outcome===null||t.resultJson===null||t.settledAt===null)return null;const r=Ae(e,t.requestId,t.requesterNodeId,t.kind);return r!==null?r:t.deliveredAt!==null&&t.deliveredAt!==void 0?null:ke(e,{requestId:t.requestId,requesterNodeId:t.requesterNodeId,kind:t.kind,outcome:t.outcome,resultJson:t.resultJson,settledAt:t.settledAt,requestDir:t.requestDir})}i(re,"terminalDeliveryMark");const Ie=d.object({sessionName:d.string().optional(),askedBy:d.string().optional(),blockedSince:d.string().optional(),profileName:d.string().optional(),nodeId:d.string().optional()}).strict(),Oe=d.object({id:d.string().regex(/^[A-Za-z0-9_-]{1,64}$/).optional(),kind:d.string().min(1),step:d.number().int().nonnegative(),config:d.record(d.string(),d.unknown()),unvalidated:d.literal(!0).optional(),display:d.literal(!0).optional()}).strict(),xe=d.object({schema:d.literal("crtr.page/v1"),dialect:d.enum(["md","html","jsx"]),title:d.string().trim().min(1),subtitle:d.string().optional(),placement:d.enum(["inline","panel"]),document:d.enum(["page.md","page.html","page.tsx"]),steps:d.number().int().positive(),slots:d.array(Oe),source:Ie.optional()}).strict().superRefine((e,t)=>{const r=e.dialect==="md"?"page.md":e.dialect==="html"?"page.html":"page.tsx";e.document!==r&&t.addIssue({code:"custom",path:["document"],message:"document must agree with dialect"}),e.dialect==="md"&&e.steps!==1&&t.addIssue({code:"custom",path:["steps"],message:"md pages have exactly one step"})});function Le(e){if(e.source===void 0)return;const{blockedSince:t,...r}=e.source,s={...r,...t!==void 0&&d.string().datetime({offset:!0}).safeParse(t).success?{emittedAt:t}:{}};return Object.keys(s).length===0?void 0:s}i(Le,"legacyPresentationSource");function je(e,t,r){return`export default function LegacyPage() { return <Page title={${JSON.stringify(e)}}${t===void 0?"":` subtitle={${JSON.stringify(t)}}`}><pre>{${JSON.stringify(r)}}</pre></Page>; }
|
|
39
|
+
`}i(je,"legacyReplayDocument");function ie(e){return Array.isArray(e.slots)?{...e,slots:e.slots.map(t=>{if(typeof t!="object"||t===null||Array.isArray(t))return t;const r=t;if(r.kind!=="text"||typeof r.config!="object"||r.config===null||Array.isArray(r.config))return t;const{editable:s,...n}=r.config;return{...r,config:n}})}:e}i(ie,"withoutLegacyTextEditable");function we(e,t){const r=c(e,"page.json"),s=xe.safeParse(t);if(!s.success)throw new Error(s.error.message);const n=s.data,o=Le(n),u={placement:n.placement,inbox:!0,reply:n.source?.blockedSince!==void 0};G(ie({schema:"crtr.page/v2",dialect:"jsx",title:n.title,...n.subtitle===void 0?{}:{subtitle:n.subtitle},delivery:u,document:"page.tsx",steps:n.steps,slots:n.slots,...o===void 0?{}:{source:o}}));const a=c(e,n.document);if(!g(a))throw new Error(`corrupt required input: ${a}`);const l=V(a,"utf8"),m=be({dialect:"jsx",document:je(n.title,n.subtitle,l),source:o,delivery:u});if(o!==void 0)return m;const{source:E,...y}=m.manifest;return{...m,manifest:y}}i(we,"migrateLegacyPage");function Tt(e){e.exec(`
|
|
36
40
|
CREATE TABLE human_requests (
|
|
37
41
|
request_id TEXT PRIMARY KEY, kind TEXT NOT NULL CHECK (kind IN ('page','review')),
|
|
38
42
|
inbox_ticket_id TEXT NOT NULL UNIQUE, request_dir TEXT NOT NULL, presentation_dir TEXT,
|
|
@@ -61,4 +65,4 @@ var oe=Object.defineProperty;var i=(e,t)=>oe(e,"name",{value:t,configurable:!0})
|
|
|
61
65
|
progress_json, feedback_json, result_json, anchor_base_sha256, anchor_base_bytes, created_at, opened_at,
|
|
62
66
|
submit_requested_at, settled_at, settlement_delivery_id, action_delivery_id, projected_at, projection_error,
|
|
63
67
|
companion_retired_at, updated_at
|
|
64
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);if(e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'reviews'").get()!==void 0){const s=e.prepare("SELECT * FROM reviews").all();for(const n of s){const o=n.state,u=o==="approved"||o==="canceled",a=o==="canceled"&&n.result_json===null?JSON.stringify({schema:"humanloop.cancel/v1",kind:"canceled",canceledAt:n.canceled_at,...n.cancel_reason===""||n.cancel_reason===null?{}:{reason:n.cancel_reason},...n.cancel_actor===null?{}:{actor:n.cancel_actor}}):n.result_json;if(u&&a===null)throw new Error(`corrupt required input: reviews/${n.review_id} has no terminal result`);const
|
|
68
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);if(e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'reviews'").get()!==void 0){const s=e.prepare("SELECT * FROM reviews").all();for(const n of s){const o=n.state,u=o==="approved"||o==="canceled",a=o==="canceled"&&n.result_json===null?JSON.stringify({schema:"humanloop.cancel/v1",kind:"canceled",canceledAt:n.canceled_at,...n.cancel_reason===""||n.cancel_reason===null?{}:{reason:n.cancel_reason},...n.cancel_actor===null?{}:{actor:n.cancel_actor}}):n.result_json;if(u&&a===null)throw new Error(`corrupt required input: reviews/${n.review_id} has no terminal result`);const l=n.bridge_node_id===null?c(z(),"reviews",n.review_id):c(N(),n.bridge_node_id),m={origin_kind:n.origin_kind,bridge_node_id:n.bridge_node_id,origin_session_file:n.origin_session_file,origin_session_id:n.origin_session_id,origin_leaf_id:n.origin_leaf_id,model_spec:n.model_spec,branch_file:n.branch_file,baseline_sha256:n.baseline_sha256,baseline_bytes:n.baseline_bytes,captured_at:n.captured_at,output_path:n.output_path},E=u?o==="approved"?"approved":"canceled":null,y=u?o==="approved"?n.approved_at:n.canceled_at:null,S=re(e,{requestId:n.review_id,requesterNodeId:n.origin_node_id,kind:"review",outcome:E,resultJson:a,settledAt:y,requestDir:l,deliveredAt:n.delivered_at}),D=te(e,n.companion_node_id,E)?y:null;t.run(n.review_id,"review",n.origin_kind==="ticket"?U(N(),w(l)):P(),l,null,n.origin_node_id,n.companion_node_id,n.idempotency_key,u?"settled":o,E,n.origin_kind==="ticket"?1:0,1,w(n.file),n.subtitle,n.file,JSON.stringify(m),null,null,null,a,n.anchor_base_sha256,n.anchor_base_bytes,n.created,n.opened_at,n.submit_requested_at,y,S,null,n.projected_at,n.projection_error,D,n.created)}e.exec("DROP TABLE reviews")}for(const s of g(N())?ce(N(),{withFileTypes:!0}):[]){if(!s.isDirectory())continue;const n=c(N(),s.name),o=c(n,"page.json"),u=c(n,"review.json");if(!g(o)){if(g(u))continue;continue}if(e.prepare("SELECT 1 FROM human_requests WHERE request_id = ?").get(s.name)!==void 0)continue;let a,l,m,E;try{const p=R(o);if(typeof p!="object"||p===null||Array.isArray(p))throw new Error("page manifest must be an object");a=p,a.schema==="crtr.page/v1"?(l=we(n,p),a=l.manifest):a.schema==="crtr.page/v2"&&(a=ie(a));const v=qe.safeParse(a.delivery);if(typeof a.title!="string"||!v.success)throw new Error(v.success?"page title must be a string":v.error.message);E=v.data,m=G(a)}catch(p){const v=p instanceof Error&&p.cause instanceof Error?p.cause.message:p instanceof Error?p.message:String(p);console.warn(`skipping legacy page ${o}: ${v}`);continue}let y=O(n);l!==void 0&&(y=ee(C(s.name),l));const S=m.source,D=c(n,"response.json"),k=g(D)?R(D):null,h=k===null?null:ve(k),se=e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'deliveries'").get()===void 0?null:e.prepare("SELECT delivery_id FROM deliveries WHERE idempotency_key = ?").get(`human-action:${U(N(),s.name)}`),X=c(n,"action.json"),$=c(n,"progress.json"),x=c(n,"feedback-comments.json"),L=c(n,"reply-route.json"),q=g(x)?R(x):null;if(q!==null&&(typeof q!="object"||typeof q.companionNodeId<"u"&&typeof q.companionNodeId!="string"))throw new Error(`corrupt required input: ${x}`);const I=g(L)?R(L):null;if(I!==null&&(typeof I!="object"||typeof I.bridge_node_id!="string"))throw new Error(`corrupt required input: ${L}`);const M=I?.bridge_node_id,F=(typeof M!="string"||e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'nodes'").get()===void 0?null:e.prepare("SELECT parent FROM nodes WHERE node_id = ?").get(M))?.parent??(typeof S?.nodeId=="string"?S.nodeId:null),W=q?.companionNodeId,J=typeof S?.emittedAt=="string"?S.emittedAt:le(o).mtime.toISOString(),B=k===null?null:JSON.stringify(k),oe=re(e,{requestId:s.name,requesterNodeId:F,kind:"page",outcome:h?.outcome??null,resultJson:B,settledAt:h?.settledAt??null,requestDir:n}),ae=te(e,W??null,h?.outcome??null)?h?.settledAt??null:null,K=C(s.name);A(K,{recursive:!0,mode:448}),t.run(s.name,"page",U(N(),s.name),K,y,F,W??null,null,h===null?"open":"settled",h?.outcome??null,E.inbox?1:0,E.inbox||E.reply?1:0,m.title,m.subtitle??null,null,JSON.stringify(m),g(X)?JSON.stringify(R(X)):null,g($)&&h===null?JSON.stringify(R($)):null,q===null?null:JSON.stringify(q),B,null,null,J,null,null,h?.settledAt??null,oe,se?.delivery_id??null,null,null,ae,J)}const r=e.prepare("SELECT request_id FROM human_requests WHERE state = 'settled' AND result_json IS NULL").get();if(r!==void 0)throw new Error(`human request migration produced terminal row without result: ${r.request_id}`);if(e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'review_comments'").get()!==void 0){const s=e.prepare("SELECT review_id FROM review_comments WHERE review_id NOT IN (SELECT request_id FROM human_requests WHERE kind = 'review') LIMIT 1").get();if(s!==void 0)throw new Error(`review comment has no migrated review request: ${s.review_id}`)}}i(Tt,"migrateHumanRequestsState");export{lt as cancelBindingRequest,Qe as commitBindingRequest,Ge as createPageRequest,Ye as getRequest,tt as getRequestByCompanion,et as getRequestByDirectory,nt as getRequestByIdempotencyKey,Ze as getRequestByInboxTicket,it as hasOpenReplyBearingRequestByRequester,Z as humanRequestsRoot,ot as listBindingRequests,rt as listOpenInboxRequests,st as listOpenReplyBearingRequests,ut as listRequests,at as listSubmitRequestedRequests,dt as listUnprojectedReviews,bt as markCompanionRetired,yt as markProjected,ht as markProjectionError,Tt as migrateHumanRequestsState,ct as openRequest,Se as openRequestsByRequester,ze as presentationDir,ee as publishPageRevision,qt as readAnchorBase,Nt as replaceAnchorBaseLocked,C as requestDir,_t as requestSubmit,Et as revisePageRequest,mt as setSettlementDeliveryMarksLocked,ft as setSubmitNoteDeliveryLocked,pt as settleRequestLocked,gt as writeProgress};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface ReviewForkResult {
|
|
2
|
+
/** The newborn fork. */
|
|
3
|
+
node_id: string;
|
|
4
|
+
/** Where the fork runs — the companion's cwd, which a viewer pane reuses. */
|
|
5
|
+
cwd: string;
|
|
6
|
+
}
|
|
7
|
+
/** Fork the review companion onto one comment. */
|
|
8
|
+
export declare function forkReviewComment(commentId: string): Promise<ReviewForkResult>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
var m=Object.defineProperty;var d=(o,n)=>m(o,"name",{value:n,configurable:!0});import{basename as c}from"node:path";import{getNode as s}from"../canvas/index.js";import{ensureReviewForkDir as w,reviewForkBranchPath as p}from"../canvas/paths.js";import{materializeSessionBranchAt as l}from"../runtime/session-branch.js";import{spawnChildPrepared as _}from"../runtime/spawn.js";import{getComment as f}from"./comments.js";import{captureOrigin as h}from"./companion.js";import{requireVisibleReview as u}from"./store.js";import{ReviewOperationError as a}from"./types.js";function v(o,n){const{line:e,end_line:i}=n.anchor,t=i>e?`lines ${e}-${i}`:`line ${e}`,r=n.anchor_line_text===""?"":`
|
|
2
|
+
> ${n.anchor_line_text}
|
|
3
|
+
`;return[`The person handed you this one comment on \`${o.file}\` so it can be worked in parallel. The review companion you were forked from keeps the rest of the document.`,`${t}:${r}`,n.text,`Address it by editing only the lines this comment is about \u2014 other forks may be editing the same file \u2014 then resolve it with \`crtr human review comment resolve ${n.comment_id}\`, and tell the companion what changed with \`crtr push update\`.`].join(`
|
|
4
|
+
|
|
5
|
+
`)}d(v,"forkTask");async function T(o){const n=f(o);if(n===null)throw new a("unknown_comment","comment was not found",{received:o});if(n.status!=="open")throw new a("comment_deleted","only an open comment can be forked",{comment_id:o,status:n.status});const e=u(n.review_id);if(e.state!=="open")throw new a("review_terminal","review already has a terminal outcome",{state:e.state,requested:"fork",review:e});const i=s(e.companion_node_id);if(i===null)throw new a("review_companion_unbound","review companion is gone",{companion_node_id:e.companion_node_id});const t=await h(e.companion_node_id);w(e.review_id);const r=p(e.review_id,o);return l(t,r),{node_id:(await _({kind:"review/companion",mode:"base",cwd:i.cwd,parent:e.companion_node_id,creator:e.companion_node_id,rootLifecycle:"resident",prompt:v(e,n),forkFrom:r,model:t.modelSpec,name:`comment on ${c(e.file)}`,reviewBinding:{review_id:e.review_id,origin_node_id:e.origin_node_id,branch_file:r,target_file:e.file}})).node.node_id,cwd:i.cwd}}d(T,"forkReviewComment");export{T as forkReviewComment};
|
|
@@ -5,6 +5,9 @@ interface AbortableSession {
|
|
|
5
5
|
export declare function refuseTurn(abort: () => void): void;
|
|
6
6
|
export declare function wasTurnRefused(): boolean;
|
|
7
7
|
export declare function clearRefusedTurn(): void;
|
|
8
|
+
/** Prevent extensions from settling a turn that broker teardown will certify. */
|
|
9
|
+
export declare function beginRuntimeTeardown(): void;
|
|
10
|
+
export declare function isRuntimeTeardownInProgress(): boolean;
|
|
8
11
|
/** Mark one synchronous ExtensionContext.abort() call as a refresh boundary. */
|
|
9
12
|
export declare function runRefreshAbort(abort: () => void): void;
|
|
10
13
|
/** Bound into Pi's extension context by the broker for every session generation. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var s=Object.defineProperty;var r=(e,n)=>s(e,"name",{value:n,configurable:!0});let t=!1,o=!1;const u=globalThis;function i(e){o=!0,e()}r(i,"refuseTurn");function a(){return o}r(a,"wasTurnRefused");function c(){o=!1}r(c,"clearRefusedTurn");function l(){u.__crtrRuntimeTeardownInProgress=!0}r(l,"beginRuntimeTeardown");function T(){return u.__crtrRuntimeTeardownInProgress===!0}r(T,"isRuntimeTeardownInProgress");function d(e){t=!0;try{e()}finally{t=!1}}r(d,"runRefreshAbort");function p(e,n){t&&(e.clearQueue(),n?.()),e.abort()}r(p,"abortSessionFromExtension");export{p as abortSessionFromExtension,l as beginRuntimeTeardown,c as clearRefusedTurn,T as isRuntimeTeardownInProgress,i as refuseTurn,d as runRefreshAbort,a as wasTurnRefused};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var ve=Object.defineProperty;var e=(t,n)=>ve(t,"name",{value:n,configurable:!0});import{envModelIntent as he,envNodeCwd as _e,envNodeId as we,envProfileId as ye}from"../../shared/env.js";import{createServer as Se}from"node:net";import{existsSync as se,readFileSync as be,unlinkSync as ae}from"node:fs";import{join as K}from"node:path";import{randomUUID as M}from"node:crypto";import{mark as Ee}from"../timing.js";import{getAgentDir as V,initTheme as Te,ModelRegistry as ke,ModelRuntime as Re}from"@earendil-works/pi-coding-agent";import{nodeDir as xe,viewSocketPath as Ce}from"../canvas/paths.js";import{bindBrokerEventSource as Ae}from"../events/source.js";import{emitEvent as E}from"../events/emit.js";import{operationIdContext as Me}from"../events/operation-id.js";import{findMissingPackagePaths as Pe}from"./package-health.js";import{FRONT_DOOR_ENV as Ie}from"./front-door.js";import{CANVAS_EXTENSIONS as X,piInvocationToSdkConfig as Oe}from"./launch.js";import{assertEngineVersion as De,loadBrokerEngine as Fe}from"./broker-sdk.js";import{resolveBundledPiPackageDir as Ne}from"./pi-cli.js";import{captureSessionChatCapabilities as Le}from"./command-surface.js";import{PoolCredentialStore as $e}from"../pool-credential-store.js";import{mutateBrokerFault as U,recordBrokerTurn as de}from"./broker/daemon-ops.js";import{modelRequestFromConfig as je,selectInitialModelRoute as Be,unregisteredConcreteModel as Ge}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as Ue}from"./stream-watchdog.js";import{probeOnline as We}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as qe,cycleAwareMessages as Ke}from"./session-cycles.js";import{projectTranscript as Ve}from"./session-visibility.js";import{currentTurnVisibility as Xe}from"./turn-visibility.js";import{isUnknownModel as H}from"./model-selection.js";import{BrokerClientRegistry as He}from"./broker/client-registry.js";import{ToolGroupTracker as Ye}from"./broker/tool-groups.js";import{onNodeNamed as ze}from"./broker/node-named.js";import{FaultRetry as Je}from"./broker/fault-retry.js";import{createTurnAdmissionGate as Qe}from"./broker/turn-admission.js";import{BROKER_IDLE_TURN_START as Ze}from"./broker/held-deferred-inbox.js";import{EventProjection as et}from"./broker/event-projection.js";import{createFrameDispatchContext as tt,handleFrame as nt}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as ot,installAdvertisedCommandInvocationContract as rt}from"./advertised-command-invocation.js";import{RebindDriver as it}from"./broker/rebind.js";import{decodeKickoffOrigin as st,KICKOFF_ORIGIN_ENV as at}from"./stamp/protocol.js";import{announceMessageOrigin as dt}from"./stamp/channel.js";import{brokerExtensionState as lt,commitBrokerModel as ct}from"./broker/daemon-ops.js";import{FrameOverflowError as mt,normalizeSnapshotTail as ut}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as fn,REVIEW_BOUNDARY_NAVIGATION_CODE as pn}from"./broker/frame-replies.js";function Y(t){return new ke(t.modelRuntime)}e(Y,"registryOf");function ft(t){return{authPath:K(t,"auth.json"),modelsPath:K(t,"models.json")}}e(ft,"modelRuntimePaths");function L(t,n){if(t==null||H(t))return null;const s=n!==void 0&&n!==""&&n!=="off"?`:${n}`:"";return`${t.provider}/${t.id}${s}`}e(L,"formatModelSpec");function pt(t,n){const s=L(t,void 0);return s===null?null:`${s}:${n===void 0||n===""?"off":n}`}e(pt,"formatExactModelSpec");const gt=12e4;let W=null;function vt(){const t=W;if(W=null,t!==null)try{t.dispose()}catch{}}e(vt,"disposeActiveSession");async function cn(t,n=process.hrtime.bigint(),s=new Date().toISOString()){Ae(t),Me.fresh(()=>{E({level:"info",event:"broker.startup.cli_entry",ts:s,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),E({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-n)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const p=new Set;let i=null;const a=e((o,r=null)=>{p.has(o)||(p.add(o),Ee(o,{duration_ms:Number(process.hrtime.bigint()-n)/1e6}),E({level:"info",event:o,duration_ms:Number(process.hrtime.bigint()-n)/1e6,fields:{runtime_version:process.version,engine_version:i,model:r}}))},"emitStartupMilestone");process.env[Ie]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX;const d=await Fe();De(d.VERSION),i=d.VERSION;const l=xe(t),m=K(l,"broker-launch.json"),h=JSON.parse(be(m,"utf8")),g=Oe(h);g.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;let{session:_,services:S,resuming:k,runtime:T}=await yt(d,g);const R=(await lt(t)).node.review_binding?.review_id;W=_;const B=We;try{process.env.PI_PACKAGE_DIR=Ne(),Te(S.settingsManager.getTheme(),!1)}catch(o){E({level:"error",event:"broker.theme.initialization_failed",error:o})}try{for(const o of Pe(V()))E({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:o.source,resolved_path:o.resolved}})}catch{}const x=Ce(t),u=new He(t),D=new Map,b=new Ye(t,o=>u.broadcast(o));ze(o=>u.broadcast({type:"node_named",...o}));let P=!1,F=!1,A,$,c,C,N,z=e(()=>{},"notifyTurnAccepted"),J=e(()=>{},"resetFrameState");c=new it({nodeId:t,cfg:g,session:_,services:S,runtime:T,registry:u,toolGroups:b,uiContext:e(()=>$,"uiContext"),faultRetry:e(()=>C,"faultRetry"),projection:e(()=>N,"projection"),setActiveSession:e(o=>{W=o},"setActiveSession"),disposeAndExit:e((o,r)=>j(o,r),"disposeAndExit"),onSessionRebind:e(()=>{J()},"onSessionRebind"),reWelcomeAll:e(()=>te(),"reWelcomeAll")});const Q=e(async(o,r=!1)=>{const f=c.session(),v=L(f.model,f.thinkingLevel);if(v===null)return null;const w=await ct(t,{spec:v,pinnedOverride:o,userSelected:r});return r&&(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",g.model=w.modelOverride,g.modelExact=!0),w.modelOverride},"persistModelChoice"),Z=e(async(o=!0,r,f=!1)=>{const v=c.session(),w=L(v.model,v.thinkingLevel),y=o?await Q(r,f):w;u.broadcast({type:"model_changed",model:H(v.model)?void 0:v.model,spec:y})},"broadcastModelChanged"),q=Qe(),me=e(o=>{q.admit(r=>{const f=c.session();return f.prompt(o,{preflightResult:r,...f.isStreaming?{streamingBehavior:"steer"}:{}}).catch(v=>{E({level:"error",event:"broker.inbox.idle_prompt_failed",error:v})})})},"startIdleInboxTurn");globalThis[Ze]=me,C=new Je({nodeId:t,cfg:g,retryProbe:B,currentSession:e(()=>c.session(),"currentSession"),currentServices:e(()=>c.services(),"currentServices"),installedGeneration:e(()=>c.installedGeneration(),"installedGeneration"),registryOf:Y,formatModelSpec:L,broadcastModelChanged:Z,turnAdmission:q}),N=new et({registry:u,faultRetry:C,installedGeneration:e(()=>c.installedGeneration(),"installedGeneration"),currentSession:e(()=>c.session(),"currentSession"),notifyTurnAccepted:e(()=>z(),"notifyTurnAccepted"),emitStartupMilestone:a,formatModelSpec:L});const ue=e(o=>{const r=c.session(),f=_t(r,R),v=ut(o.snapshotTail),w=f===void 0||v===void 0?f:f.slice(-v),y=w?.map(({message:O})=>O)??r.sessionManager.buildSessionContext().messages,G=b.summaries(),ie=w!==void 0&&v!==void 0?ht(y):void 0,ge=ie===void 0?G:Object.fromEntries(Object.entries(G).filter(([O])=>ie.has(O)));return{messages:y,...w===void 0?{}:{messageIds:w.map(({id:O})=>O)},messageVisibility:w?.map(({visibility:O})=>O)??y.map(()=>"visible"),turnVisibility:Xe(),stats:r.getSessionStats(),state:{model:H(r.model)?void 0:r.model,thinkingLevel:r.thinkingLevel,isStreaming:r.isStreaming,isCompacting:r.isCompacting,steeringMode:r.steeringMode,followUpMode:r.followUpMode,sessionFile:r.sessionFile,sessionId:r.sessionId,sessionName:r.sessionName,autoCompactionEnabled:r.autoCompactionEnabled,messageCount:r.messages.length,pendingMessageCount:r.pendingMessageCount},display:{...u.displaySnapshot()},toolGroupSummaries:ge,workingActivity:N.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),ee=e(o=>{const r=o.role==="controller"?D.values().next().value:void 0;u.sendFrame(o,{type:"welcome",snapshot:ue(o),role:o.role,pending_dialog:r!==void 0?r.request:null,agentDir:V()},!0)},"sendWelcome"),fe=e(o=>{const r=[...D.values()];for(let f=1;f<r.length;f++)u.sendFrame(o,r[f].request)},"replayExtraPendingDialogsTo"),te=e(()=>{u.forEachHelloed(ee)},"reWelcomeAll"),ne=e(o=>{if(!P){P=!0,b.persistPendingSummary(),N.dispose(),vt();try{A?.close()}catch{}u.dispose();try{se(x)&&ae(x)}catch{}u.clearAttachState(),process.exit(o)}},"completeExit"),j=e((o,r=0)=>{if(P)return;const f=o==="shutdown-hook"||o==="shutdown-after-settle";if(f&&b.finishOpenToolGroup(!0),f&&b.hasSummaryTasks()){if(F)return;F=!0,b.waitForSummaryTasks().finally(()=>ne(r));return}ne(r)},"disposeAndExit");$=St({writable:e(()=>u.writableClients(),"writable"),forward:e((o,r)=>u.sendFrame(o,r),"forward"),pending:D,broadcast:e(o=>u.broadcastUi(o),"broadcast"),onKnownStreamWait:e(o=>N.knownStreamWait(o),"onKnownStreamWait")}),c.setRebindSession(),await c.enqueueRebind(_,S);const I=tt({nodeId:t,cfg:g,registry:u,toolGroups:b,projection:N,rebind:c,boundaryReviewId:R,pendingDialogs:D,sendWelcome:ee,replayExtraPendingDialogsTo:fe,reWelcomeAll:te,disposeAndExit:j,persistModelChoice:Q,broadcastModelChanged:Z,registryOf:Y,formatModelSpec:L,formatExactModelSpec:pt,turnAdmission:q,resolveLaunchModel:ce});z=I.notifyTurnAccepted,J=I.resetForSession;try{se(x)&&ae(x)}catch{}A=Se(o=>{const r=u.create(o);o.on("data",v=>{let w;try{w=r.decoder.push(v)}catch(y){y instanceof mt?(u.sendFrame(r,{type:"error",code:"frame_overflow",message:y.message}),u.dropClient(r,`frame overflow: ${y.message}`)):u.dropClient(r,`decoder error: ${String(y)}`);return}for(const y of w)try{nt(I,r,y)}catch{}});const f=e(()=>{u.removeClient(r)},"drop");o.on("close",f),o.on("error",()=>{})}),A.on("error",o=>{P||(E({level:"error",event:"broker.socket.failed",error:o}),j("socket-error",1))}),A.listen(x,async()=>{Promise.all([U(t,{op:"clear",link:"viewer\u2194broker"}),U(t,{op:"clear",link:"relay\u2194broker"})]).catch(r=>E({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let o;try{o=await C.recoverOnStartup()}catch(r){E({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"recovery_startup"}}),j("recovery-startup-failed",1);return}if(o!=="retry-armed"&&g.firstPrompt!==void 0&&g.firstPrompt!==""){const r=st(process.env[at]);r!==null&&dt(g.firstPrompt,r),I.kickoff(g.firstPrompt)}}),u.persistAttachState();const pe=2500;let oe=!1;const re=e(async o=>{if(P||oe)return;if(oe=!0,c.isAgentRunActive()||c.session().isStreaming||I.pendingPromptDispatches()>0){const f=Date.now()+pe;for(;I.pendingPromptDispatches()>0&&!c.session().isStreaming&&Date.now()<f;)await new Promise(v=>setTimeout(v,25));if(c.session().isStreaming){const v=f-Date.now();if(v>0){let w;try{await Promise.race([c.session().abort().then(()=>!0,()=>!1),new Promise(G=>{w=setTimeout(()=>G(!1),v)})])&&await de(t,{event:"closed",end_reason:"teardown-aborted"})}finally{w!==void 0&&clearTimeout(w)}}}else(I.pendingPromptDispatches()>0||c.isAgentRunActive())&&await de(t,{event:"interrupted"})}j(o)},"abortAndExit");process.on("SIGTERM",()=>{re("SIGTERM")}),process.on("SIGINT",()=>{re("SIGINT")})}e(cn,"runBroker");function ht(t){const n=new Set;for(const s of t)if(!(s.role!=="assistant"||!Array.isArray(s.content)))for(const p of s.content)p!==null&&typeof p=="object"&&p.type==="toolCall"&&typeof p.id=="string"&&n.add(p.id);return n}e(ht,"toolCallIds");function _t(t,n){const s=t.sessionManager,p=Ke(s);return p!==void 0&&ot(p.map(({message:i})=>i)),p===void 0?void 0:Ve(p,{boundaryReviewId:n,sessionEntries:s.getEntries?.()})}e(_t,"snapshotMessages");function le(){const t=we();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}e(le,"currentBrokerNodeId");async function ce(t,n){const s=je(n.model,he(),n.modelExact===!0);if(s===void 0)return;const p=Y(t),i={cwd:_e()??n.cwd,profileId:ye()},a=Ge(s,p,i);if(a!==void 0)throw await U(le(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const d=Be(s,p,i),l=d.selected;if(l!==void 0){const m=l.candidate;return(m.rank??0)>0&&E({level:"warn",event:"broker.model.launch_fallback",fields:{requested:n.model,selected:`${m.providerId}/${m.modelId}`,route_id:m.routeId,credential_source:m.credentialSource,rank:m.rank}}),{model:l.model,thinkingLevel:m.thinkingLevel}}if(n.modelExact===!0){const m=d.rejected.map(({candidate:h,reason:g})=>`'${h.providerId}/${h.modelId}' ${g}`).join("; ");throw await U(le(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${n.model}' is unavailable \u2014 refusing to substitute (${m})`}}),new Error(`[broker] FATAL: exact-consult model '${n.model}' is unavailable`)}E({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:d.rejected.slice(0,16).map(({candidate:m,reason:h})=>({provider:m.providerId,model:m.modelId,reason:h,route_id:m.routeId,credential_source:m.credentialSource})),rejected_candidates_omitted:Math.max(0,d.rejected.length-16)}})}e(ce,"resolveLaunchModel");function wt(t){let n=!0;return{runtime:new Proxy(t,{get(p,i,a){return n&&i==="getAvailableSnapshot"?()=>[]:n&&i==="getAvailable"?async()=>[]:n&&i==="getModel"?()=>{}:Reflect.get(p,i,a)}}),reveal:e(()=>{n=!1},"reveal")}}e(wt,"modelLessRegistry");async function yt(t,n){const s=V(),p=e(async _=>{const{authPath:S,modelsPath:k}=ft(_.agentDir),T=await Re.create({credentials:new $e(S),modelsPath:k}),R=await t.createAgentSessionServices({cwd:_.cwd,agentDir:_.agentDir,modelRuntime:T,resourceLoaderOptions:{additionalExtensionPaths:n.extensionPaths,appendSystemPrompt:n.appendSystemPromptPath!==void 0?[n.appendSystemPromptPath]:void 0,noContextFiles:!0}}),B=R.resourceLoader.getExtensions();if(n.extensionPaths.some(A=>X.includes(A))){const A=new Set(B.extensions.map(c=>c.path)),$=X.filter(c=>!A.has(c));if($.length>0){const c=B.errors.filter(C=>X.includes(C.path)).map(C=>`${C.path}: ${C.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${$.join(", ")}${c===""?"":` (${c})`}`)}}const x=await ce(R,n),u=x?.model,D=x?.thinkingLevel,b=x===void 0?wt(R.modelRuntime):void 0,P=b!==void 0?{...R,modelRuntime:b.runtime}:R,F=await t.createAgentSessionFromServices({services:P,sessionManager:_.sessionManager,model:u,thinkingLevel:D,tools:n.tools,sessionStartEvent:_.sessionStartEvent});return rt(F.session),Le(F.session),b?.reveal(),{...F,services:R}},"buildForManager"),i=n.resumeSessionPath,a=n.forkFrom!==void 0&&n.forkFrom!=="";if(!a&&(i===void 0||i==="")&&n.resumeSessionId!==void 0&&n.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${n.resumeSessionId}' (pi_session_file was never captured for this node)`);const d=!a&&i!==void 0&&i!=="",l=d&&n.newCycle===!0,m=d&&!l;let h;if(a)h=t.SessionManager.forkFrom(n.forkFrom,n.cwd);else if(m||l){if(h=t.SessionManager.open(i),l){const _=h.getLeafId();h.resetLeaf(),h.appendCustomEntry(qe,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:_})}}else h=t.SessionManager.create(n.cwd);if(t.createAgentSessionRuntime!==void 0){const _=e(async k=>{const T=await p({cwd:k.cwd,agentDir:k.agentDir,sessionManager:k.sessionManager,sessionStartEvent:k.sessionStartEvent});return{...T,diagnostics:T.services.diagnostics??[]}},"factory"),S=await t.createAgentSessionRuntime(_,{cwd:n.cwd,agentDir:s,sessionManager:h});return{session:S.session,services:S.services,resuming:m,runtime:S}}const g=await p({cwd:n.cwd,agentDir:s,sessionManager:h});return{session:g.session,services:g.services,resuming:m,runtime:void 0}}e(yt,"buildBrokerSession");function St(t){const n=e((i,a,d,l)=>{if(l?.signal?.aborted)return Promise.resolve(i);const m=t.writable();return m.length===0?Promise.resolve(i):new Promise(h=>{let g;const _=e(()=>{g!==void 0&&clearTimeout(g),l?.signal?.removeEventListener("abort",S),t.pending.delete(a.id)},"cleanup"),S=e(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),h(i)},"onAbort");l?.signal?.addEventListener("abort",S,{once:!0});const k=l?.timeout!==void 0?l.timeout:gt;g=setTimeout(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),h(i)},k),typeof g.unref=="function"&&g.unref(),t.pending.set(a.id,{request:a,resolve:e(T=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),h(d(T))},"resolve")});for(const T of m)t.forward(T,a)})},"dialogPromise"),s=e(()=>{},"noop");return{[Ue]:t.onKnownStreamWait??(i=>()=>{}),get theme(){const i=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(i==null)throw new Error("Theme not initialized. Call initTheme() first.");return i},select:e((i,a,d)=>n(void 0,{type:"extension_ui_request",id:M(),method:"select",title:i,options:a,timeout:d?.timeout},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0,d),"select"),confirm:e((i,a,d)=>n(!1,{type:"extension_ui_request",id:M(),method:"confirm",title:i,message:a,timeout:d?.timeout},l=>"cancelled"in l&&l.cancelled?!1:"confirmed"in l?l.confirmed:!1,d),"confirm"),input:e((i,a,d)=>n(void 0,{type:"extension_ui_request",id:M(),method:"input",title:i,placeholder:a,timeout:d?.timeout},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0,d),"input"),editor:e((i,a)=>n(void 0,{type:"extension_ui_request",id:M(),method:"editor",title:i,prefill:a},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0),"editor"),setStatus:e((i,a)=>t.broadcast({type:"extension_ui_request",id:M(),method:"setStatus",statusKey:i,statusText:a}),"setStatus"),setWidget:e((i,a,d)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:M(),method:"setWidget",widgetKey:i,widgetLines:a,widgetPlacement:d?.placement})},"setWidget"),setTitle:e(i=>t.broadcast({type:"extension_ui_request",id:M(),method:"setTitle",title:i}),"setTitle"),notify:e((i,a)=>{const d=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:M(),method:"notify",message:i,notifyType:d})},"notify"),onTerminalInput:e(()=>s,"onTerminalInput"),setWorkingMessage:s,setWorkingVisible:s,setWorkingIndicator:s,setHiddenThinkingLabel:s,setFooter:s,setHeader:s,custom:e(()=>Promise.resolve(void 0),"custom"),pasteToEditor:s,setEditorText:s,getEditorText:e(()=>"","getEditorText"),addAutocompleteProvider:s,setEditorComponent:s,getEditorComponent:e(()=>{},"getEditorComponent"),getAllThemes:e(()=>[],"getAllThemes"),getTheme:e(()=>{},"getTheme"),setTheme:s,getToolsExpanded:e(()=>!1,"getToolsExpanded"),setToolsExpanded:s}}e(St,"makeBrokerUiContext");export{pn as REVIEW_BOUNDARY_NAVIGATION_CODE,fn as ReviewBoundaryNavigationError,yt as buildBrokerSession,vt as disposeActiveSession,St as makeBrokerUiContext,cn as runBroker,_t as snapshotMessages};
|
|
1
|
+
var ve=Object.defineProperty;var e=(t,n)=>ve(t,"name",{value:n,configurable:!0});import{envModelIntent as he,envNodeCwd as _e,envNodeId as we,envProfileId as ye}from"../../shared/env.js";import{createServer as Se}from"node:net";import{existsSync as se,readFileSync as be,unlinkSync as ae}from"node:fs";import{join as K}from"node:path";import{randomUUID as M}from"node:crypto";import{mark as Te}from"../timing.js";import{getAgentDir as V,initTheme as Ee,ModelRegistry as ke,ModelRuntime as Re}from"@earendil-works/pi-coding-agent";import{nodeDir as xe,viewSocketPath as Ce}from"../canvas/paths.js";import{bindBrokerEventSource as Ae}from"../events/source.js";import{emitEvent as T}from"../events/emit.js";import{operationIdContext as Me}from"../events/operation-id.js";import{findMissingPackagePaths as Pe}from"./package-health.js";import{FRONT_DOOR_ENV as Ie}from"./front-door.js";import{CANVAS_EXTENSIONS as X,piInvocationToSdkConfig as Oe}from"./launch.js";import{assertEngineVersion as De,loadBrokerEngine as Fe}from"./broker-sdk.js";import{resolveBundledPiPackageDir as Ne}from"./pi-cli.js";import{captureSessionChatCapabilities as Le}from"./command-surface.js";import{PoolCredentialStore as $e}from"../pool-credential-store.js";import{mutateBrokerFault as U,recordBrokerTurn as de}from"./broker/daemon-ops.js";import{modelRequestFromConfig as je,selectInitialModelRoute as Be,unregisteredConcreteModel as Ge}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as Ue}from"./stream-watchdog.js";import{probeOnline as We}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as qe,cycleAwareMessages as Ke}from"./session-cycles.js";import{projectTranscript as Ve}from"./session-visibility.js";import{currentTurnVisibility as Xe}from"./turn-visibility.js";import{isUnknownModel as H}from"./model-selection.js";import{BrokerClientRegistry as He}from"./broker/client-registry.js";import{ToolGroupTracker as Ye}from"./broker/tool-groups.js";import{onNodeNamed as ze}from"./broker/node-named.js";import{FaultRetry as Je}from"./broker/fault-retry.js";import{createTurnAdmissionGate as Qe}from"./broker/turn-admission.js";import{BROKER_IDLE_TURN_START as Ze}from"./broker/held-deferred-inbox.js";import{EventProjection as et}from"./broker/event-projection.js";import{createFrameDispatchContext as tt,handleFrame as nt}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as ot,installAdvertisedCommandInvocationContract as rt}from"./advertised-command-invocation.js";import{RebindDriver as it}from"./broker/rebind.js";import{beginRuntimeTeardown as st}from"./broker/extension-abort.js";import{decodeKickoffOrigin as at,KICKOFF_ORIGIN_ENV as dt}from"./stamp/protocol.js";import{announceMessageOrigin as lt}from"./stamp/channel.js";import{brokerExtensionState as ct,commitBrokerModel as mt}from"./broker/daemon-ops.js";import{FrameOverflowError as ut,normalizeSnapshotTail as ft}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as gn,REVIEW_BOUNDARY_NAVIGATION_CODE as vn}from"./broker/frame-replies.js";function Y(t){return new ke(t.modelRuntime)}e(Y,"registryOf");function pt(t){return{authPath:K(t,"auth.json"),modelsPath:K(t,"models.json")}}e(pt,"modelRuntimePaths");function L(t,n){if(t==null||H(t))return null;const s=n!==void 0&&n!==""&&n!=="off"?`:${n}`:"";return`${t.provider}/${t.id}${s}`}e(L,"formatModelSpec");function gt(t,n){const s=L(t,void 0);return s===null?null:`${s}:${n===void 0||n===""?"off":n}`}e(gt,"formatExactModelSpec");const vt=12e4;let W=null;function ht(){const t=W;if(W=null,t!==null)try{t.dispose()}catch{}}e(ht,"disposeActiveSession");async function un(t,n=process.hrtime.bigint(),s=new Date().toISOString()){Ae(t),Me.fresh(()=>{T({level:"info",event:"broker.startup.cli_entry",ts:s,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),T({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-n)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const p=new Set;let i=null;const a=e((o,r=null)=>{p.has(o)||(p.add(o),Te(o,{duration_ms:Number(process.hrtime.bigint()-n)/1e6}),T({level:"info",event:o,duration_ms:Number(process.hrtime.bigint()-n)/1e6,fields:{runtime_version:process.version,engine_version:i,model:r}}))},"emitStartupMilestone");process.env[Ie]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX;const d=await Fe();De(d.VERSION),i=d.VERSION;const l=xe(t),m=K(l,"broker-launch.json"),h=JSON.parse(be(m,"utf8")),g=Oe(h);g.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;let{session:_,services:S,resuming:k,runtime:E}=await St(d,g);const R=(await ct(t)).node.review_binding?.review_id;W=_;const B=We;try{process.env.PI_PACKAGE_DIR=Ne(),Ee(S.settingsManager.getTheme(),!1)}catch(o){T({level:"error",event:"broker.theme.initialization_failed",error:o})}try{for(const o of Pe(V()))T({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:o.source,resolved_path:o.resolved}})}catch{}const x=Ce(t),u=new He(t),D=new Map,b=new Ye(t,o=>u.broadcast(o));ze(o=>u.broadcast({type:"node_named",...o}));let P=!1,F=!1,A,$,c,C,N,z=e(()=>{},"notifyTurnAccepted"),J=e(()=>{},"resetFrameState");c=new it({nodeId:t,cfg:g,session:_,services:S,runtime:E,registry:u,toolGroups:b,uiContext:e(()=>$,"uiContext"),faultRetry:e(()=>C,"faultRetry"),projection:e(()=>N,"projection"),setActiveSession:e(o=>{W=o},"setActiveSession"),disposeAndExit:e((o,r)=>j(o,r),"disposeAndExit"),onSessionRebind:e(()=>{J()},"onSessionRebind"),reWelcomeAll:e(()=>te(),"reWelcomeAll")});const Q=e(async(o,r=!1)=>{const f=c.session(),v=L(f.model,f.thinkingLevel);if(v===null)return null;const w=await mt(t,{spec:v,pinnedOverride:o,userSelected:r});return r&&(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",g.model=w.modelOverride,g.modelExact=!0),w.modelOverride},"persistModelChoice"),Z=e(async(o=!0,r,f=!1)=>{const v=c.session(),w=L(v.model,v.thinkingLevel),y=o?await Q(r,f):w;u.broadcast({type:"model_changed",model:H(v.model)?void 0:v.model,spec:y})},"broadcastModelChanged"),q=Qe(),me=e(o=>{q.admit(r=>{const f=c.session();return f.prompt(o,{preflightResult:r,...f.isStreaming?{streamingBehavior:"steer"}:{}}).catch(v=>{T({level:"error",event:"broker.inbox.idle_prompt_failed",error:v})})})},"startIdleInboxTurn");globalThis[Ze]=me,C=new Je({nodeId:t,cfg:g,retryProbe:B,currentSession:e(()=>c.session(),"currentSession"),currentServices:e(()=>c.services(),"currentServices"),installedGeneration:e(()=>c.installedGeneration(),"installedGeneration"),registryOf:Y,formatModelSpec:L,broadcastModelChanged:Z,turnAdmission:q}),N=new et({registry:u,faultRetry:C,installedGeneration:e(()=>c.installedGeneration(),"installedGeneration"),currentSession:e(()=>c.session(),"currentSession"),notifyTurnAccepted:e(()=>z(),"notifyTurnAccepted"),emitStartupMilestone:a,formatModelSpec:L});const ue=e(o=>{const r=c.session(),f=wt(r,R),v=ft(o.snapshotTail),w=f===void 0||v===void 0?f:f.slice(-v),y=w?.map(({message:O})=>O)??r.sessionManager.buildSessionContext().messages,G=b.summaries(),ie=w!==void 0&&v!==void 0?_t(y):void 0,ge=ie===void 0?G:Object.fromEntries(Object.entries(G).filter(([O])=>ie.has(O)));return{messages:y,...w===void 0?{}:{messageIds:w.map(({id:O})=>O)},messageVisibility:w?.map(({visibility:O})=>O)??y.map(()=>"visible"),turnVisibility:Xe(),stats:r.getSessionStats(),state:{model:H(r.model)?void 0:r.model,thinkingLevel:r.thinkingLevel,isStreaming:r.isStreaming,isCompacting:r.isCompacting,steeringMode:r.steeringMode,followUpMode:r.followUpMode,sessionFile:r.sessionFile,sessionId:r.sessionId,sessionName:r.sessionName,autoCompactionEnabled:r.autoCompactionEnabled,messageCount:r.messages.length,pendingMessageCount:r.pendingMessageCount},display:{...u.displaySnapshot()},toolGroupSummaries:ge,workingActivity:N.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),ee=e(o=>{const r=o.role==="controller"?D.values().next().value:void 0;u.sendFrame(o,{type:"welcome",snapshot:ue(o),role:o.role,pending_dialog:r!==void 0?r.request:null,agentDir:V()},!0)},"sendWelcome"),fe=e(o=>{const r=[...D.values()];for(let f=1;f<r.length;f++)u.sendFrame(o,r[f].request)},"replayExtraPendingDialogsTo"),te=e(()=>{u.forEachHelloed(ee)},"reWelcomeAll"),ne=e(o=>{if(!P){P=!0,b.persistPendingSummary(),N.dispose(),ht();try{A?.close()}catch{}u.dispose();try{se(x)&&ae(x)}catch{}u.clearAttachState(),process.exit(o)}},"completeExit"),j=e((o,r=0)=>{if(P)return;const f=o==="shutdown-hook"||o==="shutdown-after-settle";if(f&&b.finishOpenToolGroup(!0),f&&b.hasSummaryTasks()){if(F)return;F=!0,b.waitForSummaryTasks().finally(()=>ne(r));return}ne(r)},"disposeAndExit");$=bt({writable:e(()=>u.writableClients(),"writable"),forward:e((o,r)=>u.sendFrame(o,r),"forward"),pending:D,broadcast:e(o=>u.broadcastUi(o),"broadcast"),onKnownStreamWait:e(o=>N.knownStreamWait(o),"onKnownStreamWait")}),c.setRebindSession(),await c.enqueueRebind(_,S);const I=tt({nodeId:t,cfg:g,registry:u,toolGroups:b,projection:N,rebind:c,boundaryReviewId:R,pendingDialogs:D,sendWelcome:ee,replayExtraPendingDialogsTo:fe,reWelcomeAll:te,disposeAndExit:j,persistModelChoice:Q,broadcastModelChanged:Z,registryOf:Y,formatModelSpec:L,formatExactModelSpec:gt,turnAdmission:q,resolveLaunchModel:ce});z=I.notifyTurnAccepted,J=I.resetForSession;try{se(x)&&ae(x)}catch{}A=Se(o=>{const r=u.create(o);o.on("data",v=>{let w;try{w=r.decoder.push(v)}catch(y){y instanceof ut?(u.sendFrame(r,{type:"error",code:"frame_overflow",message:y.message}),u.dropClient(r,`frame overflow: ${y.message}`)):u.dropClient(r,`decoder error: ${String(y)}`);return}for(const y of w)try{nt(I,r,y)}catch{}});const f=e(()=>{u.removeClient(r)},"drop");o.on("close",f),o.on("error",()=>{})}),A.on("error",o=>{P||(T({level:"error",event:"broker.socket.failed",error:o}),j("socket-error",1))}),A.listen(x,async()=>{Promise.all([U(t,{op:"clear",link:"viewer\u2194broker"}),U(t,{op:"clear",link:"relay\u2194broker"})]).catch(r=>T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let o;try{o=await C.recoverOnStartup()}catch(r){T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"recovery_startup"}}),j("recovery-startup-failed",1);return}if(o!=="retry-armed"&&g.firstPrompt!==void 0&&g.firstPrompt!==""){const r=at(process.env[dt]);r!==null&<(g.firstPrompt,r),I.kickoff(g.firstPrompt)}}),u.persistAttachState();const pe=2500;let oe=!1;const re=e(async o=>{if(P||oe)return;if(oe=!0,c.isAgentRunActive()||c.session().isStreaming||I.pendingPromptDispatches()>0){const f=Date.now()+pe;for(;I.pendingPromptDispatches()>0&&!c.session().isStreaming&&Date.now()<f;)await new Promise(v=>setTimeout(v,25));if(c.session().isStreaming){const v=f-Date.now();if(v>0){let w;try{st(),await Promise.race([c.session().abort().then(()=>!0,()=>!1),new Promise(G=>{w=setTimeout(()=>G(!1),v)})])&&await de(t,{event:"closed",end_reason:"teardown-aborted"})}finally{w!==void 0&&clearTimeout(w)}}}else(I.pendingPromptDispatches()>0||c.isAgentRunActive())&&await de(t,{event:"interrupted"})}j(o)},"abortAndExit");process.on("SIGTERM",()=>{re("SIGTERM")}),process.on("SIGINT",()=>{re("SIGINT")})}e(un,"runBroker");function _t(t){const n=new Set;for(const s of t)if(!(s.role!=="assistant"||!Array.isArray(s.content)))for(const p of s.content)p!==null&&typeof p=="object"&&p.type==="toolCall"&&typeof p.id=="string"&&n.add(p.id);return n}e(_t,"toolCallIds");function wt(t,n){const s=t.sessionManager,p=Ke(s);return p!==void 0&&ot(p.map(({message:i})=>i)),p===void 0?void 0:Ve(p,{boundaryReviewId:n,sessionEntries:s.getEntries?.()})}e(wt,"snapshotMessages");function le(){const t=we();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}e(le,"currentBrokerNodeId");async function ce(t,n){const s=je(n.model,he(),n.modelExact===!0);if(s===void 0)return;const p=Y(t),i={cwd:_e()??n.cwd,profileId:ye()},a=Ge(s,p,i);if(a!==void 0)throw await U(le(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const d=Be(s,p,i),l=d.selected;if(l!==void 0){const m=l.candidate;return(m.rank??0)>0&&T({level:"warn",event:"broker.model.launch_fallback",fields:{requested:n.model,selected:`${m.providerId}/${m.modelId}`,route_id:m.routeId,credential_source:m.credentialSource,rank:m.rank}}),{model:l.model,thinkingLevel:m.thinkingLevel}}if(n.modelExact===!0){const m=d.rejected.map(({candidate:h,reason:g})=>`'${h.providerId}/${h.modelId}' ${g}`).join("; ");throw await U(le(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${n.model}' is unavailable \u2014 refusing to substitute (${m})`}}),new Error(`[broker] FATAL: exact-consult model '${n.model}' is unavailable`)}T({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:d.rejected.slice(0,16).map(({candidate:m,reason:h})=>({provider:m.providerId,model:m.modelId,reason:h,route_id:m.routeId,credential_source:m.credentialSource})),rejected_candidates_omitted:Math.max(0,d.rejected.length-16)}})}e(ce,"resolveLaunchModel");function yt(t){let n=!0;return{runtime:new Proxy(t,{get(p,i,a){return n&&i==="getAvailableSnapshot"?()=>[]:n&&i==="getAvailable"?async()=>[]:n&&i==="getModel"?()=>{}:Reflect.get(p,i,a)}}),reveal:e(()=>{n=!1},"reveal")}}e(yt,"modelLessRegistry");async function St(t,n){const s=V(),p=e(async _=>{const{authPath:S,modelsPath:k}=pt(_.agentDir),E=await Re.create({credentials:new $e(S),modelsPath:k}),R=await t.createAgentSessionServices({cwd:_.cwd,agentDir:_.agentDir,modelRuntime:E,resourceLoaderOptions:{additionalExtensionPaths:n.extensionPaths,appendSystemPrompt:n.appendSystemPromptPath!==void 0?[n.appendSystemPromptPath]:void 0,noContextFiles:!0}}),B=R.resourceLoader.getExtensions();if(n.extensionPaths.some(A=>X.includes(A))){const A=new Set(B.extensions.map(c=>c.path)),$=X.filter(c=>!A.has(c));if($.length>0){const c=B.errors.filter(C=>X.includes(C.path)).map(C=>`${C.path}: ${C.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${$.join(", ")}${c===""?"":` (${c})`}`)}}const x=await ce(R,n),u=x?.model,D=x?.thinkingLevel,b=x===void 0?yt(R.modelRuntime):void 0,P=b!==void 0?{...R,modelRuntime:b.runtime}:R,F=await t.createAgentSessionFromServices({services:P,sessionManager:_.sessionManager,model:u,thinkingLevel:D,tools:n.tools,sessionStartEvent:_.sessionStartEvent});return rt(F.session),Le(F.session),b?.reveal(),{...F,services:R}},"buildForManager"),i=n.resumeSessionPath,a=n.forkFrom!==void 0&&n.forkFrom!=="";if(!a&&(i===void 0||i==="")&&n.resumeSessionId!==void 0&&n.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${n.resumeSessionId}' (pi_session_file was never captured for this node)`);const d=!a&&i!==void 0&&i!=="",l=d&&n.newCycle===!0,m=d&&!l;let h;if(a)h=t.SessionManager.forkFrom(n.forkFrom,n.cwd);else if(m||l){if(h=t.SessionManager.open(i),l){const _=h.getLeafId();h.resetLeaf(),h.appendCustomEntry(qe,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:_})}}else h=t.SessionManager.create(n.cwd);if(t.createAgentSessionRuntime!==void 0){const _=e(async k=>{const E=await p({cwd:k.cwd,agentDir:k.agentDir,sessionManager:k.sessionManager,sessionStartEvent:k.sessionStartEvent});return{...E,diagnostics:E.services.diagnostics??[]}},"factory"),S=await t.createAgentSessionRuntime(_,{cwd:n.cwd,agentDir:s,sessionManager:h});return{session:S.session,services:S.services,resuming:m,runtime:S}}const g=await p({cwd:n.cwd,agentDir:s,sessionManager:h});return{session:g.session,services:g.services,resuming:m,runtime:void 0}}e(St,"buildBrokerSession");function bt(t){const n=e((i,a,d,l)=>{if(l?.signal?.aborted)return Promise.resolve(i);const m=t.writable();return m.length===0?Promise.resolve(i):new Promise(h=>{let g;const _=e(()=>{g!==void 0&&clearTimeout(g),l?.signal?.removeEventListener("abort",S),t.pending.delete(a.id)},"cleanup"),S=e(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),h(i)},"onAbort");l?.signal?.addEventListener("abort",S,{once:!0});const k=l?.timeout!==void 0?l.timeout:vt;g=setTimeout(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),h(i)},k),typeof g.unref=="function"&&g.unref(),t.pending.set(a.id,{request:a,resolve:e(E=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),h(d(E))},"resolve")});for(const E of m)t.forward(E,a)})},"dialogPromise"),s=e(()=>{},"noop");return{[Ue]:t.onKnownStreamWait??(i=>()=>{}),get theme(){const i=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(i==null)throw new Error("Theme not initialized. Call initTheme() first.");return i},select:e((i,a,d)=>n(void 0,{type:"extension_ui_request",id:M(),method:"select",title:i,options:a,timeout:d?.timeout},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0,d),"select"),confirm:e((i,a,d)=>n(!1,{type:"extension_ui_request",id:M(),method:"confirm",title:i,message:a,timeout:d?.timeout},l=>"cancelled"in l&&l.cancelled?!1:"confirmed"in l?l.confirmed:!1,d),"confirm"),input:e((i,a,d)=>n(void 0,{type:"extension_ui_request",id:M(),method:"input",title:i,placeholder:a,timeout:d?.timeout},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0,d),"input"),editor:e((i,a)=>n(void 0,{type:"extension_ui_request",id:M(),method:"editor",title:i,prefill:a},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0),"editor"),setStatus:e((i,a)=>t.broadcast({type:"extension_ui_request",id:M(),method:"setStatus",statusKey:i,statusText:a}),"setStatus"),setWidget:e((i,a,d)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:M(),method:"setWidget",widgetKey:i,widgetLines:a,widgetPlacement:d?.placement})},"setWidget"),setTitle:e(i=>t.broadcast({type:"extension_ui_request",id:M(),method:"setTitle",title:i}),"setTitle"),notify:e((i,a)=>{const d=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:M(),method:"notify",message:i,notifyType:d})},"notify"),onTerminalInput:e(()=>s,"onTerminalInput"),setWorkingMessage:s,setWorkingVisible:s,setWorkingIndicator:s,setHiddenThinkingLabel:s,setFooter:s,setHeader:s,custom:e(()=>Promise.resolve(void 0),"custom"),pasteToEditor:s,setEditorText:s,getEditorText:e(()=>"","getEditorText"),addAutocompleteProvider:s,setEditorComponent:s,getEditorComponent:e(()=>{},"getEditorComponent"),getAllThemes:e(()=>[],"getAllThemes"),getTheme:e(()=>{},"getTheme"),setTheme:s,getToolsExpanded:e(()=>!1,"getToolsExpanded"),setToolsExpanded:s}}e(bt,"makeBrokerUiContext");export{vn as REVIEW_BOUNDARY_NAVIGATION_CODE,gn as ReviewBoundaryNavigationError,St as buildBrokerSession,ht as disposeActiveSession,bt as makeBrokerUiContext,un as runBroker,wt as snapshotMessages};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type WakeOrigin } from './bearings.js';
|
|
2
|
-
import { type NodeMeta, type Mode, type Lifecycle, type OutcomeDeliveryBinding } from '../canvas/index.js';
|
|
2
|
+
import { type NodeMeta, type Mode, type Lifecycle, type OutcomeDeliveryBinding, type ReviewBinding } from '../canvas/index.js';
|
|
3
3
|
import { type ModelRegistryLike, type ModelRequest } from '../model-routes.js';
|
|
4
4
|
export interface SpawnChildOpts {
|
|
5
5
|
kind: string;
|
|
@@ -70,6 +70,10 @@ export interface SpawnChildOpts {
|
|
|
70
70
|
worktreeCwd?: string;
|
|
71
71
|
/** Preallocated node id, used when a managed worktree must be named before birth. */
|
|
72
72
|
nodeId?: string;
|
|
73
|
+
/** Bind the newborn to a review. Its transcript is then sliced at that
|
|
74
|
+
* review's durable boundary marker, so a fork of a companion shows only the
|
|
75
|
+
* review-era conversation rather than the origin context it inherited. */
|
|
76
|
+
reviewBinding?: ReviewBinding;
|
|
73
77
|
/** Hidden ambient "current situation" text — NOT the visible prompt/body.
|
|
74
78
|
* Stored as a `situational` card BEFORE launch so canvas-context-intro's
|
|
75
79
|
* session_start bearings nest it from the node's very first turn. Passed
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var Q=Object.defineProperty;var s=(e,o)=>Q(e,"name",{value:o,configurable:!0});import{accessSync as W,constants as A,cpSync as Y,readdirSync as D,existsSync as Z,rmSync as ee}from"node:fs";import{isAbsolute as ne,resolve as oe,join as g}from"node:path";import{spawnNode as re,currentNodeContext as ie,rootOfSpine as te,newNodeId as de,preflightNodeId as ae}from"./nodes.js";import{resolveProfileOperand as se}from"../profiles/manifest.js";import{selectProfileForCwd as ce,selectProfileForCwdReadOnly as le}from"../profiles/select.js";import{buildLaunchSpecAsync as M,buildPiArgv as fe}from"./launch.js";import{createManagedWorktreeAsync as ue,rollbackManagedWorktreeAsync as me}from"../worktree-mutation-async.js";import{usage as f,brokerLaunchFailed as E}from"../errors.js";import{writeGoal as he}from"./kickoff.js";import{appendSituationalContext as we,formatSituationalProse as pe}from"./situational-context.js";import{hasRoadmap as ke,seedRoadmap as _e}from"./roadmap.js";import{buildWakeBearings as ye}from"./bearings.js";import{encodeKickoffOrigin as ve,KICKOFF_ORIGIN_ENV as ge}from"./stamp/protocol.js";import{beginExecution as be,canonicalSessionFile as I,contextDir as
|
|
1
|
+
var Q=Object.defineProperty;var s=(e,o)=>Q(e,"name",{value:o,configurable:!0});import{accessSync as W,constants as A,cpSync as Y,readdirSync as D,existsSync as Z,rmSync as ee}from"node:fs";import{isAbsolute as ne,resolve as oe,join as g}from"node:path";import{spawnNode as re,currentNodeContext as ie,rootOfSpine as te,newNodeId as de,preflightNodeId as ae}from"./nodes.js";import{resolveProfileOperand as se}from"../profiles/manifest.js";import{selectProfileForCwd as ce,selectProfileForCwdReadOnly as le}from"../profiles/select.js";import{buildLaunchSpecAsync as M,buildPiArgv as fe}from"./launch.js";import{createManagedWorktreeAsync as ue,rollbackManagedWorktreeAsync as me}from"../worktree-mutation-async.js";import{usage as f,brokerLaunchFailed as E}from"../errors.js";import{writeGoal as he}from"./kickoff.js";import{appendSituationalContext as we,formatSituationalProse as pe}from"./situational-context.js";import{hasRoadmap as ke,seedRoadmap as _e}from"./roadmap.js";import{buildWakeBearings as ye}from"./bearings.js";import{encodeKickoffOrigin as ve,KICKOFF_ORIGIN_ENV as ge}from"./stamp/protocol.js";import{beginExecution as be,canonicalSessionFile as I,contextDir as B,crtrHome as xe,findNodeBySessionFile as Fe,getNode as w,fullName as H,jobDir as Oe,nodeDir as Ce,recordExecutionPid as Se,abortExecution as P,reportsDir as $e,setFrozen as Ee}from"../canvas/index.js";import{boundFleet as Re,brokerThresholdsForDaemon as De}from"./fleet.js";import{emitEvent as Ie}from"../events/emit.js";import{openViewerWindow as Be,focusOf as Pe,windowOfPane as je}from"./placement.js";import{waitForBrokerViewSocket as Ne}from"./placement-tmux.js";import{transition as b}from"./lifecycle.js";import{beginBootFaultAttempt as Te}from"../canvas/recovery.js";import{piSessionsRoot as Le}from"./pi-vendored.js";import{headlessBrokerHost as j}from"./host.js";import{ensureDaemon as We}from"../../daemon/manage.js";import{readConfig as Ae}from"../config.js";import{modelRequestFromConfig as Me,unregisteredConcreteModel as He}from"../model-routes.js";import{openModelRegistry as Ke}from"./model-registry.js";import{MODEL_SPEC_NEXT as ze}from"./model-selection.js";import{initializeForkContextExposure as qe}from"../substrate/injected-store.js";import{discoverLifecycleHookRegistry as Ue}from"../command-hooks/discovery.js";import{invokeLifecycleHooks as Ve}from"../command-hooks/transport/exec-lifecycle.js";function x(e){return{detail:{schema:"crtr.node-outcome-detail/v1",message:e instanceof Error?e.message:String(e)}}}s(x,"launchFailureOutcome");function Xe(e,o,d){try{return j.launch(e,o,d)}catch(r){try{b(e,"crash",{reason:"launch_failed",outcome:x(r)})}catch{}const t=r.message;throw E(t.startsWith("[broker]")?t:`[broker] refusing to launch ${e}: ${t}`,"Inspect the cause above, fix the launch recipe or environment, then retry.")}}s(Xe,"launchBrokerOrCrash");function Ge(e,o){try{b(e,"crash",{reason:"launch_failed",outcome:x(o)})}catch{}try{j.teardown(e)}catch{}}s(Ge,"crashAndTearDown");function Je(e){const o=Le();if(!Z(o))throw f(`--fork-from '${e}': no pi sessions store at ${o} to resolve it from \u2014 pass a node id or an absolute .jsonl path.`,{next:"Pass a live node id, an absolute .jsonl session path, or drop --fork-from."});const d=[];for(const a of D(o,{withFileTypes:!0})){if(!a.isDirectory())continue;const c=g(o,a.name);for(const l of D(c)){if(!l.endsWith(".jsonl"))continue;const F=l.slice(0,-6),u=F.slice(F.lastIndexOf("_")+1);d.push({id:u,path:g(c,l)})}}const r=d.filter(a=>a.id===e),t=r.length>0?r:d.filter(a=>a.id.startsWith(e));if(t.length===0)throw f(`--fork-from '${e}': no pi session with that id found.`,{next:"Pass a live node id, a real session uuid/prefix, or an absolute .jsonl session path."});if(t.length>1)throw f(`--fork-from '${e}': ambiguous \u2014 ${t.length} sessions match that id prefix; pass the full id or the .jsonl path.`,{next:"Pass the full session uuid or an absolute .jsonl path to disambiguate."});return I(t[0].path)}s(Je,"resolveSessionUuid");function K(e){const o=e.trim();if(o==="")throw f("--fork-from requires a node id, session file, or session uuid.",{next:"Pass a live node id, an absolute .jsonl session path, or a session uuid/prefix."});if(o.includes("/")||o.endsWith(".jsonl"))return I(ne(o)?o:oe(process.cwd(),o));const d=w(o);if(d!==null){const r=d.pi_session_file;if(r==null||r==="")throw f(`node ${o} has no pi session yet \u2014 it has not captured a session FILE to fork from (the broker forks a .jsonl path, not a bare id).`,{next:"Pick a node that has captured a session, or drop --fork-from."});return I(r)}return Je(o)}s(K,"resolveForkSource");async function Qe(e,o,d,r={}){return e===null?null:e!==void 0&&e!==""?se(e).profileId:o!==null?w(o)?.profile_id??null:r.readOnlySelection===!0?le(d):ce(d)}s(Qe,"resolveProfileId");function z(e){const o=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return Me(e.model,o,e.modelExact===!0)}s(z,"requestFromLaunch");async function q(e,o,d){if(e===void 0||e.kind==="logical")return;const r=He(e,d??await Ke(),o);if(r!==void 0)throw f(`model '${r.request.spec}' is not registered in this daemon.`,{received:r.request.spec,next:ze})}s(q,"assertLaunchModelRegistered");function Ye(e,o,d){const r=e??o??null;if(!d&&r===null)throw new Error("spawnChild requires a calling node (CRTR_NODE_ID) or an explicit parent");return r}s(Ye,"resolveSpawner");async function U(e,o,d){try{We()}catch{}const r=ie(),t=e.root===!0,a=Ye(e.parent,r.nodeId??null,t),c=e.mode??"base",l=e.rootLifecycle??(t?"resident":"terminal"),F=t&&l==="resident",u=e.worktree===!0,p=u?e.nodeId??de():e.nodeId;e.nodeId!==void 0&&ae(e.nodeId);const k=await Qe(e.profile,a,e.cwd),N=(await M(e.kind,c,{lifecycle:l,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:e.cwd,profileId:k})).launch;await q(z(N),{cwd:e.cwd,profileId:k});const O=e.forkFrom!==void 0?K(e.forkFrom):void 0,X=O===void 0?null:Fe(O)?.node_id??null;let m,C=e.cwd;try{u&&(m=await ue(e.worktreeCwd??e.cwd,p,e.worktreeBase),C=m.path);const _=u?(await M(e.kind,c,{lifecycle:l,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:C,profileId:k})).launch:N;u&&await q(z(_),{cwd:C,profileId:k});const n=await re({kind:e.kind,mode:c,lifecycle:l,cwd:C,name:e.name??e.kind,description:e.description,parent:t?null:a,creator:e.creator,spawnedBy:t?a??void 0:void 0,profile_id:k,forkFrom:e.forkFrom,forkSourceFile:O,modelOverride:e.model===void 0?void 0:_.model,...m!==void 0?{managedWorktree:m}:{},...p!==void 0?{nodeId:p}:{},...e.reviewBinding===void 0?{}:{reviewBinding:e.reviewBinding},...e.deadlineAt===void 0?{}:{deadlineAt:e.deadlineAt},...e.outcomeDelivery===void 0?{}:{outcomeDelivery:e.outcomeDelivery},launch:_});if(d?.(n.node_id),e.forkFrom!==void 0)try{qe(n.node_id,X)}catch(i){throw b(n.node_id,"crash",{reason:"launch_failed",outcome:x(i)}),i}if(he(n.node_id,e.prompt),e.situationalContext!==void 0&&we(n.node_id,pe(e.situationalContext)),o!==void 0)try{o(n.node_id)}catch(i){throw b(n.node_id,"crash",{reason:"launch_failed",outcome:x(i)}),i}const R=e.prompt!=="",G=`${R&&e.wakeOrigin!==void 0?`${ye(e.wakeOrigin)}
|
|
2
2
|
|
|
3
|
-
`:""}${e.prompt}`;c==="orchestrator"&&!ke(n.node_id)&&_e(n.node_id,{goal:e.prompt.trim()}),await Ze(n);const h=fe(n,{prompt:G,forkFrom:O});if(h.env={...h.env,CRTR_SUBTREE:te(n.node_id)},R){const i=e.wakeOrigin!==void 0?{type:"runtime",kind:"wake",wake:e.wakeOrigin}:{type:"runtime",kind:"kickoff",...n.spawned_by!=null&&n.spawned_by!==""?{spawnedBy:n.spawned_by}:{}};h.env[ge]=ve(i)}const S=Re();if(!S.reserveSlot(n.node_id))return Ee(n.node_id,new Date().toISOString()),Ie({level:"info",event:"broker.frozen",node_id:n.node_id,fields:{live_count:S.size(),hard_cap:De().automaticReviveCap}}),{node:w(n.node_id),frozen:!0,window:null,session:null};const J=Te(n.node_id),y=be(n.node_id,{daemonEpoch:S.epoch()});h.env={...h.env,CRTR_EXECUTION_ID:y};let $;try{$=Xe(n.node_id,h,{cwd:n.cwd,name:H(n),resuming:!1})}catch(i){throw
|
|
3
|
+
`:""}${e.prompt}`;c==="orchestrator"&&!ke(n.node_id)&&_e(n.node_id,{goal:e.prompt.trim()}),await Ze(n);const h=fe(n,{prompt:G,forkFrom:O});if(h.env={...h.env,CRTR_SUBTREE:te(n.node_id)},R){const i=e.wakeOrigin!==void 0?{type:"runtime",kind:"wake",wake:e.wakeOrigin}:{type:"runtime",kind:"kickoff",...n.spawned_by!=null&&n.spawned_by!==""?{spawnedBy:n.spawned_by}:{}};h.env[ge]=ve(i)}const S=Re();if(!S.reserveSlot(n.node_id))return Ee(n.node_id,new Date().toISOString()),Ie({level:"info",event:"broker.frozen",node_id:n.node_id,fields:{live_count:S.size(),hard_cap:De().automaticReviveCap}}),{node:w(n.node_id),frozen:!0,window:null,session:null};const J=Te(n.node_id),y=be(n.node_id,{daemonEpoch:S.epoch()});h.env={...h.env,CRTR_EXECUTION_ID:y};let $;try{$=Xe(n.node_id,h,{cwd:n.cwd,name:H(n),resuming:!1})}catch(i){throw P(y,{reason:"launch_failed"}),i}finally{S.releaseReservation(n.node_id)}if($.pid===null){const i=new Error(`broker host returned no pid for ${n.node_id}`);throw P(y,{reason:"launch_failed"}),b(n.node_id,"crash",{reason:"launch_failed",outcome:x(i)}),E(`failed to launch the broker engine for ${n.node_id} (${n.name}) \u2014 the node was not started.`,`Inspect canonical event diagnostics with \`crtr sys logs --node ${n.node_id}\`, then verify the pi engine can start in this environment.`)}if(Se(y,n.node_id,$.pid)==="shutdown")throw P(y,{reason:"superseded"}),j.teardown(n.node_id),E(`broker execution was superseded for ${n.node_id}`,"Retry spawning the node.");if(F&&e.readiness==="await"&&!await Ne(n.node_id,$.exited)){const i=J.explanation();throw Ge(n.node_id,new Error(i??`broker view socket never bound for ${n.node_id}`)),E(i!==null?`the root broker ${n.node_id} could not start \u2014 ${i}`:`the root broker ${n.node_id} never bound its view socket \u2014 it was not started.`,i!==null?"Resolve the cause named above, then retry.":`The broker engine exited before binding its view socket. Inspect canonical event diagnostics with \`crtr sys logs --node ${n.node_id}\`, then retry.`)}let T=null,L=null;if(!t&&a!==null&&Ae("user").auto_open_child_viewers)try{const i=Pe(a);if(i!==null&&i.pane!==null&&i.pane!==""){const v=Be(n.node_id,i.session??"",{name:H(n),cwd:e.cwd,besidePane:i.pane,waitForBroker:!0,initialWhip:R});v!==null&&v.pane!==null&&v.pane!==""&&(L=v.session,T=je(v.pane))}}catch{}return{node:w(n.node_id),frozen:!1,window:T,session:L}}catch(_){throw m!==void 0&&p!==void 0&&w(p)===null&&await me(m),_}}s(U,"spawnChildPrepared");async function Pn(e){return U(e)}s(Pn,"spawnChild");async function Ze(e){const o=Ue(e.cwd,e.profile_id).plans.get("node:start")??[];await Ve(o,{node:{id:e.node_id,name:e.name,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,cwd:e.cwd,nodeDir:Ce(e.node_id),contextDir:B(e.node_id),jobDir:Oe(e.node_id),reportsDir:$e(e.node_id)},runtime:{isBirth:!0,canvasHome:xe(),profile:e.profile_id??null}})}s(Ze,"invokeBirthLifecycleHooks");const V=new Set(["initial-prompt.md","yield-message.md","result.json"]);async function jn(e){const o=w(e);if(o===null)throw f(`unknown node: ${e}`,{received:e,next:"List nodes and pass the id of a node with a captured pi session."});const d=K(e),r=B(e);try{W(d,A.R_OK),W(r,A.R_OK)}catch(t){throw new Error(`cannot fork ${e}: its conversation or context is unreadable \u2014 ${t.message}`)}return U({kind:o.kind,mode:"base",cwd:o.cwd,prompt:"",root:!0,readiness:"await",forkFrom:e,profile:o.profile_id,model:o.model_override??void 0},t=>{const a=B(t);for(const c of D(r,{withFileTypes:!0}))V.has(c.name)||Y(g(r,c.name),g(a,c.name),{recursive:!0,dereference:!1,force:!0});for(const c of V)ee(g(a,c),{recursive:!0,force:!0})})}s(jn,"forkNode");export{q as assertLaunchModelRegistered,jn as forkNode,Ze as invokeBirthLifecycleHooks,K as resolveForkSource,Qe as resolveProfileId,Ye as resolveSpawner,Pn as spawnChild,U as spawnChildPrepared};
|
|
@@ -2,12 +2,10 @@ export { STALL_REPROMPT } from '../../shared/generated-context.js';
|
|
|
2
2
|
export interface StopSignals {
|
|
3
3
|
/** Did the node call `push --final` (finish) this turn? */
|
|
4
4
|
pushedFinal: boolean;
|
|
5
|
-
/** Did the node call `crtr ask` (escalate to the user) this turn? */
|
|
6
|
-
requestedHumanReply: boolean;
|
|
7
5
|
}
|
|
8
6
|
export type StopAction = {
|
|
9
7
|
action: 'allow';
|
|
10
|
-
reason: 'awaiting' | 'scheduled' | 'finished' | '
|
|
8
|
+
reason: 'awaiting' | 'scheduled' | 'finished' | 'dormant';
|
|
11
9
|
} | {
|
|
12
10
|
action: 'reprompt';
|
|
13
11
|
reason: 'stalled';
|