@probelabs/probe 0.6.0-rc229 → 0.6.0-rc231
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/bin/binaries/probe-v0.6.0-rc231-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc231-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc231-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc231-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc231-x86_64-unknown-linux-musl.tar.gz +0 -0
- package/build/agent/ProbeAgent.js +128 -7
- package/build/agent/index.js +191 -12
- package/build/agent/mcp/config.js +7 -1
- package/build/agent/tasks/taskTool.js +32 -2
- package/build/agent/tools.js +4 -0
- package/build/index.js +4 -0
- package/build/tools/common.js +24 -0
- package/build/utils/path-validation.js +28 -2
- package/cjs/agent/ProbeAgent.cjs +8734 -10878
- package/cjs/index.cjs +8748 -10888
- package/package.json +2 -2
- package/src/agent/ProbeAgent.js +128 -7
- package/src/agent/mcp/config.js +7 -1
- package/src/agent/tasks/taskTool.js +32 -2
- package/src/agent/tools.js +4 -0
- package/src/index.js +4 -0
- package/src/tools/common.js +24 -0
- package/src/utils/path-validation.js +28 -2
- package/bin/binaries/probe-v0.6.0-rc229-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc229-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc229-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc229-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc229-x86_64-unknown-linux-musl.tar.gz +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -58,6 +58,8 @@ import {
|
|
|
58
58
|
implementToolDefinition,
|
|
59
59
|
editToolDefinition,
|
|
60
60
|
createToolDefinition,
|
|
61
|
+
googleSearchToolDefinition,
|
|
62
|
+
urlContextToolDefinition,
|
|
61
63
|
attemptCompletionSchema,
|
|
62
64
|
parseXmlToolCallWithThinking
|
|
63
65
|
} from './tools.js';
|
|
@@ -404,6 +406,10 @@ export class ProbeAgent {
|
|
|
404
406
|
// Initialize the AI model
|
|
405
407
|
this.initializeModel();
|
|
406
408
|
|
|
409
|
+
// Gemini built-in tools (provider-defined, server-side)
|
|
410
|
+
// These are enabled automatically when the provider is Google
|
|
411
|
+
this._geminiToolsEnabled = this._initializeGeminiBuiltinTools();
|
|
412
|
+
|
|
407
413
|
// Note: MCP initialization is now done in initialize() method
|
|
408
414
|
// Constructor must remain synchronous for backward compatibility
|
|
409
415
|
}
|
|
@@ -1320,6 +1326,15 @@ export class ProbeAgent {
|
|
|
1320
1326
|
abortSignal: controller.signal
|
|
1321
1327
|
};
|
|
1322
1328
|
|
|
1329
|
+
// Strip Gemini provider-defined tools when falling back to non-Google provider
|
|
1330
|
+
// These tools have no execute function and would cause errors on other providers
|
|
1331
|
+
if (config.provider !== 'google' && fallbackOptions.tools) {
|
|
1332
|
+
delete fallbackOptions.tools;
|
|
1333
|
+
if (this.debug) {
|
|
1334
|
+
console.error(`[DEBUG] Stripped Gemini built-in tools for fallback to ${config.provider} provider`);
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1323
1338
|
const providerRetryManager = new RetryManager({
|
|
1324
1339
|
maxRetries: config.maxRetries ?? this.retryConfig.maxRetries ?? 3,
|
|
1325
1340
|
initialDelay: this.retryConfig.initialDelay ?? 1000,
|
|
@@ -1442,6 +1457,83 @@ export class ProbeAgent {
|
|
|
1442
1457
|
}
|
|
1443
1458
|
}
|
|
1444
1459
|
|
|
1460
|
+
/**
|
|
1461
|
+
* Initialize Gemini built-in tools (gemini_google_search, gemini_url_context).
|
|
1462
|
+
* These are provider-defined tools that execute server-side on Google's infrastructure.
|
|
1463
|
+
* They are only available when the provider is Google Gemini.
|
|
1464
|
+
* @returns {{ googleSearch: boolean, urlContext: boolean }} Which tools were enabled
|
|
1465
|
+
* @private
|
|
1466
|
+
*/
|
|
1467
|
+
_initializeGeminiBuiltinTools() {
|
|
1468
|
+
const isToolAllowed = (toolName) => this.allowedTools.isEnabled(toolName);
|
|
1469
|
+
const result = { googleSearch: false, urlContext: false };
|
|
1470
|
+
|
|
1471
|
+
if (this.apiType !== 'google') {
|
|
1472
|
+
// Log info about unavailability for non-Google providers
|
|
1473
|
+
if (isToolAllowed('gemini_google_search') || isToolAllowed('gemini_url_context')) {
|
|
1474
|
+
if (this.debug) {
|
|
1475
|
+
console.error(`[DEBUG] Gemini built-in tools (gemini_google_search, gemini_url_context) are not available: provider is '${this.apiType}', not 'google'. These tools require the Google Gemini provider.`);
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
return result;
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
// Check SDK support
|
|
1482
|
+
if (!this.provider || !this.provider.tools) {
|
|
1483
|
+
console.error('[ProbeAgent] Gemini built-in tools unavailable: @ai-sdk/google does not expose provider.tools. Upgrade to @ai-sdk/google v2.0.14+.');
|
|
1484
|
+
return result;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
if (isToolAllowed('gemini_google_search')) {
|
|
1488
|
+
result.googleSearch = true;
|
|
1489
|
+
if (this.debug) {
|
|
1490
|
+
console.error('[DEBUG] Gemini built-in tool enabled: gemini_google_search');
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
if (isToolAllowed('gemini_url_context')) {
|
|
1495
|
+
result.urlContext = true;
|
|
1496
|
+
if (this.debug) {
|
|
1497
|
+
console.error('[DEBUG] Gemini built-in tool enabled: gemini_url_context');
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
return result;
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
/**
|
|
1505
|
+
* Build Gemini provider-defined tools object for streamText().
|
|
1506
|
+
* Returns undefined if no Gemini tools are enabled.
|
|
1507
|
+
* @returns {Object|undefined}
|
|
1508
|
+
* @private
|
|
1509
|
+
*/
|
|
1510
|
+
_buildGeminiProviderTools() {
|
|
1511
|
+
if (this.apiType !== 'google' || !this._geminiToolsEnabled) {
|
|
1512
|
+
return undefined;
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
const { googleSearch, urlContext } = this._geminiToolsEnabled;
|
|
1516
|
+
if (!googleSearch && !urlContext) {
|
|
1517
|
+
return undefined;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
if (!this.provider || !this.provider.tools) {
|
|
1521
|
+
return undefined;
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
const tools = {};
|
|
1525
|
+
const providerTools = this.provider.tools;
|
|
1526
|
+
|
|
1527
|
+
if (googleSearch && providerTools.googleSearch) {
|
|
1528
|
+
tools.google_search = providerTools.googleSearch({});
|
|
1529
|
+
}
|
|
1530
|
+
if (urlContext && providerTools.urlContext) {
|
|
1531
|
+
tools.url_context = providerTools.urlContext({});
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
return Object.keys(tools).length > 0 ? tools : undefined;
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1445
1537
|
/**
|
|
1446
1538
|
* Initialize AWS Bedrock model
|
|
1447
1539
|
*/
|
|
@@ -2404,10 +2496,9 @@ ${extractGuidance}
|
|
|
2404
2496
|
toolDefinitions += `${taskToolDefinition}\n`;
|
|
2405
2497
|
}
|
|
2406
2498
|
|
|
2407
|
-
// Always include attempt_completion
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
}
|
|
2499
|
+
// Always include attempt_completion unconditionally - it's a completion signal, not a tool
|
|
2500
|
+
// This ensures agents can always complete their work, regardless of tool restrictions
|
|
2501
|
+
toolDefinitions += `${attemptCompletionToolDefinition}\n`;
|
|
2411
2502
|
|
|
2412
2503
|
// Delegate tool (require both enableDelegate flag AND allowedTools permission)
|
|
2413
2504
|
// Place after attempt_completion as it's an optional tool
|
|
@@ -2420,6 +2511,14 @@ ${extractGuidance}
|
|
|
2420
2511
|
toolDefinitions += `${analyzeAllToolDefinition}\n`;
|
|
2421
2512
|
}
|
|
2422
2513
|
|
|
2514
|
+
// Gemini built-in tools (only when using Google provider)
|
|
2515
|
+
if (this._geminiToolsEnabled?.googleSearch && isToolAllowed('gemini_google_search')) {
|
|
2516
|
+
toolDefinitions += `${googleSearchToolDefinition}\n`;
|
|
2517
|
+
}
|
|
2518
|
+
if (this._geminiToolsEnabled?.urlContext && isToolAllowed('gemini_url_context')) {
|
|
2519
|
+
toolDefinitions += `${urlContextToolDefinition}\n`;
|
|
2520
|
+
}
|
|
2521
|
+
|
|
2423
2522
|
// Build XML tool guidelines with dynamic examples based on allowed tools
|
|
2424
2523
|
// Build examples only for allowed tools
|
|
2425
2524
|
let toolExamples = '';
|
|
@@ -2497,6 +2596,12 @@ The configuration is loaded from src/config.js lines 15-25 which contains the da
|
|
|
2497
2596
|
availableToolsList += '- attempt_completion: Finalize the task and provide the result to the user.\n';
|
|
2498
2597
|
availableToolsList += '- attempt_complete: Quick completion using previous response (shorthand).\n';
|
|
2499
2598
|
}
|
|
2599
|
+
if (this._geminiToolsEnabled?.googleSearch && isToolAllowed('gemini_google_search')) {
|
|
2600
|
+
availableToolsList += '- gemini_google_search: (auto) Web search via Google — invoked automatically by the model when it needs current information.\n';
|
|
2601
|
+
}
|
|
2602
|
+
if (this._geminiToolsEnabled?.urlContext && isToolAllowed('gemini_url_context')) {
|
|
2603
|
+
availableToolsList += '- gemini_url_context: (auto) URL content reader via Google — automatically fetches and reads URLs mentioned in the conversation.\n';
|
|
2604
|
+
}
|
|
2500
2605
|
|
|
2501
2606
|
let xmlToolGuidelines = `
|
|
2502
2607
|
# Tool Use Formatting
|
|
@@ -3049,12 +3154,21 @@ Follow these instructions carefully:
|
|
|
3049
3154
|
// Prepare messages with potential image content
|
|
3050
3155
|
const messagesForAI = this.prepareMessagesWithImages(currentMessages);
|
|
3051
3156
|
|
|
3052
|
-
|
|
3157
|
+
// Build streamText options, including Gemini provider-defined tools if applicable
|
|
3158
|
+
const streamOptions = {
|
|
3053
3159
|
model: this.provider ? this.provider(this.model) : this.model,
|
|
3054
3160
|
messages: messagesForAI,
|
|
3055
3161
|
maxTokens: maxResponseTokens,
|
|
3056
3162
|
temperature: 0.3,
|
|
3057
|
-
}
|
|
3163
|
+
};
|
|
3164
|
+
|
|
3165
|
+
// Inject Gemini built-in tools (gemini_google_search, gemini_url_context) when using Google provider
|
|
3166
|
+
const geminiProviderTools = this._buildGeminiProviderTools();
|
|
3167
|
+
if (geminiProviderTools) {
|
|
3168
|
+
streamOptions.tools = geminiProviderTools;
|
|
3169
|
+
}
|
|
3170
|
+
|
|
3171
|
+
const result = await this.streamTextWithRetryAndFallback(streamOptions);
|
|
3058
3172
|
|
|
3059
3173
|
// Get the promise reference BEFORE consuming stream (doesn't lock it)
|
|
3060
3174
|
const usagePromise = result.usage;
|
|
@@ -3189,8 +3303,9 @@ Follow these instructions carefully:
|
|
|
3189
3303
|
if (this.enableSkills && this.allowedTools.isEnabled('listSkills')) validTools.push('listSkills');
|
|
3190
3304
|
if (this.enableSkills && this.allowedTools.isEnabled('useSkill')) validTools.push('useSkill');
|
|
3191
3305
|
if (this.allowedTools.isEnabled('readImage')) validTools.push('readImage');
|
|
3192
|
-
// Always allow attempt_completion - it's a completion signal, not a tool
|
|
3306
|
+
// Always allow attempt_completion in validTools - it's a completion signal, not a tool
|
|
3193
3307
|
// This ensures agents can complete even when disableTools: true is set (fixes #333)
|
|
3308
|
+
// The tool DEFINITION may be hidden in raw AI mode, but we still need to recognize it
|
|
3194
3309
|
validTools.push('attempt_completion');
|
|
3195
3310
|
|
|
3196
3311
|
// Edit tools (require both allowEdit flag AND allowedTools permission)
|
|
@@ -3585,6 +3700,12 @@ Follow these instructions carefully:
|
|
|
3585
3700
|
|
|
3586
3701
|
let toolResultContent = typeof toolResult === 'string' ? toolResult : JSON.stringify(toolResult, null, 2);
|
|
3587
3702
|
|
|
3703
|
+
// Convert absolute workspace paths to relative in tool results
|
|
3704
|
+
if (this.workspaceRoot && toolResultContent) {
|
|
3705
|
+
const wsPrefix = this.workspaceRoot.endsWith(sep) ? this.workspaceRoot : this.workspaceRoot + sep;
|
|
3706
|
+
toolResultContent = toolResultContent.split(wsPrefix).join('');
|
|
3707
|
+
}
|
|
3708
|
+
|
|
3588
3709
|
// Truncate if output exceeds token limit
|
|
3589
3710
|
try {
|
|
3590
3711
|
const truncateResult = await truncateIfNeeded(toolResultContent, this.tokenCounter, this.sessionId, this.maxOutputTokens);
|
package/build/agent/index.js
CHANGED
|
@@ -3314,6 +3314,29 @@ async function validateCwdPath(inputPath, defaultPath = process.cwd()) {
|
|
|
3314
3314
|
try {
|
|
3315
3315
|
const stats = await fs5.stat(normalizedPath);
|
|
3316
3316
|
if (!stats.isDirectory()) {
|
|
3317
|
+
const resolvedPath = safeRealpath(normalizedPath);
|
|
3318
|
+
const dirPath = path4.dirname(resolvedPath);
|
|
3319
|
+
try {
|
|
3320
|
+
const dirStats = await fs5.stat(dirPath);
|
|
3321
|
+
if (dirStats.isDirectory()) {
|
|
3322
|
+
return safeRealpath(dirPath);
|
|
3323
|
+
}
|
|
3324
|
+
} catch (dirError) {
|
|
3325
|
+
if (dirError.code === "ENOENT") {
|
|
3326
|
+
throw new PathError(`Parent directory does not exist for file: ${normalizedPath}`, {
|
|
3327
|
+
suggestion: "The specified path is a file whose parent directory does not exist.",
|
|
3328
|
+
details: { path: normalizedPath, parentPath: dirPath, type: "file" }
|
|
3329
|
+
});
|
|
3330
|
+
}
|
|
3331
|
+
if (dirError.code === "EACCES") {
|
|
3332
|
+
throw new PathError(`Permission denied accessing parent directory: ${dirPath}`, {
|
|
3333
|
+
recoverable: false,
|
|
3334
|
+
suggestion: "Permission denied accessing the parent directory of the specified file.",
|
|
3335
|
+
details: { path: normalizedPath, parentPath: dirPath, type: "file" }
|
|
3336
|
+
});
|
|
3337
|
+
}
|
|
3338
|
+
throw dirError;
|
|
3339
|
+
}
|
|
3317
3340
|
throw new PathError(`Path is not a directory: ${normalizedPath}`, {
|
|
3318
3341
|
suggestion: "The specified path is a file, not a directory. Please provide a directory path for searching.",
|
|
3319
3342
|
details: { path: normalizedPath, type: "file" }
|
|
@@ -9176,7 +9199,15 @@ function createTaskTool(options = {}) {
|
|
|
9176
9199
|
});
|
|
9177
9200
|
return `Error: Invalid task parameters - ${validation.error.message}`;
|
|
9178
9201
|
}
|
|
9179
|
-
const { action, tasks, id, title, description, status, priority, dependencies, after } = validation.data;
|
|
9202
|
+
const { action, tasks: rawTasks, id, title, description, status, priority, dependencies, after } = validation.data;
|
|
9203
|
+
let tasks = rawTasks;
|
|
9204
|
+
if (typeof rawTasks === "string") {
|
|
9205
|
+
try {
|
|
9206
|
+
tasks = JSON.parse(rawTasks);
|
|
9207
|
+
} catch (e) {
|
|
9208
|
+
return `Error: Invalid tasks JSON - ${e.message}`;
|
|
9209
|
+
}
|
|
9210
|
+
}
|
|
9180
9211
|
switch (action) {
|
|
9181
9212
|
case "create": {
|
|
9182
9213
|
if (tasks && Array.isArray(tasks)) {
|
|
@@ -9351,7 +9382,8 @@ var init_taskTool = __esm({
|
|
|
9351
9382
|
});
|
|
9352
9383
|
taskSchema = external_exports.object({
|
|
9353
9384
|
action: external_exports.enum(["create", "update", "complete", "delete", "list"]),
|
|
9354
|
-
|
|
9385
|
+
// Accept both array and JSON string (AI models sometimes serialize as string)
|
|
9386
|
+
tasks: external_exports.union([external_exports.array(external_exports.union([external_exports.string(), taskItemSchema])), external_exports.string()]).optional(),
|
|
9355
9387
|
id: external_exports.string().optional(),
|
|
9356
9388
|
title: external_exports.string().optional(),
|
|
9357
9389
|
description: external_exports.string().optional(),
|
|
@@ -9462,6 +9494,25 @@ SKIP TASKS for single-goal requests, even if they require multiple searches:
|
|
|
9462
9494
|
**Key insight**: Multiple *internal steps* (search, read, analyze) are NOT the same as multiple *goals*.
|
|
9463
9495
|
A single investigation with many steps is still ONE task, not many.
|
|
9464
9496
|
|
|
9497
|
+
## Task Granularity
|
|
9498
|
+
|
|
9499
|
+
Tasks represent LOGICAL UNITS OF WORK, not individual files or steps:
|
|
9500
|
+
- "Fix 8 similar test files" \u2192 ONE task (same type of fix across files)
|
|
9501
|
+
- "Update API + tests + docs" \u2192 THREE tasks (different types of work)
|
|
9502
|
+
- "Implement feature in 5 files" \u2192 ONE task (single feature)
|
|
9503
|
+
|
|
9504
|
+
**Rule of thumb**: If you're creating more than 3-4 tasks, you're probably too granular.
|
|
9505
|
+
|
|
9506
|
+
**Anti-patterns to avoid**:
|
|
9507
|
+
- One task per file \u274C
|
|
9508
|
+
- One task per function \u274C
|
|
9509
|
+
- One task per repository (when same type of work) \u274C
|
|
9510
|
+
|
|
9511
|
+
**Good patterns**:
|
|
9512
|
+
- One task per distinct deliverable \u2713
|
|
9513
|
+
- One task per phase (implement, test, document) \u2713
|
|
9514
|
+
- One task per different type of work \u2713
|
|
9515
|
+
|
|
9465
9516
|
MODIFY TASKS when (during execution):
|
|
9466
9517
|
- You discover the problem is more complex than expected \u2192 Add new tasks
|
|
9467
9518
|
- A single task covers too much scope \u2192 Split into smaller tasks
|
|
@@ -9807,7 +9858,7 @@ function resolveTargetPath(target, cwd) {
|
|
|
9807
9858
|
}
|
|
9808
9859
|
return filePart + suffix;
|
|
9809
9860
|
}
|
|
9810
|
-
var searchSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
|
|
9861
|
+
var searchSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
|
|
9811
9862
|
var init_common = __esm({
|
|
9812
9863
|
"src/tools/common.js"() {
|
|
9813
9864
|
"use strict";
|
|
@@ -10163,6 +10214,28 @@ User: Check system info
|
|
|
10163
10214
|
</bash>
|
|
10164
10215
|
|
|
10165
10216
|
</examples>
|
|
10217
|
+
`;
|
|
10218
|
+
googleSearchToolDefinition = `
|
|
10219
|
+
## gemini_google_search (Gemini Built-in)
|
|
10220
|
+
Description: Web search powered by Google. This is a built-in Gemini capability that automatically searches the web when the model needs current information. The model decides when to search and integrates results directly into its response with source citations.
|
|
10221
|
+
|
|
10222
|
+
This tool is invoked automatically by the model \u2014 you do NOT need to use XML tool calls for it. Simply ask questions that require up-to-date or real-world information and the model will search the web as needed.
|
|
10223
|
+
|
|
10224
|
+
Capabilities:
|
|
10225
|
+
- Real-time web search with grounded citations
|
|
10226
|
+
- Automatic query generation and result synthesis
|
|
10227
|
+
- Source attribution with URLs
|
|
10228
|
+
`;
|
|
10229
|
+
urlContextToolDefinition = `
|
|
10230
|
+
## gemini_url_context (Gemini Built-in)
|
|
10231
|
+
Description: URL content reader powered by Google. This is a built-in Gemini capability that automatically fetches and analyzes the content of URLs mentioned in the conversation. When you include URLs in your message, the model can read and understand their content.
|
|
10232
|
+
|
|
10233
|
+
This tool is invoked automatically by the model \u2014 you do NOT need to use XML tool calls for it. Simply include URLs in your message and the model will fetch and analyze their content.
|
|
10234
|
+
|
|
10235
|
+
Capabilities:
|
|
10236
|
+
- Fetch and read web page content from URLs in the prompt
|
|
10237
|
+
- Supports up to 20 URLs per request
|
|
10238
|
+
- Processes HTML content (does not execute JavaScript)
|
|
10166
10239
|
`;
|
|
10167
10240
|
searchDescription = "Search code in the repository. Free-form questions are accepted, but Elasticsearch-style keyword queries work best. Use this tool first for any code-related questions.";
|
|
10168
10241
|
queryDescription = "Search code using ast-grep structural pattern matching. Use this tool to find specific code structures like functions, classes, or methods.";
|
|
@@ -55778,6 +55851,7 @@ var require_pattern = __commonJS({
|
|
|
55778
55851
|
"use strict";
|
|
55779
55852
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
55780
55853
|
var code_1 = require_code2();
|
|
55854
|
+
var util_1 = require_util3();
|
|
55781
55855
|
var codegen_1 = require_codegen();
|
|
55782
55856
|
var error = {
|
|
55783
55857
|
message: ({ schemaCode }) => (0, codegen_1.str)`must match pattern "${schemaCode}"`,
|
|
@@ -55790,10 +55864,18 @@ var require_pattern = __commonJS({
|
|
|
55790
55864
|
$data: true,
|
|
55791
55865
|
error,
|
|
55792
55866
|
code(cxt) {
|
|
55793
|
-
const { data, $data, schema, schemaCode, it } = cxt;
|
|
55867
|
+
const { gen, data, $data, schema, schemaCode, it } = cxt;
|
|
55794
55868
|
const u = it.opts.unicodeRegExp ? "u" : "";
|
|
55795
|
-
|
|
55796
|
-
|
|
55869
|
+
if ($data) {
|
|
55870
|
+
const { regExp } = it.opts.code;
|
|
55871
|
+
const regExpCode = regExp.code === "new RegExp" ? (0, codegen_1._)`new RegExp` : (0, util_1.useFunc)(gen, regExp);
|
|
55872
|
+
const valid = gen.let("valid");
|
|
55873
|
+
gen.try(() => gen.assign(valid, (0, codegen_1._)`${regExpCode}(${schemaCode}, ${u}).test(${data})`), () => gen.assign(valid, false));
|
|
55874
|
+
cxt.fail$data((0, codegen_1._)`!${valid}`);
|
|
55875
|
+
} else {
|
|
55876
|
+
const regExp = (0, code_1.usePattern)(cxt, schema);
|
|
55877
|
+
cxt.fail$data((0, codegen_1._)`!${regExp}.test(${data})`);
|
|
55878
|
+
}
|
|
55797
55879
|
}
|
|
55798
55880
|
};
|
|
55799
55881
|
exports2.default = def;
|
|
@@ -59411,7 +59493,13 @@ var init_config = __esm({
|
|
|
59411
59493
|
__filename4 = fileURLToPath6(import.meta.url);
|
|
59412
59494
|
__dirname4 = dirname3(__filename4);
|
|
59413
59495
|
DEFAULT_TIMEOUT = 3e4;
|
|
59414
|
-
MAX_TIMEOUT =
|
|
59496
|
+
MAX_TIMEOUT = (() => {
|
|
59497
|
+
if (process.env.MCP_MAX_TIMEOUT) {
|
|
59498
|
+
const parsed = parseInt(process.env.MCP_MAX_TIMEOUT, 10);
|
|
59499
|
+
if (!isNaN(parsed) && parsed >= 3e4 && parsed <= 72e5) return parsed;
|
|
59500
|
+
}
|
|
59501
|
+
return 18e5;
|
|
59502
|
+
})();
|
|
59415
59503
|
DEFAULT_CONFIG = {
|
|
59416
59504
|
mcpServers: {
|
|
59417
59505
|
// Example probe server configuration
|
|
@@ -70516,6 +70604,7 @@ var init_ProbeAgent = __esm({
|
|
|
70516
70604
|
this.fallbackManager = null;
|
|
70517
70605
|
this.engine = null;
|
|
70518
70606
|
this.initializeModel();
|
|
70607
|
+
this._geminiToolsEnabled = this._initializeGeminiBuiltinTools();
|
|
70519
70608
|
}
|
|
70520
70609
|
/**
|
|
70521
70610
|
* Parse allowedTools configuration
|
|
@@ -71248,6 +71337,12 @@ var init_ProbeAgent = __esm({
|
|
|
71248
71337
|
model: provider(model),
|
|
71249
71338
|
abortSignal: controller.signal
|
|
71250
71339
|
};
|
|
71340
|
+
if (config.provider !== "google" && fallbackOptions.tools) {
|
|
71341
|
+
delete fallbackOptions.tools;
|
|
71342
|
+
if (this.debug) {
|
|
71343
|
+
console.error(`[DEBUG] Stripped Gemini built-in tools for fallback to ${config.provider} provider`);
|
|
71344
|
+
}
|
|
71345
|
+
}
|
|
71251
71346
|
const providerRetryManager = new RetryManager({
|
|
71252
71347
|
maxRetries: config.maxRetries ?? this.retryConfig.maxRetries ?? 3,
|
|
71253
71348
|
initialDelay: this.retryConfig.initialDelay ?? 1e3,
|
|
@@ -71351,6 +71446,69 @@ var init_ProbeAgent = __esm({
|
|
|
71351
71446
|
console.log(`Using Google API with model: ${this.model}${apiUrl ? ` (URL: ${apiUrl})` : ""}`);
|
|
71352
71447
|
}
|
|
71353
71448
|
}
|
|
71449
|
+
/**
|
|
71450
|
+
* Initialize Gemini built-in tools (gemini_google_search, gemini_url_context).
|
|
71451
|
+
* These are provider-defined tools that execute server-side on Google's infrastructure.
|
|
71452
|
+
* They are only available when the provider is Google Gemini.
|
|
71453
|
+
* @returns {{ googleSearch: boolean, urlContext: boolean }} Which tools were enabled
|
|
71454
|
+
* @private
|
|
71455
|
+
*/
|
|
71456
|
+
_initializeGeminiBuiltinTools() {
|
|
71457
|
+
const isToolAllowed = (toolName) => this.allowedTools.isEnabled(toolName);
|
|
71458
|
+
const result = { googleSearch: false, urlContext: false };
|
|
71459
|
+
if (this.apiType !== "google") {
|
|
71460
|
+
if (isToolAllowed("gemini_google_search") || isToolAllowed("gemini_url_context")) {
|
|
71461
|
+
if (this.debug) {
|
|
71462
|
+
console.error(`[DEBUG] Gemini built-in tools (gemini_google_search, gemini_url_context) are not available: provider is '${this.apiType}', not 'google'. These tools require the Google Gemini provider.`);
|
|
71463
|
+
}
|
|
71464
|
+
}
|
|
71465
|
+
return result;
|
|
71466
|
+
}
|
|
71467
|
+
if (!this.provider || !this.provider.tools) {
|
|
71468
|
+
console.error("[ProbeAgent] Gemini built-in tools unavailable: @ai-sdk/google does not expose provider.tools. Upgrade to @ai-sdk/google v2.0.14+.");
|
|
71469
|
+
return result;
|
|
71470
|
+
}
|
|
71471
|
+
if (isToolAllowed("gemini_google_search")) {
|
|
71472
|
+
result.googleSearch = true;
|
|
71473
|
+
if (this.debug) {
|
|
71474
|
+
console.error("[DEBUG] Gemini built-in tool enabled: gemini_google_search");
|
|
71475
|
+
}
|
|
71476
|
+
}
|
|
71477
|
+
if (isToolAllowed("gemini_url_context")) {
|
|
71478
|
+
result.urlContext = true;
|
|
71479
|
+
if (this.debug) {
|
|
71480
|
+
console.error("[DEBUG] Gemini built-in tool enabled: gemini_url_context");
|
|
71481
|
+
}
|
|
71482
|
+
}
|
|
71483
|
+
return result;
|
|
71484
|
+
}
|
|
71485
|
+
/**
|
|
71486
|
+
* Build Gemini provider-defined tools object for streamText().
|
|
71487
|
+
* Returns undefined if no Gemini tools are enabled.
|
|
71488
|
+
* @returns {Object|undefined}
|
|
71489
|
+
* @private
|
|
71490
|
+
*/
|
|
71491
|
+
_buildGeminiProviderTools() {
|
|
71492
|
+
if (this.apiType !== "google" || !this._geminiToolsEnabled) {
|
|
71493
|
+
return void 0;
|
|
71494
|
+
}
|
|
71495
|
+
const { googleSearch, urlContext } = this._geminiToolsEnabled;
|
|
71496
|
+
if (!googleSearch && !urlContext) {
|
|
71497
|
+
return void 0;
|
|
71498
|
+
}
|
|
71499
|
+
if (!this.provider || !this.provider.tools) {
|
|
71500
|
+
return void 0;
|
|
71501
|
+
}
|
|
71502
|
+
const tools2 = {};
|
|
71503
|
+
const providerTools = this.provider.tools;
|
|
71504
|
+
if (googleSearch && providerTools.googleSearch) {
|
|
71505
|
+
tools2.google_search = providerTools.googleSearch({});
|
|
71506
|
+
}
|
|
71507
|
+
if (urlContext && providerTools.urlContext) {
|
|
71508
|
+
tools2.url_context = providerTools.urlContext({});
|
|
71509
|
+
}
|
|
71510
|
+
return Object.keys(tools2).length > 0 ? tools2 : void 0;
|
|
71511
|
+
}
|
|
71354
71512
|
/**
|
|
71355
71513
|
* Initialize AWS Bedrock model
|
|
71356
71514
|
*/
|
|
@@ -72129,16 +72287,22 @@ Workspace: ${this.allowedFolders.join(", ")}`;
|
|
|
72129
72287
|
toolDefinitions += `${taskToolDefinition}
|
|
72130
72288
|
`;
|
|
72131
72289
|
}
|
|
72132
|
-
|
|
72133
|
-
toolDefinitions += `${attemptCompletionToolDefinition}
|
|
72290
|
+
toolDefinitions += `${attemptCompletionToolDefinition}
|
|
72134
72291
|
`;
|
|
72135
|
-
}
|
|
72136
72292
|
if (this.enableDelegate && isToolAllowed("delegate")) {
|
|
72137
72293
|
toolDefinitions += `${delegateToolDefinition}
|
|
72138
72294
|
`;
|
|
72139
72295
|
}
|
|
72140
72296
|
if (isToolAllowed("analyze_all")) {
|
|
72141
72297
|
toolDefinitions += `${analyzeAllToolDefinition}
|
|
72298
|
+
`;
|
|
72299
|
+
}
|
|
72300
|
+
if (this._geminiToolsEnabled?.googleSearch && isToolAllowed("gemini_google_search")) {
|
|
72301
|
+
toolDefinitions += `${googleSearchToolDefinition}
|
|
72302
|
+
`;
|
|
72303
|
+
}
|
|
72304
|
+
if (this._geminiToolsEnabled?.urlContext && isToolAllowed("gemini_url_context")) {
|
|
72305
|
+
toolDefinitions += `${urlContextToolDefinition}
|
|
72142
72306
|
`;
|
|
72143
72307
|
}
|
|
72144
72308
|
let toolExamples = "";
|
|
@@ -72215,6 +72379,12 @@ The configuration is loaded from src/config.js lines 15-25 which contains the da
|
|
|
72215
72379
|
availableToolsList += "- attempt_completion: Finalize the task and provide the result to the user.\n";
|
|
72216
72380
|
availableToolsList += "- attempt_complete: Quick completion using previous response (shorthand).\n";
|
|
72217
72381
|
}
|
|
72382
|
+
if (this._geminiToolsEnabled?.googleSearch && isToolAllowed("gemini_google_search")) {
|
|
72383
|
+
availableToolsList += "- gemini_google_search: (auto) Web search via Google \u2014 invoked automatically by the model when it needs current information.\n";
|
|
72384
|
+
}
|
|
72385
|
+
if (this._geminiToolsEnabled?.urlContext && isToolAllowed("gemini_url_context")) {
|
|
72386
|
+
availableToolsList += "- gemini_url_context: (auto) URL content reader via Google \u2014 automatically fetches and reads URLs mentioned in the conversation.\n";
|
|
72387
|
+
}
|
|
72218
72388
|
let xmlToolGuidelines = `
|
|
72219
72389
|
# Tool Use Formatting
|
|
72220
72390
|
|
|
@@ -72665,12 +72835,17 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
72665
72835
|
try {
|
|
72666
72836
|
const executeAIRequest = async () => {
|
|
72667
72837
|
const messagesForAI = this.prepareMessagesWithImages(currentMessages);
|
|
72668
|
-
const
|
|
72838
|
+
const streamOptions = {
|
|
72669
72839
|
model: this.provider ? this.provider(this.model) : this.model,
|
|
72670
72840
|
messages: messagesForAI,
|
|
72671
72841
|
maxTokens: maxResponseTokens,
|
|
72672
72842
|
temperature: 0.3
|
|
72673
|
-
}
|
|
72843
|
+
};
|
|
72844
|
+
const geminiProviderTools = this._buildGeminiProviderTools();
|
|
72845
|
+
if (geminiProviderTools) {
|
|
72846
|
+
streamOptions.tools = geminiProviderTools;
|
|
72847
|
+
}
|
|
72848
|
+
const result = await this.streamTextWithRetryAndFallback(streamOptions);
|
|
72674
72849
|
const usagePromise = result.usage;
|
|
72675
72850
|
for await (const delta of result.textStream) {
|
|
72676
72851
|
assistantResponseContent += delta;
|
|
@@ -73060,6 +73235,10 @@ ${errorXml}
|
|
|
73060
73235
|
}
|
|
73061
73236
|
currentMessages.push({ role: "assistant", content: assistantResponseContent });
|
|
73062
73237
|
let toolResultContent = typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult, null, 2);
|
|
73238
|
+
if (this.workspaceRoot && toolResultContent) {
|
|
73239
|
+
const wsPrefix = this.workspaceRoot.endsWith(sep5) ? this.workspaceRoot : this.workspaceRoot + sep5;
|
|
73240
|
+
toolResultContent = toolResultContent.split(wsPrefix).join("");
|
|
73241
|
+
}
|
|
73063
73242
|
try {
|
|
73064
73243
|
const truncateResult = await truncateIfNeeded(toolResultContent, this.tokenCounter, this.sessionId, this.maxOutputTokens);
|
|
73065
73244
|
if (truncateResult.truncated) {
|
|
@@ -15,7 +15,13 @@ const __dirname = dirname(__filename);
|
|
|
15
15
|
* Timeout configuration constants
|
|
16
16
|
*/
|
|
17
17
|
export const DEFAULT_TIMEOUT = 30000; // 30 seconds
|
|
18
|
-
export const MAX_TIMEOUT =
|
|
18
|
+
export const MAX_TIMEOUT = (() => {
|
|
19
|
+
if (process.env.MCP_MAX_TIMEOUT) {
|
|
20
|
+
const parsed = parseInt(process.env.MCP_MAX_TIMEOUT, 10);
|
|
21
|
+
if (!isNaN(parsed) && parsed >= 30000 && parsed <= 7200000) return parsed;
|
|
22
|
+
}
|
|
23
|
+
return 1800000; // 30 minutes default - workflow tools (code checkouts, AI exploration) need time
|
|
24
|
+
})();
|
|
19
25
|
|
|
20
26
|
/**
|
|
21
27
|
* Validate and normalize a timeout value
|
|
@@ -23,7 +23,8 @@ export const taskItemSchema = z.object({
|
|
|
23
23
|
*/
|
|
24
24
|
export const taskSchema = z.object({
|
|
25
25
|
action: z.enum(['create', 'update', 'complete', 'delete', 'list']),
|
|
26
|
-
|
|
26
|
+
// Accept both array and JSON string (AI models sometimes serialize as string)
|
|
27
|
+
tasks: z.union([z.array(z.union([z.string(), taskItemSchema])), z.string()]).optional(),
|
|
27
28
|
id: z.string().optional(),
|
|
28
29
|
title: z.string().optional(),
|
|
29
30
|
description: z.string().optional(),
|
|
@@ -142,6 +143,25 @@ SKIP TASKS for single-goal requests, even if they require multiple searches:
|
|
|
142
143
|
**Key insight**: Multiple *internal steps* (search, read, analyze) are NOT the same as multiple *goals*.
|
|
143
144
|
A single investigation with many steps is still ONE task, not many.
|
|
144
145
|
|
|
146
|
+
## Task Granularity
|
|
147
|
+
|
|
148
|
+
Tasks represent LOGICAL UNITS OF WORK, not individual files or steps:
|
|
149
|
+
- "Fix 8 similar test files" → ONE task (same type of fix across files)
|
|
150
|
+
- "Update API + tests + docs" → THREE tasks (different types of work)
|
|
151
|
+
- "Implement feature in 5 files" → ONE task (single feature)
|
|
152
|
+
|
|
153
|
+
**Rule of thumb**: If you're creating more than 3-4 tasks, you're probably too granular.
|
|
154
|
+
|
|
155
|
+
**Anti-patterns to avoid**:
|
|
156
|
+
- One task per file ❌
|
|
157
|
+
- One task per function ❌
|
|
158
|
+
- One task per repository (when same type of work) ❌
|
|
159
|
+
|
|
160
|
+
**Good patterns**:
|
|
161
|
+
- One task per distinct deliverable ✓
|
|
162
|
+
- One task per phase (implement, test, document) ✓
|
|
163
|
+
- One task per different type of work ✓
|
|
164
|
+
|
|
145
165
|
MODIFY TASKS when (during execution):
|
|
146
166
|
- You discover the problem is more complex than expected → Add new tasks
|
|
147
167
|
- A single task covers too much scope → Split into smaller tasks
|
|
@@ -314,7 +334,17 @@ export function createTaskTool(options = {}) {
|
|
|
314
334
|
return `Error: Invalid task parameters - ${validation.error.message}`;
|
|
315
335
|
}
|
|
316
336
|
|
|
317
|
-
const { action, tasks, id, title, description, status, priority, dependencies, after } = validation.data;
|
|
337
|
+
const { action, tasks: rawTasks, id, title, description, status, priority, dependencies, after } = validation.data;
|
|
338
|
+
|
|
339
|
+
// Parse tasks if passed as JSON string (common AI model behavior)
|
|
340
|
+
let tasks = rawTasks;
|
|
341
|
+
if (typeof rawTasks === 'string') {
|
|
342
|
+
try {
|
|
343
|
+
tasks = JSON.parse(rawTasks);
|
|
344
|
+
} catch (e) {
|
|
345
|
+
return `Error: Invalid tasks JSON - ${e.message}`;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
318
348
|
|
|
319
349
|
switch (action) {
|
|
320
350
|
case 'create': {
|
package/build/agent/tools.js
CHANGED
|
@@ -27,6 +27,8 @@ import {
|
|
|
27
27
|
bashToolDefinition,
|
|
28
28
|
editToolDefinition,
|
|
29
29
|
createToolDefinition,
|
|
30
|
+
googleSearchToolDefinition,
|
|
31
|
+
urlContextToolDefinition,
|
|
30
32
|
parseXmlToolCall
|
|
31
33
|
} from '../index.js';
|
|
32
34
|
import { randomUUID } from 'crypto';
|
|
@@ -108,6 +110,8 @@ export {
|
|
|
108
110
|
editToolDefinition,
|
|
109
111
|
createToolDefinition,
|
|
110
112
|
attemptCompletionToolDefinition,
|
|
113
|
+
googleSearchToolDefinition,
|
|
114
|
+
urlContextToolDefinition,
|
|
111
115
|
parseXmlToolCall
|
|
112
116
|
};
|
|
113
117
|
|
package/build/index.js
CHANGED
|
@@ -35,6 +35,8 @@ import {
|
|
|
35
35
|
analyzeAllToolDefinition,
|
|
36
36
|
attemptCompletionToolDefinition,
|
|
37
37
|
bashToolDefinition,
|
|
38
|
+
googleSearchToolDefinition,
|
|
39
|
+
urlContextToolDefinition,
|
|
38
40
|
parseXmlToolCall
|
|
39
41
|
} from './tools/common.js';
|
|
40
42
|
import {
|
|
@@ -114,6 +116,8 @@ export {
|
|
|
114
116
|
bashToolDefinition,
|
|
115
117
|
editToolDefinition,
|
|
116
118
|
createToolDefinition,
|
|
119
|
+
googleSearchToolDefinition,
|
|
120
|
+
urlContextToolDefinition,
|
|
117
121
|
// Export parser function
|
|
118
122
|
parseXmlToolCall,
|
|
119
123
|
// Export task management
|