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.
- package/dist/cli.d.ts +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/commands/plugin/disable.d.ts.map +1 -1
- package/dist/commands/plugin/disable.js +3 -10
- package/dist/commands/plugin/enable.d.ts.map +1 -1
- package/dist/commands/plugin/enable.js +3 -10
- package/dist/commands/plugin/install.d.ts.map +1 -1
- package/dist/commands/plugin/install.js +4 -11
- package/dist/commands/plugin/list.d.ts.map +1 -1
- package/dist/commands/plugin/list.js +5 -39
- package/dist/commands/plugin/marketplace.js +9 -9
- package/dist/commands/plugin/uninstall.d.ts.map +1 -1
- package/dist/commands/plugin/uninstall.js +4 -17
- package/dist/commands/plugin/update.js +3 -3
- package/dist/components/App.d.ts +1 -0
- package/dist/components/App.d.ts.map +1 -1
- package/dist/components/App.js +4 -4
- package/dist/components/BackgroundTaskManager.d.ts.map +1 -1
- package/dist/components/BackgroundTaskManager.js +14 -6
- package/dist/components/ConfirmationDetails.d.ts.map +1 -1
- package/dist/components/ConfirmationDetails.js +1 -5
- package/dist/components/DiffDisplay.d.ts.map +1 -1
- package/dist/components/DiffDisplay.js +2 -7
- package/dist/components/MessageItem.d.ts.map +1 -1
- package/dist/components/MessageItem.js +1 -1
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +2 -18
- package/dist/contexts/useChat.d.ts +1 -0
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +3 -1
- package/dist/hooks/usePluginManager.d.ts.map +1 -1
- package/dist/hooks/usePluginManager.js +20 -39
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -0
- package/dist/print-cli.d.ts +1 -0
- package/dist/print-cli.d.ts.map +1 -1
- package/dist/print-cli.js +2 -1
- package/dist/utils/toolParameterTransforms.d.ts +1 -5
- package/dist/utils/toolParameterTransforms.d.ts.map +1 -1
- package/dist/utils/toolParameterTransforms.js +0 -11
- package/package.json +2 -2
- package/src/cli.tsx +3 -0
- package/src/commands/plugin/disable.ts +3 -17
- package/src/commands/plugin/enable.ts +3 -17
- package/src/commands/plugin/install.ts +4 -18
- package/src/commands/plugin/list.ts +5 -55
- package/src/commands/plugin/marketplace.ts +9 -9
- package/src/commands/plugin/uninstall.ts +4 -26
- package/src/commands/plugin/update.ts +3 -3
- package/src/components/App.tsx +10 -2
- package/src/components/BackgroundTaskManager.tsx +49 -32
- package/src/components/ConfirmationDetails.tsx +0 -6
- package/src/components/DiffDisplay.tsx +2 -16
- package/src/components/MessageItem.tsx +2 -6
- package/src/components/MessageList.tsx +2 -30
- package/src/contexts/useChat.tsx +4 -0
- package/src/hooks/usePluginManager.ts +21 -57
- package/src/index.ts +17 -0
- package/src/print-cli.ts +3 -0
- package/src/utils/toolParameterTransforms.ts +0 -18
package/src/components/App.tsx
CHANGED
|
@@ -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
|
-
|
|
18
|
+
tools?: string[];
|
|
19
|
+
}> = ({ bypassPermissions, pluginDirs, tools }) => {
|
|
18
20
|
return (
|
|
19
|
-
<ChatProvider
|
|
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
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
task.
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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
|
-
|
|
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
|
-
?
|
|
67
|
-
:
|
|
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];
|
package/src/contexts/useChat.tsx
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
Promise.resolve(
|
|
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:
|
|
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
|
|
92
|
-
|
|
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
|
-
}, [
|
|
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
|
|
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
|
-
[
|
|
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
|
|
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
|
-
[
|
|
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
|
|
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
|
-
[
|
|
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
|
-
|
|
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
|
-
[
|
|
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
|
-
|
|
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
|
-
[
|
|
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
|
|
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
|
-
[
|
|
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
|
}
|