wave-code 0.17.1 → 0.17.2
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/acp/agent.js +1 -1
- package/dist/components/ChatInterface.d.ts.map +1 -1
- package/dist/components/ChatInterface.js +5 -2
- package/dist/components/InputBox.d.ts +2 -0
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +29 -8
- package/dist/components/LoadingIndicator.d.ts +2 -1
- package/dist/components/LoadingIndicator.d.ts.map +1 -1
- package/dist/components/LoadingIndicator.js +2 -2
- package/dist/components/QueuedMessageList.d.ts.map +1 -1
- package/dist/components/QueuedMessageList.js +10 -10
- package/dist/components/StatusLine.d.ts +2 -0
- package/dist/components/StatusLine.d.ts.map +1 -1
- package/dist/components/StatusLine.js +6 -6
- package/dist/components/TaskList.d.ts +3 -0
- package/dist/components/TaskList.d.ts.map +1 -1
- package/dist/components/TaskList.js +171 -28
- package/dist/components/TaskNotificationMessage.d.ts.map +1 -1
- package/dist/components/TaskNotificationMessage.js +1 -0
- package/dist/components/WorkflowManager.d.ts +6 -0
- package/dist/components/WorkflowManager.d.ts.map +1 -0
- package/dist/components/WorkflowManager.js +102 -0
- package/dist/constants/commands.d.ts.map +1 -1
- package/dist/constants/commands.js +6 -0
- package/dist/contexts/useChat.d.ts +8 -1
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +68 -4
- package/dist/hooks/useInputManager.d.ts +2 -0
- package/dist/hooks/useInputManager.d.ts.map +1 -1
- package/dist/hooks/useInputManager.js +22 -13
- package/dist/managers/inputHandlers.d.ts.map +1 -1
- package/dist/managers/inputHandlers.js +6 -3
- package/dist/managers/inputReducer.d.ts +10 -0
- package/dist/managers/inputReducer.d.ts.map +1 -1
- package/dist/managers/inputReducer.js +41 -4
- package/dist/print-cli.d.ts.map +1 -1
- package/dist/print-cli.js +3 -31
- package/dist/reducers/workflowManagerReducer.d.ts +41 -0
- package/dist/reducers/workflowManagerReducer.d.ts.map +1 -0
- package/dist/reducers/workflowManagerReducer.js +100 -0
- package/package.json +2 -2
- package/src/acp/agent.ts +1 -1
- package/src/components/ChatInterface.tsx +10 -1
- package/src/components/InputBox.tsx +43 -3
- package/src/components/LoadingIndicator.tsx +4 -1
- package/src/components/QueuedMessageList.tsx +7 -3
- package/src/components/StatusLine.tsx +28 -16
- package/src/components/TaskList.tsx +213 -19
- package/src/components/TaskNotificationMessage.tsx +1 -0
- package/src/components/WorkflowManager.tsx +320 -0
- package/src/constants/commands.ts +6 -0
- package/src/contexts/useChat.tsx +83 -4
- package/src/hooks/useInputManager.ts +25 -13
- package/src/managers/inputHandlers.ts +5 -4
- package/src/managers/inputReducer.ts +54 -6
- package/src/print-cli.ts +3 -37
- package/src/reducers/workflowManagerReducer.ts +143 -0
package/dist/acp/agent.js
CHANGED
|
@@ -40,7 +40,7 @@ export class WaveAcpAgent {
|
|
|
40
40
|
}
|
|
41
41
|
getSessionConfigOptions(agent) {
|
|
42
42
|
const configuredModels = agent.getConfiguredModels();
|
|
43
|
-
const currentModel = agent.getModelConfig().model;
|
|
43
|
+
const currentModel = agent.getModelConfig().model || "";
|
|
44
44
|
return [
|
|
45
45
|
{
|
|
46
46
|
id: "permission_mode",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAa3D,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAa3D,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EA2IjC,CAAC"}
|
|
@@ -10,7 +10,7 @@ import { ConfirmationDetails } from "./ConfirmationDetails.js";
|
|
|
10
10
|
import { ConfirmationSelector } from "./ConfirmationSelector.js";
|
|
11
11
|
import { useChat } from "../contexts/useChat.js";
|
|
12
12
|
export const ChatInterface = () => {
|
|
13
|
-
const { messages, isLoading, isCommandRunning, isCompacting, sendMessage, abortMessage, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, maxInputTokens, slashCommands, hasSlashCommand, isConfirmationVisible, hasPendingConfirmations, confirmingTool, handleConfirmationDecision, handleConfirmationCancel, version, workdir, remountKey, requestRemount, } = useChat();
|
|
13
|
+
const { messages, isLoading, isCommandRunning, isCompacting, sendMessage, abortMessage, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, maxInputTokens, slashCommands, hasSlashCommand, isConfirmationVisible, hasPendingConfirmations, confirmingTool, handleConfirmationDecision, handleConfirmationCancel, version, workdir, remountKey, requestRemount, isGoalActive, goalElapsed, isGoalEvaluating, } = useChat();
|
|
14
14
|
const displayMessages = messages;
|
|
15
15
|
const [forceStatic, setForceStatic] = useState(false);
|
|
16
16
|
const { stdout } = useStdout();
|
|
@@ -37,5 +37,8 @@ export const ChatInterface = () => {
|
|
|
37
37
|
]);
|
|
38
38
|
if (!sessionId)
|
|
39
39
|
return null;
|
|
40
|
-
return (_jsxs(Box, { ref: chatInterfaceRef, flexDirection: "column", children: [_jsx(MessageList, { messages: displayMessages, isExpanded: isExpanded, version: version, workdir: workdir, forceStatic: forceStatic }, remountKey), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [(isLoading ||
|
|
40
|
+
return (_jsxs(Box, { ref: chatInterfaceRef, flexDirection: "column", children: [_jsx(MessageList, { messages: displayMessages, isExpanded: isExpanded, version: version, workdir: workdir, forceStatic: forceStatic }, remountKey), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [(isLoading ||
|
|
41
|
+
isCommandRunning ||
|
|
42
|
+
isCompacting ||
|
|
43
|
+
isGoalEvaluating) && (_jsx(LoadingIndicator, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompacting: isCompacting, isGoalEvaluating: isGoalEvaluating, latestTotalTokens: latestTotalTokens })), _jsx(TaskList, {}), _jsx(QueuedMessageList, {}), _jsx(InputBox, { isLoading: isLoading, isCommandRunning: isCommandRunning, sendMessage: sendMessage, abortMessage: abortMessage, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand, latestTotalTokens: latestTotalTokens, maxInputTokens: maxInputTokens, isGoalActive: isGoalActive, goalElapsed: goalElapsed })] })), isConfirmationVisible && (_jsxs(_Fragment, { children: [forceStatic ? (_jsx(Static, { items: [{ key: "confirmation-details" }], children: () => (_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded }, "confirmation-details")) })) : (_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded })), _jsx(ConfirmationSelector, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: handleConfirmationDecision, onCancel: handleConfirmationCancel })] }))] }));
|
|
41
44
|
};
|
|
@@ -18,6 +18,8 @@ export interface InputBoxProps {
|
|
|
18
18
|
hasSlashCommand?: (commandId: string) => boolean;
|
|
19
19
|
latestTotalTokens?: number;
|
|
20
20
|
maxInputTokens?: number;
|
|
21
|
+
isGoalActive?: boolean;
|
|
22
|
+
goalElapsed?: string;
|
|
21
23
|
}
|
|
22
24
|
export declare const InputBox: React.FC<InputBoxProps>;
|
|
23
25
|
//# sourceMappingURL=InputBox.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAoB9D,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,eAAO,MAAM,sBAAsB,mDACe,CAAC;AAEnD,eAAO,MAAM,6BAA6B,QAGzC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,CACZ,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,EAClD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACjC,IAAI,CAAC;IACV,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAE1B,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,mBAAmB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAE/D,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAEjD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAoU5C,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect } from "react";
|
|
2
|
+
import { useEffect, useRef, useCallback } from "react";
|
|
3
3
|
import { Box, Text } from "ink";
|
|
4
4
|
import { useInput } from "ink";
|
|
5
5
|
import { FileSelector } from "./FileSelector.js";
|
|
@@ -13,14 +13,25 @@ import { StatusCommand } from "./StatusCommand.js";
|
|
|
13
13
|
import { LoginCommand } from "./LoginCommand.js";
|
|
14
14
|
import { PluginManagerShell } from "./PluginManagerShell.js";
|
|
15
15
|
import { ModelSelector } from "./ModelSelector.js";
|
|
16
|
+
import { WorkflowManager } from "./WorkflowManager.js";
|
|
16
17
|
import { StatusLine } from "./StatusLine.js";
|
|
17
18
|
import { BtwDisplay } from "./BtwDisplay.js";
|
|
18
19
|
import { useInputManager } from "../hooks/useInputManager.js";
|
|
19
20
|
import { useChat } from "../contexts/useChat.js";
|
|
20
21
|
export const INPUT_PLACEHOLDER_TEXT = "Type your message (use /help for more info)...";
|
|
21
22
|
export const INPUT_PLACEHOLDER_TEXT_PREFIX = INPUT_PLACEHOLDER_TEXT.substring(0, 10);
|
|
22
|
-
export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mcpServers = [], connectMcpServer = async () => false, disconnectMcpServer = async () => false, slashCommands = [], hasSlashCommand = () => false, latestTotalTokens = 0, maxInputTokens = 128000, }) => {
|
|
23
|
-
const { permissionMode: chatPermissionMode, setPermissionMode: setChatPermissionMode, handleRewindSelect, backgroundCurrentTask, messages, getFullMessageThread, sessionId, workingDirectory, askBtw, currentModel, configuredModels, setModel, recreateAgent, } = useChat();
|
|
23
|
+
export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mcpServers = [], connectMcpServer = async () => false, disconnectMcpServer = async () => false, slashCommands = [], hasSlashCommand = () => false, latestTotalTokens = 0, maxInputTokens = 128000, isGoalActive, goalElapsed, }) => {
|
|
24
|
+
const { permissionMode: chatPermissionMode, setPermissionMode: setChatPermissionMode, handleRewindSelect, backgroundCurrentTask, messages, getFullMessageThread, sessionId, workingDirectory, askBtw, currentModel, configuredModels, setModel, recreateAgent, recallQueuedMessage, queuedMessages, } = useChat();
|
|
25
|
+
// Ref to hold setInputText so queue callbacks can access it before useInputManager returns
|
|
26
|
+
const setInputTextRef = useRef(() => { });
|
|
27
|
+
const hasQueuedMessages = (queuedMessages?.length ?? 0) > 0;
|
|
28
|
+
const onRecallQueuedMessage = useCallback(() => {
|
|
29
|
+
const msg = recallQueuedMessage();
|
|
30
|
+
if (msg) {
|
|
31
|
+
const prefix = msg.type === "bang" ? "!" : "";
|
|
32
|
+
setInputTextRef.current(prefix + msg.content);
|
|
33
|
+
}
|
|
34
|
+
}, [recallQueuedMessage]);
|
|
24
35
|
// Input manager with all input state and functionality (including images)
|
|
25
36
|
const { inputText, cursorPosition,
|
|
26
37
|
// Image management
|
|
@@ -32,7 +43,7 @@ export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mc
|
|
|
32
43
|
// History search
|
|
33
44
|
showHistorySearch, historySearchQuery,
|
|
34
45
|
// Task/MCP Manager
|
|
35
|
-
showBackgroundTaskManager, showMcpManager, showRewindManager, showHelp, showStatusCommand, showLoginCommand, showPluginManager, showModelSelector, setShowBackgroundTaskManager, setShowMcpManager, setShowRewindManager, setShowHelp, setShowStatusCommand, setShowLoginCommand, setShowPluginManager, setShowModelSelector,
|
|
46
|
+
showBackgroundTaskManager, showMcpManager, showRewindManager, showHelp, showStatusCommand, showLoginCommand, showPluginManager, showModelSelector, showWorkflowManager, setShowBackgroundTaskManager, setShowMcpManager, setShowRewindManager, setShowHelp, setShowStatusCommand, setShowLoginCommand, setShowPluginManager, setShowModelSelector, setShowWorkflowManager,
|
|
36
47
|
// Permission mode
|
|
37
48
|
permissionMode, setPermissionMode,
|
|
38
49
|
// BTW state
|
|
@@ -40,7 +51,9 @@ export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mc
|
|
|
40
51
|
// Main handler
|
|
41
52
|
handleInput,
|
|
42
53
|
// Manager ready state
|
|
43
|
-
isManagerReady,
|
|
54
|
+
isManagerReady,
|
|
55
|
+
// Direct state setters
|
|
56
|
+
setInputText, } = useInputManager({
|
|
44
57
|
onSendMessage: sendMessage,
|
|
45
58
|
onAskBtw: askBtw,
|
|
46
59
|
onHasSlashCommand: hasSlashCommand,
|
|
@@ -50,7 +63,13 @@ export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mc
|
|
|
50
63
|
sessionId,
|
|
51
64
|
workdir: workingDirectory,
|
|
52
65
|
getFullMessageThread,
|
|
66
|
+
hasQueuedMessages,
|
|
67
|
+
onRecallQueuedMessage,
|
|
53
68
|
});
|
|
69
|
+
// Keep setInputText ref updated for queue callbacks
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
setInputTextRef.current = setInputText;
|
|
72
|
+
}, [setInputText]);
|
|
54
73
|
// Sync permission mode from useChat to InputManager
|
|
55
74
|
useEffect(() => {
|
|
56
75
|
setPermissionMode(chatPermissionMode);
|
|
@@ -67,7 +86,8 @@ export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mc
|
|
|
67
86
|
showPluginManager ||
|
|
68
87
|
showModelSelector ||
|
|
69
88
|
showBackgroundTaskManager ||
|
|
70
|
-
showMcpManager
|
|
89
|
+
showMcpManager ||
|
|
90
|
+
showWorkflowManager) {
|
|
71
91
|
return;
|
|
72
92
|
}
|
|
73
93
|
await handleInput(input, key, attachedImages, clearImages);
|
|
@@ -116,11 +136,12 @@ export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mc
|
|
|
116
136
|
if (showModelSelector) {
|
|
117
137
|
return (_jsx(ModelSelector, { onCancel: () => setShowModelSelector(false), currentModel: currentModel, configuredModels: configuredModels, onSelectModel: setModel }));
|
|
118
138
|
}
|
|
119
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(BtwDisplay, { btwState: btwState }), showFileSelector && (_jsx(FileSelector, { files: filteredFiles, searchQuery: searchQuery, isLoading: isFileSearching, onSelect: handleFileSelect, onCancel: handleCancelFileSelect })), showCommandSelector && (_jsx(CommandSelector, { searchQuery: commandSearchQuery, onSelect: handleCommandSelect, onInsert: handleCommandInsert, onCancel: handleCancelCommandSelect, commands: slashCommands })), showHistorySearch && (_jsx(HistorySearch, { searchQuery: historySearchQuery, onSelect: handleHistorySearchSelect, onCancel: handleCancelHistorySearch })), showBackgroundTaskManager && (_jsx(BackgroundTaskManager, { onCancel: () => setShowBackgroundTaskManager(false) })), showMcpManager && (_jsx(McpManager, { onCancel: () => setShowMcpManager(false), servers: mcpServers, onConnectServer: connectMcpServer, onDisconnectServer: disconnectMcpServer })), showBackgroundTaskManager ||
|
|
139
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(BtwDisplay, { btwState: btwState }), showFileSelector && (_jsx(FileSelector, { files: filteredFiles, searchQuery: searchQuery, isLoading: isFileSearching, onSelect: handleFileSelect, onCancel: handleCancelFileSelect })), showCommandSelector && (_jsx(CommandSelector, { searchQuery: commandSearchQuery, onSelect: handleCommandSelect, onInsert: handleCommandInsert, onCancel: handleCancelCommandSelect, commands: slashCommands })), showHistorySearch && (_jsx(HistorySearch, { searchQuery: historySearchQuery, onSelect: handleHistorySearchSelect, onCancel: handleCancelHistorySearch })), showBackgroundTaskManager && (_jsx(BackgroundTaskManager, { onCancel: () => setShowBackgroundTaskManager(false) })), showMcpManager && (_jsx(McpManager, { onCancel: () => setShowMcpManager(false), servers: mcpServers, onConnectServer: connectMcpServer, onDisconnectServer: disconnectMcpServer })), showWorkflowManager && (_jsx(WorkflowManager, { onCancel: () => setShowWorkflowManager(false) })), showBackgroundTaskManager ||
|
|
120
140
|
showMcpManager ||
|
|
121
141
|
showRewindManager ||
|
|
122
142
|
showHelp ||
|
|
123
143
|
showStatusCommand ||
|
|
124
144
|
showLoginCommand ||
|
|
125
|
-
showPluginManager ||
|
|
145
|
+
showPluginManager ||
|
|
146
|
+
showWorkflowManager || (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { borderStyle: "single", borderColor: btwState.isActive ? "cyan" : "gray", borderLeft: false, borderRight: false, children: _jsx(Text, { color: isPlaceholder ? "gray" : "white", children: btwState.isActive && isPlaceholder ? (_jsxs(_Fragment, { children: [_jsx(Text, { backgroundColor: "white", color: "black", children: " " }), _jsx(Text, { color: "cyan", children: "Type your side question..." })] })) : shouldShowCursor ? (_jsxs(_Fragment, { children: [beforeCursor, _jsx(Text, { backgroundColor: "white", color: "black", children: atCursor }), afterCursor] })) : (displayText) }) }), _jsx(StatusLine, { permissionMode: permissionMode, isShellCommand: isShellCommand, isBtwActive: btwState.isActive, isGoalActive: isGoalActive, goalElapsed: goalElapsed, latestTotalTokens: latestTotalTokens, maxInputTokens: maxInputTokens })] }))] }));
|
|
126
147
|
};
|
|
@@ -2,10 +2,11 @@ export interface LoadingIndicatorProps {
|
|
|
2
2
|
isLoading?: boolean;
|
|
3
3
|
isCommandRunning?: boolean;
|
|
4
4
|
isCompacting?: boolean;
|
|
5
|
+
isGoalEvaluating?: boolean;
|
|
5
6
|
latestTotalTokens?: number;
|
|
6
7
|
}
|
|
7
8
|
export declare const LoadingIndicator: {
|
|
8
|
-
({ isLoading, isCommandRunning, isCompacting, latestTotalTokens, }: LoadingIndicatorProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
({ isLoading, isCommandRunning, isCompacting, isGoalEvaluating, latestTotalTokens, }: LoadingIndicatorProps): import("react/jsx-runtime").JSX.Element;
|
|
9
10
|
displayName: string;
|
|
10
11
|
};
|
|
11
12
|
//# sourceMappingURL=LoadingIndicator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoadingIndicator.d.ts","sourceRoot":"","sources":["../../src/components/LoadingIndicator.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,gBAAgB;
|
|
1
|
+
{"version":3,"file":"LoadingIndicator.d.ts","sourceRoot":"","sources":["../../src/components/LoadingIndicator.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,gBAAgB;0FAM1B,qBAAqB;;CAuCvB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
|
-
export const LoadingIndicator = ({ isLoading = false, isCommandRunning = false, isCompacting = false, latestTotalTokens = 0, }) => {
|
|
4
|
-
return (_jsxs(Box, { flexDirection: "column", children: [isLoading && !isCompacting && (_jsxs(Box, { children: [_jsx(Text, { color: "yellow", children: "\u273B AI is thinking... " }), latestTotalTokens > 0 && (_jsxs(_Fragment, { children: [_jsxs(Text, { color: "gray", dimColor: true, children: ["|", " "] }), _jsx(Text, { color: "blue", bold: true, children: latestTotalTokens.toLocaleString() }), _jsxs(Text, { color: "gray", dimColor: true, children: [" ", "tokens", " "] })] })), _jsxs(Text, { color: "gray", dimColor: true, children: ["|", " "] }), _jsx(Text, { color: "red", bold: true, children: "Esc" }), _jsxs(Text, { color: "gray", dimColor: true, children: [" ", "to abort"] })] })), isCommandRunning && _jsx(Text, { color: "blue", children: "\u273B Command is running..." }), isCompacting && (_jsx(Text, { color: "magenta", children: "\u273B Compacting message history..." }))] }));
|
|
3
|
+
export const LoadingIndicator = ({ isLoading = false, isCommandRunning = false, isCompacting = false, isGoalEvaluating = false, latestTotalTokens = 0, }) => {
|
|
4
|
+
return (_jsxs(Box, { flexDirection: "column", children: [isLoading && !isCompacting && !isGoalEvaluating && (_jsxs(Box, { children: [_jsx(Text, { color: "yellow", children: "\u273B AI is thinking... " }), latestTotalTokens > 0 && (_jsxs(_Fragment, { children: [_jsxs(Text, { color: "gray", dimColor: true, children: ["|", " "] }), _jsx(Text, { color: "blue", bold: true, children: latestTotalTokens.toLocaleString() }), _jsxs(Text, { color: "gray", dimColor: true, children: [" ", "tokens", " "] })] })), _jsxs(Text, { color: "gray", dimColor: true, children: ["|", " "] }), _jsx(Text, { color: "red", bold: true, children: "Esc" }), _jsxs(Text, { color: "gray", dimColor: true, children: [" ", "to abort"] })] })), isCommandRunning && _jsx(Text, { color: "blue", children: "\u273B Command is running..." }), isCompacting && (_jsx(Text, { color: "magenta", children: "\u273B Compacting message history..." })), isGoalEvaluating && _jsx(Text, { color: "cyan", children: "\u273B Evaluating goal..." })] }));
|
|
5
5
|
};
|
|
6
6
|
LoadingIndicator.displayName = "LoadingIndicator";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueuedMessageList.d.ts","sourceRoot":"","sources":["../../src/components/QueuedMessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"QueuedMessageList.d.ts","sourceRoot":"","sources":["../../src/components/QueuedMessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EA+BrC,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useChat } from "../contexts/useChat.js";
|
|
3
3
|
import { Box, Text } from "ink";
|
|
4
4
|
export const QueuedMessageList = () => {
|
|
@@ -6,13 +6,13 @@ export const QueuedMessageList = () => {
|
|
|
6
6
|
if (queuedMessages.length === 0) {
|
|
7
7
|
return null;
|
|
8
8
|
}
|
|
9
|
-
return (
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
return (_jsxs(Box, { flexDirection: "column", children: [queuedMessages.map((msg, index) => {
|
|
10
|
+
const content = msg.content.trim();
|
|
11
|
+
const hasImages = msg.images && msg.images.length > 0;
|
|
12
|
+
const prefix = msg.type === "bang" ? "! " : "";
|
|
13
|
+
const displayText = prefix + (content || (hasImages ? "[Images]" : ""));
|
|
14
|
+
return (_jsxs(Box, { children: [_jsxs(Text, { color: "gray", children: ["[", index + 1, "] "] }), _jsx(Text, { color: "gray", italic: true, children: displayText.length > 55
|
|
15
|
+
? `${displayText.substring(0, 52)}...`
|
|
16
|
+
: displayText })] }, msg.id ?? index));
|
|
17
|
+
}), _jsxs(Text, { color: "gray", dimColor: true, children: [" ", "\u2191 recall"] })] }));
|
|
18
18
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusLine.d.ts","sourceRoot":"","sources":["../../src/components/StatusLine.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,
|
|
1
|
+
{"version":3,"file":"StatusLine.d.ts","sourceRoot":"","sources":["../../src/components/StatusLine.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA0DhD,CAAC"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
|
-
export const StatusLine = ({ permissionMode, isShellCommand, isBtwActive, latestTotalTokens = 0, maxInputTokens = 128000, }) => {
|
|
3
|
+
export const StatusLine = ({ permissionMode, isShellCommand, isBtwActive, isGoalActive, goalElapsed, latestTotalTokens = 0, maxInputTokens = 128000, }) => {
|
|
4
4
|
const percentage = latestTotalTokens > 0
|
|
5
5
|
? Math.min(Math.round((latestTotalTokens / maxInputTokens) * 100), 100)
|
|
6
6
|
: 0;
|
|
7
7
|
const contextColor = percentage > 95 ? "red" : percentage > 80 ? "yellow" : "gray";
|
|
8
|
-
return (_jsxs(Box, { paddingRight: 1, justifyContent: "space-between", width: "100%", children: [isBtwActive ? (_jsxs(Text, { color: "gray", children: ["Mode: ", _jsx(Text, { color: "cyan", children: "BTW" }), " (ESC to dismiss)"] })) : isShellCommand ? (_jsxs(Text, { color: "gray", children: ["Shell: ", _jsx(Text, { color: "yellow", children: "Run shell command" })] })) : (_jsxs(Text, { color: "gray", children: ["Mode:", " ", _jsx(Text, { color: permissionMode === "plan"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
return (_jsxs(Box, { paddingRight: 1, justifyContent: "space-between", width: "100%", children: [isBtwActive ? (_jsxs(Text, { color: "gray", children: ["Mode: ", _jsx(Text, { color: "cyan", children: "BTW" }), " (ESC to dismiss)"] })) : isShellCommand ? (_jsxs(Text, { color: "gray", children: ["Shell: ", _jsx(Text, { color: "yellow", children: "Run shell command" })] })) : (_jsxs(Box, { children: [isGoalActive && (_jsxs(Text, { color: "gray", children: [_jsx(Text, { color: "cyan", children: "\u25CE /goal" }), " active", " ", goalElapsed && _jsxs(Text, { children: ["(", goalElapsed, ")"] }), " |", " "] })), _jsxs(Text, { color: "gray", children: ["Mode:", " ", _jsx(Text, { color: permissionMode === "plan"
|
|
9
|
+
? "yellow"
|
|
10
|
+
: permissionMode === "bypassPermissions"
|
|
11
|
+
? "red"
|
|
12
|
+
: "cyan", bold: permissionMode === "bypassPermissions", children: permissionMode }), " ", "(Shift+Tab to cycle)"] })] })), percentage > 0 && (_jsxs(Text, { color: contextColor, children: [percentage, "% context"] }))] }));
|
|
13
13
|
};
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import type { Task, TaskStatus } from "wave-agent-sdk";
|
|
3
|
+
export declare const getStatusIcon: (status: TaskStatus) => React.ReactNode;
|
|
4
|
+
export declare function sortTasksByPriority(tasks: Task[], completionTimestamps: Map<string, number>, now: number, needsTruncation: boolean): Task[];
|
|
2
5
|
export declare const TaskList: React.FC;
|
|
3
6
|
//# sourceMappingURL=TaskList.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskList.d.ts","sourceRoot":"","sources":["../../src/components/TaskList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"TaskList.d.ts","sourceRoot":"","sources":["../../src/components/TaskList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAKvD,eAAO,MAAM,aAAa,GAAI,QAAQ,UAAU,KAAG,KAAK,CAAC,SAaxD,CAAC;AAWF,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,IAAI,EAAE,EACb,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACzC,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,OAAO,GACvB,IAAI,EAAE,CA8CR;AAOD,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EA6J5B,CAAC"}
|
|
@@ -1,37 +1,180 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
2
3
|
import { useChat } from "../contexts/useChat.js";
|
|
3
|
-
import { Box, Text } from "ink";
|
|
4
|
+
import { Box, Text, useStdout } from "ink";
|
|
4
5
|
import { useTasks } from "../hooks/useTasks.js";
|
|
6
|
+
const RECENTLY_COMPLETED_TTL_MS = 30000;
|
|
7
|
+
const AUTO_HIDE_DELAY_MS = 5000;
|
|
8
|
+
export const getStatusIcon = (status) => {
|
|
9
|
+
switch (status) {
|
|
10
|
+
case "pending":
|
|
11
|
+
return _jsx(Text, { color: "gray", children: "\u25A1" });
|
|
12
|
+
case "in_progress":
|
|
13
|
+
return _jsx(Text, { color: "yellow", children: "\u25A0" });
|
|
14
|
+
case "completed":
|
|
15
|
+
return _jsx(Text, { color: "green", children: "\u2713" });
|
|
16
|
+
case "deleted":
|
|
17
|
+
return _jsx(Text, { color: "red", children: "\u2715" });
|
|
18
|
+
default:
|
|
19
|
+
return _jsx(Text, { color: "gray", children: "?" });
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
function byIdAsc(a, b) {
|
|
23
|
+
const aNum = parseInt(a.id, 10);
|
|
24
|
+
const bNum = parseInt(b.id, 10);
|
|
25
|
+
if (!isNaN(aNum) && !isNaN(bNum)) {
|
|
26
|
+
return aNum - bNum;
|
|
27
|
+
}
|
|
28
|
+
return a.id.localeCompare(b.id);
|
|
29
|
+
}
|
|
30
|
+
export function sortTasksByPriority(tasks, completionTimestamps, now, needsTruncation) {
|
|
31
|
+
if (!needsTruncation) {
|
|
32
|
+
// No truncation needed — sort by ID for stable ordering
|
|
33
|
+
return [...tasks].sort(byIdAsc);
|
|
34
|
+
}
|
|
35
|
+
// When truncation is needed, prioritize:
|
|
36
|
+
// recently completed > in_progress > pending (unblocked first) > older completed > deleted
|
|
37
|
+
const recentCompleted = [];
|
|
38
|
+
const olderCompleted = [];
|
|
39
|
+
for (const task of tasks.filter((t) => t.status === "completed")) {
|
|
40
|
+
const ts = completionTimestamps.get(task.id);
|
|
41
|
+
if (ts && now - ts < RECENTLY_COMPLETED_TTL_MS) {
|
|
42
|
+
recentCompleted.push(task);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
olderCompleted.push(task);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
recentCompleted.sort(byIdAsc);
|
|
49
|
+
olderCompleted.sort(byIdAsc);
|
|
50
|
+
const inProgress = tasks
|
|
51
|
+
.filter((t) => t.status === "in_progress")
|
|
52
|
+
.sort(byIdAsc);
|
|
53
|
+
const unresolvedTaskIds = new Set(tasks.filter((t) => t.status !== "completed").map((t) => t.id));
|
|
54
|
+
const pending = tasks
|
|
55
|
+
.filter((t) => t.status === "pending")
|
|
56
|
+
.sort((a, b) => {
|
|
57
|
+
const aBlocked = a.blockedBy.some((id) => unresolvedTaskIds.has(id));
|
|
58
|
+
const bBlocked = b.blockedBy.some((id) => unresolvedTaskIds.has(id));
|
|
59
|
+
if (aBlocked !== bBlocked)
|
|
60
|
+
return aBlocked ? 1 : -1;
|
|
61
|
+
return byIdAsc(a, b);
|
|
62
|
+
});
|
|
63
|
+
const deleted = tasks.filter((t) => t.status === "deleted").sort(byIdAsc);
|
|
64
|
+
return [
|
|
65
|
+
...recentCompleted,
|
|
66
|
+
...inProgress,
|
|
67
|
+
...pending,
|
|
68
|
+
...olderCompleted,
|
|
69
|
+
...deleted,
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
function getDisplayLimit(rows) {
|
|
73
|
+
const available = rows ?? 24;
|
|
74
|
+
return available <= 10 ? 0 : Math.min(10, Math.max(3, available - 14));
|
|
75
|
+
}
|
|
5
76
|
export const TaskList = () => {
|
|
6
77
|
const tasks = useTasks();
|
|
7
78
|
const { isTaskListVisible } = useChat();
|
|
8
|
-
|
|
9
|
-
|
|
79
|
+
const { stdout } = useStdout();
|
|
80
|
+
const completionTimestampsRef = React.useRef(new Map());
|
|
81
|
+
const previousCompletedIdsRef = React.useRef(null);
|
|
82
|
+
const autoHideTimerRef = React.useRef(null);
|
|
83
|
+
const [autoHidden, setAutoHidden] = React.useState(() => {
|
|
84
|
+
// If all tasks are already completed on mount (e.g. session restore),
|
|
85
|
+
// start hidden immediately instead of flashing for 5 seconds.
|
|
86
|
+
const active = tasks.filter((t) => t.status !== "deleted");
|
|
87
|
+
return active.length > 0 && active.every((t) => t.status === "completed");
|
|
88
|
+
});
|
|
89
|
+
const [, forceUpdate] = React.useState(0);
|
|
90
|
+
const now = Date.now();
|
|
91
|
+
const activeTasks = tasks.filter((t) => t.status !== "deleted");
|
|
92
|
+
// Track completion timestamps: only set when a task newly transitions to completed
|
|
93
|
+
if (previousCompletedIdsRef.current === null) {
|
|
94
|
+
previousCompletedIdsRef.current = new Set(tasks.filter((t) => t.status === "completed").map((t) => t.id));
|
|
10
95
|
}
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
case "in_progress":
|
|
16
|
-
return _jsx(Text, { color: "yellow", children: "\u25A0" });
|
|
17
|
-
case "completed":
|
|
18
|
-
return _jsx(Text, { color: "green", children: "\u2713" });
|
|
19
|
-
case "deleted":
|
|
20
|
-
return _jsx(Text, { color: "red", children: "\u2715" });
|
|
21
|
-
default:
|
|
22
|
-
return _jsx(Text, { color: "gray", children: "?" });
|
|
96
|
+
const currentCompletedIds = new Set(tasks.filter((t) => t.status === "completed").map((t) => t.id));
|
|
97
|
+
for (const id of currentCompletedIds) {
|
|
98
|
+
if (!previousCompletedIdsRef.current.has(id)) {
|
|
99
|
+
completionTimestampsRef.current.set(id, now);
|
|
23
100
|
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
101
|
+
}
|
|
102
|
+
for (const id of completionTimestampsRef.current.keys()) {
|
|
103
|
+
if (!currentCompletedIds.has(id)) {
|
|
104
|
+
completionTimestampsRef.current.delete(id);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
previousCompletedIdsRef.current = currentCompletedIds;
|
|
108
|
+
// Schedule re-render when the next recent completion expires
|
|
109
|
+
React.useEffect(() => {
|
|
110
|
+
if (completionTimestampsRef.current.size === 0)
|
|
111
|
+
return;
|
|
112
|
+
const currentNow = Date.now();
|
|
113
|
+
let earliestExpiry = Infinity;
|
|
114
|
+
for (const ts of completionTimestampsRef.current.values()) {
|
|
115
|
+
const expiry = ts + RECENTLY_COMPLETED_TTL_MS;
|
|
116
|
+
if (expiry > currentNow && expiry < earliestExpiry) {
|
|
117
|
+
earliestExpiry = expiry;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (earliestExpiry === Infinity)
|
|
121
|
+
return;
|
|
122
|
+
const timer = setTimeout(() => forceUpdate((n) => n + 1), earliestExpiry - currentNow);
|
|
123
|
+
return () => clearTimeout(timer);
|
|
124
|
+
}, [tasks]);
|
|
125
|
+
// Auto-hide logic: when all active tasks are completed
|
|
126
|
+
const allCompleted = activeTasks.length > 0 &&
|
|
127
|
+
activeTasks.every((t) => t.status === "completed");
|
|
128
|
+
React.useEffect(() => {
|
|
129
|
+
if (allCompleted && !autoHidden) {
|
|
130
|
+
autoHideTimerRef.current = setTimeout(() => {
|
|
131
|
+
setAutoHidden(true);
|
|
132
|
+
}, AUTO_HIDE_DELAY_MS);
|
|
133
|
+
}
|
|
134
|
+
if (!allCompleted && autoHidden) {
|
|
135
|
+
setAutoHidden(false);
|
|
136
|
+
}
|
|
137
|
+
return () => {
|
|
138
|
+
if (autoHideTimerRef.current) {
|
|
139
|
+
clearTimeout(autoHideTimerRef.current);
|
|
140
|
+
autoHideTimerRef.current = null;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}, [allCompleted, autoHidden]);
|
|
144
|
+
if (tasks.length === 0 || !isTaskListVisible || autoHidden) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
const displayLimit = getDisplayLimit(stdout?.rows);
|
|
148
|
+
const needsTruncation = tasks.length > displayLimit;
|
|
149
|
+
const sorted = sortTasksByPriority(tasks, completionTimestampsRef.current, now, needsTruncation);
|
|
150
|
+
const displayed = displayLimit > 0 ? sorted.slice(0, displayLimit) : [];
|
|
151
|
+
const hidden = displayLimit > 0 ? sorted.slice(displayLimit) : sorted;
|
|
152
|
+
const doneCount = tasks.filter((t) => t.status === "completed").length;
|
|
153
|
+
const inProgressCount = tasks.filter((t) => t.status === "in_progress").length;
|
|
154
|
+
const openCount = tasks.filter((t) => t.status === "pending").length;
|
|
155
|
+
// Summary parts for hidden tasks
|
|
156
|
+
const hiddenInProgress = hidden.filter((t) => t.status === "in_progress").length;
|
|
157
|
+
const hiddenPending = hidden.filter((t) => t.status === "pending").length;
|
|
158
|
+
const hiddenCompleted = hidden.filter((t) => t.status === "completed").length;
|
|
159
|
+
const summaryParts = [];
|
|
160
|
+
if (hiddenInProgress > 0)
|
|
161
|
+
summaryParts.push(`${hiddenInProgress} in progress`);
|
|
162
|
+
if (hiddenPending > 0)
|
|
163
|
+
summaryParts.push(`${hiddenPending} pending`);
|
|
164
|
+
if (hiddenCompleted > 0)
|
|
165
|
+
summaryParts.push(`${hiddenCompleted} completed`);
|
|
166
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { dimColor: true, children: [tasks.length, " tasks (", doneCount, " done, ", inProgressCount, " in progress,", " ", openCount, " open)"] }), displayed.map((task) => {
|
|
167
|
+
const isDimmed = task.status === "completed" || task.status === "deleted";
|
|
168
|
+
const unresolvedTaskIds = new Set(tasks.filter((t) => t.status !== "completed").map((t) => t.id));
|
|
169
|
+
const isBlocked = task.blockedBy &&
|
|
170
|
+
task.blockedBy.some((id) => unresolvedTaskIds.has(id));
|
|
171
|
+
const blockingTaskIds = isBlocked
|
|
172
|
+
? task.blockedBy.map((id) => `#${id}`)
|
|
173
|
+
: [];
|
|
174
|
+
const blockedByText = isBlocked && blockingTaskIds.length > 0
|
|
175
|
+
? ` (Blocked by: ${blockingTaskIds.join(", ")})`
|
|
176
|
+
: "";
|
|
177
|
+
const fullText = `${task.subject}${blockedByText}`;
|
|
178
|
+
return (_jsxs(Box, { gap: 1, children: [getStatusIcon(task.status), _jsx(Text, { dimColor: isDimmed, wrap: "truncate-end", children: fullText })] }, task.id));
|
|
179
|
+
}), displayLimit > 0 && hidden.length > 0 && (_jsxs(Text, { dimColor: true, children: [" \u2026 +", summaryParts.join(", ")] }))] }));
|
|
37
180
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskNotificationMessage.d.ts","sourceRoot":"","sources":["../../src/components/TaskNotificationMessage.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5D,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,qBAAqB,CAAC;CAC9B;
|
|
1
|
+
{"version":3,"file":"TaskNotificationMessage.d.ts","sourceRoot":"","sources":["../../src/components/TaskNotificationMessage.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5D,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,qBAAqB,CAAC;CAC9B;AASD,eAAO,MAAM,uBAAuB,GAAI,YAErC,4BAA4B,4CAW9B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowManager.d.ts","sourceRoot":"","sources":["../../src/components/WorkflowManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AASrD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAmCD,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAiR1D,CAAC"}
|