@tekmidian/pai 0.42.4 → 0.42.6

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 (292) 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-BbcfP77K.mjs} +5 -4
  9. package/dist/{chain-DTII7xeL.mjs.map → chain-BbcfP77K.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-BNjbVsQU.mjs +24 -0
  26. package/dist/{daemon-B8N1egl0.mjs → daemon-BppziPi6.mjs} +52 -38
  27. package/dist/daemon-BppziPi6.mjs.map +1 -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-Cwt4hmh5.mjs} +182 -122
  48. package/dist/fallback-Cwt4hmh5.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 +185 -103
  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 +3 -0
  96. package/dist/hooks/whisper-reinject.mjs.map +1 -1
  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 +7791 -144
  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-pXRc-8yt.mjs} +7 -6
  132. package/dist/{planner-D5Ui7DAm.mjs.map → planner-pXRc-8yt.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-LLNPpxlj.mjs} +8308 -6065
  136. package/dist/program-LLNPpxlj.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-DDdT9teG.mjs} +530 -210
  147. package/dist/run-DDdT9teG.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-BradfQk7.mjs} +4 -3
  175. package/dist/{tools-LlzcV_eK.mjs → tools-UrSHIe29.mjs} +30 -233
  176. package/dist/tools-UrSHIe29.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-TnGjJY3I.mjs +218 -0
  185. package/dist/wakeup-TnGjJY3I.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 +30 -3
  192. package/docs/commands/audit.md +88 -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 +95 -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 +56 -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/pre-compact/context-compression-hook.ts +1 -1
  248. package/src/hooks/ts/pre-tool-use/route-agents-to-worker.ts +46 -99
  249. package/src/hooks/ts/pre-tool-use/route-edits-to-worker.test.ts +47 -0
  250. package/src/hooks/ts/pre-tool-use/route-edits-to-worker.ts +96 -0
  251. package/src/hooks/ts/pre-tool-use/security-validator.ts +2 -1
  252. package/src/hooks/ts/session-end/capture-session-summary.ts +4 -4
  253. package/src/hooks/ts/session-start/initialize-session.ts +3 -3
  254. package/src/hooks/ts/session-start/inject-observations.test.ts +56 -0
  255. package/src/hooks/ts/session-start/inject-observations.ts +28 -8
  256. package/src/hooks/ts/session-start/load-core-context.ts +4 -4
  257. package/src/hooks/ts/session-start/load-project-context.ts +2 -2
  258. package/src/hooks/ts/session-start/mcp-deferred-reminder.ts +2 -0
  259. package/src/hooks/ts/session-start/session-commands.ts +4 -0
  260. package/src/hooks/ts/session-start/session-start-worker-guard.test.ts +36 -0
  261. package/src/hooks/ts/stop/stop-hook.ts +6 -11
  262. package/src/hooks/ts/user-prompt/whisper-rules.test.ts +49 -0
  263. package/src/hooks/ts/user-prompt/whisper-rules.ts +88 -47
  264. package/statusline-command.sh +277 -116
  265. package/templates/agent-prefs.example.md +8 -8
  266. package/templates/claude-md.template.md +1 -1
  267. package/templates/voices.example.json +3 -3
  268. package/dist/config-C_ErGddD.mjs +0 -3
  269. package/dist/config-_lQI_W08.mjs +0 -640
  270. package/dist/config-_lQI_W08.mjs.map +0 -1
  271. package/dist/context-handover-cache-pNFdBNrU.mjs +0 -1548
  272. package/dist/context-handover-cache-pNFdBNrU.mjs.map +0 -1
  273. package/dist/daemon-B8N1egl0.mjs.map +0 -1
  274. package/dist/daemon-DHfyoTlk.mjs +0 -23
  275. package/dist/db-O-cyAPfS.mjs +0 -3
  276. package/dist/db-XEwJbuGO.mjs +0 -3
  277. package/dist/detector-C-7KRi42.mjs +0 -5
  278. package/dist/factory-Dbo8yNPi.mjs +0 -3
  279. package/dist/fallback-oJl3BaIN.mjs.map +0 -1
  280. package/dist/main-resolver-BAfOMppW.mjs +0 -7
  281. package/dist/main-resolver-DnkxPYkr.mjs.map +0 -1
  282. package/dist/program-zpoYnJGz.mjs.map +0 -1
  283. package/dist/query-feedback-DGoVRaWD.mjs +0 -3
  284. package/dist/query-feedback-Dqz-HC__.mjs.map +0 -1
  285. package/dist/router-BTIGZR2_.mjs +0 -3
  286. package/dist/run-D7K5UALn.mjs.map +0 -1
  287. package/dist/server-D4vAieF4.mjs.map +0 -1
  288. package/dist/tools-LlzcV_eK.mjs.map +0 -1
  289. package/dist/work-queue-worker-AEmfVE0F.mjs +0 -14
  290. package/dist/work-queue-worker-DIT-VLSh.mjs +0 -2136
  291. package/dist/work-queue-worker-DIT-VLSh.mjs.map +0 -1
  292. /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 { C as ageOf, D as isChatPane, E as contextPercent, L as shortText, S as UNLABELED, T as contextLabel, _ as resolveSession, a as renderReport, d as workerDepth, h as currentTabKey, i as parseWorkerReport, k as loadStatuses, l as readInbox, u as sayToWorker, v as sessionTag, w as alive, y as workerInScope } from "./run-DDdT9teG.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,8 @@ 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
+ return c("bold", `━━ ${s.id}${sep} ${s.label} (${basename(s.cwd)})${specBit}`);
477
483
  }
478
484
  /** The chain label behind a stage label: strip the trailing " · <stage>". */
479
485
  function chainLabelOf(stages) {
@@ -558,51 +564,113 @@ function renderTable(c, statuses, scopeLabel, now = /* @__PURE__ */ new Date(),
558
564
  return lines.join("\n");
559
565
  }
560
566
  /**
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.
567
+ * The one place a model id is compacted for display, so every renderer
568
+ * shortens identically: the vendor prefix goes (the provider column already
569
+ * says who serves it), a release-date suffix goes, version segments read as
570
+ * dots, and a `[1m]` window marker is kept because it changes what the run
571
+ * costs. `claude-opus-5[1m]` → `opus-5[1m]`, `claude-haiku-4-5-20251001` →
572
+ * `haiku-4.5`, `glm-5.3[1m]` and `k3[1m]` unchanged. Empty in, empty out.
566
573
  */
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);
574
+ function shortModel(model) {
575
+ const raw = String(model ?? "").trim();
576
+ if (!raw) return "";
577
+ const wide = /\[1m\]$/i.test(raw);
578
+ let id = wide ? raw.slice(0, -4) : raw;
579
+ id = id.replace(/^(?:us\.|eu\.|apac\.)?(?:anthropic|claude|openai|google|models)[./-]/i, "");
580
+ id = id.replace(/-\d{8}$/, "");
581
+ const parts = id.split("-");
582
+ const nums = [];
583
+ while (parts.length > 1 && /^\d+(?:\.\d+)*$/.test(parts[parts.length - 1])) nums.unshift(parts.pop());
584
+ if (nums.length) id = `${parts.join("-")}-${nums.join(".")}`;
585
+ return wide ? `${id}[1m]` : id;
586
+ }
587
+ /**
588
+ * The goal of a statusline row: what the worker is FOR, never what it is doing
589
+ * this second. The operator's `--label` is the goal and is preferred over
590
+ * anything the model wrote; an unlabelled run's label already holds its prompt
591
+ * (see run.ts), so the same path shortens that to its first sentence, cut on a
592
+ * word boundary. A run with neither label nor prompt reads "unlabeled". Width
593
+ * fitting goes through shortText, the repo's one truncation helper.
594
+ */
595
+ function goalOf(s, max = 40) {
596
+ const raw = String(s.label ?? "").trim();
597
+ if (!raw || raw === "(no prompt)") return UNLABELED;
598
+ const first = raw.split(/(?<=[.!?])\s+/)[0] ?? raw;
599
+ if (first.length <= max) return shortText(first, max);
600
+ return shortText(`${first.slice(0, max - 1).replace(/\s+\S*$/, "") || first.slice(0, max - 1)}…`, max);
601
+ }
602
+ /**
603
+ * A worker pane's bottom line: `<goal> · <model> · started HH:MM · <age>` —
604
+ * what the pane is FOR and how long it has run, never the tool call it
605
+ * happens to be executing this second (that is `pai worker ps` / `follow`
606
+ * territory). `columns`, when known, shrinks the goal so the fixed
607
+ * `model · started · age` tail always survives — trimming that tail instead
608
+ * would defeat the one thing an operator scanning several panes needs at a
609
+ * glance. A legacy status with no recorded model omits that field rather
610
+ * than rendering a bare gap.
611
+ */
612
+ function paneStatusRow(s, now = /* @__PURE__ */ new Date(), columns = null) {
613
+ const model = shortModel(s.model);
614
+ const started = String(s.started ?? "").slice(11, 16);
615
+ const age = ageOf(s.started, now);
616
+ const tail = [
617
+ model,
618
+ started ? `started ${started}` : "",
619
+ age
620
+ ].filter(Boolean).join(" · ");
621
+ return `${goalOf(s, columns !== null ? Math.max(1, columns - tail.length - 3) : 40)} · ${tail}`;
575
622
  }
576
623
  /**
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.
624
+ * The statusline bar: `provider ▶N · <models> · oldest <age>` and today's
625
+ * ✓/✗ tail. Three workers used to spell out three goals, three ages and three
626
+ * models on one line and none of it fit; each worker's own pane bottom line
627
+ * now carries `goal · model · started · age` (paneStatusRow) and `pai worker
628
+ * ps` has the full table, so the bar only has to answer how many workers are
629
+ * running, on what models, and how long the oldest has been going. `<models>`
630
+ * lists distinct short model names, most-populous first (ties broken by
631
+ * name), each suffixed `×N` past one; an empty model counts under `?` rather
632
+ * than vanishing (a legacy status with no recorded model is still a worker).
633
+ * `columns`, when known, shrinks only the models segment (shortText) so the
634
+ * head, the `▶N` count and the today tally — the three things worth reading
635
+ * at a glance — never get cut for the one segment that can grow without
636
+ * bound. The chat pane contributes nothing but its provider: its age, state
637
+ * and inbox live in `pai worker ps`, not here.
583
638
  */
584
- function renderStatusLine(mine, now = /* @__PURE__ */ new Date()) {
585
- if (!mine.length) return "";
639
+ function renderStatusLine(mine, now = /* @__PURE__ */ new Date(), active = null, columns = null) {
640
+ const live = active && active !== "auto" ? active : null;
641
+ if (!mine.length) return live ?? "";
586
642
  const isChat = isChatPane;
587
643
  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));
644
+ const running = mine.filter((s) => !isChat(s) && s.state === "running" && alive(s.pid));
589
645
  const today = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}`;
590
646
  const doneToday = mine.filter((s) => s.state !== "running" && s.started.startsWith(today));
591
647
  const ok = doneToday.filter((s) => s.state === "done").length;
592
648
  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
649
  let head;
597
- if (chat) head = chat.provider;
650
+ if (live) head = live;
651
+ else if (chat) head = chat.provider;
598
652
  else {
599
653
  const providers = new Set(running.map((s) => s.provider));
600
654
  head = providers.size === 1 ? [...providers][0] : "workers";
601
655
  }
602
656
  if (running.length) head += ` ▶${running.length}`;
603
- if (rows.length) head += " | " + rows.join(" | ");
604
- if (doneToday.length) head += ` ✓${ok} ✗${bad} today`;
605
- return head;
657
+ const tail = doneToday.length ? ` ✓${ok} ✗${bad} today` : "";
658
+ if (!running.length) return head + tail;
659
+ const counts = /* @__PURE__ */ new Map();
660
+ for (const s of running) {
661
+ const m = shortModel(s.model) || "?";
662
+ counts.set(m, (counts.get(m) ?? 0) + 1);
663
+ }
664
+ 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(" · ");
665
+ const oldestPart = `oldest ${ageOf(running.reduce((a, b) => a.started < b.started ? a : b).started, now)}`;
666
+ let models = modelsFull;
667
+ const fixedLen = head.length + 3 + oldestPart.length + tail.length;
668
+ if (columns !== null && fixedLen + 3 + modelsFull.length > columns) {
669
+ const budget = columns - fixedLen - 3;
670
+ models = budget > 0 ? shortText(modelsFull, budget) : "";
671
+ }
672
+ const mid = [models, oldestPart].filter(Boolean).join(" · ");
673
+ return `${head} · ${mid}${tail}`;
606
674
  }
607
675
 
608
676
  //#endregion
@@ -825,6 +893,7 @@ async function followWorkers(logDir, target, showAll, autoExit, env = process.en
825
893
  let aborted = false;
826
894
  let lastEventAt = Date.now();
827
895
  let meterStatus = null;
896
+ let paneStatus;
828
897
  const onInt = () => {
829
898
  aborted = true;
830
899
  };
@@ -856,29 +925,11 @@ async function followWorkers(logDir, target, showAll, autoExit, env = process.en
856
925
  if (tty) out_.write("\r\x1B[K");
857
926
  };
858
927
  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
928
  const writeLiveness = () => {
878
929
  if (!tty) return;
879
930
  const secs = Math.max(0, Math.floor((Date.now() - lastEventAt) / 1e3));
880
931
  if (chat) {
881
- const text = meterStatus ? chatStatusRow(c, statusRowOf(meterStatus, secs)) : tickerText(secs, ticker.intent, ticker.tool);
932
+ const text = paneStatus ? paneStatusRow(paneStatus, /* @__PURE__ */ new Date(), columns()) : tickerText(secs, ticker.intent, ticker.tool);
882
933
  out_.write(chatTickerRow(text, rows, promptCursorCol()));
883
934
  } else {
884
935
  const meter = meterStatus ? contextMeter(c, meterStatus) : null;
@@ -1111,6 +1162,7 @@ async function followWorkers(logDir, target, showAll, autoExit, env = process.en
1111
1162
  for (;;) {
1112
1163
  if (aborted) return;
1113
1164
  const statuses = new Map(loadStatuses(logDir).map((s) => [s.id, s]));
1165
+ if (target) paneStatus = statuses.get(target) ?? paneStatus;
1114
1166
  const wanted = target ? [target] : runningIds();
1115
1167
  for (const wid of wanted) {
1116
1168
  if (handles.has(wid) || finished.has(wid)) continue;
@@ -1242,13 +1294,13 @@ function sleep(ms) {
1242
1294
  return new Promise((r) => setTimeout(r, ms));
1243
1295
  }
1244
1296
  /** Workers of this terminal for the status bar; "" when there are none. */
1245
- function statusLineOutput(logDir, term, cwd, claudeSession = "", now = /* @__PURE__ */ new Date()) {
1297
+ function statusLineOutput(logDir, term, cwd, claudeSession = "", now = /* @__PURE__ */ new Date(), active = null) {
1246
1298
  return renderStatusLine(loadStatuses(logDir).filter((s) => {
1247
1299
  const sameScope = term && workerInScope(s, term);
1248
1300
  const spawnedHere = claudeSession && s.spawnerSession === claudeSession;
1249
1301
  const sameDir = cwd && s.cwd.startsWith(cwd);
1250
1302
  return sameScope || spawnedHere || !term && sameDir;
1251
- }), now);
1303
+ }), now, active);
1252
1304
  }
1253
1305
 
1254
1306
  //#endregion
@@ -1261,10 +1313,12 @@ function statusLineOutput(logDir, term, cwd, claudeSession = "", now = /* @__PUR
1261
1313
  * section, and writes it back atomically — the file is shared with everything
1262
1314
  * else PAI runs, so a torn write is not an option.
1263
1315
  *
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.)
1316
+ * The CLI's `--key` writes the token inline as `key:` in workers.yaml
1317
+ * (quoted, and the file is kept 0600 — see workers-config.ts); `--key-file`
1318
+ * still writes only a path. The MCP `add` tool instead accepts a raw `key`
1319
+ * and parks it in ~/.claude/pai/keys/<name>, mode 0600, storing only the
1320
+ * path in the config — a chat is not a place to leave a credential lying
1321
+ * around.
1268
1322
  */
1269
1323
  function addProvider(input) {
1270
1324
  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 +1338,13 @@ function addProvider(input) {
1284
1338
  } catch {}
1285
1339
  keyFile = path;
1286
1340
  }
1287
- const { raw, workers } = readWorkersSection();
1341
+ const { raw, workers } = readWorkersSection(input.configPath);
1288
1342
  const provider = {
1289
1343
  enabled: true,
1290
1344
  protocol: input.protocol ?? "anthropic",
1291
1345
  baseUrl: input.baseUrl,
1292
1346
  keyFile,
1347
+ ...input.inlineKey ? { key: input.inlineKey } : {},
1293
1348
  models: input.fastModel ? {
1294
1349
  default: input.model,
1295
1350
  fast: input.fastModel
@@ -1321,12 +1376,12 @@ function addProvider(input) {
1321
1376
  image: input.name
1322
1377
  };
1323
1378
  }
1324
- writeWorkersSection(raw, workers);
1379
+ writeWorkersSection(raw, workers, input.configPath);
1325
1380
  return workers;
1326
1381
  }
1327
1382
  /** Change costTier / tags on an existing provider (MCP action "update"). */
1328
- function updateProvider(name, changes) {
1329
- const { raw, workers } = readWorkersSection();
1383
+ function updateProvider(name, changes, configPath) {
1384
+ const { raw, workers } = readWorkersSection(configPath);
1330
1385
  const p = workers.providers[name];
1331
1386
  if (!p) throw new WorkersConfigError(`no provider named "${name}". Configured: ${Object.keys(workers.providers).join(", ") || "(none)"}`);
1332
1387
  if (changes.costTier !== void 0) {
@@ -1337,23 +1392,23 @@ function updateProvider(name, changes) {
1337
1392
  for (const t of changes.tags) if (!PROVIDER_TAGS.includes(t)) throw new WorkersConfigError(`"${t}" is not a tag (from: ${PROVIDER_TAGS.join(", ")})`);
1338
1393
  p.tags = changes.tags;
1339
1394
  }
1340
- writeWorkersSection(raw, workers);
1395
+ writeWorkersSection(raw, workers, configPath);
1341
1396
  return workers;
1342
1397
  }
1343
- function removeProvider(name) {
1344
- const { raw, workers } = readWorkersSection();
1398
+ function removeProvider(name, configPath) {
1399
+ const { raw, workers } = readWorkersSection(configPath);
1345
1400
  if (!workers.providers[name]) throw new WorkersConfigError(`no provider named "${name}"`);
1346
1401
  delete workers.providers[name];
1347
1402
  for (const [cls, target] of Object.entries(workers.classes)) if ((typeof target === "string" ? target.split("/")[0] : target.provider) === name) delete workers.classes[cls];
1348
1403
  if (workers.active === name) workers.active = null;
1349
- writeWorkersSection(raw, workers);
1404
+ writeWorkersSection(raw, workers, configPath);
1350
1405
  return workers;
1351
1406
  }
1352
- function useProvider(name) {
1353
- const { raw, workers } = readWorkersSection();
1407
+ function useProvider(name, configPath) {
1408
+ const { raw, workers } = readWorkersSection(configPath);
1354
1409
  if (name !== ANTHROPIC_NATIVE && !workers.providers[name]) throw new WorkersConfigError(`no provider named "${name}". Configured: ${Object.keys(workers.providers).join(", ") || "(none)"}`);
1355
1410
  workers.active = name;
1356
- writeWorkersSection(raw, workers);
1411
+ writeWorkersSection(raw, workers, configPath);
1357
1412
  return workers;
1358
1413
  }
1359
1414
  /**
@@ -1382,13 +1437,13 @@ function setProviderModel(name, capability, model, configPath) {
1382
1437
  writeWorkersSection(raw, workers, configPath);
1383
1438
  return workers;
1384
1439
  }
1385
- function setProviderEnabled(name, enabled) {
1386
- const { raw, workers } = readWorkersSection();
1440
+ function setProviderEnabled(name, enabled, configPath) {
1441
+ const { raw, workers } = readWorkersSection(configPath);
1387
1442
  const p = workers.providers[name];
1388
1443
  if (!p) throw new WorkersConfigError(`no provider named "${name}"`);
1389
1444
  p.enabled = enabled;
1390
- writeWorkersSection(raw, workers);
1391
- if (enabled) clearCooldown(workersLogDir(parseWorkersConfig(raw.workers)), name);
1445
+ writeWorkersSection(raw, workers, configPath);
1446
+ if (enabled) clearCooldown(workersLogDir(workers), name);
1392
1447
  return workers;
1393
1448
  }
1394
1449
  /**
@@ -1396,8 +1451,8 @@ function setProviderEnabled(name, enabled) {
1396
1451
  * provider + optional mcp/maxCostTier/requireTags/order). An object without
1397
1452
  * a provider only constrains auto-routing for that class.
1398
1453
  */
1399
- function setClass(name, target) {
1400
- const { raw, workers } = readWorkersSection();
1454
+ function setClass(name, target, configPath) {
1455
+ const { raw, workers } = readWorkersSection(configPath);
1401
1456
  if (typeof target === "string") {
1402
1457
  const [provider, alias] = target.split("/");
1403
1458
  const native = provider === ANTHROPIC_NATIVE;
@@ -1411,20 +1466,20 @@ function setClass(name, target) {
1411
1466
  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
1467
  }
1413
1468
  workers.classes[name] = target;
1414
- writeWorkersSection(raw, workers);
1469
+ writeWorkersSection(raw, workers, configPath);
1415
1470
  return workers;
1416
1471
  }
1417
- function unsetClass(name) {
1418
- const { raw, workers } = readWorkersSection();
1472
+ function unsetClass(name, configPath) {
1473
+ const { raw, workers } = readWorkersSection(configPath);
1419
1474
  if (!(name in workers.classes)) throw new WorkersConfigError(`no class named "${name}"`);
1420
1475
  delete workers.classes[name];
1421
- writeWorkersSection(raw, workers);
1476
+ writeWorkersSection(raw, workers, configPath);
1422
1477
  return workers;
1423
1478
  }
1424
- function setWorkersEnabled(enabled) {
1425
- const { raw, workers } = readWorkersSection();
1479
+ function setWorkersEnabled(enabled, configPath) {
1480
+ const { raw, workers } = readWorkersSection(configPath);
1426
1481
  workers.enabled = enabled;
1427
- writeWorkersSection(raw, workers);
1482
+ writeWorkersSection(raw, workers, configPath);
1428
1483
  return workers;
1429
1484
  }
1430
1485
  /** `glm/fast` | `{provider, mcp, …}` → one printable target line. */
@@ -1460,15 +1515,23 @@ function describeModels(workers) {
1460
1515
  }
1461
1516
  return lines;
1462
1517
  }
1518
+ /** Classes (in declaration order) whose target resolves to this provider. */
1519
+ function classesForProvider(workers, name) {
1520
+ return Object.entries(workers.classes).filter(([, target]) => (typeof target === "string" ? target.split("/")[0] : target.provider) === name).map(([cls]) => cls);
1521
+ }
1463
1522
  /** Human-readable provider listing (quota probe included when configured). */
1464
- function describeProviders(workers) {
1523
+ function describeProviders(workers, configPath = CONFIG_FILE) {
1465
1524
  const lines = [];
1466
1525
  const nativeActive = workers.active === ANTHROPIC_NATIVE;
1467
1526
  lines.push(`${ANTHROPIC_NATIVE} [built-in${nativeActive ? ", active" : ""}] Claude Code's own OAuth/Max-plan login — no base URL, no API key`);
1527
+ lines.push(` ${modelPrefsText(nativeAnthropicProvider(workers.nativeModels))}`);
1528
+ const nativeClasses = classesForProvider(workers, ANTHROPIC_NATIVE);
1529
+ lines.push(` classes: ${nativeClasses.length ? nativeClasses.join(", ") : "(none)"}`);
1468
1530
  const names = Object.keys(workers.providers);
1469
1531
  if (!names.length) {
1470
1532
  lines.push(`no other providers configured. Add one with:`);
1471
1533
  lines.push(` pai worker providers add <name> --base-url <url> --key-file <path> --model <model>`);
1534
+ lines.push(`config: ${existsSync(workersYamlPath()) ? workersYamlPath() : configPath}`);
1472
1535
  return lines;
1473
1536
  }
1474
1537
  for (const name of names) {
@@ -1480,17 +1543,19 @@ function describeProviders(workers) {
1480
1543
  lines.push(`${name} [${flags.join(", ")}] ${p.baseUrl}`);
1481
1544
  lines.push(` ${modelPrefsText(p)}${quotaNote}`);
1482
1545
  lines.push(` ${tierTags}`);
1546
+ if (p.key) lines.push(` key ${maskKey(p.key)}`);
1483
1547
  if (p.keyFile) lines.push(` key file ${expandHome(p.keyFile)}`);
1484
- else lines.push(` no key file (token "local")`);
1548
+ if (!p.key && !p.keyFile) lines.push(` no key file (token "local")`);
1485
1549
  if (p.note) lines.push(` ${p.note}`);
1486
1550
  if (p.protocol === "openai") lines.push(` via PAI proxy ← ${p.upstreamUrl ?? "(upstreamUrl missing)"}`);
1487
1551
  if (p.engine === "codex") lines.push(` engine codex (runs through the Codex CLI)`);
1552
+ const cls = classesForProvider(workers, name);
1553
+ lines.push(` classes: ${cls.length ? cls.join(", ") : "(none)"}`);
1488
1554
  }
1489
1555
  const setNames = Object.keys(workers.mcpSets);
1490
1556
  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
1557
  if (workers.active === "auto") lines.push(`routing: auto — order [${workers.routing.order.join(", ")}], cooldown ${workers.routing.cooldownMinutes}m`);
1558
+ lines.push(`config: ${existsSync(workersYamlPath()) ? workersYamlPath() : configPath}`);
1494
1559
  return lines;
1495
1560
  }
1496
1561
 
@@ -1509,7 +1574,7 @@ function describeProviders(workers) {
1509
1574
  * and pins the top-level `model` to the provider's default model.
1510
1575
  *
1511
1576
  * What settings.json carried before the switch is saved under
1512
- * `workers.fallback.saved` in ~/.config/pai/config.json; `fallback off`
1577
+ * `workers.fallback.saved` in the PAI config file (CONFIG_FILE); `fallback off`
1513
1578
  * restores it exactly and removes the added keys. Both files are written
1514
1579
  * atomically; nothing else in them is touched. While fallback is on the
1515
1580
  * Agent hook keeps routing subagents to workers, unchanged — those runs set
@@ -1536,12 +1601,7 @@ function fallbackNotePath(logDir) {
1536
1601
  * buildRunEnv uses), the provider's own env, and the two fallback constants.
1537
1602
  */
1538
1603
  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
- }
1604
+ const token = resolveProviderKey(provider) ?? "local";
1545
1605
  return {
1546
1606
  ANTHROPIC_BASE_URL: provider.baseUrl,
1547
1607
  ANTHROPIC_AUTH_TOKEN: token,
@@ -1764,5 +1824,5 @@ function fallbackStatusText(s) {
1764
1824
  }
1765
1825
 
1766
1826
  //#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
1827
+ 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 };
1828
+ //# sourceMappingURL=fallback-Cwt4hmh5.mjs.map