wave-code 0.14.0 → 0.14.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 (53) hide show
  1. package/dist/components/BackgroundTaskManager.d.ts.map +1 -1
  2. package/dist/components/BackgroundTaskManager.js +36 -25
  3. package/dist/components/InputBox.d.ts.map +1 -1
  4. package/dist/components/InputBox.js +2 -2
  5. package/dist/components/MarketplaceAddForm.d.ts.map +1 -1
  6. package/dist/components/MarketplaceAddForm.js +48 -17
  7. package/dist/components/MarketplaceDetail.d.ts.map +1 -1
  8. package/dist/components/MarketplaceDetail.js +2 -1
  9. package/dist/components/MarketplaceList.d.ts.map +1 -1
  10. package/dist/components/MarketplaceList.js +2 -1
  11. package/dist/components/McpManager.d.ts.map +1 -1
  12. package/dist/components/McpManager.js +22 -27
  13. package/dist/components/PluginDetail.d.ts.map +1 -1
  14. package/dist/components/PluginDetail.js +22 -22
  15. package/dist/components/PluginManagerShell.d.ts +1 -0
  16. package/dist/components/PluginManagerShell.d.ts.map +1 -1
  17. package/dist/components/PluginManagerShell.js +2 -2
  18. package/dist/components/PluginManagerTypes.d.ts +2 -2
  19. package/dist/components/PluginManagerTypes.d.ts.map +1 -1
  20. package/dist/contexts/useChat.d.ts +1 -0
  21. package/dist/contexts/useChat.d.ts.map +1 -1
  22. package/dist/contexts/useChat.js +125 -98
  23. package/dist/hooks/usePluginManager.d.ts +3 -1
  24. package/dist/hooks/usePluginManager.d.ts.map +1 -1
  25. package/dist/hooks/usePluginManager.js +16 -7
  26. package/dist/reducers/backgroundTaskManagerReducer.d.ts +43 -0
  27. package/dist/reducers/backgroundTaskManagerReducer.d.ts.map +1 -0
  28. package/dist/reducers/backgroundTaskManagerReducer.js +23 -0
  29. package/dist/reducers/marketplaceAddFormReducer.d.ts +24 -0
  30. package/dist/reducers/marketplaceAddFormReducer.d.ts.map +1 -0
  31. package/dist/reducers/marketplaceAddFormReducer.js +18 -0
  32. package/dist/reducers/mcpManagerReducer.d.ts +16 -0
  33. package/dist/reducers/mcpManagerReducer.d.ts.map +1 -0
  34. package/dist/reducers/mcpManagerReducer.js +15 -0
  35. package/dist/reducers/pluginDetailReducer.d.ts +25 -0
  36. package/dist/reducers/pluginDetailReducer.d.ts.map +1 -0
  37. package/dist/reducers/pluginDetailReducer.js +38 -0
  38. package/package.json +2 -2
  39. package/src/components/BackgroundTaskManager.tsx +32 -34
  40. package/src/components/InputBox.tsx +7 -1
  41. package/src/components/MarketplaceAddForm.tsx +76 -22
  42. package/src/components/MarketplaceDetail.tsx +4 -0
  43. package/src/components/MarketplaceList.tsx +4 -0
  44. package/src/components/McpManager.tsx +30 -34
  45. package/src/components/PluginDetail.tsx +25 -33
  46. package/src/components/PluginManagerShell.tsx +3 -2
  47. package/src/components/PluginManagerTypes.ts +8 -2
  48. package/src/contexts/useChat.tsx +54 -20
  49. package/src/hooks/usePluginManager.ts +18 -7
  50. package/src/reducers/backgroundTaskManagerReducer.ts +60 -0
  51. package/src/reducers/marketplaceAddFormReducer.ts +35 -0
  52. package/src/reducers/mcpManagerReducer.ts +31 -0
  53. package/src/reducers/pluginDetailReducer.ts +58 -0
@@ -117,6 +117,8 @@ export interface ChatContextType {
117
117
  workingDirectory: string;
118
118
  version?: string;
119
119
  workdir?: string;
120
+ // Agent recreation (e.g. after plugin install)
121
+ recreateAgent: () => void;
120
122
  }
121
123
 
122
124
  const ChatContext = createContext<ChatContextType | null>(null);
@@ -332,8 +334,11 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
332
334
  );
333
335
 
334
336
  // Initialize AI manager
335
- useEffect(() => {
336
- const initializeAgent = async () => {
337
+ const initializeAgent = useCallback(
338
+ async (restoreSessionIdOverride?: string) => {
339
+ const effectiveRestoreSessionId =
340
+ restoreSessionIdOverride ?? restoreSessionId;
341
+
337
342
  const callbacks: AgentCallbacks = {
338
343
  onMessagesChange: () => {
339
344
  throttledSetMessages();
@@ -400,7 +405,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
400
405
 
401
406
  const agent = await Agent.create({
402
407
  callbacks,
403
- restoreSessionId,
408
+ restoreSessionId: effectiveRestoreSessionId,
404
409
  continueLastSession,
405
410
  logger,
406
411
  permissionMode:
@@ -442,25 +447,53 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
442
447
  } catch (error) {
443
448
  console.error("Failed to initialize AI manager:", error);
444
449
  }
445
- };
450
+ },
451
+ [
452
+ restoreSessionId,
453
+ continueLastSession,
454
+ bypassPermissions,
455
+ showConfirmation,
456
+ pluginDirs,
457
+ tools,
458
+ allowedTools,
459
+ disallowedTools,
460
+ workdir,
461
+ worktreeSession,
462
+ model,
463
+ initialPermissionMode,
464
+ throttledSetMessages,
465
+ throttledSetTokens,
466
+ ],
467
+ );
446
468
 
469
+ // Recreate agent (e.g. after plugin install) — destroys current agent and reinitializes
470
+ const recreateAgent = useCallback(() => {
471
+ const currentSessionId = agentRef.current?.sessionId;
472
+ if (agentRef.current) {
473
+ try {
474
+ agentRef.current.destroy();
475
+ } catch {
476
+ // Ignore destroy errors
477
+ }
478
+ }
479
+ agentRef.current = null;
480
+ setMessages([]);
481
+ setMcpServers([]);
482
+ setSlashCommands([]);
483
+ setSessionId("");
484
+ setIsLoading(false);
485
+ setlatestTotalTokens(0);
486
+ setIsCommandRunning(false);
487
+ setIsCompressing(false);
488
+ if (currentSessionId) {
489
+ initializeAgent(currentSessionId);
490
+ }
491
+ }, [initializeAgent]);
492
+
493
+ // Run initial agent creation
494
+ useEffect(() => {
447
495
  initializeAgent();
448
- }, [
449
- restoreSessionId,
450
- continueLastSession,
451
- bypassPermissions,
452
- showConfirmation,
453
- pluginDirs,
454
- tools,
455
- allowedTools,
456
- disallowedTools,
457
- workdir,
458
- worktreeSession,
459
- model,
460
- initialPermissionMode,
461
- throttledSetMessages,
462
- throttledSetTokens,
463
- ]);
496
+ }, [initializeAgent]);
464
497
 
465
498
  // Cleanup on unmount
466
499
  useEffect(() => {
@@ -751,6 +784,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
751
784
  workingDirectory,
752
785
  version,
753
786
  workdir,
787
+ recreateAgent,
754
788
  };
755
789
 
756
790
  return (
@@ -11,7 +11,9 @@ import {
11
11
  PluginManagerContextType,
12
12
  } from "../components/PluginManagerTypes.js";
13
13
 
14
- export function usePluginManager(): PluginManagerContextType {
14
+ export function usePluginManager(options?: {
15
+ onPluginInstalled?: () => void;
16
+ }): PluginManagerContextType {
15
17
  const [state, setState] = useState<PluginManagerState>({
16
18
  currentView: "DISCOVER",
17
19
  selectedId: null,
@@ -141,16 +143,20 @@ export function usePluginManager(): PluginManagerContextType {
141
143
  }, []);
142
144
 
143
145
  const addMarketplace = useCallback(
144
- async (source: string) => {
146
+ async (source: string, scope: "user" | "project" | "local" = "user") => {
145
147
  clearPluginFeedback();
146
148
  setState((prev: PluginManagerState) => ({
147
149
  ...prev,
148
150
  isLoading: true,
149
151
  }));
150
152
  try {
151
- await pluginCore.addMarketplace(source);
153
+ await pluginCore.addMarketplace(source, scope);
152
154
  await refresh();
153
- setSuccessMessage(`Marketplace added successfully`);
155
+ setSuccessMessage(`Marketplace added successfully (${scope} scope)`);
156
+ setState((prev: PluginManagerState) => ({
157
+ ...prev,
158
+ currentView: "MARKETPLACES",
159
+ }));
154
160
  } catch (error) {
155
161
  setState((prev: PluginManagerState) => ({
156
162
  ...prev,
@@ -163,16 +169,20 @@ export function usePluginManager(): PluginManagerContextType {
163
169
  );
164
170
 
165
171
  const removeMarketplace = useCallback(
166
- async (name: string) => {
172
+ async (name: string, scope?: "user" | "project" | "local") => {
167
173
  clearPluginFeedback();
168
174
  setState((prev: PluginManagerState) => ({
169
175
  ...prev,
170
176
  isLoading: true,
171
177
  }));
172
178
  try {
173
- await pluginCore.removeMarketplace(name);
179
+ await pluginCore.removeMarketplace(name, scope);
174
180
  await refresh();
175
181
  setSuccessMessage(`Marketplace '${name}' removed successfully`);
182
+ setState((prev: PluginManagerState) => ({
183
+ ...prev,
184
+ currentView: "MARKETPLACES",
185
+ }));
176
186
  } catch (error) {
177
187
  setState((prev: PluginManagerState) => ({
178
188
  ...prev,
@@ -222,6 +232,7 @@ export function usePluginManager(): PluginManagerContextType {
222
232
  await pluginCore.installPlugin(pluginId, scope);
223
233
  await refresh();
224
234
  setSuccessMessage(`Plugin '${name}' installed successfully`);
235
+ options?.onPluginInstalled?.();
225
236
  } catch (error) {
226
237
  setState((prev: PluginManagerState) => ({
227
238
  ...prev,
@@ -230,7 +241,7 @@ export function usePluginManager(): PluginManagerContextType {
230
241
  }));
231
242
  }
232
243
  },
233
- [pluginCore, refresh, clearPluginFeedback, setSuccessMessage],
244
+ [pluginCore, refresh, clearPluginFeedback, setSuccessMessage, options],
234
245
  );
235
246
 
236
247
  const uninstallPlugin = useCallback(
@@ -0,0 +1,60 @@
1
+ export interface Task {
2
+ id: string;
3
+ type: string;
4
+ description?: string;
5
+ status: "running" | "completed" | "failed" | "killed";
6
+ startTime: number;
7
+ exitCode?: number;
8
+ runtime?: number;
9
+ outputPath?: string;
10
+ }
11
+
12
+ export interface DetailOutput {
13
+ stdout: string;
14
+ stderr: string;
15
+ status: string;
16
+ outputPath?: string;
17
+ }
18
+
19
+ export interface BackgroundTaskManagerState {
20
+ tasks: Task[];
21
+ selectedIndex: number;
22
+ viewMode: "list" | "detail";
23
+ detailTaskId: string | null;
24
+ detailOutput: DetailOutput | null;
25
+ }
26
+
27
+ export type BackgroundTaskManagerAction =
28
+ | { type: "SET_TASKS"; tasks: Task[] }
29
+ | { type: "SELECT_INDEX"; index: number }
30
+ | { type: "SET_VIEW_MODE"; mode: "list" | "detail" }
31
+ | { type: "SET_DETAIL_TASK_ID"; id: string | null }
32
+ | { type: "SET_DETAIL_OUTPUT"; output: DetailOutput | null }
33
+ | { type: "RESET_DETAIL" };
34
+
35
+ export function backgroundTaskManagerReducer(
36
+ state: BackgroundTaskManagerState,
37
+ action: BackgroundTaskManagerAction,
38
+ ): BackgroundTaskManagerState {
39
+ switch (action.type) {
40
+ case "SET_TASKS":
41
+ return { ...state, tasks: action.tasks };
42
+ case "SELECT_INDEX":
43
+ return { ...state, selectedIndex: action.index };
44
+ case "SET_VIEW_MODE":
45
+ return { ...state, viewMode: action.mode };
46
+ case "SET_DETAIL_TASK_ID":
47
+ return { ...state, detailTaskId: action.id };
48
+ case "SET_DETAIL_OUTPUT":
49
+ return { ...state, detailOutput: action.output };
50
+ case "RESET_DETAIL":
51
+ return {
52
+ ...state,
53
+ viewMode: "list",
54
+ detailTaskId: null,
55
+ detailOutput: null,
56
+ };
57
+ default:
58
+ return state;
59
+ }
60
+ }
@@ -0,0 +1,35 @@
1
+ export interface MarketplaceAddFormState {
2
+ source: string;
3
+ scopeIndex: number;
4
+ step: "source" | "scope";
5
+ }
6
+
7
+ export type MarketplaceAddFormAction =
8
+ | { type: "SET_SOURCE"; source: string }
9
+ | { type: "SET_SCOPE_INDEX"; index: number }
10
+ | { type: "SET_STEP"; step: "source" | "scope" }
11
+ | { type: "INSERT_CHAR"; text: string }
12
+ | { type: "DELETE_CHAR" }
13
+ | { type: "BACK_TO_SOURCE" };
14
+
15
+ export function marketplaceAddFormReducer(
16
+ state: MarketplaceAddFormState,
17
+ action: MarketplaceAddFormAction,
18
+ ): MarketplaceAddFormState {
19
+ switch (action.type) {
20
+ case "SET_SOURCE":
21
+ return { ...state, source: action.source };
22
+ case "SET_SCOPE_INDEX":
23
+ return { ...state, scopeIndex: action.index };
24
+ case "SET_STEP":
25
+ return { ...state, step: action.step };
26
+ case "INSERT_CHAR":
27
+ return { ...state, source: state.source + action.text };
28
+ case "DELETE_CHAR":
29
+ return { ...state, source: state.source.slice(0, -1) };
30
+ case "BACK_TO_SOURCE":
31
+ return { ...state, step: "source" };
32
+ default:
33
+ return state;
34
+ }
35
+ }
@@ -0,0 +1,31 @@
1
+ export interface McpManagerState {
2
+ selectedIndex: number;
3
+ viewMode: "list" | "detail";
4
+ }
5
+
6
+ export type McpManagerAction =
7
+ | { type: "MOVE_UP"; serverCount: number }
8
+ | { type: "MOVE_DOWN"; serverCount: number }
9
+ | { type: "SET_VIEW_MODE"; viewMode: "list" | "detail" };
10
+
11
+ export function mcpManagerReducer(
12
+ state: McpManagerState,
13
+ action: McpManagerAction,
14
+ ): McpManagerState {
15
+ switch (action.type) {
16
+ case "MOVE_UP":
17
+ return { ...state, selectedIndex: Math.max(0, state.selectedIndex - 1) };
18
+ case "MOVE_DOWN":
19
+ return {
20
+ ...state,
21
+ selectedIndex: Math.min(
22
+ action.serverCount - 1,
23
+ state.selectedIndex + 1,
24
+ ),
25
+ };
26
+ case "SET_VIEW_MODE":
27
+ return { ...state, viewMode: action.viewMode };
28
+ default:
29
+ return state;
30
+ }
31
+ }
@@ -0,0 +1,58 @@
1
+ export interface PluginDetailState {
2
+ selectedScopeIndex: number;
3
+ selectedActionIndex: number;
4
+ }
5
+
6
+ export type PluginDetailAction =
7
+ | { type: "SELECT_SCOPE_INDEX"; index: number }
8
+ | { type: "SELECT_ACTION_INDEX"; index: number }
9
+ | { type: "MOVE_SCOPE_UP"; maxIndex: number }
10
+ | { type: "MOVE_SCOPE_DOWN"; maxIndex: number }
11
+ | { type: "MOVE_ACTION_UP"; maxIndex: number }
12
+ | { type: "MOVE_ACTION_DOWN"; maxIndex: number };
13
+
14
+ export function pluginDetailReducer(
15
+ state: PluginDetailState,
16
+ action: PluginDetailAction,
17
+ ): PluginDetailState {
18
+ switch (action.type) {
19
+ case "SELECT_SCOPE_INDEX":
20
+ return { ...state, selectedScopeIndex: action.index };
21
+ case "SELECT_ACTION_INDEX":
22
+ return { ...state, selectedActionIndex: action.index };
23
+ case "MOVE_SCOPE_UP":
24
+ return {
25
+ ...state,
26
+ selectedScopeIndex:
27
+ state.selectedScopeIndex > 0
28
+ ? state.selectedScopeIndex - 1
29
+ : action.maxIndex,
30
+ };
31
+ case "MOVE_SCOPE_DOWN":
32
+ return {
33
+ ...state,
34
+ selectedScopeIndex:
35
+ state.selectedScopeIndex < action.maxIndex
36
+ ? state.selectedScopeIndex + 1
37
+ : 0,
38
+ };
39
+ case "MOVE_ACTION_UP":
40
+ return {
41
+ ...state,
42
+ selectedActionIndex:
43
+ state.selectedActionIndex > 0
44
+ ? state.selectedActionIndex - 1
45
+ : action.maxIndex,
46
+ };
47
+ case "MOVE_ACTION_DOWN":
48
+ return {
49
+ ...state,
50
+ selectedActionIndex:
51
+ state.selectedActionIndex < action.maxIndex
52
+ ? state.selectedActionIndex + 1
53
+ : 0,
54
+ };
55
+ default:
56
+ return state;
57
+ }
58
+ }