@north-light/cli 0.3.452 → 0.3.454

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.
@@ -0,0 +1,3 @@
1
+ /** The first `$ref` in `schema` that cannot resolve inside the schema itself, as a message
2
+ * telling the caller what to change; `null` when every `$ref` resolves. */
3
+ export declare function outputSchemaRefProblem(schema: Record<string, unknown>): string | null;
@@ -0,0 +1 @@
1
+ var y=Object.defineProperty;var o=(e,n)=>y(e,"name",{value:n,configurable:!0});const p="https://json-schema.org/",g=new Set(["const","enum","default","examples"]);function $(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o($,"isObject");function u(e,n){try{return new URL(e,n)}catch{return null}}o(u,"parseUrl");function a(e){const n=new URL(e.href);return n.hash="",n.href}o(a,"withoutHash");function h(e,n,r){if(Array.isArray(e)){for(const t of e)h(t,n,r);return}if(!$(e))return;let s=n;if(typeof e.$id=="string"){const t=u(e.$id,n);t!==null&&(t.hash===""||t.hash==="#")&&(s=a(t),r.resources.has(s)||r.resources.set(s,e))}typeof e.$anchor=="string"&&r.anchors.set(`${s}#${e.$anchor}`,e),typeof e.$ref=="string"&&r.refs.push({ref:e.$ref,base:s});for(const[t,l]of Object.entries(e))g.has(t)||h(l,s,r)}o(h,"index");function A(e,n){let r=e;for(const s of n.split("/").slice(1)){let t;try{t=decodeURIComponent(s).replaceAll("~1","/").replaceAll("~0","~")}catch{return}if(Array.isArray(r))r=r[Number(t)];else if($(r)&&Object.hasOwn(r,t))r=r[t];else return}return r}o(A,"pointerGet");function b(e){const n=typeof e.$id=="string"?u(e.$id,p):null,r=n===null?p:a(n),s={resources:new Map([[r,e]]),anchors:new Map,refs:[]};h(e,r,s);for(const{ref:t,base:l}of s.refs){const i=u(t,l),c=i===null?"":decodeURIComponent(i.hash.replace(/^#/,"")),d=i===null?void 0:s.resources.get(a(i));let f;if(i===null||d===void 0?f=!1:c===""?f=!0:c.startsWith("/")?f=A(d,c)!==void 0:f=s.anchors.has(`${a(i)}#${c}`),!f){const m=!t.startsWith("#");return`$ref ${JSON.stringify(t)} does not resolve inside the schema. The schema is a single JSON object, so a $ref can only point into itself (\`#/$defs/x\`, \`#anchor\`) or at another schema document bundled under \`$defs\` with its own \`$id\` (give that document an \`$id\` that the $ref's path resolves against, e.g. \`"$defs": { "common": { "$id": "common.schema.json", \u2026 } }\`).${m?" Files are never fetched.":""}`}}return null}o(b,"outputSchemaRefProblem");export{b as outputSchemaRefProblem};
@@ -1,3 +1,4 @@
1
+ import { outputSchemaRefProblem } from './output-schema-refs.js';
1
2
  import type { DeclinedResult } from '../canvas/types.js';
2
3
  /** The pi tool a node calls to answer its pending structured-output request
3
4
  * (registered by canvas-structured-output; `run.get` names it `submitting_result`). */
@@ -58,12 +59,22 @@ export declare function readOutputRequest(nodeId: string): StructuredOutputState
58
59
  export declare function readBrokerOutputRequest(nodeId: string): StructuredOutputState;
59
60
  /** Reads the pre-request-id sidecar shape for daemon boot adoption only. */
60
61
  export declare function readLegacyOutputRequest(nodeId: string): Pick<StructuredOutputRequest, 'mode' | 'schema' | 'requestMessageId'> | null;
61
- /** Validate a submitted result value against a stored output schema. Returns
62
- * the validated value (the validator applies the same benign coercions the
63
- * retired `submit` tool did — e.g. "5" → 5 for a number field), or throws an
64
- * Error whose message lists the per-field failures. pi-ai is imported lazily
65
- * so the daemon and CLI only pay for its module graph on an actual submit. */
62
+ /** Validate a submitted result value against a stored output schema, strictly. Returns
63
+ * the value exactly as submitted, or throws an Error whose message lists the per-field
64
+ * failures. Nothing is coerced: unlike a model's tool arguments, a final result is data
65
+ * the requester stores, so `null` is never turned into `0` / `""` / `false`, `"5"` is
66
+ * not turned into `5`, and a null in an optional field is not silently dropped — each is a
67
+ * mismatch the submitter fixes. TypeBox is imported lazily so the daemon and CLI only
68
+ * pay for its module graph on an actual submit. */
66
69
  export declare function validateStructuredResult(schema: Record<string, unknown>, value: unknown): Promise<unknown>;
70
+ export { outputSchemaRefProblem };
71
+ /** Why `schema` cannot be accepted as an `output_schema`, or `null` when it can: a `$ref`
72
+ * that resolves nowhere inside it, or a keyword the validator cannot compile (a bad
73
+ * `pattern`). Checked when the schema is admitted, so the failure reaches the requester
74
+ * instead of the submitting agent, which would otherwise be refused on every attempt. */
75
+ export declare function outputSchemaProblem(schema: Record<string, unknown>): Promise<string | null>;
76
+ /** Throws the `bad_output_schema` input error when `outputSchemaProblem` finds one. */
77
+ export declare function assertOutputSchemaAccepted(schema: Record<string, unknown>): Promise<void>;
67
78
  /** Persist a validated result atomically (temp-file-plus-rename), so a
68
79
  * concurrent reader (Core's result poll peeks this file) never sees a torn
69
80
  * write. Returns the result path. */
@@ -1,6 +1,8 @@
1
- var P=Object.defineProperty;var s=(t,e)=>P(t,"name",{value:e,configurable:!0});import{existsSync as l,mkdirSync as d,readFileSync as a,unlinkSync as f,writeFileSync as h,renameSync as S}from"node:fs";import{dirname as g,resolve as j}from"node:path";import{randomUUID as b}from"node:crypto";import{nodeDir as R,nodeRunDir as O,contextDir as x,nodeAgentDir as y}from"../canvas/paths.js";import{readTextBeneathIfExists as T,unlinkBeneath as E,writeFileBeneath as q}from"../spaces/open-beneath.js";import{InputError as N}from"../io.js";import{isRecord as c}from"../../shared/predicates.js";import{setModeBeneath as A}from"../spaces/open-beneath.js";import{LAUNCHER_SOCKET as M}from"../../launcher/spec.js";const Y="submit_result",Z="A .json file path, or inline JSON beginning with `{`.",tt='The full schema (including enum, pattern, and numeric bounds) is enforced when the target submits its result (its `submit_result` tool, or `crtr push result`); a mismatch rejects with the field errors and records nothing, so an over-constrained schema costs the target retries. A target that cannot honestly satisfy the schema declines (`submit_result` with `decline`, or `crtr push result --decline "<reason>" --code <token> [--retryable]`), which records a failure outcome with reason `declined` carrying the reason, code, and retryable flag instead of a value.';function m(t){return`${R(t)}/output-schema.json`}s(m,"outputSchemaPath");function _(t){return`${O(t)}/output-schema.json`}s(_,"brokerOutputSchemaPath");function U(){const t=a("/etc/group","utf8").split(`
2
- `).find(r=>r.startsWith("crtr-data:")),e=Number(t?.split(":")[2]);if(!Number.isInteger(e))throw new Error("crtr-data group is required on sandboxed Linux");return e}s(U,"dataGroupId");function k(t,e){process.platform!=="linux"||!l(M)||A(O(t),e,432,{uid:process.getuid(),gid:U()})}s(k,"shareRunFileWithBroker");function B(t){const e=m(t),r=_(t);l(e)&&(q(O(t),r,a(e),{atomic:!0}),k(t,r))}s(B,"projectOutputSchema");function $(t,e){return`${x(t,e)}/result.json`}s($,"outputResultPath");function et(t,e){const r=T(y(t,e),$(t,e));return r===null?void 0:JSON.parse(r)}s(et,"readOutputResult");function D(t,e,r,n){return r==="terminal"?$(t,n):`${x(t,n)}/structured-requests/${e}/result.json`}s(D,"structuredRequestResultPath");function w(t,e){return`${x(t,e)}/declined.json`}s(w,"outputDeclinedPath");function rt(t){const e=t?.trim();if(e===void 0||e==="")return null;let r,n;if(e.startsWith("{"))r=e,n="inline JSON";else{const o=j(e);n=o;try{r=a(o,"utf8")}catch(i){throw new N({error:"bad_output_schema",message:`could not read output schema from ${o}: ${i.message}`,field:"output-schema",next:"Pass a readable JSON Schema file path, or inline JSON beginning with `{`."})}}let u;try{u=JSON.parse(r)}catch(o){throw new N({error:"bad_output_schema",message:`output schema from ${n} is not valid JSON: ${o.message}`,field:"output-schema",next:"Pass valid JSON whose top-level value is an object."})}if(!c(u))throw new N({error:"bad_output_schema",message:`output schema from ${n} must be a JSON object`,field:"output-schema",next:"Pass a JSON Schema object, not an array, string, number, boolean, or null."});return u}s(rt,"parseOutputSchemaValue");function nt(t){if(t.node_id===null)throw new Error(`cannot publish structured request ${t.request_id} before node binding`);const e=t.node_id,r=m(e);d(g(r),{recursive:!0});const n={request_id:t.request_id,mode:t.submission,schema:t.schema,...t.request_message_id==null?{}:{requestMessageId:t.request_message_id}},u=`${r}.${b()}.tmp`;return h(u,`${JSON.stringify(n,null,2)}
3
- `,"utf8"),S(u,r),B(e),r}s(nt,"writeStructuredRequestSidecar");function C(t){return J(m(t))}s(C,"readOutputRequest");function st(t){return J(_(t))}s(st,"readBrokerOutputRequest");function J(t){if(!l(t))return{state:"absent"};let e;try{e=a(t,"utf8")}catch(p){return{state:"invalid",error:`could not read request file: ${p.message}`}}let r;try{r=JSON.parse(e)}catch(p){return{state:"invalid",error:`request file is not valid JSON: ${p.message}`}}if(!c(r))return{state:"invalid",error:"request file top-level value must be an object"};const n=r.request_id,u=r.mode,o=r.schema;if(typeof n!="string"||n==="")return{state:"invalid",error:"request_id must be a non-empty string"};if(u!=="terminal"&&u!=="oneoff")return{state:"invalid",error:`mode must be 'terminal' or 'oneoff', got ${JSON.stringify(u)}`};if(!c(o))return{state:"invalid",error:`schema must be an object, got ${typeof o}`};const i=r.requestMessageId;return i!==void 0&&typeof i!="string"?{state:"invalid",error:`requestMessageId must be a string, got ${typeof i}`}:{state:"valid",request:{request_id:n,mode:u,schema:o,...i===void 0?{}:{requestMessageId:i}}}}s(J,"readOutputRequestAt");function ut(t){try{const e=JSON.parse(a(m(t),"utf8"));if(!c(e)||Object.hasOwn(e,"request_id"))return null;const r=e.mode,n=e.schema,u=e.requestMessageId;return r!=="terminal"&&r!=="oneoff"||!c(n)?null:{mode:r,schema:n,...typeof u=="string"?{requestMessageId:u}:{}}}catch{return null}}s(ut,"readLegacyOutputRequest");async function ot(t,e){const{validateToolArguments:r}=await import("@earendil-works/pi-ai");return r({name:"submit",description:"",parameters:t},{type:"toolCall",id:"structured-output",name:"submit",arguments:e})}s(ot,"validateStructuredResult");function it(t,e,r){const n=y(t,r),u=$(t,r);q(n,u,`${JSON.stringify(e,null,2)}
4
- `,{atomic:!0});try{E(n,w(t,r))}catch(o){if(o.code!=="ENOENT")throw o}return u}s(it,"writeOutputResult");function at(t,e,r){const n=w(t,r);return q(y(t,r),n,`${JSON.stringify(e,null,2)}
5
- `,{atomic:!0}),n}s(at,"writeOutputDeclined");function v(t){return`${R(t)}/output-schema-reprompts.json`}s(v,"schemaRepromptsPath");function ct(t){try{const e=JSON.parse(a(v(t),"utf8"));if(c(e)&&Number.isSafeInteger(e.count)&&Number.isFinite(e.at))return{count:e.count,at:e.at}}catch{}return{count:0,at:0}}s(ct,"readSchemaReprompts");function mt(t,e){const r=v(t);d(g(r),{recursive:!0});const n=`${r}.${b()}.tmp`;h(n,JSON.stringify(e),"utf8"),S(n,r)}s(mt,"writeSchemaReprompts");function F(t){try{f(v(t))}catch{}}s(F,"clearSchemaReprompts");function pt(t,e){const r=m(t);if(e!==void 0){const u=C(t);if(u.state!=="valid"||u.request.request_id!==e)return}try{f(r)}catch{}F(t);const n=_(t);try{f(n)}catch{}}s(pt,"removeOutputSchema");function lt(t,e,r,n,u){const o=D(t,e,r,u);d(g(o),{recursive:!0});const i=`${o}.${b()}.tmp`;return h(i,`${JSON.stringify(n,null,2)}
6
- `,"utf8"),{path:o,tmpPath:i}}s(lt,"stageStructuredResult");function dt(t){return S(t.tmpPath,t.path),t.path}s(dt,"installStagedStructuredProjection");export{tt as OUTPUT_SCHEMA_CONSTRAINTS,Z as OUTPUT_SCHEMA_TRANSPORT,Y as SUBMIT_RESULT_TOOL,_ as brokerOutputSchemaPath,F as clearSchemaReprompts,dt as installStagedStructuredProjection,w as outputDeclinedPath,$ as outputResultPath,m as outputSchemaPath,rt as parseOutputSchemaValue,B as projectOutputSchema,st as readBrokerOutputRequest,ut as readLegacyOutputRequest,C as readOutputRequest,et as readOutputResult,ct as readSchemaReprompts,pt as removeOutputSchema,v as schemaRepromptsPath,k as shareRunFileWithBroker,lt as stageStructuredResult,D as structuredRequestResultPath,ot as validateStructuredResult,at as writeOutputDeclined,it as writeOutputResult,mt as writeSchemaReprompts,nt as writeStructuredRequestSidecar};
1
+ var j=Object.defineProperty;var o=(t,e)=>j(t,"name",{value:e,configurable:!0});import{existsSync as d,mkdirSync as f,readFileSync as a,unlinkSync as h,writeFileSync as S,renameSync as g}from"node:fs";import{dirname as b,resolve as T}from"node:path";import{randomUUID as x}from"node:crypto";import{nodeDir as R,nodeRunDir as O,contextDir as y,nodeAgentDir as $}from"../canvas/paths.js";import{readTextBeneathIfExists as E,unlinkBeneath as k,writeFileBeneath as q}from"../spaces/open-beneath.js";import{outputSchemaRefProblem as v}from"./output-schema-refs.js";import{InputError as l}from"../io.js";import{isRecord as c}from"../../shared/predicates.js";import{setModeBeneath as A}from"../spaces/open-beneath.js";import{LAUNCHER_SOCKET as B}from"../../launcher/spec.js";const et="submit_result",rt="A .json file path, or inline JSON beginning with `{`.",nt='The full schema (including enum, pattern, and numeric bounds) is enforced when the target submits its result (its `submit_result` tool, or `crtr push result`); a mismatch rejects with the field errors and records nothing, so an over-constrained schema costs the target retries. A target that cannot honestly satisfy the schema declines (`submit_result` with `decline`, or `crtr push result --decline "<reason>" --code <token> [--retryable]`), which records a failure outcome with reason `declined` carrying the reason, code, and retryable flag instead of a value.';function p(t){return`${R(t)}/output-schema.json`}o(p,"outputSchemaPath");function _(t){return`${O(t)}/output-schema.json`}o(_,"brokerOutputSchemaPath");function M(){const t=a("/etc/group","utf8").split(`
2
+ `).find(r=>r.startsWith("crtr-data:")),e=Number(t?.split(":")[2]);if(!Number.isInteger(e))throw new Error("crtr-data group is required on sandboxed Linux");return e}o(M,"dataGroupId");function U(t,e){process.platform!=="linux"||!d(B)||A(O(t),e,432,{uid:process.getuid(),gid:M()})}o(U,"shareRunFileWithBroker");function C(t){const e=p(t),r=_(t);d(e)&&(q(O(t),r,a(e),{atomic:!0}),U(t,r))}o(C,"projectOutputSchema");function w(t,e){return`${y(t,e)}/result.json`}o(w,"outputResultPath");function ot(t,e){const r=E($(t,e),w(t,e));return r===null?void 0:JSON.parse(r)}o(ot,"readOutputResult");function D(t,e,r,n){return r==="terminal"?w(t,n):`${y(t,n)}/structured-requests/${e}/result.json`}o(D,"structuredRequestResultPath");function P(t,e){return`${y(t,e)}/declined.json`}o(P,"outputDeclinedPath");function st(t){const e=t?.trim();if(e===void 0||e==="")return null;let r,n;if(e.startsWith("{"))r=e,n="inline JSON";else{const u=T(e);n=u;try{r=a(u,"utf8")}catch(i){throw new l({error:"bad_output_schema",message:`could not read output schema from ${u}: ${i.message}`,field:"output-schema",next:"Pass a readable JSON Schema file path, or inline JSON beginning with `{`."})}}let s;try{s=JSON.parse(r)}catch(u){throw new l({error:"bad_output_schema",message:`output schema from ${n} is not valid JSON: ${u.message}`,field:"output-schema",next:"Pass valid JSON whose top-level value is an object."})}if(!c(s))throw new l({error:"bad_output_schema",message:`output schema from ${n} must be a JSON object`,field:"output-schema",next:"Pass a JSON Schema object, not an array, string, number, boolean, or null."});return s}o(st,"parseOutputSchemaValue");function ut(t){if(t.node_id===null)throw new Error(`cannot publish structured request ${t.request_id} before node binding`);const e=t.node_id,r=p(e);f(b(r),{recursive:!0});const n={request_id:t.request_id,mode:t.submission,schema:t.schema,...t.request_message_id==null?{}:{requestMessageId:t.request_message_id}},s=`${r}.${x()}.tmp`;return S(s,`${JSON.stringify(n,null,2)}
3
+ `,"utf8"),g(s,r),C(e),r}o(ut,"writeStructuredRequestSidecar");function F(t){return J(p(t))}o(F,"readOutputRequest");function it(t){return J(_(t))}o(it,"readBrokerOutputRequest");function J(t){if(!d(t))return{state:"absent"};let e;try{e=a(t,"utf8")}catch(m){return{state:"invalid",error:`could not read request file: ${m.message}`}}let r;try{r=JSON.parse(e)}catch(m){return{state:"invalid",error:`request file is not valid JSON: ${m.message}`}}if(!c(r))return{state:"invalid",error:"request file top-level value must be an object"};const n=r.request_id,s=r.mode,u=r.schema;if(typeof n!="string"||n==="")return{state:"invalid",error:"request_id must be a non-empty string"};if(s!=="terminal"&&s!=="oneoff")return{state:"invalid",error:`mode must be 'terminal' or 'oneoff', got ${JSON.stringify(s)}`};if(!c(u))return{state:"invalid",error:`schema must be an object, got ${typeof u}`};const i=r.requestMessageId;return i!==void 0&&typeof i!="string"?{state:"invalid",error:`requestMessageId must be a string, got ${typeof i}`}:{state:"valid",request:{request_id:n,mode:s,schema:u,...i===void 0?{}:{requestMessageId:i}}}}o(J,"readOutputRequestAt");function at(t){try{const e=JSON.parse(a(p(t),"utf8"));if(!c(e)||Object.hasOwn(e,"request_id"))return null;const r=e.mode,n=e.schema,s=e.requestMessageId;return r!=="terminal"&&r!=="oneoff"||!c(n)?null:{mode:r,schema:n,...typeof s=="string"?{requestMessageId:s}:{}}}catch{return null}}o(at,"readLegacyOutputRequest");async function ct(t,e){const{Compile:r}=await import("typebox/compile"),n=r(t);if(n.Check(e))return e;const s=n.Errors(e).map(u=>` - ${(u.keyword==="required"?[...u.instancePath.split("/").filter(Boolean),String(u.params.requiredProperties?.[0]??"")].filter(Boolean).join("."):u.instancePath.split("/").filter(Boolean).join("."))||"root"}: ${u.message}`);throw new Error(`Validation failed:
4
+ ${s.join(`
5
+ `)||" - Unknown validation error"}`)}o(ct,"validateStructuredResult");async function L(t){const e=v(t);if(e!==null)return e;try{const{Compile:r}=await import("typebox/compile");r(t)}catch(r){return`the schema cannot be compiled: ${r.message}`}return null}o(L,"outputSchemaProblem");async function pt(t){const e=await L(t);if(e!==null)throw new l({error:"bad_output_schema",message:`output_schema is not usable: ${e}`,field:"output-schema",next:"Fix the schema (bundle referenced documents under $defs with their own $id) and send it again."})}o(pt,"assertOutputSchemaAccepted");function lt(t,e,r){const n=$(t,r),s=w(t,r);q(n,s,`${JSON.stringify(e,null,2)}
6
+ `,{atomic:!0});try{k(n,P(t,r))}catch(u){if(u.code!=="ENOENT")throw u}return s}o(lt,"writeOutputResult");function mt(t,e,r){const n=P(t,r);return q($(t,r),n,`${JSON.stringify(e,null,2)}
7
+ `,{atomic:!0}),n}o(mt,"writeOutputDeclined");function N(t){return`${R(t)}/output-schema-reprompts.json`}o(N,"schemaRepromptsPath");function dt(t){try{const e=JSON.parse(a(N(t),"utf8"));if(c(e)&&Number.isSafeInteger(e.count)&&Number.isFinite(e.at))return{count:e.count,at:e.at}}catch{}return{count:0,at:0}}o(dt,"readSchemaReprompts");function ft(t,e){const r=N(t);f(b(r),{recursive:!0});const n=`${r}.${x()}.tmp`;S(n,JSON.stringify(e),"utf8"),g(n,r)}o(ft,"writeSchemaReprompts");function I(t){try{h(N(t))}catch{}}o(I,"clearSchemaReprompts");function ht(t,e){const r=p(t);if(e!==void 0){const s=F(t);if(s.state!=="valid"||s.request.request_id!==e)return}try{h(r)}catch{}I(t);const n=_(t);try{h(n)}catch{}}o(ht,"removeOutputSchema");function St(t,e,r,n,s){const u=D(t,e,r,s);f(b(u),{recursive:!0});const i=`${u}.${x()}.tmp`;return S(i,`${JSON.stringify(n,null,2)}
8
+ `,"utf8"),{path:u,tmpPath:i}}o(St,"stageStructuredResult");function gt(t){return g(t.tmpPath,t.path),t.path}o(gt,"installStagedStructuredProjection");export{nt as OUTPUT_SCHEMA_CONSTRAINTS,rt as OUTPUT_SCHEMA_TRANSPORT,et as SUBMIT_RESULT_TOOL,pt as assertOutputSchemaAccepted,_ as brokerOutputSchemaPath,I as clearSchemaReprompts,gt as installStagedStructuredProjection,P as outputDeclinedPath,w as outputResultPath,p as outputSchemaPath,L as outputSchemaProblem,v as outputSchemaRefProblem,st as parseOutputSchemaValue,C as projectOutputSchema,it as readBrokerOutputRequest,at as readLegacyOutputRequest,F as readOutputRequest,ot as readOutputResult,dt as readSchemaReprompts,ht as removeOutputSchema,N as schemaRepromptsPath,U as shareRunFileWithBroker,St as stageStructuredResult,D as structuredRequestResultPath,ct as validateStructuredResult,mt as writeOutputDeclined,lt as writeOutputResult,ft as writeSchemaReprompts,ut as writeStructuredRequestSidecar};
@@ -1,2 +1,2 @@
1
- var de=Object.defineProperty;var u=(t,e)=>de(t,"name",{value:e,configurable:!0});import{randomBytes as ce}from"node:crypto";import{claimNodeMail as ue,acknowledgeNodeMail as le}from"../../../core/canvas/deliveries.js";import{nodeMailEntry as fe}from"../../../core/feed/inbox.js";import{enqueueNodeMail as J,cancelPendingNodeMail as me}from"../../../core/feed/messages.js";import{reviveNode as L}from"../../../core/runtime/revive.js";import{BrokerUnreachableError as U}from"../../../core/runtime/broker-request.js";import{isBrokerLive as R}from"../../../core/runtime/model-swap.js";import{deliverLive as pe,interruptLive as ye}from"../../../core/runtime/interactive-deliver.js";import{isProfilePaused as he}from"../../../core/profiles/manifest.js";import{getNode as A,withFreshTerminalGuard as be}from"../../../core/canvas/canvas.js";import{getById as D,nodeObject as F,ownerForGrantee as we}from"../../../core/graph/objects.js";import{recordActedOn as ge}from"../../../core/graph/edges.js";import{recordWatch as G}from"../../../core/graph/watches.js";import{publish as H}from"../../../core/graph/events.js";import{readerFor as V}from"../reader.js";import{canRead as ve}from"../../../core/graph/access.js";import{withCanvasWrite as _}from"../../../core/canvas/db.js";import{getPendingStructuredRequestForNode as K}from"../../../core/canvas/structured-requests.js";import{cancelCronsOnWake as Q}from"../../../core/canvas/crons.js";import{assertNotFinalized as M,assertFinalizedForReopen as _e,commitReopenResident as P}from"../../../core/runtime/reopen.js";import{admitLegacyStructuredOutput as ke}from"../../structured-requests/sidecar.js";import{appendSituationalContext as E,formatSituationalProse as Se}from"../../../core/runtime/situational-context.js";import{formatDataCard as X}from"../../../shared/generated-context.js";import{hasNoNaturalCycle as $e}from"../../../core/runtime/revive-all.js";import{recordPendingParkActivity as Ne}from"../../park-pending.js";import{wantsExecution as je}from"../../reconcilers/node-lifecycle/wants-execution.js";import{hasFreshGroundState as qe}from"../../../core/runtime/revive.js";import{CrtrError as xe,notFound as C,usage as c}from"../../../core/errors.js";import{emitEvent as Ae}from"../../../core/events/emit.js";import{assertScope as Ce}from"../../../core/scopes.js";import{InputError as I}from"../../../core/io.js";import{ApiError as Oe}from"../../../api/index.js";import{describeObject as Re,stubOf as Fe}from"../../../core/peer/stubs.js";import{machineNameOf as Y}from"../../../core/peer/names.js";import{callerNode as Me,callerStub as Pe,forwardVerb as Z,relayError as ee,remoteStub as Ee,unknownError as te,withMachine as re}from"../../peer/forward.js";import{ownerOnly as Ie}from"../router.js";const Te=["critical","urgent","normal","deferred"];function ne(t,e){if(typeof t!="object"||t===null||Array.isArray(t))throw c(`${e} must be an object { kind, facts?, body? }`);const i=t,n=i.kind;if(typeof n!="string"||n.trim()==="")throw c(`${e}.kind is required`);if(!n.includes(":"))throw c(`${e}.kind must be namespaced (contain ':'): ${n}`);const r={kind:n},o=i.facts;if(o!==void 0){if(typeof o!="object"||o===null||Array.isArray(o))throw c(`${e}.facts must be an object of string or number values`);const d={};for(const[f,m]of Object.entries(o)){if(typeof m!="string"&&typeof m!="number")throw c(`${e}.facts.${f} must be a string or number`);d[f]=m}r.facts=d}const s=i.body;if(s!==void 0){if(typeof s!="string")throw c(`${e}.body must be a string`);r.body=s}return r}u(ne,"parseCardRequest");function oe(t,e){try{return X(t.kind,t.facts??{},t.body??"")}catch(i){throw c(`${e}: ${i instanceof Error?i.message:String(i)}`)}}u(oe,"renderCard");function Be(t){if(typeof t!="object"||t===null)throw c("a message requires a JSON body { body, tier?, fresh? }");const e=t,i=e.body,n=e.fresh===!0,r=e.tier,o=e.situational_context,s=e.output_schema,d=typeof i=="string"&&i.trim()!=="",f=typeof o=="string"&&o.trim()!=="",m=typeof s=="string"&&s.trim()!=="",S=e.situational_card,g=e.context_cards,h=S===void 0?void 0:ne(S,"situational_card");if(g!==void 0&&!Array.isArray(g))throw c("context_cards must be an array of { kind, facts?, body? }");const p=g?.map((k,N)=>ne(k,`context_cards[${N}]`));if(h!==void 0&&typeof o=="string"&&o!=="")throw c("situational_card and situational_context are mutually exclusive");const $=h!==void 0||p!==void 0&&p.length>0;if(!n&&!d&&!f&&!m&&!$)throw c("a message requires a non-empty body (or fresh: true, situational_context, a runtime card, or output_schema)");if(n&&p!==void 0&&p.length>0)throw c("context_cards cannot ride a fresh revive (no inbox entry carries them)");if(r!==void 0&&!Te.includes(r))throw c(`invalid tier: ${String(r)} (expected critical|urgent|normal|deferred)`);const l={body:typeof i=="string"?i:""};r!==void 0&&(l.tier=r),n&&(l.fresh=!0),e.reopen===!0&&(l.reopen=!0),typeof o=="string"&&(l.situational_context=o),h!==void 0&&(l.situational_card=h),p!==void 0&&(l.context_cards=p),typeof s=="string"&&(l.output_schema=s),typeof e.from=="string"&&(l.from=e.from);const b=e.delivery;if(b!==void 0&&b!=="interactive")throw c(`invalid delivery: ${String(b)} (expected interactive)`);if(b==="interactive"){if(n||l.situational_context!==void 0||l.output_schema!==void 0)throw c("interactive delivery supports a body, runtime cards, and reopen only (no fresh, situational_context, or output_schema)");if(!d)throw c("interactive delivery requires a non-empty body");if(l.tier==="deferred")throw c("interactive delivery cannot be deferred");l.delivery="interactive"}return l}u(Be,"parseSendBody");function ze(t){try{return JSON.parse(t)}catch{throw c("output_schema must be a JSON schema string")}}u(ze,"parseSchema");function We(t){return t.split(`
2
- `)[0].slice(0,120)}u(We,"label");function ie(t,e){return e===null?"":X("reopen-final-report",{report:`${t}/${e}`},"This node previously completed work. Read this final report before acting on the new instruction.")}u(ie,"previousFinalReportCard");function Je(t,e,i){if(i!==null&&i!=="human"&&D(t,i)?.type==="node"){const o=F(t,i);return{actor:o,senderNode:o}}if(i==="human")return{actor:we(t,"user:local"),senderNode:null};const n=V(t,e);return{actor:n.class==="person"?n.person:n.class==="app"?n.app:n.node,senderNode:n.class==="node"?n.node:null}}u(Je,"messageActor");function ae(t,e,i,n,r,o){const s=F(t,i),{actor:d,senderNode:f}=Je(t,e,n),m=r===null?{}:{pointer:r};ge(t,d,s),f!==null&&f.rowid!==s.rowid&&G(t,f,s,"message",{endsOn:o&&r!==null?`result:${r}`:"final"}),H(t,{event:"messaged",object:s,actor:d,attrs:{},...m}),f!==null&&H(t,{event:"sent",object:f,actor:f,attrs:{to:s.id},...m})}u(ae,"recordMessage");function Le(t,e){return new I({error:"deferred_no_natural_cycle",message:`${t} is ${e} with no natural next cycle ahead of it \u2014 a deferred message would never be delivered.`,next:"Use --tier normal, urgent, or critical to wake it now, or --reopen (with a body or --fresh) to re-task it first."})}u(Le,"deferredNoNaturalCycle");function Ue(t){if(!qe(t))throw new Oe(422,"unprocessable",`node ${t} has no goal/roadmap on disk \u2014 a fresh revive would resume amnesiac.`)}u(Ue,"assertRecoverableForFresh");function De(t,e){return t instanceof I?{error:t.payload.error,message:t.payload.message,next:t.payload.next,message_id:e}:t instanceof xe?{error:t.code,message:t.message,message_id:e}:{error:"wake_failed",message:"the target could not be woken; see the daemon log",message_id:e}}u(De,"wakeFailure");async function Ge(t,e){const i=typeof t.body=="object"&&t.body!==null&&!Array.isArray(t.body)?{...t.body}:t.body;typeof i=="object"&&i!==null&&delete i.from;const n=await Z(t,e,{method:"POST",path:`/v1/nodes/${encodeURIComponent(e)}/messages`,body:i});if(n.kind==="local")return null;if(n.kind==="unknown")throw te(e,n.unreachable);if(n.status>=400)throw ee(n.status,n.body);return _(r=>{const o=Me(r,t);if(o===null)return;const s=n.body?.object,d=Ee(r,e,"node",n.machine.id,s);G(r,o,d,"message",{endsOn:"final"})}),{status:n.status,body:re(n.body,n.machine)}}u(Ge,"forwardMessage");async function He(t){const e=await Ve(t);if(t.principal.class!=="forwarded"||typeof e.body!="object"||e.body===null)return e;const i=_(n=>{const r=F(n,t.params.id);return ve(n,V(n,t),r)?Re(n,r):{id:r.id,type:r.type,kind:null,name:r.id,owner:null}});return{...e,body:{...e.body,object:i}}}u(He,"handleMessage");async function Ve(t){const e=t.params.id,i=await Ge(t,e);if(i!==null)return i;const n=A(e);if(n===null)throw C(`unknown node: ${e}`,{received:e});const r=Be(t.body),o=r.tier??"normal",s=he(n.profile_id),d=t.principal.class==="forwarded"?_(a=>Pe(a,t)?.id??null):r.from??null;if(d!==null){const a=A(d);a!==null&&Ce(a,"crtr:act")}const f=d===null?null:_(a=>{const y=D(a,d);return y===null?null:Fe(a,y)?.home_machine??null}),m=f===null?void 0:`${d} on ${Y(f)}`,S=f===null?{}:{from_machine:Y(f)},g=r.body.trim()!=="",h=r.situational_card!==void 0?oe(r.situational_card,"situational_card"):r.situational_context!==void 0?Se(r.situational_context.trim()):"",p=h!=="",$=(r.context_cards??[]).map((a,y)=>oe(a,`context_cards[${y}]`)),l=r.output_schema!==void 0&&r.output_schema.trim()!==""?ze(r.output_schema):null;let b=!1;const k=u(a=>{if(!(l===null||b)){if(K(e)!==null)throw new I({error:"structured_request_conflict",message:`node ${e} already has a pending structured request`,next:"Wait for the current request to settle before requesting another structured result."});ke(e,"oneoff",l,a),b=!0}},"ensureSchema");if(r.fresh){const a=r.reopen?_e(e):null;r.reopen||M(e),Ue(e),k(),p&&E(e,h),r.reopen&&P(e,a);const y=await L(e,{resume:!1,capacity:"refuse"});return{status:201,body:{node_id:e,delivered:!1,revived:y.launch!==void 0}}}r.delivery==="interactive"&&!r.reopen&&M(e);let N=!1,v="";if(r.delivery==="interactive"&&r.reopen&&(v=ie(e,P(e)),N=!0),r.delivery==="interactive"&&k(),r.delivery==="interactive"&&!s&&!n.run_id&&R(n))try{return p&&E(e,h),await pe(e,r.body,{cards:[...v===""?[]:[v],...p?[h]:[],...$],origin:d==="human"?{type:"human"}:{type:"runtime",kind:"inbox",entries:[{...d===null?{}:{from:d},...m===void 0?{}:{fromName:m},kind:"message",tier:o}]}}),_(y=>ae(y,t,e,d,null,!1)),Q(e),{status:201,body:{node_id:e,delivered:!0,revived:!1,delivered_via:"engine"}}}catch(a){if(!(a instanceof U))throw a}const T=u(()=>{r.reopen||M(e);const a=ce(16).toString("hex"),y=u(x=>ae(x,t,e,d,a,l!==null),"withinEnqueue");k(a),p&&E(e,h),r.reopen&&!N&&(v=ie(e,P(e)));const O=[...v===""?[]:[v],...$],W=O.length>0?{cards:O}:{};if(g||l!==null){const x=g?r.body:`A one-off structured-output request has been granted. Submit a result matching the requested schema with the \`submit_result\` tool (\`request_id: "${K(e)?.request_id??"<request-id>"}"\`) before you stop; after it is accepted, continue normally.`;return J(e,{senderNodeId:d,...m===void 0?{}:{senderName:m},urgency:o,wake:1,kind:"message",messageId:a,withinEnqueue:y,label:We(x),bodyJson:{body:x,...S,...p?{situational:!0}:{},...W}})}return J(e,{senderNodeId:d,...m===void 0?{}:{senderName:m},urgency:o,wake:1,kind:"message",messageId:a,withinEnqueue:y,label:p?"(ambient context updated)":"(context delivered)",bodyJson:{...p?{situational:!0}:{},situationalOnly:!0,...W}})},"deliverImmediate"),w=u(()=>{if(o==="deferred"){const a=be(e,$e,T);if(a.kind==="missing")throw C(`unknown node: ${e}`,{received:e});if(a.kind==="terminal")throw Le(e,a.status);return a.result}return T()},"deliver")();w.urgency!=="deferred"&&_(()=>Ne(e));const j=A(e);if(j===null)throw C(`unknown node: ${e}`,{received:e});n.frozen_at!==null&&Q(e);let B=!1,z=!1,q;if((r.reopen||j.lifecycle==="terminal"||!je(j))&&w.urgency!=="deferred"&&!s&&!R(j))try{const a=await L(e,{resume:!0,capacity:"freeze"});B=a.launch!==void 0,z=a.outcome==="frozen"}catch(a){q=De(a,w.messageId),Ae({level:"error",event:"message.wake_failed",node_id:e,error:a,fields:{message_id:w.messageId,error_code:q.error}})}return{status:201,body:{node_id:e,delivered:!0,revived:B,...z?{not_revived_reason:"capacity_frozen"}:{},...q===void 0?{}:{wake_failed:q},delivered_at:w.createdAt,...w.urgency===o?{}:{delivered_tier:w.urgency},...r.delivery==="interactive"?{delivered_via:"inbox"}:{}}}}u(Ve,"handleMessageHere");async function Ke(t){const e=t.params.id,i=await Z(t,e,{method:"POST",path:`/v1/nodes/${encodeURIComponent(e)}/interrupt`,body:t.body});if(i.kind==="unknown")throw te(e,i.unreachable);if(i.kind==="remote"){if(i.status>=400)throw ee(i.status,i.body);return{status:i.status,body:re(i.body,i.machine)}}const n=A(e);if(n===null)throw C(`unknown node: ${e}`,{received:e});const r=me(e,{senderNodeId:"human",kind:"message"});let o=!1;if(R(n))try{o=await ye(e)!=="idle"}catch(d){if(!(d instanceof U))throw d}return{status:200,body:{node_id:e,outcome:o?"aborted_turn":r.length>0?"canceled_pending":"idle",aborted_turn:o,canceled_pending:r.length}}}u(Ke,"handleInterrupt");function se(t){if(typeof t.body!="object"||t.body===null||Array.isArray(t.body))throw c("mail requires an object body");const e=t.body;if(typeof e.execution_id!="string"||e.execution_id.trim()==="")throw c("execution_id is required");return e}u(se,"mailBody");function Qe(t){const e=se(t),i=e.channel;if(i!=="wake"&&i!=="passive"&&i!=="deferred_run")throw c("channel must be wake, passive, or deferred_run");const n=ue(t.params.id,e.execution_id,i);return{status:200,body:{action:n.action,deliveries:n.deliveries.map(o=>({delivery_id:o.deliveryId,attempts:o.attempts,handoff:o.handoff,entry:{...fe(o),seq:o.message.seq}}))}}}u(Qe,"handleMailClaim");function Xe(t){const e=se(t);if(!Array.isArray(e.deliveries))throw c("deliveries must be an array");const i=e.deliveries.map(o=>{if(typeof o!="object"||o===null||Array.isArray(o))throw c("each delivery must be an object");const s=o;if(typeof s.delivery_id!="string"||s.delivery_id==="")throw c("delivery_id is required");if(!Number.isSafeInteger(s.attempts)||s.attempts<1)throw c("attempts must be a positive integer");if(s.disposition!=="acknowledged"&&s.disposition!=="released")throw c("disposition must be acknowledged or released");return{delivery_id:s.delivery_id,attempts:s.attempts,disposition:s.disposition}}),n=le(t.params.id,e.execution_id,i.map(o=>({deliveryId:o.delivery_id,attempts:o.attempts,disposition:o.disposition})));return{status:200,body:{action:n.action,results:n.results.map(o=>({delivery_id:o.deliveryId,outcome:o.outcome}))}}}u(Xe,"handleMailAcknowledge");const Tt=Ie([{method:"POST",pattern:"/v1/nodes/:id/mail/claim",handler:Qe},{method:"POST",pattern:"/v1/nodes/:id/mail/acknowledge",handler:Xe}]),Bt=[{method:"POST",pattern:"/v1/nodes/:id/messages",scope:"crtr:act",handler:He},{method:"POST",pattern:"/v1/nodes/:id/interrupt",scope:"crtr:act",handler:Ke}];export{Tt as brokerMailRoutes,He as handleMessage,Bt as messageRoutes};
1
+ var de=Object.defineProperty;var u=(t,e)=>de(t,"name",{value:e,configurable:!0});import{randomBytes as ce}from"node:crypto";import{claimNodeMail as ue,acknowledgeNodeMail as le}from"../../../core/canvas/deliveries.js";import{nodeMailEntry as fe}from"../../../core/feed/inbox.js";import{enqueueNodeMail as J,cancelPendingNodeMail as me}from"../../../core/feed/messages.js";import{reviveNode as L}from"../../../core/runtime/revive.js";import{BrokerUnreachableError as U}from"../../../core/runtime/broker-request.js";import{isBrokerLive as R}from"../../../core/runtime/model-swap.js";import{deliverLive as pe,interruptLive as ye}from"../../../core/runtime/interactive-deliver.js";import{isProfilePaused as he}from"../../../core/profiles/manifest.js";import{getNode as O,withFreshTerminalGuard as be}from"../../../core/canvas/canvas.js";import{getById as D,nodeObject as F,ownerForGrantee as we}from"../../../core/graph/objects.js";import{recordActedOn as ge}from"../../../core/graph/edges.js";import{recordWatch as G}from"../../../core/graph/watches.js";import{publish as H}from"../../../core/graph/events.js";import{readerFor as V}from"../reader.js";import{canRead as ve}from"../../../core/graph/access.js";import{withCanvasWrite as _}from"../../../core/canvas/db.js";import{getPendingStructuredRequestForNode as K}from"../../../core/canvas/structured-requests.js";import{cancelCronsOnWake as Q}from"../../../core/canvas/crons.js";import{assertNotFinalized as M,assertFinalizedForReopen as _e,commitReopenResident as P}from"../../../core/runtime/reopen.js";import{admitLegacyStructuredOutput as ke}from"../../structured-requests/sidecar.js";import{assertOutputSchemaAccepted as Se}from"../../../core/runtime/structured-output.js";import{appendSituationalContext as E,formatSituationalProse as $e}from"../../../core/runtime/situational-context.js";import{formatDataCard as X}from"../../../shared/generated-context.js";import{hasNoNaturalCycle as Ne}from"../../../core/runtime/revive-all.js";import{recordPendingParkActivity as je}from"../../park-pending.js";import{wantsExecution as Ae}from"../../reconcilers/node-lifecycle/wants-execution.js";import{hasFreshGroundState as qe}from"../../../core/runtime/revive.js";import{CrtrError as Oe,notFound as x,usage as c}from"../../../core/errors.js";import{emitEvent as xe}from"../../../core/events/emit.js";import{assertScope as Ce}from"../../../core/scopes.js";import{InputError as I}from"../../../core/io.js";import{ApiError as Re}from"../../../api/index.js";import{describeObject as Fe,stubOf as Me}from"../../../core/peer/stubs.js";import{machineNameOf as Y}from"../../../core/peer/names.js";import{callerNode as Pe,callerStub as Ee,forwardVerb as Z,relayError as ee,remoteStub as Ie,unknownError as te,withMachine as re}from"../../peer/forward.js";import{ownerOnly as Te}from"../router.js";const Be=["critical","urgent","normal","deferred"];function ne(t,e){if(typeof t!="object"||t===null||Array.isArray(t))throw c(`${e} must be an object { kind, facts?, body? }`);const i=t,n=i.kind;if(typeof n!="string"||n.trim()==="")throw c(`${e}.kind is required`);if(!n.includes(":"))throw c(`${e}.kind must be namespaced (contain ':'): ${n}`);const r={kind:n},o=i.facts;if(o!==void 0){if(typeof o!="object"||o===null||Array.isArray(o))throw c(`${e}.facts must be an object of string or number values`);const d={};for(const[f,m]of Object.entries(o)){if(typeof m!="string"&&typeof m!="number")throw c(`${e}.facts.${f} must be a string or number`);d[f]=m}r.facts=d}const s=i.body;if(s!==void 0){if(typeof s!="string")throw c(`${e}.body must be a string`);r.body=s}return r}u(ne,"parseCardRequest");function oe(t,e){try{return X(t.kind,t.facts??{},t.body??"")}catch(i){throw c(`${e}: ${i instanceof Error?i.message:String(i)}`)}}u(oe,"renderCard");function ze(t){if(typeof t!="object"||t===null)throw c("a message requires a JSON body { body, tier?, fresh? }");const e=t,i=e.body,n=e.fresh===!0,r=e.tier,o=e.situational_context,s=e.output_schema,d=typeof i=="string"&&i.trim()!=="",f=typeof o=="string"&&o.trim()!=="",m=typeof s=="string"&&s.trim()!=="",S=e.situational_card,g=e.context_cards,h=S===void 0?void 0:ne(S,"situational_card");if(g!==void 0&&!Array.isArray(g))throw c("context_cards must be an array of { kind, facts?, body? }");const p=g?.map((k,N)=>ne(k,`context_cards[${N}]`));if(h!==void 0&&typeof o=="string"&&o!=="")throw c("situational_card and situational_context are mutually exclusive");const $=h!==void 0||p!==void 0&&p.length>0;if(!n&&!d&&!f&&!m&&!$)throw c("a message requires a non-empty body (or fresh: true, situational_context, a runtime card, or output_schema)");if(n&&p!==void 0&&p.length>0)throw c("context_cards cannot ride a fresh revive (no inbox entry carries them)");if(r!==void 0&&!Be.includes(r))throw c(`invalid tier: ${String(r)} (expected critical|urgent|normal|deferred)`);const l={body:typeof i=="string"?i:""};r!==void 0&&(l.tier=r),n&&(l.fresh=!0),e.reopen===!0&&(l.reopen=!0),typeof o=="string"&&(l.situational_context=o),h!==void 0&&(l.situational_card=h),p!==void 0&&(l.context_cards=p),typeof s=="string"&&(l.output_schema=s),typeof e.from=="string"&&(l.from=e.from);const b=e.delivery;if(b!==void 0&&b!=="interactive")throw c(`invalid delivery: ${String(b)} (expected interactive)`);if(b==="interactive"){if(n||l.situational_context!==void 0||l.output_schema!==void 0)throw c("interactive delivery supports a body, runtime cards, and reopen only (no fresh, situational_context, or output_schema)");if(!d)throw c("interactive delivery requires a non-empty body");if(l.tier==="deferred")throw c("interactive delivery cannot be deferred");l.delivery="interactive"}return l}u(ze,"parseSendBody");function We(t){let e;try{e=JSON.parse(t)}catch{throw c("output_schema must be a JSON schema string")}if(typeof e!="object"||e===null||Array.isArray(e))throw c("output_schema must be a JSON schema object");return e}u(We,"parseSchema");function Je(t){return t.split(`
2
+ `)[0].slice(0,120)}u(Je,"label");function ie(t,e){return e===null?"":X("reopen-final-report",{report:`${t}/${e}`},"This node previously completed work. Read this final report before acting on the new instruction.")}u(ie,"previousFinalReportCard");function Le(t,e,i){if(i!==null&&i!=="human"&&D(t,i)?.type==="node"){const o=F(t,i);return{actor:o,senderNode:o}}if(i==="human")return{actor:we(t,"user:local"),senderNode:null};const n=V(t,e);return{actor:n.class==="person"?n.person:n.class==="app"?n.app:n.node,senderNode:n.class==="node"?n.node:null}}u(Le,"messageActor");function ae(t,e,i,n,r,o){const s=F(t,i),{actor:d,senderNode:f}=Le(t,e,n),m=r===null?{}:{pointer:r};ge(t,d,s),f!==null&&f.rowid!==s.rowid&&G(t,f,s,"message",{endsOn:o&&r!==null?`result:${r}`:"final"}),H(t,{event:"messaged",object:s,actor:d,attrs:{},...m}),f!==null&&H(t,{event:"sent",object:f,actor:f,attrs:{to:s.id},...m})}u(ae,"recordMessage");function Ue(t,e){return new I({error:"deferred_no_natural_cycle",message:`${t} is ${e} with no natural next cycle ahead of it \u2014 a deferred message would never be delivered.`,next:"Use --tier normal, urgent, or critical to wake it now, or --reopen (with a body or --fresh) to re-task it first."})}u(Ue,"deferredNoNaturalCycle");function De(t){if(!qe(t))throw new Re(422,"unprocessable",`node ${t} has no goal/roadmap on disk \u2014 a fresh revive would resume amnesiac.`)}u(De,"assertRecoverableForFresh");function Ge(t,e){return t instanceof I?{error:t.payload.error,message:t.payload.message,next:t.payload.next,message_id:e}:t instanceof Oe?{error:t.code,message:t.message,message_id:e}:{error:"wake_failed",message:"the target could not be woken; see the daemon log",message_id:e}}u(Ge,"wakeFailure");async function He(t,e){const i=typeof t.body=="object"&&t.body!==null&&!Array.isArray(t.body)?{...t.body}:t.body;typeof i=="object"&&i!==null&&delete i.from;const n=await Z(t,e,{method:"POST",path:`/v1/nodes/${encodeURIComponent(e)}/messages`,body:i});if(n.kind==="local")return null;if(n.kind==="unknown")throw te(e,n.unreachable);if(n.status>=400)throw ee(n.status,n.body);return _(r=>{const o=Pe(r,t);if(o===null)return;const s=n.body?.object,d=Ie(r,e,"node",n.machine.id,s);G(r,o,d,"message",{endsOn:"final"})}),{status:n.status,body:re(n.body,n.machine)}}u(He,"forwardMessage");async function Ve(t){const e=await Ke(t);if(t.principal.class!=="forwarded"||typeof e.body!="object"||e.body===null)return e;const i=_(n=>{const r=F(n,t.params.id);return ve(n,V(n,t),r)?Fe(n,r):{id:r.id,type:r.type,kind:null,name:r.id,owner:null}});return{...e,body:{...e.body,object:i}}}u(Ve,"handleMessage");async function Ke(t){const e=t.params.id,i=await He(t,e);if(i!==null)return i;const n=O(e);if(n===null)throw x(`unknown node: ${e}`,{received:e});const r=ze(t.body),o=r.tier??"normal",s=he(n.profile_id),d=t.principal.class==="forwarded"?_(a=>Ee(a,t)?.id??null):r.from??null;if(d!==null){const a=O(d);a!==null&&Ce(a,"crtr:act")}const f=d===null?null:_(a=>{const y=D(a,d);return y===null?null:Me(a,y)?.home_machine??null}),m=f===null?void 0:`${d} on ${Y(f)}`,S=f===null?{}:{from_machine:Y(f)},g=r.body.trim()!=="",h=r.situational_card!==void 0?oe(r.situational_card,"situational_card"):r.situational_context!==void 0?$e(r.situational_context.trim()):"",p=h!=="",$=(r.context_cards??[]).map((a,y)=>oe(a,`context_cards[${y}]`)),l=r.output_schema!==void 0&&r.output_schema.trim()!==""?We(r.output_schema):null;l!==null&&await Se(l);let b=!1;const k=u(a=>{if(!(l===null||b)){if(K(e)!==null)throw new I({error:"structured_request_conflict",message:`node ${e} already has a pending structured request`,next:"Wait for the current request to settle before requesting another structured result."});ke(e,"oneoff",l,a),b=!0}},"ensureSchema");if(r.fresh){const a=r.reopen?_e(e):null;r.reopen||M(e),De(e),k(),p&&E(e,h),r.reopen&&P(e,a);const y=await L(e,{resume:!1,capacity:"refuse"});return{status:201,body:{node_id:e,delivered:!1,revived:y.launch!==void 0}}}r.delivery==="interactive"&&!r.reopen&&M(e);let N=!1,v="";if(r.delivery==="interactive"&&r.reopen&&(v=ie(e,P(e)),N=!0),r.delivery==="interactive"&&k(),r.delivery==="interactive"&&!s&&!n.run_id&&R(n))try{return p&&E(e,h),await pe(e,r.body,{cards:[...v===""?[]:[v],...p?[h]:[],...$],origin:d==="human"?{type:"human"}:{type:"runtime",kind:"inbox",entries:[{...d===null?{}:{from:d},...m===void 0?{}:{fromName:m},kind:"message",tier:o}]}}),_(y=>ae(y,t,e,d,null,!1)),Q(e),{status:201,body:{node_id:e,delivered:!0,revived:!1,delivered_via:"engine"}}}catch(a){if(!(a instanceof U))throw a}const T=u(()=>{r.reopen||M(e);const a=ce(16).toString("hex"),y=u(q=>ae(q,t,e,d,a,l!==null),"withinEnqueue");k(a),p&&E(e,h),r.reopen&&!N&&(v=ie(e,P(e)));const C=[...v===""?[]:[v],...$],W=C.length>0?{cards:C}:{};if(g||l!==null){const q=g?r.body:`A one-off structured-output request has been granted. Submit a result matching the requested schema with the \`submit_result\` tool (\`request_id: "${K(e)?.request_id??"<request-id>"}"\`) before you stop; after it is accepted, continue normally.`;return J(e,{senderNodeId:d,...m===void 0?{}:{senderName:m},urgency:o,wake:1,kind:"message",messageId:a,withinEnqueue:y,label:Je(q),bodyJson:{body:q,...S,...p?{situational:!0}:{},...W}})}return J(e,{senderNodeId:d,...m===void 0?{}:{senderName:m},urgency:o,wake:1,kind:"message",messageId:a,withinEnqueue:y,label:p?"(ambient context updated)":"(context delivered)",bodyJson:{...p?{situational:!0}:{},situationalOnly:!0,...W}})},"deliverImmediate"),w=u(()=>{if(o==="deferred"){const a=be(e,Ne,T);if(a.kind==="missing")throw x(`unknown node: ${e}`,{received:e});if(a.kind==="terminal")throw Ue(e,a.status);return a.result}return T()},"deliver")();w.urgency!=="deferred"&&_(()=>je(e));const j=O(e);if(j===null)throw x(`unknown node: ${e}`,{received:e});n.frozen_at!==null&&Q(e);let B=!1,z=!1,A;if((r.reopen||j.lifecycle==="terminal"||!Ae(j))&&w.urgency!=="deferred"&&!s&&!R(j))try{const a=await L(e,{resume:!0,capacity:"freeze"});B=a.launch!==void 0,z=a.outcome==="frozen"}catch(a){A=Ge(a,w.messageId),xe({level:"error",event:"message.wake_failed",node_id:e,error:a,fields:{message_id:w.messageId,error_code:A.error}})}return{status:201,body:{node_id:e,delivered:!0,revived:B,...z?{not_revived_reason:"capacity_frozen"}:{},...A===void 0?{}:{wake_failed:A},delivered_at:w.createdAt,...w.urgency===o?{}:{delivered_tier:w.urgency},...r.delivery==="interactive"?{delivered_via:"inbox"}:{}}}}u(Ke,"handleMessageHere");async function Qe(t){const e=t.params.id,i=await Z(t,e,{method:"POST",path:`/v1/nodes/${encodeURIComponent(e)}/interrupt`,body:t.body});if(i.kind==="unknown")throw te(e,i.unreachable);if(i.kind==="remote"){if(i.status>=400)throw ee(i.status,i.body);return{status:i.status,body:re(i.body,i.machine)}}const n=O(e);if(n===null)throw x(`unknown node: ${e}`,{received:e});const r=me(e,{senderNodeId:"human",kind:"message"});let o=!1;if(R(n))try{o=await ye(e)!=="idle"}catch(d){if(!(d instanceof U))throw d}return{status:200,body:{node_id:e,outcome:o?"aborted_turn":r.length>0?"canceled_pending":"idle",aborted_turn:o,canceled_pending:r.length}}}u(Qe,"handleInterrupt");function se(t){if(typeof t.body!="object"||t.body===null||Array.isArray(t.body))throw c("mail requires an object body");const e=t.body;if(typeof e.execution_id!="string"||e.execution_id.trim()==="")throw c("execution_id is required");return e}u(se,"mailBody");function Xe(t){const e=se(t),i=e.channel;if(i!=="wake"&&i!=="passive"&&i!=="deferred_run")throw c("channel must be wake, passive, or deferred_run");const n=ue(t.params.id,e.execution_id,i);return{status:200,body:{action:n.action,deliveries:n.deliveries.map(o=>({delivery_id:o.deliveryId,attempts:o.attempts,handoff:o.handoff,entry:{...fe(o),seq:o.message.seq}}))}}}u(Xe,"handleMailClaim");function Ye(t){const e=se(t);if(!Array.isArray(e.deliveries))throw c("deliveries must be an array");const i=e.deliveries.map(o=>{if(typeof o!="object"||o===null||Array.isArray(o))throw c("each delivery must be an object");const s=o;if(typeof s.delivery_id!="string"||s.delivery_id==="")throw c("delivery_id is required");if(!Number.isSafeInteger(s.attempts)||s.attempts<1)throw c("attempts must be a positive integer");if(s.disposition!=="acknowledged"&&s.disposition!=="released")throw c("disposition must be acknowledged or released");return{delivery_id:s.delivery_id,attempts:s.attempts,disposition:s.disposition}}),n=le(t.params.id,e.execution_id,i.map(o=>({deliveryId:o.delivery_id,attempts:o.attempts,disposition:o.disposition})));return{status:200,body:{action:n.action,results:n.results.map(o=>({delivery_id:o.deliveryId,outcome:o.outcome}))}}}u(Ye,"handleMailAcknowledge");const zt=Te([{method:"POST",pattern:"/v1/nodes/:id/mail/claim",handler:Xe},{method:"POST",pattern:"/v1/nodes/:id/mail/acknowledge",handler:Ye}]),Wt=[{method:"POST",pattern:"/v1/nodes/:id/messages",scope:"crtr:act",handler:Ve},{method:"POST",pattern:"/v1/nodes/:id/interrupt",scope:"crtr:act",handler:Qe}];export{zt as brokerMailRoutes,Ve as handleMessage,Wt as messageRoutes};
@@ -1 +1 @@
1
- var Se=Object.defineProperty;var a=(e,t)=>Se(e,"name",{value:t,configurable:!0});import{prepared as X}from"../../../core/sqlite-statements.js";import{envProfileId as Re}from"../../../shared/env.js";import{pausedCanvasProfiles as Oe}from"../../../core/profiles/manifest.js";import{existsSync as A,realpathSync as Z,statSync as q}from"node:fs";import{isAbsolute as F,resolve as T}from"node:path";import{appendSituationalContext as Ie,formatSituationalProse as $e}from"../../../core/runtime/situational-context.js";import{closeNode as Ce}from"../../../core/runtime/close.js";import{reviveNode as Ne}from"../../../core/runtime/revive.js";import{nowIso as G}from"../../../core/fs-utils.js";import{assertLaunchModelRegistered as B,forkNode as Ae,resolveForkSource as Te,spawnChildPrepared as Ee}from"../../../core/runtime/spawn.js";import{forkSourceNode as Pe,newNodeId as ee}from"../../../core/runtime/nodes.js";import{abandonCreateRequest as ne,childrenOf as De,completeCreateRequest as te,findCreateRequest as Le,getNode as k,recordCreateRequestNode as Me,reserveCreateRequest as oe,reserveCreateRequestNode as je,listNodes as re,recordRespawnAttempt as Fe,subscribersOf as Ge,subscriptionsOf as ie,setMessageWait as Be,updateNode as N}from"../../../core/canvas/canvas.js";import{subtreeIds as Ke}from"../../../core/canvas/nav-model.js";import{withCanvasWrite as K}from"../../../core/canvas/db.js";import{nodeObject as xe}from"../../../core/graph/objects.js";import{recordActedOn as We}from"../../../core/graph/edges.js";import{publish as Ve}from"../../../core/graph/events.js";import{readerFor as ze}from"../reader.js";import{relocateSessionCwd as Je,unbindSession as Ue}from"../../../core/canvas/sessions.js";import{ticketCountsForNodes as He}from"../../../core/canvas/attention.js";import{isSafeNodeId as Ye}from"../../../core/canvas/paths.js";import{contextDir as de,nodeAgentDir as x}from"../../../core/canvas/node-agent-paths.js";import{checkCronBirth as Qe}from"../../cron/authority.js";import{cronBirthPlacement as Xe}from"../../cron/armed-context.js";import{existsBeneath as Ze,isAbsentOrRefused as qe,isBeneathRefusal as en,readdirBeneath as nn}from"../../../core/spaces/open-beneath.js";import{readNodeMessagesPage as tn,readNodeSession as on,readNodeSnapshot as rn,transcriptMarkdown as dn}from"../../../core/runtime/node-read.js";import{assembleNodeSubject as sn}from"../../../core/substrate/subject.js";import{reviveAll as an}from"../../../core/runtime/revive-all.js";import{promoteAsync as ln,requestYieldAsync as cn,reshapeNodeAsync as W}from"../../../core/runtime/promote.js";import{recycleNode as fn}from"../../../core/runtime/recycle.js";import{relaunchRoot as un}from"../../../core/runtime/reset.js";import{assertReopenGate as pn}from"../../../core/runtime/reopen.js";import{writeYieldMessage as mn,readGoal as hn}from"../../../core/runtime/kickoff.js";import{ensureRoadmap as wn,hasRoadmap as yn}from"../../../core/runtime/roadmap.js";import{renameWindow as _n}from"../../../core/runtime/placement.js";import{buildLaunchSpecAsync as gn,explicitModelIntent as bn,normalizeModel as vn,readMergedLaunchConfigAsync as se}from"../../../core/runtime/launch.js";import{modelRequestFromConfig as kn}from"../../../core/model-routes.js";import{persistDormantModel as Sn,setModelLive as Rn}from"../../../core/runtime/model-swap.js";import{waitForBrokerViewSocket as On}from"../../../core/runtime/view-socket.js";import{BrokerUnreachableError as In}from"../../../core/runtime/broker-request.js";import{boundFleet as V}from"../../../core/runtime/fleet.js";import{admitLegacyStructuredOutput as $n}from"../../structured-requests/sidecar.js";import{OUTCOME_PAYLOAD_MAX_BYTES as ae}from"../../../core/canvas/types.js";import{HUMAN_ACTION_NAME_PATTERN as Cn}from"../../../core/human/action-binding.js";import{resolveHumanAction as Nn}from"../../../core/human-actions.js";import{parseDurationMs as An}from"../../../core/wake.js";import{claimWarmNode as Tn,refillWarmPool as le,resumeWarmClaim as En,warmPoolEnabled as Pn}from"../../../core/runtime/warm-pool.js";import{assertLaunchKind as z,isLaunchKind as Dn,resolveLaunchTarget as Ln}from"../../../core/runtime/launch-target.js";import{fullName as Mn}from"../../../core/canvas/labels.js";import{reportsForNode as ce}from"./reports.js";import{requireUsableProfile as jn}from"./profiles.js";import{assertProfileActive as Fn,loadExactProfileManifest as Gn}from"../../../core/profiles/manifest.js";import{getCron as fe}from"../../../core/canvas/crons.js";import{cronWakeOrigin as Bn}from"../../../core/runtime/bearings.js";import{boundDaemonControl as Kn}from"../../control.js";import{notFound as E,usage as h}from"../../../core/errors.js";import{assertScope as xn,validateScopes as ue}from"../../../core/scopes.js";import{scopeAllowed as O}from"../../../shared/env.js";import{toCloseResultDTO as Wn,toNodeDetailDTO as J,toNodeSummaryDTO as Vn,toReviveResultDTO as zn}from"../map.js";import{ApiError as m}from"../../../api/index.js";import{InputError as w}from"../../../core/io.js";import{brokerMayReach as U,canReadNode as pe,resolvedScopes as Jn}from"../router.js";import{forwardVerb as Un,queryWithoutMachine as Hn,relayError as Yn,unknownError as Qn,withMachine as Xn}from"../../peer/forward.js";import{fileRoot as Zn}from"../../../core/spaces/file-root.js";import{activeGrant as qn,terminalGrant as et}from"../../../core/grants/mirror.js";import{readConfig as nt}from"../../../core/config.js";import{hasConfiguredProviderCredential as tt,NO_PROVIDER_CREDENTIAL_MESSAGE as me}from"../../../core/runtime/provider-credential-gate.js";function y(e){const t=k(e);if(t===null)throw E(`unknown node: ${e}`,{received:e});return t}a(y,"requireMeta");function H(e){return{subscribesTo:ie(e),subscribers:Ge(e),children:De(e)}}a(H,"edgesFor");function g(e){const t=y(e);return J(t,H(e))}a(g,"detailOf");function ot(e){let t=ce(e).length;try{t+=nn(x(e),de(e)).length}catch(n){if(!qe(n))throw n}return t}a(ot,"countFiles");function rt(e){if(typeof e!="object"||e===null)throw h("a node create requires a JSON body");const t=e;if(t.kind!==void 0&&(typeof t.kind!="string"||t.kind.trim()===""))throw h("kind must be a non-empty string when provided");if(t.description!==void 0&&(typeof t.description!="string"||t.description.trim()===""))throw h("description must be a non-empty string when provided");if(t.creator!==void 0&&(typeof t.creator!="string"||t.creator.trim()===""))throw h("creator must be a non-empty node id when provided");if(t.scopes!==void 0&&ue(t.scopes),t.isolated!==void 0&&typeof t.isolated!="boolean")throw new m(400,"invalid_request","isolated must be a boolean",{param:"isolated"});const n=t.root_lifecycle;if(n!==void 0&&n!=="resident"&&n!=="terminal")throw h("root_lifecycle must be 'resident' or 'terminal'");if(t.request_key!==void 0&&(typeof t.request_key!="string"||t.request_key.trim()===""||t.request_key.length>128))throw h("request_key must be a non-empty string of at most 128 characters when provided");return t}a(rt,"parseCreateBody");function it(e){if(e===void 0)return;const t=An(e),n=t===null?null:new Date(Date.now()+t);if(t===null||!Number.isFinite(t)||t<=0||n===null||!Number.isFinite(n.getTime()))throw new m(422,"invalid_deadline","`deadline` must be a positive representable duration");return n.toISOString()}a(it,"parseDeadline");function dt(e){if(e!==void 0){if(typeof e!="object"||e===null||Array.isArray(e))throw new m(400,"invalid_request","`outcome_delivery` must be an object");if(typeof e.action!="string"||!Cn.test(e.action))throw new m(400,"invalid_request","`outcome_delivery.action` must be a declared action name");if(e.payload!==void 0){let t;try{t=JSON.stringify(e.payload)}catch{throw new m(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable")}if(t===void 0)throw new m(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable");if(Buffer.byteLength(t,"utf8")>ae)throw new m(413,"payload_too_large",`serialized payload exceeds ${ae} bytes`)}return e}}a(dt,"parseOutcomeDelivery");function st(e,t){const n=Nn(e.action,t);if(!("kind"in n))return{actionName:e.action,argv:n.argv,cwd:n.cwd,configOrigin:n.configOrigin,...e.payload===void 0?{}:{payload:e.payload}};throw n.kind==="unknown_action"?new m(422,"unknown_action",`no action named ${e.action} is declared from ${t}`):new m(422,"invalid_action",`${e.action} is declared in ${n.configOrigin} but unusable: ${n.reason}`,{reason:n.reason,configOrigin:n.configOrigin})}a(st,"resolveOutcomeDelivery");function at(e,t,n){const r={kind:e.kind,cwd:n,prompt:e.prompt??""};return e.mode!==void 0&&(r.mode=e.mode),e.name!==void 0&&(r.name=e.name),e.description!==void 0&&(r.description=e.description),t!==void 0&&(r.parent=t),e.creator!==void 0&&(r.creator=e.creator),e.scopes!==void 0&&(r.scopes=e.scopes),e.isolated!==void 0&&(r.isolated=e.isolated),e.root===!0&&(r.root=!0),e.root_lifecycle!==void 0&&(r.rootLifecycle=e.root_lifecycle),(e.worktree===!0||typeof e.worktree=="string")&&(r.worktree=!0),typeof e.worktree=="string"&&(r.worktreeBase=e.worktree),e.worktree!==void 0&&(r.worktreeCwd=T(e.pin_cwd??e.cwd??n)),e.fork_from!==void 0&&(r.forkFrom=e.fork_from),e.model!==void 0&&(r.model=e.model),e.profile!==void 0&&(r.profile=e.profile),e.situational_context!==void 0&&(r.situationalContext=e.situational_context),e.node_id!==void 0&&(r.nodeId=e.node_id),r}a(at,"buildRecipe");function lt(e,t,n){return!Pn()||e.prefer_warm!==!0||e.root!==!0||e.parent!=null||e.root_lifecycle==="terminal"||(e.prompt??"")!==""||e.model!==void 0||e.fork_from!==void 0||e.worktree!==void 0||e.node_id!==void 0||e.scopes!==void 0||e.isolated!==void 0?null:{kind:e.kind,mode:e.mode??"base",cwd:t,profileId:n,model:e.model??null,situationalContext:e.situational_context??null,name:e.name??null,creator:e.creator??null}}a(lt,"warmRequestFor");import{resolveCreateKind as tr}from"../../../core/runtime/launch-target.js";function he(e){const t=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return kn(e.model,t,e.modelExact===!0)}a(he,"requestFromLaunch");function ct(e,t){if(t===null)return e;if(e.scopes===void 0)return{...e,scopes:[...t]};const n=e.scopes.filter(r=>!O(t,r));if(n.length===0)return e;throw new m(403,"scope_denied",`scopes exceed the bearer token's ceiling: ${n.join(", ")}`,{scopes:n,ceiling:t})}a(ct,"withinCeiling");async function we(e,t,n){const r=(await gn(t.kind,t.mode,{lifecycle:t.lifecycle,hasManager:e.parent!==null,model:t.model,modelOverride:!0,cwd:e.cwd,profileId:e.profile_id??null})).launch;await B(he(r),{cwd:e.cwd,profileId:e.profile_id??null},n)}a(we,"assertNodeModelChangeRegistered");function ye(e,t){const n=e.principal;if(n.class!=="broker"&&n.class!=="cron")return;const r=Zn({app:n.app,resolved:Jn(n),launched:n.scopes},t,"read");if("root"in r)return;const o="missing"in r?r.missing:null;throw new m(403,"scope_missing",o?`the child's directory ${t} needs missing scope ${o}`:`no permission of this run names the child's directory ${t}`,void 0,void 0,o?{scope:o}:void 0)}a(ye,"assertCallerReaches");const Y=new Map;async function ft(e,t={},n={}){const r=ct(rt(e.body),e.ceiling);if(e.principal.class==="broker"){const l=e.principal;if(r.prefer_warm===!0&&l.app!=="app:terminal"&&(r.prefer_warm=!1),r.parent!=null){const i=y(r.parent);if(i.grantee!==l.app)throw new m(403,"other_app_run","cannot create a child under another app's node");if(!U(l,r.parent,i.grantee??"app:terminal"))throw E(`unknown node: ${r.parent}`,{received:r.parent})}if(r.creator!==void 0&&r.creator!==l.node)throw new m(403,"other_app_run","cannot create for another node");if(r.fork_from!==void 0){let i=null;try{i=Pe(Te(r.fork_from))}catch{}if(i?.grantee!==l.app||!U(l,i.node_id,i.grantee))throw new m(403,"other_app_run","cannot fork another app's conversation")}r.creator=l.node}if(e.principal.class==="cron"){const l=e.principal;for(const c of["parent","creator","fork_from","node_id"])if(r[c]!=null)throw new m(403,"permission_error",`a cron cannot set ${c} on a node it starts`);r.prefer_warm=!1;const i=Qe({grantee:l.app,sub:l.sub,grant_id:l.grant,scopes:l.scopes});if(!i.allowed)throw new m(i.reason==="scope_missing"?403:401,i.reason==="scope_missing"?"scope_missing":"grant_revoked",i.message);if(r.scopes!==void 0){const c=r.scopes.find(p=>!O(i.effectiveScopes,p)||!O(l.scopes,p));if(c!==void 0)throw new m(403,"scope_missing",`scope ${c} is not held by this cron`,void 0,void 0,{scope:c})}else l.scopes!==null&&(r.scopes=[...l.scopes]);r.node_id=ee(),l.isolated&&(r.isolated=!0,r.cwd=x(r.node_id,l.app))}r.creator!==void 0&&xn(y(r.creator),"crtr:act");const o=r.request_key?.trim();if(o===void 0||r.node_id!==void 0&&Ye(r.node_id)&&k(r.node_id)!==null&&Le(o)?.nodeId!==r.node_id)return P(e,r,t,n);const d=Y.get(o);if(d!==void 0)return d;const s=ut(e,r,o,t,n);Y.set(o,s);try{return await s}finally{Y.delete(o)}}a(ft,"handleCreate");async function ut(e,t,n,r,o){const d=oe(n);if(d.nodeId!==null&&k(d.nodeId)!==null){if(d.state!=="warm_claimed"){const s=k(d.nodeId);if(e.principal.class!=="person"&&!pe(e.principal,s.grantee??"app:terminal",d.nodeId))throw new m(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:g(d.nodeId)}}return P(e,t,r,o,d)}try{return await P(e,t,r,o,d)}catch(s){const l=oe(n);throw(l.nodeId===null||k(l.nodeId)===null)&&ne(n,l.nodeId),s}}a(ut,"handleKeyedCreateRequest");async function P(e,t,n,r,o=void 0){const d=r.deadlineAt??it(t.deadline),s=dt(t.outcome_delivery),l=e.principal.class==="cron"?Xe({grantee:e.principal.app,sub:e.principal.sub,grant_id:e.principal.grant,scopes:e.principal.scopes,cron_id:e.principal.cron,origin_run_id:e.principal.origin_run,isolated:e.principal.isolated,creator:fe(e.principal.cron)?.created_by??null},t.node_id):null;l!==null&&(t.root=l.root===!0);const i=l?.parent??t.parent??void 0;if(i==null&&t.root!==!0)throw h("a node create requires a parent (or root: true for an independent root)");let c=null;if(t.output_schema!==void 0)try{c=JSON.parse(t.output_schema)}catch{throw h("output_schema must be a JSON schema string")}const{profileId:p,kind:u,cwd:f,launch:_}=await Ln(t,{validateKind:ke});ye(e,f),t.worktree!==void 0&&ye(e,T(t.pin_cwd??t.cwd??f));const S={...t,kind:u},I=s===void 0?void 0:st(s,f);if(await B(he(_),{cwd:f,profileId:p},n.modelRegistry),!await tt(p))throw new m(412,"no_provider_credential",me,{error:"no_provider_credential",message:me,next:"The person running this runtime logs a provider in with `crtr sys setup`, or stores a provider key on the profile."});let L=null;{const $=o===void 0||o.nodeId===null||o.state==="warm_claimed"?lt(S,f,p):null,M=c===null&&r.beforeBrokerLaunch===void 0?void 0:v=>{c!==null&&$n(v,"terminal",c),r.beforeBrokerLaunch?.(v)};if(o?.state==="warm_claimed"&&o.nodeId!==null){const v=$===null?null:await En($,o.nodeId,M);if(v===null)throw ne(o.requestKey,o.nodeId),new m(503,"create_resume_failed",`could not resume warm claim ${o.nodeId}; retry the create`);return te(o.requestKey,v),{status:201,body:g(v)}}if($!==null){const v=await Tn($,{...d===void 0?{}:{deadlineAt:d},...I===void 0?{}:{outcomeDelivery:I},...o===void 0?{}:{requestKey:o.requestKey}},M);if(v!==null)return o!==void 0&&te(o.requestKey,v),le($),{status:201,body:g(v)};L=$}const j=o?.nodeId??t.node_id??(o===void 0?void 0:ee());o!==void 0&&o.nodeId===null&&je(o.requestKey,j);const R=at(j===void 0?S:{...S,node_id:j},i,f);l!==null&&(l.rootLifecycle!==void 0&&(R.rootLifecycle=l.rootLifecycle),l.scopes!==void 0&&S.scopes===void 0&&(R.scopes=l.scopes),l.run!==void 0&&(R.run=l.run),l.withinCreate!==void 0&&(R.withinCreate=l.withinCreate)),d!==void 0&&(R.deadlineAt=d),I!==void 0&&(R.outcomeDelivery=I),R.readiness=t.root===!0?"await":"launch";const Q=await Ee(R,M,()=>{L!==null&&le(L)});return o!==void 0&&Me(o.requestKey,Q.node.node_id),{status:201,body:g(Q.node.node_id)}}}a(P,"handleCreateRequest");function b(e,t){const n=e.query.getAll(t);if(n.length>1)throw h(`${t} must appear at most once`);return n[0]}a(b,"singleQueryValue");function _e(e,t){if(e!==void 0){if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;throw h(`${t} must be true or false`)}}a(_e,"optionalBoolean");function D(e,t,n){if(e!==void 0){if(n.includes(e))return e;throw h(`${t} must be one of: ${n.join(", ")}`)}}a(D,"oneOf");function pt(e){const t=new Set(["status","lifecycle","kind","mode","profile_id","profile_prefix","parent","top_level","under","hanging","include"]);for(const[_]of e.query)if(!t.has(_))throw h(`unknown nodes query parameter: ${_}`);const n=D(b(e,"status"),"status",["active","idle","done","dead","canceled"]),r=D(b(e,"lifecycle"),"lifecycle",["terminal","resident"]),o=b(e,"kind"),d=D(b(e,"mode"),"mode",["base","orchestrator"]),s=b(e,"profile_id"),l=b(e,"profile_prefix"),i=b(e,"parent"),c=_e(b(e,"top_level"),"top_level"),p=b(e,"under"),u=_e(b(e,"hanging"),"hanging"),f=D(b(e,"include"),"include",["activity"]);if(i!==void 0&&c===!0)throw h("parent and top_level=true cannot be combined");return{...n!==void 0?{status:n}:{},...r!==void 0?{lifecycle:r}:{},...o!==void 0?{kind:o}:{},...d!==void 0?{mode:d}:{},...s!==void 0?{profile_id:s}:{},...l!==void 0?{profile_prefix:l}:{},...i!==void 0?{parent:i}:{},...c!==void 0?{top_level:c}:{},...p!==void 0?{under:p}:{},...u!==void 0?{hanging:u}:{},...f!==void 0?{include:f}:{}}}a(pt,"parseListQuery");function mt(e){const t=pt(e);let n=t.status!==void 0?re({status:t.status}):re();if(e.principal.class!=="person"&&(n=n.filter(s=>pe(e.principal,s.grantee??"app:terminal",s.node_id))),t.lifecycle!==void 0&&(n=n.filter(s=>s.lifecycle===t.lifecycle)),t.kind!==void 0&&(n=n.filter(s=>s.kind===t.kind)),t.mode!==void 0&&(n=n.filter(s=>s.mode===t.mode)),t.profile_id!==void 0&&(n=n.filter(s=>s.profile_id===t.profile_id)),t.profile_prefix!==void 0&&(n=n.filter(s=>s.profile_id?.startsWith(t.profile_prefix))),t.parent!==void 0&&(n=n.filter(s=>s.parent===t.parent)),t.top_level===!0&&(n=n.filter(s=>s.parent===null)),t.under!==void 0){const s=new Set(Ke(t.under));n=n.filter(l=>s.has(l.node_id))}t.hanging===!0&&(n=n.filter(s=>s.parent!==null&&k(s.parent)===null));const r=t.include==="activity"?He(n.map(s=>s.node_id)):null,o=n.length>0?Oe():new Set;return{status:200,body:n.map(s=>{const l=Vn(s,s.profile_id!==null&&o.has(s.profile_id));if(r!==null){const i=ce(s.node_id);l.activity={latest_report:i[0]??null,final_report:s.final_report===null?null:i.find(c=>c.name===s.final_report)??null,pending_human_count:r[s.node_id]??0}}return l})}}a(mt,"handleList");async function ht(e){const t=e.params.id,n=await Un(e,t,{method:"GET",path:`/v1/nodes/${encodeURIComponent(t)}`,query:Hn(e)});if(n.kind==="unknown")throw Qn(t,n.unreachable);if(n.kind==="remote"){if(n.status>=400)throw Yn(n.status,n.body);return{status:n.status,body:Xn(n.body,n.machine)}}return y(t),{status:200,body:g(t)}}a(ht,"handleDetail");async function wt(e){const t=e.params.id;y(t);const n=await rn(t);return{status:200,body:{node_id:t,snapshot:{messages:n.snapshot.messages,...n.snapshot.messageIds===void 0?{}:{messageIds:n.snapshot.messageIds},messageVisibility:n.snapshot.messageVisibility,turnVisibility:n.snapshot.turnVisibility,stats:n.snapshot.stats,state:n.snapshot.state,display:n.snapshot.display,...n.snapshot.queued===void 0?{}:{queued:n.snapshot.queued},...n.snapshot.toolGroupSummaries===void 0?{}:{toolGroupSummaries:n.snapshot.toolGroupSummaries},...n.snapshot.turnReplies===void 0?{}:{turnReplies:n.snapshot.turnReplies},...n.snapshot.workingActivity===void 0?{}:{workingActivity:n.snapshot.workingActivity}},commands:n.commands.map(o=>({name:o.name,description:o.description,source:o.source})),captured_at:G()}}}a(wt,"handleSnapshot");async function yt(e){const t=e.params.id,n=sn(t);if(n===null)throw E(`unknown node: ${t}`,{received:t});return{status:200,body:n}}a(yt,"handleSubject");function _t(e){for(const[d]of e.query)if(d!=="cursor"&&d!=="limit")throw h(`unknown messages query parameter: ${d}`);const t=e.query.getAll("cursor"),n=e.query.getAll("limit");if(t.length>1)throw h("cursor must appear at most once");if(n.length>1)throw h("limit must appear at most once");if(n.length===0)return t.length===0?{}:{cursor:t[0]};const r=n[0],o=Number(r);if(!Number.isSafeInteger(o)||r==="")throw h("limit must be an integer from 1 through 500");return t.length===0?{limit:o}:{cursor:t[0],limit:o}}a(_t,"parseMessagesQuery");async function gt(e){const t=e.params.id,n=await tn(t,_t(e));return{status:200,body:{node_id:t,messages:n.messages,...n.messageIds===void 0?{}:{message_ids:n.messageIds},message_visibility:n.messageVisibility,next_cursor:n.nextCursor,captured_at:G()}}}a(gt,"handleMessages");function bt(e){const t=e.params.id;y(t);const n=on(t);return{status:200,body:{node_id:t,session_file:n.sessionFile,session_jsonl:n.sessionJsonl,system_prompt:n.systemPrompt,captured_at:G()}}}a(bt,"handleSession");async function vt(e){const t=e.params.id;return y(t),{status:200,body:{node_id:t,markdown:await dn(t)}}}a(vt,"handleTranscript");function kt(e){const t=e.params.id;y(t);const n=a((o,d)=>({node_id:o,label:k(o)?.name??o,dir:de(o),self:d,files:ot(o)}),"root"),r=[n(t,!0),...ie(t).map(o=>n(o.node_id,!1))].filter(o=>St(o.node_id,o.dir)||o.files>0);return{status:200,body:{node_id:t,roots:r}}}a(kt,"handleContext");function St(e,t){try{return Ze(x(e),t)}catch(n){if(en(n))return!1;throw n}}a(St,"hasDir");async function Rt(e){const t=y(e.params.id),n=e.principal.class==="broker"?e.principal.scopes:e.ceiling,r=n===null?void 0:t.scopes==null?[...n]:[...new Set([...t.scopes.filter(d=>O(n,d)),...n.filter(d=>O(t.scopes,d))])],o=await Ae(t.node_id,r,e.principal.class==="broker"?e.principal.node:void 0);return{status:201,body:g(o.node.node_id)}}a(Rt,"handleFork");async function Ot(e){const t=e.params.id;y(t);const n=e.body,r=n?.resume??!0,o=n?.reopen??!1;pn(t,o);const d=!r&&n?.cron_id!==void 0?fe(n.cron_id):null,s=await Ne(t,{resume:r,capacity:"refuse",...d!==null?{wakeReason:Bn(d,"schedule_revive")}:{}});s.outcome!=="already-live"&&Fe(t,{failures:0,notBefore:null});const l=k(t)?.status??"active";return{status:200,body:zn(t,s,l)}}a(Ot,"handleRevive");async function It(e){const t=e.params.id;return{status:200,body:{newNodeId:(await un(t))?.newNodeId??null}}}a(It,"handleRelaunchRoot");function $t(e){const t=e.params.id;y(t);const n=e.body;if(n?.caller_pid!==void 0&&(!Number.isInteger(n.caller_pid)||n.caller_pid<=0))throw h("caller_pid must be a positive integer when provided");const r=Kn(),o=Ce(t,{rootEvent:n?.finish===!0?"finish":"cancel",callerPid:n?.caller_pid,...e.principal.class==="broker"?{closer:e.principal.node}:{},...r===null?{}:{registerDetached:r.registerDetached}});return{status:200,body:Wn(o)}}a($t,"handleClose");async function Ct(e){const t=e.params.id;y(t);const n=await fn(t);return{status:200,body:{recycled:n.recycled,finalized:n.finalized,new_root:n.newRoot,delivered:n.delivered}}}a(Ct,"handleRecycle");async function Nt(e){const t=e.params.id;return y(t),await W(t,{lifecycle:"terminal"}),C(e,t,["lifecycle"]),{status:200,body:g(t)}}a(Nt,"handleDemote");async function At(e,t={}){const n=e.params.id,r=y(n),o=e.body??{};o.kind!==void 0&&await z(o.kind,r.cwd,r.profile_id??null),o.model!==void 0&&await we(r,{kind:o.kind??r.kind,mode:"orchestrator",lifecycle:o.resident===!0?"resident":r.lifecycle,model:o.model},t.modelRegistry);const d=await ln(n,{...o.kind!==void 0?{kind:o.kind}:{},...o.resident===!0?{resident:!0}:{},...o.model!==void 0?{model:o.model}:{}});C(e,n,["mode",...o.kind!==void 0?["kind"]:[],...o.resident===!0?["lifecycle"]:[],...o.model!==void 0?["model"]:[]]);const s=J(d.meta,H(n));return s.roadmap_written=d.roadmapWritten,s.roadmap_ref=d.roadmapRef,s.goal_path=d.goalPath,{status:200,body:s}}a(At,"handlePromote");async function Tt(e,t={}){const n=e.params.id,r=y(n),o=e.body??{};o.kind!==void 0&&await z(o.kind,r.cwd,r.profile_id??null),o.model!==void 0&&await we(r,{kind:o.kind??r.kind,mode:o.promote===!0?"orchestrator":r.mode,lifecycle:r.lifecycle,model:o.model},t.modelRegistry);const d=o.note??"Refresh: continue against your roadmap or goal.";mn(n,d);const s=await cn(n,{...o.promote===!0?{promote:!0}:{},...o.kind!==void 0?{kind:o.kind}:{},...o.model!==void 0?{model:o.model}:{}});return{status:200,body:J(s.meta,H(n))}}a(Tt,"handleYield");function Et(e){const t=e.params.id;y(t);const n=e.body;if(n===void 0||typeof n.controller!="string"||n.controller.trim()==="")throw h("a wait requires a controller node id");const r=k(n.controller);if(r===null)throw E(`unknown controller: ${n.controller}`,{received:n.controller});if(r.status!=="active"&&r.status!=="idle")throw new m(422,"unprocessable",`controller ${n.controller} is ${r.status}`);return Be(t,n.controller),{status:200,body:g(t)}}a(Et,"handleWait");async function Pt(e){const t=e.principal,n=await an(t.class==="broker"?o=>o.grantee===t.app&&U(t,o.node_id,o.grantee):void 0);return{status:200,body:{revived:[...n.revived],failed:[...n.failed],frozen:[...n.frozen]}}}a(Pt,"handleReviveAll");const Dt=new Set(["interrupt","steer","after-turn","next-turn"]);function Lt(e){if(e===null)return null;const t=a(r=>{throw new w({error:"invalid_listen",message:r,received:e,field:"listen",next:'Send an object mapping levels "1".."10" to interrupt|steer|after-turn|next-turn (e.g. {"3":"next-turn"}), or null to reset to the global default.'})},"bad");if(typeof e!="object"||Array.isArray(e))return t("listen must be an object or null");const n=Object.entries(e);if(n.length===0)return t("listen must name at least one level");for(const[r,o]of n)/^(?:[1-9]|10)$/.test(r)||t(`listen level must be 1..10: ${r}`),(typeof o!="string"||!Dt.has(o))&&t(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(o)}`);return JSON.stringify(Object.fromEntries(n))}a(Lt,"listenJson");function C(e,t,n,r){n.length===0&&r===void 0||K(o=>{if(r?.(o),n.length===0)return;const d=xe(o,t),s=ze(o,e),l=s.class==="person"?s.person:s.class==="app"?s.app:s.node;We(o,l,d),Ve(o,{event:"configured",object:d,actor:l,attrs:{changed:n.join(",")}})})}a(C,"recordConfigured");function ge(e){const t=V().get(e);if(t===void 0)return!1;try{return process.kill(t.pid,"SIGTERM"),!0}catch{return!1}}a(ge,"restartLiveBroker");function be(e,t){try{return Z(e)===Z(t)}catch{return!1}}a(be,"sameDirectory");async function Mt(e,t={}){const n=e.params.id,r=e.body;let o;if(r===void 0)o={};else if(typeof r=="object"&&r!==null&&!Array.isArray(r))o=r;else throw new w({error:"cwd_invalid",message:"cwd repair requires a non-null object with a non-empty cwd string",received:r,field:"cwd",next:"Send a config patch with a non-empty absolute cwd string."});if(o.profile!==void 0){if(typeof o.profile!="string"||o.profile==="")throw new w({error:"profile_invalid",message:"profile must be a non-empty profile id or name",received:o.profile,field:"profile",next:"Send a profile id or exact name."});if(Object.keys(o).some(u=>u!=="profile"&&u!=="restart"&&o[u]!==void 0))throw new w({error:"profile_not_exclusive",message:"profile can only be combined with restart",field:"profile",next:"Send profile (and optionally restart) alone."});const i=y(n),c=jn(e,o.profile);Fn(c.profileId);const p=Gn(c.profileId).manifest.grantee??"app:terminal";if(p!==(i.grantee??"app:terminal"))throw new w({error:"profile_grantee_mismatch",message:`profile ${c.profileId} belongs to ${p}, node ${n} to ${i.grantee}`,received:o.profile,field:"profile",next:"Pick a profile owned by the same app as the node."});return(i.profile_id??null)!==c.profileId&&(Dn(i.kind)?(await z(i.kind,i.cwd,c.profileId),await W(n,{profileId:c.profileId})):N(n,{profile_id:c.profileId}),C(e,n,["profile"])),o.restart===!0&&ge(n),{status:200,body:g(n)}}if(Object.prototype.hasOwnProperty.call(o,"cwd")){const i=o.cwd;if(typeof i!="string"||i==="")throw new w({error:"cwd_invalid",message:"cwd must be a non-empty string",received:i,field:"cwd",next:"Send a non-empty absolute cwd string."});if(Object.keys(o).some(f=>f!=="cwd"&&f!=="keep_session"&&f!=="restart"&&o[f]!==void 0))throw new w({error:"cwd_not_exclusive",message:"cwd repair cannot be combined with another config field",received:o,field:"cwd",next:"Send cwd as the only config field."});const c=y(n),p=A(c.cwd);if(o.keep_session===!0||p&&F(i)&&A(i)&&be(c.cwd,i)){if(!F(i))throw new w({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${i}`,received:i,field:"cwd",next:"Send an absolute path."});const f=T(i);let _=!1;try{_=q(f).isDirectory()}catch{}if(!_)throw new w({error:"cwd_missing",message:`cwd is not an existing directory: ${f}`,received:i,field:"cwd",next:"Send an existing absolute directory."});if(p&&!be(c.cwd,f))throw new w({error:"cwd_not_same_directory",message:`${f} is not the same directory as the recorded ${c.cwd}; --keep-session only relocates an alias`,received:i,field:"cwd",next:"Drop --keep-session to repair a gone cwd, or pass the real path of the recorded directory."});if(c.managed_worktree?.state==="open")throw new w({error:"cwd_node_managed_worktree_open",message:`${n} owns an open managed worktree and cannot relocate its cwd`,received:i,field:"cwd",next:"Reconcile the managed worktree first."});const S=c.cwd;return S!==f&&(K(I=>{N(n,{cwd:f}),X(I,"UPDATE crons SET cwd = ? WHERE anchor_node = ? AND cwd = ?").run(f,n,S),Je(n,S,f)}),C(e,n,["cwd"])),o.restart===!0&&ge(n),{status:200,body:g(n)}}if(V().has(n)){const f=`${n} cannot repair its cwd while its broker is live`;throw new m(409,"cwd_node_live",f,{error:"cwd_node_live",message:f,received:i,field:"cwd",next:"Let the node become dormant, then retry the cwd repair."})}if(c.fork_from!=null)throw new w({error:"cwd_node_forked",message:`${n} is a fork and cannot repair its cwd; recorded cwd: ${c.cwd}`,received:i,field:"cwd",next:`Restore ${c.cwd}, then revive the fork normally.`});if(c.managed_worktree?.state==="open")throw new w({error:"cwd_node_managed_worktree_open",message:`${n} owns an open managed worktree and cannot repair its cwd`,received:i,field:"cwd",next:"Restore or reconcile the recorded checkout, then use the managed-worktree close or abandon flow."});if(A(c.cwd))throw new w({error:"cwd_still_present",message:`${n} recorded cwd still exists: ${c.cwd}; cwd repair is not a relocation command`,received:i,field:"cwd",next:"This command only repairs a node whose recorded cwd is gone."});if(!F(i))throw new w({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${i}`,received:i,field:"cwd",next:"Send an absolute path."});const u=T(i);if(!A(u))throw new w({error:"cwd_missing",message:`cwd does not exist: ${u}`,received:i,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."});try{if(!q(u).isDirectory())throw new w({error:"cwd_not_a_directory",message:`cwd is not a directory: ${u}`,received:i,field:"cwd",next:"Send an existing absolute directory."})}catch(f){throw f instanceof w?f:new w({error:"cwd_missing",message:`cwd does not exist: ${u}`,received:i,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."})}return K(()=>{N(n,{cwd:u}),Ue(n)}),C(e,n,["cwd"]),{status:200,body:g(n)}}let d=y(n);const s=o.listen===void 0?void 0:Lt(o.listen);if(o.scopes!==void 0){const i=ue(o.scopes),c=d.grantee==="app:terminal"?et():d.grant_id?qn(d.grant_id):null,p=d.grantee==="app:terminal"&&!nt("user").runtime?.issuer;if(!i.every(u=>O(d.scopes,u)&&(c?O(c.resolved,u):p)))throw new w({error:"unknown_scope",message:"scopes may only narrow the node's current effective set",received:i,field:"scopes",next:"Send only scopes the node currently holds."});if(i.includes("crtr:act")&&!O(i,"crtr:llm"))throw new m(400,"invalid_scope","crtr:act requires crtr:llm");d=N(n,{scopes:i})}if(o.situational_context!==void 0&&Ie(n,$e(o.situational_context)),o.model!==void 0){const i=(await se(d.cwd,d.profile_id??null)).modelLadders,c=bn(o.model,i),p=vn(o.model,i);await B({kind:"concrete",spec:p},{cwd:d.cwd,profileId:d.profile_id??null},t.modelRegistry);const u=V();let f=!1;if(u.isClaimed(n)&&await On(n,u.get(n)?.handle.exited)&&(f=await Rn(n,p,c).then(()=>!0,_=>{if(_ instanceof In)return!1;throw _})),!f){if(u.isClaimed(n)){const _=`${n}'s broker did not accept the model switch; the model was not changed`;throw new m(409,"broker_not_ready",_,{error:"broker_not_ready",message:_,received:o.model,field:"model",next:"Check the node with `crtr node show`, then retry the model change."})}if(!p.includes("/"))throw h(`model must resolve to a provider/id spec: ${o.model}`);Sn(n,p,c)}d=y(n)}if(o.kind!==void 0||o.mode!==void 0||o.lifecycle!==void 0){o.kind!==void 0&&await ke(o.kind);const i=o.kind??d.kind,c=o.mode??d.mode,p=o.lifecycle??d.lifecycle;let u;c==="orchestrator"&&!yn(n)&&(u=a(()=>{const f=hn(n);wn(n,f!==null&&f.trim()!==""?{goal:f.trim()}:{})},"beforePersist")),d=await W(n,{...o.kind!==void 0?{kind:i}:{},...o.mode!==void 0?{mode:c}:{},...o.lifecycle!==void 0?{lifecycle:p}:{}},u)}o.name!==void 0&&(d=N(n,{name:o.name}),d.window&&_n(d.window,Mn(d)));const l=["scopes","situational_context","model","kind","mode","lifecycle","name","listen"].filter(i=>o[i]!==void 0);return C(e,n,l,s===void 0?void 0:i=>{X(i,"UPDATE objects SET listen_json = ? WHERE id = ? AND type = 'node'").run(s,n)}),{status:200,body:g(n)}}a(Mt,"handleConfig");async function ve(){return(await se(process.cwd(),Re()||null)).kinds}a(ve,"daemonKinds");async function ke(e){const t=Object.keys(await ve());if(!t.includes(e))throw h(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${t.sort().join(", ")}.`})}a(ke,"assertKindServer");async function jt(){const e=await ve();return{status:200,body:{kinds:Object.keys(e).sort().map(n=>({kind:n,when_to_use:e[n]?.whenToUse??null,available_to:e[n]?.availableTo??null}))}}}a(jt,"handleListKinds");const qo=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:ft},{method:"GET",pattern:"/v1/nodes",handler:mt},{method:"GET",pattern:"/v1/kinds",handler:a(()=>jt(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:Pt},{method:"GET",pattern:"/v1/nodes/:id",handler:ht},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:wt},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:yt},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:gt},{method:"GET",pattern:"/v1/nodes/:id/session",handler:bt},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:vt},{method:"GET",pattern:"/v1/nodes/:id/context",handler:kt},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:Rt},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:Ot},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:It},{method:"POST",pattern:"/v1/nodes/:id/close",handler:$t},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:Ct},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:Nt},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:At},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Tt},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Et},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:Mt}];export{Mt as handleConfig,ft as handleCreate,Rt as handleFork,mt as handleList,At as handlePromote,Tt as handleYield,qo as nodeRoutes,tr as resolveCreateKind};
1
+ var Se=Object.defineProperty;var a=(e,t)=>Se(e,"name",{value:t,configurable:!0});import{prepared as X}from"../../../core/sqlite-statements.js";import{envProfileId as Re}from"../../../shared/env.js";import{pausedCanvasProfiles as Oe}from"../../../core/profiles/manifest.js";import{existsSync as N,realpathSync as Z,statSync as q}from"node:fs";import{isAbsolute as F,resolve as T}from"node:path";import{appendSituationalContext as Ie,formatSituationalProse as $e}from"../../../core/runtime/situational-context.js";import{closeNode as Ce}from"../../../core/runtime/close.js";import{reviveNode as Ae}from"../../../core/runtime/revive.js";import{nowIso as G}from"../../../core/fs-utils.js";import{assertLaunchModelRegistered as B,forkNode as Ne,resolveForkSource as Te,spawnChildPrepared as Ee}from"../../../core/runtime/spawn.js";import{forkSourceNode as Pe,newNodeId as ee}from"../../../core/runtime/nodes.js";import{abandonCreateRequest as ne,childrenOf as De,completeCreateRequest as te,findCreateRequest as je,getNode as k,recordCreateRequestNode as Le,reserveCreateRequest as oe,reserveCreateRequestNode as Me,listNodes as re,recordRespawnAttempt as Fe,subscribersOf as Ge,subscriptionsOf as ie,setMessageWait as Be,updateNode as A}from"../../../core/canvas/canvas.js";import{subtreeIds as Ke}from"../../../core/canvas/nav-model.js";import{withCanvasWrite as K}from"../../../core/canvas/db.js";import{nodeObject as xe}from"../../../core/graph/objects.js";import{recordActedOn as We}from"../../../core/graph/edges.js";import{publish as Ve}from"../../../core/graph/events.js";import{readerFor as Je}from"../reader.js";import{relocateSessionCwd as ze,unbindSession as Ue}from"../../../core/canvas/sessions.js";import{ticketCountsForNodes as He}from"../../../core/canvas/attention.js";import{isSafeNodeId as Ye}from"../../../core/canvas/paths.js";import{contextDir as de,nodeAgentDir as x}from"../../../core/canvas/node-agent-paths.js";import{checkCronBirth as Qe}from"../../cron/authority.js";import{cronBirthPlacement as Xe}from"../../cron/armed-context.js";import{existsBeneath as Ze,isAbsentOrRefused as qe,isBeneathRefusal as en,readdirBeneath as nn}from"../../../core/spaces/open-beneath.js";import{readNodeMessagesPage as tn,readNodeSession as on,readNodeSnapshot as rn,transcriptMarkdown as dn}from"../../../core/runtime/node-read.js";import{assembleNodeSubject as sn}from"../../../core/substrate/subject.js";import{reviveAll as an}from"../../../core/runtime/revive-all.js";import{promoteAsync as ln,requestYieldAsync as cn,reshapeNodeAsync as W}from"../../../core/runtime/promote.js";import{recycleNode as fn}from"../../../core/runtime/recycle.js";import{relaunchRoot as un}from"../../../core/runtime/reset.js";import{assertReopenGate as pn}from"../../../core/runtime/reopen.js";import{writeYieldMessage as mn,readGoal as hn}from"../../../core/runtime/kickoff.js";import{ensureRoadmap as wn,hasRoadmap as yn}from"../../../core/runtime/roadmap.js";import{renameWindow as _n}from"../../../core/runtime/placement.js";import{buildLaunchSpecAsync as gn,explicitModelIntent as bn,normalizeModel as vn,readMergedLaunchConfigAsync as se}from"../../../core/runtime/launch.js";import{modelRequestFromConfig as kn}from"../../../core/model-routes.js";import{persistDormantModel as Sn,setModelLive as Rn}from"../../../core/runtime/model-swap.js";import{waitForBrokerViewSocket as On}from"../../../core/runtime/view-socket.js";import{BrokerUnreachableError as In}from"../../../core/runtime/broker-request.js";import{boundFleet as V}from"../../../core/runtime/fleet.js";import{admitLegacyStructuredOutput as $n}from"../../structured-requests/sidecar.js";import{assertOutputSchemaAccepted as Cn}from"../../../core/runtime/structured-output.js";import{OUTCOME_PAYLOAD_MAX_BYTES as ae}from"../../../core/canvas/types.js";import{HUMAN_ACTION_NAME_PATTERN as An}from"../../../core/human/action-binding.js";import{resolveHumanAction as Nn}from"../../../core/human-actions.js";import{parseDurationMs as Tn}from"../../../core/wake.js";import{claimWarmNode as En,refillWarmPool as le,resumeWarmClaim as Pn,warmPoolEnabled as Dn}from"../../../core/runtime/warm-pool.js";import{assertLaunchKind as J,isLaunchKind as jn,resolveLaunchTarget as Ln}from"../../../core/runtime/launch-target.js";import{fullName as Mn}from"../../../core/canvas/labels.js";import{reportsForNode as ce}from"./reports.js";import{requireUsableProfile as Fn}from"./profiles.js";import{assertProfileActive as Gn,loadExactProfileManifest as Bn}from"../../../core/profiles/manifest.js";import{getCron as fe}from"../../../core/canvas/crons.js";import{cronWakeOrigin as Kn}from"../../../core/runtime/bearings.js";import{boundDaemonControl as xn}from"../../control.js";import{notFound as E,usage as h}from"../../../core/errors.js";import{assertScope as Wn,validateScopes as ue}from"../../../core/scopes.js";import{scopeAllowed as O}from"../../../shared/env.js";import{toCloseResultDTO as Vn,toNodeDetailDTO as z,toNodeSummaryDTO as Jn,toReviveResultDTO as zn}from"../map.js";import{ApiError as m}from"../../../api/index.js";import{InputError as w}from"../../../core/io.js";import{brokerMayReach as U,canReadNode as pe,resolvedScopes as Un}from"../router.js";import{forwardVerb as Hn,queryWithoutMachine as Yn,relayError as Qn,unknownError as Xn,withMachine as Zn}from"../../peer/forward.js";import{fileRoot as qn}from"../../../core/spaces/file-root.js";import{activeGrant as et,terminalGrant as nt}from"../../../core/grants/mirror.js";import{readConfig as tt}from"../../../core/config.js";import{hasConfiguredProviderCredential as ot,NO_PROVIDER_CREDENTIAL_MESSAGE as me}from"../../../core/runtime/provider-credential-gate.js";function y(e){const t=k(e);if(t===null)throw E(`unknown node: ${e}`,{received:e});return t}a(y,"requireMeta");function H(e){return{subscribesTo:ie(e),subscribers:Ge(e),children:De(e)}}a(H,"edgesFor");function g(e){const t=y(e);return z(t,H(e))}a(g,"detailOf");function rt(e){let t=ce(e).length;try{t+=nn(x(e),de(e)).length}catch(n){if(!qe(n))throw n}return t}a(rt,"countFiles");function it(e){if(typeof e!="object"||e===null)throw h("a node create requires a JSON body");const t=e;if(t.kind!==void 0&&(typeof t.kind!="string"||t.kind.trim()===""))throw h("kind must be a non-empty string when provided");if(t.description!==void 0&&(typeof t.description!="string"||t.description.trim()===""))throw h("description must be a non-empty string when provided");if(t.creator!==void 0&&(typeof t.creator!="string"||t.creator.trim()===""))throw h("creator must be a non-empty node id when provided");if(t.scopes!==void 0&&ue(t.scopes),t.isolated!==void 0&&typeof t.isolated!="boolean")throw new m(400,"invalid_request","isolated must be a boolean",{param:"isolated"});const n=t.root_lifecycle;if(n!==void 0&&n!=="resident"&&n!=="terminal")throw h("root_lifecycle must be 'resident' or 'terminal'");if(t.request_key!==void 0&&(typeof t.request_key!="string"||t.request_key.trim()===""||t.request_key.length>128))throw h("request_key must be a non-empty string of at most 128 characters when provided");return t}a(it,"parseCreateBody");function dt(e){if(e===void 0)return;const t=Tn(e),n=t===null?null:new Date(Date.now()+t);if(t===null||!Number.isFinite(t)||t<=0||n===null||!Number.isFinite(n.getTime()))throw new m(422,"invalid_deadline","`deadline` must be a positive representable duration");return n.toISOString()}a(dt,"parseDeadline");function st(e){if(e!==void 0){if(typeof e!="object"||e===null||Array.isArray(e))throw new m(400,"invalid_request","`outcome_delivery` must be an object");if(typeof e.action!="string"||!An.test(e.action))throw new m(400,"invalid_request","`outcome_delivery.action` must be a declared action name");if(e.payload!==void 0){let t;try{t=JSON.stringify(e.payload)}catch{throw new m(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable")}if(t===void 0)throw new m(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable");if(Buffer.byteLength(t,"utf8")>ae)throw new m(413,"payload_too_large",`serialized payload exceeds ${ae} bytes`)}return e}}a(st,"parseOutcomeDelivery");function at(e,t){const n=Nn(e.action,t);if(!("kind"in n))return{actionName:e.action,argv:n.argv,cwd:n.cwd,configOrigin:n.configOrigin,...e.payload===void 0?{}:{payload:e.payload}};throw n.kind==="unknown_action"?new m(422,"unknown_action",`no action named ${e.action} is declared from ${t}`):new m(422,"invalid_action",`${e.action} is declared in ${n.configOrigin} but unusable: ${n.reason}`,{reason:n.reason,configOrigin:n.configOrigin})}a(at,"resolveOutcomeDelivery");function lt(e,t,n){const r={kind:e.kind,cwd:n,prompt:e.prompt??""};return e.mode!==void 0&&(r.mode=e.mode),e.name!==void 0&&(r.name=e.name),e.description!==void 0&&(r.description=e.description),t!==void 0&&(r.parent=t),e.creator!==void 0&&(r.creator=e.creator),e.scopes!==void 0&&(r.scopes=e.scopes),e.isolated!==void 0&&(r.isolated=e.isolated),e.root===!0&&(r.root=!0),e.root_lifecycle!==void 0&&(r.rootLifecycle=e.root_lifecycle),(e.worktree===!0||typeof e.worktree=="string")&&(r.worktree=!0),typeof e.worktree=="string"&&(r.worktreeBase=e.worktree),e.worktree!==void 0&&(r.worktreeCwd=T(e.pin_cwd??e.cwd??n)),e.fork_from!==void 0&&(r.forkFrom=e.fork_from),e.model!==void 0&&(r.model=e.model),e.profile!==void 0&&(r.profile=e.profile),e.situational_context!==void 0&&(r.situationalContext=e.situational_context),e.node_id!==void 0&&(r.nodeId=e.node_id),r}a(lt,"buildRecipe");function ct(e,t,n){return!Dn()||e.prefer_warm!==!0||e.root!==!0||e.parent!=null||e.root_lifecycle==="terminal"||(e.prompt??"")!==""||e.model!==void 0||e.fork_from!==void 0||e.worktree!==void 0||e.node_id!==void 0||e.scopes!==void 0||e.isolated!==void 0?null:{kind:e.kind,mode:e.mode??"base",cwd:t,profileId:n,model:e.model??null,situationalContext:e.situational_context??null,name:e.name??null,creator:e.creator??null}}a(ct,"warmRequestFor");import{resolveCreateKind as rr}from"../../../core/runtime/launch-target.js";function he(e){const t=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return kn(e.model,t,e.modelExact===!0)}a(he,"requestFromLaunch");function ft(e,t){if(t===null)return e;if(e.scopes===void 0)return{...e,scopes:[...t]};const n=e.scopes.filter(r=>!O(t,r));if(n.length===0)return e;throw new m(403,"scope_denied",`scopes exceed the bearer token's ceiling: ${n.join(", ")}`,{scopes:n,ceiling:t})}a(ft,"withinCeiling");async function we(e,t,n){const r=(await gn(t.kind,t.mode,{lifecycle:t.lifecycle,hasManager:e.parent!==null,model:t.model,modelOverride:!0,cwd:e.cwd,profileId:e.profile_id??null})).launch;await B(he(r),{cwd:e.cwd,profileId:e.profile_id??null},n)}a(we,"assertNodeModelChangeRegistered");function ye(e,t){const n=e.principal;if(n.class!=="broker"&&n.class!=="cron")return;const r=qn({app:n.app,resolved:Un(n),launched:n.scopes},t,"read");if("root"in r)return;const o="missing"in r?r.missing:null;throw new m(403,"scope_missing",o?`the child's directory ${t} needs missing scope ${o}`:`no permission of this run names the child's directory ${t}`,void 0,void 0,o?{scope:o}:void 0)}a(ye,"assertCallerReaches");const Y=new Map;async function ut(e,t={},n={}){const r=ft(it(e.body),e.ceiling);if(e.principal.class==="broker"){const c=e.principal;if(r.prefer_warm===!0&&c.app!=="app:terminal"&&(r.prefer_warm=!1),r.parent!=null){const i=y(r.parent);if(i.grantee!==c.app)throw new m(403,"other_app_run","cannot create a child under another app's node");if(!U(c,r.parent,i.grantee??"app:terminal"))throw E(`unknown node: ${r.parent}`,{received:r.parent})}if(r.creator!==void 0&&r.creator!==c.node)throw new m(403,"other_app_run","cannot create for another node");if(r.fork_from!==void 0){let i=null;try{i=Pe(Te(r.fork_from))}catch{}if(i?.grantee!==c.app||!U(c,i.node_id,i.grantee))throw new m(403,"other_app_run","cannot fork another app's conversation")}r.creator=c.node}if(e.principal.class==="cron"){const c=e.principal;for(const l of["parent","creator","fork_from","node_id"])if(r[l]!=null)throw new m(403,"permission_error",`a cron cannot set ${l} on a node it starts`);r.prefer_warm=!1;const i=Qe({grantee:c.app,sub:c.sub,grant_id:c.grant,scopes:c.scopes});if(!i.allowed)throw new m(i.reason==="scope_missing"?403:401,i.reason==="scope_missing"?"scope_missing":"grant_revoked",i.message);if(r.scopes!==void 0){const l=r.scopes.find(p=>!O(i.effectiveScopes,p)||!O(c.scopes,p));if(l!==void 0)throw new m(403,"scope_missing",`scope ${l} is not held by this cron`,void 0,void 0,{scope:l})}else c.scopes!==null&&(r.scopes=[...c.scopes]);r.node_id=ee(),c.isolated&&(r.isolated=!0,r.cwd=x(r.node_id,c.app))}r.creator!==void 0&&Wn(y(r.creator),"crtr:act");const o=r.request_key?.trim();if(o===void 0||r.node_id!==void 0&&Ye(r.node_id)&&k(r.node_id)!==null&&je(o)?.nodeId!==r.node_id)return P(e,r,t,n);const d=Y.get(o);if(d!==void 0)return d;const s=pt(e,r,o,t,n);Y.set(o,s);try{return await s}finally{Y.delete(o)}}a(ut,"handleCreate");async function pt(e,t,n,r,o){const d=oe(n);if(d.nodeId!==null&&k(d.nodeId)!==null){if(d.state!=="warm_claimed"){const s=k(d.nodeId);if(e.principal.class!=="person"&&!pe(e.principal,s.grantee??"app:terminal",d.nodeId))throw new m(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:g(d.nodeId)}}return P(e,t,r,o,d)}try{return await P(e,t,r,o,d)}catch(s){const c=oe(n);throw(c.nodeId===null||k(c.nodeId)===null)&&ne(n,c.nodeId),s}}a(pt,"handleKeyedCreateRequest");async function P(e,t,n,r,o=void 0){const d=r.deadlineAt??dt(t.deadline),s=st(t.outcome_delivery),c=e.principal.class==="cron"?Xe({grantee:e.principal.app,sub:e.principal.sub,grant_id:e.principal.grant,scopes:e.principal.scopes,cron_id:e.principal.cron,origin_run_id:e.principal.origin_run,isolated:e.principal.isolated,creator:fe(e.principal.cron)?.created_by??null},t.node_id):null;c!==null&&(t.root=c.root===!0);const i=c?.parent??t.parent??void 0;if(i==null&&t.root!==!0)throw h("a node create requires a parent (or root: true for an independent root)");let l=null;if(t.output_schema!==void 0){try{l=JSON.parse(t.output_schema)}catch{throw h("output_schema must be a JSON schema string")}if(l===null||typeof l!="object"||Array.isArray(l))throw h("output_schema must be a JSON schema object");await Cn(l)}const{profileId:p,kind:u,cwd:f,launch:_}=await Ln(t,{validateKind:ke});ye(e,f),t.worktree!==void 0&&ye(e,T(t.pin_cwd??t.cwd??f));const S={...t,kind:u},I=s===void 0?void 0:at(s,f);if(await B(he(_),{cwd:f,profileId:p},n.modelRegistry),!await ot(p))throw new m(412,"no_provider_credential",me,{error:"no_provider_credential",message:me,next:"The person running this runtime logs a provider in with `crtr sys setup`, or stores a provider key on the profile."});let j=null;{const $=o===void 0||o.nodeId===null||o.state==="warm_claimed"?ct(S,f,p):null,L=l===null&&r.beforeBrokerLaunch===void 0?void 0:v=>{l!==null&&$n(v,"terminal",l),r.beforeBrokerLaunch?.(v)};if(o?.state==="warm_claimed"&&o.nodeId!==null){const v=$===null?null:await Pn($,o.nodeId,L);if(v===null)throw ne(o.requestKey,o.nodeId),new m(503,"create_resume_failed",`could not resume warm claim ${o.nodeId}; retry the create`);return te(o.requestKey,v),{status:201,body:g(v)}}if($!==null){const v=await En($,{...d===void 0?{}:{deadlineAt:d},...I===void 0?{}:{outcomeDelivery:I},...o===void 0?{}:{requestKey:o.requestKey}},L);if(v!==null)return o!==void 0&&te(o.requestKey,v),le($),{status:201,body:g(v)};j=$}const M=o?.nodeId??t.node_id??(o===void 0?void 0:ee());o!==void 0&&o.nodeId===null&&Me(o.requestKey,M);const R=lt(M===void 0?S:{...S,node_id:M},i,f);c!==null&&(c.rootLifecycle!==void 0&&(R.rootLifecycle=c.rootLifecycle),c.scopes!==void 0&&S.scopes===void 0&&(R.scopes=c.scopes),c.run!==void 0&&(R.run=c.run),c.withinCreate!==void 0&&(R.withinCreate=c.withinCreate)),d!==void 0&&(R.deadlineAt=d),I!==void 0&&(R.outcomeDelivery=I),R.readiness=t.root===!0?"await":"launch";const Q=await Ee(R,L,()=>{j!==null&&le(j)});return o!==void 0&&Le(o.requestKey,Q.node.node_id),{status:201,body:g(Q.node.node_id)}}}a(P,"handleCreateRequest");function b(e,t){const n=e.query.getAll(t);if(n.length>1)throw h(`${t} must appear at most once`);return n[0]}a(b,"singleQueryValue");function _e(e,t){if(e!==void 0){if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;throw h(`${t} must be true or false`)}}a(_e,"optionalBoolean");function D(e,t,n){if(e!==void 0){if(n.includes(e))return e;throw h(`${t} must be one of: ${n.join(", ")}`)}}a(D,"oneOf");function mt(e){const t=new Set(["status","lifecycle","kind","mode","profile_id","profile_prefix","parent","top_level","under","hanging","include"]);for(const[_]of e.query)if(!t.has(_))throw h(`unknown nodes query parameter: ${_}`);const n=D(b(e,"status"),"status",["active","idle","done","dead","canceled"]),r=D(b(e,"lifecycle"),"lifecycle",["terminal","resident"]),o=b(e,"kind"),d=D(b(e,"mode"),"mode",["base","orchestrator"]),s=b(e,"profile_id"),c=b(e,"profile_prefix"),i=b(e,"parent"),l=_e(b(e,"top_level"),"top_level"),p=b(e,"under"),u=_e(b(e,"hanging"),"hanging"),f=D(b(e,"include"),"include",["activity"]);if(i!==void 0&&l===!0)throw h("parent and top_level=true cannot be combined");return{...n!==void 0?{status:n}:{},...r!==void 0?{lifecycle:r}:{},...o!==void 0?{kind:o}:{},...d!==void 0?{mode:d}:{},...s!==void 0?{profile_id:s}:{},...c!==void 0?{profile_prefix:c}:{},...i!==void 0?{parent:i}:{},...l!==void 0?{top_level:l}:{},...p!==void 0?{under:p}:{},...u!==void 0?{hanging:u}:{},...f!==void 0?{include:f}:{}}}a(mt,"parseListQuery");function ht(e){const t=mt(e);let n=t.status!==void 0?re({status:t.status}):re();if(e.principal.class!=="person"&&(n=n.filter(s=>pe(e.principal,s.grantee??"app:terminal",s.node_id))),t.lifecycle!==void 0&&(n=n.filter(s=>s.lifecycle===t.lifecycle)),t.kind!==void 0&&(n=n.filter(s=>s.kind===t.kind)),t.mode!==void 0&&(n=n.filter(s=>s.mode===t.mode)),t.profile_id!==void 0&&(n=n.filter(s=>s.profile_id===t.profile_id)),t.profile_prefix!==void 0&&(n=n.filter(s=>s.profile_id?.startsWith(t.profile_prefix))),t.parent!==void 0&&(n=n.filter(s=>s.parent===t.parent)),t.top_level===!0&&(n=n.filter(s=>s.parent===null)),t.under!==void 0){const s=new Set(Ke(t.under));n=n.filter(c=>s.has(c.node_id))}t.hanging===!0&&(n=n.filter(s=>s.parent!==null&&k(s.parent)===null));const r=t.include==="activity"?He(n.map(s=>s.node_id)):null,o=n.length>0?Oe():new Set;return{status:200,body:n.map(s=>{const c=Jn(s,s.profile_id!==null&&o.has(s.profile_id));if(r!==null){const i=ce(s.node_id);c.activity={latest_report:i[0]??null,final_report:s.final_report===null?null:i.find(l=>l.name===s.final_report)??null,pending_human_count:r[s.node_id]??0}}return c})}}a(ht,"handleList");async function wt(e){const t=e.params.id,n=await Hn(e,t,{method:"GET",path:`/v1/nodes/${encodeURIComponent(t)}`,query:Yn(e)});if(n.kind==="unknown")throw Xn(t,n.unreachable);if(n.kind==="remote"){if(n.status>=400)throw Qn(n.status,n.body);return{status:n.status,body:Zn(n.body,n.machine)}}return y(t),{status:200,body:g(t)}}a(wt,"handleDetail");async function yt(e){const t=e.params.id;y(t);const n=await rn(t);return{status:200,body:{node_id:t,snapshot:{messages:n.snapshot.messages,...n.snapshot.messageIds===void 0?{}:{messageIds:n.snapshot.messageIds},messageVisibility:n.snapshot.messageVisibility,turnVisibility:n.snapshot.turnVisibility,stats:n.snapshot.stats,state:n.snapshot.state,display:n.snapshot.display,...n.snapshot.queued===void 0?{}:{queued:n.snapshot.queued},...n.snapshot.toolGroupSummaries===void 0?{}:{toolGroupSummaries:n.snapshot.toolGroupSummaries},...n.snapshot.turnReplies===void 0?{}:{turnReplies:n.snapshot.turnReplies},...n.snapshot.workingActivity===void 0?{}:{workingActivity:n.snapshot.workingActivity}},commands:n.commands.map(o=>({name:o.name,description:o.description,source:o.source})),captured_at:G()}}}a(yt,"handleSnapshot");async function _t(e){const t=e.params.id,n=sn(t);if(n===null)throw E(`unknown node: ${t}`,{received:t});return{status:200,body:n}}a(_t,"handleSubject");function gt(e){for(const[d]of e.query)if(d!=="cursor"&&d!=="limit")throw h(`unknown messages query parameter: ${d}`);const t=e.query.getAll("cursor"),n=e.query.getAll("limit");if(t.length>1)throw h("cursor must appear at most once");if(n.length>1)throw h("limit must appear at most once");if(n.length===0)return t.length===0?{}:{cursor:t[0]};const r=n[0],o=Number(r);if(!Number.isSafeInteger(o)||r==="")throw h("limit must be an integer from 1 through 500");return t.length===0?{limit:o}:{cursor:t[0],limit:o}}a(gt,"parseMessagesQuery");async function bt(e){const t=e.params.id,n=await tn(t,gt(e));return{status:200,body:{node_id:t,messages:n.messages,...n.messageIds===void 0?{}:{message_ids:n.messageIds},message_visibility:n.messageVisibility,next_cursor:n.nextCursor,captured_at:G()}}}a(bt,"handleMessages");function vt(e){const t=e.params.id;y(t);const n=on(t);return{status:200,body:{node_id:t,session_file:n.sessionFile,session_jsonl:n.sessionJsonl,system_prompt:n.systemPrompt,captured_at:G()}}}a(vt,"handleSession");async function kt(e){const t=e.params.id;return y(t),{status:200,body:{node_id:t,markdown:await dn(t)}}}a(kt,"handleTranscript");function St(e){const t=e.params.id;y(t);const n=a((o,d)=>({node_id:o,label:k(o)?.name??o,dir:de(o),self:d,files:rt(o)}),"root"),r=[n(t,!0),...ie(t).map(o=>n(o.node_id,!1))].filter(o=>Rt(o.node_id,o.dir)||o.files>0);return{status:200,body:{node_id:t,roots:r}}}a(St,"handleContext");function Rt(e,t){try{return Ze(x(e),t)}catch(n){if(en(n))return!1;throw n}}a(Rt,"hasDir");async function Ot(e){const t=y(e.params.id),n=e.principal.class==="broker"?e.principal.scopes:e.ceiling,r=n===null?void 0:t.scopes==null?[...n]:[...new Set([...t.scopes.filter(d=>O(n,d)),...n.filter(d=>O(t.scopes,d))])],o=await Ne(t.node_id,r,e.principal.class==="broker"?e.principal.node:void 0);return{status:201,body:g(o.node.node_id)}}a(Ot,"handleFork");async function It(e){const t=e.params.id;y(t);const n=e.body,r=n?.resume??!0,o=n?.reopen??!1;pn(t,o);const d=!r&&n?.cron_id!==void 0?fe(n.cron_id):null,s=await Ae(t,{resume:r,capacity:"refuse",...d!==null?{wakeReason:Kn(d,"schedule_revive")}:{}});s.outcome!=="already-live"&&Fe(t,{failures:0,notBefore:null});const c=k(t)?.status??"active";return{status:200,body:zn(t,s,c)}}a(It,"handleRevive");async function $t(e){const t=e.params.id;return{status:200,body:{newNodeId:(await un(t))?.newNodeId??null}}}a($t,"handleRelaunchRoot");function Ct(e){const t=e.params.id;y(t);const n=e.body;if(n?.caller_pid!==void 0&&(!Number.isInteger(n.caller_pid)||n.caller_pid<=0))throw h("caller_pid must be a positive integer when provided");const r=xn(),o=Ce(t,{rootEvent:n?.finish===!0?"finish":"cancel",callerPid:n?.caller_pid,...e.principal.class==="broker"?{closer:e.principal.node}:{},...r===null?{}:{registerDetached:r.registerDetached}});return{status:200,body:Vn(o)}}a(Ct,"handleClose");async function At(e){const t=e.params.id;y(t);const n=await fn(t);return{status:200,body:{recycled:n.recycled,finalized:n.finalized,new_root:n.newRoot,delivered:n.delivered}}}a(At,"handleRecycle");async function Nt(e){const t=e.params.id;return y(t),await W(t,{lifecycle:"terminal"}),C(e,t,["lifecycle"]),{status:200,body:g(t)}}a(Nt,"handleDemote");async function Tt(e,t={}){const n=e.params.id,r=y(n),o=e.body??{};o.kind!==void 0&&await J(o.kind,r.cwd,r.profile_id??null),o.model!==void 0&&await we(r,{kind:o.kind??r.kind,mode:"orchestrator",lifecycle:o.resident===!0?"resident":r.lifecycle,model:o.model},t.modelRegistry);const d=await ln(n,{...o.kind!==void 0?{kind:o.kind}:{},...o.resident===!0?{resident:!0}:{},...o.model!==void 0?{model:o.model}:{}});C(e,n,["mode",...o.kind!==void 0?["kind"]:[],...o.resident===!0?["lifecycle"]:[],...o.model!==void 0?["model"]:[]]);const s=z(d.meta,H(n));return s.roadmap_written=d.roadmapWritten,s.roadmap_ref=d.roadmapRef,s.goal_path=d.goalPath,{status:200,body:s}}a(Tt,"handlePromote");async function Et(e,t={}){const n=e.params.id,r=y(n),o=e.body??{};o.kind!==void 0&&await J(o.kind,r.cwd,r.profile_id??null),o.model!==void 0&&await we(r,{kind:o.kind??r.kind,mode:o.promote===!0?"orchestrator":r.mode,lifecycle:r.lifecycle,model:o.model},t.modelRegistry);const d=o.note??"Refresh: continue against your roadmap or goal.";mn(n,d);const s=await cn(n,{...o.promote===!0?{promote:!0}:{},...o.kind!==void 0?{kind:o.kind}:{},...o.model!==void 0?{model:o.model}:{}});return{status:200,body:z(s.meta,H(n))}}a(Et,"handleYield");function Pt(e){const t=e.params.id;y(t);const n=e.body;if(n===void 0||typeof n.controller!="string"||n.controller.trim()==="")throw h("a wait requires a controller node id");const r=k(n.controller);if(r===null)throw E(`unknown controller: ${n.controller}`,{received:n.controller});if(r.status!=="active"&&r.status!=="idle")throw new m(422,"unprocessable",`controller ${n.controller} is ${r.status}`);return Be(t,n.controller),{status:200,body:g(t)}}a(Pt,"handleWait");async function Dt(e){const t=e.principal,n=await an(t.class==="broker"?o=>o.grantee===t.app&&U(t,o.node_id,o.grantee):void 0);return{status:200,body:{revived:[...n.revived],failed:[...n.failed],frozen:[...n.frozen]}}}a(Dt,"handleReviveAll");const jt=new Set(["interrupt","steer","after-turn","next-turn"]);function Lt(e){if(e===null)return null;const t=a(r=>{throw new w({error:"invalid_listen",message:r,received:e,field:"listen",next:'Send an object mapping levels "1".."10" to interrupt|steer|after-turn|next-turn (e.g. {"3":"next-turn"}), or null to reset to the global default.'})},"bad");if(typeof e!="object"||Array.isArray(e))return t("listen must be an object or null");const n=Object.entries(e);if(n.length===0)return t("listen must name at least one level");for(const[r,o]of n)/^(?:[1-9]|10)$/.test(r)||t(`listen level must be 1..10: ${r}`),(typeof o!="string"||!jt.has(o))&&t(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(o)}`);return JSON.stringify(Object.fromEntries(n))}a(Lt,"listenJson");function C(e,t,n,r){n.length===0&&r===void 0||K(o=>{if(r?.(o),n.length===0)return;const d=xe(o,t),s=Je(o,e),c=s.class==="person"?s.person:s.class==="app"?s.app:s.node;We(o,c,d),Ve(o,{event:"configured",object:d,actor:c,attrs:{changed:n.join(",")}})})}a(C,"recordConfigured");function ge(e){const t=V().get(e);if(t===void 0)return!1;try{return process.kill(t.pid,"SIGTERM"),!0}catch{return!1}}a(ge,"restartLiveBroker");function be(e,t){try{return Z(e)===Z(t)}catch{return!1}}a(be,"sameDirectory");async function Mt(e,t={}){const n=e.params.id,r=e.body;let o;if(r===void 0)o={};else if(typeof r=="object"&&r!==null&&!Array.isArray(r))o=r;else throw new w({error:"cwd_invalid",message:"cwd repair requires a non-null object with a non-empty cwd string",received:r,field:"cwd",next:"Send a config patch with a non-empty absolute cwd string."});if(o.profile!==void 0){if(typeof o.profile!="string"||o.profile==="")throw new w({error:"profile_invalid",message:"profile must be a non-empty profile id or name",received:o.profile,field:"profile",next:"Send a profile id or exact name."});if(Object.keys(o).some(u=>u!=="profile"&&u!=="restart"&&o[u]!==void 0))throw new w({error:"profile_not_exclusive",message:"profile can only be combined with restart",field:"profile",next:"Send profile (and optionally restart) alone."});const i=y(n),l=Fn(e,o.profile);Gn(l.profileId);const p=Bn(l.profileId).manifest.grantee??"app:terminal";if(p!==(i.grantee??"app:terminal"))throw new w({error:"profile_grantee_mismatch",message:`profile ${l.profileId} belongs to ${p}, node ${n} to ${i.grantee}`,received:o.profile,field:"profile",next:"Pick a profile owned by the same app as the node."});return(i.profile_id??null)!==l.profileId&&(jn(i.kind)?(await J(i.kind,i.cwd,l.profileId),await W(n,{profileId:l.profileId})):A(n,{profile_id:l.profileId}),C(e,n,["profile"])),o.restart===!0&&ge(n),{status:200,body:g(n)}}if(Object.prototype.hasOwnProperty.call(o,"cwd")){const i=o.cwd;if(typeof i!="string"||i==="")throw new w({error:"cwd_invalid",message:"cwd must be a non-empty string",received:i,field:"cwd",next:"Send a non-empty absolute cwd string."});if(Object.keys(o).some(f=>f!=="cwd"&&f!=="keep_session"&&f!=="restart"&&o[f]!==void 0))throw new w({error:"cwd_not_exclusive",message:"cwd repair cannot be combined with another config field",received:o,field:"cwd",next:"Send cwd as the only config field."});const l=y(n),p=N(l.cwd);if(o.keep_session===!0||p&&F(i)&&N(i)&&be(l.cwd,i)){if(!F(i))throw new w({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${i}`,received:i,field:"cwd",next:"Send an absolute path."});const f=T(i);let _=!1;try{_=q(f).isDirectory()}catch{}if(!_)throw new w({error:"cwd_missing",message:`cwd is not an existing directory: ${f}`,received:i,field:"cwd",next:"Send an existing absolute directory."});if(p&&!be(l.cwd,f))throw new w({error:"cwd_not_same_directory",message:`${f} is not the same directory as the recorded ${l.cwd}; --keep-session only relocates an alias`,received:i,field:"cwd",next:"Drop --keep-session to repair a gone cwd, or pass the real path of the recorded directory."});if(l.managed_worktree?.state==="open")throw new w({error:"cwd_node_managed_worktree_open",message:`${n} owns an open managed worktree and cannot relocate its cwd`,received:i,field:"cwd",next:"Reconcile the managed worktree first."});const S=l.cwd;return S!==f&&(K(I=>{A(n,{cwd:f}),X(I,"UPDATE crons SET cwd = ? WHERE anchor_node = ? AND cwd = ?").run(f,n,S),ze(n,S,f)}),C(e,n,["cwd"])),o.restart===!0&&ge(n),{status:200,body:g(n)}}if(V().has(n)){const f=`${n} cannot repair its cwd while its broker is live`;throw new m(409,"cwd_node_live",f,{error:"cwd_node_live",message:f,received:i,field:"cwd",next:"Let the node become dormant, then retry the cwd repair."})}if(l.fork_from!=null)throw new w({error:"cwd_node_forked",message:`${n} is a fork and cannot repair its cwd; recorded cwd: ${l.cwd}`,received:i,field:"cwd",next:`Restore ${l.cwd}, then revive the fork normally.`});if(l.managed_worktree?.state==="open")throw new w({error:"cwd_node_managed_worktree_open",message:`${n} owns an open managed worktree and cannot repair its cwd`,received:i,field:"cwd",next:"Restore or reconcile the recorded checkout, then use the managed-worktree close or abandon flow."});if(N(l.cwd))throw new w({error:"cwd_still_present",message:`${n} recorded cwd still exists: ${l.cwd}; cwd repair is not a relocation command`,received:i,field:"cwd",next:"This command only repairs a node whose recorded cwd is gone."});if(!F(i))throw new w({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${i}`,received:i,field:"cwd",next:"Send an absolute path."});const u=T(i);if(!N(u))throw new w({error:"cwd_missing",message:`cwd does not exist: ${u}`,received:i,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."});try{if(!q(u).isDirectory())throw new w({error:"cwd_not_a_directory",message:`cwd is not a directory: ${u}`,received:i,field:"cwd",next:"Send an existing absolute directory."})}catch(f){throw f instanceof w?f:new w({error:"cwd_missing",message:`cwd does not exist: ${u}`,received:i,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."})}return K(()=>{A(n,{cwd:u}),Ue(n)}),C(e,n,["cwd"]),{status:200,body:g(n)}}let d=y(n);const s=o.listen===void 0?void 0:Lt(o.listen);if(o.scopes!==void 0){const i=ue(o.scopes),l=d.grantee==="app:terminal"?nt():d.grant_id?et(d.grant_id):null,p=d.grantee==="app:terminal"&&!tt("user").runtime?.issuer;if(!i.every(u=>O(d.scopes,u)&&(l?O(l.resolved,u):p)))throw new w({error:"unknown_scope",message:"scopes may only narrow the node's current effective set",received:i,field:"scopes",next:"Send only scopes the node currently holds."});if(i.includes("crtr:act")&&!O(i,"crtr:llm"))throw new m(400,"invalid_scope","crtr:act requires crtr:llm");d=A(n,{scopes:i})}if(o.situational_context!==void 0&&Ie(n,$e(o.situational_context)),o.model!==void 0){const i=(await se(d.cwd,d.profile_id??null)).modelLadders,l=bn(o.model,i),p=vn(o.model,i);await B({kind:"concrete",spec:p},{cwd:d.cwd,profileId:d.profile_id??null},t.modelRegistry);const u=V();let f=!1;if(u.isClaimed(n)&&await On(n,u.get(n)?.handle.exited)&&(f=await Rn(n,p,l).then(()=>!0,_=>{if(_ instanceof In)return!1;throw _})),!f){if(u.isClaimed(n)){const _=`${n}'s broker did not accept the model switch; the model was not changed`;throw new m(409,"broker_not_ready",_,{error:"broker_not_ready",message:_,received:o.model,field:"model",next:"Check the node with `crtr node show`, then retry the model change."})}if(!p.includes("/"))throw h(`model must resolve to a provider/id spec: ${o.model}`);Sn(n,p,l)}d=y(n)}if(o.kind!==void 0||o.mode!==void 0||o.lifecycle!==void 0){o.kind!==void 0&&await ke(o.kind);const i=o.kind??d.kind,l=o.mode??d.mode,p=o.lifecycle??d.lifecycle;let u;l==="orchestrator"&&!yn(n)&&(u=a(()=>{const f=hn(n);wn(n,f!==null&&f.trim()!==""?{goal:f.trim()}:{})},"beforePersist")),d=await W(n,{...o.kind!==void 0?{kind:i}:{},...o.mode!==void 0?{mode:l}:{},...o.lifecycle!==void 0?{lifecycle:p}:{}},u)}o.name!==void 0&&(d=A(n,{name:o.name}),d.window&&_n(d.window,Mn(d)));const c=["scopes","situational_context","model","kind","mode","lifecycle","name","listen"].filter(i=>o[i]!==void 0);return C(e,n,c,s===void 0?void 0:i=>{X(i,"UPDATE objects SET listen_json = ? WHERE id = ? AND type = 'node'").run(s,n)}),{status:200,body:g(n)}}a(Mt,"handleConfig");async function ve(){return(await se(process.cwd(),Re()||null)).kinds}a(ve,"daemonKinds");async function ke(e){const t=Object.keys(await ve());if(!t.includes(e))throw h(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${t.sort().join(", ")}.`})}a(ke,"assertKindServer");async function Ft(){const e=await ve();return{status:200,body:{kinds:Object.keys(e).sort().map(n=>({kind:n,when_to_use:e[n]?.whenToUse??null,available_to:e[n]?.availableTo??null}))}}}a(Ft,"handleListKinds");const nr=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:ut},{method:"GET",pattern:"/v1/nodes",handler:ht},{method:"GET",pattern:"/v1/kinds",handler:a(()=>Ft(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:Dt},{method:"GET",pattern:"/v1/nodes/:id",handler:wt},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:yt},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:_t},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:bt},{method:"GET",pattern:"/v1/nodes/:id/session",handler:vt},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:kt},{method:"GET",pattern:"/v1/nodes/:id/context",handler:St},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:Ot},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:It},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:$t},{method:"POST",pattern:"/v1/nodes/:id/close",handler:Ct},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:At},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:Nt},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:Tt},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Et},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Pt},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:Mt}];export{Mt as handleConfig,ut as handleCreate,Ot as handleFork,ht as handleList,Tt as handlePromote,Et as handleYield,nr as nodeRoutes,rr as resolveCreateKind};
@@ -1 +1 @@
1
- var q=Object.defineProperty;var c=(a,t)=>q(a,"name",{value:t,configurable:!0});import{callerGrant as p}from"../principal.js";import{grantVersion as g}from"../../../core/grants/mirror.js";import{waitGrantChange as R}from"../../../core/grants/watch.js";import{RunError as n,idempotencyKeyOf as h,cancelRun as S,deleteRun as N,interruptRun as O,listRuns as $,messageRun as A,renameRun as j,requestedScopes as x,startRun as B,traceRun as J,waitRun as z}from"../../../core/runs/operations.js";import{canReadRun as b,requireRun as f,runCallerApp as C}from"../router.js";import{waitSeconds as v}from"../long-poll-wait.js";function l(a){if(!a||typeof a!="object"||Array.isArray(a))throw new n(400,"invalid_request","a JSON object is required");return a}c(l,"object");function y(a,t,i,u,d){if(a===null)return d;if(!/^(0|[1-9]\d*)$/.test(a)||!Number.isSafeInteger(Number(a))||Number(a)<i||Number(a)>u)throw new n(400,"invalid_request",`invalid ${t}`,t);return Number(a)}c(y,"integer");const E=256*1024;async function I(a,t,i,u,d,_){switch(a.name){case"grant.get":{if("class"in t)throw new n(403,"permission_error","an app token is required");const e=v("grant.get",u),s=u.get("since");if(s!==null&&!/^[A-Za-z0-9_-]{1,64}$/.test(s))throw new n(400,"invalid_request","invalid since","since");let r=p(t);return e&&s!==null&&g(r)===s&&(await R(t.grant,e),r=p(t)),{status:200,body:{sub:t.sub,grantee:t.grantee,client_id:t.client_id,grant:t.grant,rev:r.rev,resolved_scopes:r.resolved_scopes,spend_cap:r.spend_cap,exp:t.exp,payer:"user",dependencies:r.dependencies??{},version:g(r)}}}case"run.start":{if("class"in t)throw new n(403,"permission_error","an app token is required");const e=l(d),s=["mode","parent","fork_from","node_id","env","tools","system_prompt"];for(const o of s)if(e[o]!==void 0)throw new n(403,"owner_only",`${o} is owner-only`,o);const r=["payer","model","model_policy","deadline","kind"];for(const o of r)if(e[o]!==void 0)throw new n(400,"invalid_request",`${o} is not available`,o);for(const o of Object.keys(e))if(!["prompt","scopes","metadata","profile","isolated","cwd","worktree","output_schema","message"].includes(o))throw new n(400,"invalid_request",`unknown field ${o}`,o);if(e.profile!==void 0&&(typeof e.profile!="string"||!e.profile))throw new n(400,"invalid_request","profile must be a profile id","profile");if(e.isolated!==void 0&&typeof e.isolated!="boolean")throw new n(400,"invalid_request","isolated must be a boolean","isolated");if(e.cwd!==void 0&&(e.isolated!==!0||typeof e.cwd!="string"||!e.cwd))throw new n(400,"invalid_request","cwd is available only for an isolated run and must be an absolute path inside its root folder","cwd");if(e.worktree!==void 0&&e.isolated!==!0)throw new n(400,"invalid_request","worktree is not available","worktree");if(e.isolated===!0&&e.worktree!==void 0)throw new n(400,"invalid_request","worktree is unavailable for an isolated run","worktree");if(typeof e.prompt!="string"||!e.prompt.trim())throw new n(400,"invalid_request","prompt is required","prompt");if(e.message!==void 0&&(typeof e.message!="string"||!e.message.trim()))throw new n(400,"invalid_request","message must be a non-empty string","message");const w=e.metadata===void 0?{}:l(e.metadata);if(Buffer.byteLength(JSON.stringify(w))>4096)throw new n(400,"invalid_request","metadata exceeds 4 KB","metadata");let m;if(e.output_schema!==void 0){const o=e.output_schema;if(!o||typeof o!="object"||Array.isArray(o))throw new n(400,"invalid_request","output_schema must be a JSON Schema object","output_schema");if(Buffer.byteLength(JSON.stringify(o))>E)throw new n(400,"invalid_request","output_schema exceeds 256 KB","output_schema");m=o}const k=x(t.resolved,e.scopes,t.grantee);return{status:201,body:await B(t,{prompt:e.prompt,scopes:k,metadata:w,profile:e.profile,isolated:e.isolated,cwd:e.cwd,...m===void 0?{}:{output_schema:m},...e.message===void 0?{}:{message:e.message}},h(_))}}case"run.list":{const e=u.get("status")??void 0;if(e&&!["running","waiting_on_user","idle","settled"].includes(e))throw new n(400,"invalid_request","invalid status","status");const s=u.get("app");if(s!==null&&!/^(?:app:)?[a-z0-9][a-z0-9-]*$/.test(s))throw new n(400,"invalid_request","invalid app","app");const r=s===null?C(t):s.startsWith("app:")?s:`app:${s}`;if(r!==null&&!b(t,r))throw new n(404,"not_found","run not found");return{status:200,body:$(r,{status:e,after:u.get("after")??void 0,limit:y(u.get("limit"),"limit",1,100,50),..."class"in t&&(t.class==="broker"||t.class==="cron")&&r!==null?{visible:c(w=>b(t,r,w),"visible")}:{}})}}case"run.get":{const e=v("run.get",u),s=f(t,i),r=await z(i,s.grantee,e);return f(t,i),{status:200,body:r}}case"run.message":{const e=l(d);if(typeof e.message!="string"||!e.message.trim())throw new n(400,"invalid_request","message is required","message");if(e.start_turn!==void 0&&typeof e.start_turn!="boolean")throw new n(400,"invalid_request","start_turn must be a boolean","start_turn");return{status:202,body:await A(f(t,i,!0),e.message,void 0,e.start_turn,h(_))}}case"run.interrupt":{const e=l(d===void 0?{}:d);if(e.children!==void 0&&e.children!=="stop"&&e.children!=="continue")throw new n(400,"invalid_request","invalid children","children");return{status:200,body:await O(f(t,i,!0),e.children)}}case"run.cancel":{const e=l(d===void 0?{}:d);if(e.keep_schedules!==void 0&&typeof e.keep_schedules!="boolean")throw new n(400,"invalid_request","invalid keep_schedules","keep_schedules");return{status:200,body:await S(f(t,i,!0),{keepSchedules:e.keep_schedules})}}case"run.rename":{const e=l(d);for(const s of Object.keys(e))if(s!=="name")throw new n(400,"invalid_request",`unknown field ${s}`,s);return{status:200,body:j(f(t,i,!0),e.name)}}case"run.delete":{const{uploads_pending:e}=await N(f(t,i,!0,!0));return{status:200,body:{run_id:i,uploads_pending:e}}}case"trace.get":{const e=u.get("format")??void 0;if(e&&e!=="entries")throw new n(400,"invalid_request","unknown trace format","format");const s=f(t,i);return{status:200,body:J(i,s.grantee,e)}}default:throw new n(404,"not_found","unknown operation")}}c(I,"handleRunOperation");export{I as handleRunOperation,y as integer};
1
+ var R=Object.defineProperty;var m=(a,t)=>R(a,"name",{value:t,configurable:!0});import{callerGrant as h}from"../principal.js";import{grantVersion as g}from"../../../core/grants/mirror.js";import{waitGrantChange as S}from"../../../core/grants/watch.js";import{RunError as n,idempotencyKeyOf as b,cancelRun as $,deleteRun as N,interruptRun as O,listRuns as A,messageRun as j,renameRun as x,requestedScopes as B,startRun as J,traceRun as z,waitRun as C}from"../../../core/runs/operations.js";import{canReadRun as v,requireRun as f,runCallerApp as E}from"../router.js";import{waitSeconds as y}from"../long-poll-wait.js";import{outputSchemaProblem as K}from"../../../core/runtime/structured-output.js";function l(a){if(!a||typeof a!="object"||Array.isArray(a))throw new n(400,"invalid_request","a JSON object is required");return a}m(l,"object");function q(a,t,i,u,d){if(a===null)return d;if(!/^(0|[1-9]\d*)$/.test(a)||!Number.isSafeInteger(Number(a))||Number(a)<i||Number(a)>u)throw new n(400,"invalid_request",`invalid ${t}`,t);return Number(a)}m(q,"integer");const T=256*1024;async function W(a,t,i,u,d,_){switch(a.name){case"grant.get":{if("class"in t)throw new n(403,"permission_error","an app token is required");const e=y("grant.get",u),s=u.get("since");if(s!==null&&!/^[A-Za-z0-9_-]{1,64}$/.test(s))throw new n(400,"invalid_request","invalid since","since");let o=h(t);return e&&s!==null&&g(o)===s&&(await S(t.grant,e),o=h(t)),{status:200,body:{sub:t.sub,grantee:t.grantee,client_id:t.client_id,grant:t.grant,rev:o.rev,resolved_scopes:o.resolved_scopes,spend_cap:o.spend_cap,exp:t.exp,payer:"user",dependencies:o.dependencies??{},version:g(o)}}}case"run.start":{if("class"in t)throw new n(403,"permission_error","an app token is required");const e=l(d),s=["mode","parent","fork_from","node_id","env","tools","system_prompt"];for(const r of s)if(e[r]!==void 0)throw new n(403,"owner_only",`${r} is owner-only`,r);const o=["payer","model","model_policy","deadline","kind"];for(const r of o)if(e[r]!==void 0)throw new n(400,"invalid_request",`${r} is not available`,r);for(const r of Object.keys(e))if(!["prompt","scopes","metadata","profile","isolated","cwd","worktree","output_schema","message"].includes(r))throw new n(400,"invalid_request",`unknown field ${r}`,r);if(e.profile!==void 0&&(typeof e.profile!="string"||!e.profile))throw new n(400,"invalid_request","profile must be a profile id","profile");if(e.isolated!==void 0&&typeof e.isolated!="boolean")throw new n(400,"invalid_request","isolated must be a boolean","isolated");if(e.cwd!==void 0&&(e.isolated!==!0||typeof e.cwd!="string"||!e.cwd))throw new n(400,"invalid_request","cwd is available only for an isolated run and must be an absolute path inside its root folder","cwd");if(e.worktree!==void 0&&e.isolated!==!0)throw new n(400,"invalid_request","worktree is not available","worktree");if(e.isolated===!0&&e.worktree!==void 0)throw new n(400,"invalid_request","worktree is unavailable for an isolated run","worktree");if(typeof e.prompt!="string"||!e.prompt.trim())throw new n(400,"invalid_request","prompt is required","prompt");if(e.message!==void 0&&(typeof e.message!="string"||!e.message.trim()))throw new n(400,"invalid_request","message must be a non-empty string","message");const c=e.metadata===void 0?{}:l(e.metadata);if(Buffer.byteLength(JSON.stringify(c))>4096)throw new n(400,"invalid_request","metadata exceeds 4 KB","metadata");let w;if(e.output_schema!==void 0){const r=e.output_schema;if(!r||typeof r!="object"||Array.isArray(r))throw new n(400,"invalid_request","output_schema must be a JSON Schema object","output_schema");if(Buffer.byteLength(JSON.stringify(r))>T)throw new n(400,"invalid_request","output_schema exceeds 256 KB","output_schema");const p=await K(r);if(p!==null)throw new n(400,"invalid_request",`output_schema is not usable: ${p}`,"output_schema");w=r}const k=B(t.resolved,e.scopes,t.grantee);return{status:201,body:await J(t,{prompt:e.prompt,scopes:k,metadata:c,profile:e.profile,isolated:e.isolated,cwd:e.cwd,...w===void 0?{}:{output_schema:w},...e.message===void 0?{}:{message:e.message}},b(_))}}case"run.list":{const e=u.get("status")??void 0;if(e&&!["running","waiting_on_user","idle","settled"].includes(e))throw new n(400,"invalid_request","invalid status","status");const s=u.get("app");if(s!==null&&!/^(?:app:)?[a-z0-9][a-z0-9-]*$/.test(s))throw new n(400,"invalid_request","invalid app","app");const o=s===null?E(t):s.startsWith("app:")?s:`app:${s}`;if(o!==null&&!v(t,o))throw new n(404,"not_found","run not found");return{status:200,body:A(o,{status:e,after:u.get("after")??void 0,limit:q(u.get("limit"),"limit",1,100,50),..."class"in t&&(t.class==="broker"||t.class==="cron")&&o!==null?{visible:m(c=>v(t,o,c),"visible")}:{}})}}case"run.get":{const e=y("run.get",u),s=f(t,i),o=await C(i,s.grantee,e);return f(t,i),{status:200,body:o}}case"run.message":{const e=l(d);if(typeof e.message!="string"||!e.message.trim())throw new n(400,"invalid_request","message is required","message");if(e.start_turn!==void 0&&typeof e.start_turn!="boolean")throw new n(400,"invalid_request","start_turn must be a boolean","start_turn");return{status:202,body:await j(f(t,i,!0),e.message,void 0,e.start_turn,b(_))}}case"run.interrupt":{const e=l(d===void 0?{}:d);if(e.children!==void 0&&e.children!=="stop"&&e.children!=="continue")throw new n(400,"invalid_request","invalid children","children");return{status:200,body:await O(f(t,i,!0),e.children)}}case"run.cancel":{const e=l(d===void 0?{}:d);if(e.keep_schedules!==void 0&&typeof e.keep_schedules!="boolean")throw new n(400,"invalid_request","invalid keep_schedules","keep_schedules");return{status:200,body:await $(f(t,i,!0),{keepSchedules:e.keep_schedules})}}case"run.rename":{const e=l(d);for(const s of Object.keys(e))if(s!=="name")throw new n(400,"invalid_request",`unknown field ${s}`,s);return{status:200,body:x(f(t,i,!0),e.name)}}case"run.delete":{const{uploads_pending:e}=await N(f(t,i,!0,!0));return{status:200,body:{run_id:i,uploads_pending:e}}}case"trace.get":{const e=u.get("format")??void 0;if(e&&e!=="entries")throw new n(400,"invalid_request","unknown trace format","format");const s=f(t,i);return{status:200,body:z(i,s.grantee,e)}}default:throw new n(404,"not_found","unknown operation")}}m(W,"handleRunOperation");export{W as handleRunOperation,q as integer};
@@ -1 +1 @@
1
- var O=Object.defineProperty;var i=(t,e)=>O(t,"name",{value:e,configurable:!0});import{isSafeNodeId as h}from"../../../core/canvas/paths.js";import{admitStructuredRequest as T,bindStructuredRequest as N,getPendingStructuredRequestForNode as P,getStructuredRequest as c,settleStructuredRequest as l,toStructuredRequestDTO as _}from"../../../core/canvas/structured-requests.js";import{getNode as S}from"../../../core/canvas/canvas.js";import{ApiError as D}from"../../../api/errors.js";import{handleCreate as j}from"./nodes.js";import{handleMessage as E}from"./messages.js";import{writeStructuredRequestSidecar as k}from"../../../core/runtime/structured-output.js";import{requestBrokerTeardown as x}from"../../../core/runtime/host.js";import{transition as $}from"../../../core/runtime/lifecycle.js";import{subscribeStructuredRequest as C}from"../../structured-requests/notifier.js";import{SYNC_WORK_BUDGET_MS as R}from"../../../api/index.js";import{waitSeconds as I}from"../long-poll-wait.js";function d(t,e,n){throw new D(t,e,n)}i(d,"fail");function M(t){(typeof t!="object"||t===null||Array.isArray(t))&&d(400,"invalid_request","a structured request requires a JSON object");const e=t;(typeof e.request_id!="string"||!h(e.request_id))&&d(400,"request_id_invalid","request_id must use the node-id character rule"),e.mode!=="sync"&&e.mode!=="async"&&d(400,"invalid_request","mode must be sync or async"),typeof e.prompt!="string"&&d(400,"invalid_request","prompt must be a string"),(typeof e.output_schema!="object"||e.output_schema===null||Array.isArray(e.output_schema))&&d(400,"invalid_request","output_schema must be a JSON Schema object");const n=e.target;(typeof n!="object"||n===null)&&d(400,"invalid_request","target is required");const r=n;if(r.kind==="node")(typeof r.node_id!="string"||!h(r.node_id))&&d(400,"invalid_request","target.node_id must use the node-id character rule");else if(r.kind==="new"){(typeof r.create!="object"||r.create===null||Array.isArray(r.create))&&d(400,"invalid_request","target.create must be an object");for(const u of["prompt","output_schema","deadline","root_lifecycle","no_kickoff"])Object.hasOwn(r.create,u)&&d(400,"create_field_forbidden",`target.create may not carry ${u}`)}else d(400,"invalid_request","target.kind must be new or node");return e.work_budget_ms!==void 0&&(!Number.isInteger(e.work_budget_ms)||e.work_budget_ms<=0)&&d(400,"work_budget_invalid","work_budget_ms must be a positive integer"),e.deadline_at!==void 0&&(typeof e.deadline_at!="string"||Number.isNaN(Date.parse(e.deadline_at)))&&d(400,"invalid_request","deadline_at must be an ISO timestamp"),e}i(M,"parseCreate");function F(t,e){const n=t.deadline_at===void 0?null:Date.parse(t.deadline_at),r=t.work_budget_ms===void 0?null:e+t.work_budget_ms,u=n===null?r:r===null?n:Math.min(n,r);return t.mode==="sync"?Math.min(u??e+R,e+R):u}i(F,"deadlineFor");function v(t,e,n=""){return{...t,method:"POST",path:"",params:n===""?{}:{id:n},query:new URLSearchParams,body:e}}i(v,"context");function q(t){return{status:200,body:{admitted:!0,request:_(t)}}}i(q,"terminalAdmission");function f(t){return t!==null&&Date.now()>=t}i(f,"deadlinePassed");function w(t){return q(l(t,{intended:"expired"}).row)}i(w,"expireAdmission");async function A(t,e){let n;const r=new Promise(m=>{n=m}),u=C(t,n);try{return c(t).state==="pending"&&e>0&&await Promise.race([r,new Promise(p=>setTimeout(p,e))]),_(c(t))}finally{u()}}i(A,"waitForRequest");async function B(t,e){const n=await A(t,Math.max(0,e-Date.now()));return n.state==="pending"?_(l(t,{intended:"expired"}).row):n}i(B,"waitForTerminal");async function L(t){const e=M(t.body);e.mode==="sync"&&e.target.kind!=="new"&&d(400,"sync_requires_dedicated_node","sync requests require target.kind=new");const n=Date.now(),r=F(e,n);if(f(r))return{status:200,body:{admitted:!1,reason:"work_budget_exhausted"}};let u=null,m="terminal",p=!0;if(e.target.kind==="node"){u=e.target.node_id;const s=S(u);s===null&&d(404,"node_not_found",`unknown node: ${u}`),(s.final_report!==null||s.status==="done"||s.status==="canceled"||s.status==="dead")&&d(409,"node_terminal",`node ${u} is terminal`),P(u)!==null&&d(409,"structured_request_conflict",`node ${u} already has a pending structured request`),m="oneoff",p=!1}if(f(r))return{status:200,body:{admitted:!1,reason:"work_budget_exhausted"}};let y;try{y=T({requestId:e.request_id,mode:e.mode,submission:m,dedicated:p,schema:e.output_schema,deadlineAt:r,nodeId:u,now:Date.now()})}catch(s){const a=String(s);throw(s.code==="ERR_SQLITE_CONSTRAINT_PRIMARYKEY"||a.includes("structured_requests.request_id"))&&d(409,"request_id_in_use",`request_id ${e.request_id} is already in use`),(a.includes("idx_structured_requests_one_pending_node")||a.includes("structured_requests.node_id"))&&d(409,"structured_request_conflict","the target node already has a pending structured request"),s}if(f(r))return w(e.request_id);if(e.target.kind==="new")try{u=(await j(v(t,{...e.target.create,root:!0,root_lifecycle:"terminal",prompt:""}),{},{...r===null?{}:{deadlineAt:new Date(r).toISOString()},beforeBrokerLaunch:i(a=>{if(u=a,f(r))throw new Error("structured request deadline expired before binding");const o=N(e.request_id,a);if(!o.changed||o.row===null||o.row.state!=="pending")throw new Error("structured request bind did not remain pending");u=a,k(o.row)},"beforeBrokerLaunch")})).body.node_id}catch{const a=c(e.request_id),o=a.state==="pending"?l(e.request_id,{intended:"failed",failureReason:a.node_id===null?"node_create_failed":"bind_failed"}).row:a;if(u!==null&&o.node_id===null){const b=S(u);(b?.status==="active"||b?.status==="idle")&&$(u,"cancel",{reason:"stranded"}),await x(u)}return q(o)}else{if(f(r))return w(e.request_id);try{k(y)}catch{return q(l(e.request_id,{intended:"failed",failureReason:"bind_failed"}).row)}}const g=c(e.request_id);if(g.state!=="pending")return q(g);if(f(r))return w(e.request_id);try{await E(v(t,{body:e.prompt,tier:"normal"},u))}catch{return q(l(e.request_id,{intended:"failed",failureReason:"prompt_delivery_failed"}).row)}return e.mode==="async"?{status:202,body:{admitted:!0,request:_(c(e.request_id))}}:{status:200,body:{admitted:!0,request:await B(e.request_id,r)}}}i(L,"handleCreateStructuredRequest");async function Y(t){const e=t.params.request_id,n=I("structured-request.get",t.query),r=c(e);return r===null&&d(404,"structured_request_not_found",`unknown structured request: ${e}`),{status:200,body:n===0?_(r):await A(e,n*1e3)}}i(Y,"handleReadStructuredRequest");async function G(t){const e=l(t.params.request_id,{intended:"canceled"});return e.row===null&&d(404,"structured_request_not_found",`unknown structured request: ${t.params.request_id}`),{status:200,body:_(e.row)}}i(G,"handleCancelStructuredRequest");const ne=[{method:"POST",pattern:"/v1/structured-requests",handler:L},{method:"GET",pattern:"/v1/structured-requests/:request_id",handler:Y},{method:"POST",pattern:"/v1/structured-requests/:request_id/cancel",handler:G}];export{ne as structuredRequestRoutes};
1
+ var P=Object.defineProperty;var i=(t,e)=>P(t,"name",{value:e,configurable:!0});import{isSafeNodeId as S}from"../../../core/canvas/paths.js";import{admitStructuredRequest as T,bindStructuredRequest as N,getPendingStructuredRequestForNode as D,getStructuredRequest as l,settleStructuredRequest as _,toStructuredRequestDTO as f}from"../../../core/canvas/structured-requests.js";import{getNode as k}from"../../../core/canvas/canvas.js";import{ApiError as j}from"../../../api/errors.js";import{handleCreate as E}from"./nodes.js";import{handleMessage as $}from"./messages.js";import{outputSchemaProblem as x,writeStructuredRequestSidecar as R}from"../../../core/runtime/structured-output.js";import{requestBrokerTeardown as C}from"../../../core/runtime/host.js";import{transition as I}from"../../../core/runtime/lifecycle.js";import{subscribeStructuredRequest as M}from"../../structured-requests/notifier.js";import{SYNC_WORK_BUDGET_MS as v}from"../../../api/index.js";import{waitSeconds as F}from"../long-poll-wait.js";function n(t,e,r){throw new j(t,e,r)}i(n,"fail");function B(t){(typeof t!="object"||t===null||Array.isArray(t))&&n(400,"invalid_request","a structured request requires a JSON object");const e=t;(typeof e.request_id!="string"||!S(e.request_id))&&n(400,"request_id_invalid","request_id must use the node-id character rule"),e.mode!=="sync"&&e.mode!=="async"&&n(400,"invalid_request","mode must be sync or async"),typeof e.prompt!="string"&&n(400,"invalid_request","prompt must be a string"),(typeof e.output_schema!="object"||e.output_schema===null||Array.isArray(e.output_schema))&&n(400,"invalid_request","output_schema must be a JSON Schema object");const r=e.target;(typeof r!="object"||r===null)&&n(400,"invalid_request","target is required");const u=r;if(u.kind==="node")(typeof u.node_id!="string"||!S(u.node_id))&&n(400,"invalid_request","target.node_id must use the node-id character rule");else if(u.kind==="new"){(typeof u.create!="object"||u.create===null||Array.isArray(u.create))&&n(400,"invalid_request","target.create must be an object");for(const s of["prompt","output_schema","deadline","root_lifecycle","no_kickoff"])Object.hasOwn(u.create,s)&&n(400,"create_field_forbidden",`target.create may not carry ${s}`)}else n(400,"invalid_request","target.kind must be new or node");return e.work_budget_ms!==void 0&&(!Number.isInteger(e.work_budget_ms)||e.work_budget_ms<=0)&&n(400,"work_budget_invalid","work_budget_ms must be a positive integer"),e.deadline_at!==void 0&&(typeof e.deadline_at!="string"||Number.isNaN(Date.parse(e.deadline_at)))&&n(400,"invalid_request","deadline_at must be an ISO timestamp"),e}i(B,"parseCreate");function L(t,e){const r=t.deadline_at===void 0?null:Date.parse(t.deadline_at),u=t.work_budget_ms===void 0?null:e+t.work_budget_ms,s=r===null?u:u===null?r:Math.min(r,u);return t.mode==="sync"?Math.min(s??e+v,e+v):s}i(L,"deadlineFor");function A(t,e,r=""){return{...t,method:"POST",path:"",params:r===""?{}:{id:r},query:new URLSearchParams,body:e}}i(A,"context");function q(t){return{status:200,body:{admitted:!0,request:f(t)}}}i(q,"terminalAdmission");function m(t){return t!==null&&Date.now()>=t}i(m,"deadlinePassed");function w(t){return q(_(t,{intended:"expired"}).row)}i(w,"expireAdmission");async function O(t,e){let r;const u=new Promise(d=>{r=d}),s=M(t,r);try{return l(t).state==="pending"&&e>0&&await Promise.race([u,new Promise(p=>setTimeout(p,e))]),f(l(t))}finally{s()}}i(O,"waitForRequest");async function Y(t,e){const r=await O(t,Math.max(0,e-Date.now()));return r.state==="pending"?f(_(t,{intended:"expired"}).row):r}i(Y,"waitForTerminal");async function G(t){const e=B(t.body),r=await x(e.output_schema);r!==null&&n(400,"invalid_request",`output_schema is not usable: ${r}`),e.mode==="sync"&&e.target.kind!=="new"&&n(400,"sync_requires_dedicated_node","sync requests require target.kind=new");const u=Date.now(),s=L(e,u);if(m(s))return{status:200,body:{admitted:!1,reason:"work_budget_exhausted"}};let d=null,p="terminal",y=!0;if(e.target.kind==="node"){d=e.target.node_id;const a=k(d);a===null&&n(404,"node_not_found",`unknown node: ${d}`),(a.final_report!==null||a.status==="done"||a.status==="canceled"||a.status==="dead")&&n(409,"node_terminal",`node ${d} is terminal`),D(d)!==null&&n(409,"structured_request_conflict",`node ${d} already has a pending structured request`),p="oneoff",y=!1}if(m(s))return{status:200,body:{admitted:!1,reason:"work_budget_exhausted"}};let b;try{b=T({requestId:e.request_id,mode:e.mode,submission:p,dedicated:y,schema:e.output_schema,deadlineAt:s,nodeId:d,now:Date.now()})}catch(a){const o=String(a);throw(a.code==="ERR_SQLITE_CONSTRAINT_PRIMARYKEY"||o.includes("structured_requests.request_id"))&&n(409,"request_id_in_use",`request_id ${e.request_id} is already in use`),(o.includes("idx_structured_requests_one_pending_node")||o.includes("structured_requests.node_id"))&&n(409,"structured_request_conflict","the target node already has a pending structured request"),a}if(m(s))return w(e.request_id);if(e.target.kind==="new")try{d=(await E(A(t,{...e.target.create,root:!0,root_lifecycle:"terminal",prompt:""}),{},{...s===null?{}:{deadlineAt:new Date(s).toISOString()},beforeBrokerLaunch:i(o=>{if(d=o,m(s))throw new Error("structured request deadline expired before binding");const c=N(e.request_id,o);if(!c.changed||c.row===null||c.row.state!=="pending")throw new Error("structured request bind did not remain pending");d=o,R(c.row)},"beforeBrokerLaunch")})).body.node_id}catch{const o=l(e.request_id),c=o.state==="pending"?_(e.request_id,{intended:"failed",failureReason:o.node_id===null?"node_create_failed":"bind_failed"}).row:o;if(d!==null&&c.node_id===null){const g=k(d);(g?.status==="active"||g?.status==="idle")&&I(d,"cancel",{reason:"stranded"}),await C(d)}return q(c)}else{if(m(s))return w(e.request_id);try{R(b)}catch{return q(_(e.request_id,{intended:"failed",failureReason:"bind_failed"}).row)}}const h=l(e.request_id);if(h.state!=="pending")return q(h);if(m(s))return w(e.request_id);try{await $(A(t,{body:e.prompt,tier:"normal"},d))}catch{return q(_(e.request_id,{intended:"failed",failureReason:"prompt_delivery_failed"}).row)}return e.mode==="async"?{status:202,body:{admitted:!0,request:f(l(e.request_id))}}:{status:200,body:{admitted:!0,request:await Y(e.request_id,s)}}}i(G,"handleCreateStructuredRequest");async function J(t){const e=t.params.request_id,r=F("structured-request.get",t.query),u=l(e);return u===null&&n(404,"structured_request_not_found",`unknown structured request: ${e}`),{status:200,body:r===0?f(u):await O(e,r*1e3)}}i(J,"handleReadStructuredRequest");async function K(t){const e=_(t.params.request_id,{intended:"canceled"});return e.row===null&&n(404,"structured_request_not_found",`unknown structured request: ${t.params.request_id}`),{status:200,body:f(e.row)}}i(K,"handleCancelStructuredRequest");const se=[{method:"POST",pattern:"/v1/structured-requests",handler:G},{method:"GET",pattern:"/v1/structured-requests/:request_id",handler:J},{method:"POST",pattern:"/v1/structured-requests/:request_id/cancel",handler:K}];export{se as structuredRequestRoutes};
@@ -341,7 +341,7 @@ if (outcome.kind === 'result') {
341
341
  }
342
342
  ```
343
343
 
344
- The runtime validates the value before it records it. A submission that does not match is refused with its field errors and never appears in `runs.get`, an event, or a report, so the agent fixes it and resubmits. `output_schema` accepts a plain JSON Schema object or anything with `toJSONSchema()`, such as a Zod v4 object. The SDK sends it as a JSON object and validates nothing itself. A schema that is not an object, or is over 256 KB serialized, is refused with `invalid_request` and `param: 'output_schema'`, and no run is created. A submitted result can be at most 1 MiB. The agent submits with its `submit_result` tool, which needs no scope, so a run that only reasons and answers can be started with `scopes: ['crtr:llm']`. The same value is in `runs.get(runId).result`, which `runs.wait` returns unchanged, and on the run's `node.settled` event.
344
+ The runtime validates the value before it records it. A submission that does not match is refused with its field errors and never appears in `runs.get`, an event, or a report, so the agent fixes it and resubmits. `output_schema` accepts a plain JSON Schema object or anything with `toJSONSchema()`, such as a Zod v4 object. The SDK sends it as a JSON object and validates nothing itself. A schema that is not an object, or is over 256 KB serialized, is refused with `invalid_request` and `param: 'output_schema'`, and no run is created. A submitted result can be at most 1 MiB. The value is validated exactly as submitted, with no coercion: `null` is never turned into `0` or `""`, and `"5"` is not turned into `5`, so a mismatch is refused and the agent resubmits. The schema is one JSON object, so a `$ref` can point only into itself (`#/$defs/x`, `#anchor`) or at another schema document bundled under `$defs` with its own `$id` (`"$defs": { "common": { "$id": "common.schema.json", ... } }` resolves `common.schema.json#/$defs/x`). Files are never fetched. A schema with a `$ref` that resolves nowhere inside it, or one that cannot be compiled (a bad `pattern`), is refused with `invalid_request` and `param: 'output_schema'` and no run is created. The agent submits with its `submit_result` tool, which needs no scope, so a run that only reasons and answers can be started with `scopes: ['crtr:llm']`. The same value is in `runs.get(runId).result`, which `runs.wait` returns unchanged, and on the run's `node.settled` event.
345
345
 
346
346
  Do not parse assistant text out of `runs.trace` to get data back. `runs.trace` is for showing a person the transcript. Its text is whatever the model said, not a value anything checked.
347
347
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.452",
3
+ "version": "0.3.454",
4
4
  "description": "crtr — agent runtime with memory, plugins, and marketplaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -137,7 +137,7 @@
137
137
  },
138
138
  "license": "UNLICENSED",
139
139
  "dependencies": {
140
- "@north-light/identity": "0.3.452",
140
+ "@north-light/identity": "0.3.454",
141
141
  "@earendil-works/pi-agent-core": "1.1.0",
142
142
  "@earendil-works/pi-ai": "1.1.0",
143
143
  "@earendil-works/pi-coding-agent": "1.1.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/identity",
3
- "version": "0.3.452",
3
+ "version": "0.3.454",
4
4
  "description": "Northlight access-token verification and scope rules",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",