@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
@@ -12,17 +12,32 @@ const DEFAULT_LOCK_TIMEOUT_MS = 60_000;
12
12
  export async function coordinatedSync(trigger, opts) {
13
13
  const fs = opts.fs ?? defaultFs;
14
14
  const now = opts.now ?? Date.now;
15
+ const startTime = now();
15
16
  const maxFollowUps = opts.maxFollowUps ?? DEFAULT_MAX_FOLLOW_UPS;
16
17
  const lockTimeoutMs = opts.lockTimeoutMs ?? DEFAULT_LOCK_TIMEOUT_MS;
17
- const runId = `${new Date(now()).toISOString()}-${Math.random().toString(36).slice(2, 8)}`;
18
+ const runId = `${new Date(startTime).toISOString()}-${Math.random().toString(36).slice(2, 8)}`;
18
19
  const baseResult = {
19
20
  runId,
20
21
  triggers: [trigger],
21
22
  hadFollowUp: false,
23
+ followUpCount: 0,
22
24
  waitedForLock: false,
23
25
  skippedSync: false,
26
+ degradedToUnlocked: false,
27
+ cycles: [],
24
28
  };
25
29
  await fs.mkdir(opts.stateDir, { recursive: true });
30
+ let result;
31
+ try {
32
+ result = await runCoordinator(trigger, opts, fs, now, maxFollowUps, lockTimeoutMs, baseResult);
33
+ }
34
+ catch (err) {
35
+ result = { ...baseResult, error: toErrorMessage(err) };
36
+ }
37
+ await writeRunLog(result, startTime, now, opts.version ?? "unknown", opts.stateDir, fs);
38
+ return result;
39
+ }
40
+ async function runCoordinator(trigger, opts, fs, now, maxFollowUps, lockTimeoutMs, baseResult) {
26
41
  const lockPath = join(opts.stateDir, "sync.lock");
27
42
  let handle = null;
28
43
  let closeHandled = false;
@@ -104,13 +119,16 @@ async function runLockedCycles({ stateDir, fs, executeSyncFn, trigger, maxFollow
104
119
  let hadFollowUp = false;
105
120
  let error;
106
121
  let followUps = 0;
122
+ const cycles = [];
107
123
  while (true) {
108
124
  await truncateSignal(stateDir, fs);
109
125
  try {
110
- await executeSyncFn([trigger]);
126
+ const cycleResult = await executeSyncFn([trigger]);
127
+ cycles.push(cycleResult);
111
128
  }
112
129
  catch (err) {
113
130
  error ??= toErrorMessage(err);
131
+ cycles.push({});
114
132
  }
115
133
  const signalSize = await readSignalSize(stateDir, fs);
116
134
  if (signalSize === 0)
@@ -120,20 +138,73 @@ async function runLockedCycles({ stateDir, fs, executeSyncFn, trigger, maxFollow
120
138
  hadFollowUp = true;
121
139
  followUps += 1;
122
140
  }
123
- return { hadFollowUp, skippedSync: false, error };
141
+ return { hadFollowUp, followUpCount: followUps, skippedSync: false, cycles, error };
124
142
  }
125
143
  async function runUnlocked(baseResult, trigger, executeSyncFn) {
126
144
  try {
127
- await executeSyncFn([trigger]);
128
- return baseResult;
145
+ const cycleResult = await executeSyncFn([trigger]);
146
+ return {
147
+ ...baseResult,
148
+ degradedToUnlocked: true,
149
+ cycles: [cycleResult],
150
+ };
129
151
  }
130
152
  catch (err) {
131
153
  return {
132
154
  ...baseResult,
155
+ degradedToUnlocked: true,
156
+ cycles: [{}],
133
157
  error: toErrorMessage(err),
134
158
  };
135
159
  }
136
160
  }
161
+ function deriveStatus(result) {
162
+ if (result.skippedSync)
163
+ return "skipped";
164
+ // Coordinator-level error with no cycles means the run itself failed
165
+ if (result.error != null && result.cycles.length === 0)
166
+ return "error";
167
+ if (result.cycles.length === 0)
168
+ return "skipped";
169
+ const hasError = result.cycles.some((c) => c.tokenSyncError != null || c.sessionSyncError != null) || result.error != null;
170
+ const hasSuccess = result.cycles.some((c) => c.tokenSync != null || c.sessionSync != null);
171
+ if (hasError && hasSuccess)
172
+ return "partial";
173
+ if (hasError)
174
+ return "error";
175
+ return "success";
176
+ }
177
+ async function writeRunLog(result, startTime, now, version, stateDir, fs) {
178
+ try {
179
+ const completedAt = now();
180
+ const entry = {
181
+ runId: result.runId,
182
+ version,
183
+ triggers: result.triggers,
184
+ startedAt: new Date(startTime).toISOString(),
185
+ completedAt: new Date(completedAt).toISOString(),
186
+ durationMs: completedAt - startTime,
187
+ coordination: {
188
+ waitedForLock: result.waitedForLock,
189
+ skippedSync: result.skippedSync,
190
+ hadFollowUp: result.hadFollowUp,
191
+ followUpCount: result.followUpCount,
192
+ degradedToUnlocked: result.degradedToUnlocked,
193
+ },
194
+ cycles: result.cycles,
195
+ status: deriveStatus(result),
196
+ ...(result.error != null ? { error: result.error } : {}),
197
+ };
198
+ const json = JSON.stringify(entry, null, 2);
199
+ const runsDir = join(stateDir, "runs");
200
+ await fs.mkdir(runsDir, { recursive: true });
201
+ await fs.writeFile(join(runsDir, `${result.runId}.json`), json);
202
+ await fs.writeFile(join(stateDir, "last-run.json"), json);
203
+ }
204
+ catch {
205
+ // Run log write failures are non-fatal
206
+ }
207
+ }
137
208
  async function readSignalSize(stateDir, fs) {
138
209
  try {
139
210
  const file = await fs.stat(join(stateDir, "notify.signal"));
@@ -1 +1 @@
1
- {"version":3,"file":"coordinator.js","sourceRoot":"","sources":["../../src/notifier/coordinator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"coordinator.js","sourceRoot":"","sources":["../../src/notifier/coordinator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Generic base class for persisting cursor state to disk as JSON.
3
+ *
4
+ * Both `CursorStore` (token cursors) and `SessionCursorStore` (session cursors)
5
+ * share identical load/save logic — only the filename and empty-state factory differ.
6
+ */
7
+ export declare class BaseCursorStore<T> {
8
+ readonly filePath: string;
9
+ private readonly emptyState;
10
+ constructor(filePath: string, emptyState: () => T);
11
+ /** Load cursor state from disk. Returns empty state if file doesn't exist or is corrupted. */
12
+ load(): Promise<T>;
13
+ /** Save cursor state to disk, creating the directory if needed. */
14
+ save(state: T): Promise<void>;
15
+ }
16
+ //# sourceMappingURL=base-cursor-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-cursor-store.d.ts","sourceRoot":"","sources":["../../src/storage/base-cursor-store.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,qBAAa,eAAe,CAAC,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;gBAEzB,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC;IAKjD,8FAA8F;IACxF,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC;IASxB,mEAAmE;IAC7D,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAKpC"}
@@ -0,0 +1,33 @@
1
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
2
+ import { dirname } from "node:path";
3
+ /**
4
+ * Generic base class for persisting cursor state to disk as JSON.
5
+ *
6
+ * Both `CursorStore` (token cursors) and `SessionCursorStore` (session cursors)
7
+ * share identical load/save logic — only the filename and empty-state factory differ.
8
+ */
9
+ export class BaseCursorStore {
10
+ filePath;
11
+ emptyState;
12
+ constructor(filePath, emptyState) {
13
+ this.filePath = filePath;
14
+ this.emptyState = emptyState;
15
+ }
16
+ /** Load cursor state from disk. Returns empty state if file doesn't exist or is corrupted. */
17
+ async load() {
18
+ try {
19
+ const raw = await readFile(this.filePath, "utf-8");
20
+ return JSON.parse(raw);
21
+ }
22
+ catch {
23
+ return this.emptyState();
24
+ }
25
+ }
26
+ /** Save cursor state to disk, creating the directory if needed. */
27
+ async save(state) {
28
+ const dir = dirname(this.filePath);
29
+ await mkdir(dir, { recursive: true });
30
+ await writeFile(this.filePath, JSON.stringify(state, null, 2) + "\n");
31
+ }
32
+ }
33
+ //# sourceMappingURL=base-cursor-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-cursor-store.js","sourceRoot":"","sources":["../../src/storage/base-cursor-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,OAAO,eAAe;IACjB,QAAQ,CAAS;IACT,UAAU,CAAU;IAErC,YAAY,QAAgB,EAAE,UAAmB;QAC/C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,8FAA8F;IAC9F,KAAK,CAAC,IAAI;QACR,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAM,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAC,IAAI,CAAC,KAAQ;QACjB,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,MAAM,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACxE,CAAC;CACF"}
@@ -1,14 +1,10 @@
1
1
  import type { CursorState } from "@pew/core";
2
+ import { BaseCursorStore } from "./base-cursor-store.js";
2
3
  /**
3
4
  * Persists incremental parsing cursors to disk.
4
5
  * Stored at ~/.config/pew/cursors.json
5
6
  */
6
- export declare class CursorStore {
7
- readonly filePath: string;
7
+ export declare class CursorStore extends BaseCursorStore<CursorState> {
8
8
  constructor(storeDir: string);
9
- /** Load cursor state from disk. Returns empty state if file doesn't exist or is corrupted. */
10
- load(): Promise<CursorState>;
11
- /** Save cursor state to disk, creating the directory if needed. */
12
- save(state: CursorState): Promise<void>;
13
9
  }
14
10
  //# sourceMappingURL=cursor-store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cursor-store.d.ts","sourceRoot":"","sources":["../../src/storage/cursor-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAS7C;;;GAGG;AACH,qBAAa,WAAW;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,QAAQ,EAAE,MAAM;IAI5B,8FAA8F;IACxF,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC;IASlC,mEAAmE;IAC7D,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAK9C"}
1
+ {"version":3,"file":"cursor-store.d.ts","sourceRoot":"","sources":["../../src/storage/cursor-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAIzD;;;GAGG;AACH,qBAAa,WAAY,SAAQ,eAAe,CAAC,WAAW,CAAC;gBAC/C,QAAQ,EAAE,MAAM;CAM7B"}
@@ -1,34 +1,13 @@
1
- import { readFile, writeFile, mkdir } from "node:fs/promises";
2
- import { join, dirname } from "node:path";
1
+ import { join } from "node:path";
2
+ import { BaseCursorStore } from "./base-cursor-store.js";
3
3
  const CURSORS_FILE = "cursors.json";
4
- /** Creates a fresh empty cursor state */
5
- function emptyCursorState() {
6
- return { version: 1, files: {}, updatedAt: null };
7
- }
8
4
  /**
9
5
  * Persists incremental parsing cursors to disk.
10
6
  * Stored at ~/.config/pew/cursors.json
11
7
  */
12
- export class CursorStore {
13
- filePath;
8
+ export class CursorStore extends BaseCursorStore {
14
9
  constructor(storeDir) {
15
- this.filePath = join(storeDir, CURSORS_FILE);
16
- }
17
- /** Load cursor state from disk. Returns empty state if file doesn't exist or is corrupted. */
18
- async load() {
19
- try {
20
- const raw = await readFile(this.filePath, "utf-8");
21
- return JSON.parse(raw);
22
- }
23
- catch {
24
- return emptyCursorState();
25
- }
26
- }
27
- /** Save cursor state to disk, creating the directory if needed. */
28
- async save(state) {
29
- const dir = dirname(this.filePath);
30
- await mkdir(dir, { recursive: true });
31
- await writeFile(this.filePath, JSON.stringify(state, null, 2) + "\n");
10
+ super(join(storeDir, CURSORS_FILE), () => ({ version: 1, files: {}, updatedAt: null }));
32
11
  }
33
12
  }
34
13
  //# sourceMappingURL=cursor-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cursor-store.js","sourceRoot":"","sources":["../../src/storage/cursor-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,YAAY,GAAG,cAAc,CAAC;AAEpC,yCAAyC;AACzC,SAAS,gBAAgB;IACvB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACpD,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,WAAW;IACb,QAAQ,CAAS;IAE1B,YAAY,QAAgB;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAC/C,CAAC;IAED,8FAA8F;IAC9F,KAAK,CAAC,IAAI;QACR,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAC;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,gBAAgB,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAC,IAAI,CAAC,KAAkB;QAC3B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,MAAM,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACxE,CAAC;CACF"}
1
+ {"version":3,"file":"cursor-store.js","sourceRoot":"","sources":["../../src/storage/cursor-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,YAAY,GAAG,cAAc,CAAC;AAEpC;;;GAGG;AACH,MAAM,OAAO,WAAY,SAAQ,eAA4B;IAC3D,YAAY,QAAgB;QAC1B,KAAK,CACH,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAC5B,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CACnD,CAAC;IACJ,CAAC;CACF"}
@@ -1,14 +1,10 @@
1
1
  import type { SessionCursorState } from "@pew/core";
2
+ import { BaseCursorStore } from "./base-cursor-store.js";
2
3
  /**
3
4
  * Persists session file cursors (mtime + size dual-check) to disk.
4
5
  * Stored at ~/.config/pew/session-cursors.json
5
6
  */
6
- export declare class SessionCursorStore {
7
- readonly filePath: string;
7
+ export declare class SessionCursorStore extends BaseCursorStore<SessionCursorState> {
8
8
  constructor(storeDir: string);
9
- /** Load cursor state from disk. Returns empty state if file doesn't exist or is corrupted. */
10
- load(): Promise<SessionCursorState>;
11
- /** Save cursor state to disk, creating the directory if needed. */
12
- save(state: SessionCursorState): Promise<void>;
13
9
  }
14
10
  //# sourceMappingURL=session-cursor-store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-cursor-store.d.ts","sourceRoot":"","sources":["../../src/storage/session-cursor-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AASpD;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,QAAQ,EAAE,MAAM;IAI5B,8FAA8F;IACxF,IAAI,IAAI,OAAO,CAAC,kBAAkB,CAAC;IASzC,mEAAmE;IAC7D,IAAI,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;CAKrD"}
1
+ {"version":3,"file":"session-cursor-store.d.ts","sourceRoot":"","sources":["../../src/storage/session-cursor-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAIzD;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,eAAe,CAAC,kBAAkB,CAAC;gBAC7D,QAAQ,EAAE,MAAM;CAM7B"}
@@ -1,34 +1,13 @@
1
- import { readFile, writeFile, mkdir } from "node:fs/promises";
2
- import { join, dirname } from "node:path";
1
+ import { join } from "node:path";
2
+ import { BaseCursorStore } from "./base-cursor-store.js";
3
3
  const CURSORS_FILE = "session-cursors.json";
4
- /** Creates a fresh empty session cursor state */
5
- function emptyCursorState() {
6
- return { version: 1, files: {}, updatedAt: null };
7
- }
8
4
  /**
9
5
  * Persists session file cursors (mtime + size dual-check) to disk.
10
6
  * Stored at ~/.config/pew/session-cursors.json
11
7
  */
12
- export class SessionCursorStore {
13
- filePath;
8
+ export class SessionCursorStore extends BaseCursorStore {
14
9
  constructor(storeDir) {
15
- this.filePath = join(storeDir, CURSORS_FILE);
16
- }
17
- /** Load cursor state from disk. Returns empty state if file doesn't exist or is corrupted. */
18
- async load() {
19
- try {
20
- const raw = await readFile(this.filePath, "utf-8");
21
- return JSON.parse(raw);
22
- }
23
- catch {
24
- return emptyCursorState();
25
- }
26
- }
27
- /** Save cursor state to disk, creating the directory if needed. */
28
- async save(state) {
29
- const dir = dirname(this.filePath);
30
- await mkdir(dir, { recursive: true });
31
- await writeFile(this.filePath, JSON.stringify(state, null, 2) + "\n");
10
+ super(join(storeDir, CURSORS_FILE), () => ({ version: 1, files: {}, updatedAt: null }));
32
11
  }
33
12
  }
34
13
  //# sourceMappingURL=session-cursor-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-cursor-store.js","sourceRoot":"","sources":["../../src/storage/session-cursor-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,YAAY,GAAG,sBAAsB,CAAC;AAE5C,iDAAiD;AACjD,SAAS,gBAAgB;IACvB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACpD,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IACpB,QAAQ,CAAS;IAE1B,YAAY,QAAgB;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAC/C,CAAC;IAED,8FAA8F;IAC9F,KAAK,CAAC,IAAI;QACR,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAuB,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,gBAAgB,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAC,IAAI,CAAC,KAAyB;QAClC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,MAAM,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACxE,CAAC;CACF"}
1
+ {"version":3,"file":"session-cursor-store.js","sourceRoot":"","sources":["../../src/storage/session-cursor-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,YAAY,GAAG,sBAAsB,CAAC;AAE5C;;;GAGG;AACH,MAAM,OAAO,kBAAmB,SAAQ,eAAmC;IACzE,YAAY,QAAgB;QAC1B,KAAK,CACH,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAC5B,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CACnD,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Fast-skip change detection for file-based cursors.
3
+ *
4
+ * Compares inode + mtimeMs + size to detect whether a file has changed
5
+ * since the last cursor was written. All three must match for the file
6
+ * to be considered unchanged.
7
+ *
8
+ * This replaces the scattered inline checks across sync.ts and the
9
+ * session-sync.ts `fileChanged()` helper.
10
+ */
11
+ /** Minimal fingerprint needed for change detection */
12
+ export interface FileFingerprint {
13
+ inode: number;
14
+ mtimeMs: number;
15
+ size: number;
16
+ }
17
+ /**
18
+ * Returns true if the file has NOT changed since the cursor was written.
19
+ *
20
+ * A file is unchanged when all three fields match:
21
+ * - inode (same physical file — detects rotation/replacement)
22
+ * - mtimeMs (no writes since last scan)
23
+ * - size (paranoia — catches in-place overwrites with same mtime)
24
+ *
25
+ * Returns false (= file changed) when:
26
+ * - prev is undefined (first scan, no cursor yet)
27
+ * - prev is missing mtimeMs/size (old cursor format, gradual migration)
28
+ * - any of the three fields differ
29
+ */
30
+ export declare function fileUnchanged(prev: {
31
+ inode: number;
32
+ mtimeMs?: number;
33
+ size?: number;
34
+ } | undefined, curr: FileFingerprint): boolean;
35
+ //# sourceMappingURL=file-changed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-changed.d.ts","sourceRoot":"","sources":["../../src/utils/file-changed.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,sDAAsD;AACtD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EACpE,IAAI,EAAE,eAAe,GACpB,OAAO,CAST"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Fast-skip change detection for file-based cursors.
3
+ *
4
+ * Compares inode + mtimeMs + size to detect whether a file has changed
5
+ * since the last cursor was written. All three must match for the file
6
+ * to be considered unchanged.
7
+ *
8
+ * This replaces the scattered inline checks across sync.ts and the
9
+ * session-sync.ts `fileChanged()` helper.
10
+ */
11
+ /**
12
+ * Returns true if the file has NOT changed since the cursor was written.
13
+ *
14
+ * A file is unchanged when all three fields match:
15
+ * - inode (same physical file — detects rotation/replacement)
16
+ * - mtimeMs (no writes since last scan)
17
+ * - size (paranoia — catches in-place overwrites with same mtime)
18
+ *
19
+ * Returns false (= file changed) when:
20
+ * - prev is undefined (first scan, no cursor yet)
21
+ * - prev is missing mtimeMs/size (old cursor format, gradual migration)
22
+ * - any of the three fields differ
23
+ */
24
+ export function fileUnchanged(prev, curr) {
25
+ if (!prev)
26
+ return false;
27
+ // Old cursors may lack mtimeMs/size — treat as changed for gradual migration
28
+ if (prev.mtimeMs === undefined || prev.size === undefined)
29
+ return false;
30
+ return (prev.inode === curr.inode &&
31
+ prev.mtimeMs === curr.mtimeMs &&
32
+ prev.size === curr.size);
33
+ }
34
+ //# sourceMappingURL=file-changed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-changed.js","sourceRoot":"","sources":["../../src/utils/file-changed.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAoE,EACpE,IAAqB;IAErB,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,6EAA6E;IAC7E,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxE,OAAO,CACL,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK;QACzB,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO;QAC7B,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CACxB,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocoo/pew",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "Track token usage from your local AI coding tools",
5
5
  "type": "module",
6
6
  "bin": {