blun-king-cli 9.1.233 → 9.1.235

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.
@@ -8,6 +8,7 @@ const ASSISTANT_MESSAGE_OFFLOAD_MARKER = '[Assistant message offloaded]';
8
8
  const ASSISTANT_TOOL_NARRATION_MIN_CHARS = 120;
9
9
  const ASSISTANT_TOOL_NARRATION_MARKER = '[Earlier completed tool-step narration compacted]';
10
10
  const ASSISTANT_POST_TELEGRAM_REPLY_MARKER = '[Earlier post-reply status compacted]';
11
+ const ASSISTANT_COMPLETED_SUBAGENT_PROMPT_MARKER = '[Earlier completed subagent task omitted; use its result below]';
11
12
  const SYNTHETIC_TOOL_ARGUMENT_MARKER = JSON.stringify({
12
13
  _blun_compacted: '[Old tool call arguments cleared]',
13
14
  });
@@ -123,6 +124,78 @@ function compactHistoricalPostTelegramReplyNarration(messages) {
123
124
  return changed ? projected : messages;
124
125
  }
125
126
 
127
+ function completedSubagentResultIds(messages) {
128
+ return new Set(messages.filter((message) => {
129
+ if (
130
+ message?.role !== 'tool'
131
+ || typeof message.toolCallId !== 'string'
132
+ || message.isError === true
133
+ || !Array.isArray(message.content)
134
+ || !message.content.every((part) => part?.type === 'text' && typeof part.text === 'string')
135
+ ) return false;
136
+ const text = message.content.map((part) => part.text).join('\n');
137
+ return /(?:^|\n)status:\s*completed(?:\s|$)/iu.test(text);
138
+ }).map((message) => message.toolCallId));
139
+ }
140
+
141
+ function compactCompletedSubagentCall(call, completedIds) {
142
+ if (
143
+ call?.name !== 'Agent'
144
+ || !completedIds.has(call.id)
145
+ || (typeof call.arguments !== 'string'
146
+ && (call.arguments === null || typeof call.arguments !== 'object' || Array.isArray(call.arguments)))
147
+ ) return call;
148
+
149
+ let args = call.arguments;
150
+ if (typeof args === 'string') {
151
+ try {
152
+ args = JSON.parse(args);
153
+ } catch {
154
+ return call;
155
+ }
156
+ }
157
+ if (args === null || typeof args !== 'object' || Array.isArray(args)) return call;
158
+ if (
159
+ typeof args.prompt !== 'string'
160
+ || args.prompt.length <= ASSISTANT_COMPLETED_SUBAGENT_PROMPT_MARKER.length
161
+ || args.prompt === ASSISTANT_COMPLETED_SUBAGENT_PROMPT_MARKER
162
+ ) return call;
163
+
164
+ const compactedArgs = {
165
+ ...args,
166
+ prompt: ASSISTANT_COMPLETED_SUBAGENT_PROMPT_MARKER,
167
+ };
168
+ return {
169
+ ...call,
170
+ arguments: typeof call.arguments === 'string'
171
+ ? JSON.stringify(compactedArgs)
172
+ : compactedArgs,
173
+ };
174
+ }
175
+
176
+ function compactHistoricalCompletedSubagentPrompts(messages) {
177
+ if (!Array.isArray(messages) || messages.length === 0) return messages;
178
+
179
+ const completedIds = completedSubagentResultIds(messages);
180
+ if (completedIds.size === 0) return messages;
181
+ const recentStart = Math.max(0, messages.length - ASSISTANT_MESSAGE_KEEP_RECENT_MESSAGES);
182
+ let changed = false;
183
+ const projected = messages.map((message, historyIndex) => {
184
+ if (
185
+ historyIndex >= recentStart
186
+ || message?.role !== 'assistant'
187
+ || !Array.isArray(message.toolCalls)
188
+ || message.toolCalls.length === 0
189
+ ) return message;
190
+ const toolCalls = message.toolCalls.map((call) => compactCompletedSubagentCall(call, completedIds));
191
+ if (toolCalls.every((call, index) => call === message.toolCalls[index])) return message;
192
+ changed = true;
193
+ return { ...message, toolCalls };
194
+ });
195
+
196
+ return changed ? projected : messages;
197
+ }
198
+
126
199
  function removeSyntheticToolArgumentFailures(messages) {
127
200
  if (!Array.isArray(messages) || messages.length === 0) return messages;
128
201
 
@@ -179,6 +252,8 @@ module.exports = {
179
252
  ASSISTANT_TOOL_NARRATION_MARKER,
180
253
  ASSISTANT_TOOL_NARRATION_MIN_CHARS,
181
254
  ASSISTANT_POST_TELEGRAM_REPLY_MARKER,
255
+ ASSISTANT_COMPLETED_SUBAGENT_PROMPT_MARKER,
256
+ compactHistoricalCompletedSubagentPrompts,
182
257
  compactHistoricalPostTelegramReplyNarration,
183
258
  createAssistantMessagePreview,
184
259
  isSyntheticToolArguments,
@@ -13,6 +13,7 @@ const TOOL_RESULT_HISTORICAL_MIN_ITEM_CHARS = 600;
13
13
  const TOOL_RESULT_HISTORICAL_REPLACEMENT_BUDGET_CHARS = 600;
14
14
  const TOOL_RESULT_SUCCESS_KEEP_RECENT_MESSAGES = 12;
15
15
  const TOOL_RESULT_HISTORICAL_SUCCESS_MARKER = '[Old tool result content cleared]';
16
+ const TOOL_RESULT_REPEAT_MARKER = '[Repeated tool result omitted]';
16
17
 
17
18
  function shouldOffloadToolResult(textLength) {
18
19
  return Number.isFinite(textLength) && textLength > TOOL_RESULT_MAX_CHARS;
@@ -102,6 +103,102 @@ function compactHistoricalSuccessfulToolResults(messages) {
102
103
  return changed ? projected : messages;
103
104
  }
104
105
 
106
+ function toolCallSignaturesById(messages) {
107
+ const signatures = new Map();
108
+
109
+ for (const message of messages) {
110
+ if (!Array.isArray(message?.toolCalls)) continue;
111
+ for (const call of message.toolCalls) {
112
+ const id = call?.id ?? call?.toolCallId;
113
+ if (typeof id !== 'string' || typeof call?.name !== 'string') continue;
114
+ const args = typeof call.arguments === 'string'
115
+ ? call.arguments
116
+ : JSON.stringify(call.arguments ?? null);
117
+ signatures.set(id, `${call.name}\n${args}`);
118
+ }
119
+ }
120
+
121
+ return signatures;
122
+ }
123
+
124
+ function repeatedToolResultReference(newestToolCallId) {
125
+ return [
126
+ TOOL_RESULT_REPEAT_MARKER,
127
+ `same_as_tool_call_id: ${newestToolCallId}`,
128
+ 'reason: identical successful result for the same tool call arguments',
129
+ ].join('\n');
130
+ }
131
+
132
+ function dedupeRepeatedSuccessfulToolResults(sourceMessages, projectedMessages = sourceMessages) {
133
+ if (
134
+ !Array.isArray(sourceMessages)
135
+ || !Array.isArray(projectedMessages)
136
+ || sourceMessages.length === 0
137
+ || sourceMessages.length !== projectedMessages.length
138
+ ) return projectedMessages;
139
+
140
+ const callSignatures = toolCallSignaturesById(sourceMessages);
141
+ const seenResultsByCall = new Map();
142
+ let changed = false;
143
+ const projected = projectedMessages.slice();
144
+
145
+ for (let index = sourceMessages.length - 1; index >= 0; index -= 1) {
146
+ const message = sourceMessages[index];
147
+ const toolCallId = message?.toolCallId;
148
+ if (
149
+ message?.role !== 'tool'
150
+ || message.isError === true
151
+ || typeof toolCallId !== 'string'
152
+ || !Array.isArray(message.content)
153
+ || message.content.length === 0
154
+ || isPersistedToolResultReference(message.content)
155
+ || !message.content.every((part) => part?.type === 'text' && typeof part.text === 'string')
156
+ ) continue;
157
+
158
+ const callSignature = callSignatures.get(toolCallId);
159
+ if (callSignature === undefined) continue;
160
+ const resultShape = message.content.length;
161
+ const resultSignature = resultShape === 1
162
+ ? message.content[0].text
163
+ : JSON.stringify(message.content.map((part) => part.text));
164
+ let seenResults = seenResultsByCall.get(callSignature);
165
+ if (seenResults === undefined) {
166
+ seenResults = new Map();
167
+ seenResultsByCall.set(callSignature, seenResults);
168
+ }
169
+ let seenResultsForShape = seenResults.get(resultShape);
170
+ if (seenResultsForShape === undefined) {
171
+ seenResultsForShape = new Map();
172
+ seenResults.set(resultShape, seenResultsForShape);
173
+ }
174
+ const newest = seenResultsForShape.get(resultSignature);
175
+ if (newest === undefined) {
176
+ seenResultsForShape.set(resultSignature, { toolCallId, index });
177
+ continue;
178
+ }
179
+
180
+ const reference = repeatedToolResultReference(newest.toolCallId);
181
+ const textChars = message.content.reduce((total, part) => total + part.text.length, 0);
182
+ const projectedMessage = projected[index];
183
+ if (
184
+ reference.length >= textChars
185
+ || projectedMessage?.role !== 'tool'
186
+ || projectedMessage.toolCallId !== toolCallId
187
+ ) continue;
188
+ projected[index] = {
189
+ ...projectedMessage,
190
+ content: [{ type: 'text', text: reference }],
191
+ };
192
+ projected[newest.index] = {
193
+ ...projected[newest.index],
194
+ content: sourceMessages[newest.index].content,
195
+ };
196
+ changed = true;
197
+ }
198
+
199
+ return changed ? projected : projectedMessages;
200
+ }
201
+
105
202
  function selectToolResultBatchOffloads(textLengths) {
106
203
  if (!Array.isArray(textLengths) || textLengths.length < 2) return [];
107
204
 
@@ -170,6 +267,7 @@ module.exports = {
170
267
  TOOL_RESULT_HISTORICAL_MIN_ITEM_CHARS,
171
268
  TOOL_RESULT_HISTORICAL_REPLACEMENT_BUDGET_CHARS,
172
269
  TOOL_RESULT_HISTORICAL_SUCCESS_MARKER,
270
+ TOOL_RESULT_REPEAT_MARKER,
173
271
  TOOL_RESULT_MAX_CHARS,
174
272
  TOOL_RESULT_PREVIEW_CHARS,
175
273
  TOOL_RESULT_RECOVERY_PAGE_LINES,
@@ -178,6 +276,7 @@ module.exports = {
178
276
  compactHistoricalSuccessfulToolResults,
179
277
  compactPersistedToolResultReference,
180
278
  createToolResultPreview,
279
+ dedupeRepeatedSuccessfulToolResults,
181
280
  isPersistedToolResultReference,
182
281
  selectHistoricalToolResultOffloads,
183
282
  selectToolResultBatchOffloads,
package/blun.mjs CHANGED
@@ -79000,7 +79000,7 @@ var init_context$2 = __esmMin((() => {
79000
79000
  const historicalTelegramProjected = projectHistoricalUnaddressedTelegramMessages(duplicateUserMessagesProjected);
79001
79001
  const assistantOffloaded = this.agent.assistantMessageOffload.compact(historicalTelegramProjected);
79002
79002
  const repeatedAssistantProjected = projectRepeatedAssistantResponses(assistantOffloaded);
79003
- const result = project(this.agent.microCompaction.compact(compactHistoricalSuccessfulToolResults(this.agent.toolResultBatchOffload.compact(dedupeRecurringCronWakeups(dedupeRepeatedInjections(compactHistoricalSkillActivations(compactBaselineSkillInjections(repeatedAssistantProjected))))))), {
79003
+ const result = project(this.agent.microCompaction.compact(compactHistoricalSuccessfulToolResults(dedupeRepeatedSuccessfulToolResults(repeatedAssistantProjected, this.agent.toolResultBatchOffload.compact(dedupeRecurringCronWakeups(dedupeRepeatedInjections(compactHistoricalSkillActivations(compactBaselineSkillInjections(repeatedAssistantProjected)))))))), {
79004
79004
  ...options,
79005
79005
  onAnomaly: (anomaly) => {
79006
79006
  anomalies.push(anomaly);
@@ -260553,7 +260553,7 @@ function renderHistoricalToolResultReference(toolName, toolCallId, text, outputP
260553
260553
  function safeToolResultFileStem(toolName, toolCallId) {
260554
260554
  return `${toolName}-${toolCallId}`.replace(/[^a-zA-Z0-9._-]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 80) || "tool-result";
260555
260555
  }
260556
- var TOOL_RESULT_MAX_CHARS, TOOL_RESULT_PREVIEW_CHARS, TOOL_RESULT_RECOVERY_PAGE_LINES, TOOL_RESULT_OFFLOAD_MARKER, TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES, shouldOffloadToolResult, createToolResultPreview, compactPersistedToolResultReference, compactHistoricalSuccessfulToolResults, selectToolResultBatchOffloads, selectHistoricalToolResultOffloads, buildToolResultOffloadTelemetry;
260556
+ var TOOL_RESULT_MAX_CHARS, TOOL_RESULT_PREVIEW_CHARS, TOOL_RESULT_RECOVERY_PAGE_LINES, TOOL_RESULT_OFFLOAD_MARKER, TOOL_RESULT_HISTORICAL_KEEP_RECENT_MESSAGES, shouldOffloadToolResult, createToolResultPreview, compactPersistedToolResultReference, compactHistoricalSuccessfulToolResults, dedupeRepeatedSuccessfulToolResults, selectToolResultBatchOffloads, selectHistoricalToolResultOffloads, buildToolResultOffloadTelemetry;
260557
260557
  var init_tool_result_budget = __esmMin((() => {
260558
260558
  init_dist$6();
260559
260559
  const toolResultOffloadPolicy = createRequire(import.meta.url)("./bin/tool-result-offload-policy.cjs");
@@ -260567,6 +260567,7 @@ var init_tool_result_budget = __esmMin((() => {
260567
260567
  createToolResultPreview = toolResultOffloadPolicy.createToolResultPreview;
260568
260568
  compactPersistedToolResultReference = toolResultOffloadPolicy.compactPersistedToolResultReference;
260569
260569
  compactHistoricalSuccessfulToolResults = toolResultOffloadPolicy.compactHistoricalSuccessfulToolResults;
260570
+ dedupeRepeatedSuccessfulToolResults = toolResultOffloadPolicy.dedupeRepeatedSuccessfulToolResults;
260570
260571
  selectToolResultBatchOffloads = toolResultOffloadPolicy.selectToolResultBatchOffloads;
260571
260572
  selectHistoricalToolResultOffloads = toolResultOffloadPolicy.selectHistoricalToolResultOffloads;
260572
260573
  }));
@@ -260894,7 +260895,7 @@ function renderPersistedAssistantMessage(text, outputPath) {
260894
260895
  createAssistantMessagePreview(text)
260895
260896
  ].join("\n");
260896
260897
  }
260897
- var ASSISTANT_MESSAGE_MAX_CHARS, ASSISTANT_MESSAGE_OFFLOAD_MARKER, ASSISTANT_TOOL_NARRATION_MARKER, shouldOffloadHistoricalAssistantMessage, shouldCompactHistoricalAssistantToolNarration, compactHistoricalPostTelegramReplyNarration, removeSyntheticToolArgumentFailures, createAssistantMessagePreview;
260898
+ var ASSISTANT_MESSAGE_MAX_CHARS, ASSISTANT_MESSAGE_OFFLOAD_MARKER, ASSISTANT_TOOL_NARRATION_MARKER, shouldOffloadHistoricalAssistantMessage, shouldCompactHistoricalAssistantToolNarration, compactHistoricalPostTelegramReplyNarration, compactHistoricalCompletedSubagentPrompts, removeSyntheticToolArgumentFailures, createAssistantMessagePreview;
260898
260899
  var init_assistant_message_offload = __esmMin((() => {
260899
260900
  const policy = createRequire(import.meta.url)("./bin/assistant-message-offload-policy.cjs");
260900
260901
  ASSISTANT_MESSAGE_MAX_CHARS = policy.ASSISTANT_MESSAGE_MAX_CHARS;
@@ -260903,6 +260904,7 @@ var init_assistant_message_offload = __esmMin((() => {
260903
260904
  shouldOffloadHistoricalAssistantMessage = policy.shouldOffloadHistoricalAssistantMessage;
260904
260905
  shouldCompactHistoricalAssistantToolNarration = policy.shouldCompactHistoricalAssistantToolNarration;
260905
260906
  compactHistoricalPostTelegramReplyNarration = policy.compactHistoricalPostTelegramReplyNarration;
260907
+ compactHistoricalCompletedSubagentPrompts = policy.compactHistoricalCompletedSubagentPrompts;
260906
260908
  removeSyntheticToolArgumentFailures = policy.removeSyntheticToolArgumentFailures;
260907
260909
  createAssistantMessagePreview = policy.createAssistantMessagePreview;
260908
260910
  }));
@@ -260990,7 +260992,8 @@ var AssistantMessageOffload = class {
260990
260992
  return { ...message, content: replacement.content };
260991
260993
  });
260992
260994
  const narrationProjected = compactHistoricalPostTelegramReplyNarration(changed ? projected : messages);
260993
- return removeSyntheticToolArgumentFailures(narrationProjected);
260995
+ const subagentProjected = compactHistoricalCompletedSubagentPrompts(narrationProjected);
260996
+ return removeSyntheticToolArgumentFailures(subagentProjected);
260994
260997
  }
260995
260998
  reset(history = this.agent.context?.history ?? []) {
260996
260999
  const activeHashes = new Set(history.map((message) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.233",
3
+ "version": "9.1.235",
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": {