@tekmidian/pai 0.42.5 → 0.43.0

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 (297) hide show
  1. package/ARCHITECTURE.md +9 -9
  2. package/README.md +26 -8
  3. package/dist/{aibroker-client-BP74gGwD.mjs → aibroker-client-Bn9SnGMa.mjs} +3 -3
  4. package/dist/{aibroker-client-BP74gGwD.mjs.map → aibroker-client-Bn9SnGMa.mjs.map} +1 -1
  5. package/dist/{aibroker-client-C6m71p6O.mjs → aibroker-client-D5NT0S1N.mjs} +1 -1
  6. package/dist/{auto-route-_5zzJz5q.mjs → auto-route-CcD0OWWB.mjs} +4 -4
  7. package/dist/{auto-route-_5zzJz5q.mjs.map → auto-route-CcD0OWWB.mjs.map} +1 -1
  8. package/dist/{chain-DTII7xeL.mjs → chain-CEC1a5mX.mjs} +5 -4
  9. package/dist/{chain-DTII7xeL.mjs.map → chain-CEC1a5mX.mjs.map} +1 -1
  10. package/dist/cli/index.mjs +23 -21
  11. package/dist/cli/index.mjs.map +1 -1
  12. package/dist/cli/program.d.mts.map +1 -1
  13. package/dist/cli/program.mjs +23 -21
  14. package/dist/{clusters-j0ZuNYp9.mjs → clusters-Cw_P6lO-.mjs} +2 -2
  15. package/dist/{clusters-j0ZuNYp9.mjs.map → clusters-Cw_P6lO-.mjs.map} +1 -1
  16. package/dist/{config-B64vFg14.mjs → config-DCu8THKi.mjs} +41 -9
  17. package/dist/{config-B64vFg14.mjs.map → config-DCu8THKi.mjs.map} +1 -1
  18. package/dist/config-DeqFqa1N.mjs +3 -0
  19. package/dist/config-DxMZjpvY.mjs +1289 -0
  20. package/dist/config-DxMZjpvY.mjs.map +1 -0
  21. package/dist/context-handover-cache-B9NKSjwR.mjs +3242 -0
  22. package/dist/context-handover-cache-B9NKSjwR.mjs.map +1 -0
  23. package/dist/daemon/index.mjs +23 -22
  24. package/dist/daemon/index.mjs.map +1 -1
  25. package/dist/{daemon-B8N1egl0.mjs → daemon-BhldpFvO.mjs} +52 -38
  26. package/dist/daemon-BhldpFvO.mjs.map +1 -0
  27. package/dist/daemon-QIvCXB5f.mjs +24 -0
  28. package/dist/daemon-mcp/index.mjs +144 -117
  29. package/dist/daemon-mcp/index.mjs.map +1 -1
  30. package/dist/db-BOBfewFH.mjs +3 -0
  31. package/dist/{db-a1ixZQjr.mjs → db-DJ8rk0VM.mjs} +15 -6
  32. package/dist/{db-a1ixZQjr.mjs.map → db-DJ8rk0VM.mjs.map} +1 -1
  33. package/dist/db-DbY2O8QO.mjs +3 -0
  34. package/dist/{db-Ca5qfsMC.mjs → db-Ddns80yf.mjs} +15 -6
  35. package/dist/{db-Ca5qfsMC.mjs.map → db-Ddns80yf.mjs.map} +1 -1
  36. package/dist/{detect-CdaA48EI.mjs → detect-Bf2z-oKB.mjs} +1 -1
  37. package/dist/{detect-CdaA48EI.mjs.map → detect-Bf2z-oKB.mjs.map} +1 -1
  38. package/dist/detector-CkwkXuGh.mjs +5 -0
  39. package/dist/{detector-C73Nxm94.mjs → detector-DWXkeTlk.mjs} +2 -2
  40. package/dist/{detector-C73Nxm94.mjs.map → detector-DWXkeTlk.mjs.map} +1 -1
  41. package/dist/{embeddings-CEBGrzwu.mjs → embeddings-ClqKtLZ8.mjs} +1 -1
  42. package/dist/{embeddings-DOLZnT1X.mjs → embeddings-DvRKcQyt.mjs} +1 -1
  43. package/dist/{embeddings-DOLZnT1X.mjs.map → embeddings-DvRKcQyt.mjs.map} +1 -1
  44. package/dist/factory-47Qf_df7.mjs +3 -0
  45. package/dist/{factory-DEb9NmHJ.mjs → factory-DNYAqjH0.mjs} +8 -8
  46. package/dist/{factory-DEb9NmHJ.mjs.map → factory-DNYAqjH0.mjs.map} +1 -1
  47. package/dist/{fallback-oJl3BaIN.mjs → fallback-BQJ8PbCK.mjs} +185 -123
  48. package/dist/fallback-BQJ8PbCK.mjs.map +1 -0
  49. package/dist/{helpers-IjZkXBhj.mjs → helpers-crDEr6S2.mjs} +1 -1
  50. package/dist/{helpers-IjZkXBhj.mjs.map → helpers-crDEr6S2.mjs.map} +1 -1
  51. package/dist/hooks/capture-all-events.mjs +117 -34
  52. package/dist/hooks/capture-all-events.mjs.map +4 -4
  53. package/dist/hooks/capture-session-summary.mjs +110 -33
  54. package/dist/hooks/capture-session-summary.mjs.map +4 -4
  55. package/dist/hooks/capture-tool-output.mjs +105 -28
  56. package/dist/hooks/capture-tool-output.mjs.map +4 -4
  57. package/dist/hooks/cleanup-session-files.mjs +54 -13
  58. package/dist/hooks/cleanup-session-files.mjs.map +2 -2
  59. package/dist/hooks/context-compression-hook.mjs +7565 -122
  60. package/dist/hooks/context-compression-hook.mjs.map +4 -4
  61. package/dist/hooks/initialize-session.mjs +55 -14
  62. package/dist/hooks/initialize-session.mjs.map +2 -2
  63. package/dist/hooks/inject-observations.mjs +79 -18
  64. package/dist/hooks/inject-observations.mjs.map +3 -3
  65. package/dist/hooks/load-core-context.mjs +55 -14
  66. package/dist/hooks/load-core-context.mjs.map +2 -2
  67. package/dist/hooks/load-project-context.mjs +207 -122
  68. package/dist/hooks/load-project-context.mjs.map +4 -4
  69. package/dist/hooks/mcp-deferred-gate.mjs +54 -13
  70. package/dist/hooks/mcp-deferred-gate.mjs.map +2 -2
  71. package/dist/hooks/mcp-deferred-reminder.mjs +9 -0
  72. package/dist/hooks/mcp-deferred-reminder.mjs.map +3 -3
  73. package/dist/hooks/observe.mjs +54 -13
  74. package/dist/hooks/observe.mjs.map +2 -2
  75. package/dist/hooks/post-compact-inject.mjs +7419 -16
  76. package/dist/hooks/post-compact-inject.mjs.map +4 -4
  77. package/dist/hooks/route-agents-to-worker.mjs +7778 -171
  78. package/dist/hooks/route-agents-to-worker.mjs.map +4 -4
  79. package/dist/hooks/route-edits-to-worker.mjs +90 -0
  80. package/dist/hooks/route-edits-to-worker.mjs.map +7 -0
  81. package/dist/hooks/security-validator.mjs +147 -6
  82. package/dist/hooks/security-validator.mjs.map +4 -4
  83. package/dist/hooks/session-commands.mjs +9 -0
  84. package/dist/hooks/session-commands.mjs.map +3 -3
  85. package/dist/hooks/stop-hook.mjs +182 -105
  86. package/dist/hooks/stop-hook.mjs.map +4 -4
  87. package/dist/hooks/subagent-stop-hook.mjs +3 -0
  88. package/dist/hooks/subagent-stop-hook.mjs.map +1 -1
  89. package/dist/hooks/sync-todo-to-md.mjs +54 -13
  90. package/dist/hooks/sync-todo-to-md.mjs.map +2 -2
  91. package/dist/hooks/update-tab-on-action.mjs +3 -0
  92. package/dist/hooks/update-tab-on-action.mjs.map +1 -1
  93. package/dist/hooks/update-tab-titles.mjs +3 -0
  94. package/dist/hooks/update-tab-titles.mjs.map +1 -1
  95. package/dist/hooks/whisper-reinject.mjs +11 -0
  96. package/dist/hooks/whisper-reinject.mjs.map +3 -3
  97. package/dist/hooks/whisper-rules.mjs +134 -29
  98. package/dist/hooks/whisper-rules.mjs.map +4 -4
  99. package/dist/hooks/worker-proxy.mjs +7737 -117
  100. package/dist/hooks/worker-proxy.mjs.map +4 -4
  101. package/dist/hooks/worker-status-line.mjs +7883 -169
  102. package/dist/hooks/worker-status-line.mjs.map +4 -4
  103. package/dist/hooks/worker-supervision.mjs +7721 -115
  104. package/dist/hooks/worker-supervision.mjs.map +4 -4
  105. package/dist/index.d.mts +4 -2
  106. package/dist/index.d.mts.map +1 -1
  107. package/dist/index.mjs +10 -10
  108. package/dist/{indexer-backend-BPTzKFZU.mjs → indexer-backend-CdvCJCkD.mjs} +3 -3
  109. package/dist/{indexer-backend-BPTzKFZU.mjs.map → indexer-backend-CdvCJCkD.mjs.map} +1 -1
  110. package/dist/{ipc-client-BmypMNYk.mjs → ipc-client-C6NryMMb.mjs} +2 -2
  111. package/dist/{ipc-client-BmypMNYk.mjs.map → ipc-client-C6NryMMb.mjs.map} +1 -1
  112. package/dist/{kg-entity-r8duqhi9.mjs → kg-entity-BSjM5xZh.mjs} +1 -1
  113. package/dist/{kg-entity-r8duqhi9.mjs.map → kg-entity-BSjM5xZh.mjs.map} +1 -1
  114. package/dist/{latent-ideas-CtSca4qG.mjs → latent-ideas-BfL4nCQ3.mjs} +4 -4
  115. package/dist/{latent-ideas-CtSca4qG.mjs.map → latent-ideas-BfL4nCQ3.mjs.map} +1 -1
  116. package/dist/{link-boost-Bucnz3n8.mjs → link-boost-C5PaNdzm.mjs} +1 -1
  117. package/dist/{link-boost-Bucnz3n8.mjs.map → link-boost-C5PaNdzm.mjs.map} +1 -1
  118. package/dist/main-resolver-CnfnWa8C.mjs +7 -0
  119. package/dist/{main-resolver-DnkxPYkr.mjs → main-resolver-DvYu9jbl.mjs} +21 -11
  120. package/dist/main-resolver-DvYu9jbl.mjs.map +1 -0
  121. package/dist/{migrate-Cjzeefn9.mjs → migrate-CfERwXhY.mjs} +2 -2
  122. package/dist/{migrate-Cjzeefn9.mjs.map → migrate-CfERwXhY.mjs.map} +1 -1
  123. package/dist/{neighborhood-CM7Jgb51.mjs → neighborhood-CETR_P4y.mjs} +2 -2
  124. package/dist/{neighborhood-CM7Jgb51.mjs.map → neighborhood-CETR_P4y.mjs.map} +1 -1
  125. package/dist/{note-context-DCwE2A-M.mjs → note-context-DCcRWBoN.mjs} +1 -1
  126. package/dist/{note-context-DCwE2A-M.mjs.map → note-context-DCcRWBoN.mjs.map} +1 -1
  127. package/dist/pai-home-ChAOupZc.mjs +164 -0
  128. package/dist/pai-home-ChAOupZc.mjs.map +1 -0
  129. package/dist/{pai-marker-CHtbJMwJ.mjs → pai-marker-B20KqhA8.mjs} +1 -1
  130. package/dist/{pai-marker-CHtbJMwJ.mjs.map → pai-marker-B20KqhA8.mjs.map} +1 -1
  131. package/dist/{planner-D5Ui7DAm.mjs → planner-BlKGgpWI.mjs} +7 -6
  132. package/dist/{planner-D5Ui7DAm.mjs.map → planner-BlKGgpWI.mjs.map} +1 -1
  133. package/dist/{postgres-CtOzfoQU.mjs → postgres-CUSXWgTG.mjs} +2 -2
  134. package/dist/{postgres-CtOzfoQU.mjs.map → postgres-CUSXWgTG.mjs.map} +1 -1
  135. package/dist/{program-zpoYnJGz.mjs → program-C5jRQ1kg.mjs} +8880 -5913
  136. package/dist/program-C5jRQ1kg.mjs.map +1 -0
  137. package/dist/query-feedback-C7rSfiXU.mjs +3 -0
  138. package/dist/{query-feedback-Dqz-HC__.mjs → query-feedback-CYyOGi3y.mjs} +20 -6
  139. package/dist/query-feedback-CYyOGi3y.mjs.map +1 -0
  140. package/dist/{reranker-CwTCNsgA.mjs → reranker-B5qUTamW.mjs} +1 -1
  141. package/dist/{reranker-xPm04PXx.mjs → reranker-HHmhZk6v.mjs} +1 -1
  142. package/dist/{reranker-xPm04PXx.mjs.map → reranker-HHmhZk6v.mjs.map} +1 -1
  143. package/dist/router-CremHKTI.mjs +3 -0
  144. package/dist/{router-DD6D4j31.mjs → router-DBAZfE7X.mjs} +2 -2
  145. package/dist/{router-DD6D4j31.mjs.map → router-DBAZfE7X.mjs.map} +1 -1
  146. package/dist/{run-D7K5UALn.mjs → run-ByBKowN5.mjs} +980 -247
  147. package/dist/run-ByBKowN5.mjs.map +1 -0
  148. package/dist/{runtime-paths-rni52zHX.mjs → runtime-paths-B0P1TvUr.mjs} +1 -1
  149. package/dist/{runtime-paths-rni52zHX.mjs.map → runtime-paths-B0P1TvUr.mjs.map} +1 -1
  150. package/dist/{search-Rpk1cSBC.mjs → search-B69cQwDB.mjs} +3 -3
  151. package/dist/{search-Rpk1cSBC.mjs.map → search-B69cQwDB.mjs.map} +1 -1
  152. package/dist/{search-CfPpJAWQ.mjs → search-fb-5ovj4.mjs} +2 -2
  153. package/dist/{server-D4vAieF4.mjs → server-Ch99xt5K.mjs} +15 -14
  154. package/dist/server-Ch99xt5K.mjs.map +1 -0
  155. package/dist/skills/Advisor/SKILL.md +3 -3
  156. package/dist/skills/Providers/SKILL.md +30 -0
  157. package/dist/skills/Reconstruct/SKILL.md +1 -1
  158. package/dist/skills/VaultContext/SKILL.md +1 -1
  159. package/dist/skills/Whisper/SKILL.md +3 -3
  160. package/dist/skills/Worker/SKILL.md +1 -1
  161. package/dist/{sources-CS43CpuS.mjs → sources-KBGEA_E6.mjs} +2 -2
  162. package/dist/{sources-CS43CpuS.mjs.map → sources-KBGEA_E6.mjs.map} +1 -1
  163. package/dist/{sqlite-Cq3gJcq9.mjs → sqlite-By6r2YhZ.mjs} +3 -3
  164. package/dist/{sqlite-Cq3gJcq9.mjs.map → sqlite-By6r2YhZ.mjs.map} +1 -1
  165. package/dist/{state-CY6I-Hnc.mjs → state-DnYGRmS7.mjs} +1 -1
  166. package/dist/{state-BRdB-Bf1.mjs → state-PJrgfDLW.mjs} +1 -1
  167. package/dist/{state-BRdB-Bf1.mjs.map → state-PJrgfDLW.mjs.map} +1 -1
  168. package/dist/{stop-words-Hfu8u22w.mjs → stop-words-BaMEGVeY.mjs} +1 -1
  169. package/dist/{stop-words-Hfu8u22w.mjs.map → stop-words-BaMEGVeY.mjs.map} +1 -1
  170. package/dist/{sync-BWbe8JTg.mjs → sync-Btcb6xA4.mjs} +3 -3
  171. package/dist/{sync-BWbe8JTg.mjs.map → sync-Btcb6xA4.mjs.map} +1 -1
  172. package/dist/{themes-B7h9YDiy.mjs → themes-BVoAnLZj.mjs} +3 -3
  173. package/dist/{themes-B7h9YDiy.mjs.map → themes-BVoAnLZj.mjs.map} +1 -1
  174. package/dist/{tools-BW3NLMPk.mjs → tools-CAG2sUjf.mjs} +4 -3
  175. package/dist/{tools-LlzcV_eK.mjs → tools-DiRC5glA.mjs} +30 -233
  176. package/dist/tools-DiRC5glA.mjs.map +1 -0
  177. package/dist/{trace-u4hT-pLD.mjs → trace-Cy8quQTm.mjs} +1 -1
  178. package/dist/{trace-u4hT-pLD.mjs.map → trace-Cy8quQTm.mjs.map} +1 -1
  179. package/dist/{utils-DhMex3Ox.mjs → utils-BD8g8oSf.mjs} +1 -1
  180. package/dist/{utils-9Err2RBW.mjs → utils-CJymHkYm.mjs} +1 -1
  181. package/dist/{utils-9Err2RBW.mjs.map → utils-CJymHkYm.mjs.map} +1 -1
  182. package/dist/{vault-indexer-mata9S7b.mjs → vault-indexer-C5i-OAyr.mjs} +2 -2
  183. package/dist/{vault-indexer-mata9S7b.mjs.map → vault-indexer-C5i-OAyr.mjs.map} +1 -1
  184. package/dist/wakeup-BfElduEU.mjs +231 -0
  185. package/dist/wakeup-BfElduEU.mjs.map +1 -0
  186. package/dist/work-queue-worker-BA5IDBwQ.mjs +567 -0
  187. package/dist/work-queue-worker-BA5IDBwQ.mjs.map +1 -0
  188. package/dist/work-queue-worker-DLM2wlqM.mjs +14 -0
  189. package/dist/{zettelkasten-F0D_XfQ4.mjs → zettelkasten-BBjA7GcP.mjs} +4 -4
  190. package/dist/{zettelkasten-F0D_XfQ4.mjs.map → zettelkasten-BBjA7GcP.mjs.map} +1 -1
  191. package/docs/commands/README.md +32 -3
  192. package/docs/commands/audit.md +113 -0
  193. package/docs/commands/backup.md +2 -2
  194. package/docs/commands/clear-names.md +1 -1
  195. package/docs/commands/config.md +59 -0
  196. package/docs/commands/daemon.md +1 -1
  197. package/docs/commands/db.md +1 -1
  198. package/docs/commands/end.md +1 -1
  199. package/docs/commands/help.md +1 -1
  200. package/docs/commands/identity.md +1 -1
  201. package/docs/commands/kg.md +1 -1
  202. package/docs/commands/launch.md +45 -0
  203. package/docs/commands/mcp.md +1 -1
  204. package/docs/commands/memory.md +3 -3
  205. package/docs/commands/notify.md +1 -1
  206. package/docs/commands/observation.md +1 -1
  207. package/docs/commands/obsidian.md +1 -1
  208. package/docs/commands/pause.md +1 -1
  209. package/docs/commands/project.md +46 -1
  210. package/docs/commands/projects.md +46 -1
  211. package/docs/commands/registry.md +1 -1
  212. package/docs/commands/restore.md +1 -1
  213. package/docs/commands/session.md +1 -1
  214. package/docs/commands/sessions.md +1 -1
  215. package/docs/commands/setup.md +1 -1
  216. package/docs/commands/shell-init.md +1 -1
  217. package/docs/commands/skill.md +1 -1
  218. package/docs/commands/task.md +1 -1
  219. package/docs/commands/topic.md +1 -1
  220. package/docs/commands/update.md +1 -1
  221. package/docs/commands/worker.md +97 -6
  222. package/docs/commands/zettel.md +1 -1
  223. package/docs/provider-abstraction.md +1 -1
  224. package/docs/provider-independence-details.md +8 -5
  225. package/docs/task-bus.md +1 -1
  226. package/docs/worker.md +136 -83
  227. package/docs/workers-config.md +446 -0
  228. package/package.json +4 -2
  229. package/scripts/build-hooks.mjs +58 -3
  230. package/src/hooks/pre-compact.sh +5 -2
  231. package/src/hooks/session-stop.sh +29 -4
  232. package/src/hooks/ts/capture-all-events.ts +3 -3
  233. package/src/hooks/ts/lib/advisor-budget.test.ts +98 -0
  234. package/src/hooks/ts/lib/advisor-budget.ts +90 -0
  235. package/src/hooks/ts/lib/agent-gate.test.ts +101 -0
  236. package/src/hooks/ts/lib/agent-gate.ts +112 -0
  237. package/src/hooks/ts/lib/context-fill.ts +2 -2
  238. package/src/hooks/ts/lib/edit-gate.test.ts +52 -0
  239. package/src/hooks/ts/lib/edit-gate.ts +51 -0
  240. package/src/hooks/ts/lib/mcp-deferred-reminder.test.ts +8 -0
  241. package/src/hooks/ts/lib/pai-paths.test.ts +93 -0
  242. package/src/hooks/ts/lib/pai-paths.ts +168 -24
  243. package/src/hooks/ts/lib/project-utils/index.ts +1 -0
  244. package/src/hooks/ts/lib/project-utils/paths.ts +5 -4
  245. package/src/hooks/ts/lib/project-utils.ts +1 -0
  246. package/src/hooks/ts/post-tool-use/capture-tool-output.ts +2 -2
  247. package/src/hooks/ts/post-tool-use/whisper-reinject.test.ts +55 -0
  248. package/src/hooks/ts/post-tool-use/whisper-reinject.ts +3 -0
  249. package/src/hooks/ts/pre-compact/context-compression-hook.ts +1 -1
  250. package/src/hooks/ts/pre-tool-use/route-agents-to-worker.ts +46 -99
  251. package/src/hooks/ts/pre-tool-use/route-edits-to-worker.test.ts +47 -0
  252. package/src/hooks/ts/pre-tool-use/route-edits-to-worker.ts +96 -0
  253. package/src/hooks/ts/pre-tool-use/security-validator.ts +2 -1
  254. package/src/hooks/ts/session-end/capture-session-summary.ts +4 -4
  255. package/src/hooks/ts/session-start/initialize-session.ts +3 -3
  256. package/src/hooks/ts/session-start/inject-observations.test.ts +56 -0
  257. package/src/hooks/ts/session-start/inject-observations.ts +28 -8
  258. package/src/hooks/ts/session-start/load-core-context.ts +4 -4
  259. package/src/hooks/ts/session-start/load-project-context.ts +2 -2
  260. package/src/hooks/ts/session-start/mcp-deferred-reminder.ts +2 -0
  261. package/src/hooks/ts/session-start/session-commands.ts +4 -0
  262. package/src/hooks/ts/session-start/session-start-worker-guard.test.ts +36 -0
  263. package/src/hooks/ts/stop/stop-hook.ts +6 -11
  264. package/src/hooks/ts/user-prompt/whisper-rules.test.ts +49 -0
  265. package/src/hooks/ts/user-prompt/whisper-rules.ts +88 -47
  266. package/src/hooks/ztk-auto.sh +28 -0
  267. package/src/hooks/ztk-auto.test.ts +72 -0
  268. package/src/hooks/ztk-passthrough.mjs +71 -0
  269. package/statusline-command.sh +277 -116
  270. package/templates/agent-prefs.example.md +8 -8
  271. package/templates/claude-md.template.md +1 -1
  272. package/templates/voices.example.json +3 -3
  273. package/dist/config-C_ErGddD.mjs +0 -3
  274. package/dist/config-_lQI_W08.mjs +0 -640
  275. package/dist/config-_lQI_W08.mjs.map +0 -1
  276. package/dist/context-handover-cache-pNFdBNrU.mjs +0 -1548
  277. package/dist/context-handover-cache-pNFdBNrU.mjs.map +0 -1
  278. package/dist/daemon-B8N1egl0.mjs.map +0 -1
  279. package/dist/daemon-DHfyoTlk.mjs +0 -23
  280. package/dist/db-O-cyAPfS.mjs +0 -3
  281. package/dist/db-XEwJbuGO.mjs +0 -3
  282. package/dist/detector-C-7KRi42.mjs +0 -5
  283. package/dist/factory-Dbo8yNPi.mjs +0 -3
  284. package/dist/fallback-oJl3BaIN.mjs.map +0 -1
  285. package/dist/main-resolver-BAfOMppW.mjs +0 -7
  286. package/dist/main-resolver-DnkxPYkr.mjs.map +0 -1
  287. package/dist/program-zpoYnJGz.mjs.map +0 -1
  288. package/dist/query-feedback-DGoVRaWD.mjs +0 -3
  289. package/dist/query-feedback-Dqz-HC__.mjs.map +0 -1
  290. package/dist/router-BTIGZR2_.mjs +0 -3
  291. package/dist/run-D7K5UALn.mjs.map +0 -1
  292. package/dist/server-D4vAieF4.mjs.map +0 -1
  293. package/dist/tools-LlzcV_eK.mjs.map +0 -1
  294. package/dist/work-queue-worker-AEmfVE0F.mjs +0 -14
  295. package/dist/work-queue-worker-DIT-VLSh.mjs +0 -2136
  296. package/dist/work-queue-worker-DIT-VLSh.mjs.map +0 -1
  297. /package/dist/{indexer-D7MvSQPY.mjs → indexer-C5Le7XE7.mjs} +0 -0
@@ -1,12 +1,43 @@
1
- import { C as readJsonStrict, _ as readWorkersSection, f as isModelCapability, g as providerKeyPath, h as providerCostTier, i as PROVIDER_TAGS, m as parseWorkersConfig, n as DEFAULT_LOG_DIR, o as WorkersConfigError, p as keysDir, r as MODEL_CAPABILITIES, t as ANTHROPIC_NATIVE, u as expandHome, v as resolveModelCapability, w as writeJsonAtomic, y as writeWorkersSection } from "./config-_lQI_W08.mjs";
2
- import { _ as workersLogDir, a as clearCooldown, c as probeQuota, l as quotaSkipThreshold, p as eventsPath, u as resolveTarget } from "./server-D4vAieF4.mjs";
3
- import { C as alive, E as isChatPane, F as shortText, O as loadStatuses, S as ageOf, T as contextPercent, a as parseWorkerReport, b as workerInScope, d as sayToWorker, f as workerDepth, g as currentTabKey, o as renderReport, u as readInbox, v as resolveSession, w as contextLabel, y as sessionTag } from "./run-D7K5UALn.mjs";
1
+ import { n as CONFIG_FILE } from "./config-DCu8THKi.mjs";
2
+ import { N as readJsonStrict, P as writeJsonAtomic, b as resolveProviderKey, f as isModelCapability, g as providerCostTier, h as nativeAnthropicProvider, i as PROVIDER_TAGS, k as workersYamlPath, m as maskKey, n as DEFAULT_LOG_DIR, o as WorkersConfigError, p as keysDir, r as MODEL_CAPABILITIES, t as ANTHROPIC_NATIVE, u as expandHome, v as readWorkersSection, x as writeWorkersSection, y as resolveModelCapability } from "./config-DxMZjpvY.mjs";
3
+ import { A as loadStatuses, C as UNLABELED, D as contextPercent, E as contextLabel, O as isChatPane, R as shortText, T as alive, a as parseWorkerReport, b as workerInScope, d as sayToWorker, f as workerDepth, g as currentTabKey, o as renderReport, u as readInbox, v as resolveSession, w as ageOf, y as sessionTag } from "./run-ByBKowN5.mjs";
4
+ import { _ as workersLogDir, a as clearCooldown, c as probeQuota, l as quotaSkipThreshold, p as eventsPath, u as resolveTarget } from "./server-Ch99xt5K.mjs";
4
5
  import { chmodSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, readSync, unlinkSync, writeFileSync } from "node:fs";
5
6
  import { homedir } from "node:os";
6
- import { basename, join, relative } from "node:path";
7
+ import { basename, join, relative, resolve } from "node:path";
7
8
  import { execFileSync, spawn } from "node:child_process";
8
9
  import { createInterface } from "node:readline";
9
10
 
11
+ //#region src/workers/specfile.ts
12
+ /**
13
+ * specfile.ts — `--spec <path>` reads a worker's prompt from a file (or stdin
14
+ * via `--spec -`) instead of an inline `-p '<prompt>'`, which has repeatedly
15
+ * died on shell quoting for anything long or multi-line.
16
+ */
17
+ /** The path a --spec value resolves to for display/recording; "-" (stdin) passes through unchanged. */
18
+ function resolveSpecPath(spec, cwd) {
19
+ return spec === "-" ? "-" : resolve(cwd, spec);
20
+ }
21
+ /** The prompt text a --spec value reads: the file's exact bytes, or stdin's. */
22
+ function readSpecPrompt(spec, cwd) {
23
+ if (spec === "-") {
24
+ let content;
25
+ try {
26
+ content = readFileSync(0, "utf8");
27
+ } catch (e) {
28
+ throw new Error(`--spec -: could not read stdin: ${e.message}`);
29
+ }
30
+ if (!content) throw new Error("--spec -: stdin was empty");
31
+ return content;
32
+ }
33
+ const path = resolveSpecPath(spec, cwd);
34
+ if (!existsSync(path)) throw new Error(`--spec: file not found: ${path}`);
35
+ const content = readFileSync(path, "utf8");
36
+ if (!content) throw new Error(`--spec: file is empty: ${path}`);
37
+ return content;
38
+ }
39
+
40
+ //#endregion
10
41
  //#region src/workers/chatui.ts
11
42
  /** Dim hint shown once behind the cursor until the first line is typed. */
12
43
  const CHAT_HINT = "type here and press Enter · /help for commands";
@@ -360,32 +391,6 @@ function tickerText(secs, intent, tool, meter) {
360
391
  const line = tail ? `${head} · ${tail}` : head;
361
392
  return meter ? `${line} · ${meter}` : line;
362
393
  }
363
- /** `4m12s` — the runtime shape the status row shows. */
364
- function fmtElapsed(secs) {
365
- const s = Math.max(0, Math.floor(secs));
366
- return `${Math.floor(s / 60)}m${String(s % 60).padStart(2, "0")}s`;
367
- }
368
- /**
369
- * The chat pane's status row (always visible while following):
370
- * `[glm/glm-5.3] ctx 84k/200k (42%) · turns 12 · tools 7 · 4m12s · ⋯ 7s · <intent> · <tool>`
371
- * — context yellow past 70 %, red past 85 %, dropped when unknown; once the
372
- * worker finished, the ticker part is replaced by `✓ done` / `✗ failed`.
373
- */
374
- function chatStatusRow(c, s) {
375
- const parts = [];
376
- const pct = contextPercent(s);
377
- if (pct !== null) {
378
- const label = contextLabel(s);
379
- parts.push(pct > 85 ? c("red", label) : pct > 70 ? c("yellow", label) : label);
380
- }
381
- parts.push(`turns ${s.turns}`, `tools ${s.tools}`, fmtElapsed(s.elapsed));
382
- if (s.state && s.state !== "running") parts.push(s.state === "done" ? c("green", "✓ done") : c("red", "✗ failed"));
383
- else {
384
- parts.push(`⋯ ${Math.max(0, Math.floor(s.idle ?? 0))}s`);
385
- for (const p of [s.intent, s.tool]) if (p && p.trim()) parts.push(p.trim());
386
- }
387
- return `[${s.provider}${s.model ? "/" + s.model : ""}] ${parts.join(" · ")}`;
388
- }
389
394
  /**
390
395
  * One blank line between turns, none inside one: a blank goes before an
391
396
  * assistant message that follows a tool result or an operator message (the
@@ -473,7 +478,9 @@ function renderEvent(c, prefix, e, cwd, tools, gutter) {
473
478
  function headerLine(c, s) {
474
479
  const bits = [s.provider ? `[${s.provider}]` : "", sessionTag(s)].filter(Boolean).join(" ");
475
480
  const sep = bits ? ` ${bits}` : "";
476
- return c("bold", `━━ ${s.id}${sep} ${s.label} (${basename(s.cwd)})`);
481
+ const specBit = s.spec ? ` spec: ${s.spec}` : "";
482
+ const reportBit = s.reportFormat === "ag2" && s.reportValid === false ? " " + c("red", (s.reportErrors ?? []).length ? "R!" : "R?") : "";
483
+ return c("bold", `━━ ${s.id}${sep} ${s.label} (${basename(s.cwd)})${specBit}${reportBit}`);
477
484
  }
478
485
  /** The chain label behind a stage label: strip the trailing " · <stage>". */
479
486
  function chainLabelOf(stages) {
@@ -508,6 +515,7 @@ function renderTable(c, statuses, scopeLabel, now = /* @__PURE__ */ new Date(),
508
515
  const rowCont = (depth, last) => depth <= 0 ? " " : " " + "│ ".repeat(depth - 1) + (last ? " " : "│ ");
509
516
  const branchMark = (s) => s.branch && !s.merged ? " " + c("yellow", "⎇" + (s.commits ? String(s.commits) : "")) : "";
510
517
  const inboxMark = (s) => inbox[s.id] ? " " + c("mag", `◆${inbox[s.id]}`) : "";
518
+ const reportMark = (s) => s.reportFormat === "ag2" && s.reportValid === false ? " " + c("red", (s.reportErrors ?? []).length ? "R!" : "R?") : "";
511
519
  const lines = [c("bold", `Workers ${`${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}:${String(now.getSeconds()).padStart(2, "0")}`}`), ""];
512
520
  lines.push(c("bold", `RUNNING (${running.length})`));
513
521
  if (!running.length) lines.push(" none");
@@ -549,7 +557,7 @@ function renderTable(c, statuses, scopeLabel, now = /* @__PURE__ */ new Date(),
549
557
  const subLast = !chain && (i + 1 >= doneSlice.length || doneSlice[i + 1].parent !== s.parent);
550
558
  const col = s.state === "done" ? "green" : "red";
551
559
  const tag = sessionTag(s);
552
- lines.push(treeLine(`${chain ? " " : rowPrefix(depth, subLast)}${s.id}${inboxMark(s)} [${s.provider}]${tag ? " " + tag : ""} ${c(col, s.state.padEnd(6))} rc=${s.rc} ${String(s.secs ?? "?").padStart(4)}s turns ${String(s.turns).padStart(2)} tools ${String(s.tools).padStart(2)} ${basename(s.cwd)}${branchMark(s)} ${s.label}`, chain, last));
560
+ lines.push(treeLine(`${chain ? " " : rowPrefix(depth, subLast)}${s.id}${inboxMark(s)} [${s.provider}]${tag ? " " + tag : ""} ${c(col, s.state.padEnd(6))} rc=${s.rc} ${String(s.secs ?? "?").padStart(4)}s turns ${String(s.turns).padStart(2)} tools ${String(s.tools).padStart(2)} ${basename(s.cwd)}${branchMark(s)}${reportMark(s)} ${s.label}`, chain, last));
553
561
  }
554
562
  lines.push("");
555
563
  lines.push(c("dim", "worker follow live transcript of running workers"));
@@ -558,51 +566,113 @@ function renderTable(c, statuses, scopeLabel, now = /* @__PURE__ */ new Date(),
558
566
  return lines.join("\n");
559
567
  }
560
568
  /**
561
- * The step of a statusline row: what the worker is doing as a verb, never a
562
- * raw command. A Bash line trims to its first word (`grep -n -A4 "x" src/` →
563
- * `grep …` — no `Bash:` prefix, no flags, no quotes); the file tools keep
564
- * their `Edit: button.ts` shape; free text (what the worker last said) is
565
- * only shortened. Always ≤ 24 chars.
569
+ * The one place a model id is compacted for display, so every renderer
570
+ * shortens identically: the vendor prefix goes (the provider column already
571
+ * says who serves it), a release-date suffix goes, version segments read as
572
+ * dots, and a `[1m]` window marker is kept because it changes what the run
573
+ * costs. `claude-opus-5[1m]` → `opus-5[1m]`, `claude-haiku-4-5-20251001` →
574
+ * `haiku-4.5`, `glm-5.3[1m]` and `k3[1m]` unchanged. Empty in, empty out.
566
575
  */
567
- function stepOf(last) {
568
- const s = String(last ?? "").trim();
569
- if (s.startsWith("Bash: ")) {
570
- const cmd = s.slice(6).trim();
571
- const verb = cmd.split(/\s+/)[0] ?? "";
572
- return shortText(cmd.length > verb.length ? `${verb} …` : verb, 24);
573
- }
574
- return shortText(s, 24);
576
+ function shortModel(model) {
577
+ const raw = String(model ?? "").trim();
578
+ if (!raw) return "";
579
+ const wide = /\[1m\]$/i.test(raw);
580
+ let id = wide ? raw.slice(0, -4) : raw;
581
+ id = id.replace(/^(?:us\.|eu\.|apac\.)?(?:anthropic|claude|openai|google|models)[./-]/i, "");
582
+ id = id.replace(/-\d{8}$/, "");
583
+ const parts = id.split("-");
584
+ const nums = [];
585
+ while (parts.length > 1 && /^\d+(?:\.\d+)*$/.test(parts[parts.length - 1])) nums.unshift(parts.pop());
586
+ if (nums.length) id = `${parts.join("-")}-${nums.join(".")}`;
587
+ return wide ? `${id}[1m]` : id;
588
+ }
589
+ /**
590
+ * The goal of a statusline row: what the worker is FOR, never what it is doing
591
+ * this second. The operator's `--label` is the goal and is preferred over
592
+ * anything the model wrote; an unlabelled run's label already holds its prompt
593
+ * (see run.ts), so the same path shortens that to its first sentence, cut on a
594
+ * word boundary. A run with neither label nor prompt reads "unlabeled". Width
595
+ * fitting goes through shortText, the repo's one truncation helper.
596
+ */
597
+ function goalOf(s, max = 40) {
598
+ const raw = String(s.label ?? "").trim();
599
+ if (!raw || raw === "(no prompt)") return UNLABELED;
600
+ const first = raw.split(/(?<=[.!?])\s+/)[0] ?? raw;
601
+ if (first.length <= max) return shortText(first, max);
602
+ return shortText(`${first.slice(0, max - 1).replace(/\s+\S*$/, "") || first.slice(0, max - 1)}…`, max);
603
+ }
604
+ /**
605
+ * A worker pane's bottom line: `<goal> · <model> · started HH:MM · <age>` —
606
+ * what the pane is FOR and how long it has run, never the tool call it
607
+ * happens to be executing this second (that is `pai worker ps` / `follow`
608
+ * territory). `columns`, when known, shrinks the goal so the fixed
609
+ * `model · started · age` tail always survives — trimming that tail instead
610
+ * would defeat the one thing an operator scanning several panes needs at a
611
+ * glance. A legacy status with no recorded model omits that field rather
612
+ * than rendering a bare gap.
613
+ */
614
+ function paneStatusRow(s, now = /* @__PURE__ */ new Date(), columns = null) {
615
+ const model = shortModel(s.model);
616
+ const started = String(s.started ?? "").slice(11, 16);
617
+ const age = ageOf(s.started, now);
618
+ const tail = [
619
+ model,
620
+ started ? `started ${started}` : "",
621
+ age
622
+ ].filter(Boolean).join(" · ");
623
+ return `${goalOf(s, columns !== null ? Math.max(1, columns - tail.length - 3) : 40)} · ${tail}`;
575
624
  }
576
625
  /**
577
- * The statusline bar: `provider ▶N` then one row per running spawned worker —
578
- * `name · age · step` — and today's ✓/✗ tail. The chat pane contributes
579
- * nothing but its provider: its age, state and inbox live in `pai worker ps`,
580
- * not here. Rows are flat (the ↳ depth is ps territory) and oldest first;
581
- * `#id` joins a name only when two running workers share one label, so ids
582
- * stay rare enough to read.
626
+ * The statusline bar: `provider ▶N · <models> · oldest <age>` and today's
627
+ * ✓/✗ tail. Three workers used to spell out three goals, three ages and three
628
+ * models on one line and none of it fit; each worker's own pane bottom line
629
+ * now carries `goal · model · started · age` (paneStatusRow) and `pai worker
630
+ * ps` has the full table, so the bar only has to answer how many workers are
631
+ * running, on what models, and how long the oldest has been going. `<models>`
632
+ * lists distinct short model names, most-populous first (ties broken by
633
+ * name), each suffixed `×N` past one; an empty model counts under `?` rather
634
+ * than vanishing (a legacy status with no recorded model is still a worker).
635
+ * `columns`, when known, shrinks only the models segment (shortText) so the
636
+ * head, the `▶N` count and the today tally — the three things worth reading
637
+ * at a glance — never get cut for the one segment that can grow without
638
+ * bound. The chat pane contributes nothing but its provider: its age, state
639
+ * and inbox live in `pai worker ps`, not here.
583
640
  */
584
- function renderStatusLine(mine, now = /* @__PURE__ */ new Date()) {
585
- if (!mine.length) return "";
641
+ function renderStatusLine(mine, now = /* @__PURE__ */ new Date(), active = null, columns = null) {
642
+ const live = active && active !== "auto" ? active : null;
643
+ if (!mine.length) return live ?? "";
586
644
  const isChat = isChatPane;
587
645
  const chat = mine.find((s) => isChat(s) && s.state === "running" && alive(s.pid));
588
- const running = mine.filter((s) => !isChat(s) && s.state === "running" && alive(s.pid)).sort((a, b) => a.started.localeCompare(b.started));
646
+ const running = mine.filter((s) => !isChat(s) && s.state === "running" && alive(s.pid));
589
647
  const today = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}`;
590
648
  const doneToday = mine.filter((s) => s.state !== "running" && s.started.startsWith(today));
591
649
  const ok = doneToday.filter((s) => s.state === "done").length;
592
650
  const bad = doneToday.length - ok;
593
- const rows = running.slice(0, 3).map((s) => {
594
- return `${`${running.some((o) => o !== s && o.label === s.label) ? `#${s.id.slice(-4)} ` : ""}${s.label.slice(0, 26)}`} · ${ageOf(s.started, now)} · ${stepOf(s.last)}`;
595
- });
596
651
  let head;
597
- if (chat) head = chat.provider;
652
+ if (live) head = live;
653
+ else if (chat) head = chat.provider;
598
654
  else {
599
655
  const providers = new Set(running.map((s) => s.provider));
600
656
  head = providers.size === 1 ? [...providers][0] : "workers";
601
657
  }
602
658
  if (running.length) head += ` ▶${running.length}`;
603
- if (rows.length) head += " | " + rows.join(" | ");
604
- if (doneToday.length) head += ` ✓${ok} ✗${bad} today`;
605
- return head;
659
+ const tail = doneToday.length ? ` ✓${ok} ✗${bad} today` : "";
660
+ if (!running.length) return head + tail;
661
+ const counts = /* @__PURE__ */ new Map();
662
+ for (const s of running) {
663
+ const m = shortModel(s.model) || "?";
664
+ counts.set(m, (counts.get(m) ?? 0) + 1);
665
+ }
666
+ const modelsFull = [...counts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([m, n]) => n > 1 ? `${m} ×${n}` : m).join(" · ");
667
+ const oldestPart = `oldest ${ageOf(running.reduce((a, b) => a.started < b.started ? a : b).started, now)}`;
668
+ let models = modelsFull;
669
+ const fixedLen = head.length + 3 + oldestPart.length + tail.length;
670
+ if (columns !== null && fixedLen + 3 + modelsFull.length > columns) {
671
+ const budget = columns - fixedLen - 3;
672
+ models = budget > 0 ? shortText(modelsFull, budget) : "";
673
+ }
674
+ const mid = [models, oldestPart].filter(Boolean).join(" · ");
675
+ return `${head} · ${mid}${tail}`;
606
676
  }
607
677
 
608
678
  //#endregion
@@ -825,6 +895,7 @@ async function followWorkers(logDir, target, showAll, autoExit, env = process.en
825
895
  let aborted = false;
826
896
  let lastEventAt = Date.now();
827
897
  let meterStatus = null;
898
+ let paneStatus;
828
899
  const onInt = () => {
829
900
  aborted = true;
830
901
  };
@@ -856,29 +927,11 @@ async function followWorkers(logDir, target, showAll, autoExit, env = process.en
856
927
  if (tty) out_.write("\r\x1B[K");
857
928
  };
858
929
  let ticker = initialFollowState();
859
- const statusRowOf = (st, secs) => {
860
- const fin = finished.has(st.id);
861
- const startedAt = Date.parse((st.started ?? "").replace(" ", "T"));
862
- const elapsed = fin && st.secs !== null ? st.secs : Number.isNaN(startedAt) ? 0 : Math.floor((Date.now() - startedAt) / 1e3);
863
- return {
864
- provider: st.provider,
865
- model: st.model,
866
- contextTokens: st.contextTokens,
867
- contextWindow: st.contextWindow,
868
- turns: st.turns,
869
- tools: st.tools,
870
- elapsed,
871
- idle: secs,
872
- intent: ticker.intent,
873
- tool: ticker.tool,
874
- state: fin ? st.state === "running" ? "done" : st.state : null
875
- };
876
- };
877
930
  const writeLiveness = () => {
878
931
  if (!tty) return;
879
932
  const secs = Math.max(0, Math.floor((Date.now() - lastEventAt) / 1e3));
880
933
  if (chat) {
881
- const text = meterStatus ? chatStatusRow(c, statusRowOf(meterStatus, secs)) : tickerText(secs, ticker.intent, ticker.tool);
934
+ const text = paneStatus ? paneStatusRow(paneStatus, /* @__PURE__ */ new Date(), columns()) : tickerText(secs, ticker.intent, ticker.tool);
882
935
  out_.write(chatTickerRow(text, rows, promptCursorCol()));
883
936
  } else {
884
937
  const meter = meterStatus ? contextMeter(c, meterStatus) : null;
@@ -1111,6 +1164,7 @@ async function followWorkers(logDir, target, showAll, autoExit, env = process.en
1111
1164
  for (;;) {
1112
1165
  if (aborted) return;
1113
1166
  const statuses = new Map(loadStatuses(logDir).map((s) => [s.id, s]));
1167
+ if (target) paneStatus = statuses.get(target) ?? paneStatus;
1114
1168
  const wanted = target ? [target] : runningIds();
1115
1169
  for (const wid of wanted) {
1116
1170
  if (handles.has(wid) || finished.has(wid)) continue;
@@ -1242,13 +1296,13 @@ function sleep(ms) {
1242
1296
  return new Promise((r) => setTimeout(r, ms));
1243
1297
  }
1244
1298
  /** Workers of this terminal for the status bar; "" when there are none. */
1245
- function statusLineOutput(logDir, term, cwd, claudeSession = "", now = /* @__PURE__ */ new Date()) {
1299
+ function statusLineOutput(logDir, term, cwd, claudeSession = "", now = /* @__PURE__ */ new Date(), active = null) {
1246
1300
  return renderStatusLine(loadStatuses(logDir).filter((s) => {
1247
1301
  const sameScope = term && workerInScope(s, term);
1248
1302
  const spawnedHere = claudeSession && s.spawnerSession === claudeSession;
1249
1303
  const sameDir = cwd && s.cwd.startsWith(cwd);
1250
1304
  return sameScope || spawnedHere || !term && sameDir;
1251
- }), now);
1305
+ }), now, active);
1252
1306
  }
1253
1307
 
1254
1308
  //#endregion
@@ -1261,10 +1315,12 @@ function statusLineOutput(logDir, term, cwd, claudeSession = "", now = /* @__PUR
1261
1315
  * section, and writes it back atomically — the file is shared with everything
1262
1316
  * else PAI runs, so a torn write is not an option.
1263
1317
  *
1264
- * Keys are never stored in the config and never accepted inline from the CLI:
1265
- * only file paths. (The MCP `add` tool additionally accepts a raw `key`, which
1266
- * it immediately parks in ~/.config/pai/keys/<name>, mode 0600, storing only
1267
- * the path — a chat is not a place to leave a credential lying around.)
1318
+ * The CLI's `--key` writes the token inline as `key:` in workers.yaml
1319
+ * (quoted, and the file is kept 0600 — see workers-config.ts); `--key-file`
1320
+ * still writes only a path. The MCP `add` tool instead accepts a raw `key`
1321
+ * and parks it in ~/.claude/pai/keys/<name>, mode 0600, storing only the
1322
+ * path in the config — a chat is not a place to leave a credential lying
1323
+ * around.
1268
1324
  */
1269
1325
  function addProvider(input) {
1270
1326
  if (!/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(input.name)) throw new WorkersConfigError(`provider name "${input.name}" may only contain letters, digits, - and _`);
@@ -1284,12 +1340,13 @@ function addProvider(input) {
1284
1340
  } catch {}
1285
1341
  keyFile = path;
1286
1342
  }
1287
- const { raw, workers } = readWorkersSection();
1343
+ const { raw, workers } = readWorkersSection(input.configPath);
1288
1344
  const provider = {
1289
1345
  enabled: true,
1290
1346
  protocol: input.protocol ?? "anthropic",
1291
1347
  baseUrl: input.baseUrl,
1292
1348
  keyFile,
1349
+ ...input.inlineKey ? { key: input.inlineKey } : {},
1293
1350
  models: input.fastModel ? {
1294
1351
  default: input.model,
1295
1352
  fast: input.fastModel
@@ -1321,12 +1378,12 @@ function addProvider(input) {
1321
1378
  image: input.name
1322
1379
  };
1323
1380
  }
1324
- writeWorkersSection(raw, workers);
1381
+ writeWorkersSection(raw, workers, input.configPath);
1325
1382
  return workers;
1326
1383
  }
1327
1384
  /** Change costTier / tags on an existing provider (MCP action "update"). */
1328
- function updateProvider(name, changes) {
1329
- const { raw, workers } = readWorkersSection();
1385
+ function updateProvider(name, changes, configPath) {
1386
+ const { raw, workers } = readWorkersSection(configPath);
1330
1387
  const p = workers.providers[name];
1331
1388
  if (!p) throw new WorkersConfigError(`no provider named "${name}". Configured: ${Object.keys(workers.providers).join(", ") || "(none)"}`);
1332
1389
  if (changes.costTier !== void 0) {
@@ -1337,23 +1394,23 @@ function updateProvider(name, changes) {
1337
1394
  for (const t of changes.tags) if (!PROVIDER_TAGS.includes(t)) throw new WorkersConfigError(`"${t}" is not a tag (from: ${PROVIDER_TAGS.join(", ")})`);
1338
1395
  p.tags = changes.tags;
1339
1396
  }
1340
- writeWorkersSection(raw, workers);
1397
+ writeWorkersSection(raw, workers, configPath);
1341
1398
  return workers;
1342
1399
  }
1343
- function removeProvider(name) {
1344
- const { raw, workers } = readWorkersSection();
1400
+ function removeProvider(name, configPath) {
1401
+ const { raw, workers } = readWorkersSection(configPath);
1345
1402
  if (!workers.providers[name]) throw new WorkersConfigError(`no provider named "${name}"`);
1346
1403
  delete workers.providers[name];
1347
1404
  for (const [cls, target] of Object.entries(workers.classes)) if ((typeof target === "string" ? target.split("/")[0] : target.provider) === name) delete workers.classes[cls];
1348
1405
  if (workers.active === name) workers.active = null;
1349
- writeWorkersSection(raw, workers);
1406
+ writeWorkersSection(raw, workers, configPath);
1350
1407
  return workers;
1351
1408
  }
1352
- function useProvider(name) {
1353
- const { raw, workers } = readWorkersSection();
1409
+ function useProvider(name, configPath) {
1410
+ const { raw, workers } = readWorkersSection(configPath);
1354
1411
  if (name !== ANTHROPIC_NATIVE && !workers.providers[name]) throw new WorkersConfigError(`no provider named "${name}". Configured: ${Object.keys(workers.providers).join(", ") || "(none)"}`);
1355
1412
  workers.active = name;
1356
- writeWorkersSection(raw, workers);
1413
+ writeWorkersSection(raw, workers, configPath);
1357
1414
  return workers;
1358
1415
  }
1359
1416
  /**
@@ -1382,13 +1439,13 @@ function setProviderModel(name, capability, model, configPath) {
1382
1439
  writeWorkersSection(raw, workers, configPath);
1383
1440
  return workers;
1384
1441
  }
1385
- function setProviderEnabled(name, enabled) {
1386
- const { raw, workers } = readWorkersSection();
1442
+ function setProviderEnabled(name, enabled, configPath) {
1443
+ const { raw, workers } = readWorkersSection(configPath);
1387
1444
  const p = workers.providers[name];
1388
1445
  if (!p) throw new WorkersConfigError(`no provider named "${name}"`);
1389
1446
  p.enabled = enabled;
1390
- writeWorkersSection(raw, workers);
1391
- if (enabled) clearCooldown(workersLogDir(parseWorkersConfig(raw.workers)), name);
1447
+ writeWorkersSection(raw, workers, configPath);
1448
+ if (enabled) clearCooldown(workersLogDir(workers), name);
1392
1449
  return workers;
1393
1450
  }
1394
1451
  /**
@@ -1396,8 +1453,8 @@ function setProviderEnabled(name, enabled) {
1396
1453
  * provider + optional mcp/maxCostTier/requireTags/order). An object without
1397
1454
  * a provider only constrains auto-routing for that class.
1398
1455
  */
1399
- function setClass(name, target) {
1400
- const { raw, workers } = readWorkersSection();
1456
+ function setClass(name, target, configPath) {
1457
+ const { raw, workers } = readWorkersSection(configPath);
1401
1458
  if (typeof target === "string") {
1402
1459
  const [provider, alias] = target.split("/");
1403
1460
  const native = provider === ANTHROPIC_NATIVE;
@@ -1411,20 +1468,20 @@ function setClass(name, target) {
1411
1468
  if (target.provider !== ANTHROPIC_NATIVE && !workers.providers[target.provider]) throw new WorkersConfigError(`no provider named "${target.provider}". Configured: ${Object.keys(workers.providers).join(", ") || "(none)"}`);
1412
1469
  }
1413
1470
  workers.classes[name] = target;
1414
- writeWorkersSection(raw, workers);
1471
+ writeWorkersSection(raw, workers, configPath);
1415
1472
  return workers;
1416
1473
  }
1417
- function unsetClass(name) {
1418
- const { raw, workers } = readWorkersSection();
1474
+ function unsetClass(name, configPath) {
1475
+ const { raw, workers } = readWorkersSection(configPath);
1419
1476
  if (!(name in workers.classes)) throw new WorkersConfigError(`no class named "${name}"`);
1420
1477
  delete workers.classes[name];
1421
- writeWorkersSection(raw, workers);
1478
+ writeWorkersSection(raw, workers, configPath);
1422
1479
  return workers;
1423
1480
  }
1424
- function setWorkersEnabled(enabled) {
1425
- const { raw, workers } = readWorkersSection();
1481
+ function setWorkersEnabled(enabled, configPath) {
1482
+ const { raw, workers } = readWorkersSection(configPath);
1426
1483
  workers.enabled = enabled;
1427
- writeWorkersSection(raw, workers);
1484
+ writeWorkersSection(raw, workers, configPath);
1428
1485
  return workers;
1429
1486
  }
1430
1487
  /** `glm/fast` | `{provider, mcp, …}` → one printable target line. */
@@ -1460,15 +1517,23 @@ function describeModels(workers) {
1460
1517
  }
1461
1518
  return lines;
1462
1519
  }
1520
+ /** Classes (in declaration order) whose target resolves to this provider. */
1521
+ function classesForProvider(workers, name) {
1522
+ return Object.entries(workers.classes).filter(([, target]) => (typeof target === "string" ? target.split("/")[0] : target.provider) === name).map(([cls]) => cls);
1523
+ }
1463
1524
  /** Human-readable provider listing (quota probe included when configured). */
1464
- function describeProviders(workers) {
1525
+ function describeProviders(workers, configPath = CONFIG_FILE) {
1465
1526
  const lines = [];
1466
1527
  const nativeActive = workers.active === ANTHROPIC_NATIVE;
1467
1528
  lines.push(`${ANTHROPIC_NATIVE} [built-in${nativeActive ? ", active" : ""}] Claude Code's own OAuth/Max-plan login — no base URL, no API key`);
1529
+ lines.push(` ${modelPrefsText(nativeAnthropicProvider(workers.nativeModels))}`);
1530
+ const nativeClasses = classesForProvider(workers, ANTHROPIC_NATIVE);
1531
+ lines.push(` classes: ${nativeClasses.length ? nativeClasses.join(", ") : "(none)"}`);
1468
1532
  const names = Object.keys(workers.providers);
1469
1533
  if (!names.length) {
1470
1534
  lines.push(`no other providers configured. Add one with:`);
1471
1535
  lines.push(` pai worker providers add <name> --base-url <url> --key-file <path> --model <model>`);
1536
+ lines.push(`config: ${existsSync(workersYamlPath()) ? workersYamlPath() : configPath}`);
1472
1537
  return lines;
1473
1538
  }
1474
1539
  for (const name of names) {
@@ -1480,17 +1545,19 @@ function describeProviders(workers) {
1480
1545
  lines.push(`${name} [${flags.join(", ")}] ${p.baseUrl}`);
1481
1546
  lines.push(` ${modelPrefsText(p)}${quotaNote}`);
1482
1547
  lines.push(` ${tierTags}`);
1548
+ if (p.key) lines.push(` key ${maskKey(p.key)}`);
1483
1549
  if (p.keyFile) lines.push(` key file ${expandHome(p.keyFile)}`);
1484
- else lines.push(` no key file (token "local")`);
1550
+ if (!p.key && !p.keyFile) lines.push(` no key file (token "local")`);
1485
1551
  if (p.note) lines.push(` ${p.note}`);
1486
1552
  if (p.protocol === "openai") lines.push(` via PAI proxy ← ${p.upstreamUrl ?? "(upstreamUrl missing)"}`);
1487
1553
  if (p.engine === "codex") lines.push(` engine codex (runs through the Codex CLI)`);
1554
+ const cls = classesForProvider(workers, name);
1555
+ lines.push(` classes: ${cls.length ? cls.join(", ") : "(none)"}`);
1488
1556
  }
1489
1557
  const setNames = Object.keys(workers.mcpSets);
1490
1558
  if (setNames.length) lines.push(`mcp sets: ${setNames.map((s) => `${s}=[${workers.mcpSets[s].join(",")}]`).join(" ")}`);
1491
- const classNames = Object.keys(workers.classes);
1492
- if (classNames.length) lines.push(`classes: ${classNames.map((cl) => `${cl}=${classTargetText(workers.classes[cl])}`).join(" ")}`);
1493
1559
  if (workers.active === "auto") lines.push(`routing: auto — order [${workers.routing.order.join(", ")}], cooldown ${workers.routing.cooldownMinutes}m`);
1560
+ lines.push(`config: ${existsSync(workersYamlPath()) ? workersYamlPath() : configPath}`);
1494
1561
  return lines;
1495
1562
  }
1496
1563
 
@@ -1509,7 +1576,7 @@ function describeProviders(workers) {
1509
1576
  * and pins the top-level `model` to the provider's default model.
1510
1577
  *
1511
1578
  * What settings.json carried before the switch is saved under
1512
- * `workers.fallback.saved` in ~/.config/pai/config.json; `fallback off`
1579
+ * `workers.fallback.saved` in the PAI config file (CONFIG_FILE); `fallback off`
1513
1580
  * restores it exactly and removes the added keys. Both files are written
1514
1581
  * atomically; nothing else in them is touched. While fallback is on the
1515
1582
  * Agent hook keeps routing subagents to workers, unchanged — those runs set
@@ -1536,12 +1603,7 @@ function fallbackNotePath(logDir) {
1536
1603
  * buildRunEnv uses), the provider's own env, and the two fallback constants.
1537
1604
  */
1538
1605
  function fallbackEnv(provider) {
1539
- let token = "local";
1540
- const keyPath = providerKeyPath(provider);
1541
- if (keyPath) {
1542
- token = readFileSync(keyPath, "utf8").trim();
1543
- if (!token) throw new WorkersConfigError(`key file is empty: ${keyPath}`);
1544
- }
1606
+ const token = resolveProviderKey(provider) ?? "local";
1545
1607
  return {
1546
1608
  ANTHROPIC_BASE_URL: provider.baseUrl,
1547
1609
  ANTHROPIC_AUTH_TOKEN: token,
@@ -1764,5 +1826,5 @@ function fallbackStatusText(s) {
1764
1826
  }
1765
1827
 
1766
1828
  //#endregion
1767
- export { statusLineOutput as S, updateProvider as _, addProvider as a, psOutput as b, describeProviders as c, resolveProviderName as d, setClass as f, unsetClass as g, setWorkersEnabled as h, fallbackStatusText as i, modelPrefsText as l, setProviderModel as m, fallbackOn as n, classTargetText as o, setProviderEnabled as p, fallbackStatus as r, describeModels as s, fallbackOff as t, removeProvider as u, useProvider as v, replayOutput as x, followWorkers as y };
1768
- //# sourceMappingURL=fallback-oJl3BaIN.mjs.map
1829
+ export { readSpecPrompt as C, statusLineOutput as S, updateProvider as _, addProvider as a, psOutput as b, describeProviders as c, resolveProviderName as d, setClass as f, unsetClass as g, setWorkersEnabled as h, fallbackStatusText as i, modelPrefsText as l, setProviderModel as m, fallbackOn as n, classTargetText as o, setProviderEnabled as p, fallbackStatus as r, describeModels as s, fallbackOff as t, removeProvider as u, useProvider as v, resolveSpecPath as w, replayOutput as x, followWorkers as y };
1830
+ //# sourceMappingURL=fallback-BQJ8PbCK.mjs.map