blun-king-cli 9.1.197 → 9.1.199
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.
|
@@ -5,6 +5,10 @@ const MAX_RECENT_ASSISTANT_RESPONSES = 8;
|
|
|
5
5
|
const REQUIRED_MATCHING_RESPONSES = 3;
|
|
6
6
|
const RESPONSE_SIMILARITY_THRESHOLD = 0.78;
|
|
7
7
|
const REPEATED_RESPONSE_PLACEHOLDER = '[Historical repeated assistant response omitted; newer user corrections and instructions supersede it.]';
|
|
8
|
+
const INTRA_MESSAGE_MIN_REPEATS = 3;
|
|
9
|
+
const INTRA_MESSAGE_MIN_BLOCK_CHARS = 40;
|
|
10
|
+
const INTRA_MESSAGE_MIN_SAVED_CHARS = 1_000;
|
|
11
|
+
const INTRA_MESSAGE_REPEAT_PLACEHOLDER = '[Exact repeated assistant paragraphs omitted from model projection; raw history preserved.]';
|
|
8
12
|
|
|
9
13
|
function isUserPrompt(message) {
|
|
10
14
|
if (message?.role !== 'user') return false;
|
|
@@ -100,12 +104,74 @@ function detectRepeatedAssistantResponse(history) {
|
|
|
100
104
|
};
|
|
101
105
|
}
|
|
102
106
|
|
|
107
|
+
function compactRepeatedAssistantParagraphs(message) {
|
|
108
|
+
if (
|
|
109
|
+
message?.role !== 'assistant'
|
|
110
|
+
|| (message.toolCalls?.length ?? 0) > 0
|
|
111
|
+
|| message.origin?.kind === 'injection'
|
|
112
|
+
|| !Array.isArray(message.content)
|
|
113
|
+
) return null;
|
|
114
|
+
|
|
115
|
+
const textParts = message.content.filter(
|
|
116
|
+
(part) => part?.type === 'text' && typeof part.text === 'string',
|
|
117
|
+
);
|
|
118
|
+
if (textParts.length !== 1 || message.content.some(
|
|
119
|
+
(part) => part?.type !== 'text' && part?.type !== 'think',
|
|
120
|
+
)) return null;
|
|
121
|
+
|
|
122
|
+
const text = textParts[0].text;
|
|
123
|
+
if (/```|~~~/u.test(text)) return null;
|
|
124
|
+
const blocks = text.split(/\n\s*\n/u).map((block) => block.trim()).filter(Boolean);
|
|
125
|
+
if (blocks.length < INTRA_MESSAGE_MIN_REPEATS + 1) return null;
|
|
126
|
+
|
|
127
|
+
const counts = new Map();
|
|
128
|
+
for (const block of blocks) counts.set(block, (counts.get(block) ?? 0) + 1);
|
|
129
|
+
const repeated = new Set([...counts]
|
|
130
|
+
.filter(([block, count]) => (
|
|
131
|
+
block.length >= INTRA_MESSAGE_MIN_BLOCK_CHARS
|
|
132
|
+
&& count >= INTRA_MESSAGE_MIN_REPEATS
|
|
133
|
+
))
|
|
134
|
+
.map(([block]) => block));
|
|
135
|
+
if (repeated.size === 0) return null;
|
|
136
|
+
|
|
137
|
+
const seen = new Set();
|
|
138
|
+
const projectedBlocks = [];
|
|
139
|
+
let markerAdded = false;
|
|
140
|
+
for (const block of blocks) {
|
|
141
|
+
if (!repeated.has(block) || !seen.has(block)) {
|
|
142
|
+
projectedBlocks.push(block);
|
|
143
|
+
if (repeated.has(block)) seen.add(block);
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (!markerAdded) {
|
|
147
|
+
projectedBlocks.push(INTRA_MESSAGE_REPEAT_PLACEHOLDER);
|
|
148
|
+
markerAdded = true;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const projectedText = projectedBlocks.join('\n\n');
|
|
153
|
+
if (text.length - projectedText.length < INTRA_MESSAGE_MIN_SAVED_CHARS) return null;
|
|
154
|
+
return {
|
|
155
|
+
...message,
|
|
156
|
+
content: message.content.map((part) => (
|
|
157
|
+
part === textParts[0] ? { ...part, text: projectedText } : part
|
|
158
|
+
)),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
103
162
|
function projectRepeatedAssistantResponses(history) {
|
|
104
163
|
const detection = detectRepeatedAssistantResponse(history);
|
|
105
|
-
|
|
164
|
+
let changed = false;
|
|
165
|
+
const intraMessageProjected = history.map((message) => {
|
|
166
|
+
const projected = compactRepeatedAssistantParagraphs(message);
|
|
167
|
+
if (projected === null) return message;
|
|
168
|
+
changed = true;
|
|
169
|
+
return projected;
|
|
170
|
+
});
|
|
171
|
+
if (detection === null) return changed ? intraMessageProjected : history;
|
|
106
172
|
|
|
107
173
|
const repeatedIndexes = new Set(detection.indexes);
|
|
108
|
-
return
|
|
174
|
+
return intraMessageProjected.map((message, index) => {
|
|
109
175
|
if (!repeatedIndexes.has(index)) return message;
|
|
110
176
|
return {
|
|
111
177
|
...message,
|
|
@@ -115,12 +181,17 @@ function projectRepeatedAssistantResponses(history) {
|
|
|
115
181
|
}
|
|
116
182
|
|
|
117
183
|
module.exports = {
|
|
184
|
+
INTRA_MESSAGE_MIN_BLOCK_CHARS,
|
|
185
|
+
INTRA_MESSAGE_MIN_REPEATS,
|
|
186
|
+
INTRA_MESSAGE_MIN_SAVED_CHARS,
|
|
187
|
+
INTRA_MESSAGE_REPEAT_PLACEHOLDER,
|
|
118
188
|
MAX_RECENT_ASSISTANT_RESPONSES,
|
|
119
189
|
MIN_RESPONSE_CHARS,
|
|
120
190
|
REQUIRED_MATCHING_RESPONSES,
|
|
121
191
|
REPEATED_RESPONSE_PLACEHOLDER,
|
|
122
192
|
RESPONSE_SIMILARITY_THRESHOLD,
|
|
123
193
|
assistantResponseText,
|
|
194
|
+
compactRepeatedAssistantParagraphs,
|
|
124
195
|
detectRepeatedAssistantResponse,
|
|
125
196
|
projectRepeatedAssistantResponses,
|
|
126
197
|
responseSimilarity,
|
package/blun.mjs
CHANGED
|
@@ -260297,7 +260297,7 @@ async function budgetToolResultForModel(options) {
|
|
|
260297
260297
|
return persistToolResultForModel(options, text);
|
|
260298
260298
|
}
|
|
260299
260299
|
function reusableReadSourcePath(options) {
|
|
260300
|
-
if (options.toolName !== "Read" || options.result.isError === true
|
|
260300
|
+
if (options.toolName !== "Read" || options.result.isError === true) return;
|
|
260301
260301
|
const path = options.toolArgs?.path;
|
|
260302
260302
|
if (typeof path !== "string" || path.trim().length === 0) return;
|
|
260303
260303
|
return path;
|
|
@@ -260319,7 +260319,6 @@ function referenceReadSourceForModel(options, text, outputPath) {
|
|
|
260319
260319
|
async function persistToolResultForModel(options, knownText) {
|
|
260320
260320
|
const text = knownText ?? persistableToolResultText(options.result.output);
|
|
260321
260321
|
if (text === void 0) return options.result;
|
|
260322
|
-
if (options.result.truncated === true) return options.result;
|
|
260323
260322
|
if (options.homedir === void 0) return options.result;
|
|
260324
260323
|
const outputPath = await saveToolResult({
|
|
260325
260324
|
homedir: options.homedir,
|
|
@@ -260332,7 +260331,7 @@ async function persistToolResultForModel(options, knownText) {
|
|
|
260332
260331
|
text,
|
|
260333
260332
|
previewChars: TOOL_RESULT_PREVIEW_CHARS
|
|
260334
260333
|
}));
|
|
260335
|
-
const output = renderPersistedToolResult(options.toolName, options.toolCallId, text, outputPath);
|
|
260334
|
+
const output = renderPersistedToolResult(options.toolName, options.toolCallId, text, outputPath, options.result.truncated === true);
|
|
260336
260335
|
return options.result.isError === true ? {
|
|
260337
260336
|
...options.result,
|
|
260338
260337
|
output,
|
|
@@ -260365,10 +260364,14 @@ async function saveToolResult(options, text) {
|
|
|
260365
260364
|
return;
|
|
260366
260365
|
}
|
|
260367
260366
|
}
|
|
260368
|
-
function renderPersistedToolResult(toolName, toolCallId, text, outputPath) {
|
|
260367
|
+
function renderPersistedToolResult(toolName, toolCallId, text, outputPath, toolTruncated = false) {
|
|
260369
260368
|
const lines = [
|
|
260370
260369
|
TOOL_RESULT_OFFLOAD_MARKER,
|
|
260371
260370
|
`Tool output exceeded ${String(TOOL_RESULT_MAX_CHARS)} characters; showing a preview only.`,
|
|
260371
|
+
...(toolTruncated ? [
|
|
260372
|
+
"The tool had already truncated its raw output; the complete returned result was stored.",
|
|
260373
|
+
"stored_result_scope: tool_truncated_output"
|
|
260374
|
+
] : []),
|
|
260372
260375
|
`tool_name: ${toolName}`,
|
|
260373
260376
|
`tool_call_id: ${toolCallId}`,
|
|
260374
260377
|
`output_size_chars: ${String(text.length)}`,
|