@alpaca-editor/core 1.0.4033 → 1.0.4037
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/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/index.js.map +1 -1
- package/dist/{editor/menubar → components/ui}/LanguageSelector.d.ts +1 -1
- package/dist/{editor/menubar → components/ui}/LanguageSelector.js +8 -8
- package/dist/components/ui/LanguageSelector.js.map +1 -0
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/components/ui/dropdown-menu.d.ts +1 -1
- package/dist/components/ui/dropdown-menu.js +2 -2
- package/dist/components/ui/dropdown-menu.js.map +1 -1
- package/dist/components/ui/sonner.js +3 -1
- package/dist/components/ui/sonner.js.map +1 -1
- package/dist/config/config.js +5 -5
- package/dist/config/config.js.map +1 -1
- package/dist/editor/ContentTree.d.ts +2 -1
- package/dist/editor/ContentTree.js +33 -9
- package/dist/editor/ContentTree.js.map +1 -1
- package/dist/editor/PictureEditor.js +2 -2
- package/dist/editor/PictureEditor.js.map +1 -1
- package/dist/editor/ScrollingContentTree.d.ts +2 -1
- package/dist/editor/ScrollingContentTree.js +2 -2
- package/dist/editor/ScrollingContentTree.js.map +1 -1
- package/dist/editor/Terminal.d.ts +2 -0
- package/dist/editor/Terminal.js +2 -2
- package/dist/editor/Terminal.js.map +1 -1
- package/dist/editor/ai/AgentHistory.d.ts +11 -0
- package/dist/editor/ai/AgentHistory.js +12 -0
- package/dist/editor/ai/AgentHistory.js.map +1 -0
- package/dist/editor/ai/Agents.js +187 -24
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/AiResponseMessage.d.ts +2 -1
- package/dist/editor/ai/AiResponseMessage.js +6 -6
- package/dist/editor/ai/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/AiTerminal.d.ts +1 -0
- package/dist/editor/ai/AiTerminal.js +330 -43
- package/dist/editor/ai/AiTerminal.js.map +1 -1
- package/dist/editor/client/itemsRepository.js +19 -7
- package/dist/editor/client/itemsRepository.js.map +1 -1
- package/dist/editor/field-types/InternalLinkFieldEditor.js +48 -1
- package/dist/editor/field-types/InternalLinkFieldEditor.js.map +1 -1
- package/dist/editor/field-types/richtext/contextMenuFactory.js +1 -1
- package/dist/editor/field-types/richtext/contextMenuFactory.js.map +1 -1
- package/dist/editor/menubar/ItemLanguageVersion.js +1 -1
- package/dist/editor/menubar/ItemLanguageVersion.js.map +1 -1
- package/dist/editor/menubar/PageSelector.js +1 -1
- package/dist/editor/menubar/PageSelector.js.map +1 -1
- package/dist/editor/page-editor-chrome/FieldActionIndicator.js +1 -1
- package/dist/editor/page-editor-chrome/FieldActionIndicator.js.map +1 -1
- package/dist/editor/page-editor-chrome/FieldEditedIndicator.js +2 -2
- package/dist/editor/page-editor-chrome/FieldEditedIndicator.js.map +1 -1
- package/dist/editor/page-editor-chrome/FrameMenu.js +2 -2
- package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
- package/dist/editor/page-editor-chrome/InlineEditor.js +9 -9
- package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -1
- package/dist/editor/page-editor-chrome/LockedFieldIndicator.js +2 -2
- package/dist/editor/page-editor-chrome/LockedFieldIndicator.js.map +1 -1
- package/dist/editor/page-editor-chrome/PageEditorChrome.js +1 -1
- package/dist/editor/page-editor-chrome/PageEditorChrome.js.map +1 -1
- package/dist/editor/page-editor-chrome/PictureEditorOverlay.js +1 -1
- package/dist/editor/page-editor-chrome/PictureEditorOverlay.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +2 -2
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
- package/dist/editor/page-editor-chrome/useInlineAICompletion.js +12 -12
- package/dist/editor/page-editor-chrome/useInlineAICompletion.js.map +1 -1
- package/dist/editor/page-viewer/EditorForm.js +1 -1
- package/dist/editor/page-viewer/EditorForm.js.map +1 -1
- package/dist/editor/page-viewer/MiniMap.js +10 -11
- package/dist/editor/page-viewer/MiniMap.js.map +1 -1
- package/dist/editor/page-viewer/PageViewer.js +2 -2
- package/dist/editor/page-viewer/PageViewer.js.map +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.js +4 -4
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/page-viewer/pageViewContext.d.ts +2 -2
- package/dist/editor/page-viewer/pageViewContext.js +11 -14
- package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +21 -1
- package/dist/editor/services/agentService.js +101 -0
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/editor/services/aiService.d.ts +1 -1
- package/dist/editor/services/aiService.js +1 -2
- package/dist/editor/services/aiService.js.map +1 -1
- package/dist/editor/sidebar/GraphQL.js +5 -6
- package/dist/editor/sidebar/GraphQL.js.map +1 -1
- package/dist/editor/sidebar/MainContentTree.d.ts +2 -1
- package/dist/editor/sidebar/MainContentTree.js +9 -5
- package/dist/editor/sidebar/MainContentTree.js.map +1 -1
- package/dist/editor/ui/Icons.d.ts +5 -0
- package/dist/editor/ui/Icons.js +3 -0
- package/dist/editor/ui/Icons.js.map +1 -1
- package/dist/editor/ui/ItemNameDialogNew.js +26 -14
- package/dist/editor/ui/ItemNameDialogNew.js.map +1 -1
- package/dist/editor/ui/PerfectTree.js +54 -2
- package/dist/editor/ui/PerfectTree.js.map +1 -1
- package/dist/editor/views/CompareView.js +3 -3
- package/dist/editor/views/CompareView.js.map +1 -1
- package/dist/editor/views/EditView.js +1 -1
- package/dist/editor/views/EditView.js.map +1 -1
- package/dist/editor/views/ItemEditor.js +1 -1
- package/dist/editor/views/ItemEditor.js.map +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/page-wizard/steps/ContentStep.js +5 -5
- package/dist/page-wizard/steps/ContentStep.js.map +1 -1
- package/dist/page-wizard/steps/FindItemsStep.js +1 -1
- package/dist/page-wizard/steps/ImagesStep.js +1 -1
- package/dist/page-wizard/steps/ImagesStep.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/SelectStep.js +1 -1
- package/dist/page-wizard/steps/StructureStep.js +28 -11
- package/dist/page-wizard/steps/StructureStep.js.map +1 -1
- package/dist/page-wizard/steps/TranslateStep.d.ts +1 -0
- package/dist/page-wizard/steps/TranslateStep.js +67 -73
- package/dist/page-wizard/steps/TranslateStep.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/splash-screen/NewPage.js +1 -1
- package/dist/splash-screen/NewPage.js.map +1 -1
- package/dist/splash-screen/OpenPage.js +1 -1
- package/dist/splash-screen/OpenPage.js.map +1 -1
- package/dist/styles.css +71 -8
- package/package.json +1 -1
- package/src/components/index.ts +1 -0
- package/src/{editor/menubar → components/ui}/LanguageSelector.tsx +12 -12
- package/src/components/ui/dropdown-menu.tsx +3 -1
- package/src/components/ui/sonner.tsx +5 -1
- package/src/config/config.tsx +4 -3
- package/src/editor/ContentTree.tsx +41 -12
- package/src/editor/PictureEditor.tsx +2 -2
- package/src/editor/ScrollingContentTree.tsx +3 -0
- package/src/editor/Terminal.tsx +16 -7
- package/src/editor/ai/AgentHistory.tsx +85 -0
- package/src/editor/ai/Agents.tsx +256 -88
- package/src/editor/ai/AiResponseMessage.tsx +25 -11
- package/src/editor/ai/AiTerminal.tsx +571 -73
- package/src/editor/client/itemsRepository.ts +29 -12
- package/src/editor/field-types/InternalLinkFieldEditor.tsx +52 -1
- package/src/editor/field-types/richtext/components/SimpleRichTextEditor.css +64 -0
- package/src/editor/field-types/richtext/contextMenuFactory.tsx +7 -8
- package/src/editor/menubar/ItemLanguageVersion.tsx +1 -1
- package/src/editor/menubar/PageSelector.tsx +1 -0
- package/src/editor/page-editor-chrome/FieldActionIndicator.tsx +1 -1
- package/src/editor/page-editor-chrome/FieldEditedIndicator.tsx +3 -3
- package/src/editor/page-editor-chrome/FrameMenu.tsx +2 -2
- package/src/editor/page-editor-chrome/InlineEditor.tsx +9 -12
- package/src/editor/page-editor-chrome/LockedFieldIndicator.tsx +3 -3
- package/src/editor/page-editor-chrome/PageEditorChrome.tsx +3 -3
- package/src/editor/page-editor-chrome/PictureEditorOverlay.tsx +1 -1
- package/src/editor/page-editor-chrome/PlaceholderDropZone.tsx +1 -1
- package/src/editor/page-editor-chrome/PlaceholderDropZones.tsx +2 -2
- package/src/editor/page-editor-chrome/useInlineAICompletion.tsx +12 -18
- package/src/editor/page-viewer/EditorForm.tsx +1 -1
- package/src/editor/page-viewer/MiniMap.tsx +10 -11
- package/src/editor/page-viewer/PageViewer.tsx +8 -3
- package/src/editor/page-viewer/PageViewerFrame.tsx +4 -4
- package/src/editor/page-viewer/pageViewContext.ts +71 -66
- package/src/editor/services/agentService.ts +129 -1
- package/src/editor/services/aiService.ts +2 -4
- package/src/editor/sidebar/GraphQL.tsx +16 -15
- package/src/editor/sidebar/MainContentTree.tsx +12 -4
- package/src/editor/ui/Icons.tsx +35 -0
- package/src/editor/ui/ItemNameDialogNew.tsx +29 -13
- package/src/editor/ui/PerfectTree.tsx +70 -4
- package/src/editor/views/CompareView.tsx +3 -3
- package/src/editor/views/EditView.tsx +1 -1
- package/src/editor/views/ItemEditor.tsx +1 -1
- package/src/index.ts +10 -4
- package/src/page-wizard/steps/ContentStep.tsx +5 -5
- package/src/page-wizard/steps/FindItemsStep.tsx +1 -1
- package/src/page-wizard/steps/ImagesStep.tsx +1 -1
- package/src/page-wizard/steps/LayoutStep.tsx +1 -1
- package/src/page-wizard/steps/MetaDataStep.tsx +1 -1
- package/src/page-wizard/steps/SelectStep.tsx +1 -1
- package/src/page-wizard/steps/StructureStep.tsx +41 -17
- package/src/page-wizard/steps/TranslateStep.tsx +326 -222
- package/src/revision.ts +2 -2
- package/src/splash-screen/NewPage.tsx +1 -0
- package/src/splash-screen/OpenPage.tsx +1 -0
- package/dist/components/SimpleLanguageSelector.d.ts +0 -10
- package/dist/components/SimpleLanguageSelector.js +0 -59
- package/dist/components/SimpleLanguageSelector.js.map +0 -1
- package/dist/editor/menubar/LanguageSelector.js.map +0 -1
- package/src/components/SimpleLanguageSelector.tsx +0 -113
package/src/editor/ai/Agents.tsx
CHANGED
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
import React, { useState, useRef, useEffect } from "react";
|
|
2
2
|
import { AiTerminalOptions } from "./AiTerminal";
|
|
3
3
|
import { EditorAiTerminal } from "./EditorAiTerminal";
|
|
4
|
+
import { AgentHistory } from "./AgentHistory";
|
|
4
5
|
import { SimpleIconButton } from "../ui/SimpleIconButton";
|
|
5
|
-
import { Plus, X,
|
|
6
|
+
import { Plus, X, MoreHorizontal } from "lucide-react";
|
|
6
7
|
import { cn } from "../../lib/utils";
|
|
7
8
|
import {
|
|
8
9
|
getAgents,
|
|
9
10
|
getAgent,
|
|
10
11
|
getChatHistory,
|
|
12
|
+
closeAgent,
|
|
13
|
+
deleteAgent,
|
|
11
14
|
AgentChat,
|
|
12
15
|
AgentChatMessage,
|
|
13
16
|
} from "../services/agentService";
|
|
14
17
|
import { Message } from "./AiTerminal";
|
|
15
18
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
DropdownMenu,
|
|
20
|
+
DropdownMenuContent,
|
|
21
|
+
DropdownMenuItem,
|
|
22
|
+
DropdownMenuTrigger,
|
|
23
|
+
} from "../../components/ui/dropdown-menu";
|
|
24
|
+
|
|
21
25
|
import { useEditContext } from "../client/editContext";
|
|
22
26
|
import { AiContext } from "./AiTerminal";
|
|
23
27
|
|
|
@@ -76,9 +80,10 @@ export function Agents({
|
|
|
76
80
|
}) {
|
|
77
81
|
const [terminals, setTerminals] = useState<TerminalInstance[]>([]);
|
|
78
82
|
const [activeTerminalId, setActiveTerminalId] = useState<string | null>(null);
|
|
79
|
-
const [
|
|
83
|
+
const [closedAgents, setClosedAgents] = useState<AgentChat[]>([]);
|
|
80
84
|
const [historyPopoverOpen, setHistoryPopoverOpen] = useState(false);
|
|
81
85
|
const [loadingAgents, setLoadingAgents] = useState(true);
|
|
86
|
+
|
|
82
87
|
const nextTerminalNumber = useRef(1);
|
|
83
88
|
const editContext = useEditContext();
|
|
84
89
|
|
|
@@ -101,15 +106,11 @@ export function Agents({
|
|
|
101
106
|
setLoadingAgents(true);
|
|
102
107
|
const context = createAgentContext();
|
|
103
108
|
|
|
104
|
-
// Load
|
|
105
|
-
const activeAgentsResult = await getAgents(context
|
|
109
|
+
// Load all non-closed agents
|
|
110
|
+
const activeAgentsResult = await getAgents(context);
|
|
106
111
|
|
|
107
|
-
// Load
|
|
108
|
-
const
|
|
109
|
-
context,
|
|
110
|
-
"completed",
|
|
111
|
-
20,
|
|
112
|
-
);
|
|
112
|
+
// Load closed agents for history
|
|
113
|
+
const closedAgentsResult = await getChatHistory(context, "closed", 20);
|
|
113
114
|
|
|
114
115
|
if (activeAgentsResult && Array.isArray(activeAgentsResult)) {
|
|
115
116
|
const activeAgents = activeAgentsResult;
|
|
@@ -162,8 +163,8 @@ export function Agents({
|
|
|
162
163
|
}
|
|
163
164
|
}
|
|
164
165
|
|
|
165
|
-
if (
|
|
166
|
-
|
|
166
|
+
if (closedAgentsResult && Array.isArray(closedAgentsResult)) {
|
|
167
|
+
setClosedAgents(closedAgentsResult);
|
|
167
168
|
}
|
|
168
169
|
} catch (error) {
|
|
169
170
|
console.error("Failed to load agents:", error);
|
|
@@ -218,22 +219,165 @@ export function Agents({
|
|
|
218
219
|
nextTerminalNumber.current++;
|
|
219
220
|
};
|
|
220
221
|
|
|
221
|
-
const closeTerminal = (terminalId: string) => {
|
|
222
|
-
|
|
223
|
-
|
|
222
|
+
const closeTerminal = async (terminalId: string) => {
|
|
223
|
+
const terminal = terminals.find((t) => t.id === terminalId);
|
|
224
|
+
if (!terminal) return;
|
|
225
|
+
|
|
226
|
+
// If this terminal has an associated agent, show confirmation
|
|
227
|
+
if (terminal.agentId) {
|
|
228
|
+
editContext?.confirm({
|
|
229
|
+
header: "Close Agent",
|
|
230
|
+
message:
|
|
231
|
+
"Are you sure you want to close this agent? This will abort any running execution and mark the agent as closed.",
|
|
232
|
+
acceptLabel: "Close Agent",
|
|
233
|
+
rejectLabel: "Cancel",
|
|
234
|
+
accept: () => performCloseTerminal(terminalId),
|
|
235
|
+
reject: () => {}, // Do nothing on reject
|
|
236
|
+
});
|
|
224
237
|
return;
|
|
225
238
|
}
|
|
226
239
|
|
|
227
|
-
|
|
228
|
-
|
|
240
|
+
// For terminals without agents, close immediately
|
|
241
|
+
performCloseTerminal(terminalId);
|
|
242
|
+
};
|
|
229
243
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
244
|
+
const performCloseTerminal = async (terminalId: string) => {
|
|
245
|
+
const terminal = terminals.find((t) => t.id === terminalId);
|
|
246
|
+
|
|
247
|
+
try {
|
|
248
|
+
// If this terminal has an associated agent, close it in the backend
|
|
249
|
+
if (terminal?.agentId) {
|
|
250
|
+
const context = createAgentContext();
|
|
251
|
+
await closeAgent(terminal.agentId, context);
|
|
233
252
|
}
|
|
234
253
|
|
|
235
|
-
|
|
236
|
-
|
|
254
|
+
// Remove terminal from local state
|
|
255
|
+
setTerminals((prev) => {
|
|
256
|
+
const filtered = prev.filter((t) => t.id !== terminalId);
|
|
257
|
+
|
|
258
|
+
// If we're closing the active terminal, switch to the first remaining one
|
|
259
|
+
// or create a new one if this was the last terminal
|
|
260
|
+
if (activeTerminalId === terminalId) {
|
|
261
|
+
if (filtered.length > 0) {
|
|
262
|
+
setActiveTerminalId(filtered[0]!.id);
|
|
263
|
+
} else {
|
|
264
|
+
// Create a new terminal if this was the last one
|
|
265
|
+
const newTerminal: TerminalInstance = {
|
|
266
|
+
id: `terminal-${nextTerminalNumber.current}`,
|
|
267
|
+
title: "New Agent",
|
|
268
|
+
options: initialOptions,
|
|
269
|
+
};
|
|
270
|
+
nextTerminalNumber.current++;
|
|
271
|
+
setActiveTerminalId(newTerminal.id);
|
|
272
|
+
return [newTerminal];
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return filtered;
|
|
277
|
+
});
|
|
278
|
+
} catch (error) {
|
|
279
|
+
console.error("Failed to close agent:", error);
|
|
280
|
+
editContext?.showToast("Failed to close agent. Removing from UI.");
|
|
281
|
+
// Still remove the terminal from UI even if backend call fails
|
|
282
|
+
setTerminals((prev) => prev.filter((t) => t.id !== terminalId));
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const closeOtherTerminals = async () => {
|
|
287
|
+
if (!activeTerminalId || terminals.length <= 1) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Get all terminals except the active one
|
|
292
|
+
const otherTerminals = terminals.filter((t) => t.id !== activeTerminalId);
|
|
293
|
+
|
|
294
|
+
// Show confirmation if any of the other terminals have agents
|
|
295
|
+
const hasAgents = otherTerminals.some((t) => t.agentId);
|
|
296
|
+
|
|
297
|
+
if (hasAgents) {
|
|
298
|
+
editContext?.confirm({
|
|
299
|
+
header: "Close Other Agents",
|
|
300
|
+
message: `Are you sure you want to close ${otherTerminals.length} other agent${otherTerminals.length > 1 ? "s" : ""}? This will abort any running executions and mark them as closed.`,
|
|
301
|
+
acceptLabel: "Close Others",
|
|
302
|
+
rejectLabel: "Cancel",
|
|
303
|
+
accept: async () => {
|
|
304
|
+
// Close all other terminals
|
|
305
|
+
for (const terminal of otherTerminals) {
|
|
306
|
+
try {
|
|
307
|
+
if (terminal.agentId) {
|
|
308
|
+
const context = createAgentContext();
|
|
309
|
+
await closeAgent(terminal.agentId, context);
|
|
310
|
+
}
|
|
311
|
+
} catch (error) {
|
|
312
|
+
console.error("Failed to close agent:", error);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Keep only the active terminal
|
|
317
|
+
const activeTerminal = terminals.find(
|
|
318
|
+
(t) => t.id === activeTerminalId,
|
|
319
|
+
);
|
|
320
|
+
if (activeTerminal) {
|
|
321
|
+
setTerminals([activeTerminal]);
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
reject: () => {}, // Do nothing on reject
|
|
325
|
+
});
|
|
326
|
+
} else {
|
|
327
|
+
// No agents, just close immediately
|
|
328
|
+
const activeTerminal = terminals.find((t) => t.id === activeTerminalId);
|
|
329
|
+
if (activeTerminal) {
|
|
330
|
+
setTerminals([activeTerminal]);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
const closeAllTerminals = async () => {
|
|
336
|
+
// Show confirmation if any terminals have agents
|
|
337
|
+
const hasAgents = terminals.some((t) => t.agentId);
|
|
338
|
+
|
|
339
|
+
if (hasAgents) {
|
|
340
|
+
editContext?.confirm({
|
|
341
|
+
header: "Close All Agents",
|
|
342
|
+
message: `Are you sure you want to close all ${terminals.length} agent${terminals.length > 1 ? "s" : ""}? This will abort any running executions and mark them as closed.`,
|
|
343
|
+
acceptLabel: "Close All",
|
|
344
|
+
rejectLabel: "Cancel",
|
|
345
|
+
accept: async () => {
|
|
346
|
+
// Close all terminals with agents
|
|
347
|
+
for (const terminal of terminals) {
|
|
348
|
+
try {
|
|
349
|
+
if (terminal.agentId) {
|
|
350
|
+
const context = createAgentContext();
|
|
351
|
+
await closeAgent(terminal.agentId, context);
|
|
352
|
+
}
|
|
353
|
+
} catch (error) {
|
|
354
|
+
console.error("Failed to close agent:", error);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Create a new default terminal
|
|
359
|
+
const defaultTerminal: TerminalInstance = {
|
|
360
|
+
id: `terminal-${nextTerminalNumber.current}`,
|
|
361
|
+
title: "New Agent",
|
|
362
|
+
options: initialOptions,
|
|
363
|
+
};
|
|
364
|
+
setTerminals([defaultTerminal]);
|
|
365
|
+
setActiveTerminalId(defaultTerminal.id);
|
|
366
|
+
nextTerminalNumber.current++;
|
|
367
|
+
},
|
|
368
|
+
reject: () => {}, // Do nothing on reject
|
|
369
|
+
});
|
|
370
|
+
} else {
|
|
371
|
+
// No agents, just create a new default terminal
|
|
372
|
+
const defaultTerminal: TerminalInstance = {
|
|
373
|
+
id: `terminal-${nextTerminalNumber.current}`,
|
|
374
|
+
title: "New Agent",
|
|
375
|
+
options: initialOptions,
|
|
376
|
+
};
|
|
377
|
+
setTerminals([defaultTerminal]);
|
|
378
|
+
setActiveTerminalId(defaultTerminal.id);
|
|
379
|
+
nextTerminalNumber.current++;
|
|
380
|
+
}
|
|
237
381
|
};
|
|
238
382
|
|
|
239
383
|
const openAgentFromHistory = async (agent: AgentChat) => {
|
|
@@ -276,10 +420,42 @@ export function Agents({
|
|
|
276
420
|
setHistoryPopoverOpen(false);
|
|
277
421
|
};
|
|
278
422
|
|
|
423
|
+
const deleteAgentFromHistory = async (agent: AgentChat) => {
|
|
424
|
+
editContext?.confirm({
|
|
425
|
+
header: "Delete Agent",
|
|
426
|
+
message: `Are you sure you want to permanently delete "${agent.name}"? This action cannot be undone and will remove the agent and all its messages from the database.`,
|
|
427
|
+
acceptLabel: "Delete Permanently",
|
|
428
|
+
rejectLabel: "Cancel",
|
|
429
|
+
accept: async () => {
|
|
430
|
+
try {
|
|
431
|
+
const context = createAgentContext();
|
|
432
|
+
await deleteAgent(agent.id, context);
|
|
433
|
+
|
|
434
|
+
// Remove from closed agents list
|
|
435
|
+
setClosedAgents((prev) => prev.filter((a) => a.id !== agent.id));
|
|
436
|
+
|
|
437
|
+
// If this agent is currently open as a terminal, close it
|
|
438
|
+
const existingTerminal = terminals.find(
|
|
439
|
+
(t) => t.agentId === agent.id,
|
|
440
|
+
);
|
|
441
|
+
if (existingTerminal) {
|
|
442
|
+
performCloseTerminal(existingTerminal.id);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
editContext?.showToast("Agent deleted successfully");
|
|
446
|
+
} catch (error) {
|
|
447
|
+
console.error("Failed to delete agent:", error);
|
|
448
|
+
editContext?.showToast("Failed to delete agent. Please try again.");
|
|
449
|
+
}
|
|
450
|
+
},
|
|
451
|
+
reject: () => {}, // Do nothing on reject
|
|
452
|
+
});
|
|
453
|
+
};
|
|
454
|
+
|
|
279
455
|
if (loadingAgents) {
|
|
280
456
|
return (
|
|
281
457
|
<div className="flex h-full items-center justify-center">
|
|
282
|
-
<div className="text-
|
|
458
|
+
<div className="text-xs text-gray-500">Loading agents...</div>
|
|
283
459
|
</div>
|
|
284
460
|
);
|
|
285
461
|
}
|
|
@@ -288,7 +464,7 @@ export function Agents({
|
|
|
288
464
|
<div className="flex h-full flex-col">
|
|
289
465
|
{/* Tab Header */}
|
|
290
466
|
<div className="flex items-center border-b border-gray-200 bg-gray-50">
|
|
291
|
-
<div className="flex flex-1 overflow-x-auto">
|
|
467
|
+
<div className="flex flex-1 overflow-x-auto [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden">
|
|
292
468
|
{terminals.map((terminal) => (
|
|
293
469
|
<div
|
|
294
470
|
key={terminal.id}
|
|
@@ -301,66 +477,17 @@ export function Agents({
|
|
|
301
477
|
onClick={() => setActiveTerminalId(terminal.id)}
|
|
302
478
|
>
|
|
303
479
|
<span className="truncate">{terminal.title}</span>
|
|
304
|
-
{terminals.length > 1 && (
|
|
305
|
-
<SimpleIconButton
|
|
306
|
-
onClick={(e) => {
|
|
307
|
-
e.stopPropagation();
|
|
308
|
-
closeTerminal(terminal.id);
|
|
309
|
-
}}
|
|
310
|
-
icon={<X className="size-2" />}
|
|
311
|
-
label="Close"
|
|
312
|
-
className="ml-1 opacity-60 hover:opacity-100"
|
|
313
|
-
/>
|
|
314
|
-
)}
|
|
315
|
-
</div>
|
|
316
|
-
))}
|
|
317
|
-
</div>
|
|
318
|
-
|
|
319
|
-
{/* History Popover */}
|
|
320
|
-
<div className="flex items-center px-1">
|
|
321
|
-
<Popover
|
|
322
|
-
open={historyPopoverOpen}
|
|
323
|
-
onOpenChange={setHistoryPopoverOpen}
|
|
324
|
-
>
|
|
325
|
-
<PopoverTrigger asChild>
|
|
326
480
|
<SimpleIconButton
|
|
327
|
-
onClick={() => {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
481
|
+
onClick={(e) => {
|
|
482
|
+
e.stopPropagation();
|
|
483
|
+
closeTerminal(terminal.id);
|
|
484
|
+
}}
|
|
485
|
+
icon={<X className="size-3" />}
|
|
486
|
+
label="Close"
|
|
487
|
+
className="ml-1 opacity-60 hover:opacity-100"
|
|
331
488
|
/>
|
|
332
|
-
</
|
|
333
|
-
|
|
334
|
-
<div className="border-b border-gray-100 px-3 py-2 text-xs font-medium text-gray-500">
|
|
335
|
-
Agent History
|
|
336
|
-
</div>
|
|
337
|
-
<div className="max-h-80 overflow-y-auto">
|
|
338
|
-
{inactiveAgents.length === 0 ? (
|
|
339
|
-
<div className="px-3 py-2 text-xs text-gray-500">
|
|
340
|
-
No previous agents found
|
|
341
|
-
</div>
|
|
342
|
-
) : (
|
|
343
|
-
inactiveAgents.map((agent) => (
|
|
344
|
-
<div
|
|
345
|
-
key={agent.id}
|
|
346
|
-
className="cursor-pointer border-b border-gray-50 px-3 py-2 text-xs hover:bg-gray-50"
|
|
347
|
-
onClick={() => openAgentFromHistory(agent)}
|
|
348
|
-
>
|
|
349
|
-
<div className="truncate font-medium text-gray-900">
|
|
350
|
-
{agent.name}
|
|
351
|
-
</div>
|
|
352
|
-
<div className="truncate text-gray-500">
|
|
353
|
-
{agent.profileName}
|
|
354
|
-
</div>
|
|
355
|
-
<div className="text-xs text-gray-400">
|
|
356
|
-
{formatDateToLocalTime(agent.updatedDate)}
|
|
357
|
-
</div>
|
|
358
|
-
</div>
|
|
359
|
-
))
|
|
360
|
-
)}
|
|
361
|
-
</div>
|
|
362
|
-
</PopoverContent>
|
|
363
|
-
</Popover>
|
|
489
|
+
</div>
|
|
490
|
+
))}
|
|
364
491
|
</div>
|
|
365
492
|
|
|
366
493
|
{/* Add Terminal Button */}
|
|
@@ -368,11 +495,52 @@ export function Agents({
|
|
|
368
495
|
<SimpleIconButton
|
|
369
496
|
onClick={addTerminal}
|
|
370
497
|
icon={<Plus className="size-4" />}
|
|
371
|
-
label="Add
|
|
498
|
+
label="Add Agent"
|
|
372
499
|
className="text-gray-600 hover:text-gray-800"
|
|
373
500
|
/>
|
|
374
501
|
</div>
|
|
375
502
|
|
|
503
|
+
{/* Agent History */}
|
|
504
|
+
<div className="flex items-center px-1">
|
|
505
|
+
<AgentHistory
|
|
506
|
+
closedAgents={closedAgents}
|
|
507
|
+
isOpen={historyPopoverOpen}
|
|
508
|
+
onOpenChange={setHistoryPopoverOpen}
|
|
509
|
+
onOpenAgent={openAgentFromHistory}
|
|
510
|
+
onDeleteAgent={deleteAgentFromHistory}
|
|
511
|
+
formatDateToLocalTime={formatDateToLocalTime}
|
|
512
|
+
/>
|
|
513
|
+
</div>
|
|
514
|
+
|
|
515
|
+
{/* More Options Menu */}
|
|
516
|
+
<div className="flex items-center px-1">
|
|
517
|
+
<DropdownMenu>
|
|
518
|
+
<DropdownMenuTrigger asChild>
|
|
519
|
+
<SimpleIconButton
|
|
520
|
+
onClick={() => {}}
|
|
521
|
+
icon={<MoreHorizontal className="size-4" />}
|
|
522
|
+
label="More Options"
|
|
523
|
+
className="text-gray-600 hover:text-gray-800"
|
|
524
|
+
/>
|
|
525
|
+
</DropdownMenuTrigger>
|
|
526
|
+
<DropdownMenuContent align="end">
|
|
527
|
+
<DropdownMenuItem
|
|
528
|
+
onClick={closeOtherTerminals}
|
|
529
|
+
disabled={terminals.length <= 1}
|
|
530
|
+
className="cursor-pointer"
|
|
531
|
+
>
|
|
532
|
+
Close Other
|
|
533
|
+
</DropdownMenuItem>
|
|
534
|
+
<DropdownMenuItem
|
|
535
|
+
onClick={closeAllTerminals}
|
|
536
|
+
className="cursor-pointer"
|
|
537
|
+
>
|
|
538
|
+
Close All
|
|
539
|
+
</DropdownMenuItem>
|
|
540
|
+
</DropdownMenuContent>
|
|
541
|
+
</DropdownMenu>
|
|
542
|
+
</div>
|
|
543
|
+
|
|
376
544
|
{/* Main Close Button */}
|
|
377
545
|
{closeButton && (
|
|
378
546
|
<div className="flex items-center px-2">{closeButton}</div>
|
|
@@ -78,10 +78,12 @@ export function AiResponseMessage({
|
|
|
78
78
|
messages,
|
|
79
79
|
finished,
|
|
80
80
|
editOperations,
|
|
81
|
+
error,
|
|
81
82
|
}: {
|
|
82
83
|
messages: Message[];
|
|
83
84
|
finished: boolean;
|
|
84
85
|
editOperations: EditOperation[];
|
|
86
|
+
error?: string;
|
|
85
87
|
}) {
|
|
86
88
|
const editContext = useEditContext();
|
|
87
89
|
if (!editContext) return <></>;
|
|
@@ -206,11 +208,9 @@ export function AiResponseMessage({
|
|
|
206
208
|
id: `input-${toolCall.id}`,
|
|
207
209
|
label: "Input",
|
|
208
210
|
content: (
|
|
209
|
-
<div className="
|
|
210
|
-
<div className="
|
|
211
|
-
|
|
212
|
-
{renderJsonOrText(toolCall.function.arguments)}
|
|
213
|
-
</div>
|
|
211
|
+
<div className="h-[250px] w-full overflow-auto p-2">
|
|
212
|
+
<div className="text-xs">
|
|
213
|
+
{renderJsonOrText(toolCall.function.arguments)}
|
|
214
214
|
</div>
|
|
215
215
|
</div>
|
|
216
216
|
),
|
|
@@ -222,10 +222,8 @@ export function AiResponseMessage({
|
|
|
222
222
|
id: `output-${toolCall.id}`,
|
|
223
223
|
label: "Output",
|
|
224
224
|
content: (
|
|
225
|
-
<div className="
|
|
226
|
-
<div className="
|
|
227
|
-
<div className="text-xs">{renderJsonOrText(result || "")}</div>
|
|
228
|
-
</div>
|
|
225
|
+
<div className="h-[250px] w-full overflow-auto p-2">
|
|
226
|
+
<div className="text-xs">{renderJsonOrText(result || "")}</div>
|
|
229
227
|
</div>
|
|
230
228
|
),
|
|
231
229
|
});
|
|
@@ -248,7 +246,7 @@ export function AiResponseMessage({
|
|
|
248
246
|
const tabs = createToolCallTabs(toolCall, result || "");
|
|
249
247
|
|
|
250
248
|
return (
|
|
251
|
-
<div className="
|
|
249
|
+
<div className="flex flex-col p-3">
|
|
252
250
|
<div className="mb-3 flex items-center justify-between border-b border-gray-200 px-2 pb-1">
|
|
253
251
|
<div className="flex items-center gap-2 text-sm font-semibold text-gray-800">
|
|
254
252
|
{getToolIcon(toolCall?.function?.name || "")}
|
|
@@ -275,6 +273,22 @@ export function AiResponseMessage({
|
|
|
275
273
|
|
|
276
274
|
return (
|
|
277
275
|
<div>
|
|
276
|
+
{error && (
|
|
277
|
+
<div
|
|
278
|
+
className="mb-3 rounded-lg border-l-4 border-red-500 bg-red-50 p-3"
|
|
279
|
+
data-testid="agent-error"
|
|
280
|
+
>
|
|
281
|
+
<div className="flex items-start">
|
|
282
|
+
<div className="flex-shrink-0">
|
|
283
|
+
<X className="h-5 w-5 text-red-400" strokeWidth={1} />
|
|
284
|
+
</div>
|
|
285
|
+
<div className="ml-3">
|
|
286
|
+
<p className="text-sm font-medium text-red-800">Agent Error</p>
|
|
287
|
+
<p className="mt-1 text-sm text-red-700">{error}</p>
|
|
288
|
+
</div>
|
|
289
|
+
</div>
|
|
290
|
+
</div>
|
|
291
|
+
)}
|
|
278
292
|
{messages
|
|
279
293
|
.filter((x) => x.role !== "tool" && x.role !== "user")
|
|
280
294
|
.map((message, filteredIndex) => {
|
|
@@ -334,7 +348,7 @@ export function AiResponseMessage({
|
|
|
334
348
|
</div>
|
|
335
349
|
</PopoverTrigger>
|
|
336
350
|
<PopoverContent
|
|
337
|
-
className="w-[
|
|
351
|
+
className="w-[450px] p-0"
|
|
338
352
|
align="start"
|
|
339
353
|
side="bottom"
|
|
340
354
|
sideOffset={8}
|