wave-code 1.0.10 → 1.1.0
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.
- package/bin/wave-code.js +8 -2
- package/dist/bundle/wave.mjs +3207 -0
- package/package.json +24 -25
- package/src/commands/update.ts +2 -7
- package/src/components/App.tsx +3 -7
- package/src/components/BtwDisplay.tsx +10 -1
- package/src/components/ChatInterface.tsx +21 -52
- package/src/components/ConfirmationDetails.tsx +144 -37
- package/src/components/DiffDisplay.tsx +335 -301
- package/src/components/InputBox.tsx +3 -1
- package/src/components/LoadingIndicator.tsx +16 -2
- package/src/components/MessageBlockItem.tsx +2 -4
- package/src/components/MessageList.tsx +75 -14
- package/src/components/ReasoningDisplay.tsx +2 -4
- package/src/components/SessionSelector.tsx +82 -11
- package/src/components/StatusCommand.tsx +2 -9
- package/src/components/ToolDisplay.tsx +2 -4
- package/src/contexts/useChat.tsx +156 -335
- package/src/daemon/commands.ts +57 -27
- package/src/daemon/jsonRpcClient.ts +1 -1
- package/src/daemon/socketClient.ts +2 -2
- package/src/hooks/useInputManager.ts +1 -1
- package/src/index.ts +57 -10
- package/src/managers/inputReducer.ts +186 -104
- package/src/print-cli.ts +21 -17
- package/src/reducers/selectorReducer.ts +10 -0
- package/src/session-selector-cli.tsx +269 -28
- package/src/stdio/agentBridge.ts +22 -21
- package/src/stdio/daemonServer.ts +3 -1
- package/src/utils/clipboard.ts +21 -0
- package/src/utils/highlightUtils.ts +46 -1
- package/src/utils/readPackageJson.ts +29 -0
- package/src/utils/streamingText.ts +11 -0
- package/src/utils/worktree.ts +191 -43
- package/dist/cli.d.ts +0 -6
- package/dist/cli.js +0 -53
- package/dist/commands/plugin/disable.d.ts +0 -5
- package/dist/commands/plugin/disable.js +0 -15
- package/dist/commands/plugin/enable.d.ts +0 -5
- package/dist/commands/plugin/enable.js +0 -15
- package/dist/commands/plugin/install.d.ts +0 -5
- package/dist/commands/plugin/install.js +0 -21
- package/dist/commands/plugin/list.d.ts +0 -1
- package/dist/commands/plugin/list.js +0 -31
- package/dist/commands/plugin/marketplace.d.ts +0 -10
- package/dist/commands/plugin/marketplace.js +0 -90
- package/dist/commands/plugin/uninstall.d.ts +0 -3
- package/dist/commands/plugin/uninstall.js +0 -16
- package/dist/commands/plugin/update.d.ts +0 -3
- package/dist/commands/plugin/update.js +0 -15
- package/dist/commands/update.d.ts +0 -1
- package/dist/commands/update.js +0 -97
- package/dist/components/AgentsManager.d.ts +0 -7
- package/dist/components/AgentsManager.js +0 -109
- package/dist/components/App.d.ts +0 -9
- package/dist/components/App.js +0 -76
- package/dist/components/BackgroundTaskManager.d.ts +0 -5
- package/dist/components/BackgroundTaskManager.js +0 -99
- package/dist/components/BangDisplay.d.ts +0 -8
- package/dist/components/BangDisplay.js +0 -17
- package/dist/components/BtwDisplay.d.ts +0 -7
- package/dist/components/BtwDisplay.js +0 -19
- package/dist/components/ChatInterface.d.ts +0 -2
- package/dist/components/ChatInterface.js +0 -61
- package/dist/components/CommandSelector.d.ts +0 -10
- package/dist/components/CommandSelector.js +0 -66
- package/dist/components/CompactDisplay.d.ts +0 -8
- package/dist/components/CompactDisplay.js +0 -13
- package/dist/components/ConfirmationDetails.d.ts +0 -9
- package/dist/components/ConfirmationDetails.js +0 -45
- package/dist/components/ConfirmationSelector.d.ts +0 -13
- package/dist/components/ConfirmationSelector.js +0 -127
- package/dist/components/DiffDisplay.d.ts +0 -8
- package/dist/components/DiffDisplay.js +0 -201
- package/dist/components/DiscoverView.d.ts +0 -2
- package/dist/components/DiscoverView.js +0 -37
- package/dist/components/FileSelector.d.ts +0 -11
- package/dist/components/FileSelector.js +0 -50
- package/dist/components/HelpView.d.ts +0 -7
- package/dist/components/HelpView.js +0 -74
- package/dist/components/HistorySearch.d.ts +0 -8
- package/dist/components/HistorySearch.js +0 -66
- package/dist/components/InputBox.d.ts +0 -24
- package/dist/components/InputBox.js +0 -149
- package/dist/components/InstalledView.d.ts +0 -2
- package/dist/components/InstalledView.js +0 -45
- package/dist/components/LoadingIndicator.d.ts +0 -10
- package/dist/components/LoadingIndicator.js +0 -6
- package/dist/components/LoginCommand.d.ts +0 -5
- package/dist/components/LoginCommand.js +0 -153
- package/dist/components/Markdown.d.ts +0 -5
- package/dist/components/Markdown.js +0 -127
- package/dist/components/MarketplaceAddForm.d.ts +0 -2
- package/dist/components/MarketplaceAddForm.js +0 -55
- package/dist/components/MarketplaceDetail.d.ts +0 -2
- package/dist/components/MarketplaceDetail.js +0 -74
- package/dist/components/MarketplaceList.d.ts +0 -8
- package/dist/components/MarketplaceList.js +0 -17
- package/dist/components/MarketplaceView.d.ts +0 -2
- package/dist/components/MarketplaceView.js +0 -41
- package/dist/components/McpManager.d.ts +0 -9
- package/dist/components/McpManager.js +0 -88
- package/dist/components/MessageBlockItem.d.ts +0 -8
- package/dist/components/MessageBlockItem.js +0 -15
- package/dist/components/MessageList.d.ts +0 -10
- package/dist/components/MessageList.js +0 -80
- package/dist/components/ModelSelector.d.ts +0 -8
- package/dist/components/ModelSelector.js +0 -45
- package/dist/components/Notifications.d.ts +0 -7
- package/dist/components/Notifications.js +0 -9
- package/dist/components/PlanDisplay.d.ts +0 -7
- package/dist/components/PlanDisplay.js +0 -6
- package/dist/components/PluginDetail.d.ts +0 -2
- package/dist/components/PluginDetail.js +0 -87
- package/dist/components/PluginList.d.ts +0 -13
- package/dist/components/PluginList.js +0 -15
- package/dist/components/PluginManagerShell.d.ts +0 -6
- package/dist/components/PluginManagerShell.js +0 -92
- package/dist/components/PluginManagerTypes.d.ts +0 -35
- package/dist/components/PluginManagerTypes.js +0 -1
- package/dist/components/QueuedMessageList.d.ts +0 -2
- package/dist/components/QueuedMessageList.js +0 -18
- package/dist/components/ReasoningDisplay.d.ts +0 -8
- package/dist/components/ReasoningDisplay.js +0 -13
- package/dist/components/RewindCommand.d.ts +0 -12
- package/dist/components/RewindCommand.js +0 -78
- package/dist/components/SessionSelector.d.ts +0 -12
- package/dist/components/SessionSelector.js +0 -47
- package/dist/components/StatusCommand.d.ts +0 -5
- package/dist/components/StatusCommand.js +0 -28
- package/dist/components/StatusLine.d.ts +0 -6
- package/dist/components/StatusLine.js +0 -9
- package/dist/components/TaskList.d.ts +0 -5
- package/dist/components/TaskList.js +0 -197
- package/dist/components/TaskNotificationMessage.d.ts +0 -5
- package/dist/components/TaskNotificationMessage.js +0 -12
- package/dist/components/ToolDisplay.d.ts +0 -9
- package/dist/components/ToolDisplay.js +0 -55
- package/dist/components/WorkflowManager.d.ts +0 -5
- package/dist/components/WorkflowManager.js +0 -102
- package/dist/components/WorktreeExitPrompt.d.ts +0 -12
- package/dist/components/WorktreeExitPrompt.js +0 -35
- package/dist/constants/commands.d.ts +0 -2
- package/dist/constants/commands.js +0 -92
- package/dist/contexts/PluginManagerContext.d.ts +0 -3
- package/dist/contexts/PluginManagerContext.js +0 -9
- package/dist/contexts/useAppConfig.d.ts +0 -10
- package/dist/contexts/useAppConfig.js +0 -13
- package/dist/contexts/useChat.d.ts +0 -101
- package/dist/contexts/useChat.js +0 -993
- package/dist/contracts/status.d.ts +0 -7
- package/dist/contracts/status.js +0 -1
- package/dist/daemon/commands.d.ts +0 -49
- package/dist/daemon/commands.js +0 -341
- package/dist/daemon/jsonRpcClient.d.ts +0 -38
- package/dist/daemon/jsonRpcClient.js +0 -129
- package/dist/daemon/socketClient.d.ts +0 -13
- package/dist/daemon/socketClient.js +0 -26
- package/dist/daemon-cli.d.ts +0 -10
- package/dist/daemon-cli.js +0 -15
- package/dist/hooks/useInputManager.d.ts +0 -75
- package/dist/hooks/useInputManager.js +0 -583
- package/dist/hooks/usePluginManager.d.ts +0 -4
- package/dist/hooks/usePluginManager.js +0 -265
- package/dist/hooks/useTasks.d.ts +0 -1
- package/dist/hooks/useTasks.js +0 -5
- package/dist/index.d.ts +0 -4
- package/dist/index.js +0 -447
- package/dist/managers/inputHandlers.d.ts +0 -30
- package/dist/managers/inputHandlers.js +0 -625
- package/dist/managers/inputReducer.d.ts +0 -271
- package/dist/managers/inputReducer.js +0 -1121
- package/dist/plugin-manager-cli.d.ts +0 -5
- package/dist/plugin-manager-cli.js +0 -12
- package/dist/print-cli.d.ts +0 -10
- package/dist/print-cli.js +0 -209
- package/dist/reducers/agentsManagerReducer.d.ts +0 -26
- package/dist/reducers/agentsManagerReducer.js +0 -54
- package/dist/reducers/backgroundTaskManagerReducer.d.ts +0 -62
- package/dist/reducers/backgroundTaskManagerReducer.js +0 -106
- package/dist/reducers/confirmationReducer.d.ts +0 -37
- package/dist/reducers/confirmationReducer.js +0 -193
- package/dist/reducers/helpSelectorReducer.d.ts +0 -25
- package/dist/reducers/helpSelectorReducer.js +0 -52
- package/dist/reducers/marketplaceAddFormReducer.d.ts +0 -24
- package/dist/reducers/marketplaceAddFormReducer.js +0 -58
- package/dist/reducers/mcpManagerReducer.d.ts +0 -37
- package/dist/reducers/mcpManagerReducer.js +0 -74
- package/dist/reducers/pluginDetailReducer.d.ts +0 -32
- package/dist/reducers/pluginDetailReducer.js +0 -70
- package/dist/reducers/questionReducer.d.ts +0 -82
- package/dist/reducers/questionReducer.js +0 -375
- package/dist/reducers/rewindSelectorReducer.d.ts +0 -21
- package/dist/reducers/rewindSelectorReducer.js +0 -37
- package/dist/reducers/selectorReducer.d.ts +0 -23
- package/dist/reducers/selectorReducer.js +0 -42
- package/dist/reducers/workflowManagerReducer.d.ts +0 -40
- package/dist/reducers/workflowManagerReducer.js +0 -100
- package/dist/session-selector-cli.d.ts +0 -3
- package/dist/session-selector-cli.js +0 -25
- package/dist/stdio/agentBridge.d.ts +0 -139
- package/dist/stdio/agentBridge.js +0 -999
- package/dist/stdio/daemonServer.d.ts +0 -67
- package/dist/stdio/daemonServer.js +0 -191
- package/dist/stdio/index.d.ts +0 -5
- package/dist/stdio/index.js +0 -5
- package/dist/stdio/jsonRpcConnection.d.ts +0 -39
- package/dist/stdio/jsonRpcConnection.js +0 -135
- package/dist/stdio/protocol.d.ts +0 -41
- package/dist/stdio/protocol.js +0 -26
- package/dist/stdio/stdioServer.d.ts +0 -36
- package/dist/stdio/stdioServer.js +0 -51
- package/dist/stdio-cli.d.ts +0 -8
- package/dist/stdio-cli.js +0 -15
- package/dist/types.d.ts +0 -20
- package/dist/types.js +0 -1
- package/dist/utils/bracketedPaste.d.ts +0 -39
- package/dist/utils/bracketedPaste.js +0 -122
- package/dist/utils/clipboard.d.ts +0 -21
- package/dist/utils/clipboard.js +0 -347
- package/dist/utils/constants.d.ts +0 -16
- package/dist/utils/constants.js +0 -18
- package/dist/utils/highlightUtils.d.ts +0 -1
- package/dist/utils/highlightUtils.js +0 -93
- package/dist/utils/inputUtils.d.ts +0 -17
- package/dist/utils/inputUtils.js +0 -67
- package/dist/utils/logger.d.ts +0 -71
- package/dist/utils/logger.js +0 -259
- package/dist/utils/markdownTable.d.ts +0 -34
- package/dist/utils/markdownTable.js +0 -302
- package/dist/utils/rewindCheckpoints.d.ts +0 -8
- package/dist/utils/rewindCheckpoints.js +0 -17
- package/dist/utils/throttle.d.ts +0 -14
- package/dist/utils/throttle.js +0 -55
- package/dist/utils/toolParameterTransforms.d.ts +0 -18
- package/dist/utils/toolParameterTransforms.js +0 -73
- package/dist/utils/usageSummary.d.ts +0 -28
- package/dist/utils/usageSummary.js +0 -121
- package/dist/utils/version.d.ts +0 -1
- package/dist/utils/version.js +0 -4
- package/dist/utils/worktree.d.ts +0 -35
- package/dist/utils/worktree.js +0 -219
package/src/utils/worktree.ts
CHANGED
|
@@ -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
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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", ["
|
|
403
|
+
await execFileAsync("git", ["worktree", "prune"], {
|
|
261
404
|
cwd: repoRoot,
|
|
262
405
|
});
|
|
263
406
|
} catch {
|
|
264
|
-
// Ignore errors
|
|
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 !==
|
|
271
|
-
currentBranch !== "
|
|
430
|
+
currentBranch !== defaultBranchName &&
|
|
431
|
+
currentBranch !== "main" &&
|
|
432
|
+
currentBranch !== "master"
|
|
272
433
|
) {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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
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,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,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,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,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,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>;
|