@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.
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +30 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/notify.d.ts +7 -2
- package/dist/commands/notify.d.ts.map +1 -1
- package/dist/commands/notify.js +48 -10
- package/dist/commands/notify.js.map +1 -1
- package/dist/commands/session-sync.d.ts +12 -0
- package/dist/commands/session-sync.d.ts.map +1 -1
- package/dist/commands/session-sync.js +99 -311
- package/dist/commands/session-sync.js.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +112 -330
- package/dist/commands/sync.js.map +1 -1
- package/dist/drivers/registry.d.ts +63 -0
- package/dist/drivers/registry.d.ts.map +1 -0
- package/dist/drivers/registry.js +88 -0
- package/dist/drivers/registry.js.map +1 -0
- package/dist/drivers/session/claude-session-driver.d.ts +10 -0
- package/dist/drivers/session/claude-session-driver.d.ts.map +1 -0
- package/dist/drivers/session/claude-session-driver.js +29 -0
- package/dist/drivers/session/claude-session-driver.js.map +1 -0
- package/dist/drivers/session/codex-session-driver.d.ts +10 -0
- package/dist/drivers/session/codex-session-driver.d.ts.map +1 -0
- package/dist/drivers/session/codex-session-driver.js +29 -0
- package/dist/drivers/session/codex-session-driver.js.map +1 -0
- package/dist/drivers/session/gemini-session-driver.d.ts +10 -0
- package/dist/drivers/session/gemini-session-driver.d.ts.map +1 -0
- package/dist/drivers/session/gemini-session-driver.js +29 -0
- package/dist/drivers/session/gemini-session-driver.js.map +1 -0
- package/dist/drivers/session/openclaw-session-driver.d.ts +10 -0
- package/dist/drivers/session/openclaw-session-driver.d.ts.map +1 -0
- package/dist/drivers/session/openclaw-session-driver.js +29 -0
- package/dist/drivers/session/openclaw-session-driver.js.map +1 -0
- package/dist/drivers/session/opencode-json-session-driver.d.ts +14 -0
- package/dist/drivers/session/opencode-json-session-driver.d.ts.map +1 -0
- package/dist/drivers/session/opencode-json-session-driver.js +51 -0
- package/dist/drivers/session/opencode-json-session-driver.js.map +1 -0
- package/dist/drivers/session/opencode-sqlite-session-driver.d.ts +23 -0
- package/dist/drivers/session/opencode-sqlite-session-driver.d.ts.map +1 -0
- package/dist/drivers/session/opencode-sqlite-session-driver.js +88 -0
- package/dist/drivers/session/opencode-sqlite-session-driver.js.map +1 -0
- package/dist/drivers/token/claude-token-driver.d.ts +11 -0
- package/dist/drivers/token/claude-token-driver.d.ts.map +1 -0
- package/dist/drivers/token/claude-token-driver.js +42 -0
- package/dist/drivers/token/claude-token-driver.js.map +1 -0
- package/dist/drivers/token/codex-token-driver.d.ts +11 -0
- package/dist/drivers/token/codex-token-driver.d.ts.map +1 -0
- package/dist/drivers/token/codex-token-driver.js +59 -0
- package/dist/drivers/token/codex-token-driver.js.map +1 -0
- package/dist/drivers/token/gemini-token-driver.d.ts +11 -0
- package/dist/drivers/token/gemini-token-driver.d.ts.map +1 -0
- package/dist/drivers/token/gemini-token-driver.js +57 -0
- package/dist/drivers/token/gemini-token-driver.js.map +1 -0
- package/dist/drivers/token/openclaw-token-driver.d.ts +11 -0
- package/dist/drivers/token/openclaw-token-driver.d.ts.map +1 -0
- package/dist/drivers/token/openclaw-token-driver.js +42 -0
- package/dist/drivers/token/openclaw-token-driver.js.map +1 -0
- package/dist/drivers/token/opencode-json-token-driver.d.ts +15 -0
- package/dist/drivers/token/opencode-json-token-driver.d.ts.map +1 -0
- package/dist/drivers/token/opencode-json-token-driver.js +73 -0
- package/dist/drivers/token/opencode-json-token-driver.js.map +1 -0
- package/dist/drivers/token/opencode-sqlite-token-driver.d.ts +25 -0
- package/dist/drivers/token/opencode-sqlite-token-driver.d.ts.map +1 -0
- package/dist/drivers/token/opencode-sqlite-token-driver.js +99 -0
- package/dist/drivers/token/opencode-sqlite-token-driver.js.map +1 -0
- package/dist/drivers/types.d.ts +202 -0
- package/dist/drivers/types.d.ts.map +1 -0
- package/dist/drivers/types.js +12 -0
- package/dist/drivers/types.js.map +1 -0
- package/dist/notifier/coordinator.d.ts +3 -2
- package/dist/notifier/coordinator.d.ts.map +1 -1
- package/dist/notifier/coordinator.js +76 -5
- package/dist/notifier/coordinator.js.map +1 -1
- package/dist/storage/base-cursor-store.d.ts +16 -0
- package/dist/storage/base-cursor-store.d.ts.map +1 -0
- package/dist/storage/base-cursor-store.js +33 -0
- package/dist/storage/base-cursor-store.js.map +1 -0
- package/dist/storage/cursor-store.d.ts +2 -6
- package/dist/storage/cursor-store.d.ts.map +1 -1
- package/dist/storage/cursor-store.js +4 -25
- package/dist/storage/cursor-store.js.map +1 -1
- package/dist/storage/session-cursor-store.d.ts +2 -6
- package/dist/storage/session-cursor-store.d.ts.map +1 -1
- package/dist/storage/session-cursor-store.js +4 -25
- package/dist/storage/session-cursor-store.js.map +1 -1
- package/dist/utils/file-changed.d.ts +35 -0
- package/dist/utils/file-changed.d.ts.map +1 -0
- package/dist/utils/file-changed.js +34 -0
- package/dist/utils/file-changed.js.map +1 -0
- 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(
|
|
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
|
|
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":"AAAA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAgBjC,MAAM,SAAS,GAAU;IACvB,IAAI,EAAE,IAAgC;IACtC,IAAI,EAAE,IAAgC;IACtC,UAAU,EAAE,UAA4C;IACxD,SAAS,EAAE,SAA0C;IACrD,KAAK,EAAE,KAAkC;CAC1C,CAAC;
|
|
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":"
|
|
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 {
|
|
2
|
-
import {
|
|
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
|
-
|
|
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,
|
|
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":"
|
|
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 {
|
|
2
|
-
import {
|
|
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
|
-
|
|
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,
|
|
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"}
|