@north-light/cli 0.3.524 → 0.3.525

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/api/command-manifest/result.d.ts +4 -2
  2. package/dist/api/command-manifest/result.js +1 -1
  3. package/dist/api/command-manifest/schema.js +1 -1
  4. package/dist/api/plugin-manifest-schema.d.ts +3 -0
  5. package/dist/builtin-memory/crouter-plugin/deploying.md +2 -2
  6. package/dist/builtin-memory/crouter-plugin/output.md +3 -1
  7. package/dist/clients/attach/chrome/roster.d.ts +1 -1
  8. package/dist/clients/attach/chrome/roster.js +4 -4
  9. package/dist/clients/attach/render/chat-view.d.ts +9 -0
  10. package/dist/clients/attach/render/chat-view.js +3 -3
  11. package/dist/clients/attach/render/page-block.d.ts +2 -0
  12. package/dist/clients/attach/render/page-block.js +1 -1
  13. package/dist/clients/attach/session/connection.d.ts +1 -1
  14. package/dist/clients/attach/session/context.d.ts +1 -1
  15. package/dist/clients/attach/session/profile-files.d.ts +3 -3
  16. package/dist/clients/attach/session/profile-files.js +1 -1
  17. package/dist/clients/attach/viewer.js +633 -756
  18. package/dist/commands/pkg/browse/command-view.js +1 -1
  19. package/dist/core/canvas/db.d.ts +28 -2
  20. package/dist/core/canvas/db.js +2 -2
  21. package/dist/core/canvas/nav-model.js +1 -1
  22. package/dist/core/canvas/recovery.js +1 -1
  23. package/dist/core/conversation-store/client.d.ts +2 -2
  24. package/dist/core/conversation-store/index.d.ts +30 -2
  25. package/dist/core/conversation-store/index.js +1 -1
  26. package/dist/core/conversation-store/patch.js +1 -1
  27. package/dist/core/graph/watches.d.ts +2 -0
  28. package/dist/core/graph/watches.js +9 -9
  29. package/dist/core/help.js +7 -7
  30. package/dist/core/llm/run.js +2 -2
  31. package/dist/core/runtime/broker/fault-retry.d.ts +9 -3
  32. package/dist/core/runtime/broker/fault-retry.js +1 -1
  33. package/dist/core/runtime/broker/rebind.d.ts +4 -0
  34. package/dist/core/runtime/broker/rebind.js +1 -1
  35. package/dist/core/runtime/broker/run-turn-queue.d.ts +2 -0
  36. package/dist/core/runtime/broker/run-turn-queue.js +1 -1
  37. package/dist/core/runtime/broker-persona-guidance.d.ts +1 -1
  38. package/dist/core/runtime/broker-persona-guidance.js +3 -3
  39. package/dist/core/runtime/broker.js +1 -1
  40. package/dist/core/runtime/close.d.ts +2 -2
  41. package/dist/core/runtime/close.js +1 -1
  42. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  43. package/dist/daemon/runs/observer.js +2 -2
  44. package/docs/plugin/deploying.md +2 -2
  45. package/docs/plugin/output.md +3 -1
  46. package/package.json +2 -2
  47. package/packages/crouter-identity/package.json +1 -1
  48. package/runtime.lock.json +12 -12
@@ -1 +1 @@
1
- var N=Object.defineProperty;var u=(e,s)=>N(e,"name",{value:s,configurable:!0});import{visibleWidth as g,wrapTextWithAnsi as b}from"@earendil-works/pi-tui";import{theme as f,wrapText as x}from"../../../core/tui/panel.js";import{commandLabel as h}from"./model.js";function k(e,s,t){const n=[];return n.push(...a(h(e),t).map(r=>f.fg("accent",f.bold(r)))),n.push(...a(`${e.kind.toUpperCase()} COMMAND \xB7 ${(e.tier??"normal").toUpperCase()} TIER`,t).map(r=>f.fg("dim",r))),n.push(""),n.push(...p(e.description,t)),c(n,"WHEN TO USE",t),n.push(...p(e.whenToUse,t)),c(n,"SUMMARY",t),n.push(...p(e.summary,t)),e.kind==="leaf"?v(n,e,s,t):S(n,e,t),n}u(k,"renderCommandView");function v(e,s,t,n){if(c(e,"PARAMS",n),s.params.length===0)e.push(...p("No input parameters.",n));else for(const o of s.params)e.push(...M(o,n));if(c(e,"OUTPUT",n),s.output.length===0)e.push(...p("No output fields declared.",n));else for(const o of s.output)e.push(...m(o,n));if(c(e,"EFFECTS",n),s.effects.length===0)e.push(...p("No effects declared.",n));else for(const o of s.effects)e.push(...i(" \u2022 ",o,n));if(c(e,"INVOKED VIA",n),t.transport===null){e.push(...a("This plugin declares no command transport.",n).map(o=>f.fg("warning",o)));return}const r=t.transportTarget??"No target declared.";e.push(...i(` ${t.transport} `,r,n)),t.transport==="http"&&s.rest!==void 0&&e.push(...i(" REST ",`${s.rest.method} ${s.rest.path} \xB7 ${s.rest.streaming?"streaming response":"single response"}`,n))}u(v,"renderLeaf");function S(e,s,t){if(s.rootEntry!==void 0&&(c(e,"ROOT ENTRY",t),e.push(...i(" Concept ",s.rootEntry.concept,t)),e.push(...i(" Description ",s.rootEntry.description,t)),e.push(...i(" When to use ",s.rootEntry.whenToUse,t))),s.passthrough!==void 0&&(c(e,"PASSES THROUGH",t),e.push(...i(" Binary ",s.passthrough.bin,t)),e.push(...i(" Install ",s.passthrough.installHint,t))),c(e,"CHILDREN",t),s.children.length===0){e.push(...p(s.passthrough===void 0?"No subcommands.":"No subcommands \u2014 every argument is forwarded to the binary.",t));return}for(const n of s.children)e.push(...i(` ${h(n)} `,n.description,t))}u(S,"renderBranch");function M(e,s){const t=D(e),n=i(` ${t} `,O(e),s),r=C;return e.kind==="positional"?(e.repeatable===!0&&n.push(...i(r,"Repeatable; supply multiple values in argv order.",s)),e.encoding!==void 0&&n.push(...i(r,d(e.encoding),s)),e.defaultFromEnv!==void 0&&n.push(...i(r,E(e.defaultFromEnv),s))):e.kind==="flag"?(e.choices!==void 0&&n.push(...i(r,`Choices: ${e.choices.join(", ")}.`,s)),e.default!==void 0&&n.push(...i(r,`Default: ${R(e.default)}.`,s)),e.repeatable===!0&&n.push(...i(r,"Repeatable; supply the flag multiple times to accumulate values.",s)),e.encoding!==void 0&&n.push(...i(r,d(e.encoding),s)),e.defaultFromEnv!==void 0&&n.push(...i(r,E(e.defaultFromEnv),s)),e.hidden===!0&&n.push(...i(r,"Hidden from the command's ordinary -h output.",s,"warning"))):e.kind==="context-file"&&(n.push(...i(r,`Mapped input: ${e.name}.`,s)),e.shape!==void 0&&n.push(...i(r,`Expected JSON: ${e.shape}`,s))),n.push(...i(r,`Constraint: ${e.constraint}`,s)),n}u(M,"renderParam");function m(e,s,t=" "){const n=`${t} `,r=[...i(`${t}${e.name} `,`${e.type} \xB7 ${e.required?"required":"optional"}`,s),...i(n,`Constraint: ${e.constraint}`,s)];return r.push(...$(e,s,n)),r}u(m,"renderField");function $(e,s,t){const n=[];e.values!==void 0&&n.push(...i(t,`Values: ${e.values.join(", ")}.`,s));for(const r of e.children??[])n.push(...m(r,s,t));if(e.items!==void 0){const r=e.items,o=r.constraint.length>0?` \xB7 ${r.constraint}`:"";n.push(...i(t,`Each element: ${r.type}${o}`,s)),n.push(...$(r,s,`${t} `))}return n}u($,"renderShapeBody");const C=" ";function D(e){switch(e.kind){case"positional":return`${e.name}${e.repeatable===!0?"\u2026":""}`;case"flag":return`--${e.name}`;case"stdin":return e.name;case"context-file":return"--context-file PATH"}}u(D,"paramLabel");function O(e){const s=e.required?"required":"optional";switch(e.kind){case"positional":return`positional \xB7 ${e.type??"string"} \xB7 ${s}`;case"flag":return`flag \xB7 ${e.type} \xB7 ${s}`;case"stdin":return`stdin \xB7 raw text \xB7 ${s}`;case"context-file":return`context file \xB7 JSON file \xB7 ${s}`}}u(O,"paramMeta");function d(e){return e==="base64"?"Encoding: reads the local file's raw bytes and sends base64; the path itself is never sent.":"Encoding: reads the local file as UTF-8 text and sends its content; the path itself is never sent."}u(d,"encodingDetail");function R(e){return typeof e=="string"?JSON.stringify(e):String(e)}u(R,"formatValue");function E(e){return`When $${e} is set and non-empty, it supplies the value and counts as supplied.`}u(E,"envDefaultDetail");function c(e,s,t){e.push(""),e.push(...a(s,t).map(n=>f.fg("dim",n)))}u(c,"section");function p(e,s){return a(e,Math.max(1,s-2)).map(n=>` ${f.fg("dim",n)}`)}u(p,"paragraph");function i(e,s,t,n="dim"){const r=g(e);if(r>=t)return[...a(e.trimEnd(),t).map(l=>f.fg("accent",l)),...a(s,Math.max(1,t-2)).map(l=>` ${f.fg(n,l)}`)];const o=Math.max(1,t-r),T=" ".repeat(r);return a(s,o).map((l,y)=>y===0?`${f.fg("accent",e)}${f.fg(n,l)}`:`${T}${f.fg(n,l)}`)}u(i,"hanging");function a(e,s){const t=e.trim(),n=Math.max(1,s);return t.split(/\s+/).some(r=>g(r)>n)?b(t,n):x(t,n)}u(a,"wrapped");export{k as renderCommandView};
1
+ var x=Object.defineProperty;var u=(e,s)=>x(e,"name",{value:s,configurable:!0});import{visibleWidth as h,wrapTextWithAnsi as N}from"@earendil-works/pi-tui";import{theme as c,wrapText as b}from"../../../core/tui/panel.js";import{commandLabel as $}from"./model.js";function k(e,s,t){const n=[];return n.push(...a($(e),t).map(r=>c.fg("accent",c.bold(r)))),n.push(...a(`${e.kind.toUpperCase()} COMMAND \xB7 ${(e.tier??"normal").toUpperCase()} TIER`,t).map(r=>c.fg("dim",r))),n.push(""),n.push(...p(e.description,t)),f(n,"WHEN TO USE",t),n.push(...p(e.whenToUse,t)),f(n,"SUMMARY",t),n.push(...p(e.summary,t)),e.kind==="leaf"?v(n,e,s,t):S(n,e,t),n}u(k,"renderCommandView");function v(e,s,t,n){if(f(e,"PARAMS",n),s.params.length===0)e.push(...p("No input parameters.",n));else for(const o of s.params)e.push(...M(o,n));if(f(e,"OUTPUT",n),s.output.length===0)e.push(...p("No output fields declared.",n));else for(const o of s.output)e.push(...m(o,n));if(f(e,"EFFECTS",n),s.effects.length===0)e.push(...p("No effects declared.",n));else for(const o of s.effects)e.push(...i(" \u2022 ",o,n));if(f(e,"INVOKED VIA",n),t.transport===null){e.push(...a("This plugin declares no command transport.",n).map(o=>c.fg("warning",o)));return}const r=t.transportTarget??"No target declared.";e.push(...i(` ${t.transport} `,r,n)),t.transport==="http"&&s.rest!==void 0&&e.push(...i(" REST ",`${s.rest.method} ${s.rest.path} \xB7 ${s.rest.streaming?"streaming response":"single response"}`,n))}u(v,"renderLeaf");function S(e,s,t){if(s.rootEntry!==void 0&&(f(e,"ROOT ENTRY",t),e.push(...i(" Concept ",s.rootEntry.concept,t)),e.push(...i(" Description ",s.rootEntry.description,t)),e.push(...i(" When to use ",s.rootEntry.whenToUse,t))),s.passthrough!==void 0&&(f(e,"PASSES THROUGH",t),e.push(...i(" Binary ",s.passthrough.bin,t)),e.push(...i(" Install ",s.passthrough.installHint,t))),f(e,"CHILDREN",t),s.children.length===0){e.push(...p(s.passthrough===void 0?"No subcommands.":"No subcommands \u2014 every argument is forwarded to the binary.",t));return}for(const n of s.children)e.push(...i(` ${$(n)} `,n.description,t))}u(S,"renderBranch");function M(e,s){const t=C(e),n=i(` ${t} `,D(e),s),r=O;return e.kind==="positional"?(e.repeatable===!0&&n.push(...i(r,"Repeatable; supply multiple values in argv order.",s)),e.encoding!==void 0&&n.push(...i(r,d(e.encoding),s)),e.defaultFromEnv!==void 0&&n.push(...i(r,E(e.defaultFromEnv),s))):e.kind==="flag"?(e.choices!==void 0&&n.push(...i(r,`Choices: ${e.choices.join(", ")}.`,s)),e.default!==void 0&&n.push(...i(r,`Default: ${R(e.default)}.`,s)),e.repeatable===!0&&n.push(...i(r,"Repeatable; supply the flag multiple times to accumulate values.",s)),e.encoding!==void 0&&n.push(...i(r,d(e.encoding),s)),e.defaultFromEnv!==void 0&&n.push(...i(r,E(e.defaultFromEnv),s)),e.hidden===!0&&n.push(...i(r,"Hidden from the command's ordinary -h output.",s,"warning"))):e.kind==="context-file"&&(n.push(...i(r,`Mapped input: ${e.name}.`,s)),e.shape!==void 0&&n.push(...i(r,`Expected JSON: ${e.shape}`,s))),n.push(...i(r,`Constraint: ${e.constraint}`,s)),n}u(M,"renderParam");function m(e,s,t=" "){const n=`${t} `,r=[...i(`${t}${e.name} `,`${e.type} \xB7 ${e.required?"required":"optional"}`,s),...i(n,`Constraint: ${e.constraint}`,s)];return r.push(...g(e,s,n)),r}u(m,"renderField");function g(e,s,t){const n=[];e.values!==void 0&&n.push(...i(t,`Values: ${e.values.join(", ")}.`,s));for(const r of e.children??[])n.push(...m(r,s,t));if(e.extra!==void 0){const r=e.extra,o=r.constraint.length>0?` \xB7 ${r.constraint}`:"";n.push(...i(t,`Other members: ${r.type}${o}`,s)),n.push(...g(r,s,`${t} `))}if(e.items!==void 0){const r=e.items,o=r.constraint.length>0?` \xB7 ${r.constraint}`:"";n.push(...i(t,`Each element: ${r.type}${o}`,s)),n.push(...g(r,s,`${t} `))}return n}u(g,"renderShapeBody");const O=" ";function C(e){switch(e.kind){case"positional":return`${e.name}${e.repeatable===!0?"\u2026":""}`;case"flag":return`--${e.name}`;case"stdin":return e.name;case"context-file":return"--context-file PATH"}}u(C,"paramLabel");function D(e){const s=e.required?"required":"optional";switch(e.kind){case"positional":return`positional \xB7 ${e.type??"string"} \xB7 ${s}`;case"flag":return`flag \xB7 ${e.type} \xB7 ${s}`;case"stdin":return`stdin \xB7 raw text \xB7 ${s}`;case"context-file":return`context file \xB7 JSON file \xB7 ${s}`}}u(D,"paramMeta");function d(e){return e==="base64"?"Encoding: reads the local file's raw bytes and sends base64; the path itself is never sent.":"Encoding: reads the local file as UTF-8 text and sends its content; the path itself is never sent."}u(d,"encodingDetail");function R(e){return typeof e=="string"?JSON.stringify(e):String(e)}u(R,"formatValue");function E(e){return`When $${e} is set and non-empty, it supplies the value and counts as supplied.`}u(E,"envDefaultDetail");function f(e,s,t){e.push(""),e.push(...a(s,t).map(n=>c.fg("dim",n)))}u(f,"section");function p(e,s){return a(e,Math.max(1,s-2)).map(n=>` ${c.fg("dim",n)}`)}u(p,"paragraph");function i(e,s,t,n="dim"){const r=h(e);if(r>=t)return[...a(e.trimEnd(),t).map(l=>c.fg("accent",l)),...a(s,Math.max(1,t-2)).map(l=>` ${c.fg(n,l)}`)];const o=Math.max(1,t-r),T=" ".repeat(r);return a(s,o).map((l,y)=>y===0?`${c.fg("accent",e)}${c.fg(n,l)}`:`${T}${c.fg(n,l)}`)}u(i,"hanging");function a(e,s){const t=e.trim(),n=Math.max(1,s);return t.split(/\s+/).some(r=>h(r)>n)?N(t,n):b(t,n)}u(a,"wrapped");export{k as renderCommandView};
@@ -1,6 +1,7 @@
1
- import { DatabaseSync } from 'node:sqlite';
1
+ import { DatabaseSync, type SQLInputValue } from 'node:sqlite';
2
+ import { prepared } from '../sqlite-statements.js';
2
3
  export { MIGRATIONS } from './migrations.js';
3
- export { prepared } from '../sqlite-statements.js';
4
+ export { prepared };
4
5
  /** A schema change invalidates statements compiled against the old schema. */
5
6
  export declare function migrate(db: DatabaseSync): void;
6
7
  /** Only the daemon (and its API-server test host) registers this process-local hook.
@@ -31,3 +32,28 @@ export declare function openDb(): DatabaseSync;
31
32
  export declare function withCanvasWrite<T>(body: (db: DatabaseSync) => T): T;
32
33
  /** Close and forget the handle for the current home. Mainly for tests. */
33
34
  export declare function closeDb(): void;
35
+ export type CanvasParams = [Record<string, SQLInputValue>, ...SQLInputValue[]] | SQLInputValue[];
36
+ export interface CanvasRunResult {
37
+ changes: number | bigint;
38
+ lastInsertRowid: number | bigint;
39
+ }
40
+ export interface CanvasStatement {
41
+ get<T = Record<string, unknown>>(...params: CanvasParams): Promise<T | undefined>;
42
+ all<T = Record<string, unknown>>(...params: CanvasParams): Promise<T[]>;
43
+ run(...params: CanvasParams): Promise<CanvasRunResult>;
44
+ }
45
+ export interface CanvasDb {
46
+ /** A statement compiled once per connection; for fixed SQL only. */
47
+ prepare(sql: string): CanvasStatement;
48
+ /** A statement compiled per call; for generated SQL (IN lists, schema-dependent text). */
49
+ prepareUncached(sql: string): CanvasStatement;
50
+ exec(sql: string): Promise<void>;
51
+ /** The SQLite connection, for the synchronous migration chain only. Deleted with the Postgres swap. */
52
+ readonly raw: DatabaseSync;
53
+ }
54
+ /** The async handle over the same cached connection `openDb()` returns. */
55
+ export declare function openCanvasDb(): Promise<CanvasDb>;
56
+ /** Run `body` in one `BEGIN IMMEDIATE` transaction. A call from inside the
57
+ * body's own async context joins it and only the outermost call commits; a call
58
+ * from any other context waits its turn. A throwing body rolls back. */
59
+ export declare function withCanvasWriteAsync<T>(body: (db: CanvasDb) => Promise<T> | T): Promise<T>;
@@ -1,2 +1,2 @@
1
- var m=Object.defineProperty;var n=(e,t)=>m(e,"name",{value:t,configurable:!0});import{DatabaseSync as f}from"node:sqlite";import{forgetPrepared as a}from"../sqlite-statements.js";import{appendFileSync as u}from"node:fs";import{canvasDbPath as i,ensureHome as d}from"./paths.js";import{initializeEmptyLayout as l}from"../layout.js";import{migrate as x}from"./migrations.js";import{MIGRATIONS as L}from"./migrations.js";import{prepared as S}from"../sqlite-statements.js";function R(e){try{x(e)}finally{a(e)}}n(R,"migrate");const o=new Map;let c;function w(e){const t=s();e(t),c=e}n(w,"bindDaemonCanvasOpenHook");function E(){c=void 0}n(E,"clearDaemonCanvasOpenHook");function g(){const e=process.env.CRTR_DB_OPEN_LEDGER;if(e)try{const t=`${new Date().toISOString()} ${process.pid} ${process.argv[1]??"<unknown>"}
2
- `;u(e,t)}catch{}}n(g,"recordOpenLedger");function s(){const e=i(),t=o.get(e);if(t)return t;l(),d(),g();const r=new f(e);r.exec("PRAGMA busy_timeout = 5000;"),r.exec("PRAGMA journal_mode = WAL;"),r.exec("PRAGMA foreign_keys = ON;");try{c?.(r)}catch(p){throw r.close(),p}return o.set(e,r),r}n(s,"openDb");function I(e){const t=s();if(t.isTransaction)return e(t);t.exec("BEGIN IMMEDIATE");try{const r=e(t);return t.exec("COMMIT"),r}catch(r){try{t.exec("ROLLBACK")}catch{}throw r}}n(I,"withCanvasWrite");function v(){const e=i(),t=o.get(e);t&&(a(t),t.close(),o.delete(e))}n(v,"closeDb");export{L as MIGRATIONS,w as bindDaemonCanvasOpenHook,E as clearDaemonCanvasOpenHook,v as closeDb,R as migrate,s as openDb,S as prepared,I as withCanvasWrite};
1
+ var M=Object.defineProperty;var r=(e,t)=>M(e,"name",{value:t,configurable:!0});import{DatabaseSync as D}from"node:sqlite";import{AsyncLocalStorage as v}from"node:async_hooks";import{forgetPrepared as l,prepared as f}from"../sqlite-statements.js";import{appendFileSync as O}from"node:fs";import{canvasDbPath as w,ensureHome as k}from"./paths.js";import{initializeEmptyLayout as C}from"../layout.js";import{migrate as I}from"./migrations.js";import{MIGRATIONS as Q}from"./migrations.js";function H(e){try{I(e)}finally{l(e)}}r(H,"migrate");const c=new Map;let i;function $(e){const t=p();e(t),i=e}r($,"bindDaemonCanvasOpenHook");function q(){i=void 0}r(q,"clearDaemonCanvasOpenHook");function S(){const e=process.env.CRTR_DB_OPEN_LEDGER;if(e)try{const t=`${new Date().toISOString()} ${process.pid} ${process.argv[1]??"<unknown>"}
2
+ `;O(e,t)}catch{}}r(S,"recordOpenLedger");function p(){const e=w(),t=c.get(e);if(t)return t;C(),k(),S();const n=new D(e);n.exec("PRAGMA busy_timeout = 5000;"),n.exec("PRAGMA journal_mode = WAL;"),n.exec("PRAGMA foreign_keys = ON;");try{i?.(n)}catch(o){throw n.close(),o}return c.set(e,n),n}r(p,"openDb");function K(e){const t=p();if(t.isTransaction)return e(t);t.exec("BEGIN IMMEDIATE");try{const n=e(t);return t.exec("COMMIT"),n}catch(n){try{t.exec("ROLLBACK")}catch{}throw n}}r(K,"withCanvasWrite");function j(){const e=w(),t=c.get(e);t&&(l(t),t.close(),c.delete(e))}r(j,"closeDb");const L=1e3,m=new v;class E{static{r(this,"FifoLock")}tail=Promise.resolve();pending=0;get busy(){return this.pending>0}async acquire(){this.pending++;const t=this.tail;let n;return this.tail=new Promise(o=>{n=o}),await t,()=>{this.pending--,n()}}}const y=new WeakMap,g=new WeakMap;function h(e){let t=y.get(e);return t||y.set(e,t=new E),t}r(h,"lockFor");function d(e){const t=m.getStore();return t!==void 0&&t.open&&t.db===e}r(d,"ownsTransaction");async function s(e,t){const n=h(e);if(d(e)||!n.busy)return t();const o=await n.acquire();try{return t()}finally{o()}}r(s,"gated");function x(e,t){const n=r(o=>o,"args");return{get:r((...o)=>s(e,()=>t().get(...n(o))),"get"),all:r((...o)=>s(e,()=>t().all(...n(o))),"all"),run:r((...o)=>s(e,()=>t().run(...n(o))),"run")}}r(x,"wrapStatement");function R(e){let t=g.get(e);return t||(t={prepare:r(n=>x(e,()=>f(e,n)),"prepare"),prepareUncached:r(n=>x(e,()=>e.prepare(n)),"prepareUncached"),exec:r(n=>s(e,()=>{e.exec(n)}),"exec"),raw:e},g.set(e,t)),t}r(R,"canvasDbFor");async function T(){return R(p())}r(T,"openCanvasDb");async function z(e){const t=await T(),n=t.raw;if(d(n))return e(t);const o=await h(n).acquire(),A=Date.now(),u={db:n,open:!0};try{n.exec("BEGIN IMMEDIATE");try{const a=await m.run(u,()=>e(t));return n.exec("COMMIT"),a}catch(a){try{n.exec("ROLLBACK")}catch{}throw a}}finally{u.open=!1;const a=Date.now()-A;a>L&&console.warn(`[canvas db] write transaction held ${a}ms; its body awaited non-db work while every other db caller waited`),o()}}r(z,"withCanvasWriteAsync");export{Q as MIGRATIONS,$ as bindDaemonCanvasOpenHook,q as clearDaemonCanvasOpenHook,j as closeDb,H as migrate,T as openCanvasDb,p as openDb,f as prepared,K as withCanvasWrite,z as withCanvasWriteAsync};
@@ -1 +1 @@
1
- var R=Object.defineProperty;var o=(t,e)=>R(t,"name",{value:e,configurable:!0});import{getNode as $,subscribersOf as y,subscriptionsOf as I}from"./index.js";import{faultSummary as C}from"./status-glyph.js";import{statusRank as S}from"./node-order.js";import{nodeGlyph as _,navLabel as G,shortId as O,tokensCell as T,activityCell as D,cycleBadge as W,askBadge as L,liveBelowBadge as M,truncate as N,fillBar as w,fillWidth as k,isAttached as H,BOLD as K,DIM as g,RESET as m,REVERSE as P,BG_ATTACHED as V}from"./nav-render.js";import{PI_MAX_WIDGET_LINES as dt,VIEWPORT_FALLBACK_ROWS as ft,ESC as ht,RESET as pt,BOLD as $t,DIM as mt,REVERSE as vt,BG_ATTACHED as Et,GREEN as xt,RED as gt,YELLOW as Bt,CYAN as bt,GRAY as St,nodeGlyph as wt,visibleWidth as kt,truncate as At,fillWidth as Rt,fillBar as yt,fmtTokens as It,tokensCell as Ct,activityCell as _t,cycleBadge as Gt,navLabel as Ot,shortId as Tt,askBadge as Dt,liveBelowBadge as Wt,isAttached as Lt,hasBrokerViewers as Mt,fetchAsksMap as Nt,graphWidgetBudget as Ht,GRAPH_HINT as Kt}from"./nav-render.js";function Y(t){try{return I(t)}catch{return[]}}o(Y,"subsOf");function F(t){try{return y(t)}catch{return[]}}o(F,"mgrsOf");function q(t){return F(t)[0]?.node_id}o(q,"managerOf");function X(t){return $(t)?.kind==="human"}o(X,"isHumanAsk");function v(t){return Y(t).map(e=>e.node_id).filter(e=>!X(e))}o(v,"convoChildIds");function rt(t){return v(t).filter(e=>{const s=$(e)?.status;return s==="active"||s==="idle"})}o(rt,"liveReports");function j(t){return v(t).length}o(j,"childCount");function z(t){let e=t;const s=new Set([e]);for(;;){const c=q(e);if(c===void 0||s.has(c))break;s.add(c),e=c}return e}o(z,"climbRoot");function ct(t){const e=[],s=new Set([t]),c=v(t);for(;c.length>0;){const l=c.shift();if(!s.has(l)){s.add(l),e.push(l);for(const u of v(l))s.has(u)||c.push(u)}}return e}o(ct,"subtreeIds");function J(t){if(t===null)return"";const e=j(t.node_id);return e>0?` ${g}\u2933${e}${m}`:""}o(J,"childBadge");function Q(t){return v(t).sort((e,s)=>S($(e)?.status)-S($(s)?.status))}o(Q,"sortedChildIds");function U(t,e){const s=new Set,c=new Map,l=new Set,u=o(n=>{const i=$(n)?.status==="active";if(l.has(n))return{active:i?1:0,reveal:i||n===e};l.add(n);let d=0,r=!1;for(const h of v(n)){const f=u(h);d+=f.active,f.reveal&&(r=!0)}return c.set(n,d),r&&s.add(n),{active:d+(i?1:0),reveal:r||i||n===e}},"visit");return u(t),{expand:s,activeBelow:c}}o(U,"computeSubtreeActivity");function Z(t,e){return U(t,e).expand}o(Z,"computeDefaultExpanded");function at(t,e,s){const c=z(t),l=s??Z(c,t),u=o(r=>e.userExpanded.has(r)?!1:e.userCollapsed.has(r)?!0:!l.has(r),"isFolded"),n=[],i=new Set,d=o((r,h,f,E)=>{if(i.has(r)){const a=f?"":E?"\u2514\u2500 ":"\u251C\u2500 ";n.push({id:r,hasKids:!1,isSelf:r===t,branch:h+a,cycle:!0,collapsed:!1});return}i.add(r);const p=Q(r),x=u(r),B=f?"":E?"\u2514\u2500 ":"\u251C\u2500 ";if(n.push({id:r,hasKids:p.length>0,isSelf:r===t,branch:h+B,cycle:!1,collapsed:x}),x)return;const b=f?"":h+(E?" ":"\u2502 ");for(let a=0;a<p.length;a++)d(p[a],b,!1,a===p.length-1)},"walk");return d(c,"",!0,!0),n}o(at,"buildGraphModel");function lt(t,e,s,c,l){const u=o((a,A)=>e?w(a,k(),P):A?w(a,k(),V):N(a),"wrap");if(t.cycle){const a=`${t.branch} ${g}\u21BA ${O(t.id)}${m}`;return u(a,!1)}const n=$(t.id),i=_(n),d=G(n,t.id),r=t.isSelf?`${K}${d}${m}`:d,h=`${g}${n?.kind??""}${m}`,f=`${g}${T(n)}${m}`,E=t.hasKids&&t.collapsed,p=!e&&E?`${g}\u25B8${m} `:" ",x=n?.fault??null,B=x!==null?` \xB7 ${C(x)}`:"",b=`${t.branch}${p}${i} ${r} ${h} ${f}${W(n)}${J(n)}${M(n,c)}${L(t.id,l)}${D(n)}${B}`;return u(b,H(t.id,n,s))}o(lt,"renderGraphRow");export{Et as BG_ATTACHED,$t as BOLD,bt as CYAN,mt as DIM,ht as ESC,Kt as GRAPH_HINT,St as GRAY,xt as GREEN,dt as PI_MAX_WIDGET_LINES,gt as RED,pt as RESET,vt as REVERSE,ft as VIEWPORT_FALLBACK_ROWS,Bt as YELLOW,_t as activityCell,Dt as askBadge,at as buildGraphModel,J as childBadge,j as childCount,z as climbRoot,Z as computeDefaultExpanded,U as computeSubtreeActivity,v as convoChildIds,Gt as cycleBadge,Nt as fetchAsksMap,yt as fillBar,Rt as fillWidth,It as fmtTokens,Ht as graphWidgetBudget,Mt as hasBrokerViewers,Lt as isAttached,X as isHumanAsk,Wt as liveBelowBadge,rt as liveReports,q as managerOf,Ot as navLabel,wt as nodeGlyph,lt as renderGraphRow,Tt as shortId,Q as sortedChildIds,ct as subtreeIds,Ct as tokensCell,At as truncate,kt as visibleWidth};
1
+ var A=Object.defineProperty;var o=(t,e)=>A(t,"name",{value:e,configurable:!0});import{getNode as x,subscribersOf as R,subscriptionsOf as y}from"./index.js";import{faultSummary as I}from"./status-glyph.js";import{statusRank as C}from"./node-order.js";import{nodeGlyph as _,navLabel as G,shortId as O,tokensCell as T,activityCell as D,cycleBadge as W,askBadge as L,liveBelowBadge as M,truncate as N,fillBar as b,fillWidth as S,isAttached as H,BOLD as K,DIM as g,RESET as $,REVERSE as P,BG_ATTACHED as V}from"./nav-render.js";import{PI_MAX_WIDGET_LINES as dt,VIEWPORT_FALLBACK_ROWS as ft,ESC as ht,RESET as pt,BOLD as $t,DIM as mt,REVERSE as vt,BG_ATTACHED as Et,GREEN as xt,RED as gt,YELLOW as kt,CYAN as Bt,GRAY as bt,nodeGlyph as St,visibleWidth as wt,truncate as At,fillWidth as Rt,fillBar as yt,fmtTokens as It,tokensCell as Ct,activityCell as _t,cycleBadge as Gt,navLabel as Ot,shortId as Tt,askBadge as Dt,liveBelowBadge as Wt,isAttached as Lt,hasBrokerViewers as Mt,fetchAsksMap as Nt,graphWidgetBudget as Ht,GRAPH_HINT as Kt}from"./nav-render.js";function Y(t){try{return y(t)}catch{return[]}}o(Y,"subsOf");function F(t){try{return R(t)}catch{return[]}}o(F,"mgrsOf");function q(t){return F(t)[0]?.node_id}o(q,"managerOf");function X(t){return x(t)?.kind==="human"}o(X,"isHumanAsk");function m(t){return Y(t).map(e=>e.node_id).filter(e=>!X(e))}o(m,"convoChildIds");function st(t){return m(t).filter(e=>{const r=x(e)?.status;return r==="active"||r==="idle"})}o(st,"liveReports");function j(t){return m(t).length}o(j,"childCount");function z(t){let e=t;const r=new Set([e]);for(;;){const c=q(e);if(c===void 0||r.has(c))break;r.add(c),e=c}return e}o(z,"climbRoot");function ct(t){const e=[],r=new Set([t]),c=m(t);for(;c.length>0;){const l=c.shift();if(!r.has(l)){r.add(l),e.push(l);for(const u of m(l))r.has(u)||c.push(u)}}return e}o(ct,"subtreeIds");function J(t){if(t===null)return"";const e=j(t.node_id);return e>0?` ${g}\u2933${e}${$}`:""}o(J,"childBadge");function Q(t){return m(t).map(e=>({cid:e,rank:C(x(e)?.status)})).sort((e,r)=>e.rank-r.rank).map(({cid:e})=>e)}o(Q,"sortedChildIds");function U(t,e){const r=new Set,c=new Map,l=new Set,u=o(n=>{const i=x(n)?.status==="active";if(l.has(n))return{active:i?1:0,reveal:i||n===e};l.add(n);let d=0,s=!1;for(const h of m(n)){const f=u(h);d+=f.active,f.reveal&&(s=!0)}return c.set(n,d),s&&r.add(n),{active:d+(i?1:0),reveal:s||i||n===e}},"visit");return u(t),{expand:r,activeBelow:c}}o(U,"computeSubtreeActivity");function Z(t,e){return U(t,e).expand}o(Z,"computeDefaultExpanded");function at(t,e,r){const c=z(t),l=r??Z(c,t),u=o(s=>e.userExpanded.has(s)?!1:e.userCollapsed.has(s)?!0:!l.has(s),"isFolded"),n=[],i=new Set,d=o((s,h,f,v)=>{if(i.has(s)){const a=f?"":v?"\u2514\u2500 ":"\u251C\u2500 ";n.push({id:s,hasKids:!1,isSelf:s===t,branch:h+a,cycle:!0,collapsed:!1});return}i.add(s);const p=Q(s),E=u(s),k=f?"":v?"\u2514\u2500 ":"\u251C\u2500 ";if(n.push({id:s,hasKids:p.length>0,isSelf:s===t,branch:h+k,cycle:!1,collapsed:E}),E)return;const B=f?"":h+(v?" ":"\u2502 ");for(let a=0;a<p.length;a++)d(p[a],B,!1,a===p.length-1)},"walk");return d(c,"",!0,!0),n}o(at,"buildGraphModel");function lt(t,e,r,c,l){const u=o((a,w)=>e?b(a,S(),P):w?b(a,S(),V):N(a),"wrap");if(t.cycle){const a=`${t.branch} ${g}\u21BA ${O(t.id)}${$}`;return u(a,!1)}const n=x(t.id),i=_(n),d=G(n,t.id),s=t.isSelf?`${K}${d}${$}`:d,h=`${g}${n?.kind??""}${$}`,f=`${g}${T(n)}${$}`,v=t.hasKids&&t.collapsed,p=!e&&v?`${g}\u25B8${$} `:" ",E=n?.fault??null,k=E!==null?` \xB7 ${I(E)}`:"",B=`${t.branch}${p}${i} ${s} ${h} ${f}${W(n)}${J(n)}${M(n,c)}${L(t.id,l)}${D(n)}${k}`;return u(B,H(t.id,n,r))}o(lt,"renderGraphRow");export{Et as BG_ATTACHED,$t as BOLD,Bt as CYAN,mt as DIM,ht as ESC,Kt as GRAPH_HINT,bt as GRAY,xt as GREEN,dt as PI_MAX_WIDGET_LINES,gt as RED,pt as RESET,vt as REVERSE,ft as VIEWPORT_FALLBACK_ROWS,kt as YELLOW,_t as activityCell,Dt as askBadge,at as buildGraphModel,J as childBadge,j as childCount,z as climbRoot,Z as computeDefaultExpanded,U as computeSubtreeActivity,m as convoChildIds,Gt as cycleBadge,Nt as fetchAsksMap,yt as fillBar,Rt as fillWidth,It as fmtTokens,Ht as graphWidgetBudget,Mt as hasBrokerViewers,Lt as isAttached,X as isHumanAsk,Wt as liveBelowBadge,st as liveReports,q as managerOf,Ot as navLabel,St as nodeGlyph,lt as renderGraphRow,Tt as shortId,Q as sortedChildIds,ct as subtreeIds,Ct as tokensCell,At as truncate,wt as visibleWidth};
@@ -23,4 +23,4 @@ CREATE TABLE IF NOT EXISTS node_faults (
23
23
  );
24
24
  CREATE UNIQUE INDEX IF NOT EXISTS idx_node_faults_active ON node_faults(node_id) WHERE active = 1;
25
25
  CREATE UNIQUE INDEX IF NOT EXISTS idx_node_faults_episode ON node_faults(node_id) WHERE episode_state IS NOT NULL;
26
- `)}o(ge,"createFaultTable");function g(e,n){return typeof n=="string"&&e.includes(n)}o(g,"contains");function F(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(F,"isRecord");function K(e){if(!F(e)||typeof e.provider!="string"||e.provider===""||typeof e.model!="string"||e.model==="")return;const n=typeof e.status=="number"&&Number.isFinite(e.status)?e.status:void 0,t=typeof e.code=="string"||typeof e.code=="number"?e.code:void 0,r=typeof e.errno=="string"?e.errno:void 0,i=typeof e.body=="string"?e.body:void 0,d=_e(e.ratelimit),a=Array.isArray(e.causes)?e.causes.flatMap(u=>{if(!F(u))return[];const f={...typeof u.message=="string"?{message:u.message}:{},...typeof u.status=="number"&&Number.isFinite(u.status)?{status:u.status}:{},...typeof u.code=="string"||typeof u.code=="number"?{code:u.code}:{},...typeof u.errno=="string"?{errno:u.errno}:{},...typeof u.body=="string"?{body:u.body}:{}};return Object.keys(f).length===0?[]:[f]}):void 0;return{provider:e.provider,model:e.model,...n===void 0?{}:{status:n},...t===void 0?{}:{code:t},...r===void 0?{}:{errno:r},...i===void 0?{}:{body:i},...a===void 0||a.length===0?{}:{causes:a},...d===void 0?{}:{ratelimit:d}}}o(K,"parseProviderError");function Y(e){try{const n=JSON.parse(e);if(!g(pe,n.link)||typeof n.op!="string"||n.op===""||!g(Ee,n.kind)||typeof n.message!="string"||typeof n.since!="string")return null;const t=j(n.operation_id);if(!F(n.retry)||!g(fe,n.retry.disposition)||n.retry.by!==void 0&&!g(ye,n.retry.by)||n.retry.attempt!==void 0&&typeof n.retry.attempt!="number"||n.retry.max!==void 0&&typeof n.retry.max!="number"||n.retry.nextAt!==void 0&&typeof n.retry.nextAt!="string"||n.anchorEntryId!==void 0&&(typeof n.anchorEntryId!="string"||n.anchorEntryId===""))return null;const r=n.providerError===void 0?void 0:K(n.providerError);return n.providerError!==void 0&&r===void 0?null:{link:n.link,op:n.op,kind:n.kind,retry:{disposition:n.retry.disposition,...n.retry.by===void 0?{}:{by:n.retry.by},...n.retry.attempt===void 0?{}:{attempt:n.retry.attempt},...n.retry.max===void 0?{}:{max:n.retry.max},...n.retry.nextAt===void 0?{}:{nextAt:n.retry.nextAt}},message:n.message,since:n.since,operation_id:t,...n.anchorEntryId===void 0?{}:{anchorEntryId:n.anchorEntryId},...r===void 0?{}:{providerError:r}}}catch{return null}}o(Y,"parseLegacyFault");function Le(e){const n=ae(e);try{return se(n)}catch{return n}}o(Le,"canonicalPath");function me(e){try{const n=JSON.parse(e);if(!g(Te,n.state)||typeof n.sessionFile!="string"||n.sessionFile==="")return null;const t=JSON.stringify(n.fault),r=Y(t);if(r===null||r.link!=="pi\u2192provider"||r.retry.disposition!=="auto"||r.retry.by!=="daemon")return null;const i=n.anchorEntryId;return i!==null&&typeof i!="string"||(r.anchorEntryId??null)!==i?null:{state:n.state,sessionFile:Le(n.sessionFile),fault:r}}catch{return null}}o(me,"parseLegacyEpisode");function G(e){return e!==void 0?j(e):$.current()??$.fresh(t=>t)}o(G,"resolveOperationId");function Se(e){return e.slice(0,le)}o(Se,"clampMessage");function R(e){return e.link==="pi\u2192provider"&&e.retry.disposition==="auto"&&e.retry.by==="daemon"?3:e.retry.disposition==="fatal"?2:1}o(R,"faultPriority");function V(e){return{link:e.link,op:e.op,kind:e.kind,message:e.message,since:e.since,operationId:e.operation_id,anchorEntryId:e.anchorEntryId??null,retryDisposition:e.retry.disposition,retryBy:e.retry.by??null,retryAttempt:e.retry.attempt??null,retryMax:e.retry.max??null,retryNextAt:e.retry.nextAt??null,providerError:e.providerError===void 0?null:JSON.stringify(e.providerError)}}o(V,"encodeFault");function H(e){const n=e.provider_error_json,t=typeof n=="string"?K(JSON.parse(n)):void 0;if(typeof n=="string"&&t===void 0)throw new Error(`invalid provider error on stored fault ${e.fault_id}`);const r={disposition:e.retry_disposition,...e.retry_by===null?{}:{by:e.retry_by},...e.retry_attempt===null?{}:{attempt:e.retry_attempt},...e.retry_max===null?{}:{max:e.retry_max},...e.retry_next_at===null?{}:{nextAt:e.retry_next_at}};return{faultId:e.fault_id,link:e.link,op:e.op,kind:e.kind,message:e.message,since:e.since,operation_id:e.operation_id,retry:r,...e.anchor_entry_id===null?{}:{anchorEntryId:e.anchor_entry_id},...t===void 0?{}:{providerError:t}}}o(H,"hydrateFault");function L(e,n){const t=ue(e,"SELECT * FROM node_faults WHERE node_id = ? AND active = 1").get(n);return t===void 0?null:H(t)}o(L,"activeFault");function Q(e){if(!g(B,e.link))throw new Error(`fault link is not durable: ${e.link}`);return{link:e.link,op:e.op,kind:e.kind,retry:e.retry,message:Se(e.message),since:e.since??c(),operation_id:G(e.operation_id),...typeof e.anchorEntryId=="string"&&e.anchorEntryId!==""?{anchorEntryId:e.anchorEntryId}:{},...e.providerError===void 0?{}:{providerError:e.providerError}}}o(Q,"storedFault");function q(e,n){X({level:n.retry.disposition==="fatal"?"error":"warn",event:"fault.recorded",operation_id:n.operation_id,node_id:e,error_class:w(n),fields:{link:n.link,op:n.op,kind:n.kind,retry:n.retry,message:n.message,...n.anchorEntryId===void 0?{}:{anchor_entry_id:n.anchorEntryId},...n.providerError===void 0?{}:{provider_error:n.providerError}}})}o(q,"emitRecordedFault");function W(e,n,t,r,i){const d=C(),a=V(t),u=c();return s(e,"INSERT INTO node_faults (fault_id, node_id, link, op, kind, message, since, operation_id, anchor_entry_id, retry_disposition, retry_by, retry_attempt, retry_max, retry_next_at, provider_error_json, active, episode_state, episode_binding_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(d,n,a.link,a.op,a.kind,a.message,a.since,a.operationId,a.anchorEntryId,a.retryDisposition,a.retryBy,a.retryAttempt,a.retryMax,a.retryNextAt,a.providerError,r?1:0,i?.state??null,i?.bindingId??null,u,u),{...t,faultId:d}}o(W,"insertFault");function z(e,n,t,r){const i=V(t);return s(e,"UPDATE node_faults SET link = ?, op = ?, kind = ?, message = ?, since = ?, operation_id = ?, anchor_entry_id = ?, retry_disposition = ?, retry_by = ?, retry_attempt = ?, retry_max = ?, retry_next_at = ?, provider_error_json = ?, episode_state = COALESCE(?, episode_state), episode_binding_id = COALESCE(?, episode_binding_id), updated_at = ? WHERE fault_id = ?").run(i.link,i.op,i.kind,i.message,i.since,i.operationId,i.anchorEntryId,i.retryDisposition,i.retryBy,i.retryAttempt,i.retryMax,i.retryNextAt,i.providerError,r?.state??null,r?.bindingId??null,c(),n),{...t,faultId:n}}o(z,"updateFault");function D(e,n){s(e,"DELETE FROM node_faults WHERE fault_id = ? AND active = 0 AND episode_state IS NULL").run(n)}o(D,"deleteIfUnretained");function Z(e,n,t,r){const i=L(e,n);if(i===null){const d=s(e,"SELECT fault_id, link, kind, since, operation_id FROM node_faults WHERE node_id = ? AND active = 0 AND episode_state IS NOT NULL").get(n);return d!==void 0&&d.link===t.link&&d.kind===t.kind&&d.since===t.since&&d.operation_id===t.operation_id?(s(e,"UPDATE node_faults SET active = 1, updated_at = ? WHERE fault_id = ?").run(c(),d.fault_id),z(e,d.fault_id,t)):W(e,n,t,!0,r)}if(i.link===t.link&&i.kind===t.kind){const d={...i.retry,...t.retry};return t.retry.disposition==="fatal"&&!("nextAt"in t.retry)&&delete d.nextAt,z(e,i.faultId,{...t,since:i.since,anchorEntryId:i.anchorEntryId??t.anchorEntryId,retry:d},r)}return R(i)>R(t)?null:(s(e,"UPDATE node_faults SET active = 0, updated_at = ? WHERE fault_id = ?").run(c(),i.faultId),D(e,i.faultId),W(e,n,t,!0,r))}o(Z,"replaceActiveFault");function m(e,n,t){return s(e,"SELECT binding_id FROM sessions WHERE node_id = ? AND session_id = ? AND unbound_at IS NULL").get(n,t)?.binding_id??null}o(m,"liveBinding");function Pe(e,n){return l(t=>{const r=c();return s(t,"UPDATE executions SET turn_progress_at = ? WHERE execution_id = ? AND state != 'exited' AND turn_open_at IS NOT NULL AND turn_closed_at IS NULL").run(r,e).changes>0?!0:s(t,"UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = NULL, turn_end_reason = NULL WHERE execution_id = ? AND state != 'exited'").run(r,r,e).changes>0})}o(Pe,"openTurn");function Me(e){return l(n=>s(n,"UPDATE executions SET turn_progress_at = ? WHERE execution_id = ? AND state != 'exited' AND turn_open_at IS NOT NULL AND turn_closed_at IS NULL").run(c(),e).changes>0)}o(Me,"recordTurnProgress");function we(e,n){return l(t=>{const r=c(),i=s(t,"UPDATE executions SET turn_closed_at = ?, turn_end_reason = ? WHERE execution_id = ? AND state != 'exited' AND turn_open_at IS NOT NULL AND turn_closed_at IS NULL").run(r,n.endReason,e).changes>0;if(i&&n.endReason==="settled"){const d="(SELECT node_id FROM executions WHERE execution_id = ?)";n.viewerPresent===!0?s(t,`UPDATE nodes SET reply_at = ?, read_at = ? WHERE node_id = ${d}`).run(r,r,e):s(t,`UPDATE nodes SET reply_at = ? WHERE node_id = ${d}`).run(r,e)}return i})}o(we,"closeTurn");function Xe(e){return l(n=>s(n,"UPDATE nodes SET read_at = ? WHERE node_id = ?").run(c(),e).changes>0)}o(Xe,"markNodeRead");function $e(e,n){if(!Number.isInteger(n.consecutivePasses)||n.consecutivePasses<1||n.routes.length===0||!n.routes.every(t=>t!==""))throw new Error("invalid transport-poison verdict");return l(t=>s(t,"UPDATE executions SET exit_diagnostic_json = ? WHERE execution_id = ? AND state != 'exited'").run(JSON.stringify({schema:"crtr.execution-exit-diagnostic/v1",transport_poison:{consecutive_passes:n.consecutivePasses,routes:n.routes}}),e).changes>0)}o($e,"recordTransportPoisonVerdict");function je(e){const n=s(E(),"SELECT exit_diagnostic_json FROM executions WHERE node_id = ? ORDER BY rowid DESC LIMIT 1").get(e);if(n===void 0||n.exit_diagnostic_json===null)return null;try{const t=JSON.parse(n.exit_diagnostic_json),r=t.transport_poison;return t.schema!=="crtr.execution-exit-diagnostic/v1"||r===void 0||!Number.isInteger(r.consecutive_passes)||r.consecutive_passes<1||!Array.isArray(r.routes)||r.routes.length===0||!r.routes.every(i=>typeof i=="string"&&i!=="")?null:{consecutivePasses:r.consecutive_passes,routes:r.routes}}catch{return null}}o(je,"readTransportPoisonVerdict");function Be(e){const n=s(E(),"SELECT turn_open_at, turn_closed_at, turn_progress_at FROM executions WHERE node_id = ? AND state != 'exited'").get(e);return n===void 0?null:{busy:n.turn_open_at!==null&&n.turn_closed_at===null,progressAt:n.turn_progress_at}}o(Be,"readLiveTurn");function Je(e){const n=E(),t=s(n,"SELECT turn_closed_at, turn_progress_at FROM executions WHERE node_id = ? AND turn_open_at IS NOT NULL ORDER BY rowid DESC LIMIT 1").get(e);if(t===void 0)return null;const r=s(n,"SELECT turn_end_reason FROM executions WHERE node_id = ? ORDER BY rowid DESC LIMIT 1").get(e);return{interrupted:t.turn_closed_at===null||r?.turn_end_reason==="teardown-aborted",progressAt:t.turn_progress_at}}o(Je,"readInterruptedTurn");function Ke(e){return s(E(),"SELECT 1 FROM executions WHERE node_id = ? AND turn_open_at IS NOT NULL LIMIT 1").get(e)!==void 0}o(Ke,"hasAdmittedTurn");function Ye(e,n){const t=Q(n);return q(e,t),l(r=>Z(r,e,t))}o(Ye,"recordFault");function Ge(e,n){const t=L(E(),e);return t===null||n?.link!==void 0&&t.link!==n.link?!1:l(r=>{const i=L(r,e);if(i===null||n?.link!==void 0&&i.link!==n.link)return!1;const d=s(r,"SELECT episode_state FROM node_faults WHERE fault_id = ?").get(i.faultId);s(r,"UPDATE node_faults SET active = 0, updated_at = ? WHERE fault_id = ?").run(c(),i.faultId),d.episode_state==="pending"&&n?.preserveEpisode!==!0&&s(r,"UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE fault_id = ?").run(c(),i.faultId),D(r,i.faultId);const a=G();return X({level:"info",event:"fault.cleared",operation_id:a,node_id:e,error_class:w(i),fields:{cleared_fault_operation_id:i.operation_id,link:i.link,op:i.op,kind:i.kind,retry:i.retry,message:i.message,since:i.since,...i.anchorEntryId===void 0?{}:{anchor_entry_id:i.anchorEntryId}}}),!0})}o(Ge,"clearFault");function ee(e){return L(E(),e)}o(ee,"readFault");function Ve(e,n){const t=Q(n.input);if(t.link!=="pi\u2192provider"||t.retry.disposition!=="auto"||t.retry.by!=="daemon")throw new Error("provider retry episode requires an automatic daemon provider fault");return q(e,t),l(r=>{const i=m(r,e,n.sessionId);if(i===null)return null;const d=L(r,e);if(d!==null&&(d.link!==t.link||d.kind!==t.kind)&&R(d)>R(t))return null;const a=s(r,"SELECT fault_id FROM node_faults WHERE node_id = ? AND episode_state IS NOT NULL").all(e);s(r,"UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE node_id = ? AND episode_state IS NOT NULL").run(c(),e);for(const f of a)D(r,f.fault_id);const u=Z(r,e,t,{state:"pending",bindingId:i});return u===null?null:(s(r,"UPDATE node_faults SET episode_state = ?, episode_binding_id = ?, updated_at = ? WHERE fault_id = ?").run("pending",i,c(),u.faultId),u)})}o(Ve,"recordPendingEpisode");function Qe(e,n){return l(t=>{if(s(t,"SELECT 1 FROM nodes WHERE node_id = ? AND intent IS 'refresh'").get(e)!==void 0)return!1;const r=m(t,e,n.sessionId);return r===null?!1:s(t,"UPDATE node_faults SET episode_state = 'admitted', retry_disposition = ?, retry_by = ?, retry_attempt = ?, retry_max = ?, retry_next_at = ?, updated_at = ? WHERE node_id = ? AND fault_id = ? AND episode_state = 'pending' AND episode_binding_id = ?").run(n.retry.disposition,n.retry.by??null,n.retry.attempt??null,n.retry.max??null,n.retry.nextAt??null,c(),e,n.faultId,r).changes>0})}o(Qe,"admitEpisode");function qe(e,n){return l(t=>{const r=m(t,e,n.sessionId);return r===null?!1:s(t,"UPDATE node_faults SET episode_state = 'pending', updated_at = ? WHERE node_id = ? AND episode_state = 'admitted' AND episode_binding_id = ?").run(c(),e,r).changes>0})}o(qe,"reopenEpisode");function ze(e,n){return l(t=>{const r=m(t,e,n.sessionId);return r===null?!1:s(t,"UPDATE node_faults SET episode_state = 'invalidated', updated_at = ? WHERE node_id = ? AND episode_state != 'invalidated' AND episode_state IS NOT NULL AND episode_binding_id = ?").run(c(),e,r).changes>0})}o(ze,"invalidateEpisode");function Ze(e,n){return l(t=>{const r=m(t,e,n.sessionId);if(r===null)return!1;const i=s(t,"SELECT fault_id FROM node_faults WHERE node_id = ? AND episode_binding_id = ? AND episode_state IS NOT NULL").all(e,r);if(i.length===0)return!1;s(t,"UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE node_id = ? AND episode_binding_id = ? AND episode_state IS NOT NULL").run(c(),e,r);for(const d of i)D(t,d.fault_id);return!0})}o(Ze,"clearEpisode");function en(e){const n=s(E(),"SELECT f.*, s.session_id FROM node_faults f JOIN sessions s ON s.binding_id = f.episode_binding_id WHERE f.node_id = ? AND f.episode_state IS NOT NULL").get(e);return n===void 0?null:{state:n.episode_state,sessionId:n.session_id,fault:H(n)}}o(en,"readEpisode");function nn(){return s(E(),"SELECT f.*, s.session_id AS bound_session_id FROM node_faults f JOIN sessions s ON s.binding_id = f.episode_binding_id WHERE f.active = 1 AND f.episode_state = 'pending' AND s.unbound_at IS NULL AND s.session_id IS NOT NULL AND f.link = 'pi\u2192provider' AND f.retry_disposition = 'auto' AND f.retry_by = 'daemon' AND f.kind IN ('connection', 'rate-limit', 'overloaded')").all().map(n=>({nodeId:n.node_id,sessionId:n.bound_session_id,fault:H(n),updatedAt:n.updated_at}))}o(nn,"listPendingProviderRetries");function tn(e){const n=ee(e)===null;return{explanation(){if(!n)return null;const t=ee(e);if(t===null||t.link!=="crtr\u2192pi"||t.retry.disposition!=="fatal")return null;const r=t.op.trim(),i=t.message.trim();return r===""||i===""?null:`${r}: ${i}`}}}o(tn,"beginBootFaultAttempt");function ne(e,n){try{return de(e).mtime.toISOString()}catch{return n}}o(ne,"markerMtime");function P(e,n){if(!p(e))return null;try{return oe(e,"utf8")}catch(t){if(!n)return null;throw new Error(`cannot import recovery input ${e}: ${t.message}`)}}o(P,"legacyFile");function Ae(e,n){return s(e,"SELECT execution_id, started_at FROM executions WHERE node_id = ? ORDER BY rowid DESC LIMIT 1").get(n)??null}o(Ae,"latestExecution");function xe(e,n){const r=J(e,"nodes").has("launched_at")?s(e,"SELECT COALESCE(launched_at, created) AS started_at FROM nodes WHERE node_id = ?").get(n):s(e,"SELECT created AS started_at FROM nodes WHERE node_id = ?").get(n);if(r===void 0)throw new Error(`cannot import recovery witness for unknown node ${n}`);const i=C();return s(e,"INSERT INTO executions (execution_id, node_id, daemon_epoch, pid, process_identity, state, started_at, ended_at, exit_reason) VALUES (?, ?, NULL, NULL, NULL, 'exited', ?, ?, 'pre-consolidation')").run(i,n,r.started_at,r.started_at),{execution_id:i,started_at:r.started_at}}o(xe,"syntheticExecution");function te(e,n,t,r,i){return W(e,n,t,r,i)}o(te,"insertMigratedFault");function Ie(e,n,t,r){const i=s(e,"SELECT binding_id, node_id FROM sessions WHERE transcript_path = ? AND unbound_at IS NULL").get(t);if(i!==void 0){if(i.node_id!==n)throw new Error(`cannot import provider retry ${r}: transcript is live-owned by ${i.node_id}`);return i.binding_id}const d=s(e,"SELECT binding_id FROM sessions WHERE node_id = ? AND transcript_path = ? ORDER BY rowid DESC LIMIT 1").get(n,t);if(d!==void 0)return d.binding_id;const a=s(e,"SELECT created FROM nodes WHERE node_id = ?").get(n);if(a===void 0)throw new Error(`cannot import provider retry ${r}: unknown node ${n}`);const u=C();return s(e,"INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at, unbound_at) VALUES (?, NULL, ?, ?, NULL, NULL, ?, ?, ?)").run(u,n,t,a.created,a.created,c()),u}o(Ie,"migrationBinding");function rn(e){if(Ne(e),ge(e),!p(b()))return;const n=ie(b(),{withFileTypes:!0}).filter(r=>r.isDirectory()).sort((r,i)=>r.name.localeCompare(i.name)),t=s(e,"SELECT 1 FROM nodes WHERE node_id = ?");for(const r of n){const i=r.name,d=ce(i),a=N(d,"busy"),u=N(d,"clean-abort"),f=N(d,"transport-poison.json"),h=N(d,"fault"),S=N(d,"provider-retry"),O=p(a),U=p(u);if(!O&&!U&&!p(f)&&!p(h)&&!p(S)||!p(N(b(),i,"meta.json"))&&t.get(i)===void 0)continue;const k=P(f,!1),A=P(h,!0),x=P(S,!0);if(!O&&!U&&k===null&&A===null&&x===null)continue;let y=Ae(e,i);if(y===null&&(y=xe(e,i)),O){const _=ne(a,y.started_at);s(e,"UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = NULL, turn_end_reason = NULL WHERE execution_id = ?").run(_,_,y.execution_id)}else if(U){const _=ne(u,y.started_at);s(e,"UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = ?, turn_end_reason = 'teardown-aborted' WHERE execution_id = ?").run(_,_,_,y.execution_id)}if(k!==null)try{const _=JSON.parse(k);Number.isInteger(_.consecutivePasses)&&_.consecutivePasses>=1&&Array.isArray(_.routes)&&_.routes.length>0&&_.routes.every(M=>typeof M=="string"&&M!=="")&&s(e,"UPDATE executions SET exit_diagnostic_json = ? WHERE execution_id = ?").run(JSON.stringify({schema:"crtr.execution-exit-diagnostic/v1",transport_poison:{consecutive_passes:_.consecutivePasses,routes:_.routes}}),y.execution_id)}catch{}const I=A===null?null:Y(A);if(A!==null&&I===null)throw new Error(`cannot import recovery fault ${h}`);const T=x===null?null:me(x);if(x!==null&&T===null)throw new Error(`cannot import provider retry ${S}`);let v=I===null||I.link==="broker\u2194crtrd"?null:te(e,i,I,!0);if(T!==null){const _=Ie(e,i,T.sessionFile,S);v!==null&&v.since===T.fault.since?s(e,"UPDATE node_faults SET episode_state = ?, episode_binding_id = ?, updated_at = ? WHERE fault_id = ?").run(T.state,_,c(),v.faultId):te(e,i,T.fault,!1,{state:T.state,bindingId:_})}}}o(rn,"migrateRecoveryWitnesses");export{We as FAULT_QUIET_MS,Qe as admitEpisode,tn as beginBootFaultAttempt,Ze as clearEpisode,Ge as clearFault,we as closeTurn,Ke as hasAdmittedTurn,H as hydrateFault,ze as invalidateEpisode,nn as listPendingProviderRetries,Xe as markNodeRead,rn as migrateRecoveryWitnesses,Pe as openTurn,K as parseProviderError,en as readEpisode,ee as readFault,Je as readInterruptedTurn,Be as readLiveTurn,je as readTransportPoisonVerdict,Ye as recordFault,Ve as recordPendingEpisode,$e as recordTransportPoisonVerdict,Me as recordTurnProgress,qe as reopenEpisode};
26
+ `)}o(ge,"createFaultTable");function g(e,n){return typeof n=="string"&&e.includes(n)}o(g,"contains");function F(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(F,"isRecord");function K(e){if(!F(e)||typeof e.provider!="string"||e.provider===""||typeof e.model!="string"||e.model==="")return;const n=typeof e.status=="number"&&Number.isFinite(e.status)?e.status:void 0,t=typeof e.code=="string"||typeof e.code=="number"?e.code:void 0,r=typeof e.errno=="string"?e.errno:void 0,i=typeof e.body=="string"?e.body:void 0,d=_e(e.ratelimit),a=Array.isArray(e.causes)?e.causes.flatMap(u=>{if(!F(u))return[];const f={...typeof u.message=="string"?{message:u.message}:{},...typeof u.status=="number"&&Number.isFinite(u.status)?{status:u.status}:{},...typeof u.code=="string"||typeof u.code=="number"?{code:u.code}:{},...typeof u.errno=="string"?{errno:u.errno}:{},...typeof u.body=="string"?{body:u.body}:{}};return Object.keys(f).length===0?[]:[f]}):void 0;return{provider:e.provider,model:e.model,...n===void 0?{}:{status:n},...t===void 0?{}:{code:t},...r===void 0?{}:{errno:r},...i===void 0?{}:{body:i},...a===void 0||a.length===0?{}:{causes:a},...d===void 0?{}:{ratelimit:d}}}o(K,"parseProviderError");function Y(e){try{const n=JSON.parse(e);if(!g(pe,n.link)||typeof n.op!="string"||n.op===""||!g(Ee,n.kind)||typeof n.message!="string"||typeof n.since!="string")return null;const t=j(n.operation_id);if(!F(n.retry)||!g(fe,n.retry.disposition)||n.retry.by!==void 0&&!g(ye,n.retry.by)||n.retry.attempt!==void 0&&typeof n.retry.attempt!="number"||n.retry.max!==void 0&&typeof n.retry.max!="number"||n.retry.nextAt!==void 0&&typeof n.retry.nextAt!="string"||n.anchorEntryId!==void 0&&(typeof n.anchorEntryId!="string"||n.anchorEntryId===""))return null;const r=n.providerError===void 0?void 0:K(n.providerError);return n.providerError!==void 0&&r===void 0?null:{link:n.link,op:n.op,kind:n.kind,retry:{disposition:n.retry.disposition,...n.retry.by===void 0?{}:{by:n.retry.by},...n.retry.attempt===void 0?{}:{attempt:n.retry.attempt},...n.retry.max===void 0?{}:{max:n.retry.max},...n.retry.nextAt===void 0?{}:{nextAt:n.retry.nextAt}},message:n.message,since:n.since,operation_id:t,...n.anchorEntryId===void 0?{}:{anchorEntryId:n.anchorEntryId},...r===void 0?{}:{providerError:r}}}catch{return null}}o(Y,"parseLegacyFault");function Le(e){const n=ae(e);try{return se(n)}catch{return n}}o(Le,"canonicalPath");function me(e){try{const n=JSON.parse(e);if(!g(Te,n.state)||typeof n.sessionFile!="string"||n.sessionFile==="")return null;const t=JSON.stringify(n.fault),r=Y(t);if(r===null||r.link!=="pi\u2192provider"||r.retry.disposition!=="auto"||r.retry.by!=="daemon")return null;const i=n.anchorEntryId;return i!==null&&typeof i!="string"||(r.anchorEntryId??null)!==i?null:{state:n.state,sessionFile:Le(n.sessionFile),fault:r}}catch{return null}}o(me,"parseLegacyEpisode");function G(e){return e!==void 0?j(e):$.current()??$.fresh(t=>t)}o(G,"resolveOperationId");function Se(e){return e.slice(0,le)}o(Se,"clampMessage");function R(e){return e.link==="pi\u2192provider"&&e.retry.disposition==="auto"&&e.retry.by==="daemon"?3:e.retry.disposition==="fatal"?2:1}o(R,"faultPriority");function V(e){return{link:e.link,op:e.op,kind:e.kind,message:e.message,since:e.since,operationId:e.operation_id,anchorEntryId:e.anchorEntryId??null,retryDisposition:e.retry.disposition,retryBy:e.retry.by??null,retryAttempt:e.retry.attempt??null,retryMax:e.retry.max??null,retryNextAt:e.retry.nextAt??null,providerError:e.providerError===void 0?null:JSON.stringify(e.providerError)}}o(V,"encodeFault");function H(e){const n=e.provider_error_json,t=typeof n=="string"?K(JSON.parse(n)):void 0;if(typeof n=="string"&&t===void 0)throw new Error(`invalid provider error on stored fault ${e.fault_id}`);const r={disposition:e.retry_disposition,...e.retry_by===null?{}:{by:e.retry_by},...e.retry_attempt===null?{}:{attempt:e.retry_attempt},...e.retry_max===null?{}:{max:e.retry_max},...e.retry_next_at===null?{}:{nextAt:e.retry_next_at}};return{faultId:e.fault_id,link:e.link,op:e.op,kind:e.kind,message:e.message,since:e.since,operation_id:e.operation_id,retry:r,...e.anchor_entry_id===null?{}:{anchorEntryId:e.anchor_entry_id},...t===void 0?{}:{providerError:t}}}o(H,"hydrateFault");function L(e,n){const t=ue(e,"SELECT * FROM node_faults WHERE node_id = ? AND active = 1").get(n);return t===void 0?null:H(t)}o(L,"activeFault");function Q(e){if(!g(B,e.link))throw new Error(`fault link is not durable: ${e.link}`);return{link:e.link,op:e.op,kind:e.kind,retry:e.retry,message:Se(e.message),since:e.since??c(),operation_id:G(e.operation_id),...typeof e.anchorEntryId=="string"&&e.anchorEntryId!==""?{anchorEntryId:e.anchorEntryId}:{},...e.providerError===void 0?{}:{providerError:e.providerError}}}o(Q,"storedFault");function q(e,n){X({level:n.retry.disposition==="fatal"?"error":"warn",event:"fault.recorded",operation_id:n.operation_id,node_id:e,error_class:w(n),fields:{link:n.link,op:n.op,kind:n.kind,retry:n.retry,message:n.message,...n.anchorEntryId===void 0?{}:{anchor_entry_id:n.anchorEntryId},...n.providerError===void 0?{}:{provider_error:n.providerError}}})}o(q,"emitRecordedFault");function W(e,n,t,r,i){const d=C(),a=V(t),u=c();return s(e,"INSERT INTO node_faults (fault_id, node_id, link, op, kind, message, since, operation_id, anchor_entry_id, retry_disposition, retry_by, retry_attempt, retry_max, retry_next_at, provider_error_json, active, episode_state, episode_binding_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(d,n,a.link,a.op,a.kind,a.message,a.since,a.operationId,a.anchorEntryId,a.retryDisposition,a.retryBy,a.retryAttempt,a.retryMax,a.retryNextAt,a.providerError,r?1:0,i?.state??null,i?.bindingId??null,u,u),{...t,faultId:d}}o(W,"insertFault");function z(e,n,t,r){const i=V(t);return s(e,"UPDATE node_faults SET link = ?, op = ?, kind = ?, message = ?, since = ?, operation_id = ?, anchor_entry_id = ?, retry_disposition = ?, retry_by = ?, retry_attempt = ?, retry_max = ?, retry_next_at = ?, provider_error_json = ?, episode_state = COALESCE(?, episode_state), episode_binding_id = COALESCE(?, episode_binding_id), updated_at = ? WHERE fault_id = ?").run(i.link,i.op,i.kind,i.message,i.since,i.operationId,i.anchorEntryId,i.retryDisposition,i.retryBy,i.retryAttempt,i.retryMax,i.retryNextAt,i.providerError,r?.state??null,r?.bindingId??null,c(),n),{...t,faultId:n}}o(z,"updateFault");function D(e,n){s(e,"DELETE FROM node_faults WHERE fault_id = ? AND active = 0 AND episode_state IS NULL").run(n)}o(D,"deleteIfUnretained");function Z(e,n,t,r){const i=L(e,n);if(i===null){const d=s(e,"SELECT fault_id, link, kind, since, operation_id FROM node_faults WHERE node_id = ? AND active = 0 AND episode_state IS NOT NULL").get(n);return d!==void 0&&d.link===t.link&&d.kind===t.kind&&d.since===t.since&&d.operation_id===t.operation_id?(s(e,"UPDATE node_faults SET active = 1, updated_at = ? WHERE fault_id = ?").run(c(),d.fault_id),z(e,d.fault_id,t)):W(e,n,t,!0,r)}if(i.link===t.link&&i.kind===t.kind){const d=t.retry.disposition==="auto"?{...i.retry,...t.retry}:t.retry,u=i.retry.disposition===t.retry.disposition&&(t.retry.disposition!=="fatal"||i.message===t.message)?i.since:t.since;return z(e,i.faultId,{...t,since:u,anchorEntryId:i.anchorEntryId??t.anchorEntryId,retry:d},r)}return i.link!==t.link&&R(i)>R(t)?null:(s(e,"UPDATE node_faults SET active = 0, updated_at = ? WHERE fault_id = ?").run(c(),i.faultId),D(e,i.faultId),W(e,n,t,!0,r))}o(Z,"replaceActiveFault");function m(e,n,t){return s(e,"SELECT binding_id FROM sessions WHERE node_id = ? AND session_id = ? AND unbound_at IS NULL").get(n,t)?.binding_id??null}o(m,"liveBinding");function Pe(e,n){return l(t=>{const r=c();return s(t,"UPDATE executions SET turn_progress_at = ? WHERE execution_id = ? AND state != 'exited' AND turn_open_at IS NOT NULL AND turn_closed_at IS NULL").run(r,e).changes>0?!0:s(t,"UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = NULL, turn_end_reason = NULL WHERE execution_id = ? AND state != 'exited'").run(r,r,e).changes>0})}o(Pe,"openTurn");function Me(e){return l(n=>s(n,"UPDATE executions SET turn_progress_at = ? WHERE execution_id = ? AND state != 'exited' AND turn_open_at IS NOT NULL AND turn_closed_at IS NULL").run(c(),e).changes>0)}o(Me,"recordTurnProgress");function we(e,n){return l(t=>{const r=c(),i=s(t,"UPDATE executions SET turn_closed_at = ?, turn_end_reason = ? WHERE execution_id = ? AND state != 'exited' AND turn_open_at IS NOT NULL AND turn_closed_at IS NULL").run(r,n.endReason,e).changes>0;if(i&&n.endReason==="settled"){const d="(SELECT node_id FROM executions WHERE execution_id = ?)";n.viewerPresent===!0?s(t,`UPDATE nodes SET reply_at = ?, read_at = ? WHERE node_id = ${d}`).run(r,r,e):s(t,`UPDATE nodes SET reply_at = ? WHERE node_id = ${d}`).run(r,e)}return i})}o(we,"closeTurn");function Xe(e){return l(n=>s(n,"UPDATE nodes SET read_at = ? WHERE node_id = ?").run(c(),e).changes>0)}o(Xe,"markNodeRead");function $e(e,n){if(!Number.isInteger(n.consecutivePasses)||n.consecutivePasses<1||n.routes.length===0||!n.routes.every(t=>t!==""))throw new Error("invalid transport-poison verdict");return l(t=>s(t,"UPDATE executions SET exit_diagnostic_json = ? WHERE execution_id = ? AND state != 'exited'").run(JSON.stringify({schema:"crtr.execution-exit-diagnostic/v1",transport_poison:{consecutive_passes:n.consecutivePasses,routes:n.routes}}),e).changes>0)}o($e,"recordTransportPoisonVerdict");function je(e){const n=s(E(),"SELECT exit_diagnostic_json FROM executions WHERE node_id = ? ORDER BY rowid DESC LIMIT 1").get(e);if(n===void 0||n.exit_diagnostic_json===null)return null;try{const t=JSON.parse(n.exit_diagnostic_json),r=t.transport_poison;return t.schema!=="crtr.execution-exit-diagnostic/v1"||r===void 0||!Number.isInteger(r.consecutive_passes)||r.consecutive_passes<1||!Array.isArray(r.routes)||r.routes.length===0||!r.routes.every(i=>typeof i=="string"&&i!=="")?null:{consecutivePasses:r.consecutive_passes,routes:r.routes}}catch{return null}}o(je,"readTransportPoisonVerdict");function Be(e){const n=s(E(),"SELECT turn_open_at, turn_closed_at, turn_progress_at FROM executions WHERE node_id = ? AND state != 'exited'").get(e);return n===void 0?null:{busy:n.turn_open_at!==null&&n.turn_closed_at===null,progressAt:n.turn_progress_at}}o(Be,"readLiveTurn");function Je(e){const n=E(),t=s(n,"SELECT turn_closed_at, turn_progress_at FROM executions WHERE node_id = ? AND turn_open_at IS NOT NULL ORDER BY rowid DESC LIMIT 1").get(e);if(t===void 0)return null;const r=s(n,"SELECT turn_end_reason FROM executions WHERE node_id = ? ORDER BY rowid DESC LIMIT 1").get(e);return{interrupted:t.turn_closed_at===null||r?.turn_end_reason==="teardown-aborted",progressAt:t.turn_progress_at}}o(Je,"readInterruptedTurn");function Ke(e){return s(E(),"SELECT 1 FROM executions WHERE node_id = ? AND turn_open_at IS NOT NULL LIMIT 1").get(e)!==void 0}o(Ke,"hasAdmittedTurn");function Ye(e,n){const t=Q(n);return q(e,t),l(r=>Z(r,e,t))}o(Ye,"recordFault");function Ge(e,n){const t=L(E(),e);return t===null||n?.link!==void 0&&t.link!==n.link?!1:l(r=>{const i=L(r,e);if(i===null||n?.link!==void 0&&i.link!==n.link)return!1;const d=s(r,"SELECT episode_state FROM node_faults WHERE fault_id = ?").get(i.faultId);s(r,"UPDATE node_faults SET active = 0, updated_at = ? WHERE fault_id = ?").run(c(),i.faultId),d.episode_state==="pending"&&n?.preserveEpisode!==!0&&s(r,"UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE fault_id = ?").run(c(),i.faultId),D(r,i.faultId);const a=G();return X({level:"info",event:"fault.cleared",operation_id:a,node_id:e,error_class:w(i),fields:{cleared_fault_operation_id:i.operation_id,link:i.link,op:i.op,kind:i.kind,retry:i.retry,message:i.message,since:i.since,...i.anchorEntryId===void 0?{}:{anchor_entry_id:i.anchorEntryId}}}),!0})}o(Ge,"clearFault");function ee(e){return L(E(),e)}o(ee,"readFault");function Ve(e,n){const t=Q(n.input);if(t.link!=="pi\u2192provider"||t.retry.disposition!=="auto"||t.retry.by!=="daemon")throw new Error("provider retry episode requires an automatic daemon provider fault");return q(e,t),l(r=>{const i=m(r,e,n.sessionId);if(i===null)return null;const d=L(r,e);if(d!==null&&(d.link!==t.link||d.kind!==t.kind)&&R(d)>R(t))return null;const a=s(r,"SELECT fault_id FROM node_faults WHERE node_id = ? AND episode_state IS NOT NULL").all(e);s(r,"UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE node_id = ? AND episode_state IS NOT NULL").run(c(),e);for(const f of a)D(r,f.fault_id);const u=Z(r,e,t,{state:"pending",bindingId:i});return u===null?null:(s(r,"UPDATE node_faults SET episode_state = ?, episode_binding_id = ?, updated_at = ? WHERE fault_id = ?").run("pending",i,c(),u.faultId),u)})}o(Ve,"recordPendingEpisode");function Qe(e,n){return l(t=>{if(s(t,"SELECT 1 FROM nodes WHERE node_id = ? AND intent IS 'refresh'").get(e)!==void 0)return!1;const r=m(t,e,n.sessionId);return r===null?!1:s(t,"UPDATE node_faults SET episode_state = 'admitted', retry_disposition = ?, retry_by = ?, retry_attempt = ?, retry_max = ?, retry_next_at = ?, updated_at = ? WHERE node_id = ? AND fault_id = ? AND episode_state = 'pending' AND episode_binding_id = ?").run(n.retry.disposition,n.retry.by??null,n.retry.attempt??null,n.retry.max??null,n.retry.nextAt??null,c(),e,n.faultId,r).changes>0})}o(Qe,"admitEpisode");function qe(e,n){return l(t=>{const r=m(t,e,n.sessionId);return r===null?!1:s(t,"UPDATE node_faults SET episode_state = 'pending', updated_at = ? WHERE node_id = ? AND episode_state = 'admitted' AND episode_binding_id = ?").run(c(),e,r).changes>0})}o(qe,"reopenEpisode");function ze(e,n){return l(t=>{const r=m(t,e,n.sessionId);return r===null?!1:s(t,"UPDATE node_faults SET episode_state = 'invalidated', updated_at = ? WHERE node_id = ? AND episode_state != 'invalidated' AND episode_state IS NOT NULL AND episode_binding_id = ?").run(c(),e,r).changes>0})}o(ze,"invalidateEpisode");function Ze(e,n){return l(t=>{const r=m(t,e,n.sessionId);if(r===null)return!1;const i=s(t,"SELECT fault_id FROM node_faults WHERE node_id = ? AND episode_binding_id = ? AND episode_state IS NOT NULL").all(e,r);if(i.length===0)return!1;s(t,"UPDATE node_faults SET episode_state = NULL, episode_binding_id = NULL, updated_at = ? WHERE node_id = ? AND episode_binding_id = ? AND episode_state IS NOT NULL").run(c(),e,r);for(const d of i)D(t,d.fault_id);return!0})}o(Ze,"clearEpisode");function en(e){const n=s(E(),"SELECT f.*, s.session_id FROM node_faults f JOIN sessions s ON s.binding_id = f.episode_binding_id WHERE f.node_id = ? AND f.episode_state IS NOT NULL").get(e);return n===void 0?null:{state:n.episode_state,sessionId:n.session_id,fault:H(n)}}o(en,"readEpisode");function nn(){return s(E(),"SELECT f.*, s.session_id AS bound_session_id FROM node_faults f JOIN sessions s ON s.binding_id = f.episode_binding_id WHERE f.active = 1 AND f.episode_state = 'pending' AND s.unbound_at IS NULL AND s.session_id IS NOT NULL AND f.link = 'pi\u2192provider' AND f.retry_disposition = 'auto' AND f.retry_by = 'daemon' AND f.kind IN ('connection', 'rate-limit', 'overloaded')").all().map(n=>({nodeId:n.node_id,sessionId:n.bound_session_id,fault:H(n),updatedAt:n.updated_at}))}o(nn,"listPendingProviderRetries");function tn(e){const n=ee(e)===null;return{explanation(){if(!n)return null;const t=ee(e);if(t===null||t.link!=="crtr\u2192pi"||t.retry.disposition!=="fatal")return null;const r=t.op.trim(),i=t.message.trim();return r===""||i===""?null:`${r}: ${i}`}}}o(tn,"beginBootFaultAttempt");function ne(e,n){try{return de(e).mtime.toISOString()}catch{return n}}o(ne,"markerMtime");function P(e,n){if(!p(e))return null;try{return oe(e,"utf8")}catch(t){if(!n)return null;throw new Error(`cannot import recovery input ${e}: ${t.message}`)}}o(P,"legacyFile");function Ae(e,n){return s(e,"SELECT execution_id, started_at FROM executions WHERE node_id = ? ORDER BY rowid DESC LIMIT 1").get(n)??null}o(Ae,"latestExecution");function xe(e,n){const r=J(e,"nodes").has("launched_at")?s(e,"SELECT COALESCE(launched_at, created) AS started_at FROM nodes WHERE node_id = ?").get(n):s(e,"SELECT created AS started_at FROM nodes WHERE node_id = ?").get(n);if(r===void 0)throw new Error(`cannot import recovery witness for unknown node ${n}`);const i=C();return s(e,"INSERT INTO executions (execution_id, node_id, daemon_epoch, pid, process_identity, state, started_at, ended_at, exit_reason) VALUES (?, ?, NULL, NULL, NULL, 'exited', ?, ?, 'pre-consolidation')").run(i,n,r.started_at,r.started_at),{execution_id:i,started_at:r.started_at}}o(xe,"syntheticExecution");function te(e,n,t,r,i){return W(e,n,t,r,i)}o(te,"insertMigratedFault");function Ie(e,n,t,r){const i=s(e,"SELECT binding_id, node_id FROM sessions WHERE transcript_path = ? AND unbound_at IS NULL").get(t);if(i!==void 0){if(i.node_id!==n)throw new Error(`cannot import provider retry ${r}: transcript is live-owned by ${i.node_id}`);return i.binding_id}const d=s(e,"SELECT binding_id FROM sessions WHERE node_id = ? AND transcript_path = ? ORDER BY rowid DESC LIMIT 1").get(n,t);if(d!==void 0)return d.binding_id;const a=s(e,"SELECT created FROM nodes WHERE node_id = ?").get(n);if(a===void 0)throw new Error(`cannot import provider retry ${r}: unknown node ${n}`);const u=C();return s(e,"INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at, unbound_at) VALUES (?, NULL, ?, ?, NULL, NULL, ?, ?, ?)").run(u,n,t,a.created,a.created,c()),u}o(Ie,"migrationBinding");function rn(e){if(Ne(e),ge(e),!p(b()))return;const n=ie(b(),{withFileTypes:!0}).filter(r=>r.isDirectory()).sort((r,i)=>r.name.localeCompare(i.name)),t=s(e,"SELECT 1 FROM nodes WHERE node_id = ?");for(const r of n){const i=r.name,d=ce(i),a=N(d,"busy"),u=N(d,"clean-abort"),f=N(d,"transport-poison.json"),h=N(d,"fault"),S=N(d,"provider-retry"),O=p(a),U=p(u);if(!O&&!U&&!p(f)&&!p(h)&&!p(S)||!p(N(b(),i,"meta.json"))&&t.get(i)===void 0)continue;const k=P(f,!1),A=P(h,!0),x=P(S,!0);if(!O&&!U&&k===null&&A===null&&x===null)continue;let y=Ae(e,i);if(y===null&&(y=xe(e,i)),O){const _=ne(a,y.started_at);s(e,"UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = NULL, turn_end_reason = NULL WHERE execution_id = ?").run(_,_,y.execution_id)}else if(U){const _=ne(u,y.started_at);s(e,"UPDATE executions SET turn_open_at = ?, turn_progress_at = ?, turn_closed_at = ?, turn_end_reason = 'teardown-aborted' WHERE execution_id = ?").run(_,_,_,y.execution_id)}if(k!==null)try{const _=JSON.parse(k);Number.isInteger(_.consecutivePasses)&&_.consecutivePasses>=1&&Array.isArray(_.routes)&&_.routes.length>0&&_.routes.every(M=>typeof M=="string"&&M!=="")&&s(e,"UPDATE executions SET exit_diagnostic_json = ? WHERE execution_id = ?").run(JSON.stringify({schema:"crtr.execution-exit-diagnostic/v1",transport_poison:{consecutive_passes:_.consecutivePasses,routes:_.routes}}),y.execution_id)}catch{}const I=A===null?null:Y(A);if(A!==null&&I===null)throw new Error(`cannot import recovery fault ${h}`);const T=x===null?null:me(x);if(x!==null&&T===null)throw new Error(`cannot import provider retry ${S}`);let v=I===null||I.link==="broker\u2194crtrd"?null:te(e,i,I,!0);if(T!==null){const _=Ie(e,i,T.sessionFile,S);v!==null&&v.since===T.fault.since?s(e,"UPDATE node_faults SET episode_state = ?, episode_binding_id = ?, updated_at = ? WHERE fault_id = ?").run(T.state,_,c(),v.faultId):te(e,i,T.fault,!1,{state:T.state,bindingId:_})}}}o(rn,"migrateRecoveryWitnesses");export{We as FAULT_QUIET_MS,Qe as admitEpisode,tn as beginBootFaultAttempt,Ze as clearEpisode,Ge as clearFault,we as closeTurn,Ke as hasAdmittedTurn,H as hydrateFault,ze as invalidateEpisode,nn as listPendingProviderRetries,Xe as markNodeRead,rn as migrateRecoveryWitnesses,Pe as openTurn,K as parseProviderError,en as readEpisode,ee as readFault,Je as readInterruptedTurn,Be as readLiveTurn,je as readTransportPoisonVerdict,Ye as recordFault,Ve as recordPendingEpisode,$e as recordTransportPoisonVerdict,Me as recordTurnProgress,qe as reopenEpisode};
@@ -1,2 +1,2 @@
1
- import type { ConversationStore } from './index.js';
2
- export declare function createStoreClient(address: string, token?: string): ConversationStore;
1
+ import type { ConversationStoreClient } from './index.js';
2
+ export declare function createStoreClient(address: string, token?: string): ConversationStoreClient;
@@ -18,7 +18,10 @@ export interface ConversationWindow {
18
18
  head: number;
19
19
  tail: number;
20
20
  }
21
- export interface ConversationStore {
21
+ /** The synchronous shape pi's `SessionManager` statics need (`patch.ts`). The broker's client
22
+ * (`client.ts`: an `Atomics.wait` worker, no db) implements it. It is declared apart from
23
+ * `ConversationStore` so a change to the daemon's store never changes pi's contract. */
24
+ export interface ConversationStoreClient {
22
25
  create(nodeId: string, header: SessionHeader, entries: SessionEntry[], path?: string): string;
23
26
  /** `dedupe` makes the append idempotent by entry id: an entry already in the file is skipped.
24
27
  * A caller sets it when an earlier attempt failed ambiguously (the connection ended before a
@@ -38,7 +41,30 @@ export interface ConversationStore {
38
41
  };
39
42
  /** `read` without blocking the calling thread. Stores that read in-process may omit it;
40
43
  * use `readConversationAsync`, which falls back to `read`. */
41
- readAsync?(id: string, window?: ConversationWindow): Promise<ReturnType<ConversationStore['read']>>;
44
+ readAsync?(id: string, window?: ConversationWindow): Promise<ReturnType<ConversationStoreClient['read']>>;
45
+ header(id: string): {
46
+ header: SessionHeader;
47
+ mtime: number;
48
+ size: number;
49
+ path: string;
50
+ };
51
+ fork(id: string, nodeId?: string, leafId?: string, cwd?: string): string;
52
+ list(nodeId?: string): ConversationInfo[];
53
+ delete(id: string): void;
54
+ }
55
+ /** The daemon's file store (`createFileStore`, installed by `sessions.ts`). */
56
+ export interface ConversationStore {
57
+ create(nodeId: string, header: SessionHeader, entries: SessionEntry[], path?: string): string;
58
+ append(id: string, entries: SessionEntry[], options?: {
59
+ dedupe?: boolean;
60
+ }): void;
61
+ replace(id: string, header: SessionHeader, entries: SessionEntry[]): void;
62
+ read(id: string, window?: ConversationWindow): {
63
+ header: SessionHeader;
64
+ entries: SessionEntry[];
65
+ tail?: SessionEntry[];
66
+ path: string;
67
+ };
42
68
  /** Stream a complete conversation without blocking the daemon on a full-file read. */
43
69
  readLines?(id: string): {
44
70
  path: string;
@@ -59,6 +85,8 @@ export declare function defaultConversationRoot(): string;
59
85
  export declare function storeAddress(): string;
60
86
  export declare function installConversationStore(store: ConversationStore | undefined): void;
61
87
  export declare function conversationStore(): ConversationStore;
88
+ /** The synchronous store pi's `SessionManager` statics call: the installed store, else the client over the store socket. */
89
+ export declare function conversationClient(): ConversationStoreClient;
62
90
  /** Read a conversation without parking the event loop on the store worker. */
63
91
  export declare function readConversationAsync(id: string, window?: ConversationWindow): Promise<ReturnType<ConversationStore['read']>>;
64
92
  export { createFileStore, sessionDirectory, type AppendSection, type ConversationCanvas, type ConversationWrite } from './file-store.js';
@@ -1 +1 @@
1
- var a=Object.defineProperty;var r=(o,e)=>a(o,"name",{value:e,configurable:!0});import{appsRoot as i,socketDir as c}from"../layout.js";import{join as u}from"node:path";import{createStoreClient as f}from"./client.js";import{currentNodeToken as p}from"../runtime/broker/node-token.js";class d extends Error{static{r(this,"ConversationNotFoundError")}code="not_found";constructor(e){super(`conversation not found: ${e}`)}}function R(o){return o instanceof d}r(R,"isConversationNotFound");function y(o){return/(?:^|\/)[^/]+_([0-9a-f-]{36})\.jsonl$/i.exec(o)?.[1]??null}r(y,"conversationIdFromPath");function A(){return i()}r(A,"defaultConversationRoot");function l(){return process.env.CRTR_STORE_ADDRESS||u(c(),"store.sock")}r(l,"storeAddress");let n,s;function F(o){n=o}r(F,"installConversationStore");function m(){if(n)return n;const o=l();return s?.address!==o&&(s={address:o,store:f(o,p())}),s.store}r(m,"conversationStore");async function k(o,e){const t=m();return t.readAsync?t.readAsync(o,e):t.read(o,e)}r(k,"readConversationAsync");import{createFileStore as P,sessionDirectory as _}from"./file-store.js";import{installSessionManagerStorePatch as O}from"./patch.js";import{findOrphanedParents as j,relinkOrphanedParents as $,repairConversationFile as g}from"./repair.js";export{d as ConversationNotFoundError,y as conversationIdFromPath,m as conversationStore,P as createFileStore,A as defaultConversationRoot,j as findOrphanedParents,F as installConversationStore,O as installSessionManagerStorePatch,R as isConversationNotFound,k as readConversationAsync,$ as relinkOrphanedParents,g as repairConversationFile,_ as sessionDirectory,l as storeAddress};
1
+ var a=Object.defineProperty;var r=(o,t)=>a(o,"name",{value:t,configurable:!0});import{appsRoot as c,socketDir as u}from"../layout.js";import{join as f}from"node:path";import{createStoreClient as p}from"./client.js";import{currentNodeToken as d}from"../runtime/broker/node-token.js";class l extends Error{static{r(this,"ConversationNotFoundError")}code="not_found";constructor(t){super(`conversation not found: ${t}`)}}function R(o){return o instanceof l}r(R,"isConversationNotFound");function y(o){return/(?:^|\/)[^/]+_([0-9a-f-]{36})\.jsonl$/i.exec(o)?.[1]??null}r(y,"conversationIdFromPath");function A(){return c()}r(A,"defaultConversationRoot");function m(){return process.env.CRTR_STORE_ADDRESS||f(u(),"store.sock")}r(m,"storeAddress");let n,s;function F(o){n=o}r(F,"installConversationStore");function k(){return i()}r(k,"conversationStore");function i(){if(n)return n;const o=m();return s?.address!==o&&(s={address:o,store:p(o,d())}),s.store}r(i,"conversationClient");async function D(o,t){const e=i();return e.readAsync?e.readAsync(o,t):e.read(o,t)}r(D,"readConversationAsync");import{createFileStore as _,sessionDirectory as N}from"./file-store.js";import{installSessionManagerStorePatch as T}from"./patch.js";import{findOrphanedParents as $,relinkOrphanedParents as g,repairConversationFile as I}from"./repair.js";export{l as ConversationNotFoundError,i as conversationClient,y as conversationIdFromPath,k as conversationStore,_ as createFileStore,A as defaultConversationRoot,$ as findOrphanedParents,F as installConversationStore,T as installSessionManagerStorePatch,R as isConversationNotFound,D as readConversationAsync,g as relinkOrphanedParents,I as repairConversationFile,N as sessionDirectory,m as storeAddress};
@@ -1 +1 @@
1
- var P=Object.defineProperty;var h=(a,c)=>P(a,"name",{value:c,configurable:!0});import{dirname as E,resolve as A}from"node:path";import{SessionManager as w}from"@earendil-works/pi-coding-agent";import{conversationIdFromPath as R,conversationStore as O}from"./index.js";import{findOrphanedParents as T}from"./repair.js";import{emitEvent as I}from"../events/emit.js";const f=new WeakMap;function k(a){a>0&&Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,a)}h(k,"sleep");function C(){const a=Number(process.env.CRTR_CONVERSATION_APPEND_RETRY_MS);return Number.isFinite(a)&&a>=0?a:500}h(C,"retryDelayMs");let x=!1;function z(a){if(x)return;const c=w.prototype,d=w;for(const e of["_setSessionFile","_rewriteFile","_persist","createBranchedSession","newSession"])if(typeof c[e]!="function")throw new Error(`pi SessionManager.${e} changed; store patch cannot start`);for(const e of["create","open","continueRecent","forkFrom","findById","list","listAll"])if(typeof d[e]!="function")throw new Error(`pi SessionManager.${e} changed; store patch cannot start`);const M=c.createBranchedSession,y=c.newSession,o=O();function N(e,s){const t=T(s);t.length!==0&&I({level:"error",event:"conversation.orphaned_parent",fields:{conversation_id:e,orphan_count:t.length,orphans:t.slice(0,20).map(i=>({entry_id:i.entryId,missing_parent_id:i.missingParentId}))}})}h(N,"reportOrphans");function _(e,s){const{header:t,entries:i,path:r}=o.read(e);N(t.id,i);const n=w.inMemory(s??t.cwd);n.sessionFile=r,n.sessionDir=E(r),n._loadEntries([t,...i]),n.persist=!0,n.flushed=!0;const u=n.fileEntries[0];return u?.type==="session"&&u.version!==t.version&&n._rewriteFile(),n}h(_,"fromStore");function m(e){const[s,...t]=e.fileEntries;if(!s||s.type!=="session")throw new Error("conversation has no session header");o.create(a,s,t),e.sessionFile=o.header(s.id).path,e.sessionDir=E(e.sessionFile),e.flushed=!0,f.delete(e)}h(m,"persistNew");function B(e,s){const t=f.get(e)??{entries:[],ambiguous:!1};t.entries.push(s),f.set(e,t);let i;for(let r=0;r<2;r++){r>0&&k(C());try{o.append(e.sessionId,t.entries,t.ambiguous?{dedupe:!0}:void 0),f.delete(e);return}catch(n){i=n,t.ambiguous=!0}}throw I({level:"error",event:"conversation.append_failed",error:i,fields:{conversation_id:e.sessionId,pending_entries:t.entries.length}}),i}h(B,"appendInOrder");function g(e){const s=R(e);if(!s)throw new Error(`invalid conversation path: ${e}`);return s}h(g,"idOf"),c._setSessionFile=function(e){const{header:s,entries:t}=o.read(g(e));this.sessionFile=o.header(s.id).path,this.sessionDir=E(this.sessionFile),N(s.id,t),this._loadEntries([s,...t]),this.flushed=!0,f.delete(this)},c._rewriteFile=function(){if(!this.persist||!this.sessionFile)return;const[e,...s]=this.fileEntries;if(!e||e.type!=="session")throw new Error("conversation has no session header");o.replace(e.id,e,s),f.delete(this)},c._persist=function(e){!this.persist||!this.sessionFile||(this.flushed?B(this,e):m(this))},c.newSession=function(e){if(!this.persist)return y.call(this,e);const s=this.flushed&&this.fileEntries.length===1&&this.sessionFile!==void 0?this.sessionId:void 0;if(s!==void 0&&(e?.id===void 0||e.id===s)){const t=this.sessionFile;y.call(this,{...e,id:s});const i=this.fileEntries[0];if(!i||i.type!=="session")throw new Error("conversation has no session header");return o.replace(s,i,[]),this.sessionFile=t,this.flushed=!0,t}return y.call(this,e),m(this),this.sessionFile},c.createBranchedSession=function(e){if(!this.persist)return M.call(this,e);const s=this.sessionFile;this.persist=!1;try{M.call(this,e)}finally{this.persist=!0}const t=this.fileEntries[0];if(!t||t.type!=="session")throw new Error("branch has no header");return this.fileEntries[0]={...t,parentSession:s},m(this),this.sessionFile},d.create=(e,s,t)=>{const i=w.inMemory(e,t);return i.persist=!0,m(i),i},d.open=(e,s,t)=>_(g(e),t),d.continueRecent=e=>{const s=o.list().find(t=>t.header.cwd===A(e));return s?_(s.conversation_id,e):d.create(e)},d.forkFrom=(e,s)=>_(o.fork(g(e),a,void 0,s)),d.findById=(e,s)=>o.list().find(t=>t.conversation_id===s&&t.header.cwd===A(e))?.path;function b(e){return o.list().filter(s=>e===void 0||s.header.cwd===A(e)).map(s=>{let t,i=0,r="",n;const u=[];for(const p of o.read(s.conversation_id).entries){if(p.type==="session_info"&&(t=p.name?.trim()||void 0),p.type!=="message")continue;i++;const l=p.message;if(l.role!=="user"&&l.role!=="assistant")continue;const D=typeof l.timestamp=="number"?l.timestamp:Date.parse(p.timestamp);Number.isNaN(D)||(n=Math.max(n??0,D));const S=typeof l.content=="string"?l.content:Array.isArray(l.content)?l.content.filter(F=>F.type==="text").map(F=>F.text??"").join(" "):"";S&&(u.push(S),!r&&l.role==="user"&&(r=S))}const v=new Date(s.header.timestamp);return{path:s.path,id:s.conversation_id,cwd:s.header.cwd,...t?{name:t}:{},...s.header.parentSession?{parentSessionPath:s.header.parentSession}:{},created:v,modified:n&&n>0?new Date(n):Number.isNaN(v.getTime())?new Date(s.mtime):v,messageCount:i,firstMessage:r||"(no messages)",allMessagesText:u.join(" ")}})}h(b,"sessionInfos"),d.list=async(e,s,t,i)=>{i?.throwIfAborted();const r=b(e);return t?.(r.length,r.length,r),r},d.listAll=async(...e)=>(e.find(t=>t instanceof AbortSignal)?.throwIfAborted(),b()),x=!0}h(z,"installSessionManagerStorePatch");export{z as installSessionManagerStorePatch};
1
+ var P=Object.defineProperty;var h=(a,c)=>P(a,"name",{value:c,configurable:!0});import{dirname as E,resolve as A}from"node:path";import{SessionManager as w}from"@earendil-works/pi-coding-agent";import{conversationClient as R,conversationIdFromPath as O}from"./index.js";import{findOrphanedParents as T}from"./repair.js";import{emitEvent as I}from"../events/emit.js";const f=new WeakMap;function k(a){a>0&&Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,a)}h(k,"sleep");function C(){const a=Number(process.env.CRTR_CONVERSATION_APPEND_RETRY_MS);return Number.isFinite(a)&&a>=0?a:500}h(C,"retryDelayMs");let x=!1;function z(a){if(x)return;const c=w.prototype,d=w;for(const e of["_setSessionFile","_rewriteFile","_persist","createBranchedSession","newSession"])if(typeof c[e]!="function")throw new Error(`pi SessionManager.${e} changed; store patch cannot start`);for(const e of["create","open","continueRecent","forkFrom","findById","list","listAll"])if(typeof d[e]!="function")throw new Error(`pi SessionManager.${e} changed; store patch cannot start`);const M=c.createBranchedSession,y=c.newSession,o=R();function N(e,s){const t=T(s);t.length!==0&&I({level:"error",event:"conversation.orphaned_parent",fields:{conversation_id:e,orphan_count:t.length,orphans:t.slice(0,20).map(i=>({entry_id:i.entryId,missing_parent_id:i.missingParentId}))}})}h(N,"reportOrphans");function _(e,s){const{header:t,entries:i,path:r}=o.read(e);N(t.id,i);const n=w.inMemory(s??t.cwd);n.sessionFile=r,n.sessionDir=E(r),n._loadEntries([t,...i]),n.persist=!0,n.flushed=!0;const u=n.fileEntries[0];return u?.type==="session"&&u.version!==t.version&&n._rewriteFile(),n}h(_,"fromStore");function m(e){const[s,...t]=e.fileEntries;if(!s||s.type!=="session")throw new Error("conversation has no session header");o.create(a,s,t),e.sessionFile=o.header(s.id).path,e.sessionDir=E(e.sessionFile),e.flushed=!0,f.delete(e)}h(m,"persistNew");function B(e,s){const t=f.get(e)??{entries:[],ambiguous:!1};t.entries.push(s),f.set(e,t);let i;for(let r=0;r<2;r++){r>0&&k(C());try{o.append(e.sessionId,t.entries,t.ambiguous?{dedupe:!0}:void 0),f.delete(e);return}catch(n){i=n,t.ambiguous=!0}}throw I({level:"error",event:"conversation.append_failed",error:i,fields:{conversation_id:e.sessionId,pending_entries:t.entries.length}}),i}h(B,"appendInOrder");function g(e){const s=O(e);if(!s)throw new Error(`invalid conversation path: ${e}`);return s}h(g,"idOf"),c._setSessionFile=function(e){const{header:s,entries:t}=o.read(g(e));this.sessionFile=o.header(s.id).path,this.sessionDir=E(this.sessionFile),N(s.id,t),this._loadEntries([s,...t]),this.flushed=!0,f.delete(this)},c._rewriteFile=function(){if(!this.persist||!this.sessionFile)return;const[e,...s]=this.fileEntries;if(!e||e.type!=="session")throw new Error("conversation has no session header");o.replace(e.id,e,s),f.delete(this)},c._persist=function(e){!this.persist||!this.sessionFile||(this.flushed?B(this,e):m(this))},c.newSession=function(e){if(!this.persist)return y.call(this,e);const s=this.flushed&&this.fileEntries.length===1&&this.sessionFile!==void 0?this.sessionId:void 0;if(s!==void 0&&(e?.id===void 0||e.id===s)){const t=this.sessionFile;y.call(this,{...e,id:s});const i=this.fileEntries[0];if(!i||i.type!=="session")throw new Error("conversation has no session header");return o.replace(s,i,[]),this.sessionFile=t,this.flushed=!0,t}return y.call(this,e),m(this),this.sessionFile},c.createBranchedSession=function(e){if(!this.persist)return M.call(this,e);const s=this.sessionFile;this.persist=!1;try{M.call(this,e)}finally{this.persist=!0}const t=this.fileEntries[0];if(!t||t.type!=="session")throw new Error("branch has no header");return this.fileEntries[0]={...t,parentSession:s},m(this),this.sessionFile},d.create=(e,s,t)=>{const i=w.inMemory(e,t);return i.persist=!0,m(i),i},d.open=(e,s,t)=>_(g(e),t),d.continueRecent=e=>{const s=o.list().find(t=>t.header.cwd===A(e));return s?_(s.conversation_id,e):d.create(e)},d.forkFrom=(e,s)=>_(o.fork(g(e),a,void 0,s)),d.findById=(e,s)=>o.list().find(t=>t.conversation_id===s&&t.header.cwd===A(e))?.path;function b(e){return o.list().filter(s=>e===void 0||s.header.cwd===A(e)).map(s=>{let t,i=0,r="",n;const u=[];for(const p of o.read(s.conversation_id).entries){if(p.type==="session_info"&&(t=p.name?.trim()||void 0),p.type!=="message")continue;i++;const l=p.message;if(l.role!=="user"&&l.role!=="assistant")continue;const D=typeof l.timestamp=="number"?l.timestamp:Date.parse(p.timestamp);Number.isNaN(D)||(n=Math.max(n??0,D));const F=typeof l.content=="string"?l.content:Array.isArray(l.content)?l.content.filter(S=>S.type==="text").map(S=>S.text??"").join(" "):"";F&&(u.push(F),!r&&l.role==="user"&&(r=F))}const v=new Date(s.header.timestamp);return{path:s.path,id:s.conversation_id,cwd:s.header.cwd,...t?{name:t}:{},...s.header.parentSession?{parentSessionPath:s.header.parentSession}:{},created:v,modified:n&&n>0?new Date(n):Number.isNaN(v.getTime())?new Date(s.mtime):v,messageCount:i,firstMessage:r||"(no messages)",allMessagesText:u.join(" ")}})}h(b,"sessionInfos"),d.list=async(e,s,t,i)=>{i?.throwIfAborted();const r=b(e);return t?.(r.length,r.length,r),r},d.listAll=async(...e)=>(e.find(t=>t instanceof AbortSignal)?.throwIfAborted(),b()),x=!0}h(z,"installSessionManagerStorePatch");export{z as installSessionManagerStorePatch};
@@ -55,6 +55,8 @@ export declare function endMessageSubscriptions(db: DatabaseSync, object: Object
55
55
  export declare function watchesOf(db: DatabaseSync, reader: Reader, watcher: ObjectRow): Watch[];
56
56
  /** The watches held on `object` that the reader may see (both ends readable). */
57
57
  export declare function watchersOf(db: DatabaseSync, reader: Reader, object: ObjectRow): Watch[];
58
+ /** The ids of every object that watches `object`, whatever started the watch. */
59
+ export declare function watcherIdsOf(db: DatabaseSync, object: ObjectRow): string[];
58
60
  /** Every node below `root` in the tree (in-tree watches, watcher → object), each once. */
59
61
  export declare function descendants(db: DatabaseSync, root: ObjectRow): ObjectRow[];
60
62
  /** Every node above `leaf` in the tree (in-tree watches, object → watcher), each once. */
@@ -1,19 +1,19 @@
1
- var D=Object.defineProperty;var c=(e,t)=>D(e,"name",{value:t,configurable:!0});import{prepared as i}from"../sqlite-statements.js";import{canRead as O}from"./access.js";import{receiverForObject as j}from"./receivers.js";import{getByRowid as S}from"./objects.js";const p=["spawn","job-start","ask"],y=["report.final","report.result","notice.>"];function N(e){return JSON.stringify(Object.fromEntries(e.map(t=>[String(t.threshold),t.delivery])))}c(N,"configToJson");function I(e){const t=JSON.parse(e);return Object.entries(t).map(([o,r])=>({threshold:Number(o),delivery:r})).sort((o,r)=>r.threshold-o.threshold)}c(I,"configFromJson");function _(e,t,o){return i(e,"SELECT * FROM watches WHERE watcher = ? AND object = ?").get(t.rowid,o.rowid)}c(_,"watchRow");function d(e,t){return i(e,"SELECT * FROM watch_subscriptions WHERE watch = ? ORDER BY rowid").all(t)}c(d,"subsOf");function h(e,t){const o=d(e,t);if(o.length===0){i(e,"DELETE FROM watches WHERE rowid = ?").run(t);return}const r=o.some(n=>p.includes(n.started_by))?1:0;i(e,"UPDATE watches SET in_tree = ? WHERE rowid = ? AND in_tree != ?").run(r,t,r)}c(h,"settle");function g(e,t){return e==="message"?y:t.patterns?.length?t.patterns:[">"]}c(g,"defaultPatterns");function F(e,t,o,r,n={}){if(r==="fork")throw new Error("recordWatch: fork watches are made by copyWatchesForFork");if(t.type.includes(".")&&!j(e,t))throw new Error(`custom object ${t.id} has no receiver`);const a=new Date().toISOString();i(e,`INSERT INTO watches (watcher, object, in_tree, read_heads_key, created_at, link_app) VALUES (?, ?, 0, ?, ?, ?)
1
+ var D=Object.defineProperty;var c=(e,t)=>D(e,"name",{value:t,configurable:!0});import{prepared as i}from"../sqlite-statements.js";import{canRead as p}from"./access.js";import{receiverForObject as j}from"./receivers.js";import{getByRowid as S}from"./objects.js";const O=["spawn","job-start","ask"],y=["report.final","report.result","notice.>"];function N(e){return JSON.stringify(Object.fromEntries(e.map(t=>[String(t.threshold),t.delivery])))}c(N,"configToJson");function I(e){const t=JSON.parse(e);return Object.entries(t).map(([r,o])=>({threshold:Number(r),delivery:o})).sort((r,o)=>o.threshold-r.threshold)}c(I,"configFromJson");function h(e,t,r){return i(e,"SELECT * FROM watches WHERE watcher = ? AND object = ?").get(t.rowid,r.rowid)}c(h,"watchRow");function d(e,t){return i(e,"SELECT * FROM watch_subscriptions WHERE watch = ? ORDER BY rowid").all(t)}c(d,"subsOf");function _(e,t){const r=d(e,t);if(r.length===0){i(e,"DELETE FROM watches WHERE rowid = ?").run(t);return}const o=r.some(n=>O.includes(n.started_by))?1:0;i(e,"UPDATE watches SET in_tree = ? WHERE rowid = ? AND in_tree != ?").run(o,t,o)}c(_,"settle");function C(e,t){return e==="message"?y:t.patterns?.length?t.patterns:[">"]}c(C,"defaultPatterns");function F(e,t,r,o,n={}){if(o==="fork")throw new Error("recordWatch: fork watches are made by copyWatchesForFork");if(t.type.includes(".")&&!j(e,t))throw new Error(`custom object ${t.id} has no receiver`);const a=new Date().toISOString();i(e,`INSERT INTO watches (watcher, object, in_tree, read_heads_key, created_at, link_app) VALUES (?, ?, 0, ?, ?, ?)
2
2
  ON CONFLICT (watcher, object) DO UPDATE SET read_heads_key = COALESCE(excluded.read_heads_key, read_heads_key),
3
- link_app = COALESCE(excluded.link_app, link_app)`).run(t.rowid,o.rowid,n.readHeadsKey??null,a,n.linkApp?.rowid??null);const s=_(e,t,o),E=r==="message"?n.endsOn??"final":null,f=p.includes(r),w=d(e,s.rowid),u=i(e,`INSERT INTO watch_subscriptions (watch, pattern, filter_json, config_json, started_by, ends_on, created_at)
4
- VALUES (?, ?, ?, ?, ?, ?, ?)`);for(const R of g(r,n))w.some(l=>l.pattern===R&&(l.ends_on===null||l.ends_on===E)&&(!f||p.includes(l.started_by)))||u.run(s.rowid,R,n.filter===void 0?null:JSON.stringify(n.filter),n.config?N(n.config):null,r,E,a);h(e,s.rowid)}c(F,"recordWatch");function H(e,t,o,r){i(e,"UPDATE watches SET link_app = ? WHERE watcher = ? AND object = ?").run(r.rowid,t.rowid,o.rowid)}c(H,"markLinkWatch");function M(e,t,o,r){const n=_(e,t,o);n&&(r===void 0?i(e,"DELETE FROM watch_subscriptions WHERE watch = ?").run(n.rowid):typeof r=="string"?i(e,"DELETE FROM watch_subscriptions WHERE watch = ? AND pattern = ?").run(n.rowid,r):i(e,"DELETE FROM watch_subscriptions WHERE watch = ? AND started_by = ?").run(n.rowid,r.startedBy),h(e,n.rowid))}c(M,"unwatch");function x(e,t,o,r,n){const a=_(e,t,o),s=a?i(e,"UPDATE watch_subscriptions SET config_json = ? WHERE watch = ? AND pattern = ?").run(n?N(n):null,a.rowid,r).changes:0;if(Number(s)===0)throw new Error(`${t.id} has no subscription ${r} on ${o.id}`)}c(x,"setSubscriptionConfig");function U(e,t,o){const r=typeof o=="string"?i(e,`DELETE FROM watch_subscriptions WHERE started_by = 'message'
3
+ link_app = COALESCE(excluded.link_app, link_app)`).run(t.rowid,r.rowid,n.readHeadsKey??null,a,n.linkApp?.rowid??null);const s=h(e,t,r),E=o==="message"?n.endsOn??"final":null,f=O.includes(o),w=d(e,s.rowid),u=i(e,`INSERT INTO watch_subscriptions (watch, pattern, filter_json, config_json, started_by, ends_on, created_at)
4
+ VALUES (?, ?, ?, ?, ?, ?, ?)`);for(const R of C(o,n))w.some(l=>l.pattern===R&&(l.ends_on===null||l.ends_on===E)&&(!f||O.includes(l.started_by)))||u.run(s.rowid,R,n.filter===void 0?null:JSON.stringify(n.filter),n.config?N(n.config):null,o,E,a);_(e,s.rowid)}c(F,"recordWatch");function H(e,t,r,o){i(e,"UPDATE watches SET link_app = ? WHERE watcher = ? AND object = ?").run(o.rowid,t.rowid,r.rowid)}c(H,"markLinkWatch");function M(e,t,r,o){const n=h(e,t,r);n&&(o===void 0?i(e,"DELETE FROM watch_subscriptions WHERE watch = ?").run(n.rowid):typeof o=="string"?i(e,"DELETE FROM watch_subscriptions WHERE watch = ? AND pattern = ?").run(n.rowid,o):i(e,"DELETE FROM watch_subscriptions WHERE watch = ? AND started_by = ?").run(n.rowid,o.startedBy),_(e,n.rowid))}c(M,"unwatch");function x(e,t,r,o,n){const a=h(e,t,r),s=a?i(e,"UPDATE watch_subscriptions SET config_json = ? WHERE watch = ? AND pattern = ?").run(n?N(n):null,a.rowid,o).changes:0;if(Number(s)===0)throw new Error(`${t.id} has no subscription ${o} on ${r.id}`)}c(x,"setSubscriptionConfig");function U(e,t,r){const o=typeof r=="string"?i(e,`DELETE FROM watch_subscriptions WHERE started_by = 'message'
5
5
  AND watch IN (SELECT rowid FROM watches WHERE object = ?) RETURNING watch`).all(t.rowid):i(e,`DELETE FROM watch_subscriptions WHERE started_by = 'message' AND ends_on = ?
6
- AND watch IN (SELECT rowid FROM watches WHERE object = ?) RETURNING watch`).all(`result:${o.result}`,t.rowid);for(const n of new Set(r.map(a=>a.watch)))h(e,n)}c(U,"endMessageSubscriptions");function k(e,t){const o=S(e,t.watcher),r=S(e,t.object);return!o||!r?null:{rowid:t.rowid,watcher:o,object:r,in_tree:t.in_tree===1,read_heads_key:t.read_heads_key,created_at:t.created_at,subscriptions:d(e,t.rowid).map(n=>({rowid:n.rowid,pattern:n.pattern,started_by:n.started_by,ends_on:n.ends_on,created_at:n.created_at,filter:n.filter_json===null?null:JSON.parse(n.filter_json),config:n.config_json===null?null:I(n.config_json)}))}}c(k,"hydrate");function T(e,t,o){return o.map(r=>k(e,r)).filter(r=>r!==null&&O(e,t,r.watcher)&&O(e,t,r.object))}c(T,"visible");function J(e,t,o){return T(e,t,i(e,"SELECT * FROM watches WHERE watcher = ? ORDER BY rowid").all(o.rowid))}c(J,"watchesOf");function B(e,t,o){return T(e,t,i(e,"SELECT * FROM watches WHERE object = ? ORDER BY rowid").all(o.rowid))}c(B,"watchersOf");function v(e,t){return i(e,`WITH RECURSIVE walk(rowid) AS (
6
+ AND watch IN (SELECT rowid FROM watches WHERE object = ?) RETURNING watch`).all(`result:${r.result}`,t.rowid);for(const n of new Set(o.map(a=>a.watch)))_(e,n)}c(U,"endMessageSubscriptions");function g(e,t){const r=S(e,t.watcher),o=S(e,t.object);return!r||!o?null:{rowid:t.rowid,watcher:r,object:o,in_tree:t.in_tree===1,read_heads_key:t.read_heads_key,created_at:t.created_at,subscriptions:d(e,t.rowid).map(n=>({rowid:n.rowid,pattern:n.pattern,started_by:n.started_by,ends_on:n.ends_on,created_at:n.created_at,filter:n.filter_json===null?null:JSON.parse(n.filter_json),config:n.config_json===null?null:I(n.config_json)}))}}c(g,"hydrate");function T(e,t,r){return r.map(o=>g(e,o)).filter(o=>o!==null&&p(e,t,o.watcher)&&p(e,t,o.object))}c(T,"visible");function J(e,t,r){return T(e,t,i(e,"SELECT * FROM watches WHERE watcher = ? ORDER BY rowid").all(r.rowid))}c(J,"watchesOf");function B(e,t,r){return T(e,t,i(e,"SELECT * FROM watches WHERE object = ? ORDER BY rowid").all(r.rowid))}c(B,"watchersOf");function Y(e,t){return i(e,"SELECT o.id FROM watches w JOIN objects o ON o.rowid = w.watcher WHERE w.object = ? ORDER BY w.rowid").all(t.rowid).map(r=>r.id)}c(Y,"watcherIdsOf");function v(e,t){return i(e,`WITH RECURSIVE walk(rowid) AS (
7
7
  SELECT ?
8
8
  UNION
9
9
  SELECT w.object FROM walk CROSS JOIN watches w INDEXED BY watches_tree_down ON w.watcher = walk.rowid AND w.in_tree = 1
10
10
  ) SELECT o.* FROM walk CROSS JOIN objects o ON o.rowid = walk.rowid
11
- WHERE o.type = 'node' AND o.rowid != ?`).all(t.rowid,t.rowid)}c(v,"descendants");function Y(e,t){return i(e,`WITH RECURSIVE walk(rowid) AS (
11
+ WHERE o.type = 'node' AND o.rowid != ?`).all(t.rowid,t.rowid)}c(v,"descendants");function P(e,t){return i(e,`WITH RECURSIVE walk(rowid) AS (
12
12
  SELECT ?
13
13
  UNION
14
14
  SELECT w.watcher FROM walk CROSS JOIN watches w INDEXED BY watches_tree_up ON w.object = walk.rowid AND w.in_tree = 1
15
15
  ) SELECT o.* FROM walk CROSS JOIN objects o ON o.rowid = walk.rowid
16
- WHERE o.type = 'node' AND o.rowid != ?`).all(t.rowid,t.rowid)}c(Y,"ancestors");function P(e,t){return i(e,`SELECT o.* FROM watches w INDEXED BY watches_tree_up CROSS JOIN objects o ON o.rowid = w.watcher
17
- WHERE w.object = ? AND w.in_tree = 1 ORDER BY w.rowid`).all(t.rowid)}c(P,"treeWatchersOf");function V(e,t,o){const r=new Date().toISOString(),n=i(e,"SELECT * FROM watches WHERE watcher = ?").all(t.rowid),a=i(e,`INSERT INTO watch_subscriptions (watch, pattern, filter_json, config_json, started_by, ends_on, created_at)
18
- VALUES (?, ?, ?, ?, 'fork', ?, ?)`);for(const s of n){if(s.object===o.rowid)continue;i(e,`INSERT INTO watches (watcher, object, in_tree, read_heads_key, created_at) VALUES (?, ?, 0, ?, ?)
19
- ON CONFLICT (watcher, object) DO NOTHING`).run(o.rowid,s.object,s.read_heads_key,r);const E=_(e,o,{rowid:s.object}),f=d(e,E.rowid);for(const w of d(e,s.rowid))f.some(u=>u.pattern===w.pattern&&u.ends_on===w.ends_on)||a.run(E.rowid,w.pattern,w.filter_json,w.config_json,w.ends_on,r);h(e,E.rowid)}}c(V,"copyWatchesForFork");export{Y as ancestors,I as configFromJson,N as configToJson,V as copyWatchesForFork,v as descendants,U as endMessageSubscriptions,H as markLinkWatch,F as recordWatch,x as setSubscriptionConfig,P as treeWatchersOf,M as unwatch,B as watchersOf,J as watchesOf};
16
+ WHERE o.type = 'node' AND o.rowid != ?`).all(t.rowid,t.rowid)}c(P,"ancestors");function V(e,t){return i(e,`SELECT o.* FROM watches w INDEXED BY watches_tree_up CROSS JOIN objects o ON o.rowid = w.watcher
17
+ WHERE w.object = ? AND w.in_tree = 1 ORDER BY w.rowid`).all(t.rowid)}c(V,"treeWatchersOf");function $(e,t,r){const o=new Date().toISOString(),n=i(e,"SELECT * FROM watches WHERE watcher = ?").all(t.rowid),a=i(e,`INSERT INTO watch_subscriptions (watch, pattern, filter_json, config_json, started_by, ends_on, created_at)
18
+ VALUES (?, ?, ?, ?, 'fork', ?, ?)`);for(const s of n){if(s.object===r.rowid)continue;i(e,`INSERT INTO watches (watcher, object, in_tree, read_heads_key, created_at) VALUES (?, ?, 0, ?, ?)
19
+ ON CONFLICT (watcher, object) DO NOTHING`).run(r.rowid,s.object,s.read_heads_key,o);const E=h(e,r,{rowid:s.object}),f=d(e,E.rowid);for(const w of d(e,s.rowid))f.some(u=>u.pattern===w.pattern&&u.ends_on===w.ends_on)||a.run(E.rowid,w.pattern,w.filter_json,w.config_json,w.ends_on,o);_(e,E.rowid)}}c($,"copyWatchesForFork");export{P as ancestors,I as configFromJson,N as configToJson,$ as copyWatchesForFork,v as descendants,U as endMessageSubscriptions,H as markLinkWatch,F as recordWatch,x as setSubscriptionConfig,V as treeWatchersOf,M as unwatch,Y as watcherIdsOf,B as watchersOf,J as watchesOf};
package/dist/core/help.js CHANGED
@@ -1,9 +1,9 @@
1
- var k=Object.defineProperty;var u=(e,n)=>k(e,"name",{value:n,configurable:!0});import{outputBaseType as y}from"../api/command-manifest/schema.js";async function E(e,n,t){const s=u(async o=>{try{const i=await o();return()=>i}catch{return()=>null}},"read"),r=t===void 0?void 0:n.flags?.[t],a=new Map(r===void 0?[]:[[t,await s(r)]]);return{...e,...t===void 0&&n.leaf!==void 0?{dynamicState:await s(n.leaf)}:{},params:e.params?.map(o=>{const i=o.kind==="flag"?a.get(o.name):void 0;return o.kind==="flag"&&o.focusedHelp!==void 0&&i!==void 0?{...o,focusedHelp:{...o.focusedHelp,dynamicState:i}}:o})}}u(E,"withAsyncHelpState");function A(e,n,t){const s=Object.entries(n).map(([r,a])=>` ${r}="${a}"`).join("");return`<${e}${s}>
1
+ var N=Object.defineProperty;var u=(e,n)=>N(e,"name",{value:n,configurable:!0});import{outputBaseType as y}from"../api/command-manifest/schema.js";async function A(e,n,t){const o=u(async s=>{try{const i=await s();return()=>i}catch{return()=>null}},"read"),r=t===void 0?void 0:n.flags?.[t],a=new Map(r===void 0?[]:[[t,await o(r)]]);return{...e,...t===void 0&&n.leaf!==void 0?{dynamicState:await o(n.leaf)}:{},params:e.params?.map(s=>{const i=s.kind==="flag"?a.get(s.name):void 0;return s.kind==="flag"&&s.focusedHelp!==void 0&&i!==void 0?{...s,focusedHelp:{...s.focusedHelp,dynamicState:i}}:s})}}u(A,"withAsyncHelpState");function B(e,n,t){const o=Object.entries(n).map(([r,a])=>` ${r}="${a}"`).join("");return`<${e}${o}>
2
2
  ${t}
3
- </${e}>`}u(A,"stateBlock");function p(e){if(e===void 0)return null;try{const n=e();return n!==null&&n!==""?n:null}catch{return null}}u(p,"evalDynamic");function m(e){let n=0;for(const t of e)t.length>n&&(n=t.length);return n}u(m,"maxLen");function h(e,n){return e+" ".repeat(Math.max(0,n-e.length))}u(h,"pad");const N=`I/O contract: flags and positional args on input; stdout is agent-ready markdown/XML you
3
+ </${e}>`}u(B,"stateBlock");function h(e){if(e===void 0)return null;try{const n=e();return n!==null&&n!==""?n:null}catch{return null}}u(h,"evalDynamic");function $(e){let n=0;for(const t of e)t.length>n&&(n=t.length);return n}u($,"maxLen");function g(e,n){return e+" ".repeat(Math.max(0,n-e.length))}u(g,"pad");const I=`I/O contract: flags and positional args on input; stdout is agent-ready markdown/XML you
4
4
  act on directly \u2014 read it as a continuation of your prompt, don't parse it as data.
5
- Exit 0 on success, non-zero on failure. Schemas appear at leaf -h; a leaf may route an uncommon flag to focused --flag -h guidance.`,I="Before running a crtr command that changes state \u2014 creates, mutates, or deletes anything \u2014 whose exact contract (args, flags, effects) you haven't verified this session, run `-h` on it and read the schema first \u2014 a reliable read beats a guess that wastes a turn or triggers an unintended effect. When a leaf routes a flag to focused help, read that focused help before using the flag; the compact row is discovery, not its invocation contract. Same when the user names a capability you don't fully recognize: `-h` it before acting.";function j(e){const n=e.subcommands??[],t=e.otherSubcommandCount??0;if(n.length===0&&t===0)return[];const s=[];if(n.length>0){const r=m(n.map(a=>a.path));for(const a of n)s.push(a.desc!==void 0&&a.desc!==""?` ${h(a.path,r)} ${a.desc}`:` ${a.path}`)}if(t>0){const r=n.length>0?"other subcommand":"subcommand";s.push(` [+${t} ${r}${t===1?"":"s"} \u2014 \`crtr ${e.name} -h\`]`)}return s}u(j,"rootSubcommandLines");function B(e){const n=[];n.push(`${e.tagline}`),n.push("");for(const t of e.commands){n.push(`<command name="${t.name}">`),n.push(t.concept),n.push(`use when ${t.useWhen}`);for(const r of j(t))n.push(r);const s=p(t.dynamicState);s!==null&&n.push(s),n.push("</command>"),n.push("")}if(e.globals.length>0){n.push("Globals");const t=m(e.globals.map(s=>s.name));for(const s of e.globals)n.push(` ${h(s.name,t)} ${s.desc}`);n.push("")}return n.push(N),n.push(""),n.push(I),n.join(`
6
- `)}u(B,"renderRoot");function f(e){return e.replace(/"/g,"'")}u(f,"attr");const v=40;function C(e){if(e.length<=v)return{listed:[...e],unlisted:0};const n=e.filter(t=>t.tier==="common"||t.tier==="important");return n.length===0?{listed:[...e],unlisted:0}:{listed:n,unlisted:e.length-n.length}}u(C,"collapseWideChildren");function D(e){const n=e.length>v;return e.filter(t=>(t.tier==="common"||t.tier==="important")&&(!n||t.kind==="leaf"))}u(D,"rootPromotedChildren");function P(e){const n=[];n.push(`<command name="${e.name}" description="${f(e.summary)}">`);const t=p(e.dynamicState);t!==null&&n.push(t),e.model!==void 0&&n.push(e.model);const{listed:s,unlisted:r}=C((e.listing??[]).filter(a=>a.tier!=="hidden"));for(const a of s){const o=a.plugin===void 0?"":` plugin="${f(a.plugin)}"`,i=a.subCount!==void 0&&a.subCount>0?` subcommands="${a.subCount}"`:"";n.length>1&&n.push(""),n.push(`<subcommand name="${a.name}" description="${f(a.description)}" whenToUse="${f(a.whenToUse)}"${o}${i}/>`)}return r>0&&(n.push(""),n.push(`<unlisted-subcommands count="${r}">${r} more subcommands are not listed here. Each one runs by name, and \`crtr ${e.name} <name> -h\` prints its help.</unlisted-subcommands>`)),e.extensionIssue!==void 0&&n.push(`<extension-issue fragment="${f(e.extensionIssue.fragment)}">This repository's contributed commands were rejected: ${e.extensionIssue.message}. Run \`crtr sys doctor\` for the full report.</extension-issue>`),n.push("</command>"),n.join(`
7
- `)}u(P,"renderBranch");function O(e){if(e.kind==="positional")return`${e.name.toUpperCase()}${e.repeatable===!0?"...":""}`;if(e.kind==="stdin")return"stdin";if(e.kind==="context-file")return"--context-file PATH";const n=e;return n.type==="bool"?`--${n.name}`:`--${n.name} ${n.name.toUpperCase().replace(/-/g,"_")}`}u(O,"paramLabel");function x(e){return e===void 0?"":e==="base64"?" Local file path: the file is read and its raw bytes are base64-encoded into the request; the path itself is never sent.":" Local file path: the file is read as UTF-8 text and its content is sent as the value; the path itself is never sent."}u(x,"fileEncodingNote");function w(e){return e===void 0?"":` Defaults to $${e} when that is set and non-empty in the environment, and counts as supplied.`}u(w,"envDefaultNote");function S(e){return e==="file"?" A file: pass its path.":""}u(S,"fileParamNote");function T(e,n){return e.focusedHelp===void 0?"":` Before using this flag, run \`crtr ${n} --${e.name} -h\` and read its focused guidance.`}u(T,"focusedFlagHelpNote");function H(e,n){const t=e.required?"required":"optional";if(e.kind==="positional"){const c=e.repeatable===!0?" Repeatable \u2014 pass multiple values to accumulate in argv order.":"";return`positional, ${t}.${S(e.type)}${x(e.encoding)}${w(e.defaultFromEnv)} ${e.constraint}${c}`}if(e.kind==="stdin")return`${t}. ${e.constraint}`;if(e.kind==="context-file"){const c=e.shape!==void 0?` Shape: ${e.shape}`:"";return`${t}. Path to a JSON file.${c} ${e.constraint}`.trim()}const s=e,r=T(s,n);if(s.type==="bool")return`${t} boolean. Presence means true. ${s.constraint}${r}`.trim();const a=s.default!==void 0?` Default: ${String(s.default)}.`:"",o=s.type==="enum"&&s.choices!==void 0?` One of: ${s.choices.join(", ")}.`:"",i=s.repeatable===!0?" Repeatable \u2014 pass multiple times to accumulate.":"";return s.type==="json"?`json, ${t}. One JSON value: ${d(s.shape??{type:"unknown",constraint:""})}. ${s.constraint}${r}`.trim():`${s.type}, ${t}.${o}${a}${S(s.type)}${x(s.encoding)}${w(s.defaultFromEnv)} ${s.constraint}${i}${r}`.trim()}u(H,"paramDesc");function d(e){const n=/\|\s*null\s*$/i.test(e.type),t=y(e.type);return t==="union"&&e.variants!==void 0?`${e.variants.map(d).join(" | ")}${n?" | null":""}`:t==="map"&&e.items!==void 0?`{ [key: string]: ${d(e.items)} }${n?" | null":""}`:e.items===void 0?e.type:`array of ${d(e.items)}${n?", or null":""}`}u(d,"outputTypePhrase");function $(e){return e.values!==void 0?` One of: ${e.values.join(", ")}.`:""}u($,"outputValuesNote");function b(e,n,t){const s=m(e.map(r=>r.name));for(const r of e){const a=r.constraint.length>0?` ${r.constraint}`:"";t.push(`${n}${h(r.name,s)} ${d(r)}.${$(r)}${a}`),g(r,`${n} `,t)}}u(b,"renderOutputFields");function g(e,n,t){e.children!==void 0&&e.children.length>0&&b(e.children,n,t);for(const a of e.variants??[]){const o=$(a);t.push(`${n}variant: ${d(a)}.${o}${a.constraint.length>0?` ${a.constraint}`:""}`),g(a,`${n} `,t)}let s=e.items,r=y(e.type)==="map"?"each value":"each element";for(;s!==void 0;){const a=$(s);(s.constraint.length>0||a.length>0)&&t.push(`${n}${r}: ${d(s)}.${a}${s.constraint.length>0?` ${s.constraint}`:""}`);for(const o of s.variants??[])t.push(`${n}variant: ${d(o)}.${$(o)}${o.constraint.length>0?` ${o.constraint}`:""}`),g(o,`${n} `,t);if(s.children!==void 0&&s.children.length>0){b(s.children,n,t);return}r=y(s.type)==="map"?"each value":"each element",s=s.items}}u(g,"renderOutputShapeBody");function R(e,n){const t=[`${e.name}: ${e.summary}.`],s=(e.params??[]).filter(o=>!(o.kind==="flag"&&o.hidden===!0)),r=n===void 0?void 0:s.find(o=>o.kind==="flag"&&o.name===n&&o.focusedHelp!==void 0);if(r?.focusedHelp!==void 0){const o=r.focusedHelp;if(t.push(""),t.push(`<parameter name="${r.name}">`),t.push("When to use"),t.push(` ${o.whenToUse}`),t.push(""),t.push("Value"),t.push(` ${o.value}`),(o.effects??[]).length>0){t.push(""),t.push("Effects");for(const c of o.effects??[])t.push(` ${c}`)}const i=p(o.dynamicState);return i!==null&&(t.push(""),t.push(i)),t.push("</parameter>"),t.join(`
8
- `)}if(e.guide!==void 0&&(t.push(""),t.push(e.guide)),t.push(""),s.length>0){t.push("Input");const o=s.map(O),i=m(o);for(let c=0;c<s.length;c++){t.push(` ${h(o[c],i)} ${H(s[c],e.name)}`);const l=s[c];l.kind==="flag"&&l.type==="json"&&l.shape!==void 0&&g(l.shape,` ${" ".repeat(i)} `,t)}}else t.push(e.inputNote!==void 0?e.inputNote:"No input parameters.");t.push(""),t.push("Output (fields carried in the rendered result)"),b(e.output," ",t),t.push(""),t.push("Effects");for(const o of e.effects)t.push(` ${o}`);const a=p(e.dynamicState);return a!==null&&(t.push(""),t.push(a)),t.join(`
9
- `)}u(R,"renderLeafArgv");export{v as WIDE_BRANCH_LISTING_LIMIT,C as collapseWideChildren,P as renderBranch,R as renderLeafArgv,B as renderRoot,D as rootPromotedChildren,A as stateBlock,E as withAsyncHelpState};
5
+ Exit 0 on success, non-zero on failure. Schemas appear at leaf -h; a leaf may route an uncommon flag to focused --flag -h guidance.`,j="Before running a crtr command that changes state \u2014 creates, mutates, or deletes anything \u2014 whose exact contract (args, flags, effects) you haven't verified this session, run `-h` on it and read the schema first \u2014 a reliable read beats a guess that wastes a turn or triggers an unintended effect. When a leaf routes a flag to focused help, read that focused help before using the flag; the compact row is discovery, not its invocation contract. Same when the user names a capability you don't fully recognize: `-h` it before acting.";function C(e){const n=e.subcommands??[],t=e.otherSubcommandCount??0;if(n.length===0&&t===0)return[];const o=[];if(n.length>0){const r=$(n.map(a=>a.path));for(const a of n)o.push(a.desc!==void 0&&a.desc!==""?` ${g(a.path,r)} ${a.desc}`:` ${a.path}`)}if(t>0){const r=n.length>0?"other subcommand":"subcommand";o.push(` [+${t} ${r}${t===1?"":"s"} \u2014 \`crtr ${e.name} -h\`]`)}return o}u(C,"rootSubcommandLines");function R(e){const n=[];n.push(`${e.tagline}`),n.push("");for(const t of e.commands){n.push(`<command name="${t.name}">`),n.push(t.concept),n.push(`use when ${t.useWhen}`);for(const r of C(t))n.push(r);const o=h(t.dynamicState);o!==null&&n.push(o),n.push("</command>"),n.push("")}if(e.globals.length>0){n.push("Globals");const t=$(e.globals.map(o=>o.name));for(const o of e.globals)n.push(` ${g(o.name,t)} ${o.desc}`);n.push("")}return n.push(I),n.push(""),n.push(j),n.join(`
6
+ `)}u(R,"renderRoot");function d(e){return e.replace(/"/g,"'")}u(d,"attr");const v=40;function O(e){if(e.length<=v)return{listed:[...e],unlisted:0};const n=e.filter(t=>t.tier==="common"||t.tier==="important");return n.length===0?{listed:[...e],unlisted:0}:{listed:n,unlisted:e.length-n.length}}u(O,"collapseWideChildren");function D(e){const n=e.length>v;return e.filter(t=>(t.tier==="common"||t.tier==="important")&&(!n||t.kind==="leaf"))}u(D,"rootPromotedChildren");function P(e){const n=[];n.push(`<command name="${e.name}" description="${d(e.summary)}">`);const t=h(e.dynamicState);t!==null&&n.push(t),e.model!==void 0&&n.push(e.model);const{listed:o,unlisted:r}=O((e.listing??[]).filter(a=>a.tier!=="hidden"));for(const a of o){const s=a.plugin===void 0?"":` plugin="${d(a.plugin)}"`,i=a.subCount!==void 0&&a.subCount>0?` subcommands="${a.subCount}"`:"";n.length>1&&n.push(""),n.push(`<subcommand name="${a.name}" description="${d(a.description)}" whenToUse="${d(a.whenToUse)}"${s}${i}/>`)}return r>0&&(n.push(""),n.push(`<unlisted-subcommands count="${r}">${r} more subcommands are not listed here. Each one runs by name, and \`crtr ${e.name} <name> -h\` prints its help.</unlisted-subcommands>`)),e.extensionIssue!==void 0&&n.push(`<extension-issue fragment="${d(e.extensionIssue.fragment)}">This repository's contributed commands were rejected: ${e.extensionIssue.message}. Run \`crtr sys doctor\` for the full report.</extension-issue>`),n.push("</command>"),n.join(`
7
+ `)}u(P,"renderBranch");function T(e){if(e.kind==="positional")return`${e.name.toUpperCase()}${e.repeatable===!0?"...":""}`;if(e.kind==="stdin")return"stdin";if(e.kind==="context-file")return"--context-file PATH";const n=e;return n.type==="bool"?`--${n.name}`:`--${n.name} ${n.name.toUpperCase().replace(/-/g,"_")}`}u(T,"paramLabel");function w(e){return e===void 0?"":e==="base64"?" Local file path: the file is read and its raw bytes are base64-encoded into the request; the path itself is never sent.":" Local file path: the file is read as UTF-8 text and its content is sent as the value; the path itself is never sent."}u(w,"fileEncodingNote");function S(e){return e===void 0?"":` Defaults to $${e} when that is set and non-empty in the environment, and counts as supplied.`}u(S,"envDefaultNote");function k(e){return e==="file"?" A file: pass its path.":""}u(k,"fileParamNote");function H(e,n){return e.focusedHelp===void 0?"":` Before using this flag, run \`crtr ${n} --${e.name} -h\` and read its focused guidance.`}u(H,"focusedFlagHelpNote");function L(e,n){const t=e.required?"required":"optional";if(e.kind==="positional"){const c=e.repeatable===!0?" Repeatable \u2014 pass multiple values to accumulate in argv order.":"";return`positional, ${t}.${k(e.type)}${w(e.encoding)}${S(e.defaultFromEnv)} ${e.constraint}${c}`}if(e.kind==="stdin")return`${t}. ${e.constraint}`;if(e.kind==="context-file"){const c=e.shape!==void 0?` Shape: ${e.shape}`:"";return`${t}. Path to a JSON file.${c} ${e.constraint}`.trim()}const o=e,r=H(o,n);if(o.type==="bool")return`${t} boolean. Presence means true. ${o.constraint}${r}`.trim();const a=o.default!==void 0?` Default: ${String(o.default)}.`:"",s=o.type==="enum"&&o.choices!==void 0?` One of: ${o.choices.join(", ")}.`:"",i=o.repeatable===!0?" Repeatable \u2014 pass multiple times to accumulate.":"";return o.type==="json"?`json, ${t}. One JSON value: ${f(o.shape??{type:"unknown",constraint:""})}. ${o.constraint}${r}`.trim():`${o.type}, ${t}.${s}${a}${k(o.type)}${w(o.encoding)}${S(o.defaultFromEnv)} ${o.constraint}${i}${r}`.trim()}u(L,"paramDesc");function f(e){const n=/\|\s*null\s*$/i.test(e.type),t=y(e.type);return t==="union"&&e.variants!==void 0?`${e.variants.map(f).join(" | ")}${n?" | null":""}`:t==="map"&&e.items!==void 0?`{ [key: string]: ${f(e.items)} }${n?" | null":""}`:e.items===void 0?e.type:`array of ${f(e.items)}${n?", or null":""}`}u(f,"outputTypePhrase");function l(e){return e.values!==void 0?` One of: ${e.values.join(", ")}.`:""}u(l,"outputValuesNote");function b(e,n,t){const o=$(e.map(r=>r.name));for(const r of e){const a=r.constraint.length>0?` ${r.constraint}`:"";t.push(`${n}${g(r.name,o)} ${f(r)}.${l(r)}${a}`),p(r,`${n} `,t)}}u(b,"renderOutputFields");function x(e,n,t){const o=e.extra;o!==void 0&&(t.push(`${n}other members: ${f(o)}.${l(o)}${o.constraint.length>0?` ${o.constraint}`:""}`),p(o,`${n} `,t))}u(x,"renderExtraRow");function p(e,n,t){e.children!==void 0&&e.children.length>0&&b(e.children,n,t),x(e,n,t);for(const a of e.variants??[]){const s=l(a);t.push(`${n}variant: ${f(a)}.${s}${a.constraint.length>0?` ${a.constraint}`:""}`),p(a,`${n} `,t)}let o=e.items,r=y(e.type)==="map"?"each value":"each element";for(;o!==void 0;){const a=l(o);(o.constraint.length>0||a.length>0)&&t.push(`${n}${r}: ${f(o)}.${a}${o.constraint.length>0?` ${o.constraint}`:""}`);for(const s of o.variants??[])t.push(`${n}variant: ${f(s)}.${l(s)}${s.constraint.length>0?` ${s.constraint}`:""}`),p(s,`${n} `,t);if(o.children!==void 0&&o.children.length>0){b(o.children,n,t),x(o,n,t);return}if(o.extra!==void 0){x(o,n,t);return}r=y(o.type)==="map"?"each value":"each element",o=o.items}}u(p,"renderOutputShapeBody");function U(e,n){const t=[`${e.name}: ${e.summary}.`],o=(e.params??[]).filter(s=>!(s.kind==="flag"&&s.hidden===!0)),r=n===void 0?void 0:o.find(s=>s.kind==="flag"&&s.name===n&&s.focusedHelp!==void 0);if(r?.focusedHelp!==void 0){const s=r.focusedHelp;if(t.push(""),t.push(`<parameter name="${r.name}">`),t.push("When to use"),t.push(` ${s.whenToUse}`),t.push(""),t.push("Value"),t.push(` ${s.value}`),(s.effects??[]).length>0){t.push(""),t.push("Effects");for(const c of s.effects??[])t.push(` ${c}`)}const i=h(s.dynamicState);return i!==null&&(t.push(""),t.push(i)),t.push("</parameter>"),t.join(`
8
+ `)}if(e.guide!==void 0&&(t.push(""),t.push(e.guide)),t.push(""),o.length>0){t.push("Input");const s=o.map(T),i=$(s);for(let c=0;c<o.length;c++){t.push(` ${g(s[c],i)} ${L(o[c],e.name)}`);const m=o[c];m.kind==="flag"&&m.type==="json"&&m.shape!==void 0&&p(m.shape,` ${" ".repeat(i)} `,t)}}else t.push(e.inputNote!==void 0?e.inputNote:"No input parameters.");t.push(""),t.push("Output (fields carried in the rendered result)"),b(e.output," ",t),t.push(""),t.push("Effects");for(const s of e.effects)t.push(` ${s}`);const a=h(e.dynamicState);return a!==null&&(t.push(""),t.push(a)),t.join(`
9
+ `)}u(U,"renderLeafArgv");export{v as WIDE_BRANCH_LISTING_LIMIT,O as collapseWideChildren,P as renderBranch,U as renderLeafArgv,R as renderRoot,D as rootPromotedChildren,B as stateBlock,A as withAsyncHelpState};
@@ -1,3 +1,3 @@
1
- var ge=Object.defineProperty;var u=(e,t)=>ge(e,"name",{value:t,configurable:!0});import{randomUUID as be}from"node:crypto";import{streamSimple as ve}from"@earendil-works/pi-ai/compat";import{expandModelCandidates as re,parseModelSpec as ie,probeRouteAvailability as we}from"../model-routes.js";import{readMergedLaunchConfig as se}from"../config.js";import{openModelRegistry as xe}from"../runtime/model-registry.js";import{MAX_RATE_LIMIT_COOLDOWN_MS as ae,coolingUntilFor as de,isManagedProvider as H,markSubscriptionRateLimited as ke,markSubscriptionSuccess as je,readSubscriptionPool as Me,retryAfterMsFromHeaders as K,retryAfterMsFromError as Ae,refreshSubscriptionCredential as qe,subscriptionNeedsSuccessWrite as Re}from"../subscription-state.js";import{classifyRateLimit as $e,describeRateLimitScope as le,rateLimitHeaders as Ie}from"../rate-limit-scope.js";import{RunError as i}from"../runs/operations.js";import{recognizeProviderError as ce}from"../provider-error-recognition.js";import{isSafetyRefusal as Ce}from"./refusal.js";import{assertUnderCap as Oe,recordModelUsage as ue}from"../usage/ledger.js";import{outboundToken as Se}from"../providers/mint.js";import{discardFile as Le}from"../providers/token-cache.js";import{ProviderError as Ee}from"../providers/errors.js";import{appCandidates as Ne}from"./app-rungs.js";function De(e){return typeof e=="string"||e===null||Array.isArray(e)&&e.every(t=>t&&typeof t=="object"&&(t.type==="text"&&typeof t.text=="string"||t.type==="image_url"&&typeof t.image_url?.url=="string"&&/^data:image\/(png|jpeg|gif|webp);base64,[A-Za-z0-9+/]+={0,2}$/.test(t.image_url.url)))}u(De,"validContent");function fe(e){return Array.isArray(e)?e.map(t=>{if(t.type==="text")return t;const[,n,r]=/^data:(image\/(?:png|jpeg|gif|webp));base64,(.*)$/.exec(t.image_url.url);return{type:"image",mimeType:n,data:r}}):e??""}u(fe,"imageContent");function at(e){if(!e||typeof e!="object"||Array.isArray(e))throw new i(400,"invalid_request","body must be an object");const t=e;if(!Array.isArray(t.messages)||!t.messages.every(n=>n&&typeof n=="object"&&["system","user","assistant","tool"].includes(n.role)&&De(n.content)))throw new i(400,"invalid_request","messages must be chat messages","messages");if(t.messages.some(n=>["system","assistant"].includes(n.role)&&typeof n.content!="string"&&n.content!==null))throw new i(400,"invalid_request","system and assistant content must be text","messages");if(t.model!==void 0&&typeof t.model!="string")throw new i(400,"invalid_request","model must be a string","model");if(t.model_policy!==void 0&&!["exact","substitute"].includes(t.model_policy))throw new i(400,"invalid_request","invalid model_policy","model_policy");if(t.payer!==void 0&&!["user","app"].includes(t.payer))throw new i(400,"invalid_request","invalid payer","payer");if(t.reasoning_effort!==void 0&&!["minimal","low","medium","high","xhigh","max"].includes(t.reasoning_effort))throw new i(400,"invalid_request","invalid reasoning_effort","reasoning_effort");if(t.stream!==void 0&&typeof t.stream!="boolean")throw new i(400,"invalid_request","stream must be boolean","stream");if(t.tools!==void 0&&(!Array.isArray(t.tools)||!t.tools.every(n=>n?.type==="function"&&typeof n.function?.name=="string"&&n.function.name.length>0&&(n.function.description===void 0||typeof n.function.description=="string")&&(n.function.parameters===void 0||n.function.parameters!==null&&typeof n.function.parameters=="object"&&!Array.isArray(n.function.parameters)&&n.function.parameters.type==="object"))))throw new i(400,"invalid_request","invalid tools","tools");if(t.tool_choice!==void 0&&t.tool_choice!=="auto"&&t.tool_choice!=="none"&&t.tool_choice!=="required"&&(typeof t.tool_choice!="object"||t.tool_choice===null||t.tool_choice.type!=="function"||typeof t.tool_choice.function?.name!="string"))throw new i(400,"invalid_request","invalid tool_choice","tool_choice");if(t.messages.some(n=>n.role==="assistant"&&n.tool_calls!==void 0&&(!Array.isArray(n.tool_calls)||!n.tool_calls.every(r=>r&&typeof r.id=="string"&&typeof r.function?.name=="string"&&typeof r.function.arguments=="string"&&Fe(r.function.arguments)))))throw new i(400,"invalid_request","invalid assistant tool_calls","messages");if(t.stop!==void 0&&!(typeof t.stop=="string"||Array.isArray(t.stop)&&t.stop.every(n=>typeof n=="string")))throw new i(400,"invalid_request","invalid stop","stop");if(t.seed!==void 0&&!Number.isSafeInteger(t.seed))throw new i(400,"invalid_request","invalid seed","seed");for(const[n,r]of[["temperature",t.temperature],["top_p",t.top_p],["max_tokens",t.max_tokens]])if(r!==void 0&&(typeof r!="number"||!Number.isFinite(r)||n==="temperature"&&(r<0||r>2)||n==="top_p"&&(r<0||r>1)||n==="max_tokens"&&(!Number.isSafeInteger(r)||r<1)))throw new i(400,"invalid_request",`invalid ${n}`,n);if(t.response_format!==void 0){const n=t.response_format;if(!n||typeof n!="object"||Array.isArray(n)||!["text","json_object","json_schema"].includes(n.type)||n.type==="json_schema"&&(typeof n.json_schema?.name!="string"||!n.json_schema.name||!n.json_schema.schema||typeof n.json_schema.schema!="object"||Array.isArray(n.json_schema.schema)))throw new i(400,"invalid_request","invalid response_format","response_format")}if(t.metadata!==void 0&&Buffer.byteLength(JSON.stringify(t.metadata)??"")>4096)throw new i(400,"invalid_request","metadata exceeds 4 KB","metadata");return t}u(at,"parseLlmRequest");function Fe(e){try{const t=JSON.parse(e);return t!==null&&typeof t=="object"&&!Array.isArray(t)}catch{return!1}}u(Fe,"isJsonObject");function Te(e){const t=Date.now(),n=e.messages.map(s=>s.role==="system"?{role:"system",content:s.content??"",timestamp:t}:s.role==="tool"?{role:"toolResult",toolCallId:s.tool_call_id??"",toolName:"",content:typeof s.content=="string"||s.content===null?[{type:"text",text:s.content??""}]:fe(s.content),isError:!1,timestamp:t}:s.role==="assistant"?{role:"assistant",content:[...s.content?[{type:"text",text:s.content}]:[],...(s.tool_calls??[]).map(g=>({type:"toolCall",id:g.id,name:g.function.name,arguments:JSON.parse(g.function.arguments)}))],api:"openai-completions",provider:"openai",model:e.model??"",usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:t}:{role:"user",content:fe(s.content),timestamp:t}),r=n.findIndex(s=>s.role!=="system"),w=n.slice(0,r<0?n.length:r).map(s=>s.content),y=w.join(`
1
+ var be=Object.defineProperty;var u=(e,t)=>be(e,"name",{value:t,configurable:!0});import{randomUUID as ve}from"node:crypto";import{streamSimple as we}from"@earendil-works/pi-ai/compat";import{expandModelCandidates as ie,parseModelSpec as se,probeRouteAvailability as xe}from"../model-routes.js";import{readMergedLaunchConfig as ae}from"../config.js";import{openModelRegistry as ke}from"../runtime/model-registry.js";import{MAX_RATE_LIMIT_COOLDOWN_MS as de,coolingUntilFor as le,isManagedProvider as H,markSubscriptionRateLimited as je,markSubscriptionSuccess as Me,readSubscriptionPool as Ae,retryAfterMsFromHeaders as K,retryAfterMsFromError as qe,refreshSubscriptionCredential as $e,subscriptionNeedsSuccessWrite as Re}from"../subscription-state.js";import{classifyRateLimit as Ie,describeRateLimitScope as ce,rateLimitHeaders as Ce}from"../rate-limit-scope.js";import{RunError as i}from"../runs/operations.js";import{recognizeProviderError as Y}from"../provider-error-recognition.js";import{isSafetyRefusal as Se}from"./refusal.js";import{assertUnderCap as Oe,recordModelUsage as ue}from"../usage/ledger.js";import{outboundToken as Le}from"../providers/mint.js";import{discardFile as Ee}from"../providers/token-cache.js";import{ProviderError as Ne}from"../providers/errors.js";import{appCandidates as De}from"./app-rungs.js";function Fe(e){return typeof e=="string"||e===null||Array.isArray(e)&&e.every(t=>t&&typeof t=="object"&&(t.type==="text"&&typeof t.text=="string"||t.type==="image_url"&&typeof t.image_url?.url=="string"&&/^data:image\/(png|jpeg|gif|webp);base64,[A-Za-z0-9+/]+={0,2}$/.test(t.image_url.url)))}u(Fe,"validContent");function fe(e){return Array.isArray(e)?e.map(t=>{if(t.type==="text")return t;const[,n,r]=/^data:(image\/(?:png|jpeg|gif|webp));base64,(.*)$/.exec(t.image_url.url);return{type:"image",mimeType:n,data:r}}):e??""}u(fe,"imageContent");function Te(e,t){const n=(e instanceof Error?e.message:String(e)).split("; stack=",1)[0],r=Y({message:n}).kind;return r!=="connection"&&r!=="connection-only"?e:new i(503,"upstream_model_unavailable",n.slice(0,500),void 0,{served_model:t})}u(Te,"refreshFailure");function lt(e){if(!e||typeof e!="object"||Array.isArray(e))throw new i(400,"invalid_request","body must be an object");const t=e;if(!Array.isArray(t.messages)||!t.messages.every(n=>n&&typeof n=="object"&&["system","user","assistant","tool"].includes(n.role)&&Fe(n.content)))throw new i(400,"invalid_request","messages must be chat messages","messages");if(t.messages.some(n=>["system","assistant"].includes(n.role)&&typeof n.content!="string"&&n.content!==null))throw new i(400,"invalid_request","system and assistant content must be text","messages");if(t.model!==void 0&&typeof t.model!="string")throw new i(400,"invalid_request","model must be a string","model");if(t.model_policy!==void 0&&!["exact","substitute"].includes(t.model_policy))throw new i(400,"invalid_request","invalid model_policy","model_policy");if(t.payer!==void 0&&!["user","app"].includes(t.payer))throw new i(400,"invalid_request","invalid payer","payer");if(t.reasoning_effort!==void 0&&!["minimal","low","medium","high","xhigh","max"].includes(t.reasoning_effort))throw new i(400,"invalid_request","invalid reasoning_effort","reasoning_effort");if(t.stream!==void 0&&typeof t.stream!="boolean")throw new i(400,"invalid_request","stream must be boolean","stream");if(t.tools!==void 0&&(!Array.isArray(t.tools)||!t.tools.every(n=>n?.type==="function"&&typeof n.function?.name=="string"&&n.function.name.length>0&&(n.function.description===void 0||typeof n.function.description=="string")&&(n.function.parameters===void 0||n.function.parameters!==null&&typeof n.function.parameters=="object"&&!Array.isArray(n.function.parameters)&&n.function.parameters.type==="object"))))throw new i(400,"invalid_request","invalid tools","tools");if(t.tool_choice!==void 0&&t.tool_choice!=="auto"&&t.tool_choice!=="none"&&t.tool_choice!=="required"&&(typeof t.tool_choice!="object"||t.tool_choice===null||t.tool_choice.type!=="function"||typeof t.tool_choice.function?.name!="string"))throw new i(400,"invalid_request","invalid tool_choice","tool_choice");if(t.messages.some(n=>n.role==="assistant"&&n.tool_calls!==void 0&&(!Array.isArray(n.tool_calls)||!n.tool_calls.every(r=>r&&typeof r.id=="string"&&typeof r.function?.name=="string"&&typeof r.function.arguments=="string"&&Pe(r.function.arguments)))))throw new i(400,"invalid_request","invalid assistant tool_calls","messages");if(t.stop!==void 0&&!(typeof t.stop=="string"||Array.isArray(t.stop)&&t.stop.every(n=>typeof n=="string")))throw new i(400,"invalid_request","invalid stop","stop");if(t.seed!==void 0&&!Number.isSafeInteger(t.seed))throw new i(400,"invalid_request","invalid seed","seed");for(const[n,r]of[["temperature",t.temperature],["top_p",t.top_p],["max_tokens",t.max_tokens]])if(r!==void 0&&(typeof r!="number"||!Number.isFinite(r)||n==="temperature"&&(r<0||r>2)||n==="top_p"&&(r<0||r>1)||n==="max_tokens"&&(!Number.isSafeInteger(r)||r<1)))throw new i(400,"invalid_request",`invalid ${n}`,n);if(t.response_format!==void 0){const n=t.response_format;if(!n||typeof n!="object"||Array.isArray(n)||!["text","json_object","json_schema"].includes(n.type)||n.type==="json_schema"&&(typeof n.json_schema?.name!="string"||!n.json_schema.name||!n.json_schema.schema||typeof n.json_schema.schema!="object"||Array.isArray(n.json_schema.schema)))throw new i(400,"invalid_request","invalid response_format","response_format")}if(t.metadata!==void 0&&Buffer.byteLength(JSON.stringify(t.metadata)??"")>4096)throw new i(400,"invalid_request","metadata exceeds 4 KB","metadata");return t}u(lt,"parseLlmRequest");function Pe(e){try{const t=JSON.parse(e);return t!==null&&typeof t=="object"&&!Array.isArray(t)}catch{return!1}}u(Pe,"isJsonObject");function Ue(e){const t=Date.now(),n=e.messages.map(s=>s.role==="system"?{role:"system",content:s.content??"",timestamp:t}:s.role==="tool"?{role:"toolResult",toolCallId:s.tool_call_id??"",toolName:"",content:typeof s.content=="string"||s.content===null?[{type:"text",text:s.content??""}]:fe(s.content),isError:!1,timestamp:t}:s.role==="assistant"?{role:"assistant",content:[...s.content?[{type:"text",text:s.content}]:[],...(s.tool_calls??[]).map(g=>({type:"toolCall",id:g.id,name:g.function.name,arguments:JSON.parse(g.function.arguments)}))],api:"openai-completions",provider:"openai",model:e.model??"",usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:t}:{role:"user",content:fe(s.content),timestamp:t}),r=n.findIndex(s=>s.role!=="system"),w=n.slice(0,r<0?n.length:r).map(s=>s.content),y=w.join(`
2
2
 
3
- `),l=e.tools?.map(({function:s})=>({name:s.name,description:s.description??"",parameters:s.parameters??{type:"object",properties:{}}}));return{...y?{systemPrompt:y}:{},messages:n.slice(w.length),...l?{tools:l}:{}}}u(Te,"contextOf");function me(e,t,n,r){if(!e){const y=se(n,r),l=Object.values({...y.modelRoutes??{},...y.legacyModelRoutes??{}}),s=l.length?[y.modelLadders.defaultProvider,...y.modelRouting?.familyOrder??[],...l.map(g=>g.family)].find(g=>l.some(E=>E.family===g)):y.modelLadders.defaultProvider??"anthropic";return{kind:"logical",family:s,strength:"strong",spec:`${s}/strong`}}const w=/^([^/]+)\/(ultra|strong|medium|light)$/.exec(e);return w?{kind:"logical",family:w[1],strength:w[2],spec:e}:{kind:t==="exact"?"exact":"concrete",spec:e}}u(me,"requestFor");function Pe(e,t){const{input:n,output:r,cacheRead:w,cacheWrite:y}=e.cost;return n===0&&r===0&&w===0&&y===0?null:Number.isFinite(t)&&t>=0?t:null}u(Pe,"usdEquivalent");function Ue(e,t){return e.compat?.allowedFallbackModels?.find(r=>r.provider===e.provider&&r.model===t)}u(Ue,"allowedFallback");function dt(e){return e?{payer:e.payer??"user",sub:e.sub,grantee:e.grantee,inference_endpoint:e.inference_endpoint??null}:void 0}u(dt,"llmCallerOf");function Je(e){return e instanceof Ee?e.code==="server_error"?new i(503,"upstream_model_unavailable",e.message):new i(404,"model_unavailable",e.message):e}u(Je,"mintFailure");const We=/\bmodel is not supported when using Codex with a ChatGPT account\b/i;function He(e,t,n){if(!(e!=="openai-codex"||t===void 0||!We.test(t)))return new i(404,"model_unavailable",t,void 0,{served_model:n})}u(He,"codexAccountModelRejection");async function lt(e,t,n,r,w,y){const l=y?.payer==="app"?y:void 0;if(e.payer==="app"&&!l)throw new i(403,"payer_not_app","this grant is not app-paid");if(e.payer==="user"&&l)throw new i(400,"invalid_request","this grant is app-paid; payer cannot be user","payer");if(l&&!l.inference_endpoint)throw new i(404,"model_unavailable",`${l.grantee} is app-paid but its grant carries no inference endpoint`);const s=l?.inference_endpoint??void 0;l||Oe(w);const g=await xe(),E=u(c=>c.routeId!=="concrete"&&c.routeId!=="exact","configured"),Y=u(c=>{const h=g.find(c.providerId,c.modelId);return h!==void 0&&(!e.reasoning_effort||h.reasoning)&&(e.seed===void 0&&e.response_format===void 0||h.api==="openai-completions")&&(e.stop===void 0||["openai-completions","anthropic-messages"].includes(h.api))},"matchesFeatures"),pe=u(()=>{const c=me(e.model,e.model_policy,r?.cwd,r?.profileId),h=re(c.kind==="exact"?{kind:"concrete",spec:c.spec}:c,r?.cwd,r?.profileId).filter(E);let a;if(c.kind==="logical")a=e.model_policy==="exact"?h.filter(m=>m.family===c.family&&m.strength===c.strength).slice(0,1):h;else{const m=ie(c.spec),q=h.filter(j=>j.providerId===m?.providerId&&j.modelId===m.modelId&&(e.model_policy!=="exact"||j.thinkingLevel===m.thinkingLevel)&&Y(j));if(e.model_policy==="exact")a=q.slice(0,1);else if(q.length)a=q;else{const j=se(r?.cwd,r?.profileId),x=[...Object.values(j.modelRoutes??{}).flatMap(v=>Object.entries(v.models)),...[j.modelLadders.anthropic,j.modelLadders.openai].flatMap(v=>Object.entries(v))].find(([,v])=>v===c.spec)?.[0],f=me(void 0,"substitute",r?.cwd,r?.profileId);a=x&&f.kind==="logical"?re({...f,strength:x,spec:c.spec},r?.cwd,r?.profileId).filter(v=>E(v)&&v.strength===x):[]}}return a},"ownerCandidates");let $;if(s?$=Ne(s,e.model,e.model_policy==="exact").flatMap((c,h)=>{const a=ie(c.model);return a?[{routeId:"app",credentialSource:"app",family:"app",strength:c.strength,...a,rank:h}]:[]}):$=pe(),$=$.filter(Y),$.length===0)throw e.model_policy==="exact"?new i(400,"substitution_refused","no eligible model route is configured"):new i(404,"model_unavailable","no eligible model route is configured");const ee=`chatcmpl-${be()}`;let I=1/0,b,z;for(const c of $){if(!l&&!we(c,g).authenticated)continue;const h=g.find(c.providerId,c.modelId);if(!h)continue;const a=s?{...h,baseUrl:`${s.base_url}/${h.provider}`}:h,m=c.providerId,q=!l&&H(m)?Me(m).filter(x=>!x.authFailure):[],j=q.filter(x=>de(x,a.id)<=Date.now());if(q.length&&!j.length){const x=Math.min(...q.map(f=>de(f,a.id)));x<I&&(I=x,z=`${a.provider}/${a.id}`);continue}const te=l?[void 0,void 0]:q.length?j:[void 0];for(const[x,f]of te.entries()){const v=Date.now();let oe=f?.access;if(f&&f.expires<=Date.now()&&H(m)){const o=g.getProvider(m)?.auth.oauth;if(!o)throw new i(503,"upstream_model_unavailable",`no OAuth refresh for ${m}`,void 0,{served_model:`${a.provider}/${a.id}`});oe=(await qe(m,f.label,async(k,ne)=>{const W=await o.refresh({type:"oauth",refresh:k,access:"",expires:0,...ne?{clientId:ne}:{}},t??new AbortController().signal),V=W.clientId;return{refresh:W.refresh,access:W.access,expires:W.expires,...typeof V=="string"&&V?{clientId:V}:{}}})).access}const he=Te(e);let N;if(l&&s)try{N=await Se({audience:s.base_url,sub:l.sub,grantee:l.grantee,initiating_app:l.grantee,scope:["crtr:llm"]},{signal:t})}catch(o){throw Je(o)}const C=f||l?void 0:await g.getApiKeyAndHeaders(a);if(C&&!C.ok)continue;const p=`${a.provider}/${a.id}`,O=e.model??p;let A=!1,L,M=3e4,R;const B=[],X=[],D=[];let d,F;const T=u((o,_=null)=>({id:ee,object:"chat.completion.chunk",created:Math.floor(v/1e3),model:p,served_model:p,requested_model:O,substituted:O!==p&&!/^([^/]+)\/(ultra|strong|medium|light)$/.test(O),choices:[{index:0,delta:o,finish_reason:_}]}),"chunk"),P=u(o=>{B.push(o),n?.(o)},"emit"),_e=ve(a,he,{apiKey:N?.access_token??oe??(C?.ok?C.apiKey:void 0),...C?.ok?{headers:C.headers}:{},signal:t,reasoning:e.reasoning_effort??c.thinkingLevel,...e.temperature!==void 0?{temperature:e.temperature}:{},...e.max_tokens!==void 0?{maxTokens:e.max_tokens}:{},...e.top_p!==void 0?{samplingParams:{top_p:e.top_p}}:{},...e.tool_choice==="none"?{toolChoice:"none"}:{},onPayload:u(o=>{if(!o||typeof o!="object")return;const _=e.tool_choice,k=_==="required"?a.api==="anthropic-messages"?{type:"any"}:"required":typeof _=="object"&&_!==null?a.api==="anthropic-messages"?{type:"tool",name:_.function.name}:_:void 0;return{...o,...k?{tool_choice:k}:{},...e.stop!==void 0?{[a.api==="anthropic-messages"?"stop_sequences":"stop"]:typeof e.stop=="string"?[e.stop]:e.stop}:{},...e.seed!==void 0?{seed:e.seed}:{},...e.response_format!==void 0?{response_format:e.response_format}:{}}},"onPayload"),fetch:u(async(o,_)=>{const k=await fetch(o,_);return L=k.status,k.status===429&&(A=!0,R=k.headers,M=K(k.headers)??15e3),k},"fetch"),onResponse:u(o=>{o.status===429&&(A=!0,R=o.headers,M=K(o.headers)??15e3)},"onResponse")});try{for await(const o of _e)o.type==="text_delta"&&(X.push(o.delta),P(T({content:o.delta}))),o.type==="thinking_delta"&&(D.push(o.delta),P(T({reasoning_content:o.delta}))),o.type==="done"&&(d=o.message),o.type==="error"&&(d=o.error)}catch(o){const _=Ae(o);R===void 0&&o&&typeof o=="object"&&"headers"in o&&Object.keys(Ie(o.headers)).length&&(R=o.headers);const k=ce({status:o&&typeof o=="object"&&"status"in o?o.status:void 0,message:o instanceof Error?o.message:String(o)});if(l)F=o;else{if(!A&&k.kind!=="rate-limit")throw B.length?new i(503,"upstream_model_unavailable",o instanceof Error?o.message:String(o),void 0,{served_model:p}):o;A=!0,M=_??M}}if(l){if(L===401){if(N&&Le(N.key),x===0)continue;throw new i(404,"model_unavailable",`${s.base_url} refuses this runtime's tokens`,void 0,{served_model:p})}if(A&&K(R)===void 0)throw new i(503,"upstream_model_unavailable",`${p} was rate-limited without a retry-after`,void 0,{served_model:p});if(!A&&(F!==void 0||L!==void 0&&L>=500))throw new i(503,"upstream_model_unavailable",F instanceof Error?F.message:d?.errorMessage??"inference endpoint failed",void 0,{served_model:p})}if(!A&&d?.stopReason==="error"&&ce({message:d.errorMessage}).kind==="rate-limit"&&(A=!0,M=15e3),A){const o=$e(R,a.id);if(K(R)===void 0&&o.resetAt!==void 0&&(M=Math.max(M,o.resetAt-Date.now())),b={provider:m,model:a.id,...f?{account:f.label}:{},observation:o},console.error(`[llm] 429 from ${p}${f?` account "${f.label}"`:""}: scope=${le(o.scope)} retry_after_ms=${M} headers=${JSON.stringify(o.headers)}`),f&&H(m)&&await ke(m,f.label,M,v,Date.now(),o.scope),Date.now()+Math.min(M,ae)<I&&(I=Date.now()+Math.min(M,ae),z=p),X.length||D.length)throw new i(503,"service_unavailable","vendor rate limit after output began",void 0,{served_model:p});if(l)break;continue}const U=Ce(d);if(L===400&&e.tool_choice!==void 0&&e.tool_choice!=="auto"&&e.tool_choice!=="none"&&/\btool[_ ]choice\b/i.test(d?.errorMessage??"")&&/not supported|does not support|unsupported|cannot|must be auto/i.test(d?.errorMessage??""))throw new i(400,"invalid_request",d.errorMessage,"tool_choice",{served_model:p});if(d?.stopReason==="error"){const o=He(a.provider,d.errorMessage,p);if(o)throw o}if(!d||d.stopReason==="error"&&!U||d.stopReason==="aborted")throw new i(503,"upstream_model_unavailable",d?.errorMessage??"model request failed",void 0,{served_model:p});f&&H(m)&&Re(f,a.id)&&await je(m,f.label,v,a.id);const G=d.content.filter(o=>o.type==="toolCall").map(o=>({id:o.id,type:"function",function:{name:o.name,arguments:JSON.stringify(o.arguments)}})),Z=U?"content_filter":d.stopReason==="toolUse"?"tool_calls":d.stopReason==="length"?"length":"stop",Q=d.responseModel?Ue(a,d.responseModel):void 0,S=Q?`${a.provider}/${Q.model}`:p,J={prompt_tokens:d.usage.input,completion_tokens:d.usage.output,total_tokens:d.usage.totalTokens,cache_read_tokens:d.usage.cacheRead,cache_write_tokens:d.usage.cacheWrite,usd_equivalent:Pe(Q??a,d.usage.cost.total),served_model:S};l?ue(l.grantee,"app",S,d.usage,J.usd_equivalent):w&&ue(w.grantee,"user",S,d.usage,J.usd_equivalent);const ye={id:ee,object:"chat.completion",created:Math.floor(v/1e3),model:S,served_model:S,requested_model:O,substituted:O!==S&&!/^([^/]+)\/(ultra|strong|medium|light)$/.test(O),choices:[{index:0,message:{role:"assistant",content:X.join("")||null,...D.length?{reasoning_content:D.join("")}:{},...G.length?{tool_calls:G}:{},...U?{refusal:d.errorMessage??"Content filtered"}:{}},finish_reason:Z}],usage:J,...e.metadata!==void 0?{metadata:e.metadata}:{}};for(const[o,_]of G.entries())P(T({tool_calls:[{index:o,..._}]}));return P({...T({},Z),...U?{choices:[{index:0,delta:{},finish_reason:Z,message:{refusal:d.errorMessage??"Content filtered"}}]}:{},usage:J}),{completion:ye,chunks:B}}}throw I!==1/0?new i(429,"all_routes_exhausted","all eligible model routes are rate-limited",void 0,{retry_after_s:Math.max(1,Math.ceil((I-Date.now())/1e3)),served_model:b?`${b.provider}/${b.model}`:z,...b?{rate_limit:{provider:b.provider,model:b.model,...b.account?{account:b.account}:{},scope:le(b.observation.scope),...b.observation.claim?{claim:b.observation.claim}:{},headers:b.observation.headers}}:{}},void 0,!0):e.model_policy==="exact"?new i(400,"substitution_refused","the requested model is unavailable"):new i(404,"model_unavailable","no usable model route is available")}u(lt,"runLlm");export{dt as llmCallerOf,at as parseLlmRequest,lt as runLlm};
3
+ `),l=e.tools?.map(({function:s})=>({name:s.name,description:s.description??"",parameters:s.parameters??{type:"object",properties:{}}}));return{...y?{systemPrompt:y}:{},messages:n.slice(w.length),...l?{tools:l}:{}}}u(Ue,"contextOf");function me(e,t,n,r){if(!e){const y=ae(n,r),l=Object.values({...y.modelRoutes??{},...y.legacyModelRoutes??{}}),s=l.length?[y.modelLadders.defaultProvider,...y.modelRouting?.familyOrder??[],...l.map(g=>g.family)].find(g=>l.some(E=>E.family===g)):y.modelLadders.defaultProvider??"anthropic";return{kind:"logical",family:s,strength:"strong",spec:`${s}/strong`}}const w=/^([^/]+)\/(ultra|strong|medium|light)$/.exec(e);return w?{kind:"logical",family:w[1],strength:w[2],spec:e}:{kind:t==="exact"?"exact":"concrete",spec:e}}u(me,"requestFor");function Je(e,t){const{input:n,output:r,cacheRead:w,cacheWrite:y}=e.cost;return n===0&&r===0&&w===0&&y===0?null:Number.isFinite(t)&&t>=0?t:null}u(Je,"usdEquivalent");function We(e,t){return e.compat?.allowedFallbackModels?.find(r=>r.provider===e.provider&&r.model===t)}u(We,"allowedFallback");function ct(e){return e?{payer:e.payer??"user",sub:e.sub,grantee:e.grantee,inference_endpoint:e.inference_endpoint??null}:void 0}u(ct,"llmCallerOf");function He(e){return e instanceof Ne?e.code==="server_error"?new i(503,"upstream_model_unavailable",e.message):new i(404,"model_unavailable",e.message):e}u(He,"mintFailure");const Ke=/\bmodel is not supported when using Codex with a ChatGPT account\b/i;function ze(e,t,n){if(!(e!=="openai-codex"||t===void 0||!Ke.test(t)))return new i(404,"model_unavailable",t,void 0,{served_model:n})}u(ze,"codexAccountModelRejection");async function ut(e,t,n,r,w,y){const l=y?.payer==="app"?y:void 0;if(e.payer==="app"&&!l)throw new i(403,"payer_not_app","this grant is not app-paid");if(e.payer==="user"&&l)throw new i(400,"invalid_request","this grant is app-paid; payer cannot be user","payer");if(l&&!l.inference_endpoint)throw new i(404,"model_unavailable",`${l.grantee} is app-paid but its grant carries no inference endpoint`);const s=l?.inference_endpoint??void 0;l||Oe(w);const g=await ke(),E=u(c=>c.routeId!=="concrete"&&c.routeId!=="exact","configured"),ee=u(c=>{const h=g.find(c.providerId,c.modelId);return h!==void 0&&(!e.reasoning_effort||h.reasoning)&&(e.seed===void 0&&e.response_format===void 0||h.api==="openai-completions")&&(e.stop===void 0||["openai-completions","anthropic-messages"].includes(h.api))},"matchesFeatures"),pe=u(()=>{const c=me(e.model,e.model_policy,r?.cwd,r?.profileId),h=ie(c.kind==="exact"?{kind:"concrete",spec:c.spec}:c,r?.cwd,r?.profileId).filter(E);let a;if(c.kind==="logical")a=e.model_policy==="exact"?h.filter(m=>m.family===c.family&&m.strength===c.strength).slice(0,1):h;else{const m=se(c.spec),q=h.filter(j=>j.providerId===m?.providerId&&j.modelId===m.modelId&&(e.model_policy!=="exact"||j.thinkingLevel===m.thinkingLevel)&&ee(j));if(e.model_policy==="exact")a=q.slice(0,1);else if(q.length)a=q;else{const j=ae(r?.cwd,r?.profileId),x=[...Object.values(j.modelRoutes??{}).flatMap(v=>Object.entries(v.models)),...[j.modelLadders.anthropic,j.modelLadders.openai].flatMap(v=>Object.entries(v))].find(([,v])=>v===c.spec)?.[0],f=me(void 0,"substitute",r?.cwd,r?.profileId);a=x&&f.kind==="logical"?ie({...f,strength:x,spec:c.spec},r?.cwd,r?.profileId).filter(v=>E(v)&&v.strength===x):[]}}return a},"ownerCandidates");let R;if(s?R=De(s,e.model,e.model_policy==="exact").flatMap((c,h)=>{const a=se(c.model);return a?[{routeId:"app",credentialSource:"app",family:"app",strength:c.strength,...a,rank:h}]:[]}):R=pe(),R=R.filter(ee),R.length===0)throw e.model_policy==="exact"?new i(400,"substitution_refused","no eligible model route is configured"):new i(404,"model_unavailable","no eligible model route is configured");const te=`chatcmpl-${ve()}`;let I=1/0,b,z;for(const c of R){if(!l&&!xe(c,g).authenticated)continue;const h=g.find(c.providerId,c.modelId);if(!h)continue;const a=s?{...h,baseUrl:`${s.base_url}/${h.provider}`}:h,m=c.providerId,q=!l&&H(m)?Ae(m).filter(x=>!x.authFailure):[],j=q.filter(x=>le(x,a.id)<=Date.now());if(q.length&&!j.length){const x=Math.min(...q.map(f=>le(f,a.id)));x<I&&(I=x,z=`${a.provider}/${a.id}`);continue}const oe=l?[void 0,void 0]:q.length?j:[void 0];for(const[x,f]of oe.entries()){const v=Date.now();let ne=f?.access;if(f&&f.expires<=Date.now()&&H(m)){const o=g.getProvider(m)?.auth.oauth;if(!o)throw new i(503,"upstream_model_unavailable",`no OAuth refresh for ${m}`,void 0,{served_model:`${a.provider}/${a.id}`});ne=(await $e(m,f.label,async(k,re)=>{const W=await o.refresh({type:"oauth",refresh:k,access:"",expires:0,...re?{clientId:re}:{}},t??new AbortController().signal).catch(ge=>{throw Te(ge,`${a.provider}/${a.id}`)}),V=W.clientId;return{refresh:W.refresh,access:W.access,expires:W.expires,...typeof V=="string"&&V?{clientId:V}:{}}})).access}const he=Ue(e);let N;if(l&&s)try{N=await Le({audience:s.base_url,sub:l.sub,grantee:l.grantee,initiating_app:l.grantee,scope:["crtr:llm"]},{signal:t})}catch(o){throw He(o)}const C=f||l?void 0:await g.getApiKeyAndHeaders(a);if(C&&!C.ok)continue;const p=`${a.provider}/${a.id}`,S=e.model??p;let A=!1,L,M=3e4,$;const B=[],X=[],D=[];let d,F;const T=u((o,_=null)=>({id:te,object:"chat.completion.chunk",created:Math.floor(v/1e3),model:p,served_model:p,requested_model:S,substituted:S!==p&&!/^([^/]+)\/(ultra|strong|medium|light)$/.test(S),choices:[{index:0,delta:o,finish_reason:_}]}),"chunk"),P=u(o=>{B.push(o),n?.(o)},"emit"),_e=we(a,he,{apiKey:N?.access_token??ne??(C?.ok?C.apiKey:void 0),...C?.ok?{headers:C.headers}:{},signal:t,reasoning:e.reasoning_effort??c.thinkingLevel,...e.temperature!==void 0?{temperature:e.temperature}:{},...e.max_tokens!==void 0?{maxTokens:e.max_tokens}:{},...e.top_p!==void 0?{samplingParams:{top_p:e.top_p}}:{},...e.tool_choice==="none"?{toolChoice:"none"}:{},onPayload:u(o=>{if(!o||typeof o!="object")return;const _=e.tool_choice,k=_==="required"?a.api==="anthropic-messages"?{type:"any"}:"required":typeof _=="object"&&_!==null?a.api==="anthropic-messages"?{type:"tool",name:_.function.name}:_:void 0;return{...o,...k?{tool_choice:k}:{},...e.stop!==void 0?{[a.api==="anthropic-messages"?"stop_sequences":"stop"]:typeof e.stop=="string"?[e.stop]:e.stop}:{},...e.seed!==void 0?{seed:e.seed}:{},...e.response_format!==void 0?{response_format:e.response_format}:{}}},"onPayload"),fetch:u(async(o,_)=>{const k=await fetch(o,_);return L=k.status,k.status===429&&(A=!0,$=k.headers,M=K(k.headers)??15e3),k},"fetch"),onResponse:u(o=>{o.status===429&&(A=!0,$=o.headers,M=K(o.headers)??15e3)},"onResponse")});try{for await(const o of _e)o.type==="text_delta"&&(X.push(o.delta),P(T({content:o.delta}))),o.type==="thinking_delta"&&(D.push(o.delta),P(T({reasoning_content:o.delta}))),o.type==="done"&&(d=o.message),o.type==="error"&&(d=o.error)}catch(o){const _=qe(o);$===void 0&&o&&typeof o=="object"&&"headers"in o&&Object.keys(Ce(o.headers)).length&&($=o.headers);const k=Y({status:o&&typeof o=="object"&&"status"in o?o.status:void 0,message:o instanceof Error?o.message:String(o)});if(l)F=o;else{if(!A&&k.kind!=="rate-limit")throw B.length?new i(503,"upstream_model_unavailable",o instanceof Error?o.message:String(o),void 0,{served_model:p}):o;A=!0,M=_??M}}if(l){if(L===401){if(N&&Ee(N.key),x===0)continue;throw new i(404,"model_unavailable",`${s.base_url} refuses this runtime's tokens`,void 0,{served_model:p})}if(A&&K($)===void 0)throw new i(503,"upstream_model_unavailable",`${p} was rate-limited without a retry-after`,void 0,{served_model:p});if(!A&&(F!==void 0||L!==void 0&&L>=500))throw new i(503,"upstream_model_unavailable",F instanceof Error?F.message:d?.errorMessage??"inference endpoint failed",void 0,{served_model:p})}if(!A&&d?.stopReason==="error"&&Y({message:d.errorMessage}).kind==="rate-limit"&&(A=!0,M=15e3),A){const o=Ie($,a.id);if(K($)===void 0&&o.resetAt!==void 0&&(M=Math.max(M,o.resetAt-Date.now())),b={provider:m,model:a.id,...f?{account:f.label}:{},observation:o},console.error(`[llm] 429 from ${p}${f?` account "${f.label}"`:""}: scope=${ce(o.scope)} retry_after_ms=${M} headers=${JSON.stringify(o.headers)}`),f&&H(m)&&await je(m,f.label,M,v,Date.now(),o.scope),Date.now()+Math.min(M,de)<I&&(I=Date.now()+Math.min(M,de),z=p),X.length||D.length)throw new i(503,"service_unavailable","vendor rate limit after output began",void 0,{served_model:p});if(l)break;continue}const U=Se(d);if(L===400&&e.tool_choice!==void 0&&e.tool_choice!=="auto"&&e.tool_choice!=="none"&&/\btool[_ ]choice\b/i.test(d?.errorMessage??"")&&/not supported|does not support|unsupported|cannot|must be auto/i.test(d?.errorMessage??""))throw new i(400,"invalid_request",d.errorMessage,"tool_choice",{served_model:p});if(d?.stopReason==="error"){const o=ze(a.provider,d.errorMessage,p);if(o)throw o}if(!d||d.stopReason==="error"&&!U||d.stopReason==="aborted")throw new i(503,"upstream_model_unavailable",d?.errorMessage??"model request failed",void 0,{served_model:p});f&&H(m)&&Re(f,a.id)&&await Me(m,f.label,v,a.id);const G=d.content.filter(o=>o.type==="toolCall").map(o=>({id:o.id,type:"function",function:{name:o.name,arguments:JSON.stringify(o.arguments)}})),Z=U?"content_filter":d.stopReason==="toolUse"?"tool_calls":d.stopReason==="length"?"length":"stop",Q=d.responseModel?We(a,d.responseModel):void 0,O=Q?`${a.provider}/${Q.model}`:p,J={prompt_tokens:d.usage.input,completion_tokens:d.usage.output,total_tokens:d.usage.totalTokens,cache_read_tokens:d.usage.cacheRead,cache_write_tokens:d.usage.cacheWrite,usd_equivalent:Je(Q??a,d.usage.cost.total),served_model:O};l?ue(l.grantee,"app",O,d.usage,J.usd_equivalent):w&&ue(w.grantee,"user",O,d.usage,J.usd_equivalent);const ye={id:te,object:"chat.completion",created:Math.floor(v/1e3),model:O,served_model:O,requested_model:S,substituted:S!==O&&!/^([^/]+)\/(ultra|strong|medium|light)$/.test(S),choices:[{index:0,message:{role:"assistant",content:X.join("")||null,...D.length?{reasoning_content:D.join("")}:{},...G.length?{tool_calls:G}:{},...U?{refusal:d.errorMessage??"Content filtered"}:{}},finish_reason:Z}],usage:J,...e.metadata!==void 0?{metadata:e.metadata}:{}};for(const[o,_]of G.entries())P(T({tool_calls:[{index:o,..._}]}));return P({...T({},Z),...U?{choices:[{index:0,delta:{},finish_reason:Z,message:{refusal:d.errorMessage??"Content filtered"}}]}:{},usage:J}),{completion:ye,chunks:B}}}throw I!==1/0?new i(429,"all_routes_exhausted","all eligible model routes are rate-limited",void 0,{retry_after_s:Math.max(1,Math.ceil((I-Date.now())/1e3)),served_model:b?`${b.provider}/${b.model}`:z,...b?{rate_limit:{provider:b.provider,model:b.model,...b.account?{account:b.account}:{},scope:ce(b.observation.scope),...b.observation.claim?{claim:b.observation.claim}:{},headers:b.observation.headers}}:{}},void 0,!0):e.model_policy==="exact"?new i(400,"substitution_refused","the requested model is unavailable"):new i(404,"model_unavailable","no usable model route is available")}u(ut,"runLlm");export{ct as llmCallerOf,lt as parseLlmRequest,ut as runLlm};