@north-light/cli 0.3.504 → 0.3.506
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 +5 -1
- package/dist/api/client.js +3 -3
- package/dist/api/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/api/dto/canvas.d.ts +40 -0
- package/dist/api/routes.d.ts +2 -0
- package/dist/api/routes.js +1 -1
- package/dist/builtin-memory/crouter-sdk/release-notes.md +8 -0
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +3 -3
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +3 -2
- package/dist/clients/attach/viewer.js +575 -575
- package/dist/clients/dashboard/app.d.ts +7 -0
- package/dist/clients/dashboard/app.js +2 -0
- package/dist/clients/dashboard/model.d.ts +39 -0
- package/dist/clients/dashboard/model.js +1 -0
- package/dist/clients/dashboard/render.d.ts +29 -0
- package/dist/clients/dashboard/render.js +3 -0
- package/dist/commands/canvas-browse.js +1 -1
- package/dist/commands/surface/node/focus.js +1 -1
- package/dist/commands/surface-dashboard.d.ts +2 -0
- package/dist/commands/surface-dashboard.js +3 -0
- package/dist/commands/surface.js +1 -1
- package/dist/core/canvas/browse/app.d.ts +3 -0
- package/dist/core/canvas/browse/app.js +3 -3
- package/dist/core/canvas/browse/model.d.ts +5 -1
- package/dist/core/canvas/browse/model.js +1 -1
- package/dist/core/canvas/browse/render.d.ts +5 -0
- package/dist/core/canvas/browse/render.js +3 -3
- package/dist/core/canvas/migrations.js +1 -1
- package/dist/core/canvas/recovery.d.ts +5 -0
- package/dist/core/canvas/recovery.js +2 -2
- package/dist/core/human/requests.d.ts +3 -0
- package/dist/core/human/requests.js +17 -17
- package/dist/core/keybindings/catalog.d.ts +4 -3
- package/dist/core/keybindings/catalog.js +1 -1
- package/dist/core/llm/run.js +2 -2
- package/dist/core/runtime/broker/model-adapter.d.ts +1 -2
- package/dist/core/runtime/focus-viewer.d.ts +6 -0
- package/dist/core/runtime/focus-viewer.js +1 -1
- package/dist/core/runtime/placement-tmux.d.ts +1 -1
- package/dist/core/runtime/placement-tmux.js +1 -1
- package/dist/core/runtime/tmux-bindings.js +3 -3
- package/dist/core/runtime/tmux-driver.d.ts +6 -0
- package/dist/core/runtime/tmux-driver.js +5 -5
- package/dist/core/subscription-state.d.ts +2 -0
- package/dist/core/subscription-state.js +4 -4
- package/dist/daemon/api/bridge.js +3 -3
- package/dist/daemon/api/handlers/broker-recovery.js +1 -1
- package/dist/daemon/api/handlers/canvas.js +6 -6
- package/dist/daemon/api/handlers/nodes.js +1 -1
- package/dist/daemon/api/operations.js +1 -1
- package/dist/daemon/api/viewer-presence.d.ts +3 -0
- package/dist/daemon/api/viewer-presence.js +1 -1
- package/docs/sdk/release-notes.md +8 -0
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +12 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
var w=Object.defineProperty;var i=(r,e)=>w(r,"name",{value:e,configurable:!0});import{ApiError as E}from"../../../api/errors.js";import{getNode as I}from"../../../core/canvas/canvas.js";import{liveExecutionForNode as S}from"../../../core/canvas/executions.js";import{admitEpisode as T,clearEpisode as q,clearFault as h,closeTurn as
|
|
1
|
+
var w=Object.defineProperty;var i=(r,e)=>w(r,"name",{value:e,configurable:!0});import{ApiError as E}from"../../../api/errors.js";import{getNode as I}from"../../../core/canvas/canvas.js";import{liveExecutionForNode as S}from"../../../core/canvas/executions.js";import{admitEpisode as T,clearEpisode as q,clearFault as h,closeTurn as P,invalidateEpisode as R,openTurn as v,parseProviderError as F,readEpisode as A,readFault as l,recordFault as b,recordPendingEpisode as N,recordTransportPoisonVerdict as O,recordTurnProgress as j,reopenEpisode as L}from"../../../core/canvas/recovery.js";import{notFound as D,usage as n}from"../../../core/errors.js";import{hasPresentedViewer as B}from"../viewer-presence.js";import{ownerOnly as g}from"../router.js";const f=new Set(["pi\u2192provider","viewer\u2194broker","relay\u2194broker","viewer\u2194crtrd","daemon\u2192node","crtr\u2192pi"]),$=new Set(["rate-limit","overloaded","connection","auth","protocol","context-overflow","other","wedged","model-not-found"]),C=new Set(["auto","manual","fatal"]),K=new Set(["sdk","daemon","client"]);function d(r,e){if(typeof r!="object"||r===null||Array.isArray(r))throw n(`${e} requires a JSON object`);return r}i(d,"objectBody");function a(r){if(I(r)===null)throw D(`unknown node: ${r}`,{received:r})}i(a,"requireNode");function u(r,e){if(typeof e!="string"||e==="")throw n("expected_execution_id must be a non-empty string");const t=S(r);if(t===null||t.executionId!==e)throw new E(409,"stale_execution","broker execution is no longer current")}i(u,"requireCurrentExecution");function x(r){if(typeof r!="object"||r===null||Array.isArray(r))throw n("retry must be an object");const e=r;if(!C.has(e.disposition))throw n("retry.disposition must be auto, manual, or fatal");if(e.by!==void 0&&!K.has(e.by))throw n("retry.by must be sdk, daemon, or client");for(const t of["attempt","max"])if(e[t]!==void 0&&(!Number.isSafeInteger(e[t])||e[t]<0))throw n(`retry.${t} must be a non-negative safe integer`);if(e.nextAt!==void 0&&typeof e.nextAt!="string")throw n("retry.nextAt must be a string");return e}i(x,"parseRetry");function _(r){const e=d(r,"fault input");if(!f.has(e.link))throw n("fault link is invalid");if(typeof e.op!="string"||e.op==="")throw n("fault op must be a non-empty string");if(!$.has(e.kind))throw n("fault kind is invalid");if(typeof e.message!="string")throw n("fault message must be a string");if(e.operation_id!==void 0&&(typeof e.operation_id!="string"||e.operation_id===""))throw n("operation_id must be a non-empty string");if(e.since!==void 0&&typeof e.since!="string")throw n("since must be a string");if(e.anchor_entry_id!==void 0&&(typeof e.anchor_entry_id!="string"||e.anchor_entry_id===""))throw n("anchor_entry_id must be a non-empty string");const t=e.provider_error===void 0?void 0:F(e.provider_error);if(e.provider_error!==void 0&&t===void 0)throw n("provider_error is invalid");return{...e,...t===void 0?{}:{provider_error:t},retry:x(e.retry)}}i(_,"parseFaultInput");function y(r){return{link:r.link,op:r.op,kind:r.kind,retry:r.retry,message:r.message,...r.operation_id===void 0?{}:{operation_id:r.operation_id},...r.since===void 0?{}:{since:r.since},...r.anchor_entry_id===void 0?{}:{anchorEntryId:r.anchor_entry_id},...r.provider_error===void 0?{}:{providerError:r.provider_error}}}i(y,"faultInput");function c(r){return{fault_id:r.faultId,link:r.link,op:r.op,kind:r.kind,retry:r.retry,message:r.message,since:r.since,operation_id:r.operation_id,...r.anchorEntryId===void 0?{}:{anchor_entry_id:r.anchorEntryId},...r.providerError===void 0?{}:{provider_error:r.providerError}}}i(c,"faultDto");function k(r){const e=l(r),t=A(r);return{fault:e===null?null:c(e),episode:t===null?null:{state:t.state,session_id:t.sessionId,fault:c(t.fault)}}}i(k,"recoveryState");function U(r){const e=d(r,"broker turn"),t=e.event;if(t!=="started"&&t!=="progress"&&t!=="closed"&&t!=="interrupted"&&t!=="exit-diagnostic")throw n("event is invalid");if(typeof e.expected_execution_id!="string"||e.expected_execution_id==="")throw n("expected_execution_id must be a non-empty string");if(t==="closed"){if(e.end_reason!=="settled"&&e.end_reason!=="teardown-aborted")throw n("closed turn requires end_reason settled or teardown-aborted")}else if(e.end_reason!==void 0)throw n("end_reason is valid only for closed turns");if(t==="exit-diagnostic"){const o=d(e.exit_diagnostic,"exit_diagnostic"),s=d(o.transport_poison,"exit_diagnostic.transport_poison");if(o.schema!=="crtr.execution-exit-diagnostic/v1"||!Number.isSafeInteger(s.consecutive_passes)||s.consecutive_passes<1||!Array.isArray(s.routes)||s.routes.length===0||!s.routes.every(p=>typeof p=="string"&&p!==""))throw n("exit_diagnostic is invalid")}else if(e.exit_diagnostic!==void 0)throw n("exit_diagnostic is valid only for exit-diagnostic turns");return e}i(U,"parseTurn");function V(r){const e=r.params.id;a(e);const t=U(r.body);u(e,t.expected_execution_id);let o;switch(t.event){case"started":o=v(t.expected_execution_id,{reason:"agent-start"});break;case"interrupted":o=v(t.expected_execution_id,{reason:"prompt-unsettled"});break;case"progress":o=j(t.expected_execution_id);break;case"closed":o=P(t.expected_execution_id,{endReason:t.end_reason,viewerPresent:B(e)});break;case"exit-diagnostic":{const m=t.exit_diagnostic.transport_poison;o=O(t.expected_execution_id,{consecutivePasses:m.consecutive_passes,routes:m.routes});break}}const s=l(e)?.link;return{status:200,body:{applied:o,fault_link:s==="daemon\u2192node"||s==="pi\u2192provider"?s:null}}}i(V,"handleTurn");function Y(r){const e=d(r,"provider retry");if(typeof e.expected_execution_id!="string"||e.expected_execution_id==="")throw n("expected_execution_id must be a non-empty string");if(!["record-pending","admit","reopen","invalidate","clear"].includes(e.op))throw n("provider retry op is invalid");if(typeof e.session_id!="string"||e.session_id==="")throw n("session_id must be a non-empty string");if(e.op==="record-pending"&&(e.input=_(e.input)),e.op==="admit"){if(typeof e.fault_id!="string"||e.fault_id==="")throw n("admit requires fault_id");e.retry=x(e.retry)}return e}i(Y,"parseProviderRetry");function G(r){const e=r.params.id;a(e);const t=Y(r.body);u(e,t.expected_execution_id);let o;switch(t.op){case"record-pending":o=N(e,{sessionId:t.session_id,input:y(t.input)})!==null;break;case"admit":o=T(e,{sessionId:t.session_id,faultId:t.fault_id,retry:t.retry});break;case"reopen":o=L(e,{sessionId:t.session_id});break;case"invalidate":o=R(e,{sessionId:t.session_id});break;case"clear":o=q(e,{sessionId:t.session_id});break}return{status:200,body:{applied:o,episode:k(e).episode}}}i(G,"handleProviderRetry");function J(r){const e=d(r,"broker fault");if(typeof e.expected_execution_id!="string"||e.expected_execution_id==="")throw n("expected_execution_id must be a non-empty string");if(e.op!=="record"&&e.op!=="clear")throw n("fault op must be record or clear");if(e.op==="record"&&(e.input=_(e.input)),e.op==="clear"&&e.link!==void 0&&!f.has(e.link))throw n("fault link is invalid");if(e.preserve_episode!==void 0&&typeof e.preserve_episode!="boolean")throw n("preserve_episode must be boolean");return e}i(J,"parseBrokerFault");function W(r){const e=r.params.id;a(e);const t=J(r.body);u(e,t.expected_execution_id);const o=t.op==="record"?b(e,y(t.input)):(h(e,{...t.link===void 0?{}:{link:t.link},...t.preserve_episode===void 0?{}:{preserveEpisode:t.preserve_episode}}),l(e));return{status:200,body:{fault:o===null?null:c(o)}}}i(W,"handleBrokerFault");function z(r){const e=r.params.id;return a(e),u(e,r.query.get("expected_execution_id")),{status:200,body:k(e)}}i(z,"handleRecovery");function H(r){const e=r.params.id;a(e);const t=b(e,y(_(r.body)));return{status:200,body:{fault:t===null?null:c(t)}}}i(H,"handleNodeFaultRecord");function M(r){const e=r.params.id;a(e);const t=r.query.get("link");if(t!==null&&!f.has(t))throw n("fault link is invalid");const o=r.query.get("preserve_episode");if(o!==null&&o!=="true"&&o!=="false")throw n("preserve_episode must be true or false");return{status:200,body:{cleared:h(e,{...t===null?{}:{link:t},...o===null?{}:{preserveEpisode:o==="true"}})}}}i(M,"handleNodeFaultClear");const ie=g([{method:"POST",pattern:"/v1/broker/:id/turn",handler:V},{method:"POST",pattern:"/v1/broker/:id/provider-retry",handler:G},{method:"POST",pattern:"/v1/broker/:id/fault",handler:W},{method:"GET",pattern:"/v1/broker/:id/recovery",handler:z}]),se=g([{method:"POST",pattern:"/v1/nodes/:id/fault",handler:H},{method:"DELETE",pattern:"/v1/nodes/:id/fault",handler:M}]);export{ie as brokerRecoveryRoutes,se as nodeFaultRoutes,u as requireCurrentExecution};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var
|
|
2
|
-
`);if(e.length>0){const
|
|
3
|
-
`).forEach((y,b)=>{
|
|
4
|
-
${
|
|
5
|
-
${
|
|
6
|
-
`+
|
|
1
|
+
var Y=Object.defineProperty;var l=(t,e)=>Y(t,"name",{value:e,configurable:!0});import{gzipSync as V}from"node:zlib";import{browseNodes as F,graphNodes as X,listNodes as G,pruneNodes as Z,pruneToLimit as ee,rosterEdges as w,rosterNodes as te}from"../../../core/canvas/canvas.js";import{activeBackgroundBashJobs as ne}from"../../../core/bash-jobs.js";import{contextDir as se}from"../../../core/canvas/node-agent-paths.js";import{nowIso as $}from"../../../core/fs-utils.js";import{isPidPresent as oe}from"../../../core/canvas/pid.js";import{dashboardRowsAllFromSource as re,enrichRowsFromSource as ie}from"../../../core/canvas/render-source.js";import{localCanvasSource as P}from"../../../core/canvas/source.js";import{ticketCountsForNodes as q,ticketsAcrossCanvas as ae}from"../../../core/canvas/attention.js";import{buildCorpus as de,groupCorpus as le,resolveRef as ce}from"../../../core/canvas/history.js";import{listFocuses as D,reapEmptyNodes as ue}from"../../../core/runtime/placement.js";import{boundFleet as fe}from"../../../core/runtime/fleet.js";import{retentionHold as pe}from"../../reconcilers/live-obligation.js";import{notFound as me,usage as _}from"../../../core/errors.js";import{openDb as he}from"../../../core/canvas/db.js";import{prepared as _e}from"../../../core/sqlite-statements.js";import{view as ye}from"../../../core/canvas/tree.js";import{isFinishedWork as ge,isLiveStatus as be}from"../../../core/canvas/node-order.js";import{readNodeRecap as ve}from"../../../core/canvas/node-recap.js";import{readGoal as ke}from"../../../core/runtime/kickoff.js";import{faultSummary as Se}from"../../../core/canvas/status-glyph.js";import{listPendingAsks as we}from"../../../core/human/requests.js";import{toGraphNodeDTO as Ne}from"../map.js";import{actsAsPerson as Re,canReadNode as O,canReadRun as Ce}from"../router.js";import{ApiError as T}from"../../../api/errors.js";function N(t){return t.principal.class==="person"?null:new Set(G().filter(e=>O(t.principal,e.grantee??"app:terminal",e.node_id)).map(e=>e.node_id))}l(N,"visibleNodes");function H(t){return t.principal.class==="person"?null:new Set(G().filter(e=>e.run_id?Ce(t.principal,e.grantee??"app:terminal",e.node_id):O(t.principal,e.grantee??"app:terminal",e.node_id)).map(e=>e.node_id))}l(H,"visibleHistoryNodes");function Me(t){const e=N(t);return{status:200,body:{items:ae().filter(s=>e===null||e.has(s.node_id)).map(s=>({node_id:s.node_id,name:s.name,cwd:s.cwd,count:s.count,subjects:s.subjects}))}}}l(Me,"handleAttention");function Le(t){const e=t.body;if(e===null||typeof e!="object"||!Array.isArray(e.node_ids))throw _("attention count request requires node_ids: string[]");const n=e.node_ids;if(!n.every(o=>typeof o=="string"))throw _("attention count request node_ids must contain only strings");const s=N(t);return{status:200,body:{counts:q(n.filter(o=>s===null||s.has(o)))}}}l(Le,"handleAttentionCounts");function z(t){return Buffer.from(String(t),"utf8").toString("base64")}l(z,"encodeCursor");function x(t){const e=Number(Buffer.from(t,"base64").toString("utf8"));if(!Number.isInteger(e)||e<0)throw _(`invalid cursor: ${t}`);return e}l(x,"decodeCursor");function $e(t,e,n){const a=t.loadBody().split(`
|
|
2
|
+
`);if(e.length>0){const c=a.findIndex(u=>{const f=u.toLowerCase();return e.some(i=>f.includes(i))});if(c!==-1)return a.slice(c,c+n).map(u=>u.trim()).filter(u=>u!=="").join(" \u23CE ")}const o=a.map(c=>c.trim()).filter(c=>c!=="").slice(0,n).join(" \u23CE ");return o!==""?o:t.title}l($e,"snippet");function Be(t,e,n){const s=[...t];return e==="relevance"&&n!==void 0?s.sort((a,o)=>(n.get(o.ref)??0)-(n.get(a.ref)??0)||o.tsMs-a.tsMs||a.ref.localeCompare(o.ref)):e==="oldest"?s.sort((a,o)=>a.tsMs-o.tsMs||a.ref.localeCompare(o.ref)):s.sort((a,o)=>o.tsMs-a.tsMs||a.ref.localeCompare(o.ref)),s}l(Be,"sortArtifacts");function Ee(t){if(t==null)return{};if(typeof t!="object")throw _("history search body must be a JSON object");return t}l(Ee,"parseSearchBody");function Ie(t){if(t===null||typeof t!="object")throw _("history grep body must be a JSON object");const e=t;if(typeof e.pattern!="string"||e.pattern==="")throw _("history grep body requires a non-empty pattern");return e}l(Ie,"parseGrepBody");function j(t,e){const n={cwd:t.cwd,allCwds:t.all_cwds===!0,under:t.under,nodes:t.nodes},s={types:t.types,kinds:t.kinds,statuses:t.statuses,sinceMs:t.since_ms,untilMs:t.until_ms,origins:t.origins,roles:t.roles,from:t.from},a=H(e);return de(n,s).filter(o=>a===null||a.has(o.nodeId))}l(j,"buildCorpusFromQuery");function Oe(t){if(t==null)return{};if(typeof t!="object")throw _("history stats body must be a JSON object");return t}l(Oe,"parseStatsBody");const J=["origin","node","kind","day","type","role"];function Te(t){const e=Oe(t.body),n=e.group_by??"type";if(!J.includes(n))throw _(`--group-by must be one of: ${J.join(", ")}; received: ${String(e.group_by)}`);const s=j(e,t),a=le(s,n);return{status:200,body:{group_by:n,groups:a,total:a.reduce((c,u)=>c+u.count,0),scanned:s.length}}}l(Te,"handleHistoryStats");function je(t){const e=Ie(t.body),n=Math.min(100,Math.max(1,e.limit??20)),s=j(e,t),a=e.cursor!==void 0?x(e.cursor):0;let o;try{o=new RegExp(e.pattern,"i")}catch{throw _(`invalid regex pattern: ${e.pattern}`)}const c=[];for(const r of s)r.loadBody().split(`
|
|
3
|
+
`).forEach((y,b)=>{o.test(y)&&c.push({ref:r.ref,node:`${r.nodeName} (${r.nodeId})`,ts:r.ts,line:b+1,text:y.trim()})});c.sort((r,d)=>r.ref.localeCompare(d.ref)||r.line-d.line);const u=c.slice(a,a+n),f=a+n<c.length?z(a+n):null;return{status:200,body:{hits:u,next_cursor:f,total:c.length}}}l(je,"handleHistoryGrep");function Ae(t){const e=Ee(t.body),n=(e.query??"").trim(),s=e.weigh_body===!0,a=e.full===!0,o=Math.max(1,e.snippet_lines??1),c=Math.min(100,Math.max(1,e.limit??20)),u=e.per_node===!0;if(u&&(e.nodes===void 0||e.nodes.length===0))throw new T(400,"invalid_request","`per_node` requires a non-empty `nodes` list",{param:"nodes"});const f=j(e,t),i=e.cursor!==void 0?x(e.cursor):0,r=n.toLowerCase().split(/\s+/).filter(p=>p.length>0);let d=f,y;const b=e.sort??(r.length>0?"relevance":"recency");if(r.length>0&&b==="relevance"){y=new Map;const p=[];for(const h of f){const I=h.title.toLowerCase(),W=h.nodeName.toLowerCase(),Q=h.nodeDesc.toLowerCase(),A=s?h.loadBody().toLowerCase():null;let S=0;for(const L of r)I.includes(L)&&(S+=10),W.includes(L)&&(S+=5),Q.includes(L)&&(S+=3),A!==null&&A.includes(L)&&(S+=1);S>0&&(y.set(h.ref,S),p.push(h))}d=p}else r.length>0&&(d=f.filter(p=>{const h=`${p.title}
|
|
4
|
+
${p.nodeName}
|
|
5
|
+
${p.nodeDesc}${s?`
|
|
6
|
+
`+p.loadBody():""}`.toLowerCase();return r.some(I=>h.includes(I))}));let g=Be(d,b,y);if(u){const p=new Set;g=g.filter(h=>!p.has(h.nodeId)&&p.add(h.nodeId))}const M=u?g:g.slice(i,i+c),k=!u&&i+c<g.length?z(i+c):null;return{status:200,body:{hits:M.map(p=>{const h={ref:p.ref,node:`${p.nodeName} (${p.nodeId})`,kind:p.nodeKind,source:p.source,ts:p.ts,...u?{node_id:p.nodeId}:{}};return b==="relevance"&&y!==void 0&&(h.score=y.get(p.ref)??0),a?h.body=p.loadBody():h.snippet=$e(p,r,o),h}),next_cursor:k,total:g.length}}}l(Ae,"handleHistorySearch");function Fe(t){const e=(t.query.get("ref")??"").trim();if(!e.includes(":"))throw _(`ref must be <node-id>:inbox/<n>, <node-id>:session, or <node-id>:session/<n>; received: ${e}`,{received:e,next:"Get a valid ref from `crtr canvas history search`. Reports and documents are `crtr canvas read <name>`."});const n=ce(e);if(n===null)throw me(`no inbox entry or message for ref: ${e}`,{ref:e,next:"Re-run `crtr canvas history search` for a current ref. Reports and documents are `crtr canvas read <name>`."});if(H(t)?.has(n.nodeId)===!1)throw new T(404,"not_found","artifact not found");const s=n.source,o=t.query.get("format")==="raw"&&n.raw!==null?n.raw:n.body;return{status:200,body:{ref:e,node:`${n.nodeName} (${n.nodeId})`,source:s,ts:n.ts,content:o}}}l(Fe,"handleHistoryRead");function Ge(t){for(const[s]of t.query)if(s!=="live")throw _(`unknown snapshot query parameter: ${s}`);const e=t.query.getAll("live");if(e.length>1)throw _("live must appear at most once");const n=e[0];if(n===void 0||n==="false"||n==="0")return!1;if(n==="true"||n==="1")return!0;throw _("live must be true or false")}l(Ge,"snapshotLiveOnly");async function Pe(t){const e=new Set(D().map(r=>r.node_id)),n=N(t),s=(await re(P,e,Ge(t))).filter(r=>n===null||n.has(r.node_id)),a=q(s.map(r=>r.node_id));await ie(P,s,a);const o=s.map(r=>{const d=r.srcRow,y=d?.host_kind??"tmux";return{node_id:r.node_id,name:r.name,title:r.handle??r.name,description:r.description??null,kind:r.kind,mode:r.mode,lifecycle:r.lifecycle??d?.lifecycle,status:r.status,cwd:r.cwd,profile_id:r.profile_id??null,parent:d?.parent??null,created:r.created,host_kind:y,enterable:y==="broker",attention_count:r.asks,...d?.cycles!=null?{cycles:d.cycles}:{},...r.mtimeMs!==void 0?{last_activity:new Date(r.mtimeMs).toISOString()}:{},ctx_tokens:r.ctx_tokens,streaming:r.streaming??!1,jobs_active:d!==void 0&&oe(d.pi_pid)?ne(se(r.node_id)).length:0,waiting_for:d?.waiting_for??null,hanging:r.hanging??null,viewed:r.viewed??!1,final_report:d?.final_report??null,finalized_at:d?.finalized_at??null}}),c=new Map;for(const r of w()){const d=c.get(r.from_id);d===void 0?c.set(r.from_id,[r.to_id]):d.push(r.to_id)}const u=new Set(s.map(r=>r.node_id)),f=Object.fromEntries(s.map(r=>[r.node_id,(c.get(r.node_id)??[]).filter(d=>u.has(d))]));return{status:200,body:{generated_at:$(),nodes:o,subscriptions:f}}}l(Pe,"handleSnapshot");function K(){const t=te().map(n=>{const s=n.host_kind??"tmux";return{node_id:n.node_id,name:n.name,kind:n.kind,mode:n.mode,lifecycle:n.lifecycle,status:n.status,cwd:n.cwd,host_kind:s,enterable:s==="broker",parent:n.parent,created:n.created}}),e=w().map(n=>({from_id:n.from_id,to_id:n.to_id,active:n.active,created:n.created}));return{generated_at:$(),nodes:t,edges:e}}l(K,"buildRoster");let R=null,B=null;function qe(){return R===null?(R=Promise.resolve().then(()=>K()).finally(()=>{R=null}),R):(B===null&&(B=R.then(()=>K()).finally(()=>{B=null})),B)}l(qe,"rosterCoalesced");async function De(t){const e=await qe(),n=N(t);return n===null?{status:200,body:e}:{status:200,body:{...e,nodes:e.nodes.filter(s=>n.has(s.node_id)),edges:e.edges.filter(s=>n.has(s.from_id)&&n.has(s.to_id))}}}l(De,"handleRoster");function U(t){if(t.name!==""&&t.name!==t.kind)return t.name;const e=(t.description??"").trim();return e!==""?e:t.name}l(U,"liveRootName");function He(){const t=F(),e=new Map(t.map(i=>[i.node_id,i])),n=new Map(_e(he(),"SELECT node_id, reply_at, read_at FROM nodes WHERE parent IS NULL").all().map(i=>[i.node_id,i])),s=t.filter(i=>i.parent===null&&i.kind!=="human"&&(be(i.status)||!ge({lifecycle:i.lifecycle,finalized:i.final_report!=null}))),a=we(),o=new Map;for(const i of a)o.set(i.requester_node_id,(o.get(i.requester_node_id)??0)+1);const c=new Map;for(const i of w())c.set(i.from_id,[...c.get(i.from_id)??[],i.to_id]);const u=l(i=>{const r=e.get(i)?.fault;return r&&r.link!=="broker\u2194crtrd"?Se(r):null},"faultOf"),f=s.map(i=>{const r=[i.node_id,...ye(i.node_id)].filter(m=>e.get(m)?.kind!=="human"&&e.has(m)),d=new Set(r),y=a.filter(m=>d.has(m.requester_node_id)),b=n.get(i.node_id),g=b?.reply_at??null,M=b?.read_at??null;let k=i.created;for(const m of r){const v=e.get(m).telemetry_updated_at;v!=null&&v>k&&(k=v)}return g!==null&&g>k&&(k=g),{node_id:i.node_id,name:U(i),cwd:i.cwd,profile_id:i.profile_id,status:i.status,state_line:(()=>{const m=ve(i.node_id)?.state.trim();return m||null})(),goal:ke(i.node_id)?.trim()||null,asks:y.length,first_ask_ticket_id:y[0]?.inbox_ticket_id??null,fault:r.map(u).find(m=>m!==null)??null,running_count:r.filter(m=>e.get(m).streaming===!0).length,unread:g!==null&&(M===null||g>M),last_activity:k,children:(c.get(i.node_id)??[]).filter(m=>e.has(m)&&e.get(m).kind!=="human").map(m=>{const v=e.get(m);return{node_id:m,name:U(v),status:v.status,streaming:v.streaming===!0,asks:o.get(m)??0,fault:u(m)}})}});return{generated_at:$(),rows:f}}l(He,"buildLiveRoots");let C=null,E=null;function ze(){const t=l(()=>Promise.resolve().then(He),"run");return C===null?(C=t().finally(()=>{C=null}),C):(E===null&&(E=C.then(t).finally(()=>{E=null})),E)}l(ze,"liveRootsCoalesced");async function xe(t){if(!Re(t.principal))throw new T(403,"permission_error","only the person reads the dashboard");const e=await ze(),n=t.query.get("profile");return{status:200,body:n===null?e:{...e,rows:e.rows.filter(s=>s.profile_id===n)}}}l(xe,"handleLiveRoots");function Je(t){const e=F().filter(o=>t.principal.class==="person"||O(t.principal,o.grantee??"app:terminal",o.node_id)).map(o=>({node_id:o.node_id,name:o.name,description:o.description,kind:o.kind,mode:o.mode,lifecycle:o.lifecycle,status:o.status,cwd:o.cwd,profile_id:o.profile_id,grantee:o.grantee??"app:terminal",parent:o.parent,created:o.created,frozen_at:o.frozen_at??null,terminal_reason:o.terminal_reason??null,final_report:o.final_report??null,telemetry_tokens_in:o.telemetry_tokens_in??null,telemetry_updated_at:o.telemetry_updated_at??null,fault:o.fault&&o.fault.link!=="broker\u2194crtrd"?{...o.fault,link:o.fault.link}:null,streaming:o.streaming??!1})),n=new Set(e.map(o=>o.node_id)),s=w().filter(o=>n.has(o.from_id)&&n.has(o.to_id));return{status:200,rawBody:V(JSON.stringify({nodes:e,edges:s}),{level:1}),headers:{"content-type":"application/gzip"}}}l(Je,"handleBrowse");function Ke(t){const e=N(t);return{status:200,body:{generated_at:$(),nodes:X().filter(s=>e===null||e.has(s.node_id)).map(Ne),edges:w().filter(s=>e===null||e.has(s.from_id)&&e.has(s.to_id)).map(s=>({from_id:s.from_id,to_id:s.to_id,active:s.active,created:s.created})),focused_node_ids:D().map(s=>s.node_id).filter(s=>e===null||e.has(s))}}}l(Ke,"handleGraph");function Ue(t){if(t==null)return{};if(typeof t!="object")throw _("prune body must be a JSON object");const e=t,n=l(r=>{const d=e[r];if(d!==void 0){if(typeof d!="number"||!Number.isFinite(d))throw _(`${r} must be a number`);return d}},"num"),s=l(r=>{const d=e[r];if(d!==void 0){if(typeof d!="boolean")throw _(`${r} must be a boolean`);return d}},"bool"),a={},o=n("limit");o!==void 0&&(a.limit=o);const c=n("ttl_days");c!==void 0&&(a.ttl_days=c);const u=s("include_stale");u!==void 0&&(a.include_stale=u);const f=s("empty");f!==void 0&&(a.empty=f);const i=s("dry_run");return i!==void 0&&(a.dry_run=i),a}l(Ue,"parsePruneBody");function We(t){const e=Ue(t.body),n=e.ttl_days??14,s=e.dry_run??!1,a=pe(fe());let o;return e.limit!==void 0?o=ee({maxNodes:e.limit,held:a,dryRun:s}).pruned.map(f=>({node_id:f.node_id,status:f.status,created:f.created})):e.empty===!0?o=ue({dryRun:s}).map(f=>({node_id:f,status:"empty",created:""})):o=Z({ttlDays:n,held:a,dryRun:s,includeStale:e.include_stale??!1}).pruned.map(f=>({node_id:f.node_id,status:f.status,created:f.created})),{status:200,body:{pruned:o,dry_run:s,ttl_days:n}}}l(We,"handlePrune");const kt=[{method:"GET",pattern:"/v1/canvas/attention",handler:Me},{method:"POST",pattern:"/v1/canvas/attention/counts",handler:Le},{method:"POST",pattern:"/v1/canvas/history/search",handler:Ae},{method:"POST",pattern:"/v1/canvas/history/grep",handler:je},{method:"GET",pattern:"/v1/canvas/history/read",handler:Fe},{method:"POST",pattern:"/v1/canvas/history/stats",handler:Te},{method:"GET",pattern:"/v1/canvas/snapshot",handler:Pe},{method:"GET",pattern:"/v1/canvas/roster",handler:De},{method:"GET",pattern:"/v1/canvas/live-roots",handler:xe},{method:"GET",pattern:"/v1/canvas/browse",handler:Je},{method:"GET",pattern:"/v1/canvas/graph",handler:Ke},{method:"POST",pattern:"/v1/canvas/prune",ownerOnly:!0,handler:We}];export{kt as canvasRoutes,Je as handleBrowse};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var Re=Object.defineProperty;var a=(e,t)=>Re(e,"name",{value:t,configurable:!0});import{prepared as X}from"../../../core/sqlite-statements.js";import{envProfileId as Ie}from"../../../shared/env.js";import{pausedCanvasProfiles as Oe}from"../../../core/profiles/manifest.js";import{existsSync as N,realpathSync as Z,statSync as q}from"node:fs";import{isAbsolute as G,resolve as T}from"node:path";import{appendSituationalContext as $e,formatSituationalProse as Ae}from"../../../core/runtime/situational-context.js";import{closeNode as Ce}from"../../../core/runtime/close.js";import{reviveNode as Ne}from"../../../core/runtime/revive.js";import{nowIso as B}from"../../../core/fs-utils.js";import{assertLaunchModelRegistered as x,forkNode as Te,resolveForkSource as Ee,spawnChildPrepared as Pe}from"../../../core/runtime/spawn.js";import{forkSourceNode as De,newNodeId as ee}from"../../../core/runtime/nodes.js";import{abandonCreateRequest as ne,childrenOf as Le,completeCreateRequest as te,findCreateRequest as Me,getNode as R,recordCreateRequestNode as je,reserveCreateRequest as oe,reserveCreateRequestNode as Fe,listNodes as re,recordRespawnAttempt as Ge,subscribersOf as Be,subscriptionsOf as ie,setMessageWait as xe,updateNode as C}from"../../../core/canvas/canvas.js";import{subtreeIds as Ke}from"../../../core/canvas/nav-model.js";import{withCanvasWrite as K}from"../../../core/canvas/db.js";import{nodeObject as We}from"../../../core/graph/objects.js";import{recordActedOn as Ve}from"../../../core/graph/edges.js";import{publish as ze}from"../../../core/graph/events.js";import{readerFor as Je}from"../reader.js";import{relocateSessionCwd as Ue,unbindSession as Ye}from"../../../core/canvas/sessions.js";import{ticketCountsForNodes as He}from"../../../core/canvas/attention.js";import{isSafeNodeId as Qe}from"../../../core/canvas/paths.js";import{contextDir as de,nodeAgentDir as W}from"../../../core/canvas/node-agent-paths.js";import{checkCronBirth as Xe}from"../../cron/authority.js";import{cronBirthPlacement as Ze}from"../../cron/armed-context.js";import{existsBeneath as qe,isAbsentOrRefused as en,isBeneathRefusal as nn,readdirBeneath as tn}from"../../../core/spaces/open-beneath.js";import{readNodeMessagesPage as on,readNodeSession as rn,readNodeSnapshot as dn,transcriptMarkdown as sn}from"../../../core/runtime/node-read.js";import{assembleNodeSubject as an}from"../../../core/substrate/subject.js";import{reviveAll as ln}from"../../../core/runtime/revive-all.js";import{promoteAsync as cn,requestYieldAsync as fn,reshapeNodeAsync as V}from"../../../core/runtime/promote.js";import{recycleNode as un}from"../../../core/runtime/recycle.js";import{relaunchRoot as pn}from"../../../core/runtime/reset.js";import{assertReopenGate as mn}from"../../../core/runtime/reopen.js";import{writeYieldMessage as hn,readGoal as wn}from"../../../core/runtime/kickoff.js";import{ensureRoadmap as yn,hasRoadmap as _n}from"../../../core/runtime/roadmap.js";import{renameWindow as gn}from"../../../core/runtime/placement.js";import{buildLaunchSpecAsync as bn,explicitModelIntent as vn,normalizeModel as kn,readMergedLaunchConfigAsync as se}from"../../../core/runtime/launch.js";import{modelRequestFromConfig as Sn}from"../../../core/model-routes.js";import{persistDormantModel as Rn,setModelLive as In}from"../../../core/runtime/model-swap.js";import{waitForBrokerViewSocket as ae}from"../../../core/runtime/view-socket.js";import{BrokerUnreachableError as On}from"../../../core/runtime/broker-request.js";import{boundFleet as E}from"../../../core/runtime/fleet.js";import{admitLegacyStructuredOutput as $n}from"../../structured-requests/sidecar.js";import{assertOutputSchemaAccepted as An}from"../../../core/runtime/structured-output.js";import{OUTCOME_PAYLOAD_MAX_BYTES as le}from"../../../core/canvas/types.js";import{HUMAN_ACTION_NAME_PATTERN as Cn}from"../../../core/human/action-binding.js";import{resolveHumanAction as Nn}from"../../../core/human-actions.js";import{parseDurationMs as Tn}from"../../../core/wake.js";import{claimWarmNode as En,refillWarmPool as ce,resumeWarmClaim as Pn,warmPoolEnabled as Dn}from"../../../core/runtime/warm-pool.js";import{assertLaunchKind as z,isLaunchKind as Ln,resolveLaunchTarget as Mn}from"../../../core/runtime/launch-target.js";import{fullName as jn}from"../../../core/canvas/labels.js";import{reportsForNode as fe}from"./reports.js";import{requireUsableProfile as Fn}from"./profiles.js";import{assertProfileActive as Gn,loadExactProfileManifest as Bn}from"../../../core/profiles/manifest.js";import{getCron as ue}from"../../../core/canvas/crons.js";import{cronWakeOrigin as xn}from"../../../core/runtime/bearings.js";import{boundDaemonControl as Kn}from"../../control.js";import{notFound as P,usage as h}from"../../../core/errors.js";import{assertScope as Wn,validateScopes as pe}from"../../../core/scopes.js";import{scopeAllowed as O}from"../../../shared/env.js";import{toCloseResultDTO as Vn,toNodeDetailDTO as J,toNodeSummaryDTO as zn,toReviveResultDTO as Jn}from"../map.js";import{ApiError as m}from"../../../api/index.js";import{InputError as w}from"../../../core/io.js";import{brokerMayReach as U,canReadNode as me,resolvedScopes as Un}from"../router.js";import{forwardVerb as Yn,queryWithoutMachine as Hn,relayError as Qn,unknownError as Xn,withMachine as Zn}from"../../peer/forward.js";import{fileRoot as qn}from"../../../core/spaces/file-root.js";import{activeGrant as et,terminalGrant as nt}from"../../../core/grants/mirror.js";import{appRungForGrant as tt}from"../../../core/llm/app-rungs.js";import{APP_FAMILY as ot}from"../../../core/model-routes.js";import{readConfig as rt}from"../../../core/config.js";import{hasConfiguredProviderCredential as it,NO_PROVIDER_CREDENTIAL_MESSAGE as he}from"../../../core/runtime/provider-credential-gate.js";function y(e){const t=R(e);if(t===null)throw P(`unknown node: ${e}`,{received:e});return t}a(y,"requireMeta");function Y(e){return{subscribesTo:ie(e),subscribers:Be(e),children:Le(e)}}a(Y,"edgesFor");function g(e){const t=y(e);return J(t,Y(e))}a(g,"detailOf");function dt(e){let t=fe(e).length;try{t+=tn(W(e),de(e)).length}catch(n){if(!en(n))throw n}return t}a(dt,"countFiles");function st(e){if(typeof e!="object"||e===null)throw h("a node create requires a JSON body");const t=e;if(t.kind!==void 0&&(typeof t.kind!="string"||t.kind.trim()===""))throw h("kind must be a non-empty string when provided");if(t.description!==void 0&&(typeof t.description!="string"||t.description.trim()===""))throw h("description must be a non-empty string when provided");if(t.creator!==void 0&&(typeof t.creator!="string"||t.creator.trim()===""))throw h("creator must be a non-empty node id when provided");if(t.scopes!==void 0&&pe(t.scopes),t.isolated!==void 0&&typeof t.isolated!="boolean")throw new m(400,"invalid_request","isolated must be a boolean",{param:"isolated"});const n=t.root_lifecycle;if(n!==void 0&&n!=="resident"&&n!=="terminal")throw h("root_lifecycle must be 'resident' or 'terminal'");if(t.request_key!==void 0&&(typeof t.request_key!="string"||t.request_key.trim()===""||t.request_key.length>128))throw h("request_key must be a non-empty string of at most 128 characters when provided");return t}a(st,"parseCreateBody");function at(e){if(e===void 0)return;const t=Tn(e),n=t===null?null:new Date(Date.now()+t);if(t===null||!Number.isFinite(t)||t<=0||n===null||!Number.isFinite(n.getTime()))throw new m(422,"invalid_deadline","`deadline` must be a positive representable duration");return n.toISOString()}a(at,"parseDeadline");function lt(e){if(e!==void 0){if(typeof e!="object"||e===null||Array.isArray(e))throw new m(400,"invalid_request","`outcome_delivery` must be an object");if(typeof e.action!="string"||!Cn.test(e.action))throw new m(400,"invalid_request","`outcome_delivery.action` must be a declared action name");if(e.payload!==void 0){let t;try{t=JSON.stringify(e.payload)}catch{throw new m(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable")}if(t===void 0)throw new m(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable");if(Buffer.byteLength(t,"utf8")>le)throw new m(413,"payload_too_large",`serialized payload exceeds ${le} bytes`)}return e}}a(lt,"parseOutcomeDelivery");function ct(e,t){const n=Nn(e.action,t);if(!("kind"in n))return{actionName:e.action,argv:n.argv,cwd:n.cwd,configOrigin:n.configOrigin,...e.payload===void 0?{}:{payload:e.payload}};throw n.kind==="unknown_action"?new m(422,"unknown_action",`no action named ${e.action} is declared from ${t}`):new m(422,"invalid_action",`${e.action} is declared in ${n.configOrigin} but unusable: ${n.reason}`,{reason:n.reason,configOrigin:n.configOrigin})}a(ct,"resolveOutcomeDelivery");function ft(e,t,n){const r={kind:e.kind,cwd:n,prompt:e.prompt??""};return e.mode!==void 0&&(r.mode=e.mode),e.name!==void 0&&(r.name=e.name),e.description!==void 0&&(r.description=e.description),t!==void 0&&(r.parent=t),e.creator!==void 0&&(r.creator=e.creator),e.scopes!==void 0&&(r.scopes=e.scopes),e.isolated!==void 0&&(r.isolated=e.isolated),e.root===!0&&(r.root=!0),e.root_lifecycle!==void 0&&(r.rootLifecycle=e.root_lifecycle),(e.worktree===!0||typeof e.worktree=="string")&&(r.worktree=!0),typeof e.worktree=="string"&&(r.worktreeBase=e.worktree),e.worktree!==void 0&&(r.worktreeCwd=T(e.pin_cwd??e.cwd??n)),e.fork_from!==void 0&&(r.forkFrom=e.fork_from),e.model!==void 0&&(r.model=e.model),e.profile!==void 0&&(r.profile=e.profile),e.situational_context!==void 0&&(r.situationalContext=e.situational_context),e.node_id!==void 0&&(r.nodeId=e.node_id),r}a(ft,"buildRecipe");function ut(e,t,n){return!Dn()||e.prefer_warm!==!0||e.root!==!0||e.parent!=null||e.root_lifecycle==="terminal"||(e.prompt??"")!==""||e.model!==void 0||e.fork_from!==void 0||e.worktree!==void 0||e.node_id!==void 0||e.scopes!==void 0||e.isolated!==void 0?null:{kind:e.kind,mode:e.mode??"base",cwd:t,profileId:n,model:e.model??null,situationalContext:e.situational_context??null,name:e.name??null,creator:e.creator??null}}a(ut,"warmRequestFor");import{resolveCreateKind as lr}from"../../../core/runtime/launch-target.js";function we(e){const t=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return Sn(e.model,t,e.modelExact===!0)}a(we,"requestFromLaunch");function pt(e,t){if(t===null)return e;if(e.scopes===void 0)return{...e,scopes:[...t]};const n=e.scopes.filter(r=>!O(t,r));if(n.length===0)return e;throw new m(403,"scope_denied",`scopes exceed the bearer token's ceiling: ${n.join(", ")}`,{scopes:n,ceiling:t})}a(pt,"withinCeiling");async function ye(e,t,n){const r=(await bn(t.kind,t.mode,{lifecycle:t.lifecycle,hasManager:e.parent!==null,model:t.model,modelOverride:!0,cwd:e.cwd,profileId:e.profile_id??null})).launch;await x(we(r),{cwd:e.cwd,profileId:e.profile_id??null},n)}a(ye,"assertNodeModelChangeRegistered");function _e(e,t){const n=e.principal;if(n.class!=="broker"&&n.class!=="cron")return;const r=qn({app:n.app,resolved:Un(n),launched:n.scopes},t,"read");if("root"in r)return;const o="missing"in r?r.missing:null;throw new m(403,"scope_missing",o?`the child's directory ${t} needs missing scope ${o}`:`no permission of this run names the child's directory ${t}`,void 0,void 0,o?{scope:o}:void 0)}a(_e,"assertCallerReaches");const H=new Map;async function mt(e,t={},n={}){const r=pt(st(e.body),e.ceiling);if(e.principal.class==="broker"){const c=e.principal;if(r.prefer_warm===!0&&c.app!=="app:terminal"&&(r.prefer_warm=!1),r.parent!=null){const i=y(r.parent);if(i.grantee!==c.app)throw new m(403,"other_app_run","cannot create a child under another app's node");if(!U(c,r.parent,i.grantee??"app:terminal"))throw P(`unknown node: ${r.parent}`,{received:r.parent})}if(r.creator!==void 0&&r.creator!==c.node)throw new m(403,"other_app_run","cannot create for another node");if(r.fork_from!==void 0){let i=null;try{i=De(Ee(r.fork_from))}catch{}if(i?.grantee!==c.app||!U(c,i.node_id,i.grantee))throw new m(403,"other_app_run","cannot fork another app's conversation")}r.creator=c.node}if(e.principal.class==="cron"){const c=e.principal;for(const l of["parent","creator","fork_from","node_id"])if(r[l]!=null)throw new m(403,"permission_error",`a cron cannot set ${l} on a node it starts`);r.prefer_warm=!1;const i=Xe({grantee:c.app,sub:c.sub,grant_id:c.grant,scopes:c.scopes});if(!i.allowed)throw new m(i.reason==="scope_missing"?403:401,i.reason==="scope_missing"?"scope_missing":"grant_revoked",i.message);if(r.scopes!==void 0){const l=r.scopes.find(u=>!O(i.effectiveScopes,u)||!O(c.scopes,u));if(l!==void 0)throw new m(403,"scope_missing",`scope ${l} is not held by this cron`,void 0,void 0,{scope:l})}else c.scopes!==null&&(r.scopes=[...c.scopes]);r.node_id=ee(),c.isolated&&(r.isolated=!0,r.cwd=W(r.node_id,c.app))}r.creator!==void 0&&Wn(y(r.creator),"crtr:act");const o=r.request_key?.trim();if(o===void 0||r.node_id!==void 0&&Qe(r.node_id)&&R(r.node_id)!==null&&Me(o)?.nodeId!==r.node_id)return D(e,r,t,n);const s=H.get(o);if(s!==void 0)return s;const d=ht(e,r,o,t,n);H.set(o,d);try{return await d}finally{H.delete(o)}}a(mt,"handleCreate");async function ht(e,t,n,r,o){const s=oe(n);if(s.nodeId!==null&&R(s.nodeId)!==null){if(s.state!=="warm_claimed"){const d=R(s.nodeId);if(e.principal.class!=="person"&&!me(e.principal,d.grantee??"app:terminal",s.nodeId))throw new m(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:g(s.nodeId)}}return D(e,t,r,o,s)}try{return await D(e,t,r,o,s)}catch(d){const c=oe(n);throw(c.nodeId===null||R(c.nodeId)===null)&&ne(n,c.nodeId),d}}a(ht,"handleKeyedCreateRequest");async function D(e,t,n,r,o=void 0){const s=r.deadlineAt??at(t.deadline),d=lt(t.outcome_delivery),c=e.principal.class==="cron"?Ze({grantee:e.principal.app,sub:e.principal.sub,grant_id:e.principal.grant,scopes:e.principal.scopes,cron_id:e.principal.cron,origin_run_id:e.principal.origin_run,isolated:e.principal.isolated,creator:ue(e.principal.cron)?.created_by??null},t.node_id):null;c!==null&&(t.root=c.root===!0);const i=c?.parent??t.parent??void 0;if(i==null&&t.root!==!0)throw h("a node create requires a parent (or root: true for an independent root)");let l=null;if(t.output_schema!==void 0){try{l=JSON.parse(t.output_schema)}catch{throw h("output_schema must be a JSON schema string")}if(l===null||typeof l!="object"||Array.isArray(l))throw h("output_schema must be a JSON schema object");await An(l)}const{profileId:u,kind:p,cwd:f,launch:b}=await Mn(t,{validateKind:Se});_e(e,f),t.worktree!==void 0&&_e(e,T(t.pin_cwd??t.cwd??f));const v={...t,kind:p},_=d===void 0?void 0:ct(d,f);if(await x(we(b),{cwd:f,profileId:u},n.modelRegistry),!await it(u))throw new m(412,"no_provider_credential",he,{error:"no_provider_credential",message:he,next:"The person running this runtime logs a provider in with `crtr sys setup`, or stores a provider key on the profile."});let M=null;{const $=o===void 0||o.nodeId===null||o.state==="warm_claimed"?ut(v,f,u):null,j=l===null&&r.beforeBrokerLaunch===void 0?void 0:S=>{l!==null&&$n(S,"terminal",l),r.beforeBrokerLaunch?.(S)};if(o?.state==="warm_claimed"&&o.nodeId!==null){const S=$===null?null:await Pn($,o.nodeId,j);if(S===null)throw ne(o.requestKey,o.nodeId),new m(503,"create_resume_failed",`could not resume warm claim ${o.nodeId}; retry the create`);return te(o.requestKey,S),{status:201,body:g(S)}}if($!==null){const S=await En($,{...s===void 0?{}:{deadlineAt:s},..._===void 0?{}:{outcomeDelivery:_},...o===void 0?{}:{requestKey:o.requestKey}},j);if(S!==null)return o!==void 0&&te(o.requestKey,S),ce($),{status:201,body:g(S)};M=$}const F=o?.nodeId??t.node_id??(o===void 0?void 0:ee());o!==void 0&&o.nodeId===null&&Fe(o.requestKey,F);const I=ft(F===void 0?v:{...v,node_id:F},i,f);c!==null&&(c.rootLifecycle!==void 0&&(I.rootLifecycle=c.rootLifecycle),c.scopes!==void 0&&v.scopes===void 0&&(I.scopes=c.scopes),c.run!==void 0&&(I.run=c.run),c.withinCreate!==void 0&&(I.withinCreate=c.withinCreate)),s!==void 0&&(I.deadlineAt=s),_!==void 0&&(I.outcomeDelivery=_),I.readiness=t.root===!0?"await":"launch";const Q=await Pe(I,j,()=>{M!==null&&ce(M)});return o!==void 0&&je(o.requestKey,Q.node.node_id),{status:201,body:g(Q.node.node_id)}}}a(D,"handleCreateRequest");function k(e,t){const n=e.query.getAll(t);if(n.length>1)throw h(`${t} must appear at most once`);return n[0]}a(k,"singleQueryValue");function ge(e,t){if(e!==void 0){if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;throw h(`${t} must be true or false`)}}a(ge,"optionalBoolean");function L(e,t,n){if(e!==void 0){if(n.includes(e))return e;throw h(`${t} must be one of: ${n.join(", ")}`)}}a(L,"oneOf");function wt(e){const t=new Set(["status","lifecycle","kind","mode","profile_id","profile_prefix","parent","top_level","under","hanging","include"]);for(const[b]of e.query)if(!t.has(b))throw h(`unknown nodes query parameter: ${b}`);const n=L(k(e,"status"),"status",["active","idle","done","dead","canceled"]),r=L(k(e,"lifecycle"),"lifecycle",["terminal","resident"]),o=k(e,"kind"),s=L(k(e,"mode"),"mode",["base","orchestrator"]),d=k(e,"profile_id"),c=k(e,"profile_prefix"),i=k(e,"parent"),l=ge(k(e,"top_level"),"top_level"),u=k(e,"under"),p=ge(k(e,"hanging"),"hanging"),f=L(k(e,"include"),"include",["activity"]);if(i!==void 0&&l===!0)throw h("parent and top_level=true cannot be combined");return{...n!==void 0?{status:n}:{},...r!==void 0?{lifecycle:r}:{},...o!==void 0?{kind:o}:{},...s!==void 0?{mode:s}:{},...d!==void 0?{profile_id:d}:{},...c!==void 0?{profile_prefix:c}:{},...i!==void 0?{parent:i}:{},...l!==void 0?{top_level:l}:{},...u!==void 0?{under:u}:{},...p!==void 0?{hanging:p}:{},...f!==void 0?{include:f}:{}}}a(wt,"parseListQuery");function yt(e){const t=wt(e);let n=t.status!==void 0?re({status:t.status}):re();if(e.principal.class!=="person"&&(n=n.filter(d=>me(e.principal,d.grantee??"app:terminal",d.node_id))),t.lifecycle!==void 0&&(n=n.filter(d=>d.lifecycle===t.lifecycle)),t.kind!==void 0&&(n=n.filter(d=>d.kind===t.kind)),t.mode!==void 0&&(n=n.filter(d=>d.mode===t.mode)),t.profile_id!==void 0&&(n=n.filter(d=>d.profile_id===t.profile_id)),t.profile_prefix!==void 0&&(n=n.filter(d=>d.profile_id?.startsWith(t.profile_prefix))),t.parent!==void 0&&(n=n.filter(d=>d.parent===t.parent)),t.top_level===!0&&(n=n.filter(d=>d.parent===null)),t.under!==void 0){const d=new Set(Ke(t.under));n=n.filter(c=>d.has(c.node_id))}t.hanging===!0&&(n=n.filter(d=>d.parent!==null&&R(d.parent)===null));const r=t.include==="activity"?He(n.map(d=>d.node_id)):null,o=n.length>0?Oe():new Set;return{status:200,body:n.map(d=>{const c=zn(d,d.profile_id!==null&&o.has(d.profile_id));if(r!==null){const i=fe(d.node_id);c.activity={latest_report:i[0]??null,final_report:d.final_report===null?null:i.find(l=>l.name===d.final_report)??null,pending_human_count:r[d.node_id]??0}}return c})}}a(yt,"handleList");async function _t(e){const t=e.params.id,n=await Yn(e,t,{method:"GET",path:`/v1/nodes/${encodeURIComponent(t)}`,query:Hn(e)});if(n.kind==="unknown")throw Xn(t,n.unreachable);if(n.kind==="remote"){if(n.status>=400)throw Qn(n.status,n.body);return{status:n.status,body:Zn(n.body,n.machine)}}return y(t),{status:200,body:g(t)}}a(_t,"handleDetail");async function gt(e){const t=e.params.id;y(t);const n=await dn(t);return{status:200,body:{node_id:t,snapshot:{messages:n.snapshot.messages,...n.snapshot.messageIds===void 0?{}:{messageIds:n.snapshot.messageIds},messageVisibility:n.snapshot.messageVisibility,turnVisibility:n.snapshot.turnVisibility,stats:n.snapshot.stats,state:n.snapshot.state,display:n.snapshot.display,...n.snapshot.queued===void 0?{}:{queued:n.snapshot.queued},...n.snapshot.toolGroupSummaries===void 0?{}:{toolGroupSummaries:n.snapshot.toolGroupSummaries},...n.snapshot.turnReplies===void 0?{}:{turnReplies:n.snapshot.turnReplies},...n.snapshot.workingActivity===void 0?{}:{workingActivity:n.snapshot.workingActivity}},commands:n.commands.map(o=>({name:o.name,description:o.description,source:o.source})),captured_at:B()}}}a(gt,"handleSnapshot");async function bt(e){const t=e.params.id,n=an(t);if(n===null)throw P(`unknown node: ${t}`,{received:t});return{status:200,body:n}}a(bt,"handleSubject");function vt(e){for(const[s]of e.query)if(s!=="cursor"&&s!=="limit")throw h(`unknown messages query parameter: ${s}`);const t=e.query.getAll("cursor"),n=e.query.getAll("limit");if(t.length>1)throw h("cursor must appear at most once");if(n.length>1)throw h("limit must appear at most once");if(n.length===0)return t.length===0?{}:{cursor:t[0]};const r=n[0],o=Number(r);if(!Number.isSafeInteger(o)||r==="")throw h("limit must be an integer from 1 through 500");return t.length===0?{limit:o}:{cursor:t[0],limit:o}}a(vt,"parseMessagesQuery");async function kt(e){const t=e.params.id,n=await on(t,vt(e));return{status:200,body:{node_id:t,messages:n.messages,...n.messageIds===void 0?{}:{message_ids:n.messageIds},message_visibility:n.messageVisibility,next_cursor:n.nextCursor,captured_at:B()}}}a(kt,"handleMessages");function St(e){const t=e.params.id;y(t);const n=rn(t);return{status:200,body:{node_id:t,session_file:n.sessionFile,session_jsonl:n.sessionJsonl,system_prompt:n.systemPrompt,captured_at:B()}}}a(St,"handleSession");async function Rt(e){const t=e.params.id;return y(t),{status:200,body:{node_id:t,markdown:await sn(t)}}}a(Rt,"handleTranscript");function It(e){const t=e.params.id;y(t);const n=a((o,s)=>({node_id:o,label:R(o)?.name??o,dir:de(o),self:s,files:dt(o)}),"root"),r=[n(t,!0),...ie(t).map(o=>n(o.node_id,!1))].filter(o=>Ot(o.node_id,o.dir)||o.files>0);return{status:200,body:{node_id:t,roots:r}}}a(It,"handleContext");function Ot(e,t){try{return qe(W(e),t)}catch(n){if(nn(n))return!1;throw n}}a(Ot,"hasDir");async function $t(e){const t=y(e.params.id),n=e.principal.class==="broker"?e.principal.scopes:e.ceiling,r=n===null?void 0:t.scopes==null?[...n]:[...new Set([...t.scopes.filter(s=>O(n,s)),...n.filter(s=>O(t.scopes,s))])],o=await Te(t.node_id,r,e.principal.class==="broker"?e.principal.node:void 0);return{status:201,body:g(o.node.node_id)}}a($t,"handleFork");const At=1e4;async function Ct(e){const t=e.params.id;y(t);const n=e.body,r=n?.resume??!0,o=n?.reopen??!1;mn(t,o);const s=!r&&n?.cron_id!==void 0?ue(n.cron_id):null,d=await Ne(t,{resume:r,capacity:"refuse",...s!==null?{wakeReason:xn(s,"schedule_revive")}:{}});d.outcome!=="already-live"&&Ge(t,{failures:0,notBefore:null});const c=R(t)?.status??"active",i=(d.launch??E().get(t)?.handle)?.exited,l=d.outcome!=="frozen"&&await ae(t,i,At);return{status:200,body:Jn(t,d,c,l)}}a(Ct,"handleRevive");async function Nt(e){const t=e.params.id;return{status:200,body:{newNodeId:(await pn(t))?.newNodeId??null}}}a(Nt,"handleRelaunchRoot");function Tt(e){const t=e.params.id;y(t);const n=e.body;if(n?.caller_pid!==void 0&&(!Number.isInteger(n.caller_pid)||n.caller_pid<=0))throw h("caller_pid must be a positive integer when provided");const r=Kn(),o=Ce(t,{rootEvent:n?.finish===!0?"finish":"cancel",callerPid:n?.caller_pid,...e.principal.class==="broker"?{closer:e.principal.node}:{},...r===null?{}:{registerDetached:r.registerDetached}});return{status:200,body:Vn(o)}}a(Tt,"handleClose");async function Et(e){const t=e.params.id;y(t);const n=await un(t);return{status:200,body:{recycled:n.recycled,finalized:n.finalized,new_root:n.newRoot,delivered:n.delivered}}}a(Et,"handleRecycle");async function Pt(e){const t=e.params.id;return y(t),await V(t,{lifecycle:"terminal"}),A(e,t,["lifecycle"]),{status:200,body:g(t)}}a(Pt,"handleDemote");async function Dt(e,t={}){const n=e.params.id,r=y(n),o=e.body??{};o.kind!==void 0&&await z(o.kind,r.cwd,r.profile_id??null),o.model!==void 0&&await ye(r,{kind:o.kind??r.kind,mode:"orchestrator",lifecycle:o.resident===!0?"resident":r.lifecycle,model:o.model},t.modelRegistry);const s=await cn(n,{...o.kind!==void 0?{kind:o.kind}:{},...o.resident===!0?{resident:!0}:{},...o.model!==void 0?{model:o.model}:{}});A(e,n,["mode",...o.kind!==void 0?["kind"]:[],...o.resident===!0?["lifecycle"]:[],...o.model!==void 0?["model"]:[]]);const d=J(s.meta,Y(n));return d.roadmap_written=s.roadmapWritten,d.roadmap_ref=s.roadmapRef,d.goal_path=s.goalPath,{status:200,body:d}}a(Dt,"handlePromote");async function Lt(e,t={}){const n=e.params.id,r=y(n),o=e.body??{};o.kind!==void 0&&await z(o.kind,r.cwd,r.profile_id??null),o.model!==void 0&&await ye(r,{kind:o.kind??r.kind,mode:o.promote===!0?"orchestrator":r.mode,lifecycle:r.lifecycle,model:o.model},t.modelRegistry);const s=o.note??"Refresh: continue against your roadmap or goal.";hn(n,s);const d=await fn(n,{...o.promote===!0?{promote:!0}:{},...o.kind!==void 0?{kind:o.kind}:{},...o.model!==void 0?{model:o.model}:{}});return{status:200,body:J(d.meta,Y(n))}}a(Lt,"handleYield");function Mt(e){const t=e.params.id;y(t);const n=e.body;if(n===void 0||typeof n.controller!="string"||n.controller.trim()==="")throw h("a wait requires a controller node id");const r=R(n.controller);if(r===null)throw P(`unknown controller: ${n.controller}`,{received:n.controller});if(r.status!=="active"&&r.status!=="idle")throw new m(422,"unprocessable",`controller ${n.controller} is ${r.status}`);return xe(t,n.controller),{status:200,body:g(t)}}a(Mt,"handleWait");async function jt(e){const t=e.principal,n=await ln(t.class==="broker"?o=>o.grantee===t.app&&U(t,o.node_id,o.grantee):void 0);return{status:200,body:{revived:[...n.revived],failed:[...n.failed],frozen:[...n.frozen]}}}a(jt,"handleReviveAll");const Ft=new Set(["interrupt","steer","after-turn","next-turn"]);function Gt(e){if(e===null)return null;const t=a(r=>{throw new w({error:"invalid_listen",message:r,received:e,field:"listen",next:'Send an object mapping levels "1".."10" to interrupt|steer|after-turn|next-turn (e.g. {"3":"next-turn"}), or null to reset to the global default.'})},"bad");if(typeof e!="object"||Array.isArray(e))return t("listen must be an object or null");const n=Object.entries(e);if(n.length===0)return t("listen must name at least one level");for(const[r,o]of n)/^(?:[1-9]|10)$/.test(r)||t(`listen level must be 1..10: ${r}`),(typeof o!="string"||!Ft.has(o))&&t(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(o)}`);return JSON.stringify(Object.fromEntries(n))}a(Gt,"listenJson");function A(e,t,n,r){n.length===0&&r===void 0||K(o=>{if(r?.(o),n.length===0)return;const s=We(o,t),d=Je(o,e),c=d.class==="person"?d.person:d.class==="app"?d.app:d.node;Ve(o,c,s),ze(o,{event:"configured",object:s,actor:c,attrs:{changed:n.join(",")}})})}a(A,"recordConfigured");function be(e){const t=E().get(e);if(t===void 0)return!1;try{return process.kill(t.pid,"SIGTERM"),!0}catch{return!1}}a(be,"restartLiveBroker");function ve(e,t){try{return Z(e)===Z(t)}catch{return!1}}a(ve,"sameDirectory");async function Bt(e,t={}){const n=e.params.id,r=e.body;let o;if(r===void 0)o={};else if(typeof r=="object"&&r!==null&&!Array.isArray(r))o=r;else throw new w({error:"cwd_invalid",message:"cwd repair requires a non-null object with a non-empty cwd string",received:r,field:"cwd",next:"Send a config patch with a non-empty absolute cwd string."});if(o.profile!==void 0){if(typeof o.profile!="string"||o.profile==="")throw new w({error:"profile_invalid",message:"profile must be a non-empty profile id or name",received:o.profile,field:"profile",next:"Send a profile id or exact name."});if(Object.keys(o).some(p=>p!=="profile"&&p!=="restart"&&o[p]!==void 0))throw new w({error:"profile_not_exclusive",message:"profile can only be combined with restart",field:"profile",next:"Send profile (and optionally restart) alone."});const i=y(n),l=Fn(e,o.profile);Gn(l.profileId);const u=Bn(l.profileId).manifest.grantee??"app:terminal";if(u!==(i.grantee??"app:terminal"))throw new w({error:"profile_grantee_mismatch",message:`profile ${l.profileId} belongs to ${u}, node ${n} to ${i.grantee}`,received:o.profile,field:"profile",next:"Pick a profile owned by the same app as the node."});return(i.profile_id??null)!==l.profileId&&(Ln(i.kind)?(await z(i.kind,i.cwd,l.profileId),await V(n,{profileId:l.profileId})):C(n,{profile_id:l.profileId}),A(e,n,["profile"])),o.restart===!0&&be(n),{status:200,body:g(n)}}if(Object.prototype.hasOwnProperty.call(o,"cwd")){const i=o.cwd;if(typeof i!="string"||i==="")throw new w({error:"cwd_invalid",message:"cwd must be a non-empty string",received:i,field:"cwd",next:"Send a non-empty absolute cwd string."});if(Object.keys(o).some(f=>f!=="cwd"&&f!=="keep_session"&&f!=="restart"&&o[f]!==void 0))throw new w({error:"cwd_not_exclusive",message:"cwd repair cannot be combined with another config field",received:o,field:"cwd",next:"Send cwd as the only config field."});const l=y(n),u=N(l.cwd);if(o.keep_session===!0||u&&G(i)&&N(i)&&ve(l.cwd,i)){if(!G(i))throw new w({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${i}`,received:i,field:"cwd",next:"Send an absolute path."});const f=T(i);let b=!1;try{b=q(f).isDirectory()}catch{}if(!b)throw new w({error:"cwd_missing",message:`cwd is not an existing directory: ${f}`,received:i,field:"cwd",next:"Send an existing absolute directory."});if(u&&!ve(l.cwd,f))throw new w({error:"cwd_not_same_directory",message:`${f} is not the same directory as the recorded ${l.cwd}; --keep-session only relocates an alias`,received:i,field:"cwd",next:"Drop --keep-session to repair a gone cwd, or pass the real path of the recorded directory."});if(l.managed_worktree?.state==="open")throw new w({error:"cwd_node_managed_worktree_open",message:`${n} owns an open managed worktree and cannot relocate its cwd`,received:i,field:"cwd",next:"Reconcile the managed worktree first."});const v=l.cwd;return v!==f&&(K(_=>{C(n,{cwd:f}),X(_,"UPDATE crons SET cwd = ? WHERE anchor_node = ? AND cwd = ?").run(f,n,v),Ue(n,v,f)}),A(e,n,["cwd"])),o.restart===!0&&be(n),{status:200,body:g(n)}}if(E().has(n)){const f=`${n} cannot repair its cwd while its broker is live`;throw new m(409,"cwd_node_live",f,{error:"cwd_node_live",message:f,received:i,field:"cwd",next:"Let the node become dormant, then retry the cwd repair."})}if(l.fork_from!=null)throw new w({error:"cwd_node_forked",message:`${n} is a fork and cannot repair its cwd; recorded cwd: ${l.cwd}`,received:i,field:"cwd",next:`Restore ${l.cwd}, then revive the fork normally.`});if(l.managed_worktree?.state==="open")throw new w({error:"cwd_node_managed_worktree_open",message:`${n} owns an open managed worktree and cannot repair its cwd`,received:i,field:"cwd",next:"Restore or reconcile the recorded checkout, then use the managed-worktree close or abandon flow."});if(N(l.cwd))throw new w({error:"cwd_still_present",message:`${n} recorded cwd still exists: ${l.cwd}; cwd repair is not a relocation command`,received:i,field:"cwd",next:"This command only repairs a node whose recorded cwd is gone."});if(!G(i))throw new w({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${i}`,received:i,field:"cwd",next:"Send an absolute path."});const p=T(i);if(!N(p))throw new w({error:"cwd_missing",message:`cwd does not exist: ${p}`,received:i,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."});try{if(!q(p).isDirectory())throw new w({error:"cwd_not_a_directory",message:`cwd is not a directory: ${p}`,received:i,field:"cwd",next:"Send an existing absolute directory."})}catch(f){throw f instanceof w?f:new w({error:"cwd_missing",message:`cwd does not exist: ${p}`,received:i,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."})}return K(()=>{C(n,{cwd:p}),Ye(n)}),A(e,n,["cwd"]),{status:200,body:g(n)}}let s=y(n);const d=o.listen===void 0?void 0:Gt(o.listen);if(o.scopes!==void 0){const i=pe(o.scopes),l=s.grantee==="app:terminal"?nt():s.grant_id?et(s.grant_id):null,u=s.grantee==="app:terminal"&&!rt("user").runtime?.issuer;if(!i.every(p=>O(s.scopes,p)&&(l?O(l.resolved,p):u)))throw new w({error:"unknown_scope",message:"scopes may only narrow the node's current effective set",received:i,field:"scopes",next:"Send only scopes the node currently holds."});if(i.includes("crtr:act")&&!O(i,"crtr:llm"))throw new m(400,"invalid_scope","crtr:act requires crtr:llm");s=C(n,{scopes:i})}if(o.situational_context!==void 0&&$e(n,Ae(o.situational_context)),o.model!==void 0){const i=(await se(s.cwd,s.profile_id??null)).modelLadders,l=vn(o.model,i),u=tt(s.grant_id,o.model,l===void 0),p=u?{family:ot,strength:u.strength}:l,f=u?u.model:kn(o.model,i);await x({kind:"concrete",spec:f},{cwd:s.cwd,profileId:s.profile_id??null},t.modelRegistry);const b=E();let v=!1;if(b.isClaimed(n)&&await ae(n,b.get(n)?.handle.exited)&&(v=await In(n,f,p).then(()=>!0,_=>{if(_ instanceof On)return!1;throw _})),!v){if(b.isClaimed(n)){const _=`${n}'s broker did not accept the model switch; the model was not changed`;throw new m(409,"broker_not_ready",_,{error:"broker_not_ready",message:_,received:o.model,field:"model",next:"Check the node with `crtr node show`, then retry the model change."})}if(!f.includes("/"))throw h(`model must resolve to a provider/id spec: ${o.model}`);Rn(n,f,p)}s=y(n)}if(o.kind!==void 0||o.mode!==void 0||o.lifecycle!==void 0){o.kind!==void 0&&await Se(o.kind);const i=o.kind??s.kind,l=o.mode??s.mode,u=o.lifecycle??s.lifecycle;let p;l==="orchestrator"&&!_n(n)&&(p=a(()=>{const f=wn(n);yn(n,f!==null&&f.trim()!==""?{goal:f.trim()}:{})},"beforePersist")),s=await V(n,{...o.kind!==void 0?{kind:i}:{},...o.mode!==void 0?{mode:l}:{},...o.lifecycle!==void 0?{lifecycle:u}:{}},p)}o.name!==void 0&&(s=C(n,{name:o.name}),s.window&&gn(s.window,jn(s)));const c=["scopes","situational_context","model","kind","mode","lifecycle","name","listen"].filter(i=>o[i]!==void 0);return A(e,n,c,d===void 0?void 0:i=>{X(i,"UPDATE objects SET listen_json = ? WHERE id = ? AND type = 'node'").run(d,n)}),{status:200,body:g(n)}}a(Bt,"handleConfig");async function ke(){return(await se(process.cwd(),Ie()||null)).kinds}a(ke,"daemonKinds");async function Se(e){const t=Object.keys(await ke());if(!t.includes(e))throw h(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${t.sort().join(", ")}.`})}a(Se,"assertKindServer");async function xt(){const e=await ke();return{status:200,body:{kinds:Object.keys(e).sort().map(n=>({kind:n,when_to_use:e[n]?.whenToUse??null,available_to:e[n]?.availableTo??null}))}}}a(xt,"handleListKinds");const dr=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:mt},{method:"GET",pattern:"/v1/nodes",handler:yt},{method:"GET",pattern:"/v1/kinds",handler:a(()=>xt(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:jt},{method:"GET",pattern:"/v1/nodes/:id",handler:_t},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:gt},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:bt},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:kt},{method:"GET",pattern:"/v1/nodes/:id/session",handler:St},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:Rt},{method:"GET",pattern:"/v1/nodes/:id/context",handler:It},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:$t},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:Ct},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:Nt},{method:"POST",pattern:"/v1/nodes/:id/close",handler:Tt},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:Et},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:Pt},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:Dt},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Lt},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Mt},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:Bt}];export{Bt as handleConfig,mt as handleCreate,$t as handleFork,yt as handleList,Dt as handlePromote,Lt as handleYield,dr as nodeRoutes,lr as resolveCreateKind};
|
|
1
|
+
var Oe=Object.defineProperty;var a=(e,t)=>Oe(e,"name",{value:t,configurable:!0});import{prepared as Z}from"../../../core/sqlite-statements.js";import{envProfileId as Ie}from"../../../shared/env.js";import{pausedCanvasProfiles as Ae}from"../../../core/profiles/manifest.js";import{existsSync as N,realpathSync as q,statSync as ee}from"node:fs";import{isAbsolute as F,resolve as T}from"node:path";import{appendSituationalContext as $e,formatSituationalProse as Ce}from"../../../core/runtime/situational-context.js";import{closeNode as Ne}from"../../../core/runtime/close.js";import{reviveNode as Te}from"../../../core/runtime/revive.js";import{nowIso as B}from"../../../core/fs-utils.js";import{appPaidLaunch as Ee,assertLaunchModelRegistered as K,forkNode as Pe,resolveForkSource as De,spawnChildPrepared as Le}from"../../../core/runtime/spawn.js";import{forkSourceNode as Me,newNodeId as ne}from"../../../core/runtime/nodes.js";import{abandonCreateRequest as te,childrenOf as je,completeCreateRequest as oe,findCreateRequest as Ge,getNode as R,recordCreateRequestNode as Fe,reserveCreateRequest as re,reserveCreateRequestNode as Be,listNodes as ie,recordRespawnAttempt as Ke,subscribersOf as We,subscriptionsOf as de,setMessageWait as xe,updateNode as C}from"../../../core/canvas/canvas.js";import{subtreeIds as Ve}from"../../../core/canvas/nav-model.js";import{withCanvasWrite as W}from"../../../core/canvas/db.js";import{markNodeRead as ze}from"../../../core/canvas/recovery.js";import{nodeObject as Je}from"../../../core/graph/objects.js";import{recordActedOn as Ue}from"../../../core/graph/edges.js";import{publish as Ye}from"../../../core/graph/events.js";import{readerFor as He}from"../reader.js";import{relocateSessionCwd as Qe,unbindSession as Xe}from"../../../core/canvas/sessions.js";import{ticketCountsForNodes as Ze}from"../../../core/canvas/attention.js";import{isSafeNodeId as qe}from"../../../core/canvas/paths.js";import{contextDir as se,nodeAgentDir as x}from"../../../core/canvas/node-agent-paths.js";import{checkCronBirth as en}from"../../cron/authority.js";import{cronBirthPlacement as nn}from"../../cron/armed-context.js";import{existsBeneath as tn,isAbsentOrRefused as on,isBeneathRefusal as rn,readdirBeneath as dn}from"../../../core/spaces/open-beneath.js";import{readNodeMessagesPage as sn,readNodeSession as an,readNodeSnapshot as ln,transcriptMarkdown as cn}from"../../../core/runtime/node-read.js";import{assembleNodeSubject as fn}from"../../../core/substrate/subject.js";import{reviveAll as un}from"../../../core/runtime/revive-all.js";import{promoteAsync as pn,requestYieldAsync as mn,reshapeNodeAsync as V}from"../../../core/runtime/promote.js";import{recycleNode as hn}from"../../../core/runtime/recycle.js";import{relaunchRoot as wn}from"../../../core/runtime/reset.js";import{assertReopenGate as yn}from"../../../core/runtime/reopen.js";import{writeYieldMessage as _n,readGoal as gn}from"../../../core/runtime/kickoff.js";import{ensureRoadmap as bn,hasRoadmap as vn}from"../../../core/runtime/roadmap.js";import{renameWindow as kn}from"../../../core/runtime/placement.js";import{buildLaunchSpecAsync as Sn,explicitModelIntent as Rn,normalizeModel as On,readMergedLaunchConfigAsync as ae}from"../../../core/runtime/launch.js";import{modelRequestFromConfig as In}from"../../../core/model-routes.js";import{persistDormantModel as An,setModelLive as $n}from"../../../core/runtime/model-swap.js";import{waitForBrokerViewSocket as le}from"../../../core/runtime/view-socket.js";import{BrokerUnreachableError as Cn}from"../../../core/runtime/broker-request.js";import{boundFleet as E}from"../../../core/runtime/fleet.js";import{admitLegacyStructuredOutput as Nn}from"../../structured-requests/sidecar.js";import{assertOutputSchemaAccepted as Tn}from"../../../core/runtime/structured-output.js";import{OUTCOME_PAYLOAD_MAX_BYTES as ce}from"../../../core/canvas/types.js";import{HUMAN_ACTION_NAME_PATTERN as En}from"../../../core/human/action-binding.js";import{resolveHumanAction as Pn}from"../../../core/human-actions.js";import{parseDurationMs as Dn}from"../../../core/wake.js";import{claimWarmNode as Ln,refillWarmPool as fe,resumeWarmClaim as Mn,warmPoolEnabled as jn}from"../../../core/runtime/warm-pool.js";import{assertLaunchKind as z,isLaunchKind as Gn,resolveLaunchTarget as Fn}from"../../../core/runtime/launch-target.js";import{fullName as Bn}from"../../../core/canvas/labels.js";import{reportsForNode as ue}from"./reports.js";import{requireUsableProfile as Kn}from"./profiles.js";import{assertProfileActive as Wn,loadExactProfileManifest as xn}from"../../../core/profiles/manifest.js";import{getCron as pe}from"../../../core/canvas/crons.js";import{cronWakeOrigin as Vn}from"../../../core/runtime/bearings.js";import{boundDaemonControl as zn}from"../../control.js";import{notFound as P,usage as h}from"../../../core/errors.js";import{assertScope as Jn,validateScopes as me}from"../../../core/scopes.js";import{scopeAllowed as I}from"../../../shared/env.js";import{toCloseResultDTO as Un,toNodeDetailDTO as J,toNodeSummaryDTO as Yn,toReviveResultDTO as Hn}from"../map.js";import{ApiError as u}from"../../../api/index.js";import{InputError as y}from"../../../core/io.js";import{actsAsPerson as Qn,brokerMayReach as U,canReadNode as he,resolvedScopes as Xn}from"../router.js";import{forwardVerb as Zn,queryWithoutMachine as qn,relayError as et,unknownError as nt,withMachine as tt}from"../../peer/forward.js";import{fileRoot as ot}from"../../../core/spaces/file-root.js";import{activeGrant as rt,payerOfGrant as it,terminalGrant as dt}from"../../../core/grants/mirror.js";import{appRungForGrant as st}from"../../../core/llm/app-rungs.js";import{APP_FAMILY as at}from"../../../core/model-routes.js";import{readConfig as lt}from"../../../core/config.js";import{hasConfiguredProviderCredential as ct,NO_PROVIDER_CREDENTIAL_MESSAGE as we}from"../../../core/runtime/provider-credential-gate.js";function w(e){const t=R(e);if(t===null)throw P(`unknown node: ${e}`,{received:e});return t}a(w,"requireMeta");function Y(e){return{subscribesTo:de(e),subscribers:We(e),children:je(e)}}a(Y,"edgesFor");function g(e){const t=w(e);return J(t,Y(e))}a(g,"detailOf");function ft(e){let t=ue(e).length;try{t+=dn(x(e),se(e)).length}catch(n){if(!on(n))throw n}return t}a(ft,"countFiles");function ut(e){if(typeof e!="object"||e===null)throw h("a node create requires a JSON body");const t=e;if(t.kind!==void 0&&(typeof t.kind!="string"||t.kind.trim()===""))throw h("kind must be a non-empty string when provided");if(t.description!==void 0&&(typeof t.description!="string"||t.description.trim()===""))throw h("description must be a non-empty string when provided");if(t.creator!==void 0&&(typeof t.creator!="string"||t.creator.trim()===""))throw h("creator must be a non-empty node id when provided");if(t.scopes!==void 0&&me(t.scopes),t.isolated!==void 0&&typeof t.isolated!="boolean")throw new u(400,"invalid_request","isolated must be a boolean",{param:"isolated"});const n=t.root_lifecycle;if(n!==void 0&&n!=="resident"&&n!=="terminal")throw h("root_lifecycle must be 'resident' or 'terminal'");if(t.request_key!==void 0&&(typeof t.request_key!="string"||t.request_key.trim()===""||t.request_key.length>128))throw h("request_key must be a non-empty string of at most 128 characters when provided");return t}a(ut,"parseCreateBody");function pt(e){if(e===void 0)return;const t=Dn(e),n=t===null?null:new Date(Date.now()+t);if(t===null||!Number.isFinite(t)||t<=0||n===null||!Number.isFinite(n.getTime()))throw new u(422,"invalid_deadline","`deadline` must be a positive representable duration");return n.toISOString()}a(pt,"parseDeadline");function mt(e){if(e!==void 0){if(typeof e!="object"||e===null||Array.isArray(e))throw new u(400,"invalid_request","`outcome_delivery` must be an object");if(typeof e.action!="string"||!En.test(e.action))throw new u(400,"invalid_request","`outcome_delivery.action` must be a declared action name");if(e.payload!==void 0){let t;try{t=JSON.stringify(e.payload)}catch{throw new u(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable")}if(t===void 0)throw new u(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable");if(Buffer.byteLength(t,"utf8")>ce)throw new u(413,"payload_too_large",`serialized payload exceeds ${ce} bytes`)}return e}}a(mt,"parseOutcomeDelivery");function ht(e,t){const n=Pn(e.action,t);if(!("kind"in n))return{actionName:e.action,argv:n.argv,cwd:n.cwd,configOrigin:n.configOrigin,...e.payload===void 0?{}:{payload:e.payload}};throw n.kind==="unknown_action"?new u(422,"unknown_action",`no action named ${e.action} is declared from ${t}`):new u(422,"invalid_action",`${e.action} is declared in ${n.configOrigin} but unusable: ${n.reason}`,{reason:n.reason,configOrigin:n.configOrigin})}a(ht,"resolveOutcomeDelivery");function wt(e,t,n){const r={kind:e.kind,cwd:n,prompt:e.prompt??""};return e.mode!==void 0&&(r.mode=e.mode),e.name!==void 0&&(r.name=e.name),e.description!==void 0&&(r.description=e.description),t!==void 0&&(r.parent=t),e.creator!==void 0&&(r.creator=e.creator),e.scopes!==void 0&&(r.scopes=e.scopes),e.isolated!==void 0&&(r.isolated=e.isolated),e.root===!0&&(r.root=!0),e.root_lifecycle!==void 0&&(r.rootLifecycle=e.root_lifecycle),(e.worktree===!0||typeof e.worktree=="string")&&(r.worktree=!0),typeof e.worktree=="string"&&(r.worktreeBase=e.worktree),e.worktree!==void 0&&(r.worktreeCwd=T(e.pin_cwd??e.cwd??n)),e.fork_from!==void 0&&(r.forkFrom=e.fork_from),e.model!==void 0&&(r.model=e.model),e.profile!==void 0&&(r.profile=e.profile),e.situational_context!==void 0&&(r.situationalContext=e.situational_context),e.node_id!==void 0&&(r.nodeId=e.node_id),r}a(wt,"buildRecipe");function yt(e,t,n){return!jn()||e.prefer_warm!==!0||e.root!==!0||e.parent!=null||e.root_lifecycle==="terminal"||(e.prompt??"")!==""||e.model!==void 0||e.fork_from!==void 0||e.worktree!==void 0||e.node_id!==void 0||e.scopes!==void 0||e.isolated!==void 0?null:{kind:e.kind,mode:e.mode??"base",cwd:t,profileId:n,model:e.model??null,situationalContext:e.situational_context??null,name:e.name??null,creator:e.creator??null}}a(yt,"warmRequestFor");import{resolveCreateKind as wr}from"../../../core/runtime/launch-target.js";function ye(e){const t=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return In(e.model,t,e.modelExact===!0)}a(ye,"requestFromLaunch");function _t(e,t){if(t===null)return e;if(e.scopes===void 0)return{...e,scopes:[...t]};const n=e.scopes.filter(r=>!I(t,r));if(n.length===0)return e;throw new u(403,"scope_denied",`scopes exceed the bearer token's ceiling: ${n.join(", ")}`,{scopes:n,ceiling:t})}a(_t,"withinCeiling");async function _e(e,t,n){const r=(await Sn(t.kind,t.mode,{lifecycle:t.lifecycle,hasManager:e.parent!==null,model:t.model,modelOverride:!0,cwd:e.cwd,profileId:e.profile_id??null})).launch;await K(ye(r),{cwd:e.cwd,profileId:e.profile_id??null},n)}a(_e,"assertNodeModelChangeRegistered");function ge(e,t){const n=e.principal;if(n.class!=="broker"&&n.class!=="cron")return;const r=ot({app:n.app,resolved:Xn(n),launched:n.scopes},t,"read");if("root"in r)return;const o="missing"in r?r.missing:null;throw new u(403,"scope_missing",o?`the child's directory ${t} needs missing scope ${o}`:`no permission of this run names the child's directory ${t}`,void 0,void 0,o?{scope:o}:void 0)}a(ge,"assertCallerReaches");const H=new Map;async function gt(e,t={},n={}){const r=_t(ut(e.body),e.ceiling);if(e.principal.class==="broker"){const c=e.principal;if(r.prefer_warm===!0&&c.app!=="app:terminal"&&(r.prefer_warm=!1),r.parent!=null){const i=w(r.parent);if(i.grantee!==c.app)throw new u(403,"other_app_run","cannot create a child under another app's node");if(!U(c,r.parent,i.grantee??"app:terminal"))throw P(`unknown node: ${r.parent}`,{received:r.parent})}if(r.creator!==void 0&&r.creator!==c.node)throw new u(403,"other_app_run","cannot create for another node");if(r.fork_from!==void 0){let i=null;try{i=Me(De(r.fork_from))}catch{}if(i?.grantee!==c.app||!U(c,i.node_id,i.grantee))throw new u(403,"other_app_run","cannot fork another app's conversation")}r.creator=c.node}if(e.principal.class==="cron"){const c=e.principal;for(const l of["parent","creator","fork_from","node_id"])if(r[l]!=null)throw new u(403,"permission_error",`a cron cannot set ${l} on a node it starts`);r.prefer_warm=!1;const i=en({grantee:c.app,sub:c.sub,grant_id:c.grant,scopes:c.scopes});if(!i.allowed)throw new u(i.reason==="scope_missing"?403:401,i.reason==="scope_missing"?"scope_missing":"grant_revoked",i.message);if(r.scopes!==void 0){const l=r.scopes.find(p=>!I(i.effectiveScopes,p)||!I(c.scopes,p));if(l!==void 0)throw new u(403,"scope_missing",`scope ${l} is not held by this cron`,void 0,void 0,{scope:l})}else c.scopes!==null&&(r.scopes=[...c.scopes]);r.node_id=ne(),c.isolated&&(r.isolated=!0,r.cwd=x(r.node_id,c.app))}r.creator!==void 0&&Jn(w(r.creator),"crtr:act");const o=r.request_key?.trim();if(o===void 0||r.node_id!==void 0&&qe(r.node_id)&&R(r.node_id)!==null&&Ge(o)?.nodeId!==r.node_id)return D(e,r,t,n);const s=H.get(o);if(s!==void 0)return s;const d=bt(e,r,o,t,n);H.set(o,d);try{return await d}finally{H.delete(o)}}a(gt,"handleCreate");async function bt(e,t,n,r,o){const s=re(n);if(s.nodeId!==null&&R(s.nodeId)!==null){if(s.state!=="warm_claimed"){const d=R(s.nodeId);if(e.principal.class!=="person"&&!he(e.principal,d.grantee??"app:terminal",s.nodeId))throw new u(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:g(s.nodeId)}}return D(e,t,r,o,s)}try{return await D(e,t,r,o,s)}catch(d){const c=re(n);throw(c.nodeId===null||R(c.nodeId)===null)&&te(n,c.nodeId),d}}a(bt,"handleKeyedCreateRequest");async function D(e,t,n,r,o=void 0){const s=r.deadlineAt??pt(t.deadline),d=mt(t.outcome_delivery),c=e.principal.class==="cron"?nn({grantee:e.principal.app,sub:e.principal.sub,grant_id:e.principal.grant,scopes:e.principal.scopes,cron_id:e.principal.cron,origin_run_id:e.principal.origin_run,isolated:e.principal.isolated,creator:pe(e.principal.cron)?.created_by??null},t.node_id):null;c!==null&&(t.root=c.root===!0);const i=c?.parent??t.parent??void 0;if(i==null&&t.root!==!0)throw h("a node create requires a parent (or root: true for an independent root)");let l=null;if(t.output_schema!==void 0){try{l=JSON.parse(t.output_schema)}catch{throw h("output_schema must be a JSON schema string")}if(l===null||typeof l!="object"||Array.isArray(l))throw h("output_schema must be a JSON schema object");await Tn(l)}const{profileId:p,kind:m,cwd:f,launch:b}=await Fn(t,{validateKind:Re});ge(e,f),t.worktree!==void 0&&ge(e,T(t.pin_cwd??t.cwd??f));const v={...t,kind:m},_=d===void 0?void 0:ht(d,f),Q=("grant"in e.principal?e.principal.grant:null)??(i==null?null:R(i)?.grant_id??null);if(await K(ye(Ee(b,Q,t.model)),{cwd:f,profileId:p},n.modelRegistry),it(Q)!=="app"&&!await ct(p))throw new u(412,"no_provider_credential",we,{error:"no_provider_credential",message:we,next:"The person running this runtime logs a provider in with `crtr sys setup`, or stores a provider key on the profile."});let M=null;{const A=o===void 0||o.nodeId===null||o.state==="warm_claimed"?yt(v,f,p):null,j=l===null&&r.beforeBrokerLaunch===void 0?void 0:S=>{l!==null&&Nn(S,"terminal",l),r.beforeBrokerLaunch?.(S)};if(o?.state==="warm_claimed"&&o.nodeId!==null){const S=A===null?null:await Mn(A,o.nodeId,j);if(S===null)throw te(o.requestKey,o.nodeId),new u(503,"create_resume_failed",`could not resume warm claim ${o.nodeId}; retry the create`);return oe(o.requestKey,S),{status:201,body:g(S)}}if(A!==null){const S=await Ln(A,{...s===void 0?{}:{deadlineAt:s},..._===void 0?{}:{outcomeDelivery:_},...o===void 0?{}:{requestKey:o.requestKey}},j);if(S!==null)return o!==void 0&&oe(o.requestKey,S),fe(A),{status:201,body:g(S)};M=A}const G=o?.nodeId??t.node_id??(o===void 0?void 0:ne());o!==void 0&&o.nodeId===null&&Be(o.requestKey,G);const O=wt(G===void 0?v:{...v,node_id:G},i,f);c!==null&&(c.rootLifecycle!==void 0&&(O.rootLifecycle=c.rootLifecycle),c.scopes!==void 0&&v.scopes===void 0&&(O.scopes=c.scopes),c.run!==void 0&&(O.run=c.run),c.withinCreate!==void 0&&(O.withinCreate=c.withinCreate)),s!==void 0&&(O.deadlineAt=s),_!==void 0&&(O.outcomeDelivery=_),O.readiness=t.root===!0?"await":"launch";const X=await Le(O,j,()=>{M!==null&&fe(M)});return o!==void 0&&Fe(o.requestKey,X.node.node_id),{status:201,body:g(X.node.node_id)}}}a(D,"handleCreateRequest");function k(e,t){const n=e.query.getAll(t);if(n.length>1)throw h(`${t} must appear at most once`);return n[0]}a(k,"singleQueryValue");function be(e,t){if(e!==void 0){if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;throw h(`${t} must be true or false`)}}a(be,"optionalBoolean");function L(e,t,n){if(e!==void 0){if(n.includes(e))return e;throw h(`${t} must be one of: ${n.join(", ")}`)}}a(L,"oneOf");function vt(e){const t=new Set(["status","lifecycle","kind","mode","profile_id","profile_prefix","parent","top_level","under","hanging","include"]);for(const[b]of e.query)if(!t.has(b))throw h(`unknown nodes query parameter: ${b}`);const n=L(k(e,"status"),"status",["active","idle","done","dead","canceled"]),r=L(k(e,"lifecycle"),"lifecycle",["terminal","resident"]),o=k(e,"kind"),s=L(k(e,"mode"),"mode",["base","orchestrator"]),d=k(e,"profile_id"),c=k(e,"profile_prefix"),i=k(e,"parent"),l=be(k(e,"top_level"),"top_level"),p=k(e,"under"),m=be(k(e,"hanging"),"hanging"),f=L(k(e,"include"),"include",["activity"]);if(i!==void 0&&l===!0)throw h("parent and top_level=true cannot be combined");return{...n!==void 0?{status:n}:{},...r!==void 0?{lifecycle:r}:{},...o!==void 0?{kind:o}:{},...s!==void 0?{mode:s}:{},...d!==void 0?{profile_id:d}:{},...c!==void 0?{profile_prefix:c}:{},...i!==void 0?{parent:i}:{},...l!==void 0?{top_level:l}:{},...p!==void 0?{under:p}:{},...m!==void 0?{hanging:m}:{},...f!==void 0?{include:f}:{}}}a(vt,"parseListQuery");function kt(e){const t=vt(e);let n=t.status!==void 0?ie({status:t.status}):ie();if(e.principal.class!=="person"&&(n=n.filter(d=>he(e.principal,d.grantee??"app:terminal",d.node_id))),t.lifecycle!==void 0&&(n=n.filter(d=>d.lifecycle===t.lifecycle)),t.kind!==void 0&&(n=n.filter(d=>d.kind===t.kind)),t.mode!==void 0&&(n=n.filter(d=>d.mode===t.mode)),t.profile_id!==void 0&&(n=n.filter(d=>d.profile_id===t.profile_id)),t.profile_prefix!==void 0&&(n=n.filter(d=>d.profile_id?.startsWith(t.profile_prefix))),t.parent!==void 0&&(n=n.filter(d=>d.parent===t.parent)),t.top_level===!0&&(n=n.filter(d=>d.parent===null)),t.under!==void 0){const d=new Set(Ve(t.under));n=n.filter(c=>d.has(c.node_id))}t.hanging===!0&&(n=n.filter(d=>d.parent!==null&&R(d.parent)===null));const r=t.include==="activity"?Ze(n.map(d=>d.node_id)):null,o=n.length>0?Ae():new Set;return{status:200,body:n.map(d=>{const c=Yn(d,d.profile_id!==null&&o.has(d.profile_id));if(r!==null){const i=ue(d.node_id);c.activity={latest_report:i[0]??null,final_report:d.final_report===null?null:i.find(l=>l.name===d.final_report)??null,pending_human_count:r[d.node_id]??0}}return c})}}a(kt,"handleList");async function St(e){const t=e.params.id,n=await Zn(e,t,{method:"GET",path:`/v1/nodes/${encodeURIComponent(t)}`,query:qn(e)});if(n.kind==="unknown")throw nt(t,n.unreachable);if(n.kind==="remote"){if(n.status>=400)throw et(n.status,n.body);return{status:n.status,body:tt(n.body,n.machine)}}return w(t),{status:200,body:g(t)}}a(St,"handleDetail");async function Rt(e){const t=e.params.id;w(t);const n=await ln(t);return{status:200,body:{node_id:t,snapshot:{messages:n.snapshot.messages,...n.snapshot.messageIds===void 0?{}:{messageIds:n.snapshot.messageIds},messageVisibility:n.snapshot.messageVisibility,turnVisibility:n.snapshot.turnVisibility,stats:n.snapshot.stats,state:n.snapshot.state,display:n.snapshot.display,...n.snapshot.queued===void 0?{}:{queued:n.snapshot.queued},...n.snapshot.toolGroupSummaries===void 0?{}:{toolGroupSummaries:n.snapshot.toolGroupSummaries},...n.snapshot.turnReplies===void 0?{}:{turnReplies:n.snapshot.turnReplies},...n.snapshot.workingActivity===void 0?{}:{workingActivity:n.snapshot.workingActivity}},commands:n.commands.map(o=>({name:o.name,description:o.description,source:o.source})),captured_at:B()}}}a(Rt,"handleSnapshot");async function Ot(e){const t=e.params.id,n=fn(t);if(n===null)throw P(`unknown node: ${t}`,{received:t});return{status:200,body:n}}a(Ot,"handleSubject");function It(e){for(const[s]of e.query)if(s!=="cursor"&&s!=="limit")throw h(`unknown messages query parameter: ${s}`);const t=e.query.getAll("cursor"),n=e.query.getAll("limit");if(t.length>1)throw h("cursor must appear at most once");if(n.length>1)throw h("limit must appear at most once");if(n.length===0)return t.length===0?{}:{cursor:t[0]};const r=n[0],o=Number(r);if(!Number.isSafeInteger(o)||r==="")throw h("limit must be an integer from 1 through 500");return t.length===0?{limit:o}:{cursor:t[0],limit:o}}a(It,"parseMessagesQuery");async function At(e){const t=e.params.id,n=await sn(t,It(e));return{status:200,body:{node_id:t,messages:n.messages,...n.messageIds===void 0?{}:{message_ids:n.messageIds},message_visibility:n.messageVisibility,next_cursor:n.nextCursor,captured_at:B()}}}a(At,"handleMessages");function $t(e){const t=e.params.id;w(t);const n=an(t);return{status:200,body:{node_id:t,session_file:n.sessionFile,session_jsonl:n.sessionJsonl,system_prompt:n.systemPrompt,captured_at:B()}}}a($t,"handleSession");async function Ct(e){const t=e.params.id;return w(t),{status:200,body:{node_id:t,markdown:await cn(t)}}}a(Ct,"handleTranscript");function Nt(e){const t=e.params.id;w(t);const n=a((o,s)=>({node_id:o,label:R(o)?.name??o,dir:se(o),self:s,files:ft(o)}),"root"),r=[n(t,!0),...de(t).map(o=>n(o.node_id,!1))].filter(o=>Tt(o.node_id,o.dir)||o.files>0);return{status:200,body:{node_id:t,roots:r}}}a(Nt,"handleContext");function Tt(e,t){try{return tn(x(e),t)}catch(n){if(rn(n))return!1;throw n}}a(Tt,"hasDir");async function Et(e){const t=w(e.params.id),n=e.principal.class==="broker"?e.principal.scopes:e.ceiling,r=n===null?void 0:t.scopes==null?[...n]:[...new Set([...t.scopes.filter(s=>I(n,s)),...n.filter(s=>I(t.scopes,s))])],o=await Pe(t.node_id,r,e.principal.class==="broker"?e.principal.node:void 0);return{status:201,body:g(o.node.node_id)}}a(Et,"handleFork");const Pt=1e4;async function Dt(e){const t=e.params.id;w(t);const n=e.body,r=n?.resume??!0,o=n?.reopen??!1;yn(t,o);const s=!r&&n?.cron_id!==void 0?pe(n.cron_id):null,d=await Te(t,{resume:r,capacity:"refuse",...s!==null?{wakeReason:Vn(s,"schedule_revive")}:{}});d.outcome!=="already-live"&&Ke(t,{failures:0,notBefore:null});const c=R(t)?.status??"active",i=(d.launch??E().get(t)?.handle)?.exited,l=d.outcome!=="frozen"&&await le(t,i,Pt);return{status:200,body:Hn(t,d,c,l)}}a(Dt,"handleRevive");async function Lt(e){const t=e.params.id;return{status:200,body:{newNodeId:(await wn(t))?.newNodeId??null}}}a(Lt,"handleRelaunchRoot");function Mt(e){const t=e.params.id;w(t);const n=e.body;if(n?.caller_pid!==void 0&&(!Number.isInteger(n.caller_pid)||n.caller_pid<=0))throw h("caller_pid must be a positive integer when provided");const r=zn(),o=Ne(t,{rootEvent:n?.finish===!0?"finish":"cancel",callerPid:n?.caller_pid,...e.principal.class==="broker"?{closer:e.principal.node}:{},...r===null?{}:{registerDetached:r.registerDetached}});return{status:200,body:Un(o)}}a(Mt,"handleClose");function jt(e){if(!Qn(e.principal))throw new u(403,"permission_error","only the person marks a conversation read");const t=e.params.id;return w(t),ze(t),{status:204}}a(jt,"handleMarkRead");async function Gt(e){const t=e.params.id;w(t);const n=await hn(t);return{status:200,body:{recycled:n.recycled,finalized:n.finalized,new_root:n.newRoot,delivered:n.delivered}}}a(Gt,"handleRecycle");async function Ft(e){const t=e.params.id;return w(t),await V(t,{lifecycle:"terminal"}),$(e,t,["lifecycle"]),{status:200,body:g(t)}}a(Ft,"handleDemote");async function Bt(e,t={}){const n=e.params.id,r=w(n),o=e.body??{};o.kind!==void 0&&await z(o.kind,r.cwd,r.profile_id??null),o.model!==void 0&&await _e(r,{kind:o.kind??r.kind,mode:"orchestrator",lifecycle:o.resident===!0?"resident":r.lifecycle,model:o.model},t.modelRegistry);const s=await pn(n,{...o.kind!==void 0?{kind:o.kind}:{},...o.resident===!0?{resident:!0}:{},...o.model!==void 0?{model:o.model}:{}});$(e,n,["mode",...o.kind!==void 0?["kind"]:[],...o.resident===!0?["lifecycle"]:[],...o.model!==void 0?["model"]:[]]);const d=J(s.meta,Y(n));return d.roadmap_written=s.roadmapWritten,d.roadmap_ref=s.roadmapRef,d.goal_path=s.goalPath,{status:200,body:d}}a(Bt,"handlePromote");async function Kt(e,t={}){const n=e.params.id,r=w(n),o=e.body??{};o.kind!==void 0&&await z(o.kind,r.cwd,r.profile_id??null),o.model!==void 0&&await _e(r,{kind:o.kind??r.kind,mode:o.promote===!0?"orchestrator":r.mode,lifecycle:r.lifecycle,model:o.model},t.modelRegistry);const s=o.note??"Refresh: continue against your roadmap or goal.";_n(n,s);const d=await mn(n,{...o.promote===!0?{promote:!0}:{},...o.kind!==void 0?{kind:o.kind}:{},...o.model!==void 0?{model:o.model}:{}});return{status:200,body:J(d.meta,Y(n))}}a(Kt,"handleYield");function Wt(e){const t=e.params.id;w(t);const n=e.body;if(n===void 0||typeof n.controller!="string"||n.controller.trim()==="")throw h("a wait requires a controller node id");const r=R(n.controller);if(r===null)throw P(`unknown controller: ${n.controller}`,{received:n.controller});if(r.status!=="active"&&r.status!=="idle")throw new u(422,"unprocessable",`controller ${n.controller} is ${r.status}`);return xe(t,n.controller),{status:200,body:g(t)}}a(Wt,"handleWait");async function xt(e){const t=e.principal,n=await un(t.class==="broker"?o=>o.grantee===t.app&&U(t,o.node_id,o.grantee):void 0);return{status:200,body:{revived:[...n.revived],failed:[...n.failed],frozen:[...n.frozen]}}}a(xt,"handleReviveAll");const Vt=new Set(["interrupt","steer","after-turn","next-turn"]);function zt(e){if(e===null)return null;const t=a(r=>{throw new y({error:"invalid_listen",message:r,received:e,field:"listen",next:'Send an object mapping levels "1".."10" to interrupt|steer|after-turn|next-turn (e.g. {"3":"next-turn"}), or null to reset to the global default.'})},"bad");if(typeof e!="object"||Array.isArray(e))return t("listen must be an object or null");const n=Object.entries(e);if(n.length===0)return t("listen must name at least one level");for(const[r,o]of n)/^(?:[1-9]|10)$/.test(r)||t(`listen level must be 1..10: ${r}`),(typeof o!="string"||!Vt.has(o))&&t(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(o)}`);return JSON.stringify(Object.fromEntries(n))}a(zt,"listenJson");function $(e,t,n,r){n.length===0&&r===void 0||W(o=>{if(r?.(o),n.length===0)return;const s=Je(o,t),d=He(o,e),c=d.class==="person"?d.person:d.class==="app"?d.app:d.node;Ue(o,c,s),Ye(o,{event:"configured",object:s,actor:c,attrs:{changed:n.join(",")}})})}a($,"recordConfigured");function ve(e){const t=E().get(e);if(t===void 0)return!1;try{return process.kill(t.pid,"SIGTERM"),!0}catch{return!1}}a(ve,"restartLiveBroker");function ke(e,t){try{return q(e)===q(t)}catch{return!1}}a(ke,"sameDirectory");async function Jt(e,t={}){const n=e.params.id,r=e.body;let o;if(r===void 0)o={};else if(typeof r=="object"&&r!==null&&!Array.isArray(r))o=r;else throw new y({error:"cwd_invalid",message:"cwd repair requires a non-null object with a non-empty cwd string",received:r,field:"cwd",next:"Send a config patch with a non-empty absolute cwd string."});if(o.profile!==void 0){if(typeof o.profile!="string"||o.profile==="")throw new y({error:"profile_invalid",message:"profile must be a non-empty profile id or name",received:o.profile,field:"profile",next:"Send a profile id or exact name."});if(Object.keys(o).some(m=>m!=="profile"&&m!=="restart"&&o[m]!==void 0))throw new y({error:"profile_not_exclusive",message:"profile can only be combined with restart",field:"profile",next:"Send profile (and optionally restart) alone."});const i=w(n),l=Kn(e,o.profile);Wn(l.profileId);const p=xn(l.profileId).manifest.grantee??"app:terminal";if(p!==(i.grantee??"app:terminal"))throw new y({error:"profile_grantee_mismatch",message:`profile ${l.profileId} belongs to ${p}, node ${n} to ${i.grantee}`,received:o.profile,field:"profile",next:"Pick a profile owned by the same app as the node."});return(i.profile_id??null)!==l.profileId&&(Gn(i.kind)?(await z(i.kind,i.cwd,l.profileId),await V(n,{profileId:l.profileId})):C(n,{profile_id:l.profileId}),$(e,n,["profile"])),o.restart===!0&&ve(n),{status:200,body:g(n)}}if(Object.prototype.hasOwnProperty.call(o,"cwd")){const i=o.cwd;if(typeof i!="string"||i==="")throw new y({error:"cwd_invalid",message:"cwd must be a non-empty string",received:i,field:"cwd",next:"Send a non-empty absolute cwd string."});if(Object.keys(o).some(f=>f!=="cwd"&&f!=="keep_session"&&f!=="restart"&&o[f]!==void 0))throw new y({error:"cwd_not_exclusive",message:"cwd repair cannot be combined with another config field",received:o,field:"cwd",next:"Send cwd as the only config field."});const l=w(n),p=N(l.cwd);if(o.keep_session===!0||p&&F(i)&&N(i)&&ke(l.cwd,i)){if(!F(i))throw new y({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${i}`,received:i,field:"cwd",next:"Send an absolute path."});const f=T(i);let b=!1;try{b=ee(f).isDirectory()}catch{}if(!b)throw new y({error:"cwd_missing",message:`cwd is not an existing directory: ${f}`,received:i,field:"cwd",next:"Send an existing absolute directory."});if(p&&!ke(l.cwd,f))throw new y({error:"cwd_not_same_directory",message:`${f} is not the same directory as the recorded ${l.cwd}; --keep-session only relocates an alias`,received:i,field:"cwd",next:"Drop --keep-session to repair a gone cwd, or pass the real path of the recorded directory."});if(l.managed_worktree?.state==="open")throw new y({error:"cwd_node_managed_worktree_open",message:`${n} owns an open managed worktree and cannot relocate its cwd`,received:i,field:"cwd",next:"Reconcile the managed worktree first."});const v=l.cwd;return v!==f&&(W(_=>{C(n,{cwd:f}),Z(_,"UPDATE crons SET cwd = ? WHERE anchor_node = ? AND cwd = ?").run(f,n,v),Qe(n,v,f)}),$(e,n,["cwd"])),o.restart===!0&&ve(n),{status:200,body:g(n)}}if(E().has(n)){const f=`${n} cannot repair its cwd while its broker is live`;throw new u(409,"cwd_node_live",f,{error:"cwd_node_live",message:f,received:i,field:"cwd",next:"Let the node become dormant, then retry the cwd repair."})}if(l.fork_from!=null)throw new y({error:"cwd_node_forked",message:`${n} is a fork and cannot repair its cwd; recorded cwd: ${l.cwd}`,received:i,field:"cwd",next:`Restore ${l.cwd}, then revive the fork normally.`});if(l.managed_worktree?.state==="open")throw new y({error:"cwd_node_managed_worktree_open",message:`${n} owns an open managed worktree and cannot repair its cwd`,received:i,field:"cwd",next:"Restore or reconcile the recorded checkout, then use the managed-worktree close or abandon flow."});if(N(l.cwd))throw new y({error:"cwd_still_present",message:`${n} recorded cwd still exists: ${l.cwd}; cwd repair is not a relocation command`,received:i,field:"cwd",next:"This command only repairs a node whose recorded cwd is gone."});if(!F(i))throw new y({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${i}`,received:i,field:"cwd",next:"Send an absolute path."});const m=T(i);if(!N(m))throw new y({error:"cwd_missing",message:`cwd does not exist: ${m}`,received:i,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."});try{if(!ee(m).isDirectory())throw new y({error:"cwd_not_a_directory",message:`cwd is not a directory: ${m}`,received:i,field:"cwd",next:"Send an existing absolute directory."})}catch(f){throw f instanceof y?f:new y({error:"cwd_missing",message:`cwd does not exist: ${m}`,received:i,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."})}return W(()=>{C(n,{cwd:m}),Xe(n)}),$(e,n,["cwd"]),{status:200,body:g(n)}}let s=w(n);const d=o.listen===void 0?void 0:zt(o.listen);if(o.scopes!==void 0){const i=me(o.scopes),l=s.grantee==="app:terminal"?dt():s.grant_id?rt(s.grant_id):null,p=s.grantee==="app:terminal"&&!lt("user").runtime?.issuer;if(!i.every(m=>I(s.scopes,m)&&(l?I(l.resolved,m):p)))throw new y({error:"unknown_scope",message:"scopes may only narrow the node's current effective set",received:i,field:"scopes",next:"Send only scopes the node currently holds."});if(i.includes("crtr:act")&&!I(i,"crtr:llm"))throw new u(400,"invalid_scope","crtr:act requires crtr:llm");s=C(n,{scopes:i})}if(o.situational_context!==void 0&&$e(n,Ce(o.situational_context)),o.model!==void 0){const i=(await ae(s.cwd,s.profile_id??null)).modelLadders,l=Rn(o.model,i),p=st(s.grant_id,o.model,l===void 0),m=p?{family:at,strength:p.strength}:l,f=p?p.model:On(o.model,i);await K({kind:"concrete",spec:f},{cwd:s.cwd,profileId:s.profile_id??null},t.modelRegistry);const b=E();let v=!1;if(b.isClaimed(n)&&await le(n,b.get(n)?.handle.exited)&&(v=await $n(n,f,m).then(()=>!0,_=>{if(_ instanceof Cn)return!1;throw _})),!v){if(b.isClaimed(n)){const _=`${n}'s broker did not accept the model switch; the model was not changed`;throw new u(409,"broker_not_ready",_,{error:"broker_not_ready",message:_,received:o.model,field:"model",next:"Check the node with `crtr node show`, then retry the model change."})}if(!f.includes("/"))throw h(`model must resolve to a provider/id spec: ${o.model}`);An(n,f,m)}s=w(n)}if(o.kind!==void 0||o.mode!==void 0||o.lifecycle!==void 0){o.kind!==void 0&&await Re(o.kind);const i=o.kind??s.kind,l=o.mode??s.mode,p=o.lifecycle??s.lifecycle;let m;l==="orchestrator"&&!vn(n)&&(m=a(()=>{const f=gn(n);bn(n,f!==null&&f.trim()!==""?{goal:f.trim()}:{})},"beforePersist")),s=await V(n,{...o.kind!==void 0?{kind:i}:{},...o.mode!==void 0?{mode:l}:{},...o.lifecycle!==void 0?{lifecycle:p}:{}},m)}o.name!==void 0&&(s=C(n,{name:o.name}),s.window&&kn(s.window,Bn(s)));const c=["scopes","situational_context","model","kind","mode","lifecycle","name","listen"].filter(i=>o[i]!==void 0);return $(e,n,c,d===void 0?void 0:i=>{Z(i,"UPDATE objects SET listen_json = ? WHERE id = ? AND type = 'node'").run(d,n)}),{status:200,body:g(n)}}a(Jt,"handleConfig");async function Se(){return(await ae(process.cwd(),Ie()||null)).kinds}a(Se,"daemonKinds");async function Re(e){const t=Object.keys(await Se());if(!t.includes(e))throw h(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${t.sort().join(", ")}.`})}a(Re,"assertKindServer");async function Ut(){const e=await Se();return{status:200,body:{kinds:Object.keys(e).sort().map(n=>({kind:n,when_to_use:e[n]?.whenToUse??null,available_to:e[n]?.availableTo??null}))}}}a(Ut,"handleListKinds");const pr=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:gt},{method:"GET",pattern:"/v1/nodes",handler:kt},{method:"GET",pattern:"/v1/kinds",handler:a(()=>Ut(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:xt},{method:"GET",pattern:"/v1/nodes/:id",handler:St},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:Rt},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:Ot},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:At},{method:"GET",pattern:"/v1/nodes/:id/session",handler:$t},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:Ct},{method:"GET",pattern:"/v1/nodes/:id/context",handler:Nt},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:Et},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:Dt},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:Lt},{method:"POST",pattern:"/v1/nodes/:id/close",handler:Mt},{method:"POST",pattern:"/v1/nodes/:id/read",handler:jt},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:Gt},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:Ft},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:Bt},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Kt},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Wt},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:Jt}];export{Jt as handleConfig,gt as handleCreate,Et as handleFork,kt as handleList,Bt as handlePromote,Kt as handleYield,pr as nodeRoutes,wr as resolveCreateKind};
|