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.
Files changed (108) hide show
  1. package/dist/cli.d.ts +2 -4
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +24 -52
  4. package/dist/components/App.d.ts +3 -4
  5. package/dist/components/App.d.ts.map +1 -1
  6. package/dist/components/App.js +49 -6
  7. package/dist/components/BackgroundTaskManager.d.ts.map +1 -1
  8. package/dist/components/BackgroundTaskManager.js +12 -20
  9. package/dist/components/BangDisplay.d.ts +9 -0
  10. package/dist/components/BangDisplay.d.ts.map +1 -0
  11. package/dist/components/{CommandOutputDisplay.js → BangDisplay.js} +1 -1
  12. package/dist/components/ChatInterface.d.ts.map +1 -1
  13. package/dist/components/ChatInterface.js +3 -2
  14. package/dist/components/CommandSelector.d.ts.map +1 -1
  15. package/dist/components/CommandSelector.js +18 -2
  16. package/dist/components/ConfirmationSelector.d.ts.map +1 -1
  17. package/dist/components/ConfirmationSelector.js +105 -8
  18. package/dist/components/HelpView.d.ts.map +1 -1
  19. package/dist/components/HelpView.js +2 -0
  20. package/dist/components/HistorySearch.d.ts.map +1 -1
  21. package/dist/components/HistorySearch.js +19 -25
  22. package/dist/components/InputBox.d.ts.map +1 -1
  23. package/dist/components/InputBox.js +9 -3
  24. package/dist/components/MarketplaceAddForm.d.ts.map +1 -1
  25. package/dist/components/MarketplaceAddForm.js +13 -6
  26. package/dist/components/MarketplaceDetail.d.ts.map +1 -1
  27. package/dist/components/MarketplaceDetail.js +8 -3
  28. package/dist/components/MessageBlockItem.js +2 -2
  29. package/dist/components/MessageList.d.ts +4 -1
  30. package/dist/components/MessageList.d.ts.map +1 -1
  31. package/dist/components/MessageList.js +15 -8
  32. package/dist/components/PluginDetail.d.ts.map +1 -1
  33. package/dist/components/PluginDetail.js +14 -3
  34. package/dist/components/PluginManagerShell.d.ts.map +1 -1
  35. package/dist/components/PluginManagerShell.js +3 -3
  36. package/dist/components/PluginManagerTypes.d.ts +2 -0
  37. package/dist/components/PluginManagerTypes.d.ts.map +1 -1
  38. package/dist/components/SessionSelector.d.ts.map +1 -1
  39. package/dist/components/SessionSelector.js +10 -13
  40. package/dist/components/StatusCommand.d.ts +6 -0
  41. package/dist/components/StatusCommand.d.ts.map +1 -0
  42. package/dist/components/StatusCommand.js +28 -0
  43. package/dist/components/WorktreeExitPrompt.d.ts +13 -0
  44. package/dist/components/WorktreeExitPrompt.d.ts.map +1 -0
  45. package/dist/components/WorktreeExitPrompt.js +26 -0
  46. package/dist/contexts/useChat.d.ts +9 -5
  47. package/dist/contexts/useChat.d.ts.map +1 -1
  48. package/dist/contexts/useChat.js +38 -8
  49. package/dist/contracts/status.d.ts +8 -0
  50. package/dist/contracts/status.d.ts.map +1 -0
  51. package/dist/contracts/status.js +1 -0
  52. package/dist/hooks/useInputManager.d.ts +2 -0
  53. package/dist/hooks/useInputManager.d.ts.map +1 -1
  54. package/dist/hooks/useInputManager.js +12 -0
  55. package/dist/hooks/usePluginManager.d.ts.map +1 -1
  56. package/dist/hooks/usePluginManager.js +41 -13
  57. package/dist/hooks/useTasks.js +2 -2
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +53 -4
  60. package/dist/managers/InputManager.d.ts +6 -0
  61. package/dist/managers/InputManager.d.ts.map +1 -1
  62. package/dist/managers/InputManager.js +32 -13
  63. package/dist/print-cli.d.ts +2 -4
  64. package/dist/print-cli.d.ts.map +1 -1
  65. package/dist/print-cli.js +31 -2
  66. package/dist/session-selector-cli.d.ts +3 -1
  67. package/dist/session-selector-cli.d.ts.map +1 -1
  68. package/dist/session-selector-cli.js +2 -2
  69. package/dist/types.d.ts +11 -0
  70. package/dist/types.d.ts.map +1 -0
  71. package/dist/types.js +1 -0
  72. package/dist/utils/worktree.d.ts +23 -0
  73. package/dist/utils/worktree.d.ts.map +1 -0
  74. package/dist/utils/worktree.js +135 -0
  75. package/package.json +2 -2
  76. package/src/cli.tsx +36 -59
  77. package/src/components/App.tsx +99 -11
  78. package/src/components/BackgroundTaskManager.tsx +12 -20
  79. package/src/components/{CommandOutputDisplay.tsx → BangDisplay.tsx} +4 -4
  80. package/src/components/ChatInterface.tsx +8 -0
  81. package/src/components/CommandSelector.tsx +18 -1
  82. package/src/components/ConfirmationSelector.tsx +118 -9
  83. package/src/components/HelpView.tsx +2 -0
  84. package/src/components/HistorySearch.tsx +25 -30
  85. package/src/components/InputBox.tsx +11 -1
  86. package/src/components/MarketplaceAddForm.tsx +21 -8
  87. package/src/components/MarketplaceDetail.tsx +19 -4
  88. package/src/components/MessageBlockItem.tsx +3 -3
  89. package/src/components/MessageList.tsx +47 -23
  90. package/src/components/PluginDetail.tsx +30 -6
  91. package/src/components/PluginManagerShell.tsx +24 -6
  92. package/src/components/PluginManagerTypes.ts +2 -0
  93. package/src/components/SessionSelector.tsx +38 -24
  94. package/src/components/StatusCommand.tsx +94 -0
  95. package/src/components/WorktreeExitPrompt.tsx +86 -0
  96. package/src/contexts/useChat.tsx +57 -13
  97. package/src/contracts/status.ts +7 -0
  98. package/src/hooks/useInputManager.ts +12 -0
  99. package/src/hooks/usePluginManager.ts +47 -13
  100. package/src/hooks/useTasks.ts +2 -2
  101. package/src/index.ts +71 -12
  102. package/src/managers/InputManager.ts +37 -15
  103. package/src/print-cli.ts +48 -5
  104. package/src/session-selector-cli.tsx +6 -2
  105. package/src/types.ts +11 -0
  106. package/src/utils/worktree.ts +164 -0
  107. package/dist/components/CommandOutputDisplay.d.ts +0 -9
  108. package/dist/components/CommandOutputDisplay.d.ts.map +0 -1
@@ -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
- // Session tasks
53
- sessionTasks: Task[];
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
- // Session tasks state
148
- const [sessionTasks, setSessionTasks] = useState<Task[]>([]);
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
- }, 50);
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
- onTasksChange: (tasks) => {
269
+ onBackgroundTasksChange: (tasks) => {
257
270
  setBackgroundTasks([...tasks]);
258
271
  },
259
- onSessionTasksChange: (tasks) => {
260
- setSessionTasks([...tasks]);
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
- sessionTasks,
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 (
@@ -0,0 +1,7 @@
1
+ export interface AgentStatus {
2
+ version: string;
3
+ sessionId: string;
4
+ cwd: string;
5
+ baseURL: string;
6
+ model: string;
7
+ }
@@ -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
  }
@@ -1,6 +1,6 @@
1
1
  import { useChat } from "../contexts/useChat.js";
2
2
 
3
3
  export const useTasks = () => {
4
- const { sessionTasks } = useChat();
5
- return sessionTasks;
4
+ const { tasks } = useChat();
5
+ return tasks;
6
6
  };
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: argv.pluginDir as string[],
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
- pluginDirs: argv.pluginDir as string[],
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: argv.pluginDir as string[],
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);