@adhdev/daemon-core 0.9.82-rc.293 → 0.9.82-rc.295
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/index.js +227 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +227 -20
- package/dist/index.mjs.map +1 -1
- package/dist/providers/spec/cli-adapter.d.ts +23 -0
- package/dist/providers/types/interactive-prompt.d.ts +36 -0
- package/package.json +2 -2
- package/src/config/chat-history.ts +255 -10
- package/src/mesh/coordinator-prompt.ts +1 -0
- package/src/providers/cli-provider-instance.ts +36 -14
- package/src/providers/spec/cli-adapter.ts +61 -0
- package/src/providers/types/interactive-prompt.ts +37 -8
package/dist/index.mjs
CHANGED
|
@@ -270,10 +270,10 @@ function readInjected(value) {
|
|
|
270
270
|
}
|
|
271
271
|
function getDaemonBuildInfo() {
|
|
272
272
|
if (cached) return cached;
|
|
273
|
-
const commit = readInjected(true ? "
|
|
274
|
-
const commitShort = readInjected(true ? "
|
|
275
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
276
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
273
|
+
const commit = readInjected(true ? "dc26917ced80beb84689897738b6edb82208c146" : void 0) ?? "unknown";
|
|
274
|
+
const commitShort = readInjected(true ? "dc26917c" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
275
|
+
const version = readInjected(true ? "0.9.82-rc.295" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
276
|
+
const builtAt = readInjected(true ? "2026-06-16T13:44:28.663Z" : void 0);
|
|
277
277
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
278
278
|
return cached;
|
|
279
279
|
}
|
|
@@ -2007,6 +2007,7 @@ function buildRulesSection(coordinatorCliType) {
|
|
|
2007
2007
|
- **Verify via git, not source.** Use \`mesh_git_status\` to confirm side effects. Treat agent summaries as self-reports, not verification.
|
|
2008
2008
|
- **Limit parallelism.** Start with 1\u20132 tasks; scale only on success. Never duplicate a session because \`mesh_read_chat\` shows no final message while tool/terminal activity is ongoing. This caps *concurrent* load \u2014 it does not mean serialize independent work: when a new, independent request arrives and there is headroom under \`maxParallelTasks\`, dispatch it right away rather than waiting for an in-flight task or a user nudge (read-only diagnosis especially, since it has no merge cost).
|
|
2009
2009
|
- **Check history first.** Call \`mesh_task_history\` at session start to avoid duplicate work and inform recovery. On failure, read task history before retrying.
|
|
2010
|
+
- **Sequence shared-base-moving merges.** Parallel dispatch is encouraged, but merging one worktree can advance another in-flight worktree's base \u2014 especially the oss submodule pointer \u2014 turning a clean fast-forward into a diverged rebase (patch-equivalence correctly blocks this). Before merging an in-flight worktree while siblings are also in flight, land in an intentional order, re-clone long-running worktrees from the advanced base, or expect to manually rebase + ff-only the laggards; merging an independent fix mid-flight can strand siblings into a rebase.
|
|
2010
2011
|
- **Converge branches.** After worktree tasks: refine/fast-forward, or classify as \`pushed_feature_branch_needs_merge\` / \`blocked_review\` / \`cleanup_candidate\` / \`not_mergeable\`. Clean up with \`mesh_remove_node\`.
|
|
2011
2012
|
- **Refinery is config-driven.** \`mesh_refine_node\` must run validation from \`.adhdev/refine.{json,yaml,yml}\` or \`repo-mesh.refine.*\`. Heuristics are scaffolding only.
|
|
2012
2013
|
- **Submodule reachability = publish-needed.** \`submodule_reachability_failed\` \u2192 classify as \`blocked_review\`, request user approval to push to submodule main, then rerun \`mesh_refine_node\`.
|
|
@@ -15302,10 +15303,12 @@ function detectClaudeTuiMultiSelect(screenText) {
|
|
|
15302
15303
|
if (/Space to (?:select|toggle)|toggle selection|select multiple|select all that apply/i.test(screenText)) {
|
|
15303
15304
|
return true;
|
|
15304
15305
|
}
|
|
15305
|
-
const optionCheckbox =
|
|
15306
|
+
const optionCheckbox = `(?:\\[[ xX]\\]|[\u2610\u2612\u25FB\u25FC])`;
|
|
15307
|
+
const beforeNumber = new RegExp(`^\\s*(?:[\u276F\u203A>]\\s*)?${optionCheckbox}\\s*\\d+\\.\\s+\\S`);
|
|
15308
|
+
const afterNumber = new RegExp(`^\\s*(?:[\u276F\u203A>]\\s*)?\\d+\\.\\s*${optionCheckbox}\\s+\\S`);
|
|
15306
15309
|
for (const line of screenText.split(/\r?\n/)) {
|
|
15307
15310
|
if (line.includes("\u2714 Submit")) continue;
|
|
15308
|
-
if (
|
|
15311
|
+
if (beforeNumber.test(line) || afterNumber.test(line)) return true;
|
|
15309
15312
|
}
|
|
15310
15313
|
return false;
|
|
15311
15314
|
}
|
|
@@ -15445,6 +15448,16 @@ function parseClaudeInteractiveTuiQuestion(page, index) {
|
|
|
15445
15448
|
...allowFreeform ? { allowFreeform: true } : {}
|
|
15446
15449
|
};
|
|
15447
15450
|
}
|
|
15451
|
+
function readFocusedClaudeTuiQuestion(screenText) {
|
|
15452
|
+
if (!screenText.includes("Enter to select")) return null;
|
|
15453
|
+
const parsed = parseClaudeInteractiveTuiQuestion({ screenText }, 0);
|
|
15454
|
+
if (!parsed) return null;
|
|
15455
|
+
return {
|
|
15456
|
+
question: parsed.question,
|
|
15457
|
+
...parsed.header ? { header: parsed.header } : {},
|
|
15458
|
+
multiSelect: parsed.multiSelect
|
|
15459
|
+
};
|
|
15460
|
+
}
|
|
15448
15461
|
function detectClaudeAskUserQuestionPromptFromTuiPages(pages, options) {
|
|
15449
15462
|
if (pages.length === 0) return null;
|
|
15450
15463
|
const headers = claudeTuiQuestionHeaders(pages[0].screenText);
|
|
@@ -21571,22 +21584,160 @@ function isBoundedTailRequest(limit, offset, excludeRecentCount) {
|
|
|
21571
21584
|
if (!Number.isFinite(numericOffset) || !Number.isFinite(numericExclude)) return false;
|
|
21572
21585
|
return true;
|
|
21573
21586
|
}
|
|
21587
|
+
var REVERSE_TAIL_SMALL_FILE_BYTES = 64 * 1024;
|
|
21588
|
+
var REVERSE_TAIL_CHUNK_BYTES = 64 * 1024;
|
|
21589
|
+
var TAIL_LINES_RETAINED = BOUNDED_TAIL_MAX_LIMIT + 2 * BOUNDED_TAIL_SLACK;
|
|
21590
|
+
var INCREMENTAL_TAIL_CACHE_MAX_ENTRIES = 64;
|
|
21591
|
+
var incrementalTailCache = /* @__PURE__ */ new Map();
|
|
21592
|
+
function evictIncrementalTailCache() {
|
|
21593
|
+
while (incrementalTailCache.size > INCREMENTAL_TAIL_CACHE_MAX_ENTRIES) {
|
|
21594
|
+
const oldest = incrementalTailCache.keys().next().value;
|
|
21595
|
+
if (oldest === void 0) break;
|
|
21596
|
+
incrementalTailCache.delete(oldest);
|
|
21597
|
+
}
|
|
21598
|
+
}
|
|
21599
|
+
function splitBufferLines(buf) {
|
|
21600
|
+
const lines = [];
|
|
21601
|
+
let lineEnd = buf.length;
|
|
21602
|
+
let firstNewline = -1;
|
|
21603
|
+
for (let i = buf.length - 1; i >= 0; i--) {
|
|
21604
|
+
if (buf[i] !== 10) continue;
|
|
21605
|
+
if (i + 1 < lineEnd) {
|
|
21606
|
+
lines.push(buf.toString("utf-8", i + 1, lineEnd));
|
|
21607
|
+
}
|
|
21608
|
+
lineEnd = i;
|
|
21609
|
+
firstNewline = i;
|
|
21610
|
+
}
|
|
21611
|
+
lines.reverse();
|
|
21612
|
+
const head = firstNewline >= 0 ? buf.subarray(0, firstNewline) : buf;
|
|
21613
|
+
return { head, lines };
|
|
21614
|
+
}
|
|
21615
|
+
function readReverseTailLines(filePath, needed) {
|
|
21616
|
+
const fd = fs5.openSync(filePath, "r");
|
|
21617
|
+
try {
|
|
21618
|
+
const stat2 = fs5.fstatSync(fd);
|
|
21619
|
+
const size = stat2.size;
|
|
21620
|
+
let position = size;
|
|
21621
|
+
let carry = Buffer.alloc(0);
|
|
21622
|
+
const collected = [];
|
|
21623
|
+
while (position > 0 && collected.length < needed) {
|
|
21624
|
+
const chunkSize = Math.min(REVERSE_TAIL_CHUNK_BYTES, position);
|
|
21625
|
+
position -= chunkSize;
|
|
21626
|
+
const chunk = Buffer.alloc(chunkSize);
|
|
21627
|
+
fs5.readSync(fd, chunk, 0, chunkSize, position);
|
|
21628
|
+
const combined = carry.length ? Buffer.concat([chunk, carry]) : chunk;
|
|
21629
|
+
const { head, lines } = splitBufferLines(combined);
|
|
21630
|
+
carry = head;
|
|
21631
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
21632
|
+
collected.push(lines[i]);
|
|
21633
|
+
}
|
|
21634
|
+
}
|
|
21635
|
+
const reachedStart = position <= 0;
|
|
21636
|
+
if (reachedStart && carry.length) {
|
|
21637
|
+
collected.push(carry.toString("utf-8"));
|
|
21638
|
+
}
|
|
21639
|
+
collected.reverse();
|
|
21640
|
+
return { lines: collected, coversWholeFile: reachedStart, size, mtimeMs: stat2.mtimeMs };
|
|
21641
|
+
} finally {
|
|
21642
|
+
fs5.closeSync(fd);
|
|
21643
|
+
}
|
|
21644
|
+
}
|
|
21645
|
+
function readFileTailLines(filePath, needed) {
|
|
21646
|
+
let stat2;
|
|
21647
|
+
try {
|
|
21648
|
+
stat2 = fs5.statSync(filePath);
|
|
21649
|
+
} catch {
|
|
21650
|
+
return { lines: [], coversWholeFile: true };
|
|
21651
|
+
}
|
|
21652
|
+
const size = stat2.size;
|
|
21653
|
+
const mtimeMs = stat2.mtimeMs;
|
|
21654
|
+
if (size === 0) {
|
|
21655
|
+
incrementalTailCache.delete(filePath);
|
|
21656
|
+
return { lines: [], coversWholeFile: true };
|
|
21657
|
+
}
|
|
21658
|
+
const cached2 = incrementalTailCache.get(filePath);
|
|
21659
|
+
if (cached2) {
|
|
21660
|
+
if (cached2.size === size && cached2.mtimeMs === mtimeMs) {
|
|
21661
|
+
incrementalTailCache.delete(filePath);
|
|
21662
|
+
incrementalTailCache.set(filePath, cached2);
|
|
21663
|
+
if (cached2.coversWholeFile || cached2.lines.length >= needed) {
|
|
21664
|
+
return { lines: cached2.lines, coversWholeFile: cached2.coversWholeFile };
|
|
21665
|
+
}
|
|
21666
|
+
} else if (size > cached2.size) {
|
|
21667
|
+
const incremental = tryIncrementalTailGrowth(filePath, cached2, size, mtimeMs, needed);
|
|
21668
|
+
if (incremental) return { lines: incremental.lines, coversWholeFile: incremental.coversWholeFile };
|
|
21669
|
+
}
|
|
21670
|
+
incrementalTailCache.delete(filePath);
|
|
21671
|
+
}
|
|
21672
|
+
if (size <= REVERSE_TAIL_SMALL_FILE_BYTES) {
|
|
21673
|
+
let content;
|
|
21674
|
+
try {
|
|
21675
|
+
content = fs5.readFileSync(filePath, "utf-8");
|
|
21676
|
+
} catch {
|
|
21677
|
+
return { lines: [], coversWholeFile: true };
|
|
21678
|
+
}
|
|
21679
|
+
const lines = content.split("\n");
|
|
21680
|
+
if (lines.length && lines[lines.length - 1] === "") lines.pop();
|
|
21681
|
+
storeIncrementalTailCache(filePath, size, mtimeMs, lines, true);
|
|
21682
|
+
return { lines, coversWholeFile: true };
|
|
21683
|
+
}
|
|
21684
|
+
let result;
|
|
21685
|
+
try {
|
|
21686
|
+
result = readReverseTailLines(filePath, needed);
|
|
21687
|
+
} catch {
|
|
21688
|
+
return { lines: [], coversWholeFile: true };
|
|
21689
|
+
}
|
|
21690
|
+
storeIncrementalTailCache(filePath, result.size, result.mtimeMs, result.lines, result.coversWholeFile);
|
|
21691
|
+
return { lines: result.lines, coversWholeFile: result.coversWholeFile };
|
|
21692
|
+
}
|
|
21693
|
+
function tryIncrementalTailGrowth(filePath, cached2, size, mtimeMs, needed) {
|
|
21694
|
+
const fd = fs5.openSync(filePath, "r");
|
|
21695
|
+
try {
|
|
21696
|
+
if (cached2.size > 0) {
|
|
21697
|
+
const boundary = Buffer.alloc(1);
|
|
21698
|
+
fs5.readSync(fd, boundary, 0, 1, cached2.size - 1);
|
|
21699
|
+
if (boundary[0] !== 10) return null;
|
|
21700
|
+
}
|
|
21701
|
+
const appendedLength = size - cached2.size;
|
|
21702
|
+
const appended = Buffer.alloc(appendedLength);
|
|
21703
|
+
fs5.readSync(fd, appended, 0, appendedLength, cached2.size);
|
|
21704
|
+
const newLines = appended.toString("utf-8").split("\n");
|
|
21705
|
+
if (newLines.length && newLines[newLines.length - 1] === "") newLines.pop();
|
|
21706
|
+
const merged = cached2.lines.concat(newLines);
|
|
21707
|
+
const trimmed = merged.length > TAIL_LINES_RETAINED ? merged.slice(merged.length - TAIL_LINES_RETAINED) : merged;
|
|
21708
|
+
const coversWholeFile = cached2.coversWholeFile && trimmed.length === merged.length;
|
|
21709
|
+
storeIncrementalTailCache(filePath, size, mtimeMs, trimmed, coversWholeFile);
|
|
21710
|
+
if (coversWholeFile || trimmed.length >= needed) {
|
|
21711
|
+
return { lines: trimmed, coversWholeFile };
|
|
21712
|
+
}
|
|
21713
|
+
return { lines: trimmed, coversWholeFile };
|
|
21714
|
+
} catch {
|
|
21715
|
+
return null;
|
|
21716
|
+
} finally {
|
|
21717
|
+
fs5.closeSync(fd);
|
|
21718
|
+
}
|
|
21719
|
+
}
|
|
21720
|
+
function storeIncrementalTailCache(filePath, size, mtimeMs, lines, coversWholeFile) {
|
|
21721
|
+
const retained = lines.length > TAIL_LINES_RETAINED ? lines.slice(lines.length - TAIL_LINES_RETAINED) : lines;
|
|
21722
|
+
const covers = coversWholeFile && retained.length === lines.length;
|
|
21723
|
+
incrementalTailCache.delete(filePath);
|
|
21724
|
+
incrementalTailCache.set(filePath, { size, mtimeMs, lines: retained, coversWholeFile: covers });
|
|
21725
|
+
evictIncrementalTailCache();
|
|
21726
|
+
}
|
|
21574
21727
|
function readBoundedTailRecords(agentType, dir, files, needed) {
|
|
21575
21728
|
const collected = [];
|
|
21576
21729
|
const seen = /* @__PURE__ */ new Set();
|
|
21577
21730
|
let readAllFiles = true;
|
|
21578
21731
|
for (let f = 0; f < files.length; f++) {
|
|
21579
21732
|
const filePath = path12.join(dir, files[f]);
|
|
21580
|
-
|
|
21581
|
-
|
|
21582
|
-
|
|
21583
|
-
} catch {
|
|
21584
|
-
continue;
|
|
21585
|
-
}
|
|
21586
|
-
const lines = content.trim().split("\n").filter(Boolean);
|
|
21733
|
+
const remaining = Math.max(0, needed - collected.length);
|
|
21734
|
+
const perFileNeeded = Math.min(needed, remaining + BOUNDED_TAIL_SLACK);
|
|
21735
|
+
const { lines, coversWholeFile } = readFileTailLines(filePath, perFileNeeded);
|
|
21587
21736
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
21737
|
+
const line = lines[i];
|
|
21738
|
+
if (!line) continue;
|
|
21588
21739
|
try {
|
|
21589
|
-
const parsed = JSON.parse(
|
|
21740
|
+
const parsed = JSON.parse(line);
|
|
21590
21741
|
const sanitizedMessage = sanitizeHistoryMessage(agentType, parsed);
|
|
21591
21742
|
if (!sanitizedMessage) continue;
|
|
21592
21743
|
const hash = buildHistoryMessageHash(agentType, sanitizedMessage);
|
|
@@ -21596,6 +21747,10 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
|
|
|
21596
21747
|
} catch {
|
|
21597
21748
|
}
|
|
21598
21749
|
}
|
|
21750
|
+
if (!coversWholeFile) {
|
|
21751
|
+
readAllFiles = false;
|
|
21752
|
+
break;
|
|
21753
|
+
}
|
|
21599
21754
|
if (collected.length >= needed && f < files.length - 1) {
|
|
21600
21755
|
readAllFiles = false;
|
|
21601
21756
|
break;
|
|
@@ -31552,12 +31707,14 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
31552
31707
|
}
|
|
31553
31708
|
this.maybeClearResolvedClaudeTuiPrompt();
|
|
31554
31709
|
this.maybeCaptureClaudeTuiPrompt();
|
|
31710
|
+
this.maybeUpgradeClaudeTuiMultiSelect();
|
|
31555
31711
|
this.statusCallback?.();
|
|
31556
31712
|
return;
|
|
31557
31713
|
case "pty_data":
|
|
31558
31714
|
this.detectInteractivePromptFromPtyChunk(ev.chunk);
|
|
31559
31715
|
this.maybeClearResolvedClaudeTuiPrompt();
|
|
31560
31716
|
this.maybeCaptureClaudeTuiPrompt();
|
|
31717
|
+
this.maybeUpgradeClaudeTuiMultiSelect();
|
|
31561
31718
|
try {
|
|
31562
31719
|
this.ptyDataCallback?.(ev.chunk);
|
|
31563
31720
|
} catch {
|
|
@@ -31706,6 +31863,53 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
31706
31863
|
this.claudeTuiPromptCaptureInFlight = false;
|
|
31707
31864
|
});
|
|
31708
31865
|
}
|
|
31866
|
+
/**
|
|
31867
|
+
* The TUI prompt is captured on the FIRST frame that renders the
|
|
31868
|
+
* "Enter to select" footer. At that instant the option rows' checkbox
|
|
31869
|
+
* column may not have drawn yet, so `detectClaudeTuiMultiSelect` returns
|
|
31870
|
+
* false and the prompt is frozen as single-select — the dashboard then
|
|
31871
|
+
* renders radio buttons even though the picker is multi-select.
|
|
31872
|
+
*
|
|
31873
|
+
* While the same TUI prompt is still on screen, re-check the live snapshot:
|
|
31874
|
+
* if checkbox glyphs have since appeared, promote any single-select
|
|
31875
|
+
* question to multi-select and re-emit status. Promotion is one-way
|
|
31876
|
+
* (false→true only) — once a question is known multi-select we never demote
|
|
31877
|
+
* it, since the glyph column can scroll out of view on later frames.
|
|
31878
|
+
*
|
|
31879
|
+
* For MULTI-question prompts the per-page Tab capture is the actual source
|
|
31880
|
+
* of the bug: pages 2..N are snapshotted ~120ms after the Tab keypress,
|
|
31881
|
+
* before their option-row glyph column has redrawn, so those questions
|
|
31882
|
+
* freeze as single-select while page 1 (already settled) is correct. We
|
|
31883
|
+
* cannot upgrade blindly — the live snapshot shows only ONE focused page —
|
|
31884
|
+
* but we CAN read that page's question text/header and upgrade the matching
|
|
31885
|
+
* question. As the user navigates the picker (or it settles), each page is
|
|
31886
|
+
* eventually re-read and repaired.
|
|
31887
|
+
*/
|
|
31888
|
+
maybeUpgradeClaudeTuiMultiSelect() {
|
|
31889
|
+
if (this.cliType !== "claude-cli" || this.interactivePromptTransport !== "tui" || !this.activeInteractivePrompt) return;
|
|
31890
|
+
const questions = this.activeInteractivePrompt.questions;
|
|
31891
|
+
if (questions.every((q) => q.multiSelect)) return;
|
|
31892
|
+
let screenText = "";
|
|
31893
|
+
try {
|
|
31894
|
+
screenText = this.driver.snapshot();
|
|
31895
|
+
} catch {
|
|
31896
|
+
return;
|
|
31897
|
+
}
|
|
31898
|
+
if (!screenText.includes("Enter to select")) return;
|
|
31899
|
+
if (questions.length === 1) {
|
|
31900
|
+
if (questions[0].multiSelect) return;
|
|
31901
|
+
if (!detectClaudeTuiMultiSelect(screenText)) return;
|
|
31902
|
+
questions[0].multiSelect = true;
|
|
31903
|
+
this.statusCallback?.();
|
|
31904
|
+
return;
|
|
31905
|
+
}
|
|
31906
|
+
const focused = readFocusedClaudeTuiQuestion(screenText);
|
|
31907
|
+
if (!focused || !focused.multiSelect) return;
|
|
31908
|
+
const match = questions.find((q) => focused.header && q.header && q.header === focused.header || q.question === focused.question);
|
|
31909
|
+
if (!match || match.multiSelect) return;
|
|
31910
|
+
match.multiSelect = true;
|
|
31911
|
+
this.statusCallback?.();
|
|
31912
|
+
}
|
|
31709
31913
|
readClaudeTuiHeaders(screenText) {
|
|
31710
31914
|
const navLine = screenText.split(/\r?\n/).find((line) => line.includes("\u2714 Submit") && /[☐☒]/.test(line));
|
|
31711
31915
|
if (!navLine) return [];
|
|
@@ -31855,6 +32059,7 @@ function normalizeProviderSessionId(provider, providerSessionId) {
|
|
|
31855
32059
|
}
|
|
31856
32060
|
|
|
31857
32061
|
// src/providers/cli-provider-instance.ts
|
|
32062
|
+
var STATUS_HYDRATION_TAIL_LIMIT = 200;
|
|
31858
32063
|
function isIdleStatus(value) {
|
|
31859
32064
|
const status = typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
31860
32065
|
return !status || status === "idle" || status === "ready";
|
|
@@ -33517,12 +33722,14 @@ ${effect.notification.body || ""}`.trim();
|
|
|
33517
33722
|
const newestMessageAt = parsedMessages.reduce((newest, message) => Math.max(newest, getMessageTime(message)), 0);
|
|
33518
33723
|
return newestMessageAt === 0;
|
|
33519
33724
|
}
|
|
33520
|
-
syncCanonicalSavedHistoryIfNeeded() {
|
|
33725
|
+
syncCanonicalSavedHistoryIfNeeded(options = {}) {
|
|
33521
33726
|
if (!this.providerSessionId) return false;
|
|
33522
33727
|
const canonicalHistory = this.provider.nativeHistory;
|
|
33523
33728
|
if (!canonicalHistory) return false;
|
|
33729
|
+
const limit = options.full ? Number.MAX_SAFE_INTEGER : STATUS_HYDRATION_TAIL_LIMIT;
|
|
33730
|
+
const windowTag = options.full ? "full" : `tail:${STATUS_HYDRATION_TAIL_LIMIT}`;
|
|
33524
33731
|
if (isNativeSourceCanonicalHistory(canonicalHistory)) {
|
|
33525
|
-
const cacheKey = [this.type, this.providerSessionId, this.workingDir].join("\0");
|
|
33732
|
+
const cacheKey = [this.type, this.providerSessionId, this.workingDir, windowTag].join("\0");
|
|
33526
33733
|
const now = Date.now();
|
|
33527
33734
|
if (cacheKey === this.lastNativeSourceCanonicalCacheKey && now - this.lastNativeSourceCanonicalCheckAt < 2e3) {
|
|
33528
33735
|
return true;
|
|
@@ -33534,7 +33741,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
33534
33741
|
historySessionId: this.providerSessionId,
|
|
33535
33742
|
workspace: this.workingDir,
|
|
33536
33743
|
offset: 0,
|
|
33537
|
-
limit
|
|
33744
|
+
limit,
|
|
33538
33745
|
historyBehavior: this.provider.historyBehavior,
|
|
33539
33746
|
scripts: this.provider.scripts
|
|
33540
33747
|
});
|
|
@@ -33550,7 +33757,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
33550
33757
|
return true;
|
|
33551
33758
|
}
|
|
33552
33759
|
try {
|
|
33553
|
-
const cacheKey = [this.type, this.providerSessionId, this.workingDir, canonicalHistory.mode || "materialized-mirror"].join("\0");
|
|
33760
|
+
const cacheKey = [this.type, this.providerSessionId, this.workingDir, canonicalHistory.mode || "materialized-mirror", windowTag].join("\0");
|
|
33554
33761
|
const now = Date.now();
|
|
33555
33762
|
if (cacheKey === this.lastNativeSourceCanonicalCacheKey && now - this.lastNativeSourceCanonicalCheckAt < 2e3) {
|
|
33556
33763
|
return true;
|
|
@@ -33560,7 +33767,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
33560
33767
|
if (!materializeProviderNativeHistory(this.type, canonicalHistory, this.providerSessionId, this.workingDir, this.provider.scripts)) {
|
|
33561
33768
|
return false;
|
|
33562
33769
|
}
|
|
33563
|
-
const restoredHistory = readChatHistory(this.type, 0,
|
|
33770
|
+
const restoredHistory = readChatHistory(this.type, 0, limit, this.providerSessionId, 0, this.provider.historyBehavior);
|
|
33564
33771
|
this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
|
|
33565
33772
|
role: message.role,
|
|
33566
33773
|
content: message.content,
|
|
@@ -33575,7 +33782,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
33575
33782
|
}
|
|
33576
33783
|
restorePersistedHistoryFromCurrentSession() {
|
|
33577
33784
|
if (!this.providerSessionId) return;
|
|
33578
|
-
this.syncCanonicalSavedHistoryIfNeeded();
|
|
33785
|
+
this.syncCanonicalSavedHistoryIfNeeded({ full: true });
|
|
33579
33786
|
const restoredHistory = isNativeSourceCanonicalHistory(this.provider.nativeHistory) ? readProviderChatHistory(this.type, {
|
|
33580
33787
|
canonicalHistory: this.provider.nativeHistory,
|
|
33581
33788
|
historySessionId: this.providerSessionId,
|