wave-code 0.12.1 → 0.12.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.
Files changed (42) hide show
  1. package/dist/components/App.d.ts +1 -0
  2. package/dist/components/App.d.ts.map +1 -1
  3. package/dist/components/App.js +5 -2
  4. package/dist/components/BackgroundTaskManager.d.ts.map +1 -1
  5. package/dist/components/BackgroundTaskManager.js +2 -1
  6. package/dist/components/BangDisplay.d.ts.map +1 -1
  7. package/dist/components/BangDisplay.js +2 -14
  8. package/dist/components/ChatInterface.d.ts.map +1 -1
  9. package/dist/components/ChatInterface.js +17 -27
  10. package/dist/components/ConfirmationDetails.d.ts +0 -1
  11. package/dist/components/ConfirmationDetails.d.ts.map +1 -1
  12. package/dist/components/ConfirmationDetails.js +4 -12
  13. package/dist/components/ConfirmationSelector.d.ts +0 -1
  14. package/dist/components/ConfirmationSelector.d.ts.map +1 -1
  15. package/dist/components/ConfirmationSelector.js +4 -12
  16. package/dist/components/MessageList.d.ts +1 -2
  17. package/dist/components/MessageList.d.ts.map +1 -1
  18. package/dist/components/MessageList.js +4 -14
  19. package/dist/components/RewindCommand.d.ts.map +1 -1
  20. package/dist/components/RewindCommand.js +2 -4
  21. package/dist/components/ToolDisplay.d.ts.map +1 -1
  22. package/dist/components/ToolDisplay.js +2 -5
  23. package/dist/contexts/useChat.d.ts.map +1 -1
  24. package/dist/contexts/useChat.js +26 -11
  25. package/dist/utils/logger.d.ts.map +1 -1
  26. package/dist/utils/logger.js +3 -6
  27. package/dist/utils/throttle.d.ts +15 -0
  28. package/dist/utils/throttle.d.ts.map +1 -0
  29. package/dist/utils/throttle.js +55 -0
  30. package/package.json +2 -2
  31. package/src/components/App.tsx +6 -2
  32. package/src/components/BackgroundTaskManager.tsx +3 -6
  33. package/src/components/BangDisplay.tsx +4 -22
  34. package/src/components/ChatInterface.tsx +18 -33
  35. package/src/components/ConfirmationDetails.tsx +2 -15
  36. package/src/components/ConfirmationSelector.tsx +3 -15
  37. package/src/components/MessageList.tsx +3 -16
  38. package/src/components/RewindCommand.tsx +3 -5
  39. package/src/components/ToolDisplay.tsx +2 -5
  40. package/src/contexts/useChat.tsx +33 -10
  41. package/src/utils/logger.ts +3 -7
  42. package/src/utils/throttle.ts +75 -0
@@ -5,6 +5,7 @@ interface AppProps extends BaseAppProps {
5
5
  continueLastSession?: boolean;
6
6
  onExit: (shouldRemove: boolean) => void;
7
7
  }
8
+ export declare const ChatInterfaceWithRemount: React.FC;
8
9
  export declare const App: React.FC<AppProps>;
9
10
  export {};
10
11
  //# sourceMappingURL=App.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAWxE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,UAAU,QAAS,SAAQ,YAAY;IACrC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,MAAM,EAAE,CAAC,YAAY,EAAE,OAAO,KAAK,IAAI,CAAC;CACzC;AAgJD,eAAO,MAAM,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,QAAQ,CAmClC,CAAC"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAWxE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,UAAU,QAAS,SAAQ,YAAY;IACrC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,MAAM,EAAE,CAAC,YAAY,EAAE,OAAO,KAAK,IAAI,CAAC;CACzC;AAiGD,eAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC,EAiD5C,CAAC;AAEF,eAAO,MAAM,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,QAAQ,CAmClC,CAAC"}
@@ -50,11 +50,12 @@ const AppWithProviders = ({ bypassPermissions, permissionMode, pluginDirs, tools
50
50
  }
51
51
  return (_jsx(ChatProvider, { bypassPermissions: bypassPermissions, permissionMode: permissionMode, pluginDirs: pluginDirs, tools: tools, allowedTools: allowedTools, disallowedTools: disallowedTools, workdir: workdir, worktreeSession: worktreeSession, version: version, model: model, children: _jsx(ChatInterfaceWithRemount, {}) }));
52
52
  };
53
- const ChatInterfaceWithRemount = () => {
53
+ export const ChatInterfaceWithRemount = () => {
54
54
  const { stdout } = useStdout();
55
55
  const { isExpanded, rewindId, wasLastDetailsTooTall, sessionId } = useChat();
56
56
  const [remountKey, setRemountKey] = useState(String(isExpanded) + rewindId + wasLastDetailsTooTall);
57
57
  const prevSessionId = useRef(sessionId);
58
+ const isRemountScheduled = useRef(false);
58
59
  useEffect(() => {
59
60
  const newKey = String(isExpanded) +
60
61
  rewindId +
@@ -62,13 +63,15 @@ const ChatInterfaceWithRemount = () => {
62
63
  (prevSessionId.current && sessionId && prevSessionId.current !== sessionId
63
64
  ? sessionId
64
65
  : "");
65
- if (newKey !== remountKey) {
66
+ if (newKey !== remountKey && !isRemountScheduled.current) {
67
+ isRemountScheduled.current = true;
66
68
  const timeout = setTimeout(() => {
67
69
  stdout?.write("\u001b[2J\u001b[3J\u001b[0;0H", (err) => {
68
70
  if (err) {
69
71
  console.error("Failed to clear terminal:", err);
70
72
  }
71
73
  setRemountKey(newKey);
74
+ isRemountScheduled.current = false;
72
75
  });
73
76
  }, 100);
74
77
  return () => clearTimeout(timeout);
@@ -1 +1 @@
1
- {"version":3,"file":"BackgroundTaskManager.d.ts","sourceRoot":"","sources":["../../src/components/BackgroundTaskManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAenD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CA6UtE,CAAC"}
1
+ {"version":3,"file":"BackgroundTaskManager.d.ts","sourceRoot":"","sources":["../../src/components/BackgroundTaskManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAgBnD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CAyUtE,CAAC"}
@@ -2,6 +2,7 @@ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useState, useEffect } from "react";
3
3
  import { Box, Text, useInput } from "ink";
4
4
  import { useChat } from "../contexts/useChat.js";
5
+ import { getLastLines } from "wave-agent-sdk";
5
6
  export const BackgroundTaskManager = ({ onCancel, }) => {
6
7
  const { backgroundTasks, getBackgroundTaskOutput, stopBackgroundTask } = useChat();
7
8
  const [tasks, setTasks] = useState([]);
@@ -102,7 +103,7 @@ export const BackgroundTaskManager = ({ onCancel, }) => {
102
103
  setViewMode("list");
103
104
  return null;
104
105
  }
105
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "cyan", bold: true, children: ["Background Task Details: ", task.id] }) }), _jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Type:" }), " ", task.type] }) }), task.description && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Description:" }), " ", task.description] }) })), _jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Status:" }), " ", task.status, task.exitCode !== undefined && ` (exit code: ${task.exitCode})`] }) }), _jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Started:" }), " ", formatTime(task.startTime), task.runtime !== undefined && (_jsxs(Text, { children: [" ", "| ", _jsx(Text, { color: "blue", children: "Runtime:" }), " ", formatDuration(task.runtime)] }))] }) }), task.outputPath && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Log File:" }), " ", task.outputPath] }) }))] }), detailOutput.stdout && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "green", bold: true, children: "OUTPUT (last 10 lines):" }), _jsx(Box, { borderStyle: "single", borderColor: "green", padding: 1, children: _jsx(Text, { children: detailOutput.stdout.split("\n").slice(-10).join("\n") }) })] })), detailOutput.stderr && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "red", bold: true, children: "ERRORS:" }), _jsx(Box, { borderStyle: "single", borderColor: "red", padding: 1, children: _jsx(Text, { color: "red", children: detailOutput.stderr.split("\n").slice(-10).join("\n") }) })] })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: [task.status === "running" ? "k to stop · " : "", "Esc to go back"] }) })] }));
106
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1, gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: "cyan", bold: true, children: ["Background Task Details: ", task.id] }) }), _jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Type:" }), " ", task.type] }) }), task.description && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Description:" }), " ", task.description] }) })), _jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Status:" }), " ", task.status, task.exitCode !== undefined && ` (exit code: ${task.exitCode})`] }) }), _jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Started:" }), " ", formatTime(task.startTime), task.runtime !== undefined && (_jsxs(Text, { children: [" ", "| ", _jsx(Text, { color: "blue", children: "Runtime:" }), " ", formatDuration(task.runtime)] }))] }) }), task.outputPath && (_jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "Log File:" }), " ", task.outputPath] }) }))] }), detailOutput.stdout && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "green", bold: true, children: "OUTPUT (last 10 lines):" }), _jsx(Box, { borderStyle: "single", borderColor: "green", padding: 1, children: _jsx(Text, { children: getLastLines(detailOutput.stdout, 10) }) })] })), detailOutput.stderr && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "red", bold: true, children: "ERRORS:" }), _jsx(Box, { borderStyle: "single", borderColor: "red", padding: 1, children: _jsx(Text, { color: "red", children: getLastLines(detailOutput.stderr, 10) }) })] })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: [task.status === "running" ? "k to stop · " : "", "Esc to go back"] }) })] }));
106
107
  }
107
108
  if (!backgroundTasks) {
108
109
  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: "Background Tasks" }), _jsx(Text, { children: "Background tasks not available" }), _jsx(Text, { dimColor: true, children: "Press Escape to close" })] }));
@@ -1 +1 @@
1
- {"version":3,"file":"BangDisplay.d.ts","sourceRoot":"","sources":["../../src/components/BangDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,UAAU,gBAAgB;IACxB,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAiDlD,CAAC"}
1
+ {"version":3,"file":"BangDisplay.d.ts","sourceRoot":"","sources":["../../src/components/BangDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD,UAAU,gBAAgB;IACxB,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA8BlD,CAAC"}
@@ -1,17 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useEffect } from "react";
3
2
  import { Box, Text } from "ink";
3
+ import { getLastLines } from "wave-agent-sdk";
4
4
  export const BangDisplay = ({ block, isExpanded = false, }) => {
5
5
  const { command, output, isRunning, exitCode } = block;
6
- const [isOverflowing, setIsOverflowing] = useState(false);
7
6
  const MAX_LINES = 3; // Set maximum display lines
8
- // Detect if content is overflowing
9
- useEffect(() => {
10
- if (output) {
11
- const lines = output.split("\n");
12
- setIsOverflowing(!isExpanded && lines.length > MAX_LINES);
13
- }
14
- }, [output, isExpanded]);
15
7
  const getStatusColor = () => {
16
8
  if (isRunning)
17
9
  return "yellow";
@@ -21,9 +13,5 @@ export const BangDisplay = ({ block, isExpanded = false, }) => {
21
13
  return "red";
22
14
  return "gray"; // Unknown state
23
15
  };
24
- return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: getStatusColor(), children: "! " }), _jsx(Text, { color: "white", children: command })] }), output && (_jsx(Box, { paddingLeft: 2, height: isExpanded
25
- ? undefined
26
- : Math.min(output.split("\n").length, MAX_LINES), overflow: "hidden", children: _jsx(Text, { color: "gray", children: isOverflowing
27
- ? output.split("\n").slice(-MAX_LINES).join("\n")
28
- : output }) }))] }));
16
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: getStatusColor(), children: "! " }), _jsx(Text, { color: "white", children: command })] }), output && (_jsx(Box, { paddingLeft: 2, overflow: "hidden", children: _jsx(Text, { color: "gray", children: isExpanded ? output : getLastLines(output, MAX_LINES) }) }))] }));
29
17
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AActE,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAqKjC,CAAC"}
1
+ {"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyD,MAAM,OAAO,CAAC;AAc9E,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAsJjC,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useCallback, useLayoutEffect } from "react";
3
- import { Box, useStdout } from "ink";
2
+ import { useState, useCallback, useLayoutEffect, useRef } from "react";
3
+ import { Box, useStdout, measureElement } from "ink";
4
4
  import { MessageList } from "./MessageList.js";
5
5
  import { BtwDisplay } from "./BtwDisplay.js";
6
6
  import { InputBox } from "./InputBox.js";
@@ -12,45 +12,35 @@ import { ConfirmationSelector } from "./ConfirmationSelector.js";
12
12
  import { useChat } from "../contexts/useChat.js";
13
13
  export const ChatInterface = () => {
14
14
  const { stdout } = useStdout();
15
- const [detailsHeight, setDetailsHeight] = useState(0);
16
- const [selectorHeight, setSelectorHeight] = useState(0);
17
- const [dynamicBlocksHeight, setDynamicBlocksHeight] = useState(0);
18
15
  const [isConfirmationTooTall, setIsConfirmationTooTall] = useState(false);
19
16
  const { messages, isLoading, isCommandRunning, isCompressing, sendMessage, abortMessage, mcpServers, connectMcpServer, disconnectMcpServer, isExpanded, sessionId, latestTotalTokens, slashCommands, hasSlashCommand, isConfirmationVisible, confirmingTool, handleConfirmationDecision, handleConfirmationCancel: originalHandleConfirmationCancel, setWasLastDetailsTooTall, version, workdir, btwState, } = useChat();
20
- const displayMessages = messages;
21
- const handleDetailsHeightMeasured = useCallback((height) => {
22
- setDetailsHeight(height);
23
- }, []);
24
- const handleSelectorHeightMeasured = useCallback((height) => {
25
- setSelectorHeight(height);
26
- }, []);
27
- const handleDynamicBlocksHeightMeasured = useCallback((height) => {
28
- setDynamicBlocksHeight(height);
29
- }, []);
17
+ const interfaceRef = useRef(null);
30
18
  useLayoutEffect(() => {
31
19
  if (!isConfirmationVisible) {
32
20
  setIsConfirmationTooTall(false);
33
- setDetailsHeight(0);
34
- setSelectorHeight(0);
35
- setDynamicBlocksHeight(0);
36
21
  return;
37
22
  }
38
23
  if (isConfirmationTooTall) {
39
24
  return;
40
25
  }
41
- const terminalHeight = stdout?.rows || 24;
42
- const totalHeight = detailsHeight + selectorHeight + dynamicBlocksHeight;
43
- if (totalHeight > terminalHeight - 3) {
44
- setIsConfirmationTooTall(true);
26
+ if (interfaceRef.current) {
27
+ const { height } = measureElement(interfaceRef.current);
28
+ const terminalHeight = stdout?.rows || 24;
29
+ if (height > terminalHeight - 3) {
30
+ setIsConfirmationTooTall(true);
31
+ }
45
32
  }
46
33
  }, [
47
- detailsHeight,
48
- selectorHeight,
49
- dynamicBlocksHeight,
50
- stdout?.rows,
34
+ messages,
35
+ isLoading,
36
+ isCommandRunning,
37
+ isCompressing,
38
+ isExpanded,
51
39
  isConfirmationVisible,
52
40
  isConfirmationTooTall,
41
+ stdout?.rows,
53
42
  ]);
43
+ const displayMessages = messages;
54
44
  const handleConfirmationCancel = useCallback(() => {
55
45
  if (isConfirmationTooTall) {
56
46
  setWasLastDetailsTooTall((prev) => prev + 1);
@@ -75,5 +65,5 @@ export const ChatInterface = () => {
75
65
  ]);
76
66
  if (!sessionId)
77
67
  return null;
78
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(MessageList, { messages: displayMessages, isExpanded: isExpanded, forceStatic: isConfirmationVisible && isConfirmationTooTall, version: version, workdir: workdir, onDynamicBlocksHeightMeasured: handleDynamicBlocksHeightMeasured }), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [_jsx(BtwDisplay, { btwState: btwState }), (isLoading || isCommandRunning || isCompressing) && (_jsx(LoadingIndicator, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompressing: isCompressing, 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: [_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded, onHeightMeasured: handleDetailsHeightMeasured, isStatic: isConfirmationTooTall }), _jsx(ConfirmationSelector, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: wrappedHandleConfirmationDecision, onCancel: handleConfirmationCancel, onAbort: abortMessage, onHeightMeasured: handleSelectorHeightMeasured })] }))] }));
68
+ return (_jsxs(Box, { ref: interfaceRef, flexDirection: "column", children: [_jsx(MessageList, { messages: displayMessages, isExpanded: isExpanded, forceStatic: isConfirmationVisible && isConfirmationTooTall, version: version, workdir: workdir }), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [_jsx(BtwDisplay, { btwState: btwState }), (isLoading || isCommandRunning || isCompressing) && (_jsx(LoadingIndicator, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompressing: isCompressing, 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: [_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded, isStatic: isConfirmationTooTall }), _jsx(ConfirmationSelector, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: wrappedHandleConfirmationDecision, onCancel: handleConfirmationCancel, onAbort: abortMessage })] }))] }));
79
69
  };
@@ -4,7 +4,6 @@ export interface ConfirmationDetailsProps {
4
4
  toolInput?: Record<string, unknown>;
5
5
  planContent?: string;
6
6
  isExpanded?: boolean;
7
- onHeightMeasured?: (height: number) => void;
8
7
  isStatic?: boolean;
9
8
  }
10
9
  export declare const ConfirmationDetails: React.FC<ConfirmationDetailsProps>;
@@ -1 +1 @@
1
- {"version":3,"file":"ConfirmationDetails.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationDetails.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAsCvD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAyElE,CAAC"}
1
+ {"version":3,"file":"ConfirmationDetails.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationDetails.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAsC1B,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CA6DlE,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import React, { useLayoutEffect, useRef } from "react";
3
- import { Box, Text, useStdout, measureElement, Static } from "ink";
2
+ import React from "react";
3
+ import { Box, Text, Static } from "ink";
4
4
  import { BASH_TOOL_NAME, EDIT_TOOL_NAME, WRITE_TOOL_NAME, EXIT_PLAN_MODE_TOOL_NAME, ASK_USER_QUESTION_TOOL_NAME, } from "wave-agent-sdk";
5
5
  import { DiffDisplay } from "./DiffDisplay.js";
6
6
  import { PlanDisplay } from "./PlanDisplay.js";
@@ -25,18 +25,10 @@ const getActionDescription = (toolName, toolInput) => {
25
25
  return "Execute operation";
26
26
  }
27
27
  };
28
- export const ConfirmationDetails = ({ toolName, toolInput, planContent, isExpanded = false, onHeightMeasured, isStatic = false, }) => {
29
- const { stdout } = useStdout();
30
- const boxRef = useRef(null);
28
+ export const ConfirmationDetails = ({ toolName, toolInput, planContent, isExpanded = false, isStatic = false, }) => {
31
29
  const startLineNumber = toolInput?.startLineNumber ??
32
30
  (toolName === WRITE_TOOL_NAME ? 1 : undefined);
33
- useLayoutEffect(() => {
34
- if (boxRef.current) {
35
- const { height } = measureElement(boxRef.current);
36
- onHeightMeasured?.(height);
37
- }
38
- }, [stdout?.rows, onHeightMeasured, toolInput, isExpanded]);
39
- const content = (_jsxs(Box, { ref: boxRef, flexDirection: "column", borderStyle: "single", borderColor: "yellow", borderBottom: false, borderLeft: false, borderRight: false, children: [_jsxs(Text, { color: "yellow", bold: true, children: ["Tool: ", toolName] }), _jsx(Text, { color: "yellow", children: getActionDescription(toolName, toolInput) }), _jsx(DiffDisplay, { toolName: toolName, parameters: JSON.stringify(toolInput), startLineNumber: startLineNumber }), toolName !== WRITE_TOOL_NAME &&
31
+ const content = (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "yellow", borderBottom: false, borderLeft: false, borderRight: false, children: [_jsxs(Text, { color: "yellow", bold: true, children: ["Tool: ", toolName] }), _jsx(Text, { color: "yellow", children: getActionDescription(toolName, toolInput) }), _jsx(DiffDisplay, { toolName: toolName, parameters: JSON.stringify(toolInput), startLineNumber: startLineNumber }), toolName !== WRITE_TOOL_NAME &&
40
32
  toolName !== EDIT_TOOL_NAME &&
41
33
  toolName !== EXIT_PLAN_MODE_TOOL_NAME &&
42
34
  toolName !== ASK_USER_QUESTION_TOOL_NAME &&
@@ -9,7 +9,6 @@ export interface ConfirmationSelectorProps {
9
9
  onDecision: (decision: PermissionDecision) => void;
10
10
  onCancel: () => void;
11
11
  onAbort: () => void;
12
- onHeightMeasured?: (height: number) => void;
13
12
  }
14
13
  export declare const ConfirmationSelector: React.FC<ConfirmationSelectorProps>;
15
14
  //# sourceMappingURL=ConfirmationSelector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ConfirmationSelector.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuD,MAAM,OAAO,CAAC;AAE5E,OAAO,KAAK,EAAE,kBAAkB,EAAwB,MAAM,gBAAgB,CAAC;AAgB/E,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACnD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AASD,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CA2nBpE,CAAC"}
1
+ {"version":3,"file":"ConfirmationSelector.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAwB,MAAM,gBAAgB,CAAC;AAgB/E,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACnD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AASD,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CAgnBpE,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect, useLayoutEffect, useRef, useState } from "react";
3
- import { Box, Text, useInput, useStdout, measureElement } from "ink";
2
+ import { useEffect, useRef, useState } from "react";
3
+ import { Box, Text, useInput } from "ink";
4
4
  import { BASH_TOOL_NAME, EXIT_PLAN_MODE_TOOL_NAME, ASK_USER_QUESTION_TOOL_NAME, } from "wave-agent-sdk";
5
5
  const getHeaderColor = (header) => {
6
6
  const colors = ["red", "green", "blue", "magenta", "cyan"];
@@ -10,15 +10,7 @@ const getHeaderColor = (header) => {
10
10
  }
11
11
  return colors[Math.abs(hash) % colors.length];
12
12
  };
13
- export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hidePersistentOption, isExpanded = false, onDecision, onCancel, onAbort, onHeightMeasured, }) => {
14
- const { stdout } = useStdout();
15
- const boxRef = useRef(null);
16
- useLayoutEffect(() => {
17
- if (boxRef.current) {
18
- const { height } = measureElement(boxRef.current);
19
- onHeightMeasured?.(height);
20
- }
21
- }, [stdout?.rows, onHeightMeasured, toolName, toolInput, isExpanded]);
13
+ export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hidePersistentOption, isExpanded = false, onDecision, onCancel, onAbort, }) => {
22
14
  const [state, setState] = useState({
23
15
  selectedOption: toolName === EXIT_PLAN_MODE_TOOL_NAME ? "clear" : "allow",
24
16
  alternativeText: "",
@@ -414,7 +406,7 @@ export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hid
414
406
  });
415
407
  const placeholderText = "Type here to tell Wave what to change";
416
408
  const showPlaceholder = state.selectedOption === "alternative" && !state.hasUserInput;
417
- return (_jsxs(Box, { ref: boxRef, flexDirection: "column", children: [toolName === ASK_USER_QUESTION_TOOL_NAME &&
409
+ return (_jsxs(Box, { flexDirection: "column", children: [toolName === ASK_USER_QUESTION_TOOL_NAME &&
418
410
  currentQuestion &&
419
411
  !isExpanded && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: getHeaderColor(currentQuestion.header), bold: true, children: currentQuestion.header.slice(0, 12).toUpperCase() }), _jsx(Box, { marginLeft: 1, children: _jsx(Text, { bold: true, children: currentQuestion.question }) })] }), _jsx(Box, { flexDirection: "column", children: [...currentQuestion.options, { label: "Other" }].map((option, index) => {
420
412
  const isSelected = questionState.selectedOptionIndex === index;
@@ -6,7 +6,6 @@ export interface MessageListProps {
6
6
  forceStatic?: boolean;
7
7
  version?: string;
8
8
  workdir?: string;
9
- onDynamicBlocksHeightMeasured?: (height: number) => void;
10
9
  }
11
- export declare const MessageList: React.MemoExoticComponent<({ messages, isExpanded, forceStatic, version, workdir, onDynamicBlocksHeightMeasured, }: MessageListProps) => import("react/jsx-runtime").JSX.Element>;
10
+ export declare const MessageList: React.MemoExoticComponent<({ messages, isExpanded, forceStatic, version, workdir, }: MessageListProps) => import("react/jsx-runtime").JSX.Element>;
12
11
  //# sourceMappingURL=MessageList.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAGvD,OAAO,KAAK,EAAE,OAAO,EAAgB,MAAM,gBAAgB,CAAC;AAG5D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6BAA6B,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1D;AAED,eAAO,MAAM,WAAW,sHAQnB,gBAAgB,6CA4HpB,CAAC"}
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,OAAO,EAAgB,MAAM,gBAAgB,CAAC;AAG5D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,WAAW,uFAOnB,gBAAgB,6CAiHpB,CAAC"}
@@ -1,9 +1,9 @@
1
1
  import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import React, { useLayoutEffect, useRef } from "react";
2
+ import React from "react";
3
3
  import os from "os";
4
- import { Box, Text, Static, measureElement } from "ink";
4
+ import { Box, Text, Static } from "ink";
5
5
  import { MessageBlockItem } from "./MessageBlockItem.js";
6
- export const MessageList = React.memo(({ messages, isExpanded = false, forceStatic = false, version, workdir, onDynamicBlocksHeightMeasured, }) => {
6
+ export const MessageList = React.memo(({ messages, isExpanded = false, forceStatic = false, version, workdir, }) => {
7
7
  const welcomeMessage = (_jsxs(Box, { flexDirection: "column", paddingTop: 1, children: [_jsxs(Text, { color: "gray", children: ["WAVE", version ? ` v${version}` : ""] }), workdir && (_jsx(Text, { color: "gray", wrap: "truncate-middle", children: workdir.replace(os.homedir(), "~") }))] }));
8
8
  // Limit messages to prevent long rendering times
9
9
  const maxMessages = 10;
@@ -35,16 +35,6 @@ export const MessageList = React.memo(({ messages, isExpanded = false, forceStat
35
35
  });
36
36
  const staticBlocks = blocksWithStatus.filter((b) => !b.isDynamic);
37
37
  const dynamicBlocks = blocksWithStatus.filter((b) => b.isDynamic);
38
- const dynamicBlocksRef = useRef(null);
39
- useLayoutEffect(() => {
40
- if (dynamicBlocksRef.current) {
41
- const { height } = measureElement(dynamicBlocksRef.current);
42
- onDynamicBlocksHeightMeasured?.(height);
43
- }
44
- else {
45
- onDynamicBlocksHeightMeasured?.(0);
46
- }
47
- }, [dynamicBlocks, isExpanded, onDynamicBlocksHeightMeasured]);
48
38
  const staticItems = [
49
39
  {
50
40
  isWelcome: true,
@@ -64,7 +54,7 @@ export const MessageList = React.memo(({ messages, isExpanded = false, forceStat
64
54
  return null;
65
55
  }
66
56
  return (_jsx(MessageBlockItem, { block: item.block, message: item.message, isExpanded: isExpanded, paddingTop: 1 }, item.key));
67
- } })), dynamicBlocks.length > 0 && (_jsx(Box, { ref: dynamicBlocksRef, flexDirection: "column", children: dynamicBlocks.map((item) => (_jsx(MessageBlockItem, { block: item.block, message: item.message, isExpanded: isExpanded, paddingTop: 1 }, item.key))) }))] }));
57
+ } })), dynamicBlocks.length > 0 && (_jsx(Box, { flexDirection: "column", children: dynamicBlocks.map((item) => (_jsx(MessageBlockItem, { block: item.block, message: item.message, isExpanded: isExpanded, paddingTop: 1 }, item.key))) }))] }));
68
58
  });
69
59
  // Add display name for debugging
70
60
  MessageList.displayName = "MessageList";
@@ -1 +1 @@
1
- {"version":3,"file":"RewindCommand.d.ts","sourceRoot":"","sources":["../../src/components/RewindCommand.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,OAAO,EAAa,MAAM,gBAAgB,CAAC;AAEzD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,OAAO,CAAC;QACnC,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,UAAU,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC,CAAC;CACJ;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAwJtD,CAAC"}
1
+ {"version":3,"file":"RewindCommand.d.ts","sourceRoot":"","sources":["../../src/components/RewindCommand.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAG9C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,OAAO,CAAC;QACnC,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,UAAU,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC,CAAC;CACJ;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAqJtD,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React, { useState } from "react";
3
3
  import { Box, Text, useInput } from "ink";
4
+ import { getMessageContent } from "wave-agent-sdk";
4
5
  export const RewindCommand = ({ messages: initialMessages, onSelect, onCancel, getFullMessageThread, }) => {
5
6
  const [messages, setMessages] = useState(initialMessages);
6
7
  const [isLoading, setIsLoading] = useState(!!getFullMessageThread);
@@ -54,10 +55,7 @@ export const RewindCommand = ({ messages: initialMessages, onSelect, onCancel, g
54
55
  return (_jsxs(Box, { flexDirection: "column", paddingX: 1, gap: 1, borderStyle: "single", borderColor: "cyan", borderLeft: false, borderRight: false, children: [_jsx(Box, { children: _jsx(Text, { color: "cyan", bold: true, children: "Rewind: Select a message to revert to" }) }), _jsx(Box, { flexDirection: "column", children: visibleCheckpoints.map((checkpoint, index) => {
55
56
  const actualIndex = startIndex + index;
56
57
  const isSelected = actualIndex === selectedIndex;
57
- const content = checkpoint.msg.blocks
58
- .filter((b) => b.type === "text")
59
- .map((b) => b.content)
60
- .join(" ")
58
+ const content = getMessageContent(checkpoint.msg)
61
59
  .replace(/\n/g, "\\n")
62
60
  .substring(0, 60);
63
61
  return (_jsx(Box, { children: _jsxs(Text, { color: isSelected ? "black" : "white", backgroundColor: isSelected ? "cyan" : undefined, children: [isSelected ? "▶ " : " ", "[", checkpoint.index, "]", " ", content || "(No text content)", actualIndex === checkpoints.length - 1 ? " (Latest)" : ""] }) }, checkpoint.index));
@@ -1 +1 @@
1
- {"version":3,"file":"ToolDisplay.d.ts","sourceRoot":"","sources":["../../src/components/ToolDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD,UAAU,gBAAgB;IACxB,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAmIlD,CAAC"}
1
+ {"version":3,"file":"ToolDisplay.d.ts","sourceRoot":"","sources":["../../src/components/ToolDisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAIhD,UAAU,gBAAgB;IACxB,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA+HlD,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Text } from "ink";
3
+ import { getLastLines } from "wave-agent-sdk";
3
4
  import { DiffDisplay } from "./DiffDisplay.js";
4
5
  export const ToolDisplay = ({ block, isExpanded = false, }) => {
5
6
  const { parameters, result, compactParams, stage, success, error, name } = block;
@@ -31,11 +32,7 @@ export const ToolDisplay = ({ block, isExpanded = false, }) => {
31
32
  }
32
33
  // If no shortResult but has result, return last 5 lines
33
34
  if (block.result) {
34
- const lines = block.result.split("\n");
35
- if (lines.length > 5) {
36
- return lines.slice(-5).join("\n");
37
- }
38
- return block.result;
35
+ return getLastLines(block.result, 5);
39
36
  }
40
37
  return null;
41
38
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACf,MAAM,gBAAgB,CAAC;AAWxB,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,aAAa,EAAE,OAAO,CAAC;IAEvB,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,oBAAoB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,cAAc,EAAE,KAAK,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACnD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACtC,CAAC,CAAC;IAEH,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,CACX,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,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAE1B,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,EAAE,MAAM,MAAM,EAAE,CAAC;IACpC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,gBAAgB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAE9D,eAAe,EAAE,cAAc,EAAE,CAAC;IAElC,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,uBAAuB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK;QAC3C,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,IAAI,CAAC;IACT,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAEhD,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAEhD,cAAc,EAAE,cAAc,CAAC;IAC/B,iBAAiB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,kBAAkB,EAAE,OAAO,CAAC;IAE5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,cAAc,CAAC,EAAE;QACf,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,gBAAgB,EAAE,CAChB,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,eAAe,CAAC,EAAE,MAAM,EACxB,oBAAoB,CAAC,EAAE,OAAO,EAC9B,WAAW,CAAC,EAAE,MAAM,KACjB,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACjC,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,0BAA0B,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACnE,wBAAwB,EAAE,MAAM,IAAI,CAAC;IAErC,qBAAqB,EAAE,MAAM,IAAI,CAAC;IAElC,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,oBAAoB,EAAE,MAAM,OAAO,CAAC;QAClC,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,UAAU,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC,CAAC;IACH,qBAAqB,EAAE,MAAM,CAAC;IAC9B,wBAAwB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IAEvE,gBAAgB,EAAE,MAAM,OAAO,gBAAgB,EAAE,aAAa,CAAC;IAC/D,cAAc,EAAE,MAAM,OAAO,gBAAgB,EAAE,WAAW,CAAC;IAC3D,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,6BAA6B,EAAE,QAAQ,CAAC;IACzD,WAAW,EAAE,CACX,OAAO,EAAE,OAAO,CAAC,OAAO,6BAA6B,EAAE,QAAQ,CAAC,KAC7D,IAAI,CAAC;CACX;AAID,eAAO,MAAM,OAAO,uBAMnB,CAAC;AAEF,MAAM,WAAW,iBAAkB,SAAQ,YAAY;IACrD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAwmBpD,CAAC"}
1
+ {"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { createContext, useContext, useCallback, useRef, useEffect, useState, } from "react";
2
+ import { createContext, useContext, useCallback, useRef, useEffect, useState, useMemo, } from "react";
3
3
  import { useInput } from "ink";
4
4
  import { useAppConfig } from "./useAppConfig.js";
5
- import { Agent, OPERATION_CANCELLED_BY_USER, } from "wave-agent-sdk";
5
+ import { Agent, OPERATION_CANCELLED_BY_USER, cloneMessage, } from "wave-agent-sdk";
6
6
  import { logger } from "../utils/logger.js";
7
+ import { throttle } from "../utils/throttle.js";
7
8
  import { displayUsageSummary } from "../utils/usageSummary.js";
8
9
  import { expandLongTextPlaceholders } from "../managers/inputHandlers.js";
9
10
  const ChatContext = createContext(null);
@@ -19,13 +20,25 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
19
20
  // Message Display State
20
21
  const [isExpanded, setIsExpanded] = useState(false);
21
22
  const isExpandedRef = useRef(isExpanded);
22
- useEffect(() => {
23
- isExpandedRef.current = isExpanded;
24
- }, [isExpanded]);
25
23
  const [isTaskListVisible, setIsTaskListVisible] = useState(true);
26
24
  const [queuedMessages, setQueuedMessages] = useState([]);
27
- // AI State
28
25
  const [messages, setMessages] = useState([]);
26
+ const throttledSetMessages = useMemo(() => throttle(() => {
27
+ if (!isExpandedRef.current && agentRef.current) {
28
+ setMessages([...agentRef.current.messages]);
29
+ }
30
+ }, 300), []);
31
+ useEffect(() => {
32
+ isExpandedRef.current = isExpanded;
33
+ if (isExpanded) {
34
+ throttledSetMessages.cancel();
35
+ }
36
+ }, [isExpanded, throttledSetMessages]);
37
+ useEffect(() => {
38
+ return () => {
39
+ throttledSetMessages.cancel();
40
+ };
41
+ }, [throttledSetMessages]);
29
42
  const [isLoading, setIsLoading] = useState(false);
30
43
  const [latestTotalTokens, setlatestTotalTokens] = useState(0);
31
44
  const [sessionId, setSessionId] = useState("");
@@ -93,9 +106,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
93
106
  const initializeAgent = async () => {
94
107
  const callbacks = {
95
108
  onMessagesChange: () => {
96
- if (!isExpandedRef.current && agentRef.current) {
97
- setMessages([...agentRef.current.messages]);
98
- }
109
+ throttledSetMessages();
99
110
  },
100
111
  onServersChange: (servers) => {
101
112
  setMcpServers([...servers]);
@@ -196,6 +207,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
196
207
  worktreeSession,
197
208
  model,
198
209
  initialPermissionMode,
210
+ throttledSetMessages,
199
211
  ]);
200
212
  // Cleanup on unmount
201
213
  useEffect(() => {
@@ -240,7 +252,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
240
252
  if (command) {
241
253
  setIsCommandRunning(true);
242
254
  try {
243
- await agentRef.current?.executeBashCommand(command);
255
+ await agentRef.current?.bang(command);
244
256
  }
245
257
  finally {
246
258
  setIsCommandRunning(false);
@@ -404,14 +416,17 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
404
416
  // Clear terminal screen when expanded state changes
405
417
  setIsExpanded((prev) => {
406
418
  const newExpanded = !prev;
419
+ isExpandedRef.current = newExpanded;
407
420
  if (newExpanded) {
408
421
  // Transitioning to EXPANDED: Freeze the current view
422
+ // Cancel any pending throttled updates to avoid overwriting the frozen state
423
+ throttledSetMessages.cancel();
409
424
  // Deep copy the last message to ensure it doesn't update if the agent is still writing to it
410
425
  setMessages((currentMessages) => {
411
426
  if (currentMessages.length === 0)
412
427
  return currentMessages;
413
428
  const lastMessage = currentMessages[currentMessages.length - 1];
414
- const frozenLastMessage = JSON.parse(JSON.stringify(lastMessage));
429
+ const frozenLastMessage = cloneMessage(lastMessage);
415
430
  return [...currentMessages.slice(0, -1), frozenLastMessage];
416
431
  });
417
432
  }
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAUH;;GAEG;AACH,oBAAY,QAAQ;IAClB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;CACV;AAsBD;;GAEG;AACH,UAAU,SAAS;IACjB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;CAC7B;AAiID;;GAEG;AACH,eAAO,MAAM,MAAM;IACjB;;OAEG;qBACc,OAAO,EAAE,KAAG,IAAI;IAIjC;;OAEG;oBACa,OAAO,EAAE,KAAG,IAAI;IAIhC;;OAEG;oBACa,OAAO,EAAE,KAAG,IAAI;IAIhC;;OAEG;qBACc,OAAO,EAAE,KAAG,IAAI;CAGlC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,QAAO,SAE/B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,QAAO,MAE7B,CAAC;AAEF;;GAEG;AACH,UAAU,gBAAgB;IACxB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;CACnB;AAqDD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GACtB,eAAe,OAAO,CAAC,gBAAgB,CAAC,KACvC,OAAO,CAAC,IAAI,CAiBd,CAAC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH;;GAEG;AACH,oBAAY,QAAQ;IAClB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;CACV;AAsBD;;GAEG;AACH,UAAU,SAAS;IACjB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;CAC7B;AAiID;;GAEG;AACH,eAAO,MAAM,MAAM;IACjB;;OAEG;qBACc,OAAO,EAAE,KAAG,IAAI;IAIjC;;OAEG;oBACa,OAAO,EAAE,KAAG,IAAI;IAIhC;;OAEG;oBACa,OAAO,EAAE,KAAG,IAAI;IAIhC;;OAEG;qBACc,OAAO,EAAE,KAAG,IAAI;CAGlC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,QAAO,SAE/B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,QAAO,MAE7B,CAAC;AAEF;;GAEG;AACH,UAAU,gBAAgB;IACxB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;CACnB;AAgDD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GACtB,eAAe,OAAO,CAAC,gBAAgB,CAAC,KACvC,OAAO,CAAC,IAAI,CAiBd,CAAC"}
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import * as fs from "fs";
11
11
  import { Chalk } from "chalk";
12
+ import { getLastLines } from "wave-agent-sdk";
12
13
  import { LOG_FILE, DATA_DIRECTORY } from "./constants.js";
13
14
  const chalk = new Chalk({ level: 3 });
14
15
  const logFile = process.env.LOG_FILE || LOG_FILE;
@@ -225,15 +226,11 @@ const truncateLogFileIfNeeded = (config) => {
225
226
  // If file size exceeds limit, truncate file
226
227
  if (stats.size > config.maxFileSize) {
227
228
  const content = fs.readFileSync(logFile, "utf8");
228
- const lines = content.split("\n");
229
- // Keep the last specified number of lines
230
- const keepLines = Math.min(config.keepLines, lines.length);
231
- const truncatedContent = lines.slice(-keepLines).join("\n");
229
+ const truncatedContent = getLastLines(content, config.keepLines);
232
230
  // Write truncated content
233
231
  fs.writeFileSync(logFile, truncatedContent);
234
232
  // Record truncation operation
235
- const removedLines = lines.length - keepLines;
236
- logger.debug(`Log file truncated: removed ${removedLines} lines, kept last ${keepLines} lines`);
233
+ logger.debug(`Log file truncated: file size ${stats.size} exceeded limit ${config.maxFileSize}, kept last ${config.keepLines} lines`);
237
234
  }
238
235
  }
239
236
  catch (error) {
@@ -0,0 +1,15 @@
1
+ export interface ThrottleOptions {
2
+ leading?: boolean;
3
+ trailing?: boolean;
4
+ }
5
+ export interface ThrottledFunction<T extends (...args: unknown[]) => void> {
6
+ (...args: Parameters<T>): void;
7
+ cancel: () => void;
8
+ flush: () => void;
9
+ }
10
+ /**
11
+ * Creates a throttled function that only invokes `func` at most once per
12
+ * every `wait` milliseconds.
13
+ */
14
+ export declare function throttle<T extends (...args: unknown[]) => void>(func: T, wait: number, options?: ThrottleOptions): ThrottledFunction<T>;
15
+ //# sourceMappingURL=throttle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../../src/utils/throttle.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;IACvE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC/B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,EAC7D,IAAI,EAAE,CAAC,EACP,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,eAAmD,GAC3D,iBAAiB,CAAC,CAAC,CAAC,CAuDtB"}