blun-king-cli 9.1.526 → 9.1.536
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 +67 -0
- package/LIESMICH.txt +36 -1
- package/README.md +35 -1
- package/bin/agent-resume-snapshot.cjs +31 -0
- package/bin/assistant-message-offload-policy.cjs +21 -2
- package/bin/codebase-search-runtime.cjs +23 -0
- package/bin/empty-response-retry-policy.cjs +29 -0
- package/bin/fredrik-glm-provider.cjs +256 -0
- package/bin/history-offload-pressure-policy.cjs +33 -0
- package/bin/programmatic-context-isolation.cjs +25 -0
- package/bin/programmatic-tool-runtime.mjs +301 -0
- package/bin/skill-activation-performance-policy.cjs +9 -0
- package/bin/structured-subagent-output.cjs +252 -0
- package/bin/telegram-direct-focus-policy.cjs +25 -1
- package/bin/todo-list-turn-policy.cjs +111 -1
- package/bin/tool-result-offload-policy.cjs +29 -0
- package/bin/turn-thinking-policy.cjs +6 -15
- package/bin/turn-tool-performance-policy.cjs +5 -4
- package/bin/user-message-offload-policy.cjs +10 -1
- package/blun.mjs +709 -127
- package/codebase-index/README.md +70 -0
- package/codebase-index/codebase_index.py +358 -0
- package/fredrik-glm-profile.toml.example +26 -0
- package/package.json +25 -3
- package/scripts/check-active-work-steer-regression.js +46 -0
- package/scripts/check-codebase-search-packaging-regression.js +92 -0
- package/scripts/check-copy-command-regression.js +74 -0
- package/scripts/check-current-turn-read-pin-mutation-regression.js +72 -0
- package/scripts/check-current-turn-read-pin-regression.js +94 -0
- package/scripts/check-deepseek-native-max-regression.js +49 -0
- package/scripts/check-empty-response-effort-downgrade-regression.js +48 -0
- package/scripts/check-fredrik-glm-mutation-regression.js +18 -0
- package/scripts/check-fredrik-glm-regression.js +169 -0
- package/scripts/check-history-pressure-offload-regression.js +77 -0
- package/scripts/check-programmatic-context-isolation-regression.js +193 -0
- package/scripts/check-programmatic-tool-regression.js +294 -0
- package/scripts/check-resume-replay-regression.js +2 -0
- package/scripts/check-startup-swarm-command-regression.js +24 -0
- package/scripts/check-structured-subagent-output-regression.js +331 -0
- package/scripts/check-telegram-direct-work-resume-regression.js +53 -0
- package/scripts/check-todo-progress-regression.js +416 -0
- package/scripts/check-tool-schema-capacity-regression.js +40 -0
- package/scripts/programmatic-tool-runtime.test.mjs +365 -0
- package/scripts/structured-subagent-output.test.cjs +170 -0
|
@@ -1,6 +1,109 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const TODO_LIST_TOOL_NAME = 'TodoList';
|
|
4
|
+
const MAX_TODO_ITEMS = 32;
|
|
5
|
+
const BASE_TODO_REFRESH_WORK_CALL_LIMIT = 8;
|
|
6
|
+
const MAX_TODO_REFRESH_WORK_CALL_LIMIT = 64;
|
|
7
|
+
const TODO_STALLED_WARNING_STREAK = 3;
|
|
8
|
+
|
|
9
|
+
function canonicalStoredTodos(todos) {
|
|
10
|
+
if (!Array.isArray(todos)) return [];
|
|
11
|
+
return todos
|
|
12
|
+
.filter((todo) => todo?.status !== 'done')
|
|
13
|
+
.map((todo) => ({
|
|
14
|
+
title: String(todo?.title ?? ''),
|
|
15
|
+
status: String(todo?.status ?? ''),
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function semanticTodoFingerprint(todos) {
|
|
20
|
+
return JSON.stringify(canonicalStoredTodos(todos)
|
|
21
|
+
.map((todo) => `${todo.status}\0${todo.title}`)
|
|
22
|
+
.sort());
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function todoTitleCounts(todos) {
|
|
26
|
+
const counts = new Map();
|
|
27
|
+
for (const todo of Array.isArray(todos) ? todos : []) {
|
|
28
|
+
const title = String(todo?.title ?? '');
|
|
29
|
+
counts.set(title, (counts.get(title) ?? 0) + 1);
|
|
30
|
+
}
|
|
31
|
+
return counts;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function sameTitleCounts(left, right) {
|
|
35
|
+
if (left.size !== right.size) return false;
|
|
36
|
+
for (const [title, count] of left) {
|
|
37
|
+
if (right.get(title) !== count) return false;
|
|
38
|
+
}
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function assessTodoListBounds(input) {
|
|
43
|
+
const currentTodos = canonicalStoredTodos(input?.currentTodos);
|
|
44
|
+
const nextTodos = canonicalStoredTodos(input?.nextTodos);
|
|
45
|
+
if (currentTodos.length > MAX_TODO_ITEMS) {
|
|
46
|
+
const currentTitles = todoTitleCounts(currentTodos);
|
|
47
|
+
const submittedTitles = todoTitleCounts(input?.nextTodos);
|
|
48
|
+
if (!sameTitleCounts(currentTitles, submittedTitles)) {
|
|
49
|
+
return {
|
|
50
|
+
block: true,
|
|
51
|
+
reason: `An oversized legacy TodoList may remove an unresolved legacy item only by submitting it as done. Do not add, omit, or rename items until the visible list is at or below ${String(MAX_TODO_ITEMS)}.`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (nextTodos.length > currentTodos.length) {
|
|
56
|
+
return {
|
|
57
|
+
block: true,
|
|
58
|
+
reason: `An oversized legacy TodoList must stay unchanged or shrink toward ${String(MAX_TODO_ITEMS)} visible items.`,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (nextTodos.length <= MAX_TODO_ITEMS) return undefined;
|
|
66
|
+
return {
|
|
67
|
+
block: true,
|
|
68
|
+
reason: `TodoList accepts at most ${String(MAX_TODO_ITEMS)} visible items. Group the work into task-specific phases before continuing.`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function todoRefreshWorkCallLimit(unchangedRefreshStreak) {
|
|
73
|
+
const exponent = Math.min(Math.max(Number(unchangedRefreshStreak) || 0, 0), 3);
|
|
74
|
+
return Math.min(
|
|
75
|
+
MAX_TODO_REFRESH_WORK_CALL_LIMIT,
|
|
76
|
+
BASE_TODO_REFRESH_WORK_CALL_LIMIT * (2 ** exponent),
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function assessTodoMaintenanceUpdate(input) {
|
|
81
|
+
const changed = semanticTodoFingerprint(input?.currentTodos)
|
|
82
|
+
!== semanticTodoFingerprint(input?.nextTodos);
|
|
83
|
+
if (changed) {
|
|
84
|
+
return {
|
|
85
|
+
changed: true,
|
|
86
|
+
unchangedRefreshStreak: 0,
|
|
87
|
+
refreshWorkCallLimit: BASE_TODO_REFRESH_WORK_CALL_LIMIT,
|
|
88
|
+
preserveRecentEvidence: false,
|
|
89
|
+
requireConcreteProgress: false,
|
|
90
|
+
emitStalledWarning: false,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const previousStreak = Math.max(Number(input?.unchangedRefreshStreak) || 0, 0);
|
|
95
|
+
const hasNewEvidence = (Number(input?.recentEvidenceCount) || 0) > 0;
|
|
96
|
+
const unchangedRefreshStreak = hasNewEvidence ? previousStreak + 1 : previousStreak;
|
|
97
|
+
return {
|
|
98
|
+
changed: false,
|
|
99
|
+
unchangedRefreshStreak,
|
|
100
|
+
refreshWorkCallLimit: todoRefreshWorkCallLimit(unchangedRefreshStreak),
|
|
101
|
+
preserveRecentEvidence: true,
|
|
102
|
+
requireConcreteProgress: unchangedRefreshStreak >= 2,
|
|
103
|
+
emitStalledWarning: hasNewEvidence
|
|
104
|
+
&& unchangedRefreshStreak === TODO_STALLED_WARNING_STREAK,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
4
107
|
|
|
5
108
|
function enforceSingleTodoWritePerStep(context) {
|
|
6
109
|
if (context?.toolCall?.name !== TODO_LIST_TOOL_NAME) return undefined;
|
|
@@ -18,4 +121,11 @@ function enforceSingleTodoWritePerStep(context) {
|
|
|
18
121
|
};
|
|
19
122
|
}
|
|
20
123
|
|
|
21
|
-
module.exports = {
|
|
124
|
+
module.exports = {
|
|
125
|
+
MAX_TODO_ITEMS,
|
|
126
|
+
assessTodoListBounds,
|
|
127
|
+
assessTodoMaintenanceUpdate,
|
|
128
|
+
canonicalStoredTodos,
|
|
129
|
+
enforceSingleTodoWritePerStep,
|
|
130
|
+
todoRefreshWorkCallLimit,
|
|
131
|
+
};
|
|
@@ -78,6 +78,33 @@ function freshToolResultIds(messages) {
|
|
|
78
78
|
return resultIds;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
function currentUserTurnStartIndex(messages) {
|
|
82
|
+
if (!Array.isArray(messages) || messages.length === 0) return -1;
|
|
83
|
+
|
|
84
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
85
|
+
const message = messages[index];
|
|
86
|
+
if (message?.role === 'user' && message.origin?.kind === 'user') return index;
|
|
87
|
+
}
|
|
88
|
+
return -1;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function currentTurnReadToolResultIds(messages) {
|
|
92
|
+
const turnStart = currentUserTurnStartIndex(messages);
|
|
93
|
+
if (turnStart < 0) return new Set();
|
|
94
|
+
|
|
95
|
+
const resultIds = new Set();
|
|
96
|
+
for (let index = turnStart + 1; index < messages.length; index += 1) {
|
|
97
|
+
const message = messages[index];
|
|
98
|
+
if (message?.role !== 'assistant' || !Array.isArray(message.toolCalls)) continue;
|
|
99
|
+
for (const call of message.toolCalls) {
|
|
100
|
+
if (call?.name !== 'Read') continue;
|
|
101
|
+
const id = call.id ?? call.toolCallId;
|
|
102
|
+
if (typeof id === 'string' && id.length > 0) resultIds.add(id);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return resultIds;
|
|
106
|
+
}
|
|
107
|
+
|
|
81
108
|
function compactPersistedToolResultReference(content) {
|
|
82
109
|
if (!isPersistedToolResultReference(content)) return content;
|
|
83
110
|
|
|
@@ -318,6 +345,8 @@ module.exports = {
|
|
|
318
345
|
compactHistoricalSuccessfulToolResults,
|
|
319
346
|
compactPersistedToolResultReference,
|
|
320
347
|
createToolResultPreview,
|
|
348
|
+
currentTurnReadToolResultIds,
|
|
349
|
+
currentUserTurnStartIndex,
|
|
321
350
|
dedupeRepeatedSuccessfulToolResults,
|
|
322
351
|
freshToolResultIds,
|
|
323
352
|
isPersistedToolResultReference,
|
|
@@ -7,7 +7,6 @@ const BOSNIAN_STANDALONE_CHAT = /^(?:zdravo|pozdrav|hvala|ćao|cao)[.!?]*$/iu;
|
|
|
7
7
|
const IDENTITY_CHAT = /^(?:wer bist du|who are you|wie geht(?: es dir)?|how are you|na|kako si|kako je king|ko si ti|ko stoji iza tebe)[.!?]*$/iu;
|
|
8
8
|
const STATUS_ONLY_CHECK_IN = /(?:\bstandabfrage\b|\bstatusabfrage\b|\bkurzes?\s+update\b|\bwo\s+stehst\s+du\b|\bwie\s+weit\s+bist\s+du\b|\bwhere\s+are\s+you\b|\bquick\s+status\b)/iu;
|
|
9
9
|
const STATUS_FOLLOW_UP_ACTION = /\b(?:aendere|arbeite|baue|build|change|delete|deploy|deploye|fahr|fix|fixe|implement|implementiere|install|installiere|loesche|mach|patch|pruefe|repariere|run|schreibe|setze|start|starte|stop|stoppe|test|teste|write)\b/iu;
|
|
10
|
-
const LIGHTWEIGHT_STEER = /\b(?:cool|danke|dankeschoen|gute arbeit|passt|perfekt|stolz|super|freut mich)\b/iu;
|
|
11
10
|
const STANDALONE_CHAT_COMPLETION_TOKENS = 1024;
|
|
12
11
|
const ADAPTIVE_LOW_COMPLETION_TOKENS = 4096;
|
|
13
12
|
const STANDARD_TURN_MAX_COMPLETION_TOKENS = 24_576;
|
|
@@ -68,20 +67,12 @@ function capTurnCompletionTokens(maxOutputSize) {
|
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
function selectThinkingEffortForBufferedSteer(text, originKind) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
!normalized
|
|
78
|
-
|| normalized.length > 180
|
|
79
|
-
|| String(text ?? "").split(/\r?\n/u).length > 2
|
|
80
|
-
|| ACTIONABLE_PROMPT.test(normalized)
|
|
81
|
-
|| EXPLICIT_THINKING_INTENT.test(normalized)
|
|
82
|
-
) return undefined;
|
|
83
|
-
|
|
84
|
-
return LIGHTWEIGHT_STEER.test(normalized) ? "low" : undefined;
|
|
70
|
+
// A buffered steer belongs to an already-running work turn. It may add
|
|
71
|
+
// context, but must never replace that turn's model effort, tool catalog,
|
|
72
|
+
// history projection, or completion budget with the fast-chat profile.
|
|
73
|
+
void text;
|
|
74
|
+
void originKind;
|
|
75
|
+
return undefined;
|
|
85
76
|
}
|
|
86
77
|
|
|
87
78
|
module.exports = {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const TOOL_SCHEMA_BUDGET_RATIO = 0.
|
|
4
|
-
const TOOL_SCHEMA_MAX_TOKENS =
|
|
3
|
+
const TOOL_SCHEMA_BUDGET_RATIO = 0.35;
|
|
4
|
+
const TOOL_SCHEMA_MAX_TOKENS = 64_000;
|
|
5
5
|
const DEFERRED_TOOL_LOADER_NAME = 'ToolSearch';
|
|
6
|
-
const MAX_PERSISTENT_DEFERRED_TOOLS =
|
|
6
|
+
const MAX_PERSISTENT_DEFERRED_TOOLS = 12;
|
|
7
7
|
const MAX_TOOL_SEARCH_QUERY_CHARS = 1_000;
|
|
8
|
-
const MAX_AUTO_RANKED_TOOLS =
|
|
8
|
+
const MAX_AUTO_RANKED_TOOLS = 6;
|
|
9
9
|
const TOOL_RANK_EMBEDDED_CONTENT_RE = /<(attached_documents?|attachment_content|document_content|file_content)\b[^>]*>[\s\S]*?<\/\1>/giu;
|
|
10
10
|
const TOOL_RANK_STOP_WORDS = new Set([
|
|
11
11
|
'aber', 'also', 'and', 'aus', 'bitte', 'can', 'das', 'den', 'der', 'des', 'die', 'dies', 'diese',
|
|
@@ -469,6 +469,7 @@ module.exports = {
|
|
|
469
469
|
CORE_TOOL_NAMES,
|
|
470
470
|
DEFERRED_TOOL_LOADER_NAME,
|
|
471
471
|
MAX_PERSISTENT_DEFERRED_TOOLS,
|
|
472
|
+
MAX_AUTO_RANKED_TOOLS,
|
|
472
473
|
MAX_TOOL_SEARCH_QUERY_CHARS,
|
|
473
474
|
TOOL_SCHEMA_BUDGET_RATIO,
|
|
474
475
|
TOOL_SCHEMA_MAX_TOKENS,
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const {
|
|
4
|
+
hasHistoricalOffloadPressure,
|
|
5
|
+
historyTextChars,
|
|
6
|
+
} = require('./history-offload-pressure-policy.cjs');
|
|
7
|
+
|
|
3
8
|
const USER_MESSAGE_MAX_CHARS = 200_000;
|
|
4
9
|
const HISTORICAL_USER_MESSAGE_MAX_CHARS = 4_000;
|
|
5
10
|
const USER_MESSAGE_KEEP_RECENT_MESSAGES = 20;
|
|
@@ -14,6 +19,7 @@ function shouldOffloadUserMessage(textChars) {
|
|
|
14
19
|
function shouldOffloadHistoricalUserMessage(options = {}) {
|
|
15
20
|
const historyIndex = Number(options.historyIndex);
|
|
16
21
|
const historyLength = Number(options.historyLength);
|
|
22
|
+
const historyChars = Number(options.historyChars);
|
|
17
23
|
const textChars = Number(options.textChars);
|
|
18
24
|
if (
|
|
19
25
|
!Number.isSafeInteger(historyIndex)
|
|
@@ -24,7 +30,9 @@ function shouldOffloadHistoricalUserMessage(options = {}) {
|
|
|
24
30
|
|| historyIndex >= historyLength
|
|
25
31
|
) return false;
|
|
26
32
|
const cutoff = Math.max(0, historyLength - USER_MESSAGE_KEEP_RECENT_MESSAGES);
|
|
27
|
-
return
|
|
33
|
+
return hasHistoricalOffloadPressure({ historyLength, historyChars })
|
|
34
|
+
&& historyIndex < cutoff
|
|
35
|
+
&& textChars > HISTORICAL_USER_MESSAGE_MAX_CHARS;
|
|
28
36
|
}
|
|
29
37
|
|
|
30
38
|
function createUserMessagePreview(text) {
|
|
@@ -87,6 +95,7 @@ module.exports = {
|
|
|
87
95
|
USER_MESSAGE_PREVIEW_LINE_CHARS,
|
|
88
96
|
compactHistoricalPersistedUserMessageReferences,
|
|
89
97
|
createUserMessagePreview,
|
|
98
|
+
historyTextChars,
|
|
90
99
|
shouldOffloadHistoricalUserMessage,
|
|
91
100
|
shouldOffloadUserMessage,
|
|
92
101
|
};
|