blun-king-cli 9.1.423 → 9.1.425
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.
|
@@ -14,7 +14,8 @@ const NON_ACTIONABLE_USER_ORIGINS = new Set([
|
|
|
14
14
|
'skill_activation',
|
|
15
15
|
]);
|
|
16
16
|
const STOP_WORDS = new Set([
|
|
17
|
-
'aber', 'alle', 'alles', 'auch', '
|
|
17
|
+
'aber', 'alle', 'alles', 'auch', 'das', 'dem', 'den', 'der', 'des', 'die',
|
|
18
|
+
'ein', 'eine', 'einem', 'einen', 'einer', 'eines',
|
|
18
19
|
'fuer', 'haben', 'hier', 'immer', 'jetzt', 'kann', 'machen', 'mehr', 'mich',
|
|
19
20
|
'nicht', 'noch', 'oder', 'sein', 'sind', 'soll', 'und', 'uns', 'von', 'was',
|
|
20
21
|
'wenn', 'werden', 'wie', 'with', 'that', 'this', 'from', 'have', 'into',
|
|
@@ -22,8 +23,36 @@ const STOP_WORDS = new Set([
|
|
|
22
23
|
]);
|
|
23
24
|
const REUSABLE_HEADING = /\b(rule|regel|condition|bedingung|countercheck|gegenprobe|trigger|ausloeser|auslöser)\b/iu;
|
|
24
25
|
|
|
26
|
+
const SEMANTIC_SIGNAL_RULES = Object.freeze([
|
|
27
|
+
['problem:reliability', /\b(?:error|failure|failed|broken|crash(?:ed)?|timeout|unavailable|corrupt(?:ed)?|dropped|missing|lost|fehler|scheiter\w*|absturz|ausfall|kaputt|defekt|fehlend|verloren|unerreichbar|abbruch)\b/iu],
|
|
28
|
+
['problem:delivery', /\b(?:deliver\w*|receiv\w*|message\w*|repl(?:y|ies)|inbox|outbox|send(?:ing|s|t)?|consum\w*|zustell\w*|empfang\w*|nachricht\w*|meldung\w*|senden|bekomm\w*|antwort\w*)\b/iu],
|
|
29
|
+
['problem:stagnation', /\b(?:loop\w*|repeat\w*|stuck|hang(?:ing)?|freeze|frozen|idle|no progress|stop(?:s|ped)? consuming|schleife\w*|wiederhol\w*|hang\w*|stillstand|leerlauf|kein fortschritt|taub)\b/iu],
|
|
30
|
+
['problem:performance', /\b(?:slow|latency|bottleneck|throughput|memory pressure|cpu|vram|langsam\w*|latenz|durchsatz|engpass|speicherdruck)\b/iu],
|
|
31
|
+
['problem:protocol', /\b(?:schema|contract|payload|protocol|format|version mismatch|manifest mismatch|vertrag|protokoll|versionskonflikt)\b/iu],
|
|
32
|
+
['problem:capability', /\b(?:capabilit\w*|missing tool|not available|unsupported|fahigkeit\w*|werkzeug fehlt|nicht verfugbar)\b/iu],
|
|
33
|
+
['area:orchestration', /\b(?:agent\w*|worker\w*|queue\w*|checkpoint\w*|heartbeat\w*|delegat\w*|owner\w*|responsib\w*|task\w*|turn\w*|busy|group\w*|channel\w*|arbeiter\w*|warteschlange\w*|prufpunkt\w*|herzschlag\w*|zustandig\w*|auftrag\w*|zug\w*|beschaftigt|gruppe\w*|gruppen\w*|kanal\w*)\b/iu],
|
|
34
|
+
['area:memory', /\b(?:memory|recall|remember\w*|context|history|resume|checkpoint|mnemo|gedachtnis|erinner\w*|kontext|verlauf|wiederaufnahme)\b/iu],
|
|
35
|
+
['area:release', /\b(?:release\w*|rollout\w*|update\w*|updater\w*|npm|package\w*|manifest\w*|version\w*|veroffentlich\w*|paket\w*|integrity|integritat)\b/iu],
|
|
36
|
+
['area:media', /\b(?:image\w*|video\w*|audio\w*|portrait\w*|render\w*|pixel\w*|media|bild\w*|foto\w*|gesicht\w*|stimme\w*)\b/iu],
|
|
37
|
+
['risk:validation', /\b(?:verif\w*|validat\w*|test\w*|check\w*|gate\w*|rollback\w*|canary|proof|evidence|sha(?:256|512)?|measur\w*|inspect\w*|(?:ge)?pruf\w*|gegenprobe\w*|beleg\w*|evidenz\w*|mess\w*|kontroll\w*)\b/iu],
|
|
38
|
+
['action:repair', /\b(?:fix\w*|repair\w*|restore\w*|recover\w*|reparier\w*|beheb\w*|wiederherstell\w*)\b/iu],
|
|
39
|
+
['action:investigate', /\b(?:inspect\w*|diagnos\w*|measure\w*|trace\w*|check\w*|(?:ge)?pruf\w*|mess\w*|untersuch\w*)\b/iu],
|
|
40
|
+
]);
|
|
41
|
+
|
|
25
42
|
function normalizeText(value) {
|
|
26
|
-
return String(value || '')
|
|
43
|
+
return String(value || '')
|
|
44
|
+
.normalize('NFKD')
|
|
45
|
+
.replace(/\p{M}/gu, '')
|
|
46
|
+
.replace(/\u00df/gu, 'ss')
|
|
47
|
+
.toLowerCase();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function semanticSignalTags(value) {
|
|
51
|
+
const normalized = normalizeText(value);
|
|
52
|
+
if (!normalized) return [];
|
|
53
|
+
return SEMANTIC_SIGNAL_RULES
|
|
54
|
+
.filter(([, pattern]) => pattern.test(normalized))
|
|
55
|
+
.map(([tag]) => tag);
|
|
27
56
|
}
|
|
28
57
|
|
|
29
58
|
function terms(value) {
|
|
@@ -100,15 +129,25 @@ function isReusableSection(section) {
|
|
|
100
129
|
return REUSABLE_HEADING.test(`${section.heading}\n${section.body}`);
|
|
101
130
|
}
|
|
102
131
|
|
|
103
|
-
function scoreSection(section, queryTerms) {
|
|
132
|
+
function scoreSection(section, queryTerms, queryTags) {
|
|
104
133
|
const heading = normalizeText(`${section.parent} ${section.heading}`);
|
|
105
134
|
const body = normalizeText(section.body);
|
|
106
135
|
let score = isReusableSection(section) ? 1 : 0;
|
|
136
|
+
let lexicalMatches = 0;
|
|
107
137
|
for (const term of queryTerms) {
|
|
108
|
-
if (heading.includes(term))
|
|
109
|
-
|
|
138
|
+
if (heading.includes(term)) {
|
|
139
|
+
score += 6;
|
|
140
|
+
lexicalMatches += 1;
|
|
141
|
+
}
|
|
142
|
+
if (body.includes(term)) {
|
|
143
|
+
score += 4;
|
|
144
|
+
lexicalMatches += 1;
|
|
145
|
+
}
|
|
110
146
|
}
|
|
111
|
-
|
|
147
|
+
const sectionTags = new Set(semanticSignalTags(`${heading}\n${body}`));
|
|
148
|
+
const semanticMatches = queryTags.filter((tag) => sectionTags.has(tag));
|
|
149
|
+
score += semanticMatches.length * 2;
|
|
150
|
+
return { lexicalMatches, score, semanticMatches };
|
|
112
151
|
}
|
|
113
152
|
|
|
114
153
|
function compactSection(section, maxChars) {
|
|
@@ -144,16 +183,24 @@ function selectRelevantMistakeSources(sources, query, options = {}) {
|
|
|
144
183
|
}))
|
|
145
184
|
));
|
|
146
185
|
const queryTerms = terms(query);
|
|
186
|
+
const queryTags = semanticSignalTags(query);
|
|
147
187
|
const ranked = sections.map((section) => {
|
|
148
188
|
const reusable = isReusableSection(section);
|
|
149
|
-
const score = scoreSection(section, queryTerms);
|
|
189
|
+
const { lexicalMatches, score, semanticMatches } = scoreSection(section, queryTerms, queryTags);
|
|
150
190
|
return {
|
|
151
191
|
...section,
|
|
152
|
-
|
|
192
|
+
lexicalMatches,
|
|
153
193
|
reusable,
|
|
154
194
|
score,
|
|
195
|
+
semanticMatches,
|
|
155
196
|
};
|
|
156
197
|
});
|
|
198
|
+
const hasLexicalMatch = ranked.some((section) => section.lexicalMatches > 0);
|
|
199
|
+
for (const section of ranked) {
|
|
200
|
+
section.matched = hasLexicalMatch
|
|
201
|
+
? section.lexicalMatches > 0
|
|
202
|
+
: section.semanticMatches.length > 0;
|
|
203
|
+
}
|
|
157
204
|
const hasMatch = ranked.some((section) => section.matched);
|
|
158
205
|
ranked.sort((left, right) => {
|
|
159
206
|
if (hasMatch && right.score !== left.score) return right.score - left.score;
|
|
@@ -188,6 +235,11 @@ function selectRelevantMistakeSources(sources, query, options = {}) {
|
|
|
188
235
|
selected.sort((left, right) => left.ordinal - right.ordinal);
|
|
189
236
|
const text = [header, ...selected.map((section) => section.rendered)].join('\n\n').slice(0, maxChars);
|
|
190
237
|
return {
|
|
238
|
+
selected: selected.map((section) => ({
|
|
239
|
+
heading: section.heading,
|
|
240
|
+
reference: normalizedSources[section.sourceIndex]?.reference || '',
|
|
241
|
+
semanticMatches: section.semanticMatches || [],
|
|
242
|
+
})),
|
|
191
243
|
selectedChars: text.length,
|
|
192
244
|
selectedSections: selected.length,
|
|
193
245
|
text,
|
|
@@ -209,6 +261,7 @@ module.exports = {
|
|
|
209
261
|
RECENT_USER_MESSAGES,
|
|
210
262
|
isLowInformationMistakeTurn,
|
|
211
263
|
recentUserText,
|
|
264
|
+
semanticSignalTags,
|
|
212
265
|
selectRelevantMistakeContent,
|
|
213
266
|
selectRelevantMistakeSources,
|
|
214
267
|
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const MAX_SUBAGENT_HANDOFF_ATTEMPTS = 1;
|
|
4
|
+
const MAX_PARTIAL_HANDOFF_CHARS = 6000;
|
|
5
|
+
const SUBAGENT_MAX_TOKENS_ERROR =
|
|
6
|
+
"Subagent turn failed before completing its final summary: reason=max_tokens";
|
|
7
|
+
const SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT = [
|
|
8
|
+
"Your previous turn reached max_tokens before its final handoff.",
|
|
9
|
+
"Do not call any tools and do not repeat completed work.",
|
|
10
|
+
"Return one concise recovery handoff of at most 1200 words with:",
|
|
11
|
+
"1. completed work and concrete findings",
|
|
12
|
+
"2. exact files changed or created",
|
|
13
|
+
"3. checks already run and their actual results",
|
|
14
|
+
"4. unfinished work or blockers",
|
|
15
|
+
"5. the exact next action for the parent or this same agent",
|
|
16
|
+
"State clearly that the task is incomplete when anything remains.",
|
|
17
|
+
].join("\n");
|
|
18
|
+
|
|
19
|
+
function shouldRequestSubagentHandoff(stopReason, attempts) {
|
|
20
|
+
return stopReason === "max_tokens"
|
|
21
|
+
&& Number.isSafeInteger(attempts)
|
|
22
|
+
&& attempts >= 0
|
|
23
|
+
&& attempts < MAX_SUBAGENT_HANDOFF_ATTEMPTS;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function boundedPartialHandoff(partialSummary) {
|
|
27
|
+
const normalized = typeof partialSummary === "string" ? partialSummary.trim() : "";
|
|
28
|
+
if (normalized.length <= MAX_PARTIAL_HANDOFF_CHARS) return normalized;
|
|
29
|
+
return `${normalized.slice(0, MAX_PARTIAL_HANDOFF_CHARS)}\n[partial handoff truncated]`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function buildSubagentMaxTokensFailure(partialSummary) {
|
|
33
|
+
const partial = boundedPartialHandoff(partialSummary);
|
|
34
|
+
const lines = [
|
|
35
|
+
`${SUBAGENT_MAX_TOKENS_ERROR}.`,
|
|
36
|
+
"The automatic concise handoff also reached max_tokens.",
|
|
37
|
+
];
|
|
38
|
+
if (partial.length > 0) {
|
|
39
|
+
lines.push("", "[partial_handoff]", partial, "[/partial_handoff]");
|
|
40
|
+
}
|
|
41
|
+
lines.push(
|
|
42
|
+
"",
|
|
43
|
+
"Resume the same subagent instead of starting the task again; its context and completed tool work are preserved.",
|
|
44
|
+
);
|
|
45
|
+
return lines.join("\n");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
MAX_PARTIAL_HANDOFF_CHARS,
|
|
50
|
+
MAX_SUBAGENT_HANDOFF_ATTEMPTS,
|
|
51
|
+
SUBAGENT_MAX_TOKENS_ERROR,
|
|
52
|
+
SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT,
|
|
53
|
+
buildSubagentMaxTokensFailure,
|
|
54
|
+
shouldRequestSubagentHandoff,
|
|
55
|
+
};
|
package/blun.mjs
CHANGED
|
@@ -252261,7 +252261,21 @@ async function runChildTurnToCompletion(child, signal) {
|
|
|
252261
252261
|
if (typeof statusCode === "number") error.statusCode = statusCode;
|
|
252262
252262
|
throw error;
|
|
252263
252263
|
}
|
|
252264
|
-
|
|
252264
|
+
return completion.stopReason;
|
|
252265
|
+
}
|
|
252266
|
+
async function completeChildTurnWithMaxTokensHandoff(child, signal) {
|
|
252267
|
+
let stopReason = await runChildTurnToCompletion(child, signal);
|
|
252268
|
+
let handoffAttempts = 0;
|
|
252269
|
+
while (shouldRequestSubagentHandoff(stopReason, handoffAttempts)) {
|
|
252270
|
+
handoffAttempts += 1;
|
|
252271
|
+
signal.throwIfAborted();
|
|
252272
|
+
if (child.turn.prompt([{
|
|
252273
|
+
type: "text",
|
|
252274
|
+
text: SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT
|
|
252275
|
+
}], SUBAGENT_PROMPT_ORIGIN) === null) throw new Error("Subagent could not start its max_tokens recovery handoff.");
|
|
252276
|
+
stopReason = await runChildTurnToCompletion(child, signal);
|
|
252277
|
+
}
|
|
252278
|
+
if (stopReason === "max_tokens") throw new Error(buildSubagentMaxTokensFailure(lastAssistantText(child)));
|
|
252265
252279
|
}
|
|
252266
252280
|
function providerRateLimitErrorFromPayload(error) {
|
|
252267
252281
|
const requestId = typeof error.details?.["requestId"] === "string" ? error.details["requestId"] : null;
|
|
@@ -252280,7 +252294,7 @@ function shouldSuppressQueuedAttemptFailureEvent(options, error) {
|
|
|
252280
252294
|
if (isProviderRateLimitError(error)) return true;
|
|
252281
252295
|
return isAbortError$4(error) || options.signal.aborted;
|
|
252282
252296
|
}
|
|
252283
|
-
var DEFAULT_SUBAGENT_TIMEOUT_MS, resolveSubagentTimeoutMs, runAgentWithTimeoutContinuation, buildSubagentUsageDelta, SUMMARY_MIN_LENGTH, SUMMARY_CONTINUATION_ATTEMPTS, HOOK_TEXT_PREVIEW_LENGTH,
|
|
252297
|
+
var DEFAULT_SUBAGENT_TIMEOUT_MS, resolveSubagentTimeoutMs, runAgentWithTimeoutContinuation, buildSubagentUsageDelta, SUBAGENT_MAX_TOKENS_ERROR, SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT, buildSubagentMaxTokensFailure, shouldRequestSubagentHandoff, SUMMARY_MIN_LENGTH, SUMMARY_CONTINUATION_ATTEMPTS, HOOK_TEXT_PREVIEW_LENGTH, TOOL_CALL_DISABLED_MESSAGE, SUBAGENT_PROMPT_ORIGIN, SIDE_QUESTION_SYSTEM_REMINDER, SessionSubagentHost;
|
|
252284
252298
|
var init_subagent_host = __esmMin((() => {
|
|
252285
252299
|
init_src$4();
|
|
252286
252300
|
init_errors$8();
|
|
@@ -252294,10 +252308,15 @@ var init_subagent_host = __esmMin((() => {
|
|
|
252294
252308
|
init_summary_continuation();
|
|
252295
252309
|
({ DEFAULT_SUBAGENT_TIMEOUT_MS, resolveSubagentTimeoutMs, runAgentWithTimeoutContinuation } = createRequire(import.meta.url)("./bin/subagent-timeout-policy.cjs"));
|
|
252296
252310
|
({ buildSubagentUsageDelta } = createRequire(import.meta.url)("./bin/subagent-usage-rollup-policy.cjs"));
|
|
252311
|
+
({
|
|
252312
|
+
SUBAGENT_MAX_TOKENS_ERROR,
|
|
252313
|
+
SUBAGENT_MAX_TOKENS_HANDOFF_PROMPT,
|
|
252314
|
+
buildSubagentMaxTokensFailure,
|
|
252315
|
+
shouldRequestSubagentHandoff
|
|
252316
|
+
} = createRequire(import.meta.url)("./bin/subagent-max-tokens-handoff-policy.cjs"));
|
|
252297
252317
|
SUMMARY_MIN_LENGTH = 200;
|
|
252298
252318
|
SUMMARY_CONTINUATION_ATTEMPTS = 1;
|
|
252299
252319
|
HOOK_TEXT_PREVIEW_LENGTH = 500;
|
|
252300
|
-
SUBAGENT_MAX_TOKENS_ERROR = "Subagent turn failed before completing its final summary: reason=max_tokens";
|
|
252301
252320
|
TOOL_CALL_DISABLED_MESSAGE = "Tool calls are disabled for side questions. Answer with text only.";
|
|
252302
252321
|
SUBAGENT_PROMPT_ORIGIN = {
|
|
252303
252322
|
kind: "system_trigger",
|
|
@@ -252561,7 +252580,7 @@ IMPORTANT:
|
|
|
252561
252580
|
return this.waitForChildCompletion(parent, childId, child, profileName, options);
|
|
252562
252581
|
}
|
|
252563
252582
|
async waitForChildCompletion(parent, childId, child, profileName, options) {
|
|
252564
|
-
await
|
|
252583
|
+
await completeChildTurnWithMaxTokensHandoff(child, options.signal);
|
|
252565
252584
|
let result = lastAssistantText(child);
|
|
252566
252585
|
let remainingContinuations = SUMMARY_CONTINUATION_ATTEMPTS;
|
|
252567
252586
|
while (remainingContinuations > 0 && result.length < SUMMARY_MIN_LENGTH) {
|
|
@@ -252571,7 +252590,7 @@ IMPORTANT:
|
|
|
252571
252590
|
type: "text",
|
|
252572
252591
|
text: summary_continuation_default
|
|
252573
252592
|
}], SUBAGENT_PROMPT_ORIGIN);
|
|
252574
|
-
await
|
|
252593
|
+
await completeChildTurnWithMaxTokensHandoff(child, options.signal);
|
|
252575
252594
|
result = lastAssistantText(child);
|
|
252576
252595
|
}
|
|
252577
252596
|
const usage = child.usage.data().total;
|
|
@@ -252709,7 +252728,7 @@ function formatForegroundAgentFailure(handle, message, timedOut) {
|
|
|
252709
252728
|
"",
|
|
252710
252729
|
`subagent error: ${message}`
|
|
252711
252730
|
];
|
|
252712
|
-
if (timedOut) lines.push(`resume_hint: Continue with Agent(resume="${handle.agentId}", prompt="continue"). Use agent_id only; do not set subagent_type. The subagent retains its prior context; redo any unfinished tool call if its result was lost.`);
|
|
252731
|
+
if (timedOut || message.includes(SUBAGENT_MAX_TOKENS_ERROR)) lines.push(`resume_hint: Continue with Agent(resume="${handle.agentId}", prompt="continue"). Use agent_id only; do not set subagent_type. The subagent retains its prior context; redo any unfinished tool call if its result was lost.`);
|
|
252713
252732
|
return lines.join("\n");
|
|
252714
252733
|
}
|
|
252715
252734
|
function launchErrorMessage(error, signal) {
|