@tekmidian/pai 0.42.5 → 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.
- 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-BbcfP77K.mjs} +5 -4
- package/dist/{chain-DTII7xeL.mjs.map → chain-BbcfP77K.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-BNjbVsQU.mjs +24 -0
- package/dist/{daemon-B8N1egl0.mjs → daemon-BppziPi6.mjs} +52 -38
- package/dist/daemon-BppziPi6.mjs.map +1 -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-Cwt4hmh5.mjs} +182 -122
- package/dist/fallback-Cwt4hmh5.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 +185 -103
- 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 +3 -0
- package/dist/hooks/whisper-reinject.mjs.map +1 -1
- 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 +7791 -144
- 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-pXRc-8yt.mjs} +7 -6
- package/dist/{planner-D5Ui7DAm.mjs.map → planner-pXRc-8yt.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-LLNPpxlj.mjs} +8308 -6065
- package/dist/program-LLNPpxlj.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-DDdT9teG.mjs} +530 -210
- package/dist/run-DDdT9teG.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-BradfQk7.mjs} +4 -3
- package/dist/{tools-LlzcV_eK.mjs → tools-UrSHIe29.mjs} +30 -233
- package/dist/tools-UrSHIe29.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-TnGjJY3I.mjs +218 -0
- package/dist/wakeup-TnGjJY3I.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 +30 -3
- package/docs/commands/audit.md +88 -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 +95 -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 +56 -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/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/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
package/dist/hooks/stop-hook.mjs
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __paiCreateRequire } from 'node:module';
|
|
3
|
+
const require = __paiCreateRequire(import.meta.url);
|
|
4
|
+
if (!process.env.PAI_QUIET_NOTICES) process.env.PAI_QUIET_NOTICES = '1';
|
|
2
5
|
|
|
3
6
|
// src/hooks/ts/lib/worker-session.ts
|
|
4
7
|
function isWorkerSession(env = process.env) {
|
|
@@ -6,28 +9,58 @@ function isWorkerSession(env = process.env) {
|
|
|
6
9
|
}
|
|
7
10
|
|
|
8
11
|
// src/hooks/ts/stop/stop-hook.ts
|
|
9
|
-
import { readFileSync as
|
|
10
|
-
import { join as
|
|
12
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync6, existsSync as existsSync8, unlinkSync } from "fs";
|
|
13
|
+
import { join as join9, basename as basename4, dirname as dirname2 } from "path";
|
|
11
14
|
import { connect } from "net";
|
|
12
15
|
import { randomUUID } from "crypto";
|
|
13
16
|
|
|
14
17
|
// src/hooks/ts/lib/project-utils/paths.ts
|
|
15
|
-
import { existsSync as
|
|
16
|
-
import { join as
|
|
18
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync as readdirSync2, linkSync, copyFileSync as copyFileSync2 } from "fs";
|
|
19
|
+
import { join as join3, basename } from "path";
|
|
20
|
+
|
|
21
|
+
// src/hooks/ts/lib/pai-paths.ts
|
|
22
|
+
import { homedir as homedir2 } from "os";
|
|
23
|
+
import { resolve, join as join2 } from "path";
|
|
24
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
25
|
+
|
|
26
|
+
// src/config/pai-home.ts
|
|
27
|
+
import { existsSync, mkdirSync, readFileSync, copyFileSync, renameSync, readdirSync, statSync } from "node:fs";
|
|
28
|
+
import { homedir } from "node:os";
|
|
29
|
+
import { join, dirname } from "node:path";
|
|
30
|
+
function paiHomeDir() {
|
|
31
|
+
return process.env.PAI_HOME || join(homedir(), ".claude", "pai");
|
|
32
|
+
}
|
|
33
|
+
function paiHomePath(...segments) {
|
|
34
|
+
return join(paiHomeDir(), ...segments);
|
|
35
|
+
}
|
|
36
|
+
var noticesPrinted = /* @__PURE__ */ new Set();
|
|
37
|
+
function resolvePaiFile(newPath, oldCandidates, migrateHint) {
|
|
38
|
+
if (existsSync(newPath)) return newPath;
|
|
39
|
+
for (const old of oldCandidates) {
|
|
40
|
+
if (existsSync(old)) {
|
|
41
|
+
if (!noticesPrinted.has(newPath)) {
|
|
42
|
+
noticesPrinted.add(newPath);
|
|
43
|
+
process.stderr.write(
|
|
44
|
+
`pai: ${old} is at an old location \u2014 run \`${migrateHint}\` to move it to ${newPath}
|
|
45
|
+
`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return old;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return newPath;
|
|
52
|
+
}
|
|
17
53
|
|
|
18
54
|
// src/hooks/ts/lib/pai-paths.ts
|
|
19
|
-
import { homedir } from "os";
|
|
20
|
-
import { resolve, join } from "path";
|
|
21
|
-
import { existsSync, readFileSync } from "fs";
|
|
22
55
|
function loadEnvFile() {
|
|
23
56
|
const possiblePaths = [
|
|
24
|
-
resolve(process.env.PAI_DIR || "", ".env"),
|
|
25
|
-
resolve(
|
|
57
|
+
resolve(process.env.ADAPTER_DIR || process.env.PAI_DIR || "", ".env"),
|
|
58
|
+
resolve(homedir2(), ".claude", ".env")
|
|
26
59
|
];
|
|
27
60
|
for (const envPath of possiblePaths) {
|
|
28
|
-
if (
|
|
61
|
+
if (existsSync2(envPath)) {
|
|
29
62
|
try {
|
|
30
|
-
const content =
|
|
63
|
+
const content = readFileSync2(envPath, "utf-8");
|
|
31
64
|
for (const line of content.split("\n")) {
|
|
32
65
|
const trimmed = line.trim();
|
|
33
66
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -38,8 +71,8 @@ function loadEnvFile() {
|
|
|
38
71
|
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
39
72
|
value = value.slice(1, -1);
|
|
40
73
|
}
|
|
41
|
-
value = value.replace(/\$HOME/g,
|
|
42
|
-
value = value.replace(/^~(?=\/|$)/,
|
|
74
|
+
value = value.replace(/\$HOME/g, homedir2());
|
|
75
|
+
value = value.replace(/^~(?=\/|$)/, homedir2());
|
|
43
76
|
if (process.env[key] === void 0) {
|
|
44
77
|
process.env[key] = value;
|
|
45
78
|
}
|
|
@@ -52,29 +85,67 @@ function loadEnvFile() {
|
|
|
52
85
|
}
|
|
53
86
|
}
|
|
54
87
|
loadEnvFile();
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
88
|
+
function defaultAdapterDir() {
|
|
89
|
+
return resolve(homedir2(), ".claude");
|
|
90
|
+
}
|
|
91
|
+
function suppressDeprecationNotices() {
|
|
92
|
+
if (process.env.PAI_QUIET_NOTICES === "1") return true;
|
|
93
|
+
const idx = process.argv.indexOf("--output-format");
|
|
94
|
+
return idx !== -1 && process.argv[idx + 1] === "json";
|
|
95
|
+
}
|
|
96
|
+
function warnPaiDirDeprecatedOnce(message) {
|
|
97
|
+
const g = globalThis;
|
|
98
|
+
if (g.__paiDirNoticePrinted || suppressDeprecationNotices()) return;
|
|
99
|
+
g.__paiDirNoticePrinted = true;
|
|
100
|
+
process.stderr.write(`pai: ${message}
|
|
101
|
+
`);
|
|
102
|
+
}
|
|
103
|
+
function resolveAdapterDir() {
|
|
104
|
+
if (process.env.ADAPTER_DIR) {
|
|
105
|
+
const adapterDir = resolve(process.env.ADAPTER_DIR);
|
|
106
|
+
if (process.env.PAI_DIR) {
|
|
107
|
+
const paiDir = resolve(process.env.PAI_DIR);
|
|
108
|
+
if (paiDir !== adapterDir) {
|
|
109
|
+
warnPaiDirDeprecatedOnce(
|
|
110
|
+
`ADAPTER_DIR (${adapterDir}) and PAI_DIR (${paiDir}) are both set and differ \u2014 ADAPTER_DIR wins. PAI_DIR still works for one release.`
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return adapterDir;
|
|
115
|
+
}
|
|
116
|
+
if (process.env.PAI_DIR) {
|
|
117
|
+
const paiDir = resolve(process.env.PAI_DIR);
|
|
118
|
+
if (paiDir !== defaultAdapterDir()) {
|
|
119
|
+
warnPaiDirDeprecatedOnce(
|
|
120
|
+
"PAI_DIR is deprecated \u2014 use ADAPTER_DIR for the harness adapter root (~/.claude). PAI_DIR still works for one release."
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
return paiDir;
|
|
124
|
+
}
|
|
125
|
+
return defaultAdapterDir();
|
|
126
|
+
}
|
|
127
|
+
var ADAPTER_DIR = resolveAdapterDir();
|
|
128
|
+
var HOOKS_DIR = join2(ADAPTER_DIR, "Hooks");
|
|
129
|
+
var SKILLS_DIR = join2(ADAPTER_DIR, "Skills");
|
|
130
|
+
var AGENTS_DIR = join2(ADAPTER_DIR, "Agents");
|
|
131
|
+
var COMMANDS_DIR = join2(ADAPTER_DIR, "Commands");
|
|
61
132
|
function validatePAIStructure() {
|
|
62
|
-
if (!
|
|
63
|
-
console.error(`
|
|
64
|
-
console.error(` Expected ~/.claude or set
|
|
133
|
+
if (!existsSync2(ADAPTER_DIR)) {
|
|
134
|
+
console.error(`ADAPTER_DIR does not exist: ${ADAPTER_DIR}`);
|
|
135
|
+
console.error(` Expected ~/.claude or set ADAPTER_DIR environment variable`);
|
|
65
136
|
process.exit(1);
|
|
66
137
|
}
|
|
67
|
-
if (!
|
|
138
|
+
if (!existsSync2(HOOKS_DIR)) {
|
|
68
139
|
console.error(`PAI hooks directory not found: ${HOOKS_DIR}`);
|
|
69
|
-
console.error(` Your
|
|
70
|
-
console.error(` Current
|
|
140
|
+
console.error(` Your ADAPTER_DIR may be misconfigured`);
|
|
141
|
+
console.error(` Current ADAPTER_DIR: ${ADAPTER_DIR}`);
|
|
71
142
|
process.exit(1);
|
|
72
143
|
}
|
|
73
144
|
}
|
|
74
145
|
validatePAIStructure();
|
|
75
146
|
|
|
76
147
|
// src/hooks/ts/lib/project-utils/paths.ts
|
|
77
|
-
var PROJECTS_DIR =
|
|
148
|
+
var PROJECTS_DIR = join3(ADAPTER_DIR, "projects");
|
|
78
149
|
var PROBE_CWD_PATTERNS = [
|
|
79
150
|
"/CodexBar/ClaudeProbe",
|
|
80
151
|
"/ClaudeProbe"
|
|
@@ -88,56 +159,56 @@ function encodePath(path) {
|
|
|
88
159
|
}
|
|
89
160
|
function getProjectDir(cwd) {
|
|
90
161
|
const encoded = encodePath(cwd);
|
|
91
|
-
return
|
|
162
|
+
return join3(PROJECTS_DIR, encoded);
|
|
92
163
|
}
|
|
93
164
|
function getNotesDir(cwd) {
|
|
94
|
-
return
|
|
165
|
+
return join3(getProjectDir(cwd), "Notes");
|
|
95
166
|
}
|
|
96
167
|
function findNotesDir(cwd) {
|
|
97
168
|
const cwdBasename = basename(cwd).toLowerCase();
|
|
98
|
-
if (cwdBasename === "notes" &&
|
|
169
|
+
if (cwdBasename === "notes" && existsSync3(cwd)) {
|
|
99
170
|
return { path: cwd, isLocal: true };
|
|
100
171
|
}
|
|
101
172
|
const localPaths = [
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
173
|
+
join3(cwd, "Notes"),
|
|
174
|
+
join3(cwd, "notes"),
|
|
175
|
+
join3(cwd, ".claude", "Notes")
|
|
105
176
|
];
|
|
106
177
|
for (const path of localPaths) {
|
|
107
|
-
if (
|
|
178
|
+
if (existsSync3(path)) {
|
|
108
179
|
return { path, isLocal: true };
|
|
109
180
|
}
|
|
110
181
|
}
|
|
111
182
|
return { path: getNotesDir(cwd), isLocal: false };
|
|
112
183
|
}
|
|
113
184
|
function getSessionsDirFromProjectDir(projectDir) {
|
|
114
|
-
return
|
|
185
|
+
return join3(projectDir, "sessions");
|
|
115
186
|
}
|
|
116
187
|
function ensureSessionsDirFromProjectDir(projectDir) {
|
|
117
188
|
const sessionsDir = getSessionsDirFromProjectDir(projectDir);
|
|
118
|
-
if (!
|
|
119
|
-
|
|
189
|
+
if (!existsSync3(sessionsDir)) {
|
|
190
|
+
mkdirSync2(sessionsDir, { recursive: true });
|
|
120
191
|
console.error(`Created sessions directory: ${sessionsDir}`);
|
|
121
192
|
}
|
|
122
193
|
return sessionsDir;
|
|
123
194
|
}
|
|
124
195
|
function archiveSessionFilesToSessionsDir(projectDir, excludeFile, silent = false) {
|
|
125
196
|
const sessionsDir = ensureSessionsDirFromProjectDir(projectDir);
|
|
126
|
-
if (!
|
|
127
|
-
const files =
|
|
197
|
+
if (!existsSync3(projectDir)) return 0;
|
|
198
|
+
const files = readdirSync2(projectDir);
|
|
128
199
|
let archivedCount = 0;
|
|
129
200
|
for (const file of files) {
|
|
130
201
|
if (!file.endsWith(".jsonl") || file === excludeFile) continue;
|
|
131
|
-
const sourcePath =
|
|
132
|
-
const destPath =
|
|
133
|
-
if (
|
|
202
|
+
const sourcePath = join3(projectDir, file);
|
|
203
|
+
const destPath = join3(sessionsDir, file);
|
|
204
|
+
if (existsSync3(destPath)) continue;
|
|
134
205
|
try {
|
|
135
206
|
linkSync(sourcePath, destPath);
|
|
136
207
|
if (!silent) console.error(`Archived ${file} \u2192 sessions/ (still resumable)`);
|
|
137
208
|
archivedCount++;
|
|
138
209
|
} catch (error) {
|
|
139
210
|
try {
|
|
140
|
-
|
|
211
|
+
copyFileSync2(sourcePath, destPath);
|
|
141
212
|
if (!silent) console.error(`Copied ${file} \u2192 sessions/ (hardlink unavailable)`);
|
|
142
213
|
archivedCount++;
|
|
143
214
|
} catch {
|
|
@@ -149,26 +220,26 @@ function archiveSessionFilesToSessionsDir(projectDir, excludeFile, silent = fals
|
|
|
149
220
|
}
|
|
150
221
|
function findTodoPath(cwd) {
|
|
151
222
|
const localPaths = [
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
223
|
+
join3(cwd, "TODO.md"),
|
|
224
|
+
join3(cwd, "notes", "TODO.md"),
|
|
225
|
+
join3(cwd, "Notes", "TODO.md"),
|
|
226
|
+
join3(cwd, ".claude", "TODO.md")
|
|
156
227
|
];
|
|
157
228
|
for (const path of localPaths) {
|
|
158
|
-
if (
|
|
229
|
+
if (existsSync3(path)) return path;
|
|
159
230
|
}
|
|
160
|
-
return
|
|
231
|
+
return join3(getNotesDir(cwd), "TODO.md");
|
|
161
232
|
}
|
|
162
233
|
|
|
163
234
|
// src/hooks/ts/lib/project-utils/notify.ts
|
|
164
|
-
import { existsSync as
|
|
165
|
-
import { join as
|
|
166
|
-
import { homedir as
|
|
235
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
236
|
+
import { join as join4 } from "path";
|
|
237
|
+
import { homedir as homedir3 } from "os";
|
|
167
238
|
function isWhatsAppEnabled() {
|
|
168
239
|
try {
|
|
169
|
-
const settingsPath =
|
|
170
|
-
if (!
|
|
171
|
-
const settings = JSON.parse(
|
|
240
|
+
const settingsPath = join4(homedir3(), ".claude", "settings.json");
|
|
241
|
+
if (!existsSync4(settingsPath)) return false;
|
|
242
|
+
const settings = JSON.parse(readFileSync3(settingsPath, "utf-8"));
|
|
172
243
|
const enabled = settings.enabledMcpjsonServers || [];
|
|
173
244
|
return enabled.includes("aibroker") || enabled.includes("whazaa") || enabled.includes("telex");
|
|
174
245
|
} catch {
|
|
@@ -213,40 +284,40 @@ async function sendNtfyNotification(message, retries = 2) {
|
|
|
213
284
|
}
|
|
214
285
|
|
|
215
286
|
// src/hooks/ts/lib/project-utils/session-notes.ts
|
|
216
|
-
import { existsSync as
|
|
217
|
-
import { join as
|
|
287
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync3, readdirSync as readdirSync3, readFileSync as readFileSync4, writeFileSync, renameSync as renameSync2 } from "fs";
|
|
288
|
+
import { join as join5, basename as basename2 } from "path";
|
|
218
289
|
function getCurrentNotePath(notesDir) {
|
|
219
|
-
if (!
|
|
290
|
+
if (!existsSync5(notesDir)) return null;
|
|
220
291
|
const findLatestIn = (dir) => {
|
|
221
|
-
if (!
|
|
222
|
-
const files =
|
|
292
|
+
if (!existsSync5(dir)) return null;
|
|
293
|
+
const files = readdirSync3(dir).filter((f) => f.match(/^\d{3,4}[\s_-].*\.md$/)).sort((a, b) => {
|
|
223
294
|
const numA = parseInt(a.match(/^(\d+)/)?.[1] || "0", 10);
|
|
224
295
|
const numB = parseInt(b.match(/^(\d+)/)?.[1] || "0", 10);
|
|
225
296
|
return numA - numB;
|
|
226
297
|
});
|
|
227
298
|
if (files.length === 0) return null;
|
|
228
|
-
return
|
|
299
|
+
return join5(dir, files[files.length - 1]);
|
|
229
300
|
};
|
|
230
301
|
const now = /* @__PURE__ */ new Date();
|
|
231
302
|
const year = String(now.getFullYear());
|
|
232
303
|
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
233
|
-
const currentMonthDir =
|
|
304
|
+
const currentMonthDir = join5(notesDir, year, month);
|
|
234
305
|
const found = findLatestIn(currentMonthDir);
|
|
235
306
|
if (found) return found;
|
|
236
307
|
const prevDate = new Date(now.getFullYear(), now.getMonth() - 1, 1);
|
|
237
308
|
const prevYear = String(prevDate.getFullYear());
|
|
238
309
|
const prevMonth = String(prevDate.getMonth() + 1).padStart(2, "0");
|
|
239
|
-
const prevMonthDir =
|
|
310
|
+
const prevMonthDir = join5(notesDir, prevYear, prevMonth);
|
|
240
311
|
const prevFound = findLatestIn(prevMonthDir);
|
|
241
312
|
if (prevFound) return prevFound;
|
|
242
313
|
return findLatestIn(notesDir);
|
|
243
314
|
}
|
|
244
315
|
function addWorkToSessionNote(notePath, workItems, sectionTitle) {
|
|
245
|
-
if (!
|
|
316
|
+
if (!existsSync5(notePath)) {
|
|
246
317
|
console.error(`Note file not found: ${notePath}`);
|
|
247
318
|
return;
|
|
248
319
|
}
|
|
249
|
-
let content =
|
|
320
|
+
let content = readFileSync4(notePath, "utf-8");
|
|
250
321
|
let workText = "";
|
|
251
322
|
if (sectionTitle) workText += `
|
|
252
323
|
### ${sectionTitle}
|
|
@@ -335,8 +406,8 @@ function extractMeaningfulName(noteContent, summary) {
|
|
|
335
406
|
return "";
|
|
336
407
|
}
|
|
337
408
|
function renameSessionNote(notePath, meaningfulName) {
|
|
338
|
-
if (!meaningfulName || !
|
|
339
|
-
const dir =
|
|
409
|
+
if (!meaningfulName || !existsSync5(notePath)) return notePath;
|
|
410
|
+
const dir = join5(notePath, "..");
|
|
340
411
|
const oldFilename = basename2(notePath);
|
|
341
412
|
const correctMatch = oldFilename.match(/^(\d{3,4}) - (\d{4}-\d{2}-\d{2}) - .*\.md$/);
|
|
342
413
|
const legacyMatch = oldFilename.match(/^(\d{3,4})_(\d{4}-\d{2}-\d{2})_.*\.md$/);
|
|
@@ -346,10 +417,10 @@ function renameSessionNote(notePath, meaningfulName) {
|
|
|
346
417
|
const titleCaseName = meaningfulName.split(/[\s_-]+/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ").trim();
|
|
347
418
|
const paddedNumber = noteNumber.padStart(4, "0");
|
|
348
419
|
const newFilename = `${paddedNumber} - ${date} - ${titleCaseName}.md`;
|
|
349
|
-
const newPath =
|
|
420
|
+
const newPath = join5(dir, newFilename);
|
|
350
421
|
if (newFilename === oldFilename) return notePath;
|
|
351
422
|
try {
|
|
352
|
-
|
|
423
|
+
renameSync2(notePath, newPath);
|
|
353
424
|
console.error(`Renamed note: ${oldFilename} \u2192 ${newFilename}`);
|
|
354
425
|
return newPath;
|
|
355
426
|
} catch (error) {
|
|
@@ -358,11 +429,11 @@ function renameSessionNote(notePath, meaningfulName) {
|
|
|
358
429
|
}
|
|
359
430
|
}
|
|
360
431
|
function finalizeSessionNote(notePath, summary) {
|
|
361
|
-
if (!
|
|
432
|
+
if (!existsSync5(notePath)) {
|
|
362
433
|
console.error(`Note file not found: ${notePath}`);
|
|
363
434
|
return notePath;
|
|
364
435
|
}
|
|
365
|
-
let content =
|
|
436
|
+
let content = readFileSync4(notePath, "utf-8");
|
|
366
437
|
if (content.includes("**Status:** Completed")) {
|
|
367
438
|
console.error(`Note already finalized: ${basename2(notePath)}`);
|
|
368
439
|
return notePath;
|
|
@@ -398,20 +469,20 @@ ${summary || "Session completed."}`
|
|
|
398
469
|
}
|
|
399
470
|
|
|
400
471
|
// src/hooks/ts/lib/project-utils/todo.ts
|
|
401
|
-
import { existsSync as
|
|
402
|
-
import { join as
|
|
472
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "fs";
|
|
473
|
+
import { join as join7, basename as basename3 } from "path";
|
|
403
474
|
|
|
404
475
|
// src/session/checkpoint-block.ts
|
|
405
476
|
import {
|
|
406
|
-
existsSync as
|
|
407
|
-
readFileSync as
|
|
477
|
+
existsSync as existsSync6,
|
|
478
|
+
readFileSync as readFileSync5,
|
|
408
479
|
writeFileSync as writeFileSync2,
|
|
409
|
-
readdirSync as
|
|
410
|
-
renameSync as
|
|
411
|
-
mkdirSync as
|
|
480
|
+
readdirSync as readdirSync4,
|
|
481
|
+
renameSync as renameSync3,
|
|
482
|
+
mkdirSync as mkdirSync4,
|
|
412
483
|
realpathSync
|
|
413
484
|
} from "node:fs";
|
|
414
|
-
import { join as
|
|
485
|
+
import { join as join6 } from "node:path";
|
|
415
486
|
var TODO_LOCATIONS = [
|
|
416
487
|
"Notes/TODO.md",
|
|
417
488
|
".claude/Notes/TODO.md",
|
|
@@ -427,10 +498,10 @@ var ARCHIVE_LIMIT = 5;
|
|
|
427
498
|
var CONTINUE_HEADING = "## Continue";
|
|
428
499
|
function findProjectTodo(rootPath) {
|
|
429
500
|
for (const rel of TODO_LOCATIONS) {
|
|
430
|
-
const full =
|
|
431
|
-
if (
|
|
501
|
+
const full = join6(rootPath, rel);
|
|
502
|
+
if (existsSync6(full)) {
|
|
432
503
|
try {
|
|
433
|
-
return { path: full, content:
|
|
504
|
+
return { path: full, content: readFileSync5(full, "utf8") };
|
|
434
505
|
} catch {
|
|
435
506
|
}
|
|
436
507
|
}
|
|
@@ -440,15 +511,15 @@ function findProjectTodo(rootPath) {
|
|
|
440
511
|
function resolveTodoTarget(rootPath, opts = {}) {
|
|
441
512
|
const found = findProjectTodo(rootPath);
|
|
442
513
|
if (found) return found;
|
|
443
|
-
const notesDir =
|
|
514
|
+
const notesDir = join6(rootPath, "Notes");
|
|
444
515
|
if (opts.create !== false) {
|
|
445
516
|
try {
|
|
446
|
-
if (!
|
|
517
|
+
if (!existsSync6(notesDir)) mkdirSync4(notesDir, { recursive: true });
|
|
447
518
|
} catch {
|
|
448
519
|
return null;
|
|
449
520
|
}
|
|
450
521
|
}
|
|
451
|
-
return { path:
|
|
522
|
+
return { path: join6(notesDir, "TODO.md"), content: "" };
|
|
452
523
|
}
|
|
453
524
|
function parseMarker(line) {
|
|
454
525
|
const trimmed = line.trim();
|
|
@@ -737,10 +808,10 @@ function applyContinue(opts) {
|
|
|
737
808
|
const tmpPath = `${target.path}.continue.tmp`;
|
|
738
809
|
try {
|
|
739
810
|
writeFileSync2(tmpPath, newContent, "utf8");
|
|
740
|
-
|
|
811
|
+
renameSync3(tmpPath, target.path);
|
|
741
812
|
} catch (err) {
|
|
742
813
|
try {
|
|
743
|
-
if (
|
|
814
|
+
if (existsSync6(tmpPath)) renameSync3(tmpPath, `${tmpPath}.dead`);
|
|
744
815
|
} catch {
|
|
745
816
|
}
|
|
746
817
|
return {
|
|
@@ -756,9 +827,9 @@ function applyContinue(opts) {
|
|
|
756
827
|
// src/hooks/ts/lib/project-utils/todo.ts
|
|
757
828
|
function ensureTodoMd(cwd) {
|
|
758
829
|
const todoPath = findTodoPath(cwd);
|
|
759
|
-
if (!
|
|
760
|
-
const parentDir =
|
|
761
|
-
if (!
|
|
830
|
+
if (!existsSync7(todoPath)) {
|
|
831
|
+
const parentDir = join7(todoPath, "..");
|
|
832
|
+
if (!existsSync7(parentDir)) mkdirSync5(parentDir, { recursive: true });
|
|
762
833
|
const content = `# TODO
|
|
763
834
|
|
|
764
835
|
## Current Session
|
|
@@ -813,7 +884,7 @@ function updateTodoContinue(cwd, noteFilename, state, tokenDisplay, sessionId) {
|
|
|
813
884
|
try {
|
|
814
885
|
const todoPath = result.path;
|
|
815
886
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
816
|
-
let content =
|
|
887
|
+
let content = readFileSync6(todoPath, "utf-8");
|
|
817
888
|
content = content.replace(/(\n---\s*)*(\n\*Last updated:.*\*\s*)+$/g, "");
|
|
818
889
|
content = content.trimEnd() + `
|
|
819
890
|
|
|
@@ -829,6 +900,17 @@ function updateTodoContinue(cwd, noteFilename, state, tokenDisplay, sessionId) {
|
|
|
829
900
|
);
|
|
830
901
|
}
|
|
831
902
|
|
|
903
|
+
// src/config/pai-files.ts
|
|
904
|
+
import { homedir as homedir4 } from "node:os";
|
|
905
|
+
import { join as join8 } from "node:path";
|
|
906
|
+
function oldSessionStateDir() {
|
|
907
|
+
return join8(homedir4(), ".config", "pai", "session-state");
|
|
908
|
+
}
|
|
909
|
+
function sessionStateDir() {
|
|
910
|
+
return resolvePaiFile(paiHomePath("session-state"), [oldSessionStateDir()], "pai config migrate");
|
|
911
|
+
}
|
|
912
|
+
var SESSION_STOP_LOCK_ABANDONED_AFTER_MS = 60 * 60 * 1e3;
|
|
913
|
+
|
|
832
914
|
// src/hooks/ts/stop/stop-hook.ts
|
|
833
915
|
var DAEMON_SOCKET = process.env.PAI_SOCKET ?? "/tmp/pai.sock";
|
|
834
916
|
var DAEMON_TIMEOUT_MS = 800;
|
|
@@ -840,17 +922,11 @@ var AUTO_SAVE_INTERVAL = (() => {
|
|
|
840
922
|
}
|
|
841
923
|
return 15;
|
|
842
924
|
})();
|
|
843
|
-
var SESSION_STATE_DIR = join7(
|
|
844
|
-
process.env.HOME ?? "/tmp",
|
|
845
|
-
".config",
|
|
846
|
-
"pai",
|
|
847
|
-
"session-state"
|
|
848
|
-
);
|
|
849
925
|
function readSessionState(sessionId) {
|
|
850
926
|
try {
|
|
851
|
-
const stateFile =
|
|
852
|
-
if (!
|
|
853
|
-
const raw =
|
|
927
|
+
const stateFile = join9(sessionStateDir(), `${sessionId}.json`);
|
|
928
|
+
if (!existsSync8(stateFile)) return { humanMessageCount: 0 };
|
|
929
|
+
const raw = readFileSync7(stateFile, "utf-8");
|
|
854
930
|
const parsed = JSON.parse(raw);
|
|
855
931
|
return {
|
|
856
932
|
humanMessageCount: typeof parsed.humanMessageCount === "number" ? parsed.humanMessageCount : 0
|
|
@@ -861,8 +937,9 @@ function readSessionState(sessionId) {
|
|
|
861
937
|
}
|
|
862
938
|
function writeSessionState(sessionId, state) {
|
|
863
939
|
try {
|
|
864
|
-
|
|
865
|
-
|
|
940
|
+
const dir = paiHomePath("session-state");
|
|
941
|
+
mkdirSync6(dir, { recursive: true });
|
|
942
|
+
const stateFile = join9(dir, `${sessionId}.json`);
|
|
866
943
|
writeFileSync4(stateFile, JSON.stringify(state, null, 2), "utf-8");
|
|
867
944
|
} catch (e) {
|
|
868
945
|
console.error(`STOP-HOOK: Could not write session state: ${e}`);
|
|
@@ -870,8 +947,8 @@ function writeSessionState(sessionId, state) {
|
|
|
870
947
|
}
|
|
871
948
|
function deleteSessionState(sessionId) {
|
|
872
949
|
try {
|
|
873
|
-
const stateFile =
|
|
874
|
-
if (
|
|
950
|
+
const stateFile = join9(sessionStateDir(), `${sessionId}.json`);
|
|
951
|
+
if (existsSync8(stateFile)) {
|
|
875
952
|
unlinkSync(stateFile);
|
|
876
953
|
}
|
|
877
954
|
} catch {
|
|
@@ -1333,7 +1410,7 @@ async function executeDirectly(lines, transcriptPath, cwd, message, lastUserQuer
|
|
|
1333
1410
|
console.error(`Could not finalize session note: ${noteError}`);
|
|
1334
1411
|
}
|
|
1335
1412
|
try {
|
|
1336
|
-
const transcriptDir =
|
|
1413
|
+
const transcriptDir = dirname2(transcriptPath);
|
|
1337
1414
|
const archivedCount = archiveSessionFilesToSessionsDir(transcriptDir);
|
|
1338
1415
|
if (archivedCount > 0) {
|
|
1339
1416
|
console.error(`Archived ${archivedCount} session file(s) to sessions/`);
|
|
@@ -1392,7 +1469,7 @@ STOP-HOOK TRIGGERED AT ${timestamp}`);
|
|
|
1392
1469
|
}
|
|
1393
1470
|
let transcript;
|
|
1394
1471
|
try {
|
|
1395
|
-
transcript =
|
|
1472
|
+
transcript = readFileSync7(transcriptPath, "utf-8");
|
|
1396
1473
|
debug(`Transcript loaded: ${transcript.split("\n").length} lines`);
|
|
1397
1474
|
} catch (e) {
|
|
1398
1475
|
console.error(`Error reading transcript: ${e}`);
|