toolpack-sdk 1.0.0 → 1.1.0-SNAPSHOT
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/README.md +115 -4
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +82 -79
- package/dist/client/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/knowledge/embedders/gemini-embedder.d.ts +21 -0
- package/dist/knowledge/embedders/gemini-embedder.d.ts.map +1 -0
- package/dist/knowledge/embedders/gemini-embedder.js +93 -0
- package/dist/knowledge/embedders/gemini-embedder.js.map +1 -0
- package/dist/knowledge/embedders/ollama-embedder.d.ts +12 -0
- package/dist/knowledge/embedders/ollama-embedder.d.ts.map +1 -0
- package/dist/knowledge/embedders/ollama-embedder.js +68 -0
- package/dist/knowledge/embedders/ollama-embedder.js.map +1 -0
- package/dist/knowledge/embedders/openai-embedder.d.ts +14 -0
- package/dist/knowledge/embedders/openai-embedder.d.ts.map +1 -0
- package/dist/knowledge/embedders/openai-embedder.js +94 -0
- package/dist/knowledge/embedders/openai-embedder.js.map +1 -0
- package/dist/knowledge/errors.d.ts +22 -0
- package/dist/knowledge/errors.d.ts.map +1 -0
- package/dist/knowledge/errors.js +51 -0
- package/dist/knowledge/errors.js.map +1 -0
- package/dist/knowledge/index.d.ts +12 -0
- package/dist/knowledge/index.d.ts.map +1 -0
- package/dist/knowledge/index.js +26 -0
- package/dist/knowledge/index.js.map +1 -0
- package/dist/knowledge/knowledge.d.ts +38 -0
- package/dist/knowledge/knowledge.d.ts.map +1 -0
- package/dist/knowledge/knowledge.js +287 -0
- package/dist/knowledge/knowledge.js.map +1 -0
- package/dist/knowledge/providers/memory-provider.d.ts +15 -0
- package/dist/knowledge/providers/memory-provider.d.ts.map +1 -0
- package/dist/knowledge/providers/memory-provider.js +113 -0
- package/dist/knowledge/providers/memory-provider.js.map +1 -0
- package/dist/knowledge/sources/json-source.d.ts +18 -0
- package/dist/knowledge/sources/json-source.d.ts.map +1 -0
- package/dist/knowledge/sources/json-source.js +224 -0
- package/dist/knowledge/sources/json-source.js.map +1 -0
- package/dist/knowledge/sources/markdown-source.d.ts +27 -0
- package/dist/knowledge/sources/markdown-source.d.ts.map +1 -0
- package/dist/knowledge/sources/markdown-source.js +410 -0
- package/dist/knowledge/sources/markdown-source.js.map +1 -0
- package/dist/knowledge/sources/sqlite-text-source.d.ts +18 -0
- package/dist/knowledge/sources/sqlite-text-source.d.ts.map +1 -0
- package/dist/knowledge/sources/sqlite-text-source.js +201 -0
- package/dist/knowledge/sources/sqlite-text-source.js.map +1 -0
- package/dist/knowledge/types.d.ts +130 -0
- package/dist/knowledge/types.d.ts.map +1 -0
- package/dist/knowledge/types.js +3 -0
- package/dist/knowledge/types.js.map +1 -0
- package/dist/mcp/client.js +1 -1
- package/dist/mcp/client.js.map +1 -1
- package/dist/providers/anthropic/index.js +13 -13
- package/dist/providers/anthropic/index.js.map +1 -1
- package/dist/providers/config.d.ts +0 -2
- package/dist/providers/config.d.ts.map +1 -1
- package/dist/providers/config.js.map +1 -1
- package/dist/providers/gemini/index.js +10 -10
- package/dist/providers/gemini/index.js.map +1 -1
- package/dist/providers/ollama/adapter.d.ts.map +1 -1
- package/dist/providers/ollama/adapter.js +14 -18
- package/dist/providers/ollama/adapter.js.map +1 -1
- package/dist/providers/ollama/slm-healer.js +7 -7
- package/dist/providers/ollama/slm-healer.js.map +1 -1
- package/dist/providers/openai/index.d.ts.map +1 -1
- package/dist/providers/openai/index.js +15 -21
- package/dist/providers/openai/index.js.map +1 -1
- package/dist/providers/provider-logger.d.ts +17 -9
- package/dist/providers/provider-logger.d.ts.map +1 -1
- package/dist/providers/provider-logger.js +68 -26
- package/dist/providers/provider-logger.js.map +1 -1
- package/dist/toolpack.d.ts +12 -0
- package/dist/toolpack.d.ts.map +1 -1
- package/dist/toolpack.js +36 -34
- package/dist/toolpack.js.map +1 -1
- package/dist/tools/cloud-tools/tools/deploy/index.d.ts.map +1 -1
- package/dist/tools/cloud-tools/tools/deploy/index.js +2 -0
- package/dist/tools/cloud-tools/tools/deploy/index.js.map +1 -1
- package/dist/tools/cloud-tools/tools/list/index.d.ts.map +1 -1
- package/dist/tools/cloud-tools/tools/list/index.js +2 -0
- package/dist/tools/cloud-tools/tools/list/index.js.map +1 -1
- package/dist/tools/coding-tools/tools/find-references/index.d.ts.map +1 -1
- package/dist/tools/coding-tools/tools/find-references/index.js +2 -0
- package/dist/tools/coding-tools/tools/find-references/index.js.map +1 -1
- package/dist/tools/coding-tools/tools/find-symbol/index.d.ts.map +1 -1
- package/dist/tools/coding-tools/tools/find-symbol/index.js +2 -0
- package/dist/tools/coding-tools/tools/find-symbol/index.js.map +1 -1
- package/dist/tools/coding-tools/tools/get-exports/index.d.ts.map +1 -1
- package/dist/tools/coding-tools/tools/get-exports/index.js +2 -0
- package/dist/tools/coding-tools/tools/get-exports/index.js.map +1 -1
- package/dist/tools/coding-tools/tools/get-imports/index.d.ts.map +1 -1
- package/dist/tools/coding-tools/tools/get-imports/index.js +2 -0
- package/dist/tools/coding-tools/tools/get-imports/index.js.map +1 -1
- package/dist/tools/coding-tools/tools/get-outline/index.d.ts.map +1 -1
- package/dist/tools/coding-tools/tools/get-outline/index.js +2 -0
- package/dist/tools/coding-tools/tools/get-outline/index.js.map +1 -1
- package/dist/tools/coding-tools/tools/get-symbols/index.d.ts.map +1 -1
- package/dist/tools/coding-tools/tools/get-symbols/index.js +2 -0
- package/dist/tools/coding-tools/tools/get-symbols/index.js.map +1 -1
- package/dist/tools/config-loader.d.ts +13 -0
- package/dist/tools/config-loader.d.ts.map +1 -1
- package/dist/tools/config-loader.js +20 -8
- package/dist/tools/config-loader.js.map +1 -1
- package/dist/tools/create-tool-project.d.ts.map +1 -1
- package/dist/tools/create-tool-project.js +2 -1
- package/dist/tools/create-tool-project.js.map +1 -1
- package/dist/tools/db-tools/tools/query/index.d.ts.map +1 -1
- package/dist/tools/db-tools/tools/query/index.js +2 -0
- package/dist/tools/db-tools/tools/query/index.js.map +1 -1
- package/dist/tools/diff-tools/tools/apply/index.d.ts.map +1 -1
- package/dist/tools/diff-tools/tools/apply/index.js +2 -0
- package/dist/tools/diff-tools/tools/apply/index.js.map +1 -1
- package/dist/tools/diff-tools/tools/create/index.d.ts.map +1 -1
- package/dist/tools/diff-tools/tools/create/index.js +2 -0
- package/dist/tools/diff-tools/tools/create/index.js.map +1 -1
- package/dist/tools/exec-tools/tools/run/index.d.ts.map +1 -1
- package/dist/tools/exec-tools/tools/run/index.js +2 -0
- package/dist/tools/exec-tools/tools/run/index.js.map +1 -1
- package/dist/tools/exec-tools/tools/run-background/index.d.ts.map +1 -1
- package/dist/tools/exec-tools/tools/run-background/index.js +5 -0
- package/dist/tools/exec-tools/tools/run-background/index.js.map +1 -1
- package/dist/tools/exec-tools/tools/run-shell/index.d.ts.map +1 -1
- package/dist/tools/exec-tools/tools/run-shell/index.js +2 -0
- package/dist/tools/exec-tools/tools/run-shell/index.js.map +1 -1
- package/dist/tools/fs-tools/tools/delete-file/index.d.ts.map +1 -1
- package/dist/tools/fs-tools/tools/delete-file/index.js +2 -0
- package/dist/tools/fs-tools/tools/delete-file/index.js.map +1 -1
- package/dist/tools/fs-tools/tools/read-file/index.d.ts.map +1 -1
- package/dist/tools/fs-tools/tools/read-file/index.js +2 -0
- package/dist/tools/fs-tools/tools/read-file/index.js.map +1 -1
- package/dist/tools/fs-tools/tools/search/index.d.ts.map +1 -1
- package/dist/tools/fs-tools/tools/search/index.js +2 -0
- package/dist/tools/fs-tools/tools/search/index.js.map +1 -1
- package/dist/tools/fs-tools/tools/write-file/index.d.ts.map +1 -1
- package/dist/tools/fs-tools/tools/write-file/index.js +2 -0
- package/dist/tools/fs-tools/tools/write-file/index.js.map +1 -1
- package/dist/tools/http-tools/tools/delete/index.d.ts.map +1 -1
- package/dist/tools/http-tools/tools/delete/index.js +2 -0
- package/dist/tools/http-tools/tools/delete/index.js.map +1 -1
- package/dist/tools/http-tools/tools/download/index.d.ts.map +1 -1
- package/dist/tools/http-tools/tools/download/index.js +2 -0
- package/dist/tools/http-tools/tools/download/index.js.map +1 -1
- package/dist/tools/http-tools/tools/get/index.d.ts.map +1 -1
- package/dist/tools/http-tools/tools/get/index.js +2 -0
- package/dist/tools/http-tools/tools/get/index.js.map +1 -1
- package/dist/tools/http-tools/tools/post/index.d.ts.map +1 -1
- package/dist/tools/http-tools/tools/post/index.js +2 -0
- package/dist/tools/http-tools/tools/post/index.js.map +1 -1
- package/dist/tools/http-tools/tools/put/index.d.ts.map +1 -1
- package/dist/tools/http-tools/tools/put/index.js +2 -0
- package/dist/tools/http-tools/tools/put/index.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/system-tools/tools/cwd/index.d.ts.map +1 -1
- package/dist/tools/system-tools/tools/cwd/index.js +2 -0
- package/dist/tools/system-tools/tools/cwd/index.js.map +1 -1
- package/dist/tools/system-tools/tools/env/index.d.ts.map +1 -1
- package/dist/tools/system-tools/tools/env/index.js +2 -0
- package/dist/tools/system-tools/tools/env/index.js.map +1 -1
- package/dist/tools/system-tools/tools/info/index.d.ts.map +1 -1
- package/dist/tools/system-tools/tools/info/index.js +2 -0
- package/dist/tools/system-tools/tools/info/index.js.map +1 -1
- package/dist/tools/types.d.ts +1 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js +1 -0
- package/dist/tools/types.js.map +1 -1
- package/dist/tools/web-tools/tools/fetch/index.d.ts.map +1 -1
- package/dist/tools/web-tools/tools/fetch/index.js +2 -0
- package/dist/tools/web-tools/tools/fetch/index.js.map +1 -1
- package/dist/tools/web-tools/tools/scrape/index.d.ts.map +1 -1
- package/dist/tools/web-tools/tools/scrape/index.js +2 -0
- package/dist/tools/web-tools/tools/scrape/index.js.map +1 -1
- package/dist/tools/web-tools/tools/search/index.d.ts.map +1 -1
- package/dist/tools/web-tools/tools/search/index.js +44 -7
- package/dist/tools/web-tools/tools/search/index.js.map +1 -1
- package/dist/tools/web-tools/tools/search/schema.js +1 -1
- package/dist/tools/web-tools/tools/search/schema.js.map +1 -1
- package/dist/workflows/planning/planner.d.ts.map +1 -1
- package/dist/workflows/planning/planner.js +16 -2
- package/dist/workflows/planning/planner.js.map +1 -1
- package/dist/workflows/steps/step-executor.d.ts.map +1 -1
- package/dist/workflows/steps/step-executor.js +17 -5
- package/dist/workflows/steps/step-executor.js.map +1 -1
- package/dist/workflows/workflow-executor.d.ts.map +1 -1
- package/dist/workflows/workflow-executor.js +32 -2
- package/dist/workflows/workflow-executor.js.map +1 -1
- package/package.json +4 -4
package/dist/client/index.js
CHANGED
|
@@ -16,12 +16,12 @@ function newRequestId() {
|
|
|
16
16
|
return `${Date.now()}-${REQUEST_SEQ}`;
|
|
17
17
|
}
|
|
18
18
|
function logRequestMessages(requestId, messages) {
|
|
19
|
-
if (!(0, provider_logger_1.
|
|
19
|
+
if (!(0, provider_logger_1.shouldLog)('debug'))
|
|
20
20
|
return;
|
|
21
|
-
(0, provider_logger_1.
|
|
21
|
+
(0, provider_logger_1.logDebug)(`[AIClient][${requestId}] Messages (${messages.length}):`);
|
|
22
22
|
messages.forEach((m, i) => {
|
|
23
23
|
const preview = (0, provider_logger_1.safePreview)(m.content, 300);
|
|
24
|
-
(0, provider_logger_1.
|
|
24
|
+
(0, provider_logger_1.logDebug)(`[AIClient][${requestId}] #${i} role=${m.role} content=${preview}`);
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
27
|
function extractLastUserText(messages) {
|
|
@@ -124,7 +124,7 @@ function extractToolContext(messages) {
|
|
|
124
124
|
}
|
|
125
125
|
async function inferNeedsToolsWithAI(provider, providerName, messages, fastModel) {
|
|
126
126
|
const requestId = newRequestId();
|
|
127
|
-
(0, provider_logger_1.
|
|
127
|
+
(0, provider_logger_1.logDebug)(`[AIClient][${requestId}] inferNeedsToolsWithAI() provider=${providerName} model=${fastModel}`);
|
|
128
128
|
// Extract tool context from recent tool calls
|
|
129
129
|
const toolContext = extractToolContext(messages);
|
|
130
130
|
// Get the last user message
|
|
@@ -152,11 +152,11 @@ Answer only: YES or NO`;
|
|
|
152
152
|
});
|
|
153
153
|
const answer = (response.content || '').trim().toUpperCase();
|
|
154
154
|
const needsTools = answer.startsWith('YES');
|
|
155
|
-
(0, provider_logger_1.
|
|
155
|
+
(0, provider_logger_1.logDebug)(`[AIClient][${requestId}] inferNeedsToolsWithAI() context="${toolContext}" message="${userMessage.substring(0, 50)}" result=${needsTools} (raw: ${answer})`);
|
|
156
156
|
return needsTools;
|
|
157
157
|
}
|
|
158
158
|
catch (error) {
|
|
159
|
-
(0, provider_logger_1.
|
|
159
|
+
(0, provider_logger_1.logWarn)(`[AIClient][${requestId}] inferNeedsToolsWithAI() error=${error} - falling back to false`);
|
|
160
160
|
return false;
|
|
161
161
|
}
|
|
162
162
|
}
|
|
@@ -177,11 +177,6 @@ function inferLookupOnly(messages) {
|
|
|
177
177
|
];
|
|
178
178
|
return lookupPatterns.some(r => r.test(text)) && !mutatingPatterns.some(r => r.test(text));
|
|
179
179
|
}
|
|
180
|
-
const TOOL_RESULT_MAX_CHARS = (() => {
|
|
181
|
-
const raw = process.env.TOOLPACK_SDK_TOOL_RESULT_MAX_CHARS;
|
|
182
|
-
const n = raw ? Number(raw) : NaN;
|
|
183
|
-
return Number.isFinite(n) && n > 0 ? n : 20_000;
|
|
184
|
-
})();
|
|
185
180
|
class AIClient extends events_1.EventEmitter {
|
|
186
181
|
providers;
|
|
187
182
|
defaultProvider;
|
|
@@ -194,6 +189,7 @@ class AIClient extends events_1.EventEmitter {
|
|
|
194
189
|
activeMode = null;
|
|
195
190
|
overrideSystemPrompt;
|
|
196
191
|
disableBaseContext;
|
|
192
|
+
toolResultMaxChars;
|
|
197
193
|
constructor(config) {
|
|
198
194
|
super();
|
|
199
195
|
this.providers = new Map(Object.entries(config.providers));
|
|
@@ -206,6 +202,8 @@ class AIClient extends events_1.EventEmitter {
|
|
|
206
202
|
this.toolOrchestrator = new tool_orchestrator_js_1.ToolOrchestrator();
|
|
207
203
|
this.overrideSystemPrompt = config.systemPrompt;
|
|
208
204
|
this.disableBaseContext = config.disableBaseContext || false;
|
|
205
|
+
const configuredMax = this.toolsConfig.resultMaxChars ?? types_js_1.DEFAULT_TOOLS_CONFIG.resultMaxChars ?? 20_000;
|
|
206
|
+
this.toolResultMaxChars = Number.isFinite(configuredMax) && configuredMax > 0 ? configuredMax : 20_000;
|
|
209
207
|
// Index tools for BM25 search if registry is provided
|
|
210
208
|
if (this.toolRegistry) {
|
|
211
209
|
this.bm25Engine.index(this.toolRegistry.getAll());
|
|
@@ -276,7 +274,7 @@ class AIClient extends events_1.EventEmitter {
|
|
|
276
274
|
*/
|
|
277
275
|
setMode(mode) {
|
|
278
276
|
this.activeMode = mode;
|
|
279
|
-
(0, provider_logger_1.
|
|
277
|
+
(0, provider_logger_1.logInfo)(`[AIClient] Mode set to: ${mode ? mode.displayName : 'none (cleared)'}`);
|
|
280
278
|
}
|
|
281
279
|
/**
|
|
282
280
|
* Get the currently active mode.
|
|
@@ -291,7 +289,7 @@ class AIClient extends events_1.EventEmitter {
|
|
|
291
289
|
reindexTools() {
|
|
292
290
|
if (this.toolRegistry) {
|
|
293
291
|
this.bm25Engine.index(this.toolRegistry.getAll());
|
|
294
|
-
(0, provider_logger_1.
|
|
292
|
+
(0, provider_logger_1.logInfo)(`[AIClient] Re-indexed ${this.bm25Engine.getIndexedCount()} tools for BM25 search`);
|
|
295
293
|
}
|
|
296
294
|
}
|
|
297
295
|
/**
|
|
@@ -326,7 +324,7 @@ class AIClient extends events_1.EventEmitter {
|
|
|
326
324
|
if (!needsTools && intelligentDetection?.enabled && hasTools) {
|
|
327
325
|
const afterToolCall = isAfterToolCall(enrichedRequest.messages, intelligentDetection.maxFollowUpMessages);
|
|
328
326
|
if (afterToolCall) {
|
|
329
|
-
(0, provider_logger_1.
|
|
327
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] Message is after tool call, using AI to infer tool needs`);
|
|
330
328
|
const fastModel = getFastModelForProvider(resolvedProviderName || 'openai');
|
|
331
329
|
needsTools = await inferNeedsToolsWithAI(provider, resolvedProviderName || 'openai', enrichedRequest.messages, fastModel);
|
|
332
330
|
aiInferenceUsed = true;
|
|
@@ -340,14 +338,14 @@ class AIClient extends events_1.EventEmitter {
|
|
|
340
338
|
}
|
|
341
339
|
else if (shouldForceNone) {
|
|
342
340
|
enrichedRequest.tool_choice = 'none';
|
|
343
|
-
(0, provider_logger_1.
|
|
341
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] AI inference determined no tools needed, setting tool_choice=none`);
|
|
344
342
|
}
|
|
345
343
|
const providerClass = provider?.constructor?.name || 'UnknownProvider';
|
|
346
344
|
const outboundReq = { ...enrichedRequest, __toolpack_request_id: requestId };
|
|
347
|
-
(0, provider_logger_1.
|
|
345
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] generate() start provider=${resolvedProviderName} class=${providerClass} model=${enrichedRequest.model} messages=${enrichedRequest.messages.length} tools=${enrichedRequest.tools?.length || 0} tool_choice=${enrichedRequest.tool_choice ?? 'unset'} policy=${policy} needsTools=${needsTools} autoExecute=${this.toolsConfig.enabled && this.toolsConfig.autoExecute}`);
|
|
348
346
|
logRequestMessages(requestId, enrichedRequest.messages);
|
|
349
347
|
let response = await provider.generate(outboundReq);
|
|
350
|
-
(0, provider_logger_1.
|
|
348
|
+
(0, provider_logger_1.logDebug)(`[AIClient][${requestId}] generate() initial response finish_reason=${response.finish_reason ?? 'unknown'} tool_calls=${response.tool_calls?.length || 0} content_preview=${(0, provider_logger_1.safePreview)(response.content || '', 200)}`);
|
|
351
349
|
// Auto-execute tool call loop
|
|
352
350
|
if (this.toolsConfig.enabled && this.toolsConfig.autoExecute && this.toolRegistry) {
|
|
353
351
|
// Classify query to adjust maxToolRounds
|
|
@@ -356,19 +354,19 @@ class AIClient extends events_1.EventEmitter {
|
|
|
356
354
|
const baseMaxRounds = this.toolsConfig.maxToolRounds;
|
|
357
355
|
const maxRounds = this.queryClassifier.getToolRoundsAdjustment(classification, baseMaxRounds);
|
|
358
356
|
if (maxRounds !== baseMaxRounds) {
|
|
359
|
-
(0, provider_logger_1.
|
|
357
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] Query classified as ${classification.type} (confidence: ${classification.confidence.toFixed(2)}), adjusted maxToolRounds: ${baseMaxRounds} → ${maxRounds}`);
|
|
360
358
|
}
|
|
361
359
|
else {
|
|
362
|
-
(0, provider_logger_1.
|
|
360
|
+
(0, provider_logger_1.logDebug)(`[AIClient][${requestId}] Query classified as ${classification.type} (confidence: ${classification.confidence.toFixed(2)}), keeping maxToolRounds: ${maxRounds}`);
|
|
363
361
|
}
|
|
364
362
|
let rounds = 0;
|
|
365
363
|
const messages = [...enrichedRequest.messages];
|
|
366
364
|
if (response.tool_calls && response.tool_calls.length > 0) {
|
|
367
|
-
(0, provider_logger_1.
|
|
365
|
+
(0, provider_logger_1.logInfo)(`[AIClient] Received ${response.tool_calls.length} tool call(s): ${response.tool_calls.map(tc => tc.name).join(', ')}`);
|
|
368
366
|
}
|
|
369
367
|
while (response.tool_calls && response.tool_calls.length > 0 && rounds < maxRounds) {
|
|
370
368
|
rounds++;
|
|
371
|
-
(0, provider_logger_1.
|
|
369
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] generate() tool round ${rounds}/${maxRounds} tool_calls=${response.tool_calls.length}`);
|
|
372
370
|
// Add assistant message with tool calls to conversation
|
|
373
371
|
messages.push({
|
|
374
372
|
role: 'assistant',
|
|
@@ -389,7 +387,7 @@ class AIClient extends events_1.EventEmitter {
|
|
|
389
387
|
let toolCallsToExecute = response.tool_calls;
|
|
390
388
|
const webFetchCalls = response.tool_calls.filter(tc => tc.name === 'web.fetch');
|
|
391
389
|
if (webFetchCalls.length > MAX_WEB_FETCH_CALLS) {
|
|
392
|
-
(0, provider_logger_1.
|
|
390
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] Limiting web.fetch calls from ${webFetchCalls.length} → ${MAX_WEB_FETCH_CALLS} to prevent context overflow`);
|
|
393
391
|
const limitedWebFetch = webFetchCalls.slice(0, MAX_WEB_FETCH_CALLS);
|
|
394
392
|
const otherCalls = response.tool_calls.filter(tc => tc.name !== 'web.fetch');
|
|
395
393
|
toolCallsToExecute = [...otherCalls, ...limitedWebFetch];
|
|
@@ -407,7 +405,7 @@ class AIClient extends events_1.EventEmitter {
|
|
|
407
405
|
const MAX_TOOL_OUTPUT_PER_ROUND = 50_000;
|
|
408
406
|
let roundOutputSize = 0;
|
|
409
407
|
if (useParallel) {
|
|
410
|
-
(0, provider_logger_1.
|
|
408
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] Using parallel execution for ${toolCallsToExecute.length} tools`);
|
|
411
409
|
const toolResults = await this.toolOrchestrator.executeWithDependencies(toolCallsToExecute, (toolCall) => this.executeTool(toolCall), 5 // maxConcurrent
|
|
412
410
|
);
|
|
413
411
|
// Add results in original order with budget tracking
|
|
@@ -425,7 +423,7 @@ class AIClient extends events_1.EventEmitter {
|
|
|
425
423
|
const resultStr = typeof result === 'string' ? result : JSON.stringify(result);
|
|
426
424
|
// Check budget before adding
|
|
427
425
|
if (roundOutputSize + resultStr.length > MAX_TOOL_OUTPUT_PER_ROUND) {
|
|
428
|
-
(0, provider_logger_1.
|
|
426
|
+
(0, provider_logger_1.logWarn)(`[AIClient][${requestId}] Tool output budget exceeded (${MAX_TOOL_OUTPUT_PER_ROUND} chars), adding placeholder for remaining tools`);
|
|
429
427
|
messages.push({
|
|
430
428
|
role: 'tool',
|
|
431
429
|
tool_call_id: toolCall.id,
|
|
@@ -434,8 +432,8 @@ class AIClient extends events_1.EventEmitter {
|
|
|
434
432
|
parallelBudgetExceeded = true;
|
|
435
433
|
continue;
|
|
436
434
|
}
|
|
437
|
-
const content = typeof result === 'string' && result.length >
|
|
438
|
-
? `${result.slice(0,
|
|
435
|
+
const content = typeof result === 'string' && result.length > this.toolResultMaxChars
|
|
436
|
+
? `${result.slice(0, this.toolResultMaxChars)}\n[TRUNCATED tool result: ${result.length} chars]`
|
|
439
437
|
: result;
|
|
440
438
|
const contentStr = typeof content === 'string' ? content : JSON.stringify(content);
|
|
441
439
|
roundOutputSize += contentStr.length;
|
|
@@ -445,10 +443,10 @@ class AIClient extends events_1.EventEmitter {
|
|
|
445
443
|
content,
|
|
446
444
|
});
|
|
447
445
|
}
|
|
448
|
-
(0, provider_logger_1.
|
|
446
|
+
(0, provider_logger_1.logDebug)(`[AIClient][${requestId}] Round tool output size: ${roundOutputSize} chars (budget: ${MAX_TOOL_OUTPUT_PER_ROUND})`);
|
|
449
447
|
}
|
|
450
448
|
else {
|
|
451
|
-
(0, provider_logger_1.
|
|
449
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] Using sequential execution for ${toolCallsToExecute.length} tools`);
|
|
452
450
|
// Sequential execution with budget tracking
|
|
453
451
|
let seqBudgetExceeded = false;
|
|
454
452
|
for (const toolCall of toolCallsToExecute) {
|
|
@@ -464,7 +462,7 @@ class AIClient extends events_1.EventEmitter {
|
|
|
464
462
|
const resultStr = typeof result === 'string' ? result : JSON.stringify(result);
|
|
465
463
|
// Check budget before adding
|
|
466
464
|
if (roundOutputSize + resultStr.length > MAX_TOOL_OUTPUT_PER_ROUND) {
|
|
467
|
-
(0, provider_logger_1.
|
|
465
|
+
(0, provider_logger_1.logWarn)(`[AIClient][${requestId}] Tool output budget exceeded (${MAX_TOOL_OUTPUT_PER_ROUND} chars), adding placeholder for remaining tools`);
|
|
468
466
|
messages.push({
|
|
469
467
|
role: 'tool',
|
|
470
468
|
tool_call_id: toolCall.id,
|
|
@@ -473,8 +471,8 @@ class AIClient extends events_1.EventEmitter {
|
|
|
473
471
|
seqBudgetExceeded = true;
|
|
474
472
|
continue;
|
|
475
473
|
}
|
|
476
|
-
const content = typeof result === 'string' && result.length >
|
|
477
|
-
? `${result.slice(0,
|
|
474
|
+
const content = typeof result === 'string' && result.length > this.toolResultMaxChars
|
|
475
|
+
? `${result.slice(0, this.toolResultMaxChars)}\n[TRUNCATED tool result: ${result.length} chars]`
|
|
478
476
|
: result;
|
|
479
477
|
const contentStr = typeof content === 'string' ? content : JSON.stringify(content);
|
|
480
478
|
roundOutputSize += contentStr.length;
|
|
@@ -484,7 +482,7 @@ class AIClient extends events_1.EventEmitter {
|
|
|
484
482
|
content,
|
|
485
483
|
});
|
|
486
484
|
}
|
|
487
|
-
(0, provider_logger_1.
|
|
485
|
+
(0, provider_logger_1.logDebug)(`[AIClient][${requestId}] Round tool output size: ${roundOutputSize} chars (budget: ${MAX_TOOL_OUTPUT_PER_ROUND})`);
|
|
488
486
|
}
|
|
489
487
|
// Call the model again with updated messages
|
|
490
488
|
const rawFollowupReq = { ...enrichedRequest, messages, __toolpack_request_id: requestId };
|
|
@@ -492,14 +490,14 @@ class AIClient extends events_1.EventEmitter {
|
|
|
492
490
|
const followupReq = await this.enrichRequestWithTools(rawFollowupReq);
|
|
493
491
|
if (followupReq.tool_choice === 'required') {
|
|
494
492
|
followupReq.tool_choice = lookupOnly ? 'none' : 'auto';
|
|
495
|
-
(0, provider_logger_1.
|
|
493
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] generate() followup tool_choice override required->${followupReq.tool_choice}`);
|
|
496
494
|
}
|
|
497
|
-
if ((0, provider_logger_1.
|
|
498
|
-
(0, provider_logger_1.
|
|
495
|
+
if ((0, provider_logger_1.shouldLog)('debug')) {
|
|
496
|
+
(0, provider_logger_1.logDebug)(`[AIClient][${requestId}] generate() followup request messages=${messages.length}`);
|
|
499
497
|
logRequestMessages(requestId, messages);
|
|
500
498
|
}
|
|
501
499
|
response = await provider.generate(followupReq);
|
|
502
|
-
(0, provider_logger_1.
|
|
500
|
+
(0, provider_logger_1.logDebug)(`[AIClient][${requestId}] generate() followup response finish_reason=${response.finish_reason ?? 'unknown'} tool_calls=${response.tool_calls?.length || 0} content_preview=${(0, provider_logger_1.safePreview)(response.content || '', 200)}`);
|
|
503
501
|
}
|
|
504
502
|
}
|
|
505
503
|
return response;
|
|
@@ -533,7 +531,7 @@ class AIClient extends events_1.EventEmitter {
|
|
|
533
531
|
if (!needsTools && intelligentDetection?.enabled && hasTools) {
|
|
534
532
|
const afterToolCall = isAfterToolCall(enrichedRequest.messages, intelligentDetection.maxFollowUpMessages);
|
|
535
533
|
if (afterToolCall) {
|
|
536
|
-
(0, provider_logger_1.
|
|
534
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] Message is after tool call, using AI to infer tool needs`);
|
|
537
535
|
const fastModel = getFastModelForProvider(resolvedProviderName || 'openai');
|
|
538
536
|
needsTools = await inferNeedsToolsWithAI(provider, resolvedProviderName || 'openai', enrichedRequest.messages, fastModel);
|
|
539
537
|
aiInferenceUsed = true;
|
|
@@ -547,11 +545,11 @@ class AIClient extends events_1.EventEmitter {
|
|
|
547
545
|
}
|
|
548
546
|
else if (shouldForceNone) {
|
|
549
547
|
enrichedRequest.tool_choice = 'none';
|
|
550
|
-
(0, provider_logger_1.
|
|
548
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] AI inference determined no tools needed, setting tool_choice=none`);
|
|
551
549
|
}
|
|
552
550
|
const providerClass = provider?.constructor?.name || 'UnknownProvider';
|
|
553
551
|
const baseReq = { ...enrichedRequest, __toolpack_request_id: requestId };
|
|
554
|
-
(0, provider_logger_1.
|
|
552
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] stream() start provider=${resolvedProviderName} class=${providerClass} model=${enrichedRequest.model} messages=${enrichedRequest.messages.length} tools=${enrichedRequest.tools?.length || 0} tool_choice=${enrichedRequest.tool_choice ?? 'unset'} policy=${policy} needsTools=${needsTools} autoExecute=${this.toolsConfig.enabled && this.toolsConfig.autoExecute}`);
|
|
555
553
|
logRequestMessages(requestId, enrichedRequest.messages);
|
|
556
554
|
if (!this.toolsConfig.enabled || !this.toolsConfig.autoExecute || !this.toolRegistry) {
|
|
557
555
|
yield* provider.stream(baseReq);
|
|
@@ -565,34 +563,34 @@ class AIClient extends events_1.EventEmitter {
|
|
|
565
563
|
const baseMaxRounds = this.toolsConfig.maxToolRounds;
|
|
566
564
|
const maxRounds = this.queryClassifier.getToolRoundsAdjustment(classification, baseMaxRounds);
|
|
567
565
|
if (maxRounds !== baseMaxRounds) {
|
|
568
|
-
(0, provider_logger_1.
|
|
566
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] stream() Query classified as ${classification.type} (confidence: ${classification.confidence.toFixed(2)}), adjusted maxToolRounds: ${baseMaxRounds} → ${maxRounds}`);
|
|
569
567
|
}
|
|
570
568
|
while (rounds <= maxRounds) {
|
|
571
569
|
// Check for abort signal at start of each round
|
|
572
570
|
if (request.signal?.aborted) {
|
|
573
|
-
(0, provider_logger_1.
|
|
571
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] stream() aborted by signal`);
|
|
574
572
|
return;
|
|
575
573
|
}
|
|
576
574
|
let accumulatedContent = '';
|
|
577
575
|
const pendingToolCalls = [];
|
|
578
|
-
(0, provider_logger_1.
|
|
576
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] stream() round_start ${rounds + 1}/${maxRounds}`);
|
|
579
577
|
let lastFinishReason = null;
|
|
580
578
|
const rawRoundReq = { ...baseReq, messages };
|
|
581
579
|
// Re-enrich to include any newly discovered tools from previous rounds
|
|
582
580
|
const roundReq = await this.enrichRequestWithTools(rawRoundReq);
|
|
583
581
|
if (rounds > 0 && roundReq.tool_choice === 'required') {
|
|
584
582
|
roundReq.tool_choice = lookupOnly ? 'none' : 'auto';
|
|
585
|
-
(0, provider_logger_1.
|
|
583
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] stream() round_${rounds + 1} tool_choice override required->${roundReq.tool_choice}`);
|
|
586
584
|
}
|
|
587
585
|
for await (const chunk of provider.stream(roundReq)) {
|
|
588
586
|
// Check for abort signal during streaming
|
|
589
587
|
if (request.signal?.aborted) {
|
|
590
|
-
(0, provider_logger_1.
|
|
588
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] stream() aborted by signal during chunk processing`);
|
|
591
589
|
return;
|
|
592
590
|
}
|
|
593
591
|
if (chunk.tool_calls && chunk.tool_calls.length > 0) {
|
|
594
592
|
pendingToolCalls.push(...chunk.tool_calls);
|
|
595
|
-
(0, provider_logger_1.
|
|
593
|
+
(0, provider_logger_1.logDebug)(`[AIClient][${requestId}] stream() tool_calls_chunk count=${chunk.tool_calls.length} names=${chunk.tool_calls.map(tc => tc.name).join(', ')}`);
|
|
596
594
|
// Yield tool calls in the chunk so consumers can track them
|
|
597
595
|
yield chunk;
|
|
598
596
|
}
|
|
@@ -607,18 +605,18 @@ class AIClient extends events_1.EventEmitter {
|
|
|
607
605
|
yield chunk;
|
|
608
606
|
}
|
|
609
607
|
}
|
|
610
|
-
(0, provider_logger_1.
|
|
608
|
+
(0, provider_logger_1.logDebug)(`[AIClient][${requestId}] stream() round_end finish_reason=${lastFinishReason ?? 'unknown'} accumulated_len=${accumulatedContent.length} tool_calls_total=${pendingToolCalls.length} content_preview=${(0, provider_logger_1.safePreview)(accumulatedContent, 200)}`);
|
|
611
609
|
// If no tool calls, we're done
|
|
612
610
|
if (pendingToolCalls.length === 0) {
|
|
613
611
|
break;
|
|
614
612
|
}
|
|
615
|
-
(0, provider_logger_1.
|
|
613
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] stream() received ${pendingToolCalls.length} tool call(s): ${pendingToolCalls.map(tc => tc.name).join(', ')}`);
|
|
616
614
|
rounds++;
|
|
617
615
|
if (rounds > maxRounds) {
|
|
618
|
-
(0, provider_logger_1.
|
|
616
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] stream() max tool rounds (${maxRounds}) reached`);
|
|
619
617
|
break;
|
|
620
618
|
}
|
|
621
|
-
(0, provider_logger_1.
|
|
619
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] stream() tool round ${rounds}/${maxRounds}`);
|
|
622
620
|
// Add assistant message and tool results to conversation
|
|
623
621
|
messages.push({
|
|
624
622
|
role: 'assistant',
|
|
@@ -637,7 +635,7 @@ class AIClient extends events_1.EventEmitter {
|
|
|
637
635
|
let toolCallsToExecute = pendingToolCalls;
|
|
638
636
|
const webFetchCalls = pendingToolCalls.filter(tc => tc.name === 'web.fetch');
|
|
639
637
|
if (webFetchCalls.length > MAX_WEB_FETCH_CALLS) {
|
|
640
|
-
(0, provider_logger_1.
|
|
638
|
+
(0, provider_logger_1.logInfo)(`[AIClient][${requestId}] Limiting web.fetch calls from ${webFetchCalls.length} → ${MAX_WEB_FETCH_CALLS} to prevent context overflow`);
|
|
641
639
|
const limitedWebFetch = webFetchCalls.slice(0, MAX_WEB_FETCH_CALLS);
|
|
642
640
|
const otherCalls = pendingToolCalls.filter(tc => tc.name !== 'web.fetch');
|
|
643
641
|
toolCallsToExecute = [...otherCalls, ...limitedWebFetch];
|
|
@@ -688,7 +686,7 @@ class AIClient extends events_1.EventEmitter {
|
|
|
688
686
|
const resultStr = typeof result === 'string' ? result : JSON.stringify(result);
|
|
689
687
|
// Check budget before adding
|
|
690
688
|
if (roundOutputSize + resultStr.length > MAX_TOOL_OUTPUT_PER_ROUND) {
|
|
691
|
-
(0, provider_logger_1.
|
|
689
|
+
(0, provider_logger_1.logWarn)(`[AIClient][${requestId}] Tool output budget exceeded (${MAX_TOOL_OUTPUT_PER_ROUND} chars), adding placeholder for remaining tools`);
|
|
692
690
|
messages.push({
|
|
693
691
|
role: 'tool',
|
|
694
692
|
tool_call_id: toolCall.id,
|
|
@@ -697,8 +695,8 @@ class AIClient extends events_1.EventEmitter {
|
|
|
697
695
|
budgetExceeded = true;
|
|
698
696
|
continue;
|
|
699
697
|
}
|
|
700
|
-
const content = typeof result === 'string' && result.length >
|
|
701
|
-
? `${result.slice(0,
|
|
698
|
+
const content = typeof result === 'string' && result.length > this.toolResultMaxChars
|
|
699
|
+
? `${result.slice(0, this.toolResultMaxChars)}\n[TRUNCATED tool result: ${result.length} chars]`
|
|
702
700
|
: result;
|
|
703
701
|
const contentStr = typeof content === 'string' ? content : JSON.stringify(content);
|
|
704
702
|
roundOutputSize += contentStr.length;
|
|
@@ -717,9 +715,9 @@ class AIClient extends events_1.EventEmitter {
|
|
|
717
715
|
}],
|
|
718
716
|
};
|
|
719
717
|
}
|
|
720
|
-
(0, provider_logger_1.
|
|
721
|
-
if ((0, provider_logger_1.
|
|
722
|
-
(0, provider_logger_1.
|
|
718
|
+
(0, provider_logger_1.logDebug)(`[AIClient][${requestId}] Round tool output size: ${roundOutputSize} chars (budget: ${MAX_TOOL_OUTPUT_PER_ROUND})`);
|
|
719
|
+
if ((0, provider_logger_1.shouldLog)('debug')) {
|
|
720
|
+
(0, provider_logger_1.logDebug)(`[AIClient][${requestId}] stream() after_tools messages=${messages.length}`);
|
|
723
721
|
logRequestMessages(requestId, messages);
|
|
724
722
|
}
|
|
725
723
|
}
|
|
@@ -747,11 +745,11 @@ class AIClient extends events_1.EventEmitter {
|
|
|
747
745
|
async enrichRequestWithTools(request) {
|
|
748
746
|
// If mode blocks ALL tools, return request with no tools
|
|
749
747
|
if (this.activeMode?.blockAllTools) {
|
|
750
|
-
(0, provider_logger_1.
|
|
748
|
+
(0, provider_logger_1.logInfo)(`[AIClient] Mode "${this.activeMode.displayName}" blocks all tools`);
|
|
751
749
|
return request;
|
|
752
750
|
}
|
|
753
|
-
if (!this.toolsConfig.enabled || !this.toolRegistry) {
|
|
754
|
-
(0, provider_logger_1.
|
|
751
|
+
if (!this.toolsConfig.enabled || (!this.toolRegistry && (request.tools?.length || 0) === 0)) {
|
|
752
|
+
(0, provider_logger_1.logDebug)(`[AIClient] Tools disabled or no registry`);
|
|
755
753
|
return request;
|
|
756
754
|
}
|
|
757
755
|
// Merge mode-specific tool search config with global config
|
|
@@ -766,22 +764,22 @@ class AIClient extends events_1.EventEmitter {
|
|
|
766
764
|
...(this.activeMode.toolSearch.alwaysLoadedCategories ? { alwaysLoadedCategories: this.activeMode.toolSearch.alwaysLoadedCategories } : {}),
|
|
767
765
|
}
|
|
768
766
|
};
|
|
769
|
-
(0, provider_logger_1.
|
|
767
|
+
(0, provider_logger_1.logDebug)(`[AIClient] Merged mode toolSearch config: enabled=${resolvedToolsConfig.toolSearch?.enabled}, alwaysLoadedTools=${resolvedToolsConfig.toolSearch?.alwaysLoadedTools?.length || 0}`);
|
|
770
768
|
}
|
|
771
769
|
// If the request already has tools, only add newly discovered tools when tool.search mode is enabled
|
|
772
770
|
if (request.tools && request.tools.length > 0) {
|
|
773
771
|
if (!resolvedToolsConfig.toolSearch?.enabled || !this.toolRegistry) {
|
|
774
|
-
(0, provider_logger_1.
|
|
772
|
+
(0, provider_logger_1.logDebug)(`[AIClient] Request already has ${request.tools.length} tools`);
|
|
775
773
|
return request;
|
|
776
774
|
}
|
|
777
775
|
let schemas = await this.toolRouter.resolve(request.messages, this.toolRegistry, resolvedToolsConfig);
|
|
778
|
-
(0, provider_logger_1.
|
|
776
|
+
(0, provider_logger_1.logDebug)(`[AIClient] Resolved ${schemas.length} tools to send: ${schemas.map(s => s.name).join(', ') || 'none'}`);
|
|
779
777
|
if (this.activeMode && schemas.length > 0) {
|
|
780
778
|
const beforeCount = schemas.length;
|
|
781
779
|
schemas = this.filterSchemasByMode(schemas, this.activeMode);
|
|
782
780
|
const filteredCount = beforeCount - schemas.length;
|
|
783
781
|
if (filteredCount > 0) {
|
|
784
|
-
(0, provider_logger_1.
|
|
782
|
+
(0, provider_logger_1.logInfo)(`[AIClient] Mode "${this.activeMode.displayName}" filtered out ${filteredCount} tools`);
|
|
785
783
|
}
|
|
786
784
|
}
|
|
787
785
|
const existingToolNames = new Set(request.tools.map(tool => tool.function.name));
|
|
@@ -796,7 +794,7 @@ class AIClient extends events_1.EventEmitter {
|
|
|
796
794
|
},
|
|
797
795
|
}));
|
|
798
796
|
if (newTools.length === 0) {
|
|
799
|
-
(0, provider_logger_1.
|
|
797
|
+
(0, provider_logger_1.logDebug)(`[AIClient] Request already has ${request.tools.length} tools (no new discoveries)`);
|
|
800
798
|
return request;
|
|
801
799
|
}
|
|
802
800
|
let enrichedRequest = {
|
|
@@ -808,15 +806,20 @@ class AIClient extends events_1.EventEmitter {
|
|
|
808
806
|
}
|
|
809
807
|
return enrichedRequest;
|
|
810
808
|
}
|
|
811
|
-
|
|
812
|
-
|
|
809
|
+
if (!this.toolRegistry) {
|
|
810
|
+
(0, provider_logger_1.logDebug)('[AIClient] Tool registry not configured, skipping tool resolution');
|
|
811
|
+
return request;
|
|
812
|
+
}
|
|
813
|
+
const activeRegistry = this.toolRegistry;
|
|
814
|
+
let schemas = await this.toolRouter.resolve(request.messages, activeRegistry, resolvedToolsConfig);
|
|
815
|
+
(0, provider_logger_1.logDebug)(`[AIClient] Resolved ${schemas.length} tools to send: ${schemas.map(s => s.name).join(', ') || 'none'}`);
|
|
813
816
|
// Apply mode-based filtering
|
|
814
817
|
if (this.activeMode && schemas.length > 0) {
|
|
815
818
|
const beforeCount = schemas.length;
|
|
816
819
|
schemas = this.filterSchemasByMode(schemas, this.activeMode);
|
|
817
820
|
const filteredCount = beforeCount - schemas.length;
|
|
818
821
|
if (filteredCount > 0) {
|
|
819
|
-
(0, provider_logger_1.
|
|
822
|
+
(0, provider_logger_1.logInfo)(`[AIClient] Mode "${this.activeMode.displayName}" filtered out ${filteredCount} tools`);
|
|
820
823
|
}
|
|
821
824
|
}
|
|
822
825
|
if (schemas.length === 0) {
|
|
@@ -832,7 +835,7 @@ class AIClient extends events_1.EventEmitter {
|
|
|
832
835
|
}));
|
|
833
836
|
let enrichedRequest = { ...request, tools };
|
|
834
837
|
// Inject Tool Search system prompt if enabled
|
|
835
|
-
if (this.toolsConfig.toolSearch?.enabled &&
|
|
838
|
+
if (this.toolsConfig.toolSearch?.enabled && activeRegistry) {
|
|
836
839
|
enrichedRequest = this.injectToolSearchPrompt(enrichedRequest);
|
|
837
840
|
}
|
|
838
841
|
return enrichedRequest;
|
|
@@ -866,11 +869,11 @@ class AIClient extends events_1.EventEmitter {
|
|
|
866
869
|
*/
|
|
867
870
|
injectModeSystemPrompt(request) {
|
|
868
871
|
if (!this.activeMode || !this.activeMode.systemPrompt) {
|
|
869
|
-
(0, provider_logger_1.
|
|
872
|
+
(0, provider_logger_1.logDebug)(`[AIClient] injectModeSystemPrompt: No active mode or empty systemPrompt. activeMode=${this.activeMode?.name}, systemPrompt=${this.activeMode?.systemPrompt?.substring(0, 50)}`);
|
|
870
873
|
return request;
|
|
871
874
|
}
|
|
872
875
|
const modePrompt = this.activeMode.systemPrompt;
|
|
873
|
-
(0, provider_logger_1.
|
|
876
|
+
(0, provider_logger_1.logDebug)(`[AIClient] injectModeSystemPrompt: Injecting mode prompt for ${this.activeMode.name}, length=${modePrompt.length}`);
|
|
874
877
|
const hasSystemMessage = request.messages.some(m => m.role === 'system');
|
|
875
878
|
if (hasSystemMessage) {
|
|
876
879
|
// Prepend mode prompt to existing system message
|
|
@@ -1036,7 +1039,7 @@ NEVER guess or hallucinate tool names. ALWAYS use tool.search to discover tools
|
|
|
1036
1039
|
status: 'started',
|
|
1037
1040
|
args: toolCall.arguments,
|
|
1038
1041
|
});
|
|
1039
|
-
(0, provider_logger_1.
|
|
1042
|
+
(0, provider_logger_1.logInfo)(`[AIClient] Executing tool: ${toolCall.name} with args: ${(0, provider_logger_1.safePreview)(toolCall.arguments, 500)}`);
|
|
1040
1043
|
if (!this.toolRegistry) {
|
|
1041
1044
|
const error = 'No tool registry configured';
|
|
1042
1045
|
this.emit('tool:failed', {
|
|
@@ -1073,7 +1076,7 @@ NEVER guess or hallucinate tool names. ALWAYS use tool.search to discover tools
|
|
|
1073
1076
|
}
|
|
1074
1077
|
const tool = this.toolRegistry.get(toolCall.name);
|
|
1075
1078
|
if (!tool) {
|
|
1076
|
-
(0, provider_logger_1.
|
|
1079
|
+
(0, provider_logger_1.logWarn)(`[AIClient] Tool '${toolCall.name}' not found in registry`);
|
|
1077
1080
|
// Fuzzy match: detect common hallucination patterns
|
|
1078
1081
|
const suggestion = this.findSimilarToolName(toolCall.name);
|
|
1079
1082
|
const errorMsg = suggestion
|
|
@@ -1092,7 +1095,7 @@ NEVER guess or hallucinate tool names. ALWAYS use tool.search to discover tools
|
|
|
1092
1095
|
const ctx = {
|
|
1093
1096
|
workspaceRoot: process.cwd(),
|
|
1094
1097
|
config: this.toolsConfig?.additionalConfigurations ?? {},
|
|
1095
|
-
log: (msg) => (0, provider_logger_1.
|
|
1098
|
+
log: (msg) => (0, provider_logger_1.logInfo)(`[Tool] ${msg}`),
|
|
1096
1099
|
};
|
|
1097
1100
|
const result = await tool.execute(toolCall.arguments, ctx);
|
|
1098
1101
|
const duration = Date.now() - startTime;
|
|
@@ -1114,9 +1117,9 @@ NEVER guess or hallucinate tool names. ALWAYS use tool.search to discover tools
|
|
|
1114
1117
|
status: 'success',
|
|
1115
1118
|
timestamp: Date.now(),
|
|
1116
1119
|
});
|
|
1117
|
-
(0, provider_logger_1.
|
|
1118
|
-
if ((0, provider_logger_1.
|
|
1119
|
-
(0, provider_logger_1.
|
|
1120
|
+
(0, provider_logger_1.logInfo)(`[AIClient] Tool ${toolCall.name} executed successfully in ${duration}ms result_len=${result?.length ?? 0}`);
|
|
1121
|
+
if ((0, provider_logger_1.shouldLog)('debug')) {
|
|
1122
|
+
(0, provider_logger_1.logDebug)(`[AIClient] Tool ${toolCall.name} result_preview=${(0, provider_logger_1.safePreview)(result, 400)}`);
|
|
1120
1123
|
}
|
|
1121
1124
|
return result;
|
|
1122
1125
|
}
|
|
@@ -1141,7 +1144,7 @@ NEVER guess or hallucinate tool names. ALWAYS use tool.search to discover tools
|
|
|
1141
1144
|
status: 'error',
|
|
1142
1145
|
timestamp: Date.now(),
|
|
1143
1146
|
});
|
|
1144
|
-
(0, provider_logger_1.
|
|
1147
|
+
(0, provider_logger_1.logError)(`[AIClient] Tool ${toolCall.name} failed: ${(0, provider_logger_1.safePreview)(errorMsg, 300)}`);
|
|
1145
1148
|
return JSON.stringify({ error: errorMsg });
|
|
1146
1149
|
}
|
|
1147
1150
|
}
|
|
@@ -1213,12 +1216,12 @@ NEVER guess or hallucinate tool names. ALWAYS use tool.search to discover tools
|
|
|
1213
1216
|
executeToolSearch(args) {
|
|
1214
1217
|
const { query, category } = args;
|
|
1215
1218
|
const limit = this.toolsConfig.toolSearch?.searchResultLimit ?? 5;
|
|
1216
|
-
(0, provider_logger_1.
|
|
1219
|
+
(0, provider_logger_1.logInfo)(`[AIClient] Executing tool.search: query="${query}" category=${category || 'all'} limit=${limit}`);
|
|
1217
1220
|
const results = this.bm25Engine.search(query, { limit, category });
|
|
1218
1221
|
// Record discovered tools in the cache
|
|
1219
1222
|
const toolNames = results.map(r => r.toolName);
|
|
1220
1223
|
this.toolRouter.getDiscoveryCache().recordDiscovery(query, toolNames);
|
|
1221
|
-
(0, provider_logger_1.
|
|
1224
|
+
(0, provider_logger_1.logDebug)(`[AIClient] tool.search found ${results.length} tools: ${toolNames.join(', ') || 'none'}`);
|
|
1222
1225
|
return JSON.stringify({
|
|
1223
1226
|
query,
|
|
1224
1227
|
found: results.length,
|