@tekmidian/pai 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +67 -5
  3. package/dist/aibroker-client-BxzeEHPF.mjs +3 -0
  4. package/dist/{aibroker-client-CXEYBzbf.mjs → aibroker-client-CQPGqLxL.mjs} +1 -1
  5. package/dist/atomic-file-BorMa4T3.mjs +21 -0
  6. package/dist/{auto-route-D5SXrMpB.mjs → auto-route-B4azPk4l.mjs} +3 -3
  7. package/dist/auto-route-BjoMHKyI.mjs +11 -0
  8. package/dist/budget-Dod6rnA9.mjs +15 -0
  9. package/dist/{caller-identity-CVTuiLSs.mjs → caller-identity-yLFb7CKq.mjs} +6 -5
  10. package/dist/{capacity-DaXrVj3J.mjs → capacity-DEveQdFV.mjs} +3 -3
  11. package/dist/{chain-BcQlIlEd.mjs → chain-D-yvET_y.mjs} +5 -5
  12. package/dist/cli/index.mjs +1621 -357
  13. package/dist/cockpit-actions-BWunx3rY.mjs +20 -0
  14. package/dist/{cockpit-actions-ODmt8yF9.mjs → cockpit-actions-C8GlTzts.mjs} +84 -42
  15. package/dist/cockpit-memory-vTlFWV7F.mjs +20 -0
  16. package/dist/{config-BSXKyeJ1.mjs → config-Bu1_vbY8.mjs} +42 -3
  17. package/dist/{config-B955yYmo.mjs → config-Cxi-aBf4.mjs} +2 -2
  18. package/dist/{config-TaWmdTLx.mjs → config-DtENJ6cL.mjs} +1 -1
  19. package/dist/{config-D5chi2LO.mjs → config-XpZWOYOG.mjs} +2 -2
  20. package/dist/{controls-BGkK_Bdi.mjs → controls-BcKFHeG1.mjs} +37 -22
  21. package/dist/daemon/index.mjs +43 -42
  22. package/dist/{daemon-CorGh6Ub.mjs → daemon-ColVHwGZ.mjs} +103 -55
  23. package/dist/daemon-N7WhYi6I.mjs +45 -0
  24. package/dist/daemon-mcp/index.mjs +40 -39
  25. package/dist/{define-DGFu-sCf.mjs → define-CjJsmq-6.mjs} +1 -1
  26. package/dist/{detect-C1d5cUkT.mjs → detect-9CZNO0yf.mjs} +2 -2
  27. package/dist/detect-D1ziFFfA.mjs +10 -0
  28. package/dist/{embed-pass-CeQD8kRE.mjs → embed-pass-DIWjA68P.mjs} +5 -5
  29. package/dist/{embedding-gate-BHuBsgHD.mjs → embedding-gate-6rZrWRXa.mjs} +5 -5
  30. package/dist/{embedding-gate-Z7CJSOJk.mjs → embedding-gate-Cnk4YCyX.mjs} +3 -3
  31. package/dist/{embeddings-D4t6L-EH.mjs → embeddings-BVq3esBF.mjs} +1 -1
  32. package/dist/{embeddings-OF9Pt4by.mjs → embeddings-CIkJBKd-.mjs} +1 -1
  33. package/dist/{endreason-x1KOSrcO.mjs → endreason-C577xIQz.mjs} +7 -6
  34. package/dist/{env-DArqGq-Z.mjs → env-BE8mrsxr.mjs} +1 -1
  35. package/dist/factory-Bsib-qDG.mjs +9 -0
  36. package/dist/{factory-BtjbQ0np.mjs → factory-DjAAsqr_.mjs} +15 -13
  37. package/dist/{fallback-BIyEpPsQ.mjs → fallback-DFlItw1Z.mjs} +5 -5
  38. package/dist/{fmt-age-BiSHrTKN.mjs → fmt-age-ByDkvkoU.mjs} +1 -1
  39. package/dist/{health-C6jZWvRG.mjs → health-Dnym-qcT.mjs} +4 -4
  40. package/dist/{helpers-DFmYRCOa.mjs → helpers-BD6V-p9w.mjs} +2 -2
  41. package/dist/helpers-CMGjy_0N.mjs +10 -0
  42. package/dist/{helpers-CJpb_MNB.mjs → helpers-CRuBUas3.mjs} +87 -38
  43. package/dist/hooks/capture-all-events.mjs +52 -11
  44. package/dist/hooks/capture-session-summary.mjs +64 -47
  45. package/dist/hooks/capture-tool-output.mjs +49 -8
  46. package/dist/hooks/context-compression-hook.mjs +30 -10
  47. package/dist/hooks/initialize-session.mjs +1 -0
  48. package/dist/hooks/load-core-context.mjs +1 -1
  49. package/dist/hooks/load-project-context.mjs +32 -29
  50. package/dist/hooks/security-validator.mjs +45 -13
  51. package/dist/hooks/stop-hook.mjs +54 -16
  52. package/dist/hooks/supervision-banner.mjs +9 -0
  53. package/dist/hooks/sync-todo-to-md.mjs +147 -113
  54. package/dist/hooks/worker-edit-repair.mjs +2 -1
  55. package/dist/hooks/worker-guard.mjs +40 -16
  56. package/dist/hooks/worker-note.mjs +12 -5
  57. package/dist/hooks/worker-path-repair.mjs +1 -1
  58. package/dist/hooks/worker-pool-host.mjs +214 -116
  59. package/dist/hooks/worker-status-line.mjs +195 -114
  60. package/dist/index.d.mts +18 -0
  61. package/dist/index.mjs +12 -12
  62. package/dist/{indexer-backend-BM2CUSu8.mjs → indexer-backend-_a6UNhXJ.mjs} +149 -96
  63. package/dist/{ipc-client-BMqWw_gv.mjs → ipc-client-CaiGJnSM.mjs} +1 -1
  64. package/dist/{ipc-client-YYDD6zzU.mjs → ipc-client-ZRmDKd5Z.mjs} +1 -1
  65. package/dist/kill-tree-BG7dRVtp.mjs +10 -0
  66. package/dist/{kill-tree-BjYz5BxK.mjs → kill-tree-EWYaEk5v.mjs} +8 -8
  67. package/dist/{launch-CLp0OJxV.mjs → launch-CXVlZjHt.mjs} +8 -8
  68. package/dist/{launch-DgqQdAjI.mjs → launch-Jh5NVeNe.mjs} +3 -3
  69. package/dist/local-candidate-DLdwQt0s.mjs +112 -0
  70. package/dist/local-instances-DOxSgT_L.mjs +210 -0
  71. package/dist/local-instances-ZeRkkuS5.mjs +6 -0
  72. package/dist/{local-tiers-DPZYqv9m.mjs → local-tiers-BE4jGaMa.mjs} +2 -2
  73. package/dist/{local-tiers-DnBIAkbK.mjs → local-tiers-DNMI5W86.mjs} +3 -3
  74. package/dist/{main-config-ops-C0SflOWk.mjs → main-config-ops-BEMpuhDz.mjs} +3 -3
  75. package/dist/{main-resolver-DVPpSWVy.mjs → main-resolver-3Ns1HPmS.mjs} +18 -17
  76. package/dist/{migrate-BUJHadA8.mjs → migrate-DrA_OwlZ.mjs} +45 -14
  77. package/dist/min-max-DrSRUaWQ.mjs +16 -0
  78. package/dist/{model-inventory-Dasber3S.mjs → model-inventory-BFVSNFT3.mjs} +13 -12
  79. package/dist/{models-add-Bt7aUHDs.mjs → models-add-BtB3Se6f.mjs} +39 -38
  80. package/dist/operator-BTqvTIc8.mjs +7 -0
  81. package/dist/{operator-DZxcP-g8.mjs → operator-CyuB3aVw.mjs} +3 -3
  82. package/dist/{pai-marker-kIYuNt3c.mjs → pai-marker-DurzIbw8.mjs} +7 -6
  83. package/dist/{pane-audit-OGYrOAik.mjs → pane-audit-BQytYa60.mjs} +7 -7
  84. package/dist/{paths-DoRuFc60.mjs → paths-CFHTloSe.mjs} +3 -3
  85. package/dist/{paths-DoIyRnhx.mjs → paths-CHifubDh.mjs} +3 -3
  86. package/dist/{planner-DLGOYlVb.mjs → planner-BM27GBfC.mjs} +31 -30
  87. package/dist/{pool-CZ5MZaXg.mjs → pool-BRvoOkv6.mjs} +3 -3
  88. package/dist/{pool-cli-BxNSPzzY.mjs → pool-cli-B_YR8_Gl.mjs} +5 -5
  89. package/dist/{pool-cli-CbJfl37y.mjs → pool-cli-DkZTAlSW.mjs} +6 -6
  90. package/dist/postgres-BdBNkL_l.mjs +7 -0
  91. package/dist/{postgres-CDnd_k5f.mjs → postgres-C6ti4haA.mjs} +55 -34
  92. package/dist/{project-setup-DM4npnL3.mjs → project-setup-CfpApz5o.mjs} +131 -74
  93. package/dist/providers-BeDiVEb-.mjs +16 -0
  94. package/dist/{providers-UsKtLcUR.mjs → providers-CblTFrhz.mjs} +6 -6
  95. package/dist/{query-feedback-I-txSnld.mjs → query-feedback-BRfPtqki.mjs} +2 -2
  96. package/dist/registrable-C7b6givx.mjs +9 -0
  97. package/dist/{registrable-LrRIVYQc.mjs → registrable-Uzgmfyhz.mjs} +4 -4
  98. package/dist/render-Cc2j5QG9.mjs +13 -0
  99. package/dist/{render-BDbb4CF-.mjs → render-CwIrgxLi.mjs} +8 -8
  100. package/dist/{reranker-B4r4vykM.mjs → reranker-8g6xMwP7.mjs} +1 -1
  101. package/dist/{reranker-DxxMCtA0.mjs → reranker-CqCbpGnX.mjs} +1 -1
  102. package/dist/{root-BMeJuHOb.mjs → root-BWy0c2Lq.mjs} +11 -11
  103. package/dist/root-wC_6Fx0B.mjs +36 -0
  104. package/dist/route-table-B7zpoypi.mjs +15 -0
  105. package/dist/{router-L8Nu-OHF.mjs → router-CQSc3lk3.mjs} +17 -7
  106. package/dist/{router-D6Ec6Fid.mjs → router-DwHJRgG9.mjs} +1 -1
  107. package/dist/{routing-CUyiglfu.mjs → routing-BAAST9vT.mjs} +27 -308
  108. package/dist/{routing-ZuGlc0ge.mjs → routing-CENt4HH1.mjs} +13 -12
  109. package/dist/{run-ulAi5dFD.mjs → run-6Q9kCPem.mjs} +35 -33
  110. package/dist/{scan-B7I0gPe-.mjs → scan-ZQWm-_se.mjs} +6 -6
  111. package/dist/{local-candidate-jOjTNlOL.mjs → scheduler-CtUyWJ3O.mjs} +7 -109
  112. package/dist/scheduler-dmHXoRvm.mjs +3 -0
  113. package/dist/{scope-D5VSQxe4.mjs → scope-D-h6F6DN.mjs} +4 -4
  114. package/dist/{search-CPoE0830.mjs → search-RSyeQqj1.mjs} +18 -18
  115. package/dist/session-Bok2PqRS.mjs +35 -0
  116. package/dist/{session-CNXF6DLP.mjs → session-DVUExUnX.mjs} +55 -31
  117. package/dist/session-scan-BJI_ZO8M.mjs +9 -0
  118. package/dist/{session-scan-BDLEc4w1.mjs → session-scan-W-gbwJHM.mjs} +6 -6
  119. package/dist/{sources-CjhUKKtO.mjs → sources-ESUkZaWv.mjs} +1 -1
  120. package/dist/{status-DYydKQUI.mjs → status-Dm4dYciN.mjs} +4 -4
  121. package/dist/{status-CvVi9cDf.mjs → status-ggJ7lgVg.mjs} +17 -9
  122. package/dist/{stop-words-SdSL1WKH.mjs → stop-words-DSEYQdNe.mjs} +1 -1
  123. package/dist/{test-isolation-CoDeOVXb.mjs → test-isolation-lqSmYxr0.mjs} +1 -1
  124. package/dist/{timeouts-OwEONmc8.mjs → timeouts-1MLooEBB.mjs} +1 -1
  125. package/dist/{tool-errors-AeRQuG3Y.mjs → tool-errors-7E13StWd.mjs} +4 -3
  126. package/dist/{tool-errors-R5E0fCgf.mjs → tool-errors-CJWODvlo.mjs} +6 -6
  127. package/dist/{viewer-DtWj5Vti.mjs → viewer-DcpJwGKE.mjs} +15 -15
  128. package/dist/viewer-MWBVJP3u.mjs +22 -0
  129. package/dist/{wait-BMUR-U-U.mjs → wait-ByV0OyMZ.mjs} +3 -3
  130. package/dist/{worker-config-BLqa1yiD.mjs → worker-config-BDYNxbYz.mjs} +294 -92
  131. package/dist/worker-config-gmAq_-rI.mjs +41 -0
  132. package/dist/{workers-config-DEI9lrV4.mjs → workers-config-f8KrkY4L.mjs} +2 -2
  133. package/dist/{worktree-zmRf556h.mjs → worktree-CrnOqTBW.mjs} +37 -7
  134. package/dist/{zettelkasten-nigq7fqs.mjs → zettelkasten-B_rRRRvD.mjs} +5 -5
  135. package/dist/{zettelkasten-Cr_Xj0mG.mjs → zettelkasten-BzMm8REH.mjs} +29 -19
  136. package/docs/README.md +2 -0
  137. package/docs/cockpit.md +10 -4
  138. package/docs/commands/README.md +4 -4
  139. package/docs/commands/backup.md +2 -0
  140. package/docs/commands/install.md +29 -4
  141. package/docs/commands/providers.md +1 -1
  142. package/docs/commands/restore.md +4 -0
  143. package/docs/commands/setup.md +29 -4
  144. package/docs/commands/worker.md +1 -1
  145. package/docs/config.md +2 -0
  146. package/docs/features.md +299 -0
  147. package/docs/images/architecture.drawio +51 -0
  148. package/docs/images/architecture.svg +3 -0
  149. package/docs/images/cockpit-01-system-tokens.jpg +0 -0
  150. package/docs/images/cockpit-02-totals-cache.jpg +0 -0
  151. package/docs/images/cockpit-03-local-servers-models-pool.jpg +0 -0
  152. package/docs/images/cockpit-04-workers-memory.jpg +0 -0
  153. package/docs/images/cockpit-05-performance.jpg +0 -0
  154. package/docs/images/cockpit-06-runs-speed-routing.jpg +0 -0
  155. package/docs/images/cockpit-07-settings-registry.jpg +0 -0
  156. package/docs/install/index.md +29 -0
  157. package/docs/three-tier-coding.md +1 -1
  158. package/gemini-extension.json +1 -1
  159. package/package.json +1 -5
  160. package/pai-plugin.json +1 -1
  161. package/plugins/context-preservation/plugin.json +1 -1
  162. package/plugins/core/plugin.json +1 -1
  163. package/plugins/core/skills/setup/SKILL.md +41 -9
  164. package/plugins/creative/plugin.json +1 -1
  165. package/plugins/observability/plugin.json +1 -1
  166. package/plugins/productivity/plugin.json +1 -1
  167. package/plugins/semantic-search/plugin.json +1 -1
  168. package/plugins/ui/plugin.json +1 -1
  169. package/plugins/zettelkasten/plugin.json +1 -1
  170. package/src/hooks/session-autosave.sh +8 -1
  171. package/src/hooks/session-stop.sh +8 -1
  172. package/src/hooks/ts/capture-all-events.ts +7 -12
  173. package/src/hooks/ts/lib/context-fill.ts +2 -1
  174. package/src/hooks/ts/lib/path-repair.ts +1 -1
  175. package/src/hooks/ts/lib/project-utils/notify.ts +1 -0
  176. package/src/hooks/ts/lib/project-utils/session-notes.ts +23 -6
  177. package/src/hooks/ts/lib/raw-capture.ts +36 -0
  178. package/src/hooks/ts/lib/session-summary.ts +129 -0
  179. package/src/hooks/ts/lib/todo-sync.ts +120 -0
  180. package/src/hooks/ts/lib/worker-git-guard.ts +1 -1
  181. package/src/hooks/ts/post-tool-use/capture-tool-output.ts +6 -10
  182. package/src/hooks/ts/post-tool-use/sync-todo-to-md.ts +5 -105
  183. package/src/hooks/ts/pre-compact/context-compression-hook.ts +1 -1
  184. package/src/hooks/ts/pre-tool-use/security-validator.ts +35 -14
  185. package/src/hooks/ts/session-end/capture-session-summary.ts +20 -128
  186. package/src/hooks/ts/session-start/load-core-context.ts +3 -3
  187. package/src/hooks/ts/session-start/load-project-context.ts +18 -22
  188. package/src/hooks/ts/stop/stop-hook.ts +13 -5
  189. package/src/hooks/ztk-auto.sh +7 -2
  190. package/dist/aibroker-client-JjE74jo0.mjs +0 -3
  191. package/dist/auto-route-BRk8NEFv.mjs +0 -11
  192. package/dist/budget-DuhQ2zzG.mjs +0 -14
  193. package/dist/cockpit-actions-DcQ-ucU8.mjs +0 -19
  194. package/dist/cockpit-memory-KV45PPO2.mjs +0 -19
  195. package/dist/daemon-C7yt_ptC.mjs +0 -44
  196. package/dist/detect-DRUkmHnb.mjs +0 -10
  197. package/dist/factory-DAGG9_n8.mjs +0 -9
  198. package/dist/helpers-DPJEHPq6.mjs +0 -10
  199. package/dist/kill-tree-LV0Q7Mte.mjs +0 -10
  200. package/dist/operator-CfL0HiBK.mjs +0 -7
  201. package/dist/postgres-DgqWyqhN.mjs +0 -7
  202. package/dist/providers-CTu2s1z2.mjs +0 -15
  203. package/dist/registrable-D9aNZOTh.mjs +0 -9
  204. package/dist/render-BSfVlYHj.mjs +0 -13
  205. package/dist/root-xI9DqVIe.mjs +0 -35
  206. package/dist/route-table-HjvnLVEU.mjs +0 -14
  207. package/dist/session-BJHzmUg2.mjs +0 -34
  208. package/dist/session-scan-YORKE1NO.mjs +0 -9
  209. package/dist/viewer-B8709jDN.mjs +0 -22
  210. package/dist/worker-config-D8tRuvo7.mjs +0 -40
  211. package/docs/images/cockpit-limits-routing.jpg +0 -0
  212. package/docs/images/cockpit-models.jpg +0 -0
  213. package/docs/images/cockpit-usage.jpg +0 -0
  214. package/docs/images/cockpit-workers-system.jpg +0 -0
  215. package/scripts/build-docs.mjs +0 -41
  216. package/scripts/build-hooks.mjs +0 -311
  217. package/scripts/build-skill-stubs.mjs +0 -216
  218. package/scripts/copy-defaults.mjs +0 -46
@@ -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}`})`);
@@ -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);
@@ -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) {
@@ -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
 
@@ -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;
@@ -22197,11 +22266,19 @@ 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}"`;
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
+ ];
22203
22280
  return new Promise((resolve11) => {
22204
- const child = spawn("osascript", ["-e", script], {
22281
+ const child = spawn("osascript", args, {
22205
22282
  detached: true,
22206
22283
  stdio: "ignore"
22207
22284
  });
@@ -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) {
@@ -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];
@@ -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();
@@ -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,7 +28656,7 @@ 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";
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";
28574
28660
  import { basename as basename8, dirname as dirname22, isAbsolute as isAbsolute2, join as join43, resolve as resolve6, sep as sep2 } from "node:path";
28575
28661
  import { tmpdir as tmpdir3, platform } from "node:os";
28576
28662
  function isSlotWorktree(dir) {
@@ -28701,7 +28787,7 @@ function ensureScratchExcluded(cwd) {
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);
@@ -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 {
@@ -29802,6 +29897,7 @@ function gcWorktrees(logDir2, olderThanHours = 24, dryRun = false, now = Date.no
29802
29897
  const owned = new Set(statuses.map((s) => ownedTree(s)?.dir).filter((d) => !!d).map((d) => resolve6(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) });
@@ -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;
@@ -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";
@@ -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}`;
@@ -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) {
@@ -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";
@@ -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({
@@ -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");
@@ -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++) {
@@ -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,7 +36282,7 @@ 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";
36285
+ import { existsSync as existsSync55, mkdirSync as mkdirSync40, writeFileSync as writeFileSync32, realpathSync as realpathSync4 } from "node:fs";
36188
36286
  import { dirname as dirname27, join as join56, resolve as resolve10, isAbsolute as isAbsolute3 } from "node:path";
36189
36287
  function slotsDir(logDir2) {
36190
36288
  return join56(logDir2, "slots");
@@ -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;
@@ -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})