@probelabs/probe 0.6.0-rc277 → 0.6.0-rc279
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-rc279-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc279-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc279-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc279-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/{probe-v0.6.0-rc277-x86_64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc279-x86_64-unknown-linux-musl.tar.gz} +0 -0
- package/build/agent/ProbeAgent.js +63 -11
- package/build/agent/index.js +129 -33
- package/build/agent/shared/prompts.js +30 -8
- package/build/delegate.js +40 -11
- package/build/tools/analyzeAll.js +8 -4
- package/build/tools/vercel.js +7 -4
- package/cjs/agent/ProbeAgent.cjs +132 -34
- package/cjs/index.cjs +129 -33
- package/package.json +1 -1
- package/src/agent/ProbeAgent.js +63 -11
- package/src/agent/shared/prompts.js +30 -8
- package/src/delegate.js +40 -11
- package/src/tools/analyzeAll.js +8 -4
- package/src/tools/vercel.js +7 -4
- package/bin/binaries/probe-v0.6.0-rc277-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc277-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc277-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc277-x86_64-pc-windows-msvc.zip +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -104,7 +104,6 @@ import {
|
|
|
104
104
|
TaskManager,
|
|
105
105
|
createTaskTool,
|
|
106
106
|
taskSystemPrompt,
|
|
107
|
-
taskGuidancePrompt,
|
|
108
107
|
createTaskCompletionBlockedMessage
|
|
109
108
|
} from './tasks/index.js';
|
|
110
109
|
import { z } from 'zod';
|
|
@@ -126,6 +125,27 @@ const MAX_HISTORY_MESSAGES = 100;
|
|
|
126
125
|
// Maximum image file size (20MB) to prevent OOM attacks
|
|
127
126
|
const MAX_IMAGE_FILE_SIZE = 20 * 1024 * 1024;
|
|
128
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Truncate a string for debug logging, showing first and last portion.
|
|
130
|
+
*/
|
|
131
|
+
export function debugTruncate(s, limit = 200) {
|
|
132
|
+
if (s.length <= limit) return s;
|
|
133
|
+
const half = Math.floor(limit / 2);
|
|
134
|
+
return s.substring(0, half) + ` ... [${s.length} chars] ... ` + s.substring(s.length - half);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Log tool results details for debug output.
|
|
139
|
+
*/
|
|
140
|
+
export function debugLogToolResults(toolResults) {
|
|
141
|
+
if (!toolResults || toolResults.length === 0) return;
|
|
142
|
+
for (const tr of toolResults) {
|
|
143
|
+
const argsStr = JSON.stringify(tr.args || {});
|
|
144
|
+
const resultStr = typeof tr.result === 'string' ? tr.result : JSON.stringify(tr.result || '');
|
|
145
|
+
console.log(`[DEBUG] tool: ${tr.toolName} | args: ${debugTruncate(argsStr)} | result: ${debugTruncate(resultStr)}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
129
149
|
/**
|
|
130
150
|
* ProbeAgent class to handle AI interactions with code search capabilities
|
|
131
151
|
*/
|
|
@@ -194,6 +214,7 @@ export class ProbeAgent {
|
|
|
194
214
|
this.enableExecutePlan = !!options.enableExecutePlan;
|
|
195
215
|
this.debug = options.debug || process.env.DEBUG === '1';
|
|
196
216
|
this.cancelled = false;
|
|
217
|
+
this._abortController = new AbortController();
|
|
197
218
|
this.tracer = options.tracer || null;
|
|
198
219
|
this.outline = !!options.outline;
|
|
199
220
|
this.searchDelegate = options.searchDelegate !== undefined ? !!options.searchDelegate : true;
|
|
@@ -793,6 +814,7 @@ export class ProbeAgent {
|
|
|
793
814
|
searchDelegateProvider: this.searchDelegateProvider,
|
|
794
815
|
searchDelegateModel: this.searchDelegateModel,
|
|
795
816
|
delegationManager: this.delegationManager, // Per-instance delegation limits
|
|
817
|
+
parentAbortSignal: this._abortController.signal, // Propagate cancellation to delegations
|
|
796
818
|
outputBuffer: this._outputBuffer,
|
|
797
819
|
concurrencyLimiter: this.concurrencyLimiter, // Global AI concurrency limiter
|
|
798
820
|
isToolAllowed,
|
|
@@ -1363,6 +1385,19 @@ export class ProbeAgent {
|
|
|
1363
1385
|
const controller = new AbortController();
|
|
1364
1386
|
const timeoutState = { timeoutId: null };
|
|
1365
1387
|
|
|
1388
|
+
// Link agent-level abort to this operation's controller
|
|
1389
|
+
// so that cancel() / cleanup() stops the current streamText call
|
|
1390
|
+
if (this._abortController.signal.aborted) {
|
|
1391
|
+
controller.abort();
|
|
1392
|
+
} else {
|
|
1393
|
+
const onAgentAbort = () => controller.abort();
|
|
1394
|
+
this._abortController.signal.addEventListener('abort', onAgentAbort, { once: true });
|
|
1395
|
+
// Clean up listener when this controller aborts (from any source)
|
|
1396
|
+
controller.signal.addEventListener('abort', () => {
|
|
1397
|
+
this._abortController.signal.removeEventListener('abort', onAgentAbort);
|
|
1398
|
+
}, { once: true });
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1366
1401
|
// Set up overall operation timeout (default 5 minutes)
|
|
1367
1402
|
if (this.maxOperationTimeout && this.maxOperationTimeout > 0) {
|
|
1368
1403
|
timeoutState.timeoutId = setTimeout(() => {
|
|
@@ -1730,7 +1765,8 @@ export class ProbeAgent {
|
|
|
1730
1765
|
allowEdit: this.allowEdit,
|
|
1731
1766
|
allowedTools: allowedToolsForDelegate,
|
|
1732
1767
|
debug: this.debug,
|
|
1733
|
-
tracer: this.tracer
|
|
1768
|
+
tracer: this.tracer,
|
|
1769
|
+
parentAbortSignal: this._abortController.signal
|
|
1734
1770
|
};
|
|
1735
1771
|
|
|
1736
1772
|
if (this.debug) {
|
|
@@ -3153,14 +3189,6 @@ Follow these instructions carefully:
|
|
|
3153
3189
|
// Create user message with optional image support
|
|
3154
3190
|
let userMessage = { role: 'user', content: message.trim() };
|
|
3155
3191
|
|
|
3156
|
-
// START CHECKPOINT: Inject task guidance if tasks are enabled
|
|
3157
|
-
if (this.enableTasks) {
|
|
3158
|
-
userMessage.content = userMessage.content + '\n\n' + taskGuidancePrompt;
|
|
3159
|
-
if (this.debug) {
|
|
3160
|
-
console.log('[DEBUG] Task guidance injected into user message');
|
|
3161
|
-
}
|
|
3162
|
-
}
|
|
3163
|
-
|
|
3164
3192
|
// If schema is provided, prepend JSON format requirement to user message
|
|
3165
3193
|
if (options.schema && !options._schemaFormatted) {
|
|
3166
3194
|
const schemaInstructions = generateSchemaInstructions(options.schema, { debug: this.debug });
|
|
@@ -3378,6 +3406,11 @@ Follow these instructions carefully:
|
|
|
3378
3406
|
completionAttempted = true;
|
|
3379
3407
|
}, toolContext);
|
|
3380
3408
|
|
|
3409
|
+
if (this.debug) {
|
|
3410
|
+
const toolNames = Object.keys(tools);
|
|
3411
|
+
console.log(`[DEBUG] Agent tools registered (${toolNames.length}): ${toolNames.join(', ')}`);
|
|
3412
|
+
}
|
|
3413
|
+
|
|
3381
3414
|
let maxResponseTokens = this.maxResponseTokens;
|
|
3382
3415
|
if (!maxResponseTokens) {
|
|
3383
3416
|
maxResponseTokens = 4000;
|
|
@@ -3427,6 +3460,7 @@ Follow these instructions carefully:
|
|
|
3427
3460
|
|
|
3428
3461
|
if (this.debug) {
|
|
3429
3462
|
console.log(`[DEBUG] Step ${currentIteration}/${maxIterations} finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
3463
|
+
debugLogToolResults(toolResults);
|
|
3430
3464
|
}
|
|
3431
3465
|
}
|
|
3432
3466
|
};
|
|
@@ -3638,6 +3672,7 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
3638
3672
|
}
|
|
3639
3673
|
if (this.debug) {
|
|
3640
3674
|
console.log(`[DEBUG] Completion prompt step finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
3675
|
+
debugLogToolResults(toolResults);
|
|
3641
3676
|
}
|
|
3642
3677
|
}
|
|
3643
3678
|
};
|
|
@@ -4554,6 +4589,11 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
4554
4589
|
* Clean up resources (including MCP connections)
|
|
4555
4590
|
*/
|
|
4556
4591
|
async cleanup() {
|
|
4592
|
+
// Abort any in-flight operations (delegations, streaming, etc.)
|
|
4593
|
+
if (!this._abortController.signal.aborted) {
|
|
4594
|
+
this._abortController.abort();
|
|
4595
|
+
}
|
|
4596
|
+
|
|
4557
4597
|
// Clean up MCP bridge
|
|
4558
4598
|
if (this.mcpBridge) {
|
|
4559
4599
|
try {
|
|
@@ -4583,12 +4623,24 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
4583
4623
|
}
|
|
4584
4624
|
|
|
4585
4625
|
/**
|
|
4586
|
-
* Cancel the current request
|
|
4626
|
+
* Cancel the current request and all in-flight delegations.
|
|
4627
|
+
* Aborts the internal AbortController so streamText, subagents,
|
|
4628
|
+
* and any code checking the signal will stop.
|
|
4587
4629
|
*/
|
|
4588
4630
|
cancel() {
|
|
4589
4631
|
this.cancelled = true;
|
|
4632
|
+
this._abortController.abort();
|
|
4590
4633
|
if (this.debug) {
|
|
4591
4634
|
console.log(`[DEBUG] Agent cancelled for session ${this.sessionId}`);
|
|
4592
4635
|
}
|
|
4593
4636
|
}
|
|
4637
|
+
|
|
4638
|
+
/**
|
|
4639
|
+
* Get the abort signal for this agent.
|
|
4640
|
+
* Delegations and subagents should check this signal.
|
|
4641
|
+
* @returns {AbortSignal}
|
|
4642
|
+
*/
|
|
4643
|
+
get abortSignal() {
|
|
4644
|
+
return this._abortController.signal;
|
|
4645
|
+
}
|
|
4594
4646
|
}
|
package/build/agent/index.js
CHANGED
|
@@ -3862,12 +3862,17 @@ async function delegate({
|
|
|
3862
3862
|
mcpConfigPath = null,
|
|
3863
3863
|
delegationManager = null,
|
|
3864
3864
|
// Optional per-instance manager, falls back to default singleton
|
|
3865
|
-
concurrencyLimiter = null
|
|
3865
|
+
concurrencyLimiter = null,
|
|
3866
3866
|
// Optional global AI concurrency limiter
|
|
3867
|
+
parentAbortSignal = null
|
|
3868
|
+
// Optional AbortSignal from parent to cancel this delegation
|
|
3867
3869
|
}) {
|
|
3868
3870
|
if (!task || typeof task !== "string") {
|
|
3869
3871
|
throw new Error("Task parameter is required and must be a string");
|
|
3870
3872
|
}
|
|
3873
|
+
if (parentAbortSignal?.aborted) {
|
|
3874
|
+
throw new Error("Delegation cancelled: parent operation was aborted");
|
|
3875
|
+
}
|
|
3871
3876
|
const hasExplicitTimeout = Object.prototype.hasOwnProperty.call(arguments?.[0] ?? {}, "timeout");
|
|
3872
3877
|
if (!hasExplicitTimeout) {
|
|
3873
3878
|
const envTimeoutMs = parseInt(process.env.DELEGATION_TIMEOUT_MS || "", 10);
|
|
@@ -3952,12 +3957,37 @@ async function delegate({
|
|
|
3952
3957
|
}
|
|
3953
3958
|
const timeoutPromise = new Promise((_, reject2) => {
|
|
3954
3959
|
timeoutId = setTimeout(() => {
|
|
3960
|
+
subagent.cancel();
|
|
3955
3961
|
reject2(new Error(`Delegation timed out after ${timeout} seconds`));
|
|
3956
3962
|
}, timeout * 1e3);
|
|
3957
3963
|
});
|
|
3964
|
+
let parentAbortHandler;
|
|
3965
|
+
const parentAbortPromise = new Promise((_, reject2) => {
|
|
3966
|
+
if (parentAbortSignal) {
|
|
3967
|
+
if (parentAbortSignal.aborted) {
|
|
3968
|
+
subagent.cancel();
|
|
3969
|
+
reject2(new Error("Delegation cancelled: parent operation was aborted"));
|
|
3970
|
+
return;
|
|
3971
|
+
}
|
|
3972
|
+
parentAbortHandler = () => {
|
|
3973
|
+
subagent.cancel();
|
|
3974
|
+
reject2(new Error("Delegation cancelled: parent operation was aborted"));
|
|
3975
|
+
};
|
|
3976
|
+
parentAbortSignal.addEventListener("abort", parentAbortHandler, { once: true });
|
|
3977
|
+
}
|
|
3978
|
+
});
|
|
3958
3979
|
const answerOptions = schema ? { schema } : void 0;
|
|
3959
3980
|
const answerPromise = answerOptions ? subagent.answer(task, [], answerOptions) : subagent.answer(task);
|
|
3960
|
-
const
|
|
3981
|
+
const racers = [answerPromise, timeoutPromise];
|
|
3982
|
+
if (parentAbortSignal) racers.push(parentAbortPromise);
|
|
3983
|
+
let response;
|
|
3984
|
+
try {
|
|
3985
|
+
response = await Promise.race(racers);
|
|
3986
|
+
} finally {
|
|
3987
|
+
if (parentAbortHandler && parentAbortSignal) {
|
|
3988
|
+
parentAbortSignal.removeEventListener("abort", parentAbortHandler);
|
|
3989
|
+
}
|
|
3990
|
+
}
|
|
3961
3991
|
if (timeoutId !== null) {
|
|
3962
3992
|
clearTimeout(timeoutId);
|
|
3963
3993
|
timeoutId = null;
|
|
@@ -4369,8 +4399,9 @@ Instructions:
|
|
|
4369
4399
|
promptType: "code-researcher",
|
|
4370
4400
|
allowedTools: ["extract"],
|
|
4371
4401
|
maxIterations: 5,
|
|
4372
|
-
delegationManager: options.delegationManager
|
|
4402
|
+
delegationManager: options.delegationManager,
|
|
4373
4403
|
// Per-instance delegation limits
|
|
4404
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
4374
4405
|
// timeout removed - inherit default from delegate (300s)
|
|
4375
4406
|
});
|
|
4376
4407
|
return { chunk, result };
|
|
@@ -4469,8 +4500,9 @@ Organize all findings into clear categories with items listed under each.${compl
|
|
|
4469
4500
|
promptType: "code-researcher",
|
|
4470
4501
|
allowedTools: [],
|
|
4471
4502
|
maxIterations: 5,
|
|
4472
|
-
delegationManager: options.delegationManager
|
|
4503
|
+
delegationManager: options.delegationManager,
|
|
4473
4504
|
// Per-instance delegation limits
|
|
4505
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
4474
4506
|
// timeout removed - inherit default from delegate (300s)
|
|
4475
4507
|
});
|
|
4476
4508
|
return result;
|
|
@@ -4534,8 +4566,9 @@ CRITICAL: Do NOT guess keywords. Actually run searches and see what returns resu
|
|
|
4534
4566
|
promptType: "code-researcher",
|
|
4535
4567
|
// Full tool access for exploration and experimentation
|
|
4536
4568
|
maxIterations: 15,
|
|
4537
|
-
delegationManager: options.delegationManager
|
|
4569
|
+
delegationManager: options.delegationManager,
|
|
4538
4570
|
// Per-instance delegation limits
|
|
4571
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
4539
4572
|
// timeout removed - inherit default from delegate (300s)
|
|
4540
4573
|
});
|
|
4541
4574
|
const plan = parsePlanningResult(stripResultTags(result));
|
|
@@ -4592,8 +4625,9 @@ When done, use the attempt_completion tool with your answer as the result.`;
|
|
|
4592
4625
|
promptType: "code-researcher",
|
|
4593
4626
|
allowedTools: [],
|
|
4594
4627
|
maxIterations: 5,
|
|
4595
|
-
delegationManager: options.delegationManager
|
|
4628
|
+
delegationManager: options.delegationManager,
|
|
4596
4629
|
// Per-instance delegation limits
|
|
4630
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
4597
4631
|
// timeout removed - inherit default from delegate (300s)
|
|
4598
4632
|
});
|
|
4599
4633
|
return stripResultTags(result);
|
|
@@ -9277,7 +9311,8 @@ var init_vercel = __esm({
|
|
|
9277
9311
|
promptType: "code-searcher",
|
|
9278
9312
|
allowedTools: ["search", "extract", "listFiles", "attempt_completion"],
|
|
9279
9313
|
searchDelegate: false,
|
|
9280
|
-
schema: CODE_SEARCH_SCHEMA
|
|
9314
|
+
schema: CODE_SEARCH_SCHEMA,
|
|
9315
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
9281
9316
|
});
|
|
9282
9317
|
const delegateResult = options.tracer?.withSpan ? await options.tracer.withSpan("search.delegate", runDelegation, {
|
|
9283
9318
|
"search.query": searchQuery,
|
|
@@ -9491,7 +9526,7 @@ var init_vercel = __esm({
|
|
|
9491
9526
|
name: "delegate",
|
|
9492
9527
|
description: delegateDescription,
|
|
9493
9528
|
inputSchema: delegateSchema,
|
|
9494
|
-
execute: async ({ task, currentIteration, maxIterations, parentSessionId, path: path9, provider, model, tracer, searchDelegate }) => {
|
|
9529
|
+
execute: async ({ task, currentIteration, maxIterations, parentSessionId, path: path9, provider, model, tracer, searchDelegate, parentAbortSignal }) => {
|
|
9495
9530
|
if (!task || typeof task !== "string") {
|
|
9496
9531
|
throw new Error("Task parameter is required and must be a non-empty string");
|
|
9497
9532
|
}
|
|
@@ -9549,8 +9584,9 @@ var init_vercel = __esm({
|
|
|
9549
9584
|
enableMcp,
|
|
9550
9585
|
mcpConfig,
|
|
9551
9586
|
mcpConfigPath,
|
|
9552
|
-
delegationManager
|
|
9587
|
+
delegationManager,
|
|
9553
9588
|
// Per-instance delegation limits
|
|
9589
|
+
parentAbortSignal
|
|
9554
9590
|
});
|
|
9555
9591
|
return result;
|
|
9556
9592
|
}
|
|
@@ -9588,8 +9624,9 @@ var init_vercel = __esm({
|
|
|
9588
9624
|
provider: options.provider,
|
|
9589
9625
|
model: options.model,
|
|
9590
9626
|
tracer: options.tracer,
|
|
9591
|
-
delegationManager
|
|
9627
|
+
delegationManager,
|
|
9592
9628
|
// Per-instance delegation limits
|
|
9629
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
9593
9630
|
});
|
|
9594
9631
|
return result;
|
|
9595
9632
|
} catch (error) {
|
|
@@ -31932,7 +31969,7 @@ ${taskManager.formatTasksForPrompt()}`;
|
|
|
31932
31969
|
}
|
|
31933
31970
|
};
|
|
31934
31971
|
}
|
|
31935
|
-
var taskItemSchema, taskSchema, taskSystemPrompt
|
|
31972
|
+
var taskItemSchema, taskSchema, taskSystemPrompt;
|
|
31936
31973
|
var init_taskTool = __esm({
|
|
31937
31974
|
"src/agent/tasks/taskTool.js"() {
|
|
31938
31975
|
"use strict";
|
|
@@ -31993,11 +32030,6 @@ Tasks = logical units of work, not files or steps.
|
|
|
31993
32030
|
- Circular dependencies are rejected
|
|
31994
32031
|
- attempt_completion is blocked while tasks remain unresolved
|
|
31995
32032
|
`;
|
|
31996
|
-
taskGuidancePrompt = `Does this request have MULTIPLE DISTINCT GOALS?
|
|
31997
|
-
- "Do A AND B AND C" (multiple goals) \u2192 Create tasks for each goal
|
|
31998
|
-
- "Investigate/explain/find X" (single goal) \u2192 Skip tasks, just answer directly
|
|
31999
|
-
Multiple internal steps for ONE goal = NO tasks needed.
|
|
32000
|
-
If creating tasks, use the task tool with action="create" first.`;
|
|
32001
32033
|
}
|
|
32002
32034
|
});
|
|
32003
32035
|
|
|
@@ -70753,8 +70785,20 @@ If the solution is clear, you can jump to implementation right away. If not, ask
|
|
|
70753
70785
|
- Check imports and existing utilities before creating new helpers \u2014 the project may already have what you need.
|
|
70754
70786
|
|
|
70755
70787
|
# Task Planning
|
|
70756
|
-
|
|
70757
|
-
-
|
|
70788
|
+
When the request has **multiple distinct goals** (e.g. "Fix bug A AND add feature B"), use the task tool to track them:
|
|
70789
|
+
- Call the task tool with action="create" and a tasks array. Each task must have an "id" field.
|
|
70790
|
+
- Update task status to "in_progress" when starting and "completed" when done.
|
|
70791
|
+
- All tasks must be completed or cancelled before calling attempt_completion.
|
|
70792
|
+
- Stay flexible \u2014 add, remove, or reorganize tasks as your understanding changes.
|
|
70793
|
+
|
|
70794
|
+
Do NOT create tasks for single-goal requests, even complex ones. Multiple internal steps for one goal (search, read, analyze, implement) do not need tasks.
|
|
70795
|
+
|
|
70796
|
+
# Discovering Project Commands
|
|
70797
|
+
Before building or testing, determine the project's toolchain:
|
|
70798
|
+
- Check for Makefile, package.json (scripts), Cargo.toml, go.mod, pyproject.toml, or similar
|
|
70799
|
+
- Look for CI config (.github/workflows/, .gitlab-ci.yml) to see what commands CI runs
|
|
70800
|
+
- Read README for build/test instructions if the above are unclear
|
|
70801
|
+
- Common patterns: \`make build\`/\`make test\`, \`npm run build\`/\`npm test\`, \`cargo build\`/\`cargo test\`, \`go build ./...\`/\`go test ./...\`, \`python -m pytest\`
|
|
70758
70802
|
|
|
70759
70803
|
# During Implementation
|
|
70760
70804
|
- Always create a new branch before making changes to the codebase.
|
|
@@ -70765,12 +70809,22 @@ If the solution is clear, you can jump to implementation right away. If not, ask
|
|
|
70765
70809
|
- When editing files, keep edits focused and minimal. For changes spanning more than a few lines, prefer line-targeted editing (start_line/end_line) over text replacement (old_string) \u2014 it constrains scope and prevents accidental removal of adjacent content. Never include unrelated sections in an edit operation.
|
|
70766
70810
|
- After every significant change, verify the project still builds and passes linting. Do not wait until the end to discover breakage.
|
|
70767
70811
|
|
|
70768
|
-
#
|
|
70769
|
-
|
|
70770
|
-
-
|
|
70771
|
-
-
|
|
70772
|
-
-
|
|
70773
|
-
-
|
|
70812
|
+
# Writing Tests
|
|
70813
|
+
Every change must include tests. Before writing them:
|
|
70814
|
+
- Find existing test files for the module you changed \u2014 look in \`tests/\`, \`__tests__/\`, \`*_test.go\`, \`*.test.js\`, \`*.spec.ts\`, or co-located test modules (\`#[cfg(test)]\` in Rust).
|
|
70815
|
+
- Read those tests to understand the project's testing patterns: framework, assertion style, mocking approach, file naming, test organization.
|
|
70816
|
+
- Prefer extending an existing test file over creating a new one when your change is in the same module.
|
|
70817
|
+
- Write tests that cover the main path and important edge cases. Include a failing-input test when relevant.
|
|
70818
|
+
- When fixing a bug, write a failing test first that reproduces the bug, then fix the code to make it pass.
|
|
70819
|
+
|
|
70820
|
+
# Verify Changes
|
|
70821
|
+
Before committing or creating a PR, run through this checklist:
|
|
70822
|
+
1. **Build** \u2014 run the project-appropriate build command (go build, npm run build, cargo build, make, etc.). Fix any compilation errors.
|
|
70823
|
+
2. **Lint & typecheck** \u2014 run linter/formatter if the project has one (eslint, clippy, golangci-lint, etc.). Fix any new warnings.
|
|
70824
|
+
3. **Test** \u2014 run the full test suite (go test ./..., npm test, cargo test, make test, pytest, etc.). Fix any failures, including pre-existing tests you may have broken.
|
|
70825
|
+
4. **Review** \u2014 re-read your diff. Ensure no debug code, no unrelated changes, no secrets, no missing files.
|
|
70826
|
+
|
|
70827
|
+
Do NOT skip verification. Do NOT proceed to PR creation with a broken build or failing tests.
|
|
70774
70828
|
|
|
70775
70829
|
# GitHub Integration
|
|
70776
70830
|
- Use the \`gh\` CLI for all GitHub operations: issues, pull requests, checks, releases.
|
|
@@ -81751,7 +81805,9 @@ __export(ProbeAgent_exports, {
|
|
|
81751
81805
|
ENGINE_ACTIVITY_TIMEOUT_DEFAULT: () => ENGINE_ACTIVITY_TIMEOUT_DEFAULT,
|
|
81752
81806
|
ENGINE_ACTIVITY_TIMEOUT_MAX: () => ENGINE_ACTIVITY_TIMEOUT_MAX,
|
|
81753
81807
|
ENGINE_ACTIVITY_TIMEOUT_MIN: () => ENGINE_ACTIVITY_TIMEOUT_MIN,
|
|
81754
|
-
ProbeAgent: () => ProbeAgent
|
|
81808
|
+
ProbeAgent: () => ProbeAgent,
|
|
81809
|
+
debugLogToolResults: () => debugLogToolResults,
|
|
81810
|
+
debugTruncate: () => debugTruncate
|
|
81755
81811
|
});
|
|
81756
81812
|
import dotenv2 from "dotenv";
|
|
81757
81813
|
import { createAnthropic as createAnthropic2 } from "@ai-sdk/anthropic";
|
|
@@ -81764,6 +81820,19 @@ import { EventEmitter as EventEmitter5 } from "events";
|
|
|
81764
81820
|
import { existsSync as existsSync7 } from "fs";
|
|
81765
81821
|
import { readFile as readFile3, stat, readdir as readdir3 } from "fs/promises";
|
|
81766
81822
|
import { resolve as resolve7, isAbsolute as isAbsolute6, dirname as dirname5, basename, normalize as normalize2, sep as sep5 } from "path";
|
|
81823
|
+
function debugTruncate(s, limit = 200) {
|
|
81824
|
+
if (s.length <= limit) return s;
|
|
81825
|
+
const half = Math.floor(limit / 2);
|
|
81826
|
+
return s.substring(0, half) + ` ... [${s.length} chars] ... ` + s.substring(s.length - half);
|
|
81827
|
+
}
|
|
81828
|
+
function debugLogToolResults(toolResults) {
|
|
81829
|
+
if (!toolResults || toolResults.length === 0) return;
|
|
81830
|
+
for (const tr of toolResults) {
|
|
81831
|
+
const argsStr = JSON.stringify(tr.args || {});
|
|
81832
|
+
const resultStr = typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result || "");
|
|
81833
|
+
console.log(`[DEBUG] tool: ${tr.toolName} | args: ${debugTruncate(argsStr)} | result: ${debugTruncate(resultStr)}`);
|
|
81834
|
+
}
|
|
81835
|
+
}
|
|
81767
81836
|
var ENGINE_ACTIVITY_TIMEOUT_DEFAULT, ENGINE_ACTIVITY_TIMEOUT_MIN, ENGINE_ACTIVITY_TIMEOUT_MAX, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
|
|
81768
81837
|
var init_ProbeAgent = __esm({
|
|
81769
81838
|
"src/agent/ProbeAgent.js"() {
|
|
@@ -81872,6 +81941,7 @@ var init_ProbeAgent = __esm({
|
|
|
81872
81941
|
this.enableExecutePlan = !!options.enableExecutePlan;
|
|
81873
81942
|
this.debug = options.debug || process.env.DEBUG === "1";
|
|
81874
81943
|
this.cancelled = false;
|
|
81944
|
+
this._abortController = new AbortController();
|
|
81875
81945
|
this.tracer = options.tracer || null;
|
|
81876
81946
|
this.outline = !!options.outline;
|
|
81877
81947
|
this.searchDelegate = options.searchDelegate !== void 0 ? !!options.searchDelegate : true;
|
|
@@ -82317,6 +82387,8 @@ var init_ProbeAgent = __esm({
|
|
|
82317
82387
|
searchDelegateModel: this.searchDelegateModel,
|
|
82318
82388
|
delegationManager: this.delegationManager,
|
|
82319
82389
|
// Per-instance delegation limits
|
|
82390
|
+
parentAbortSignal: this._abortController.signal,
|
|
82391
|
+
// Propagate cancellation to delegations
|
|
82320
82392
|
outputBuffer: this._outputBuffer,
|
|
82321
82393
|
concurrencyLimiter: this.concurrencyLimiter,
|
|
82322
82394
|
// Global AI concurrency limiter
|
|
@@ -82764,6 +82836,15 @@ var init_ProbeAgent = __esm({
|
|
|
82764
82836
|
}
|
|
82765
82837
|
const controller = new AbortController();
|
|
82766
82838
|
const timeoutState = { timeoutId: null };
|
|
82839
|
+
if (this._abortController.signal.aborted) {
|
|
82840
|
+
controller.abort();
|
|
82841
|
+
} else {
|
|
82842
|
+
const onAgentAbort = () => controller.abort();
|
|
82843
|
+
this._abortController.signal.addEventListener("abort", onAgentAbort, { once: true });
|
|
82844
|
+
controller.signal.addEventListener("abort", () => {
|
|
82845
|
+
this._abortController.signal.removeEventListener("abort", onAgentAbort);
|
|
82846
|
+
}, { once: true });
|
|
82847
|
+
}
|
|
82767
82848
|
if (this.maxOperationTimeout && this.maxOperationTimeout > 0) {
|
|
82768
82849
|
timeoutState.timeoutId = setTimeout(() => {
|
|
82769
82850
|
controller.abort();
|
|
@@ -83067,7 +83148,8 @@ var init_ProbeAgent = __esm({
|
|
|
83067
83148
|
allowEdit: this.allowEdit,
|
|
83068
83149
|
allowedTools: allowedToolsForDelegate,
|
|
83069
83150
|
debug: this.debug,
|
|
83070
|
-
tracer: this.tracer
|
|
83151
|
+
tracer: this.tracer,
|
|
83152
|
+
parentAbortSignal: this._abortController.signal
|
|
83071
83153
|
};
|
|
83072
83154
|
if (this.debug) {
|
|
83073
83155
|
console.log(`[DEBUG] Executing delegate tool`);
|
|
@@ -84229,12 +84311,6 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84229
84311
|
});
|
|
84230
84312
|
const systemMessage = await this.getSystemMessage();
|
|
84231
84313
|
let userMessage = { role: "user", content: message.trim() };
|
|
84232
|
-
if (this.enableTasks) {
|
|
84233
|
-
userMessage.content = userMessage.content + "\n\n" + taskGuidancePrompt;
|
|
84234
|
-
if (this.debug) {
|
|
84235
|
-
console.log("[DEBUG] Task guidance injected into user message");
|
|
84236
|
-
}
|
|
84237
|
-
}
|
|
84238
84314
|
if (options.schema && !options._schemaFormatted) {
|
|
84239
84315
|
const schemaInstructions = generateSchemaInstructions(options.schema, { debug: this.debug });
|
|
84240
84316
|
userMessage.content = message.trim() + schemaInstructions;
|
|
@@ -84390,6 +84466,10 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84390
84466
|
completionResult = result;
|
|
84391
84467
|
completionAttempted = true;
|
|
84392
84468
|
}, toolContext);
|
|
84469
|
+
if (this.debug) {
|
|
84470
|
+
const toolNames = Object.keys(tools2);
|
|
84471
|
+
console.log(`[DEBUG] Agent tools registered (${toolNames.length}): ${toolNames.join(", ")}`);
|
|
84472
|
+
}
|
|
84393
84473
|
let maxResponseTokens = this.maxResponseTokens;
|
|
84394
84474
|
if (!maxResponseTokens) {
|
|
84395
84475
|
maxResponseTokens = 4e3;
|
|
@@ -84429,6 +84509,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84429
84509
|
}
|
|
84430
84510
|
if (this.debug) {
|
|
84431
84511
|
console.log(`[DEBUG] Step ${currentIteration}/${maxIterations} finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
84512
|
+
debugLogToolResults(toolResults);
|
|
84432
84513
|
}
|
|
84433
84514
|
}
|
|
84434
84515
|
};
|
|
@@ -84585,6 +84666,7 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
84585
84666
|
}
|
|
84586
84667
|
if (this.debug) {
|
|
84587
84668
|
console.log(`[DEBUG] Completion prompt step finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
84669
|
+
debugLogToolResults(toolResults);
|
|
84588
84670
|
}
|
|
84589
84671
|
}
|
|
84590
84672
|
};
|
|
@@ -85295,6 +85377,9 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
85295
85377
|
* Clean up resources (including MCP connections)
|
|
85296
85378
|
*/
|
|
85297
85379
|
async cleanup() {
|
|
85380
|
+
if (!this._abortController.signal.aborted) {
|
|
85381
|
+
this._abortController.abort();
|
|
85382
|
+
}
|
|
85298
85383
|
if (this.mcpBridge) {
|
|
85299
85384
|
try {
|
|
85300
85385
|
await this.mcpBridge.cleanup();
|
|
@@ -85318,14 +85403,25 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
85318
85403
|
this.clearHistory();
|
|
85319
85404
|
}
|
|
85320
85405
|
/**
|
|
85321
|
-
* Cancel the current request
|
|
85406
|
+
* Cancel the current request and all in-flight delegations.
|
|
85407
|
+
* Aborts the internal AbortController so streamText, subagents,
|
|
85408
|
+
* and any code checking the signal will stop.
|
|
85322
85409
|
*/
|
|
85323
85410
|
cancel() {
|
|
85324
85411
|
this.cancelled = true;
|
|
85412
|
+
this._abortController.abort();
|
|
85325
85413
|
if (this.debug) {
|
|
85326
85414
|
console.log(`[DEBUG] Agent cancelled for session ${this.sessionId}`);
|
|
85327
85415
|
}
|
|
85328
85416
|
}
|
|
85417
|
+
/**
|
|
85418
|
+
* Get the abort signal for this agent.
|
|
85419
|
+
* Delegations and subagents should check this signal.
|
|
85420
|
+
* @returns {AbortSignal}
|
|
85421
|
+
*/
|
|
85422
|
+
get abortSignal() {
|
|
85423
|
+
return this._abortController.signal;
|
|
85424
|
+
}
|
|
85329
85425
|
};
|
|
85330
85426
|
}
|
|
85331
85427
|
});
|
|
@@ -81,8 +81,20 @@ If the solution is clear, you can jump to implementation right away. If not, ask
|
|
|
81
81
|
- Check imports and existing utilities before creating new helpers — the project may already have what you need.
|
|
82
82
|
|
|
83
83
|
# Task Planning
|
|
84
|
-
|
|
85
|
-
-
|
|
84
|
+
When the request has **multiple distinct goals** (e.g. "Fix bug A AND add feature B"), use the task tool to track them:
|
|
85
|
+
- Call the task tool with action="create" and a tasks array. Each task must have an "id" field.
|
|
86
|
+
- Update task status to "in_progress" when starting and "completed" when done.
|
|
87
|
+
- All tasks must be completed or cancelled before calling attempt_completion.
|
|
88
|
+
- Stay flexible — add, remove, or reorganize tasks as your understanding changes.
|
|
89
|
+
|
|
90
|
+
Do NOT create tasks for single-goal requests, even complex ones. Multiple internal steps for one goal (search, read, analyze, implement) do not need tasks.
|
|
91
|
+
|
|
92
|
+
# Discovering Project Commands
|
|
93
|
+
Before building or testing, determine the project's toolchain:
|
|
94
|
+
- Check for Makefile, package.json (scripts), Cargo.toml, go.mod, pyproject.toml, or similar
|
|
95
|
+
- Look for CI config (.github/workflows/, .gitlab-ci.yml) to see what commands CI runs
|
|
96
|
+
- Read README for build/test instructions if the above are unclear
|
|
97
|
+
- Common patterns: \`make build\`/\`make test\`, \`npm run build\`/\`npm test\`, \`cargo build\`/\`cargo test\`, \`go build ./...\`/\`go test ./...\`, \`python -m pytest\`
|
|
86
98
|
|
|
87
99
|
# During Implementation
|
|
88
100
|
- Always create a new branch before making changes to the codebase.
|
|
@@ -93,12 +105,22 @@ If the solution is clear, you can jump to implementation right away. If not, ask
|
|
|
93
105
|
- When editing files, keep edits focused and minimal. For changes spanning more than a few lines, prefer line-targeted editing (start_line/end_line) over text replacement (old_string) — it constrains scope and prevents accidental removal of adjacent content. Never include unrelated sections in an edit operation.
|
|
94
106
|
- After every significant change, verify the project still builds and passes linting. Do not wait until the end to discover breakage.
|
|
95
107
|
|
|
96
|
-
#
|
|
97
|
-
|
|
98
|
-
-
|
|
99
|
-
-
|
|
100
|
-
-
|
|
101
|
-
-
|
|
108
|
+
# Writing Tests
|
|
109
|
+
Every change must include tests. Before writing them:
|
|
110
|
+
- Find existing test files for the module you changed — look in \`tests/\`, \`__tests__/\`, \`*_test.go\`, \`*.test.js\`, \`*.spec.ts\`, or co-located test modules (\`#[cfg(test)]\` in Rust).
|
|
111
|
+
- Read those tests to understand the project's testing patterns: framework, assertion style, mocking approach, file naming, test organization.
|
|
112
|
+
- Prefer extending an existing test file over creating a new one when your change is in the same module.
|
|
113
|
+
- Write tests that cover the main path and important edge cases. Include a failing-input test when relevant.
|
|
114
|
+
- When fixing a bug, write a failing test first that reproduces the bug, then fix the code to make it pass.
|
|
115
|
+
|
|
116
|
+
# Verify Changes
|
|
117
|
+
Before committing or creating a PR, run through this checklist:
|
|
118
|
+
1. **Build** — run the project-appropriate build command (go build, npm run build, cargo build, make, etc.). Fix any compilation errors.
|
|
119
|
+
2. **Lint & typecheck** — run linter/formatter if the project has one (eslint, clippy, golangci-lint, etc.). Fix any new warnings.
|
|
120
|
+
3. **Test** — run the full test suite (go test ./..., npm test, cargo test, make test, pytest, etc.). Fix any failures, including pre-existing tests you may have broken.
|
|
121
|
+
4. **Review** — re-read your diff. Ensure no debug code, no unrelated changes, no secrets, no missing files.
|
|
122
|
+
|
|
123
|
+
Do NOT skip verification. Do NOT proceed to PR creation with a broken build or failing tests.
|
|
102
124
|
|
|
103
125
|
# GitHub Integration
|
|
104
126
|
- Use the \`gh\` CLI for all GitHub operations: issues, pull requests, checks, releases.
|