@nocoo/pew 0.7.0 → 0.9.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 (91) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +30 -1
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/notify.d.ts +7 -2
  5. package/dist/commands/notify.d.ts.map +1 -1
  6. package/dist/commands/notify.js +48 -10
  7. package/dist/commands/notify.js.map +1 -1
  8. package/dist/commands/session-sync.d.ts +12 -0
  9. package/dist/commands/session-sync.d.ts.map +1 -1
  10. package/dist/commands/session-sync.js +99 -311
  11. package/dist/commands/session-sync.js.map +1 -1
  12. package/dist/commands/sync.d.ts.map +1 -1
  13. package/dist/commands/sync.js +112 -330
  14. package/dist/commands/sync.js.map +1 -1
  15. package/dist/drivers/registry.d.ts +63 -0
  16. package/dist/drivers/registry.d.ts.map +1 -0
  17. package/dist/drivers/registry.js +88 -0
  18. package/dist/drivers/registry.js.map +1 -0
  19. package/dist/drivers/session/claude-session-driver.d.ts +10 -0
  20. package/dist/drivers/session/claude-session-driver.d.ts.map +1 -0
  21. package/dist/drivers/session/claude-session-driver.js +29 -0
  22. package/dist/drivers/session/claude-session-driver.js.map +1 -0
  23. package/dist/drivers/session/codex-session-driver.d.ts +10 -0
  24. package/dist/drivers/session/codex-session-driver.d.ts.map +1 -0
  25. package/dist/drivers/session/codex-session-driver.js +29 -0
  26. package/dist/drivers/session/codex-session-driver.js.map +1 -0
  27. package/dist/drivers/session/gemini-session-driver.d.ts +10 -0
  28. package/dist/drivers/session/gemini-session-driver.d.ts.map +1 -0
  29. package/dist/drivers/session/gemini-session-driver.js +29 -0
  30. package/dist/drivers/session/gemini-session-driver.js.map +1 -0
  31. package/dist/drivers/session/openclaw-session-driver.d.ts +10 -0
  32. package/dist/drivers/session/openclaw-session-driver.d.ts.map +1 -0
  33. package/dist/drivers/session/openclaw-session-driver.js +29 -0
  34. package/dist/drivers/session/openclaw-session-driver.js.map +1 -0
  35. package/dist/drivers/session/opencode-json-session-driver.d.ts +14 -0
  36. package/dist/drivers/session/opencode-json-session-driver.d.ts.map +1 -0
  37. package/dist/drivers/session/opencode-json-session-driver.js +51 -0
  38. package/dist/drivers/session/opencode-json-session-driver.js.map +1 -0
  39. package/dist/drivers/session/opencode-sqlite-session-driver.d.ts +23 -0
  40. package/dist/drivers/session/opencode-sqlite-session-driver.d.ts.map +1 -0
  41. package/dist/drivers/session/opencode-sqlite-session-driver.js +88 -0
  42. package/dist/drivers/session/opencode-sqlite-session-driver.js.map +1 -0
  43. package/dist/drivers/token/claude-token-driver.d.ts +11 -0
  44. package/dist/drivers/token/claude-token-driver.d.ts.map +1 -0
  45. package/dist/drivers/token/claude-token-driver.js +42 -0
  46. package/dist/drivers/token/claude-token-driver.js.map +1 -0
  47. package/dist/drivers/token/codex-token-driver.d.ts +11 -0
  48. package/dist/drivers/token/codex-token-driver.d.ts.map +1 -0
  49. package/dist/drivers/token/codex-token-driver.js +59 -0
  50. package/dist/drivers/token/codex-token-driver.js.map +1 -0
  51. package/dist/drivers/token/gemini-token-driver.d.ts +11 -0
  52. package/dist/drivers/token/gemini-token-driver.d.ts.map +1 -0
  53. package/dist/drivers/token/gemini-token-driver.js +57 -0
  54. package/dist/drivers/token/gemini-token-driver.js.map +1 -0
  55. package/dist/drivers/token/openclaw-token-driver.d.ts +11 -0
  56. package/dist/drivers/token/openclaw-token-driver.d.ts.map +1 -0
  57. package/dist/drivers/token/openclaw-token-driver.js +42 -0
  58. package/dist/drivers/token/openclaw-token-driver.js.map +1 -0
  59. package/dist/drivers/token/opencode-json-token-driver.d.ts +15 -0
  60. package/dist/drivers/token/opencode-json-token-driver.d.ts.map +1 -0
  61. package/dist/drivers/token/opencode-json-token-driver.js +73 -0
  62. package/dist/drivers/token/opencode-json-token-driver.js.map +1 -0
  63. package/dist/drivers/token/opencode-sqlite-token-driver.d.ts +25 -0
  64. package/dist/drivers/token/opencode-sqlite-token-driver.d.ts.map +1 -0
  65. package/dist/drivers/token/opencode-sqlite-token-driver.js +99 -0
  66. package/dist/drivers/token/opencode-sqlite-token-driver.js.map +1 -0
  67. package/dist/drivers/types.d.ts +202 -0
  68. package/dist/drivers/types.d.ts.map +1 -0
  69. package/dist/drivers/types.js +12 -0
  70. package/dist/drivers/types.js.map +1 -0
  71. package/dist/notifier/coordinator.d.ts +3 -2
  72. package/dist/notifier/coordinator.d.ts.map +1 -1
  73. package/dist/notifier/coordinator.js +76 -5
  74. package/dist/notifier/coordinator.js.map +1 -1
  75. package/dist/storage/base-cursor-store.d.ts +16 -0
  76. package/dist/storage/base-cursor-store.d.ts.map +1 -0
  77. package/dist/storage/base-cursor-store.js +33 -0
  78. package/dist/storage/base-cursor-store.js.map +1 -0
  79. package/dist/storage/cursor-store.d.ts +2 -6
  80. package/dist/storage/cursor-store.d.ts.map +1 -1
  81. package/dist/storage/cursor-store.js +4 -25
  82. package/dist/storage/cursor-store.js.map +1 -1
  83. package/dist/storage/session-cursor-store.d.ts +2 -6
  84. package/dist/storage/session-cursor-store.d.ts.map +1 -1
  85. package/dist/storage/session-cursor-store.js +4 -25
  86. package/dist/storage/session-cursor-store.js.map +1 -1
  87. package/dist/utils/file-changed.d.ts +35 -0
  88. package/dist/utils/file-changed.d.ts.map +1 -0
  89. package/dist/utils/file-changed.js +34 -0
  90. package/dist/utils/file-changed.js.map +1 -0
  91. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-token-driver.js","sourceRoot":"","sources":["../../../src/drivers/token/codex-token-driver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAkB5D,MAAM,CAAC,MAAM,gBAAgB,GAAiC;IAC5D,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,OAAO;IAEf,KAAK,CAAC,QAAQ,CAAC,IAAkB,EAAE,IAAiB;QAClD,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAAE,OAAO,EAAE,CAAC;QACtC,OAAO,kBAAkB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACnD,CAAC;IAED,UAAU,CAAC,MAA+B,EAAE,WAA4B;QACtE,OAAO,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC5C,CAAC;IAED,WAAW,CAAC,MAA+B,EAAE,WAA4B;QACvE,MAAM,QAAQ,GAAG,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,WAAW,CAAC,KAAK,CAAC;QAC9D,OAAO;YACL,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAChD,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;YACzD,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;SACxD,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAgB,EAAE,MAAmB;QAC/C,MAAM,CAAC,GAAG,MAA0B,CAAC;QACrC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;YAClC,QAAQ;YACR,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,SAAS,EAAE,CAAC,CAAC,SAAS;SACvB,CAAC,CAAC;QACH,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B,CAAC;IACJ,CAAC;IAED,WAAW,CACT,WAA4B,EAC5B,MAAwB,EACxB,KAAmB;QAEnB,MAAM,CAAC,GAAG,MAA0B,CAAC;QACrC,OAAO;YACL,KAAK,EAAE,WAAW,CAAC,KAAK;YACxB,OAAO,EAAE,WAAW,CAAC,OAAO;YAC5B,IAAI,EAAE,WAAW,CAAC,IAAI;YACtB,MAAM,EAAE,CAAC,CAAC,SAAS;YACnB,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Gemini CLI file token driver.
3
+ *
4
+ * Strategy: Array-index JSON parsing with cumulative diff.
5
+ * Skip gate: fileUnchanged() (inode + mtimeMs + size).
6
+ * Parser: parseGeminiFile({ filePath, startIndex, lastTotals })
7
+ */
8
+ import type { GeminiCursor } from "@pew/core";
9
+ import type { FileTokenDriver } from "../types.js";
10
+ export declare const geminiTokenDriver: FileTokenDriver<GeminiCursor>;
11
+ //# sourceMappingURL=gemini-token-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-token-driver.d.ts","sourceRoot":"","sources":["../../../src/drivers/token/gemini-token-driver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,WAAW,CAAC;AAI1D,OAAO,KAAK,EACV,eAAe,EAOhB,MAAM,aAAa,CAAC;AASrB,eAAO,MAAM,iBAAiB,EAAE,eAAe,CAAC,YAAY,CAqD3D,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Gemini CLI file token driver.
3
+ *
4
+ * Strategy: Array-index JSON parsing with cumulative diff.
5
+ * Skip gate: fileUnchanged() (inode + mtimeMs + size).
6
+ * Parser: parseGeminiFile({ filePath, startIndex, lastTotals })
7
+ */
8
+ import { discoverGeminiFiles } from "../../discovery/sources.js";
9
+ import { parseGeminiFile } from "../../parsers/gemini.js";
10
+ import { fileUnchanged } from "../../utils/file-changed.js";
11
+ export const geminiTokenDriver = {
12
+ kind: "file",
13
+ source: "gemini-cli",
14
+ async discover(opts, _ctx) {
15
+ if (!opts.geminiDir)
16
+ return [];
17
+ return discoverGeminiFiles(opts.geminiDir);
18
+ },
19
+ shouldSkip(cursor, fingerprint) {
20
+ return fileUnchanged(cursor, fingerprint);
21
+ },
22
+ resumeState(cursor, fingerprint) {
23
+ const sameFile = cursor && cursor.inode === fingerprint.inode;
24
+ return {
25
+ kind: "array-index",
26
+ startIndex: sameFile ? (cursor.lastIndex ?? -1) : -1,
27
+ lastTotals: sameFile ? (cursor.lastTotals ?? null) : null,
28
+ };
29
+ },
30
+ async parse(filePath, resume) {
31
+ const r = resume;
32
+ const result = await parseGeminiFile({
33
+ filePath,
34
+ startIndex: r.startIndex,
35
+ lastTotals: r.lastTotals,
36
+ });
37
+ return {
38
+ deltas: result.deltas,
39
+ lastIndex: result.lastIndex,
40
+ lastTotals: result.lastTotals,
41
+ lastModel: result.lastModel,
42
+ };
43
+ },
44
+ buildCursor(fingerprint, result, _prev) {
45
+ const r = result;
46
+ return {
47
+ inode: fingerprint.inode,
48
+ mtimeMs: fingerprint.mtimeMs,
49
+ size: fingerprint.size,
50
+ lastIndex: r.lastIndex,
51
+ lastTotals: r.lastTotals,
52
+ lastModel: r.lastModel,
53
+ updatedAt: new Date().toISOString(),
54
+ };
55
+ },
56
+ };
57
+ //# sourceMappingURL=gemini-token-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-token-driver.js","sourceRoot":"","sources":["../../../src/drivers/token/gemini-token-driver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAkB5D,MAAM,CAAC,MAAM,iBAAiB,GAAkC;IAC9D,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,YAAY;IAEpB,KAAK,CAAC,QAAQ,CAAC,IAAkB,EAAE,IAAiB;QAClD,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO,EAAE,CAAC;QAC/B,OAAO,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC;IAED,UAAU,CAAC,MAAgC,EAAE,WAA4B;QACvE,OAAO,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC5C,CAAC;IAED,WAAW,CAAC,MAAgC,EAAE,WAA4B;QACxE,MAAM,QAAQ,GAAG,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,WAAW,CAAC,KAAK,CAAC;QAC9D,OAAO;YACL,IAAI,EAAE,aAAa;YACnB,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpD,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;SAC1D,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAgB,EAAE,MAAmB;QAC/C,MAAM,CAAC,GAAG,MAA+B,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC;YACnC,QAAQ;YACR,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,UAAU,EAAE,CAAC,CAAC,UAAU;SACzB,CAAC,CAAC;QACH,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B,CAAC;IACJ,CAAC;IAED,WAAW,CACT,WAA4B,EAC5B,MAAwB,EACxB,KAAoB;QAEpB,MAAM,CAAC,GAAG,MAA2B,CAAC;QACtC,OAAO;YACL,KAAK,EAAE,WAAW,CAAC,KAAK;YACxB,OAAO,EAAE,WAAW,CAAC,OAAO;YAC5B,IAAI,EAAE,WAAW,CAAC,IAAI;YACtB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * OpenClaw file token driver.
3
+ *
4
+ * Strategy: Byte-offset JSONL streaming.
5
+ * Skip gate: fileUnchanged() (inode + mtimeMs + size).
6
+ * Parser: parseOpenClawFile({ filePath, startOffset })
7
+ */
8
+ import type { ByteOffsetCursor } from "@pew/core";
9
+ import type { FileTokenDriver } from "../types.js";
10
+ export declare const openClawTokenDriver: FileTokenDriver<ByteOffsetCursor>;
11
+ //# sourceMappingURL=openclaw-token-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-token-driver.d.ts","sourceRoot":"","sources":["../../../src/drivers/token/openclaw-token-driver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAIlD,OAAO,KAAK,EACV,eAAe,EAOhB,MAAM,aAAa,CAAC;AAOrB,eAAO,MAAM,mBAAmB,EAAE,eAAe,CAAC,gBAAgB,CAuCjE,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * OpenClaw file token driver.
3
+ *
4
+ * Strategy: Byte-offset JSONL streaming.
5
+ * Skip gate: fileUnchanged() (inode + mtimeMs + size).
6
+ * Parser: parseOpenClawFile({ filePath, startOffset })
7
+ */
8
+ import { discoverOpenClawFiles } from "../../discovery/sources.js";
9
+ import { parseOpenClawFile } from "../../parsers/openclaw.js";
10
+ import { fileUnchanged } from "../../utils/file-changed.js";
11
+ export const openClawTokenDriver = {
12
+ kind: "file",
13
+ source: "openclaw",
14
+ async discover(opts, _ctx) {
15
+ if (!opts.openclawDir)
16
+ return [];
17
+ return discoverOpenClawFiles(opts.openclawDir);
18
+ },
19
+ shouldSkip(cursor, fingerprint) {
20
+ return fileUnchanged(cursor, fingerprint);
21
+ },
22
+ resumeState(cursor, fingerprint) {
23
+ const startOffset = cursor && cursor.inode === fingerprint.inode ? (cursor.offset ?? 0) : 0;
24
+ return { kind: "byte-offset", startOffset };
25
+ },
26
+ async parse(filePath, resume) {
27
+ const r = resume;
28
+ const result = await parseOpenClawFile({ filePath, startOffset: r.startOffset });
29
+ return { deltas: result.deltas, endOffset: result.endOffset };
30
+ },
31
+ buildCursor(fingerprint, result, _prev) {
32
+ const r = result;
33
+ return {
34
+ inode: fingerprint.inode,
35
+ mtimeMs: fingerprint.mtimeMs,
36
+ size: fingerprint.size,
37
+ offset: r.endOffset,
38
+ updatedAt: new Date().toISOString(),
39
+ };
40
+ },
41
+ };
42
+ //# sourceMappingURL=openclaw-token-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-token-driver.js","sourceRoot":"","sources":["../../../src/drivers/token/openclaw-token-driver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAgB5D,MAAM,CAAC,MAAM,mBAAmB,GAAsC;IACpE,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,UAAU;IAElB,KAAK,CAAC,QAAQ,CAAC,IAAkB,EAAE,IAAiB;QAClD,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO,EAAE,CAAC;QACjC,OAAO,qBAAqB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACjD,CAAC;IAED,UAAU,CAAC,MAAoC,EAAE,WAA4B;QAC3E,OAAO,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC5C,CAAC;IAED,WAAW,CAAC,MAAoC,EAAE,WAA4B;QAC5E,MAAM,WAAW,GACf,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1E,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAgB,EAAE,MAAmB;QAC/C,MAAM,CAAC,GAAG,MAA+B,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QACjF,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;IAChE,CAAC;IAED,WAAW,CACT,WAA4B,EAC5B,MAAwB,EACxB,KAAwB;QAExB,MAAM,CAAC,GAAG,MAA6B,CAAC;QACxC,OAAO;YACL,KAAK,EAAE,WAAW,CAAC,KAAK;YACxB,OAAO,EAAE,WAAW,CAAC,OAAO;YAC5B,IAAI,EAAE,WAAW,CAAC,IAAI;YACtB,MAAM,EAAE,CAAC,CAAC,SAAS;YACnB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * OpenCode JSON file token driver.
3
+ *
4
+ * Strategy: Cumulative diff per-file JSON parsing.
5
+ * Skip gate: fileUnchanged() (inode + mtimeMs + size) — triple-check.
6
+ * Parser: parseOpenCodeFile({ filePath, lastTotals })
7
+ *
8
+ * Special behaviors:
9
+ * - discover() reads/writes ctx.dirMtimes for directory-level skip optimization.
10
+ * - afterAll() deposits messageKeys into ctx for cross-source dedup with SQLite.
11
+ */
12
+ import type { OpenCodeCursor } from "@pew/core";
13
+ import type { FileTokenDriver } from "../types.js";
14
+ export declare const openCodeJsonTokenDriver: FileTokenDriver<OpenCodeCursor>;
15
+ //# sourceMappingURL=opencode-json-token-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-json-token-driver.d.ts","sourceRoot":"","sources":["../../../src/drivers/token/opencode-json-token-driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,cAAc,EAA8B,MAAM,WAAW,CAAC;AAI5E,OAAO,KAAK,EACV,eAAe,EAOhB,MAAM,aAAa,CAAC;AAWrB,eAAO,MAAM,uBAAuB,EAAE,eAAe,CAAC,cAAc,CAmEnE,CAAC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * OpenCode JSON file token driver.
3
+ *
4
+ * Strategy: Cumulative diff per-file JSON parsing.
5
+ * Skip gate: fileUnchanged() (inode + mtimeMs + size) — triple-check.
6
+ * Parser: parseOpenCodeFile({ filePath, lastTotals })
7
+ *
8
+ * Special behaviors:
9
+ * - discover() reads/writes ctx.dirMtimes for directory-level skip optimization.
10
+ * - afterAll() deposits messageKeys into ctx for cross-source dedup with SQLite.
11
+ */
12
+ import { discoverOpenCodeFiles } from "../../discovery/sources.js";
13
+ import { parseOpenCodeFile } from "../../parsers/opencode.js";
14
+ import { fileUnchanged } from "../../utils/file-changed.js";
15
+ /** Internally tracked dirMtimes from latest discovery */
16
+ let lastDirMtimes;
17
+ export const openCodeJsonTokenDriver = {
18
+ kind: "file",
19
+ source: "opencode",
20
+ async discover(opts, ctx) {
21
+ if (!opts.openCodeMessageDir)
22
+ return [];
23
+ const discovery = await discoverOpenCodeFiles(opts.openCodeMessageDir, ctx.dirMtimes);
24
+ // Store dirMtimes back into context for orchestrator persistence
25
+ ctx.dirMtimes = discovery.dirMtimes;
26
+ lastDirMtimes = discovery.dirMtimes;
27
+ return discovery.files;
28
+ },
29
+ shouldSkip(cursor, fingerprint) {
30
+ return fileUnchanged(cursor, fingerprint);
31
+ },
32
+ resumeState(cursor, fingerprint) {
33
+ const sameFile = cursor && cursor.inode === fingerprint.inode;
34
+ return {
35
+ kind: "opencode-json",
36
+ lastTotals: sameFile ? (cursor.lastTotals ?? null) : null,
37
+ };
38
+ },
39
+ async parse(filePath, resume) {
40
+ const r = resume;
41
+ const result = await parseOpenCodeFile({ filePath, lastTotals: r.lastTotals });
42
+ return {
43
+ deltas: result.delta ? [result.delta] : [],
44
+ messageKey: result.messageKey,
45
+ lastTotals: result.lastTotals,
46
+ };
47
+ },
48
+ buildCursor(fingerprint, result, _prev) {
49
+ const r = result;
50
+ return {
51
+ inode: fingerprint.inode,
52
+ mtimeMs: fingerprint.mtimeMs,
53
+ size: fingerprint.size,
54
+ lastTotals: r.lastTotals,
55
+ messageKey: r.messageKey,
56
+ updatedAt: new Date().toISOString(),
57
+ };
58
+ },
59
+ afterAll(cursors, ctx) {
60
+ // Deposit messageKeys into context for SQLite dedup
61
+ const keys = new Set();
62
+ for (const cursor of Object.values(cursors)) {
63
+ const oc = cursor;
64
+ if (oc.messageKey) {
65
+ keys.add(oc.messageKey);
66
+ }
67
+ }
68
+ if (keys.size > 0) {
69
+ ctx.messageKeys = keys;
70
+ }
71
+ },
72
+ };
73
+ //# sourceMappingURL=opencode-json-token-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-json-token-driver.js","sourceRoot":"","sources":["../../../src/drivers/token/opencode-json-token-driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAiB5D,yDAAyD;AACzD,IAAI,aAAiD,CAAC;AAEtD,MAAM,CAAC,MAAM,uBAAuB,GAAoC;IACtE,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,UAAU;IAElB,KAAK,CAAC,QAAQ,CAAC,IAAkB,EAAE,GAAgB;QACjD,IAAI,CAAC,IAAI,CAAC,kBAAkB;YAAE,OAAO,EAAE,CAAC;QACxC,MAAM,SAAS,GAAG,MAAM,qBAAqB,CAC3C,IAAI,CAAC,kBAAkB,EACvB,GAAG,CAAC,SAAS,CACd,CAAC;QACF,iEAAiE;QACjE,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;QACpC,aAAa,GAAG,SAAS,CAAC,SAAS,CAAC;QACpC,OAAO,SAAS,CAAC,KAAK,CAAC;IACzB,CAAC;IAED,UAAU,CAAC,MAAkC,EAAE,WAA4B;QACzE,OAAO,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC5C,CAAC;IAED,WAAW,CAAC,MAAkC,EAAE,WAA4B;QAC1E,MAAM,QAAQ,GAAG,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,WAAW,CAAC,KAAK,CAAC;QAC9D,OAAO;YACL,IAAI,EAAE,eAAe;YACrB,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;SAC1D,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAgB,EAAE,MAAmB;QAC/C,MAAM,CAAC,GAAG,MAAiC,CAAC;QAC5C,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;QAC/E,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;YAC1C,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC;IACJ,CAAC;IAED,WAAW,CACT,WAA4B,EAC5B,MAAwB,EACxB,KAAsB;QAEtB,MAAM,CAAC,GAAG,MAAiC,CAAC;QAC5C,OAAO;YACL,KAAK,EAAE,WAAW,CAAC,KAAK;YACxB,OAAO,EAAE,WAAW,CAAC,OAAO;YAC5B,IAAI,EAAE,WAAW,CAAC,IAAI;YACtB,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;IACJ,CAAC;IAED,QAAQ,CAAC,OAAuC,EAAE,GAAgB;QAChE,oDAAoD;QACpD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5C,MAAM,EAAE,GAAG,MAAwB,CAAC;YACpC,IAAI,EAAE,CAAC,UAAU,EAAE,CAAC;gBAClB,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAClB,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC;QACzB,CAAC;IACH,CAAC;CACF,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * OpenCode SQLite DB token driver.
3
+ *
4
+ * Strategy: Watermark-based query (WHERE time_created >= ?).
5
+ * Manages its own DB handle lifecycle.
6
+ * Reads ctx.messageKeys for cross-source dedup with OpenCode JSON.
7
+ *
8
+ * This driver requires a factory function (openMessageDb) to be provided
9
+ * via constructor options, since bun:sqlite is not always available.
10
+ */
11
+ import type { OpenCodeSqliteCursor } from "@pew/core";
12
+ import type { QueryMessagesFn } from "../../parsers/opencode-sqlite.js";
13
+ import type { DbTokenDriver } from "../types.js";
14
+ /** Options needed to construct the SQLite token driver */
15
+ export interface OpenCodeSqliteTokenDriverOpts {
16
+ /** Path to the OpenCode SQLite database */
17
+ dbPath: string;
18
+ /** Factory for opening the DB (DI for testability — bun:sqlite not always available) */
19
+ openMessageDb: (dbPath: string) => {
20
+ queryMessages: QueryMessagesFn;
21
+ close: () => void;
22
+ } | null;
23
+ }
24
+ export declare function createOpenCodeSqliteTokenDriver(opts: OpenCodeSqliteTokenDriverOpts): DbTokenDriver<OpenCodeSqliteCursor>;
25
+ //# sourceMappingURL=opencode-sqlite-token-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-sqlite-token-driver.d.ts","sourceRoot":"","sources":["../../../src/drivers/token/opencode-sqlite-token-driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAA8B,MAAM,aAAa,CAAC;AAE7E,0DAA0D;AAC1D,MAAM,WAAW,6BAA6B;IAC5C,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,wFAAwF;IACxF,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK;QAAE,aAAa,EAAE,eAAe,CAAC;QAAC,KAAK,EAAE,MAAM,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;CACjG;AAED,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,6BAA6B,GAClC,aAAa,CAAC,oBAAoB,CAAC,CAmGrC"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * OpenCode SQLite DB token driver.
3
+ *
4
+ * Strategy: Watermark-based query (WHERE time_created >= ?).
5
+ * Manages its own DB handle lifecycle.
6
+ * Reads ctx.messageKeys for cross-source dedup with OpenCode JSON.
7
+ *
8
+ * This driver requires a factory function (openMessageDb) to be provided
9
+ * via constructor options, since bun:sqlite is not always available.
10
+ */
11
+ import { stat } from "node:fs/promises";
12
+ import { processOpenCodeMessages } from "../../parsers/opencode-sqlite.js";
13
+ export function createOpenCodeSqliteTokenDriver(opts) {
14
+ return {
15
+ kind: "db",
16
+ source: "opencode",
17
+ async run(prevCursor, ctx) {
18
+ // Check if DB file exists
19
+ const dbStat = await stat(opts.dbPath).catch(() => null);
20
+ if (!dbStat) {
21
+ return {
22
+ deltas: [],
23
+ cursor: prevCursor ?? {
24
+ lastTimeCreated: 0,
25
+ lastProcessedIds: [],
26
+ lastSessionUpdated: 0,
27
+ inode: 0,
28
+ updatedAt: new Date().toISOString(),
29
+ },
30
+ rowCount: 0,
31
+ };
32
+ }
33
+ const dbInode = dbStat.ino;
34
+ // If inode changed (DB recreated), reset cursor
35
+ const lastTimeCreated = prevCursor && prevCursor.inode === dbInode
36
+ ? prevCursor.lastTimeCreated
37
+ : 0;
38
+ const prevProcessedIds = new Set(prevCursor && prevCursor.inode === dbInode
39
+ ? (prevCursor.lastProcessedIds ?? [])
40
+ : []);
41
+ const handle = opts.openMessageDb(opts.dbPath);
42
+ if (!handle) {
43
+ return {
44
+ deltas: [],
45
+ cursor: prevCursor ?? {
46
+ lastTimeCreated: 0,
47
+ lastProcessedIds: [],
48
+ lastSessionUpdated: 0,
49
+ inode: dbInode,
50
+ updatedAt: new Date().toISOString(),
51
+ },
52
+ rowCount: 0,
53
+ };
54
+ }
55
+ try {
56
+ // Query uses >= to avoid missing same-millisecond rows.
57
+ // We dedup previously-processed IDs from the prior batch.
58
+ const rawRows = handle.queryMessages(lastTimeCreated);
59
+ const rows = prevProcessedIds.size > 0
60
+ ? rawRows.filter((r) => !prevProcessedIds.has(r.id))
61
+ : rawRows;
62
+ // Read messageKeys from context for cross-source dedup.
63
+ // During the overlap window, both JSON and SQLite sources contain
64
+ // the same messages. We skip any SQLite row whose messageKey is
65
+ // already tracked by a JSON file cursor.
66
+ const jsonMessageKeys = ctx.messageKeys ?? new Set();
67
+ const filteredRows = rows.filter((row) => {
68
+ if (row.role !== "assistant")
69
+ return true;
70
+ const key = `${row.session_id}|${row.id}`;
71
+ return !jsonMessageKeys.has(key);
72
+ });
73
+ const result = processOpenCodeMessages(filteredRows);
74
+ // Update cursor — advance past ALL rows (including deduped).
75
+ const maxTime = rawRows.length > 0
76
+ ? rawRows[rawRows.length - 1].time_created
77
+ : lastTimeCreated;
78
+ const idsAtMax = rawRows
79
+ .filter((r) => r.time_created === maxTime)
80
+ .map((r) => r.id);
81
+ return {
82
+ deltas: result.deltas,
83
+ cursor: {
84
+ lastTimeCreated: maxTime,
85
+ lastProcessedIds: idsAtMax,
86
+ lastSessionUpdated: prevCursor?.lastSessionUpdated ?? 0,
87
+ inode: dbInode,
88
+ updatedAt: new Date().toISOString(),
89
+ },
90
+ rowCount: rawRows.length,
91
+ };
92
+ }
93
+ finally {
94
+ handle.close();
95
+ }
96
+ },
97
+ };
98
+ }
99
+ //# sourceMappingURL=opencode-sqlite-token-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-sqlite-token-driver.js","sourceRoot":"","sources":["../../../src/drivers/token/opencode-sqlite-token-driver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Driver interfaces for the unified source driver architecture.
3
+ *
4
+ * Two driver kinds:
5
+ * - File-based: discover → for each file: stat → shouldSkip → resumeState → parse → buildCursor
6
+ * - DB-based: single run() call (manages own DB lifecycle, watermark, dedup)
7
+ *
8
+ * These are CLI-internal contracts — not shared across packages.
9
+ * Parsers and discovery functions are unchanged; drivers are thin wrappers.
10
+ */
11
+ import type { Source, FileCursorBase, SessionSnapshot, SessionFileCursor, TokenDelta } from "@pew/core";
12
+ import type { ParsedDelta } from "../parsers/claude.js";
13
+ import type { FileFingerprint } from "../utils/file-changed.js";
14
+ export type { FileFingerprint } from "../utils/file-changed.js";
15
+ export type { ParsedDelta } from "../parsers/claude.js";
16
+ /**
17
+ * Shared state bag passed to all drivers in a sync run.
18
+ *
19
+ * Drivers may read or write entries. The orchestrator creates the context
20
+ * before the driver loop, passes it to every driver, and persists any
21
+ * state that drivers deposited (e.g. dirMtimes → CursorState).
22
+ *
23
+ * This replaces the previous pattern where sync.ts had hard-coded
24
+ * knowledge of OpenCode internals (messageKey collection, dirMtimes).
25
+ */
26
+ export interface SyncContext {
27
+ /**
28
+ * Message keys deposited by OpenCode JSON token driver.
29
+ * Read by OpenCode SQLite token driver for cross-source dedup.
30
+ */
31
+ messageKeys?: Set<string>;
32
+ /**
33
+ * Directory mtime cache for OpenCode JSON discovery optimization.
34
+ * Read/written by the OpenCode JSON token driver.
35
+ * Persisted to CursorState.dirMtimes by the orchestrator.
36
+ */
37
+ dirMtimes?: Record<string, number>;
38
+ }
39
+ /**
40
+ * Options passed to driver discover() methods.
41
+ *
42
+ * Each driver reads its relevant directory from this bag.
43
+ * Drivers whose directory is absent return [].
44
+ */
45
+ export interface DiscoverOpts {
46
+ claudeDir?: string;
47
+ codexSessionsDir?: string;
48
+ geminiDir?: string;
49
+ openCodeMessageDir?: string;
50
+ openCodeDbPath?: string;
51
+ openclawDir?: string;
52
+ }
53
+ /**
54
+ * Base result from a file token driver's parse() method.
55
+ *
56
+ * The orchestrator only reads `deltas`. Driver-specific state
57
+ * (endOffset, lastTotals, lastModel, etc.) is typed in concrete
58
+ * driver implementations and consumed by buildCursor().
59
+ */
60
+ export interface TokenParseResult {
61
+ deltas: ParsedDelta[];
62
+ }
63
+ /**
64
+ * Resume state for byte-offset JSONL parsers (Claude, OpenClaw, Codex).
65
+ */
66
+ export interface ByteOffsetResumeState {
67
+ readonly kind: "byte-offset";
68
+ startOffset: number;
69
+ }
70
+ /**
71
+ * Resume state for array-index JSON parsers (Gemini).
72
+ */
73
+ export interface ArrayIndexResumeState {
74
+ readonly kind: "array-index";
75
+ startIndex: number;
76
+ lastTotals: TokenDelta | null;
77
+ }
78
+ /**
79
+ * Resume state for OpenCode JSON per-file parser.
80
+ */
81
+ export interface OpenCodeJsonResumeState {
82
+ readonly kind: "opencode-json";
83
+ lastTotals: TokenDelta | null;
84
+ }
85
+ /**
86
+ * Resume state for Codex (byte-offset + cumulative diff state).
87
+ */
88
+ export interface CodexResumeState {
89
+ readonly kind: "codex";
90
+ startOffset: number;
91
+ lastTotals: TokenDelta | null;
92
+ lastModel: string | null;
93
+ }
94
+ /**
95
+ * Union of all resume state variants.
96
+ * Discriminated by `kind` so drivers can narrow safely.
97
+ */
98
+ export type ResumeState = ByteOffsetResumeState | ArrayIndexResumeState | OpenCodeJsonResumeState | CodexResumeState;
99
+ /** Progress callback compatible with both sync and session-sync */
100
+ export type OnProgress = (event: {
101
+ source: string;
102
+ phase: string;
103
+ current?: number;
104
+ total?: number;
105
+ message?: string;
106
+ }) => void;
107
+ /**
108
+ * Token driver for file-based sources.
109
+ *
110
+ * The generic loop is:
111
+ * discover → for each file: stat → shouldSkip → resumeState → parse → buildCursor
112
+ *
113
+ * TCursor is source-specific (ByteOffsetCursor, GeminiCursor, etc.)
114
+ * and must extend FileCursorBase.
115
+ */
116
+ export interface FileTokenDriver<TCursor extends FileCursorBase = FileCursorBase> {
117
+ readonly kind: "file";
118
+ readonly source: Source;
119
+ /** Discover candidate files for this source */
120
+ discover(opts: DiscoverOpts, ctx: SyncContext): Promise<string[]>;
121
+ /** Fast skip: has this file changed since last cursor? Uses fileUnchanged() internally. */
122
+ shouldSkip(cursor: TCursor | undefined, fingerprint: FileFingerprint): boolean;
123
+ /** Extract incremental resume state from cursor (offset, lastIndex, etc.) */
124
+ resumeState(cursor: TCursor | undefined, fingerprint: FileFingerprint): ResumeState;
125
+ /** Parse file from resume point, return deltas + driver-specific state */
126
+ parse(filePath: string, resume: ResumeState): Promise<TokenParseResult>;
127
+ /** Build cursor to persist after successful parse */
128
+ buildCursor(fingerprint: FileFingerprint, result: TokenParseResult, prev?: TCursor): TCursor;
129
+ /**
130
+ * Optional post-parse hook. Called after all files are processed.
131
+ * Used by OpenCode JSON to deposit messageKeys into context.
132
+ */
133
+ afterAll?(cursors: Record<string, FileCursorBase>, ctx: SyncContext): void;
134
+ }
135
+ /**
136
+ * Session driver for file-based sources.
137
+ *
138
+ * TCursor defaults to SessionFileCursor but can be narrowed.
139
+ * OpenCode JSON session driver uses { mtimeMs: number } only
140
+ * (directory scan — size unreliable across filesystems).
141
+ */
142
+ export interface FileSessionDriver<TCursor = SessionFileCursor> {
143
+ readonly kind: "file";
144
+ readonly source: Source;
145
+ /** Discover candidate files/dirs for this source */
146
+ discover(opts: DiscoverOpts): Promise<string[]>;
147
+ /** Fast skip: driver owns comparison logic for its cursor type */
148
+ shouldSkip(cursor: TCursor | undefined, fingerprint: FileFingerprint): boolean;
149
+ /** Full-scan parse, return session snapshots */
150
+ parse(filePath: string): Promise<SessionSnapshot[]>;
151
+ /** Build cursor to persist after successful parse */
152
+ buildCursor(fingerprint: FileFingerprint): TCursor;
153
+ }
154
+ /**
155
+ * Result from a DB token driver's run() method.
156
+ */
157
+ export interface DbTokenResult<TCursor> {
158
+ deltas: ParsedDelta[];
159
+ cursor: TCursor;
160
+ /** Number of raw rows queried (for filesScanned/progress reporting) */
161
+ rowCount: number;
162
+ }
163
+ /**
164
+ * Token driver for DB-query sources (OpenCode SQLite).
165
+ *
166
+ * NOT part of the generic file loop. The orchestrator calls run() directly.
167
+ * The driver manages its own DB handle lifecycle, watermark, and dedup.
168
+ */
169
+ export interface DbTokenDriver<TCursor = unknown> {
170
+ readonly kind: "db";
171
+ readonly source: Source;
172
+ /**
173
+ * Execute the full DB sync cycle:
174
+ * open → query → parse → return results + new cursor.
175
+ *
176
+ * Reads cross-driver state (messageKeys) from ctx for dedup.
177
+ */
178
+ run(prevCursor: TCursor | undefined, ctx: SyncContext): Promise<DbTokenResult<TCursor>>;
179
+ }
180
+ /**
181
+ * Result from a DB session driver's run() method.
182
+ */
183
+ export interface DbSessionResult<TCursor> {
184
+ snapshots: SessionSnapshot[];
185
+ cursor: TCursor;
186
+ /** Number of raw rows queried */
187
+ rowCount: number;
188
+ }
189
+ /**
190
+ * Session driver for DB-query sources (OpenCode SQLite).
191
+ * Same pattern as DbTokenDriver but produces SessionSnapshot[].
192
+ */
193
+ export interface DbSessionDriver<TCursor = unknown> {
194
+ readonly kind: "db";
195
+ readonly source: Source;
196
+ run(prevCursor: TCursor | undefined, ctx: SyncContext): Promise<DbSessionResult<TCursor>>;
197
+ }
198
+ /** Any token driver (file or DB) */
199
+ export type TokenDriver = FileTokenDriver | DbTokenDriver;
200
+ /** Any session driver (file or DB) */
201
+ export type SessionDriver = FileSessionDriver | DbSessionDriver;
202
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/drivers/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Driver interfaces for the unified source driver architecture.
3
+ *
4
+ * Two driver kinds:
5
+ * - File-based: discover → for each file: stat → shouldSkip → resumeState → parse → buildCursor
6
+ * - DB-based: single run() call (manages own DB lifecycle, watermark, dedup)
7
+ *
8
+ * These are CLI-internal contracts — not shared across packages.
9
+ * Parsers and discovery functions are unchanged; drivers are thin wrappers.
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/drivers/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
@@ -1,4 +1,4 @@
1
- import type { CoordinatorRunResult, SyncTrigger } from "@pew/core";
1
+ import type { CoordinatorRunResult, SyncCycleResult, SyncTrigger } from "@pew/core";
2
2
  interface LockHandle {
3
3
  lock?(mode?: string, options?: {
4
4
  nonBlocking?: boolean;
@@ -18,7 +18,8 @@ interface FsOps {
18
18
  }
19
19
  export interface CoordinatorOptions {
20
20
  stateDir: string;
21
- executeSyncFn: (triggers: SyncTrigger[]) => Promise<void>;
21
+ executeSyncFn: (triggers: SyncTrigger[]) => Promise<SyncCycleResult>;
22
+ version?: string;
22
23
  now?: () => number;
23
24
  fs?: FsOps;
24
25
  maxFollowUps?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../../src/notifier/coordinator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAEnE,UAAU,UAAU;IAClB,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,UAAU,KAAK;IACb,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3D,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5E;AAUD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,KAAK,CAAC;IACX,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAKD,wBAAsB,eAAe,CACnC,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,oBAAoB,CAAC,CA6F/B"}
1
+ {"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../../src/notifier/coordinator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAe,eAAe,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAEjG,UAAU,UAAU;IAClB,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,UAAU,KAAK;IACb,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3D,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5E;AAUD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,KAAK,CAAC;IACX,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAKD,wBAAsB,eAAe,CACnC,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,oBAAoB,CAAC,CA4B/B"}