wave-agent-sdk 0.8.2 → 0.8.4

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 (55) hide show
  1. package/dist/agent.js +2 -2
  2. package/dist/constants/tools.d.ts +1 -2
  3. package/dist/constants/tools.d.ts.map +1 -1
  4. package/dist/constants/tools.js +1 -2
  5. package/dist/managers/permissionManager.d.ts.map +1 -1
  6. package/dist/managers/permissionManager.js +49 -36
  7. package/dist/managers/pluginManager.d.ts.map +1 -1
  8. package/dist/managers/pluginManager.js +28 -1
  9. package/dist/managers/subagentManager.d.ts +3 -3
  10. package/dist/managers/subagentManager.d.ts.map +1 -1
  11. package/dist/managers/subagentManager.js +13 -12
  12. package/dist/managers/toolManager.d.ts +2 -2
  13. package/dist/managers/toolManager.d.ts.map +1 -1
  14. package/dist/managers/toolManager.js +4 -6
  15. package/dist/prompts/index.d.ts.map +1 -1
  16. package/dist/prompts/index.js +3 -3
  17. package/dist/tools/agentTool.d.ts +6 -0
  18. package/dist/tools/agentTool.d.ts.map +1 -0
  19. package/dist/tools/{taskTool.js → agentTool.js} +42 -30
  20. package/dist/tools/grepTool.js +2 -2
  21. package/dist/tools/skillTool.js +2 -2
  22. package/dist/tools/types.d.ts +1 -1
  23. package/dist/tools/types.d.ts.map +1 -1
  24. package/dist/utils/bashParser.d.ts +4 -0
  25. package/dist/utils/bashParser.d.ts.map +1 -1
  26. package/dist/utils/bashParser.js +39 -2
  27. package/dist/utils/builtinSubagents.d.ts.map +1 -1
  28. package/dist/utils/builtinSubagents.js +1 -3
  29. package/dist/utils/gitUtils.d.ts.map +1 -1
  30. package/dist/utils/gitUtils.js +47 -1
  31. package/dist/utils/path.d.ts +0 -10
  32. package/dist/utils/path.d.ts.map +1 -1
  33. package/dist/utils/path.js +0 -61
  34. package/package.json +2 -5
  35. package/src/agent.ts +2 -2
  36. package/src/constants/tools.ts +1 -2
  37. package/src/managers/permissionManager.ts +61 -44
  38. package/src/managers/pluginManager.ts +39 -1
  39. package/src/managers/subagentManager.ts +13 -12
  40. package/src/managers/toolManager.ts +4 -6
  41. package/src/prompts/index.ts +3 -2
  42. package/src/tools/{taskTool.ts → agentTool.ts} +42 -30
  43. package/src/tools/grepTool.ts +2 -2
  44. package/src/tools/skillTool.ts +2 -2
  45. package/src/tools/types.ts +1 -1
  46. package/src/utils/bashParser.ts +50 -2
  47. package/src/utils/builtinSubagents.ts +0 -3
  48. package/src/utils/gitUtils.ts +48 -1
  49. package/src/utils/path.ts +0 -62
  50. package/dist/tools/lsTool.d.ts +0 -6
  51. package/dist/tools/lsTool.d.ts.map +0 -1
  52. package/dist/tools/lsTool.js +0 -175
  53. package/dist/tools/taskTool.d.ts +0 -6
  54. package/dist/tools/taskTool.d.ts.map +0 -1
  55. package/src/tools/lsTool.ts +0 -212
@@ -20,6 +20,7 @@ import {
20
20
  splitBashCommand,
21
21
  stripEnvVars,
22
22
  stripRedirections,
23
+ hasWriteRedirections,
23
24
  getSmartPrefix,
24
25
  DANGEROUS_COMMANDS,
25
26
  } from "../utils/bashParser.js";
@@ -29,7 +30,6 @@ import {
29
30
  EDIT_TOOL_NAME,
30
31
  WRITE_TOOL_NAME,
31
32
  READ_TOOL_NAME,
32
- LS_TOOL_NAME,
33
33
  } from "../constants/tools.js";
34
34
  import { Container } from "../utils/container.js";
35
35
  import { ConfigurationService } from "../services/configurationService.js";
@@ -464,6 +464,9 @@ export class PermissionManager {
464
464
  const parts = splitBashCommand(command);
465
465
 
466
466
  const isDangerous = parts.some((part) => {
467
+ if (hasWriteRedirections(part)) {
468
+ return true;
469
+ }
467
470
  const processedPart = stripRedirections(stripEnvVars(part));
468
471
  const commandMatch = processedPart.match(/^(\w+)(\s+.*)?$/);
469
472
  if (commandMatch) {
@@ -523,7 +526,17 @@ export class PermissionManager {
523
526
  // Handle Bash command rules
524
527
  if (toolName === BASH_TOOL_NAME) {
525
528
  const command = String(context.toolInput?.command || "");
526
- const processedPart = stripRedirections(stripEnvVars(command));
529
+ const hasWriteInPattern = hasWriteRedirections(pattern);
530
+ const hasWriteInCommand = hasWriteRedirections(command);
531
+
532
+ // If the command has write redirections, it must match a pattern that also has write redirections
533
+ if (hasWriteInCommand && !hasWriteInPattern) {
534
+ return false;
535
+ }
536
+
537
+ const processedPart = hasWriteInPattern
538
+ ? stripEnvVars(command)
539
+ : stripRedirections(stripEnvVars(command));
527
540
  // For Bash commands, we want '*' to match everything including slashes and spaces
528
541
  // minimatch's default behavior for '*' is to not match across directory separators
529
542
  // We use a regex to replace '*' with '.*' (match anything)
@@ -536,12 +549,7 @@ export class PermissionManager {
536
549
  }
537
550
 
538
551
  // Handle path-based rules (e.g., "Read(**/*.env)")
539
- const pathTools = [
540
- READ_TOOL_NAME,
541
- WRITE_TOOL_NAME,
542
- EDIT_TOOL_NAME,
543
- LS_TOOL_NAME,
544
- ];
552
+ const pathTools = [READ_TOOL_NAME, WRITE_TOOL_NAME, EDIT_TOOL_NAME];
545
553
  if (pathTools.includes(toolName)) {
546
554
  const targetPath = (context.toolInput?.file_path ||
547
555
  context.toolInput?.path) as string | undefined;
@@ -561,6 +569,7 @@ export class PermissionManager {
561
569
  const isAllowedByRuleList = (
562
570
  ctx: ToolPermissionContext,
563
571
  rules: string[],
572
+ isDefaultRules: boolean = false,
564
573
  ) => {
565
574
  if (ctx.toolName === BASH_TOOL_NAME && ctx.toolInput?.command) {
566
575
  const command = String(ctx.toolInput.command);
@@ -570,53 +579,60 @@ export class PermissionManager {
570
579
  const workdir = ctx.toolInput?.workdir as string | undefined;
571
580
 
572
581
  return parts.every((part) => {
582
+ const hasWrite = hasWriteRedirections(part);
573
583
  const processedPart = stripRedirections(stripEnvVars(part));
574
584
 
575
585
  // Check for safe commands
576
- const commandMatch = processedPart.match(/^(\w+)(\s+.*)?$/);
577
- if (commandMatch) {
578
- const cmd = commandMatch[1];
579
- const args = commandMatch[2]?.trim() || "";
580
-
581
- if (SAFE_COMMANDS.includes(cmd)) {
582
- if (cmd === "pwd" || cmd === "true" || cmd === "false") {
583
- return true;
584
- }
585
-
586
- if (workdir) {
587
- // For cd and ls, check paths
588
- const pathArgs =
589
- (args.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || []).filter(
590
- (arg) => !arg.startsWith("-"),
591
- ) || [];
592
-
593
- if (pathArgs.length === 0) {
594
- // cd or ls without arguments operates on current dir (workdir)
586
+ if (!hasWrite) {
587
+ const commandMatch = processedPart.match(/^(\w+)(\s+.*)?$/);
588
+ if (commandMatch) {
589
+ const cmd = commandMatch[1];
590
+ const args = commandMatch[2]?.trim() || "";
591
+
592
+ if (SAFE_COMMANDS.includes(cmd)) {
593
+ if (cmd === "pwd" || cmd === "true" || cmd === "false") {
595
594
  return true;
596
595
  }
597
596
 
598
- const allPathsSafe = pathArgs.every((pathArg) => {
599
- // Remove quotes if present
600
- const cleanPath = pathArg.replace(/^['"](.*)['"]$/, "$1");
601
- const { isInside } = this.isInsideSafeZone(
602
- cleanPath,
603
- workdir,
604
- );
605
- return isInside;
606
- });
607
-
608
- if (allPathsSafe) {
609
- return true;
597
+ if (workdir) {
598
+ // For cd and ls, check paths
599
+ const pathArgs =
600
+ (args.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || []).filter(
601
+ (arg) => !arg.startsWith("-"),
602
+ ) || [];
603
+
604
+ if (pathArgs.length === 0) {
605
+ // cd or ls without arguments operates on current dir (workdir)
606
+ return true;
607
+ }
608
+
609
+ const allPathsSafe = pathArgs.every((pathArg) => {
610
+ // Remove quotes if present
611
+ const cleanPath = pathArg.replace(/^['"](.*)['"]$/, "$1");
612
+ const { isInside } = this.isInsideSafeZone(
613
+ cleanPath,
614
+ workdir,
615
+ );
616
+ return isInside;
617
+ });
618
+
619
+ if (allPathsSafe) {
620
+ return true;
621
+ }
610
622
  }
611
623
  }
612
624
  }
613
625
  }
614
626
 
615
627
  // Check if this specific part is allowed by any rule
628
+ if (hasWrite && isDefaultRules) {
629
+ return false;
630
+ }
631
+
616
632
  // We create a temporary context with just this part of the command
617
633
  const partContext = {
618
634
  ...ctx,
619
- toolInput: { ...ctx.toolInput, command: processedPart },
635
+ toolInput: { ...ctx.toolInput, command: part },
620
636
  };
621
637
  const allowedByRule = rules.some((rule) => {
622
638
  return this.matchesRule(partContext, rule);
@@ -643,7 +659,7 @@ export class PermissionManager {
643
659
  }
644
660
 
645
661
  // Check default allowed rules
646
- return isAllowedByRuleList(context, DEFAULT_ALLOWED_RULES);
662
+ return isAllowedByRuleList(context, DEFAULT_ALLOWED_RULES, true);
647
663
  }
648
664
 
649
665
  /**
@@ -659,13 +675,14 @@ export class PermissionManager {
659
675
  const rules: string[] = [];
660
676
 
661
677
  for (const part of parts) {
678
+ const hasWrite = hasWriteRedirections(part);
662
679
  const processedPart = stripRedirections(stripEnvVars(part));
663
680
 
664
681
  // Check for safe commands
665
682
  const commandMatch = processedPart.match(/^(\w+)(\s+.*)?$/);
666
683
  let isSafe = false;
667
684
 
668
- if (commandMatch) {
685
+ if (commandMatch && !hasWrite) {
669
686
  const cmd = commandMatch[1];
670
687
  const args = commandMatch[2]?.trim() || "";
671
688
 
@@ -724,11 +741,11 @@ export class PermissionManager {
724
741
  }
725
742
  }
726
743
 
727
- const smartPrefix = getSmartPrefix(processedPart);
744
+ const smartPrefix = hasWrite ? null : getSmartPrefix(processedPart);
728
745
  if (smartPrefix) {
729
746
  rules.push(`Bash(${smartPrefix}*)`);
730
747
  } else {
731
- rules.push(`Bash(${processedPart})`);
748
+ rules.push(`Bash(${hasWrite ? stripEnvVars(part) : processedPart})`);
732
749
  }
733
750
  }
734
751
  }
@@ -73,7 +73,45 @@ export class PluginManager {
73
73
  }
74
74
 
75
75
  const marketplaceService = new MarketplaceService();
76
- const installedRegistry = await marketplaceService.getInstalledPlugins();
76
+ let installedRegistry = await marketplaceService.getInstalledPlugins();
77
+ const knownMarketplaces = await marketplaceService.listMarketplaces();
78
+
79
+ // Identify missing enabled plugins and auto-install them if marketplace is known
80
+ for (const pluginId of Object.keys(this.enabledPlugins)) {
81
+ if (this.enabledPlugins[pluginId] !== true) continue;
82
+
83
+ const [name, marketplaceName] = pluginId.split("@");
84
+ if (!name || !marketplaceName) continue;
85
+
86
+ const isInstalled = installedRegistry.plugins.some(
87
+ (p) => p.name === name && p.marketplace === marketplaceName,
88
+ );
89
+
90
+ if (!isInstalled) {
91
+ const isMarketplaceKnown = knownMarketplaces.some(
92
+ (m) => m.name === marketplaceName,
93
+ );
94
+
95
+ if (isMarketplaceKnown) {
96
+ logger?.info(`Auto-installing missing plugin: ${pluginId}`);
97
+ try {
98
+ await marketplaceService.installPlugin(pluginId);
99
+ } catch (installError) {
100
+ logger?.error(
101
+ `Failed to auto-install plugin ${pluginId}:`,
102
+ installError,
103
+ );
104
+ }
105
+ } else {
106
+ logger?.warn(
107
+ `Plugin ${pluginId} is enabled but marketplace ${marketplaceName} is unknown. Skipping auto-install.`,
108
+ );
109
+ }
110
+ }
111
+ }
112
+
113
+ // Refresh registry after potential auto-installs
114
+ installedRegistry = await marketplaceService.getInstalledPlugins();
77
115
 
78
116
  for (const p of installedRegistry.plugins) {
79
117
  const pluginId = `${p.name}@${p.marketplace}`;
@@ -9,6 +9,7 @@ import type {
9
9
  import { AIManager } from "./aiManager.js";
10
10
  import { MessageManager } from "./messageManager.js";
11
11
  import { ToolManager } from "./toolManager.js";
12
+ import { AGENT_TOOL_NAME } from "../constants/tools.js";
12
13
  import {
13
14
  addConsolidatedAbortListener,
14
15
  createAbortPromise,
@@ -287,12 +288,12 @@ export class SubagentManager {
287
288
  }
288
289
 
289
290
  /**
290
- * Execute task using subagent instance
291
+ * Execute agent using subagent instance
291
292
  *
292
- * IMPORTANT: This method automatically filters out the Task tool from allowedTools
293
+ * IMPORTANT: This method automatically filters out the Agent tool from allowedTools
293
294
  * to prevent subagents from spawning other subagents (infinite recursion protection)
294
295
  */
295
- async executeTask(
296
+ async executeAgent(
296
297
  instance: SubagentInstance,
297
298
  prompt: string,
298
299
  abortSignal?: AbortSignal,
@@ -301,7 +302,7 @@ export class SubagentManager {
301
302
  try {
302
303
  // Check if already aborted before starting
303
304
  if (abortSignal?.aborted) {
304
- throw new Error("Task was aborted before execution started");
305
+ throw new Error("Agent was aborted before execution started");
305
306
  }
306
307
 
307
308
  // Set status to active and update parent
@@ -433,17 +434,17 @@ export class SubagentManager {
433
434
  // Add the user's prompt as a message
434
435
  instance.messageManager.addUserMessage({ content: prompt });
435
436
 
436
- // Create enabled tools list - always exclude Task tool to prevent subagent recursion
437
+ // Create enabled tools list - always exclude Agent tool to prevent subagent recursion
437
438
  // Use instance.configuration.tools if provided, otherwise fallback to all tools
438
439
  let enabledTools = instance.configuration.tools;
439
440
 
440
- // Always filter out the Task tool to prevent subagents from creating sub-subagents
441
+ // Always filter out the Agent tool to prevent subagents from creating sub-subagents
441
442
  if (enabledTools) {
442
- enabledTools = enabledTools.filter((tool) => tool !== "Task");
443
+ enabledTools = enabledTools.filter((tool) => tool !== AGENT_TOOL_NAME);
443
444
  } else {
444
- // If no tools specified, get all tools except Task
445
+ // If no tools specified, get all tools except Agent
445
446
  const allTools = instance.toolManager.list().map((tool) => tool.name);
446
- enabledTools = allTools.filter((tool) => tool !== "Task");
447
+ enabledTools = allTools.filter((tool) => tool !== AGENT_TOOL_NAME);
447
448
  }
448
449
 
449
450
  // Execute the AI request with tool restrictions
@@ -476,7 +477,7 @@ export class SubagentManager {
476
477
  if (abortSignal && !instance.backgroundTaskId) {
477
478
  await Promise.race([
478
479
  executeAI,
479
- createAbortPromise(abortSignal, "Task was aborted"),
480
+ createAbortPromise(abortSignal, "Agent was aborted"),
480
481
  ]);
481
482
  } else {
482
483
  await executeAI;
@@ -510,7 +511,7 @@ export class SubagentManager {
510
511
  const task = backgroundTaskManager.getTask(instance.backgroundTaskId);
511
512
  if (task) {
512
513
  task.status = "completed";
513
- task.stdout = response || "Task completed with no text response";
514
+ task.stdout = response || "Agent completed with no text response";
514
515
  task.endTime = Date.now();
515
516
  if (task.startTime) {
516
517
  task.runtime = task.endTime - task.startTime;
@@ -518,7 +519,7 @@ export class SubagentManager {
518
519
  }
519
520
  }
520
521
 
521
- return response || "Task completed with no text response";
522
+ return response || "Agent completed with no text response";
522
523
  } catch (error) {
523
524
  const backgroundTaskManager = this.container.has("BackgroundTaskManager")
524
525
  ? this.container.get<BackgroundTaskManager>("BackgroundTaskManager")
@@ -9,10 +9,9 @@ import { askUserQuestionTool } from "../tools/askUserQuestion.js";
9
9
  // New tools
10
10
  import { globTool } from "../tools/globTool.js";
11
11
  import { grepTool } from "../tools/grepTool.js";
12
- import { lsTool } from "../tools/lsTool.js";
13
12
  import { readTool } from "../tools/readTool.js";
14
13
  import { lspTool } from "../tools/lspTool.js";
15
- import { taskTool } from "../tools/taskTool.js";
14
+ import { agentTool } from "../tools/agentTool.js";
16
15
  import { skillTool } from "../tools/skillTool.js";
17
16
  import {
18
17
  taskCreateTool,
@@ -78,10 +77,10 @@ class ToolManager {
78
77
  *
79
78
  * This method can be called multiple times safely. When called without dependencies,
80
79
  * it registers basic tools (Bash, Read, Write, TaskCreate, etc.). When called with
81
- * dependencies, it also registers tools that require managers (Task, Skill).
80
+ * dependencies, it also registers tools that require managers (Agent, Skill).
82
81
  *
83
82
  * @param deps Optional dependencies for advanced tools
84
- * @param deps.subagentManager SubagentManager instance for Task tool
83
+ * @param deps.subagentManager SubagentManager instance for Agent tool
85
84
  * @param deps.skillManager SkillManager instance for Skill tool
86
85
  *
87
86
  * @example
@@ -107,10 +106,9 @@ class ToolManager {
107
106
  askUserQuestionTool,
108
107
  globTool,
109
108
  grepTool,
110
- lsTool,
111
109
  readTool,
112
110
  lspTool,
113
- taskTool,
111
+ agentTool,
114
112
  skillTool,
115
113
  taskCreateTool,
116
114
  taskGetTool,
@@ -14,6 +14,7 @@ import {
14
14
  READ_TOOL_NAME,
15
15
  WRITE_TOOL_NAME,
16
16
  EXIT_PLAN_MODE_TOOL_NAME,
17
+ AGENT_TOOL_NAME,
17
18
  } from "../constants/tools.js";
18
19
 
19
20
  export const BASE_SYSTEM_PROMPT = `You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.
@@ -61,7 +62,7 @@ You should build your plan incrementally by writing to or editing this file. NOT
61
62
  ## Plan Workflow
62
63
 
63
64
  ### Phase 1: Initial Understanding
64
- Goal: Gain a comprehensive understanding of the user's request by reading through code and asking them questions. Critical: In this phase you should only use the Task subagent type with subagent_type=${EXPLORE_SUBAGENT_TYPE}.
65
+ Goal: Gain a comprehensive understanding of the user's request by reading through code and asking them questions. Critical: In this phase you should only use the ${AGENT_TOOL_NAME} tool with subagent_type=${EXPLORE_SUBAGENT_TYPE}.
65
66
 
66
67
  1. Focus on understanding the user's request and the code associated with their request. Actively search for existing functions, utilities, and patterns that can be reused — avoid proposing new code when suitable implementations already exist.
67
68
 
@@ -74,7 +75,7 @@ Goal: Gain a comprehensive understanding of the user's request by reading throug
74
75
  ### Phase 2: Design
75
76
  Goal: Design an implementation approach.
76
77
 
77
- Launch Task agent(s) with subagent_type=${PLAN_SUBAGENT_TYPE} to design the implementation based on the user's intent and your exploration results from Phase 1.
78
+ Launch agent(s) with subagent_type=${PLAN_SUBAGENT_TYPE} to design the implementation based on the user's intent and your exploration results from Phase 1.
78
79
 
79
80
  You can launch up to 3 agent(s) in parallel.
80
81
 
@@ -1,6 +1,6 @@
1
1
  import type { ToolPlugin, ToolResult, ToolContext } from "./types.js";
2
2
  import { EXPLORE_SUBAGENT_TYPE } from "../constants/subagents.js";
3
- import { TASK_TOOL_NAME } from "../constants/tools.js";
3
+ import { AGENT_TOOL_NAME } from "../constants/tools.js";
4
4
  import type { SubagentConfiguration } from "../utils/subagentParser.js";
5
5
  import {
6
6
  countToolBlocks,
@@ -8,16 +8,16 @@ import {
8
8
  } from "../utils/messageOperations.js";
9
9
 
10
10
  /**
11
- * Task tool plugin for delegating tasks to specialized subagents
11
+ * Agent tool plugin for launching specialized agents to handle complex tasks
12
12
  */
13
- export const taskTool: ToolPlugin = {
14
- name: TASK_TOOL_NAME,
13
+ export const agentTool: ToolPlugin = {
14
+ name: AGENT_TOOL_NAME,
15
15
  config: {
16
16
  type: "function" as const,
17
17
  function: {
18
- name: TASK_TOOL_NAME,
18
+ name: AGENT_TOOL_NAME,
19
19
  description:
20
- "Delegate a task to a specialized subagent. Use this when you need specialized expertise or want to break down complex work into focused subtasks.",
20
+ "Launch a new agent to handle complex, multi-step tasks autonomously.",
21
21
  parameters: {
22
22
  type: "object",
23
23
  properties: {
@@ -47,19 +47,31 @@ export const taskTool: ToolPlugin = {
47
47
  prompt: (args?: { availableSubagents?: SubagentConfiguration[] }) => {
48
48
  const subagentList = args?.availableSubagents
49
49
  ? args.availableSubagents
50
- .map((config) => `- ${config.name}: ${config.description}`)
50
+ .map((config) => {
51
+ let toolsStr = "";
52
+ if (config.tools && config.tools.length > 0) {
53
+ toolsStr = ` (Tools: ${config.tools.join(", ")})`;
54
+ } else {
55
+ toolsStr = " (Tools: *)";
56
+ }
57
+
58
+ return `- ${config.name}: ${config.description}${toolsStr}`;
59
+ })
51
60
  .join("\n")
52
61
  : "";
53
62
 
54
- return `
55
- Delegate a task to a specialized subagent. Use this when you need specialized expertise or want to break down complex work into focused subtasks.
63
+ return `Launch a new agent to handle complex, multi-step tasks autonomously.
64
+
65
+ The Agent tool launches specialized agents (subprocesses) that autonomously handle complex tasks. Each agent type has specific capabilities and tools available to it.
66
+
67
+ Available agent types and the tools they have access to:
68
+ ${subagentList || "No agents configured"}
56
69
 
57
- Available subagents:
58
- ${subagentList || "No subagents configured"}
70
+ When using the Agent tool, you must specify a subagent_type parameter to select which agent type to use.
59
71
 
60
- - When doing file search, prefer to use the ${TASK_TOOL_NAME} tool in order to reduce context usage.
61
- - You should proactively use the ${TASK_TOOL_NAME} tool with specialized agents when the task at hand matches the agent's description.
62
- - VERY IMPORTANT: When exploring the codebase to gather context or to answer a question that is not a needle query for a specific file/class/function, it is CRITICAL that you use the ${TASK_TOOL_NAME} tool with subagent_type=${EXPLORE_SUBAGENT_TYPE} instead of running search commands directly.`;
72
+ - When doing file search, prefer to use the ${AGENT_TOOL_NAME} tool in order to reduce context usage.
73
+ - You should proactively use the ${AGENT_TOOL_NAME} tool with specialized agents when the task at hand matches the agent's description.
74
+ - VERY IMPORTANT: When exploring the codebase to gather context or to answer a question that is not a needle query for a specific file/class/function, it is CRITICAL that you use the ${AGENT_TOOL_NAME} tool with subagent_type=${EXPLORE_SUBAGENT_TYPE} instead of running search commands directly.`;
63
75
  },
64
76
 
65
77
  execute: async (
@@ -72,7 +84,7 @@ ${subagentList || "No subagents configured"}
72
84
  success: false,
73
85
  content: "",
74
86
  error: "Subagent manager not available in tool context",
75
- shortResult: "Task delegation failed",
87
+ shortResult: "Agent delegation failed",
76
88
  };
77
89
  }
78
90
 
@@ -87,7 +99,7 @@ ${subagentList || "No subagents configured"}
87
99
  success: false,
88
100
  content: "",
89
101
  error: "description parameter is required and must be a string",
90
- shortResult: "Task delegation failed",
102
+ shortResult: "Agent delegation failed",
91
103
  };
92
104
  }
93
105
 
@@ -96,7 +108,7 @@ ${subagentList || "No subagents configured"}
96
108
  success: false,
97
109
  content: "",
98
110
  error: "prompt parameter is required and must be a string",
99
- shortResult: "Task delegation failed",
111
+ shortResult: "Agent delegation failed",
100
112
  };
101
113
  }
102
114
 
@@ -105,7 +117,7 @@ ${subagentList || "No subagents configured"}
105
117
  success: false,
106
118
  content: "",
107
119
  error: "subagent_type parameter is required and must be a string",
108
- shortResult: "Task delegation failed",
120
+ shortResult: "Agent delegation failed",
109
121
  };
110
122
  }
111
123
 
@@ -121,14 +133,14 @@ ${subagentList || "No subagents configured"}
121
133
  return {
122
134
  success: false,
123
135
  content: "",
124
- error: `No subagent found matching "${subagent_type}". Available subagents: ${availableNames || "none"}`,
125
- shortResult: "Subagent not found",
136
+ error: `No agent found matching "${subagent_type}". Available agents: ${availableNames || "none"}`,
137
+ shortResult: "Agent not found",
126
138
  };
127
139
  }
128
140
 
129
141
  let isBackgrounded = false;
130
142
 
131
- // Create subagent instance and execute task
143
+ // Create subagent instance and execute agent
132
144
  const instance = await subagentManager.createInstance(
133
145
  configuration,
134
146
  {
@@ -173,8 +185,8 @@ ${subagentList || "No subagents configured"}
173
185
  await subagentManager.backgroundInstance(instance.subagentId);
174
186
  resolve({
175
187
  success: true,
176
- content: "Task backgrounded",
177
- shortResult: "Task backgrounded",
188
+ content: "Agent backgrounded",
189
+ shortResult: "Agent backgrounded",
178
190
  isManuallyBackgrounded: true,
179
191
  });
180
192
  },
@@ -182,7 +194,7 @@ ${subagentList || "No subagents configured"}
182
194
  }
183
195
 
184
196
  try {
185
- const result = await subagentManager.executeTask(
197
+ const result = await subagentManager.executeAgent(
186
198
  instance,
187
199
  prompt,
188
200
  context.abortSignal,
@@ -196,13 +208,13 @@ ${subagentList || "No subagents configured"}
196
208
  if (run_in_background) {
197
209
  resolve({
198
210
  success: true,
199
- content: `Task started in background with ID: ${result}`,
200
- shortResult: `Task started in background: ${result}`,
211
+ content: `Agent started in background with ID: ${result}`,
212
+ shortResult: `Agent started in background: ${result}`,
201
213
  });
202
214
  return;
203
215
  }
204
216
 
205
- // Cleanup subagent instance after task completion
217
+ // Cleanup subagent instance after agent completion
206
218
  subagentManager.cleanupInstance(instance.subagentId);
207
219
 
208
220
  const messages = instance.messageManager.getMessages();
@@ -213,14 +225,14 @@ ${subagentList || "No subagents configured"}
213
225
  resolve({
214
226
  success: true,
215
227
  content: result,
216
- shortResult: `Task completed${summary ? ` ${summary}` : ""}`,
228
+ shortResult: `Agent completed${summary ? ` ${summary}` : ""}`,
217
229
  });
218
230
  } catch (error) {
219
231
  if (!isBackgrounded) {
220
232
  resolve({
221
233
  success: false,
222
234
  content: "",
223
- error: `Task delegation failed: ${error instanceof Error ? error.message : String(error)}`,
235
+ error: `Agent delegation failed: ${error instanceof Error ? error.message : String(error)}`,
224
236
  shortResult: "Delegation error",
225
237
  });
226
238
  }
@@ -237,7 +249,7 @@ ${subagentList || "No subagents configured"}
237
249
  return {
238
250
  success: false,
239
251
  content: "",
240
- error: `Task delegation failed: ${error instanceof Error ? error.message : String(error)}`,
252
+ error: `Agent delegation failed: ${error instanceof Error ? error.message : String(error)}`,
241
253
  shortResult: "Delegation error",
242
254
  };
243
255
  }
@@ -6,7 +6,7 @@ import { getDisplayPath } from "../utils/path.js";
6
6
  import {
7
7
  GREP_TOOL_NAME,
8
8
  BASH_TOOL_NAME,
9
- TASK_TOOL_NAME,
9
+ AGENT_TOOL_NAME,
10
10
  } from "../constants/tools.js";
11
11
 
12
12
  /**
@@ -94,7 +94,7 @@ export const grepTool: ToolPlugin = {
94
94
  - Supports full regex syntax (e.g., "log.*Error", "function\\s+\\w+")
95
95
  - Filter files with glob parameter (e.g., "*.js", "**/*.tsx") or type parameter (e.g., "js", "py", "rust")
96
96
  - Output modes: "content" shows matching lines, "files_with_matches" shows only file paths (default), "count" shows match counts
97
- - Use ${TASK_TOOL_NAME} tool for open-ended searches requiring multiple rounds
97
+ - Use ${AGENT_TOOL_NAME} tool for open-ended searches requiring multiple rounds
98
98
  - Pattern syntax: Uses ripgrep (not grep) - literal braces need escaping (use \`interface\\{\\}\` to find \`interface{}\` in Go code)
99
99
  - Multiline matching: By default patterns match within single lines only. For cross-line patterns like \`struct \\{[\\s\\S]*?field\`, use \`multiline: true\`
100
100
  `,
@@ -155,14 +155,14 @@ export const skillTool: ToolPlugin = {
155
155
  );
156
156
 
157
157
  try {
158
- const result = await subagentManager.executeTask(
158
+ const result = await subagentManager.executeAgent(
159
159
  instance,
160
160
  skillResult.content,
161
161
  context.abortSignal,
162
162
  false,
163
163
  );
164
164
 
165
- // Cleanup subagent instance after task completion
165
+ // Cleanup subagent instance after agent completion
166
166
  subagentManager.cleanupInstance(instance.subagentId);
167
167
 
168
168
  const messages = instance.messageManager.getMessages();
@@ -73,7 +73,7 @@ export interface ToolContext {
73
73
  foregroundTaskManager?: import("../types/processes.js").IForegroundTaskManager;
74
74
  /** Task manager instance for task management */
75
75
  taskManager: import("../services/taskManager.js").TaskManager;
76
- /** Subagent manager instance for task delegation */
76
+ /** Subagent manager instance for agent delegation */
77
77
  subagentManager?: import("../managers/subagentManager.js").SubagentManager;
78
78
  /** Skill manager instance for skill invocation */
79
79
  skillManager?: import("../managers/skillManager.js").SkillManager;