blun-king-cli 9.1.203 → 9.1.205
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.
|
@@ -1,6 +1,69 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const ERROR_MEMORY_MAX_CHARS = 2_800;
|
|
4
|
+
const ERROR_MEMORY_MAX_PATTERNS = 6;
|
|
5
|
+
const CORE_PATTERN_NUMBERS = new Set([4, 9, 10, 11]);
|
|
6
|
+
const STOP_WORDS = new Set([
|
|
7
|
+
'aber', 'alle', 'alles', 'auch', 'belegt', 'beweis', 'echt', 'echte', 'echten',
|
|
8
|
+
'echter', 'eine', 'einem', 'einen', 'einer', 'das', 'den', 'fuer', 'gegen',
|
|
9
|
+
'haben', 'hier', 'immer',
|
|
10
|
+
'jetzt', 'kann', 'machen', 'mehr', 'nicht', 'noch', 'oder', 'pruefe', 'pruefen',
|
|
11
|
+
'pruefung', 'sein', 'sind', 'soll', 'und', 'vollstaendig', 'vollstaendige',
|
|
12
|
+
'wenn', 'werden', 'with', 'that',
|
|
13
|
+
'this', 'from', 'have', 'into', 'your', 'you', 'the', 'and', 'for', 'are',
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
function normalizedTerms(value) {
|
|
17
|
+
return [...new Set(String(value || '')
|
|
18
|
+
.normalize('NFKD')
|
|
19
|
+
.replace(/\p{M}/gu, '')
|
|
20
|
+
.toLowerCase()
|
|
21
|
+
.match(/[\p{L}\p{N}_-]{3,}/gu) || [])]
|
|
22
|
+
.filter((term) => !STOP_WORDS.has(term));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function fieldMatchesTerm(fieldTerms, term) {
|
|
26
|
+
return fieldTerms.some((fieldTerm) => (
|
|
27
|
+
fieldTerm === term
|
|
28
|
+
|| (term.length >= 6 && fieldTerm.includes(term))
|
|
29
|
+
|| (fieldTerm.length >= 6 && term.includes(fieldTerm))
|
|
30
|
+
));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function selectRelevantErrorMemoryPatterns(patterns, query, options = {}) {
|
|
34
|
+
const maxPatterns = Math.max(1, Number(options.maxPatterns) || ERROR_MEMORY_MAX_PATTERNS);
|
|
35
|
+
const source = Array.isArray(patterns) ? patterns.filter(Boolean) : [];
|
|
36
|
+
if (source.length <= maxPatterns) return source;
|
|
37
|
+
|
|
38
|
+
const queryTerms = normalizedTerms(query);
|
|
39
|
+
const ranked = source.map((pattern, index) => {
|
|
40
|
+
const title = normalizedTerms(pattern.title);
|
|
41
|
+
const rule = normalizedTerms(pattern.rule);
|
|
42
|
+
const check = normalizedTerms(pattern.check);
|
|
43
|
+
let score = 0;
|
|
44
|
+
for (const term of queryTerms) {
|
|
45
|
+
if (fieldMatchesTerm(title, term)) score += 4;
|
|
46
|
+
if (fieldMatchesTerm(rule, term)) score += 2;
|
|
47
|
+
if (fieldMatchesTerm(check, term)) score += 1;
|
|
48
|
+
}
|
|
49
|
+
return { index, pattern, score };
|
|
50
|
+
});
|
|
51
|
+
const selectedIndexes = new Set(ranked
|
|
52
|
+
.filter(({ pattern }) => CORE_PATTERN_NUMBERS.has(Number(pattern.number)))
|
|
53
|
+
.map(({ index }) => index));
|
|
54
|
+
ranked
|
|
55
|
+
.filter(({ index, score }) => !selectedIndexes.has(index) && score > 0)
|
|
56
|
+
.sort((left, right) => right.score - left.score || left.index - right.index)
|
|
57
|
+
.slice(0, Math.max(0, maxPatterns - selectedIndexes.size))
|
|
58
|
+
.forEach(({ index }) => selectedIndexes.add(index));
|
|
59
|
+
|
|
60
|
+
if (selectedIndexes.size === 0) {
|
|
61
|
+
source.slice(-Math.min(2, maxPatterns)).forEach((pattern) => {
|
|
62
|
+
selectedIndexes.add(source.indexOf(pattern));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return source.filter((pattern, index) => selectedIndexes.has(index)).slice(0, maxPatterns);
|
|
66
|
+
}
|
|
4
67
|
|
|
5
68
|
function buildCompactErrorMemoryReminder(patterns) {
|
|
6
69
|
const lines = [
|
|
@@ -42,7 +105,9 @@ function compactLegacyErrorMemoryReminder(text) {
|
|
|
42
105
|
}
|
|
43
106
|
|
|
44
107
|
module.exports = {
|
|
108
|
+
ERROR_MEMORY_MAX_PATTERNS,
|
|
45
109
|
ERROR_MEMORY_MAX_CHARS,
|
|
46
110
|
buildCompactErrorMemoryReminder,
|
|
47
111
|
compactLegacyErrorMemoryReminder,
|
|
112
|
+
selectRelevantErrorMemoryPatterns,
|
|
48
113
|
};
|
|
@@ -8,6 +8,7 @@ const REPEATED_RESPONSE_PLACEHOLDER = '[Historical repeated assistant response o
|
|
|
8
8
|
const INTRA_MESSAGE_MIN_REPEATS = 3;
|
|
9
9
|
const INTRA_MESSAGE_MIN_BLOCK_CHARS = 40;
|
|
10
10
|
const INTRA_MESSAGE_MIN_SAVED_CHARS = 1_000;
|
|
11
|
+
const INTRA_MESSAGE_SIMILARITY_THRESHOLD = 0.88;
|
|
11
12
|
const INTRA_MESSAGE_REPEAT_PLACEHOLDER = '[Exact repeated assistant paragraphs omitted from model projection; raw history preserved.]';
|
|
12
13
|
|
|
13
14
|
function isUserPrompt(message) {
|
|
@@ -60,6 +61,17 @@ function responseSimilarity(left, right) {
|
|
|
60
61
|
return (2 * intersection) / (leftBigrams.size + rightBigrams.size);
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
function fencedBlockIndexes(blocks) {
|
|
65
|
+
const protectedIndexes = new Set();
|
|
66
|
+
let insideFence = false;
|
|
67
|
+
for (let index = 0; index < blocks.length; index += 1) {
|
|
68
|
+
const fenceCount = blocks[index].match(/(?:^|\n)\s*(?:```|~~~)/gu)?.length ?? 0;
|
|
69
|
+
if (insideFence || fenceCount > 0) protectedIndexes.add(index);
|
|
70
|
+
if (fenceCount % 2 === 1) insideFence = !insideFence;
|
|
71
|
+
}
|
|
72
|
+
return protectedIndexes;
|
|
73
|
+
}
|
|
74
|
+
|
|
63
75
|
function hasUserPromptBetween(history, leftIndex, rightIndex) {
|
|
64
76
|
for (let index = leftIndex + 1; index < rightIndex; index += 1) {
|
|
65
77
|
if (isUserPrompt(history[index])) return true;
|
|
@@ -120,27 +132,31 @@ function compactRepeatedAssistantParagraphs(message) {
|
|
|
120
132
|
)) return null;
|
|
121
133
|
|
|
122
134
|
const text = textParts[0].text;
|
|
123
|
-
if (/```|~~~/u.test(text)) return null;
|
|
124
135
|
const blocks = text.split(/\n\s*\n/u).map((block) => block.trim()).filter(Boolean);
|
|
125
136
|
if (blocks.length < INTRA_MESSAGE_MIN_REPEATS + 1) return null;
|
|
137
|
+
const protectedIndexes = fencedBlockIndexes(blocks);
|
|
138
|
+
|
|
139
|
+
const clusters = [];
|
|
140
|
+
for (let index = 0; index < blocks.length; index += 1) {
|
|
141
|
+
const block = blocks[index];
|
|
142
|
+
if (protectedIndexes.has(index) || block.length < INTRA_MESSAGE_MIN_BLOCK_CHARS) continue;
|
|
143
|
+
const cluster = clusters.find((candidate) => (
|
|
144
|
+
candidate.representative === block
|
|
145
|
+
|| responseSimilarity(candidate.representative, block) >= INTRA_MESSAGE_SIMILARITY_THRESHOLD
|
|
146
|
+
));
|
|
147
|
+
if (cluster) cluster.indexes.push(index);
|
|
148
|
+
else clusters.push({ indexes: [index], representative: block });
|
|
149
|
+
}
|
|
150
|
+
const repeatedIndexes = new Set(clusters
|
|
151
|
+
.filter((cluster) => cluster.indexes.length >= INTRA_MESSAGE_MIN_REPEATS)
|
|
152
|
+
.flatMap((cluster) => cluster.indexes.slice(1)));
|
|
153
|
+
if (repeatedIndexes.size === 0) return null;
|
|
126
154
|
|
|
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
155
|
const projectedBlocks = [];
|
|
139
156
|
let markerAdded = false;
|
|
140
|
-
for (
|
|
141
|
-
if (!
|
|
142
|
-
projectedBlocks.push(
|
|
143
|
-
if (repeated.has(block)) seen.add(block);
|
|
157
|
+
for (let index = 0; index < blocks.length; index += 1) {
|
|
158
|
+
if (!repeatedIndexes.has(index)) {
|
|
159
|
+
projectedBlocks.push(blocks[index]);
|
|
144
160
|
continue;
|
|
145
161
|
}
|
|
146
162
|
if (!markerAdded) {
|
|
@@ -184,6 +200,7 @@ module.exports = {
|
|
|
184
200
|
INTRA_MESSAGE_MIN_BLOCK_CHARS,
|
|
185
201
|
INTRA_MESSAGE_MIN_REPEATS,
|
|
186
202
|
INTRA_MESSAGE_MIN_SAVED_CHARS,
|
|
203
|
+
INTRA_MESSAGE_SIMILARITY_THRESHOLD,
|
|
187
204
|
INTRA_MESSAGE_REPEAT_PLACEHOLDER,
|
|
188
205
|
MAX_RECENT_ASSISTANT_RESPONSES,
|
|
189
206
|
MIN_RESPONSE_CHARS,
|
package/blun.mjs
CHANGED
|
@@ -79260,6 +79260,11 @@ var init_error_memory$1 = __esmMin((() => {
|
|
|
79260
79260
|
getInjection() {
|
|
79261
79261
|
const patterns = this.agent.errorMemory?.getActivePatterns();
|
|
79262
79262
|
if (!patterns || patterns.length === 0) return void 0;
|
|
79263
|
+
try {
|
|
79264
|
+
const { buildCompactErrorMemoryReminder, selectRelevantErrorMemoryPatterns } = createRequire(import.meta.url)("./bin/error-memory-performance-policy.cjs");
|
|
79265
|
+
const { recentUserText } = createRequire(import.meta.url)("./bin/mistake-relevance-policy.cjs");
|
|
79266
|
+
return buildCompactErrorMemoryReminder(selectRelevantErrorMemoryPatterns(patterns, recentUserText(this.agent.context.history)));
|
|
79267
|
+
} catch {}
|
|
79263
79268
|
return buildErrorMemoryReminder(patterns);
|
|
79264
79269
|
}
|
|
79265
79270
|
};
|