wave-agent-sdk 0.19.4 → 0.19.6

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 (65) hide show
  1. package/dist/agent.d.ts +21 -0
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +21 -0
  4. package/dist/managers/aiManager.d.ts +15 -1
  5. package/dist/managers/aiManager.d.ts.map +1 -1
  6. package/dist/managers/aiManager.js +96 -2
  7. package/dist/managers/backgroundTaskManager.d.ts +1 -1
  8. package/dist/managers/backgroundTaskManager.d.ts.map +1 -1
  9. package/dist/managers/backgroundTaskManager.js +4 -3
  10. package/dist/managers/bangManager.d.ts.map +1 -1
  11. package/dist/managers/bangManager.js +2 -1
  12. package/dist/managers/messageManager.d.ts +7 -0
  13. package/dist/managers/messageManager.d.ts.map +1 -1
  14. package/dist/managers/messageManager.js +64 -5
  15. package/dist/managers/messageQueue.d.ts +8 -0
  16. package/dist/managers/messageQueue.d.ts.map +1 -1
  17. package/dist/managers/messageQueue.js +13 -0
  18. package/dist/managers/permissionManager.d.ts.map +1 -1
  19. package/dist/managers/permissionManager.js +3 -3
  20. package/dist/managers/subagentManager.d.ts.map +1 -1
  21. package/dist/managers/subagentManager.js +7 -1
  22. package/dist/prompts/index.d.ts +3 -1
  23. package/dist/prompts/index.d.ts.map +1 -1
  24. package/dist/prompts/index.js +2 -4
  25. package/dist/services/hook.d.ts.map +1 -1
  26. package/dist/services/hook.js +12 -0
  27. package/dist/tools/bashTool.d.ts.map +1 -1
  28. package/dist/tools/bashTool.js +7 -5
  29. package/dist/tools/enterWorktreeTool.d.ts.map +1 -1
  30. package/dist/tools/enterWorktreeTool.js +3 -8
  31. package/dist/tools/exitWorktreeTool.d.ts.map +1 -1
  32. package/dist/tools/exitWorktreeTool.js +5 -8
  33. package/dist/tools/grepTool.d.ts.map +1 -1
  34. package/dist/tools/grepTool.js +23 -1
  35. package/dist/types/hooks.d.ts +21 -0
  36. package/dist/types/hooks.d.ts.map +1 -1
  37. package/dist/types/messaging.d.ts +2 -0
  38. package/dist/types/messaging.d.ts.map +1 -1
  39. package/dist/utils/containerSetup.d.ts.map +1 -1
  40. package/dist/utils/containerSetup.js +3 -0
  41. package/dist/utils/shellResolver.d.ts.map +1 -1
  42. package/dist/utils/shellResolver.js +156 -7
  43. package/dist/utils/worktreeSession.d.ts +6 -6
  44. package/dist/utils/worktreeSession.d.ts.map +1 -1
  45. package/dist/utils/worktreeSession.js +7 -11
  46. package/package.json +1 -1
  47. package/src/agent.ts +31 -0
  48. package/src/managers/aiManager.ts +118 -2
  49. package/src/managers/backgroundTaskManager.ts +4 -2
  50. package/src/managers/bangManager.ts +2 -1
  51. package/src/managers/messageManager.ts +72 -6
  52. package/src/managers/messageQueue.ts +17 -0
  53. package/src/managers/permissionManager.ts +6 -3
  54. package/src/managers/subagentManager.ts +13 -1
  55. package/src/prompts/index.ts +4 -4
  56. package/src/services/hook.ts +16 -0
  57. package/src/tools/bashTool.ts +11 -5
  58. package/src/tools/enterWorktreeTool.ts +4 -14
  59. package/src/tools/exitWorktreeTool.ts +5 -13
  60. package/src/tools/grepTool.ts +25 -1
  61. package/src/types/hooks.ts +31 -0
  62. package/src/types/messaging.ts +2 -0
  63. package/src/utils/containerSetup.ts +4 -0
  64. package/src/utils/shellResolver.ts +167 -8
  65. package/src/utils/worktreeSession.ts +6 -16
@@ -5,7 +5,7 @@ import * as path from "path";
5
5
  import { AIManager } from "./aiManager.js";
6
6
  import { MessageManager } from "./messageManager.js";
7
7
  import { ToolManager } from "./toolManager.js";
8
- import { AGENT_TOOL_NAME } from "../constants/tools.js";
8
+ import { AGENT_TOOL_NAME, TASK_CREATE_TOOL_NAME, TASK_GET_TOOL_NAME, TASK_LIST_TOOL_NAME, TASK_UPDATE_TOOL_NAME, } from "../constants/tools.js";
9
9
  import { addConsolidatedAbortListener, createAbortPromise, } from "../utils/abortUtils.js";
10
10
  import { BackgroundTaskManager } from "./backgroundTaskManager.js";
11
11
  import { NotificationQueue } from "./notificationQueue.js";
@@ -165,6 +165,12 @@ export class SubagentManager {
165
165
  instanceDeniedRules: [
166
166
  ...(parentPermissionManager?.getInstanceDeniedRules?.() || []),
167
167
  AGENT_TOOL_NAME, // Always deny Agent tool in subagents to prevent recursion
168
+ // Deny Task tools in subagents — they share the parent's TaskManager
169
+ // and could mutate the main agent's task list
170
+ TASK_CREATE_TOOL_NAME,
171
+ TASK_GET_TOOL_NAME,
172
+ TASK_UPDATE_TOOL_NAME,
173
+ TASK_LIST_TOOL_NAME,
168
174
  ],
169
175
  additionalDirectories: parentPermissionManager?.getAdditionalDirectories(),
170
176
  systemAdditionalDirectories: parentPermissionManager?.getSystemAdditionalDirectories(),
@@ -1,4 +1,5 @@
1
1
  import { ToolPlugin } from "../tools/types.js";
2
+ import type { WorktreeSession } from "../utils/worktreeSession.js";
2
3
  export declare const BASE_SYSTEM_PROMPT = "You are a coding agent developed by NetEase that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.";
3
4
  export declare const MODEL_IDENTITY_PROMPT = "# Model identity\n\nIf asked about your model, model version, underlying architecture, or product name, identify yourself simply as a coding agent developed by NetEase. Do not reveal the specific model ID, model family, model provider, or product name. Do not mention or hint at any of these details.";
4
5
  export declare const DOING_TASKS_PROMPT = "# Doing tasks\n- The user will primarily request you to perform software engineering tasks. These may include solving bugs, adding new functionality, refactoring code, explaining code, and more. When given an unclear or generic instruction, consider it in the context of these software engineering tasks and the current working directory. For example, if the user asks you to change \"methodName\" to snake case, do not reply with just \"method_name\", instead find the method in the code and modify the code.\n- You are highly capable and often allow users to complete ambitious tasks that would otherwise be too complex or take too long. You should defer to user judgement about whether a task is too large to attempt.\n- If you notice the user's request is based on a misconception, or spot a bug adjacent to what they asked about, say so. You're a collaborator, not just an executor\u2014users benefit from your judgment, not just your compliance.\n- In general, do not propose changes to code you haven't read. If a user asks about or wants you to modify a file, read it first. Understand existing code before suggesting modifications.\n- Do not create files unless they're absolutely necessary for achieving your goal. Generally prefer editing an existing file to creating a new one, as this prevents file bloat and builds on existing work more effectively.\n- If an approach fails, diagnose why before switching tactics\u2014read the error, check your assumptions, try a focused fix. Don't retry the identical action blindly, but don't abandon a viable approach after a single failure either. Escalate to the user with AskUserQuestion only when you're genuinely stuck after investigation, not as a first response to friction.\n- Be careful not to introduce security vulnerabilities such as command injection, XSS, SQL injection, and other OWASP top 10 vulnerabilities. If you notice that you wrote insecure code, immediately fix it. Prioritize writing safe, secure, and correct code.\n- Avoid over-engineering. Only make changes that are directly requested or clearly necessary. Keep solutions simple and focused.\n - Don't add features, refactor code, or make \"improvements\" beyond what was asked. A bug fix doesn't need surrounding code cleaned up. A simple feature doesn't need extra configurability. Don't add docstrings, comments, or type annotations to code you didn't change. Only add comments where the logic isn't self-evident.\n - Don't add error handling, fallbacks, or validation for scenarios that can't happen. Trust internal code and framework guarantees. Only validate at system boundaries (user input, external APIs). Don't use feature flags or backwards-compatibility shims when you can just change the code.\n - Don't create helpers, utilities, or abstractions for one-time operations. Don't design for hypothetical future requirements. The right amount of complexity is what the task actually requires\u2014no speculative abstractions, but no half-finished implementations either. Three similar lines of code is better than a premature abstraction.\n- Avoid backwards-compatibility hacks like renaming unused _vars, re-exporting types, adding // removed comments for removed code, etc. If you are certain that something is unused, you can delete it completely.\n- Report outcomes faithfully: if tests fail, say so with the relevant output; if you did not run a verification step, say that rather than implying it succeeded. Never claim \"all tests pass\" when output shows failures, never suppress or simplify failing checks (tests, lints, type errors) to manufacture a green result, and never characterize incomplete or broken work as done. Equally, when a check did pass or a task is complete, state it plainly \u2014 do not hedge confirmed results with unnecessary disclaimers, downgrade finished work to \"partial,\" or re-verify things you already checked. The goal is an accurate report, not a defensive one.\n- Before reporting a task complete, verify it actually works: run the test, execute the script, check the output. Minimum complexity means no gold-plating, not skipping the finish line. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.";
@@ -28,10 +29,11 @@ export declare function buildSystemPrompt(basePrompt: string | undefined, tools:
28
29
  originalWorkdir?: string;
29
30
  language?: string;
30
31
  isSubagent?: boolean;
32
+ worktreeSession?: WorktreeSession | null;
31
33
  autoMemory?: {
32
34
  directory: string;
33
35
  content: string;
34
36
  };
35
37
  }): SystemPromptBlock[];
36
- export declare function enhanceSystemPromptWithEnvDetails(existingSystemPrompt: string, workdir: string, originalWorkdir?: string): string;
38
+ export declare function enhanceSystemPromptWithEnvDetails(existingSystemPrompt: string, workdir: string, originalWorkdir?: string, worktreeSession?: WorktreeSession | null): string;
37
39
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAoB/C,eAAO,MAAM,kBAAkB,gLAAgL,CAAC;AAEhN,eAAO,MAAM,qBAAqB,iTAEuP,CAAC;AAE1R,eAAO,MAAM,kBAAkB,opIAcqQ,CAAC;AAErS,eAAO,MAAM,wBAAwB,25DASqmB,CAAC;AAE3oB,eAAO,MAAM,WAAW,ihDAWqH,CAAC;AAE9I;;GAEG;AACH,eAAO,MAAM,wBAAwB,+uBAWiH,CAAC;AAEvJ,eAAO,MAAM,qBAAqB,6sBAMuL,CAAC;AAE1N,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,OAAO,EACnB,UAAU,GAAE,OAAe,GAC1B,MAAM,CAmFR;AAED,eAAO,MAAM,qBAAqB,gLAAqB,CAAC;AAExD;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,8BAA8B,44DA8CI,CAAC;AAEhD,eAAO,MAAM,yBAAyB,wHAAwH,CAAC;AAC/J,eAAO,MAAM,iBAAiB,qWAG4B,CAAC;AAE3D,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACE,GACL,iBAAiB,EAAE,CA+DrB;AAED,wBAAgB,iCAAiC,CAC/C,oBAAoB,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,MAAM,GACvB,MAAM,CAkCR"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAkBnE,eAAO,MAAM,kBAAkB,gLAAgL,CAAC;AAEhN,eAAO,MAAM,qBAAqB,iTAEuP,CAAC;AAE1R,eAAO,MAAM,kBAAkB,opIAcqQ,CAAC;AAErS,eAAO,MAAM,wBAAwB,25DASqmB,CAAC;AAE3oB,eAAO,MAAM,WAAW,ihDAWqH,CAAC;AAE9I;;GAEG;AACH,eAAO,MAAM,wBAAwB,+uBAWiH,CAAC;AAEvJ,eAAO,MAAM,qBAAqB,6sBAMuL,CAAC;AAE1N,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,OAAO,EACnB,UAAU,GAAE,OAAe,GAC1B,MAAM,CAmFR;AAED,eAAO,MAAM,qBAAqB,gLAAqB,CAAC;AAExD;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,8BAA8B,44DA8CI,CAAC;AAEhD,eAAO,MAAM,yBAAyB,wHAAwH,CAAC;AAC/J,eAAO,MAAM,iBAAiB,qWAG4B,CAAC;AAE3D,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,UAAU,CAAC,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACE,GACL,iBAAiB,EAAE,CA+DrB;AAED,wBAAgB,iCAAiC,CAC/C,oBAAoB,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,MAAM,EACxB,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,GACvC,MAAM,CAgCR"}
@@ -1,6 +1,5 @@
1
1
  import * as os from "node:os";
2
2
  import { isGitRepository } from "../utils/gitUtils.js";
3
- import { getCurrentWorktreeSession } from "../utils/worktreeSession.js";
4
3
  import { buildAutoMemoryPrompt } from "./autoMemory.js";
5
4
  import { EXPLORE_SUBAGENT_TYPE, PLAN_SUBAGENT_TYPE, } from "../constants/subagents.js";
6
5
  import { ASK_USER_QUESTION_TOOL_NAME, EDIT_TOOL_NAME, WRITE_TOOL_NAME, EXIT_PLAN_MODE_TOOL_NAME, AGENT_TOOL_NAME, BASH_TOOL_NAME, READ_TOOL_NAME, GLOB_TOOL_NAME, GREP_TOOL_NAME, } from "../constants/tools.js";
@@ -230,7 +229,7 @@ export function buildSystemPrompt(basePrompt, tools, options = {}) {
230
229
  : shell.includes("bash")
231
230
  ? "bash"
232
231
  : shell;
233
- const worktreeSession = getCurrentWorktreeSession();
232
+ const worktreeSession = options.worktreeSession;
234
233
  dynamicText += `
235
234
 
236
235
  Here is useful information about the environment you are running in:
@@ -255,7 +254,7 @@ Today's date: ${today}
255
254
  }
256
255
  return blocks;
257
256
  }
258
- export function enhanceSystemPromptWithEnvDetails(existingSystemPrompt, workdir, originalWorkdir) {
257
+ export function enhanceSystemPromptWithEnvDetails(existingSystemPrompt, workdir, originalWorkdir, worktreeSession) {
259
258
  const isGitRepo = isGitRepository(workdir);
260
259
  const platform = os.platform();
261
260
  const osVersion = `${os.type()} ${os.release()}`;
@@ -266,7 +265,6 @@ export function enhanceSystemPromptWithEnvDetails(existingSystemPrompt, workdir,
266
265
  : shell.includes("bash")
267
266
  ? "bash"
268
267
  : shell;
269
- const worktreeSession = getCurrentWorktreeSession();
270
268
  const notes = `Notes:
271
269
  - Agent threads always have their cwd reset between bash calls, as a result please only use absolute file paths.${worktreeSession ? `\n- You are in a git worktree at ${worktreeSession.worktreePath} (branch: ${worktreeSession.worktreeBranch}). Absolute paths from prior context may refer to the original repo at ${worktreeSession.originalCwd}; translate them to your worktree. Do NOT edit files outside this worktree.` : ""}
272
270
  - In your final response, share file paths (always absolute, never relative) that are relevant to the task. Include code snippets only when the exact text is load-bearing (e.g., a bug you found, a function signature the caller asked for) — do not recap code you merely read.
@@ -1 +1 @@
1
- {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/services/hook.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EAElC,MAAM,mBAAmB,CAAC;AAuG3B;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,EAC5D,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CA6I9B;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,EAC5D,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAchC;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAMhC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAsBtD"}
1
+ {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/services/hook.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,EAElC,MAAM,mBAAmB,CAAC;AAuH3B;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,EAC5D,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CA6I9B;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,EAC5D,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAchC;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAMhC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAsBtD"}
@@ -83,6 +83,18 @@ async function buildHookJsonInput(context) {
83
83
  jsonInput.end_source = context.endSource;
84
84
  }
85
85
  }
86
+ // Add background_tasks and session_crons for Stop events only (not SubagentStop).
87
+ // Fields are always present for Stop (empty arrays when nothing in flight).
88
+ if (context.event === "Stop") {
89
+ jsonInput.background_tasks = context.backgroundTasks ?? [];
90
+ jsonInput.session_crons = context.sessionCrons ?? [];
91
+ }
92
+ // Add last_assistant_message for Stop and SubagentStop events.
93
+ // Omitted when undefined (no text content in last assistant message).
94
+ if ((context.event === "Stop" || context.event === "SubagentStop") &&
95
+ context.lastAssistantMessage !== undefined) {
96
+ jsonInput.last_assistant_message = context.lastAssistantMessage;
97
+ }
86
98
  return jsonInput;
87
99
  }
88
100
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"bashTool.d.ts","sourceRoot":"","sources":["../../src/tools/bashTool.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AA0CtE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UA8iBtB,CAAC"}
1
+ {"version":3,"file":"bashTool.d.ts","sourceRoot":"","sources":["../../src/tools/bashTool.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AA0CtE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UAojBtB,CAAC"}
@@ -152,13 +152,15 @@ The working directory persists between commands. Try to maintain your current wo
152
152
  error: "Command parameter is required and must be a string",
153
153
  };
154
154
  }
155
- // Resolve shell path: on Windows, use Git Bash; on other platforms, use default
155
+ // Resolve shell path: on Windows, use Git Bash; on macOS/Linux, use bash or zsh
156
156
  const shellPath = resolveShellPath();
157
- if (process.platform === "win32" && !shellPath) {
157
+ if (!shellPath) {
158
158
  return {
159
159
  success: false,
160
160
  content: "",
161
- error: "Git Bash not found. Please install Git for Windows or set GIT_BASH_PATH environment variable.",
161
+ error: process.platform === "win32"
162
+ ? "Git Bash not found. Please install Git for Windows or set WAVE_GIT_BASH_PATH environment variable."
163
+ : "No suitable shell found. Please ensure bash or zsh is installed, or set WAVE_SHELL environment variable.",
162
164
  };
163
165
  }
164
166
  // Validate timeout
@@ -207,7 +209,7 @@ The working directory persists between commands. Try to maintain your current wo
207
209
  error: "Background task manager not available",
208
210
  };
209
211
  }
210
- const { id: taskId } = backgroundTaskManager.startShell(command);
212
+ const { id: taskId } = backgroundTaskManager.startShell(command, undefined, context.workdir);
211
213
  const task = backgroundTaskManager.getTask(taskId);
212
214
  const outputPath = task?.outputPath;
213
215
  const backgroundMsg = [
@@ -230,7 +232,7 @@ The working directory persists between commands. Try to maintain your current wo
230
232
  const tempCwdFileForBash = toPosixPath(tempCwdFile);
231
233
  const wrappedCommand = wrapCommandForCwdTracking(command, tempCwdFileForBash);
232
234
  const child = spawn(wrappedCommand, {
233
- shell: shellPath || true,
235
+ shell: shellPath,
234
236
  stdio: "pipe",
235
237
  detached: true,
236
238
  cwd: context.workdir,
@@ -1 +1 @@
1
- {"version":3,"file":"enterWorktreeTool.d.ts","sourceRoot":"","sources":["../../src/tools/enterWorktreeTool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAetE,eAAO,MAAM,0BAA0B,qxCA0BtC,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,UAqI/B,CAAC"}
1
+ {"version":3,"file":"enterWorktreeTool.d.ts","sourceRoot":"","sources":["../../src/tools/enterWorktreeTool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAWtE,eAAO,MAAM,0BAA0B,qxCA0BtC,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,UA+H/B,CAAC"}
@@ -2,7 +2,6 @@
2
2
  * EnterWorktree tool - creates an isolated git worktree and switches the session into it.
3
3
  * Mirrors Claude Code's EnterWorktree tool behavior and prompt.
4
4
  */
5
- import { getCurrentWorktreeSession, setCurrentWorktreeSession, } from "../utils/worktreeSession.js";
6
5
  import { createWorktree, validateWorktreeName, generateWorktreeName, } from "../utils/worktreeUtils.js";
7
6
  import { getGitMainRepoRoot } from "../utils/gitUtils.js";
8
7
  import { ENTER_WORKTREE_TOOL_NAME } from "../constants/tools.js";
@@ -55,7 +54,7 @@ export const enterWorktreeTool = {
55
54
  prompt: () => ENTER_WORKTREE_TOOL_PROMPT,
56
55
  async execute(args, context) {
57
56
  // Validate not already in a worktree created by this session
58
- if (getCurrentWorktreeSession()) {
57
+ if (context.aiManager?.getWorktreeSession()) {
59
58
  return {
60
59
  success: false,
61
60
  content: "Already in a worktree session. Use ExitWorktree to leave before creating a new one.",
@@ -95,16 +94,12 @@ export const enterWorktreeTool = {
95
94
  repoRoot: worktreeInfo.repoRoot,
96
95
  originalHeadCommit: worktreeInfo.originalHeadCommit,
97
96
  };
98
- // Set module-level session state
99
- setCurrentWorktreeSession(session);
100
- // Update CWD via AIManager
97
+ // Set per-session worktree state and update CWD via AIManager
101
98
  const aiManager = context.aiManager;
102
99
  if (aiManager) {
100
+ aiManager.setWorktreeSession(session);
103
101
  aiManager.setWorkdir(worktreeInfo.path);
104
102
  }
105
- // Also update the container's Workdir entry
106
- // (Container is not directly accessible from ToolContext, but AIManager.setWorkdir
107
- // handles both its internal field and process.chdir)
108
103
  // Trigger WorktreeCreate hook if worktree is new
109
104
  let hookTriggered = false;
110
105
  if (session.isNew && context.hookManager) {
@@ -1 +1 @@
1
- {"version":3,"file":"exitWorktreeTool.d.ts","sourceRoot":"","sources":["../../src/tools/exitWorktreeTool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAYtE,eAAO,MAAM,yBAAyB,gvDA4BrC,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,UAiM9B,CAAC"}
1
+ {"version":3,"file":"exitWorktreeTool.d.ts","sourceRoot":"","sources":["../../src/tools/exitWorktreeTool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAQtE,eAAO,MAAM,yBAAyB,gvDA4BrC,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,UA6L9B,CAAC"}
@@ -2,7 +2,6 @@
2
2
  * ExitWorktree tool - exits a worktree session and returns to the original directory.
3
3
  * Mirrors Claude Code's ExitWorktree tool behavior and prompt.
4
4
  */
5
- import { getCurrentWorktreeSession, setCurrentWorktreeSession, } from "../utils/worktreeSession.js";
6
5
  import { removeWorktree, countWorktreeChanges, } from "../utils/worktreeUtils.js";
7
6
  import { EXIT_WORKTREE_TOOL_NAME } from "../constants/tools.js";
8
7
  import { logger } from "../utils/globalLogger.js";
@@ -70,8 +69,8 @@ export const exitWorktreeTool = {
70
69
  error: 'Missing required parameter: "action"',
71
70
  };
72
71
  }
73
- // Validate: must be in an active worktree session
74
- const session = getCurrentWorktreeSession();
72
+ // Validate: must be in an active worktree session (for this session)
73
+ const session = context.aiManager?.getWorktreeSession();
75
74
  if (!session) {
76
75
  return {
77
76
  success: false,
@@ -109,10 +108,9 @@ export const exitWorktreeTool = {
109
108
  const { originalCwd, worktreePath, worktreeBranch } = session;
110
109
  if (action === "keep") {
111
110
  // Clear session state
112
- setCurrentWorktreeSession(null);
113
- // Restore CWD
114
111
  const aiManager = context.aiManager;
115
112
  if (aiManager) {
113
+ aiManager.setWorktreeSession(null);
116
114
  aiManager.setWorkdir(originalCwd);
117
115
  }
118
116
  return {
@@ -131,11 +129,10 @@ export const exitWorktreeTool = {
131
129
  // Count changes BEFORE removing the worktree (directory will be gone after)
132
130
  const summary = countWorktreeChanges(worktreePath, session.originalHeadCommit) ?? { changedFiles: 0, commits: 0 };
133
131
  removeWorktree(worktreeInfo);
134
- // Clear session state
135
- setCurrentWorktreeSession(null);
136
- // Restore CWD
132
+ // Clear session state and restore CWD
137
133
  const aiManager = context.aiManager;
138
134
  if (aiManager) {
135
+ aiManager.setWorktreeSession(null);
139
136
  aiManager.setWorkdir(originalCwd);
140
137
  }
141
138
  // Trigger WorktreeRemove hook (non-blocking)
@@ -1 +1 @@
1
- {"version":3,"file":"grepTool.d.ts","sourceRoot":"","sources":["../../src/tools/grepTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAUtE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UA8StB,CAAC"}
1
+ {"version":3,"file":"grepTool.d.ts","sourceRoot":"","sources":["../../src/tools/grepTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAsBtE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UA0TtB,CAAC"}
@@ -2,6 +2,17 @@ import { spawn } from "child_process";
2
2
  import { rgPath } from "../utils/ripgrep.js";
3
3
  import { getDisplayPath } from "../utils/path.js";
4
4
  import { GREP_TOOL_NAME, BASH_TOOL_NAME, AGENT_TOOL_NAME, } from "../constants/tools.js";
5
+ // Version control system directories to exclude from searches.
6
+ // These are excluded automatically because they create noise in search results.
7
+ // Mirrors Claude Code's VCS_DIRECTORIES_TO_EXCLUDE.
8
+ const VCS_DIRECTORIES_TO_EXCLUDE = [
9
+ ".git",
10
+ ".svn",
11
+ ".hg",
12
+ ".bzr",
13
+ ".jj",
14
+ ".sl",
15
+ ];
5
16
  /**
6
17
  * Grep tool plugin - powerful search tool based on ripgrep
7
18
  */
@@ -119,7 +130,18 @@ export const grepTool = {
119
130
  }
120
131
  try {
121
132
  const workdir = context.workdir;
122
- const rgArgs = ["--color=never", "--max-columns=500"];
133
+ const rgArgs = [
134
+ "--color=never",
135
+ "--max-columns=500",
136
+ // Search hidden files/directories by default (aligns with Claude Code).
137
+ // --hidden does NOT disable .gitignore; only --no-ignore would.
138
+ "--hidden",
139
+ ];
140
+ // Exclude VCS directories to avoid noise from version control metadata.
141
+ // --hidden above would otherwise traverse .git/.svn/etc.
142
+ for (const dir of VCS_DIRECTORIES_TO_EXCLUDE) {
143
+ rgArgs.push("--glob", `!${dir}`);
144
+ }
123
145
  // Set output mode
124
146
  if (outputMode === "files_with_matches") {
125
147
  rgArgs.push("-l");
@@ -79,6 +79,24 @@ export interface HookJsonInput {
79
79
  end_source?: SessionEndSource;
80
80
  compact_instructions?: string;
81
81
  compact_summary?: string;
82
+ background_tasks?: BackgroundTaskInfo[];
83
+ session_crons?: SessionCronInfo[];
84
+ last_assistant_message?: string;
85
+ }
86
+ export interface BackgroundTaskInfo {
87
+ id: string;
88
+ type: "shell" | "subagent" | "workflow";
89
+ status: string;
90
+ description: string;
91
+ command?: string;
92
+ agent_type?: string;
93
+ name?: string;
94
+ }
95
+ export interface SessionCronInfo {
96
+ id: string;
97
+ schedule: string;
98
+ recurring: boolean;
99
+ prompt: string;
82
100
  }
83
101
  export interface ExtendedHookExecutionContext extends HookExecutionContext {
84
102
  sessionId?: string;
@@ -97,6 +115,9 @@ export interface ExtendedHookExecutionContext extends HookExecutionContext {
97
115
  endSource?: SessionEndSource;
98
116
  compactInstructions?: string;
99
117
  compactSummary?: string;
118
+ backgroundTasks?: BackgroundTaskInfo[];
119
+ sessionCrons?: SessionCronInfo[];
120
+ lastAssistantMessage?: string;
100
121
  }
101
122
  export interface HookEnvironment {
102
123
  WAVE_PROJECT_DIR: string;
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/types/hooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/types/hooks.ts"],"names":[],"mappings":"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"}
@@ -74,6 +74,8 @@ export interface ReasoningBlock {
74
74
  type: "reasoning";
75
75
  content: string;
76
76
  stage?: "streaming" | "end";
77
+ startTime?: number;
78
+ endTime?: number;
77
79
  }
78
80
  export interface FileHistoryBlock {
79
81
  type: "file_history";
@@ -1 +1 @@
1
- {"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../../src/types/messaging.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../../src/types/messaging.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"containerSetup.d.ts","sourceRoot":"","sources":["../../src/utils/containerSetup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AA0B3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAM3E,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,mBAAmB,CAAC;AACvE,OAAO,KAAK,EACV,cAAc,EACd,KAAK,EACL,IAAI,EACJ,cAAc,EAEf,MAAM,mBAAmB,CAAC;AAM3B,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAGhB,uBAAuB,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IAC3D,aAAa,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACvC,sBAAsB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACvD,wBAAwB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,0BAA0B,GACvC,SAAS,CAkTX"}
1
+ {"version":3,"file":"containerSetup.d.ts","sourceRoot":"","sources":["../../src/utils/containerSetup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AA0B3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAM3E,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,mBAAmB,CAAC;AACvE,OAAO,KAAK,EACV,cAAc,EACd,KAAK,EACL,IAAI,EACJ,cAAc,EAEf,MAAM,mBAAmB,CAAC;AAM3B,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAGhB,uBAAuB,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IAC3D,aAAa,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACvC,sBAAsB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACvD,wBAAwB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,0BAA0B,GACvC,SAAS,CAsTX"}
@@ -42,6 +42,9 @@ export function setupAgentContainer(setupOptions) {
42
42
  container.register("WorktreeName", options.worktreeName);
43
43
  container.register("MainRepoRoot", getGitMainRepoRoot(workdir));
44
44
  }
45
+ // Per-agent worktree session state (EnterWorktree/ExitWorktree). Stored in the
46
+ // container so it is isolated per session, not shared process-wide.
47
+ container.register("WorktreeSession", null);
45
48
  const notificationQueue = new NotificationQueue();
46
49
  container.register("NotificationQueue", notificationQueue);
47
50
  const messageQueue = new MessageQueue();
@@ -1 +1 @@
1
- {"version":3,"file":"shellResolver.d.ts","sourceRoot":"","sources":["../../src/utils/shellResolver.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,sBAAsB,UAGlC,CAAC;AAEF,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAuBrD"}
1
+ {"version":3,"file":"shellResolver.d.ts","sourceRoot":"","sources":["../../src/utils/shellResolver.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,sBAAsB,UAGlC,CAAC;AAgLF,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAMrD"}
@@ -1,25 +1,174 @@
1
1
  import fs from "fs";
2
+ import path from "path";
3
+ import { execFileSync } from "child_process";
2
4
  export const WINDOWS_GIT_BASH_PATHS = [
3
5
  "C:\\Program Files\\Git\\bin\\bash.exe",
4
6
  "C:\\Program Files (x86)\\Git\\bin\\bash.exe",
5
7
  ];
6
- export function resolveShellPath() {
7
- if (process.platform !== "win32") {
8
+ // Common git.exe locations (checked before falling back to `where.exe`).
9
+ const WINDOWS_GIT_EXE_PATHS = [
10
+ "C:\\Program Files\\Git\\cmd\\git.exe",
11
+ "C:\\Program Files (x86)\\Git\\cmd\\git.exe",
12
+ ];
13
+ // Common directories where bash/zsh may live, used as fallback after PATH lookup.
14
+ const FIXED_SHELL_DIRS = [
15
+ "/bin",
16
+ "/usr/bin",
17
+ "/usr/local/bin",
18
+ "/opt/homebrew/bin",
19
+ ];
20
+ function isExecutable(shellPath) {
21
+ try {
22
+ fs.accessSync(shellPath, fs.constants.X_OK);
23
+ return true;
24
+ }
25
+ catch {
26
+ return false;
27
+ }
28
+ }
29
+ /** Resolve a command name (e.g. "bash") to an absolute path by searching $PATH. */
30
+ function which(command) {
31
+ const pathEnv = process.env.PATH;
32
+ if (!pathEnv)
33
+ return undefined;
34
+ for (const dir of pathEnv.split(":")) {
35
+ if (!dir)
36
+ continue;
37
+ const candidate = path.join(dir, command);
38
+ if (isExecutable(candidate)) {
39
+ return candidate;
40
+ }
41
+ }
42
+ return undefined;
43
+ }
44
+ function isSupportedShell(shellPath) {
45
+ return shellPath.includes("bash") || shellPath.includes("zsh");
46
+ }
47
+ /**
48
+ * Locate the `git` executable on Windows, then infer bash.exe from it.
49
+ * Checks common Git for Windows install locations first, then falls back
50
+ * to `where.exe git` (aligned with Claude Code's findExecutable('git')).
51
+ * Returns the inferred bash.exe path, or undefined if not found.
52
+ */
53
+ function inferGitBashFromGit() {
54
+ // 1. Common git.exe locations
55
+ let gitExe;
56
+ for (const candidate of WINDOWS_GIT_EXE_PATHS) {
57
+ if (fs.existsSync(candidate)) {
58
+ gitExe = candidate;
59
+ break;
60
+ }
61
+ }
62
+ // 2. Fallback: where.exe git
63
+ if (!gitExe) {
64
+ try {
65
+ const result = execFileSync("where", ["git"], {
66
+ stdio: "pipe",
67
+ encoding: "utf8",
68
+ timeout: 3000,
69
+ }).trim();
70
+ // where.exe may return multiple lines; take the first non-empty one.
71
+ gitExe = result.split(/\r?\n/).find((line) => line.trim()) || undefined;
72
+ }
73
+ catch {
74
+ gitExe = undefined;
75
+ }
76
+ }
77
+ if (!gitExe)
8
78
  return undefined;
79
+ // git.exe is at <install>/cmd/git.exe → bash.exe is at <install>/bin/bash.exe
80
+ // join treats git.exe as a segment, so ".." cancels it (→ cmd dir),
81
+ // the second ".." cancels cmd (→ <install>), then bin/bash.exe.
82
+ const bashPath = path.win32.join(gitExe, "..", "..", "bin", "bash.exe");
83
+ if (fs.existsSync(bashPath)) {
84
+ return bashPath;
85
+ }
86
+ return undefined;
87
+ }
88
+ /**
89
+ * Resolve a bash or zsh binary on macOS/Linux.
90
+ *
91
+ * Priority (aligned with Claude Code's findSuitableShell):
92
+ * 1. WAVE_SHELL env var (only if it points to an executable bash/zsh)
93
+ * 2. $SHELL (only if it is bash/zsh)
94
+ * 3. `which bash` / `which zsh` discovered on $PATH
95
+ * 4. Common fixed locations (/bin, /usr/bin, /usr/local/bin, /opt/homebrew/bin)
96
+ *
97
+ * When $SHELL is bash, bash is preferred; otherwise zsh is preferred. This
98
+ * matters because /bin/sh may be dash (Debian/Ubuntu) or POSIX-mode bash
99
+ * (macOS), neither of which supports bashisms like process substitution
100
+ * `<()`, causing `eval '<()...'` to fail at parse time.
101
+ */
102
+ function resolveUnixShell() {
103
+ // 1. WAVE_SHELL env override
104
+ const waveShell = process.env.WAVE_SHELL;
105
+ if (waveShell && isSupportedShell(waveShell) && isExecutable(waveShell)) {
106
+ return waveShell;
107
+ }
108
+ // 2. $SHELL (only bash/zsh)
109
+ const envShell = process.env.SHELL;
110
+ const isEnvShellSupported = !!envShell && isSupportedShell(envShell);
111
+ const preferBash = envShell?.includes("bash") ?? false;
112
+ // 3. Locate via PATH
113
+ const bashPath = which("bash");
114
+ const zshPath = which("zsh");
115
+ // 4. Fixed common locations, ordered by user preference
116
+ const shellOrder = preferBash ? ["bash", "zsh"] : ["zsh", "bash"];
117
+ const candidates = shellOrder.flatMap((shell) => FIXED_SHELL_DIRS.map((dir) => `${dir}/${shell}`));
118
+ // Discovered PATH paths: preferred type first, the other as fallback
119
+ if (preferBash) {
120
+ if (bashPath)
121
+ candidates.unshift(bashPath);
122
+ if (zshPath)
123
+ candidates.push(zshPath);
9
124
  }
10
- if (process.env.GIT_BASH_PATH) {
11
- return process.env.GIT_BASH_PATH;
125
+ else {
126
+ if (zshPath)
127
+ candidates.unshift(zshPath);
128
+ if (bashPath)
129
+ candidates.push(bashPath);
12
130
  }
131
+ // Always prioritize $SHELL if it is a supported, executable shell
132
+ if (isEnvShellSupported && envShell && isExecutable(envShell)) {
133
+ candidates.unshift(envShell);
134
+ }
135
+ return candidates.find((candidate) => isExecutable(candidate));
136
+ }
137
+ /**
138
+ * Resolve the Git Bash path on Windows.
139
+ *
140
+ * Priority (aligned with Claude Code's findGitBashPath):
141
+ * 1. WAVE_GIT_BASH_PATH env var
142
+ * 2. Infer from `git` executable location (<git dir>/../../bin/bash.exe)
143
+ * 3. Common install paths (C:\Program Files\Git\bin\bash.exe, etc.)
144
+ */
145
+ function resolveWindowsShell() {
146
+ // 1. Env var override
147
+ if (process.env.WAVE_GIT_BASH_PATH) {
148
+ return process.env.WAVE_GIT_BASH_PATH;
149
+ }
150
+ // 2. Infer from git executable location
151
+ const inferred = inferGitBashFromGit();
152
+ if (inferred) {
153
+ return inferred;
154
+ }
155
+ // 4. Common install paths
13
156
  const paths = [
14
157
  ...WINDOWS_GIT_BASH_PATHS,
15
158
  process.env.LOCALAPPDATA
16
159
  ? `${process.env.LOCALAPPDATA}\\Programs\\Git\\bin\\bash.exe`
17
160
  : null,
18
161
  ].filter(Boolean);
19
- for (const path of paths) {
20
- if (fs.existsSync(path)) {
21
- return path;
162
+ for (const p of paths) {
163
+ if (fs.existsSync(p)) {
164
+ return p;
22
165
  }
23
166
  }
24
167
  return undefined;
25
168
  }
169
+ export function resolveShellPath() {
170
+ if (process.platform === "win32") {
171
+ return resolveWindowsShell();
172
+ }
173
+ return resolveUnixShell();
174
+ }
@@ -1,9 +1,11 @@
1
1
  /**
2
- * Module-level worktree session state tracking.
3
- * Analogous to Claude Code's currentWorktreeSession in worktree.ts.
2
+ * Worktree session state tracking.
4
3
  *
5
- * Tracks whether the current session entered a worktree via EnterWorktree tool,
6
- * so ExitWorktree can validate scope and restore the original CWD.
4
+ * The session state is stored per-agent in each session's DI container (see the
5
+ * "WorktreeSession" container slot registered in containerSetup.ts and accessed via
6
+ * AIManager.getWorktreeSession()/setWorktreeSession()). This keeps worktree state
7
+ * isolated per session in stdio multi-agent mode — a process-level singleton would
8
+ * leak state across concurrent sessions (see specs/047-worktree.md FR-042).
7
9
  */
8
10
  export interface WorktreeSession {
9
11
  /** The working directory the session was in before EnterWorktree */
@@ -21,6 +23,4 @@ export interface WorktreeSession {
21
23
  /** The HEAD commit of the original branch at worktree creation time */
22
24
  originalHeadCommit?: string;
23
25
  }
24
- export declare function getCurrentWorktreeSession(): WorktreeSession | null;
25
- export declare function setCurrentWorktreeSession(session: WorktreeSession | null): void;
26
26
  //# sourceMappingURL=worktreeSession.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worktreeSession.d.ts","sourceRoot":"","sources":["../../src/utils/worktreeSession.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,KAAK,EAAE,OAAO,CAAC;IACf,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAID,wBAAgB,yBAAyB,IAAI,eAAe,GAAG,IAAI,CAElE;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,eAAe,GAAG,IAAI,GAC9B,IAAI,CAEN"}
1
+ {"version":3,"file":"worktreeSession.d.ts","sourceRoot":"","sources":["../../src/utils/worktreeSession.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,KAAK,EAAE,OAAO,CAAC;IACf,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B"}
@@ -1,14 +1,10 @@
1
1
  /**
2
- * Module-level worktree session state tracking.
3
- * Analogous to Claude Code's currentWorktreeSession in worktree.ts.
2
+ * Worktree session state tracking.
4
3
  *
5
- * Tracks whether the current session entered a worktree via EnterWorktree tool,
6
- * so ExitWorktree can validate scope and restore the original CWD.
4
+ * The session state is stored per-agent in each session's DI container (see the
5
+ * "WorktreeSession" container slot registered in containerSetup.ts and accessed via
6
+ * AIManager.getWorktreeSession()/setWorktreeSession()). This keeps worktree state
7
+ * isolated per session in stdio multi-agent mode — a process-level singleton would
8
+ * leak state across concurrent sessions (see specs/047-worktree.md FR-042).
7
9
  */
8
- let currentWorktreeSession = null;
9
- export function getCurrentWorktreeSession() {
10
- return currentWorktreeSession;
11
- }
12
- export function setCurrentWorktreeSession(session) {
13
- currentWorktreeSession = session;
14
- }
10
+ export {};