@tekmidian/pai 0.16.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.
Files changed (123) hide show
  1. package/README.md +11 -3
  2. package/dist/auto-route-DkIRampF.mjs +86 -0
  3. package/dist/auto-route-DkIRampF.mjs.map +1 -0
  4. package/dist/checkpoint-block-Bl0HD3U2.mjs.map +1 -1
  5. package/dist/checkpoint-block-C05sK_HK.mjs +1056 -0
  6. package/dist/checkpoint-block-C05sK_HK.mjs.map +1 -0
  7. package/dist/checkpoint-block-CUCG10Uh.mjs +1022 -0
  8. package/dist/checkpoint-block-CUCG10Uh.mjs.map +1 -0
  9. package/dist/checkpoint-block-D5IyLLTr.mjs +1062 -0
  10. package/dist/checkpoint-block-D5IyLLTr.mjs.map +1 -0
  11. package/dist/cli/index.mjs +6 -6
  12. package/dist/cli/program.mjs +7 -7
  13. package/dist/cli/program.mjs.map +1 -1
  14. package/dist/daemon/index.mjs +9 -9
  15. package/dist/daemon-9AL6Pwh-.mjs +1581 -0
  16. package/dist/daemon-9AL6Pwh-.mjs.map +1 -0
  17. package/dist/daemon-Bbk-_rV6.mjs +1581 -0
  18. package/dist/daemon-Bbk-_rV6.mjs.map +1 -0
  19. package/dist/daemon-BvcaMk4g.mjs +1581 -0
  20. package/dist/daemon-BvcaMk4g.mjs.map +1 -0
  21. package/dist/daemon-CTDEfwcq.mjs +1576 -0
  22. package/dist/daemon-CTDEfwcq.mjs.map +1 -0
  23. package/dist/daemon-ClbfaF60.mjs +1576 -0
  24. package/dist/daemon-ClbfaF60.mjs.map +1 -0
  25. package/dist/daemon-DDQNDgYF.mjs +1576 -0
  26. package/dist/daemon-DDQNDgYF.mjs.map +1 -0
  27. package/dist/daemon-DU8yDWlQ.mjs +1576 -0
  28. package/dist/daemon-DU8yDWlQ.mjs.map +1 -0
  29. package/dist/daemon-NJr4iSW3.mjs +1576 -0
  30. package/dist/daemon-NJr4iSW3.mjs.map +1 -0
  31. package/dist/detector-Bwzm3E_x.mjs +74 -0
  32. package/dist/detector-Bwzm3E_x.mjs.map +1 -0
  33. package/dist/embeddings-Bn86ssxR.mjs +119 -0
  34. package/dist/embeddings-Bn86ssxR.mjs.map +1 -0
  35. package/dist/factory-0-57Ac-7.mjs +72 -0
  36. package/dist/factory-0-57Ac-7.mjs.map +1 -0
  37. package/dist/factory-PDXQdkLO.mjs +72 -0
  38. package/dist/factory-PDXQdkLO.mjs.map +1 -0
  39. package/dist/hooks/context-compression-hook.mjs +36 -4
  40. package/dist/hooks/context-compression-hook.mjs.map +3 -3
  41. package/dist/hooks/load-project-context.mjs +188 -6
  42. package/dist/hooks/load-project-context.mjs.map +4 -4
  43. package/dist/hooks/stop-hook.mjs +36 -4
  44. package/dist/hooks/stop-hook.mjs.map +3 -3
  45. package/dist/index.mjs +3 -3
  46. package/dist/indexer-backend-BmaS2VcD.mjs +299 -0
  47. package/dist/indexer-backend-BmaS2VcD.mjs.map +1 -0
  48. package/dist/indexer-backend-COrJ5rjS.mjs +299 -0
  49. package/dist/indexer-backend-COrJ5rjS.mjs.map +1 -0
  50. package/dist/indexer-backend-NwD7TBGh.mjs +301 -0
  51. package/dist/indexer-backend-NwD7TBGh.mjs.map +1 -0
  52. package/dist/latent-ideas-BwM3WdBp.mjs +191 -0
  53. package/dist/latent-ideas-BwM3WdBp.mjs.map +1 -0
  54. package/dist/neighborhood-DZY0wkpE.mjs +135 -0
  55. package/dist/neighborhood-DZY0wkpE.mjs.map +1 -0
  56. package/dist/pick-B0q5cy79.mjs +11785 -0
  57. package/dist/pick-B0q5cy79.mjs.map +1 -0
  58. package/dist/pick-BHE9_iA0.mjs +11947 -0
  59. package/dist/pick-BHE9_iA0.mjs.map +1 -0
  60. package/dist/pick-BaTjoNqM.mjs +11544 -0
  61. package/dist/pick-BaTjoNqM.mjs.map +1 -0
  62. package/dist/pick-C6JbZfN4.mjs +11893 -0
  63. package/dist/pick-C6JbZfN4.mjs.map +1 -0
  64. package/dist/pick-CK-bJyjp.mjs +11883 -0
  65. package/dist/pick-CK-bJyjp.mjs.map +1 -0
  66. package/dist/pick-CLBkGHyI.mjs +11826 -0
  67. package/dist/pick-CLBkGHyI.mjs.map +1 -0
  68. package/dist/pick-CTOif21h.mjs +11544 -0
  69. package/dist/pick-CTOif21h.mjs.map +1 -0
  70. package/dist/pick-Ck2cdQgD.mjs +11893 -0
  71. package/dist/pick-Ck2cdQgD.mjs.map +1 -0
  72. package/dist/pick-Cr4nJzHA.mjs +11914 -0
  73. package/dist/pick-Cr4nJzHA.mjs.map +1 -0
  74. package/dist/pick-D4dFfKAu.mjs +11893 -0
  75. package/dist/pick-D4dFfKAu.mjs.map +1 -0
  76. package/dist/pick-D7-lYiGX.mjs +11543 -0
  77. package/dist/pick-D7-lYiGX.mjs.map +1 -0
  78. package/dist/pick-DMjCY0np.mjs +11875 -0
  79. package/dist/pick-DMjCY0np.mjs.map +1 -0
  80. package/dist/pick-DbX4OrCP.mjs +11543 -0
  81. package/dist/pick-DbX4OrCP.mjs.map +1 -0
  82. package/dist/pick-iCiPjlnC.mjs +11893 -0
  83. package/dist/pick-iCiPjlnC.mjs.map +1 -0
  84. package/dist/pick-sF9GnQUS.mjs +11893 -0
  85. package/dist/pick-sF9GnQUS.mjs.map +1 -0
  86. package/dist/pick-yHKUrnfG.mjs +11793 -0
  87. package/dist/pick-yHKUrnfG.mjs.map +1 -0
  88. package/dist/postgres-BJxiqtqg.mjs +891 -0
  89. package/dist/postgres-BJxiqtqg.mjs.map +1 -0
  90. package/dist/search-CpTv1I24.mjs +298 -0
  91. package/dist/search-CpTv1I24.mjs.map +1 -0
  92. package/dist/skills/Pause/SKILL.md +11 -4
  93. package/dist/sqlite-CZ0LFili.mjs +271 -0
  94. package/dist/sqlite-CZ0LFili.mjs.map +1 -0
  95. package/dist/sqlite-Nw8ZW5Rj.mjs +271 -0
  96. package/dist/sqlite-Nw8ZW5Rj.mjs.map +1 -0
  97. package/dist/sync--BoxBBok.mjs +310 -0
  98. package/dist/sync--BoxBBok.mjs.map +1 -0
  99. package/dist/themes-BBOlGXAg.mjs +148 -0
  100. package/dist/themes-BBOlGXAg.mjs.map +1 -0
  101. package/dist/tools-B6BmaAvz.mjs +1939 -0
  102. package/dist/tools-B6BmaAvz.mjs.map +1 -0
  103. package/dist/tools-CAIY8TAb.mjs +1939 -0
  104. package/dist/tools-CAIY8TAb.mjs.map +1 -0
  105. package/dist/work-queue-worker-BoHIH70K.mjs +1856 -0
  106. package/dist/work-queue-worker-BoHIH70K.mjs.map +1 -0
  107. package/dist/work-queue-worker-CZGcQoLw.mjs +1856 -0
  108. package/dist/work-queue-worker-CZGcQoLw.mjs.map +1 -0
  109. package/dist/work-queue-worker-D05Ze9e9.mjs +1856 -0
  110. package/dist/work-queue-worker-D05Ze9e9.mjs.map +1 -0
  111. package/dist/work-queue-worker-DdXFINfH.mjs +1856 -0
  112. package/dist/work-queue-worker-DdXFINfH.mjs.map +1 -0
  113. package/dist/zettelkasten-D0N_A_OE.mjs +1063 -0
  114. package/dist/zettelkasten-D0N_A_OE.mjs.map +1 -0
  115. package/docs/commands/README.md +2 -1
  116. package/docs/commands/pause.md +1 -1
  117. package/docs/commands/session.md +27 -3
  118. package/package.json +1 -1
  119. package/plugins/context-preservation/hooks/hooks.json +12 -1
  120. package/scripts/build-hooks.mjs +1 -0
  121. package/src/hooks/session-autosave.sh +69 -0
  122. package/src/hooks/session-stop.sh +32 -1
  123. package/src/hooks/ts/session-start/load-project-context.ts +44 -0
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/hooks/ts/session-start/load-project-context.ts
4
- import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync5, statSync } from "fs";
4
+ import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
5
5
  import { join as join6, basename as basename4, dirname, resolve as resolve2 } from "path";
6
6
  import { homedir as homedir4 } from "os";
7
7
  import { execSync } from "child_process";
8
8
 
9
9
  // src/memory/wakeup.ts
10
- import { existsSync, readdirSync, readFileSync } from "node:fs";
10
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
11
11
  import { join, basename } from "node:path";
12
12
  import { homedir } from "node:os";
13
13
  var L1_TOKEN_BUDGET = 800;
@@ -68,10 +68,26 @@ function findSessionNotes(notesDir) {
68
68
  }
69
69
  };
70
70
  scanDir(notesDir);
71
+ const dateOf = (p) => basename(p).match(/(\d{4}-\d{2}-\d{2})/)?.[1] ?? "";
72
+ const numberOf = (p) => parseInt(basename(p).match(/^(\d+)/)?.[1] ?? "0", 10);
73
+ const mtimeOf = (p) => {
74
+ try {
75
+ return statSync(p).mtimeMs;
76
+ } catch {
77
+ return 0;
78
+ }
79
+ };
71
80
  result.sort((a, b) => {
72
- const numA = parseInt(basename(a).match(/^(\d+)/)?.[1] ?? "0", 10);
73
- const numB = parseInt(basename(b).match(/^(\d+)/)?.[1] ?? "0", 10);
74
- return numB - numA;
81
+ const dateA = dateOf(a);
82
+ const dateB = dateOf(b);
83
+ if (dateA !== dateB) {
84
+ if (!dateA) return 1;
85
+ if (!dateB) return -1;
86
+ return dateB.localeCompare(dateA);
87
+ }
88
+ const byNumber = numberOf(b) - numberOf(a);
89
+ if (byNumber !== 0) return byNumber;
90
+ return mtimeOf(b) - mtimeOf(a);
75
91
  });
76
92
  return result;
77
93
  }
@@ -161,6 +177,141 @@ ${essentialStory}`);
161
177
  return parts.join("\n\n");
162
178
  }
163
179
 
180
+ // src/session/checkpoint-block.ts
181
+ var MARKER_OPEN = "<!-- pai:checkpoint";
182
+ var MARKER_CLOSE = "<!-- /pai:checkpoint -->";
183
+ var CONTINUE_HEADING = "## Continue";
184
+ function parseMarker(line) {
185
+ const trimmed = line.trim();
186
+ if (!trimmed.startsWith(MARKER_OPEN)) return null;
187
+ const attrs = {};
188
+ for (const m of trimmed.matchAll(/([a-zA-Z][\w-]*)="([^"]*)"/g)) {
189
+ attrs[m[1]] = m[2];
190
+ }
191
+ return {
192
+ authored: attrs.authored === "model" ? "model" : "auto",
193
+ session: attrs.session || void 0,
194
+ sessionId: attrs["session-id"] || void 0,
195
+ ts: attrs.ts || void 0
196
+ };
197
+ }
198
+ var BOILERPLATE_PATTERNS = [
199
+ /^##\s+Continue$/,
200
+ /^<!--\s*\/?pai:checkpoint/,
201
+ /^>\s*\*\*Last session:\*\*/,
202
+ /^>\s*\*\*Paused at:\*\*/,
203
+ /^>\s*Working directory:/,
204
+ /^>\s*Resume with:/,
205
+ /^>\s*_No checkpoint body was recorded/,
206
+ /^-{3,}$/
207
+ ];
208
+ var BLANK_LINE = /^>?\s*$/;
209
+ function extractSectionContent(lines) {
210
+ const kept = [];
211
+ for (const line of lines) {
212
+ const t = line.trim();
213
+ if (BOILERPLATE_PATTERNS.some((re) => re.test(t))) continue;
214
+ kept.push(line);
215
+ }
216
+ return trimBlankEdges(collapseBlankRuns(kept)).join("\n");
217
+ }
218
+ function trimBlankEdges(lines) {
219
+ let start = 0;
220
+ let end = lines.length;
221
+ while (start < end && BLANK_LINE.test(lines[start].trim())) start += 1;
222
+ while (end > start && BLANK_LINE.test(lines[end - 1].trim())) end -= 1;
223
+ return lines.slice(start, end);
224
+ }
225
+ function collapseBlankRuns(lines) {
226
+ const out = [];
227
+ let lastWasBlank = false;
228
+ for (const line of lines) {
229
+ const isBlank = BLANK_LINE.test(line.trim());
230
+ if (isBlank && lastWasBlank) continue;
231
+ out.push(line);
232
+ lastWasBlank = isBlank;
233
+ }
234
+ return out;
235
+ }
236
+ function locateContinue(content) {
237
+ const lines = content.split("\n");
238
+ const startIdx = lines.findIndex((l) => l.trim() === CONTINUE_HEADING);
239
+ if (startIdx === -1) return null;
240
+ let meta = null;
241
+ let markerIdx = -1;
242
+ for (let i = startIdx + 1; i < Math.min(startIdx + 6, lines.length); i++) {
243
+ const parsed = parseMarker(lines[i]);
244
+ if (parsed) {
245
+ meta = parsed;
246
+ markerIdx = i;
247
+ break;
248
+ }
249
+ if (lines[i].trim() !== "") break;
250
+ }
251
+ let endIdx = lines.length;
252
+ if (markerIdx !== -1) {
253
+ const closeIdx = lines.findIndex(
254
+ (l, i) => i > markerIdx && l.trim() === MARKER_CLOSE
255
+ );
256
+ if (closeIdx !== -1) {
257
+ endIdx = closeIdx + 1;
258
+ } else {
259
+ endIdx = heuristicEnd(lines, startIdx);
260
+ }
261
+ } else {
262
+ endIdx = heuristicEnd(lines, startIdx);
263
+ }
264
+ let trailingEnd = endIdx;
265
+ while (trailingEnd < lines.length && lines[trailingEnd].trim() === "") {
266
+ trailingEnd += 1;
267
+ }
268
+ if (trailingEnd < lines.length && lines[trailingEnd].trim() === "---") {
269
+ trailingEnd += 1;
270
+ } else {
271
+ trailingEnd = endIdx;
272
+ }
273
+ return {
274
+ startIdx,
275
+ endIdx: trailingEnd,
276
+ meta,
277
+ lines: lines.slice(startIdx, trailingEnd)
278
+ };
279
+ }
280
+ function heuristicEnd(lines, startIdx) {
281
+ for (let i = startIdx + 1; i < lines.length; i++) {
282
+ const trimmed = lines[i].trim();
283
+ if (trimmed === "---" || /^##(?!#)/.test(trimmed) && trimmed !== CONTINUE_HEADING) {
284
+ return i;
285
+ }
286
+ }
287
+ return lines.length;
288
+ }
289
+ function readContinueCheckpoint(content) {
290
+ const found = locateContinue(content);
291
+ if (!found) return null;
292
+ const body = found.meta ? extractMarkedBody(found.lines) : extractSectionContent(found.lines);
293
+ if (!body) return null;
294
+ return { meta: found.meta, body, raw: found.lines.join("\n") };
295
+ }
296
+ function extractMarkedBody(lines) {
297
+ const markerIdx = lines.findIndex((l) => parseMarker(l) !== null);
298
+ if (markerIdx === -1) return extractSectionContent(lines);
299
+ const closeIdx = lines.findIndex(
300
+ (l, i) => i > markerIdx && l.trim() === MARKER_CLOSE
301
+ );
302
+ if (closeIdx === -1) return extractSectionContent(lines);
303
+ let bodyStart = markerIdx + 1;
304
+ while (bodyStart < closeIdx) {
305
+ const t = lines[bodyStart].trim();
306
+ if (BLANK_LINE.test(t) || t.startsWith(">")) {
307
+ bodyStart += 1;
308
+ continue;
309
+ }
310
+ break;
311
+ }
312
+ return trimBlankEdges(lines.slice(bodyStart, closeIdx)).join("\n");
313
+ }
314
+
164
315
  // src/hooks/ts/lib/project-utils/paths.ts
165
316
  import { existsSync as existsSync3, mkdirSync, readdirSync as readdirSync2, renameSync } from "fs";
166
317
  import { join as join3, basename as basename2 } from "path";
@@ -573,7 +724,7 @@ async function main() {
573
724
  const jsonlFiles = files.filter((f) => f.endsWith(".jsonl")).map((f) => ({
574
725
  name: f,
575
726
  path: join6(projectDir, f),
576
- mtime: statSync(join6(projectDir, f)).mtime.getTime()
727
+ mtime: statSync2(join6(projectDir, f)).mtime.getTime()
577
728
  })).sort((a, b) => b.mtime - a.mtime);
578
729
  if (jsonlFiles.length > 1) {
579
730
  const { mkdirSync: mkdirSync3, renameSync: renameSync3 } = await import("fs");
@@ -750,6 +901,37 @@ Session Commands:
750
901
  </system-reminder>
751
902
  `;
752
903
  console.log(reminder);
904
+ if (existsSync6(todoPath)) {
905
+ try {
906
+ const checkpoint = readContinueCheckpoint(readFileSync5(todoPath, "utf-8"));
907
+ if (checkpoint) {
908
+ const from = checkpoint.meta?.session ? `
909
+ From session: ${checkpoint.meta.session}` : "";
910
+ const when = checkpoint.meta?.ts ? `
911
+ Paused at: ${checkpoint.meta.ts}` : "";
912
+ const resume = checkpoint.meta?.sessionId ? `
913
+ Resume that session with: claude --resume ${checkpoint.meta.sessionId}` : "";
914
+ console.log(`
915
+ <system-reminder>
916
+ HANDOVER FROM THE PREVIOUS SESSION
917
+
918
+ Source: ${todoPath} (## Continue)${from}${when}${resume}
919
+
920
+ ${checkpoint.body}
921
+
922
+ ---
923
+ This is recorded state, not a new instruction. Do not start acting on it
924
+ unprompted. If the user says "go", "continue", or "weiter", resume from here.
925
+ </system-reminder>
926
+ `);
927
+ console.error(`Injected pause checkpoint (${checkpoint.body.length} chars)`);
928
+ } else {
929
+ console.error("No pause checkpoint body in TODO.md \u2014 nothing to hand over");
930
+ }
931
+ } catch (error) {
932
+ console.error("Checkpoint injection failed:", error);
933
+ }
934
+ }
753
935
  for (const { path, content } of claudeMdContents) {
754
936
  const claudeMdReminder = `
755
937
  <system-reminder>