wave-code 1.0.10 → 1.1.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.
Files changed (248) hide show
  1. package/bin/wave-code.js +8 -2
  2. package/dist/bundle/wave.mjs +3231 -0
  3. package/package.json +24 -25
  4. package/src/cli.tsx +6 -1
  5. package/src/commands/update.ts +2 -7
  6. package/src/components/App.tsx +3 -7
  7. package/src/components/BtwDisplay.tsx +10 -1
  8. package/src/components/ChatInterface.tsx +21 -52
  9. package/src/components/ConfirmationDetails.tsx +144 -37
  10. package/src/components/DiffDisplay.tsx +335 -301
  11. package/src/components/InputBox.tsx +17 -2
  12. package/src/components/LoadingIndicator.tsx +16 -2
  13. package/src/components/MessageBlockItem.tsx +2 -4
  14. package/src/components/MessageList.tsx +75 -14
  15. package/src/components/ReasoningDisplay.tsx +2 -4
  16. package/src/components/SessionSelector.tsx +82 -11
  17. package/src/components/SkillsManager.tsx +312 -0
  18. package/src/components/StatusCommand.tsx +2 -9
  19. package/src/components/ToolDisplay.tsx +2 -4
  20. package/src/constants/commands.ts +6 -0
  21. package/src/contexts/useChat.tsx +245 -301
  22. package/src/daemon/commands.ts +57 -27
  23. package/src/daemon/jsonRpcClient.ts +1 -1
  24. package/src/daemon/socketClient.ts +2 -2
  25. package/src/hooks/useInputManager.ts +7 -1
  26. package/src/index.ts +57 -10
  27. package/src/managers/inputHandlers.ts +2 -0
  28. package/src/managers/inputReducer.ts +195 -104
  29. package/src/print-cli.ts +25 -17
  30. package/src/reducers/selectorReducer.ts +10 -0
  31. package/src/reducers/skillsManagerReducer.ts +91 -0
  32. package/src/session-selector-cli.tsx +269 -28
  33. package/src/stdio/agentBridge.ts +30 -21
  34. package/src/stdio/daemonServer.ts +3 -1
  35. package/src/stdio/protocol.ts +2 -0
  36. package/src/utils/clipboard.ts +21 -0
  37. package/src/utils/highlightUtils.ts +46 -1
  38. package/src/utils/readPackageJson.ts +29 -0
  39. package/src/utils/streamingText.ts +11 -0
  40. package/src/utils/worktree.ts +191 -43
  41. package/dist/cli.d.ts +0 -6
  42. package/dist/cli.js +0 -53
  43. package/dist/commands/plugin/disable.d.ts +0 -5
  44. package/dist/commands/plugin/disable.js +0 -15
  45. package/dist/commands/plugin/enable.d.ts +0 -5
  46. package/dist/commands/plugin/enable.js +0 -15
  47. package/dist/commands/plugin/install.d.ts +0 -5
  48. package/dist/commands/plugin/install.js +0 -21
  49. package/dist/commands/plugin/list.d.ts +0 -1
  50. package/dist/commands/plugin/list.js +0 -31
  51. package/dist/commands/plugin/marketplace.d.ts +0 -10
  52. package/dist/commands/plugin/marketplace.js +0 -90
  53. package/dist/commands/plugin/uninstall.d.ts +0 -3
  54. package/dist/commands/plugin/uninstall.js +0 -16
  55. package/dist/commands/plugin/update.d.ts +0 -3
  56. package/dist/commands/plugin/update.js +0 -15
  57. package/dist/commands/update.d.ts +0 -1
  58. package/dist/commands/update.js +0 -97
  59. package/dist/components/AgentsManager.d.ts +0 -7
  60. package/dist/components/AgentsManager.js +0 -109
  61. package/dist/components/App.d.ts +0 -9
  62. package/dist/components/App.js +0 -76
  63. package/dist/components/BackgroundTaskManager.d.ts +0 -5
  64. package/dist/components/BackgroundTaskManager.js +0 -99
  65. package/dist/components/BangDisplay.d.ts +0 -8
  66. package/dist/components/BangDisplay.js +0 -17
  67. package/dist/components/BtwDisplay.d.ts +0 -7
  68. package/dist/components/BtwDisplay.js +0 -19
  69. package/dist/components/ChatInterface.d.ts +0 -2
  70. package/dist/components/ChatInterface.js +0 -61
  71. package/dist/components/CommandSelector.d.ts +0 -10
  72. package/dist/components/CommandSelector.js +0 -66
  73. package/dist/components/CompactDisplay.d.ts +0 -8
  74. package/dist/components/CompactDisplay.js +0 -13
  75. package/dist/components/ConfirmationDetails.d.ts +0 -9
  76. package/dist/components/ConfirmationDetails.js +0 -45
  77. package/dist/components/ConfirmationSelector.d.ts +0 -13
  78. package/dist/components/ConfirmationSelector.js +0 -127
  79. package/dist/components/DiffDisplay.d.ts +0 -8
  80. package/dist/components/DiffDisplay.js +0 -201
  81. package/dist/components/DiscoverView.d.ts +0 -2
  82. package/dist/components/DiscoverView.js +0 -37
  83. package/dist/components/FileSelector.d.ts +0 -11
  84. package/dist/components/FileSelector.js +0 -50
  85. package/dist/components/HelpView.d.ts +0 -7
  86. package/dist/components/HelpView.js +0 -74
  87. package/dist/components/HistorySearch.d.ts +0 -8
  88. package/dist/components/HistorySearch.js +0 -66
  89. package/dist/components/InputBox.d.ts +0 -24
  90. package/dist/components/InputBox.js +0 -149
  91. package/dist/components/InstalledView.d.ts +0 -2
  92. package/dist/components/InstalledView.js +0 -45
  93. package/dist/components/LoadingIndicator.d.ts +0 -10
  94. package/dist/components/LoadingIndicator.js +0 -6
  95. package/dist/components/LoginCommand.d.ts +0 -5
  96. package/dist/components/LoginCommand.js +0 -153
  97. package/dist/components/Markdown.d.ts +0 -5
  98. package/dist/components/Markdown.js +0 -127
  99. package/dist/components/MarketplaceAddForm.d.ts +0 -2
  100. package/dist/components/MarketplaceAddForm.js +0 -55
  101. package/dist/components/MarketplaceDetail.d.ts +0 -2
  102. package/dist/components/MarketplaceDetail.js +0 -74
  103. package/dist/components/MarketplaceList.d.ts +0 -8
  104. package/dist/components/MarketplaceList.js +0 -17
  105. package/dist/components/MarketplaceView.d.ts +0 -2
  106. package/dist/components/MarketplaceView.js +0 -41
  107. package/dist/components/McpManager.d.ts +0 -9
  108. package/dist/components/McpManager.js +0 -88
  109. package/dist/components/MessageBlockItem.d.ts +0 -8
  110. package/dist/components/MessageBlockItem.js +0 -15
  111. package/dist/components/MessageList.d.ts +0 -10
  112. package/dist/components/MessageList.js +0 -80
  113. package/dist/components/ModelSelector.d.ts +0 -8
  114. package/dist/components/ModelSelector.js +0 -45
  115. package/dist/components/Notifications.d.ts +0 -7
  116. package/dist/components/Notifications.js +0 -9
  117. package/dist/components/PlanDisplay.d.ts +0 -7
  118. package/dist/components/PlanDisplay.js +0 -6
  119. package/dist/components/PluginDetail.d.ts +0 -2
  120. package/dist/components/PluginDetail.js +0 -87
  121. package/dist/components/PluginList.d.ts +0 -13
  122. package/dist/components/PluginList.js +0 -15
  123. package/dist/components/PluginManagerShell.d.ts +0 -6
  124. package/dist/components/PluginManagerShell.js +0 -92
  125. package/dist/components/PluginManagerTypes.d.ts +0 -35
  126. package/dist/components/PluginManagerTypes.js +0 -1
  127. package/dist/components/QueuedMessageList.d.ts +0 -2
  128. package/dist/components/QueuedMessageList.js +0 -18
  129. package/dist/components/ReasoningDisplay.d.ts +0 -8
  130. package/dist/components/ReasoningDisplay.js +0 -13
  131. package/dist/components/RewindCommand.d.ts +0 -12
  132. package/dist/components/RewindCommand.js +0 -78
  133. package/dist/components/SessionSelector.d.ts +0 -12
  134. package/dist/components/SessionSelector.js +0 -47
  135. package/dist/components/StatusCommand.d.ts +0 -5
  136. package/dist/components/StatusCommand.js +0 -28
  137. package/dist/components/StatusLine.d.ts +0 -6
  138. package/dist/components/StatusLine.js +0 -9
  139. package/dist/components/TaskList.d.ts +0 -5
  140. package/dist/components/TaskList.js +0 -197
  141. package/dist/components/TaskNotificationMessage.d.ts +0 -5
  142. package/dist/components/TaskNotificationMessage.js +0 -12
  143. package/dist/components/ToolDisplay.d.ts +0 -9
  144. package/dist/components/ToolDisplay.js +0 -55
  145. package/dist/components/WorkflowManager.d.ts +0 -5
  146. package/dist/components/WorkflowManager.js +0 -102
  147. package/dist/components/WorktreeExitPrompt.d.ts +0 -12
  148. package/dist/components/WorktreeExitPrompt.js +0 -35
  149. package/dist/constants/commands.d.ts +0 -2
  150. package/dist/constants/commands.js +0 -92
  151. package/dist/contexts/PluginManagerContext.d.ts +0 -3
  152. package/dist/contexts/PluginManagerContext.js +0 -9
  153. package/dist/contexts/useAppConfig.d.ts +0 -10
  154. package/dist/contexts/useAppConfig.js +0 -13
  155. package/dist/contexts/useChat.d.ts +0 -101
  156. package/dist/contexts/useChat.js +0 -993
  157. package/dist/contracts/status.d.ts +0 -7
  158. package/dist/contracts/status.js +0 -1
  159. package/dist/daemon/commands.d.ts +0 -49
  160. package/dist/daemon/commands.js +0 -341
  161. package/dist/daemon/jsonRpcClient.d.ts +0 -38
  162. package/dist/daemon/jsonRpcClient.js +0 -129
  163. package/dist/daemon/socketClient.d.ts +0 -13
  164. package/dist/daemon/socketClient.js +0 -26
  165. package/dist/daemon-cli.d.ts +0 -10
  166. package/dist/daemon-cli.js +0 -15
  167. package/dist/hooks/useInputManager.d.ts +0 -75
  168. package/dist/hooks/useInputManager.js +0 -583
  169. package/dist/hooks/usePluginManager.d.ts +0 -4
  170. package/dist/hooks/usePluginManager.js +0 -265
  171. package/dist/hooks/useTasks.d.ts +0 -1
  172. package/dist/hooks/useTasks.js +0 -5
  173. package/dist/index.d.ts +0 -4
  174. package/dist/index.js +0 -447
  175. package/dist/managers/inputHandlers.d.ts +0 -30
  176. package/dist/managers/inputHandlers.js +0 -625
  177. package/dist/managers/inputReducer.d.ts +0 -271
  178. package/dist/managers/inputReducer.js +0 -1121
  179. package/dist/plugin-manager-cli.d.ts +0 -5
  180. package/dist/plugin-manager-cli.js +0 -12
  181. package/dist/print-cli.d.ts +0 -10
  182. package/dist/print-cli.js +0 -209
  183. package/dist/reducers/agentsManagerReducer.d.ts +0 -26
  184. package/dist/reducers/agentsManagerReducer.js +0 -54
  185. package/dist/reducers/backgroundTaskManagerReducer.d.ts +0 -62
  186. package/dist/reducers/backgroundTaskManagerReducer.js +0 -106
  187. package/dist/reducers/confirmationReducer.d.ts +0 -37
  188. package/dist/reducers/confirmationReducer.js +0 -193
  189. package/dist/reducers/helpSelectorReducer.d.ts +0 -25
  190. package/dist/reducers/helpSelectorReducer.js +0 -52
  191. package/dist/reducers/marketplaceAddFormReducer.d.ts +0 -24
  192. package/dist/reducers/marketplaceAddFormReducer.js +0 -58
  193. package/dist/reducers/mcpManagerReducer.d.ts +0 -37
  194. package/dist/reducers/mcpManagerReducer.js +0 -74
  195. package/dist/reducers/pluginDetailReducer.d.ts +0 -32
  196. package/dist/reducers/pluginDetailReducer.js +0 -70
  197. package/dist/reducers/questionReducer.d.ts +0 -82
  198. package/dist/reducers/questionReducer.js +0 -375
  199. package/dist/reducers/rewindSelectorReducer.d.ts +0 -21
  200. package/dist/reducers/rewindSelectorReducer.js +0 -37
  201. package/dist/reducers/selectorReducer.d.ts +0 -23
  202. package/dist/reducers/selectorReducer.js +0 -42
  203. package/dist/reducers/workflowManagerReducer.d.ts +0 -40
  204. package/dist/reducers/workflowManagerReducer.js +0 -100
  205. package/dist/session-selector-cli.d.ts +0 -3
  206. package/dist/session-selector-cli.js +0 -25
  207. package/dist/stdio/agentBridge.d.ts +0 -139
  208. package/dist/stdio/agentBridge.js +0 -999
  209. package/dist/stdio/daemonServer.d.ts +0 -67
  210. package/dist/stdio/daemonServer.js +0 -191
  211. package/dist/stdio/index.d.ts +0 -5
  212. package/dist/stdio/index.js +0 -5
  213. package/dist/stdio/jsonRpcConnection.d.ts +0 -39
  214. package/dist/stdio/jsonRpcConnection.js +0 -135
  215. package/dist/stdio/protocol.d.ts +0 -41
  216. package/dist/stdio/protocol.js +0 -26
  217. package/dist/stdio/stdioServer.d.ts +0 -36
  218. package/dist/stdio/stdioServer.js +0 -51
  219. package/dist/stdio-cli.d.ts +0 -8
  220. package/dist/stdio-cli.js +0 -15
  221. package/dist/types.d.ts +0 -20
  222. package/dist/types.js +0 -1
  223. package/dist/utils/bracketedPaste.d.ts +0 -39
  224. package/dist/utils/bracketedPaste.js +0 -122
  225. package/dist/utils/clipboard.d.ts +0 -21
  226. package/dist/utils/clipboard.js +0 -347
  227. package/dist/utils/constants.d.ts +0 -16
  228. package/dist/utils/constants.js +0 -18
  229. package/dist/utils/highlightUtils.d.ts +0 -1
  230. package/dist/utils/highlightUtils.js +0 -93
  231. package/dist/utils/inputUtils.d.ts +0 -17
  232. package/dist/utils/inputUtils.js +0 -67
  233. package/dist/utils/logger.d.ts +0 -71
  234. package/dist/utils/logger.js +0 -259
  235. package/dist/utils/markdownTable.d.ts +0 -34
  236. package/dist/utils/markdownTable.js +0 -302
  237. package/dist/utils/rewindCheckpoints.d.ts +0 -8
  238. package/dist/utils/rewindCheckpoints.js +0 -17
  239. package/dist/utils/throttle.d.ts +0 -14
  240. package/dist/utils/throttle.js +0 -55
  241. package/dist/utils/toolParameterTransforms.d.ts +0 -18
  242. package/dist/utils/toolParameterTransforms.js +0 -73
  243. package/dist/utils/usageSummary.d.ts +0 -28
  244. package/dist/utils/usageSummary.js +0 -121
  245. package/dist/utils/version.d.ts +0 -1
  246. package/dist/utils/version.js +0 -4
  247. package/dist/utils/worktree.d.ts +0 -35
  248. 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;