forge-remote 2.2.0 → 2.2.1
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/package.json
CHANGED
|
@@ -44,6 +44,16 @@ const TOOL_RESULT_TRUNCATE_BYTES = 8 * 1024;
|
|
|
44
44
|
// outputs occasionally exceed Firestore limits; truncate with a marker.
|
|
45
45
|
const TEXT_TRUNCATE_BYTES = 64 * 1024;
|
|
46
46
|
|
|
47
|
+
// First-sight backfill cap. When mirroring is enabled on a project that
|
|
48
|
+
// already has a multi-MB session.jsonl on disk (e.g., a long-running
|
|
49
|
+
// conversation), we don't want to dump the entire history into Firestore —
|
|
50
|
+
// that's slow, expensive, and almost certainly not what the user wants.
|
|
51
|
+
// Instead, jump near the end of the file and ingest only the last chunk
|
|
52
|
+
// so the user gets a few hundred recent events for context. New sessions
|
|
53
|
+
// (file size <= the threshold) are processed from byte 0 as normal.
|
|
54
|
+
const INITIAL_BACKFILL_THRESHOLD_BYTES = 256 * 1024;
|
|
55
|
+
const INITIAL_BACKFILL_TAIL_BYTES = 64 * 1024;
|
|
56
|
+
|
|
47
57
|
// File-event types in the .jsonl that aren't user-visible — skip silently.
|
|
48
58
|
const SKIP_TYPES = new Set([
|
|
49
59
|
"queue-operation",
|
|
@@ -353,6 +363,11 @@ async function processFile(absPath) {
|
|
|
353
363
|
offset: 0,
|
|
354
364
|
idleTimer: null,
|
|
355
365
|
sessionDocReady: false,
|
|
366
|
+
// True once we've decided where to start reading. Stays false until
|
|
367
|
+
// the user has opted in AND we've applied the initial-backfill rule
|
|
368
|
+
// below — that way the bootstrap only runs once, on the first real
|
|
369
|
+
// read attempt, not on every "add" event for a non-mirrored project.
|
|
370
|
+
bootstrapped: false,
|
|
356
371
|
};
|
|
357
372
|
fileState.set(absPath, state);
|
|
358
373
|
|
|
@@ -361,6 +376,7 @@ async function processFile(absPath) {
|
|
|
361
376
|
const saved = cursors[absPath];
|
|
362
377
|
if (saved && typeof saved.offset === "number") {
|
|
363
378
|
state.offset = saved.offset;
|
|
379
|
+
state.bootstrapped = true; // saved cursor wins over backfill heuristic
|
|
364
380
|
}
|
|
365
381
|
}
|
|
366
382
|
|
|
@@ -373,6 +389,24 @@ async function processFile(absPath) {
|
|
|
373
389
|
} catch {
|
|
374
390
|
return;
|
|
375
391
|
}
|
|
392
|
+
|
|
393
|
+
// First-sight bootstrap: if we don't have a saved cursor and the file is
|
|
394
|
+
// already larger than the threshold (because Claude has been writing to
|
|
395
|
+
// it before mirroring was enabled), jump close to the end so we ingest
|
|
396
|
+
// only the most recent chunk. Without this, opting in on a long-running
|
|
397
|
+
// session would dump the entire history into Firestore.
|
|
398
|
+
if (!state.bootstrapped) {
|
|
399
|
+
if (stat.size > INITIAL_BACKFILL_THRESHOLD_BYTES) {
|
|
400
|
+
state.offset = stat.size - INITIAL_BACKFILL_TAIL_BYTES;
|
|
401
|
+
log.info(
|
|
402
|
+
`claude-session-watcher: ${state.sessionId.slice(0, 8)} ` +
|
|
403
|
+
`large existing file (${(stat.size / 1024 / 1024).toFixed(1)}MB) — ` +
|
|
404
|
+
`tail-only from byte ${state.offset}`,
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
state.bootstrapped = true;
|
|
408
|
+
}
|
|
409
|
+
|
|
376
410
|
if (stat.size <= state.offset) return;
|
|
377
411
|
|
|
378
412
|
// If the file shrunk (rotation? unlikely for jsonl but possible), reset.
|