blun-king-cli 9.1.103 → 9.1.104
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 +3 -1
- package/bin/foreground-output-capture-policy.cjs +41 -0
- package/blun.mjs +25 -19
- package/package.json +1 -1
package/LIESMICH.txt
CHANGED
|
@@ -91,6 +91,8 @@ Ab BLUN King 9.1.98 kann King einen abgeschlossenen Arbeitsabschnitt verdichten,
|
|
|
91
91
|
|
|
92
92
|
Große textbasierte Werkzeugergebnisse bleiben nicht mehr vollständig im Modellkontext. Ab 12.001 Zeichen speichert BLUN King das vollständige Ergebnis in einer privaten Datei im Sitzungsordner `tool-results`. Im Modellkontext verbleiben die ersten 1.000 und die letzten 1.000 Zeichen, die genaue Zahl der ausgelassenen Zeichen und der `output_path`. Der Agent kann das vollständige Ergebnis anschließend mit `Read` seitenweise über diesen Pfad lesen. Ergebnisse bis einschließlich 12.000 Zeichen, gemischte Medienergebnisse und bereits gekürzte Ergebnisse bleiben unverändert. Auch eine spätere Mikroverdichtung bewahrt den Dateiverweis. Beispiel: Bei einem Suchergebnis mit 30.000 Zeichen sehen folgende Modellanfragen den Anfang und das abschließende Ergebnis oder den Fehler; der vollständige Text bleibt lokal verfügbar.
|
|
93
93
|
|
|
94
|
+
Version 9.1.104 lässt Shell-Befehle im Vordergrund auch bei sehr großen Ausgaben bis zum regulären Ende laufen. King schreibt bis zu 16 MiB fortlaufend in das private Aufgabenprotokoll, verwirft darüber hinausgehende Ausgaben und meldet den tatsächlichen Exit-Code, statt den Prozess wegen der Ausgabemenge zu beenden. Kleine Ausgaben, Hintergrundaufgaben, Zeitgrenzen und manuelle Abbrüche bleiben unverändert.
|
|
95
|
+
|
|
94
96
|
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.
|
|
95
97
|
|
|
96
98
|
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.
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Voraussetzung ist Node.js 24.15 oder neuer. Die geprüfte Version wird exakt
|
|
|
9
9
|
installiert:
|
|
10
10
|
|
|
11
11
|
```powershell
|
|
12
|
-
npm install -g blun-king-cli@9.1.
|
|
12
|
+
npm install -g blun-king-cli@9.1.104
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
## Reproduzierbares Staging und Packen
|
|
@@ -111,6 +111,8 @@ Ab BLUN King 9.1.98 kann King einen abgeschlossenen Arbeitsabschnitt verdichten,
|
|
|
111
111
|
|
|
112
112
|
Große textbasierte Werkzeugergebnisse bleiben nicht mehr vollständig im Modellkontext. Ab 12.001 Zeichen speichert BLUN King das vollständige Ergebnis in einer privaten Datei im Sitzungsordner `tool-results`. Im Modellkontext verbleiben die ersten 1.000 und die letzten 1.000 Zeichen, die genaue Zahl der ausgelassenen Zeichen und der `output_path`. Der Agent kann das vollständige Ergebnis anschließend mit `Read` seitenweise über diesen Pfad lesen. Ergebnisse bis einschließlich 12.000 Zeichen, gemischte Medienergebnisse und bereits gekürzte Ergebnisse bleiben unverändert. Auch eine spätere Mikroverdichtung bewahrt den Dateiverweis. Beispiel: Bei einem Suchergebnis mit 30.000 Zeichen sehen folgende Modellanfragen den Anfang und das abschließende Ergebnis oder den Fehler; der vollständige Text bleibt lokal verfügbar.
|
|
113
113
|
|
|
114
|
+
Version 9.1.104 lässt Shell-Befehle im Vordergrund auch bei sehr großen Ausgaben bis zum regulären Ende laufen. King schreibt bis zu 16 MiB fortlaufend in das private Aufgabenprotokoll, verwirft darüber hinausgehende Ausgaben und meldet den tatsächlichen Exit-Code, statt den Prozess wegen der Ausgabemenge zu beenden. Kleine Ausgaben, Hintergrundaufgaben, Zeitgrenzen und manuelle Abbrüche bleiben unverändert.
|
|
115
|
+
|
|
114
116
|
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.
|
|
115
117
|
|
|
116
118
|
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.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const MAX_FOREGROUND_CAPTURE_BYTES = 16 * 1024 * 1024;
|
|
4
|
+
|
|
5
|
+
function utf8PrefixWithinBytes(text, maxBytes) {
|
|
6
|
+
if (maxBytes <= 0 || text.length === 0) return '';
|
|
7
|
+
if (Buffer.byteLength(text, 'utf8') <= maxBytes) return text;
|
|
8
|
+
|
|
9
|
+
let low = 0;
|
|
10
|
+
let high = text.length;
|
|
11
|
+
while (low < high) {
|
|
12
|
+
const middle = Math.ceil((low + high) / 2);
|
|
13
|
+
if (Buffer.byteLength(text.slice(0, middle), 'utf8') <= maxBytes) low = middle;
|
|
14
|
+
else high = middle - 1;
|
|
15
|
+
}
|
|
16
|
+
if (low > 0 && low < text.length) {
|
|
17
|
+
const last = text.charCodeAt(low - 1);
|
|
18
|
+
if (last >= 0xD800 && last <= 0xDBFF) low -= 1;
|
|
19
|
+
}
|
|
20
|
+
return text.slice(0, low);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function captureForegroundOutputChunk(text, capturedBytes, maxBytes = MAX_FOREGROUND_CAPTURE_BYTES) {
|
|
24
|
+
const observedBytes = Buffer.byteLength(text, 'utf8');
|
|
25
|
+
const remainingBytes = Math.max(0, maxBytes - Math.max(0, capturedBytes));
|
|
26
|
+
const capturedText = utf8PrefixWithinBytes(text, remainingBytes);
|
|
27
|
+
const newCapturedBytes = Buffer.byteLength(capturedText, 'utf8');
|
|
28
|
+
return {
|
|
29
|
+
capturedText,
|
|
30
|
+
observedBytes,
|
|
31
|
+
capturedBytes: newCapturedBytes,
|
|
32
|
+
droppedBytes: observedBytes - newCapturedBytes,
|
|
33
|
+
capped: newCapturedBytes < observedBytes,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = {
|
|
38
|
+
MAX_FOREGROUND_CAPTURE_BYTES,
|
|
39
|
+
captureForegroundOutputChunk,
|
|
40
|
+
utf8PrefixWithinBytes,
|
|
41
|
+
};
|
package/blun.mjs
CHANGED
|
@@ -29316,9 +29316,6 @@ function isBackgroundTaskTerminal(status) {
|
|
|
29316
29316
|
return TERMINAL_STATUSES.has(status);
|
|
29317
29317
|
}
|
|
29318
29318
|
/** Terminal `stopReason` recorded when a foreground command trips the output ceiling. */
|
|
29319
|
-
function foregroundOutputLimitReason() {
|
|
29320
|
-
return `Output limit exceeded: the command produced more than ${Math.floor(MAX_FOREGROUND_OUTPUT_BYTES / (1024 * 1024))} MiB and was terminated. Redirect large output to a file (e.g. \`command > out.txt\`) and inspect it in slices instead.`;
|
|
29321
|
-
}
|
|
29322
29319
|
/**
|
|
29323
29320
|
* Generate `{prefix}-{8 base36 chars}`.
|
|
29324
29321
|
*
|
|
@@ -29378,7 +29375,7 @@ function buildBackgroundTaskNotificationBody(info) {
|
|
|
29378
29375
|
"The subagent retains its full prior context across the restart, but any in-flight tool call lost its result and may need to be redone."
|
|
29379
29376
|
].join("\n")}`;
|
|
29380
29377
|
}
|
|
29381
|
-
var MAX_OUTPUT_BYTES$2, NOTIFICATION_FALLBACK_PREVIEW_BYTES,
|
|
29378
|
+
var MAX_OUTPUT_BYTES$2, NOTIFICATION_FALLBACK_PREVIEW_BYTES, MAX_FOREGROUND_CAPTURE_BYTES, captureForegroundOutputChunk, SIGTERM_GRACE_MS$1, USER_INTERRUPT_REASON$1, _ALPHABET, BackgroundManager;
|
|
29382
29379
|
var init_background = __esmMin((() => {
|
|
29383
29380
|
init_dist$4();
|
|
29384
29381
|
init_errors$4();
|
|
@@ -29392,7 +29389,7 @@ var init_background = __esmMin((() => {
|
|
|
29392
29389
|
init_question_task();
|
|
29393
29390
|
MAX_OUTPUT_BYTES$2 = 1024 * 1024;
|
|
29394
29391
|
NOTIFICATION_FALLBACK_PREVIEW_BYTES = 3e3;
|
|
29395
|
-
|
|
29392
|
+
({ MAX_FOREGROUND_CAPTURE_BYTES, captureForegroundOutputChunk } = createRequire(import.meta.url)("./bin/foreground-output-capture-policy.cjs"));
|
|
29396
29393
|
SIGTERM_GRACE_MS$1 = 5e3;
|
|
29397
29394
|
USER_INTERRUPT_REASON$1 = "Interrupted by user";
|
|
29398
29395
|
_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
@@ -29470,7 +29467,8 @@ var init_background = __esmMin((() => {
|
|
|
29470
29467
|
outputChunks: [],
|
|
29471
29468
|
outputRingChars: 0,
|
|
29472
29469
|
outputSizeBytes: 0,
|
|
29473
|
-
|
|
29470
|
+
outputCapturedBytes: 0,
|
|
29471
|
+
outputCaptureCapped: false,
|
|
29474
29472
|
status: "running",
|
|
29475
29473
|
options: entryOptions,
|
|
29476
29474
|
startedAt: Date.now(),
|
|
@@ -29708,27 +29706,32 @@ var init_background = __esmMin((() => {
|
|
|
29708
29706
|
return entry.persistWriteQueue;
|
|
29709
29707
|
}
|
|
29710
29708
|
appendOutput(entry, chunk) {
|
|
29711
|
-
|
|
29712
|
-
|
|
29713
|
-
|
|
29709
|
+
const capture = this.isDetached(entry) ? {
|
|
29710
|
+
capturedText: chunk,
|
|
29711
|
+
observedBytes: Buffer.byteLength(chunk, "utf-8"),
|
|
29712
|
+
capturedBytes: Buffer.byteLength(chunk, "utf-8"),
|
|
29713
|
+
droppedBytes: 0,
|
|
29714
|
+
capped: false
|
|
29715
|
+
} : captureForegroundOutputChunk(chunk, entry.outputCapturedBytes);
|
|
29716
|
+
entry.outputSizeBytes += capture.observedBytes;
|
|
29717
|
+
entry.outputCapturedBytes += capture.capturedBytes;
|
|
29718
|
+
if (capture.capped) entry.outputCaptureCapped = true;
|
|
29719
|
+
if (capture.capturedText.length === 0) return;
|
|
29720
|
+
entry.outputChunks.push(capture.capturedText);
|
|
29721
|
+
entry.outputRingChars += capture.capturedText.length;
|
|
29714
29722
|
while (entry.outputRingChars > MAX_OUTPUT_BYTES$2 && entry.outputChunks.length > 1) {
|
|
29715
29723
|
const removed = entry.outputChunks.shift();
|
|
29716
29724
|
if (removed === void 0) break;
|
|
29717
29725
|
entry.outputRingChars -= removed.length;
|
|
29718
29726
|
}
|
|
29719
|
-
if (!entry.outputLimitTripped && !this.isDetached(entry) && entry.outputSizeBytes > MAX_FOREGROUND_OUTPUT_BYTES) {
|
|
29720
|
-
entry.outputLimitTripped = true;
|
|
29721
|
-
this.stop(entry.taskId, foregroundOutputLimitReason());
|
|
29722
|
-
}
|
|
29723
|
-
if (entry.outputLimitTripped) return;
|
|
29724
29727
|
if (this.persistence === void 0) return;
|
|
29725
29728
|
if (!entry.outputPersistStarted) {
|
|
29726
|
-
entry.pendingOutput.push(
|
|
29727
|
-
entry.pendingOutputBytes +=
|
|
29729
|
+
entry.pendingOutput.push(capture.capturedText);
|
|
29730
|
+
entry.pendingOutputBytes += capture.capturedBytes;
|
|
29728
29731
|
if (entry.pendingOutputBytes > MAX_OUTPUT_BYTES$2) this.startOutputPersist(entry);
|
|
29729
29732
|
return;
|
|
29730
29733
|
}
|
|
29731
|
-
this.appendTaskOutput(entry,
|
|
29734
|
+
this.appendTaskOutput(entry, capture.capturedText);
|
|
29732
29735
|
}
|
|
29733
29736
|
/** Enqueue an `output.log` append, serialized per task. No-op when detached managers omit persistence. */
|
|
29734
29737
|
appendTaskOutput(entry, chunk) {
|
|
@@ -29925,6 +29928,7 @@ var init_background = __esmMin((() => {
|
|
|
29925
29928
|
endedAt: entry.endedAt,
|
|
29926
29929
|
stopReason: entry.stopReason,
|
|
29927
29930
|
terminalNotificationSuppressed: entry.terminalNotificationSuppressed,
|
|
29931
|
+
outputCaptureCapped: entry.outputCaptureCapped,
|
|
29928
29932
|
timeoutMs: entry.options.timeoutMs
|
|
29929
29933
|
};
|
|
29930
29934
|
return entry.task.toInfo(base);
|
|
@@ -262142,7 +262146,7 @@ var init_bash = __esmMin((() => {
|
|
|
262142
262146
|
MAX_TIMEOUT_S,
|
|
262143
262147
|
MAX_BACKGROUND_TIMEOUT_S
|
|
262144
262148
|
};
|
|
262145
|
-
bash_default = "Execute a `{{ SHELL_NAME }}` command for pipes, environment variables, processes, git, package managers, build or test runners, and other genuine shell semantics.\n\nPrefer the dedicated tools when they fit: `Read` for a known file, `Write` to create or replace a file, `Edit` for exact changes, `Glob` to locate files, and `Grep` to search contents. Their output is bounded and their permissions are clearer.\n\nStdout and stderr are combined. Long output
|
|
262149
|
+
bash_default = "Execute a `{{ SHELL_NAME }}` command for pipes, environment variables, processes, git, package managers, build or test runners, and other genuine shell semantics.\n\nPrefer the dedicated tools when they fit: `Read` for a known file, `Write` to create or replace a file, `Edit` for exact changes, `Glob` to locate files, and `Grep` to search contents. Their output is bounded and their permissions are clearer.\n\nStdout and stderr are combined. Long foreground output is streamed to a private file; capture stops at a safe size while the command continues to its real exit code. A non-zero command ends with its exit code; timeouts and user interrupts are reported separately.\n\nEach call runs in a fresh shell environment. Variables, `cd`, and shell history do not carry into later calls; pass `cwd` or use absolute paths. Foreground commands default to {{ DEFAULT_TIMEOUT_S }}s and allow up to {{ MAX_TIMEOUT_S }}s through `timeout`. Do not run interactive commands or commands that may run forever in the foreground.\n\nWith `run_in_background=true`, provide a short `description`; the tool returns a task ID and notifies you on completion. Background tasks default to {{ DEFAULT_BACKGROUND_TIMEOUT_S }}s and allow up to {{ MAX_BACKGROUND_TIMEOUT_S }}s. Use `disable_timeout=true` only when no deadline is appropriate. Use `TaskOutput` for a status or output snapshot and `TaskStop` only to cancel. After launch, normally return control instead of immediately waiting.\n\nQuote paths containing spaces. Chain dependent commands with `&&`; issue independent read-only checks as parallel tool calls. Use `;`, `||`, pipes, redirects, and shell control flow when their semantics are required.\n\nStay inside the working directory unless the user explicitly requests otherwise. Avoid `..`, and never require superuser privileges without explicit instruction. Command availability depends on the host; verify unfamiliar commands before relying on them.";
|
|
262146
262150
|
BashTool = class {
|
|
262147
262151
|
kaos;
|
|
262148
262152
|
cwd;
|
|
@@ -262308,8 +262312,10 @@ var init_bash = __esmMin((() => {
|
|
|
262308
262312
|
if (!result.truncated) return result;
|
|
262309
262313
|
const output = await this.backgroundManager.getOutputSnapshot(taskId, 0);
|
|
262310
262314
|
if (!output.fullOutputAvailable || output.outputPath === void 0) return result;
|
|
262315
|
+
const captureCapped = this.backgroundManager.getTask(taskId)?.outputCaptureCapped === true;
|
|
262311
262316
|
const taskOutputHint = this.allowBackground ? `, or TaskOutput(task_id="${taskId}", block=false)` : "";
|
|
262312
|
-
const
|
|
262317
|
+
const captureNotice = captureCapped ? `\n[Capture capped at ${String(MAX_FOREGROUND_CAPTURE_BYTES)} bytes. Additional output was discarded, but the command continued to its real exit code.]` : "";
|
|
262318
|
+
const reference = `\n\n[Full output saved]\ntask_id: ${taskId}\noutput_path: ${output.outputPath}\noutput_size_bytes: ${String(output.outputSizeBytes)}${captureNotice}\nnext_step: Use Read with output_path to page through the full log${taskOutputHint}.`;
|
|
262313
262319
|
return {
|
|
262314
262320
|
...result,
|
|
262315
262321
|
output: `${result.output}${reference}`
|