blun-king-cli 9.1.213 → 9.1.215
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 +107 -0
- package/blun.mjs +76 -7
- 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,
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const COMMAND_TOOLS = new Set([
|
|
4
|
+
'bash',
|
|
5
|
+
'command',
|
|
6
|
+
'exec_command',
|
|
7
|
+
'shell',
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
const VERIFICATION_COMMAND = /(?:^|(?:&&|\|\||;|\s))(?:(?:node\s+--(?:test|check))|(?:(?:npm|pnpm|yarn)\s+(?:test|(?:run\s+)?(?:test|lint|check|typecheck|build)))|(?:python(?:3)?\s+-m\s+pytest)|(?:pytest)|(?:go\s+test)|(?:cargo\s+test)|(?:dotnet\s+test)|(?:npx\s+)?(?:tsc|eslint|biome\s+check))\b/iu;
|
|
11
|
+
|
|
12
|
+
function isRealUserMessage(message) {
|
|
13
|
+
if (message?.role !== 'user') return false;
|
|
14
|
+
const kind = message.origin?.kind;
|
|
15
|
+
return kind !== 'injection' && kind !== 'compaction_summary' && kind !== 'system_trigger';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function currentUserTurn(history) {
|
|
19
|
+
if (!Array.isArray(history)) return [];
|
|
20
|
+
for (let index = history.length - 1; index >= 0; index -= 1) {
|
|
21
|
+
if (isRealUserMessage(history[index])) return history.slice(index + 1);
|
|
22
|
+
}
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function parseArguments(value) {
|
|
27
|
+
if (value && typeof value === 'object') return value;
|
|
28
|
+
if (typeof value !== 'string') return null;
|
|
29
|
+
try {
|
|
30
|
+
const parsed = JSON.parse(value);
|
|
31
|
+
return parsed && typeof parsed === 'object' ? parsed : null;
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function normalizeCommand(value) {
|
|
38
|
+
return typeof value === 'string' ? value.trim().replace(/\s+/gu, ' ') : '';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function describeVerificationCall(call) {
|
|
42
|
+
const toolName = typeof call?.name === 'string' ? call.name : '';
|
|
43
|
+
if (!COMMAND_TOOLS.has(toolName.toLowerCase())) return null;
|
|
44
|
+
const args = parseArguments(call.arguments);
|
|
45
|
+
const command = normalizeCommand(args?.command ?? args?.cmd);
|
|
46
|
+
if (!command || !VERIFICATION_COMMAND.test(command)) return null;
|
|
47
|
+
return { toolName, command };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function toolCallsFrom(message) {
|
|
51
|
+
if (message?.role !== 'assistant') return [];
|
|
52
|
+
if (Array.isArray(message.toolCalls)) return message.toolCalls;
|
|
53
|
+
if (Array.isArray(message.tool_calls)) return message.tool_calls;
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function detectValidatedLearningSignal(history) {
|
|
58
|
+
const turn = currentUserTurn(history);
|
|
59
|
+
const calls = new Map();
|
|
60
|
+
const failures = new Map();
|
|
61
|
+
let signal = null;
|
|
62
|
+
|
|
63
|
+
for (const message of turn) {
|
|
64
|
+
for (const call of toolCallsFrom(message)) {
|
|
65
|
+
if (typeof call?.id !== 'string') continue;
|
|
66
|
+
const verification = describeVerificationCall(call);
|
|
67
|
+
calls.set(call.id, {
|
|
68
|
+
toolName: typeof call.name === 'string' ? call.name : '',
|
|
69
|
+
verification,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (message?.role !== 'tool' || typeof message.toolCallId !== 'string') continue;
|
|
74
|
+
const call = calls.get(message.toolCallId);
|
|
75
|
+
if (!call) continue;
|
|
76
|
+
|
|
77
|
+
if (call.toolName.toLowerCase() === 'mistakerecord' && message.isError !== true) {
|
|
78
|
+
signal = null;
|
|
79
|
+
failures.clear();
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!call.verification) continue;
|
|
84
|
+
const key = `${call.verification.toolName.toLowerCase()}\0${call.verification.command}`;
|
|
85
|
+
if (message.isError === true) {
|
|
86
|
+
failures.set(key, message.toolCallId);
|
|
87
|
+
signal = null;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const failedToolCallId = failures.get(key);
|
|
92
|
+
if (!failedToolCallId) continue;
|
|
93
|
+
signal = {
|
|
94
|
+
toolName: call.verification.toolName,
|
|
95
|
+
command: call.verification.command,
|
|
96
|
+
failedToolCallId,
|
|
97
|
+
successfulToolCallId: message.toolCallId,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return signal;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = {
|
|
105
|
+
detectValidatedLearningSignal,
|
|
106
|
+
normalizeCommand,
|
|
107
|
+
};
|
package/blun.mjs
CHANGED
|
@@ -232133,6 +232133,47 @@ var init_repeated_assistant_response = __esmMin((() => {
|
|
|
232133
232133
|
};
|
|
232134
232134
|
}));
|
|
232135
232135
|
//#endregion
|
|
232136
|
+
//#region ../../packages/agent-core/src/agent/injection/validated-learning-signal.ts
|
|
232137
|
+
function isValidatedLearningSignalReminder(message) {
|
|
232138
|
+
return message.origin?.kind === "injection" && message.origin.variant === "validated_learning_signal";
|
|
232139
|
+
}
|
|
232140
|
+
function buildValidatedLearningSignalReminder() {
|
|
232141
|
+
return [
|
|
232142
|
+
"<validated-learning-signal>",
|
|
232143
|
+
"The same verification command failed and now succeeds in this user turn.",
|
|
232144
|
+
"Use MistakeRecord only when the red-to-green result exposes a reusable lesson.",
|
|
232145
|
+
"Do not record transient environment failures, raw command output, or a success with no general repetition guard.",
|
|
232146
|
+
"If there is a reusable lesson, record the incorrect assumption, the measured correction, and the concrete condition that would cause it again.",
|
|
232147
|
+
"</validated-learning-signal>"
|
|
232148
|
+
].join("\n");
|
|
232149
|
+
}
|
|
232150
|
+
var ValidatedLearningSignalInjector, detectValidatedLearningSignal;
|
|
232151
|
+
var init_validated_learning_signal = __esmMin((() => {
|
|
232152
|
+
init_injector();
|
|
232153
|
+
({ detectValidatedLearningSignal } = createRequire(import.meta.url)("./bin/validated-learning-signal.cjs"));
|
|
232154
|
+
ValidatedLearningSignalInjector = class extends DynamicInjector {
|
|
232155
|
+
injectionVariant = "validated_learning_signal";
|
|
232156
|
+
async inject() {
|
|
232157
|
+
const signal = detectValidatedLearningSignal(this.agent.context.history);
|
|
232158
|
+
const existing = this.agent.context.history.filter(isValidatedLearningSignalReminder);
|
|
232159
|
+
if (signal === null) {
|
|
232160
|
+
if (existing.length > 0) this.agent.context.removeSystemRemindersMatching(isValidatedLearningSignalReminder);
|
|
232161
|
+
return;
|
|
232162
|
+
}
|
|
232163
|
+
const injection = buildValidatedLearningSignalReminder();
|
|
232164
|
+
const expected = `<system-reminder>\n${injection}\n</system-reminder>`;
|
|
232165
|
+
if (existing.length === 1 && reminderText(existing[0]) === expected) return;
|
|
232166
|
+
this.agent.context.removeSystemRemindersMatching(isValidatedLearningSignalReminder);
|
|
232167
|
+
this.injectedAt = this.agent.context.history.length;
|
|
232168
|
+
this.lastInjection = injection;
|
|
232169
|
+
this.agent.context.appendSystemReminder(injection, {
|
|
232170
|
+
kind: "injection",
|
|
232171
|
+
variant: this.injectionVariant
|
|
232172
|
+
});
|
|
232173
|
+
}
|
|
232174
|
+
};
|
|
232175
|
+
}));
|
|
232176
|
+
//#endregion
|
|
232136
232177
|
//#region ../../packages/agent-core/src/agent/injection/mission-contract-evidence.js
|
|
232137
232178
|
function createEvidenceApi(dependencies) {
|
|
232138
232179
|
"use strict";
|
|
@@ -232932,6 +232973,7 @@ var init_manager$2 = __esmMin((() => {
|
|
|
232932
232973
|
init_plugin_session_start();
|
|
232933
232974
|
init_plan_mode();
|
|
232934
232975
|
init_repeated_assistant_response();
|
|
232976
|
+
init_validated_learning_signal();
|
|
232935
232977
|
init_tool_awareness();
|
|
232936
232978
|
ACTIVE_BACKGROUND_TASK_GUIDANCE = "The conversation was compacted, so the earlier messages that started these background tasks are gone — but the tasks are still running from before. Do not start duplicates. Use TaskOutput to fetch a task’s result, TaskList to list them, TaskUpdate to send additional instructions to a running agent task, and TaskStop to cancel one.";
|
|
232937
232979
|
InjectionManager = class {
|
|
@@ -232948,6 +232990,7 @@ var init_manager$2 = __esmMin((() => {
|
|
|
232948
232990
|
new ToolAwarenessInjector(agent),
|
|
232949
232991
|
new MistakeMdInjector(agent),
|
|
232950
232992
|
new RepeatedAssistantResponseInjector(agent),
|
|
232993
|
+
new ValidatedLearningSignalInjector(agent),
|
|
232951
232994
|
new ActionStyleInjector(agent),
|
|
232952
232995
|
new PlanModeInjector(agent),
|
|
232953
232996
|
new PermissionModeInjector(agent)
|
|
@@ -502512,7 +502555,10 @@ var ChannelQueueDeadlineController = class {
|
|
|
502512
502555
|
}
|
|
502513
502556
|
requestDeliveryNow() {
|
|
502514
502557
|
if (this.retainReleaseWhileDeliveryIsInFlight()) return;
|
|
502515
|
-
if (this.host.hasWaitingWork() && !this.host.canDeliverWork())
|
|
502558
|
+
if (this.host.hasWaitingWork() && !this.host.canDeliverWork()) {
|
|
502559
|
+
this.scheduleRetry();
|
|
502560
|
+
return;
|
|
502561
|
+
}
|
|
502516
502562
|
this.requestDelivery();
|
|
502517
502563
|
}
|
|
502518
502564
|
retainReleaseWhileDeliveryIsInFlight() {
|
|
@@ -515043,6 +515089,7 @@ function turnsToTrim(turns, maxTurns, hysteresis) {
|
|
|
515043
515089
|
const {
|
|
515044
515090
|
AUTO_UPDATE_SETTLE_MS,
|
|
515045
515091
|
RUNNING_UPDATE_HANDOFF_EXIT_CODE,
|
|
515092
|
+
RUNNING_UPDATE_HANDOFF_ACK_MESSAGE,
|
|
515046
515093
|
RUNNING_UPDATE_HANDOFF_MESSAGE,
|
|
515047
515094
|
RUNNING_UPDATE_MODE_MESSAGE,
|
|
515048
515095
|
RUNNING_UPDATE_PREPARED_MESSAGE,
|
|
@@ -515105,10 +515152,29 @@ function requestRunningUpdateAtSafeBoundary(tui) {
|
|
|
515105
515152
|
}
|
|
515106
515153
|
function installRunningUpdateListener(tui) {
|
|
515107
515154
|
const handler = (message) => {
|
|
515155
|
+
if (message?.type === RUNNING_UPDATE_HANDOFF_ACK_MESSAGE) {
|
|
515156
|
+
if (!tui.runningUpdateHandoffStarted || message.version !== tui.runningUpdatePreparedVersion || message.mode !== tui.runningUpdatePreparedMode || message.sessionId !== tui.getCurrentSessionId()) return;
|
|
515157
|
+
if (!isSafeRuntimeBoundary({
|
|
515158
|
+
isShuttingDown: tui.isShuttingDown,
|
|
515159
|
+
streamingPhase: tui.state.appState.streamingPhase,
|
|
515160
|
+
isCompacting: tui.state.appState.isCompacting,
|
|
515161
|
+
queuedMessages: tui.state.queuedMessages.length,
|
|
515162
|
+
activeToolCalls: tui.streamingUI.hasActiveToolCalls() ? 1 : 0,
|
|
515163
|
+
shellCommands: tui.shellOutputStreams.size,
|
|
515164
|
+
queueCommandRunning: tui.queueCommandRunning
|
|
515165
|
+
})) {
|
|
515166
|
+
tui.runningUpdateHandoffStarted = false;
|
|
515167
|
+
return;
|
|
515168
|
+
}
|
|
515169
|
+
tui.showStatus("Ein Update wird geladen und die TUI wird neu gestartet.", "success");
|
|
515170
|
+
void tui.stop(RUNNING_UPDATE_HANDOFF_EXIT_CODE).catch(() => {
|
|
515171
|
+
tui.runningUpdateHandoffStarted = false;
|
|
515172
|
+
});
|
|
515173
|
+
return;
|
|
515174
|
+
}
|
|
515108
515175
|
if (message?.type !== RUNNING_UPDATE_PREPARED_MESSAGE || typeof message.version !== "string" || message.mode !== RUNNING_UPDATE_MODES.RESUME && message.mode !== RUNNING_UPDATE_MODES.NEW) return;
|
|
515109
515176
|
tui.runningUpdatePreparedVersion = message.version;
|
|
515110
515177
|
tui.runningUpdatePreparedMode = message.mode;
|
|
515111
|
-
tui.showStatus(`Update ${message.version} ist bereit und wird beim nächsten Start aktiviert.`, "success");
|
|
515112
515178
|
requestRunningUpdateAtSafeBoundary(tui);
|
|
515113
515179
|
};
|
|
515114
515180
|
process.on("message", handler);
|
|
@@ -515990,7 +516056,8 @@ var BlunTUI = class {
|
|
|
515990
516056
|
}
|
|
515991
516057
|
canDeliverQueuedChannelHead() {
|
|
515992
516058
|
const item = this.state.queuedMessages[0];
|
|
515993
|
-
|
|
516059
|
+
const hasActiveTurn = this.streamingUI.hasActiveTurn() || (this.state.appState.streamingPhase !== "idle" && this.state.appState.streamingPhase !== "shell");
|
|
516060
|
+
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;
|
|
515994
516061
|
return true;
|
|
515995
516062
|
}
|
|
515996
516063
|
async deliverQueuedChannelHead() {
|
|
@@ -516181,7 +516248,8 @@ var BlunTUI = class {
|
|
|
516181
516248
|
this.scheduleQueueDrain();
|
|
516182
516249
|
}
|
|
516183
516250
|
steerQueueFlushPrefix() {
|
|
516184
|
-
|
|
516251
|
+
const hasActiveTurn = this.streamingUI.hasActiveTurn() || this.state.appState.streamingPhase !== "idle";
|
|
516252
|
+
if (this.queueSteerInFlight !== void 0 || this.queueFlushBatchRemaining === 0 || this.deferUserMessages || this.state.appState.isCompacting || this.state.appState.streamingPhase === "shell" || !hasActiveTurn) return;
|
|
516185
516253
|
const session = this.session;
|
|
516186
516254
|
if (session === void 0 || this.state.appState.model.trim().length === 0) {
|
|
516187
516255
|
this.showError(llmNotSetMessage());
|
|
@@ -516294,7 +516362,7 @@ var BlunTUI = class {
|
|
|
516294
516362
|
channelAcknowledge: acknowledge,
|
|
516295
516363
|
...envelope.meta["image_path"] !== void 0 ? { channelImagePath: envelope.meta["image_path"] } : {}
|
|
516296
516364
|
});
|
|
516297
|
-
this.
|
|
516365
|
+
this.channelQueueDeadline.requestDeliveryNow();
|
|
516298
516366
|
this.scheduleQueueDrain();
|
|
516299
516367
|
this.track("input_queue");
|
|
516300
516368
|
this.updateQueueDisplay();
|
|
@@ -516766,7 +516834,7 @@ var BlunTUI = class {
|
|
|
516766
516834
|
this.sendTelegramRemoteCommandMessage(session, input, options, telegramContext);
|
|
516767
516835
|
return;
|
|
516768
516836
|
}
|
|
516769
|
-
if (this.deferUserMessages || this.state.appState.streamingPhase !== "idle" || this.state.appState.isCompacting) {
|
|
516837
|
+
if (this.deferUserMessages || this.streamingUI.hasActiveTurn() || this.state.appState.streamingPhase !== "idle" || this.state.appState.isCompacting) {
|
|
516770
516838
|
this.enqueueMessage(input, options);
|
|
516771
516839
|
return;
|
|
516772
516840
|
}
|
|
@@ -516777,7 +516845,8 @@ var BlunTUI = class {
|
|
|
516777
516845
|
for (const part of input) this.enqueueMessage(part);
|
|
516778
516846
|
return;
|
|
516779
516847
|
}
|
|
516780
|
-
|
|
516848
|
+
const hasActiveTurn = this.streamingUI.hasActiveTurn() || this.state.appState.streamingPhase !== "idle";
|
|
516849
|
+
if (!hasActiveTurn) {
|
|
516781
516850
|
for (const part of input) this.sendMessageInternal(session, part);
|
|
516782
516851
|
return;
|
|
516783
516852
|
}
|