blun-king-cli 9.1.120 → 9.1.121
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/LIESMICH.txt +2 -0
- package/README.md +2 -0
- package/bin/tool-result-offload-policy.cjs +39 -0
- package/blun.mjs +75 -9
- package/package.json +1 -1
package/LIESMICH.txt
CHANGED
|
@@ -119,6 +119,8 @@ Ab BLUN King 9.1.119 enthält der bei jedem Modellschritt erneut gesendete Promp
|
|
|
119
119
|
|
|
120
120
|
Ab BLUN King 9.1.120 lagert die Konsole auch große ältere Assistentenantworten aus dem aktiven Modellkontext in private Sitzungsdateien aus. Der vollständige Gesprächsverlauf bleibt erhalten; im Modellkontext verbleiben eine begrenzte Vorschau und der Dateipfad. Die 20 neuesten Nachrichten sowie Assistentenantworten mit Werkzeugaufrufen bleiben unverändert, damit laufende Arbeit und Aufrufketten vollständig verfügbar sind.
|
|
121
121
|
|
|
122
|
+
Ab BLUN King 9.1.121 begrenzt die Modellprojektion auch die Gesamtgröße älterer, mittelgroßer Werkzeugergebnisse, die ausschließlich Text enthalten. Überschreiten Werkzeugergebnisse außerhalb der letzten 20 Nachrichten zusammen 12.000 Zeichen, archiviert King so viele der größten geeigneten Ergebnisse wie nötig und behält nur kompakte, lesbare Dateiverweise im Modellkontext. Der nur ergänzte Rohverlauf und die vollständigen Ergebnisse bleiben unverändert. Gemischte Medienergebnisse und die letzten 20 Nachrichten werden nicht angetastet. In einer gemessenen Sitzung von Fredrik wählte dieser Schnitt 12 ältere Ergebnisse aus und verringerte die projizierte alte Werkzeugausgabe um mindestens 63.444 Zeichen, also um etwa 15.861 geschätzte Token.
|
|
123
|
+
|
|
122
124
|
Verliert ein delegierter Einzelagent oder ein Mitglied eines Agentenschwarms die Provider-Verbindung, erhält es eine leere Provider-Antwort, bricht sein Stream wegen Leerlaufs ab oder meldet der Server HTTP 408/500/502/503/504, setzt BLUN King denselben Agenten anhand seines dauerhaften Verlaufs fort. Bei Einzelagenten sowie bei Schwarm-Unterbrechungen außerhalb von HTTP 429 wartet die erste Fortsetzung zwei Sekunden und die zweite fünf Sekunden; danach bleibt der ursprüngliche Fehler sichtbar. HTTP 429 behält im Schwarm seine getrennte, längere Überlastungsregel. Authentifizierungs-, Zahlungs- oder Kontingent-, Richtlinien-, Kontext-, Werkzeug- und Codefehler sowie manuelle Abbrüche lösen keine automatische Fortsetzung aus. Jeder Fortsetzungsversuch verwendet die bestehende Agenten-ID, damit bereits abgeschlossene Arbeit nicht wiederholt wird.
|
|
123
125
|
|
|
124
126
|
Rein lesende Sitzungsdiagnose
|
package/README.md
CHANGED
|
@@ -125,6 +125,8 @@ Ab BLUN King 9.1.119 enthält der bei jedem Modellschritt erneut gesendete Promp
|
|
|
125
125
|
|
|
126
126
|
Ab BLUN King 9.1.120 lagert die Konsole auch große ältere Assistentenantworten aus dem aktiven Modellkontext in private Sitzungsdateien aus. Der vollständige Gesprächsverlauf bleibt erhalten; im Modellkontext verbleiben eine begrenzte Vorschau und der Dateipfad. Die 20 neuesten Nachrichten sowie Assistentenantworten mit Werkzeugaufrufen bleiben unverändert, damit laufende Arbeit und Aufrufketten vollständig verfügbar sind.
|
|
127
127
|
|
|
128
|
+
Ab BLUN King 9.1.121 begrenzt die Modellprojektion auch die Gesamtgröße älterer, mittelgroßer Werkzeugergebnisse, die ausschließlich Text enthalten. Überschreiten Werkzeugergebnisse außerhalb der letzten 20 Nachrichten zusammen 12.000 Zeichen, archiviert King so viele der größten geeigneten Ergebnisse wie nötig und behält nur kompakte, lesbare Dateiverweise im Modellkontext. Der nur ergänzte Rohverlauf und die vollständigen Ergebnisse bleiben unverändert. Gemischte Medienergebnisse und die letzten 20 Nachrichten werden nicht angetastet. In einer gemessenen Sitzung von Fredrik wählte dieser Schnitt 12 ältere Ergebnisse aus und verringerte die projizierte alte Werkzeugausgabe um mindestens 63.444 Zeichen, also um etwa 15.861 geschätzte Token.
|
|
129
|
+
|
|
128
130
|
Ab BLUN King 9.1.99 werden auch direkt aufeinanderfolgende reine Textergebnisse als Stapel betrachtet. Enthalten sie zusammen mehr als 12.000 Zeichen, obwohl kein einzelnes Ergebnis diese Grenze überschreitet, speichert King so viele der größten geeigneten Ergebnisse wie nötig in privaten Dateien. In der Modellprojektion verbleiben lesbare Verweise. Der unveränderte Sitzungsrohverlauf bleibt vollständig erhalten. Gemischte Medienergebnisse, einzelne Ergebnisse unter 3.000 Zeichen und Stapel bis einschließlich 12.000 Zeichen bleiben unverändert. Beispiel: Bei zwei Suchergebnissen mit 7.000 und 6.000 Zeichen wird das größere Ergebnis privat gespeichert; Anfang, Ende, ausgelassene Zeichenzahl und `output_path` bleiben für den Agenten sichtbar.
|
|
129
131
|
|
|
130
132
|
Ab BLUN King 9.1.100 beendet eine begrenzte Grep-Inhaltssuche ripgrep, sobald der Versatz, die angeforderten Zeilen und eine zusätzliche Vorschauzeile vollständig vorliegen. Die Vorschauzeile belegt, ob eine weitere Seite existiert, ohne vorher bis zu 10 MB einzulesen. Unbegrenzte Suchen, Trefferzählungen und nach Änderungszeit sortierte Dateilisten laufen weiterhin vollständig durch.
|
|
@@ -6,6 +6,10 @@ const TOOL_RESULT_OFFLOAD_MARKER = '[Tool result offloaded]';
|
|
|
6
6
|
const TOOL_RESULT_BATCH_MAX_CHARS = TOOL_RESULT_MAX_CHARS;
|
|
7
7
|
const TOOL_RESULT_BATCH_MIN_ITEM_CHARS = 3_000;
|
|
8
8
|
const TOOL_RESULT_BATCH_REPLACEMENT_BUDGET_CHARS = 2_500;
|
|
9
|
+
const TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES = 20;
|
|
10
|
+
const TOOL_RESULT_HISTORICAL_MAX_CHARS = TOOL_RESULT_BATCH_MAX_CHARS;
|
|
11
|
+
const TOOL_RESULT_HISTORICAL_MIN_ITEM_CHARS = 600;
|
|
12
|
+
const TOOL_RESULT_HISTORICAL_REPLACEMENT_BUDGET_CHARS = 600;
|
|
9
13
|
|
|
10
14
|
function shouldOffloadToolResult(textLength) {
|
|
11
15
|
return Number.isFinite(textLength) && textLength > TOOL_RESULT_MAX_CHARS;
|
|
@@ -62,15 +66,50 @@ function selectToolResultBatchOffloads(textLengths) {
|
|
|
62
66
|
: [];
|
|
63
67
|
}
|
|
64
68
|
|
|
69
|
+
function selectHistoricalToolResultOffloads(textLengths) {
|
|
70
|
+
if (!Array.isArray(textLengths) || textLengths.length === 0) return [];
|
|
71
|
+
|
|
72
|
+
const normalized = textLengths.map((length) => (
|
|
73
|
+
Number.isFinite(length) && length > 0 ? Math.floor(length) : 0
|
|
74
|
+
));
|
|
75
|
+
const totalChars = normalized.reduce((total, length) => total + length, 0);
|
|
76
|
+
if (totalChars <= TOOL_RESULT_HISTORICAL_MAX_CHARS) return [];
|
|
77
|
+
|
|
78
|
+
let projectedChars = totalChars;
|
|
79
|
+
const selected = [];
|
|
80
|
+
const candidates = normalized
|
|
81
|
+
.map((length, index) => ({ index, length }))
|
|
82
|
+
.filter(({ length }) => (
|
|
83
|
+
length >= TOOL_RESULT_HISTORICAL_MIN_ITEM_CHARS
|
|
84
|
+
&& length > TOOL_RESULT_HISTORICAL_REPLACEMENT_BUDGET_CHARS
|
|
85
|
+
))
|
|
86
|
+
.sort((left, right) => right.length - left.length || left.index - right.index);
|
|
87
|
+
|
|
88
|
+
for (const candidate of candidates) {
|
|
89
|
+
if (projectedChars <= TOOL_RESULT_HISTORICAL_MAX_CHARS) break;
|
|
90
|
+
projectedChars -= candidate.length - TOOL_RESULT_HISTORICAL_REPLACEMENT_BUDGET_CHARS;
|
|
91
|
+
selected.push(candidate.index);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return projectedChars <= TOOL_RESULT_HISTORICAL_MAX_CHARS
|
|
95
|
+
? selected.sort((left, right) => left - right)
|
|
96
|
+
: [];
|
|
97
|
+
}
|
|
98
|
+
|
|
65
99
|
module.exports = {
|
|
66
100
|
TOOL_RESULT_BATCH_MAX_CHARS,
|
|
67
101
|
TOOL_RESULT_BATCH_MIN_ITEM_CHARS,
|
|
68
102
|
TOOL_RESULT_BATCH_REPLACEMENT_BUDGET_CHARS,
|
|
103
|
+
TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES,
|
|
104
|
+
TOOL_RESULT_HISTORICAL_MAX_CHARS,
|
|
105
|
+
TOOL_RESULT_HISTORICAL_MIN_ITEM_CHARS,
|
|
106
|
+
TOOL_RESULT_HISTORICAL_REPLACEMENT_BUDGET_CHARS,
|
|
69
107
|
TOOL_RESULT_MAX_CHARS,
|
|
70
108
|
TOOL_RESULT_PREVIEW_CHARS,
|
|
71
109
|
TOOL_RESULT_OFFLOAD_MARKER,
|
|
72
110
|
createToolResultPreview,
|
|
73
111
|
isPersistedToolResultReference,
|
|
112
|
+
selectHistoricalToolResultOffloads,
|
|
74
113
|
selectToolResultBatchOffloads,
|
|
75
114
|
shouldOffloadToolResult,
|
|
76
115
|
};
|
package/blun.mjs
CHANGED
|
@@ -260329,10 +260329,53 @@ function renderReadSourceReference(toolName, toolCallId, text, outputPath) {
|
|
|
260329
260329
|
lines.push("", "[preview: head and tail]", createToolResultPreview(text));
|
|
260330
260330
|
return lines.join("\n");
|
|
260331
260331
|
}
|
|
260332
|
+
async function persistHistoricalToolResultForModel(options, knownText) {
|
|
260333
|
+
const text = knownText ?? persistableToolResultText(options.result.output);
|
|
260334
|
+
if (text === void 0 || options.result.truncated === true) return options.result;
|
|
260335
|
+
const readSourcePath = reusableReadSourcePath(options);
|
|
260336
|
+
let outputPath = readSourcePath;
|
|
260337
|
+
let storageMode = "original_file";
|
|
260338
|
+
if (outputPath === void 0) {
|
|
260339
|
+
if (options.homedir === void 0) return options.result;
|
|
260340
|
+
outputPath = await saveToolResult({
|
|
260341
|
+
homedir: options.homedir,
|
|
260342
|
+
toolName: options.toolName,
|
|
260343
|
+
toolCallId: options.toolCallId
|
|
260344
|
+
}, text);
|
|
260345
|
+
storageMode = "private_archive";
|
|
260346
|
+
}
|
|
260347
|
+
if (outputPath === void 0) return options.result;
|
|
260348
|
+
options.telemetry?.track("tool_result_historical_offloaded", {
|
|
260349
|
+
...buildToolResultOffloadTelemetry({
|
|
260350
|
+
toolName: options.toolName,
|
|
260351
|
+
text,
|
|
260352
|
+
previewChars: 0
|
|
260353
|
+
}),
|
|
260354
|
+
storage_mode: storageMode
|
|
260355
|
+
});
|
|
260356
|
+
return {
|
|
260357
|
+
...options.result,
|
|
260358
|
+
output: renderHistoricalToolResultReference(options.toolName, options.toolCallId, text, outputPath, storageMode),
|
|
260359
|
+
...(options.result.isError === true ? { isError: true } : {})
|
|
260360
|
+
};
|
|
260361
|
+
}
|
|
260362
|
+
function renderHistoricalToolResultReference(toolName, toolCallId, text, outputPath, storageMode) {
|
|
260363
|
+
return [
|
|
260364
|
+
TOOL_RESULT_OFFLOAD_MARKER,
|
|
260365
|
+
"An older tool result was archived to keep the active context fast.",
|
|
260366
|
+
`storage_mode: ${storageMode}`,
|
|
260367
|
+
`tool_name: ${toolName}`,
|
|
260368
|
+
`tool_call_id: ${toolCallId}`,
|
|
260369
|
+
`output_size_chars: ${String(text.length)}`,
|
|
260370
|
+
`output_size_bytes: ${String(Buffer.byteLength(text, "utf8"))}`,
|
|
260371
|
+
`output_path: ${outputPath}`,
|
|
260372
|
+
"next_step: Use Read with output_path if the full result is needed again."
|
|
260373
|
+
].join("\n");
|
|
260374
|
+
}
|
|
260332
260375
|
function safeToolResultFileStem(toolName, toolCallId) {
|
|
260333
260376
|
return `${toolName}-${toolCallId}`.replace(/[^a-zA-Z0-9._-]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 80) || "tool-result";
|
|
260334
260377
|
}
|
|
260335
|
-
var TOOL_RESULT_MAX_CHARS, TOOL_RESULT_PREVIEW_CHARS, TOOL_RESULT_OFFLOAD_MARKER, shouldOffloadToolResult, createToolResultPreview, selectToolResultBatchOffloads, buildToolResultOffloadTelemetry;
|
|
260378
|
+
var TOOL_RESULT_MAX_CHARS, TOOL_RESULT_PREVIEW_CHARS, TOOL_RESULT_OFFLOAD_MARKER, TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES, shouldOffloadToolResult, createToolResultPreview, selectToolResultBatchOffloads, selectHistoricalToolResultOffloads, buildToolResultOffloadTelemetry;
|
|
260336
260379
|
var init_tool_result_budget = __esmMin((() => {
|
|
260337
260380
|
init_dist$6();
|
|
260338
260381
|
const toolResultOffloadPolicy = createRequire(import.meta.url)("./bin/tool-result-offload-policy.cjs");
|
|
@@ -260340,9 +260383,11 @@ var init_tool_result_budget = __esmMin((() => {
|
|
|
260340
260383
|
TOOL_RESULT_MAX_CHARS = toolResultOffloadPolicy.TOOL_RESULT_MAX_CHARS;
|
|
260341
260384
|
TOOL_RESULT_PREVIEW_CHARS = toolResultOffloadPolicy.TOOL_RESULT_PREVIEW_CHARS;
|
|
260342
260385
|
TOOL_RESULT_OFFLOAD_MARKER = toolResultOffloadPolicy.TOOL_RESULT_OFFLOAD_MARKER;
|
|
260386
|
+
TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES = toolResultOffloadPolicy.TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES;
|
|
260343
260387
|
shouldOffloadToolResult = toolResultOffloadPolicy.shouldOffloadToolResult;
|
|
260344
260388
|
createToolResultPreview = toolResultOffloadPolicy.createToolResultPreview;
|
|
260345
260389
|
selectToolResultBatchOffloads = toolResultOffloadPolicy.selectToolResultBatchOffloads;
|
|
260390
|
+
selectHistoricalToolResultOffloads = toolResultOffloadPolicy.selectHistoricalToolResultOffloads;
|
|
260346
260391
|
}));
|
|
260347
260392
|
//#endregion
|
|
260348
260393
|
//#region ../../packages/agent-core/src/agent/turn/tool-result-batch-offload.ts
|
|
@@ -260360,7 +260405,20 @@ var ToolResultBatchOffload = class {
|
|
|
260360
260405
|
if (message?.role !== "tool") break;
|
|
260361
260406
|
tail.unshift(message);
|
|
260362
260407
|
}
|
|
260363
|
-
const
|
|
260408
|
+
const tailIds = new Set(tail.map((message) => message.toolCallId).filter((id) => id !== void 0));
|
|
260409
|
+
const recentStart = Math.max(0, history.length - TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES);
|
|
260410
|
+
const historical = history.slice(0, recentStart).filter((message) => message?.role === "tool" && !tailIds.has(message.toolCallId));
|
|
260411
|
+
const candidateBatches = [{
|
|
260412
|
+
messages: tail,
|
|
260413
|
+
historical: false,
|
|
260414
|
+
select: selectToolResultBatchOffloads
|
|
260415
|
+
}, {
|
|
260416
|
+
messages: historical,
|
|
260417
|
+
historical: true,
|
|
260418
|
+
select: selectHistoricalToolResultOffloads
|
|
260419
|
+
}].map((batch) => ({
|
|
260420
|
+
...batch,
|
|
260421
|
+
candidates: batch.messages.map((message) => {
|
|
260364
260422
|
if (message.toolCallId === void 0 || this.replacements.has(message.toolCallId) || isPersistedToolResultReference(message.content)) return;
|
|
260365
260423
|
const text = persistableToolResultText(message.content);
|
|
260366
260424
|
if (text === void 0) return;
|
|
@@ -260371,15 +260429,19 @@ var ToolResultBatchOffload = class {
|
|
|
260371
260429
|
toolName: toolCall?.name ?? "Tool",
|
|
260372
260430
|
toolArgs: this.toolArgsFor(toolCall)
|
|
260373
260431
|
};
|
|
260374
|
-
|
|
260375
|
-
|
|
260376
|
-
|
|
260432
|
+
}).filter((candidate) => candidate !== void 0)
|
|
260433
|
+
}));
|
|
260434
|
+
const selectedCandidates = candidateBatches.flatMap((batch) => batch.select(batch.candidates.map((candidate) => candidate.text.length)).map((index) => {
|
|
260435
|
+
const candidate = batch.candidates[index];
|
|
260436
|
+
return candidate === void 0 ? void 0 : { ...candidate, historical: batch.historical };
|
|
260437
|
+
}).filter((candidate) => candidate !== void 0));
|
|
260438
|
+
if (selectedCandidates.length === 0) return 0;
|
|
260377
260439
|
const replacements = [];
|
|
260378
260440
|
let charsBefore = 0;
|
|
260379
260441
|
let charsAfter = 0;
|
|
260380
|
-
|
|
260381
|
-
|
|
260382
|
-
|
|
260442
|
+
let historicalResultCount = 0;
|
|
260443
|
+
let tailResultCount = 0;
|
|
260444
|
+
for (const candidate of selectedCandidates) {
|
|
260383
260445
|
const original = {
|
|
260384
260446
|
output: candidate.message.content,
|
|
260385
260447
|
isError: candidate.message.isError
|
|
@@ -260393,7 +260455,7 @@ var ToolResultBatchOffload = class {
|
|
|
260393
260455
|
telemetry: this.agent.telemetry
|
|
260394
260456
|
};
|
|
260395
260457
|
const readSourcePath = reusableReadSourcePath(resultOptions);
|
|
260396
|
-
const persisted = readSourcePath === void 0 ? await persistToolResultForModel(resultOptions, candidate.text) : referenceReadSourceForModel(resultOptions, candidate.text, readSourcePath);
|
|
260458
|
+
const persisted = candidate.historical ? await persistHistoricalToolResultForModel(resultOptions, candidate.text) : readSourcePath === void 0 ? await persistToolResultForModel(resultOptions, candidate.text) : referenceReadSourceForModel(resultOptions, candidate.text, readSourcePath);
|
|
260397
260459
|
if (persisted === original || typeof persisted.output !== "string" || persisted.output.length >= candidate.text.length) continue;
|
|
260398
260460
|
const content = [{
|
|
260399
260461
|
type: "text",
|
|
@@ -260405,11 +260467,15 @@ var ToolResultBatchOffload = class {
|
|
|
260405
260467
|
});
|
|
260406
260468
|
charsBefore += candidate.text.length;
|
|
260407
260469
|
charsAfter += persisted.output.length;
|
|
260470
|
+
if (candidate.historical) historicalResultCount += 1;
|
|
260471
|
+
else tailResultCount += 1;
|
|
260408
260472
|
}
|
|
260409
260473
|
if (replacements.length === 0) return 0;
|
|
260410
260474
|
this.apply(replacements);
|
|
260411
260475
|
this.agent.telemetry.track("tool_result_batch_offloaded", {
|
|
260412
260476
|
result_count: replacements.length,
|
|
260477
|
+
historical_result_count: historicalResultCount,
|
|
260478
|
+
tail_result_count: tailResultCount,
|
|
260413
260479
|
chars_before: charsBefore,
|
|
260414
260480
|
chars_after: charsAfter,
|
|
260415
260481
|
chars_saved: charsBefore - charsAfter
|