wave-code 0.9.0 → 0.9.1

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.
@@ -4,6 +4,7 @@ export { type FileItem } from "wave-agent-sdk";
4
4
  export interface FileSelectorProps {
5
5
  files: FileItem[];
6
6
  searchQuery: string;
7
+ isLoading?: boolean;
7
8
  onSelect: (filePath: string) => void;
8
9
  onCancel: () => void;
9
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FileSelector.d.ts","sourceRoot":"","sources":["../../src/components/FileSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAqHpD,CAAC"}
1
+ {"version":3,"file":"FileSelector.d.ts","sourceRoot":"","sources":["../../src/components/FileSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA8HpD,CAAC"}
@@ -1,7 +1,7 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
3
  import { Box, Text, useInput } from "ink";
4
- export const FileSelector = ({ files, searchQuery, onSelect, onCancel, }) => {
4
+ export const FileSelector = ({ files, searchQuery, isLoading = false, onSelect, onCancel, }) => {
5
5
  const [selectedIndex, setSelectedIndex] = useState(0);
6
6
  useInput((input, key) => {
7
7
  if (key.return || key.tab) {
@@ -24,7 +24,7 @@ export const FileSelector = ({ files, searchQuery, onSelect, onCancel, }) => {
24
24
  }
25
25
  });
26
26
  if (files.length === 0) {
27
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: "yellow", borderBottom: false, borderLeft: false, borderRight: false, children: [_jsxs(Text, { color: "yellow", children: ["No files found for \"", searchQuery, "\""] }), _jsx(Text, { dimColor: true, children: "Press Escape to cancel" })] }));
27
+ return (_jsx(Box, { flexDirection: "column", borderStyle: "single", borderColor: isLoading ? "cyan" : "yellow", borderBottom: false, borderLeft: false, borderRight: false, children: isLoading ? (_jsx(Text, { color: "cyan", bold: true, children: "Select File/Directory..." })) : (_jsxs(_Fragment, { children: [_jsxs(Text, { color: "yellow", children: ["No files found for \"", searchQuery, "\""] }), _jsx(Text, { dimColor: true, children: "Press Escape to cancel" })] })) }));
28
28
  }
29
29
  const maxDisplay = 10;
30
30
  // Calculate display window start and end positions
@@ -1,7 +1,8 @@
1
1
  import React from "react";
2
+ import { type PromptEntry } from "wave-agent-sdk";
2
3
  export interface HistorySearchProps {
3
4
  searchQuery: string;
4
- onSelect: (prompt: string) => void;
5
+ onSelect: (entry: PromptEntry) => void;
5
6
  onCancel: () => void;
6
7
  }
7
8
  export declare const HistorySearch: React.FC<HistorySearchProps>;
@@ -1 +1 @@
1
- {"version":3,"file":"HistorySearch.d.ts","sourceRoot":"","sources":["../../src/components/HistorySearch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAkKtD,CAAC"}
1
+ {"version":3,"file":"HistorySearch.d.ts","sourceRoot":"","sources":["../../src/components/HistorySearch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,EAAwB,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAExE,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACvC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAkKtD,CAAC"}
@@ -27,7 +27,7 @@ export const HistorySearch = ({ searchQuery, onSelect, onCancel, }) => {
27
27
  if (key.return) {
28
28
  if (entriesRef.current.length > 0 &&
29
29
  selectedIndexRef.current < entriesRef.current.length) {
30
- onSelect(entriesRef.current[selectedIndexRef.current].prompt);
30
+ onSelect(entriesRef.current[selectedIndexRef.current]);
31
31
  }
32
32
  return;
33
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAczC,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,KAC/C,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;CAClD;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAkO5C,CAAC"}
1
+ {"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../src/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAczC,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,KAC/C,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;CAClD;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAsO5C,CAAC"}
@@ -15,13 +15,13 @@ import { useChat } from "../contexts/useChat.js";
15
15
  export const INPUT_PLACEHOLDER_TEXT = "Type your message (use /help for more info)...";
16
16
  export const INPUT_PLACEHOLDER_TEXT_PREFIX = INPUT_PLACEHOLDER_TEXT.substring(0, 10);
17
17
  export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mcpServers = [], connectMcpServer = async () => false, disconnectMcpServer = async () => false, slashCommands = [], hasSlashCommand = () => false, }) => {
18
- const { permissionMode: chatPermissionMode, setPermissionMode: setChatPermissionMode, handleRewindSelect, backgroundCurrentTask, messages, getFullMessageThread, clearMessages, } = useChat();
18
+ const { permissionMode: chatPermissionMode, setPermissionMode: setChatPermissionMode, handleRewindSelect, backgroundCurrentTask, messages, getFullMessageThread, clearMessages, sessionId, } = useChat();
19
19
  // Input manager with all input state and functionality (including images)
20
20
  const { inputText, cursorPosition,
21
21
  // Image management
22
22
  attachedImages, clearImages,
23
23
  // File selector
24
- showFileSelector, filteredFiles, fileSearchQuery: searchQuery, handleFileSelect, handleCancelFileSelect,
24
+ showFileSelector, filteredFiles, fileSearchQuery: searchQuery, isFileSearching, handleFileSelect, handleCancelFileSelect,
25
25
  // Command selector
26
26
  showCommandSelector, commandSearchQuery, handleCommandSelect, handleCommandInsert, handleCancelCommandSelect, handleHistorySearchSelect, handleCancelHistorySearch,
27
27
  // History search
@@ -40,6 +40,7 @@ export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mc
40
40
  onBackgroundCurrentTask: backgroundCurrentTask,
41
41
  onPermissionModeChange: setChatPermissionMode,
42
42
  onClearMessages: clearMessages,
43
+ sessionId,
43
44
  });
44
45
  // Sync permission mode from useChat to InputManager
45
46
  useEffect(() => {
@@ -84,7 +85,7 @@ export const InputBox = ({ sendMessage = () => { }, abortMessage = () => { }, mc
84
85
  if (showStatusCommand) {
85
86
  return _jsx(StatusCommand, { onCancel: () => setShowStatusCommand(false) });
86
87
  }
87
- return (_jsxs(Box, { flexDirection: "column", children: [showFileSelector && (_jsx(FileSelector, { files: filteredFiles, searchQuery: searchQuery, 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 ||
88
+ return (_jsxs(Box, { flexDirection: "column", children: [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 ||
88
89
  showMcpManager ||
89
90
  showRewindManager ||
90
91
  showHelp ||
@@ -1,12 +1,13 @@
1
1
  import { Key } from "ink";
2
2
  import { InputManagerCallbacks } from "../managers/inputReducer.js";
3
- import { PermissionMode } from "wave-agent-sdk";
3
+ import { PermissionMode, PromptEntry } from "wave-agent-sdk";
4
4
  export declare const useInputManager: (callbacks?: Partial<InputManagerCallbacks>) => {
5
5
  inputText: string;
6
6
  cursorPosition: number;
7
7
  showFileSelector: boolean;
8
8
  filteredFiles: import("wave-agent-sdk").FileItem[];
9
9
  fileSearchQuery: string;
10
+ isFileSearching: boolean;
10
11
  atPosition: number;
11
12
  showCommandSelector: boolean;
12
13
  commandSearchQuery: string;
@@ -46,7 +47,7 @@ export declare const useInputManager: (callbacks?: Partial<InputManagerCallbacks
46
47
  handleCancelCommandSelect: () => void;
47
48
  updateCommandSearchQuery: (query: string) => void;
48
49
  checkForSlashDeletion: (cursorPos: number) => boolean;
49
- handleHistorySearchSelect: (prompt: string) => void;
50
+ handleHistorySearchSelect: (entry: PromptEntry) => void;
50
51
  handleCancelHistorySearch: () => void;
51
52
  processSelectorInput: (char: string) => void;
52
53
  setShowBackgroundTaskManager: (show: boolean) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"useInputManager.d.ts","sourceRoot":"","sources":["../../src/hooks/useInputManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAGL,qBAAqB,EACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAkC,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGhF,eAAO,MAAM,eAAe,GAC1B,YAAW,OAAO,CAAC,qBAAqB,CAAM;;;;;;;;;;;;;;;;;;;;+BAsIA,MAAM;;;;;qCAoBA,MAAM;iCAIV,MAAM;;;;;mCAaJ,MAAM;oCAIL,MAAM;wCAIF,MAAM;mCAIX,MAAM;;;;mCASN,MAAM;;;;;sCAkCH,MAAM;uCAIL,MAAM;wCAQL,MAAM;;iCAUb,MAAM;yCAYE,OAAO;8BAIlB,OAAO;iCAIJ,OAAO;wBAIhB,OAAO;iCAIE,OAAO;8BAIV,cAAc;0BAKlB,MAAM,YAAY,MAAM;2BAIvB,MAAM;;;8BAYH,MAAM;mCAW/B,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;uCAYnB,MAAM;;yBAajD,MAAM,OACR,GAAG,kBACQ,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,gBACvD,MAAM,IAAI;yBAxFY,MAAM;kCAIG,MAAM;;CAmLxD,CAAC"}
1
+ {"version":3,"file":"useInputManager.d.ts","sourceRoot":"","sources":["../../src/hooks/useInputManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAGL,qBAAqB,EACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,cAAc,EACd,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAGxB,eAAO,MAAM,eAAe,GAC1B,YAAW,OAAO,CAAC,qBAAqB,CAAM;;;;;;;;;;;;;;;;;;;;;+BAsIA,MAAM;;;;;qCAoBA,MAAM;iCAIV,MAAM;;;;;mCAaJ,MAAM;oCAIL,MAAM;wCAIF,MAAM;mCAIX,MAAM;;;;mCASN,MAAM;;;;;sCAkCH,MAAM;uCAIL,MAAM;uCAQN,WAAW;;iCAQjB,MAAM;yCAYE,OAAO;8BAIlB,OAAO;iCAIJ,OAAO;wBAIhB,OAAO;iCAIE,OAAO;8BAIV,cAAc;0BAKlB,MAAM,YAAY,MAAM;2BAIvB,MAAM;;;8BAYH,MAAM;mCAW/B,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;uCAYnB,MAAM;;yBAajD,MAAM,OACR,GAAG,kBACQ,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,gBACvD,MAAM,IAAI;yBAxFY,MAAM;kCAIG,MAAM;;CAoLxD,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { useEffect, useReducer, useCallback, useRef } from "react";
2
2
  import { inputReducer, initialState, } from "../managers/inputReducer.js";
3
- import { searchFiles as searchFilesUtil } from "wave-agent-sdk";
3
+ import { searchFiles as searchFilesUtil, } from "wave-agent-sdk";
4
4
  import * as handlers from "../managers/inputHandlers.js";
5
5
  export const useInputManager = (callbacks = {}) => {
6
6
  const [state, dispatch] = useReducer(inputReducer, initialState);
@@ -25,7 +25,9 @@ export const useInputManager = (callbacks = {}) => {
25
25
  // Handle debounced file search
26
26
  useEffect(() => {
27
27
  if (state.showFileSelector) {
28
- const debounceDelay = parseInt(process.env.FILE_SELECTOR_DEBOUNCE_MS || "300", 10);
28
+ const debounceDelay = state.fileSearchQuery === ""
29
+ ? 0
30
+ : parseInt(process.env.FILE_SELECTOR_DEBOUNCE_MS || "300", 10);
29
31
  const timer = setTimeout(async () => {
30
32
  try {
31
33
  const fileItems = await searchFilesUtil(state.fileSearchQuery);
@@ -47,7 +49,7 @@ export const useInputManager = (callbacks = {}) => {
47
49
  const processedInput = stateRef.current.pasteBuffer.replace(/\r/g, "\n");
48
50
  dispatch({ type: "COMPRESS_AND_INSERT_TEXT", payload: processedInput });
49
51
  dispatch({ type: "END_PASTE" });
50
- callbacksRef.current.onResetHistoryNavigation?.();
52
+ dispatch({ type: "RESET_HISTORY_NAVIGATION" });
51
53
  }, pasteDebounceDelay);
52
54
  return () => clearTimeout(timer);
53
55
  }
@@ -161,10 +163,8 @@ export const useInputManager = (callbacks = {}) => {
161
163
  const checkForSlashDeletion = useCallback((cursorPos) => {
162
164
  return handlers.checkForSlashDeletion(stateRef.current, dispatch, cursorPos);
163
165
  }, []);
164
- const handleHistorySearchSelect = useCallback((prompt) => {
165
- dispatch({ type: "SET_INPUT_TEXT", payload: prompt });
166
- dispatch({ type: "SET_CURSOR_POSITION", payload: prompt.length });
167
- dispatch({ type: "CANCEL_HISTORY_SEARCH" });
166
+ const handleHistorySearchSelect = useCallback((entry) => {
167
+ dispatch({ type: "SELECT_HISTORY_ENTRY", payload: entry });
168
168
  }, []);
169
169
  const handleCancelHistorySearch = useCallback(() => {
170
170
  dispatch({ type: "CANCEL_HISTORY_SEARCH" });
@@ -231,6 +231,7 @@ export const useInputManager = (callbacks = {}) => {
231
231
  showFileSelector: state.showFileSelector,
232
232
  filteredFiles: state.filteredFiles,
233
233
  fileSearchQuery: state.fileSearchQuery,
234
+ isFileSearching: state.isFileSearching,
234
235
  atPosition: state.atPosition,
235
236
  showCommandSelector: state.showCommandSelector,
236
237
  commandSearchQuery: state.commandSearchQuery,
@@ -1 +1 @@
1
- {"version":3,"file":"inputHandlers.d.ts","sourceRoot":"","sources":["../../src/managers/inputHandlers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inputHandlers.d.ts","sourceRoot":"","sources":["../../src/managers/inputHandlers.ts"],"names":[],"mappings":"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"}
@@ -27,12 +27,12 @@ export const handleSubmit = async (state, dispatch, callbacks, attachedImagesOve
27
27
  .map((img) => ({ path: img.path, mimeType: img.mimeType }));
28
28
  let cleanContent = state.inputText.replace(imageRegex, "").trim();
29
29
  cleanContent = expandLongTextPlaceholders(cleanContent, state.longTextMap);
30
- PromptHistoryManager.addEntry(cleanContent).catch((err) => {
30
+ PromptHistoryManager.addEntry(cleanContent, callbacks.sessionId, state.longTextMap).catch((err) => {
31
31
  callbacks.logger?.error("Failed to save prompt history", err);
32
32
  });
33
33
  callbacks.onSendMessage?.(cleanContent, referencedImages.length > 0 ? referencedImages : undefined);
34
34
  dispatch({ type: "CLEAR_INPUT" });
35
- callbacks.onResetHistoryNavigation?.();
35
+ dispatch({ type: "RESET_HISTORY_NAVIGATION" });
36
36
  dispatch({ type: "CLEAR_LONG_TEXT_MAP" });
37
37
  }
38
38
  };
@@ -190,7 +190,7 @@ export const handlePasteInput = (state, dispatch, callbacks, input) => {
190
190
  if (char === "!" && state.cursorPosition === 0) {
191
191
  char = "!";
192
192
  }
193
- callbacks.onResetHistoryNavigation?.();
193
+ dispatch({ type: "RESET_HISTORY_NAVIGATION" });
194
194
  dispatch({ type: "INSERT_TEXT", payload: char });
195
195
  processSelectorInput(state, dispatch, char);
196
196
  }
@@ -348,6 +348,21 @@ export const handleNormalInput = async (state, dispatch, callbacks, input, key,
348
348
  else if (state.showCommandSelector) {
349
349
  dispatch({ type: "CANCEL_COMMAND_SELECTOR" });
350
350
  }
351
+ else if (state.historyIndex !== -1) {
352
+ dispatch({ type: "RESET_HISTORY_NAVIGATION" });
353
+ }
354
+ return true;
355
+ }
356
+ if (key.upArrow) {
357
+ if (state.history.length === 0) {
358
+ const history = await PromptHistoryManager.getHistory(callbacks.sessionId);
359
+ dispatch({ type: "SET_HISTORY_ENTRIES", payload: history });
360
+ }
361
+ dispatch({ type: "NAVIGATE_HISTORY", payload: "up" });
362
+ return true;
363
+ }
364
+ if (key.downArrow) {
365
+ dispatch({ type: "NAVIGATE_HISTORY", payload: "down" });
351
366
  return true;
352
367
  }
353
368
  if (key.backspace || key.delete) {
@@ -357,7 +372,7 @@ export const handleNormalInput = async (state, dispatch, callbacks, input, key,
357
372
  const afterCursor = state.inputText.substring(state.cursorPosition);
358
373
  const newInputText = beforeCursor + afterCursor;
359
374
  dispatch({ type: "DELETE_CHAR" });
360
- callbacks.onResetHistoryNavigation?.();
375
+ dispatch({ type: "RESET_HISTORY_NAVIGATION" });
361
376
  checkForAtDeletion(state, dispatch, newCursorPosition);
362
377
  checkForSlashDeletion(state, dispatch, newCursorPosition);
363
378
  // Reactivate file selector if cursor is now within an @word
@@ -1,4 +1,4 @@
1
- import { FileItem, PermissionMode, Logger } from "wave-agent-sdk";
1
+ import { FileItem, PermissionMode, Logger, PromptEntry } from "wave-agent-sdk";
2
2
  export interface AttachedImage {
3
3
  id: number;
4
4
  path: string;
@@ -24,8 +24,8 @@ export interface InputManagerCallbacks {
24
24
  onAbortMessage?: () => void;
25
25
  onClearMessages?: () => void;
26
26
  onBackgroundCurrentTask?: () => void;
27
- onResetHistoryNavigation?: () => void;
28
27
  onPermissionModeChange?: (mode: PermissionMode) => void;
28
+ sessionId?: string;
29
29
  logger?: Logger;
30
30
  }
31
31
  export interface InputState {
@@ -54,6 +54,11 @@ export interface InputState {
54
54
  isPasting: boolean;
55
55
  pasteBuffer: string;
56
56
  initialPasteCursorPosition: number;
57
+ history: PromptEntry[];
58
+ historyIndex: number;
59
+ originalInputText: string;
60
+ originalLongTextMap: Record<string, string>;
61
+ isFileSearching: boolean;
57
62
  }
58
63
  export declare const initialState: InputState;
59
64
  export type InputAction = {
@@ -152,6 +157,17 @@ export type InputAction = {
152
157
  path: string;
153
158
  mimeType: string;
154
159
  };
160
+ } | {
161
+ type: "SET_HISTORY_ENTRIES";
162
+ payload: PromptEntry[];
163
+ } | {
164
+ type: "NAVIGATE_HISTORY";
165
+ payload: "up" | "down";
166
+ } | {
167
+ type: "RESET_HISTORY_NAVIGATION";
168
+ } | {
169
+ type: "SELECT_HISTORY_ENTRY";
170
+ payload: PromptEntry;
155
171
  };
156
172
  export declare function inputReducer(state: InputState, action: InputAction): InputState;
157
173
  //# sourceMappingURL=inputReducer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"inputReducer.d.ts","sourceRoot":"","sources":["../../src/managers/inputReducer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inputReducer.d.ts","sourceRoot":"","sources":["../../src/managers/inputReducer.ts"],"names":[],"mappings":"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"}
@@ -24,11 +24,20 @@ export const initialState = {
24
24
  isPasting: false,
25
25
  pasteBuffer: "",
26
26
  initialPasteCursorPosition: 0,
27
+ history: [],
28
+ historyIndex: -1,
29
+ originalInputText: "",
30
+ originalLongTextMap: {},
31
+ isFileSearching: false,
27
32
  };
28
33
  export function inputReducer(state, action) {
29
34
  switch (action.type) {
30
35
  case "SET_INPUT_TEXT":
31
- return { ...state, inputText: action.payload };
36
+ return {
37
+ ...state,
38
+ inputText: action.payload,
39
+ historyIndex: -1,
40
+ };
32
41
  case "SET_CURSOR_POSITION":
33
42
  return {
34
43
  ...state,
@@ -43,6 +52,7 @@ export function inputReducer(state, action) {
43
52
  ...state,
44
53
  inputText: newText,
45
54
  cursorPosition: newCursorPosition,
55
+ historyIndex: -1,
46
56
  };
47
57
  }
48
58
  case "DELETE_CHAR": {
@@ -55,6 +65,7 @@ export function inputReducer(state, action) {
55
65
  ...state,
56
66
  inputText: newText,
57
67
  cursorPosition: newCursorPosition,
68
+ historyIndex: -1,
58
69
  };
59
70
  }
60
71
  return state;
@@ -70,11 +81,20 @@ export function inputReducer(state, action) {
70
81
  atPosition: action.payload,
71
82
  fileSearchQuery: "",
72
83
  filteredFiles: [],
84
+ isFileSearching: true,
73
85
  };
74
86
  case "SET_FILE_SEARCH_QUERY":
75
- return { ...state, fileSearchQuery: action.payload };
87
+ return {
88
+ ...state,
89
+ fileSearchQuery: action.payload,
90
+ isFileSearching: true,
91
+ };
76
92
  case "SET_FILTERED_FILES":
77
- return { ...state, filteredFiles: action.payload };
93
+ return {
94
+ ...state,
95
+ filteredFiles: action.payload,
96
+ isFileSearching: false,
97
+ };
78
98
  case "CANCEL_FILE_SELECTOR":
79
99
  return {
80
100
  ...state,
@@ -83,6 +103,7 @@ export function inputReducer(state, action) {
83
103
  fileSearchQuery: "",
84
104
  filteredFiles: [],
85
105
  selectorJustUsed: true,
106
+ isFileSearching: false,
86
107
  };
87
108
  case "ACTIVATE_COMMAND_SELECTOR":
88
109
  return {
@@ -189,6 +210,7 @@ export function inputReducer(state, action) {
189
210
  cursorPosition: newCursorPosition,
190
211
  longTextCounter: newLongTextCounter,
191
212
  longTextMap: newLongTextMap,
213
+ historyIndex: -1,
192
214
  };
193
215
  }
194
216
  case "CLEAR_LONG_TEXT_MAP":
@@ -198,6 +220,7 @@ export function inputReducer(state, action) {
198
220
  ...state,
199
221
  inputText: "",
200
222
  cursorPosition: 0,
223
+ historyIndex: -1,
201
224
  };
202
225
  case "START_PASTE":
203
226
  return {
@@ -234,8 +257,74 @@ export function inputReducer(state, action) {
234
257
  imageIdCounter: state.imageIdCounter + 1,
235
258
  inputText: newText,
236
259
  cursorPosition: newCursorPosition,
260
+ historyIndex: -1,
261
+ };
262
+ }
263
+ case "SET_HISTORY_ENTRIES":
264
+ return { ...state, history: action.payload };
265
+ case "NAVIGATE_HISTORY": {
266
+ const direction = action.payload;
267
+ let newIndex = state.historyIndex;
268
+ let newOriginalInputText = state.originalInputText;
269
+ let newOriginalLongTextMap = state.originalLongTextMap;
270
+ if (direction === "up") {
271
+ if (newIndex === -1) {
272
+ newOriginalInputText = state.inputText;
273
+ newOriginalLongTextMap = state.longTextMap;
274
+ }
275
+ newIndex = Math.min(state.history.length - 1, newIndex + 1);
276
+ }
277
+ else {
278
+ newIndex = Math.max(-1, newIndex - 1);
279
+ }
280
+ if (newIndex === -1) {
281
+ return {
282
+ ...state,
283
+ historyIndex: newIndex,
284
+ inputText: newOriginalInputText,
285
+ longTextMap: newOriginalLongTextMap,
286
+ cursorPosition: newOriginalInputText.length,
287
+ originalInputText: newOriginalInputText,
288
+ originalLongTextMap: newOriginalLongTextMap,
289
+ };
290
+ }
291
+ else {
292
+ const entry = state.history[newIndex];
293
+ return {
294
+ ...state,
295
+ historyIndex: newIndex,
296
+ inputText: entry.prompt,
297
+ longTextMap: entry.longTextMap || {},
298
+ cursorPosition: entry.prompt.length,
299
+ originalInputText: newOriginalInputText,
300
+ originalLongTextMap: newOriginalLongTextMap,
301
+ };
302
+ }
303
+ }
304
+ case "SELECT_HISTORY_ENTRY": {
305
+ const entry = action.payload;
306
+ return {
307
+ ...state,
308
+ inputText: entry.prompt,
309
+ longTextMap: entry.longTextMap || {},
310
+ cursorPosition: entry.prompt.length,
311
+ historyIndex: -1,
312
+ history: [],
313
+ originalInputText: "",
314
+ originalLongTextMap: {},
315
+ showHistorySearch: false,
316
+ historySearchQuery: "",
317
+ selectorJustUsed: true,
237
318
  };
238
319
  }
320
+ case "RESET_HISTORY_NAVIGATION":
321
+ return {
322
+ ...state,
323
+ historyIndex: -1,
324
+ history: [],
325
+ originalInputText: "",
326
+ originalLongTextMap: {},
327
+ };
239
328
  default:
240
329
  return state;
241
330
  }
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH;;GAEG;AACH,oBAAY,QAAQ;IAClB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;CACV;AAYD;;GAEG;AACH,UAAU,SAAS;IACjB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;CAC7B;AA8HD;;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;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;AA+HD;;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"}
@@ -8,7 +8,9 @@
8
8
  * - This can significantly improve test execution performance by avoiding unnecessary disk writes
9
9
  */
10
10
  import * as fs from "fs";
11
+ import { Chalk } from "chalk";
11
12
  import { LOG_FILE, DATA_DIRECTORY } from "./constants.js";
13
+ const chalk = new Chalk({ level: 3 });
12
14
  const logFile = process.env.LOG_FILE || LOG_FILE;
13
15
  /**
14
16
  * Log level enumeration
@@ -29,6 +31,15 @@ const LOG_LEVEL_NAMES = {
29
31
  [LogLevel.WARN]: "WARN",
30
32
  [LogLevel.ERROR]: "ERROR",
31
33
  };
34
+ /**
35
+ * Log level color mapping
36
+ */
37
+ const LEVEL_COLORS = {
38
+ [LogLevel.DEBUG]: chalk.gray,
39
+ [LogLevel.INFO]: chalk.blue,
40
+ [LogLevel.WARN]: chalk.yellow,
41
+ [LogLevel.ERROR]: chalk.red,
42
+ };
32
43
  /**
33
44
  * Parse log level from environment variable
34
45
  */
@@ -125,7 +136,8 @@ const logMessage = (level, ...args) => {
125
136
  }
126
137
  const levelName = LOG_LEVEL_NAMES[level];
127
138
  const timestamp = new Date().toISOString();
128
- const formattedMessage = `[${timestamp}] [${levelName}] ${messageText}\n`;
139
+ const color = LEVEL_COLORS[level] || ((s) => s);
140
+ const formattedMessage = `[${chalk.gray(timestamp)}] [${color(levelName)}] ${messageText}\n`;
129
141
  try {
130
142
  // Ensure directory exists
131
143
  if (!fs.existsSync(DATA_DIRECTORY)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-code",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "CLI-based code assistant powered by AI, built with React and Ink",
5
5
  "repository": {
6
6
  "type": "git",
@@ -39,7 +39,7 @@
39
39
  "react": "^19.2.4",
40
40
  "react-dom": "19.2.4",
41
41
  "yargs": "^17.7.2",
42
- "wave-agent-sdk": "0.9.0"
42
+ "wave-agent-sdk": "0.9.1"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/react": "^19.1.8",
@@ -7,6 +7,7 @@ export { type FileItem } from "wave-agent-sdk";
7
7
  export interface FileSelectorProps {
8
8
  files: FileItem[];
9
9
  searchQuery: string;
10
+ isLoading?: boolean;
10
11
  onSelect: (filePath: string) => void;
11
12
  onCancel: () => void;
12
13
  }
@@ -14,6 +15,7 @@ export interface FileSelectorProps {
14
15
  export const FileSelector: React.FC<FileSelectorProps> = ({
15
16
  files,
16
17
  searchQuery,
18
+ isLoading = false,
17
19
  onSelect,
18
20
  onCancel,
19
21
  }) => {
@@ -48,13 +50,21 @@ export const FileSelector: React.FC<FileSelectorProps> = ({
48
50
  <Box
49
51
  flexDirection="column"
50
52
  borderStyle="single"
51
- borderColor="yellow"
53
+ borderColor={isLoading ? "cyan" : "yellow"}
52
54
  borderBottom={false}
53
55
  borderLeft={false}
54
56
  borderRight={false}
55
57
  >
56
- <Text color="yellow">No files found for "{searchQuery}"</Text>
57
- <Text dimColor>Press Escape to cancel</Text>
58
+ {isLoading ? (
59
+ <Text color="cyan" bold>
60
+ Select File/Directory...
61
+ </Text>
62
+ ) : (
63
+ <>
64
+ <Text color="yellow">No files found for "{searchQuery}"</Text>
65
+ <Text dimColor>Press Escape to cancel</Text>
66
+ </>
67
+ )}
58
68
  </Box>
59
69
  );
60
70
  }
@@ -4,7 +4,7 @@ import { PromptHistoryManager, type PromptEntry } from "wave-agent-sdk";
4
4
 
5
5
  export interface HistorySearchProps {
6
6
  searchQuery: string;
7
- onSelect: (prompt: string) => void;
7
+ onSelect: (entry: PromptEntry) => void;
8
8
  onCancel: () => void;
9
9
  }
10
10
 
@@ -44,7 +44,7 @@ export const HistorySearch: React.FC<HistorySearchProps> = ({
44
44
  entriesRef.current.length > 0 &&
45
45
  selectedIndexRef.current < entriesRef.current.length
46
46
  ) {
47
- onSelect(entriesRef.current[selectedIndexRef.current].prompt);
47
+ onSelect(entriesRef.current[selectedIndexRef.current]);
48
48
  }
49
49
  return;
50
50
  }
@@ -57,6 +57,7 @@ export const InputBox: React.FC<InputBoxProps> = ({
57
57
  messages,
58
58
  getFullMessageThread,
59
59
  clearMessages,
60
+ sessionId,
60
61
  } = useChat();
61
62
 
62
63
  // Input manager with all input state and functionality (including images)
@@ -70,6 +71,7 @@ export const InputBox: React.FC<InputBoxProps> = ({
70
71
  showFileSelector,
71
72
  filteredFiles,
72
73
  fileSearchQuery: searchQuery,
74
+ isFileSearching,
73
75
  handleFileSelect,
74
76
  handleCancelFileSelect,
75
77
  // Command selector
@@ -108,6 +110,7 @@ export const InputBox: React.FC<InputBoxProps> = ({
108
110
  onBackgroundCurrentTask: backgroundCurrentTask,
109
111
  onPermissionModeChange: setChatPermissionMode,
110
112
  onClearMessages: clearMessages,
113
+ sessionId,
111
114
  });
112
115
 
113
116
  // Sync permission mode from useChat to InputManager
@@ -183,6 +186,7 @@ export const InputBox: React.FC<InputBoxProps> = ({
183
186
  <FileSelector
184
187
  files={filteredFiles}
185
188
  searchQuery={searchQuery}
189
+ isLoading={isFileSearching}
186
190
  onSelect={handleFileSelect}
187
191
  onCancel={handleCancelFileSelect}
188
192
  />
@@ -5,7 +5,11 @@ import {
5
5
  initialState,
6
6
  InputManagerCallbacks,
7
7
  } from "../managers/inputReducer.js";
8
- import { searchFiles as searchFilesUtil, PermissionMode } from "wave-agent-sdk";
8
+ import {
9
+ searchFiles as searchFilesUtil,
10
+ PermissionMode,
11
+ PromptEntry,
12
+ } from "wave-agent-sdk";
9
13
  import * as handlers from "../managers/inputHandlers.js";
10
14
 
11
15
  export const useInputManager = (
@@ -37,10 +41,10 @@ export const useInputManager = (
37
41
  // Handle debounced file search
38
42
  useEffect(() => {
39
43
  if (state.showFileSelector) {
40
- const debounceDelay = parseInt(
41
- process.env.FILE_SELECTOR_DEBOUNCE_MS || "300",
42
- 10,
43
- );
44
+ const debounceDelay =
45
+ state.fileSearchQuery === ""
46
+ ? 0
47
+ : parseInt(process.env.FILE_SELECTOR_DEBOUNCE_MS || "300", 10);
44
48
  const timer = setTimeout(async () => {
45
49
  try {
46
50
  const fileItems = await searchFilesUtil(state.fileSearchQuery);
@@ -68,7 +72,7 @@ export const useInputManager = (
68
72
  );
69
73
  dispatch({ type: "COMPRESS_AND_INSERT_TEXT", payload: processedInput });
70
74
  dispatch({ type: "END_PASTE" });
71
- callbacksRef.current.onResetHistoryNavigation?.();
75
+ dispatch({ type: "RESET_HISTORY_NAVIGATION" });
72
76
  }, pasteDebounceDelay);
73
77
  return () => clearTimeout(timer);
74
78
  }
@@ -247,10 +251,8 @@ export const useInputManager = (
247
251
  );
248
252
  }, []);
249
253
 
250
- const handleHistorySearchSelect = useCallback((prompt: string) => {
251
- dispatch({ type: "SET_INPUT_TEXT", payload: prompt });
252
- dispatch({ type: "SET_CURSOR_POSITION", payload: prompt.length });
253
- dispatch({ type: "CANCEL_HISTORY_SEARCH" });
254
+ const handleHistorySearchSelect = useCallback((entry: PromptEntry) => {
255
+ dispatch({ type: "SELECT_HISTORY_ENTRY", payload: entry });
254
256
  }, []);
255
257
 
256
258
  const handleCancelHistorySearch = useCallback(() => {
@@ -370,6 +372,7 @@ export const useInputManager = (
370
372
  showFileSelector: state.showFileSelector,
371
373
  filteredFiles: state.filteredFiles,
372
374
  fileSearchQuery: state.fileSearchQuery,
375
+ isFileSearching: state.isFileSearching,
373
376
  atPosition: state.atPosition,
374
377
  showCommandSelector: state.showCommandSelector,
375
378
  commandSearchQuery: state.commandSearchQuery,
@@ -54,7 +54,11 @@ export const handleSubmit = async (
54
54
  let cleanContent = state.inputText.replace(imageRegex, "").trim();
55
55
  cleanContent = expandLongTextPlaceholders(cleanContent, state.longTextMap);
56
56
 
57
- PromptHistoryManager.addEntry(cleanContent).catch((err: unknown) => {
57
+ PromptHistoryManager.addEntry(
58
+ cleanContent,
59
+ callbacks.sessionId,
60
+ state.longTextMap,
61
+ ).catch((err: unknown) => {
58
62
  callbacks.logger?.error("Failed to save prompt history", err);
59
63
  });
60
64
 
@@ -63,7 +67,7 @@ export const handleSubmit = async (
63
67
  referencedImages.length > 0 ? referencedImages : undefined,
64
68
  );
65
69
  dispatch({ type: "CLEAR_INPUT" });
66
- callbacks.onResetHistoryNavigation?.();
70
+ dispatch({ type: "RESET_HISTORY_NAVIGATION" });
67
71
  dispatch({ type: "CLEAR_LONG_TEXT_MAP" });
68
72
  }
69
73
  };
@@ -276,7 +280,7 @@ export const handlePasteInput = (
276
280
  char = "!";
277
281
  }
278
282
 
279
- callbacks.onResetHistoryNavigation?.();
283
+ dispatch({ type: "RESET_HISTORY_NAVIGATION" });
280
284
  dispatch({ type: "INSERT_TEXT", payload: char });
281
285
 
282
286
  processSelectorInput(state, dispatch, char);
@@ -494,10 +498,28 @@ export const handleNormalInput = async (
494
498
  dispatch({ type: "CANCEL_FILE_SELECTOR" });
495
499
  } else if (state.showCommandSelector) {
496
500
  dispatch({ type: "CANCEL_COMMAND_SELECTOR" });
501
+ } else if (state.historyIndex !== -1) {
502
+ dispatch({ type: "RESET_HISTORY_NAVIGATION" });
497
503
  }
498
504
  return true;
499
505
  }
500
506
 
507
+ if (key.upArrow) {
508
+ if (state.history.length === 0) {
509
+ const history = await PromptHistoryManager.getHistory(
510
+ callbacks.sessionId,
511
+ );
512
+ dispatch({ type: "SET_HISTORY_ENTRIES", payload: history });
513
+ }
514
+ dispatch({ type: "NAVIGATE_HISTORY", payload: "up" });
515
+ return true;
516
+ }
517
+
518
+ if (key.downArrow) {
519
+ dispatch({ type: "NAVIGATE_HISTORY", payload: "down" });
520
+ return true;
521
+ }
522
+
501
523
  if (key.backspace || key.delete) {
502
524
  if (state.cursorPosition > 0) {
503
525
  const newCursorPosition = state.cursorPosition - 1;
@@ -509,7 +531,7 @@ export const handleNormalInput = async (
509
531
  const newInputText = beforeCursor + afterCursor;
510
532
 
511
533
  dispatch({ type: "DELETE_CHAR" });
512
- callbacks.onResetHistoryNavigation?.();
534
+ dispatch({ type: "RESET_HISTORY_NAVIGATION" });
513
535
 
514
536
  checkForAtDeletion(state, dispatch, newCursorPosition);
515
537
  checkForSlashDeletion(state, dispatch, newCursorPosition);
@@ -1,4 +1,4 @@
1
- import { FileItem, PermissionMode, Logger } from "wave-agent-sdk";
1
+ import { FileItem, PermissionMode, Logger, PromptEntry } from "wave-agent-sdk";
2
2
 
3
3
  export interface AttachedImage {
4
4
  id: number;
@@ -35,8 +35,8 @@ export interface InputManagerCallbacks {
35
35
  onAbortMessage?: () => void;
36
36
  onClearMessages?: () => void;
37
37
  onBackgroundCurrentTask?: () => void;
38
- onResetHistoryNavigation?: () => void;
39
38
  onPermissionModeChange?: (mode: PermissionMode) => void;
39
+ sessionId?: string;
40
40
  logger?: Logger;
41
41
  }
42
42
 
@@ -66,6 +66,11 @@ export interface InputState {
66
66
  isPasting: boolean;
67
67
  pasteBuffer: string;
68
68
  initialPasteCursorPosition: number;
69
+ history: PromptEntry[];
70
+ historyIndex: number;
71
+ originalInputText: string;
72
+ originalLongTextMap: Record<string, string>;
73
+ isFileSearching: boolean;
69
74
  }
70
75
 
71
76
  export const initialState: InputState = {
@@ -94,6 +99,11 @@ export const initialState: InputState = {
94
99
  isPasting: false,
95
100
  pasteBuffer: "",
96
101
  initialPasteCursorPosition: 0,
102
+ history: [],
103
+ historyIndex: -1,
104
+ originalInputText: "",
105
+ originalLongTextMap: {},
106
+ isFileSearching: false,
97
107
  };
98
108
 
99
109
  export type InputAction =
@@ -131,7 +141,11 @@ export type InputAction =
131
141
  | {
132
142
  type: "ADD_IMAGE_AND_INSERT_PLACEHOLDER";
133
143
  payload: { path: string; mimeType: string };
134
- };
144
+ }
145
+ | { type: "SET_HISTORY_ENTRIES"; payload: PromptEntry[] }
146
+ | { type: "NAVIGATE_HISTORY"; payload: "up" | "down" }
147
+ | { type: "RESET_HISTORY_NAVIGATION" }
148
+ | { type: "SELECT_HISTORY_ENTRY"; payload: PromptEntry };
135
149
 
136
150
  export function inputReducer(
137
151
  state: InputState,
@@ -139,7 +153,11 @@ export function inputReducer(
139
153
  ): InputState {
140
154
  switch (action.type) {
141
155
  case "SET_INPUT_TEXT":
142
- return { ...state, inputText: action.payload };
156
+ return {
157
+ ...state,
158
+ inputText: action.payload,
159
+ historyIndex: -1,
160
+ };
143
161
  case "SET_CURSOR_POSITION":
144
162
  return {
145
163
  ...state,
@@ -157,6 +175,7 @@ export function inputReducer(
157
175
  ...state,
158
176
  inputText: newText,
159
177
  cursorPosition: newCursorPosition,
178
+ historyIndex: -1,
160
179
  };
161
180
  }
162
181
  case "DELETE_CHAR": {
@@ -172,6 +191,7 @@ export function inputReducer(
172
191
  ...state,
173
192
  inputText: newText,
174
193
  cursorPosition: newCursorPosition,
194
+ historyIndex: -1,
175
195
  };
176
196
  }
177
197
  return state;
@@ -190,11 +210,20 @@ export function inputReducer(
190
210
  atPosition: action.payload,
191
211
  fileSearchQuery: "",
192
212
  filteredFiles: [],
213
+ isFileSearching: true,
193
214
  };
194
215
  case "SET_FILE_SEARCH_QUERY":
195
- return { ...state, fileSearchQuery: action.payload };
216
+ return {
217
+ ...state,
218
+ fileSearchQuery: action.payload,
219
+ isFileSearching: true,
220
+ };
196
221
  case "SET_FILTERED_FILES":
197
- return { ...state, filteredFiles: action.payload };
222
+ return {
223
+ ...state,
224
+ filteredFiles: action.payload,
225
+ isFileSearching: false,
226
+ };
198
227
  case "CANCEL_FILE_SELECTOR":
199
228
  return {
200
229
  ...state,
@@ -203,6 +232,7 @@ export function inputReducer(
203
232
  fileSearchQuery: "",
204
233
  filteredFiles: [],
205
234
  selectorJustUsed: true,
235
+ isFileSearching: false,
206
236
  };
207
237
  case "ACTIVATE_COMMAND_SELECTOR":
208
238
  return {
@@ -314,6 +344,7 @@ export function inputReducer(
314
344
  cursorPosition: newCursorPosition,
315
345
  longTextCounter: newLongTextCounter,
316
346
  longTextMap: newLongTextMap,
347
+ historyIndex: -1,
317
348
  };
318
349
  }
319
350
  case "CLEAR_LONG_TEXT_MAP":
@@ -323,6 +354,7 @@ export function inputReducer(
323
354
  ...state,
324
355
  inputText: "",
325
356
  cursorPosition: 0,
357
+ historyIndex: -1,
326
358
  };
327
359
  case "START_PASTE":
328
360
  return {
@@ -359,8 +391,74 @@ export function inputReducer(
359
391
  imageIdCounter: state.imageIdCounter + 1,
360
392
  inputText: newText,
361
393
  cursorPosition: newCursorPosition,
394
+ historyIndex: -1,
362
395
  };
363
396
  }
397
+ case "SET_HISTORY_ENTRIES":
398
+ return { ...state, history: action.payload };
399
+ case "NAVIGATE_HISTORY": {
400
+ const direction = action.payload;
401
+ let newIndex = state.historyIndex;
402
+ let newOriginalInputText = state.originalInputText;
403
+ let newOriginalLongTextMap = state.originalLongTextMap;
404
+
405
+ if (direction === "up") {
406
+ if (newIndex === -1) {
407
+ newOriginalInputText = state.inputText;
408
+ newOriginalLongTextMap = state.longTextMap;
409
+ }
410
+ newIndex = Math.min(state.history.length - 1, newIndex + 1);
411
+ } else {
412
+ newIndex = Math.max(-1, newIndex - 1);
413
+ }
414
+
415
+ if (newIndex === -1) {
416
+ return {
417
+ ...state,
418
+ historyIndex: newIndex,
419
+ inputText: newOriginalInputText,
420
+ longTextMap: newOriginalLongTextMap,
421
+ cursorPosition: newOriginalInputText.length,
422
+ originalInputText: newOriginalInputText,
423
+ originalLongTextMap: newOriginalLongTextMap,
424
+ };
425
+ } else {
426
+ const entry = state.history[newIndex];
427
+ return {
428
+ ...state,
429
+ historyIndex: newIndex,
430
+ inputText: entry.prompt,
431
+ longTextMap: entry.longTextMap || {},
432
+ cursorPosition: entry.prompt.length,
433
+ originalInputText: newOriginalInputText,
434
+ originalLongTextMap: newOriginalLongTextMap,
435
+ };
436
+ }
437
+ }
438
+ case "SELECT_HISTORY_ENTRY": {
439
+ const entry = action.payload;
440
+ return {
441
+ ...state,
442
+ inputText: entry.prompt,
443
+ longTextMap: entry.longTextMap || {},
444
+ cursorPosition: entry.prompt.length,
445
+ historyIndex: -1,
446
+ history: [],
447
+ originalInputText: "",
448
+ originalLongTextMap: {},
449
+ showHistorySearch: false,
450
+ historySearchQuery: "",
451
+ selectorJustUsed: true,
452
+ };
453
+ }
454
+ case "RESET_HISTORY_NAVIGATION":
455
+ return {
456
+ ...state,
457
+ historyIndex: -1,
458
+ history: [],
459
+ originalInputText: "",
460
+ originalLongTextMap: {},
461
+ };
364
462
  default:
365
463
  return state;
366
464
  }
@@ -9,8 +9,11 @@
9
9
  */
10
10
 
11
11
  import * as fs from "fs";
12
+ import { Chalk } from "chalk";
12
13
  import { LOG_FILE, DATA_DIRECTORY } from "./constants.js";
13
14
 
15
+ const chalk = new Chalk({ level: 3 });
16
+
14
17
  const logFile = process.env.LOG_FILE || LOG_FILE;
15
18
 
16
19
  /**
@@ -33,6 +36,16 @@ const LOG_LEVEL_NAMES = {
33
36
  [LogLevel.ERROR]: "ERROR",
34
37
  };
35
38
 
39
+ /**
40
+ * Log level color mapping
41
+ */
42
+ const LEVEL_COLORS = {
43
+ [LogLevel.DEBUG]: chalk.gray,
44
+ [LogLevel.INFO]: chalk.blue,
45
+ [LogLevel.WARN]: chalk.yellow,
46
+ [LogLevel.ERROR]: chalk.red,
47
+ };
48
+
36
49
  /**
37
50
  * Log configuration interface
38
51
  */
@@ -146,7 +159,8 @@ const logMessage = (level: LogLevel, ...args: unknown[]): void => {
146
159
 
147
160
  const levelName = LOG_LEVEL_NAMES[level];
148
161
  const timestamp = new Date().toISOString();
149
- const formattedMessage = `[${timestamp}] [${levelName}] ${messageText}\n`;
162
+ const color = LEVEL_COLORS[level] || ((s: string) => s);
163
+ const formattedMessage = `[${chalk.gray(timestamp)}] [${color(levelName)}] ${messageText}\n`;
150
164
 
151
165
  try {
152
166
  // Ensure directory exists