blun-king-cli 9.1.213 → 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.
@@ -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)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.213",
3
+ "version": "9.1.214",
4
4
  "description": "BLUN CLI - your own AI agent with a Telegram channel. Get it done. With BLUN.",
5
5
  "license": "MIT",
6
6
  "bin": {