@tekmidian/pai 1.0.0 → 1.0.3

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 (219) 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-B7Yu6Uam.mjs} +3 -3
  7. package/dist/auto-route-CjjQqU1o.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-7n9Gx56r.mjs} +5 -5
  12. package/dist/cli/index.mjs +1628 -370
  13. package/dist/{cockpit-actions-ODmt8yF9.mjs → cockpit-actions-BBHeyEZI.mjs} +84 -42
  14. package/dist/cockpit-actions-DR9X514g.mjs +20 -0
  15. package/dist/cockpit-memory--dnShXBA.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-CPoeudou.mjs} +37 -22
  21. package/dist/daemon/index.mjs +43 -42
  22. package/dist/daemon-DKdBNKfa.mjs +45 -0
  23. package/dist/{daemon-CorGh6Ub.mjs → daemon-DPAo6WTa.mjs} +103 -55
  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 +329 -231
  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-Cll7le4P.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-C1QIc1DA.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-BcZyJguM.mjs} +7 -6
  83. package/dist/{pane-audit-OGYrOAik.mjs → pane-audit-DKQt71s4.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-BmFACdLa.mjs} +31 -30
  87. package/dist/{pool-CZ5MZaXg.mjs → pool-Dh-q3iJi.mjs} +45 -6
  88. package/dist/{pool-cli-BxNSPzzY.mjs → pool-cli-BggU8GRp.mjs} +5 -5
  89. package/dist/{pool-cli-CbJfl37y.mjs → pool-cli-DQ6OzRy2.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-jvfONJTQ.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-BzH4TObg.mjs +9 -0
  97. package/dist/{registrable-LrRIVYQc.mjs → registrable-DpyTtajg.mjs} +4 -4
  98. package/dist/{render-BDbb4CF-.mjs → render-BYmQkuLd.mjs} +8 -8
  99. package/dist/render-CoMvwMPs.mjs +13 -0
  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-FtJsxYnm.mjs +36 -0
  103. package/dist/{root-BMeJuHOb.mjs → root-Xglu0OPD.mjs} +11 -11
  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-CSC7mgPf.mjs} +35 -33
  110. package/dist/{scan-B7I0gPe-.mjs → scan-C_Y5W9py.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-CNXF6DLP.mjs → session-8iqQDkqb.mjs} +55 -31
  116. package/dist/session-BeqAbNPd.mjs +35 -0
  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-CqozWW39.mjs +22 -0
  128. package/dist/{viewer-DtWj5Vti.mjs → viewer-mDXUNHNy.mjs} +15 -15
  129. package/dist/{wait-BMUR-U-U.mjs → wait-ByV0OyMZ.mjs} +3 -3
  130. package/dist/{worker-config-BLqa1yiD.mjs → worker-config-CJhEMk19.mjs} +294 -92
  131. package/dist/worker-config-DESkIjMF.mjs +41 -0
  132. package/dist/{workers-config-DEI9lrV4.mjs → workers-config-f8KrkY4L.mjs} +2 -2
  133. package/dist/{worktree-zmRf556h.mjs → worktree-CRs2gyg0.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.png +0 -0
  149. package/docs/images/architecture.svg +3 -0
  150. package/docs/images/cockpit-01-system-tokens.jpg +0 -0
  151. package/docs/images/cockpit-02-totals-cache.jpg +0 -0
  152. package/docs/images/cockpit-03-local-servers-models-pool.jpg +0 -0
  153. package/docs/images/cockpit-04-workers-memory.jpg +0 -0
  154. package/docs/images/cockpit-05-performance.jpg +0 -0
  155. package/docs/images/cockpit-06-runs-speed-routing.jpg +0 -0
  156. package/docs/images/cockpit-07-settings-registry.jpg +0 -0
  157. package/docs/install/index.md +29 -0
  158. package/docs/three-tier-coding.md +1 -1
  159. package/gemini-extension.json +1 -1
  160. package/package.json +1 -5
  161. package/pai-plugin.json +1 -1
  162. package/plugins/context-preservation/plugin.json +1 -1
  163. package/plugins/core/plugin.json +1 -1
  164. package/plugins/core/skills/setup/SKILL.md +41 -9
  165. package/plugins/creative/plugin.json +1 -1
  166. package/plugins/observability/plugin.json +1 -1
  167. package/plugins/productivity/plugin.json +1 -1
  168. package/plugins/semantic-search/plugin.json +1 -1
  169. package/plugins/ui/plugin.json +1 -1
  170. package/plugins/zettelkasten/plugin.json +1 -1
  171. package/src/hooks/session-autosave.sh +8 -1
  172. package/src/hooks/session-stop.sh +8 -1
  173. package/src/hooks/ts/capture-all-events.ts +7 -12
  174. package/src/hooks/ts/lib/context-fill.ts +2 -1
  175. package/src/hooks/ts/lib/path-repair.ts +1 -1
  176. package/src/hooks/ts/lib/project-utils/notify.ts +1 -0
  177. package/src/hooks/ts/lib/project-utils/session-notes.ts +23 -6
  178. package/src/hooks/ts/lib/raw-capture.ts +36 -0
  179. package/src/hooks/ts/lib/session-summary.ts +129 -0
  180. package/src/hooks/ts/lib/todo-sync.ts +120 -0
  181. package/src/hooks/ts/lib/worker-git-guard.ts +1 -1
  182. package/src/hooks/ts/post-tool-use/capture-tool-output.ts +6 -10
  183. package/src/hooks/ts/post-tool-use/sync-todo-to-md.ts +5 -105
  184. package/src/hooks/ts/pre-compact/context-compression-hook.ts +1 -1
  185. package/src/hooks/ts/pre-tool-use/security-validator.ts +35 -14
  186. package/src/hooks/ts/session-end/capture-session-summary.ts +20 -128
  187. package/src/hooks/ts/session-start/load-core-context.ts +3 -3
  188. package/src/hooks/ts/session-start/load-project-context.ts +18 -22
  189. package/src/hooks/ts/stop/stop-hook.ts +13 -5
  190. package/src/hooks/ztk-auto.sh +7 -2
  191. package/dist/aibroker-client-JjE74jo0.mjs +0 -3
  192. package/dist/auto-route-BRk8NEFv.mjs +0 -11
  193. package/dist/budget-DuhQ2zzG.mjs +0 -14
  194. package/dist/cockpit-actions-DcQ-ucU8.mjs +0 -19
  195. package/dist/cockpit-memory-KV45PPO2.mjs +0 -19
  196. package/dist/daemon-C7yt_ptC.mjs +0 -44
  197. package/dist/detect-DRUkmHnb.mjs +0 -10
  198. package/dist/factory-DAGG9_n8.mjs +0 -9
  199. package/dist/helpers-DPJEHPq6.mjs +0 -10
  200. package/dist/kill-tree-LV0Q7Mte.mjs +0 -10
  201. package/dist/operator-CfL0HiBK.mjs +0 -7
  202. package/dist/postgres-DgqWyqhN.mjs +0 -7
  203. package/dist/providers-CTu2s1z2.mjs +0 -15
  204. package/dist/registrable-D9aNZOTh.mjs +0 -9
  205. package/dist/render-BSfVlYHj.mjs +0 -13
  206. package/dist/root-xI9DqVIe.mjs +0 -35
  207. package/dist/route-table-HjvnLVEU.mjs +0 -14
  208. package/dist/session-BJHzmUg2.mjs +0 -34
  209. package/dist/session-scan-YORKE1NO.mjs +0 -9
  210. package/dist/viewer-B8709jDN.mjs +0 -22
  211. package/dist/worker-config-D8tRuvo7.mjs +0 -40
  212. package/docs/images/cockpit-limits-routing.jpg +0 -0
  213. package/docs/images/cockpit-models.jpg +0 -0
  214. package/docs/images/cockpit-usage.jpg +0 -0
  215. package/docs/images/cockpit-workers-system.jpg +0 -0
  216. package/scripts/build-docs.mjs +0 -41
  217. package/scripts/build-hooks.mjs +0 -311
  218. package/scripts/build-skill-stubs.mjs +0 -216
  219. package/scripts/copy-defaults.mjs +0 -46
@@ -1,37 +1,39 @@
1
1
  import { _ as warn, c as ok, i as err, n as dim } from "./utils-J2b9y8PC.mjs";
2
2
  import { g as paiHomePath, h as paiHomeDir, l as claudeHomeDir, t as aibrokerHomeDir, u as claudeProjectsDir } from "./runtime-paths-WsO9sJFc.mjs";
3
- import { Et as parseLedger, G as inlineWorkersYamlKeys, J as parseBuiltinAnthropic, K as migrateWorkersToYaml, Q as relocateWorkersYaml, R as isLoopbackUrl, T as parseProvider, W as initWorkersYaml, Y as parseWorkersYamlDocument, c as WorkersConfigError, et as workersYamlLegacyNotice, ft as parseEntry, it as yamlProviderToRaw, j as readWorkersSection, lt as findTier, m as isLocalProvider, o as PROVIDER_TAGS, p as getProviderOrNative, q as needsWorkersYamlRelocation, t as ANTHROPIC_NATIVE, tt as workersYamlPath, wt as appendLedger, y as nativeAnthropicProvider, z as loopbackUrl } from "./config-D5chi2LO.mjs";
4
- import { D as readJsonStrict, O as writeJsonAtomic, f as readMainConfigRaw, m as deepMergeConfig, n as CONFIG_FILE, o as expandHome, u as paiConfigFilePath, v as shippedDefaultsDir, y as shippedMainDefaults } from "./config-BSXKyeJ1.mjs";
5
- import { i as ledgerPath, t as WORKER_ID_RE, u as workersLogDir } from "./paths-DoIyRnhx.mjs";
6
- import { E as worktreesStatsCached, l as formatWorktreesStats } from "./worktree-zmRf556h.mjs";
7
- import { T as ownsPidCached, b as loadStatusesCached, g as isLive, v as loadStatus } from "./status-CvVi9cDf.mjs";
8
- import { C as describeMcp, _ as readPoolMetrics, f as poolMetricsPath, h as poolSettings, i as bundleBuildStamp, l as poolHostProbe, o as poolCarry, u as poolHostStale, v as readPoolState, x as warmOrCold } from "./pool-CZ5MZaXg.mjs";
9
- import { a as ownerSessionName } from "./scope-D5VSQxe4.mjs";
10
- import { $t as onBattery, At as applyPolicyToRoutes, Bn as reconcileInstances, Bt as routeText, Dt as isTailnetOrLocalName, E as budgetCache, Fn as instanceEngineKey, Gt as setSessionRoute, I as buildSpeed, In as instanceNumber, Jt as POLICY_MODES, L as percentile, Ln as instancesFromProcesses, Lt as resolveSessionArg, Ot as loopbackRefusal, Pt as flowText, Qn as markTimeOrdered, Qt as findLocal, Rn as readInstances, Rt as routeChoices, Vn as writeInstances, Vt as servingChip, W as currentInventory, Wt as setRoute, Yt as clearPolicy, Zn as isTimeOrdered, _n as probeLoopback, at as readInventoryInput, en as parseDuration, gn as pickLocal, hn as localTierOrder, it as readInventory, jt as clearSessionRoute, ln as readProfiles, nn as routeRun, nr as splitBySessionKind, pn as currentLocalStatus, rn as writePolicy, rr as usageLogFile, rt as processTreeRssMb, sn as getProfile, tn as readPolicy, tr as readUsageCached, wt as duplicateModelIds, zn as readLiveInstances, zt as routeRows } from "./routing-CUyiglfu.mjs";
11
- import { C as stopLines, T as tierButtons, _ as readLocalConfig, a as LocalTierError, c as fetchServedModels, f as listensOnPort, g as planStart, h as parseServers, l as fmtRss, m as parseLocalConfig, u as healthUrl, v as resolveModelPath, x as stopCommandFor } from "./local-tiers-DPZYqv9m.mjs";
12
- import { b as testSlots, c as listBuildsSync, g as buildSlots, h as waitReason, i as buildsDir, p as ticketKind } from "./caller-identity-CVTuiLSs.mjs";
13
- import { g as sharedScheduler, i as localStatusLine, m as schedPlain, o as readLocalStatus, u as readSchedFile } from "./local-candidate-jOjTNlOL.mjs";
14
- import { l as reorderQueue, o as providerCap, s as queueRows, u as reorderQueueTo } from "./capacity-DaXrVj3J.mjs";
15
- import { t as LOCAL_PROBE_TIMEOUT_MS } from "./timeouts-OwEONmc8.mjs";
16
- import { n as OPT, t as CliError } from "./define-DGFu-sCf.mjs";
17
- import { c as resolveFromModule } from "./postgres-CDnd_k5f.mjs";
18
- import { c as ensureProxyRunning, l as proxyPort, u as stopProxy } from "./launch-DgqQdAjI.mjs";
19
- import { a as colorEnabled, f as renderTable, n as readBudget, o as makeStyle } from "./health-C6jZWvRG.mjs";
20
- import { H as testProvider, o as sessionWorkersLine } from "./run-ulAi5dFD.mjs";
21
- import { U as planRows, V as loadPlanStatuses, i as localIdleLine, n as markControlsHeld, s as readLocalIdle, t as clickrControlsArgv, yt as psTable } from "./controls-BGkK_Bdi.mjs";
22
- import { n as diskBundleMtime, r as ensurePoolHost } from "./pool-cli-BxNSPzzY.mjs";
23
- import { a as readAudit, d as loadPaneRunStatuses, f as paneRunRows } from "./pane-audit-OGYrOAik.mjs";
24
- import { b as useProvider, f as setClass, g as setWorkersEnabled, l as removeProvider, m as setProviderEnabled, p as setProviderCap, r as classTargetText, s as describeProviders, t as addProvider, v as unsetClass, y as updateProvider } from "./providers-UsKtLcUR.mjs";
25
- import { C as embeddingRuntimeName, F as cockpitLayout, I as cockpitProbeSettings, O as liveMemoryDeps, T as cockpitMemoryPayload, _ as runtimeJobProgress, d as readCockpitJob, f as readLabels, g as runningRuntimeJobs, k as memoryJobProgress, m as runCockpitAction, o as defaultDeps, t as COCKPIT_ACTION_EVENT, w as readRuntimeCommands } from "./cockpit-actions-ODmt8yF9.mjs";
26
- import { i as fallbackStatusText, n as fallbackOn, r as fallbackStatus, t as fallbackOff } from "./fallback-BIyEpPsQ.mjs";
27
- import { appendFileSync, chmodSync, closeSync, copyFileSync, existsSync, fstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
3
+ import { Et as parseLedger, G as inlineWorkersYamlKeys, J as parseBuiltinAnthropic, K as migrateWorkersToYaml, Q as relocateWorkersYaml, R as isLoopbackUrl, T as parseProvider, W as initWorkersYaml, Y as parseWorkersYamlDocument, c as WorkersConfigError, et as workersYamlLegacyNotice, ft as parseEntry, it as yamlProviderToRaw, j as readWorkersSection, lt as findTier, m as isLocalProvider, o as PROVIDER_TAGS, p as getProviderOrNative, q as needsWorkersYamlRelocation, t as ANTHROPIC_NATIVE, tt as workersYamlPath, wt as appendLedger, y as nativeAnthropicProvider, z as loopbackUrl } from "./config-XpZWOYOG.mjs";
4
+ import { D as readJsonStrict, O as writeJsonAtomic, f as readMainConfigRaw, m as deepMergeConfig, n as CONFIG_FILE, o as expandHome, u as paiConfigFilePath, v as shippedDefaultsDir, y as shippedMainDefaults } from "./config-Bu1_vbY8.mjs";
5
+ import { i as ledgerPath, t as WORKER_ID_RE, u as workersLogDir } from "./paths-CHifubDh.mjs";
6
+ import { E as worktreesStatsCached, l as formatWorktreesStats } from "./worktree-CRs2gyg0.mjs";
7
+ import { T as ownsPidCached, b as loadStatusesCached, g as isLive, v as loadStatus } from "./status-ggJ7lgVg.mjs";
8
+ import { C as describeMcp, _ as readPoolMetrics, f as poolMetricsPath, h as poolSettings, i as bundleBuildStamp, l as poolHostProbe, o as poolCarry, u as poolHostStale, v as readPoolState, x as warmOrCold } from "./pool-Dh-q3iJi.mjs";
9
+ import { a as ownerSessionName } from "./scope-D-h6F6DN.mjs";
10
+ import { $t as findLocal, Bt as routeRows, E as budgetCache, Ft as flowText, Gn as isTimeOrdered, Gt as setRoute, Ht as servingChip, I as buildSpeed, Kn as markTimeOrdered, Kt as setSessionRoute, L as percentile, Mt as clearSessionRoute, Ot as isTailnetOrLocalName, Rt as resolveSessionArg, Tt as duplicateModelIds, Vt as routeText, W as currentInventory, Xn as usageLogFile, Xt as clearPolicy, Yn as splitBySessionKind, Yt as POLICY_MODES, _n as pickLocal, at as readInventoryInput, cn as getProfile, en as onBattery, gn as localTierOrder, in as writePolicy, it as readInventory, jt as applyPolicyToRoutes, kt as loopbackRefusal, mn as currentLocalStatus, nn as readPolicy, rn as routeRun, rt as processTreeRssMb, tn as parseDuration, un as readProfiles, vn as probeLoopback, zt as routeChoices } from "./routing-BAAST9vT.mjs";
11
+ import { C as stopLines, T as tierButtons, _ as readLocalConfig, a as LocalTierError, c as fetchServedModels, f as listensOnPort, g as planStart, h as parseServers, l as fmtRss, m as parseLocalConfig, u as healthUrl, v as resolveModelPath, x as stopCommandFor } from "./local-tiers-BE4jGaMa.mjs";
12
+ import { _ as buildSlots, a as buildsDir, g as waitReason, l as listBuildsSync, m as ticketKind, n as breakStaleMutex, x as testSlots } from "./caller-identity-yLFb7CKq.mjs";
13
+ import { f as sharedScheduler, o as readSchedFile, u as schedPlain } from "./scheduler-CtUyWJ3O.mjs";
14
+ import { l as reorderQueue, o as providerCap, s as queueRows, u as reorderQueueTo } from "./capacity-DEveQdFV.mjs";
15
+ import { a as instancesFromProcesses, d as reconcileInstances, i as instanceNumber, l as readInstances, p as writeInstances, r as instanceEngineKey, u as readLiveInstances } from "./local-instances-DOxSgT_L.mjs";
16
+ import { i as localStatusLine, s as readLocalStatus } from "./local-candidate-DLdwQt0s.mjs";
17
+ import { t as LOCAL_PROBE_TIMEOUT_MS } from "./timeouts-1MLooEBB.mjs";
18
+ import { n as OPT, t as CliError } from "./define-CjJsmq-6.mjs";
19
+ import { c as resolveFromModule } from "./postgres-C6ti4haA.mjs";
20
+ import { c as ensureProxyRunning, l as proxyPort, u as stopProxy } from "./launch-Jh5NVeNe.mjs";
21
+ import { a as colorEnabled, f as renderTable, n as readBudget, o as makeStyle } from "./health-Dnym-qcT.mjs";
22
+ import { H as testProvider, o as sessionWorkersLine } from "./run-CSC7mgPf.mjs";
23
+ import { U as planRows, V as loadPlanStatuses, i as localIdleLine, n as markControlsHeld, s as readLocalIdle, t as clickrControlsArgv, yt as psTable } from "./controls-CPoeudou.mjs";
24
+ import { n as diskBundleMtime, r as ensurePoolHost } from "./pool-cli-BggU8GRp.mjs";
25
+ import { a as readAudit, d as loadPaneRunStatuses, f as paneRunRows } from "./pane-audit-DKQt71s4.mjs";
26
+ import { b as useProvider, f as setClass, g as setWorkersEnabled, l as removeProvider, m as setProviderEnabled, p as setProviderCap, r as classTargetText, s as describeProviders, t as addProvider, v as unsetClass, y as updateProvider } from "./providers-CblTFrhz.mjs";
27
+ import { A as cockpitMemoryPayload, B as cockpitLayout, N as liveMemoryDeps, O as embeddingRuntimeName, P as memoryJobProgress, S as runtimeJobProgress, V as cockpitProbeSettings, c as defaultDeps, g as readLabels, h as readCockpitJob, k as readRuntimeCommands, t as COCKPIT_ACTION_EVENT, v as runCockpitAction, x as runningRuntimeJobs } from "./cockpit-actions-BBHeyEZI.mjs";
28
+ import { i as fallbackStatusText, n as fallbackOn, r as fallbackStatus, t as fallbackOff } from "./fallback-DFlItw1Z.mjs";
29
+ import { appendFileSync, chmodSync, closeSync, copyFileSync, existsSync, fstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, renameSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
30
+ import { createHash } from "node:crypto";
28
31
  import { basename, dirname, join, resolve } from "node:path";
29
32
  import chalk from "chalk";
30
33
  import { homedir, loadavg } from "node:os";
31
34
  import { execFile, execFileSync, spawn } from "node:child_process";
32
35
  import { fileURLToPath } from "node:url";
33
36
  import { LineCounter, isMap, isScalar, parse, parseDocument } from "yaml";
34
- import { createHash } from "node:crypto";
35
37
  import { connect, createServer } from "node:net";
36
38
 
37
39
  //#region src/cli/commands/providers.ts
@@ -5871,7 +5873,6 @@ function cockpitHtml() {
5871
5873
  * UI that shows the project separately. Unknown ids map to null.
5872
5874
  */
5873
5875
  function defaultSources() {
5874
- homedir();
5875
5876
  return {
5876
5877
  workerDirs: [paiHomePath("logs", "workers"), join(claudeHomeDir(), "logs", "workers")],
5877
5878
  agentSessionsFile: paiHomePath("agent-sessions.json"),
@@ -5897,6 +5898,11 @@ function jobSessionName(id, jobsDir = defaultSources().jobsDir, now = Date.now()
5897
5898
  if (hit && now - hit.at < JOB_TTL_MS) return hit.name;
5898
5899
  const raw = readJson(join(jobsDir, id8, "state.json"))?.name;
5899
5900
  const name = typeof raw === "string" && raw ? raw : null;
5901
+ jobCache.delete(key);
5902
+ for (const [k, v] of jobCache) {
5903
+ if (now - v.at < JOB_TTL_MS) break;
5904
+ jobCache.delete(k);
5905
+ }
5900
5906
  jobCache.set(key, {
5901
5907
  at: now,
5902
5908
  name
@@ -6035,20 +6041,26 @@ function loadSessionMap(src = defaultSources()) {
6035
6041
  /** The loader below as steps: a `yield` after each directory or file, so a driver can hand the event loop back between them. */
6036
6042
  function* loadSessionMapSteps(src = defaultSources()) {
6037
6043
  const map = /* @__PURE__ */ new Map();
6038
- if (src.projectsDir && existsSync(src.projectsDir)) for (const d of readdirSync(src.projectsDir)) {
6039
- const name = d.split("-").filter(Boolean).pop();
6040
- if (!name) continue;
6041
- let files = [];
6044
+ if (src.projectsDir && existsSync(src.projectsDir)) {
6045
+ let projectDirs = [];
6042
6046
  try {
6043
- files = readdirSync(join(src.projectsDir, d));
6044
- } catch {
6045
- continue;
6046
- }
6047
- for (const f of files) {
6048
- const id = f.endsWith(".jsonl") ? f.slice(0, -6) : "";
6049
- if (id) map.set(id, { name });
6047
+ projectDirs = readdirSync(src.projectsDir);
6048
+ } catch {}
6049
+ for (const d of projectDirs) {
6050
+ const name = d.split("-").filter(Boolean).pop();
6051
+ if (!name) continue;
6052
+ let files = [];
6053
+ try {
6054
+ files = readdirSync(join(src.projectsDir, d));
6055
+ } catch {
6056
+ continue;
6057
+ }
6058
+ for (const f of files) {
6059
+ const id = f.endsWith(".jsonl") ? f.slice(0, -6) : "";
6060
+ if (id) map.set(id, { name });
6061
+ }
6062
+ yield;
6050
6063
  }
6051
- yield;
6052
6064
  }
6053
6065
  const agents = existsSync(src.agentSessionsFile) ? readJson(src.agentSessionsFile) : void 0;
6054
6066
  if (agents) for (const [id, project] of Object.entries(agents)) {
@@ -6087,7 +6099,13 @@ function* loadSessionMapSteps(src = defaultSources()) {
6087
6099
  }
6088
6100
  for (const dir of src.workerDirs) {
6089
6101
  if (!existsSync(dir)) continue;
6090
- for (const f of readdirSync(dir)) {
6102
+ let dirFiles = [];
6103
+ try {
6104
+ dirFiles = readdirSync(dir);
6105
+ } catch {
6106
+ continue;
6107
+ }
6108
+ for (const f of dirFiles) {
6091
6109
  if (!f.endsWith(".status")) continue;
6092
6110
  yield;
6093
6111
  const s = readJson(join(dir, f));
@@ -6202,7 +6220,7 @@ function* withWorkerAttributionSteps(map, rows, windows, now = Date.now()) {
6202
6220
  hits.set(w.worker, w);
6203
6221
  }
6204
6222
  if (!hits.size) continue;
6205
- const first = Math.min(...reqs.map((r) => r.t));
6223
+ const first = reqs.reduce((m, r) => Math.min(m, r.t), Infinity);
6206
6224
  const best = [...hits.values()].sort((a, b) => b.startMs - a.startMs)[0];
6207
6225
  if (best.startMs > first) continue;
6208
6226
  out.set(id, {
@@ -6725,26 +6743,86 @@ function tierProviderList() {
6725
6743
  }
6726
6744
  const WHOLE_LOG_TTL_MS = 3e4;
6727
6745
  const wholeLogMemo = /* @__PURE__ */ new WeakMap();
6746
+ /** Whole-log figures, folded row by row as the log is read so the rows themselves can be dropped once they are older than any window. */
6747
+ var LogAgg = class {
6748
+ /** per provider+model: requests, prompt tokens, first ts (a fold by model owner is applied on top at read time) */
6749
+ pairs = /* @__PURE__ */ new Map();
6750
+ /** tokens per UTC day per model, with the sequence number of the model's first row that day (keeps the model order of a row scan) */
6751
+ daily = /* @__PURE__ */ new Map();
6752
+ seq = 0;
6753
+ add(r) {
6754
+ const model = typeof r.model === "string" ? canonicalModel(r.model) : "";
6755
+ const k = `${r.provider}\u0000${model}`;
6756
+ const p = this.pairs.get(k) ?? {
6757
+ provider: r.provider,
6758
+ model,
6759
+ n: 0,
6760
+ prompt: 0,
6761
+ since: r.ts
6762
+ };
6763
+ p.n++;
6764
+ p.prompt += (r.input_tokens ?? 0) + (r.cache_read_input_tokens ?? 0) + (r.cache_creation_input_tokens ?? 0);
6765
+ if (r.ts < p.since) p.since = r.ts;
6766
+ this.pairs.set(k, p);
6767
+ const day = bucketStart(Date.parse(r.ts), DAY$1);
6768
+ const d = this.daily.get(day) ?? /* @__PURE__ */ new Map();
6769
+ const e = d.get(model) ?? {
6770
+ sum: 0,
6771
+ seq: this.seq
6772
+ };
6773
+ e.sum += (r.input_tokens ?? 0) + (r.output_tokens ?? 0) + (r.cache_creation_input_tokens ?? 0) + (r.cache_read_input_tokens ?? 0);
6774
+ d.set(model, e);
6775
+ this.daily.set(day, d);
6776
+ this.seq++;
6777
+ }
6778
+ /** Forget the day buckets before `cut`: no window looks back further than the 14 days the daily chart shows. */
6779
+ pruneDaily(cut) {
6780
+ for (const day of this.daily.keys()) if (day < cut) this.daily.delete(day);
6781
+ }
6782
+ /** The pairs as the fold of the providers would have rewritten their rows. */
6783
+ folded(providers) {
6784
+ const owners = modelOwners(providers);
6785
+ const all = [...this.pairs.values()];
6786
+ return owners.size ? foldProviders(all, providers, owners) : all;
6787
+ }
6788
+ };
6789
+ const aggs = /* @__PURE__ */ new WeakMap();
6790
+ /** The aggregates a cached log carries; a plain array (tests, callers that bring their own rows) is scanned. */
6791
+ function aggOf(rows) {
6792
+ const have = aggs.get(rows);
6793
+ if (have) return have;
6794
+ const a = new LogAgg();
6795
+ for (const r of rows) a.add(r);
6796
+ return a;
6797
+ }
6728
6798
  /** The parts of the cockpit payload that read the whole log whatever the window is. Costly on a big log, so they are kept per log array until it grows or 30 s pass (the speed table moves with the clock). */
6729
- function wholeLog(allRows, now, providers) {
6799
+ function wholeLog(allRows, agg, now, providers) {
6730
6800
  const sig = JSON.stringify(Object.entries(providers).map(([k, v]) => [k, v.baseUrl]));
6731
6801
  const m = wholeLogMemo.get(allRows);
6732
6802
  if (m && m.n === allRows.length && m.sig === sig && Math.abs(now - m.at) < WHOLE_LOG_TTL_MS) return m.out;
6733
6803
  const dayFrom = bucketStart(now, DAY$1) - 13 * DAY$1;
6734
6804
  const days = [];
6735
6805
  for (let t = dayFrom; t <= now; t += DAY$1) days.push(t);
6736
- const daily = {};
6737
- for (const r of allRows) {
6738
- const t = Date.parse(r.ts);
6739
- if (t < dayFrom) continue;
6740
- const arr = daily[canonicalModel(r.model)] ??= days.map(() => 0);
6741
- arr[Math.floor((bucketStart(t, DAY$1) - dayFrom) / DAY$1)] += (r.input_tokens ?? 0) + (r.output_tokens ?? 0) + (r.cache_creation_input_tokens ?? 0) + (r.cache_read_input_tokens ?? 0);
6806
+ const daily = dict();
6807
+ const inRange = [];
6808
+ for (const [day, ms] of agg.daily) {
6809
+ if (day < dayFrom) continue;
6810
+ for (const [model, e] of ms) inRange.push({
6811
+ day,
6812
+ model,
6813
+ ...e
6814
+ });
6815
+ }
6816
+ inRange.sort((a, b) => a.seq - b.seq);
6817
+ for (const e of inRange) {
6818
+ const arr = daily[e.model] ??= days.map(() => 0);
6819
+ arr[Math.floor((e.day - dayFrom) / DAY$1)] += e.sum;
6742
6820
  }
6743
- const promptByProvider = {};
6744
- const promptSince = {};
6745
- for (const r of allRows) {
6746
- if (!promptSince[r.provider] || r.ts < promptSince[r.provider]) promptSince[r.provider] = r.ts;
6747
- promptByProvider[r.provider] = (promptByProvider[r.provider] ?? 0) + (r.input_tokens ?? 0) + (r.cache_read_input_tokens ?? 0) + (r.cache_creation_input_tokens ?? 0);
6821
+ const promptByProvider = dict();
6822
+ const promptSince = dict();
6823
+ for (const p of agg.folded(providers)) {
6824
+ if (!promptSince[p.provider] || p.since < promptSince[p.provider]) promptSince[p.provider] = p.since;
6825
+ promptByProvider[p.provider] = (promptByProvider[p.provider] ?? 0) + p.prompt;
6748
6826
  }
6749
6827
  const out = {
6750
6828
  days,
@@ -6794,23 +6872,23 @@ function windowRows(allRows, from) {
6794
6872
  function buildCockpitData(allRows, win, now = Date.now(), sessions = /* @__PURE__ */ new Map(), pool = null, providers = {}) {
6795
6873
  const { span, bucket } = WINDOWS[win];
6796
6874
  const from = bucketStart(now - span, bucket);
6875
+ const agg = aggOf(allRows);
6797
6876
  allRows = foldedRows(allRows, providers);
6798
6877
  const rows = windowRows(allRows, from);
6799
6878
  const retries = retryRows(rows);
6800
6879
  const ecoCount = /* @__PURE__ */ new Map();
6801
- for (const r of allRows) {
6802
- const m = canonicalModel(r.model);
6803
- const c = ecoCount.get(m) ?? /* @__PURE__ */ new Map();
6880
+ for (const r of agg.folded(providers)) {
6881
+ const c = ecoCount.get(r.model) ?? /* @__PURE__ */ new Map();
6804
6882
  const e = providerEcosystem(r.provider, providers);
6805
- c.set(e, (c.get(e) ?? 0) + 1);
6806
- ecoCount.set(m, c);
6883
+ c.set(e, (c.get(e) ?? 0) + r.n);
6884
+ ecoCount.set(r.model, c);
6807
6885
  }
6808
- const ecosystems = {};
6886
+ const ecosystems = dict();
6809
6887
  for (const [m, c] of ecoCount) ecosystems[m] = [...c.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))[0][0];
6810
6888
  const series = [];
6811
6889
  for (let t = from; t <= now; t += bucket) series.push({
6812
6890
  t,
6813
- models: {}
6891
+ models: dict()
6814
6892
  });
6815
6893
  const total = tok();
6816
6894
  let errors = 0;
@@ -6821,7 +6899,7 @@ function buildCockpitData(allRows, win, now = Date.now(), sessions = /* @__PURE_
6821
6899
  const byInstance = /* @__PURE__ */ new Map();
6822
6900
  const bySession = /* @__PURE__ */ new Map();
6823
6901
  const pause = /* @__PURE__ */ new Map();
6824
- const bustParts = {};
6902
+ const bustParts = dict();
6825
6903
  for (const r of rows) {
6826
6904
  const model = canonicalModel(r.model);
6827
6905
  const t = Date.parse(r.ts);
@@ -6938,7 +7016,7 @@ function buildCockpitData(allRows, win, now = Date.now(), sessions = /* @__PURE_
6938
7016
  workerEnd: info?.endMs ?? null
6939
7017
  };
6940
7018
  }).sort((a, b) => b.input + b.output + b.cacheWrite + b.cacheRead - (a.input + a.output + a.cacheWrite + a.cacheRead));
6941
- const { daily, days, promptByProvider, promptSince, speed } = wholeLog(allRows, now, providers);
7019
+ const { daily, days, promptByProvider, promptSince, speed } = wholeLog(allRows, agg, now, providers);
6942
7020
  const withRatio = (x) => ({
6943
7021
  ...x,
6944
7022
  hitRatio: hitRatio(x)
@@ -6995,45 +7073,93 @@ function buildCockpitData(allRows, win, now = Date.now(), sessions = /* @__PURE_
6995
7073
  pool: pool && pool.tasks > 0 ? pool : null
6996
7074
  };
6997
7075
  }
7076
+ const USAGE_HEAD_BYTES = 4096;
7077
+ /** A map keyed by logged names (model, provider): no prototype, so a key such as "__proto__" is an ordinary entry. */
7078
+ const dict = () => Object.create(null);
6998
7079
  /**
6999
7080
  * The usage log as rows, kept in memory: a log that only grew is read from where the last read
7000
7081
  * stopped (the router appends a row per request, so a full reread of tens of MB on every append
7001
7082
  * would block the event loop); one that shrank or was replaced is read again from the start.
7083
+ * The whole-log figures (prompt tokens and first ts per provider, requests per provider+model,
7084
+ * tokens per day) are folded into running aggregates as rows are read; the rows themselves are
7085
+ * kept for ROWS_KEPT_MS only (the 7 d window reaches back 8 d at most, one day of slack on top)
7086
+ * and dropped once a day, so memory follows the window, not the log.
7002
7087
  */
7003
- function cachedRows(file = usageLogFile()) {
7088
+ const ROWS_KEPT_MS = 9 * DAY$1;
7089
+ const DAILY_KEPT_MS = 15 * DAY$1;
7090
+ function cachedRows(file = usageLogFile(), clock = Date.now) {
7004
7091
  let rows = [];
7092
+ let agg = new LogAgg();
7093
+ let lastTrim = 0;
7094
+ let ordered = true;
7005
7095
  let offset = 0;
7006
7096
  let mtimeMs = 0;
7097
+ let ino = -1;
7098
+ let head = "";
7099
+ let lastMs = 0;
7100
+ const fresh = (kept) => {
7101
+ rows = kept;
7102
+ if (ordered) markTimeOrdered(rows);
7103
+ aggs.set(rows, agg);
7104
+ };
7105
+ const reset = () => {
7106
+ ordered = true;
7107
+ agg = new LogAgg();
7108
+ lastTrim = clock();
7109
+ fresh([]);
7110
+ offset = 0;
7111
+ ino = -1;
7112
+ head = "";
7113
+ lastMs = 0;
7114
+ mtimeMs = 0;
7115
+ };
7116
+ reset();
7007
7117
  return () => {
7008
7118
  try {
7009
- const st = statSync(file);
7010
- if (st.size === offset && st.mtimeMs === mtimeMs) return rows;
7011
- if (st.size < offset) {
7012
- rows = [];
7013
- offset = 0;
7014
- }
7015
7119
  const fd = openSync(file, "r");
7016
7120
  try {
7121
+ const st = fstatSync(fd);
7122
+ const headLen = Math.min(USAGE_HEAD_BYTES, st.size);
7123
+ const headBuf = Buffer.alloc(headLen);
7124
+ readSync(fd, headBuf, 0, headLen, 0);
7125
+ const nowHead = headBuf.toString("latin1");
7126
+ if (offset > 0 && (st.ino !== ino || st.size < offset || !nowHead.startsWith(head))) reset();
7127
+ if (st.size === offset && st.mtimeMs === mtimeMs) return rows;
7017
7128
  const buf = Buffer.alloc(st.size - offset);
7018
7129
  const n = readSync(fd, buf, 0, buf.length, offset);
7019
- const text = buf.subarray(0, n).toString("utf8");
7020
- const end = text.lastIndexOf("\n") + 1;
7021
- const added = [];
7022
- for (const l of text.slice(0, end).split("\n")) {
7130
+ let chunk = buf.subarray(0, n);
7131
+ const nl = chunk.lastIndexOf(10);
7132
+ chunk = nl < 0 ? chunk.subarray(0, 0) : chunk.subarray(0, nl + 1);
7133
+ const from = rows.length;
7134
+ for (const l of chunk.toString("utf8").split("\n")) {
7023
7135
  if (!l) continue;
7024
7136
  try {
7025
- added.push(JSON.parse(l));
7137
+ const r = JSON.parse(l);
7138
+ agg.add(r);
7139
+ rows.push(r);
7026
7140
  } catch {}
7027
7141
  }
7028
- if (added.length) rows = rows.concat(added);
7029
- offset += Buffer.byteLength(text.slice(0, end), "utf8");
7142
+ for (let i = from; i < rows.length; i++) {
7143
+ const t = Date.parse(rows[i].ts);
7144
+ if (t < lastMs) ordered = false;
7145
+ else if (t >= 0) lastMs = t;
7146
+ }
7147
+ if (!ordered) fresh([...rows]);
7148
+ const at = clock();
7149
+ if (at - lastTrim >= DAY$1) {
7150
+ lastTrim = at;
7151
+ agg.pruneDaily(bucketStart(at, DAY$1) - DAILY_KEPT_MS);
7152
+ fresh(rows.filter((r) => !(Date.parse(r.ts) < at - ROWS_KEPT_MS)));
7153
+ }
7154
+ offset += chunk.length;
7155
+ ino = st.ino;
7156
+ if (head.length < USAGE_HEAD_BYTES) head = nowHead.slice(0, Math.min(offset, USAGE_HEAD_BYTES));
7157
+ mtimeMs = st.mtimeMs;
7030
7158
  } finally {
7031
7159
  closeSync(fd);
7032
7160
  }
7033
- mtimeMs = st.mtimeMs;
7034
7161
  } catch {
7035
- rows = [];
7036
- offset = 0;
7162
+ reset();
7037
7163
  }
7038
7164
  return rows;
7039
7165
  };
@@ -7533,15 +7659,18 @@ function cachedPoolCarry() {
7533
7659
  /** The whole request body as text. */
7534
7660
  function readBody(req) {
7535
7661
  return new Promise((resolve, reject) => {
7536
- let data = "";
7662
+ const chunks = [];
7663
+ let size = 0;
7537
7664
  req.on("data", (c) => {
7538
- data += c;
7539
- if (data.length > 64e3) {
7665
+ const b = typeof c === "string" ? Buffer.from(c) : c;
7666
+ chunks.push(b);
7667
+ size += b.length;
7668
+ if (size > 64e3) {
7540
7669
  reject(/* @__PURE__ */ new Error("body too large"));
7541
7670
  req.destroy();
7542
7671
  }
7543
7672
  });
7544
- req.on("end", () => resolve(data));
7673
+ req.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
7545
7674
  req.on("error", reject);
7546
7675
  });
7547
7676
  }
@@ -7724,7 +7853,7 @@ function cockpitBuildId() {
7724
7853
  * unless router.bind opens a second listener (then every cockpit route,
7725
7854
  * writes included, is token-gated — see src/router/cockpit-auth.ts).
7726
7855
  */
7727
- function handleCockpit(req, res, limits, readRows = readUsageCached, sessionMap = loadSessionMap, system, workerWindows = loadWorkerWindows, readPool = cachedPoolCarry(), readPoolPanel = sharedPoolPanel, queueLogDir = workersLogDir) {
7856
+ function handleCockpit(req, res, limits, readRows = cachedRows(), sessionMap = loadSessionMap, system, workerWindows = loadWorkerWindows, readPool = cachedPoolCarry(), readPoolPanel = sharedPoolPanel, queueLogDir = workersLogDir) {
7728
7857
  const url = new URL(req.url ?? "/", "http://localhost");
7729
7858
  if (url.pathname !== "/cockpit" && !url.pathname.startsWith("/cockpit/")) return false;
7730
7859
  const send = (status, type, body) => {
@@ -8599,6 +8728,12 @@ function writeResults(suite, rows) {
8599
8728
  writeFileSync(file, `# A/B results\n\nGenerated by \`pai worker bench\`; void rows excluded from pass/total.\n\n${aggregate(rows)}\n`);
8600
8729
  return file;
8601
8730
  }
8731
+ /** A throttle setting must be a positive number: NaN would disable the gate, 0 would wait forever. */
8732
+ function positiveNumber(flag, v) {
8733
+ const n = typeof v === "number" ? v : typeof v === "string" && v.trim() !== "" ? Number(v) : NaN;
8734
+ if (!Number.isFinite(n) || n <= 0) throw new Error(`${flag} must be a positive number, got "${String(v)}"`);
8735
+ return n;
8736
+ }
8602
8737
 
8603
8738
  //#endregion
8604
8739
  //#region src/cli/lib/settings-manager.ts
@@ -9040,7 +9175,7 @@ function collectEnv(pairs) {
9040
9175
  return o;
9041
9176
  }
9042
9177
  function parseCostTier(v) {
9043
- const n = parseInt(v, 10);
9178
+ const n = /^\s*\d+\s*$/.test(v) ? Number(v) : NaN;
9044
9179
  if (!Number.isInteger(n) || n < 1 || n > 5) throw new WorkersConfigError(`cost tier must be an integer 1 (cheapest) … 5 (most expensive), got "${v}"`);
9045
9180
  return n;
9046
9181
  }
@@ -9138,7 +9273,7 @@ const providersAddCommand = {
9138
9273
  name: "key",
9139
9274
  type: "string",
9140
9275
  value: "TOKEN",
9141
- summary: "API token, written into workers.yaml; use instead of --key-file"
9276
+ summary: "API token, written into workers.yaml; visible in ps and shell history, prefer --key-file"
9142
9277
  },
9143
9278
  {
9144
9279
  name: "key-file",
@@ -9218,6 +9353,7 @@ const providersAddCommand = {
9218
9353
  const baseUrl = o["base-url"] ?? o.url;
9219
9354
  if (protocol !== "openai" && !baseUrl) throw new WorkersConfigError("--base-url (or --url) is required (only --protocol openai goes without it)");
9220
9355
  if (o.key && o["key-file"]) throw new WorkersConfigError("--key and --key-file are alternatives — pass one, not both");
9356
+ if (o.key) out(warn("--key puts the token in the process list and shell history; prefer --key-file"));
9221
9357
  const costTier = o["cost-tier"] !== void 0 ? parseCostTier(String(o["cost-tier"])) : void 0;
9222
9358
  const tags = collectTags(ctx.multi?.tags);
9223
9359
  addProvider({
@@ -9859,6 +9995,16 @@ function launchDetached(plan) {
9859
9995
  closeSync(fd);
9860
9996
  return Object.assign(() => child.exitCode, child.pid !== void 0 ? { pid: child.pid } : {});
9861
9997
  }
9998
+ /** SIGTERM a launched server's process group (it is a group leader), else the pid. */
9999
+ function killGroup(pid) {
10000
+ try {
10001
+ process.kill(-pid, "SIGTERM");
10002
+ } catch {
10003
+ try {
10004
+ process.kill(pid, "SIGTERM");
10005
+ } catch {}
10006
+ }
10007
+ }
9862
10008
  /** Live servers of catalogue models, one per (model, port). */
9863
10009
  function liveServers(cfg) {
9864
10010
  return instancesFromProcesses(psTable("pid=,rss=,command="), cfg, scriptListeners(cfg));
@@ -9875,6 +10021,36 @@ function currentInstances(cfg, deps = {}) {
9875
10021
  * instances keep running; a short memory or a full model (maxInstances) refuses.
9876
10022
  */
9877
10023
  async function startInstance(cfg, model, deps = {}) {
10024
+ return withStartLock(deps.startDir ?? logDir(), model, (release) => startInstanceLocked(cfg, model, deps, release));
10025
+ }
10026
+ /** One start per model at a time: the lock covers read-check-allocate-write and is released once the row is written. */
10027
+ async function withStartLock(dir, model, fn) {
10028
+ mkdirSync(dir, { recursive: true });
10029
+ const m = join(dir, `start-${model.replace(/[^\w.-]/g, "_")}.lock`);
10030
+ const t0 = Date.now();
10031
+ for (;;) try {
10032
+ mkdirSync(m);
10033
+ break;
10034
+ } catch {
10035
+ breakStaleMutex(m, 6e4);
10036
+ if (Date.now() - t0 > 12e4) throw new LocalTierError(`${model}: another start is in progress`);
10037
+ await sleep(10 + Math.random() * 20);
10038
+ }
10039
+ let released = false;
10040
+ const release = () => {
10041
+ if (released) return;
10042
+ released = true;
10043
+ try {
10044
+ rmdirSync(m);
10045
+ } catch {}
10046
+ };
10047
+ try {
10048
+ return await fn(release);
10049
+ } finally {
10050
+ release();
10051
+ }
10052
+ }
10053
+ async function startInstanceLocked(cfg, model, deps, release) {
9878
10054
  const tier = cfg.tiers[model];
9879
10055
  if (!tier) throw new LocalTierError(`no model "${model}" (configured: ${Object.keys(cfg.tiers).join(", ") || "none"})`);
9880
10056
  const dir = deps.startDir ?? logDir();
@@ -9925,10 +10101,12 @@ async function startInstance(cfg, model, deps = {}) {
9925
10101
  });
9926
10102
  writeInstances(dir, [...rows.filter((r) => r.id !== id), instance]);
9927
10103
  const exited = (deps.launch ?? launchDetached)(plan);
10104
+ release();
9928
10105
  out(dim(`starting ${tier.label} #${n} (${tier.provider}) on :${port}, log ${plan.logPath}`));
9929
10106
  const up = deps.up ?? ((p) => healthOk(tier, p));
9930
10107
  const deadline = Date.now() + plan.readyMs;
9931
10108
  const failWith = (error, msg) => {
10109
+ if (exited.pid !== void 0 && exited() === null) killGroup(exited.pid);
9932
10110
  failLocalStart(dir, error, id);
9933
10111
  writeInstances(dir, readInstances(dir).map((r) => r.id === id ? {
9934
10112
  ...r,
@@ -10086,6 +10264,25 @@ async function stopInstance(cfg, target, opts = {}, deps = {}) {
10086
10264
  }
10087
10265
  return picked;
10088
10266
  }
10267
+ /**
10268
+ * Requests in flight per instance id, from the snapshot the router mirrors to its log dir (the scheduler lives in
10269
+ * the router process, not here). A missing or unreadable snapshot cannot be checked: the lookup throws so
10270
+ * the stop is refused unless confirmed.
10271
+ */
10272
+ async function cliInflight(cfg, deps = {}) {
10273
+ const [{ engineInflight }, { readSchedFile }, { instanceEngineKey }] = await Promise.all([
10274
+ import("./cockpit-actions-DR9X514g.mjs"),
10275
+ import("./scheduler-dmHXoRvm.mjs"),
10276
+ import("./local-instances-ZeRkkuS5.mjs")
10277
+ ]);
10278
+ const now = deps.now ?? Date.now();
10279
+ const snap = readSchedFile(deps.startDir ?? logDir(), now);
10280
+ const keys = new Map(currentInstances(cfg, deps).map((r) => [r.id, instanceEngineKey(r)]));
10281
+ return (id) => {
10282
+ if (!snap) throw new LocalTierError(`${id}: in-flight requests could not be checked (no router snapshot); confirm to stop anyway (--yes)`);
10283
+ return engineInflight(snap, keys.get(id) ?? id);
10284
+ };
10285
+ }
10089
10286
  /** Stop every local server PAI knows (the instances, then anything left on a catalogue port), then wait until the ports are free. */
10090
10287
  async function stopAll(cfg) {
10091
10288
  for (const m of new Set(currentInstances(cfg).map((r) => r.model))) await stopInstance(cfg, m, { all: true }, { confirm: true });
@@ -10194,7 +10391,10 @@ const workerLocalCommand = {
10194
10391
  out(ok(`stopped ${(await stopInstance(cfg, name, {
10195
10392
  count,
10196
10393
  all: !!ctx.opts.all
10197
- }, { confirm: !!ctx.opts.yes })).map((d) => d.id).join(", ")}`));
10394
+ }, {
10395
+ confirm: !!ctx.opts.yes,
10396
+ inflight: await cliInflight(cfg)
10397
+ })).map((d) => d.id).join(", ")}`));
10198
10398
  return;
10199
10399
  }
10200
10400
  const tier = cfg.tiers[name];
@@ -10293,6 +10493,8 @@ const workerBenchCommand = {
10293
10493
  const tasks = o.tasks ? String(o.tasks).split(",") : all;
10294
10494
  const unknown = tasks.filter((t) => !all.includes(t));
10295
10495
  if (unknown.length) throw new Error(`unknown task(s): ${unknown.join(", ")}`);
10496
+ const maxParallel = positiveNumber("--max-parallel", o["max-parallel"]);
10497
+ const maxLoad = positiveNumber("--max-load", o["max-load"]);
10296
10498
  const arms = planArms(tasks, String(o.providers).split(","), prompt, Math.max(1, Number(o.repeat) || 1));
10297
10499
  out(`${arms.length} arm(s), prompt ${prompt}, max ${o["max-parallel"]} parallel, load gate ${o["max-load"]}`);
10298
10500
  if (ctx.dryRun) {
@@ -10302,8 +10504,8 @@ const workerBenchCommand = {
10302
10504
  const rows = await runBench({
10303
10505
  suite,
10304
10506
  arms,
10305
- maxParallel: Number(o["max-parallel"]),
10306
- maxLoad: Number(o["max-load"]),
10507
+ maxParallel,
10508
+ maxLoad,
10307
10509
  log: (s) => out(s)
10308
10510
  });
10309
10511
  out(aggregate(rows));
@@ -10489,7 +10691,7 @@ const workerPoolCommand = {
10489
10691
  async run(ctx) {
10490
10692
  try {
10491
10693
  const action = ctx.args.ACTION;
10492
- const { poolOn, poolOff, poolStatusText } = await import("./pool-cli-CbJfl37y.mjs");
10694
+ const { poolOn, poolOff, poolStatusText } = await import("./pool-cli-DQ6OzRy2.mjs");
10493
10695
  if (action === void 0 || action === "status") return void out(await poolStatusText(logDir()));
10494
10696
  if (action === "on") return void (await poolOn(logDir())).forEach((l) => out(l));
10495
10697
  if (action === "off") return void (await poolOff(logDir())).forEach((l) => out(l));
@@ -10665,5 +10867,5 @@ const WORKER_CONFIG_COMMANDS = [
10665
10867
  ];
10666
10868
 
10667
10869
  //#endregion
10668
- export { createEndpointHealth as $, workerOffCommand as A, allocatePort as B, workerClassesCommand as C, workerInstallCommand as D, workerFallbackCommand as E, workerProxyCommand as F, cachedSessionMap as G, sizeOnDiskGb as H, workerRolesCommand as I, setActionHooks as J, cachedWorkerWindows as K, workerRouteCommand as L, workerPolicyCommand as M, workerPoolCommand as N, workerLocalCommand as O, workerProvidersCommand as P, exportDefaultLayout as Q, installWorkers as R, workerBenchCommand as S, workerControlsCommand as T, SystemMonitor as U, canBind as V, cachedRows as W, setRuntimeSampler as X, setEndpointHealth as Y, warmCockpit as Z, serverLine as _, collectTags as a, hashText as at, stopAll as b, fail as c, killInstance as d, loadSessionMap as et, launchDetached as f, portOpen as g, portListeners as h, collectEnv as i, defaultRegistryCtx as it, workerOnCommand as j, workerMcpCommand as k, healthOk as l, parseCostTier as m, WORKER_CONFIG_COMMANDS as n, sessionDisplayName as nt, controlsArgv as o, saveRegistry as ot, listServers as p, handleCockpit as q, buildClassTarget as r, withWorkerAttribution as rt, currentInstances as s, providersCommand as st, PROVIDER_EDIT_COMMANDS as t, loadWorkerWindows as tt, isUp as u, startInstance as v, workerConfigCommand as w, stopInstance as x, startTier as y, mergeSettings as z };
10669
- //# sourceMappingURL=worker-config-BLqa1yiD.mjs.map
10870
+ export { exportDefaultLayout as $, workerMcpCommand as A, mergeSettings as B, workerBenchCommand as C, workerFallbackCommand as D, workerControlsCommand as E, workerProvidersCommand as F, cachedRows as G, canBind as H, workerProxyCommand as I, handleCockpit as J, cachedSessionMap as K, workerRolesCommand as L, workerOnCommand as M, workerPolicyCommand as N, workerInstallCommand as O, workerPoolCommand as P, warmCockpit as Q, workerRouteCommand as R, stopInstance as S, workerConfigCommand as T, sizeOnDiskGb as U, allocatePort as V, SystemMonitor as W, setEndpointHealth as X, setActionHooks as Y, setRuntimeSampler as Z, portOpen as _, collectEnv as a, defaultRegistryCtx as at, startTier as b, currentInstances as c, providersCommand as ct, isUp as d, createEndpointHealth as et, killInstance as f, portListeners as g, parseCostTier as h, cliInflight as i, withWorkerAttribution as it, workerOffCommand as j, workerLocalCommand as k, fail as l, listServers as m, WORKER_CONFIG_COMMANDS as n, loadWorkerWindows as nt, collectTags as o, hashText as ot, launchDetached as p, cachedWorkerWindows as q, buildClassTarget as r, sessionDisplayName as rt, controlsArgv as s, saveRegistry as st, PROVIDER_EDIT_COMMANDS as t, loadSessionMap as tt, healthOk as u, serverLine as v, workerClassesCommand as w, stopAll as x, startInstance as y, installWorkers as z };
10871
+ //# sourceMappingURL=worker-config-CJhEMk19.mjs.map