blun-king-cli 9.1.82 → 9.1.83

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.82
12
+ npm install -g blun-king-cli@9.1.83
13
13
 
14
14
  Start
15
15
  -----
@@ -74,17 +74,9 @@ doppelten Namen bleiben unverändert.
74
74
 
75
75
  Kontextentlastung bei langen Sitzungen
76
76
  --------------------------------------
77
- King bewahrt den vollständigen Verlauf weiterhin im Sitzungs-Wire auf. Erreicht
78
- der aktive Verlauf 75 Prozent des Modellfensters, ersetzt die Modellprojektion
79
- ältere große Werkzeugergebnisse durch einen kurzen Platzhalter. Die letzten 20
80
- Nachrichten bleiben unverändert. Solange der Prefix-Cache warm ist, wird der
81
- Schnitt höchstens nach jeweils 20 weiteren Nachrichten verschoben. Nach einer
82
- Stunde ohne Modellantwort darf er sofort nachziehen.
83
-
84
- Dabei werden keine gespeicherten Nachrichten geändert oder gelöscht. Fortsetzen,
85
- Exportieren und die sichtbare Historie behalten die ursprünglichen
86
- Werkzeugergebnisse. Das Telemetrieereignis `micro_compaction_finished` nennt den
87
- Auslöser, den Schnitt und die geschätzte Tokenzahl vor und nach der Entlastung.
77
+ King bewahrt den vollständigen Verlauf weiterhin im Sitzungs-Wire auf. Erreicht der aktive Verlauf 75 Prozent des Modellfensters, ersetzt die Modellprojektion ältere große Werkzeugergebnisse sowie große Argumente abgeschlossener Werkzeugaufrufe durch kurze Platzhalter. Werkzeugargumente werden nur entlastet, wenn ein zugehöriges Werkzeugergebnis vorliegt und die gespeicherten Argumente gültiges JSON sind. Die letzten 20 Nachrichten bleiben unverändert. Solange der Prefix-Cache warm ist, wird der Schnitt höchstens nach jeweils 20 weiteren Nachrichten verschoben. Nach einer Stunde ohne Modellantwort darf er sofort nachziehen.
78
+
79
+ Dabei werden keine gespeicherten Nachrichten geändert oder gelöscht. Fortsetzen, Exportieren und die sichtbare Historie behalten die ursprünglichen Werkzeugergebnisse und Werkzeugargumente. Das Telemetrieereignis `micro_compaction_finished` nennt den Auslöser, den Schnitt und die geschätzte Tokenzahl vor und nach der Entlastung. Außerdem zählt es getrennt, wie viele Werkzeugergebnisse und Werkzeugargumente entlastet wurden. Der Sitzungsinspektor summiert zusätzlich die eingesparten Argument-Token, ohne Inhalte offenzulegen. Beispiel: Ein früherer `Write`-Aufruf mit einem vollständigen Dateiinhalt bleibt im Wire erhalten; die Modellprojektion trägt nur noch einen Platzhalter, sobald für diesen `Write`-Aufruf ein zugehöriges Ergebnis vorliegt.
88
80
 
89
81
  ## Große Werkzeugausgaben und isolierte Teilagenten
90
82
 
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.82
12
+ npm install -g blun-king-cli@9.1.83
13
13
  ```
14
14
 
15
15
  ## Reproduzierbares Staging und Packen
@@ -96,17 +96,9 @@ doppelten Namen bleiben unverändert.
96
96
 
97
97
  ## Kontextentlastung bei langen Sitzungen
98
98
 
99
- King bewahrt den vollständigen Verlauf weiterhin im Sitzungs-Wire auf. Erreicht
100
- der aktive Verlauf 75 Prozent des Modellfensters, ersetzt die Modellprojektion
101
- ältere große Werkzeugergebnisse durch einen kurzen Platzhalter. Die letzten 20
102
- Nachrichten bleiben unverändert. Solange der Prefix-Cache warm ist, wird der
103
- Schnitt höchstens nach jeweils 20 weiteren Nachrichten verschoben. Nach einer
104
- Stunde ohne Modellantwort darf er sofort nachziehen.
105
-
106
- Dabei werden keine gespeicherten Nachrichten geändert oder gelöscht. Fortsetzen,
107
- Exportieren und die sichtbare Historie behalten die ursprünglichen
108
- Werkzeugergebnisse. Das Telemetrieereignis `micro_compaction_finished` nennt den
109
- Auslöser, den Schnitt und die geschätzte Tokenzahl vor und nach der Entlastung.
99
+ King bewahrt den vollständigen Verlauf weiterhin im Sitzungs-Wire auf. Erreicht der aktive Verlauf 75 Prozent des Modellfensters, ersetzt die Modellprojektion ältere große Werkzeugergebnisse sowie große Argumente abgeschlossener Werkzeugaufrufe durch kurze Platzhalter. Werkzeugargumente werden nur entlastet, wenn ein zugehöriges Werkzeugergebnis vorliegt und die gespeicherten Argumente gültiges JSON sind. Die letzten 20 Nachrichten bleiben unverändert. Solange der Prefix-Cache warm ist, wird der Schnitt höchstens nach jeweils 20 weiteren Nachrichten verschoben. Nach einer Stunde ohne Modellantwort darf er sofort nachziehen.
100
+
101
+ Dabei werden keine gespeicherten Nachrichten geändert oder gelöscht. Fortsetzen, Exportieren und die sichtbare Historie behalten die ursprünglichen Werkzeugergebnisse und Werkzeugargumente. Das Telemetrieereignis `micro_compaction_finished` nennt den Auslöser, den Schnitt und die geschätzte Tokenzahl vor und nach der Entlastung. Außerdem zählt es getrennt, wie viele Werkzeugergebnisse und Werkzeugargumente entlastet wurden. Der Sitzungsinspektor summiert zusätzlich die eingesparten Argument-Token, ohne Inhalte offenzulegen. Beispiel: Ein früherer `Write`-Aufruf mit einem vollständigen Dateiinhalt bleibt im Wire erhalten; die Modellprojektion trägt nur noch einen Platzhalter, sobald für diesen `Write`-Aufruf ein zugehöriges Ergebnis vorliegt.
110
102
 
111
103
  ## Große Werkzeugausgaben und isolierte Teilagenten
112
104
 
package/blun.mjs CHANGED
@@ -75916,6 +75916,7 @@ var init_micro = __esmMin((() => {
75916
75916
  minContentTokens: 100,
75917
75917
  cacheMissedThresholdMs: 3600 * 1e3,
75918
75918
  truncatedMarker: "[Old tool result content cleared]",
75919
+ truncatedArgumentsMarker: "[Old tool call arguments cleared]",
75919
75920
  minContextUsageRatio: .5
75920
75921
  };
75921
75922
  MicroCompaction = class {
@@ -75959,22 +75960,26 @@ var init_micro = __esmMin((() => {
75959
75960
  const previousCutoff = this.cutoff;
75960
75961
  const effect = this.measureEffect(history, selection.cutoff);
75961
75962
  const previousEffect = this.measureEffect(history, previousCutoff);
75962
- if (effect.truncatedToolResultCount <= previousEffect.truncatedToolResultCount) return;
75963
+ if (effect.truncatedToolResultCount <= previousEffect.truncatedToolResultCount && effect.truncatedToolArgumentCount <= previousEffect.truncatedToolArgumentCount) return;
75963
75964
  this.apply(selection.cutoff);
75964
75965
  const rawContextTokens = estimateTokensForMessages(history);
75965
- const tokensBefore = rawContextTokens - previousEffect.truncatedToolResultTokensBefore + previousEffect.truncatedToolResultTokensAfter;
75966
- const tokensAfter = rawContextTokens - effect.truncatedToolResultTokensBefore + effect.truncatedToolResultTokensAfter;
75966
+ const tokensBefore = rawContextTokens - previousEffect.truncatedToolResultTokensBefore + previousEffect.truncatedToolResultTokensAfter - previousEffect.truncatedToolArgumentTokensBefore + previousEffect.truncatedToolArgumentTokensAfter;
75967
+ const tokensAfter = rawContextTokens - effect.truncatedToolResultTokensBefore + effect.truncatedToolResultTokensAfter - effect.truncatedToolArgumentTokensBefore + effect.truncatedToolArgumentTokensAfter;
75967
75968
  this.agent.telemetry.track("micro_compaction_finished", {
75968
75969
  trigger: selection.trigger,
75969
75970
  keep_recent_messages: config.keepRecentMessages,
75970
75971
  min_content_tokens: config.minContentTokens,
75971
75972
  cache_missed_threshold_ms: config.cacheMissedThresholdMs,
75972
75973
  truncated_marker: config.truncatedMarker,
75974
+ truncated_arguments_marker: config.truncatedArgumentsMarker,
75973
75975
  min_context_usage_ratio: config.minContextUsageRatio,
75974
75976
  context_usage_ratio: selection.contextUsageRatio,
75975
75977
  truncated_tool_result_count: effect.truncatedToolResultCount,
75976
75978
  truncated_tool_result_tokens_before: effect.truncatedToolResultTokensBefore,
75977
75979
  truncated_tool_result_tokens_after: effect.truncatedToolResultTokensAfter,
75980
+ truncated_tool_argument_count: effect.truncatedToolArgumentCount,
75981
+ truncated_tool_argument_tokens_before: effect.truncatedToolArgumentTokensBefore,
75982
+ truncated_tool_argument_tokens_after: effect.truncatedToolArgumentTokensAfter,
75978
75983
  tokens_before: tokensBefore,
75979
75984
  tokens_after: tokensAfter,
75980
75985
  previous_cutoff: previousCutoff,
@@ -75986,6 +75991,8 @@ var init_micro = __esmMin((() => {
75986
75991
  }
75987
75992
  compact(messages) {
75988
75993
  const config = this.config;
75994
+ const completedToolCallIds = new Set(messages.filter((message) => message?.role === "tool" && message.toolCallId !== void 0).map((message) => message.toolCallId));
75995
+ const serializedArgumentsMarker = JSON.stringify({ _blun_compacted: config.truncatedArgumentsMarker });
75989
75996
  const result = [];
75990
75997
  let i = 0;
75991
75998
  for (const msg of messages) {
@@ -75996,6 +76003,26 @@ var init_micro = __esmMin((() => {
75996
76003
  text: config.truncatedMarker
75997
76004
  }]
75998
76005
  });
76006
+ else if (i < this.cutoff && msg.role === "assistant" && Array.isArray(msg.toolCalls)) {
76007
+ let changed = false;
76008
+ const toolCalls = msg.toolCalls.map((call) => {
76009
+ if (!completedToolCallIds.has(call.id) || typeof call.arguments !== "string" || this.toolArgumentTokens(call.arguments) < config.minContentTokens) return call;
76010
+ try {
76011
+ JSON.parse(call.arguments);
76012
+ } catch {
76013
+ return call;
76014
+ }
76015
+ changed = true;
76016
+ return {
76017
+ ...call,
76018
+ arguments: serializedArgumentsMarker
76019
+ };
76020
+ });
76021
+ result.push(changed ? {
76022
+ ...msg,
76023
+ toolCalls
76024
+ } : msg);
76025
+ }
75999
76026
  else result.push(msg);
76000
76027
  i++;
76001
76028
  }
@@ -76003,28 +76030,70 @@ var init_micro = __esmMin((() => {
76003
76030
  }
76004
76031
  measureEffect(messages, cutoff) {
76005
76032
  let markerTokenCount;
76033
+ let argumentsMarkerTokenCount;
76006
76034
  let truncatedToolResultCount = 0;
76007
76035
  let truncatedToolResultTokensBefore = 0;
76008
76036
  let truncatedToolResultTokensAfter = 0;
76037
+ let truncatedToolArgumentCount = 0;
76038
+ let truncatedToolArgumentTokensBefore = 0;
76039
+ let truncatedToolArgumentTokensAfter = 0;
76040
+ const completedToolCallIds = new Set(messages.filter((message) => message?.role === "tool" && message.toolCallId !== void 0).map((message) => message.toolCallId));
76041
+ const serializedArgumentsMarker = JSON.stringify({ _blun_compacted: this.config.truncatedArgumentsMarker });
76009
76042
  for (let i = 0; i < messages.length && i < cutoff; i++) {
76010
76043
  const message = messages[i];
76011
- if (message?.role !== "tool" || message.toolCallId === void 0) continue;
76012
- const contentTokens = estimateTokensForContentParts(message.content);
76013
- if (contentTokens < this.config.minContentTokens) continue;
76014
- markerTokenCount ??= estimateTokensForContentParts([{
76015
- type: "text",
76016
- text: this.config.truncatedMarker
76017
- }]);
76018
- truncatedToolResultCount += 1;
76019
- truncatedToolResultTokensBefore += contentTokens;
76020
- truncatedToolResultTokensAfter += markerTokenCount;
76044
+ if (message?.role === "tool" && message.toolCallId !== void 0) {
76045
+ const contentTokens = estimateTokensForContentParts(message.content);
76046
+ if (contentTokens >= this.config.minContentTokens) {
76047
+ markerTokenCount ??= estimateTokensForContentParts([{
76048
+ type: "text",
76049
+ text: this.config.truncatedMarker
76050
+ }]);
76051
+ truncatedToolResultCount += 1;
76052
+ truncatedToolResultTokensBefore += contentTokens;
76053
+ truncatedToolResultTokensAfter += markerTokenCount;
76054
+ }
76055
+ }
76056
+ if (message?.role !== "assistant" || !Array.isArray(message.toolCalls)) continue;
76057
+ for (const call of message.toolCalls) {
76058
+ if (!completedToolCallIds.has(call.id) || typeof call.arguments !== "string") continue;
76059
+ try {
76060
+ JSON.parse(call.arguments);
76061
+ } catch {
76062
+ continue;
76063
+ }
76064
+ const argumentTokens = this.toolArgumentTokens(call.arguments);
76065
+ if (argumentTokens < this.config.minContentTokens) continue;
76066
+ argumentsMarkerTokenCount ??= this.toolArgumentTokens(serializedArgumentsMarker);
76067
+ truncatedToolArgumentCount += 1;
76068
+ truncatedToolArgumentTokensBefore += argumentTokens;
76069
+ truncatedToolArgumentTokensAfter += argumentsMarkerTokenCount;
76070
+ }
76021
76071
  }
76022
76072
  return {
76023
76073
  truncatedToolResultCount,
76024
76074
  truncatedToolResultTokensBefore,
76025
- truncatedToolResultTokensAfter
76075
+ truncatedToolResultTokensAfter,
76076
+ truncatedToolArgumentCount,
76077
+ truncatedToolArgumentTokensBefore,
76078
+ truncatedToolArgumentTokensAfter
76026
76079
  };
76027
76080
  }
76081
+ toolArgumentTokens(argumentsValue) {
76082
+ return estimateTokensForMessages([{
76083
+ role: "assistant",
76084
+ content: [],
76085
+ toolCalls: [{
76086
+ type: "function",
76087
+ id: "",
76088
+ name: "",
76089
+ arguments: argumentsValue
76090
+ }]
76091
+ }]) - estimateTokensForMessages([{
76092
+ role: "assistant",
76093
+ content: [],
76094
+ toolCalls: []
76095
+ }]);
76096
+ }
76028
76097
  };
76029
76098
  }));
76030
76099
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.82",
3
+ "version": "9.1.83",
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": {
@@ -9,7 +9,7 @@ compatibility: designed for BLUN Code
9
9
 
10
10
  Use the bundled script instead of manually reading `wire.jsonl` or telemetry files. It reports counts and timing metadata without returning prompts, system instructions, tool arguments, tool results, private paths, or hidden reasoning.
11
11
 
12
- In addition to wire and telemetry counts, the summary reads only structured `turn request tools` fields from the session's own BLUN log. It reports eligible, selected, and deferred schema counts, estimated schema tokens avoided, and suppression reasons. Other log lines are ignored and never emitted.
12
+ In addition to wire and telemetry counts, the summary reads only structured `turn request tools` fields from the session's own BLUN log. It reports eligible, selected, and deferred schema counts, estimated schema tokens avoided, and suppression reasons. Micro-compaction telemetry also reports how many completed tool-call arguments were relieved and the estimated argument tokens saved. Argument contents are never returned. Other log lines are ignored and never emitted.
13
13
 
14
14
  Resolve `SKILL_DIR` to the directory containing this file. Do not assume a user-specific installation path.
15
15
 
@@ -278,6 +278,8 @@ async function summarizeTelemetry(telemetryDir, sessionId, warnings) {
278
278
  offloaded_tool_results: 0,
279
279
  offloaded_output_chars: 0,
280
280
  truncated_tool_results: 0,
281
+ truncated_tool_arguments: 0,
282
+ truncated_tool_argument_tokens_saved: 0,
281
283
  };
282
284
  if (!fs.existsSync(telemetryDir)) return summary;
283
285
 
@@ -290,6 +292,10 @@ async function summarizeTelemetry(telemetryDir, sessionId, warnings) {
290
292
  if (record.event === 'micro_compaction_finished') {
291
293
  summary.micro_compactions += 1;
292
294
  summary.truncated_tool_results += numberValue(record.properties?.truncated_tool_result_count);
295
+ summary.truncated_tool_arguments += numberValue(record.properties?.truncated_tool_argument_count);
296
+ summary.truncated_tool_argument_tokens_saved += Math.max(0,
297
+ numberValue(record.properties?.truncated_tool_argument_tokens_before)
298
+ - numberValue(record.properties?.truncated_tool_argument_tokens_after));
293
299
  } else if (record.event === 'compaction_failed') {
294
300
  summary.full_compaction_failures += 1;
295
301
  } else if (record.event === 'tool_result_offloaded') {