blun-king-cli 9.1.462 → 9.1.463
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.
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function replayWindowStartIndex(records, activeTurnCount, startsTurn) {
|
|
4
|
+
if (
|
|
5
|
+
!Array.isArray(records)
|
|
6
|
+
|| !Number.isSafeInteger(activeTurnCount)
|
|
7
|
+
|| activeTurnCount <= 0
|
|
8
|
+
|| typeof startsTurn !== 'function'
|
|
9
|
+
) {
|
|
10
|
+
return 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let remainingTurns = activeTurnCount;
|
|
14
|
+
for (let index = records.length - 1; index >= 0; index -= 1) {
|
|
15
|
+
if (!startsTurn(records[index])) continue;
|
|
16
|
+
remainingTurns -= 1;
|
|
17
|
+
if (remainingTurns === 0) return index;
|
|
18
|
+
}
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = { replayWindowStartIndex };
|
|
@@ -41,6 +41,7 @@ class SessionScrollbackArchive {
|
|
|
41
41
|
this.loadedChunks = new Map();
|
|
42
42
|
this.lineCount = 0;
|
|
43
43
|
this.loadedExisting = false;
|
|
44
|
+
this.activeTurnCount = undefined;
|
|
44
45
|
|
|
45
46
|
if (reset) {
|
|
46
47
|
this.reset();
|
|
@@ -108,6 +109,21 @@ class SessionScrollbackArchive {
|
|
|
108
109
|
return output;
|
|
109
110
|
}
|
|
110
111
|
|
|
112
|
+
setActiveTurnCount(count) {
|
|
113
|
+
if (!isNonNegativeInteger(count)) return false;
|
|
114
|
+
if (this.activeTurnCount === count) return true;
|
|
115
|
+
const previous = this.activeTurnCount;
|
|
116
|
+
this.activeTurnCount = count;
|
|
117
|
+
try {
|
|
118
|
+
fs.mkdirSync(this.directory, { recursive: true });
|
|
119
|
+
this.writeIndex(this.chunks, this.lineCount);
|
|
120
|
+
return true;
|
|
121
|
+
} catch {
|
|
122
|
+
this.activeTurnCount = previous;
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
111
127
|
reset() {
|
|
112
128
|
try {
|
|
113
129
|
fs.rmSync(this.directory, { recursive: true, force: true });
|
|
@@ -116,6 +132,7 @@ class SessionScrollbackArchive {
|
|
|
116
132
|
this.loadedChunks.clear();
|
|
117
133
|
this.lineCount = 0;
|
|
118
134
|
this.loadedExisting = false;
|
|
135
|
+
this.activeTurnCount = undefined;
|
|
119
136
|
}
|
|
120
137
|
|
|
121
138
|
clear() {
|
|
@@ -165,6 +182,9 @@ class SessionScrollbackArchive {
|
|
|
165
182
|
|
|
166
183
|
this.chunks = chunks;
|
|
167
184
|
this.lineCount = parsed.totalLines;
|
|
185
|
+
this.activeTurnCount = isNonNegativeInteger(parsed.activeTurnCount)
|
|
186
|
+
? parsed.activeTurnCount
|
|
187
|
+
: undefined;
|
|
168
188
|
this.loadedExisting = true;
|
|
169
189
|
} catch {}
|
|
170
190
|
}
|
|
@@ -195,6 +215,9 @@ class SessionScrollbackArchive {
|
|
|
195
215
|
schemaVersion: ARCHIVE_SCHEMA_VERSION,
|
|
196
216
|
totalLines,
|
|
197
217
|
chunks,
|
|
218
|
+
...(isNonNegativeInteger(this.activeTurnCount)
|
|
219
|
+
? { activeTurnCount: this.activeTurnCount }
|
|
220
|
+
: {}),
|
|
198
221
|
}));
|
|
199
222
|
}
|
|
200
223
|
}
|
package/blun.mjs
CHANGED
|
@@ -13,6 +13,7 @@ import compactionModelPolicy from "./bin/compaction-model-policy.cjs";
|
|
|
13
13
|
import agentResumeSnapshot from "./bin/agent-resume-snapshot.cjs";
|
|
14
14
|
import sessionResumeCheckpoint from "./bin/session-resume-checkpoint.cjs";
|
|
15
15
|
import sessionScrollbackArchive from "./bin/session-scrollback-archive.cjs";
|
|
16
|
+
import sessionReplayWindowPolicy from "./bin/session-replay-window-policy.cjs";
|
|
16
17
|
import crypto$1, { createHash, randomBytes, randomInt, randomUUID, timingSafeEqual } from "node:crypto";
|
|
17
18
|
import * as fs$16 from "node:fs";
|
|
18
19
|
import Kt, { accessSync, appendFileSync, chmodSync, closeSync, constants, copyFileSync, createReadStream, createWriteStream, existsSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, promises, readFileSync, readSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
@@ -50,6 +51,7 @@ const { resolveCompactionModelAlias } = compactionModelPolicy;
|
|
|
50
51
|
const { createAgentResumeSnapshot, restoreAgentResumeSnapshot } = agentResumeSnapshot;
|
|
51
52
|
const { loadResumeCheckpoint, writeResumeCheckpoint } = sessionResumeCheckpoint;
|
|
52
53
|
const { SessionScrollbackArchive, sessionScrollbackArchiveDirectory } = sessionScrollbackArchive;
|
|
54
|
+
const { replayWindowStartIndex } = sessionReplayWindowPolicy;
|
|
53
55
|
import { EventEmitter as EventEmitter$1 } from "node:events";
|
|
54
56
|
import { StringDecoder } from "node:string_decoder";
|
|
55
57
|
import co from "node:assert";
|
|
@@ -506116,9 +506118,15 @@ var ScrollbackBuffer = class {
|
|
|
506116
506118
|
get totalLines() {
|
|
506117
506119
|
return this.archive.totalLines + this.snapshotLines.length;
|
|
506118
506120
|
}
|
|
506121
|
+
get activeTurnCount() {
|
|
506122
|
+
return this.archive instanceof SessionScrollbackArchive ? this.archive.activeTurnCount : void 0;
|
|
506123
|
+
}
|
|
506119
506124
|
archiveLines(lines) {
|
|
506120
506125
|
return this.archive.append(lines);
|
|
506121
506126
|
}
|
|
506127
|
+
setActiveTurnCount(count) {
|
|
506128
|
+
return this.archive instanceof SessionScrollbackArchive ? this.archive.setActiveTurnCount(count) : false;
|
|
506129
|
+
}
|
|
506122
506130
|
usePersistentArchive(directory, options) {
|
|
506123
506131
|
this.releaseArchive();
|
|
506124
506132
|
const archive = new SessionScrollbackArchive({
|
|
@@ -506515,12 +506523,17 @@ var ScrollbackController = class {
|
|
|
506515
506523
|
reset: !resumeCheckpointRestored,
|
|
506516
506524
|
reuse: resumeCheckpointRestored
|
|
506517
506525
|
});
|
|
506518
|
-
|
|
506519
|
-
|
|
506526
|
+
const activeTurnCount = resumeCheckpointRestored && loadedExisting && buffer.totalLines > 0 ? buffer.activeTurnCount : void 0;
|
|
506527
|
+
this.suppressReplayArchiveWrites = resumeCheckpointRestored && loadedExisting && activeTurnCount === void 0;
|
|
506528
|
+
return activeTurnCount;
|
|
506520
506529
|
}
|
|
506521
506530
|
finishSessionReplay() {
|
|
506531
|
+
this.persistActiveTurnCount(groupTurns(this.state.transcriptEntries).length);
|
|
506522
506532
|
this.suppressReplayArchiveWrites = false;
|
|
506523
506533
|
}
|
|
506534
|
+
persistActiveTurnCount(count) {
|
|
506535
|
+
this.buffer?.setActiveTurnCount(count);
|
|
506536
|
+
}
|
|
506524
506537
|
archiveComponents(components) {
|
|
506525
506538
|
const buffer = this.buffer;
|
|
506526
506539
|
if (buffer === void 0 || components.length === 0) return components.length === 0;
|
|
@@ -509544,6 +509557,21 @@ function createReplayRenderContext() {
|
|
|
509544
509557
|
suppressNextPlanModeOffNotice: false
|
|
509545
509558
|
};
|
|
509546
509559
|
}
|
|
509560
|
+
function replayRecordStartsVisibleTurn(record) {
|
|
509561
|
+
if (record?.type !== "message" || record.message?.role !== "user") return false;
|
|
509562
|
+
const message = record.message;
|
|
509563
|
+
if (backgroundOrigin(message) !== void 0) return false;
|
|
509564
|
+
if (message.origin?.kind === "hook_result" || message.origin?.kind === "injection") return false;
|
|
509565
|
+
if (message.origin?.kind === "shell_command") return message.origin.phase === "input";
|
|
509566
|
+
if (message.origin?.kind === "cron_job" || message.origin?.kind === "cron_missed") return false;
|
|
509567
|
+
if (isGoalForkClearedSystemReminder(message)) return false;
|
|
509568
|
+
if (goalOutcomeReminderFromSystemMessage(message) !== null) return false;
|
|
509569
|
+
const skill = skillActivationFromOrigin(message.origin);
|
|
509570
|
+
if (skill !== void 0) return message.origin?.kind === "skill_activation" && message.origin.trigger === "user-slash";
|
|
509571
|
+
const pluginCommand = pluginCommandFromOrigin(message.origin);
|
|
509572
|
+
if (pluginCommand !== void 0) return message.origin?.kind === "plugin_command" && message.origin.trigger === "user-slash";
|
|
509573
|
+
return true;
|
|
509574
|
+
}
|
|
509547
509575
|
function replayEntry(context, kind, content, renderMode, extras = {}) {
|
|
509548
509576
|
return {
|
|
509549
509577
|
id: nextTranscriptId(),
|
|
@@ -509810,9 +509838,9 @@ var SessionReplayRenderer = class {
|
|
|
509810
509838
|
this.host.showError(uiText("replay.error.unavailable"));
|
|
509811
509839
|
return false;
|
|
509812
509840
|
}
|
|
509813
|
-
this.host.scrollbackController.prepareSessionReplay(main);
|
|
509841
|
+
const activeTurnCount = this.host.scrollbackController.prepareSessionReplay(main);
|
|
509814
509842
|
this.hydrateSnapshot(main);
|
|
509815
|
-
await this.renderRecords(main);
|
|
509843
|
+
await this.renderRecords(main, activeTurnCount);
|
|
509816
509844
|
this.applyTerminalBackgroundAgentStatuses(main);
|
|
509817
509845
|
this.host.mergeAllTurnSteps();
|
|
509818
509846
|
this.host.requestTranscriptRender();
|
|
@@ -509880,9 +509908,11 @@ var SessionReplayRenderer = class {
|
|
|
509880
509908
|
state.footer.setBackgroundCounts(countActiveBackgroundTasks(sessionEventHandler.backgroundTasks));
|
|
509881
509909
|
state.ui.requestRender();
|
|
509882
509910
|
}
|
|
509883
|
-
async renderRecords(agent) {
|
|
509911
|
+
async renderRecords(agent, activeTurnCount) {
|
|
509884
509912
|
const context = createReplayRenderContext();
|
|
509885
|
-
|
|
509913
|
+
const startIndex = replayWindowStartIndex(agent.replay, activeTurnCount, replayRecordStartsVisibleTurn);
|
|
509914
|
+
for (let recordIndex = startIndex; recordIndex < agent.replay.length; recordIndex++) {
|
|
509915
|
+
const record = agent.replay[recordIndex];
|
|
509886
509916
|
this.renderRecord(context, record);
|
|
509887
509917
|
if (shouldYieldSessionReplay(recordIndex + 1, agent.replay.length)) await yieldSessionReplayControl();
|
|
509888
509918
|
}
|
|
@@ -519134,9 +519164,11 @@ var BlunTUI = class {
|
|
|
519134
519164
|
markTranscriptComponent(component, entry);
|
|
519135
519165
|
this.state.transcriptContainer.addChild(component);
|
|
519136
519166
|
}
|
|
519137
|
-
const
|
|
519167
|
+
const turnBoundary = component !== null && this.isTurnBoundaryComponent(component);
|
|
519168
|
+
const trimmed = turnBoundary ? this.trimTranscriptWindow() : false;
|
|
519138
519169
|
const deferReplayWork = this.state.appState.isReplaying;
|
|
519139
519170
|
const merged = deferReplayWork ? false : this.mergeCurrentTurnSteps();
|
|
519171
|
+
if (turnBoundary && !deferReplayWork) this.scrollbackController.persistActiveTurnCount(groupTurns(this.state.transcriptEntries).length);
|
|
519140
519172
|
if ((component || trimmed || merged) && !deferReplayWork) this.state.ui.requestRender();
|
|
519141
519173
|
}
|
|
519142
519174
|
appendApprovalTranscriptEntry(request, response) {
|