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 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.106
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(`[${error.code}] ${filteredMessage}`);
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) || matchesKey(data, Key.enter) || printable === "q" || printable === "Q") {
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.scrollTop = Math.max(0, this.scrollTop - 1);
497254
+ this.selectedCommandIndex = Math.max(0, this.selectedCommandIndex - 1);
497210
497255
  return;
497211
497256
  }
497212
497257
  if (matchesKey(data, Key.down)) {
497213
- this.scrollTop += 1;
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.scrollTop = Math.max(0, this.scrollTop - 10);
497262
+ this.selectedCommandIndex = Math.max(0, this.selectedCommandIndex - 10);
497218
497263
  return;
497219
497264
  }
497220
- if (matchesKey(data, Key.pageDown)) this.scrollTop += 10;
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
- return ` ${slashColor((cmdLabels[i] ?? `/${cmd.name}`).padEnd(cmdWidth))} ${dim(cmd.description)}`;
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({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.106",
3
+ "version": "9.1.108",
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": {