blun-king-cli 9.1.289 → 9.1.291

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.
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ async function waitForAbortableCompletion(signal, work, onAbort) {
4
+ const listenerRegistered = !signal.aborted;
5
+ if (listenerRegistered) signal.addEventListener('abort', onAbort, { once: true });
6
+ else onAbort();
7
+ try {
8
+ return await work;
9
+ } finally {
10
+ if (listenerRegistered) signal.removeEventListener('abort', onAbort);
11
+ }
12
+ }
13
+
14
+ module.exports = { waitForAbortableCompletion };
@@ -0,0 +1,70 @@
1
+ 'use strict';
2
+
3
+ function wholeNonNegative(value) {
4
+ if (!Number.isFinite(value) || value <= 0) return 0;
5
+ return Math.floor(value);
6
+ }
7
+
8
+ function claimTokens(remaining, value) {
9
+ return Math.min(remaining, wholeNonNegative(value));
10
+ }
11
+
12
+ function buildContextDoctor(input = {}) {
13
+ const projectedTokens = wholeNonNegative(input.projectedTokenCount);
14
+ const maxTokens = wholeNonNegative(input.effectiveMaxContextTokens);
15
+ const conversationTokens = wholeNonNegative(input.conversationTokens);
16
+
17
+ const systemTotal = wholeNonNegative(input.systemPromptTokens);
18
+ let systemRemaining = systemTotal;
19
+ const personalityTokens = claimTokens(systemRemaining, input.personalityPromptTokens);
20
+ systemRemaining -= personalityTokens;
21
+ const socialTokens = claimTokens(systemRemaining, input.socialPromptTokens);
22
+ systemRemaining -= socialTokens;
23
+ const skillTokens = claimTokens(systemRemaining, input.skillPromptTokens);
24
+ systemRemaining -= skillTokens;
25
+ const runtimeTokens = claimTokens(systemRemaining, input.runtimePromptTokens);
26
+ systemRemaining -= runtimeTokens;
27
+
28
+ const toolTotal = wholeNonNegative(input.toolSchemaTokens);
29
+ let toolRemaining = toolTotal;
30
+ const builtinTokens = claimTokens(toolRemaining, input.builtinToolSchemaTokens);
31
+ toolRemaining -= builtinTokens;
32
+ const userTokens = claimTokens(toolRemaining, input.userToolSchemaTokens);
33
+ toolRemaining -= userTokens;
34
+ const mcpTokens = claimTokens(toolRemaining, input.mcpToolSchemaTokens);
35
+ toolRemaining -= mcpTokens;
36
+
37
+ const accountedTokens = systemTotal + conversationTokens + toolTotal;
38
+ const providerOverheadTokens = Math.max(0, projectedTokens - accountedTokens);
39
+ const freeTokens = Math.max(0, maxTokens - projectedTokens);
40
+ const ratio = maxTokens > 0 ? Math.min(1, projectedTokens / maxTokens) : 0;
41
+
42
+ return {
43
+ projectedTokens,
44
+ maxTokens,
45
+ freeTokens,
46
+ ratio,
47
+ providerOverheadTokens,
48
+ conversationTokens,
49
+ system: {
50
+ coreTokens: systemRemaining,
51
+ personalityTokens,
52
+ socialTokens,
53
+ skillTokens,
54
+ runtimeTokens,
55
+ totalTokens: systemTotal,
56
+ },
57
+ tools: {
58
+ builtinTokens,
59
+ userTokens,
60
+ mcpTokens,
61
+ otherTokens: toolRemaining,
62
+ totalTokens: toolTotal,
63
+ },
64
+ };
65
+ }
66
+
67
+ module.exports = {
68
+ buildContextDoctor,
69
+ wholeNonNegative,
70
+ };
package/blun.mjs CHANGED
@@ -75292,9 +75292,10 @@ function extractCompactionSummary(response) {
75292
75292
  if (summary.trim().length === 0) throw new APIEmptyResponseError("The compaction response did not contain a non-empty summary.");
75293
75293
  return summary;
75294
75294
  }
75295
- var archiveCompactionHistory, buildCompactionArchiveNotice, capCompactionCompletionTokens, capCompactionStageTarget, proactiveCompactionEligibility, COMPACTION_THINKING_EFFORT, COMPACTION_SYSTEM_PROMPT, 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;
75295
+ var archiveCompactionHistory, buildCompactionArchiveNotice, capCompactionCompletionTokens, capCompactionStageTarget, proactiveCompactionEligibility, waitForAbortableCompletion, COMPACTION_THINKING_EFFORT, COMPACTION_SYSTEM_PROMPT, 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;
75296
75296
  var init_full = __esmMin((() => {
75297
75297
  ({ archiveCompactionHistory, buildCompactionArchiveNotice } = createRequire(import.meta.url)("./bin/compaction-history-archive.cjs"));
75298
+ ({ waitForAbortableCompletion } = createRequire(import.meta.url)("./bin/abort-listener-policy.cjs"));
75298
75299
  ({ capCompactionCompletionTokens, capCompactionStageTarget } = createRequire(import.meta.url)("./bin/compaction-stage-policy.cjs"));
75299
75300
  ({ proactiveCompactionEligibility } = createRequire(import.meta.url)("./bin/proactive-compaction-policy.cjs"));
75300
75301
  init_errors$8();
@@ -75556,14 +75557,14 @@ var init_full = __esmMin((() => {
75556
75557
  const active = this.compacting;
75557
75558
  if (active) {
75558
75559
  active.blockedByTurn = true;
75559
- signal.addEventListener("abort", () => {
75560
+ const onAbort = () => {
75560
75561
  if (this.compacting === active) this.cancel();
75561
- });
75562
+ };
75562
75563
  this.agent.emitEvent({
75563
75564
  type: "compaction.blocked",
75564
75565
  turnId: this.agent.turn.currentId
75565
75566
  });
75566
- await active.promise;
75567
+ await waitForAbortableCompletion(signal, active.promise, onAbort);
75567
75568
  }
75568
75569
  }
75569
75570
  async compactionWorker(signal, data) {
@@ -264324,6 +264325,16 @@ var init_tool$1 = __esmMin((() => {
264324
264325
  data() {
264325
264326
  return Array.from(this.toolInfos());
264326
264327
  }
264328
+ contextSchemaTokenBreakdown() {
264329
+ const totals = { builtin: 0, user: 0, mcp: 0 };
264330
+ for (const tool of this.loopTools) {
264331
+ const tokens = estimateTokensForTools([tool]);
264332
+ if (this.mcpTools.has(tool.name)) totals.mcp += tokens;
264333
+ else if (this.userTools.has(tool.name)) totals.user += tokens;
264334
+ else totals.builtin += tokens;
264335
+ }
264336
+ return totals;
264337
+ }
264327
264338
  storeData() {
264328
264339
  return { ...this.store };
264329
264340
  }
@@ -265275,15 +265286,30 @@ var init_agent = __esmMin((() => {
265275
265286
  resumeGoal: () => this.goal.resumeGoal(),
265276
265287
  cancelGoal: () => this.goal.cancelGoal(),
265277
265288
  getBackgroundOutput: (payload) => this.background.readOutput(payload.taskId, payload.tail),
265278
- getContext: () => ({
265279
- ...this.context.data(),
265280
- projectedTokenCount: this.fullCompaction.estimateCurrentRequestTokens(),
265281
- effectiveMaxContextTokens: this.fullCompaction.getEffectiveMaxContextTokens(),
265282
- compactionBudgetTokens: this.fullCompaction.getCompactionBudgetTokens(),
265283
- systemPromptTokens: estimateTokens$1(this.effectiveSystemPrompt),
265284
- conversationTokens: estimateTokensForMessages(this.context.messages),
265285
- toolSchemaTokens: estimateTokensForTools(this.tools.loopTools)
265286
- }),
265289
+ getContext: () => {
265290
+ const systemPrompt = this.effectiveSystemPrompt;
265291
+ const includedTokens = (block) => block.length > 0 && systemPrompt.includes(block) ? estimateTokens$1(block) : 0;
265292
+ const personalityPromptTokens = includedTokens(personaSystemBlock()) + includedTokens(soulSystemBlock());
265293
+ const socialPromptTokens = includedTokens(identitySystemBlock()) + includedTokens(naturalPresenceSystemBlock());
265294
+ const skillPrompt = this.skills?.registry.getModelSkillListing() ?? "";
265295
+ const toolBreakdown = this.tools.contextSchemaTokenBreakdown();
265296
+ return {
265297
+ ...this.context.data(),
265298
+ projectedTokenCount: this.fullCompaction.estimateCurrentRequestTokens(),
265299
+ effectiveMaxContextTokens: this.fullCompaction.getEffectiveMaxContextTokens(),
265300
+ compactionBudgetTokens: this.fullCompaction.getCompactionBudgetTokens(),
265301
+ systemPromptTokens: estimateTokens$1(systemPrompt),
265302
+ personalityPromptTokens,
265303
+ socialPromptTokens,
265304
+ skillPromptTokens: includedTokens(skillPrompt),
265305
+ runtimePromptTokens: includedTokens(this.runtimeSystemPromptAppend),
265306
+ conversationTokens: estimateTokensForMessages(this.context.messages),
265307
+ toolSchemaTokens: estimateTokensForTools(this.tools.loopTools),
265308
+ builtinToolSchemaTokens: toolBreakdown.builtin,
265309
+ userToolSchemaTokens: toolBreakdown.user,
265310
+ mcpToolSchemaTokens: toolBreakdown.mcp
265311
+ };
265312
+ },
265287
265313
  getConfig: () => this.config.data(),
265288
265314
  getPermission: () => this.permission.data(),
265289
265315
  getPlan: () => this.planMode.data(),
@@ -403318,6 +403344,13 @@ const BUILTIN_SLASH_COMMAND_DEFINITIONS = [
403318
403344
  priority: 65,
403319
403345
  availability: "always"
403320
403346
  },
403347
+ {
403348
+ name: "context-doctor",
403349
+ aliases: [],
403350
+ descriptionKey: "contextDoctor.description",
403351
+ priority: 66,
403352
+ availability: "always"
403353
+ },
403321
403354
  {
403322
403355
  name: "improve",
403323
403356
  aliases: ["learning"],
@@ -416989,6 +417022,92 @@ registerUiCatalogFragment({
416989
417022
  "usage.context.title": "Kontextové okno"
416990
417023
  }
416991
417024
  });
417025
+ registerUiCatalogFragment({
417026
+ en: {
417027
+ "contextDoctor.title": "Context doctor",
417028
+ "contextDoctor.description": "Break down injected context without calling the model",
417029
+ "contextDoctor.core": "Core instructions",
417030
+ "contextDoctor.personality": "Personality and soul",
417031
+ "contextDoctor.social": "Relationships and presence",
417032
+ "contextDoctor.skills": "Skills index",
417033
+ "contextDoctor.runtime": "Runtime additions",
417034
+ "contextDoctor.builtinTools": "Built-in tools",
417035
+ "contextDoctor.userTools": "User tools",
417036
+ "contextDoctor.mcpTools": "MCP tools",
417037
+ "contextDoctor.otherTools": "Other tool schemas",
417038
+ "contextDoctor.providerOverhead": "Provider overhead"
417039
+ },
417040
+ de: {
417041
+ "contextDoctor.title": "Kontextdiagnose",
417042
+ "contextDoctor.description": "Aufschlüsselung des eingefügten Kontexts ohne Modellaufruf",
417043
+ "contextDoctor.core": "Kernanweisungen",
417044
+ "contextDoctor.personality": "Persönlichkeit und Seele",
417045
+ "contextDoctor.social": "Beziehungen und Präsenz",
417046
+ "contextDoctor.skills": "Fähigkeitenverzeichnis",
417047
+ "contextDoctor.runtime": "Laufzeitergänzungen",
417048
+ "contextDoctor.builtinTools": "Integrierte Werkzeuge",
417049
+ "contextDoctor.userTools": "Benutzerwerkzeuge",
417050
+ "contextDoctor.mcpTools": "MCP-Werkzeuge",
417051
+ "contextDoctor.otherTools": "Weitere Werkzeugschemata",
417052
+ "contextDoctor.providerOverhead": "Anbieterbedingter Zusatzaufwand"
417053
+ },
417054
+ es: {
417055
+ "contextDoctor.title": "Diagnóstico del contexto",
417056
+ "contextDoctor.description": "Desglose del contexto insertado sin llamar al modelo",
417057
+ "contextDoctor.core": "Instrucciones principales",
417058
+ "contextDoctor.personality": "Personalidad y esencia",
417059
+ "contextDoctor.social": "Relaciones y presencia",
417060
+ "contextDoctor.skills": "Índice de habilidades",
417061
+ "contextDoctor.runtime": "Adiciones en tiempo de ejecución",
417062
+ "contextDoctor.builtinTools": "Herramientas integradas",
417063
+ "contextDoctor.userTools": "Herramientas del usuario",
417064
+ "contextDoctor.mcpTools": "Herramientas MCP",
417065
+ "contextDoctor.otherTools": "Otros esquemas de herramientas",
417066
+ "contextDoctor.providerOverhead": "Sobrecarga del proveedor"
417067
+ },
417068
+ fr: {
417069
+ "contextDoctor.title": "Diagnostic du contexte",
417070
+ "contextDoctor.description": "Répartition du contexte injecté sans appel au modèle",
417071
+ "contextDoctor.core": "Instructions principales",
417072
+ "contextDoctor.personality": "Personnalité et identité",
417073
+ "contextDoctor.social": "Relations et présence",
417074
+ "contextDoctor.skills": "Index des compétences",
417075
+ "contextDoctor.runtime": "Ajouts à l’exécution",
417076
+ "contextDoctor.builtinTools": "Outils intégrés",
417077
+ "contextDoctor.userTools": "Outils de l’utilisateur",
417078
+ "contextDoctor.mcpTools": "Outils MCP",
417079
+ "contextDoctor.otherTools": "Autres schémas d’outils",
417080
+ "contextDoctor.providerOverhead": "Surcoût du fournisseur"
417081
+ },
417082
+ sv: {
417083
+ "contextDoctor.title": "Kontextdiagnos",
417084
+ "contextDoctor.description": "Uppdelning av infogad kontext utan modellanrop",
417085
+ "contextDoctor.core": "Grundinstruktioner",
417086
+ "contextDoctor.personality": "Personlighet och identitet",
417087
+ "contextDoctor.social": "Relationer och närvaro",
417088
+ "contextDoctor.skills": "Färdighetsindex",
417089
+ "contextDoctor.runtime": "Körtidstillägg",
417090
+ "contextDoctor.builtinTools": "Inbyggda verktyg",
417091
+ "contextDoctor.userTools": "Användarverktyg",
417092
+ "contextDoctor.mcpTools": "MCP-verktyg",
417093
+ "contextDoctor.otherTools": "Övriga verktygsscheman",
417094
+ "contextDoctor.providerOverhead": "Leverantörspåslag"
417095
+ },
417096
+ cs: {
417097
+ "contextDoctor.title": "Diagnostika kontextu",
417098
+ "contextDoctor.description": "Rozpis vloženého kontextu bez volání modelu",
417099
+ "contextDoctor.core": "Základní pokyny",
417100
+ "contextDoctor.personality": "Osobnost a identita",
417101
+ "contextDoctor.social": "Vztahy a přítomnost",
417102
+ "contextDoctor.skills": "Přehled dovedností",
417103
+ "contextDoctor.runtime": "Doplňky za běhu",
417104
+ "contextDoctor.builtinTools": "Vestavěné nástroje",
417105
+ "contextDoctor.userTools": "Uživatelské nástroje",
417106
+ "contextDoctor.mcpTools": "Nástroje MCP",
417107
+ "contextDoctor.otherTools": "Ostatní schémata nástrojů",
417108
+ "contextDoctor.providerOverhead": "Režie poskytovatele"
417109
+ }
417110
+ });
416992
417111
  const LEFT_MARGIN$1 = 2;
416993
417112
  const SIDE_PADDING$1 = 1;
416994
417113
  const BOX_OVERHEAD = LEFT_MARGIN$1 + 2 + 2 * SIDE_PADDING$1;
@@ -417117,6 +417236,7 @@ function buildManagedUsageReportLines(options) {
417117
417236
  var { buildApprovalRejectionStop } = createRequire(import.meta.url)("./bin/approval-rejection-stop.cjs");
417118
417237
  var { reconcileContextBudget } = createRequire(import.meta.url)("./bin/context-budget-ledger.cjs");
417119
417238
  var { buildContextInsight } = createRequire(import.meta.url)("./bin/context-insight-policy.cjs");
417239
+ var { buildContextDoctor } = createRequire(import.meta.url)("./bin/context-doctor-policy.cjs");
417120
417240
  var { buildValidatedLearningInsight } = createRequire(import.meta.url)("./bin/validated-learning-insight-policy.cjs");
417121
417241
  var { readValidatedLearningCandidates } = createRequire(import.meta.url)("./bin/validated-learning-signal.cjs");
417122
417242
  function buildUsageReportLines(options) {
@@ -418210,6 +418330,41 @@ async function showContextInsight(host) {
418210
418330
  host.state.transcriptContainer.addChild(panel);
418211
418331
  host.state.ui.requestRender();
418212
418332
  }
418333
+ function buildContextDoctorLines(doctor) {
418334
+ const value = (text) => currentTheme.fg("text", text);
418335
+ const muted = (text) => currentTheme.fg("textDim", text);
418336
+ const locale = getCurrentUiLocale();
418337
+ const tokenValue = (tokens) => value(formatExactTokenCount(tokens, locale));
418338
+ const line = (key, tokens, indent = 2) => `${" ".repeat(indent)}${muted(`${uiText(key)}:`)} ${tokenValue(tokens)}`;
418339
+ const bar = currentTheme.fg(doctor.ratio >= 0.9 ? "error" : doctor.ratio >= 0.75 ? "warning" : "success", renderProgressBar(doctor.ratio, 20));
418340
+ const lines = [
418341
+ ` ${bar} ${value(`${(doctor.ratio * 100).toFixed(1)}%`.padStart(6, " "))} ${muted(`(${formatExactTokenCount(doctor.projectedTokens, locale)} / ${formatExactTokenCount(doctor.maxTokens, locale)})`)}`,
418342
+ "",
418343
+ line("export.system", doctor.system.totalTokens),
418344
+ line("contextDoctor.core", doctor.system.coreTokens, 4),
418345
+ line("contextDoctor.personality", doctor.system.personalityTokens, 4),
418346
+ line("contextDoctor.social", doctor.system.socialTokens, 4),
418347
+ line("contextDoctor.skills", doctor.system.skillTokens, 4),
418348
+ line("contextDoctor.runtime", doctor.system.runtimeTokens, 4),
418349
+ "",
418350
+ line("mcp.capability.tools", doctor.tools.totalTokens),
418351
+ line("contextDoctor.builtinTools", doctor.tools.builtinTokens, 4),
418352
+ line("contextDoctor.userTools", doctor.tools.userTokens, 4),
418353
+ line("contextDoctor.mcpTools", doctor.tools.mcpTokens, 4),
418354
+ line("contextDoctor.otherTools", doctor.tools.otherTokens, 4),
418355
+ "",
418356
+ line("export.conversation", doctor.conversationTokens),
418357
+ line("contextDoctor.providerOverhead", doctor.providerOverheadTokens),
418358
+ ` ${muted(uiText("usage.plan.metric.remaining", { count: formatExactTokenCount(doctor.freeTokens, locale) }))}`
418359
+ ];
418360
+ return lines;
418361
+ }
418362
+ async function showContextDoctor(host) {
418363
+ const doctor = buildContextDoctor(await host.requireSession().getContext());
418364
+ const panel = new UsagePanelComponent(() => buildContextDoctorLines(doctor), "primary", uiText("contextDoctor.title"));
418365
+ host.state.transcriptContainer.addChild(panel);
418366
+ host.state.ui.requestRender();
418367
+ }
418213
418368
  async function showUsage(host) {
418214
418369
  const [sessionUsage, managedUsage, runtimeStatus] = await Promise.all([
418215
418370
  loadSessionUsageReport(host),
@@ -495460,6 +495615,9 @@ async function handleBuiltInSlashCommand(host, name, args) {
495460
495615
  case "context":
495461
495616
  await showContextInsight(host);
495462
495617
  return;
495618
+ case "context-doctor":
495619
+ await showContextDoctor(host);
495620
+ return;
495463
495621
  case "usage":
495464
495622
  await showUsage(host);
495465
495623
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.289",
3
+ "version": "9.1.291",
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": {
@@ -56,5 +56,6 @@
56
56
  "dependencies": {
57
57
  "blun-king-cli": "^9.1.62",
58
58
  "node-addon-api": "^7.1.1"
59
- }
59
+ },
60
+ "devDependencies": {}
60
61
  }