wave-agent-sdk 0.19.5 → 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 (62) 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 +14 -1
  5. package/dist/managers/aiManager.d.ts.map +1 -1
  6. package/dist/managers/aiManager.js +39 -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 +6 -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/types/hooks.d.ts +2 -0
  34. package/dist/types/hooks.d.ts.map +1 -1
  35. package/dist/types/messaging.d.ts +2 -0
  36. package/dist/types/messaging.d.ts.map +1 -1
  37. package/dist/utils/containerSetup.d.ts.map +1 -1
  38. package/dist/utils/containerSetup.js +3 -0
  39. package/dist/utils/shellResolver.d.ts.map +1 -1
  40. package/dist/utils/shellResolver.js +156 -7
  41. package/dist/utils/worktreeSession.d.ts +6 -6
  42. package/dist/utils/worktreeSession.d.ts.map +1 -1
  43. package/dist/utils/worktreeSession.js +7 -11
  44. package/package.json +1 -1
  45. package/src/agent.ts +31 -0
  46. package/src/managers/aiManager.ts +49 -2
  47. package/src/managers/backgroundTaskManager.ts +4 -2
  48. package/src/managers/bangManager.ts +2 -1
  49. package/src/managers/messageManager.ts +72 -6
  50. package/src/managers/messageQueue.ts +17 -0
  51. package/src/managers/permissionManager.ts +6 -3
  52. package/src/managers/subagentManager.ts +13 -1
  53. package/src/prompts/index.ts +4 -4
  54. package/src/services/hook.ts +9 -0
  55. package/src/tools/bashTool.ts +11 -5
  56. package/src/tools/enterWorktreeTool.ts +4 -14
  57. package/src/tools/exitWorktreeTool.ts +5 -13
  58. package/src/types/hooks.ts +2 -0
  59. package/src/types/messaging.ts +2 -0
  60. package/src/utils/containerSetup.ts +4 -0
  61. package/src/utils/shellResolver.ts +167 -8
  62. package/src/utils/worktreeSession.ts +6 -16
@@ -1,19 +1,170 @@
1
1
  import fs from "fs";
2
+ import path from "path";
3
+ import { execFileSync } from "child_process";
2
4
 
3
5
  export const WINDOWS_GIT_BASH_PATHS = [
4
6
  "C:\\Program Files\\Git\\bin\\bash.exe",
5
7
  "C:\\Program Files (x86)\\Git\\bin\\bash.exe",
6
8
  ];
7
9
 
8
- export function resolveShellPath(): string | undefined {
9
- if (process.platform !== "win32") {
10
- return undefined;
10
+ // Common git.exe locations (checked before falling back to `where.exe`).
11
+ const WINDOWS_GIT_EXE_PATHS = [
12
+ "C:\\Program Files\\Git\\cmd\\git.exe",
13
+ "C:\\Program Files (x86)\\Git\\cmd\\git.exe",
14
+ ];
15
+
16
+ // Common directories where bash/zsh may live, used as fallback after PATH lookup.
17
+ const FIXED_SHELL_DIRS = [
18
+ "/bin",
19
+ "/usr/bin",
20
+ "/usr/local/bin",
21
+ "/opt/homebrew/bin",
22
+ ];
23
+
24
+ function isExecutable(shellPath: string): boolean {
25
+ try {
26
+ fs.accessSync(shellPath, fs.constants.X_OK);
27
+ return true;
28
+ } catch {
29
+ return false;
30
+ }
31
+ }
32
+
33
+ /** Resolve a command name (e.g. "bash") to an absolute path by searching $PATH. */
34
+ function which(command: string): string | undefined {
35
+ const pathEnv = process.env.PATH;
36
+ if (!pathEnv) return undefined;
37
+ for (const dir of pathEnv.split(":")) {
38
+ if (!dir) continue;
39
+ const candidate = path.join(dir, command);
40
+ if (isExecutable(candidate)) {
41
+ return candidate;
42
+ }
43
+ }
44
+ return undefined;
45
+ }
46
+
47
+ function isSupportedShell(shellPath: string): boolean {
48
+ return shellPath.includes("bash") || shellPath.includes("zsh");
49
+ }
50
+
51
+ /**
52
+ * Locate the `git` executable on Windows, then infer bash.exe from it.
53
+ * Checks common Git for Windows install locations first, then falls back
54
+ * to `where.exe git` (aligned with Claude Code's findExecutable('git')).
55
+ * Returns the inferred bash.exe path, or undefined if not found.
56
+ */
57
+ function inferGitBashFromGit(): string | undefined {
58
+ // 1. Common git.exe locations
59
+ let gitExe: string | undefined;
60
+ for (const candidate of WINDOWS_GIT_EXE_PATHS) {
61
+ if (fs.existsSync(candidate)) {
62
+ gitExe = candidate;
63
+ break;
64
+ }
65
+ }
66
+
67
+ // 2. Fallback: where.exe git
68
+ if (!gitExe) {
69
+ try {
70
+ const result = execFileSync("where", ["git"], {
71
+ stdio: "pipe",
72
+ encoding: "utf8",
73
+ timeout: 3000,
74
+ }).trim();
75
+ // where.exe may return multiple lines; take the first non-empty one.
76
+ gitExe = result.split(/\r?\n/).find((line) => line.trim()) || undefined;
77
+ } catch {
78
+ gitExe = undefined;
79
+ }
80
+ }
81
+
82
+ if (!gitExe) return undefined;
83
+
84
+ // git.exe is at <install>/cmd/git.exe → bash.exe is at <install>/bin/bash.exe
85
+ // join treats git.exe as a segment, so ".." cancels it (→ cmd dir),
86
+ // the second ".." cancels cmd (→ <install>), then bin/bash.exe.
87
+ const bashPath = path.win32.join(gitExe, "..", "..", "bin", "bash.exe");
88
+ if (fs.existsSync(bashPath)) {
89
+ return bashPath;
11
90
  }
91
+ return undefined;
92
+ }
12
93
 
13
- if (process.env.GIT_BASH_PATH) {
14
- return process.env.GIT_BASH_PATH;
94
+ /**
95
+ * Resolve a bash or zsh binary on macOS/Linux.
96
+ *
97
+ * Priority (aligned with Claude Code's findSuitableShell):
98
+ * 1. WAVE_SHELL env var (only if it points to an executable bash/zsh)
99
+ * 2. $SHELL (only if it is bash/zsh)
100
+ * 3. `which bash` / `which zsh` discovered on $PATH
101
+ * 4. Common fixed locations (/bin, /usr/bin, /usr/local/bin, /opt/homebrew/bin)
102
+ *
103
+ * When $SHELL is bash, bash is preferred; otherwise zsh is preferred. This
104
+ * matters because /bin/sh may be dash (Debian/Ubuntu) or POSIX-mode bash
105
+ * (macOS), neither of which supports bashisms like process substitution
106
+ * `<()`, causing `eval '<()...'` to fail at parse time.
107
+ */
108
+ function resolveUnixShell(): string | undefined {
109
+ // 1. WAVE_SHELL env override
110
+ const waveShell = process.env.WAVE_SHELL;
111
+ if (waveShell && isSupportedShell(waveShell) && isExecutable(waveShell)) {
112
+ return waveShell;
15
113
  }
16
114
 
115
+ // 2. $SHELL (only bash/zsh)
116
+ const envShell = process.env.SHELL;
117
+ const isEnvShellSupported = !!envShell && isSupportedShell(envShell);
118
+ const preferBash = envShell?.includes("bash") ?? false;
119
+
120
+ // 3. Locate via PATH
121
+ const bashPath = which("bash");
122
+ const zshPath = which("zsh");
123
+
124
+ // 4. Fixed common locations, ordered by user preference
125
+ const shellOrder = preferBash ? ["bash", "zsh"] : ["zsh", "bash"];
126
+ const candidates = shellOrder.flatMap((shell) =>
127
+ FIXED_SHELL_DIRS.map((dir) => `${dir}/${shell}`),
128
+ );
129
+
130
+ // Discovered PATH paths: preferred type first, the other as fallback
131
+ if (preferBash) {
132
+ if (bashPath) candidates.unshift(bashPath);
133
+ if (zshPath) candidates.push(zshPath);
134
+ } else {
135
+ if (zshPath) candidates.unshift(zshPath);
136
+ if (bashPath) candidates.push(bashPath);
137
+ }
138
+
139
+ // Always prioritize $SHELL if it is a supported, executable shell
140
+ if (isEnvShellSupported && envShell && isExecutable(envShell)) {
141
+ candidates.unshift(envShell);
142
+ }
143
+
144
+ return candidates.find((candidate) => isExecutable(candidate));
145
+ }
146
+
147
+ /**
148
+ * Resolve the Git Bash path on Windows.
149
+ *
150
+ * Priority (aligned with Claude Code's findGitBashPath):
151
+ * 1. WAVE_GIT_BASH_PATH env var
152
+ * 2. Infer from `git` executable location (<git dir>/../../bin/bash.exe)
153
+ * 3. Common install paths (C:\Program Files\Git\bin\bash.exe, etc.)
154
+ */
155
+ function resolveWindowsShell(): string | undefined {
156
+ // 1. Env var override
157
+ if (process.env.WAVE_GIT_BASH_PATH) {
158
+ return process.env.WAVE_GIT_BASH_PATH;
159
+ }
160
+
161
+ // 2. Infer from git executable location
162
+ const inferred = inferGitBashFromGit();
163
+ if (inferred) {
164
+ return inferred;
165
+ }
166
+
167
+ // 4. Common install paths
17
168
  const paths = [
18
169
  ...WINDOWS_GIT_BASH_PATHS,
19
170
  process.env.LOCALAPPDATA
@@ -21,11 +172,19 @@ export function resolveShellPath(): string | undefined {
21
172
  : null,
22
173
  ].filter(Boolean) as string[];
23
174
 
24
- for (const path of paths) {
25
- if (fs.existsSync(path)) {
26
- return path;
175
+ for (const p of paths) {
176
+ if (fs.existsSync(p)) {
177
+ return p;
27
178
  }
28
179
  }
29
180
 
30
181
  return undefined;
31
182
  }
183
+
184
+ export function resolveShellPath(): string | undefined {
185
+ if (process.platform === "win32") {
186
+ return resolveWindowsShell();
187
+ }
188
+
189
+ return resolveUnixShell();
190
+ }
@@ -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
 
9
11
  export interface WorktreeSession {
@@ -22,15 +24,3 @@ export interface WorktreeSession {
22
24
  /** The HEAD commit of the original branch at worktree creation time */
23
25
  originalHeadCommit?: string;
24
26
  }
25
-
26
- let currentWorktreeSession: WorktreeSession | null = null;
27
-
28
- export function getCurrentWorktreeSession(): WorktreeSession | null {
29
- return currentWorktreeSession;
30
- }
31
-
32
- export function setCurrentWorktreeSession(
33
- session: WorktreeSession | null,
34
- ): void {
35
- currentWorktreeSession = session;
36
- }