blun-king-cli 9.1.168 → 9.1.169
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.
|
@@ -4,6 +4,16 @@ const TOOL_SCHEMA_BUDGET_RATIO = 0.25;
|
|
|
4
4
|
const TOOL_SCHEMA_MAX_TOKENS = 32_000;
|
|
5
5
|
const DEFERRED_TOOL_LOADER_NAME = 'ToolSearch';
|
|
6
6
|
const MAX_PERSISTENT_DEFERRED_TOOLS = 12;
|
|
7
|
+
const TOOL_SEARCH_INTENT_WORDS = new Set([
|
|
8
|
+
'find', 'fetch', 'get', 'holen', 'list', 'read', 'search', 'show', 'anzeigen', 'lesen', 'suchen',
|
|
9
|
+
]);
|
|
10
|
+
const TOOL_SEARCH_RELATED_TERM_GROUPS = Object.freeze([
|
|
11
|
+
Object.freeze([
|
|
12
|
+
'current', 'inbox', 'latest', 'message', 'messages', 'nachricht', 'nachrichten', 'queue', 'queued',
|
|
13
|
+
'recent', 'update', 'updates',
|
|
14
|
+
]),
|
|
15
|
+
Object.freeze(['history', 'log', 'logs', 'protokoll', 'transcript', 'verlauf']),
|
|
16
|
+
]);
|
|
7
17
|
const CORE_TOOL_NAMES = Object.freeze([
|
|
8
18
|
'Bash',
|
|
9
19
|
'Read',
|
|
@@ -66,6 +76,56 @@ function searchDeferredTools(tools, query) {
|
|
|
66
76
|
}).filter(Boolean).sort((left, right) => right.score - left.score || String(left.tool.name).localeCompare(String(right.tool.name))).slice(0, 5).map((entry) => entry.tool);
|
|
67
77
|
}
|
|
68
78
|
|
|
79
|
+
function relatedSearchTerms(token) {
|
|
80
|
+
const group = TOOL_SEARCH_RELATED_TERM_GROUPS.find((terms) => terms.includes(token));
|
|
81
|
+
return group || [token];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function searchRelatedDeferredTools(tools, query) {
|
|
85
|
+
const normalized = String(query || '').trim().toLowerCase();
|
|
86
|
+
if (!normalized || normalized.startsWith('select:')) return [];
|
|
87
|
+
const tokens = normalized.split(/\s+/).filter(Boolean);
|
|
88
|
+
const requiredNameTokens = tokens.filter((token) => token.startsWith('+')).map((token) => token.slice(1)).filter(Boolean);
|
|
89
|
+
const searchTokens = tokens
|
|
90
|
+
.filter((token) => !token.startsWith('+'))
|
|
91
|
+
.filter((token) => !TOOL_SEARCH_INTENT_WORDS.has(token));
|
|
92
|
+
if (searchTokens.length < 2) return [];
|
|
93
|
+
const minimumMatchedTokens = Math.max(2, Math.ceil(searchTokens.length * 0.75));
|
|
94
|
+
|
|
95
|
+
return tools.map((tool) => {
|
|
96
|
+
const name = String(tool?.name || '').toLowerCase();
|
|
97
|
+
const description = String(tool?.description || '').toLowerCase();
|
|
98
|
+
if (!requiredNameTokens.every((token) => name.includes(token))) return null;
|
|
99
|
+
let matchedTokens = 0;
|
|
100
|
+
let score = requiredNameTokens.length * 8;
|
|
101
|
+
for (const token of searchTokens) {
|
|
102
|
+
if (name.includes(token)) {
|
|
103
|
+
matchedTokens += 1;
|
|
104
|
+
score += 8;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (description.includes(token)) {
|
|
108
|
+
matchedTokens += 1;
|
|
109
|
+
score += 4;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const related = relatedSearchTerms(token).filter((term) => term !== token);
|
|
113
|
+
if (related.some((term) => name.includes(term))) {
|
|
114
|
+
matchedTokens += 1;
|
|
115
|
+
score += 3;
|
|
116
|
+
} else if (related.some((term) => description.includes(term))) {
|
|
117
|
+
matchedTokens += 1;
|
|
118
|
+
score += 2;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return matchedTokens >= minimumMatchedTokens ? { tool, score, matchedTokens } : null;
|
|
122
|
+
}).filter(Boolean).sort((left, right) => (
|
|
123
|
+
right.matchedTokens - left.matchedTokens
|
|
124
|
+
|| right.score - left.score
|
|
125
|
+
|| String(left.tool.name).localeCompare(String(right.tool.name))
|
|
126
|
+
)).slice(0, 5).map((entry) => entry.tool);
|
|
127
|
+
}
|
|
128
|
+
|
|
69
129
|
function rememberLoadedTool(loadedToolNames, name) {
|
|
70
130
|
loadedToolNames.delete(name);
|
|
71
131
|
loadedToolNames.add(name);
|
|
@@ -109,7 +169,12 @@ function createDeferredToolLoader(selectedTools, deferredTools, loadedToolNames
|
|
|
109
169
|
description: query ? `Searching tool schemas for ${query}` : 'Searching tool schemas',
|
|
110
170
|
approvalRule: DEFERRED_TOOL_LOADER_NAME,
|
|
111
171
|
execute: async () => {
|
|
112
|
-
|
|
172
|
+
let matches = searchDeferredTools([...available.values()], query);
|
|
173
|
+
let relatedFallback = false;
|
|
174
|
+
if (matches.length === 0) {
|
|
175
|
+
matches = searchRelatedDeferredTools([...available.values()], query);
|
|
176
|
+
relatedFallback = matches.length > 0;
|
|
177
|
+
}
|
|
113
178
|
if (matches.length === 0) {
|
|
114
179
|
const alreadyLoaded = query.toLowerCase().startsWith('select:')
|
|
115
180
|
? searchDeferredTools(
|
|
@@ -143,7 +208,7 @@ function createDeferredToolLoader(selectedTools, deferredTools, loadedToolNames
|
|
|
143
208
|
}
|
|
144
209
|
return {
|
|
145
210
|
isError: false,
|
|
146
|
-
output:
|
|
211
|
+
output: `${relatedFallback ? 'Loaded related tool schemas' : 'Loaded tool schemas'}: ${loaded.join(', ')}. Invoke them in the next step.`,
|
|
147
212
|
};
|
|
148
213
|
},
|
|
149
214
|
};
|