@probelabs/probe 0.6.0-rc154 → 0.6.0-rc159

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.
Files changed (31) hide show
  1. package/bin/binaries/probe-v0.6.0-rc159-aarch64-apple-darwin.tar.gz +0 -0
  2. package/bin/binaries/probe-v0.6.0-rc159-aarch64-unknown-linux-musl.tar.gz +0 -0
  3. package/bin/binaries/probe-v0.6.0-rc159-x86_64-apple-darwin.tar.gz +0 -0
  4. package/bin/binaries/probe-v0.6.0-rc159-x86_64-pc-windows-msvc.zip +0 -0
  5. package/bin/binaries/probe-v0.6.0-rc159-x86_64-unknown-linux-musl.tar.gz +0 -0
  6. package/build/agent/ProbeAgent.d.ts +2 -0
  7. package/build/agent/ProbeAgent.js +20 -4
  8. package/build/agent/acp/server.js +1 -0
  9. package/build/agent/index.js +464 -216
  10. package/build/delegate.js +326 -201
  11. package/build/downloader.js +46 -17
  12. package/build/extractor.js +12 -12
  13. package/build/tools/vercel.js +55 -14
  14. package/build/utils.js +18 -9
  15. package/cjs/agent/ProbeAgent.cjs +478 -234
  16. package/cjs/index.cjs +41496 -41272
  17. package/package.json +2 -2
  18. package/src/agent/ProbeAgent.d.ts +2 -0
  19. package/src/agent/ProbeAgent.js +20 -4
  20. package/src/agent/acp/server.js +1 -0
  21. package/src/agent/index.js +8 -0
  22. package/src/delegate.js +326 -201
  23. package/src/downloader.js +46 -17
  24. package/src/extractor.js +12 -12
  25. package/src/tools/vercel.js +55 -14
  26. package/src/utils.js +18 -9
  27. package/bin/binaries/probe-v0.6.0-rc154-aarch64-apple-darwin.tar.gz +0 -0
  28. package/bin/binaries/probe-v0.6.0-rc154-aarch64-unknown-linux-gnu.tar.gz +0 -0
  29. package/bin/binaries/probe-v0.6.0-rc154-x86_64-apple-darwin.tar.gz +0 -0
  30. package/bin/binaries/probe-v0.6.0-rc154-x86_64-pc-windows-msvc.zip +0 -0
  31. package/bin/binaries/probe-v0.6.0-rc154-x86_64-unknown-linux-gnu.tar.gz +0 -0
@@ -2440,7 +2440,7 @@ var require_dist_cjs15 = __commonJS({
2440
2440
  var MIN_WAIT_TIME = 6e3;
2441
2441
  async function writeRequestBody(httpRequest, request, maxContinueTimeoutMs = MIN_WAIT_TIME) {
2442
2442
  const headers = request.headers ?? {};
2443
- const expect = headers["Expect"] || headers["expect"];
2443
+ const expect = headers.Expect || headers.expect;
2444
2444
  let timeoutId = -1;
2445
2445
  let sendBody = true;
2446
2446
  if (expect === "100-continue") {
@@ -2568,6 +2568,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
2568
2568
  this.config = await this.configProvider;
2569
2569
  }
2570
2570
  return new Promise((_resolve, _reject) => {
2571
+ const config = this.config;
2571
2572
  let writeRequestBodyPromise = void 0;
2572
2573
  const timeouts = [];
2573
2574
  const resolve4 = async (arg) => {
@@ -2580,9 +2581,6 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
2580
2581
  timeouts.forEach(timing.clearTimeout);
2581
2582
  _reject(arg);
2582
2583
  };
2583
- if (!this.config) {
2584
- throw new Error("Node HTTP request handler config is not resolved");
2585
- }
2586
2584
  if (abortSignal?.aborted) {
2587
2585
  const abortError = new Error("Request aborted");
2588
2586
  abortError.name = "AbortError";
@@ -2590,10 +2588,18 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
2590
2588
  return;
2591
2589
  }
2592
2590
  const isSSL = request.protocol === "https:";
2593
- const agent = isSSL ? this.config.httpsAgent : this.config.httpAgent;
2591
+ const headers = request.headers ?? {};
2592
+ const expectContinue = (headers.Expect ?? headers.expect) === "100-continue";
2593
+ let agent = isSSL ? config.httpsAgent : config.httpAgent;
2594
+ if (expectContinue) {
2595
+ agent = new (isSSL ? https.Agent : http.Agent)({
2596
+ keepAlive: false,
2597
+ maxSockets: Infinity
2598
+ });
2599
+ }
2594
2600
  timeouts.push(timing.setTimeout(() => {
2595
- this.socketWarningTimestamp = _NodeHttpHandler.checkSocketUsage(agent, this.socketWarningTimestamp, this.config.logger);
2596
- }, this.config.socketAcquisitionWarningTimeout ?? (this.config.requestTimeout ?? 2e3) + (this.config.connectionTimeout ?? 1e3)));
2601
+ this.socketWarningTimestamp = _NodeHttpHandler.checkSocketUsage(agent, this.socketWarningTimestamp, config.logger);
2602
+ }, config.socketAcquisitionWarningTimeout ?? (config.requestTimeout ?? 2e3) + (config.connectionTimeout ?? 1e3)));
2597
2603
  const queryString = querystringBuilder.buildQueryString(request.query || {});
2598
2604
  let auth = void 0;
2599
2605
  if (request.username != null || request.password != null) {
@@ -2655,10 +2661,10 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
2655
2661
  abortSignal.onabort = onAbort;
2656
2662
  }
2657
2663
  }
2658
- const effectiveRequestTimeout = requestTimeout ?? this.config.requestTimeout;
2659
- timeouts.push(setConnectionTimeout(req, reject2, this.config.connectionTimeout));
2660
- timeouts.push(setRequestTimeout(req, reject2, effectiveRequestTimeout, this.config.throwOnRequestTimeout, this.config.logger ?? console));
2661
- timeouts.push(setSocketTimeout(req, reject2, this.config.socketTimeout));
2664
+ const effectiveRequestTimeout = requestTimeout ?? config.requestTimeout;
2665
+ timeouts.push(setConnectionTimeout(req, reject2, config.connectionTimeout));
2666
+ timeouts.push(setRequestTimeout(req, reject2, effectiveRequestTimeout, config.throwOnRequestTimeout, config.logger ?? console));
2667
+ timeouts.push(setSocketTimeout(req, reject2, config.socketTimeout));
2662
2668
  const httpAgent = nodeHttpsOptions.agent;
2663
2669
  if (typeof httpAgent === "object" && "keepAlive" in httpAgent) {
2664
2670
  timeouts.push(setSocketKeepAlive(req, {
@@ -27643,6 +27649,28 @@ var init_directory_resolver = __esm({
27643
27649
  });
27644
27650
 
27645
27651
  // src/downloader.js
27652
+ function sanitizeError(err) {
27653
+ try {
27654
+ const status = err?.response?.status;
27655
+ const statusText = err?.response?.statusText;
27656
+ const url = err?.config?.url || err?.response?.config?.url;
27657
+ const code = err?.code;
27658
+ const serverMsg = typeof err?.response?.data === "string" ? err.response.data.slice(0, 500) : typeof err?.response?.data?.message === "string" ? err.response.data.message : void 0;
27659
+ const base = err?.message || String(err);
27660
+ const parts = [base];
27661
+ if (status || statusText) parts.push(`[${status ?? ""} ${statusText ?? ""}]`.trim());
27662
+ if (code) parts.push(`code=${code}`);
27663
+ if (url) parts.push(`url=${url}`);
27664
+ if (serverMsg) parts.push(`server="${String(serverMsg).replace(/\s+/g, " ").trim()}"`);
27665
+ const e3 = new Error(parts.filter(Boolean).join(" "));
27666
+ if (status) e3.status = status;
27667
+ if (code) e3.code = code;
27668
+ if (url) e3.url = url;
27669
+ return e3;
27670
+ } catch (_2) {
27671
+ return new Error(err?.message || String(err));
27672
+ }
27673
+ }
27646
27674
  async function acquireFileLock(lockPath, version) {
27647
27675
  const lockData = {
27648
27676
  version,
@@ -27791,7 +27819,7 @@ function detectOsArch() {
27791
27819
  case "linux":
27792
27820
  osInfo = {
27793
27821
  type: "linux",
27794
- keywords: ["linux", "Linux", "gnu"]
27822
+ keywords: ["linux", "Linux", "musl", "gnu"]
27795
27823
  };
27796
27824
  break;
27797
27825
  case "darwin":
@@ -27835,7 +27863,7 @@ function constructAssetInfo(version, osInfo, archInfo) {
27835
27863
  let extension;
27836
27864
  switch (osInfo.type) {
27837
27865
  case "linux":
27838
- platform = `${archInfo.type}-unknown-linux-gnu`;
27866
+ platform = `${archInfo.type}-unknown-linux-musl`;
27839
27867
  extension = "tar.gz";
27840
27868
  break;
27841
27869
  case "darwin":
@@ -27952,7 +27980,7 @@ async function getLatestRelease(version) {
27952
27980
  }
27953
27981
  return { tag: tag2, assets };
27954
27982
  }
27955
- throw error2;
27983
+ throw sanitizeError(error2);
27956
27984
  }
27957
27985
  }
27958
27986
  function findBestAsset(assets, osInfo, archInfo) {
@@ -28166,7 +28194,7 @@ async function extractBinary(assetPath, outputDir) {
28166
28194
  return binaryPath;
28167
28195
  } catch (error2) {
28168
28196
  console.error(`Error extracting binary: ${error2 instanceof Error ? error2.message : String(error2)}`);
28169
- throw error2;
28197
+ throw sanitizeError(error2);
28170
28198
  }
28171
28199
  }
28172
28200
  async function getVersionInfo(binDir) {
@@ -28331,8 +28359,8 @@ async function downloadProbeBinary(version) {
28331
28359
  }
28332
28360
  return await withDownloadLock(version, () => doDownload(version));
28333
28361
  } catch (error2) {
28334
- console.error("Error downloading probe binary:", error2);
28335
- throw error2;
28362
+ console.error("Error downloading probe binary:", error2?.message || String(error2));
28363
+ throw sanitizeError(error2);
28336
28364
  }
28337
28365
  }
28338
28366
  var import_axios, import_fs_extra2, import_path2, import_crypto, import_util3, import_child_process, import_tar, import_os2, import_url2, exec, REPO_OWNER, REPO_NAME, BINARY_NAME, __filename2, __dirname2, downloadLocks, LOCK_TIMEOUT_MS, LOCK_POLL_INTERVAL_MS, MAX_LOCK_WAIT_MS;
@@ -28375,9 +28403,15 @@ async function getBinaryPath(options = {}) {
28375
28403
  probeBinaryPath = await downloadProbeBinary(version);
28376
28404
  return probeBinaryPath;
28377
28405
  }
28378
- const binDir = await getPackageBinDir();
28379
28406
  const isWindows = process.platform === "win32";
28380
28407
  const binaryName = isWindows ? "probe.exe" : "probe-binary";
28408
+ const localPackageBin = import_path3.default.resolve(__dirname3, "..", "bin");
28409
+ const localBinaryPath = import_path3.default.join(localPackageBin, binaryName);
28410
+ if (import_fs_extra3.default.existsSync(localBinaryPath) && !forceDownload) {
28411
+ probeBinaryPath = localBinaryPath;
28412
+ return probeBinaryPath;
28413
+ }
28414
+ const binDir = await getPackageBinDir();
28381
28415
  const binaryPath = import_path3.default.join(binDir, binaryName);
28382
28416
  if (import_fs_extra3.default.existsSync(binaryPath) && !forceDownload) {
28383
28417
  probeBinaryPath = binaryPath;
@@ -28822,6 +28856,262 @@ var init_grep = __esm({
28822
28856
  }
28823
28857
  });
28824
28858
 
28859
+ // src/delegate.js
28860
+ async function delegate({
28861
+ task,
28862
+ timeout = 300,
28863
+ debug = false,
28864
+ currentIteration = 0,
28865
+ maxIterations = 30,
28866
+ tracer = null,
28867
+ parentSessionId = null,
28868
+ path: path7 = null,
28869
+ provider = null,
28870
+ model = null
28871
+ }) {
28872
+ if (!task || typeof task !== "string") {
28873
+ throw new Error("Task parameter is required and must be a string");
28874
+ }
28875
+ const sessionId = (0, import_crypto2.randomUUID)();
28876
+ const startTime = Date.now();
28877
+ const remainingIterations = Math.max(1, maxIterations - currentIteration);
28878
+ const delegationSpan = tracer ? tracer.createDelegationSpan(sessionId, task) : null;
28879
+ let timeoutId = null;
28880
+ let acquired = false;
28881
+ try {
28882
+ delegationManager.tryAcquire(parentSessionId);
28883
+ acquired = true;
28884
+ if (debug) {
28885
+ const stats = delegationManager.getStats();
28886
+ console.error(`[DELEGATE] Starting delegation session ${sessionId}`);
28887
+ console.error(`[DELEGATE] Parent session: ${parentSessionId || "none"}`);
28888
+ console.error(`[DELEGATE] Task: ${task}`);
28889
+ console.error(`[DELEGATE] Current iteration: ${currentIteration}/${maxIterations}`);
28890
+ console.error(`[DELEGATE] Remaining iterations for subagent: ${remainingIterations}`);
28891
+ console.error(`[DELEGATE] Timeout configured: ${timeout} seconds`);
28892
+ console.error(`[DELEGATE] Global active delegations: ${stats.globalActive}/${stats.maxConcurrent}`);
28893
+ console.error(`[DELEGATE] Using ProbeAgent SDK with code-researcher prompt`);
28894
+ }
28895
+ const subagent = new ProbeAgent({
28896
+ sessionId,
28897
+ promptType: "code-researcher",
28898
+ // Clean prompt, not inherited from parent
28899
+ enableDelegate: false,
28900
+ // Explicitly disable delegation to prevent recursion
28901
+ disableMermaidValidation: true,
28902
+ // Faster processing
28903
+ disableJsonValidation: true,
28904
+ // Simpler responses
28905
+ maxIterations: remainingIterations,
28906
+ debug,
28907
+ tracer,
28908
+ path: path7,
28909
+ // Inherit from parent
28910
+ provider,
28911
+ // Inherit from parent
28912
+ model
28913
+ // Inherit from parent
28914
+ });
28915
+ if (debug) {
28916
+ console.error(`[DELEGATE] Created subagent with session ${sessionId}`);
28917
+ console.error(`[DELEGATE] Subagent config: promptType=code-researcher, enableDelegate=false, maxIterations=${remainingIterations}`);
28918
+ }
28919
+ const timeoutPromise = new Promise((_2, reject2) => {
28920
+ timeoutId = setTimeout(() => {
28921
+ reject2(new Error(`Delegation timed out after ${timeout} seconds`));
28922
+ }, timeout * 1e3);
28923
+ });
28924
+ const answerPromise = subagent.answer(task);
28925
+ const response = await Promise.race([answerPromise, timeoutPromise]);
28926
+ if (timeoutId !== null) {
28927
+ clearTimeout(timeoutId);
28928
+ timeoutId = null;
28929
+ }
28930
+ const duration = Date.now() - startTime;
28931
+ if (typeof response !== "string") {
28932
+ throw new Error("Delegate agent returned invalid response (not a string)");
28933
+ }
28934
+ const trimmedResponse = response.trim();
28935
+ if (trimmedResponse.length === 0) {
28936
+ throw new Error("Delegate agent returned empty or whitespace-only response");
28937
+ }
28938
+ if (trimmedResponse.includes("\0")) {
28939
+ throw new Error("Delegate agent returned response containing null bytes");
28940
+ }
28941
+ if (debug) {
28942
+ console.error(`[DELEGATE] Task completed successfully for session ${sessionId}`);
28943
+ console.error(`[DELEGATE] Duration: ${(duration / 1e3).toFixed(2)}s`);
28944
+ console.error(`[DELEGATE] Response length: ${response.length} chars`);
28945
+ }
28946
+ if (tracer) {
28947
+ tracer.recordDelegationEvent("completed", {
28948
+ "delegation.session_id": sessionId,
28949
+ "delegation.parent_session_id": parentSessionId,
28950
+ "delegation.duration_ms": duration,
28951
+ "delegation.response_length": response.length,
28952
+ "delegation.success": true
28953
+ });
28954
+ if (delegationSpan) {
28955
+ delegationSpan.setAttributes({
28956
+ "delegation.result.success": true,
28957
+ "delegation.result.response_length": response.length,
28958
+ "delegation.result.duration_ms": duration
28959
+ });
28960
+ delegationSpan.setStatus({ code: 1 });
28961
+ delegationSpan.end();
28962
+ }
28963
+ }
28964
+ if (acquired) {
28965
+ delegationManager.release(parentSessionId, debug);
28966
+ }
28967
+ return response;
28968
+ } catch (error2) {
28969
+ if (timeoutId !== null) {
28970
+ clearTimeout(timeoutId);
28971
+ timeoutId = null;
28972
+ }
28973
+ const duration = Date.now() - startTime;
28974
+ if (acquired) {
28975
+ delegationManager.release(parentSessionId, debug);
28976
+ }
28977
+ if (debug) {
28978
+ console.error(`[DELEGATE] Task failed for session ${sessionId} after ${duration}ms`);
28979
+ console.error(`[DELEGATE] Error: ${error2.message}`);
28980
+ console.error(`[DELEGATE] Stack: ${error2.stack}`);
28981
+ }
28982
+ if (tracer) {
28983
+ tracer.recordDelegationEvent("failed", {
28984
+ "delegation.session_id": sessionId,
28985
+ "delegation.parent_session_id": parentSessionId,
28986
+ "delegation.duration_ms": duration,
28987
+ "delegation.error_message": error2.message,
28988
+ "delegation.success": false
28989
+ });
28990
+ if (delegationSpan) {
28991
+ delegationSpan.setAttributes({
28992
+ "delegation.result.success": false,
28993
+ "delegation.result.error": error2.message,
28994
+ "delegation.result.duration_ms": duration
28995
+ });
28996
+ delegationSpan.setStatus({ code: 2, message: error2.message });
28997
+ delegationSpan.end();
28998
+ }
28999
+ }
29000
+ throw new Error(`Delegation failed: ${error2.message}`);
29001
+ }
29002
+ }
29003
+ var import_crypto2, DelegationManager, delegationManager;
29004
+ var init_delegate = __esm({
29005
+ "src/delegate.js"() {
29006
+ "use strict";
29007
+ import_crypto2 = require("crypto");
29008
+ init_ProbeAgent();
29009
+ DelegationManager = class {
29010
+ constructor() {
29011
+ this.maxConcurrent = parseInt(process.env.MAX_CONCURRENT_DELEGATIONS || "3", 10);
29012
+ this.maxPerSession = parseInt(process.env.MAX_DELEGATIONS_PER_SESSION || "10", 10);
29013
+ this.sessionDelegations = /* @__PURE__ */ new Map();
29014
+ this.globalActive = 0;
29015
+ this.cleanupInterval = setInterval(() => {
29016
+ try {
29017
+ this.cleanupStaleSessions();
29018
+ } catch (error2) {
29019
+ console.error("[DelegationManager] Error during cleanup:", error2);
29020
+ }
29021
+ }, 5 * 60 * 1e3);
29022
+ if (this.cleanupInterval.unref) {
29023
+ this.cleanupInterval.unref();
29024
+ }
29025
+ }
29026
+ /**
29027
+ * Check limits and increment counters (synchronous, atomic in Node.js event loop)
29028
+ * @param {string|null|undefined} parentSessionId - Parent session ID for tracking
29029
+ */
29030
+ tryAcquire(parentSessionId) {
29031
+ if (parentSessionId !== null && parentSessionId !== void 0 && typeof parentSessionId !== "string") {
29032
+ throw new TypeError("parentSessionId must be a string, null, or undefined");
29033
+ }
29034
+ if (this.globalActive >= this.maxConcurrent) {
29035
+ throw new Error(`Maximum concurrent delegations (${this.maxConcurrent}) reached. Please wait for some delegations to complete.`);
29036
+ }
29037
+ if (parentSessionId) {
29038
+ const sessionData = this.sessionDelegations.get(parentSessionId);
29039
+ const sessionCount = sessionData?.count || 0;
29040
+ if (sessionCount >= this.maxPerSession) {
29041
+ throw new Error(`Maximum delegations per session (${this.maxPerSession}) reached for session ${parentSessionId}`);
29042
+ }
29043
+ }
29044
+ this.globalActive++;
29045
+ if (parentSessionId) {
29046
+ const sessionData = this.sessionDelegations.get(parentSessionId);
29047
+ if (sessionData) {
29048
+ sessionData.count++;
29049
+ sessionData.lastUpdated = Date.now();
29050
+ } else {
29051
+ this.sessionDelegations.set(parentSessionId, {
29052
+ count: 1,
29053
+ lastUpdated: Date.now()
29054
+ });
29055
+ }
29056
+ }
29057
+ return true;
29058
+ }
29059
+ /**
29060
+ * Decrement counters (synchronous, atomic in Node.js event loop)
29061
+ */
29062
+ release(parentSessionId, debug = false) {
29063
+ this.globalActive = Math.max(0, this.globalActive - 1);
29064
+ if (parentSessionId) {
29065
+ const sessionData = this.sessionDelegations.get(parentSessionId);
29066
+ if (sessionData) {
29067
+ sessionData.count = Math.max(0, sessionData.count - 1);
29068
+ if (sessionData.count === 0) {
29069
+ this.sessionDelegations.delete(parentSessionId);
29070
+ }
29071
+ }
29072
+ }
29073
+ if (debug) {
29074
+ console.error(`[DELEGATE] Released. Global active: ${this.globalActive}`);
29075
+ }
29076
+ }
29077
+ /**
29078
+ * Get current stats for monitoring
29079
+ */
29080
+ getStats() {
29081
+ return {
29082
+ globalActive: this.globalActive,
29083
+ maxConcurrent: this.maxConcurrent,
29084
+ maxPerSession: this.maxPerSession,
29085
+ sessionCount: this.sessionDelegations.size
29086
+ };
29087
+ }
29088
+ /**
29089
+ * Clean up stale sessions (sessions with count=0 that haven't been updated in 1 hour)
29090
+ */
29091
+ cleanupStaleSessions() {
29092
+ const oneHourAgo = Date.now() - 60 * 60 * 1e3;
29093
+ for (const [sessionId, data2] of this.sessionDelegations.entries()) {
29094
+ if (data2.count === 0 && data2.lastUpdated < oneHourAgo) {
29095
+ this.sessionDelegations.delete(sessionId);
29096
+ }
29097
+ }
29098
+ }
29099
+ /**
29100
+ * Cleanup all resources (for testing or shutdown)
29101
+ */
29102
+ cleanup() {
29103
+ if (this.cleanupInterval) {
29104
+ clearInterval(this.cleanupInterval);
29105
+ this.cleanupInterval = null;
29106
+ }
29107
+ this.sessionDelegations.clear();
29108
+ this.globalActive = 0;
29109
+ }
29110
+ };
29111
+ delegationManager = new DelegationManager();
29112
+ }
29113
+ });
29114
+
28825
29115
  // node_modules/zod/v3/helpers/util.js
28826
29116
  var util, objectUtil, ZodParsedType, getParsedType;
28827
29117
  var init_util2 = __esm({
@@ -33035,7 +33325,7 @@ function parseTargets(targets) {
33035
33325
  }
33036
33326
  return targets.split(/\s+/).filter((f3) => f3.length > 0);
33037
33327
  }
33038
- var searchSchema, querySchema, extractSchema, delegateSchema, bashSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, attemptCompletionToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, DEFAULT_VALID_TOOLS;
33328
+ var searchSchema, querySchema, extractSchema, delegateSchema, bashSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, DEFAULT_VALID_TOOLS;
33039
33329
  var init_common2 = __esm({
33040
33330
  "src/tools/common.js"() {
33041
33331
  "use strict";
@@ -33240,6 +33530,26 @@ User: Read file inside the dependency
33240
33530
  </extract>
33241
33531
 
33242
33532
  </examples>
33533
+ `;
33534
+ delegateToolDefinition = `
33535
+ ## delegate
33536
+ Description: Automatically delegate big distinct tasks to specialized probe subagents within the agentic loop. Use this when you recognize that a user's request involves multiple large, distinct components that would benefit from parallel processing or specialized focus. The AI agent should automatically identify opportunities for task separation and use delegation without explicit user instruction.
33537
+
33538
+ Parameters:
33539
+ - task: (required) A complete, self-contained task that can be executed independently by a subagent. Should be specific and focused on one area of expertise.
33540
+
33541
+ Usage Pattern:
33542
+ When the AI agent encounters complex multi-part requests, it should automatically break them down and delegate:
33543
+
33544
+ <delegate>
33545
+ <task>Analyze all authentication and authorization code in the codebase for security vulnerabilities and provide specific remediation recommendations</task>
33546
+ </delegate>
33547
+
33548
+ <delegate>
33549
+ <task>Review database queries and API endpoints for performance bottlenecks and suggest optimization strategies</task>
33550
+ </delegate>
33551
+
33552
+ The agent uses this tool automatically when it identifies that work can be separated into distinct, parallel tasks for more efficient processing.
33243
33553
  `;
33244
33554
  attemptCompletionToolDefinition = `
33245
33555
  ## attempt_completion
@@ -33268,194 +33578,6 @@ I have refactored the search module according to the requirements and verified t
33268
33578
  }
33269
33579
  });
33270
33580
 
33271
- // src/delegate.js
33272
- async function delegate({ task, timeout = 300, debug = false, currentIteration = 0, maxIterations = 30, tracer = null }) {
33273
- if (!task || typeof task !== "string") {
33274
- throw new Error("Task parameter is required and must be a string");
33275
- }
33276
- const sessionId = (0, import_crypto2.randomUUID)();
33277
- const startTime = Date.now();
33278
- const remainingIterations = Math.max(1, maxIterations - currentIteration);
33279
- if (debug) {
33280
- console.error(`[DELEGATE] Starting delegation session ${sessionId}`);
33281
- console.error(`[DELEGATE] Task: ${task}`);
33282
- console.error(`[DELEGATE] Current iteration: ${currentIteration}/${maxIterations}`);
33283
- console.error(`[DELEGATE] Remaining iterations for subagent: ${remainingIterations}`);
33284
- console.error(`[DELEGATE] Timeout configured: ${timeout} seconds`);
33285
- console.error(`[DELEGATE] Using clean agent environment with code-researcher prompt`);
33286
- }
33287
- try {
33288
- const binaryPath = await getBinaryPath();
33289
- const args = [
33290
- "agent",
33291
- "--task",
33292
- task,
33293
- "--session-id",
33294
- sessionId,
33295
- "--prompt-type",
33296
- "code-researcher",
33297
- // Automatically use default code researcher prompt
33298
- "--no-schema-validation",
33299
- // Automatically disable schema validation
33300
- "--no-mermaid-validation",
33301
- // Automatically disable mermaid validation
33302
- "--max-iterations",
33303
- remainingIterations.toString()
33304
- // Automatically limit to remaining iterations
33305
- ];
33306
- if (debug) {
33307
- args.push("--debug");
33308
- console.error(`[DELEGATE] Using binary at: ${binaryPath}`);
33309
- console.error(`[DELEGATE] Command args: ${args.join(" ")}`);
33310
- }
33311
- return new Promise((resolve4, reject2) => {
33312
- const delegationSpan = tracer ? tracer.createDelegationSpan(sessionId, task) : null;
33313
- const process2 = (0, import_child_process6.spawn)(binaryPath, args, {
33314
- stdio: ["pipe", "pipe", "pipe"],
33315
- timeout: timeout * 1e3
33316
- });
33317
- let stdout = "";
33318
- let stderr = "";
33319
- let isResolved = false;
33320
- process2.stdout.on("data", (data2) => {
33321
- const chunk = data2.toString();
33322
- stdout += chunk;
33323
- if (debug) {
33324
- const preview = createMessagePreview(chunk);
33325
- console.error(`[DELEGATE] stdout chunk received (${chunk.length} chars): ${preview}`);
33326
- }
33327
- });
33328
- process2.stderr.on("data", (data2) => {
33329
- const chunk = data2.toString();
33330
- stderr += chunk;
33331
- if (debug) {
33332
- const preview = createMessagePreview(chunk);
33333
- console.error(`[DELEGATE] stderr chunk received (${chunk.length} chars): ${preview}`);
33334
- }
33335
- });
33336
- process2.on("close", (code) => {
33337
- if (isResolved) return;
33338
- isResolved = true;
33339
- const duration = Date.now() - startTime;
33340
- if (debug) {
33341
- console.error(`[DELEGATE] Process completed with code ${code} in ${duration}ms`);
33342
- console.error(`[DELEGATE] Duration: ${(duration / 1e3).toFixed(2)}s`);
33343
- console.error(`[DELEGATE] Total stdout: ${stdout.length} chars`);
33344
- console.error(`[DELEGATE] Total stderr: ${stderr.length} chars`);
33345
- }
33346
- if (code === 0) {
33347
- const response = stdout.trim();
33348
- if (!response) {
33349
- if (debug) {
33350
- console.error(`[DELEGATE] Task completed but returned empty response for session ${sessionId}`);
33351
- }
33352
- reject2(new Error("Delegate agent returned empty response"));
33353
- return;
33354
- }
33355
- if (debug) {
33356
- console.error(`[DELEGATE] Task completed successfully for session ${sessionId}`);
33357
- console.error(`[DELEGATE] Response length: ${response.length} chars`);
33358
- }
33359
- if (tracer) {
33360
- tracer.recordDelegationEvent("completed", {
33361
- "delegation.session_id": sessionId,
33362
- "delegation.duration_ms": duration,
33363
- "delegation.response_length": response.length,
33364
- "delegation.success": true
33365
- });
33366
- if (delegationSpan) {
33367
- delegationSpan.setAttributes({
33368
- "delegation.result.success": true,
33369
- "delegation.result.response_length": response.length,
33370
- "delegation.result.duration_ms": duration
33371
- });
33372
- delegationSpan.setStatus({ code: 1 });
33373
- delegationSpan.end();
33374
- }
33375
- }
33376
- resolve4(response);
33377
- } else {
33378
- const errorMessage = stderr.trim() || `Delegate process failed with exit code ${code}`;
33379
- if (debug) {
33380
- console.error(`[DELEGATE] Task failed for session ${sessionId} with code ${code}`);
33381
- console.error(`[DELEGATE] Error message: ${errorMessage}`);
33382
- }
33383
- if (tracer) {
33384
- tracer.recordDelegationEvent("failed", {
33385
- "delegation.session_id": sessionId,
33386
- "delegation.duration_ms": duration,
33387
- "delegation.exit_code": code,
33388
- "delegation.error_message": errorMessage,
33389
- "delegation.success": false
33390
- });
33391
- if (delegationSpan) {
33392
- delegationSpan.setAttributes({
33393
- "delegation.result.success": false,
33394
- "delegation.result.exit_code": code,
33395
- "delegation.result.error": errorMessage,
33396
- "delegation.result.duration_ms": duration
33397
- });
33398
- delegationSpan.setStatus({ code: 2, message: errorMessage });
33399
- delegationSpan.end();
33400
- }
33401
- }
33402
- reject2(new Error(`Delegation failed: ${errorMessage}`));
33403
- }
33404
- });
33405
- process2.on("error", (error2) => {
33406
- if (isResolved) return;
33407
- isResolved = true;
33408
- const duration = Date.now() - startTime;
33409
- if (debug) {
33410
- console.error(`[DELEGATE] Process spawn error after ${duration}ms:`, error2);
33411
- console.error(`[DELEGATE] Session ${sessionId} failed during process creation`);
33412
- console.error(`[DELEGATE] Error type: ${error2.code || "unknown"}`);
33413
- }
33414
- reject2(new Error(`Failed to start delegate process: ${error2.message}`));
33415
- });
33416
- setTimeout(() => {
33417
- if (isResolved) return;
33418
- isResolved = true;
33419
- const duration = Date.now() - startTime;
33420
- if (debug) {
33421
- console.error(`[DELEGATE] Process timeout after ${(duration / 1e3).toFixed(2)}s (limit: ${timeout}s)`);
33422
- console.error(`[DELEGATE] Terminating session ${sessionId} due to timeout`);
33423
- console.error(`[DELEGATE] Partial stdout: ${stdout.substring(0, 500)}${stdout.length > 500 ? "..." : ""}`);
33424
- console.error(`[DELEGATE] Partial stderr: ${stderr.substring(0, 500)}${stderr.length > 500 ? "..." : ""}`);
33425
- }
33426
- process2.kill("SIGTERM");
33427
- setTimeout(() => {
33428
- if (!process2.killed) {
33429
- if (debug) {
33430
- console.error(`[DELEGATE] Force killing process ${sessionId} after graceful timeout`);
33431
- }
33432
- process2.kill("SIGKILL");
33433
- }
33434
- }, 5e3);
33435
- reject2(new Error(`Delegation timed out after ${timeout} seconds`));
33436
- }, timeout * 1e3);
33437
- });
33438
- } catch (error2) {
33439
- const duration = Date.now() - startTime;
33440
- if (debug) {
33441
- console.error(`[DELEGATE] Error in delegate function after ${duration}ms:`, error2);
33442
- console.error(`[DELEGATE] Session ${sessionId} failed during setup`);
33443
- console.error(`[DELEGATE] Error stack: ${error2.stack}`);
33444
- }
33445
- throw new Error(`Delegation setup failed: ${error2.message}`);
33446
- }
33447
- }
33448
- var import_child_process6, import_crypto2;
33449
- var init_delegate = __esm({
33450
- "src/delegate.js"() {
33451
- "use strict";
33452
- import_child_process6 = require("child_process");
33453
- import_crypto2 = require("crypto");
33454
- init_utils2();
33455
- init_common2();
33456
- }
33457
- });
33458
-
33459
33581
  // src/tools/vercel.js
33460
33582
  var import_ai, searchTool, queryTool, extractTool, delegateTool;
33461
33583
  var init_vercel = __esm({
@@ -33628,21 +33750,50 @@ var init_vercel = __esm({
33628
33750
  name: "delegate",
33629
33751
  description: delegateDescription,
33630
33752
  inputSchema: delegateSchema,
33631
- execute: async ({ task }) => {
33632
- try {
33633
- if (debug) {
33634
- console.error(`Executing delegate with task: "${task}"`);
33635
- }
33636
- const result = await delegate({
33637
- task,
33638
- timeout,
33639
- debug
33640
- });
33641
- return result;
33642
- } catch (error2) {
33643
- console.error("Error executing delegate command:", error2);
33644
- return `Error executing delegate command: ${error2.message}`;
33753
+ execute: async ({ task, currentIteration, maxIterations, parentSessionId, path: path7, provider, model, tracer }) => {
33754
+ if (!task || typeof task !== "string") {
33755
+ throw new Error("Task parameter is required and must be a non-empty string");
33645
33756
  }
33757
+ if (task.trim().length === 0) {
33758
+ throw new Error("Task parameter cannot be empty or whitespace only");
33759
+ }
33760
+ if (currentIteration !== void 0 && (typeof currentIteration !== "number" || currentIteration < 0)) {
33761
+ throw new Error("currentIteration must be a non-negative number");
33762
+ }
33763
+ if (maxIterations !== void 0 && (typeof maxIterations !== "number" || maxIterations < 1)) {
33764
+ throw new Error("maxIterations must be a positive number");
33765
+ }
33766
+ if (parentSessionId !== void 0 && parentSessionId !== null && typeof parentSessionId !== "string") {
33767
+ throw new TypeError("parentSessionId must be a string, null, or undefined");
33768
+ }
33769
+ if (path7 !== void 0 && path7 !== null && typeof path7 !== "string") {
33770
+ throw new TypeError("path must be a string, null, or undefined");
33771
+ }
33772
+ if (provider !== void 0 && provider !== null && typeof provider !== "string") {
33773
+ throw new TypeError("provider must be a string, null, or undefined");
33774
+ }
33775
+ if (model !== void 0 && model !== null && typeof model !== "string") {
33776
+ throw new TypeError("model must be a string, null, or undefined");
33777
+ }
33778
+ if (debug) {
33779
+ console.error(`Executing delegate with task: "${task.substring(0, 100)}${task.length > 100 ? "..." : ""}"`);
33780
+ if (parentSessionId) {
33781
+ console.error(`Parent session: ${parentSessionId}`);
33782
+ }
33783
+ }
33784
+ const result = await delegate({
33785
+ task,
33786
+ timeout,
33787
+ debug,
33788
+ currentIteration: currentIteration || 0,
33789
+ maxIterations: maxIterations || 30,
33790
+ parentSessionId,
33791
+ path: path7,
33792
+ provider,
33793
+ model,
33794
+ tracer
33795
+ });
33796
+ return result;
33646
33797
  }
33647
33798
  });
33648
33799
  };
@@ -34525,7 +34676,7 @@ async function executeBashCommand(command, options = {}) {
34525
34676
  return;
34526
34677
  }
34527
34678
  const [cmd, ...cmdArgs] = args;
34528
- const child = (0, import_child_process7.spawn)(cmd, cmdArgs, {
34679
+ const child = (0, import_child_process6.spawn)(cmd, cmdArgs, {
34529
34680
  cwd,
34530
34681
  env: processEnv,
34531
34682
  stdio: ["ignore", "pipe", "pipe"],
@@ -34709,11 +34860,11 @@ function validateExecutionOptions(options = {}) {
34709
34860
  warnings
34710
34861
  };
34711
34862
  }
34712
- var import_child_process7, import_path4, import_fs;
34863
+ var import_child_process6, import_path4, import_fs;
34713
34864
  var init_bashExecutor = __esm({
34714
34865
  "src/agent/bashExecutor.js"() {
34715
34866
  "use strict";
34716
- import_child_process7 = require("child_process");
34867
+ import_child_process6 = require("child_process");
34717
34868
  import_path4 = require("path");
34718
34869
  import_fs = require("fs");
34719
34870
  init_bashCommandUtils();
@@ -35145,15 +35296,15 @@ function shouldIgnore(filePath, ignorePatterns) {
35145
35296
  }
35146
35297
  return false;
35147
35298
  }
35148
- var import_fs2, import_path6, import_util11, import_child_process8, execAsync3;
35299
+ var import_fs2, import_path6, import_util11, import_child_process7, execAsync3;
35149
35300
  var init_file_lister = __esm({
35150
35301
  "src/utils/file-lister.js"() {
35151
35302
  "use strict";
35152
35303
  import_fs2 = __toESM(require("fs"), 1);
35153
35304
  import_path6 = __toESM(require("path"), 1);
35154
35305
  import_util11 = require("util");
35155
- import_child_process8 = require("child_process");
35156
- execAsync3 = (0, import_util11.promisify)(import_child_process8.exec);
35306
+ import_child_process7 = require("child_process");
35307
+ execAsync3 = (0, import_util11.promisify)(import_child_process7.exec);
35157
35308
  }
35158
35309
  });
35159
35310
 
@@ -41910,12 +42061,12 @@ function createWrappedTools(baseTools) {
41910
42061
  }
41911
42062
  return wrappedTools;
41912
42063
  }
41913
- var import_child_process9, import_util12, import_crypto3, import_events, import_fs5, import_fs6, import_path8, toolCallEmitter, activeToolExecutions, wrapToolWithEmitter, listFilesTool, searchFilesTool, listFilesToolInstance, searchFilesToolInstance;
42064
+ var import_child_process8, import_util12, import_crypto3, import_events, import_fs5, import_fs6, import_path8, toolCallEmitter, activeToolExecutions, wrapToolWithEmitter, listFilesTool, searchFilesTool, listFilesToolInstance, searchFilesToolInstance;
41914
42065
  var init_probeTool = __esm({
41915
42066
  "src/agent/probeTool.js"() {
41916
42067
  "use strict";
41917
42068
  init_index();
41918
- import_child_process9 = require("child_process");
42069
+ import_child_process8 = require("child_process");
41919
42070
  import_util12 = require("util");
41920
42071
  import_crypto3 = require("crypto");
41921
42072
  import_events = require("events");
@@ -55476,13 +55627,24 @@ function mapFlowchartParserError(err, text) {
55476
55627
  length: len
55477
55628
  };
55478
55629
  }
55479
- if (tokType === "QuotedString") {
55630
+ if (tokType === "QuotedString" || tokType === "SquareOpen" || tokType === "SquareClose") {
55480
55631
  const context = err?.context;
55481
55632
  const inLinkRule = context?.ruleStack?.includes("linkTextInline") || context?.ruleStack?.includes("link") || false;
55482
55633
  const lineContent = allLines[Math.max(0, line - 1)] || "";
55483
55634
  const beforeQuote = lineContent.slice(0, Math.max(0, column - 1));
55484
55635
  const hasLinkBefore = beforeQuote.match(/--\s*$|==\s*$|-\.\s*$|-\.-\s*$|\[\s*$/);
55485
55636
  if (inLinkRule || hasLinkBefore) {
55637
+ if (tokType === "SquareOpen" || tokType === "SquareClose") {
55638
+ return {
55639
+ line,
55640
+ column,
55641
+ severity: "error",
55642
+ code: "FL-EDGE-LABEL-BRACKET",
55643
+ message: "Square brackets [ ] are not supported inside inline edge labels.",
55644
+ hint: "Use HTML entities &#91; and &#93; inside |...|, e.g., --|run: &#91;aggregate&#93;|-->",
55645
+ length: len
55646
+ };
55647
+ }
55486
55648
  const quotedText = found.startsWith('"') ? found.slice(1, -1) : found;
55487
55649
  return {
55488
55650
  line,
@@ -55576,7 +55738,7 @@ function mapFlowchartParserError(err, text) {
55576
55738
  }
55577
55739
  }
55578
55740
  }
55579
- if (tokType === "QuotedString") {
55741
+ if (tokType === "QuotedString" || tokType === "SquareOpen" || tokType === "SquareClose") {
55580
55742
  return {
55581
55743
  line,
55582
55744
  column,
@@ -55597,7 +55759,7 @@ function mapFlowchartParserError(err, text) {
55597
55759
  return { line, column, severity: "error", code: "FL-NODE-UNCLOSED-BRACKET", message: "Unclosed '['. Add a matching ']' before the arrow or newline.", hint: "Example: A[Label] --> B", length: 1 };
55598
55760
  }
55599
55761
  if (expecting(err, "RoundClose")) {
55600
- if (tokType === "QuotedString") {
55762
+ if (tokType === "QuotedString" || tokType === "SquareOpen" || tokType === "SquareClose") {
55601
55763
  return {
55602
55764
  line,
55603
55765
  column,
@@ -55636,7 +55798,7 @@ function mapFlowchartParserError(err, text) {
55636
55798
  return { line, column, severity: "error", code: "FL-NODE-UNCLOSED-BRACKET", message: "Unclosed '('. Add a matching ')'.", hint: "Example: B(Label)", length: 1 };
55637
55799
  }
55638
55800
  if (expecting(err, "DiamondClose")) {
55639
- if (tokType === "QuotedString") {
55801
+ if (tokType === "QuotedString" || tokType === "SquareOpen" || tokType === "SquareClose") {
55640
55802
  return {
55641
55803
  line,
55642
55804
  column,
@@ -56482,6 +56644,53 @@ function validateFlowchart(text, options = {}) {
56482
56644
  }
56483
56645
  }
56484
56646
  }
56647
+ {
56648
+ const byLine = /* @__PURE__ */ new Map();
56649
+ const collect = (arr) => {
56650
+ for (const e3 of arr || []) {
56651
+ if (e3 && e3.code === "FL-LABEL-PARENS-UNQUOTED") {
56652
+ const ln = e3.line ?? 0;
56653
+ const col = e3.column ?? 1;
56654
+ const list2 = byLine.get(ln) || [];
56655
+ list2.push(col);
56656
+ byLine.set(ln, list2);
56657
+ }
56658
+ }
56659
+ };
56660
+ collect(prevErrors);
56661
+ collect(errs);
56662
+ const lines2 = text2.split(/\r?\n/);
56663
+ for (let ii = 0; ii < lines2.length; ii++) {
56664
+ const raw2 = lines2[ii] || "";
56665
+ if (!raw2.includes("[") || !raw2.includes("]"))
56666
+ continue;
56667
+ let search2 = 0;
56668
+ while (true) {
56669
+ const open2 = raw2.indexOf("[", search2);
56670
+ if (open2 === -1)
56671
+ break;
56672
+ const close2 = raw2.indexOf("]", open2 + 1);
56673
+ if (close2 === -1)
56674
+ break;
56675
+ const seg2 = raw2.slice(open2 + 1, close2);
56676
+ const trimmed2 = seg2.trim();
56677
+ const ln2 = ii + 1;
56678
+ const lsp = trimmed2.slice(0, 1);
56679
+ const rsp = trimmed2.slice(-1);
56680
+ const isSlashPair = (lsp === "/" || lsp === "\\") && (rsp === "/" || rsp === "\\");
56681
+ const isParenWrapped = lsp === "(" && rsp === ")";
56682
+ const segStartCol = open2 + 2;
56683
+ const segEndCol = close2 + 1;
56684
+ const existing = byLine.get(ln2) || [];
56685
+ const covered = existing.some((c3) => c3 >= segStartCol && c3 <= segEndCol);
56686
+ if (!covered && !/^".*"$/.test(trimmed2) && (seg2.includes("(") || seg2.includes(")")) && !isSlashPair && !isParenWrapped) {
56687
+ errs.push({ line: ln2, column: segStartCol, severity: "error", code: "FL-LABEL-PARENS-UNQUOTED", message: "Parentheses inside an unquoted label are not supported by Mermaid.", hint: 'Wrap the label in quotes, e.g., A["Mark (X)"] \u2014 or replace ( and ) with HTML entities: &#40; and &#41;.' });
56688
+ byLine.set(ln2, existing.concat([segStartCol]));
56689
+ }
56690
+ search2 = close2 + 1;
56691
+ }
56692
+ }
56693
+ }
56485
56694
  const dblEsc = (text2.match(/\\\"/g) || []).length;
56486
56695
  const dq = (text2.match(/\"/g) || []).length - dblEsc;
56487
56696
  const sq = (text2.match(/'/g) || []).length;
@@ -58826,6 +59035,21 @@ function computeFixes(text, errors, level = "safe") {
58826
59035
  }
58827
59036
  continue;
58828
59037
  }
59038
+ if (is("FL-EDGE-LABEL-BRACKET", e3)) {
59039
+ const lineText = lineTextAt(text, e3.line);
59040
+ const firstBar = lineText.indexOf("|");
59041
+ const secondBar = firstBar >= 0 ? lineText.indexOf("|", firstBar + 1) : -1;
59042
+ if (firstBar >= 0 && secondBar > firstBar) {
59043
+ const before = lineText.slice(0, firstBar + 1);
59044
+ const label = lineText.slice(firstBar + 1, secondBar);
59045
+ const after = lineText.slice(secondBar);
59046
+ const fixedLabel = label.replace(/\[/g, "&#91;").replace(/\]/g, "&#93;");
59047
+ const fixedLine = before + fixedLabel + after;
59048
+ const finalLine = fixedLine.replace(/\[([^\]]*)\]/g, (m3, seg) => "[" + String(seg).replace(/`/g, "") + "]");
59049
+ edits.push({ start: { line: e3.line, column: 1 }, end: { line: e3.line, column: lineText.length + 1 }, newText: finalLine });
59050
+ }
59051
+ continue;
59052
+ }
58829
59053
  if (is("FL-EDGE-LABEL-BACKTICK", e3)) {
58830
59054
  const lineText = lineTextAt(text, e3.line);
58831
59055
  const re = /^(.*?--)\s*([^|>]+?)\s*(-->|==>|\.->|->)(.*)$/;
@@ -80981,6 +81205,7 @@ var init_ProbeAgent = __esm({
80981
81205
  * @param {string} [options.customPrompt] - Custom prompt to replace the default system message
80982
81206
  * @param {string} [options.promptType] - Predefined prompt type (architect, code-review, support)
80983
81207
  * @param {boolean} [options.allowEdit=false] - Allow the use of the 'implement' tool
81208
+ * @param {boolean} [options.enableDelegate=false] - Enable the delegate tool for task distribution to subagents
80984
81209
  * @param {string} [options.path] - Search directory path
80985
81210
  * @param {string} [options.provider] - Force specific AI provider
80986
81211
  * @param {string} [options.model] - Override model name
@@ -81002,6 +81227,7 @@ var init_ProbeAgent = __esm({
81002
81227
  this.customPrompt = options.customPrompt || null;
81003
81228
  this.promptType = options.promptType || "code-explorer";
81004
81229
  this.allowEdit = !!options.allowEdit;
81230
+ this.enableDelegate = !!options.enableDelegate;
81005
81231
  this.debug = options.debug || process.env.DEBUG === "1";
81006
81232
  this.cancelled = false;
81007
81233
  this.tracer = options.tracer || null;
@@ -81596,6 +81822,10 @@ ${attemptCompletionToolDefinition}
81596
81822
  `;
81597
81823
  if (this.allowEdit) {
81598
81824
  toolDefinitions += `${implementToolDefinition}
81825
+ `;
81826
+ }
81827
+ if (this.enableDelegate) {
81828
+ toolDefinitions += `${delegateToolDefinition}
81599
81829
  `;
81600
81830
  }
81601
81831
  let xmlToolGuidelines = `
@@ -81659,7 +81889,7 @@ Available Tools:
81659
81889
  - extract: Extract specific code blocks or lines from files.
81660
81890
  - listFiles: List files and directories in a specified location.
81661
81891
  - searchFiles: Find files matching a glob pattern with recursive search capability.
81662
- ${this.allowEdit ? "- implement: Implement a feature or fix a bug using aider.\n" : ""}
81892
+ ${this.allowEdit ? "- implement: Implement a feature or fix a bug using aider.\n" : ""}${this.enableDelegate ? "- delegate: Delegate big distinct tasks to specialized probe subagents.\n" : ""}
81663
81893
  - attempt_completion: Finalize the task and provide the result to the user.
81664
81894
  - attempt_complete: Quick completion using previous response (shorthand).
81665
81895
  `;
@@ -81979,6 +82209,9 @@ You are working with a repository located at: ${searchDirectory}
81979
82209
  if (this.allowEdit) {
81980
82210
  validTools.push("implement");
81981
82211
  }
82212
+ if (this.enableDelegate) {
82213
+ validTools.push("delegate");
82214
+ }
81982
82215
  const nativeTools = validTools;
81983
82216
  const parsedTool = this.mcpBridge ? parseHybridXmlToolCall(assistantResponseContent, nativeTools, this.mcpBridge) : parseXmlToolCallWithThinking(assistantResponseContent, validTools);
81984
82217
  if (parsedTool) {
@@ -82092,11 +82325,21 @@ ${toolResultContent}
82092
82325
  ...toolParams,
82093
82326
  currentIteration,
82094
82327
  maxIterations,
82328
+ parentSessionId: this.sessionId,
82329
+ // Pass parent session ID for tracking
82330
+ path: this.searchPath,
82331
+ // Inherit search path
82332
+ provider: this.provider,
82333
+ // Inherit AI provider
82334
+ model: this.model,
82335
+ // Inherit model
82095
82336
  debug: this.debug,
82096
82337
  tracer: this.tracer
82097
82338
  };
82098
82339
  if (this.debug) {
82099
82340
  console.log(`[DEBUG] Executing delegate tool at iteration ${currentIteration}/${maxIterations}`);
82341
+ console.log(`[DEBUG] Parent session: ${this.sessionId}`);
82342
+ console.log(`[DEBUG] Inherited config: path=${this.searchPath}, provider=${this.provider}, model=${this.model}`);
82100
82343
  console.log(`[DEBUG] Delegate task: ${toolParams.task?.substring(0, 100)}...`);
82101
82344
  }
82102
82345
  if (this.tracer) {
@@ -82687,6 +82930,7 @@ Convert your previous response content into actual JSON data that follows this s
82687
82930
  customPrompt: this.customPrompt,
82688
82931
  promptType: this.promptType,
82689
82932
  allowEdit: this.allowEdit,
82933
+ enableDelegate: this.enableDelegate,
82690
82934
  path: this.allowedFolders[0],
82691
82935
  // Use first allowed folder as primary path
82692
82936
  allowedFolders: [...this.allowedFolders],