@north-light/cli 0.3.595 → 0.3.596

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.
@@ -1,2 +1,2 @@
1
- var x=Object.defineProperty;var a=(n,t)=>x(n,"name",{value:t,configurable:!0});import{ApiError as A}from"../../api/errors.js";import{envGrantee as E}from"../../shared/env.js";import{deriveNameFromUrl as C}from"../../core/git.js";import{notFound as u,usage as O,CrtrError as h}from"../../core/errors.js";import{nowIso as k}from"../../core/fs-utils.js";import{appRevisionOf as P,currentSnapshot as j,writeSettings as R}from"../../core/scoped-state/person-store.js";import{ExitCode as w}from"../../types.js";import{cliClient as y,rethrowAsCliError as m}from"../api-client.js";const v={name:"crouter-official-marketplace",url:"https://github.com/crouton-labs/crouter-official-marketplace.git"},c=a(()=>E()??"app:terminal","appId"),p=a(()=>j().apps[c()]??{plugins:{},marketplaces:{},revision:"absent"},"block");async function d(n){const t=c();await R(r=>{const i=r.apps[t],s=structuredClone({plugins:i?.plugins??{},marketplaces:i?.marketplaces??{}});return n(s),[{op:"app-plugins.replace",app:t,plugins:s.plugins,marketplaces:s.marketplaces,ifRevision:P(i)}]})}a(d,"change");async function $(n){return await b(n).catch(t=>m(t))}a($,"resolve");async function b(n){return await y().documents.reconcilePackages({plugins:n})}a(b,"resolveRaw");async function _(){return await y().documents.reconcilePackages().catch(n=>m(n))}a(_,"resolveAll");function f(n,t){const r={not_public:"installed without documents: the directory reads public marketplaces only",not_found:"installed without documents: the directory does not list it",directory_unreachable:"installed; its documents arrive on the next sync because the directory is unreachable"},i=(n.unavailable??[]).filter(e=>t===void 0||e.plugin===t).map(e=>`${e.plugin}: ${r[e.reason]}`),s=n.invalid.filter(e=>t===void 0||e.path.startsWith(`${t}/`)).map(e=>`${e.path.split("/")[0]}: ${e.path} was not published: ${e.error}`),l=(n.kinds?.refused??[]).filter(e=>t===void 0||e.plugin===t).map(e=>`${e.plugin}: kind ${e.kind} not registered: ${e.message}`);return[...i,...s,...l]}a(f,"unavailableWarnings");async function q(n){const t=n.split("/");if(t.length!==2||t[0]===""||t[1]==="")throw O(`invalid plugin install ref: ${n}
2
- A sandboxed node installs marketplace/plugin from a marketplace added with \`crtr pkg market add\`.`);const[r,i]=t,s=p();if(s.plugins[i]!==void 0)throw new h("conflict",`plugin "${i}" is already installed in ${c()}`,w.GENERAL);const l=s.marketplaces[r]??(r===v.name?{url:v.url,ref:"main",installed_at:k()}:void 0);if(l===void 0)throw u(`marketplace not found: ${r}`);await d(e=>{e.marketplaces[r]=l,e.plugins[i]={enabled:!0,source_marketplace:r}});try{const e=await b([i]),o=f(e,i);return{name:i,app:c(),...o.length>0?{warnings:o}:{}}}catch(e){if(!(e instanceof A)||e.code!=="name_taken"&&e.code!=="not_found")return m(e);throw await d(o=>{delete o.plugins[i],s.marketplaces[r]===void 0&&!Object.values(o.plugins).some(g=>g.source_marketplace===r)&&delete o.marketplaces[r]}),e.code==="not_found"?u(e.message):new h("conflict",`${e.message}; uninstall that marketplace's plugin or pick another`,w.GENERAL,{plugin:i})}}a(q,"installAppPlugin");async function z(n){if(p().plugins[n]===void 0)throw u(`plugin not found: ${n}`);return await d(t=>{delete t.plugins[n]}),{app:c()}}a(z,"removeAppPlugin");async function B(n,t){if(p().plugins[n]===void 0)throw u(`plugin not found: ${n}`);await d(i=>{i.plugins[n]={...i.plugins[n],enabled:t}});const r=t?f(await $([n]),n):[];return{name:n,app:c(),enabled:t,...r.length>0?{warnings:r}:{}}}a(B,"setAppPluginEnabled");async function D(n){const t=Object.keys(p().plugins);if(n!==void 0&&!t.includes(n))throw u(`plugin not found: ${n}`);const r=n===void 0?t:[n],i=r.length===0?void 0:n===void 0?await _():await $(r),s=a(l=>(i?.conflicts??[]).filter(e=>e.plugin===l).map(e=>`${l}: no documents: ${e.message}`),"conflicted");return{updated:r.map(l=>{const e=i===void 0?[]:[...s(l),...f(i,l)];return{name:l,...e.length>0?{warnings:e}:{}}})}}a(D,"updateAppPlugins");async function H(n){const t=Object.entries(p().plugins).filter(([,e])=>n||e.enabled!==!1).sort(([e],[o])=>e.localeCompare(o)),i=t.filter(([,e])=>e.enabled!==!1).map(([e])=>e).length===0?void 0:await _(),s=a(e=>{const o=i?.conflicts.find(g=>g.plugin===e);return o!==void 0?`no documents: ${o.message}`:i===void 0?void 0:f(i,e)[0]},"why"),l=t.map(([e,o])=>({name:e,scope:c(),enabled:o.enabled!==!1,...o.source_marketplace===void 0?{}:{source_marketplace:o.source_marketplace},...o.version===void 0?{}:{version:o.version},...s(e)===void 0?{}:{documents:s(e)}}));return{items:l,next_cursor:null,total:l.length}}a(H,"listAppPlugins");async function J(n,t){const r=C(n);return await d(i=>{i.marketplaces[r]={url:n,ref:t??"main",installed_at:k()}}),{name:r,app:c()}}a(J,"addAppMarketplace");function K(){const n=Object.entries(p().marketplaces).sort(([t],[r])=>t.localeCompare(r)).map(([t,r])=>({name:t,scope:c(),url:r.url,ref:r.ref}));return{items:n,next_cursor:null,total:n.length}}a(K,"listAppMarketplaces");async function Q(n){if(p().marketplaces[n]===void 0)throw u(`marketplace not found: ${n}`);return await d(t=>{delete t.marketplaces[n];for(const[r,i]of Object.entries(t.plugins))i.source_marketplace===n&&delete t.plugins[r]}),{app:c()}}a(Q,"removeAppMarketplace");export{J as addAppMarketplace,c as appId,q as installAppPlugin,K as listAppMarketplaces,H as listAppPlugins,Q as removeAppMarketplace,z as removeAppPlugin,B as setAppPluginEnabled,D as updateAppPlugins};
1
+ var x=Object.defineProperty;var i=(n,t)=>x(n,"name",{value:t,configurable:!0});import{ApiError as A}from"../../api/errors.js";import{envGrantee as E}from"../../shared/env.js";import{deriveNameFromUrl as C}from"../../core/git.js";import{notFound as u,usage as O,CrtrError as h}from"../../core/errors.js";import{nowIso as k}from"../../core/fs-utils.js";import{appRevisionOf as P,currentSnapshot as j,writeSettings as R}from"../../core/scoped-state/person-store.js";import{ExitCode as w}from"../../types.js";import{cliClient as y,rethrowAsCliError as m}from"../api-client.js";const b={name:"crouter-official-marketplace",url:"https://github.com/crouton-labs/crouter-official-marketplace.git"},c=i(()=>E()??"app:terminal","appId"),p=i(()=>j().apps[c()]??{plugins:{},marketplaces:{},revision:"absent"},"block");async function d(n){const t=c();await R(r=>{const a=r.apps[t],s=structuredClone({plugins:a?.plugins??{},marketplaces:a?.marketplaces??{}});return n(s),[{op:"app-plugins.replace",app:t,plugins:s.plugins,marketplaces:s.marketplaces,ifRevision:P(a)}]})}i(d,"change");async function v(n){return await $(n).catch(t=>m(t))}i(v,"resolve");async function $(n){return await y().documents.reconcilePackages({plugins:n})}i($,"resolveRaw");async function _(){return await y().documents.reconcilePackages().catch(n=>m(n))}i(_,"resolveAll");function f(n,t){const r={not_public:"installed without documents: the directory reads public marketplaces only",not_found:"installed without documents: the directory does not list it",directory_unreachable:"installed; the directory did not answer this check, so documents already published stay readable and any not yet published arrive on the next package sync"},a=(n.unavailable??[]).filter(e=>t===void 0||e.plugin===t).map(e=>`${e.plugin}: ${r[e.reason]}`),s=n.invalid.filter(e=>t===void 0||e.path.startsWith(`${t}/`)).map(e=>`${e.path.split("/")[0]}: ${e.path} was not published: ${e.error}`),l=(n.kinds?.refused??[]).filter(e=>t===void 0||e.plugin===t).map(e=>`${e.plugin}: kind ${e.kind} not registered: ${e.message}`);return[...a,...s,...l]}i(f,"unavailableWarnings");async function q(n){const t=n.split("/");if(t.length!==2||t[0]===""||t[1]==="")throw O(`invalid plugin install ref: ${n}
2
+ A sandboxed node installs marketplace/plugin from a marketplace added with \`crtr pkg market add\`.`);const[r,a]=t,s=p();if(s.plugins[a]!==void 0)throw new h("conflict",`plugin "${a}" is already installed in ${c()}`,w.GENERAL);const l=s.marketplaces[r]??(r===b.name?{url:b.url,ref:"main",installed_at:k()}:void 0);if(l===void 0)throw u(`marketplace not found: ${r}`);await d(e=>{e.marketplaces[r]=l,e.plugins[a]={enabled:!0,source_marketplace:r}});try{const e=await $([a]),o=f(e,a);return{name:a,app:c(),...o.length>0?{warnings:o}:{}}}catch(e){if(!(e instanceof A)||e.code!=="name_taken"&&e.code!=="not_found")return m(e);throw await d(o=>{delete o.plugins[a],s.marketplaces[r]===void 0&&!Object.values(o.plugins).some(g=>g.source_marketplace===r)&&delete o.marketplaces[r]}),e.code==="not_found"?u(e.message):new h("conflict",`${e.message}; uninstall that marketplace's plugin or pick another`,w.GENERAL,{plugin:a})}}i(q,"installAppPlugin");async function z(n){if(p().plugins[n]===void 0)throw u(`plugin not found: ${n}`);return await d(t=>{delete t.plugins[n]}),{app:c()}}i(z,"removeAppPlugin");async function B(n,t){if(p().plugins[n]===void 0)throw u(`plugin not found: ${n}`);await d(a=>{a.plugins[n]={...a.plugins[n],enabled:t}});const r=t?f(await v([n]),n):[];return{name:n,app:c(),enabled:t,...r.length>0?{warnings:r}:{}}}i(B,"setAppPluginEnabled");async function D(n){const t=Object.keys(p().plugins);if(n!==void 0&&!t.includes(n))throw u(`plugin not found: ${n}`);const r=n===void 0?t:[n],a=r.length===0?void 0:n===void 0?await _():await v(r),s=i(l=>(a?.conflicts??[]).filter(e=>e.plugin===l).map(e=>`${l}: no documents: ${e.message}`),"conflicted");return{updated:r.map(l=>{const e=a===void 0?[]:[...s(l),...f(a,l)];return{name:l,...e.length>0?{warnings:e}:{}}})}}i(D,"updateAppPlugins");async function H(n){const t=Object.entries(p().plugins).filter(([,e])=>n||e.enabled!==!1).sort(([e],[o])=>e.localeCompare(o)),a=t.filter(([,e])=>e.enabled!==!1).map(([e])=>e).length===0?void 0:await _(),s=i(e=>{const o=a?.conflicts.find(g=>g.plugin===e);return o!==void 0?`no documents: ${o.message}`:a===void 0?void 0:f(a,e)[0]},"why"),l=t.map(([e,o])=>({name:e,scope:c(),enabled:o.enabled!==!1,...o.source_marketplace===void 0?{}:{source_marketplace:o.source_marketplace},...o.version===void 0?{}:{version:o.version},...s(e)===void 0?{}:{documents:s(e)}}));return{items:l,next_cursor:null,total:l.length}}i(H,"listAppPlugins");async function J(n,t){const r=C(n);return await d(a=>{a.marketplaces[r]={url:n,ref:t??"main",installed_at:k()}}),{name:r,app:c()}}i(J,"addAppMarketplace");function K(){const n=Object.entries(p().marketplaces).sort(([t],[r])=>t.localeCompare(r)).map(([t,r])=>({name:t,scope:c(),url:r.url,ref:r.ref}));return{items:n,next_cursor:null,total:n.length}}i(K,"listAppMarketplaces");async function Q(n){if(p().marketplaces[n]===void 0)throw u(`marketplace not found: ${n}`);return await d(t=>{delete t.marketplaces[n];for(const[r,a]of Object.entries(t.plugins))a.source_marketplace===n&&delete t.plugins[r]}),{app:c()}}i(Q,"removeAppMarketplace");export{J as addAppMarketplace,c as appId,q as installAppPlugin,K as listAppMarketplaces,H as listAppPlugins,Q as removeAppMarketplace,z as removeAppPlugin,B as setAppPluginEnabled,D as updateAppPlugins};
@@ -47,6 +47,10 @@ export declare function buildRequestPlan(spec: HttpInvokerSpec, input: Record<st
47
47
  * Shared by the HTTP-plugin plan and the provider-leaf adapter, so every
48
48
  * transport ships file content and none ships the path string. */
49
49
  export declare function readPathParam(commandLabel: string, param: InputParam, value: unknown): unknown;
50
+ /** Convert an authored kebab param name to the camelCase key parseArgv emits.
51
+ * Must stay identical to command.ts's flagNameToKey so lookups + the presence
52
+ * set line up. */
53
+ export declare function paramKey(name: string): string;
50
54
  /** Map a unary 2xx body to the validated result object, or throw
51
55
  * cli_protocol_error (GENERAL) for bad JSON / a non-object / an output mismatch. */
52
56
  export declare function mapUnary2xx(spec: HttpInvokerSpec, body: string): Record<string, unknown>;
@@ -1 +1 @@
1
- var R=Object.defineProperty;var c=(e,t)=>R(e,"name",{value:t,configurable:!0});import{readFileSync as O,statSync as k}from"node:fs";import{resolve as j}from"node:path";import{validateDeclaredResult as C}from"../../../api/command-manifest/result.js";import{CrtrError as w}from"../../errors.js";import{envelopeClaimsStale as P,staleErrorDetails as z}from"../../manifest-stale.js";import{ExitCode as h}from"../../../types.js";import{isRecord as x}from"../../../shared/predicates.js";import{trimHeaderValue as U}from"./sign.js";import{outboundTraceparent as q}from"../../../shared/traceparent.js";const T=/^[a-z][a-z0-9]*(_[a-z0-9]+)*$/,I=new Set(["internal","unknown_path","command_collision","cli_protocol_error"]),D=new Set(["authorization","crtr-request-id","crtr-run-id","crtr-approval","crtr-upload-id","crtr-upload-link","accept","content-type","crtr-caller","crtr-signature","traceparent"]),M=new Set(["crtr-caller","crtr-signature","crtr-request-id"]);function ne(e,t,r,n){const i=new Map;for(const o of e.params)i.set(o.name,o);const f=Object.entries(e.rest.params),u=e.baseUrl??new URL(e.registration.endpoint).origin;let y=e.rest.path;for(const[o,a]of f){if(a.in!=="path")continue;const s=t[b(o)];y=y.split(`{${o}}`).join(J(s))}const S=new URL(y,u);for(const[o,a]of f){if(a.in!=="query")continue;const s=b(o);v(i.get(o),s,t,r)&&S.searchParams.append(a.as??o,String(t[s]))}const m=G(e,f,i,t,r,n.fileMode),p=Object.keys(m).length>0?JSON.stringify(m):void 0,l={},d=c((o,a)=>{const s=Object.keys(l).find(g=>g.toLowerCase()===o.toLowerCase());s!==void 0&&delete l[s],l[o]=U(a)},"setHeader");d("Accept","application/json"),d("Crtr-Request-Id",n.requestId),n.authorization!==null&&d("Authorization",n.authorization);for(const[o,a]of f){if(a.in!=="header")continue;const s=b(o);if(!v(i.get(o),s,t,r))continue;const g=a.as;if(M.has(g.toLowerCase())||n.fileMode==="pass-through"&&D.has(g.toLowerCase()))throw new w("invalid_type",`${E(e)}: header "${g}" is reserved for the runtime`,h.USAGE,{field:o,next:"Remove the runtime-owned header mapping from the manifest."});const A=String(t[s]);if(/[\r\n]/.test(A))throw new w("invalid_type",`${E(e)}: header "${g}" value must not contain a newline`,h.USAGE,{field:o,received:"(newline in header value)",next:"Remove newline characters from the value."});d(g,A)}p!==void 0&&d("Content-Type","application/json");for(const[o,a]of Object.entries(n.extraHeaders)){if(n.fileMode==="pass-through"&&/[\r\n]/.test(a))throw new w("invalid_type",`${E(e)}: header "${o}" value must not contain a newline`,h.USAGE);d(o,a)}if(n.fileMode==="pass-through"){if(d("Accept","application/json"),p!==void 0)d("Content-Type","application/json");else{const o=Object.keys(l).find(a=>a.toLowerCase()==="content-type");o!==void 0&&delete l[o]}if(d("Crtr-Request-Id",n.requestId),n.traceId!==void 0&&d("traceparent",q(n.traceId)),n.authorization!==null)d("Authorization",n.authorization);else{const o=Object.keys(l).find(a=>a.toLowerCase()==="authorization");o!==void 0&&delete l[o]}}return{url:S,method:e.rest.method,headers:l,...p!==void 0?{body:p}:{}}}c(ne,"buildRequestPlan");function G(e,t,r,n,i,f){const u=new Map;for(const[m,p]of t){if(p.in!=="body")continue;const l=p.as??m,d=u.get(l);d!==void 0?d.push(m):u.set(l,[m])}const y={};for(const[m,p]of u){const l=p.map(s=>({name:s,param:r.get(s)})),d=l.find(s=>s.param.kind!=="stdin"),o=l.find(s=>s.param.kind==="stdin");let a;d!==void 0&&v(d.param,b(d.name),n,i)?a={param:d.param,value:n[b(d.name)]}:o!==void 0&&v(o.param,b(o.name),n,i)&&(a={param:o.param,value:n[b(o.name)]}),a!==void 0&&(y[m]=H(e,a.param,a.value,f))}const S={...e.rest.body};return e.rest.bodyRoot!==void 0?S[e.rest.bodyRoot]=y:Object.assign(S,y),S}c(G,"assembleBody");function H(e,t,r,n){return n==="pass-through"||t.kind==="context-file"?r:(t.kind==="positional"||t.kind==="flag")&&t.type==="path"?N(E(e),t,r):r}c(H,"materializeBodyValue");function N(e,t,r){if(Array.isArray(r))return r.map(u=>N(e,t,u));const n=String(r),i=j(process.cwd(),n);let f;try{f=k(i)}catch{throw _(e,t.name,n,"no file exists at that path","an existing local file path")}if(!f.isFile())throw _(e,t.name,n,"the path is not a regular file","a regular local file (not a directory, socket, or device)");try{return"encoding"in t&&t.encoding==="base64"?O(i).toString("base64"):O(i,"utf8")}catch{throw _(e,t.name,n,"the file could not be read","a readable local file path")}}c(N,"readPathParam");function _(e,t,r,n,i){return new w("invalid_type",`${e}: cannot read file for "${t}" \u2014 ${n}: ${r}`,h.USAGE,{field:t,received:r,next:`Pass ${i}, relative to the current directory or absolute.`})}c(_,"fileError");function v(e,t,r,n){return n!==void 0?n.providedParams.has(t):Object.prototype.hasOwnProperty.call(r,t)&&r[t]!==void 0}c(v,"isPresent");function J(e){const t=String(e);return t==="."||t===".."?t.replace(/\./g,"%2E"):encodeURIComponent(t)}c(J,"encodePathSegmentValue");function b(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}c(b,"paramKey");function oe(e,t){let r;try{r=JSON.parse(t)}catch{throw $(e,"response body was not valid JSON","a JSON object matching the declared output")}if(!x(r))throw $(e,`response body was not a JSON object (got ${B(r)})`,"a JSON object matching the declared output");const n=C(e.output,r);if(n!==null){const f=e.output.find(u=>u.name===n.field)?.type??"unknown";throw n.receivedType!==void 0?$(e,`output field "${n.field}" has the wrong type`,`${n.field}: ${n.expected??f}`):$(e,`response is missing required output field "${n.field}"`,`a "${n.field}" field of type ${f}`)}return r}c(oe,"mapUnary2xx");function ie(e,t,r){const n=V(t),i=L(r);if(i!==null){const f=T.test(i.code)&&!I.has(i.code);throw new w(f?i.code:"cli_protocol_error",i.message,n,{...i.received!==void 0?{received:i.received}:{},...i.field!==void 0?{field:i.field}:{},...i.manifestStale?z(e.registration.name):{},http_status:t,next:i.next??"Inspect the backend response, then retry if appropriate."})}throw new w("cli_http_error",`${E(e)}: request failed with HTTP ${t}`,n,{http_status:t,next:"Inspect the backend response, then retry if appropriate."})}c(ie,"throwNon2xx");function L(e){let t;try{t=JSON.parse(e)}catch{return null}if(!x(t)||!x(t.error))return null;const r=t.error;return typeof r.code!="string"||typeof r.message!="string"?null:{code:r.code,message:r.message,...typeof r.field=="string"?{field:r.field}:{},...r.received!==void 0?{received:r.received}:{},...typeof r.next=="string"?{next:r.next}:{},manifestStale:P(r),...r.question!==void 0?{question:r.question}:{}}}c(L,"parseHttpError");function V(e){return e===400||e===401||e===403||e===422?h.USAGE:e===404?h.NOT_FOUND:e===409?h.AMBIGUOUS:h.GENERAL}c(V,"deriveExit");function $(e,t,r){return new w("cli_protocol_error",`${E(e)}: ${t}. Expected ${r}.`,h.GENERAL,{received:t,next:`Run \`crtr pkg plugin update ${e.registration.name}\` or inspect the backend response.`})}c($,"protocolError");function E(e){return`HTTP-transport plugin "${e.registration.name}" command \`${e.commandPath.join(" ")}\``}c(E,"label");function B(e){return e===null?"null":Array.isArray(e)?"array":typeof e}c(B,"typeName");export{ne as buildRequestPlan,oe as mapUnary2xx,L as parseHttpError,N as readPathParam,ie as throwNon2xx};
1
+ var R=Object.defineProperty;var c=(e,t)=>R(e,"name",{value:t,configurable:!0});import{readFileSync as O,statSync as k}from"node:fs";import{resolve as j}from"node:path";import{validateDeclaredResult as C}from"../../../api/command-manifest/result.js";import{CrtrError as w}from"../../errors.js";import{envelopeClaimsStale as P,staleErrorDetails as z}from"../../manifest-stale.js";import{ExitCode as h}from"../../../types.js";import{isRecord as x}from"../../../shared/predicates.js";import{trimHeaderValue as U}from"./sign.js";import{outboundTraceparent as q}from"../../../shared/traceparent.js";const T=/^[a-z][a-z0-9]*(_[a-z0-9]+)*$/,I=new Set(["internal","unknown_path","command_collision","cli_protocol_error"]),D=new Set(["authorization","crtr-request-id","crtr-run-id","crtr-approval","crtr-upload-id","crtr-upload-link","accept","content-type","crtr-caller","crtr-signature","traceparent"]),M=new Set(["crtr-caller","crtr-signature","crtr-request-id"]);function ne(e,t,r,n){const i=new Map;for(const o of e.params)i.set(o.name,o);const f=Object.entries(e.rest.params),u=e.baseUrl??new URL(e.registration.endpoint).origin;let y=e.rest.path;for(const[o,a]of f){if(a.in!=="path")continue;const s=t[b(o)];y=y.split(`{${o}}`).join(J(s))}const S=new URL(y,u);for(const[o,a]of f){if(a.in!=="query")continue;const s=b(o);v(i.get(o),s,t,r)&&S.searchParams.append(a.as??o,String(t[s]))}const m=G(e,f,i,t,r,n.fileMode),p=Object.keys(m).length>0?JSON.stringify(m):void 0,l={},d=c((o,a)=>{const s=Object.keys(l).find(g=>g.toLowerCase()===o.toLowerCase());s!==void 0&&delete l[s],l[o]=U(a)},"setHeader");d("Accept","application/json"),d("Crtr-Request-Id",n.requestId),n.authorization!==null&&d("Authorization",n.authorization);for(const[o,a]of f){if(a.in!=="header")continue;const s=b(o);if(!v(i.get(o),s,t,r))continue;const g=a.as;if(M.has(g.toLowerCase())||n.fileMode==="pass-through"&&D.has(g.toLowerCase()))throw new w("invalid_type",`${E(e)}: header "${g}" is reserved for the runtime`,h.USAGE,{field:o,next:"Remove the runtime-owned header mapping from the manifest."});const A=String(t[s]);if(/[\r\n]/.test(A))throw new w("invalid_type",`${E(e)}: header "${g}" value must not contain a newline`,h.USAGE,{field:o,received:"(newline in header value)",next:"Remove newline characters from the value."});d(g,A)}p!==void 0&&d("Content-Type","application/json");for(const[o,a]of Object.entries(n.extraHeaders)){if(n.fileMode==="pass-through"&&/[\r\n]/.test(a))throw new w("invalid_type",`${E(e)}: header "${o}" value must not contain a newline`,h.USAGE);d(o,a)}if(n.fileMode==="pass-through"){if(d("Accept","application/json"),p!==void 0)d("Content-Type","application/json");else{const o=Object.keys(l).find(a=>a.toLowerCase()==="content-type");o!==void 0&&delete l[o]}if(d("Crtr-Request-Id",n.requestId),n.traceId!==void 0&&d("traceparent",q(n.traceId)),n.authorization!==null)d("Authorization",n.authorization);else{const o=Object.keys(l).find(a=>a.toLowerCase()==="authorization");o!==void 0&&delete l[o]}}return{url:S,method:e.rest.method,headers:l,...p!==void 0?{body:p}:{}}}c(ne,"buildRequestPlan");function G(e,t,r,n,i,f){const u=new Map;for(const[m,p]of t){if(p.in!=="body")continue;const l=p.as??m,d=u.get(l);d!==void 0?d.push(m):u.set(l,[m])}const y={};for(const[m,p]of u){const l=p.map(s=>({name:s,param:r.get(s)})),d=l.find(s=>s.param.kind!=="stdin"),o=l.find(s=>s.param.kind==="stdin");let a;d!==void 0&&v(d.param,b(d.name),n,i)?a={param:d.param,value:n[b(d.name)]}:o!==void 0&&v(o.param,b(o.name),n,i)&&(a={param:o.param,value:n[b(o.name)]}),a!==void 0&&(y[m]=H(e,a.param,a.value,f))}const S={...e.rest.body};return e.rest.bodyRoot!==void 0?S[e.rest.bodyRoot]=y:Object.assign(S,y),S}c(G,"assembleBody");function H(e,t,r,n){return n==="pass-through"||t.kind==="context-file"?r:(t.kind==="positional"||t.kind==="flag")&&t.type==="path"?N(E(e),t,r):r}c(H,"materializeBodyValue");function N(e,t,r){if(Array.isArray(r))return r.map(u=>N(e,t,u));const n=String(r),i=j(process.cwd(),n);let f;try{f=k(i)}catch{throw _(e,t.name,n,"no file exists at that path","an existing local file path")}if(!f.isFile())throw _(e,t.name,n,"the path is not a regular file","a regular local file (not a directory, socket, or device)");try{return"encoding"in t&&t.encoding==="base64"?O(i).toString("base64"):O(i,"utf8")}catch{throw _(e,t.name,n,"the file could not be read","a readable local file path")}}c(N,"readPathParam");function _(e,t,r,n,i){return new w("invalid_type",`${e}: cannot read file for "${t}" \u2014 ${n}: ${r}`,h.USAGE,{field:t,received:r,next:`Pass ${i}, relative to the current directory or absolute.`})}c(_,"fileError");function v(e,t,r,n){return n!==void 0?n.providedParams.has(t):Object.prototype.hasOwnProperty.call(r,t)&&r[t]!==void 0}c(v,"isPresent");function J(e){const t=String(e);return t==="."||t===".."?t.replace(/\./g,"%2E"):encodeURIComponent(t)}c(J,"encodePathSegmentValue");function b(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}c(b,"paramKey");function oe(e,t){let r;try{r=JSON.parse(t)}catch{throw $(e,"response body was not valid JSON","a JSON object matching the declared output")}if(!x(r))throw $(e,`response body was not a JSON object (got ${B(r)})`,"a JSON object matching the declared output");const n=C(e.output,r);if(n!==null){const f=e.output.find(u=>u.name===n.field)?.type??"unknown";throw n.receivedType!==void 0?$(e,`output field "${n.field}" has the wrong type`,`${n.field}: ${n.expected??f}`):$(e,`response is missing required output field "${n.field}"`,`a "${n.field}" field of type ${f}`)}return r}c(oe,"mapUnary2xx");function ie(e,t,r){const n=V(t),i=L(r);if(i!==null){const f=T.test(i.code)&&!I.has(i.code);throw new w(f?i.code:"cli_protocol_error",i.message,n,{...i.received!==void 0?{received:i.received}:{},...i.field!==void 0?{field:i.field}:{},...i.manifestStale?z(e.registration.name):{},http_status:t,next:i.next??"Inspect the backend response, then retry if appropriate."})}throw new w("cli_http_error",`${E(e)}: request failed with HTTP ${t}`,n,{http_status:t,next:"Inspect the backend response, then retry if appropriate."})}c(ie,"throwNon2xx");function L(e){let t;try{t=JSON.parse(e)}catch{return null}if(!x(t)||!x(t.error))return null;const r=t.error;return typeof r.code!="string"||typeof r.message!="string"?null:{code:r.code,message:r.message,...typeof r.field=="string"?{field:r.field}:{},...r.received!==void 0?{received:r.received}:{},...typeof r.next=="string"?{next:r.next}:{},manifestStale:P(r),...r.question!==void 0?{question:r.question}:{}}}c(L,"parseHttpError");function V(e){return e===400||e===401||e===403||e===422?h.USAGE:e===404?h.NOT_FOUND:e===409?h.AMBIGUOUS:h.GENERAL}c(V,"deriveExit");function $(e,t,r){return new w("cli_protocol_error",`${E(e)}: ${t}. Expected ${r}.`,h.GENERAL,{received:t,next:`Run \`crtr pkg plugin update ${e.registration.name}\` or inspect the backend response.`})}c($,"protocolError");function E(e){return`HTTP-transport plugin "${e.registration.name}" command \`${e.commandPath.join(" ")}\``}c(E,"label");function B(e){return e===null?"null":Array.isArray(e)?"array":typeof e}c(B,"typeName");export{ne as buildRequestPlan,oe as mapUnary2xx,b as paramKey,L as parseHttpError,N as readPathParam,ie as throwNon2xx};
package/dist/core/io.js CHANGED
@@ -1,7 +1,7 @@
1
- var _=Object.defineProperty;var i=(e,t)=>_(e,"name",{value:t,configurable:!0});import{appendFileSync as b,statSync as w}from"node:fs";import{CrtrError as c}from"./errors.js";import{ExitCode as a}from"../types.js";import{PREVIEW_RESULT_PATH_ENV as h}from"./preview-result-path.js";import{renderError as A}from"./render.js";import{ApiError as E}from"../api/index.js";let p=!1,f;const v=256*1024;function q(e){const t=process.env[h];f=t===void 0||t===""?void 0:{path:e,jsonl:[]}}i(q,"beginPreview");function y(e){const t=process.env[h];if(t===void 0||t==="")return;const s=`${JSON.stringify({path:f?.path??"",...e})}
2
- `;try{if((w(t,{throwIfNoEntry:!1})?.size??0)+Buffer.byteLength(s,"utf8")>v)return;b(t,s,"utf8")}catch{}}i(y,"publishPreview");function B(e){f!==void 0&&(e!=null?y({result:e}):(f.jsonl.length>0||f.error!==void 0)&&y({...f.jsonl.length>0?{jsonl:f.jsonl}:{},...f.error===void 0?{}:{error:f.error}}))}i(B,"publishPreviewResult");function g(e){f?.jsonl.push(e)}i(g,"recordPreviewLine");function G(e){try{const t=JSON.parse(e);t!==null&&typeof t=="object"&&!Array.isArray(t)&&g(t)}catch{}}i(G,"recordPreviewJsonLine");function K(e){f!==void 0&&(f.error=e)}i(K,"recordPreviewError");function F(e){p=e}i(F,"setJsonOutput");function z(){return p}i(z,"isJsonOutput");class m extends c{static{i(this,"InputError")}payload;constructor(t,s=a.USAGE){super(t.error,t.message,s,{...t}),this.name="InputError",this.payload=t}}async function D(){if(process.stdin.isTTY)return"";const e=[];for await(const t of process.stdin)e.push(t);return Buffer.concat(e).toString("utf8")}i(D,"readStdinRaw");async function V(e=200){return process.stdin.isTTY?"":await new Promise(t=>{const s=[];let n=!1;const r=i(()=>{n||(n=!0,clearTimeout(u),process.stdin.removeListener("data",o),process.stdin.removeListener("end",l),process.stdin.removeListener("error",d),process.stdin.pause(),t(Buffer.concat(s).toString("utf8")))},"finish"),o=i(x=>s.push(x),"onData"),l=i(()=>r(),"onEnd"),d=i(()=>r(),"onError"),u=setTimeout(r,e);process.stdin.on("data",o),process.stdin.on("end",l),process.stdin.on("error",d),process.stdin.resume()})}i(V,"peekStdinRaw");function Y(e){process.stdout.write(JSON.stringify(e,null,2)+`
1
+ var b=Object.defineProperty;var i=(e,t)=>b(e,"name",{value:t,configurable:!0});import{appendFileSync as _,statSync as w}from"node:fs";import{CrtrError as c}from"./errors.js";import{ExitCode as a}from"../types.js";import{PREVIEW_RESULT_PATH_ENV as h}from"./preview-result-path.js";import{renderError as A}from"./render.js";import{ApiError as E}from"../api/index.js";let p=!1,f;const T=256*1024;function q(e){const t=process.env[h];f=t===void 0||t===""?void 0:{path:e,jsonl:[]}}i(q,"beginPreview");function y(e){const t=process.env[h];if(t===void 0||t==="")return;const s=`${JSON.stringify({path:f?.path??"",...e})}
2
+ `;try{if((w(t,{throwIfNoEntry:!1})?.size??0)+Buffer.byteLength(s,"utf8")>T)return;_(t,s,"utf8")}catch{}}i(y,"publishPreview");function B(e){f!==void 0&&(e!=null?y({result:e}):(f.jsonl.length>0||f.error!==void 0)&&y({...f.jsonl.length>0?{jsonl:f.jsonl}:{},...f.error===void 0?{}:{error:f.error}}))}i(B,"publishPreviewResult");function g(e){f?.jsonl.push(e)}i(g,"recordPreviewLine");function G(e){try{const t=JSON.parse(e);t!==null&&typeof t=="object"&&!Array.isArray(t)&&g(t)}catch{}}i(G,"recordPreviewJsonLine");function K(e){f!==void 0&&(f.error=e)}i(K,"recordPreviewError");function F(e){p=e}i(F,"setJsonOutput");function z(){return p}i(z,"isJsonOutput");class m extends c{static{i(this,"InputError")}payload;constructor(t,s=a.USAGE){super(t.error,t.message,s,{...t}),this.name="InputError",this.payload=t}}async function D(){if(process.stdin.isTTY)return"";const e=[];for await(const t of process.stdin)e.push(t);return Buffer.concat(e).toString("utf8")}i(D,"readStdinRaw");async function V(e=200){return process.stdin.isTTY?"":await new Promise(t=>{const s=[];let n=!1;const r=i(()=>{n||(n=!0,clearTimeout(u),process.stdin.removeListener("data",o),process.stdin.removeListener("end",l),process.stdin.removeListener("error",d),process.stdin.pause(),t(Buffer.concat(s).toString("utf8")))},"finish"),o=i(x=>s.push(x),"onData"),l=i(()=>r(),"onEnd"),d=i(()=>r(),"onError"),u=setTimeout(r,e);process.stdin.on("data",o),process.stdin.on("end",l),process.stdin.on("error",d),process.stdin.resume()})}i(V,"peekStdinRaw");function Y(e){process.stdout.write(JSON.stringify(e,null,2)+`
3
3
  `)}i(Y,"emit");function H(e){g(e),process.stdout.write(JSON.stringify(e)+`
4
4
  `)}i(H,"emitLine");function M(e){return new Promise(t=>{let s=!1;const n=i(o=>{o.code==="EPIPE"&&r(!1)},"onErr"),r=i(o=>{s||(s=!0,process.stdout.off("error",n),t(o))},"finish");process.stdout.on("error",n);try{process.stdout.write(e,o=>r(o==null))}catch{r(!1)}})}i(M,"writeStdout");function X(e){process.stderr.write(e+`
5
- `)}i(X,"diag");function S(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}i(S,"isRecord");function T(e){if(e instanceof m)return e.payload;const t=e.details!==void 0?e.details:{},s=t.primaryCompleted===!0&&t.result!==null&&typeof t.result=="object"&&!Array.isArray(t.result)?O(t.result):void 0,n=t.next!==void 0?t.next:"Inspect the error and adjust the call. See -h for the schema.",r={error:e.code,message:e.message,received:t.received,field:t.field,...typeof t.http_status=="number"?{http_status:t.http_status}:{},...typeof t.retry_after_s=="number"?{retry_after_s:t.retry_after_s}:{},...S(t.details)?{details:t.details}:{}};return s===void 0?{...r,next:n}:{...r,primaryCompleted:!0,result:s,next:n}}i(T,"payloadOf");function O(e){const t=new WeakSet;try{const s=JSON.stringify(e,(n,r)=>{if(typeof r=="bigint")return{$crtrType:"bigint",value:r.toString()};if(typeof r=="number"&&!Number.isFinite(r))return{$crtrType:"number",value:String(r)};if(typeof r>"u"||typeof r=="function"||typeof r=="symbol")return{$crtrType:typeof r};if(r!==null&&typeof r=="object"){if(t.has(r))return{$crtrType:"circular"};t.add(r)}return r});if(s!==void 0){const n=JSON.parse(s);if(n!==null&&typeof n=="object"&&!Array.isArray(n))return n}}catch{}return{$crtrType:"unavailable",message:"The completed primary result could not be represented as JSON."}}i(O,"jsonSafeResult");const N={400:"invalid_request",404:"not_found",409:"conflict",422:"unprocessable"};function R(e,t,s={}){if(e.code==="daemon_restarting")return new c("daemon_restarting",e.message,a.NETWORK,{next:"crtrd is now on the new generation \u2014 retry the command."});if(e.code==="layout_migration_required")return new c("layout_migration_required",e.message,a.NETWORK,{next:"Run `crtr sys migrate` while the runtime is offline, then restart it."});if(e.code==="daemon_unavailable")return new c("daemon_unavailable",e.message,a.NETWORK,{next:"Start it with `crtr sys daemon start`, then retry."});if(e.code==="northlight_unreachable"){const d=e.details?.next;return new c("northlight_unreachable",e.message,a.NETWORK,{next:typeof d=="string"&&d!==""?d:"Check this computer's internet connection, then retry."})}if(e.code==="model_sign_in_required"){const d=e.details?.url;return new m({error:e.code,message:e.message,next:typeof d=="string"?`Ask the person to sign in at ${d}, then retry.`:"Ask the person to sign in to an AI subscription on their Northlight account, then retry.",...typeof d=="string"?{details:{url:d}}:{}},a.USAGE)}const n=e.details,r=$(e,n,s.providerCall===!0);if(e.status===503||s.providerCall===!0&&e.status===504&&r.code!==void 0){const d=r.code??e.code,u={next:r.next??t??"Retry the command; if it persists, inspect the unavailable service named in the error."};return r.details!==void 0&&(u.details=r.details),r.code!==void 0&&(r.field!==void 0&&(u.field=r.field),r.received!==void 0&&(u.received=r.received),r.retryAfterS!==void 0&&(u.retry_after_s=r.retryAfterS)),new c(d,e.message,a.NETWORK,u)}const o=Array.isArray(n?.violations)?n.violations.map(d=>`${String(d.field)} ${String(d.problem)}${d.received!==void 0?` (received ${JSON.stringify(d.received)})`:""}`):[],l=n&&typeof n.error=="string"&&typeof n.message=="string"&&typeof n.next=="string"?n:{error:r.code??N[e.status]??e.code,...r.field!==void 0?{field:r.field}:{},...r.received!==void 0?{received:r.received}:{},...r.retryAfterS!==void 0?{retry_after_s:r.retryAfterS}:{},...r.details!==void 0?{details:r.details}:{},message:o.length>0?`${e.message}: ${o.join("; ")}`:e.message.trim()!==""?e.message:`request refused (HTTP ${e.status}, ${e.code}) with no message`,next:r.next??t??(r.retryAfterS!==void 0?`Wait ${r.retryAfterS}s, then retry; do not retry sooner.`:e.status>=500?"This is a crtr bug, not a bad call. Retry; if it persists, report it (the daemon log holds the full cause).":e.status===404&&r.code===void 0?"List nodes with `crtr node inspect list`.":"Inspect the error and adjust the call. See -h for the schema.")};return new m(l,j(l.error,e.status))}i(R,"apiErrorToCliError");function $(e,t,s){const n=i(o=>typeof o=="string"&&/^[a-z][a-z0-9_]*$/.test(o),"snake");if(s&&e.origin!==void 0&&e.origin!=="provider"&&n(e.code)){const o={code:e.code};return(e.status===503||e.status===504)&&(o.next=e.retryable===!0?"Retry the command; if it persists, the machine or service named in the error is unavailable.":"Read the error before retrying: the action may already have run."),S(e.details)&&(o.details=e.details),e.param!==void 0&&(o.field=e.param),typeof e.retryAfterS=="number"&&(o.retryAfterS=e.retryAfterS),o}if(e.origin!=="provider"||t===void 0||t===null||typeof t!="object")return{};const r={};return typeof t.status=="number"&&n(t.code)&&(r.code=t.code),typeof t.next=="string"&&t.next.trim()!==""&&(r.next=t.next),typeof t.field=="string"&&t.field!==""?r.field=t.field:e.param!==void 0&&(r.field=e.param),t.received!==void 0&&t.received!==null&&(r.received=t.received),typeof e.retryAfterS=="number"&&(r.retryAfterS=e.retryAfterS),r}i($,"providerSupplied");function j(e,t){return e==="not_found"||t===404?a.NOT_FOUND:e==="ambiguous"?a.AMBIGUOUS:a.USAGE}i(j,"exitForCliCode");function P(e){if(e instanceof E){P(R(e));return}if(e instanceof c){const n=T(e);f!==void 0&&y({error:n});const r=p?JSON.stringify(n,null,2):A(n);process.stdout.write(r+`
5
+ `)}i(X,"diag");function S(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}i(S,"isRecord");function v(e){if(e instanceof m)return e.payload;const t=e.details!==void 0?e.details:{},s=t.primaryCompleted===!0&&t.result!==null&&typeof t.result=="object"&&!Array.isArray(t.result)?O(t.result):void 0,n=t.next!==void 0?t.next:"Inspect the error and adjust the call. See -h for the schema.",r={error:e.code,message:e.message,received:t.received,field:t.field,...typeof t.http_status=="number"?{http_status:t.http_status}:{},...typeof t.retry_after_s=="number"?{retry_after_s:t.retry_after_s}:{},...S(t.details)?{details:t.details}:{}};return s===void 0?{...r,next:n}:{...r,primaryCompleted:!0,result:s,next:n}}i(v,"payloadOf");function O(e){const t=new WeakSet;try{const s=JSON.stringify(e,(n,r)=>{if(typeof r=="bigint")return{$crtrType:"bigint",value:r.toString()};if(typeof r=="number"&&!Number.isFinite(r))return{$crtrType:"number",value:String(r)};if(typeof r>"u"||typeof r=="function"||typeof r=="symbol")return{$crtrType:typeof r};if(r!==null&&typeof r=="object"){if(t.has(r))return{$crtrType:"circular"};t.add(r)}return r});if(s!==void 0){const n=JSON.parse(s);if(n!==null&&typeof n=="object"&&!Array.isArray(n))return n}}catch{}return{$crtrType:"unavailable",message:"The completed primary result could not be represented as JSON."}}i(O,"jsonSafeResult");const N={400:"invalid_request",404:"not_found",409:"conflict",422:"unprocessable"};function R(e,t,s={}){if(e.code==="daemon_restarting")return new c("daemon_restarting",e.message,a.NETWORK,{next:"crtrd is now on the new generation \u2014 retry the command."});if(e.code==="layout_migration_required")return new c("layout_migration_required",e.message,a.NETWORK,{next:"Run `crtr sys migrate` while the runtime is offline, then restart it."});if(e.code==="daemon_unavailable")return new c("daemon_unavailable",e.message,a.NETWORK,{next:"Start it with `crtr sys daemon start`, then retry."});if(e.code==="northlight_unreachable"){const d=e.details?.next;return new c("northlight_unreachable",e.message,a.NETWORK,{next:typeof d=="string"&&d!==""?d:"Check this computer's internet connection, then retry."})}if(e.code==="model_sign_in_required"){const d=e.details?.url;return new m({error:e.code,message:e.message,next:typeof d=="string"?`Ask the person to sign in at ${d}, then retry.`:"Ask the person to sign in to an AI subscription on their Northlight account, then retry.",...typeof d=="string"?{details:{url:d}}:{}},a.USAGE)}const n=e.details,r=$(e,n,s.providerCall===!0);if(e.status===503||s.providerCall===!0&&e.status===504&&r.code!==void 0){const d=r.code??e.code,u={next:r.next??t??"Retry the command; if it persists, inspect the unavailable service named in the error."};return r.details!==void 0&&(u.details=r.details),r.code!==void 0&&(r.field!==void 0&&(u.field=r.field),r.received!==void 0&&(u.received=r.received),r.retryAfterS!==void 0&&(u.retry_after_s=r.retryAfterS)),new c(d,e.message,a.NETWORK,u)}const o=Array.isArray(n?.violations)?n.violations.map(d=>`${String(d.field)} ${String(d.problem)}${d.received!==void 0?` (received ${JSON.stringify(d.received)})`:""}`):[],l=n&&typeof n.error=="string"&&typeof n.message=="string"&&typeof n.next=="string"?n:{error:r.code??N[e.status]??e.code,...r.field!==void 0?{field:r.field}:{},...r.received!==void 0?{received:r.received}:{},...r.retryAfterS!==void 0?{retry_after_s:r.retryAfterS}:{},...r.details!==void 0?{details:r.details}:{},message:o.length>0?`${e.message}: ${o.join("; ")}`:e.message.trim()!==""?e.message:`request refused (HTTP ${e.status}, ${e.code}) with no message`,next:r.next??(n?.outcome==="unknown"?"The change may already be applied: check the current state before repeating it, and do not report it failed.":void 0)??t??(r.retryAfterS!==void 0?`Wait ${r.retryAfterS}s, then retry; do not retry sooner.`:e.status>=500?"This is a crtr bug, not a bad call. Retry; if it persists, report it (the daemon log holds the full cause).":e.status===404&&r.code===void 0?"List nodes with `crtr node inspect list`.":"Inspect the error and adjust the call. See -h for the schema.")};return new m(l,j(l.error,e.status))}i(R,"apiErrorToCliError");function $(e,t,s){const n=i(o=>typeof o=="string"&&/^[a-z][a-z0-9_]*$/.test(o),"snake");if(s&&e.origin!==void 0&&e.origin!=="provider"&&n(e.code)){const o={code:e.code};return(e.status===503||e.status===504)&&(o.next=e.retryable===!0?"Retry the command; if it persists, the machine or service named in the error is unavailable.":"Read the error before retrying: the action may already have run."),S(e.details)&&(o.details=e.details),e.param!==void 0&&(o.field=e.param),typeof e.retryAfterS=="number"&&(o.retryAfterS=e.retryAfterS),o}if(e.origin!=="provider"||t===void 0||t===null||typeof t!="object")return{};const r={};return typeof t.status=="number"&&n(t.code)&&(r.code=t.code),typeof t.next=="string"&&t.next.trim()!==""&&(r.next=t.next),typeof t.field=="string"&&t.field!==""?r.field=t.field:e.param!==void 0&&(r.field=e.param),t.received!==void 0&&t.received!==null&&(r.received=t.received),typeof e.retryAfterS=="number"&&(r.retryAfterS=e.retryAfterS),r}i($,"providerSupplied");function j(e,t){return e==="not_found"||t===404?a.NOT_FOUND:e==="ambiguous"?a.AMBIGUOUS:a.USAGE}i(j,"exitForCliCode");function P(e){if(e instanceof E){P(R(e));return}if(e instanceof c){const n=v(e);f!==void 0&&y({error:n});const r=p?JSON.stringify(n,null,2):A(n);process.stdout.write(r+`
6
6
  `),process.exitCode=e.exitCode;return}const t=e,s=t!=null&&typeof t.message=="string"?t.message:String(e);process.stderr.write(JSON.stringify({error:"internal",message:s,next:"This is a crtr bug, not a bad call. Retry; if it persists, report it."},null,2)+`
7
- `),process.exitCode=a.GENERAL}i(P,"handle");export{m as InputError,v as PREVIEW_RESULT_MAX_BYTES,R as apiErrorToCliError,q as beginPreview,X as diag,Y as emit,H as emitLine,P as handle,z as isJsonOutput,V as peekStdinRaw,B as publishPreviewResult,D as readStdinRaw,K as recordPreviewError,G as recordPreviewJsonLine,g as recordPreviewLine,F as setJsonOutput,M as writeStdout};
7
+ `),process.exitCode=a.GENERAL}i(P,"handle");export{m as InputError,T as PREVIEW_RESULT_MAX_BYTES,R as apiErrorToCliError,q as beginPreview,X as diag,Y as emit,H as emitLine,P as handle,z as isJsonOutput,V as peekStdinRaw,B as publishPreviewResult,D as readStdinRaw,K as recordPreviewError,G as recordPreviewJsonLine,g as recordPreviewLine,F as setJsonOutput,M as writeStdout};
@@ -1 +1 @@
1
- var ue=Object.defineProperty;var m=(e,o)=>ue(e,"name",{value:o,configurable:!0});import{validateDeclaredResult as G}from"../../api/command-manifest/result.js";import{callerAllows as le,requireGroup as pe}from"../../daemon/api/handlers/providers.js";import{callerTerminalGrant as ce}from"../grants/terminal.js";import{findRefusal as fe,payerOf as me,refusalError as ve,refusedMark as ge,writeCharge as he}from"../ledger/index.js";import{listInstalledPlugins as we}from"../resolver.js";import{emitEvent as ye}from"../events/emit.js";import{ProviderError as l,scopeMissing as be}from"./errors.js";import{resolveProviderRef as _e}from"./roots.js";import{providerToolPath as je}from"../plugin-objects-manifest.js";import{ensureProviderBundle as Ae,refreshProviderBundle as Y,resolveProviderBundle as O,unavailableProviderError as ke}from"./bundles.js";import{prepareFileCall as $e,resignForRetry as Z,resolveFileResult as ee}from"./files.js";import{consumeApproval as Pe,requireProviderApproval as Ee}from"./approval.js";import{outboundToken as qe}from"./mint.js";import{discardFile as Ce}from"./token-cache.js";import{registerProviderCall as Re}from"./inflight.js";import{buildRequestPlan as Me}from"../command-plugins/transport/http-plan.js";import{newTraceId as Te}from"../../shared/traceparent.js";import{sendProviderRequest as Ie,ProviderTransportError as Be}from"./request.js";import{acceptProviderReceipt as Se}from"./receipts.js";import{writeProviderAudit as Ne}from"./audit.js";import{selectDevice as Oe,sendDeviceCall as Fe,deviceFailure as De,deviceUnreachable as re,DEFAULT_DEVICE_REQUEST_MS as Ue}from"./device.js";import{isLibsSearch as te,wantsBundling as Le,callLibsSearch as Je,bundleExec as He,mapLibOutcome as xe,reportLibCalls as Ge}from"./device-libs.js";import{ownMachineId as ze}from"../peer/directory.js";import{directoryIssuer as Qe}from"../directory/issuer.js";import{isCloudRole as Ve}from"../canvas/person-state.js";import{formatCrtrCaller as oe}from"../command-plugins/caller-header.js";import{getNode as We}from"../canvas/canvas.js";import{envelopeForProviderCaller as Ke,EnvelopeError as Xe}from"../peer/envelope.js";const Ye="app:terminal";function ie(e){const o=[],n=m((c,r,i)=>{const u=[...r,c.name],a=i||c.tier==="hidden";if(c.kind==="branch"){for(const v of c.children)n(v,u,a);return}const A=je(e.roots.length,u);o.push({tool:A,leaf:c,hidden:a})},"walk");for(const c of e.roots)n(c,[],!1);return o}m(ie,"providerLeaves");function ne(e){if(e.kind!=="branch")return null;const o=[];for(const h of e.children)if(h.kind==="branch"){const b=ne(h);b&&o.push(b)}else if("group"in h&&h.group){const{kind:b,name:p,description:_,whenToUse:w,tier:y,summary:k,params:$,output:t,effects:d,group:j}=h;o.push({kind:b,name:p,description:_,whenToUse:w,...y===void 0?{}:{tier:y},summary:k,params:$,output:t,effects:d,group:j})}if(o.length===0)return null;const{kind:n,name:c,description:r,whenToUse:i,tier:u,summary:a,model:A,rootEntry:v}=e;return{kind:n,name:c,description:r,whenToUse:i,...u===void 0?{}:{tier:u},summary:a,...A===void 0?{}:{model:A},...v===void 0?{}:{rootEntry:v},children:o}}m(ne,"providerHelpBranch");async function Sr(e,o){const n=await O(o),c=ie(n.commands),r=we("user").find(i=>i.name===o)?.manifest.description??o;return{provider:o,status:"available",major:n.major,display_name:r,transport:n.transport.kind,groups:n.provider.groups.filter(i=>le(e,`${o}:${i.group}`)).map(i=>({group:i.group,leaves:c.filter(({leaf:u,hidden:a})=>!a&&u.group===i.group).map(({tool:u,leaf:a})=>({tool:u,description:a.description,summary:a.summary,params:a.params,output:a.output}))})),commands:n.commands.roots.flatMap(i=>{const u=ne(i);return u?[u]:[]})}}m(Sr,"providerTools");async function Ze(e){return await Se(e.headers["crtr-receipt"],e)}m(Ze,"onProviderResponse");async function er(e){if(e.class==="person"){const o=(await ce())?.sub;if(!o)throw new l("grant_revoked","This machine has no active Northlight grant for your terminal. Run `crtr sys join` again from /account/machines.");return{sub:o,grantee:o}}if(!e.sub||!e.grantee)throw new l("grant_revoked","the caller has no active grant");return{sub:e.sub,grantee:e.grantee}}m(er,"identity");function rr(e,o){return[`${e.id}:${o.group}`]}m(rr,"callScope");function tr(e,o){const n=ie(e.commands).find(c=>c.tool===o);if(!n)throw new l("not_found",`tool "${o}" is not in provider "${e.id}"`,{param:"tool"});if(!n.leaf.group)throw new l("not_found",`tool "${o}" has no group`,{param:"tool"});return n.leaf}m(tr,"leafFor");function z(e){if(!e||typeof e!="object"||Array.isArray(e))return{};const o=e.error;return!o||typeof o!="object"||Array.isArray(o)?{}:o}m(z,"errorBody");function or(e){const o=Array.isArray(e)?e[0]:e;if(!o)return;const n=Number(o);if(Number.isFinite(n)&&n>=0)return n;const c=Date.parse(o);return Number.isFinite(c)?Math.max(0,Math.ceil((c-Date.now())/1e3)):void 0}m(or,"retryAfter");function F(e,o,n,c=!1){const r=z(o),i=typeof r.code=="string"?r.code:void 0,u=typeof r.message=="string"?r.message:`provider answered HTTP ${e}`,a=typeof r.field=="string"?r.field:void 0,v={origin:"provider",details:{code:i??null,message:u,...a?{field:a}:{},...typeof r.next=="string"?{next:r.next}:{},...r.received!==void 0?{received:r.received}:{},status:e},...a?{param:a}:{}};return e===429?new l("provider_rate_limited",u,{...v,retry_after_s:or(n["retry-after"])}):e===401||e>=500?new l("provider_unavailable",u,v):e===403&&i==="provider_refused"?new l("provider_refused",u,v):e===403&&i==="approval_required"?new l("provider_error",c?"provider asked for approval again":"provider approval question is invalid",{...v,status:e}):new l("provider_error",u,{...v,status:e})}m(F,"mapProviderResponse");function se(e,o){return JSON.stringify({major:e.major,endpoint:e.transport.kind==="http"?e.transport.endpoint:null,baseUrl:e.commands.baseUrl??null,rest:o.rest,params:o.params,output:o.output})}m(se,"approvalShape");async function ir(e){const o=e.origin!==void 0?oe({node:e.origin.node??void 0,run:e.origin.run??void 0,machine:e.origin.machine}):oe({node:e.node_id??void 0,run:e.run_id??void 0,profile:e.node_id?(await We(e.node_id))?.profile_id??void 0:void 0,machine:Qe()!==null?ze():void 0});return o===""?{}:{"Crtr-Caller":o}}m(ir,"crtrCallerHeader");async function Nr(e,o,n){const c=_e(o.provider);if(c===null)throw new l("not_found",`provider "${o.provider}" is not available`,{param:"provider"});const r={...o,provider:c},i=new AbortController,u=m(()=>i.abort(n.signal.reason),"abort");n.signal.aborted?u():n.signal.addEventListener("abort",u,{once:!0});let a=n.requestId;const A=n.traceId??Te(),v=Re({request_id:a,run_id:e.run_id,node_id:e.node_id,controller:i});let h,b,p,_,w,y,k,$="allowed";try{if(Ve()&&e.class==="person"&&e.resolved!==null&&!e.resolved.some(g=>g.startsWith(`${r.provider}:`)))throw be(`${r.provider}:*`);try{await Ae(r.provider)}catch{throw ke(r.provider)}let t=await O(r.provider,r.version),d=!1,j=!1,P,D,q,Q=!1,V=!1,U,W=0;for(;;){const g=tr(t,r.tool);if(p=`${t.id}:${g.group}`,pe(e,t.id,g.group),t.transport.kind!=="machine"&&r.machine!==void 0)throw new l("invalid_argument",`provider "${t.id}" is not served by a device, so it takes no machine`,{param:"machine"});t.transport.kind==="machine"&&U===void 0&&(U=await Oe(r.machine,void 0,{newest:te(t.major,r.tool)}),W=Date.now()+(t.commands.timeouts?.requestMs??Ue));let L=null;if(r.approval&&!Q){const s=await Pe(e,r,se(t,g));q=s.option,L=s.prepared,k=r.approval,a=s.requestId,Q=!0}const B={params:g.params.filter(s=>"type"in s&&s.type==="file").map(s=>s.name),output:g.output.find(s=>s.type==="file")?.name??null},K=JSON.stringify(B);if(D!==void 0&&D!==K)throw new l("provider_bad_response","the refreshed manifest changed the tool file contract",{origin:"provider",details:{status:409,message:"manifest_stale changed the tool file contract"}});D=K,L&&(P=await Z(e,B,r.arguments,L,{signal:i.signal})),P??=await $e(e,B,r.arguments,{signal:i.signal});const{sub:M,grantee:S}=await er(e);if(t.transport.kind==="machine"){const s=await nr(e,t,r,g,P,{sub:M,requestId:a,deadlineAt:W,signal:i.signal,machine:U});return y=s.responder,h=s.cleanup,{status:200,body:s.result}}const X=t.transport.endpoint;let C;try{C=await qe({audience:X,sub:M,grantee:S,initiating_app:S,scope:rr(t,g)},{signal:i.signal})}catch(s){if(!(s instanceof l)||s.details?.directory_error!=="invalid_target"||j)throw s;j=!0,await Y(t.id,{conditional:!1,...r.version===void 0?{}:{version:r.version}});const E=await O(t.id,r.version);if(E.transport.kind==="machine"||E.transport.endpoint===X)throw s;t=E;continue}_=C.jti;const J=e.class==="person"?Ye:S,T=me({call:"tool",tokenPayer:C.payer,sub:M}),H=await fe({scope:"call",payer:T.payer,funding:T.funding,sub:M,grantee:J,provider:`app:${t.id}`});if(H!==null)throw await he({request:a,kind:"tool",what:`${t.id}:${r.tool}`,usd:0,payer:T.payer,funding:T.funding,sub:M,grantee:J,node:e.node_id,run:e.run_id,provider:`app:${t.id}`,causedBy:n.causedBy??null,refused:ge(H)}),ve(H);const ae={registration:{name:t.id,endpoint:t.transport.endpoint},...t.commands.baseUrl?{baseUrl:t.commands.baseUrl}:{},...t.commands.timeouts?{timeouts:t.commands.timeouts}:{},params:g.params,rest:g.rest,output:g.output,commandPath:[t.id,...r.tool.split(" ")]},de=Me(ae,P.arguments,void 0,{authorization:`Bearer ${C.access_token}`,requestId:a,traceId:A,fileMode:"pass-through",extraHeaders:{...n.causedBy?{"Crtr-Caused-By":n.causedBy}:{},...e.run_id?{"Crtr-Run-Id":e.run_id}:{},...await ir(e),...q?{"Crtr-Approval":q}:{},...P.headers}});b??=Date.now()+(t.commands.timeouts?.requestMs??3e4);let f;try{if(f=await Ie(de,{connectMs:t.commands.timeouts?.connectMs,requestMs:t.commands.timeouts?.requestMs,deadlineAt:b,signal:i.signal}),i.signal.aborted)throw i.signal.reason??new Error("provider call aborted")}catch(s){throw i.signal.aborted?i.signal.reason??s:s instanceof Be?new l("provider_unavailable",s.message,{origin:"provider",details:{status:null,code:s.kind}}):s}if(w??=await Ze({provider:t.id,tool:r.tool,request_id:a,run_id:e.run_id,sub:M,grantee:S,payer:C.payer,ledger_grantee:J,funding:T.funding,node_id:e.node_id,caused_by:n.causedBy??null,jti:C.jti,status:f.status,headers:f.headers}),y=f.headers["crtr-responder"],f.status===401&&Ce(C.key),f.status>=200&&f.status<300){const s=f.body;if(!s||typeof s!="object"||Array.isArray(s))throw new l("provider_bad_response","provider result is not a JSON object",{origin:"provider",details:{status:f.status,message:"provider result is not a JSON object"}});let E;try{E=await ee(e,P,s,{signal:i.signal})}catch(I){throw I instanceof l&&I.code==="provider_error"?new l("provider_bad_response",I.message,{origin:"provider",details:{status:f.status,message:I.message}}):I}h=E.cleanup;const N=G(g.output,E.result);if(N)throw new l("provider_bad_response",`provider result has an invalid output field "${N.field}"`,{origin:"provider",param:N.field,details:{status:f.status,...N}});if(i.signal.aborted)throw i.signal.reason??new Error("provider call aborted");return{status:200,body:E.result}}const R=z(f.body);if(f.status===403&&R.code==="approval_required"&&!q&&!V){V=!0;const s=await Ee(e,r,a,R.question,i.signal,se(t,g),P);if(k=s.questionId,q=s.option,P=await Z(e,B,r.arguments,P,{signal:i.signal}),b=void 0,i.signal.aborted)throw new l("user_denied","the approval wait was canceled");continue}if(f.status===403&&R.code==="approval_required"&&q)throw F(f.status,f.body,f.headers,!0);const x=f.status===410&&R.code==="unsupported_major"&&r.version===void 0;if(f.status!==401&&(R.manifest_stale===!0||x)&&!d){d=!0;const s=t.major;await Y(t.id,{conditional:!1,...r.version===void 0?{}:{version:r.version}}),t=await O(t.id,r.version),ye({level:"info",event:"daemon.providers.call_retried",fields:{provider:t.id,tool:r.tool,reason:x?"unsupported_major":"manifest_stale",major_before:s,major_after:t.major,...x&&typeof R.received=="number"?{received:R.received}:{}}});continue}throw F(f.status,f.body,f.headers,!!q)}}catch(t){throw t instanceof l&&t.question_id&&(k=t.question_id),y===void 0&&t instanceof l&&typeof t.responder=="string"&&(y=t.responder),$=`refused:${t instanceof l?t.code:"server_error"}`,await h?.(),t}finally{try{await Ne({request_id:a,caller:e,provider:r.provider,tool:r.tool,scope_checked:p,outcome:$,jti:_,receipt_id:w,responder:y,question_id:k})}finally{v()}n.signal.removeEventListener("abort",u)}}m(Nr,"callProvider");async function nr(e,o,n,c,r,i){const{machine:u}=i;let a;try{a=await Ke(e,i.sub)}catch(d){throw d instanceof Xe?new l("invalid_request",d.message,{origin:"runtime"}):d}const A={machine:u,envelope:a,signal:i.signal,deadlineAt:i.deadlineAt,mapFailure:F};if(te(o.major,n.tool)){const d=await Je(A,r.arguments,o.major),j=G(c.output,d);if(j)throw new l("provider_bad_response",`the libraries result has an invalid output field "${j.field}"`,{origin:"provider",param:j.field,details:{status:200,...j}});return{result:d,responder:void 0,cleanup:void 0}}let v=r.arguments,h=null,b="";if(Le(o.major,n.tool,r.arguments)){const d=await He(A,r.arguments,o.major);if(i.deadlineAt-Date.now()<=0)throw re(u,"timeout","");d!==null&&(v=d.arguments,h=d.services,b=d.release)}const p=await Fe(u,{tool:n.tool,arguments:v,version:o.major,requestId:i.requestId,runId:e.run_id,deadlineAt:i.deadlineAt,upload:r.upload===null?null:{id:r.upload.upload_id,link:r.upload.upload_link}},a,i.signal);if(i.signal.aborted)throw i.signal.reason??new Error("provider call aborted");if("unreachable"in p)throw re(u,p.unreachable.reason,p.unreachable.message);const _=p.headers["crtr-responder"],w=z(p.body);if(p.status<200||p.status>=300){const d=De(u,p.status,typeof w.code=="string"?w.code:void 0,typeof w.message=="string"?w.message:void 0,p.body),j=d===null&&p.status>=500&&typeof w.code=="string"?new l("provider_error",typeof w.message=="string"?w.message:`the device answered HTTP ${p.status}`,{origin:"runtime",status:p.status,details:{code:w.code,status:p.status}}):null;throw Object.assign(d??j??F(p.status,p.body,p.headers),{responder:_})}const y=p.body&&typeof p.body=="object"&&!Array.isArray(p.body)?p.body.result:void 0;if(!y||typeof y!="object"||Array.isArray(y))throw Object.assign(new l("provider_bad_response","the device result is not a JSON object",{origin:"provider",details:{status:p.status,message:"the device result is not a JSON object"}}),{responder:_});let k=y;if(h!==null){const d=xe(k,h);if(Ge(u,a,b,d.calls),"error"in d)throw Object.assign(d.error,{responder:_});k=d.result}let $;try{$=await ee(e,r,k,{signal:i.signal})}catch(d){throw d instanceof l&&d.code==="provider_error"?Object.assign(new l("provider_bad_response",d.message,{origin:"provider",details:{status:p.status,message:d.message}}),{responder:_}):d}const t=G(c.output,$.result);if(t)throw await $.cleanup?.(),Object.assign(new l("provider_bad_response",`the device result has an invalid output field "${t.field}"`,{origin:"provider",param:t.field,details:{status:p.status,...t}}),{responder:_});return{result:$.result,responder:_,cleanup:$.cleanup}}m(nr,"callDevice");export{Nr as callProvider,ir as crtrCallerHeader,er as identity,F as mapProviderResponse,Ze as onProviderResponse,ie as providerLeaves,Sr as providerTools};
1
+ var ue=Object.defineProperty;var m=(e,t)=>ue(e,"name",{value:t,configurable:!0});import{validateDeclaredResult as G}from"../../api/command-manifest/result.js";import{callerAllows as le,requireGroup as pe}from"../../daemon/api/handlers/providers.js";import{callerTerminalGrant as ce}from"../grants/terminal.js";import{findRefusal as fe,payerOf as me,refusalError as ve,refusedMark as ge,writeCharge as he}from"../ledger/index.js";import{listInstalledPlugins as we}from"../resolver.js";import{emitEvent as ye}from"../events/emit.js";import{ProviderError as p,scopeMissing as be}from"./errors.js";import{resolveProviderRef as _e}from"./roots.js";import{providerToolPath as je}from"../plugin-objects-manifest.js";import{ensureProviderBundle as Ae,refreshProviderBundle as Y,resolveProviderBundle as S,unavailableProviderError as ke}from"./bundles.js";import{prepareFileCall as $e,resignForRetry as Z,resolveFileResult as ee}from"./files.js";import{consumeApproval as Pe,requireProviderApproval as Ee}from"./approval.js";import{outboundToken as qe}from"./mint.js";import{discardFile as Ce}from"./token-cache.js";import{registerProviderCall as Re}from"./inflight.js";import{buildRequestPlan as Me,paramKey as Te}from"../command-plugins/transport/http-plan.js";import{newTraceId as Ie}from"../../shared/traceparent.js";import{sendProviderRequest as Oe,ProviderTransportError as Be}from"./request.js";import{acceptProviderReceipt as Ne}from"./receipts.js";import{writeProviderAudit as Se}from"./audit.js";import{selectDevice as Fe,sendDeviceCall as De,deviceFailure as Ue,deviceUnreachable as re,DEFAULT_DEVICE_REQUEST_MS as Le}from"./device.js";import{isLibsSearch as te,wantsBundling as Je,callLibsSearch as He,bundleExec as xe,mapLibOutcome as Ge,reportLibCalls as ze}from"./device-libs.js";import{ownMachineId as Ke}from"../peer/directory.js";import{directoryIssuer as Qe}from"../directory/issuer.js";import{isCloudRole as Ve}from"../canvas/person-state.js";import{formatCrtrCaller as oe}from"../command-plugins/caller-header.js";import{getNode as We}from"../canvas/canvas.js";import{envelopeForProviderCaller as Xe,EnvelopeError as Ye}from"../peer/envelope.js";const Ze="app:terminal";function ne(e){const t=[],i=m((u,r,n)=>{const l=[...r,u.name],a=n||u.tier==="hidden";if(u.kind==="branch"){for(const v of u.children)i(v,l,a);return}const A=je(e.roots.length,l);t.push({tool:A,leaf:u,hidden:a})},"walk");for(const u of e.roots)i(u,[],!1);return t}m(ne,"providerLeaves");function ie(e){if(e.kind!=="branch")return null;const t=[];for(const h of e.children)if(h.kind==="branch"){const b=ie(h);b&&t.push(b)}else if("group"in h&&h.group){const{kind:b,name:c,description:_,whenToUse:w,tier:y,summary:k,params:$,output:o,effects:d,group:j}=h;t.push({kind:b,name:c,description:_,whenToUse:w,...y===void 0?{}:{tier:y},summary:k,params:$,output:o,effects:d,group:j})}if(t.length===0)return null;const{kind:i,name:u,description:r,whenToUse:n,tier:l,summary:a,model:A,rootEntry:v}=e;return{kind:i,name:u,description:r,whenToUse:n,...l===void 0?{}:{tier:l},summary:a,...A===void 0?{}:{model:A},...v===void 0?{}:{rootEntry:v},children:t}}m(ie,"providerHelpBranch");async function Sr(e,t){const i=await S(t),u=ne(i.commands),r=we("user").find(n=>n.name===t)?.manifest.description??t;return{provider:t,status:"available",major:i.major,display_name:r,transport:i.transport.kind,groups:i.provider.groups.filter(n=>le(e,`${t}:${n.group}`)).map(n=>({group:n.group,leaves:u.filter(({leaf:l,hidden:a})=>!a&&l.group===n.group).map(({tool:l,leaf:a})=>({tool:l,description:a.description,summary:a.summary,params:a.params,output:a.output}))})),commands:i.commands.roots.flatMap(n=>{const l=ie(n);return l?[l]:[]})}}m(Sr,"providerTools");async function er(e){return await Ne(e.headers["crtr-receipt"],e)}m(er,"onProviderResponse");async function rr(e){if(e.class==="person"){const t=(await ce())?.sub;if(!t)throw new p("grant_revoked","This machine has no active Northlight grant for your terminal. Run `crtr sys join` again from /account/machines.");return{sub:t,grantee:t}}if(!e.sub||!e.grantee)throw new p("grant_revoked","the caller has no active grant");return{sub:e.sub,grantee:e.grantee}}m(rr,"identity");function tr(e,t){return[`${e.id}:${t.group}`]}m(tr,"callScope");function or(e,t){const i=ne(e.commands).find(u=>u.tool===t);if(!i)throw new p("not_found",`tool "${t}" is not in provider "${e.id}"`,{param:"tool"});if(!i.leaf.group)throw new p("not_found",`tool "${t}" has no group`,{param:"tool"});return i.leaf}m(or,"leafFor");function z(e){if(!e||typeof e!="object"||Array.isArray(e))return{};const t=e.error;return!t||typeof t!="object"||Array.isArray(t)?{}:t}m(z,"errorBody");function nr(e){const t=Array.isArray(e)?e[0]:e;if(!t)return;const i=Number(t);if(Number.isFinite(i)&&i>=0)return i;const u=Date.parse(t);return Number.isFinite(u)?Math.max(0,Math.ceil((u-Date.now())/1e3)):void 0}m(nr,"retryAfter");function F(e,t,i,u=!1){const r=z(t),n=typeof r.code=="string"?r.code:void 0,l=typeof r.message=="string"?r.message:`provider answered HTTP ${e}`,a=typeof r.field=="string"?r.field:void 0,v={origin:"provider",details:{code:n??null,message:l,...a?{field:a}:{},...typeof r.next=="string"?{next:r.next}:{},...r.received!==void 0?{received:r.received}:{},status:e},...a?{param:a}:{}};return e===429?new p("provider_rate_limited",l,{...v,retry_after_s:nr(i["retry-after"])}):e===401||e>=500?new p("provider_unavailable",l,v):e===403&&n==="provider_refused"?new p("provider_refused",l,v):e===403&&n==="approval_required"?new p("provider_error",u?"provider asked for approval again":"provider approval question is invalid",{...v,status:e}):new p("provider_error",l,{...v,status:e})}m(F,"mapProviderResponse");function se(e,t){return JSON.stringify({major:e.major,endpoint:e.transport.kind==="http"?e.transport.endpoint:null,baseUrl:e.commands.baseUrl??null,rest:t.rest,params:t.params,output:t.output})}m(se,"approvalShape");async function ir(e){const t=e.origin!==void 0?oe({node:e.origin.node??void 0,run:e.origin.run??void 0,machine:e.origin.machine}):oe({node:e.node_id??void 0,run:e.run_id??void 0,profile:e.node_id?(await We(e.node_id))?.profile_id??void 0:void 0,machine:Qe()!==null?Ke():void 0});return t===""?{}:{"Crtr-Caller":t}}m(ir,"crtrCallerHeader");async function Fr(e,t,i){const u=_e(t.provider);if(u===null)throw new p("not_found",`provider "${t.provider}" is not available`,{param:"provider"});const r={...t,provider:u},n=new AbortController,l=m(()=>n.abort(i.signal.reason),"abort");i.signal.aborted?l():i.signal.addEventListener("abort",l,{once:!0});let a=i.requestId;const A=i.traceId??Ie(),v=Re({request_id:a,run_id:e.run_id,node_id:e.node_id,controller:n});let h,b,c,_,w,y,k,$="allowed";try{if(Ve()&&e.class==="person"&&e.resolved!==null&&!e.resolved.some(g=>g.startsWith(`${r.provider}:`)))throw be(`${r.provider}:*`);try{await Ae(r.provider)}catch{throw ke(r.provider)}let o=await S(r.provider,r.version),d=!1,j=!1,P,D,q,K=!1,Q=!1,U,V=0;for(;;){const g=or(o,r.tool);if(c=`${o.id}:${g.group}`,pe(e,o.id,g.group),o.transport.kind!=="machine"&&r.machine!==void 0)throw new p("invalid_argument",`provider "${o.id}" is not served by a device, so it takes no machine`,{param:"machine"});o.transport.kind==="machine"&&U===void 0&&(U=await Fe(r.machine,void 0,{newest:te(o.major,r.tool)}),V=Date.now()+(o.commands.timeouts?.requestMs??Le));let L=null;if(r.approval&&!K){const s=await Pe(e,r,se(o,g));q=s.option,L=s.prepared,k=r.approval,a=s.requestId,K=!0}const O={params:g.params.filter(s=>"type"in s&&s.type==="file").map(s=>s.name),output:g.output.find(s=>s.type==="file")?.name??null},W=JSON.stringify(O);if(D!==void 0&&D!==W)throw new p("provider_bad_response","the refreshed manifest changed the tool file contract",{origin:"provider",details:{status:409,message:"manifest_stale changed the tool file contract"}});D=W,L&&(P=await Z(e,O,r.arguments,L,{signal:n.signal})),P??=await $e(e,O,r.arguments,{signal:n.signal});const{sub:M,grantee:B}=await rr(e);if(o.transport.kind==="machine"){const s=await ar(e,o,r,g,P,{sub:M,requestId:a,deadlineAt:V,signal:n.signal,machine:U});return y=s.responder,h=s.cleanup,{status:200,body:s.result}}const X=o.transport.endpoint;let C;try{C=await qe({audience:X,sub:M,grantee:B,initiating_app:B,scope:tr(o,g)},{signal:n.signal})}catch(s){if(!(s instanceof p)||s.details?.directory_error!=="invalid_target"||j)throw s;j=!0,await Y(o.id,{conditional:!1,...r.version===void 0?{}:{version:r.version}});const E=await S(o.id,r.version);if(E.transport.kind==="machine"||E.transport.endpoint===X)throw s;o=E;continue}_=C.jti;const J=e.class==="person"?Ze:B,T=me({call:"tool",tokenPayer:C.payer,sub:M}),H=await fe({scope:"call",payer:T.payer,funding:T.funding,sub:M,grantee:J,provider:`app:${o.id}`});if(H!==null)throw await he({request:a,kind:"tool",what:`${o.id}:${r.tool}`,usd:0,payer:T.payer,funding:T.funding,sub:M,grantee:J,node:e.node_id,run:e.run_id,provider:`app:${o.id}`,causedBy:i.causedBy??null,refused:ge(H)}),ve(H);const ae={registration:{name:o.id,endpoint:o.transport.endpoint},...o.commands.baseUrl?{baseUrl:o.commands.baseUrl}:{},...o.commands.timeouts?{timeouts:o.commands.timeouts}:{},params:g.params,rest:g.rest,output:g.output,commandPath:[o.id,...r.tool.split(" ")]},de=Me(ae,P.arguments,void 0,{authorization:`Bearer ${C.access_token}`,requestId:a,traceId:A,fileMode:"pass-through",extraHeaders:{...i.causedBy?{"Crtr-Caused-By":i.causedBy}:{},...e.run_id?{"Crtr-Run-Id":e.run_id}:{},...await ir(e),...q?{"Crtr-Approval":q}:{},...P.headers}});b??=Date.now()+(o.commands.timeouts?.requestMs??3e4);let f;try{if(f=await Oe(de,{connectMs:o.commands.timeouts?.connectMs,requestMs:o.commands.timeouts?.requestMs,deadlineAt:b,signal:n.signal}),n.signal.aborted)throw n.signal.reason??new Error("provider call aborted")}catch(s){throw n.signal.aborted?n.signal.reason??s:s instanceof Be?new p("provider_unavailable",s.message,{origin:"provider",details:{status:null,code:s.kind}}):s}if(w??=await er({provider:o.id,tool:r.tool,request_id:a,run_id:e.run_id,sub:M,grantee:B,payer:C.payer,ledger_grantee:J,funding:T.funding,node_id:e.node_id,caused_by:i.causedBy??null,jti:C.jti,status:f.status,headers:f.headers}),y=f.headers["crtr-responder"],f.status===401&&Ce(C.key),f.status>=200&&f.status<300){const s=f.body;if(!s||typeof s!="object"||Array.isArray(s))throw new p("provider_bad_response","provider result is not a JSON object",{origin:"provider",details:{status:f.status,message:"provider result is not a JSON object"}});let E;try{E=await ee(e,P,s,{signal:n.signal})}catch(I){throw I instanceof p&&I.code==="provider_error"?new p("provider_bad_response",I.message,{origin:"provider",details:{status:f.status,message:I.message}}):I}h=E.cleanup;const N=G(g.output,E.result);if(N)throw new p("provider_bad_response",`provider result has an invalid output field "${N.field}"`,{origin:"provider",param:N.field,details:{status:f.status,...N}});if(n.signal.aborted)throw n.signal.reason??new Error("provider call aborted");return{status:200,body:E.result}}const R=z(f.body);if(f.status===403&&R.code==="approval_required"&&!q&&!Q){Q=!0;const s=await Ee(e,r,a,R.question,n.signal,se(o,g),P);if(k=s.questionId,q=s.option,P=await Z(e,O,r.arguments,P,{signal:n.signal}),b=void 0,n.signal.aborted)throw new p("user_denied","the approval wait was canceled");continue}if(f.status===403&&R.code==="approval_required"&&q)throw F(f.status,f.body,f.headers,!0);const x=f.status===410&&R.code==="unsupported_major"&&r.version===void 0;if(f.status!==401&&(R.manifest_stale===!0||x)&&!d){d=!0;const s=o.major;await Y(o.id,{conditional:!1,...r.version===void 0?{}:{version:r.version}}),o=await S(o.id,r.version),ye({level:"info",event:"daemon.providers.call_retried",fields:{provider:o.id,tool:r.tool,reason:x?"unsupported_major":"manifest_stale",major_before:s,major_after:o.major,...x&&typeof R.received=="number"?{received:R.received}:{}}});continue}throw F(f.status,f.body,f.headers,!!q)}}catch(o){throw o instanceof p&&o.question_id&&(k=o.question_id),y===void 0&&o instanceof p&&typeof o.responder=="string"&&(y=o.responder),$=`refused:${o instanceof p?o.code:"server_error"}`,await h?.(),o}finally{try{await Se({request_id:a,caller:e,provider:r.provider,tool:r.tool,scope_checked:c,outcome:$,jti:_,receipt_id:w,responder:y,question_id:k})}finally{v()}i.signal.removeEventListener("abort",l)}}m(Fr,"callProvider");function sr(e,t){const i={...t};for(const{name:u}of e.params){const r=Te(u);r===u||!Object.hasOwn(i,r)||(i[u]=i[r],delete i[r])}return i}m(sr,"declaredNames");async function ar(e,t,i,u,r,n){const{machine:l}=n;let a;try{a=await Xe(e,n.sub)}catch(d){throw d instanceof Ye?new p("invalid_request",d.message,{origin:"runtime"}):d}const A={machine:l,envelope:a,signal:n.signal,deadlineAt:n.deadlineAt,mapFailure:F};if(te(t.major,i.tool)){const d=await He(A,r.arguments,t.major),j=G(u.output,d);if(j)throw new p("provider_bad_response",`the libraries result has an invalid output field "${j.field}"`,{origin:"provider",param:j.field,details:{status:200,...j}});return{result:d,responder:void 0,cleanup:void 0}}let v=r.arguments,h=null,b="";if(Je(t.major,i.tool,r.arguments)){const d=await xe(A,r.arguments,t.major);if(n.deadlineAt-Date.now()<=0)throw re(l,"timeout","");d!==null&&(v=d.arguments,h=d.services,b=d.release)}const c=await De(l,{tool:i.tool,arguments:sr(u,v),version:t.major,requestId:n.requestId,runId:e.run_id,deadlineAt:n.deadlineAt,upload:r.upload===null?null:{id:r.upload.upload_id,link:r.upload.upload_link}},a,n.signal);if(n.signal.aborted)throw n.signal.reason??new Error("provider call aborted");if("unreachable"in c)throw re(l,c.unreachable.reason,c.unreachable.message);const _=c.headers["crtr-responder"],w=z(c.body);if(c.status<200||c.status>=300){const d=Ue(l,c.status,typeof w.code=="string"?w.code:void 0,typeof w.message=="string"?w.message:void 0,c.body),j=d===null&&c.status>=500&&typeof w.code=="string"?new p("provider_error",typeof w.message=="string"?w.message:`the device answered HTTP ${c.status}`,{origin:"runtime",status:c.status,details:{code:w.code,status:c.status}}):null;throw Object.assign(d??j??F(c.status,c.body,c.headers),{responder:_})}const y=c.body&&typeof c.body=="object"&&!Array.isArray(c.body)?c.body.result:void 0;if(!y||typeof y!="object"||Array.isArray(y))throw Object.assign(new p("provider_bad_response","the device result is not a JSON object",{origin:"provider",details:{status:c.status,message:"the device result is not a JSON object"}}),{responder:_});let k=y;if(h!==null){const d=Ge(k,h);if(ze(l,a,b,d.calls),"error"in d)throw Object.assign(d.error,{responder:_});k=d.result}let $;try{$=await ee(e,r,k,{signal:n.signal})}catch(d){throw d instanceof p&&d.code==="provider_error"?Object.assign(new p("provider_bad_response",d.message,{origin:"provider",details:{status:c.status,message:d.message}}),{responder:_}):d}const o=G(u.output,$.result);if(o)throw await $.cleanup?.(),Object.assign(new p("provider_bad_response",`the device result has an invalid output field "${o.field}"`,{origin:"provider",param:o.field,details:{status:c.status,...o}}),{responder:_});return{result:$.result,responder:_,cleanup:$.cleanup}}m(ar,"callDevice");export{Fr as callProvider,ir as crtrCallerHeader,rr as identity,F as mapProviderResponse,er as onProviderResponse,ne as providerLeaves,Sr as providerTools};
@@ -1,5 +1,3 @@
1
1
  import type { MailEntryDTO } from '../../../api/dto/mail.js';
2
- /** A message whose body overflowed the digest carries the full text in its row (`data.body_full`) and names a path as
3
- * its `ref`. The broker writes the text at that path in its own filesystem so the agent reads it as it always has,
4
- * and drops the copy from the entry it renders. */
5
- export declare function materializeSpilledBody(entry: MailEntryDTO): MailEntryDTO;
2
+ /** Materialize overflow text in the broker's writable node folder, not the daemon's runtime records. */
3
+ export declare function materializeSpilledBody(entry: MailEntryDTO, nodeId: string): MailEntryDTO;
@@ -1 +1 @@
1
- var t=Object.defineProperty;var f=(i,r)=>t(i,"name",{value:r,configurable:!0});import{mkdirSync as d,writeFileSync as l}from"node:fs";import{dirname as o}from"node:path";function c(i){const r=i.data?.body_full;if(typeof r!="string"||i.ref===void 0||!i.ref.startsWith("/"))return i;d(o(i.ref),{recursive:!0}),l(i.ref,r,"utf8");const{body_full:a,...e}=i.data;return{...i,data:e}}f(c,"materializeSpilledBody");export{c as materializeSpilledBody};
1
+ var a=Object.defineProperty;var t=(e,i)=>a(e,"name",{value:i,configurable:!0});import{mkdirSync as d,writeFileSync as l}from"node:fs";import{basename as s,dirname as m,join as n}from"node:path";import{nodeAgentDir as u}from"../../canvas/paths.js";function _(e,i){const o=e.data?.body_full;if(typeof o!="string"||e.ref===void 0||!e.ref.startsWith("/"))return e;const r=n(u(i),"messages",s(e.ref));d(m(r),{recursive:!0}),l(r,o,"utf8");const{body_full:c,...f}=e.data;return{...e,ref:r,data:f}}t(_,"materializeSpilledBody");export{_ as materializeSpilledBody};
@@ -1,2 +1,2 @@
1
1
  var J=Object.defineProperty;var l=(r,t)=>J(r,"name",{value:t,configurable:!0});import{envInboxBetweenTurns as $,envNodeId as G,envProfileId as X,envWatcherDebounceMs as j,envWatcherTickMs as z,envWatcherBackstopMs as L}from"../shared/env.js";import{coalesceBrokerInbox as V,entryCards as Q}from"../core/runtime/broker/inbox.js";import{acknowledgeBrokerMail as Y,claimBrokerMail as K,brokerExtensionState as O,recordConversationWriteFault as Z}from"../core/runtime/broker/daemon-ops.js";import{materializeSpilledBody as ee}from"../core/runtime/broker/spilled-body.js";import{brokerSignalClient as P}from"../core/runtime/broker/signal-stream.js";import{wasTurnRefused as te}from"../core/runtime/broker/extension-abort.js";import{isDaemonTransportApiError as A,isTokenRevokedApiError as ie}from"../api/errors.js";import{announceMessageOrigin as ne,messageSignature as C}from"../core/runtime/stamp/channel.js";import{captureGoalIfAbsent as se,generateAndCommitInitialName as re}from"./broker-local.js";import{emitEvent as D}from"../core/events/emit.js";import{errorClassFromError as ae}from"../core/events/errors.js";import{operationIdContext as g}from"../core/events/operation-id.js";import{SITUATIONAL_CONTEXT_CUSTOM_TYPE as x}from"../shared/generated-context.js";import{isProfilePaused as de}from"../core/profiles/manifest.js";import{brokerDisposeAndExit as H,brokerIdleTurnStart as oe,brokerRunTurnBusy as fe,brokerRunSteer as _,HELD_DEFERRED_INBOX_PROMPT_JOIN as le}from"../core/runtime/broker/held-deferred-inbox.js";const E=64,U=16;let v,he=0;class q extends Error{static{l(this,"WatcherFatalError")}constructor(t,e){super(t,{cause:e}),this.name="WatcherFatalError"}}function ue(){return{tickMs:z(),debounceMs:j()}}l(ue,"resolveCadence");function T(){const r=G();return r===void 0||r.trim()===""?void 0:r}l(T,"currentNodeId");function B(){const r=X();return r!==void 0&&r!==""&&de(r)}l(B,"profilePaused");function M(r){try{return ae(r)}catch{return{class:"unknown"}}}l(M,"safeErrorClass");function w(r){try{D(r)}catch{}}l(w,"emitBestEffort");function I(r){try{g.fresh(t=>{w({...r,operation_id:t})})}catch{}}l(I,"emitFreshBestEffort");function S(r,t){try{g.run(r,()=>{w({...t,operation_id:r})})}catch{}}l(S,"emitStoredBestEffort");function ce(r){return r.kind==="human"?{type:"human"}:{type:"runtime",kind:"inbox",entries:r.entries.map(t=>({...t.from===null?{}:{from:t.from},...t.from_name===void 0?{}:{fromName:t.from_name},kind:t.kind,tier:t.tier,...t.ref===void 0?{}:{ref:t.ref}}))}}l(ce,"deliveryOrigin");function k(r,t){if(r.length===0)throw new Error(`cannot create an empty ${t} delivery`);const e=[...new Set(r.map(n=>n.operation_id))].sort(),i=e.length-U;return{channel:t,entryIds:r.map(n=>n.entry_id),throughEntryId:r.at(-1).entry_id,sourceOperationIds:e.slice(0,U),...i>0?{sourceOperationIdsOmitted:i}:{}}}l(k,"deliveryFacts");function b(r){return{channel:r.channel,entry_ids:r.entryIds,through_entry_id:r.throughEntryId,source_operation_ids:r.sourceOperationIds,...r.sourceOperationIdsOmitted===void 0?{}:{source_operation_ids_omitted:r.sourceOperationIdsOmitted}}}l(b,"deliveryFields");function me(r){S(r.operationId,{level:"info",event:"inbox.delivery.completed",outcome:"succeeded",fields:b(r)})}l(me,"emitDeliveryCompleted");function F(r,t,e,i){S(r,{level:"error",event:"inbox.delivery.failed",outcome:"failed",error:i,error_class:M(i),fields:{stage:e,...b(t)}})}l(F,"emitDeliveryFailure");function R(r,t){S(r.operationId,{level:"error",event:"inbox.delivery.failed",outcome:"failed",error_class:{class:"unknown"},fields:{stage:"abandoned",reason:t,...b(r)}})}l(R,"emitDeliveryAbandoned");function pe(r){return typeof r=="string"?r:Array.isArray(r)?r.filter(t=>typeof t=="object"&&t!==null&&typeof t.text=="string").map(t=>t.text).join(`
2
- `):""}l(pe,"messageText");function W(r){return r==="quit"||r==="reload"||r==="new"||r==="resume"||r==="fork"}l(W,"isSessionShutdownReason");function ye(r){switch(r){case"quit":return"shutdown";case"reload":case"new":case"resume":case"fork":return"reload";default:return r}}l(ye,"disposalReasonForShutdown");function ge(r){return typeof r=="string"?r.slice(0,128):r===null?"null":r===void 0?"undefined":typeof r=="number"||typeof r=="boolean"||typeof r=="bigint"?String(r).slice(0,128):typeof r}l(ge,"boundedRuntimeReason");class be{static{l(this,"CanvasInboxWatcher")}pi;cadence;generation;timer;backstop;debounceTimer;signalUnsubscribers=[];rerun=!1;retryNeeded=!1;polledOk=!1;armed=!1;lastCtx;streaming=!1;runNode=$();nodeId;claims=new Map;reportBodies=new Map;tickInFlight;buffer=[];lastArrival=0;pendingHandoffs=[];pendingCommit;promptJoinInFlight=!1;replayUnseenInherited=!1;seeded=!1;disposed=!1;disposalReason;fatalError;fatalEscaped=!1;constructor(t,e,i){this.pi=t,this.cadence=e,this.generation=i}start(){const t=l((e,i)=>{this.canMutate()&&this.captureCtx(e,i)},"capture");this.pi.on("session_start",(e,i)=>{this.canMutate()&&(this.captureCtx(e,i),this.arm())}),this.pi.on("turn_end",t),this.pi.on("agent_start",(e,i)=>{this.canMutate()&&(this.captureCtx(e,i),this.streaming=!0)}),this.pi.on("agent_end",(e,i)=>{this.canMutate()&&(this.captureCtx(e,i),this.streaming=!1)}),this.pi.on("message_end",e=>{if(!this.canMutate())return;const i=e?.message;if(i?.role!=="user"&&i?.role!=="custom"||!this.pendingHandoffs.some(d=>d.awaitingDequeue!==void 0))return;const n=C(pe(i.content)),s=this.pendingHandoffs.find(d=>d.awaitingDequeue===n);s!==void 0&&delete s.awaitingDequeue}),this.pi.on("agent_settled",async(e,i)=>{if(!this.canMutate())return;this.captureCtx(e,i);const n=T();if(n!==void 0)try{this.assertNodeOwnership(n,"settle"),await this.tickInFlight,this.seeded||await this.claimMail(n),this.returnUnconsumedSteers();const s=await this.settle(n,i,!1,!0);s==="refresh_held"&&this.dispose("refresh",!1),this.runNode&&s==="settled"&&this.canMutate()&&this.buffer.length>0&&await this.flushOrdinary(n),this.syncTimers()}catch(s){this.dispose("shutdown",!1,void 0,{error:s,stage:"settle"})}}),this.pi.on("session_shutdown",async e=>{if(!this.canMutate())return;let i;try{i=e?.reason}catch{i=void 0}const n=W(i)?ye(i):"reload";W(i)||I({level:"warn",event:"inbox.lifecycle.unknown_shutdown_reason",outcome:"failed",fields:{reason:ge(i)}});try{await this.disposeAtSettlement(n,this.lastCtx)}catch(s){this.dispose(n,!1,void 0,{error:s,stage:"settle"})}})}arm(){if(this.armed)return;this.armed=!0;const t=P();this.signalUnsubscribers.push(t.subscribe("state",()=>this.syncTimers()),t.subscribe("mail",()=>this.runTick("schedule")),t.subscribe("resync",()=>this.runTick("schedule"))),this.syncTimers(),t.state!=="connected"&&this.runTick("schedule")}async disposeAtSettlement(t,e){const i=T();if(i===void 0){this.dispose(t,!1);return}try{this.assertNodeOwnership(i,"settle"),this.returnUnconsumedSteers();const n=await this.settle(i,e,t!=="refresh");this.dispose(n==="refresh_held"?"refresh":t,!1)}catch(n){this.dispose(t,!1,void 0,{error:n,stage:"settle"})}}dispose(t,e,i,n){if(this.disposed)return;this.disposed=!0,this.disposalReason=t,this.clearTimer();for(const d of this.signalUnsubscribers.splice(0))d();const s=n;{const d=[...new Set([...this.pendingCommit?.handoffs??[],...this.pendingHandoffs.splice(0)])];this.buffer.length=0,this.claims.clear(),this.reportBodies.clear(),this.pendingCommit=void 0,this.promptJoinInFlight=!1,this.replayUnseenInherited=!1,this.nodeId=void 0,this.lastCtx=void 0,this.lastArrival=0,this.streaming=!1,this.seeded=!1,this.ownsCurrentGeneration()&&(v=void 0);for(const a of d)R(a,t)}if(s!==void 0){this.scheduleHandlerFatal(s.error,s.stage);return}}ownsCurrentGeneration(){return v===this&&v.generation===this.generation}canMutate(){return this.ownsCurrentGeneration()&&!this.disposed&&this.fatalError===void 0}captureCtx(t,e){e!==void 0&&(this.lastCtx=e)}clearTimer(){this.timer!==void 0&&clearInterval(this.timer),this.backstop!==void 0&&clearInterval(this.backstop),this.debounceTimer!==void 0&&clearTimeout(this.debounceTimer),this.timer=this.backstop=this.debounceTimer=void 0}syncTimers(){if(!this.armed||!this.canMutate())return;const t=P().state,e=t==="connected",i=t!=="stopped"&&(t!=="connected"||this.buffer.length>0||this.pendingCommit!==void 0||this.retryNeeded);i&&this.timer===void 0?(this.timer=setInterval(()=>this.runTick("schedule"),this.cadence.tickMs),this.timer.unref?.()):!i&&this.timer!==void 0&&(clearInterval(this.timer),this.timer=void 0),e&&this.backstop===void 0?(this.backstop=setInterval(()=>this.runTick("schedule"),L()),this.backstop.unref?.()):!e&&this.backstop!==void 0&&(clearInterval(this.backstop),this.backstop=void 0),this.buffer.length===0&&this.debounceTimer!==void 0&&(clearTimeout(this.debounceTimer),this.debounceTimer=void 0)}armDebounce(){this.debounceTimer!==void 0&&clearTimeout(this.debounceTimer);const t=Math.max(0,this.lastArrival+this.cadence.debounceMs-Date.now());this.debounceTimer=setTimeout(()=>{this.debounceTimer=void 0,this.runTick("schedule")},t),this.debounceTimer.unref?.()}isIdle(){if(this.runNode&&fe())return!1;try{if(typeof this.lastCtx?.isIdle=="function")return this.lastCtx.isIdle()===!0}catch{}return!this.streaming}assertNodeOwnership(t,e){!this.seeded||this.nodeId===void 0||this.nodeId===t||this.raiseReadFatal(e,new Error(`watcher node changed from ${this.nodeId} to ${t}`))}raiseFatal(t,e,i,n){throw this.fatalError===void 0&&(this.fatalError=new q(e,i),this.clearTimer(),I({level:"error",event:t,outcome:"failed",error:i,error_class:M(i),fields:n})),this.fatalError}raiseReadFatal(t,e){return this.raiseFatal("inbox.read.failed",`inbox ${t} state is corrupt`,e,{stage:t})}raiseSituationalFatal(t,e){return this.raiseFatal("inbox.situational_context.missing","situational context marker has no readable sidecar",e,{entry_id:t})}escapeFatal(t,e){if(!this.fatalEscaped){if(this.fatalEscaped=!0,e==="throw")throw t;queueMicrotask(()=>{throw t})}}scheduleHandlerFatal(t,e){let i;if(t instanceof q)i=t;else try{this.raiseReadFatal(e,t)}catch(n){i=n}this.escapeFatal(i,"schedule")}runTick(t="throw"){if(!this.canMutate())return;if(this.tickInFlight!==void 0){this.rerun=!0;return}const e=this.tick().then(()=>{this.retryNeeded=!1,this.polledOk=!0}).catch(i=>{if(this.canMutate()){if(A(i)){this.retryNeeded=!0,I({level:"warn",event:"inbox.read.failed",outcome:"failed",error:i,error_class:M(i),fields:{stage:"poll"}});return}if(this.polledOk&&ie(i)){this.clearTimer(),I({level:"info",event:"inbox.poll.token_revoked",outcome:"succeeded",fields:{stage:"poll"}}),H()?.("token-revoked");return}this.scheduleHandlerFatal(i,"poll")}}).finally(()=>{this.tickInFlight===e&&(this.tickInFlight=void 0),this.syncTimers(),this.rerun&&this.canMutate()&&(this.rerun=!1,this.runTick("schedule"))});this.tickInFlight=e}async claimMail(t){this.assertNodeOwnership(t,"poll");let e;try{e=await K(t,"wake",this.reportBodies)}catch(a){throw A(a)&&(this.replayUnseenInherited=!0),a}if(!this.canMutate()||e.action==="hold")return!1;const i=this.replayUnseenInherited;this.replayUnseenInherited=!1,this.nodeId=t,this.seeded=!0;const n=new Set(e.deliveries.map(a=>a.entry.entry_id)),s=this.buffer.filter(a=>!n.has(a.entry_id));for(const a of s)this.claims.delete(a.entry_id);if(this.buffer.splice(0,this.buffer.length,...this.buffer.filter(a=>n.has(a.entry_id))),s.length>0){const a=globalThis[Symbol.for("@crouton-kit/crtr:watcher-cancel-probe")];typeof a=="function"&&a(s.map(f=>f.entry_id),process.hrtime.bigint())}let d=!1;for(const a of e.deliveries){const f=a.entry.entry_id;this.claims.has(f)||(a.entry=ee(a.entry),this.claims.set(f,a),a.handoff==="inherited"&&!i?g.fresh(o=>{this.pendingHandoffs.push({...k([a.entry],"visible"),operationId:o,settleAtAgentSettled:!0})}):(this.buffer.push(a.entry),this.lastArrival=Date.now(),d=!0))}return d&&this.armDebounce(),this.syncTimers(),!0}async tick(){const t=T();if(t!==void 0){if(this.pendingCommit!==void 0){await this.retryPendingCommit(t)==="refresh_held"&&this.canMutate()&&this.dispose("refresh",!1);return}this.promptJoinInFlight||B()||this.pendingHandoffs.length>=E||await this.claimMail(t)&&this.buffer.length>0&&(!this.runNode||this.isIdle()||this.buffer.some(e=>e.tier==="critical")||this.buffer.some(e=>this.isRunSteer(e))&&_()?.steerable())&&Date.now()-this.lastArrival>=this.cadence.debounceMs&&await this.flushOrdinary(t)}}missingChannelEntries(t){const e=t.filter(s=>this.claims.has(s.entry_id)),i=this.coveredEntryIds("hidden"),n=this.coveredEntryIds("visible");return{hiddenEntries:e.filter(s=>(s.data?.situational===!0||s.data?.situationalOnly===!0)&&!i.has(s.entry_id)),visibleEntries:e.filter(s=>s.data?.situationalOnly!==!0&&!n.has(s.entry_id))}}isRunSteer(t){return this.runNode&&t.kind==="message"&&(t.from??"system")==="human"&&t.data?.steer===!0}returnUnconsumedSteers(){const t=_()?.takeUnconsumed()??[];if(t.length===0)return;const e=new Set(t.flatMap(n=>n.messageIds));this.detachPending(n=>n.settlesThroughBridge===!0&&n.entryIds.every(s=>e.has(s)));const i=[...e].map(n=>this.claims.get(n)?.entry).filter(n=>n!==void 0);this.requeueFromBatch(i,e)}visibleRoute(t){return t.length===0?"none":this.isIdle()?"idle":this.runNode?t.some(e=>e.tier==="critical")?"critical":t.some(e=>this.isRunSteer(e))&&_()?.steerable()?"steer":"none":t.some(e=>e.tier==="critical")?"critical":t.some(e=>e.tier==="urgent"||e.kind==="final")?"steer":"followUp"}buildPlan(t){const{hiddenEntries:e,visibleEntries:i}=this.missingChannelEntries(t),n=new Set(e.map(u=>u.entry_id)),s=new Set(i.map(u=>u.entry_id)),d=t.filter(u=>n.has(u.entry_id)||s.has(u.entry_id)),a=this.isIdle()&&d.length>0&&d.every(u=>u.tier==="deferred"),f=this.visibleRoute(i)==="critical",o=!a&&!f&&e.length>0,m=!a&&!f&&i.length>0;return{hiddenEntries:e,visibleEntries:i,deferredHold:a,sendCount:Number(o)+Number(m)}}ordinaryPlan(){return this.buildPlan(this.buffer)}async contextCards(t,e){const i=[];if(e.some(n=>n.data?.situational===!0)){const n=e.at(-1).entry_id;let s;try{s=(await O(t)).situational_card}catch(d){this.raiseSituationalFatal(n,d)}s===null&&this.raiseSituationalFatal(n,new Error(`missing situational context for entry ${n}`)),i.push(s)}for(const n of e)n.data?.situationalOnly===!0&&i.push(...Q(n));return i}digest(t,e){try{return V(t)}catch(i){this.raiseReadFatal(e,i)}}sendDelivery(t,e,i,n,s){this.pendingHandoffs.length>=E&&this.raiseReadFatal(n,new Error(`pending handoff capacity exceeded before ${t} send`));let d;try{d=k(e,t)}catch(o){this.raiseReadFatal(n,o)}let a;try{g.fresh(o=>{a=o,w({level:"info",event:"inbox.delivery.started",operation_id:o,fields:b(d)}),i()})}catch(o){return a===void 0&&this.raiseReadFatal(n,o),F(a,d,"send",o),"failed"}a===void 0&&this.raiseReadFatal(n,new Error(`${t} delivery returned without an operation id`));const f={operationId:a,...d,...s===void 0?{}:{awaitingDequeue:s}};return this.canMutate()?(this.pendingHandoffs.push(f),"handed-off"):(this.disposed&&this.disposalReason!==void 0&&R(f,this.disposalReason),"inactive")}sendContext(t,e,i,n,s,d){const a=n==="steer"||n==="followUp"?n:this.isIdle()?void 0:"followUp",f=a===void 0||i.length===0?void 0:C(i.at(-1));return this.sendDelivery("hidden",e,()=>{this.runNode&&s&&this.pi.appendEntry("crtr-turn-input",{message_ids:e.map(o=>o.entry_id)}),i.forEach((o,m)=>{const u=s&&m===i.length-1;this.pi.sendMessage({customType:x,content:o,display:!0,details:{nodeId:t}},a!==void 0?{deliverAs:a}:u?{deliverAs:"followUp",triggerTurn:!0}:{})})},d,f)}sendVisible(t,e,i,n,s,d){return this.sendDelivery("visible",t,()=>{if(s!=="idle"&&s!=="steer"&&s!=="followUp")throw new Error(`visible send requested for non-send route ${s}`);for(const a of e)this.pi.sendMessage({customType:x,content:a,display:!0},s==="idle"?{}:{deliverAs:s});if(ne(i,n),s==="idle"){const a=oe();if(a===void 0)throw new Error("broker idle-turn admission is unavailable");a(i,this.runNode?t.map(f=>f.entry_id):[])}else this.pi.sendUserMessage(i,{deliverAs:s})},d,s==="steer"||s==="followUp"?C(i):void 0)}abortCritical(){try{this.lastCtx?.abort?.()}catch{}}requeueFromBatch(t,e){if(e.size===0)return;const i=t.filter(d=>e.has(d.entry_id)),n=new Set(i.map(d=>d.entry_id)),s=this.buffer.filter(d=>!n.has(d.entry_id));this.buffer.splice(0,this.buffer.length,...i,...s)}async executePlan(t,e,i){const n=new Set,s=this.visibleRoute(e.visibleEntries);if(s==="critical"){if(this.abortCritical(),!this.canMutate())return{inactive:!0,requeueEntryIds:n};for(const o of e.visibleEntries)n.add(o.entry_id);for(const o of e.hiddenEntries)n.add(o.entry_id);return{inactive:!1,requeueEntryIds:n}}if(this.runNode&&s==="none")return{inactive:!1,requeueEntryIds:new Set([...e.hiddenEntries,...e.visibleEntries].map(o=>o.entry_id))};if(this.runNode&&s==="steer"){let o=-1;e.visibleEntries.forEach((h,y)=>{this.isRunSteer(h)&&(o=y)});const m=e.visibleEntries.slice(0,o+1);if(e.hiddenEntries.length>0||m.some(h=>h.kind!=="message"||h.tier==="deferred"||(h.from??"system")!=="human"))return{inactive:!1,requeueEntryIds:new Set([...e.hiddenEntries,...e.visibleEntries].map(h=>h.entry_id))};const u=this.digest(m,i),c=u.map(h=>({text:h.text,messageIds:h.entries.map(y=>y.entry_id),cards:h.cards}));if(_()?.accept(c)!=="accepted")return{inactive:!1,requeueEntryIds:new Set([...e.hiddenEntries,...e.visibleEntries].map(h=>h.entry_id))};for(const h of u){const y=k(h.entries,"visible");g.fresh(N=>{w({level:"info",event:"inbox.delivery.started",operation_id:N,fields:b(y)}),this.pendingHandoffs.push({...y,operationId:N,settlesThroughBridge:!0})})}const p=new Set(m.map(h=>h.entry_id));for(const h of e.visibleEntries)p.has(h.entry_id)||n.add(h.entry_id);for(const h of e.hiddenEntries)n.add(h.entry_id);return{inactive:!1,requeueEntryIds:n}}const d=e.visibleEntries.length>0?this.digest(e.visibleEntries,i):[],[a,...f]=d;for(const o of f)for(const m of o.entries)n.add(m.entry_id);if(e.hiddenEntries.length>0){const o=await this.contextCards(t,e.hiddenEntries),m=this.sendContext(t,e.hiddenEntries,o,s,a===void 0,i);if(m==="inactive")return{inactive:!0,requeueEntryIds:n};if(m==="failed")for(const u of e.hiddenEntries)n.add(u.entry_id)}if(!this.canMutate())return{inactive:!0,requeueEntryIds:n};if(a!==void 0){const o=this.sendVisible(a.entries,a.cards,a.text,ce(a),s,i);if(o==="inactive")return{inactive:!0,requeueEntryIds:n};if(o==="failed")for(const m of a.entries)n.add(m.entry_id);else a.kind==="human"&&(await se(t,a.text).catch(()=>{}),re(t,a.text))}return{inactive:!1,requeueEntryIds:n}}async flushOrdinary(t){if(this.buffer.length===0)return"empty";const e=this.ordinaryPlan();if(e.deferredHold)return"held";if(this.pendingHandoffs.length+e.sendCount>E)return"capacity-blocked";const i=[...this.buffer],n=await this.executePlan(t,e,"poll");return n.inactive||(this.buffer.splice(0,i.length),this.requeueFromBatch(i,n.requeueEntryIds)),"attempted"}async prependHeldDeferredInbox(t){if(!this.canMutate()||this.nodeId===void 0||B())return;const e=this.ordinaryPlan();if(!e.deferredHold)return;const i=e.visibleEntries.length===0?[]:this.digest(e.visibleEntries,"poll"),n=+(e.hiddenEntries.length>0)+i.length;if(this.pendingHandoffs.length+n>E)return;const s=[...this.buffer];this.promptJoinInFlight=!0;try{this.runNode&&this.pi.appendEntry("crtr-turn-input",{message_ids:[...e.hiddenEntries,...e.visibleEntries].map(d=>d.entry_id)}),e.hiddenEntries.length>0&&await this.sendPromptJoinDelivery(t,"hidden",e.hiddenEntries,await this.contextCards(this.nodeId,e.hiddenEntries));for(const d of i)await this.sendPromptJoinDelivery(t,"visible",d.entries,[...d.cards,d.text]);if(!this.canMutate())return;this.buffer.splice(0,s.length)}finally{this.promptJoinInFlight=!1}}async sendPromptJoinDelivery(t,e,i,n){let s;try{s=k(i,e)}catch(f){this.raiseReadFatal("poll",f)}let d;try{await g.fresh(async f=>{d=f,w({level:"info",event:"inbox.delivery.started",operation_id:f,fields:b(s)});for(const o of n)await t.sendCustomMessage({customType:x,content:o,display:!0})})}catch(f){throw d===void 0&&this.raiseReadFatal("poll",f),F(d,s,"send",f),f}d===void 0&&this.raiseReadFatal("poll",new Error(`${e} prompt-join delivery returned without an operation id`));const a={operationId:d,...s,settleAtAgentSettled:!0};if(!this.canMutate()){this.disposed&&this.disposalReason!==void 0&&R(a,this.disposalReason);return}this.pendingHandoffs.push(a)}coveredEntryIds(t){const e=new Set;for(const i of this.pendingHandoffs)if(i.channel===t)for(const n of i.entryIds)e.add(n);return e}retryPendingCommit(t){const e=this.pendingCommit;if(e===void 0)return Promise.resolve("settled");if(e.attempt!==void 0)return e.attempt;const i=this.attemptPendingCommit(t,e).finally(()=>{e.attempt===i&&(e.attempt=void 0)});return e.attempt=i,i}async attemptPendingCommit(t,e){let i=!1;try{const s=await Y(t,e.receipts);if(s.action==="hold")return"refresh_held";for(const d of e.receipts){const a=s.results.find(f=>f.delivery_id===d.delivery_id);if(a?.outcome!==d.disposition&&a?.outcome!=="stale")throw new Error("daemon returned no terminal mail settlement outcome")}i=s.results.every(d=>d.outcome==="acknowledged")}catch(s){if(this.pendingCommit===e)for(const d of e.handoffs)F(d.operationId,d,"receipt_commit",s);return String(s?.message).startsWith("conversation_write_failed")&&(D({level:"error",event:"broker.exited",node_id:t,error:s,fields:{fault:"conversation_write_failed"}}),await Z(t,s),H()?.("conversation_write_failed",1)),"held"}if(this.pendingCommit!==e)return"settled";for(const s of e.entryIds)this.claims.delete(s);if(e.receipts.some(s=>s.disposition==="released")){const s=new Set(e.entryIds);this.buffer.splice(0,this.buffer.length,...this.buffer.filter(d=>!s.has(d.entry_id)))}this.pendingCommit=void 0;const n=this.detachPending(s=>s.entryIds.every(d=>!this.claims.has(d)));for(const s of n)i&&me(s);return"settled"}async settle(t,e,i,n=!1){if(i)try{if(e?.hasPendingMessages?.()===!0)return"held"}catch{}if(this.pendingCommit!==void 0)return this.retryPendingCommit(t);const s=te(),d=!s&&this.pendingHandoffs.some(c=>c.awaitingDequeue!==void 0)&&await this.nodeRefreshing(t);if(this.pendingCommit!==void 0)return this.retryPendingCommit(t);const a=new Set(this.buffer.map(c=>c.entry_id)),f=new Set(d?this.pendingHandoffs.filter(c=>c.awaitingDequeue!==void 0).flatMap(c=>[...c.entryIds]):[]),o=this.pendingHandoffs.filter(c=>(n||c.settleAtAgentSettled!==!0)&&c.entryIds.every(p=>!f.has(p))),m=new Set(o.flatMap(c=>[...c.entryIds])),u=[...this.claims.keys()].filter(c=>s||m.has(c)&&!a.has(c));return u.length===0?"settled":(this.pendingCommit={handoffs:o,entryIds:u,receipts:u.map(c=>{const p=this.claims.get(c);return{delivery_id:p.delivery_id,attempts:p.attempts,disposition:s?"released":"acknowledged"}})},this.retryPendingCommit(t))}async nodeRefreshing(t){try{return(await O(t)).node.intent==="refresh"}catch{return!0}}detachPending(t){const e=[];for(let i=this.pendingHandoffs.length-1;i>=0;i-=1){const n=this.pendingHandoffs[i];t(n)&&e.push(...this.pendingHandoffs.splice(i,1))}return e.reverse(),e}}function ve(r,t){v?.dispose("reload",!1);const e=new be(r,t,++he);v=e;const i=l(n=>e.prependHeldDeferredInbox(n),"promptJoin");globalThis[le]=i;try{e.start()}catch(n){throw e.dispose("reload",!1),n}return e}l(ve,"installWatcher");function we(r){const t=ve(r,ue());return()=>t.dispose("shutdown",!1)}l(we,"registerCanvasInboxWatcher");var He=we;export{He as default,we as registerCanvasInboxWatcher};
2
+ `):""}l(pe,"messageText");function W(r){return r==="quit"||r==="reload"||r==="new"||r==="resume"||r==="fork"}l(W,"isSessionShutdownReason");function ye(r){switch(r){case"quit":return"shutdown";case"reload":case"new":case"resume":case"fork":return"reload";default:return r}}l(ye,"disposalReasonForShutdown");function ge(r){return typeof r=="string"?r.slice(0,128):r===null?"null":r===void 0?"undefined":typeof r=="number"||typeof r=="boolean"||typeof r=="bigint"?String(r).slice(0,128):typeof r}l(ge,"boundedRuntimeReason");class be{static{l(this,"CanvasInboxWatcher")}pi;cadence;generation;timer;backstop;debounceTimer;signalUnsubscribers=[];rerun=!1;retryNeeded=!1;polledOk=!1;armed=!1;lastCtx;streaming=!1;runNode=$();nodeId;claims=new Map;reportBodies=new Map;tickInFlight;buffer=[];lastArrival=0;pendingHandoffs=[];pendingCommit;promptJoinInFlight=!1;replayUnseenInherited=!1;seeded=!1;disposed=!1;disposalReason;fatalError;fatalEscaped=!1;constructor(t,e,i){this.pi=t,this.cadence=e,this.generation=i}start(){const t=l((e,i)=>{this.canMutate()&&this.captureCtx(e,i)},"capture");this.pi.on("session_start",(e,i)=>{this.canMutate()&&(this.captureCtx(e,i),this.arm())}),this.pi.on("turn_end",t),this.pi.on("agent_start",(e,i)=>{this.canMutate()&&(this.captureCtx(e,i),this.streaming=!0)}),this.pi.on("agent_end",(e,i)=>{this.canMutate()&&(this.captureCtx(e,i),this.streaming=!1)}),this.pi.on("message_end",e=>{if(!this.canMutate())return;const i=e?.message;if(i?.role!=="user"&&i?.role!=="custom"||!this.pendingHandoffs.some(d=>d.awaitingDequeue!==void 0))return;const n=C(pe(i.content)),s=this.pendingHandoffs.find(d=>d.awaitingDequeue===n);s!==void 0&&delete s.awaitingDequeue}),this.pi.on("agent_settled",async(e,i)=>{if(!this.canMutate())return;this.captureCtx(e,i);const n=T();if(n!==void 0)try{this.assertNodeOwnership(n,"settle"),await this.tickInFlight,this.seeded||await this.claimMail(n),this.returnUnconsumedSteers();const s=await this.settle(n,i,!1,!0);s==="refresh_held"&&this.dispose("refresh",!1),this.runNode&&s==="settled"&&this.canMutate()&&this.buffer.length>0&&await this.flushOrdinary(n),this.syncTimers()}catch(s){this.dispose("shutdown",!1,void 0,{error:s,stage:"settle"})}}),this.pi.on("session_shutdown",async e=>{if(!this.canMutate())return;let i;try{i=e?.reason}catch{i=void 0}const n=W(i)?ye(i):"reload";W(i)||I({level:"warn",event:"inbox.lifecycle.unknown_shutdown_reason",outcome:"failed",fields:{reason:ge(i)}});try{await this.disposeAtSettlement(n,this.lastCtx)}catch(s){this.dispose(n,!1,void 0,{error:s,stage:"settle"})}})}arm(){if(this.armed)return;this.armed=!0;const t=P();this.signalUnsubscribers.push(t.subscribe("state",()=>this.syncTimers()),t.subscribe("mail",()=>this.runTick("schedule")),t.subscribe("resync",()=>this.runTick("schedule"))),this.syncTimers(),t.state!=="connected"&&this.runTick("schedule")}async disposeAtSettlement(t,e){const i=T();if(i===void 0){this.dispose(t,!1);return}try{this.assertNodeOwnership(i,"settle"),this.returnUnconsumedSteers();const n=await this.settle(i,e,t!=="refresh");this.dispose(n==="refresh_held"?"refresh":t,!1)}catch(n){this.dispose(t,!1,void 0,{error:n,stage:"settle"})}}dispose(t,e,i,n){if(this.disposed)return;this.disposed=!0,this.disposalReason=t,this.clearTimer();for(const d of this.signalUnsubscribers.splice(0))d();const s=n;{const d=[...new Set([...this.pendingCommit?.handoffs??[],...this.pendingHandoffs.splice(0)])];this.buffer.length=0,this.claims.clear(),this.reportBodies.clear(),this.pendingCommit=void 0,this.promptJoinInFlight=!1,this.replayUnseenInherited=!1,this.nodeId=void 0,this.lastCtx=void 0,this.lastArrival=0,this.streaming=!1,this.seeded=!1,this.ownsCurrentGeneration()&&(v=void 0);for(const a of d)R(a,t)}if(s!==void 0){this.scheduleHandlerFatal(s.error,s.stage);return}}ownsCurrentGeneration(){return v===this&&v.generation===this.generation}canMutate(){return this.ownsCurrentGeneration()&&!this.disposed&&this.fatalError===void 0}captureCtx(t,e){e!==void 0&&(this.lastCtx=e)}clearTimer(){this.timer!==void 0&&clearInterval(this.timer),this.backstop!==void 0&&clearInterval(this.backstop),this.debounceTimer!==void 0&&clearTimeout(this.debounceTimer),this.timer=this.backstop=this.debounceTimer=void 0}syncTimers(){if(!this.armed||!this.canMutate())return;const t=P().state,e=t==="connected",i=t!=="stopped"&&(t!=="connected"||this.buffer.length>0||this.pendingCommit!==void 0||this.retryNeeded);i&&this.timer===void 0?(this.timer=setInterval(()=>this.runTick("schedule"),this.cadence.tickMs),this.timer.unref?.()):!i&&this.timer!==void 0&&(clearInterval(this.timer),this.timer=void 0),e&&this.backstop===void 0?(this.backstop=setInterval(()=>this.runTick("schedule"),L()),this.backstop.unref?.()):!e&&this.backstop!==void 0&&(clearInterval(this.backstop),this.backstop=void 0),this.buffer.length===0&&this.debounceTimer!==void 0&&(clearTimeout(this.debounceTimer),this.debounceTimer=void 0)}armDebounce(){this.debounceTimer!==void 0&&clearTimeout(this.debounceTimer);const t=Math.max(0,this.lastArrival+this.cadence.debounceMs-Date.now());this.debounceTimer=setTimeout(()=>{this.debounceTimer=void 0,this.runTick("schedule")},t),this.debounceTimer.unref?.()}isIdle(){if(this.runNode&&fe())return!1;try{if(typeof this.lastCtx?.isIdle=="function")return this.lastCtx.isIdle()===!0}catch{}return!this.streaming}assertNodeOwnership(t,e){!this.seeded||this.nodeId===void 0||this.nodeId===t||this.raiseReadFatal(e,new Error(`watcher node changed from ${this.nodeId} to ${t}`))}raiseFatal(t,e,i,n){throw this.fatalError===void 0&&(this.fatalError=new q(e,i),this.clearTimer(),I({level:"error",event:t,outcome:"failed",error:i,error_class:M(i),fields:n})),this.fatalError}raiseReadFatal(t,e){return this.raiseFatal("inbox.read.failed",`inbox ${t} state is corrupt`,e,{stage:t})}raiseSituationalFatal(t,e){return this.raiseFatal("inbox.situational_context.missing","situational context marker has no readable sidecar",e,{entry_id:t})}escapeFatal(t,e){if(!this.fatalEscaped){if(this.fatalEscaped=!0,e==="throw")throw t;queueMicrotask(()=>{throw t})}}scheduleHandlerFatal(t,e){let i;if(t instanceof q)i=t;else try{this.raiseReadFatal(e,t)}catch(n){i=n}this.escapeFatal(i,"schedule")}runTick(t="throw"){if(!this.canMutate())return;if(this.tickInFlight!==void 0){this.rerun=!0;return}const e=this.tick().then(()=>{this.retryNeeded=!1,this.polledOk=!0}).catch(i=>{if(this.canMutate()){if(A(i)){this.retryNeeded=!0,I({level:"warn",event:"inbox.read.failed",outcome:"failed",error:i,error_class:M(i),fields:{stage:"poll"}});return}if(this.polledOk&&ie(i)){this.clearTimer(),I({level:"info",event:"inbox.poll.token_revoked",outcome:"succeeded",fields:{stage:"poll"}}),H()?.("token-revoked");return}this.scheduleHandlerFatal(i,"poll")}}).finally(()=>{this.tickInFlight===e&&(this.tickInFlight=void 0),this.syncTimers(),this.rerun&&this.canMutate()&&(this.rerun=!1,this.runTick("schedule"))});this.tickInFlight=e}async claimMail(t){this.assertNodeOwnership(t,"poll");let e;try{e=await K(t,"wake",this.reportBodies)}catch(a){throw A(a)&&(this.replayUnseenInherited=!0),a}if(!this.canMutate()||e.action==="hold")return!1;const i=this.replayUnseenInherited;this.replayUnseenInherited=!1,this.nodeId=t,this.seeded=!0;const n=new Set(e.deliveries.map(a=>a.entry.entry_id)),s=this.buffer.filter(a=>!n.has(a.entry_id));for(const a of s)this.claims.delete(a.entry_id);if(this.buffer.splice(0,this.buffer.length,...this.buffer.filter(a=>n.has(a.entry_id))),s.length>0){const a=globalThis[Symbol.for("@crouton-kit/crtr:watcher-cancel-probe")];typeof a=="function"&&a(s.map(f=>f.entry_id),process.hrtime.bigint())}let d=!1;for(const a of e.deliveries){const f=a.entry.entry_id;this.claims.has(f)||(a.entry=ee(a.entry,t),this.claims.set(f,a),a.handoff==="inherited"&&!i?g.fresh(o=>{this.pendingHandoffs.push({...k([a.entry],"visible"),operationId:o,settleAtAgentSettled:!0})}):(this.buffer.push(a.entry),this.lastArrival=Date.now(),d=!0))}return d&&this.armDebounce(),this.syncTimers(),!0}async tick(){const t=T();if(t!==void 0){if(this.pendingCommit!==void 0){await this.retryPendingCommit(t)==="refresh_held"&&this.canMutate()&&this.dispose("refresh",!1);return}this.promptJoinInFlight||B()||this.pendingHandoffs.length>=E||await this.claimMail(t)&&this.buffer.length>0&&(!this.runNode||this.isIdle()||this.buffer.some(e=>e.tier==="critical")||this.buffer.some(e=>this.isRunSteer(e))&&_()?.steerable())&&Date.now()-this.lastArrival>=this.cadence.debounceMs&&await this.flushOrdinary(t)}}missingChannelEntries(t){const e=t.filter(s=>this.claims.has(s.entry_id)),i=this.coveredEntryIds("hidden"),n=this.coveredEntryIds("visible");return{hiddenEntries:e.filter(s=>(s.data?.situational===!0||s.data?.situationalOnly===!0)&&!i.has(s.entry_id)),visibleEntries:e.filter(s=>s.data?.situationalOnly!==!0&&!n.has(s.entry_id))}}isRunSteer(t){return this.runNode&&t.kind==="message"&&(t.from??"system")==="human"&&t.data?.steer===!0}returnUnconsumedSteers(){const t=_()?.takeUnconsumed()??[];if(t.length===0)return;const e=new Set(t.flatMap(n=>n.messageIds));this.detachPending(n=>n.settlesThroughBridge===!0&&n.entryIds.every(s=>e.has(s)));const i=[...e].map(n=>this.claims.get(n)?.entry).filter(n=>n!==void 0);this.requeueFromBatch(i,e)}visibleRoute(t){return t.length===0?"none":this.isIdle()?"idle":this.runNode?t.some(e=>e.tier==="critical")?"critical":t.some(e=>this.isRunSteer(e))&&_()?.steerable()?"steer":"none":t.some(e=>e.tier==="critical")?"critical":t.some(e=>e.tier==="urgent"||e.kind==="final")?"steer":"followUp"}buildPlan(t){const{hiddenEntries:e,visibleEntries:i}=this.missingChannelEntries(t),n=new Set(e.map(u=>u.entry_id)),s=new Set(i.map(u=>u.entry_id)),d=t.filter(u=>n.has(u.entry_id)||s.has(u.entry_id)),a=this.isIdle()&&d.length>0&&d.every(u=>u.tier==="deferred"),f=this.visibleRoute(i)==="critical",o=!a&&!f&&e.length>0,m=!a&&!f&&i.length>0;return{hiddenEntries:e,visibleEntries:i,deferredHold:a,sendCount:Number(o)+Number(m)}}ordinaryPlan(){return this.buildPlan(this.buffer)}async contextCards(t,e){const i=[];if(e.some(n=>n.data?.situational===!0)){const n=e.at(-1).entry_id;let s;try{s=(await O(t)).situational_card}catch(d){this.raiseSituationalFatal(n,d)}s===null&&this.raiseSituationalFatal(n,new Error(`missing situational context for entry ${n}`)),i.push(s)}for(const n of e)n.data?.situationalOnly===!0&&i.push(...Q(n));return i}digest(t,e){try{return V(t)}catch(i){this.raiseReadFatal(e,i)}}sendDelivery(t,e,i,n,s){this.pendingHandoffs.length>=E&&this.raiseReadFatal(n,new Error(`pending handoff capacity exceeded before ${t} send`));let d;try{d=k(e,t)}catch(o){this.raiseReadFatal(n,o)}let a;try{g.fresh(o=>{a=o,w({level:"info",event:"inbox.delivery.started",operation_id:o,fields:b(d)}),i()})}catch(o){return a===void 0&&this.raiseReadFatal(n,o),F(a,d,"send",o),"failed"}a===void 0&&this.raiseReadFatal(n,new Error(`${t} delivery returned without an operation id`));const f={operationId:a,...d,...s===void 0?{}:{awaitingDequeue:s}};return this.canMutate()?(this.pendingHandoffs.push(f),"handed-off"):(this.disposed&&this.disposalReason!==void 0&&R(f,this.disposalReason),"inactive")}sendContext(t,e,i,n,s,d){const a=n==="steer"||n==="followUp"?n:this.isIdle()?void 0:"followUp",f=a===void 0||i.length===0?void 0:C(i.at(-1));return this.sendDelivery("hidden",e,()=>{this.runNode&&s&&this.pi.appendEntry("crtr-turn-input",{message_ids:e.map(o=>o.entry_id)}),i.forEach((o,m)=>{const u=s&&m===i.length-1;this.pi.sendMessage({customType:x,content:o,display:!0,details:{nodeId:t}},a!==void 0?{deliverAs:a}:u?{deliverAs:"followUp",triggerTurn:!0}:{})})},d,f)}sendVisible(t,e,i,n,s,d){return this.sendDelivery("visible",t,()=>{if(s!=="idle"&&s!=="steer"&&s!=="followUp")throw new Error(`visible send requested for non-send route ${s}`);for(const a of e)this.pi.sendMessage({customType:x,content:a,display:!0},s==="idle"?{}:{deliverAs:s});if(ne(i,n),s==="idle"){const a=oe();if(a===void 0)throw new Error("broker idle-turn admission is unavailable");a(i,this.runNode?t.map(f=>f.entry_id):[])}else this.pi.sendUserMessage(i,{deliverAs:s})},d,s==="steer"||s==="followUp"?C(i):void 0)}abortCritical(){try{this.lastCtx?.abort?.()}catch{}}requeueFromBatch(t,e){if(e.size===0)return;const i=t.filter(d=>e.has(d.entry_id)),n=new Set(i.map(d=>d.entry_id)),s=this.buffer.filter(d=>!n.has(d.entry_id));this.buffer.splice(0,this.buffer.length,...i,...s)}async executePlan(t,e,i){const n=new Set,s=this.visibleRoute(e.visibleEntries);if(s==="critical"){if(this.abortCritical(),!this.canMutate())return{inactive:!0,requeueEntryIds:n};for(const o of e.visibleEntries)n.add(o.entry_id);for(const o of e.hiddenEntries)n.add(o.entry_id);return{inactive:!1,requeueEntryIds:n}}if(this.runNode&&s==="none")return{inactive:!1,requeueEntryIds:new Set([...e.hiddenEntries,...e.visibleEntries].map(o=>o.entry_id))};if(this.runNode&&s==="steer"){let o=-1;e.visibleEntries.forEach((h,y)=>{this.isRunSteer(h)&&(o=y)});const m=e.visibleEntries.slice(0,o+1);if(e.hiddenEntries.length>0||m.some(h=>h.kind!=="message"||h.tier==="deferred"||(h.from??"system")!=="human"))return{inactive:!1,requeueEntryIds:new Set([...e.hiddenEntries,...e.visibleEntries].map(h=>h.entry_id))};const u=this.digest(m,i),c=u.map(h=>({text:h.text,messageIds:h.entries.map(y=>y.entry_id),cards:h.cards}));if(_()?.accept(c)!=="accepted")return{inactive:!1,requeueEntryIds:new Set([...e.hiddenEntries,...e.visibleEntries].map(h=>h.entry_id))};for(const h of u){const y=k(h.entries,"visible");g.fresh(N=>{w({level:"info",event:"inbox.delivery.started",operation_id:N,fields:b(y)}),this.pendingHandoffs.push({...y,operationId:N,settlesThroughBridge:!0})})}const p=new Set(m.map(h=>h.entry_id));for(const h of e.visibleEntries)p.has(h.entry_id)||n.add(h.entry_id);for(const h of e.hiddenEntries)n.add(h.entry_id);return{inactive:!1,requeueEntryIds:n}}const d=e.visibleEntries.length>0?this.digest(e.visibleEntries,i):[],[a,...f]=d;for(const o of f)for(const m of o.entries)n.add(m.entry_id);if(e.hiddenEntries.length>0){const o=await this.contextCards(t,e.hiddenEntries),m=this.sendContext(t,e.hiddenEntries,o,s,a===void 0,i);if(m==="inactive")return{inactive:!0,requeueEntryIds:n};if(m==="failed")for(const u of e.hiddenEntries)n.add(u.entry_id)}if(!this.canMutate())return{inactive:!0,requeueEntryIds:n};if(a!==void 0){const o=this.sendVisible(a.entries,a.cards,a.text,ce(a),s,i);if(o==="inactive")return{inactive:!0,requeueEntryIds:n};if(o==="failed")for(const m of a.entries)n.add(m.entry_id);else a.kind==="human"&&(await se(t,a.text).catch(()=>{}),re(t,a.text))}return{inactive:!1,requeueEntryIds:n}}async flushOrdinary(t){if(this.buffer.length===0)return"empty";const e=this.ordinaryPlan();if(e.deferredHold)return"held";if(this.pendingHandoffs.length+e.sendCount>E)return"capacity-blocked";const i=[...this.buffer],n=await this.executePlan(t,e,"poll");return n.inactive||(this.buffer.splice(0,i.length),this.requeueFromBatch(i,n.requeueEntryIds)),"attempted"}async prependHeldDeferredInbox(t){if(!this.canMutate()||this.nodeId===void 0||B())return;const e=this.ordinaryPlan();if(!e.deferredHold)return;const i=e.visibleEntries.length===0?[]:this.digest(e.visibleEntries,"poll"),n=+(e.hiddenEntries.length>0)+i.length;if(this.pendingHandoffs.length+n>E)return;const s=[...this.buffer];this.promptJoinInFlight=!0;try{this.runNode&&this.pi.appendEntry("crtr-turn-input",{message_ids:[...e.hiddenEntries,...e.visibleEntries].map(d=>d.entry_id)}),e.hiddenEntries.length>0&&await this.sendPromptJoinDelivery(t,"hidden",e.hiddenEntries,await this.contextCards(this.nodeId,e.hiddenEntries));for(const d of i)await this.sendPromptJoinDelivery(t,"visible",d.entries,[...d.cards,d.text]);if(!this.canMutate())return;this.buffer.splice(0,s.length)}finally{this.promptJoinInFlight=!1}}async sendPromptJoinDelivery(t,e,i,n){let s;try{s=k(i,e)}catch(f){this.raiseReadFatal("poll",f)}let d;try{await g.fresh(async f=>{d=f,w({level:"info",event:"inbox.delivery.started",operation_id:f,fields:b(s)});for(const o of n)await t.sendCustomMessage({customType:x,content:o,display:!0})})}catch(f){throw d===void 0&&this.raiseReadFatal("poll",f),F(d,s,"send",f),f}d===void 0&&this.raiseReadFatal("poll",new Error(`${e} prompt-join delivery returned without an operation id`));const a={operationId:d,...s,settleAtAgentSettled:!0};if(!this.canMutate()){this.disposed&&this.disposalReason!==void 0&&R(a,this.disposalReason);return}this.pendingHandoffs.push(a)}coveredEntryIds(t){const e=new Set;for(const i of this.pendingHandoffs)if(i.channel===t)for(const n of i.entryIds)e.add(n);return e}retryPendingCommit(t){const e=this.pendingCommit;if(e===void 0)return Promise.resolve("settled");if(e.attempt!==void 0)return e.attempt;const i=this.attemptPendingCommit(t,e).finally(()=>{e.attempt===i&&(e.attempt=void 0)});return e.attempt=i,i}async attemptPendingCommit(t,e){let i=!1;try{const s=await Y(t,e.receipts);if(s.action==="hold")return"refresh_held";for(const d of e.receipts){const a=s.results.find(f=>f.delivery_id===d.delivery_id);if(a?.outcome!==d.disposition&&a?.outcome!=="stale")throw new Error("daemon returned no terminal mail settlement outcome")}i=s.results.every(d=>d.outcome==="acknowledged")}catch(s){if(this.pendingCommit===e)for(const d of e.handoffs)F(d.operationId,d,"receipt_commit",s);return String(s?.message).startsWith("conversation_write_failed")&&(D({level:"error",event:"broker.exited",node_id:t,error:s,fields:{fault:"conversation_write_failed"}}),await Z(t,s),H()?.("conversation_write_failed",1)),"held"}if(this.pendingCommit!==e)return"settled";for(const s of e.entryIds)this.claims.delete(s);if(e.receipts.some(s=>s.disposition==="released")){const s=new Set(e.entryIds);this.buffer.splice(0,this.buffer.length,...this.buffer.filter(d=>!s.has(d.entry_id)))}this.pendingCommit=void 0;const n=this.detachPending(s=>s.entryIds.every(d=>!this.claims.has(d)));for(const s of n)i&&me(s);return"settled"}async settle(t,e,i,n=!1){if(i)try{if(e?.hasPendingMessages?.()===!0)return"held"}catch{}if(this.pendingCommit!==void 0)return this.retryPendingCommit(t);const s=te(),d=!s&&this.pendingHandoffs.some(c=>c.awaitingDequeue!==void 0)&&await this.nodeRefreshing(t);if(this.pendingCommit!==void 0)return this.retryPendingCommit(t);const a=new Set(this.buffer.map(c=>c.entry_id)),f=new Set(d?this.pendingHandoffs.filter(c=>c.awaitingDequeue!==void 0).flatMap(c=>[...c.entryIds]):[]),o=this.pendingHandoffs.filter(c=>(n||c.settleAtAgentSettled!==!0)&&c.entryIds.every(p=>!f.has(p))),m=new Set(o.flatMap(c=>[...c.entryIds])),u=[...this.claims.keys()].filter(c=>s||m.has(c)&&!a.has(c));return u.length===0?"settled":(this.pendingCommit={handoffs:o,entryIds:u,receipts:u.map(c=>{const p=this.claims.get(c);return{delivery_id:p.delivery_id,attempts:p.attempts,disposition:s?"released":"acknowledged"}})},this.retryPendingCommit(t))}async nodeRefreshing(t){try{return(await O(t)).node.intent==="refresh"}catch{return!0}}detachPending(t){const e=[];for(let i=this.pendingHandoffs.length-1;i>=0;i-=1){const n=this.pendingHandoffs[i];t(n)&&e.push(...this.pendingHandoffs.splice(i,1))}return e.reverse(),e}}function ve(r,t){v?.dispose("reload",!1);const e=new be(r,t,++he);v=e;const i=l(n=>e.prependHeldDeferredInbox(n),"promptJoin");globalThis[le]=i;try{e.start()}catch(n){throw e.dispose("reload",!1),n}return e}l(ve,"installWatcher");function we(r){const t=ve(r,ue());return()=>t.dispose("shutdown",!1)}l(we,"registerCanvasInboxWatcher");var He=we;export{He as default,we as registerCanvasInboxWatcher};
package/docs/ci-runner.md CHANGED
@@ -83,7 +83,7 @@ Installing and upgrading: get a registration token (`gh api -X POST repos/Northl
83
83
 
84
84
  ## No double run on `main`
85
85
 
86
- `publish.yml` starts with a `gate` job. It reads the pushed commit's **git tree** and looks for a workflow artifact named `tested-tree-<tree>`. `test.yml`'s final `tested` job creates that artifact only after `checks` and every `lane` shard pass, on every pull request run and on every run of Publish's own `tests` job.
86
+ `publish.yml` starts with a `gate` job. It reads the pushed commit's **git tree** and looks for a workflow artifact named `tested-tree-<tree>`. `test.yml`'s final `tested` job creates that artifact only in mode `full`, after `checks` and every `linux` shard pass and every `macos` job passed (or was skipped because this is a pull request, where macOS never runs), on every such pull request run and on every run of Publish's own `tests` job. A tree released from a pull request's record therefore never ran its `laptopOnly` tests on macOS.
87
87
 
88
88
  - Rebase-merging a PR whose tested merge ref has the same tree as the resulting `main` commit → artifact found → `tests` is skipped and `publish` proceeds.
89
89
  - A direct push to `main`, or a merge after `main` moved (a different tree from the one the PR run tested) → no artifact → the full suite runs exactly as before. A release commit (`chore: release …`, pushed by Publish itself) changes the tree, so a PR not updated since before the latest release runs the suite once on merge; update the branch to avoid it.
@@ -107,16 +107,16 @@ The hourly `17 * * * *` schedule and the `promote`, `api_ref`, `env_docker_ref`
107
107
 
108
108
  | Event | ubuntu `checks` + `select` | ubuntu `linux` (container) | `macos` (laptop-only tests) |
109
109
  | --- | --- | --- | --- |
110
- | pull request push | yes | the selected files (narrowed by Preflight's pick when there is one), sharded to ~4 min; none for a docs-only change | the selected files that carry `laptopOnly` tags, if any |
111
- | pull request with the `full-ci` label, or a change whose path forces it | yes | all of it | all of it |
110
+ | pull request push | yes | the selected files (narrowed by Preflight's pick when there is one), sharded to ~4 min; none for a docs-only change | never (macOS does not run on a pull request) |
111
+ | pull request with the `full-ci` label, or a change whose path forces it | yes | all of it | never (macOS does not run on a pull request) |
112
112
  | merge queue run (`merge_group`; inert until a queue ruleset exists) | yes | all of it | all of it |
113
113
  | `workflow_dispatch` (`gh workflow run test.yml --ref <branch>`) | yes | all of it | all of it |
114
114
  | push to `main` (Publish's `tests` job) | yes | all of it, unless `gate` found `tested-tree-<tree>` | same |
115
115
 
116
116
  - Selected tests run on every push with no label. Add `full-ci` to force the whole suite (`gh pr edit <n> --add-label full-ci`). Labels other than `full-ci` start nothing and cancel nothing.
117
- - On a pull request each matrix (`linux`, `macos`) is `fail-fast`: the first failing job cancels that matrix's other jobs, the matrix result is `failure`, and `full suite` still runs and is red. On main, merge queue and dispatch runs every job finishes. A Linux failure does not cancel the macOS matrix.
117
+ - On a pull request each matrix (`linux`; `macos` never runs there) is `fail-fast`: the first failing job cancels that matrix's other jobs, the matrix result is `failure`, and `full suite` still runs and is red. On main, merge queue and dispatch runs every job finishes. A Linux failure does not cancel the macOS matrix.
118
118
  - `record tested tree` runs only in mode `full`, so a partial run never lets Publish skip the suite.
119
- - The `full suite` job is the single result to require. It fails if `checks` or `select` did not succeed or any job failed or was cancelled; in mode `full` it also fails unless every `linux` and `macos` job succeeded (skipped is not enough), so Publish (which calls this file) can only release a tree whose full suite passed. In mode `none` it passes and says no tests are affected.
119
+ - The `full suite` job is the single result to require. It fails if `checks` or `select` did not succeed or any job failed or was cancelled; in mode `full` it also fails unless every `linux` and `macos` job succeeded (skipped is not enough, except `macos` on a pull request, where it never runs), so Publish (which calls this file) can only release a tree whose full suite passed. In mode `none` it passes and says no tests are affected.
120
120
  - `checks` builds once on ubuntu and uploads the JS output; the `linux` jobs unpack it and compile the Linux native addon in the container (the build is glibc, the image musl), and the `macos` jobs unpack it as is.
121
121
 
122
122
  ## The selector: `scripts/ci-select.mjs`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.595",
3
+ "version": "0.3.596",
4
4
  "description": "crtr — agent runtime with memory, plugins, and marketplaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -145,7 +145,7 @@
145
145
  },
146
146
  "license": "UNLICENSED",
147
147
  "dependencies": {
148
- "@north-light/identity": "0.3.595",
148
+ "@north-light/identity": "0.3.596",
149
149
  "@earendil-works/chord": "1.1.0",
150
150
  "@earendil-works/pi-agent-core": "1.1.0",
151
151
  "@earendil-works/pi-ai": "1.1.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/identity",
3
- "version": "0.3.595",
3
+ "version": "0.3.596",
4
4
  "description": "Northlight access-token verification and scope rules",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/runtime.lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.595",
3
+ "version": "0.3.596",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@north-light/cli",
9
- "version": "0.3.595",
9
+ "version": "0.3.596",
10
10
  "hasInstallScript": true,
11
11
  "license": "UNLICENSED",
12
12
  "workspaces": [
@@ -28,7 +28,7 @@
28
28
  "@milkdown/preset-gfm": "^7.22.3",
29
29
  "@milkdown/prose": "^7.22.3",
30
30
  "@milkdown/utils": "^7.22.3",
31
- "@north-light/identity": "0.3.595",
31
+ "@north-light/identity": "0.3.596",
32
32
  "cron-parser": "^5.6.0",
33
33
  "esbuild": "^0.27.7",
34
34
  "jose": "^6.2.12",
@@ -11956,17 +11956,17 @@
11956
11956
  },
11957
11957
  "packages/crouter-api": {
11958
11958
  "name": "@north-light/api",
11959
- "version": "0.3.595",
11959
+ "version": "0.3.596",
11960
11960
  "license": "UNLICENSED"
11961
11961
  },
11962
11962
  "packages/crouter-env-docker": {
11963
11963
  "name": "@north-light/env-docker",
11964
- "version": "0.3.595",
11964
+ "version": "0.3.596",
11965
11965
  "license": "UNLICENSED"
11966
11966
  },
11967
11967
  "packages/crouter-identity": {
11968
11968
  "name": "@north-light/identity",
11969
- "version": "0.3.595",
11969
+ "version": "0.3.596",
11970
11970
  "license": "UNLICENSED",
11971
11971
  "dependencies": {
11972
11972
  "jose": "^6.2.1"
@@ -11974,21 +11974,21 @@
11974
11974
  },
11975
11975
  "packages/crouter-plugin": {
11976
11976
  "name": "@north-light/plugin",
11977
- "version": "0.3.595",
11977
+ "version": "0.3.596",
11978
11978
  "license": "UNLICENSED",
11979
11979
  "dependencies": {
11980
- "@north-light/api": "0.3.595",
11981
- "@north-light/identity": "0.3.595"
11980
+ "@north-light/api": "0.3.596",
11981
+ "@north-light/identity": "0.3.596"
11982
11982
  }
11983
11983
  },
11984
11984
  "packages/crouter-sdk": {
11985
11985
  "name": "@north-light/sdk",
11986
- "version": "0.3.595",
11986
+ "version": "0.3.596",
11987
11987
  "license": "UNLICENSED",
11988
11988
  "dependencies": {
11989
- "@north-light/api": "0.3.595",
11990
- "@north-light/identity": "0.3.595",
11991
- "@north-light/plugin": "0.3.595",
11989
+ "@north-light/api": "0.3.596",
11990
+ "@north-light/identity": "0.3.596",
11991
+ "@north-light/plugin": "0.3.596",
11992
11992
  "jose": "^6.2.1"
11993
11993
  },
11994
11994
  "bin": {