wave-code 0.7.1 → 0.8.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/dist/cli.d.ts +2 -4
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +24 -52
- package/dist/components/App.d.ts +3 -4
- package/dist/components/App.d.ts.map +1 -1
- package/dist/components/App.js +49 -6
- package/dist/components/BackgroundTaskManager.d.ts.map +1 -1
- package/dist/components/BackgroundTaskManager.js +12 -20
- package/dist/components/BangDisplay.d.ts +9 -0
- package/dist/components/BangDisplay.d.ts.map +1 -0
- package/dist/components/{CommandOutputDisplay.js → BangDisplay.js} +1 -1
- package/dist/components/ChatInterface.d.ts.map +1 -1
- package/dist/components/ChatInterface.js +3 -2
- package/dist/components/CommandSelector.d.ts.map +1 -1
- package/dist/components/CommandSelector.js +18 -2
- package/dist/components/ConfirmationSelector.d.ts.map +1 -1
- package/dist/components/ConfirmationSelector.js +105 -8
- package/dist/components/HelpView.d.ts.map +1 -1
- package/dist/components/HelpView.js +2 -0
- package/dist/components/HistorySearch.d.ts.map +1 -1
- package/dist/components/HistorySearch.js +19 -25
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +9 -3
- package/dist/components/MarketplaceAddForm.d.ts.map +1 -1
- package/dist/components/MarketplaceAddForm.js +13 -6
- package/dist/components/MarketplaceDetail.d.ts.map +1 -1
- package/dist/components/MarketplaceDetail.js +8 -3
- package/dist/components/MessageBlockItem.js +2 -2
- package/dist/components/MessageList.d.ts +4 -1
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +15 -8
- package/dist/components/PluginDetail.d.ts.map +1 -1
- package/dist/components/PluginDetail.js +14 -3
- package/dist/components/PluginManagerShell.d.ts.map +1 -1
- package/dist/components/PluginManagerShell.js +3 -3
- package/dist/components/PluginManagerTypes.d.ts +2 -0
- package/dist/components/PluginManagerTypes.d.ts.map +1 -1
- package/dist/components/SessionSelector.d.ts.map +1 -1
- package/dist/components/SessionSelector.js +10 -13
- package/dist/components/StatusCommand.d.ts +6 -0
- package/dist/components/StatusCommand.d.ts.map +1 -0
- package/dist/components/StatusCommand.js +28 -0
- package/dist/components/WorktreeExitPrompt.d.ts +13 -0
- package/dist/components/WorktreeExitPrompt.d.ts.map +1 -0
- package/dist/components/WorktreeExitPrompt.js +26 -0
- package/dist/contexts/useChat.d.ts +9 -5
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +38 -8
- package/dist/contracts/status.d.ts +8 -0
- package/dist/contracts/status.d.ts.map +1 -0
- package/dist/contracts/status.js +1 -0
- package/dist/hooks/useInputManager.d.ts +2 -0
- package/dist/hooks/useInputManager.d.ts.map +1 -1
- package/dist/hooks/useInputManager.js +12 -0
- package/dist/hooks/usePluginManager.d.ts.map +1 -1
- package/dist/hooks/usePluginManager.js +41 -13
- package/dist/hooks/useTasks.js +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +53 -4
- package/dist/managers/InputManager.d.ts +6 -0
- package/dist/managers/InputManager.d.ts.map +1 -1
- package/dist/managers/InputManager.js +32 -13
- package/dist/print-cli.d.ts +2 -4
- package/dist/print-cli.d.ts.map +1 -1
- package/dist/print-cli.js +31 -2
- package/dist/session-selector-cli.d.ts +3 -1
- package/dist/session-selector-cli.d.ts.map +1 -1
- package/dist/session-selector-cli.js +2 -2
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/utils/worktree.d.ts +23 -0
- package/dist/utils/worktree.d.ts.map +1 -0
- package/dist/utils/worktree.js +135 -0
- package/package.json +2 -2
- package/src/cli.tsx +36 -59
- package/src/components/App.tsx +99 -11
- package/src/components/BackgroundTaskManager.tsx +12 -20
- package/src/components/{CommandOutputDisplay.tsx → BangDisplay.tsx} +4 -4
- package/src/components/ChatInterface.tsx +8 -0
- package/src/components/CommandSelector.tsx +18 -1
- package/src/components/ConfirmationSelector.tsx +118 -9
- package/src/components/HelpView.tsx +2 -0
- package/src/components/HistorySearch.tsx +25 -30
- package/src/components/InputBox.tsx +11 -1
- package/src/components/MarketplaceAddForm.tsx +21 -8
- package/src/components/MarketplaceDetail.tsx +19 -4
- package/src/components/MessageBlockItem.tsx +3 -3
- package/src/components/MessageList.tsx +47 -23
- package/src/components/PluginDetail.tsx +30 -6
- package/src/components/PluginManagerShell.tsx +24 -6
- package/src/components/PluginManagerTypes.ts +2 -0
- package/src/components/SessionSelector.tsx +38 -24
- package/src/components/StatusCommand.tsx +94 -0
- package/src/components/WorktreeExitPrompt.tsx +86 -0
- package/src/contexts/useChat.tsx +57 -13
- package/src/contracts/status.ts +7 -0
- package/src/hooks/useInputManager.ts +12 -0
- package/src/hooks/usePluginManager.ts +47 -13
- package/src/hooks/useTasks.ts +2 -2
- package/src/index.ts +71 -12
- package/src/managers/InputManager.ts +37 -15
- package/src/print-cli.ts +48 -5
- package/src/session-selector-cli.tsx +6 -2
- package/src/types.ts +11 -0
- package/src/utils/worktree.ts +164 -0
- package/dist/components/CommandOutputDisplay.d.ts +0 -9
- package/dist/components/CommandOutputDisplay.d.ts.map +0 -1
package/src/contexts/useChat.tsx
CHANGED
|
@@ -25,6 +25,8 @@ import {
|
|
|
25
25
|
import { logger } from "../utils/logger.js";
|
|
26
26
|
import { displayUsageSummary } from "../utils/usageSummary.js";
|
|
27
27
|
|
|
28
|
+
import { BaseAppProps } from "../types.js";
|
|
29
|
+
|
|
28
30
|
// Main Chat Context
|
|
29
31
|
export interface ChatContextType {
|
|
30
32
|
messages: Message[];
|
|
@@ -43,14 +45,15 @@ export interface ChatContextType {
|
|
|
43
45
|
) => Promise<void>;
|
|
44
46
|
abortMessage: () => void;
|
|
45
47
|
latestTotalTokens: number;
|
|
48
|
+
clearMessages: () => void;
|
|
46
49
|
// MCP functionality
|
|
47
50
|
mcpServers: McpServerStatus[];
|
|
48
51
|
connectMcpServer: (serverName: string) => Promise<boolean>;
|
|
49
52
|
disconnectMcpServer: (serverName: string) => Promise<boolean>;
|
|
50
53
|
// Background tasks
|
|
51
54
|
backgroundTasks: BackgroundTask[];
|
|
52
|
-
//
|
|
53
|
-
|
|
55
|
+
// Tasks
|
|
56
|
+
tasks: Task[];
|
|
54
57
|
getBackgroundTaskOutput: (
|
|
55
58
|
taskId: string,
|
|
56
59
|
) => { stdout: string; stderr: string; status: string } | null;
|
|
@@ -92,6 +95,12 @@ export interface ChatContextType {
|
|
|
92
95
|
}>;
|
|
93
96
|
wasLastDetailsTooTall: number;
|
|
94
97
|
setWasLastDetailsTooTall: React.Dispatch<React.SetStateAction<number>>;
|
|
98
|
+
// Status metadata
|
|
99
|
+
getGatewayConfig: () => import("wave-agent-sdk").GatewayConfig;
|
|
100
|
+
getModelConfig: () => import("wave-agent-sdk").ModelConfig;
|
|
101
|
+
workingDirectory: string;
|
|
102
|
+
version?: string;
|
|
103
|
+
workdir?: string;
|
|
95
104
|
}
|
|
96
105
|
|
|
97
106
|
const ChatContext = createContext<ChatContextType | null>(null);
|
|
@@ -104,11 +113,8 @@ export const useChat = () => {
|
|
|
104
113
|
return context;
|
|
105
114
|
};
|
|
106
115
|
|
|
107
|
-
export interface ChatProviderProps {
|
|
116
|
+
export interface ChatProviderProps extends BaseAppProps {
|
|
108
117
|
children: React.ReactNode;
|
|
109
|
-
bypassPermissions?: boolean;
|
|
110
|
-
pluginDirs?: string[];
|
|
111
|
-
tools?: string[];
|
|
112
118
|
}
|
|
113
119
|
|
|
114
120
|
export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
@@ -116,6 +122,10 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
116
122
|
bypassPermissions,
|
|
117
123
|
pluginDirs,
|
|
118
124
|
tools,
|
|
125
|
+
workdir,
|
|
126
|
+
worktreeSession,
|
|
127
|
+
version,
|
|
128
|
+
model,
|
|
119
129
|
}) => {
|
|
120
130
|
const { restoreSessionId, continueLastSession } = useAppConfig();
|
|
121
131
|
|
|
@@ -144,8 +154,8 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
144
154
|
|
|
145
155
|
// Background tasks state
|
|
146
156
|
const [backgroundTasks, setBackgroundTasks] = useState<BackgroundTask[]>([]);
|
|
147
|
-
//
|
|
148
|
-
const [
|
|
157
|
+
// Tasks state
|
|
158
|
+
const [tasks, setTasks] = useState<Task[]>([]);
|
|
149
159
|
|
|
150
160
|
// Command state
|
|
151
161
|
const [slashCommands, setSlashCommands] = useState<SlashCommand[]>([]);
|
|
@@ -195,6 +205,9 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
195
205
|
// Rewind state
|
|
196
206
|
const [rewindId, setRewindId] = useState(0);
|
|
197
207
|
|
|
208
|
+
// Status metadata state
|
|
209
|
+
const [workingDirectory, setWorkingDirectory] = useState("");
|
|
210
|
+
|
|
198
211
|
// Confirmation too tall state
|
|
199
212
|
const [wasLastDetailsTooTall, setWasLastDetailsTooTall] = useState(0);
|
|
200
213
|
|
|
@@ -237,7 +250,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
237
250
|
setMessages([...agentRef.current.messages]);
|
|
238
251
|
}
|
|
239
252
|
messagesUpdateTimerRef.current = null;
|
|
240
|
-
},
|
|
253
|
+
}, 100);
|
|
241
254
|
}
|
|
242
255
|
}
|
|
243
256
|
},
|
|
@@ -253,11 +266,11 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
253
266
|
onCompressionStateChange: (isCompressingState) => {
|
|
254
267
|
setIsCompressing(isCompressingState);
|
|
255
268
|
},
|
|
256
|
-
|
|
269
|
+
onBackgroundTasksChange: (tasks) => {
|
|
257
270
|
setBackgroundTasks([...tasks]);
|
|
258
271
|
},
|
|
259
|
-
|
|
260
|
-
|
|
272
|
+
onTasksChange: (tasks) => {
|
|
273
|
+
setTasks([...tasks]);
|
|
261
274
|
},
|
|
262
275
|
onSubagentMessagesChange: (subagentId: string, messages: Message[]) => {
|
|
263
276
|
logger.debug("onSubagentMessagesChange", subagentId, messages.length);
|
|
@@ -316,6 +329,10 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
316
329
|
stream: false, // 关闭流式模式
|
|
317
330
|
plugins: pluginDirs?.map((path) => ({ type: "local", path })),
|
|
318
331
|
tools,
|
|
332
|
+
workdir,
|
|
333
|
+
worktreeName: worktreeSession?.name,
|
|
334
|
+
isNewWorktree: worktreeSession?.isNew,
|
|
335
|
+
model,
|
|
319
336
|
});
|
|
320
337
|
|
|
321
338
|
agentRef.current = agent;
|
|
@@ -328,6 +345,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
328
345
|
setIsCommandRunning(agent.isCommandRunning);
|
|
329
346
|
setIsCompressing(agent.isCompressing);
|
|
330
347
|
setPermissionModeState(agent.getPermissionMode());
|
|
348
|
+
setWorkingDirectory(agent.workingDirectory);
|
|
331
349
|
|
|
332
350
|
// Get initial MCP servers state
|
|
333
351
|
const mcpServers = agent.getMcpServers?.() || [];
|
|
@@ -349,6 +367,8 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
349
367
|
showConfirmation,
|
|
350
368
|
pluginDirs,
|
|
351
369
|
tools,
|
|
370
|
+
workdir,
|
|
371
|
+
worktreeSession,
|
|
352
372
|
]);
|
|
353
373
|
|
|
354
374
|
// Cleanup on unmount
|
|
@@ -431,6 +451,10 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
431
451
|
agentRef.current?.abortMessage();
|
|
432
452
|
}, []);
|
|
433
453
|
|
|
454
|
+
const clearMessages = useCallback(() => {
|
|
455
|
+
agentRef.current?.clearMessages();
|
|
456
|
+
}, []);
|
|
457
|
+
|
|
434
458
|
// Permission management methods
|
|
435
459
|
const setPermissionMode = useCallback((mode: PermissionMode) => {
|
|
436
460
|
setPermissionModeState((prev) => {
|
|
@@ -535,6 +559,20 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
535
559
|
return { messages: [], sessionIds: [] };
|
|
536
560
|
}, []);
|
|
537
561
|
|
|
562
|
+
const getGatewayConfig = useCallback(() => {
|
|
563
|
+
if (!agentRef.current) {
|
|
564
|
+
return { baseURL: "" };
|
|
565
|
+
}
|
|
566
|
+
return agentRef.current.getGatewayConfig();
|
|
567
|
+
}, []);
|
|
568
|
+
|
|
569
|
+
const getModelConfig = useCallback(() => {
|
|
570
|
+
if (!agentRef.current) {
|
|
571
|
+
return { model: "", fastModel: "" };
|
|
572
|
+
}
|
|
573
|
+
return agentRef.current.getModelConfig();
|
|
574
|
+
}, []);
|
|
575
|
+
|
|
538
576
|
// Listen for Ctrl+O hotkey to toggle collapse/expand state and ESC to cancel confirmation
|
|
539
577
|
useInput((input, key) => {
|
|
540
578
|
if (key.ctrl && input === "o") {
|
|
@@ -584,13 +622,14 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
584
622
|
sessionId,
|
|
585
623
|
sendMessage,
|
|
586
624
|
abortMessage,
|
|
625
|
+
clearMessages,
|
|
587
626
|
latestTotalTokens,
|
|
588
627
|
isCompressing,
|
|
589
628
|
mcpServers,
|
|
590
629
|
connectMcpServer,
|
|
591
630
|
disconnectMcpServer,
|
|
592
631
|
backgroundTasks,
|
|
593
|
-
|
|
632
|
+
tasks,
|
|
594
633
|
getBackgroundTaskOutput,
|
|
595
634
|
stopBackgroundTask,
|
|
596
635
|
slashCommands,
|
|
@@ -611,6 +650,11 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
611
650
|
getFullMessageThread,
|
|
612
651
|
wasLastDetailsTooTall,
|
|
613
652
|
setWasLastDetailsTooTall,
|
|
653
|
+
getGatewayConfig,
|
|
654
|
+
getModelConfig,
|
|
655
|
+
workingDirectory,
|
|
656
|
+
version,
|
|
657
|
+
workdir,
|
|
614
658
|
};
|
|
615
659
|
|
|
616
660
|
return (
|
|
@@ -38,6 +38,7 @@ export const useInputManager = (
|
|
|
38
38
|
const [showMcpManager, setShowMcpManager] = useState(false);
|
|
39
39
|
const [showRewindManager, setShowRewindManager] = useState(false);
|
|
40
40
|
const [showHelp, setShowHelp] = useState(false);
|
|
41
|
+
const [showStatusCommand, setShowStatusCommand] = useState(false);
|
|
41
42
|
const [permissionMode, setPermissionModeState] =
|
|
42
43
|
useState<PermissionMode>("default");
|
|
43
44
|
const [attachedImages, setAttachedImages] = useState<AttachedImage[]>([]);
|
|
@@ -71,6 +72,9 @@ export const useInputManager = (
|
|
|
71
72
|
onHelpStateChange: (show) => {
|
|
72
73
|
setShowHelp(show);
|
|
73
74
|
},
|
|
75
|
+
onStatusCommandStateChange: (show) => {
|
|
76
|
+
setShowStatusCommand(show);
|
|
77
|
+
},
|
|
74
78
|
onPermissionModeChange: (mode) => {
|
|
75
79
|
setPermissionModeState(mode);
|
|
76
80
|
callbacks.onPermissionModeChange?.(mode);
|
|
@@ -108,6 +112,9 @@ export const useInputManager = (
|
|
|
108
112
|
onHelpStateChange: (show) => {
|
|
109
113
|
setShowHelp(show);
|
|
110
114
|
},
|
|
115
|
+
onStatusCommandStateChange: (show) => {
|
|
116
|
+
setShowStatusCommand(show);
|
|
117
|
+
},
|
|
111
118
|
onPermissionModeChange: (mode) => {
|
|
112
119
|
setPermissionModeState(mode);
|
|
113
120
|
callbacks.onPermissionModeChange?.(mode);
|
|
@@ -268,6 +275,7 @@ export const useInputManager = (
|
|
|
268
275
|
showMcpManager,
|
|
269
276
|
showRewindManager,
|
|
270
277
|
showHelp,
|
|
278
|
+
showStatusCommand,
|
|
271
279
|
permissionMode,
|
|
272
280
|
attachedImages,
|
|
273
281
|
isManagerReady,
|
|
@@ -316,6 +324,10 @@ export const useInputManager = (
|
|
|
316
324
|
managerRef.current?.setShowHelp(show);
|
|
317
325
|
setShowHelp(show);
|
|
318
326
|
}, []),
|
|
327
|
+
setShowStatusCommand: useCallback((show: boolean) => {
|
|
328
|
+
managerRef.current?.setShowStatusCommand(show);
|
|
329
|
+
setShowStatusCommand(show);
|
|
330
|
+
}, []),
|
|
319
331
|
setPermissionMode: useCallback((mode: PermissionMode) => {
|
|
320
332
|
setPermissionModeState(mode);
|
|
321
333
|
managerRef.current?.setPermissionMode(mode);
|
|
@@ -17,6 +17,7 @@ export function usePluginManager(): PluginManagerContextType {
|
|
|
17
17
|
selectedId: null,
|
|
18
18
|
isLoading: true,
|
|
19
19
|
error: null,
|
|
20
|
+
successMessage: null,
|
|
20
21
|
searchQuery: "",
|
|
21
22
|
});
|
|
22
23
|
|
|
@@ -34,11 +35,37 @@ export function usePluginManager(): PluginManagerContextType {
|
|
|
34
35
|
|
|
35
36
|
const pluginCore = useMemo(() => new PluginCore(), []);
|
|
36
37
|
|
|
38
|
+
const clearPluginFeedback = useCallback(() => {
|
|
39
|
+
setState((prev: PluginManagerState) => ({
|
|
40
|
+
...prev,
|
|
41
|
+
error: null,
|
|
42
|
+
successMessage: null,
|
|
43
|
+
}));
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
const setSuccessMessage = useCallback(
|
|
47
|
+
(message: string) => {
|
|
48
|
+
setState((prev: PluginManagerState) => ({
|
|
49
|
+
...prev,
|
|
50
|
+
successMessage: message,
|
|
51
|
+
error: null,
|
|
52
|
+
}));
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
setState((prev: PluginManagerState) => ({
|
|
55
|
+
...prev,
|
|
56
|
+
successMessage:
|
|
57
|
+
prev.successMessage === message ? null : prev.successMessage,
|
|
58
|
+
}));
|
|
59
|
+
}, 5000);
|
|
60
|
+
},
|
|
61
|
+
[setState],
|
|
62
|
+
);
|
|
63
|
+
|
|
37
64
|
const refresh = useCallback(async () => {
|
|
65
|
+
clearPluginFeedback();
|
|
38
66
|
setState((prev: PluginManagerState) => ({
|
|
39
67
|
...prev,
|
|
40
68
|
isLoading: true,
|
|
41
|
-
error: null,
|
|
42
69
|
}));
|
|
43
70
|
try {
|
|
44
71
|
const [mks, installed, enabledMap] = await Promise.all([
|
|
@@ -115,14 +142,15 @@ export function usePluginManager(): PluginManagerContextType {
|
|
|
115
142
|
|
|
116
143
|
const addMarketplace = useCallback(
|
|
117
144
|
async (source: string) => {
|
|
145
|
+
clearPluginFeedback();
|
|
118
146
|
setState((prev: PluginManagerState) => ({
|
|
119
147
|
...prev,
|
|
120
148
|
isLoading: true,
|
|
121
|
-
error: null,
|
|
122
149
|
}));
|
|
123
150
|
try {
|
|
124
151
|
await pluginCore.addMarketplace(source);
|
|
125
152
|
await refresh();
|
|
153
|
+
setSuccessMessage(`Marketplace added successfully`);
|
|
126
154
|
} catch (error) {
|
|
127
155
|
setState((prev: PluginManagerState) => ({
|
|
128
156
|
...prev,
|
|
@@ -131,19 +159,20 @@ export function usePluginManager(): PluginManagerContextType {
|
|
|
131
159
|
}));
|
|
132
160
|
}
|
|
133
161
|
},
|
|
134
|
-
[pluginCore, refresh],
|
|
162
|
+
[pluginCore, refresh, clearPluginFeedback, setSuccessMessage],
|
|
135
163
|
);
|
|
136
164
|
|
|
137
165
|
const removeMarketplace = useCallback(
|
|
138
166
|
async (name: string) => {
|
|
167
|
+
clearPluginFeedback();
|
|
139
168
|
setState((prev: PluginManagerState) => ({
|
|
140
169
|
...prev,
|
|
141
170
|
isLoading: true,
|
|
142
|
-
error: null,
|
|
143
171
|
}));
|
|
144
172
|
try {
|
|
145
173
|
await pluginCore.removeMarketplace(name);
|
|
146
174
|
await refresh();
|
|
175
|
+
setSuccessMessage(`Marketplace '${name}' removed successfully`);
|
|
147
176
|
} catch (error) {
|
|
148
177
|
setState((prev: PluginManagerState) => ({
|
|
149
178
|
...prev,
|
|
@@ -152,19 +181,20 @@ export function usePluginManager(): PluginManagerContextType {
|
|
|
152
181
|
}));
|
|
153
182
|
}
|
|
154
183
|
},
|
|
155
|
-
[pluginCore, refresh],
|
|
184
|
+
[pluginCore, refresh, clearPluginFeedback, setSuccessMessage],
|
|
156
185
|
);
|
|
157
186
|
|
|
158
187
|
const updateMarketplace = useCallback(
|
|
159
188
|
async (name: string) => {
|
|
189
|
+
clearPluginFeedback();
|
|
160
190
|
setState((prev: PluginManagerState) => ({
|
|
161
191
|
...prev,
|
|
162
192
|
isLoading: true,
|
|
163
|
-
error: null,
|
|
164
193
|
}));
|
|
165
194
|
try {
|
|
166
195
|
await pluginCore.updateMarketplace(name);
|
|
167
196
|
await refresh();
|
|
197
|
+
setSuccessMessage(`Marketplace '${name}' updated successfully`);
|
|
168
198
|
} catch (error) {
|
|
169
199
|
setState((prev: PluginManagerState) => ({
|
|
170
200
|
...prev,
|
|
@@ -173,7 +203,7 @@ export function usePluginManager(): PluginManagerContextType {
|
|
|
173
203
|
}));
|
|
174
204
|
}
|
|
175
205
|
},
|
|
176
|
-
[pluginCore, refresh],
|
|
206
|
+
[pluginCore, refresh, clearPluginFeedback, setSuccessMessage],
|
|
177
207
|
);
|
|
178
208
|
|
|
179
209
|
const installPlugin = useCallback(
|
|
@@ -182,15 +212,16 @@ export function usePluginManager(): PluginManagerContextType {
|
|
|
182
212
|
marketplace: string,
|
|
183
213
|
scope: "user" | "project" | "local" = "project",
|
|
184
214
|
) => {
|
|
215
|
+
clearPluginFeedback();
|
|
185
216
|
setState((prev: PluginManagerState) => ({
|
|
186
217
|
...prev,
|
|
187
218
|
isLoading: true,
|
|
188
|
-
error: null,
|
|
189
219
|
}));
|
|
190
220
|
try {
|
|
191
221
|
const pluginId = `${name}@${marketplace}`;
|
|
192
222
|
await pluginCore.installPlugin(pluginId, scope);
|
|
193
223
|
await refresh();
|
|
224
|
+
setSuccessMessage(`Plugin '${name}' installed successfully`);
|
|
194
225
|
} catch (error) {
|
|
195
226
|
setState((prev: PluginManagerState) => ({
|
|
196
227
|
...prev,
|
|
@@ -199,20 +230,21 @@ export function usePluginManager(): PluginManagerContextType {
|
|
|
199
230
|
}));
|
|
200
231
|
}
|
|
201
232
|
},
|
|
202
|
-
[pluginCore, refresh],
|
|
233
|
+
[pluginCore, refresh, clearPluginFeedback, setSuccessMessage],
|
|
203
234
|
);
|
|
204
235
|
|
|
205
236
|
const uninstallPlugin = useCallback(
|
|
206
237
|
async (name: string, marketplace: string) => {
|
|
238
|
+
clearPluginFeedback();
|
|
207
239
|
setState((prev: PluginManagerState) => ({
|
|
208
240
|
...prev,
|
|
209
241
|
isLoading: true,
|
|
210
|
-
error: null,
|
|
211
242
|
}));
|
|
212
243
|
try {
|
|
213
244
|
const pluginId = `${name}@${marketplace}`;
|
|
214
245
|
await pluginCore.uninstallPlugin(pluginId);
|
|
215
246
|
await refresh();
|
|
247
|
+
setSuccessMessage(`Plugin '${name}' uninstalled successfully`);
|
|
216
248
|
} catch (error) {
|
|
217
249
|
setState((prev: PluginManagerState) => ({
|
|
218
250
|
...prev,
|
|
@@ -221,20 +253,21 @@ export function usePluginManager(): PluginManagerContextType {
|
|
|
221
253
|
}));
|
|
222
254
|
}
|
|
223
255
|
},
|
|
224
|
-
[pluginCore, refresh],
|
|
256
|
+
[pluginCore, refresh, clearPluginFeedback, setSuccessMessage],
|
|
225
257
|
);
|
|
226
258
|
|
|
227
259
|
const updatePlugin = useCallback(
|
|
228
260
|
async (name: string, marketplace: string) => {
|
|
261
|
+
clearPluginFeedback();
|
|
229
262
|
setState((prev: PluginManagerState) => ({
|
|
230
263
|
...prev,
|
|
231
264
|
isLoading: true,
|
|
232
|
-
error: null,
|
|
233
265
|
}));
|
|
234
266
|
try {
|
|
235
267
|
const pluginId = `${name}@${marketplace}`;
|
|
236
268
|
await pluginCore.updatePlugin(pluginId);
|
|
237
269
|
await refresh();
|
|
270
|
+
setSuccessMessage(`Plugin '${name}' updated successfully`);
|
|
238
271
|
} catch (error) {
|
|
239
272
|
setState((prev: PluginManagerState) => ({
|
|
240
273
|
...prev,
|
|
@@ -243,7 +276,7 @@ export function usePluginManager(): PluginManagerContextType {
|
|
|
243
276
|
}));
|
|
244
277
|
}
|
|
245
278
|
},
|
|
246
|
-
[pluginCore, refresh],
|
|
279
|
+
[pluginCore, refresh, clearPluginFeedback, setSuccessMessage],
|
|
247
280
|
);
|
|
248
281
|
|
|
249
282
|
return {
|
|
@@ -261,6 +294,7 @@ export function usePluginManager(): PluginManagerContextType {
|
|
|
261
294
|
uninstallPlugin,
|
|
262
295
|
updatePlugin,
|
|
263
296
|
refresh,
|
|
297
|
+
clearPluginFeedback,
|
|
264
298
|
},
|
|
265
299
|
};
|
|
266
300
|
}
|
package/src/hooks/useTasks.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import yargs from "yargs";
|
|
2
2
|
import { hideBin } from "yargs/helpers";
|
|
3
3
|
import { startCli } from "./cli.js";
|
|
4
|
-
import { Scope } from "wave-agent-sdk";
|
|
4
|
+
import { Scope, generateRandomName } from "wave-agent-sdk";
|
|
5
|
+
import { createWorktree, type WorktreeSession } from "./utils/worktree.js";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { readFileSync } from "fs";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
|
|
10
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const packageJsonPath = path.resolve(__dirname, "../package.json");
|
|
12
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
13
|
+
const version = packageJson.version;
|
|
5
14
|
|
|
6
15
|
// Export main function for external use
|
|
7
16
|
export async function main() {
|
|
8
17
|
try {
|
|
18
|
+
const originalCwd = process.cwd();
|
|
9
19
|
const argv = await yargs(hideBin(process.argv))
|
|
10
20
|
.option("restore", {
|
|
11
21
|
alias: "r",
|
|
@@ -20,6 +30,12 @@ export async function main() {
|
|
|
20
30
|
type: "boolean",
|
|
21
31
|
global: false,
|
|
22
32
|
})
|
|
33
|
+
.option("worktree", {
|
|
34
|
+
alias: "w",
|
|
35
|
+
description: "Start session in a git worktree (optional name)",
|
|
36
|
+
type: "string",
|
|
37
|
+
global: false,
|
|
38
|
+
})
|
|
23
39
|
.option("print", {
|
|
24
40
|
alias: "p",
|
|
25
41
|
description: "Print response without interactive mode",
|
|
@@ -49,6 +65,11 @@ export async function main() {
|
|
|
49
65
|
type: "string",
|
|
50
66
|
global: false,
|
|
51
67
|
})
|
|
68
|
+
.option("model", {
|
|
69
|
+
description: "Specify the AI model to use",
|
|
70
|
+
type: "string",
|
|
71
|
+
global: false,
|
|
72
|
+
})
|
|
52
73
|
.command(
|
|
53
74
|
"plugin",
|
|
54
75
|
"Manage plugins and marketplaces",
|
|
@@ -231,6 +252,30 @@ export async function main() {
|
|
|
231
252
|
|
|
232
253
|
const tools = parseTools(argv.tools as string | undefined);
|
|
233
254
|
|
|
255
|
+
// Resolve plugin directories to absolute paths before any worktree logic
|
|
256
|
+
const pluginDirs = (argv.pluginDir as string[] | undefined)?.map((dir) =>
|
|
257
|
+
path.resolve(originalCwd, dir),
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
let worktreeSession: WorktreeSession | undefined;
|
|
261
|
+
if (
|
|
262
|
+
argv.worktree !== undefined ||
|
|
263
|
+
process.argv.includes("-w") ||
|
|
264
|
+
process.argv.includes("--worktree")
|
|
265
|
+
) {
|
|
266
|
+
let name = argv.worktree as string | undefined;
|
|
267
|
+
if (!name || name === "") {
|
|
268
|
+
name = generateRandomName();
|
|
269
|
+
}
|
|
270
|
+
worktreeSession = createWorktree(name, originalCwd);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const workdir = worktreeSession?.path || originalCwd;
|
|
274
|
+
|
|
275
|
+
if (worktreeSession) {
|
|
276
|
+
process.chdir(workdir);
|
|
277
|
+
}
|
|
278
|
+
|
|
234
279
|
// Handle restore session command
|
|
235
280
|
if (
|
|
236
281
|
argv.restore === "" ||
|
|
@@ -241,7 +286,7 @@ export async function main() {
|
|
|
241
286
|
const { startSessionSelectorCli } = await import(
|
|
242
287
|
"./session-selector-cli.js"
|
|
243
288
|
);
|
|
244
|
-
const selectedSessionId = await startSessionSelectorCli();
|
|
289
|
+
const selectedSessionId = await startSessionSelectorCli({ workdir });
|
|
245
290
|
if (!selectedSessionId) {
|
|
246
291
|
return;
|
|
247
292
|
}
|
|
@@ -249,8 +294,12 @@ export async function main() {
|
|
|
249
294
|
return startCli({
|
|
250
295
|
restoreSessionId: selectedSessionId,
|
|
251
296
|
bypassPermissions: argv.dangerouslySkipPermissions,
|
|
252
|
-
pluginDirs
|
|
297
|
+
pluginDirs,
|
|
253
298
|
tools,
|
|
299
|
+
worktreeSession,
|
|
300
|
+
workdir,
|
|
301
|
+
version,
|
|
302
|
+
model: argv.model as string | undefined,
|
|
254
303
|
});
|
|
255
304
|
}
|
|
256
305
|
|
|
@@ -258,22 +307,32 @@ export async function main() {
|
|
|
258
307
|
if (argv.print !== undefined) {
|
|
259
308
|
const { startPrintCli } = await import("./print-cli.js");
|
|
260
309
|
return startPrintCli({
|
|
261
|
-
restoreSessionId: argv.restore,
|
|
262
|
-
continueLastSession: argv.continue,
|
|
310
|
+
restoreSessionId: argv.restore as string | undefined,
|
|
311
|
+
continueLastSession: argv.continue as boolean | undefined,
|
|
263
312
|
message: argv.print,
|
|
264
|
-
showStats: argv.showStats,
|
|
265
|
-
bypassPermissions: argv.dangerouslySkipPermissions
|
|
266
|
-
|
|
313
|
+
showStats: argv.showStats as boolean | undefined,
|
|
314
|
+
bypassPermissions: argv.dangerouslySkipPermissions as
|
|
315
|
+
| boolean
|
|
316
|
+
| undefined,
|
|
317
|
+
pluginDirs,
|
|
267
318
|
tools,
|
|
319
|
+
worktreeSession,
|
|
320
|
+
workdir,
|
|
321
|
+
version,
|
|
322
|
+
model: argv.model as string | undefined,
|
|
268
323
|
});
|
|
269
324
|
}
|
|
270
325
|
|
|
271
326
|
await startCli({
|
|
272
|
-
restoreSessionId: argv.restore,
|
|
273
|
-
continueLastSession: argv.continue,
|
|
274
|
-
bypassPermissions: argv.dangerouslySkipPermissions,
|
|
275
|
-
pluginDirs
|
|
327
|
+
restoreSessionId: argv.restore as string | undefined,
|
|
328
|
+
continueLastSession: argv.continue as boolean | undefined,
|
|
329
|
+
bypassPermissions: argv.dangerouslySkipPermissions as boolean | undefined,
|
|
330
|
+
pluginDirs,
|
|
276
331
|
tools,
|
|
332
|
+
worktreeSession,
|
|
333
|
+
workdir,
|
|
334
|
+
version,
|
|
335
|
+
model: argv.model as string | undefined,
|
|
277
336
|
});
|
|
278
337
|
} catch (error) {
|
|
279
338
|
console.error("Failed to start WAVE Code:", error);
|