wave-code 0.13.5 → 0.14.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 (31) hide show
  1. package/dist/components/ChatInterface.d.ts.map +1 -1
  2. package/dist/components/ChatInterface.js +1 -1
  3. package/dist/components/ConfirmationSelector.d.ts +0 -1
  4. package/dist/components/ConfirmationSelector.d.ts.map +1 -1
  5. package/dist/components/ConfirmationSelector.js +111 -259
  6. package/dist/components/MessageList.d.ts.map +1 -1
  7. package/dist/components/MessageList.js +4 -6
  8. package/dist/components/TaskNotificationMessage.js +1 -1
  9. package/dist/contexts/useChat.d.ts.map +1 -1
  10. package/dist/contexts/useChat.js +3 -4
  11. package/dist/managers/inputHandlers.d.ts.map +1 -1
  12. package/dist/managers/inputHandlers.js +6 -9
  13. package/dist/managers/inputReducer.d.ts +6 -0
  14. package/dist/managers/inputReducer.d.ts.map +1 -1
  15. package/dist/managers/inputReducer.js +15 -0
  16. package/dist/reducers/confirmationReducer.d.ts +26 -0
  17. package/dist/reducers/confirmationReducer.d.ts.map +1 -0
  18. package/dist/reducers/confirmationReducer.js +45 -0
  19. package/dist/reducers/questionReducer.d.ts +69 -0
  20. package/dist/reducers/questionReducer.d.ts.map +1 -0
  21. package/dist/reducers/questionReducer.js +195 -0
  22. package/package.json +2 -2
  23. package/src/components/ChatInterface.tsx +0 -1
  24. package/src/components/ConfirmationSelector.tsx +122 -304
  25. package/src/components/MessageList.tsx +10 -14
  26. package/src/components/TaskNotificationMessage.tsx +1 -1
  27. package/src/contexts/useChat.tsx +3 -4
  28. package/src/managers/inputHandlers.ts +6 -8
  29. package/src/managers/inputReducer.ts +19 -0
  30. package/src/reducers/confirmationReducer.ts +74 -0
  31. package/src/reducers/questionReducer.ts +251 -0
@@ -1 +1 @@
1
- {"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAa3D,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAgIjC,CAAC"}
1
+ {"version":3,"file":"ChatInterface.d.ts","sourceRoot":"","sources":["../../src/components/ChatInterface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAa3D,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EA+HjC,CAAC"}
@@ -37,5 +37,5 @@ export const ChatInterface = () => {
37
37
  ]);
38
38
  if (!sessionId)
39
39
  return null;
40
- return (_jsxs(Box, { ref: chatInterfaceRef, flexDirection: "column", children: [_jsx(MessageList, { messages: displayMessages, isExpanded: isExpanded, version: version, workdir: workdir, forceStatic: forceStatic }, remountKey), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [(isLoading || isCommandRunning || isCompressing) && (_jsx(LoadingIndicator, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompressing: isCompressing, latestTotalTokens: latestTotalTokens })), _jsx(TaskList, {}), _jsx(QueuedMessageList, {}), _jsx(InputBox, { isLoading: isLoading, isCommandRunning: isCommandRunning, sendMessage: sendMessage, abortMessage: abortMessage, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand })] })), isConfirmationVisible && (_jsxs(_Fragment, { children: [forceStatic ? (_jsx(Static, { items: [{ key: "confirmation-details" }], children: () => (_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded }, "confirmation-details")) })) : (_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded })), _jsx(ConfirmationSelector, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: handleConfirmationDecision, onCancel: handleConfirmationCancel, onAbort: abortMessage })] }))] }));
40
+ return (_jsxs(Box, { ref: chatInterfaceRef, flexDirection: "column", children: [_jsx(MessageList, { messages: displayMessages, isExpanded: isExpanded, version: version, workdir: workdir, forceStatic: forceStatic }, remountKey), !isConfirmationVisible && !isExpanded && (_jsxs(_Fragment, { children: [(isLoading || isCommandRunning || isCompressing) && (_jsx(LoadingIndicator, { isLoading: isLoading, isCommandRunning: isCommandRunning, isCompressing: isCompressing, latestTotalTokens: latestTotalTokens })), _jsx(TaskList, {}), _jsx(QueuedMessageList, {}), _jsx(InputBox, { isLoading: isLoading, isCommandRunning: isCommandRunning, sendMessage: sendMessage, abortMessage: abortMessage, mcpServers: mcpServers, connectMcpServer: connectMcpServer, disconnectMcpServer: disconnectMcpServer, slashCommands: slashCommands, hasSlashCommand: hasSlashCommand })] })), isConfirmationVisible && (_jsxs(_Fragment, { children: [forceStatic ? (_jsx(Static, { items: [{ key: "confirmation-details" }], children: () => (_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded }, "confirmation-details")) })) : (_jsx(ConfirmationDetails, { toolName: confirmingTool.name, toolInput: confirmingTool.input, planContent: confirmingTool.planContent, isExpanded: isExpanded })), _jsx(ConfirmationSelector, { toolName: confirmingTool.name, toolInput: confirmingTool.input, suggestedPrefix: confirmingTool.suggestedPrefix, hidePersistentOption: confirmingTool.hidePersistentOption, isExpanded: isExpanded, onDecision: handleConfirmationDecision, onCancel: handleConfirmationCancel })] }))] }));
41
41
  };
@@ -8,7 +8,6 @@ export interface ConfirmationSelectorProps {
8
8
  isExpanded?: boolean;
9
9
  onDecision: (decision: PermissionDecision) => void;
10
10
  onCancel: () => void;
11
- onAbort: () => void;
12
11
  }
13
12
  export declare const ConfirmationSelector: React.FC<ConfirmationSelectorProps>;
14
13
  //# sourceMappingURL=ConfirmationSelector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ConfirmationSelector.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAwB,MAAM,gBAAgB,CAAC;AAiB/E,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACnD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AASD,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CA6nBpE,CAAC"}
1
+ {"version":3,"file":"ConfirmationSelector.d.ts","sourceRoot":"","sources":["../../src/components/ConfirmationSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAErD,OAAO,KAAK,EAAE,kBAAkB,EAAwB,MAAM,gBAAgB,CAAC;AAsB/E,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACnD,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CA0cpE,CAAC"}
@@ -1,7 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect, useRef, useState } from "react";
2
+ import { useEffect, useReducer } from "react";
3
3
  import { Box, Text, useInput } from "ink";
4
4
  import { BASH_TOOL_NAME, EXIT_PLAN_MODE_TOOL_NAME, ENTER_PLAN_MODE_TOOL_NAME, ASK_USER_QUESTION_TOOL_NAME, } from "wave-agent-sdk";
5
+ import { confirmationReducer, } from "../reducers/confirmationReducer.js";
6
+ import { questionReducer } from "../reducers/questionReducer.js";
5
7
  const getHeaderColor = (header) => {
6
8
  const colors = ["red", "green", "blue", "magenta", "cyan"];
7
9
  let hash = 0;
@@ -10,14 +12,16 @@ const getHeaderColor = (header) => {
10
12
  }
11
13
  return colors[Math.abs(hash) % colors.length];
12
14
  };
13
- export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hidePersistentOption, isExpanded = false, onDecision, onCancel, onAbort, }) => {
14
- const [state, setState] = useState({
15
+ export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hidePersistentOption, isExpanded = false, onDecision, onCancel, }) => {
16
+ const [state, dispatch] = useReducer(confirmationReducer, {
15
17
  selectedOption: toolName === EXIT_PLAN_MODE_TOOL_NAME ? "clear" : "allow",
16
18
  alternativeText: "",
17
19
  alternativeCursorPosition: 0,
18
20
  hasUserInput: false,
21
+ decision: null,
19
22
  });
20
- const [questionState, setQuestionState] = useState({
23
+ const questions = toolInput?.questions || [];
24
+ const [questionState, questionDispatch] = useReducer(questionReducer, {
21
25
  currentQuestionIndex: 0,
22
26
  selectedOptionIndex: 0,
23
27
  selectedOptionIndices: new Set(),
@@ -25,16 +29,19 @@ export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hid
25
29
  otherText: "",
26
30
  otherCursorPosition: 0,
27
31
  savedStates: {},
32
+ decision: null,
28
33
  });
29
- const pendingDecisionRef = useRef(null);
34
+ // Handle decisions from reducers
30
35
  useEffect(() => {
31
- if (pendingDecisionRef.current) {
32
- const decision = pendingDecisionRef.current;
33
- pendingDecisionRef.current = null;
34
- onDecision(decision);
36
+ if (state.decision) {
37
+ onDecision(state.decision);
35
38
  }
36
- });
37
- const questions = toolInput?.questions || [];
39
+ }, [state.decision, onDecision]);
40
+ useEffect(() => {
41
+ if (questionState.decision) {
42
+ onDecision(questionState.decision);
43
+ }
44
+ }, [questionState.decision, onDecision]);
38
45
  const currentQuestion = questions[questionState.currentQuestionIndex];
39
46
  const getAutoOptionText = () => {
40
47
  if (toolName === EXIT_PLAN_MODE_TOOL_NAME) {
@@ -58,7 +65,6 @@ export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hid
58
65
  useInput((input, key) => {
59
66
  if (key.escape) {
60
67
  onCancel();
61
- onAbort();
62
68
  return;
63
69
  }
64
70
  if (toolName === ASK_USER_QUESTION_TOOL_NAME) {
@@ -67,278 +73,148 @@ export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hid
67
73
  const options = [...currentQuestion.options, { label: "Other" }];
68
74
  const isMultiSelect = currentQuestion.multiSelect;
69
75
  if (key.return) {
70
- setQuestionState((prev) => {
71
- const isOtherFocused = prev.selectedOptionIndex === options.length - 1;
72
- let answer = "";
73
- if (isMultiSelect) {
74
- const selectedLabels = Array.from(prev.selectedOptionIndices)
75
- .filter((i) => i < currentQuestion.options.length)
76
- .map((i) => currentQuestion.options[i].label);
77
- const isOtherChecked = prev.selectedOptionIndices.has(options.length - 1);
78
- if (isOtherChecked && prev.otherText.trim()) {
79
- selectedLabels.push(prev.otherText.trim());
80
- }
81
- answer = selectedLabels.join(", ");
82
- }
83
- else {
84
- if (isOtherFocused) {
85
- answer = prev.otherText.trim();
86
- }
87
- else {
88
- answer = options[prev.selectedOptionIndex].label;
89
- }
90
- }
91
- if (!answer)
92
- return prev;
93
- const newAnswers = {
94
- ...prev.userAnswers,
95
- [currentQuestion.question]: answer,
96
- };
97
- if (prev.currentQuestionIndex < questions.length - 1) {
98
- const nextIndex = prev.currentQuestionIndex + 1;
99
- const savedStates = {
100
- ...prev.savedStates,
101
- [prev.currentQuestionIndex]: {
102
- selectedOptionIndex: prev.selectedOptionIndex,
103
- selectedOptionIndices: prev.selectedOptionIndices,
104
- otherText: prev.otherText,
105
- otherCursorPosition: prev.otherCursorPosition,
106
- },
107
- };
108
- const nextState = savedStates[nextIndex] || {
109
- selectedOptionIndex: 0,
110
- selectedOptionIndices: new Set(),
111
- otherText: "",
112
- otherCursorPosition: 0,
113
- };
114
- return {
115
- ...prev,
116
- currentQuestionIndex: nextIndex,
117
- ...nextState,
118
- userAnswers: newAnswers,
119
- savedStates,
120
- };
121
- }
122
- else {
123
- const finalAnswers = { ...newAnswers };
124
- // Also collect from savedStates for any questions that were skipped via Tab
125
- for (const [idxStr, s] of Object.entries(prev.savedStates)) {
126
- const idx = parseInt(idxStr);
127
- const q = questions[idx];
128
- if (q && !finalAnswers[q.question]) {
129
- const opts = [...q.options, { label: "Other" }];
130
- let a = "";
131
- if (q.multiSelect) {
132
- const selectedLabels = Array.from(s.selectedOptionIndices)
133
- .filter((i) => i < q.options.length)
134
- .map((i) => q.options[i].label);
135
- const isOtherChecked = s.selectedOptionIndices.has(opts.length - 1);
136
- if (isOtherChecked && s.otherText.trim()) {
137
- selectedLabels.push(s.otherText.trim());
138
- }
139
- a = selectedLabels.join(", ");
140
- }
141
- else {
142
- if (s.selectedOptionIndex === opts.length - 1) {
143
- a = s.otherText.trim();
144
- }
145
- else {
146
- a = opts[s.selectedOptionIndex].label;
147
- }
148
- }
149
- if (a)
150
- finalAnswers[q.question] = a;
151
- }
152
- }
153
- // Only submit if all questions have been answered
154
- const allAnswered = questions.every((q) => finalAnswers[q.question]);
155
- if (!allAnswered)
156
- return prev;
157
- pendingDecisionRef.current = {
158
- behavior: "allow",
159
- message: JSON.stringify(finalAnswers),
160
- };
161
- return {
162
- ...prev,
163
- userAnswers: finalAnswers,
164
- };
165
- }
76
+ questionDispatch({
77
+ type: "CONFIRM_ANSWER",
78
+ currentQuestion,
79
+ options,
80
+ isMultiSelect: !!isMultiSelect,
81
+ questions,
166
82
  });
167
83
  return;
168
84
  }
169
85
  if (input === " ") {
170
- setQuestionState((prev) => {
171
- const isOtherFocused = prev.selectedOptionIndex === options.length - 1;
172
- if (isMultiSelect &&
173
- (!isOtherFocused ||
174
- !prev.selectedOptionIndices.has(prev.selectedOptionIndex))) {
175
- const nextIndices = new Set(prev.selectedOptionIndices);
176
- if (nextIndices.has(prev.selectedOptionIndex))
177
- nextIndices.delete(prev.selectedOptionIndex);
178
- else
179
- nextIndices.add(prev.selectedOptionIndex);
180
- return {
181
- ...prev,
182
- selectedOptionIndices: nextIndices,
183
- };
184
- }
185
- return prev;
186
- });
86
+ const isOtherFocused = questionState.selectedOptionIndex === options.length - 1;
87
+ if (isMultiSelect &&
88
+ (!isOtherFocused ||
89
+ !questionState.selectedOptionIndices.has(questionState.selectedOptionIndex))) {
90
+ questionDispatch({
91
+ type: "TOGGLE_MULTI_SELECT",
92
+ optionsLength: options.length,
93
+ });
94
+ return;
95
+ }
187
96
  // If it's other and focused, we don't return here, allowing the input handler below to handle it
188
97
  }
189
98
  if (key.upArrow) {
190
- setQuestionState((prev) => ({
191
- ...prev,
192
- selectedOptionIndex: Math.max(0, prev.selectedOptionIndex - 1),
193
- }));
99
+ questionDispatch({
100
+ type: "MOVE_OPTION_UP",
101
+ maxIndex: options.length - 1,
102
+ });
194
103
  return;
195
104
  }
196
105
  if (key.downArrow) {
197
- setQuestionState((prev) => ({
198
- ...prev,
199
- selectedOptionIndex: Math.min(options.length - 1, prev.selectedOptionIndex + 1),
200
- }));
106
+ questionDispatch({
107
+ type: "MOVE_OPTION_DOWN",
108
+ maxIndex: options.length - 1,
109
+ });
201
110
  return;
202
111
  }
203
112
  if (key.tab) {
204
- setQuestionState((prev) => {
205
- const direction = key.shift ? -1 : 1;
206
- let nextIndex = prev.currentQuestionIndex + direction;
207
- if (nextIndex < 0)
208
- nextIndex = questions.length - 1;
209
- if (nextIndex >= questions.length)
210
- nextIndex = 0;
211
- if (nextIndex === prev.currentQuestionIndex)
212
- return prev;
213
- const savedStates = {
214
- ...prev.savedStates,
215
- [prev.currentQuestionIndex]: {
216
- selectedOptionIndex: prev.selectedOptionIndex,
217
- selectedOptionIndices: prev.selectedOptionIndices,
218
- otherText: prev.otherText,
219
- otherCursorPosition: prev.otherCursorPosition,
220
- },
221
- };
222
- const nextState = savedStates[nextIndex] || {
223
- selectedOptionIndex: 0,
224
- selectedOptionIndices: new Set(),
225
- otherText: "",
226
- otherCursorPosition: 0,
227
- };
228
- return {
229
- ...prev,
230
- currentQuestionIndex: nextIndex,
231
- ...nextState,
232
- savedStates,
233
- };
113
+ questionDispatch({
114
+ type: "CYCLE_QUESTION",
115
+ shift: key.shift,
116
+ questionCount: questions.length,
117
+ });
118
+ return;
119
+ }
120
+ // Always dispatch Other actions unconditionally; the reducer checks
121
+ // isOtherFocused from the latest state, so this works correctly even
122
+ // when inputs are batched before React re-renders.
123
+ if (key.leftArrow) {
124
+ questionDispatch({
125
+ type: "MOVE_OTHER_LEFT",
126
+ optionsLength: options.length,
127
+ });
128
+ return;
129
+ }
130
+ if (key.rightArrow) {
131
+ questionDispatch({
132
+ type: "MOVE_OTHER_RIGHT",
133
+ optionsLength: options.length,
134
+ });
135
+ return;
136
+ }
137
+ if (key.backspace || key.delete) {
138
+ questionDispatch({
139
+ type: "DELETE_OTHER",
140
+ optionsLength: options.length,
141
+ });
142
+ return;
143
+ }
144
+ if (input && !key.ctrl && !key.meta) {
145
+ questionDispatch({
146
+ type: "INSERT_OTHER",
147
+ text: input,
148
+ optionsLength: options.length,
234
149
  });
235
150
  return;
236
151
  }
237
- setQuestionState((prev) => {
238
- const isOtherFocused = prev.selectedOptionIndex === options.length - 1;
239
- if (isOtherFocused) {
240
- if (key.leftArrow) {
241
- return {
242
- ...prev,
243
- otherCursorPosition: Math.max(0, prev.otherCursorPosition - 1),
244
- };
245
- }
246
- if (key.rightArrow) {
247
- return {
248
- ...prev,
249
- otherCursorPosition: Math.min(prev.otherText.length, prev.otherCursorPosition + 1),
250
- };
251
- }
252
- if (key.backspace || key.delete) {
253
- if (prev.otherCursorPosition > 0) {
254
- return {
255
- ...prev,
256
- otherText: prev.otherText.slice(0, prev.otherCursorPosition - 1) +
257
- prev.otherText.slice(prev.otherCursorPosition),
258
- otherCursorPosition: prev.otherCursorPosition - 1,
259
- };
260
- }
261
- }
262
- if (input && !key.ctrl && !key.meta) {
263
- return {
264
- ...prev,
265
- otherText: prev.otherText.slice(0, prev.otherCursorPosition) +
266
- input +
267
- prev.otherText.slice(prev.otherCursorPosition),
268
- otherCursorPosition: prev.otherCursorPosition + input.length,
269
- };
270
- }
271
- }
272
- return prev;
273
- });
274
152
  return;
275
153
  }
276
154
  if (key.return) {
155
+ let decision = null;
277
156
  if (state.selectedOption === "clear") {
278
- onDecision({
157
+ decision = {
279
158
  behavior: "allow",
280
159
  newPermissionMode: "acceptEdits",
281
160
  clearContext: true,
282
- });
161
+ };
283
162
  }
284
163
  else if (state.selectedOption === "allow") {
285
164
  if (toolName === EXIT_PLAN_MODE_TOOL_NAME) {
286
- onDecision({ behavior: "allow", newPermissionMode: "default" });
165
+ decision = { behavior: "allow", newPermissionMode: "default" };
287
166
  }
288
167
  else if (toolName === ENTER_PLAN_MODE_TOOL_NAME) {
289
- onDecision({ behavior: "allow", newPermissionMode: "plan" });
168
+ decision = { behavior: "allow", newPermissionMode: "plan" };
290
169
  }
291
170
  else {
292
- onDecision({ behavior: "allow" });
171
+ decision = { behavior: "allow" };
293
172
  }
294
173
  }
295
174
  else if (state.selectedOption === "auto") {
296
175
  if (toolName === BASH_TOOL_NAME) {
297
176
  const command = toolInput?.command || "";
298
177
  if (command.trim().startsWith("mkdir")) {
299
- onDecision({ behavior: "allow", newPermissionMode: "acceptEdits" });
178
+ decision = { behavior: "allow", newPermissionMode: "acceptEdits" };
300
179
  }
301
180
  else {
302
181
  const rule = suggestedPrefix
303
182
  ? `Bash(${suggestedPrefix})`
304
183
  : `Bash(${toolInput?.command})`;
305
- onDecision({ behavior: "allow", newPermissionRule: rule });
184
+ decision = { behavior: "allow", newPermissionRule: rule };
306
185
  }
307
186
  }
308
187
  else if (toolName === ENTER_PLAN_MODE_TOOL_NAME) {
309
- onDecision({ behavior: "allow", newPermissionMode: "plan" });
188
+ decision = { behavior: "allow", newPermissionMode: "plan" };
310
189
  }
311
190
  else if (toolName.startsWith("mcp__")) {
312
- onDecision({ behavior: "allow", newPermissionRule: toolName });
191
+ decision = { behavior: "allow", newPermissionRule: toolName };
313
192
  }
314
193
  else {
315
- onDecision({ behavior: "allow", newPermissionMode: "acceptEdits" });
194
+ decision = { behavior: "allow", newPermissionMode: "acceptEdits" };
316
195
  }
317
196
  }
318
197
  else if (state.alternativeText.trim()) {
319
- onDecision({ behavior: "deny", message: state.alternativeText.trim() });
198
+ decision = { behavior: "deny", message: state.alternativeText.trim() };
320
199
  }
321
200
  else if (toolName === ENTER_PLAN_MODE_TOOL_NAME) {
322
- onDecision({
201
+ decision = {
323
202
  behavior: "deny",
324
203
  message: "User chose not to enter plan mode",
325
- });
204
+ };
205
+ }
206
+ if (decision) {
207
+ dispatch({ type: "CONFIRM", decision });
326
208
  }
327
209
  return;
328
210
  }
329
211
  if (state.selectedOption === "alternative") {
330
212
  if (key.leftArrow) {
331
- setState((prev) => ({
332
- ...prev,
333
- alternativeCursorPosition: Math.max(0, prev.alternativeCursorPosition - 1),
334
- }));
213
+ dispatch({ type: "MOVE_CURSOR_LEFT" });
335
214
  return;
336
215
  }
337
216
  if (key.rightArrow) {
338
- setState((prev) => ({
339
- ...prev,
340
- alternativeCursorPosition: Math.min(prev.alternativeText.length, prev.alternativeCursorPosition + 1),
341
- }));
217
+ dispatch({ type: "MOVE_CURSOR_RIGHT" });
342
218
  return;
343
219
  }
344
220
  }
@@ -352,20 +228,20 @@ export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hid
352
228
  if (key.upArrow) {
353
229
  const currentIndex = availableOptions.indexOf(state.selectedOption);
354
230
  if (currentIndex > 0) {
355
- setState((prev) => ({
356
- ...prev,
357
- selectedOption: availableOptions[currentIndex - 1],
358
- }));
231
+ dispatch({
232
+ type: "SELECT_OPTION",
233
+ option: availableOptions[currentIndex - 1],
234
+ });
359
235
  }
360
236
  return;
361
237
  }
362
238
  if (key.downArrow) {
363
239
  const currentIndex = availableOptions.indexOf(state.selectedOption);
364
240
  if (currentIndex < availableOptions.length - 1) {
365
- setState((prev) => ({
366
- ...prev,
367
- selectedOption: availableOptions[currentIndex + 1],
368
- }));
241
+ dispatch({
242
+ type: "SELECT_OPTION",
243
+ option: availableOptions[currentIndex + 1],
244
+ });
369
245
  }
370
246
  return;
371
247
  }
@@ -377,42 +253,18 @@ export const ConfirmationSelector = ({ toolName, toolInput, suggestedPrefix, hid
377
253
  nextIndex = availableOptions.length - 1;
378
254
  if (nextIndex >= availableOptions.length)
379
255
  nextIndex = 0;
380
- setState((prev) => ({
381
- ...prev,
382
- selectedOption: availableOptions[nextIndex],
383
- }));
256
+ dispatch({
257
+ type: "SELECT_OPTION",
258
+ option: availableOptions[nextIndex],
259
+ });
384
260
  return;
385
261
  }
386
262
  if (input && !key.ctrl && !key.meta && !("alt" in key && key.alt)) {
387
- setState((prev) => {
388
- const nextText = prev.alternativeText.slice(0, prev.alternativeCursorPosition) +
389
- input +
390
- prev.alternativeText.slice(prev.alternativeCursorPosition);
391
- return {
392
- ...prev,
393
- selectedOption: "alternative",
394
- alternativeText: nextText,
395
- alternativeCursorPosition: prev.alternativeCursorPosition + input.length,
396
- hasUserInput: true,
397
- };
398
- });
263
+ dispatch({ type: "INSERT_TEXT", text: input });
399
264
  return;
400
265
  }
401
266
  if (key.backspace || key.delete) {
402
- setState((prev) => {
403
- if (prev.alternativeCursorPosition > 0) {
404
- const nextText = prev.alternativeText.slice(0, prev.alternativeCursorPosition - 1) +
405
- prev.alternativeText.slice(prev.alternativeCursorPosition);
406
- return {
407
- ...prev,
408
- selectedOption: "alternative",
409
- alternativeText: nextText,
410
- alternativeCursorPosition: prev.alternativeCursorPosition - 1,
411
- hasUserInput: nextText.length > 0,
412
- };
413
- }
414
- return prev;
415
- });
267
+ dispatch({ type: "BACKSPACE" });
416
268
  return;
417
269
  }
418
270
  });
@@ -1 +1 @@
1
- {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,OAAO,EAAgB,MAAM,gBAAgB,CAAC;AAG5D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,WAAW,uFAOnB,gBAAgB,6CAqIpB,CAAC"}
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,OAAO,EAAgB,MAAM,gBAAgB,CAAC;AAG5D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,WAAW,uFAOnB,gBAAgB,6CAiIpB,CAAC"}
@@ -14,14 +14,12 @@ export const MessageList = React.memo(({ messages, isExpanded = false, forceStat
14
14
  b.stage === "streaming" ||
15
15
  b.stage === "start")) ||
16
16
  (b.type === "bang" && b.stage === "running") ||
17
- (b.type === "reasoning" && b.stage === "streaming");
17
+ (b.type === "reasoning" && b.stage === "streaming") ||
18
+ (b.type === "text" && b.stage === "streaming");
18
19
  // Flatten messages into blocks with metadata
19
- // Filter out streaming text blocks to avoid frequent height changes,
20
- // but allow streaming reasoning blocks (rendered as truncated gray text)
20
+ // Include streaming text blocks (rendered as truncated gray text)
21
21
  const allBlocks = visibleMessages.flatMap((message, messageIndex) => {
22
- return message.blocks
23
- .filter((block) => !(block.type === "text" && block.stage === "streaming"))
24
- .map((block, blockIndex) => ({
22
+ return message.blocks.map((block, blockIndex) => ({
25
23
  block,
26
24
  message,
27
25
  messageIndex,
@@ -7,5 +7,5 @@ const statusColor = {
7
7
  };
8
8
  export const TaskNotificationMessage = ({ block, }) => {
9
9
  const color = statusColor[block.status];
10
- return (_jsx(Box, { flexDirection: "column", children: _jsxs(Box, { children: [_jsx(Text, { color: color, children: "\u25CF " }), _jsx(Text, { color: "white", children: block.summary })] }) }));
10
+ return (_jsx(Box, { flexDirection: "column", children: _jsxs(Box, { children: [_jsx(Text, { color: color, children: "\u25C6 " }), _jsx(Text, { color: "white", children: block.summary })] }) }));
11
11
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/contexts/useChat.tsx"],"names":[],"mappings":"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"}
@@ -357,6 +357,7 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
357
357
  if (currentConfirmation) {
358
358
  currentConfirmation.reject();
359
359
  }
360
+ agentRef.current?.abortMessage();
360
361
  hideConfirmation();
361
362
  }, [currentConfirmation, hideConfirmation]);
362
363
  const backgroundCurrentTask = useCallback(() => {
@@ -429,10 +430,8 @@ export const ChatProvider = ({ children, bypassPermissions, permissionMode: init
429
430
  setIsTaskListVisible((prev) => !prev);
430
431
  }
431
432
  // Handle ESC key to cancel confirmation
432
- if (key.escape) {
433
- if (isConfirmationVisible) {
434
- handleConfirmationCancel();
435
- }
433
+ if (key.escape && isConfirmationVisible) {
434
+ handleConfirmationCancel();
436
435
  }
437
436
  });
438
437
  const contextValue = {
@@ -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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"}
@@ -198,15 +198,12 @@ export const handlePasteInput = (state, dispatch, callbacks, input) => {
198
198
  inputString.includes("\n") ||
199
199
  inputString.includes("\r");
200
200
  if (isPasteOperation) {
201
- if (!state.isPasting) {
202
- dispatch({
203
- type: "START_PASTE",
204
- payload: { buffer: inputString, cursorPosition: state.cursorPosition },
205
- });
206
- }
207
- else {
208
- dispatch({ type: "APPEND_PASTE_BUFFER", payload: inputString });
209
- }
201
+ // Dispatch a single action type; the reducer determines start vs append
202
+ // by checking pasteBuffer, avoiding stale state issues
203
+ dispatch({
204
+ type: "APPEND_PASTE_CHUNK",
205
+ payload: { chunk: inputString, cursorPosition: state.cursorPosition },
206
+ });
210
207
  }
211
208
  else {
212
209
  let char = inputString;