@probelabs/probe 0.6.0-rc295 → 0.6.0-rc296
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 +7 -0
- package/bin/binaries/{probe-v0.6.0-rc295-aarch64-apple-darwin.tar.gz → probe-v0.6.0-rc296-aarch64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc295-aarch64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc296-aarch64-unknown-linux-musl.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc295-x86_64-apple-darwin.tar.gz → probe-v0.6.0-rc296-x86_64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc295-x86_64-pc-windows-msvc.zip → probe-v0.6.0-rc296-x86_64-pc-windows-msvc.zip} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc295-x86_64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc296-x86_64-unknown-linux-musl.tar.gz} +0 -0
- package/build/agent/ProbeAgent.d.ts +8 -2
- package/build/agent/ProbeAgent.js +683 -10
- package/build/agent/mcp/client.js +81 -4
- package/build/agent/mcp/xmlBridge.js +11 -0
- package/build/agent/otelLogBridge.js +184 -0
- package/build/agent/simpleTelemetry.js +8 -0
- package/build/delegate.js +75 -6
- package/build/index.js +6 -2
- package/build/tools/common.js +84 -11
- package/build/tools/vercel.js +78 -18
- package/cjs/agent/ProbeAgent.cjs +858 -32
- package/cjs/agent/simpleTelemetry.cjs +112 -0
- package/cjs/index.cjs +970 -32
- package/index.d.ts +26 -0
- package/package.json +1 -1
- package/src/agent/ProbeAgent.d.ts +8 -2
- package/src/agent/ProbeAgent.js +683 -10
- package/src/agent/mcp/client.js +81 -4
- package/src/agent/mcp/xmlBridge.js +11 -0
- package/src/agent/otelLogBridge.js +184 -0
- package/src/agent/simpleTelemetry.js +8 -0
- package/src/delegate.js +75 -6
- package/src/index.js +6 -2
- package/src/tools/common.js +84 -11
- package/src/tools/vercel.js +78 -18
package/build/tools/vercel.js
CHANGED
|
@@ -254,6 +254,10 @@ function buildSearchDelegateTask({ searchQuery, searchPath, exact, language, all
|
|
|
254
254
|
'- Use exact=true when searching for a KNOWN symbol name (function, type, variable, struct).',
|
|
255
255
|
'- exact=true matches the literal string only — no stemming, no splitting.',
|
|
256
256
|
'- This is ideal for precise lookups: exact=true "ForwardMessage", exact=true "SessionLimiter", exact=true "ThrottleRetryLimit".',
|
|
257
|
+
'- IMPORTANT: Use exact=true when searching for strings containing punctuation, quotes, or empty values.',
|
|
258
|
+
' Default BM25 search strips punctuation and treats quoted empty strings as noise.',
|
|
259
|
+
' Example: searching for \'description: ""\' with exact=false will NOT find empty description fields — it just matches "description".',
|
|
260
|
+
' Use exact=true for literal patterns like \'description: ""\', \'value: \\\'\\\'\', or any YAML/config field with specific punctuation.',
|
|
257
261
|
'- Do NOT use exact=true for exploratory/conceptual queries — use the default for those.',
|
|
258
262
|
'',
|
|
259
263
|
'Combining searches with OR:',
|
|
@@ -313,7 +317,13 @@ function buildSearchDelegateTask({ searchQuery, searchPath, exact, language, all
|
|
|
313
317
|
'WHEN TO STOP:',
|
|
314
318
|
'- After you have explored the main concept AND related subsystems.',
|
|
315
319
|
'- Once you have 5-15 targets covering different aspects of the query.',
|
|
316
|
-
'- If you get a "DUPLICATE SEARCH BLOCKED" message,
|
|
320
|
+
'- If you get a "DUPLICATE SEARCH BLOCKED" message, do NOT rephrase the same query — try a FUNDAMENTALLY different approach:',
|
|
321
|
+
' * Switch between exact=true and exact=false',
|
|
322
|
+
' * Search for a broader term and filter results manually',
|
|
323
|
+
' * Use listFiles to browse the directory structure directly',
|
|
324
|
+
' * Look for related/surrounding patterns instead of the exact string',
|
|
325
|
+
'- If 2-3 genuinely different search approaches fail, STOP and report what you tried and why it failed.',
|
|
326
|
+
' Do NOT keep trying variations of the same failing concept.',
|
|
317
327
|
'',
|
|
318
328
|
'Strategy:',
|
|
319
329
|
'1. Analyze the query — identify key concepts, then brainstorm SYNONYMS and alternative terms for each.',
|
|
@@ -371,10 +381,10 @@ export const searchTool = (options = {}) => {
|
|
|
371
381
|
return result;
|
|
372
382
|
};
|
|
373
383
|
|
|
374
|
-
// Track previous non-paginated searches
|
|
375
|
-
const previousSearches = new
|
|
376
|
-
// Track
|
|
377
|
-
|
|
384
|
+
// Track previous non-paginated searches: key → { hadResults: boolean }
|
|
385
|
+
const previousSearches = new Map();
|
|
386
|
+
// Track per-key consecutive block counts (not global, to avoid cross-query pollution)
|
|
387
|
+
const dupBlockCounts = new Map();
|
|
378
388
|
// Track pagination counts per query to cap runaway pagination
|
|
379
389
|
const paginationCounts = new Map();
|
|
380
390
|
const MAX_PAGES_PER_QUERY = 3;
|
|
@@ -444,22 +454,28 @@ export const searchTool = (options = {}) => {
|
|
|
444
454
|
if (!searchDelegate) {
|
|
445
455
|
// Block duplicate non-paginated searches (models sometimes repeat the exact same call)
|
|
446
456
|
// Allow pagination: only nextPage=true is a legitimate repeat of the same query
|
|
447
|
-
//
|
|
448
|
-
|
|
449
|
-
const searchKey = `${searchQuery}::${exact || false}`;
|
|
457
|
+
// Include path in dedup key so same query across different repos is allowed (#520)
|
|
458
|
+
const searchKey = `${searchPath}::${searchQuery}::${exact || false}`;
|
|
450
459
|
if (!nextPage) {
|
|
451
460
|
if (previousSearches.has(searchKey)) {
|
|
452
|
-
|
|
461
|
+
const blockCount = (dupBlockCounts.get(searchKey) || 0) + 1;
|
|
462
|
+
dupBlockCounts.set(searchKey, blockCount);
|
|
453
463
|
if (debug) {
|
|
454
|
-
console.error(`[DEDUP] Blocked duplicate search (${
|
|
464
|
+
console.error(`[DEDUP] Blocked duplicate search (${blockCount}x): "${searchQuery}" (path: "${searchPath}")`);
|
|
455
465
|
}
|
|
456
|
-
if (
|
|
457
|
-
return 'STOP. You have been blocked ' +
|
|
466
|
+
if (blockCount >= 3) {
|
|
467
|
+
return 'STOP. You have been blocked ' + blockCount + ' times for repeating the same search. You MUST provide your final answer NOW with whatever information you have. Do NOT call any more tools.';
|
|
458
468
|
}
|
|
459
|
-
|
|
469
|
+
const prev = previousSearches.get(searchKey);
|
|
470
|
+
if (prev.hadResults) {
|
|
471
|
+
return `DUPLICATE SEARCH BLOCKED (${blockCount}x). You already searched for "${searchQuery}" in this path and found results. Do NOT repeat. Use extract to examine the files you already found, try a COMPLETELY different keyword, or provide your final answer.`;
|
|
472
|
+
}
|
|
473
|
+
const exactHint = exact
|
|
474
|
+
? 'You used exact=true. Try a broader search with exact=false, or use listFiles to browse the directory structure.'
|
|
475
|
+
: 'Try exact=true if you need literal/punctuation matching (e.g. \'description: ""\'), or use listFiles to explore directories, or search for a broader/related term and filter manually.';
|
|
476
|
+
return `DUPLICATE SEARCH BLOCKED (${blockCount}x). You already searched for "${searchQuery}" in this path and got NO results. This term does not appear in the codebase. Do NOT repeat or rephrase — try a FUNDAMENTALLY different approach: ${exactHint} If multiple approaches have failed, provide your final answer with what you know.`;
|
|
460
477
|
}
|
|
461
|
-
previousSearches.
|
|
462
|
-
consecutiveDupBlocks = 0; // Reset on successful new search
|
|
478
|
+
previousSearches.set(searchKey, { hadResults: false });
|
|
463
479
|
paginationCounts.set(searchKey, 0);
|
|
464
480
|
} else {
|
|
465
481
|
// Cap pagination to prevent runaway page-through of broad queries
|
|
@@ -474,6 +490,16 @@ export const searchTool = (options = {}) => {
|
|
|
474
490
|
}
|
|
475
491
|
try {
|
|
476
492
|
const result = maybeAnnotate(await runRawSearch());
|
|
493
|
+
// Track whether this search had results for better dedup messages
|
|
494
|
+
if (typeof result === 'string' && result.includes('No results found')) {
|
|
495
|
+
// Append contextual hint for ticket/issue ID queries
|
|
496
|
+
if (/^[A-Z]+-\d+$/.test(searchQuery.trim()) || /^[A-Z]+-\d+$/.test(searchQuery.replace(/"/g, '').trim())) {
|
|
497
|
+
return result + '\n\n⚠️ Your query looks like a ticket/issue ID (e.g., JIRA-1234). Ticket IDs are rarely present in source code. Search for the technical concepts described in the ticket instead (e.g., function names, error messages, variable names).';
|
|
498
|
+
}
|
|
499
|
+
} else if (typeof result === 'string') {
|
|
500
|
+
const entry = previousSearches.get(searchKey);
|
|
501
|
+
if (entry) entry.hadResults = true;
|
|
502
|
+
}
|
|
477
503
|
// Track files found in search results for staleness detection
|
|
478
504
|
if (options.fileTracker && typeof result === 'string') {
|
|
479
505
|
options.fileTracker.trackFilesFromOutput(result, effectiveSearchCwd).catch(() => {});
|
|
@@ -862,7 +888,11 @@ export const extractTool = (options = {}) => {
|
|
|
862
888
|
* @returns {Object} Configured delegate tool
|
|
863
889
|
*/
|
|
864
890
|
export const delegateTool = (options = {}) => {
|
|
865
|
-
const { debug = false, timeout = 300, cwd, allowedFolders, workspaceRoot, enableBash = false, bashConfig, architectureFileName, enableMcp = false, mcpConfig = null, mcpConfigPath = null, delegationManager = null
|
|
891
|
+
const { debug = false, timeout = 300, cwd, allowedFolders, workspaceRoot, enableBash = false, bashConfig, architectureFileName, enableMcp = false, mcpConfig = null, mcpConfigPath = null, delegationManager = null,
|
|
892
|
+
// Timeout settings inherited from parent agent
|
|
893
|
+
timeoutBehavior, maxOperationTimeout, requestTimeout, gracefulTimeoutBonusSteps,
|
|
894
|
+
negotiatedTimeoutBudget, negotiatedTimeoutMaxRequests, negotiatedTimeoutMaxPerRequest,
|
|
895
|
+
parentOperationStartTime, onSubagentCreated, onSubagentCompleted } = options;
|
|
866
896
|
|
|
867
897
|
return tool({
|
|
868
898
|
name: 'delegate',
|
|
@@ -941,9 +971,32 @@ export const delegateTool = (options = {}) => {
|
|
|
941
971
|
}
|
|
942
972
|
|
|
943
973
|
// Execute delegation - let errors propagate naturally
|
|
974
|
+
// Cap delegate timeout to remaining parent budget (with 10% headroom)
|
|
975
|
+
let effectiveTimeout = timeout;
|
|
976
|
+
if (parentOperationStartTime && maxOperationTimeout) {
|
|
977
|
+
const elapsed = Date.now() - parentOperationStartTime;
|
|
978
|
+
const remaining = maxOperationTimeout - elapsed;
|
|
979
|
+
const budgetCap = Math.max(30, Math.floor(remaining * 0.9 / 1000)); // seconds, min 30s
|
|
980
|
+
if (budgetCap < effectiveTimeout) {
|
|
981
|
+
effectiveTimeout = budgetCap;
|
|
982
|
+
if (debug) {
|
|
983
|
+
console.error(`[DELEGATE] Capping timeout from ${timeout}s to ${effectiveTimeout}s (remaining parent budget: ${Math.floor(remaining/1000)}s)`);
|
|
984
|
+
}
|
|
985
|
+
if (tracer) {
|
|
986
|
+
tracer.addEvent('delegation.budget_capped', {
|
|
987
|
+
'delegation.original_timeout_s': timeout,
|
|
988
|
+
'delegation.effective_timeout_s': effectiveTimeout,
|
|
989
|
+
'delegation.parent_elapsed_ms': elapsed,
|
|
990
|
+
'delegation.parent_remaining_ms': remaining,
|
|
991
|
+
'delegation.parent_session_id': parentSessionId,
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
|
|
944
997
|
const result = await delegate({
|
|
945
998
|
task,
|
|
946
|
-
timeout,
|
|
999
|
+
timeout: effectiveTimeout,
|
|
947
1000
|
debug,
|
|
948
1001
|
currentIteration: currentIteration || 0,
|
|
949
1002
|
maxIterations: maxIterations || 30,
|
|
@@ -961,7 +1014,14 @@ export const delegateTool = (options = {}) => {
|
|
|
961
1014
|
mcpConfig,
|
|
962
1015
|
mcpConfigPath,
|
|
963
1016
|
delegationManager, // Per-instance delegation limits
|
|
964
|
-
parentAbortSignal
|
|
1017
|
+
parentAbortSignal,
|
|
1018
|
+
// Inherit timeout settings for subagent
|
|
1019
|
+
timeoutBehavior,
|
|
1020
|
+
requestTimeout,
|
|
1021
|
+
gracefulTimeoutBonusSteps,
|
|
1022
|
+
// Subagent lifecycle callbacks for graceful stop coordination
|
|
1023
|
+
onSubagentCreated,
|
|
1024
|
+
onSubagentCompleted,
|
|
965
1025
|
});
|
|
966
1026
|
|
|
967
1027
|
return result;
|