wave-code 0.6.4 → 0.7.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 (61) hide show
  1. package/dist/cli.d.ts +1 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +2 -2
  4. package/dist/commands/plugin/disable.d.ts.map +1 -1
  5. package/dist/commands/plugin/disable.js +3 -10
  6. package/dist/commands/plugin/enable.d.ts.map +1 -1
  7. package/dist/commands/plugin/enable.js +3 -10
  8. package/dist/commands/plugin/install.d.ts.map +1 -1
  9. package/dist/commands/plugin/install.js +4 -11
  10. package/dist/commands/plugin/list.d.ts.map +1 -1
  11. package/dist/commands/plugin/list.js +5 -39
  12. package/dist/commands/plugin/marketplace.js +9 -9
  13. package/dist/commands/plugin/uninstall.d.ts.map +1 -1
  14. package/dist/commands/plugin/uninstall.js +4 -17
  15. package/dist/commands/plugin/update.js +3 -3
  16. package/dist/components/App.d.ts +1 -0
  17. package/dist/components/App.d.ts.map +1 -1
  18. package/dist/components/App.js +4 -4
  19. package/dist/components/BackgroundTaskManager.d.ts.map +1 -1
  20. package/dist/components/BackgroundTaskManager.js +14 -6
  21. package/dist/components/ConfirmationDetails.d.ts.map +1 -1
  22. package/dist/components/ConfirmationDetails.js +1 -5
  23. package/dist/components/DiffDisplay.d.ts.map +1 -1
  24. package/dist/components/DiffDisplay.js +2 -7
  25. package/dist/components/MessageItem.d.ts.map +1 -1
  26. package/dist/components/MessageItem.js +1 -1
  27. package/dist/components/MessageList.d.ts.map +1 -1
  28. package/dist/components/MessageList.js +2 -18
  29. package/dist/contexts/useChat.d.ts +1 -0
  30. package/dist/contexts/useChat.d.ts.map +1 -1
  31. package/dist/contexts/useChat.js +3 -1
  32. package/dist/hooks/usePluginManager.d.ts.map +1 -1
  33. package/dist/hooks/usePluginManager.js +20 -39
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +16 -0
  36. package/dist/print-cli.d.ts +1 -0
  37. package/dist/print-cli.d.ts.map +1 -1
  38. package/dist/print-cli.js +2 -1
  39. package/dist/utils/toolParameterTransforms.d.ts +1 -5
  40. package/dist/utils/toolParameterTransforms.d.ts.map +1 -1
  41. package/dist/utils/toolParameterTransforms.js +0 -11
  42. package/package.json +2 -2
  43. package/src/cli.tsx +3 -0
  44. package/src/commands/plugin/disable.ts +3 -17
  45. package/src/commands/plugin/enable.ts +3 -17
  46. package/src/commands/plugin/install.ts +4 -18
  47. package/src/commands/plugin/list.ts +5 -55
  48. package/src/commands/plugin/marketplace.ts +9 -9
  49. package/src/commands/plugin/uninstall.ts +4 -26
  50. package/src/commands/plugin/update.ts +3 -3
  51. package/src/components/App.tsx +10 -2
  52. package/src/components/BackgroundTaskManager.tsx +49 -32
  53. package/src/components/ConfirmationDetails.tsx +0 -6
  54. package/src/components/DiffDisplay.tsx +2 -16
  55. package/src/components/MessageItem.tsx +2 -6
  56. package/src/components/MessageList.tsx +2 -30
  57. package/src/contexts/useChat.tsx +4 -0
  58. package/src/hooks/usePluginManager.ts +21 -57
  59. package/src/index.ts +17 -0
  60. package/src/print-cli.ts +3 -0
  61. package/src/utils/toolParameterTransforms.ts +0 -18
@@ -9,14 +9,20 @@ interface AppProps {
9
9
  continueLastSession?: boolean;
10
10
  bypassPermissions?: boolean;
11
11
  pluginDirs?: string[];
12
+ tools?: string[];
12
13
  }
13
14
 
14
15
  const AppWithProviders: React.FC<{
15
16
  bypassPermissions?: boolean;
16
17
  pluginDirs?: string[];
17
- }> = ({ bypassPermissions, pluginDirs }) => {
18
+ tools?: string[];
19
+ }> = ({ bypassPermissions, pluginDirs, tools }) => {
18
20
  return (
19
- <ChatProvider bypassPermissions={bypassPermissions} pluginDirs={pluginDirs}>
21
+ <ChatProvider
22
+ bypassPermissions={bypassPermissions}
23
+ pluginDirs={pluginDirs}
24
+ tools={tools}
25
+ >
20
26
  <ChatInterfaceWithRemount />
21
27
  </ChatProvider>
22
28
  );
@@ -74,6 +80,7 @@ export const App: React.FC<AppProps> = ({
74
80
  continueLastSession,
75
81
  bypassPermissions,
76
82
  pluginDirs,
83
+ tools,
77
84
  }) => {
78
85
  return (
79
86
  <AppProvider
@@ -83,6 +90,7 @@ export const App: React.FC<AppProps> = ({
83
90
  <AppWithProviders
84
91
  bypassPermissions={bypassPermissions}
85
92
  pluginDirs={pluginDirs}
93
+ tools={tools}
86
94
  />
87
95
  </AppProvider>
88
96
  );
@@ -23,6 +23,7 @@ export const BackgroundTaskManager: React.FC<BackgroundTaskManagerProps> = ({
23
23
  useChat();
24
24
  const [tasks, setTasks] = useState<Task[]>([]);
25
25
  const [selectedIndex, setSelectedIndex] = useState(0);
26
+ const MAX_VISIBLE_ITEMS = 3;
26
27
  const [viewMode, setViewMode] = useState<"list" | "detail">("list");
27
28
  const [detailTaskId, setDetailTaskId] = useState<string | null>(null);
28
29
  const [detailOutput, setDetailOutput] = useState<{
@@ -70,6 +71,16 @@ export const BackgroundTaskManager: React.FC<BackgroundTaskManagerProps> = ({
70
71
  stopBackgroundTask(taskId);
71
72
  };
72
73
 
74
+ // Calculate visible window
75
+ const startIndex = Math.max(
76
+ 0,
77
+ Math.min(
78
+ selectedIndex - Math.floor(MAX_VISIBLE_ITEMS / 2),
79
+ Math.max(0, tasks.length - MAX_VISIBLE_ITEMS),
80
+ ),
81
+ );
82
+ const visibleTasks = tasks.slice(startIndex, startIndex + MAX_VISIBLE_ITEMS);
83
+
73
84
  useInput((input, key) => {
74
85
  if (viewMode === "list") {
75
86
  // List mode navigation
@@ -273,40 +284,46 @@ export const BackgroundTaskManager: React.FC<BackgroundTaskManagerProps> = ({
273
284
  </Box>
274
285
  <Text dimColor>Select a task to view details</Text>
275
286
 
276
- {tasks.map((task, index) => (
277
- <Box key={task.id} flexDirection="column">
278
- <Text
279
- color={index === selectedIndex ? "black" : "white"}
280
- backgroundColor={index === selectedIndex ? "cyan" : undefined}
281
- >
282
- {index === selectedIndex ? "▶ " : " "}
283
- {index + 1}. [{task.id}] {task.type}
284
- {task.description ? `: ${task.description}` : ""}
285
- <Text
286
- color={
287
- task.status === "running"
288
- ? "green"
289
- : task.status === "completed"
290
- ? "blue"
291
- : "red"
292
- }
293
- >
294
- {" "}
295
- ({task.status})
296
- </Text>
297
- </Text>
298
- {index === selectedIndex && (
299
- <Box marginLeft={4} flexDirection="column">
300
- <Text color="gray" dimColor>
301
- Started: {formatTime(task.startTime)}
302
- {task.runtime !== undefined &&
303
- ` | Runtime: ${formatDuration(task.runtime)}`}
304
- {task.exitCode !== undefined && ` | Exit: ${task.exitCode}`}
287
+ <Box flexDirection="column">
288
+ {visibleTasks.map((task, index) => {
289
+ const actualIndex = startIndex + index;
290
+ const isSelected = actualIndex === selectedIndex;
291
+ return (
292
+ <Box key={task.id} flexDirection="column">
293
+ <Text
294
+ color={isSelected ? "black" : "white"}
295
+ backgroundColor={isSelected ? "cyan" : undefined}
296
+ >
297
+ {isSelected ? "▶ " : " "}
298
+ {actualIndex + 1}. [{task.id}] {task.type}
299
+ {task.description ? `: ${task.description}` : ""}
300
+ <Text
301
+ color={
302
+ task.status === "running"
303
+ ? "green"
304
+ : task.status === "completed"
305
+ ? "blue"
306
+ : "red"
307
+ }
308
+ >
309
+ {" "}
310
+ ({task.status})
311
+ </Text>
305
312
  </Text>
313
+ {isSelected && (
314
+ <Box marginLeft={4} flexDirection="column">
315
+ <Text color="gray" dimColor>
316
+ Started: {formatTime(task.startTime)}
317
+ {task.runtime !== undefined &&
318
+ ` | Runtime: ${formatDuration(task.runtime)}`}
319
+ {task.exitCode !== undefined && ` | Exit: ${task.exitCode}`}
320
+ </Text>
321
+ </Box>
322
+ )}
306
323
  </Box>
307
- )}
308
- </Box>
309
- ))}
324
+ );
325
+ })}
326
+ </Box>
310
327
 
311
328
  <Box marginTop={1}>
312
329
  <Text dimColor>
@@ -3,8 +3,6 @@ import { Box, Text, useStdout, measureElement, Static } from "ink";
3
3
  import {
4
4
  BASH_TOOL_NAME,
5
5
  EDIT_TOOL_NAME,
6
- MULTI_EDIT_TOOL_NAME,
7
- DELETE_FILE_TOOL_NAME,
8
6
  WRITE_TOOL_NAME,
9
7
  EXIT_PLAN_MODE_TOOL_NAME,
10
8
  ASK_USER_QUESTION_TOOL_NAME,
@@ -26,10 +24,6 @@ const getActionDescription = (
26
24
  return `Execute command: ${toolInput.command || "unknown command"}`;
27
25
  case EDIT_TOOL_NAME:
28
26
  return `Edit file: ${toolInput.file_path || "unknown file"}`;
29
- case MULTI_EDIT_TOOL_NAME:
30
- return `Edit multiple sections in: ${toolInput.file_path || "unknown file"}`;
31
- case DELETE_FILE_TOOL_NAME:
32
- return `Delete file: ${toolInput.target_file || "unknown file"}`;
33
27
  case WRITE_TOOL_NAME:
34
28
  return `Write to file: ${toolInput.file_path || "unknown file"}`;
35
29
  case EXIT_PLAN_MODE_TOOL_NAME:
@@ -1,10 +1,6 @@
1
1
  import React, { useMemo } from "react";
2
2
  import { Box, Text } from "ink";
3
- import {
4
- WRITE_TOOL_NAME,
5
- EDIT_TOOL_NAME,
6
- MULTI_EDIT_TOOL_NAME,
7
- } from "wave-agent-sdk";
3
+ import { WRITE_TOOL_NAME, EDIT_TOOL_NAME } from "wave-agent-sdk";
8
4
  import { transformToolBlockToChanges } from "../utils/toolParameterTransforms.js";
9
5
  import { diffLines, diffWords } from "diff";
10
6
 
@@ -18,8 +14,7 @@ export const DiffDisplay: React.FC<DiffDisplayProps> = ({
18
14
  parameters,
19
15
  }) => {
20
16
  const showDiff =
21
- toolName &&
22
- [WRITE_TOOL_NAME, EDIT_TOOL_NAME, MULTI_EDIT_TOOL_NAME].includes(toolName);
17
+ toolName && [WRITE_TOOL_NAME, EDIT_TOOL_NAME].includes(toolName);
23
18
 
24
19
  // Diff detection and transformation using typed parameters
25
20
  const changes = useMemo(() => {
@@ -109,15 +104,6 @@ export const DiffDisplay: React.FC<DiffDisplayProps> = ({
109
104
 
110
105
  changes.forEach((change, changeIndex) => {
111
106
  try {
112
- // Add ellipsis between non-contiguous edits in MultiEdit
113
- if (toolName === MULTI_EDIT_TOOL_NAME && changeIndex > 0) {
114
- allElements.push(
115
- <Box key={`multi-edit-separator-${changeIndex}`}>
116
- <Text color="gray">...</Text>
117
- </Box>,
118
- );
119
- }
120
-
121
107
  // Get line-level diff to understand the structure
122
108
  const lineDiffs = diffLines(
123
109
  change.oldContent || "",
@@ -25,14 +25,10 @@ export const MessageItem = ({ message, isExpanded }: MessageItemProps) => {
25
25
  {block.type === "text" && block.content.trim() && (
26
26
  <Box>
27
27
  {block.customCommandContent && (
28
- <Text color="cyan" bold>
29
- $
30
- </Text>
28
+ <Text color="cyan" bold>$ </Text>
31
29
  )}
32
30
  {block.source === MessageSource.HOOK && (
33
- <Text color="magenta" bold>
34
- ~
35
- </Text>
31
+ <Text color="magenta" bold>~ </Text>
36
32
  )}
37
33
  {message.role === "user" ? (
38
34
  <Text backgroundColor="gray" color="white">
@@ -1,12 +1,6 @@
1
1
  import React from "react";
2
2
  import { Box, Text, Static } from "ink";
3
3
  import type { Message } from "wave-agent-sdk";
4
- import {
5
- TASK_CREATE_TOOL_NAME,
6
- TASK_GET_TOOL_NAME,
7
- TASK_UPDATE_TOOL_NAME,
8
- TASK_LIST_TOOL_NAME,
9
- } from "wave-agent-sdk";
10
4
  import { MessageItem } from "./MessageItem.js";
11
5
 
12
6
  export interface MessageListProps {
@@ -40,31 +34,9 @@ export const MessageList = React.memo(
40
34
  const maxExpandedMessages = 20;
41
35
  const shouldLimitMessages =
42
36
  isExpanded && messages.length > maxExpandedMessages;
43
-
44
- // Filter out task management tools and empty messages
45
- const taskMgmtTools = [
46
- TASK_CREATE_TOOL_NAME,
47
- TASK_GET_TOOL_NAME,
48
- TASK_UPDATE_TOOL_NAME,
49
- TASK_LIST_TOOL_NAME,
50
- ];
51
- const filteredMessages = messages
52
- .map((message) => ({
53
- ...message,
54
- blocks: message.blocks.filter(
55
- (block) =>
56
- !(
57
- block.type === "tool" &&
58
- typeof block.name === "string" &&
59
- taskMgmtTools.includes(block.name)
60
- ),
61
- ),
62
- }))
63
- .filter((message) => message.blocks.length > 0);
64
-
65
37
  const displayMessages = shouldLimitMessages
66
- ? filteredMessages.slice(-maxExpandedMessages)
67
- : filteredMessages;
38
+ ? messages.slice(-maxExpandedMessages)
39
+ : messages;
68
40
 
69
41
  // Compute which messages to render statically vs dynamically
70
42
  const lastMessage = displayMessages[displayMessages.length - 1];
@@ -108,12 +108,14 @@ export interface ChatProviderProps {
108
108
  children: React.ReactNode;
109
109
  bypassPermissions?: boolean;
110
110
  pluginDirs?: string[];
111
+ tools?: string[];
111
112
  }
112
113
 
113
114
  export const ChatProvider: React.FC<ChatProviderProps> = ({
114
115
  children,
115
116
  bypassPermissions,
116
117
  pluginDirs,
118
+ tools,
117
119
  }) => {
118
120
  const { restoreSessionId, continueLastSession } = useAppConfig();
119
121
 
@@ -304,6 +306,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
304
306
  canUseTool: permissionCallback,
305
307
  stream: false, // 关闭流式模式
306
308
  plugins: pluginDirs?.map((path) => ({ type: "local", path })),
309
+ tools,
307
310
  });
308
311
 
309
312
  agentRef.current = agent;
@@ -336,6 +339,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
336
339
  bypassPermissions,
337
340
  showConfirmation,
338
341
  pluginDirs,
342
+ tools,
339
343
  ]);
340
344
 
341
345
  // Cleanup on unmount
@@ -1,9 +1,6 @@
1
1
  import { useState, useCallback, useEffect, useMemo } from "react";
2
2
  import {
3
- MarketplaceService,
4
- PluginScopeManager,
5
- ConfigurationService,
6
- PluginManager,
3
+ PluginCore,
7
4
  KnownMarketplace,
8
5
  InstalledPlugin,
9
6
  MarketplacePluginEntry,
@@ -35,25 +32,7 @@ export function usePluginManager(): PluginManagerContextType {
35
32
  })[]
36
33
  >([]);
37
34
 
38
- const marketplaceService = useMemo(() => new MarketplaceService(), []);
39
- const configurationService = useMemo(() => new ConfigurationService(), []);
40
- const pluginManager = useMemo(
41
- () =>
42
- new PluginManager({
43
- workdir: process.cwd(),
44
- configurationService,
45
- }),
46
- [configurationService],
47
- );
48
- const pluginScopeManager = useMemo(
49
- () =>
50
- new PluginScopeManager({
51
- workdir: process.cwd(),
52
- configurationService,
53
- pluginManager,
54
- }),
55
- [configurationService, pluginManager],
56
- );
35
+ const pluginCore = useMemo(() => new PluginCore(), []);
57
36
 
58
37
  const refresh = useCallback(async () => {
59
38
  setState((prev: PluginManagerState) => ({
@@ -63,9 +42,9 @@ export function usePluginManager(): PluginManagerContextType {
63
42
  }));
64
43
  try {
65
44
  const [mks, installed, enabledMap] = await Promise.all([
66
- marketplaceService.listMarketplaces(),
67
- marketplaceService.getInstalledPlugins(),
68
- Promise.resolve(pluginScopeManager.getMergedEnabledPlugins()),
45
+ pluginCore.listMarketplaces(),
46
+ pluginCore.getInstalledPlugins(),
47
+ Promise.resolve(pluginCore.getMergedEnabledPlugins()),
69
48
  ]);
70
49
 
71
50
  setMarketplaces(mks);
@@ -74,7 +53,7 @@ export function usePluginManager(): PluginManagerContextType {
74
53
  return {
75
54
  ...p,
76
55
  enabled: !!enabledMap[pluginId],
77
- scope: pluginScopeManager.findPluginScope(pluginId) || undefined,
56
+ scope: pluginCore.findPluginScope(pluginId) || undefined,
78
57
  };
79
58
  });
80
59
 
@@ -88,8 +67,8 @@ export function usePluginManager(): PluginManagerContextType {
88
67
  })[] = [];
89
68
  for (const mk of mks) {
90
69
  try {
91
- const manifest = await marketplaceService.loadMarketplaceManifest(
92
- marketplaceService.getMarketplacePath(mk),
70
+ const manifest = await pluginCore.loadMarketplaceManifest(
71
+ pluginCore.getMarketplacePath(mk),
93
72
  );
94
73
  manifest.plugins.forEach((p) => {
95
74
  const pluginId = `${p.name}@${mk.name}`;
@@ -120,7 +99,7 @@ export function usePluginManager(): PluginManagerContextType {
120
99
  error: error instanceof Error ? error.message : String(error),
121
100
  }));
122
101
  }
123
- }, [marketplaceService, pluginScopeManager]);
102
+ }, [pluginCore]);
124
103
 
125
104
  useEffect(() => {
126
105
  refresh();
@@ -142,7 +121,7 @@ export function usePluginManager(): PluginManagerContextType {
142
121
  error: null,
143
122
  }));
144
123
  try {
145
- await marketplaceService.addMarketplace(source);
124
+ await pluginCore.addMarketplace(source);
146
125
  await refresh();
147
126
  } catch (error) {
148
127
  setState((prev: PluginManagerState) => ({
@@ -152,7 +131,7 @@ export function usePluginManager(): PluginManagerContextType {
152
131
  }));
153
132
  }
154
133
  },
155
- [marketplaceService, refresh],
134
+ [pluginCore, refresh],
156
135
  );
157
136
 
158
137
  const removeMarketplace = useCallback(
@@ -163,7 +142,7 @@ export function usePluginManager(): PluginManagerContextType {
163
142
  error: null,
164
143
  }));
165
144
  try {
166
- await marketplaceService.removeMarketplace(name);
145
+ await pluginCore.removeMarketplace(name);
167
146
  await refresh();
168
147
  } catch (error) {
169
148
  setState((prev: PluginManagerState) => ({
@@ -173,7 +152,7 @@ export function usePluginManager(): PluginManagerContextType {
173
152
  }));
174
153
  }
175
154
  },
176
- [marketplaceService, refresh],
155
+ [pluginCore, refresh],
177
156
  );
178
157
 
179
158
  const updateMarketplace = useCallback(
@@ -184,7 +163,7 @@ export function usePluginManager(): PluginManagerContextType {
184
163
  error: null,
185
164
  }));
186
165
  try {
187
- await marketplaceService.updateMarketplace(name);
166
+ await pluginCore.updateMarketplace(name);
188
167
  await refresh();
189
168
  } catch (error) {
190
169
  setState((prev: PluginManagerState) => ({
@@ -194,7 +173,7 @@ export function usePluginManager(): PluginManagerContextType {
194
173
  }));
195
174
  }
196
175
  },
197
- [marketplaceService, refresh],
176
+ [pluginCore, refresh],
198
177
  );
199
178
 
200
179
  const installPlugin = useCallback(
@@ -210,9 +189,7 @@ export function usePluginManager(): PluginManagerContextType {
210
189
  }));
211
190
  try {
212
191
  const pluginId = `${name}@${marketplace}`;
213
- const workdir = process.cwd();
214
- await marketplaceService.installPlugin(pluginId, workdir);
215
- await pluginScopeManager.enablePlugin(scope, pluginId);
192
+ await pluginCore.installPlugin(pluginId, scope);
216
193
  await refresh();
217
194
  } catch (error) {
218
195
  setState((prev: PluginManagerState) => ({
@@ -222,7 +199,7 @@ export function usePluginManager(): PluginManagerContextType {
222
199
  }));
223
200
  }
224
201
  },
225
- [marketplaceService, pluginScopeManager, refresh],
202
+ [pluginCore, refresh],
226
203
  );
227
204
 
228
205
  const uninstallPlugin = useCallback(
@@ -234,20 +211,7 @@ export function usePluginManager(): PluginManagerContextType {
234
211
  }));
235
212
  try {
236
213
  const pluginId = `${name}@${marketplace}`;
237
- const workdir = process.cwd();
238
-
239
- // 1. Remove from global registry and potentially clean up cache
240
- await marketplaceService.uninstallPlugin(pluginId, workdir);
241
-
242
- // 2. Find the scope where it's currently enabled and remove it from there
243
- const scope = pluginScopeManager.findPluginScope(pluginId);
244
- if (scope) {
245
- await configurationService.removeEnabledPlugin(
246
- workdir,
247
- scope,
248
- pluginId,
249
- );
250
- }
214
+ await pluginCore.uninstallPlugin(pluginId);
251
215
  await refresh();
252
216
  } catch (error) {
253
217
  setState((prev: PluginManagerState) => ({
@@ -257,7 +221,7 @@ export function usePluginManager(): PluginManagerContextType {
257
221
  }));
258
222
  }
259
223
  },
260
- [configurationService, marketplaceService, pluginScopeManager, refresh],
224
+ [pluginCore, refresh],
261
225
  );
262
226
 
263
227
  const updatePlugin = useCallback(
@@ -269,7 +233,7 @@ export function usePluginManager(): PluginManagerContextType {
269
233
  }));
270
234
  try {
271
235
  const pluginId = `${name}@${marketplace}`;
272
- await marketplaceService.updatePlugin(pluginId);
236
+ await pluginCore.updatePlugin(pluginId);
273
237
  await refresh();
274
238
  } catch (error) {
275
239
  setState((prev: PluginManagerState) => ({
@@ -279,7 +243,7 @@ export function usePluginManager(): PluginManagerContextType {
279
243
  }));
280
244
  }
281
245
  },
282
- [marketplaceService, refresh],
246
+ [pluginCore, refresh],
283
247
  );
284
248
 
285
249
  return {
package/src/index.ts CHANGED
@@ -43,6 +43,12 @@ export async function main() {
43
43
  string: true,
44
44
  global: false,
45
45
  })
46
+ .option("tools", {
47
+ description:
48
+ 'Specify a comma-separated list of tools to enable (e.g., \'Bash,Read,Write\'). Use "" to disable all, "default" for all.',
49
+ type: "string",
50
+ global: false,
51
+ })
46
52
  .command(
47
53
  "plugin",
48
54
  "Manage plugins and marketplaces",
@@ -217,6 +223,14 @@ export async function main() {
217
223
  .strict()
218
224
  .parseAsync();
219
225
 
226
+ const parseTools = (tools: string | undefined): string[] | undefined => {
227
+ if (tools === undefined || tools === "default") return undefined;
228
+ if (tools === "") return [];
229
+ return tools.split(",").map((t) => t.trim());
230
+ };
231
+
232
+ const tools = parseTools(argv.tools as string | undefined);
233
+
220
234
  // Handle restore session command
221
235
  if (
222
236
  argv.restore === "" ||
@@ -236,6 +250,7 @@ export async function main() {
236
250
  restoreSessionId: selectedSessionId,
237
251
  bypassPermissions: argv.dangerouslySkipPermissions,
238
252
  pluginDirs: argv.pluginDir as string[],
253
+ tools,
239
254
  });
240
255
  }
241
256
 
@@ -249,6 +264,7 @@ export async function main() {
249
264
  showStats: argv.showStats,
250
265
  bypassPermissions: argv.dangerouslySkipPermissions,
251
266
  pluginDirs: argv.pluginDir as string[],
267
+ tools,
252
268
  });
253
269
  }
254
270
 
@@ -257,6 +273,7 @@ export async function main() {
257
273
  continueLastSession: argv.continue,
258
274
  bypassPermissions: argv.dangerouslySkipPermissions,
259
275
  pluginDirs: argv.pluginDir as string[],
276
+ tools,
260
277
  });
261
278
  } catch (error) {
262
279
  console.error("Failed to start WAVE Code:", error);
package/src/print-cli.ts CHANGED
@@ -8,6 +8,7 @@ export interface PrintCliOptions {
8
8
  showStats?: boolean;
9
9
  bypassPermissions?: boolean;
10
10
  pluginDirs?: string[];
11
+ tools?: string[];
11
12
  }
12
13
 
13
14
  function displayTimingInfo(startTime: Date, showStats: boolean): void {
@@ -33,6 +34,7 @@ export async function startPrintCli(options: PrintCliOptions): Promise<void> {
33
34
  showStats = false,
34
35
  bypassPermissions,
35
36
  pluginDirs,
37
+ tools,
36
38
  } = options;
37
39
 
38
40
  if (
@@ -136,6 +138,7 @@ export async function startPrintCli(options: PrintCliOptions): Promise<void> {
136
138
  continueLastSession,
137
139
  permissionMode: bypassPermissions ? "bypassPermissions" : undefined,
138
140
  plugins: pluginDirs?.map((path) => ({ type: "local", path })),
141
+ tools,
139
142
  // 保持流式模式以获得更好的命令行用户体验
140
143
  });
141
144
 
@@ -7,7 +7,6 @@ import {
7
7
  type Change,
8
8
  type WriteToolParameters,
9
9
  type EditToolParameters,
10
- type MultiEditToolParameters,
11
10
  } from "wave-agent-sdk";
12
11
  import { logger } from "./logger.js";
13
12
 
@@ -55,18 +54,6 @@ export function transformEditParameters(
55
54
  ];
56
55
  }
57
56
 
58
- /**
59
- * Transform MultiEdit tool parameters to changes
60
- */
61
- export function transformMultiEditParameters(
62
- parameters: MultiEditToolParameters,
63
- ): Change[] {
64
- return parameters.edits.map((edit) => ({
65
- oldContent: edit.old_string,
66
- newContent: edit.new_string,
67
- }));
68
- }
69
-
70
57
  /**
71
58
  * Transform tool block parameters into standardized Change[] array for diff display
72
59
  * Forces type judgment based on tool name using type assertions
@@ -89,11 +76,6 @@ export function transformToolBlockToChanges(
89
76
  case "Edit":
90
77
  return transformEditParameters(parsedParams as EditToolParameters);
91
78
 
92
- case "MultiEdit":
93
- return transformMultiEditParameters(
94
- parsedParams as MultiEditToolParameters,
95
- );
96
-
97
79
  default:
98
80
  return [];
99
81
  }