@tekmidian/pai 0.15.0 → 0.17.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/README.md +11 -3
- package/dist/{auto-route-CLYcToZ5.mjs → auto-route-CdvjEWs5.mjs} +4 -4
- package/dist/{auto-route-CLYcToZ5.mjs.map → auto-route-CdvjEWs5.mjs.map} +1 -1
- package/dist/auto-route-DkIRampF.mjs +86 -0
- package/dist/auto-route-DkIRampF.mjs.map +1 -0
- package/dist/{kg-extraction-C8DEUHTS.mjs → checkpoint-block-Bl0HD3U2.mjs} +442 -13
- package/dist/checkpoint-block-Bl0HD3U2.mjs.map +1 -0
- package/dist/checkpoint-block-C05sK_HK.mjs +1056 -0
- package/dist/checkpoint-block-C05sK_HK.mjs.map +1 -0
- package/dist/checkpoint-block-CUCG10Uh.mjs +1022 -0
- package/dist/checkpoint-block-CUCG10Uh.mjs.map +1 -0
- package/dist/checkpoint-block-D5IyLLTr.mjs +1062 -0
- package/dist/checkpoint-block-D5IyLLTr.mjs.map +1 -0
- package/dist/cli/index.mjs +14 -12
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/program.d.mts.map +1 -1
- package/dist/cli/program.mjs +31 -16
- package/dist/cli/program.mjs.map +1 -1
- package/dist/{clusters-BYPw7vfW.mjs → clusters-CKWDwcMX.mjs} +2 -2
- package/dist/{clusters-BYPw7vfW.mjs.map → clusters-CKWDwcMX.mjs.map} +1 -1
- package/dist/{config-C8m-tPhP.mjs → config-DGOfoGfm.mjs} +1 -1
- package/dist/{config-C8m-tPhP.mjs.map → config-DGOfoGfm.mjs.map} +1 -1
- package/dist/daemon/index.mjs +18 -16
- package/dist/daemon/index.mjs.map +1 -1
- package/dist/{daemon-COSvHTNu.mjs → daemon-1rKbN-fd.mjs} +31 -30
- package/dist/{daemon-COSvHTNu.mjs.map → daemon-1rKbN-fd.mjs.map} +1 -1
- package/dist/daemon-9AL6Pwh-.mjs +1581 -0
- package/dist/daemon-9AL6Pwh-.mjs.map +1 -0
- package/dist/daemon-Bbk-_rV6.mjs +1581 -0
- package/dist/daemon-Bbk-_rV6.mjs.map +1 -0
- package/dist/daemon-BvcaMk4g.mjs +1581 -0
- package/dist/daemon-BvcaMk4g.mjs.map +1 -0
- package/dist/daemon-CTDEfwcq.mjs +1576 -0
- package/dist/daemon-CTDEfwcq.mjs.map +1 -0
- package/dist/daemon-ClbfaF60.mjs +1576 -0
- package/dist/daemon-ClbfaF60.mjs.map +1 -0
- package/dist/daemon-DDQNDgYF.mjs +1576 -0
- package/dist/daemon-DDQNDgYF.mjs.map +1 -0
- package/dist/daemon-DU8yDWlQ.mjs +1576 -0
- package/dist/daemon-DU8yDWlQ.mjs.map +1 -0
- package/dist/daemon-NJr4iSW3.mjs +1576 -0
- package/dist/daemon-NJr4iSW3.mjs.map +1 -0
- package/dist/daemon-mcp/index.mjs +2 -2
- package/dist/db-BtuN768f.mjs +206 -0
- package/dist/db-BtuN768f.mjs.map +1 -0
- package/dist/{db-CmYbAVCD.mjs → db-CYmBWcjh.mjs} +1 -1
- package/dist/{db-CmYbAVCD.mjs.map → db-CYmBWcjh.mjs.map} +1 -1
- package/dist/{detect-KjycLtXM.mjs → detect-Bf2z-oKB.mjs} +1 -1
- package/dist/{detect-KjycLtXM.mjs.map → detect-Bf2z-oKB.mjs.map} +1 -1
- package/dist/{detector-ZiOhHszd.mjs → detector-Bwzm3E_x.mjs} +2 -2
- package/dist/{detector-ZiOhHszd.mjs.map → detector-Bwzm3E_x.mjs.map} +1 -1
- package/dist/detector-rq9JGTmS.mjs +74 -0
- package/dist/detector-rq9JGTmS.mjs.map +1 -0
- package/dist/embeddings-Bn86ssxR.mjs +119 -0
- package/dist/embeddings-Bn86ssxR.mjs.map +1 -0
- package/dist/{embeddings-BJPOcbik.mjs → embeddings-DGRAPAYb.mjs} +1 -1
- package/dist/{embeddings-BJPOcbik.mjs.map → embeddings-DGRAPAYb.mjs.map} +1 -1
- package/dist/{factory-Q88X1bAN.mjs → factory-0-57Ac-7.mjs} +8 -5
- package/dist/{factory-Q88X1bAN.mjs.map → factory-0-57Ac-7.mjs.map} +1 -1
- package/dist/factory-HcQsQqh0.mjs +72 -0
- package/dist/factory-HcQsQqh0.mjs.map +1 -0
- package/dist/factory-PDXQdkLO.mjs +72 -0
- package/dist/factory-PDXQdkLO.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.map +1 -1
- package/dist/hooks/capture-session-summary.mjs.map +1 -1
- package/dist/hooks/capture-tool-output.mjs.map +1 -1
- package/dist/hooks/cleanup-session-files.mjs.map +1 -1
- package/dist/hooks/context-compression-hook.mjs +336 -48
- package/dist/hooks/context-compression-hook.mjs.map +4 -4
- package/dist/hooks/initialize-session.mjs.map +1 -1
- package/dist/hooks/inject-observations.mjs.map +1 -1
- package/dist/hooks/load-core-context.mjs.map +1 -1
- package/dist/hooks/load-project-context.mjs +188 -6
- package/dist/hooks/load-project-context.mjs.map +4 -4
- package/dist/hooks/observe.mjs.map +1 -1
- package/dist/hooks/post-compact-inject.mjs.map +1 -1
- package/dist/hooks/security-validator.mjs.map +1 -1
- package/dist/hooks/session-commands.mjs.map +1 -1
- package/dist/hooks/stop-hook.mjs +331 -43
- package/dist/hooks/stop-hook.mjs.map +4 -4
- package/dist/hooks/subagent-stop-hook.mjs.map +1 -1
- package/dist/hooks/sync-todo-to-md.mjs.map +1 -1
- package/dist/hooks/update-tab-on-action.mjs.map +1 -1
- package/dist/hooks/update-tab-titles.mjs.map +1 -1
- package/dist/hooks/whisper-rules.mjs.map +1 -1
- package/dist/index.d.mts +0 -9
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +10 -9
- package/dist/indexer-AEcT8wHf.mjs +1 -0
- package/dist/{indexer-backend-Cm5RS7y0.mjs → indexer-backend-BQZXoarl.mjs} +3 -3
- package/dist/{indexer-backend-Cm5RS7y0.mjs.map → indexer-backend-BQZXoarl.mjs.map} +1 -1
- package/dist/indexer-backend-BmaS2VcD.mjs +299 -0
- package/dist/indexer-backend-BmaS2VcD.mjs.map +1 -0
- package/dist/indexer-backend-COrJ5rjS.mjs +299 -0
- package/dist/indexer-backend-COrJ5rjS.mjs.map +1 -0
- package/dist/indexer-backend-NwD7TBGh.mjs +301 -0
- package/dist/indexer-backend-NwD7TBGh.mjs.map +1 -0
- package/dist/{ipc-client-CoyUHPod.mjs → ipc-client-vO2GV325.mjs} +1 -1
- package/dist/{ipc-client-CoyUHPod.mjs.map → ipc-client-vO2GV325.mjs.map} +1 -1
- package/dist/{kg-entity-LXblD7LZ.mjs → kg-entity-DbOMPdF9.mjs} +1 -1
- package/dist/{kg-entity-LXblD7LZ.mjs.map → kg-entity-DbOMPdF9.mjs.map} +1 -1
- package/dist/{latent-ideas-RyC6eyqI.mjs → latent-ideas-BwM3WdBp.mjs} +4 -4
- package/dist/{latent-ideas-RyC6eyqI.mjs.map → latent-ideas-BwM3WdBp.mjs.map} +1 -1
- package/dist/latent-ideas-C6IFFT0-.mjs +191 -0
- package/dist/latent-ideas-C6IFFT0-.mjs.map +1 -0
- package/dist/{main-resolver-uFxNiDy7.mjs → main-resolver-DimnS2qP.mjs} +22 -22
- package/dist/{main-resolver-uFxNiDy7.mjs.map → main-resolver-DimnS2qP.mjs.map} +1 -1
- package/dist/{migrate-B02wDDgS.mjs → migrate-fLD6rAdO.mjs} +2 -2
- package/dist/{migrate-B02wDDgS.mjs.map → migrate-fLD6rAdO.mjs.map} +1 -1
- package/dist/{neighborhood-CklGIB8r.mjs → neighborhood-CzRNG2Oy.mjs} +2 -2
- package/dist/{neighborhood-CklGIB8r.mjs.map → neighborhood-CzRNG2Oy.mjs.map} +1 -1
- package/dist/neighborhood-DZY0wkpE.mjs +135 -0
- package/dist/neighborhood-DZY0wkpE.mjs.map +1 -0
- package/dist/{note-context-qvZlVXVO.mjs → note-context-CrfMbr4R.mjs} +1 -1
- package/dist/{note-context-qvZlVXVO.mjs.map → note-context-CrfMbr4R.mjs.map} +1 -1
- package/dist/{pai-marker-HVBwwBW-.mjs → pai-marker-B20KqhA8.mjs} +44 -2
- package/dist/pai-marker-B20KqhA8.mjs.map +1 -0
- package/dist/pick-B0q5cy79.mjs +11785 -0
- package/dist/pick-B0q5cy79.mjs.map +1 -0
- package/dist/{pick-r95zvydr.mjs → pick-B3zEYjin.mjs} +2288 -497
- package/dist/pick-B3zEYjin.mjs.map +1 -0
- package/dist/pick-BHE9_iA0.mjs +11947 -0
- package/dist/pick-BHE9_iA0.mjs.map +1 -0
- package/dist/pick-BaTjoNqM.mjs +11544 -0
- package/dist/pick-BaTjoNqM.mjs.map +1 -0
- package/dist/pick-C6JbZfN4.mjs +11893 -0
- package/dist/pick-C6JbZfN4.mjs.map +1 -0
- package/dist/pick-CK-bJyjp.mjs +11883 -0
- package/dist/pick-CK-bJyjp.mjs.map +1 -0
- package/dist/pick-CLBkGHyI.mjs +11826 -0
- package/dist/pick-CLBkGHyI.mjs.map +1 -0
- package/dist/pick-CTOif21h.mjs +11544 -0
- package/dist/pick-CTOif21h.mjs.map +1 -0
- package/dist/pick-Ck2cdQgD.mjs +11893 -0
- package/dist/pick-Ck2cdQgD.mjs.map +1 -0
- package/dist/pick-Cr4nJzHA.mjs +11914 -0
- package/dist/pick-Cr4nJzHA.mjs.map +1 -0
- package/dist/pick-D4dFfKAu.mjs +11893 -0
- package/dist/pick-D4dFfKAu.mjs.map +1 -0
- package/dist/pick-D7-lYiGX.mjs +11543 -0
- package/dist/pick-D7-lYiGX.mjs.map +1 -0
- package/dist/pick-DMjCY0np.mjs +11875 -0
- package/dist/pick-DMjCY0np.mjs.map +1 -0
- package/dist/pick-DbX4OrCP.mjs +11543 -0
- package/dist/pick-DbX4OrCP.mjs.map +1 -0
- package/dist/pick-iCiPjlnC.mjs +11893 -0
- package/dist/pick-iCiPjlnC.mjs.map +1 -0
- package/dist/pick-sF9GnQUS.mjs +11893 -0
- package/dist/pick-sF9GnQUS.mjs.map +1 -0
- package/dist/pick-yHKUrnfG.mjs +11793 -0
- package/dist/pick-yHKUrnfG.mjs.map +1 -0
- package/dist/postgres-BJxiqtqg.mjs +891 -0
- package/dist/postgres-BJxiqtqg.mjs.map +1 -0
- package/dist/{postgres-B451Hnkm.mjs → postgres-zjKqPl4X.mjs} +2 -2
- package/dist/{postgres-B451Hnkm.mjs.map → postgres-zjKqPl4X.mjs.map} +1 -1
- package/dist/{query-feedback-fapbqRgh.mjs → query-feedback-BoY8_Dbb.mjs} +1 -1
- package/dist/{query-feedback-fapbqRgh.mjs.map → query-feedback-BoY8_Dbb.mjs.map} +1 -1
- package/dist/{reranker-C08R99zn.mjs → reranker-CMNZcfVx.mjs} +1 -1
- package/dist/{reranker-C08R99zn.mjs.map → reranker-CMNZcfVx.mjs.map} +1 -1
- package/dist/{search-HcdKtMla.mjs → search-CpTv1I24.mjs} +3 -3
- package/dist/{search-HcdKtMla.mjs.map → search-CpTv1I24.mjs.map} +1 -1
- package/dist/search-i2nlQ-JM.mjs +298 -0
- package/dist/search-i2nlQ-JM.mjs.map +1 -0
- package/dist/skills/End/SKILL.md +78 -0
- package/dist/skills/Pause/SKILL.md +84 -0
- package/dist/sqlite-CZ0LFili.mjs +271 -0
- package/dist/sqlite-CZ0LFili.mjs.map +1 -0
- package/dist/{sqlite-DQpY1Esi.mjs → sqlite-ChSCYwiC.mjs} +3 -3
- package/dist/{sqlite-DQpY1Esi.mjs.map → sqlite-ChSCYwiC.mjs.map} +1 -1
- package/dist/sqlite-Nw8ZW5Rj.mjs +271 -0
- package/dist/sqlite-Nw8ZW5Rj.mjs.map +1 -0
- package/dist/{state-BIlxNRUn.mjs → state-BXIdbxDs.mjs} +1 -1
- package/dist/{state-BIlxNRUn.mjs.map → state-BXIdbxDs.mjs.map} +1 -1
- package/dist/{stop-words-BwplsQ3z.mjs → stop-words-BaMEGVeY.mjs} +1 -1
- package/dist/{stop-words-BwplsQ3z.mjs.map → stop-words-BaMEGVeY.mjs.map} +1 -1
- package/dist/{sync-uPR4g438.mjs → sync--BoxBBok.mjs} +6 -205
- package/dist/sync--BoxBBok.mjs.map +1 -0
- package/dist/sync-CmBKOL3K.mjs +310 -0
- package/dist/sync-CmBKOL3K.mjs.map +1 -0
- package/dist/{themes-Cg8oG9Ra.mjs → themes-BBOlGXAg.mjs} +3 -3
- package/dist/{themes-Cg8oG9Ra.mjs.map → themes-BBOlGXAg.mjs.map} +1 -1
- package/dist/themes-nvRM8v84.mjs +148 -0
- package/dist/themes-nvRM8v84.mjs.map +1 -0
- package/dist/tools-B6BmaAvz.mjs +1939 -0
- package/dist/tools-B6BmaAvz.mjs.map +1 -0
- package/dist/tools-CAIY8TAb.mjs +1939 -0
- package/dist/tools-CAIY8TAb.mjs.map +1 -0
- package/dist/{tools-Op3C2Nm6.mjs → tools-CznjzfYz.mjs} +26 -26
- package/dist/{tools-Op3C2Nm6.mjs.map → tools-CznjzfYz.mjs.map} +1 -1
- package/dist/{trace-CLK-NPkb.mjs → trace-B8oz1ok0.mjs} +1 -1
- package/dist/{trace-CLK-NPkb.mjs.map → trace-B8oz1ok0.mjs.map} +1 -1
- package/dist/{utils-CqqgB0dH.mjs → utils-BAxjW3j8.mjs} +1 -1
- package/dist/{utils-CqqgB0dH.mjs.map → utils-BAxjW3j8.mjs.map} +1 -1
- package/dist/{vault-indexer-Dn_BccVK.mjs → vault-indexer-DrttVeEk.mjs} +2 -2
- package/dist/{vault-indexer-Dn_BccVK.mjs.map → vault-indexer-DrttVeEk.mjs.map} +1 -1
- package/dist/{work-queue-worker-BwouhVkb.mjs → work-queue-worker-BPXLkEik.mjs} +47 -30
- package/dist/work-queue-worker-BPXLkEik.mjs.map +1 -0
- package/dist/work-queue-worker-BoHIH70K.mjs +1856 -0
- package/dist/work-queue-worker-BoHIH70K.mjs.map +1 -0
- package/dist/work-queue-worker-CZGcQoLw.mjs +1856 -0
- package/dist/work-queue-worker-CZGcQoLw.mjs.map +1 -0
- package/dist/work-queue-worker-D05Ze9e9.mjs +1856 -0
- package/dist/work-queue-worker-D05Ze9e9.mjs.map +1 -0
- package/dist/work-queue-worker-DdXFINfH.mjs +1856 -0
- package/dist/work-queue-worker-DdXFINfH.mjs.map +1 -0
- package/dist/{zettelkasten-NwBD1NsT.mjs → zettelkasten-CTlt1dGv.mjs} +4 -4
- package/dist/{zettelkasten-NwBD1NsT.mjs.map → zettelkasten-CTlt1dGv.mjs.map} +1 -1
- package/dist/zettelkasten-D0N_A_OE.mjs +1063 -0
- package/dist/zettelkasten-D0N_A_OE.mjs.map +1 -0
- package/docs/commands/README.md +18 -0
- package/docs/commands/backup.md +1 -1
- package/docs/commands/clear-names.md +1 -1
- package/docs/commands/daemon.md +1 -1
- package/docs/commands/db.md +1 -1
- package/docs/commands/end.md +4 -1
- package/docs/commands/help.md +1 -1
- package/docs/commands/kg.md +1 -1
- package/docs/commands/mcp.md +1 -1
- package/docs/commands/memory.md +1 -1
- 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 +5 -2
- package/docs/commands/project.md +1 -1
- package/docs/commands/projects.md +1 -1
- package/docs/commands/registry.md +18 -1
- package/docs/commands/restore.md +1 -1
- package/docs/commands/session.md +295 -0
- 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/zettel.md +1 -1
- package/package.json +1 -1
- package/plugins/context-preservation/hooks/hooks.json +12 -1
- package/scripts/build-hooks.mjs +33 -3
- package/src/hooks/session-autosave.sh +69 -0
- package/src/hooks/session-stop.sh +32 -1
- package/src/hooks/ts/lib/project-utils/todo.test.ts +132 -0
- package/src/hooks/ts/lib/project-utils/todo.ts +60 -34
- package/src/hooks/ts/session-start/load-project-context.ts +44 -0
- package/dist/kg-extraction-C8DEUHTS.mjs.map +0 -1
- package/dist/pai-marker-HVBwwBW-.mjs.map +0 -1
- package/dist/pick-r95zvydr.mjs.map +0 -1
- package/dist/sync-uPR4g438.mjs.map +0 -1
- package/dist/work-queue-worker-BwouhVkb.mjs.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/hooks/ts/pre-compact/context-compression-hook.ts
|
|
4
|
-
import { existsSync as
|
|
5
|
-
import { basename as basename3, dirname, join as
|
|
4
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
5
|
+
import { basename as basename3, dirname, join as join7 } from "path";
|
|
6
6
|
import { tmpdir } from "os";
|
|
7
7
|
import { connect } from "net";
|
|
8
8
|
import { randomUUID } from "crypto";
|
|
@@ -420,13 +420,292 @@ function calculateSessionTokens(jsonlPath) {
|
|
|
420
420
|
}
|
|
421
421
|
|
|
422
422
|
// src/hooks/ts/lib/project-utils/todo.ts
|
|
423
|
-
import { existsSync as
|
|
424
|
-
import { join as
|
|
423
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "fs";
|
|
424
|
+
import { join as join6 } from "path";
|
|
425
|
+
|
|
426
|
+
// src/session/checkpoint-block.ts
|
|
427
|
+
import {
|
|
428
|
+
existsSync as existsSync6,
|
|
429
|
+
readFileSync as readFileSync5,
|
|
430
|
+
writeFileSync as writeFileSync2,
|
|
431
|
+
readdirSync as readdirSync3,
|
|
432
|
+
renameSync as renameSync3,
|
|
433
|
+
mkdirSync as mkdirSync3,
|
|
434
|
+
realpathSync
|
|
435
|
+
} from "node:fs";
|
|
436
|
+
import { join as join5 } from "node:path";
|
|
437
|
+
var TODO_LOCATIONS = [
|
|
438
|
+
"Notes/TODO.md",
|
|
439
|
+
".claude/Notes/TODO.md",
|
|
440
|
+
"tasks/todo.md",
|
|
441
|
+
"TODO.md"
|
|
442
|
+
];
|
|
443
|
+
var MARKER_OPEN = "<!-- pai:checkpoint";
|
|
444
|
+
var MARKER_CLOSE = "<!-- /pai:checkpoint -->";
|
|
445
|
+
var CONTINUE_HEADING = "## Continue";
|
|
446
|
+
function findProjectTodo(rootPath) {
|
|
447
|
+
for (const rel of TODO_LOCATIONS) {
|
|
448
|
+
const full = join5(rootPath, rel);
|
|
449
|
+
if (existsSync6(full)) {
|
|
450
|
+
try {
|
|
451
|
+
return { path: full, content: readFileSync5(full, "utf8") };
|
|
452
|
+
} catch {
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
function resolveTodoTarget(rootPath, opts = {}) {
|
|
459
|
+
const found = findProjectTodo(rootPath);
|
|
460
|
+
if (found) return found;
|
|
461
|
+
const notesDir = join5(rootPath, "Notes");
|
|
462
|
+
if (opts.create !== false) {
|
|
463
|
+
try {
|
|
464
|
+
if (!existsSync6(notesDir)) mkdirSync3(notesDir, { recursive: true });
|
|
465
|
+
} catch {
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return { path: join5(notesDir, "TODO.md"), content: "" };
|
|
470
|
+
}
|
|
471
|
+
function parseMarker(line) {
|
|
472
|
+
const trimmed = line.trim();
|
|
473
|
+
if (!trimmed.startsWith(MARKER_OPEN)) return null;
|
|
474
|
+
const attrs = {};
|
|
475
|
+
for (const m of trimmed.matchAll(/([a-zA-Z][\w-]*)="([^"]*)"/g)) {
|
|
476
|
+
attrs[m[1]] = m[2];
|
|
477
|
+
}
|
|
478
|
+
return {
|
|
479
|
+
authored: attrs.authored === "model" ? "model" : "auto",
|
|
480
|
+
session: attrs.session || void 0,
|
|
481
|
+
sessionId: attrs["session-id"] || void 0,
|
|
482
|
+
ts: attrs.ts || void 0
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
var BOILERPLATE_PATTERNS = [
|
|
486
|
+
/^##\s+Continue$/,
|
|
487
|
+
/^<!--\s*\/?pai:checkpoint/,
|
|
488
|
+
/^>\s*\*\*Last session:\*\*/,
|
|
489
|
+
/^>\s*\*\*Paused at:\*\*/,
|
|
490
|
+
/^>\s*Working directory:/,
|
|
491
|
+
/^>\s*Resume with:/,
|
|
492
|
+
/^>\s*_No checkpoint body was recorded/,
|
|
493
|
+
/^-{3,}$/
|
|
494
|
+
];
|
|
495
|
+
var BLANK_LINE = /^>?\s*$/;
|
|
496
|
+
function isBoilerplateOnly(lines) {
|
|
497
|
+
return lines.every((line) => {
|
|
498
|
+
const t = line.trim();
|
|
499
|
+
return BLANK_LINE.test(t) || BOILERPLATE_PATTERNS.some((re) => re.test(t));
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
function extractSectionContent(lines) {
|
|
503
|
+
const kept = [];
|
|
504
|
+
for (const line of lines) {
|
|
505
|
+
const t = line.trim();
|
|
506
|
+
if (BOILERPLATE_PATTERNS.some((re) => re.test(t))) continue;
|
|
507
|
+
kept.push(line);
|
|
508
|
+
}
|
|
509
|
+
return trimBlankEdges(collapseBlankRuns(kept)).join("\n");
|
|
510
|
+
}
|
|
511
|
+
function trimBlankEdges(lines) {
|
|
512
|
+
let start = 0;
|
|
513
|
+
let end = lines.length;
|
|
514
|
+
while (start < end && BLANK_LINE.test(lines[start].trim())) start += 1;
|
|
515
|
+
while (end > start && BLANK_LINE.test(lines[end - 1].trim())) end -= 1;
|
|
516
|
+
return lines.slice(start, end);
|
|
517
|
+
}
|
|
518
|
+
function collapseBlankRuns(lines) {
|
|
519
|
+
const out = [];
|
|
520
|
+
let lastWasBlank = false;
|
|
521
|
+
for (const line of lines) {
|
|
522
|
+
const isBlank = BLANK_LINE.test(line.trim());
|
|
523
|
+
if (isBlank && lastWasBlank) continue;
|
|
524
|
+
out.push(line);
|
|
525
|
+
lastWasBlank = isBlank;
|
|
526
|
+
}
|
|
527
|
+
return out;
|
|
528
|
+
}
|
|
529
|
+
function locateContinue(content) {
|
|
530
|
+
const lines = content.split("\n");
|
|
531
|
+
const startIdx = lines.findIndex((l) => l.trim() === CONTINUE_HEADING);
|
|
532
|
+
if (startIdx === -1) return null;
|
|
533
|
+
let meta = null;
|
|
534
|
+
let markerIdx = -1;
|
|
535
|
+
for (let i = startIdx + 1; i < Math.min(startIdx + 6, lines.length); i++) {
|
|
536
|
+
const parsed = parseMarker(lines[i]);
|
|
537
|
+
if (parsed) {
|
|
538
|
+
meta = parsed;
|
|
539
|
+
markerIdx = i;
|
|
540
|
+
break;
|
|
541
|
+
}
|
|
542
|
+
if (lines[i].trim() !== "") break;
|
|
543
|
+
}
|
|
544
|
+
let endIdx = lines.length;
|
|
545
|
+
if (markerIdx !== -1) {
|
|
546
|
+
const closeIdx = lines.findIndex(
|
|
547
|
+
(l, i) => i > markerIdx && l.trim() === MARKER_CLOSE
|
|
548
|
+
);
|
|
549
|
+
if (closeIdx !== -1) {
|
|
550
|
+
endIdx = closeIdx + 1;
|
|
551
|
+
} else {
|
|
552
|
+
endIdx = heuristicEnd(lines, startIdx);
|
|
553
|
+
}
|
|
554
|
+
} else {
|
|
555
|
+
endIdx = heuristicEnd(lines, startIdx);
|
|
556
|
+
}
|
|
557
|
+
let trailingEnd = endIdx;
|
|
558
|
+
while (trailingEnd < lines.length && lines[trailingEnd].trim() === "") {
|
|
559
|
+
trailingEnd += 1;
|
|
560
|
+
}
|
|
561
|
+
if (trailingEnd < lines.length && lines[trailingEnd].trim() === "---") {
|
|
562
|
+
trailingEnd += 1;
|
|
563
|
+
} else {
|
|
564
|
+
trailingEnd = endIdx;
|
|
565
|
+
}
|
|
566
|
+
return {
|
|
567
|
+
startIdx,
|
|
568
|
+
endIdx: trailingEnd,
|
|
569
|
+
meta,
|
|
570
|
+
lines: lines.slice(startIdx, trailingEnd)
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
function heuristicEnd(lines, startIdx) {
|
|
574
|
+
for (let i = startIdx + 1; i < lines.length; i++) {
|
|
575
|
+
const trimmed = lines[i].trim();
|
|
576
|
+
if (trimmed === "---" || /^##(?!#)/.test(trimmed) && trimmed !== CONTINUE_HEADING) {
|
|
577
|
+
return i;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
return lines.length;
|
|
581
|
+
}
|
|
582
|
+
function stripContinue(content) {
|
|
583
|
+
const found = locateContinue(content);
|
|
584
|
+
if (!found) return content;
|
|
585
|
+
const lines = content.split("\n");
|
|
586
|
+
const before = lines.slice(0, found.startIdx);
|
|
587
|
+
const after = lines.slice(found.endIdx);
|
|
588
|
+
while (after.length > 0 && after[0].trim() === "") after.shift();
|
|
589
|
+
return [...before, ...after].join("\n");
|
|
590
|
+
}
|
|
591
|
+
function escapeAttr(value) {
|
|
592
|
+
return value.replace(/"/g, "'");
|
|
593
|
+
}
|
|
594
|
+
function buildContinueBlock(opts) {
|
|
595
|
+
const ts = opts.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
596
|
+
const attrs = [
|
|
597
|
+
`authored="${opts.authored}"`,
|
|
598
|
+
`session="${escapeAttr(opts.sessionLine)}"`,
|
|
599
|
+
opts.sessionId ? `session-id="${escapeAttr(opts.sessionId)}"` : null,
|
|
600
|
+
`ts="${ts}"`
|
|
601
|
+
].filter(Boolean).join(" ");
|
|
602
|
+
const header = [
|
|
603
|
+
`> **Last session:** ${opts.sessionLine}`,
|
|
604
|
+
`> **Paused at:** ${ts}`,
|
|
605
|
+
">",
|
|
606
|
+
`> Working directory: ${opts.cwd}`
|
|
607
|
+
];
|
|
608
|
+
if (opts.sessionId) {
|
|
609
|
+
header.push(">", `> Resume with: \`claude --resume ${opts.sessionId}\``);
|
|
610
|
+
}
|
|
611
|
+
const body = (opts.body ?? "").trim();
|
|
612
|
+
const parts = [
|
|
613
|
+
CONTINUE_HEADING,
|
|
614
|
+
"",
|
|
615
|
+
`${MARKER_OPEN} ${attrs} -->`,
|
|
616
|
+
"",
|
|
617
|
+
...header
|
|
618
|
+
];
|
|
619
|
+
if (body) {
|
|
620
|
+
parts.push("", body);
|
|
621
|
+
} else {
|
|
622
|
+
parts.push(
|
|
623
|
+
">",
|
|
624
|
+
"> _No checkpoint body was recorded \u2014 see the latest session note._"
|
|
625
|
+
);
|
|
626
|
+
}
|
|
627
|
+
parts.push("", MARKER_CLOSE, "", "---", "");
|
|
628
|
+
return parts.join("\n");
|
|
629
|
+
}
|
|
630
|
+
function isSameSession(meta, opts) {
|
|
631
|
+
if (meta.sessionId && opts.sessionId) {
|
|
632
|
+
return meta.sessionId === opts.sessionId;
|
|
633
|
+
}
|
|
634
|
+
return meta.session === opts.sessionLine;
|
|
635
|
+
}
|
|
636
|
+
function applyContinue(opts) {
|
|
637
|
+
const target = resolveTodoTarget(opts.rootPath, { create: !opts.dryRun });
|
|
638
|
+
if (!target) {
|
|
639
|
+
return {
|
|
640
|
+
action: "failed",
|
|
641
|
+
path: null,
|
|
642
|
+
block: buildContinueBlock(opts),
|
|
643
|
+
error: "Could not resolve or create a TODO.md target"
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
const existing = locateContinue(target.content);
|
|
647
|
+
let carriedForward = false;
|
|
648
|
+
let effectiveBody = opts.body;
|
|
649
|
+
if (opts.authored === "auto" && existing) {
|
|
650
|
+
if (existing.meta?.authored === "model" && isSameSession(existing.meta, opts)) {
|
|
651
|
+
return {
|
|
652
|
+
action: "preserved",
|
|
653
|
+
path: target.path,
|
|
654
|
+
block: buildContinueBlock(opts),
|
|
655
|
+
preservedMeta: existing.meta
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
if (existing.meta && !(opts.body ?? "").trim() && !isBoilerplateOnly(existing.lines)) {
|
|
659
|
+
return {
|
|
660
|
+
action: "preserved",
|
|
661
|
+
path: target.path,
|
|
662
|
+
block: buildContinueBlock(opts),
|
|
663
|
+
preservedMeta: existing.meta ?? void 0
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
if (!existing.meta && !isBoilerplateOnly(existing.lines)) {
|
|
667
|
+
const salvaged = extractSectionContent(existing.lines);
|
|
668
|
+
if (salvaged) {
|
|
669
|
+
effectiveBody = [
|
|
670
|
+
"_Carried forward from the previous checkpoint (author unknown \u2014 this",
|
|
671
|
+
"block predates checkpoint authorship markers):_",
|
|
672
|
+
"",
|
|
673
|
+
salvaged
|
|
674
|
+
].join("\n");
|
|
675
|
+
carriedForward = true;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
const block = buildContinueBlock({ ...opts, body: effectiveBody });
|
|
680
|
+
if (opts.dryRun) {
|
|
681
|
+
return { action: "written", path: target.path, block, carriedForward };
|
|
682
|
+
}
|
|
683
|
+
const newContent = block + stripContinue(target.content).trimStart();
|
|
684
|
+
const tmpPath = `${target.path}.continue.tmp`;
|
|
685
|
+
try {
|
|
686
|
+
writeFileSync2(tmpPath, newContent, "utf8");
|
|
687
|
+
renameSync3(tmpPath, target.path);
|
|
688
|
+
} catch (err) {
|
|
689
|
+
try {
|
|
690
|
+
if (existsSync6(tmpPath)) renameSync3(tmpPath, `${tmpPath}.dead`);
|
|
691
|
+
} catch {
|
|
692
|
+
}
|
|
693
|
+
return {
|
|
694
|
+
action: "failed",
|
|
695
|
+
path: target.path,
|
|
696
|
+
block,
|
|
697
|
+
error: String(err)
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
return { action: "written", path: target.path, block, carriedForward };
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// src/hooks/ts/lib/project-utils/todo.ts
|
|
425
704
|
function ensureTodoMd(cwd) {
|
|
426
705
|
const todoPath = findTodoPath(cwd);
|
|
427
|
-
if (!
|
|
428
|
-
const parentDir =
|
|
429
|
-
if (!
|
|
706
|
+
if (!existsSync7(todoPath)) {
|
|
707
|
+
const parentDir = join6(todoPath, "..");
|
|
708
|
+
if (!existsSync7(parentDir)) mkdirSync4(parentDir, { recursive: true });
|
|
430
709
|
const content = `# TODO
|
|
431
710
|
|
|
432
711
|
## Current Session
|
|
@@ -441,43 +720,52 @@ function ensureTodoMd(cwd) {
|
|
|
441
720
|
|
|
442
721
|
*Last updated: ${(/* @__PURE__ */ new Date()).toISOString()}*
|
|
443
722
|
`;
|
|
444
|
-
|
|
723
|
+
writeFileSync3(todoPath, content);
|
|
445
724
|
console.error(`Created TODO.md: ${todoPath}`);
|
|
446
725
|
}
|
|
447
726
|
return todoPath;
|
|
448
727
|
}
|
|
449
728
|
function updateTodoContinue(cwd, noteFilename, state, tokenDisplay) {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
content = titleMatch[1] + continueSection + content.substring(titleMatch[0].length);
|
|
469
|
-
} else {
|
|
470
|
-
content = continueSection + content;
|
|
729
|
+
ensureTodoMd(cwd);
|
|
730
|
+
const result = applyContinue({
|
|
731
|
+
rootPath: cwd,
|
|
732
|
+
authored: "auto",
|
|
733
|
+
// The hooks identify a session by its note filename; `pai pause` resolves
|
|
734
|
+
// the same string from the registry (and falls back to this filename when
|
|
735
|
+
// the registry has no session row). They must agree, because this string
|
|
736
|
+
// is the key that decides whether an authored checkpoint belongs to the
|
|
737
|
+
// current session and must be preserved.
|
|
738
|
+
sessionLine: noteFilename.replace(/\.md$/, ""),
|
|
739
|
+
cwd,
|
|
740
|
+
body: state?.trim() || void 0
|
|
741
|
+
});
|
|
742
|
+
if (result.action === "preserved") {
|
|
743
|
+
console.error(
|
|
744
|
+
"TODO.md ## Continue left intact \u2014 authored checkpoint for this session"
|
|
745
|
+
);
|
|
746
|
+
return;
|
|
471
747
|
}
|
|
472
|
-
|
|
473
|
-
|
|
748
|
+
if (result.action === "failed") {
|
|
749
|
+
console.error(`TODO.md ## Continue update failed: ${result.error}`);
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
try {
|
|
753
|
+
const todoPath = result.path;
|
|
754
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
755
|
+
let content = readFileSync6(todoPath, "utf-8");
|
|
756
|
+
content = content.replace(/(\n---\s*)*(\n\*Last updated:.*\*\s*)+$/g, "");
|
|
757
|
+
content = content.trimEnd() + `
|
|
474
758
|
|
|
475
759
|
---
|
|
476
760
|
|
|
477
761
|
*Last updated: ${now}*
|
|
478
762
|
`;
|
|
479
|
-
|
|
480
|
-
|
|
763
|
+
writeFileSync3(todoPath, content);
|
|
764
|
+
} catch {
|
|
765
|
+
}
|
|
766
|
+
console.error(
|
|
767
|
+
result.carriedForward ? "TODO.md ## Continue section updated (previous content carried forward)" : "TODO.md ## Continue section updated"
|
|
768
|
+
);
|
|
481
769
|
}
|
|
482
770
|
|
|
483
771
|
// src/hooks/ts/pre-compact/context-compression-hook.ts
|
|
@@ -497,7 +785,7 @@ function contentToText(content) {
|
|
|
497
785
|
}
|
|
498
786
|
function getTranscriptStats(transcriptPath) {
|
|
499
787
|
try {
|
|
500
|
-
const content =
|
|
788
|
+
const content = readFileSync7(transcriptPath, "utf-8");
|
|
501
789
|
const lines = content.trim().split("\n");
|
|
502
790
|
let userMessages = 0;
|
|
503
791
|
let assistantMessages = 0;
|
|
@@ -526,7 +814,7 @@ function parseTranscript(transcriptPath) {
|
|
|
526
814
|
workItems: []
|
|
527
815
|
};
|
|
528
816
|
try {
|
|
529
|
-
const raw =
|
|
817
|
+
const raw = readFileSync7(transcriptPath, "utf-8");
|
|
530
818
|
const lines = raw.trim().split("\n");
|
|
531
819
|
const seenSummaries = /* @__PURE__ */ new Set();
|
|
532
820
|
for (const line of lines) {
|
|
@@ -662,9 +950,9 @@ function deriveTitle(data) {
|
|
|
662
950
|
var CUMULATIVE_STATE_FILE = ".compact-state.json";
|
|
663
951
|
function loadCumulativeState(notesDir) {
|
|
664
952
|
try {
|
|
665
|
-
const filePath =
|
|
666
|
-
if (!
|
|
667
|
-
const raw = JSON.parse(
|
|
953
|
+
const filePath = join7(notesDir, CUMULATIVE_STATE_FILE);
|
|
954
|
+
if (!existsSync8(filePath)) return null;
|
|
955
|
+
const raw = JSON.parse(readFileSync7(filePath, "utf-8"));
|
|
668
956
|
return {
|
|
669
957
|
userMessages: raw.userMessages || [],
|
|
670
958
|
summaries: raw.summaries || [],
|
|
@@ -696,8 +984,8 @@ function mergeTranscriptData(accumulated, current) {
|
|
|
696
984
|
}
|
|
697
985
|
function saveCumulativeState(notesDir, data, notePath) {
|
|
698
986
|
try {
|
|
699
|
-
const filePath =
|
|
700
|
-
|
|
987
|
+
const filePath = join7(notesDir, CUMULATIVE_STATE_FILE);
|
|
988
|
+
writeFileSync4(filePath, JSON.stringify({
|
|
701
989
|
...data,
|
|
702
990
|
notePath,
|
|
703
991
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -840,9 +1128,9 @@ async function main() {
|
|
|
840
1128
|
const data = parseTranscript(hookInput.transcript_path);
|
|
841
1129
|
let notesInfo;
|
|
842
1130
|
try {
|
|
843
|
-
notesInfo = hookInput.cwd ? findNotesDir(hookInput.cwd) : { path:
|
|
1131
|
+
notesInfo = hookInput.cwd ? findNotesDir(hookInput.cwd) : { path: join7(dirname(hookInput.transcript_path), "Notes"), isLocal: false };
|
|
844
1132
|
} catch {
|
|
845
|
-
notesInfo = { path:
|
|
1133
|
+
notesInfo = { path: join7(dirname(hookInput.transcript_path), "Notes"), isLocal: false };
|
|
846
1134
|
}
|
|
847
1135
|
const accumulated = loadCumulativeState(notesInfo.path);
|
|
848
1136
|
const merged = mergeTranscriptData(accumulated, data);
|
|
@@ -858,10 +1146,10 @@ async function main() {
|
|
|
858
1146
|
notePath = createSessionNote(notesInfo.path, "Untitled Session");
|
|
859
1147
|
} else {
|
|
860
1148
|
try {
|
|
861
|
-
let noteContent =
|
|
1149
|
+
let noteContent = readFileSync7(notePath, "utf-8");
|
|
862
1150
|
if (noteContent.includes("**Status:** Completed")) {
|
|
863
1151
|
noteContent = noteContent.replace("**Status:** Completed", "**Status:** In Progress");
|
|
864
|
-
|
|
1152
|
+
writeFileSync4(notePath, noteContent);
|
|
865
1153
|
console.error(`Reopened completed note for continued session: ${basename3(notePath)}`);
|
|
866
1154
|
}
|
|
867
1155
|
} catch {
|
|
@@ -880,12 +1168,12 @@ ${state}` : `Context compression triggered at ~${tokenDisplay} tokens with ${sta
|
|
|
880
1168
|
const newPath = renameSessionNote(notePath, title);
|
|
881
1169
|
if (newPath !== notePath) {
|
|
882
1170
|
try {
|
|
883
|
-
let noteContent =
|
|
1171
|
+
let noteContent = readFileSync7(newPath, "utf-8");
|
|
884
1172
|
noteContent = noteContent.replace(
|
|
885
1173
|
/^(# Session \d+:)\s*.*$/m,
|
|
886
1174
|
`$1 ${title}`
|
|
887
1175
|
);
|
|
888
|
-
|
|
1176
|
+
writeFileSync4(newPath, noteContent);
|
|
889
1177
|
console.error(`Updated note H1 to match rename`);
|
|
890
1178
|
} catch {
|
|
891
1179
|
}
|
|
@@ -926,8 +1214,8 @@ rename it based on actual work done and add a rich summary.` : "";
|
|
|
926
1214
|
"</system-reminder>"
|
|
927
1215
|
].join("\n");
|
|
928
1216
|
try {
|
|
929
|
-
const stateFile =
|
|
930
|
-
|
|
1217
|
+
const stateFile = join7(tmpdir(), `pai-compact-state-${hookInput.session_id}.txt`);
|
|
1218
|
+
writeFileSync4(stateFile, injection, "utf-8");
|
|
931
1219
|
console.error(`Session state saved to ${stateFile} (${injection.length} chars)`);
|
|
932
1220
|
} catch (err) {
|
|
933
1221
|
console.error(`Failed to save state file: ${err}`);
|