@probelabs/probe 0.6.0-rc278 → 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-rc278-x86_64-apple-darwin.tar.gz → 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-rc279-x86_64-unknown-linux-musl.tar.gz +0 -0
- package/build/agent/ProbeAgent.js +63 -2
- package/build/agent/index.js +98 -13
- 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 +101 -14
- package/cjs/index.cjs +98 -13
- package/package.json +1 -1
- package/src/agent/ProbeAgent.js +63 -2
- 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-rc278-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc278-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc278-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc278-x86_64-unknown-linux-musl.tar.gz +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -125,6 +125,27 @@ const MAX_HISTORY_MESSAGES = 100;
|
|
|
125
125
|
// Maximum image file size (20MB) to prevent OOM attacks
|
|
126
126
|
const MAX_IMAGE_FILE_SIZE = 20 * 1024 * 1024;
|
|
127
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
|
+
|
|
128
149
|
/**
|
|
129
150
|
* ProbeAgent class to handle AI interactions with code search capabilities
|
|
130
151
|
*/
|
|
@@ -193,6 +214,7 @@ export class ProbeAgent {
|
|
|
193
214
|
this.enableExecutePlan = !!options.enableExecutePlan;
|
|
194
215
|
this.debug = options.debug || process.env.DEBUG === '1';
|
|
195
216
|
this.cancelled = false;
|
|
217
|
+
this._abortController = new AbortController();
|
|
196
218
|
this.tracer = options.tracer || null;
|
|
197
219
|
this.outline = !!options.outline;
|
|
198
220
|
this.searchDelegate = options.searchDelegate !== undefined ? !!options.searchDelegate : true;
|
|
@@ -792,6 +814,7 @@ export class ProbeAgent {
|
|
|
792
814
|
searchDelegateProvider: this.searchDelegateProvider,
|
|
793
815
|
searchDelegateModel: this.searchDelegateModel,
|
|
794
816
|
delegationManager: this.delegationManager, // Per-instance delegation limits
|
|
817
|
+
parentAbortSignal: this._abortController.signal, // Propagate cancellation to delegations
|
|
795
818
|
outputBuffer: this._outputBuffer,
|
|
796
819
|
concurrencyLimiter: this.concurrencyLimiter, // Global AI concurrency limiter
|
|
797
820
|
isToolAllowed,
|
|
@@ -1362,6 +1385,19 @@ export class ProbeAgent {
|
|
|
1362
1385
|
const controller = new AbortController();
|
|
1363
1386
|
const timeoutState = { timeoutId: null };
|
|
1364
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
|
+
|
|
1365
1401
|
// Set up overall operation timeout (default 5 minutes)
|
|
1366
1402
|
if (this.maxOperationTimeout && this.maxOperationTimeout > 0) {
|
|
1367
1403
|
timeoutState.timeoutId = setTimeout(() => {
|
|
@@ -1729,7 +1765,8 @@ export class ProbeAgent {
|
|
|
1729
1765
|
allowEdit: this.allowEdit,
|
|
1730
1766
|
allowedTools: allowedToolsForDelegate,
|
|
1731
1767
|
debug: this.debug,
|
|
1732
|
-
tracer: this.tracer
|
|
1768
|
+
tracer: this.tracer,
|
|
1769
|
+
parentAbortSignal: this._abortController.signal
|
|
1733
1770
|
};
|
|
1734
1771
|
|
|
1735
1772
|
if (this.debug) {
|
|
@@ -3369,6 +3406,11 @@ Follow these instructions carefully:
|
|
|
3369
3406
|
completionAttempted = true;
|
|
3370
3407
|
}, toolContext);
|
|
3371
3408
|
|
|
3409
|
+
if (this.debug) {
|
|
3410
|
+
const toolNames = Object.keys(tools);
|
|
3411
|
+
console.log(`[DEBUG] Agent tools registered (${toolNames.length}): ${toolNames.join(', ')}`);
|
|
3412
|
+
}
|
|
3413
|
+
|
|
3372
3414
|
let maxResponseTokens = this.maxResponseTokens;
|
|
3373
3415
|
if (!maxResponseTokens) {
|
|
3374
3416
|
maxResponseTokens = 4000;
|
|
@@ -3418,6 +3460,7 @@ Follow these instructions carefully:
|
|
|
3418
3460
|
|
|
3419
3461
|
if (this.debug) {
|
|
3420
3462
|
console.log(`[DEBUG] Step ${currentIteration}/${maxIterations} finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
3463
|
+
debugLogToolResults(toolResults);
|
|
3421
3464
|
}
|
|
3422
3465
|
}
|
|
3423
3466
|
};
|
|
@@ -3629,6 +3672,7 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
3629
3672
|
}
|
|
3630
3673
|
if (this.debug) {
|
|
3631
3674
|
console.log(`[DEBUG] Completion prompt step finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
3675
|
+
debugLogToolResults(toolResults);
|
|
3632
3676
|
}
|
|
3633
3677
|
}
|
|
3634
3678
|
};
|
|
@@ -4545,6 +4589,11 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
4545
4589
|
* Clean up resources (including MCP connections)
|
|
4546
4590
|
*/
|
|
4547
4591
|
async cleanup() {
|
|
4592
|
+
// Abort any in-flight operations (delegations, streaming, etc.)
|
|
4593
|
+
if (!this._abortController.signal.aborted) {
|
|
4594
|
+
this._abortController.abort();
|
|
4595
|
+
}
|
|
4596
|
+
|
|
4548
4597
|
// Clean up MCP bridge
|
|
4549
4598
|
if (this.mcpBridge) {
|
|
4550
4599
|
try {
|
|
@@ -4574,12 +4623,24 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
4574
4623
|
}
|
|
4575
4624
|
|
|
4576
4625
|
/**
|
|
4577
|
-
* 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.
|
|
4578
4629
|
*/
|
|
4579
4630
|
cancel() {
|
|
4580
4631
|
this.cancelled = true;
|
|
4632
|
+
this._abortController.abort();
|
|
4581
4633
|
if (this.debug) {
|
|
4582
4634
|
console.log(`[DEBUG] Agent cancelled for session ${this.sessionId}`);
|
|
4583
4635
|
}
|
|
4584
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
|
+
}
|
|
4585
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) {
|
|
@@ -81768,7 +81805,9 @@ __export(ProbeAgent_exports, {
|
|
|
81768
81805
|
ENGINE_ACTIVITY_TIMEOUT_DEFAULT: () => ENGINE_ACTIVITY_TIMEOUT_DEFAULT,
|
|
81769
81806
|
ENGINE_ACTIVITY_TIMEOUT_MAX: () => ENGINE_ACTIVITY_TIMEOUT_MAX,
|
|
81770
81807
|
ENGINE_ACTIVITY_TIMEOUT_MIN: () => ENGINE_ACTIVITY_TIMEOUT_MIN,
|
|
81771
|
-
ProbeAgent: () => ProbeAgent
|
|
81808
|
+
ProbeAgent: () => ProbeAgent,
|
|
81809
|
+
debugLogToolResults: () => debugLogToolResults,
|
|
81810
|
+
debugTruncate: () => debugTruncate
|
|
81772
81811
|
});
|
|
81773
81812
|
import dotenv2 from "dotenv";
|
|
81774
81813
|
import { createAnthropic as createAnthropic2 } from "@ai-sdk/anthropic";
|
|
@@ -81781,6 +81820,19 @@ import { EventEmitter as EventEmitter5 } from "events";
|
|
|
81781
81820
|
import { existsSync as existsSync7 } from "fs";
|
|
81782
81821
|
import { readFile as readFile3, stat, readdir as readdir3 } from "fs/promises";
|
|
81783
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
|
+
}
|
|
81784
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;
|
|
81785
81837
|
var init_ProbeAgent = __esm({
|
|
81786
81838
|
"src/agent/ProbeAgent.js"() {
|
|
@@ -81889,6 +81941,7 @@ var init_ProbeAgent = __esm({
|
|
|
81889
81941
|
this.enableExecutePlan = !!options.enableExecutePlan;
|
|
81890
81942
|
this.debug = options.debug || process.env.DEBUG === "1";
|
|
81891
81943
|
this.cancelled = false;
|
|
81944
|
+
this._abortController = new AbortController();
|
|
81892
81945
|
this.tracer = options.tracer || null;
|
|
81893
81946
|
this.outline = !!options.outline;
|
|
81894
81947
|
this.searchDelegate = options.searchDelegate !== void 0 ? !!options.searchDelegate : true;
|
|
@@ -82334,6 +82387,8 @@ var init_ProbeAgent = __esm({
|
|
|
82334
82387
|
searchDelegateModel: this.searchDelegateModel,
|
|
82335
82388
|
delegationManager: this.delegationManager,
|
|
82336
82389
|
// Per-instance delegation limits
|
|
82390
|
+
parentAbortSignal: this._abortController.signal,
|
|
82391
|
+
// Propagate cancellation to delegations
|
|
82337
82392
|
outputBuffer: this._outputBuffer,
|
|
82338
82393
|
concurrencyLimiter: this.concurrencyLimiter,
|
|
82339
82394
|
// Global AI concurrency limiter
|
|
@@ -82781,6 +82836,15 @@ var init_ProbeAgent = __esm({
|
|
|
82781
82836
|
}
|
|
82782
82837
|
const controller = new AbortController();
|
|
82783
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
|
+
}
|
|
82784
82848
|
if (this.maxOperationTimeout && this.maxOperationTimeout > 0) {
|
|
82785
82849
|
timeoutState.timeoutId = setTimeout(() => {
|
|
82786
82850
|
controller.abort();
|
|
@@ -83084,7 +83148,8 @@ var init_ProbeAgent = __esm({
|
|
|
83084
83148
|
allowEdit: this.allowEdit,
|
|
83085
83149
|
allowedTools: allowedToolsForDelegate,
|
|
83086
83150
|
debug: this.debug,
|
|
83087
|
-
tracer: this.tracer
|
|
83151
|
+
tracer: this.tracer,
|
|
83152
|
+
parentAbortSignal: this._abortController.signal
|
|
83088
83153
|
};
|
|
83089
83154
|
if (this.debug) {
|
|
83090
83155
|
console.log(`[DEBUG] Executing delegate tool`);
|
|
@@ -84401,6 +84466,10 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84401
84466
|
completionResult = result;
|
|
84402
84467
|
completionAttempted = true;
|
|
84403
84468
|
}, toolContext);
|
|
84469
|
+
if (this.debug) {
|
|
84470
|
+
const toolNames = Object.keys(tools2);
|
|
84471
|
+
console.log(`[DEBUG] Agent tools registered (${toolNames.length}): ${toolNames.join(", ")}`);
|
|
84472
|
+
}
|
|
84404
84473
|
let maxResponseTokens = this.maxResponseTokens;
|
|
84405
84474
|
if (!maxResponseTokens) {
|
|
84406
84475
|
maxResponseTokens = 4e3;
|
|
@@ -84440,6 +84509,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84440
84509
|
}
|
|
84441
84510
|
if (this.debug) {
|
|
84442
84511
|
console.log(`[DEBUG] Step ${currentIteration}/${maxIterations} finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
84512
|
+
debugLogToolResults(toolResults);
|
|
84443
84513
|
}
|
|
84444
84514
|
}
|
|
84445
84515
|
};
|
|
@@ -84596,6 +84666,7 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
84596
84666
|
}
|
|
84597
84667
|
if (this.debug) {
|
|
84598
84668
|
console.log(`[DEBUG] Completion prompt step finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
84669
|
+
debugLogToolResults(toolResults);
|
|
84599
84670
|
}
|
|
84600
84671
|
}
|
|
84601
84672
|
};
|
|
@@ -85306,6 +85377,9 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
85306
85377
|
* Clean up resources (including MCP connections)
|
|
85307
85378
|
*/
|
|
85308
85379
|
async cleanup() {
|
|
85380
|
+
if (!this._abortController.signal.aborted) {
|
|
85381
|
+
this._abortController.abort();
|
|
85382
|
+
}
|
|
85309
85383
|
if (this.mcpBridge) {
|
|
85310
85384
|
try {
|
|
85311
85385
|
await this.mcpBridge.cleanup();
|
|
@@ -85329,14 +85403,25 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
85329
85403
|
this.clearHistory();
|
|
85330
85404
|
}
|
|
85331
85405
|
/**
|
|
85332
|
-
* 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.
|
|
85333
85409
|
*/
|
|
85334
85410
|
cancel() {
|
|
85335
85411
|
this.cancelled = true;
|
|
85412
|
+
this._abortController.abort();
|
|
85336
85413
|
if (this.debug) {
|
|
85337
85414
|
console.log(`[DEBUG] Agent cancelled for session ${this.sessionId}`);
|
|
85338
85415
|
}
|
|
85339
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
|
+
}
|
|
85340
85425
|
};
|
|
85341
85426
|
}
|
|
85342
85427
|
});
|
package/build/delegate.js
CHANGED
|
@@ -386,12 +386,18 @@ export async function delegate({
|
|
|
386
386
|
mcpConfig = null,
|
|
387
387
|
mcpConfigPath = null,
|
|
388
388
|
delegationManager = null, // Optional per-instance manager, falls back to default singleton
|
|
389
|
-
concurrencyLimiter = null // Optional global AI concurrency limiter
|
|
389
|
+
concurrencyLimiter = null, // Optional global AI concurrency limiter
|
|
390
|
+
parentAbortSignal = null // Optional AbortSignal from parent to cancel this delegation
|
|
390
391
|
}) {
|
|
391
392
|
if (!task || typeof task !== 'string') {
|
|
392
393
|
throw new Error('Task parameter is required and must be a string');
|
|
393
394
|
}
|
|
394
395
|
|
|
396
|
+
// Check if parent has already been cancelled
|
|
397
|
+
if (parentAbortSignal?.aborted) {
|
|
398
|
+
throw new Error('Delegation cancelled: parent operation was aborted');
|
|
399
|
+
}
|
|
400
|
+
|
|
395
401
|
// Support runtime timeout override via environment variables when timeout not explicitly passed
|
|
396
402
|
// This allows operators to configure delegation timeouts without code changes
|
|
397
403
|
// Priority: DELEGATION_TIMEOUT_MS (milliseconds) > DELEGATION_TIMEOUT_SECONDS > DELEGATION_TIMEOUT (seconds)
|
|
@@ -481,24 +487,47 @@ export async function delegate({
|
|
|
481
487
|
console.error(`[DELEGATE] Subagent config: promptType=${promptType}, enableDelegate=false, maxIterations=${remainingIterations}`);
|
|
482
488
|
}
|
|
483
489
|
|
|
484
|
-
// Set up timeout
|
|
485
|
-
//
|
|
486
|
-
//
|
|
487
|
-
// This is acceptable since:
|
|
488
|
-
// 1. The promise will eventually resolve/reject and be garbage collected
|
|
489
|
-
// 2. The delegation slot is properly released on timeout
|
|
490
|
-
// 3. The parent receives timeout error and can handle it
|
|
491
|
-
// Future improvement: Add signal parameter to ProbeAgent.answer(task, [], { signal })
|
|
490
|
+
// Set up timeout and parent abort handling.
|
|
491
|
+
// When timeout fires or parent aborts, we cancel the subagent so it
|
|
492
|
+
// stops making API calls and releases resources promptly.
|
|
492
493
|
const timeoutPromise = new Promise((_, reject) => {
|
|
493
494
|
timeoutId = setTimeout(() => {
|
|
495
|
+
subagent.cancel();
|
|
494
496
|
reject(new Error(`Delegation timed out after ${timeout} seconds`));
|
|
495
497
|
}, timeout * 1000);
|
|
496
498
|
});
|
|
497
499
|
|
|
498
|
-
//
|
|
500
|
+
// Listen for parent abort signal
|
|
501
|
+
let parentAbortHandler;
|
|
502
|
+
const parentAbortPromise = new Promise((_, reject) => {
|
|
503
|
+
if (parentAbortSignal) {
|
|
504
|
+
if (parentAbortSignal.aborted) {
|
|
505
|
+
subagent.cancel();
|
|
506
|
+
reject(new Error('Delegation cancelled: parent operation was aborted'));
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
parentAbortHandler = () => {
|
|
510
|
+
subagent.cancel();
|
|
511
|
+
reject(new Error('Delegation cancelled: parent operation was aborted'));
|
|
512
|
+
};
|
|
513
|
+
parentAbortSignal.addEventListener('abort', parentAbortHandler, { once: true });
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
// Execute the task with timeout and parent abort
|
|
499
518
|
const answerOptions = schema ? { schema } : undefined;
|
|
500
519
|
const answerPromise = answerOptions ? subagent.answer(task, [], answerOptions) : subagent.answer(task);
|
|
501
|
-
const
|
|
520
|
+
const racers = [answerPromise, timeoutPromise];
|
|
521
|
+
if (parentAbortSignal) racers.push(parentAbortPromise);
|
|
522
|
+
let response;
|
|
523
|
+
try {
|
|
524
|
+
response = await Promise.race(racers);
|
|
525
|
+
} finally {
|
|
526
|
+
// Clean up parent abort listener to prevent memory leaks
|
|
527
|
+
if (parentAbortHandler && parentAbortSignal) {
|
|
528
|
+
parentAbortSignal.removeEventListener('abort', parentAbortHandler);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
502
531
|
|
|
503
532
|
// Clear timeout immediately after race completes to prevent memory leak
|
|
504
533
|
// Note: timeoutId is always set by this point (synchronous in Promise constructor)
|
|
@@ -192,7 +192,8 @@ Instructions:
|
|
|
192
192
|
promptType: 'code-researcher',
|
|
193
193
|
allowedTools: ['extract'],
|
|
194
194
|
maxIterations: 5,
|
|
195
|
-
delegationManager: options.delegationManager // Per-instance delegation limits
|
|
195
|
+
delegationManager: options.delegationManager, // Per-instance delegation limits
|
|
196
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
196
197
|
// timeout removed - inherit default from delegate (300s)
|
|
197
198
|
});
|
|
198
199
|
|
|
@@ -328,7 +329,8 @@ Organize all findings into clear categories with items listed under each.${compl
|
|
|
328
329
|
promptType: 'code-researcher',
|
|
329
330
|
allowedTools: [],
|
|
330
331
|
maxIterations: 5,
|
|
331
|
-
delegationManager: options.delegationManager // Per-instance delegation limits
|
|
332
|
+
delegationManager: options.delegationManager, // Per-instance delegation limits
|
|
333
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
332
334
|
// timeout removed - inherit default from delegate (300s)
|
|
333
335
|
});
|
|
334
336
|
|
|
@@ -404,7 +406,8 @@ CRITICAL: Do NOT guess keywords. Actually run searches and see what returns resu
|
|
|
404
406
|
promptType: 'code-researcher',
|
|
405
407
|
// Full tool access for exploration and experimentation
|
|
406
408
|
maxIterations: 15,
|
|
407
|
-
delegationManager: options.delegationManager // Per-instance delegation limits
|
|
409
|
+
delegationManager: options.delegationManager, // Per-instance delegation limits
|
|
410
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
408
411
|
// timeout removed - inherit default from delegate (300s)
|
|
409
412
|
});
|
|
410
413
|
|
|
@@ -475,7 +478,8 @@ When done, use the attempt_completion tool with your answer as the result.`;
|
|
|
475
478
|
promptType: 'code-researcher',
|
|
476
479
|
allowedTools: [],
|
|
477
480
|
maxIterations: 5,
|
|
478
|
-
delegationManager: options.delegationManager // Per-instance delegation limits
|
|
481
|
+
delegationManager: options.delegationManager, // Per-instance delegation limits
|
|
482
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
479
483
|
// timeout removed - inherit default from delegate (300s)
|
|
480
484
|
});
|
|
481
485
|
|
package/build/tools/vercel.js
CHANGED
|
@@ -277,7 +277,8 @@ export const searchTool = (options = {}) => {
|
|
|
277
277
|
promptType: 'code-searcher',
|
|
278
278
|
allowedTools: ['search', 'extract', 'listFiles', 'attempt_completion'],
|
|
279
279
|
searchDelegate: false,
|
|
280
|
-
schema: CODE_SEARCH_SCHEMA
|
|
280
|
+
schema: CODE_SEARCH_SCHEMA,
|
|
281
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
281
282
|
});
|
|
282
283
|
|
|
283
284
|
const delegateResult = options.tracer?.withSpan
|
|
@@ -581,7 +582,7 @@ export const delegateTool = (options = {}) => {
|
|
|
581
582
|
name: 'delegate',
|
|
582
583
|
description: delegateDescription,
|
|
583
584
|
inputSchema: delegateSchema,
|
|
584
|
-
execute: async ({ task, currentIteration, maxIterations, parentSessionId, path, provider, model, tracer, searchDelegate }) => {
|
|
585
|
+
execute: async ({ task, currentIteration, maxIterations, parentSessionId, path, provider, model, tracer, searchDelegate, parentAbortSignal }) => {
|
|
585
586
|
// Validate required parameters - throw errors for consistency
|
|
586
587
|
if (!task || typeof task !== 'string') {
|
|
587
588
|
throw new Error('Task parameter is required and must be a non-empty string');
|
|
@@ -673,7 +674,8 @@ export const delegateTool = (options = {}) => {
|
|
|
673
674
|
enableMcp,
|
|
674
675
|
mcpConfig,
|
|
675
676
|
mcpConfigPath,
|
|
676
|
-
delegationManager // Per-instance delegation limits
|
|
677
|
+
delegationManager, // Per-instance delegation limits
|
|
678
|
+
parentAbortSignal
|
|
677
679
|
});
|
|
678
680
|
|
|
679
681
|
return result;
|
|
@@ -733,7 +735,8 @@ export const analyzeAllTool = (options = {}) => {
|
|
|
733
735
|
provider: options.provider,
|
|
734
736
|
model: options.model,
|
|
735
737
|
tracer: options.tracer,
|
|
736
|
-
delegationManager // Per-instance delegation limits
|
|
738
|
+
delegationManager, // Per-instance delegation limits
|
|
739
|
+
parentAbortSignal: options.parentAbortSignal || null
|
|
737
740
|
});
|
|
738
741
|
|
|
739
742
|
return result;
|