wave-code 0.14.1 → 0.14.3
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/components/ChatInterface.js +2 -2
- package/dist/components/CompactDisplay.d.ts +9 -0
- package/dist/components/CompactDisplay.d.ts.map +1 -0
- package/dist/components/{CompressDisplay.js → CompactDisplay.js} +2 -2
- package/dist/components/InstalledView.d.ts.map +1 -1
- package/dist/components/InstalledView.js +5 -2
- package/dist/components/LoadingIndicator.d.ts +2 -2
- package/dist/components/LoadingIndicator.d.ts.map +1 -1
- package/dist/components/LoadingIndicator.js +2 -2
- package/dist/components/MessageBlockItem.js +2 -2
- package/dist/components/ModelSelector.d.ts.map +1 -1
- package/dist/components/ModelSelector.js +8 -1
- package/dist/components/PluginList.d.ts.map +1 -1
- package/dist/components/PluginList.js +5 -2
- package/dist/contexts/useChat.d.ts +1 -1
- package/dist/contexts/useChat.d.ts.map +1 -1
- package/dist/contexts/useChat.js +6 -6
- package/dist/utils/usageSummary.d.ts +1 -1
- package/dist/utils/usageSummary.d.ts.map +1 -1
- package/dist/utils/usageSummary.js +7 -7
- package/package.json +2 -2
- package/src/components/ChatInterface.tsx +3 -3
- package/src/components/{CompressDisplay.tsx → CompactDisplay.tsx} +5 -5
- package/src/components/InstalledView.tsx +15 -2
- package/src/components/LoadingIndicator.tsx +5 -5
- package/src/components/MessageBlockItem.tsx +3 -3
- package/src/components/ModelSelector.tsx +36 -16
- package/src/components/PluginList.tsx +16 -2
- package/src/contexts/useChat.tsx +7 -7
- package/src/utils/usageSummary.ts +8 -8
- package/dist/components/CompressDisplay.d.ts +0 -9
- package/dist/components/CompressDisplay.d.ts.map +0 -1
|
@@ -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,
|
|
13
|
+
const { messages, isLoading, isCommandRunning, isCompacting, sendMessage, abortMessage, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, slashCommands, hasSlashCommand, isConfirmationVisible, hasPendingConfirmations, confirmingTool, handleConfirmationDecision, handleConfirmationCancel, version, workdir, remountKey, requestRemount, } = useChat();
|
|
14
14
|
const displayMessages = messages;
|
|
15
15
|
const [forceStatic, setForceStatic] = useState(false);
|
|
16
16
|
const { stdout } = useStdout();
|
|
@@ -37,5 +37,5 @@ 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 || isCommandRunning ||
|
|
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 || isCommandRunning || isCompacting) && (_jsx(LoadingIndicator, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompacting: isCompacting, 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 })] })), 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
41
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { CompactBlock } from "wave-agent-sdk";
|
|
3
|
+
interface CompactDisplayProps {
|
|
4
|
+
block: CompactBlock;
|
|
5
|
+
isExpanded?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare const CompactDisplay: React.FC<CompactDisplayProps>;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=CompactDisplay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactDisplay.d.ts","sourceRoot":"","sources":["../../src/components/CompactDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,UAAU,mBAAmB;IAC3B,KAAK,EAAE,YAAY,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA+BxD,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo } from "react";
|
|
3
3
|
import { Box, Text } from "ink";
|
|
4
|
-
export const
|
|
4
|
+
export const CompactDisplay = ({ block }) => {
|
|
5
5
|
const { content } = block;
|
|
6
6
|
const { displayContent } = useMemo(() => {
|
|
7
7
|
if (!content) {
|
|
@@ -9,5 +9,5 @@ export const CompressDisplay = ({ block }) => {
|
|
|
9
9
|
}
|
|
10
10
|
return { displayContent: content };
|
|
11
11
|
}, [content]);
|
|
12
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { children: _jsx(Text, { children: "
|
|
12
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { children: _jsx(Text, { children: "Compacted Messages" }) }), content && (_jsx(Box, { marginTop: 1, flexDirection: "column", children: _jsx(Box, { paddingLeft: 2, borderLeft: true, borderColor: "gray", flexDirection: "column", children: _jsx(Text, { color: "white", children: displayContent }) }) }))] }));
|
|
13
13
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstalledView.d.ts","sourceRoot":"","sources":["../../src/components/InstalledView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAIxC,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"InstalledView.d.ts","sourceRoot":"","sources":["../../src/components/InstalledView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAIxC,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAqEjC,CAAC"}
|
|
@@ -23,8 +23,11 @@ export const InstalledView = () => {
|
|
|
23
23
|
if (installedPlugins.length === 0) {
|
|
24
24
|
return (_jsx(Box, { padding: 1, children: _jsx(Text, { dimColor: true, children: "No plugins installed." }) }));
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
const MAX_VISIBLE_ITEMS = 3;
|
|
27
|
+
const startIndex = Math.max(0, Math.min(selectedIndex - Math.floor(MAX_VISIBLE_ITEMS / 2), Math.max(0, installedPlugins.length - MAX_VISIBLE_ITEMS)));
|
|
28
|
+
const visiblePlugins = installedPlugins.slice(startIndex, startIndex + MAX_VISIBLE_ITEMS);
|
|
29
|
+
return (_jsx(Box, { flexDirection: "column", children: visiblePlugins.map((plugin, index) => {
|
|
30
|
+
const isSelected = index + startIndex === selectedIndex;
|
|
28
31
|
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: isSelected ? "cyan" : undefined, children: [isSelected ? "> " : " ", _jsx(Text, { bold: true, children: plugin.name }), _jsxs(Text, { dimColor: true, children: [" @", plugin.marketplace] }), plugin.scope && _jsxs(Text, { color: "gray", children: [" (", plugin.scope, ")"] })] }) }), isSelected && (_jsx(Box, { marginLeft: 4, children: _jsx(Text, { dimColor: true, children: "Press Enter for actions" }) }))] }, `${plugin.name}@${plugin.marketplace}`));
|
|
29
32
|
}) }));
|
|
30
33
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export interface LoadingIndicatorProps {
|
|
2
2
|
isLoading?: boolean;
|
|
3
3
|
isCommandRunning?: boolean;
|
|
4
|
-
|
|
4
|
+
isCompacting?: boolean;
|
|
5
5
|
latestTotalTokens?: number;
|
|
6
6
|
}
|
|
7
7
|
export declare const LoadingIndicator: {
|
|
8
|
-
({ isLoading, isCommandRunning,
|
|
8
|
+
({ isLoading, isCommandRunning, isCompacting, latestTotalTokens, }: LoadingIndicatorProps): import("react/jsx-runtime").JSX.Element;
|
|
9
9
|
displayName: string;
|
|
10
10
|
};
|
|
11
11
|
//# 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,
|
|
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;wEAK1B,qBAAqB;;CAsCvB,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,
|
|
4
|
-
return (_jsxs(Box, { flexDirection: "column", children: [isLoading && !
|
|
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..." }))] }));
|
|
5
5
|
};
|
|
6
6
|
LoadingIndicator.displayName = "LoadingIndicator";
|
|
@@ -3,7 +3,7 @@ import { Box, Text } from "ink";
|
|
|
3
3
|
import { MessageSource } from "wave-agent-sdk";
|
|
4
4
|
import { BangDisplay } from "./BangDisplay.js";
|
|
5
5
|
import { ToolDisplay } from "./ToolDisplay.js";
|
|
6
|
-
import {
|
|
6
|
+
import { CompactDisplay } from "./CompactDisplay.js";
|
|
7
7
|
import { ReasoningDisplay } from "./ReasoningDisplay.js";
|
|
8
8
|
import { Markdown } from "./Markdown.js";
|
|
9
9
|
import { TaskNotificationMessage } from "./TaskNotificationMessage.js";
|
|
@@ -11,5 +11,5 @@ export const MessageBlockItem = ({ block, message, isExpanded, paddingTop = 0, }
|
|
|
11
11
|
return (_jsxs(Box, { flexDirection: "column", paddingTop: paddingTop, children: [block.type === "text" && block.content.trim() && (_jsxs(Box, { children: [block.source === MessageSource.HOOK && (_jsxs(Text, { color: "magenta", bold: true, children: ["~", " "] })), message.role === "user" || isExpanded ? (_jsx(Text, { backgroundColor: message.role === "user" ? "gray" : undefined, color: "white", children: block.content })) : block.stage === "streaming" ? (_jsx(Text, { color: "gray", wrap: "truncate-end", children: (() => {
|
|
12
12
|
const flat = block.content.replace(/\n/g, "\\n");
|
|
13
13
|
return flat.length > 30 ? `…${flat.slice(-30)}` : flat;
|
|
14
|
-
})() })) : (_jsx(Markdown, { children: block.content }))] })), block.type === "error" && (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", block.content] }) })), block.type === "bang" && (_jsx(BangDisplay, { block: block, isExpanded: isExpanded })), block.type === "tool" && (_jsx(ToolDisplay, { block: block, isExpanded: isExpanded })), block.type === "image" && (_jsxs(Box, { children: [_jsx(Text, { color: "magenta", bold: true, children: "# Image" }), block.imageUrls && block.imageUrls.length > 0 && (_jsxs(Text, { color: "gray", dimColor: true, children: [" ", "(", block.imageUrls.length, ")"] }))] })), block.type === "
|
|
14
|
+
})() })) : (_jsx(Markdown, { children: block.content }))] })), block.type === "error" && (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", block.content] }) })), block.type === "bang" && (_jsx(BangDisplay, { block: block, isExpanded: isExpanded })), block.type === "tool" && (_jsx(ToolDisplay, { block: block, isExpanded: isExpanded })), block.type === "image" && (_jsxs(Box, { children: [_jsx(Text, { color: "magenta", bold: true, children: "# Image" }), block.imageUrls && block.imageUrls.length > 0 && (_jsxs(Text, { color: "gray", dimColor: true, children: [" ", "(", block.imageUrls.length, ")"] }))] })), block.type === "compact" && (_jsx(CompactDisplay, { block: block, isExpanded: isExpanded })), block.type === "reasoning" && (_jsx(ReasoningDisplay, { block: block, isExpanded: isExpanded })), block.type === "task_notification" && (_jsx(TaskNotificationMessage, { block: block }))] }));
|
|
15
15
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModelSelector.d.ts","sourceRoot":"","sources":["../../src/components/ModelSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;
|
|
1
|
+
{"version":3,"file":"ModelSelector.d.ts","sourceRoot":"","sources":["../../src/components/ModelSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAID,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAoHtD,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from "react";
|
|
3
3
|
import { Box, Text, useInput } from "ink";
|
|
4
|
+
const MAX_VISIBLE_ITEMS = 5;
|
|
4
5
|
export const ModelSelector = ({ onCancel, currentModel, configuredModels, onSelectModel, }) => {
|
|
5
6
|
const [selectedIndex, setSelectedIndex] = useState(() => {
|
|
6
7
|
const index = configuredModels.indexOf(currentModel);
|
|
@@ -27,8 +28,14 @@ export const ModelSelector = ({ onCancel, currentModel, configuredModels, onSele
|
|
|
27
28
|
return;
|
|
28
29
|
}
|
|
29
30
|
});
|
|
31
|
+
// Calculate visible window
|
|
32
|
+
const startIndex = Math.max(0, Math.min(selectedIndex - Math.floor(MAX_VISIBLE_ITEMS / 2), Math.max(0, configuredModels.length - MAX_VISIBLE_ITEMS)));
|
|
33
|
+
const visibleModels = configuredModels.slice(startIndex, startIndex + MAX_VISIBLE_ITEMS);
|
|
30
34
|
if (configuredModels.length === 0) {
|
|
31
35
|
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: "Select AI Model" }), _jsx(Text, { children: "No models configured" }), _jsx(Text, { dimColor: true, children: "Press Escape to close" })] }));
|
|
32
36
|
}
|
|
33
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsx(Text, { color: "cyan", bold: true, children: "Select AI Model" }) }), _jsx(Text, { dimColor: true, children: "Select a model to use for the current session" }),
|
|
37
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsx(Text, { color: "cyan", bold: true, children: "Select AI Model" }) }), _jsx(Text, { dimColor: true, children: "Select a model to use for the current session" }), visibleModels.map((model, index) => {
|
|
38
|
+
const actualIndex = startIndex + index;
|
|
39
|
+
return (_jsx(Box, { children: _jsxs(Text, { color: actualIndex === selectedIndex ? "black" : "white", backgroundColor: actualIndex === selectedIndex ? "cyan" : undefined, children: [actualIndex === selectedIndex ? "▶ " : " ", model, model === currentModel ? (_jsx(Text, { color: "green", children: " (current)" })) : ("")] }) }, model));
|
|
40
|
+
}), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "\u2191/\u2193 to select \u00B7 Enter to confirm \u00B7 Esc to cancel" }) })] }));
|
|
34
41
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PluginList.d.ts","sourceRoot":"","sources":["../../src/components/PluginList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAExD,UAAU,eAAe;IACvB,OAAO,EAAE,CAAC,sBAAsB,GAAG;QACjC,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,OAAO,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC,EAAE,CAAC;IACL,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;
|
|
1
|
+
{"version":3,"file":"PluginList.d.ts","sourceRoot":"","sources":["../../src/components/PluginList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAExD,UAAU,eAAe;IACvB,OAAO,EAAE,CAAC,sBAAsB,GAAG;QACjC,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,OAAO,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC,EAAE,CAAC;IACL,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAID,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAgDhD,CAAC"}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
|
+
const MAX_VISIBLE_ITEMS = 3;
|
|
3
4
|
export const PluginList = ({ plugins, selectedIndex, }) => {
|
|
4
5
|
if (plugins.length === 0) {
|
|
5
6
|
return (_jsx(Box, { padding: 1, children: _jsx(Text, { dimColor: true, children: "No plugins found." }) }));
|
|
6
7
|
}
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
const startIndex = Math.max(0, Math.min(selectedIndex - Math.floor(MAX_VISIBLE_ITEMS / 2), Math.max(0, plugins.length - MAX_VISIBLE_ITEMS)));
|
|
9
|
+
const visiblePlugins = plugins.slice(startIndex, startIndex + MAX_VISIBLE_ITEMS);
|
|
10
|
+
return (_jsx(Box, { flexDirection: "column", children: visiblePlugins.map((plugin, index) => {
|
|
11
|
+
const isSelected = index + startIndex === selectedIndex;
|
|
9
12
|
const pluginId = `${plugin.name}@${plugin.marketplace}`;
|
|
10
13
|
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: isSelected ? "cyan" : undefined, children: [isSelected ? "> " : " ", _jsx(Text, { bold: true, children: plugin.name }), _jsxs(Text, { dimColor: true, children: [" @", plugin.marketplace] }), plugin.version && _jsxs(Text, { color: "blue", children: [" v", plugin.version] })] }) }), _jsx(Box, { marginLeft: 4, children: _jsx(Text, { dimColor: true, children: plugin.description }) })] }, pluginId));
|
|
11
14
|
}) }));
|
|
@@ -5,7 +5,7 @@ export interface ChatContextType {
|
|
|
5
5
|
messages: Message[];
|
|
6
6
|
isLoading: boolean;
|
|
7
7
|
isCommandRunning: boolean;
|
|
8
|
-
|
|
8
|
+
isCompacting: boolean;
|
|
9
9
|
isExpanded: boolean;
|
|
10
10
|
isTaskListVisible: boolean;
|
|
11
11
|
setIsTaskListVisible: (visible: boolean) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,aAAa,EACd,MAAM,gBAAgB,CAAC;AAYxB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,
|
|
1
|
+
{"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"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"}
|
package/dist/contexts/useChat.js
CHANGED
|
@@ -48,7 +48,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
48
48
|
const [latestTotalTokens, setlatestTotalTokens] = useState(0);
|
|
49
49
|
const [sessionId, setSessionId] = useState("");
|
|
50
50
|
const [isCommandRunning, setIsCommandRunning] = useState(false);
|
|
51
|
-
const [
|
|
51
|
+
const [isCompacting, setIsCompacting] = useState(false);
|
|
52
52
|
const [currentModel, setCurrentModelState] = useState("");
|
|
53
53
|
const [configuredModels, setConfiguredModels] = useState([]);
|
|
54
54
|
const [queuedMessages, setQueuedMessages] = useState([]);
|
|
@@ -129,8 +129,8 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
129
129
|
onLatestTotalTokensChange: (tokens) => {
|
|
130
130
|
throttledSetTokens(tokens);
|
|
131
131
|
},
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
onCompactionStateChange: (isCompactingState) => {
|
|
133
|
+
setIsCompacting(isCompactingState);
|
|
134
134
|
},
|
|
135
135
|
onBackgroundTasksChange: (tasks) => {
|
|
136
136
|
setBackgroundTasks([...tasks]);
|
|
@@ -196,7 +196,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
196
196
|
setIsLoading(agent.isLoading);
|
|
197
197
|
setlatestTotalTokens(agent.latestTotalTokens);
|
|
198
198
|
setIsCommandRunning(agent.isCommandRunning);
|
|
199
|
-
|
|
199
|
+
setIsCompacting(agent.isCompacting);
|
|
200
200
|
setPermissionModeState(agent.getPermissionMode());
|
|
201
201
|
setWorkingDirectory(agent.workingDirectory);
|
|
202
202
|
setCurrentModelState(agent.getModelConfig().model);
|
|
@@ -246,7 +246,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
246
246
|
setIsLoading(false);
|
|
247
247
|
setlatestTotalTokens(0);
|
|
248
248
|
setIsCommandRunning(false);
|
|
249
|
-
|
|
249
|
+
setIsCompacting(false);
|
|
250
250
|
if (currentSessionId) {
|
|
251
251
|
initializeAgent(currentSessionId);
|
|
252
252
|
}
|
|
@@ -477,7 +477,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
|
|
|
477
477
|
configuredModels,
|
|
478
478
|
getConfiguredModels,
|
|
479
479
|
setModel,
|
|
480
|
-
|
|
480
|
+
isCompacting,
|
|
481
481
|
mcpServers,
|
|
482
482
|
connectMcpServer,
|
|
483
483
|
disconnectMcpServer,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usageSummary.d.ts","sourceRoot":"","sources":["../../src/utils/usageSummary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE;QACV,WAAW,EAAE,MAAM,CAAC;QACpB,
|
|
1
|
+
{"version":3,"file":"usageSummary.d.ts","sourceRoot":"","sources":["../../src/utils/usageSummary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE;QACV,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IAEF,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,cAAc,CAAC,EAAE;QACf,yBAAyB,EAAE,MAAM,CAAC;QAClC,yBAAyB,EAAE,MAAM,CAAC;KACnC,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,KAAK,EAAE,GACd,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAyE9B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,KAAK,EAAE,EACf,eAAe,CAAC,EAAE,MAAM,GACvB,IAAI,CAwHN"}
|
|
@@ -15,7 +15,7 @@ export function calculateTokenSummary(usages) {
|
|
|
15
15
|
total_tokens: 0,
|
|
16
16
|
operations: {
|
|
17
17
|
agent_calls: 0,
|
|
18
|
-
|
|
18
|
+
compactions: 0,
|
|
19
19
|
},
|
|
20
20
|
});
|
|
21
21
|
}
|
|
@@ -52,8 +52,8 @@ export function calculateTokenSummary(usages) {
|
|
|
52
52
|
if (usage.operation_type === "agent") {
|
|
53
53
|
summary.operations.agent_calls += 1;
|
|
54
54
|
}
|
|
55
|
-
else if (usage.operation_type === "
|
|
56
|
-
summary.operations.
|
|
55
|
+
else if (usage.operation_type === "compact") {
|
|
56
|
+
summary.operations.compactions += 1;
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
// Convert Map to Record and sort by total tokens
|
|
@@ -83,7 +83,7 @@ export function displayUsageSummary(usages, sessionFilePath) {
|
|
|
83
83
|
let totalCompletion = 0;
|
|
84
84
|
let totalTokens = 0;
|
|
85
85
|
let totalAgentCalls = 0;
|
|
86
|
-
let
|
|
86
|
+
let totalCompactions = 0;
|
|
87
87
|
let totalCacheRead = 0;
|
|
88
88
|
let totalCacheCreation = 0;
|
|
89
89
|
let totalCache5m = 0;
|
|
@@ -121,13 +121,13 @@ export function displayUsageSummary(usages, sessionFilePath) {
|
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
|
-
console.log(` Operations: ${summary.operations.agent_calls} agent calls, ${summary.operations.
|
|
124
|
+
console.log(` Operations: ${summary.operations.agent_calls} agent calls, ${summary.operations.compactions} compactions`);
|
|
125
125
|
console.log();
|
|
126
126
|
totalPrompt += summary.prompt_tokens;
|
|
127
127
|
totalCompletion += summary.completion_tokens;
|
|
128
128
|
totalTokens += summary.total_tokens;
|
|
129
129
|
totalAgentCalls += summary.operations.agent_calls;
|
|
130
|
-
|
|
130
|
+
totalCompactions += summary.operations.compactions;
|
|
131
131
|
}
|
|
132
132
|
if (Object.keys(summaries).length > 1) {
|
|
133
133
|
console.log("Overall Total:");
|
|
@@ -149,6 +149,6 @@ export function displayUsageSummary(usages, sessionFilePath) {
|
|
|
149
149
|
console.log(` 1h cache: ${totalCache1h.toLocaleString()} tokens`);
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
|
-
console.log(` Operations: ${totalAgentCalls} agent calls, ${
|
|
152
|
+
console.log(` Operations: ${totalAgentCalls} agent calls, ${totalCompactions} compactions`);
|
|
153
153
|
}
|
|
154
154
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wave-code",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.3",
|
|
4
4
|
"description": "CLI-based code assistant powered by AI, built with React and Ink",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"semver": "^7.7.4",
|
|
43
43
|
"yargs": "^17.7.2",
|
|
44
44
|
"zod": "^3.23.8",
|
|
45
|
-
"wave-agent-sdk": "0.14.
|
|
45
|
+
"wave-agent-sdk": "0.14.3"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/react": "^19.1.8",
|
|
@@ -16,7 +16,7 @@ export const ChatInterface: React.FC = () => {
|
|
|
16
16
|
messages,
|
|
17
17
|
isLoading,
|
|
18
18
|
isCommandRunning,
|
|
19
|
-
|
|
19
|
+
isCompacting,
|
|
20
20
|
sendMessage,
|
|
21
21
|
abortMessage,
|
|
22
22
|
mcpServers,
|
|
@@ -79,11 +79,11 @@ export const ChatInterface: React.FC = () => {
|
|
|
79
79
|
|
|
80
80
|
{!isConfirmationVisible && !isExpanded && (
|
|
81
81
|
<>
|
|
82
|
-
{(isLoading || isCommandRunning ||
|
|
82
|
+
{(isLoading || isCommandRunning || isCompacting) && (
|
|
83
83
|
<LoadingIndicator
|
|
84
84
|
isLoading={isLoading}
|
|
85
85
|
isCommandRunning={isCommandRunning}
|
|
86
|
-
|
|
86
|
+
isCompacting={isCompacting}
|
|
87
87
|
latestTotalTokens={latestTotalTokens}
|
|
88
88
|
/>
|
|
89
89
|
)}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import React, { useMemo } from "react";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
|
-
import type {
|
|
3
|
+
import type { CompactBlock } from "wave-agent-sdk";
|
|
4
4
|
|
|
5
|
-
interface
|
|
6
|
-
block:
|
|
5
|
+
interface CompactDisplayProps {
|
|
6
|
+
block: CompactBlock;
|
|
7
7
|
isExpanded?: boolean;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export const
|
|
10
|
+
export const CompactDisplay: React.FC<CompactDisplayProps> = ({ block }) => {
|
|
11
11
|
const { content } = block;
|
|
12
12
|
|
|
13
13
|
const { displayContent } = useMemo(() => {
|
|
@@ -21,7 +21,7 @@ export const CompressDisplay: React.FC<CompressDisplayProps> = ({ block }) => {
|
|
|
21
21
|
return (
|
|
22
22
|
<Box flexDirection="column">
|
|
23
23
|
<Box>
|
|
24
|
-
<Text>
|
|
24
|
+
<Text>Compacted Messages</Text>
|
|
25
25
|
</Box>
|
|
26
26
|
|
|
27
27
|
{content && (
|
|
@@ -30,10 +30,23 @@ export const InstalledView: React.FC = () => {
|
|
|
30
30
|
);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
const MAX_VISIBLE_ITEMS = 3;
|
|
34
|
+
const startIndex = Math.max(
|
|
35
|
+
0,
|
|
36
|
+
Math.min(
|
|
37
|
+
selectedIndex - Math.floor(MAX_VISIBLE_ITEMS / 2),
|
|
38
|
+
Math.max(0, installedPlugins.length - MAX_VISIBLE_ITEMS),
|
|
39
|
+
),
|
|
40
|
+
);
|
|
41
|
+
const visiblePlugins = installedPlugins.slice(
|
|
42
|
+
startIndex,
|
|
43
|
+
startIndex + MAX_VISIBLE_ITEMS,
|
|
44
|
+
);
|
|
45
|
+
|
|
33
46
|
return (
|
|
34
47
|
<Box flexDirection="column">
|
|
35
|
-
{
|
|
36
|
-
const isSelected = index === selectedIndex;
|
|
48
|
+
{visiblePlugins.map((plugin, index) => {
|
|
49
|
+
const isSelected = index + startIndex === selectedIndex;
|
|
37
50
|
return (
|
|
38
51
|
<Box
|
|
39
52
|
key={`${plugin.name}@${plugin.marketplace}`}
|
|
@@ -4,19 +4,19 @@ import { Box, Text } from "ink";
|
|
|
4
4
|
export interface LoadingIndicatorProps {
|
|
5
5
|
isLoading?: boolean;
|
|
6
6
|
isCommandRunning?: boolean;
|
|
7
|
-
|
|
7
|
+
isCompacting?: boolean;
|
|
8
8
|
latestTotalTokens?: number;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export const LoadingIndicator = ({
|
|
12
12
|
isLoading = false,
|
|
13
13
|
isCommandRunning = false,
|
|
14
|
-
|
|
14
|
+
isCompacting = false,
|
|
15
15
|
latestTotalTokens = 0,
|
|
16
16
|
}: LoadingIndicatorProps) => {
|
|
17
17
|
return (
|
|
18
18
|
<Box flexDirection="column">
|
|
19
|
-
{isLoading && !
|
|
19
|
+
{isLoading && !isCompacting && (
|
|
20
20
|
<Box>
|
|
21
21
|
<Text color="yellow">✻ AI is thinking... </Text>
|
|
22
22
|
{latestTotalTokens > 0 && (
|
|
@@ -46,8 +46,8 @@ export const LoadingIndicator = ({
|
|
|
46
46
|
</Box>
|
|
47
47
|
)}
|
|
48
48
|
{isCommandRunning && <Text color="blue">✻ Command is running...</Text>}
|
|
49
|
-
{
|
|
50
|
-
<Text color="magenta">✻
|
|
49
|
+
{isCompacting && (
|
|
50
|
+
<Text color="magenta">✻ Compacting message history...</Text>
|
|
51
51
|
)}
|
|
52
52
|
</Box>
|
|
53
53
|
);
|
|
@@ -4,7 +4,7 @@ import type { Message, MessageBlock } from "wave-agent-sdk";
|
|
|
4
4
|
import { MessageSource } from "wave-agent-sdk";
|
|
5
5
|
import { BangDisplay } from "./BangDisplay.js";
|
|
6
6
|
import { ToolDisplay } from "./ToolDisplay.js";
|
|
7
|
-
import {
|
|
7
|
+
import { CompactDisplay } from "./CompactDisplay.js";
|
|
8
8
|
import { ReasoningDisplay } from "./ReasoningDisplay.js";
|
|
9
9
|
import { Markdown } from "./Markdown.js";
|
|
10
10
|
import { TaskNotificationMessage } from "./TaskNotificationMessage.js";
|
|
@@ -79,8 +79,8 @@ export const MessageBlockItem = ({
|
|
|
79
79
|
</Box>
|
|
80
80
|
)}
|
|
81
81
|
|
|
82
|
-
{block.type === "
|
|
83
|
-
<
|
|
82
|
+
{block.type === "compact" && (
|
|
83
|
+
<CompactDisplay block={block} isExpanded={isExpanded} />
|
|
84
84
|
)}
|
|
85
85
|
|
|
86
86
|
{block.type === "reasoning" && (
|
|
@@ -8,6 +8,8 @@ export interface ModelSelectorProps {
|
|
|
8
8
|
onSelectModel: (model: string) => void;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
const MAX_VISIBLE_ITEMS = 5;
|
|
12
|
+
|
|
11
13
|
export const ModelSelector: React.FC<ModelSelectorProps> = ({
|
|
12
14
|
onCancel,
|
|
13
15
|
currentModel,
|
|
@@ -46,6 +48,19 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
|
|
|
46
48
|
}
|
|
47
49
|
});
|
|
48
50
|
|
|
51
|
+
// Calculate visible window
|
|
52
|
+
const startIndex = Math.max(
|
|
53
|
+
0,
|
|
54
|
+
Math.min(
|
|
55
|
+
selectedIndex - Math.floor(MAX_VISIBLE_ITEMS / 2),
|
|
56
|
+
Math.max(0, configuredModels.length - MAX_VISIBLE_ITEMS),
|
|
57
|
+
),
|
|
58
|
+
);
|
|
59
|
+
const visibleModels = configuredModels.slice(
|
|
60
|
+
startIndex,
|
|
61
|
+
startIndex + MAX_VISIBLE_ITEMS,
|
|
62
|
+
);
|
|
63
|
+
|
|
49
64
|
if (configuredModels.length === 0) {
|
|
50
65
|
return (
|
|
51
66
|
<Box
|
|
@@ -84,22 +99,27 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
|
|
|
84
99
|
</Box>
|
|
85
100
|
<Text dimColor>Select a model to use for the current session</Text>
|
|
86
101
|
|
|
87
|
-
{
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
{visibleModels.map((model, index) => {
|
|
103
|
+
const actualIndex = startIndex + index;
|
|
104
|
+
return (
|
|
105
|
+
<Box key={model}>
|
|
106
|
+
<Text
|
|
107
|
+
color={actualIndex === selectedIndex ? "black" : "white"}
|
|
108
|
+
backgroundColor={
|
|
109
|
+
actualIndex === selectedIndex ? "cyan" : undefined
|
|
110
|
+
}
|
|
111
|
+
>
|
|
112
|
+
{actualIndex === selectedIndex ? "▶ " : " "}
|
|
113
|
+
{model}
|
|
114
|
+
{model === currentModel ? (
|
|
115
|
+
<Text color="green"> (current)</Text>
|
|
116
|
+
) : (
|
|
117
|
+
""
|
|
118
|
+
)}
|
|
119
|
+
</Text>
|
|
120
|
+
</Box>
|
|
121
|
+
);
|
|
122
|
+
})}
|
|
103
123
|
|
|
104
124
|
<Box marginTop={1}>
|
|
105
125
|
<Text dimColor>↑/↓ to select · Enter to confirm · Esc to cancel</Text>
|
|
@@ -12,6 +12,8 @@ interface PluginListProps {
|
|
|
12
12
|
onSelect?: (index: number) => void;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
const MAX_VISIBLE_ITEMS = 3;
|
|
16
|
+
|
|
15
17
|
export const PluginList: React.FC<PluginListProps> = ({
|
|
16
18
|
plugins,
|
|
17
19
|
selectedIndex,
|
|
@@ -24,10 +26,22 @@ export const PluginList: React.FC<PluginListProps> = ({
|
|
|
24
26
|
);
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
const startIndex = Math.max(
|
|
30
|
+
0,
|
|
31
|
+
Math.min(
|
|
32
|
+
selectedIndex - Math.floor(MAX_VISIBLE_ITEMS / 2),
|
|
33
|
+
Math.max(0, plugins.length - MAX_VISIBLE_ITEMS),
|
|
34
|
+
),
|
|
35
|
+
);
|
|
36
|
+
const visiblePlugins = plugins.slice(
|
|
37
|
+
startIndex,
|
|
38
|
+
startIndex + MAX_VISIBLE_ITEMS,
|
|
39
|
+
);
|
|
40
|
+
|
|
27
41
|
return (
|
|
28
42
|
<Box flexDirection="column">
|
|
29
|
-
{
|
|
30
|
-
const isSelected = index === selectedIndex;
|
|
43
|
+
{visiblePlugins.map((plugin, index) => {
|
|
44
|
+
const isSelected = index + startIndex === selectedIndex;
|
|
31
45
|
const pluginId = `${plugin.name}@${plugin.marketplace}`;
|
|
32
46
|
|
|
33
47
|
return (
|
package/src/contexts/useChat.tsx
CHANGED
|
@@ -37,7 +37,7 @@ export interface ChatContextType {
|
|
|
37
37
|
messages: Message[];
|
|
38
38
|
isLoading: boolean;
|
|
39
39
|
isCommandRunning: boolean;
|
|
40
|
-
|
|
40
|
+
isCompacting: boolean;
|
|
41
41
|
// Message display state
|
|
42
42
|
isExpanded: boolean;
|
|
43
43
|
isTaskListVisible: boolean;
|
|
@@ -204,7 +204,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
204
204
|
const [latestTotalTokens, setlatestTotalTokens] = useState(0);
|
|
205
205
|
const [sessionId, setSessionId] = useState("");
|
|
206
206
|
const [isCommandRunning, setIsCommandRunning] = useState(false);
|
|
207
|
-
const [
|
|
207
|
+
const [isCompacting, setIsCompacting] = useState(false);
|
|
208
208
|
const [currentModel, setCurrentModelState] = useState("");
|
|
209
209
|
const [configuredModels, setConfiguredModels] = useState<string[]>([]);
|
|
210
210
|
const [queuedMessages, setQueuedMessages] = useState<QueuedMessage[]>([]);
|
|
@@ -352,8 +352,8 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
352
352
|
onLatestTotalTokensChange: (tokens) => {
|
|
353
353
|
throttledSetTokens(tokens);
|
|
354
354
|
},
|
|
355
|
-
|
|
356
|
-
|
|
355
|
+
onCompactionStateChange: (isCompactingState) => {
|
|
356
|
+
setIsCompacting(isCompactingState);
|
|
357
357
|
},
|
|
358
358
|
onBackgroundTasksChange: (tasks) => {
|
|
359
359
|
setBackgroundTasks([...tasks]);
|
|
@@ -431,7 +431,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
431
431
|
setIsLoading(agent.isLoading);
|
|
432
432
|
setlatestTotalTokens(agent.latestTotalTokens);
|
|
433
433
|
setIsCommandRunning(agent.isCommandRunning);
|
|
434
|
-
|
|
434
|
+
setIsCompacting(agent.isCompacting);
|
|
435
435
|
setPermissionModeState(agent.getPermissionMode());
|
|
436
436
|
setWorkingDirectory(agent.workingDirectory);
|
|
437
437
|
setCurrentModelState(agent.getModelConfig().model);
|
|
@@ -484,7 +484,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
484
484
|
setIsLoading(false);
|
|
485
485
|
setlatestTotalTokens(0);
|
|
486
486
|
setIsCommandRunning(false);
|
|
487
|
-
|
|
487
|
+
setIsCompacting(false);
|
|
488
488
|
if (currentSessionId) {
|
|
489
489
|
initializeAgent(currentSessionId);
|
|
490
490
|
}
|
|
@@ -753,7 +753,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
753
753
|
configuredModels,
|
|
754
754
|
getConfiguredModels,
|
|
755
755
|
setModel,
|
|
756
|
-
|
|
756
|
+
isCompacting,
|
|
757
757
|
mcpServers,
|
|
758
758
|
connectMcpServer,
|
|
759
759
|
disconnectMcpServer,
|
|
@@ -10,7 +10,7 @@ export interface TokenSummary {
|
|
|
10
10
|
total_tokens: number;
|
|
11
11
|
operations: {
|
|
12
12
|
agent_calls: number;
|
|
13
|
-
|
|
13
|
+
compactions: number;
|
|
14
14
|
};
|
|
15
15
|
// Cache-related tokens (for Claude models)
|
|
16
16
|
cache_read_input_tokens?: number;
|
|
@@ -42,7 +42,7 @@ export function calculateTokenSummary(
|
|
|
42
42
|
total_tokens: 0,
|
|
43
43
|
operations: {
|
|
44
44
|
agent_calls: 0,
|
|
45
|
-
|
|
45
|
+
compactions: 0,
|
|
46
46
|
},
|
|
47
47
|
});
|
|
48
48
|
}
|
|
@@ -85,8 +85,8 @@ export function calculateTokenSummary(
|
|
|
85
85
|
// Track operation types
|
|
86
86
|
if (usage.operation_type === "agent") {
|
|
87
87
|
summary.operations.agent_calls += 1;
|
|
88
|
-
} else if (usage.operation_type === "
|
|
89
|
-
summary.operations.
|
|
88
|
+
} else if (usage.operation_type === "compact") {
|
|
89
|
+
summary.operations.compactions += 1;
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -129,7 +129,7 @@ export function displayUsageSummary(
|
|
|
129
129
|
let totalCompletion = 0;
|
|
130
130
|
let totalTokens = 0;
|
|
131
131
|
let totalAgentCalls = 0;
|
|
132
|
-
let
|
|
132
|
+
let totalCompactions = 0;
|
|
133
133
|
let totalCacheRead = 0;
|
|
134
134
|
let totalCacheCreation = 0;
|
|
135
135
|
let totalCache5m = 0;
|
|
@@ -190,7 +190,7 @@ export function displayUsageSummary(
|
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
console.log(
|
|
193
|
-
` Operations: ${summary.operations.agent_calls} agent calls, ${summary.operations.
|
|
193
|
+
` Operations: ${summary.operations.agent_calls} agent calls, ${summary.operations.compactions} compactions`,
|
|
194
194
|
);
|
|
195
195
|
console.log();
|
|
196
196
|
|
|
@@ -198,7 +198,7 @@ export function displayUsageSummary(
|
|
|
198
198
|
totalCompletion += summary.completion_tokens;
|
|
199
199
|
totalTokens += summary.total_tokens;
|
|
200
200
|
totalAgentCalls += summary.operations.agent_calls;
|
|
201
|
-
|
|
201
|
+
totalCompactions += summary.operations.compactions;
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
if (Object.keys(summaries).length > 1) {
|
|
@@ -228,7 +228,7 @@ export function displayUsageSummary(
|
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
console.log(
|
|
231
|
-
` Operations: ${totalAgentCalls} agent calls, ${
|
|
231
|
+
` Operations: ${totalAgentCalls} agent calls, ${totalCompactions} compactions`,
|
|
232
232
|
);
|
|
233
233
|
}
|
|
234
234
|
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import type { CompressBlock } from "wave-agent-sdk";
|
|
3
|
-
interface CompressDisplayProps {
|
|
4
|
-
block: CompressBlock;
|
|
5
|
-
isExpanded?: boolean;
|
|
6
|
-
}
|
|
7
|
-
export declare const CompressDisplay: React.FC<CompressDisplayProps>;
|
|
8
|
-
export {};
|
|
9
|
-
//# sourceMappingURL=CompressDisplay.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CompressDisplay.d.ts","sourceRoot":"","sources":["../../src/components/CompressDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,UAAU,oBAAoB;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA+B1D,CAAC"}
|