blun-king-cli 9.1.214 → 9.1.216
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/bin/launcher-runtime.js +25 -6
- package/bin/running-update.cjs +2 -0
- package/bin/validated-learning-signal.cjs +182 -0
- package/blun.mjs +39 -10
- package/package.json +1 -1
package/bin/launcher-runtime.js
CHANGED
|
@@ -30,6 +30,7 @@ const { acquireSharedRuntimeLease, tryAcquireUpdateLease } = require('./update-l
|
|
|
30
30
|
const { compareSemver, runExplicitUpdate, runUpdateNotice } = require('./update-notice');
|
|
31
31
|
const {
|
|
32
32
|
RUNNING_UPDATE_HANDOFF_EXIT_CODE,
|
|
33
|
+
RUNNING_UPDATE_HANDOFF_ACK_MESSAGE,
|
|
33
34
|
RUNNING_UPDATE_HANDOFF_MESSAGE,
|
|
34
35
|
RUNNING_UPDATE_MODE_MESSAGE,
|
|
35
36
|
RUNNING_UPDATE_PREPARED_MESSAGE,
|
|
@@ -397,12 +398,26 @@ async function superviseProtectedCore(args, env, cwd, releaseNotice, options = {
|
|
|
397
398
|
handoffSessionId = message.sessionId;
|
|
398
399
|
handoffMode = runningUpdateMode;
|
|
399
400
|
handoffCwd = resolveHandoffCwd(message.cwd, cwd);
|
|
400
|
-
if (preparedTarget !== undefined) {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
401
|
+
if (preparedTarget !== undefined && message.version === preparedTarget.version) {
|
|
402
|
+
try {
|
|
403
|
+
(options.stageRuntime || stageRuntime)(env.BLUN_SHARED_HOME, preparedTarget, {
|
|
404
|
+
mode: handoffMode,
|
|
405
|
+
sessionId: handoffSessionId,
|
|
406
|
+
cwd: handoffCwd,
|
|
407
|
+
});
|
|
408
|
+
child.send({
|
|
409
|
+
type: RUNNING_UPDATE_HANDOFF_ACK_MESSAGE,
|
|
410
|
+
version: preparedTarget.version,
|
|
411
|
+
mode: handoffMode,
|
|
412
|
+
sessionId: handoffSessionId,
|
|
413
|
+
}, (error) => {
|
|
414
|
+
if (error) options.onRunningUpdateError?.(error);
|
|
415
|
+
});
|
|
416
|
+
} catch (error) {
|
|
417
|
+
handoffSessionId = undefined;
|
|
418
|
+
handoffMode = undefined;
|
|
419
|
+
options.onRunningUpdateError?.(error);
|
|
420
|
+
}
|
|
406
421
|
}
|
|
407
422
|
}
|
|
408
423
|
};
|
|
@@ -471,6 +486,7 @@ async function superviseProtectedCore(args, env, cwd, releaseNotice, options = {
|
|
|
471
486
|
},
|
|
472
487
|
activateTarget: async (target) => {
|
|
473
488
|
await (options.activateRuntime || activateRuntime)(env.BLUN_SHARED_HOME, target);
|
|
489
|
+
(options.clearPendingRuntime || clearPendingRuntime)(env.BLUN_SHARED_HOME, target);
|
|
474
490
|
(options.recordRunningUpdateEvent || recordRunningUpdateEvent)(env.BLUN_SHARED_HOME, {
|
|
475
491
|
event: 'activated',
|
|
476
492
|
fromVersion: readPackageVersionAt(packageRoot),
|
|
@@ -485,6 +501,9 @@ async function superviseProtectedCore(args, env, cwd, releaseNotice, options = {
|
|
|
485
501
|
}
|
|
486
502
|
},
|
|
487
503
|
});
|
|
504
|
+
if (handoff.kind !== 'activated') {
|
|
505
|
+
(options.clearPendingRuntime || clearPendingRuntime)(env.BLUN_SHARED_HOME, preparedTarget);
|
|
506
|
+
}
|
|
488
507
|
const resumed = handoff.core;
|
|
489
508
|
if (resumed === undefined || resumed.ready !== true) return 1;
|
|
490
509
|
const resumedArgs = handoffArgsForMode(args, handoffMode, handoffSessionId);
|
package/bin/running-update.cjs
CHANGED
|
@@ -16,6 +16,7 @@ const REGISTRY_URL = 'https://registry.npmjs.org/blun-king-cli';
|
|
|
16
16
|
const ACTIVE_RUNTIME_FILE = 'active-runtime.json';
|
|
17
17
|
const PENDING_RUNTIME_FILE = 'pending-runtime.json';
|
|
18
18
|
const RUNNING_UPDATE_HANDOFF_EXIT_CODE = 76;
|
|
19
|
+
const RUNNING_UPDATE_HANDOFF_ACK_MESSAGE = 'blun-running-update-handoff-ack';
|
|
19
20
|
const RUNNING_UPDATE_PREPARED_MESSAGE = 'blun-running-update-prepared';
|
|
20
21
|
const RUNNING_UPDATE_HANDOFF_MESSAGE = 'blun-running-update-handoff';
|
|
21
22
|
const RUNNING_UPDATE_MODE_MESSAGE = 'blun-running-update-mode';
|
|
@@ -559,6 +560,7 @@ module.exports = {
|
|
|
559
560
|
PENDING_RUNTIME_FILE,
|
|
560
561
|
AUTO_UPDATE_SETTLE_MS,
|
|
561
562
|
RUNNING_UPDATE_HANDOFF_EXIT_CODE,
|
|
563
|
+
RUNNING_UPDATE_HANDOFF_ACK_MESSAGE,
|
|
562
564
|
RUNNING_UPDATE_HANDOFF_MESSAGE,
|
|
563
565
|
RUNNING_UPDATE_MODE_MESSAGE,
|
|
564
566
|
RUNNING_UPDATE_PREPARED_MESSAGE,
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const crypto = require('node:crypto');
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
|
|
7
|
+
const CANDIDATE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
8
|
+
const SCHEMA_VERSION = 1;
|
|
9
|
+
|
|
3
10
|
const COMMAND_TOOLS = new Set([
|
|
4
11
|
'bash',
|
|
5
12
|
'command',
|
|
@@ -101,7 +108,182 @@ function detectValidatedLearningSignal(history) {
|
|
|
101
108
|
return signal;
|
|
102
109
|
}
|
|
103
110
|
|
|
111
|
+
function profileKey(value) {
|
|
112
|
+
const normalized = typeof value === 'string' ? value.trim() : '';
|
|
113
|
+
return (normalized || 'default').replace(/[^a-z0-9._-]/giu, '_').slice(0, 64);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function candidateDirectory(homeDir, profile) {
|
|
117
|
+
return path.join(
|
|
118
|
+
path.resolve(homeDir),
|
|
119
|
+
'self-improvement',
|
|
120
|
+
'validated-learning',
|
|
121
|
+
profileKey(profile),
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function atomicCreate(filePath, value) {
|
|
126
|
+
fs.mkdirSync(path.dirname(filePath), { mode: 0o700, recursive: true });
|
|
127
|
+
const temporary = `${filePath}.${process.pid}.${crypto.randomBytes(8).toString('hex')}.tmp`;
|
|
128
|
+
fs.writeFileSync(temporary, `${JSON.stringify(value)}\n`, { encoding: 'utf8', mode: 0o600 });
|
|
129
|
+
try {
|
|
130
|
+
fs.linkSync(temporary, filePath);
|
|
131
|
+
return true;
|
|
132
|
+
} catch (error) {
|
|
133
|
+
if (error?.code !== 'EEXIST') throw error;
|
|
134
|
+
return false;
|
|
135
|
+
} finally {
|
|
136
|
+
fs.rmSync(temporary, { force: true });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function statusMarker(filePath, status) {
|
|
141
|
+
return `${filePath}.${status}`;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function readCandidate(filePath) {
|
|
145
|
+
try {
|
|
146
|
+
const candidate = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
147
|
+
for (const status of ['recorded', 'expired']) {
|
|
148
|
+
const markerPath = statusMarker(filePath, status);
|
|
149
|
+
if (!fs.existsSync(markerPath)) continue;
|
|
150
|
+
const marker = JSON.parse(fs.readFileSync(markerPath, 'utf8'));
|
|
151
|
+
return { ...candidate, ...marker, filePath };
|
|
152
|
+
}
|
|
153
|
+
return { ...candidate, filePath };
|
|
154
|
+
} catch {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function readValidatedLearningCandidates(options = {}) {
|
|
160
|
+
const homeDir = typeof options.homeDir === 'string' ? options.homeDir.trim() : '';
|
|
161
|
+
if (!homeDir) return [];
|
|
162
|
+
const directory = candidateDirectory(homeDir, options.profile);
|
|
163
|
+
try {
|
|
164
|
+
return fs.readdirSync(directory, { withFileTypes: true })
|
|
165
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith('.json'))
|
|
166
|
+
.map((entry) => readCandidate(path.join(directory, entry.name)))
|
|
167
|
+
.filter(Boolean)
|
|
168
|
+
.sort((left, right) => Date.parse(left.createdAt) - Date.parse(right.createdAt));
|
|
169
|
+
} catch {
|
|
170
|
+
return [];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function currentTurnHasSuccessfulMistakeRecord(history) {
|
|
175
|
+
const calls = new Set();
|
|
176
|
+
for (const message of currentUserTurn(history)) {
|
|
177
|
+
for (const call of toolCallsFrom(message)) {
|
|
178
|
+
if (typeof call?.id === 'string' && String(call.name).toLowerCase() === 'mistakerecord') {
|
|
179
|
+
calls.add(call.id);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (message?.role === 'tool'
|
|
183
|
+
&& typeof message.toolCallId === 'string'
|
|
184
|
+
&& calls.has(message.toolCallId)
|
|
185
|
+
&& message.isError !== true) {
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function newestPending(candidates) {
|
|
193
|
+
for (let index = candidates.length - 1; index >= 0; index -= 1) {
|
|
194
|
+
if (candidates[index].status === 'pending') return candidates[index];
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function markCandidate(candidate, status, nowIso) {
|
|
200
|
+
if (!candidate?.filePath) return;
|
|
201
|
+
atomicCreate(statusMarker(candidate.filePath, status), {
|
|
202
|
+
resolvedAt: nowIso,
|
|
203
|
+
status,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function createCandidate(signal, options, nowIso) {
|
|
208
|
+
const profile = profileKey(options.profile);
|
|
209
|
+
const commandHash = crypto.createHash('sha256').update(signal.command).digest('hex');
|
|
210
|
+
const digest = crypto.createHash('sha256').update([
|
|
211
|
+
profile,
|
|
212
|
+
commandHash,
|
|
213
|
+
signal.failedToolCallId,
|
|
214
|
+
signal.successfulToolCallId,
|
|
215
|
+
].join('\0')).digest('hex').slice(0, 32);
|
|
216
|
+
const id = `vl-${digest}`;
|
|
217
|
+
const filePath = path.join(candidateDirectory(options.homeDir, profile), `${id}.json`);
|
|
218
|
+
atomicCreate(filePath, {
|
|
219
|
+
schemaVersion: SCHEMA_VERSION,
|
|
220
|
+
id,
|
|
221
|
+
type: 'validated_red_green',
|
|
222
|
+
status: 'pending',
|
|
223
|
+
profile,
|
|
224
|
+
verification: {
|
|
225
|
+
toolName: signal.toolName,
|
|
226
|
+
commandHash,
|
|
227
|
+
},
|
|
228
|
+
evidence: {
|
|
229
|
+
failedToolCallId: signal.failedToolCallId,
|
|
230
|
+
successfulToolCallId: signal.successfulToolCallId,
|
|
231
|
+
},
|
|
232
|
+
createdAt: nowIso,
|
|
233
|
+
});
|
|
234
|
+
return readCandidate(filePath);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function syncValidatedLearningCandidate(history, options = {}) {
|
|
238
|
+
const signal = detectValidatedLearningSignal(history);
|
|
239
|
+
const homeDir = typeof options.homeDir === 'string' ? options.homeDir.trim() : '';
|
|
240
|
+
if (!homeDir) {
|
|
241
|
+
return signal === null ? null : {
|
|
242
|
+
...signal,
|
|
243
|
+
source: 'current_turn',
|
|
244
|
+
status: 'pending',
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const nowMs = (options.now || Date.now)();
|
|
249
|
+
const nowIso = new Date(nowMs).toISOString();
|
|
250
|
+
try {
|
|
251
|
+
let candidates = readValidatedLearningCandidates({
|
|
252
|
+
homeDir,
|
|
253
|
+
profile: options.profile,
|
|
254
|
+
});
|
|
255
|
+
if (currentTurnHasSuccessfulMistakeRecord(history)) {
|
|
256
|
+
markCandidate(newestPending(candidates), 'recorded', nowIso);
|
|
257
|
+
candidates = readValidatedLearningCandidates({ homeDir, profile: options.profile });
|
|
258
|
+
}
|
|
259
|
+
if (signal !== null) {
|
|
260
|
+
return {
|
|
261
|
+
...createCandidate(signal, { homeDir, profile: options.profile }, nowIso),
|
|
262
|
+
source: 'current_turn',
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
for (const candidate of candidates) {
|
|
267
|
+
if (candidate.status !== 'pending') continue;
|
|
268
|
+
if (nowMs - Date.parse(candidate.createdAt) >= CANDIDATE_TTL_MS) {
|
|
269
|
+
markCandidate(candidate, 'expired', nowIso);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
candidates = readValidatedLearningCandidates({ homeDir, profile: options.profile });
|
|
273
|
+
const pending = newestPending(candidates);
|
|
274
|
+
return pending === null ? null : { ...pending, source: 'persisted' };
|
|
275
|
+
} catch {
|
|
276
|
+
return signal === null ? null : {
|
|
277
|
+
...signal,
|
|
278
|
+
source: 'current_turn',
|
|
279
|
+
status: 'pending',
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
104
284
|
module.exports = {
|
|
105
285
|
detectValidatedLearningSignal,
|
|
106
286
|
normalizeCommand,
|
|
287
|
+
readValidatedLearningCandidates,
|
|
288
|
+
syncValidatedLearningCandidate,
|
|
107
289
|
};
|
package/blun.mjs
CHANGED
|
@@ -232147,14 +232147,17 @@ function buildValidatedLearningSignalReminder() {
|
|
|
232147
232147
|
"</validated-learning-signal>"
|
|
232148
232148
|
].join("\n");
|
|
232149
232149
|
}
|
|
232150
|
-
var ValidatedLearningSignalInjector,
|
|
232150
|
+
var ValidatedLearningSignalInjector, syncValidatedLearningCandidate;
|
|
232151
232151
|
var init_validated_learning_signal = __esmMin((() => {
|
|
232152
232152
|
init_injector();
|
|
232153
|
-
({
|
|
232153
|
+
({ syncValidatedLearningCandidate } = createRequire(import.meta.url)("./bin/validated-learning-signal.cjs"));
|
|
232154
232154
|
ValidatedLearningSignalInjector = class extends DynamicInjector {
|
|
232155
232155
|
injectionVariant = "validated_learning_signal";
|
|
232156
232156
|
async inject() {
|
|
232157
|
-
const signal =
|
|
232157
|
+
const signal = syncValidatedLearningCandidate(this.agent.context.history, {
|
|
232158
|
+
homeDir: process.env["BLUN_SHARED_HOME"] ?? process.env["BLUN_HOME"] ?? "",
|
|
232159
|
+
profile: process.env["BLUN_PROFILE"] ?? "default"
|
|
232160
|
+
});
|
|
232158
232161
|
const existing = this.agent.context.history.filter(isValidatedLearningSignalReminder);
|
|
232159
232162
|
if (signal === null) {
|
|
232160
232163
|
if (existing.length > 0) this.agent.context.removeSystemRemindersMatching(isValidatedLearningSignalReminder);
|
|
@@ -502555,7 +502558,10 @@ var ChannelQueueDeadlineController = class {
|
|
|
502555
502558
|
}
|
|
502556
502559
|
requestDeliveryNow() {
|
|
502557
502560
|
if (this.retainReleaseWhileDeliveryIsInFlight()) return;
|
|
502558
|
-
if (this.host.hasWaitingWork() && !this.host.canDeliverWork())
|
|
502561
|
+
if (this.host.hasWaitingWork() && !this.host.canDeliverWork()) {
|
|
502562
|
+
this.scheduleRetry();
|
|
502563
|
+
return;
|
|
502564
|
+
}
|
|
502559
502565
|
this.requestDelivery();
|
|
502560
502566
|
}
|
|
502561
502567
|
retainReleaseWhileDeliveryIsInFlight() {
|
|
@@ -515086,6 +515092,7 @@ function turnsToTrim(turns, maxTurns, hysteresis) {
|
|
|
515086
515092
|
const {
|
|
515087
515093
|
AUTO_UPDATE_SETTLE_MS,
|
|
515088
515094
|
RUNNING_UPDATE_HANDOFF_EXIT_CODE,
|
|
515095
|
+
RUNNING_UPDATE_HANDOFF_ACK_MESSAGE,
|
|
515089
515096
|
RUNNING_UPDATE_HANDOFF_MESSAGE,
|
|
515090
515097
|
RUNNING_UPDATE_MODE_MESSAGE,
|
|
515091
515098
|
RUNNING_UPDATE_PREPARED_MESSAGE,
|
|
@@ -515148,10 +515155,29 @@ function requestRunningUpdateAtSafeBoundary(tui) {
|
|
|
515148
515155
|
}
|
|
515149
515156
|
function installRunningUpdateListener(tui) {
|
|
515150
515157
|
const handler = (message) => {
|
|
515158
|
+
if (message?.type === RUNNING_UPDATE_HANDOFF_ACK_MESSAGE) {
|
|
515159
|
+
if (!tui.runningUpdateHandoffStarted || message.version !== tui.runningUpdatePreparedVersion || message.mode !== tui.runningUpdatePreparedMode || message.sessionId !== tui.getCurrentSessionId()) return;
|
|
515160
|
+
if (!isSafeRuntimeBoundary({
|
|
515161
|
+
isShuttingDown: tui.isShuttingDown,
|
|
515162
|
+
streamingPhase: tui.state.appState.streamingPhase,
|
|
515163
|
+
isCompacting: tui.state.appState.isCompacting,
|
|
515164
|
+
queuedMessages: tui.state.queuedMessages.length,
|
|
515165
|
+
activeToolCalls: tui.streamingUI.hasActiveToolCalls() ? 1 : 0,
|
|
515166
|
+
shellCommands: tui.shellOutputStreams.size,
|
|
515167
|
+
queueCommandRunning: tui.queueCommandRunning
|
|
515168
|
+
})) {
|
|
515169
|
+
tui.runningUpdateHandoffStarted = false;
|
|
515170
|
+
return;
|
|
515171
|
+
}
|
|
515172
|
+
tui.showStatus("Ein Update wird geladen und die TUI wird neu gestartet.", "success");
|
|
515173
|
+
void tui.stop(RUNNING_UPDATE_HANDOFF_EXIT_CODE).catch(() => {
|
|
515174
|
+
tui.runningUpdateHandoffStarted = false;
|
|
515175
|
+
});
|
|
515176
|
+
return;
|
|
515177
|
+
}
|
|
515151
515178
|
if (message?.type !== RUNNING_UPDATE_PREPARED_MESSAGE || typeof message.version !== "string" || message.mode !== RUNNING_UPDATE_MODES.RESUME && message.mode !== RUNNING_UPDATE_MODES.NEW) return;
|
|
515152
515179
|
tui.runningUpdatePreparedVersion = message.version;
|
|
515153
515180
|
tui.runningUpdatePreparedMode = message.mode;
|
|
515154
|
-
tui.showStatus(`Update ${message.version} ist bereit und wird beim nächsten Start aktiviert.`, "success");
|
|
515155
515181
|
requestRunningUpdateAtSafeBoundary(tui);
|
|
515156
515182
|
};
|
|
515157
515183
|
process.on("message", handler);
|
|
@@ -516033,7 +516059,8 @@ var BlunTUI = class {
|
|
|
516033
516059
|
}
|
|
516034
516060
|
canDeliverQueuedChannelHead() {
|
|
516035
516061
|
const item = this.state.queuedMessages[0];
|
|
516036
|
-
|
|
516062
|
+
const hasActiveTurn = this.streamingUI.hasActiveTurn() || (this.state.appState.streamingPhase !== "idle" && this.state.appState.streamingPhase !== "shell");
|
|
516063
|
+
if (this.isShuttingDown || this.queueCommandRunning || this.queueSteerInFlight !== void 0 || this.editorReplacementActive || this.deferUserMessages || this.session === void 0 || this.state.appState.model.trim().length === 0 || !hasActiveTurn || item?.mode !== "channel") return false;
|
|
516037
516064
|
return true;
|
|
516038
516065
|
}
|
|
516039
516066
|
async deliverQueuedChannelHead() {
|
|
@@ -516224,7 +516251,8 @@ var BlunTUI = class {
|
|
|
516224
516251
|
this.scheduleQueueDrain();
|
|
516225
516252
|
}
|
|
516226
516253
|
steerQueueFlushPrefix() {
|
|
516227
|
-
|
|
516254
|
+
const hasActiveTurn = this.streamingUI.hasActiveTurn() || this.state.appState.streamingPhase !== "idle";
|
|
516255
|
+
if (this.queueSteerInFlight !== void 0 || this.queueFlushBatchRemaining === 0 || this.deferUserMessages || this.state.appState.isCompacting || this.state.appState.streamingPhase === "shell" || !hasActiveTurn) return;
|
|
516228
516256
|
const session = this.session;
|
|
516229
516257
|
if (session === void 0 || this.state.appState.model.trim().length === 0) {
|
|
516230
516258
|
this.showError(llmNotSetMessage());
|
|
@@ -516337,7 +516365,7 @@ var BlunTUI = class {
|
|
|
516337
516365
|
channelAcknowledge: acknowledge,
|
|
516338
516366
|
...envelope.meta["image_path"] !== void 0 ? { channelImagePath: envelope.meta["image_path"] } : {}
|
|
516339
516367
|
});
|
|
516340
|
-
this.
|
|
516368
|
+
this.channelQueueDeadline.requestDeliveryNow();
|
|
516341
516369
|
this.scheduleQueueDrain();
|
|
516342
516370
|
this.track("input_queue");
|
|
516343
516371
|
this.updateQueueDisplay();
|
|
@@ -516809,7 +516837,7 @@ var BlunTUI = class {
|
|
|
516809
516837
|
this.sendTelegramRemoteCommandMessage(session, input, options, telegramContext);
|
|
516810
516838
|
return;
|
|
516811
516839
|
}
|
|
516812
|
-
if (this.deferUserMessages || this.state.appState.streamingPhase !== "idle" || this.state.appState.isCompacting) {
|
|
516840
|
+
if (this.deferUserMessages || this.streamingUI.hasActiveTurn() || this.state.appState.streamingPhase !== "idle" || this.state.appState.isCompacting) {
|
|
516813
516841
|
this.enqueueMessage(input, options);
|
|
516814
516842
|
return;
|
|
516815
516843
|
}
|
|
@@ -516820,7 +516848,8 @@ var BlunTUI = class {
|
|
|
516820
516848
|
for (const part of input) this.enqueueMessage(part);
|
|
516821
516849
|
return;
|
|
516822
516850
|
}
|
|
516823
|
-
|
|
516851
|
+
const hasActiveTurn = this.streamingUI.hasActiveTurn() || this.state.appState.streamingPhase !== "idle";
|
|
516852
|
+
if (!hasActiveTurn) {
|
|
516824
516853
|
for (const part of input) this.sendMessageInternal(session, part);
|
|
516825
516854
|
return;
|
|
516826
516855
|
}
|