wave-code 1.0.9 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/bin/wave-code.js +8 -2
  2. package/dist/bundle/wave.mjs +3207 -0
  3. package/package.json +24 -25
  4. package/src/commands/update.ts +2 -7
  5. package/src/components/App.tsx +3 -7
  6. package/src/components/BtwDisplay.tsx +10 -1
  7. package/src/components/ChatInterface.tsx +21 -52
  8. package/src/components/ConfirmationDetails.tsx +144 -37
  9. package/src/components/DiffDisplay.tsx +335 -301
  10. package/src/components/InputBox.tsx +3 -1
  11. package/src/components/LoadingIndicator.tsx +16 -2
  12. package/src/components/MessageBlockItem.tsx +2 -4
  13. package/src/components/MessageList.tsx +75 -14
  14. package/src/components/ReasoningDisplay.tsx +2 -4
  15. package/src/components/SessionSelector.tsx +82 -11
  16. package/src/components/StatusCommand.tsx +2 -9
  17. package/src/components/ToolDisplay.tsx +2 -4
  18. package/src/contexts/useChat.tsx +172 -350
  19. package/src/daemon/commands.ts +57 -27
  20. package/src/daemon/jsonRpcClient.ts +1 -1
  21. package/src/daemon/socketClient.ts +2 -2
  22. package/src/hooks/useInputManager.ts +1 -1
  23. package/src/index.ts +57 -10
  24. package/src/managers/inputReducer.ts +186 -104
  25. package/src/print-cli.ts +21 -17
  26. package/src/reducers/selectorReducer.ts +10 -0
  27. package/src/session-selector-cli.tsx +269 -28
  28. package/src/stdio/agentBridge.ts +22 -21
  29. package/src/stdio/daemonServer.ts +3 -1
  30. package/src/stdio/jsonRpcConnection.ts +19 -1
  31. package/src/stdio/stdioServer.ts +17 -0
  32. package/src/utils/clipboard.ts +21 -0
  33. package/src/utils/highlightUtils.ts +46 -1
  34. package/src/utils/readPackageJson.ts +29 -0
  35. package/src/utils/streamingText.ts +11 -0
  36. package/src/utils/worktree.ts +191 -43
  37. package/dist/cli.d.ts +0 -6
  38. package/dist/cli.js +0 -53
  39. package/dist/commands/plugin/disable.d.ts +0 -5
  40. package/dist/commands/plugin/disable.js +0 -15
  41. package/dist/commands/plugin/enable.d.ts +0 -5
  42. package/dist/commands/plugin/enable.js +0 -15
  43. package/dist/commands/plugin/install.d.ts +0 -5
  44. package/dist/commands/plugin/install.js +0 -21
  45. package/dist/commands/plugin/list.d.ts +0 -1
  46. package/dist/commands/plugin/list.js +0 -31
  47. package/dist/commands/plugin/marketplace.d.ts +0 -10
  48. package/dist/commands/plugin/marketplace.js +0 -90
  49. package/dist/commands/plugin/uninstall.d.ts +0 -3
  50. package/dist/commands/plugin/uninstall.js +0 -16
  51. package/dist/commands/plugin/update.d.ts +0 -3
  52. package/dist/commands/plugin/update.js +0 -15
  53. package/dist/commands/update.d.ts +0 -1
  54. package/dist/commands/update.js +0 -97
  55. package/dist/components/AgentsManager.d.ts +0 -7
  56. package/dist/components/AgentsManager.js +0 -109
  57. package/dist/components/App.d.ts +0 -9
  58. package/dist/components/App.js +0 -76
  59. package/dist/components/BackgroundTaskManager.d.ts +0 -5
  60. package/dist/components/BackgroundTaskManager.js +0 -99
  61. package/dist/components/BangDisplay.d.ts +0 -8
  62. package/dist/components/BangDisplay.js +0 -17
  63. package/dist/components/BtwDisplay.d.ts +0 -7
  64. package/dist/components/BtwDisplay.js +0 -19
  65. package/dist/components/ChatInterface.d.ts +0 -2
  66. package/dist/components/ChatInterface.js +0 -61
  67. package/dist/components/CommandSelector.d.ts +0 -10
  68. package/dist/components/CommandSelector.js +0 -66
  69. package/dist/components/CompactDisplay.d.ts +0 -8
  70. package/dist/components/CompactDisplay.js +0 -13
  71. package/dist/components/ConfirmationDetails.d.ts +0 -9
  72. package/dist/components/ConfirmationDetails.js +0 -45
  73. package/dist/components/ConfirmationSelector.d.ts +0 -13
  74. package/dist/components/ConfirmationSelector.js +0 -127
  75. package/dist/components/DiffDisplay.d.ts +0 -8
  76. package/dist/components/DiffDisplay.js +0 -201
  77. package/dist/components/DiscoverView.d.ts +0 -2
  78. package/dist/components/DiscoverView.js +0 -37
  79. package/dist/components/FileSelector.d.ts +0 -11
  80. package/dist/components/FileSelector.js +0 -50
  81. package/dist/components/HelpView.d.ts +0 -7
  82. package/dist/components/HelpView.js +0 -74
  83. package/dist/components/HistorySearch.d.ts +0 -8
  84. package/dist/components/HistorySearch.js +0 -66
  85. package/dist/components/InputBox.d.ts +0 -24
  86. package/dist/components/InputBox.js +0 -149
  87. package/dist/components/InstalledView.d.ts +0 -2
  88. package/dist/components/InstalledView.js +0 -45
  89. package/dist/components/LoadingIndicator.d.ts +0 -10
  90. package/dist/components/LoadingIndicator.js +0 -6
  91. package/dist/components/LoginCommand.d.ts +0 -5
  92. package/dist/components/LoginCommand.js +0 -153
  93. package/dist/components/Markdown.d.ts +0 -5
  94. package/dist/components/Markdown.js +0 -127
  95. package/dist/components/MarketplaceAddForm.d.ts +0 -2
  96. package/dist/components/MarketplaceAddForm.js +0 -55
  97. package/dist/components/MarketplaceDetail.d.ts +0 -2
  98. package/dist/components/MarketplaceDetail.js +0 -74
  99. package/dist/components/MarketplaceList.d.ts +0 -8
  100. package/dist/components/MarketplaceList.js +0 -17
  101. package/dist/components/MarketplaceView.d.ts +0 -2
  102. package/dist/components/MarketplaceView.js +0 -41
  103. package/dist/components/McpManager.d.ts +0 -9
  104. package/dist/components/McpManager.js +0 -88
  105. package/dist/components/MessageBlockItem.d.ts +0 -8
  106. package/dist/components/MessageBlockItem.js +0 -15
  107. package/dist/components/MessageList.d.ts +0 -10
  108. package/dist/components/MessageList.js +0 -80
  109. package/dist/components/ModelSelector.d.ts +0 -8
  110. package/dist/components/ModelSelector.js +0 -45
  111. package/dist/components/Notifications.d.ts +0 -7
  112. package/dist/components/Notifications.js +0 -9
  113. package/dist/components/PlanDisplay.d.ts +0 -7
  114. package/dist/components/PlanDisplay.js +0 -6
  115. package/dist/components/PluginDetail.d.ts +0 -2
  116. package/dist/components/PluginDetail.js +0 -87
  117. package/dist/components/PluginList.d.ts +0 -13
  118. package/dist/components/PluginList.js +0 -15
  119. package/dist/components/PluginManagerShell.d.ts +0 -6
  120. package/dist/components/PluginManagerShell.js +0 -92
  121. package/dist/components/PluginManagerTypes.d.ts +0 -35
  122. package/dist/components/PluginManagerTypes.js +0 -1
  123. package/dist/components/QueuedMessageList.d.ts +0 -2
  124. package/dist/components/QueuedMessageList.js +0 -18
  125. package/dist/components/ReasoningDisplay.d.ts +0 -8
  126. package/dist/components/ReasoningDisplay.js +0 -13
  127. package/dist/components/RewindCommand.d.ts +0 -12
  128. package/dist/components/RewindCommand.js +0 -78
  129. package/dist/components/SessionSelector.d.ts +0 -12
  130. package/dist/components/SessionSelector.js +0 -47
  131. package/dist/components/StatusCommand.d.ts +0 -5
  132. package/dist/components/StatusCommand.js +0 -28
  133. package/dist/components/StatusLine.d.ts +0 -6
  134. package/dist/components/StatusLine.js +0 -9
  135. package/dist/components/TaskList.d.ts +0 -5
  136. package/dist/components/TaskList.js +0 -197
  137. package/dist/components/TaskNotificationMessage.d.ts +0 -5
  138. package/dist/components/TaskNotificationMessage.js +0 -12
  139. package/dist/components/ToolDisplay.d.ts +0 -9
  140. package/dist/components/ToolDisplay.js +0 -55
  141. package/dist/components/WorkflowManager.d.ts +0 -5
  142. package/dist/components/WorkflowManager.js +0 -102
  143. package/dist/components/WorktreeExitPrompt.d.ts +0 -12
  144. package/dist/components/WorktreeExitPrompt.js +0 -35
  145. package/dist/constants/commands.d.ts +0 -2
  146. package/dist/constants/commands.js +0 -92
  147. package/dist/contexts/PluginManagerContext.d.ts +0 -3
  148. package/dist/contexts/PluginManagerContext.js +0 -9
  149. package/dist/contexts/useAppConfig.d.ts +0 -10
  150. package/dist/contexts/useAppConfig.js +0 -13
  151. package/dist/contexts/useChat.d.ts +0 -101
  152. package/dist/contexts/useChat.js +0 -992
  153. package/dist/contracts/status.d.ts +0 -7
  154. package/dist/contracts/status.js +0 -1
  155. package/dist/daemon/commands.d.ts +0 -49
  156. package/dist/daemon/commands.js +0 -341
  157. package/dist/daemon/jsonRpcClient.d.ts +0 -38
  158. package/dist/daemon/jsonRpcClient.js +0 -129
  159. package/dist/daemon/socketClient.d.ts +0 -13
  160. package/dist/daemon/socketClient.js +0 -26
  161. package/dist/daemon-cli.d.ts +0 -10
  162. package/dist/daemon-cli.js +0 -15
  163. package/dist/hooks/useInputManager.d.ts +0 -75
  164. package/dist/hooks/useInputManager.js +0 -583
  165. package/dist/hooks/usePluginManager.d.ts +0 -4
  166. package/dist/hooks/usePluginManager.js +0 -265
  167. package/dist/hooks/useTasks.d.ts +0 -1
  168. package/dist/hooks/useTasks.js +0 -5
  169. package/dist/index.d.ts +0 -4
  170. package/dist/index.js +0 -447
  171. package/dist/managers/inputHandlers.d.ts +0 -30
  172. package/dist/managers/inputHandlers.js +0 -625
  173. package/dist/managers/inputReducer.d.ts +0 -271
  174. package/dist/managers/inputReducer.js +0 -1121
  175. package/dist/plugin-manager-cli.d.ts +0 -5
  176. package/dist/plugin-manager-cli.js +0 -12
  177. package/dist/print-cli.d.ts +0 -10
  178. package/dist/print-cli.js +0 -209
  179. package/dist/reducers/agentsManagerReducer.d.ts +0 -26
  180. package/dist/reducers/agentsManagerReducer.js +0 -54
  181. package/dist/reducers/backgroundTaskManagerReducer.d.ts +0 -62
  182. package/dist/reducers/backgroundTaskManagerReducer.js +0 -106
  183. package/dist/reducers/confirmationReducer.d.ts +0 -37
  184. package/dist/reducers/confirmationReducer.js +0 -193
  185. package/dist/reducers/helpSelectorReducer.d.ts +0 -25
  186. package/dist/reducers/helpSelectorReducer.js +0 -52
  187. package/dist/reducers/marketplaceAddFormReducer.d.ts +0 -24
  188. package/dist/reducers/marketplaceAddFormReducer.js +0 -58
  189. package/dist/reducers/mcpManagerReducer.d.ts +0 -37
  190. package/dist/reducers/mcpManagerReducer.js +0 -74
  191. package/dist/reducers/pluginDetailReducer.d.ts +0 -32
  192. package/dist/reducers/pluginDetailReducer.js +0 -70
  193. package/dist/reducers/questionReducer.d.ts +0 -82
  194. package/dist/reducers/questionReducer.js +0 -375
  195. package/dist/reducers/rewindSelectorReducer.d.ts +0 -21
  196. package/dist/reducers/rewindSelectorReducer.js +0 -37
  197. package/dist/reducers/selectorReducer.d.ts +0 -23
  198. package/dist/reducers/selectorReducer.js +0 -42
  199. package/dist/reducers/workflowManagerReducer.d.ts +0 -40
  200. package/dist/reducers/workflowManagerReducer.js +0 -100
  201. package/dist/session-selector-cli.d.ts +0 -3
  202. package/dist/session-selector-cli.js +0 -25
  203. package/dist/stdio/agentBridge.d.ts +0 -139
  204. package/dist/stdio/agentBridge.js +0 -999
  205. package/dist/stdio/daemonServer.d.ts +0 -67
  206. package/dist/stdio/daemonServer.js +0 -191
  207. package/dist/stdio/index.d.ts +0 -5
  208. package/dist/stdio/index.js +0 -5
  209. package/dist/stdio/jsonRpcConnection.d.ts +0 -30
  210. package/dist/stdio/jsonRpcConnection.js +0 -127
  211. package/dist/stdio/protocol.d.ts +0 -41
  212. package/dist/stdio/protocol.js +0 -26
  213. package/dist/stdio/stdioServer.d.ts +0 -28
  214. package/dist/stdio/stdioServer.js +0 -36
  215. package/dist/stdio-cli.d.ts +0 -8
  216. package/dist/stdio-cli.js +0 -15
  217. package/dist/types.d.ts +0 -20
  218. package/dist/types.js +0 -1
  219. package/dist/utils/bracketedPaste.d.ts +0 -39
  220. package/dist/utils/bracketedPaste.js +0 -122
  221. package/dist/utils/clipboard.d.ts +0 -21
  222. package/dist/utils/clipboard.js +0 -347
  223. package/dist/utils/constants.d.ts +0 -16
  224. package/dist/utils/constants.js +0 -18
  225. package/dist/utils/highlightUtils.d.ts +0 -1
  226. package/dist/utils/highlightUtils.js +0 -93
  227. package/dist/utils/inputUtils.d.ts +0 -17
  228. package/dist/utils/inputUtils.js +0 -67
  229. package/dist/utils/logger.d.ts +0 -71
  230. package/dist/utils/logger.js +0 -259
  231. package/dist/utils/markdownTable.d.ts +0 -34
  232. package/dist/utils/markdownTable.js +0 -302
  233. package/dist/utils/rewindCheckpoints.d.ts +0 -8
  234. package/dist/utils/rewindCheckpoints.js +0 -17
  235. package/dist/utils/throttle.d.ts +0 -14
  236. package/dist/utils/throttle.js +0 -55
  237. package/dist/utils/toolParameterTransforms.d.ts +0 -18
  238. package/dist/utils/toolParameterTransforms.js +0 -73
  239. package/dist/utils/usageSummary.d.ts +0 -28
  240. package/dist/utils/usageSummary.js +0 -121
  241. package/dist/utils/version.d.ts +0 -1
  242. package/dist/utils/version.js +0 -4
  243. package/dist/utils/worktree.d.ts +0 -35
  244. package/dist/utils/worktree.js +0 -219
@@ -1,75 +0,0 @@
1
- import { Key } from "ink";
2
- import { InputManagerCallbacks } from "../managers/inputReducer.js";
3
- import { PermissionMode, PromptEntry } from "wave-agent-sdk";
4
- export declare const useInputManager: (callbacks?: Partial<InputManagerCallbacks>) => {
5
- inputText: string;
6
- cursorPosition: number;
7
- showFileSelector: boolean;
8
- filteredFiles: import("wave-agent-sdk").FileItem[];
9
- fileSearchQuery: string;
10
- isFileSearching: boolean;
11
- atPosition: number;
12
- showCommandSelector: boolean;
13
- commandSearchQuery: string;
14
- slashPosition: number;
15
- showHistorySearch: boolean;
16
- historySearchQuery: string;
17
- showBackgroundTaskManager: boolean;
18
- showMcpManager: boolean;
19
- showAgentsManager: boolean;
20
- showRewindManager: boolean;
21
- showHelp: boolean;
22
- showStatusCommand: boolean;
23
- showLoginCommand: boolean;
24
- showPluginManager: boolean;
25
- showModelSelector: boolean;
26
- showWorkflowManager: boolean;
27
- permissionMode: PermissionMode;
28
- attachedImages: import("../managers/inputReducer.js").AttachedImage[];
29
- btwState: import("../managers/inputReducer.js").BtwState;
30
- escClearPending: boolean;
31
- isManagerReady: boolean;
32
- insertTextAtCursor: (text: string) => void;
33
- deleteCharAtCursor: () => void;
34
- clearInput: () => void;
35
- moveCursorLeft: () => void;
36
- moveCursorRight: () => void;
37
- activateFileSelector: (position: number) => void;
38
- handleFileSelect: (filePath: string) => void;
39
- handleCancelFileSelect: () => void;
40
- updateFileSearchQuery: (query: string) => void;
41
- checkForAtDeletion: (cursorPos: number) => boolean;
42
- activateCommandSelector: (position: number) => void;
43
- handleCommandSelect: (command: string) => void;
44
- handleCommandInsert: (command: string) => void;
45
- handleCancelCommandSelect: () => void;
46
- updateCommandSearchQuery: (query: string) => void;
47
- checkForSlashDeletion: (cursorPos: number) => boolean;
48
- handleHistorySearchSelect: (entry: PromptEntry) => void;
49
- handleCancelHistorySearch: () => void;
50
- processSelectorInput: (char: string) => void;
51
- setShowBackgroundTaskManager: (show: boolean) => void;
52
- setShowMcpManager: (show: boolean) => void;
53
- setShowAgentsManager: (show: boolean) => void;
54
- setShowRewindManager: (show: boolean) => void;
55
- setShowHelp: (show: boolean) => void;
56
- setShowStatusCommand: (show: boolean) => void;
57
- setShowLoginCommand: (show: boolean) => void;
58
- setShowPluginManager: (show: boolean) => void;
59
- setShowModelSelector: (show: boolean) => void;
60
- setShowWorkflowManager: (show: boolean) => void;
61
- setPermissionMode: (mode: PermissionMode) => void;
62
- setBtwState: (payload: Partial<import("../managers/inputReducer.js").BtwState>) => void;
63
- addImage: (imagePath: string, mimeType: string) => void;
64
- removeImage: (imageId: number) => void;
65
- clearImages: () => void;
66
- handlePasteImage: () => Promise<boolean>;
67
- handlePasteInput: (input: string) => void;
68
- handleSubmit: () => Promise<void>;
69
- expandLongTextPlaceholders: (text: string) => string;
70
- clearLongTextMap: () => void;
71
- handleInput: (input: string, key: Key) => Promise<boolean>;
72
- setInputText: (text: string) => void;
73
- setCursorPosition: (position: number) => void;
74
- manager: null;
75
- };
@@ -1,583 +0,0 @@
1
- import { useEffect, useReducer, useCallback, useRef } from "react";
2
- import { inputReducer, initialState, ESC_DOUBLE_PRESS_TIMEOUT_MS, btwOverlayActiveRef, } from "../managers/inputReducer.js";
3
- import { createBracketedPasteDetector } from "../utils/bracketedPaste.js";
4
- import { searchFiles as searchFilesUtil, PromptHistoryManager, } from "wave-agent-sdk";
5
- import * as handlers from "../managers/inputHandlers.js";
6
- export const useInputManager = (callbacks = {}) => {
7
- const [state, dispatch] = useReducer(inputReducer, initialState);
8
- // Detects bracketed paste (DECSET 2004) markers so pasted text is inserted
9
- // without triggering submit — a pasted trailing \r must not be treated as
10
- // Enter (see utils/bracketedPaste.ts).
11
- const pasteDetectorRef = useRef(createBracketedPasteDetector());
12
- // Abort plumbing for the /btw side question: ABORT_BTW (set when the overlay
13
- // is dismissed while loading) aborts the in-flight onAskBtw call; the
14
- // dismissed ref suppresses the late SET_BTW_STATE dispatch / error logging.
15
- const btwAbortRef = useRef(null);
16
- const btwDismissedRef = useRef(false);
17
- const { onInputTextChange, onCursorPositionChange, onFileSelectorStateChange, onCommandSelectorStateChange, onHistorySearchStateChange, onBackgroundTaskManagerStateChange, onMcpManagerStateChange, onRewindManagerStateChange, onHelpStateChange, onStatusCommandStateChange, onPluginManagerStateChange, onModelSelectorStateChange, onWorkflowManagerStateChange, onImagesStateChange, onSendMessage, onHasSlashCommand, onAbortMessage, onBackgroundCurrentTask, onPermissionModeChange, onAskBtw, sessionId, workdir, getFullMessageThread, logger, hasQueuedMessages: hasQueuedMessagesProp, onRecallQueuedMessage, onClearMessages, onCompact, onAddDir, isIdle: isIdleProp, } = callbacks;
18
- // Handle debounced file search
19
- useEffect(() => {
20
- if (state.showFileSelector) {
21
- const debounceDelay = state.fileSearchQuery === ""
22
- ? 0
23
- : parseInt(process.env.FILE_SELECTOR_DEBOUNCE_MS || "300", 10);
24
- const timer = setTimeout(async () => {
25
- try {
26
- const fileItems = await searchFilesUtil(state.fileSearchQuery);
27
- dispatch({ type: "SET_FILTERED_FILES", payload: fileItems });
28
- }
29
- catch (error) {
30
- console.error("File search error:", error);
31
- dispatch({ type: "SET_FILTERED_FILES", payload: [] });
32
- }
33
- }, debounceDelay);
34
- return () => clearTimeout(timer);
35
- }
36
- }, [state.showFileSelector, state.fileSearchQuery]);
37
- // Auto-expire the double-Esc clear pending flag after the timeout window
38
- // (aligned with Claude Code's useDoublePress timeout-based expiry).
39
- useEffect(() => {
40
- if (!state.escClearPending)
41
- return;
42
- const timer = setTimeout(() => {
43
- dispatch({ type: "RESET_ESC_CLEAR_PENDING" });
44
- }, ESC_DOUBLE_PRESS_TIMEOUT_MS);
45
- return () => clearTimeout(timer);
46
- }, [state.escClearPending]);
47
- // Sync state changes with callbacks
48
- useEffect(() => {
49
- onInputTextChange?.(state.inputText);
50
- }, [state.inputText, onInputTextChange]);
51
- useEffect(() => {
52
- onCursorPositionChange?.(state.cursorPosition);
53
- }, [state.cursorPosition, onCursorPositionChange]);
54
- // Handle pending effects
55
- useEffect(() => {
56
- if (!state.pendingEffect)
57
- return;
58
- const effect = state.pendingEffect;
59
- dispatch({ type: "CLEAR_PENDING_EFFECT" });
60
- const runEffect = async () => {
61
- try {
62
- switch (effect.type) {
63
- case "SEND_MESSAGE":
64
- await onSendMessage?.(effect.content, effect.images, effect.longTextMap);
65
- PromptHistoryManager.addEntry(effect.content, sessionId, effect.longTextMap, workdir).catch((err) => {
66
- logger?.error("Failed to save prompt history", err);
67
- });
68
- break;
69
- case "ABORT_MESSAGE":
70
- onAbortMessage?.();
71
- break;
72
- case "SAVE_PROMPT_HISTORY":
73
- PromptHistoryManager.addEntry(effect.content, sessionId, effect.longTextMap, workdir).catch((err) => {
74
- logger?.error("Failed to save prompt history", err);
75
- });
76
- break;
77
- case "BACKGROUND_CURRENT_TASK":
78
- onBackgroundCurrentTask?.();
79
- break;
80
- case "ASK_BTW": {
81
- const controller = new AbortController();
82
- btwAbortRef.current = controller;
83
- btwDismissedRef.current = false;
84
- try {
85
- const answer = await onAskBtw?.(effect.question, controller.signal, (content) => {
86
- // Stream partial answers into the overlay so the user sees
87
- // the response grow in real time (same visual language as
88
- // assistant text / thinking blocks) instead of a static
89
- // "Answering..." indicator.
90
- if (!btwDismissedRef.current) {
91
- dispatch({
92
- type: "SET_BTW_STATE",
93
- payload: { answer: content, isLoading: true },
94
- });
95
- }
96
- });
97
- if (!btwDismissedRef.current) {
98
- dispatch({
99
- type: "SET_BTW_STATE",
100
- payload: { answer, isLoading: false },
101
- });
102
- }
103
- }
104
- catch (error) {
105
- if (!btwDismissedRef.current) {
106
- console.error("Failed to ask side question:", error);
107
- dispatch({
108
- type: "SET_BTW_STATE",
109
- payload: {
110
- answer: "Error: Failed to get an answer for your side question.",
111
- isLoading: false,
112
- },
113
- });
114
- }
115
- }
116
- break;
117
- }
118
- case "ABORT_BTW":
119
- btwDismissedRef.current = true;
120
- btwAbortRef.current?.abort();
121
- btwAbortRef.current = null;
122
- break;
123
- case "PERMISSION_MODE_CHANGE":
124
- onPermissionModeChange?.(effect.mode);
125
- break;
126
- case "FETCH_HISTORY": {
127
- let sessionIds = sessionId
128
- ? [sessionId]
129
- : undefined;
130
- if (getFullMessageThread) {
131
- try {
132
- const thread = await getFullMessageThread();
133
- sessionIds = thread.sessionIds;
134
- }
135
- catch (error) {
136
- logger?.error("Failed to fetch ancestor session IDs", error);
137
- }
138
- }
139
- const history = await PromptHistoryManager.getHistory({
140
- sessionId: sessionIds,
141
- workdir: workdir,
142
- });
143
- dispatch({ type: "SET_HISTORY_ENTRIES", payload: history });
144
- dispatch({ type: "NAVIGATE_HISTORY", payload: "up" });
145
- break;
146
- }
147
- case "PASTE_IMAGE":
148
- try {
149
- await handlers.handlePasteImage(dispatch);
150
- }
151
- catch (error) {
152
- console.warn("Failed to handle paste image:", error);
153
- }
154
- break;
155
- case "EXECUTE_COMMAND":
156
- if (onSendMessage && onHasSlashCommand?.(effect.command)) {
157
- const fullCommand = `/${effect.command}`;
158
- try {
159
- await onSendMessage(fullCommand, undefined, {});
160
- }
161
- catch (error) {
162
- console.error("Failed to execute slash command:", error);
163
- }
164
- }
165
- else {
166
- // Internal command handling
167
- const command = effect.command;
168
- if (command === "tasks") {
169
- dispatch({
170
- type: "SET_SHOW_BACKGROUND_TASK_MANAGER",
171
- payload: true,
172
- });
173
- }
174
- else if (command === "mcp") {
175
- dispatch({ type: "SET_SHOW_MCP_MANAGER", payload: true });
176
- }
177
- else if (command === "agents") {
178
- dispatch({ type: "SET_SHOW_AGENTS_MANAGER", payload: true });
179
- }
180
- else if (command === "rewind") {
181
- dispatch({ type: "SET_SHOW_REWIND_MANAGER", payload: true });
182
- }
183
- else if (command === "help") {
184
- dispatch({ type: "SET_SHOW_HELP", payload: true });
185
- }
186
- else if (command === "status") {
187
- dispatch({ type: "SET_SHOW_STATUS_COMMAND", payload: true });
188
- }
189
- else if (command === "login") {
190
- dispatch({ type: "SET_SHOW_LOGIN_COMMAND", payload: true });
191
- }
192
- else if (command === "logout") {
193
- dispatch({ type: "SET_SHOW_LOGIN_COMMAND", payload: true });
194
- }
195
- else if (command === "btw") {
196
- // Bare /btw executed via the command selector — show usage
197
- // (aligned with Claude Code's empty-args message).
198
- dispatch({
199
- type: "SET_BTW_STATE",
200
- payload: {
201
- question: "",
202
- isLoading: false,
203
- answer: "Usage: /btw <your question>",
204
- },
205
- });
206
- }
207
- else if (command === "plugin") {
208
- dispatch({ type: "SET_SHOW_PLUGIN_MANAGER", payload: true });
209
- }
210
- else if (command === "model") {
211
- dispatch({ type: "SET_SHOW_MODEL_SELECTOR", payload: true });
212
- }
213
- else if (command === "workflows") {
214
- dispatch({ type: "SET_SHOW_WORKFLOW_MANAGER", payload: true });
215
- }
216
- else if (command === "clear") {
217
- await onClearMessages?.();
218
- }
219
- else if (command === "compact") {
220
- await onCompact?.(effect.args);
221
- }
222
- else if (command === "add-dir") {
223
- await onAddDir?.(effect.args);
224
- }
225
- }
226
- break;
227
- case "RECALL_QUEUED_MESSAGE":
228
- onRecallQueuedMessage?.();
229
- break;
230
- }
231
- }
232
- catch (error) {
233
- console.error("Effect execution error:", error);
234
- }
235
- };
236
- runEffect();
237
- }, [
238
- state.pendingEffect,
239
- onSendMessage,
240
- onAbortMessage,
241
- onBackgroundCurrentTask,
242
- onAskBtw,
243
- onPermissionModeChange,
244
- sessionId,
245
- workdir,
246
- getFullMessageThread,
247
- logger,
248
- onHasSlashCommand,
249
- onRecallQueuedMessage,
250
- onClearMessages,
251
- onCompact,
252
- onAddDir,
253
- ]);
254
- useEffect(() => {
255
- onFileSelectorStateChange?.(state.showFileSelector, state.filteredFiles, state.fileSearchQuery, state.atPosition);
256
- }, [
257
- state.showFileSelector,
258
- state.filteredFiles,
259
- state.fileSearchQuery,
260
- state.atPosition,
261
- onFileSelectorStateChange,
262
- ]);
263
- useEffect(() => {
264
- onCommandSelectorStateChange?.(state.showCommandSelector, state.commandSearchQuery, state.slashPosition);
265
- }, [
266
- state.showCommandSelector,
267
- state.commandSearchQuery,
268
- state.slashPosition,
269
- onCommandSelectorStateChange,
270
- ]);
271
- useEffect(() => {
272
- onHistorySearchStateChange?.(state.showHistorySearch, state.historySearchQuery);
273
- }, [
274
- state.showHistorySearch,
275
- state.historySearchQuery,
276
- onHistorySearchStateChange,
277
- ]);
278
- useEffect(() => {
279
- onBackgroundTaskManagerStateChange?.(state.showBackgroundTaskManager);
280
- }, [state.showBackgroundTaskManager, onBackgroundTaskManagerStateChange]);
281
- useEffect(() => {
282
- onMcpManagerStateChange?.(state.showMcpManager);
283
- }, [state.showMcpManager, onMcpManagerStateChange]);
284
- useEffect(() => {
285
- onRewindManagerStateChange?.(state.showRewindManager);
286
- }, [state.showRewindManager, onRewindManagerStateChange]);
287
- useEffect(() => {
288
- onHelpStateChange?.(state.showHelp);
289
- }, [state.showHelp, onHelpStateChange]);
290
- useEffect(() => {
291
- onStatusCommandStateChange?.(state.showStatusCommand);
292
- }, [state.showStatusCommand, onStatusCommandStateChange]);
293
- useEffect(() => {
294
- onPluginManagerStateChange?.(state.showPluginManager);
295
- }, [state.showPluginManager, onPluginManagerStateChange]);
296
- useEffect(() => {
297
- onModelSelectorStateChange?.(state.showModelSelector);
298
- }, [state.showModelSelector, onModelSelectorStateChange]);
299
- useEffect(() => {
300
- onWorkflowManagerStateChange?.(state.showWorkflowManager);
301
- }, [state.showWorkflowManager, onWorkflowManagerStateChange]);
302
- useEffect(() => {
303
- onImagesStateChange?.(state.attachedImages);
304
- }, [state.attachedImages, onImagesStateChange]);
305
- // Keep the shared overlay-active flag in sync so App's Ctrl+C exit handler
306
- // can defer to the /btw overlay (ink runs ALL useInput handlers per keypress
307
- // with no propagation control).
308
- useEffect(() => {
309
- btwOverlayActiveRef.current =
310
- state.btwState.question !== "" || state.btwState.answer !== undefined;
311
- }, [state.btwState.question, state.btwState.answer]);
312
- // Methods
313
- const insertTextAtCursor = useCallback((text) => {
314
- dispatch({ type: "INSERT_TEXT", payload: text });
315
- }, []);
316
- const deleteCharAtCursor = useCallback(() => {
317
- dispatch({ type: "DELETE_CHAR" });
318
- }, []);
319
- const clearInput = useCallback(() => {
320
- dispatch({ type: "CLEAR_INPUT" });
321
- }, []);
322
- const moveCursorLeft = useCallback(() => {
323
- dispatch({ type: "MOVE_CURSOR", payload: -1 });
324
- }, []);
325
- const moveCursorRight = useCallback(() => {
326
- dispatch({ type: "MOVE_CURSOR", payload: 1 });
327
- }, []);
328
- const activateFileSelector = useCallback((position) => {
329
- dispatch({ type: "ACTIVATE_FILE_SELECTOR", payload: position });
330
- }, []);
331
- const handleFileSelect = useCallback((filePath) => {
332
- dispatch({ type: "SELECT_FILE", payload: filePath });
333
- }, []);
334
- const handleCancelFileSelect = useCallback(() => {
335
- dispatch({ type: "CANCEL_FILE_SELECTOR" });
336
- }, []);
337
- const updateFileSearchQuery = useCallback((query) => {
338
- dispatch({ type: "SET_FILE_SEARCH_QUERY", payload: query });
339
- }, []);
340
- const checkForAtDeletion = useCallback((cursorPos) => {
341
- // This is now largely handled inside HANDLE_KEY,
342
- // but kept for external calls if any.
343
- return handlers.checkForAtDeletion(state, dispatch, cursorPos);
344
- }, [state]);
345
- const activateCommandSelector = useCallback((position) => {
346
- dispatch({ type: "ACTIVATE_COMMAND_SELECTOR", payload: position });
347
- }, []);
348
- const handleCommandSelect = useCallback((command) => {
349
- dispatch({ type: "SELECT_COMMAND", payload: command });
350
- }, []);
351
- const handleCommandInsert = useCallback((command) => {
352
- dispatch({ type: "INSERT_COMMAND", payload: command });
353
- }, []);
354
- const handleCancelCommandSelect = useCallback(() => {
355
- dispatch({ type: "CANCEL_COMMAND_SELECTOR" });
356
- }, []);
357
- const updateCommandSearchQuery = useCallback((query) => {
358
- dispatch({ type: "SET_COMMAND_SEARCH_QUERY", payload: query });
359
- }, []);
360
- const checkForSlashDeletion = useCallback((cursorPos) => {
361
- return handlers.checkForSlashDeletion(state, dispatch, cursorPos);
362
- }, [state]);
363
- const handleHistorySearchSelect = useCallback((entry) => {
364
- dispatch({ type: "SELECT_HISTORY_ENTRY", payload: entry });
365
- }, []);
366
- const handleCancelHistorySearch = useCallback(() => {
367
- dispatch({ type: "CANCEL_HISTORY_SEARCH" });
368
- }, []);
369
- const processSelectorInput = useCallback((char) => {
370
- handlers.processSelectorInput(state, dispatch, char);
371
- }, [state]);
372
- const setInputText = useCallback((text) => {
373
- dispatch({ type: "SET_INPUT_TEXT", payload: text });
374
- }, []);
375
- const setCursorPosition = useCallback((position) => {
376
- dispatch({ type: "SET_CURSOR_POSITION", payload: position });
377
- }, []);
378
- const setShowBackgroundTaskManager = useCallback((show) => {
379
- dispatch({ type: "SET_SHOW_BACKGROUND_TASK_MANAGER", payload: show });
380
- }, []);
381
- const setShowMcpManager = useCallback((show) => {
382
- dispatch({ type: "SET_SHOW_MCP_MANAGER", payload: show });
383
- }, []);
384
- const setShowAgentsManager = useCallback((show) => {
385
- dispatch({ type: "SET_SHOW_AGENTS_MANAGER", payload: show });
386
- }, []);
387
- const setShowRewindManager = useCallback((show) => {
388
- dispatch({ type: "SET_SHOW_REWIND_MANAGER", payload: show });
389
- }, []);
390
- const setShowHelp = useCallback((show) => {
391
- dispatch({ type: "SET_SHOW_HELP", payload: show });
392
- }, []);
393
- const setShowStatusCommand = useCallback((show) => {
394
- dispatch({ type: "SET_SHOW_STATUS_COMMAND", payload: show });
395
- }, []);
396
- const setShowLoginCommand = useCallback((show) => {
397
- dispatch({ type: "SET_SHOW_LOGIN_COMMAND", payload: show });
398
- }, []);
399
- const setShowPluginManager = useCallback((show) => {
400
- dispatch({ type: "SET_SHOW_PLUGIN_MANAGER", payload: show });
401
- }, []);
402
- const setShowModelSelector = useCallback((show) => {
403
- dispatch({ type: "SET_SHOW_MODEL_SELECTOR", payload: show });
404
- }, []);
405
- const setShowWorkflowManager = useCallback((show) => {
406
- dispatch({ type: "SET_SHOW_WORKFLOW_MANAGER", payload: show });
407
- }, []);
408
- const setPermissionMode = useCallback((mode) => {
409
- dispatch({ type: "SET_PERMISSION_MODE", payload: mode });
410
- onPermissionModeChange?.(mode);
411
- }, [onPermissionModeChange]);
412
- const setBtwState = useCallback((payload) => {
413
- dispatch({ type: "SET_BTW_STATE", payload });
414
- }, []);
415
- const addImage = useCallback((imagePath, mimeType) => {
416
- dispatch({ type: "ADD_IMAGE", payload: { path: imagePath, mimeType } });
417
- }, []);
418
- const removeImage = useCallback((imageId) => {
419
- dispatch({ type: "REMOVE_IMAGE", payload: imageId });
420
- }, []);
421
- const clearImages = useCallback(() => {
422
- dispatch({ type: "CLEAR_IMAGES" });
423
- }, []);
424
- const handlePasteImage = useCallback(async () => {
425
- return await handlers.handlePasteImage(dispatch);
426
- }, []);
427
- const handlePasteInput = useCallback((input) => {
428
- dispatch({
429
- type: "HANDLE_KEY",
430
- payload: {
431
- input,
432
- key: {},
433
- hasSlashCommand: (cmd) => !!onHasSlashCommand?.(cmd),
434
- hasQueuedMessages: hasQueuedMessagesProp ?? false,
435
- isIdle: isIdleProp ?? false,
436
- },
437
- });
438
- }, [onHasSlashCommand, hasQueuedMessagesProp, isIdleProp]);
439
- const handleSubmit = useCallback(async () => {
440
- dispatch({
441
- type: "HANDLE_KEY",
442
- payload: {
443
- input: "",
444
- key: { return: true },
445
- hasSlashCommand: (cmd) => !!onHasSlashCommand?.(cmd),
446
- hasQueuedMessages: hasQueuedMessagesProp ?? false,
447
- isIdle: isIdleProp ?? false,
448
- },
449
- });
450
- }, [onHasSlashCommand, hasQueuedMessagesProp, isIdleProp]);
451
- const expandLongTextPlaceholders = useCallback((text) => {
452
- return handlers.expandLongTextPlaceholders(text, state.longTextMap);
453
- }, [state.longTextMap]);
454
- const clearLongTextMap = useCallback(() => {
455
- dispatch({ type: "CLEAR_LONG_TEXT_MAP" });
456
- }, []);
457
- const handleInput = useCallback(async (input, key) => {
458
- const result = pasteDetectorRef.current.process(input);
459
- if (result.kind === "consume") {
460
- // Content of an in-flight bracketed paste (or an empty paste):
461
- // hold it, never submit or insert prematurely.
462
- return true;
463
- }
464
- if (result.kind === "paste") {
465
- if (result.leadingInput) {
466
- dispatch({
467
- type: "HANDLE_KEY",
468
- payload: {
469
- input: result.leadingInput,
470
- key,
471
- hasSlashCommand: (cmd) => !!onHasSlashCommand?.(cmd),
472
- hasQueuedMessages: hasQueuedMessagesProp ?? false,
473
- isIdle: isIdleProp ?? false,
474
- },
475
- });
476
- }
477
- if (result.text !== "") {
478
- // Insert-only: \r → \n normalizes CRLF terminals, matching the
479
- // canonical paste path (inputHandlers.handlePasteInput).
480
- dispatch({
481
- type: "INSERT_TEXT_WITH_PLACEHOLDER",
482
- payload: result.text.replace(/\r/g, "\n"),
483
- });
484
- }
485
- return true;
486
- }
487
- dispatch({
488
- type: "HANDLE_KEY",
489
- payload: {
490
- input: result.input,
491
- key,
492
- hasSlashCommand: (cmd) => !!onHasSlashCommand?.(cmd),
493
- hasQueuedMessages: hasQueuedMessagesProp ?? false,
494
- isIdle: isIdleProp ?? false,
495
- },
496
- });
497
- return true;
498
- }, [onHasSlashCommand, hasQueuedMessagesProp, isIdleProp]);
499
- return {
500
- // State
501
- inputText: state.inputText,
502
- cursorPosition: state.cursorPosition,
503
- showFileSelector: state.showFileSelector,
504
- filteredFiles: state.filteredFiles,
505
- fileSearchQuery: state.fileSearchQuery,
506
- isFileSearching: state.isFileSearching,
507
- atPosition: state.atPosition,
508
- showCommandSelector: state.showCommandSelector,
509
- commandSearchQuery: state.commandSearchQuery,
510
- slashPosition: state.slashPosition,
511
- showHistorySearch: state.showHistorySearch,
512
- historySearchQuery: state.historySearchQuery,
513
- showBackgroundTaskManager: state.showBackgroundTaskManager,
514
- showMcpManager: state.showMcpManager,
515
- showAgentsManager: state.showAgentsManager,
516
- showRewindManager: state.showRewindManager,
517
- showHelp: state.showHelp,
518
- showStatusCommand: state.showStatusCommand,
519
- showLoginCommand: state.showLoginCommand,
520
- showPluginManager: state.showPluginManager,
521
- showModelSelector: state.showModelSelector,
522
- showWorkflowManager: state.showWorkflowManager,
523
- permissionMode: state.permissionMode,
524
- attachedImages: state.attachedImages,
525
- btwState: state.btwState,
526
- escClearPending: state.escClearPending,
527
- isManagerReady: true,
528
- // Methods
529
- insertTextAtCursor,
530
- deleteCharAtCursor,
531
- clearInput,
532
- moveCursorLeft,
533
- moveCursorRight,
534
- // File selector
535
- activateFileSelector,
536
- handleFileSelect,
537
- handleCancelFileSelect,
538
- updateFileSearchQuery,
539
- checkForAtDeletion,
540
- // Command selector
541
- activateCommandSelector,
542
- handleCommandSelect,
543
- handleCommandInsert,
544
- handleCancelCommandSelect,
545
- updateCommandSearchQuery,
546
- checkForSlashDeletion,
547
- // History search
548
- handleHistorySearchSelect,
549
- handleCancelHistorySearch,
550
- // Special handling
551
- processSelectorInput,
552
- // Bash/MCP Manager
553
- setShowBackgroundTaskManager,
554
- setShowMcpManager,
555
- setShowAgentsManager,
556
- setShowRewindManager,
557
- setShowHelp,
558
- setShowStatusCommand,
559
- setShowLoginCommand,
560
- setShowPluginManager,
561
- setShowModelSelector,
562
- setShowWorkflowManager,
563
- setPermissionMode,
564
- setBtwState,
565
- // Image management
566
- addImage,
567
- removeImage,
568
- clearImages,
569
- handlePasteImage,
570
- // Paste and text handling
571
- handlePasteInput,
572
- handleSubmit,
573
- expandLongTextPlaceholders,
574
- clearLongTextMap,
575
- // Main input handler
576
- handleInput,
577
- // Direct state setters
578
- setInputText,
579
- setCursorPosition,
580
- // Manager reference (for compatibility, though it's null now)
581
- manager: null,
582
- };
583
- };
@@ -1,4 +0,0 @@
1
- import { PluginManagerContextType } from "../components/PluginManagerTypes.js";
2
- export declare function usePluginManager(options?: {
3
- onPluginInstalled?: () => void;
4
- }): PluginManagerContextType;