@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,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,65 +9,98 @@ function isWorkerSession(env = process.env) {
|
|
|
6
9
|
}
|
|
7
10
|
|
|
8
11
|
// src/hooks/ts/session-start/load-project-context.ts
|
|
9
|
-
import { existsSync as
|
|
10
|
-
import { join as
|
|
11
|
-
import { homedir as
|
|
12
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
|
|
13
|
+
import { join as join7, basename as basename4, dirname as dirname2, resolve as resolve2 } from "path";
|
|
14
|
+
import { homedir as homedir5 } from "os";
|
|
12
15
|
import { execSync } from "child_process";
|
|
13
16
|
|
|
14
17
|
// src/memory/wakeup.ts
|
|
15
|
-
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
16
|
-
import { join, basename } from "node:path";
|
|
18
|
+
import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
|
|
19
|
+
import { join as join2, basename } from "node:path";
|
|
20
|
+
import { homedir as homedir2 } from "node:os";
|
|
21
|
+
|
|
22
|
+
// src/config/pai-home.ts
|
|
23
|
+
import { existsSync, mkdirSync, readFileSync, copyFileSync, renameSync, readdirSync, statSync } from "node:fs";
|
|
17
24
|
import { homedir } from "node:os";
|
|
18
|
-
|
|
25
|
+
import { join, dirname } from "node:path";
|
|
26
|
+
function paiHomeDir() {
|
|
27
|
+
return process.env.PAI_HOME || join(homedir(), ".claude", "pai");
|
|
28
|
+
}
|
|
29
|
+
function paiHomePath(...segments) {
|
|
30
|
+
return join(paiHomeDir(), ...segments);
|
|
31
|
+
}
|
|
32
|
+
var noticesPrinted = /* @__PURE__ */ new Set();
|
|
33
|
+
function resolvePaiFile(newPath, oldCandidates, migrateHint) {
|
|
34
|
+
if (existsSync(newPath)) return newPath;
|
|
35
|
+
for (const old of oldCandidates) {
|
|
36
|
+
if (existsSync(old)) {
|
|
37
|
+
if (!noticesPrinted.has(newPath)) {
|
|
38
|
+
noticesPrinted.add(newPath);
|
|
39
|
+
process.stderr.write(
|
|
40
|
+
`pai: ${old} is at an old location \u2014 run \`${migrateHint}\` to move it to ${newPath}
|
|
41
|
+
`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
return old;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return newPath;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/memory/wakeup.ts
|
|
51
|
+
var L1_TOKEN_BUDGET = 300;
|
|
19
52
|
var L1_CHAR_BUDGET = L1_TOKEN_BUDGET * 4;
|
|
20
|
-
var L1_MAX_NOTES =
|
|
53
|
+
var L1_MAX_NOTES = 3;
|
|
21
54
|
var EXTRACT_SECTIONS = [
|
|
22
55
|
"Work Done",
|
|
23
56
|
"Key Decisions",
|
|
24
57
|
"Next Steps",
|
|
25
58
|
"Checkpoint"
|
|
26
59
|
];
|
|
27
|
-
var IDENTITY_FILE =
|
|
28
|
-
function loadL0Identity() {
|
|
29
|
-
|
|
60
|
+
var IDENTITY_FILE = join2(homedir2(), ".pai", "identity.txt");
|
|
61
|
+
function loadL0Identity(opts = {}) {
|
|
62
|
+
const newPath = opts.newPath ?? paiHomePath("identity.txt");
|
|
63
|
+
const legacyPath = opts.legacyPath ?? IDENTITY_FILE;
|
|
64
|
+
const path = existsSync2(newPath) ? newPath : legacyPath;
|
|
65
|
+
if (!existsSync2(path)) return "";
|
|
30
66
|
try {
|
|
31
|
-
return
|
|
67
|
+
return readFileSync2(path, "utf-8").trim();
|
|
32
68
|
} catch {
|
|
33
69
|
return "";
|
|
34
70
|
}
|
|
35
71
|
}
|
|
36
72
|
function findNotesDirForProject(rootPath) {
|
|
37
73
|
const localCandidates = [
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
74
|
+
join2(rootPath, "Notes"),
|
|
75
|
+
join2(rootPath, "notes"),
|
|
76
|
+
join2(rootPath, ".claude", "Notes")
|
|
41
77
|
];
|
|
42
78
|
for (const p of localCandidates) {
|
|
43
|
-
if (
|
|
79
|
+
if (existsSync2(p)) return p;
|
|
44
80
|
}
|
|
45
81
|
const encoded = rootPath.replace(/\//g, "-").replace(/\./g, "-").replace(/ /g, "-");
|
|
46
|
-
const centralNotes =
|
|
47
|
-
|
|
82
|
+
const centralNotes = join2(
|
|
83
|
+
homedir2(),
|
|
48
84
|
".claude",
|
|
49
85
|
"projects",
|
|
50
86
|
encoded,
|
|
51
87
|
"Notes"
|
|
52
88
|
);
|
|
53
|
-
if (
|
|
89
|
+
if (existsSync2(centralNotes)) return centralNotes;
|
|
54
90
|
return null;
|
|
55
91
|
}
|
|
56
92
|
function findSessionNotes(notesDir) {
|
|
57
93
|
const result = [];
|
|
58
94
|
const scanDir = (dir) => {
|
|
59
|
-
if (!
|
|
95
|
+
if (!existsSync2(dir)) return;
|
|
60
96
|
let entries;
|
|
61
97
|
try {
|
|
62
|
-
entries =
|
|
98
|
+
entries = readdirSync2(dir, { withFileTypes: true }).map((e) => ({ name: e.name, isDir: e.isDirectory() }));
|
|
63
99
|
} catch {
|
|
64
100
|
return;
|
|
65
101
|
}
|
|
66
102
|
for (const entry of entries) {
|
|
67
|
-
const fullPath =
|
|
103
|
+
const fullPath = join2(dir, entry.name);
|
|
68
104
|
if (entry.isDir) {
|
|
69
105
|
scanDir(fullPath);
|
|
70
106
|
} else if (entry.name.match(/^\d{3,4}[\s_-].*\.md$/)) {
|
|
@@ -77,7 +113,7 @@ function findSessionNotes(notesDir) {
|
|
|
77
113
|
const numberOf = (p) => parseInt(basename(p).match(/^(\d+)/)?.[1] ?? "0", 10);
|
|
78
114
|
const mtimeOf = (p) => {
|
|
79
115
|
try {
|
|
80
|
-
return
|
|
116
|
+
return statSync2(p).mtimeMs;
|
|
81
117
|
} catch {
|
|
82
118
|
return 0;
|
|
83
119
|
}
|
|
@@ -96,7 +132,10 @@ function findSessionNotes(notesDir) {
|
|
|
96
132
|
});
|
|
97
133
|
return result;
|
|
98
134
|
}
|
|
99
|
-
function
|
|
135
|
+
function normalizeLine(line) {
|
|
136
|
+
return line.replace(/^(- \[[ x]\] |- |\* |\d+\.\s)/, "").trim().replace(/\s+/g, " ");
|
|
137
|
+
}
|
|
138
|
+
function extractKeyLines(content, maxChars, seen = /* @__PURE__ */ new Set()) {
|
|
100
139
|
const lines = content.split("\n");
|
|
101
140
|
const selected = [];
|
|
102
141
|
let inTargetSection = false;
|
|
@@ -126,7 +165,10 @@ function extractKeyLines(content, maxChars) {
|
|
|
126
165
|
const trimmed = line.trim();
|
|
127
166
|
if (!trimmed || trimmed.startsWith("<!--") || trimmed === "---") continue;
|
|
128
167
|
if (trimmed.startsWith("- ") || trimmed.startsWith("* ") || trimmed.match(/^\d+\./) || trimmed.startsWith("**")) {
|
|
168
|
+
const normalized = normalizeLine(trimmed);
|
|
169
|
+
if (seen.has(normalized)) continue;
|
|
129
170
|
if (charCount + trimmed.length + 1 > maxChars) break;
|
|
171
|
+
seen.add(normalized);
|
|
130
172
|
selected.push(trimmed);
|
|
131
173
|
charCount += trimmed.length + 1;
|
|
132
174
|
}
|
|
@@ -140,12 +182,13 @@ function buildL1EssentialStory(rootPath, tokenBudget = L1_TOKEN_BUDGET) {
|
|
|
140
182
|
const noteFiles = findSessionNotes(notesDir).slice(0, L1_MAX_NOTES);
|
|
141
183
|
if (noteFiles.length === 0) return "";
|
|
142
184
|
const sections = [];
|
|
185
|
+
const seen = /* @__PURE__ */ new Set();
|
|
143
186
|
let remaining = charBudget;
|
|
144
187
|
for (const noteFile of noteFiles) {
|
|
145
188
|
if (remaining <= 50) break;
|
|
146
189
|
let content;
|
|
147
190
|
try {
|
|
148
|
-
content =
|
|
191
|
+
content = readFileSync2(noteFile, "utf-8");
|
|
149
192
|
} catch {
|
|
150
193
|
continue;
|
|
151
194
|
}
|
|
@@ -154,7 +197,7 @@ function buildL1EssentialStory(rootPath, tokenBudget = L1_TOKEN_BUDGET) {
|
|
|
154
197
|
const dateLabel = titleMatch ? titleMatch[1] : "";
|
|
155
198
|
const titleLabel = titleMatch ? titleMatch[2] : name.replace(/^\d+ - /, "").replace(/\.md$/, "");
|
|
156
199
|
const perNoteChars = Math.min(remaining, Math.floor(charBudget / noteFiles.length) + 200);
|
|
157
|
-
const extracted = extractKeyLines(content, perNoteChars);
|
|
200
|
+
const extracted = extractKeyLines(content, perNoteChars, seen);
|
|
158
201
|
if (!extracted) continue;
|
|
159
202
|
const noteBlock = `[${dateLabel} - ${titleLabel}]
|
|
160
203
|
${extracted}`;
|
|
@@ -318,23 +361,19 @@ function extractMarkedBody(lines) {
|
|
|
318
361
|
}
|
|
319
362
|
var AUTHORED_GRACE_MS = 60 * 60 * 1e3;
|
|
320
363
|
|
|
321
|
-
// src/hooks/ts/lib/project-utils/paths.ts
|
|
322
|
-
import { existsSync as existsSync3, mkdirSync, readdirSync as readdirSync2, linkSync, copyFileSync } from "fs";
|
|
323
|
-
import { join as join3, basename as basename2 } from "path";
|
|
324
|
-
|
|
325
364
|
// src/hooks/ts/lib/pai-paths.ts
|
|
326
|
-
import { homedir as
|
|
327
|
-
import { resolve, join as
|
|
328
|
-
import { existsSync as
|
|
365
|
+
import { homedir as homedir3 } from "os";
|
|
366
|
+
import { resolve, join as join3 } from "path";
|
|
367
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
329
368
|
function loadEnvFile() {
|
|
330
369
|
const possiblePaths = [
|
|
331
|
-
resolve(process.env.PAI_DIR || "", ".env"),
|
|
332
|
-
resolve(
|
|
370
|
+
resolve(process.env.ADAPTER_DIR || process.env.PAI_DIR || "", ".env"),
|
|
371
|
+
resolve(homedir3(), ".claude", ".env")
|
|
333
372
|
];
|
|
334
373
|
for (const envPath of possiblePaths) {
|
|
335
|
-
if (
|
|
374
|
+
if (existsSync3(envPath)) {
|
|
336
375
|
try {
|
|
337
|
-
const content =
|
|
376
|
+
const content = readFileSync3(envPath, "utf-8");
|
|
338
377
|
for (const line of content.split("\n")) {
|
|
339
378
|
const trimmed = line.trim();
|
|
340
379
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -345,8 +384,8 @@ function loadEnvFile() {
|
|
|
345
384
|
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
346
385
|
value = value.slice(1, -1);
|
|
347
386
|
}
|
|
348
|
-
value = value.replace(/\$HOME/g,
|
|
349
|
-
value = value.replace(/^~(?=\/|$)/,
|
|
387
|
+
value = value.replace(/\$HOME/g, homedir3());
|
|
388
|
+
value = value.replace(/^~(?=\/|$)/, homedir3());
|
|
350
389
|
if (process.env[key] === void 0) {
|
|
351
390
|
process.env[key] = value;
|
|
352
391
|
}
|
|
@@ -359,29 +398,75 @@ function loadEnvFile() {
|
|
|
359
398
|
}
|
|
360
399
|
}
|
|
361
400
|
loadEnvFile();
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
401
|
+
function defaultAdapterDir() {
|
|
402
|
+
return resolve(homedir3(), ".claude");
|
|
403
|
+
}
|
|
404
|
+
function suppressDeprecationNotices() {
|
|
405
|
+
if (process.env.PAI_QUIET_NOTICES === "1") return true;
|
|
406
|
+
const idx = process.argv.indexOf("--output-format");
|
|
407
|
+
return idx !== -1 && process.argv[idx + 1] === "json";
|
|
408
|
+
}
|
|
409
|
+
function warnPaiDirDeprecatedOnce(message) {
|
|
410
|
+
const g = globalThis;
|
|
411
|
+
if (g.__paiDirNoticePrinted || suppressDeprecationNotices()) return;
|
|
412
|
+
g.__paiDirNoticePrinted = true;
|
|
413
|
+
process.stderr.write(`pai: ${message}
|
|
414
|
+
`);
|
|
415
|
+
}
|
|
416
|
+
function resolveAdapterDir() {
|
|
417
|
+
if (process.env.ADAPTER_DIR) {
|
|
418
|
+
const adapterDir = resolve(process.env.ADAPTER_DIR);
|
|
419
|
+
if (process.env.PAI_DIR) {
|
|
420
|
+
const paiDir = resolve(process.env.PAI_DIR);
|
|
421
|
+
if (paiDir !== adapterDir) {
|
|
422
|
+
warnPaiDirDeprecatedOnce(
|
|
423
|
+
`ADAPTER_DIR (${adapterDir}) and PAI_DIR (${paiDir}) are both set and differ \u2014 ADAPTER_DIR wins. PAI_DIR still works for one release.`
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return adapterDir;
|
|
428
|
+
}
|
|
429
|
+
if (process.env.PAI_DIR) {
|
|
430
|
+
const paiDir = resolve(process.env.PAI_DIR);
|
|
431
|
+
if (paiDir !== defaultAdapterDir()) {
|
|
432
|
+
warnPaiDirDeprecatedOnce(
|
|
433
|
+
"PAI_DIR is deprecated \u2014 use ADAPTER_DIR for the harness adapter root (~/.claude). PAI_DIR still works for one release."
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
return paiDir;
|
|
437
|
+
}
|
|
438
|
+
return defaultAdapterDir();
|
|
439
|
+
}
|
|
440
|
+
var ADAPTER_DIR = resolveAdapterDir();
|
|
441
|
+
var HOOKS_DIR = join3(ADAPTER_DIR, "Hooks");
|
|
442
|
+
var SKILLS_DIR = join3(ADAPTER_DIR, "Skills");
|
|
443
|
+
var AGENTS_DIR = join3(ADAPTER_DIR, "Agents");
|
|
444
|
+
var COMMANDS_DIR = join3(ADAPTER_DIR, "Commands");
|
|
368
445
|
function validatePAIStructure() {
|
|
369
|
-
if (!
|
|
370
|
-
console.error(`
|
|
371
|
-
console.error(` Expected ~/.claude or set
|
|
446
|
+
if (!existsSync3(ADAPTER_DIR)) {
|
|
447
|
+
console.error(`ADAPTER_DIR does not exist: ${ADAPTER_DIR}`);
|
|
448
|
+
console.error(` Expected ~/.claude or set ADAPTER_DIR environment variable`);
|
|
372
449
|
process.exit(1);
|
|
373
450
|
}
|
|
374
|
-
if (!
|
|
451
|
+
if (!existsSync3(HOOKS_DIR)) {
|
|
375
452
|
console.error(`PAI hooks directory not found: ${HOOKS_DIR}`);
|
|
376
|
-
console.error(` Your
|
|
377
|
-
console.error(` Current
|
|
453
|
+
console.error(` Your ADAPTER_DIR may be misconfigured`);
|
|
454
|
+
console.error(` Current ADAPTER_DIR: ${ADAPTER_DIR}`);
|
|
378
455
|
process.exit(1);
|
|
379
456
|
}
|
|
380
457
|
}
|
|
381
458
|
validatePAIStructure();
|
|
459
|
+
function oldSessionRoutingPath() {
|
|
460
|
+
return join3(ADAPTER_DIR, "session-routing.json");
|
|
461
|
+
}
|
|
462
|
+
function sessionRoutingPath() {
|
|
463
|
+
return resolvePaiFile(paiHomePath("session-routing.json"), [oldSessionRoutingPath()], "pai config migrate --history");
|
|
464
|
+
}
|
|
382
465
|
|
|
383
466
|
// src/hooks/ts/lib/project-utils/paths.ts
|
|
384
|
-
|
|
467
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync as readdirSync3, linkSync, copyFileSync as copyFileSync2 } from "fs";
|
|
468
|
+
import { join as join4, basename as basename2 } from "path";
|
|
469
|
+
var PROJECTS_DIR = join4(ADAPTER_DIR, "projects");
|
|
385
470
|
var PROBE_CWD_PATTERNS = [
|
|
386
471
|
"/CodexBar/ClaudeProbe",
|
|
387
472
|
"/ClaudeProbe"
|
|
@@ -395,56 +480,56 @@ function encodePath(path) {
|
|
|
395
480
|
}
|
|
396
481
|
function getProjectDir(cwd) {
|
|
397
482
|
const encoded = encodePath(cwd);
|
|
398
|
-
return
|
|
483
|
+
return join4(PROJECTS_DIR, encoded);
|
|
399
484
|
}
|
|
400
485
|
function getNotesDir(cwd) {
|
|
401
|
-
return
|
|
486
|
+
return join4(getProjectDir(cwd), "Notes");
|
|
402
487
|
}
|
|
403
488
|
function findNotesDir(cwd) {
|
|
404
489
|
const cwdBasename = basename2(cwd).toLowerCase();
|
|
405
|
-
if (cwdBasename === "notes" &&
|
|
490
|
+
if (cwdBasename === "notes" && existsSync4(cwd)) {
|
|
406
491
|
return { path: cwd, isLocal: true };
|
|
407
492
|
}
|
|
408
493
|
const localPaths = [
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
494
|
+
join4(cwd, "Notes"),
|
|
495
|
+
join4(cwd, "notes"),
|
|
496
|
+
join4(cwd, ".claude", "Notes")
|
|
412
497
|
];
|
|
413
498
|
for (const path of localPaths) {
|
|
414
|
-
if (
|
|
499
|
+
if (existsSync4(path)) {
|
|
415
500
|
return { path, isLocal: true };
|
|
416
501
|
}
|
|
417
502
|
}
|
|
418
503
|
return { path: getNotesDir(cwd), isLocal: false };
|
|
419
504
|
}
|
|
420
505
|
function getSessionsDirFromProjectDir(projectDir) {
|
|
421
|
-
return
|
|
506
|
+
return join4(projectDir, "sessions");
|
|
422
507
|
}
|
|
423
508
|
function ensureSessionsDirFromProjectDir(projectDir) {
|
|
424
509
|
const sessionsDir = getSessionsDirFromProjectDir(projectDir);
|
|
425
|
-
if (!
|
|
426
|
-
|
|
510
|
+
if (!existsSync4(sessionsDir)) {
|
|
511
|
+
mkdirSync2(sessionsDir, { recursive: true });
|
|
427
512
|
console.error(`Created sessions directory: ${sessionsDir}`);
|
|
428
513
|
}
|
|
429
514
|
return sessionsDir;
|
|
430
515
|
}
|
|
431
516
|
function archiveSessionFilesToSessionsDir(projectDir, excludeFile, silent = false) {
|
|
432
517
|
const sessionsDir = ensureSessionsDirFromProjectDir(projectDir);
|
|
433
|
-
if (!
|
|
434
|
-
const files =
|
|
518
|
+
if (!existsSync4(projectDir)) return 0;
|
|
519
|
+
const files = readdirSync3(projectDir);
|
|
435
520
|
let archivedCount = 0;
|
|
436
521
|
for (const file of files) {
|
|
437
522
|
if (!file.endsWith(".jsonl") || file === excludeFile) continue;
|
|
438
|
-
const sourcePath =
|
|
439
|
-
const destPath =
|
|
440
|
-
if (
|
|
523
|
+
const sourcePath = join4(projectDir, file);
|
|
524
|
+
const destPath = join4(sessionsDir, file);
|
|
525
|
+
if (existsSync4(destPath)) continue;
|
|
441
526
|
try {
|
|
442
527
|
linkSync(sourcePath, destPath);
|
|
443
528
|
if (!silent) console.error(`Archived ${file} \u2192 sessions/ (still resumable)`);
|
|
444
529
|
archivedCount++;
|
|
445
530
|
} catch (error) {
|
|
446
531
|
try {
|
|
447
|
-
|
|
532
|
+
copyFileSync2(sourcePath, destPath);
|
|
448
533
|
if (!silent) console.error(`Copied ${file} \u2192 sessions/ (hardlink unavailable)`);
|
|
449
534
|
archivedCount++;
|
|
450
535
|
} catch {
|
|
@@ -456,41 +541,41 @@ function archiveSessionFilesToSessionsDir(projectDir, excludeFile, silent = fals
|
|
|
456
541
|
}
|
|
457
542
|
function findTodoPath(cwd) {
|
|
458
543
|
const localPaths = [
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
544
|
+
join4(cwd, "TODO.md"),
|
|
545
|
+
join4(cwd, "notes", "TODO.md"),
|
|
546
|
+
join4(cwd, "Notes", "TODO.md"),
|
|
547
|
+
join4(cwd, ".claude", "TODO.md")
|
|
463
548
|
];
|
|
464
549
|
for (const path of localPaths) {
|
|
465
|
-
if (
|
|
550
|
+
if (existsSync4(path)) return path;
|
|
466
551
|
}
|
|
467
|
-
return
|
|
552
|
+
return join4(getNotesDir(cwd), "TODO.md");
|
|
468
553
|
}
|
|
469
554
|
function findAllClaudeMdPaths(cwd) {
|
|
470
555
|
const foundPaths = [];
|
|
471
556
|
const localPaths = [
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
557
|
+
join4(cwd, ".claude", "CLAUDE.md"),
|
|
558
|
+
join4(cwd, "CLAUDE.md"),
|
|
559
|
+
join4(cwd, "Notes", "CLAUDE.md"),
|
|
560
|
+
join4(cwd, "notes", "CLAUDE.md"),
|
|
561
|
+
join4(cwd, "Prompts", "CLAUDE.md"),
|
|
562
|
+
join4(cwd, "prompts", "CLAUDE.md")
|
|
478
563
|
];
|
|
479
564
|
for (const path of localPaths) {
|
|
480
|
-
if (
|
|
565
|
+
if (existsSync4(path)) foundPaths.push(path);
|
|
481
566
|
}
|
|
482
567
|
return foundPaths;
|
|
483
568
|
}
|
|
484
569
|
|
|
485
570
|
// src/hooks/ts/lib/project-utils/notify.ts
|
|
486
|
-
import { existsSync as
|
|
487
|
-
import { join as
|
|
488
|
-
import { homedir as
|
|
571
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
572
|
+
import { join as join5 } from "path";
|
|
573
|
+
import { homedir as homedir4 } from "os";
|
|
489
574
|
function isWhatsAppEnabled() {
|
|
490
575
|
try {
|
|
491
|
-
const settingsPath =
|
|
492
|
-
if (!
|
|
493
|
-
const settings = JSON.parse(
|
|
576
|
+
const settingsPath = join5(homedir4(), ".claude", "settings.json");
|
|
577
|
+
if (!existsSync5(settingsPath)) return false;
|
|
578
|
+
const settings = JSON.parse(readFileSync4(settingsPath, "utf-8"));
|
|
494
579
|
const enabled = settings.enabledMcpjsonServers || [];
|
|
495
580
|
return enabled.includes("aibroker") || enabled.includes("whazaa") || enabled.includes("telex");
|
|
496
581
|
} catch {
|
|
@@ -535,21 +620,21 @@ async function sendNtfyNotification(message, retries = 2) {
|
|
|
535
620
|
}
|
|
536
621
|
|
|
537
622
|
// src/hooks/ts/lib/project-utils/session-notes.ts
|
|
538
|
-
import { existsSync as
|
|
539
|
-
import { join as
|
|
623
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readdirSync as readdirSync4, readFileSync as readFileSync5, writeFileSync, renameSync as renameSync2 } from "fs";
|
|
624
|
+
import { join as join6, basename as basename3 } from "path";
|
|
540
625
|
function getMonthDir(notesDir) {
|
|
541
626
|
const now = /* @__PURE__ */ new Date();
|
|
542
627
|
const year = String(now.getFullYear());
|
|
543
628
|
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
544
|
-
const monthDir =
|
|
545
|
-
if (!
|
|
546
|
-
|
|
629
|
+
const monthDir = join6(notesDir, year, month);
|
|
630
|
+
if (!existsSync6(monthDir)) {
|
|
631
|
+
mkdirSync3(monthDir, { recursive: true });
|
|
547
632
|
}
|
|
548
633
|
return monthDir;
|
|
549
634
|
}
|
|
550
635
|
function getNextNoteNumber(notesDir) {
|
|
551
636
|
const monthDir = getMonthDir(notesDir);
|
|
552
|
-
const files =
|
|
637
|
+
const files = readdirSync4(monthDir).filter((f) => f.match(/^\d{3,4}[\s_-]/)).sort();
|
|
553
638
|
if (files.length === 0) return "0001";
|
|
554
639
|
let maxNumber = 0;
|
|
555
640
|
for (const file of files) {
|
|
@@ -562,27 +647,27 @@ function getNextNoteNumber(notesDir) {
|
|
|
562
647
|
return String(maxNumber + 1).padStart(4, "0");
|
|
563
648
|
}
|
|
564
649
|
function getCurrentNotePath(notesDir) {
|
|
565
|
-
if (!
|
|
650
|
+
if (!existsSync6(notesDir)) return null;
|
|
566
651
|
const findLatestIn = (dir) => {
|
|
567
|
-
if (!
|
|
568
|
-
const files =
|
|
652
|
+
if (!existsSync6(dir)) return null;
|
|
653
|
+
const files = readdirSync4(dir).filter((f) => f.match(/^\d{3,4}[\s_-].*\.md$/)).sort((a, b) => {
|
|
569
654
|
const numA = parseInt(a.match(/^(\d+)/)?.[1] || "0", 10);
|
|
570
655
|
const numB = parseInt(b.match(/^(\d+)/)?.[1] || "0", 10);
|
|
571
656
|
return numA - numB;
|
|
572
657
|
});
|
|
573
658
|
if (files.length === 0) return null;
|
|
574
|
-
return
|
|
659
|
+
return join6(dir, files[files.length - 1]);
|
|
575
660
|
};
|
|
576
661
|
const now = /* @__PURE__ */ new Date();
|
|
577
662
|
const year = String(now.getFullYear());
|
|
578
663
|
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
579
|
-
const currentMonthDir =
|
|
664
|
+
const currentMonthDir = join6(notesDir, year, month);
|
|
580
665
|
const found = findLatestIn(currentMonthDir);
|
|
581
666
|
if (found) return found;
|
|
582
667
|
const prevDate = new Date(now.getFullYear(), now.getMonth() - 1, 1);
|
|
583
668
|
const prevYear = String(prevDate.getFullYear());
|
|
584
669
|
const prevMonth = String(prevDate.getMonth() + 1).padStart(2, "0");
|
|
585
|
-
const prevMonthDir =
|
|
670
|
+
const prevMonthDir = join6(notesDir, prevYear, prevMonth);
|
|
586
671
|
const prevFound = findLatestIn(prevMonthDir);
|
|
587
672
|
if (prevFound) return prevFound;
|
|
588
673
|
return findLatestIn(notesDir);
|
|
@@ -592,7 +677,7 @@ function createSessionNote(notesDir, description) {
|
|
|
592
677
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
593
678
|
const monthDir = getMonthDir(notesDir);
|
|
594
679
|
const filename = `${noteNumber} - ${date} - New Session.md`;
|
|
595
|
-
const filepath =
|
|
680
|
+
const filepath = join6(monthDir, filename);
|
|
596
681
|
const content = `# Session ${noteNumber}: ${description}
|
|
597
682
|
|
|
598
683
|
**Date:** ${date}
|
|
@@ -630,16 +715,16 @@ function findPaiBinary() {
|
|
|
630
715
|
`${process.env.HOME}/.local/bin/pai`
|
|
631
716
|
];
|
|
632
717
|
for (const p of fallbacks) {
|
|
633
|
-
if (
|
|
718
|
+
if (existsSync7(p)) return p;
|
|
634
719
|
}
|
|
635
720
|
}
|
|
636
721
|
return "pai";
|
|
637
722
|
}
|
|
638
723
|
function getRoutedNotesPath() {
|
|
639
|
-
const routingFile =
|
|
640
|
-
if (!
|
|
724
|
+
const routingFile = sessionRoutingPath();
|
|
725
|
+
if (!existsSync7(routingFile)) return null;
|
|
641
726
|
try {
|
|
642
|
-
const routing = JSON.parse(
|
|
727
|
+
const routing = JSON.parse(readFileSync6(routingFile, "utf-8"));
|
|
643
728
|
const active = routing?.active_session;
|
|
644
729
|
if (active?.notes_path) {
|
|
645
730
|
return active.notes_path;
|
|
@@ -664,16 +749,16 @@ var PROJECT_SIGNALS = [
|
|
|
664
749
|
"CMakeLists.txt",
|
|
665
750
|
"tsconfig.json",
|
|
666
751
|
"CLAUDE.md",
|
|
667
|
-
|
|
752
|
+
join7("Notes", "PAI.md")
|
|
668
753
|
];
|
|
669
754
|
function hasProjectSignals(dir) {
|
|
670
755
|
for (const signal of PROJECT_SIGNALS) {
|
|
671
|
-
if (
|
|
756
|
+
if (existsSync7(join7(dir, signal))) return true;
|
|
672
757
|
}
|
|
673
758
|
return false;
|
|
674
759
|
}
|
|
675
760
|
function isGuardedPath(dir) {
|
|
676
|
-
const home =
|
|
761
|
+
const home = homedir5();
|
|
677
762
|
const resolved = resolve2(dir);
|
|
678
763
|
if (resolved === home) return true;
|
|
679
764
|
const parts = resolved.split("/").filter(Boolean);
|
|
@@ -707,7 +792,7 @@ async function main() {
|
|
|
707
792
|
const cwd = hookInput?.cwd || process.cwd();
|
|
708
793
|
let projectName = basename4(cwd);
|
|
709
794
|
if (projectName.toLowerCase() === "notes") {
|
|
710
|
-
projectName = basename4(
|
|
795
|
+
projectName = basename4(dirname2(cwd));
|
|
711
796
|
}
|
|
712
797
|
console.error(`Working directory: ${cwd}`);
|
|
713
798
|
console.error(`Project: ${projectName}`);
|
|
@@ -723,7 +808,7 @@ async function main() {
|
|
|
723
808
|
for (const path of claudeMdPaths) {
|
|
724
809
|
console.error(` - ${path}`);
|
|
725
810
|
try {
|
|
726
|
-
const content =
|
|
811
|
+
const content = readFileSync6(path, "utf-8");
|
|
727
812
|
claudeMdContents.push({ path, content });
|
|
728
813
|
console.error(` Read ${content.length} chars`);
|
|
729
814
|
} catch (error) {
|
|
@@ -737,9 +822,9 @@ async function main() {
|
|
|
737
822
|
const routedPath = getRoutedNotesPath();
|
|
738
823
|
let notesDir;
|
|
739
824
|
if (routedPath) {
|
|
740
|
-
const { mkdirSync:
|
|
741
|
-
if (!
|
|
742
|
-
|
|
825
|
+
const { mkdirSync: mkdirSync4 } = await import("fs");
|
|
826
|
+
if (!existsSync7(routedPath)) {
|
|
827
|
+
mkdirSync4(routedPath, { recursive: true });
|
|
743
828
|
console.error(`Created routed Notes: ${routedPath}`);
|
|
744
829
|
} else {
|
|
745
830
|
console.error(`Notes directory: ${routedPath} (routed via pai route)`);
|
|
@@ -751,9 +836,9 @@ async function main() {
|
|
|
751
836
|
notesDir = notesInfo.path;
|
|
752
837
|
console.error(`Notes directory: ${notesDir} (local)`);
|
|
753
838
|
} else {
|
|
754
|
-
if (!
|
|
755
|
-
const { mkdirSync:
|
|
756
|
-
|
|
839
|
+
if (!existsSync7(notesInfo.path)) {
|
|
840
|
+
const { mkdirSync: mkdirSync4 } = await import("fs");
|
|
841
|
+
mkdirSync4(notesInfo.path, { recursive: true });
|
|
757
842
|
console.error(`Created central Notes: ${notesInfo.path}`);
|
|
758
843
|
} else {
|
|
759
844
|
console.error(`Notes directory: ${notesInfo.path} (central)`);
|
|
@@ -762,7 +847,7 @@ async function main() {
|
|
|
762
847
|
}
|
|
763
848
|
}
|
|
764
849
|
const projectDir = getProjectDir(cwd);
|
|
765
|
-
if (
|
|
850
|
+
if (existsSync7(projectDir)) {
|
|
766
851
|
try {
|
|
767
852
|
const own = hookInput?.session_id ? `${hookInput.session_id}.jsonl` : void 0;
|
|
768
853
|
archiveSessionFilesToSessionsDir(projectDir, own, true);
|
|
@@ -771,11 +856,11 @@ async function main() {
|
|
|
771
856
|
}
|
|
772
857
|
}
|
|
773
858
|
const todoPath = findTodoPath(cwd);
|
|
774
|
-
const hasTodo =
|
|
859
|
+
const hasTodo = existsSync7(todoPath);
|
|
775
860
|
if (hasTodo) {
|
|
776
861
|
console.error(`TODO.md: ${todoPath}`);
|
|
777
862
|
} else {
|
|
778
|
-
const newTodoPath =
|
|
863
|
+
const newTodoPath = join7(notesDir, "TODO.md");
|
|
779
864
|
const { writeFileSync: writeFileSync2 } = await import("fs");
|
|
780
865
|
writeFileSync2(newTodoPath, `# TODO
|
|
781
866
|
|
|
@@ -802,7 +887,7 @@ async function main() {
|
|
|
802
887
|
console.error(`
|
|
803
888
|
Using existing session note: ${basename4(activeNotePath)}`);
|
|
804
889
|
try {
|
|
805
|
-
const content =
|
|
890
|
+
const content = readFileSync6(activeNotePath, "utf-8");
|
|
806
891
|
const lines = content.split("\n").slice(0, 12);
|
|
807
892
|
console.error("--- Current Note Preview ---");
|
|
808
893
|
for (const line of lines) {
|
|
@@ -813,9 +898,9 @@ Using existing session note: ${basename4(activeNotePath)}`);
|
|
|
813
898
|
}
|
|
814
899
|
}
|
|
815
900
|
}
|
|
816
|
-
if (
|
|
901
|
+
if (existsSync7(todoPath)) {
|
|
817
902
|
try {
|
|
818
|
-
const todoContent =
|
|
903
|
+
const todoContent = readFileSync6(todoPath, "utf-8");
|
|
819
904
|
const todoLines = todoContent.split("\n").filter((l) => l.includes("[ ]")).slice(0, 5);
|
|
820
905
|
if (todoLines.length > 0) {
|
|
821
906
|
console.error("\nOpen TODOs:");
|
|
@@ -926,9 +1011,9 @@ Session Commands:
|
|
|
926
1011
|
</system-reminder>
|
|
927
1012
|
`;
|
|
928
1013
|
console.log(reminder);
|
|
929
|
-
if (
|
|
1014
|
+
if (existsSync7(todoPath)) {
|
|
930
1015
|
try {
|
|
931
|
-
const checkpoint = readContinueCheckpoint(
|
|
1016
|
+
const checkpoint = readContinueCheckpoint(readFileSync6(todoPath, "utf-8"));
|
|
932
1017
|
if (checkpoint) {
|
|
933
1018
|
const from = checkpoint.meta?.session ? `
|
|
934
1019
|
From session: ${checkpoint.meta.session}` : "";
|