@north-light/cli 0.3.548 → 0.3.550
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/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/api/dto/custom-objects.d.ts +1 -1
- package/dist/api/dto/docs.d.ts +12 -0
- package/dist/api/dto/objects.d.ts +17 -1
- package/dist/api/dto/objects.js +1 -1
- package/dist/api/dto/permissions.d.ts +76 -0
- package/dist/api/dto/permissions.js +1 -0
- package/dist/api/index.d.ts +3 -2
- package/dist/api/index.js +1 -1
- package/dist/api/routes.d.ts +4 -0
- package/dist/api/routes.js +1 -1
- package/dist/builtin-memory/crouter-concepts/documents.md +1 -1
- package/dist/builtin-memory/crouter-concepts/scopes-and-trust.md +2 -2
- package/dist/builtin-memory/crouter-sdk/release-notes.md +11 -0
- package/dist/builtin-memory/internal/INDEX.md +2 -1
- package/dist/builtin-memory/internal/agent-shaping.md +1 -1
- package/dist/builtin-memory/internal/storage-tiers.md +1 -1
- package/dist/builtin-memory/northlight-apps/guides/files-and-documents.md +3 -3
- package/dist/builtin-memory/northlight-apps/guides/many-users.md +1 -1
- package/dist/builtin-memory/northlight-apps/guides/test-your-app.md +1 -1
- package/dist/clients/attach/viewer.js +9 -9
- package/dist/commands/canvas/list.js +2 -2
- package/dist/commands/canvas/share.d.ts +2 -0
- package/dist/commands/canvas/share.js +2 -0
- package/dist/commands/canvas.js +1 -1
- package/dist/commands/doc/edit.js +1 -1
- package/dist/commands/doc/shared.js +1 -1
- package/dist/commands/doc/write.js +1 -1
- package/dist/commands/sys/sync-skills.js +2 -2
- package/dist/core/canvas/canvas.js +20 -20
- package/dist/core/canvas/db.js +4 -4
- package/dist/core/canvas/export-sqlite.js +2 -2
- package/dist/core/canvas/import-sqlite.js +5 -5
- package/dist/core/canvas/outcome-actions.js +3 -3
- package/dist/core/canvas/person.js +11 -9
- package/dist/core/canvas/schema-pg.sql +49 -5
- package/dist/core/environments.js +1 -1
- package/dist/core/feed/feed.js +1 -1
- package/dist/core/grants/mirror.d.ts +9 -1
- package/dist/core/grants/mirror.js +2 -2
- package/dist/core/grants/sync.js +1 -1
- package/dist/core/graph/access.d.ts +8 -49
- package/dist/core/graph/access.js +4 -7
- package/dist/core/graph/custom.d.ts +5 -2
- package/dist/core/graph/custom.js +9 -9
- package/dist/core/graph/deletion.js +5 -4
- package/dist/core/graph/documents.d.ts +12 -3
- package/dist/core/graph/documents.js +13 -7
- package/dist/core/graph/edges.js +3 -3
- package/dist/core/graph/events.js +12 -8
- package/dist/core/graph/kinds/document.js +4 -4
- package/dist/core/graph/kinds/kind.js +1 -1
- package/dist/core/graph/kinds/node.js +5 -5
- package/dist/core/graph/names.d.ts +16 -1
- package/dist/core/graph/names.js +11 -3
- package/dist/core/graph/objects.d.ts +19 -2
- package/dist/core/graph/objects.js +16 -10
- package/dist/core/graph/package-docs.js +5 -5
- package/dist/core/graph/package-files.js +2 -2
- package/dist/core/graph/reader.js +3 -3
- package/dist/core/graph/repo-sync/exchange.js +2 -2
- package/dist/core/graph/rules.d.ts +7 -5
- package/dist/core/graph/rules.js +3 -3
- package/dist/core/graph/types.d.ts +12 -1
- package/dist/core/graph/types.js +1 -1
- package/dist/core/graph/watches.d.ts +1 -1
- package/dist/core/graph/watches.js +9 -8
- package/dist/core/peer/envelope.d.ts +1 -1
- package/dist/core/peer/envelope.js +1 -1
- package/dist/core/peer/stubs.d.ts +1 -1
- package/dist/core/peer/stubs.js +1 -1
- package/dist/core/permissions/boot.d.ts +17 -0
- package/dist/core/permissions/boot.js +18 -0
- package/dist/core/permissions/builtin.d.ts +8 -0
- package/dist/core/permissions/builtin.js +20 -0
- package/dist/core/permissions/ceiling.d.ts +57 -0
- package/dist/core/permissions/ceiling.js +22 -0
- package/dist/core/permissions/compile.d.ts +14 -0
- package/dist/core/permissions/compile.js +1 -0
- package/dist/core/permissions/errors.d.ts +7 -0
- package/dist/core/permissions/errors.js +1 -0
- package/dist/core/permissions/evaluator.d.ts +28 -0
- package/dist/core/permissions/evaluator.js +6 -0
- package/dist/core/permissions/facts.d.ts +56 -0
- package/dist/core/permissions/facts.js +2 -0
- package/dist/core/permissions/schema-parser.d.ts +29 -0
- package/dist/core/permissions/schema-parser.js +2 -0
- package/dist/core/permissions/schemas.d.ts +21 -0
- package/dist/core/permissions/schemas.js +2 -0
- package/dist/core/permissions/sql.d.ts +16 -0
- package/dist/core/permissions/sql.js +1 -0
- package/dist/core/runtime/broker/frame-client.d.ts +1 -1
- package/dist/core/runtime/broker/frame-client.js +1 -1
- package/dist/core/runtime/broker/frame-dispatch.d.ts +1 -1
- package/dist/core/runtime/broker/frame-dispatch.js +1 -1
- package/dist/core/runtime/broker/frame-read.d.ts +4 -3
- package/dist/core/runtime/broker/frame-read.js +1 -1
- package/dist/core/runtime/broker-protocol.d.ts +1 -1
- package/dist/core/runtime/host.js +3 -3
- package/dist/core/runtime/placement.js +1 -1
- package/dist/core/runtime/roadmap.js +1 -1
- package/dist/core/substrate/delivery/corpus.d.ts +2 -2
- package/dist/core/substrate/delivery/corpus.js +3 -3
- package/dist/core/substrate/delivery/deliver.js +2 -2
- package/dist/core/substrate/delivery/render-event.js +6 -6
- package/dist/core/substrate/subject-fields.d.ts +2 -0
- package/dist/core/substrate/subject.js +1 -1
- package/dist/daemon/api/app-listener.js +12 -12
- package/dist/daemon/api/bridge.d.ts +1 -1
- package/dist/daemon/api/bridge.js +4 -4
- package/dist/daemon/api/handlers/attach.d.ts +4 -1
- package/dist/daemon/api/handlers/attach.js +1 -1
- package/dist/daemon/api/handlers/canvas.js +5 -5
- package/dist/daemon/api/handlers/check.d.ts +2 -0
- package/dist/daemon/api/handlers/check.js +1 -0
- package/dist/daemon/api/handlers/custom-objects.js +2 -2
- package/dist/daemon/api/handlers/docs.js +1 -1
- package/dist/daemon/api/handlers/files.js +1 -1
- package/dist/daemon/api/handlers/memory.js +7 -6
- package/dist/daemon/api/handlers/nodes.js +1 -1
- package/dist/daemon/api/handlers/objects.js +3 -3
- package/dist/daemon/api/handlers/relations.d.ts +2 -0
- package/dist/daemon/api/handlers/relations.js +1 -0
- package/dist/daemon/api/handlers/schemas.d.ts +12 -0
- package/dist/daemon/api/handlers/schemas.js +1 -0
- package/dist/daemon/api/handlers/shares.d.ts +2 -0
- package/dist/daemon/api/handlers/shares.js +1 -0
- package/dist/daemon/api/operations.js +1 -1
- package/dist/daemon/api/router.d.ts +10 -6
- package/dist/daemon/api/router.js +1 -1
- package/dist/daemon/api/server.js +1 -1
- package/dist/daemon/api/vendor-signin.js +21 -24
- package/dist/daemon/crtrd.js +12 -12
- package/dist/daemon/reconcilers/delivery-lane.js +2 -2
- package/dist/migrations/004-canvas-documents/fields.d.ts +1 -1
- package/dist/migrations/004-canvas-documents/fields.js +2 -2
- package/docs/apps/guides/files-and-documents.md +3 -3
- package/docs/apps/guides/many-users.md +1 -1
- package/docs/apps/guides/test-your-app.md +1 -1
- package/docs/cli/documents-and-preferences.md +1 -1
- package/docs/concepts/documents.md +1 -1
- package/docs/concepts/scopes-and-trust.md +2 -2
- package/docs/sdk/release-notes.md +11 -0
- package/package.json +2 -2
- package/packages/crouter-identity/dist/index.js +14 -1
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +13 -13
- package/dist/core/graph/spaces/app.d.ts +0 -3
- package/dist/core/graph/spaces/app.js +0 -1
- package/dist/core/graph/spaces/index.d.ts +0 -18
- package/dist/core/graph/spaces/index.js +0 -1
- package/dist/core/graph/spaces/own-memory.d.ts +0 -18
- package/dist/core/graph/spaces/own-memory.js +0 -1
- package/dist/core/graph/spaces/person.d.ts +0 -5
- package/dist/core/graph/spaces/person.js +0 -3
- package/dist/core/graph/spaces/repo.d.ts +0 -14
- package/dist/core/graph/spaces/repo.js +0 -1
- package/dist/core/runs/confinement.d.ts +0 -25
- package/dist/core/runs/confinement.js +0 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var
|
|
2
|
-
`);if(e.length>0){const
|
|
3
|
-
`).forEach((u,g)=>{
|
|
1
|
+
var Q=Object.defineProperty;var c=(n,e)=>Q(n,"name",{value:e,configurable:!0});import{gzipSync as Y}from"node:zlib";import{browseNodes as B,graphNodes as V,pruneNodes as X,pruneToLimit as Z,rosterEdges as N,rosterNodes as ee}from"../../../core/canvas/canvas.js";import{liveObjectWaitsNamed as te,readControllerWait as ne}from"../../../core/canvas/waits.js";import{activeBackgroundBashJobs as se}from"../../../core/bash-jobs.js";import{contextDir as oe}from"../../../core/canvas/node-agent-paths.js";import{nowIso as I}from"../../../core/fs-utils.js";import{isPidPresent as re}from"../../../core/canvas/pid.js";import{dashboardRowsAllFromSource as ie,enrichRowsFromSource as ae}from"../../../core/canvas/render-source.js";import{localCanvasSource as P}from"../../../core/canvas/source.js";import{ticketCountsForNodes as F,ticketsAcrossCanvas as de}from"../../../core/canvas/attention.js";import{buildCorpus as le,groupCorpus as ce,resolveRef as ue}from"../../../core/canvas/history.js";import{listFocuses as G,reapEmptyNodes as fe}from"../../../core/runtime/placement.js";import{boundFleet as me}from"../../../core/runtime/fleet.js";import{retentionHold as pe}from"../../reconcilers/live-obligation.js";import{notFound as _e,usage as _}from"../../../core/errors.js";import{openDb as ye}from"../../../core/canvas/db.js";import{view as he}from"../../../core/canvas/tree.js";import{isLiveStatus as be}from"../../../core/canvas/node-order.js";import{readNodeRecap as ge}from"../../../core/canvas/node-recap.js";import{readGoal as ve}from"../../../core/runtime/kickoff.js";import{faultSummary as we}from"../../../core/canvas/status-glyph.js";import{listPendingAsks as ke}from"../../../core/human/requests.js";import{toGraphNodeDTO as Se}from"../map.js";import{actsAsPerson as Ne,readableNodeIds as D}from"../router.js";import{ApiError as T}from"../../../api/errors.js";import{mapAsync as q}from"../../../core/async-array.js";async function w(n){return await D(n.principal)}c(w,"visibleNodes");async function Ce(n){const e=await w(n);return{status:200,body:{items:(await de()).filter(t=>e===null||e.has(t.node_id)).map(t=>({node_id:t.node_id,name:t.name,cwd:t.cwd,count:t.count,subjects:t.subjects}))}}}c(Ce,"handleAttention");async function Re(n){const e=n.body;if(e===null||typeof e!="object"||!Array.isArray(e.node_ids))throw _("attention count request requires node_ids: string[]");const o=e.node_ids;if(!o.every(l=>typeof l=="string"))throw _("attention count request node_ids must contain only strings");const t=await w(n);return{status:200,body:{counts:await F(o.filter(l=>t===null||t.has(l)))}}}c(Re,"handleAttentionCounts");function x(n){return Buffer.from(String(n),"utf8").toString("base64")}c(x,"encodeCursor");function H(n){const e=Number(Buffer.from(n,"base64").toString("utf8"));if(!Number.isInteger(e)||e<0)throw _(`invalid cursor: ${n}`);return e}c(H,"decodeCursor");function je(n,e,o){const a=n.loadBody().split(`
|
|
2
|
+
`);if(e.length>0){const i=a.findIndex(m=>{const f=m.toLowerCase();return e.some(y=>f.includes(y))});if(i!==-1)return a.slice(i,i+o).map(m=>m.trim()).filter(m=>m!=="").join(" \u23CE ")}const l=a.map(i=>i.trim()).filter(i=>i!=="").slice(0,o).join(" \u23CE ");return l!==""?l:n.title}c(je,"snippet");function Ie(n,e,o){const t=[...n];return e==="relevance"&&o!==void 0?t.sort((a,l)=>(o.get(l.ref)??0)-(o.get(a.ref)??0)||l.tsMs-a.tsMs||a.ref.localeCompare(l.ref)):e==="oldest"?t.sort((a,l)=>a.tsMs-l.tsMs||a.ref.localeCompare(l.ref)):t.sort((a,l)=>l.tsMs-a.tsMs||a.ref.localeCompare(l.ref)),t}c(Ie,"sortArtifacts");function Me(n){if(n==null)return{};if(typeof n!="object")throw _("history search body must be a JSON object");return n}c(Me,"parseSearchBody");function Le(n){if(n===null||typeof n!="object")throw _("history grep body must be a JSON object");const e=n;if(typeof e.pattern!="string"||e.pattern==="")throw _("history grep body requires a non-empty pattern");return e}c(Le,"parseGrepBody");async function $(n,e){const o={cwd:n.cwd,allCwds:n.all_cwds===!0,under:n.under,nodes:n.nodes},t={types:n.types,kinds:n.kinds,statuses:n.statuses,sinceMs:n.since_ms,untilMs:n.until_ms,origins:n.origins,roles:n.roles,from:n.from},a=await w(e);return(await le(o,t)).filter(l=>a===null||a.has(l.nodeId))}c($,"buildCorpusFromQuery");function Oe(n){if(n==null)return{};if(typeof n!="object")throw _("history stats body must be a JSON object");return n}c(Oe,"parseStatsBody");const z=["origin","node","kind","day","type","role"];async function Ee(n){const e=Oe(n.body),o=e.group_by??"type";if(!z.includes(o))throw _(`--group-by must be one of: ${z.join(", ")}; received: ${String(e.group_by)}`);const t=await $(e,n),a=ce(t,o);return{status:200,body:{group_by:o,groups:a,total:a.reduce((i,m)=>i+m.count,0),scanned:t.length}}}c(Ee,"handleHistoryStats");async function Te(n){const e=Le(n.body),o=Math.min(100,Math.max(1,e.limit??20)),t=await $(e,n),a=e.cursor!==void 0?H(e.cursor):0;let l;try{l=new RegExp(e.pattern,"i")}catch{throw _(`invalid regex pattern: ${e.pattern}`)}const i=[];for(const r of t)r.loadBody().split(`
|
|
3
|
+
`).forEach((u,g)=>{l.test(u)&&i.push({ref:r.ref,node:`${r.nodeName} (${r.nodeId})`,ts:r.ts,line:g+1,text:u.trim()})});i.sort((r,s)=>r.ref.localeCompare(s.ref)||r.line-s.line);const m=i.slice(a,a+o),f=a+o<i.length?x(a+o):null;return{status:200,body:{hits:m,next_cursor:f,total:i.length}}}c(Te,"handleHistoryGrep");async function $e(n){const e=Me(n.body),o=(e.query??"").trim(),t=e.weigh_body===!0,a=e.full===!0,l=Math.max(1,e.snippet_lines??1),i=Math.min(100,Math.max(1,e.limit??20)),m=e.per_node===!0;if(m&&(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=await $(e,n),y=e.cursor!==void 0?H(e.cursor):0,r=o.toLowerCase().split(/\s+/).filter(d=>d.length>0);let s=f,u;const g=e.sort??(r.length>0?"relevance":"recency");if(r.length>0&&g==="relevance"){u=new Map;const d=[];for(const p of f){const E=p.title.toLowerCase(),W=p.nodeName.toLowerCase(),U=p.nodeDesc.toLowerCase(),A=t?p.loadBody().toLowerCase():null;let S=0;for(const j of r)E.includes(j)&&(S+=10),W.includes(j)&&(S+=5),U.includes(j)&&(S+=3),A!==null&&A.includes(j)&&(S+=1);S>0&&(u.set(p.ref,S),d.push(p))}s=d}else r.length>0&&(s=f.filter(d=>{const p=`${d.title}
|
|
4
4
|
${d.nodeName}
|
|
5
|
-
${d.nodeDesc}${
|
|
6
|
-
`+d.loadBody():""}`.toLowerCase();return
|
|
5
|
+
${d.nodeDesc}${t?`
|
|
6
|
+
`+d.loadBody():""}`.toLowerCase();return r.some(E=>p.includes(E))}));let b=Ie(s,g,u);if(m){const d=new Set;b=b.filter(p=>!d.has(p.nodeId)&&d.add(p.nodeId))}const v=m?b:b.slice(y,y+i),h=!m&&y+i<b.length?x(y+i):null;return{status:200,body:{hits:v.map(d=>{const p={ref:d.ref,node:`${d.nodeName} (${d.nodeId})`,kind:d.nodeKind,source:d.source,ts:d.ts,...m?{node_id:d.nodeId}:{}};return g==="relevance"&&u!==void 0&&(p.score=u.get(d.ref)??0),a?p.body=d.loadBody():p.snippet=je(d,r,l),p}),next_cursor:h,total:b.length}}}c($e,"handleHistorySearch");async function Ae(n){const e=(n.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 o=await ue(e);if(o===null)throw _e(`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((await w(n))?.has(o.nodeId)===!1)throw new T(404,"not_found","artifact not found");const t=o.source,l=n.query.get("format")==="raw"&&o.raw!==null?o.raw:o.body;return{status:200,body:{ref:e,node:`${o.nodeName} (${o.nodeId})`,source:t,ts:o.ts,content:l}}}c(Ae,"handleHistoryRead");function Be(n){for(const[t]of n.query)if(t!=="live")throw _(`unknown snapshot query parameter: ${t}`);const e=n.query.getAll("live");if(e.length>1)throw _("live must appear at most once");const o=e[0];if(o===void 0||o==="false"||o==="0")return!1;if(o==="true"||o==="1")return!0;throw _("live must be true or false")}c(Be,"snapshotLiveOnly");async function Pe(n){const e=new Set((await G()).map(r=>r.node_id)),o=await w(n),t=(await ie(P,e,Be(n))).filter(r=>o===null||o.has(r.node_id)),a=await F(t.map(r=>r.node_id));await ae(P,t,a);const l=await q(t,async r=>{const s=r.srcRow,u=s?.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??s?.lifecycle,status:r.status,cwd:r.cwd,profile_id:r.profile_id??null,parent:s?.parent??null,created:r.created,host_kind:u,enterable:u==="broker",attention_count:r.asks,...s?.cycles!=null?{cycles:s.cycles}:{},...r.mtimeMs!==void 0?{last_activity:new Date(r.mtimeMs).toISOString()}:{},ctx_tokens:r.ctx_tokens,streaming:r.streaming??!1,jobs_active:s!==void 0&&re(s.pi_pid)?se(await oe(r.node_id)).length:0,waiting_for:(await ne(r.node_id))?.controllerId??null,hanging:r.hanging??null,viewed:r.viewed??!1,final_report:s?.final_report??null,finalized_at:s?.finalized_at??null}}),i=new Map;for(const r of await N()){const s=i.get(r.from_id);s===void 0?i.set(r.from_id,[r.to_id]):s.push(r.to_id)}const m=new Set(t.map(r=>r.node_id)),f=Object.fromEntries(t.map(r=>[r.node_id,(i.get(r.node_id)??[]).filter(s=>m.has(s))]));return{status:200,body:{generated_at:I(),nodes:l,subscriptions:f}}}c(Pe,"handleSnapshot");async function J(){const n=(await ee()).map(t=>{const a=t.host_kind??"tmux";return{node_id:t.node_id,name:t.name,kind:t.kind,mode:t.mode,lifecycle:t.lifecycle,status:t.status,cwd:t.cwd,host_kind:a,enterable:a==="broker",parent:t.parent,created:t.created,description:t.description}}),e=(await N()).map(t=>({from_id:t.from_id,to_id:t.to_id,active:t.active,created:t.created})),o=(await te()).map(t=>({node_id:t.nodeId,object_id:t.objectId,object_type:t.objectType,object_name:t.objectName,created:new Date(t.createdAt).toISOString()}));return{generated_at:I(),nodes:n,edges:e,object_waits:o}}c(J,"buildRoster");let C=null,M=null;function Fe(){return C===null?(C=Promise.resolve().then(async()=>await J()).finally(()=>{C=null}),C):(M===null&&(M=C.then(async()=>await J()).finally(()=>{M=null})),M)}c(Fe,"rosterCoalesced");async function Ge(n){const e=await Fe(),o=await w(n);return o===null?{status:200,body:e}:{status:200,body:{...e,nodes:e.nodes.filter(t=>o.has(t.node_id)),edges:e.edges.filter(t=>o.has(t.from_id)&&o.has(t.to_id)),object_waits:(e.object_waits??[]).filter(t=>o.has(t.node_id))}}}c(Ge,"handleRoster");function K(n){if(n.name!==""&&n.name!==n.kind)return n.name;const e=(n.description??"").trim();return e!==""?e:n.name}c(K,"liveRootName");const De=1440*6e4;async function qe(){const n=await B(),e=new Map(n.map(s=>[s.node_id,s])),o=new Map((await(await ye()).prepare("SELECT node_id, reply_at, read_at, intent FROM nodes WHERE parent IS NULL").all()).map(s=>[s.node_id,s])),t=await ke(),a=new Map;for(const s of t)a.set(s.requester_node_id,(a.get(s.requester_node_id)??0)+1);const l=new Date(Date.now()-De).toISOString(),i=c(s=>{const u=o.get(s.node_id);return u?.reply_at!=null&&(u.read_at==null||u.reply_at>u.read_at)||(a.get(s.node_id)??0)>0?!0:s.status!=="done"||u?.intent!=="parked"?!1:[s.created,s.telemetry_updated_at,u.reply_at].reduce((v,h)=>h!=null&&h>v?h:v,"")>=l},"keepFinished"),m=n.filter(s=>s.parent===null&&s.kind!=="human"&&(be(s.status)||i(s))),f=new Map;for(const s of await N())f.set(s.from_id,[...f.get(s.from_id)??[],s.to_id]);const y=c(s=>{const u=e.get(s)?.fault;return u&&u.link!=="broker\u2194crtrd"?we(u):null},"faultOf"),r=await q(m,async s=>{const u=[s.node_id,...await he(s.node_id)].filter(d=>e.get(d)?.kind!=="human"&&e.has(d)),g=new Set(u),b=t.filter(d=>g.has(d.requester_node_id)),v=o.get(s.node_id),h=v?.reply_at??null,O=v?.read_at??null;let k=s.created;for(const d of u){const p=e.get(d).telemetry_updated_at;p!=null&&p>k&&(k=p)}return h!==null&&h>k&&(k=h),{node_id:s.node_id,name:K(s),cwd:s.cwd,profile_id:s.profile_id,status:s.status,state_line:(()=>{const d=ge(s.node_id)?.state.trim();return d||null})(),goal:(await ve(s.node_id))?.trim()||null,asks:b.length,first_ask_ticket_id:b[0]?.inbox_ticket_id??null,fault:u.map(y).find(d=>d!==null)??null,running_count:u.filter(d=>e.get(d).streaming===!0).length,unread:h!==null&&(O===null||h>O),last_activity:k,children:(f.get(s.node_id)??[]).filter(d=>e.has(d)&&e.get(d).kind!=="human").map(d=>{const p=e.get(d);return{node_id:d,name:K(p),status:p.status,streaming:p.streaming===!0,asks:a.get(d)??0,fault:y(d)}})}});return{generated_at:I(),rows:r}}c(qe,"buildLiveRoots");let R=null,L=null;function xe(){const n=c(()=>Promise.resolve().then(qe),"run");return R===null?(R=n().finally(()=>{R=null}),R):(L===null&&(L=R.then(n).finally(()=>{L=null})),L)}c(xe,"liveRootsCoalesced");async function He(n){if(!Ne(n.principal))throw new T(403,"permission_error","only the person reads the dashboard");const e=await xe(),o=n.query.get("profile");return{status:200,body:o===null?e:{...e,rows:e.rows.filter(t=>t.profile_id===o)}}}c(He,"handleLiveRoots");async function ze(n){const e=await D(n.principal),o=(await B()).filter(i=>e===null||e.has(i.node_id)).map(i=>({node_id:i.node_id,name:i.name,description:i.description,kind:i.kind,mode:i.mode,lifecycle:i.lifecycle,status:i.status,cwd:i.cwd,profile_id:i.profile_id,grantee:i.grantee??"app:terminal",parent:i.parent,created:i.created,frozen_at:i.frozen_at??null,terminal_reason:i.terminal_reason??null,final_report:i.final_report??null,telemetry_tokens_in:i.telemetry_tokens_in??null,telemetry_updated_at:i.telemetry_updated_at??null,fault:i.fault&&i.fault.link!=="broker\u2194crtrd"?{...i.fault,link:i.fault.link}:null,streaming:i.streaming??!1})),t=new Set(o.map(i=>i.node_id)),a=(await N()).filter(i=>t.has(i.from_id)&&t.has(i.to_id));return{status:200,rawBody:Y(JSON.stringify({nodes:o,edges:a}),{level:1}),headers:{"content-type":"application/gzip"}}}c(ze,"handleBrowse");async function Je(n){const e=await w(n);return{status:200,body:{generated_at:I(),nodes:(await V()).filter(t=>e===null||e.has(t.node_id)).map(Se),edges:(await N()).filter(t=>e===null||e.has(t.from_id)&&e.has(t.to_id)).map(t=>({from_id:t.from_id,to_id:t.to_id,active:t.active,created:t.created})),focused_node_ids:(await G()).map(t=>t.node_id).filter(t=>e===null||e.has(t))}}}c(Je,"handleGraph");function Ke(n){if(n==null)return{};if(typeof n!="object")throw _("prune body must be a JSON object");const e=n,o=c(r=>{const s=e[r];if(s!==void 0){if(typeof s!="number"||!Number.isFinite(s))throw _(`${r} must be a number`);return s}},"num"),t=c(r=>{const s=e[r];if(s!==void 0){if(typeof s!="boolean")throw _(`${r} must be a boolean`);return s}},"bool"),a={},l=o("limit");l!==void 0&&(a.limit=l);const i=o("ttl_days");i!==void 0&&(a.ttl_days=i);const m=t("include_stale");m!==void 0&&(a.include_stale=m);const f=t("empty");f!==void 0&&(a.empty=f);const y=t("dry_run");return y!==void 0&&(a.dry_run=y),a}c(Ke,"parsePruneBody");async function We(n){const e=Ke(n.body),o=e.ttl_days??14,t=e.dry_run??!1,a=await pe(me());let l;return e.limit!==void 0?l=(await Z({maxNodes:e.limit,held:a,dryRun:t})).pruned.map(f=>({node_id:f.node_id,status:f.status,created:f.created})):e.empty===!0?l=(await fe({dryRun:t})).map(f=>({node_id:f,status:"empty",created:""})):l=(await X({ttlDays:o,held:a,dryRun:t,includeStale:e.include_stale??!1})).pruned.map(f=>({node_id:f.node_id,status:f.status,created:f.created})),{status:200,body:{pruned:l,dry_run:t,ttl_days:o}}}c(We,"handlePrune");const wt=[{method:"GET",pattern:"/v1/canvas/attention",handler:Ce},{method:"POST",pattern:"/v1/canvas/attention/counts",handler:Re},{method:"POST",pattern:"/v1/canvas/history/search",handler:$e},{method:"POST",pattern:"/v1/canvas/history/grep",handler:Te},{method:"GET",pattern:"/v1/canvas/history/read",handler:Ae},{method:"POST",pattern:"/v1/canvas/history/stats",handler:Ee},{method:"GET",pattern:"/v1/canvas/snapshot",handler:Pe},{method:"GET",pattern:"/v1/canvas/roster",handler:Ge},{method:"GET",pattern:"/v1/canvas/live-roots",handler:He},{method:"GET",pattern:"/v1/canvas/browse",handler:ze},{method:"GET",pattern:"/v1/canvas/graph",handler:Je},{method:"POST",pattern:"/v1/canvas/prune",ownerOnly:!0,handler:We}];export{wt as canvasRoutes,ze as handleBrowse};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var n=Object.defineProperty;var c=(r,a)=>n(r,"name",{value:a,configurable:!0});import{withCanvasWrite as p}from"../../../core/canvas/db.js";import{OBJECT_TYPE as u}from"../../../core/permissions/builtin.js";import{check as m,checkUser as f}from"../../../core/permissions/evaluator.js";import{parseResource as l,parseSubject as d}from"../../../core/permissions/facts.js";import{ApiError as h}from"../../../api/errors.js";import{invalidRequest as b,isRecord as w}from"./validate.js";import{readerFor as y}from"../reader.js";import{appCaller as k,asApiError as j,requireOwnNamespace as v}from"./schemas.js";async function R(r){const{app:a}=k(r),t=[],o=w(r.body)?r.body:(t.push({field:"body",problem:"must be an object"}),{});for(const e of["subject","permission","resource"])typeof o[e]!="string"&&t.push({field:e,problem:"must be a string"});t.length>0&&b("check request",t);try{const e=d(o.subject);if(e.type!=="user"||e.relation!==""||e.id==="*")throw new h(400,"invalid_request","`subject` must be `user:<id>`");const s=l(o.resource);return await p(async i=>{if(s.type!==u)await v(i,a,s.type);else if(!await m(i,await y(i,r),"read",s.id))return{allowed:!1};return{allowed:await f(i,e.id,o.permission,s)}})}catch(e){throw j(e)}}c(R,"check");const _=[{method:"POST",pattern:"/v1/check",handler:c(async r=>({status:200,body:await R(r)}),"handler")}];export{_ as checkRoutes};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
1
|
+
var A=Object.defineProperty;var a=(r,e)=>A(r,"name",{value:e,configurable:!0});import{ApiError as c}from"../../../api/errors.js";import{emitEvent as C}from"../../../core/events/emit.js";import{withCanvasWrite as w,openDb as F}from"../../../core/canvas/db.js";import{registerCustomObject as $,publishCustom as L,unregisterCustomObject as P,pendingFor as H,acknowledge as I,verifyPublishToken as j,mayActAs as b,onQueueSignal as W,customReachable as k}from"../../../core/graph/custom.js";import{getById as l}from"../../../core/graph/objects.js";import{readerFor as M}from"../../../core/graph/reader.js";import{resolveName as N}from"../../../core/graph/names.js";import{stubOf as D}from"../../../core/peer/stubs.js";import{PRIVACY_LEVELS_DTO as z}from"../../../api/dto/objects.js";import{receiverForObject as Q}from"../../../core/graph/receivers.js";import{readerFor as m,resolveRef as V}from"../reader.js";import{isRecord as d}from"./validate.js";import{asApiError as B}from"./schemas.js";import{receiverEndpoint as G,resolveReceiverAddress as J}from"../../../core/graph/receiver-url.js";const p=a(r=>{throw new c(400,"invalid_request",`invalid ${r}`)},"bad"),f=a(()=>{throw new c(404,"not_found","custom object not found")},"missing");async function y(r,e){const n=await l(r,e)??await(async()=>{const i=await M(r,{class:"person"},async()=>[]),o=await N(r,i,e);return"object"in o?o.object:null})();return!n||!n.type.includes(".")||n.deleted_at!==null?f():n}a(y,"customObjectRef");async function U(r,e,t){if(await Q(r,t)==="argv"&&(e.publishToken||e.principal.class!=="person"&&e.principal.class!=="broker"))throw new c(403,"argv_forbidden","argv object requires a person or node principal")}a(U,"fenceArgv");async function v(r,e,t,n=!1){if(e.publishToken){if(await j(r,t,e.publishToken))return t;if(n)return f();throw new c(401,"invalid_publish_token","invalid publish token")}if(e.principal.class==="anonymous")return f();const i=await m(r,e),o=t.owner===null?null:await l(r,t.owner);return!o||!await b(r,i,o)||!await k(r,i,t)?f():i.class==="person"?i.person:i.class==="app"?i.app:i.class==="node"?i.node:i.object}a(v,"authorizeCustom");async function Y(r){const e=r.body;if((!d(e)||typeof e.kind!="string"||typeof e.name!="string"||typeof e.description!="string"||e.events!==void 0&&!d(e.events)||e.owner!==void 0&&typeof e.owner!="string"||e.rotate_token!==void 0&&typeof e.rotate_token!="boolean"||e.privacy!==void 0&&!z.includes(e.privacy))&&p("register request"),d(e.receiver)&&"url"in e.receiver&&typeof e.receiver.url=="string")try{await J(G(e.receiver.url))}catch(t){throw new c(400,"invalid_receiver",`invalid receiver URL: ${String(t)}`)}return await w(async t=>{const n=await m(t,r),i=e.owner===void 0?n.class==="person"?n.person:n.app:await(async()=>{const u=await V(t,n,e.owner);return"deleted"in u||"remote"in u?f():u})();["person","app","repo","profile"].includes(i.type)||p("owner");const o=await $(t,n,{kind:e.kind,name:e.name,owner:i,description:e.description,...e.events===void 0?{}:{events:e.events},...e.receiver===void 0?{}:{receiver:e.receiver},rotateToken:e.rotate_token,...e.privacy===void 0?{}:{privacy:e.privacy}}).catch(u=>{throw B(u)});return{id:o.object.id,name:o.object.name,...o.token?{token:o.token}:{}}})}a(Y,"register");async function K(r,e,t){const n=await r.prepare("SELECT owner, source, declared FROM object_kinds WHERE name = ?").get(t.type);if(!n||n.source==="register")return;if(n.source==="manifest"&&n.declared===0)throw new c(409,"kind_inert",`${t.type} is no longer declared by an installed plugin`);if(e.publishToken)return;const i=await l(r,n.owner);if(!i||!await b(r,await m(r,e),i))throw new c(403,"forbidden",`only ${i?.name??"the kind owner"} may publish ${t.type}`)}a(K,"requirePublisher");async function X(r){const e=r.body;return(!d(e)||typeof e.event!="string"||typeof e.summary!="string"||e.cause!==void 0&&typeof e.cause!="string")&&p("publish request"),await w(async t=>{const n=await y(t,r.params.ref),i=await D(t,n);if(i!==null)throw new c(404,"not_here",`${n.id} is not homed on this machine (it is a stub of ${i.home_machine})`,{id:n.id,home_machine:i.home_machine});const o=await v(t,r,n);return await K(t,r,n),await L(t,n,o,e)})}a(X,"publish");async function Z(r){await w(async e=>{const t=await y(e,r.params.ref),n=await v(e,r,t);await U(e,r,t),await P(e,t,n)})}a(Z,"unregister");async function x(r){const e=r.body;return(!d(e)||!Array.isArray(e.delivery_ids)||e.delivery_ids.some(t=>typeof t!="string"))&&p("delivery_ids"),await w(async t=>{const n=await y(t,r.params.ref);return await v(t,r,n,!0),await E(t,n),await I(t,n,e.delivery_ids)})}a(x,"ack");async function E(r,e){if((await r.prepare("SELECT receiver_json FROM custom_objects WHERE object = ?").get(e.id))?.receiver_json!=='"queue"')throw new c(409,"not_a_queue","object does not have a queue receiver")}a(E,"requireQueue");async function ee(r){const e=r.query.get("after");e!==null&&(!/^\d+$/.test(e)||!Number.isSafeInteger(Number(e)))&&p("after");const t=await F(),n=await y(t,r.params.ref);await v(t,r,n,!0),await E(t,n);const i=r.res;i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8","cache-control":"no-cache","x-accel-buffering":"no"});let o=-1;const u=a(async()=>{const s=await l(t,n.id);if(!s||s.deleted_at!==null)return!1;if(r.publishToken)return await j(t,s,r.publishToken)&&(await t.prepare("SELECT receiver_json FROM custom_objects WHERE object = ?").get(s.id))?.receiver_json==='"queue"';if(r.principal.class==="anonymous")return!1;const _=s.owner===null?null:await l(t,s.owner),g=await m(t,r);return _!==null&&await b(t,g,_)&&await k(t,g,s)&&(await t.prepare("SELECT receiver_json FROM custom_objects WHERE object = ?").get(s.id))?.receiver_json==='"queue"'},"authorized"),h=a(async()=>{if(!(i.destroyed||i.writableEnded)){if(!await u()){i.end();return}for(const s of await H(t,n,o))i.write(`${JSON.stringify(s)}
|
|
2
2
|
`),o=s.seq}},"flush"),R=await W(n.id,h),O=a(async()=>{await h(),!i.destroyed&&!i.writableEnded&&i.write(`
|
|
3
|
-
`)},"beat"),q=setInterval(()=>{O().catch(s=>
|
|
3
|
+
`)},"beat"),q=setInterval(()=>{O().catch(s=>C({level:"error",event:"api.custom_objects.heartbeat_failed",node_id:n.id,error:s}))},15e3),S=a(()=>{clearInterval(q),R()},"close");return i.once("close",S),await h(),{status:200}}a(ee,"stream");const T=a(r=>async e=>({status:200,body:await r(e)}),"ok"),ye=[{method:"POST",pattern:"/v1/custom-objects",handler:a(async r=>({status:200,body:await Y(r)}),"handler")},{method:"POST",pattern:"/v1/custom-objects/:ref/events",handler:T(X)},{method:"DELETE",pattern:"/v1/custom-objects/:ref",handler:a(async r=>(await Z(r),{status:204}),"handler")},{method:"GET",pattern:"/v1/custom-objects/:ref/deliveries",handler:ee},{method:"POST",pattern:"/v1/custom-objects/:ref/deliveries/ack",handler:T(x)}];export{v as authorizeCustom,y as customObjectRef,ye as customObjectRoutes,U as fenceArgv};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var oe=Object.defineProperty;var u=(n,e)=>oe(n,"name",{value:e,configurable:!0});import{ApiError as _}from"../../../api/errors.js";import{DOC_KINDS as q,DOC_UNSET_FIELDS as H}from"../../../api/dto/docs.js";import{PRIVACY_LEVELS_DTO as U}from"../../../api/dto/objects.js";import{withCanvasWrite as k}from"../../../core/canvas/db.js";import{CrtrError as re}from"../../../core/errors.js";import{emitEvent as ie}from"../../../core/events/emit.js";import{canChange as V,spaceOf as ae}from"../../../core/graph/access.js";import{get as O}from"../../../core/graph/bodies.js";import{deleteDocument as se,documentRecord as F,editDocument as ce,heads as x,history as de,linksIn as K,moveDocument as ue,readBase as fe,setDocumentRecord as le,withCurrentNames as me,writeDocument as pe}from"../../../core/graph/documents.js";import{resolveName as X}from"../../../core/graph/names.js";import{getById as L}from"../../../core/graph/objects.js";import{noteRepoDocumentsChanged as we}from"../../../core/graph/repo-sync/index.js";import{checkoutsForCwd as he}from"../../../core/graph/repo-sync/repos.js";import{lintRules as ye,rulesOf as ve}from"../../../core/graph/rules.js";import{unifiedDiff as ge}from"../../../core/graph/diff.js";import{ownerFromFlag as M,readerFor as E,resolveRef as z}from"../reader.js";import{filterAsync as _e,flatMapAsync as be}from"../../../core/async-array.js";function y(n,e,t,o,i={}){return new _(n,e,t,{...i,error:e,message:t,next:o})}u(y,"refuse");const b=u((n,e)=>new _(400,"invalid_request",n,e),"invalid");function R(n){const e=n.body;if(e===void 0)return{};if(typeof e!="object"||e===null||Array.isArray(e))throw b("the request body must be a JSON object");return e}u(R,"bodyOf");const C=u(async n=>async e=>await he(n,e),"reposFnFor");function S(n,e){if(n instanceof re){const t=n.details;if(n.code==="read_first")throw y(409,"read_first",n.message,`Read it first with \`crtr canvas read ${e?.id??"<ref>"}\`, then rerun the edit.`,t??{});if(n.code==="conflict")throw new _(409,"name_taken",n.message,t);if(n.code==="forbidden")throw typeof t?.next=="string"?y(403,"forbidden",n.message,t.next,t):new _(403,"forbidden",n.message,t);if(n.code==="scope_missing")throw y(403,"scope_missing",n.message,`Launch the run with \`${String(t?.scope)}\` in its scopes list.`,t??{});if(t?.rule==="repo-public-only")throw y(422,"repo_documents_are_public",n.message,'Own it as `user` and add a rule with `if: {"repo": "<handle>"}` so it loads only in that repo.')}throw n}u(S,"mapGraphError");async function W(n,e,t){const o=await z(n,e,decodeURIComponent(t));if("remote"in o)throw y(404,"not_found",G(o.remote),"Check the name with `crtr canvas search`.");if("deleted"in o)throw new _(404,"not_found",`${o.deleted.name} is deleted`,{id:o.deleted.id,deleted:!0});if(o.type!=="document")throw b(`${t} is a ${o.type}, not a document`);return o}u(W,"refDocument");function G(n){return`no object named ${n} on this runtime; it may be on another runtime, or the name may be misspelled`}u(G,"remoteMessage");async function ke(n,e){const t=e.owner===null?null:await L(n,e.owner);return t?t.type==="node"?t.id:t.name:""}u(ke,"ownerHandle");async function j(n,e){const t=await ke(n,e);return t?`${t}/${e.name}`:e.name}u(j,"canonicalName");async function Ee(n,e){const t=e.owner===null?null:await L(n,e.owner),o=t?{id:t.id,type:t.type,handle:t.type==="node"?t.id:t.name}:null;return{id:e.id,type:e.type,kind:e.kind,owner:o,privacy:e.privacy,name:e.name,preview:e.preview??"",created_at:e.created_at,deleted_at:e.deleted_at}}u(Ee,"objectDTO");async function $e(n,e){const t=e.owner===null?null:await L(n,e.owner);return t?.type==="repo"?t:null}u($e,"repoOwner");async function N(n,e,t,o){const i=[...new Map(await be(t,async f=>{const a=await $e(n,f);return a?[[a.id,a]]:[]})).values()],s=e.class==="node"?e.cwd:o,r=e.class==="node"?[...e.checkouts,...e.projectCheckouts].map(f=>f.root):[];return{repos:i,dirs:[...new Set([...s!==void 0?[s]:[],...r])]}}u(N,"repoChange");async function T(n){for(const e of n.repos)try{await we(e,n.dirs)}catch(t){ie({level:"warn",event:"repo_sync.failed",outcome:"failed",error:t,fields:{repo:e.name,step:"export",reason:t instanceof Error?t.message:String(t)}})}}u(T,"syncChanged");const Y=/^[A-Za-z0-9_-]+(\/[A-Za-z0-9_-]+)*$/;function Ae(n,e){if(n===void 0)return;if(!Array.isArray(n)){e.push("`rules` must be a list");return}const t=n.map(i=>{if(typeof i!="object"||i===null||Array.isArray(i))return i;const{match_frontmatter:s,...r}=i;return"matchFrontmatter"in r?{...r,match_frontmatter:r.matchFrontmatter}:s===void 0?r:{...r,matchFrontmatter:s}}),o=ye(t);if(o){e.push(o.replaceAll("matchFrontmatter","match_frontmatter"));return}return t}u(Ae,"rulesFromDTO");function Z(n,e){const t={},o=u(a=>{const c=n[a];if(c!==void 0){if(typeof c!="string"){e.push(`\`${a}\` must be a string`);return}return c}},"str"),i=o("preview");i!==void 0&&(i.trim()===""||/[\r\n]/.test(i)?e.push("`preview` must be one non-empty line"):t.preview=i);const s=o("summary");s!==void 0&&(t.summary=s);const r=o("why_it_exists");if(r!==void 0&&(t.whyItExists=r),n.privacy!==void 0&&(U.includes(n.privacy)?t.privacy=n.privacy:e.push(`\`privacy\` must be one of ${U.join(", ")}`)),n.unlisted!==void 0&&(typeof n.unlisted!="boolean"?e.push("`unlisted` must be a boolean"):t.unlisted=n.unlisted),n.lint_ignore!==void 0){const a=n.lint_ignore;!Array.isArray(a)||a.some(c=>typeof c!="string")?e.push("`lint_ignore` must be a list of strings"):t.lintIgnore=a}if(n.extensions!==void 0){const a=n.extensions;typeof a!="object"||a===null||Array.isArray(a)||Object.values(a).some(c=>typeof c!="object"||c===null||Array.isArray(c))?e.push("`extensions` must map each plugin to an object of fields"):t.extensions=a}const f=Ae(n.rules,e);return f!==void 0&&(t.rules=f),t}u(Z,"fieldsFrom");function J(n){if(n.length>0)throw b(n.join("; "),{errors:n})}u(J,"failOn");async function Q(n,e,t,o){const i=await _e(K(t),async s=>"remote"in await X(n,e,s));return{...o.length>0?{unresolved_links:o}:{},...i.length>0?{remote_links:i}:{}}}u(Q,"linkReport");async function Oe(n){const e=R(n),t=[],o=e.name;(typeof o!="string"||!Y.test(o))&&t.push("`name` must be segments of letters, digits, `_` or `-` joined by `/`"),typeof e.body!="string"&&t.push("`body` must be a string"),typeof e.preview!="string"&&t.push("`preview` is required");const i=e.kind??"knowledge";q.includes(i)||t.push(i==="report"?"reports are written only by `crtr push`":`\`kind\` must be one of ${q.join(", ")}`);const s=Z(e,t);e.cwd!==void 0&&typeof e.cwd!="string"&&t.push("`cwd` must be a string"),J(t);const r=e,{dto:f,change:a}=await k(async c=>{const w=await E(c,n),d=await M(c,w,r.owner,r.cwd);if(!await V(c,w,d))throw new _(404,"not_found",`no owner ${d.name} you can write to`);try{const{object:p,unresolved:l}=await pe(c,w,{...s,owner:d,name:r.name,kind:i,preview:s.preview,privacy:s.privacy??"public"},r.body,await C(c));return{dto:{id:p.id,name:await j(c,p),...await Q(c,w,r.body,l)},change:await N(c,w,[p],r.cwd)}}catch(p){S(p)}});return await T(a),f}u(Oe,"write");function je(n,e){let t=n;e.forEach(({old:o,new:i},s)=>{const r=o===""?-1:t.indexOf(o);if(r<0)throw y(422,"replace_no_match",`replace[${s}]: old text not found in the revision you read`,"Copy the old text exactly from your last read and rerun.",{index:s});if(t.indexOf(o,r+1)>=0)throw y(422,"replace_ambiguous",`replace[${s}]: old text occurs more than once`,"Include more surrounding text so the old text matches once, and rerun.",{index:s});t=t.slice(0,r)+i+t.slice(r+o.length)})}u(je,"checkReplacements");async function De(n){const e=R(n),t=[],o=e.body!==void 0,i=e.replace!==void 0;o&&i&&t.push("give `body` or `replace`, not both"),o&&typeof e.body!="string"&&t.push("`body` must be a string");const s=e.replace;i&&(!Array.isArray(s)||s.length===0||s.some(d=>typeof d!="object"||d===null||typeof d.old!="string"||typeof d.new!="string"))&&t.push("`replace` must be a non-empty list of {old, new} strings"),(typeof e.rationale!="string"||e.rationale.trim()==="")&&t.push("`rationale` is required"),e.verbatim!==void 0&&typeof e.verbatim!="boolean"&&t.push("`verbatim` must be a boolean"),e.base!==void 0&&(typeof e.base!="string"||e.base==="")&&t.push("`base` must be a non-empty heads key"),e.base!==void 0&&!o&&!i&&t.push("`base` applies only to a `body` or `replace` edit");const r=Z(e,t),f=e.unset??[];if(!Array.isArray(f)||f.some(d=>!H.includes(d)))t.push(`\`unset\` takes only ${H.join(", ")}`);else for(const d of f)d==="summary"&&(r.summary=null),d==="why_it_exists"&&(r.whyItExists=null),d==="unlisted"&&(r.unlisted=!1),d==="lint_ignore"&&(r.lintIgnore=null),d==="extensions"&&(r.extensions=null),d==="rules"&&(r.rules=[]);t.length===0&&!o&&!i&&Object.keys(r).length===0&&t.push("nothing to change: give `body`, `replace`, or a field"),J(t);const a=e,{dto:c,synced:w}=await k(async d=>{const p=await E(d,n),l=await W(d,p,n.params.ref),g=await j(d,l),A=await N(d,p,[l]);try{if(!o&&!i)return await le(d,p,l,r),{dto:{id:l.id,name:g,revision:(await F(d,l)).revision},synced:A};const v=a.base??await fe(d,p,l);if(i&&v!==null){const B=await F(d,l),P=await x(d,l);B.source_path===null&&B.heads_key===v&&P.length===1&&je(await me(d,l,O(P[0].body_hash)),a.replace)}const D=a.verbatim===!0,m=o?{body:a.body,verbatim:D}:{replace:a.replace,verbatim:D},h=await ce(d,p,l,m,a.rationale,v,r,await C(d));if("stale"in h)throw y(409,"stale_revision",`${g} changed after your read; it is now at revision ${h.stale.revision}`,`Read it again with \`crtr canvas read ${g}\`, then redo your change on the current text.`,{stale:h.stale});const I=O((await x(d,l))[0].body_hash);return{dto:{id:l.id,name:g,revision:h.revision,...await Q(d,p,I,h.unresolved)},synced:A}}catch(v){S(v,l)}});return await T(w),c}u(De,"edit");async function Re(n){const e=R(n);if(e.new_name===void 0&&e.owner===void 0)throw b("give a new name, an owner, or both");if(e.new_name!==void 0&&(typeof e.new_name!="string"||!Y.test(e.new_name)))throw b("`new_name` must be segments of letters, digits, `_` or `-` joined by `/`");const{dto:t,change:o}=await k(async i=>{const s=await E(i,n),r=await W(i,s,n.params.ref),f=e.owner===void 0?void 0:await M(i,s,e.owner,e.cwd);try{const a=await ue(i,s,r,{...e.new_name!==void 0?{name:e.new_name}:{},...f?{owner:f}:{}},await C(i));return{dto:{id:a.id,name:await j(i,a)},change:await N(i,s,[r,a],e.cwd)}}catch(a){S(a,r)}});return await T(o),t}u(Re,"move");async function Ce(n){const{dto:e,change:t}=await k(async o=>{const i=await E(o,n),s=await W(o,i,n.params.ref),r=await j(o,s),f=await N(o,i,[s]);try{await se(o,i,s,await C(o))}catch(a){S(a,s)}return{dto:{id:s.id,name:r},change:f}});return await T(t),e}u(Ce,"remove");async function Se(n){const e=n.query.get("diff"),t=e===null?void 0:Number(e);if(t!==void 0&&!(Number.isInteger(t)&&t>0))throw b("`diff` must be a revision number");return await k(async o=>{const i=await E(o,n),s=await z(o,i,decodeURIComponent(n.params.ref));if("remote"in s)throw y(404,"not_found",G(s.remote),"Check the name with `crtr canvas search`.");const r="deleted"in s?s.deleted:s;if(r.type!=="document")throw b(`${r.name} is a ${r.type}, not a document`);const f=await de(o,i,r),a={object:await Ee(o,r),revisions:f.map(c=>({rev_id:c.rev_id,number:c.number,author_id:c.author,rationale:c.rationale,verbatim:c.verbatim,created_at:c.created_at,parents:c.parents}))};if(t!==void 0){const c=f.find(d=>d.number===t);if(!c)throw new _(404,"not_found",`${r.name} has no revision ${t}`);const w=c.parents[0]===void 0?void 0:f.find(d=>d.rev_id===c.parents[0]);a.diff=ge(w?O(w.body_hash):"",O(c.body_hash))}return a})}u(Se,"revisionHistory");const ee=1e3,te=1e3,ne=3e3,Ne=/^When\b.+\bbecause\b.+/,Te=u(n=>{const e=n.trim();return e===""?0:e.split(/\s+/).length},"words");function Ie(n,e){if(n.some(o=>o.on==="boot"&&o.deliver==="content")&&e>ee)return`body is ${e} words, over the ${ee}-word cap for a boot rule at content (the whole body enters every node's context). Keep the core here and move separate subjects into [[linked]] documents.`;const t=[...new Set(n.filter(o=>o.on!=="boot"&&o.deliver==="content").map(o=>o.on))];return t.length>0&&e>te?`body is ${e} words, over the ${te}-word cap for a content rule on ${t.join("/")}. Keep the core here and move separate subjects into [[linked]] documents.`:n.some(o=>o.on==="boot"&&o.deliver==="preview")&&e>ne?`body is ${e} words, over the ${ne}-word cap for a boot rule at preview. Keep the core here and move separate subjects into [[linked]] documents.`:null}u(Ie,"lengthFinding");async function Fe(n){const e=R(n);return await k(async t=>{const o=await E(t,n),i=e.owner===void 0?null:await M(t,o,e.owner,e.cwd),s=await t.prepare("SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL AND home_machine IS NULL AND kind != 'report' ORDER BY name").all(),r=[],f=new Map;for(const a of s){if(i&&a.owner!==i.id||!await V(t,o,a))continue;const c=await F(t,a),w=new Set(c.lint_ignore??[]),d=await j(t,a),p=u((m,h,I)=>{w.has(m)||r.push({name:d,severity:h,rule:m,message:I})},"add"),l=await ve(t,a),g=(await x(t,a))[0],A=g?O(g.body_hash):"",v=Ie(l,Te(A));v&&p("length","error",v),l.some(m=>m.deliver==="preview")&&!Ne.test(a.preview??"")&&p("preview-shape","error",`a rule delivers this document at preview, so the preview must read "When <situation in the reader's work>, read this because <what the reader gains>"`);const D=new Set((await t.prepare("SELECT written_as FROM edges WHERE type = 'links-to' AND src = ?").all(a.id)).map(m=>m.written_as));for(const m of K(A)){if(D.has(m))continue;const h=await X(t,o,m);"remote"in h||"object"in h||"deleted"in h||p("links","warning",`[[${m}]] names no object in your view`)}if(l.some(m=>m.on==="workspace-open"&&m.deliver==="content")){const m=await ae(t,a);m.type==="repo"&&!w.has("workspace-open")&&f.set(m.name,[...f.get(m.name)??[],d])}}for(const[a,c]of f)if(!(c.length<2))for(const w of c)r.push({name:w,severity:"warning",rule:"workspace-open",message:`repo ${a} has ${c.length} documents delivered at content on workspace-open (${c.join(", ")}); keep one and link the rest from it`});return{findings:r}})}u(Fe,"lint");const $=u((n,e=200)=>async t=>({status:e,body:await n(t)}),"ok"),et=[{method:"POST",pattern:"/v1/docs",handler:$(Oe,201)},{method:"PATCH",pattern:"/v1/docs/:ref",handler:$(De)},{method:"POST",pattern:"/v1/docs/:ref/move",handler:$(Re)},{method:"DELETE",pattern:"/v1/docs/:ref",handler:$(Ce)},{method:"GET",pattern:"/v1/docs/:ref/history",handler:$(Se)},{method:"POST",pattern:"/v1/docs/lint",handler:$(Fe)}];export{j as canonicalName,et as docRoutes,N as repoChange,T as syncChanged};
|
|
1
|
+
var oe=Object.defineProperty;var u=(n,e)=>oe(n,"name",{value:e,configurable:!0});import{ApiError as k}from"../../../api/errors.js";import{DOC_KINDS as P,DOC_UNSET_FIELDS as H}from"../../../api/dto/docs.js";import{PRIVACY_LEVELS_DTO as U}from"../../../api/dto/objects.js";import{withCanvasWrite as A}from"../../../core/canvas/db.js";import{CrtrError as re}from"../../../core/errors.js";import{emitEvent as ie}from"../../../core/events/emit.js";import{canChange as ae,spaceOf as se}from"../../../core/graph/access.js";import{get as $}from"../../../core/graph/bodies.js";import{deleteDocument as ce,documentRecord as I,editDocument as de,heads as x,history as ue,linksIn as V,moveDocument as fe,readBase as le,setDocumentRecord as me,withCurrentNames as pe,writeDocument as he}from"../../../core/graph/documents.js";import{resolveName as K}from"../../../core/graph/names.js";import{getById as L}from"../../../core/graph/objects.js";import{noteRepoDocumentsChanged as we}from"../../../core/graph/repo-sync/index.js";import{checkoutsForCwd as ye}from"../../../core/graph/repo-sync/repos.js";import{lintRules as ge,rulesOf as ve}from"../../../core/graph/rules.js";import{unifiedDiff as _e}from"../../../core/graph/diff.js";import{ownerForGrantee as be}from"../../../core/graph/objects.js";import{ownerFromFlag as W,readerFor as E,resolveRef as G}from"../reader.js";import{appCaller as X,asApiError as ke,requireOwnNamespace as Ae}from"./schemas.js";import{filterAsync as Ee,flatMapAsync as Oe}from"../../../core/async-array.js";function g(n,e,t,o,a={}){return new k(n,e,t,{...a,error:e,message:t,next:o})}u(g,"refuse");const b=u((n,e)=>new k(400,"invalid_request",n,e),"invalid");function R(n){const e=n.body;if(e===void 0)return{};if(typeof e!="object"||e===null||Array.isArray(e))throw b("the request body must be a JSON object");return e}u(R,"bodyOf");const C=u(async n=>async e=>await ye(n,e),"reposFnFor");function N(n,e){if(n instanceof re){const t=n.details;if(n.code==="read_first")throw g(409,"read_first",n.message,`Read it first with \`crtr canvas read ${e?.id??"<ref>"}\`, then rerun the edit.`,t??{});if(n.code==="conflict")throw new k(409,"name_taken",n.message,t);if(n.code==="forbidden")throw typeof t?.next=="string"?g(403,"forbidden",n.message,t.next,t):new k(403,"forbidden",n.message,t);if(n.code==="scope_missing")throw g(403,"scope_missing",n.message,`Launch the run with \`${String(t?.scope)}\` in its scopes list.`,t??{});if(t?.rule==="repo-public-only")throw g(422,"repo_documents_are_public",n.message,'Own it as `user` and add a rule with `if: {"repo": "<handle>"}` so it loads only in that repo.')}throw ke(n)}u(N,"mapGraphError");async function M(n,e,t){const o=await G(n,e,decodeURIComponent(t));if("remote"in o)throw g(404,"not_found",z(o.remote),"Check the name with `crtr canvas search`.");if("deleted"in o)throw new k(404,"not_found",`${o.deleted.name} is deleted`,{id:o.deleted.id,deleted:!0});if(o.type!=="document")throw b(`${t} is a ${o.type}, not a document`);return o}u(M,"refDocument");function z(n){return`no object named ${n} on this runtime; it may be on another runtime, or the name may be misspelled`}u(z,"remoteMessage");async function $e(n,e){const t=e.owner===null?null:await L(n,e.owner);return t?t.type==="node"?t.id:t.name:""}u($e,"ownerHandle");async function j(n,e){const t=await $e(n,e);return t?`${t}/${e.name}`:e.name}u(j,"canonicalName");async function je(n,e){const t=e.owner===null?null:await L(n,e.owner),o=t?{id:t.id,type:t.type,handle:t.type==="node"?t.id:t.name}:null;return{id:e.id,type:e.type,kind:e.kind,owner:o,privacy:e.privacy,name:e.name,preview:e.preview??"",created_at:e.created_at,deleted_at:e.deleted_at,...e.type==="document"?{schema_type:e.schema_type??null}:{}}}u(je,"objectDTO");async function De(n,e){const t=e.owner===null?null:await L(n,e.owner);return t?.type==="repo"?t:null}u(De,"repoOwner");async function S(n,e,t,o){const a=[...new Map(await Oe(t,async f=>{const r=await De(n,f);return r?[[r.id,r]]:[]})).values()],c=e.class==="node"?e.cwd:o,s=e.class==="node"?[...e.checkouts,...e.projectCheckouts].map(f=>f.root):[];return{repos:a,dirs:[...new Set([...c!==void 0?[c]:[],...s])]}}u(S,"repoChange");async function T(n){for(const e of n.repos)try{await we(e,n.dirs)}catch(t){ie({level:"warn",event:"repo_sync.failed",outcome:"failed",error:t,fields:{repo:e.name,step:"export",reason:t instanceof Error?t.message:String(t)}})}}u(T,"syncChanged");const Y=/^[A-Za-z0-9_-]+(\/[A-Za-z0-9_-]+)*$/;function Re(n,e){if(n===void 0)return;if(!Array.isArray(n)){e.push("`rules` must be a list");return}const t=n.map(a=>{if(typeof a!="object"||a===null||Array.isArray(a))return a;const{match_frontmatter:c,...s}=a;return"matchFrontmatter"in s?{...s,match_frontmatter:s.matchFrontmatter}:c===void 0?s:{...s,matchFrontmatter:c}}),o=ge(t);if(o){e.push(o.replaceAll("matchFrontmatter","match_frontmatter"));return}return t}u(Re,"rulesFromDTO");function Z(n,e){const t={},o=u(r=>{const d=n[r];if(d!==void 0){if(typeof d!="string"){e.push(`\`${r}\` must be a string`);return}return d}},"str"),a=o("preview");a!==void 0&&(a.trim()===""||/[\r\n]/.test(a)?e.push("`preview` must be one non-empty line"):t.preview=a);const c=o("summary");c!==void 0&&(t.summary=c);const s=o("why_it_exists");if(s!==void 0&&(t.whyItExists=s),n.privacy!==void 0&&(U.includes(n.privacy)?t.privacy=n.privacy:e.push(`\`privacy\` must be one of ${U.join(", ")}`)),n.unlisted!==void 0&&(typeof n.unlisted!="boolean"?e.push("`unlisted` must be a boolean"):t.unlisted=n.unlisted),n.lint_ignore!==void 0){const r=n.lint_ignore;!Array.isArray(r)||r.some(d=>typeof d!="string")?e.push("`lint_ignore` must be a list of strings"):t.lintIgnore=r}if(n.extensions!==void 0){const r=n.extensions;typeof r!="object"||r===null||Array.isArray(r)||Object.values(r).some(d=>typeof d!="object"||d===null||Array.isArray(d))?e.push("`extensions` must map each plugin to an object of fields"):t.extensions=r}const f=Re(n.rules,e);return f!==void 0&&(t.rules=f),t}u(Z,"fieldsFrom");function J(n){if(n.length>0)throw b(n.join("; "),{errors:n})}u(J,"failOn");async function Q(n,e,t,o){const a=await Ee(V(t),async c=>"remote"in await K(n,e,c));return{...o.length>0?{unresolved_links:o}:{},...a.length>0?{remote_links:a}:{}}}u(Q,"linkReport");async function Ce(n){const e=R(n),t=[],o=e.name;(typeof o!="string"||!Y.test(o))&&t.push("`name` must be segments of letters, digits, `_` or `-` joined by `/`"),typeof e.body!="string"&&t.push("`body` must be a string"),typeof e.preview!="string"&&t.push("`preview` is required");const a=e.kind??"knowledge";P.includes(a)||t.push(a==="report"?"reports are written only by `crtr push`":`\`kind\` must be one of ${P.join(", ")}`);const c=Z(e,t);e.cwd!==void 0&&typeof e.cwd!="string"&&t.push("`cwd` must be a string");const s=e.schema_type;s!==void 0&&typeof s!="string"&&t.push("`schema_type` must be a string");const f=e.relations;f!==void 0&&(!Array.isArray(f)||f.some(i=>typeof i!="object"||i===null||typeof i.relation!="string"||typeof i.subject!="string"))&&t.push("`relations` must be a list of {relation, subject} strings"),J(t);const r=e,{dto:d,change:w}=await A(async i=>{const l=await E(i,n);r.schema_type!==void 0?await Ae(i,X(n).app,r.schema_type):r.relations!==void 0&&X(n);const m=r.owner==="user"&&l.class==="app"&&l.sub!==void 0?await be(i,l.sub.startsWith("user:")?l.sub:`user:${l.sub}`):await W(i,l,r.owner,r.cwd);try{const{object:h,unresolved:_}=await he(i,l,{...c,owner:m,name:r.name,kind:a,preview:c.preview,privacy:c.privacy??"public",...r.schema_type!==void 0?{schemaType:r.schema_type}:{},...r.relations!==void 0?{relations:r.relations}:{}},r.body,await C(i));return{dto:{id:h.id,name:await j(i,h),...await Q(i,l,r.body,_)},change:await S(i,l,[h],r.cwd)}}catch(h){N(h)}});return await T(w),d}u(Ce,"write");function Ne(n,e){let t=n;e.forEach(({old:o,new:a},c)=>{const s=o===""?-1:t.indexOf(o);if(s<0)throw g(422,"replace_no_match",`replace[${c}]: old text not found in the revision you read`,"Copy the old text exactly from your last read and rerun.",{index:c});if(t.indexOf(o,s+1)>=0)throw g(422,"replace_ambiguous",`replace[${c}]: old text occurs more than once`,"Include more surrounding text so the old text matches once, and rerun.",{index:c});t=t.slice(0,s)+a+t.slice(s+o.length)})}u(Ne,"checkReplacements");async function Se(n){const e=R(n),t=[],o=e.body!==void 0,a=e.replace!==void 0;o&&a&&t.push("give `body` or `replace`, not both"),o&&typeof e.body!="string"&&t.push("`body` must be a string");const c=e.replace;a&&(!Array.isArray(c)||c.length===0||c.some(i=>typeof i!="object"||i===null||typeof i.old!="string"||typeof i.new!="string"))&&t.push("`replace` must be a non-empty list of {old, new} strings"),(typeof e.rationale!="string"||e.rationale.trim()==="")&&t.push("`rationale` is required"),e.verbatim!==void 0&&typeof e.verbatim!="boolean"&&t.push("`verbatim` must be a boolean"),e.base!==void 0&&(typeof e.base!="string"||e.base==="")&&t.push("`base` must be a non-empty heads key"),e.base!==void 0&&!o&&!a&&t.push("`base` applies only to a `body` or `replace` edit");const s=Z(e,t),f=e.unset??[];if(!Array.isArray(f)||f.some(i=>!H.includes(i)))t.push(`\`unset\` takes only ${H.join(", ")}`);else for(const i of f)i==="summary"&&(s.summary=null),i==="why_it_exists"&&(s.whyItExists=null),i==="unlisted"&&(s.unlisted=!1),i==="lint_ignore"&&(s.lintIgnore=null),i==="extensions"&&(s.extensions=null),i==="rules"&&(s.rules=[]);t.length===0&&!o&&!a&&Object.keys(s).length===0&&t.push("nothing to change: give `body`, `replace`, or a field"),J(t);const r=e,{dto:d,synced:w}=await A(async i=>{const l=await E(i,n),m=await M(i,l,n.params.ref),h=await j(i,m),_=await S(i,l,[m]);try{if(!o&&!a)return await me(i,l,m,s,r.rationale),{dto:{id:m.id,name:h,revision:(await I(i,m)).revision},synced:_};const v=r.base??await le(i,l,m);if(a&&v!==null){const q=await I(i,m),B=await x(i,m);q.source_path===null&&q.heads_key===v&&B.length===1&&Ne(await pe(i,m,$(B[0].body_hash)),r.replace)}const D=r.verbatim===!0,p=o?{body:r.body,verbatim:D}:{replace:r.replace,verbatim:D},y=await de(i,l,m,p,r.rationale,v,s,await C(i));if("stale"in y)throw g(409,"stale_revision",`${h} changed after your read; it is now at revision ${y.stale.revision}`,`Read it again with \`crtr canvas read ${h}\`, then redo your change on the current text.`,{stale:y.stale});const F=$((await x(i,m))[0].body_hash);return{dto:{id:m.id,name:h,revision:y.revision,...await Q(i,l,F,y.unresolved)},synced:_}}catch(v){N(v,m)}});return await T(w),d}u(Se,"edit");async function Te(n){const e=R(n);if(e.new_name===void 0&&e.owner===void 0)throw b("give a new name, an owner, or both");if(e.new_name!==void 0&&(typeof e.new_name!="string"||!Y.test(e.new_name)))throw b("`new_name` must be segments of letters, digits, `_` or `-` joined by `/`");const{dto:t,change:o}=await A(async a=>{const c=await E(a,n),s=await M(a,c,n.params.ref),f=e.owner===void 0?void 0:await W(a,c,e.owner,e.cwd);try{const r=await fe(a,c,s,{...e.new_name!==void 0?{name:e.new_name}:{},...f?{owner:f}:{}},await C(a));return{dto:{id:r.id,name:await j(a,r)},change:await S(a,c,[s,r],e.cwd)}}catch(r){N(r,s)}});return await T(o),t}u(Te,"move");async function Fe(n){const{dto:e,change:t}=await A(async o=>{const a=await E(o,n),c=await M(o,a,n.params.ref),s=await j(o,c),f=await S(o,a,[c]);try{await ce(o,a,c,await C(o))}catch(r){N(r,c)}return{dto:{id:c.id,name:s},change:f}});return await T(t),e}u(Fe,"remove");async function Ie(n){const e=n.query.get("diff"),t=e===null?void 0:Number(e);if(t!==void 0&&!(Number.isInteger(t)&&t>0))throw b("`diff` must be a revision number");return await A(async o=>{const a=await E(o,n),c=await G(o,a,decodeURIComponent(n.params.ref));if("remote"in c)throw g(404,"not_found",z(c.remote),"Check the name with `crtr canvas search`.");const s="deleted"in c?c.deleted:c;if(s.type!=="document")throw b(`${s.name} is a ${s.type}, not a document`);const f=await ue(o,a,s),r={object:await je(o,s),revisions:f.map(d=>({rev_id:d.rev_id,number:d.number,author_id:d.author,rationale:d.rationale,verbatim:d.verbatim,created_at:d.created_at,parents:d.parents,acting_app:d.acting_app,acting_for:d.acting_for}))};if(t!==void 0){const d=f.find(i=>i.number===t);if(!d)throw new k(404,"not_found",`${s.name} has no revision ${t}`);const w=d.parents[0]===void 0?void 0:f.find(i=>i.rev_id===d.parents[0]);r.diff=_e(w?$(w.body_hash):"",$(d.body_hash))}return r})}u(Ie,"revisionHistory");const ee=1e3,te=1e3,ne=3e3,xe=/^When\b.+\bbecause\b.+/,Le=u(n=>{const e=n.trim();return e===""?0:e.split(/\s+/).length},"words");function We(n,e){if(n.some(o=>o.on==="boot"&&o.deliver==="content")&&e>ee)return`body is ${e} words, over the ${ee}-word cap for a boot rule at content (the whole body enters every node's context). Keep the core here and move separate subjects into [[linked]] documents.`;const t=[...new Set(n.filter(o=>o.on!=="boot"&&o.deliver==="content").map(o=>o.on))];return t.length>0&&e>te?`body is ${e} words, over the ${te}-word cap for a content rule on ${t.join("/")}. Keep the core here and move separate subjects into [[linked]] documents.`:n.some(o=>o.on==="boot"&&o.deliver==="preview")&&e>ne?`body is ${e} words, over the ${ne}-word cap for a boot rule at preview. Keep the core here and move separate subjects into [[linked]] documents.`:null}u(We,"lengthFinding");async function Me(n){const e=R(n);return await A(async t=>{const o=await E(t,n),a=e.owner===void 0?null:await W(t,o,e.owner,e.cwd),c=await t.prepare("SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL AND home_machine IS NULL AND kind != 'report' ORDER BY name").all(),s=[],f=new Map;for(const r of c){if(a&&r.owner!==a.id||!await ae(t,o,r))continue;const d=await I(t,r),w=new Set(d.lint_ignore??[]),i=await j(t,r),l=u((p,y,F)=>{w.has(p)||s.push({name:i,severity:y,rule:p,message:F})},"add"),m=await ve(t,r),h=(await x(t,r))[0],_=h?$(h.body_hash):"",v=We(m,Le(_));v&&l("length","error",v),m.some(p=>p.deliver==="preview")&&!xe.test(r.preview??"")&&l("preview-shape","error",`a rule delivers this document at preview, so the preview must read "When <situation in the reader's work>, read this because <what the reader gains>"`);const D=new Set((await t.prepare("SELECT written_as FROM edges WHERE type = 'links-to' AND src = ?").all(r.id)).map(p=>p.written_as));for(const p of V(_)){if(D.has(p))continue;const y=await K(t,o,p);"remote"in y||"object"in y||"deleted"in y||l("links","warning",`[[${p}]] names no object in your view`)}if(m.some(p=>p.on==="workspace-open"&&p.deliver==="content")){const p=await se(t,r);p.type==="repo"&&!w.has("workspace-open")&&f.set(p.name,[...f.get(p.name)??[],i])}}for(const[r,d]of f)if(!(d.length<2))for(const w of d)s.push({name:w,severity:"warning",rule:"workspace-open",message:`repo ${r} has ${d.length} documents delivered at content on workspace-open (${d.join(", ")}); keep one and link the rest from it`});return{findings:s}})}u(Me,"lint");const O=u((n,e=200)=>async t=>({status:e,body:await n(t)}),"ok"),at=[{method:"POST",pattern:"/v1/docs",handler:O(Ce,201)},{method:"PATCH",pattern:"/v1/docs/:ref",handler:O(Se)},{method:"POST",pattern:"/v1/docs/:ref/move",handler:O(Te)},{method:"DELETE",pattern:"/v1/docs/:ref",handler:O(Fe)},{method:"GET",pattern:"/v1/docs/:ref/history",handler:O(Ie)},{method:"POST",pattern:"/v1/docs/lint",handler:O(Me)}];export{j as canonicalName,at as docRoutes,S as repoChange,T as syncChanged};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var R=Object.defineProperty;var s=(e,t)=>R(e,"name",{value:t,configurable:!0});import{closeSync as T,constants as q,fstatSync as B,readSync as v}from"node:fs";import{isAbsolute as L,relative as F,resolve as b,sep as I}from"node:path";import{filterAsync as M}from"../../../core/async-array.js";import{appSpace as g}from"../../../core/layout.js";import{ApiError as d}from"../../../api/index.js";import{notFound as E,usage as c}from"../../../core/errors.js";import{InputError as k}from"../../../core/io.js";import{RunError as m}from"../../../core/runs/operations.js";import{isBeneathRefusal as z,listBeneath as N,openBeneath as O,writeFileBeneath as D}from"../../../core/spaces/open-beneath.js";import{fileRoot as P}from"../../../core/spaces/permissions.js";import{openDb as C}from"../../../core/canvas/db.js";import{canReadNode as $,resolvedScopes as S}from"../router.js";const y=512*1024,A=1024*1024,W=1e3;function h(e,t){if(e===null||e==="")throw c(`a file ${t} requires a \`path\` ${t==="write"?"body field":"query param"}`);if(!L(e))throw c(`file ${t} path must be absolute`,{received:e});return e}s(h,"requireAbsolutePath");function _(e){if(e==null)return"utf8";if(e==="utf8"||e==="base64")return e;throw c("encoding must be `utf8` or `base64`",{received:e})}s(_,"parseEncoding");function p(e,t,i){if(e instanceof d||e instanceof k||e instanceof m)throw e;if(z(e))throw new m(400,"invalid_request",`${t} meets a symlink, leaves its permitted root, or is not a regular file`,"path");const n=e.code;throw n==="ENOENT"?E(`no such file: ${t}`,{received:t}):n==="EACCES"||n==="EPERM"?new d(403,"forbidden",`permission denied ${i} ${t}`):new d(500,"internal",`cannot ${i} ${t}: ${e instanceof Error?e.message:String(e)}`)}s(p,"mapFilesystemError");async function Y(e,t,i,n){const r=await(await C()).prepare("SELECT isolated FROM nodes WHERE node_id = ?").get(t),[l,f]=F(g(i).root,b(n)).split(I),a=l==="nodes"&&f?await $(e.principal,i,f):!1;return{isolated:r?.isolated===1,reaches:s(()=>a,"reaches")}}s(Y,"runConfinementFor");async function w(e,t,i){const n=e.principal;if(n.class==="forwarded"||n.class==="machine")throw new d(403,"permission_error","this operation is not available to the caller");const o=n.class==="person"?null:n.class==="app"?{app:n.app,resolved:n.scopes,launched:null}:n.class==="cron"?{app:n.app,resolved:await S(n),launched:n.scopes}:{app:n.app,resolved:await S(n),launched:n.scopes,run:await Y(e,n.node,n.app,t)},r=P(o,t,i);if("root"in r)return r.root;throw"hidden"in r?E(`no such file: ${t}`,{received:t}):new m(403,"scope_missing",r.missing?`missing scope ${r.missing}`:`no permission names ${t}`,void 0,void 0,r.missing??void 0)}s(w,"rootFor");function Z(e,t,i){let n;try{n=O(e,t,q.O_RDONLY)}catch(o){return p(o,t,"reading")}try{const o=B(n);if(o.isDirectory())throw c(`file peek path is a directory: ${t}`,{received:t});const r=Buffer.allocUnsafe(Math.min(o.size,y)+1),l=v(n,r,0,r.length,0),f=l>y,a=r.subarray(0,Math.min(l,y)).toString(i);return{path:t,content:a,truncated:f}}catch(o){return p(o,t,"reading")}finally{T(n)}}s(Z,"readHead");async function j(e){const t=h(e.query.get("path"),"peek");return{status:200,body:Z(await w(e,t,"read"),t,_(e.query.get("encoding")))}}s(j,"handlePeek");function G(e){return e.length%4===0&&/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(e)}s(G,"isBase64");function H(e){if(typeof e!="object"||e===null||Array.isArray(e))throw c("file write requires an object body");const t=e,i=h(typeof t.path=="string"?t.path:null,"write");if(typeof t.content!="string")throw c("file write requires a string `content` body field");const n=_(t.encoding);if(n==="base64"&&!G(t.content))throw c("base64 file content must be valid base64");return{path:i,content:t.content,encoding:n}}s(H,"parseWriteBody");function U(e,t,i){if(i.byteLength>A)throw new d(413,"file_too_large",`file content exceeds the ${A} byte limit`);try{return D(e,t,i,{mode:process.platform==="linux"?432:384,atomic:!0}),{path:t,bytes_written:i.byteLength}}catch(n){return p(n,t,"writing")}}s(U,"writeAtomically");async function X(e){const{path:t,content:i,encoding:n}=H(e.body);return{status:200,body:U(await w(e,t,"rw"),t,Buffer.from(i,n))}}s(X,"handleWrite");function K(e){if(e===null)return W;const t=Number(e);if(!Number.isInteger(t)||t<1)throw c("file list limit must be a positive integer",{received:e});return t}s(K,"parseLimit");async function J(e){const t=h(e.query.get("path"),"list"),i=K(e.query.get("limit")),n=await w(e,t,"read");let o;try{o=N(n,t,i+1)}catch(a){return p(a,t,"listing")}const r=e.principal;r.class==="broker"&&b(t)===g(r.app).nodes&&(o=await M(o,async({name:a})=>await $(r,r.app,a)));const l=o.slice(0,i).map(({name:a,stat:u})=>({name:a,type:u.isFile()?"file":u.isDirectory()?"dir":"other",size:u.size,modified:u.mtime.toISOString()}));return{status:200,body:{path:t,entries:l,truncated:o.length>i}}}s(J,"handleList");const fe=[{method:"GET",pattern:"/v1/files/peek",scope:"crtr:act",handler:j},{method:"POST",pattern:"/v1/files/write",scope:"crtr:act",handler:X},{method:"GET",pattern:"/v1/files/list",scope:"crtr:act",handler:J}];export{fe as fileRoutes};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
var
|
|
2
|
-
AND NOT EXISTS (SELECT 1 FROM revision_parents p WHERE p.parent = r.rev_id) ORDER BY r.number DESC, r.rev_id LIMIT 1`).get(t.id),o=await e.prepare("SELECT created_at, author FROM revisions WHERE document = ? ORDER BY number, created_at LIMIT 1").get(t.id);if(!n||!o)throw
|
|
3
|
-
JOIN identities i ON i.object = CASE WHEN a.type = 'node' THEN
|
|
4
|
-
WHERE a.id = ?`).get(t))?.external_id??null}r(
|
|
1
|
+
var b=Object.defineProperty;var r=(e,t)=>b(e,"name",{value:t,configurable:!0});import{createHash as x}from"node:crypto";import{withCanvasWrite as g}from"../../../core/canvas/db.js";import{canRead as T}from"../../../core/graph/access.js";import{permits as k}from"../../../core/permissions/evaluator.js";import{bodyOf as M}from"../../../core/graph/bodies.js";import{ownerForGrantee as C}from"../../../core/graph/objects.js";import{readerFor as F}from"../../../core/graph/reader.js";import{checkoutsForCwd as H}from"../../../core/graph/repo-sync/repos.js";import{RunError as h}from"../../../core/runs/operations.js";import{mapAsync as j}from"../../../core/async-array.js";import{personId as B}from"../../../core/canvas/person.js";const ut=new Set(["memory.list","memory.get"]),W=1024*1024,w=/^[A-Za-z0-9_-]+(\/[A-Za-z0-9_-]+)*$/,N=["knowledge","preference"],s=r((e,t)=>new h(400,"invalid_request",e,t),"invalid"),O=r(()=>new h(404,"not_found","no memory document by that name"),"notFound");function _(e){const t=e.get("store");if(t===null)throw s("store is required","store");if(t!=="user")throw s('store must be "user"',"store")}r(_,"store");function J(e){const t=e.get("kind");if(t===null)return null;if(!N.includes(t))throw s("kind must be knowledge or preference","kind");return t}r(J,"kindOf");function Y(e){const t=e.get("limit");if(t===null)return 50;if(!/^(0|[1-9]\d*)$/.test(t)||Number(t)<1||Number(t)>100)throw s("limit must be an integer from 1 to 100","limit");return Number(t)}r(Y,"limitOf");function U(e,t){return x("sha256").update(JSON.stringify(["user",e,t])).digest("base64url").slice(0,16)}r(U,"filterHash");function $(e,t){return Buffer.from(JSON.stringify({n:e,f:t}),"utf8").toString("base64url")}r($,"encodeCursor");function z(e,t){if(e===null)return null;try{if(!/^[A-Za-z0-9_-]+$/.test(e))throw new Error("not base64url");const n=JSON.parse(Buffer.from(e,"base64url").toString("utf8"));if(typeof n.n=="string"&&w.test(n.n)&&n.f===t)return n.n}catch{}throw s("cursor is not the next_cursor of a previous page with the same store, path and kind","cursor")}r(z,"decodeCursor");async function R(e){return await C(e,B())}r(R,"personObject");async function v(e,t){return await F(e,t,async n=>await H(e,n))}r(v,"graphReader");async function S(e,t){const n=await e.prepare(`SELECT r.body_hash, r.created_at FROM revisions r WHERE r.document = ?
|
|
2
|
+
AND NOT EXISTS (SELECT 1 FROM revision_parents p WHERE p.parent = r.rev_id) ORDER BY r.number DESC, r.rev_id LIMIT 1`).get(t.id),o=await e.prepare("SELECT created_at, author FROM revisions WHERE document = ? ORDER BY number, created_at LIMIT 1").get(t.id);if(!n||!o)throw O();return{head:n,first:o}}r(S,"revisions");async function A(e,t){const{head:n,first:o}=await S(e,t),a=t.name.lastIndexOf("/");return{name:t.name,folder:a<0?"":t.name.slice(0,a),kind:t.kind,preview:t.preview,summary:t.summary,privacy:t.privacy,revision:t.revision,created_at:o.created_at,updated_at:n.created_at}}r(A,"item");async function G(e,t){return t===null?null:(await e.prepare(`SELECT i.external_id FROM objects a LEFT JOIN nodes n ON n.node_id = a.id
|
|
3
|
+
JOIN identities i ON i.object = CASE WHEN a.type = 'node' THEN n.app ELSE a.id END AND i.scheme = 'app'
|
|
4
|
+
WHERE a.id = ?`).get(t))?.external_id??null}r(G,"granteeOf");function Z(e,t){if(e.length<=t)return e;let n=t;for(;n>0&&(e[n]&192)===128;)n--;return e.subarray(0,n)}r(Z,"utf8Prefix");async function P(e,t){_(t);const n=t.get("path");if(n!==null&&!w.test(n))throw s("path must be name segments of letters, digits, `_` or `-` joined by `/`","path");const o=J(t),a=Y(t),d=U(n,o),i=z(t.get("cursor"),d);return await g(async u=>{const l=await v(u,e),c=await R(u),m=n===null?null:`${n}/`,f=o===null?N:[o],y=await k(u,l,"read"),E=await u.prepareUncached(`SELECT o.*, d.summary, d.revision, d.source_path FROM objects o JOIN documents d ON d.object = o.id
|
|
5
5
|
WHERE o.owner = ? AND o.type = 'document' AND o.deleted_at IS NULL AND d.unlisted = 0
|
|
6
6
|
AND o.kind IN (?, ?) AND (?::text IS NULL OR starts_with(o.name, ?::text)) AND (?::text IS NULL OR o.name > ?::text)
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
AND ${y.sql}
|
|
8
|
+
ORDER BY o.name LIMIT ?`).all(c.id,f[0],f[f.length-1],m,m,i,i,...y.params,a+1),p=E.slice(0,a),D=E.length>a;return{items:await j(p,async L=>await A(u,L)),next_cursor:D?$(p[p.length-1].name,d):null}})}r(P,"memoryList");async function X(e,t){_(t);const n=t.get("name");if(n===null)throw s("name is required","name");if(!w.test(n))throw s("name must be segments of letters, digits, `_` or `-` joined by `/`","name");return await g(async o=>{const a=await v(o,e),d=await R(o),i=await o.prepare(`SELECT o.*, d.summary, d.revision, d.source_path FROM objects o JOIN documents d ON d.object = o.id
|
|
9
|
+
WHERE o.owner = ? AND o.type = 'document' AND o.name = ? AND o.deleted_at IS NULL AND o.kind IN ('knowledge', 'preference')`).get(d.id,n);if(!i||!await T(o,a,i))throw O();const{head:u,first:l}=await S(o,i),c=Buffer.from(M(u.body_hash,i.source_path),"utf8"),m=Z(c,W);return{...await A(o,i),body:m.toString("utf8"),size:c.length,truncated:m.length<c.length,grantee:await G(o,l.author)}})}r(X,"memoryGet");async function I(e,t,n){if(e==="memory.list")return{status:200,body:await P(t,n)};if(e==="memory.get")return{status:200,body:await X(t,n)};throw new h(404,"not_found","unknown operation")}r(I,"handleMemoryOperation");const ct=[{method:"GET",pattern:"/v1/memory",handler:r(async e=>await I("memory.list",e.principal,e.query),"handler")},{method:"GET",pattern:"/v1/memory/document",handler:r(async e=>await I("memory.get",e.principal,e.query),"handler")}];export{W as MEMORY_BODY_MAX_BYTES,ut as MEMORY_OPERATIONS,I as handleMemoryOperation,X as memoryGet,P as memoryList,ct as memoryRoutes,Z as utf8Prefix};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var Ie=Object.defineProperty;var d=(e,n)=>Ie(e,"name",{value:n,configurable:!0});import{envProfileId as Oe}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 Pe,assertLaunchModelRegistered as K,forkNode as Ee,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 ie,findCreateRequest as Ge,getNode as R,recordCreateRequestNode as Fe,reserveCreateRequest as oe,reserveCreateRequestNode as Be,listNodes as Ke,recordRespawnAttempt as Ve,subscribersOf as We,subscriptionsOf as re,updateNode as C}from"../../../core/canvas/canvas.js";import{armControllerWait as xe}from"../../../core/canvas/waits.js";import{withCanvasWrite as V}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 ae,nodeAgentDir as W}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 an}from"../../../core/spaces/open-beneath.js";import{readNodeMessagesPage as dn,readNodeSession as sn,readNodeSnapshot as ln,transcriptMarkdown as cn}from"../../../core/runtime/node-read.js";import{assembleNodeSubject as un}from"../../../core/substrate/subject.js";import{reviveAll as fn}from"../../../core/runtime/revive-all.js";import{promoteAsync as pn,requestYieldAsync as mn,reshapeNodeAsync as x}from"../../../core/runtime/promote.js";import{recycleNode as wn}from"../../../core/runtime/recycle.js";import{relaunchRoot as hn}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 In,readMergedLaunchConfigAsync as de}from"../../../core/runtime/launch.js";import{modelRequestFromConfig as On}from"../../../core/model-routes.js";import{persistDormantModel as An,setModelLive as $n}from"../../../core/runtime/model-swap.js";import{waitForBrokerViewSocket as se}from"../../../core/runtime/view-socket.js";import{BrokerUnreachableError as Cn}from"../../../core/runtime/broker-request.js";import{boundFleet as P}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 le}from"../../../core/canvas/types.js";import{HUMAN_ACTION_NAME_PATTERN as Pn}from"../../../core/human/action-binding.js";import{resolveHumanAction as En}from"../../../core/human-actions.js";import{parseDurationMs as Dn}from"../../../core/wake.js";import{claimWarmNode as Ln,refillWarmPool as ce,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 Vn,loadExactProfileManifest as Wn}from"../../../core/profiles/manifest.js";import{getCron as fe}from"../../../core/canvas/crons.js";import{cronWakeOrigin as xn}from"../../../core/runtime/bearings.js";import{boundDaemonControl as zn}from"../../control.js";import{notFound as E,usage as m}from"../../../core/errors.js";import{assertScope as Jn,validateScopes as pe}from"../../../core/scopes.js";import{scopeAllowed as O}from"../../../shared/env.js";import{toCloseResultDTO as Un,toNodeDetailDTO as J,toNodeSummaryDTO as Yn,toReviveResultDTO as Hn}from"../map.js";import{ApiError as p}from"../../../api/index.js";import{InputError as y}from"../../../core/io.js";import{actsAsPerson as Qn,brokerMayReach as U,canReadNode as me,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 it}from"../../../core/spaces/file-root.js";import{activeGrant as ot,payerOfGrant as rt,terminalGrant as at}from"../../../core/grants/mirror.js";import{appRungForGrant as dt}from"../../../core/llm/app-rungs.js";import{APP_FAMILY as st}from"../../../core/model-routes.js";import{hasConfiguredProviderCredential as lt,NO_PROVIDER_CREDENTIAL_MESSAGE as we}from"../../../core/runtime/provider-credential-gate.js";import{filterAsync as he,mapAsync as ye}from"../../../core/async-array.js";async function h(e){const n=await R(e);if(n===null)throw E(`unknown node: ${e}`,{received:e});return n}d(h,"requireMeta");async function Y(e){return{subscribesTo:await re(e),subscribers:await We(e),children:await je(e)}}d(Y,"edgesFor");async function b(e){const n=await h(e);return await J(n,await Y(e))}d(b,"detailOf");async function ct(e){let n=(await ue(e)).length;try{n+=an(await W(e),await ae(e)).length}catch(t){if(!on(t))throw t}return n}d(ct,"countFiles");function ut(e){if(typeof e!="object"||e===null)throw m("a node create requires a JSON body");const n=e;if(n.kind!==void 0&&(typeof n.kind!="string"||n.kind.trim()===""))throw m("kind must be a non-empty string when provided");if(n.description!==void 0&&(typeof n.description!="string"||n.description.trim()===""))throw m("description must be a non-empty string when provided");if(n.creator!==void 0&&(typeof n.creator!="string"||n.creator.trim()===""))throw m("creator must be a non-empty node id when provided");if(n.scopes!==void 0&&pe(n.scopes),n.isolated!==void 0&&typeof n.isolated!="boolean")throw new p(400,"invalid_request","isolated must be a boolean",{param:"isolated"});const t=n.root_lifecycle;if(t!==void 0&&t!=="resident"&&t!=="terminal")throw m("root_lifecycle must be 'resident' or 'terminal'");if(n.request_key!==void 0&&(typeof n.request_key!="string"||n.request_key.trim()===""||n.request_key.length>128))throw m("request_key must be a non-empty string of at most 128 characters when provided");return n}d(ut,"parseCreateBody");function ft(e){if(e===void 0)return;const n=Dn(e),t=n===null?null:new Date(Date.now()+n);if(n===null||!Number.isFinite(n)||n<=0||t===null||!Number.isFinite(t.getTime()))throw new p(422,"invalid_deadline","`deadline` must be a positive representable duration");return t.toISOString()}d(ft,"parseDeadline");function pt(e){if(e!==void 0){if(typeof e!="object"||e===null||Array.isArray(e))throw new p(400,"invalid_request","`outcome_delivery` must be an object");if(typeof e.action!="string"||!Pn.test(e.action))throw new p(400,"invalid_request","`outcome_delivery.action` must be a declared action name");if(e.payload!==void 0){let n;try{n=JSON.stringify(e.payload)}catch{throw new p(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable")}if(n===void 0)throw new p(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable");if(Buffer.byteLength(n,"utf8")>le)throw new p(413,"payload_too_large",`serialized payload exceeds ${le} bytes`)}return e}}d(pt,"parseOutcomeDelivery");function mt(e,n){const t=En(e.action,n);if(!("kind"in t))return{actionName:e.action,argv:t.argv,cwd:t.cwd,configOrigin:t.configOrigin,...e.payload===void 0?{}:{payload:e.payload}};throw t.kind==="unknown_action"?new p(422,"unknown_action",`no action named ${e.action} is declared from ${n}`):new p(422,"invalid_action",`${e.action} is declared in ${t.configOrigin} but unusable: ${t.reason}`,{reason:t.reason,configOrigin:t.configOrigin})}d(mt,"resolveOutcomeDelivery");function wt(e,n,t){const o={kind:e.kind,cwd:t,prompt:e.prompt??""};return e.mode!==void 0&&(o.mode=e.mode),e.name!==void 0&&(o.name=e.name),e.description!==void 0&&(o.description=e.description),n!==void 0&&(o.parent=n),e.creator!==void 0&&(o.creator=e.creator),e.scopes!==void 0&&(o.scopes=e.scopes),e.isolated!==void 0&&(o.isolated=e.isolated),e.root===!0&&(o.root=!0),e.root_lifecycle!==void 0&&(o.rootLifecycle=e.root_lifecycle),(e.worktree===!0||typeof e.worktree=="string")&&(o.worktree=!0),typeof e.worktree=="string"&&(o.worktreeBase=e.worktree),e.worktree!==void 0&&(o.worktreeCwd=T(e.pin_cwd??e.cwd??t)),e.fork_from!==void 0&&(o.forkFrom=e.fork_from),e.model!==void 0&&(o.model=e.model),e.profile!==void 0&&(o.profile=e.profile),e.situational_context!==void 0&&(o.situationalContext=e.situational_context),e.node_id!==void 0&&(o.nodeId=e.node_id),o}d(wt,"buildRecipe");function ht(e,n,t){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:n,profileId:t,model:e.model??null,situationalContext:e.situational_context??null,name:e.name??null,creator:e.creator??null}}d(ht,"warmRequestFor");import{resolveCreateKind as mo}from"../../../core/runtime/launch-target.js";function _e(e){const n=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return On(e.model,n,e.modelExact===!0)}d(_e,"requestFromLaunch");function yt(e,n){if(n===null)return e;if(e.scopes===void 0)return{...e,scopes:[...n]};const t=e.scopes.filter(o=>!O(n,o));if(t.length===0)return e;throw new p(403,"scope_denied",`scopes exceed the bearer token's ceiling: ${t.join(", ")}`,{scopes:t,ceiling:n})}d(yt,"withinCeiling");async function ge(e,n,t){const o=(await Sn(n.kind,n.mode,{lifecycle:n.lifecycle,hasManager:e.parent!==null,model:n.model,modelOverride:!0,cwd:e.cwd,profileId:e.profile_id??null})).launch;await K(_e(o),{cwd:e.cwd,profileId:e.profile_id??null},t)}d(ge,"assertNodeModelChangeRegistered");async function be(e,n){const t=e.principal;if(t.class!=="broker"&&t.class!=="cron")return;const o=it({app:t.app,resolved:await Xn(t),launched:t.scopes},n,"read");if("root"in o)return;const i="missing"in o?o.missing:null;throw new p(403,"scope_missing",i?`the child's directory ${n} needs missing scope ${i}`:`no permission of this run names the child's directory ${n}`,void 0,void 0,i?{scope:i}:void 0)}d(be,"assertCallerReaches");const H=new Map;async function _t(e,n={},t={}){const o=yt(ut(e.body),e.ceiling);if(e.principal.class==="broker"){const c=e.principal;if(o.prefer_warm===!0&&c.app!=="app:terminal"&&(o.prefer_warm=!1),o.parent!=null){const r=await h(o.parent);if(r.grantee!==c.app)throw new p(403,"other_app_run","cannot create a child under another app's node");if(!await U(c,o.parent,r.grantee??"app:terminal"))throw E(`unknown node: ${o.parent}`,{received:o.parent})}if(o.creator!==void 0&&o.creator!==c.node)throw new p(403,"other_app_run","cannot create for another node");if(o.fork_from!==void 0){let r=null;try{r=await Me(await De(o.fork_from))}catch{}if(r?.grantee!==c.app||!await U(c,r.node_id,r.grantee))throw new p(403,"other_app_run","cannot fork another app's conversation")}o.creator=c.node}if(e.principal.class==="cron"){const c=e.principal;for(const s of["parent","creator","fork_from","node_id"])if(o[s]!=null)throw new p(403,"permission_error",`a cron cannot set ${s} on a node it starts`);o.prefer_warm=!1;const r=await en({grantee:c.app,sub:c.sub,grant_id:c.grant,scopes:c.scopes});if(!r.allowed)throw new p(r.reason==="scope_missing"?403:401,r.reason==="scope_missing"?"scope_missing":"grant_revoked",r.message);if(o.scopes!==void 0){const s=o.scopes.find(f=>!O(r.effectiveScopes,f)||!O(c.scopes,f));if(s!==void 0)throw new p(403,"scope_missing",`scope ${s} is not held by this cron`,void 0,void 0,{scope:s})}else c.scopes!==null&&(o.scopes=[...c.scopes]);o.node_id=await ne(),c.isolated&&(o.isolated=!0,o.cwd=await W(o.node_id,c.app))}o.creator!==void 0&&Jn(await h(o.creator),"crtr:act");const i=o.request_key?.trim();if(i===void 0||o.node_id!==void 0&&qe(o.node_id)&&await R(o.node_id)!==null&&(await Ge(i))?.nodeId!==o.node_id)return D(e,o,n,t);const a=H.get(i);if(a!==void 0)return a;const l=gt(e,o,i,n,t);H.set(i,l);try{return await l}finally{H.delete(i)}}d(_t,"handleCreate");async function gt(e,n,t,o,i){const a=await oe(t);if(a.nodeId!==null&&await R(a.nodeId)!==null){if(a.state!=="warm_claimed"){const l=await R(a.nodeId);if(e.principal.class!=="person"&&!await me(e.principal,l.grantee??"app:terminal",a.nodeId))throw new p(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:await b(a.nodeId)}}return D(e,n,o,i,a)}try{return await D(e,n,o,i,a)}catch(l){const c=await oe(t);throw(c.nodeId===null||await R(c.nodeId)===null)&&await te(t,c.nodeId),l}}d(gt,"handleKeyedCreateRequest");async function D(e,n,t,o,i=void 0){const a=o.deadlineAt??ft(n.deadline),l=pt(n.outcome_delivery),c=e.principal.class==="cron"?await 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:(await fe(e.principal.cron))?.created_by??null},n.node_id):null;c!==null&&(n.root=c.root===!0);const r=c?.parent??n.parent??void 0;if(r==null&&n.root!==!0)throw m("a node create requires a parent (or root: true for an independent root)");let s=null;if(n.output_schema!==void 0){try{s=JSON.parse(n.output_schema)}catch{throw m("output_schema must be a JSON schema string")}if(s===null||typeof s!="object"||Array.isArray(s))throw m("output_schema must be a JSON schema object");await Tn(s)}const{profileId:f,kind:w,cwd:u,launch:k}=await Fn(n,{validateKind:Re});await be(e,u),n.worktree!==void 0&&await be(e,T(n.pin_cwd??n.cwd??u));const _={...n,kind:w},g=l===void 0?void 0:mt(l,u),X=("grant"in e.principal?e.principal.grant:null)??(r==null?null:(await R(r))?.grant_id??null);if(await K(_e(await Pe(k,X,n.model)),{cwd:u,profileId:f},t.modelRegistry),await rt(X)!=="app"&&!await lt(f))throw new p(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=i===void 0||i.nodeId===null||i.state==="warm_claimed"?ht(_,u,f):null,j=s===null&&o.beforeBrokerLaunch===void 0?void 0:async S=>{s!==null&&await Nn(S,"terminal",s),o.beforeBrokerLaunch?.(S)};if(i?.state==="warm_claimed"&&i.nodeId!==null){const S=A===null?null:await Mn(A,i.nodeId,j);if(S===null)throw await te(i.requestKey,i.nodeId),new p(503,"create_resume_failed",`could not resume warm claim ${i.nodeId}; retry the create`);return await ie(i.requestKey,S),{status:201,body:await b(S)}}if(A!==null){const S=await Ln(A,{...a===void 0?{}:{deadlineAt:a},...g===void 0?{}:{outcomeDelivery:g},...i===void 0?{}:{requestKey:i.requestKey}},j);if(S!==null)return i!==void 0&&await ie(i.requestKey,S),ce(A),{status:201,body:await b(S)};M=A}const G=i?.nodeId??n.node_id??(i===void 0?void 0:await ne());i!==void 0&&i.nodeId===null&&await Be(i.requestKey,G);const I=wt(G===void 0?_:{..._,node_id:G},r,u);c!==null&&(c.rootLifecycle!==void 0&&(I.rootLifecycle=c.rootLifecycle),c.scopes!==void 0&&_.scopes===void 0&&(I.scopes=c.scopes),c.run!==void 0&&(I.run=c.run),c.withinCreate!==void 0&&(I.withinCreate=c.withinCreate)),a!==void 0&&(I.deadlineAt=a),g!==void 0&&(I.outcomeDelivery=g),I.readiness=n.root===!0?"await":"launch";const Z=await Le(I,j,()=>{M!==null&&ce(M)});return i!==void 0&&await Fe(i.requestKey,Z.node.node_id),{status:201,body:await b(Z.node.node_id)}}}d(D,"handleCreateRequest");function v(e,n){const t=e.query.getAll(n);if(t.length>1)throw m(`${n} must appear at most once`);return t[0]}d(v,"singleQueryValue");function Q(e,n){if(e!==void 0){if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;throw m(`${n} must be true or false`)}}d(Q,"optionalBoolean");function L(e,n,t){if(e!==void 0){if(t.includes(e))return e;throw m(`${n} must be one of: ${t.join(", ")}`)}}d(L,"oneOf");function bt(e){const n=new Set(["status","lifecycle","kind","mode","profile_id","profile_prefix","parent","top_level","under","under_inclusive","hanging","include"]);for(const[_]of e.query)if(!n.has(_))throw m(`unknown nodes query parameter: ${_}`);const t=L(v(e,"status"),"status",["active","idle","done","dead","canceled"]),o=L(v(e,"lifecycle"),"lifecycle",["terminal","resident"]),i=v(e,"kind"),a=L(v(e,"mode"),"mode",["base","orchestrator"]),l=v(e,"profile_id"),c=v(e,"profile_prefix"),r=v(e,"parent"),s=Q(v(e,"top_level"),"top_level"),f=v(e,"under"),w=Q(v(e,"under_inclusive"),"under_inclusive"),u=Q(v(e,"hanging"),"hanging"),k=L(v(e,"include"),"include",["activity"]);if(r!==void 0&&s===!0)throw m("parent and top_level=true cannot be combined");return{...t!==void 0?{status:t}:{},...o!==void 0?{lifecycle:o}:{},...i!==void 0?{kind:i}:{},...a!==void 0?{mode:a}:{},...l!==void 0?{profile_id:l}:{},...c!==void 0?{profile_prefix:c}:{},...r!==void 0?{parent:r}:{},...s!==void 0?{top_level:s}:{},...f!==void 0?{under:f}:{},...w!==void 0?{under_inclusive:w}:{},...u!==void 0?{hanging:u}:{},...k!==void 0?{include:k}:{}}}d(bt,"parseListQuery");async function vt(e){const n=bt(e);let t=await Ke({...n.status!==void 0?{status:n.status}:{},...n.lifecycle!==void 0?{lifecycle:n.lifecycle}:{},...n.kind!==void 0?{kind:n.kind}:{},...n.mode!==void 0?{mode:n.mode}:{},...n.profile_id!==void 0?{profileId:n.profile_id}:{},...n.profile_prefix!==void 0?{profilePrefix:n.profile_prefix}:{},...n.parent!==void 0?{parent:n.parent}:{},...n.top_level===!0?{topLevel:!0}:{},...n.under!==void 0?{under:n.under}:{},...n.under_inclusive===!0?{underInclusive:!0}:{},...n.hanging===!0?{hanging:!0}:{}});e.principal.class!=="person"&&(t=await he(t,async l=>await me(e.principal,l.grantee??"app:terminal",l.node_id)));const o=n.include==="activity"?await Ze(t.map(l=>l.node_id)):null,i=t.length>0?Ae():new Set;return{status:200,body:await ye(t,async l=>{const c=await Yn(l,l.profile_id!==null&&i.has(l.profile_id));if(o!==null){const r=await ue(l.node_id);c.activity={latest_report:r[0]??null,final_report:l.final_report===null?null:r.find(s=>s.name===l.final_report)??null,pending_human_count:o[l.node_id]??0}}return c})}}d(vt,"handleList");async function kt(e){const n=e.params.id,t=await Zn(e,n,{method:"GET",path:`/v1/nodes/${encodeURIComponent(n)}`,query:qn(e)});if(t.kind==="unknown")throw nt(n,t.unreachable);if(t.kind==="remote"){if(t.status>=400)throw et(t.status,t.body);return{status:t.status,body:tt(t.body,t.machine)}}return await h(n),{status:200,body:await b(n)}}d(kt,"handleDetail");async function St(e){const n=e.params.id;await h(n);const t=await ln(n);return{status:200,body:{node_id:n,snapshot:{messages:t.snapshot.messages,...t.snapshot.messageIds===void 0?{}:{messageIds:t.snapshot.messageIds},messageVisibility:t.snapshot.messageVisibility,turnVisibility:t.snapshot.turnVisibility,stats:t.snapshot.stats,state:t.snapshot.state,display:t.snapshot.display,...t.snapshot.queued===void 0?{}:{queued:t.snapshot.queued},...t.snapshot.toolGroupSummaries===void 0?{}:{toolGroupSummaries:t.snapshot.toolGroupSummaries},...t.snapshot.turnReplies===void 0?{}:{turnReplies:t.snapshot.turnReplies},...t.snapshot.workingActivity===void 0?{}:{workingActivity:t.snapshot.workingActivity}},commands:t.commands.map(i=>({name:i.name,description:i.description,source:i.source})),captured_at:B()}}}d(St,"handleSnapshot");async function Rt(e){const n=e.params.id,t=await un(n);if(t===null)throw E(`unknown node: ${n}`,{received:n});return{status:200,body:t}}d(Rt,"handleSubject");function It(e){for(const[a]of e.query)if(a!=="cursor"&&a!=="limit")throw m(`unknown messages query parameter: ${a}`);const n=e.query.getAll("cursor"),t=e.query.getAll("limit");if(n.length>1)throw m("cursor must appear at most once");if(t.length>1)throw m("limit must appear at most once");if(t.length===0)return n.length===0?{}:{cursor:n[0]};const o=t[0],i=Number(o);if(!Number.isSafeInteger(i)||o==="")throw m("limit must be an integer from 1 through 500");return n.length===0?{limit:i}:{cursor:n[0],limit:i}}d(It,"parseMessagesQuery");async function Ot(e){const n=e.params.id,t=await dn(n,It(e));return{status:200,body:{node_id:n,messages:t.messages,...t.messageIds===void 0?{}:{message_ids:t.messageIds},message_visibility:t.messageVisibility,next_cursor:t.nextCursor,captured_at:B()}}}d(Ot,"handleMessages");async function At(e){const n=e.params.id;await h(n);const t=await sn(n);return{status:200,body:{node_id:n,session_file:t.sessionFile,session_jsonl:t.sessionJsonl,system_prompt:t.systemPrompt,captured_at:B()}}}d(At,"handleSession");async function $t(e){const n=e.params.id;return await h(n),{status:200,body:{node_id:n,markdown:await cn(n)}}}d($t,"handleTranscript");async function Ct(e){const n=e.params.id;await h(n);const t=d(async(i,a)=>({node_id:i,label:(await R(i))?.name??i,dir:await ae(i),self:a,files:await ct(i)}),"root"),o=await he([await t(n,!0),...await ye(await re(n),async i=>await t(i.node_id,!1))],async i=>await Nt(i.node_id,i.dir)||i.files>0);return{status:200,body:{node_id:n,roots:o}}}d(Ct,"handleContext");async function Nt(e,n){try{return tn(await W(e),n)}catch(t){if(rn(t))return!1;throw t}}d(Nt,"hasDir");async function Tt(e){const n=await h(e.params.id),t=e.principal.class==="broker"?e.principal.scopes:e.ceiling,o=t===null?void 0:n.scopes==null?[...t]:[...new Set([...n.scopes.filter(a=>O(t,a)),...t.filter(a=>O(n.scopes,a))])],i=await Ee(n.node_id,o,e.principal.class==="broker"?e.principal.node:void 0);return{status:201,body:await b(i.node.node_id)}}d(Tt,"handleFork");const Pt=1e4;async function Et(e){const n=e.params.id;await h(n);const t=e.body,o=t?.resume??!0,i=t?.reopen??!1;await yn(n,i,e.principal.class==="broker"?e.principal.node:null);const a=!o&&t?.cron_id!==void 0?await fe(t.cron_id):null,l=await Te(n,{resume:o,capacity:"refuse",...a!==null?{wakeReason:await xn(a,"schedule_revive")}:{}});l.outcome!=="already-live"&&await Ve(n,{failures:0,notBefore:null});const c=(await R(n))?.status??"active",r=(l.launch??P().get(n)?.handle)?.exited,s=l.outcome!=="frozen"&&await se(n,r,Pt);return{status:200,body:Hn(n,l,c,s)}}d(Et,"handleRevive");async function Dt(e){const n=e.params.id;return{status:200,body:{newNodeId:(await hn(n))?.newNodeId??null}}}d(Dt,"handleRelaunchRoot");async function Lt(e){const n=e.params.id;await h(n);const t=e.body;if(t?.caller_pid!==void 0&&(!Number.isInteger(t.caller_pid)||t.caller_pid<=0))throw m("caller_pid must be a positive integer when provided");const o=zn(),i=new Promise(l=>{e.res.once("close",()=>l())}),a=await Ne(n,{teardownAfter:i,rootEvent:t?.finish===!0?"finish":"cancel",callerPid:t?.caller_pid,...e.principal.class==="broker"?{closer:e.principal.node}:{},...o===null?{}:{registerDetached:o.registerDetached}});return{status:200,body:Un(a)}}d(Lt,"handleClose");async function Mt(e){if(!Qn(e.principal))throw new p(403,"permission_error","only the person marks a conversation read");const n=e.params.id;return await h(n),await ze(n),{status:204}}d(Mt,"handleMarkRead");async function jt(e){const n=e.params.id;await h(n);const t=await wn(n);return{status:200,body:{recycled:t.recycled,finalized:t.finalized,new_root:t.newRoot,delivered:t.delivered}}}d(jt,"handleRecycle");async function Gt(e){const n=e.params.id;return await h(n),await x(n,{lifecycle:"terminal"}),await $(e,n,["lifecycle"]),{status:200,body:await b(n)}}d(Gt,"handleDemote");async function Ft(e,n={}){const t=e.params.id,o=await h(t),i=e.body??{};i.kind!==void 0&&await z(i.kind,o.cwd,o.profile_id??null),i.model!==void 0&&await ge(o,{kind:i.kind??o.kind,mode:"orchestrator",lifecycle:i.resident===!0?"resident":o.lifecycle,model:i.model},n.modelRegistry);const a=await pn(t,{...i.kind!==void 0?{kind:i.kind}:{},...i.resident===!0?{resident:!0}:{},...i.model!==void 0?{model:i.model}:{}});await $(e,t,["mode",...i.kind!==void 0?["kind"]:[],...i.resident===!0?["lifecycle"]:[],...i.model!==void 0?["model"]:[]]);const l=await J(a.meta,await Y(t));return l.roadmap_written=a.roadmapWritten,l.roadmap_ref=a.roadmapRef,l.goal_path=a.goalPath,{status:200,body:l}}d(Ft,"handlePromote");async function Bt(e,n={}){const t=e.params.id,o=await h(t),i=e.body??{};i.kind!==void 0&&await z(i.kind,o.cwd,o.profile_id??null),i.model!==void 0&&await ge(o,{kind:i.kind??o.kind,mode:i.promote===!0?"orchestrator":o.mode,lifecycle:o.lifecycle,model:i.model},n.modelRegistry);const a=i.note??"Refresh: continue against your roadmap or goal.";await _n(t,a);const l=await mn(t,{...i.promote===!0?{promote:!0}:{},...i.kind!==void 0?{kind:i.kind}:{},...i.model!==void 0?{model:i.model}:{}});return{status:200,body:await J(l.meta,await Y(t))}}d(Bt,"handleYield");async function Kt(e){const n=e.params.id;await h(n);const t=e.body;if(t===void 0||typeof t.controller!="string"||t.controller.trim()==="")throw m("a wait requires a controller node id");const o=await R(t.controller);if(o===null)throw E(`unknown controller: ${t.controller}`,{received:t.controller});if(o.status!=="active"&&o.status!=="idle")throw new p(422,"unprocessable",`controller ${t.controller} is ${o.status}`);return await xe(n,t.controller),{status:200,body:await b(n)}}d(Kt,"handleWait");async function Vt(e){const n=e.principal,t=await fn(n.class==="broker"?async i=>i.grantee===n.app&&await U(n,i.node_id,i.grantee):void 0);return{status:200,body:{revived:[...t.revived],failed:[...t.failed],frozen:[...t.frozen]}}}d(Vt,"handleReviveAll");const Wt=new Set(["interrupt","steer","after-turn","next-turn"]);function xt(e){if(e===null)return null;const n=d(o=>{throw new y({error:"invalid_listen",message:o,received:e,field:"listen",next:'Send an object mapping levels "1".."10" to interrupt|steer|after-turn|next-turn (e.g. {"3":"next-turn"}), or null to reset to the global default.'})},"bad");if(typeof e!="object"||Array.isArray(e))return n("listen must be an object or null");const t=Object.entries(e);if(t.length===0)return n("listen must name at least one level");for(const[o,i]of t)/^(?:[1-9]|10)$/.test(o)||n(`listen level must be 1..10: ${o}`),(typeof i!="string"||!Wt.has(i))&&n(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(i)}`);return JSON.stringify(Object.fromEntries(t))}d(xt,"listenJson");async function $(e,n,t,o){t.length===0&&o===void 0||await V(async i=>{if(o?.(i),t.length===0)return;const a=await Je(i,n),l=await He(i,e),c=l.class==="person"?l.person:l.class==="app"?l.app:l.node;await Ue(i,c,a),await Ye(i,{event:"configured",object:a,actor:c,attrs:{changed:t.join(",")}})})}d($,"recordConfigured");function ve(e){const n=P().get(e);if(n===void 0)return!1;try{return process.kill(n.pid,"SIGTERM"),!0}catch{return!1}}d(ve,"restartLiveBroker");function ke(e,n){try{return q(e)===q(n)}catch{return!1}}d(ke,"sameDirectory");async function zt(e,n={}){const t=e.params.id,o=e.body;let i;if(o===void 0)i={};else if(typeof o=="object"&&o!==null&&!Array.isArray(o))i=o;else throw new y({error:"cwd_invalid",message:"cwd repair requires a non-null object with a non-empty cwd string",received:o,field:"cwd",next:"Send a config patch with a non-empty absolute cwd string."});if(i.profile!==void 0){if(typeof i.profile!="string"||i.profile==="")throw new y({error:"profile_invalid",message:"profile must be a non-empty profile id or name",received:i.profile,field:"profile",next:"Send a profile id or exact name."});if(Object.keys(i).some(w=>w!=="profile"&&w!=="restart"&&i[w]!==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 r=await h(t),s=await Kn(e,i.profile);Vn(s.profileId);const f=Wn(s.profileId).manifest.grantee??"app:terminal";if(f!==(r.grantee??"app:terminal"))throw new y({error:"profile_grantee_mismatch",message:`profile ${s.profileId} belongs to ${f}, node ${t} to ${r.grantee}`,received:i.profile,field:"profile",next:"Pick a profile owned by the same app as the node."});return(r.profile_id??null)!==s.profileId&&(Gn(r.kind)?(await z(r.kind,r.cwd,s.profileId),await x(t,{profileId:s.profileId})):await C(t,{profile_id:s.profileId}),await $(e,t,["profile"])),i.restart===!0&&ve(t),{status:200,body:await b(t)}}if(Object.prototype.hasOwnProperty.call(i,"cwd")){const r=i.cwd;if(typeof r!="string"||r==="")throw new y({error:"cwd_invalid",message:"cwd must be a non-empty string",received:r,field:"cwd",next:"Send a non-empty absolute cwd string."});if(Object.keys(i).some(u=>u!=="cwd"&&u!=="keep_session"&&u!=="restart"&&i[u]!==void 0))throw new y({error:"cwd_not_exclusive",message:"cwd repair cannot be combined with another config field",received:i,field:"cwd",next:"Send cwd as the only config field."});const s=await h(t),f=N(s.cwd);if(i.keep_session===!0||f&&F(r)&&N(r)&&ke(s.cwd,r)){if(!F(r))throw new y({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${r}`,received:r,field:"cwd",next:"Send an absolute path."});const u=T(r);let k=!1;try{k=ee(u).isDirectory()}catch{}if(!k)throw new y({error:"cwd_missing",message:`cwd is not an existing directory: ${u}`,received:r,field:"cwd",next:"Send an existing absolute directory."});if(f&&!ke(s.cwd,u))throw new y({error:"cwd_not_same_directory",message:`${u} is not the same directory as the recorded ${s.cwd}; --keep-session only relocates an alias`,received:r,field:"cwd",next:"Drop --keep-session to repair a gone cwd, or pass the real path of the recorded directory."});if(s.managed_worktree?.state==="open")throw new y({error:"cwd_node_managed_worktree_open",message:`${t} owns an open managed worktree and cannot relocate its cwd`,received:r,field:"cwd",next:"Reconcile the managed worktree first."});const _=s.cwd;return _!==u&&(await V(async g=>{await C(t,{cwd:u}),await g.prepare("UPDATE crons SET cwd = ? WHERE anchor_node = ? AND cwd = ?").run(u,t,_),await Qe(t,_,u)}),await $(e,t,["cwd"])),i.restart===!0&&ve(t),{status:200,body:await b(t)}}if(P().has(t)){const u=`${t} cannot repair its cwd while its broker is live`;throw new p(409,"cwd_node_live",u,{error:"cwd_node_live",message:u,received:r,field:"cwd",next:"Let the node become dormant, then retry the cwd repair."})}if(s.fork_from!=null)throw new y({error:"cwd_node_forked",message:`${t} is a fork and cannot repair its cwd; recorded cwd: ${s.cwd}`,received:r,field:"cwd",next:`Restore ${s.cwd}, then revive the fork normally.`});if(s.managed_worktree?.state==="open")throw new y({error:"cwd_node_managed_worktree_open",message:`${t} owns an open managed worktree and cannot repair its cwd`,received:r,field:"cwd",next:"Restore or reconcile the recorded checkout, then use the managed-worktree close or abandon flow."});if(N(s.cwd))throw new y({error:"cwd_still_present",message:`${t} recorded cwd still exists: ${s.cwd}; cwd repair is not a relocation command`,received:r,field:"cwd",next:"This command only repairs a node whose recorded cwd is gone."});if(!F(r))throw new y({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${r}`,received:r,field:"cwd",next:"Send an absolute path."});const w=T(r);if(!N(w))throw new y({error:"cwd_missing",message:`cwd does not exist: ${w}`,received:r,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."});try{if(!ee(w).isDirectory())throw new y({error:"cwd_not_a_directory",message:`cwd is not a directory: ${w}`,received:r,field:"cwd",next:"Send an existing absolute directory."})}catch(u){throw u instanceof y?u:new y({error:"cwd_missing",message:`cwd does not exist: ${w}`,received:r,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."})}return await V(async()=>{await C(t,{cwd:w}),await Xe(t)}),await $(e,t,["cwd"]),{status:200,body:await b(t)}}let a=await h(t);const l=i.listen===void 0?void 0:xt(i.listen);if(i.scopes!==void 0){const r=pe(i.scopes),s=a.grantee==="app:terminal"?await at():a.grant_id?await ot(a.grant_id):null;if(!r.every(f=>O(a.scopes,f)&&s!==null&&O(s.resolved,f)))throw new y({error:"unknown_scope",message:"scopes may only narrow the node's current effective set",received:r,field:"scopes",next:"Send only scopes the node currently holds."});if(r.includes("crtr:act")&&!O(r,"crtr:llm"))throw new p(400,"invalid_scope","crtr:act requires crtr:llm");a=await C(t,{scopes:r})}if(i.situational_context!==void 0&&$e(t,Ce(i.situational_context)),i.model!==void 0){const r=(await de(a.cwd,a.profile_id??null)).modelLadders,s=Rn(i.model,r),f=await dt(a.grant_id,i.model,s===void 0),w=f?{family:st,strength:f.strength}:s,u=f?f.model:In(i.model,r);await K({kind:"concrete",spec:u},{cwd:a.cwd,profileId:a.profile_id??null},n.modelRegistry);const k=P();let _=!1;if(k.isClaimed(t)&&await se(t,k.get(t)?.handle.exited)&&(_=await $n(t,u,w).then(()=>!0,g=>{if(g instanceof Cn)return!1;throw g})),!_){if(k.isClaimed(t)){const g=`${t}'s broker did not accept the model switch; the model was not changed`;throw new p(409,"broker_not_ready",g,{error:"broker_not_ready",message:g,received:i.model,field:"model",next:"Check the node with `crtr node show`, then retry the model change."})}if(!u.includes("/"))throw m(`model must resolve to a provider/id spec: ${i.model}`);await An(t,u,w)}a=await h(t)}if(i.kind!==void 0||i.mode!==void 0||i.lifecycle!==void 0){i.kind!==void 0&&await Re(i.kind);const r=i.kind??a.kind,s=i.mode??a.mode,f=i.lifecycle??a.lifecycle;let w;s==="orchestrator"&&!await vn(t)&&(w=d(async()=>{const u=await gn(t);await bn(t,u!==null&&u.trim()!==""?{goal:u.trim()}:{})},"beforePersist")),a=await x(t,{...i.kind!==void 0?{kind:r}:{},...i.mode!==void 0?{mode:s}:{},...i.lifecycle!==void 0?{lifecycle:f}:{}},w)}i.name!==void 0&&(a=await C(t,{name:i.name}),a.window&&kn(a.window,Bn(a)));const c=["scopes","situational_context","model","kind","mode","lifecycle","name","listen"].filter(r=>i[r]!==void 0);return await $(e,t,c,l===void 0?void 0:async r=>{await r.prepare("UPDATE objects SET listen_json = ? WHERE id = ? AND type = 'node'").run(l,t)}),{status:200,body:await b(t)}}d(zt,"handleConfig");async function Se(){return(await de(process.cwd(),Oe()||null)).kinds}d(Se,"daemonKinds");async function Re(e){const n=Object.keys(await Se());if(!n.includes(e))throw m(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${n.sort().join(", ")}.`})}d(Re,"assertKindServer");async function Jt(){const e=await Se();return{status:200,body:{kinds:Object.keys(e).sort().map(t=>({kind:t,when_to_use:e[t]?.whenToUse??null,available_to:e[t]?.availableTo??null}))}}}d(Jt,"handleListKinds");const uo=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:_t},{method:"GET",pattern:"/v1/nodes",handler:vt},{method:"GET",pattern:"/v1/kinds",handler:d(()=>Jt(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:Vt},{method:"GET",pattern:"/v1/nodes/:id",handler:kt},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:St},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:Rt},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:Ot},{method:"GET",pattern:"/v1/nodes/:id/session",handler:At},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:$t},{method:"GET",pattern:"/v1/nodes/:id/context",handler:Ct},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:Tt},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:Et},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:Dt},{method:"POST",pattern:"/v1/nodes/:id/close",handler:Lt},{method:"POST",pattern:"/v1/nodes/:id/read",handler:Mt},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:jt},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:Gt},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:Ft},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Bt},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Kt},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:zt}];export{zt as handleConfig,_t as handleCreate,Tt as handleFork,vt as handleList,Ft as handlePromote,Bt as handleYield,uo as nodeRoutes,mo as resolveCreateKind};
|
|
1
|
+
var Se=Object.defineProperty;var s=(e,n)=>Se(e,"name",{value:n,configurable:!0});import{envProfileId as Re}from"../../../shared/env.js";import{pausedCanvasProfiles as Ie}from"../../../core/profiles/manifest.js";import{existsSync as C,realpathSync as q,statSync as ee}from"node:fs";import{isAbsolute as B,resolve as T}from"node:path";import{appendSituationalContext as Oe,formatSituationalProse as Ae}from"../../../core/runtime/situational-context.js";import{closeNode as $e}from"../../../core/runtime/close.js";import{reviveNode as Ne}from"../../../core/runtime/revive.js";import{nowIso as K}from"../../../core/fs-utils.js";import{appPaidLaunch as Ce,assertLaunchModelRegistered as V,forkNode as Te,resolveForkSource as Pe,spawnChildPrepared as Ee}from"../../../core/runtime/spawn.js";import{forkSourceNode as De,newNodeId as ne}from"../../../core/runtime/nodes.js";import{abandonCreateRequest as te,childrenOf as Le,completeCreateRequest as ie,findCreateRequest as je,getNode as R,recordCreateRequestNode as Me,reserveCreateRequest as oe,reserveCreateRequestNode as Ge,listNodes as Fe,recordRespawnAttempt as Be,subscribersOf as Ke,subscriptionsOf as re,updateNode as N}from"../../../core/canvas/canvas.js";import{armControllerWait as Ve}from"../../../core/canvas/waits.js";import{withCanvasWrite as W}from"../../../core/canvas/db.js";import{markNodeRead as We}from"../../../core/canvas/recovery.js";import{nodeObject as xe}from"../../../core/graph/objects.js";import{recordActedOn as ze}from"../../../core/graph/edges.js";import{publish as Je}from"../../../core/graph/events.js";import{readerFor as Ue}from"../reader.js";import{relocateSessionCwd as Ye,unbindSession as He}from"../../../core/canvas/sessions.js";import{ticketCountsForNodes as Qe}from"../../../core/canvas/attention.js";import{isSafeNodeId as Xe}from"../../../core/canvas/paths.js";import{contextDir as ae,nodeAgentDir as x}from"../../../core/canvas/node-agent-paths.js";import{checkCronBirth as Ze}from"../../cron/authority.js";import{cronBirthPlacement as qe}from"../../cron/armed-context.js";import{existsBeneath as en,isAbsentOrRefused as nn,isBeneathRefusal as tn,readdirBeneath as on}from"../../../core/spaces/open-beneath.js";import{readNodeMessagesPage as rn,readNodeSession as an,readNodeSnapshot as dn,transcriptMarkdown as sn}from"../../../core/runtime/node-read.js";import{assembleNodeSubject as ln}from"../../../core/substrate/subject.js";import{reviveAll as cn}from"../../../core/runtime/revive-all.js";import{promoteAsync as un,requestYieldAsync as fn,reshapeNodeAsync as z}from"../../../core/runtime/promote.js";import{recycleNode as pn}from"../../../core/runtime/recycle.js";import{relaunchRoot as mn}from"../../../core/runtime/reset.js";import{assertReopenGate as wn}from"../../../core/runtime/reopen.js";import{writeYieldMessage as hn,readGoal as yn}from"../../../core/runtime/kickoff.js";import{ensureRoadmap as _n,hasRoadmap as gn}from"../../../core/runtime/roadmap.js";import{renameWindow as bn}from"../../../core/runtime/placement.js";import{buildLaunchSpecAsync as vn,explicitModelIntent as kn,normalizeModel as Sn,readMergedLaunchConfigAsync as de}from"../../../core/runtime/launch.js";import{modelRequestFromConfig as Rn}from"../../../core/model-routes.js";import{persistDormantModel as In,setModelLive as On}from"../../../core/runtime/model-swap.js";import{waitForBrokerViewSocket as se}from"../../../core/runtime/view-socket.js";import{BrokerUnreachableError as An}from"../../../core/runtime/broker-request.js";import{boundFleet as P}from"../../../core/runtime/fleet.js";import{admitLegacyStructuredOutput as $n}from"../../structured-requests/sidecar.js";import{assertOutputSchemaAccepted as Nn}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 Tn}from"../../../core/human-actions.js";import{parseDurationMs as Pn}from"../../../core/wake.js";import{claimWarmNode as En,refillWarmPool as ce,resumeWarmClaim as Dn,warmPoolEnabled as Ln}from"../../../core/runtime/warm-pool.js";import{assertLaunchKind as J,isLaunchKind as jn,resolveLaunchTarget as Mn}from"../../../core/runtime/launch-target.js";import{fullName as Gn}from"../../../core/canvas/labels.js";import{reportsForNode as ue}from"./reports.js";import{requireUsableProfile as Fn}from"./profiles.js";import{assertProfileActive as Bn,loadExactProfileManifest as Kn}from"../../../core/profiles/manifest.js";import{getCron as fe}from"../../../core/canvas/crons.js";import{cronWakeOrigin as Vn}from"../../../core/runtime/bearings.js";import{boundDaemonControl as Wn}from"../../control.js";import{notFound as E,usage as m}from"../../../core/errors.js";import{assertScope as xn,validateScopes as pe}from"../../../core/scopes.js";import{scopeAllowed as O}from"../../../shared/env.js";import{toCloseResultDTO as zn,toNodeDetailDTO as U,toNodeSummaryDTO as Jn,toReviveResultDTO as Un}from"../map.js";import{ApiError as p}from"../../../api/index.js";import{InputError as y}from"../../../core/io.js";import{actsAsPerson as Yn,canReadNode as D,readableNodeIds as Hn,resolvedScopes as Qn}from"../router.js";import{forwardVerb as Xn,queryWithoutMachine as Zn,relayError as qn,unknownError as et,withMachine as nt}from"../../peer/forward.js";import{fileRoot as tt}from"../../../core/spaces/file-root.js";import{activeGrant as it,payerOfGrant as ot,terminalGrant as rt}from"../../../core/grants/mirror.js";import{appRungForGrant as at}from"../../../core/llm/app-rungs.js";import{APP_FAMILY as dt}from"../../../core/model-routes.js";import{hasConfiguredProviderCredential as st,NO_PROVIDER_CREDENTIAL_MESSAGE as me}from"../../../core/runtime/provider-credential-gate.js";import{filterAsync as lt,mapAsync as we}from"../../../core/async-array.js";async function h(e){const n=await R(e);if(n===null)throw E(`unknown node: ${e}`,{received:e});return n}s(h,"requireMeta");async function Y(e){return{subscribesTo:await re(e),subscribers:await Ke(e),children:await Le(e)}}s(Y,"edgesFor");async function b(e){const n=await h(e);return await U(n,await Y(e))}s(b,"detailOf");async function ct(e){let n=(await ue(e)).length;try{n+=on(await x(e),await ae(e)).length}catch(t){if(!nn(t))throw t}return n}s(ct,"countFiles");function ut(e){if(typeof e!="object"||e===null)throw m("a node create requires a JSON body");const n=e;if(n.kind!==void 0&&(typeof n.kind!="string"||n.kind.trim()===""))throw m("kind must be a non-empty string when provided");if(n.description!==void 0&&(typeof n.description!="string"||n.description.trim()===""))throw m("description must be a non-empty string when provided");if(n.creator!==void 0&&(typeof n.creator!="string"||n.creator.trim()===""))throw m("creator must be a non-empty node id when provided");if(n.scopes!==void 0&&pe(n.scopes),n.isolated!==void 0&&typeof n.isolated!="boolean")throw new p(400,"invalid_request","isolated must be a boolean",{param:"isolated"});const t=n.root_lifecycle;if(t!==void 0&&t!=="resident"&&t!=="terminal")throw m("root_lifecycle must be 'resident' or 'terminal'");if(n.request_key!==void 0&&(typeof n.request_key!="string"||n.request_key.trim()===""||n.request_key.length>128))throw m("request_key must be a non-empty string of at most 128 characters when provided");return n}s(ut,"parseCreateBody");function ft(e){if(e===void 0)return;const n=Pn(e),t=n===null?null:new Date(Date.now()+n);if(n===null||!Number.isFinite(n)||n<=0||t===null||!Number.isFinite(t.getTime()))throw new p(422,"invalid_deadline","`deadline` must be a positive representable duration");return t.toISOString()}s(ft,"parseDeadline");function pt(e){if(e!==void 0){if(typeof e!="object"||e===null||Array.isArray(e))throw new p(400,"invalid_request","`outcome_delivery` must be an object");if(typeof e.action!="string"||!Cn.test(e.action))throw new p(400,"invalid_request","`outcome_delivery.action` must be a declared action name");if(e.payload!==void 0){let n;try{n=JSON.stringify(e.payload)}catch{throw new p(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable")}if(n===void 0)throw new p(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable");if(Buffer.byteLength(n,"utf8")>le)throw new p(413,"payload_too_large",`serialized payload exceeds ${le} bytes`)}return e}}s(pt,"parseOutcomeDelivery");function mt(e,n){const t=Tn(e.action,n);if(!("kind"in t))return{actionName:e.action,argv:t.argv,cwd:t.cwd,configOrigin:t.configOrigin,...e.payload===void 0?{}:{payload:e.payload}};throw t.kind==="unknown_action"?new p(422,"unknown_action",`no action named ${e.action} is declared from ${n}`):new p(422,"invalid_action",`${e.action} is declared in ${t.configOrigin} but unusable: ${t.reason}`,{reason:t.reason,configOrigin:t.configOrigin})}s(mt,"resolveOutcomeDelivery");function wt(e,n,t){const o={kind:e.kind,cwd:t,prompt:e.prompt??""};return e.mode!==void 0&&(o.mode=e.mode),e.name!==void 0&&(o.name=e.name),e.description!==void 0&&(o.description=e.description),n!==void 0&&(o.parent=n),e.creator!==void 0&&(o.creator=e.creator),e.scopes!==void 0&&(o.scopes=e.scopes),e.isolated!==void 0&&(o.isolated=e.isolated),e.root===!0&&(o.root=!0),e.root_lifecycle!==void 0&&(o.rootLifecycle=e.root_lifecycle),(e.worktree===!0||typeof e.worktree=="string")&&(o.worktree=!0),typeof e.worktree=="string"&&(o.worktreeBase=e.worktree),e.worktree!==void 0&&(o.worktreeCwd=T(e.pin_cwd??e.cwd??t)),e.fork_from!==void 0&&(o.forkFrom=e.fork_from),e.model!==void 0&&(o.model=e.model),e.profile!==void 0&&(o.profile=e.profile),e.situational_context!==void 0&&(o.situationalContext=e.situational_context),e.node_id!==void 0&&(o.nodeId=e.node_id),o}s(wt,"buildRecipe");function ht(e,n,t){return!Ln()||e.prefer_warm!==!0||e.root!==!0||e.parent!=null||e.root_lifecycle==="terminal"||(e.prompt??"")!==""||e.model!==void 0||e.fork_from!==void 0||e.worktree!==void 0||e.node_id!==void 0||e.scopes!==void 0||e.isolated!==void 0?null:{kind:e.kind,mode:e.mode??"base",cwd:n,profileId:t,model:e.model??null,situationalContext:e.situational_context??null,name:e.name??null,creator:e.creator??null}}s(ht,"warmRequestFor");import{resolveCreateKind as mo}from"../../../core/runtime/launch-target.js";function he(e){const n=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return Rn(e.model,n,e.modelExact===!0)}s(he,"requestFromLaunch");function yt(e,n){if(n===null)return e;if(e.scopes===void 0)return{...e,scopes:[...n]};const t=e.scopes.filter(o=>!O(n,o));if(t.length===0)return e;throw new p(403,"scope_denied",`scopes exceed the bearer token's ceiling: ${t.join(", ")}`,{scopes:t,ceiling:n})}s(yt,"withinCeiling");async function ye(e,n,t){const o=(await vn(n.kind,n.mode,{lifecycle:n.lifecycle,hasManager:e.parent!==null,model:n.model,modelOverride:!0,cwd:e.cwd,profileId:e.profile_id??null})).launch;await V(he(o),{cwd:e.cwd,profileId:e.profile_id??null},t)}s(ye,"assertNodeModelChangeRegistered");async function _e(e,n){const t=e.principal;if(t.class!=="broker"&&t.class!=="cron")return;const o=tt({app:t.app,resolved:await Qn(t),launched:t.scopes},n,"read");if("root"in o)return;const i="missing"in o?o.missing:null;throw new p(403,"scope_missing",i?`the child's directory ${n} needs missing scope ${i}`:`no permission of this run names the child's directory ${n}`,void 0,void 0,i?{scope:i}:void 0)}s(_e,"assertCallerReaches");const H=new Map;async function _t(e,n={},t={}){const o=yt(ut(e.body),e.ceiling);if(e.principal.class==="broker"){const d=e.principal;if(o.prefer_warm===!0&&d.app!=="app:terminal"&&(o.prefer_warm=!1),o.parent!=null){const r=await h(o.parent);if(r.grantee!==d.app)throw new p(403,"other_app_run","cannot create a child under another app's node");if(!await D(d,r.grantee??"app:terminal",o.parent))throw E(`unknown node: ${o.parent}`,{received:o.parent})}if(o.creator!==void 0&&o.creator!==d.node)throw new p(403,"other_app_run","cannot create for another node");if(o.fork_from!==void 0){let r=null;try{r=await De(await Pe(o.fork_from))}catch{}if(r?.grantee!==d.app||!await D(d,r.grantee,r.node_id))throw new p(403,"other_app_run","cannot fork another app's conversation")}o.creator=d.node}if(e.principal.class==="cron"){const d=e.principal;for(const l of["parent","creator","fork_from","node_id"])if(o[l]!=null)throw new p(403,"permission_error",`a cron cannot set ${l} on a node it starts`);o.prefer_warm=!1;const r=await Ze({grantee:d.app,sub:d.sub,grant_id:d.grant,scopes:d.scopes});if(!r.allowed)throw new p(r.reason==="scope_missing"?403:401,r.reason==="scope_missing"?"scope_missing":"grant_revoked",r.message);if(o.scopes!==void 0){const l=o.scopes.find(f=>!O(r.effectiveScopes,f)||!O(d.scopes,f));if(l!==void 0)throw new p(403,"scope_missing",`scope ${l} is not held by this cron`,void 0,void 0,{scope:l})}else d.scopes!==null&&(o.scopes=[...d.scopes]);o.node_id=await ne(),d.isolated&&(o.isolated=!0,o.cwd=await x(o.node_id,d.app))}o.creator!==void 0&&xn(await h(o.creator),"crtr:act");const i=o.request_key?.trim();if(i===void 0||o.node_id!==void 0&&Xe(o.node_id)&&await R(o.node_id)!==null&&(await je(i))?.nodeId!==o.node_id)return L(e,o,n,t);const a=H.get(i);if(a!==void 0)return a;const u=gt(e,o,i,n,t);H.set(i,u);try{return await u}finally{H.delete(i)}}s(_t,"handleCreate");async function gt(e,n,t,o,i){const a=await oe(t);if(a.nodeId!==null&&await R(a.nodeId)!==null){if(a.state!=="warm_claimed"){const u=await R(a.nodeId);if(e.principal.class!=="person"&&!await D(e.principal,u.grantee??"app:terminal",a.nodeId))throw new p(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:await b(a.nodeId)}}return L(e,n,o,i,a)}try{return await L(e,n,o,i,a)}catch(u){const d=await oe(t);throw(d.nodeId===null||await R(d.nodeId)===null)&&await te(t,d.nodeId),u}}s(gt,"handleKeyedCreateRequest");async function L(e,n,t,o,i=void 0){const a=o.deadlineAt??ft(n.deadline),u=pt(n.outcome_delivery),d=e.principal.class==="cron"?await qe({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:(await fe(e.principal.cron))?.created_by??null},n.node_id):null;d!==null&&(n.root=d.root===!0);const r=d?.parent??n.parent??void 0;if(r==null&&n.root!==!0)throw m("a node create requires a parent (or root: true for an independent root)");let l=null;if(n.output_schema!==void 0){try{l=JSON.parse(n.output_schema)}catch{throw m("output_schema must be a JSON schema string")}if(l===null||typeof l!="object"||Array.isArray(l))throw m("output_schema must be a JSON schema object");await Nn(l)}const{profileId:f,kind:w,cwd:c,launch:k}=await Mn(n,{validateKind:ke});await _e(e,c),n.worktree!==void 0&&await _e(e,T(n.pin_cwd??n.cwd??c));const _={...n,kind:w},g=u===void 0?void 0:mt(u,c),X=("grant"in e.principal?e.principal.grant:null)??(r==null?null:(await R(r))?.grant_id??null);if(await V(he(await Ce(k,X,n.model)),{cwd:c,profileId:f},t.modelRegistry),await ot(X)!=="app"&&!await st(f))throw new p(412,"no_provider_credential",me,{error:"no_provider_credential",message:me,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=i===void 0||i.nodeId===null||i.state==="warm_claimed"?ht(_,c,f):null,G=l===null&&o.beforeBrokerLaunch===void 0?void 0:async S=>{l!==null&&await $n(S,"terminal",l),o.beforeBrokerLaunch?.(S)};if(i?.state==="warm_claimed"&&i.nodeId!==null){const S=A===null?null:await Dn(A,i.nodeId,G);if(S===null)throw await te(i.requestKey,i.nodeId),new p(503,"create_resume_failed",`could not resume warm claim ${i.nodeId}; retry the create`);return await ie(i.requestKey,S),{status:201,body:await b(S)}}if(A!==null){const S=await En(A,{...a===void 0?{}:{deadlineAt:a},...g===void 0?{}:{outcomeDelivery:g},...i===void 0?{}:{requestKey:i.requestKey}},G);if(S!==null)return i!==void 0&&await ie(i.requestKey,S),ce(A),{status:201,body:await b(S)};M=A}const F=i?.nodeId??n.node_id??(i===void 0?void 0:await ne());i!==void 0&&i.nodeId===null&&await Ge(i.requestKey,F);const I=wt(F===void 0?_:{..._,node_id:F},r,c);d!==null&&(d.rootLifecycle!==void 0&&(I.rootLifecycle=d.rootLifecycle),d.scopes!==void 0&&_.scopes===void 0&&(I.scopes=d.scopes),d.run!==void 0&&(I.run=d.run),d.withinCreate!==void 0&&(I.withinCreate=d.withinCreate)),a!==void 0&&(I.deadlineAt=a),g!==void 0&&(I.outcomeDelivery=g),I.readiness=n.root===!0?"await":"launch";const Z=await Ee(I,G,()=>{M!==null&&ce(M)});return i!==void 0&&await Me(i.requestKey,Z.node.node_id),{status:201,body:await b(Z.node.node_id)}}}s(L,"handleCreateRequest");function v(e,n){const t=e.query.getAll(n);if(t.length>1)throw m(`${n} must appear at most once`);return t[0]}s(v,"singleQueryValue");function Q(e,n){if(e!==void 0){if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;throw m(`${n} must be true or false`)}}s(Q,"optionalBoolean");function j(e,n,t){if(e!==void 0){if(t.includes(e))return e;throw m(`${n} must be one of: ${t.join(", ")}`)}}s(j,"oneOf");function bt(e){const n=new Set(["status","lifecycle","kind","mode","profile_id","profile_prefix","parent","top_level","under","under_inclusive","hanging","include"]);for(const[_]of e.query)if(!n.has(_))throw m(`unknown nodes query parameter: ${_}`);const t=j(v(e,"status"),"status",["active","idle","done","dead","canceled"]),o=j(v(e,"lifecycle"),"lifecycle",["terminal","resident"]),i=v(e,"kind"),a=j(v(e,"mode"),"mode",["base","orchestrator"]),u=v(e,"profile_id"),d=v(e,"profile_prefix"),r=v(e,"parent"),l=Q(v(e,"top_level"),"top_level"),f=v(e,"under"),w=Q(v(e,"under_inclusive"),"under_inclusive"),c=Q(v(e,"hanging"),"hanging"),k=j(v(e,"include"),"include",["activity"]);if(r!==void 0&&l===!0)throw m("parent and top_level=true cannot be combined");return{...t!==void 0?{status:t}:{},...o!==void 0?{lifecycle:o}:{},...i!==void 0?{kind:i}:{},...a!==void 0?{mode:a}:{},...u!==void 0?{profile_id:u}:{},...d!==void 0?{profile_prefix:d}:{},...r!==void 0?{parent:r}:{},...l!==void 0?{top_level:l}:{},...f!==void 0?{under:f}:{},...w!==void 0?{under_inclusive:w}:{},...c!==void 0?{hanging:c}:{},...k!==void 0?{include:k}:{}}}s(bt,"parseListQuery");async function vt(e){const n=bt(e);let t=await Fe({...n.status!==void 0?{status:n.status}:{},...n.lifecycle!==void 0?{lifecycle:n.lifecycle}:{},...n.kind!==void 0?{kind:n.kind}:{},...n.mode!==void 0?{mode:n.mode}:{},...n.profile_id!==void 0?{profileId:n.profile_id}:{},...n.profile_prefix!==void 0?{profilePrefix:n.profile_prefix}:{},...n.parent!==void 0?{parent:n.parent}:{},...n.top_level===!0?{topLevel:!0}:{},...n.under!==void 0?{under:n.under}:{},...n.under_inclusive===!0?{underInclusive:!0}:{},...n.hanging===!0?{hanging:!0}:{}});const o=await Hn(e.principal);o!==null&&(t=t.filter(d=>o.has(d.node_id)));const i=n.include==="activity"?await Qe(t.map(d=>d.node_id)):null,a=t.length>0?Ie():new Set;return{status:200,body:await we(t,async d=>{const r=await Jn(d,d.profile_id!==null&&a.has(d.profile_id));if(i!==null){const l=await ue(d.node_id);r.activity={latest_report:l[0]??null,final_report:d.final_report===null?null:l.find(f=>f.name===d.final_report)??null,pending_human_count:i[d.node_id]??0}}return r})}}s(vt,"handleList");async function kt(e){const n=e.params.id,t=await Xn(e,n,{method:"GET",path:`/v1/nodes/${encodeURIComponent(n)}`,query:Zn(e)});if(t.kind==="unknown")throw et(n,t.unreachable);if(t.kind==="remote"){if(t.status>=400)throw qn(t.status,t.body);return{status:t.status,body:nt(t.body,t.machine)}}return await h(n),{status:200,body:await b(n)}}s(kt,"handleDetail");async function St(e){const n=e.params.id;await h(n);const t=await dn(n);return{status:200,body:{node_id:n,snapshot:{messages:t.snapshot.messages,...t.snapshot.messageIds===void 0?{}:{messageIds:t.snapshot.messageIds},messageVisibility:t.snapshot.messageVisibility,turnVisibility:t.snapshot.turnVisibility,stats:t.snapshot.stats,state:t.snapshot.state,display:t.snapshot.display,...t.snapshot.queued===void 0?{}:{queued:t.snapshot.queued},...t.snapshot.toolGroupSummaries===void 0?{}:{toolGroupSummaries:t.snapshot.toolGroupSummaries},...t.snapshot.turnReplies===void 0?{}:{turnReplies:t.snapshot.turnReplies},...t.snapshot.workingActivity===void 0?{}:{workingActivity:t.snapshot.workingActivity}},commands:t.commands.map(i=>({name:i.name,description:i.description,source:i.source})),captured_at:K()}}}s(St,"handleSnapshot");async function Rt(e){const n=e.params.id,t=await ln(n);if(t===null)throw E(`unknown node: ${n}`,{received:n});return{status:200,body:t}}s(Rt,"handleSubject");function It(e){for(const[a]of e.query)if(a!=="cursor"&&a!=="limit")throw m(`unknown messages query parameter: ${a}`);const n=e.query.getAll("cursor"),t=e.query.getAll("limit");if(n.length>1)throw m("cursor must appear at most once");if(t.length>1)throw m("limit must appear at most once");if(t.length===0)return n.length===0?{}:{cursor:n[0]};const o=t[0],i=Number(o);if(!Number.isSafeInteger(i)||o==="")throw m("limit must be an integer from 1 through 500");return n.length===0?{limit:i}:{cursor:n[0],limit:i}}s(It,"parseMessagesQuery");async function Ot(e){const n=e.params.id,t=await rn(n,It(e));return{status:200,body:{node_id:n,messages:t.messages,...t.messageIds===void 0?{}:{message_ids:t.messageIds},message_visibility:t.messageVisibility,next_cursor:t.nextCursor,captured_at:K()}}}s(Ot,"handleMessages");async function At(e){const n=e.params.id;await h(n);const t=await an(n);return{status:200,body:{node_id:n,session_file:t.sessionFile,session_jsonl:t.sessionJsonl,system_prompt:t.systemPrompt,captured_at:K()}}}s(At,"handleSession");async function $t(e){const n=e.params.id;return await h(n),{status:200,body:{node_id:n,markdown:await sn(n)}}}s($t,"handleTranscript");async function Nt(e){const n=e.params.id;await h(n);const t=s(async(i,a)=>({node_id:i,label:(await R(i))?.name??i,dir:await ae(i),self:a,files:await ct(i)}),"root"),o=await lt([await t(n,!0),...await we(await re(n),async i=>await t(i.node_id,!1))],async i=>await Ct(i.node_id,i.dir)||i.files>0);return{status:200,body:{node_id:n,roots:o}}}s(Nt,"handleContext");async function Ct(e,n){try{return en(await x(e),n)}catch(t){if(tn(t))return!1;throw t}}s(Ct,"hasDir");async function Tt(e){const n=await h(e.params.id),t=e.principal.class==="broker"?e.principal.scopes:e.ceiling,o=t===null?void 0:n.scopes==null?[...t]:[...new Set([...n.scopes.filter(a=>O(t,a)),...t.filter(a=>O(n.scopes,a))])],i=await Te(n.node_id,o,e.principal.class==="broker"?e.principal.node:void 0);return{status:201,body:await b(i.node.node_id)}}s(Tt,"handleFork");const Pt=1e4;async function Et(e){const n=e.params.id;await h(n);const t=e.body,o=t?.resume??!0,i=t?.reopen??!1;await wn(n,i,e.principal.class==="broker"?e.principal.node:null);const a=!o&&t?.cron_id!==void 0?await fe(t.cron_id):null,u=await Ne(n,{resume:o,capacity:"refuse",...a!==null?{wakeReason:await Vn(a,"schedule_revive")}:{}});u.outcome!=="already-live"&&await Be(n,{failures:0,notBefore:null});const d=(await R(n))?.status??"active",r=(u.launch??P().get(n)?.handle)?.exited,l=u.outcome!=="frozen"&&await se(n,r,Pt);return{status:200,body:Un(n,u,d,l)}}s(Et,"handleRevive");async function Dt(e){const n=e.params.id;return{status:200,body:{newNodeId:(await mn(n))?.newNodeId??null}}}s(Dt,"handleRelaunchRoot");async function Lt(e){const n=e.params.id;await h(n);const t=e.body;if(t?.caller_pid!==void 0&&(!Number.isInteger(t.caller_pid)||t.caller_pid<=0))throw m("caller_pid must be a positive integer when provided");const o=Wn(),i=new Promise(u=>{e.res.once("close",()=>u())}),a=await $e(n,{teardownAfter:i,rootEvent:t?.finish===!0?"finish":"cancel",callerPid:t?.caller_pid,...e.principal.class==="broker"?{closer:e.principal.node}:{},...o===null?{}:{registerDetached:o.registerDetached}});return{status:200,body:zn(a)}}s(Lt,"handleClose");async function jt(e){if(!Yn(e.principal))throw new p(403,"permission_error","only the person marks a conversation read");const n=e.params.id;return await h(n),await We(n),{status:204}}s(jt,"handleMarkRead");async function Mt(e){const n=e.params.id;await h(n);const t=await pn(n);return{status:200,body:{recycled:t.recycled,finalized:t.finalized,new_root:t.newRoot,delivered:t.delivered}}}s(Mt,"handleRecycle");async function Gt(e){const n=e.params.id;return await h(n),await z(n,{lifecycle:"terminal"}),await $(e,n,["lifecycle"]),{status:200,body:await b(n)}}s(Gt,"handleDemote");async function Ft(e,n={}){const t=e.params.id,o=await h(t),i=e.body??{};i.kind!==void 0&&await J(i.kind,o.cwd,o.profile_id??null),i.model!==void 0&&await ye(o,{kind:i.kind??o.kind,mode:"orchestrator",lifecycle:i.resident===!0?"resident":o.lifecycle,model:i.model},n.modelRegistry);const a=await un(t,{...i.kind!==void 0?{kind:i.kind}:{},...i.resident===!0?{resident:!0}:{},...i.model!==void 0?{model:i.model}:{}});await $(e,t,["mode",...i.kind!==void 0?["kind"]:[],...i.resident===!0?["lifecycle"]:[],...i.model!==void 0?["model"]:[]]);const u=await U(a.meta,await Y(t));return u.roadmap_written=a.roadmapWritten,u.roadmap_ref=a.roadmapRef,u.goal_path=a.goalPath,{status:200,body:u}}s(Ft,"handlePromote");async function Bt(e,n={}){const t=e.params.id,o=await h(t),i=e.body??{};i.kind!==void 0&&await J(i.kind,o.cwd,o.profile_id??null),i.model!==void 0&&await ye(o,{kind:i.kind??o.kind,mode:i.promote===!0?"orchestrator":o.mode,lifecycle:o.lifecycle,model:i.model},n.modelRegistry);const a=i.note??"Refresh: continue against your roadmap or goal.";await hn(t,a);const u=await fn(t,{...i.promote===!0?{promote:!0}:{},...i.kind!==void 0?{kind:i.kind}:{},...i.model!==void 0?{model:i.model}:{}});return{status:200,body:await U(u.meta,await Y(t))}}s(Bt,"handleYield");async function Kt(e){const n=e.params.id;await h(n);const t=e.body;if(t===void 0||typeof t.controller!="string"||t.controller.trim()==="")throw m("a wait requires a controller node id");const o=await R(t.controller);if(o===null)throw E(`unknown controller: ${t.controller}`,{received:t.controller});if(o.status!=="active"&&o.status!=="idle")throw new p(422,"unprocessable",`controller ${t.controller} is ${o.status}`);return await Ve(n,t.controller),{status:200,body:await b(n)}}s(Kt,"handleWait");async function Vt(e){const n=e.principal,t=await cn(n.class==="broker"?async i=>i.grantee===n.app&&await D(n,i.grantee,i.node_id):void 0);return{status:200,body:{revived:[...t.revived],failed:[...t.failed],frozen:[...t.frozen]}}}s(Vt,"handleReviveAll");const Wt=new Set(["interrupt","steer","after-turn","next-turn"]);function xt(e){if(e===null)return null;const n=s(o=>{throw new y({error:"invalid_listen",message:o,received:e,field:"listen",next:'Send an object mapping levels "1".."10" to interrupt|steer|after-turn|next-turn (e.g. {"3":"next-turn"}), or null to reset to the global default.'})},"bad");if(typeof e!="object"||Array.isArray(e))return n("listen must be an object or null");const t=Object.entries(e);if(t.length===0)return n("listen must name at least one level");for(const[o,i]of t)/^(?:[1-9]|10)$/.test(o)||n(`listen level must be 1..10: ${o}`),(typeof i!="string"||!Wt.has(i))&&n(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(i)}`);return JSON.stringify(Object.fromEntries(t))}s(xt,"listenJson");async function $(e,n,t,o){t.length===0&&o===void 0||await W(async i=>{if(o?.(i),t.length===0)return;const a=await xe(i,n),u=await Ue(i,e),d=u.class==="person"?u.person:u.class==="app"?u.app:u.node;await ze(i,d,a),await Je(i,{event:"configured",object:a,actor:d,attrs:{changed:t.join(",")}})})}s($,"recordConfigured");function ge(e){const n=P().get(e);if(n===void 0)return!1;try{return process.kill(n.pid,"SIGTERM"),!0}catch{return!1}}s(ge,"restartLiveBroker");function be(e,n){try{return q(e)===q(n)}catch{return!1}}s(be,"sameDirectory");async function zt(e,n={}){const t=e.params.id,o=e.body;let i;if(o===void 0)i={};else if(typeof o=="object"&&o!==null&&!Array.isArray(o))i=o;else throw new y({error:"cwd_invalid",message:"cwd repair requires a non-null object with a non-empty cwd string",received:o,field:"cwd",next:"Send a config patch with a non-empty absolute cwd string."});if(i.profile!==void 0){if(typeof i.profile!="string"||i.profile==="")throw new y({error:"profile_invalid",message:"profile must be a non-empty profile id or name",received:i.profile,field:"profile",next:"Send a profile id or exact name."});if(Object.keys(i).some(w=>w!=="profile"&&w!=="restart"&&i[w]!==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 r=await h(t),l=await Fn(e,i.profile);Bn(l.profileId);const f=Kn(l.profileId).manifest.grantee??"app:terminal";if(f!==(r.grantee??"app:terminal"))throw new y({error:"profile_grantee_mismatch",message:`profile ${l.profileId} belongs to ${f}, node ${t} to ${r.grantee}`,received:i.profile,field:"profile",next:"Pick a profile owned by the same app as the node."});return(r.profile_id??null)!==l.profileId&&(jn(r.kind)?(await J(r.kind,r.cwd,l.profileId),await z(t,{profileId:l.profileId})):await N(t,{profile_id:l.profileId}),await $(e,t,["profile"])),i.restart===!0&&ge(t),{status:200,body:await b(t)}}if(Object.prototype.hasOwnProperty.call(i,"cwd")){const r=i.cwd;if(typeof r!="string"||r==="")throw new y({error:"cwd_invalid",message:"cwd must be a non-empty string",received:r,field:"cwd",next:"Send a non-empty absolute cwd string."});if(Object.keys(i).some(c=>c!=="cwd"&&c!=="keep_session"&&c!=="restart"&&i[c]!==void 0))throw new y({error:"cwd_not_exclusive",message:"cwd repair cannot be combined with another config field",received:i,field:"cwd",next:"Send cwd as the only config field."});const l=await h(t),f=C(l.cwd);if(i.keep_session===!0||f&&B(r)&&C(r)&&be(l.cwd,r)){if(!B(r))throw new y({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${r}`,received:r,field:"cwd",next:"Send an absolute path."});const c=T(r);let k=!1;try{k=ee(c).isDirectory()}catch{}if(!k)throw new y({error:"cwd_missing",message:`cwd is not an existing directory: ${c}`,received:r,field:"cwd",next:"Send an existing absolute directory."});if(f&&!be(l.cwd,c))throw new y({error:"cwd_not_same_directory",message:`${c} is not the same directory as the recorded ${l.cwd}; --keep-session only relocates an alias`,received:r,field:"cwd",next:"Drop --keep-session to repair a gone cwd, or pass the real path of the recorded directory."});if(l.managed_worktree?.state==="open")throw new y({error:"cwd_node_managed_worktree_open",message:`${t} owns an open managed worktree and cannot relocate its cwd`,received:r,field:"cwd",next:"Reconcile the managed worktree first."});const _=l.cwd;return _!==c&&(await W(async g=>{await N(t,{cwd:c}),await g.prepare("UPDATE crons SET cwd = ? WHERE anchor_node = ? AND cwd = ?").run(c,t,_),await Ye(t,_,c)}),await $(e,t,["cwd"])),i.restart===!0&&ge(t),{status:200,body:await b(t)}}if(P().has(t)){const c=`${t} cannot repair its cwd while its broker is live`;throw new p(409,"cwd_node_live",c,{error:"cwd_node_live",message:c,received:r,field:"cwd",next:"Let the node become dormant, then retry the cwd repair."})}if(l.fork_from!=null)throw new y({error:"cwd_node_forked",message:`${t} is a fork and cannot repair its cwd; recorded cwd: ${l.cwd}`,received:r,field:"cwd",next:`Restore ${l.cwd}, then revive the fork normally.`});if(l.managed_worktree?.state==="open")throw new y({error:"cwd_node_managed_worktree_open",message:`${t} owns an open managed worktree and cannot repair its cwd`,received:r,field:"cwd",next:"Restore or reconcile the recorded checkout, then use the managed-worktree close or abandon flow."});if(C(l.cwd))throw new y({error:"cwd_still_present",message:`${t} recorded cwd still exists: ${l.cwd}; cwd repair is not a relocation command`,received:r,field:"cwd",next:"This command only repairs a node whose recorded cwd is gone."});if(!B(r))throw new y({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${r}`,received:r,field:"cwd",next:"Send an absolute path."});const w=T(r);if(!C(w))throw new y({error:"cwd_missing",message:`cwd does not exist: ${w}`,received:r,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."});try{if(!ee(w).isDirectory())throw new y({error:"cwd_not_a_directory",message:`cwd is not a directory: ${w}`,received:r,field:"cwd",next:"Send an existing absolute directory."})}catch(c){throw c instanceof y?c:new y({error:"cwd_missing",message:`cwd does not exist: ${w}`,received:r,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."})}return await W(async()=>{await N(t,{cwd:w}),await He(t)}),await $(e,t,["cwd"]),{status:200,body:await b(t)}}let a=await h(t);const u=i.listen===void 0?void 0:xt(i.listen);if(i.scopes!==void 0){const r=pe(i.scopes),l=a.grantee==="app:terminal"?await rt():a.grant_id?await it(a.grant_id):null;if(!r.every(f=>O(a.scopes,f)&&l!==null&&O(l.resolved,f)))throw new y({error:"unknown_scope",message:"scopes may only narrow the node's current effective set",received:r,field:"scopes",next:"Send only scopes the node currently holds."});if(r.includes("crtr:act")&&!O(r,"crtr:llm"))throw new p(400,"invalid_scope","crtr:act requires crtr:llm");a=await N(t,{scopes:r})}if(i.situational_context!==void 0&&Oe(t,Ae(i.situational_context)),i.model!==void 0){const r=(await de(a.cwd,a.profile_id??null)).modelLadders,l=kn(i.model,r),f=await at(a.grant_id,i.model,l===void 0),w=f?{family:dt,strength:f.strength}:l,c=f?f.model:Sn(i.model,r);await V({kind:"concrete",spec:c},{cwd:a.cwd,profileId:a.profile_id??null},n.modelRegistry);const k=P();let _=!1;if(k.isClaimed(t)&&await se(t,k.get(t)?.handle.exited)&&(_=await On(t,c,w).then(()=>!0,g=>{if(g instanceof An)return!1;throw g})),!_){if(k.isClaimed(t)){const g=`${t}'s broker did not accept the model switch; the model was not changed`;throw new p(409,"broker_not_ready",g,{error:"broker_not_ready",message:g,received:i.model,field:"model",next:"Check the node with `crtr node show`, then retry the model change."})}if(!c.includes("/"))throw m(`model must resolve to a provider/id spec: ${i.model}`);await In(t,c,w)}a=await h(t)}if(i.kind!==void 0||i.mode!==void 0||i.lifecycle!==void 0){i.kind!==void 0&&await ke(i.kind);const r=i.kind??a.kind,l=i.mode??a.mode,f=i.lifecycle??a.lifecycle;let w;l==="orchestrator"&&!await gn(t)&&(w=s(async()=>{const c=await yn(t);await _n(t,c!==null&&c.trim()!==""?{goal:c.trim()}:{})},"beforePersist")),a=await z(t,{...i.kind!==void 0?{kind:r}:{},...i.mode!==void 0?{mode:l}:{},...i.lifecycle!==void 0?{lifecycle:f}:{}},w)}i.name!==void 0&&(a=await N(t,{name:i.name}),a.window&&bn(a.window,Gn(a)));const d=["scopes","situational_context","model","kind","mode","lifecycle","name","listen"].filter(r=>i[r]!==void 0);return await $(e,t,d,u===void 0?void 0:async r=>{await r.prepare("UPDATE objects SET listen_json = ? WHERE id = ? AND type = 'node'").run(u,t)}),{status:200,body:await b(t)}}s(zt,"handleConfig");async function ve(){return(await de(process.cwd(),Re()||null)).kinds}s(ve,"daemonKinds");async function ke(e){const n=Object.keys(await ve());if(!n.includes(e))throw m(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${n.sort().join(", ")}.`})}s(ke,"assertKindServer");async function Jt(){const e=await ve();return{status:200,body:{kinds:Object.keys(e).sort().map(t=>({kind:t,when_to_use:e[t]?.whenToUse??null,available_to:e[t]?.availableTo??null}))}}}s(Jt,"handleListKinds");const uo=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:_t},{method:"GET",pattern:"/v1/nodes",handler:vt},{method:"GET",pattern:"/v1/kinds",handler:s(()=>Jt(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:Vt},{method:"GET",pattern:"/v1/nodes/:id",handler:kt},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:St},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:Rt},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:Ot},{method:"GET",pattern:"/v1/nodes/:id/session",handler:At},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:$t},{method:"GET",pattern:"/v1/nodes/:id/context",handler:Nt},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:Tt},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:Et},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:Dt},{method:"POST",pattern:"/v1/nodes/:id/close",handler:Lt},{method:"POST",pattern:"/v1/nodes/:id/read",handler:jt},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:Mt},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:Gt},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:Ft},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Bt},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Kt},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:zt}];export{zt as handleConfig,_t as handleCreate,Tt as handleFork,vt as handleList,Ft as handlePromote,Bt as handleYield,uo as nodeRoutes,mo as resolveCreateKind};
|