@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
@@ -9985,7 +9985,7 @@ var init_paths = __esm({
9985
9985
 
9986
9986
  // src/config/claude-json.ts
9987
9987
  import { homedir as homedir3 } from "node:os";
9988
- import { join as join8 } from "node:path";
9988
+ import { join as join8, resolve as resolve3 } from "node:path";
9989
9989
  function claudeJsonPath() {
9990
9990
  return join8(homedir3(), ".claude.json");
9991
9991
  }
@@ -10260,9 +10260,9 @@ function poolPort(config) {
10260
10260
  return config.pool?.port ?? DEFAULT_POOL_PORT;
10261
10261
  }
10262
10262
  function postTaskToPool(port2, task, timeoutMs, path = "/task", handover, handoverWaitMs = 2e4) {
10263
- return new Promise((resolve11) => {
10263
+ return new Promise((resolve12) => {
10264
10264
  let connected = false;
10265
- const fail = (detail) => resolve11({ error: connected ? "claim-error" : "unreachable", detail });
10265
+ const fail = (detail) => resolve12({ error: connected ? "claim-error" : "unreachable", detail });
10266
10266
  const body = JSON.stringify(task);
10267
10267
  const req = httpRequest(
10268
10268
  {
@@ -10279,7 +10279,7 @@ function postTaskToPool(port2, task, timeoutMs, path = "/task", handover, handov
10279
10279
  res.on("end", () => {
10280
10280
  try {
10281
10281
  const resp = JSON.parse(Buffer.concat(chunks).toString("utf8"));
10282
- resolve11(resp.pooled ? { ok: resp } : { miss: resp.reason ?? "refused" });
10282
+ resolve12(resp.pooled ? { ok: resp } : { miss: resp.reason ?? "refused" });
10283
10283
  } catch (e) {
10284
10284
  fail(`unreadable answer: ${e instanceof Error ? e.message : String(e)}`);
10285
10285
  }
@@ -10289,12 +10289,12 @@ function postTaskToPool(port2, task, timeoutMs, path = "/task", handover, handov
10289
10289
  );
10290
10290
  req.setTimeout(timeoutMs, () => {
10291
10291
  req.destroy();
10292
- resolve11({ error: "timeout", detail: `no answer within ${timeoutMs} ms` });
10292
+ resolve12({ error: "timeout", detail: `no answer within ${timeoutMs} ms` });
10293
10293
  });
10294
10294
  req.on("socket", (s) => s.on("connect", () => connected = true));
10295
10295
  req.on("error", (e) => {
10296
10296
  if (e.code === "ECONNREFUSED" && handover?.() && handoverWaitMs > 0) {
10297
- setTimeout(() => void postTaskToPool(port2, task, timeoutMs, path, handover, handoverWaitMs - 300).then(resolve11), 300);
10297
+ setTimeout(() => void postTaskToPool(port2, task, timeoutMs, path, handover, handoverWaitMs - 300).then(resolve12), 300);
10298
10298
  return;
10299
10299
  }
10300
10300
  fail(e.message);
@@ -10303,33 +10303,33 @@ function postTaskToPool(port2, task, timeoutMs, path = "/task", handover, handov
10303
10303
  });
10304
10304
  }
10305
10305
  function poolHostProbe(port2, timeoutMs = 500) {
10306
- return new Promise((resolve11) => {
10306
+ return new Promise((resolve12) => {
10307
10307
  const req = httpRequest({ host: LOOPBACK_HOST, port: port2, path: "/healthz", method: "GET", timeout: timeoutMs }, (res) => {
10308
10308
  res.resume();
10309
- res.on("end", () => resolve11(res.statusCode === 200 ? "up" : "down"));
10310
- res.on("error", () => resolve11("down"));
10309
+ res.on("end", () => resolve12(res.statusCode === 200 ? "up" : "down"));
10310
+ res.on("error", () => resolve12("down"));
10311
10311
  });
10312
10312
  req.on("timeout", () => {
10313
10313
  req.destroy();
10314
- resolve11("timeout");
10314
+ resolve12("timeout");
10315
10315
  });
10316
- req.on("error", () => resolve11("down"));
10316
+ req.on("error", () => resolve12("down"));
10317
10317
  req.end();
10318
10318
  });
10319
10319
  }
10320
10320
  function poolHostPid(port2, timeoutMs = 500) {
10321
- return new Promise((resolve11) => {
10321
+ return new Promise((resolve12) => {
10322
10322
  const req = httpRequest({ host: LOOPBACK_HOST, port: port2, path: "/healthz", method: "GET", timeout: timeoutMs }, (res) => {
10323
10323
  res.resume();
10324
10324
  const pid = parseInt(String(res.headers["x-pool-host-pid"] ?? ""), 10);
10325
- res.on("end", () => resolve11(res.statusCode === 200 ? Number.isFinite(pid) ? pid : 0 : null));
10326
- res.on("error", () => resolve11(null));
10325
+ res.on("end", () => resolve12(res.statusCode === 200 ? Number.isFinite(pid) ? pid : 0 : null));
10326
+ res.on("error", () => resolve12(null));
10327
10327
  });
10328
10328
  req.on("timeout", () => {
10329
10329
  req.destroy();
10330
- resolve11(null);
10330
+ resolve12(null);
10331
10331
  });
10332
- req.on("error", () => resolve11(null));
10332
+ req.on("error", () => resolve12(null));
10333
10333
  req.end();
10334
10334
  });
10335
10335
  }
@@ -10755,7 +10755,7 @@ var init_agentish = __esm({
10755
10755
  });
10756
10756
 
10757
10757
  // src/router/usage.ts
10758
- var usageLogFile, MAX_LINE, MAX_JSON, USAGE_CACHE_WINDOW_MS;
10758
+ var usageLogFile, MAX_LINE, MAX_JSON;
10759
10759
  var init_usage = __esm({
10760
10760
  "src/router/usage.ts"() {
10761
10761
  "use strict";
@@ -10763,7 +10763,23 @@ var init_usage = __esm({
10763
10763
  usageLogFile = () => paiHomePath("logs", "router-usage.jsonl");
10764
10764
  MAX_LINE = 256 * 1024;
10765
10765
  MAX_JSON = 4 * 1024 * 1024;
10766
- USAGE_CACHE_WINDOW_MS = 7 * 864e5;
10766
+ }
10767
+ });
10768
+
10769
+ // src/utils/min-max.ts
10770
+ function minOf(values) {
10771
+ let m = Infinity;
10772
+ for (const v of values) if (v < m) m = v;
10773
+ return m;
10774
+ }
10775
+ function maxOf(values) {
10776
+ let m = -Infinity;
10777
+ for (const v of values) if (v > m) m = v;
10778
+ return m;
10779
+ }
10780
+ var init_min_max = __esm({
10781
+ "src/utils/min-max.ts"() {
10782
+ "use strict";
10767
10783
  }
10768
10784
  });
10769
10785
 
@@ -10886,6 +10902,21 @@ function resolveToken() {
10886
10902
  }
10887
10903
  return process.env.FORGE_TOKEN || process.env.AIBROKER_FORGE_TOKEN || void 0;
10888
10904
  }
10905
+ function curlQuote(v) {
10906
+ if (/[\r\n]/.test(v)) throw new ForgeError("refusing newline in curl config value");
10907
+ return v.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
10908
+ }
10909
+ function buildCurlConfig(method, url, token, timeoutMs) {
10910
+ return [
10911
+ `url = "${curlQuote(url)}"`,
10912
+ `request = "${curlQuote(method)}"`,
10913
+ `header = "Authorization: token ${curlQuote(token)}"`,
10914
+ `header = "Content-Type: application/json"`,
10915
+ `max-time = ${Math.max(0.5, timeoutMs / 1e3)}`,
10916
+ `silent`,
10917
+ `write-out = "\\n%{http_code}"`
10918
+ ].join("\n");
10919
+ }
10889
10920
  function forgeClient(cwd, cfg, deps) {
10890
10921
  const token = deps.token ?? resolveToken();
10891
10922
  if (!token) throw new ForgeError("no forge token");
@@ -10970,15 +11001,7 @@ var init_forge_sink = __esm({
10970
11001
  ForgeError = class extends Error {
10971
11002
  };
10972
11003
  curlHttp = (method, url, token, body, timeoutMs) => {
10973
- const cfg = [
10974
- `url = "${url}"`,
10975
- `request = "${method}"`,
10976
- `header = "Authorization: token ${token}"`,
10977
- `header = "Content-Type: application/json"`,
10978
- `max-time = ${Math.max(0.5, timeoutMs / 1e3)}`,
10979
- `silent`,
10980
- `write-out = "\\n%{http_code}"`
10981
- ].join("\n");
11004
+ const cfg = buildCurlConfig(method, url, token, timeoutMs);
10982
11005
  const argv = body !== void 0 ? ["-K", "-", "--data-raw", body] : ["-K", "-"];
10983
11006
  const r = spawnSync("curl", argv, { input: cfg, encoding: "utf8", timeout: timeoutMs + 500, maxBuffer: 16 * 1024 * 1024 });
10984
11007
  if (r.error || r.status !== 0) throw new ForgeError(`curl failed (${r.error?.message ?? `exit ${r.status}`})`);
@@ -11260,7 +11283,7 @@ var init_wait_on = __esm({
11260
11283
  // src/workers/report.ts
11261
11284
  import { execFileSync as execFileSync7 } from "node:child_process";
11262
11285
  import { statSync as statSync5 } from "node:fs";
11263
- import { isAbsolute, relative, resolve as resolve3 } from "node:path";
11286
+ import { isAbsolute, relative, resolve as resolve4 } from "node:path";
11264
11287
  function ag2ReportBlock() {
11265
11288
  const spec = ag2Spec();
11266
11289
  return [
@@ -11423,7 +11446,7 @@ function verifyReportChanges(changed, cwd, startMs) {
11423
11446
  const raw = (ch.path ?? "").trim();
11424
11447
  if (!raw) continue;
11425
11448
  if (/^delete:/i.test(raw)) continue;
11426
- const abs = isAbsolute(raw) ? raw : resolve3(cwd, raw);
11449
+ const abs = isAbsolute(raw) ? raw : resolve4(cwd, raw);
11427
11450
  let mtimeMs;
11428
11451
  try {
11429
11452
  mtimeMs = statSync5(abs).mtimeMs;
@@ -11673,6 +11696,7 @@ var TOOL_ERRORS_FILE, CROSS_WORKER_WINDOW_MS, SAME_WORKER_WINDOW_MS, RESEND_MS,
11673
11696
  var init_tool_errors = __esm({
11674
11697
  "src/workers/tool-errors.ts"() {
11675
11698
  "use strict";
11699
+ init_min_max();
11676
11700
  init_heredoc();
11677
11701
  init_render_decision();
11678
11702
  init_wait();
@@ -12054,6 +12078,7 @@ var defaultDeps, ticketsDir, ticketFile;
12054
12078
  var init_queue = __esm({
12055
12079
  "src/builds/queue.ts"() {
12056
12080
  "use strict";
12081
+ init_min_max();
12057
12082
  init_pai_home();
12058
12083
  init_config4();
12059
12084
  defaultDeps = () => ({
@@ -12099,6 +12124,7 @@ var init_parking = __esm({
12099
12124
  var init_scheduler = __esm({
12100
12125
  "src/router/scheduler.ts"() {
12101
12126
  "use strict";
12127
+ init_min_max();
12102
12128
  }
12103
12129
  });
12104
12130
 
@@ -12463,6 +12489,7 @@ var localInstancesPath;
12463
12489
  var init_local_instances = __esm({
12464
12490
  "src/workers/local-instances.ts"() {
12465
12491
  "use strict";
12492
+ init_min_max();
12466
12493
  init_local_tiers();
12467
12494
  localInstancesPath = (logDir2) => join19(logDir2, "local-instances.json");
12468
12495
  }
@@ -12690,10 +12717,11 @@ var init_local_provider = __esm({
12690
12717
 
12691
12718
  // src/config/atomic-file.ts
12692
12719
  import { mkdirSync as mkdirSync14, renameSync as renameSync10, rmSync as rmSync4, writeFileSync as writeFileSync13 } from "node:fs";
12720
+ import { randomBytes } from "node:crypto";
12693
12721
  import { dirname as dirname13 } from "node:path";
12694
12722
  function writeFileAtomic(path, text) {
12695
12723
  mkdirSync14(dirname13(path), { recursive: true });
12696
- const tmp = `${path}.${process.pid}.tmp`;
12724
+ const tmp = `${path}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
12697
12725
  try {
12698
12726
  writeFileSync13(tmp, text, "utf8");
12699
12727
  renameSync10(tmp, path);
@@ -12839,14 +12867,14 @@ function anthropicUsageUrl() {
12839
12867
  return new URL("/api/oauth/usage", loadConfig().router.claudeUpstream);
12840
12868
  }
12841
12869
  function getJson(url, headers, timeoutMs = 5e3) {
12842
- return new Promise((resolve11, reject) => {
12870
+ return new Promise((resolve12, reject) => {
12843
12871
  const mod = url.protocol === "https:" ? https : http;
12844
12872
  const rq = mod.get(url, { headers, timeout: timeoutMs }, (res) => {
12845
12873
  let t = "";
12846
12874
  res.on("data", (c) => t += c);
12847
12875
  res.on(
12848
12876
  "end",
12849
- () => res.statusCode === 200 ? resolve11(t) : reject(new HttpError(res.statusCode ?? 0, res.statusCode === 429 ? parseRetryAfter(res.headers["retry-after"]) : void 0))
12877
+ () => res.statusCode === 200 ? resolve12(t) : reject(new HttpError(res.statusCode ?? 0, res.statusCode === 429 ? parseRetryAfter(res.headers["retry-after"]) : void 0))
12850
12878
  );
12851
12879
  });
12852
12880
  rq.on("timeout", () => rq.destroy(new Error("timeout")));
@@ -12854,7 +12882,7 @@ function getJson(url, headers, timeoutMs = 5e3) {
12854
12882
  });
12855
12883
  }
12856
12884
  function sh(cmd, args) {
12857
- return new Promise((resolve11) => execFile(cmd, args, { timeout: 4e3 }, (_e, out) => resolve11(String(out ?? "").trim())));
12885
+ return new Promise((resolve12) => execFile(cmd, args, { timeout: 4e3 }, (_e, out) => resolve12(String(out ?? "").trim())));
12858
12886
  }
12859
12887
  async function anthropicToken() {
12860
12888
  for (const args of [["-a", process.env.USER ?? ""], []]) {
@@ -15102,7 +15130,7 @@ var require_utils_webcrypto = __commonJS({
15102
15130
  var nodeCrypto = __require("crypto");
15103
15131
  module.exports = {
15104
15132
  postgresMd5PasswordHash,
15105
- randomBytes: randomBytes2,
15133
+ randomBytes: randomBytes3,
15106
15134
  deriveKey,
15107
15135
  sha256: sha2562,
15108
15136
  hashByName,
@@ -15112,7 +15140,7 @@ var require_utils_webcrypto = __commonJS({
15112
15140
  var webCrypto = nodeCrypto.webcrypto || globalThis.crypto;
15113
15141
  var subtleCrypto = webCrypto.subtle;
15114
15142
  var textEncoder = new TextEncoder();
15115
- function randomBytes2(length) {
15143
+ function randomBytes3(length) {
15116
15144
  return webCrypto.getRandomValues(Buffer.alloc(length));
15117
15145
  }
15118
15146
  async function md5(string) {
@@ -16937,7 +16965,7 @@ var require_dist2 = __commonJS({
16937
16965
  function parse4(stream, callback) {
16938
16966
  const parser = new parser_1.Parser();
16939
16967
  stream.on("data", (buffer) => parser.parse(buffer, callback));
16940
- return new Promise((resolve11) => stream.on("end", () => resolve11()));
16968
+ return new Promise((resolve12) => stream.on("end", () => resolve12()));
16941
16969
  }
16942
16970
  exports.parse = parse4;
16943
16971
  }
@@ -17664,12 +17692,12 @@ var require_client = __commonJS({
17664
17692
  this._connect(callback);
17665
17693
  return;
17666
17694
  }
17667
- return new this._Promise((resolve11, reject) => {
17695
+ return new this._Promise((resolve12, reject) => {
17668
17696
  this._connect((error) => {
17669
17697
  if (error) {
17670
17698
  reject(error);
17671
17699
  } else {
17672
- resolve11(this);
17700
+ resolve12(this);
17673
17701
  }
17674
17702
  });
17675
17703
  });
@@ -18011,8 +18039,8 @@ var require_client = __commonJS({
18011
18039
  readTimeout = config.query_timeout || this.connectionParameters.query_timeout;
18012
18040
  query = new Query2(config, values, callback);
18013
18041
  if (!query.callback) {
18014
- result = new this._Promise((resolve11, reject) => {
18015
- query.callback = (err, res) => err ? reject(err) : resolve11(res);
18042
+ result = new this._Promise((resolve12, reject) => {
18043
+ query.callback = (err, res) => err ? reject(err) : resolve12(res);
18016
18044
  }).catch((err) => {
18017
18045
  Error.captureStackTrace(err);
18018
18046
  throw err;
@@ -18085,8 +18113,8 @@ var require_client = __commonJS({
18085
18113
  if (cb) {
18086
18114
  this.connection.once("end", cb);
18087
18115
  } else {
18088
- return new this._Promise((resolve11) => {
18089
- this.connection.once("end", resolve11);
18116
+ return new this._Promise((resolve12) => {
18117
+ this.connection.once("end", resolve12);
18090
18118
  });
18091
18119
  }
18092
18120
  }
@@ -18135,8 +18163,8 @@ var require_pg_pool = __commonJS({
18135
18163
  const cb = function(err, client) {
18136
18164
  err ? rej(err) : res(client);
18137
18165
  };
18138
- const result = new Promise2(function(resolve11, reject) {
18139
- res = resolve11;
18166
+ const result = new Promise2(function(resolve12, reject) {
18167
+ res = resolve12;
18140
18168
  rej = reject;
18141
18169
  }).catch((err) => {
18142
18170
  Error.captureStackTrace(err);
@@ -18557,8 +18585,8 @@ var require_query2 = __commonJS({
18557
18585
  NativeQuery.prototype._getPromise = function() {
18558
18586
  if (this._promise) return this._promise;
18559
18587
  this._promise = new Promise(
18560
- function(resolve11, reject) {
18561
- this._once("end", resolve11);
18588
+ function(resolve12, reject) {
18589
+ this._once("end", resolve12);
18562
18590
  this._once("error", reject);
18563
18591
  }.bind(this)
18564
18592
  );
@@ -18730,12 +18758,12 @@ var require_client2 = __commonJS({
18730
18758
  this._connect(callback);
18731
18759
  return;
18732
18760
  }
18733
- return new this._Promise((resolve11, reject) => {
18761
+ return new this._Promise((resolve12, reject) => {
18734
18762
  this._connect((error) => {
18735
18763
  if (error) {
18736
18764
  reject(error);
18737
18765
  } else {
18738
- resolve11(this);
18766
+ resolve12(this);
18739
18767
  }
18740
18768
  });
18741
18769
  });
@@ -18759,8 +18787,8 @@ var require_client2 = __commonJS({
18759
18787
  query = new NativeQuery(config, values, callback);
18760
18788
  if (!query.callback) {
18761
18789
  let resolveOut, rejectOut;
18762
- result = new this._Promise((resolve11, reject) => {
18763
- resolveOut = resolve11;
18790
+ result = new this._Promise((resolve12, reject) => {
18791
+ resolveOut = resolve12;
18764
18792
  rejectOut = reject;
18765
18793
  }).catch((err) => {
18766
18794
  Error.captureStackTrace(err);
@@ -18816,8 +18844,8 @@ var require_client2 = __commonJS({
18816
18844
  }
18817
18845
  let result;
18818
18846
  if (!cb) {
18819
- result = new this._Promise(function(resolve11, reject) {
18820
- cb = (err) => err ? reject(err) : resolve11();
18847
+ result = new this._Promise(function(resolve12, reject) {
18848
+ cb = (err) => err ? reject(err) : resolve12();
18821
18849
  });
18822
18850
  }
18823
18851
  this.native.end(function() {
@@ -19345,12 +19373,11 @@ function bufferToVector(buf) {
19345
19373
  return floats;
19346
19374
  }
19347
19375
  function buildPgTsQuery(query) {
19348
- const tokens = query.toLowerCase().split(/[\s\p{P}]+/u).filter(Boolean).filter((t) => t.length >= 2).filter((t) => !STOP_WORDS.has(t)).map((t) => t.replace(/'/g, "''").replace(/[&|!():]/g, "")).filter(Boolean);
19349
- if (tokens.length === 0) {
19350
- const raw = query.replace(/[^a-z0-9]/gi, " ").trim().split(/\s+/).filter(Boolean).join(" | ");
19351
- return raw || "";
19352
- }
19353
- return tokens.join(" | ");
19376
+ const words = query.toLowerCase().match(/[\p{L}\p{N}_]+/gu) ?? [];
19377
+ const long = words.filter((t) => t.length >= 2);
19378
+ const tokens = long.filter((t) => !STOP_WORDS.has(t));
19379
+ const chosen = tokens.length > 0 ? tokens : long;
19380
+ return chosen.map((t) => `'${t}'`).join(" | ");
19354
19381
  }
19355
19382
  var init_helpers = __esm({
19356
19383
  "src/storage/postgres/helpers.ts"() {
@@ -19392,6 +19419,7 @@ async function searchKeyword(pool, query, opts) {
19392
19419
  const limitParam = `$${paramIdx}`;
19393
19420
  const sql = `
19394
19421
  SELECT
19422
+ id,
19395
19423
  project_id,
19396
19424
  path,
19397
19425
  start_line,
@@ -19399,6 +19427,8 @@ async function searchKeyword(pool, query, opts) {
19399
19427
  text AS snippet,
19400
19428
  tier,
19401
19429
  source,
19430
+ updated_at,
19431
+ last_accessed_at,
19402
19432
  ts_rank(fts_vector, to_tsquery('simple', $1)) AS rank_score
19403
19433
  FROM pai_chunks
19404
19434
  WHERE ${conditions.join(" AND ")}
@@ -19407,7 +19437,9 @@ async function searchKeyword(pool, query, opts) {
19407
19437
  `;
19408
19438
  try {
19409
19439
  const result = await pool.query(sql, params);
19440
+ const minScore = opts?.minScore ?? 0;
19410
19441
  return result.rows.map((row) => ({
19442
+ chunkId: row.id,
19411
19443
  projectId: row.project_id,
19412
19444
  path: row.path,
19413
19445
  startLine: row.start_line,
@@ -19415,8 +19447,10 @@ async function searchKeyword(pool, query, opts) {
19415
19447
  snippet: row.snippet,
19416
19448
  score: row.rank_score,
19417
19449
  tier: row.tier,
19418
- source: row.source
19419
- }));
19450
+ source: row.source,
19451
+ updatedAt: Number(row.updated_at),
19452
+ lastAccessedAt: row.last_accessed_at != null ? Number(row.last_accessed_at) : void 0
19453
+ })).filter((r) => r.score >= minScore);
19420
19454
  } catch (e) {
19421
19455
  process.stderr.write(`[pai-postgres] searchKeyword error: ${e}
19422
19456
  `);
@@ -20060,7 +20094,7 @@ function splitBySections(lines) {
20060
20094
  const splitAt = new Set(headings.filter((h) => h.level <= 3).map((h) => h.line));
20061
20095
  const flush = () => {
20062
20096
  const text = current2.map((l) => l.text).join("\n");
20063
- sections.push({ lines: current2, tokens: estimateTokens(text), headingPath: currentPath });
20097
+ sections.push({ lines: current2, tokens: sizeOf(text), headingPath: currentPath });
20064
20098
  current2 = [];
20065
20099
  };
20066
20100
  for (const line of lines) {
@@ -20079,7 +20113,7 @@ function splitByParagraphs(block) {
20079
20113
  for (const line of block.lines) {
20080
20114
  if (line.text.trim() === "" && current2.length > 0) {
20081
20115
  const text = current2.map((l) => l.text).join("\n");
20082
- paragraphs.push({ lines: [...current2], tokens: estimateTokens(text), headingPath: block.headingPath });
20116
+ paragraphs.push({ lines: [...current2], tokens: sizeOf(text), headingPath: block.headingPath });
20083
20117
  current2 = [];
20084
20118
  } else {
20085
20119
  current2.push(line);
@@ -20087,44 +20121,68 @@ function splitByParagraphs(block) {
20087
20121
  }
20088
20122
  if (current2.length > 0) {
20089
20123
  const text = current2.map((l) => l.text).join("\n");
20090
- paragraphs.push({ lines: current2, tokens: estimateTokens(text), headingPath: block.headingPath });
20124
+ paragraphs.push({ lines: current2, tokens: sizeOf(text), headingPath: block.headingPath });
20091
20125
  }
20092
20126
  return paragraphs.length > 0 ? paragraphs : [block];
20093
20127
  }
20094
- function splitBySentences(block, maxTokens) {
20095
- const fullText = block.lines.map((l) => l.text).join(" ");
20096
- const sentenceRe = /(?<=[.!?])\s+(?=[A-Z"'])/g;
20097
- const sentences = fullText.split(sentenceRe);
20128
+ function sizeOf(text) {
20129
+ return Math.max(estimateTokens(text), Math.ceil(text.length / MAX_CHARS_PER_TOKEN));
20130
+ }
20131
+ function splitLine(text, lineNo, budget) {
20132
+ if (sizeOf(text) <= budget) return [{ text, lineNo, join: "" }];
20133
+ const maxChars = budget * MAX_CHARS_PER_TOKEN;
20134
+ const pieces = [];
20135
+ const push = (t, join58) => {
20136
+ if (t) pieces.push({ text: t, lineNo, join: join58 });
20137
+ };
20138
+ let acc = "";
20139
+ const emit = () => {
20140
+ push(acc, pieces.length > 0 ? " " : "");
20141
+ acc = "";
20142
+ };
20143
+ const addWord = (word) => {
20144
+ if (acc && sizeOf(acc + " " + word) > budget) emit();
20145
+ if (sizeOf(word) > budget) {
20146
+ if (acc) emit();
20147
+ for (let i = 0; i < word.length; i += maxChars) {
20148
+ push(word.slice(i, i + maxChars), i === 0 ? pieces.length > 0 ? " " : "" : "");
20149
+ }
20150
+ return;
20151
+ }
20152
+ acc = acc ? acc + " " + word : word;
20153
+ };
20154
+ for (const sentence of text.split(/(?<=[.!?])\s+(?=[A-Z"'])/)) {
20155
+ if (acc && sizeOf(acc + " " + sentence) > budget) emit();
20156
+ if (sizeOf(sentence) <= budget) {
20157
+ acc = acc ? acc + " " + sentence : sentence;
20158
+ } else {
20159
+ for (const word of sentence.split(/\s+/).filter(Boolean)) addWord(word);
20160
+ }
20161
+ }
20162
+ emit();
20163
+ return pieces;
20164
+ }
20165
+ function splitOversized(block, budget) {
20098
20166
  const result = [];
20099
- let accText = "";
20100
- const startLine = block.lines[0]?.lineNo ?? 1;
20101
- const endLine = block.lines[block.lines.length - 1]?.lineNo ?? startLine;
20102
- const totalLines = endLine - startLine + 1;
20103
- const linesPerSentence = Math.max(1, Math.floor(totalLines / Math.max(1, sentences.length)));
20104
- let sentenceIdx = 0;
20105
- let approxLine = startLine;
20167
+ let cur = [];
20168
+ let curText = "";
20106
20169
  const flush = () => {
20107
- if (!accText.trim()) return;
20108
- const endApprox = Math.min(approxLine + linesPerSentence - 1, endLine);
20109
- result.push({
20110
- lines: [{ text: accText.trim(), lineNo: approxLine }],
20111
- tokens: estimateTokens(accText),
20112
- headingPath: block.headingPath
20113
- });
20114
- approxLine = endApprox + 1;
20115
- accText = "";
20170
+ if (cur.length > 0) result.push({ lines: cur, tokens: sizeOf(curText), headingPath: block.headingPath });
20171
+ cur = [];
20172
+ curText = "";
20116
20173
  };
20117
- for (const sentence of sentences) {
20118
- sentenceIdx++;
20119
- const candidateText = accText ? accText + " " + sentence : sentence;
20120
- if (estimateTokens(candidateText) > maxTokens && accText) {
20121
- flush();
20122
- accText = sentence;
20123
- } else {
20124
- accText = candidateText;
20174
+ const add = (piece, sep4) => {
20175
+ const last = cur[cur.length - 1];
20176
+ if (last && piece.join && last.lineNo === piece.lineNo) last.text += piece.join + piece.text;
20177
+ else cur.push({ text: piece.text, lineNo: piece.lineNo });
20178
+ curText += (curText ? sep4 : "") + piece.text;
20179
+ };
20180
+ for (const line of block.lines) {
20181
+ for (const piece of splitLine(line.text, line.lineNo, budget)) {
20182
+ if (cur.length > 0 && sizeOf(curText + "\n" + piece.text) > budget) flush();
20183
+ add(piece, piece.join ? piece.join : "\n");
20125
20184
  }
20126
20185
  }
20127
- void sentenceIdx;
20128
20186
  flush();
20129
20187
  return result.length > 0 ? result : [block];
20130
20188
  }
@@ -20143,7 +20201,8 @@ function buildOverlapPrefix(lastChunk, overlapTokens) {
20143
20201
  return kept.map((text, idx) => ({ text, lineNo: Math.max(lastChunk.startLine, startLine + idx) }));
20144
20202
  }
20145
20203
  function stripPrivateTags(content) {
20146
- return content.replace(/<private>[\s\S]*?<\/private>/gi, "");
20204
+ const blank = (m) => m.replace(/[^\n]/g, "");
20205
+ return content.replace(/<private>[\s\S]*?<\/private>/gi, blank).replace(/<private>[\s\S]*$/i, blank);
20147
20206
  }
20148
20207
  function breadcrumb(path) {
20149
20208
  return path.length > 0 ? `[${path.join(" > ")}]
@@ -20163,7 +20222,7 @@ function chunkMarkdown(content, opts) {
20163
20222
  const sections = splitBySections(lines);
20164
20223
  const finalBlocks = [];
20165
20224
  for (const section of sections) {
20166
- const budget = Math.max(1, maxTokens - estimateTokens(breadcrumb(section.headingPath)));
20225
+ const budget = Math.max(1, maxTokens - sizeOf(breadcrumb(section.headingPath)));
20167
20226
  if (section.tokens <= budget) {
20168
20227
  finalBlocks.push(section);
20169
20228
  continue;
@@ -20174,8 +20233,7 @@ function chunkMarkdown(content, opts) {
20174
20233
  finalBlocks.push(para);
20175
20234
  continue;
20176
20235
  }
20177
- const sentences = splitBySentences(para, budget);
20178
- finalBlocks.push(...sentences);
20236
+ finalBlocks.push(...splitOversized(para, budget));
20179
20237
  }
20180
20238
  }
20181
20239
  const chunks = [];
@@ -20200,7 +20258,7 @@ function chunkMarkdown(content, opts) {
20200
20258
  }
20201
20259
  return chunks;
20202
20260
  }
20203
- var CHUNKER_VERSION, DEFAULT_MAX_TOKENS, DEFAULT_OVERLAP;
20261
+ var CHUNKER_VERSION, DEFAULT_MAX_TOKENS, DEFAULT_OVERLAP, MAX_CHARS_PER_TOKEN;
20204
20262
  var init_chunker = __esm({
20205
20263
  "src/memory/chunker.ts"() {
20206
20264
  "use strict";
@@ -20208,6 +20266,7 @@ var init_chunker = __esm({
20208
20266
  CHUNKER_VERSION = 2;
20209
20267
  DEFAULT_MAX_TOKENS = 400;
20210
20268
  DEFAULT_OVERLAP = 80;
20269
+ MAX_CHARS_PER_TOKEN = 6;
20211
20270
  }
20212
20271
  });
20213
20272
 
@@ -20235,7 +20294,7 @@ function chunkId(projectId, path, chunkIndex, startLine, endLine) {
20235
20294
  return createHash4("sha256").update(`${projectId}:${path}:${chunkIndex}:${startLine}:${endLine}`).digest("hex");
20236
20295
  }
20237
20296
  function yieldToEventLoop() {
20238
- return new Promise((resolve11) => setTimeout(resolve11, 10));
20297
+ return new Promise((resolve12) => setTimeout(resolve12, 10));
20239
20298
  }
20240
20299
  function walkMdFiles(dir, acc, cap = MAX_FILES_PER_PROJECT, depth = 0) {
20241
20300
  const results = acc ?? [];
@@ -20381,8 +20440,9 @@ var init_retry = __esm({
20381
20440
  // src/memory/indexer/async.ts
20382
20441
  import { readFileSync as readFileSync29, statSync as statSync8, existsSync as existsSync29 } from "node:fs";
20383
20442
  import { join as join26, relative as relative2, basename as basename4 } from "node:path";
20384
- async function indexFileWithBackend(backend, projectId, rootPath, relativePath, source, tier) {
20443
+ async function indexFileWithBackend(backend, projectId, rootPath, relativePath, source, tier, pathPrefix = "") {
20385
20444
  const absPath = join26(rootPath, relativePath);
20445
+ const dbPath = pathPrefix + relativePath;
20386
20446
  let content;
20387
20447
  let stat;
20388
20448
  try {
@@ -20394,17 +20454,17 @@ async function indexFileWithBackend(backend, projectId, rootPath, relativePath,
20394
20454
  const hash = fileContentHash(content);
20395
20455
  const mtime = Math.floor(stat.mtimeMs);
20396
20456
  const size = stat.size;
20397
- const existingHash = await backend.getFileHash(projectId, relativePath);
20457
+ const existingHash = await backend.getFileHash(projectId, dbPath);
20398
20458
  if (existingHash === hash) return false;
20399
- await backend.deleteChunksForFile(projectId, relativePath);
20459
+ await backend.deleteChunksForFile(projectId, dbPath);
20400
20460
  const rawChunks = chunkMarkdown(content);
20401
20461
  const updatedAt = Date.now();
20402
20462
  const chunks = rawChunks.map((c, i) => ({
20403
- id: chunkId(projectId, relativePath, i, c.startLine, c.endLine),
20463
+ id: chunkId(projectId, dbPath, i, c.startLine, c.endLine),
20404
20464
  projectId,
20405
20465
  source,
20406
20466
  tier,
20407
- path: relativePath,
20467
+ path: dbPath,
20408
20468
  startLine: c.startLine,
20409
20469
  endLine: c.endLine,
20410
20470
  hash: c.hash,
@@ -20413,7 +20473,7 @@ async function indexFileWithBackend(backend, projectId, rootPath, relativePath,
20413
20473
  embedding: null
20414
20474
  }));
20415
20475
  await backend.insertChunks(chunks);
20416
- await backend.upsertFile({ projectId, path: relativePath, source, tier, hash, mtime, size });
20476
+ await backend.upsertFile({ projectId, path: dbPath, source, tier, hash, mtime, size });
20417
20477
  return true;
20418
20478
  }
20419
20479
  async function indexProjectWithBackend(backend, projectId, rootPath, claudeNotesDir) {
@@ -20457,6 +20517,7 @@ async function indexProjectWithBackend(backend, projectId, rootPath, claudeNotes
20457
20517
  embedding: null
20458
20518
  };
20459
20519
  try {
20520
+ if ((await backend.getChunkIds(projectId, syntheticPath)).length > 0) continue;
20460
20521
  await backend.insertChunks([titleChunk]);
20461
20522
  } catch {
20462
20523
  }
@@ -20495,6 +20556,7 @@ async function indexProjectWithBackend(backend, projectId, rootPath, claudeNotes
20495
20556
  embedding: null
20496
20557
  };
20497
20558
  try {
20559
+ if ((await backend.getChunkIds(projectId, syntheticPath)).length > 0) continue;
20498
20560
  await backend.insertChunks([titleChunk]);
20499
20561
  } catch {
20500
20562
  }
@@ -20504,19 +20566,19 @@ async function indexProjectWithBackend(backend, projectId, rootPath, claudeNotes
20504
20566
  const claudeProjectDir = claudeNotesDir.slice(0, -"/Notes".length);
20505
20567
  const claudeMemoryMd = join26(claudeProjectDir, "MEMORY.md");
20506
20568
  if (existsSync29(claudeMemoryMd)) {
20507
- filesToIndex.push({ absPath: claudeMemoryMd, rootBase: claudeProjectDir, source: "memory", tier: "evergreen" });
20569
+ filesToIndex.push({ absPath: claudeMemoryMd, rootBase: claudeProjectDir, source: "memory", tier: "evergreen", pathPrefix: CLAUDE_MEMORY_PREFIX });
20508
20570
  }
20509
20571
  const claudeMemoryDir = join26(claudeProjectDir, "memory");
20510
20572
  for (const absPath of walkMdFiles(claudeMemoryDir)) {
20511
20573
  const relPath = relative2(claudeProjectDir, absPath);
20512
20574
  const tier = detectTier(relPath);
20513
- filesToIndex.push({ absPath, rootBase: claudeProjectDir, source: "memory", tier });
20575
+ filesToIndex.push({ absPath, rootBase: claudeProjectDir, source: "memory", tier, pathPrefix: CLAUDE_MEMORY_PREFIX });
20514
20576
  }
20515
20577
  }
20516
20578
  }
20517
20579
  await yieldToEventLoop();
20518
20580
  let filesSinceYield = 0;
20519
- for (const { absPath, rootBase, source, tier } of filesToIndex) {
20581
+ for (const { absPath, rootBase, source, tier, pathPrefix = "" } of filesToIndex) {
20520
20582
  if (filesSinceYield >= INDEX_YIELD_EVERY) {
20521
20583
  await yieldToEventLoop();
20522
20584
  filesSinceYield = 0;
@@ -20524,9 +20586,9 @@ async function indexProjectWithBackend(backend, projectId, rootPath, claudeNotes
20524
20586
  filesSinceYield++;
20525
20587
  const relPath = relative2(rootBase, absPath);
20526
20588
  try {
20527
- const changed = await indexFileWithBackend(backend, projectId, rootBase, relPath, source, tier);
20589
+ const changed = await indexFileWithBackend(backend, projectId, rootBase, relPath, source, tier, pathPrefix);
20528
20590
  if (changed) {
20529
- const ids = await backend.getChunkIds(projectId, relPath);
20591
+ const ids = await backend.getChunkIds(projectId, pathPrefix + relPath);
20530
20592
  result.filesProcessed++;
20531
20593
  result.chunksCreated += ids.length;
20532
20594
  } else {
@@ -20537,8 +20599,8 @@ async function indexProjectWithBackend(backend, projectId, rootPath, claudeNotes
20537
20599
  }
20538
20600
  }
20539
20601
  const livePaths = /* @__PURE__ */ new Set();
20540
- for (const { absPath, rootBase } of filesToIndex) {
20541
- livePaths.add(relative2(rootBase, absPath));
20602
+ for (const { absPath, rootBase, pathPrefix = "" } of filesToIndex) {
20603
+ livePaths.add(pathPrefix + relative2(rootBase, absPath));
20542
20604
  }
20543
20605
  const dbChunkPaths = await backend.getDistinctChunkPaths(projectId);
20544
20606
  const stalePaths = [];
@@ -20565,6 +20627,7 @@ async function indexAllWithBackend(backend, registry) {
20565
20627
  }
20566
20628
  return { projects: projects.length, result: totals };
20567
20629
  }
20630
+ var CLAUDE_MEMORY_PREFIX;
20568
20631
  var init_async = __esm({
20569
20632
  "src/memory/indexer/async.ts"() {
20570
20633
  "use strict";
@@ -20573,6 +20636,7 @@ var init_async = __esm({
20573
20636
  init_chunker();
20574
20637
  init_helpers2();
20575
20638
  init_retry();
20639
+ CLAUDE_MEMORY_PREFIX = ".claude-memory/";
20576
20640
  }
20577
20641
  });
20578
20642
 
@@ -21581,6 +21645,7 @@ var init_backend = __esm({
21581
21645
  async insertChunks(chunks) {
21582
21646
  if (chunks.length === 0) return;
21583
21647
  const client = await this.pool.connect();
21648
+ let releaseErr;
21584
21649
  try {
21585
21650
  await client.query("BEGIN");
21586
21651
  for (const c of chunks) {
@@ -21618,10 +21683,14 @@ var init_backend = __esm({
21618
21683
  }
21619
21684
  await client.query("COMMIT");
21620
21685
  } catch (e) {
21621
- await client.query("ROLLBACK");
21686
+ try {
21687
+ await client.query("ROLLBACK");
21688
+ } catch (rollbackErr) {
21689
+ releaseErr = rollbackErr instanceof Error ? rollbackErr : new Error(String(rollbackErr));
21690
+ }
21622
21691
  throw e;
21623
21692
  } finally {
21624
- client.release();
21693
+ client.release(releaseErr);
21625
21694
  }
21626
21695
  }
21627
21696
  async getDistinctChunkPaths(projectId) {
@@ -22090,7 +22159,7 @@ var init_ntfy = __esm({
22090
22159
  "Content-Type": "text/plain; charset=utf-8"
22091
22160
  };
22092
22161
  if (payload.title) {
22093
- headers["Title"] = payload.title;
22162
+ headers["Title"] = /^[\x20-\x7e]*$/.test(payload.title) ? payload.title : `=?UTF-8?B?${Buffer.from(payload.title, "utf8").toString("base64")}?=`;
22094
22163
  }
22095
22164
  if (cfg.priority && cfg.priority !== "default") {
22096
22165
  headers["Priority"] = cfg.priority;
@@ -22113,7 +22182,7 @@ var init_ntfy = __esm({
22113
22182
  import { connect } from "node:net";
22114
22183
  import { randomUUID } from "node:crypto";
22115
22184
  function callHub(method, params) {
22116
- return new Promise((resolve11) => {
22185
+ return new Promise((resolve12) => {
22117
22186
  let done = false;
22118
22187
  let buffer = "";
22119
22188
  let timer = null;
@@ -22128,7 +22197,7 @@ function callHub(method, params) {
22128
22197
  socket?.destroy();
22129
22198
  } catch {
22130
22199
  }
22131
- resolve11(ok);
22200
+ resolve12(ok);
22132
22201
  }
22133
22202
  const socket = connect(hubSocket(), () => {
22134
22203
  const request = {
@@ -22197,17 +22266,25 @@ var init_macos = __esm({
22197
22266
  if (process.platform !== "darwin") return false;
22198
22267
  try {
22199
22268
  const title = payload.title ?? "PAI";
22200
- const safeTitle = title.replace(/'/g, "\\'");
22201
- const safeMessage = payload.message.replace(/'/g, "\\'");
22202
- const script = `display notification "${safeMessage}" with title "${safeTitle}"`;
22203
- return new Promise((resolve11) => {
22204
- const child = spawn("osascript", ["-e", script], {
22269
+ const args = [
22270
+ "-e",
22271
+ "on run argv",
22272
+ "-e",
22273
+ "display notification (item 1 of argv) with title (item 2 of argv)",
22274
+ "-e",
22275
+ "end run",
22276
+ "--",
22277
+ payload.message,
22278
+ title
22279
+ ];
22280
+ return new Promise((resolve12) => {
22281
+ const child = spawn("osascript", args, {
22205
22282
  detached: true,
22206
22283
  stdio: "ignore"
22207
22284
  });
22208
22285
  child.unref();
22209
- child.on("error", () => resolve11(false));
22210
- setTimeout(() => resolve11(true), 200);
22286
+ child.on("error", () => resolve12(false));
22287
+ setTimeout(() => resolve12(true), 200);
22211
22288
  });
22212
22289
  } catch {
22213
22290
  return false;
@@ -22725,13 +22802,13 @@ var require_backup = __commonJS({
22725
22802
  var runBackup = (backup, handler) => {
22726
22803
  let rate = 0;
22727
22804
  let useDefault = true;
22728
- return new Promise((resolve11, reject) => {
22805
+ return new Promise((resolve12, reject) => {
22729
22806
  setImmediate(function step() {
22730
22807
  try {
22731
22808
  const progress = backup.transfer(rate);
22732
22809
  if (!progress.remainingPages) {
22733
22810
  backup.close();
22734
- resolve11(progress);
22811
+ resolve12(progress);
22735
22812
  return;
22736
22813
  }
22737
22814
  if (useDefault) {
@@ -23538,8 +23615,8 @@ async function findTunnelsForSlugMap2(db, slugMap, opts) {
23538
23615
  const totalOccurrences = rows.reduce((s, r) => s + Number(r.cnt), 0);
23539
23616
  if (totalOccurrences < opts.min_occurrences) continue;
23540
23617
  const projects = rows.map((r) => slugMap[r.project_id] ?? String(r.project_id)).filter(Boolean);
23541
- const firstSeen = Math.min(...rows.map((r) => r.first_seen));
23542
- const lastSeen = Math.max(...rows.map((r) => r.last_seen));
23618
+ const firstSeen = minOf(rows.map((r) => r.first_seen));
23619
+ const lastSeen = maxOf(rows.map((r) => r.last_seen));
23543
23620
  tunnels.push({
23544
23621
  concept: term,
23545
23622
  projects,
@@ -23578,6 +23655,7 @@ async function findTunnelsSqlite(db, registry, options) {
23578
23655
  var init_tunnels2 = __esm({
23579
23656
  "src/storage/sqlite/tunnels.ts"() {
23580
23657
  "use strict";
23658
+ init_min_max();
23581
23659
  init_stop_words();
23582
23660
  }
23583
23661
  });
@@ -26044,8 +26122,9 @@ var init_registry_sqlite = __esm({
26044
26122
  `;
26045
26123
  if (where.length) sql += " WHERE " + where.join(" AND ");
26046
26124
  sql += " ORDER BY s.date DESC, s.number DESC";
26047
- const limit = opts.limit ?? 20;
26048
- sql += ` LIMIT ${limit}`;
26125
+ const limit = Math.max(1, Math.trunc(Number(opts.limit ?? 20)) || 20);
26126
+ sql += " LIMIT ?";
26127
+ params.push(limit);
26049
26128
  return this.db.prepare(sql).all(...params);
26050
26129
  }
26051
26130
  async findSessionByFilename(projectId, filename) {
@@ -26474,15 +26553,15 @@ __export(detect_exports, {
26474
26553
  formatDetection: () => formatDetection,
26475
26554
  formatDetectionJson: () => formatDetectionJson
26476
26555
  });
26477
- import { resolve as resolve4 } from "node:path";
26556
+ import { resolve as resolve5 } from "node:path";
26478
26557
  async function detectProject(cwd) {
26479
- const target = resolve4(cwd ?? process.cwd());
26558
+ const target = resolve5(cwd ?? process.cwd());
26480
26559
  const backend = await getRegistryBackend();
26481
26560
  const projects = await backend.listProjectsByPathLengthDesc({ excludeArchived: true });
26482
26561
  let matched = null;
26483
26562
  let matchType = "exact";
26484
26563
  for (const p of projects) {
26485
- const root = resolve4(p.root_path);
26564
+ const root = resolve5(p.root_path);
26486
26565
  if (target === root) {
26487
26566
  matched = p;
26488
26567
  matchType = "exact";
@@ -26497,7 +26576,7 @@ async function detectProject(cwd) {
26497
26576
  if (!matched) return null;
26498
26577
  const sessionCount = await backend.countSessionsForProject(matched.id);
26499
26578
  const lastDate = await backend.getMostRecentSessionDate(matched.id);
26500
- const relative4 = matchType === "parent" ? target.slice(resolve4(matched.root_path).length + 1) : null;
26579
+ const relative4 = matchType === "parent" ? target.slice(resolve5(matched.root_path).length + 1) : null;
26501
26580
  return {
26502
26581
  id: matched.id,
26503
26582
  slug: matched.slug,
@@ -26553,7 +26632,7 @@ var init_detect = __esm({
26553
26632
  });
26554
26633
 
26555
26634
  // src/cli/lib/utils.ts
26556
- import { resolve as resolve5, basename as basename6, join as join30 } from "node:path";
26635
+ import { resolve as resolve6, basename as basename6, join as join30 } from "node:path";
26557
26636
  import { mkdirSync as mkdirSync21, existsSync as existsSync31, writeFileSync as writeFileSync18, readdirSync as readdirSync8, statSync as statSync10 } from "node:fs";
26558
26637
  function encIndex(entries) {
26559
26638
  let idx = indexes.get(entries);
@@ -27728,9 +27807,13 @@ function pinWorkersYamlCopy(env, root = WORKER_CONFIG_COPY_ROOT) {
27728
27807
  } catch {
27729
27808
  }
27730
27809
  }
27731
- function buildRunEnv(provider, headless, proxyUrl, providerName, routerEnabled, orchestrate) {
27810
+ function nativeLaunchEnv() {
27732
27811
  const env = { ...process.env };
27733
27812
  delete env.ANTHROPIC_API_KEY;
27813
+ return env;
27814
+ }
27815
+ function buildRunEnv(provider, headless, proxyUrl, providerName, routerEnabled, orchestrate) {
27816
+ const env = nativeLaunchEnv();
27734
27817
  if (headless) {
27735
27818
  for (const k of SESSION_IDENTITY_VARS) delete env[k];
27736
27819
  for (const k of HEADLESS_STRIP_VARS) delete env[k];
@@ -27885,11 +27968,11 @@ var init_run_env = __esm({
27885
27968
  // src/router/supervisor.ts
27886
27969
  import { connect as connect2 } from "node:net";
27887
27970
  function probeRouter(port2 = routerPort(), timeoutMs = LOCAL_PROBE_TIMEOUT_MS) {
27888
- return new Promise((resolve11) => {
27971
+ return new Promise((resolve12) => {
27889
27972
  const sock = connect2({ host: LOOPBACK_HOST, port: port2 });
27890
27973
  const done = (up) => {
27891
27974
  sock.destroy();
27892
- resolve11(up);
27975
+ resolve12(up);
27893
27976
  };
27894
27977
  sock.setTimeout(timeoutMs, () => done(false));
27895
27978
  sock.once("connect", () => done(true));
@@ -27909,7 +27992,7 @@ var init_supervisor = __esm({
27909
27992
 
27910
27993
  // src/workers/endreason.ts
27911
27994
  import { execFileSync as execFileSync10 } from "node:child_process";
27912
- import { existsSync as existsSync36, readFileSync as readFileSync36, unlinkSync as unlinkSync6, writeFileSync as writeFileSync23 } from "node:fs";
27995
+ import { existsSync as existsSync36, readFileSync as readFileSync36, unlinkSync as unlinkSync6 } from "node:fs";
27913
27996
  import { appendFileSync as appendFileSync4 } from "node:fs";
27914
27997
  import { join as join36 } from "node:path";
27915
27998
  function callerDescription(env = process.env) {
@@ -27928,7 +28011,7 @@ function requestKill(logDir2, ledger, id, by = callerDescription(), forced = fal
27928
28011
  ...forced ? { forced } : {},
27929
28012
  ...reason ? { reason } : {}
27930
28013
  };
27931
- writeFileSync23(killMarkerPath(logDir2, id), JSON.stringify(req));
28014
+ writeFileAtomic(killMarkerPath(logDir2, id), JSON.stringify(req));
27932
28015
  appendLedger(ledger, "WORKER-KILL", { id, by, pid: req.pid, ppid: req.ppid, cwd: req.cwd, ...forced ? { forced: 1 } : {}, ...reason ? { reason } : {} });
27933
28016
  }
27934
28017
  function readMarker(logDir2, id) {
@@ -27996,6 +28079,7 @@ var killMarkerPath;
27996
28079
  var init_endreason = __esm({
27997
28080
  "src/workers/endreason.ts"() {
27998
28081
  "use strict";
28082
+ init_atomic_file();
27999
28083
  init_paths();
28000
28084
  init_ledger();
28001
28085
  init_status();
@@ -28004,7 +28088,7 @@ var init_endreason = __esm({
28004
28088
  });
28005
28089
 
28006
28090
  // src/workers/loop-stop.ts
28007
- import { existsSync as existsSync37, readFileSync as readFileSync37, unlinkSync as unlinkSync7, writeFileSync as writeFileSync24 } from "node:fs";
28091
+ import { existsSync as existsSync37, readFileSync as readFileSync37, unlinkSync as unlinkSync7 } from "node:fs";
28008
28092
  import { join as join37 } from "node:path";
28009
28093
  function takeLoopStop(logDir2, id) {
28010
28094
  const p = loopStopMarkerPath(logDir2, id);
@@ -28033,6 +28117,7 @@ var loopStopMarkerPath;
28033
28117
  var init_loop_stop = __esm({
28034
28118
  "src/workers/loop-stop.ts"() {
28035
28119
  "use strict";
28120
+ init_atomic_file();
28036
28121
  init_endreason();
28037
28122
  init_status();
28038
28123
  init_queue();
@@ -28440,7 +28525,7 @@ function sayToWorker(logDir2, id, text, timeoutMs = 4e3) {
28440
28525
  new Error(`worker ${id} has no operator socket (${path}) \u2014 it may predate this PAI version`)
28441
28526
  );
28442
28527
  }
28443
- return new Promise((resolve11, reject) => {
28528
+ return new Promise((resolve12, reject) => {
28444
28529
  const sock = connect3(path);
28445
28530
  const fail = (e) => {
28446
28531
  sock.destroy();
@@ -28454,7 +28539,7 @@ function sayToWorker(logDir2, id, text, timeoutMs = 4e3) {
28454
28539
  sock.once("data", (d) => {
28455
28540
  sock.end();
28456
28541
  const reply = d.toString("utf8").trim();
28457
- if (reply === "ok") resolve11("ok");
28542
+ if (reply === "ok") resolve12("ok");
28458
28543
  else reject(new Error(`worker ${id} did not take the message: ${reply.replace(/^err /, "") || "no acknowledgement"}`));
28459
28544
  });
28460
28545
  sock.once("close", () => fail(new Error("connection closed before the worker acknowledged")));
@@ -28534,7 +28619,7 @@ var init_scratch = __esm({
28534
28619
  });
28535
28620
 
28536
28621
  // src/workers/pending.ts
28537
- import { existsSync as existsSync43, readFileSync as readFileSync42, statSync as statSync14, writeFileSync as writeFileSync25 } from "node:fs";
28622
+ import { existsSync as existsSync43, readFileSync as readFileSync42, statSync as statSync14 } from "node:fs";
28538
28623
  import { join as join42 } from "node:path";
28539
28624
  function invalidatePendingCache(logDir2, repoRoot) {
28540
28625
  const file = join42(logDir2, "pending-cache.json");
@@ -28554,13 +28639,14 @@ function invalidatePendingCache(logDir2, repoRoot) {
28554
28639
  }
28555
28640
  if (!changed) return;
28556
28641
  try {
28557
- writeFileSync25(file, JSON.stringify(cache));
28642
+ writeFileAtomic(file, JSON.stringify(cache));
28558
28643
  } catch {
28559
28644
  }
28560
28645
  }
28561
28646
  var init_pending = __esm({
28562
28647
  "src/workers/pending.ts"() {
28563
28648
  "use strict";
28649
+ init_atomic_file();
28564
28650
  init_status();
28565
28651
  init_paths();
28566
28652
  init_worktree();
@@ -28570,11 +28656,11 @@ var init_pending = __esm({
28570
28656
 
28571
28657
  // src/workers/worktree.ts
28572
28658
  import { execFile as execFile2, execFileSync as execFileSync11, spawnSync as spawnSync3 } from "node:child_process";
28573
- import { existsSync as existsSync44, lstatSync, mkdirSync as mkdirSync28, readFileSync as readFileSync43, mkdtempSync as mkdtempSync2, writeFileSync as writeFileSync26, readdirSync as readdirSync13, readlinkSync, realpathSync as realpathSync2, rmSync as rmSync9, statSync as statSync15 } from "node:fs";
28574
- import { basename as basename8, dirname as dirname22, isAbsolute as isAbsolute2, join as join43, resolve as resolve6, sep as sep2 } from "node:path";
28659
+ import { existsSync as existsSync44, lstatSync, mkdirSync as mkdirSync28, readFileSync as readFileSync43, mkdtempSync as mkdtempSync2, writeFileSync as writeFileSync23, readdirSync as readdirSync13, readlinkSync, realpathSync as realpathSync2, rmSync as rmSync9, statSync as statSync15 } from "node:fs";
28660
+ import { basename as basename8, dirname as dirname22, isAbsolute as isAbsolute2, join as join43, resolve as resolve7, sep as sep2 } from "node:path";
28575
28661
  import { tmpdir as tmpdir3, platform } from "node:os";
28576
28662
  function isSlotWorktree(dir) {
28577
- return basename8(dirname22(resolve6(dir))) === "slots";
28663
+ return basename8(dirname22(resolve7(dir))) === "slots";
28578
28664
  }
28579
28665
  function worktreesDir(logDir2) {
28580
28666
  return join43(logDir2, "worktrees");
@@ -28697,11 +28783,11 @@ function isPaiBookkeepingPath(path) {
28697
28783
  function ensureScratchExcluded(cwd) {
28698
28784
  try {
28699
28785
  const rel = git(cwd, ["rev-parse", "--git-path", "info/exclude"]);
28700
- const file = isAbsolute2(rel) ? rel : resolve6(cwd, rel);
28786
+ const file = isAbsolute2(rel) ? rel : resolve7(cwd, rel);
28701
28787
  const cur = existsSync44(file) ? readFileSync43(file, "utf8") : "";
28702
28788
  if (cur.split("\n").some((l) => l.trim() === ".pai-scratch/")) return;
28703
28789
  mkdirSync28(dirname22(file), { recursive: true });
28704
- writeFileSync26(file, `${cur}${cur === "" || cur.endsWith("\n") ? "" : "\n"}.pai-scratch/
28790
+ writeFileSync23(file, `${cur}${cur === "" || cur.endsWith("\n") ? "" : "\n"}.pai-scratch/
28705
28791
  `, "utf8");
28706
28792
  } catch {
28707
28793
  }
@@ -28876,7 +28962,7 @@ function salvageIgnored(cwd, wtDir, id) {
28876
28962
  lines.push(`salvaged ${rel} from worker ${id}`);
28877
28963
  }
28878
28964
  mkdirSync28(dirname22(dest), { recursive: true });
28879
- writeFileSync26(dest, data);
28965
+ writeFileSync23(dest, data);
28880
28966
  } catch {
28881
28967
  lines.pop();
28882
28968
  failed.push(rel);
@@ -28895,7 +28981,7 @@ function transcriptWrites(logDir2, id, dir) {
28895
28981
  } catch {
28896
28982
  return [];
28897
28983
  }
28898
- const roots = [resolve6(dir)];
28984
+ const roots = [resolve7(dir)];
28899
28985
  try {
28900
28986
  roots.push(realpathSync2(dir));
28901
28987
  } catch {
@@ -28910,7 +28996,7 @@ function transcriptWrites(logDir2, id, dir) {
28910
28996
  if (b?.type !== "tool_use" || !["Write", "Edit", "MultiEdit", "NotebookEdit"].includes(b.name ?? "")) continue;
28911
28997
  const fp = b.input?.file_path;
28912
28998
  if (typeof fp !== "string") continue;
28913
- const abs = resolve6(fp);
28999
+ const abs = resolve7(fp);
28914
29000
  if (roots.some((r) => abs.startsWith(r + sep2))) out.add(abs);
28915
29001
  }
28916
29002
  } catch {
@@ -28939,7 +29025,7 @@ function worktreeKnowledge(logDir2, id, dir, base) {
28939
29025
  } catch {
28940
29026
  }
28941
29027
  k.ignored = ignoredKnowledge(dir);
28942
- const root = resolve6(dir);
29028
+ const root = resolve7(dir);
28943
29029
  for (const abs of transcriptWrites(logDir2, id, dir)) {
28944
29030
  if (existsSync44(abs)) continue;
28945
29031
  const rel = abs.startsWith(root + sep2) ? abs.slice(root.length + 1) : abs;
@@ -28980,7 +29066,7 @@ function symlinkEscapesWorktree(wtDir, relPath) {
28980
29066
  }
28981
29067
  if (!stat.isSymbolicLink()) return false;
28982
29068
  const target = readlinkSync(full);
28983
- const resolvedTarget = isAbsolute2(target) ? target : resolve6(dirname22(full), target);
29069
+ const resolvedTarget = isAbsolute2(target) ? target : resolve7(dirname22(full), target);
28984
29070
  const realTarget = existsSync44(resolvedTarget) ? realpathSync2(resolvedTarget) : resolvedTarget;
28985
29071
  const realWtDir = realpathSync2(wtDir);
28986
29072
  return realTarget !== realWtDir && !realTarget.startsWith(realWtDir + sep2);
@@ -29235,7 +29321,7 @@ function mergeWorker(logDir2, id, opts = {}) {
29235
29321
  let files = [];
29236
29322
  let inProgress = false;
29237
29323
  try {
29238
- inProgress = existsSync44(resolve6(st.cwd, git(st.cwd, ["rev-parse", "--git-path", "MERGE_HEAD"])));
29324
+ inProgress = existsSync44(resolve7(st.cwd, git(st.cwd, ["rev-parse", "--git-path", "MERGE_HEAD"])));
29239
29325
  if (inProgress) files = git(st.cwd, ["diff", "--name-only", "--diff-filter=U"]).split("\n").filter(Boolean);
29240
29326
  } catch {
29241
29327
  }
@@ -29435,7 +29521,7 @@ function branchArchived(repo, branchRef, refs) {
29435
29521
  function commonDir(dir) {
29436
29522
  try {
29437
29523
  const raw = git(dir, ["rev-parse", "--git-common-dir"]);
29438
- return isAbsolute2(raw) ? raw : resolve6(dir, raw);
29524
+ return isAbsolute2(raw) ? raw : resolve7(dir, raw);
29439
29525
  } catch {
29440
29526
  return null;
29441
29527
  }
@@ -29527,7 +29613,7 @@ function archiveWorktree(logDir2, id, dir, branch) {
29527
29613
  let repo;
29528
29614
  try {
29529
29615
  const raw = git(dir, ["rev-parse", "--git-common-dir"]);
29530
- repo = isAbsolute2(raw) ? raw : resolve6(dir, raw);
29616
+ repo = isAbsolute2(raw) ? raw : resolve7(dir, raw);
29531
29617
  } catch {
29532
29618
  throw new Error("not a git worktree");
29533
29619
  }
@@ -29589,6 +29675,15 @@ function dirBytes(dir) {
29589
29675
  const r = spawnSync3("du", ["-sk", dir], { encoding: "utf8" });
29590
29676
  return (parseInt(String(r.stdout).split(" ")[0] ?? "", 10) || 0) * 1024;
29591
29677
  }
29678
+ function isRealWorktree(dir) {
29679
+ try {
29680
+ const real = realpathSync2(dir);
29681
+ if (realpathSync2(git(dir, ["rev-parse", "--show-toplevel"])) !== real) return false;
29682
+ return git(dir, ["worktree", "list", "--porcelain"]).split("\n").some((l) => l.startsWith("worktree ") && realpathOr(l.slice(9)) === real);
29683
+ } catch {
29684
+ return false;
29685
+ }
29686
+ }
29592
29687
  function busyPid(dir) {
29593
29688
  let real = dir;
29594
29689
  try {
@@ -29618,7 +29713,7 @@ function archiveSlotBranch(logDir2, st, tree, dryRun, report, out) {
29618
29713
  let repo;
29619
29714
  try {
29620
29715
  const raw = git(st.cwd, ["rev-parse", "--git-common-dir"]);
29621
- repo = isAbsolute2(raw) ? raw : resolve6(st.cwd, raw);
29716
+ repo = isAbsolute2(raw) ? raw : resolve7(st.cwd, raw);
29622
29717
  git(repo, ["rev-parse", "--verify", "-q", `refs/heads/${tree.branch}`]);
29623
29718
  } catch {
29624
29719
  return;
@@ -29667,13 +29762,13 @@ function gcForeign(logDir2, repo, owned, dryRun, report, out, archive) {
29667
29762
  } catch {
29668
29763
  return;
29669
29764
  }
29670
- const pai2 = resolve6(logDir2);
29765
+ const pai2 = resolve7(logDir2);
29671
29766
  const blocks = raw.split("\n\n").map((b) => b.trim()).filter(Boolean);
29672
29767
  blocks.slice(1).forEach((block) => {
29673
29768
  const field = (k) => block.split("\n").find((l) => l.startsWith(k + " "))?.slice(k.length + 1);
29674
29769
  const dir = field("worktree");
29675
29770
  if (!dir || !existsSync44(dir) || block.includes("\nprunable")) return;
29676
- const real = resolve6(dir);
29771
+ const real = resolve7(dir);
29677
29772
  if (owned.has(real) || real === pai2 || real.startsWith(pai2 + sep2) || isSlotWorktree(real)) return;
29678
29773
  const ref = field("branch");
29679
29774
  const branch = ref?.replace(/^refs\/heads\//, "");
@@ -29693,7 +29788,7 @@ function realpathOr(p) {
29693
29788
  try {
29694
29789
  return realpathSync2(p);
29695
29790
  } catch {
29696
- return resolve6(p);
29791
+ return resolve7(p);
29697
29792
  }
29698
29793
  }
29699
29794
  function gcScratchTrees(statuses, owned, extraRepos, out, archive) {
@@ -29799,9 +29894,10 @@ function gcWorktrees(logDir2, olderThanHours = 24, dryRun = false, now = Date.no
29799
29894
  const out = [];
29800
29895
  const root = worktreesDir(logDir2);
29801
29896
  const statuses = loadStatuses(logDir2);
29802
- const owned = new Set(statuses.map((s) => ownedTree(s)?.dir).filter((d) => !!d).map((d) => resolve6(d)));
29897
+ const owned = new Set(statuses.map((s) => ownedTree(s)?.dir).filter((d) => !!d).map((d) => resolve7(d)));
29803
29898
  const archive = (id, dir, branch, st) => {
29804
29899
  const target = `refs/pai-archive/${id}`;
29900
+ if (!isRealWorktree(dir)) return void out.push({ id, skipped: "not a worktree" });
29805
29901
  const pid = busyPid(dir);
29806
29902
  if (pid) {
29807
29903
  if (!dryRun) appendLedger(ledgerPath(logDir2), "WORKER-GC-SKIP", { id, reason: "busy", pid: String(pid) });
@@ -29872,7 +29968,7 @@ function gcWorktrees(logDir2, olderThanHours = 24, dryRun = false, now = Date.no
29872
29968
  if (existsSync44(root)) {
29873
29969
  for (const ent of readdirSync13(root, { withFileTypes: true })) {
29874
29970
  const dir = join43(root, ent.name);
29875
- if (!ent.isDirectory() || owned.has(resolve6(dir)) || isSlotWorktree(dir) || ent.name.startsWith("spare-") || landed.has(realpathOr(dir))) continue;
29971
+ if (!ent.isDirectory() || owned.has(resolve7(dir)) || isSlotWorktree(dir) || ent.name.startsWith("spare-") || landed.has(realpathOr(dir))) continue;
29876
29972
  try {
29877
29973
  if (Math.floor(statSync15(dir).mtimeMs) > cutoff) continue;
29878
29974
  } catch {
@@ -29907,7 +30003,7 @@ function gcWorktreesThrottled(logDir2, everyMin = 60, now = Date.now(), opts = {
29907
30003
  } catch {
29908
30004
  }
29909
30005
  mkdirSync28(logDir2, { recursive: true });
29910
- writeFileSync26(stamp, String(now), "utf8");
30006
+ writeFileSync23(stamp, String(now), "utf8");
29911
30007
  return gcWorktrees(logDir2, opts.olderThanHours ?? 24, false, now, false, opts.maxGb);
29912
30008
  }
29913
30009
  var WRITING_TOOLS, KNOWLEDGE_IGNORE_NAMES, KNOWLEDGE_IGNORE_SUFFIXES, MAX_SALVAGE_DELETES, MergeConflictError, withGate, GATE_MARK, STUB_PATTERN, TEST_CASE, OWNED_PREFIXES, GC_STAMP;
@@ -29954,7 +30050,7 @@ __export(aibroker_client_exports, {
29954
30050
  import { connect as connect4 } from "node:net";
29955
30051
  import { randomUUID as randomUUID2 } from "node:crypto";
29956
30052
  function callAiBroker(method, params = {}, timeoutMs = 8e3, caller = {}) {
29957
- return new Promise((resolve11, reject) => {
30053
+ return new Promise((resolve12, reject) => {
29958
30054
  const socketPath = brokerSocket();
29959
30055
  let done = false;
29960
30056
  let buffer = "";
@@ -29971,7 +30067,7 @@ function callAiBroker(method, params = {}, timeoutMs = 8e3, caller = {}) {
29971
30067
  } catch {
29972
30068
  }
29973
30069
  if (err) reject(err);
29974
- else resolve11(value);
30070
+ else resolve12(value);
29975
30071
  }
29976
30072
  const socket = connect4(socketPath, () => {
29977
30073
  const request = {
@@ -30347,7 +30443,7 @@ var init_kill_tree = __esm({
30347
30443
  // src/workers/reap.ts
30348
30444
  import { execFileSync as execFileSync13 } from "node:child_process";
30349
30445
  import { existsSync as existsSync45, readdirSync as readdirSync14, realpathSync as realpathSync3 } from "node:fs";
30350
- import { join as join45, resolve as resolve7, sep as sep3 } from "node:path";
30446
+ import { join as join45, resolve as resolve8, sep as sep3 } from "node:path";
30351
30447
  function commandOf(pid) {
30352
30448
  try {
30353
30449
  return execFileSync13("ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
@@ -30475,7 +30571,7 @@ var init_reap = __esm({
30475
30571
  });
30476
30572
 
30477
30573
  // src/workers/active-time.ts
30478
- import { mkdirSync as mkdirSync29, readFileSync as readFileSync45, statSync as statSync16, writeFileSync as writeFileSync27 } from "node:fs";
30574
+ import { mkdirSync as mkdirSync29, readFileSync as readFileSync45, statSync as statSync16, writeFileSync as writeFileSync24 } from "node:fs";
30479
30575
  import { join as join46 } from "node:path";
30480
30576
  function read(logDir2, id) {
30481
30577
  try {
@@ -30668,7 +30764,7 @@ var init_translate = __esm({
30668
30764
 
30669
30765
  // src/workers/proxy/server.ts
30670
30766
  import { spawn as spawn2 } from "node:child_process";
30671
- import { existsSync as existsSync47, readFileSync as readFileSync46, writeFileSync as writeFileSync28, mkdirSync as mkdirSync30, unlinkSync as unlinkSync9 } from "node:fs";
30767
+ import { existsSync as existsSync47, readFileSync as readFileSync46, writeFileSync as writeFileSync25, mkdirSync as mkdirSync30, unlinkSync as unlinkSync9 } from "node:fs";
30672
30768
  import { connect as connect5 } from "node:net";
30673
30769
  import { dirname as dirname23, join as join47 } from "node:path";
30674
30770
  import { fileURLToPath as fileURLToPath4 } from "node:url";
@@ -30679,12 +30775,12 @@ function proxyPidPath(logDir2) {
30679
30775
  return join47(logDir2, "proxy.pid");
30680
30776
  }
30681
30777
  function proxyListening(port2 = proxyPort(), timeoutMs = 400) {
30682
- return new Promise((resolve11) => {
30778
+ return new Promise((resolve12) => {
30683
30779
  const sock = connect5({ port: port2, host: HOST });
30684
30780
  const done = (ok) => {
30685
30781
  sock.removeAllListeners();
30686
30782
  sock.destroy();
30687
- resolve11(ok);
30783
+ resolve12(ok);
30688
30784
  };
30689
30785
  sock.setTimeout(timeoutMs, () => done(false));
30690
30786
  sock.once("connect", () => done(true));
@@ -30721,7 +30817,7 @@ async function ensureProxyRunning(port2, logDir2) {
30721
30817
  stdio: "ignore"
30722
30818
  });
30723
30819
  child.unref();
30724
- writeFileSync28(proxyPidPath(logDir2), `${child.pid}
30820
+ writeFileSync25(proxyPidPath(logDir2), `${child.pid}
30725
30821
  `, "utf8");
30726
30822
  for (let i = 0; i < 40; i++) {
30727
30823
  if (await proxyListening(port2)) return `http://${HOST}:${port2}`;
@@ -30996,9 +31092,9 @@ async function reaskAg2Report(a) {
30996
31092
  proc.stdout.on("data", (chunk) => {
30997
31093
  out += chunk.toString("utf8");
30998
31094
  });
30999
- await new Promise((resolve11) => {
31000
- proc.on("error", () => resolve11());
31001
- proc.on("close", () => resolve11());
31095
+ await new Promise((resolve12) => {
31096
+ proc.on("error", () => resolve12());
31097
+ proc.on("close", () => resolve12());
31002
31098
  });
31003
31099
  clearTimeout(timer);
31004
31100
  return resultFromOutput(out);
@@ -31180,7 +31276,7 @@ var init_escalate = __esm({
31180
31276
  });
31181
31277
 
31182
31278
  // src/workers/engines/image.ts
31183
- import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync29 } from "node:fs";
31279
+ import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync26 } from "node:fs";
31184
31280
  import { dirname as dirname24 } from "node:path";
31185
31281
  async function runImageCapability(opts) {
31186
31282
  if (!opts.provider.baseUrl) {
@@ -31242,7 +31338,7 @@ async function runImageCapability(opts) {
31242
31338
  }
31243
31339
  const bytes = Buffer.from(b64, "base64");
31244
31340
  mkdirSync31(dirname24(opts.outPath), { recursive: true });
31245
- writeFileSync29(opts.outPath, bytes);
31341
+ writeFileSync26(opts.outPath, bytes);
31246
31342
  return {
31247
31343
  ok: true,
31248
31344
  path: opts.outPath,
@@ -31481,7 +31577,7 @@ var init_pane_bar = __esm({
31481
31577
  // src/workers/pane-exec.ts
31482
31578
  import { EventEmitter } from "node:events";
31483
31579
  import { createHash as createHash8 } from "node:crypto";
31484
- import { existsSync as existsSync48, mkdirSync as mkdirSync32, readFileSync as readFileSync47, readdirSync as readdirSync15, renameSync as renameSync16, unlinkSync as unlinkSync10, writeFileSync as writeFileSync30 } from "node:fs";
31580
+ import { existsSync as existsSync48, mkdirSync as mkdirSync32, readFileSync as readFileSync47, readdirSync as readdirSync15, renameSync as renameSync16, unlinkSync as unlinkSync10, writeFileSync as writeFileSync27 } from "node:fs";
31485
31581
  import { createConnection, createServer as createServer2 } from "node:net";
31486
31582
  import { tmpdir as tmpdir4 } from "node:os";
31487
31583
  import { join as join48 } from "node:path";
@@ -31496,7 +31592,7 @@ function paneExecCommand(id, node = process.execPath, cli = process.argv[1] ?? "
31496
31592
  function writeJson(path, v) {
31497
31593
  mkdirSync32(paneExecDir(), { recursive: true });
31498
31594
  const tmp = `${path}.${process.pid}.tmp`;
31499
- writeFileSync30(tmp, JSON.stringify(v), "utf8");
31595
+ writeFileSync27(tmp, JSON.stringify(v), "utf8");
31500
31596
  renameSync16(tmp, path);
31501
31597
  }
31502
31598
  function readExit(id) {
@@ -31527,16 +31623,16 @@ async function openOwnedPane(o) {
31527
31623
  let session;
31528
31624
  let sock = null;
31529
31625
  let server;
31530
- const connected = new Promise((resolve11) => {
31626
+ const connected = new Promise((resolve12) => {
31531
31627
  server = createServer2((s2) => {
31532
31628
  sock = s2;
31533
31629
  server.close();
31534
- resolve11(s2);
31630
+ resolve12(s2);
31535
31631
  });
31536
31632
  });
31537
- await new Promise((resolve11, reject) => {
31633
+ await new Promise((resolve12, reject) => {
31538
31634
  server.once("error", reject);
31539
- server.listen(sockPath(o.id), resolve11);
31635
+ server.listen(sockPath(o.id), resolve12);
31540
31636
  });
31541
31637
  const fail = async (e) => {
31542
31638
  server.close();
@@ -31776,7 +31872,7 @@ import {
31776
31872
  readFileSync as readFileSync48,
31777
31873
  renameSync as renameSync17,
31778
31874
  rmSync as rmSync10,
31779
- writeFileSync as writeFileSync31
31875
+ writeFileSync as writeFileSync28
31780
31876
  } from "node:fs";
31781
31877
  import { homedir as homedir9, tmpdir as tmpdir5 } from "node:os";
31782
31878
  import { dirname as dirname25, join as join49 } from "node:path";
@@ -31815,14 +31911,14 @@ function pickSplit(panes, hostId) {
31815
31911
  return best ? { id: best.id, dir: best.dir, cols: best.cols, rows: best.rows, small: true } : null;
31816
31912
  }
31817
31913
  function osascript(script, args) {
31818
- return new Promise((resolve11, reject) => {
31914
+ return new Promise((resolve12, reject) => {
31819
31915
  const proc = spawn4("osascript", ["-l", "JavaScript", "-", ...args], { stdio: ["pipe", "pipe", "pipe"] });
31820
31916
  let out = "";
31821
31917
  let err = "";
31822
31918
  proc.stdout.on("data", (c) => out += c.toString("utf8"));
31823
31919
  proc.stderr.on("data", (c) => err += c.toString("utf8"));
31824
31920
  proc.on("error", reject);
31825
- proc.on("close", () => resolve11({ stdout: out, stderr: err }));
31921
+ proc.on("close", () => resolve12({ stdout: out, stderr: err }));
31826
31922
  proc.stdin.write(script);
31827
31923
  proc.stdin.end();
31828
31924
  });
@@ -31917,7 +32013,7 @@ function writeDynamicProfile(parent, fontSize, read2 = itermPrefs) {
31917
32013
  const dir = dirname25(path);
31918
32014
  if (!existsSync49(dir)) mkdirSync33(dir, { recursive: true });
31919
32015
  const tmp = `${path}.tmp`;
31920
- writeFileSync31(tmp, JSON.stringify({ Profiles: [profile] }, null, 2) + "\n", "utf8");
32016
+ writeFileSync28(tmp, JSON.stringify({ Profiles: [profile] }, null, 2) + "\n", "utf8");
31921
32017
  renameSync17(tmp, path);
31922
32018
  }
31923
32019
  async function followProfile(fontSize, read2 = itermPrefs) {
@@ -31984,7 +32080,7 @@ function saveEntry(logDir2, e) {
31984
32080
  const path = entryPath(logDir2, e);
31985
32081
  mkdirSync33(dirname25(path), { recursive: true });
31986
32082
  const tmp = `${path}.${process.pid}.tmp`;
31987
- writeFileSync31(tmp, JSON.stringify({ session: e.session, worker: e.worker, opened: e.opened, ...e.host ? { host: e.host } : {} }, null, 1), "utf8");
32083
+ writeFileSync28(tmp, JSON.stringify({ session: e.session, worker: e.worker, opened: e.opened, ...e.host ? { host: e.host } : {} }, null, 1), "utf8");
31988
32084
  renameSync17(tmp, path);
31989
32085
  }
31990
32086
  function dropEntry(logDir2, e, caller, reason) {
@@ -31994,7 +32090,7 @@ function dropEntry(logDir2, e, caller, reason) {
31994
32090
  rmSync10(entryPath(logDir2, e), { force: true });
31995
32091
  if (existsSync49(legacy)) {
31996
32092
  const rest = readEntry2(legacy, e.scope ?? "").filter((x) => x.session !== e.session);
31997
- writeFileSync31(legacy, JSON.stringify(rest.map(({ scope: _s, ...x }) => x), null, 1), "utf8");
32093
+ writeFileSync28(legacy, JSON.stringify(rest.map(({ scope: _s, ...x }) => x), null, 1), "utf8");
31998
32094
  }
31999
32095
  }
32000
32096
  async function listItermSessions(run = osascript) {
@@ -33013,9 +33109,9 @@ var init_lifecycle = __esm({
33013
33109
  });
33014
33110
 
33015
33111
  // src/workers/note-delivery.ts
33016
- import { randomBytes } from "node:crypto";
33112
+ import { randomBytes as randomBytes2 } from "node:crypto";
33017
33113
  function newNoteToken() {
33018
- return randomBytes(4).toString("hex");
33114
+ return randomBytes2(4).toString("hex");
33019
33115
  }
33020
33116
  var NOTE_TOKEN_ENV;
33021
33117
  var init_note_delivery = __esm({
@@ -33059,18 +33155,18 @@ var init_browser_tools = __esm({
33059
33155
  });
33060
33156
 
33061
33157
  // src/workers/project-config.ts
33062
- import { resolve as resolve8 } from "node:path";
33158
+ import { resolve as resolve9 } from "node:path";
33063
33159
  function asStringArray(v) {
33064
33160
  if (!Array.isArray(v)) return void 0;
33065
33161
  const out = v.filter((x) => typeof x === "string");
33066
33162
  return out.length ? out : void 0;
33067
33163
  }
33068
33164
  async function projectLaunchConfig(cwd, registry) {
33069
- const target = resolve8(cwd);
33165
+ const target = resolve9(cwd);
33070
33166
  const backend = registry ?? await getRegistryBackend();
33071
33167
  const rows = await backend.listProjectsByPathLengthDesc({ excludeArchived: true });
33072
33168
  for (const row of rows) {
33073
- const root = resolve8(row.root_path);
33169
+ const root = resolve9(row.root_path);
33074
33170
  if (target !== root && !target.startsWith(root + "/")) continue;
33075
33171
  if (!row.session_config) return null;
33076
33172
  let parsed;
@@ -33345,7 +33441,7 @@ var init_execute_prepare = __esm({
33345
33441
 
33346
33442
  // src/workers/edit-assist.ts
33347
33443
  import { readFileSync as readFileSync49 } from "node:fs";
33348
- import { resolve as resolve9 } from "node:path";
33444
+ import { resolve as resolve10 } from "node:path";
33349
33445
  function editAssist(i) {
33350
33446
  if (i.errorText.includes("No changes to make: old_string and new_string are exactly the same")) {
33351
33447
  return "old_string and new_string are identical: the file already contains your intended text; check whether this step is done (grep for it) before editing again.";
@@ -33438,8 +33534,9 @@ function computeSimilarity(s1, s2) {
33438
33534
  break;
33439
33535
  }
33440
33536
  }
33537
+ const overlapCap = minLength - prefixLength;
33441
33538
  const totalLength = Math.max(s1.length, s2.length);
33442
- return totalLength > 0 ? (prefixLength + suffixLength) / totalLength : 0;
33539
+ return (prefixLength + Math.min(suffixLength, overlapCap)) / totalLength;
33443
33540
  }
33444
33541
  function isEditAssistError(errorText) {
33445
33542
  return errorText.includes("No changes to make: old_string and new_string are exactly the same") || errorText.includes("String to replace not found in file");
@@ -33452,7 +33549,7 @@ function editHintFor(input, errorText, cwd) {
33452
33549
  let fileText = null;
33453
33550
  if (typeof i.file_path === "string") {
33454
33551
  try {
33455
- fileText = readFileSync49(resolve9(cwd, i.file_path), "utf8");
33552
+ fileText = readFileSync49(resolve10(cwd, i.file_path), "utf8");
33456
33553
  } catch {
33457
33554
  fileText = null;
33458
33555
  }
@@ -33556,7 +33653,7 @@ var init_notice_policy = __esm({
33556
33653
 
33557
33654
  // src/workers/pailot-guard.ts
33558
33655
  import { createHash as createHash9 } from "node:crypto";
33559
- import { mkdirSync as mkdirSync34, readFileSync as readFileSync50, renameSync as renameSync18, writeFileSync as writeFileSync32 } from "node:fs";
33656
+ import { mkdirSync as mkdirSync34, readFileSync as readFileSync50, renameSync as renameSync18, writeFileSync as writeFileSync29 } from "node:fs";
33560
33657
  import { join as join50 } from "node:path";
33561
33658
  function load(logDir2) {
33562
33659
  try {
@@ -33570,7 +33667,7 @@ function save(logDir2, s) {
33570
33667
  try {
33571
33668
  mkdirSync34(logDir2, { recursive: true });
33572
33669
  const tmp = `${stateFile(logDir2)}.${process.pid}.tmp`;
33573
- writeFileSync32(tmp, JSON.stringify(s), "utf8");
33670
+ writeFileSync29(tmp, JSON.stringify(s), "utf8");
33574
33671
  renameSync18(tmp, stateFile(logDir2));
33575
33672
  } catch {
33576
33673
  }
@@ -33622,7 +33719,7 @@ var init_pailot_guard = __esm({
33622
33719
 
33623
33720
  // src/workers/run-events.ts
33624
33721
  import { spawn as spawn6 } from "node:child_process";
33625
- import { existsSync as existsSync50, mkdirSync as mkdirSync35, openSync as openSync4, readdirSync as readdirSync17, readFileSync as readFileSync51, writeFileSync as writeFileSync33 } from "node:fs";
33722
+ import { existsSync as existsSync50, mkdirSync as mkdirSync35, openSync as openSync4, readdirSync as readdirSync17, readFileSync as readFileSync51, writeFileSync as writeFileSync30 } from "node:fs";
33626
33723
  function originFromEnv(env = process.env) {
33627
33724
  if (env.PAI_RUN_ORIGIN) {
33628
33725
  try {
@@ -33772,6 +33869,7 @@ var init_worker_trouble = __esm({
33772
33869
  var init_usage2 = __esm({
33773
33870
  "src/workers/usage.ts"() {
33774
33871
  "use strict";
33872
+ init_min_max();
33775
33873
  init_paths();
33776
33874
  init_status();
33777
33875
  init_config3();
@@ -34045,7 +34143,7 @@ var init_pool_host_run = __esm({
34045
34143
 
34046
34144
  // src/workers/pool-cli.ts
34047
34145
  import { spawn as spawn7 } from "node:child_process";
34048
- import { closeSync as closeSync4, existsSync as existsSync52, mkdirSync as mkdirSync37, statSync as statSync18, unlinkSync as unlinkSync11, writeFileSync as writeFileSync34, readFileSync as readFileSync52 } from "node:fs";
34146
+ import { closeSync as closeSync4, existsSync as existsSync52, mkdirSync as mkdirSync37, statSync as statSync18, unlinkSync as unlinkSync11, writeFileSync as writeFileSync31, readFileSync as readFileSync52 } from "node:fs";
34049
34147
  import { dirname as dirname26, join as join52 } from "node:path";
34050
34148
  import { fileURLToPath as fileURLToPath5 } from "node:url";
34051
34149
  function standalonePoolHostPath() {
@@ -34081,7 +34179,7 @@ async function startPoolHost(logDir2, port2, waitMs) {
34081
34179
  });
34082
34180
  child.unref();
34083
34181
  closeSync4(logFd);
34084
- writeFileSync34(poolPidPath(logDir2), `${child.pid}
34182
+ writeFileSync31(poolPidPath(logDir2), `${child.pid}
34085
34183
  `, "utf8");
34086
34184
  appendLedger(ledgerPath(logDir2), "POOL-HOST-START", { pid: child.pid ?? 0, port: port2, note: "spawned by a client" });
34087
34185
  for (let i = 0; i < waitMs / 250; i++) {
@@ -34713,14 +34811,14 @@ async function foldRun(a, p) {
34713
34811
  state.closeTimer = null;
34714
34812
  }
34715
34813
  writeEvent({ type: "operator", text, handoff: isHandoffMessage(text) });
34716
- return new Promise((resolve11) => {
34814
+ return new Promise((resolve12) => {
34717
34815
  try {
34718
34816
  stdin.write(
34719
34817
  stdinUserMessage(operatorUserText(text)) + "\n",
34720
- (e) => resolve11(e ? `write to the worker failed: ${e.message}` : void 0)
34818
+ (e) => resolve12(e ? `write to the worker failed: ${e.message}` : void 0)
34721
34819
  );
34722
34820
  } catch (e) {
34723
- resolve11(`write to the worker failed: ${e.message}`);
34821
+ resolve12(`write to the worker failed: ${e.message}`);
34724
34822
  }
34725
34823
  });
34726
34824
  }) : null;
@@ -34844,11 +34942,11 @@ async function foldRun(a, p) {
34844
34942
  }
34845
34943
  });
34846
34944
  }
34847
- let rc = await new Promise((resolve11, reject) => {
34945
+ let rc = await new Promise((resolve12, reject) => {
34848
34946
  const onError = (e) => void failRun(e).then(() => reject(e), () => reject(e));
34849
34947
  if (earlyError) onError(earlyError);
34850
34948
  else proc.on("error", onError);
34851
- proc.on("close", (code) => resolve11(code ?? (state.killed ? 143 : 1)));
34949
+ proc.on("close", (code) => resolve12(code ?? (state.killed ? 143 : 1)));
34852
34950
  });
34853
34951
  if (state.troubleTimer) clearInterval(state.troubleTimer);
34854
34952
  if (state.trouble) {
@@ -35377,11 +35475,11 @@ async function executeCodexRun(a) {
35377
35475
  saveStatus(logDir2, status);
35378
35476
  for (const ev of fold.events.splice(0)) writeEvent(ev);
35379
35477
  });
35380
- const rc = await new Promise((resolve11, reject) => {
35478
+ const rc = await new Promise((resolve12, reject) => {
35381
35479
  const onError = (e) => void failRun(e).then(() => reject(e), () => reject(e));
35382
35480
  if (earlyError) onError(earlyError);
35383
35481
  else proc.on("error", onError);
35384
- proc.on("close", (code) => resolve11(code ?? (killed ? 143 : 1)));
35482
+ proc.on("close", (code) => resolve12(code ?? (killed ? 143 : 1)));
35385
35483
  });
35386
35484
  const secs = Math.floor((Date.now() - t0) / 1e3);
35387
35485
  const finalText = fold.finalText ?? "";
@@ -35479,12 +35577,12 @@ async function returnControlsIfHeld(logDir2, id) {
35479
35577
  if (!id) return;
35480
35578
  const status = loadStatus(logDir2, id);
35481
35579
  if (!status?.controlsHeld) return;
35482
- await new Promise((resolve11) => {
35580
+ await new Promise((resolve12) => {
35483
35581
  let done = false;
35484
35582
  const finish = () => {
35485
35583
  if (done) return;
35486
35584
  done = true;
35487
- resolve11();
35585
+ resolve12();
35488
35586
  };
35489
35587
  try {
35490
35588
  const proc = spawn8("clickr", clickrControlsReturnArgv(id), { stdio: "ignore" });
@@ -36154,7 +36252,7 @@ init_config3();
36154
36252
  init_paths();
36155
36253
  init_pool();
36156
36254
  import { spawn as spawn10 } from "node:child_process";
36157
- import { mkdirSync as mkdirSync42, writeFileSync as writeFileSync36 } from "node:fs";
36255
+ import { mkdirSync as mkdirSync42, writeFileSync as writeFileSync33 } from "node:fs";
36158
36256
 
36159
36257
  // src/workers/pool-host.ts
36160
36258
  init_loopback_guard();
@@ -36184,8 +36282,8 @@ import { openSync as openSync8, closeSync as closeSync7, writeSync as writeSync3
36184
36282
  // src/workers/slots.ts
36185
36283
  init_pai_home();
36186
36284
  init_worktree();
36187
- import { existsSync as existsSync55, mkdirSync as mkdirSync40, writeFileSync as writeFileSync35, realpathSync as realpathSync4 } from "node:fs";
36188
- import { dirname as dirname27, join as join56, resolve as resolve10, isAbsolute as isAbsolute3 } from "node:path";
36285
+ import { existsSync as existsSync55, mkdirSync as mkdirSync40, writeFileSync as writeFileSync32, realpathSync as realpathSync4 } from "node:fs";
36286
+ import { dirname as dirname27, join as join56, resolve as resolve11, isAbsolute as isAbsolute3 } from "node:path";
36189
36287
  function slotsDir(logDir2) {
36190
36288
  return join56(logDir2, "slots");
36191
36289
  }
@@ -36195,7 +36293,7 @@ function slotPath(logDir2, provider, n) {
36195
36293
  function slotRepo(dir) {
36196
36294
  try {
36197
36295
  const raw = git(dir, ["rev-parse", "--git-common-dir"]);
36198
- const resolved = isAbsolute3(raw) ? raw : resolve10(dir, raw);
36296
+ const resolved = isAbsolute3(raw) ? raw : resolve11(dir, raw);
36199
36297
  return realpathSync4(resolved);
36200
36298
  } catch {
36201
36299
  return null;
@@ -36208,7 +36306,7 @@ function slotServesRepo(logDir2, provider, n, repo) {
36208
36306
  if (!slotRepoPath) return false;
36209
36307
  try {
36210
36308
  const repoCommon = git(repo, ["rev-parse", "--git-common-dir"]);
36211
- const resolvedRepo = isAbsolute3(repoCommon) ? repoCommon : resolve10(repo, repoCommon);
36309
+ const resolvedRepo = isAbsolute3(repoCommon) ? repoCommon : resolve11(repo, repoCommon);
36212
36310
  return slotRepoPath === realpathSync4(resolvedRepo);
36213
36311
  } catch {
36214
36312
  return false;
@@ -36234,7 +36332,7 @@ function prepareSlot(logDir2, provider, n, repo, taskId, baseRef) {
36234
36332
  const uncommitted = uncommittedPaths(dir);
36235
36333
  const untracked = uncommitted.filter((p) => !p.startsWith(".git/"));
36236
36334
  mkdirSync40(dirname27(patchPath), { recursive: true });
36237
- writeFileSync35(patchPath, `${diff}
36335
+ writeFileSync32(patchPath, `${diff}
36238
36336
  untracked/other: ${untracked.join(" ")}
36239
36337
  `);
36240
36338
  salvagePatch = patchPath;
@@ -36379,8 +36477,8 @@ var PoolSlotSession = class {
36379
36477
  this.feeding = true;
36380
36478
  let result = null;
36381
36479
  let resolveFeed = null;
36382
- const done = new Promise((resolve11) => {
36383
- resolveFeed = () => resolve11(result);
36480
+ const done = new Promise((resolve12) => {
36481
+ resolveFeed = () => resolve12(result);
36384
36482
  });
36385
36483
  const listener = (e) => {
36386
36484
  if (e.type === "slot-exit") {
@@ -36415,7 +36513,7 @@ var PoolSlotSession = class {
36415
36513
  /** Resolves when the process exits (immediately when it already has). */
36416
36514
  waitExit() {
36417
36515
  if (this.exited) return Promise.resolve(this.exitCode);
36418
- return new Promise((resolve11) => this.exitWaiters.push(resolve11));
36516
+ return new Promise((resolve12) => this.exitWaiters.push(resolve12));
36419
36517
  }
36420
36518
  /**
36421
36519
  * Resolves on the slot's init event (or its exit, or the timeout). The
@@ -36424,7 +36522,7 @@ var PoolSlotSession = class {
36424
36522
  */
36425
36523
  waitInit(timeoutMs) {
36426
36524
  if (this.exited) return Promise.resolve(null);
36427
- return new Promise((resolve11) => {
36525
+ return new Promise((resolve12) => {
36428
36526
  let timer = setTimeout(done, timeoutMs);
36429
36527
  const listener = (e) => {
36430
36528
  if (e.type === "system" && e.subtype === "init") {
@@ -36438,7 +36536,7 @@ var PoolSlotSession = class {
36438
36536
  if (!timer) return;
36439
36537
  clearTimeout(timer);
36440
36538
  timer = null;
36441
- resolve11(e ?? null);
36539
+ resolve12(e ?? null);
36442
36540
  }
36443
36541
  this.listeners.add(listener);
36444
36542
  });
@@ -36467,20 +36565,20 @@ function routerUsageTail(file) {
36467
36565
  }
36468
36566
  }
36469
36567
  function readBody(req, max = 8 * 1024 * 1024) {
36470
- return new Promise((resolve11) => {
36568
+ return new Promise((resolve12) => {
36471
36569
  const chunks = [];
36472
36570
  let size = 0;
36473
36571
  req.on("data", (c) => {
36474
36572
  size += c.length;
36475
36573
  if (size > max) {
36476
- resolve11(null);
36574
+ resolve12(null);
36477
36575
  req.destroy();
36478
36576
  return;
36479
36577
  }
36480
36578
  chunks.push(c);
36481
36579
  });
36482
- req.on("end", () => resolve11(Buffer.concat(chunks).toString("utf8")));
36483
- req.on("error", () => resolve11(null));
36580
+ req.on("end", () => resolve12(Buffer.concat(chunks).toString("utf8")));
36581
+ req.on("error", () => resolve12(null));
36484
36582
  });
36485
36583
  }
36486
36584
  function sendJson(res, status, body) {
@@ -37249,7 +37347,7 @@ function createPoolHost(opts = {}) {
37249
37347
  }
37250
37348
  for (const list of [...spares.values()]) for (const e of [...list]) discardSpare(e, "host shutdown");
37251
37349
  persist();
37252
- await new Promise((resolve11) => server.close(() => resolve11()));
37350
+ await new Promise((resolve12) => server.close(() => resolve12()));
37253
37351
  };
37254
37352
  const reapSlots = () => {
37255
37353
  let n = 0;
@@ -37313,9 +37411,9 @@ function createPoolHost(opts = {}) {
37313
37411
  return true;
37314
37412
  }
37315
37413
  clearReloadMarker(logDir2);
37316
- await new Promise((resolve11) => {
37317
- server.once("error", () => resolve11());
37318
- server.listen(port2, LOOPBACK_HOST, () => resolve11());
37414
+ await new Promise((resolve12) => {
37415
+ server.once("error", () => resolve12());
37416
+ server.listen(port2, LOOPBACK_HOST, () => resolve12());
37319
37417
  });
37320
37418
  appendLedger(ledger, "POOL-HOST-RELOAD-FAILED", { pid: process.pid, bundle: opts.bundlePath, note: why });
37321
37419
  reloading = false;
@@ -37445,7 +37543,7 @@ var listen = () => {
37445
37543
  host.listening();
37446
37544
  if (logDir) {
37447
37545
  mkdirSync42(logDir, { recursive: true });
37448
- writeFileSync36(poolPidPath(logDir), `${process.pid}
37546
+ writeFileSync33(poolPidPath(logDir), `${process.pid}
37449
37547
  `, "utf8");
37450
37548
  }
37451
37549
  process.stderr.write(`pai worker pool host listening on ${loopbackUrl(host.port)} (cwd ${host.logDir})