wave-code 1.0.10 → 1.1.1

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 (248) hide show
  1. package/bin/wave-code.js +8 -2
  2. package/dist/bundle/wave.mjs +3231 -0
  3. package/package.json +24 -25
  4. package/src/cli.tsx +6 -1
  5. package/src/commands/update.ts +2 -7
  6. package/src/components/App.tsx +3 -7
  7. package/src/components/BtwDisplay.tsx +10 -1
  8. package/src/components/ChatInterface.tsx +21 -52
  9. package/src/components/ConfirmationDetails.tsx +144 -37
  10. package/src/components/DiffDisplay.tsx +335 -301
  11. package/src/components/InputBox.tsx +17 -2
  12. package/src/components/LoadingIndicator.tsx +16 -2
  13. package/src/components/MessageBlockItem.tsx +2 -4
  14. package/src/components/MessageList.tsx +75 -14
  15. package/src/components/ReasoningDisplay.tsx +2 -4
  16. package/src/components/SessionSelector.tsx +82 -11
  17. package/src/components/SkillsManager.tsx +312 -0
  18. package/src/components/StatusCommand.tsx +2 -9
  19. package/src/components/ToolDisplay.tsx +2 -4
  20. package/src/constants/commands.ts +6 -0
  21. package/src/contexts/useChat.tsx +245 -301
  22. package/src/daemon/commands.ts +57 -27
  23. package/src/daemon/jsonRpcClient.ts +1 -1
  24. package/src/daemon/socketClient.ts +2 -2
  25. package/src/hooks/useInputManager.ts +7 -1
  26. package/src/index.ts +57 -10
  27. package/src/managers/inputHandlers.ts +2 -0
  28. package/src/managers/inputReducer.ts +195 -104
  29. package/src/print-cli.ts +25 -17
  30. package/src/reducers/selectorReducer.ts +10 -0
  31. package/src/reducers/skillsManagerReducer.ts +91 -0
  32. package/src/session-selector-cli.tsx +269 -28
  33. package/src/stdio/agentBridge.ts +30 -21
  34. package/src/stdio/daemonServer.ts +3 -1
  35. package/src/stdio/protocol.ts +2 -0
  36. package/src/utils/clipboard.ts +21 -0
  37. package/src/utils/highlightUtils.ts +46 -1
  38. package/src/utils/readPackageJson.ts +29 -0
  39. package/src/utils/streamingText.ts +11 -0
  40. package/src/utils/worktree.ts +191 -43
  41. package/dist/cli.d.ts +0 -6
  42. package/dist/cli.js +0 -53
  43. package/dist/commands/plugin/disable.d.ts +0 -5
  44. package/dist/commands/plugin/disable.js +0 -15
  45. package/dist/commands/plugin/enable.d.ts +0 -5
  46. package/dist/commands/plugin/enable.js +0 -15
  47. package/dist/commands/plugin/install.d.ts +0 -5
  48. package/dist/commands/plugin/install.js +0 -21
  49. package/dist/commands/plugin/list.d.ts +0 -1
  50. package/dist/commands/plugin/list.js +0 -31
  51. package/dist/commands/plugin/marketplace.d.ts +0 -10
  52. package/dist/commands/plugin/marketplace.js +0 -90
  53. package/dist/commands/plugin/uninstall.d.ts +0 -3
  54. package/dist/commands/plugin/uninstall.js +0 -16
  55. package/dist/commands/plugin/update.d.ts +0 -3
  56. package/dist/commands/plugin/update.js +0 -15
  57. package/dist/commands/update.d.ts +0 -1
  58. package/dist/commands/update.js +0 -97
  59. package/dist/components/AgentsManager.d.ts +0 -7
  60. package/dist/components/AgentsManager.js +0 -109
  61. package/dist/components/App.d.ts +0 -9
  62. package/dist/components/App.js +0 -76
  63. package/dist/components/BackgroundTaskManager.d.ts +0 -5
  64. package/dist/components/BackgroundTaskManager.js +0 -99
  65. package/dist/components/BangDisplay.d.ts +0 -8
  66. package/dist/components/BangDisplay.js +0 -17
  67. package/dist/components/BtwDisplay.d.ts +0 -7
  68. package/dist/components/BtwDisplay.js +0 -19
  69. package/dist/components/ChatInterface.d.ts +0 -2
  70. package/dist/components/ChatInterface.js +0 -61
  71. package/dist/components/CommandSelector.d.ts +0 -10
  72. package/dist/components/CommandSelector.js +0 -66
  73. package/dist/components/CompactDisplay.d.ts +0 -8
  74. package/dist/components/CompactDisplay.js +0 -13
  75. package/dist/components/ConfirmationDetails.d.ts +0 -9
  76. package/dist/components/ConfirmationDetails.js +0 -45
  77. package/dist/components/ConfirmationSelector.d.ts +0 -13
  78. package/dist/components/ConfirmationSelector.js +0 -127
  79. package/dist/components/DiffDisplay.d.ts +0 -8
  80. package/dist/components/DiffDisplay.js +0 -201
  81. package/dist/components/DiscoverView.d.ts +0 -2
  82. package/dist/components/DiscoverView.js +0 -37
  83. package/dist/components/FileSelector.d.ts +0 -11
  84. package/dist/components/FileSelector.js +0 -50
  85. package/dist/components/HelpView.d.ts +0 -7
  86. package/dist/components/HelpView.js +0 -74
  87. package/dist/components/HistorySearch.d.ts +0 -8
  88. package/dist/components/HistorySearch.js +0 -66
  89. package/dist/components/InputBox.d.ts +0 -24
  90. package/dist/components/InputBox.js +0 -149
  91. package/dist/components/InstalledView.d.ts +0 -2
  92. package/dist/components/InstalledView.js +0 -45
  93. package/dist/components/LoadingIndicator.d.ts +0 -10
  94. package/dist/components/LoadingIndicator.js +0 -6
  95. package/dist/components/LoginCommand.d.ts +0 -5
  96. package/dist/components/LoginCommand.js +0 -153
  97. package/dist/components/Markdown.d.ts +0 -5
  98. package/dist/components/Markdown.js +0 -127
  99. package/dist/components/MarketplaceAddForm.d.ts +0 -2
  100. package/dist/components/MarketplaceAddForm.js +0 -55
  101. package/dist/components/MarketplaceDetail.d.ts +0 -2
  102. package/dist/components/MarketplaceDetail.js +0 -74
  103. package/dist/components/MarketplaceList.d.ts +0 -8
  104. package/dist/components/MarketplaceList.js +0 -17
  105. package/dist/components/MarketplaceView.d.ts +0 -2
  106. package/dist/components/MarketplaceView.js +0 -41
  107. package/dist/components/McpManager.d.ts +0 -9
  108. package/dist/components/McpManager.js +0 -88
  109. package/dist/components/MessageBlockItem.d.ts +0 -8
  110. package/dist/components/MessageBlockItem.js +0 -15
  111. package/dist/components/MessageList.d.ts +0 -10
  112. package/dist/components/MessageList.js +0 -80
  113. package/dist/components/ModelSelector.d.ts +0 -8
  114. package/dist/components/ModelSelector.js +0 -45
  115. package/dist/components/Notifications.d.ts +0 -7
  116. package/dist/components/Notifications.js +0 -9
  117. package/dist/components/PlanDisplay.d.ts +0 -7
  118. package/dist/components/PlanDisplay.js +0 -6
  119. package/dist/components/PluginDetail.d.ts +0 -2
  120. package/dist/components/PluginDetail.js +0 -87
  121. package/dist/components/PluginList.d.ts +0 -13
  122. package/dist/components/PluginList.js +0 -15
  123. package/dist/components/PluginManagerShell.d.ts +0 -6
  124. package/dist/components/PluginManagerShell.js +0 -92
  125. package/dist/components/PluginManagerTypes.d.ts +0 -35
  126. package/dist/components/PluginManagerTypes.js +0 -1
  127. package/dist/components/QueuedMessageList.d.ts +0 -2
  128. package/dist/components/QueuedMessageList.js +0 -18
  129. package/dist/components/ReasoningDisplay.d.ts +0 -8
  130. package/dist/components/ReasoningDisplay.js +0 -13
  131. package/dist/components/RewindCommand.d.ts +0 -12
  132. package/dist/components/RewindCommand.js +0 -78
  133. package/dist/components/SessionSelector.d.ts +0 -12
  134. package/dist/components/SessionSelector.js +0 -47
  135. package/dist/components/StatusCommand.d.ts +0 -5
  136. package/dist/components/StatusCommand.js +0 -28
  137. package/dist/components/StatusLine.d.ts +0 -6
  138. package/dist/components/StatusLine.js +0 -9
  139. package/dist/components/TaskList.d.ts +0 -5
  140. package/dist/components/TaskList.js +0 -197
  141. package/dist/components/TaskNotificationMessage.d.ts +0 -5
  142. package/dist/components/TaskNotificationMessage.js +0 -12
  143. package/dist/components/ToolDisplay.d.ts +0 -9
  144. package/dist/components/ToolDisplay.js +0 -55
  145. package/dist/components/WorkflowManager.d.ts +0 -5
  146. package/dist/components/WorkflowManager.js +0 -102
  147. package/dist/components/WorktreeExitPrompt.d.ts +0 -12
  148. package/dist/components/WorktreeExitPrompt.js +0 -35
  149. package/dist/constants/commands.d.ts +0 -2
  150. package/dist/constants/commands.js +0 -92
  151. package/dist/contexts/PluginManagerContext.d.ts +0 -3
  152. package/dist/contexts/PluginManagerContext.js +0 -9
  153. package/dist/contexts/useAppConfig.d.ts +0 -10
  154. package/dist/contexts/useAppConfig.js +0 -13
  155. package/dist/contexts/useChat.d.ts +0 -101
  156. package/dist/contexts/useChat.js +0 -993
  157. package/dist/contracts/status.d.ts +0 -7
  158. package/dist/contracts/status.js +0 -1
  159. package/dist/daemon/commands.d.ts +0 -49
  160. package/dist/daemon/commands.js +0 -341
  161. package/dist/daemon/jsonRpcClient.d.ts +0 -38
  162. package/dist/daemon/jsonRpcClient.js +0 -129
  163. package/dist/daemon/socketClient.d.ts +0 -13
  164. package/dist/daemon/socketClient.js +0 -26
  165. package/dist/daemon-cli.d.ts +0 -10
  166. package/dist/daemon-cli.js +0 -15
  167. package/dist/hooks/useInputManager.d.ts +0 -75
  168. package/dist/hooks/useInputManager.js +0 -583
  169. package/dist/hooks/usePluginManager.d.ts +0 -4
  170. package/dist/hooks/usePluginManager.js +0 -265
  171. package/dist/hooks/useTasks.d.ts +0 -1
  172. package/dist/hooks/useTasks.js +0 -5
  173. package/dist/index.d.ts +0 -4
  174. package/dist/index.js +0 -447
  175. package/dist/managers/inputHandlers.d.ts +0 -30
  176. package/dist/managers/inputHandlers.js +0 -625
  177. package/dist/managers/inputReducer.d.ts +0 -271
  178. package/dist/managers/inputReducer.js +0 -1121
  179. package/dist/plugin-manager-cli.d.ts +0 -5
  180. package/dist/plugin-manager-cli.js +0 -12
  181. package/dist/print-cli.d.ts +0 -10
  182. package/dist/print-cli.js +0 -209
  183. package/dist/reducers/agentsManagerReducer.d.ts +0 -26
  184. package/dist/reducers/agentsManagerReducer.js +0 -54
  185. package/dist/reducers/backgroundTaskManagerReducer.d.ts +0 -62
  186. package/dist/reducers/backgroundTaskManagerReducer.js +0 -106
  187. package/dist/reducers/confirmationReducer.d.ts +0 -37
  188. package/dist/reducers/confirmationReducer.js +0 -193
  189. package/dist/reducers/helpSelectorReducer.d.ts +0 -25
  190. package/dist/reducers/helpSelectorReducer.js +0 -52
  191. package/dist/reducers/marketplaceAddFormReducer.d.ts +0 -24
  192. package/dist/reducers/marketplaceAddFormReducer.js +0 -58
  193. package/dist/reducers/mcpManagerReducer.d.ts +0 -37
  194. package/dist/reducers/mcpManagerReducer.js +0 -74
  195. package/dist/reducers/pluginDetailReducer.d.ts +0 -32
  196. package/dist/reducers/pluginDetailReducer.js +0 -70
  197. package/dist/reducers/questionReducer.d.ts +0 -82
  198. package/dist/reducers/questionReducer.js +0 -375
  199. package/dist/reducers/rewindSelectorReducer.d.ts +0 -21
  200. package/dist/reducers/rewindSelectorReducer.js +0 -37
  201. package/dist/reducers/selectorReducer.d.ts +0 -23
  202. package/dist/reducers/selectorReducer.js +0 -42
  203. package/dist/reducers/workflowManagerReducer.d.ts +0 -40
  204. package/dist/reducers/workflowManagerReducer.js +0 -100
  205. package/dist/session-selector-cli.d.ts +0 -3
  206. package/dist/session-selector-cli.js +0 -25
  207. package/dist/stdio/agentBridge.d.ts +0 -139
  208. package/dist/stdio/agentBridge.js +0 -999
  209. package/dist/stdio/daemonServer.d.ts +0 -67
  210. package/dist/stdio/daemonServer.js +0 -191
  211. package/dist/stdio/index.d.ts +0 -5
  212. package/dist/stdio/index.js +0 -5
  213. package/dist/stdio/jsonRpcConnection.d.ts +0 -39
  214. package/dist/stdio/jsonRpcConnection.js +0 -135
  215. package/dist/stdio/protocol.d.ts +0 -41
  216. package/dist/stdio/protocol.js +0 -26
  217. package/dist/stdio/stdioServer.d.ts +0 -36
  218. package/dist/stdio/stdioServer.js +0 -51
  219. package/dist/stdio-cli.d.ts +0 -8
  220. package/dist/stdio-cli.js +0 -15
  221. package/dist/types.d.ts +0 -20
  222. package/dist/types.js +0 -1
  223. package/dist/utils/bracketedPaste.d.ts +0 -39
  224. package/dist/utils/bracketedPaste.js +0 -122
  225. package/dist/utils/clipboard.d.ts +0 -21
  226. package/dist/utils/clipboard.js +0 -347
  227. package/dist/utils/constants.d.ts +0 -16
  228. package/dist/utils/constants.js +0 -18
  229. package/dist/utils/highlightUtils.d.ts +0 -1
  230. package/dist/utils/highlightUtils.js +0 -93
  231. package/dist/utils/inputUtils.d.ts +0 -17
  232. package/dist/utils/inputUtils.js +0 -67
  233. package/dist/utils/logger.d.ts +0 -71
  234. package/dist/utils/logger.js +0 -259
  235. package/dist/utils/markdownTable.d.ts +0 -34
  236. package/dist/utils/markdownTable.js +0 -302
  237. package/dist/utils/rewindCheckpoints.d.ts +0 -8
  238. package/dist/utils/rewindCheckpoints.js +0 -17
  239. package/dist/utils/throttle.d.ts +0 -14
  240. package/dist/utils/throttle.js +0 -55
  241. package/dist/utils/toolParameterTransforms.d.ts +0 -18
  242. package/dist/utils/toolParameterTransforms.js +0 -73
  243. package/dist/utils/usageSummary.d.ts +0 -28
  244. package/dist/utils/usageSummary.js +0 -121
  245. package/dist/utils/version.d.ts +0 -1
  246. package/dist/utils/version.js +0 -4
  247. package/dist/utils/worktree.d.ts +0 -35
  248. package/dist/utils/worktree.js +0 -219
@@ -6,7 +6,12 @@ import {
6
6
  getDefaultRemoteBranch,
7
7
  getGitMainRepoRoot,
8
8
  performPostCreationSetup,
9
+ loadMergedWaveConfig,
10
+ hasWorktreeCreateHook,
11
+ executeWorktreeCreateHook,
12
+ executeWorktreeRemoveHook,
9
13
  } from "wave-agent-sdk";
14
+ import { logger } from "./logger.js";
10
15
 
11
16
  // Never use execFileSync here: the shared `wave --stdio` process handles all
12
17
  // desktop sessions, so a synchronous git call (especially a multi-second
@@ -21,6 +26,12 @@ export interface WorktreeSession {
21
26
  hasUncommittedChanges: boolean;
22
27
  hasNewCommits: boolean;
23
28
  isNew: boolean;
29
+ /**
30
+ * True when this worktree was created by a WorktreeCreate hook (not by git).
31
+ * Removal delegates to the WorktreeRemove hook; wave never runs
32
+ * `git worktree remove` for hook-based worktrees (aligned with Claude Code).
33
+ */
34
+ hookBased?: boolean;
24
35
  }
25
36
 
26
37
  // --- Worktree name validation ------------------------------------------------
@@ -55,6 +66,49 @@ export function validateWorktreeSlug(name: string): void {
55
66
  }
56
67
  }
57
68
 
69
+ /**
70
+ * List all worktree paths of the git repository containing `cwd`.
71
+ *
72
+ * Uses `git worktree list --porcelain` (same discovery Claude Code uses for
73
+ * its resume picker). The current worktree is returned first (when `cwd` is
74
+ * inside one), followed by the remaining worktrees alphabetically.
75
+ *
76
+ * @param cwd Directory to run the git command from
77
+ * @returns Array of absolute worktree paths; empty when git is unavailable,
78
+ * `cwd` is not inside a git repository, or the repo has a single worktree.
79
+ */
80
+ export async function listWorktrees(cwd: string): Promise<string[]> {
81
+ try {
82
+ const { stdout } = await execFileAsync(
83
+ "git",
84
+ ["worktree", "list", "--porcelain"],
85
+ { cwd },
86
+ );
87
+
88
+ const worktreePaths = stdout
89
+ .split("\n")
90
+ .filter((line) => line.startsWith("worktree "))
91
+ .map((line) => line.slice("worktree ".length).normalize("NFC"));
92
+
93
+ if (worktreePaths.length <= 1) return worktreePaths;
94
+
95
+ // Current worktree first, then alphabetical
96
+ const currentWorktree = worktreePaths.find(
97
+ (wt) => cwd === wt || cwd.startsWith(wt + path.sep),
98
+ );
99
+ const otherWorktrees = worktreePaths
100
+ .filter((wt) => wt !== currentWorktree)
101
+ .sort((a, b) => a.localeCompare(b));
102
+
103
+ return currentWorktree
104
+ ? [currentWorktree, ...otherWorktrees]
105
+ : otherWorktrees;
106
+ } catch {
107
+ // Not a git repository, git unavailable, or command failed
108
+ return [];
109
+ }
110
+ }
111
+
58
112
  /**
59
113
  * Create a new git worktree
60
114
  * @param name Worktree name
@@ -70,6 +124,33 @@ export async function createWorktree(
70
124
  options?: { baseRef?: "fresh" | "head"; baseBranch?: string },
71
125
  ): Promise<WorktreeSession> {
72
126
  validateWorktreeSlug(name);
127
+
128
+ // Hook-based creation first (allows user-configured VCS, including non-git).
129
+ // The hook prints the created worktree's absolute path to stdout; wave never
130
+ // runs `git worktree add` when a WorktreeCreate hook is configured.
131
+ const config = loadMergedWaveConfig(cwd);
132
+ if (hasWorktreeCreateHook(config?.hooks)) {
133
+ const { worktreePath } = await executeWorktreeCreateHook(
134
+ name,
135
+ config?.hooks,
136
+ {
137
+ projectDir: cwd,
138
+ sessionId: "",
139
+ env: config?.env,
140
+ },
141
+ );
142
+ return {
143
+ name,
144
+ path: worktreePath,
145
+ branch: "",
146
+ repoRoot: getGitMainRepoRoot(cwd) ?? cwd,
147
+ hasUncommittedChanges: false,
148
+ hasNewCommits: false,
149
+ isNew: true,
150
+ hookBased: true,
151
+ };
152
+ }
153
+
73
154
  const session = await createWorktreeInternal(name, cwd, options);
74
155
  if (session.isNew) {
75
156
  await performPostCreationSetup(session.path, session.repoRoot);
@@ -222,31 +303,80 @@ async function createWorktreeInternal(
222
303
  }
223
304
  }
224
305
 
306
+ /**
307
+ * On Windows, prefix an absolute path with the extended-length marker (`\\?\`)
308
+ * so recursive removal bypasses the 260-char MAX_PATH limit. POSIX paths are
309
+ * returned unchanged.
310
+ */
311
+ function toExtendedLengthPath(worktreePath: string): string {
312
+ if (process.platform !== "win32") {
313
+ return worktreePath;
314
+ }
315
+ const absolute = path.win32.resolve(worktreePath);
316
+ if (absolute.startsWith("\\\\?\\")) {
317
+ return absolute;
318
+ }
319
+ if (absolute.startsWith("\\\\")) {
320
+ // UNC path: \\server\share -> \\?\UNC\server\share
321
+ return `\\\\?\\UNC\\${absolute.slice(2)}`;
322
+ }
323
+ return `\\\\?\\${absolute}`;
324
+ }
325
+
225
326
  /**
226
327
  * Remove a git worktree and its associated branch
227
328
  * @param session Worktree session details
329
+ *
330
+ * Removal is best-effort: `git worktree remove --force` deletes the worktree
331
+ * metadata before the working directory, and on Windows its recursive deletion
332
+ * is MAX_PATH-limited — deep paths (e.g. node_modules) can fail with "Filename
333
+ * too long", leaving an orphan directory. When git fails we fall back to
334
+ * fs.rmSync with an extended-length path (bypasses MAX_PATH) and prune stale
335
+ * metadata. Failures are logged but never block branch deletion.
228
336
  */
229
337
  export async function removeWorktree(session: WorktreeSession): Promise<void> {
338
+ // Hook-based worktrees are removed by the WorktreeRemove hook; wave never
339
+ // runs `git worktree remove` for them. If no WorktreeRemove hook is
340
+ // configured, the worktree is left in place with a warning (CC semantics).
341
+ if (session.hookBased) {
342
+ const config = loadMergedWaveConfig(session.repoRoot);
343
+ const hookRan = await executeWorktreeRemoveHook(
344
+ session.path,
345
+ config?.hooks,
346
+ {
347
+ projectDir: session.repoRoot,
348
+ sessionId: "",
349
+ env: config?.env,
350
+ },
351
+ );
352
+ if (!hookRan) {
353
+ logger.warn(
354
+ `No WorktreeRemove hook configured, hook-based worktree left at: ${session.path}`,
355
+ );
356
+ }
357
+ return;
358
+ }
359
+
230
360
  const repoRoot = session.repoRoot;
231
361
 
362
+ // Get current branch in worktree before removing it
363
+ let currentBranch: string | undefined;
232
364
  try {
233
- // Get current branch in worktree before removing it
234
- let currentBranch: string | undefined;
235
- try {
236
- const { stdout } = await execFileAsync(
237
- "git",
238
- ["rev-parse", "--abbrev-ref", "HEAD"],
239
- {
240
- cwd: session.path,
241
- encoding: "utf8",
242
- },
243
- );
244
- currentBranch = stdout.trim();
245
- } catch {
246
- // Ignore errors getting current branch
247
- }
365
+ const { stdout } = await execFileAsync(
366
+ "git",
367
+ ["rev-parse", "--abbrev-ref", "HEAD"],
368
+ {
369
+ cwd: session.path,
370
+ encoding: "utf8",
371
+ },
372
+ );
373
+ currentBranch = stdout.trim();
374
+ } catch {
375
+ // Ignore errors getting current branch
376
+ }
248
377
 
249
- // Remove worktree
378
+ // Remove worktree
379
+ try {
250
380
  await execFileAsync(
251
381
  "git",
252
382
  ["worktree", "remove", "--force", session.path],
@@ -254,42 +384,60 @@ export async function removeWorktree(session: WorktreeSession): Promise<void> {
254
384
  cwd: repoRoot,
255
385
  },
256
386
  );
257
-
258
- // Delete original branch
387
+ } catch (error: unknown) {
388
+ logger.warn(
389
+ "git worktree remove failed, falling back to fs.rmSync:",
390
+ error,
391
+ );
392
+ try {
393
+ fs.rmSync(toExtendedLengthPath(session.path), {
394
+ recursive: true,
395
+ force: true,
396
+ });
397
+ } catch (rmError: unknown) {
398
+ logger.error("Failed to remove worktree or branch:", rmError);
399
+ }
400
+ // git removes worktree metadata before the working directory; prune any
401
+ // leftovers in case git failed before deleting them.
259
402
  try {
260
- await execFileAsync("git", ["branch", "-D", session.branch], {
403
+ await execFileAsync("git", ["worktree", "prune"], {
261
404
  cwd: repoRoot,
262
405
  });
263
406
  } catch {
264
- // Ignore errors deleting original branch
407
+ // Ignore errors pruning stale metadata
265
408
  }
409
+ }
410
+
411
+ // Delete original branch
412
+ try {
413
+ await execFileAsync("git", ["branch", "-D", session.branch], {
414
+ cwd: repoRoot,
415
+ });
416
+ } catch {
417
+ // Ignore errors deleting original branch
418
+ }
419
+
420
+ // Delete current branch if it's different and not a protected branch
421
+ if (
422
+ currentBranch &&
423
+ currentBranch !== session.branch &&
424
+ currentBranch !== "HEAD"
425
+ ) {
426
+ const defaultRemoteBranch = getDefaultRemoteBranch(repoRoot);
427
+ const defaultBranchName = defaultRemoteBranch.split("/").pop();
266
428
 
267
- // Delete current branch if it's different and not a protected branch
268
429
  if (
269
- currentBranch &&
270
- currentBranch !== session.branch &&
271
- currentBranch !== "HEAD"
430
+ currentBranch !== defaultBranchName &&
431
+ currentBranch !== "main" &&
432
+ currentBranch !== "master"
272
433
  ) {
273
- const defaultRemoteBranch = getDefaultRemoteBranch(repoRoot);
274
- const defaultBranchName = defaultRemoteBranch.split("/").pop();
275
-
276
- if (
277
- currentBranch !== defaultBranchName &&
278
- currentBranch !== "main" &&
279
- currentBranch !== "master"
280
- ) {
281
- try {
282
- await execFileAsync("git", ["branch", "-D", currentBranch], {
283
- cwd: repoRoot,
284
- });
285
- } catch {
286
- // Ignore errors deleting current branch
287
- }
434
+ try {
435
+ await execFileAsync("git", ["branch", "-D", currentBranch], {
436
+ cwd: repoRoot,
437
+ });
438
+ } catch {
439
+ // Ignore errors deleting current branch
288
440
  }
289
441
  }
290
- } catch (error: unknown) {
291
- console.error(
292
- `Failed to remove worktree or branch: ${(error as Error).message}`,
293
- );
294
442
  }
295
443
  }
package/dist/cli.d.ts DELETED
@@ -1,6 +0,0 @@
1
- import { BaseAppProps } from "./types.js";
2
- export interface CliOptions extends BaseAppProps {
3
- restoreSessionId?: string;
4
- continueLastSession?: boolean;
5
- }
6
- export declare function startCli(options: CliOptions): Promise<void>;
package/dist/cli.js DELETED
@@ -1,53 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { render } from "ink";
3
- import { App } from "./components/App.js";
4
- import { cleanupLogs } from "./utils/logger.js";
5
- import { removeWorktree } from "./utils/worktree.js";
6
- export async function startCli(options) {
7
- const { restoreSessionId, continueLastSession, bypassPermissions, permissionMode, pluginDirs, additionalDirectories, tools, allowedTools, disallowedTools, worktreeSession, workdir, originalCwd, version, model, mcpServers, } = options;
8
- // Continue with ink-based UI for normal mode
9
- let shouldRemoveWorktree = false;
10
- // Enable bracketed paste (DECSET 2004) so terminals wrap pasted text in
11
- // \x1b[200~ ... \x1b[201~ markers. The input pipeline uses these to insert
12
- // pasted text without submitting (a pasted trailing \r is not an Enter).
13
- // Terminals without bracketed-paste support ignore the sequence and paste
14
- // without markers, falling back to legacy behavior. No-op when stdout is
15
- // not a TTY (piped input, stdio mode).
16
- const stdoutIsTTY = process.stdout.isTTY === true;
17
- if (stdoutIsTTY) {
18
- process.stdout.write("\x1b[?2004h");
19
- }
20
- const handleExit = (shouldRemove) => {
21
- shouldRemoveWorktree = shouldRemove;
22
- unmount();
23
- };
24
- // Render the application
25
- const { unmount, waitUntilExit } = render(_jsx(App, { restoreSessionId: restoreSessionId, continueLastSession: continueLastSession, bypassPermissions: bypassPermissions, permissionMode: permissionMode, pluginDirs: pluginDirs, additionalDirectories: additionalDirectories, tools: tools, allowedTools: allowedTools, disallowedTools: disallowedTools, worktreeSession: worktreeSession, workdir: workdir, originalCwd: originalCwd, version: version, model: model, mcpServers: mcpServers, onExit: handleExit }), { exitOnCtrlC: false });
26
- // Wait for the app to finish unmounting
27
- try {
28
- await waitUntilExit();
29
- }
30
- finally {
31
- // Disable bracketed paste (DECSET 2004) so the terminal returns to its
32
- // previous paste handling.
33
- if (stdoutIsTTY) {
34
- process.stdout.write("\x1b[?2004l");
35
- }
36
- }
37
- try {
38
- // Clean up old log files
39
- await cleanupLogs().catch((error) => {
40
- console.warn("Failed to cleanup old logs:", error);
41
- });
42
- // Cleanup worktree if requested
43
- if (shouldRemoveWorktree && worktreeSession) {
44
- process.chdir(worktreeSession.repoRoot);
45
- await removeWorktree(worktreeSession);
46
- }
47
- process.exit(0);
48
- }
49
- catch (error) {
50
- console.error("Error during cleanup:", error);
51
- process.exit(1);
52
- }
53
- }
@@ -1,5 +0,0 @@
1
- import { Scope } from "wave-agent-sdk";
2
- export declare function disablePluginCommand(argv: {
3
- plugin: string;
4
- scope?: Scope;
5
- }): Promise<void>;
@@ -1,15 +0,0 @@
1
- import { PluginCore } from "wave-agent-sdk";
2
- export async function disablePluginCommand(argv) {
3
- const workdir = process.cwd();
4
- const pluginCore = new PluginCore(workdir);
5
- try {
6
- const scope = await pluginCore.disablePlugin(argv.plugin, argv.scope);
7
- console.log(`Successfully disabled plugin: ${argv.plugin} in ${scope} scope`);
8
- process.exit(0);
9
- }
10
- catch (error) {
11
- const message = error instanceof Error ? error.message : String(error);
12
- console.error(`Failed to disable plugin: ${message}`);
13
- process.exit(1);
14
- }
15
- }
@@ -1,5 +0,0 @@
1
- import { Scope } from "wave-agent-sdk";
2
- export declare function enablePluginCommand(argv: {
3
- plugin: string;
4
- scope?: Scope;
5
- }): Promise<void>;
@@ -1,15 +0,0 @@
1
- import { PluginCore } from "wave-agent-sdk";
2
- export async function enablePluginCommand(argv) {
3
- const workdir = process.cwd();
4
- const pluginCore = new PluginCore(workdir);
5
- try {
6
- const scope = await pluginCore.enablePlugin(argv.plugin, argv.scope);
7
- console.log(`Successfully enabled plugin: ${argv.plugin} in ${scope} scope`);
8
- process.exit(0);
9
- }
10
- catch (error) {
11
- const message = error instanceof Error ? error.message : String(error);
12
- console.error(`Failed to enable plugin: ${message}`);
13
- process.exit(1);
14
- }
15
- }
@@ -1,5 +0,0 @@
1
- import { Scope } from "wave-agent-sdk";
2
- export declare function installPluginCommand(argv: {
3
- plugin: string;
4
- scope?: Scope;
5
- }): Promise<void>;
@@ -1,21 +0,0 @@
1
- import { PluginCore } from "wave-agent-sdk";
2
- export async function installPluginCommand(argv) {
3
- const workdir = process.cwd();
4
- const pluginCore = new PluginCore(workdir);
5
- try {
6
- const installed = await pluginCore.installPlugin(argv.plugin);
7
- console.log(`Successfully installed plugin: ${installed.name} v${installed.version} from ${installed.marketplace}`);
8
- console.log(`Cache path: ${installed.cachePath}`);
9
- if (argv.scope) {
10
- const pluginId = `${installed.name}@${installed.marketplace}`;
11
- await pluginCore.enablePlugin(pluginId, argv.scope);
12
- console.log(`Plugin ${pluginId} enabled in ${argv.scope} scope`);
13
- }
14
- process.exit(0);
15
- }
16
- catch (error) {
17
- const message = error instanceof Error ? error.message : String(error);
18
- console.error(`Failed to install plugin: ${message}`);
19
- process.exit(1);
20
- }
21
- }
@@ -1 +0,0 @@
1
- export declare function listPluginsCommand(): Promise<void>;
@@ -1,31 +0,0 @@
1
- import { PluginCore } from "wave-agent-sdk";
2
- export async function listPluginsCommand() {
3
- const pluginCore = new PluginCore(process.cwd());
4
- try {
5
- const { plugins, mergedEnabled } = await pluginCore.listPlugins();
6
- if (plugins.length === 0) {
7
- console.log("No plugins found in registered marketplaces.");
8
- }
9
- else {
10
- console.log("Plugins:");
11
- plugins.forEach((p) => {
12
- const pluginId = `${p.name}@${p.marketplace}`;
13
- const isEnabled = mergedEnabled[pluginId] !== false;
14
- const status = p.installed
15
- ? isEnabled
16
- ? "enabled"
17
- : "disabled"
18
- : "not installed";
19
- const versionStr = p.version ? ` v${p.version}` : "";
20
- const scopeStr = p.scope ? ` (${p.scope})` : "";
21
- console.log(`- ${pluginId}${versionStr}${scopeStr} [${status}]`);
22
- });
23
- }
24
- process.exit(0);
25
- }
26
- catch (error) {
27
- const message = error instanceof Error ? error.message : String(error);
28
- console.error(`Failed to list plugins: ${message}`);
29
- process.exit(1);
30
- }
31
- }
@@ -1,10 +0,0 @@
1
- export declare function addMarketplaceCommand(argv: {
2
- input: string;
3
- }): Promise<void>;
4
- export declare function listMarketplacesCommand(): Promise<void>;
5
- export declare function removeMarketplaceCommand(argv: {
6
- name: string;
7
- }): Promise<void>;
8
- export declare function updateMarketplaceCommand(argv: {
9
- name?: string;
10
- }): Promise<void>;
@@ -1,90 +0,0 @@
1
- import { PluginCore } from "wave-agent-sdk";
2
- export async function addMarketplaceCommand(argv) {
3
- const pluginCore = new PluginCore(process.cwd());
4
- try {
5
- const marketplace = await pluginCore.addMarketplace(argv.input);
6
- const source = marketplace.source;
7
- let sourceInfo = "";
8
- if (source.source === "directory") {
9
- sourceInfo = source.path;
10
- }
11
- else if (source.source === "github") {
12
- sourceInfo = source.repo + (source.ref ? `#${source.ref}` : "");
13
- }
14
- else {
15
- sourceInfo = source.url + (source.ref ? `#${source.ref}` : "");
16
- }
17
- console.log(`Successfully added marketplace: ${marketplace.name} (${sourceInfo})`);
18
- process.exit(0);
19
- }
20
- catch (error) {
21
- const message = error instanceof Error ? error.message : String(error);
22
- console.error(`Failed to add marketplace: ${message}`);
23
- process.exit(1);
24
- }
25
- }
26
- export async function listMarketplacesCommand() {
27
- const pluginCore = new PluginCore(process.cwd());
28
- try {
29
- const marketplaces = await pluginCore.listMarketplaces();
30
- if (marketplaces.length === 0) {
31
- console.log("No marketplaces registered.");
32
- }
33
- else {
34
- console.log("Registered Marketplaces:");
35
- marketplaces.forEach((m) => {
36
- const source = m.source;
37
- let sourceInfo = "";
38
- if (source.source === "directory") {
39
- sourceInfo = source.path;
40
- }
41
- else if (source.source === "github") {
42
- sourceInfo = source.repo + (source.ref ? `#${source.ref}` : "");
43
- }
44
- else {
45
- sourceInfo = source.url + (source.ref ? `#${source.ref}` : "");
46
- }
47
- const builtinLabel = m.isBuiltin ? " [builtin]" : "";
48
- const lastUpdatedLabel = m.lastUpdated
49
- ? ` (Last updated: ${new Date(m.lastUpdated).toLocaleString()})`
50
- : "";
51
- console.log(`- ${m.name}${builtinLabel}: ${sourceInfo} (${m.source.source})${lastUpdatedLabel}`);
52
- });
53
- }
54
- process.exit(0);
55
- }
56
- catch (error) {
57
- const message = error instanceof Error ? error.message : String(error);
58
- console.error(`Failed to list marketplaces: ${message}`);
59
- process.exit(1);
60
- }
61
- }
62
- export async function removeMarketplaceCommand(argv) {
63
- const pluginCore = new PluginCore(process.cwd());
64
- try {
65
- await pluginCore.removeMarketplace(argv.name);
66
- console.log(`Successfully removed marketplace: ${argv.name}`);
67
- process.exit(0);
68
- }
69
- catch (error) {
70
- const message = error instanceof Error ? error.message : String(error);
71
- console.error(`Failed to remove marketplace: ${message}`);
72
- process.exit(1);
73
- }
74
- }
75
- export async function updateMarketplaceCommand(argv) {
76
- const pluginCore = new PluginCore(process.cwd());
77
- try {
78
- console.log(argv.name
79
- ? `Updating marketplace: ${argv.name}...`
80
- : "Updating all marketplaces...");
81
- await pluginCore.updateMarketplace(argv.name);
82
- console.log("Successfully updated.");
83
- process.exit(0);
84
- }
85
- catch (error) {
86
- const message = error instanceof Error ? error.message : String(error);
87
- console.error(`Failed to update marketplace: ${message}`);
88
- process.exit(1);
89
- }
90
- }
@@ -1,3 +0,0 @@
1
- export declare function uninstallPluginCommand(argv: {
2
- plugin: string;
3
- }): Promise<void>;
@@ -1,16 +0,0 @@
1
- import { PluginCore } from "wave-agent-sdk";
2
- export async function uninstallPluginCommand(argv) {
3
- const workdir = process.cwd();
4
- const pluginCore = new PluginCore(workdir);
5
- try {
6
- await pluginCore.uninstallPlugin(argv.plugin);
7
- console.log(`Successfully uninstalled plugin: ${argv.plugin}`);
8
- console.log(`Cleaned up plugin configuration from all scopes`);
9
- process.exit(0);
10
- }
11
- catch (error) {
12
- const message = error instanceof Error ? error.message : String(error);
13
- console.error(`Failed to uninstall plugin: ${message}`);
14
- process.exit(1);
15
- }
16
- }
@@ -1,3 +0,0 @@
1
- export declare function updatePluginCommand(argv: {
2
- plugin: string;
3
- }): Promise<void>;
@@ -1,15 +0,0 @@
1
- import { PluginCore } from "wave-agent-sdk";
2
- export async function updatePluginCommand(argv) {
3
- const pluginCore = new PluginCore(process.cwd());
4
- try {
5
- const updated = await pluginCore.updatePlugin(argv.plugin);
6
- console.log(`Successfully updated plugin: ${updated.name} v${updated.version} from ${updated.marketplace}`);
7
- console.log(`Cache path: ${updated.cachePath}`);
8
- process.exit(0);
9
- }
10
- catch (error) {
11
- const message = error instanceof Error ? error.message : String(error);
12
- console.error(`Failed to update plugin: ${message}`);
13
- process.exit(1);
14
- }
15
- }
@@ -1 +0,0 @@
1
- export declare function updateCommand(): Promise<void>;