@tekmidian/pai 1.0.0 → 1.0.2

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 (218) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +67 -5
  3. package/dist/aibroker-client-BxzeEHPF.mjs +3 -0
  4. package/dist/{aibroker-client-CXEYBzbf.mjs → aibroker-client-CQPGqLxL.mjs} +1 -1
  5. package/dist/atomic-file-BorMa4T3.mjs +21 -0
  6. package/dist/{auto-route-D5SXrMpB.mjs → auto-route-B4azPk4l.mjs} +3 -3
  7. package/dist/auto-route-BjoMHKyI.mjs +11 -0
  8. package/dist/budget-Dod6rnA9.mjs +15 -0
  9. package/dist/{caller-identity-CVTuiLSs.mjs → caller-identity-yLFb7CKq.mjs} +6 -5
  10. package/dist/{capacity-DaXrVj3J.mjs → capacity-DEveQdFV.mjs} +3 -3
  11. package/dist/{chain-BcQlIlEd.mjs → chain-D-yvET_y.mjs} +5 -5
  12. package/dist/cli/index.mjs +1621 -357
  13. package/dist/cockpit-actions-BWunx3rY.mjs +20 -0
  14. package/dist/{cockpit-actions-ODmt8yF9.mjs → cockpit-actions-C8GlTzts.mjs} +84 -42
  15. package/dist/cockpit-memory-vTlFWV7F.mjs +20 -0
  16. package/dist/{config-BSXKyeJ1.mjs → config-Bu1_vbY8.mjs} +42 -3
  17. package/dist/{config-B955yYmo.mjs → config-Cxi-aBf4.mjs} +2 -2
  18. package/dist/{config-TaWmdTLx.mjs → config-DtENJ6cL.mjs} +1 -1
  19. package/dist/{config-D5chi2LO.mjs → config-XpZWOYOG.mjs} +2 -2
  20. package/dist/{controls-BGkK_Bdi.mjs → controls-BcKFHeG1.mjs} +37 -22
  21. package/dist/daemon/index.mjs +43 -42
  22. package/dist/{daemon-CorGh6Ub.mjs → daemon-ColVHwGZ.mjs} +103 -55
  23. package/dist/daemon-N7WhYi6I.mjs +45 -0
  24. package/dist/daemon-mcp/index.mjs +40 -39
  25. package/dist/{define-DGFu-sCf.mjs → define-CjJsmq-6.mjs} +1 -1
  26. package/dist/{detect-C1d5cUkT.mjs → detect-9CZNO0yf.mjs} +2 -2
  27. package/dist/detect-D1ziFFfA.mjs +10 -0
  28. package/dist/{embed-pass-CeQD8kRE.mjs → embed-pass-DIWjA68P.mjs} +5 -5
  29. package/dist/{embedding-gate-BHuBsgHD.mjs → embedding-gate-6rZrWRXa.mjs} +5 -5
  30. package/dist/{embedding-gate-Z7CJSOJk.mjs → embedding-gate-Cnk4YCyX.mjs} +3 -3
  31. package/dist/{embeddings-D4t6L-EH.mjs → embeddings-BVq3esBF.mjs} +1 -1
  32. package/dist/{embeddings-OF9Pt4by.mjs → embeddings-CIkJBKd-.mjs} +1 -1
  33. package/dist/{endreason-x1KOSrcO.mjs → endreason-C577xIQz.mjs} +7 -6
  34. package/dist/{env-DArqGq-Z.mjs → env-BE8mrsxr.mjs} +1 -1
  35. package/dist/factory-Bsib-qDG.mjs +9 -0
  36. package/dist/{factory-BtjbQ0np.mjs → factory-DjAAsqr_.mjs} +15 -13
  37. package/dist/{fallback-BIyEpPsQ.mjs → fallback-DFlItw1Z.mjs} +5 -5
  38. package/dist/{fmt-age-BiSHrTKN.mjs → fmt-age-ByDkvkoU.mjs} +1 -1
  39. package/dist/{health-C6jZWvRG.mjs → health-Dnym-qcT.mjs} +4 -4
  40. package/dist/{helpers-DFmYRCOa.mjs → helpers-BD6V-p9w.mjs} +2 -2
  41. package/dist/helpers-CMGjy_0N.mjs +10 -0
  42. package/dist/{helpers-CJpb_MNB.mjs → helpers-CRuBUas3.mjs} +87 -38
  43. package/dist/hooks/capture-all-events.mjs +52 -11
  44. package/dist/hooks/capture-session-summary.mjs +64 -47
  45. package/dist/hooks/capture-tool-output.mjs +49 -8
  46. package/dist/hooks/context-compression-hook.mjs +30 -10
  47. package/dist/hooks/initialize-session.mjs +1 -0
  48. package/dist/hooks/load-core-context.mjs +1 -1
  49. package/dist/hooks/load-project-context.mjs +32 -29
  50. package/dist/hooks/security-validator.mjs +45 -13
  51. package/dist/hooks/stop-hook.mjs +54 -16
  52. package/dist/hooks/supervision-banner.mjs +9 -0
  53. package/dist/hooks/sync-todo-to-md.mjs +147 -113
  54. package/dist/hooks/worker-edit-repair.mjs +2 -1
  55. package/dist/hooks/worker-guard.mjs +40 -16
  56. package/dist/hooks/worker-note.mjs +12 -5
  57. package/dist/hooks/worker-path-repair.mjs +1 -1
  58. package/dist/hooks/worker-pool-host.mjs +214 -116
  59. package/dist/hooks/worker-status-line.mjs +195 -114
  60. package/dist/index.d.mts +18 -0
  61. package/dist/index.mjs +12 -12
  62. package/dist/{indexer-backend-BM2CUSu8.mjs → indexer-backend-_a6UNhXJ.mjs} +149 -96
  63. package/dist/{ipc-client-BMqWw_gv.mjs → ipc-client-CaiGJnSM.mjs} +1 -1
  64. package/dist/{ipc-client-YYDD6zzU.mjs → ipc-client-ZRmDKd5Z.mjs} +1 -1
  65. package/dist/kill-tree-BG7dRVtp.mjs +10 -0
  66. package/dist/{kill-tree-BjYz5BxK.mjs → kill-tree-EWYaEk5v.mjs} +8 -8
  67. package/dist/{launch-CLp0OJxV.mjs → launch-CXVlZjHt.mjs} +8 -8
  68. package/dist/{launch-DgqQdAjI.mjs → launch-Jh5NVeNe.mjs} +3 -3
  69. package/dist/local-candidate-DLdwQt0s.mjs +112 -0
  70. package/dist/local-instances-DOxSgT_L.mjs +210 -0
  71. package/dist/local-instances-ZeRkkuS5.mjs +6 -0
  72. package/dist/{local-tiers-DPZYqv9m.mjs → local-tiers-BE4jGaMa.mjs} +2 -2
  73. package/dist/{local-tiers-DnBIAkbK.mjs → local-tiers-DNMI5W86.mjs} +3 -3
  74. package/dist/{main-config-ops-C0SflOWk.mjs → main-config-ops-BEMpuhDz.mjs} +3 -3
  75. package/dist/{main-resolver-DVPpSWVy.mjs → main-resolver-3Ns1HPmS.mjs} +18 -17
  76. package/dist/{migrate-BUJHadA8.mjs → migrate-DrA_OwlZ.mjs} +45 -14
  77. package/dist/min-max-DrSRUaWQ.mjs +16 -0
  78. package/dist/{model-inventory-Dasber3S.mjs → model-inventory-BFVSNFT3.mjs} +13 -12
  79. package/dist/{models-add-Bt7aUHDs.mjs → models-add-BtB3Se6f.mjs} +39 -38
  80. package/dist/operator-BTqvTIc8.mjs +7 -0
  81. package/dist/{operator-DZxcP-g8.mjs → operator-CyuB3aVw.mjs} +3 -3
  82. package/dist/{pai-marker-kIYuNt3c.mjs → pai-marker-DurzIbw8.mjs} +7 -6
  83. package/dist/{pane-audit-OGYrOAik.mjs → pane-audit-BQytYa60.mjs} +7 -7
  84. package/dist/{paths-DoRuFc60.mjs → paths-CFHTloSe.mjs} +3 -3
  85. package/dist/{paths-DoIyRnhx.mjs → paths-CHifubDh.mjs} +3 -3
  86. package/dist/{planner-DLGOYlVb.mjs → planner-BM27GBfC.mjs} +31 -30
  87. package/dist/{pool-CZ5MZaXg.mjs → pool-BRvoOkv6.mjs} +3 -3
  88. package/dist/{pool-cli-BxNSPzzY.mjs → pool-cli-B_YR8_Gl.mjs} +5 -5
  89. package/dist/{pool-cli-CbJfl37y.mjs → pool-cli-DkZTAlSW.mjs} +6 -6
  90. package/dist/postgres-BdBNkL_l.mjs +7 -0
  91. package/dist/{postgres-CDnd_k5f.mjs → postgres-C6ti4haA.mjs} +55 -34
  92. package/dist/{project-setup-DM4npnL3.mjs → project-setup-CfpApz5o.mjs} +131 -74
  93. package/dist/providers-BeDiVEb-.mjs +16 -0
  94. package/dist/{providers-UsKtLcUR.mjs → providers-CblTFrhz.mjs} +6 -6
  95. package/dist/{query-feedback-I-txSnld.mjs → query-feedback-BRfPtqki.mjs} +2 -2
  96. package/dist/registrable-C7b6givx.mjs +9 -0
  97. package/dist/{registrable-LrRIVYQc.mjs → registrable-Uzgmfyhz.mjs} +4 -4
  98. package/dist/render-Cc2j5QG9.mjs +13 -0
  99. package/dist/{render-BDbb4CF-.mjs → render-CwIrgxLi.mjs} +8 -8
  100. package/dist/{reranker-B4r4vykM.mjs → reranker-8g6xMwP7.mjs} +1 -1
  101. package/dist/{reranker-DxxMCtA0.mjs → reranker-CqCbpGnX.mjs} +1 -1
  102. package/dist/{root-BMeJuHOb.mjs → root-BWy0c2Lq.mjs} +11 -11
  103. package/dist/root-wC_6Fx0B.mjs +36 -0
  104. package/dist/route-table-B7zpoypi.mjs +15 -0
  105. package/dist/{router-L8Nu-OHF.mjs → router-CQSc3lk3.mjs} +17 -7
  106. package/dist/{router-D6Ec6Fid.mjs → router-DwHJRgG9.mjs} +1 -1
  107. package/dist/{routing-CUyiglfu.mjs → routing-BAAST9vT.mjs} +27 -308
  108. package/dist/{routing-ZuGlc0ge.mjs → routing-CENt4HH1.mjs} +13 -12
  109. package/dist/{run-ulAi5dFD.mjs → run-6Q9kCPem.mjs} +35 -33
  110. package/dist/{scan-B7I0gPe-.mjs → scan-ZQWm-_se.mjs} +6 -6
  111. package/dist/{local-candidate-jOjTNlOL.mjs → scheduler-CtUyWJ3O.mjs} +7 -109
  112. package/dist/scheduler-dmHXoRvm.mjs +3 -0
  113. package/dist/{scope-D5VSQxe4.mjs → scope-D-h6F6DN.mjs} +4 -4
  114. package/dist/{search-CPoE0830.mjs → search-RSyeQqj1.mjs} +18 -18
  115. package/dist/session-Bok2PqRS.mjs +35 -0
  116. package/dist/{session-CNXF6DLP.mjs → session-DVUExUnX.mjs} +55 -31
  117. package/dist/session-scan-BJI_ZO8M.mjs +9 -0
  118. package/dist/{session-scan-BDLEc4w1.mjs → session-scan-W-gbwJHM.mjs} +6 -6
  119. package/dist/{sources-CjhUKKtO.mjs → sources-ESUkZaWv.mjs} +1 -1
  120. package/dist/{status-DYydKQUI.mjs → status-Dm4dYciN.mjs} +4 -4
  121. package/dist/{status-CvVi9cDf.mjs → status-ggJ7lgVg.mjs} +17 -9
  122. package/dist/{stop-words-SdSL1WKH.mjs → stop-words-DSEYQdNe.mjs} +1 -1
  123. package/dist/{test-isolation-CoDeOVXb.mjs → test-isolation-lqSmYxr0.mjs} +1 -1
  124. package/dist/{timeouts-OwEONmc8.mjs → timeouts-1MLooEBB.mjs} +1 -1
  125. package/dist/{tool-errors-AeRQuG3Y.mjs → tool-errors-7E13StWd.mjs} +4 -3
  126. package/dist/{tool-errors-R5E0fCgf.mjs → tool-errors-CJWODvlo.mjs} +6 -6
  127. package/dist/{viewer-DtWj5Vti.mjs → viewer-DcpJwGKE.mjs} +15 -15
  128. package/dist/viewer-MWBVJP3u.mjs +22 -0
  129. package/dist/{wait-BMUR-U-U.mjs → wait-ByV0OyMZ.mjs} +3 -3
  130. package/dist/{worker-config-BLqa1yiD.mjs → worker-config-BDYNxbYz.mjs} +294 -92
  131. package/dist/worker-config-gmAq_-rI.mjs +41 -0
  132. package/dist/{workers-config-DEI9lrV4.mjs → workers-config-f8KrkY4L.mjs} +2 -2
  133. package/dist/{worktree-zmRf556h.mjs → worktree-CrnOqTBW.mjs} +37 -7
  134. package/dist/{zettelkasten-nigq7fqs.mjs → zettelkasten-B_rRRRvD.mjs} +5 -5
  135. package/dist/{zettelkasten-Cr_Xj0mG.mjs → zettelkasten-BzMm8REH.mjs} +29 -19
  136. package/docs/README.md +2 -0
  137. package/docs/cockpit.md +10 -4
  138. package/docs/commands/README.md +4 -4
  139. package/docs/commands/backup.md +2 -0
  140. package/docs/commands/install.md +29 -4
  141. package/docs/commands/providers.md +1 -1
  142. package/docs/commands/restore.md +4 -0
  143. package/docs/commands/setup.md +29 -4
  144. package/docs/commands/worker.md +1 -1
  145. package/docs/config.md +2 -0
  146. package/docs/features.md +299 -0
  147. package/docs/images/architecture.drawio +51 -0
  148. package/docs/images/architecture.svg +3 -0
  149. package/docs/images/cockpit-01-system-tokens.jpg +0 -0
  150. package/docs/images/cockpit-02-totals-cache.jpg +0 -0
  151. package/docs/images/cockpit-03-local-servers-models-pool.jpg +0 -0
  152. package/docs/images/cockpit-04-workers-memory.jpg +0 -0
  153. package/docs/images/cockpit-05-performance.jpg +0 -0
  154. package/docs/images/cockpit-06-runs-speed-routing.jpg +0 -0
  155. package/docs/images/cockpit-07-settings-registry.jpg +0 -0
  156. package/docs/install/index.md +29 -0
  157. package/docs/three-tier-coding.md +1 -1
  158. package/gemini-extension.json +1 -1
  159. package/package.json +1 -5
  160. package/pai-plugin.json +1 -1
  161. package/plugins/context-preservation/plugin.json +1 -1
  162. package/plugins/core/plugin.json +1 -1
  163. package/plugins/core/skills/setup/SKILL.md +41 -9
  164. package/plugins/creative/plugin.json +1 -1
  165. package/plugins/observability/plugin.json +1 -1
  166. package/plugins/productivity/plugin.json +1 -1
  167. package/plugins/semantic-search/plugin.json +1 -1
  168. package/plugins/ui/plugin.json +1 -1
  169. package/plugins/zettelkasten/plugin.json +1 -1
  170. package/src/hooks/session-autosave.sh +8 -1
  171. package/src/hooks/session-stop.sh +8 -1
  172. package/src/hooks/ts/capture-all-events.ts +7 -12
  173. package/src/hooks/ts/lib/context-fill.ts +2 -1
  174. package/src/hooks/ts/lib/path-repair.ts +1 -1
  175. package/src/hooks/ts/lib/project-utils/notify.ts +1 -0
  176. package/src/hooks/ts/lib/project-utils/session-notes.ts +23 -6
  177. package/src/hooks/ts/lib/raw-capture.ts +36 -0
  178. package/src/hooks/ts/lib/session-summary.ts +129 -0
  179. package/src/hooks/ts/lib/todo-sync.ts +120 -0
  180. package/src/hooks/ts/lib/worker-git-guard.ts +1 -1
  181. package/src/hooks/ts/post-tool-use/capture-tool-output.ts +6 -10
  182. package/src/hooks/ts/post-tool-use/sync-todo-to-md.ts +5 -105
  183. package/src/hooks/ts/pre-compact/context-compression-hook.ts +1 -1
  184. package/src/hooks/ts/pre-tool-use/security-validator.ts +35 -14
  185. package/src/hooks/ts/session-end/capture-session-summary.ts +20 -128
  186. package/src/hooks/ts/session-start/load-core-context.ts +3 -3
  187. package/src/hooks/ts/session-start/load-project-context.ts +18 -22
  188. package/src/hooks/ts/stop/stop-hook.ts +13 -5
  189. package/src/hooks/ztk-auto.sh +7 -2
  190. package/dist/aibroker-client-JjE74jo0.mjs +0 -3
  191. package/dist/auto-route-BRk8NEFv.mjs +0 -11
  192. package/dist/budget-DuhQ2zzG.mjs +0 -14
  193. package/dist/cockpit-actions-DcQ-ucU8.mjs +0 -19
  194. package/dist/cockpit-memory-KV45PPO2.mjs +0 -19
  195. package/dist/daemon-C7yt_ptC.mjs +0 -44
  196. package/dist/detect-DRUkmHnb.mjs +0 -10
  197. package/dist/factory-DAGG9_n8.mjs +0 -9
  198. package/dist/helpers-DPJEHPq6.mjs +0 -10
  199. package/dist/kill-tree-LV0Q7Mte.mjs +0 -10
  200. package/dist/operator-CfL0HiBK.mjs +0 -7
  201. package/dist/postgres-DgqWyqhN.mjs +0 -7
  202. package/dist/providers-CTu2s1z2.mjs +0 -15
  203. package/dist/registrable-D9aNZOTh.mjs +0 -9
  204. package/dist/render-BSfVlYHj.mjs +0 -13
  205. package/dist/root-xI9DqVIe.mjs +0 -35
  206. package/dist/route-table-HjvnLVEU.mjs +0 -14
  207. package/dist/session-BJHzmUg2.mjs +0 -34
  208. package/dist/session-scan-YORKE1NO.mjs +0 -9
  209. package/dist/viewer-B8709jDN.mjs +0 -22
  210. package/dist/worker-config-D8tRuvo7.mjs +0 -40
  211. package/docs/images/cockpit-limits-routing.jpg +0 -0
  212. package/docs/images/cockpit-models.jpg +0 -0
  213. package/docs/images/cockpit-usage.jpg +0 -0
  214. package/docs/images/cockpit-workers-system.jpg +0 -0
  215. package/scripts/build-docs.mjs +0 -41
  216. package/scripts/build-hooks.mjs +0 -311
  217. package/scripts/build-skill-stubs.mjs +0 -216
  218. package/scripts/copy-defaults.mjs +0 -46
@@ -0,0 +1,112 @@
1
+ import { L as isLoopbackHostname, tt as workersYamlPath } from "./config-XpZWOYOG.mjs";
2
+ import { _ as readLocalConfig } from "./local-tiers-BE4jGaMa.mjs";
3
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
+
6
+ //#region src/workers/local-status.ts
7
+ /**
8
+ * local-status.ts — the one authoritative answer to "which local model is
9
+ * running?" (incident 2026-10-19: a session curled ports 8010/8011/8020, found
10
+ * nothing, and went looking for how to start a model server while the running
11
+ * one was never considered). The PAI daemon computes the answer every 30 s and
12
+ * caches it in <logDir>/local-status.json; everything else only reads it:
13
+ * `pai worker local`, the `local_status` MCP tool, resolveLocalProvider, the
14
+ * prompt hint and the Bash guard. Readers fall back to a direct probe only
15
+ * when the cache is missing or stale (daemon unreachable).
16
+ */
17
+ const LOCAL_STATUS_REFRESH_MS = 3e4;
18
+ /** A cache older than this means the daemon is not refreshing it. */
19
+ const LOCAL_STATUS_MAX_AGE_MS = 18e4;
20
+ /** The model callers that need exactly one use: the first of `running` (the one `--local` favours). */
21
+ function primaryLocal(st) {
22
+ return st?.running?.[0] ?? null;
23
+ }
24
+ const localStatusPath = (logDir) => join(logDir, "local-status.json");
25
+ const NO_SERVER_HINT = "do not start model servers";
26
+ function localStatusLine(st) {
27
+ if (st.running.length) return `local: ${st.running.map((r) => `${r.provider} (${r.model})`).join(", ")} running — use \`pai worker run --local\``;
28
+ return `local: none running — local work is not available; ${NO_SERVER_HINT}`;
29
+ }
30
+ function writeLocalStatus(logDir, st) {
31
+ const path = localStatusPath(logDir);
32
+ mkdirSync(dirname(path), { recursive: true });
33
+ const tmp = `${path}.${process.pid}.tmp`;
34
+ writeFileSync(tmp, JSON.stringify(st) + "\n", "utf8");
35
+ renameSync(tmp, path);
36
+ }
37
+ /** Like readLocalStatus, but says why there is no answer: missing, unparsable, stale (age) or bad shape. */
38
+ function readLocalStatusWhy(logDir, now = Date.now(), maxAgeMs = LOCAL_STATUS_MAX_AGE_MS) {
39
+ const path = localStatusPath(logDir);
40
+ if (!existsSync(path)) return {
41
+ status: null,
42
+ reason: "status file missing"
43
+ };
44
+ let st;
45
+ try {
46
+ st = JSON.parse(readFileSync(path, "utf8"));
47
+ } catch {
48
+ return {
49
+ status: null,
50
+ reason: "status file unparsable"
51
+ };
52
+ }
53
+ if (!st || typeof st !== "object") return {
54
+ status: null,
55
+ reason: "status file has a bad shape"
56
+ };
57
+ const raw = st.running;
58
+ st.running = Array.isArray(raw) ? raw : raw && typeof raw === "object" ? [raw] : [];
59
+ const at = Date.parse(st.at);
60
+ if (Number.isNaN(at) || !Array.isArray(st.down) || !Array.isArray(st.disabled)) return {
61
+ status: null,
62
+ reason: "status file has a bad shape"
63
+ };
64
+ const age = now - at;
65
+ if (age > maxAgeMs) return {
66
+ status: null,
67
+ reason: `status ${Math.round(age / 1e3)} s old (max ${Math.round(maxAgeMs / 1e3)} s)`
68
+ };
69
+ return { status: st };
70
+ }
71
+ /** The daemon's cached answer; null when absent, damaged or older than maxAgeMs. */
72
+ function readLocalStatus(logDir, now = Date.now(), maxAgeMs = LOCAL_STATUS_MAX_AGE_MS) {
73
+ return readLocalStatusWhy(logDir, now, maxAgeMs).status;
74
+ }
75
+ /** Text + JSON of the answer for the CLI and the MCP tool. */
76
+ function localStatusReport(st) {
77
+ const extra = (st.down.length ? ` down: ${st.down.join(", ")}.` : "") + (st.disabled.length ? ` disabled: ${st.disabled.join(", ")}.` : "");
78
+ return {
79
+ text: localStatusLine(st) + (extra ? `\n${extra.trim()}` : ""),
80
+ json: st
81
+ };
82
+ }
83
+
84
+ //#endregion
85
+ //#region src/workers/local-candidate.ts
86
+ /**
87
+ * Providers a `local:` tier launches. `pai worker local <tier>` and the cockpit
88
+ * start those without touching `enabled:`, so a running tier server is a
89
+ * candidate for --local even when its provider entry is switched off.
90
+ */
91
+ function tierProviderNames(yamlPath = workersYamlPath()) {
92
+ try {
93
+ return Object.values(readLocalConfig(yamlPath).tiers).map((t) => t.provider);
94
+ } catch {
95
+ return [];
96
+ }
97
+ }
98
+ function isLoopbackBaseUrl(url) {
99
+ try {
100
+ return isLoopbackHostname(new URL(url).hostname);
101
+ } catch {
102
+ return false;
103
+ }
104
+ }
105
+ /** A loopback provider --local may run on: enabled, or launched by a tier. */
106
+ function isLocalCandidate(p, name, tierProviders) {
107
+ return (p.enabled || tierProviders.includes(name)) && isLoopbackBaseUrl(p.baseUrl);
108
+ }
109
+
110
+ //#endregion
111
+ export { localStatusReport as a, writeLocalStatus as c, localStatusLine as i, tierProviderNames as n, primaryLocal as o, LOCAL_STATUS_REFRESH_MS as r, readLocalStatus as s, isLocalCandidate as t };
112
+ //# sourceMappingURL=local-candidate-DLdwQt0s.mjs.map
@@ -0,0 +1,210 @@
1
+ import { n as minOf } from "./min-max-DrSRUaWQ.mjs";
2
+ import { h as parseServers, v as resolveModelPath } from "./local-tiers-BE4jGaMa.mjs";
3
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
+
6
+ //#region src/workers/local-instances.ts
7
+ /**
8
+ * local-instances.ts — the running instances of local models.
9
+ *
10
+ * An instance is one server process of a catalogue model (a `local_tiers:`
11
+ * entry) on its own port. The source of truth is the running processes
12
+ * (`parseServers`); `<logDir>/local-instances.json` adds what ps cannot know
13
+ * (start time, log, failure). Processes win: `reconcileInstances` drops a row
14
+ * whose pid is gone and adopts a catalogue server that has no row.
15
+ */
16
+ const localInstancesPath = (logDir) => join(logDir, "local-instances.json");
17
+ /** Is the process alive (signal 0; EPERM means it exists under another user). */
18
+ function pidAlive(pid) {
19
+ try {
20
+ process.kill(pid, 0);
21
+ return true;
22
+ } catch (e) {
23
+ return e.code === "EPERM";
24
+ }
25
+ }
26
+ function readInstances(logDir) {
27
+ const path = localInstancesPath(logDir);
28
+ if (!existsSync(path)) return [];
29
+ try {
30
+ const j = JSON.parse(readFileSync(path, "utf8"));
31
+ return Array.isArray(j) ? j.filter((r) => r && typeof r.id === "string" && typeof r.model === "string") : [];
32
+ } catch {
33
+ return [];
34
+ }
35
+ }
36
+ /** The recorded rows minus managed ones whose process is gone (killed outside PAI); failed rows stay until dismissed. Readers that report or route use this; writers read the raw file. */
37
+ function readLiveInstances(logDir) {
38
+ return readInstances(logDir).filter((r) => !(r.origin === "managed" && r.state !== "failed" && r.pid && !pidAlive(r.pid)));
39
+ }
40
+ /** Atomic write (tmp + rename). */
41
+ function writeInstances(logDir, rows) {
42
+ const path = localInstancesPath(logDir);
43
+ mkdirSync(dirname(path), { recursive: true });
44
+ const tmp = `${path}.${process.pid}.tmp`;
45
+ writeFileSync(tmp, JSON.stringify(rows) + "\n", "utf8");
46
+ renameSync(tmp, path);
47
+ }
48
+ /** Router / scheduler engine key: n=1 keeps the bare provider name, later copies are `<provider>#<n>`. */
49
+ function engineKey(provider, n) {
50
+ return n <= 1 ? provider : `${provider}#${n}`;
51
+ }
52
+ /** The n of an instance id `<model>#<n>` (1 when it carries none). */
53
+ function instanceNumber(id) {
54
+ const m = /#(\d+)$/.exec(id);
55
+ return m ? Number(m[1]) : 1;
56
+ }
57
+ function instanceEngineKey(i) {
58
+ return engineKey(i.provider, instanceNumber(i.id));
59
+ }
60
+ /** vllm-mlx servers on a port no tier names (a second copy): the tier is the one whose model path the command serves. */
61
+ function vllmByModelPath(psOut, cfg, selfPid, byPath) {
62
+ const out = [];
63
+ for (const line of psOut.split("\n")) {
64
+ const m = /^\s*(\d+)\s+(\d+)\s+(.*)$/.exec(line);
65
+ if (!m || Number(m[1]) === selfPid) continue;
66
+ const cmd = m[3];
67
+ const sv = /\bserve\s+(\S+)/.exec(cmd);
68
+ const pm = /--port\s+(\d+)/.exec(cmd);
69
+ if (!sv || !pm || !cmd.includes(cfg.launcher.processMatch)) continue;
70
+ const tier = byPath.get(sv[1]);
71
+ if (!tier) continue;
72
+ out.push({
73
+ pid: Number(m[1]),
74
+ rssKb: Number(m[2]),
75
+ port: Number(pm[1]),
76
+ tier,
77
+ provider: cfg.tiers[tier].provider
78
+ });
79
+ }
80
+ return out;
81
+ }
82
+ /** Servers of catalogue models, one per (model, port): the engine child of a Strata server is folded into its server. */
83
+ function instancesFromProcesses(psOut, cfg, listeners = {}, selfPid = process.pid) {
84
+ const seen = /* @__PURE__ */ new Set();
85
+ const out = [];
86
+ const byPath = /* @__PURE__ */ new Map();
87
+ for (const t of Object.values(cfg.tiers)) if (t.engine === "vllm-mlx") byPath.set(resolveModelPath(t.model), t.tier);
88
+ for (const s of [...parseServers(psOut, cfg, selfPid, listeners), ...vllmByModelPath(psOut, cfg, selfPid, byPath)]) {
89
+ if (!s.tier || s.port === null) continue;
90
+ const key = `${s.tier}:${s.port}`;
91
+ if (seen.has(key)) continue;
92
+ seen.add(key);
93
+ out.push(s);
94
+ }
95
+ return out;
96
+ }
97
+ /**
98
+ * Join state rows with the live servers. A row follows its pid, else its
99
+ * port; a live server without a row is adopted as `ready` under the smallest
100
+ * free `<model>#<n>`. Rows with no live server are dropped, except `failed`
101
+ * ones (kept until the next start dismisses them).
102
+ */
103
+ function reconcileInstances(rows, servers, cfg, now = Date.now()) {
104
+ const out = [];
105
+ const used = /* @__PURE__ */ new Set();
106
+ const claimed = /* @__PURE__ */ new Set();
107
+ for (const r of rows) {
108
+ if (r.origin === "registered") continue;
109
+ if (r.state === "failed") {
110
+ out.push(r);
111
+ used.add(r.id);
112
+ continue;
113
+ }
114
+ const s = servers.find((x) => !claimed.has(x) && x.tier === r.model && (x.pid === r.pid || x.port === r.port));
115
+ if (!s) continue;
116
+ claimed.add(s);
117
+ out.push({
118
+ ...r,
119
+ pid: s.pid,
120
+ port: s.port ?? r.port
121
+ });
122
+ used.add(r.id);
123
+ }
124
+ for (const s of servers) {
125
+ if (claimed.has(s) || !s.tier || s.port === null) continue;
126
+ const tier = cfg.tiers[s.tier];
127
+ if (!tier) continue;
128
+ let n = 1;
129
+ while (used.has(`${s.tier}#${n}`)) n++;
130
+ const id = `${s.tier}#${n}`;
131
+ used.add(id);
132
+ out.push({
133
+ id,
134
+ model: s.tier,
135
+ provider: tier.provider,
136
+ url: `http://127.0.0.1:${s.port}`,
137
+ origin: "managed",
138
+ port: s.port,
139
+ pid: s.pid,
140
+ state: "ready",
141
+ startedAt: now,
142
+ log: ""
143
+ });
144
+ }
145
+ return out.sort((a, b) => a.model.localeCompare(b.model) || instanceNumber(a.id) - instanceNumber(b.id));
146
+ }
147
+ /**
148
+ * Endpoints declared in workers.yaml `providers:` with a url that no catalogue
149
+ * model launches: no pid, health is a probe (state `ready` until one says
150
+ * otherwise). Loopback or another machine alike.
151
+ */
152
+ function registeredInstances(providers, cfg) {
153
+ const launched = new Set(Object.values(cfg.tiers).map((t) => t.provider));
154
+ const out = [];
155
+ for (const [name, p] of Object.entries(providers)) {
156
+ if (!p.url || launched.has(name)) continue;
157
+ const port = /:(\d+)(?:\/|$)/.exec(p.url)?.[1];
158
+ out.push({
159
+ id: name,
160
+ model: name,
161
+ provider: name,
162
+ url: p.url.replace(/\/+$/, ""),
163
+ origin: "registered",
164
+ port: port ? Number(port) : 0,
165
+ state: "ready",
166
+ startedAt: 0,
167
+ log: "",
168
+ ...p.characteristics ? { characteristics: p.characteristics } : {}
169
+ });
170
+ }
171
+ return out;
172
+ }
173
+ const rrCounters = /* @__PURE__ */ new Map();
174
+ /**
175
+ * The instance (of `running`, already one provider's; `model` keys the round-robin) to send the next request to: the ready one with the
176
+ * fewest requests in flight (`busy` by engine key); ties go round-robin per
177
+ * model. Null when none is ready.
178
+ */
179
+ function pickInstance(model, running, busy) {
180
+ const ready = running.filter((i) => i.state === "ready");
181
+ if (!ready.length) return null;
182
+ const load = ready.map((i) => busy(instanceEngineKey(i)));
183
+ const min = minOf(load);
184
+ const tied = ready.filter((_, k) => load[k] === min);
185
+ const n = rrCounters.get(model) ?? 0;
186
+ rrCounters.set(model, n + 1);
187
+ return tied[n % tied.length];
188
+ }
189
+ /**
190
+ * The endpoint registry: managed instances plus the enabled providers that
191
+ * declare `characteristics` (a url alone is a cloud or local provider, not a
192
+ * registered endpoint). A managed instance wins over a registered one of the
193
+ * same id.
194
+ */
195
+ function endpointRegistry(managed, providers, cfg) {
196
+ const declared = {};
197
+ for (const [name, p] of Object.entries(providers)) {
198
+ if (p.enabled === false || !p.characteristics) continue;
199
+ declared[name] = {
200
+ url: p.baseUrl,
201
+ characteristics: p.characteristics
202
+ };
203
+ }
204
+ const ids = new Set(managed.map((i) => i.id));
205
+ return [...managed, ...registeredInstances(declared, cfg).filter((i) => !ids.has(i.id))];
206
+ }
207
+
208
+ //#endregion
209
+ export { instancesFromProcesses as a, pidAlive as c, reconcileInstances as d, registeredInstances as f, instanceNumber as i, readInstances as l, engineKey as n, localInstancesPath as o, writeInstances as p, instanceEngineKey as r, pickInstance as s, endpointRegistry as t, readLiveInstances as u };
210
+ //# sourceMappingURL=local-instances-DOxSgT_L.mjs.map
@@ -0,0 +1,6 @@
1
+ import "./config-XpZWOYOG.mjs";
2
+ import "./config-Bu1_vbY8.mjs";
3
+ import "./local-tiers-BE4jGaMa.mjs";
4
+ import { a as instancesFromProcesses, c as pidAlive, d as reconcileInstances, f as registeredInstances, i as instanceNumber, l as readInstances, n as engineKey, o as localInstancesPath, p as writeInstances, r as instanceEngineKey, s as pickInstance, t as endpointRegistry, u as readLiveInstances } from "./local-instances-DOxSgT_L.mjs";
5
+
6
+ export { endpointRegistry, engineKey, instanceEngineKey, instanceNumber, instancesFromProcesses, localInstancesPath, pickInstance, pidAlive, readInstances, readLiveInstances, reconcileInstances, registeredInstances, writeInstances };
@@ -1,5 +1,5 @@
1
1
  import { g as paiHomePath } from "./runtime-paths-WsO9sJFc.mjs";
2
- import { o as expandHome } from "./config-BSXKyeJ1.mjs";
2
+ import { o as expandHome } from "./config-Bu1_vbY8.mjs";
3
3
  import { existsSync, readFileSync, readdirSync } from "node:fs";
4
4
  import { dirname, join } from "node:path";
5
5
  import { homedir } from "node:os";
@@ -467,4 +467,4 @@ const shellQuote = shq;
467
467
 
468
468
  //#endregion
469
469
  export { stopLines as C, stopLine as S, tierButtons as T, readLocalConfig as _, LocalTierError as a, splitCommand as b, fetchServedModels as c, installedModelDirs as d, listensOnPort as f, planStart as g, parseServers as h, DEFAULT_RESERVE_GB as i, fmtRss as l, parseLocalConfig as m, DEFAULT_HEALTH as n, defaultLauncher as o, logPathFor as p, DEFAULT_MAX_INSTANCES as r, defaultStrataPython as s, DEFAULT_COMMON_FLAGS as t, healthUrl as u, resolveModelPath as v, strataInfo as w, stopCommandFor as x, shellQuote as y };
470
- //# sourceMappingURL=local-tiers-DPZYqv9m.mjs.map
470
+ //# sourceMappingURL=local-tiers-BE4jGaMa.mjs.map
@@ -1,5 +1,5 @@
1
- import "./config-D5chi2LO.mjs";
2
- import "./config-BSXKyeJ1.mjs";
3
- import { C as stopLines, S as stopLine, T as tierButtons, _ as readLocalConfig, a as LocalTierError, b as splitCommand, c as fetchServedModels, d as installedModelDirs, f as listensOnPort, g as planStart, h as parseServers, i as DEFAULT_RESERVE_GB, l as fmtRss, m as parseLocalConfig, n as DEFAULT_HEALTH, o as defaultLauncher, p as logPathFor, r as DEFAULT_MAX_INSTANCES, s as defaultStrataPython, t as DEFAULT_COMMON_FLAGS, u as healthUrl, v as resolveModelPath, w as strataInfo, x as stopCommandFor, y as shellQuote } from "./local-tiers-DPZYqv9m.mjs";
1
+ import "./config-XpZWOYOG.mjs";
2
+ import "./config-Bu1_vbY8.mjs";
3
+ import { C as stopLines, S as stopLine, T as tierButtons, _ as readLocalConfig, a as LocalTierError, b as splitCommand, c as fetchServedModels, d as installedModelDirs, f as listensOnPort, g as planStart, h as parseServers, i as DEFAULT_RESERVE_GB, l as fmtRss, m as parseLocalConfig, n as DEFAULT_HEALTH, o as defaultLauncher, p as logPathFor, r as DEFAULT_MAX_INSTANCES, s as defaultStrataPython, t as DEFAULT_COMMON_FLAGS, u as healthUrl, v as resolveModelPath, w as strataInfo, x as stopCommandFor, y as shellQuote } from "./local-tiers-BE4jGaMa.mjs";
4
4
 
5
5
  export { readLocalConfig };
@@ -1,5 +1,5 @@
1
- import { _ as maskKey, j as readWorkersSection, tt as workersYamlPath } from "./config-D5chi2LO.mjs";
2
- import { C as migrateMainConfigToYaml, E as writeYamlFileAtomic, c as loadConfig, d as paiConfigYamlFilePath, f as readMainConfigRaw, i as defaults, p as writeMainConfigRaw, u as paiConfigFilePath, x as userWorkersYamlRaw } from "./config-BSXKyeJ1.mjs";
1
+ import { _ as maskKey, j as readWorkersSection, tt as workersYamlPath } from "./config-XpZWOYOG.mjs";
2
+ import { C as migrateMainConfigToYaml, E as writeYamlFileAtomic, c as loadConfig, d as paiConfigYamlFilePath, f as readMainConfigRaw, i as defaults, p as writeMainConfigRaw, u as paiConfigFilePath, x as userWorkersYamlRaw } from "./config-Bu1_vbY8.mjs";
3
3
  import { existsSync } from "node:fs";
4
4
  import { Document } from "yaml";
5
5
 
@@ -239,4 +239,4 @@ function unsetConfigValueOp(dottedPath) {
239
239
 
240
240
  //#endregion
241
241
  export { listConfigOp as a, getConfigValueOp as i, formatConfigGetOutput as n, setConfigValueOp as o, formatConfigSource as r, unsetConfigValueOp as s, MainConfigOpsError as t };
242
- //# sourceMappingURL=main-config-ops-C0SflOWk.mjs.map
242
+ //# sourceMappingURL=main-config-ops-BEMpuhDz.mjs.map
@@ -1,19 +1,20 @@
1
1
  import { _ as warn, c as ok, i as err, l as renderTable, n as dim, o as header } from "./utils-J2b9y8PC.mjs";
2
- import "./config-D5chi2LO.mjs";
3
- import "./config-BSXKyeJ1.mjs";
4
- import "./paths-DoIyRnhx.mjs";
5
- import "./status-CvVi9cDf.mjs";
6
- import { d as terminalHasName } from "./scope-D5VSQxe4.mjs";
7
- import "./routing-CUyiglfu.mjs";
8
- import "./tool-errors-AeRQuG3Y.mjs";
9
- import "./wait-BMUR-U-U.mjs";
10
- import "./local-tiers-DPZYqv9m.mjs";
11
- import "./caller-identity-CVTuiLSs.mjs";
12
- import "./local-candidate-jOjTNlOL.mjs";
13
- import "./capacity-DaXrVj3J.mjs";
14
- import { c as resumeOfferBlock, l as resumeRouteFor, n as launchInDir } from "./launch-CLp0OJxV.mjs";
15
- import { i as switchToSession, n as fetchLiveSessions } from "./aibroker-client-CXEYBzbf.mjs";
16
- import { s as scanSessions, t as fmtAge } from "./session-scan-BDLEc4w1.mjs";
2
+ import "./config-XpZWOYOG.mjs";
3
+ import "./config-Bu1_vbY8.mjs";
4
+ import "./paths-CHifubDh.mjs";
5
+ import "./status-ggJ7lgVg.mjs";
6
+ import { d as terminalHasName } from "./scope-D-h6F6DN.mjs";
7
+ import "./routing-BAAST9vT.mjs";
8
+ import "./tool-errors-7E13StWd.mjs";
9
+ import "./wait-ByV0OyMZ.mjs";
10
+ import "./local-tiers-BE4jGaMa.mjs";
11
+ import "./caller-identity-yLFb7CKq.mjs";
12
+ import "./capacity-DEveQdFV.mjs";
13
+ import "./local-instances-DOxSgT_L.mjs";
14
+ import "./local-candidate-DLdwQt0s.mjs";
15
+ import { c as resumeOfferBlock, l as resumeRouteFor, n as launchInDir } from "./launch-CXVlZjHt.mjs";
16
+ import { i as switchToSession, n as fetchLiveSessions } from "./aibroker-client-CQPGqLxL.mjs";
17
+ import { s as scanSessions, t as fmtAge } from "./session-scan-W-gbwJHM.mjs";
17
18
  import { createReadStream, existsSync, realpathSync } from "node:fs";
18
19
  import { basename, join } from "node:path";
19
20
  import chalk from "chalk";
@@ -599,7 +600,7 @@ async function openMatch(entry, allSessions, dryRun, resume, auto) {
599
600
  }
600
601
  async function getRegisteredProjects(all = false) {
601
602
  try {
602
- const { getRegistryBackend } = await import("./factory-DAGG9_n8.mjs");
603
+ const { getRegistryBackend } = await import("./factory-Bsib-qDG.mjs");
603
604
  return await (await getRegistryBackend()).listProjectsWithSessionStats(all ? {} : { status: "active" });
604
605
  } catch {
605
606
  return [];
@@ -783,4 +784,4 @@ async function cmdMain(query, pickN, opts) {
783
784
 
784
785
  //#endregion
785
786
  export { cmdMain };
786
- //# sourceMappingURL=main-resolver-DVPpSWVy.mjs.map
787
+ //# sourceMappingURL=main-resolver-3Ns1HPmS.mjs.map
@@ -1,6 +1,7 @@
1
1
  import { h as smartDecodeDir } from "./utils-J2b9y8PC.mjs";
2
2
  import { l as claudeHomeDir } from "./runtime-paths-WsO9sJFc.mjs";
3
3
  import { existsSync, readFileSync, readdirSync } from "node:fs";
4
+ import { createHash } from "node:crypto";
4
5
  import { join } from "node:path";
5
6
 
6
7
  //#region src/registry/migrate.ts
@@ -21,6 +22,39 @@ import { join } from "node:path";
21
22
  * Legacy: "NNNN_YYYY-MM-DD_description.md" (underscores)
22
23
  */
23
24
  /**
25
+ * Extract project entries from a parsed session-registry.json. Supports both
26
+ * formats:
27
+ * list-based: { "projects": [ { "encoded_dir", "original_path" }, ... ] }
28
+ * object-keyed: { "<encoded_dir>": { ... } } (original Claude format)
29
+ * The `version` key and non-object values are not projects.
30
+ */
31
+ function parseRegistryEntries(parsed) {
32
+ const out = [];
33
+ if (!parsed || typeof parsed !== "object") return out;
34
+ const obj = parsed;
35
+ if (Array.isArray(obj.projects)) {
36
+ for (const item of obj.projects) {
37
+ if (!item || typeof item !== "object") continue;
38
+ const entry = item;
39
+ const key = entry.encoded_dir;
40
+ if (typeof key === "string" && key) out.push({
41
+ encodedDir: key,
42
+ entry
43
+ });
44
+ }
45
+ return out;
46
+ }
47
+ for (const [key, value] of Object.entries(obj)) {
48
+ if (key === "version") continue;
49
+ if (!value || typeof value !== "object" || Array.isArray(value)) continue;
50
+ out.push({
51
+ encodedDir: key,
52
+ entry: value
53
+ });
54
+ }
55
+ return out;
56
+ }
57
+ /**
24
58
  * Build a lookup table from session-registry.json mapping encoded_dir →
25
59
  * original_path. This is the authoritative source for decoding because the
26
60
  * encoding is ambiguous: `/`, ` ` (space), `.` (dot), and `-` (literal
@@ -40,17 +74,10 @@ function buildEncodedDirMap(jsonPath = join(claudeHomeDir(), "session-registry.j
40
74
  const map = /* @__PURE__ */ new Map();
41
75
  if (!existsSync(jsonPath)) return map;
42
76
  try {
43
- const raw = readFileSync(jsonPath, "utf8");
44
- const parsed = JSON.parse(raw);
45
- if (Array.isArray(parsed.projects)) for (const entry of parsed.projects) {
46
- const key = entry.encoded_dir;
77
+ const parsed = JSON.parse(readFileSync(jsonPath, "utf8"));
78
+ for (const { encodedDir, entry } of parseRegistryEntries(parsed)) {
47
79
  const val = entry.original_path;
48
- if (key && val) map.set(key, val);
49
- }
50
- else for (const [key, value] of Object.entries(parsed)) {
51
- if (key === "version") continue;
52
- const val = value?.original_path;
53
- if (val) map.set(key, val);
80
+ if (typeof val === "string" && val) map.set(encodedDir, val);
54
81
  }
55
82
  } catch {}
56
83
  return map;
@@ -100,6 +127,10 @@ function decodeEncodedDir(encoded, lookupMap) {
100
127
  function slugify(value) {
101
128
  return (value.includes("/") ? value.replace(/\/$/, "").split("/").pop() ?? value : value).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
102
129
  }
130
+ /** Stable slug for names slugify() reduces to nothing (e.g. non-ASCII only). */
131
+ function fallbackSlug(value) {
132
+ return "project-" + createHash("sha1").update(value).digest("hex").slice(0, 8);
133
+ }
103
134
  /** Match `0027 - 2026-01-04 - Some Description.md` */
104
135
  const MODERN_RE = /^(\d{4})\s+-\s+(\d{4}-\d{2}-\d{2})\s+-\s+(.+)\.md$/i;
105
136
  /** Match `0027_2026-01-04_some_description.md` */
@@ -159,16 +190,16 @@ async function migrateFromJson(backend, registryPath = join(claudeHomeDir(), "se
159
190
  let registry;
160
191
  try {
161
192
  const raw = readFileSync(registryPath, "utf8");
162
- registry = JSON.parse(raw);
193
+ registry = parseRegistryEntries(JSON.parse(raw));
163
194
  } catch (err) {
164
195
  result.errors.push(`Failed to parse registry JSON: ${String(err)}`);
165
196
  return result;
166
197
  }
167
198
  const now = Date.now();
168
199
  const lookupMap = buildEncodedDirMap(registryPath);
169
- for (const [encodedDir, entry] of Object.entries(registry)) {
200
+ for (const { encodedDir, entry } of registry) {
170
201
  const rootPath = decodeEncodedDir(encodedDir, lookupMap);
171
- const baseSlug = slugify(rootPath);
202
+ const baseSlug = slugify(rootPath) || fallbackSlug(rootPath);
172
203
  const { id: projectId, created } = await backend.createProjectWithSlugRetry({
173
204
  baseSlug,
174
205
  displayName: entry.displayName ?? rootPath.split("/").pop() ?? rootPath,
@@ -212,4 +243,4 @@ async function migrateFromJson(backend, registryPath = join(claudeHomeDir(), "se
212
243
 
213
244
  //#endregion
214
245
  export { slugify as a, parseSessionFilename as i, decodeEncodedDir as n, migrateFromJson as r, buildEncodedDirMap as t };
215
- //# sourceMappingURL=migrate-BUJHadA8.mjs.map
246
+ //# sourceMappingURL=migrate-DrA_OwlZ.mjs.map
@@ -0,0 +1,16 @@
1
+ //#region src/utils/min-max.ts
2
+ /** Min/max without argument spread: Math.min(...arr) throws RangeError above ~120k elements. */
3
+ function minOf(values) {
4
+ let m = Infinity;
5
+ for (const v of values) if (v < m) m = v;
6
+ return m;
7
+ }
8
+ function maxOf(values) {
9
+ let m = -Infinity;
10
+ for (const v of values) if (v > m) m = v;
11
+ return m;
12
+ }
13
+
14
+ //#endregion
15
+ export { minOf as n, maxOf as t };
16
+ //# sourceMappingURL=min-max-DrSRUaWQ.mjs.map
@@ -1,14 +1,15 @@
1
- import "./config-D5chi2LO.mjs";
2
- import "./config-BSXKyeJ1.mjs";
3
- import "./paths-DoIyRnhx.mjs";
4
- import "./status-CvVi9cDf.mjs";
5
- import "./scope-D5VSQxe4.mjs";
6
- import { $ as parseFootprint, B as MODEL_INVENTORY_MAX_AGE_MS, G as fmtMem, H as ProbeHold, J as inventoryRows, K as fmtMemMapped, Q as modelLabel, R as DOWN_AFTER_MISSES, U as computeInventory, V as MODEL_INVENTORY_REFRESH_MS, W as currentInventory, X as liveDeps, Y as inventoryText, Z as modelKind, at as readInventoryInput, ct as writeInventory, et as parseSizeMb, it as readInventory, nt as processTreeMemory, ot as readModelLabels, q as inventoryPath, rt as processTreeRssMb, st as startInventoryRefresh, tt as parseTable, z as INVENTORY_HEADERS } from "./routing-CUyiglfu.mjs";
7
- import "./tool-errors-AeRQuG3Y.mjs";
8
- import "./wait-BMUR-U-U.mjs";
9
- import "./local-tiers-DPZYqv9m.mjs";
10
- import "./caller-identity-CVTuiLSs.mjs";
11
- import "./local-candidate-jOjTNlOL.mjs";
12
- import "./capacity-DaXrVj3J.mjs";
1
+ import "./config-XpZWOYOG.mjs";
2
+ import "./config-Bu1_vbY8.mjs";
3
+ import "./paths-CHifubDh.mjs";
4
+ import "./status-ggJ7lgVg.mjs";
5
+ import "./scope-D-h6F6DN.mjs";
6
+ import { $ as parseFootprint, B as MODEL_INVENTORY_MAX_AGE_MS, G as fmtMem, H as ProbeHold, J as inventoryRows, K as fmtMemMapped, Q as modelLabel, R as DOWN_AFTER_MISSES, U as computeInventory, V as MODEL_INVENTORY_REFRESH_MS, W as currentInventory, X as liveDeps, Y as inventoryText, Z as modelKind, at as readInventoryInput, ct as writeInventory, et as parseSizeMb, it as readInventory, nt as processTreeMemory, ot as readModelLabels, q as inventoryPath, rt as processTreeRssMb, st as startInventoryRefresh, tt as parseTable, z as INVENTORY_HEADERS } from "./routing-BAAST9vT.mjs";
7
+ import "./tool-errors-7E13StWd.mjs";
8
+ import "./wait-ByV0OyMZ.mjs";
9
+ import "./local-tiers-BE4jGaMa.mjs";
10
+ import "./caller-identity-yLFb7CKq.mjs";
11
+ import "./capacity-DEveQdFV.mjs";
12
+ import "./local-instances-DOxSgT_L.mjs";
13
+ import "./local-candidate-DLdwQt0s.mjs";
13
14
 
14
15
  export { computeInventory, currentInventory, processTreeRssMb, readInventoryInput, writeInventory };
@@ -1,41 +1,42 @@
1
1
  import "./utils-J2b9y8PC.mjs";
2
- import { tt as workersYamlPath } from "./config-D5chi2LO.mjs";
3
- import "./config-BSXKyeJ1.mjs";
4
- import "./paths-DoIyRnhx.mjs";
5
- import "./worktree-zmRf556h.mjs";
6
- import "./status-CvVi9cDf.mjs";
7
- import "./pool-CZ5MZaXg.mjs";
8
- import "./helpers-CJpb_MNB.mjs";
9
- import "./scope-D5VSQxe4.mjs";
10
- import "./routing-CUyiglfu.mjs";
11
- import "./tool-errors-AeRQuG3Y.mjs";
12
- import "./wait-BMUR-U-U.mjs";
13
- import { g as planStart, m as parseLocalConfig, o as defaultLauncher, y as shellQuote } from "./local-tiers-DPZYqv9m.mjs";
14
- import "./caller-identity-CVTuiLSs.mjs";
15
- import "./local-candidate-jOjTNlOL.mjs";
16
- import "./capacity-DaXrVj3J.mjs";
17
- import "./factory-BtjbQ0np.mjs";
18
- import "./postgres-CDnd_k5f.mjs";
19
- import "./embedding-gate-BHuBsgHD.mjs";
20
- import "./embeddings-D4t6L-EH.mjs";
21
- import "./router-L8Nu-OHF.mjs";
22
- import "./launch-DgqQdAjI.mjs";
23
- import "./health-C6jZWvRG.mjs";
24
- import "./run-ulAi5dFD.mjs";
25
- import "./controls-BGkK_Bdi.mjs";
26
- import "./endreason-x1KOSrcO.mjs";
27
- import "./render-BDbb4CF-.mjs";
28
- import "./operator-DZxcP-g8.mjs";
29
- import "./kill-tree-BjYz5BxK.mjs";
30
- import "./pool-cli-BxNSPzzY.mjs";
31
- import "./pane-audit-OGYrOAik.mjs";
32
- import "./providers-UsKtLcUR.mjs";
33
- import { B as allocatePort, H as sizeOnDiskGb, V as canBind, at as hashText, d as killInstance, f as launchDetached, h as portListeners, it as defaultRegistryCtx, l as healthOk, ot as saveRegistry } from "./worker-config-BLqa1yiD.mjs";
34
- import "./main-config-ops-C0SflOWk.mjs";
35
- import "./cockpit-actions-ODmt8yF9.mjs";
36
- import "./ipc-client-BMqWw_gv.mjs";
37
- import "./embed-pass-CeQD8kRE.mjs";
38
- import "./fallback-BIyEpPsQ.mjs";
2
+ import { tt as workersYamlPath } from "./config-XpZWOYOG.mjs";
3
+ import "./config-Bu1_vbY8.mjs";
4
+ import "./paths-CHifubDh.mjs";
5
+ import "./worktree-CrnOqTBW.mjs";
6
+ import "./status-ggJ7lgVg.mjs";
7
+ import "./pool-BRvoOkv6.mjs";
8
+ import "./helpers-CRuBUas3.mjs";
9
+ import "./scope-D-h6F6DN.mjs";
10
+ import "./routing-BAAST9vT.mjs";
11
+ import "./tool-errors-7E13StWd.mjs";
12
+ import "./wait-ByV0OyMZ.mjs";
13
+ import { g as planStart, m as parseLocalConfig, o as defaultLauncher, y as shellQuote } from "./local-tiers-BE4jGaMa.mjs";
14
+ import "./caller-identity-yLFb7CKq.mjs";
15
+ import "./capacity-DEveQdFV.mjs";
16
+ import "./local-instances-DOxSgT_L.mjs";
17
+ import "./local-candidate-DLdwQt0s.mjs";
18
+ import "./factory-DjAAsqr_.mjs";
19
+ import "./postgres-C6ti4haA.mjs";
20
+ import "./embedding-gate-6rZrWRXa.mjs";
21
+ import "./embeddings-BVq3esBF.mjs";
22
+ import "./router-CQSc3lk3.mjs";
23
+ import "./launch-Jh5NVeNe.mjs";
24
+ import "./health-Dnym-qcT.mjs";
25
+ import "./run-6Q9kCPem.mjs";
26
+ import "./controls-BcKFHeG1.mjs";
27
+ import "./endreason-C577xIQz.mjs";
28
+ import "./render-CwIrgxLi.mjs";
29
+ import "./operator-CyuB3aVw.mjs";
30
+ import "./kill-tree-EWYaEk5v.mjs";
31
+ import "./pool-cli-B_YR8_Gl.mjs";
32
+ import "./pane-audit-BQytYa60.mjs";
33
+ import "./providers-CblTFrhz.mjs";
34
+ import { H as canBind, U as sizeOnDiskGb, V as allocatePort, at as defaultRegistryCtx, f as killInstance, g as portListeners, ot as hashText, p as launchDetached, st as saveRegistry, u as healthOk } from "./worker-config-BDYNxbYz.mjs";
35
+ import "./main-config-ops-BEMpuhDz.mjs";
36
+ import "./cockpit-actions-C8GlTzts.mjs";
37
+ import "./ipc-client-CaiGJnSM.mjs";
38
+ import "./embed-pass-DIWjA68P.mjs";
39
+ import "./fallback-DFlItw1Z.mjs";
39
40
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
40
41
  import { basename, join } from "node:path";
41
42
  import { homedir } from "node:os";
@@ -331,4 +332,4 @@ async function smokeTest(cfg, name, d = {}) {
331
332
 
332
333
  //#endregion
333
334
  export { addModel };
334
- //# sourceMappingURL=models-add-Bt7aUHDs.mjs.map
335
+ //# sourceMappingURL=models-add-BtB3Se6f.mjs.map