wave-code 0.2.1 → 0.5.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/commands/plugin/disable.d.ts +2 -1
- package/dist/commands/plugin/disable.d.ts.map +1 -1
- package/dist/commands/plugin/disable.js +3 -2
- package/dist/commands/plugin/enable.d.ts +2 -1
- package/dist/commands/plugin/enable.d.ts.map +1 -1
- package/dist/commands/plugin/enable.js +3 -2
- package/dist/commands/plugin/install.d.ts +2 -1
- package/dist/commands/plugin/install.d.ts.map +1 -1
- package/dist/commands/plugin/list.d.ts.map +1 -1
- package/dist/commands/plugin/list.js +15 -3
- package/dist/commands/plugin/marketplace.d.ts +3 -0
- package/dist/commands/plugin/marketplace.d.ts.map +1 -1
- package/dist/commands/plugin/marketplace.js +15 -1
- package/dist/commands/plugin/uninstall.d.ts +4 -0
- package/dist/commands/plugin/uninstall.d.ts.map +1 -0
- package/dist/commands/plugin/uninstall.js +29 -0
- package/dist/commands/plugin/update.d.ts +4 -0
- package/dist/commands/plugin/update.d.ts.map +1 -0
- package/dist/commands/plugin/update.js +15 -0
- package/dist/components/ChatInterface.d.ts.map +1 -1
- package/dist/components/ChatInterface.js +2 -2
- package/dist/components/CommandSelector.d.ts.map +1 -1
- package/dist/components/CommandSelector.js +9 -3
- package/dist/components/Confirmation.d.ts.map +1 -1
- package/dist/components/Confirmation.js +73 -20
- package/dist/components/DiffDisplay.d.ts +0 -1
- package/dist/components/DiffDisplay.d.ts.map +1 -1
- package/dist/components/DiffDisplay.js +38 -59
- package/dist/components/DiscoverView.d.ts +3 -0
- package/dist/components/DiscoverView.d.ts.map +1 -0
- package/dist/components/DiscoverView.js +25 -0
- package/dist/components/FileSelector.js +1 -1
- package/dist/components/HistorySearch.d.ts +8 -0
- package/dist/components/HistorySearch.d.ts.map +1 -0
- package/dist/components/HistorySearch.js +67 -0
- package/dist/components/InputBox.d.ts +1 -1
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +29 -19
- package/dist/components/InstalledView.d.ts +3 -0
- package/dist/components/InstalledView.d.ts.map +1 -0
- package/dist/components/InstalledView.js +30 -0
- package/dist/components/Markdown.d.ts.map +1 -1
- package/dist/components/Markdown.js +24 -10
- package/dist/components/MarketplaceAddForm.d.ts +3 -0
- package/dist/components/MarketplaceAddForm.d.ts.map +1 -0
- package/dist/components/MarketplaceAddForm.js +26 -0
- package/dist/components/MarketplaceDetail.d.ts +3 -0
- package/dist/components/MarketplaceDetail.d.ts.map +1 -0
- package/dist/components/MarketplaceDetail.js +38 -0
- package/dist/components/MarketplaceList.d.ts +9 -0
- package/dist/components/MarketplaceList.d.ts.map +1 -0
- package/dist/components/MarketplaceList.js +16 -0
- package/dist/components/MarketplaceView.d.ts +3 -0
- package/dist/components/MarketplaceView.d.ts.map +1 -0
- package/dist/components/MarketplaceView.js +28 -0
- package/dist/components/PlanDisplay.d.ts.map +1 -1
- package/dist/components/PlanDisplay.js +2 -2
- package/dist/components/PluginDetail.d.ts +3 -0
- package/dist/components/PluginDetail.d.ts.map +1 -0
- package/dist/components/PluginDetail.js +63 -0
- package/dist/components/PluginList.d.ts +14 -0
- package/dist/components/PluginList.d.ts.map +1 -0
- package/dist/components/PluginList.js +12 -0
- package/dist/components/PluginManagerShell.d.ts +5 -0
- package/dist/components/PluginManagerShell.d.ts.map +1 -0
- package/dist/components/PluginManagerShell.js +89 -0
- package/dist/components/PluginManagerTypes.d.ts +33 -0
- package/dist/components/PluginManagerTypes.d.ts.map +1 -0
- package/dist/components/PluginManagerTypes.js +1 -0
- package/dist/components/RewindCommand.d.ts +9 -0
- package/dist/components/RewindCommand.d.ts.map +1 -0
- package/dist/components/RewindCommand.js +42 -0
- package/dist/components/SessionSelector.d.ts +11 -0
- package/dist/components/SessionSelector.d.ts.map +1 -0
- package/dist/components/SessionSelector.js +38 -0
- package/dist/components/SubagentBlock.d.ts.map +1 -1
- package/dist/components/SubagentBlock.js +24 -1
- package/dist/components/TaskManager.d.ts +6 -0
- package/dist/components/TaskManager.d.ts.map +1 -0
- package/dist/components/TaskManager.js +114 -0
- package/dist/components/ToolResultDisplay.d.ts.map +1 -1
- package/dist/components/ToolResultDisplay.js +2 -1
- package/dist/contexts/PluginManagerContext.d.ts +4 -0
- package/dist/contexts/PluginManagerContext.d.ts.map +1 -0
- package/dist/contexts/PluginManagerContext.js +9 -0
- package/dist/contexts/useChat.d.ts +7 -4
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +37 -12
- package/dist/hooks/useInputManager.d.ts +8 -16
- package/dist/hooks/useInputManager.d.ts.map +1 -1
- package/dist/hooks/useInputManager.js +39 -55
- package/dist/hooks/usePluginManager.d.ts +3 -0
- package/dist/hooks/usePluginManager.d.ts.map +1 -0
- package/dist/hooks/usePluginManager.js +227 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +150 -177
- package/dist/managers/InputManager.d.ts +18 -26
- package/dist/managers/InputManager.d.ts.map +1 -1
- package/dist/managers/InputManager.js +93 -119
- package/dist/plugin-manager-cli.d.ts +6 -0
- package/dist/plugin-manager-cli.d.ts.map +1 -0
- package/dist/plugin-manager-cli.js +12 -0
- package/dist/session-selector-cli.d.ts +2 -0
- package/dist/session-selector-cli.d.ts.map +1 -0
- package/dist/session-selector-cli.js +25 -0
- package/package.json +9 -5
- package/src/commands/plugin/disable.ts +7 -3
- package/src/commands/plugin/enable.ts +7 -3
- package/src/commands/plugin/install.ts +2 -1
- package/src/commands/plugin/list.ts +21 -3
- package/src/commands/plugin/marketplace.ts +17 -1
- package/src/commands/plugin/uninstall.ts +39 -0
- package/src/commands/plugin/update.ts +19 -0
- package/src/components/ChatInterface.tsx +2 -1
- package/src/components/CommandSelector.tsx +10 -3
- package/src/components/Confirmation.tsx +115 -25
- package/src/components/DiffDisplay.tsx +60 -106
- package/src/components/DiscoverView.tsx +31 -0
- package/src/components/FileSelector.tsx +1 -1
- package/src/components/HistorySearch.tsx +148 -0
- package/src/components/InputBox.tsx +51 -34
- package/src/components/InstalledView.tsx +61 -0
- package/src/components/Markdown.tsx +44 -28
- package/src/components/MarketplaceAddForm.tsx +39 -0
- package/src/components/MarketplaceDetail.tsx +79 -0
- package/src/components/MarketplaceList.tsx +52 -0
- package/src/components/MarketplaceView.tsx +43 -0
- package/src/components/PlanDisplay.tsx +14 -19
- package/src/components/PluginDetail.tsx +147 -0
- package/src/components/PluginList.tsx +51 -0
- package/src/components/PluginManagerShell.tsx +189 -0
- package/src/components/PluginManagerTypes.ts +47 -0
- package/src/components/RewindCommand.tsx +114 -0
- package/src/components/SessionSelector.tsx +127 -0
- package/src/components/SubagentBlock.tsx +34 -1
- package/src/components/{BashShellManager.tsx → TaskManager.tsx} +79 -75
- package/src/components/ToolResultDisplay.tsx +6 -2
- package/src/contexts/PluginManagerContext.ts +15 -0
- package/src/contexts/useChat.tsx +51 -20
- package/src/hooks/useInputManager.ts +39 -71
- package/src/hooks/usePluginManager.ts +302 -0
- package/src/index.ts +241 -280
- package/src/managers/InputManager.ts +113 -162
- package/src/plugin-manager-cli.tsx +13 -0
- package/src/session-selector-cli.tsx +37 -0
- package/dist/components/BashHistorySelector.d.ts +0 -11
- package/dist/components/BashHistorySelector.d.ts.map +0 -1
- package/dist/components/BashHistorySelector.js +0 -93
- package/dist/components/BashShellManager.d.ts +0 -6
- package/dist/components/BashShellManager.d.ts.map +0 -1
- package/dist/components/BashShellManager.js +0 -116
- package/dist/hooks/usePagination.d.ts +0 -20
- package/dist/hooks/usePagination.d.ts.map +0 -1
- package/dist/hooks/usePagination.js +0 -168
- package/src/components/BashHistorySelector.tsx +0 -181
- package/src/hooks/usePagination.ts +0 -203
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { Box, Text, useInput } from "ink";
|
|
3
|
+
import type { SessionMetadata } from "wave-agent-sdk";
|
|
4
|
+
|
|
5
|
+
export interface SessionSelectorProps {
|
|
6
|
+
sessions: (SessionMetadata & { firstMessage?: string })[];
|
|
7
|
+
onSelect: (sessionId: string) => void;
|
|
8
|
+
onCancel: () => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const SessionSelector: React.FC<SessionSelectorProps> = ({
|
|
12
|
+
sessions,
|
|
13
|
+
onSelect,
|
|
14
|
+
onCancel,
|
|
15
|
+
}) => {
|
|
16
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
17
|
+
|
|
18
|
+
useInput((input, key) => {
|
|
19
|
+
if (key.return) {
|
|
20
|
+
if (sessions.length > 0 && selectedIndex < sessions.length) {
|
|
21
|
+
onSelect(sessions[selectedIndex].id);
|
|
22
|
+
}
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (key.escape) {
|
|
27
|
+
onCancel();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (key.upArrow) {
|
|
32
|
+
setSelectedIndex(Math.max(0, selectedIndex - 1));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (key.downArrow) {
|
|
37
|
+
setSelectedIndex(Math.min(sessions.length - 1, selectedIndex + 1));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (sessions.length === 0) {
|
|
43
|
+
return (
|
|
44
|
+
<Box
|
|
45
|
+
flexDirection="column"
|
|
46
|
+
borderStyle="single"
|
|
47
|
+
borderColor="yellow"
|
|
48
|
+
borderLeft={false}
|
|
49
|
+
borderRight={false}
|
|
50
|
+
paddingX={1}
|
|
51
|
+
width="100%"
|
|
52
|
+
>
|
|
53
|
+
<Text color="yellow">No sessions found.</Text>
|
|
54
|
+
<Text dimColor>Press Escape to cancel</Text>
|
|
55
|
+
</Box>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const maxDisplay = 10;
|
|
60
|
+
const startIndex = Math.max(
|
|
61
|
+
0,
|
|
62
|
+
Math.min(
|
|
63
|
+
selectedIndex - Math.floor(maxDisplay / 2),
|
|
64
|
+
sessions.length - maxDisplay,
|
|
65
|
+
),
|
|
66
|
+
);
|
|
67
|
+
const displaySessions = sessions.slice(startIndex, startIndex + maxDisplay);
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<Box
|
|
71
|
+
flexDirection="column"
|
|
72
|
+
paddingX={1}
|
|
73
|
+
gap={1}
|
|
74
|
+
borderStyle="single"
|
|
75
|
+
borderColor="cyan"
|
|
76
|
+
borderLeft={false}
|
|
77
|
+
borderRight={false}
|
|
78
|
+
width="100%"
|
|
79
|
+
>
|
|
80
|
+
<Box>
|
|
81
|
+
<Text color="cyan" bold>
|
|
82
|
+
Select a session to resume
|
|
83
|
+
</Text>
|
|
84
|
+
</Box>
|
|
85
|
+
|
|
86
|
+
<Box flexDirection="column">
|
|
87
|
+
{displaySessions.map((session, index) => {
|
|
88
|
+
const actualIndex = startIndex + index;
|
|
89
|
+
const isSelected = actualIndex === selectedIndex;
|
|
90
|
+
const lastActiveAt = new Date(session.lastActiveAt).toLocaleString();
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<Box key={session.id} flexDirection="column" width="100%">
|
|
94
|
+
<Box width="100%">
|
|
95
|
+
<Text
|
|
96
|
+
color={isSelected ? "black" : "white"}
|
|
97
|
+
backgroundColor={isSelected ? "cyan" : undefined}
|
|
98
|
+
>
|
|
99
|
+
{isSelected ? "▶ " : " "}
|
|
100
|
+
{session.id} | {lastActiveAt} | {session.latestTotalTokens}{" "}
|
|
101
|
+
tokens
|
|
102
|
+
</Text>
|
|
103
|
+
</Box>
|
|
104
|
+
<Box marginLeft={4} width="100%">
|
|
105
|
+
<Text dimColor italic>
|
|
106
|
+
{session.firstMessage}
|
|
107
|
+
</Text>
|
|
108
|
+
</Box>
|
|
109
|
+
</Box>
|
|
110
|
+
);
|
|
111
|
+
})}
|
|
112
|
+
</Box>
|
|
113
|
+
|
|
114
|
+
{sessions.length > maxDisplay && (
|
|
115
|
+
<Box>
|
|
116
|
+
<Text dimColor>
|
|
117
|
+
... showing {displaySessions.length} of {sessions.length} sessions
|
|
118
|
+
</Text>
|
|
119
|
+
</Box>
|
|
120
|
+
)}
|
|
121
|
+
|
|
122
|
+
<Box>
|
|
123
|
+
<Text dimColor>↑↓ navigate • Enter to select • Esc to cancel</Text>
|
|
124
|
+
</Box>
|
|
125
|
+
</Box>
|
|
126
|
+
);
|
|
127
|
+
};
|
|
@@ -2,6 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
3
|
import type { SubagentBlock as SubagentBlockType } from "wave-agent-sdk";
|
|
4
4
|
import { useChat } from "../contexts/useChat.js";
|
|
5
|
+
import { Markdown } from "./Markdown.js";
|
|
5
6
|
|
|
6
7
|
interface SubagentBlockProps {
|
|
7
8
|
block: SubagentBlockType;
|
|
@@ -10,6 +11,11 @@ interface SubagentBlockProps {
|
|
|
10
11
|
export const SubagentBlock: React.FC<SubagentBlockProps> = ({ block }) => {
|
|
11
12
|
const { subagentMessages } = useChat();
|
|
12
13
|
|
|
14
|
+
// If the subagent is running in the background, don't show the block
|
|
15
|
+
if (block.runInBackground) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
// Get messages for this subagent from context
|
|
14
20
|
const messages = subagentMessages[block.subagentId] || [];
|
|
15
21
|
|
|
@@ -59,6 +65,26 @@ export const SubagentBlock: React.FC<SubagentBlockProps> = ({ block }) => {
|
|
|
59
65
|
|
|
60
66
|
const { tools: lastTwoTools, totalToolCount } = getLastTwoTools();
|
|
61
67
|
|
|
68
|
+
// Get the last text message content if completed
|
|
69
|
+
const getLastTextMessage = () => {
|
|
70
|
+
if (block.status !== "completed") return null;
|
|
71
|
+
|
|
72
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
73
|
+
const message = messages[i];
|
|
74
|
+
if (message.role === "assistant") {
|
|
75
|
+
for (let j = message.blocks.length - 1; j >= 0; j--) {
|
|
76
|
+
const messageBlock = message.blocks[j];
|
|
77
|
+
if (messageBlock.type === "text" && messageBlock.content) {
|
|
78
|
+
return messageBlock.content;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const lastTextMessage = getLastTextMessage();
|
|
87
|
+
|
|
62
88
|
return (
|
|
63
89
|
<Box
|
|
64
90
|
borderRight={false}
|
|
@@ -86,8 +112,15 @@ export const SubagentBlock: React.FC<SubagentBlockProps> = ({ block }) => {
|
|
|
86
112
|
</Box>
|
|
87
113
|
</Box>
|
|
88
114
|
|
|
115
|
+
{/* Last Text Message Section */}
|
|
116
|
+
{lastTextMessage && (
|
|
117
|
+
<Box marginTop={1}>
|
|
118
|
+
<Markdown>{lastTextMessage}</Markdown>
|
|
119
|
+
</Box>
|
|
120
|
+
)}
|
|
121
|
+
|
|
89
122
|
{/* Tool Names Section - Vertical List */}
|
|
90
|
-
{lastTwoTools.length > 0 && (
|
|
123
|
+
{block.status !== "completed" && lastTwoTools.length > 0 && (
|
|
91
124
|
<Box flexDirection="column" marginTop={1} gap={1}>
|
|
92
125
|
{totalToolCount > 2 && (
|
|
93
126
|
<Text color="gray" dimColor>
|
|
@@ -2,55 +2,55 @@ import React, { useState, useEffect } from "react";
|
|
|
2
2
|
import { Box, Text, useInput } from "ink";
|
|
3
3
|
import { useChat } from "../contexts/useChat.js";
|
|
4
4
|
|
|
5
|
-
interface
|
|
5
|
+
interface Task {
|
|
6
6
|
id: string;
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
type: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
status: "running" | "completed" | "failed" | "killed";
|
|
9
10
|
startTime: number;
|
|
10
11
|
exitCode?: number;
|
|
11
12
|
runtime?: number;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
export interface
|
|
15
|
+
export interface TaskManagerProps {
|
|
15
16
|
onCancel: () => void;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
export const
|
|
19
|
-
|
|
20
|
-
}) => {
|
|
21
|
-
const { backgroundShells, getBackgroundShellOutput, killBackgroundShell } =
|
|
19
|
+
export const TaskManager: React.FC<TaskManagerProps> = ({ onCancel }) => {
|
|
20
|
+
const { backgroundTasks, getBackgroundTaskOutput, stopBackgroundTask } =
|
|
22
21
|
useChat();
|
|
23
|
-
const [
|
|
22
|
+
const [tasks, setTasks] = useState<Task[]>([]);
|
|
24
23
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
25
24
|
const [viewMode, setViewMode] = useState<"list" | "detail">("list");
|
|
26
|
-
const [
|
|
25
|
+
const [detailTaskId, setDetailTaskId] = useState<string | null>(null);
|
|
27
26
|
const [detailOutput, setDetailOutput] = useState<{
|
|
28
27
|
stdout: string;
|
|
29
28
|
stderr: string;
|
|
30
29
|
status: string;
|
|
31
30
|
} | null>(null);
|
|
32
31
|
|
|
33
|
-
// Convert
|
|
32
|
+
// Convert backgroundTasks to local Task format
|
|
34
33
|
useEffect(() => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
id:
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
34
|
+
setTasks(
|
|
35
|
+
backgroundTasks.map((task) => ({
|
|
36
|
+
id: task.id,
|
|
37
|
+
type: task.type,
|
|
38
|
+
description: task.description,
|
|
39
|
+
status: task.status,
|
|
40
|
+
startTime: task.startTime,
|
|
41
|
+
exitCode: task.exitCode,
|
|
42
|
+
runtime: task.runtime,
|
|
43
43
|
})),
|
|
44
44
|
);
|
|
45
|
-
}, [
|
|
45
|
+
}, [backgroundTasks]);
|
|
46
46
|
|
|
47
|
-
// Load detail output for selected
|
|
47
|
+
// Load detail output for selected task
|
|
48
48
|
useEffect(() => {
|
|
49
|
-
if (viewMode === "detail" &&
|
|
50
|
-
const output =
|
|
49
|
+
if (viewMode === "detail" && detailTaskId) {
|
|
50
|
+
const output = getBackgroundTaskOutput(detailTaskId);
|
|
51
51
|
setDetailOutput(output);
|
|
52
52
|
}
|
|
53
|
-
}, [viewMode,
|
|
53
|
+
}, [viewMode, detailTaskId, getBackgroundTaskOutput]);
|
|
54
54
|
|
|
55
55
|
const formatDuration = (ms: number): string => {
|
|
56
56
|
if (ms < 1000) return `${ms}ms`;
|
|
@@ -64,17 +64,17 @@ export const BashShellManager: React.FC<BashShellManagerProps> = ({
|
|
|
64
64
|
return new Date(timestamp).toLocaleTimeString();
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
-
const
|
|
68
|
-
|
|
67
|
+
const stopTask = (taskId: string) => {
|
|
68
|
+
stopBackgroundTask(taskId);
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
useInput((input, key) => {
|
|
72
72
|
if (viewMode === "list") {
|
|
73
73
|
// List mode navigation
|
|
74
74
|
if (key.return) {
|
|
75
|
-
if (
|
|
76
|
-
const
|
|
77
|
-
|
|
75
|
+
if (tasks.length > 0 && selectedIndex < tasks.length) {
|
|
76
|
+
const selectedTask = tasks[selectedIndex];
|
|
77
|
+
setDetailTaskId(selectedTask.id);
|
|
78
78
|
setViewMode("detail");
|
|
79
79
|
}
|
|
80
80
|
return;
|
|
@@ -91,14 +91,14 @@ export const BashShellManager: React.FC<BashShellManagerProps> = ({
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
if (key.downArrow) {
|
|
94
|
-
setSelectedIndex(Math.min(
|
|
94
|
+
setSelectedIndex(Math.min(tasks.length - 1, selectedIndex + 1));
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
if (input === "k" &&
|
|
99
|
-
const
|
|
100
|
-
if (
|
|
101
|
-
|
|
98
|
+
if (input === "k" && tasks.length > 0 && selectedIndex < tasks.length) {
|
|
99
|
+
const selectedTask = tasks[selectedIndex];
|
|
100
|
+
if (selectedTask.status === "running") {
|
|
101
|
+
stopTask(selectedTask.id);
|
|
102
102
|
}
|
|
103
103
|
return;
|
|
104
104
|
}
|
|
@@ -106,24 +106,24 @@ export const BashShellManager: React.FC<BashShellManagerProps> = ({
|
|
|
106
106
|
// Detail mode navigation
|
|
107
107
|
if (key.escape) {
|
|
108
108
|
setViewMode("list");
|
|
109
|
-
|
|
109
|
+
setDetailTaskId(null);
|
|
110
110
|
setDetailOutput(null);
|
|
111
111
|
return;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
if (input === "k" &&
|
|
115
|
-
const
|
|
116
|
-
if (
|
|
117
|
-
|
|
114
|
+
if (input === "k" && detailTaskId) {
|
|
115
|
+
const task = tasks.find((t) => t.id === detailTaskId);
|
|
116
|
+
if (task && task.status === "running") {
|
|
117
|
+
stopTask(detailTaskId);
|
|
118
118
|
}
|
|
119
119
|
return;
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
});
|
|
123
123
|
|
|
124
|
-
if (viewMode === "detail" &&
|
|
125
|
-
const
|
|
126
|
-
if (!
|
|
124
|
+
if (viewMode === "detail" && detailTaskId && detailOutput) {
|
|
125
|
+
const task = tasks.find((t) => t.id === detailTaskId);
|
|
126
|
+
if (!task) {
|
|
127
127
|
setViewMode("list");
|
|
128
128
|
return null;
|
|
129
129
|
}
|
|
@@ -141,31 +141,37 @@ export const BashShellManager: React.FC<BashShellManagerProps> = ({
|
|
|
141
141
|
>
|
|
142
142
|
<Box>
|
|
143
143
|
<Text color="cyan" bold>
|
|
144
|
-
Background
|
|
144
|
+
Background Task Details: {task.id}
|
|
145
145
|
</Text>
|
|
146
146
|
</Box>
|
|
147
147
|
|
|
148
148
|
<Box flexDirection="column" gap={1}>
|
|
149
149
|
<Box>
|
|
150
150
|
<Text>
|
|
151
|
-
<Text color="blue">
|
|
151
|
+
<Text color="blue">Type:</Text> {task.type}
|
|
152
152
|
</Text>
|
|
153
153
|
</Box>
|
|
154
|
+
{task.description && (
|
|
155
|
+
<Box>
|
|
156
|
+
<Text>
|
|
157
|
+
<Text color="blue">Description:</Text> {task.description}
|
|
158
|
+
</Text>
|
|
159
|
+
</Box>
|
|
160
|
+
)}
|
|
154
161
|
<Box>
|
|
155
162
|
<Text>
|
|
156
|
-
<Text color="blue">Status:</Text> {
|
|
157
|
-
{
|
|
158
|
-
` (exit code: ${shell.exitCode})`}
|
|
163
|
+
<Text color="blue">Status:</Text> {task.status}
|
|
164
|
+
{task.exitCode !== undefined && ` (exit code: ${task.exitCode})`}
|
|
159
165
|
</Text>
|
|
160
166
|
</Box>
|
|
161
167
|
<Box>
|
|
162
168
|
<Text>
|
|
163
|
-
<Text color="blue">Started:</Text> {formatTime(
|
|
164
|
-
{
|
|
169
|
+
<Text color="blue">Started:</Text> {formatTime(task.startTime)}
|
|
170
|
+
{task.runtime !== undefined && (
|
|
165
171
|
<Text>
|
|
166
172
|
{" "}
|
|
167
173
|
| <Text color="blue">Runtime:</Text>{" "}
|
|
168
|
-
{formatDuration(
|
|
174
|
+
{formatDuration(task.runtime)}
|
|
169
175
|
</Text>
|
|
170
176
|
)}
|
|
171
177
|
</Text>
|
|
@@ -175,7 +181,7 @@ export const BashShellManager: React.FC<BashShellManagerProps> = ({
|
|
|
175
181
|
{detailOutput.stdout && (
|
|
176
182
|
<Box flexDirection="column" marginTop={1}>
|
|
177
183
|
<Text color="green" bold>
|
|
178
|
-
|
|
184
|
+
OUTPUT (last 10 lines):
|
|
179
185
|
</Text>
|
|
180
186
|
<Box borderStyle="single" borderColor="green" padding={1}>
|
|
181
187
|
<Text>
|
|
@@ -188,7 +194,7 @@ export const BashShellManager: React.FC<BashShellManagerProps> = ({
|
|
|
188
194
|
{detailOutput.stderr && (
|
|
189
195
|
<Box flexDirection="column" marginTop={1}>
|
|
190
196
|
<Text color="red" bold>
|
|
191
|
-
|
|
197
|
+
ERRORS:
|
|
192
198
|
</Text>
|
|
193
199
|
<Box borderStyle="single" borderColor="red" padding={1}>
|
|
194
200
|
<Text color="red">
|
|
@@ -200,14 +206,14 @@ export const BashShellManager: React.FC<BashShellManagerProps> = ({
|
|
|
200
206
|
|
|
201
207
|
<Box marginTop={1}>
|
|
202
208
|
<Text dimColor>
|
|
203
|
-
{
|
|
209
|
+
{task.status === "running" ? "k to stop · " : ""}Esc to go back
|
|
204
210
|
</Text>
|
|
205
211
|
</Box>
|
|
206
212
|
</Box>
|
|
207
213
|
);
|
|
208
214
|
}
|
|
209
215
|
|
|
210
|
-
if (!
|
|
216
|
+
if (!backgroundTasks) {
|
|
211
217
|
return (
|
|
212
218
|
<Box
|
|
213
219
|
flexDirection="column"
|
|
@@ -219,15 +225,15 @@ export const BashShellManager: React.FC<BashShellManagerProps> = ({
|
|
|
219
225
|
paddingTop={1}
|
|
220
226
|
>
|
|
221
227
|
<Text color="cyan" bold>
|
|
222
|
-
Background
|
|
228
|
+
Background Tasks
|
|
223
229
|
</Text>
|
|
224
|
-
<Text>Background
|
|
230
|
+
<Text>Background tasks not available</Text>
|
|
225
231
|
<Text dimColor>Press Escape to close</Text>
|
|
226
232
|
</Box>
|
|
227
233
|
);
|
|
228
234
|
}
|
|
229
235
|
|
|
230
|
-
if (
|
|
236
|
+
if (tasks.length === 0) {
|
|
231
237
|
return (
|
|
232
238
|
<Box
|
|
233
239
|
flexDirection="column"
|
|
@@ -239,9 +245,9 @@ export const BashShellManager: React.FC<BashShellManagerProps> = ({
|
|
|
239
245
|
paddingTop={1}
|
|
240
246
|
>
|
|
241
247
|
<Text color="cyan" bold>
|
|
242
|
-
Background
|
|
248
|
+
Background Tasks
|
|
243
249
|
</Text>
|
|
244
|
-
<Text>No background
|
|
250
|
+
<Text>No background tasks found</Text>
|
|
245
251
|
<Text dimColor>Press Escape to close</Text>
|
|
246
252
|
</Box>
|
|
247
253
|
);
|
|
@@ -260,42 +266,40 @@ export const BashShellManager: React.FC<BashShellManagerProps> = ({
|
|
|
260
266
|
>
|
|
261
267
|
<Box>
|
|
262
268
|
<Text color="cyan" bold>
|
|
263
|
-
Background
|
|
269
|
+
Background Tasks
|
|
264
270
|
</Text>
|
|
265
271
|
</Box>
|
|
266
|
-
<Text dimColor>Select a
|
|
272
|
+
<Text dimColor>Select a task to view details</Text>
|
|
267
273
|
|
|
268
|
-
{
|
|
269
|
-
<Box key={
|
|
274
|
+
{tasks.map((task, index) => (
|
|
275
|
+
<Box key={task.id} flexDirection="column">
|
|
270
276
|
<Text
|
|
271
277
|
color={index === selectedIndex ? "black" : "white"}
|
|
272
278
|
backgroundColor={index === selectedIndex ? "cyan" : undefined}
|
|
273
279
|
>
|
|
274
280
|
{index === selectedIndex ? "▶ " : " "}
|
|
275
|
-
{index + 1}.{
|
|
276
|
-
{
|
|
277
|
-
? shell.command.substring(0, 47) + "..."
|
|
278
|
-
: shell.command}
|
|
281
|
+
{index + 1}. [{task.id}] {task.type}
|
|
282
|
+
{task.description ? `: ${task.description}` : ""}
|
|
279
283
|
<Text
|
|
280
284
|
color={
|
|
281
|
-
|
|
285
|
+
task.status === "running"
|
|
282
286
|
? "green"
|
|
283
|
-
:
|
|
287
|
+
: task.status === "completed"
|
|
284
288
|
? "blue"
|
|
285
289
|
: "red"
|
|
286
290
|
}
|
|
287
291
|
>
|
|
288
292
|
{" "}
|
|
289
|
-
({
|
|
293
|
+
({task.status})
|
|
290
294
|
</Text>
|
|
291
295
|
</Text>
|
|
292
296
|
{index === selectedIndex && (
|
|
293
297
|
<Box marginLeft={4} flexDirection="column">
|
|
294
298
|
<Text color="gray" dimColor>
|
|
295
|
-
|
|
296
|
-
{
|
|
297
|
-
` | Runtime: ${formatDuration(
|
|
298
|
-
{
|
|
299
|
+
Started: {formatTime(task.startTime)}
|
|
300
|
+
{task.runtime !== undefined &&
|
|
301
|
+
` | Runtime: ${formatDuration(task.runtime)}`}
|
|
302
|
+
{task.exitCode !== undefined && ` | Exit: ${task.exitCode}`}
|
|
299
303
|
</Text>
|
|
300
304
|
</Box>
|
|
301
305
|
)}
|
|
@@ -305,7 +309,7 @@ export const BashShellManager: React.FC<BashShellManagerProps> = ({
|
|
|
305
309
|
<Box marginTop={1}>
|
|
306
310
|
<Text dimColor>
|
|
307
311
|
↑/↓ to select · Enter to view ·{" "}
|
|
308
|
-
{
|
|
312
|
+
{tasks[selectedIndex]?.status === "running" ? "k to stop · " : ""}Esc
|
|
309
313
|
to close
|
|
310
314
|
</Text>
|
|
311
315
|
</Box>
|
|
@@ -44,6 +44,9 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
|
|
|
44
44
|
|
|
45
45
|
const toolName = name ? String(name) : "Tool";
|
|
46
46
|
|
|
47
|
+
const isBackgroundable =
|
|
48
|
+
stage === "running" && (toolName === "Bash" || toolName === "Task");
|
|
49
|
+
|
|
47
50
|
// Get shortResult, if not available show last 5 lines of result
|
|
48
51
|
const getShortResult = () => {
|
|
49
52
|
if (block.shortResult) {
|
|
@@ -76,6 +79,7 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
|
|
|
76
79
|
<Text color={getStatusColor()}> {getStatusText()}</Text>
|
|
77
80
|
{/* Display image indicator */}
|
|
78
81
|
{hasImages() && <Text color="blue"> {getImageIndicator()}</Text>}
|
|
82
|
+
{isBackgroundable && <Text color="gray"> [Ctrl-B] Background</Text>}
|
|
79
83
|
</Box>
|
|
80
84
|
|
|
81
85
|
{/* Display shortResult in collapsed state */}
|
|
@@ -135,8 +139,8 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
|
|
|
135
139
|
</Box>
|
|
136
140
|
)}
|
|
137
141
|
|
|
138
|
-
{/* Diff display - only show after tool execution completes */}
|
|
139
|
-
{stage === "end" && (
|
|
142
|
+
{/* Diff display - only show after tool execution completes and was successful */}
|
|
143
|
+
{stage === "end" && success && (
|
|
140
144
|
<DiffDisplay toolName={name} parameters={parameters} />
|
|
141
145
|
)}
|
|
142
146
|
</Box>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
import { PluginManagerContextType } from "../components/PluginManagerTypes.js";
|
|
3
|
+
|
|
4
|
+
export const PluginManagerContext =
|
|
5
|
+
createContext<PluginManagerContextType | null>(null);
|
|
6
|
+
|
|
7
|
+
export const usePluginManagerContext = () => {
|
|
8
|
+
const context = useContext(PluginManagerContext);
|
|
9
|
+
if (!context) {
|
|
10
|
+
throw new Error(
|
|
11
|
+
"usePluginManagerContext must be used within a PluginManagerProvider",
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
return context;
|
|
15
|
+
};
|