blun-king-cli 9.1.83 → 9.1.85

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 CHANGED
@@ -9,7 +9,7 @@ Installation
9
9
  ------------
10
10
  Die geprüfte Version exakt global installieren:
11
11
 
12
- npm install -g blun-king-cli@9.1.83
12
+ npm install -g blun-king-cli@9.1.85
13
13
 
14
14
  Start
15
15
  -----
@@ -80,7 +80,7 @@ Dabei werden keine gespeicherten Nachrichten geändert oder gelöscht. Fortsetze
80
80
 
81
81
  ## Große Werkzeugausgaben und isolierte Teilagenten
82
82
 
83
- Werkzeugausgaben mit mehr als 50.000 Zeichen werden vollständig unter `<agent-home>/tool-results/` gespeichert. Im Modellkontext bleiben nur eine Vorschau der ersten 2.000 Zeichen, der genaue `output_path` und der Hinweis, die Datei bei Bedarf mit `Read` zu öffnen. Dadurch bleibt die vollständige Ausgabe wiederauffindbar, ohne in jedem weiteren Modellschritt erneut als großer Textblock mitzufahren.
83
+ 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 eine Vorschau mit 2.000 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 enthalten die folgenden Modellanfragen nur noch die Vorschau und den lesbaren Pfad; der vollständige Text bleibt lokal verfügbar.
84
84
 
85
85
  Das Telemetrieereignis `tool_result_offloaded` enthält ausschließlich `tool_name`, `output_size_chars`, `output_size_bytes` und `preview_size_chars`. Es enthält weder den Inhalt noch den Speicherpfad. Beispiel: Eine Ausgabe mit 80.000 Zeichen erzeugt eine Vorschau mit 2.000 Zeichen; die Telemetrie zeigt die Größenersparnis, ohne Nutzdaten zu protokollieren.
86
86
 
@@ -227,6 +227,13 @@ sodass auch kurze Schritte wie Rendern und Speichern in der Produktionskette
227
227
  sichtbar sind. Aktualisierte Vorschaubilder werden erneuert; Medienpfade und
228
228
  Webadressen sind als Terminalverweise anklickbar.
229
229
 
230
+ Gestufte Verdichtung für große Sitzungen
231
+ -----------------------------------------
232
+
233
+ Eine Vollverdichtung verwendet jetzt pro Zusammenfassungsstufe höchstens 64.000 geschätzte Eingabe-Token als Zielwert. Die feste Sicherheitsgrenze des aktiven Modells bleibt unverändert. King teilt den älteren Verlauf an gültigen Nachrichtengrenzen, fasst jeden chronologischen Abschnitt zusammen und übernimmt diese Zusammenfassung in die nächste Stufe. Dabei wird kein noch nicht zusammengefasster Verlauf verworfen. Ist eine einzelne unteilbare Nachricht größer als der Stufenzielwert, bleibt die bestehende feste Sicherheitsgrenze der Rückfallweg.
234
+
235
+ Beispiel: Ein auf 256.000 Token geschätzter Verdichtungsauftrag wird in mehreren kleineren Stufen verarbeitet, statt als eine einzige große Anbieteranfrage. Die genaue Stufenzahl hängt von den Nachrichtengrenzen und den erzeugten Zwischenzusammenfassungen ab. Der Protokolleintrag `compaction stage request` nennt `targetInputTokens`; das Telemetrieereignis `compaction_finished` nennt `stage_count`. Das private Verlaufsarchiv und der ursprüngliche Sitzungs-Wire bleiben vollständig.
236
+
230
237
  Wiederauffindbarer Verdichtungsverlauf
231
238
  --------------------------------------
232
239
 
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.83
12
+ npm install -g blun-king-cli@9.1.85
13
13
  ```
14
14
 
15
15
  ## Reproduzierbares Staging und Packen
@@ -102,7 +102,7 @@ Dabei werden keine gespeicherten Nachrichten geändert oder gelöscht. Fortsetze
102
102
 
103
103
  ## Große Werkzeugausgaben und isolierte Teilagenten
104
104
 
105
- Werkzeugausgaben mit mehr als 50.000 Zeichen werden vollständig unter `<agent-home>/tool-results/` gespeichert. Im Modellkontext bleiben nur eine Vorschau der ersten 2.000 Zeichen, der genaue `output_path` und der Hinweis, die Datei bei Bedarf mit `Read` zu öffnen. Dadurch bleibt die vollständige Ausgabe wiederauffindbar, ohne in jedem weiteren Modellschritt erneut als großer Textblock mitzufahren.
105
+ 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 eine Vorschau mit 2.000 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 enthalten die folgenden Modellanfragen nur noch die Vorschau und den lesbaren Pfad; der vollständige Text bleibt lokal verfügbar.
106
106
 
107
107
  Das Telemetrieereignis `tool_result_offloaded` enthält ausschließlich `tool_name`, `output_size_chars`, `output_size_bytes` und `preview_size_chars`. Es enthält weder den Inhalt noch den Speicherpfad. Beispiel: Eine Ausgabe mit 80.000 Zeichen erzeugt eine Vorschau mit 2.000 Zeichen; die Telemetrie zeigt die Größenersparnis, ohne Nutzdaten zu protokollieren.
108
108
 
@@ -255,6 +255,12 @@ sodass auch kurze Schritte wie Rendern und Speichern in der Produktionskette
255
255
  sichtbar sind. Aktualisierte Vorschaubilder werden erneuert; Medienpfade und
256
256
  Webadressen sind als Terminalverweise anklickbar.
257
257
 
258
+ ## Gestufte Verdichtung für große Sitzungen
259
+
260
+ Eine Vollverdichtung verwendet jetzt pro Zusammenfassungsstufe höchstens 64.000 geschätzte Eingabe-Token als Zielwert. Die feste Sicherheitsgrenze des aktiven Modells bleibt unverändert. King teilt den älteren Verlauf an gültigen Nachrichtengrenzen, fasst jeden chronologischen Abschnitt zusammen und übernimmt diese Zusammenfassung in die nächste Stufe. Dabei wird kein noch nicht zusammengefasster Verlauf verworfen. Ist eine einzelne unteilbare Nachricht größer als der Stufenzielwert, bleibt die bestehende feste Sicherheitsgrenze der Rückfallweg.
261
+
262
+ Beispiel: Ein auf 256.000 Token geschätzter Verdichtungsauftrag wird in mehreren kleineren Stufen verarbeitet, statt als eine einzige große Anbieteranfrage. Die genaue Stufenzahl hängt von den Nachrichtengrenzen und den erzeugten Zwischenzusammenfassungen ab. Der Protokolleintrag `compaction stage request` nennt `targetInputTokens`; das Telemetrieereignis `compaction_finished` nennt `stage_count`. Das private Verlaufsarchiv und der ursprüngliche Sitzungs-Wire bleiben vollständig.
263
+
258
264
  ## Wiederauffindbarer Verdichtungsverlauf
259
265
 
260
266
  Bevor eine erfolgreiche Vollverdichtung ältere Nachrichten ersetzt, schreibt King den verdrängten Verlauf in ein privates Markdown-Archiv unter `~/.blun/conversation-history/`. Die Verdichtungszusammenfassung enthält den genauen `history_path`, sodass der Agent mit `Read` Einzelheiten wiederfinden kann, die nicht in der Zusammenfassung stehen.
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ const DEFAULT_COMPACTION_STAGE_MAX_TOKENS = 64_000;
4
+
5
+ function capCompactionStageTarget(safeRequestLimitTokens) {
6
+ if (!Number.isFinite(safeRequestLimitTokens) || safeRequestLimitTokens <= 0) return 0;
7
+ return Math.min(Math.floor(safeRequestLimitTokens), DEFAULT_COMPACTION_STAGE_MAX_TOKENS);
8
+ }
9
+
10
+ module.exports = {
11
+ DEFAULT_COMPACTION_STAGE_MAX_TOKENS,
12
+ capCompactionStageTarget,
13
+ };
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+
3
+ const TOOL_RESULT_MAX_CHARS = 12_000;
4
+ const TOOL_RESULT_PREVIEW_CHARS = 2_000;
5
+ const TOOL_RESULT_OFFLOAD_MARKER = '[Tool result offloaded]';
6
+
7
+ function shouldOffloadToolResult(textLength) {
8
+ return Number.isFinite(textLength) && textLength > TOOL_RESULT_MAX_CHARS;
9
+ }
10
+
11
+ function isPersistedToolResultReference(content) {
12
+ if (!Array.isArray(content)) return false;
13
+
14
+ return content.some((part) => {
15
+ if (part?.type !== 'text' || typeof part.text !== 'string') return false;
16
+ if (!part.text.includes('\noutput_path: ')) return false;
17
+ return part.text.startsWith(`${TOOL_RESULT_OFFLOAD_MARKER}\n`)
18
+ || /^Tool output exceeded \d+ characters; showing a preview only\.\n/u.test(part.text);
19
+ });
20
+ }
21
+
22
+ module.exports = {
23
+ TOOL_RESULT_MAX_CHARS,
24
+ TOOL_RESULT_PREVIEW_CHARS,
25
+ TOOL_RESULT_OFFLOAD_MARKER,
26
+ isPersistedToolResultReference,
27
+ shouldOffloadToolResult,
28
+ };
package/blun.mjs CHANGED
@@ -75237,9 +75237,10 @@ function extractCompactionSummary(response) {
75237
75237
  if (summary.trim().length === 0) throw new APIEmptyResponseError("The compaction response did not contain a non-empty summary.");
75238
75238
  return summary;
75239
75239
  }
75240
- var archiveCompactionHistory, buildCompactionArchiveNotice, DEFAULT_COMPACTION_MAX_COMPLETION_TOKENS, COMPACTION_THINKING_EFFORT, COMPACTION_SUMMARY_RESERVE_RATIO, MAX_HIERARCHICAL_COMPACTION_PASSES, HIERARCHICAL_COMPACTION_PREFIX, CompactionTruncatedError, CompactionStallError, COMPACTION_STALL_MEASUREMENT_MULTIPLIER, REBUILT_AFTER_COMPACTION_INJECTION_VARIANTS, FullCompaction, MAX_COMPACTION_OVERFLOW_SHRINK_ATTEMPTS, COMPACTION_OVERFLOW_SHRINK_RATIOS;
75240
+ var archiveCompactionHistory, buildCompactionArchiveNotice, capCompactionStageTarget, DEFAULT_COMPACTION_MAX_COMPLETION_TOKENS, COMPACTION_THINKING_EFFORT, COMPACTION_SUMMARY_RESERVE_RATIO, MAX_HIERARCHICAL_COMPACTION_PASSES, HIERARCHICAL_COMPACTION_PREFIX, CompactionTruncatedError, CompactionStallError, COMPACTION_STALL_MEASUREMENT_MULTIPLIER, REBUILT_AFTER_COMPACTION_INJECTION_VARIANTS, FullCompaction, MAX_COMPACTION_OVERFLOW_SHRINK_ATTEMPTS, COMPACTION_OVERFLOW_SHRINK_RATIOS;
75241
75241
  var init_full = __esmMin((() => {
75242
75242
  ({ archiveCompactionHistory, buildCompactionArchiveNotice } = createRequire(import.meta.url)("./bin/compaction-history-archive.cjs"));
75243
+ ({ capCompactionStageTarget } = createRequire(import.meta.url)("./bin/compaction-stage-policy.cjs"));
75243
75244
  init_errors$8();
75244
75245
  init_src$4();
75245
75246
  init_errors$4();
@@ -75578,14 +75579,15 @@ var init_full = __esmMin((() => {
75578
75579
  while (true) {
75579
75580
  const compactionRequestLimit = this.getEffectiveMaxContextTokens();
75580
75581
  const safeCompactionRequestLimit = compactionRequestLimit > 0 ? Math.max(1, Math.floor(compactionRequestLimit * (1 - COMPACTION_SUMMARY_RESERVE_RATIO))) : compactionRequestLimit;
75582
+ const targetCompactionRequestLimit = capCompactionStageTarget(safeCompactionRequestLimit);
75581
75583
  let messages = buildRequestMessages(historyForModel, instruction);
75582
75584
  let estimatedCompactionRequestTokens = this.estimateRequestTokens(messages, this.agent.effectiveSystemPrompt, compactionTools);
75583
75585
  initialCompactionRequestTokens ??= estimatedCompactionRequestTokens;
75584
75586
  let hierarchicalChunkEnd;
75585
- if (safeCompactionRequestLimit > 0 && estimatedCompactionRequestTokens >= safeCompactionRequestLimit) {
75587
+ if (targetCompactionRequestLimit > 0 && estimatedCompactionRequestTokens >= targetCompactionRequestLimit) {
75586
75588
  if (historyForModel.length > 1) {
75587
75589
  const chunkInstruction = `${instruction}\n\nThis request contains only the oldest chronological segment. Summarize every fact needed by a later merge pass. Do not assume later messages are visible.`;
75588
- const chunk = selectHierarchicalCompactionChunk(historyForModel, safeCompactionRequestLimit, safeCompactionRequestLimit, (candidate) => {
75590
+ const chunk = selectHierarchicalCompactionChunk(historyForModel, targetCompactionRequestLimit, safeCompactionRequestLimit, (candidate) => {
75589
75591
  const candidateMessages = buildRequestMessages(candidate, chunkInstruction);
75590
75592
  return {
75591
75593
  messages: candidateMessages,
@@ -75598,7 +75600,7 @@ var init_full = __esmMin((() => {
75598
75600
  estimatedCompactionRequestTokens = chunk.estimatedTokens;
75599
75601
  }
75600
75602
  }
75601
- if (hierarchicalChunkEnd === void 0) throw new BlunError(ErrorCodes.CONTEXT_OVERFLOW, `Compaction stopped before upload: the conversation (${String(tokensBefore)} tokens) could not be divided into a request below the active model window (${String(compactionRequestLimit)} tokens).`, { details: {
75603
+ if (hierarchicalChunkEnd === void 0 && estimatedCompactionRequestTokens >= safeCompactionRequestLimit) throw new BlunError(ErrorCodes.CONTEXT_OVERFLOW, `Compaction stopped before upload: the conversation (${String(tokensBefore)} tokens) could not be divided into a request below the active model window (${String(compactionRequestLimit)} tokens).`, { details: {
75602
75604
  contextBrakeBlocked: true,
75603
75605
  estimatedRequestTokens: estimatedCompactionRequestTokens,
75604
75606
  maxContextTokens: compactionRequestLimit,
@@ -75623,6 +75625,7 @@ var init_full = __esmMin((() => {
75623
75625
  activeContextTokens: this.estimateProjectedRequestTokens(),
75624
75626
  estimatedInputTokens: estimatedCompactionRequestTokens,
75625
75627
  windowUsagePercent,
75628
+ targetInputTokens: targetCompactionRequestLimit,
75626
75629
  safeInputLimitTokens: safeCompactionRequestLimit,
75627
75630
  maxContextTokens: compactionRequestLimit
75628
75631
  });
@@ -75809,6 +75812,7 @@ var init_full = __esmMin((() => {
75809
75812
  retry_count: retryCount,
75810
75813
  round: 1,
75811
75814
  thinking_effort: COMPACTION_THINKING_EFFORT,
75815
+ stage_count: hierarchicalPassCount + 1,
75812
75816
  ...usage === null ? {} : {
75813
75817
  input_tokens: inputTotal(usage),
75814
75818
  output_tokens: usage.output
@@ -75907,9 +75911,10 @@ var init_full = __esmMin((() => {
75907
75911
  }));
75908
75912
  //#endregion
75909
75913
  //#region ../../packages/agent-core/src/agent/compaction/micro.ts
75910
- var selectMicroCompactionCutoff, DEFAULT_CONFIG, MicroCompaction;
75914
+ var selectMicroCompactionCutoff, isPersistedToolResultReference, DEFAULT_CONFIG, MicroCompaction;
75911
75915
  var init_micro = __esmMin((() => {
75912
75916
  ({ selectMicroCompactionCutoff } = createRequire(import.meta.url)("./bin/micro-compaction-policy.cjs"));
75917
+ ({ isPersistedToolResultReference } = createRequire(import.meta.url)("./bin/tool-result-offload-policy.cjs"));
75913
75918
  init_tokens();
75914
75919
  DEFAULT_CONFIG = {
75915
75920
  keepRecentMessages: 20,
@@ -75996,7 +76001,7 @@ var init_micro = __esmMin((() => {
75996
76001
  const result = [];
75997
76002
  let i = 0;
75998
76003
  for (const msg of messages) {
75999
- if (i < this.cutoff && msg.role === "tool" && msg.toolCallId !== void 0 && estimateTokensForContentParts(msg.content) >= config.minContentTokens) result.push({
76004
+ if (i < this.cutoff && msg.role === "tool" && msg.toolCallId !== void 0 && !isPersistedToolResultReference(msg.content) && estimateTokensForContentParts(msg.content) >= config.minContentTokens) result.push({
76000
76005
  ...msg,
76001
76006
  content: [{
76002
76007
  type: "text",
@@ -76041,7 +76046,7 @@ var init_micro = __esmMin((() => {
76041
76046
  const serializedArgumentsMarker = JSON.stringify({ _blun_compacted: this.config.truncatedArgumentsMarker });
76042
76047
  for (let i = 0; i < messages.length && i < cutoff; i++) {
76043
76048
  const message = messages[i];
76044
- if (message?.role === "tool" && message.toolCallId !== void 0) {
76049
+ if (message?.role === "tool" && message.toolCallId !== void 0 && !isPersistedToolResultReference(message.content)) {
76045
76050
  const contentTokens = estimateTokensForContentParts(message.content);
76046
76051
  if (contentTokens >= this.config.minContentTokens) {
76047
76052
  markerTokenCount ??= estimateTokensForContentParts([{
@@ -259957,7 +259962,7 @@ var init_tool_dedup = __esmMin((() => {
259957
259962
  //#region ../../packages/agent-core/src/agent/turn/tool-result-budget.ts
259958
259963
  async function budgetToolResultForModel(options) {
259959
259964
  const text = persistableToolResultText(options.result.output);
259960
- if (text === void 0 || text.length <= TOOL_RESULT_MAX_CHARS) return options.result;
259965
+ if (text === void 0 || !shouldOffloadToolResult(text.length)) return options.result;
259961
259966
  if (options.result.truncated === true) return options.result;
259962
259967
  if (options.homedir === void 0) return options.result;
259963
259968
  const outputPath = await saveToolResult({
@@ -259996,7 +260001,8 @@ async function saveToolResult(options, text) {
259996
260001
  const outputPath = join$4(dir, `${safeToolResultFileStem(options.toolName, options.toolCallId)}-${randomUUID()}.txt`);
259997
260002
  await writeFile(outputPath, text, {
259998
260003
  encoding: "utf8",
259999
- flag: "wx"
260004
+ flag: "wx",
260005
+ mode: 384
260000
260006
  });
260001
260007
  return outputPath;
260002
260008
  } catch {
@@ -260005,6 +260011,7 @@ async function saveToolResult(options, text) {
260005
260011
  }
260006
260012
  function renderPersistedToolResult(toolName, toolCallId, text, outputPath) {
260007
260013
  const lines = [
260014
+ TOOL_RESULT_OFFLOAD_MARKER,
260008
260015
  `Tool output exceeded ${String(TOOL_RESULT_MAX_CHARS)} characters; showing a preview only.`,
260009
260016
  `tool_name: ${toolName}`,
260010
260017
  `tool_call_id: ${toolCallId}`,
@@ -260019,12 +260026,15 @@ function renderPersistedToolResult(toolName, toolCallId, text, outputPath) {
260019
260026
  function safeToolResultFileStem(toolName, toolCallId) {
260020
260027
  return `${toolName}-${toolCallId}`.replace(/[^a-zA-Z0-9._-]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 80) || "tool-result";
260021
260028
  }
260022
- var TOOL_RESULT_MAX_CHARS, TOOL_RESULT_PREVIEW_CHARS, buildToolResultOffloadTelemetry;
260029
+ var TOOL_RESULT_MAX_CHARS, TOOL_RESULT_PREVIEW_CHARS, TOOL_RESULT_OFFLOAD_MARKER, shouldOffloadToolResult, buildToolResultOffloadTelemetry;
260023
260030
  var init_tool_result_budget = __esmMin((() => {
260024
260031
  init_dist$6();
260032
+ const toolResultOffloadPolicy = createRequire(import.meta.url)("./bin/tool-result-offload-policy.cjs");
260025
260033
  ({ buildToolResultOffloadTelemetry } = createRequire(import.meta.url)("./bin/tool-result-offload-telemetry.cjs"));
260026
- TOOL_RESULT_MAX_CHARS = 5e4;
260027
- TOOL_RESULT_PREVIEW_CHARS = 2e3;
260034
+ TOOL_RESULT_MAX_CHARS = toolResultOffloadPolicy.TOOL_RESULT_MAX_CHARS;
260035
+ TOOL_RESULT_PREVIEW_CHARS = toolResultOffloadPolicy.TOOL_RESULT_PREVIEW_CHARS;
260036
+ TOOL_RESULT_OFFLOAD_MARKER = toolResultOffloadPolicy.TOOL_RESULT_OFFLOAD_MARKER;
260037
+ shouldOffloadToolResult = toolResultOffloadPolicy.shouldOffloadToolResult;
260028
260038
  }));
260029
260039
  //#endregion
260030
260040
  //#region ../../packages/agent-core/src/agent/turn/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.83",
3
+ "version": "9.1.85",
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": {