blun-king-cli 9.1.495 → 9.1.496
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/CHANGELOG.md +7 -0
- package/LIESMICH.txt +9 -1
- package/README.md +9 -1
- package/bin/telegram-addressed-focus.cjs +10 -0
- package/blun.mjs +51 -12
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 9.1.496 - 2026-08-30
|
|
4
|
+
|
|
5
|
+
- Delivers Telegram user messages automatically one at a time without depending on the manual Ctrl+S or Escape release counter.
|
|
6
|
+
- Retires only the exact accepted or answered Telegram message ID, preserving newer messages from the same chat and removing delivered items from the visible queue.
|
|
7
|
+
- Enforces truthful progress for every existing visible TodoList, including sessions without an active Goal, and rejects unchanged refreshes after extended work.
|
|
8
|
+
- Hides successful internal hook payloads from visible output while keeping blocking hook failures visible.
|
|
9
|
+
|
|
3
10
|
## 9.1.495 - 2026-08-30
|
|
4
11
|
|
|
5
12
|
- Starts every new or replaced goal with a fresh visible TodoList and requires a truthful refresh after at most eight work batches.
|
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.496
|
|
13
13
|
|
|
14
14
|
Start
|
|
15
15
|
-----
|
|
@@ -65,6 +65,14 @@ geschriebenen Entwurf zu löschen. Das gilt auch bei
|
|
|
65
65
|
Autovervollständigung, Geistervorschlägen, Bash-Eingabe und einer offenen
|
|
66
66
|
Mehrzeileneingabe.
|
|
67
67
|
|
|
68
|
+
Version 9.1.496 stellt Telegram-Nutzernachrichten automatisch einzeln zu, ohne
|
|
69
|
+
die automatische Zustellung an den manuellen Strg+S-/Escape-Zähler zu koppeln.
|
|
70
|
+
Nach Annahme oder Antwort wird nur die exakt verarbeitete Nachrichten-ID aus der
|
|
71
|
+
sichtbaren Queue entfernt; spätere Meldungen desselben Chats bleiben erhalten.
|
|
72
|
+
Vorhandene Todo-Listen bleiben auch ohne aktives Ziel verbindlich und müssen nach
|
|
73
|
+
längerer Arbeit belegbaren Fortschritt zeigen. Erfolgreiche interne Hook-Ausgaben
|
|
74
|
+
bleiben unsichtbar, blockierende Hook-Fehler werden weiterhin angezeigt.
|
|
75
|
+
|
|
68
76
|
Version 9.1.495 startet jedes neue Ziel mit einer frischen sichtbaren Todo-Liste,
|
|
69
77
|
erzwingt regelmäßige wahrheitsgemäße Fortschrittsstände und quittiert normale
|
|
70
78
|
Telegram-Nachrichten erst am Zugende. Dadurch bleiben sie nach einem Neustart
|
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.496
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
## Reproduzierbares Staging und Packen
|
|
@@ -81,6 +81,14 @@ konkurrierenden Start zurückgewiesen und bleiben an der Spitze der
|
|
|
81
81
|
FIFO-Warteschlange. Für diesen normalen Wartestatus erscheint kein
|
|
82
82
|
`turn.agent_busy`-Fehler.
|
|
83
83
|
|
|
84
|
+
Version 9.1.496 stellt Telegram-Nutzernachrichten automatisch einzeln zu, ohne
|
|
85
|
+
die automatische Zustellung an den manuellen Strg+S-/Escape-Zähler zu koppeln.
|
|
86
|
+
Nach Annahme oder Antwort wird nur die exakt verarbeitete Nachrichten-ID aus der
|
|
87
|
+
sichtbaren Queue entfernt; spätere Meldungen desselben Chats bleiben erhalten.
|
|
88
|
+
Vorhandene Todo-Listen bleiben auch ohne aktives Ziel verbindlich und müssen nach
|
|
89
|
+
längerer Arbeit belegbaren Fortschritt zeigen. Erfolgreiche interne Hook-Ausgaben
|
|
90
|
+
bleiben unsichtbar, blockierende Hook-Fehler werden weiterhin angezeigt.
|
|
91
|
+
|
|
84
92
|
Version 9.1.495 startet jedes neue Ziel mit einer frischen sichtbaren Todo-Liste,
|
|
85
93
|
erzwingt regelmäßige wahrheitsgemäße Fortschrittsstände und quittiert normale
|
|
86
94
|
Telegram-Nachrichten erst am Zugende. Dadurch bleiben sie nach einem Neustart
|
|
@@ -36,6 +36,16 @@ function createAddressedChannelFocusStore(options = {}) {
|
|
|
36
36
|
return true;
|
|
37
37
|
},
|
|
38
38
|
|
|
39
|
+
clearIds(ids) {
|
|
40
|
+
const expected = new Set(Array.from(ids ?? [], (id) => String(id)));
|
|
41
|
+
if (expected.size === 0) return false;
|
|
42
|
+
const next = items.filter((item) => !expected.has(item.id));
|
|
43
|
+
if (next.length === items.length) return false;
|
|
44
|
+
items = next;
|
|
45
|
+
publish();
|
|
46
|
+
return true;
|
|
47
|
+
},
|
|
48
|
+
|
|
39
49
|
snapshot,
|
|
40
50
|
};
|
|
41
51
|
}
|
package/blun.mjs
CHANGED
|
@@ -423203,13 +423203,15 @@ function validInitialIdeaPlan(value) {
|
|
|
423203
423203
|
return active === 1;
|
|
423204
423204
|
}
|
|
423205
423205
|
function enforceGoalTodoPolicy(agent, context) {
|
|
423206
|
-
if (isIdeaGoal(agent)
|
|
423206
|
+
if (isIdeaGoal(agent)) return;
|
|
423207
|
+
const activeGoal = agent.goal.getActiveGoal();
|
|
423207
423208
|
const todos = ideaTodos(agent);
|
|
423208
423209
|
const progress = agent.goalTodoPolicyState ??= {
|
|
423209
423210
|
workCallsSinceRefresh: 0,
|
|
423210
423211
|
refreshRequired: false
|
|
423211
423212
|
};
|
|
423212
423213
|
if (todos.length === 0) {
|
|
423214
|
+
if (activeGoal === null) return;
|
|
423213
423215
|
const firstCall = context.toolCalls[0];
|
|
423214
423216
|
if (context.toolCall.id !== firstCall?.id || context.toolCall.name !== "TodoList") return {
|
|
423215
423217
|
block: true,
|
|
@@ -423224,11 +423226,37 @@ function enforceGoalTodoPolicy(agent, context) {
|
|
|
423224
423226
|
return;
|
|
423225
423227
|
}
|
|
423226
423228
|
if (context.toolCall.name === "TodoList") {
|
|
423229
|
+
const nextTodos = context.args?.todos;
|
|
423230
|
+
if (!Array.isArray(nextTodos)) return;
|
|
423231
|
+
if (nextTodos.length === 0) {
|
|
423232
|
+
if (activeGoal !== null) return {
|
|
423233
|
+
block: true,
|
|
423234
|
+
reason: "An active goal keeps its TodoList until UpdateGoal records a truthful terminal state. Reconcile the list instead of clearing it."
|
|
423235
|
+
};
|
|
423236
|
+
if (todos.some((todo) => !IDEA_TERMINAL_TODO_STATUSES.includes(todo.status))) return {
|
|
423237
|
+
block: true,
|
|
423238
|
+
reason: "Do not clear unfinished TodoList work. Record a truthful terminal status for every item first."
|
|
423239
|
+
};
|
|
423240
|
+
} else {
|
|
423241
|
+
const inProgressCount = nextTodos.filter((todo) => todo?.status === "in_progress").length;
|
|
423242
|
+
const allTerminal = nextTodos.every((todo) => IDEA_TERMINAL_TODO_STATUSES.includes(todo?.status));
|
|
423243
|
+
if (!allTerminal && inProgressCount !== 1) return {
|
|
423244
|
+
block: true,
|
|
423245
|
+
reason: "A maintained TodoList must keep exactly one item in_progress while unfinished work remains."
|
|
423246
|
+
};
|
|
423247
|
+
}
|
|
423248
|
+
if (progress.refreshRequired) {
|
|
423249
|
+
const normalized = (value) => value.map((todo) => ({ title: String(todo?.title ?? "").trim(), status: todo?.status }));
|
|
423250
|
+
if (JSON.stringify(normalized(nextTodos)) === JSON.stringify(normalized(todos))) return {
|
|
423251
|
+
block: true,
|
|
423252
|
+
reason: "TodoList is unchanged after extended work. Mark evidenced progress, advance the active item, or refine its title to the concrete verified substep before continuing."
|
|
423253
|
+
};
|
|
423254
|
+
}
|
|
423227
423255
|
progress.workCallsSinceRefresh = 0;
|
|
423228
423256
|
progress.refreshRequired = false;
|
|
423229
423257
|
return;
|
|
423230
423258
|
}
|
|
423231
|
-
if (context.toolCall.name === "UpdateGoal" && (context.args?.status === "complete" || context.args?.status === "blocked")) {
|
|
423259
|
+
if (activeGoal !== null && context.toolCall.name === "UpdateGoal" && (context.args?.status === "complete" || context.args?.status === "blocked")) {
|
|
423232
423260
|
if (todos.some((todo) => !IDEA_TERMINAL_TODO_STATUSES.includes(todo.status))) return {
|
|
423233
423261
|
block: true,
|
|
423234
423262
|
reason: "The goal cannot finish while a visible TodoList item has no truthful terminal status. Reconcile the list first."
|
|
@@ -497076,7 +497104,7 @@ function runPromptTurn(session, prompt, outputFormat, stdout, stderr, model) {
|
|
|
497076
497104
|
outputWriter.writeAssistantDelta(event.delta);
|
|
497077
497105
|
return;
|
|
497078
497106
|
case "hook.result":
|
|
497079
|
-
outputWriter.writeHookResult(event);
|
|
497107
|
+
if (shouldDisplayHookResult(event)) outputWriter.writeHookResult(event);
|
|
497080
497108
|
return;
|
|
497081
497109
|
case "thinking.delta":
|
|
497082
497110
|
outputWriter.writeThinkingDelta(event.delta);
|
|
@@ -497140,6 +497168,9 @@ function promptInputText(input) {
|
|
|
497140
497168
|
const text = input.filter((part) => part.type === "text").map((part) => part.text).join("\n\n");
|
|
497141
497169
|
return text.trim().length > 0 ? text : void 0;
|
|
497142
497170
|
}
|
|
497171
|
+
function shouldDisplayHookResult(event) {
|
|
497172
|
+
return event.blocked === true;
|
|
497173
|
+
}
|
|
497143
497174
|
var PromptTranscriptWriter = class {
|
|
497144
497175
|
assistantWriter;
|
|
497145
497176
|
thinkingWriter;
|
|
@@ -503884,6 +503915,7 @@ var BtwPanelController = class {
|
|
|
503884
503915
|
this.armInactivityTimer(this.activeForAgent(event.agentId));
|
|
503885
503916
|
return true;
|
|
503886
503917
|
case "hook.result":
|
|
503918
|
+
if (!shouldDisplayHookResult(event)) return true;
|
|
503887
503919
|
this.clearInactivityTimer(this.activeForAgent(event.agentId));
|
|
503888
503920
|
panel.appendAnswer(formatHookResultPlain(event));
|
|
503889
503921
|
this.host.state.ui.requestRender();
|
|
@@ -507960,7 +507992,7 @@ var SubAgentEventHandler = class {
|
|
|
507960
507992
|
const toolCall = this.host.streamingUI.getToolComponent(parentToolCallId);
|
|
507961
507993
|
if (toolCall === void 0) return true;
|
|
507962
507994
|
toolCall.setSubagentMeta(childAgentId, info.name);
|
|
507963
|
-
if (event.type === "hook.result") toolCall.appendSubagentText(formatHookResultPlain(event), "text");
|
|
507995
|
+
if (event.type === "hook.result" && shouldDisplayHookResult(event)) toolCall.appendSubagentText(formatHookResultPlain(event), "text");
|
|
507964
507996
|
else if (event.type === "assistant.delta") toolCall.appendSubagentText(event.delta, "text");
|
|
507965
507997
|
else if (event.type === "thinking.delta") toolCall.appendSubagentText(event.delta, "thinking");
|
|
507966
507998
|
else if (event.type === "tool.call.started") toolCall.appendSubToolCall({
|
|
@@ -508996,6 +509028,7 @@ var SessionEventHandler = class {
|
|
|
508996
509028
|
streamingUI.scheduleFlush();
|
|
508997
509029
|
}
|
|
508998
509030
|
handleHookResult(event) {
|
|
509031
|
+
if (!shouldDisplayHookResult(event)) return;
|
|
508999
509032
|
this.host.streamingUI.flushNow();
|
|
509000
509033
|
if (this.host.streamingUI.hasThinkingDraft()) this.host.streamingUI.flushThinkingToTranscript("idle");
|
|
509001
509034
|
this.host.streamingUI.finalizeAssistantStream();
|
|
@@ -510580,6 +510613,7 @@ var SessionReplayRenderer = class {
|
|
|
510580
510613
|
}
|
|
510581
510614
|
renderHookResult(context, message) {
|
|
510582
510615
|
if (message.origin?.kind !== "hook_result") return;
|
|
510616
|
+
if (message.origin.blocked !== true) return;
|
|
510583
510617
|
this.flushAssistant(context);
|
|
510584
510618
|
this.host.appendTranscriptEntry(replayEntry(context, "assistant", formatHookResultMessageForTranscript(contentPartsToText(message.content), message.origin.event, message.origin.blocked === true), "markdown"));
|
|
510585
510619
|
}
|
|
@@ -517969,7 +518003,7 @@ var BlunTUI = class {
|
|
|
517969
518003
|
canDeliverQueuedChannelHead() {
|
|
517970
518004
|
const item = this.state.queuedMessages[0];
|
|
517971
518005
|
const hasActiveTurn = this.streamingUI.hasActiveTurn() || (this.state.appState.streamingPhase !== "idle" && this.state.appState.streamingPhase !== "shell");
|
|
517972
|
-
if (this.isShuttingDown || this.queueCommandRunning || this.queueSteerInFlight !== void 0 || this.
|
|
518006
|
+
if (this.isShuttingDown || this.queueCommandRunning || this.queueSteerInFlight !== void 0 || this.editorReplacementActive || this.deferUserMessages || this.session === void 0 || this.state.appState.model.trim().length === 0 || !hasActiveTurn || item?.mode !== "channel") return false;
|
|
517973
518007
|
return true;
|
|
517974
518008
|
}
|
|
517975
518009
|
async deliverQueuedChannelHead() {
|
|
@@ -517998,7 +518032,8 @@ var BlunTUI = class {
|
|
|
517998
518032
|
}
|
|
517999
518033
|
const batchEnd = item.channelAttention === true ? 1 : item.channelUrgent === true ? this.state.queuedMessages.findIndex((queued) => queued.channelUrgent !== true) : item.channelDirect === true ? this.state.queuedMessages.findIndex((queued) => queued.channelDirect !== true) : item.channelAddressed === true ? this.state.queuedMessages.findIndex((queued) => queued.channelAddressed !== true) : this.state.queuedMessages.findIndex((queued) => queued.mode !== "channel" || queued.channelContextOnly === true || queued.channelAttention === true);
|
|
518000
518034
|
const candidateCount = batchEnd < 0 ? this.state.queuedMessages.length : batchEnd;
|
|
518001
|
-
const
|
|
518035
|
+
const deliveryLimit = this.queueFlushBatchRemaining > 0 ? this.queueFlushBatchRemaining : 1;
|
|
518036
|
+
const items = this.state.queuedMessages.slice(0, Math.min(candidateCount, deliveryLimit));
|
|
518002
518037
|
if (items.length === 0) return false;
|
|
518003
518038
|
this.state.queuedMessages = this.state.queuedMessages.slice(items.length);
|
|
518004
518039
|
this.updateQueueDisplay();
|
|
@@ -518037,6 +518072,7 @@ var BlunTUI = class {
|
|
|
518037
518072
|
stepStarted: false,
|
|
518038
518073
|
turnEnded: false,
|
|
518039
518074
|
onCommit: () => {
|
|
518075
|
+
this.clearAddressedChannelFocusIds(items.map((queued) => queued.channelFocusId));
|
|
518040
518076
|
renderTranscripts();
|
|
518041
518077
|
for (const queued of queuedItems) queued.channelTranscriptRendered = true;
|
|
518042
518078
|
const acknowledge = () => {
|
|
@@ -518112,7 +518148,7 @@ var BlunTUI = class {
|
|
|
518112
518148
|
const delivered = this.pendingChannelReplyGuards.filter((guard) => guard.chatId === chatId);
|
|
518113
518149
|
if (delivered.length === 0) return;
|
|
518114
518150
|
this.pendingChannelReplyGuards = this.pendingChannelReplyGuards.filter((guard) => guard.chatId !== chatId);
|
|
518115
|
-
this.
|
|
518151
|
+
this.clearAddressedChannelFocusIds(delivered.map((guard) => guard.channelFocusId));
|
|
518116
518152
|
for (const guard of delivered) if (guard.directFocus === true) this.directFocusController.noteReplyDelivered(chatId);
|
|
518117
518153
|
this.updateAddressedChannelFocus();
|
|
518118
518154
|
}
|
|
@@ -518122,6 +518158,9 @@ var BlunTUI = class {
|
|
|
518122
518158
|
clearAddressedChannelFocus(chatId) {
|
|
518123
518159
|
return this.addressedChannelFocusStore.clearChat(chatId);
|
|
518124
518160
|
}
|
|
518161
|
+
clearAddressedChannelFocusIds(ids) {
|
|
518162
|
+
return this.addressedChannelFocusStore.clearIds(ids.filter((id) => id !== void 0));
|
|
518163
|
+
}
|
|
518125
518164
|
updateAddressedChannelFocus() {
|
|
518126
518165
|
this.state.channelFocusContainer.clear();
|
|
518127
518166
|
const queuedFocusIds = new Set([
|
|
@@ -518500,9 +518539,7 @@ var BlunTUI = class {
|
|
|
518500
518539
|
else if (directEnvelope !== void 0) enqueueTelegramDirect(this.state.queuedMessages, item);
|
|
518501
518540
|
else if (addressed) enqueueTelegramAddressed(this.state.queuedMessages, item);
|
|
518502
518541
|
else this.state.queuedMessages.push(item);
|
|
518503
|
-
|
|
518504
|
-
if (activeTurn) this.releaseNextQueuedMessage();
|
|
518505
|
-
if (this.queueFlushBatchRemaining > 0) this.channelQueueDeadline.requestDeliveryNow();
|
|
518542
|
+
this.channelQueueDeadline.requestDeliveryNow();
|
|
518506
518543
|
this.scheduleQueueDrain();
|
|
518507
518544
|
this.track("input_queue");
|
|
518508
518545
|
this.updateQueueDisplay();
|
|
@@ -518697,6 +518734,7 @@ var BlunTUI = class {
|
|
|
518697
518734
|
}, imagePart] : focusedModelInput;
|
|
518698
518735
|
session.promptAccepted(promptInput, channelPromptOrigin(channelReportSources)).then((result) => {
|
|
518699
518736
|
if (result.duplicate === true) {
|
|
518737
|
+
if (channelFocusId !== void 0) this.clearAddressedChannelFocusIds([channelFocusId]);
|
|
518700
518738
|
finishPersonalMemoryRememberIntentTurn(session.id);
|
|
518701
518739
|
if (installedGuard !== void 0 && this.pendingChannelReplyGuard === installedGuard) this.pendingChannelReplyGuard = previousGuard;
|
|
518702
518740
|
this.setAppState({ streamingPhase: "idle" });
|
|
@@ -518708,6 +518746,7 @@ var BlunTUI = class {
|
|
|
518708
518746
|
return;
|
|
518709
518747
|
}
|
|
518710
518748
|
if (result.accepted) {
|
|
518749
|
+
if (channelFocusId !== void 0) this.clearAddressedChannelFocusIds([channelFocusId]);
|
|
518711
518750
|
if (acknowledge !== void 0 && result.turnId !== null && result.turnId !== void 0) {
|
|
518712
518751
|
this.channelPromptInFlight = {
|
|
518713
518752
|
turnId: String(result.turnId),
|
|
@@ -518841,7 +518880,7 @@ var BlunTUI = class {
|
|
|
518841
518880
|
const args = entry.toolCallData?.args;
|
|
518842
518881
|
return String(args?.["chat_id"] ?? args?.["chatId"] ?? "") === guard.chatId;
|
|
518843
518882
|
}) || outboxGrewForChat(guard.outboxMarker, guard.chatId)) {
|
|
518844
|
-
this.
|
|
518883
|
+
this.clearAddressedChannelFocusIds?.([guard.channelFocusId]);
|
|
518845
518884
|
if (guard.directFocus === true) this.directFocusController.noteReplyDelivered(guard.chatId);
|
|
518846
518885
|
continue;
|
|
518847
518886
|
}
|
|
@@ -518867,7 +518906,7 @@ var BlunTUI = class {
|
|
|
518867
518906
|
if (finalText.length === 0) continue;
|
|
518868
518907
|
sendReplyFallback(guard.chatId, finalText, guard.contextOnly).then((sent) => {
|
|
518869
518908
|
if (!sent) return;
|
|
518870
|
-
this.
|
|
518909
|
+
this.clearAddressedChannelFocusIds?.([guard.channelFocusId]);
|
|
518871
518910
|
if (guard.directFocus === true) this.directFocusController.noteReplyDelivered(guard.chatId);
|
|
518872
518911
|
this.showStatus(uiText("blunTui.telegram.fallbackDelivered"));
|
|
518873
518912
|
});
|