@north-light/crouter 0.3.321 → 0.3.323

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 (111) hide show
  1. package/bin/progress-painter.mjs +89 -0
  2. package/bin/runtime-selector.mjs +123 -4
  3. package/dist/api/client.d.ts +35 -18
  4. package/dist/api/client.js +2 -2
  5. package/dist/api/dto/broker-ops.d.ts +9 -0
  6. package/dist/api/dto/canvas.d.ts +23 -1
  7. package/dist/api/dto/modelauth.d.ts +15 -0
  8. package/dist/api/dto/nodes.d.ts +8 -0
  9. package/dist/api/errors.d.ts +6 -3
  10. package/dist/api/errors.js +1 -1
  11. package/dist/api/index.d.ts +2 -2
  12. package/dist/api/index.js +1 -1
  13. package/dist/api/node-transport.d.ts +18 -0
  14. package/dist/api/node-transport.js +1 -0
  15. package/dist/api/routes.d.ts +3 -0
  16. package/dist/api/routes.js +1 -1
  17. package/dist/builtin-memory/crouter-sdk.md +86 -0
  18. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +1 -1
  19. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +1 -1
  20. package/dist/cli.js +8 -2
  21. package/dist/clients/attach/chrome/canvas-panels.js +1 -1
  22. package/dist/clients/attach/overlays/graph.d.ts +6 -5
  23. package/dist/clients/attach/overlays/graph.js +1 -1
  24. package/dist/clients/attach/render/chat-view.d.ts +5 -1
  25. package/dist/clients/attach/render/chat-view.js +1 -1
  26. package/dist/clients/attach/session/frames.d.ts +1 -0
  27. package/dist/clients/attach/session/frames.js +1 -1
  28. package/dist/clients/attach/viewer.js +576 -576
  29. package/dist/commands/api-client.js +3 -3
  30. package/dist/commands/memory/read.js +2 -2
  31. package/dist/commands/node/create.js +3 -3
  32. package/dist/commands/sys/branch.js +1 -1
  33. package/dist/commands/sys/connect.d.ts +1 -0
  34. package/dist/commands/sys/connect.js +3 -0
  35. package/dist/commands/sys/daemon.js +1 -1
  36. package/dist/commands/sys/panels/plugins-panel.js +1 -1
  37. package/dist/commands/sys/panels/provider-panel.d.ts +4 -0
  38. package/dist/commands/sys/panels/provider-panel.js +1 -1
  39. package/dist/commands/sys/provider-login.d.ts +8 -0
  40. package/dist/commands/sys/provider-login.js +9 -0
  41. package/dist/commands/sys/setup-core.d.ts +4 -0
  42. package/dist/commands/sys/setup-core.js +7 -4
  43. package/dist/commands/sys/setup-wizard.d.ts +1 -1
  44. package/dist/commands/sys/setup-wizard.js +1 -1
  45. package/dist/commands/sys.js +1 -1
  46. package/dist/core/canvas/canvas.d.ts +24 -0
  47. package/dist/core/canvas/canvas.js +29 -15
  48. package/dist/core/canvas/migrations.js +35 -32
  49. package/dist/core/canvas/nav-model.d.ts +1 -1
  50. package/dist/core/canvas/nav-model.js +1 -1
  51. package/dist/core/canvas/nav-render.d.ts +31 -25
  52. package/dist/core/canvas/nav-render.js +1 -1
  53. package/dist/core/canvas/paths.d.ts +4 -4
  54. package/dist/core/canvas/render-source.d.ts +6 -16
  55. package/dist/core/canvas/render-source.js +9 -9
  56. package/dist/core/canvas/types.d.ts +16 -0
  57. package/dist/core/config.js +1 -1
  58. package/dist/core/provider-credential.d.ts +6 -0
  59. package/dist/core/provider-credential.js +1 -0
  60. package/dist/core/runtime/boot-root.d.ts +2 -0
  61. package/dist/core/runtime/boot-root.js +1 -1
  62. package/dist/core/runtime/broker/daemon-ops.d.ts +2 -1
  63. package/dist/core/runtime/broker/daemon-ops.js +1 -1
  64. package/dist/core/runtime/front-door-login.d.ts +2 -0
  65. package/dist/core/runtime/front-door-login.js +1 -0
  66. package/dist/core/runtime/front-door.js +7 -5
  67. package/dist/core/runtime/nerd-font.d.ts +19 -1
  68. package/dist/core/runtime/nerd-font.js +2 -2
  69. package/dist/core/runtime/progress-bar.d.ts +13 -0
  70. package/dist/core/runtime/progress-bar.js +2 -0
  71. package/dist/core/runtime/provider-credential-gate.d.ts +4 -0
  72. package/dist/core/runtime/provider-credential-gate.js +2 -0
  73. package/dist/core/runtime/spawn-env.d.ts +7 -0
  74. package/dist/core/runtime/spawn-env.js +1 -1
  75. package/dist/core/secrets.d.ts +3 -0
  76. package/dist/core/secrets.js +2 -2
  77. package/dist/core/subscription-state.d.ts +1 -1
  78. package/dist/core/subscription-state.js +3 -3
  79. package/dist/core/termrender/termrender.d.ts +3 -1
  80. package/dist/core/termrender/termrender.js +13 -13
  81. package/dist/core/user-settings.d.ts +4 -0
  82. package/dist/core/user-settings.js +1 -1
  83. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  84. package/dist/daemon/api/handlers/canvas.js +4 -4
  85. package/dist/daemon/api/handlers/health.d.ts +1 -1
  86. package/dist/daemon/api/handlers/health.js +3 -3
  87. package/dist/daemon/api/handlers/modelauth.js +1 -1
  88. package/dist/daemon/api/map.d.ts +15 -1
  89. package/dist/daemon/api/map.js +2 -2
  90. package/dist/daemon/api/server.d.ts +5 -1
  91. package/dist/daemon/api/server.js +4 -4
  92. package/dist/daemon/crtrd-cli.js +1 -1
  93. package/dist/daemon/fleet.js +1 -1
  94. package/dist/daemon/manage.d.ts +1 -0
  95. package/dist/daemon/manage.js +2 -2
  96. package/dist/pi-extensions/canvas-stophook.js +1 -1
  97. package/dist/types.d.ts +7 -0
  98. package/dist/types.js +1 -1
  99. package/docs/sdk/README.md +54 -0
  100. package/docs/sdk/client.md +92 -0
  101. package/docs/sdk/docker.md +63 -0
  102. package/docs/sdk/errors.md +85 -0
  103. package/docs/sdk/getting-started.md +160 -0
  104. package/docs/sdk/memory.md +107 -0
  105. package/docs/sdk/migration.md +108 -0
  106. package/docs/sdk/nodes.md +193 -0
  107. package/docs/sdk/resources.md +71 -0
  108. package/docs/sdk/streaming.md +124 -0
  109. package/package.json +1 -1
  110. package/runtime.lock.json +6 -6
  111. package/scripts/install-runtime.mjs +7 -3
@@ -1 +1 @@
1
- var $=Object.defineProperty;var d=(o,e)=>$(o,"name",{value:e,configurable:!0});import{matchesKey as g,truncateToWidth as a,visibleWidth as m}from"@earendil-works/pi-tui";import{formatGesture as b,matchesPiTuiInput as v}from"../../core/keybindings/index.js";import{buildSetupInitialState as S,executeSetupSubmission as P,formatSetupExecutionSummary as k,packagePlanAction as I,reconcileInboxFrontDoor as y,renderSetupStaticInstructions as x}from"./setup-core.js";import{runSetupSettingsProcess as C}from"./setup-settings-runner.js";import{DependenciesPanel as w}from"./panels/dependencies-panel.js";import{PAGE_CHROME_ROWS as D,pageFrame as L,theme as n}from"../../core/tui/panel.js";import{PluginsPanel as W}from"./panels/plugins-panel.js";import{ProviderPanel as T}from"./panels/provider-panel.js";const u=["Providers","Plugins","Dependencies"];class A{static{d(this,"SetupWizard")}bindings;terminalRows;providers;plugins;dependencies;step=0;confirming=!1;cachedWidth;cachedHeight;cachedLines;_focused=!1;installedPackageIds;onSubmit;onCancel;constructor(e,i,t,s,r,c,p,l,f){this.bindings=l,this.terminalRows=f,this.installedPackageIds=i;const h=d(()=>this.invalidate(),"invalidate");this.providers=new T(s,r,c,p),this.providers.onChange=h,this.plugins=new W(e,i,h),this.dependencies=new w(t,h)}set focused(e){this._focused=e}get focused(){return this._focused}invalidate(){this.cachedWidth=void 0,this.cachedHeight=void 0,this.cachedLines=void 0}matches(e,i){return v(this.bindings,e,i,(t,s)=>g(t,s))}label(e){const i=this.bindings.gestures(e);return i.length===0?"disabled":b(i[0].split(" > ").pop())}fieldSafeLabel(e){const i=this.bindings.gestures(e).filter(t=>{if(t.includes(" > "))return!0;const s=t.split("+").pop();return!(s==="up"||s==="down"||s==="left"||s==="right")&&(s.length>1||t.includes("+"))});return i.length===0?"Disabled":i.map(b).join(" / ")}setStep(e){this.step=e,this.invalidate()}moveStep(e){this.setStep((this.step+e+u.length)%u.length)}advance(){this.step===2?this.finalize():this.moveStep(1)}cancel(){if(this.confirming){this.confirming=!1,this.invalidate();return}this.onCancel?.()}dispose(){this.providers.dispose()}hasPendingInstalls(){return this.plugins.selected.some(e=>!this.installedPackageIds.has(e.id))||this.dependencies.selected.length>0}buildSubmission(){return{packages:[...this.plugins.selected],installedPackageIds:new Set(this.installedPackageIds),systemDeps:[...this.dependencies.selected]}}finalize(){if(this.confirming||!this.hasPendingInstalls()){this.onSubmit?.(this.buildSubmission());return}this.confirming=!0,this.invalidate()}currentPanel(){return this.step===0?this.providers:this.step===1?this.plugins:this.dependencies}handleInput(e){const i=this.currentPanel(),t=d((r,c)=>this.matches(r,c),"match");if(this.step===0&&this.providers.isNestedFlowActive()){i.handleInput(e,t)&&this.invalidate();return}if(this.confirming){this.matches("crtr.setup.confirm.accept",e)?this.onSubmit?.(this.buildSubmission()):this.matches("crtr.setup.confirm.back",e)&&(this.confirming=!1,this.invalidate());return}if(this.matches("crtr.setup.cancel",e)){this.cancel();return}if(this.matches("crtr.setup.tab-next",e)){this.moveStep(1);return}if(this.matches("crtr.setup.tab-previous",e)){this.moveStep(-1);return}if(i.handleInput(e,t)){this.invalidate();return}this.matches("crtr.setup.advance",e)&&this.advance()}renderTrail(e){const t=u.map((s,r)=>{if(r===this.step)return n.bg("selectedBg",` ${r+1} ${s} `);const c=r<this.step?n.fg("success","\u2713"):`${r+1}`;return n.fg("dim",` ${c} ${s} `)}).join(n.fg("dim","\u203A"));return m(t)<=e?[a(t,e),""]:[a(`${n.fg("dim",`Step ${this.step+1} of ${u.length}`)} ${n.fg("accent",n.bold(u[this.step]))}`,e),""]}footer(e){const i=`${this.fieldSafeLabel("crtr.setup.tab-next")}/${this.fieldSafeLabel("crtr.setup.tab-previous")} step \xB7 ${this.label("crtr.setup.cancel")} cancel`,t=`${this.label("crtr.setup.list-down")}/${this.label("crtr.setup.list-up")}`;let s;this.confirming?s=`${this.label("crtr.setup.confirm.accept")} confirm \xB7 ${this.label("crtr.setup.confirm.back")} go back`:this.step===0?s=this.providers.isNestedFlowActive()?"OAuth in progress \xB7 esc cancel":`${t} select \xB7 a add \xB7 p prefer \xB7 r rename \xB7 l re-login \xB7 x remove \xB7 ${this.label("crtr.setup.advance")} next`:this.step===1?s=`${t} move \xB7 ${this.label("crtr.setup.toggle")} toggle \xB7 ${this.label("crtr.setup.details")} details \xB7 ${this.label("crtr.setup.advance")} next`:s=`${t} move \xB7 ${this.label("crtr.setup.toggle")} toggle \xB7 ${this.label("crtr.setup.advance")} finish`;const r=e-m(s)-m(i);return r>=2?`${n.fg("dim",s)}${" ".repeat(r)}${n.fg("dim",i)}`:n.fg("dim",s)}renderConfirm(e){const i=this.buildSubmission(),t=[a(n.fg("warning",n.bold("Confirm installs")),e),""];if(i.packages.length===0&&i.systemDeps.length===0)return[...t,a(n.fg("success",`Nothing to install; ${this.label("crtr.setup.confirm.accept")} finish.`),e)];if(i.packages.length){t.push(a(n.fg("accent","Packages"),e));for(const s of i.packages)t.push(a(` \u2022 ${s.name} ${n.fg("dim","\u2192")} ${this.installedPackageIds.has(s.id)?n.fg("success","skip (already installed)"):n.fg("muted",I(s))}`,e))}if(i.systemDeps.length){t.push(a(n.fg("accent","System deps"),e));for(const s of i.systemDeps)t.push(a(` \u2022 ${s.tool} ${n.fg("dim","\u2192")} ${n.fg("muted",s.command??s.hint)}`,e))}return t}render(e){const i=this.step===0,t=this.terminalRows();if(!i&&this.cachedLines&&this.cachedWidth===e&&this.cachedHeight===t)return this.cachedLines;const s=this.currentPanel(),r=Math.max(1,t-D),c=this.confirming||r<=2?[]:this.renderTrail(e),p=Math.max(1,r-c.length),l=L({width:e,height:t,title:"crouter setup",meta:this.confirming?"review":`step ${this.step+1} of ${u.length}`,body:[...c,...this.confirming?this.renderConfirm(e):s.render(e,p)],footer:this.footer(e)});return i||(this.cachedWidth=e,this.cachedHeight=t,this.cachedLines=l),l}}async function j(){const o=S();if(await y(),!process.stdout.isTTY){process.stdout.write(x(o));return}const e=await C(({tui:t,terminal:s,agentDir:r,runtime:c,registry:p,bindings:l},f)=>{const h=new A(o.manifest,o.installedPackageIds,o.systemPlans,t,r,c,p,l,()=>s.rows);return h.onCancel=f.cancel,h.onSubmit=f.submit,h},(t,s)=>t.length>0&&t.charCodeAt(0)<32&&v(s,"crtr.setup.cancel",t,(r,c)=>g(r,c)));if(e===void 0)return;const i=await P(e);process.stdout.write(k(i))}d(j,"runSetup");export{A as SetupWizard,j as runSetup};
1
+ var S=Object.defineProperty;var p=(o,e)=>S(o,"name",{value:e,configurable:!0});import{matchesKey as b,truncateToWidth as a,visibleWidth as g}from"@earendil-works/pi-tui";import{formatGesture as v,matchesPiTuiInput as $}from"../../core/keybindings/index.js";import{buildSetupInitialState as P,executeSetupSubmission as k,formatSetupExecutionSummary as I,packagePlanAction as y,reconcileInboxFrontDoor as w,renderSetupStaticInstructions as x}from"./setup-core.js";import{runSetupSettingsProcess as C}from"./setup-settings-runner.js";import{DependenciesPanel as W}from"./panels/dependencies-panel.js";import{PAGE_CHROME_ROWS as D,pageFrame as L,theme as n}from"../../core/tui/panel.js";import{PluginsPanel as A}from"./panels/plugins-panel.js";import{ProviderPanel as H}from"./panels/provider-panel.js";const d=["Providers","Plugins","Dependencies"];class T{static{p(this,"SetupWizard")}bindings;terminalRows;providers;plugins;dependencies;step=0;confirming=!1;cachedWidth;cachedHeight;cachedLines;_focused=!1;installedPackageIds;onSubmit;onCancel;constructor(e,i,s,t,r,c,l,u,f){this.bindings=u,this.terminalRows=f,this.installedPackageIds=i;const h=p(()=>this.invalidate(),"invalidate");this.providers=new H(t,r,c,l),this.providers.onChange=h,this.plugins=new A(e,i,h),this.dependencies=new W(s,h)}set focused(e){this._focused=e}get focused(){return this._focused}invalidate(){this.cachedWidth=void 0,this.cachedHeight=void 0,this.cachedLines=void 0}matches(e,i){return $(this.bindings,e,i,(s,t)=>b(s,t))}label(e){const i=this.bindings.gestures(e);return i.length===0?"disabled":v(i[0].split(" > ").pop())}fieldSafeLabel(e){const i=this.bindings.gestures(e).filter(s=>{if(s.includes(" > "))return!0;const t=s.split("+").pop();return!(t==="up"||t==="down"||t==="left"||t==="right")&&(t.length>1||s.includes("+"))});return i.length===0?"Disabled":i.map(v).join(" / ")}setStep(e){this.step=e,this.invalidate()}moveStep(e){this.setStep((this.step+e+d.length)%d.length)}advance(){this.step===2?this.finalize():this.moveStep(1)}cancel(){if(this.confirming){this.confirming=!1,this.invalidate();return}this.onCancel?.()}dispose(){this.providers.dispose()}hasPendingInstalls(){return this.plugins.selected.some(e=>!this.installedPackageIds.has(e.id))||this.dependencies.selected.length>0}buildSubmission(){return{packages:[...this.plugins.selected],installedPackageIds:new Set(this.installedPackageIds),systemDeps:[...this.dependencies.selected]}}finalize(){if(this.confirming||!this.hasPendingInstalls()){this.onSubmit?.(this.buildSubmission());return}this.confirming=!0,this.invalidate()}currentPanel(){return this.step===0?this.providers:this.step===1?this.plugins:this.dependencies}handleInput(e){const i=this.currentPanel(),s=p((r,c)=>this.matches(r,c),"match");if(this.step===0&&this.providers.isNestedFlowActive()){i.handleInput(e,s)&&this.invalidate();return}if(this.confirming){this.matches("crtr.setup.confirm.accept",e)?this.onSubmit?.(this.buildSubmission()):this.matches("crtr.setup.confirm.back",e)&&(this.confirming=!1,this.invalidate());return}if(this.matches("crtr.setup.cancel",e)){this.cancel();return}if(this.matches("crtr.setup.tab-next",e)){this.moveStep(1);return}if(this.matches("crtr.setup.tab-previous",e)){this.moveStep(-1);return}if(i.handleInput(e,s)){this.invalidate();return}this.matches("crtr.setup.advance",e)&&this.advance()}renderTrail(e){const s=d.map((t,r)=>{if(r===this.step)return n.bg("selectedBg",` ${r+1} ${t} `);const c=r<this.step?n.fg("success","\u2713"):`${r+1}`;return n.fg("dim",` ${c} ${t} `)}).join(n.fg("dim","\u203A"));return g(s)<=e?[a(s,e),""]:[a(`${n.fg("dim",`Step ${this.step+1} of ${d.length}`)} ${n.fg("accent",n.bold(d[this.step]))}`,e),""]}footer(e){const i=`${this.fieldSafeLabel("crtr.setup.tab-next")}/${this.fieldSafeLabel("crtr.setup.tab-previous")} step \xB7 ${this.label("crtr.setup.cancel")} cancel`,s=`${this.label("crtr.setup.list-down")}/${this.label("crtr.setup.list-up")}`;let t;this.confirming?t=`${this.label("crtr.setup.confirm.accept")} confirm \xB7 ${this.label("crtr.setup.confirm.back")} go back`:this.step===0?t=this.providers.isNestedFlowActive()?"OAuth in progress \xB7 esc cancel":`${s} select \xB7 a add \xB7 p prefer \xB7 r rename \xB7 l re-login \xB7 x remove \xB7 ${this.label("crtr.setup.advance")} next`:this.step===1?t=`${s} move \xB7 ${this.label("crtr.setup.toggle")} toggle \xB7 ${this.label("crtr.setup.details")} details \xB7 ${this.label("crtr.setup.advance")} next`:t=`${s} move \xB7 ${this.label("crtr.setup.toggle")} toggle \xB7 ${this.label("crtr.setup.advance")} finish`;const r=e-g(t)-g(i);return r>=2?`${n.fg("dim",t)}${" ".repeat(r)}${n.fg("dim",i)}`:n.fg("dim",t)}renderConfirm(e){const i=this.buildSubmission(),s=[a(n.fg("warning",n.bold("Confirm installs")),e),""];if(i.packages.length===0&&i.systemDeps.length===0)return[...s,a(n.fg("success",`Nothing to install; ${this.label("crtr.setup.confirm.accept")} finish.`),e)];if(i.packages.length){s.push(a(n.fg("accent","Packages"),e));for(const t of i.packages)s.push(a(` \u2022 ${t.name} ${n.fg("dim","\u2192")} ${this.installedPackageIds.has(t.id)?n.fg("success","skip (already installed)"):n.fg("muted",y(t))}`,e))}if(i.systemDeps.length){s.push(a(n.fg("accent","System deps"),e));for(const t of i.systemDeps)s.push(a(` \u2022 ${t.tool} ${n.fg("dim","\u2192")} ${n.fg("muted",t.command??t.hint)}`,e))}return s}render(e){const i=this.step===0,s=this.terminalRows();if(!i&&this.cachedLines&&this.cachedWidth===e&&this.cachedHeight===s)return this.cachedLines;const t=this.currentPanel(),r=Math.max(1,s-D),c=this.confirming||r<=2?[]:this.renderTrail(e),l=Math.max(1,r-c.length),u=L({width:e,height:s,title:"crouter setup",meta:this.confirming?"review":`step ${this.step+1} of ${d.length}`,body:[...c,...this.confirming?this.renderConfirm(e):t.render(e,l)],footer:this.footer(e)});return i||(this.cachedWidth=e,this.cachedHeight=s,this.cachedLines=u),u}}function E(){process.stdout.write("\x1B[2J\x1B[H")}p(E,"clearWizardFrame");async function B(){const o=P();let e=!1;if(await w(),!process.stdout.isTTY)return process.stdout.write(x(o)),"skipped";const i=await C(({tui:t,terminal:r,agentDir:c,runtime:l,registry:u,bindings:f},h)=>{const m=new T(o.manifest,o.installedPackageIds,o.systemPlans,t,c,l,u,f,()=>r.rows);return m.onCancel=h.cancel,m.onSubmit=h.submit,m},(t,r)=>t===""?(e=!0,!0):t.length>0&&t.charCodeAt(0)<32&&$(r,"crtr.setup.cancel",t,(c,l)=>b(c,l)));if(E(),e){const t=new Error("Interrupted");throw t.name="AbortError",t}if(i===void 0)return"skipped";const s=await k(i);return process.stdout.write(I(s)),"completed"}p(B,"runSetup");export{T as SetupWizard,B as runSetup};
@@ -1 +1 @@
1
- var s=Object.defineProperty;var r=(o,m)=>s(o,"name",{value:m,configurable:!0});import{defineSysBranch as t}from"./sys/branch.js";import{configBranch as e}from"./sys/config.js";import{daemonBranch as f}from"./sys/daemon.js";import{sysDoctorLeaf as i}from"./sys/doctor.js";import{sysFeedbackLeaf as a}from"./sys/feedback.js";import{sysLogsLeaf as p}from"./sys/logs.js";import{sysWorktreesLeaf as n}from"./sys/worktrees.js";import{sysSettingsLeaf as y}from"./sys/settings.js";import{sysSetupLeaf as c}from"./sys/setup.js";import{supportBranch as L}from"./sys/support.js";import{contextBranch as h}from"./sys/context.js";import{sysSyncBranch as B}from"./sys/sync.js";import{sysMigrateLeaf as g}from"./sys/migrate.js";import{sysUpdateLeaf as S,sysVersionLeaf as d}from"./sys/update.js";function z(){return t([y,e,c,i,h,a,p,n,L,S,d,g,B,f])}r(z,"registerSys");export{z as registerSys};
1
+ var s=Object.defineProperty;var r=(o,m)=>s(o,"name",{value:m,configurable:!0});import{defineSysBranch as t}from"./sys/branch.js";import{configBranch as e}from"./sys/config.js";import{daemonBranch as f}from"./sys/daemon.js";import{sysDoctorLeaf as i}from"./sys/doctor.js";import{sysFeedbackLeaf as a}from"./sys/feedback.js";import{sysLogsLeaf as p}from"./sys/logs.js";import{sysWorktreesLeaf as n}from"./sys/worktrees.js";import{sysSettingsLeaf as y}from"./sys/settings.js";import{sysConnectLeaf as c}from"./sys/connect.js";import{sysSetupLeaf as L}from"./sys/setup.js";import{supportBranch as h}from"./sys/support.js";import{contextBranch as B}from"./sys/context.js";import{sysSyncBranch as g}from"./sys/sync.js";import{sysMigrateLeaf as S}from"./sys/migrate.js";import{sysUpdateLeaf as d,sysVersionLeaf as u}from"./sys/update.js";function A(){return t([y,e,c,L,i,B,a,p,n,h,d,u,S,g,f])}r(A,"registerSys");export{A as registerSys};
@@ -92,6 +92,30 @@ export declare function listNodesByProfile(profileId: string): NodeMeta[];
92
92
  /** All rows, optionally filtered by status and terminal execution traces. Unclaimed warm spares are excluded. */
93
93
  /** Every node's durable memory-resolution coordinates, including unclaimed warm-pool spares. */
94
94
  export declare function listNodeMemoryTargets(): NodeMemoryTarget[];
95
+ export declare function updateNodeTelemetry(nodeId: string, telemetry: {
96
+ tokensIn: number;
97
+ contextTokens: number | null;
98
+ lastActivity: string | null;
99
+ updatedAt: string;
100
+ }): void;
101
+ export interface GraphNodeRow {
102
+ node_id: string;
103
+ name: string;
104
+ description: string | null;
105
+ cycles: number | null;
106
+ kind: string;
107
+ status: NodeStatus;
108
+ frozen_at: string | null;
109
+ pi_pid: number | null;
110
+ telemetry_context_tokens: number | null;
111
+ telemetry_last_activity: string | null;
112
+ fault: NodeRow['fault'];
113
+ streaming: boolean;
114
+ }
115
+ /** Stored fields the attach graph displays, plus the two live execution cues it
116
+ * needs. This keeps the interactive graph off the full node-summary projection
117
+ * and its unused runtime, outcome, and placement fields. */
118
+ export declare function graphNodes(): GraphNodeRow[];
95
119
  export declare function listNodes(filter?: {
96
120
  status?: NodeStatus | NodeStatus[];
97
121
  withRecordedPid?: boolean;
@@ -1,29 +1,43 @@
1
- var k=Object.defineProperty;var o=(e,n)=>k(e,"name",{value:n,configurable:!0});import{envNodeId as O}from"../../shared/env.js";import{existsSync as F,realpathSync as H,rmSync as R,statSync as j}from"node:fs";import{join as I,resolve as U}from"node:path";import{openDb as s,withCanvasWrite as p}from"./db.js";import{activateArmedExternalActionDelivery as M,armExternalActionDelivery as P}from"./deliveries.js";import{findNodeBySessionFileSql as C}from"./sessions.js";import{hydrateFault as $}from"./recovery.js";import{hasUnreconciledWorktree as B,openWorktree as z,readWorktree as J,worktreeFromRow as Y}from"./worktrees.js";import{isPidAlive as h,recordedPidLiveness as q}from"./pid.js";import{ensureHome as V,ensureNodeDirs as G,jobDir as K,nodeDir as S}from"./paths.js";function f(e,n){if(e==null)return null;const t=JSON.stringify(e);if(t===void 0)throw new TypeError(`${n} must be JSON-serializable`);return t}o(f,"jsonValue");function y(e,n,t){P(e,{destinationId:t.actionName,adapter:{adapter:"subprocess",argv:t.argv,cwd:t.cwd,config_origin:t.configOrigin,payload:t.payload??null},idempotencyKey:`node-outcome:${n}`})}o(y,"insertArmedOutcomeDelivery");function Q(e,n){n.prepare('INSERT INTO nodes (node_id, name, description, title, icon, cycles, kind, mode, lifecycle, cwd, host_kind, profile_id, parent, spawned_by, creator, fork_from, fork_source_file, created, passive_default, cycle_pending, model_override, persona_ack_json, review_binding_json, launch_config_json, status, intent, waiting_for, final_report, finalized_at, deadline_at, "window", tmux_session, pane) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)').run(e.node_id,e.name,e.description??null,e.title??null,e.icon??null,e.cycles??null,e.kind,e.mode,e.lifecycle,e.cwd,e.host_kind??null,e.profile_id??null,e.parent??null,e.spawned_by??null,e.creator??null,e.fork_from??null,e.fork_source_file??null,e.created,e.passive_default===!0?1:0,e.cycle_pending===!0?1:0,e.model_override??null,f(e.persona_ack,"persona_ack"),f(e.review_binding,"review_binding"),f(e.launch,"launch"),e.status??"active",e.intent??null,e.waiting_for??null,e.final_report??null,e.finalized_at??null,e.deadline_at??null,e.window??null,e.tmux_session??null,e.pane??null)}o(Q,"seedRow");function X(e){if(e.fault_id==null)return null;const n=Object.entries(e).filter(([t])=>t.startsWith("fault_")).map(([t,r])=>[t==="fault_id"?t:t.slice(6),r]);return $(Object.fromEntries(n))}o(X,"faultFrom");function _(e){const n={node_id:e.node_id,name:e.name,description:e.description??void 0,cycles:e.cycles??void 0,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind??null,profile_id:e.profile_id??null,parent:e.parent??null,created:e.created,intent:e.intent??null,waiting_for:e.waiting_for??null,frozen_at:e.frozen_at??null,respawn_failures:e.respawn_failures??0,respawn_not_before:e.respawn_not_before??null,launched_at:e.launched_at??null,last_settled_at:e.last_settled_at??null,terminal_reason:e.terminal_reason??null,final_report:e.final_report??null,finalized_at:e.finalized_at??null,outcome_kind:e.outcome_kind??null,outcome_reason:e.outcome_reason??null,outcome_at:e.outcome_at??null,outcome_revision:e.outcome_revision??0,outcome_detail_json:e.outcome_detail_json??null,deadline_at:e.deadline_at??null,pi_pid:e.pi_pid??null,pi_pid_identity:e.pi_pid_identity??null,window:e.window??null,tmux_session:e.tmux_session??null,pane:e.pane??null,fault:null,streaming:!1},t=n.pi_pid===null?!1:h(n.pi_pid),r=X(e);return n.fault=r?.link==="pi\u2192provider"&&r.retry.by==="daemon"&&r.retry.disposition==="auto"&&!t?null:r,n.streaming=e.turn_open_at!==null&&e.turn_closed_at===null&&t,n}o(_,"rowFrom");function T(e,n=J(e.node_id)){return{..._(e),title:e.title??void 0,icon:e.icon??void 0,spawned_by:e.spawned_by??null,creator:e.creator??null,fork_from:e.fork_from??null,fork_source_file:e.fork_source_file??null,passive_default:e.passive_default===1,cycle_pending:e.cycle_pending===1,model_override:e.model_override??null,persona_ack:e.persona_ack_json==null?void 0:JSON.parse(e.persona_ack_json),review_binding:e.review_binding_json==null?void 0:JSON.parse(e.review_binding_json),launch:e.launch_config_json==null?void 0:JSON.parse(e.launch_config_json),pi_session_id:e.pi_session_id??null,pi_session_file:e.pi_session_file??null,...n===null?{}:{managed_worktree:n}}}o(T,"metaFrom");function Ee(e,n={}){return V(),p(t=>{Q(e,t),e.managed_worktree!==void 0&&e.managed_worktree!==null&&z(e.node_id,e.managed_worktree,t),n.outcomeDelivery!==void 0&&y(t,e.node_id,n.outcomeDelivery)}),G(e.node_id),E(e.node_id)}o(Ee,"createNode");function E(e){const n=s().prepare("SELECT * FROM node_rows WHERE node_id = ?").get(e);return n===void 0?null:T(n)}o(E,"getNode");function me(e){const n=U(e);return F(n)?H(n):n}o(me,"canonicalSessionFile");function we(e){const n=C(e);return n===null?null:E(n)}o(we,"findNodeBySessionFile");function Ne(e){const n=s().prepare("SELECT * FROM node_rows WHERE node_id = ?").get(e);return n?_(n):null}o(Ne,"getRow");function Re(e){const n=s().prepare("SELECT * FROM node_rows WHERE pane = ?").get(e);return n?_(n):null}o(Re,"getRowByPane");function Se(e){return s().prepare(`SELECT * FROM node_rows
1
+ var F=Object.defineProperty;var o=(e,n)=>F(e,"name",{value:n,configurable:!0});import{envNodeId as O}from"../../shared/env.js";import{existsSync as H,realpathSync as j,rmSync as N,statSync as I}from"node:fs";import{join as U,resolve as M}from"node:path";import{openDb as d,withCanvasWrite as _}from"./db.js";import{activateArmedExternalActionDelivery as C,armExternalActionDelivery as P}from"./deliveries.js";import{findNodeBySessionFileSql as $}from"./sessions.js";import{hydrateFault as B}from"./recovery.js";import{hasUnreconciledWorktree as z,openWorktree as Y,readWorktree as J,worktreeFromRow as q}from"./worktrees.js";import{isPidAlive as y,recordedPidLiveness as V}from"./pid.js";import{ensureHome as G,ensureNodeDirs as K,jobDir as Q,nodeDir as S}from"./paths.js";function f(e,n){if(e==null)return null;const t=JSON.stringify(e);if(t===void 0)throw new TypeError(`${n} must be JSON-serializable`);return t}o(f,"jsonValue");function h(e,n,t){P(e,{destinationId:t.actionName,adapter:{adapter:"subprocess",argv:t.argv,cwd:t.cwd,config_origin:t.configOrigin,payload:t.payload??null},idempotencyKey:`node-outcome:${n}`})}o(h,"insertArmedOutcomeDelivery");function X(e,n){n.prepare('INSERT INTO nodes (node_id, name, description, title, icon, cycles, kind, mode, lifecycle, cwd, host_kind, profile_id, parent, spawned_by, creator, fork_from, fork_source_file, created, passive_default, cycle_pending, model_override, persona_ack_json, review_binding_json, launch_config_json, status, intent, waiting_for, final_report, finalized_at, deadline_at, "window", tmux_session, pane) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)').run(e.node_id,e.name,e.description??null,e.title??null,e.icon??null,e.cycles??null,e.kind,e.mode,e.lifecycle,e.cwd,e.host_kind??null,e.profile_id??null,e.parent??null,e.spawned_by??null,e.creator??null,e.fork_from??null,e.fork_source_file??null,e.created,e.passive_default===!0?1:0,e.cycle_pending===!0?1:0,e.model_override??null,f(e.persona_ack,"persona_ack"),f(e.review_binding,"review_binding"),f(e.launch,"launch"),e.status??"active",e.intent??null,e.waiting_for??null,e.final_report??null,e.finalized_at??null,e.deadline_at??null,e.window??null,e.tmux_session??null,e.pane??null)}o(X,"seedRow");function T(e){if(e.fault_id==null)return null;const n=Object.entries(e).filter(([t])=>t.startsWith("fault_")).map(([t,r])=>[t==="fault_id"?t:t.slice(6),r]);return B(Object.fromEntries(n))}o(T,"faultFrom");function p(e){const n={node_id:e.node_id,name:e.name,description:e.description??void 0,cycles:e.cycles??void 0,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind??null,profile_id:e.profile_id??null,parent:e.parent??null,created:e.created,intent:e.intent??null,waiting_for:e.waiting_for??null,frozen_at:e.frozen_at??null,respawn_failures:e.respawn_failures??0,respawn_not_before:e.respawn_not_before??null,launched_at:e.launched_at??null,last_settled_at:e.last_settled_at??null,terminal_reason:e.terminal_reason??null,final_report:e.final_report??null,finalized_at:e.finalized_at??null,outcome_kind:e.outcome_kind??null,outcome_reason:e.outcome_reason??null,outcome_at:e.outcome_at??null,outcome_revision:e.outcome_revision??0,outcome_detail_json:e.outcome_detail_json??null,deadline_at:e.deadline_at??null,telemetry_tokens_in:e.telemetry_tokens_in??null,telemetry_context_tokens:e.telemetry_context_tokens??null,telemetry_last_activity:e.telemetry_last_activity??null,telemetry_updated_at:e.telemetry_updated_at??null,pi_pid:e.pi_pid??null,pi_pid_identity:e.pi_pid_identity??null,window:e.window??null,tmux_session:e.tmux_session??null,pane:e.pane??null,fault:null,streaming:!1},t=n.pi_pid===null?!1:y(n.pi_pid),r=T(e);return n.fault=r?.link==="pi\u2192provider"&&r.retry.by==="daemon"&&r.retry.disposition==="auto"&&!t?null:r,n.streaming=e.turn_open_at!==null&&e.turn_closed_at===null&&t,n}o(p,"rowFrom");function D(e,n=J(e.node_id)){return{...p(e),title:e.title??void 0,icon:e.icon??void 0,spawned_by:e.spawned_by??null,creator:e.creator??null,fork_from:e.fork_from??null,fork_source_file:e.fork_source_file??null,passive_default:e.passive_default===1,cycle_pending:e.cycle_pending===1,model_override:e.model_override??null,persona_ack:e.persona_ack_json==null?void 0:JSON.parse(e.persona_ack_json),review_binding:e.review_binding_json==null?void 0:JSON.parse(e.review_binding_json),launch:e.launch_config_json==null?void 0:JSON.parse(e.launch_config_json),pi_session_id:e.pi_session_id??null,pi_session_file:e.pi_session_file??null,...n===null?{}:{managed_worktree:n}}}o(D,"metaFrom");function Ee(e,n={}){return G(),_(t=>{X(e,t),e.managed_worktree!==void 0&&e.managed_worktree!==null&&Y(e.node_id,e.managed_worktree,t),n.outcomeDelivery!==void 0&&h(t,e.node_id,n.outcomeDelivery)}),K(e.node_id),E(e.node_id)}o(Ee,"createNode");function E(e){const n=d().prepare("SELECT * FROM node_rows WHERE node_id = ?").get(e);return n===void 0?null:D(n)}o(E,"getNode");function me(e){const n=M(e);return H(n)?j(n):n}o(me,"canonicalSessionFile");function we(e){const n=$(e);return n===null?null:E(n)}o(we,"findNodeBySessionFile");function Re(e){const n=d().prepare("SELECT * FROM node_rows WHERE node_id = ?").get(e);return n?p(n):null}o(Re,"getRow");function Ne(e){const n=d().prepare("SELECT * FROM node_rows WHERE pane = ?").get(e);return n?p(n):null}o(Ne,"getRowByPane");function ye(e){return d().prepare(`SELECT * FROM node_rows
2
2
  WHERE deadline_at IS NOT NULL AND outcome_at IS NULL
3
3
  AND deadline_at <= ? AND status IN ('active','idle') AND kind != 'human'
4
- ORDER BY deadline_at, created, node_id`).all(e).map(_)}o(Se,"dueNodeDeadlines");function ge(e,n){return Number(s().prepare("UPDATE nodes SET deadline_at = ? WHERE node_id = ?").run(n,e).changes)===1}o(ge,"setNodeDeadline");function Oe(e,n){return!Number.isFinite(n)||n<=0?0:p(t=>{const r=t.prepare(`SELECT node_id, deadline_at FROM nodes
5
- WHERE profile_id = ? AND deadline_at IS NOT NULL AND status IN ('active', 'idle')`).all(e),i=t.prepare("UPDATE nodes SET deadline_at = ? WHERE node_id = ? AND deadline_at = ?");let d=0;for(const a of r){const u=Date.parse(a.deadline_at);Number.isNaN(u)||(d+=Number(i.run(new Date(u+n).toISOString(),a.node_id,a.deadline_at).changes))}return d})}o(Oe,"shiftProfileNodeDeadlines");function Z(e,n){if(e==null)return null;if(typeof e=="string"||typeof e=="number"||typeof e=="bigint"||e instanceof Uint8Array)return e;throw new TypeError(`${n} must be a SQLite scalar`)}o(Z,"sqlInput");function he(e,n){const t=[],r=o((d,a=d)=>{Object.prototype.hasOwnProperty.call(n,d)&&t.push([a,Z(n[d],d)])},"add");if(r("name"),r("description"),r("title"),r("icon"),r("cycles"),r("kind"),r("mode"),r("lifecycle"),r("cwd"),r("host_kind"),r("profile_id"),r("parent"),r("spawned_by"),r("creator"),r("fork_from"),r("fork_source_file"),r("model_override"),Object.prototype.hasOwnProperty.call(n,"passive_default")&&t.push(["passive_default",n.passive_default===!0?1:0]),Object.prototype.hasOwnProperty.call(n,"cycle_pending")&&t.push(["cycle_pending",n.cycle_pending===!0?1:0]),Object.prototype.hasOwnProperty.call(n,"persona_ack")&&t.push(["persona_ack_json",f(n.persona_ack,"persona_ack")]),Object.prototype.hasOwnProperty.call(n,"review_binding")&&t.push(["review_binding_json",f(n.review_binding,"review_binding")]),Object.prototype.hasOwnProperty.call(n,"launch")&&t.push(["launch_config_json",f(n.launch,"launch")]),t.length===0){const d=E(e);if(d===null)throw new Error(`unknown node: ${e}`);return d}if(s().prepare(`UPDATE nodes SET ${t.map(([d])=>`${d} = ?`).join(", ")} WHERE node_id = ?`).run(...t.map(([,d])=>d),e).changes!==1)throw new Error(`unknown node: ${e}`);return E(e)}o(he,"updateNode");function ye(e,n){s().prepare("UPDATE nodes SET status = ? WHERE node_id = ?").run(n,e)}o(ye,"setStatus");function Te(e,n){s().prepare("UPDATE nodes SET intent = ? WHERE node_id = ?").run(n??null,e)}o(Te,"setIntent");function De(e,n,t={}){if(t.outcome===void 0){const i=[],d=[];Object.prototype.hasOwnProperty.call(n,"status")&&(i.push("status = ?"),d.push(n.status??null)),Object.prototype.hasOwnProperty.call(n,"intent")&&(i.push("intent = ?"),d.push(n.intent??null)),Object.prototype.hasOwnProperty.call(n,"terminal_reason")&&(i.push("terminal_reason = ?"),d.push(n.terminal_reason??null));const a=["node_id = ?"];d.push(e),t.fromStatuses!==void 0&&(a.push(`status IN (${t.fromStatuses.map(()=>"?").join(", ")})`),d.push(...t.fromStatuses)),t.requireNoFinalReport===!0&&a.push("final_report IS NULL");const u=s().prepare(`UPDATE nodes SET ${i.join(", ")} WHERE ${a.join(" AND ")}`).run(...d);return Number(u.changes)}const r=t.outcome;return p(i=>{const d=[],a=[];Object.prototype.hasOwnProperty.call(n,"status")&&(d.push("status = ?"),a.push(n.status??null)),Object.prototype.hasOwnProperty.call(n,"intent")&&(d.push("intent = ?"),a.push(n.intent??null)),Object.prototype.hasOwnProperty.call(n,"terminal_reason")&&(d.push("terminal_reason = ?"),a.push(n.terminal_reason??null));const u=o((re,W)=>r.supersede===!0?"?":`CASE WHEN outcome_at IS NULL THEN ? ELSE ${W} END`,"outcomeValue");d.push(`outcome_kind = ${u(r.kind,"outcome_kind")}`,`outcome_reason = ${u(r.reason,"outcome_reason")}`,`outcome_detail_json = ${u(r.detailJson,"outcome_detail_json")}`,`outcome_revision = ${r.supersede===!0?"outcome_revision + 1":"CASE WHEN outcome_at IS NULL THEN outcome_revision + 1 ELSE outcome_revision END"}`,`outcome_at = ${u(r.at,"outcome_at")}`),a.push(r.kind,r.reason,r.detailJson,r.at);const c=["node_id = ?"];a.push(e),t.fromStatuses!==void 0&&(c.push(`status IN (${t.fromStatuses.map(()=>"?").join(", ")})`),a.push(...t.fromStatuses)),t.requireNoFinalReport===!0&&c.push("final_report IS NULL");const l=i.prepare(`UPDATE nodes SET ${d.join(", ")} WHERE ${c.join(" AND ")}`).run(...a);if(Number(l.changes)===0)return 0;const N=i.prepare("SELECT outcome_at FROM nodes WHERE node_id = ?").get(e);return(r.supersede===!0||N.outcome_at===r.at)&&r.documentJson!==null&&r.documentJson!==void 0&&M(i,{idempotencyKey:`node-outcome:${e}`,label:e,bodyJson:r.documentJson,supersede:r.supersede===!0}),Number(l.changes)})}o(De,"transitionStatusIntent");function Le(e){return s().prepare("SELECT final_report FROM nodes WHERE node_id = ?").get(e)?.final_report??null}o(Le,"getFinalReport");function Ae(e,n){return s().prepare("UPDATE nodes SET final_report = NULL, finalized_at = NULL WHERE node_id = ? AND final_report = ?").run(e,n).changes>0}o(Ae,"clearFinalReportIfMatches");function be(e,n){s().prepare('UPDATE nodes SET tmux_session = ?, "window" = ?, pane = ? WHERE node_id = ?').run(n.tmux_session??null,n.window??null,n.pane??null,e)}o(be,"setPresence");function ve(e,n){s().prepare("UPDATE nodes SET launched_at = ?, frozen_at = NULL, respawn_not_before = NULL WHERE node_id = ?").run(n,e)}o(ve,"recordLaunch");function xe(e,n){s().prepare("UPDATE nodes SET last_settled_at = ? WHERE node_id = ?").run(n,e)}o(xe,"recordSettledTurn");function We(e,n){s().prepare("UPDATE nodes SET frozen_at = ? WHERE node_id = ?").run(n,e)}o(We,"setFrozen");function ke(e){s().prepare("UPDATE nodes SET frozen_at = NULL WHERE node_id = ?").run(e)}o(ke,"clearFrozen");function Fe(e,n){s().prepare("UPDATE nodes SET respawn_failures = ?, respawn_not_before = ? WHERE node_id = ?").run(n.failures,n.notBefore,e)}o(Fe,"recordRespawnAttempt");const m="node_id NOT IN (SELECT node_id FROM warm_pool)",D=["state","cleanup_state","path","branch","repo_root","base_ref","base_sha","created_at","closed_at","next_attempt_at","attempts","quarantined","sweep_reason","sweep_detail","sweep_last_at","sweep_observed_json","abandoned_json","land_intent_json","disposal_json"];function ee(e){return e.worktree_state===null?null:Y(Object.fromEntries(D.map(n=>[n,e[`worktree_${n}`]])))}o(ee,"worktreeFromProjection");function He(e){const n=D.map(r=>`w.${r} AS worktree_${r}`).join(", ");return s().prepare(`SELECT n.*, ${n} FROM node_rows n LEFT JOIN worktrees w ON w.node_id = n.node_id WHERE n.profile_id = ? ORDER BY n.created`).all(e).map(r=>T(r,ee(r)))}o(He,"listNodesByProfile");function je(){return s().prepare("SELECT node_id, cwd, profile_id FROM nodes ORDER BY created").all().map(e=>{const n=e;return{nodeId:n.node_id,cwd:n.cwd,profileId:n.profile_id}})}o(je,"listNodeMemoryTargets");function ne(e){const n=[m],t=[];if(e?.status!==void 0){const i=Array.isArray(e.status)?e.status:[e.status];n.push(`status IN (${i.map(()=>"?").join(",")})`),t.push(...i)}return e?.withRecordedPid===!0&&n.push("pi_pid IS NOT NULL"),e?.withRecordedPidOrFrozen===!0&&n.push("(pi_pid IS NOT NULL OR frozen_at IS NOT NULL)"),s().prepare(`SELECT * FROM node_rows WHERE ${n.join(" AND ")} ORDER BY created`).all(...t).map(_)}o(ne,"listNodes");function Ie(){return s().prepare(`SELECT * FROM node_rows
4
+ ORDER BY deadline_at, created, node_id`).all(e).map(p)}o(ye,"dueNodeDeadlines");function Se(e,n){return Number(d().prepare("UPDATE nodes SET deadline_at = ? WHERE node_id = ?").run(n,e).changes)===1}o(Se,"setNodeDeadline");function ge(e,n){return!Number.isFinite(n)||n<=0?0:_(t=>{const r=t.prepare(`SELECT node_id, deadline_at FROM nodes
5
+ WHERE profile_id = ? AND deadline_at IS NOT NULL AND status IN ('active', 'idle')`).all(e),i=t.prepare("UPDATE nodes SET deadline_at = ? WHERE node_id = ? AND deadline_at = ?");let a=0;for(const s of r){const u=Date.parse(s.deadline_at);Number.isNaN(u)||(a+=Number(i.run(new Date(u+n).toISOString(),s.node_id,s.deadline_at).changes))}return a})}o(ge,"shiftProfileNodeDeadlines");function Z(e,n){if(e==null)return null;if(typeof e=="string"||typeof e=="number"||typeof e=="bigint"||e instanceof Uint8Array)return e;throw new TypeError(`${n} must be a SQLite scalar`)}o(Z,"sqlInput");function Oe(e,n){const t=[],r=o((a,s=a)=>{Object.prototype.hasOwnProperty.call(n,a)&&t.push([s,Z(n[a],a)])},"add");if(r("name"),r("description"),r("title"),r("icon"),r("cycles"),r("kind"),r("mode"),r("lifecycle"),r("cwd"),r("host_kind"),r("profile_id"),r("parent"),r("spawned_by"),r("creator"),r("fork_from"),r("fork_source_file"),r("model_override"),Object.prototype.hasOwnProperty.call(n,"passive_default")&&t.push(["passive_default",n.passive_default===!0?1:0]),Object.prototype.hasOwnProperty.call(n,"cycle_pending")&&t.push(["cycle_pending",n.cycle_pending===!0?1:0]),Object.prototype.hasOwnProperty.call(n,"persona_ack")&&t.push(["persona_ack_json",f(n.persona_ack,"persona_ack")]),Object.prototype.hasOwnProperty.call(n,"review_binding")&&t.push(["review_binding_json",f(n.review_binding,"review_binding")]),Object.prototype.hasOwnProperty.call(n,"launch")&&t.push(["launch_config_json",f(n.launch,"launch")]),t.length===0){const a=E(e);if(a===null)throw new Error(`unknown node: ${e}`);return a}if(d().prepare(`UPDATE nodes SET ${t.map(([a])=>`${a} = ?`).join(", ")} WHERE node_id = ?`).run(...t.map(([,a])=>a),e).changes!==1)throw new Error(`unknown node: ${e}`);return E(e)}o(Oe,"updateNode");function he(e,n){d().prepare("UPDATE nodes SET status = ? WHERE node_id = ?").run(n,e)}o(he,"setStatus");function Te(e,n){d().prepare("UPDATE nodes SET intent = ? WHERE node_id = ?").run(n??null,e)}o(Te,"setIntent");function De(e,n,t={}){if(t.outcome===void 0){const i=[],a=[];Object.prototype.hasOwnProperty.call(n,"status")&&(i.push("status = ?"),a.push(n.status??null)),Object.prototype.hasOwnProperty.call(n,"intent")&&(i.push("intent = ?"),a.push(n.intent??null)),Object.prototype.hasOwnProperty.call(n,"terminal_reason")&&(i.push("terminal_reason = ?"),a.push(n.terminal_reason??null));const s=["node_id = ?"];a.push(e),t.fromStatuses!==void 0&&(s.push(`status IN (${t.fromStatuses.map(()=>"?").join(", ")})`),a.push(...t.fromStatuses)),t.requireNoFinalReport===!0&&s.push("final_report IS NULL");const u=d().prepare(`UPDATE nodes SET ${i.join(", ")} WHERE ${s.join(" AND ")}`).run(...a);return Number(u.changes)}const r=t.outcome;return _(i=>{const a=[],s=[];Object.prototype.hasOwnProperty.call(n,"status")&&(a.push("status = ?"),s.push(n.status??null)),Object.prototype.hasOwnProperty.call(n,"intent")&&(a.push("intent = ?"),s.push(n.intent??null)),Object.prototype.hasOwnProperty.call(n,"terminal_reason")&&(a.push("terminal_reason = ?"),s.push(n.terminal_reason??null));const u=o((re,W)=>r.supersede===!0?"?":`CASE WHEN outcome_at IS NULL THEN ? ELSE ${W} END`,"outcomeValue");a.push(`outcome_kind = ${u(r.kind,"outcome_kind")}`,`outcome_reason = ${u(r.reason,"outcome_reason")}`,`outcome_detail_json = ${u(r.detailJson,"outcome_detail_json")}`,`outcome_revision = ${r.supersede===!0?"outcome_revision + 1":"CASE WHEN outcome_at IS NULL THEN outcome_revision + 1 ELSE outcome_revision END"}`,`outcome_at = ${u(r.at,"outcome_at")}`),s.push(r.kind,r.reason,r.detailJson,r.at);const c=["node_id = ?"];s.push(e),t.fromStatuses!==void 0&&(c.push(`status IN (${t.fromStatuses.map(()=>"?").join(", ")})`),s.push(...t.fromStatuses)),t.requireNoFinalReport===!0&&c.push("final_report IS NULL");const l=i.prepare(`UPDATE nodes SET ${a.join(", ")} WHERE ${c.join(" AND ")}`).run(...s);if(Number(l.changes)===0)return 0;const R=i.prepare("SELECT outcome_at FROM nodes WHERE node_id = ?").get(e);return(r.supersede===!0||R.outcome_at===r.at)&&r.documentJson!==null&&r.documentJson!==void 0&&C(i,{idempotencyKey:`node-outcome:${e}`,label:e,bodyJson:r.documentJson,supersede:r.supersede===!0}),Number(l.changes)})}o(De,"transitionStatusIntent");function Ae(e){return d().prepare("SELECT final_report FROM nodes WHERE node_id = ?").get(e)?.final_report??null}o(Ae,"getFinalReport");function Le(e,n){return d().prepare("UPDATE nodes SET final_report = NULL, finalized_at = NULL WHERE node_id = ? AND final_report = ?").run(e,n).changes>0}o(Le,"clearFinalReportIfMatches");function ke(e,n){d().prepare('UPDATE nodes SET tmux_session = ?, "window" = ?, pane = ? WHERE node_id = ?').run(n.tmux_session??null,n.window??null,n.pane??null,e)}o(ke,"setPresence");function ve(e,n){d().prepare("UPDATE nodes SET launched_at = ?, frozen_at = NULL, respawn_not_before = NULL WHERE node_id = ?").run(n,e)}o(ve,"recordLaunch");function be(e,n){d().prepare("UPDATE nodes SET last_settled_at = ? WHERE node_id = ?").run(n,e)}o(be,"recordSettledTurn");function xe(e,n){d().prepare("UPDATE nodes SET frozen_at = ? WHERE node_id = ?").run(n,e)}o(xe,"setFrozen");function We(e){d().prepare("UPDATE nodes SET frozen_at = NULL WHERE node_id = ?").run(e)}o(We,"clearFrozen");function Fe(e,n){d().prepare("UPDATE nodes SET respawn_failures = ?, respawn_not_before = ? WHERE node_id = ?").run(n.failures,n.notBefore,e)}o(Fe,"recordRespawnAttempt");const m="node_id NOT IN (SELECT node_id FROM warm_pool)",A=["state","cleanup_state","path","branch","repo_root","base_ref","base_sha","created_at","closed_at","next_attempt_at","attempts","quarantined","sweep_reason","sweep_detail","sweep_last_at","sweep_observed_json","abandoned_json","land_intent_json","disposal_json"];function ee(e){return e.worktree_state===null?null:q(Object.fromEntries(A.map(n=>[n,e[`worktree_${n}`]])))}o(ee,"worktreeFromProjection");function He(e){const n=A.map(r=>`w.${r} AS worktree_${r}`).join(", ");return d().prepare(`SELECT n.*, ${n} FROM node_rows n LEFT JOIN worktrees w ON w.node_id = n.node_id WHERE n.profile_id = ? ORDER BY n.created`).all(e).map(r=>D(r,ee(r)))}o(He,"listNodesByProfile");function je(){return d().prepare("SELECT node_id, cwd, profile_id FROM nodes ORDER BY created").all().map(e=>{const n=e;return{nodeId:n.node_id,cwd:n.cwd,profileId:n.profile_id}})}o(je,"listNodeMemoryTargets");function Ie(e,n){d().prepare(`UPDATE nodes
6
+ SET telemetry_tokens_in = ?,
7
+ telemetry_context_tokens = COALESCE(?, telemetry_context_tokens),
8
+ telemetry_last_activity = COALESCE(?, telemetry_last_activity),
9
+ telemetry_updated_at = ?
10
+ WHERE node_id = ?
11
+ AND (telemetry_updated_at IS NULL OR telemetry_updated_at < ?)`).run(n.tokensIn,n.contextTokens,n.lastActivity,n.updatedAt,e,n.updatedAt)}o(Ie,"updateNodeTelemetry");function Ue(){return d().prepare(`SELECT
12
+ node_id, name, description, cycles, kind, status, frozen_at,
13
+ telemetry_context_tokens, telemetry_last_activity,
14
+ pi_pid, turn_open_at, turn_closed_at,
15
+ fault_id, fault_link, fault_op, fault_kind, fault_message, fault_since,
16
+ fault_operation_id, fault_anchor_entry_id, fault_retry_disposition,
17
+ fault_retry_by, fault_retry_attempt, fault_retry_max, fault_retry_next_at,
18
+ fault_provider_error_json
19
+ FROM node_rows WHERE ${m} ORDER BY created`).all().map(n=>{const t=n.pi_pid??null,r=y(t),i=T(n);return{node_id:n.node_id,name:n.name,description:n.description??null,cycles:n.cycles??null,kind:n.kind,status:n.status,frozen_at:n.frozen_at??null,pi_pid:t,telemetry_context_tokens:n.telemetry_context_tokens??null,telemetry_last_activity:n.telemetry_last_activity??null,fault:i?.link==="pi\u2192provider"&&i.retry.by==="daemon"&&i.retry.disposition==="auto"&&!r?null:i,streaming:n.turn_open_at!==null&&n.turn_closed_at===null&&r}})}o(Ue,"graphNodes");function ne(e){const n=[m],t=[];if(e?.status!==void 0){const i=Array.isArray(e.status)?e.status:[e.status];n.push(`status IN (${i.map(()=>"?").join(",")})`),t.push(...i)}return e?.withRecordedPid===!0&&n.push("pi_pid IS NOT NULL"),e?.withRecordedPidOrFrozen===!0&&n.push("(pi_pid IS NOT NULL OR frozen_at IS NOT NULL)"),d().prepare(`SELECT * FROM node_rows WHERE ${n.join(" AND ")} ORDER BY created`).all(...t).map(p)}o(ne,"listNodes");function Me(){return d().prepare(`SELECT * FROM node_rows
6
20
  WHERE ${m} AND kind != 'human'
7
21
  AND (status IN ('active', 'idle') OR (status IN ('done', 'canceled', 'dead') AND (pi_pid IS NOT NULL OR frozen_at IS NOT NULL)))
8
- ORDER BY created`).all().map(_)}o(Ie,"listNodesForSupervision");function Ue(){return s().prepare(`SELECT node_id, name, created FROM nodes WHERE ${m} ORDER BY created`).all()}o(Ue,"listNodeIdentities");function Me(e,n){p(t=>{t.prepare("INSERT OR REPLACE INTO warm_pool (node_id, recipe_key, created) VALUES (?, ?, ?)").run(e,n,new Date().toISOString())})}o(Me,"registerWarmSpare");function Pe(e){return p(n=>n.prepare("DELETE FROM warm_pool WHERE node_id = ?").run(e).changes>0)}o(Pe,"unregisterWarmSpare");function g(e,n){const t=`SELECT w.node_id AS node_id, w.recipe_key AS recipe_key, w.created AS created,
22
+ ORDER BY created`).all().map(p)}o(Me,"listNodesForSupervision");function Ce(){return d().prepare(`SELECT node_id, name, created FROM nodes WHERE ${m} ORDER BY created`).all()}o(Ce,"listNodeIdentities");function Pe(e,n){_(t=>{t.prepare("INSERT OR REPLACE INTO warm_pool (node_id, recipe_key, created) VALUES (?, ?, ?)").run(e,n,new Date().toISOString())})}o(Pe,"registerWarmSpare");function $e(e){return _(n=>n.prepare("DELETE FROM warm_pool WHERE node_id = ?").run(e).changes>0)}o($e,"unregisterWarmSpare");function g(e,n){const t=`SELECT w.node_id AS node_id, w.recipe_key AS recipe_key, w.created AS created,
9
23
  n.status AS status, n.pi_pid AS pi_pid, n.pi_pid_identity AS pi_pid_identity
10
- FROM warm_pool w JOIN node_rows n ON n.node_id = w.node_id`+(n===void 0?"":" WHERE w.recipe_key = ?")+" ORDER BY w.created";return(n===void 0?e.prepare(t).all():e.prepare(t).all(n)).map(i=>({node_id:i.node_id,recipe_key:i.recipe_key,created:i.created,status:i.status,pi_pid:i.pi_pid??null,pi_pid_identity:i.pi_pid_identity??null}))}o(g,"warmSpareRowsFor");function Ce(){return g(s())}o(Ce,"listWarmSpares");function $e(e){return s().prepare("SELECT 1 FROM warm_pool WHERE node_id = ?").get(e)!==void 0}o($e,"isWarmSpare");function L(e){return e.status!=="active"&&e.status!=="idle"?!1:q(e.pi_pid,e.pi_pid_identity)==="alive"}o(L,"spareIsClaimable");function Be(e,n,t={}){return p(r=>{const i=g(r,e).find(L);return i===void 0||r.prepare("DELETE FROM warm_pool WHERE node_id = ?").run(i.node_id).changes===0?null:(r.prepare("UPDATE nodes SET created = ?, deadline_at = ? WHERE node_id = ?").run(n,t.deadlineAt??null,i.node_id),t.outcomeDelivery!==void 0&&y(r,i.node_id,t.outcomeDelivery),i.node_id)})}o(Be,"claimWarmSpare");function ze(e){return g(s(),e).filter(L).length}o(ze,"warmSpareCount");function Je(e){return s().prepare("SELECT node_id FROM nodes WHERE parent = ? ORDER BY created").all(e).map(n=>n.node_id)}o(Je,"childrenOf");function Ye(){return s().prepare(`SELECT node_id, name, kind, mode, lifecycle, status, cwd, host_kind, parent, created
11
- FROM nodes WHERE ${m} ORDER BY created`).all().map(e=>({node_id:e.node_id,name:e.name,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind??null,parent:e.parent??null,created:e.created}))}o(Ye,"rosterNodes");function qe(){return s().prepare("SELECT from_id, to_id, active, created FROM edges WHERE type = 'subscribes_to' ORDER BY created").all().map(e=>({from_id:e.from_id,to_id:e.to_id,active:e.active===1,created:e.created}))}o(qe,"rosterEdges");function Ve(e){return s().prepare(`SELECT * FROM node_rows
24
+ FROM warm_pool w JOIN node_rows n ON n.node_id = w.node_id`+(n===void 0?"":" WHERE w.recipe_key = ?")+" ORDER BY w.created";return(n===void 0?e.prepare(t).all():e.prepare(t).all(n)).map(i=>({node_id:i.node_id,recipe_key:i.recipe_key,created:i.created,status:i.status,pi_pid:i.pi_pid??null,pi_pid_identity:i.pi_pid_identity??null}))}o(g,"warmSpareRowsFor");function Be(){return g(d())}o(Be,"listWarmSpares");function ze(e){return d().prepare("SELECT 1 FROM warm_pool WHERE node_id = ?").get(e)!==void 0}o(ze,"isWarmSpare");function L(e){return e.status!=="active"&&e.status!=="idle"?!1:V(e.pi_pid,e.pi_pid_identity)==="alive"}o(L,"spareIsClaimable");function Ye(e,n,t={}){return _(r=>{const i=g(r,e).find(L);return i===void 0||r.prepare("DELETE FROM warm_pool WHERE node_id = ?").run(i.node_id).changes===0?null:(r.prepare("UPDATE nodes SET created = ?, deadline_at = ? WHERE node_id = ?").run(n,t.deadlineAt??null,i.node_id),t.outcomeDelivery!==void 0&&h(r,i.node_id,t.outcomeDelivery),i.node_id)})}o(Ye,"claimWarmSpare");function Je(e){return g(d(),e).filter(L).length}o(Je,"warmSpareCount");function qe(e){return d().prepare("SELECT node_id FROM nodes WHERE parent = ? ORDER BY created").all(e).map(n=>n.node_id)}o(qe,"childrenOf");function Ve(){return d().prepare(`SELECT node_id, name, kind, mode, lifecycle, status, cwd, host_kind, parent, created
25
+ FROM nodes WHERE ${m} ORDER BY created`).all().map(e=>({node_id:e.node_id,name:e.name,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,status:e.status,cwd:e.cwd,host_kind:e.host_kind??null,parent:e.parent??null,created:e.created}))}o(Ve,"rosterNodes");function Ge(){return d().prepare("SELECT from_id, to_id, active, created FROM edges WHERE type = 'subscribes_to' ORDER BY created").all().map(e=>({from_id:e.from_id,to_id:e.to_id,active:e.active===1,created:e.created}))}o(Ge,"rosterEdges");function Ke(e){return d().prepare(`SELECT * FROM node_rows
12
26
  WHERE parent IS NULL AND kind != 'human'
13
27
  AND status IN ('active','idle') AND cwd = ?
14
28
  AND ${m}
15
- ORDER BY created DESC`).all(e).map(_)}o(Ve,"listResumableRoots");function A(e,n,t,r){s().prepare(`INSERT INTO edges (type, from_id, to_id, active, created)
29
+ ORDER BY created DESC`).all(e).map(p)}o(Ke,"listResumableRoots");function k(e,n,t,r){d().prepare(`INSERT INTO edges (type, from_id, to_id, active, created)
16
30
  VALUES (?, ?, ?, ?, ?)
17
- ON CONFLICT(type, from_id, to_id) DO UPDATE SET active=excluded.active`).run(e,n,t,r?1:0,new Date().toISOString())}o(A,"addEdge");function Ge(e,n,t=!0){A("subscribes_to",e,n,t)}o(Ge,"subscribe");function Ke(e,n){s().prepare("DELETE FROM edges WHERE type = ? AND from_id = ? AND to_id = ?").run("subscribes_to",e,n)}o(Ke,"unsubscribe");function Qe(e,n,t){s().prepare("UPDATE edges SET active = ? WHERE type = ? AND from_id = ? AND to_id = ?").run(t?1:0,"subscribes_to",e,n)}o(Qe,"setSubscriptionActive");function Xe(e,n){A("spawned_by",e,n,!0)}o(Xe,"recordSpawn");function Ze(e){return s().prepare(`SELECT from_id AS node_id, active, created FROM edges
18
- WHERE type = 'subscribes_to' AND to_id = ? ORDER BY created`).all(e).map(n=>({node_id:n.node_id,active:n.active===1,created:n.created}))}o(Ze,"subscribersOf");function b(e){return s().prepare(`SELECT to_id AS node_id, active, created FROM edges
19
- WHERE type = 'subscribes_to' AND from_id = ? ORDER BY created`).all(e).map(n=>({node_id:n.node_id,active:n.active===1,created:n.created}))}o(b,"subscriptionsOf");function en(e){const n=new Set([e]),t=[],r=b(e).map(i=>i.node_id);for(;r.length>0;){const i=r.shift();if(!n.has(i)){n.add(i),t.push(i);for(const d of b(i))n.has(d.node_id)||r.push(d.node_id)}}return t}o(en,"view");function nn(e){return s().prepare(`SELECT 1 FROM edges e JOIN nodes n ON n.node_id = e.to_id
31
+ ON CONFLICT(type, from_id, to_id) DO UPDATE SET active=excluded.active`).run(e,n,t,r?1:0,new Date().toISOString())}o(k,"addEdge");function Qe(e,n,t=!0){k("subscribes_to",e,n,t)}o(Qe,"subscribe");function Xe(e,n){d().prepare("DELETE FROM edges WHERE type = ? AND from_id = ? AND to_id = ?").run("subscribes_to",e,n)}o(Xe,"unsubscribe");function Ze(e,n,t){d().prepare("UPDATE edges SET active = ? WHERE type = ? AND from_id = ? AND to_id = ?").run(t?1:0,"subscribes_to",e,n)}o(Ze,"setSubscriptionActive");function en(e,n){k("spawned_by",e,n,!0)}o(en,"recordSpawn");function nn(e){return d().prepare(`SELECT from_id AS node_id, active, created FROM edges
32
+ WHERE type = 'subscribes_to' AND to_id = ? ORDER BY created`).all(e).map(n=>({node_id:n.node_id,active:n.active===1,created:n.created}))}o(nn,"subscribersOf");function v(e){return d().prepare(`SELECT to_id AS node_id, active, created FROM edges
33
+ WHERE type = 'subscribes_to' AND from_id = ? ORDER BY created`).all(e).map(n=>({node_id:n.node_id,active:n.active===1,created:n.created}))}o(v,"subscriptionsOf");function tn(e){const n=new Set([e]),t=[],r=v(e).map(i=>i.node_id);for(;r.length>0;){const i=r.shift();if(!n.has(i)){n.add(i),t.push(i);for(const a of v(i))n.has(a.node_id)||r.push(a.node_id)}}return t}o(tn,"view");function rn(e){return d().prepare(`SELECT 1 FROM edges e JOIN nodes n ON n.node_id = e.to_id
20
34
  WHERE e.type = 'subscribes_to' AND e.from_id = ? AND e.active = 1
21
- AND n.status IN ('active', 'idle') LIMIT 1`).get(e)!==void 0}o(nn,"hasActiveLiveSubscription");function tn(e){return s().prepare(`SELECT 1 FROM edges e JOIN nodes n ON n.node_id = e.from_id
35
+ AND n.status IN ('active', 'idle') LIMIT 1`).get(e)!==void 0}o(rn,"hasActiveLiveSubscription");function on(e){return d().prepare(`SELECT 1 FROM edges e JOIN nodes n ON n.node_id = e.from_id
22
36
  WHERE e.type = 'subscribes_to' AND e.to_id = ? AND e.active = 1
23
- AND n.status IN ('active', 'idle') LIMIT 1`).get(e)!==void 0}o(tn,"hasLiveSubscriber");function rn(e){const n=E(e)?.waiting_for;if(n==null)return!1;const t=E(n);return t!==null&&(t.status==="active"||t.status==="idle")}o(rn,"hasLiveMessageWait");function on(e,n){s().prepare("UPDATE nodes SET waiting_for = ?, waiting_for_generation = waiting_for_generation + 1 WHERE node_id = ?").run(n,e)}o(on,"setMessageWait");function dn(e,n,t){return p(r=>{const i=r.prepare("SELECT waiting_for_generation FROM nodes WHERE node_id = ? AND waiting_for = ?").get(e,n),d=t();return n!==null&&i!==void 0&&r.prepare("UPDATE nodes SET waiting_for = NULL WHERE node_id = ? AND waiting_for = ? AND waiting_for_generation = ?").run(e,n,i.waiting_for_generation),d})}o(dn,"deliverAndSettleMessageWait");function sn(e,n,t){return p(r=>{const i=r.prepare(`SELECT waiter.waiting_for, waiter.waiting_for_generation, target.status AS controller_status
37
+ AND n.status IN ('active', 'idle') LIMIT 1`).get(e)!==void 0}o(on,"hasLiveSubscriber");function an(e){const n=E(e)?.waiting_for;if(n==null)return!1;const t=E(n);return t!==null&&(t.status==="active"||t.status==="idle")}o(an,"hasLiveMessageWait");function dn(e,n){d().prepare("UPDATE nodes SET waiting_for = ?, waiting_for_generation = waiting_for_generation + 1 WHERE node_id = ?").run(n,e)}o(dn,"setMessageWait");function sn(e,n,t){return _(r=>{const i=r.prepare("SELECT waiting_for_generation FROM nodes WHERE node_id = ? AND waiting_for = ?").get(e,n),a=t();return n!==null&&i!==void 0&&r.prepare("UPDATE nodes SET waiting_for = NULL WHERE node_id = ? AND waiting_for = ? AND waiting_for_generation = ?").run(e,n,i.waiting_for_generation),a})}o(sn,"deliverAndSettleMessageWait");function un(e,n,t){return _(r=>{const i=r.prepare(`SELECT waiter.waiting_for, waiter.waiting_for_generation, target.status AS controller_status
24
38
  FROM nodes AS waiter LEFT JOIN nodes AS target ON target.node_id = waiter.waiting_for
25
- WHERE waiter.node_id = ?`).get(e),d=i?.controller_status==="active"||i?.controller_status==="idle";if(i?.waiting_for!==n||d)return null;const a=t();return r.prepare("UPDATE nodes SET waiting_for = NULL WHERE node_id = ? AND waiting_for = ? AND waiting_for_generation = ?").run(e,n,i.waiting_for_generation),a})}o(sn,"settleDeadMessageWait");function an(e,n,t){return p(r=>{const i=r.prepare("SELECT status, final_report, frozen_at FROM nodes WHERE node_id = ?").get(e);return i===void 0?{kind:"missing"}:n(i)?{kind:"terminal",status:i.status,final_report:i.final_report}:{kind:"ran",result:t()}})}o(an,"withFreshTerminalGuard");function w(e){return B(e)}o(w,"hasUnreconciledManagedWorktree");function v(e,n={}){return!["done","dead","canceled"].includes(e.status)||e.pi_pid!==null||e.frozen_at!==null||w(e.node_id)||e.node_id===O()?!1:n.pastTtl===!0||!["crashed","stranded",null].includes(e.terminal_reason??null)}o(v,"isCollectible");function un(e){if(w(e))return{deleted:!1};const n=p(t=>(t.prepare("DELETE FROM nodes WHERE node_id = ?").run(e),{deleted:!0}));return R(S(e),{recursive:!0,force:!0}),n}o(un,"deleteNode");function ln(e){const n=[...new Set(e)];if(n.length===0)return[];const t=n.filter(w);if(t.length>0)throw new Error(`refusing to delete nodes with unreconciled managed worktrees: ${t.join(", ")}`);const r=n.map(()=>"?").join(","),i=p(d=>{const a=d.prepare(`SELECT node_id FROM nodes WHERE node_id IN (${r}) ORDER BY created`).all(...n).map(({node_id:u})=>u);return d.prepare(`DELETE FROM nodes WHERE node_id IN (${r})`).run(...n),a});for(const d of i)R(S(d),{recursive:!0,force:!0});return i}o(ln,"deleteNodes");function cn(e){const n=e.dryRun??!1,t=e.includeStale??!1,r=new Date(Date.now()-e.ttlDays*864e5).toISOString(),i=O()??"",d=s(),a=d.prepare(`SELECT * FROM node_rows
39
+ WHERE waiter.node_id = ?`).get(e),a=i?.controller_status==="active"||i?.controller_status==="idle";if(i?.waiting_for!==n||a)return null;const s=t();return r.prepare("UPDATE nodes SET waiting_for = NULL WHERE node_id = ? AND waiting_for = ? AND waiting_for_generation = ?").run(e,n,i.waiting_for_generation),s})}o(un,"settleDeadMessageWait");function ln(e,n,t){return _(r=>{const i=r.prepare("SELECT status, final_report, frozen_at FROM nodes WHERE node_id = ?").get(e);return i===void 0?{kind:"missing"}:n(i)?{kind:"terminal",status:i.status,final_report:i.final_report}:{kind:"ran",result:t()}})}o(ln,"withFreshTerminalGuard");function w(e){return z(e)}o(w,"hasUnreconciledManagedWorktree");function b(e,n={}){return!["done","dead","canceled"].includes(e.status)||e.pi_pid!==null||e.frozen_at!==null||w(e.node_id)||e.node_id===O()?!1:n.pastTtl===!0||!["crashed","stranded",null].includes(e.terminal_reason??null)}o(b,"isCollectible");function cn(e){if(w(e))return{deleted:!1};const n=_(t=>(t.prepare("DELETE FROM nodes WHERE node_id = ?").run(e),{deleted:!0}));return N(S(e),{recursive:!0,force:!0}),n}o(cn,"deleteNode");function _n(e){const n=[...new Set(e)];if(n.length===0)return[];const t=n.filter(w);if(t.length>0)throw new Error(`refusing to delete nodes with unreconciled managed worktrees: ${t.join(", ")}`);const r=n.map(()=>"?").join(","),i=_(a=>{const s=a.prepare(`SELECT node_id FROM nodes WHERE node_id IN (${r}) ORDER BY created`).all(...n).map(({node_id:u})=>u);return a.prepare(`DELETE FROM nodes WHERE node_id IN (${r})`).run(...n),s});for(const a of i)N(S(a),{recursive:!0,force:!0});return i}o(_n,"deleteNodes");function pn(e){const n=e.dryRun??!1,t=e.includeStale??!1,r=new Date(Date.now()-e.ttlDays*864e5).toISOString(),i=O()??"",a=d(),s=a.prepare(`SELECT * FROM node_rows
26
40
  WHERE status IN ('dead', 'done', 'canceled') AND created < ?
27
- ORDER BY created`).all(r).map(_).filter(l=>v(l,{pastTtl:!0})).map(l=>({node_id:l.node_id,status:l.status,created:l.created})),u=t?d.prepare(`SELECT node_id, status, created, pi_pid FROM node_rows
41
+ ORDER BY created`).all(r).map(p).filter(l=>b(l,{pastTtl:!0})).map(l=>({node_id:l.node_id,status:l.status,created:l.created})),u=t?a.prepare(`SELECT node_id, status, created, pi_pid FROM node_rows
28
42
  WHERE status IN ('active', 'idle') AND created < ?
29
- ORDER BY created`).all(r).filter(l=>{if(l.node_id===i)return!1;const N=l.pi_pid;return!h(N)}).map(l=>({node_id:l.node_id,status:l.status,created:l.created})).filter(l=>!w(l.node_id)):[],c=[...a,...u];return n||c.length===0?{pruned:c,dryRun:n}:(x(c),{pruned:c,dryRun:n})}o(cn,"pruneNodes");function x(e){if(e.length!==0){p(n=>{const t=n.prepare("DELETE FROM nodes WHERE node_id = ?");for(const r of e)t.run(r.node_id)});for(const n of e)R(S(n.node_id),{recursive:!0,force:!0})}}o(x,"deletePrunedNodes");function te(e,n){try{const r=j(I(K(e),"telemetry.json"),{throwIfNoEntry:!1});if(r!==void 0)return r.mtimeMs}catch{}const t=Date.parse(n);return Number.isNaN(t)?0:t}o(te,"recencyMs");function pn(e){const n=e.dryRun??!1,r=ne().map(u=>({row:u,recency:te(u.node_id,u.created),retained:!v(u)})).sort((u,c)=>c.recency-u.recency),i=r.filter(u=>u.retained).length,d=Math.max(e.maxNodes,i),a=r.filter((u,c)=>c>=d&&!u.retained).map(({row:u})=>({node_id:u.node_id,status:u.status,created:u.created}));return n||a.length===0?{pruned:a,dryRun:n}:(x(a),{pruned:a,dryRun:n})}o(pn,"pruneToLimit");export{me as canonicalSessionFile,Je as childrenOf,Be as claimWarmSpare,Ae as clearFinalReportIfMatches,ke as clearFrozen,Ee as createNode,un as deleteNode,ln as deleteNodes,dn as deliverAndSettleMessageWait,Se as dueNodeDeadlines,we as findNodeBySessionFile,Le as getFinalReport,E as getNode,Ne as getRow,Re as getRowByPane,nn as hasActiveLiveSubscription,rn as hasLiveMessageWait,tn as hasLiveSubscriber,v as isCollectible,$e as isWarmSpare,Ue as listNodeIdentities,je as listNodeMemoryTargets,ne as listNodes,He as listNodesByProfile,Ie as listNodesForSupervision,Ve as listResumableRoots,Ce as listWarmSpares,cn as pruneNodes,pn as pruneToLimit,ve as recordLaunch,Fe as recordRespawnAttempt,xe as recordSettledTurn,Xe as recordSpawn,Me as registerWarmSpare,qe as rosterEdges,Ye as rosterNodes,We as setFrozen,Te as setIntent,on as setMessageWait,ge as setNodeDeadline,be as setPresence,ye as setStatus,Qe as setSubscriptionActive,sn as settleDeadMessageWait,Oe as shiftProfileNodeDeadlines,Ge as subscribe,Ze as subscribersOf,b as subscriptionsOf,De as transitionStatusIntent,Pe as unregisterWarmSpare,Ke as unsubscribe,he as updateNode,en as view,ze as warmSpareCount,an as withFreshTerminalGuard};
43
+ ORDER BY created`).all(r).filter(l=>{if(l.node_id===i)return!1;const R=l.pi_pid;return!y(R)}).map(l=>({node_id:l.node_id,status:l.status,created:l.created})).filter(l=>!w(l.node_id)):[],c=[...s,...u];return n||c.length===0?{pruned:c,dryRun:n}:(x(c),{pruned:c,dryRun:n})}o(pn,"pruneNodes");function x(e){if(e.length!==0){_(n=>{const t=n.prepare("DELETE FROM nodes WHERE node_id = ?");for(const r of e)t.run(r.node_id)});for(const n of e)N(S(n.node_id),{recursive:!0,force:!0})}}o(x,"deletePrunedNodes");function te(e,n){try{const r=I(U(Q(e),"telemetry.json"),{throwIfNoEntry:!1});if(r!==void 0)return r.mtimeMs}catch{}const t=Date.parse(n);return Number.isNaN(t)?0:t}o(te,"recencyMs");function fn(e){const n=e.dryRun??!1,r=ne().map(u=>({row:u,recency:te(u.node_id,u.created),retained:!b(u)})).sort((u,c)=>c.recency-u.recency),i=r.filter(u=>u.retained).length,a=Math.max(e.maxNodes,i),s=r.filter((u,c)=>c>=a&&!u.retained).map(({row:u})=>({node_id:u.node_id,status:u.status,created:u.created}));return n||s.length===0?{pruned:s,dryRun:n}:(x(s),{pruned:s,dryRun:n})}o(fn,"pruneToLimit");export{me as canonicalSessionFile,qe as childrenOf,Ye as claimWarmSpare,Le as clearFinalReportIfMatches,We as clearFrozen,Ee as createNode,cn as deleteNode,_n as deleteNodes,sn as deliverAndSettleMessageWait,ye as dueNodeDeadlines,we as findNodeBySessionFile,Ae as getFinalReport,E as getNode,Re as getRow,Ne as getRowByPane,Ue as graphNodes,rn as hasActiveLiveSubscription,an as hasLiveMessageWait,on as hasLiveSubscriber,b as isCollectible,ze as isWarmSpare,Ce as listNodeIdentities,je as listNodeMemoryTargets,ne as listNodes,He as listNodesByProfile,Me as listNodesForSupervision,Ke as listResumableRoots,Be as listWarmSpares,pn as pruneNodes,fn as pruneToLimit,ve as recordLaunch,Fe as recordRespawnAttempt,be as recordSettledTurn,en as recordSpawn,Pe as registerWarmSpare,Ge as rosterEdges,Ve as rosterNodes,xe as setFrozen,Te as setIntent,dn as setMessageWait,Se as setNodeDeadline,ke as setPresence,he as setStatus,Ze as setSubscriptionActive,un as settleDeadMessageWait,ge as shiftProfileNodeDeadlines,Qe as subscribe,nn as subscribersOf,v as subscriptionsOf,De as transitionStatusIntent,$e as unregisterWarmSpare,Xe as unsubscribe,Oe as updateNode,Ie as updateNodeTelemetry,tn as view,Je as warmSpareCount,ln as withFreshTerminalGuard};
@@ -1,4 +1,4 @@
1
- var J=Object.defineProperty;var i=(e,n)=>J(e,"name",{value:n,configurable:!0});import{importNodeSqlAuthority as Q,recreateNodeRowsView as V}from"./node-sql-migration.js";import{migrateRecoveryWitnesses as Z}from"./recovery.js";import{migrateMessagingState as ee}from"./deliveries.js";import{migrateHumanRequestsState as ne}from"../human/requests.js";import{existsSync as A,readFileSync as h,readdirSync as X,realpathSync as te}from"node:fs";import{basename as oe,join as y,resolve as H}from"node:path";import{crtrHome as ie,isSafeNodeId as re,nodesRoot as S,nodeMetaPath as m}from"./paths.js";import{STATE_MIGRATIONS as se}from"../../migrations/registry.js";import{customExtensionPaths as Te}from"./extensions.js";import{readMetaObject as P,updateJsonFileDurably as b,withMetaLock as Ee,writeMetaObjectLocked as ae}from"./meta-file.js";function de(e){e.exec(`
1
+ var J=Object.defineProperty;var i=(e,n)=>J(e,"name",{value:n,configurable:!0});import{importNodeSqlAuthority as Q,recreateNodeRowsView as V}from"./node-sql-migration.js";import{migrateRecoveryWitnesses as Z}from"./recovery.js";import{migrateMessagingState as ee}from"./deliveries.js";import{migrateHumanRequestsState as ne}from"../human/requests.js";import{existsSync as p,readFileSync as S,readdirSync as U,realpathSync as te,statSync as oe}from"node:fs";import{basename as ie,join as w,resolve as H}from"node:path";import{crtrHome as re,isSafeNodeId as se,nodesRoot as I,nodeMetaPath as X}from"./paths.js";import{STATE_MIGRATIONS as Te}from"../../migrations/registry.js";import{customExtensionPaths as Ee}from"./extensions.js";import{readMetaObject as P,updateJsonFileDurably as b,withMetaLock as ae,writeMetaObjectLocked as de}from"./meta-file.js";function _e(e){e.exec(`
2
2
  CREATE TABLE IF NOT EXISTS nodes (
3
3
  node_id TEXT PRIMARY KEY,
4
4
  name TEXT NOT NULL,
@@ -23,7 +23,7 @@ CREATE TABLE IF NOT EXISTS edges (
23
23
  CREATE INDEX IF NOT EXISTS idx_edges_to ON edges(type, to_id);
24
24
  CREATE INDEX IF NOT EXISTS idx_edges_from ON edges(type, from_id);
25
25
  CREATE INDEX IF NOT EXISTS idx_nodes_status ON nodes(status);
26
- `)}i(de,"baselineSchema");function w(e,n){return new Set(e.prepare(`PRAGMA table_info(${n})`).all().map(t=>t.name))}i(w,"tableColumns");function Y(e,n,t,o){n.has(t)||(e.exec(o),n.add(t))}i(Y,"addColumnIfMissing");function l(e){return w(e,"nodes")}i(l,"nodeColumns");const a=Y;function _e(e){const n=l(e);a(e,n,"intent","ALTER TABLE nodes ADD COLUMN intent TEXT;"),a(e,n,"pi_pid","ALTER TABLE nodes ADD COLUMN pi_pid INTEGER;"),a(e,n,"window","ALTER TABLE nodes ADD COLUMN window TEXT;"),a(e,n,"tmux_session","ALTER TABLE nodes ADD COLUMN tmux_session TEXT;")}i(_e,"addRuntimeColumns");function ce(e){const n=S();if(!A(n))return;const t=e.prepare('UPDATE nodes SET intent = ?, pi_pid = ?, "window" = ?, tmux_session = ? WHERE node_id = ?');for(const o of X(n)){const s=m(o);if(!A(s))continue;let T;try{T=JSON.parse(h(s,"utf8"))}catch{continue}t.run(T.intent??null,T.pi_pid??null,T.window??null,T.tmux_session??null,o)}}i(ce,"backfillRuntime");function Ne(e){if(!(e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'edges'").get()!==void 0)){e.exec(`
26
+ `)}i(_e,"baselineSchema");function x(e,n){return new Set(e.prepare(`PRAGMA table_info(${n})`).all().map(t=>t.name))}i(x,"tableColumns");function Y(e,n,t,o){n.has(t)||(e.exec(o),n.add(t))}i(Y,"addColumnIfMissing");function l(e){return x(e,"nodes")}i(l,"nodeColumns");const a=Y;function ce(e){const n=l(e);a(e,n,"intent","ALTER TABLE nodes ADD COLUMN intent TEXT;"),a(e,n,"pi_pid","ALTER TABLE nodes ADD COLUMN pi_pid INTEGER;"),a(e,n,"window","ALTER TABLE nodes ADD COLUMN window TEXT;"),a(e,n,"tmux_session","ALTER TABLE nodes ADD COLUMN tmux_session TEXT;")}i(ce,"addRuntimeColumns");function Ne(e){const n=I();if(!p(n))return;const t=e.prepare('UPDATE nodes SET intent = ?, pi_pid = ?, "window" = ?, tmux_session = ? WHERE node_id = ?');for(const o of U(n)){const T=X(o);if(!p(T))continue;let r;try{r=JSON.parse(S(T,"utf8"))}catch{continue}t.run(r.intent??null,r.pi_pid??null,r.window??null,r.tmux_session??null,o)}}i(Ne,"backfillRuntime");function ue(e){if(!(e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'edges'").get()!==void 0)){e.exec(`
27
27
  CREATE TABLE edges (
28
28
  type TEXT NOT NULL,
29
29
  from_id TEXT NOT NULL,
@@ -57,14 +57,14 @@ DROP TABLE edges;
57
57
  ALTER TABLE edges_new RENAME TO edges;
58
58
  CREATE INDEX IF NOT EXISTS idx_edges_to ON edges(type, to_id);
59
59
  CREATE INDEX IF NOT EXISTS idx_edges_from ON edges(type, from_id);
60
- `);const o=e.prepare("SELECT COUNT(*) AS n FROM edges").get().n;if(o!==t)throw new Error(`edges FK rebuild lost rows: expected ${t} non-orphan edge(s), got ${o}`);const s=e.prepare("PRAGMA foreign_key_check").all();if(s.length>0)throw new Error(`edges FK rebuild left ${s.length} foreign-key violation(s)`);e.exec("COMMIT")}catch(o){throw e.exec("ROLLBACK"),o}}finally{e.exec("PRAGMA foreign_keys = ON;")}}i(Ne,"edgesForeignKeyCascade");function ue(e){const n=l(e);a(e,n,"pane","ALTER TABLE nodes ADD COLUMN pane TEXT;")}i(ue,"addPaneColumn");function le(e){e.exec(`
60
+ `);const o=e.prepare("SELECT COUNT(*) AS n FROM edges").get().n;if(o!==t)throw new Error(`edges FK rebuild lost rows: expected ${t} non-orphan edge(s), got ${o}`);const T=e.prepare("PRAGMA foreign_key_check").all();if(T.length>0)throw new Error(`edges FK rebuild left ${T.length} foreign-key violation(s)`);e.exec("COMMIT")}catch(o){throw e.exec("ROLLBACK"),o}}finally{e.exec("PRAGMA foreign_keys = ON;")}}i(ue,"edgesForeignKeyCascade");function le(e){const n=l(e);a(e,n,"pane","ALTER TABLE nodes ADD COLUMN pane TEXT;")}i(le,"addPaneColumn");function Le(e){e.exec(`
61
61
  CREATE TABLE IF NOT EXISTS focuses (
62
62
  focus_id TEXT PRIMARY KEY, -- stable internal id for the viewport
63
63
  pane TEXT, -- the durable %pane_id realizing the focus
64
64
  session TEXT, -- derived cache of the user session (reconciled from pane)
65
65
  node_id TEXT NOT NULL UNIQUE -- the node shown; UNIQUE \u2192 a node occupies <=1 focus
66
66
  );
67
- `)}i(le,"addFocusesTable");function Le(e){e.exec(`
67
+ `)}i(Le,"addFocusesTable");function pe(e){e.exec(`
68
68
  CREATE TABLE IF NOT EXISTS wakeups (
69
69
  wakeup_id TEXT PRIMARY KEY,
70
70
  node_id TEXT, -- TARGET + node-anchored cancel anchor; NULL = canvas-detached
@@ -80,7 +80,7 @@ CREATE INDEX IF NOT EXISTS idx_wakeups_fire ON wakeups(fire_at);
80
80
  CREATE INDEX IF NOT EXISTS idx_wakeups_node ON wakeups(node_id); -- by-node cancel / list
81
81
  CREATE INDEX IF NOT EXISTS idx_wakeups_owner ON wakeups(owner_id); -- by-owner reap (ruling A)
82
82
  CREATE UNIQUE INDEX IF NOT EXISTS idx_wakeups_deadline ON wakeups(node_id) WHERE kind = 'deadline';
83
- `)}i(Le,"appendWakeupsTable");function pe(e){e.exec(`
83
+ `)}i(pe,"appendWakeupsTable");function Oe(e){e.exec(`
84
84
  CREATE TABLE IF NOT EXISTS triggers (
85
85
  trigger_id TEXT PRIMARY KEY,
86
86
  owner_id TEXT NOT NULL,
@@ -131,12 +131,12 @@ SELECT
131
131
  FROM wakeups;
132
132
 
133
133
  DROP TABLE wakeups;
134
- `)}i(pe,"migrateWakeupsToTriggers");function Oe(e){const n=l(e);a(e,n,"host_kind","ALTER TABLE nodes ADD COLUMN host_kind TEXT;")}i(Oe,"addHostKindColumn");function Ae(e){e.exec(`
134
+ `)}i(Oe,"migrateWakeupsToTriggers");function Ae(e){const n=l(e);a(e,n,"host_kind","ALTER TABLE nodes ADD COLUMN host_kind TEXT;")}i(Ae,"addHostKindColumn");function fe(e){e.exec(`
135
135
  CREATE TABLE IF NOT EXISTS canvas_meta (
136
136
  key TEXT PRIMARY KEY,
137
137
  value TEXT NOT NULL
138
138
  );
139
- `)}i(Ae,"addCanvasMetaTable");function fe(e){const n=l(e);a(e,n,"profile_id","ALTER TABLE nodes ADD COLUMN profile_id TEXT;")}i(fe,"addProfileIdColumn");function Ie(e){const n=l(e);a(e,n,"pi_pid_identity","ALTER TABLE nodes ADD COLUMN pi_pid_identity TEXT;")}i(Ie,"addPidIdentityColumn");function Re(e){const n=l(e);a(e,n,"waiting_for","ALTER TABLE nodes ADD COLUMN waiting_for TEXT;")}i(Re,"addMessageWaitColumn");function $(e){const n=l(e);if(n.size===0)return;a(e,n,"final_report","ALTER TABLE nodes ADD COLUMN final_report TEXT;"),a(e,n,"finalized_at","ALTER TABLE nodes ADD COLUMN finalized_at TEXT;");const t=e.prepare("SELECT node_id FROM nodes WHERE status = 'done' AND final_report IS NULL").all(),o=e.prepare("UPDATE nodes SET final_report = ?, finalized_at = ? WHERE node_id = ? AND final_report IS NULL");for(const{node_id:s}of t){const T=y(S(),s,"reports");if(!A(T))continue;let r=null;for(const E of X(T))if(E.endsWith(".md"))try{const d=h(y(T,E),"utf8"),_=/^---\nnode: [^\n]+\nkind: final\nts: ([^\n]+)\n---\n/.exec(d);if(_===null||Number.isNaN(Date.parse(_[1])))continue;const c={name:E,ts:_[1]};(r===null||c.ts>r.ts||c.ts===r.ts&&c.name>r.name)&&(r=c)}catch{}r!==null&&o.run(r.name,r.ts,s)}}i($,"addCanonicalFinalColumns");function me(e){const n=S();if(A(n))for(const t of X(n)){const o=m(t);A(o)&&b(o,s=>{const T=s.launch;if(typeof T!="object"||T===null||Array.isArray(T))return!1;const r=T.extensions;if(!Array.isArray(r)||!r.every(d=>typeof d=="string"))return!1;const E=Te(r);return E.length===r.length?!1:(T.extensions=E,!0)})}}i(me,"normalizePersistedLaunchExtensions");function Xe(e){const n=l(e);a(e,n,"waiting_for_generation","ALTER TABLE nodes ADD COLUMN waiting_for_generation INTEGER NOT NULL DEFAULT 0;")}i(Xe,"addMessageWaitGenerationColumn");function Se(e){e.exec(`
139
+ `)}i(fe,"addCanvasMetaTable");function me(e){const n=l(e);a(e,n,"profile_id","ALTER TABLE nodes ADD COLUMN profile_id TEXT;")}i(me,"addProfileIdColumn");function Re(e){const n=l(e);a(e,n,"pi_pid_identity","ALTER TABLE nodes ADD COLUMN pi_pid_identity TEXT;")}i(Re,"addPidIdentityColumn");function Ie(e){const n=l(e);a(e,n,"waiting_for","ALTER TABLE nodes ADD COLUMN waiting_for TEXT;")}i(Ie,"addMessageWaitColumn");function W(e){const n=l(e);if(n.size===0)return;a(e,n,"final_report","ALTER TABLE nodes ADD COLUMN final_report TEXT;"),a(e,n,"finalized_at","ALTER TABLE nodes ADD COLUMN finalized_at TEXT;");const t=e.prepare("SELECT node_id FROM nodes WHERE status = 'done' AND final_report IS NULL").all(),o=e.prepare("UPDATE nodes SET final_report = ?, finalized_at = ? WHERE node_id = ? AND final_report IS NULL");for(const{node_id:T}of t){const r=w(I(),T,"reports");if(!p(r))continue;let s=null;for(const E of U(r))if(E.endsWith(".md"))try{const d=S(w(r,E),"utf8"),_=/^---\nnode: [^\n]+\nkind: final\nts: ([^\n]+)\n---\n/.exec(d);if(_===null||Number.isNaN(Date.parse(_[1])))continue;const c={name:E,ts:_[1]};(s===null||c.ts>s.ts||c.ts===s.ts&&c.name>s.name)&&(s=c)}catch{}s!==null&&o.run(s.name,s.ts,T)}}i(W,"addCanonicalFinalColumns");function Xe(e){const n=I();if(p(n))for(const t of U(n)){const o=X(t);p(o)&&b(o,T=>{const r=T.launch;if(typeof r!="object"||r===null||Array.isArray(r))return!1;const s=r.extensions;if(!Array.isArray(s)||!s.every(d=>typeof d=="string"))return!1;const E=Ee(s);return E.length===s.length?!1:(r.extensions=E,!0)})}}i(Xe,"normalizePersistedLaunchExtensions");function Se(e){const n=l(e);a(e,n,"waiting_for_generation","ALTER TABLE nodes ADD COLUMN waiting_for_generation INTEGER NOT NULL DEFAULT 0;")}i(Se,"addMessageWaitGenerationColumn");function Ue(e){e.exec(`
140
140
  CREATE TABLE IF NOT EXISTS consult_outbox (
141
141
  node_id TEXT PRIMARY KEY, -- legacy work node id
142
142
  dir TEXT NOT NULL, -- legacy ticket directory
@@ -150,15 +150,15 @@ CREATE INDEX IF NOT EXISTS idx_consult_outbox_status ON consult_outbox(status);
150
150
  CREATE INDEX IF NOT EXISTS idx_consult_outbox_dir ON consult_outbox(dir);
151
151
  CREATE INDEX IF NOT EXISTS idx_consult_outbox_dir_request_status ON consult_outbox(dir, request_id, status);
152
152
  CREATE INDEX IF NOT EXISTS idx_consult_outbox_dir_status ON consult_outbox(dir, status);
153
- `)}i(Se,"addHumanWorkOutboxTable");function Ue(e){const n=w(e,"consult_outbox"),t=i((o,s)=>Y(e,n,o,s),"add");t("work_kind","ALTER TABLE consult_outbox ADD COLUMN work_kind TEXT NOT NULL DEFAULT 'follow_up';"),t("interaction_id","ALTER TABLE consult_outbox ADD COLUMN interaction_id TEXT;"),t("generation_id","ALTER TABLE consult_outbox ADD COLUMN generation_id TEXT;"),t("interaction_snapshot","ALTER TABLE consult_outbox ADD COLUMN interaction_snapshot TEXT;"),t("handler_command","ALTER TABLE consult_outbox ADD COLUMN handler_command TEXT;"),t("handler_args_json","ALTER TABLE consult_outbox ADD COLUMN handler_args_json TEXT;"),t("claim_token","ALTER TABLE consult_outbox ADD COLUMN claim_token TEXT;"),e.exec(`
153
+ `)}i(Ue,"addHumanWorkOutboxTable");function ge(e){const n=x(e,"consult_outbox"),t=i((o,T)=>Y(e,n,o,T),"add");t("work_kind","ALTER TABLE consult_outbox ADD COLUMN work_kind TEXT NOT NULL DEFAULT 'follow_up';"),t("interaction_id","ALTER TABLE consult_outbox ADD COLUMN interaction_id TEXT;"),t("generation_id","ALTER TABLE consult_outbox ADD COLUMN generation_id TEXT;"),t("interaction_snapshot","ALTER TABLE consult_outbox ADD COLUMN interaction_snapshot TEXT;"),t("handler_command","ALTER TABLE consult_outbox ADD COLUMN handler_command TEXT;"),t("handler_args_json","ALTER TABLE consult_outbox ADD COLUMN handler_args_json TEXT;"),t("claim_token","ALTER TABLE consult_outbox ADD COLUMN claim_token TEXT;"),e.exec(`
154
154
  CREATE INDEX IF NOT EXISTS idx_consult_outbox_human_work_status ON consult_outbox(work_kind, status);
155
155
  CREATE INDEX IF NOT EXISTS idx_consult_outbox_human_work_dir_status ON consult_outbox(dir, work_kind, status);
156
156
  CREATE INDEX IF NOT EXISTS idx_consult_outbox_human_work_request_status ON consult_outbox(dir, request_id, work_kind, status);
157
157
  CREATE UNIQUE INDEX IF NOT EXISTS idx_consult_outbox_visual_request ON consult_outbox(dir, request_id, work_kind) WHERE work_kind = 'visual';
158
- `)}i(Ue,"addHumanWorkColumns");function ge(e){e.exec(`
158
+ `)}i(ge,"addHumanWorkColumns");function De(e){e.exec(`
159
159
  CREATE INDEX IF NOT EXISTS idx_nodes_parent ON nodes(parent);
160
160
  CREATE INDEX IF NOT EXISTS idx_nodes_created ON nodes(created);
161
- `)}i(ge,"addNodeParentCreatedIndexes");function Ce(e){e.exec(`
161
+ `)}i(De,"addNodeParentCreatedIndexes");function Ce(e){e.exec(`
162
162
  CREATE TABLE IF NOT EXISTS crons (
163
163
  cron_id TEXT PRIMARY KEY,
164
164
  name TEXT NOT NULL, -- agent-legible label; how it shows in list
@@ -213,38 +213,38 @@ CREATE TABLE IF NOT EXISTS cron_runs ( -- bounded ring, last 20 p
213
213
  FOREIGN KEY (cron_id) REFERENCES crons(cron_id) ON DELETE CASCADE
214
214
  );
215
215
  CREATE INDEX IF NOT EXISTS idx_cron_runs_cron ON cron_runs(cron_id, started);
216
- `)}i(Ce,"addCronsTables");function f(e){return`'${e.replace(/'/g,`'"'"'`)}'`}i(f,"shellSingleQuote");function De(e,n){let t=0;for(;;){const o=`${n}_${t}`;if(!e.split(`
217
- `).includes(o))return o;t++}}i(De,"uniqueHeredocDelimiter");function W(e,n,t){const o=De(n,t);return`${e} <<'${o}'
216
+ `)}i(Ce,"addCronsTables");function f(e){return`'${e.replace(/'/g,`'"'"'`)}'`}i(f,"shellSingleQuote");function he(e,n){let t=0;for(;;){const o=`${n}_${t}`;if(!e.split(`
217
+ `).includes(o))return o;t++}}i(he,"uniqueHeredocDelimiter");function $(e,n,t){const o=he(n,t);return`${e} <<'${o}'
218
218
  ${n}
219
- ${o}`}i(W,"heredocCommand");function he(e){if(typeof e!="string")return{};try{const n=JSON.parse(e);return typeof n!="object"||n===null||Array.isArray(n)?{}:n}catch{return{}}}i(he,"migrationPayload");function L(e,n,t){const o=e[n];if(typeof o!="string"||o.trim()==="")throw new Error(`trigger ${t} payload requires non-empty ${n}`);return o}i(L,"requiredString");function U(e,n){const t=e[n];return typeof t=="string"&&t.trim()!==""?t:void 0}i(U,"optionalString");function I(e,n){const t=e[n];return typeof t=="string"&&t.trim()!==""?t:void 0}i(I,"optionalColumn");function K(e,n,t,o){return W(`crtr node message send --to ${f(e)} --tier ${f(n)}`,t,`CRTR_MIGRATED_${o.replace(/[^A-Za-z0-9]/g,"_")}`)}i(K,"migratedMessageCommand");function we(e,n){return`printf '%s\\n' "$CRTR_GATE_STDOUT" | crtr node message send --to ${f(e)} --tier ${f(n)}`}i(we,"migratedGateStdoutMessageCommand");function xe(e,n){const t=[`crtr node new --kind ${f(L(e,"kind",n))}`],o=[["mode","mode"],["cwd","cwd"],["name","name"],["parent","parent"],["worktreeBase","worktree"],["forkFrom","fork-from"],["model","model"],["profile","profile"],["situationalContext","situational-context"]];for(const[T,r]of o){const E=U(e,T);E!==void 0&&t.push(`--${r} ${f(E)}`)}e.root===!0&&t.push("--root");const s=L(e,"prompt",n);return W(t.join(" "),s,`CRTR_MIGRATED_${n.replace(/[^A-Za-z0-9]/g,"_")}`)}i(xe,"migratedSpawnCommand");const q="migration.v22.skipped";function ve(e){const n=e.prepare("SELECT cwd FROM nodes WHERE parent IS NULL ORDER BY created LIMIT 1").get();return(n!==void 0?I(n,"cwd"):void 0)??process.cwd()}i(ve,"ambientMigrationCwd");function Fe(e){let n;try{n=e.prepare("SELECT eval_pid FROM triggers WHERE eval_state = 'running' AND eval_pid IS NOT NULL").all()}catch{return}for(const t of n){const o=t.eval_pid;if(!(typeof o!="number"||!Number.isInteger(o)||o<=1))try{process.kill(-o,"SIGTERM")}catch{}}}i(Fe,"reapRunningPredicateEvaluations");function ye(e){const n=[],t=e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'triggers'").get()!==void 0;t&&Fe(e);let o=[];if(t)try{o=e.prepare("SELECT * FROM triggers ORDER BY created, trigger_id").all()}catch(r){n.push({trigger_id:"<unreadable table>",reason:`triggers table could not be read: ${r instanceof Error?r.message:String(r)}`})}const s=ve(e),T=e.prepare(`
219
+ ${o}`}i($,"heredocCommand");function we(e){if(typeof e!="string")return{};try{const n=JSON.parse(e);return typeof n!="object"||n===null||Array.isArray(n)?{}:n}catch{return{}}}i(we,"migrationPayload");function L(e,n,t){const o=e[n];if(typeof o!="string"||o.trim()==="")throw new Error(`trigger ${t} payload requires non-empty ${n}`);return o}i(L,"requiredString");function g(e,n){const t=e[n];return typeof t=="string"&&t.trim()!==""?t:void 0}i(g,"optionalString");function m(e,n){const t=e[n];return typeof t=="string"&&t.trim()!==""?t:void 0}i(m,"optionalColumn");function K(e,n,t,o){return $(`crtr node message send --to ${f(e)} --tier ${f(n)}`,t,`CRTR_MIGRATED_${o.replace(/[^A-Za-z0-9]/g,"_")}`)}i(K,"migratedMessageCommand");function xe(e,n){return`printf '%s\\n' "$CRTR_GATE_STDOUT" | crtr node message send --to ${f(e)} --tier ${f(n)}`}i(xe,"migratedGateStdoutMessageCommand");function ye(e,n){const t=[`crtr node new --kind ${f(L(e,"kind",n))}`],o=[["mode","mode"],["cwd","cwd"],["name","name"],["parent","parent"],["worktreeBase","worktree"],["forkFrom","fork-from"],["model","model"],["profile","profile"],["situationalContext","situational-context"]];for(const[r,s]of o){const E=g(e,r);E!==void 0&&t.push(`--${s} ${f(E)}`)}e.root===!0&&t.push("--root");const T=L(e,"prompt",n);return $(t.join(" "),T,`CRTR_MIGRATED_${n.replace(/[^A-Za-z0-9]/g,"_")}`)}i(ye,"migratedSpawnCommand");const q="migration.v22.skipped";function ve(e){const n=e.prepare("SELECT cwd FROM nodes WHERE parent IS NULL ORDER BY created LIMIT 1").get();return(n!==void 0?m(n,"cwd"):void 0)??process.cwd()}i(ve,"ambientMigrationCwd");function Fe(e){let n;try{n=e.prepare("SELECT eval_pid FROM triggers WHERE eval_state = 'running' AND eval_pid IS NOT NULL").all()}catch{return}for(const t of n){const o=t.eval_pid;if(!(typeof o!="number"||!Number.isInteger(o)||o<=1))try{process.kill(-o,"SIGTERM")}catch{}}}i(Fe,"reapRunningPredicateEvaluations");function ke(e){const n=[],t=e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'triggers'").get()!==void 0;t&&Fe(e);let o=[];if(t)try{o=e.prepare("SELECT * FROM triggers ORDER BY created, trigger_id").all()}catch(s){n.push({trigger_id:"<unreadable table>",reason:`triggers table could not be read: ${s instanceof Error?s.message:String(s)}`})}const T=ve(e),r=e.prepare(`
220
220
  INSERT OR REPLACE INTO crons (
221
221
  cron_id, name, created_by, command, fire_at, recur, tz, expires_at,
222
222
  anchor_node, cancel_on_wake, cwd, env_json, profile, scope,
223
223
  run_timeout_s, overlap, on_output, sink, tier, created, updated
224
- ) VALUES (?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, NULL, ?, 'profile', ?, 'skip', 'on-failure', '{}', ?, ?, ?)`);for(const r of o){const E=I(r,"trigger_id");if(E===void 0){n.push({trigger_id:"<unidentified row>",reason:"row carries no trigger_id"});continue}try{ke(e,T,r,E,s)}catch(d){n.push({trigger_id:E,reason:d instanceof Error?d.message:String(d)})}}n.length>0&&(e.prepare("INSERT INTO canvas_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(q,JSON.stringify(n)),console.warn(`[canvas migration v22] ${n.length} retired schedule(s) could not be converted to crons and were dropped; see canvas_meta['${q}']: `+n.map(r=>`${r.trigger_id} (${r.reason})`).join("; "))),e.exec(`
224
+ ) VALUES (?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, NULL, ?, 'profile', ?, 'skip', 'on-failure', '{}', ?, ?, ?)`);for(const s of o){const E=m(s,"trigger_id");if(E===void 0){n.push({trigger_id:"<unidentified row>",reason:"row carries no trigger_id"});continue}try{Me(e,r,s,E,T)}catch(d){n.push({trigger_id:E,reason:d instanceof Error?d.message:String(d)})}}n.length>0&&(e.prepare("INSERT INTO canvas_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(q,JSON.stringify(n)),console.warn(`[canvas migration v22] ${n.length} retired schedule(s) could not be converted to crons and were dropped; see canvas_meta['${q}']: `+n.map(s=>`${s.trigger_id} (${s.reason})`).join("; "))),e.exec(`
225
225
  DROP INDEX IF EXISTS idx_triggers_fire;
226
226
  DROP INDEX IF EXISTS idx_triggers_node;
227
227
  DROP INDEX IF EXISTS idx_triggers_owner;
228
228
  DROP INDEX IF EXISTS idx_triggers_eval;
229
229
  DROP INDEX IF EXISTS idx_triggers_deadline;
230
230
  DROP TABLE IF EXISTS triggers;
231
- `)}i(ye,"migrateTriggersToCrons");function ke(e,n,t,o,s){const T=L(t,"owner_id",o),r=e.prepare("SELECT cwd, profile_id FROM nodes WHERE node_id = ?").get(T),E=(r===void 0?void 0:I(r,"cwd"))??s,d=r===void 0?null:I(r,"profile_id")??null,_=I(t,"node_id")??null,c=L(t,"action",o),N=L(t,"action_mode",o),u=L(t,"trigger_type",o),R=he(t.payload),M=I(t,"created")??new Date().toISOString(),C=N==="deadline_message"?"urgent":U(R,"tier")??"normal",x=U(R,"label");let p,D,G=!1;if(c==="msg"&&(N==="inbox_message"||N==="deadline_message")){if(_===null)throw new Error("has no message target");const O=U(R,"body");O!==void 0?p=K(_,C,O,o):u==="when"?(G=!0,p=we(_,C)):p=K(_,C,x??"Scheduled message (no body was recorded when this schedule was armed).",o),D=x??(N==="deadline_message"?"deadline":"scheduled message")}else if(c==="msg"&&N==="fresh_revive"){if(_===null)throw new Error("has no revive target");p=`crtr node lifecycle revive ${f(_)} --fresh`,D=x??"scheduled fresh revive"}else if(c==="new"&&N==="node_birth")p=xe(R,o),D=U(R,"name")??`scheduled ${L(R,"kind",o)} node`;else throw new Error(`has unsupported action ${c}/${N}`);let v,F,B=null;if(u==="when"){v=L(t,"next_eval_at",o),F=L(t,"eval_every",o),B=I(t,"timeout_at")??null;const O=L(t,"when_script",o);p=`${G?`if ! CRTR_GATE_STDOUT="$(
232
- ${O}
231
+ `)}i(ke,"migrateTriggersToCrons");function Me(e,n,t,o,T){const r=L(t,"owner_id",o),s=e.prepare("SELECT cwd, profile_id FROM nodes WHERE node_id = ?").get(r),E=(s===void 0?void 0:m(s,"cwd"))??T,d=s===void 0?null:m(s,"profile_id")??null,_=m(t,"node_id")??null,c=L(t,"action",o),N=L(t,"action_mode",o),u=L(t,"trigger_type",o),R=we(t.payload),M=m(t,"created")??new Date().toISOString(),C=N==="deadline_message"?"urgent":g(R,"tier")??"normal",y=g(R,"label");let O,h,B=!1;if(c==="msg"&&(N==="inbox_message"||N==="deadline_message")){if(_===null)throw new Error("has no message target");const A=g(R,"body");A!==void 0?O=K(_,C,A,o):u==="when"?(B=!0,O=xe(_,C)):O=K(_,C,y??"Scheduled message (no body was recorded when this schedule was armed).",o),h=y??(N==="deadline_message"?"deadline":"scheduled message")}else if(c==="msg"&&N==="fresh_revive"){if(_===null)throw new Error("has no revive target");O=`crtr node lifecycle revive ${f(_)} --fresh`,h=y??"scheduled fresh revive"}else if(c==="new"&&N==="node_birth")O=ye(R,o),h=g(R,"name")??`scheduled ${L(R,"kind",o)} node`;else throw new Error(`has unsupported action ${c}/${N}`);let v,F,G=null;if(u==="when"){v=L(t,"next_eval_at",o),F=L(t,"eval_every",o),G=m(t,"timeout_at")??null;const A=L(t,"when_script",o);O=`${B?`if ! CRTR_GATE_STDOUT="$(
232
+ ${A}
233
233
  )"; then`:`if ! (
234
- ${O}
234
+ ${A}
235
235
  ); then`}
236
236
  exit 0
237
237
  fi
238
238
  {
239
- ${p}
240
- } && crtr cron cancel "$CRTR_CRON_ID"`}else if(u==="at"||u==="every"||u==="until")v=L(t,"fire_at",o),F=u==="every"?L(t,"recur",o):null;else throw new Error(`has unknown timing type ${u}`);if(N==="deadline_message"&&_!==null){const O=e.prepare("SELECT cron_id FROM crons WHERE anchor_node = ? AND cancel_on_wake = 1 AND cron_id <> ?").get(_,o);if(O!==void 0)throw new Error(`node ${_} already has a migrated deadline (${String(O.cron_id)}); only one is allowed`)}n.run(o,D,T,p,v,F,B,_,N==="deadline_message"?1:0,E,d,300,C,M,M)}i(ke,"convertTriggerRow");function Me(e){const n=w(e,"crons");n.size===0||n.has("run_pid_identity")||e.exec("ALTER TABLE crons ADD COLUMN run_pid_identity TEXT;")}i(Me,"addCronRunPidIdentityColumn");function Ge(e){const n=w(e,"crons");n.size!==0&&(n.has("run_out_of_band")||e.exec("ALTER TABLE crons ADD COLUMN run_out_of_band INTEGER NOT NULL DEFAULT 0;"),n.has("queued")&&e.exec("ALTER TABLE crons DROP COLUMN queued;"))}i(Ge,"addCronOutOfBandColumn");function Be(e){e.exec(`
239
+ ${O}
240
+ } && crtr cron cancel "$CRTR_CRON_ID"`}else if(u==="at"||u==="every"||u==="until")v=L(t,"fire_at",o),F=u==="every"?L(t,"recur",o):null;else throw new Error(`has unknown timing type ${u}`);if(N==="deadline_message"&&_!==null){const A=e.prepare("SELECT cron_id FROM crons WHERE anchor_node = ? AND cancel_on_wake = 1 AND cron_id <> ?").get(_,o);if(A!==void 0)throw new Error(`node ${_} already has a migrated deadline (${String(A.cron_id)}); only one is allowed`)}n.run(o,h,r,O,v,F,G,_,N==="deadline_message"?1:0,E,d,300,C,M,M)}i(Me,"convertTriggerRow");function Be(e){const n=x(e,"crons");n.size===0||n.has("run_pid_identity")||e.exec("ALTER TABLE crons ADD COLUMN run_pid_identity TEXT;")}i(Be,"addCronRunPidIdentityColumn");function Ge(e){const n=x(e,"crons");n.size!==0&&(n.has("run_out_of_band")||e.exec("ALTER TABLE crons ADD COLUMN run_out_of_band INTEGER NOT NULL DEFAULT 0;"),n.has("queued")&&e.exec("ALTER TABLE crons DROP COLUMN queued;"))}i(Ge,"addCronOutOfBandColumn");function He(e){e.exec(`
241
241
  CREATE TABLE IF NOT EXISTS warm_pool (
242
242
  node_id TEXT PRIMARY KEY REFERENCES nodes(node_id) ON DELETE CASCADE,
243
243
  recipe_key TEXT NOT NULL, -- frozen launch tuple this spare was minted for
244
244
  created TEXT NOT NULL -- ISO 8601, mint time (oldest spare claimed first)
245
245
  );
246
246
  CREATE INDEX IF NOT EXISTS idx_warm_pool_recipe ON warm_pool(recipe_key, created);
247
- `)}i(Be,"addWarmPoolTable");function He(e){const n=e.prepare("SELECT node_id, dir, root, request_id, work_kind, status, final_report, updated_at FROM consult_outbox").all();e.exec(`
247
+ `)}i(He,"addWarmPoolTable");function Pe(e){const n=e.prepare("SELECT node_id, dir, root, request_id, work_kind, status, final_report, updated_at FROM consult_outbox").all();e.exec(`
248
248
  CREATE TABLE consult_outbox_new (
249
249
  node_id TEXT PRIMARY KEY,
250
250
  ticket_node_id TEXT NOT NULL,
@@ -256,7 +256,7 @@ CREATE TABLE consult_outbox_new (
256
256
  );
257
257
  `);const t=e.prepare(`
258
258
  INSERT INTO consult_outbox_new (node_id, ticket_node_id, request_id, work_kind, status, final_report, updated_at)
259
- VALUES (?, ?, ?, ?, ?, ?, ?)`);let o=0;for(const s of n){const T=oe(s.dir);if(!(s.root===H(s.root)&&s.dir===y(s.root,T))||!re(T)){o+=1;continue}t.run(s.node_id,T,s.request_id,s.work_kind,s.status,s.final_report,s.updated_at)}o>0&&console.warn(`[canvas migration v26] dropped ${o} consult_outbox row(s) whose legacy ticket path cannot safely map to a ticket node id`),e.exec(`
259
+ VALUES (?, ?, ?, ?, ?, ?, ?)`);let o=0;for(const T of n){const r=ie(T.dir);if(!(T.root===H(T.root)&&T.dir===w(T.root,r))||!se(r)){o+=1;continue}t.run(T.node_id,r,T.request_id,T.work_kind,T.status,T.final_report,T.updated_at)}o>0&&console.warn(`[canvas migration v26] dropped ${o} consult_outbox row(s) whose legacy ticket path cannot safely map to a ticket node id`),e.exec(`
260
260
  DROP TABLE consult_outbox;
261
261
  ALTER TABLE consult_outbox_new RENAME TO consult_outbox;
262
262
 
@@ -265,7 +265,7 @@ CREATE INDEX IF NOT EXISTS idx_consult_outbox_human_work_status ON consult_outbo
265
265
  CREATE INDEX IF NOT EXISTS idx_consult_outbox_ticket_status ON consult_outbox(ticket_node_id, work_kind, status);
266
266
  CREATE INDEX IF NOT EXISTS idx_consult_outbox_ticket_request_status ON consult_outbox(ticket_node_id, request_id, work_kind, status);
267
267
  CREATE UNIQUE INDEX IF NOT EXISTS idx_consult_outbox_visual_request ON consult_outbox(ticket_node_id, request_id, work_kind) WHERE work_kind = 'visual';
268
- `)}i(He,"narrowHumanWorkOutbox");function Pe(e){e.exec(`
268
+ `)}i(Pe,"narrowHumanWorkOutbox");function be(e){e.exec(`
269
269
  CREATE TABLE IF NOT EXISTS reviews (
270
270
  review_id TEXT PRIMARY KEY,
271
271
  idempotency_key TEXT NOT NULL UNIQUE,
@@ -309,7 +309,7 @@ CREATE INDEX IF NOT EXISTS idx_reviews_state ON reviews(state);
309
309
  CREATE INDEX IF NOT EXISTS idx_reviews_origin ON reviews(origin_node_id);
310
310
  CREATE INDEX IF NOT EXISTS idx_reviews_file ON reviews(file);
311
311
  CREATE INDEX IF NOT EXISTS idx_reviews_bridge ON reviews(bridge_node_id);
312
- `)}i(Pe,"addReviewsTable");function be(e){e.exec(`
312
+ `)}i(be,"addReviewsTable");function Ye(e){e.exec(`
313
313
  CREATE TABLE IF NOT EXISTS review_comments (
314
314
  comment_id TEXT PRIMARY KEY,
315
315
  review_id TEXT NOT NULL,
@@ -354,13 +354,13 @@ CREATE INDEX IF NOT EXISTS idx_review_comment_events_review_seq
354
354
  ON review_comment_events(review_id, seq);
355
355
  CREATE INDEX IF NOT EXISTS idx_review_comment_events_comment_seq
356
356
  ON review_comment_events(comment_id, seq);
357
- `)}i(be,"addReviewCommentTables");function Ye(e){e.exec(`
357
+ `)}i(Ye,"addReviewCommentTables");function We(e){e.exec(`
358
358
  ALTER TABLE review_comments
359
359
  ADD COLUMN anchor_state TEXT NOT NULL DEFAULT 'live' CHECK (anchor_state IN ('live', 'detached'));
360
- `)}i(Ye,"addReviewCommentAnchorState");function $e(e){e.exec("DROP TABLE IF EXISTS consult_outbox")}i($e,"dropConsultOutbox");function We(e){e.exec("ALTER TABLE reviews ADD COLUMN submit_requested_at TEXT")}i(We,"addReviewSubmitRequested");function Ke(e){e.exec(`
360
+ `)}i(We,"addReviewCommentAnchorState");function $e(e){e.exec("DROP TABLE IF EXISTS consult_outbox")}i($e,"dropConsultOutbox");function Ke(e){e.exec("ALTER TABLE reviews ADD COLUMN submit_requested_at TEXT")}i(Ke,"addReviewSubmitRequested");function qe(e){e.exec(`
361
361
  ALTER TABLE crons ADD COLUMN held INTEGER NOT NULL DEFAULT 0;
362
362
  ALTER TABLE crons ADD COLUMN last_poke_at TEXT;
363
- `)}i(Ke,"addCronHeldColumns");function qe(e){e.exec(`
363
+ `)}i(qe,"addCronHeldColumns");function je(e){e.exec(`
364
364
  CREATE TABLE human_action_deliveries (
365
365
  request_id TEXT PRIMARY KEY,
366
366
  state TEXT NOT NULL,
@@ -378,18 +378,18 @@ CREATE TABLE human_action_deliveries (
378
378
  updated_at INTEGER NOT NULL
379
379
  );
380
380
  CREATE INDEX idx_human_action_deliveries_due ON human_action_deliveries(state, next_attempt_at);
381
- `)}i(qe,"addHumanActionDeliveries");function je(e){const n=l(e);a(e,n,"pi_session_file","ALTER TABLE nodes ADD COLUMN pi_session_file TEXT;");for(const t of X(S(),{withFileTypes:!0}))if(t.isDirectory())try{const o=JSON.parse(h(m(t.name),"utf8"));typeof o.pi_session_file=="string"&&e.prepare("UPDATE nodes SET pi_session_file = ? WHERE node_id = ?").run(o.pi_session_file,t.name)}catch{}e.exec("CREATE INDEX IF NOT EXISTS idx_nodes_pi_session_file ON nodes(pi_session_file);")}i(je,"addNodeSessionFileIndex");function j(e,n){const t=i(E=>{const d=H(E);return A(d)?te(d):d},"canonical"),o=e.prepare("UPDATE nodes SET pi_session_file = ? WHERE node_id = ?");e.exec("DROP INDEX IF EXISTS idx_nodes_pi_session_file;");const s=e.prepare("SELECT node_id FROM nodes ORDER BY created ASC, node_id ASC").all();for(const{node_id:E}of s){const d=m(E);if(P(d)===null){o.run(null,E);continue}const _=Ee(d,()=>{const c=P(d);if(c===null)throw new Error(`node ${E} session metadata changed during ownership migration`);if(typeof c.pi_session_file!="string")return null;const N=c.pi_session_file,u=t(N);return u!==N&&(c.pi_session_file=u,ae(d,c)),u});o.run(_,E)}const T=e.prepare(`
381
+ `)}i(je,"addHumanActionDeliveries");function ze(e){const n=l(e);a(e,n,"pi_session_file","ALTER TABLE nodes ADD COLUMN pi_session_file TEXT;");for(const t of U(I(),{withFileTypes:!0}))if(t.isDirectory())try{const o=JSON.parse(S(X(t.name),"utf8"));typeof o.pi_session_file=="string"&&e.prepare("UPDATE nodes SET pi_session_file = ? WHERE node_id = ?").run(o.pi_session_file,t.name)}catch{}e.exec("CREATE INDEX IF NOT EXISTS idx_nodes_pi_session_file ON nodes(pi_session_file);")}i(ze,"addNodeSessionFileIndex");function j(e,n){const t=i(E=>{const d=H(E);return p(d)?te(d):d},"canonical"),o=e.prepare("UPDATE nodes SET pi_session_file = ? WHERE node_id = ?");e.exec("DROP INDEX IF EXISTS idx_nodes_pi_session_file;");const T=e.prepare("SELECT node_id FROM nodes ORDER BY created ASC, node_id ASC").all();for(const{node_id:E}of T){const d=X(E);if(P(d)===null){o.run(null,E);continue}const _=ae(d,()=>{const c=P(d);if(c===null)throw new Error(`node ${E} session metadata changed during ownership migration`);if(typeof c.pi_session_file!="string")return null;const N=c.pi_session_file,u=t(N);return u!==N&&(c.pi_session_file=u,de(d,c)),u});o.run(_,E)}const r=e.prepare(`
382
382
  SELECT pi_session_file
383
383
  FROM nodes
384
384
  WHERE pi_session_file IS NOT NULL
385
385
  GROUP BY pi_session_file
386
386
  HAVING COUNT(*) > 1
387
- `).all();if(!n&&T.length>0){const E=T.map(({pi_session_file:d})=>d).join(", ");throw new Error(`cannot restore unique Pi session ownership: authoritative metadata has concurrent claimants for ${E}`)}const r=e.prepare("UPDATE nodes SET pi_session_file = NULL WHERE node_id = ?");for(const{pi_session_file:E}of T){const d=e.prepare(`
387
+ `).all();if(!n&&r.length>0){const E=r.map(({pi_session_file:d})=>d).join(", ");throw new Error(`cannot restore unique Pi session ownership: authoritative metadata has concurrent claimants for ${E}`)}const s=e.prepare("UPDATE nodes SET pi_session_file = NULL WHERE node_id = ?");for(const{pi_session_file:E}of r){const d=e.prepare(`
388
388
  SELECT node_id
389
389
  FROM nodes
390
390
  WHERE pi_session_file = ?
391
391
  ORDER BY created ASC, node_id ASC
392
- `).all(E);for(const{node_id:_}of d.slice(1)){if(!b(m(_),N=>{const u=N.pi_session_file;if(typeof u!="string"||t(u)!==E)throw new Error(`node ${_} session metadata changed during ownership migration`);return N.pi_session_id=null,N.pi_session_file=null,!0}))throw new Error(`node ${_} session metadata changed during ownership migration`);r.run(_)}}e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_nodes_pi_session_file ON nodes(pi_session_file);")}i(j,"reconcileNodeSessionFileOwners");function ze(e){j(e,!0)}i(ze,"makeNodeSessionFileUnique");function Je(e){j(e,!1)}i(Je,"repairNodeSessionFileUniqueIndex");function Qe(e){const n=l(e);a(e,n,"frozen_at","ALTER TABLE nodes ADD COLUMN frozen_at TEXT;"),a(e,n,"respawn_failures","ALTER TABLE nodes ADD COLUMN respawn_failures INTEGER NOT NULL DEFAULT 0;"),a(e,n,"respawn_not_before","ALTER TABLE nodes ADD COLUMN respawn_not_before TEXT;"),a(e,n,"launched_at","ALTER TABLE nodes ADD COLUMN launched_at TEXT;"),a(e,n,"last_settled_at","ALTER TABLE nodes ADD COLUMN last_settled_at TEXT;"),a(e,n,"terminal_reason","ALTER TABLE nodes ADD COLUMN terminal_reason TEXT;"),e.exec(`
392
+ `).all(E);for(const{node_id:_}of d.slice(1)){if(!b(X(_),N=>{const u=N.pi_session_file;if(typeof u!="string"||t(u)!==E)throw new Error(`node ${_} session metadata changed during ownership migration`);return N.pi_session_id=null,N.pi_session_file=null,!0}))throw new Error(`node ${_} session metadata changed during ownership migration`);s.run(_)}}e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_nodes_pi_session_file ON nodes(pi_session_file);")}i(j,"reconcileNodeSessionFileOwners");function Je(e){j(e,!0)}i(Je,"makeNodeSessionFileUnique");function Qe(e){j(e,!1)}i(Qe,"repairNodeSessionFileUniqueIndex");function Ve(e){const n=l(e);a(e,n,"frozen_at","ALTER TABLE nodes ADD COLUMN frozen_at TEXT;"),a(e,n,"respawn_failures","ALTER TABLE nodes ADD COLUMN respawn_failures INTEGER NOT NULL DEFAULT 0;"),a(e,n,"respawn_not_before","ALTER TABLE nodes ADD COLUMN respawn_not_before TEXT;"),a(e,n,"launched_at","ALTER TABLE nodes ADD COLUMN launched_at TEXT;"),a(e,n,"last_settled_at","ALTER TABLE nodes ADD COLUMN last_settled_at TEXT;"),a(e,n,"terminal_reason","ALTER TABLE nodes ADD COLUMN terminal_reason TEXT;"),e.exec(`
393
393
  UPDATE nodes SET terminal_reason = CASE
394
394
  WHEN status = 'done' AND final_report IS NOT NULL THEN 'finalized'
395
395
  WHEN status = 'done' AND intent = 'parked' THEN 'parked'
@@ -398,7 +398,7 @@ UPDATE nodes SET terminal_reason = CASE
398
398
  WHEN status = 'dead' THEN 'crashed'
399
399
  END
400
400
  WHERE status IN ('done','canceled','dead') AND terminal_reason IS NULL;
401
- `)}i(Qe,"addNodeLifecycleColumns");function Ve(e){const n=l(e);a(e,n,"description","ALTER TABLE nodes ADD COLUMN description TEXT;"),a(e,n,"cycles","ALTER TABLE nodes ADD COLUMN cycles INTEGER;");const t=S();if(!A(t))return;const o=e.prepare("UPDATE nodes SET description = ?, cycles = ? WHERE node_id = ?");for(const s of X(t)){const T=m(s);if(!A(T))continue;let r;try{r=JSON.parse(h(T,"utf8"))}catch{continue}const E=typeof r.description=="string"?r.description:null,d=typeof r.cycles=="number"?r.cycles:null;o.run(E,d,s)}}i(Ve,"addNodeLabelColumns");function Ze(e){const n=l(e);a(e,n,"outcome_kind","ALTER TABLE nodes ADD COLUMN outcome_kind TEXT;"),a(e,n,"outcome_reason","ALTER TABLE nodes ADD COLUMN outcome_reason TEXT;"),a(e,n,"outcome_at","ALTER TABLE nodes ADD COLUMN outcome_at TEXT;"),a(e,n,"outcome_revision","ALTER TABLE nodes ADD COLUMN outcome_revision INTEGER NOT NULL DEFAULT 0;"),a(e,n,"outcome_detail_json","ALTER TABLE nodes ADD COLUMN outcome_detail_json TEXT;"),a(e,n,"deadline_at","ALTER TABLE nodes ADD COLUMN deadline_at TEXT;"),e.exec(`
401
+ `)}i(Ve,"addNodeLifecycleColumns");function Ze(e){const n=l(e);a(e,n,"description","ALTER TABLE nodes ADD COLUMN description TEXT;"),a(e,n,"cycles","ALTER TABLE nodes ADD COLUMN cycles INTEGER;");const t=I();if(!p(t))return;const o=e.prepare("UPDATE nodes SET description = ?, cycles = ? WHERE node_id = ?");for(const T of U(t)){const r=X(T);if(!p(r))continue;let s;try{s=JSON.parse(S(r,"utf8"))}catch{continue}const E=typeof s.description=="string"?s.description:null,d=typeof s.cycles=="number"?s.cycles:null;o.run(E,d,T)}}i(Ze,"addNodeLabelColumns");function en(e){const n=l(e);a(e,n,"outcome_kind","ALTER TABLE nodes ADD COLUMN outcome_kind TEXT;"),a(e,n,"outcome_reason","ALTER TABLE nodes ADD COLUMN outcome_reason TEXT;"),a(e,n,"outcome_at","ALTER TABLE nodes ADD COLUMN outcome_at TEXT;"),a(e,n,"outcome_revision","ALTER TABLE nodes ADD COLUMN outcome_revision INTEGER NOT NULL DEFAULT 0;"),a(e,n,"outcome_detail_json","ALTER TABLE nodes ADD COLUMN outcome_detail_json TEXT;"),a(e,n,"deadline_at","ALTER TABLE nodes ADD COLUMN deadline_at TEXT;"),e.exec(`
402
402
  CREATE TABLE IF NOT EXISTS node_outcome_deliveries (
403
403
  node_id TEXT PRIMARY KEY,
404
404
  state TEXT NOT NULL,
@@ -431,11 +431,14 @@ UPDATE nodes SET outcome_kind='failure',
431
431
  outcome_reason=COALESCE(terminal_reason,'crashed'),
432
432
  outcome_at=COALESCE(finalized_at, created), outcome_revision=1
433
433
  WHERE final_report IS NULL AND status IN ('done','dead','canceled') AND outcome_at IS NULL;
434
- `)}i(Ze,"addNodeOutcomeAndDeadline");function en(e){e.exec(`
434
+ `)}i(en,"addNodeOutcomeAndDeadline");function nn(e){const n=l(e);a(e,n,"telemetry_tokens_in","ALTER TABLE nodes ADD COLUMN telemetry_tokens_in INTEGER;"),a(e,n,"telemetry_context_tokens","ALTER TABLE nodes ADD COLUMN telemetry_context_tokens INTEGER;"),a(e,n,"telemetry_last_activity","ALTER TABLE nodes ADD COLUMN telemetry_last_activity TEXT;"),a(e,n,"telemetry_updated_at","ALTER TABLE nodes ADD COLUMN telemetry_updated_at TEXT;");const t=e.prepare(`UPDATE nodes
435
+ SET telemetry_tokens_in = ?, telemetry_context_tokens = ?,
436
+ telemetry_last_activity = ?, telemetry_updated_at = ?
437
+ WHERE node_id = ?`);for(const{node_id:o}of e.prepare("SELECT node_id FROM nodes").all()){const T=w(I(),o,"job","telemetry.json");if(p(T))try{const r=JSON.parse(S(T,"utf8")),s=typeof r.tokens_in=="number"&&Number.isFinite(r.tokens_in)?r.tokens_in:null,E=typeof r.context_tokens=="number"&&Number.isFinite(r.context_tokens)?r.context_tokens:null,d=typeof r.last_activity=="string"?r.last_activity:null,_=oe(T).mtime.toISOString();t.run(s,E,d,_,o)}catch{}}}i(nn,"addNodeTelemetryColumns");function tn(e){e.exec(`
435
438
  CREATE INDEX IF NOT EXISTS deliveries_external_due_order
436
439
  ON deliveries(state, next_attempt_at, created_at, delivery_id)
437
440
  WHERE destination_kind = 'external_action' AND canceled_at IS NULL;
438
441
  DROP INDEX IF EXISTS deliveries_external_due;
439
442
  CREATE INDEX IF NOT EXISTS idx_nodes_parent_created ON nodes(parent, created);
440
443
  CREATE INDEX IF NOT EXISTS idx_edges_type_created ON edges(type, created);
441
- `)}i(en,"addRecurringLaneIndexes");const nn=se.filter(e=>e.lane==="journaled").map(e=>n=>e.apply(n,ie()));function tn(e){V(e)}i(tn,"projectLiveNodeState");const g=[de,_e,ce,Ne,ue,le,Le,Oe,pe,Ae,fe,Ie,Re,$,me,$,Xe,Se,Ue,ge,Ce,ye,Me,Ge,Be,He,Pe,be,Ye,$e,We,Ke,qe,je,Qe,ze,Je,Ve,Ze,...nn,e=>{Q(e),Z(e),ee(e),ne(e)},en,tn],on=new Set([3]);function k(e){return e.prepare("PRAGMA user_version").get().user_version}i(k,"currentUserVersion");function z(e,n){g[n](e),e.exec(`PRAGMA user_version = ${n+1}`)}i(z,"applyMigration");function On(e){const n=k(e);if(n>g.length)throw new Error(`unsupported canvas schema version ${n} (latest supported ${g.length})`);if(n===g.length)return;const t=e.prepare("PRAGMA busy_timeout").get().timeout;e.exec("PRAGMA busy_timeout = 60000;");try{rn(e)}finally{e.exec(`PRAGMA busy_timeout = ${t};`)}}i(On,"migrate");function rn(e){for(;;){const n=k(e);if(n>=g.length)return;if(e.isTransaction||on.has(n)){z(e,n);continue}e.exec("BEGIN IMMEDIATE");try{k(e)===n&&z(e,n),e.exec("COMMIT")}catch(t){try{e.exec("ROLLBACK")}catch{}throw t}}}i(rn,"runPendingMigrations");export{g as MIGRATIONS,On as migrate};
444
+ `)}i(tn,"addRecurringLaneIndexes");const on=Te.filter(e=>e.lane==="journaled").map(e=>n=>e.apply(n,re()));function rn(e){V(e)}i(rn,"projectLiveNodeState");const D=[_e,ce,Ne,ue,le,Le,pe,Ae,Oe,fe,me,Re,Ie,W,Xe,W,Se,Ue,ge,De,Ce,ke,Be,Ge,He,Pe,be,Ye,We,$e,Ke,qe,je,ze,Ve,Je,Qe,Ze,en,...on,e=>{Q(e),Z(e),ee(e),ne(e)},tn,rn,nn],sn=new Set([3]);function k(e){return e.prepare("PRAGMA user_version").get().user_version}i(k,"currentUserVersion");function z(e,n){D[n](e),e.exec(`PRAGMA user_version = ${n+1}`)}i(z,"applyMigration");function fn(e){const n=k(e);if(n>D.length)throw new Error(`unsupported canvas schema version ${n} (latest supported ${D.length})`);if(n===D.length)return;const t=e.prepare("PRAGMA busy_timeout").get().timeout;e.exec("PRAGMA busy_timeout = 60000;");try{Tn(e)}finally{e.exec(`PRAGMA busy_timeout = ${t};`)}}i(fn,"migrate");function Tn(e){for(;;){const n=k(e);if(n>=D.length)return;if(e.isTransaction||sn.has(n)){z(e,n);continue}e.exec("BEGIN IMMEDIATE");try{k(e)===n&&z(e,n),e.exec("COMMIT")}catch(t){try{e.exec("ROLLBACK")}catch{}throw t}}}i(Tn,"runPendingMigrations");export{D as MIGRATIONS,fn as migrate};
@@ -1,6 +1,6 @@
1
1
  import { type FlatRow, type FoldState, type SubtreeActivity } from './nav-render.js';
2
2
  import type { NodeMeta } from './index.js';
3
- export { PI_MAX_WIDGET_LINES, VIEWPORT_FALLBACK_ROWS, ESC, RESET, BOLD, DIM, REVERSE, BG_ATTACHED, GREEN, RED, YELLOW, CYAN, GRAY, nodeGlyph, visibleWidth, truncate, fillWidth, fillBar, readTelemetry, fmtTokens, tokensCell, activityCell, cycleBadge, navLabel, shortId, askBadge, liveBelowBadge, isAttached, hasBrokerViewers, fetchAsksMap, graphWidgetBudget, GRAPH_HINT, type Telemetry, type FlatRow, type FoldState, type SubtreeActivity, } from './nav-render.js';
3
+ export { PI_MAX_WIDGET_LINES, VIEWPORT_FALLBACK_ROWS, ESC, RESET, BOLD, DIM, REVERSE, BG_ATTACHED, GREEN, RED, YELLOW, CYAN, GRAY, nodeGlyph, visibleWidth, truncate, fillWidth, fillBar, fmtTokens, tokensCell, activityCell, cycleBadge, navLabel, shortId, askBadge, liveBelowBadge, isAttached, hasBrokerViewers, fetchAsksMap, graphWidgetBudget, GRAPH_HINT, type FlatRow, type FoldState, type SubtreeActivity, } from './nav-render.js';
4
4
  /** First manager (by created) — the UP step for the ancestry spine. */
5
5
  export declare function managerOf(id: string): string | undefined;
6
6
  /** A kind:'human' node is a control-plane ASK (a page on the human's