@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.
- package/ARCHITECTURE.md +9 -9
- package/README.md +26 -8
- package/dist/{aibroker-client-BP74gGwD.mjs → aibroker-client-Bn9SnGMa.mjs} +3 -3
- package/dist/{aibroker-client-BP74gGwD.mjs.map → aibroker-client-Bn9SnGMa.mjs.map} +1 -1
- package/dist/{aibroker-client-C6m71p6O.mjs → aibroker-client-D5NT0S1N.mjs} +1 -1
- package/dist/{auto-route-_5zzJz5q.mjs → auto-route-CcD0OWWB.mjs} +4 -4
- package/dist/{auto-route-_5zzJz5q.mjs.map → auto-route-CcD0OWWB.mjs.map} +1 -1
- package/dist/{chain-DTII7xeL.mjs → chain-CEC1a5mX.mjs} +5 -4
- package/dist/{chain-DTII7xeL.mjs.map → chain-CEC1a5mX.mjs.map} +1 -1
- package/dist/cli/index.mjs +23 -21
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/program.d.mts.map +1 -1
- package/dist/cli/program.mjs +23 -21
- package/dist/{clusters-j0ZuNYp9.mjs → clusters-Cw_P6lO-.mjs} +2 -2
- package/dist/{clusters-j0ZuNYp9.mjs.map → clusters-Cw_P6lO-.mjs.map} +1 -1
- package/dist/{config-B64vFg14.mjs → config-DCu8THKi.mjs} +41 -9
- package/dist/{config-B64vFg14.mjs.map → config-DCu8THKi.mjs.map} +1 -1
- package/dist/config-DeqFqa1N.mjs +3 -0
- package/dist/config-DxMZjpvY.mjs +1289 -0
- package/dist/config-DxMZjpvY.mjs.map +1 -0
- package/dist/context-handover-cache-B9NKSjwR.mjs +3242 -0
- package/dist/context-handover-cache-B9NKSjwR.mjs.map +1 -0
- package/dist/daemon/index.mjs +23 -22
- package/dist/daemon/index.mjs.map +1 -1
- package/dist/{daemon-B8N1egl0.mjs → daemon-BhldpFvO.mjs} +52 -38
- package/dist/daemon-BhldpFvO.mjs.map +1 -0
- package/dist/daemon-QIvCXB5f.mjs +24 -0
- package/dist/daemon-mcp/index.mjs +144 -117
- package/dist/daemon-mcp/index.mjs.map +1 -1
- package/dist/db-BOBfewFH.mjs +3 -0
- package/dist/{db-a1ixZQjr.mjs → db-DJ8rk0VM.mjs} +15 -6
- package/dist/{db-a1ixZQjr.mjs.map → db-DJ8rk0VM.mjs.map} +1 -1
- package/dist/db-DbY2O8QO.mjs +3 -0
- package/dist/{db-Ca5qfsMC.mjs → db-Ddns80yf.mjs} +15 -6
- package/dist/{db-Ca5qfsMC.mjs.map → db-Ddns80yf.mjs.map} +1 -1
- package/dist/{detect-CdaA48EI.mjs → detect-Bf2z-oKB.mjs} +1 -1
- package/dist/{detect-CdaA48EI.mjs.map → detect-Bf2z-oKB.mjs.map} +1 -1
- package/dist/detector-CkwkXuGh.mjs +5 -0
- package/dist/{detector-C73Nxm94.mjs → detector-DWXkeTlk.mjs} +2 -2
- package/dist/{detector-C73Nxm94.mjs.map → detector-DWXkeTlk.mjs.map} +1 -1
- package/dist/{embeddings-CEBGrzwu.mjs → embeddings-ClqKtLZ8.mjs} +1 -1
- package/dist/{embeddings-DOLZnT1X.mjs → embeddings-DvRKcQyt.mjs} +1 -1
- package/dist/{embeddings-DOLZnT1X.mjs.map → embeddings-DvRKcQyt.mjs.map} +1 -1
- package/dist/factory-47Qf_df7.mjs +3 -0
- package/dist/{factory-DEb9NmHJ.mjs → factory-DNYAqjH0.mjs} +8 -8
- package/dist/{factory-DEb9NmHJ.mjs.map → factory-DNYAqjH0.mjs.map} +1 -1
- package/dist/{fallback-oJl3BaIN.mjs → fallback-BQJ8PbCK.mjs} +185 -123
- package/dist/fallback-BQJ8PbCK.mjs.map +1 -0
- package/dist/{helpers-IjZkXBhj.mjs → helpers-crDEr6S2.mjs} +1 -1
- package/dist/{helpers-IjZkXBhj.mjs.map → helpers-crDEr6S2.mjs.map} +1 -1
- package/dist/hooks/capture-all-events.mjs +117 -34
- package/dist/hooks/capture-all-events.mjs.map +4 -4
- package/dist/hooks/capture-session-summary.mjs +110 -33
- package/dist/hooks/capture-session-summary.mjs.map +4 -4
- package/dist/hooks/capture-tool-output.mjs +105 -28
- package/dist/hooks/capture-tool-output.mjs.map +4 -4
- package/dist/hooks/cleanup-session-files.mjs +54 -13
- package/dist/hooks/cleanup-session-files.mjs.map +2 -2
- package/dist/hooks/context-compression-hook.mjs +7565 -122
- package/dist/hooks/context-compression-hook.mjs.map +4 -4
- package/dist/hooks/initialize-session.mjs +55 -14
- package/dist/hooks/initialize-session.mjs.map +2 -2
- package/dist/hooks/inject-observations.mjs +79 -18
- package/dist/hooks/inject-observations.mjs.map +3 -3
- package/dist/hooks/load-core-context.mjs +55 -14
- package/dist/hooks/load-core-context.mjs.map +2 -2
- package/dist/hooks/load-project-context.mjs +207 -122
- package/dist/hooks/load-project-context.mjs.map +4 -4
- package/dist/hooks/mcp-deferred-gate.mjs +54 -13
- package/dist/hooks/mcp-deferred-gate.mjs.map +2 -2
- package/dist/hooks/mcp-deferred-reminder.mjs +9 -0
- package/dist/hooks/mcp-deferred-reminder.mjs.map +3 -3
- package/dist/hooks/observe.mjs +54 -13
- package/dist/hooks/observe.mjs.map +2 -2
- package/dist/hooks/post-compact-inject.mjs +7419 -16
- package/dist/hooks/post-compact-inject.mjs.map +4 -4
- package/dist/hooks/route-agents-to-worker.mjs +7778 -171
- package/dist/hooks/route-agents-to-worker.mjs.map +4 -4
- package/dist/hooks/route-edits-to-worker.mjs +90 -0
- package/dist/hooks/route-edits-to-worker.mjs.map +7 -0
- package/dist/hooks/security-validator.mjs +147 -6
- package/dist/hooks/security-validator.mjs.map +4 -4
- package/dist/hooks/session-commands.mjs +9 -0
- package/dist/hooks/session-commands.mjs.map +3 -3
- package/dist/hooks/stop-hook.mjs +182 -105
- package/dist/hooks/stop-hook.mjs.map +4 -4
- package/dist/hooks/subagent-stop-hook.mjs +3 -0
- package/dist/hooks/subagent-stop-hook.mjs.map +1 -1
- package/dist/hooks/sync-todo-to-md.mjs +54 -13
- package/dist/hooks/sync-todo-to-md.mjs.map +2 -2
- package/dist/hooks/update-tab-on-action.mjs +3 -0
- package/dist/hooks/update-tab-on-action.mjs.map +1 -1
- package/dist/hooks/update-tab-titles.mjs +3 -0
- package/dist/hooks/update-tab-titles.mjs.map +1 -1
- package/dist/hooks/whisper-reinject.mjs +11 -0
- package/dist/hooks/whisper-reinject.mjs.map +3 -3
- package/dist/hooks/whisper-rules.mjs +134 -29
- package/dist/hooks/whisper-rules.mjs.map +4 -4
- package/dist/hooks/worker-proxy.mjs +7737 -117
- package/dist/hooks/worker-proxy.mjs.map +4 -4
- package/dist/hooks/worker-status-line.mjs +7883 -169
- package/dist/hooks/worker-status-line.mjs.map +4 -4
- package/dist/hooks/worker-supervision.mjs +7721 -115
- package/dist/hooks/worker-supervision.mjs.map +4 -4
- package/dist/index.d.mts +4 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +10 -10
- package/dist/{indexer-backend-BPTzKFZU.mjs → indexer-backend-CdvCJCkD.mjs} +3 -3
- package/dist/{indexer-backend-BPTzKFZU.mjs.map → indexer-backend-CdvCJCkD.mjs.map} +1 -1
- package/dist/{ipc-client-BmypMNYk.mjs → ipc-client-C6NryMMb.mjs} +2 -2
- package/dist/{ipc-client-BmypMNYk.mjs.map → ipc-client-C6NryMMb.mjs.map} +1 -1
- package/dist/{kg-entity-r8duqhi9.mjs → kg-entity-BSjM5xZh.mjs} +1 -1
- package/dist/{kg-entity-r8duqhi9.mjs.map → kg-entity-BSjM5xZh.mjs.map} +1 -1
- package/dist/{latent-ideas-CtSca4qG.mjs → latent-ideas-BfL4nCQ3.mjs} +4 -4
- package/dist/{latent-ideas-CtSca4qG.mjs.map → latent-ideas-BfL4nCQ3.mjs.map} +1 -1
- package/dist/{link-boost-Bucnz3n8.mjs → link-boost-C5PaNdzm.mjs} +1 -1
- package/dist/{link-boost-Bucnz3n8.mjs.map → link-boost-C5PaNdzm.mjs.map} +1 -1
- package/dist/main-resolver-CnfnWa8C.mjs +7 -0
- package/dist/{main-resolver-DnkxPYkr.mjs → main-resolver-DvYu9jbl.mjs} +21 -11
- package/dist/main-resolver-DvYu9jbl.mjs.map +1 -0
- package/dist/{migrate-Cjzeefn9.mjs → migrate-CfERwXhY.mjs} +2 -2
- package/dist/{migrate-Cjzeefn9.mjs.map → migrate-CfERwXhY.mjs.map} +1 -1
- package/dist/{neighborhood-CM7Jgb51.mjs → neighborhood-CETR_P4y.mjs} +2 -2
- package/dist/{neighborhood-CM7Jgb51.mjs.map → neighborhood-CETR_P4y.mjs.map} +1 -1
- package/dist/{note-context-DCwE2A-M.mjs → note-context-DCcRWBoN.mjs} +1 -1
- package/dist/{note-context-DCwE2A-M.mjs.map → note-context-DCcRWBoN.mjs.map} +1 -1
- package/dist/pai-home-ChAOupZc.mjs +164 -0
- package/dist/pai-home-ChAOupZc.mjs.map +1 -0
- package/dist/{pai-marker-CHtbJMwJ.mjs → pai-marker-B20KqhA8.mjs} +1 -1
- package/dist/{pai-marker-CHtbJMwJ.mjs.map → pai-marker-B20KqhA8.mjs.map} +1 -1
- package/dist/{planner-D5Ui7DAm.mjs → planner-BlKGgpWI.mjs} +7 -6
- package/dist/{planner-D5Ui7DAm.mjs.map → planner-BlKGgpWI.mjs.map} +1 -1
- package/dist/{postgres-CtOzfoQU.mjs → postgres-CUSXWgTG.mjs} +2 -2
- package/dist/{postgres-CtOzfoQU.mjs.map → postgres-CUSXWgTG.mjs.map} +1 -1
- package/dist/{program-zpoYnJGz.mjs → program-C5jRQ1kg.mjs} +8880 -5913
- package/dist/program-C5jRQ1kg.mjs.map +1 -0
- package/dist/query-feedback-C7rSfiXU.mjs +3 -0
- package/dist/{query-feedback-Dqz-HC__.mjs → query-feedback-CYyOGi3y.mjs} +20 -6
- package/dist/query-feedback-CYyOGi3y.mjs.map +1 -0
- package/dist/{reranker-CwTCNsgA.mjs → reranker-B5qUTamW.mjs} +1 -1
- package/dist/{reranker-xPm04PXx.mjs → reranker-HHmhZk6v.mjs} +1 -1
- package/dist/{reranker-xPm04PXx.mjs.map → reranker-HHmhZk6v.mjs.map} +1 -1
- package/dist/router-CremHKTI.mjs +3 -0
- package/dist/{router-DD6D4j31.mjs → router-DBAZfE7X.mjs} +2 -2
- package/dist/{router-DD6D4j31.mjs.map → router-DBAZfE7X.mjs.map} +1 -1
- package/dist/{run-D7K5UALn.mjs → run-ByBKowN5.mjs} +980 -247
- package/dist/run-ByBKowN5.mjs.map +1 -0
- package/dist/{runtime-paths-rni52zHX.mjs → runtime-paths-B0P1TvUr.mjs} +1 -1
- package/dist/{runtime-paths-rni52zHX.mjs.map → runtime-paths-B0P1TvUr.mjs.map} +1 -1
- package/dist/{search-Rpk1cSBC.mjs → search-B69cQwDB.mjs} +3 -3
- package/dist/{search-Rpk1cSBC.mjs.map → search-B69cQwDB.mjs.map} +1 -1
- package/dist/{search-CfPpJAWQ.mjs → search-fb-5ovj4.mjs} +2 -2
- package/dist/{server-D4vAieF4.mjs → server-Ch99xt5K.mjs} +15 -14
- package/dist/server-Ch99xt5K.mjs.map +1 -0
- package/dist/skills/Advisor/SKILL.md +3 -3
- package/dist/skills/Providers/SKILL.md +30 -0
- package/dist/skills/Reconstruct/SKILL.md +1 -1
- package/dist/skills/VaultContext/SKILL.md +1 -1
- package/dist/skills/Whisper/SKILL.md +3 -3
- package/dist/skills/Worker/SKILL.md +1 -1
- package/dist/{sources-CS43CpuS.mjs → sources-KBGEA_E6.mjs} +2 -2
- package/dist/{sources-CS43CpuS.mjs.map → sources-KBGEA_E6.mjs.map} +1 -1
- package/dist/{sqlite-Cq3gJcq9.mjs → sqlite-By6r2YhZ.mjs} +3 -3
- package/dist/{sqlite-Cq3gJcq9.mjs.map → sqlite-By6r2YhZ.mjs.map} +1 -1
- package/dist/{state-CY6I-Hnc.mjs → state-DnYGRmS7.mjs} +1 -1
- package/dist/{state-BRdB-Bf1.mjs → state-PJrgfDLW.mjs} +1 -1
- package/dist/{state-BRdB-Bf1.mjs.map → state-PJrgfDLW.mjs.map} +1 -1
- package/dist/{stop-words-Hfu8u22w.mjs → stop-words-BaMEGVeY.mjs} +1 -1
- package/dist/{stop-words-Hfu8u22w.mjs.map → stop-words-BaMEGVeY.mjs.map} +1 -1
- package/dist/{sync-BWbe8JTg.mjs → sync-Btcb6xA4.mjs} +3 -3
- package/dist/{sync-BWbe8JTg.mjs.map → sync-Btcb6xA4.mjs.map} +1 -1
- package/dist/{themes-B7h9YDiy.mjs → themes-BVoAnLZj.mjs} +3 -3
- package/dist/{themes-B7h9YDiy.mjs.map → themes-BVoAnLZj.mjs.map} +1 -1
- package/dist/{tools-BW3NLMPk.mjs → tools-CAG2sUjf.mjs} +4 -3
- package/dist/{tools-LlzcV_eK.mjs → tools-DiRC5glA.mjs} +30 -233
- package/dist/tools-DiRC5glA.mjs.map +1 -0
- package/dist/{trace-u4hT-pLD.mjs → trace-Cy8quQTm.mjs} +1 -1
- package/dist/{trace-u4hT-pLD.mjs.map → trace-Cy8quQTm.mjs.map} +1 -1
- package/dist/{utils-DhMex3Ox.mjs → utils-BD8g8oSf.mjs} +1 -1
- package/dist/{utils-9Err2RBW.mjs → utils-CJymHkYm.mjs} +1 -1
- package/dist/{utils-9Err2RBW.mjs.map → utils-CJymHkYm.mjs.map} +1 -1
- package/dist/{vault-indexer-mata9S7b.mjs → vault-indexer-C5i-OAyr.mjs} +2 -2
- package/dist/{vault-indexer-mata9S7b.mjs.map → vault-indexer-C5i-OAyr.mjs.map} +1 -1
- package/dist/wakeup-BfElduEU.mjs +231 -0
- package/dist/wakeup-BfElduEU.mjs.map +1 -0
- package/dist/work-queue-worker-BA5IDBwQ.mjs +567 -0
- package/dist/work-queue-worker-BA5IDBwQ.mjs.map +1 -0
- package/dist/work-queue-worker-DLM2wlqM.mjs +14 -0
- package/dist/{zettelkasten-F0D_XfQ4.mjs → zettelkasten-BBjA7GcP.mjs} +4 -4
- package/dist/{zettelkasten-F0D_XfQ4.mjs.map → zettelkasten-BBjA7GcP.mjs.map} +1 -1
- package/docs/commands/README.md +32 -3
- package/docs/commands/audit.md +113 -0
- package/docs/commands/backup.md +2 -2
- package/docs/commands/clear-names.md +1 -1
- package/docs/commands/config.md +59 -0
- package/docs/commands/daemon.md +1 -1
- package/docs/commands/db.md +1 -1
- package/docs/commands/end.md +1 -1
- package/docs/commands/help.md +1 -1
- package/docs/commands/identity.md +1 -1
- package/docs/commands/kg.md +1 -1
- package/docs/commands/launch.md +45 -0
- package/docs/commands/mcp.md +1 -1
- package/docs/commands/memory.md +3 -3
- package/docs/commands/notify.md +1 -1
- package/docs/commands/observation.md +1 -1
- package/docs/commands/obsidian.md +1 -1
- package/docs/commands/pause.md +1 -1
- package/docs/commands/project.md +46 -1
- package/docs/commands/projects.md +46 -1
- package/docs/commands/registry.md +1 -1
- package/docs/commands/restore.md +1 -1
- package/docs/commands/session.md +1 -1
- package/docs/commands/sessions.md +1 -1
- package/docs/commands/setup.md +1 -1
- package/docs/commands/shell-init.md +1 -1
- package/docs/commands/skill.md +1 -1
- package/docs/commands/task.md +1 -1
- package/docs/commands/topic.md +1 -1
- package/docs/commands/update.md +1 -1
- package/docs/commands/worker.md +97 -6
- package/docs/commands/zettel.md +1 -1
- package/docs/provider-abstraction.md +1 -1
- package/docs/provider-independence-details.md +8 -5
- package/docs/task-bus.md +1 -1
- package/docs/worker.md +136 -83
- package/docs/workers-config.md +446 -0
- package/package.json +4 -2
- package/scripts/build-hooks.mjs +58 -3
- package/src/hooks/pre-compact.sh +5 -2
- package/src/hooks/session-stop.sh +29 -4
- package/src/hooks/ts/capture-all-events.ts +3 -3
- package/src/hooks/ts/lib/advisor-budget.test.ts +98 -0
- package/src/hooks/ts/lib/advisor-budget.ts +90 -0
- package/src/hooks/ts/lib/agent-gate.test.ts +101 -0
- package/src/hooks/ts/lib/agent-gate.ts +112 -0
- package/src/hooks/ts/lib/context-fill.ts +2 -2
- package/src/hooks/ts/lib/edit-gate.test.ts +52 -0
- package/src/hooks/ts/lib/edit-gate.ts +51 -0
- package/src/hooks/ts/lib/mcp-deferred-reminder.test.ts +8 -0
- package/src/hooks/ts/lib/pai-paths.test.ts +93 -0
- package/src/hooks/ts/lib/pai-paths.ts +168 -24
- package/src/hooks/ts/lib/project-utils/index.ts +1 -0
- package/src/hooks/ts/lib/project-utils/paths.ts +5 -4
- package/src/hooks/ts/lib/project-utils.ts +1 -0
- package/src/hooks/ts/post-tool-use/capture-tool-output.ts +2 -2
- package/src/hooks/ts/post-tool-use/whisper-reinject.test.ts +55 -0
- package/src/hooks/ts/post-tool-use/whisper-reinject.ts +3 -0
- package/src/hooks/ts/pre-compact/context-compression-hook.ts +1 -1
- package/src/hooks/ts/pre-tool-use/route-agents-to-worker.ts +46 -99
- package/src/hooks/ts/pre-tool-use/route-edits-to-worker.test.ts +47 -0
- package/src/hooks/ts/pre-tool-use/route-edits-to-worker.ts +96 -0
- package/src/hooks/ts/pre-tool-use/security-validator.ts +2 -1
- package/src/hooks/ts/session-end/capture-session-summary.ts +4 -4
- package/src/hooks/ts/session-start/initialize-session.ts +3 -3
- package/src/hooks/ts/session-start/inject-observations.test.ts +56 -0
- package/src/hooks/ts/session-start/inject-observations.ts +28 -8
- package/src/hooks/ts/session-start/load-core-context.ts +4 -4
- package/src/hooks/ts/session-start/load-project-context.ts +2 -2
- package/src/hooks/ts/session-start/mcp-deferred-reminder.ts +2 -0
- package/src/hooks/ts/session-start/session-commands.ts +4 -0
- package/src/hooks/ts/session-start/session-start-worker-guard.test.ts +36 -0
- package/src/hooks/ts/stop/stop-hook.ts +6 -11
- package/src/hooks/ts/user-prompt/whisper-rules.test.ts +49 -0
- package/src/hooks/ts/user-prompt/whisper-rules.ts +88 -47
- package/src/hooks/ztk-auto.sh +28 -0
- package/src/hooks/ztk-auto.test.ts +72 -0
- package/src/hooks/ztk-passthrough.mjs +71 -0
- package/statusline-command.sh +277 -116
- package/templates/agent-prefs.example.md +8 -8
- package/templates/claude-md.template.md +1 -1
- package/templates/voices.example.json +3 -3
- package/dist/config-C_ErGddD.mjs +0 -3
- package/dist/config-_lQI_W08.mjs +0 -640
- package/dist/config-_lQI_W08.mjs.map +0 -1
- package/dist/context-handover-cache-pNFdBNrU.mjs +0 -1548
- package/dist/context-handover-cache-pNFdBNrU.mjs.map +0 -1
- package/dist/daemon-B8N1egl0.mjs.map +0 -1
- package/dist/daemon-DHfyoTlk.mjs +0 -23
- package/dist/db-O-cyAPfS.mjs +0 -3
- package/dist/db-XEwJbuGO.mjs +0 -3
- package/dist/detector-C-7KRi42.mjs +0 -5
- package/dist/factory-Dbo8yNPi.mjs +0 -3
- package/dist/fallback-oJl3BaIN.mjs.map +0 -1
- package/dist/main-resolver-BAfOMppW.mjs +0 -7
- package/dist/main-resolver-DnkxPYkr.mjs.map +0 -1
- package/dist/program-zpoYnJGz.mjs.map +0 -1
- package/dist/query-feedback-DGoVRaWD.mjs +0 -3
- package/dist/query-feedback-Dqz-HC__.mjs.map +0 -1
- package/dist/router-BTIGZR2_.mjs +0 -3
- package/dist/run-D7K5UALn.mjs.map +0 -1
- package/dist/server-D4vAieF4.mjs.map +0 -1
- package/dist/tools-LlzcV_eK.mjs.map +0 -1
- package/dist/work-queue-worker-AEmfVE0F.mjs +0 -14
- package/dist/work-queue-worker-DIT-VLSh.mjs +0 -2136
- package/dist/work-queue-worker-DIT-VLSh.mjs.map +0 -1
- /package/dist/{indexer-D7MvSQPY.mjs → indexer-C5Le7XE7.mjs} +0 -0
|
@@ -1,12 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { C as
|
|
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
|
-
|
|
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
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
*
|
|
565
|
-
*
|
|
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
|
|
568
|
-
const
|
|
569
|
-
if (
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
}
|
|
574
|
-
|
|
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
|
|
578
|
-
*
|
|
579
|
-
*
|
|
580
|
-
*
|
|
581
|
-
*
|
|
582
|
-
*
|
|
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
|
-
|
|
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))
|
|
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 (
|
|
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
|
-
|
|
604
|
-
if (
|
|
605
|
-
|
|
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 =
|
|
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
|
-
*
|
|
1265
|
-
*
|
|
1266
|
-
*
|
|
1267
|
-
*
|
|
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(
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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-
|
|
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
|