blun-king-cli 9.1.106 → 9.1.108
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 +3 -1
- package/bin/repeated-injection-projection.cjs +44 -0
- package/blun.mjs +90 -15
- package/package.json +1 -1
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.108
|
|
13
13
|
|
|
14
14
|
Start
|
|
15
15
|
-----
|
|
@@ -85,6 +85,8 @@ King bewahrt den vollständigen Verlauf weiterhin im Sitzungs-Wire auf. Erreicht
|
|
|
85
85
|
|
|
86
86
|
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.
|
|
87
87
|
|
|
88
|
+
Ab BLUN King 9.1.108 entfernt die Modellprojektion außerdem identische, wiederholt eingespeiste Systemhinweise. Pro Hinweisart und exaktem Text bleibt die neueste Fassung erhalten; geänderte Hinweise, normale Nutzernachrichten, Werkzeugaufrufe und gemischte Inhalte bleiben unverändert. Der Sitzungs-Wire wird nicht umgeschrieben. Dadurch werden lange fortgesetzte Sitzungen kleiner an den Anbieter übertragen, ohne Verlauf, Export oder Wiederaufnahme zu verkürzen. Beispiel: Wird derselbe Werkzeughinweis bei 80 Zügen erneut eingespeist, sieht das Modell nur die neueste identische Fassung. Ändert sich der Hinweis, bleiben beide Fassungen sichtbar.
|
|
89
|
+
|
|
88
90
|
Ab BLUN King 9.1.98 kann King einen abgeschlossenen Arbeitsabschnitt verdichten, bevor die harte automatische Grenze erreicht ist. Unterhalb der halben Vollverdichtungsgrenze bleibt `CompactConversation` vollständig aus dem Modellprompt. Ab 128.000 geschätzten Token im Standardmodellfenster wird es für den nächsten Modellschritt verfügbar. Die Verdichtung beginnt erst nach Abschluss des aktuellen Werkzeugschritts, öffnet keinen konkurrierenden Zug und lässt den ursprünglichen Verlauf bei einem Fehlschlag unverändert.
|
|
89
91
|
|
|
90
92
|
## Große Werkzeugausgaben und isolierte Teilagenten
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function repeatedInjectionKey(message) {
|
|
4
|
+
if (message?.role !== 'user') return null;
|
|
5
|
+
if (message?.origin?.kind !== 'injection') return null;
|
|
6
|
+
const variant = String(message.origin.variant || '').trim();
|
|
7
|
+
if (!variant) return null;
|
|
8
|
+
if (!Array.isArray(message.content) || message.content.length !== 1) return null;
|
|
9
|
+
const part = message.content[0];
|
|
10
|
+
if (part?.type !== 'text' || typeof part.text !== 'string') return null;
|
|
11
|
+
if (Array.isArray(message.toolCalls) && message.toolCalls.length > 0) return null;
|
|
12
|
+
return { variant, text: part.text };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function dedupeRepeatedInjections(history) {
|
|
16
|
+
if (!Array.isArray(history) || history.length < 2) return history;
|
|
17
|
+
const seenByVariant = new Map();
|
|
18
|
+
const kept = [];
|
|
19
|
+
|
|
20
|
+
for (let index = history.length - 1; index >= 0; index -= 1) {
|
|
21
|
+
const message = history[index];
|
|
22
|
+
const key = repeatedInjectionKey(message);
|
|
23
|
+
if (key === null) {
|
|
24
|
+
kept.push(message);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
let seenTexts = seenByVariant.get(key.variant);
|
|
28
|
+
if (seenTexts === undefined) {
|
|
29
|
+
seenTexts = new Set();
|
|
30
|
+
seenByVariant.set(key.variant, seenTexts);
|
|
31
|
+
}
|
|
32
|
+
if (seenTexts.has(key.text)) continue;
|
|
33
|
+
seenTexts.add(key.text);
|
|
34
|
+
kept.push(message);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
kept.reverse();
|
|
38
|
+
return kept.length === history.length ? history : kept;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = {
|
|
42
|
+
dedupeRepeatedInjections,
|
|
43
|
+
repeatedInjectionKey,
|
|
44
|
+
};
|
package/blun.mjs
CHANGED
|
@@ -75970,10 +75970,11 @@ var init_full = __esmMin((() => {
|
|
|
75970
75970
|
}));
|
|
75971
75971
|
//#endregion
|
|
75972
75972
|
//#region ../../packages/agent-core/src/agent/compaction/micro.ts
|
|
75973
|
-
var selectMicroCompactionCutoff, isPersistedToolResultReference, DEFAULT_CONFIG, MicroCompaction;
|
|
75973
|
+
var selectMicroCompactionCutoff, isPersistedToolResultReference, dedupeRepeatedInjections, DEFAULT_CONFIG, MicroCompaction;
|
|
75974
75974
|
var init_micro = __esmMin((() => {
|
|
75975
75975
|
({ selectMicroCompactionCutoff } = createRequire(import.meta.url)("./bin/micro-compaction-policy.cjs"));
|
|
75976
75976
|
({ isPersistedToolResultReference } = createRequire(import.meta.url)("./bin/tool-result-offload-policy.cjs"));
|
|
75977
|
+
({ dedupeRepeatedInjections } = createRequire(import.meta.url)("./bin/repeated-injection-projection.cjs"));
|
|
75977
75978
|
init_tokens();
|
|
75978
75979
|
DEFAULT_CONFIG = {
|
|
75979
75980
|
keepRecentMessages: 20,
|
|
@@ -78940,7 +78941,7 @@ var init_context$2 = __esmMin((() => {
|
|
|
78940
78941
|
}
|
|
78941
78942
|
project(messages, options) {
|
|
78942
78943
|
const anomalies = [];
|
|
78943
|
-
const result = project(this.agent.userMessageOffload.compact(this.agent.microCompaction.compact(this.agent.toolResultBatchOffload.compact(messages))), {
|
|
78944
|
+
const result = project(this.agent.userMessageOffload.compact(this.agent.microCompaction.compact(this.agent.toolResultBatchOffload.compact(dedupeRepeatedInjections(messages)))), {
|
|
78944
78945
|
...options,
|
|
78945
78946
|
onAnomaly: (anomaly) => {
|
|
78946
78947
|
anomalies.push(anomaly);
|
|
@@ -412849,27 +412850,45 @@ const STREAMING_ARGS_PREVIEW_MAX_CHARS = 64 * 1024;
|
|
|
412849
412850
|
registerUiCatalogFragment({
|
|
412850
412851
|
en: {
|
|
412851
412852
|
"eventPayload.providerFiltered": "Provider filtered the response before visible output (finishReason={finishReason}{raw}).",
|
|
412852
|
-
"eventPayload.modelEmptyResponse": "King ended twice without producing content. Please send the message again."
|
|
412853
|
+
"eventPayload.modelEmptyResponse": "King ended twice without producing content. Please send the message again.",
|
|
412854
|
+
"eventPayload.providerBusy": "King is busy right now. Please try again shortly.",
|
|
412855
|
+
"eventPayload.providerUnavailable": "King could not complete this response. Please try again.",
|
|
412856
|
+
"eventPayload.providerAuthRequired": "Your King connection needs to be renewed. Please sign in again."
|
|
412853
412857
|
},
|
|
412854
412858
|
de: {
|
|
412855
412859
|
"eventPayload.providerFiltered": "Der Anbieter hat die Antwort vor der sichtbaren Ausgabe gefiltert (finishReason={finishReason}{raw}).",
|
|
412856
|
-
"eventPayload.modelEmptyResponse": "King hat die Antwort zweimal ohne Inhalt beendet. Bitte sende die Nachricht noch einmal."
|
|
412860
|
+
"eventPayload.modelEmptyResponse": "King hat die Antwort zweimal ohne Inhalt beendet. Bitte sende die Nachricht noch einmal.",
|
|
412861
|
+
"eventPayload.providerBusy": "King ist gerade ausgelastet. Bitte versuche es gleich noch einmal.",
|
|
412862
|
+
"eventPayload.providerUnavailable": "King konnte diese Antwort nicht abschließen. Bitte versuche es noch einmal.",
|
|
412863
|
+
"eventPayload.providerAuthRequired": "Die Verbindung zu King muss erneuert werden. Bitte melde dich erneut an."
|
|
412857
412864
|
},
|
|
412858
412865
|
es: {
|
|
412859
412866
|
"eventPayload.providerFiltered": "El proveedor filtró la respuesta antes de que se mostrara la salida (finishReason={finishReason}{raw}).",
|
|
412860
|
-
"eventPayload.modelEmptyResponse": "King terminó dos veces sin generar contenido. Envía el mensaje de nuevo."
|
|
412867
|
+
"eventPayload.modelEmptyResponse": "King terminó dos veces sin generar contenido. Envía el mensaje de nuevo.",
|
|
412868
|
+
"eventPayload.providerBusy": "King está ocupado en este momento. Vuelve a intentarlo en unos instantes.",
|
|
412869
|
+
"eventPayload.providerUnavailable": "King no ha podido completar esta respuesta. Vuelve a intentarlo.",
|
|
412870
|
+
"eventPayload.providerAuthRequired": "Es necesario renovar la conexión con King. Vuelve a iniciar sesión."
|
|
412861
412871
|
},
|
|
412862
412872
|
fr: {
|
|
412863
412873
|
"eventPayload.providerFiltered": "Le fournisseur a filtré la réponse avant l’affichage de la sortie (finishReason={finishReason}{raw}).",
|
|
412864
|
-
"eventPayload.modelEmptyResponse": "King a terminé deux fois sans produire de contenu. Envoyez à nouveau le message."
|
|
412874
|
+
"eventPayload.modelEmptyResponse": "King a terminé deux fois sans produire de contenu. Envoyez à nouveau le message.",
|
|
412875
|
+
"eventPayload.providerBusy": "King est occupé pour le moment. Réessayez dans quelques instants.",
|
|
412876
|
+
"eventPayload.providerUnavailable": "King n’a pas pu terminer cette réponse. Réessayez.",
|
|
412877
|
+
"eventPayload.providerAuthRequired": "La connexion à King doit être renouvelée. Reconnectez-vous."
|
|
412865
412878
|
},
|
|
412866
412879
|
sv: {
|
|
412867
412880
|
"eventPayload.providerFiltered": "Leverantören filtrerade svaret innan någon utdata visades (finishReason={finishReason}{raw}).",
|
|
412868
|
-
"eventPayload.modelEmptyResponse": "King avslutade två gånger utan att skapa något innehåll. Skicka meddelandet igen."
|
|
412881
|
+
"eventPayload.modelEmptyResponse": "King avslutade två gånger utan att skapa något innehåll. Skicka meddelandet igen.",
|
|
412882
|
+
"eventPayload.providerBusy": "King är upptagen just nu. Försök igen om en liten stund.",
|
|
412883
|
+
"eventPayload.providerUnavailable": "King kunde inte slutföra svaret. Försök igen.",
|
|
412884
|
+
"eventPayload.providerAuthRequired": "Anslutningen till King behöver förnyas. Logga in igen."
|
|
412869
412885
|
},
|
|
412870
412886
|
cs: {
|
|
412871
412887
|
"eventPayload.providerFiltered": "Poskytovatel filtroval odpověď před viditelným výstupem (finishReason={finishReason}{raw}).",
|
|
412872
|
-
"eventPayload.modelEmptyResponse": "King dvakrát ukončil odpověď bez obsahu. Odešlete zprávu znovu."
|
|
412888
|
+
"eventPayload.modelEmptyResponse": "King dvakrát ukončil odpověď bez obsahu. Odešlete zprávu znovu.",
|
|
412889
|
+
"eventPayload.providerBusy": "King je právě zaneprázdněný. Zkuste to za chvíli znovu.",
|
|
412890
|
+
"eventPayload.providerUnavailable": "King nemohl tuto odpověď dokončit. Zkuste to znovu.",
|
|
412891
|
+
"eventPayload.providerAuthRequired": "Připojení ke Kingovi je potřeba obnovit. Přihlaste se znovu."
|
|
412873
412892
|
}
|
|
412874
412893
|
});
|
|
412875
412894
|
//#endregion
|
|
@@ -412944,10 +412963,24 @@ function formatErrorMessage$2(error) {
|
|
|
412944
412963
|
}
|
|
412945
412964
|
function formatErrorPayload(error) {
|
|
412946
412965
|
if (error.code === "model.empty_response") return uiText("eventPayload.modelEmptyResponse");
|
|
412966
|
+
if (error.code === "provider.rate_limit") return uiText("eventPayload.providerBusy");
|
|
412967
|
+
if (error.code === "provider.api_error" || error.code === "provider.connection_error") return uiText("eventPayload.providerUnavailable");
|
|
412968
|
+
if (error.code === "provider.auth_error") return uiText("eventPayload.providerAuthRequired");
|
|
412947
412969
|
const filteredMessage = formatProviderFilteredMessage(error.details);
|
|
412948
|
-
if (filteredMessage !== void 0) return projectBlunIdentity(
|
|
412970
|
+
if (filteredMessage !== void 0) return projectBlunIdentity(filteredMessage);
|
|
412949
412971
|
return projectBlunIdentity(`[${error.code}] ${error.message}`);
|
|
412950
412972
|
}
|
|
412973
|
+
|
|
412974
|
+
const CUSTOMER_FACING_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
412975
|
+
"provider.rate_limit",
|
|
412976
|
+
"provider.api_error",
|
|
412977
|
+
"provider.connection_error",
|
|
412978
|
+
"provider.auth_error",
|
|
412979
|
+
"model.empty_response"
|
|
412980
|
+
]);
|
|
412981
|
+
function shouldShowErrorReportHint(event) {
|
|
412982
|
+
return !CUSTOMER_FACING_ERROR_CODES.has(event.code);
|
|
412983
|
+
}
|
|
412951
412984
|
function formatProviderFilteredMessage(details) {
|
|
412952
412985
|
const finishReason = stringDetail(details, "finishReason");
|
|
412953
412986
|
const rawFinishReason = stringDetail(details, "rawFinishReason");
|
|
@@ -497195,29 +497228,41 @@ var HelpPanelComponent = class extends Container {
|
|
|
497195
497228
|
focused = false;
|
|
497196
497229
|
opts;
|
|
497197
497230
|
scrollTop = 0;
|
|
497231
|
+
selectedCommandIndex = 0;
|
|
497232
|
+
showCommandDetail = false;
|
|
497198
497233
|
constructor(opts) {
|
|
497199
497234
|
super();
|
|
497200
497235
|
this.opts = opts;
|
|
497201
497236
|
}
|
|
497202
497237
|
handleInput(data) {
|
|
497203
497238
|
const printable = decodeKittyPrintable(data) ?? data;
|
|
497204
|
-
if (matchesKey(data, Key.escape) ||
|
|
497239
|
+
if (matchesKey(data, Key.escape) || printable === "q" || printable === "Q") {
|
|
497205
497240
|
this.opts.onClose();
|
|
497206
497241
|
return;
|
|
497207
497242
|
}
|
|
497243
|
+
const sortedCmds = [...this.opts.commands].toSorted(compareSlashCommandsForDisplay);
|
|
497244
|
+
if (sortedCmds.length === 0) return;
|
|
497245
|
+
if (matchesKey(data, Key.right) || matchesKey(data, Key.enter)) {
|
|
497246
|
+
this.showCommandDetail = true;
|
|
497247
|
+
return;
|
|
497248
|
+
}
|
|
497249
|
+
if (matchesKey(data, Key.left)) {
|
|
497250
|
+
this.showCommandDetail = false;
|
|
497251
|
+
return;
|
|
497252
|
+
}
|
|
497208
497253
|
if (matchesKey(data, Key.up)) {
|
|
497209
|
-
this.
|
|
497254
|
+
this.selectedCommandIndex = Math.max(0, this.selectedCommandIndex - 1);
|
|
497210
497255
|
return;
|
|
497211
497256
|
}
|
|
497212
497257
|
if (matchesKey(data, Key.down)) {
|
|
497213
|
-
this.
|
|
497258
|
+
this.selectedCommandIndex = Math.min(sortedCmds.length - 1, this.selectedCommandIndex + 1);
|
|
497214
497259
|
return;
|
|
497215
497260
|
}
|
|
497216
497261
|
if (matchesKey(data, Key.pageUp)) {
|
|
497217
|
-
this.
|
|
497262
|
+
this.selectedCommandIndex = Math.max(0, this.selectedCommandIndex - 10);
|
|
497218
497263
|
return;
|
|
497219
497264
|
}
|
|
497220
|
-
if (matchesKey(data, Key.pageDown)) this.
|
|
497265
|
+
if (matchesKey(data, Key.pageDown)) this.selectedCommandIndex = Math.min(sortedCmds.length - 1, this.selectedCommandIndex + 10);
|
|
497221
497266
|
}
|
|
497222
497267
|
render(width) {
|
|
497223
497268
|
const accent = (text) => currentTheme.fg("primary", text);
|
|
@@ -497228,6 +497273,8 @@ var HelpPanelComponent = class extends Container {
|
|
|
497228
497273
|
const shortcuts = this.opts.shortcuts ?? DEFAULT_KEYBOARD_SHORTCUTS;
|
|
497229
497274
|
const kbdWidth = Math.max(8, ...shortcuts.map((s) => s.keys.length));
|
|
497230
497275
|
const sortedCmds = [...this.opts.commands].toSorted(compareSlashCommandsForDisplay);
|
|
497276
|
+
this.selectedCommandIndex = Math.max(0, Math.min(this.selectedCommandIndex, Math.max(0, sortedCmds.length - 1)));
|
|
497277
|
+
if (this.showCommandDetail && sortedCmds.length > 0) return this.renderCommandDetail(width, sortedCmds);
|
|
497231
497278
|
const cmdLabels = sortedCmds.map((c) => {
|
|
497232
497279
|
const aliases = c.aliases.length > 0 ? ` (${c.aliases.map((a) => "/" + a).join(", ")})` : "";
|
|
497233
497280
|
return `/${c.name}${aliases}`;
|
|
@@ -497244,7 +497291,10 @@ var HelpPanelComponent = class extends Container {
|
|
|
497244
497291
|
"",
|
|
497245
497292
|
` ${currentTheme.bold(uiText("help.slashCommands"))}`,
|
|
497246
497293
|
...sortedCmds.map((cmd, i) => {
|
|
497247
|
-
|
|
497294
|
+
const marker = i === this.selectedCommandIndex ? accent("â–¶") : " ";
|
|
497295
|
+
const label = (cmdLabels[i] ?? `/${cmd.name}`).padEnd(cmdWidth);
|
|
497296
|
+
const commandText = i === this.selectedCommandIndex ? currentTheme.boldFg("primary", label) : slashColor(label);
|
|
497297
|
+
return ` ${marker} ${commandText} ${dim(cmd.description)}`;
|
|
497248
497298
|
}),
|
|
497249
497299
|
"",
|
|
497250
497300
|
accent("─".repeat(width))
|
|
@@ -497252,6 +497302,9 @@ var HelpPanelComponent = class extends Container {
|
|
|
497252
497302
|
const content = lines.slice(1, lines.length - 1);
|
|
497253
497303
|
const maxVisible = Math.max(5, this.opts.maxVisible ?? 24);
|
|
497254
497304
|
if (content.length > maxVisible) {
|
|
497305
|
+
const selectedLine = 7 + shortcuts.length + this.selectedCommandIndex;
|
|
497306
|
+
if (selectedLine < this.scrollTop) this.scrollTop = selectedLine;
|
|
497307
|
+
if (selectedLine >= this.scrollTop + maxVisible) this.scrollTop = selectedLine - maxVisible + 1;
|
|
497255
497308
|
this.scrollTop = Math.max(0, Math.min(this.scrollTop, content.length - maxVisible));
|
|
497256
497309
|
const slice = content.slice(this.scrollTop, this.scrollTop + maxVisible);
|
|
497257
497310
|
const scrollInfo = muted(` ${uiText("help.scrollInfo", {
|
|
@@ -497269,6 +497322,27 @@ var HelpPanelComponent = class extends Container {
|
|
|
497269
497322
|
this.scrollTop = 0;
|
|
497270
497323
|
return lines.map((line) => truncateToWidth(line, width));
|
|
497271
497324
|
}
|
|
497325
|
+
renderCommandDetail(width, sortedCmds) {
|
|
497326
|
+
const accent = (text) => currentTheme.fg("primary", text);
|
|
497327
|
+
const dim = (text) => currentTheme.fg("textDim", text);
|
|
497328
|
+
const muted = (text) => currentTheme.fg("textMuted", text);
|
|
497329
|
+
const command = sortedCmds[this.selectedCommandIndex];
|
|
497330
|
+
if (command === void 0) return [];
|
|
497331
|
+
const argumentHint = typeof command.argumentHint === "string" && command.argumentHint.length > 0 ? ` ${command.argumentHint}` : "";
|
|
497332
|
+
const aliases = command.aliases.length > 0 ? command.aliases.map((alias) => `/${alias}`).join(", ") : "—";
|
|
497333
|
+
const descriptionLines = wrapTextWithAnsi(dim(command.description), Math.max(10, width - 4)).map((line) => ` ${line}`);
|
|
497334
|
+
return [
|
|
497335
|
+
accent("─".repeat(width)),
|
|
497336
|
+
currentTheme.boldFg("primary", ` /${command.name}${argumentHint}`),
|
|
497337
|
+
"",
|
|
497338
|
+
...descriptionLines,
|
|
497339
|
+
"",
|
|
497340
|
+
` ${muted("=")} ${dim(aliases)}`,
|
|
497341
|
+
"",
|
|
497342
|
+
muted(` ${this.selectedCommandIndex + 1}/${sortedCmds.length} · ↑↓ · ↠· Esc / q`),
|
|
497343
|
+
accent("─".repeat(width))
|
|
497344
|
+
].map((line) => truncateToWidth(line, width));
|
|
497345
|
+
}
|
|
497272
497346
|
};
|
|
497273
497347
|
function localizedShortcut(keys, descriptionKey) {
|
|
497274
497348
|
return {
|
|
@@ -506756,6 +506830,7 @@ var SessionEventHandler = class {
|
|
|
506756
506830
|
this.showErrorReportHint(event);
|
|
506757
506831
|
}
|
|
506758
506832
|
showErrorReportHint(event) {
|
|
506833
|
+
if (!shouldShowErrorReportHint(event)) return;
|
|
506759
506834
|
const { appState } = this.host.state;
|
|
506760
506835
|
if (appState.sessionId.length === 0) return;
|
|
506761
506836
|
this.host.showStatus(errorReportHintLine({
|