@alpaca-editor/core 1.0.4018 → 1.0.4027
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/components/SimpleLanguageSelector.d.ts +2 -1
- package/dist/components/SimpleLanguageSelector.js +9 -2
- package/dist/components/SimpleLanguageSelector.js.map +1 -1
- package/dist/components/ui/input.js +1 -1
- package/dist/components/ui/input.js.map +1 -1
- package/dist/components/ui/tooltip.d.ts +3 -1
- package/dist/components/ui/tooltip.js +2 -2
- package/dist/components/ui/tooltip.js.map +1 -1
- package/dist/config/config.js +4 -0
- package/dist/config/config.js.map +1 -1
- package/dist/config/types.d.ts +2 -0
- package/dist/editor/ContentTree.js +1 -1
- package/dist/editor/ContentTree.js.map +1 -1
- package/dist/editor/ContextMenu.js +26 -0
- package/dist/editor/ContextMenu.js.map +1 -1
- package/dist/editor/FieldHistory.js +1 -1
- package/dist/editor/FieldHistory.js.map +1 -1
- package/dist/editor/FieldListField.js +2 -2
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/Terminal.js +3 -1
- package/dist/editor/Terminal.js.map +1 -1
- package/dist/editor/ai/Agents.js +37 -18
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/AiResponseMessage.js +71 -5
- package/dist/editor/ai/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/AiTerminal.d.ts +3 -1
- package/dist/editor/ai/AiTerminal.js +53 -24
- package/dist/editor/ai/AiTerminal.js.map +1 -1
- package/dist/editor/ai/AiToolCall.js +3 -3
- package/dist/editor/ai/AiToolCall.js.map +1 -1
- package/dist/editor/ai/EditorAiTerminal.d.ts +2 -1
- package/dist/editor/ai/EditorAiTerminal.js +2 -2
- package/dist/editor/ai/EditorAiTerminal.js.map +1 -1
- package/dist/editor/client/EditorClient.js +5 -1
- package/dist/editor/client/EditorClient.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +2 -0
- package/dist/editor/client/editContext.js.map +1 -1
- package/dist/editor/client/operations.d.ts +1 -0
- package/dist/editor/client/operations.js +7 -0
- package/dist/editor/client/operations.js.map +1 -1
- package/dist/editor/commands/componentCommands.js +1 -1
- package/dist/editor/commands/componentCommands.js.map +1 -1
- package/dist/editor/field-types/ImageFieldEditor.js +1 -1
- package/dist/editor/field-types/ImageFieldEditor.js.map +1 -1
- package/dist/editor/field-types/MultiLineText.js +1 -1
- package/dist/editor/field-types/MultiLineText.js.map +1 -1
- package/dist/editor/field-types/PictureFieldEditor.js +1 -1
- package/dist/editor/field-types/PictureFieldEditor.js.map +1 -1
- package/dist/editor/field-types/RawEditor.js +1 -1
- package/dist/editor/field-types/RawEditor.js.map +1 -1
- package/dist/editor/field-types/RichTextEditorComponent.js +16 -17
- package/dist/editor/field-types/RichTextEditorComponent.js.map +1 -1
- package/dist/editor/field-types/SingleLineText.js +1 -1
- package/dist/editor/field-types/SingleLineText.js.map +1 -1
- package/dist/editor/field-types/richtext/components/SimpleDropdown.d.ts +18 -0
- package/dist/editor/field-types/richtext/components/SimpleDropdown.js +71 -0
- package/dist/editor/field-types/richtext/components/SimpleDropdown.js.map +1 -0
- package/dist/editor/field-types/richtext/components/SimpleRichTextEditor.d.ts +5 -0
- package/dist/editor/field-types/richtext/components/SimpleRichTextEditor.js +359 -0
- package/dist/editor/field-types/richtext/components/SimpleRichTextEditor.js.map +1 -0
- package/dist/editor/field-types/richtext/components/SimpleToolbar.d.ts +16 -0
- package/dist/editor/field-types/richtext/components/SimpleToolbar.js +181 -0
- package/dist/editor/field-types/richtext/components/SimpleToolbar.js.map +1 -0
- package/dist/editor/field-types/richtext/components/SimpleToolbarButton.d.ts +9 -0
- package/dist/editor/field-types/richtext/components/SimpleToolbarButton.js +14 -0
- package/dist/editor/field-types/richtext/components/SimpleToolbarButton.js.map +1 -0
- package/dist/editor/field-types/richtext/contextMenuFactory.d.ts +4 -0
- package/dist/editor/field-types/richtext/contextMenuFactory.js +193 -0
- package/dist/editor/field-types/richtext/contextMenuFactory.js.map +1 -0
- package/dist/editor/field-types/richtext/index.d.ts +6 -5
- package/dist/editor/field-types/richtext/index.js +6 -5
- package/dist/editor/field-types/richtext/index.js.map +1 -1
- package/dist/editor/field-types/richtext/types.d.ts +16 -16
- package/dist/editor/field-types/richtext/types.js +84 -84
- package/dist/editor/field-types/richtext/types.js.map +1 -1
- package/dist/editor/page-editor-chrome/CommentHighlighting.js +1 -1
- package/dist/editor/page-editor-chrome/CommentHighlighting.js.map +1 -1
- package/dist/editor/page-editor-chrome/FrameMenu.js +5 -5
- package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.js +3 -2
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +14 -4
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/editor/services/aiService.d.ts +1 -0
- package/dist/editor/services/aiService.js +1 -0
- package/dist/editor/services/aiService.js.map +1 -1
- package/dist/page-wizard/PageWizard.d.ts +2 -0
- package/dist/page-wizard/PageWizard.js +6 -13
- package/dist/page-wizard/PageWizard.js.map +1 -1
- package/dist/page-wizard/WizardSteps.js +3 -1
- package/dist/page-wizard/WizardSteps.js.map +1 -1
- package/dist/page-wizard/service.d.ts +1 -0
- package/dist/page-wizard/service.js +7 -0
- package/dist/page-wizard/service.js.map +1 -1
- package/dist/page-wizard/steps/ContentStep.js +210 -33
- package/dist/page-wizard/steps/ContentStep.js.map +1 -1
- package/dist/page-wizard/steps/FindItemsStep.js +11 -3
- package/dist/page-wizard/steps/FindItemsStep.js.map +1 -1
- package/dist/page-wizard/steps/LayoutStep.js +1 -1
- package/dist/page-wizard/steps/LayoutStep.js.map +1 -1
- package/dist/page-wizard/steps/MetaDataStep.js +1 -1
- package/dist/page-wizard/steps/MetaDataStep.js.map +1 -1
- package/dist/page-wizard/steps/SchottSelectImagesStep.d.ts +2 -0
- package/dist/page-wizard/steps/SchottSelectImagesStep.js +55 -0
- package/dist/page-wizard/steps/SchottSelectImagesStep.js.map +1 -0
- package/dist/page-wizard/steps/StructureStep.js +20 -5
- package/dist/page-wizard/steps/StructureStep.js.map +1 -1
- package/dist/page-wizard/steps/TranslateStep.d.ts +2 -0
- package/dist/page-wizard/steps/TranslateStep.js +413 -0
- package/dist/page-wizard/steps/TranslateStep.js.map +1 -0
- package/dist/page-wizard/utils/dataAccessor.d.ts +7 -0
- package/dist/page-wizard/utils/dataAccessor.js +76 -0
- package/dist/page-wizard/utils/dataAccessor.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/splash-screen/NewPage.js +5 -4
- package/dist/splash-screen/NewPage.js.map +1 -1
- package/dist/splash-screen/OpenPage.js +2 -1
- package/dist/splash-screen/OpenPage.js.map +1 -1
- package/dist/splash-screen/RecentPages.js +3 -1
- package/dist/splash-screen/RecentPages.js.map +1 -1
- package/dist/styles.css +57 -0
- package/package.json +5 -4
- package/src/components/SimpleLanguageSelector.tsx +11 -1
- package/src/components/ui/input.tsx +1 -1
- package/src/components/ui/tooltip.tsx +3 -2
- package/src/config/config.tsx +4 -0
- package/src/config/types.ts +6 -0
- package/src/editor/ContentTree.tsx +1 -1
- package/src/editor/ContextMenu.tsx +39 -0
- package/src/editor/FieldHistory.tsx +1 -1
- package/src/editor/FieldListField.tsx +2 -6
- package/src/editor/Terminal.tsx +5 -1
- package/src/editor/ai/Agents.tsx +90 -46
- package/src/editor/ai/AiResponseMessage.tsx +185 -24
- package/src/editor/ai/AiTerminal.tsx +104 -50
- package/src/editor/ai/AiToolCall.tsx +14 -4
- package/src/editor/ai/EditorAiTerminal.tsx +3 -0
- package/src/editor/client/EditorClient.tsx +9 -1
- package/src/editor/client/editContext.ts +2 -0
- package/src/editor/client/operations.ts +9 -0
- package/src/editor/commands/componentCommands.tsx +1 -1
- package/src/editor/field-types/ImageFieldEditor.tsx +1 -0
- package/src/editor/field-types/MultiLineText.tsx +1 -0
- package/src/editor/field-types/PictureFieldEditor.tsx +1 -0
- package/src/editor/field-types/RawEditor.tsx +1 -0
- package/src/editor/field-types/RichTextEditorComponent.tsx +27 -25
- package/src/editor/field-types/SingleLineText.tsx +1 -0
- package/src/editor/field-types/richtext/components/SimpleDropdown.tsx +165 -0
- package/src/editor/field-types/richtext/components/SimpleRichTextEditor.css +261 -0
- package/src/editor/field-types/richtext/components/SimpleRichTextEditor.tsx +505 -0
- package/src/editor/field-types/richtext/components/SimpleToolbar.tsx +362 -0
- package/src/editor/field-types/richtext/components/SimpleToolbarButton.tsx +36 -0
- package/src/editor/field-types/richtext/contextMenuFactory.tsx +264 -0
- package/src/editor/field-types/richtext/index.ts +6 -5
- package/src/editor/field-types/richtext/types.ts +168 -148
- package/src/editor/page-editor-chrome/CommentHighlighting.tsx +1 -1
- package/src/editor/page-editor-chrome/FrameMenu.tsx +16 -11
- package/src/editor/page-editor-chrome/PlaceholderDropZone.tsx +1 -1
- package/src/editor/page-viewer/PageViewerFrame.tsx +4 -3
- package/src/editor/services/agentService.ts +16 -5
- package/src/editor/services/aiService.ts +4 -0
- package/src/page-wizard/PageWizard.tsx +10 -13
- package/src/page-wizard/WizardSteps.tsx +3 -1
- package/src/page-wizard/service.ts +11 -0
- package/src/page-wizard/steps/ContentStep.tsx +376 -43
- package/src/page-wizard/steps/FindItemsStep.tsx +23 -3
- package/src/page-wizard/steps/LayoutStep.tsx +1 -1
- package/src/page-wizard/steps/MetaDataStep.tsx +1 -1
- package/src/page-wizard/steps/SchottSelectImagesStep.tsx +141 -0
- package/src/page-wizard/steps/StructureStep.tsx +40 -5
- package/src/page-wizard/steps/TranslateStep.tsx +772 -0
- package/src/page-wizard/utils/dataAccessor.ts +85 -0
- package/src/revision.ts +2 -2
- package/src/splash-screen/NewPage.tsx +18 -3
- package/src/splash-screen/OpenPage.tsx +14 -1
- package/src/splash-screen/RecentPages.tsx +4 -2
- package/tsconfig.build.json +1 -0
package/src/editor/ai/Agents.tsx
CHANGED
|
@@ -4,7 +4,13 @@ import { EditorAiTerminal } from "./EditorAiTerminal";
|
|
|
4
4
|
import { SimpleIconButton } from "../ui/SimpleIconButton";
|
|
5
5
|
import { Plus, X, History } from "lucide-react";
|
|
6
6
|
import { cn } from "../../lib/utils";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
getAgents,
|
|
9
|
+
getAgent,
|
|
10
|
+
getChatHistory,
|
|
11
|
+
AgentChat,
|
|
12
|
+
AgentChatMessage,
|
|
13
|
+
} from "../services/agentService";
|
|
8
14
|
import { Message } from "./AiTerminal";
|
|
9
15
|
import {
|
|
10
16
|
Popover,
|
|
@@ -21,22 +27,41 @@ interface TerminalInstance {
|
|
|
21
27
|
messages?: Message[];
|
|
22
28
|
}
|
|
23
29
|
|
|
24
|
-
function convertAgentMessagesToTerminalMessages(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
function convertAgentMessagesToTerminalMessages(
|
|
31
|
+
agentMessages: AgentChatMessage[],
|
|
32
|
+
): Message[] {
|
|
33
|
+
return (
|
|
34
|
+
agentMessages
|
|
35
|
+
// Keep all messages including tool results for complete conversation context
|
|
36
|
+
.map((msg) => ({
|
|
37
|
+
id: msg.id,
|
|
38
|
+
content: msg.content,
|
|
39
|
+
name: msg.name,
|
|
40
|
+
role: msg.role,
|
|
41
|
+
tool_calls:
|
|
42
|
+
msg.toolCalls?.map((toolCall) => ({
|
|
43
|
+
id: toolCall.toolCallId,
|
|
44
|
+
displayName: toolCall.functionName,
|
|
45
|
+
function: {
|
|
46
|
+
name: toolCall.functionName,
|
|
47
|
+
arguments: toolCall.functionArguments || "",
|
|
48
|
+
},
|
|
49
|
+
})) || [],
|
|
50
|
+
tool_call_id: msg.toolCallId,
|
|
51
|
+
}))
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function formatDateToLocalTime(dateString: string): string {
|
|
56
|
+
// Ensure the date string is treated as UTC if it doesn't have timezone info
|
|
57
|
+
const normalizedDate =
|
|
58
|
+
dateString.includes("Z") ||
|
|
59
|
+
dateString.includes("+") ||
|
|
60
|
+
dateString.includes("-", 19)
|
|
61
|
+
? dateString
|
|
62
|
+
: dateString + "Z";
|
|
63
|
+
|
|
64
|
+
return new Date(normalizedDate).toLocaleString();
|
|
40
65
|
}
|
|
41
66
|
|
|
42
67
|
export function Agents({
|
|
@@ -58,39 +83,41 @@ export function Agents({
|
|
|
58
83
|
loadAgentsFromBackend();
|
|
59
84
|
}, []);
|
|
60
85
|
|
|
61
|
-
|
|
62
|
-
|
|
63
86
|
const loadAgentsFromBackend = async () => {
|
|
64
87
|
try {
|
|
65
88
|
setLoadingAgents(true);
|
|
66
|
-
|
|
89
|
+
|
|
67
90
|
// Load active agents
|
|
68
91
|
const activeAgentsResult = await getAgents("active");
|
|
69
|
-
|
|
92
|
+
|
|
70
93
|
// Load inactive agents for history
|
|
71
94
|
const inactiveAgentsResult = await getChatHistory("completed", 20);
|
|
72
|
-
|
|
95
|
+
|
|
73
96
|
if (activeAgentsResult.type === "success" && activeAgentsResult.data) {
|
|
74
97
|
const activeAgents = activeAgentsResult.data;
|
|
75
|
-
|
|
98
|
+
|
|
76
99
|
// Create terminals for active agents
|
|
77
100
|
const activeTerminals: TerminalInstance[] = await Promise.all(
|
|
78
101
|
activeAgents.map(async (agent, index) => {
|
|
79
102
|
// Load messages for each active agent
|
|
80
103
|
const agentWithMessages = await loadAgentMessages(agent.id);
|
|
81
|
-
|
|
104
|
+
|
|
82
105
|
return {
|
|
83
106
|
id: `agent-${agent.id}`,
|
|
84
107
|
title: agent.name || `Agent ${index + 1}`,
|
|
85
108
|
agentId: agent.id,
|
|
86
109
|
options: initialOptions,
|
|
87
|
-
messages: agentWithMessages?.messages
|
|
110
|
+
messages: agentWithMessages?.messages
|
|
111
|
+
? convertAgentMessagesToTerminalMessages(
|
|
112
|
+
agentWithMessages.messages,
|
|
113
|
+
)
|
|
114
|
+
: [],
|
|
88
115
|
};
|
|
89
|
-
})
|
|
116
|
+
}),
|
|
90
117
|
);
|
|
91
|
-
|
|
118
|
+
|
|
92
119
|
setTerminals(activeTerminals);
|
|
93
|
-
|
|
120
|
+
|
|
94
121
|
// Set the first active terminal as active, or create a new one if none exist
|
|
95
122
|
if (activeTerminals.length > 0) {
|
|
96
123
|
setActiveTerminalId(activeTerminals[0]!.id);
|
|
@@ -106,11 +133,13 @@ export function Agents({
|
|
|
106
133
|
nextTerminalNumber.current++;
|
|
107
134
|
}
|
|
108
135
|
}
|
|
109
|
-
|
|
110
|
-
if (
|
|
136
|
+
|
|
137
|
+
if (
|
|
138
|
+
inactiveAgentsResult.type === "success" &&
|
|
139
|
+
inactiveAgentsResult.data
|
|
140
|
+
) {
|
|
111
141
|
setInactiveAgents(inactiveAgentsResult.data);
|
|
112
142
|
}
|
|
113
|
-
|
|
114
143
|
} catch (error) {
|
|
115
144
|
console.error("Failed to load agents:", error);
|
|
116
145
|
// Create a default terminal on error
|
|
@@ -127,7 +156,9 @@ export function Agents({
|
|
|
127
156
|
}
|
|
128
157
|
};
|
|
129
158
|
|
|
130
|
-
const loadAgentMessages = async (
|
|
159
|
+
const loadAgentMessages = async (
|
|
160
|
+
agentId: string,
|
|
161
|
+
): Promise<AgentChat | null> => {
|
|
131
162
|
try {
|
|
132
163
|
const result = await getAgent(agentId);
|
|
133
164
|
if (result.type === "success" && result.data) {
|
|
@@ -170,8 +201,8 @@ export function Agents({
|
|
|
170
201
|
|
|
171
202
|
const openAgentFromHistory = async (agent: AgentChat) => {
|
|
172
203
|
// Check if this agent is already open as a terminal
|
|
173
|
-
const existingTerminal = terminals.find(t => t.agentId === agent.id);
|
|
174
|
-
|
|
204
|
+
const existingTerminal = terminals.find((t) => t.agentId === agent.id);
|
|
205
|
+
|
|
175
206
|
if (existingTerminal) {
|
|
176
207
|
// Switch to existing terminal
|
|
177
208
|
setActiveTerminalId(existingTerminal.id);
|
|
@@ -181,14 +212,16 @@ export function Agents({
|
|
|
181
212
|
|
|
182
213
|
// Load the agent with messages
|
|
183
214
|
const agentWithMessages = await loadAgentMessages(agent.id);
|
|
184
|
-
|
|
215
|
+
|
|
185
216
|
// Create new terminal for this agent
|
|
186
217
|
const newTerminal: TerminalInstance = {
|
|
187
218
|
id: `agent-${agent.id}`,
|
|
188
219
|
title: agent.name,
|
|
189
220
|
agentId: agent.id,
|
|
190
221
|
options: initialOptions,
|
|
191
|
-
messages: agentWithMessages?.messages
|
|
222
|
+
messages: agentWithMessages?.messages
|
|
223
|
+
? convertAgentMessagesToTerminalMessages(agentWithMessages.messages)
|
|
224
|
+
: [],
|
|
192
225
|
};
|
|
193
226
|
|
|
194
227
|
setTerminals((prev) => [...prev, newTerminal]);
|
|
@@ -238,7 +271,10 @@ export function Agents({
|
|
|
238
271
|
|
|
239
272
|
{/* History Popover */}
|
|
240
273
|
<div className="flex items-center px-1">
|
|
241
|
-
<Popover
|
|
274
|
+
<Popover
|
|
275
|
+
open={historyPopoverOpen}
|
|
276
|
+
onOpenChange={setHistoryPopoverOpen}
|
|
277
|
+
>
|
|
242
278
|
<PopoverTrigger asChild>
|
|
243
279
|
<SimpleIconButton
|
|
244
280
|
onClick={() => {}}
|
|
@@ -248,7 +284,7 @@ export function Agents({
|
|
|
248
284
|
/>
|
|
249
285
|
</PopoverTrigger>
|
|
250
286
|
<PopoverContent className="w-64 p-0" align="end">
|
|
251
|
-
<div className="px-3 py-2 text-xs font-medium text-gray-500
|
|
287
|
+
<div className="border-b border-gray-100 px-3 py-2 text-xs font-medium text-gray-500">
|
|
252
288
|
Agent History
|
|
253
289
|
</div>
|
|
254
290
|
<div className="max-h-80 overflow-y-auto">
|
|
@@ -260,17 +296,17 @@ export function Agents({
|
|
|
260
296
|
inactiveAgents.map((agent) => (
|
|
261
297
|
<div
|
|
262
298
|
key={agent.id}
|
|
263
|
-
className="cursor-pointer px-3 py-2 text-xs hover:bg-gray-50
|
|
299
|
+
className="cursor-pointer border-b border-gray-50 px-3 py-2 text-xs hover:bg-gray-50"
|
|
264
300
|
onClick={() => openAgentFromHistory(agent)}
|
|
265
301
|
>
|
|
266
|
-
<div className="font-medium text-gray-900
|
|
302
|
+
<div className="truncate font-medium text-gray-900">
|
|
267
303
|
{agent.name}
|
|
268
304
|
</div>
|
|
269
|
-
<div className="text-gray-500
|
|
305
|
+
<div className="truncate text-gray-500">
|
|
270
306
|
{agent.profileName}
|
|
271
307
|
</div>
|
|
272
|
-
<div className="text-gray-400
|
|
273
|
-
{
|
|
308
|
+
<div className="text-xs text-gray-400">
|
|
309
|
+
{formatDateToLocalTime(agent.updatedDate)}
|
|
274
310
|
</div>
|
|
275
311
|
</div>
|
|
276
312
|
))
|
|
@@ -306,12 +342,20 @@ export function Agents({
|
|
|
306
342
|
activeTerminalId === terminal.id ? "block" : "hidden",
|
|
307
343
|
)}
|
|
308
344
|
>
|
|
309
|
-
<EditorAiTerminal
|
|
345
|
+
<EditorAiTerminal
|
|
310
346
|
options={{
|
|
311
347
|
...terminal.options,
|
|
312
348
|
// Pass the pre-loaded messages to the terminal
|
|
313
|
-
initialMessages: terminal.messages
|
|
314
|
-
}}
|
|
349
|
+
initialMessages: terminal.messages,
|
|
350
|
+
}}
|
|
351
|
+
onAgentNameUpdate={(name) => {
|
|
352
|
+
// Update the terminal title when agent name is updated
|
|
353
|
+
setTerminals((prev) =>
|
|
354
|
+
prev.map((t) =>
|
|
355
|
+
t.id === terminal.id ? { ...t, title: name } : t,
|
|
356
|
+
),
|
|
357
|
+
);
|
|
358
|
+
}}
|
|
315
359
|
/>
|
|
316
360
|
</div>
|
|
317
361
|
))}
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
import { useState } from "react";
|
|
1
|
+
import { useState, useEffect } from "react";
|
|
2
|
+
import JSONPretty from "react-json-pretty";
|
|
2
3
|
|
|
3
4
|
import { useEditContext } from "../client/editContext";
|
|
4
5
|
import { EditOperation } from "../../types";
|
|
5
6
|
import { Message } from "./AiTerminal";
|
|
6
|
-
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
Popover,
|
|
10
|
+
PopoverContent,
|
|
11
|
+
PopoverTrigger,
|
|
12
|
+
} from "../../components/ui/popover";
|
|
13
|
+
import { SimpleTabs, Tab } from "../ui/SimpleTabs";
|
|
7
14
|
|
|
8
15
|
export function AiResponseMessage({
|
|
9
16
|
messages,
|
|
@@ -22,6 +29,27 @@ export function AiResponseMessage({
|
|
|
22
29
|
undefined,
|
|
23
30
|
);
|
|
24
31
|
|
|
32
|
+
// Store tool calls to preserve them during streaming
|
|
33
|
+
const [preservedToolCalls, setPreservedToolCalls] = useState<{
|
|
34
|
+
[messageIndex: number]: any[];
|
|
35
|
+
}>({});
|
|
36
|
+
|
|
37
|
+
console.log(messages);
|
|
38
|
+
|
|
39
|
+
// Update preserved tool calls when messages change
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const newPreservedToolCalls = { ...preservedToolCalls };
|
|
42
|
+
|
|
43
|
+
messages.forEach((message, index) => {
|
|
44
|
+
if (message.tool_calls && message.tool_calls.length > 0) {
|
|
45
|
+
// Store non-empty tool calls
|
|
46
|
+
newPreservedToolCalls[index] = message.tool_calls;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
setPreservedToolCalls(newPreservedToolCalls);
|
|
51
|
+
}, [messages]);
|
|
52
|
+
|
|
25
53
|
const reversedEditOperations = [...editOperations].reverse();
|
|
26
54
|
|
|
27
55
|
const canReject =
|
|
@@ -32,32 +60,165 @@ export function AiResponseMessage({
|
|
|
32
60
|
!editContext.editHistory[index]?.canUndo,
|
|
33
61
|
) === undefined;
|
|
34
62
|
|
|
63
|
+
// Helper function to render JSON or text
|
|
64
|
+
const renderJsonOrText = (json: string) => {
|
|
65
|
+
try {
|
|
66
|
+
const parsed = JSON.parse(json);
|
|
67
|
+
return (
|
|
68
|
+
<div className="font-mono text-xs whitespace-pre-wrap">
|
|
69
|
+
<pre className="break-words whitespace-pre-wrap">
|
|
70
|
+
{JSON.stringify(parsed, null, 2)}
|
|
71
|
+
</pre>
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
} catch (e) {
|
|
75
|
+
return (
|
|
76
|
+
<div className="font-mono text-xs break-words whitespace-pre-wrap">
|
|
77
|
+
{json}
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// Helper function to create tabs for a tool call
|
|
84
|
+
const createToolCallTabs = (
|
|
85
|
+
toolCall: any,
|
|
86
|
+
result: Message | undefined,
|
|
87
|
+
): Tab[] => {
|
|
88
|
+
const tabs: Tab[] = [
|
|
89
|
+
{
|
|
90
|
+
id: `input-${toolCall.id}`,
|
|
91
|
+
label: "Input",
|
|
92
|
+
content: (
|
|
93
|
+
<div className="max-h-96 overflow-auto p-2">
|
|
94
|
+
<div className="mb-1 text-sm font-semibold text-gray-700">
|
|
95
|
+
Arguments:
|
|
96
|
+
</div>
|
|
97
|
+
<div className="text-xs">
|
|
98
|
+
{renderJsonOrText(toolCall.function.arguments)}
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
),
|
|
102
|
+
},
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
if (result) {
|
|
106
|
+
tabs.push({
|
|
107
|
+
id: `output-${toolCall.id}`,
|
|
108
|
+
label: "Output",
|
|
109
|
+
content: (
|
|
110
|
+
<div className="max-h-96 overflow-auto p-2">
|
|
111
|
+
<div className="mb-1 text-sm font-semibold text-gray-700">
|
|
112
|
+
Result:
|
|
113
|
+
</div>
|
|
114
|
+
<div className="text-xs">
|
|
115
|
+
{renderJsonOrText(result.content || "")}
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return tabs;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// Helper function to create tool call popover content
|
|
126
|
+
const ToolCallPopover = ({
|
|
127
|
+
toolCall,
|
|
128
|
+
result,
|
|
129
|
+
}: {
|
|
130
|
+
toolCall: any;
|
|
131
|
+
result: Message | undefined;
|
|
132
|
+
}) => {
|
|
133
|
+
const [activeTab, setActiveTab] = useState(0);
|
|
134
|
+
const tabs = createToolCallTabs(toolCall, result);
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<div className="w-96">
|
|
138
|
+
<div className="mb-3 border-b border-gray-200 pb-2">
|
|
139
|
+
<div className="text-sm font-semibold text-gray-800">
|
|
140
|
+
{toolCall.displayName || toolCall.function.name}
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
<SimpleTabs
|
|
144
|
+
tabs={tabs}
|
|
145
|
+
activeTab={activeTab}
|
|
146
|
+
setActiveTab={setActiveTab}
|
|
147
|
+
className="mb-3 border-b border-gray-200"
|
|
148
|
+
tabClassName="text-xs"
|
|
149
|
+
/>
|
|
150
|
+
</div>
|
|
151
|
+
);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// Helper function to find tool result by tool call id
|
|
155
|
+
const findToolResult = (toolCallId: string): Message | undefined => {
|
|
156
|
+
return messages.find(
|
|
157
|
+
(msg) => msg.role === "tool" && msg.tool_call_id === toolCallId,
|
|
158
|
+
);
|
|
159
|
+
};
|
|
160
|
+
|
|
35
161
|
return (
|
|
36
162
|
<div>
|
|
37
163
|
{messages
|
|
38
164
|
.filter((x) => x.role !== "tool")
|
|
39
|
-
.map((message,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
165
|
+
.map((message, filteredIndex) => {
|
|
166
|
+
// Find the original index of this message in the unfiltered array
|
|
167
|
+
const originalIndex = messages.findIndex((m) => m.id === message.id);
|
|
168
|
+
// Use preserved tool calls if current message has empty tool calls
|
|
169
|
+
const toolCalls =
|
|
170
|
+
message.tool_calls && message.tool_calls.length > 0
|
|
171
|
+
? message.tool_calls
|
|
172
|
+
: preservedToolCalls[originalIndex] || [];
|
|
173
|
+
return (
|
|
174
|
+
<div key={filteredIndex}>
|
|
175
|
+
{toolCalls.length > 0 && (
|
|
176
|
+
<div className="mb-2 flex flex-wrap gap-2">
|
|
177
|
+
{toolCalls.map((toolCall, toolIndex) => {
|
|
178
|
+
const toolResult = findToolResult(toolCall.id);
|
|
179
|
+
return (
|
|
180
|
+
<Popover
|
|
181
|
+
key={toolIndex}
|
|
182
|
+
enableIframeClickDetection={false}
|
|
183
|
+
>
|
|
184
|
+
<PopoverTrigger asChild>
|
|
185
|
+
<div className="inline-flex cursor-pointer items-center gap-1 text-xs text-gray-500 hover:text-gray-700">
|
|
186
|
+
<i className="pi pi-wrench text-xs" />
|
|
187
|
+
<span>
|
|
188
|
+
{toolCall?.displayName ||
|
|
189
|
+
toolCall?.function?.name ||
|
|
190
|
+
"tool call"}
|
|
191
|
+
</span>
|
|
192
|
+
</div>
|
|
193
|
+
</PopoverTrigger>
|
|
194
|
+
<PopoverContent
|
|
195
|
+
className="p-3"
|
|
196
|
+
align="start"
|
|
197
|
+
side="bottom"
|
|
198
|
+
sideOffset={8}
|
|
199
|
+
onMouseDown={(e) => e.stopPropagation()}
|
|
200
|
+
onClick={(e) => e.stopPropagation()}
|
|
201
|
+
>
|
|
202
|
+
<div className="max-h-[500px] overflow-hidden">
|
|
203
|
+
<ToolCallPopover
|
|
204
|
+
toolCall={toolCall}
|
|
205
|
+
result={toolResult}
|
|
206
|
+
/>
|
|
207
|
+
</div>
|
|
208
|
+
</PopoverContent>
|
|
209
|
+
</Popover>
|
|
210
|
+
);
|
|
211
|
+
})}
|
|
212
|
+
</div>
|
|
213
|
+
)}
|
|
214
|
+
<div
|
|
215
|
+
dangerouslySetInnerHTML={{
|
|
216
|
+
__html: message.formattedContent || message.content || "",
|
|
217
|
+
}}
|
|
218
|
+
/>
|
|
219
|
+
</div>
|
|
220
|
+
);
|
|
221
|
+
})}
|
|
61
222
|
{/* <div
|
|
62
223
|
dangerouslySetInnerHTML={{
|
|
63
224
|
__html: responseText.replaceAll("\\n", "<br>"),
|