blun-king-cli 9.1.81 → 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.
|
|
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
|
-
|
|
79
|
-
|
|
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
|
|
|
@@ -99,6 +91,8 @@ Rein lesende Sitzungsdiagnose
|
|
|
99
91
|
|
|
100
92
|
Der mitgelieferte Standardskill `blun-session-inspector` untersucht den nur ergänzten Sitzungs-Wire und die zugehörigen Telemetriedateien, ohne eine Sitzung zu verändern. Er meldet Modellschritte, Werkzeugaufrufe, Zähler zum Tokenverbrauch, Voll- und Mikroverdichtungen, fehlgeschlagene Verdichtungen sowie ausgelagerte Werkzeugergebnisse. Prompts, Systemanweisungen, Werkzeugargumente, Werkzeugergebnisse, private Pfade und verborgenes Denken erscheinen nicht in der Standardausgabe.
|
|
101
93
|
|
|
94
|
+
Zusätzlich liest der Inspektor das sitzungseigene BLUN-Protokoll und meldet, wie viele Werkzeugschemata verfügbar, ausgewählt und zurückgestellt waren, wie viele geschätzte Schema-Token vermieden wurden und warum die Werkzeugmenge reduziert wurde. Andere Protokollinhalte werden weder ausgegeben noch ausgewertet.
|
|
95
|
+
|
|
102
96
|
Beispiele:
|
|
103
97
|
|
|
104
98
|
node "$SKILL_DIR/scripts/inspect-session.cjs" --list 20
|
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.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.
|
|
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.
|
|
105
100
|
|
|
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.
|
|
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
|
|
|
@@ -120,6 +112,8 @@ Reguläre `Agent`-Teilaufgaben verwenden eine eigene `ContextMemory` und eine ei
|
|
|
120
112
|
|
|
121
113
|
Der mitgelieferte Standardskill `blun-session-inspector` untersucht den nur ergänzten Sitzungs-Wire und die zugehörigen Telemetriedateien, ohne eine Sitzung zu verändern. Er meldet Modellschritte, Werkzeugaufrufe, Zähler zum Tokenverbrauch, Voll- und Mikroverdichtungen, fehlgeschlagene Verdichtungen sowie ausgelagerte Werkzeugergebnisse. Prompts, Systemanweisungen, Werkzeugargumente, Werkzeugergebnisse, private Pfade und verborgenes Denken erscheinen nicht in der Standardausgabe.
|
|
122
114
|
|
|
115
|
+
Zusätzlich liest der Inspektor das sitzungseigene BLUN-Protokoll und meldet, wie viele Werkzeugschemata verfügbar, ausgewählt und zurückgestellt waren, wie viele geschätzte Schema-Token vermieden wurden und warum die Werkzeugmenge reduziert wurde. Andere Protokollinhalte werden weder ausgegeben noch ausgewertet.
|
|
116
|
+
|
|
123
117
|
Beispiele:
|
|
124
118
|
|
|
125
119
|
```text
|
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
|
|
76012
|
-
|
|
76013
|
-
|
|
76014
|
-
|
|
76015
|
-
|
|
76016
|
-
|
|
76017
|
-
|
|
76018
|
-
|
|
76019
|
-
|
|
76020
|
-
|
|
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
|
@@ -9,6 +9,8 @@ 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. 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
|
+
|
|
12
14
|
Resolve `SKILL_DIR` to the directory containing this file. Do not assume a user-specific installation path.
|
|
13
15
|
|
|
14
16
|
List recent sessions:
|
|
@@ -139,6 +139,17 @@ function numberValue(value) {
|
|
|
139
139
|
return Number.isFinite(Number(value)) ? Number(value) : 0;
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
+
function emptyTokenSeries() {
|
|
143
|
+
return { total: 0, min: null, max: null, last: null };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function addTokenValue(series, value) {
|
|
147
|
+
series.total += value;
|
|
148
|
+
series.min = series.min === null ? value : Math.min(series.min, value);
|
|
149
|
+
series.max = series.max === null ? value : Math.max(series.max, value);
|
|
150
|
+
series.last = value;
|
|
151
|
+
}
|
|
152
|
+
|
|
142
153
|
function usageValue(usage, camelName, snakeName) {
|
|
143
154
|
return numberValue(usage?.[camelName] ?? usage?.[snakeName]);
|
|
144
155
|
}
|
|
@@ -267,6 +278,8 @@ async function summarizeTelemetry(telemetryDir, sessionId, warnings) {
|
|
|
267
278
|
offloaded_tool_results: 0,
|
|
268
279
|
offloaded_output_chars: 0,
|
|
269
280
|
truncated_tool_results: 0,
|
|
281
|
+
truncated_tool_arguments: 0,
|
|
282
|
+
truncated_tool_argument_tokens_saved: 0,
|
|
270
283
|
};
|
|
271
284
|
if (!fs.existsSync(telemetryDir)) return summary;
|
|
272
285
|
|
|
@@ -279,6 +292,10 @@ async function summarizeTelemetry(telemetryDir, sessionId, warnings) {
|
|
|
279
292
|
if (record.event === 'micro_compaction_finished') {
|
|
280
293
|
summary.micro_compactions += 1;
|
|
281
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));
|
|
282
299
|
} else if (record.event === 'compaction_failed') {
|
|
283
300
|
summary.full_compaction_failures += 1;
|
|
284
301
|
} else if (record.event === 'tool_result_offloaded') {
|
|
@@ -290,6 +307,61 @@ async function summarizeTelemetry(telemetryDir, sessionId, warnings) {
|
|
|
290
307
|
return summary;
|
|
291
308
|
}
|
|
292
309
|
|
|
310
|
+
async function summarizeToolSchemas(logPath) {
|
|
311
|
+
const summary = {
|
|
312
|
+
requests: 0,
|
|
313
|
+
deferred_requests: 0,
|
|
314
|
+
suppression_reasons: [],
|
|
315
|
+
eligible_schema_tokens: emptyTokenSeries(),
|
|
316
|
+
selected_schema_tokens: emptyTokenSeries(),
|
|
317
|
+
estimated_schema_tokens_avoided: 0,
|
|
318
|
+
last: null,
|
|
319
|
+
};
|
|
320
|
+
if (!fs.existsSync(logPath)) return summary;
|
|
321
|
+
|
|
322
|
+
const reasonCounts = new Map();
|
|
323
|
+
const input = fs.createReadStream(logPath, { encoding: 'utf8' });
|
|
324
|
+
const lines = readline.createInterface({ input, crlfDelay: Infinity });
|
|
325
|
+
for await (const line of lines) {
|
|
326
|
+
if (!line.includes('turn request tools')) continue;
|
|
327
|
+
const values = Object.fromEntries(
|
|
328
|
+
[...line.matchAll(/\b(toolSuppressionReason|eligibleToolCount|selectedToolCount|deferredToolCount|eligibleToolSchemaTokens|selectedToolSchemaTokens)=([^\s]+)/gu)]
|
|
329
|
+
.map((match) => [match[1], match[2]]),
|
|
330
|
+
);
|
|
331
|
+
const numericKeys = [
|
|
332
|
+
'eligibleToolCount',
|
|
333
|
+
'selectedToolCount',
|
|
334
|
+
'deferredToolCount',
|
|
335
|
+
'eligibleToolSchemaTokens',
|
|
336
|
+
'selectedToolSchemaTokens',
|
|
337
|
+
];
|
|
338
|
+
if (!values.toolSuppressionReason || !numericKeys.every((key) => /^\d+$/u.test(values[key] || ''))) continue;
|
|
339
|
+
|
|
340
|
+
const eligibleToolCount = Number(values.eligibleToolCount);
|
|
341
|
+
const selectedToolCount = Number(values.selectedToolCount);
|
|
342
|
+
const deferredToolCount = Number(values.deferredToolCount);
|
|
343
|
+
const eligibleSchemaTokens = Number(values.eligibleToolSchemaTokens);
|
|
344
|
+
const selectedSchemaTokens = Number(values.selectedToolSchemaTokens);
|
|
345
|
+
summary.requests += 1;
|
|
346
|
+
if (deferredToolCount > 0) summary.deferred_requests += 1;
|
|
347
|
+
reasonCounts.set(values.toolSuppressionReason, (reasonCounts.get(values.toolSuppressionReason) || 0) + 1);
|
|
348
|
+
addTokenValue(summary.eligible_schema_tokens, eligibleSchemaTokens);
|
|
349
|
+
addTokenValue(summary.selected_schema_tokens, selectedSchemaTokens);
|
|
350
|
+
summary.estimated_schema_tokens_avoided += Math.max(0, eligibleSchemaTokens - selectedSchemaTokens);
|
|
351
|
+
summary.last = {
|
|
352
|
+
eligible_tool_count: eligibleToolCount,
|
|
353
|
+
selected_tool_count: selectedToolCount,
|
|
354
|
+
deferred_tool_count: deferredToolCount,
|
|
355
|
+
eligible_schema_tokens: eligibleSchemaTokens,
|
|
356
|
+
selected_schema_tokens: selectedSchemaTokens,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
summary.suppression_reasons = [...reasonCounts.entries()]
|
|
360
|
+
.map(([reason, requests]) => ({ reason, requests }))
|
|
361
|
+
.sort((left, right) => right.requests - left.requests || left.reason.localeCompare(right.reason));
|
|
362
|
+
return summary;
|
|
363
|
+
}
|
|
364
|
+
|
|
293
365
|
function listSessions(options, profileRoot, sessions, warnings) {
|
|
294
366
|
const listed = sessions
|
|
295
367
|
.filter((entry) => {
|
|
@@ -337,6 +409,7 @@ async function inspectSession(options, profileRoot, sessions, inheritedWarnings)
|
|
|
337
409
|
agents,
|
|
338
410
|
totals: combineAgents(agents),
|
|
339
411
|
telemetry: await summarizeTelemetry(path.join(options.blunHome, 'telemetry'), entry.sessionId, warnings),
|
|
412
|
+
tool_schemas: await summarizeToolSchemas(path.join(entry.sessionDir, 'logs', 'blun.log')),
|
|
340
413
|
warnings,
|
|
341
414
|
};
|
|
342
415
|
if (options.includeMetadata) {
|