@north-light/crouter 0.3.331 → 0.3.333

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 (128) hide show
  1. package/README.md +2 -2
  2. package/dist/api/command-manifest/manifest.js +1 -1
  3. package/dist/build-root.js +1 -1
  4. package/dist/builtin-memory/crouter-concepts/INDEX.md +13 -0
  5. package/dist/builtin-memory/crouter-concepts/README.md +19 -0
  6. package/dist/builtin-memory/crouter-concepts/lifecycle-and-wakes.md +28 -0
  7. package/dist/builtin-memory/crouter-concepts/memory.md +36 -0
  8. package/dist/builtin-memory/crouter-concepts/nodes-and-the-canvas.md +30 -0
  9. package/dist/builtin-memory/crouter-concepts/profiles-kinds-and-modes.md +33 -0
  10. package/dist/builtin-memory/crouter-concepts/scopes-and-trust.md +34 -0
  11. package/dist/builtin-memory/crouter-concepts/why-a-daemon.md +31 -0
  12. package/dist/builtin-memory/crouter-plugin/README.md +10 -13
  13. package/dist/builtin-memory/crouter-plugin/bundles-and-memory.md +2 -4
  14. package/dist/builtin-memory/crouter-plugin/commands.md +4 -7
  15. package/dist/builtin-memory/crouter-plugin/deploying.md +4 -7
  16. package/dist/builtin-memory/crouter-plugin/errors.md +2 -5
  17. package/dist/builtin-memory/crouter-plugin/getting-started.md +3 -6
  18. package/dist/builtin-memory/crouter-plugin/output.md +1 -3
  19. package/dist/builtin-memory/crouter-plugin/parameters.md +3 -4
  20. package/dist/builtin-memory/crouter-sdk/README.md +3 -4
  21. package/dist/builtin-memory/crouter-sdk/bash.md +2 -3
  22. package/dist/builtin-memory/crouter-sdk/client.md +3 -4
  23. package/dist/builtin-memory/crouter-sdk/docker.md +2 -4
  24. package/dist/builtin-memory/crouter-sdk/errors.md +9 -4
  25. package/dist/builtin-memory/crouter-sdk/files.md +2 -3
  26. package/dist/builtin-memory/crouter-sdk/getting-started.md +19 -6
  27. package/dist/builtin-memory/crouter-sdk/memory.md +3 -4
  28. package/dist/builtin-memory/crouter-sdk/migration.md +2 -6
  29. package/dist/builtin-memory/crouter-sdk/nodes.md +3 -3
  30. package/dist/builtin-memory/crouter-sdk/resources.md +2 -4
  31. package/dist/builtin-memory/crouter-sdk/streaming.md +3 -4
  32. package/dist/clients/attach/input/capabilities.js +1 -1
  33. package/dist/clients/attach/overlays/help.js +1 -1
  34. package/dist/clients/attach/slash/dispatch.js +1 -1
  35. package/dist/clients/attach/viewer.js +762 -765
  36. package/dist/commands/sys/branch.js +1 -1
  37. package/dist/commands/sys/connect.js +3 -3
  38. package/dist/commands/sys/setup-core.d.ts +1 -1
  39. package/dist/commands/sys/setup-core.js +4 -4
  40. package/dist/commands/sys/tutorial/branch.d.ts +1 -0
  41. package/dist/commands/sys/tutorial/branch.js +1 -0
  42. package/dist/commands/sys/tutorial/lessons.d.ts +6 -0
  43. package/dist/commands/sys/tutorial/lessons.js +12 -0
  44. package/dist/commands/sys/tutorial/scenario.d.ts +1 -0
  45. package/dist/commands/sys/tutorial/scenario.js +2 -0
  46. package/dist/commands/sys/tutorial/tracks.d.ts +2 -0
  47. package/dist/commands/sys/tutorial/tracks.js +4 -0
  48. package/dist/commands/sys.js +1 -1
  49. package/dist/core/runtime/boot-root.d.ts +7 -0
  50. package/dist/core/runtime/boot-root.js +4 -4
  51. package/dist/core/runtime/first-run-offer.d.ts +11 -0
  52. package/dist/core/runtime/first-run-offer.js +5 -0
  53. package/dist/core/runtime/front-door.js +3 -3
  54. package/dist/core/runtime/spawn.d.ts +3 -1
  55. package/dist/core/runtime/spawn.js +2 -2
  56. package/dist/core/scopes.d.ts +4 -2
  57. package/dist/core/scopes.js +1 -1
  58. package/dist/core/secrets.d.ts +11 -0
  59. package/dist/core/secrets.js +2 -2
  60. package/dist/daemon/api/bridge.d.ts +4 -0
  61. package/dist/daemon/api/bridge.js +2 -2
  62. package/dist/daemon/api/handlers/attach.d.ts +1 -1
  63. package/dist/daemon/api/handlers/attach.js +1 -1
  64. package/dist/daemon/api/handlers/bash.js +1 -1
  65. package/dist/daemon/api/handlers/broker-ops.d.ts +1 -1
  66. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  67. package/dist/daemon/api/handlers/broker-recovery.d.ts +1 -1
  68. package/dist/daemon/api/handlers/broker-recovery.js +1 -1
  69. package/dist/daemon/api/handlers/canvas.js +4 -4
  70. package/dist/daemon/api/handlers/crons.d.ts +1 -1
  71. package/dist/daemon/api/handlers/crons.js +1 -1
  72. package/dist/daemon/api/handlers/daemon.d.ts +1 -1
  73. package/dist/daemon/api/handlers/daemon.js +1 -1
  74. package/dist/daemon/api/handlers/files.js +1 -1
  75. package/dist/daemon/api/handlers/focus.d.ts +1 -1
  76. package/dist/daemon/api/handlers/focus.js +1 -1
  77. package/dist/daemon/api/handlers/human-requests.js +1 -1
  78. package/dist/daemon/api/handlers/memory.js +1 -1
  79. package/dist/daemon/api/handlers/messages.d.ts +1 -1
  80. package/dist/daemon/api/handlers/messages.js +2 -2
  81. package/dist/daemon/api/handlers/model-config.d.ts +1 -1
  82. package/dist/daemon/api/handlers/model-config.js +1 -1
  83. package/dist/daemon/api/handlers/modelauth.js +1 -1
  84. package/dist/daemon/api/handlers/nodes.js +1 -1
  85. package/dist/daemon/api/handlers/profiles.js +1 -1
  86. package/dist/daemon/api/handlers/reports.js +1 -1
  87. package/dist/daemon/api/handlers/reviews.js +1 -1
  88. package/dist/daemon/api/handlers/worktree.d.ts +1 -1
  89. package/dist/daemon/api/handlers/worktree.js +1 -1
  90. package/dist/daemon/api/router.d.ts +20 -1
  91. package/dist/daemon/api/router.js +1 -1
  92. package/dist/daemon/api/server.js +1 -11
  93. package/dist/types.js +1 -1
  94. package/docs/cli/README.md +16 -0
  95. package/docs/cli/canvas-and-dashboard.md +56 -0
  96. package/docs/cli/first-session.md +55 -0
  97. package/docs/cli/human-inbox.md +34 -0
  98. package/docs/cli/memory-and-preferences.md +50 -0
  99. package/docs/cli/the-viewer.md +79 -0
  100. package/docs/concepts/README.md +17 -0
  101. package/docs/concepts/lifecycle-and-wakes.md +26 -0
  102. package/docs/concepts/memory.md +34 -0
  103. package/docs/concepts/nodes-and-the-canvas.md +28 -0
  104. package/docs/concepts/profiles-kinds-and-modes.md +31 -0
  105. package/docs/concepts/scopes-and-trust.md +32 -0
  106. package/docs/concepts/why-a-daemon.md +29 -0
  107. package/docs/plugin/README.md +5 -0
  108. package/docs/plugin/bundles-and-memory.md +5 -0
  109. package/docs/plugin/commands.md +5 -0
  110. package/docs/plugin/deploying.md +5 -0
  111. package/docs/plugin/errors.md +5 -0
  112. package/docs/plugin/getting-started.md +5 -0
  113. package/docs/plugin/output.md +5 -0
  114. package/docs/plugin/parameters.md +5 -0
  115. package/docs/sdk/README.md +5 -0
  116. package/docs/sdk/bash.md +5 -0
  117. package/docs/sdk/client.md +6 -1
  118. package/docs/sdk/docker.md +5 -0
  119. package/docs/sdk/errors.md +12 -0
  120. package/docs/sdk/files.md +5 -0
  121. package/docs/sdk/getting-started.md +21 -1
  122. package/docs/sdk/memory.md +5 -0
  123. package/docs/sdk/migration.md +5 -0
  124. package/docs/sdk/nodes.md +6 -1
  125. package/docs/sdk/resources.md +5 -0
  126. package/docs/sdk/streaming.md +5 -0
  127. package/package.json +10 -9
  128. package/runtime.lock.json +6734 -670
@@ -1,8 +1,8 @@
1
- var A=Object.defineProperty;var c=(r,e)=>A(r,"name",{value:e,configurable:!0});import{createConnection as E}from"node:net";import{WebSocketServer as _}from"ws";import{isSafeNodeId as g,viewSocketPath as b}from"../../core/canvas/paths.js";import{getNode as w}from"../../core/canvas/index.js";import{BROKER_READ_CAPS as S,CLIENT_READ_CAPS as $,FrameDecoder as R,FrameOverflowError as T}from"../../core/runtime/broker-protocol.js";import{classify as v}from"../../core/fault-classifier.js";import{clearFault as h,recordFault as p}from"../../core/canvas/recovery.js";import{decideAttachRevive as C}from"../../core/runtime/revive.js";import{probeViewSocket as P,waitForBrokerViewSocket as x}from"../../core/runtime/view-socket.js";const B=new _({noServer:!0,maxPayload:S.maxLineBytes}),N=25e3,O=6e4;function F(r,e=N,s=O){let t=!0,a=!1,n=Date.now();const f=c(()=>{t=!0},"acknowledge"),u=c(()=>{a||(a=!0,clearInterval(m),r.off("pong",f))},"stop");r.on("pong",f);const m=setInterval(()=>{if(Date.now()-n>s){t=!0;return}if(!t){u(),r.terminate();return}t=!1;try{r.ping()}catch{u(),r.terminate()}},e);return m.unref(),{stop:u,noteActivity:c(()=>{n=Date.now()},"noteActivity")}}c(F,"startRemoteAttachHeartbeat");function k(r){const e=Buffer.from(r,"utf8");return e.byteLength<=123?r:e.subarray(0,123).toString("utf8")}c(k,"clampReason");function d(r,e,s,t,a){const n=JSON.stringify({error:{code:t,message:a}}),f=`HTTP/1.1 ${e} ${s}\r
1
+ var A=Object.defineProperty;var c=(r,e)=>A(r,"name",{value:e,configurable:!0});import{createConnection as E}from"node:net";import{WebSocketServer as _}from"ws";import{isSafeNodeId as g,viewSocketPath as b}from"../../core/canvas/paths.js";import{getNode as w}from"../../core/canvas/index.js";import{BROKER_READ_CAPS as S,CLIENT_READ_CAPS as $,FrameDecoder as R,FrameOverflowError as T}from"../../core/runtime/broker-protocol.js";import{classify as v}from"../../core/fault-classifier.js";import{clearFault as h,recordFault as p}from"../../core/canvas/recovery.js";import{decideAttachRevive as x}from"../../core/runtime/revive.js";import{probeViewSocket as C,waitForBrokerViewSocket as P}from"../../core/runtime/view-socket.js";const B=new _({noServer:!0,maxPayload:S.maxLineBytes}),N=25e3,O=6e4;function F(r,e=N,s=O){let t=!0,a=!1,n=Date.now();const f=c(()=>{t=!0},"acknowledge"),u=c(()=>{a||(a=!0,clearInterval(m),r.off("pong",f))},"stop");r.on("pong",f);const m=setInterval(()=>{if(Date.now()-n>s){t=!0;return}if(!t){u(),r.terminate();return}t=!1;try{r.ping()}catch{u(),r.terminate()}},e);return m.unref(),{stop:u,noteActivity:c(()=>{n=Date.now()},"noteActivity")}}c(F,"startRemoteAttachHeartbeat");function k(r){const e=Buffer.from(r,"utf8");return e.byteLength<=123?r:e.subarray(0,123).toString("utf8")}c(k,"clampReason");function d(r,e,s,t,a){const n=JSON.stringify({error:{code:t,message:a}}),f=`HTTP/1.1 ${e} ${s}\r
2
2
  content-type: application/json; charset=utf-8\r
3
3
  content-length: ${Buffer.byteLength(n)}\r
4
4
  connection: close\r
5
5
  \r
6
6
  `+n;try{r.end(f)}catch{try{r.destroy()}catch{}}}c(d,"refuseUpgrade");function U(r){if(new URL(r.url??"/","http://127.0.0.1").searchParams.get("revive")==="0")return!0;const s=r.headers["x-crtr-attach-revive"];return(Array.isArray(s)?s[0]:s)==="0"}c(U,"reviveOptedOut");function D(r){return new URL(r.url??"/","http://127.0.0.1").searchParams.get("wakeParked")==="1"}c(D,"wakeParkedRequested");function L(r,e){if(!g(e)){try{r.close(1008,k(`invalid node id: ${e}`))}catch{}return}if(w(e)===null){try{r.close(1011,k(`no node ${e}`))}catch{}return}h(e,{link:"viewer\u2194crtrd"});const s=b(e),t=E(s),a=new R($);let n=!1,f=!1,u;t.on("connect",()=>{h(e,{link:"relay\u2194broker"})});const m=c((o,l)=>{if(!n){if(n=!0,u?.stop(),!t.destroyed)try{t.destroy()}catch{}try{r.close(o,k(l))}catch{}}},"teardown");u=F(r),t.on("data",o=>{u?.noteActivity();let l;try{l=a.push(o)}catch(i){const y=i instanceof T?`broker sent an oversized frame (${i.message})`:`failed to decode a broker frame for ${e}`;m(1009,y);return}for(const i of l)r.readyState===r.OPEN&&r.send(JSON.stringify(i))}),t.on("error",o=>{const l=v("relay\u2194broker",o);p(e,{link:"relay\u2194broker",op:"bridge socket",kind:l.kind,retry:{disposition:"manual"},message:o.message});const i=o.code==="ECONNREFUSED"||o.code==="ENOENT"?`no running broker for ${e}`:`view socket error for ${e}: ${o.message}`;m(1011,i)}),t.on("close",o=>{n||o||(h(e,{link:"relay\u2194broker"}),m(1e3,"broker socket closed"))}),r.on("close",(o,l)=>{const i=l.toString("utf8");if(n){o===1e3&&h(e,{link:"viewer\u2194crtrd"});return}if(o===1e3)h(e,{link:"viewer\u2194crtrd"});else if(!f){f=!0;const y=v("viewer\u2194crtrd",{code:o,reason:i});p(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:y.kind,retry:{disposition:"auto"},message:i||`remote attach closed (${o})`})}m(o,i||`remote attach closed (${o})`)}),r.on("error",()=>{if(!f){f=!0;const o=v("viewer\u2194crtrd",{code:1006,reason:"remote attach websocket error"});p(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:o.kind,retry:{disposition:"auto"},message:"remote attach websocket error"})}m(1011,"remote attach websocket error")}),r.on("message",o=>{if(n||t.destroyed)return;u?.noteActivity();const i=(Array.isArray(o)?Buffer.concat(o):Buffer.isBuffer(o)?o:Buffer.from(new Uint8Array(o))).toString("utf8"),y=i.endsWith(`
7
7
  `)?i:i+`
8
- `;try{t.write(y)}catch{}})}c(L,"bridgeConnection");async function X(r,e,s,t){e.on("error",()=>{});try{if(!g(t)){d(e,400,"Bad Request","invalid_node_id",`invalid node id: ${t}`);return}if(w(t)===null){d(e,404,"Not Found","node_not_found",`no node ${t}`);return}if(U(r)){if(!await P(b(t),250)){d(e,409,"Conflict","node_dormant",`node ${t} is dormant and revive was opted out (?revive=0)`);return}}else{let a;try{const n=await C(t,{resume:!0,capacity:"refuse"},D(r));if(n.parked){d(e,409,"Conflict","node_dormant",`node ${t} is parked; attach with ?wakeParked=1 to wake it`);return}a=n.result.launch?.exited}catch(n){const f=n instanceof Error?n.message:String(n);d(e,409,"Conflict","attach_revive_failed",`attach revive failed: ${f}`);return}if(!await x(t,a)){d(e,409,"Conflict","broker_not_ready",`broker view socket for ${t} did not become listenable after revive`);return}}if(e.destroyed)return;B.handleUpgrade(r,e,s,a=>L(a,t))}catch(a){const n=a instanceof Error?a.message:String(a);d(e,500,"Internal Server Error","internal",`attach upgrade failed: ${n}`)}}c(X,"handleAttachUpgrade");export{N as REMOTE_ATTACH_HEARTBEAT_MS,O as REMOTE_ATTACH_QUIET_MS,X as handleAttachUpgrade,F as startRemoteAttachHeartbeat};
8
+ `;try{t.write(y)}catch{}})}c(L,"bridgeConnection");async function X(r,e,s,t){e.on("error",()=>{});try{if(!g(t)){d(e,400,"Bad Request","invalid_node_id",`invalid node id: ${t}`);return}if(w(t)===null){d(e,404,"Not Found","node_not_found",`no node ${t}`);return}if(U(r)){if(!await C(b(t),250)){d(e,409,"Conflict","node_dormant",`node ${t} is dormant and revive was opted out (?revive=0)`);return}}else{let a;try{const n=await x(t,{resume:!0,capacity:"refuse"},D(r));if(n.parked){d(e,409,"Conflict","node_dormant",`node ${t} is parked; attach with ?wakeParked=1 to wake it`);return}a=n.result.launch?.exited}catch(n){const f=n instanceof Error?n.message:String(n);d(e,409,"Conflict","attach_revive_failed",`attach revive failed: ${f}`);return}if(!await P(t,a)){d(e,409,"Conflict","broker_not_ready",`broker view socket for ${t} did not become listenable after revive`);return}}if(e.destroyed)return;B.handleUpgrade(r,e,s,a=>L(a,t))}catch(a){const n=a instanceof Error?a.message:String(a);d(e,500,"Internal Server Error","internal",`attach upgrade failed: ${n}`)}}c(X,"handleAttachUpgrade");export{N as REMOTE_ATTACH_HEARTBEAT_MS,O as REMOTE_ATTACH_QUIET_MS,X as handleAttachUpgrade,d as refuseUpgrade,F as startRemoteAttachHeartbeat};
@@ -1,2 +1,2 @@
1
- import type { RouteTable } from '../router.js';
1
+ import { type RouteTable } from '../router.js';
2
2
  export declare const attachRoutes: RouteTable;
@@ -1 +1 @@
1
- var c=Object.defineProperty;var u=(t,e)=>c(t,"name",{value:e,configurable:!0});import{getNode as m}from"../../../core/canvas/canvas.js";import{decideAttachRevive as k}from"../../../core/runtime/revive.js";import{viewSocketPath as l}from"../../../core/canvas/paths.js";import{waitForBrokerViewSocket as v}from"../../../core/runtime/placement-tmux.js";import{notFound as p,usage as n}from"../../../core/errors.js";function w(t){if(t==null)return{resume:!0,revive:!0,wakeParked:!0};if(typeof t!="object")throw n("attach body must be a JSON object { resume?, revive?, wakeParked? }");const e=t.resume,r=t.revive,o=t.wakeParked;if(e!==void 0&&typeof e!="boolean")throw n("resume must be a boolean");if(r!==void 0&&typeof r!="boolean")throw n("revive must be a boolean");if(o!==void 0&&typeof o!="boolean")throw n("wakeParked must be a boolean");return{resume:e??!0,revive:r??!0,wakeParked:o??!0}}u(w,"parseAttachBody");async function h(t){const e=t.params.id;if(m(e)===null)throw p(`unknown node: ${e}`,{received:e});const{resume:r,revive:o,wakeParked:f}=w(t.body);let i=!1,d=!1,s=!1;if(o){const a=await k(e,{resume:r,capacity:"refuse"},f);s=a.parked,a.parked||(i=a.result.launch!==void 0,d=a.result.resumed,i&&await v(e))}return{status:200,body:{node_id:e,socket_path:l(e),revived:i,resumed:d,parked:s}}}u(h,"handleAttach");const B=[{method:"POST",pattern:"/v1/nodes/:id/attach",handler:h}];export{B as attachRoutes};
1
+ var c=Object.defineProperty;var u=(t,e)=>c(t,"name",{value:e,configurable:!0});import{getNode as m}from"../../../core/canvas/canvas.js";import{decideAttachRevive as k}from"../../../core/runtime/revive.js";import{viewSocketPath as l}from"../../../core/canvas/paths.js";import{waitForBrokerViewSocket as v}from"../../../core/runtime/placement-tmux.js";import{notFound as p,usage as n}from"../../../core/errors.js";import{ownerOnly as w}from"../router.js";function h(t){if(t==null)return{resume:!0,revive:!0,wakeParked:!0};if(typeof t!="object")throw n("attach body must be a JSON object { resume?, revive?, wakeParked? }");const e=t.resume,r=t.revive,o=t.wakeParked;if(e!==void 0&&typeof e!="boolean")throw n("resume must be a boolean");if(r!==void 0&&typeof r!="boolean")throw n("revive must be a boolean");if(o!==void 0&&typeof o!="boolean")throw n("wakeParked must be a boolean");return{resume:e??!0,revive:r??!0,wakeParked:o??!0}}u(h,"parseAttachBody");async function b(t){const e=t.params.id;if(m(e)===null)throw p(`unknown node: ${e}`,{received:e});const{resume:r,revive:o,wakeParked:f}=h(t.body);let i=!1,d=!1,s=!1;if(o){const a=await k(e,{resume:r,capacity:"refuse"},f);s=a.parked,a.parked||(i=a.result.launch!==void 0,d=a.result.resumed,i&&await v(e))}return{status:200,body:{node_id:e,socket_path:l(e),revived:i,resumed:d,parked:s}}}u(b,"handleAttach");const F=w([{method:"POST",pattern:"/v1/nodes/:id/attach",handler:b}]);export{F as attachRoutes};
@@ -1 +1 @@
1
- var m=Object.defineProperty;var d=(r,t)=>m(r,"name",{value:t,configurable:!0});import{statSync as u}from"node:fs";import{isAbsolute as f}from"node:path";import{ApiError as a}from"../../../api/index.js";import{buildOperationalEnvBase as l}from"../../../core/runtime/spawn-env.js";import{runCommandOnce as p}from"../../../core/runtime/run-command.js";import{readProfileEnvVars as w}from"../../../core/profiles/env-store.js";import{usage as s}from"../../../core/errors.js";const _=60,c=600,y=256*1024;function b(r){if(typeof r!="object"||r===null||Array.isArray(r))throw s("bash requires an object body");const t=r;if(typeof t.command!="string"||t.command==="")throw s("bash requires a non-empty `command`");if(typeof t.cwd!="string"||!f(t.cwd))throw new a(404,"cwd_not_found","cwd must name an absolute directory");try{if(!u(t.cwd).isDirectory())throw new Error("not a directory")}catch{throw new a(404,"cwd_not_found",`cwd not found: ${t.cwd}`)}const e=t.timeout_s??_;if(typeof e!="number"||!Number.isFinite(e)||e<=0||e>c)throw new a(422,"invalid_timeout",`timeout_s must be greater than 0 and at most ${c}`);if(t.profile!==void 0&&typeof t.profile!="string")throw s("profile must be a string");let n;if(t.env!==void 0){if(typeof t.env!="object"||t.env===null||Array.isArray(t.env))throw s("env must be an object of string values");n={};for(const[i,o]of Object.entries(t.env)){if(typeof o!="string")throw s("env must be an object of string values");n[i]=o}}return{command:t.command,cwd:t.cwd,timeout_s:e,env:n,profile:t.profile}}d(b,"parseRequest");async function T(r){const t=b(r.body),e=t.profile??null,n=l({targetCwd:t.cwd,targetProfileId:e}),i={...n,...w(e),...t.env,...e===null?{}:{CRTR_PROFILE_ID:e},CRTR_ADMITTED_HOST_PATH:n.CRTR_ADMITTED_HOST_PATH},o=await p({command:t.command,cwd:t.cwd,env:i,timeoutMs:t.timeout_s*1e3,headBytes:y}).completion;if(o.processError!==null)throw o.processError;return{status:200,body:{exit_code:o.timedOut?null:o.exitCode,signal:o.signal,stdout:o.stdout,stdout_truncated:o.stdoutTruncated,stderr:o.stderr,stderr_truncated:o.stderrTruncated,timed_out:o.timedOut,duration_ms:o.durationMs}}}d(T,"handleBash");const C=[{method:"POST",pattern:"/v1/bash",handler:T}];export{C as bashRoutes};
1
+ var m=Object.defineProperty;var d=(r,t)=>m(r,"name",{value:t,configurable:!0});import{statSync as u}from"node:fs";import{isAbsolute as f}from"node:path";import{ApiError as a}from"../../../api/index.js";import{buildOperationalEnvBase as l}from"../../../core/runtime/spawn-env.js";import{runCommandOnce as p}from"../../../core/runtime/run-command.js";import{readProfileEnvVars as w}from"../../../core/profiles/env-store.js";import{usage as s}from"../../../core/errors.js";const _=60,c=600,y=256*1024;function b(r){if(typeof r!="object"||r===null||Array.isArray(r))throw s("bash requires an object body");const t=r;if(typeof t.command!="string"||t.command==="")throw s("bash requires a non-empty `command`");if(typeof t.cwd!="string"||!f(t.cwd))throw new a(404,"cwd_not_found","cwd must name an absolute directory");try{if(!u(t.cwd).isDirectory())throw new Error("not a directory")}catch{throw new a(404,"cwd_not_found",`cwd not found: ${t.cwd}`)}const e=t.timeout_s??_;if(typeof e!="number"||!Number.isFinite(e)||e<=0||e>c)throw new a(422,"invalid_timeout",`timeout_s must be greater than 0 and at most ${c}`);if(t.profile!==void 0&&typeof t.profile!="string")throw s("profile must be a string");let n;if(t.env!==void 0){if(typeof t.env!="object"||t.env===null||Array.isArray(t.env))throw s("env must be an object of string values");n={};for(const[i,o]of Object.entries(t.env)){if(typeof o!="string")throw s("env must be an object of string values");n[i]=o}}return{command:t.command,cwd:t.cwd,timeout_s:e,env:n,profile:t.profile}}d(b,"parseRequest");async function T(r){const t=b(r.body),e=t.profile??null,n=l({targetCwd:t.cwd,targetProfileId:e}),i={...n,...w(e),...t.env,...e===null?{}:{CRTR_PROFILE_ID:e},CRTR_ADMITTED_HOST_PATH:n.CRTR_ADMITTED_HOST_PATH},o=await p({command:t.command,cwd:t.cwd,env:i,timeoutMs:t.timeout_s*1e3,headBytes:y}).completion;if(o.processError!==null)throw o.processError;return{status:200,body:{exit_code:o.timedOut?null:o.exitCode,signal:o.signal,stdout:o.stdout,stdout_truncated:o.stdoutTruncated,stderr:o.stderr,stderr_truncated:o.stderrTruncated,timed_out:o.timedOut,duration_ms:o.durationMs}}}d(T,"handleBash");const C=[{method:"POST",pattern:"/v1/bash",scope:"act",handler:T}];export{C as bashRoutes};
@@ -1,2 +1,2 @@
1
- import type { RouteTable } from '../router.js';
1
+ import { type RouteTable } from '../router.js';
2
2
  export declare const brokerOperationRoutes: RouteTable;
@@ -1 +1 @@
1
- var F=Object.defineProperty;var r=(t,e)=>F(t,"name",{value:e,configurable:!0});import{canonicalSessionFile as A,findNodeBySessionFile as P,getNode as k,isWarmSpare as T,listNodeIdentities as I,recordSettledTurn as R,setPresence as w,subscriptionsOf as $,updateNode as g,updateNodeTelemetry as q}from"../../../core/canvas/canvas.js";import{recordExecutionPid as C}from"../../../core/canvas/executions.js";import{bindSession as j,readLiveSession as E,transferSession as M}from"../../../core/canvas/sessions.js";import{isSafeNodeId as D}from"../../../core/canvas/paths.js";import{isPidAlive as L}from"../../../core/canvas/pid.js";import{editorLabel as N}from"../../../core/canvas/labels.js";import{assembleNodeSubject as G}from"../../../core/substrate/subject.js";import{withCanvasWrite as l}from"../../../core/canvas/db.js";import{notFound as v,usage as s}from"../../../core/errors.js";import{hasUnseenWakeMail as O}from"../../../core/canvas/deliveries.js";import{clearYieldMessage as J}from"../../../core/runtime/kickoff.js";import{transition as h}from"../../../core/runtime/lifecycle.js";import{focusOf as b,tearDownNode as x}from"../../../core/runtime/placement.js";import{hasAttachedBrokerViewers as W}from"../../../core/runtime/broker/client-registry.js";import{evaluateStop as U}from"../../../core/runtime/stop-guard.js";import{clearFault as m,recordFault as V}from"../../../core/canvas/recovery.js";import{updateModelRecipe as Y}from"../../../core/runtime/model-swap.js";import{completeCompanionRequestedSubmit as z}from"../../review/finish.js";import{emitEvent as H}from"../../../core/events/emit.js";import{consumePendingPark as K,recordPendingParkActivity as Q}from"../../park-pending.js";import{shouldParkAfterSummary as X}from"../../park-activity.js";import{requireCurrentExecution as f}from"./broker-recovery.js";function p(t,e){if(typeof t!="object"||t===null||Array.isArray(t))throw s(`${e} requires a JSON body`);return t}r(p,"objectBody");function Z(t){const e=p(t,"broker session-bound");if(typeof e.executionId!="string"||e.executionId==="")throw s("executionId must be a non-empty string");if(typeof e.piSessionId!="string"||e.piSessionId==="")throw s("piSessionId must be a non-empty string");if(e.sessionFile!==null&&typeof e.sessionFile!="string")throw s("sessionFile must be a string or null");if(!Number.isSafeInteger(e.pid)||e.pid<=0)throw s("pid must be a positive safe integer");if(e.reason!==null&&typeof e.reason!="string")throw s("reason must be a string or null");if(!Array.isArray(e.reviewBoundaryIds)||!e.reviewBoundaryIds.every(n=>typeof n=="string"))throw s("reviewBoundaryIds must be an array of strings");return e}r(Z,"parseSessionBoundBody");function ee(t){const e=p(t,"broker settle");if(typeof e.stopReason!="string")throw s("stopReason must be a string");for(const n of["backgroundJobsRunning","pushedFinal"])if(typeof e[n]!="boolean")throw s(`${n} must be a boolean`);return e}r(ee,"parseSettleBody");function te(t){const e=p(t,"broker park-complete");if(e.outcome!=="completed"&&e.outcome!=="failed")throw s("outcome must be completed or failed");return e}r(te,"parseParkCompleteBody");function ne(t){const e=p(t,"broker telemetry");if(typeof e.expected_execution_id!="string"||e.expected_execution_id==="")throw s("expected_execution_id must be a non-empty string");if(typeof e.tokens_in!="number"||!Number.isFinite(e.tokens_in)||e.tokens_in<0)throw s("tokens_in must be a non-negative finite number");if(e.context_tokens!==null&&(typeof e.context_tokens!="number"||!Number.isFinite(e.context_tokens)||e.context_tokens<0))throw s("context_tokens must be a non-negative finite number or null");if(e.last_activity!==null&&typeof e.last_activity!="string")throw s("last_activity must be a string or null");if(typeof e.updated_at!="string"||Number.isNaN(Date.parse(e.updated_at)))throw s("updated_at must be an ISO timestamp");return{...e,updated_at:new Date(e.updated_at).toISOString()}}r(ne,"parseTelemetryBody");function ie(t){const e=p(t,"broker model");if(typeof e.spec!="string"||e.spec.trim()==="")throw s("spec must be a non-empty string");if(e.pinnedOverride!==void 0&&typeof e.pinnedOverride!="boolean")throw s("pinnedOverride must be a boolean when present");if(typeof e.userSelected!="boolean")throw s("userSelected must be a boolean");return e}r(ie,"parseModelCommitBody");function _(t){const e=k(t);if(e===null)throw v(`unknown node: ${t}`,{received:t});return e}r(_,"requireNode");function y(t){return{node_id:t.node_id,name:t.name,...t.description===void 0?{}:{description:t.description},...t.title===void 0?{}:{title:t.title},...t.icon===void 0?{}:{icon:t.icon},kind:t.kind,mode:t.mode,lifecycle:t.lifecycle,status:t.status,cwd:t.cwd,parent:t.parent??null,fork_from:t.fork_from??null,profile_id:t.profile_id??null,...t.managed_worktree===void 0?{}:{managed_worktree:t.managed_worktree===null?null:{state:t.managed_worktree.state,...t.managed_worktree.cleanup===void 0?{}:{cleanup:t.managed_worktree.cleanup},path:t.managed_worktree.path,branch:t.managed_worktree.branch,base_ref:t.managed_worktree.base_ref,base_sha:t.managed_worktree.base_sha}},...t.review_binding===void 0?{}:{review_binding:t.review_binding??null},intent:t.intent??null,...t.persona_ack===void 0?{}:{persona_ack:t.persona_ack},created:t.created}}r(y,"extensionNode");function oe(t){const e=_(t),n=[],o=new Set([t]);let i=e.parent??null;for(;i!==null&&i!==""&&!o.has(i);){o.add(i);const c=k(i);if(c===null)break;n.unshift(y(c)),i=c.parent??null}const a=$(t).map(c=>k(c.node_id)).filter(c=>c!==null&&c.kind!=="human").sort((c,S)=>c.status===S.status?0:c.status==="active"?-1:S.status==="active"?1:0).map(y),u=typeof e.fork_source_file=="string"?P(e.fork_source_file):null,d=G(t);if(d===null)throw v(`unknown node: ${t}`,{received:t});return{node:y(e),warm_spare:T(t),ancestors:n,children:a,fork_source:u===null?null:y(u),subject:d,report_nodes:I()}}r(oe,"extensionState");function B(t,e){return t?.kind===e.kind&&t?.mode===e.mode&&t?.lifecycle===e.lifecycle}r(B,"samePersona");function re(t){const e=p(t,"broker generated-name");if(e.kind!=="initial"&&e.kind!=="recap")throw s("kind must be initial or recap");if(typeof e.description!="string"||typeof e.title!="string"||typeof e.icon!="string")throw s("description, title, and icon must be strings");if(e.kind==="initial")return e;const n=e.expected;if(typeof n!="object"||n===null||Array.isArray(n)||["name","description","title","icon","kind"].some(o=>typeof n[o]!="string"))throw s("recap expected must contain name, description, title, icon, and kind strings");return e}r(re,"parseGeneratedNameBody");function se(t){const e=p(t,"broker persona-ack"),n=r(o=>{const i=e[o];if(typeof i!="object"||i===null||Array.isArray(i)||typeof i.kind!="string"||i.mode!=="base"&&i.mode!=="orchestrator"||i.lifecycle!=="terminal"&&i.lifecycle!=="resident")throw s(`${o} must be a persona state`);return i},"parse");return{expected_execution_id:e.expected_execution_id,from:n("from"),to:n("to")}}r(se,"parsePersonaAckBody");function ae(t){const e=t.params.id,n=Z(t.body),o=n.sessionFile===null?null:A(n.sessionFile);return{status:200,body:l(()=>{const a=_(e);if(C(n.executionId,e,n.pid)==="shutdown")return{action:"shutdown"};const u=a.review_binding?.review_id;if(u!==void 0&&!n.reviewBoundaryIds.includes(u))return{action:"shutdown"};if(n.reason==="new"&&a.parent==null)return{action:"relaunch_root"};if(n.reason!=="new"&&a.fork_from!=null&&a.pi_session_id==null&&o===null)return{action:"shutdown"};const d=o===null?null:P(o);if(d!==null&&d.node_id!==e){if(L(d.pi_pid))return V(e,{link:"daemon\u2192node",op:"session-file-ownership",kind:"protocol",retry:{disposition:"fatal"},message:`refusing to bind ${o}: it is owned by live node ${d.node_id}`}),{action:"shutdown"};const c=E(d.node_id);if(c===null||M({fromNodeId:d.node_id,fromBindingId:c.bindingId,toNodeId:e,executionId:n.executionId,sessionId:n.piSessionId,transcriptPath:o})!=="transferred")return{action:"shutdown"}}else if(j(e,{executionId:n.executionId,sessionId:n.piSessionId,transcriptPath:o})==="shutdown")return{action:"shutdown"};return n.reason!=="new"&&(J(e),a.intent==="refresh"&&h(e,"revive")),{action:"none"}})}}r(ae,"handleSessionBound");function de(t,e){const n=k(t);if(n===null){if(e.pushedFinal)return{action:"shutdown"};throw v(`unknown node: ${t}`,{received:t})}if(R(t,new Date().toISOString()),e.stopReason==="quit")return(n.status==="active"||n.status==="idle")&&n.intent===null&&(h(t,"finish"),m(t),b(t)!==null&&x(t),w(t,{pane:null,tmux_session:null,window:null})),{action:"shutdown"};if(e.stopReason!=="stop"&&e.stopReason!=="length")return m(t,{link:"daemon\u2192node"}),n.intent==="refresh"?{action:"shutdown"}:{action:"stay_dormant"};const o={pushedFinal:e.pushedFinal};if(o.pushedFinal||n.status==="done")return m(t),b(t)!==null&&x(t),w(t,{pane:null,tmux_session:null,window:null}),{action:"shutdown"};if(n.intent==="refresh")return m(t),{action:"shutdown"};const i=U(t,o,e.backgroundJobsRunning);return m(t),i.action==="reprompt"?{action:"reprompt",prompt:i.message}:i.reason==="finished"?O(t)?{action:"stay_dormant"}:{action:"shutdown"}:i.reason!=="awaiting"&&i.reason!=="scheduled"?{action:"stay_dormant"}:b(t)!==null||W(t)||O(t)?{action:"stay_dormant"}:(h(t,"release"),{action:"shutdown"})}r(de,"settleBroker");function ue(t){const e=t.params.id,n=ee(t.body);f(e,n.expected_execution_id);const o=l(()=>de(e,n));return o.action!=="reprompt"&&z(e),{status:200,body:o}}r(ue,"handleSettle");function ce(t){const e=t.params.id,n=te(t.body);return f(e,n.expected_execution_id),{status:200,body:l(()=>{const i=K(e);if(i===void 0)return{action:"stay_dormant"};const a=_(e);return X(e,a,i)?(m(e),h(e,"park"),b(e)!==null&&x(e),w(e,{pane:null,tmux_session:null,window:null}),H({level:n.outcome==="completed"?"info":"warn",event:"broker.park.complete",...D(e)?{node_id:e}:{},outcome:n.outcome==="completed"?"succeeded":"failed"}),{action:"shutdown"}):{action:"stay_dormant"}})}}r(ce,"handleParkComplete");function le(t){const e=t.params.id;return f(e,p(t.body,"broker park-activity").expected_execution_id),{status:200,body:l(()=>({activity:Q(e)?"recorded":"none"}))}}r(le,"handleParkActivity");function pe(t){const e=t.params.id,n=ne(t.body);return f(e,n.expected_execution_id),l(()=>{q(e,{tokensIn:n.tokens_in,contextTokens:n.context_tokens,lastActivity:n.last_activity,updatedAt:n.updated_at})}),{status:204}}r(pe,"handleTelemetry");function fe(t){const e=t.params.id,n=ie(t.body);return f(e,n.expected_execution_id),{status:200,body:{modelOverride:l(()=>Y(_(e),n.spec,n.pinnedOverride,n.userSelected)).model_override}}}r(fe,"handleModelCommit");function me(t){return{status:200,body:oe(t.params.id)}}r(me,"handleExtensionState");function _e(t){const e=t.params.id,n=re(t.body);return f(e,n.expected_execution_id),{status:200,body:l(()=>{const i=_(e);if(n.kind==="initial"){if((i.description??"").trim()!=="")return{applied:!1};const d=g(e,{description:n.description,...n.title.trim()===""?{}:{title:n.title},...n.icon.trim()===""?{}:{icon:n.icon}});return{applied:!0,editorLabel:N(d),description:d.description??"",title:d.title??"",icon:d.icon??""}}const a=n.expected;if(i.name!==a.name||(i.description??"")!==a.description||(i.title??"")!==a.title||(i.icon??"")!==a.icon||i.kind!==a.kind)return{applied:!1};const u=g(e,{description:n.description,title:n.title.trim()===""?void 0:n.title,icon:n.icon.trim()===""?void 0:n.icon});return{applied:!0,editorLabel:N(u),description:u.description??"",title:u.title??"",icon:u.icon??""}})}}r(_e,"handleGeneratedName");function ke(t){const e=t.params.id,n=se(t.body);return f(e,n.expected_execution_id),{status:200,body:l(()=>{const i=_(e),a={kind:i.kind,mode:i.mode,lifecycle:i.lifecycle},u=i.persona_ack,d=u===void 0?a:{kind:u.kind??i.kind,mode:u.mode,lifecycle:u.lifecycle};return!B(a,n.to)||!B(d,n.from)?{applied:!1}:(g(e,{persona_ack:n.to}),{applied:!0})})}}r(ke,"handlePersonaAck");const De=[{method:"POST",pattern:"/v1/nodes/:id/broker/session-bound",handler:ae},{method:"POST",pattern:"/v1/nodes/:id/broker/settle",handler:ue},{method:"POST",pattern:"/v1/nodes/:id/broker/park-complete",handler:ce},{method:"POST",pattern:"/v1/nodes/:id/broker/park-activity",handler:le},{method:"POST",pattern:"/v1/nodes/:id/broker/telemetry",handler:pe},{method:"POST",pattern:"/v1/nodes/:id/broker/model",handler:fe},{method:"GET",pattern:"/v1/nodes/:id/broker/extension-state",handler:me},{method:"POST",pattern:"/v1/nodes/:id/broker/generated-name",handler:_e},{method:"POST",pattern:"/v1/nodes/:id/broker/persona-ack",handler:ke}];export{De as brokerOperationRoutes};
1
+ var F=Object.defineProperty;var r=(t,e)=>F(t,"name",{value:e,configurable:!0});import{canonicalSessionFile as A,findNodeBySessionFile as P,getNode as k,isWarmSpare as T,listNodeIdentities as I,recordSettledTurn as R,setPresence as w,subscriptionsOf as $,updateNode as g,updateNodeTelemetry as q}from"../../../core/canvas/canvas.js";import{recordExecutionPid as C}from"../../../core/canvas/executions.js";import{bindSession as j,readLiveSession as E,transferSession as M}from"../../../core/canvas/sessions.js";import{isSafeNodeId as D}from"../../../core/canvas/paths.js";import{isPidAlive as L}from"../../../core/canvas/pid.js";import{editorLabel as N}from"../../../core/canvas/labels.js";import{assembleNodeSubject as G}from"../../../core/substrate/subject.js";import{withCanvasWrite as l}from"../../../core/canvas/db.js";import{notFound as v,usage as s}from"../../../core/errors.js";import{hasUnseenWakeMail as O}from"../../../core/canvas/deliveries.js";import{clearYieldMessage as J}from"../../../core/runtime/kickoff.js";import{transition as h}from"../../../core/runtime/lifecycle.js";import{focusOf as b,tearDownNode as x}from"../../../core/runtime/placement.js";import{hasAttachedBrokerViewers as W}from"../../../core/runtime/broker/client-registry.js";import{evaluateStop as U}from"../../../core/runtime/stop-guard.js";import{clearFault as f,recordFault as V}from"../../../core/canvas/recovery.js";import{updateModelRecipe as Y}from"../../../core/runtime/model-swap.js";import{completeCompanionRequestedSubmit as z}from"../../review/finish.js";import{emitEvent as H}from"../../../core/events/emit.js";import{consumePendingPark as K,recordPendingParkActivity as Q}from"../../park-pending.js";import{shouldParkAfterSummary as X}from"../../park-activity.js";import{ownerOnly as Z}from"../router.js";import{requireCurrentExecution as m}from"./broker-recovery.js";function p(t,e){if(typeof t!="object"||t===null||Array.isArray(t))throw s(`${e} requires a JSON body`);return t}r(p,"objectBody");function ee(t){const e=p(t,"broker session-bound");if(typeof e.executionId!="string"||e.executionId==="")throw s("executionId must be a non-empty string");if(typeof e.piSessionId!="string"||e.piSessionId==="")throw s("piSessionId must be a non-empty string");if(e.sessionFile!==null&&typeof e.sessionFile!="string")throw s("sessionFile must be a string or null");if(!Number.isSafeInteger(e.pid)||e.pid<=0)throw s("pid must be a positive safe integer");if(e.reason!==null&&typeof e.reason!="string")throw s("reason must be a string or null");if(!Array.isArray(e.reviewBoundaryIds)||!e.reviewBoundaryIds.every(n=>typeof n=="string"))throw s("reviewBoundaryIds must be an array of strings");return e}r(ee,"parseSessionBoundBody");function te(t){const e=p(t,"broker settle");if(typeof e.stopReason!="string")throw s("stopReason must be a string");for(const n of["backgroundJobsRunning","pushedFinal"])if(typeof e[n]!="boolean")throw s(`${n} must be a boolean`);return e}r(te,"parseSettleBody");function ne(t){const e=p(t,"broker park-complete");if(e.outcome!=="completed"&&e.outcome!=="failed")throw s("outcome must be completed or failed");return e}r(ne,"parseParkCompleteBody");function ie(t){const e=p(t,"broker telemetry");if(typeof e.expected_execution_id!="string"||e.expected_execution_id==="")throw s("expected_execution_id must be a non-empty string");if(typeof e.tokens_in!="number"||!Number.isFinite(e.tokens_in)||e.tokens_in<0)throw s("tokens_in must be a non-negative finite number");if(e.context_tokens!==null&&(typeof e.context_tokens!="number"||!Number.isFinite(e.context_tokens)||e.context_tokens<0))throw s("context_tokens must be a non-negative finite number or null");if(e.last_activity!==null&&typeof e.last_activity!="string")throw s("last_activity must be a string or null");if(typeof e.updated_at!="string"||Number.isNaN(Date.parse(e.updated_at)))throw s("updated_at must be an ISO timestamp");return{...e,updated_at:new Date(e.updated_at).toISOString()}}r(ie,"parseTelemetryBody");function oe(t){const e=p(t,"broker model");if(typeof e.spec!="string"||e.spec.trim()==="")throw s("spec must be a non-empty string");if(e.pinnedOverride!==void 0&&typeof e.pinnedOverride!="boolean")throw s("pinnedOverride must be a boolean when present");if(typeof e.userSelected!="boolean")throw s("userSelected must be a boolean");return e}r(oe,"parseModelCommitBody");function _(t){const e=k(t);if(e===null)throw v(`unknown node: ${t}`,{received:t});return e}r(_,"requireNode");function y(t){return{node_id:t.node_id,name:t.name,...t.description===void 0?{}:{description:t.description},...t.title===void 0?{}:{title:t.title},...t.icon===void 0?{}:{icon:t.icon},kind:t.kind,mode:t.mode,lifecycle:t.lifecycle,status:t.status,cwd:t.cwd,parent:t.parent??null,fork_from:t.fork_from??null,profile_id:t.profile_id??null,...t.managed_worktree===void 0?{}:{managed_worktree:t.managed_worktree===null?null:{state:t.managed_worktree.state,...t.managed_worktree.cleanup===void 0?{}:{cleanup:t.managed_worktree.cleanup},path:t.managed_worktree.path,branch:t.managed_worktree.branch,base_ref:t.managed_worktree.base_ref,base_sha:t.managed_worktree.base_sha}},...t.review_binding===void 0?{}:{review_binding:t.review_binding??null},intent:t.intent??null,...t.persona_ack===void 0?{}:{persona_ack:t.persona_ack},created:t.created}}r(y,"extensionNode");function re(t){const e=_(t),n=[],o=new Set([t]);let i=e.parent??null;for(;i!==null&&i!==""&&!o.has(i);){o.add(i);const c=k(i);if(c===null)break;n.unshift(y(c)),i=c.parent??null}const a=$(t).map(c=>k(c.node_id)).filter(c=>c!==null&&c.kind!=="human").sort((c,S)=>c.status===S.status?0:c.status==="active"?-1:S.status==="active"?1:0).map(y),u=typeof e.fork_source_file=="string"?P(e.fork_source_file):null,d=G(t);if(d===null)throw v(`unknown node: ${t}`,{received:t});return{node:y(e),warm_spare:T(t),ancestors:n,children:a,fork_source:u===null?null:y(u),subject:d,report_nodes:I()}}r(re,"extensionState");function B(t,e){return t?.kind===e.kind&&t?.mode===e.mode&&t?.lifecycle===e.lifecycle}r(B,"samePersona");function se(t){const e=p(t,"broker generated-name");if(e.kind!=="initial"&&e.kind!=="recap")throw s("kind must be initial or recap");if(typeof e.description!="string"||typeof e.title!="string"||typeof e.icon!="string")throw s("description, title, and icon must be strings");if(e.kind==="initial")return e;const n=e.expected;if(typeof n!="object"||n===null||Array.isArray(n)||["name","description","title","icon","kind"].some(o=>typeof n[o]!="string"))throw s("recap expected must contain name, description, title, icon, and kind strings");return e}r(se,"parseGeneratedNameBody");function ae(t){const e=p(t,"broker persona-ack"),n=r(o=>{const i=e[o];if(typeof i!="object"||i===null||Array.isArray(i)||typeof i.kind!="string"||i.mode!=="base"&&i.mode!=="orchestrator"||i.lifecycle!=="terminal"&&i.lifecycle!=="resident")throw s(`${o} must be a persona state`);return i},"parse");return{expected_execution_id:e.expected_execution_id,from:n("from"),to:n("to")}}r(ae,"parsePersonaAckBody");function de(t){const e=t.params.id,n=ee(t.body),o=n.sessionFile===null?null:A(n.sessionFile);return{status:200,body:l(()=>{const a=_(e);if(C(n.executionId,e,n.pid)==="shutdown")return{action:"shutdown"};const u=a.review_binding?.review_id;if(u!==void 0&&!n.reviewBoundaryIds.includes(u))return{action:"shutdown"};if(n.reason==="new"&&a.parent==null)return{action:"relaunch_root"};if(n.reason!=="new"&&a.fork_from!=null&&a.pi_session_id==null&&o===null)return{action:"shutdown"};const d=o===null?null:P(o);if(d!==null&&d.node_id!==e){if(L(d.pi_pid))return V(e,{link:"daemon\u2192node",op:"session-file-ownership",kind:"protocol",retry:{disposition:"fatal"},message:`refusing to bind ${o}: it is owned by live node ${d.node_id}`}),{action:"shutdown"};const c=E(d.node_id);if(c===null||M({fromNodeId:d.node_id,fromBindingId:c.bindingId,toNodeId:e,executionId:n.executionId,sessionId:n.piSessionId,transcriptPath:o})!=="transferred")return{action:"shutdown"}}else if(j(e,{executionId:n.executionId,sessionId:n.piSessionId,transcriptPath:o})==="shutdown")return{action:"shutdown"};return n.reason!=="new"&&(J(e),a.intent==="refresh"&&h(e,"revive")),{action:"none"}})}}r(de,"handleSessionBound");function ue(t,e){const n=k(t);if(n===null){if(e.pushedFinal)return{action:"shutdown"};throw v(`unknown node: ${t}`,{received:t})}if(R(t,new Date().toISOString()),e.stopReason==="quit")return(n.status==="active"||n.status==="idle")&&n.intent===null&&(h(t,"finish"),f(t),b(t)!==null&&x(t),w(t,{pane:null,tmux_session:null,window:null})),{action:"shutdown"};if(e.stopReason!=="stop"&&e.stopReason!=="length")return f(t,{link:"daemon\u2192node"}),n.intent==="refresh"?{action:"shutdown"}:{action:"stay_dormant"};const o={pushedFinal:e.pushedFinal};if(o.pushedFinal||n.status==="done")return f(t),b(t)!==null&&x(t),w(t,{pane:null,tmux_session:null,window:null}),{action:"shutdown"};if(n.intent==="refresh")return f(t),{action:"shutdown"};const i=U(t,o,e.backgroundJobsRunning);return f(t),i.action==="reprompt"?{action:"reprompt",prompt:i.message}:i.reason==="finished"?O(t)?{action:"stay_dormant"}:{action:"shutdown"}:i.reason!=="awaiting"&&i.reason!=="scheduled"?{action:"stay_dormant"}:b(t)!==null||W(t)||O(t)?{action:"stay_dormant"}:(h(t,"release"),{action:"shutdown"})}r(ue,"settleBroker");function ce(t){const e=t.params.id,n=te(t.body);m(e,n.expected_execution_id);const o=l(()=>ue(e,n));return o.action!=="reprompt"&&z(e),{status:200,body:o}}r(ce,"handleSettle");function le(t){const e=t.params.id,n=ne(t.body);return m(e,n.expected_execution_id),{status:200,body:l(()=>{const i=K(e);if(i===void 0)return{action:"stay_dormant"};const a=_(e);return X(e,a,i)?(f(e),h(e,"park"),b(e)!==null&&x(e),w(e,{pane:null,tmux_session:null,window:null}),H({level:n.outcome==="completed"?"info":"warn",event:"broker.park.complete",...D(e)?{node_id:e}:{},outcome:n.outcome==="completed"?"succeeded":"failed"}),{action:"shutdown"}):{action:"stay_dormant"}})}}r(le,"handleParkComplete");function pe(t){const e=t.params.id;return m(e,p(t.body,"broker park-activity").expected_execution_id),{status:200,body:l(()=>({activity:Q(e)?"recorded":"none"}))}}r(pe,"handleParkActivity");function me(t){const e=t.params.id,n=ie(t.body);return m(e,n.expected_execution_id),l(()=>{q(e,{tokensIn:n.tokens_in,contextTokens:n.context_tokens,lastActivity:n.last_activity,updatedAt:n.updated_at})}),{status:204}}r(me,"handleTelemetry");function fe(t){const e=t.params.id,n=oe(t.body);return m(e,n.expected_execution_id),{status:200,body:{modelOverride:l(()=>Y(_(e),n.spec,n.pinnedOverride,n.userSelected)).model_override}}}r(fe,"handleModelCommit");function _e(t){return{status:200,body:re(t.params.id)}}r(_e,"handleExtensionState");function ke(t){const e=t.params.id,n=se(t.body);return m(e,n.expected_execution_id),{status:200,body:l(()=>{const i=_(e);if(n.kind==="initial"){if((i.description??"").trim()!=="")return{applied:!1};const d=g(e,{description:n.description,...n.title.trim()===""?{}:{title:n.title},...n.icon.trim()===""?{}:{icon:n.icon}});return{applied:!0,editorLabel:N(d),description:d.description??"",title:d.title??"",icon:d.icon??""}}const a=n.expected;if(i.name!==a.name||(i.description??"")!==a.description||(i.title??"")!==a.title||(i.icon??"")!==a.icon||i.kind!==a.kind)return{applied:!1};const u=g(e,{description:n.description,title:n.title.trim()===""?void 0:n.title,icon:n.icon.trim()===""?void 0:n.icon});return{applied:!0,editorLabel:N(u),description:u.description??"",title:u.title??"",icon:u.icon??""}})}}r(ke,"handleGeneratedName");function he(t){const e=t.params.id,n=ae(t.body);return m(e,n.expected_execution_id),{status:200,body:l(()=>{const i=_(e),a={kind:i.kind,mode:i.mode,lifecycle:i.lifecycle},u=i.persona_ack,d=u===void 0?a:{kind:u.kind??i.kind,mode:u.mode,lifecycle:u.lifecycle};return!B(a,n.to)||!B(d,n.from)?{applied:!1}:(g(e,{persona_ack:n.to}),{applied:!0})})}}r(he,"handlePersonaAck");const Ge=Z([{method:"POST",pattern:"/v1/nodes/:id/broker/session-bound",handler:de},{method:"POST",pattern:"/v1/nodes/:id/broker/settle",handler:ce},{method:"POST",pattern:"/v1/nodes/:id/broker/park-complete",handler:le},{method:"POST",pattern:"/v1/nodes/:id/broker/park-activity",handler:pe},{method:"POST",pattern:"/v1/nodes/:id/broker/telemetry",handler:me},{method:"POST",pattern:"/v1/nodes/:id/broker/model",handler:fe},{method:"GET",pattern:"/v1/nodes/:id/broker/extension-state",handler:_e},{method:"POST",pattern:"/v1/nodes/:id/broker/generated-name",handler:ke},{method:"POST",pattern:"/v1/nodes/:id/broker/persona-ack",handler:he}]);export{Ge as brokerOperationRoutes};
@@ -1,4 +1,4 @@
1
- import type { RouteTable } from '../router.js';
1
+ import { type RouteTable } from '../router.js';
2
2
  export declare function requireCurrentExecution(nodeId: string, expectedExecutionId: unknown): void;
3
3
  export declare const brokerRecoveryRoutes: RouteTable;
4
4
  export declare const nodeFaultRoutes: RouteTable;
@@ -1 +1 @@
1
- var x=Object.defineProperty;var i=(r,e)=>x(r,"name",{value:e,configurable:!0});import{ApiError as k}from"../../../api/errors.js";import{getNode as w}from"../../../core/canvas/canvas.js";import{liveExecutionForNode as E}from"../../../core/canvas/executions.js";import{admitEpisode as I,clearEpisode as S,clearFault as y,closeTurn as T,invalidateEpisode as q,openTurn as h,parseProviderError as R,readEpisode as F,readFault as m,recordFault as v,recordPendingEpisode as A,recordTransportPoisonVerdict as N,recordTurnProgress as P,reopenEpisode as O}from"../../../core/canvas/recovery.js";import{notFound as j,usage as n}from"../../../core/errors.js";const l=new Set(["pi\u2192provider","viewer\u2194broker","relay\u2194broker","viewer\u2194crtrd","daemon\u2192node","crtr\u2192pi"]),D=new Set(["rate-limit","overloaded","connection","auth","protocol","context-overflow","other","wedged","model-not-found"]),L=new Set(["auto","manual","fatal"]),B=new Set(["sdk","daemon","client"]);function d(r,e){if(typeof r!="object"||r===null||Array.isArray(r))throw n(`${e} requires a JSON object`);return r}i(d,"objectBody");function a(r){if(w(r)===null)throw j(`unknown node: ${r}`,{received:r})}i(a,"requireNode");function c(r,e){if(typeof e!="string"||e==="")throw n("expected_execution_id must be a non-empty string");const t=E(r);if(t===null||t.executionId!==e)throw new k(409,"stale_execution","broker execution is no longer current")}i(c,"requireCurrentExecution");function b(r){if(typeof r!="object"||r===null||Array.isArray(r))throw n("retry must be an object");const e=r;if(!L.has(e.disposition))throw n("retry.disposition must be auto, manual, or fatal");if(e.by!==void 0&&!B.has(e.by))throw n("retry.by must be sdk, daemon, or client");for(const t of["attempt","max"])if(e[t]!==void 0&&(!Number.isSafeInteger(e[t])||e[t]<0))throw n(`retry.${t} must be a non-negative safe integer`);if(e.nextAt!==void 0&&typeof e.nextAt!="string")throw n("retry.nextAt must be a string");return e}i(b,"parseRetry");function f(r){const e=d(r,"fault input");if(!l.has(e.link))throw n("fault link is invalid");if(typeof e.op!="string"||e.op==="")throw n("fault op must be a non-empty string");if(!D.has(e.kind))throw n("fault kind is invalid");if(typeof e.message!="string")throw n("fault message must be a string");if(e.operation_id!==void 0&&(typeof e.operation_id!="string"||e.operation_id===""))throw n("operation_id must be a non-empty string");if(e.since!==void 0&&typeof e.since!="string")throw n("since must be a string");if(e.anchor_entry_id!==void 0&&(typeof e.anchor_entry_id!="string"||e.anchor_entry_id===""))throw n("anchor_entry_id must be a non-empty string");const t=e.provider_error===void 0?void 0:R(e.provider_error);if(e.provider_error!==void 0&&t===void 0)throw n("provider_error is invalid");return{...e,...t===void 0?{}:{provider_error:t},retry:b(e.retry)}}i(f,"parseFaultInput");function _(r){return{link:r.link,op:r.op,kind:r.kind,retry:r.retry,message:r.message,...r.operation_id===void 0?{}:{operation_id:r.operation_id},...r.since===void 0?{}:{since:r.since},...r.anchor_entry_id===void 0?{}:{anchorEntryId:r.anchor_entry_id},...r.provider_error===void 0?{}:{providerError:r.provider_error}}}i(_,"faultInput");function p(r){return{fault_id:r.faultId,link:r.link,op:r.op,kind:r.kind,retry:r.retry,message:r.message,since:r.since,operation_id:r.operation_id,...r.anchorEntryId===void 0?{}:{anchor_entry_id:r.anchorEntryId},...r.providerError===void 0?{}:{provider_error:r.providerError}}}i(p,"faultDto");function g(r){const e=m(r),t=F(r);return{fault:e===null?null:p(e),episode:t===null?null:{state:t.state,session_id:t.sessionId,fault:p(t.fault)}}}i(g,"recoveryState");function $(r){const e=d(r,"broker turn"),t=e.event;if(t!=="started"&&t!=="progress"&&t!=="closed"&&t!=="interrupted"&&t!=="exit-diagnostic")throw n("event is invalid");if(typeof e.expected_execution_id!="string"||e.expected_execution_id==="")throw n("expected_execution_id must be a non-empty string");if(t==="closed"){if(e.end_reason!=="settled"&&e.end_reason!=="teardown-aborted")throw n("closed turn requires end_reason settled or teardown-aborted")}else if(e.end_reason!==void 0)throw n("end_reason is valid only for closed turns");if(t==="exit-diagnostic"){const o=d(e.exit_diagnostic,"exit_diagnostic"),s=d(o.transport_poison,"exit_diagnostic.transport_poison");if(o.schema!=="crtr.execution-exit-diagnostic/v1"||!Number.isSafeInteger(s.consecutive_passes)||s.consecutive_passes<1||!Array.isArray(s.routes)||s.routes.length===0||!s.routes.every(u=>typeof u=="string"&&u!==""))throw n("exit_diagnostic is invalid")}else if(e.exit_diagnostic!==void 0)throw n("exit_diagnostic is valid only for exit-diagnostic turns");return e}i($,"parseTurn");function C(r){const e=r.params.id;a(e);const t=$(r.body);c(e,t.expected_execution_id);let o;switch(t.event){case"started":o=h(t.expected_execution_id,{reason:"agent-start"});break;case"interrupted":o=h(t.expected_execution_id,{reason:"prompt-unsettled"});break;case"progress":o=P(t.expected_execution_id);break;case"closed":o=T(t.expected_execution_id,{endReason:t.end_reason});break;case"exit-diagnostic":{const u=t.exit_diagnostic.transport_poison;o=N(t.expected_execution_id,{consecutivePasses:u.consecutive_passes,routes:u.routes});break}}return{status:200,body:{applied:o}}}i(C,"handleTurn");function K(r){const e=d(r,"provider retry");if(typeof e.expected_execution_id!="string"||e.expected_execution_id==="")throw n("expected_execution_id must be a non-empty string");if(!["record-pending","admit","reopen","invalidate","clear"].includes(e.op))throw n("provider retry op is invalid");if(typeof e.session_id!="string"||e.session_id==="")throw n("session_id must be a non-empty string");if(e.op==="record-pending"&&(e.input=f(e.input)),e.op==="admit"){if(typeof e.fault_id!="string"||e.fault_id==="")throw n("admit requires fault_id");e.retry=b(e.retry)}return e}i(K,"parseProviderRetry");function U(r){const e=r.params.id;a(e);const t=K(r.body);c(e,t.expected_execution_id);let o;switch(t.op){case"record-pending":o=A(e,{sessionId:t.session_id,input:_(t.input)})!==null;break;case"admit":o=I(e,{sessionId:t.session_id,faultId:t.fault_id,retry:t.retry});break;case"reopen":o=O(e,{sessionId:t.session_id});break;case"invalidate":o=q(e,{sessionId:t.session_id});break;case"clear":o=S(e,{sessionId:t.session_id});break}return{status:200,body:{applied:o,episode:g(e).episode}}}i(U,"handleProviderRetry");function Y(r){const e=d(r,"broker fault");if(typeof e.expected_execution_id!="string"||e.expected_execution_id==="")throw n("expected_execution_id must be a non-empty string");if(e.op!=="record"&&e.op!=="clear")throw n("fault op must be record or clear");if(e.op==="record"&&(e.input=f(e.input)),e.op==="clear"&&e.link!==void 0&&!l.has(e.link))throw n("fault link is invalid");if(e.preserve_episode!==void 0&&typeof e.preserve_episode!="boolean")throw n("preserve_episode must be boolean");return e}i(Y,"parseBrokerFault");function G(r){const e=r.params.id;a(e);const t=Y(r.body);c(e,t.expected_execution_id);const o=t.op==="record"?v(e,_(t.input)):(y(e,{...t.link===void 0?{}:{link:t.link},...t.preserve_episode===void 0?{}:{preserveEpisode:t.preserve_episode}}),m(e));return{status:200,body:{fault:o===null?null:p(o)}}}i(G,"handleBrokerFault");function J(r){const e=r.params.id;return a(e),c(e,r.query.get("expected_execution_id")),{status:200,body:g(e)}}i(J,"handleRecovery");function V(r){const e=r.params.id;a(e);const t=v(e,_(f(r.body)));return{status:200,body:{fault:t===null?null:p(t)}}}i(V,"handleNodeFaultRecord");function W(r){const e=r.params.id;a(e);const t=r.query.get("link");if(t!==null&&!l.has(t))throw n("fault link is invalid");const o=r.query.get("preserve_episode");if(o!==null&&o!=="true"&&o!=="false")throw n("preserve_episode must be true or false");return{status:200,body:{cleared:y(e,{...t===null?{}:{link:t},...o===null?{}:{preserveEpisode:o==="true"}})}}}i(W,"handleNodeFaultClear");const ee=[{method:"POST",pattern:"/v1/broker/:id/turn",handler:C},{method:"POST",pattern:"/v1/broker/:id/provider-retry",handler:U},{method:"POST",pattern:"/v1/broker/:id/fault",handler:G},{method:"GET",pattern:"/v1/broker/:id/recovery",handler:J}],re=[{method:"POST",pattern:"/v1/nodes/:id/fault",handler:V},{method:"DELETE",pattern:"/v1/nodes/:id/fault",handler:W}];export{ee as brokerRecoveryRoutes,re as nodeFaultRoutes,c as requireCurrentExecution};
1
+ var k=Object.defineProperty;var i=(r,e)=>k(r,"name",{value:e,configurable:!0});import{ApiError as w}from"../../../api/errors.js";import{getNode as E}from"../../../core/canvas/canvas.js";import{liveExecutionForNode as I}from"../../../core/canvas/executions.js";import{admitEpisode as S,clearEpisode as T,clearFault as y,closeTurn as q,invalidateEpisode as R,openTurn as m,parseProviderError as F,readEpisode as A,readFault as h,recordFault as v,recordPendingEpisode as N,recordTransportPoisonVerdict as P,recordTurnProgress as O,reopenEpisode as j}from"../../../core/canvas/recovery.js";import{notFound as D,usage as n}from"../../../core/errors.js";import{ownerOnly as b}from"../router.js";const l=new Set(["pi\u2192provider","viewer\u2194broker","relay\u2194broker","viewer\u2194crtrd","daemon\u2192node","crtr\u2192pi"]),L=new Set(["rate-limit","overloaded","connection","auth","protocol","context-overflow","other","wedged","model-not-found"]),B=new Set(["auto","manual","fatal"]),$=new Set(["sdk","daemon","client"]);function d(r,e){if(typeof r!="object"||r===null||Array.isArray(r))throw n(`${e} requires a JSON object`);return r}i(d,"objectBody");function a(r){if(E(r)===null)throw D(`unknown node: ${r}`,{received:r})}i(a,"requireNode");function c(r,e){if(typeof e!="string"||e==="")throw n("expected_execution_id must be a non-empty string");const t=I(r);if(t===null||t.executionId!==e)throw new w(409,"stale_execution","broker execution is no longer current")}i(c,"requireCurrentExecution");function g(r){if(typeof r!="object"||r===null||Array.isArray(r))throw n("retry must be an object");const e=r;if(!B.has(e.disposition))throw n("retry.disposition must be auto, manual, or fatal");if(e.by!==void 0&&!$.has(e.by))throw n("retry.by must be sdk, daemon, or client");for(const t of["attempt","max"])if(e[t]!==void 0&&(!Number.isSafeInteger(e[t])||e[t]<0))throw n(`retry.${t} must be a non-negative safe integer`);if(e.nextAt!==void 0&&typeof e.nextAt!="string")throw n("retry.nextAt must be a string");return e}i(g,"parseRetry");function f(r){const e=d(r,"fault input");if(!l.has(e.link))throw n("fault link is invalid");if(typeof e.op!="string"||e.op==="")throw n("fault op must be a non-empty string");if(!L.has(e.kind))throw n("fault kind is invalid");if(typeof e.message!="string")throw n("fault message must be a string");if(e.operation_id!==void 0&&(typeof e.operation_id!="string"||e.operation_id===""))throw n("operation_id must be a non-empty string");if(e.since!==void 0&&typeof e.since!="string")throw n("since must be a string");if(e.anchor_entry_id!==void 0&&(typeof e.anchor_entry_id!="string"||e.anchor_entry_id===""))throw n("anchor_entry_id must be a non-empty string");const t=e.provider_error===void 0?void 0:F(e.provider_error);if(e.provider_error!==void 0&&t===void 0)throw n("provider_error is invalid");return{...e,...t===void 0?{}:{provider_error:t},retry:g(e.retry)}}i(f,"parseFaultInput");function _(r){return{link:r.link,op:r.op,kind:r.kind,retry:r.retry,message:r.message,...r.operation_id===void 0?{}:{operation_id:r.operation_id},...r.since===void 0?{}:{since:r.since},...r.anchor_entry_id===void 0?{}:{anchorEntryId:r.anchor_entry_id},...r.provider_error===void 0?{}:{providerError:r.provider_error}}}i(_,"faultInput");function p(r){return{fault_id:r.faultId,link:r.link,op:r.op,kind:r.kind,retry:r.retry,message:r.message,since:r.since,operation_id:r.operation_id,...r.anchorEntryId===void 0?{}:{anchor_entry_id:r.anchorEntryId},...r.providerError===void 0?{}:{provider_error:r.providerError}}}i(p,"faultDto");function x(r){const e=h(r),t=A(r);return{fault:e===null?null:p(e),episode:t===null?null:{state:t.state,session_id:t.sessionId,fault:p(t.fault)}}}i(x,"recoveryState");function C(r){const e=d(r,"broker turn"),t=e.event;if(t!=="started"&&t!=="progress"&&t!=="closed"&&t!=="interrupted"&&t!=="exit-diagnostic")throw n("event is invalid");if(typeof e.expected_execution_id!="string"||e.expected_execution_id==="")throw n("expected_execution_id must be a non-empty string");if(t==="closed"){if(e.end_reason!=="settled"&&e.end_reason!=="teardown-aborted")throw n("closed turn requires end_reason settled or teardown-aborted")}else if(e.end_reason!==void 0)throw n("end_reason is valid only for closed turns");if(t==="exit-diagnostic"){const o=d(e.exit_diagnostic,"exit_diagnostic"),s=d(o.transport_poison,"exit_diagnostic.transport_poison");if(o.schema!=="crtr.execution-exit-diagnostic/v1"||!Number.isSafeInteger(s.consecutive_passes)||s.consecutive_passes<1||!Array.isArray(s.routes)||s.routes.length===0||!s.routes.every(u=>typeof u=="string"&&u!==""))throw n("exit_diagnostic is invalid")}else if(e.exit_diagnostic!==void 0)throw n("exit_diagnostic is valid only for exit-diagnostic turns");return e}i(C,"parseTurn");function K(r){const e=r.params.id;a(e);const t=C(r.body);c(e,t.expected_execution_id);let o;switch(t.event){case"started":o=m(t.expected_execution_id,{reason:"agent-start"});break;case"interrupted":o=m(t.expected_execution_id,{reason:"prompt-unsettled"});break;case"progress":o=O(t.expected_execution_id);break;case"closed":o=q(t.expected_execution_id,{endReason:t.end_reason});break;case"exit-diagnostic":{const u=t.exit_diagnostic.transport_poison;o=P(t.expected_execution_id,{consecutivePasses:u.consecutive_passes,routes:u.routes});break}}return{status:200,body:{applied:o}}}i(K,"handleTurn");function U(r){const e=d(r,"provider retry");if(typeof e.expected_execution_id!="string"||e.expected_execution_id==="")throw n("expected_execution_id must be a non-empty string");if(!["record-pending","admit","reopen","invalidate","clear"].includes(e.op))throw n("provider retry op is invalid");if(typeof e.session_id!="string"||e.session_id==="")throw n("session_id must be a non-empty string");if(e.op==="record-pending"&&(e.input=f(e.input)),e.op==="admit"){if(typeof e.fault_id!="string"||e.fault_id==="")throw n("admit requires fault_id");e.retry=g(e.retry)}return e}i(U,"parseProviderRetry");function Y(r){const e=r.params.id;a(e);const t=U(r.body);c(e,t.expected_execution_id);let o;switch(t.op){case"record-pending":o=N(e,{sessionId:t.session_id,input:_(t.input)})!==null;break;case"admit":o=S(e,{sessionId:t.session_id,faultId:t.fault_id,retry:t.retry});break;case"reopen":o=j(e,{sessionId:t.session_id});break;case"invalidate":o=R(e,{sessionId:t.session_id});break;case"clear":o=T(e,{sessionId:t.session_id});break}return{status:200,body:{applied:o,episode:x(e).episode}}}i(Y,"handleProviderRetry");function G(r){const e=d(r,"broker fault");if(typeof e.expected_execution_id!="string"||e.expected_execution_id==="")throw n("expected_execution_id must be a non-empty string");if(e.op!=="record"&&e.op!=="clear")throw n("fault op must be record or clear");if(e.op==="record"&&(e.input=f(e.input)),e.op==="clear"&&e.link!==void 0&&!l.has(e.link))throw n("fault link is invalid");if(e.preserve_episode!==void 0&&typeof e.preserve_episode!="boolean")throw n("preserve_episode must be boolean");return e}i(G,"parseBrokerFault");function J(r){const e=r.params.id;a(e);const t=G(r.body);c(e,t.expected_execution_id);const o=t.op==="record"?v(e,_(t.input)):(y(e,{...t.link===void 0?{}:{link:t.link},...t.preserve_episode===void 0?{}:{preserveEpisode:t.preserve_episode}}),h(e));return{status:200,body:{fault:o===null?null:p(o)}}}i(J,"handleBrokerFault");function V(r){const e=r.params.id;return a(e),c(e,r.query.get("expected_execution_id")),{status:200,body:x(e)}}i(V,"handleRecovery");function W(r){const e=r.params.id;a(e);const t=v(e,_(f(r.body)));return{status:200,body:{fault:t===null?null:p(t)}}}i(W,"handleNodeFaultRecord");function z(r){const e=r.params.id;a(e);const t=r.query.get("link");if(t!==null&&!l.has(t))throw n("fault link is invalid");const o=r.query.get("preserve_episode");if(o!==null&&o!=="true"&&o!=="false")throw n("preserve_episode must be true or false");return{status:200,body:{cleared:y(e,{...t===null?{}:{link:t},...o===null?{}:{preserveEpisode:o==="true"}})}}}i(z,"handleNodeFaultClear");const te=b([{method:"POST",pattern:"/v1/broker/:id/turn",handler:K},{method:"POST",pattern:"/v1/broker/:id/provider-retry",handler:Y},{method:"POST",pattern:"/v1/broker/:id/fault",handler:J},{method:"GET",pattern:"/v1/broker/:id/recovery",handler:V}]),ne=b([{method:"POST",pattern:"/v1/nodes/:id/fault",handler:W},{method:"DELETE",pattern:"/v1/nodes/:id/fault",handler:z}]);export{te as brokerRecoveryRoutes,ne as nodeFaultRoutes,c as requireCurrentExecution};
@@ -1,6 +1,6 @@
1
- var P=Object.defineProperty;var u=(t,e)=>P(t,"name",{value:e,configurable:!0});import{graphNodes as I,pruneNodes as K,pruneToLimit as A,rosterEdges as C,rosterNodes as D}from"../../../core/canvas/canvas.js";import{activeBackgroundBashJobs as q}from"../../../core/bash-jobs.js";import{contextDir as H}from"../../../core/canvas/paths.js";import{nowIso as k}from"../../../core/fs-utils.js";import{isPidPresent as J}from"../../../core/canvas/pid.js";import{dashboardRowsAllFromSource as z,enrichRowsFromSource as Q}from"../../../core/canvas/render-source.js";import{localCanvasSource as M}from"../../../core/canvas/source.js";import{ticketCountsForNodes as j,ticketsAcrossCanvas as U}from"../../../core/canvas/attention.js";import{buildCorpus as Y,groupCorpus as V,resolveRef as W}from"../../../core/canvas/history.js";import{listFocuses as R,reapEmptyNodes as X}from"../../../core/runtime/placement.js";import{notFound as Z,usage as p}from"../../../core/errors.js";import{toGraphNodeDTO as ee}from"../map.js";function te(){return{status:200,body:{items:U().map(e=>({node_id:e.node_id,name:e.name,cwd:e.cwd,count:e.count,subjects:e.subjects}))}}}u(te,"handleAttention");function ne(t){const e=t.body;if(e===null||typeof e!="object"||!Array.isArray(e.node_ids))throw p("attention count request requires node_ids: string[]");const n=e.node_ids;if(!n.every(s=>typeof s=="string"))throw p("attention count request node_ids must contain only strings");return{status:200,body:{counts:j(n)}}}u(ne,"handleAttentionCounts");function B(t){return Buffer.from(String(t),"utf8").toString("base64")}u(B,"encodeCursor");function x(t){const e=Number(Buffer.from(t,"base64").toString("utf8"));if(!Number.isInteger(e)||e<0)throw p(`invalid cursor: ${t}`);return e}u(x,"decodeCursor");function oe(t,e,n){const s=t.loadBody().split(`
2
- `);if(e.length>0){const i=s.findIndex(d=>{const o=d.toLowerCase();return e.some(c=>o.includes(c))});if(i!==-1)return s.slice(i,i+n).map(d=>d.trim()).filter(d=>d!=="").join(" \u23CE ")}const a=s.map(i=>i.trim()).filter(i=>i!=="").slice(0,n).join(" \u23CE ");return a!==""?a:t.title}u(oe,"snippet");function re(t,e,n){const r=[...t];return e==="relevance"&&n!==void 0?r.sort((s,a)=>(n.get(a.ref)??0)-(n.get(s.ref)??0)||a.tsMs-s.tsMs||s.ref.localeCompare(a.ref)):e==="oldest"?r.sort((s,a)=>s.tsMs-a.tsMs||s.ref.localeCompare(a.ref)):r.sort((s,a)=>a.tsMs-s.tsMs||s.ref.localeCompare(a.ref)),r}u(re,"sortArtifacts");function se(t){if(t==null)return{};if(typeof t!="object")throw p("history search body must be a JSON object");return t}u(se,"parseSearchBody");function ie(t){if(t===null||typeof t!="object")throw p("history grep body must be a JSON object");const e=t;if(typeof e.pattern!="string"||e.pattern==="")throw p("history grep body requires a non-empty pattern");return e}u(ie,"parseGrepBody");function $(t){const e={cwd:t.cwd,allCwds:t.all_cwds===!0,under:t.under,nodes:t.nodes},n={types:t.types,reportKind:t.report_kind,kinds:t.kinds,statuses:t.statuses,sinceMs:t.since_ms,untilMs:t.until_ms,origins:t.origins,roles:t.roles,from:t.from};return Y(e,n)}u($,"buildCorpusFromQuery");function de(t){if(t==null)return{};if(typeof t!="object")throw p("history stats body must be a JSON object");return t}u(de,"parseStatsBody");const L=["origin","node","kind","day","type","role"];function ae(t){const e=de(t.body),n=e.group_by??"type";if(!L.includes(n))throw p(`--group-by must be one of: ${L.join(", ")}; received: ${String(e.group_by)}`);const r=$(e),s=V(r,n);return{status:200,body:{group_by:n,groups:s,total:s.reduce((i,d)=>i+d.count,0),scanned:r.length}}}u(ae,"handleHistoryStats");function ce(t){const e=ie(t.body),n=Math.min(100,Math.max(1,e.limit??20)),r=$(e),s=e.cursor!==void 0?x(e.cursor):0;let a;try{a=new RegExp(e.pattern,"i")}catch{throw p(`invalid regex pattern: ${e.pattern}`)}const i=[];for(const f of r)f.loadBody().split(`
3
- `).forEach((y,b)=>{a.test(y)&&i.push({ref:f.ref,node:`${f.nodeName} (${f.nodeId})`,ts:f.ts,line:b+1,text:y.trim()})});i.sort((f,m)=>f.ref.localeCompare(m.ref)||f.line-m.line);const d=i.slice(s,s+n),o=s+n<i.length?B(s+n):null;return{status:200,body:{hits:d,next_cursor:o,total:i.length}}}u(ce,"handleHistoryGrep");function ue(t){const e=se(t.body),n=(e.query??"").trim(),r=e.weigh_body===!0,s=e.full===!0,a=Math.max(1,e.snippet_lines??1),i=Math.min(100,Math.max(1,e.limit??20)),d=$(e),o=e.cursor!==void 0?x(e.cursor):0,c=n.toLowerCase().split(/\s+/).filter(l=>l.length>0);let f=d,m;const y=e.sort??(c.length>0?"relevance":"recency");if(c.length>0&&y==="relevance"){m=new Map;const l=[];for(const h of d){const S=h.title.toLowerCase(),F=h.nodeName.toLowerCase(),G=h.nodeDesc.toLowerCase(),N=r?h.loadBody().toLowerCase():null;let _=0;for(const v of c)S.includes(v)&&(_+=10),F.includes(v)&&(_+=5),G.includes(v)&&(_+=3),N!==null&&N.includes(v)&&(_+=1);_>0&&(m.set(h.ref,_),l.push(h))}f=l}else c.length>0&&(f=d.filter(l=>{const h=`${l.title}
1
+ var P=Object.defineProperty;var u=(t,e)=>P(t,"name",{value:e,configurable:!0});import{graphNodes as I,pruneNodes as K,pruneToLimit as A,rosterEdges as C,rosterNodes as D}from"../../../core/canvas/canvas.js";import{activeBackgroundBashJobs as q}from"../../../core/bash-jobs.js";import{contextDir as H}from"../../../core/canvas/paths.js";import{nowIso as k}from"../../../core/fs-utils.js";import{isPidPresent as J}from"../../../core/canvas/pid.js";import{dashboardRowsAllFromSource as z,enrichRowsFromSource as Q}from"../../../core/canvas/render-source.js";import{localCanvasSource as M}from"../../../core/canvas/source.js";import{ticketCountsForNodes as j,ticketsAcrossCanvas as U}from"../../../core/canvas/attention.js";import{buildCorpus as Y,groupCorpus as V,resolveRef as W}from"../../../core/canvas/history.js";import{listFocuses as R,reapEmptyNodes as X}from"../../../core/runtime/placement.js";import{notFound as Z,usage as p}from"../../../core/errors.js";import{toGraphNodeDTO as ee}from"../map.js";function te(){return{status:200,body:{items:U().map(e=>({node_id:e.node_id,name:e.name,cwd:e.cwd,count:e.count,subjects:e.subjects}))}}}u(te,"handleAttention");function ne(t){const e=t.body;if(e===null||typeof e!="object"||!Array.isArray(e.node_ids))throw p("attention count request requires node_ids: string[]");const n=e.node_ids;if(!n.every(s=>typeof s=="string"))throw p("attention count request node_ids must contain only strings");return{status:200,body:{counts:j(n)}}}u(ne,"handleAttentionCounts");function B(t){return Buffer.from(String(t),"utf8").toString("base64")}u(B,"encodeCursor");function O(t){const e=Number(Buffer.from(t,"base64").toString("utf8"));if(!Number.isInteger(e)||e<0)throw p(`invalid cursor: ${t}`);return e}u(O,"decodeCursor");function oe(t,e,n){const s=t.loadBody().split(`
2
+ `);if(e.length>0){const i=s.findIndex(d=>{const o=d.toLowerCase();return e.some(c=>o.includes(c))});if(i!==-1)return s.slice(i,i+n).map(d=>d.trim()).filter(d=>d!=="").join(" \u23CE ")}const a=s.map(i=>i.trim()).filter(i=>i!=="").slice(0,n).join(" \u23CE ");return a!==""?a:t.title}u(oe,"snippet");function re(t,e,n){const r=[...t];return e==="relevance"&&n!==void 0?r.sort((s,a)=>(n.get(a.ref)??0)-(n.get(s.ref)??0)||a.tsMs-s.tsMs||s.ref.localeCompare(a.ref)):e==="oldest"?r.sort((s,a)=>s.tsMs-a.tsMs||s.ref.localeCompare(a.ref)):r.sort((s,a)=>a.tsMs-s.tsMs||s.ref.localeCompare(a.ref)),r}u(re,"sortArtifacts");function se(t){if(t==null)return{};if(typeof t!="object")throw p("history search body must be a JSON object");return t}u(se,"parseSearchBody");function ie(t){if(t===null||typeof t!="object")throw p("history grep body must be a JSON object");const e=t;if(typeof e.pattern!="string"||e.pattern==="")throw p("history grep body requires a non-empty pattern");return e}u(ie,"parseGrepBody");function $(t){const e={cwd:t.cwd,allCwds:t.all_cwds===!0,under:t.under,nodes:t.nodes},n={types:t.types,reportKind:t.report_kind,kinds:t.kinds,statuses:t.statuses,sinceMs:t.since_ms,untilMs:t.until_ms,origins:t.origins,roles:t.roles,from:t.from};return Y(e,n)}u($,"buildCorpusFromQuery");function de(t){if(t==null)return{};if(typeof t!="object")throw p("history stats body must be a JSON object");return t}u(de,"parseStatsBody");const x=["origin","node","kind","day","type","role"];function ae(t){const e=de(t.body),n=e.group_by??"type";if(!x.includes(n))throw p(`--group-by must be one of: ${x.join(", ")}; received: ${String(e.group_by)}`);const r=$(e),s=V(r,n);return{status:200,body:{group_by:n,groups:s,total:s.reduce((i,d)=>i+d.count,0),scanned:r.length}}}u(ae,"handleHistoryStats");function ce(t){const e=ie(t.body),n=Math.min(100,Math.max(1,e.limit??20)),r=$(e),s=e.cursor!==void 0?O(e.cursor):0;let a;try{a=new RegExp(e.pattern,"i")}catch{throw p(`invalid regex pattern: ${e.pattern}`)}const i=[];for(const f of r)f.loadBody().split(`
3
+ `).forEach((y,b)=>{a.test(y)&&i.push({ref:f.ref,node:`${f.nodeName} (${f.nodeId})`,ts:f.ts,line:b+1,text:y.trim()})});i.sort((f,m)=>f.ref.localeCompare(m.ref)||f.line-m.line);const d=i.slice(s,s+n),o=s+n<i.length?B(s+n):null;return{status:200,body:{hits:d,next_cursor:o,total:i.length}}}u(ce,"handleHistoryGrep");function ue(t){const e=se(t.body),n=(e.query??"").trim(),r=e.weigh_body===!0,s=e.full===!0,a=Math.max(1,e.snippet_lines??1),i=Math.min(100,Math.max(1,e.limit??20)),d=$(e),o=e.cursor!==void 0?O(e.cursor):0,c=n.toLowerCase().split(/\s+/).filter(l=>l.length>0);let f=d,m;const y=e.sort??(c.length>0?"relevance":"recency");if(c.length>0&&y==="relevance"){m=new Map;const l=[];for(const h of d){const S=h.title.toLowerCase(),F=h.nodeName.toLowerCase(),G=h.nodeDesc.toLowerCase(),N=r?h.loadBody().toLowerCase():null;let _=0;for(const v of c)S.includes(v)&&(_+=10),F.includes(v)&&(_+=5),G.includes(v)&&(_+=3),N!==null&&N.includes(v)&&(_+=1);_>0&&(m.set(h.ref,_),l.push(h))}f=l}else c.length>0&&(f=d.filter(l=>{const h=`${l.title}
4
4
  ${l.nodeName}
5
5
  ${l.nodeDesc}${r?`
6
- `+l.loadBody():""}`.toLowerCase();return c.some(S=>h.includes(S))}));const b=re(f,y,m),T=b.slice(o,o+i),E=o+i<b.length?B(o+i):null;return{status:200,body:{hits:T.map(l=>{const h={ref:l.ref,node:`${l.nodeName} (${l.nodeId})`,kind:l.nodeKind,source:l.source==="report"&&l.reportKind?`report:${l.reportKind}`:l.source,ts:l.ts};return y==="relevance"&&m!==void 0&&(h.score=m.get(l.ref)??0),s?h.body=l.loadBody():h.snippet=oe(l,c,a),h}),next_cursor:E,total:b.length}}}u(ue,"handleHistorySearch");function le(t){const e=(t.query.get("ref")??"").trim(),n=t.query.get("frontmatter")==="true";if(!e.includes(":"))throw p(`ref must be <node-id>:<relpath>; received: ${e}`,{received:e,next:"Get a valid ref from `crtr canvas history search` or `crtr node inspect artifacts <node-id>`."});let r;try{r=W(e)}catch(o){throw p(`ref rejected: ${o.message}`,{received:e,next:"Refs come verbatim from `crtr canvas history search`; do not hand-construct relpaths."})}if(r===null)throw Z(`no artifact for ref: ${e}`,{ref:e,next:"The node or file may not exist. Re-run `crtr canvas history search` for a current ref, or `crtr node inspect artifacts <node-id>` to list a node's artifacts."});const s=r.source==="report"&&r.reportKind?`report:${r.reportKind}`:r.source,i=(t.query.get("format")==="raw"||n)&&r.raw!==null?r.raw:r.body;return{status:200,body:{ref:e,node:`${r.nodeName} (${r.nodeId})`,source:s,ts:r.ts,content:i}}}u(le,"handleHistoryRead");function fe(t){for(const[r]of t.query)if(r!=="live")throw p(`unknown snapshot query parameter: ${r}`);const e=t.query.getAll("live");if(e.length>1)throw p("live must appear at most once");const n=e[0];if(n===void 0||n==="false"||n==="0")return!1;if(n==="true"||n==="1")return!0;throw p("live must be true or false")}u(fe,"snapshotLiveOnly");async function me(t){const e=new Set(R().map(o=>o.node_id)),n=await z(M,e,fe(t)),r=j(n.map(o=>o.node_id));await Q(M,n,r);const s=n.map(o=>{const c=o.srcRow,f=c?.host_kind??"tmux";return{node_id:o.node_id,name:o.name,title:o.handle??o.name,description:o.description??null,kind:o.kind,mode:o.mode,lifecycle:o.lifecycle??c?.lifecycle,status:o.status,cwd:o.cwd,profile_id:o.profile_id??null,parent:c?.parent??null,created:o.created,host_kind:f,enterable:f==="broker",attention_count:o.asks,...c?.cycles!=null?{cycles:c.cycles}:{},...o.mtimeMs!==void 0?{last_activity:new Date(o.mtimeMs).toISOString()}:{},ctx_tokens:o.ctx_tokens,streaming:o.streaming??!1,jobs_active:c!==void 0&&J(c.pi_pid)?q(H(o.node_id)).length:0,waiting_for:c?.waiting_for??null,hanging:o.hanging??null,viewed:o.viewed??!1,final_report:c?.final_report??null,finalized_at:c?.finalized_at??null}}),a=new Map;for(const o of C()){const c=a.get(o.from_id);c===void 0?a.set(o.from_id,[o.to_id]):c.push(o.to_id)}const i=Object.fromEntries(n.map(o=>[o.node_id,a.get(o.node_id)??[]]));return{status:200,body:{generated_at:k(),nodes:s,subscriptions:i}}}u(me,"handleSnapshot");function O(){const t=D().map(n=>{const r=n.host_kind??"tmux";return{node_id:n.node_id,name:n.name,kind:n.kind,mode:n.mode,lifecycle:n.lifecycle,status:n.status,cwd:n.cwd,host_kind:r,enterable:r==="broker",parent:n.parent,created:n.created}}),e=C().map(n=>({from_id:n.from_id,to_id:n.to_id,active:n.active,created:n.created}));return{generated_at:k(),nodes:t,edges:e}}u(O,"buildRoster");let g=null,w=null;function pe(){return g===null?(g=Promise.resolve().then(()=>O()).finally(()=>{g=null}),g):(w===null&&(w=g.then(()=>O()).finally(()=>{w=null})),w)}u(pe,"rosterCoalesced");async function he(){return{status:200,body:await pe()}}u(he,"handleRoster");function ye(){return{status:200,body:{generated_at:k(),nodes:I().map(ee),edges:C().map(e=>({from_id:e.from_id,to_id:e.to_id,active:e.active,created:e.created})),focused_node_ids:R().map(e=>e.node_id)}}}u(ye,"handleGraph");function _e(t){if(t==null)return{};if(typeof t!="object")throw p("prune body must be a JSON object");const e=t,n=u(f=>{const m=e[f];if(m!==void 0){if(typeof m!="number"||!Number.isFinite(m))throw p(`${f} must be a number`);return m}},"num"),r=u(f=>{const m=e[f];if(m!==void 0){if(typeof m!="boolean")throw p(`${f} must be a boolean`);return m}},"bool"),s={},a=n("limit");a!==void 0&&(s.limit=a);const i=n("ttl_days");i!==void 0&&(s.ttl_days=i);const d=r("include_stale");d!==void 0&&(s.include_stale=d);const o=r("empty");o!==void 0&&(s.empty=o);const c=r("dry_run");return c!==void 0&&(s.dry_run=c),s}u(_e,"parsePruneBody");function be(t){const e=_e(t.body),n=e.ttl_days??14,r=e.dry_run??!1;let s;return e.limit!==void 0?s=A({maxNodes:e.limit,dryRun:r}).pruned.map(d=>({node_id:d.node_id,status:d.status,created:d.created})):e.empty===!0?s=X({dryRun:r}).map(d=>({node_id:d,status:"empty",created:""})):s=K({ttlDays:n,dryRun:r,includeStale:e.include_stale??!1}).pruned.map(d=>({node_id:d.node_id,status:d.status,created:d.created})),{status:200,body:{pruned:s,dry_run:r,ttl_days:n}}}u(be,"handlePrune");const Te=[{method:"GET",pattern:"/v1/canvas/attention",handler:te},{method:"POST",pattern:"/v1/canvas/attention/counts",handler:ne},{method:"POST",pattern:"/v1/canvas/history/search",handler:ue},{method:"POST",pattern:"/v1/canvas/history/grep",handler:ce},{method:"GET",pattern:"/v1/canvas/history/read",handler:le},{method:"POST",pattern:"/v1/canvas/history/stats",handler:ae},{method:"GET",pattern:"/v1/canvas/snapshot",handler:me},{method:"GET",pattern:"/v1/canvas/roster",handler:he},{method:"GET",pattern:"/v1/canvas/graph",handler:ye},{method:"POST",pattern:"/v1/canvas/prune",handler:be}];export{Te as canvasRoutes};
6
+ `+l.loadBody():""}`.toLowerCase();return c.some(S=>h.includes(S))}));const b=re(f,y,m),T=b.slice(o,o+i),E=o+i<b.length?B(o+i):null;return{status:200,body:{hits:T.map(l=>{const h={ref:l.ref,node:`${l.nodeName} (${l.nodeId})`,kind:l.nodeKind,source:l.source==="report"&&l.reportKind?`report:${l.reportKind}`:l.source,ts:l.ts};return y==="relevance"&&m!==void 0&&(h.score=m.get(l.ref)??0),s?h.body=l.loadBody():h.snippet=oe(l,c,a),h}),next_cursor:E,total:b.length}}}u(ue,"handleHistorySearch");function le(t){const e=(t.query.get("ref")??"").trim(),n=t.query.get("frontmatter")==="true";if(!e.includes(":"))throw p(`ref must be <node-id>:<relpath>; received: ${e}`,{received:e,next:"Get a valid ref from `crtr canvas history search` or `crtr node inspect artifacts <node-id>`."});let r;try{r=W(e)}catch(o){throw p(`ref rejected: ${o.message}`,{received:e,next:"Refs come verbatim from `crtr canvas history search`; do not hand-construct relpaths."})}if(r===null)throw Z(`no artifact for ref: ${e}`,{ref:e,next:"The node or file may not exist. Re-run `crtr canvas history search` for a current ref, or `crtr node inspect artifacts <node-id>` to list a node's artifacts."});const s=r.source==="report"&&r.reportKind?`report:${r.reportKind}`:r.source,i=(t.query.get("format")==="raw"||n)&&r.raw!==null?r.raw:r.body;return{status:200,body:{ref:e,node:`${r.nodeName} (${r.nodeId})`,source:s,ts:r.ts,content:i}}}u(le,"handleHistoryRead");function fe(t){for(const[r]of t.query)if(r!=="live")throw p(`unknown snapshot query parameter: ${r}`);const e=t.query.getAll("live");if(e.length>1)throw p("live must appear at most once");const n=e[0];if(n===void 0||n==="false"||n==="0")return!1;if(n==="true"||n==="1")return!0;throw p("live must be true or false")}u(fe,"snapshotLiveOnly");async function me(t){const e=new Set(R().map(o=>o.node_id)),n=await z(M,e,fe(t)),r=j(n.map(o=>o.node_id));await Q(M,n,r);const s=n.map(o=>{const c=o.srcRow,f=c?.host_kind??"tmux";return{node_id:o.node_id,name:o.name,title:o.handle??o.name,description:o.description??null,kind:o.kind,mode:o.mode,lifecycle:o.lifecycle??c?.lifecycle,status:o.status,cwd:o.cwd,profile_id:o.profile_id??null,parent:c?.parent??null,created:o.created,host_kind:f,enterable:f==="broker",attention_count:o.asks,...c?.cycles!=null?{cycles:c.cycles}:{},...o.mtimeMs!==void 0?{last_activity:new Date(o.mtimeMs).toISOString()}:{},ctx_tokens:o.ctx_tokens,streaming:o.streaming??!1,jobs_active:c!==void 0&&J(c.pi_pid)?q(H(o.node_id)).length:0,waiting_for:c?.waiting_for??null,hanging:o.hanging??null,viewed:o.viewed??!1,final_report:c?.final_report??null,finalized_at:c?.finalized_at??null}}),a=new Map;for(const o of C()){const c=a.get(o.from_id);c===void 0?a.set(o.from_id,[o.to_id]):c.push(o.to_id)}const i=Object.fromEntries(n.map(o=>[o.node_id,a.get(o.node_id)??[]]));return{status:200,body:{generated_at:k(),nodes:s,subscriptions:i}}}u(me,"handleSnapshot");function L(){const t=D().map(n=>{const r=n.host_kind??"tmux";return{node_id:n.node_id,name:n.name,kind:n.kind,mode:n.mode,lifecycle:n.lifecycle,status:n.status,cwd:n.cwd,host_kind:r,enterable:r==="broker",parent:n.parent,created:n.created}}),e=C().map(n=>({from_id:n.from_id,to_id:n.to_id,active:n.active,created:n.created}));return{generated_at:k(),nodes:t,edges:e}}u(L,"buildRoster");let g=null,w=null;function pe(){return g===null?(g=Promise.resolve().then(()=>L()).finally(()=>{g=null}),g):(w===null&&(w=g.then(()=>L()).finally(()=>{w=null})),w)}u(pe,"rosterCoalesced");async function he(){return{status:200,body:await pe()}}u(he,"handleRoster");function ye(){return{status:200,body:{generated_at:k(),nodes:I().map(ee),edges:C().map(e=>({from_id:e.from_id,to_id:e.to_id,active:e.active,created:e.created})),focused_node_ids:R().map(e=>e.node_id)}}}u(ye,"handleGraph");function _e(t){if(t==null)return{};if(typeof t!="object")throw p("prune body must be a JSON object");const e=t,n=u(f=>{const m=e[f];if(m!==void 0){if(typeof m!="number"||!Number.isFinite(m))throw p(`${f} must be a number`);return m}},"num"),r=u(f=>{const m=e[f];if(m!==void 0){if(typeof m!="boolean")throw p(`${f} must be a boolean`);return m}},"bool"),s={},a=n("limit");a!==void 0&&(s.limit=a);const i=n("ttl_days");i!==void 0&&(s.ttl_days=i);const d=r("include_stale");d!==void 0&&(s.include_stale=d);const o=r("empty");o!==void 0&&(s.empty=o);const c=r("dry_run");return c!==void 0&&(s.dry_run=c),s}u(_e,"parsePruneBody");function be(t){const e=_e(t.body),n=e.ttl_days??14,r=e.dry_run??!1;let s;return e.limit!==void 0?s=A({maxNodes:e.limit,dryRun:r}).pruned.map(d=>({node_id:d.node_id,status:d.status,created:d.created})):e.empty===!0?s=X({dryRun:r}).map(d=>({node_id:d,status:"empty",created:""})):s=K({ttlDays:n,dryRun:r,includeStale:e.include_stale??!1}).pruned.map(d=>({node_id:d.node_id,status:d.status,created:d.created})),{status:200,body:{pruned:s,dry_run:r,ttl_days:n}}}u(be,"handlePrune");const Te=[{method:"GET",pattern:"/v1/canvas/attention",handler:te},{method:"POST",pattern:"/v1/canvas/attention/counts",handler:ne},{method:"POST",pattern:"/v1/canvas/history/search",handler:ue},{method:"POST",pattern:"/v1/canvas/history/grep",handler:ce},{method:"GET",pattern:"/v1/canvas/history/read",handler:le},{method:"POST",pattern:"/v1/canvas/history/stats",handler:ae},{method:"GET",pattern:"/v1/canvas/snapshot",handler:me},{method:"GET",pattern:"/v1/canvas/roster",handler:he},{method:"GET",pattern:"/v1/canvas/graph",handler:ye},{method:"POST",pattern:"/v1/canvas/prune",ownerOnly:!0,handler:be}];export{Te as canvasRoutes};
@@ -1,2 +1,2 @@
1
- import type { RouteTable } from '../router.js';
1
+ import { type RouteTable } from '../router.js';
2
2
  export declare const cronRoutes: RouteTable;
@@ -1 +1 @@
1
- var z=Object.defineProperty;var o=(e,n)=>z(e,"name",{value:n,configurable:!0});import{randomUUID as B}from"node:crypto";import{ApiError as d}from"../../../api/errors.js";import{armCron as G,cancelCron as L,getCron as l,listCrons as y,listCronRuns as j,pokeHeldCrons as Z,setCronState as q}from"../../../core/canvas/crons.js";import{getNode as k}from"../../../core/canvas/canvas.js";import{assertScope as N}from"../../../core/scopes.js";import{InputError as t}from"../../../core/io.js";import{nextSlotAfter as H}from"../../../core/wake.js";import{executeCron as Y,markSelfCanceledCronRun as F}from"../../cron-run.js";import{toCronDTO as f,toCronRunDTO as C}from"../map.js";function h(e,n){const r=e[n];if(typeof r!="string"||r.trim()==="")throw new t({error:"missing_field",message:`cron arm request requires a non-empty "${n}"`,field:n,next:`Send a non-empty string "${n}".`});return r}o(h,"requireString");function _(e,n,r,s){if(e==null)return s;if(typeof e=="string"&&r.includes(e))return e;throw new t({error:`bad_${n}`,message:`"${String(e)}" is not a valid ${n}`,field:n,next:`Use one of: ${r.join(", ")}.`})}o(_,"requireEnum");function K(e){if(e==="human")return JSON.stringify({human:!0});if(e.startsWith("node:")){const n=e.slice(5).trim();if(n==="")throw new t({error:"bad_sink",message:"node sink requires a node id",field:"sink",next:'Use sink "node:<node-id>".'});if(k(n)===null)throw new t({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 t({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 t({error:"bad_sink",message:`"${e}" is not a valid sink`,field:"sink",next:"Use node:<node-id>, spawn:<kind>, or human."})}o(K,"parseSinkSpec");const M=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/;function T(e,n){if(!M.test(e)||Number.isNaN(Date.parse(e)))throw new t({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}o(T,"requireUtcIso");function Q(e){try{H(e,new Date)}catch(n){throw new t({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}o(Q,"requireRecur");function V(e){let n;try{n=JSON.parse(e)}catch{throw new t({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 t({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,s]of Object.entries(n))if(typeof s!="string")throw new t({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}o(V,"requireEnvJson");function b(e){const n=e.query.get("profile");return n!==null&&n.trim()!==""?n.trim():null}o(b,"callerProfile");function E(e,n){return n===null||e.scope==="global"||e.profile===n}o(E,"inScope");function X(e){const n=e.body??{},r=h(n,"name"),s=h(n,"command"),i=T(h(n,"fire_at"),"fire_at"),P=h(n,"cwd"),A=typeof n.recur=="string"&&n.recur!==""?Q(n.recur):null,J=typeof n.expires_at=="string"&&n.expires_at!==""?T(n.expires_at,"expires_at"):null,U=typeof n.env_json=="string"&&n.env_json!==""?V(n.env_json):null,a=typeof n.sink=="string"&&n.sink.trim()!==""?n.sink.trim():null,c=_(n.on_output,"on_output",["silent","on-failure","always","on-change"],a?.startsWith("node:")?"on-change":"on-failure"),R=_(n.overlap,"overlap",["skip","queue","replace"],"skip"),D=_(n.tier,"tier",["normal","urgent","critical"],"normal"),x=c==="always"||c==="on-change";if(x&&a===null)throw new t({error:"sink_required",message:`on_output "${c}" 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(!x&&a!==null)throw new t({error:"sink_unused",message:`on_output "${c}" 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 W=a!==null?K(a):"{}",g=typeof n.created_by=="string"&&n.created_by!==""?n.created_by:null;if(g!==null){const v=k(g);v!==null&&(N(v,"schedule"),a?.startsWith("spawn:")&&N(v,"act"))}const u=typeof n.anchor_node=="string"&&n.anchor_node!==""?n.anchor_node:null;if(u!==null&&k(u)===null)throw new t({error:"anchor_not_found",message:`anchor node ${u} 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 O=n.cancel_on_wake===!0;if(O&&u===null)throw new t({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 p=n.run_timeout_s??300;if(typeof p!="number"||!Number.isInteger(p)||p<=0)throw new t({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 w=typeof n.profile=="string"&&n.profile!==""?n.profile:null,$=_(n.scope,"scope",["profile","global"],w!==null?"profile":"global");if($==="profile"&&w===null)throw new t({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.'});const I=B();return G({cron_id:I,name:r,created_by:g,command:s,fire_at:i,recur:A,tz:typeof n.tz=="string"?n.tz:null,expires_at:J,anchor_node:u,cancel_on_wake:O,cwd:P,env_json:U,profile:w,scope:$,run_timeout_s:p,overlap:R,on_output:c,sink:W,tier:D}),{status:201,body:f(l(I),null)}}o(X,"handleArm");function nn(e){const n=b(e);return{status:200,body:(n===null?y({all:!0}):[...y({profile:n}),...y({global:!0})].sort((s,i)=>s.fire_at<i.fire_at?-1:s.fire_at>i.fire_at?1:0)).map(s=>f(s,S(s)))}}o(nn,"handleList");function S(e){return j(e.cron_id)[0]??null}o(S,"lastRunOf");function m(e){const n=e.params.cronId,r=l(n);if(r===null)throw new d(404,"cron_not_found",`no cron ${n}`);if(!E(r,b(e)))throw new d(404,"cron_not_found",`no cron ${n} in this profile \u2014 it is scoped to another profile`);return r}o(m,"requireCron");function en(e){const n=m(e),r=j(n.cron_id);return{status:200,body:{cron:f(n,r[0]??null),runs:r.map(C)}}}o(en,"handleShow");function rn(e){const n=m(e);q(n.cron_id,"paused");const r=l(n.cron_id);return{status:200,body:f(r,S(r))}}o(rn,"handlePause");function on(e){const n=m(e);q(n.cron_id,"active");const r=l(n.cron_id);return{status:200,body:f(r,S(r))}}o(on,"handleResume");async function tn(e){const n=m(e);if(n.run_state==="running")throw new d(409,"cron_running",`cron ${n.cron_id} has a run in flight \u2014 wait for it to settle`);const r=await Y(n,{outOfBand:!0});if(r===null)throw new d(409,"cron_running",`cron ${n.cron_id} was claimed by a concurrent run \u2014 check \`cron show\` for its result`);return{status:200,body:C(r)}}o(tn,"handleRun");function sn(){const e=new Date().toISOString();return{status:200,body:{unparked:Z(e),at:e}}}o(sn,"handlePoke");function an(e){const n=e.params.cronId,r=l(n);if(r!==null&&!E(r,b(e)))throw new d(404,"cron_not_found",`no cron ${n} in this profile \u2014 it is scoped to another profile`);const s=e.query.get("run_id"),i=s!==null&&F(n,s);return L(n,{preserveRunningProcess:i}),{status:204}}o(an,"handleCancel");const wn=[{method:"POST",pattern:"/v1/crons",handler:X},{method:"GET",pattern:"/v1/crons",handler:nn},{method:"GET",pattern:"/v1/crons/:cronId",handler:en},{method:"POST",pattern:"/v1/crons/:cronId/pause",handler:rn},{method:"POST",pattern:"/v1/crons/:cronId/resume",handler:on},{method:"POST",pattern:"/v1/crons/poke",handler:sn},{method:"POST",pattern:"/v1/crons/:cronId/run",handler:tn},{method:"DELETE",pattern:"/v1/crons/:cronId",handler:an}];export{wn as cronRoutes};
1
+ var z=Object.defineProperty;var o=(e,n)=>z(e,"name",{value:n,configurable:!0});import{randomUUID as B}from"node:crypto";import{ApiError as d}from"../../../api/errors.js";import{armCron as G,cancelCron as L,getCron as l,listCrons as y,listCronRuns as j,pokeHeldCrons as Z,setCronState as q}from"../../../core/canvas/crons.js";import{getNode as k}from"../../../core/canvas/canvas.js";import{assertScope as C}from"../../../core/scopes.js";import{InputError as t}from"../../../core/io.js";import{nextSlotAfter as H}from"../../../core/wake.js";import{executeCron as Y,markSelfCanceledCronRun as F}from"../../cron-run.js";import{toCronDTO as f,toCronRunDTO as N}from"../map.js";import{assertCeiling as K}from"../router.js";function h(e,n){const r=e[n];if(typeof r!="string"||r.trim()==="")throw new t({error:"missing_field",message:`cron arm request requires a non-empty "${n}"`,field:n,next:`Send a non-empty string "${n}".`});return r}o(h,"requireString");function m(e,n,r,s){if(e==null)return s;if(typeof e=="string"&&r.includes(e))return e;throw new t({error:`bad_${n}`,message:`"${String(e)}" is not a valid ${n}`,field:n,next:`Use one of: ${r.join(", ")}.`})}o(m,"requireEnum");function M(e){if(e==="human")return JSON.stringify({human:!0});if(e.startsWith("node:")){const n=e.slice(5).trim();if(n==="")throw new t({error:"bad_sink",message:"node sink requires a node id",field:"sink",next:'Use sink "node:<node-id>".'});if(k(n)===null)throw new t({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 t({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 t({error:"bad_sink",message:`"${e}" is not a valid sink`,field:"sink",next:"Use node:<node-id>, spawn:<kind>, or human."})}o(M,"parseSinkSpec");const Q=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/;function T(e,n){if(!Q.test(e)||Number.isNaN(Date.parse(e)))throw new t({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}o(T,"requireUtcIso");function V(e){try{H(e,new Date)}catch(n){throw new t({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}o(V,"requireRecur");function X(e){let n;try{n=JSON.parse(e)}catch{throw new t({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 t({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,s]of Object.entries(n))if(typeof s!="string")throw new t({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}o(X,"requireEnvJson");function b(e){const n=e.query.get("profile");return n!==null&&n.trim()!==""?n.trim():null}o(b,"callerProfile");function E(e,n){return n===null||e.scope==="global"||e.profile===n}o(E,"inScope");function nn(e){const n=e.body??{},r=h(n,"name"),s=h(n,"command"),a=T(h(n,"fire_at"),"fire_at"),P=h(n,"cwd"),A=typeof n.recur=="string"&&n.recur!==""?V(n.recur):null,J=typeof n.expires_at=="string"&&n.expires_at!==""?T(n.expires_at,"expires_at"):null,U=typeof n.env_json=="string"&&n.env_json!==""?X(n.env_json):null,i=typeof n.sink=="string"&&n.sink.trim()!==""?n.sink.trim():null,c=m(n.on_output,"on_output",["silent","on-failure","always","on-change"],i?.startsWith("node:")?"on-change":"on-failure"),R=m(n.overlap,"overlap",["skip","queue","replace"],"skip"),D=m(n.tier,"tier",["normal","urgent","critical"],"normal"),x=c==="always"||c==="on-change";if(x&&i===null)throw new t({error:"sink_required",message:`on_output "${c}" 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(!x&&i!==null)throw new t({error:"sink_unused",message:`on_output "${c}" 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 W=i!==null?M(i):"{}";i?.startsWith("spawn:")&&K(e.ceiling,"act");const g=typeof n.created_by=="string"&&n.created_by!==""?n.created_by:null;if(g!==null){const v=k(g);v!==null&&(C(v,"schedule"),i?.startsWith("spawn:")&&C(v,"act"))}const u=typeof n.anchor_node=="string"&&n.anchor_node!==""?n.anchor_node:null;if(u!==null&&k(u)===null)throw new t({error:"anchor_not_found",message:`anchor node ${u} 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 O=n.cancel_on_wake===!0;if(O&&u===null)throw new t({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 p=n.run_timeout_s??300;if(typeof p!="number"||!Number.isInteger(p)||p<=0)throw new t({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 w=typeof n.profile=="string"&&n.profile!==""?n.profile:null,$=m(n.scope,"scope",["profile","global"],w!==null?"profile":"global");if($==="profile"&&w===null)throw new t({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.'});const I=B();return G({cron_id:I,name:r,created_by:g,command:s,fire_at:a,recur:A,tz:typeof n.tz=="string"?n.tz:null,expires_at:J,anchor_node:u,cancel_on_wake:O,cwd:P,env_json:U,profile:w,scope:$,run_timeout_s:p,overlap:R,on_output:c,sink:W,tier:D}),{status:201,body:f(l(I),null)}}o(nn,"handleArm");function en(e){const n=b(e);return{status:200,body:(n===null?y({all:!0}):[...y({profile:n}),...y({global:!0})].sort((s,a)=>s.fire_at<a.fire_at?-1:s.fire_at>a.fire_at?1:0)).map(s=>f(s,S(s)))}}o(en,"handleList");function S(e){return j(e.cron_id)[0]??null}o(S,"lastRunOf");function _(e){const n=e.params.cronId,r=l(n);if(r===null)throw new d(404,"cron_not_found",`no cron ${n}`);if(!E(r,b(e)))throw new d(404,"cron_not_found",`no cron ${n} in this profile \u2014 it is scoped to another profile`);return r}o(_,"requireCron");function rn(e){const n=_(e),r=j(n.cron_id);return{status:200,body:{cron:f(n,r[0]??null),runs:r.map(N)}}}o(rn,"handleShow");function on(e){const n=_(e);q(n.cron_id,"paused");const r=l(n.cron_id);return{status:200,body:f(r,S(r))}}o(on,"handlePause");function tn(e){const n=_(e);q(n.cron_id,"active");const r=l(n.cron_id);return{status:200,body:f(r,S(r))}}o(tn,"handleResume");async function sn(e){const n=_(e);if(n.run_state==="running")throw new d(409,"cron_running",`cron ${n.cron_id} has a run in flight \u2014 wait for it to settle`);const r=await Y(n,{outOfBand:!0});if(r===null)throw new d(409,"cron_running",`cron ${n.cron_id} was claimed by a concurrent run \u2014 check \`cron show\` for its result`);return{status:200,body:N(r)}}o(sn,"handleRun");function an(){const e=new Date().toISOString();return{status:200,body:{unparked:Z(e),at:e}}}o(an,"handlePoke");function cn(e){const n=e.params.cronId,r=l(n);if(r!==null&&!E(r,b(e)))throw new d(404,"cron_not_found",`no cron ${n} in this profile \u2014 it is scoped to another profile`);const s=e.query.get("run_id"),a=s!==null&&F(n,s);return L(n,{preserveRunningProcess:a}),{status:204}}o(cn,"handleCancel");const yn=[{method:"POST",pattern:"/v1/crons",scope:"schedule",handler:nn},{method:"GET",pattern:"/v1/crons",handler:en},{method:"GET",pattern:"/v1/crons/:cronId",handler:rn},{method:"POST",pattern:"/v1/crons/:cronId/pause",scope:"schedule",handler:on},{method:"POST",pattern:"/v1/crons/:cronId/resume",scope:"schedule",handler:tn},{method:"POST",pattern:"/v1/crons/poke",scope:"schedule",handler:an},{method:"POST",pattern:"/v1/crons/:cronId/run",scope:"schedule",handler:sn},{method:"DELETE",pattern:"/v1/crons/:cronId",scope:"schedule",handler:cn}];export{yn as cronRoutes};
@@ -1,2 +1,2 @@
1
- import type { RouteTable } from '../router.js';
1
+ import { type RouteTable } from '../router.js';
2
2
  export declare const daemonRoutes: RouteTable;
@@ -1 +1 @@
1
- var i=Object.defineProperty;var s=(e,t)=>i(e,"name",{value:t,configurable:!0});import{toMigrateStateDTO as u}from"../map.js";import{boundDaemonControl as n}from"../../control.js";function c(){const e=n();if(e===null)throw{status:503,code:"daemon_control_unavailable",message:"this API server is not hosted by a live daemon and cannot hand over"};const{graceMs:t}=e.requestHandover();return{status:202,body:{accepted:!0,predecessor_pid:process.pid,predecessor_epoch:e.epoch,grace_ms:t}}}s(c,"handleRestart");async function m(e){if(e.body!==void 0)throw{status:400,code:"invalid_request",message:"admission request must not include a body"};const t=n();if(t===null)throw{status:503,code:"daemon_control_unavailable",message:"this API server is not hosted by a live daemon and cannot admit normal work"};return{status:200,body:await t.admitStartup()}}s(m,"handleAdmit");async function l(e){const t=n();if(t===null)throw{status:503,code:"daemon_control_unavailable",message:"this API server is not hosted by a live daemon and cannot migrate its corpus"};const r=e.body;if(r!==void 0&&(typeof r!="object"||r===null||Array.isArray(r)))throw{status:400,code:"invalid_request",message:"migration request body must be an object"};const o=r??{};if(o.dry_run!==void 0&&typeof o.dry_run!="boolean")throw{status:400,code:"invalid_request",message:"dry_run must be a boolean"};if(o.dirs!==void 0&&(!Array.isArray(o.dirs)||o.dirs.some(d=>typeof d!="string")))throw{status:400,code:"invalid_request",message:"dirs must be an array of strings"};const a=await t.repairMigrations({dryRun:o.dry_run===!0,dirs:o.dirs??[]});return{status:200,body:u(a.result,{resumed:a.resumed,resumeError:a.resumeError})}}s(l,"handleMigrate");const f=[{method:"POST",pattern:"/v1/daemon/restart",handler:s(e=>c(),"handler")},{method:"POST",pattern:"/v1/daemon/migrate",handler:l},{method:"POST",pattern:"/v1/daemon/admit",handler:m}];export{f as daemonRoutes};
1
+ var i=Object.defineProperty;var s=(e,t)=>i(e,"name",{value:t,configurable:!0});import{toMigrateStateDTO as u}from"../map.js";import{boundDaemonControl as a}from"../../control.js";import{ownerOnly as m}from"../router.js";function c(){const e=a();if(e===null)throw{status:503,code:"daemon_control_unavailable",message:"this API server is not hosted by a live daemon and cannot hand over"};const{graceMs:t}=e.requestHandover();return{status:202,body:{accepted:!0,predecessor_pid:process.pid,predecessor_epoch:e.epoch,grace_ms:t}}}s(c,"handleRestart");async function l(e){if(e.body!==void 0)throw{status:400,code:"invalid_request",message:"admission request must not include a body"};const t=a();if(t===null)throw{status:503,code:"daemon_control_unavailable",message:"this API server is not hosted by a live daemon and cannot admit normal work"};return{status:200,body:await t.admitStartup()}}s(l,"handleAdmit");async function y(e){const t=a();if(t===null)throw{status:503,code:"daemon_control_unavailable",message:"this API server is not hosted by a live daemon and cannot migrate its corpus"};const r=e.body;if(r!==void 0&&(typeof r!="object"||r===null||Array.isArray(r)))throw{status:400,code:"invalid_request",message:"migration request body must be an object"};const o=r??{};if(o.dry_run!==void 0&&typeof o.dry_run!="boolean")throw{status:400,code:"invalid_request",message:"dry_run must be a boolean"};if(o.dirs!==void 0&&(!Array.isArray(o.dirs)||o.dirs.some(d=>typeof d!="string")))throw{status:400,code:"invalid_request",message:"dirs must be an array of strings"};const n=await t.repairMigrations({dryRun:o.dry_run===!0,dirs:o.dirs??[]});return{status:200,body:u(n.result,{resumed:n.resumed,resumeError:n.resumeError})}}s(y,"handleMigrate");const v=m([{method:"POST",pattern:"/v1/daemon/restart",handler:s(e=>c(),"handler")},{method:"POST",pattern:"/v1/daemon/migrate",handler:y},{method:"POST",pattern:"/v1/daemon/admit",handler:l}]);export{v as daemonRoutes};
@@ -1 +1 @@
1
- var p=Object.defineProperty;var c=(e,t)=>p(e,"name",{value:t,configurable:!0});import{closeSync as y,fsyncSync as S,fstatSync as T,lstatSync as $,mkdirSync as A,openSync as g,readSync as q,readdirSync as _,realpathSync as I,renameSync as L,statSync as N,unlinkSync as k,writeSync as z}from"node:fs";import{randomUUID as B}from"node:crypto";import{basename as M,dirname as F,isAbsolute as O,join as b}from"node:path";import{ApiError as a}from"../../../api/index.js";import{notFound as P,usage as u}from"../../../core/errors.js";import{InputError as D}from"../../../core/io.js";const m=512*1024,w=1024*1024,R=1e3;function h(e,t){if(e===null||e==="")throw u(`a file ${t} requires a \`path\` ${t==="write"?"body field":"query param"}`);if(!O(e))throw u(`file ${t} path must be absolute`,{received:e});return e}c(h,"requireAbsolutePath");function E(e){if(e==null)return"utf8";if(e==="utf8"||e==="base64")return e;throw u("encoding must be `utf8` or `base64`",{received:e})}c(E,"parseEncoding");function l(e,t,n){if(e instanceof a||e instanceof D)throw e;const r=e.code;throw r==="ENOENT"?P(`no such file: ${t}`,{received:t}):r==="EACCES"||r==="EPERM"?new a(403,"forbidden",`permission denied ${n} ${t}`):new a(500,"internal",`cannot ${n} ${t}: ${e instanceof Error?e.message:String(e)}`)}c(l,"mapFilesystemError");function U(e,t){let n;try{n=g(e,"r")}catch(r){return l(r,e,"reading")}try{const r=T(n);if(r.isDirectory())throw u(`file peek path is a directory: ${e}`,{received:e});const f=Buffer.allocUnsafe(Math.min(r.size,m)+1),o=q(n,f,0,f.length,0),i=o>m,s=f.subarray(0,Math.min(o,m)).toString(t);return{path:e,content:s,truncated:i}}catch(r){return l(r,e,"reading")}finally{y(n)}}c(U,"readHead");function j(e){const t=h(e.query.get("path"),"peek");return{status:200,body:U(t,E(e.query.get("encoding")))}}c(j,"handlePeek");function C(e){return e.length%4===0&&/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(e)}c(C,"isBase64");function W(e){if(typeof e!="object"||e===null||Array.isArray(e))throw u("file write requires an object body");const t=e,n=h(typeof t.path=="string"?t.path:null,"write");if(typeof t.content!="string")throw u("file write requires a string `content` body field");const r=E(t.encoding);if(r==="base64"&&!C(t.content))throw u("base64 file content must be valid base64");return{path:n,content:t.content,encoding:r}}c(W,"parseWriteBody");function Z(e){try{if(!$(e).isSymbolicLink())return e}catch(t){return t.code!=="ENOENT"?l(t,e,"resolving"):e}try{return I(e)}catch(t){return l(t,e,"resolving")}}c(Z,"writeTarget");function v(e,t){if(t.byteLength>w)throw new a(413,"file_too_large",`file content exceeds the ${w} byte limit`);const n=Z(e),r=F(n);try{A(r,{recursive:!0})}catch(i){return l(i,e,"creating parent directory for")}const f=b(r,`.${M(e)}.${B()}.tmp`);let o;try{o=g(f,"wx",384);let i=0;for(;i<t.length;)i+=z(o,t,i,t.length-i);return S(o),y(o),o=void 0,L(f,n),{path:e,bytes_written:t.byteLength}}catch(i){return l(i,e,"writing")}finally{o!==void 0&&y(o);try{k(f)}catch(i){if(i.code!=="ENOENT")throw i}}}c(v,"writeAtomically");function G(e){const{path:t,content:n,encoding:r}=W(e.body);return{status:200,body:v(t,Buffer.from(n,r))}}c(G,"handleWrite");function X(e){if(e===null)return R;const t=Number(e);if(!Number.isInteger(t)||t<1)throw u("file list limit must be a positive integer",{received:e});return t}c(X,"parseLimit");function Y(e){const t=h(e.query.get("path"),"list"),n=X(e.query.get("limit"));let r;try{r=_(t,{withFileTypes:!0}).sort((s,d)=>s.name.localeCompare(d.name))}catch(s){return l(s,t,"listing")}const f=r.slice(0,n),o=[];try{for(const s of f){const d=N(b(t,s.name));o.push({name:s.name,type:d.isFile()?"file":d.isDirectory()?"dir":"other",size:d.size,modified:d.mtime.toISOString()})}}catch(s){return l(s,t,"listing")}return{status:200,body:{path:t,entries:o,truncated:r.length>n}}}c(Y,"handleList");const te=[{method:"GET",pattern:"/v1/files/peek",handler:j},{method:"POST",pattern:"/v1/files/write",handler:G},{method:"GET",pattern:"/v1/files/list",handler:Y}];export{te as fileRoutes};
1
+ var E=Object.defineProperty;var c=(e,t)=>E(e,"name",{value:t,configurable:!0});import{closeSync as y,fsyncSync as S,fstatSync as T,lstatSync as $,mkdirSync as A,openSync as g,readSync as q,readdirSync as _,realpathSync as I,renameSync as L,statSync as N,unlinkSync as k,writeSync as z}from"node:fs";import{randomUUID as B}from"node:crypto";import{basename as M,dirname as F,isAbsolute as O,join as b}from"node:path";import{ApiError as d}from"../../../api/index.js";import{notFound as P,usage as u}from"../../../core/errors.js";import{InputError as D}from"../../../core/io.js";const m=512*1024,w=1024*1024,R=1e3;function h(e,t){if(e===null||e==="")throw u(`a file ${t} requires a \`path\` ${t==="write"?"body field":"query param"}`);if(!O(e))throw u(`file ${t} path must be absolute`,{received:e});return e}c(h,"requireAbsolutePath");function p(e){if(e==null)return"utf8";if(e==="utf8"||e==="base64")return e;throw u("encoding must be `utf8` or `base64`",{received:e})}c(p,"parseEncoding");function l(e,t,n){if(e instanceof d||e instanceof D)throw e;const r=e.code;throw r==="ENOENT"?P(`no such file: ${t}`,{received:t}):r==="EACCES"||r==="EPERM"?new d(403,"forbidden",`permission denied ${n} ${t}`):new d(500,"internal",`cannot ${n} ${t}: ${e instanceof Error?e.message:String(e)}`)}c(l,"mapFilesystemError");function U(e,t){let n;try{n=g(e,"r")}catch(r){return l(r,e,"reading")}try{const r=T(n);if(r.isDirectory())throw u(`file peek path is a directory: ${e}`,{received:e});const f=Buffer.allocUnsafe(Math.min(r.size,m)+1),o=q(n,f,0,f.length,0),i=o>m,s=f.subarray(0,Math.min(o,m)).toString(t);return{path:e,content:s,truncated:i}}catch(r){return l(r,e,"reading")}finally{y(n)}}c(U,"readHead");function j(e){const t=h(e.query.get("path"),"peek");return{status:200,body:U(t,p(e.query.get("encoding")))}}c(j,"handlePeek");function C(e){return e.length%4===0&&/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(e)}c(C,"isBase64");function W(e){if(typeof e!="object"||e===null||Array.isArray(e))throw u("file write requires an object body");const t=e,n=h(typeof t.path=="string"?t.path:null,"write");if(typeof t.content!="string")throw u("file write requires a string `content` body field");const r=p(t.encoding);if(r==="base64"&&!C(t.content))throw u("base64 file content must be valid base64");return{path:n,content:t.content,encoding:r}}c(W,"parseWriteBody");function Z(e){try{if(!$(e).isSymbolicLink())return e}catch(t){return t.code!=="ENOENT"?l(t,e,"resolving"):e}try{return I(e)}catch(t){return l(t,e,"resolving")}}c(Z,"writeTarget");function v(e,t){if(t.byteLength>w)throw new d(413,"file_too_large",`file content exceeds the ${w} byte limit`);const n=Z(e),r=F(n);try{A(r,{recursive:!0})}catch(i){return l(i,e,"creating parent directory for")}const f=b(r,`.${M(e)}.${B()}.tmp`);let o;try{o=g(f,"wx",384);let i=0;for(;i<t.length;)i+=z(o,t,i,t.length-i);return S(o),y(o),o=void 0,L(f,n),{path:e,bytes_written:t.byteLength}}catch(i){return l(i,e,"writing")}finally{o!==void 0&&y(o);try{k(f)}catch(i){if(i.code!=="ENOENT")throw i}}}c(v,"writeAtomically");function G(e){const{path:t,content:n,encoding:r}=W(e.body);return{status:200,body:v(t,Buffer.from(n,r))}}c(G,"handleWrite");function X(e){if(e===null)return R;const t=Number(e);if(!Number.isInteger(t)||t<1)throw u("file list limit must be a positive integer",{received:e});return t}c(X,"parseLimit");function Y(e){const t=h(e.query.get("path"),"list"),n=X(e.query.get("limit"));let r;try{r=_(t,{withFileTypes:!0}).sort((s,a)=>s.name.localeCompare(a.name))}catch(s){return l(s,t,"listing")}const f=r.slice(0,n),o=[];try{for(const s of f){const a=N(b(t,s.name));o.push({name:s.name,type:a.isFile()?"file":a.isDirectory()?"dir":"other",size:a.size,modified:a.mtime.toISOString()})}}catch(s){return l(s,t,"listing")}return{status:200,body:{path:t,entries:o,truncated:r.length>n}}}c(Y,"handleList");const te=[{method:"GET",pattern:"/v1/files/peek",scope:"act",handler:j},{method:"POST",pattern:"/v1/files/write",scope:"act",handler:G},{method:"GET",pattern:"/v1/files/list",scope:"act",handler:Y}];export{te as fileRoutes};
@@ -1,2 +1,2 @@
1
- import type { RouteTable } from '../router.js';
1
+ import { type RouteTable } from '../router.js';
2
2
  export declare const focusRoutes: RouteTable;
@@ -1 +1 @@
1
- var r=Object.defineProperty;var s=(n,e)=>r(n,"name",{value:e,configurable:!0});import{focusByPane as i,focusOf as d,listFocuses as a,registerViewerFocus as c}from"../../../core/runtime/placement.js";import{closeFocusRow as f,setFocusPane as p}from"../../../core/canvas/focuses.js";import{usage as o}from"../../../core/errors.js";function u(n){return n===null?null:{focus_id:n.focus_id,pane:n.pane,session:n.session,node_id:n.node_id}}s(u,"toFocusDTO");function l(){return{status:200,body:a().map(e=>u(e))}}s(l,"handleListFocuses");function h(n){const e=n.query.get("node_id");if(e===null||e==="")throw o("focuses/by-node requires a node_id query param");return{status:200,body:u(d(e))}}s(h,"handleFocusByNode");function y(n){const e=n.query.get("pane");if(e===null||e==="")throw o("focuses/by-pane requires a pane query param");return{status:200,body:u(i(e))}}s(y,"handleFocusByPane");function m(n){if(typeof n!="object"||n===null)throw o("register-focus body must be a JSON object");const e=n;if(typeof e.node_id!="string"||e.node_id==="")throw o("node_id is required");if(typeof e.pane!="string"||e.pane==="")throw o("pane is required");return{node_id:e.node_id,pane:e.pane,session:typeof e.session=="string"?e.session:null,window:typeof e.window=="string"?e.window:null}}s(m,"parseRegisterBody");function _(n){const e=m(n.body),t=c(e.node_id,e.pane,e.session,e.window);return{status:200,body:u(t)}}s(_,"handleRegisterFocus");function b(n){if(typeof n!="object"||n===null)throw o("set-focus-pane body must be a JSON object");const e=n;return{pane:typeof e.pane=="string"?e.pane:null,session:typeof e.session=="string"?e.session:null}}s(b,"parseSetPaneBody");function w(n){const e=n.params.focus_id;if(e===void 0||e==="")throw o("focus_id is required");const t=b(n.body);return p(e,t.pane,t.session),{status:204}}s(w,"handleSetFocusPane");function g(n){const e=n.params.focus_id;if(e===void 0||e==="")throw o("focus_id is required");return f(e),{status:204}}s(g,"handleCloseFocus");const v=[{method:"GET",pattern:"/v1/focuses",handler:l},{method:"POST",pattern:"/v1/focuses",handler:_},{method:"GET",pattern:"/v1/focuses/by-node",handler:h},{method:"GET",pattern:"/v1/focuses/by-pane",handler:y},{method:"PATCH",pattern:"/v1/focuses/:focus_id",handler:w},{method:"DELETE",pattern:"/v1/focuses/:focus_id",handler:g}];export{v as focusRoutes};
1
+ var r=Object.defineProperty;var o=(n,e)=>r(n,"name",{value:e,configurable:!0});import{focusByPane as i,focusOf as d,listFocuses as a,registerViewerFocus as c}from"../../../core/runtime/placement.js";import{closeFocusRow as f,setFocusPane as p}from"../../../core/canvas/focuses.js";import{usage as s}from"../../../core/errors.js";import{ownerOnly as l}from"../router.js";function u(n){return n===null?null:{focus_id:n.focus_id,pane:n.pane,session:n.session,node_id:n.node_id}}o(u,"toFocusDTO");function y(){return{status:200,body:a().map(e=>u(e))}}o(y,"handleListFocuses");function h(n){const e=n.query.get("node_id");if(e===null||e==="")throw s("focuses/by-node requires a node_id query param");return{status:200,body:u(d(e))}}o(h,"handleFocusByNode");function m(n){const e=n.query.get("pane");if(e===null||e==="")throw s("focuses/by-pane requires a pane query param");return{status:200,body:u(i(e))}}o(m,"handleFocusByPane");function _(n){if(typeof n!="object"||n===null)throw s("register-focus body must be a JSON object");const e=n;if(typeof e.node_id!="string"||e.node_id==="")throw s("node_id is required");if(typeof e.pane!="string"||e.pane==="")throw s("pane is required");return{node_id:e.node_id,pane:e.pane,session:typeof e.session=="string"?e.session:null,window:typeof e.window=="string"?e.window:null}}o(_,"parseRegisterBody");function b(n){const e=_(n.body),t=c(e.node_id,e.pane,e.session,e.window);return{status:200,body:u(t)}}o(b,"handleRegisterFocus");function w(n){if(typeof n!="object"||n===null)throw s("set-focus-pane body must be a JSON object");const e=n;return{pane:typeof e.pane=="string"?e.pane:null,session:typeof e.session=="string"?e.session:null}}o(w,"parseSetPaneBody");function g(n){const e=n.params.focus_id;if(e===void 0||e==="")throw s("focus_id is required");const t=w(n.body);return p(e,t.pane,t.session),{status:204}}o(g,"handleSetFocusPane");function q(n){const e=n.params.focus_id;if(e===void 0||e==="")throw s("focus_id is required");return f(e),{status:204}}o(q,"handleCloseFocus");const O=l([{method:"GET",pattern:"/v1/focuses",handler:y},{method:"POST",pattern:"/v1/focuses",handler:b},{method:"GET",pattern:"/v1/focuses/by-node",handler:h},{method:"GET",pattern:"/v1/focuses/by-pane",handler:m},{method:"PATCH",pattern:"/v1/focuses/:focus_id",handler:g},{method:"DELETE",pattern:"/v1/focuses/:focus_id",handler:q}]);export{O as focusRoutes};
@@ -1 +1 @@
1
- var R=Object.defineProperty;var o=(e,t)=>R(e,"name",{value:t,configurable:!0});import{statSync as j}from"node:fs";import{isAbsolute as E}from"node:path";import{ApiError as s}from"../../../api/index.js";import{readExternalActionDelivery as N}from"../../../core/canvas/deliveries.js";import{isSafeNodeId as P}from"../../../core/canvas/paths.js";import{getNode as x}from"../../../core/canvas/canvas.js";import{assertScope as T}from"../../../core/scopes.js";import{resolvePageComponents as C}from"../../../core/config.js";import{resolveHumanAction as I}from"../../../core/human-actions.js";import{HUMAN_ACTION_NAME_PATTERN as $}from"../../../core/human/action-binding.js";import{createPageRequest as D,getRequest as J}from"../../../core/human/requests.js";import{preparePageSource as F}from"../../../core/human/page-authoring.js";import{publishPage as M,validatePageTicketResponses as H}from"../../../core/human/tickets.js";import{cancelHumanTicket as L,resolvePageTicket as U}from"../../human/finish.js";import{inboxPageProjection as B}from"./inbox-page.js";const G=1e3,_=200,p={placement:"inline",inbox:!0,reply:!1},b=["sessionName","askedBy","emittedAt","profileName","nodeId"];function c(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(c,"isPlainObject");function l(e,t,n){for(const r of Object.keys(e))if(!t.includes(r))throw new s(400,"invalid_request",`unexpected field in ${n}: ${r}`)}o(l,"requireNoExtraKeys");function i(e){return new s(400,"invalid_request",e)}o(i,"invalid");function g(e){if(!c(e))throw i("`page` must be an object");if(l(e,["dialect","source"],"`page`"),e.dialect!=="jsx"&&e.dialect!=="html")throw i('`page.dialect` must be "jsx" or "html"');if(typeof e.source!="string"||e.source.trim()==="")throw i("`page.source` must be the authored page text");return{dialect:e.dialect,source:e.source}}o(g,"validatePage");function q(e,t){const n=e??t;if(n!=="inline"&&n!=="panel")throw i('`delivery.placement` must be "inline" or "panel"');return n}o(q,"validatePlacement");function K(e,t){if(e===void 0)return p;if(!c(e))throw i("`delivery` must be an object");l(e,["placement","inbox","reply"],"`delivery`");const n=e.inbox??p.inbox,r=e.reply??p.reply;if(typeof n!="boolean")throw i("`delivery.inbox` must be boolean");if(typeof r!="boolean")throw i("`delivery.reply` must be boolean");if(r&&t===null)throw i("`delivery.reply` requires `requester_node_id`");return{placement:q(e.placement,p.placement),inbox:n,reply:r}}o(K,"validateCreateDelivery");function X(e,t){if(e===void 0)return t;if(!c(e))throw i("`delivery` must be an object");return l(e,["placement"],"`delivery`"),{...t,placement:q(e.placement,t.placement)}}o(X,"validateReplaceDelivery");function z(e){if(e===void 0)return;if(!c(e))throw i("`source` must be an object");l(e,b,"`source`");const t={};for(const n of b){const r=e[n];if(r!==void 0){if(typeof r!="string"||r==="")throw i(`\`source.${n}\` must be a nonempty string`);t[n]=r}}return t}o(z,"validateSource");function V(e){if(typeof e!="string"||e==="")throw i("`creator_cwd` is required");if(!E(e))throw i("`creator_cwd` must be an absolute path");try{if(!j(e).isDirectory())throw i(`\`creator_cwd\` is not a directory: ${e}`)}catch(t){throw t instanceof s?t:i(`\`creator_cwd\` does not exist: ${e}`)}return e}o(V,"validateCreatorCwd");function Y(e){if(e!==void 0){if(!c(e))throw i("`action` must be an object");if(l(e,["name","payload"],"`action`"),typeof e.name!="string"||!$.test(e.name))throw i("`action.name` must be a declared action name");return{name:e.name,payload:e.payload??null}}}o(Y,"validateActionSelection");function Q(e){if(e==null)return null;if(typeof e!="string"||!P(e))throw i("`requester_node_id` must be a safe node id or null");return e}o(Q,"validateRequesterNodeId");function W(e){if(!c(e))throw i("request body is required");l(e,["page","delivery","source","requester_node_id","creator_cwd","action"],"the request body");const t=z(e.source),n=Q(e.requester_node_id),r=Y(e.action);return{page:g(e.page),delivery:K(e.delivery,n),...t===void 0?{}:{source:t},requesterNodeId:n,creatorCwd:V(e.creator_cwd),...r===void 0?{}:{action:r}}}o(W,"validateCreateRequest");function Z(e,t){if(!c(e))throw i("request body is required");return l(e,["page","delivery"],"the request body"),{page:g(e.page),delivery:X(e.delivery,t)}}o(Z,"validateReplaceRequest");function y(e,t,n){if(e!==void 0){if(typeof e!="string"||e.trim()===""||e.length>n)throw i(`\`${t}\` must be nonempty after trim and at most ${n} characters`);return e}}o(y,"optionalBoundedString");function ee(e){if(!c(e))throw i("request body is required");if(l(e,["responses","actor"],"the request body"),!c(e.responses))throw i("`responses` must be an object");const t=y(e.actor,"actor",_);return{responses:e.responses,...t===void 0?{}:{actor:t}}}o(ee,"validateRespondRequest");function te(e){if(e===void 0)return{};if(!c(e))throw i("request body must be an object");l(e,["reason","actor"],"the request body");const t=y(e.reason,"reason",G),n=y(e.actor,"actor",_);return{...t===void 0?{}:{reason:t},...n===void 0?{}:{actor:n}}}o(te,"validateSettleRequest");function m(e){const t=e.params.request_id;if(typeof t!="string"||t==="")throw i("request id is required");return t}o(m,"requestId");function f(e){const t=J(e);if(t===null||t.kind!=="page")throw new s(404,"not_found","no request with that id");return t}o(f,"requirePageRequest");function v(e){try{const t=JSON.parse(e.specification_json);if(!c(t))throw new Error("not an object");return t}catch{throw new s(500,"internal","the request specification could not be read")}}o(v,"manifest");function ne(e){if(e.result_json===null)return null;try{return JSON.parse(e.result_json)}catch{throw new s(500,"internal","the request result could not be read")}}o(ne,"terminalResult");function re(e){if(e.action_json===null)return null;try{const t=JSON.parse(e.action_json);if(t.schema!=="crtr.human-action-binding/v1"||typeof t.name!="string")throw new Error("invalid action");return t}catch{throw new s(500,"internal","the request action could not be read")}}o(re,"frozenAction");function oe(e){return e.state!=="settled"?"pending":e.outcome==="answered"?"answered":e.outcome==="dismissed"?"dismissed":"canceled"}o(oe,"requestState");function ie(e){if(e.action_delivery_id===null)return{state:"none",attempt:0};const t=N(`human-action:${e.inbox_ticket_id}`);if(t===null)return{state:"none",attempt:0};const n=t.state==="acknowledged"?"accepted":t.state==="permanent_failed"?"permanent_failed":t.state==="handed_off"?"running":"pending",r={state:n,attempt:t.attempts};return n==="pending"&&t.nextAttemptAt!==null&&(r.next_attempt_at=new Date(t.nextAttemptAt).toISOString()),t.acknowledgedAt!==null&&(r.accepted_at=new Date(t.acknowledgedAt).toISOString()),t.failedAt!==null&&(r.permanent_failed_at=new Date(t.failedAt).toISOString()),t.lastFailure!==null&&(r.last_failure=t.lastFailure),r}o(ie,"deliveryDetail");function h(e){const t=v(e),n=ne(e),r=oe(e),a={request_id:e.request_id,inbox_ticket_id:e.inbox_ticket_id,request_dir:e.request_dir,kind:e.kind,state:r,title:e.title,source:t.source??{},emitted_at:t.source?.emittedAt??e.created_at};e.subtitle!==null&&(a.subtitle=e.subtitle),e.kind==="page"&&(a.page=B(e)),n!==null&&(a.settled_at=e.settled_at??e.updated_at,n.kind==="page"&&r==="answered"&&(a.responses=n.responses),n.kind==="canceled"&&n.reason!==void 0&&(a.reason=n.reason),n.kind==="page"&&n.actor!==void 0&&(a.actor=n.actor),n.kind==="canceled"&&n.actor!==void 0&&(a.actor=n.actor));const u=re(e);return u!==null&&(a.action={name:u.name,payload:u.payload},a.delivery=ie(e)),a}o(h,"requestToDTO");function w(e,t,n,r){try{return F({dialect:e,document:t,source:n,delivery:r,productKinds:C()})}catch(a){throw i(a instanceof Error?a.message:"the page could not be prepared")}}o(w,"prepareOrReject");function ae(e){const t=W(e.body),n=t.requesterNodeId??t.source?.nodeId;if(n!=null){const d=x(n);d!==null&&T(d,"ask")}let r;if(t.action!==void 0){const d=I(t.action.name,t.creatorCwd);if("kind"in d){const O=d.kind==="unknown_action"?`no action named ${d.name} is declared from ${t.creatorCwd}`:`${d.name} is declared in ${d.configOrigin} but unusable: ${d.reason}`;throw new s(400,d.kind,O)}r=JSON.stringify({schema:"crtr.human-action-binding/v1",name:t.action.name,payload:t.action.payload,creatorCwd:t.creatorCwd,configOrigin:d.configOrigin,argv:d.argv,cwd:d.cwd})}const a=w(t.page.dialect,t.page.source,t.source,t.delivery),u=D({prepared:a,requester_node_id:t.requesterNodeId,...r===void 0?{}:{action_json:r}});return{status:201,body:{request_id:u.request_id,request_dir:u.request_dir,state:"pending",...t.action===void 0?{}:{action:{name:t.action.name}},delivery_state:"none"}}}o(ae,"handleCreate");function se(e){return{status:200,body:h(f(m(e)))}}o(se,"handleGet");function de(e){const t=f(m(e));if(t.state==="settled")throw new s(409,"already_settled","the request already has a terminal result");const n=v(t),r=Z(e.body,n.delivery),a=w(r.page.dialect,r.page.source,n.source,r.delivery);try{M(t.request_dir,a)}catch(u){throw u instanceof Error&&u.message===`page request is not open: ${t.request_id}`?new s(409,"already_settled","the request already has a terminal result"):u}return{status:200,body:h(f(t.request_id))}}o(de,"handleReplace");function S(e){return e instanceof s?e:e instanceof Error&&e.message.includes("unknown page request")?new s(404,"not_found","no request with that id"):e instanceof Error&&e.message==="page_has_no_response_lifecycle"?new s(409,"not_settleable","this request carries no response lifecycle"):new s(500,"internal","the request could not be settled")}o(S,"settlementError");function A(e){if(e.state==="settled")throw new s(409,"already_settled","the request already has a terminal result");if(!e.settleable)throw new s(409,"not_settleable","this request carries no response lifecycle")}o(A,"requireSettleable");async function ce(e){const t=f(m(e)),n=ee(e.body);A(t);try{H(t.request_dir,n.responses)}catch(r){throw i(r instanceof Error?r.message:"the response map is invalid")}try{await U(t.request_id,n.responses,n.actor===void 0?{}:{actor:n.actor})}catch(r){throw S(r)}return{status:200,body:h(f(t.request_id))}}o(ce,"handleRespond");async function k(e,t){const n=f(m(e)),r=te(e.body);A(n);try{await L(n.request_id,{...r,disposition:t})}catch(a){throw S(a)}return{status:200,body:h(f(n.request_id))}}o(k,"settle");const Oe=[{method:"POST",pattern:"/v1/human/requests",handler:ae},{method:"GET",pattern:"/v1/human/requests/:request_id",handler:se},{method:"POST",pattern:"/v1/human/requests/:request_id/replace",handler:de},{method:"POST",pattern:"/v1/human/requests/:request_id/respond",handler:ce},{method:"POST",pattern:"/v1/human/requests/:request_id/dismiss",handler:o(e=>k(e,"dismissed"),"handler")},{method:"POST",pattern:"/v1/human/requests/:request_id/cancel",handler:o(e=>k(e,"canceled"),"handler")}];export{Oe as humanRequestRoutes};
1
+ var R=Object.defineProperty;var o=(e,t)=>R(e,"name",{value:t,configurable:!0});import{statSync as j}from"node:fs";import{isAbsolute as E}from"node:path";import{ApiError as s}from"../../../api/index.js";import{readExternalActionDelivery as N}from"../../../core/canvas/deliveries.js";import{isSafeNodeId as P}from"../../../core/canvas/paths.js";import{getNode as x}from"../../../core/canvas/canvas.js";import{assertScope as T}from"../../../core/scopes.js";import{resolvePageComponents as C}from"../../../core/config.js";import{resolveHumanAction as I}from"../../../core/human-actions.js";import{HUMAN_ACTION_NAME_PATTERN as $}from"../../../core/human/action-binding.js";import{createPageRequest as D,getRequest as J}from"../../../core/human/requests.js";import{preparePageSource as F}from"../../../core/human/page-authoring.js";import{publishPage as M,validatePageTicketResponses as H}from"../../../core/human/tickets.js";import{cancelHumanTicket as L,resolvePageTicket as U}from"../../human/finish.js";import{inboxPageProjection as B}from"./inbox-page.js";const G=1e3,_=200,p={placement:"inline",inbox:!0,reply:!1},b=["sessionName","askedBy","emittedAt","profileName","nodeId"];function c(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(c,"isPlainObject");function l(e,t,n){for(const r of Object.keys(e))if(!t.includes(r))throw new s(400,"invalid_request",`unexpected field in ${n}: ${r}`)}o(l,"requireNoExtraKeys");function i(e){return new s(400,"invalid_request",e)}o(i,"invalid");function g(e){if(!c(e))throw i("`page` must be an object");if(l(e,["dialect","source"],"`page`"),e.dialect!=="jsx"&&e.dialect!=="html")throw i('`page.dialect` must be "jsx" or "html"');if(typeof e.source!="string"||e.source.trim()==="")throw i("`page.source` must be the authored page text");return{dialect:e.dialect,source:e.source}}o(g,"validatePage");function q(e,t){const n=e??t;if(n!=="inline"&&n!=="panel")throw i('`delivery.placement` must be "inline" or "panel"');return n}o(q,"validatePlacement");function K(e,t){if(e===void 0)return p;if(!c(e))throw i("`delivery` must be an object");l(e,["placement","inbox","reply"],"`delivery`");const n=e.inbox??p.inbox,r=e.reply??p.reply;if(typeof n!="boolean")throw i("`delivery.inbox` must be boolean");if(typeof r!="boolean")throw i("`delivery.reply` must be boolean");if(r&&t===null)throw i("`delivery.reply` requires `requester_node_id`");return{placement:q(e.placement,p.placement),inbox:n,reply:r}}o(K,"validateCreateDelivery");function X(e,t){if(e===void 0)return t;if(!c(e))throw i("`delivery` must be an object");return l(e,["placement"],"`delivery`"),{...t,placement:q(e.placement,t.placement)}}o(X,"validateReplaceDelivery");function z(e){if(e===void 0)return;if(!c(e))throw i("`source` must be an object");l(e,b,"`source`");const t={};for(const n of b){const r=e[n];if(r!==void 0){if(typeof r!="string"||r==="")throw i(`\`source.${n}\` must be a nonempty string`);t[n]=r}}return t}o(z,"validateSource");function V(e){if(typeof e!="string"||e==="")throw i("`creator_cwd` is required");if(!E(e))throw i("`creator_cwd` must be an absolute path");try{if(!j(e).isDirectory())throw i(`\`creator_cwd\` is not a directory: ${e}`)}catch(t){throw t instanceof s?t:i(`\`creator_cwd\` does not exist: ${e}`)}return e}o(V,"validateCreatorCwd");function Y(e){if(e!==void 0){if(!c(e))throw i("`action` must be an object");if(l(e,["name","payload"],"`action`"),typeof e.name!="string"||!$.test(e.name))throw i("`action.name` must be a declared action name");return{name:e.name,payload:e.payload??null}}}o(Y,"validateActionSelection");function Q(e){if(e==null)return null;if(typeof e!="string"||!P(e))throw i("`requester_node_id` must be a safe node id or null");return e}o(Q,"validateRequesterNodeId");function W(e){if(!c(e))throw i("request body is required");l(e,["page","delivery","source","requester_node_id","creator_cwd","action"],"the request body");const t=z(e.source),n=Q(e.requester_node_id),r=Y(e.action);return{page:g(e.page),delivery:K(e.delivery,n),...t===void 0?{}:{source:t},requesterNodeId:n,creatorCwd:V(e.creator_cwd),...r===void 0?{}:{action:r}}}o(W,"validateCreateRequest");function Z(e,t){if(!c(e))throw i("request body is required");return l(e,["page","delivery"],"the request body"),{page:g(e.page),delivery:X(e.delivery,t)}}o(Z,"validateReplaceRequest");function y(e,t,n){if(e!==void 0){if(typeof e!="string"||e.trim()===""||e.length>n)throw i(`\`${t}\` must be nonempty after trim and at most ${n} characters`);return e}}o(y,"optionalBoundedString");function ee(e){if(!c(e))throw i("request body is required");if(l(e,["responses","actor"],"the request body"),!c(e.responses))throw i("`responses` must be an object");const t=y(e.actor,"actor",_);return{responses:e.responses,...t===void 0?{}:{actor:t}}}o(ee,"validateRespondRequest");function te(e){if(e===void 0)return{};if(!c(e))throw i("request body must be an object");l(e,["reason","actor"],"the request body");const t=y(e.reason,"reason",G),n=y(e.actor,"actor",_);return{...t===void 0?{}:{reason:t},...n===void 0?{}:{actor:n}}}o(te,"validateSettleRequest");function m(e){const t=e.params.request_id;if(typeof t!="string"||t==="")throw i("request id is required");return t}o(m,"requestId");function f(e){const t=J(e);if(t===null||t.kind!=="page")throw new s(404,"not_found","no request with that id");return t}o(f,"requirePageRequest");function v(e){try{const t=JSON.parse(e.specification_json);if(!c(t))throw new Error("not an object");return t}catch{throw new s(500,"internal","the request specification could not be read")}}o(v,"manifest");function ne(e){if(e.result_json===null)return null;try{return JSON.parse(e.result_json)}catch{throw new s(500,"internal","the request result could not be read")}}o(ne,"terminalResult");function re(e){if(e.action_json===null)return null;try{const t=JSON.parse(e.action_json);if(t.schema!=="crtr.human-action-binding/v1"||typeof t.name!="string")throw new Error("invalid action");return t}catch{throw new s(500,"internal","the request action could not be read")}}o(re,"frozenAction");function oe(e){return e.state!=="settled"?"pending":e.outcome==="answered"?"answered":e.outcome==="dismissed"?"dismissed":"canceled"}o(oe,"requestState");function ie(e){if(e.action_delivery_id===null)return{state:"none",attempt:0};const t=N(`human-action:${e.inbox_ticket_id}`);if(t===null)return{state:"none",attempt:0};const n=t.state==="acknowledged"?"accepted":t.state==="permanent_failed"?"permanent_failed":t.state==="handed_off"?"running":"pending",r={state:n,attempt:t.attempts};return n==="pending"&&t.nextAttemptAt!==null&&(r.next_attempt_at=new Date(t.nextAttemptAt).toISOString()),t.acknowledgedAt!==null&&(r.accepted_at=new Date(t.acknowledgedAt).toISOString()),t.failedAt!==null&&(r.permanent_failed_at=new Date(t.failedAt).toISOString()),t.lastFailure!==null&&(r.last_failure=t.lastFailure),r}o(ie,"deliveryDetail");function h(e){const t=v(e),n=ne(e),r=oe(e),a={request_id:e.request_id,inbox_ticket_id:e.inbox_ticket_id,request_dir:e.request_dir,kind:e.kind,state:r,title:e.title,source:t.source??{},emitted_at:t.source?.emittedAt??e.created_at};e.subtitle!==null&&(a.subtitle=e.subtitle),e.kind==="page"&&(a.page=B(e)),n!==null&&(a.settled_at=e.settled_at??e.updated_at,n.kind==="page"&&r==="answered"&&(a.responses=n.responses),n.kind==="canceled"&&n.reason!==void 0&&(a.reason=n.reason),n.kind==="page"&&n.actor!==void 0&&(a.actor=n.actor),n.kind==="canceled"&&n.actor!==void 0&&(a.actor=n.actor));const u=re(e);return u!==null&&(a.action={name:u.name,payload:u.payload},a.delivery=ie(e)),a}o(h,"requestToDTO");function w(e,t,n,r){try{return F({dialect:e,document:t,source:n,delivery:r,productKinds:C()})}catch(a){throw i(a instanceof Error?a.message:"the page could not be prepared")}}o(w,"prepareOrReject");function ae(e){const t=W(e.body),n=t.requesterNodeId??t.source?.nodeId;if(n!=null){const d=x(n);d!==null&&T(d,"ask")}let r;if(t.action!==void 0){const d=I(t.action.name,t.creatorCwd);if("kind"in d){const O=d.kind==="unknown_action"?`no action named ${d.name} is declared from ${t.creatorCwd}`:`${d.name} is declared in ${d.configOrigin} but unusable: ${d.reason}`;throw new s(400,d.kind,O)}r=JSON.stringify({schema:"crtr.human-action-binding/v1",name:t.action.name,payload:t.action.payload,creatorCwd:t.creatorCwd,configOrigin:d.configOrigin,argv:d.argv,cwd:d.cwd})}const a=w(t.page.dialect,t.page.source,t.source,t.delivery),u=D({prepared:a,requester_node_id:t.requesterNodeId,...r===void 0?{}:{action_json:r}});return{status:201,body:{request_id:u.request_id,request_dir:u.request_dir,state:"pending",...t.action===void 0?{}:{action:{name:t.action.name}},delivery_state:"none"}}}o(ae,"handleCreate");function se(e){return{status:200,body:h(f(m(e)))}}o(se,"handleGet");function de(e){const t=f(m(e));if(t.state==="settled")throw new s(409,"already_settled","the request already has a terminal result");const n=v(t),r=Z(e.body,n.delivery),a=w(r.page.dialect,r.page.source,n.source,r.delivery);try{M(t.request_dir,a)}catch(u){throw u instanceof Error&&u.message===`page request is not open: ${t.request_id}`?new s(409,"already_settled","the request already has a terminal result"):u}return{status:200,body:h(f(t.request_id))}}o(de,"handleReplace");function S(e){return e instanceof s?e:e instanceof Error&&e.message.includes("unknown page request")?new s(404,"not_found","no request with that id"):e instanceof Error&&e.message==="page_has_no_response_lifecycle"?new s(409,"not_settleable","this request carries no response lifecycle"):new s(500,"internal","the request could not be settled")}o(S,"settlementError");function k(e){if(e.state==="settled")throw new s(409,"already_settled","the request already has a terminal result");if(!e.settleable)throw new s(409,"not_settleable","this request carries no response lifecycle")}o(k,"requireSettleable");async function ce(e){const t=f(m(e)),n=ee(e.body);k(t);try{H(t.request_dir,n.responses)}catch(r){throw i(r instanceof Error?r.message:"the response map is invalid")}try{await U(t.request_id,n.responses,n.actor===void 0?{}:{actor:n.actor})}catch(r){throw S(r)}return{status:200,body:h(f(t.request_id))}}o(ce,"handleRespond");async function A(e,t){const n=f(m(e)),r=te(e.body);k(n);try{await L(n.request_id,{...r,disposition:t})}catch(a){throw S(a)}return{status:200,body:h(f(n.request_id))}}o(A,"settle");const Oe=[{method:"POST",pattern:"/v1/human/requests",scope:"ask",handler:ae},{method:"GET",pattern:"/v1/human/requests/:request_id",handler:se},{method:"POST",pattern:"/v1/human/requests/:request_id/replace",handler:de},{method:"POST",pattern:"/v1/human/requests/:request_id/respond",handler:ce},{method:"POST",pattern:"/v1/human/requests/:request_id/dismiss",handler:o(e=>A(e,"dismissed"),"handler")},{method:"POST",pattern:"/v1/human/requests/:request_id/cancel",handler:o(e=>A(e,"canceled"),"handler")}];export{Oe as humanRequestRoutes};
@@ -1 +1 @@
1
- var Y=Object.defineProperty;var a=(e,n)=>Y(e,"name",{value:n,configurable:!0});import{getNode as N}from"../../../core/canvas/canvas.js";import{ApiError as l}from"../../../api/errors.js";import{assertScope as J}from"../../../core/scopes.js";import{CrtrError as X}from"../../../core/errors.js";import{memoryDir as x}from"../../../core/runtime/memory.js";import{NEUTRAL_PROJECT_MEMORY as K,projectScopeRoots as L,scopeMemoryDir as Q}from"../../../core/scope.js";import{profileMemoryDir as F}from"../../../core/profiles/manifest.js";import{openProjectMemoryStore as V}from"../../../core/memory-resolver.js";import{candidateLocation as ee,createDoc as te,deleteDoc as ne,listDocs as oe,moveDoc as re,readDoc as ie,readHistory as se,searchDocs as de,updateDoc as ae}from"../../../core/memory/service.js";import{MEMORY_SCOPES as z,isMemoryDocName as S}from"../../../api/dto/memory.js";import{invalidRequest as w,isRecord as R,objectBody as j,optionalString as y,requiredString as b}from"./validate.js";const _="memory:read",I="memory:write",E=100,G=100;function q(e){const n=e.params.name;if(n===void 0||!S(n))throw new l(400,"invalid_memory_doc_name","memory document name must be slash-joined [A-Za-z0-9_-] segments");return n}a(q,"requireName");function k(e){return Object.fromEntries(e.query.entries())}a(k,"queryObject");function $(e,n){return{scope:e,storeRoot:n,namespace:"",mountStatus:"ready",projectMemory:K}}a($,"nativeStore");function p(e,n){const t=[];for(const m of Object.keys(e))n.includes(m)||t.push({field:m,problem:"is not allowed",received:e[m]});const r=y(e,"node",t),i=y(e,"cwd",t),o=y(e,"profile",t),s=y(e,"store",t);s!==void 0&&!z.includes(s)&&t.push({field:"store",problem:`must be one of ${z.join(", ")}`,received:s}),r!==void 0&&(i!==void 0||o!==void 0)&&t.push({field:"node",problem:"derives cwd and profile and cannot be combined with either"}),t.length>0&&w("memory scope",t);let d,u;if(r!==void 0){const m=N(r);if(m===null)throw new l(404,"node_not_found",`unknown node: ${r}`);d={cwd:m.cwd,profileId:m.profile_id??null,nodeId:m.node_id},u=m.node_id}else d={cwd:i??"/",profileId:o??null,nodeId:null};const c=s;if(c==="node"&&u===void 0)throw new l(400,"invalid_request","store node requires node");if(c==="profile"&&d.profileId===null)throw new l(400,"invalid_request","store profile requires profile or node with a profile");return{target:d,...c===void 0?{}:{scope:c},...u===void 0?{}:{nodeId:u}}}a(p,"resolveScope");function h(e,n){if(e.nodeId===void 0)return;const t=N(e.nodeId);if(t===null)throw new l(404,"node_not_found",`unknown node: ${e.nodeId}`);J(t,n)}a(h,"requireScope");function f(e,n){const t=e.scope;if(!n)return{...t===void 0?{}:{scope:t}};const r=t??(L(e.target.cwd,e.target.profileId).length>0?"project":"user");if(r==="builtin")throw new l(400,"invalid_request","builtin memory is read-only");if(r==="node")return{scope:r,store:$("node",x(e.target.nodeId)),memoryDir:x(e.target.nodeId)};if(r==="profile")return{scope:r,store:$("profile",F(e.target.profileId)),memoryDir:F(e.target.profileId)};if(r==="project"){const o=L(e.target.cwd,e.target.profileId)[0];if(o===void 0)throw new l(400,"invalid_request","store project requires a project memory store in cwd or profile");const s=V(o.slice(0,-8).replace(/\/$/,""));return{scope:r,store:s,memoryDir:s.storeRoot}}const i=Q("user");if(i===null)throw new Error("user memory directory unavailable");return{scope:"user",store:$("user",i),memoryDir:i}}a(f,"selection");function Z(e,n){return e.length>1?e.map(t=>ee(t,n)):void 0}a(Z,"candidates");function B(e){return{name:e.name,short_form:e.shortForm,kind:e.kind,scope:e.scope,extensions:e.extensions,path:e.path,store_root:e.storeRoot,physical_relative_path:e.physicalRelativePath,...Z(e.candidates,e.candidates[0])===void 0?{}:{candidates:Z(e.candidates,e.candidates[0])}}}a(B,"summary");function H(e){try{const n=ie(e);if(n.kind==="document")return n}catch(n){if(!(n instanceof X)||n.code!=="not_found")throw n}throw new l(404,"memory_document_not_found",`memory document not found: ${e.name}`)}a(H,"requestedDocument");function A(e,n,t=f(n,!1),r=!1){const i=H({target:n.target,...t,name:e,frontmatter:r,interpolateNodePaths:!1}),o=i.doc;return{...B({name:o.name,kind:String(o.frontmatter?.kind??""),scope:o.scope,path:o.path,storeRoot:o.root,physicalRelativePath:o.physicalRelativePath,shortForm:String(o.frontmatter?.["short-form"]??""),slash:o.frontmatter?.slash===!0,extensions:o.frontmatter?.extensions??{},candidates:i.candidates}),body:i.content,frontmatter:o.frontmatter,representation:o.representation,links:[...i.links]}}a(A,"document");function T(e,n,t){if(e===void 0)return t;const r=typeof e=="number"?e:Number(e);if(!Number.isInteger(r)||r<1||r>G)throw new l(400,"invalid_request",`${n} must be an integer from 1 through ${G}`);return r}a(T,"number");function U(e,n){const t=typeof e=="number"?e:Number(e);if(!Number.isFinite(t)||t<1)throw new l(400,"invalid_request",`${n} must be a finite number of at least 1`);return t}a(U,"positiveNumber");function D(e,n){const t=e[n];if(t!==void 0){if(t===!0||t==="true")return!0;if(t===!1||t==="false")return!1;throw new l(400,"invalid_request",`${n} must be a boolean`)}}a(D,"optionalBoolean");function W(e,n,t=[]){if(e!==void 0&&!R(e))throw new l(400,"invalid_request","frontmatter must be an object");const r=e===void 0?{}:e;for(const s of t)if(s in r)throw new l(400,"invalid_request",`frontmatter.${s} cannot be set directly`);const i={},o={"short-form":"shortForm","when-and-why-to-read":"whenAndWhyToRead","lint-ignore":"lintIgnore",rationale:"docRationale",kind:"kind",unlisted:"unlisted",surfaces:"surface",gate:"gate",slash:"slash"};for(const[s,d]of Object.entries(r)){const u=o[s];if(u===void 0)throw new l(400,"invalid_request",`frontmatter.${s} is not writable through this route`);if(s==="unlisted"||s==="slash"){if(d!==!0)throw new l(400,"invalid_request",`frontmatter.${s} must be true; remove it with unset`)}else if(s==="surfaces"){if(!Array.isArray(d)||!d.every(c=>typeof c=="string"))throw new l(400,"invalid_request","frontmatter.surfaces must be a string array")}else if(s==="lint-ignore"){if(!Array.isArray(d)||!d.every(c=>typeof c=="string"))throw new l(400,"invalid_request","frontmatter.lint-ignore must be a string array")}else if(typeof d!="string"||d.trim()==="")throw new l(400,"invalid_request",`frontmatter.${s} must be a non-empty string`);i[u]=d}if(n!==void 0){if(!R(n))throw new l(400,"invalid_request","extensions must be an object");const s=[];for(const[d,u]of Object.entries(n)){if(!R(u))throw new l(400,"invalid_request",`extensions.${d} must be an object`);for(const[c,m]of Object.entries(u))s.push(`extensions.${d}.${c}=${String(m)}`)}i.extension=s}return i}a(W,"frontmatterFields");function le(e){const n=k(e),t=[],r=y(n,"kind",t),i=y(n,"after",t);t.length>0&&w("memory list query",t);const o=p(n,["node","cwd","profile","store","kind","limit","after"]);h(o,_);const s=oe({target:o.target,...f(o,!1),...r===void 0?{}:{kind:r}}).sort((m,g)=>m.name.localeCompare(g.name)),d=i===void 0?s:s.filter(m=>m.name.localeCompare(i)>0),u=d.slice(0,T(n.limit,"limit",E)).map(B);return{status:200,body:{object:"list",data:u,has_more:d.length>u.length}}}a(le,"handleList");function ue(e){const n=k(e),t=p(n,["node","cwd","profile","store","frontmatter"]);return h(t,_),{status:200,body:A(q(e),t,f(t,!1),D(n,"frontmatter")===!0)}}a(ue,"handleRetrieve");function me(e){const n=[],t=j(e.body,["name","kind","when_and_why_to_read","body","frontmatter","extensions","node","cwd","profile","store"],n),r=b(t,"name",n),i=b(t,"kind",n),o=b(t,"when_and_why_to_read",n),s=b(t,"body",n);if(n.length>0&&w("memory create request",n),!S(r))throw new l(400,"invalid_memory_doc_name","memory document name must be slash-joined [A-Za-z0-9_-] segments");const d=p(t,["name","kind","when_and_why_to_read","body","frontmatter","extensions","node","cwd","profile","store"]);h(d,I);const u=f(d,!0),c={name:r,kind:i,whenAndWhyToRead:o,body:s,...W(t.frontmatter,t.extensions,["kind","when-and-why-to-read","origin","last-updated"])},m=te({target:d.target,scope:u.scope,memoryDir:u.memoryDir,store:u.store,isExplicitProjectStore:!1,origin:{created:new Date().toISOString(),cwd:d.target.cwd,...d.target.nodeId===null?{}:{node:d.target.nodeId}},fields:c}),g=A(m.name,d,u);return{status:200,body:m.findings===void 0?g:{...g,findings:m.findings}}}a(me,"handleCreate");function ce(e){const n=[],t=j(e.body,["rationale","body","frontmatter","extensions","unset","node","cwd","profile","store"],n),r=b(t,"rationale",n);t.body!==void 0&&typeof t.body!="string"&&n.push({field:"body",problem:"must be a string",received:t.body}),t.unset!==void 0&&(!Array.isArray(t.unset)||!t.unset.every(d=>typeof d=="string"))&&n.push({field:"unset",problem:"must be a string array",received:t.unset}),n.length>0&&w("memory update request",n);const i=q(e),o=p(t,["rationale","body","frontmatter","extensions","unset","node","cwd","profile","store"]);h(o,I);const s=W(t.frontmatter,t.extensions,["kind","when-and-why-to-read","origin","last-updated"]);return ae({target:o.target,selection:{target:o.target,...f(o,!1)},fields:{name:i,rationale:r,...t.body===void 0?{}:{body:t.body},...t.unset===void 0?{}:{unset:t.unset},...s}}),{status:200,body:A(i,o)}}a(ce,"handleUpdate");function fe(e){const n=p(k(e),["node","cwd","profile","store"]);h(n,I);const t=q(e);return{status:200,body:{...ne({target:n.target,selection:{target:n.target,...f(n,!1)},fields:{name:t}}),deleted:!0}}}a(fe,"handleDelete");function pe(e){const n=[],t=j(e.body,["to","node","cwd","profile","store"],n),r=b(t,"to",n);if(n.length>0&&w("memory move request",n),!S(r))throw new l(400,"invalid_memory_doc_name","memory document name must be slash-joined [A-Za-z0-9_-] segments");const i=p(t,["to","node","cwd","profile","store"]);h(i,I);const o=q(e);return{status:200,body:re({target:i.target,selection:{target:i.target,...f(i,!1)},fields:{name:o,to:r}})}}a(pe,"handleMove");function O(e){return"line"in e?`${e.name}\0${e.scope}\0${e.physical_relative_path}\0${String(e.line).padStart(10,"0")}`:e.name}a(O,"grepCursor");function he(e){const n=[],t=j(e.body,["query","kind","grep","body","limit","after","min_score","node","cwd","profile","store"],n),r=b(t,"query",n),i=y(t,"kind",n),o=y(t,"after",n);n.length>0&&w("memory search request",n);const s=p(t,["query","kind","grep","body","limit","after","min_score","node","cwd","profile","store"]);h(s,_);const d=D(t,"grep"),u=D(t,"body"),c=t.min_score===void 0?void 0:U(t.min_score,"min_score");if(d===!0&&u===!0)throw new l(400,"invalid_request","grep and body cannot both be true");if(d===!0&&c!==void 0)throw new l(400,"invalid_request","min_score is only available in ranked mode");const g=[...de({target:s.target,...f(s,!1),query:r,...i===void 0?{}:{kind:i},...d===void 0?{}:{grep:d},...u===void 0?{}:{body:u},...c===void 0?{}:{minScore:c}}).hits].sort((v,C)=>d===!0?O(v).localeCompare(O(C)):v.name.localeCompare(C.name)),P=o===void 0?g:g.filter(v=>(d===!0?O(v):v.name).localeCompare(o)>0),M=P.slice(0,T(t.limit,"limit",E));return{status:200,body:{object:"list",data:M,has_more:P.length>M.length}}}a(he,"handleSearch");function ye(e){const n=k(e),t=p(n,["node","cwd","profile","store","limit","revision","diff"]);h(t,_);const r=n.revision===void 0?void 0:U(n.revision,"revision"),i=D(n,"diff"),o=se({target:t.target,...f(t,!1),name:q(e),limit:T(n.limit,"limit",E),...r===void 0?{}:{revision:r},...i===void 0?{}:{diff:i}});return{status:200,body:{name:o.name,scope:o.scope,log_path:o.logPath,total:o.total,...o.deleted===void 0?{}:{deleted:o.deleted},..."record"in o?{record:o.record}:{revisions:[...o.revisions]}}}}a(ye,"handleHistory");function ge(e){const n=k(e),t=e.query.get("name");if(t===null||!S(t))throw new l(400,"invalid_memory_doc_name","memory document name must be slash-joined [A-Za-z0-9_-] segments");const r=p(n,["name","node","cwd","profile","store"]);h(r,_);const i=H({target:r.target,...f(r,!1),name:t});return{status:200,body:{name:i.doc.name,scope:i.doc.scope,path:i.doc.path,store_root:i.doc.root,physical_relative_path:i.doc.physicalRelativePath,...i.doc.plugin===void 0?{}:{plugin:i.doc.plugin}}}}a(ge,"handleResolve");const $e=[{method:"GET",pattern:"/v1/memory/docs",handler:le},{method:"GET",pattern:"/v1/memory/docs/:name",handler:ue},{method:"POST",pattern:"/v1/memory/docs",handler:me},{method:"PATCH",pattern:"/v1/memory/docs/:name",handler:ce},{method:"DELETE",pattern:"/v1/memory/docs/:name",handler:fe},{method:"POST",pattern:"/v1/memory/docs/:name/move",handler:pe},{method:"POST",pattern:"/v1/memory/search",handler:he},{method:"GET",pattern:"/v1/memory/docs/:name/history",handler:ye},{method:"GET",pattern:"/v1/memory/resolve",handler:ge}];export{$e as memoryRoutes};
1
+ var Y=Object.defineProperty;var a=(e,n)=>Y(e,"name",{value:n,configurable:!0});import{getNode as N}from"../../../core/canvas/canvas.js";import{ApiError as m}from"../../../api/errors.js";import{assertScope as J}from"../../../core/scopes.js";import{CrtrError as X}from"../../../core/errors.js";import{memoryDir as x}from"../../../core/runtime/memory.js";import{NEUTRAL_PROJECT_MEMORY as K,projectScopeRoots as L,scopeMemoryDir as Q}from"../../../core/scope.js";import{profileMemoryDir as F}from"../../../core/profiles/manifest.js";import{openProjectMemoryStore as V}from"../../../core/memory-resolver.js";import{candidateLocation as ee,createDoc as te,deleteDoc as ne,listDocs as oe,moveDoc as re,readDoc as ie,readHistory as se,searchDocs as de,updateDoc as ae}from"../../../core/memory/service.js";import{MEMORY_SCOPES as z,isMemoryDocName as S}from"../../../api/dto/memory.js";import{invalidRequest as b,isRecord as R,objectBody as j,optionalString as h,requiredString as w}from"./validate.js";const _="memory:read",I="memory:write",E=100,G=100;function q(e){const n=e.params.name;if(n===void 0||!S(n))throw new m(400,"invalid_memory_doc_name","memory document name must be slash-joined [A-Za-z0-9_-] segments");return n}a(q,"requireName");function k(e){return Object.fromEntries(e.query.entries())}a(k,"queryObject");function $(e,n){return{scope:e,storeRoot:n,namespace:"",mountStatus:"ready",projectMemory:K}}a($,"nativeStore");function p(e,n){const t=[];for(const c of Object.keys(e))n.includes(c)||t.push({field:c,problem:"is not allowed",received:e[c]});const r=h(e,"node",t),i=h(e,"cwd",t),o=h(e,"profile",t),s=h(e,"store",t);s!==void 0&&!z.includes(s)&&t.push({field:"store",problem:`must be one of ${z.join(", ")}`,received:s}),r!==void 0&&(i!==void 0||o!==void 0)&&t.push({field:"node",problem:"derives cwd and profile and cannot be combined with either"}),t.length>0&&b("memory scope",t);let d,l;if(r!==void 0){const c=N(r);if(c===null)throw new m(404,"node_not_found",`unknown node: ${r}`);d={cwd:c.cwd,profileId:c.profile_id??null,nodeId:c.node_id},l=c.node_id}else d={cwd:i??"/",profileId:o??null,nodeId:null};const u=s;if(u==="node"&&l===void 0)throw new m(400,"invalid_request","store node requires node");if(u==="profile"&&d.profileId===null)throw new m(400,"invalid_request","store profile requires profile or node with a profile");return{target:d,...u===void 0?{}:{scope:u},...l===void 0?{}:{nodeId:l}}}a(p,"resolveScope");function y(e,n){if(e.nodeId===void 0)return;const t=N(e.nodeId);if(t===null)throw new m(404,"node_not_found",`unknown node: ${e.nodeId}`);J(t,n)}a(y,"requireScope");function f(e,n){const t=e.scope;if(!n)return{...t===void 0?{}:{scope:t}};const r=t??(L(e.target.cwd,e.target.profileId).length>0?"project":"user");if(r==="builtin")throw new m(400,"invalid_request","builtin memory is read-only");if(r==="node")return{scope:r,store:$("node",x(e.target.nodeId)),memoryDir:x(e.target.nodeId)};if(r==="profile")return{scope:r,store:$("profile",F(e.target.profileId)),memoryDir:F(e.target.profileId)};if(r==="project"){const o=L(e.target.cwd,e.target.profileId)[0];if(o===void 0)throw new m(400,"invalid_request","store project requires a project memory store in cwd or profile");const s=V(o.slice(0,-8).replace(/\/$/,""));return{scope:r,store:s,memoryDir:s.storeRoot}}const i=Q("user");if(i===null)throw new Error("user memory directory unavailable");return{scope:"user",store:$("user",i),memoryDir:i}}a(f,"selection");function Z(e,n){return e.length>1?e.map(t=>ee(t,n)):void 0}a(Z,"candidates");function B(e){return{name:e.name,short_form:e.shortForm,kind:e.kind,scope:e.scope,extensions:e.extensions,path:e.path,store_root:e.storeRoot,physical_relative_path:e.physicalRelativePath,...Z(e.candidates,e.candidates[0])===void 0?{}:{candidates:Z(e.candidates,e.candidates[0])}}}a(B,"summary");function H(e){try{const n=ie(e);if(n.kind==="document")return n}catch(n){if(!(n instanceof X)||n.code!=="not_found")throw n}throw new m(404,"memory_document_not_found",`memory document not found: ${e.name}`)}a(H,"requestedDocument");function A(e,n,t=f(n,!1),r=!1){const i=H({target:n.target,...t,name:e,frontmatter:r,interpolateNodePaths:!1}),o=i.doc;return{...B({name:o.name,kind:String(o.frontmatter?.kind??""),scope:o.scope,path:o.path,storeRoot:o.root,physicalRelativePath:o.physicalRelativePath,shortForm:String(o.frontmatter?.["short-form"]??""),slash:o.frontmatter?.slash===!0,extensions:o.frontmatter?.extensions??{},candidates:i.candidates}),body:i.content,frontmatter:o.frontmatter,representation:o.representation,links:[...i.links]}}a(A,"document");function T(e,n,t){if(e===void 0)return t;const r=typeof e=="number"?e:Number(e);if(!Number.isInteger(r)||r<1||r>G)throw new m(400,"invalid_request",`${n} must be an integer from 1 through ${G}`);return r}a(T,"number");function U(e,n){const t=typeof e=="number"?e:Number(e);if(!Number.isFinite(t)||t<1)throw new m(400,"invalid_request",`${n} must be a finite number of at least 1`);return t}a(U,"positiveNumber");function D(e,n){const t=e[n];if(t!==void 0){if(t===!0||t==="true")return!0;if(t===!1||t==="false")return!1;throw new m(400,"invalid_request",`${n} must be a boolean`)}}a(D,"optionalBoolean");function W(e,n,t=[]){if(e!==void 0&&!R(e))throw new m(400,"invalid_request","frontmatter must be an object");const r=e===void 0?{}:e;for(const s of t)if(s in r)throw new m(400,"invalid_request",`frontmatter.${s} cannot be set directly`);const i={},o={"short-form":"shortForm","when-and-why-to-read":"whenAndWhyToRead","lint-ignore":"lintIgnore",rationale:"docRationale",kind:"kind",unlisted:"unlisted",surfaces:"surface",gate:"gate",slash:"slash"};for(const[s,d]of Object.entries(r)){const l=o[s];if(l===void 0)throw new m(400,"invalid_request",`frontmatter.${s} is not writable through this route`);if(s==="unlisted"||s==="slash"){if(d!==!0)throw new m(400,"invalid_request",`frontmatter.${s} must be true; remove it with unset`)}else if(s==="surfaces"){if(!Array.isArray(d)||!d.every(u=>typeof u=="string"))throw new m(400,"invalid_request","frontmatter.surfaces must be a string array")}else if(s==="lint-ignore"){if(!Array.isArray(d)||!d.every(u=>typeof u=="string"))throw new m(400,"invalid_request","frontmatter.lint-ignore must be a string array")}else if(typeof d!="string"||d.trim()==="")throw new m(400,"invalid_request",`frontmatter.${s} must be a non-empty string`);i[l]=d}if(n!==void 0){if(!R(n))throw new m(400,"invalid_request","extensions must be an object");const s=[];for(const[d,l]of Object.entries(n)){if(!R(l))throw new m(400,"invalid_request",`extensions.${d} must be an object`);for(const[u,c]of Object.entries(l))s.push(`extensions.${d}.${u}=${String(c)}`)}i.extension=s}return i}a(W,"frontmatterFields");function me(e){const n=k(e),t=[],r=h(n,"kind",t),i=h(n,"after",t);t.length>0&&b("memory list query",t);const o=p(n,["node","cwd","profile","store","kind","limit","after"]);y(o,_);const s=oe({target:o.target,...f(o,!1),...r===void 0?{}:{kind:r}}).sort((c,g)=>c.name.localeCompare(g.name)),d=i===void 0?s:s.filter(c=>c.name.localeCompare(i)>0),l=d.slice(0,T(n.limit,"limit",E)).map(B);return{status:200,body:{object:"list",data:l,has_more:d.length>l.length}}}a(me,"handleList");function le(e){const n=k(e),t=p(n,["node","cwd","profile","store","frontmatter"]);return y(t,_),{status:200,body:A(q(e),t,f(t,!1),D(n,"frontmatter")===!0)}}a(le,"handleRetrieve");function ce(e){const n=[],t=j(e.body,["name","kind","when_and_why_to_read","body","frontmatter","extensions","node","cwd","profile","store"],n),r=w(t,"name",n),i=w(t,"kind",n),o=w(t,"when_and_why_to_read",n),s=w(t,"body",n);if(n.length>0&&b("memory create request",n),!S(r))throw new m(400,"invalid_memory_doc_name","memory document name must be slash-joined [A-Za-z0-9_-] segments");const d=p(t,["name","kind","when_and_why_to_read","body","frontmatter","extensions","node","cwd","profile","store"]);y(d,I);const l=f(d,!0),u={name:r,kind:i,whenAndWhyToRead:o,body:s,...W(t.frontmatter,t.extensions,["kind","when-and-why-to-read","origin","last-updated"])},c=te({target:d.target,scope:l.scope,memoryDir:l.memoryDir,store:l.store,isExplicitProjectStore:!1,origin:{created:new Date().toISOString(),cwd:d.target.cwd,...d.target.nodeId===null?{}:{node:d.target.nodeId}},fields:u}),g=A(c.name,d,l);return{status:200,body:c.findings===void 0?g:{...g,findings:c.findings}}}a(ce,"handleCreate");function ue(e){const n=[],t=j(e.body,["rationale","body","frontmatter","extensions","unset","node","cwd","profile","store"],n),r=w(t,"rationale",n);t.body!==void 0&&typeof t.body!="string"&&n.push({field:"body",problem:"must be a string",received:t.body}),t.unset!==void 0&&(!Array.isArray(t.unset)||!t.unset.every(d=>typeof d=="string"))&&n.push({field:"unset",problem:"must be a string array",received:t.unset}),n.length>0&&b("memory update request",n);const i=q(e),o=p(t,["rationale","body","frontmatter","extensions","unset","node","cwd","profile","store"]);y(o,I);const s=W(t.frontmatter,t.extensions,["kind","when-and-why-to-read","origin","last-updated"]);return ae({target:o.target,selection:{target:o.target,...f(o,!1)},fields:{name:i,rationale:r,...t.body===void 0?{}:{body:t.body},...t.unset===void 0?{}:{unset:t.unset},...s}}),{status:200,body:A(i,o)}}a(ue,"handleUpdate");function fe(e){const n=p(k(e),["node","cwd","profile","store"]);y(n,I);const t=q(e);return{status:200,body:{...ne({target:n.target,selection:{target:n.target,...f(n,!1)},fields:{name:t}}),deleted:!0}}}a(fe,"handleDelete");function pe(e){const n=[],t=j(e.body,["to","node","cwd","profile","store"],n),r=w(t,"to",n);if(n.length>0&&b("memory move request",n),!S(r))throw new m(400,"invalid_memory_doc_name","memory document name must be slash-joined [A-Za-z0-9_-] segments");const i=p(t,["to","node","cwd","profile","store"]);y(i,I);const o=q(e);return{status:200,body:re({target:i.target,selection:{target:i.target,...f(i,!1)},fields:{name:o,to:r}})}}a(pe,"handleMove");function O(e){return"line"in e?`${e.name}\0${e.scope}\0${e.physical_relative_path}\0${String(e.line).padStart(10,"0")}`:e.name}a(O,"grepCursor");function ye(e){const n=[],t=j(e.body,["query","kind","grep","body","limit","after","min_score","node","cwd","profile","store"],n),r=w(t,"query",n),i=h(t,"kind",n),o=h(t,"after",n);n.length>0&&b("memory search request",n);const s=p(t,["query","kind","grep","body","limit","after","min_score","node","cwd","profile","store"]);y(s,_);const d=D(t,"grep"),l=D(t,"body"),u=t.min_score===void 0?void 0:U(t.min_score,"min_score");if(d===!0&&l===!0)throw new m(400,"invalid_request","grep and body cannot both be true");if(d===!0&&u!==void 0)throw new m(400,"invalid_request","min_score is only available in ranked mode");const g=[...de({target:s.target,...f(s,!1),query:r,...i===void 0?{}:{kind:i},...d===void 0?{}:{grep:d},...l===void 0?{}:{body:l},...u===void 0?{}:{minScore:u}}).hits].sort((v,C)=>d===!0?O(v).localeCompare(O(C)):v.name.localeCompare(C.name)),P=o===void 0?g:g.filter(v=>(d===!0?O(v):v.name).localeCompare(o)>0),M=P.slice(0,T(t.limit,"limit",E));return{status:200,body:{object:"list",data:M,has_more:P.length>M.length}}}a(ye,"handleSearch");function he(e){const n=k(e),t=p(n,["node","cwd","profile","store","limit","revision","diff"]);y(t,_);const r=n.revision===void 0?void 0:U(n.revision,"revision"),i=D(n,"diff"),o=se({target:t.target,...f(t,!1),name:q(e),limit:T(n.limit,"limit",E),...r===void 0?{}:{revision:r},...i===void 0?{}:{diff:i}});return{status:200,body:{name:o.name,scope:o.scope,log_path:o.logPath,total:o.total,...o.deleted===void 0?{}:{deleted:o.deleted},..."record"in o?{record:o.record}:{revisions:[...o.revisions]}}}}a(he,"handleHistory");function ge(e){const n=k(e),t=e.query.get("name");if(t===null||!S(t))throw new m(400,"invalid_memory_doc_name","memory document name must be slash-joined [A-Za-z0-9_-] segments");const r=p(n,["name","node","cwd","profile","store"]);y(r,_);const i=H({target:r.target,...f(r,!1),name:t});return{status:200,body:{name:i.doc.name,scope:i.doc.scope,path:i.doc.path,store_root:i.doc.root,physical_relative_path:i.doc.physicalRelativePath,...i.doc.plugin===void 0?{}:{plugin:i.doc.plugin}}}}a(ge,"handleResolve");const $e=[{method:"GET",pattern:"/v1/memory/docs",scope:"memory:read",handler:me},{method:"GET",pattern:"/v1/memory/docs/:name",scope:"memory:read",handler:le},{method:"POST",pattern:"/v1/memory/docs",scope:"memory:write",handler:ce},{method:"PATCH",pattern:"/v1/memory/docs/:name",scope:"memory:write",handler:ue},{method:"DELETE",pattern:"/v1/memory/docs/:name",scope:"memory:write",handler:fe},{method:"POST",pattern:"/v1/memory/docs/:name/move",scope:"memory:write",handler:pe},{method:"POST",pattern:"/v1/memory/search",scope:"memory:read",handler:ye},{method:"GET",pattern:"/v1/memory/docs/:name/history",scope:"memory:read",handler:he},{method:"GET",pattern:"/v1/memory/resolve",scope:"memory:read",handler:ge}];export{$e as memoryRoutes};
@@ -1,3 +1,3 @@
1
- import type { RouteTable } from '../router.js';
1
+ import { type RouteTable } from '../router.js';
2
2
  export declare const brokerMailRoutes: RouteTable;
3
3
  export declare const messageRoutes: RouteTable;