@dexto/tui 1.7.1 → 1.8.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.
- package/dist/agent-backend.cjs +16 -2
- package/dist/agent-backend.d.ts +5 -2
- package/dist/agent-backend.d.ts.map +1 -1
- package/dist/agent-backend.js +15 -2
- package/dist/agent-backend.test.cjs +28 -2
- package/dist/agent-backend.test.js +28 -2
- package/dist/components/ApprovalPrompt.cjs +6 -5
- package/dist/components/ApprovalPrompt.d.ts +1 -1
- package/dist/components/ApprovalPrompt.d.ts.map +1 -1
- package/dist/components/ApprovalPrompt.js +6 -5
- package/dist/components/TextBufferInput.cjs +14 -1
- package/dist/components/TextBufferInput.d.ts +5 -1
- package/dist/components/TextBufferInput.d.ts.map +1 -1
- package/dist/components/TextBufferInput.js +14 -1
- package/dist/components/chat/QueuedMessagesDisplay.cjs +17 -8
- package/dist/components/chat/QueuedMessagesDisplay.d.ts +7 -1
- package/dist/components/chat/QueuedMessagesDisplay.d.ts.map +1 -1
- package/dist/components/chat/QueuedMessagesDisplay.js +16 -8
- package/dist/components/input/InputArea.cjs +4 -0
- package/dist/components/input/InputArea.d.ts +5 -1
- package/dist/components/input/InputArea.d.ts.map +1 -1
- package/dist/components/input/InputArea.js +4 -0
- package/dist/components/modes/AlternateBufferCLI.cjs +20 -1
- package/dist/components/modes/AlternateBufferCLI.d.ts.map +1 -1
- package/dist/components/modes/AlternateBufferCLI.js +21 -2
- package/dist/components/modes/StaticCLI.cjs +20 -1
- package/dist/components/modes/StaticCLI.d.ts.map +1 -1
- package/dist/components/modes/StaticCLI.js +21 -2
- package/dist/components/overlays/LoginOverlay.cjs +2 -10
- package/dist/components/overlays/LoginOverlay.d.ts.map +1 -1
- package/dist/components/overlays/LoginOverlay.js +3 -11
- package/dist/containers/InputContainer.cjs +119 -18
- package/dist/containers/InputContainer.d.ts +6 -2
- package/dist/containers/InputContainer.d.ts.map +1 -1
- package/dist/containers/InputContainer.js +119 -18
- package/dist/hooks/useAgentEvents.cjs +27 -5
- package/dist/hooks/useAgentEvents.d.ts +3 -2
- package/dist/hooks/useAgentEvents.d.ts.map +1 -1
- package/dist/hooks/useAgentEvents.js +27 -5
- package/dist/hooks/useCLIState.cjs +10 -4
- package/dist/hooks/useCLIState.d.ts +2 -0
- package/dist/hooks/useCLIState.d.ts.map +1 -1
- package/dist/hooks/useCLIState.js +10 -4
- package/dist/hooks/useInputOrchestrator.cjs +15 -14
- package/dist/hooks/useInputOrchestrator.d.ts +6 -6
- package/dist/hooks/useInputOrchestrator.d.ts.map +1 -1
- package/dist/hooks/useInputOrchestrator.js +15 -14
- package/dist/host/index.cjs +6 -6
- package/dist/host/index.d.ts +8 -17
- package/dist/host/index.d.ts.map +1 -1
- package/dist/host/index.js +5 -5
- package/dist/host/index.test.cjs +47 -0
- package/dist/host/index.test.d.ts +2 -0
- package/dist/host/index.test.d.ts.map +1 -0
- package/dist/host/index.test.js +50 -0
- package/dist/index.d.cts +10 -15
- package/dist/interactive-commands/command-parser.cjs +1 -0
- package/dist/interactive-commands/command-parser.d.ts.map +1 -1
- package/dist/interactive-commands/command-parser.js +1 -0
- package/dist/interactive-commands/commands.cjs +3 -0
- package/dist/interactive-commands/commands.d.ts.map +1 -1
- package/dist/interactive-commands/commands.js +3 -0
- package/dist/interactive-commands/commands.test.cjs +42 -0
- package/dist/interactive-commands/commands.test.js +42 -0
- package/dist/interactive-commands/prompt-commands.cjs +4 -66
- package/dist/interactive-commands/prompt-commands.d.ts +1 -2
- package/dist/interactive-commands/prompt-commands.d.ts.map +1 -1
- package/dist/interactive-commands/prompt-commands.js +4 -66
- package/dist/interactive-commands/skill-commands.cjs +73 -0
- package/dist/interactive-commands/skill-commands.d.ts +9 -0
- package/dist/interactive-commands/skill-commands.d.ts.map +1 -0
- package/dist/interactive-commands/skill-commands.js +49 -0
- package/dist/services/processStream.cjs +23 -4
- package/dist/services/processStream.d.ts +3 -1
- package/dist/services/processStream.d.ts.map +1 -1
- package/dist/services/processStream.js +23 -4
- package/dist/services/processStream.test.cjs +52 -2
- package/dist/services/processStream.test.js +52 -2
- package/dist/state/initialState.cjs +2 -1
- package/dist/state/initialState.d.ts.map +1 -1
- package/dist/state/initialState.js +2 -1
- package/dist/state/reducer.cjs +10 -5
- package/dist/state/reducer.d.ts.map +1 -1
- package/dist/state/reducer.js +10 -5
- package/dist/state/types.d.ts +2 -0
- package/dist/state/types.d.ts.map +1 -1
- package/dist/utils/messageFormatting.cjs +0 -23
- package/dist/utils/messageFormatting.d.ts +0 -13
- package/dist/utils/messageFormatting.d.ts.map +1 -1
- package/dist/utils/messageFormatting.js +0 -21
- package/dist/utils/queuedComposerContent.cjs +148 -0
- package/dist/utils/queuedComposerContent.d.ts +17 -0
- package/dist/utils/queuedComposerContent.d.ts.map +1 -0
- package/dist/utils/queuedComposerContent.js +123 -0
- package/dist/utils/queuedComposerContent.test.cjs +176 -0
- package/dist/utils/queuedComposerContent.test.d.ts +2 -0
- package/dist/utils/queuedComposerContent.test.d.ts.map +1 -0
- package/dist/utils/queuedComposerContent.test.js +175 -0
- package/package.json +4 -4
|
@@ -32,13 +32,14 @@ __export(InputContainer_exports, {
|
|
|
32
32
|
});
|
|
33
33
|
module.exports = __toCommonJS(InputContainer_exports);
|
|
34
34
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
35
|
-
var import_react = require("react");
|
|
35
|
+
var import_react = __toESM(require("react"), 1);
|
|
36
36
|
var import_core = require("@dexto/core");
|
|
37
37
|
var import_InputArea = require("../components/input/InputArea.js");
|
|
38
38
|
var import_services = require("../services/index.js");
|
|
39
39
|
var import_contexts = require("../contexts/index.js");
|
|
40
40
|
var import_messageFormatting = require("../utils/messageFormatting.js");
|
|
41
41
|
var import_idGenerator = require("../utils/idGenerator.js");
|
|
42
|
+
var import_queuedComposerContent = require("../utils/queuedComposerContent.js");
|
|
42
43
|
var import_host = require("../host/index.js");
|
|
43
44
|
var import_overlayPresentation = require("../utils/overlayPresentation.js");
|
|
44
45
|
var import_agent_backend = require("../agent-backend.js");
|
|
@@ -50,6 +51,7 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
50
51
|
session,
|
|
51
52
|
initialPrompt,
|
|
52
53
|
approval,
|
|
54
|
+
steerMessages,
|
|
53
55
|
queuedMessages,
|
|
54
56
|
setInput,
|
|
55
57
|
setUi,
|
|
@@ -57,6 +59,7 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
57
59
|
setMessages,
|
|
58
60
|
setPendingMessages,
|
|
59
61
|
setDequeuedBuffer,
|
|
62
|
+
setSteerMessages,
|
|
60
63
|
setQueuedMessages,
|
|
61
64
|
setApproval,
|
|
62
65
|
setApprovalQueue,
|
|
@@ -68,6 +71,8 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
68
71
|
useStreaming = true
|
|
69
72
|
}, ref) {
|
|
70
73
|
const sessionCreationPromiseRef = (0, import_react.useRef)(null);
|
|
74
|
+
const queuedEditPendingRef = (0, import_react.useRef)(false);
|
|
75
|
+
const [isQueuedEditPending, setIsQueuedEditPending] = import_react.default.useState(false);
|
|
71
76
|
const didAutoSubmitInitialPromptRef = (0, import_react.useRef)(false);
|
|
72
77
|
const soundService = (0, import_contexts.useSoundService)();
|
|
73
78
|
const autoApproveEditsRef = (0, import_react.useRef)(ui.autoApproveEdits);
|
|
@@ -83,21 +88,81 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
83
88
|
sessionCreationPromiseRef.current = null;
|
|
84
89
|
}
|
|
85
90
|
}, [session.id]);
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
91
|
+
const popQueuedMessageForEdit = (0, import_react.useCallback)(
|
|
92
|
+
async (message, editingQueuedFollowUp, removeMessage) => {
|
|
93
|
+
if (queuedEditPendingRef.current) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const result = (0, import_queuedComposerContent.restoreQueuedContentForComposer)(message);
|
|
97
|
+
if (!result.ok) {
|
|
98
|
+
setMessages((prev) => [
|
|
99
|
+
...prev,
|
|
100
|
+
{
|
|
101
|
+
id: (0, import_idGenerator.generateMessageId)("system"),
|
|
102
|
+
role: "system",
|
|
103
|
+
content: result.reason,
|
|
104
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
105
|
+
}
|
|
106
|
+
]);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
queuedEditPendingRef.current = true;
|
|
110
|
+
setIsQueuedEditPending(true);
|
|
111
|
+
let removed = false;
|
|
112
|
+
try {
|
|
113
|
+
removed = await removeMessage();
|
|
114
|
+
if (!removed) {
|
|
115
|
+
setMessages((prev) => [
|
|
116
|
+
...prev,
|
|
117
|
+
{
|
|
118
|
+
id: (0, import_idGenerator.generateMessageId)("system"),
|
|
119
|
+
role: "system",
|
|
120
|
+
content: "Queued input could not be edited because it is no longer pending.",
|
|
121
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
122
|
+
}
|
|
123
|
+
]);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
buffer.setText(result.composer.text);
|
|
127
|
+
setInput((prev) => ({
|
|
128
|
+
...prev,
|
|
129
|
+
value: result.composer.text,
|
|
130
|
+
images: result.composer.images,
|
|
131
|
+
pastedBlocks: [],
|
|
132
|
+
historyIndex: -1,
|
|
133
|
+
draftBeforeHistory: "",
|
|
134
|
+
editingQueuedFollowUp
|
|
135
|
+
}));
|
|
136
|
+
} catch {
|
|
137
|
+
setMessages((prev) => [
|
|
138
|
+
...prev,
|
|
139
|
+
{
|
|
140
|
+
id: (0, import_idGenerator.generateMessageId)("system"),
|
|
141
|
+
role: "system",
|
|
142
|
+
content: "Queued input could not be edited. Try again.",
|
|
143
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
144
|
+
}
|
|
145
|
+
]);
|
|
146
|
+
} finally {
|
|
147
|
+
queuedEditPendingRef.current = false;
|
|
148
|
+
setIsQueuedEditPending(false);
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
[buffer, setInput, setMessages]
|
|
152
|
+
);
|
|
89
153
|
const handleHistoryNavigate = (0, import_react.useCallback)(
|
|
90
154
|
(direction) => {
|
|
91
155
|
const { history, historyIndex, draftBeforeHistory } = input;
|
|
92
156
|
if (direction === "up") {
|
|
93
157
|
if (queuedMessages.length > 0 && session.id) {
|
|
158
|
+
const sessionId = session.id;
|
|
94
159
|
const lastQueued = queuedMessages[queuedMessages.length - 1];
|
|
95
160
|
if (lastQueued) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
161
|
+
void popQueuedMessageForEdit(
|
|
162
|
+
lastQueued,
|
|
163
|
+
true,
|
|
164
|
+
() => agent.removeFollowUpMessage(sessionId, lastQueued.id)
|
|
165
|
+
);
|
|
101
166
|
return;
|
|
102
167
|
}
|
|
103
168
|
}
|
|
@@ -110,7 +175,8 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
110
175
|
...prev,
|
|
111
176
|
draftBeforeHistory: currentText,
|
|
112
177
|
historyIndex: history.length - 1,
|
|
113
|
-
value: history[history.length - 1] || ""
|
|
178
|
+
value: history[history.length - 1] || "",
|
|
179
|
+
editingQueuedFollowUp: false
|
|
114
180
|
}));
|
|
115
181
|
buffer.setText(history[history.length - 1] || "");
|
|
116
182
|
return;
|
|
@@ -121,7 +187,12 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
121
187
|
}
|
|
122
188
|
const historyItem = history[newIndex] || "";
|
|
123
189
|
buffer.setText(historyItem);
|
|
124
|
-
setInput((prev) => ({
|
|
190
|
+
setInput((prev) => ({
|
|
191
|
+
...prev,
|
|
192
|
+
value: historyItem,
|
|
193
|
+
historyIndex: newIndex,
|
|
194
|
+
editingQueuedFollowUp: false
|
|
195
|
+
}));
|
|
125
196
|
} else {
|
|
126
197
|
if (ui.isProcessing) return;
|
|
127
198
|
if (historyIndex < 0) return;
|
|
@@ -132,7 +203,8 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
132
203
|
setInput((prev) => ({
|
|
133
204
|
...prev,
|
|
134
205
|
value: historyItem,
|
|
135
|
-
historyIndex: newIndex
|
|
206
|
+
historyIndex: newIndex,
|
|
207
|
+
editingQueuedFollowUp: false
|
|
136
208
|
}));
|
|
137
209
|
} else {
|
|
138
210
|
buffer.setText(draftBeforeHistory);
|
|
@@ -140,7 +212,8 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
140
212
|
...prev,
|
|
141
213
|
value: draftBeforeHistory,
|
|
142
214
|
historyIndex: -1,
|
|
143
|
-
draftBeforeHistory: ""
|
|
215
|
+
draftBeforeHistory: "",
|
|
216
|
+
editingQueuedFollowUp: false
|
|
144
217
|
}));
|
|
145
218
|
}
|
|
146
219
|
}
|
|
@@ -152,10 +225,26 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
152
225
|
queuedMessages,
|
|
153
226
|
session.id,
|
|
154
227
|
agent,
|
|
155
|
-
|
|
228
|
+
popQueuedMessageForEdit,
|
|
156
229
|
ui.isProcessing
|
|
157
230
|
]
|
|
158
231
|
);
|
|
232
|
+
const handleCurrentTurnEdit = (0, import_react.useCallback)(() => {
|
|
233
|
+
if (steerMessages.length === 0 || !session.id) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
const lastSteer = steerMessages[steerMessages.length - 1];
|
|
237
|
+
if (!lastSteer) {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
const sessionId = session.id;
|
|
241
|
+
void popQueuedMessageForEdit(
|
|
242
|
+
lastSteer,
|
|
243
|
+
false,
|
|
244
|
+
() => agent.removeSteerMessage(sessionId, lastSteer.id)
|
|
245
|
+
);
|
|
246
|
+
return true;
|
|
247
|
+
}, [agent, popQueuedMessageForEdit, session.id, steerMessages]);
|
|
159
248
|
const handleTriggerOverlay = (0, import_react.useCallback)(
|
|
160
249
|
(trigger) => {
|
|
161
250
|
if (approval) return;
|
|
@@ -308,7 +397,7 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
308
397
|
return result;
|
|
309
398
|
}, []);
|
|
310
399
|
const handleSubmit = (0, import_react.useCallback)(
|
|
311
|
-
async (value, bypassOverlayCheck = false) => {
|
|
400
|
+
async (value, bypassOverlayCheck = false, queueAsFollowUp = false) => {
|
|
312
401
|
const expandedValue = expandPasteBlocks(value, input.pastedBlocks);
|
|
313
402
|
const trimmed = expandedValue.trim();
|
|
314
403
|
if (!trimmed) return;
|
|
@@ -321,8 +410,13 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
321
410
|
mimeType: img.mimeType
|
|
322
411
|
});
|
|
323
412
|
}
|
|
413
|
+
const submitAsFollowUp = queueAsFollowUp || input.editingQueuedFollowUp;
|
|
324
414
|
try {
|
|
325
|
-
|
|
415
|
+
if (submitAsFollowUp) {
|
|
416
|
+
await agent.followUp(session.id, { content });
|
|
417
|
+
} else {
|
|
418
|
+
await agent.steer(session.id, { content });
|
|
419
|
+
}
|
|
326
420
|
buffer.setText("");
|
|
327
421
|
setInput((prev) => {
|
|
328
422
|
const newHistory = prev.history.length > 0 && prev.history[prev.history.length - 1] === trimmed ? prev.history : [...prev.history, trimmed].slice(-100);
|
|
@@ -332,6 +426,7 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
332
426
|
history: newHistory,
|
|
333
427
|
historyIndex: -1,
|
|
334
428
|
draftBeforeHistory: "",
|
|
429
|
+
editingQueuedFollowUp: false,
|
|
335
430
|
images: [],
|
|
336
431
|
pastedBlocks: []
|
|
337
432
|
};
|
|
@@ -342,7 +437,7 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
342
437
|
{
|
|
343
438
|
id: (0, import_idGenerator.generateMessageId)("error"),
|
|
344
439
|
role: "system",
|
|
345
|
-
content: `Failed to
|
|
440
|
+
content: `Failed to submit ${submitAsFollowUp ? "follow-up" : "steer"} message: ${error instanceof Error ? error.message : String(error)}`,
|
|
346
441
|
timestamp: /* @__PURE__ */ new Date()
|
|
347
442
|
}
|
|
348
443
|
]);
|
|
@@ -363,6 +458,7 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
363
458
|
history: newHistory,
|
|
364
459
|
historyIndex: -1,
|
|
365
460
|
draftBeforeHistory: "",
|
|
461
|
+
editingQueuedFollowUp: false,
|
|
366
462
|
images: [],
|
|
367
463
|
// Clear images on submit
|
|
368
464
|
pastedBlocks: [],
|
|
@@ -464,6 +560,7 @@ const InputContainer = (0, import_react.forwardRef)(
|
|
|
464
560
|
setDequeuedBuffer,
|
|
465
561
|
setUi,
|
|
466
562
|
setSession,
|
|
563
|
+
setSteerMessages,
|
|
467
564
|
setQueuedMessages,
|
|
468
565
|
setApproval,
|
|
469
566
|
setApprovalQueue
|
|
@@ -583,6 +680,7 @@ ${trimmed}`;
|
|
|
583
680
|
setDequeuedBuffer,
|
|
584
681
|
setUi,
|
|
585
682
|
setSession,
|
|
683
|
+
setSteerMessages,
|
|
586
684
|
setQueuedMessages,
|
|
587
685
|
setApproval,
|
|
588
686
|
setApprovalQueue
|
|
@@ -629,6 +727,7 @@ ${trimmed}`;
|
|
|
629
727
|
setMessages,
|
|
630
728
|
setPendingMessages,
|
|
631
729
|
setDequeuedBuffer,
|
|
730
|
+
setSteerMessages,
|
|
632
731
|
setQueuedMessages,
|
|
633
732
|
setSession,
|
|
634
733
|
agent,
|
|
@@ -667,7 +766,7 @@ ${trimmed}`;
|
|
|
667
766
|
const mainInputAllowed = mainInputAllowedOverlays.includes(ui.activeOverlay);
|
|
668
767
|
const isHistorySearchActive = ui.historySearch.isActive;
|
|
669
768
|
const isInputActive = !approval && mainInputAllowed && !isHistorySearchActive;
|
|
670
|
-
const isInputDisabled = approval !== null || !mainInputAllowed || isHistorySearchActive;
|
|
769
|
+
const isInputDisabled = approval !== null || !mainInputAllowed || isHistorySearchActive || isQueuedEditPending;
|
|
671
770
|
const shouldHandleSubmit = ui.activeOverlay === "none" || ui.activeOverlay === "approval";
|
|
672
771
|
const canNavigateHistory = !approval && ui.activeOverlay === "none";
|
|
673
772
|
const shouldHideInputArea = (0, import_overlayPresentation.getOverlayPresentation)(ui.activeOverlay, approval) === "focus";
|
|
@@ -684,10 +783,12 @@ ${trimmed}`;
|
|
|
684
783
|
buffer,
|
|
685
784
|
onSubmit: shouldHandleSubmit ? handleSubmit : () => {
|
|
686
785
|
},
|
|
786
|
+
onQueueSubmit: shouldHandleSubmit ? (value) => void handleSubmit(value, false, true) : void 0,
|
|
687
787
|
isDisabled: isInputDisabled,
|
|
688
788
|
isActive: isInputActive,
|
|
689
789
|
placeholder,
|
|
690
790
|
onHistoryNavigate: canNavigateHistory ? handleHistoryNavigate : void 0,
|
|
791
|
+
onCurrentTurnEdit: handleCurrentTurnEdit,
|
|
691
792
|
onTriggerOverlay: handleTriggerOverlay,
|
|
692
793
|
onKeyboardScroll,
|
|
693
794
|
imageCount: input.images.length,
|
|
@@ -26,7 +26,9 @@ interface InputContainerProps {
|
|
|
26
26
|
/** If provided, auto-submits once when the UI is ready */
|
|
27
27
|
initialPrompt?: string | undefined;
|
|
28
28
|
approval: ApprovalRequest | null;
|
|
29
|
-
/**
|
|
29
|
+
/** Active-turn input waiting for the next executor boundary */
|
|
30
|
+
steerMessages: QueuedMessage[];
|
|
31
|
+
/** Follow-up messages waiting to run after the current turn */
|
|
30
32
|
queuedMessages: QueuedMessage[];
|
|
31
33
|
setInput: React.Dispatch<React.SetStateAction<InputState>>;
|
|
32
34
|
setUi: React.Dispatch<React.SetStateAction<UIState>>;
|
|
@@ -37,7 +39,9 @@ interface InputContainerProps {
|
|
|
37
39
|
setPendingMessages: React.Dispatch<React.SetStateAction<Message[]>>;
|
|
38
40
|
/** Setter for dequeued buffer (user messages waiting to render after pending) */
|
|
39
41
|
setDequeuedBuffer: React.Dispatch<React.SetStateAction<Message[]>>;
|
|
40
|
-
/** Setter for
|
|
42
|
+
/** Setter for active-turn steer messages */
|
|
43
|
+
setSteerMessages: React.Dispatch<React.SetStateAction<QueuedMessage[]>>;
|
|
44
|
+
/** Setter for queued follow-up messages */
|
|
41
45
|
setQueuedMessages: React.Dispatch<React.SetStateAction<QueuedMessage[]>>;
|
|
42
46
|
/** Setter for current approval request (for approval UI via processStream) */
|
|
43
47
|
setApproval: React.Dispatch<React.SetStateAction<ApprovalRequest | null>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputContainer.d.ts","sourceRoot":"","sources":["../../src/containers/InputContainer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA0E,MAAM,OAAO,CAAC;AAC/F,OAAO,KAAK,EAAoC,aAAa,EAAE,MAAM,aAAa,CAAC;AAGnF,OAAO,EAAE,YAAY,EAAiB,MAAM,sBAAsB,CAAC;AAEnE,OAAO,KAAK,EACR,OAAO,EACP,OAAO,EACP,UAAU,EACV,YAAY,EAGZ,QAAQ,EACX,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"InputContainer.d.ts","sourceRoot":"","sources":["../../src/containers/InputContainer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useRef, useEffect, useImperativeHandle, forwardRef } from "react";
|
|
2
|
+
import React, { useCallback, useRef, useEffect, useImperativeHandle, forwardRef } from "react";
|
|
3
3
|
import { getReasoningProfile } from "@dexto/core";
|
|
4
4
|
import { InputArea } from "../components/input/InputArea.js";
|
|
5
5
|
import { processStream } from "../services/index.js";
|
|
6
6
|
import { useSoundService } from "../contexts/index.js";
|
|
7
7
|
import { createUserMessage } from "../utils/messageFormatting.js";
|
|
8
8
|
import { generateMessageId } from "../utils/idGenerator.js";
|
|
9
|
+
import { restoreQueuedContentForComposer } from "../utils/queuedComposerContent.js";
|
|
9
10
|
import { captureAnalytics } from "../host/index.js";
|
|
10
11
|
import { getOverlayPresentation } from "../utils/overlayPresentation.js";
|
|
11
12
|
import {
|
|
@@ -21,6 +22,7 @@ const InputContainer = forwardRef(
|
|
|
21
22
|
session,
|
|
22
23
|
initialPrompt,
|
|
23
24
|
approval,
|
|
25
|
+
steerMessages,
|
|
24
26
|
queuedMessages,
|
|
25
27
|
setInput,
|
|
26
28
|
setUi,
|
|
@@ -28,6 +30,7 @@ const InputContainer = forwardRef(
|
|
|
28
30
|
setMessages,
|
|
29
31
|
setPendingMessages,
|
|
30
32
|
setDequeuedBuffer,
|
|
33
|
+
setSteerMessages,
|
|
31
34
|
setQueuedMessages,
|
|
32
35
|
setApproval,
|
|
33
36
|
setApprovalQueue,
|
|
@@ -39,6 +42,8 @@ const InputContainer = forwardRef(
|
|
|
39
42
|
useStreaming = true
|
|
40
43
|
}, ref) {
|
|
41
44
|
const sessionCreationPromiseRef = useRef(null);
|
|
45
|
+
const queuedEditPendingRef = useRef(false);
|
|
46
|
+
const [isQueuedEditPending, setIsQueuedEditPending] = React.useState(false);
|
|
42
47
|
const didAutoSubmitInitialPromptRef = useRef(false);
|
|
43
48
|
const soundService = useSoundService();
|
|
44
49
|
const autoApproveEditsRef = useRef(ui.autoApproveEdits);
|
|
@@ -54,21 +59,81 @@ const InputContainer = forwardRef(
|
|
|
54
59
|
sessionCreationPromiseRef.current = null;
|
|
55
60
|
}
|
|
56
61
|
}, [session.id]);
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
const popQueuedMessageForEdit = useCallback(
|
|
63
|
+
async (message, editingQueuedFollowUp, removeMessage) => {
|
|
64
|
+
if (queuedEditPendingRef.current) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const result = restoreQueuedContentForComposer(message);
|
|
68
|
+
if (!result.ok) {
|
|
69
|
+
setMessages((prev) => [
|
|
70
|
+
...prev,
|
|
71
|
+
{
|
|
72
|
+
id: generateMessageId("system"),
|
|
73
|
+
role: "system",
|
|
74
|
+
content: result.reason,
|
|
75
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
76
|
+
}
|
|
77
|
+
]);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
queuedEditPendingRef.current = true;
|
|
81
|
+
setIsQueuedEditPending(true);
|
|
82
|
+
let removed = false;
|
|
83
|
+
try {
|
|
84
|
+
removed = await removeMessage();
|
|
85
|
+
if (!removed) {
|
|
86
|
+
setMessages((prev) => [
|
|
87
|
+
...prev,
|
|
88
|
+
{
|
|
89
|
+
id: generateMessageId("system"),
|
|
90
|
+
role: "system",
|
|
91
|
+
content: "Queued input could not be edited because it is no longer pending.",
|
|
92
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
93
|
+
}
|
|
94
|
+
]);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
buffer.setText(result.composer.text);
|
|
98
|
+
setInput((prev) => ({
|
|
99
|
+
...prev,
|
|
100
|
+
value: result.composer.text,
|
|
101
|
+
images: result.composer.images,
|
|
102
|
+
pastedBlocks: [],
|
|
103
|
+
historyIndex: -1,
|
|
104
|
+
draftBeforeHistory: "",
|
|
105
|
+
editingQueuedFollowUp
|
|
106
|
+
}));
|
|
107
|
+
} catch {
|
|
108
|
+
setMessages((prev) => [
|
|
109
|
+
...prev,
|
|
110
|
+
{
|
|
111
|
+
id: generateMessageId("system"),
|
|
112
|
+
role: "system",
|
|
113
|
+
content: "Queued input could not be edited. Try again.",
|
|
114
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
115
|
+
}
|
|
116
|
+
]);
|
|
117
|
+
} finally {
|
|
118
|
+
queuedEditPendingRef.current = false;
|
|
119
|
+
setIsQueuedEditPending(false);
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
[buffer, setInput, setMessages]
|
|
123
|
+
);
|
|
60
124
|
const handleHistoryNavigate = useCallback(
|
|
61
125
|
(direction) => {
|
|
62
126
|
const { history, historyIndex, draftBeforeHistory } = input;
|
|
63
127
|
if (direction === "up") {
|
|
64
128
|
if (queuedMessages.length > 0 && session.id) {
|
|
129
|
+
const sessionId = session.id;
|
|
65
130
|
const lastQueued = queuedMessages[queuedMessages.length - 1];
|
|
66
131
|
if (lastQueued) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
132
|
+
void popQueuedMessageForEdit(
|
|
133
|
+
lastQueued,
|
|
134
|
+
true,
|
|
135
|
+
() => agent.removeFollowUpMessage(sessionId, lastQueued.id)
|
|
136
|
+
);
|
|
72
137
|
return;
|
|
73
138
|
}
|
|
74
139
|
}
|
|
@@ -81,7 +146,8 @@ const InputContainer = forwardRef(
|
|
|
81
146
|
...prev,
|
|
82
147
|
draftBeforeHistory: currentText,
|
|
83
148
|
historyIndex: history.length - 1,
|
|
84
|
-
value: history[history.length - 1] || ""
|
|
149
|
+
value: history[history.length - 1] || "",
|
|
150
|
+
editingQueuedFollowUp: false
|
|
85
151
|
}));
|
|
86
152
|
buffer.setText(history[history.length - 1] || "");
|
|
87
153
|
return;
|
|
@@ -92,7 +158,12 @@ const InputContainer = forwardRef(
|
|
|
92
158
|
}
|
|
93
159
|
const historyItem = history[newIndex] || "";
|
|
94
160
|
buffer.setText(historyItem);
|
|
95
|
-
setInput((prev) => ({
|
|
161
|
+
setInput((prev) => ({
|
|
162
|
+
...prev,
|
|
163
|
+
value: historyItem,
|
|
164
|
+
historyIndex: newIndex,
|
|
165
|
+
editingQueuedFollowUp: false
|
|
166
|
+
}));
|
|
96
167
|
} else {
|
|
97
168
|
if (ui.isProcessing) return;
|
|
98
169
|
if (historyIndex < 0) return;
|
|
@@ -103,7 +174,8 @@ const InputContainer = forwardRef(
|
|
|
103
174
|
setInput((prev) => ({
|
|
104
175
|
...prev,
|
|
105
176
|
value: historyItem,
|
|
106
|
-
historyIndex: newIndex
|
|
177
|
+
historyIndex: newIndex,
|
|
178
|
+
editingQueuedFollowUp: false
|
|
107
179
|
}));
|
|
108
180
|
} else {
|
|
109
181
|
buffer.setText(draftBeforeHistory);
|
|
@@ -111,7 +183,8 @@ const InputContainer = forwardRef(
|
|
|
111
183
|
...prev,
|
|
112
184
|
value: draftBeforeHistory,
|
|
113
185
|
historyIndex: -1,
|
|
114
|
-
draftBeforeHistory: ""
|
|
186
|
+
draftBeforeHistory: "",
|
|
187
|
+
editingQueuedFollowUp: false
|
|
115
188
|
}));
|
|
116
189
|
}
|
|
117
190
|
}
|
|
@@ -123,10 +196,26 @@ const InputContainer = forwardRef(
|
|
|
123
196
|
queuedMessages,
|
|
124
197
|
session.id,
|
|
125
198
|
agent,
|
|
126
|
-
|
|
199
|
+
popQueuedMessageForEdit,
|
|
127
200
|
ui.isProcessing
|
|
128
201
|
]
|
|
129
202
|
);
|
|
203
|
+
const handleCurrentTurnEdit = useCallback(() => {
|
|
204
|
+
if (steerMessages.length === 0 || !session.id) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
const lastSteer = steerMessages[steerMessages.length - 1];
|
|
208
|
+
if (!lastSteer) {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
const sessionId = session.id;
|
|
212
|
+
void popQueuedMessageForEdit(
|
|
213
|
+
lastSteer,
|
|
214
|
+
false,
|
|
215
|
+
() => agent.removeSteerMessage(sessionId, lastSteer.id)
|
|
216
|
+
);
|
|
217
|
+
return true;
|
|
218
|
+
}, [agent, popQueuedMessageForEdit, session.id, steerMessages]);
|
|
130
219
|
const handleTriggerOverlay = useCallback(
|
|
131
220
|
(trigger) => {
|
|
132
221
|
if (approval) return;
|
|
@@ -279,7 +368,7 @@ const InputContainer = forwardRef(
|
|
|
279
368
|
return result;
|
|
280
369
|
}, []);
|
|
281
370
|
const handleSubmit = useCallback(
|
|
282
|
-
async (value, bypassOverlayCheck = false) => {
|
|
371
|
+
async (value, bypassOverlayCheck = false, queueAsFollowUp = false) => {
|
|
283
372
|
const expandedValue = expandPasteBlocks(value, input.pastedBlocks);
|
|
284
373
|
const trimmed = expandedValue.trim();
|
|
285
374
|
if (!trimmed) return;
|
|
@@ -292,8 +381,13 @@ const InputContainer = forwardRef(
|
|
|
292
381
|
mimeType: img.mimeType
|
|
293
382
|
});
|
|
294
383
|
}
|
|
384
|
+
const submitAsFollowUp = queueAsFollowUp || input.editingQueuedFollowUp;
|
|
295
385
|
try {
|
|
296
|
-
|
|
386
|
+
if (submitAsFollowUp) {
|
|
387
|
+
await agent.followUp(session.id, { content });
|
|
388
|
+
} else {
|
|
389
|
+
await agent.steer(session.id, { content });
|
|
390
|
+
}
|
|
297
391
|
buffer.setText("");
|
|
298
392
|
setInput((prev) => {
|
|
299
393
|
const newHistory = prev.history.length > 0 && prev.history[prev.history.length - 1] === trimmed ? prev.history : [...prev.history, trimmed].slice(-100);
|
|
@@ -303,6 +397,7 @@ const InputContainer = forwardRef(
|
|
|
303
397
|
history: newHistory,
|
|
304
398
|
historyIndex: -1,
|
|
305
399
|
draftBeforeHistory: "",
|
|
400
|
+
editingQueuedFollowUp: false,
|
|
306
401
|
images: [],
|
|
307
402
|
pastedBlocks: []
|
|
308
403
|
};
|
|
@@ -313,7 +408,7 @@ const InputContainer = forwardRef(
|
|
|
313
408
|
{
|
|
314
409
|
id: generateMessageId("error"),
|
|
315
410
|
role: "system",
|
|
316
|
-
content: `Failed to
|
|
411
|
+
content: `Failed to submit ${submitAsFollowUp ? "follow-up" : "steer"} message: ${error instanceof Error ? error.message : String(error)}`,
|
|
317
412
|
timestamp: /* @__PURE__ */ new Date()
|
|
318
413
|
}
|
|
319
414
|
]);
|
|
@@ -334,6 +429,7 @@ const InputContainer = forwardRef(
|
|
|
334
429
|
history: newHistory,
|
|
335
430
|
historyIndex: -1,
|
|
336
431
|
draftBeforeHistory: "",
|
|
432
|
+
editingQueuedFollowUp: false,
|
|
337
433
|
images: [],
|
|
338
434
|
// Clear images on submit
|
|
339
435
|
pastedBlocks: [],
|
|
@@ -435,6 +531,7 @@ const InputContainer = forwardRef(
|
|
|
435
531
|
setDequeuedBuffer,
|
|
436
532
|
setUi,
|
|
437
533
|
setSession,
|
|
534
|
+
setSteerMessages,
|
|
438
535
|
setQueuedMessages,
|
|
439
536
|
setApproval,
|
|
440
537
|
setApprovalQueue
|
|
@@ -554,6 +651,7 @@ ${trimmed}`;
|
|
|
554
651
|
setDequeuedBuffer,
|
|
555
652
|
setUi,
|
|
556
653
|
setSession,
|
|
654
|
+
setSteerMessages,
|
|
557
655
|
setQueuedMessages,
|
|
558
656
|
setApproval,
|
|
559
657
|
setApprovalQueue
|
|
@@ -600,6 +698,7 @@ ${trimmed}`;
|
|
|
600
698
|
setMessages,
|
|
601
699
|
setPendingMessages,
|
|
602
700
|
setDequeuedBuffer,
|
|
701
|
+
setSteerMessages,
|
|
603
702
|
setQueuedMessages,
|
|
604
703
|
setSession,
|
|
605
704
|
agent,
|
|
@@ -638,7 +737,7 @@ ${trimmed}`;
|
|
|
638
737
|
const mainInputAllowed = mainInputAllowedOverlays.includes(ui.activeOverlay);
|
|
639
738
|
const isHistorySearchActive = ui.historySearch.isActive;
|
|
640
739
|
const isInputActive = !approval && mainInputAllowed && !isHistorySearchActive;
|
|
641
|
-
const isInputDisabled = approval !== null || !mainInputAllowed || isHistorySearchActive;
|
|
740
|
+
const isInputDisabled = approval !== null || !mainInputAllowed || isHistorySearchActive || isQueuedEditPending;
|
|
642
741
|
const shouldHandleSubmit = ui.activeOverlay === "none" || ui.activeOverlay === "approval";
|
|
643
742
|
const canNavigateHistory = !approval && ui.activeOverlay === "none";
|
|
644
743
|
const shouldHideInputArea = getOverlayPresentation(ui.activeOverlay, approval) === "focus";
|
|
@@ -655,10 +754,12 @@ ${trimmed}`;
|
|
|
655
754
|
buffer,
|
|
656
755
|
onSubmit: shouldHandleSubmit ? handleSubmit : () => {
|
|
657
756
|
},
|
|
757
|
+
onQueueSubmit: shouldHandleSubmit ? (value) => void handleSubmit(value, false, true) : void 0,
|
|
658
758
|
isDisabled: isInputDisabled,
|
|
659
759
|
isActive: isInputActive,
|
|
660
760
|
placeholder,
|
|
661
761
|
onHistoryNavigate: canNavigateHistory ? handleHistoryNavigate : void 0,
|
|
762
|
+
onCurrentTurnEdit: handleCurrentTurnEdit,
|
|
662
763
|
onTriggerOverlay: handleTriggerOverlay,
|
|
663
764
|
onKeyboardScroll,
|
|
664
765
|
imageCount: input.images.length,
|