blun-king-cli 9.1.212 → 9.1.214
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/validated-learning-signal.cjs +107 -0
- package/blun.mjs +44 -1
- package/package.json +1 -1
|
@@ -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";
|
|
@@ -232794,7 +232835,7 @@ var init_mission_contract = __esmMin((() => {
|
|
|
232794
232835
|
"Treat this machine-readable contract as the source of truth.",
|
|
232795
232836
|
"Do not claim completion until every acceptance criterion has matching evidence.",
|
|
232796
232837
|
"If a criterion cannot be verified, report the gap instead of claiming success.",
|
|
232797
|
-
"If the same test or check first fails and later passes because of your fix, invoke
|
|
232838
|
+
"If the same test or check first fails and later passes because of your fix, invoke MistakeRecord after the green rerun and before mission_review.",
|
|
232798
232839
|
"Record the failure class, symptom, root cause, failed attempts, effective fix, affected files, and a concrete repetition guard. Runtime red-to-green evidence is mandatory.",
|
|
232799
232840
|
"For any mission that changes files, invoke mission_review after the relevant tests and before UpdateGoal complete.",
|
|
232800
232841
|
"If mission_review returns findings, fix every validated finding, rerun affected tests, and invoke mission_review again.",
|
|
@@ -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)
|