@north-light/cli 0.3.537 → 0.3.539

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.
Files changed (80) hide show
  1. package/dist/api/contract.d.ts +1 -1
  2. package/dist/api/contract.js +1 -1
  3. package/dist/api/dto/profiles.d.ts +2 -0
  4. package/dist/builtin-memory/crouter-sdk/release-notes.md +8 -0
  5. package/dist/clients/attach/viewer.js +454 -454
  6. package/dist/commands/profile/list.js +1 -1
  7. package/dist/commands/profile/show.js +1 -1
  8. package/dist/commands/sys/join.js +1 -1
  9. package/dist/commands/sys/sync-shared.d.ts +1 -1
  10. package/dist/commands/sys/sync-shared.js +1 -1
  11. package/dist/core/canvas/canvas.d.ts +0 -6
  12. package/dist/core/canvas/canvas.js +17 -22
  13. package/dist/core/canvas/crons.js +10 -10
  14. package/dist/core/canvas/db.js +4 -4
  15. package/dist/core/canvas/export-sqlite.js +1 -1
  16. package/dist/core/canvas/legacy-person.d.ts +4 -0
  17. package/dist/core/canvas/legacy-person.js +1 -0
  18. package/dist/core/canvas/migrations.js +58 -58
  19. package/dist/core/canvas/node-tokens.d.ts +0 -4
  20. package/dist/core/canvas/node-tokens.js +3 -3
  21. package/dist/core/canvas/person.d.ts +39 -0
  22. package/dist/core/canvas/person.js +18 -0
  23. package/dist/core/canvas/schema-pg.sql +11 -0
  24. package/dist/core/directory/join.d.ts +2 -2
  25. package/dist/core/environments.d.ts +10 -0
  26. package/dist/core/environments.js +1 -0
  27. package/dist/core/grants/local.d.ts +4 -4
  28. package/dist/core/grants/local.js +1 -1
  29. package/dist/core/grants/mirror.d.ts +1 -1
  30. package/dist/core/grants/on-sync.js +1 -1
  31. package/dist/core/grants/sync.js +1 -1
  32. package/dist/core/graph/kinds/environment.d.ts +2 -0
  33. package/dist/core/graph/kinds/environment.js +2 -0
  34. package/dist/core/graph/kinds/registry.js +1 -1
  35. package/dist/core/graph/objects.d.ts +1 -1
  36. package/dist/core/graph/objects.js +7 -7
  37. package/dist/core/graph/reader.d.ts +0 -1
  38. package/dist/core/graph/reader.js +3 -3
  39. package/dist/core/layout-migrate/index.js +3 -3
  40. package/dist/core/layout-migrate/stores.js +3 -3
  41. package/dist/core/peer/stubs.js +1 -1
  42. package/dist/core/runs/events.d.ts +0 -2
  43. package/dist/core/runs/events.js +4 -4
  44. package/dist/core/runs/operations.d.ts +0 -3
  45. package/dist/core/runs/operations.js +6 -6
  46. package/dist/core/runtime/close.js +1 -1
  47. package/dist/core/runtime/host.js +3 -3
  48. package/dist/core/runtime/launch-target.d.ts +10 -1
  49. package/dist/core/runtime/launch-target.js +1 -1
  50. package/dist/core/runtime/nodes.js +1 -1
  51. package/dist/core/scoped-state/db.js +2 -2
  52. package/dist/core/scoped-state/profiles.js +1 -1
  53. package/dist/core/scoped-state/schema.d.ts +4 -0
  54. package/dist/core/scoped-state/schema.js +3 -3
  55. package/dist/core/spaces/process.js +1 -1
  56. package/dist/daemon/api/handlers/crons.js +1 -1
  57. package/dist/daemon/api/handlers/hook-exec.js +1 -1
  58. package/dist/daemon/api/handlers/memory.js +5 -5
  59. package/dist/daemon/api/handlers/messages.js +2 -2
  60. package/dist/daemon/api/handlers/nodes.js +1 -1
  61. package/dist/daemon/api/handlers/profiles.js +1 -1
  62. package/dist/daemon/api/reader.js +1 -1
  63. package/dist/daemon/api/router.js +1 -1
  64. package/dist/daemon/api/vendor-signin.js +15 -15
  65. package/dist/daemon/cron/armed-context.js +1 -1
  66. package/dist/daemon/cron/authority.d.ts +1 -2
  67. package/dist/daemon/cron/authority.js +1 -1
  68. package/dist/daemon/crtrd.js +12 -12
  69. package/dist/daemon/reconcilers/storage-maintenance.d.ts +3 -0
  70. package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
  71. package/dist/migrations/004-canvas-documents/apply.js +1 -1
  72. package/dist/migrations/004-canvas-documents/index.js +2 -2
  73. package/dist/types.d.ts +2 -0
  74. package/docs/cli/join-northlight.md +1 -1
  75. package/docs/sdk/release-notes.md +8 -0
  76. package/package.json +2 -2
  77. package/packages/crouter-identity/package.json +1 -1
  78. package/runtime.lock.json +12 -12
  79. package/dist/daemon/joined-owner.d.ts +0 -5
  80. package/dist/daemon/joined-owner.js +0 -1
@@ -1 +1 @@
1
- var C=Object.defineProperty;var u=(e,r)=>C(e,"name",{value:r,configurable:!0});import{existsSync as v}from"node:fs";import{assertGranteeRunsHere as $}from"../runtime/unsandboxed.js";import{randomUUID as N}from"node:crypto";import{join as g}from"node:path";import{getNode as R}from"../canvas/canvas.js";import{nodeAgentDir as O,nodeHome as k,nodeRunDir as H}from"../canvas/paths.js";import{appSpace as K}from"../layout.js";import{activeGrant as h,activeGrantForApp as _,grantFor as I,grantsGeneration as S}from"../grants/mirror.js";import{readConfig as B}from"../config.js";import{emitEvent as y}from"../events/emit.js";import{ensureAppSpace as F}from"./space.js";import{compileLaunch as G,launchStillGranted as M}from"./mounts.js";import{pinSandboxRuntimeHome as j}from"./runtime-home.js";import{sandboxCacheEnv as q}from"./cache-env.js";import{launcherRequest as b}from"../../launcher/client.js";import{LAUNCHER_SOCKET as T}from"../../launcher/spec.js";function U(e){return`cron-${e}`}u(U,"cronLaunchId");function ce(){if(process.platform!=="linux")return!1;if(v(T))return!0;throw new Error("root launcher socket is unavailable; refusing an unsandboxed app process")}u(ce,"appProcessSandboxed");function fe(){return A??(process.platform==="linux"&&v(T))}u(fe,"appProcessesSandboxed");let A;function le(e){A=e}u(le,"__setAppProcessesSandboxedForTest");async function me(e,r,n,o=!1,t,d){const a=n===void 0?null:await R(n),s=d!==void 0?d.grantId?await h(d.grantId):await I(e,d.sub):a?null:await _(e);if(d!==void 0?!s&&!(d.grantId===null&&e==="app:terminal"):!a&&!s)throw new Error(`no active grant for ${e}`);return(await G({nodeId:n??"proc-cwd-check",app:e,...d!==void 0?{sub:d.sub,grantId:s?.id??null,scopes:d.scopes}:{sub:a?a.sub??"user:local":s.sub,grantId:a?a.grant_id??null:s.id,scopes:a?.scopes??null},command:["true"],env:{},...n===void 0?{withoutNode:!0}:{},...t===void 0?{}:{folder:t},isolated:a?.isolated===!0||o,auditMissing:u(()=>{},"auditMissing")})).mounts.some(({source:c})=>r===c||r.startsWith(c==="/"?"/":`${c}/`))}u(me,"cwdIsMounted");async function D(e,r="SIGKILL",n){if(!("ok"in await b({operation:"stop",pid:e,signal:r,...n===void 0?{}:{nodeId:n}})))throw new Error("launcher did not stop process")}u(D,"stopAppProcess");function W(e,r,n,o,t){return o?t??O(e,r):n}u(W,"appProcessCwd");async function pe(e){if(e.cron!==void 0&&(e.nodeId!==void 0||e.principal===void 0))throw new Error("a cron launch has a stored principal and no node");const r=e.nodeId===void 0?null:await R(e.nodeId);if(e.nodeId!==void 0&&!r)throw new Error(`missing node ${e.nodeId}`);const n=r?.grantee??e.app??"app:terminal";if($(n),e.app!==void 0&&e.app!==n)throw new Error("app does not match node");const o=e.principal;let t=null;if(o!==void 0){if(t=o.grantId?await h(o.grantId):await I(n,o.sub),!(t===null&&o.grantId===null&&n==="app:terminal"&&!B("user").runtime?.issuer)&&(!t||t.grantee!==n||t.sub!==o.sub))throw new Error(`no active grant for ${n}`)}else if(r){if(n!=="app:terminal"&&!(r.grant_id?await h(r.grant_id):await I(n,r.sub??"user:local")))throw new Error(`no active grant for ${n}`)}else if(t=await _(n),!t)throw new Error(`no active grant for ${n}`);await F(n);const d=e.cron===void 0?e.nodeId??`proc-${N()}`:U(e.cron.executionId),a=r?.isolated===!0||e.isolated===!0;if(a&&!r&&e.folder===void 0)throw new Error("isolated process requires a live node");const s=K(n),m=W(d,n,e.cwd,a,e.folder),c=r?k(d,n,a):a&&e.folder!==void 0?g(e.folder,"home"):s.home,L=j(Object.fromEntries(Object.entries({...e.env,...process.platform==="linux"?q(n):{},HOME:c,PI_CODING_AGENT_DIR:g(c,".pi","agent"),PWD:m,...e.nodeId===void 0&&e.cron===void 0?{}:{CRTR_API_SOCKET:g(H(d),"cli.sock")}}).filter(i=>i[1]!==void 0))),E=o!==void 0?{nodeId:d,app:n,sub:o.sub,grantId:t?.id??null,scopes:o.scopes}:{nodeId:d,app:n,sub:r?r.sub??"user:local":t.sub,grantId:r?r.grant_id??null:t.id,scopes:r?.scopes??null},P=u(async()=>{const i=await G({...E,command:e.command,env:L,...e.nodeId===void 0?{withoutNode:!0}:{},isolated:a,cwd:m,...e.folder===void 0?{}:{folder:e.folder},...e.cron===void 0?{}:{cron:e.cron.anchorDir===void 0?{}:{anchorDir:e.cron.anchorDir}},...e.pluginRoot===void 0?{}:{pluginRoot:e.pluginRoot},auditMissing:u(w=>y({level:"warn",event:"process.mount.missing",...e.nodeId===void 0?{}:{node_id:e.nodeId},fields:{source:w}}),"auditMissing")});if(e.pluginRoot!==void 0&&(i.pluginRoot=e.pluginRoot),e.capture===!1){if(e.nodeId===void 0||e.stdin!==void 0)throw new Error("uncaptured process requires a node and no stdin")}else i.capture={stdoutBytes:e.stdoutBytes??256*1024,stderrBytes:e.stderrBytes??256*1024,...e.stderrTail?{stderrTail:!0}:{},...e.stdin===void 0?{}:{stdin:e.stdin}};return i},"compile");let f;for(let i=0;i<2&&f===void 0;i++){const w=await S(),x=await P(),l=await b({operation:"launch",spec:x});if(!("pid"in l))throw new Error("launcher did not return a process id");if(await S()===w||await M(E,x)){f=l.pid;break}y({level:"info",event:"process.launch.regranted",...e.nodeId===void 0?{}:{node_id:e.nodeId},fields:{pid:l.pid}}),await D(l.pid,"SIGKILL").catch(()=>{})}if(f===void 0)throw new Error("grant changed during every launch attempt");const p=f;return{pid:p,get completion(){return b({operation:"wait",pid:p}).then(i=>{if(!("result"in i))throw new Error("launcher did not return process completion");return i.result})},stop:u((i="SIGKILL")=>D(p,i,e.cron===void 0?e.nodeId:d),"stop")}}u(pe,"launchAppProcess");export{le as __setAppProcessesSandboxedForTest,W as appProcessCwd,ce as appProcessSandboxed,fe as appProcessesSandboxed,U as cronLaunchId,me as cwdIsMounted,pe as launchAppProcess,D as stopAppProcess};
1
+ var C=Object.defineProperty;var u=(e,r)=>C(e,"name",{value:r,configurable:!0});import{existsSync as R}from"node:fs";import{assertGranteeRunsHere as N}from"../runtime/unsandboxed.js";import{randomUUID as O}from"node:crypto";import{join as h}from"node:path";import{getNode as _}from"../canvas/canvas.js";import{nodeAgentDir as k,nodeHome as H,nodeRunDir as K}from"../canvas/paths.js";import{appSpace as B}from"../layout.js";import{activeGrant as g,activeGrantForApp as S,grantFor as I,grantsGeneration as y}from"../grants/mirror.js";import{emitEvent as G}from"../events/emit.js";import{ensureAppSpace as F}from"./space.js";import{compileLaunch as A,launchStillGranted as M}from"./mounts.js";import{pinSandboxRuntimeHome as j}from"./runtime-home.js";import{sandboxCacheEnv as q}from"./cache-env.js";import{launcherRequest as b}from"../../launcher/client.js";import{LAUNCHER_SOCKET as D}from"../../launcher/spec.js";import{personId as E}from"../canvas/person.js";function U(e){return`cron-${e}`}u(U,"cronLaunchId");function se(){if(process.platform!=="linux")return!1;if(R(D))return!0;throw new Error("root launcher socket is unavailable; refusing an unsandboxed app process")}u(se,"appProcessSandboxed");function fe(){return L??(process.platform==="linux"&&R(D))}u(fe,"appProcessesSandboxed");let L;function le(e){L=e}u(le,"__setAppProcessesSandboxedForTest");async function me(e,r,n,a=!1,t,d){const o=n===void 0?null:await _(n),c=d!==void 0?d.grantId?await g(d.grantId):await I(e,d.sub):o?null:await S(e);if((d!==void 0||!o)&&!c)throw new Error(`no active grant for ${e}`);return(await A({nodeId:n??"proc-cwd-check",app:e,...d!==void 0?{sub:d.sub,grantId:c?.id??null,scopes:d.scopes}:{sub:o?o.sub??E():c.sub,grantId:o?o.grant_id??null:c.id,scopes:o?.scopes??null},command:["true"],env:{},...n===void 0?{withoutNode:!0}:{},...t===void 0?{}:{folder:t},isolated:o?.isolated===!0||a,auditMissing:u(()=>{},"auditMissing")})).mounts.some(({source:s})=>r===s||r.startsWith(s==="/"?"/":`${s}/`))}u(me,"cwdIsMounted");async function P(e,r="SIGKILL",n){if(!("ok"in await b({operation:"stop",pid:e,signal:r,...n===void 0?{}:{nodeId:n}})))throw new Error("launcher did not stop process")}u(P,"stopAppProcess");function W(e,r,n,a,t){return a?t??k(e,r):n}u(W,"appProcessCwd");async function pe(e){if(e.cron!==void 0&&(e.nodeId!==void 0||e.principal===void 0))throw new Error("a cron launch has a stored principal and no node");const r=e.nodeId===void 0?null:await _(e.nodeId);if(e.nodeId!==void 0&&!r)throw new Error(`missing node ${e.nodeId}`);const n=r?.grantee??e.app??"app:terminal";if(N(n),e.app!==void 0&&e.app!==n)throw new Error("app does not match node");const a=e.principal;let t=null;if(a!==void 0){if(t=a.grantId?await g(a.grantId):await I(n,a.sub),!t||t.grantee!==n||t.sub!==a.sub)throw new Error(`no active grant for ${n}`)}else if(r){if(n!=="app:terminal"&&!(r.grant_id?await g(r.grant_id):await I(n,r.sub??E())))throw new Error(`no active grant for ${n}`)}else if(t=await S(n),!t)throw new Error(`no active grant for ${n}`);await F(n);const d=e.cron===void 0?e.nodeId??`proc-${O()}`:U(e.cron.executionId),o=r?.isolated===!0||e.isolated===!0;if(o&&!r&&e.folder===void 0)throw new Error("isolated process requires a live node");const c=B(n),m=W(d,n,e.cwd,o,e.folder),s=r?H(d,n,o):o&&e.folder!==void 0?h(e.folder,"home"):c.home,T=j(Object.fromEntries(Object.entries({...e.env,...process.platform==="linux"?q(n):{},HOME:s,PI_CODING_AGENT_DIR:h(s,".pi","agent"),PWD:m,...e.nodeId===void 0&&e.cron===void 0?{}:{CRTR_API_SOCKET:h(K(d),"cli.sock")}}).filter(i=>i[1]!==void 0))),x=a!==void 0?{nodeId:d,app:n,sub:a.sub,grantId:t?.id??null,scopes:a.scopes}:{nodeId:d,app:n,sub:r?r.sub??E():t.sub,grantId:r?r.grant_id??null:t.id,scopes:r?.scopes??null},$=u(async()=>{const i=await A({...x,command:e.command,env:T,...e.nodeId===void 0?{withoutNode:!0}:{},isolated:o,cwd:m,...e.folder===void 0?{}:{folder:e.folder},...e.cron===void 0?{}:{cron:e.cron.anchorDir===void 0?{}:{anchorDir:e.cron.anchorDir}},...e.pluginRoot===void 0?{}:{pluginRoot:e.pluginRoot},auditMissing:u(w=>G({level:"warn",event:"process.mount.missing",...e.nodeId===void 0?{}:{node_id:e.nodeId},fields:{source:w}}),"auditMissing")});if(e.pluginRoot!==void 0&&(i.pluginRoot=e.pluginRoot),e.capture===!1){if(e.nodeId===void 0||e.stdin!==void 0)throw new Error("uncaptured process requires a node and no stdin")}else i.capture={stdoutBytes:e.stdoutBytes??256*1024,stderrBytes:e.stderrBytes??256*1024,...e.stderrTail?{stderrTail:!0}:{},...e.stdin===void 0?{}:{stdin:e.stdin}};return i},"compile");let f;for(let i=0;i<2&&f===void 0;i++){const w=await y(),v=await $(),l=await b({operation:"launch",spec:v});if(!("pid"in l))throw new Error("launcher did not return a process id");if(await y()===w||await M(x,v)){f=l.pid;break}G({level:"info",event:"process.launch.regranted",...e.nodeId===void 0?{}:{node_id:e.nodeId},fields:{pid:l.pid}}),await P(l.pid,"SIGKILL").catch(()=>{})}if(f===void 0)throw new Error("grant changed during every launch attempt");const p=f;return{pid:p,get completion(){return b({operation:"wait",pid:p}).then(i=>{if(!("result"in i))throw new Error("launcher did not return process completion");return i.result})},stop:u((i="SIGKILL")=>P(p,i,e.cron===void 0?e.nodeId:d),"stop")}}u(pe,"launchAppProcess");export{le as __setAppProcessesSandboxedForTest,W as appProcessCwd,se as appProcessSandboxed,fe as appProcessesSandboxed,U as cronLaunchId,me as cwdIsMounted,pe as launchAppProcess,P as stopAppProcess};
@@ -1 +1 @@
1
- var X=Object.defineProperty;var t=(e,n)=>X(e,"name",{value:n,configurable:!0});import{randomUUID as nn}from"node:crypto";import{relative as en,resolve as z,sep as G}from"node:path";import{ApiError as c}from"../../../api/errors.js";import{armCron as rn,parseCronSink as on,getCron as v,listCrons as P,listCronRuns as F,pokeHeldCrons as tn,setCronState as L}from"../../../core/canvas/crons.js";import{getNode as _}from"../../../core/canvas/canvas.js";import{appSpace as sn,cronFolder as an}from"../../../core/layout.js";import{appProcessesSandboxed as cn,cwdIsMounted as ln}from"../../../core/spaces/process.js";import{activeGrant as dn,activeGrantForApp as un,grantFor as pn,terminalGrant as fn}from"../../../core/grants/mirror.js";import{readConfig as wn}from"../../../core/config.js";import{assertScope as Z}from"../../../core/scopes.js";import{InputError as a}from"../../../core/io.js";import{nextSlotAfter as _n}from"../../../core/wake.js";import{executeCron as hn,markSelfCanceledCronRun as mn}from"../../cron-run.js";import{toCronDTO as k,toCronRunDTO as H}from"../map.js";import{appOf as T,assertCeiling as gn,canReadNode as yn}from"../router.js";import{checkCronBirth as bn,checkCronFire as vn}from"../../cron/authority.js";import{endCron as kn}from"../../cron/ended.js";import{requireUsableProfile as Sn}from"./profiles.js";import{filterAsync as $n,mapAsync as Cn}from"../../../core/async-array.js";function E(e,n){const r=e[n];if(typeof r!="string"||r.trim()==="")throw new a({error:"missing_field",message:`cron arm request requires a non-empty "${n}"`,field:n,next:`Send a non-empty string "${n}".`});return r}t(E,"requireString");function C(e,n,r,o){if(e==null)return o;if(typeof e=="string"&&r.includes(e))return e;throw new a({error:`bad_${n}`,message:`"${String(e)}" is not a valid ${n}`,field:n,next:`Use one of: ${r.join(", ")}.`})}t(C,"requireEnum");async function On(e){if(e==="human")return JSON.stringify({human:!0});if(e.startsWith("node:")){const n=e.slice(5).trim();if(n==="")throw new a({error:"bad_sink",message:"node sink requires a node id",field:"sink",next:'Use sink "node:<node-id>".'});if(await _(n)===null)throw new a({error:"sink_node_not_found",message:`sink node ${n} does not exist on the canvas`,field:"sink",next:"Name a live node id, or use spawn:<kind> for a delivery that outlives any one node."});return JSON.stringify({node:n})}if(e.startsWith("spawn:")){const n=e.slice(6).trim();if(n==="")throw new a({error:"bad_sink",message:"spawn sink requires a node kind",field:"sink",next:'Use sink "spawn:<kind>" (e.g. spawn:general).'});return JSON.stringify({spawn:n})}throw new a({error:"bad_sink",message:`"${e}" is not a valid sink`,field:"sink",next:"Use node:<node-id>, spawn:<kind>, or human."})}t(On,"parseSinkSpec");const In=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/;function M(e,n){if(!In.test(e)||Number.isNaN(Date.parse(e)))throw new a({error:`bad_${n}`,message:`"${e}" is not a UTC ISO instant`,field:n,next:'Send a resolved UTC instant like "2026-06-07T09:00:00.000Z" (the client resolves the time grammar).'});return e}t(M,"requireUtcIso");function qn(e){try{_n(e,new Date)}catch(n){throw new a({error:"bad_recur",message:`recur is not advanceable: ${n instanceof Error?n.message:String(n)}`,field:"recur",next:'Send recur JSON the daemon can advance: {"every":"6h"} or {"cron":"0 9 * * *","tz":"America/New_York"}.'})}return e}t(qn,"requireRecur");function Nn(e){let n;try{n=JSON.parse(e)}catch{throw new a({error:"bad_env_json",message:"env_json is not valid JSON",field:"env_json",next:'Send a JSON object of string values, e.g. {"API_BASE":"https://x"}.'})}if(typeof n!="object"||n===null||Array.isArray(n))throw new a({error:"bad_env_json",message:"env_json must be a JSON object",field:"env_json",next:'Send a JSON object of string values, e.g. {"API_BASE":"https://x"}.'});for(const[r,o]of Object.entries(n))if(typeof o!="string")throw new a({error:"bad_env_json",message:`env_json value for "${r}" is not a string`,field:"env_json",next:"Every env value must be a string."});return e}t(Nn,"requireEnvJson");function U(e){const n=e.query.get("profile");return n!==null&&n.trim()!==""?n.trim():null}t(U,"callerProfile");function Y(e,n){return n===null||e.scope==="global"||e.profile===n}t(Y,"inScope");function K(e){return e.principal.class==="person"?null:T(e.principal)}t(K,"callerApp");async function J(e,n){return await yn(e.principal,n.grantee,n.created_by??void 0)}t(J,"visibleTo");function jn(e){return typeof e.anchor_node=="string"&&e.anchor_node!==""?e.anchor_node:null}t(jn,"anchorNodeOf");async function An(e,n,r,o,i,l){const d=typeof e.cwd=="string"&&e.cwd.trim()!==""?z(e.cwd):null;if(!cn()){if(d===null)throw new a({error:"missing_field",message:'cron arm request requires a non-empty "cwd"',field:"cwd",next:'Send a non-empty string "cwd".'});return d}const h=o!==null&&await _(o)!==null?o:void 0,u=t(async q=>await ln(n,q,h,i,void 0,l),"reaches");if(d!==null&&await u(d))return d;const s=sn(n).files;if(d!==null&&e.cwd_is_default!==!0)throw new c(400,"invalid_request",`cwd ${d} is not inside a directory this app's cron runs can see, so every run would fail to start; use a directory under ${s}`,{cwd:d,default:s},void 0,{param:"cwd"});const p=r===null?null:(await _(r))?.cwd??null;return p!==null&&await u(p)?p:s}t(An,"resolveArmedCwd");async function Pn(e,n,r){const o=e.principal;if(o.class==="person"){const s=await fn();return{sub:s?.sub??"user:local",grant_id:s?.id??null,scopes:null,origin_run_id:null}}if(o.class==="app"){const s=await un(n);if(s===null)throw new c(401,"grant_revoked",`no active grant for ${n}`);const p=e.ceiling??o.scopes;return{sub:s.sub,grant_id:s.id,scopes:p===null?null:[...p],origin_run_id:null}}if(o.class==="cron"){const s=await vn({grantee:o.app,sub:o.sub,grant_id:o.grant,scopes:o.scopes});if(!s.allowed)throw new c(s.reason==="scope_missing"?403:401,s.reason==="scope_missing"?"scope_missing":"grant_revoked",s.message);return{sub:o.sub,grant_id:o.grant,scopes:o.scopes===null?null:[...o.scopes],origin_run_id:o.origin_run}}if(o.class!=="broker")throw new c(401,"unauthorized","this caller cannot arm a cron");const i=r??await _(o.node),l=i?.grant_id??o.grant,d=i?.sub??o.sub,h=l!=null?await dn(l):await pn(n,d);if(h===null){if(n==="app:terminal"&&!wn("user").runtime?.issuer)return{sub:d,grant_id:l??null,scopes:i?.scopes??o.scopes,origin_run_id:i?.run_id??o.run};throw new c(401,"grant_revoked","the node grant is not active")}const u=i?.scopes??o.scopes;return{sub:h.sub,grant_id:h.id,scopes:u===null?null:[...u],origin_run_id:i?.run_id??o.run}}t(Pn,"armPrincipal");async function Tn(e){const n=e.body??{},r=E(n,"name"),o=E(n,"command"),i=M(E(n,"fire_at"),"fire_at"),l=typeof n.recur=="string"&&n.recur!==""?qn(n.recur):null,d=typeof n.expires_at=="string"&&n.expires_at!==""?M(n.expires_at,"expires_at"):null,h=typeof n.env_json=="string"&&n.env_json!==""?Nn(n.env_json):null,u=typeof n.sink=="string"&&n.sink.trim()!==""?n.sink.trim():null,s=C(n.on_output,"on_output",["silent","on-failure","always","on-change"],u?.startsWith("node:")?"on-change":"on-failure"),p=C(n.overlap,"overlap",["skip","queue","replace"],"skip"),q=C(n.tier,"tier",["normal","urgent","critical"],"normal"),D=s==="always"||s==="on-change";if(D&&u===null)throw new a({error:"sink_required",message:`on_output "${s}" delivers stdout every qualifying run \u2014 it needs a sink`,field:"sink",next:"Pass sink node:<node-id> (a living node's inbox), spawn:<kind> (birth a fresh node per delivery), or human (the humanloop inbox)."});if(!D&&u!==null)throw new a({error:"sink_unused",message:`on_output "${s}" never delivers stdout \u2014 a sink would be dead config`,field:"sink",next:'Drop the sink, or use on_output "always"/"on-change" if delivery is the point.'});const Q=u!==null?await On(u):"{}";if(u?.startsWith("spawn:")&&(gn(e.ceiling,"crtr:act"),e.principal.class==="cron")){const w=await bn({grantee:e.principal.app,sub:e.principal.sub,grant_id:e.principal.grant,scopes:e.principal.scopes});if(!w.allowed)throw new c(w.reason==="scope_missing"?403:401,w.reason==="scope_missing"?"scope_missing":"grant_revoked",w.message)}const y=T(e.principal)??"app:terminal",b=e.principal.class==="broker"?e.principal.node:e.principal.class==="cron"?null:typeof n.created_by=="string"&&n.created_by!==""?n.created_by:null;if(e.principal.class==="broker"&&n.created_by!=null&&n.created_by!==b)throw new c(403,"permission_error","a broker may only arm a cron as its own node");const m=b===null?null:await _(b);if(m!==null){if(m.grantee!==y)throw new a({error:"creator_app_mismatch",message:"creator node belongs to another app",field:"created_by",next:"Use a node of the calling app."});Z(m,"crtr:schedule"),u?.startsWith("spawn:")&&Z(m,"crtr:act")}if(n.isolated!==void 0&&typeof n.isolated!="boolean")throw new c(400,"invalid_request","isolated must be a boolean");if(m?.isolated&&n.isolated===!1)throw new c(403,"isolated_run","a cron created by an isolated node cannot escape isolation");const W=m?.isolated===!0||e.principal.class==="cron"&&e.principal.isolated;if(W&&n.isolated===!1)throw new c(403,"isolated_run","a cron created by an isolated caller cannot escape isolation");const N=W||n.isolated===!0,g=await Pn(e,y,m),j=nn(),S=N?an(y,j):null;if(S!==null&&n.cwd_is_default!==!0){const w=en(S,typeof n.cwd=="string"&&n.cwd.trim()!==""?z(n.cwd):S);if(w===".."||w.startsWith(`..${G}`)||w.startsWith(G))throw new c(400,"invalid_request","an isolated cron must run in its own cron folder",{param:"cwd"})}const V=S??await An(n,y,b,jn(n),N,{sub:g.sub,grantId:g.grant_id,scopes:g.scopes}),f=typeof n.anchor_node=="string"&&n.anchor_node!==""?n.anchor_node:null;if(f!==null&&await _(f)!==null&&(await _(f)).grantee!==y)throw new a({error:"anchor_app_mismatch",message:"anchor node belongs to another app",field:"anchor_node",next:"Use an anchor of the calling app."});if(f!==null&&await _(f)===null)throw new a({error:"anchor_not_found",message:`anchor node ${f} does not exist on the canvas`,field:"anchor_node",next:"Name a live node id, or drop the anchor \u2014 an unanchored cron outlives every node."});const B=n.cancel_on_wake===!0;if(B&&f===null)throw new a({error:"cancel_on_wake_needs_anchor",message:"cancel_on_wake couples the cron to a node's dormancy \u2014 it requires an anchor node",field:"anchor_node",next:"Pass anchor_node with the node whose wake should cancel this cron."});const $=n.run_timeout_s??300;if(typeof $!="number"||!Number.isInteger($)||$<=0)throw new a({error:"bad_run_timeout",message:`run_timeout_s must be a positive integer (got ${String(n.run_timeout_s)})`,field:"run_timeout_s",next:"Send the timeout in whole seconds, e.g. 300."});const A=typeof n.profile=="string"&&n.profile!==""?(await Sn(e,n.profile)).profileId:null,x=C(n.scope,"scope",["profile","global"],A!==null?"profile":"global");if(x==="profile"&&A===null)throw new a({error:"scope_needs_profile",message:'scope "profile" names the profile the cron lists and cancels within \u2014 it requires a profile',field:"profile",next:'Send a profile, or use scope "global" for a canvas-home-wide cron.'});return await rn({cron_id:j,name:r,created_by:b,grantee:y,sub:g.sub,grant_id:g.grant_id,scopes:g.scopes,origin_run_id:g.origin_run_id,isolated:N,command:o,fire_at:i,recur:l,tz:typeof n.tz=="string"?n.tz:null,expires_at:d,anchor_node:f,cancel_on_wake:B,cwd:V,env_json:h,profile:A,scope:x,run_timeout_s:$,overlap:p,on_output:s,sink:Q,tier:q}),{status:201,body:k(await v(j),null)}}t(Tn,"handleArm");async function En(e){const n=U(e),r=e.query.get("created_by");if(r==="")throw new c(400,"invalid_request","created_by must be nonempty when present");const o=await $n((n===null?await P({all:!0}):[...await P({profile:n}),...await P({global:!0})].sort((i,l)=>i.fire_at<l.fire_at?-1:i.fire_at>l.fire_at?1:0)).filter(i=>r===null||i.created_by===r),async i=>await J(e,i));return{status:200,body:await Cn(o,async i=>k(i,await R(i)))}}t(En,"handleList");async function R(e){return(await F(e.cron_id))[0]??null}t(R,"lastRunOf");async function O(e){const n=e.params.cronId,r=await v(n);if(r===null||!await J(e,r))throw new c(404,"cron_not_found",`no cron ${n}`);if(!Y(r,U(e)))throw new c(404,"cron_not_found",`no cron ${n} in this profile \u2014 it is scoped to another profile`);return r}t(O,"requireCron");function I(e,n){const r=K(e);if(r!==null&&n.grantee!==r)throw new c(403,"other_app_run",`cron ${n.cron_id} belongs to another app`);return n}t(I,"requireOwnCron");async function Un(e){const n=await O(e),r=await F(n.cron_id);return{status:200,body:{cron:k(n,r[0]??null),runs:r.map(H)}}}t(Un,"handleShow");async function Jn(e){const n=I(e,await O(e));await L(n.cron_id,"paused");const r=await v(n.cron_id);return{status:200,body:k(r,await R(r))}}t(Jn,"handlePause");async function Rn(e){const n=I(e,await O(e));await L(n.cron_id,"active");const r=await v(n.cron_id);return{status:200,body:k(r,await R(r))}}t(Rn,"handleResume");async function Dn(e){const n=I(e,await O(e));if(n.run_state==="running")throw new c(409,"cron_running",`cron ${n.cron_id} has a run in flight \u2014 wait for it to settle`);const r=await hn(n,{outOfBand:!0});if(r===null)throw new c(409,"cron_running",`cron ${n.cron_id} was claimed by a concurrent run \u2014 check \`cron show\` for its result`);return{status:200,body:H(r)}}t(Dn,"handleRun");async function Wn(e){const n=new Date().toISOString();return{status:200,body:{unparked:await tn(n,K(e)),at:n}}}t(Wn,"handlePoke");function Bn(e,n){const r=e.principal;if(r.class==="cron")return r.cron===n.cron_id?null:{kind:"canceled",by:`cron ${r.cron}`};if(r.class==="broker"){const i=on(n.sink);return i?.kind==="node"&&i.node===r.node?null:{kind:"canceled",by:`node ${r.node}`}}const o=T(r);return{kind:"canceled",by:o===null||o==="app:terminal"?"the person":o}}t(Bn,"cancelNotice");async function xn(e){const n=e.params.cronId,r=await v(n);if(r!==null&&!await J(e,r))throw new c(404,"cron_not_found",`no cron ${n}`);if(r!==null&&!Y(r,U(e)))throw new c(404,"cron_not_found",`no cron ${n} in this profile \u2014 it is scoped to another profile`);r!==null&&I(e,r);const o=e.query.get("run_id"),i=e.principal.class==="cron"?o===e.principal.execution&&n===e.principal.cron:!0,l=o!==null&&i&&mn(n,o);return r!==null&&await kn(r,l?null:Bn(e,r),{preserveRunningProcess:l}),{status:204}}t(xn,"handleCancel");const ce=[{method:"POST",pattern:"/v1/crons",scope:"crtr:schedule",handler:Tn},{method:"GET",pattern:"/v1/crons",handler:En},{method:"GET",pattern:"/v1/crons/:cronId",handler:Un},{method:"POST",pattern:"/v1/crons/:cronId/pause",scope:"crtr:schedule",handler:Jn},{method:"POST",pattern:"/v1/crons/:cronId/resume",scope:"crtr:schedule",handler:Rn},{method:"POST",pattern:"/v1/crons/poke",scope:"crtr:schedule",handler:Wn},{method:"POST",pattern:"/v1/crons/:cronId/run",scope:"crtr:schedule",handler:Dn},{method:"DELETE",pattern:"/v1/crons/:cronId",scope:"crtr:schedule",handler:xn}];export{ce as cronRoutes};
1
+ var X=Object.defineProperty;var t=(e,n)=>X(e,"name",{value:n,configurable:!0});import{randomUUID as nn}from"node:crypto";import{relative as en,resolve as z,sep as G}from"node:path";import{ApiError as c}from"../../../api/errors.js";import{armCron as rn,parseCronSink as on,getCron as v,listCrons as P,listCronRuns as F,pokeHeldCrons as tn,setCronState as L}from"../../../core/canvas/crons.js";import{getNode as _}from"../../../core/canvas/canvas.js";import{appSpace as sn,cronFolder as an}from"../../../core/layout.js";import{appProcessesSandboxed as cn,cwdIsMounted as ln}from"../../../core/spaces/process.js";import{activeGrant as dn,activeGrantForApp as un,grantFor as pn,terminalGrant as fn}from"../../../core/grants/mirror.js";import{assertScope as Z}from"../../../core/scopes.js";import{InputError as a}from"../../../core/io.js";import{nextSlotAfter as wn}from"../../../core/wake.js";import{executeCron as _n,markSelfCanceledCronRun as hn}from"../../cron-run.js";import{toCronDTO as k,toCronRunDTO as H}from"../map.js";import{appOf as T,assertCeiling as mn,canReadNode as gn}from"../router.js";import{checkCronBirth as yn,checkCronFire as bn}from"../../cron/authority.js";import{endCron as vn}from"../../cron/ended.js";import{requireUsableProfile as kn}from"./profiles.js";import{filterAsync as Sn,mapAsync as $n}from"../../../core/async-array.js";import{personId as On}from"../../../core/canvas/person.js";function E(e,n){const r=e[n];if(typeof r!="string"||r.trim()==="")throw new a({error:"missing_field",message:`cron arm request requires a non-empty "${n}"`,field:n,next:`Send a non-empty string "${n}".`});return r}t(E,"requireString");function O(e,n,r,o){if(e==null)return o;if(typeof e=="string"&&r.includes(e))return e;throw new a({error:`bad_${n}`,message:`"${String(e)}" is not a valid ${n}`,field:n,next:`Use one of: ${r.join(", ")}.`})}t(O,"requireEnum");async function Cn(e){if(e==="human")return JSON.stringify({human:!0});if(e.startsWith("node:")){const n=e.slice(5).trim();if(n==="")throw new a({error:"bad_sink",message:"node sink requires a node id",field:"sink",next:'Use sink "node:<node-id>".'});if(await _(n)===null)throw new a({error:"sink_node_not_found",message:`sink node ${n} does not exist on the canvas`,field:"sink",next:"Name a live node id, or use spawn:<kind> for a delivery that outlives any one node."});return JSON.stringify({node:n})}if(e.startsWith("spawn:")){const n=e.slice(6).trim();if(n==="")throw new a({error:"bad_sink",message:"spawn sink requires a node kind",field:"sink",next:'Use sink "spawn:<kind>" (e.g. spawn:general).'});return JSON.stringify({spawn:n})}throw new a({error:"bad_sink",message:`"${e}" is not a valid sink`,field:"sink",next:"Use node:<node-id>, spawn:<kind>, or human."})}t(Cn,"parseSinkSpec");const In=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/;function M(e,n){if(!In.test(e)||Number.isNaN(Date.parse(e)))throw new a({error:`bad_${n}`,message:`"${e}" is not a UTC ISO instant`,field:n,next:'Send a resolved UTC instant like "2026-06-07T09:00:00.000Z" (the client resolves the time grammar).'});return e}t(M,"requireUtcIso");function qn(e){try{wn(e,new Date)}catch(n){throw new a({error:"bad_recur",message:`recur is not advanceable: ${n instanceof Error?n.message:String(n)}`,field:"recur",next:'Send recur JSON the daemon can advance: {"every":"6h"} or {"cron":"0 9 * * *","tz":"America/New_York"}.'})}return e}t(qn,"requireRecur");function Nn(e){let n;try{n=JSON.parse(e)}catch{throw new a({error:"bad_env_json",message:"env_json is not valid JSON",field:"env_json",next:'Send a JSON object of string values, e.g. {"API_BASE":"https://x"}.'})}if(typeof n!="object"||n===null||Array.isArray(n))throw new a({error:"bad_env_json",message:"env_json must be a JSON object",field:"env_json",next:'Send a JSON object of string values, e.g. {"API_BASE":"https://x"}.'});for(const[r,o]of Object.entries(n))if(typeof o!="string")throw new a({error:"bad_env_json",message:`env_json value for "${r}" is not a string`,field:"env_json",next:"Every env value must be a string."});return e}t(Nn,"requireEnvJson");function U(e){const n=e.query.get("profile");return n!==null&&n.trim()!==""?n.trim():null}t(U,"callerProfile");function Y(e,n){return n===null||e.scope==="global"||e.profile===n}t(Y,"inScope");function K(e){return e.principal.class==="person"?null:T(e.principal)}t(K,"callerApp");async function J(e,n){return await gn(e.principal,n.grantee,n.created_by??void 0)}t(J,"visibleTo");function jn(e){return typeof e.anchor_node=="string"&&e.anchor_node!==""?e.anchor_node:null}t(jn,"anchorNodeOf");async function An(e,n,r,o,i,l){const u=typeof e.cwd=="string"&&e.cwd.trim()!==""?z(e.cwd):null;if(!cn()){if(u===null)throw new a({error:"missing_field",message:'cron arm request requires a non-empty "cwd"',field:"cwd",next:'Send a non-empty string "cwd".'});return u}const h=o!==null&&await _(o)!==null?o:void 0,d=t(async q=>await ln(n,q,h,i,void 0,l),"reaches");if(u!==null&&await d(u))return u;const s=sn(n).files;if(u!==null&&e.cwd_is_default!==!0)throw new c(400,"invalid_request",`cwd ${u} is not inside a directory this app's cron runs can see, so every run would fail to start; use a directory under ${s}`,{cwd:u,default:s},void 0,{param:"cwd"});const p=r===null?null:(await _(r))?.cwd??null;return p!==null&&await d(p)?p:s}t(An,"resolveArmedCwd");async function Pn(e,n,r){const o=e.principal;if(o.class==="person"){const s=await fn();return{sub:s?.sub??On(),grant_id:s?.id??null,scopes:null,origin_run_id:null}}if(o.class==="app"){const s=await un(n);if(s===null)throw new c(401,"grant_revoked",`no active grant for ${n}`);const p=e.ceiling??o.scopes;return{sub:s.sub,grant_id:s.id,scopes:p===null?null:[...p],origin_run_id:null}}if(o.class==="cron"){const s=await bn({grantee:o.app,sub:o.sub,grant_id:o.grant,scopes:o.scopes});if(!s.allowed)throw new c(s.reason==="scope_missing"?403:401,s.reason==="scope_missing"?"scope_missing":"grant_revoked",s.message);return{sub:o.sub,grant_id:o.grant,scopes:o.scopes===null?null:[...o.scopes],origin_run_id:o.origin_run}}if(o.class!=="broker")throw new c(401,"unauthorized","this caller cannot arm a cron");const i=r??await _(o.node),l=i?.grant_id??o.grant,u=i?.sub??o.sub,h=l!=null?await dn(l):await pn(n,u);if(h===null)throw new c(401,"grant_revoked","the node grant is not active");const d=i?.scopes??o.scopes;return{sub:h.sub,grant_id:h.id,scopes:d===null?null:[...d],origin_run_id:i?.run_id??o.run}}t(Pn,"armPrincipal");async function Tn(e){const n=e.body??{},r=E(n,"name"),o=E(n,"command"),i=M(E(n,"fire_at"),"fire_at"),l=typeof n.recur=="string"&&n.recur!==""?qn(n.recur):null,u=typeof n.expires_at=="string"&&n.expires_at!==""?M(n.expires_at,"expires_at"):null,h=typeof n.env_json=="string"&&n.env_json!==""?Nn(n.env_json):null,d=typeof n.sink=="string"&&n.sink.trim()!==""?n.sink.trim():null,s=O(n.on_output,"on_output",["silent","on-failure","always","on-change"],d?.startsWith("node:")?"on-change":"on-failure"),p=O(n.overlap,"overlap",["skip","queue","replace"],"skip"),q=O(n.tier,"tier",["normal","urgent","critical"],"normal"),D=s==="always"||s==="on-change";if(D&&d===null)throw new a({error:"sink_required",message:`on_output "${s}" delivers stdout every qualifying run \u2014 it needs a sink`,field:"sink",next:"Pass sink node:<node-id> (a living node's inbox), spawn:<kind> (birth a fresh node per delivery), or human (the humanloop inbox)."});if(!D&&d!==null)throw new a({error:"sink_unused",message:`on_output "${s}" never delivers stdout \u2014 a sink would be dead config`,field:"sink",next:'Drop the sink, or use on_output "always"/"on-change" if delivery is the point.'});const Q=d!==null?await Cn(d):"{}";if(d?.startsWith("spawn:")&&(mn(e.ceiling,"crtr:act"),e.principal.class==="cron")){const w=await yn({grantee:e.principal.app,sub:e.principal.sub,grant_id:e.principal.grant,scopes:e.principal.scopes});if(!w.allowed)throw new c(w.reason==="scope_missing"?403:401,w.reason==="scope_missing"?"scope_missing":"grant_revoked",w.message)}const y=T(e.principal)??"app:terminal",b=e.principal.class==="broker"?e.principal.node:e.principal.class==="cron"?null:typeof n.created_by=="string"&&n.created_by!==""?n.created_by:null;if(e.principal.class==="broker"&&n.created_by!=null&&n.created_by!==b)throw new c(403,"permission_error","a broker may only arm a cron as its own node");const m=b===null?null:await _(b);if(m!==null){if(m.grantee!==y)throw new a({error:"creator_app_mismatch",message:"creator node belongs to another app",field:"created_by",next:"Use a node of the calling app."});Z(m,"crtr:schedule"),d?.startsWith("spawn:")&&Z(m,"crtr:act")}if(n.isolated!==void 0&&typeof n.isolated!="boolean")throw new c(400,"invalid_request","isolated must be a boolean");if(m?.isolated&&n.isolated===!1)throw new c(403,"isolated_run","a cron created by an isolated node cannot escape isolation");const W=m?.isolated===!0||e.principal.class==="cron"&&e.principal.isolated;if(W&&n.isolated===!1)throw new c(403,"isolated_run","a cron created by an isolated caller cannot escape isolation");const N=W||n.isolated===!0,g=await Pn(e,y,m),j=nn(),S=N?an(y,j):null;if(S!==null&&n.cwd_is_default!==!0){const w=en(S,typeof n.cwd=="string"&&n.cwd.trim()!==""?z(n.cwd):S);if(w===".."||w.startsWith(`..${G}`)||w.startsWith(G))throw new c(400,"invalid_request","an isolated cron must run in its own cron folder",{param:"cwd"})}const V=S??await An(n,y,b,jn(n),N,{sub:g.sub,grantId:g.grant_id,scopes:g.scopes}),f=typeof n.anchor_node=="string"&&n.anchor_node!==""?n.anchor_node:null;if(f!==null&&await _(f)!==null&&(await _(f)).grantee!==y)throw new a({error:"anchor_app_mismatch",message:"anchor node belongs to another app",field:"anchor_node",next:"Use an anchor of the calling app."});if(f!==null&&await _(f)===null)throw new a({error:"anchor_not_found",message:`anchor node ${f} does not exist on the canvas`,field:"anchor_node",next:"Name a live node id, or drop the anchor \u2014 an unanchored cron outlives every node."});const B=n.cancel_on_wake===!0;if(B&&f===null)throw new a({error:"cancel_on_wake_needs_anchor",message:"cancel_on_wake couples the cron to a node's dormancy \u2014 it requires an anchor node",field:"anchor_node",next:"Pass anchor_node with the node whose wake should cancel this cron."});const $=n.run_timeout_s??300;if(typeof $!="number"||!Number.isInteger($)||$<=0)throw new a({error:"bad_run_timeout",message:`run_timeout_s must be a positive integer (got ${String(n.run_timeout_s)})`,field:"run_timeout_s",next:"Send the timeout in whole seconds, e.g. 300."});const A=typeof n.profile=="string"&&n.profile!==""?(await kn(e,n.profile)).profileId:null,x=O(n.scope,"scope",["profile","global"],A!==null?"profile":"global");if(x==="profile"&&A===null)throw new a({error:"scope_needs_profile",message:'scope "profile" names the profile the cron lists and cancels within \u2014 it requires a profile',field:"profile",next:'Send a profile, or use scope "global" for a canvas-home-wide cron.'});return await rn({cron_id:j,name:r,created_by:b,grantee:y,sub:g.sub,grant_id:g.grant_id,scopes:g.scopes,origin_run_id:g.origin_run_id,isolated:N,command:o,fire_at:i,recur:l,tz:typeof n.tz=="string"?n.tz:null,expires_at:u,anchor_node:f,cancel_on_wake:B,cwd:V,env_json:h,profile:A,scope:x,run_timeout_s:$,overlap:p,on_output:s,sink:Q,tier:q}),{status:201,body:k(await v(j),null)}}t(Tn,"handleArm");async function En(e){const n=U(e),r=e.query.get("created_by");if(r==="")throw new c(400,"invalid_request","created_by must be nonempty when present");const o=await Sn((n===null?await P({all:!0}):[...await P({profile:n}),...await P({global:!0})].sort((i,l)=>i.fire_at<l.fire_at?-1:i.fire_at>l.fire_at?1:0)).filter(i=>r===null||i.created_by===r),async i=>await J(e,i));return{status:200,body:await $n(o,async i=>k(i,await R(i)))}}t(En,"handleList");async function R(e){return(await F(e.cron_id))[0]??null}t(R,"lastRunOf");async function C(e){const n=e.params.cronId,r=await v(n);if(r===null||!await J(e,r))throw new c(404,"cron_not_found",`no cron ${n}`);if(!Y(r,U(e)))throw new c(404,"cron_not_found",`no cron ${n} in this profile \u2014 it is scoped to another profile`);return r}t(C,"requireCron");function I(e,n){const r=K(e);if(r!==null&&n.grantee!==r)throw new c(403,"other_app_run",`cron ${n.cron_id} belongs to another app`);return n}t(I,"requireOwnCron");async function Un(e){const n=await C(e),r=await F(n.cron_id);return{status:200,body:{cron:k(n,r[0]??null),runs:r.map(H)}}}t(Un,"handleShow");async function Jn(e){const n=I(e,await C(e));await L(n.cron_id,"paused");const r=await v(n.cron_id);return{status:200,body:k(r,await R(r))}}t(Jn,"handlePause");async function Rn(e){const n=I(e,await C(e));await L(n.cron_id,"active");const r=await v(n.cron_id);return{status:200,body:k(r,await R(r))}}t(Rn,"handleResume");async function Dn(e){const n=I(e,await C(e));if(n.run_state==="running")throw new c(409,"cron_running",`cron ${n.cron_id} has a run in flight \u2014 wait for it to settle`);const r=await _n(n,{outOfBand:!0});if(r===null)throw new c(409,"cron_running",`cron ${n.cron_id} was claimed by a concurrent run \u2014 check \`cron show\` for its result`);return{status:200,body:H(r)}}t(Dn,"handleRun");async function Wn(e){const n=new Date().toISOString();return{status:200,body:{unparked:await tn(n,K(e)),at:n}}}t(Wn,"handlePoke");function Bn(e,n){const r=e.principal;if(r.class==="cron")return r.cron===n.cron_id?null:{kind:"canceled",by:`cron ${r.cron}`};if(r.class==="broker"){const i=on(n.sink);return i?.kind==="node"&&i.node===r.node?null:{kind:"canceled",by:`node ${r.node}`}}const o=T(r);return{kind:"canceled",by:o===null||o==="app:terminal"?"the person":o}}t(Bn,"cancelNotice");async function xn(e){const n=e.params.cronId,r=await v(n);if(r!==null&&!await J(e,r))throw new c(404,"cron_not_found",`no cron ${n}`);if(r!==null&&!Y(r,U(e)))throw new c(404,"cron_not_found",`no cron ${n} in this profile \u2014 it is scoped to another profile`);r!==null&&I(e,r);const o=e.query.get("run_id"),i=e.principal.class==="cron"?o===e.principal.execution&&n===e.principal.cron:!0,l=o!==null&&i&&hn(n,o);return r!==null&&await vn(r,l?null:Bn(e,r),{preserveRunningProcess:l}),{status:204}}t(xn,"handleCancel");const ce=[{method:"POST",pattern:"/v1/crons",scope:"crtr:schedule",handler:Tn},{method:"GET",pattern:"/v1/crons",handler:En},{method:"GET",pattern:"/v1/crons/:cronId",handler:Un},{method:"POST",pattern:"/v1/crons/:cronId/pause",scope:"crtr:schedule",handler:Jn},{method:"POST",pattern:"/v1/crons/:cronId/resume",scope:"crtr:schedule",handler:Rn},{method:"POST",pattern:"/v1/crons/poke",scope:"crtr:schedule",handler:Wn},{method:"POST",pattern:"/v1/crons/:cronId/run",scope:"crtr:schedule",handler:Dn},{method:"DELETE",pattern:"/v1/crons/:cronId",scope:"crtr:schedule",handler:xn}];export{ce as cronRoutes};
@@ -1 +1 @@
1
- var x=Object.defineProperty;var c=(o,n)=>x(o,"name",{value:n,configurable:!0});import{realpathSync as E}from"node:fs";import{isAbsolute as y,relative as _,sep as h}from"node:path";import{ApiError as r}from"../../../api/index.js";import{coreHookCatalog as T}from"../../../build-root.js";import{getNode as O}from"../../../core/canvas/canvas.js";import{isSafeNodeId as P,nodeAgentDir as A}from"../../../core/canvas/paths.js";import{discoverHookRegistry as I}from"../../../core/command-hooks/discovery.js";import{EXEC_HOOK_TIMEOUT_MS as S}from"../../../core/command-hooks/transport/exec-invoke.js";import{buildAppProcessEnv as H}from"../../../core/runtime/spawn-env.js";import{compileLaunch as N}from"../../../core/spaces/mounts.js";import{appProcessSandboxed as M,launchAppProcess as R}from"../../../core/spaces/process.js";import{requireCurrentExecution as B}from"./broker-recovery.js";async function k(o,n,t){const i=o.params.id;if(i===void 0?o.principal.class!=="person":!P(i)||o.principal.class!=="broker"||o.principal.node!==i)throw new r(403,"permission_error","hook execution requires its current node, or the person for the global route");const e=i===void 0?null:await O(i);if(i!==void 0&&!e)throw new r(404,"not_found","node not found");if(i!==void 0&&await B(i,n),typeof t!="string"||!y(t))throw new r(400,"invalid_request","hook cwd must be absolute");if(!M())throw new r(400,"invalid_request","hook routes require the root launcher");let d;try{d=E(t)}catch(u){throw u.code==="ENOENT"?new r(400,"invalid_request","hook cwd does not exist"):u}if(e){if(e.isolated===!0){const a=A(i,e.grantee??"app:terminal"),s=_(a,d);if(s===".."||s.startsWith(`..${h}`)||s.startsWith(h))throw new r(403,"permission_error","hook cwd is outside the isolated node folder")}const u=await N({nodeId:i,app:o.principal.class==="broker"?o.principal.app:"app:terminal",sub:e.sub??"user:local",grantId:e.grant_id??null,scopes:e.scopes??null,isolated:e.isolated===!0,command:[],env:{},auditMissing:c(()=>{},"auditMissing")}),f=c(a=>{const s=_(a,d);return s===""||s!==".."&&!s.startsWith(`..${h}`)&&!y(s)},"within");if(!u.mounts.some(a=>f(a.source)))throw new r(403,"permission_error","hook cwd is outside the node mounts")}return{id:i,node:e,cwd:d,app:e&&o.principal.class==="broker"?o.principal.app:"app:terminal"}}c(k,"checkedContext");async function b(o,n){const t=I(await T(),o,n);if(!t.valid)throw new r(422,"hook_registry_invalid","the effective hook registry is invalid");return t}c(b,"currentRegistry");async function C(o){const{node:n,cwd:t}=await k(o,o.query.get("expected_execution_id"),o.query.get("cwd"));return{status:200,body:{hooks:(await b(t,n.profile_id??null)).hooks.filter(e=>e.plugin.scope==="user").map(e=>({id:e.id,plugin:e.plugin.name,target:e.target,phase:e.phase,op:e.op,description:e.description,effects:e.effects,declarationIndex:e.declarationIndex}))}}}c(C,"handleHookPlan");async function v(o){const n=o.body;if(!n||typeof n!="object"||Array.isArray(n))throw new r(400,"invalid_request","hook execution requires a JSON body");const t=n,{id:i,node:e,cwd:d,app:u}=await k(o,t.expected_execution_id,t.cwd);if(typeof t.hook_id!="string"||typeof t.request!="string")throw new r(400,"invalid_request","hook execution requires hook_id and request");const a=(await b(d,e?.profile_id??null)).hooks.find(p=>p.id===t.hook_id);if(!a)throw new r(404,"hook_not_registered","hook id is not registered for this cwd");const s=H(d,e?.profile_id??null,u),m=await R({...i===void 0?{}:{nodeId:i},app:u,command:[a.executable,"--crtr-hook-protocol","1"],cwd:d,pluginRoot:a.plugin.root,env:s,stdin:t.request,stdoutBytes:10*1024*1024,stderrBytes:64*1024});let l,w=!1;try{const p=await Promise.race([m.completion,new Promise((W,g)=>{l=setTimeout(()=>{w=!0,m.stop().then(()=>g(new r(504,"hook_timeout","hook executable timed out")),q=>g(q))},S)})]);if(w)throw new r(504,"hook_timeout","hook executable timed out");if(p.stdoutTruncated)throw new r(502,"hook_output_limit","hook stdout exceeded the 10 MiB cap");return{status:200,body:{stdout:p.stdout,status:p.exitCode,signal:p.signal}}}finally{l&&clearTimeout(l)}}c(v,"handleHookExec");const Y=[{method:"GET",pattern:"/v1/nodes/:id/hooks/plan",handler:C},{method:"POST",pattern:"/v1/nodes/:id/hooks/exec",handler:v},{method:"POST",pattern:"/v1/hooks/exec",handler:v}];export{Y as hookExecRoutes};
1
+ var x=Object.defineProperty;var u=(o,n)=>x(o,"name",{value:n,configurable:!0});import{realpathSync as E}from"node:fs";import{isAbsolute as y,relative as _,sep as h}from"node:path";import{ApiError as r}from"../../../api/index.js";import{coreHookCatalog as T}from"../../../build-root.js";import{getNode as I}from"../../../core/canvas/canvas.js";import{isSafeNodeId as O,nodeAgentDir as P}from"../../../core/canvas/paths.js";import{discoverHookRegistry as A}from"../../../core/command-hooks/discovery.js";import{EXEC_HOOK_TIMEOUT_MS as S}from"../../../core/command-hooks/transport/exec-invoke.js";import{buildAppProcessEnv as H}from"../../../core/runtime/spawn-env.js";import{compileLaunch as N}from"../../../core/spaces/mounts.js";import{appProcessSandboxed as M,launchAppProcess as R}from"../../../core/spaces/process.js";import{requireCurrentExecution as B}from"./broker-recovery.js";import{personId as C}from"../../../core/canvas/person.js";async function k(o,n,t){const i=o.params.id;if(i===void 0?o.principal.class!=="person":!O(i)||o.principal.class!=="broker"||o.principal.node!==i)throw new r(403,"permission_error","hook execution requires its current node, or the person for the global route");const e=i===void 0?null:await I(i);if(i!==void 0&&!e)throw new r(404,"not_found","node not found");if(i!==void 0&&await B(i,n),typeof t!="string"||!y(t))throw new r(400,"invalid_request","hook cwd must be absolute");if(!M())throw new r(400,"invalid_request","hook routes require the root launcher");let d;try{d=E(t)}catch(p){throw p.code==="ENOENT"?new r(400,"invalid_request","hook cwd does not exist"):p}if(e){if(e.isolated===!0){const a=P(i,e.grantee??"app:terminal"),s=_(a,d);if(s===".."||s.startsWith(`..${h}`)||s.startsWith(h))throw new r(403,"permission_error","hook cwd is outside the isolated node folder")}const p=await N({nodeId:i,app:o.principal.class==="broker"?o.principal.app:"app:terminal",sub:e.sub??C(),grantId:e.grant_id??null,scopes:e.scopes??null,isolated:e.isolated===!0,command:[],env:{},auditMissing:u(()=>{},"auditMissing")}),f=u(a=>{const s=_(a,d);return s===""||s!==".."&&!s.startsWith(`..${h}`)&&!y(s)},"within");if(!p.mounts.some(a=>f(a.source)))throw new r(403,"permission_error","hook cwd is outside the node mounts")}return{id:i,node:e,cwd:d,app:e&&o.principal.class==="broker"?o.principal.app:"app:terminal"}}u(k,"checkedContext");async function b(o,n){const t=A(await T(),o,n);if(!t.valid)throw new r(422,"hook_registry_invalid","the effective hook registry is invalid");return t}u(b,"currentRegistry");async function W(o){const{node:n,cwd:t}=await k(o,o.query.get("expected_execution_id"),o.query.get("cwd"));return{status:200,body:{hooks:(await b(t,n.profile_id??null)).hooks.filter(e=>e.plugin.scope==="user").map(e=>({id:e.id,plugin:e.plugin.name,target:e.target,phase:e.phase,op:e.op,description:e.description,effects:e.effects,declarationIndex:e.declarationIndex}))}}}u(W,"handleHookPlan");async function v(o){const n=o.body;if(!n||typeof n!="object"||Array.isArray(n))throw new r(400,"invalid_request","hook execution requires a JSON body");const t=n,{id:i,node:e,cwd:d,app:p}=await k(o,t.expected_execution_id,t.cwd);if(typeof t.hook_id!="string"||typeof t.request!="string")throw new r(400,"invalid_request","hook execution requires hook_id and request");const a=(await b(d,e?.profile_id??null)).hooks.find(c=>c.id===t.hook_id);if(!a)throw new r(404,"hook_not_registered","hook id is not registered for this cwd");const s=H(d,e?.profile_id??null,p),m=await R({...i===void 0?{}:{nodeId:i},app:p,command:[a.executable,"--crtr-hook-protocol","1"],cwd:d,pluginRoot:a.plugin.root,env:s,stdin:t.request,stdoutBytes:10*1024*1024,stderrBytes:64*1024});let l,w=!1;try{const c=await Promise.race([m.completion,new Promise(($,g)=>{l=setTimeout(()=>{w=!0,m.stop().then(()=>g(new r(504,"hook_timeout","hook executable timed out")),q=>g(q))},S)})]);if(w)throw new r(504,"hook_timeout","hook executable timed out");if(c.stdoutTruncated)throw new r(502,"hook_output_limit","hook stdout exceeded the 10 MiB cap");return{status:200,body:{stdout:c.stdout,status:c.exitCode,signal:c.signal}}}finally{l&&clearTimeout(l)}}u(v,"handleHookExec");const ee=[{method:"GET",pattern:"/v1/nodes/:id/hooks/plan",handler:W},{method:"POST",pattern:"/v1/nodes/:id/hooks/exec",handler:v},{method:"POST",pattern:"/v1/hooks/exec",handler:v}];export{ee as hookExecRoutes};
@@ -1,8 +1,8 @@
1
- var x=Object.defineProperty;var r=(e,t)=>x(e,"name",{value:t,configurable:!0});import{createHash as M}from"node:crypto";import{withCanvasWrite as N}from"../../../core/canvas/db.js";import{canRead as _}from"../../../core/graph/access.js";import{bodyOf as C}from"../../../core/graph/bodies.js";import{ensureOwner as H}from"../../../core/graph/objects.js";import{readerFor as j}from"../../../core/graph/reader.js";import{checkoutsForCwd as B}from"../../../core/graph/repo-sync/repos.js";import{RunError as E}from"../../../core/runs/operations.js";import{mapAsync as F}from"../../../core/async-array.js";const it=new Set(["memory.list","memory.get"]),W=1024*1024,g=/^[A-Za-z0-9_-]+(\/[A-Za-z0-9_-]+)*$/,O=["knowledge","preference"],s=r((e,t)=>new E(400,"invalid_request",e,t),"invalid"),R=r(()=>new E(404,"not_found","no memory document by that name"),"notFound");function v(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(v,"store");function Y(e){const t=e.get("kind");if(t===null)return null;if(!O.includes(t))throw s("kind must be knowledge or preference","kind");return t}r(Y,"kindOf");function J(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(J,"limitOf");function z(e,t){return M("sha256").update(JSON.stringify(["user",e,t])).digest("base64url").slice(0,16)}r(z,"filterHash");function U(e,t){return Buffer.from(JSON.stringify({n:e,f:t}),"utf8").toString("base64url")}r(U,"encodeCursor");function $(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"&&g.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($,"decodeCursor");async function S(e){return await H(e,"person","local-user","user:local","user")}r(S,"personObject");async function A(e,t){return await j(e,t,async n=>await B(e,n))}r(A,"graphReader");async function b(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 R();return{head:n,first:o}}r(b,"revisions");async function I(e,t){const{head:n,first:o}=await b(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(I,"item");async function G(e,t){return t===null?null:(await e.prepare(`SELECT i.external_id FROM objects a
1
+ var x=Object.defineProperty;var r=(e,t)=>x(e,"name",{value:t,configurable:!0});import{createHash as M}from"node:crypto";import{withCanvasWrite as N}from"../../../core/canvas/db.js";import{canRead as _}from"../../../core/graph/access.js";import{bodyOf as C}from"../../../core/graph/bodies.js";import{ownerForGrantee as H}from"../../../core/graph/objects.js";import{readerFor as F}from"../../../core/graph/reader.js";import{checkoutsForCwd as j}from"../../../core/graph/repo-sync/repos.js";import{RunError as E}from"../../../core/runs/operations.js";import{mapAsync as B}from"../../../core/async-array.js";import{personId as W}from"../../../core/canvas/person.js";const ut=new Set(["memory.list","memory.get"]),Y=1024*1024,g=/^[A-Za-z0-9_-]+(\/[A-Za-z0-9_-]+)*$/,O=["knowledge","preference"],s=r((e,t)=>new E(400,"invalid_request",e,t),"invalid"),R=r(()=>new E(404,"not_found","no memory document by that name"),"notFound");function v(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(v,"store");function J(e){const t=e.get("kind");if(t===null)return null;if(!O.includes(t))throw s("kind must be knowledge or preference","kind");return t}r(J,"kindOf");function z(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(z,"limitOf");function G(e,t){return M("sha256").update(JSON.stringify(["user",e,t])).digest("base64url").slice(0,16)}r(G,"filterHash");function U(e,t){return Buffer.from(JSON.stringify({n:e,f:t}),"utf8").toString("base64url")}r(U,"encodeCursor");function $(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"&&g.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($,"decodeCursor");async function S(e){return await H(e,W())}r(S,"personObject");async function A(e,t){return await F(e,t,async n=>await j(e,n))}r(A,"graphReader");async function I(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 R();return{head:n,first:o}}r(I,"revisions");async function b(e,t){const{head:n,first:o}=await I(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(b,"item");async function Z(e,t){return t===null?null:(await e.prepare(`SELECT i.external_id FROM objects a
3
3
  JOIN identities i ON i.object = CASE WHEN a.type = 'node' THEN a.owner 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");const L=200;async function P(e,t){v(t);const n=t.get("path");if(n!==null&&!g.test(n))throw s("path must be name segments of letters, digits, `_` or `-` joined by `/`","path");const o=Y(t),a=J(t),d=z(n,o);let i=$(t.get("cursor"),d);return await N(async u=>{const p=await A(u,e),c=await S(u),m=n===null?null:`${n}/`,h=o===null?O:[o],k=u.prepare(`SELECT o.*, d.summary, d.revision, d.source_path FROM objects o JOIN documents d ON d.object = o.id
4
+ WHERE a.id = ?`).get(t))?.external_id??null}r(Z,"granteeOf");function P(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(P,"utf8Prefix");const L=200;async function X(e,t){v(t);const n=t.get("path");if(n!==null&&!g.test(n))throw s("path must be name segments of letters, digits, `_` or `-` joined by `/`","path");const o=J(t),a=z(t),l=G(n,o);let i=$(t.get("cursor"),l);return await N(async u=>{const p=await A(u,e),c=await S(u),m=n===null?null:`${n}/`,h=o===null?O:[o],k=u.prepare(`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
- ORDER BY o.name LIMIT ?`),l=[];for(;;){const f=await k.all(c.id,h[0],h[h.length-1],m,m,i,i,L);for(const y of f)if(i=y.name,await _(u,p,y)&&l.push(y),l.length>a)break;if(l.length>a||f.length<L)break}const w=l.slice(0,a),T=l.length>a;return{items:await F(w,async f=>await I(u,f)),next_cursor:T?U(w[w.length-1].name,d):null}})}r(P,"memoryList");async function X(e,t){v(t);const n=t.get("name");if(n===null)throw s("name is required","name");if(!g.test(n))throw s("name must be segments of letters, digits, `_` or `-` joined by `/`","name");return await N(async o=>{const a=await A(o,e),d=await S(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
8
- 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 _(o,a,i))throw R();const{head:u,first:p}=await b(o,i),c=Buffer.from(C(u.body_hash,i.source_path),"utf8"),m=Z(c,W);return{...await I(o,i),body:m.toString("utf8"),size:c.length,truncated:m.length<c.length,grantee:await G(o,p.author)}})}r(X,"memoryGet");async function D(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 E(404,"not_found","unknown operation")}r(D,"handleMemoryOperation");const st=[{method:"GET",pattern:"/v1/memory",handler:r(async e=>await D("memory.list",e.principal,e.query),"handler")},{method:"GET",pattern:"/v1/memory/document",handler:r(async e=>await D("memory.get",e.principal,e.query),"handler")}];export{W as MEMORY_BODY_MAX_BYTES,it as MEMORY_OPERATIONS,D as handleMemoryOperation,X as memoryGet,P as memoryList,st as memoryRoutes,Z as utf8Prefix};
7
+ ORDER BY o.name LIMIT ?`),d=[];for(;;){const f=await k.all(c.id,h[0],h[h.length-1],m,m,i,i,L);for(const y of f)if(i=y.name,await _(u,p,y)&&d.push(y),d.length>a)break;if(d.length>a||f.length<L)break}const w=d.slice(0,a),T=d.length>a;return{items:await B(w,async f=>await b(u,f)),next_cursor:T?U(w[w.length-1].name,l):null}})}r(X,"memoryList");async function K(e,t){v(t);const n=t.get("name");if(n===null)throw s("name is required","name");if(!g.test(n))throw s("name must be segments of letters, digits, `_` or `-` joined by `/`","name");return await N(async o=>{const a=await A(o,e),l=await S(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
8
+ WHERE o.owner = ? AND o.type = 'document' AND o.name = ? AND o.deleted_at IS NULL AND o.kind IN ('knowledge', 'preference')`).get(l.id,n);if(!i||!await _(o,a,i))throw R();const{head:u,first:p}=await I(o,i),c=Buffer.from(C(u.body_hash,i.source_path),"utf8"),m=P(c,Y);return{...await b(o,i),body:m.toString("utf8"),size:c.length,truncated:m.length<c.length,grantee:await Z(o,p.author)}})}r(K,"memoryGet");async function D(e,t,n){if(e==="memory.list")return{status:200,body:await X(t,n)};if(e==="memory.get")return{status:200,body:await K(t,n)};throw new E(404,"not_found","unknown operation")}r(D,"handleMemoryOperation");const ct=[{method:"GET",pattern:"/v1/memory",handler:r(async e=>await D("memory.list",e.principal,e.query),"handler")},{method:"GET",pattern:"/v1/memory/document",handler:r(async e=>await D("memory.get",e.principal,e.query),"handler")}];export{Y as MEMORY_BODY_MAX_BYTES,ut as MEMORY_OPERATIONS,D as handleMemoryOperation,K as memoryGet,X as memoryList,ct as memoryRoutes,P as utf8Prefix};
@@ -1,2 +1,2 @@
1
- var ce=Object.defineProperty;var u=(t,e)=>ce(t,"name",{value:e,configurable:!0});import{randomBytes as ue}from"node:crypto";import{claimNodeMail as le,acknowledgeNodeMail as fe}from"../../../core/canvas/deliveries.js";import{nodeMailEntry as me}from"../../../core/feed/inbox.js";import{enqueueNodeMail as D,cancelPendingNodeMail as pe}from"../../../core/feed/messages.js";import{reviveNode as L}from"../../../core/runtime/revive.js";import{BrokerUnreachableError as U}from"../../../core/runtime/broker-request.js";import{isBrokerLive as R}from"../../../core/runtime/model-swap.js";import{deliverLive as ye,interruptLive as he}from"../../../core/runtime/interactive-deliver.js";import{isProfilePaused as we}from"../../../core/profiles/manifest.js";import{getNode as O,withFreshTerminalGuard as be}from"../../../core/canvas/canvas.js";import{getById as G,nodeObject as F,ownerForGrantee as ge}from"../../../core/graph/objects.js";import{recordActedOn as ve}from"../../../core/graph/edges.js";import{recordWatch as H}from"../../../core/graph/watches.js";import{publish as V}from"../../../core/graph/events.js";import{readerFor as K}from"../reader.js";import{canRead as _e}from"../../../core/graph/access.js";import{withCanvasWrite as k}from"../../../core/canvas/db.js";import{getPendingStructuredRequestForNode as Q}from"../../../core/canvas/structured-requests.js";import{consumeDeadlineOnWake as X}from"../../../core/feed/messages.js";import{assertNotFinalized as M,assertFinalizedForReopen as ke,commitReopenResident as P}from"../../../core/runtime/reopen.js";import{admitLegacyStructuredOutput as Se}from"../../structured-requests/sidecar.js";import{assertOutputSchemaAccepted as $e}from"../../../core/runtime/structured-output.js";import{appendSituationalContext as E,formatSituationalProse as Ne}from"../../../core/runtime/situational-context.js";import{formatDataCard as Y}from"../../../shared/generated-context.js";import{hasNoNaturalCycle as je}from"../../../core/runtime/revive-all.js";import{recordPendingParkActivity as Ae}from"../../park-pending.js";import{wantsExecution as qe}from"../../reconcilers/node-lifecycle/wants-execution.js";import{hasFreshGroundState as Oe}from"../../../core/runtime/revive.js";import{CrtrError as Ce,notFound as C,usage as c}from"../../../core/errors.js";import{emitEvent as xe}from"../../../core/events/emit.js";import{assertScope as Re}from"../../../core/scopes.js";import{InputError as I}from"../../../core/io.js";import{ApiError as Fe}from"../../../api/index.js";import{describeObject as Me,stubOf as Pe}from"../../../core/peer/stubs.js";import{machineNameOf as Z}from"../../../core/peer/names.js";import{callerNode as Ee,callerStub as Ie,forwardVerb as ee,relayError as te,remoteStub as Te,unknownError as re,withMachine as ne}from"../../peer/forward.js";import{ownerOnly as Be}from"../router.js";const ze=["critical","urgent","normal","deferred"];function oe(t,e){if(typeof t!="object"||t===null||Array.isArray(t))throw c(`${e} must be an object { kind, facts?, body? }`);const a=t,n=a.kind;if(typeof n!="string"||n.trim()==="")throw c(`${e}.kind is required`);if(!n.includes(":"))throw c(`${e}.kind must be namespaced (contain ':'): ${n}`);const r={kind:n},o=a.facts;if(o!==void 0){if(typeof o!="object"||o===null||Array.isArray(o))throw c(`${e}.facts must be an object of string or number values`);const d={};for(const[l,m]of Object.entries(o)){if(typeof m!="string"&&typeof m!="number")throw c(`${e}.facts.${l} must be a string or number`);d[l]=m}r.facts=d}const s=a.body;if(s!==void 0){if(typeof s!="string")throw c(`${e}.body must be a string`);r.body=s}return r}u(oe,"parseCardRequest");function ae(t,e){try{return Y(t.kind,t.facts??{},t.body??"")}catch(a){throw c(`${e}: ${a instanceof Error?a.message:String(a)}`)}}u(ae,"renderCard");function We(t){if(typeof t!="object"||t===null)throw c("a message requires a JSON body { body, tier?, fresh? }");const e=t,a=e.body,n=e.fresh===!0,r=e.tier,o=e.situational_context,s=e.output_schema,d=typeof a=="string"&&a.trim()!=="",l=typeof o=="string"&&o.trim()!=="",m=typeof s=="string"&&s.trim()!=="",v=e.situational_card,S=e.context_cards,b=v===void 0?void 0:oe(v,"situational_card");if(S!==void 0&&!Array.isArray(S))throw c("context_cards must be an array of { kind, facts?, body? }");const p=S?.map((N,$)=>oe(N,`context_cards[${$}]`));if(b!==void 0&&typeof o=="string"&&o!=="")throw c("situational_card and situational_context are mutually exclusive");const w=b!==void 0||p!==void 0&&p.length>0;if(!n&&!d&&!l&&!m&&!w)throw c("a message requires a non-empty body (or fresh: true, situational_context, a runtime card, or output_schema)");if(n&&p!==void 0&&p.length>0)throw c("context_cards cannot ride a fresh revive (no inbox entry carries them)");if(r!==void 0&&!ze.includes(r))throw c(`invalid tier: ${String(r)} (expected critical|urgent|normal|deferred)`);const f={body:typeof a=="string"?a:""};r!==void 0&&(f.tier=r),n&&(f.fresh=!0),e.reopen===!0&&(f.reopen=!0),typeof o=="string"&&(f.situational_context=o),b!==void 0&&(f.situational_card=b),p!==void 0&&(f.context_cards=p),typeof s=="string"&&(f.output_schema=s),typeof e.from=="string"&&(f.from=e.from);const y=e.delivery;if(y!==void 0&&y!=="interactive")throw c(`invalid delivery: ${String(y)} (expected interactive)`);if(y==="interactive"){if(n||f.situational_context!==void 0||f.output_schema!==void 0)throw c("interactive delivery supports a body, runtime cards, and reopen only (no fresh, situational_context, or output_schema)");if(!d)throw c("interactive delivery requires a non-empty body");if(f.tier==="deferred")throw c("interactive delivery cannot be deferred");f.delivery="interactive"}return f}u(We,"parseSendBody");function Je(t){let e;try{e=JSON.parse(t)}catch{throw c("output_schema must be a JSON schema string")}if(typeof e!="object"||e===null||Array.isArray(e))throw c("output_schema must be a JSON schema object");return e}u(Je,"parseSchema");function De(t){return t.split(`
2
- `)[0].slice(0,120)}u(De,"label");function ie(t,e){return e===null?"":Y("reopen-final-report",{report:`${t}/${e}`},"This node previously completed work. Read this final report before acting on the new instruction.")}u(ie,"previousFinalReportCard");async function Le(t,e,a){if(a!==null&&a!=="human"&&(await G(t,a))?.type==="node"){const o=await F(t,a);return{actor:o,senderNode:o}}if(a==="human")return{actor:await ge(t,"user:local"),senderNode:null};const n=await K(t,e);return{actor:n.class==="person"?n.person:n.class==="app"?n.app:n.node,senderNode:n.class==="node"?n.node:null}}u(Le,"messageActor");async function se(t,e,a,n,r,o){const s=await F(t,a),{actor:d,senderNode:l}=await Le(t,e,n),m=r===null?{}:{pointer:r};await ve(t,d,s),l!==null&&l.id!==s.id&&await H(t,l,s,"message",{endsOn:o&&r!==null?`result:${r}`:"final"}),await V(t,{event:"messaged",object:s,actor:d,attrs:{},...m}),l!==null&&await V(t,{event:"sent",object:l,actor:l,attrs:{to:s.id},...m})}u(se,"recordMessage");function Ue(t,e){return new I({error:"deferred_no_natural_cycle",message:`${t} is ${e} with no natural next cycle ahead of it \u2014 a deferred message would never be delivered.`,next:"Use --tier normal, urgent, or critical to wake it now, or --reopen (with a body or --fresh) to re-task it first."})}u(Ue,"deferredNoNaturalCycle");async function Ge(t){if(!await Oe(t))throw new Fe(422,"unprocessable",`node ${t} has no goal/roadmap on disk \u2014 a fresh revive would resume amnesiac.`)}u(Ge,"assertRecoverableForFresh");function He(t,e){return t instanceof I?{error:t.payload.error,message:t.payload.message,next:t.payload.next,message_id:e}:t instanceof Ce?{error:t.code,message:t.message,message_id:e}:{error:"wake_failed",message:"the target could not be woken; see the daemon log",message_id:e}}u(He,"wakeFailure");async function Ve(t,e){const a=typeof t.body=="object"&&t.body!==null&&!Array.isArray(t.body)?{...t.body}:t.body;typeof a=="object"&&a!==null&&delete a.from;const n=await ee(t,e,{method:"POST",path:`/v1/nodes/${encodeURIComponent(e)}/messages`,body:a});if(n.kind==="local")return null;if(n.kind==="unknown")throw re(e,n.unreachable);if(n.status>=400)throw te(n.status,n.body);return await k(async r=>{const o=await Ee(r,t);if(o===null)return;const s=n.body?.object,d=await Te(r,e,"node",n.machine.id,s);await H(r,o,d,"message",{endsOn:"final"})}),{status:n.status,body:ne(n.body,n.machine)}}u(Ve,"forwardMessage");async function Ke(t){const e=await Qe(t);if(t.principal.class!=="forwarded"||typeof e.body!="object"||e.body===null)return e;const a=await k(async n=>{const r=await F(n,t.params.id);return await _e(n,await K(n,t),r)?await Me(n,r):{id:r.id,type:r.type,kind:null,name:r.id,owner:null}});return{...e,body:{...e.body,object:a}}}u(Ke,"handleMessage");async function Qe(t){const e=t.params.id,a=await Ve(t,e);if(a!==null)return a;const n=await O(e);if(n===null)throw C(`unknown node: ${e}`,{received:e});const r=We(t.body),o=r.tier??"normal",s=we(n.profile_id),d=t.principal.class==="forwarded"?await k(async i=>(await Ie(i,t))?.id??null):r.from??null;if(d!==null){const i=await O(d);i!==null&&Re(i,"crtr:act")}const l=d===null?null:await k(async i=>{const h=await G(i,d);return h===null?null:(await Pe(i,h))?.home_machine??null}),m=l===null?void 0:`${d} on ${Z(l)}`,v=t.principal.class==="broker"?t.principal.node:null,S=l===null?{}:{from_machine:Z(l)},b=r.body.trim()!=="",p=r.situational_card!==void 0?ae(r.situational_card,"situational_card"):r.situational_context!==void 0?Ne(r.situational_context.trim()):"",w=p!=="",f=(r.context_cards??[]).map((i,h)=>ae(i,`context_cards[${h}]`)),y=r.output_schema!==void 0&&r.output_schema.trim()!==""?Je(r.output_schema):null;y!==null&&await $e(y);let N=!1;const $=u(async i=>{if(!(y===null||N)){if(await Q(e)!==null)throw new I({error:"structured_request_conflict",message:`node ${e} already has a pending structured request`,next:"Wait for the current request to settle before requesting another structured result."});await Se(e,"oneoff",y,i),N=!0}},"ensureSchema");if(r.fresh){const i=r.reopen?await ke(e):null;r.reopen||await M(e),await Ge(e),await $(),w&&E(e,p),r.reopen&&await P(e,i,v);const h=await L(e,{resume:!1,capacity:"refuse"});return{status:201,body:{node_id:e,delivered:!1,revived:h.launch!==void 0}}}r.delivery==="interactive"&&!r.reopen&&await M(e);let T=!1,_="";if(r.delivery==="interactive"&&r.reopen&&(_=ie(e,await P(e,void 0,v)),T=!0),r.delivery==="interactive"&&await $(),r.delivery==="interactive"&&!s&&!n.run_id&&R(n))try{return w&&E(e,p),await ye(e,r.body,{cards:[..._===""?[]:[_],...w?[p]:[],...f],origin:d==="human"?{type:"human"}:{type:"runtime",kind:"inbox",entries:[{...d===null?{}:{from:d},...m===void 0?{}:{fromName:m},kind:"message",tier:o}]}}),await k(async h=>await se(h,t,e,d,null,!1)),await X(e),{status:201,body:{node_id:e,delivered:!0,revived:!1,delivered_via:"engine"}}}catch(i){if(!(i instanceof U))throw i}const B=u(async()=>{r.reopen||await M(e);const i=ue(16).toString("hex"),h=u(async q=>await se(q,t,e,d,i,y!==null),"withinEnqueue");await $(i),w&&E(e,p),r.reopen&&!T&&(_=ie(e,await P(e,void 0,v)));const x=[..._===""?[]:[_],...f],J=x.length>0?{cards:x}:{};if(b||y!==null){const q=b?r.body:`A one-off structured-output request has been granted. Submit a result matching the requested schema with the \`submit_result\` tool (\`request_id: "${(await Q(e))?.request_id??"<request-id>"}"\`) before you stop; after it is accepted, continue normally.`;return await D(e,{senderNodeId:d,...m===void 0?{}:{senderName:m},urgency:o,wake:1,kind:"message",messageId:i,withinEnqueue:h,label:De(q),bodyJson:{body:q,...S,...w?{situational:!0}:{},...J}})}return await D(e,{senderNodeId:d,...m===void 0?{}:{senderName:m},urgency:o,wake:1,kind:"message",messageId:i,withinEnqueue:h,label:w?"(ambient context updated)":"(context delivered)",bodyJson:{...w?{situational:!0}:{},situationalOnly:!0,...J}})},"deliverImmediate"),g=await u(async()=>{if(o==="deferred"){const i=await be(e,je,B);if(i.kind==="missing")throw C(`unknown node: ${e}`,{received:e});if(i.kind==="terminal")throw Ue(e,i.status);return i.result}return await B()},"deliver")();g.urgency!=="deferred"&&await k(async()=>Ae(e));const j=await O(e);if(j===null)throw C(`unknown node: ${e}`,{received:e});n.frozen_at!==null&&await X(e);let z=!1,W=!1,A;if((r.reopen||j.lifecycle==="terminal"||!await qe(j))&&g.urgency!=="deferred"&&!s&&!R(j))try{const i=await L(e,{resume:!0,capacity:"freeze"});z=i.launch!==void 0,W=i.outcome==="frozen"}catch(i){A=He(i,g.messageId),xe({level:"error",event:"message.wake_failed",node_id:e,error:i,fields:{message_id:g.messageId,error_code:A.error}})}return{status:201,body:{node_id:e,delivered:!0,revived:z,...W?{not_revived_reason:"capacity_frozen"}:{},...A===void 0?{}:{wake_failed:A},delivered_at:g.createdAt,...g.urgency===o?{}:{delivered_tier:g.urgency},...r.delivery==="interactive"?{delivered_via:"inbox"}:{}}}}u(Qe,"handleMessageHere");async function Xe(t){const e=t.params.id,a=await ee(t,e,{method:"POST",path:`/v1/nodes/${encodeURIComponent(e)}/interrupt`,body:t.body});if(a.kind==="unknown")throw re(e,a.unreachable);if(a.kind==="remote"){if(a.status>=400)throw te(a.status,a.body);return{status:a.status,body:ne(a.body,a.machine)}}const n=await O(e);if(n===null)throw C(`unknown node: ${e}`,{received:e});const r=await pe(e,{senderNodeId:"human",kind:"message"});let o=!1;if(R(n))try{o=await he(e)!=="idle"}catch(d){if(!(d instanceof U))throw d}return{status:200,body:{node_id:e,outcome:o?"aborted_turn":r.length>0?"canceled_pending":"idle",aborted_turn:o,canceled_pending:r.length}}}u(Xe,"handleInterrupt");function de(t){if(typeof t.body!="object"||t.body===null||Array.isArray(t.body))throw c("mail requires an object body");const e=t.body;if(typeof e.execution_id!="string"||e.execution_id.trim()==="")throw c("execution_id is required");return e}u(de,"mailBody");async function Ye(t){const e=de(t),a=e.channel;if(a!=="wake"&&a!=="passive"&&a!=="deferred_run")throw c("channel must be wake, passive, or deferred_run");const n=await le(t.params.id,e.execution_id,a);return{status:200,body:{action:n.action,deliveries:n.deliveries.map(o=>({delivery_id:o.deliveryId,attempts:o.attempts,handoff:o.handoff,entry:{...me(o),seq:o.message.seq}}))}}}u(Ye,"handleMailClaim");async function Ze(t){const e=de(t);if(!Array.isArray(e.deliveries))throw c("deliveries must be an array");const a=e.deliveries.map(o=>{if(typeof o!="object"||o===null||Array.isArray(o))throw c("each delivery must be an object");const s=o;if(typeof s.delivery_id!="string"||s.delivery_id==="")throw c("delivery_id is required");if(!Number.isSafeInteger(s.attempts)||s.attempts<1)throw c("attempts must be a positive integer");if(s.disposition!=="acknowledged"&&s.disposition!=="released")throw c("disposition must be acknowledged or released");return{delivery_id:s.delivery_id,attempts:s.attempts,disposition:s.disposition}}),n=await fe(t.params.id,e.execution_id,a.map(o=>({deliveryId:o.delivery_id,attempts:o.attempts,disposition:o.disposition})));return{status:200,body:{action:n.action,results:n.results.map(o=>({delivery_id:o.deliveryId,outcome:o.outcome}))}}}u(Ze,"handleMailAcknowledge");const Wt=Be([{method:"POST",pattern:"/v1/nodes/:id/mail/claim",handler:Ye},{method:"POST",pattern:"/v1/nodes/:id/mail/acknowledge",handler:Ze}]),Jt=[{method:"POST",pattern:"/v1/nodes/:id/messages",scope:"crtr:act",handler:Ke},{method:"POST",pattern:"/v1/nodes/:id/interrupt",scope:"crtr:act",handler:Xe}];export{Wt as brokerMailRoutes,Ke as handleMessage,Jt as messageRoutes};
1
+ var ce=Object.defineProperty;var u=(t,e)=>ce(t,"name",{value:e,configurable:!0});import{randomBytes as ue}from"node:crypto";import{claimNodeMail as le,acknowledgeNodeMail as fe}from"../../../core/canvas/deliveries.js";import{nodeMailEntry as me}from"../../../core/feed/inbox.js";import{enqueueNodeMail as D,cancelPendingNodeMail as pe}from"../../../core/feed/messages.js";import{reviveNode as L}from"../../../core/runtime/revive.js";import{BrokerUnreachableError as U}from"../../../core/runtime/broker-request.js";import{isBrokerLive as R}from"../../../core/runtime/model-swap.js";import{deliverLive as ye,interruptLive as he}from"../../../core/runtime/interactive-deliver.js";import{isProfilePaused as we}from"../../../core/profiles/manifest.js";import{getNode as O,withFreshTerminalGuard as be}from"../../../core/canvas/canvas.js";import{getById as G,nodeObject as F,ownerForGrantee as ge}from"../../../core/graph/objects.js";import{recordActedOn as ve}from"../../../core/graph/edges.js";import{recordWatch as H}from"../../../core/graph/watches.js";import{publish as V}from"../../../core/graph/events.js";import{readerFor as K}from"../reader.js";import{canRead as _e}from"../../../core/graph/access.js";import{withCanvasWrite as k}from"../../../core/canvas/db.js";import{getPendingStructuredRequestForNode as Q}from"../../../core/canvas/structured-requests.js";import{consumeDeadlineOnWake as X}from"../../../core/feed/messages.js";import{assertNotFinalized as M,assertFinalizedForReopen as ke,commitReopenResident as I}from"../../../core/runtime/reopen.js";import{admitLegacyStructuredOutput as Se}from"../../structured-requests/sidecar.js";import{assertOutputSchemaAccepted as $e}from"../../../core/runtime/structured-output.js";import{appendSituationalContext as P,formatSituationalProse as Ne}from"../../../core/runtime/situational-context.js";import{formatDataCard as Y}from"../../../shared/generated-context.js";import{hasNoNaturalCycle as je}from"../../../core/runtime/revive-all.js";import{recordPendingParkActivity as Ae}from"../../park-pending.js";import{wantsExecution as qe}from"../../reconcilers/node-lifecycle/wants-execution.js";import{hasFreshGroundState as Oe}from"../../../core/runtime/revive.js";import{CrtrError as Ce,notFound as C,usage as c}from"../../../core/errors.js";import{emitEvent as xe}from"../../../core/events/emit.js";import{assertScope as Re}from"../../../core/scopes.js";import{InputError as E}from"../../../core/io.js";import{ApiError as Fe}from"../../../api/index.js";import{describeObject as Me,stubOf as Ie}from"../../../core/peer/stubs.js";import{machineNameOf as Z}from"../../../core/peer/names.js";import{callerNode as Pe,callerStub as Ee,forwardVerb as ee,relayError as te,remoteStub as Te,unknownError as re,withMachine as ne}from"../../peer/forward.js";import{ownerOnly as Be}from"../router.js";import{personId as ze}from"../../../core/canvas/person.js";const We=["critical","urgent","normal","deferred"];function oe(t,e){if(typeof t!="object"||t===null||Array.isArray(t))throw c(`${e} must be an object { kind, facts?, body? }`);const a=t,n=a.kind;if(typeof n!="string"||n.trim()==="")throw c(`${e}.kind is required`);if(!n.includes(":"))throw c(`${e}.kind must be namespaced (contain ':'): ${n}`);const r={kind:n},o=a.facts;if(o!==void 0){if(typeof o!="object"||o===null||Array.isArray(o))throw c(`${e}.facts must be an object of string or number values`);const d={};for(const[l,m]of Object.entries(o)){if(typeof m!="string"&&typeof m!="number")throw c(`${e}.facts.${l} must be a string or number`);d[l]=m}r.facts=d}const s=a.body;if(s!==void 0){if(typeof s!="string")throw c(`${e}.body must be a string`);r.body=s}return r}u(oe,"parseCardRequest");function ae(t,e){try{return Y(t.kind,t.facts??{},t.body??"")}catch(a){throw c(`${e}: ${a instanceof Error?a.message:String(a)}`)}}u(ae,"renderCard");function Je(t){if(typeof t!="object"||t===null)throw c("a message requires a JSON body { body, tier?, fresh? }");const e=t,a=e.body,n=e.fresh===!0,r=e.tier,o=e.situational_context,s=e.output_schema,d=typeof a=="string"&&a.trim()!=="",l=typeof o=="string"&&o.trim()!=="",m=typeof s=="string"&&s.trim()!=="",v=e.situational_card,S=e.context_cards,b=v===void 0?void 0:oe(v,"situational_card");if(S!==void 0&&!Array.isArray(S))throw c("context_cards must be an array of { kind, facts?, body? }");const p=S?.map((N,$)=>oe(N,`context_cards[${$}]`));if(b!==void 0&&typeof o=="string"&&o!=="")throw c("situational_card and situational_context are mutually exclusive");const w=b!==void 0||p!==void 0&&p.length>0;if(!n&&!d&&!l&&!m&&!w)throw c("a message requires a non-empty body (or fresh: true, situational_context, a runtime card, or output_schema)");if(n&&p!==void 0&&p.length>0)throw c("context_cards cannot ride a fresh revive (no inbox entry carries them)");if(r!==void 0&&!We.includes(r))throw c(`invalid tier: ${String(r)} (expected critical|urgent|normal|deferred)`);const f={body:typeof a=="string"?a:""};r!==void 0&&(f.tier=r),n&&(f.fresh=!0),e.reopen===!0&&(f.reopen=!0),typeof o=="string"&&(f.situational_context=o),b!==void 0&&(f.situational_card=b),p!==void 0&&(f.context_cards=p),typeof s=="string"&&(f.output_schema=s),typeof e.from=="string"&&(f.from=e.from);const y=e.delivery;if(y!==void 0&&y!=="interactive")throw c(`invalid delivery: ${String(y)} (expected interactive)`);if(y==="interactive"){if(n||f.situational_context!==void 0||f.output_schema!==void 0)throw c("interactive delivery supports a body, runtime cards, and reopen only (no fresh, situational_context, or output_schema)");if(!d)throw c("interactive delivery requires a non-empty body");if(f.tier==="deferred")throw c("interactive delivery cannot be deferred");f.delivery="interactive"}return f}u(Je,"parseSendBody");function De(t){let e;try{e=JSON.parse(t)}catch{throw c("output_schema must be a JSON schema string")}if(typeof e!="object"||e===null||Array.isArray(e))throw c("output_schema must be a JSON schema object");return e}u(De,"parseSchema");function Le(t){return t.split(`
2
+ `)[0].slice(0,120)}u(Le,"label");function ie(t,e){return e===null?"":Y("reopen-final-report",{report:`${t}/${e}`},"This node previously completed work. Read this final report before acting on the new instruction.")}u(ie,"previousFinalReportCard");async function Ue(t,e,a){if(a!==null&&a!=="human"&&(await G(t,a))?.type==="node"){const o=await F(t,a);return{actor:o,senderNode:o}}if(a==="human")return{actor:await ge(t,ze()),senderNode:null};const n=await K(t,e);return{actor:n.class==="person"?n.person:n.class==="app"?n.app:n.node,senderNode:n.class==="node"?n.node:null}}u(Ue,"messageActor");async function se(t,e,a,n,r,o){const s=await F(t,a),{actor:d,senderNode:l}=await Ue(t,e,n),m=r===null?{}:{pointer:r};await ve(t,d,s),l!==null&&l.id!==s.id&&await H(t,l,s,"message",{endsOn:o&&r!==null?`result:${r}`:"final"}),await V(t,{event:"messaged",object:s,actor:d,attrs:{},...m}),l!==null&&await V(t,{event:"sent",object:l,actor:l,attrs:{to:s.id},...m})}u(se,"recordMessage");function Ge(t,e){return new E({error:"deferred_no_natural_cycle",message:`${t} is ${e} with no natural next cycle ahead of it \u2014 a deferred message would never be delivered.`,next:"Use --tier normal, urgent, or critical to wake it now, or --reopen (with a body or --fresh) to re-task it first."})}u(Ge,"deferredNoNaturalCycle");async function He(t){if(!await Oe(t))throw new Fe(422,"unprocessable",`node ${t} has no goal/roadmap on disk \u2014 a fresh revive would resume amnesiac.`)}u(He,"assertRecoverableForFresh");function Ve(t,e){return t instanceof E?{error:t.payload.error,message:t.payload.message,next:t.payload.next,message_id:e}:t instanceof Ce?{error:t.code,message:t.message,message_id:e}:{error:"wake_failed",message:"the target could not be woken; see the daemon log",message_id:e}}u(Ve,"wakeFailure");async function Ke(t,e){const a=typeof t.body=="object"&&t.body!==null&&!Array.isArray(t.body)?{...t.body}:t.body;typeof a=="object"&&a!==null&&delete a.from;const n=await ee(t,e,{method:"POST",path:`/v1/nodes/${encodeURIComponent(e)}/messages`,body:a});if(n.kind==="local")return null;if(n.kind==="unknown")throw re(e,n.unreachable);if(n.status>=400)throw te(n.status,n.body);return await k(async r=>{const o=await Pe(r,t);if(o===null)return;const s=n.body?.object,d=await Te(r,e,"node",n.machine.id,s);await H(r,o,d,"message",{endsOn:"final"})}),{status:n.status,body:ne(n.body,n.machine)}}u(Ke,"forwardMessage");async function Qe(t){const e=await Xe(t);if(t.principal.class!=="forwarded"||typeof e.body!="object"||e.body===null)return e;const a=await k(async n=>{const r=await F(n,t.params.id);return await _e(n,await K(n,t),r)?await Me(n,r):{id:r.id,type:r.type,kind:null,name:r.id,owner:null}});return{...e,body:{...e.body,object:a}}}u(Qe,"handleMessage");async function Xe(t){const e=t.params.id,a=await Ke(t,e);if(a!==null)return a;const n=await O(e);if(n===null)throw C(`unknown node: ${e}`,{received:e});const r=Je(t.body),o=r.tier??"normal",s=we(n.profile_id),d=t.principal.class==="forwarded"?await k(async i=>(await Ee(i,t))?.id??null):r.from??null;if(d!==null){const i=await O(d);i!==null&&Re(i,"crtr:act")}const l=d===null?null:await k(async i=>{const h=await G(i,d);return h===null?null:(await Ie(i,h))?.home_machine??null}),m=l===null?void 0:`${d} on ${Z(l)}`,v=t.principal.class==="broker"?t.principal.node:null,S=l===null?{}:{from_machine:Z(l)},b=r.body.trim()!=="",p=r.situational_card!==void 0?ae(r.situational_card,"situational_card"):r.situational_context!==void 0?Ne(r.situational_context.trim()):"",w=p!=="",f=(r.context_cards??[]).map((i,h)=>ae(i,`context_cards[${h}]`)),y=r.output_schema!==void 0&&r.output_schema.trim()!==""?De(r.output_schema):null;y!==null&&await $e(y);let N=!1;const $=u(async i=>{if(!(y===null||N)){if(await Q(e)!==null)throw new E({error:"structured_request_conflict",message:`node ${e} already has a pending structured request`,next:"Wait for the current request to settle before requesting another structured result."});await Se(e,"oneoff",y,i),N=!0}},"ensureSchema");if(r.fresh){const i=r.reopen?await ke(e):null;r.reopen||await M(e),await He(e),await $(),w&&P(e,p),r.reopen&&await I(e,i,v);const h=await L(e,{resume:!1,capacity:"refuse"});return{status:201,body:{node_id:e,delivered:!1,revived:h.launch!==void 0}}}r.delivery==="interactive"&&!r.reopen&&await M(e);let T=!1,_="";if(r.delivery==="interactive"&&r.reopen&&(_=ie(e,await I(e,void 0,v)),T=!0),r.delivery==="interactive"&&await $(),r.delivery==="interactive"&&!s&&!n.run_id&&R(n))try{return w&&P(e,p),await ye(e,r.body,{cards:[..._===""?[]:[_],...w?[p]:[],...f],origin:d==="human"?{type:"human"}:{type:"runtime",kind:"inbox",entries:[{...d===null?{}:{from:d},...m===void 0?{}:{fromName:m},kind:"message",tier:o}]}}),await k(async h=>await se(h,t,e,d,null,!1)),await X(e),{status:201,body:{node_id:e,delivered:!0,revived:!1,delivered_via:"engine"}}}catch(i){if(!(i instanceof U))throw i}const B=u(async()=>{r.reopen||await M(e);const i=ue(16).toString("hex"),h=u(async q=>await se(q,t,e,d,i,y!==null),"withinEnqueue");await $(i),w&&P(e,p),r.reopen&&!T&&(_=ie(e,await I(e,void 0,v)));const x=[..._===""?[]:[_],...f],J=x.length>0?{cards:x}:{};if(b||y!==null){const q=b?r.body:`A one-off structured-output request has been granted. Submit a result matching the requested schema with the \`submit_result\` tool (\`request_id: "${(await Q(e))?.request_id??"<request-id>"}"\`) before you stop; after it is accepted, continue normally.`;return await D(e,{senderNodeId:d,...m===void 0?{}:{senderName:m},urgency:o,wake:1,kind:"message",messageId:i,withinEnqueue:h,label:Le(q),bodyJson:{body:q,...S,...w?{situational:!0}:{},...J}})}return await D(e,{senderNodeId:d,...m===void 0?{}:{senderName:m},urgency:o,wake:1,kind:"message",messageId:i,withinEnqueue:h,label:w?"(ambient context updated)":"(context delivered)",bodyJson:{...w?{situational:!0}:{},situationalOnly:!0,...J}})},"deliverImmediate"),g=await u(async()=>{if(o==="deferred"){const i=await be(e,je,B);if(i.kind==="missing")throw C(`unknown node: ${e}`,{received:e});if(i.kind==="terminal")throw Ge(e,i.status);return i.result}return await B()},"deliver")();g.urgency!=="deferred"&&await k(async()=>Ae(e));const j=await O(e);if(j===null)throw C(`unknown node: ${e}`,{received:e});n.frozen_at!==null&&await X(e);let z=!1,W=!1,A;if((r.reopen||j.lifecycle==="terminal"||!await qe(j))&&g.urgency!=="deferred"&&!s&&!R(j))try{const i=await L(e,{resume:!0,capacity:"freeze"});z=i.launch!==void 0,W=i.outcome==="frozen"}catch(i){A=Ve(i,g.messageId),xe({level:"error",event:"message.wake_failed",node_id:e,error:i,fields:{message_id:g.messageId,error_code:A.error}})}return{status:201,body:{node_id:e,delivered:!0,revived:z,...W?{not_revived_reason:"capacity_frozen"}:{},...A===void 0?{}:{wake_failed:A},delivered_at:g.createdAt,...g.urgency===o?{}:{delivered_tier:g.urgency},...r.delivery==="interactive"?{delivered_via:"inbox"}:{}}}}u(Xe,"handleMessageHere");async function Ye(t){const e=t.params.id,a=await ee(t,e,{method:"POST",path:`/v1/nodes/${encodeURIComponent(e)}/interrupt`,body:t.body});if(a.kind==="unknown")throw re(e,a.unreachable);if(a.kind==="remote"){if(a.status>=400)throw te(a.status,a.body);return{status:a.status,body:ne(a.body,a.machine)}}const n=await O(e);if(n===null)throw C(`unknown node: ${e}`,{received:e});const r=await pe(e,{senderNodeId:"human",kind:"message"});let o=!1;if(R(n))try{o=await he(e)!=="idle"}catch(d){if(!(d instanceof U))throw d}return{status:200,body:{node_id:e,outcome:o?"aborted_turn":r.length>0?"canceled_pending":"idle",aborted_turn:o,canceled_pending:r.length}}}u(Ye,"handleInterrupt");function de(t){if(typeof t.body!="object"||t.body===null||Array.isArray(t.body))throw c("mail requires an object body");const e=t.body;if(typeof e.execution_id!="string"||e.execution_id.trim()==="")throw c("execution_id is required");return e}u(de,"mailBody");async function Ze(t){const e=de(t),a=e.channel;if(a!=="wake"&&a!=="passive"&&a!=="deferred_run")throw c("channel must be wake, passive, or deferred_run");const n=await le(t.params.id,e.execution_id,a);return{status:200,body:{action:n.action,deliveries:n.deliveries.map(o=>({delivery_id:o.deliveryId,attempts:o.attempts,handoff:o.handoff,entry:{...me(o),seq:o.message.seq}}))}}}u(Ze,"handleMailClaim");async function et(t){const e=de(t);if(!Array.isArray(e.deliveries))throw c("deliveries must be an array");const a=e.deliveries.map(o=>{if(typeof o!="object"||o===null||Array.isArray(o))throw c("each delivery must be an object");const s=o;if(typeof s.delivery_id!="string"||s.delivery_id==="")throw c("delivery_id is required");if(!Number.isSafeInteger(s.attempts)||s.attempts<1)throw c("attempts must be a positive integer");if(s.disposition!=="acknowledged"&&s.disposition!=="released")throw c("disposition must be acknowledged or released");return{delivery_id:s.delivery_id,attempts:s.attempts,disposition:s.disposition}}),n=await fe(t.params.id,e.execution_id,a.map(o=>({deliveryId:o.delivery_id,attempts:o.attempts,disposition:o.disposition})));return{status:200,body:{action:n.action,results:n.results.map(o=>({delivery_id:o.deliveryId,outcome:o.outcome}))}}}u(et,"handleMailAcknowledge");const Dt=Be([{method:"POST",pattern:"/v1/nodes/:id/mail/claim",handler:Ze},{method:"POST",pattern:"/v1/nodes/:id/mail/acknowledge",handler:et}]),Lt=[{method:"POST",pattern:"/v1/nodes/:id/messages",scope:"crtr:act",handler:Qe},{method:"POST",pattern:"/v1/nodes/:id/interrupt",scope:"crtr:act",handler:Ye}];export{Dt as brokerMailRoutes,Qe as handleMessage,Lt as messageRoutes};
@@ -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 w}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 f}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{readConfig as lt}from"../../../core/config.js";import{hasConfiguredProviderCredential as ct,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 ut(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(ut,"countFiles");function ft(e){if(typeof e!="object"||e===null)throw w("a node create requires a JSON body");const n=e;if(n.kind!==void 0&&(typeof n.kind!="string"||n.kind.trim()===""))throw w("kind must be a non-empty string when provided");if(n.description!==void 0&&(typeof n.description!="string"||n.description.trim()===""))throw w("description must be a non-empty string when provided");if(n.creator!==void 0&&(typeof n.creator!="string"||n.creator.trim()===""))throw w("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 f(400,"invalid_request","isolated must be a boolean",{param:"isolated"});const t=n.root_lifecycle;if(t!==void 0&&t!=="resident"&&t!=="terminal")throw w("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 w("request_key must be a non-empty string of at most 128 characters when provided");return n}d(ft,"parseCreateBody");function pt(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 f(422,"invalid_deadline","`deadline` must be a positive representable duration");return t.toISOString()}d(pt,"parseDeadline");function mt(e){if(e!==void 0){if(typeof e!="object"||e===null||Array.isArray(e))throw new f(400,"invalid_request","`outcome_delivery` must be an object");if(typeof e.action!="string"||!Pn.test(e.action))throw new f(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 f(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable")}if(n===void 0)throw new f(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable");if(Buffer.byteLength(n,"utf8")>le)throw new f(413,"payload_too_large",`serialized payload exceeds ${le} bytes`)}return e}}d(mt,"parseOutcomeDelivery");function wt(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 f(422,"unknown_action",`no action named ${e.action} is declared from ${n}`):new f(422,"invalid_action",`${e.action} is declared in ${t.configOrigin} but unusable: ${t.reason}`,{reason:t.reason,configOrigin:t.configOrigin})}d(wt,"resolveOutcomeDelivery");function ht(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(ht,"buildRecipe");function yt(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(yt,"warmRequestFor");import{resolveCreateKind as ho}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 _t(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 f(403,"scope_denied",`scopes exceed the bearer token's ceiling: ${t.join(", ")}`,{scopes:t,ceiling:n})}d(_t,"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 f(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 gt(e,n={},t={}){const o=_t(ft(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 f(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 f(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 f(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 f(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 f(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(p=>!O(r.effectiveScopes,p)||!O(c.scopes,p));if(s!==void 0)throw new f(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=bt(e,o,i,n,t);H.set(i,l);try{return await l}finally{H.delete(i)}}d(gt,"handleCreate");async function bt(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 f(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(bt,"handleKeyedCreateRequest");async function D(e,n,t,o,i=void 0){const a=o.deadlineAt??pt(n.deadline),l=mt(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 w("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 w("output_schema must be a JSON schema string")}if(s===null||typeof s!="object"||Array.isArray(s))throw w("output_schema must be a JSON schema object");await Tn(s)}const{profileId:p,kind:m,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:m},g=l===void 0?void 0:wt(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:p},t.modelRegistry),await rt(X)!=="app"&&!await ct(p))throw new f(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"?yt(_,u,p):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 f(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=ht(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 w(`${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 w(`${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 w(`${n} must be one of: ${t.join(", ")}`)}}d(L,"oneOf");function vt(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 w(`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"),p=v(e,"under"),m=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 w("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}:{},...p!==void 0?{under:p}:{},...m!==void 0?{under_inclusive:m}:{},...u!==void 0?{hanging:u}:{},...k!==void 0?{include:k}:{}}}d(vt,"parseListQuery");async function kt(e){const n=vt(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(kt,"handleList");async function St(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(St,"handleDetail");async function Rt(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(Rt,"handleSnapshot");async function It(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(It,"handleSubject");function Ot(e){for(const[a]of e.query)if(a!=="cursor"&&a!=="limit")throw w(`unknown messages query parameter: ${a}`);const n=e.query.getAll("cursor"),t=e.query.getAll("limit");if(n.length>1)throw w("cursor must appear at most once");if(t.length>1)throw w("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 w("limit must be an integer from 1 through 500");return n.length===0?{limit:i}:{cursor:n[0],limit:i}}d(Ot,"parseMessagesQuery");async function At(e){const n=e.params.id,t=await dn(n,Ot(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(At,"handleMessages");async function $t(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($t,"handleSession");async function Ct(e){const n=e.params.id;return await h(n),{status:200,body:{node_id:n,markdown:await cn(n)}}}d(Ct,"handleTranscript");async function Nt(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 ut(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 Tt(i.node_id,i.dir)||i.files>0);return{status:200,body:{node_id:n,roots:o}}}d(Nt,"handleContext");async function Tt(e,n){try{return tn(await W(e),n)}catch(t){if(rn(t))return!1;throw t}}d(Tt,"hasDir");async function Pt(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(Pt,"handleFork");const Et=1e4;async function Dt(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,Et);return{status:200,body:Hn(n,l,c,s)}}d(Dt,"handleRevive");async function Lt(e){const n=e.params.id;return{status:200,body:{newNodeId:(await hn(n))?.newNodeId??null}}}d(Lt,"handleRelaunchRoot");async function Mt(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 w("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(Mt,"handleClose");async function jt(e){if(!Qn(e.principal))throw new f(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(jt,"handleMarkRead");async function Gt(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(Gt,"handleRecycle");async function Ft(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(Ft,"handleDemote");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:"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(Bt,"handlePromote");async function Kt(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(Kt,"handleYield");async function Vt(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 w("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 f(422,"unprocessable",`controller ${t.controller} is ${o.status}`);return await xe(n,t.controller),{status:200,body:await b(n)}}d(Vt,"handleWait");async function Wt(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(Wt,"handleReviveAll");const xt=new Set(["interrupt","steer","after-turn","next-turn"]);function zt(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"||!xt.has(i))&&n(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(i)}`);return JSON.stringify(Object.fromEntries(t))}d(zt,"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 Jt(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(m=>m!=="profile"&&m!=="restart"&&i[m]!==void 0))throw new y({error:"profile_not_exclusive",message:"profile can only be combined with restart",field:"profile",next:"Send profile (and optionally restart) alone."});const r=await h(t),s=await Kn(e,i.profile);Vn(s.profileId);const p=Wn(s.profileId).manifest.grantee??"app:terminal";if(p!==(r.grantee??"app:terminal"))throw new y({error:"profile_grantee_mismatch",message:`profile ${s.profileId} belongs to ${p}, 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),p=N(s.cwd);if(i.keep_session===!0||p&&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(p&&!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 f(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 m=T(r);if(!N(m))throw new y({error:"cwd_missing",message:`cwd does not exist: ${m}`,received:r,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."});try{if(!ee(m).isDirectory())throw new y({error:"cwd_not_a_directory",message:`cwd is not a directory: ${m}`,received: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: ${m}`,received:r,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."})}return await V(async()=>{await C(t,{cwd:m}),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:zt(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,p=a.grantee==="app:terminal"&&!lt("user").runtime?.issuer;if(!r.every(m=>O(a.scopes,m)&&(s?O(s.resolved,m):p)))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 f(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),p=await dt(a.grant_id,i.model,s===void 0),m=p?{family:st,strength:p.strength}:s,u=p?p.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,m).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 f(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 w(`model must resolve to a provider/id spec: ${i.model}`);await An(t,u,m)}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,p=i.lifecycle??a.lifecycle;let m;s==="orchestrator"&&!await vn(t)&&(m=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:p}:{}},m)}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(Jt,"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 w(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${n.sort().join(", ")}.`})}d(Re,"assertKindServer");async function Ut(){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(Ut,"handleListKinds");const po=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:gt},{method:"GET",pattern:"/v1/nodes",handler:kt},{method:"GET",pattern:"/v1/kinds",handler:d(()=>Ut(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:Wt},{method:"GET",pattern:"/v1/nodes/:id",handler:St},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:Rt},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:It},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:At},{method:"GET",pattern:"/v1/nodes/:id/session",handler:$t},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:Ct},{method:"GET",pattern:"/v1/nodes/:id/context",handler:Nt},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:Pt},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:Dt},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:Lt},{method:"POST",pattern:"/v1/nodes/:id/close",handler:Mt},{method:"POST",pattern:"/v1/nodes/:id/read",handler:jt},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:Gt},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:Ft},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:Bt},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Kt},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Vt},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:Jt}];export{Jt as handleConfig,gt as handleCreate,Pt as handleFork,kt as handleList,Bt as handlePromote,Kt as handleYield,po as nodeRoutes,ho as resolveCreateKind};
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 +1 @@
1
- var N=Object.defineProperty;var o=(t,e)=>N(t,"name",{value:e,configurable:!0});import{assertLaunchKind as c}from"../../../core/runtime/launch-target.js";import{listNodesByProfile as v,shiftProfileNodeDeadlines as q}from"../../../core/canvas/canvas.js";import{liveExecutionForNode as O}from"../../../core/canvas/executions.js";import{shiftAutoBackgroundBashDeadlines as L}from"../../../core/bash-jobs.js";import{contextDir as $}from"../../../core/canvas/node-agent-paths.js";import{boundFleet as S}from"../../../core/runtime/fleet.js";import{recordedPidLiveness as V}from"../../../core/canvas/pid.js";import{withCanvasWrite as b}from"../../../core/canvas/db.js";import{reposForCwd as F}from"../../../core/graph/repo-sync/repos.js";import{renameProfileObject as M}from"../../../core/graph/objects.js";import{usage as l}from"../../../core/errors.js";import{ApiError as f}from"../../../api/errors.js";import{scopeAllowed as P}from"../../../core/scopes.js";import{validateEnvVarName as R}from"../../../core/env-name.js";import{listProfileEnvNames as C,removeProfileEnvVar as G,setProfileEnvVar as U}from"../../../core/profiles/env-store.js";import{isDeploymentName as B,listAppEnvNames as K,removeAppEnvVar as H,setAppEnvVar as W}from"../../../core/profiles/app-env-store.js";import{addProfileProject as z,assertDeliveryLimits as J,setProfileDeliveryLimit as E,assertProfileProjects as h,createProfile as g,ensureRootProfile as Q,listProfiles as u,loadProfileManifest as y,pauseProfile as X,removeProfileProject as Y,renameProfile as Z,resumeProfile as x,setProfileDefaultKind as ee,updateProfileMetadata as te}from"../../../core/profiles/manifest.js";import{requestProfileDeletion as ne}from"../../profile-delete.js";import{brokerSignalBus as re}from"../../broker-signals/bus.js";import{toProfileDTO as d}from"../map.js";import{actsAsPerson as ae,appOf as w,resolvedScopes as ie}from"../router.js";const j="root";function m(t){return w(t.principal)??"app:terminal"}o(m,"callerApp");function A(t,e,r=null){if(u().some(n=>n.manifest.name===e&&n.profileId!==r&&(n.manifest.grantee??"app:terminal")===t))throw new f(400,"invalid_request",`${t} already has a profile named ${e}`)}o(A,"assertNameFree");async function p(t,e){const r=await I(t,e),n=r.manifest.grantee??"app:terminal";if(t.principal.class!=="person"&&n!==w(t.principal))throw new f(403,"permission_error",`profile ${r.profileId} belongs to ${n}; only that app changes it`);return r}o(p,"requireOwnProfile");async function oe(t){const e=t.body??{};if(typeof e.name!="string"||e.name.trim()==="")throw l("a profile name is required",{field:"name"});e.projects!==void 0&&h(e.projects);const r=m(t),n=e.name.trim();A(r,n),e.default_kind!==void 0&&await c(e.default_kind,process.cwd(),null);const a=g(n,e.projects??[],{defaultKind:e.default_kind,metadata:e.metadata,grantee:r});return{status:201,body:d(a)}}o(oe,"handleCreate");async function se(t,e){const r=e.trim();if(r==="")throw l("profile name must not be empty");return await b(async n=>(await M(n,t,r),Z(t,r)))}o(se,"renameProfileAndHandle");async function de(t,e,r){const n=await b(async a=>(await F(a,r)).map(i=>i.name));z(t,r);for(const a of n)e[a]===void 0&&e[`repo:${a}`]===void 0&&E(t,a,"preview")}o(de,"addProjectWithDefaultLimit");async function le(t){const{profileId:e,manifest:r}=await p(t,t.params.name),n=t.body??{};return n.name!==void 0&&A(r.grantee??"app:terminal",n.name.trim(),e),n.default_kind!==void 0&&await c(n.default_kind,process.cwd(),e),n.add_project!==void 0&&h([n.add_project]),n.set_delivery_limit!==void 0&&J({[n.set_delivery_limit.owner]:n.set_delivery_limit.level}),n.name!==void 0&&await se(e,n.name),n.default_kind!==void 0&&ee(e,n.default_kind),n.add_project!==void 0&&await de(e,r.delivery_limits??{},n.add_project.path),n.set_delivery_limit!==void 0&&E(e,n.set_delivery_limit.owner,n.set_delivery_limit.level),n.remove_project!==void 0&&Y(e,n.remove_project),{status:200,body:d(y(e))}}o(le,"handleUpdate");async function fe(t){const{profileId:e}=await p(t,t.params.name);return{status:200,body:{profile_id:e,names:C(e)}}}o(fe,"handleEnvList");function _(t){const e=t.params.var,r=R(e);if(!r.isValid)throw l(`invalid env var name: ${r.errors.join("; ")}`,{field:"name",received:e});return e}o(_,"requireEnvVarName");function T(t){const e=_(t);if(B(e)&&!ae(t.principal))throw new f(403,"permission_error",`${e} is deployment-wide; only a person changes it`);return e}o(T,"requireSelfEnvVarName");async function pe(t){const{profileId:e}=await p(t,t.params.name),r=_(t),{value:n}=t.body??{};if(typeof n!="string"||n==="")throw l("a non-empty env value is required",{field:"value"});return{status:200,body:{profile_id:e,changed:U(e,r,n)}}}o(pe,"handleEnvSet");async function me(t){const{profileId:e}=await p(t,t.params.name),r=_(t);return{status:200,body:{profile_id:e,changed:G(e,r)}}}o(me,"handleEnvRemove");async function ue(t){const e=t.params.name,r=t.body??{};r.projects!==void 0&&h(r.projects);const n=m(t);if(e===j&&n==="app:terminal")return{status:200,body:d(Q())};if(e===j)throw new f(403,"permission_error","root belongs to the terminal app");const a=u().find(s=>s.manifest.name===e&&(s.manifest.grantee??"app:terminal")===n);if(a!==void 0)return{status:200,body:d(a)};r.default_kind!==void 0&&await c(r.default_kind,process.cwd(),null);const i=g(e,r.projects??[],{defaultKind:r.default_kind,metadata:r.metadata,grantee:n});return{status:200,body:d(i)}}o(ue,"handleEnsure");async function ce(t){const e=await p(t,t.params.name),r=t.body??{};if(typeof r!="object"||r===null||Array.isArray(r))throw l("profile metadata body must be an object",{field:"body"});const n=r,a=n.unset===void 0?[]:n.unset;if(!Array.isArray(a)||a.some(k=>typeof k!="string"))throw l("profile metadata `unset` must be an array of strings",{field:"unset"});const i=n.set===void 0?{}:n.set,s=te(e.profileId,i,a);return{status:200,body:d(s)}}o(ce,"handleSetMetadata");async function ve(t){const e=y(t.params.name),r=X(e.profileId),n=(await v(e.profileId)).filter(i=>i.status==="active"||i.status==="idle");if(n.length===0)return{status:200,body:{profile_id:e.profileId,paused_at:r.manifest.paused_at}};const a=S();for(const i of n){const s=a.get(i.node_id);if(s!==void 0){a.interruptForProfilePause(i.node_id,s.pid);continue}i.pi_pid!=null&&V(i.pi_pid,i.pi_pid_identity)==="alive"&&a.interruptForProfilePause(i.node_id,i.pi_pid)}return{status:200,body:{profile_id:e.profileId,paused_at:r.manifest.paused_at}}}o(ve,"handlePause");async function he(t){const e=y(t.params.name),r=x(e.profileId);for(const n of await v(e.profileId))(n.status==="active"||n.status==="idle"||await O(n.node_id)!==null)&&re.markMail(n.node_id);if(r.pausedAt!==null){const n=Date.parse(r.pausedAt);if(!Number.isNaN(n)){const a=Math.max(0,Date.now()-n);await q(e.profileId,a);for(const i of await v(e.profileId))i.status!=="dead"&&L(await $(i.node_id),a)}}return{status:200,body:{profile_id:e.profileId,paused_at:r.manifest.paused_at}}}o(he,"handleResume");async function D(t){const e=t.principal;if(e.class==="person")return u();const r=await ie(e);return u().filter(({profileId:n,manifest:a})=>{const i=a.grantee??"app:terminal";if(i===w(e))return!0;const s=`crtr:memory:rw:${i}:profile:${n}`;return P(r,s)&&(e.class!=="broker"||P(e.scopes,s))})}o(D,"visibleProfiles");async function I(t,e){const r=await D(t),n=r.find(({profileId:i})=>i===e),a=n?[n]:r.filter(({manifest:i})=>i.name===e);if(a.length===0)throw new f(404,"not_found","profile not found");if(a.length>1)throw new f(400,"ambiguous","profile name matches multiple visible profiles; use an exact id");return a[0]}o(I,"requireUsableProfile");async function ye(t){return{status:200,body:(await D(t)).map(d)}}o(ye,"handleList");async function we(t){return{status:200,body:d(await I(t,t.params.name))}}o(we,"handleGet");async function _e(t){return ne((await p(t,t.params.name)).profileId,t.body)}o(_e,"handleDelete");const Ue=[{method:"GET",pattern:"/v1/apps/self/env",handler:o(t=>({status:200,body:{names:K(m(t))}}),"handler")},{method:"PUT",pattern:"/v1/apps/self/env/:var",handler:o(t=>{const e=T(t),{value:r}=t.body??{};if(typeof r!="string"||!r)throw l("a non-empty env value is required",{field:"value"});return{status:200,body:{changed:W(m(t),e,r)}}},"handler")},{method:"DELETE",pattern:"/v1/apps/self/env/:var",handler:o(t=>({status:200,body:{changed:H(m(t),T(t))}}),"handler")},{method:"PUT",pattern:"/v1/profiles/:name",handler:ue},{method:"POST",pattern:"/v1/profiles/:name/pause",ownerOnly:!0,handler:ve},{method:"POST",pattern:"/v1/profiles/:name/resume",ownerOnly:!0,handler:he},{method:"PATCH",pattern:"/v1/profiles/:name/metadata",handler:ce},{method:"POST",pattern:"/v1/profiles",handler:oe},{method:"PATCH",pattern:"/v1/profiles/:name",handler:le},{method:"GET",pattern:"/v1/profiles/:name/env",handler:fe},{method:"PUT",pattern:"/v1/profiles/:name/env/:var",handler:pe},{method:"DELETE",pattern:"/v1/profiles/:name/env/:var",handler:me},{method:"DELETE",pattern:"/v1/profiles/:name",handler:_e},{method:"GET",pattern:"/v1/profiles",handler:ye},{method:"GET",pattern:"/v1/profiles/:name",handler:we}];export{de as addProjectWithDefaultLimit,Ue as profileRoutes,se as renameProfileAndHandle,I as requireUsableProfile};
1
+ var N=Object.defineProperty;var o=(e,t)=>N(e,"name",{value:t,configurable:!0});import{assertLaunchKind as c}from"../../../core/runtime/launch-target.js";import{listNodesByProfile as v,shiftProfileNodeDeadlines as O}from"../../../core/canvas/canvas.js";import{liveExecutionForNode as q}from"../../../core/canvas/executions.js";import{shiftAutoBackgroundBashDeadlines as L}from"../../../core/bash-jobs.js";import{contextDir as $}from"../../../core/canvas/node-agent-paths.js";import{boundFleet as S}from"../../../core/runtime/fleet.js";import{recordedPidLiveness as V}from"../../../core/canvas/pid.js";import{withCanvasWrite as b}from"../../../core/canvas/db.js";import{reposForCwd as F}from"../../../core/graph/repo-sync/repos.js";import{renameProfileObject as M}from"../../../core/graph/objects.js";import{usage as l}from"../../../core/errors.js";import{ApiError as f}from"../../../api/errors.js";import{scopeAllowed as P}from"../../../core/scopes.js";import{validateEnvVarName as R}from"../../../core/env-name.js";import{listProfileEnvNames as C,removeProfileEnvVar as G,setProfileEnvVar as U}from"../../../core/profiles/env-store.js";import{isDeploymentName as B,listAppEnvNames as K,removeAppEnvVar as H,setAppEnvVar as W}from"../../../core/profiles/app-env-store.js";import{addProfileProject as z,assertDeliveryLimits as J,setProfileDeliveryLimit as E,assertProfileProjects as h,createProfile as g,ensureRootProfile as Q,listProfiles as u,loadProfileManifest as y,pauseProfile as X,removeProfileProject as Y,renameProfile as Z,resumeProfile as x,setProfileDefaultKind as ee,updateProfileMetadata as te}from"../../../core/profiles/manifest.js";import{requestProfileDeletion as ne}from"../../profile-delete.js";import{brokerSignalBus as re}from"../../broker-signals/bus.js";import{toProfileDTO as ae}from"../map.js";import{machineEnvironmentId as ie}from"../../../core/environments.js";import{actsAsPerson as oe,appOf as w,resolvedScopes as se}from"../router.js";const j="root";function d(e){return{...ae(e),environment_id:e.manifest.environment_id??ie()}}o(d,"toProfileDTO");function m(e){return w(e.principal)??"app:terminal"}o(m,"callerApp");function A(e,t,r=null){if(u().some(n=>n.manifest.name===t&&n.profileId!==r&&(n.manifest.grantee??"app:terminal")===e))throw new f(400,"invalid_request",`${e} already has a profile named ${t}`)}o(A,"assertNameFree");async function p(e,t){const r=await I(e,t),n=r.manifest.grantee??"app:terminal";if(e.principal.class!=="person"&&n!==w(e.principal))throw new f(403,"permission_error",`profile ${r.profileId} belongs to ${n}; only that app changes it`);return r}o(p,"requireOwnProfile");async function de(e){const t=e.body??{};if(typeof t.name!="string"||t.name.trim()==="")throw l("a profile name is required",{field:"name"});t.projects!==void 0&&h(t.projects);const r=m(e),n=t.name.trim();A(r,n),t.default_kind!==void 0&&await c(t.default_kind,process.cwd(),null);const a=g(n,t.projects??[],{defaultKind:t.default_kind,metadata:t.metadata,grantee:r});return{status:201,body:d(a)}}o(de,"handleCreate");async function le(e,t){const r=t.trim();if(r==="")throw l("profile name must not be empty");return await b(async n=>(await M(n,e,r),Z(e,r)))}o(le,"renameProfileAndHandle");async function fe(e,t,r){const n=await b(async a=>(await F(a,r)).map(i=>i.name));z(e,r);for(const a of n)t[a]===void 0&&t[`repo:${a}`]===void 0&&E(e,a,"preview")}o(fe,"addProjectWithDefaultLimit");async function pe(e){const{profileId:t,manifest:r}=await p(e,e.params.name),n=e.body??{};return n.name!==void 0&&A(r.grantee??"app:terminal",n.name.trim(),t),n.default_kind!==void 0&&await c(n.default_kind,process.cwd(),t),n.add_project!==void 0&&h([n.add_project]),n.set_delivery_limit!==void 0&&J({[n.set_delivery_limit.owner]:n.set_delivery_limit.level}),n.name!==void 0&&await le(t,n.name),n.default_kind!==void 0&&ee(t,n.default_kind),n.add_project!==void 0&&await fe(t,r.delivery_limits??{},n.add_project.path),n.set_delivery_limit!==void 0&&E(t,n.set_delivery_limit.owner,n.set_delivery_limit.level),n.remove_project!==void 0&&Y(t,n.remove_project),{status:200,body:d(y(t))}}o(pe,"handleUpdate");async function me(e){const{profileId:t}=await p(e,e.params.name);return{status:200,body:{profile_id:t,names:C(t)}}}o(me,"handleEnvList");function _(e){const t=e.params.var,r=R(t);if(!r.isValid)throw l(`invalid env var name: ${r.errors.join("; ")}`,{field:"name",received:t});return t}o(_,"requireEnvVarName");function T(e){const t=_(e);if(B(t)&&!oe(e.principal))throw new f(403,"permission_error",`${t} is deployment-wide; only a person changes it`);return t}o(T,"requireSelfEnvVarName");async function ue(e){const{profileId:t}=await p(e,e.params.name),r=_(e),{value:n}=e.body??{};if(typeof n!="string"||n==="")throw l("a non-empty env value is required",{field:"value"});return{status:200,body:{profile_id:t,changed:U(t,r,n)}}}o(ue,"handleEnvSet");async function ce(e){const{profileId:t}=await p(e,e.params.name),r=_(e);return{status:200,body:{profile_id:t,changed:G(t,r)}}}o(ce,"handleEnvRemove");async function ve(e){const t=e.params.name,r=e.body??{};r.projects!==void 0&&h(r.projects);const n=m(e);if(t===j&&n==="app:terminal")return{status:200,body:d(Q())};if(t===j)throw new f(403,"permission_error","root belongs to the terminal app");const a=u().find(s=>s.manifest.name===t&&(s.manifest.grantee??"app:terminal")===n);if(a!==void 0)return{status:200,body:d(a)};r.default_kind!==void 0&&await c(r.default_kind,process.cwd(),null);const i=g(t,r.projects??[],{defaultKind:r.default_kind,metadata:r.metadata,grantee:n});return{status:200,body:d(i)}}o(ve,"handleEnsure");async function he(e){const t=await p(e,e.params.name),r=e.body??{};if(typeof r!="object"||r===null||Array.isArray(r))throw l("profile metadata body must be an object",{field:"body"});const n=r,a=n.unset===void 0?[]:n.unset;if(!Array.isArray(a)||a.some(k=>typeof k!="string"))throw l("profile metadata `unset` must be an array of strings",{field:"unset"});const i=n.set===void 0?{}:n.set,s=te(t.profileId,i,a);return{status:200,body:d(s)}}o(he,"handleSetMetadata");async function ye(e){const t=y(e.params.name),r=X(t.profileId),n=(await v(t.profileId)).filter(i=>i.status==="active"||i.status==="idle");if(n.length===0)return{status:200,body:{profile_id:t.profileId,paused_at:r.manifest.paused_at}};const a=S();for(const i of n){const s=a.get(i.node_id);if(s!==void 0){a.interruptForProfilePause(i.node_id,s.pid);continue}i.pi_pid!=null&&V(i.pi_pid,i.pi_pid_identity)==="alive"&&a.interruptForProfilePause(i.node_id,i.pi_pid)}return{status:200,body:{profile_id:t.profileId,paused_at:r.manifest.paused_at}}}o(ye,"handlePause");async function we(e){const t=y(e.params.name),r=x(t.profileId);for(const n of await v(t.profileId))(n.status==="active"||n.status==="idle"||await q(n.node_id)!==null)&&re.markMail(n.node_id);if(r.pausedAt!==null){const n=Date.parse(r.pausedAt);if(!Number.isNaN(n)){const a=Math.max(0,Date.now()-n);await O(t.profileId,a);for(const i of await v(t.profileId))i.status!=="dead"&&L(await $(i.node_id),a)}}return{status:200,body:{profile_id:t.profileId,paused_at:r.manifest.paused_at}}}o(we,"handleResume");async function D(e){const t=e.principal;if(t.class==="person")return u();const r=await se(t);return u().filter(({profileId:n,manifest:a})=>{const i=a.grantee??"app:terminal";if(i===w(t))return!0;const s=`crtr:memory:rw:${i}:profile:${n}`;return P(r,s)&&(t.class!=="broker"||P(t.scopes,s))})}o(D,"visibleProfiles");async function I(e,t){const r=await D(e),n=r.find(({profileId:i})=>i===t),a=n?[n]:r.filter(({manifest:i})=>i.name===t);if(a.length===0)throw new f(404,"not_found","profile not found");if(a.length>1)throw new f(400,"ambiguous","profile name matches multiple visible profiles; use an exact id");return a[0]}o(I,"requireUsableProfile");async function _e(e){return{status:200,body:(await D(e)).map(d)}}o(_e,"handleList");async function be(e){return{status:200,body:d(await I(e,e.params.name))}}o(be,"handleGet");async function Pe(e){return ne((await p(e,e.params.name)).profileId,e.body)}o(Pe,"handleDelete");const He=[{method:"GET",pattern:"/v1/apps/self/env",handler:o(e=>({status:200,body:{names:K(m(e))}}),"handler")},{method:"PUT",pattern:"/v1/apps/self/env/:var",handler:o(e=>{const t=T(e),{value:r}=e.body??{};if(typeof r!="string"||!r)throw l("a non-empty env value is required",{field:"value"});return{status:200,body:{changed:W(m(e),t,r)}}},"handler")},{method:"DELETE",pattern:"/v1/apps/self/env/:var",handler:o(e=>({status:200,body:{changed:H(m(e),T(e))}}),"handler")},{method:"PUT",pattern:"/v1/profiles/:name",handler:ve},{method:"POST",pattern:"/v1/profiles/:name/pause",ownerOnly:!0,handler:ye},{method:"POST",pattern:"/v1/profiles/:name/resume",ownerOnly:!0,handler:we},{method:"PATCH",pattern:"/v1/profiles/:name/metadata",handler:he},{method:"POST",pattern:"/v1/profiles",handler:de},{method:"PATCH",pattern:"/v1/profiles/:name",handler:pe},{method:"GET",pattern:"/v1/profiles/:name/env",handler:me},{method:"PUT",pattern:"/v1/profiles/:name/env/:var",handler:ue},{method:"DELETE",pattern:"/v1/profiles/:name/env/:var",handler:ce},{method:"DELETE",pattern:"/v1/profiles/:name",handler:Pe},{method:"GET",pattern:"/v1/profiles",handler:_e},{method:"GET",pattern:"/v1/profiles/:name",handler:be}];export{fe as addProjectWithDefaultLimit,He as profileRoutes,le as renameProfileAndHandle,I as requireUsableProfile};