@parhelia/core 0.1.11873 → 0.1.11955
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/agents-view/AgentsInbox.d.ts +1 -1
- package/dist/agents-view/AgentsInbox.js +15 -2
- package/dist/agents-view/AgentsInbox.js.map +1 -1
- package/dist/agents-view/AgentsSidebar.d.ts +20 -0
- package/dist/agents-view/AgentsSidebar.js +21 -0
- package/dist/agents-view/AgentsSidebar.js.map +1 -0
- package/dist/agents-view/AgentsView.d.ts +6 -7
- package/dist/agents-view/AgentsView.js +63 -25
- package/dist/agents-view/AgentsView.js.map +1 -1
- package/dist/agents-view/AgentsWorkspaceView.d.ts +2 -6
- package/dist/agents-view/AgentsWorkspaceView.js +242 -112
- package/dist/agents-view/AgentsWorkspaceView.js.map +1 -1
- package/dist/components/ui/context-menu.js +24 -9
- package/dist/components/ui/context-menu.js.map +1 -1
- package/dist/components/ui/select.js +1 -1
- package/dist/components/ui/select.js.map +1 -1
- package/dist/config/config.js +15 -11
- package/dist/config/config.js.map +1 -1
- package/dist/editor/ContentTree.js +2 -2
- package/dist/editor/ContentTree.js.map +1 -1
- package/dist/editor/ContextMenu.js +11 -5
- package/dist/editor/ContextMenu.js.map +1 -1
- package/dist/editor/FieldListField.js +1 -1
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/MainLayout.js.map +1 -1
- package/dist/editor/MobileLayout.js +19 -9
- package/dist/editor/MobileLayout.js.map +1 -1
- package/dist/editor/ai/AgentStatusBadge.d.ts +1 -1
- package/dist/editor/ai/AgentStatusBadge.js +18 -2
- package/dist/editor/ai/AgentStatusBadge.js.map +1 -1
- package/dist/editor/ai/AgentTerminal.js +342 -55
- package/dist/editor/ai/AgentTerminal.js.map +1 -1
- package/dist/editor/ai/AiResponseMessage.js +46 -4
- package/dist/editor/ai/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/ContextInfoBar.js +151 -5
- package/dist/editor/ai/ContextInfoBar.js.map +1 -1
- package/dist/editor/ai/EditOperationsPanel.d.ts +2 -1
- package/dist/editor/ai/EditOperationsPanel.js +6 -1
- package/dist/editor/ai/EditOperationsPanel.js.map +1 -1
- package/dist/editor/ai/dialogs/AgentDialogHandler.js +64 -15
- package/dist/editor/ai/dialogs/AgentDialogHandler.js.map +1 -1
- package/dist/editor/ai/dialogs/QuestionnaireInline.js +111 -20
- package/dist/editor/ai/dialogs/QuestionnaireInline.js.map +1 -1
- package/dist/editor/ai/dialogs/agentDialogTypes.d.ts +24 -0
- package/dist/editor/ai/dialogs/agentDialogTypes.js.map +1 -1
- package/dist/editor/ai/useAgentStatus.d.ts +1 -0
- package/dist/editor/ai/useAgentStatus.js +74 -29
- package/dist/editor/ai/useAgentStatus.js.map +1 -1
- package/dist/editor/client/EditorShell.js +72 -8
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/hooks/useQuota.d.ts +7 -0
- package/dist/editor/client/hooks/useQuota.js.map +1 -1
- package/dist/editor/client/hooks/useSocketMessageHandler.js +10 -1
- package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
- package/dist/editor/client/pageModelBuilder.js +3 -30
- package/dist/editor/client/pageModelBuilder.js.map +1 -1
- package/dist/editor/client/ui/EditorChrome.js +31 -1
- package/dist/editor/client/ui/EditorChrome.js.map +1 -1
- package/dist/editor/commands/componentCommands.js +106 -6
- package/dist/editor/commands/componentCommands.js.map +1 -1
- package/dist/editor/commands/itemCommands.d.ts +1 -0
- package/dist/editor/commands/itemCommands.js +28 -1
- package/dist/editor/commands/itemCommands.js.map +1 -1
- package/dist/editor/componentTreeHelper.js +22 -2
- package/dist/editor/componentTreeHelper.js.map +1 -1
- package/dist/editor/insertMenuItems.d.ts +4 -0
- package/dist/editor/insertMenuItems.js +66 -0
- package/dist/editor/insertMenuItems.js.map +1 -0
- package/dist/editor/menubar/toolbar-sections/UtilityControls.js +1 -1
- package/dist/editor/menubar/toolbar-sections/UtilityControls.js.map +1 -1
- package/dist/editor/page-editor-chrome/FrameMenus.js +8 -1
- package/dist/editor/page-editor-chrome/FrameMenus.js.map +1 -1
- package/dist/editor/page-editor-chrome/InlineEditor.js +25 -11
- package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +32 -17
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +17 -11
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
- package/dist/editor/page-viewer/EditorForm.js +6 -5
- package/dist/editor/page-viewer/EditorForm.js.map +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.js +49 -1
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.js +5 -0
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.js.map +1 -1
- package/dist/editor/pageModel.d.ts +2 -0
- package/dist/editor/reviews/CreateReviewConfirmStep.d.ts +16 -0
- package/dist/editor/reviews/CreateReviewConfirmStep.js +37 -0
- package/dist/editor/reviews/CreateReviewConfirmStep.js.map +1 -0
- package/dist/editor/reviews/CreateReviewDetailsStep.d.ts +51 -0
- package/dist/editor/reviews/CreateReviewDetailsStep.js +121 -0
- package/dist/editor/reviews/CreateReviewDetailsStep.js.map +1 -0
- package/dist/editor/reviews/CreateReviewDialog.js +260 -173
- package/dist/editor/reviews/CreateReviewDialog.js.map +1 -1
- package/dist/editor/reviews/CreateReviewSuccessStep.d.ts +6 -0
- package/dist/editor/reviews/CreateReviewSuccessStep.js +8 -0
- package/dist/editor/reviews/CreateReviewSuccessStep.js.map +1 -0
- package/dist/editor/reviews/DecisionsMatrix.js +96 -25
- package/dist/editor/reviews/DecisionsMatrix.js.map +1 -1
- package/dist/editor/reviews/MultiReviewManager.js +25 -3
- package/dist/editor/reviews/MultiReviewManager.js.map +1 -1
- package/dist/editor/reviews/PagesPanel.js +31 -15
- package/dist/editor/reviews/PagesPanel.js.map +1 -1
- package/dist/editor/reviews/ReviewCard.js +13 -7
- package/dist/editor/reviews/ReviewCard.js.map +1 -1
- package/dist/editor/reviews/ReviewDetail.js +2 -2
- package/dist/editor/reviews/ReviewDetail.js.map +1 -1
- package/dist/editor/reviews/ReviewsList.js +7 -3
- package/dist/editor/reviews/ReviewsList.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +14 -1
- package/dist/editor/services/agentService.js +27 -1
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/editor/services/aiService.d.ts +39 -1
- package/dist/editor/services/aiService.js +12 -2
- package/dist/editor/services/aiService.js.map +1 -1
- package/dist/editor/services/serviceHelper.d.ts +1 -1
- package/dist/editor/services/serviceHelper.js +2 -1
- package/dist/editor/services/serviceHelper.js.map +1 -1
- package/dist/editor/settings/About.js +1 -1
- package/dist/editor/settings/About.js.map +1 -1
- package/dist/editor/settings/QuotaInfo.js +202 -4
- package/dist/editor/settings/QuotaInfo.js.map +1 -1
- package/dist/editor/settings/panels/SearchConfigPanel.js +11 -13
- package/dist/editor/settings/panels/SearchConfigPanel.js.map +1 -1
- package/dist/editor/settings/status/useStartupChecks.js +2 -1
- package/dist/editor/settings/status/useStartupChecks.js.map +1 -1
- package/dist/editor/sidebar/ComponentTree.js +26 -20
- package/dist/editor/sidebar/ComponentTree.js.map +1 -1
- package/dist/editor/sidebar/MobileWorkspacePopover.d.ts +16 -0
- package/dist/editor/sidebar/MobileWorkspacePopover.js +35 -0
- package/dist/editor/sidebar/MobileWorkspacePopover.js.map +1 -0
- package/dist/editor/sidebar/NavigationSidebar.js +30 -14
- package/dist/editor/sidebar/NavigationSidebar.js.map +1 -1
- package/dist/editor/ui/ItemNameDialogNew.js +8 -8
- package/dist/editor/ui/ItemNameDialogNew.js.map +1 -1
- package/dist/editor/ui/SharedFolderSelectorDialog.d.ts +11 -0
- package/dist/editor/ui/SharedFolderSelectorDialog.js +79 -0
- package/dist/editor/ui/SharedFolderSelectorDialog.js.map +1 -0
- package/dist/editor/ui/SimpleTabs.js +1 -1
- package/dist/editor/ui/SimpleTabs.js.map +1 -1
- package/dist/editor/ui/Splitter.js +4 -2
- package/dist/editor/ui/Splitter.js.map +1 -1
- package/dist/editor/ui/TreeListSelector.d.ts +2 -1
- package/dist/editor/ui/TreeListSelector.js +2 -2
- package/dist/editor/ui/TreeListSelector.js.map +1 -1
- package/dist/editor/utils.js +42 -0
- package/dist/editor/utils.js.map +1 -1
- package/dist/editor/views/EditorSlot.js +7 -8
- package/dist/editor/views/EditorSlot.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/setup/wizard/steps/ImportModelDialog.js +24 -22
- package/dist/setup/wizard/steps/ImportModelDialog.js.map +1 -1
- package/dist/splash-screen/NewPage.js +2 -2
- package/dist/splash-screen/NewPage.js.map +1 -1
- package/dist/splash-screen/RecentPages.js +1 -1
- package/dist/splash-screen/RecentPages.js.map +1 -1
- package/dist/task-board/TaskBoardWorkspace.d.ts +1 -0
- package/dist/task-board/TaskBoardWorkspace.js +1094 -0
- package/dist/task-board/TaskBoardWorkspace.js.map +1 -0
- package/dist/task-board/components/AddDependencyDialog.d.ts +8 -0
- package/dist/task-board/components/AddDependencyDialog.js +53 -0
- package/dist/task-board/components/AddDependencyDialog.js.map +1 -0
- package/dist/task-board/components/AssignAgentDialog.d.ts +7 -0
- package/dist/task-board/components/AssignAgentDialog.js +96 -0
- package/dist/task-board/components/AssignAgentDialog.js.map +1 -0
- package/dist/task-board/components/CommentsList.d.ts +3 -0
- package/dist/task-board/components/CommentsList.js +36 -0
- package/dist/task-board/components/CommentsList.js.map +1 -0
- package/dist/task-board/components/CreateProjectDialog.d.ts +7 -0
- package/dist/task-board/components/CreateProjectDialog.js +175 -0
- package/dist/task-board/components/CreateProjectDialog.js.map +1 -0
- package/dist/task-board/components/CreateTaskDialog.d.ts +7 -0
- package/dist/task-board/components/CreateTaskDialog.js +76 -0
- package/dist/task-board/components/CreateTaskDialog.js.map +1 -0
- package/dist/task-board/components/ProjectAgentsPanel.d.ts +4 -0
- package/dist/task-board/components/ProjectAgentsPanel.js +159 -0
- package/dist/task-board/components/ProjectAgentsPanel.js.map +1 -0
- package/dist/task-board/components/ProjectDashboard.d.ts +25 -0
- package/dist/task-board/components/ProjectDashboard.js +91 -0
- package/dist/task-board/components/ProjectDashboard.js.map +1 -0
- package/dist/task-board/components/ProjectList.d.ts +7 -0
- package/dist/task-board/components/ProjectList.js +74 -0
- package/dist/task-board/components/ProjectList.js.map +1 -0
- package/dist/task-board/components/ProjectSettingsDialog.d.ts +8 -0
- package/dist/task-board/components/ProjectSettingsDialog.js +146 -0
- package/dist/task-board/components/ProjectSettingsDialog.js.map +1 -0
- package/dist/task-board/components/TaskAgentPanel.d.ts +10 -0
- package/dist/task-board/components/TaskAgentPanel.js +42 -0
- package/dist/task-board/components/TaskAgentPanel.js.map +1 -0
- package/dist/task-board/components/TaskAssigneePicker.d.ts +12 -0
- package/dist/task-board/components/TaskAssigneePicker.js +115 -0
- package/dist/task-board/components/TaskAssigneePicker.js.map +1 -0
- package/dist/task-board/components/TaskBoardTitlebar.d.ts +1 -0
- package/dist/task-board/components/TaskBoardTitlebar.js +60 -0
- package/dist/task-board/components/TaskBoardTitlebar.js.map +1 -0
- package/dist/task-board/components/TaskCard.d.ts +9 -0
- package/dist/task-board/components/TaskCard.js +24 -0
- package/dist/task-board/components/TaskCard.js.map +1 -0
- package/dist/task-board/components/TaskDetailDialog.d.ts +11 -0
- package/dist/task-board/components/TaskDetailDialog.js +8 -0
- package/dist/task-board/components/TaskDetailDialog.js.map +1 -0
- package/dist/task-board/components/TaskDetailPanel.d.ts +13 -0
- package/dist/task-board/components/TaskDetailPanel.js +322 -0
- package/dist/task-board/components/TaskDetailPanel.js.map +1 -0
- package/dist/task-board/components/TaskRow.d.ts +9 -0
- package/dist/task-board/components/TaskRow.js +25 -0
- package/dist/task-board/components/TaskRow.js.map +1 -0
- package/dist/task-board/index.d.ts +15 -0
- package/dist/task-board/index.js +18 -0
- package/dist/task-board/index.js.map +1 -0
- package/dist/task-board/services/taskService.d.ts +52 -0
- package/dist/task-board/services/taskService.js +74 -0
- package/dist/task-board/services/taskService.js.map +1 -0
- package/dist/task-board/taskAgentConfig.d.ts +7 -0
- package/dist/task-board/taskAgentConfig.js +43 -0
- package/dist/task-board/taskAgentConfig.js.map +1 -0
- package/dist/task-board/taskAgentLink.d.ts +2 -0
- package/dist/task-board/taskAgentLink.js +35 -0
- package/dist/task-board/taskAgentLink.js.map +1 -0
- package/dist/task-board/taskBoardNavStore.d.ts +35 -0
- package/dist/task-board/taskBoardNavStore.js +42 -0
- package/dist/task-board/taskBoardNavStore.js.map +1 -0
- package/dist/task-board/taskExecutionStatus.d.ts +12 -0
- package/dist/task-board/taskExecutionStatus.js +96 -0
- package/dist/task-board/taskExecutionStatus.js.map +1 -0
- package/dist/task-board/taskStatus.d.ts +2 -0
- package/dist/task-board/taskStatus.js +26 -0
- package/dist/task-board/taskStatus.js.map +1 -0
- package/dist/task-board/types.d.ts +169 -0
- package/dist/task-board/types.js +2 -0
- package/dist/task-board/types.js.map +1 -0
- package/dist/task-board/utils/projectHierarchy.d.ts +13 -0
- package/dist/task-board/utils/projectHierarchy.js +34 -0
- package/dist/task-board/utils/projectHierarchy.js.map +1 -0
- package/dist/task-board/views/KanbanView.d.ts +14 -0
- package/dist/task-board/views/KanbanView.js +136 -0
- package/dist/task-board/views/KanbanView.js.map +1 -0
- package/dist/task-board/views/ListView.d.ts +13 -0
- package/dist/task-board/views/ListView.js +74 -0
- package/dist/task-board/views/ListView.js.map +1 -0
- package/dist/task-board/views/PlanningView.d.ts +7 -0
- package/dist/task-board/views/PlanningView.js +112 -0
- package/dist/task-board/views/PlanningView.js.map +1 -0
- package/package.json +1 -1
|
@@ -21,6 +21,32 @@ import { cn } from "../../lib/utils";
|
|
|
21
21
|
import { Select } from "../../components/ui/select";
|
|
22
22
|
import { AgentTerminalStatusBar } from "./AgentTerminalStatusBar";
|
|
23
23
|
import { useMediaQuery } from "../client/hooks/useMediaQuery";
|
|
24
|
+
import { SimpleTabs } from "../ui/SimpleTabs";
|
|
25
|
+
function buildPlaceholderAgentDetails(agentStub) {
|
|
26
|
+
const now = new Date().toISOString();
|
|
27
|
+
const updated = agentStub.updatedDate || now;
|
|
28
|
+
// AgentDetails has required fields, but some workspaces only pass an Agent stub initially.
|
|
29
|
+
// This placeholder keeps streaming/tool-call UI working until `getAgent()` returns full details.
|
|
30
|
+
return {
|
|
31
|
+
...agentStub,
|
|
32
|
+
name: agentStub.name || "Agent",
|
|
33
|
+
userId: agentStub.userId || "",
|
|
34
|
+
updatedDate: updated,
|
|
35
|
+
profileName: agentStub.profileName || "",
|
|
36
|
+
model: agentStub.model || "",
|
|
37
|
+
createdDate: agentStub.createdDate || updated,
|
|
38
|
+
totalTokensUsed: 0,
|
|
39
|
+
totalInputTokens: 0,
|
|
40
|
+
totalOutputTokens: 0,
|
|
41
|
+
totalCachedInputTokens: 0,
|
|
42
|
+
totalInputTokenCost: 0,
|
|
43
|
+
totalOutputTokenCost: 0,
|
|
44
|
+
totalCachedInputTokenCost: 0,
|
|
45
|
+
totalCost: 0,
|
|
46
|
+
currency: agentStub.currency || "USD",
|
|
47
|
+
messageCount: agentStub.messageCount || 0,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
24
50
|
// Simple user message component
|
|
25
51
|
const UserMessage = ({ message }) => {
|
|
26
52
|
// Parse source agent name from content if it starts with "[From ...]:"
|
|
@@ -50,7 +76,7 @@ const UserMessage = ({ message }) => {
|
|
|
50
76
|
message.sourceAgent?.name;
|
|
51
77
|
}
|
|
52
78
|
const displayName = sourceAgentName ? `[From ${sourceAgentName}]` : "You";
|
|
53
|
-
return (_jsxs("div", { className: "flex gap-3 p-4", children: [_jsx("div", { className: "
|
|
79
|
+
return (_jsxs("div", { className: "flex gap-3 p-4", children: [_jsx("div", { className: "shrink-0", children: _jsx(User, { className: "text-theme-secondary h-5 w-5", strokeWidth: 1 }) }), _jsxs("div", { className: "min-w-0 flex-1 select-text", children: [_jsxs("div", { className: "mb-1 flex items-center gap-2", children: [_jsx("span", { className: "text-[12px] font-medium text-gray-900", children: displayName }), message.createdDate && (_jsx("span", { className: "text-[12px] text-gray-400", "data-testid": "user-message-timestamp", "data-timestamp": message.createdDate, children: formatTime(new Date(message.createdDate)) }))] }), _jsx("div", { className: "prose prose max-w-none text-[12px] text-gray-700 select-text", children: displayContent })] })] }));
|
|
54
80
|
};
|
|
55
81
|
// Helper to extract todos from potentially incomplete JSON during streaming
|
|
56
82
|
const extractPartialTodos = (jsonText) => {
|
|
@@ -408,7 +434,7 @@ const TodoListPanel = ({ messages, agentMetadata, }) => {
|
|
|
408
434
|
return "text-gray-900";
|
|
409
435
|
}
|
|
410
436
|
};
|
|
411
|
-
return (_jsxs("div", { className: "border-t border-gray-200 bg-gray-50", children: [_jsxs("button", { onClick: () => setIsExpanded(!isExpanded), className: "flex w-full cursor-pointer items-center justify-between px-4 py-2 text-left transition-colors hover:bg-gray-100", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ListTodo, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 }), _jsx("span", { className: "text-[11px] font-medium text-gray-700", children: "Todo List" }), isUpdating ? (_jsxs("span", { className: "text-theme-secondary flex items-center gap-1 text-[11px]", children: [_jsx(Loader2, { className: "h-3 w-3 animate-spin", strokeWidth: 1 }), "Updating..."] })) : (_jsxs("span", { className: "text-[11px] text-gray-500", children: [completedCount, "/", totalCount, " completed"] }))] }), isExpanded ? (_jsx(ChevronUp, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 })) : (_jsx(ChevronDown, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 }))] }), isExpanded && (_jsxs("div", { className: "max-h-64 overflow-y-auto px-4 pb-3", children: [todos.length > 0 && (_jsx("div", { className: "space-y-1.5", children: todos.map((todo, idx) => (_jsxs("div", { className: "flex items-start gap-2 rounded bg-white p-2 text-[11px]", children: [_jsx("div", { className: "
|
|
437
|
+
return (_jsxs("div", { className: "border-t border-gray-200 bg-gray-50", children: [_jsxs("button", { onClick: () => setIsExpanded(!isExpanded), className: "flex w-full cursor-pointer items-center justify-between px-4 py-2 text-left transition-colors hover:bg-gray-100", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ListTodo, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 }), _jsx("span", { className: "text-[11px] font-medium text-gray-700", children: "Todo List" }), isUpdating ? (_jsxs("span", { className: "text-theme-secondary flex items-center gap-1 text-[11px]", children: [_jsx(Loader2, { className: "h-3 w-3 animate-spin", strokeWidth: 1 }), "Updating..."] })) : (_jsxs("span", { className: "text-[11px] text-gray-500", children: [completedCount, "/", totalCount, " completed"] }))] }), isExpanded ? (_jsx(ChevronUp, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 })) : (_jsx(ChevronDown, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 }))] }), isExpanded && (_jsxs("div", { className: "max-h-64 overflow-y-auto px-4 pb-3", children: [todos.length > 0 && (_jsx("div", { className: "space-y-1.5", children: todos.map((todo, idx) => (_jsxs("div", { className: "flex items-start gap-2 rounded bg-white p-2 text-[11px]", children: [_jsx("div", { className: "shrink-0 pt-0.5", children: getStatusIcon(todo.status) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: getTextClass(todo.status), children: todo.title }), todo.instructions && (_jsx("div", { className: "mt-0.5 text-[11px] text-gray-500", children: todo.instructions }))] })] }, todo.id || `${todo.messageId}-${idx}`))) })), isUpdating && (_jsxs("div", { className: `flex items-center gap-2 rounded px-3 py-2 text-[11px] ${todos.length > 0
|
|
412
438
|
? "bg-theme-secondary-light text-theme-secondary mt-2"
|
|
413
439
|
: "justify-center bg-white text-gray-500"}`, children: [_jsx(Loader2, { className: "h-3 w-3 animate-spin", strokeWidth: 1 }), _jsx("span", { children: todos.length > 0
|
|
414
440
|
? "Updating todo list..."
|
|
@@ -520,6 +546,59 @@ const getOperationsForMessageGroup = (messages, agentOperations) => {
|
|
|
520
546
|
const matched = agentOperations.filter((op) => op.toolCallId && toolCallIds.has(op.toolCallId));
|
|
521
547
|
return matched;
|
|
522
548
|
};
|
|
549
|
+
const stringifyToolField = (value) => {
|
|
550
|
+
if (value === undefined || value === null)
|
|
551
|
+
return undefined;
|
|
552
|
+
if (typeof value === "string") {
|
|
553
|
+
return value.trim().length > 0 ? value : undefined;
|
|
554
|
+
}
|
|
555
|
+
try {
|
|
556
|
+
return JSON.stringify(value);
|
|
557
|
+
}
|
|
558
|
+
catch {
|
|
559
|
+
return String(value);
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
const getFirstToolCallEnvelope = (data) => {
|
|
563
|
+
if (!data || typeof data !== "object")
|
|
564
|
+
return undefined;
|
|
565
|
+
const direct = data.toolCall || data.tool_call || data.ToolCall;
|
|
566
|
+
if (direct)
|
|
567
|
+
return direct;
|
|
568
|
+
const arrayCandidates = [data.tool_calls, data.toolCalls, data.ToolCalls];
|
|
569
|
+
for (const candidate of arrayCandidates) {
|
|
570
|
+
if (Array.isArray(candidate) && candidate.length > 0) {
|
|
571
|
+
return candidate[0];
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return undefined;
|
|
575
|
+
};
|
|
576
|
+
const extractToolCallFields = (data) => {
|
|
577
|
+
const envelope = getFirstToolCallEnvelope(data);
|
|
578
|
+
const functionPayload = data?.function || data?.Function || envelope?.function || envelope?.Function;
|
|
579
|
+
const functionName = data?.functionName ||
|
|
580
|
+
data?.name ||
|
|
581
|
+
functionPayload?.name ||
|
|
582
|
+
functionPayload?.Name ||
|
|
583
|
+
envelope?.functionName ||
|
|
584
|
+
envelope?.name ||
|
|
585
|
+
envelope?.FunctionName ||
|
|
586
|
+
envelope?.Name ||
|
|
587
|
+
"unknown";
|
|
588
|
+
const toolCallId = data?.toolCallId || data?.id || envelope?.id || envelope?.Id;
|
|
589
|
+
const functionArguments = stringifyToolField(data?.functionArguments) ||
|
|
590
|
+
stringifyToolField(data?.arguments) ||
|
|
591
|
+
stringifyToolField(functionPayload?.arguments) ||
|
|
592
|
+
stringifyToolField(functionPayload?.Arguments) ||
|
|
593
|
+
stringifyToolField(envelope?.functionArguments) ||
|
|
594
|
+
stringifyToolField(envelope?.arguments) ||
|
|
595
|
+
"{}";
|
|
596
|
+
return {
|
|
597
|
+
toolCallId,
|
|
598
|
+
functionName,
|
|
599
|
+
functionArguments,
|
|
600
|
+
};
|
|
601
|
+
};
|
|
523
602
|
// Convert agent messages to AI terminal format for a response group
|
|
524
603
|
const convertAgentMessagesToAiFormat = (agentMessages) => {
|
|
525
604
|
return agentMessages.map((agentMessage) => {
|
|
@@ -576,7 +655,7 @@ const convertAgentMessagesToAiFormat = (agentMessages) => {
|
|
|
576
655
|
export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive = true, compact = false, hideContext = false, hideBottomControls = false, hideGreeting = false, simpleMode = false, className, initialPrompt, onAgentUpdate, }) {
|
|
577
656
|
const editContext = useEditContext();
|
|
578
657
|
const fieldsContext = useFieldsEditContext();
|
|
579
|
-
const [agent, setAgent] = useState(
|
|
658
|
+
const [agent, setAgent] = useState(() => buildPlaceholderAgentDetails(agentStub));
|
|
580
659
|
const [messages, setMessages] = useState([]);
|
|
581
660
|
const [agentOperations, setAgentOperations] = useState([]);
|
|
582
661
|
const [prompt, setPrompt] = useState("");
|
|
@@ -587,6 +666,15 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
587
666
|
const [activePlaceholderInput, setActivePlaceholderInput] = useState(null);
|
|
588
667
|
const [allPlaceholdersFilled, setAllPlaceholdersFilled] = useState(false);
|
|
589
668
|
const [agentMetadata, setAgentMetadata] = useState(null);
|
|
669
|
+
// Ensure we always have an agent object for streaming handlers, even before `getAgent()` resolves.
|
|
670
|
+
// This prevents early tool calls (e.g., ask-questionnaire) from being dropped in compact/workspace UIs.
|
|
671
|
+
useEffect(() => {
|
|
672
|
+
setAgent((prev) => {
|
|
673
|
+
if (prev?.id === agentStub.id)
|
|
674
|
+
return prev;
|
|
675
|
+
return buildPlaceholderAgentDetails(agentStub);
|
|
676
|
+
});
|
|
677
|
+
}, [agentStub.id]);
|
|
590
678
|
// Generate a stable clientSessionId per component instance for stream deduplication
|
|
591
679
|
const clientSessionIdRef = useRef(null);
|
|
592
680
|
if (!clientSessionIdRef.current) {
|
|
@@ -680,7 +768,103 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
680
768
|
const [mode, setMode] = useState("supervised");
|
|
681
769
|
const [queuedPrompts, setQueuedPrompts] = useState([]);
|
|
682
770
|
const isMobile = useMediaQuery("(max-width: 768px)");
|
|
771
|
+
const [contextPanelsActiveTab, setContextPanelsActiveTab] = useState(0);
|
|
772
|
+
const [hiddenContextPanelTabIds, setHiddenContextPanelTabIds] = useState(new Set());
|
|
683
773
|
const [showCostAndAgent, setShowCostAndAgent] = useState(false);
|
|
774
|
+
const hasSpawnedAgents = useMemo(() => {
|
|
775
|
+
if (!agentMetadata)
|
|
776
|
+
return false;
|
|
777
|
+
const childAgents = agentMetadata?.ChildAgents ||
|
|
778
|
+
agentMetadata?.childAgents;
|
|
779
|
+
if (!Array.isArray(childAgents) || childAgents.length === 0)
|
|
780
|
+
return false;
|
|
781
|
+
return childAgents.some((a) => a != null && typeof a === "object" && (a.AgentId || a.agentId));
|
|
782
|
+
}, [agentMetadata]);
|
|
783
|
+
const hasTodoContent = useMemo(() => {
|
|
784
|
+
const metadataTodos = (() => {
|
|
785
|
+
try {
|
|
786
|
+
const todoList = agentMetadata?.additionalData?.todoList ||
|
|
787
|
+
agentMetadata?.todoList;
|
|
788
|
+
if (todoList?.items && Array.isArray(todoList.items)) {
|
|
789
|
+
const raw = todoList.items.filter((item) => item?.title || item?.text || item?.label || item?.task);
|
|
790
|
+
return raw.length > 0;
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
catch {
|
|
794
|
+
// ignore
|
|
795
|
+
}
|
|
796
|
+
return false;
|
|
797
|
+
})();
|
|
798
|
+
if (metadataTodos)
|
|
799
|
+
return true;
|
|
800
|
+
const fromMessages = extractTodosFromMessages(messages);
|
|
801
|
+
if (fromMessages.length > 0)
|
|
802
|
+
return true;
|
|
803
|
+
const isUpdating = messages.some((msg) => msg.role === "assistant" &&
|
|
804
|
+
!msg.isCompleted &&
|
|
805
|
+
(msg.content || "").includes("todo_list"));
|
|
806
|
+
return isUpdating;
|
|
807
|
+
}, [agentMetadata, messages]);
|
|
808
|
+
const prevAgentIdRef = useRef(undefined);
|
|
809
|
+
const [hasHistoryContent, setHasHistoryContent] = useState(false);
|
|
810
|
+
useEffect(() => {
|
|
811
|
+
const currentId = agent?.id;
|
|
812
|
+
if (prevAgentIdRef.current !== currentId) {
|
|
813
|
+
prevAgentIdRef.current = currentId;
|
|
814
|
+
setHiddenContextPanelTabIds((prev) => {
|
|
815
|
+
if (prev.has("history")) {
|
|
816
|
+
const next = new Set(prev);
|
|
817
|
+
next.delete("history");
|
|
818
|
+
return next;
|
|
819
|
+
}
|
|
820
|
+
return prev;
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
}, [agent?.id]);
|
|
824
|
+
useEffect(() => {
|
|
825
|
+
if (!agent?.id) {
|
|
826
|
+
setHasHistoryContent(false);
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
setHasHistoryContent(false);
|
|
830
|
+
let cancelled = false;
|
|
831
|
+
getAgentHistory(agent.id, 10)
|
|
832
|
+
.then((result) => {
|
|
833
|
+
if (cancelled)
|
|
834
|
+
return;
|
|
835
|
+
if (result.type === "success" &&
|
|
836
|
+
result.data &&
|
|
837
|
+
result.data.length > 0) {
|
|
838
|
+
setHasHistoryContent(true);
|
|
839
|
+
}
|
|
840
|
+
else {
|
|
841
|
+
setHasHistoryContent(false);
|
|
842
|
+
}
|
|
843
|
+
})
|
|
844
|
+
.catch(() => {
|
|
845
|
+
if (!cancelled)
|
|
846
|
+
setHasHistoryContent(false);
|
|
847
|
+
});
|
|
848
|
+
return () => {
|
|
849
|
+
cancelled = true;
|
|
850
|
+
};
|
|
851
|
+
}, [agent?.id]);
|
|
852
|
+
const agentIdForHistoryRef = useRef(agent?.id);
|
|
853
|
+
agentIdForHistoryRef.current = agent?.id;
|
|
854
|
+
useEffect(() => {
|
|
855
|
+
if (!agent?.id || !editContext?.addSocketMessageListener)
|
|
856
|
+
return;
|
|
857
|
+
const unsubscribe = editContext.addSocketMessageListener((message) => {
|
|
858
|
+
if (message.type !== "edit-operation")
|
|
859
|
+
return;
|
|
860
|
+
const op = message.payload;
|
|
861
|
+
const operationAgentId = op.agentId || op.user?.agentId;
|
|
862
|
+
if (operationAgentId === agentIdForHistoryRef.current) {
|
|
863
|
+
setHasHistoryContent(true);
|
|
864
|
+
}
|
|
865
|
+
});
|
|
866
|
+
return () => unsubscribe();
|
|
867
|
+
}, [agent?.id, editContext?.addSocketMessageListener]);
|
|
684
868
|
const modeOptions = useMemo(() => [
|
|
685
869
|
{
|
|
686
870
|
value: "supervised",
|
|
@@ -1053,25 +1237,18 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
1053
1237
|
// Shared stream message handlers with messageId support
|
|
1054
1238
|
const createNewStreamMessage = useCallback((messageId, agentData) => {
|
|
1055
1239
|
const currentAgent = agentData || agent;
|
|
1056
|
-
|
|
1057
|
-
console.error("❌ createNewStreamMessage: No agent available", {
|
|
1058
|
-
messageId,
|
|
1059
|
-
agentData: !!agentData,
|
|
1060
|
-
agent: !!agent,
|
|
1061
|
-
});
|
|
1062
|
-
throw new Error("No agent available");
|
|
1063
|
-
}
|
|
1240
|
+
const effectiveAgentId = currentAgent?.id || agentStub.id;
|
|
1064
1241
|
// Reduced: avoid verbose logging during streaming
|
|
1065
1242
|
return {
|
|
1066
1243
|
id: messageId,
|
|
1067
|
-
agentId:
|
|
1244
|
+
agentId: effectiveAgentId,
|
|
1068
1245
|
messageIndex: -1,
|
|
1069
1246
|
role: "assistant",
|
|
1070
1247
|
content: "",
|
|
1071
1248
|
name: "agent",
|
|
1072
1249
|
messageType: "streaming",
|
|
1073
1250
|
isCompleted: false,
|
|
1074
|
-
model: currentAgent
|
|
1251
|
+
model: currentAgent?.model || "",
|
|
1075
1252
|
tokensUsed: 0,
|
|
1076
1253
|
inputTokens: 0,
|
|
1077
1254
|
outputTokens: 0,
|
|
@@ -1080,11 +1257,11 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
1080
1257
|
outputTokenCost: 0,
|
|
1081
1258
|
cachedInputTokenCost: 0,
|
|
1082
1259
|
totalCost: 0,
|
|
1083
|
-
currency: currentAgent
|
|
1260
|
+
currency: currentAgent?.currency || "USD",
|
|
1084
1261
|
createdDate: new Date().toISOString(),
|
|
1085
1262
|
toolCalls: [],
|
|
1086
1263
|
};
|
|
1087
|
-
}, [agent]);
|
|
1264
|
+
}, [agent, agentStub.id]);
|
|
1088
1265
|
const handleContentChunk = useCallback((message, agentData) => {
|
|
1089
1266
|
// Get messageId from data, or generate one from agent ID (for backward compatibility)
|
|
1090
1267
|
// If no messageId is provided, we'll use the last assistant message or create a new one
|
|
@@ -1226,7 +1403,8 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
1226
1403
|
});
|
|
1227
1404
|
}, [createNewStreamMessage, agent]);
|
|
1228
1405
|
const handleToolCall = useCallback((message, agentData) => {
|
|
1229
|
-
const
|
|
1406
|
+
const extractedToolCall = extractToolCallFields(message.data);
|
|
1407
|
+
const toolCallId = extractedToolCall.toolCallId || crypto.randomUUID();
|
|
1230
1408
|
// Prefer provided messageId, otherwise fall back to the last streaming assistant message
|
|
1231
1409
|
let toolCallMessageId = message.data?.messageId;
|
|
1232
1410
|
if (!toolCallMessageId) {
|
|
@@ -1237,6 +1415,11 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
1237
1415
|
if (lastStreaming?.id) {
|
|
1238
1416
|
toolCallMessageId = lastStreaming.id;
|
|
1239
1417
|
}
|
|
1418
|
+
else {
|
|
1419
|
+
// Tool calls can arrive before any assistant content chunk (common for dialog tools like ask-questionnaire).
|
|
1420
|
+
// Create a synthetic streaming message so the UI can render the tool call immediately.
|
|
1421
|
+
toolCallMessageId = crypto.randomUUID();
|
|
1422
|
+
}
|
|
1240
1423
|
}
|
|
1241
1424
|
// Find or create the target message for this tool call
|
|
1242
1425
|
if (toolCallMessageId) {
|
|
@@ -1264,19 +1447,13 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
1264
1447
|
}
|
|
1265
1448
|
// Add tool call to the message in the array
|
|
1266
1449
|
if (toolCallMessageId && message.data && toolCallId) {
|
|
1267
|
-
const functionName = message.data.functionName ||
|
|
1268
|
-
message.data.name ||
|
|
1269
|
-
message.data.function?.name ||
|
|
1270
|
-
"unknown";
|
|
1271
1450
|
const toolCall = {
|
|
1272
1451
|
id: toolCallId,
|
|
1273
1452
|
messageId: toolCallMessageId,
|
|
1274
1453
|
dbMessageId: message.data.messageId, // Database message ID for approval/rejection
|
|
1275
1454
|
toolCallId: toolCallId,
|
|
1276
|
-
functionName: functionName,
|
|
1277
|
-
functionArguments:
|
|
1278
|
-
message.data.arguments ||
|
|
1279
|
-
JSON.stringify(message.data.function?.arguments || {}),
|
|
1455
|
+
functionName: extractedToolCall.functionName,
|
|
1456
|
+
functionArguments: extractedToolCall.functionArguments,
|
|
1280
1457
|
functionResult: message.data.functionResult || message.data.result || "",
|
|
1281
1458
|
functionError: message.data.functionError || message.data.error || "",
|
|
1282
1459
|
isCompleted: false,
|
|
@@ -1320,7 +1497,11 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
1320
1497
|
// Check if the new data has more information than what we have
|
|
1321
1498
|
const newArgs = toolCall.functionArguments;
|
|
1322
1499
|
const existingArgs = existingToolCall.functionArguments;
|
|
1323
|
-
const
|
|
1500
|
+
const newArgsText = stringifyToolField(newArgs) || "";
|
|
1501
|
+
const existingArgsText = stringifyToolField(existingArgs) || "";
|
|
1502
|
+
const hasMoreCompleteArgs = (newArgsText.length > existingArgsText.length &&
|
|
1503
|
+
newArgsText !== existingArgsText) ||
|
|
1504
|
+
(existingArgsText === "{}" && newArgsText !== "{}");
|
|
1324
1505
|
const hasNewResult = toolCall.functionResult && !existingToolCall.functionResult;
|
|
1325
1506
|
const hasNewError = toolCall.functionError && !existingToolCall.functionError;
|
|
1326
1507
|
const hasNewApprovalInfo = toolCall.requiresApproval && !existingToolCall.requiresApproval;
|
|
@@ -1344,8 +1525,8 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
1344
1525
|
updatedToolCalls[idx] = {
|
|
1345
1526
|
...existing,
|
|
1346
1527
|
functionArguments: hasMoreCompleteArgs
|
|
1347
|
-
?
|
|
1348
|
-
: existing.functionArguments,
|
|
1528
|
+
? newArgsText
|
|
1529
|
+
: existingArgsText || existing.functionArguments,
|
|
1349
1530
|
functionResult: toolCall.functionResult || existing.functionResult,
|
|
1350
1531
|
functionError: toolCall.functionError || existing.functionError,
|
|
1351
1532
|
requiresApproval: toolCall.requiresApproval || existing.requiresApproval,
|
|
@@ -1381,7 +1562,8 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
1381
1562
|
}
|
|
1382
1563
|
}, [createNewStreamMessage]);
|
|
1383
1564
|
const handleToolResult = useCallback((message, agentData) => {
|
|
1384
|
-
const
|
|
1565
|
+
const extractedToolCall = extractToolCallFields(message.data);
|
|
1566
|
+
const resultToolCallId = extractedToolCall.toolCallId || crypto.randomUUID();
|
|
1385
1567
|
// Prefer provided messageId, otherwise fall back to the last streaming assistant message
|
|
1386
1568
|
let resultMessageId = message.data?.messageId;
|
|
1387
1569
|
if (!resultMessageId) {
|
|
@@ -1500,18 +1682,12 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
1500
1682
|
}
|
|
1501
1683
|
else if (message.data && resultToolCallId && resultMessageId) {
|
|
1502
1684
|
// Create new tool call if it doesn't exist
|
|
1503
|
-
const functionName = message.data.functionName ||
|
|
1504
|
-
message.data.name ||
|
|
1505
|
-
message.data.function?.name ||
|
|
1506
|
-
"unknown";
|
|
1507
1685
|
const toolCall = {
|
|
1508
1686
|
id: resultToolCallId,
|
|
1509
1687
|
messageId: resultMessageId,
|
|
1510
1688
|
toolCallId: resultToolCallId,
|
|
1511
|
-
functionName: functionName,
|
|
1512
|
-
functionArguments:
|
|
1513
|
-
message.data.arguments ||
|
|
1514
|
-
JSON.stringify(message.data.function?.arguments || {}),
|
|
1689
|
+
functionName: extractedToolCall.functionName,
|
|
1690
|
+
functionArguments: extractedToolCall.functionArguments,
|
|
1515
1691
|
functionResult: message.data.functionResult || message.data.result || "",
|
|
1516
1692
|
functionError: message.data.functionError || message.data.error || "",
|
|
1517
1693
|
isCompleted: true,
|
|
@@ -1806,8 +1982,15 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
1806
1982
|
seenMessageIdsRef.current.add(msg.id.toLowerCase());
|
|
1807
1983
|
}
|
|
1808
1984
|
});
|
|
1809
|
-
// Keep local streaming
|
|
1985
|
+
// Keep local streaming if the agent is still active (running/waiting); otherwise discard locals.
|
|
1986
|
+
// This is important for dialog-style tools (e.g., ask-questionnaire) where the agent may be
|
|
1987
|
+
// "waiting" but we still want to keep the in-flight tool call UI visible.
|
|
1810
1988
|
const isRunning = agentData.status === "running" || agentData.status === 1;
|
|
1989
|
+
const isWaiting = agentData.status === "waitingForApproval" ||
|
|
1990
|
+
agentData.status === 2 ||
|
|
1991
|
+
agentData.status === "costLimitReached" ||
|
|
1992
|
+
agentData.status === 7;
|
|
1993
|
+
const keepLocalStreaming = isRunning || isWaiting;
|
|
1811
1994
|
// Filter local messages to only include streaming/incomplete messages that aren't in DB
|
|
1812
1995
|
// This prevents duplicates when reloading - DB messages are source of truth for completed messages
|
|
1813
1996
|
const localStreaming = isRunning
|
|
@@ -1825,7 +2008,19 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
1825
2008
|
// Don't keep completed messages from local state - DB is source of truth
|
|
1826
2009
|
return false;
|
|
1827
2010
|
})
|
|
1828
|
-
:
|
|
2011
|
+
: keepLocalStreaming
|
|
2012
|
+
? messagesRef.current.filter((localMsg) => {
|
|
2013
|
+
if (!localMsg.id)
|
|
2014
|
+
return false;
|
|
2015
|
+
if (!localMsg.isCompleted &&
|
|
2016
|
+
localMsg.messageType === "streaming") {
|
|
2017
|
+
const existsInDb = dbMessages.some((dbMsg) => dbMsg.id &&
|
|
2018
|
+
dbMsg.id.toLowerCase() === localMsg.id.toLowerCase());
|
|
2019
|
+
return !existsInDb;
|
|
2020
|
+
}
|
|
2021
|
+
return false;
|
|
2022
|
+
})
|
|
2023
|
+
: [];
|
|
1829
2024
|
const merged = mergeMessagesById(dbMessages, localStreaming);
|
|
1830
2025
|
messagesRef.current = merged;
|
|
1831
2026
|
setMessages(merged);
|
|
@@ -2731,26 +2926,57 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
2731
2926
|
window.addEventListener("editor:focusAgentPrompt", focusHandler);
|
|
2732
2927
|
return () => window.removeEventListener("editor:focusAgentPrompt", focusHandler);
|
|
2733
2928
|
}, []);
|
|
2929
|
+
// Keep stable refs so we don't miss window events during effect re-runs.
|
|
2930
|
+
const agentIdRefForDialogs = useRef(null);
|
|
2931
|
+
const agentStubIdRefForDialogs = useRef(agentStub.id);
|
|
2932
|
+
const isActiveRefForDialogs = useRef(isActive);
|
|
2933
|
+
const scrollToBottomRefForDialogs = useRef(scrollToBottom);
|
|
2934
|
+
useEffect(() => {
|
|
2935
|
+
agentIdRefForDialogs.current = agent?.id ?? null;
|
|
2936
|
+
}, [agent?.id]);
|
|
2937
|
+
useEffect(() => {
|
|
2938
|
+
agentStubIdRefForDialogs.current = agentStub.id;
|
|
2939
|
+
}, [agentStub.id]);
|
|
2940
|
+
useEffect(() => {
|
|
2941
|
+
isActiveRefForDialogs.current = isActive;
|
|
2942
|
+
}, [isActive]);
|
|
2943
|
+
useEffect(() => {
|
|
2944
|
+
scrollToBottomRefForDialogs.current = scrollToBottom;
|
|
2945
|
+
}, [scrollToBottom]);
|
|
2734
2946
|
// Listen for agent inline dialog requests from AgentDialogHandler
|
|
2735
2947
|
useEffect(() => {
|
|
2736
2948
|
const handleDialogShow = (event) => {
|
|
2737
|
-
const
|
|
2738
|
-
|
|
2739
|
-
|
|
2949
|
+
const detail = event?.detail;
|
|
2950
|
+
const request = detail?.request;
|
|
2951
|
+
const onComplete = detail?.onComplete;
|
|
2952
|
+
const onCancel = detail?.onCancel;
|
|
2953
|
+
const terminalAgentId = agentIdRefForDialogs.current;
|
|
2954
|
+
const terminalAgentStubId = agentStubIdRefForDialogs.current;
|
|
2955
|
+
const isActiveNow = isActiveRefForDialogs.current;
|
|
2956
|
+
if (!isActiveNow)
|
|
2957
|
+
return;
|
|
2958
|
+
if (!request)
|
|
2959
|
+
return;
|
|
2960
|
+
// Only handle dialog requests for this terminal's agent stub
|
|
2961
|
+
if (request.agentId && terminalAgentStubId && request.agentId !== terminalAgentStubId) {
|
|
2740
2962
|
return;
|
|
2741
2963
|
}
|
|
2742
2964
|
console.log("[AgentTerminal] Received inline dialog request:", request);
|
|
2743
2965
|
setActiveInlineDialog({ request, onComplete, onCancel });
|
|
2744
2966
|
// Notify AgentDialogHandler that we accepted the dialog (stops retry mechanism)
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2967
|
+
if (request.callbackId) {
|
|
2968
|
+
window.dispatchEvent(new CustomEvent("agent:dialog:accepted", {
|
|
2969
|
+
detail: { callbackId: request.callbackId },
|
|
2970
|
+
}));
|
|
2971
|
+
}
|
|
2748
2972
|
// Scroll to bottom to show the dialog
|
|
2749
|
-
setTimeout(
|
|
2973
|
+
setTimeout(() => scrollToBottomRefForDialogs.current?.(), 100);
|
|
2750
2974
|
};
|
|
2751
2975
|
window.addEventListener("agent:dialog:show", handleDialogShow);
|
|
2752
|
-
return () =>
|
|
2753
|
-
|
|
2976
|
+
return () => {
|
|
2977
|
+
window.removeEventListener("agent:dialog:show", handleDialogShow);
|
|
2978
|
+
};
|
|
2979
|
+
}, []);
|
|
2754
2980
|
// Announce when this terminal is ready to accept dialogs
|
|
2755
2981
|
// This allows AgentDialogHandler to re-dispatch pending dialogs when switching to an agent
|
|
2756
2982
|
useEffect(() => {
|
|
@@ -2868,6 +3094,17 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
2868
3094
|
console.error("Failed to persist pending settings", e);
|
|
2869
3095
|
}
|
|
2870
3096
|
}, [agent?.id]);
|
|
3097
|
+
const getSubmitErrorMessage = (error) => {
|
|
3098
|
+
const fallback = "Failed to submit prompt. Please try again.";
|
|
3099
|
+
if (!(error instanceof Error))
|
|
3100
|
+
return fallback;
|
|
3101
|
+
const cleaned = error.message
|
|
3102
|
+
.replace(/^Failed to start agent:\s*/i, "")
|
|
3103
|
+
.replace(/^Unknown error\s*/i, "")
|
|
3104
|
+
.replace(/^Error:\s*/i, "")
|
|
3105
|
+
.trim();
|
|
3106
|
+
return cleaned || fallback;
|
|
3107
|
+
};
|
|
2871
3108
|
const handleSubmit = async () => {
|
|
2872
3109
|
// Guard against double-submit and missing context
|
|
2873
3110
|
if (isSubmitting) {
|
|
@@ -3044,7 +3281,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3044
3281
|
}
|
|
3045
3282
|
catch (err) {
|
|
3046
3283
|
console.error("[AgentTerminal] Failed to submit prompt:", err);
|
|
3047
|
-
setError(
|
|
3284
|
+
setError(getSubmitErrorMessage(err));
|
|
3048
3285
|
setIsWaitingForResponse(false);
|
|
3049
3286
|
isWaitingRef.current = false;
|
|
3050
3287
|
// Remove the optimistic user message on API error
|
|
@@ -3276,7 +3513,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3276
3513
|
}
|
|
3277
3514
|
catch (err) {
|
|
3278
3515
|
console.error("[AgentTerminal] Failed to submit quick message:", err);
|
|
3279
|
-
setError(
|
|
3516
|
+
setError(getSubmitErrorMessage(err));
|
|
3280
3517
|
setIsWaitingForResponse(false);
|
|
3281
3518
|
isWaitingRef.current = false;
|
|
3282
3519
|
// Remove the optimistic user message on API error
|
|
@@ -3827,7 +4064,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3827
4064
|
const errorMessage = currentAgent?.statusMessage;
|
|
3828
4065
|
if (!isErrorStatus || !errorMessage)
|
|
3829
4066
|
return null;
|
|
3830
|
-
return (_jsx("div", { className: "m-3 rounded border border-red-300 bg-red-50 p-3 text-[11px] text-red-900", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(AlertCircle, { className: "mt-0.5 h-4 w-4
|
|
4067
|
+
return (_jsx("div", { className: "m-3 rounded border border-red-300 bg-red-50 p-3 text-[11px] text-red-900", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(AlertCircle, { className: "mt-0.5 h-4 w-4 shrink-0 text-red-500", strokeWidth: 1 }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "mb-1 font-semibold", children: "Agent Error" }), _jsx("div", { className: "text-red-800", children: errorMessage })] })] }) }));
|
|
3831
4068
|
};
|
|
3832
4069
|
return (_jsxs("div", { className: `flex h-full flex-col ${className || ""}`, children: [parentAgentId && !simpleMode && (_jsx("div", { className: "border-b border-gray-200 bg-gray-50 px-4 py-2", children: _jsxs("button", { onClick: handleBackToParent, className: "flex items-center gap-2 text-[11px] text-gray-600 transition-colors hover:text-gray-900", title: "Back to parent agent", children: [_jsx(ArrowLeft, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }), _jsx("span", { children: "Back to parent agent" })] }) })), _jsxs("div", { ref: messagesContainerRef, className: "flex-1 overflow-y-auto", onScroll: handleScroll, children: [error && (_jsx("div", { className: "m-4 rounded-lg border-l-4 border-red-500 bg-red-50 p-3 select-text", children: _jsxs("div", { className: "flex items-start", children: [_jsx(AlertCircle, { className: "mt-0.5 h-5 w-5 text-red-400", strokeWidth: 1 }), _jsxs("div", { className: "ml-3", children: [_jsx("p", { className: "text-[11px] font-medium text-red-800", children: "Error" }), _jsx("p", { className: "mt-1 text-[11px] text-red-700", children: error })] })] }) })), messages.length === 0 && !error && !hideGreeting && (_jsx("div", { className: "flex h-full items-center justify-center", children: !activeProfile ? (_jsx(Loader2, { className: "mx-auto h-8 w-8 animate-spin text-gray-400" })) : (_jsx(AgentGreeting, { profile: activeProfile, onPromptClick: (p) => {
|
|
3833
4070
|
setPrompt(p);
|
|
@@ -3916,12 +4153,62 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
3916
4153
|
} }, groupIndex));
|
|
3917
4154
|
}
|
|
3918
4155
|
});
|
|
3919
|
-
})(), shouldShowThinkingDots && (_jsxs("div", { className: "flex gap-3 px-4 py-3", "data-testid": "agent-thinking-dots", children: [_jsx("div", { className: "
|
|
4156
|
+
})(), shouldShowThinkingDots && (_jsxs("div", { className: "flex gap-3 px-4 py-3", "data-testid": "agent-thinking-dots", children: [_jsx("div", { className: "shrink-0", children: activeProfile?.svgIcon ? (_jsx("div", { className: "text-gray-2 flex h-6 w-6 items-center justify-center [&>svg]:h-full [&>svg]:w-full", dangerouslySetInnerHTML: {
|
|
3920
4157
|
__html: activeProfile.svgIcon,
|
|
3921
4158
|
} })) : (_jsx(SecretAgentIcon, { size: 20, strokeWidth: 1, className: "text-gray-2" })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "mb-1 flex items-center gap-2", children: [_jsx("span", { className: "text-dark text-xs font-medium", children: activeProfile?.agentName ||
|
|
3922
4159
|
activeProfile?.displayTitle ||
|
|
3923
4160
|
activeProfile?.name ||
|
|
3924
|
-
"Agent" }), _jsx("span", { className: "text-xs text-gray-400", children: formatTime(new Date()) })] }), _jsxs("div", { className: "flex items-center gap-1 pt-2", children: [_jsx("div", { className: "h-1 w-1 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.3s]" }), _jsx("div", { className: "h-1 w-1 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.15s]" }), _jsx("div", { className: "h-1 w-1 animate-bounce rounded-full bg-gray-400" })] })] })] }))] }), !simpleMode && renderCostLimitBanner(), _jsx("div", { ref: messagesEndRef })] }), !hideContext &&
|
|
4161
|
+
"Agent" }), _jsx("span", { className: "text-xs text-gray-400", children: formatTime(new Date()) })] }), _jsxs("div", { className: "flex items-center gap-1 pt-2", children: [_jsx("div", { className: "h-1 w-1 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.3s]" }), _jsx("div", { className: "h-1 w-1 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.15s]" }), _jsx("div", { className: "h-1 w-1 animate-bounce rounded-full bg-gray-400" })] })] })] }))] }), !simpleMode && renderCostLimitBanner(), _jsx("div", { ref: messagesEndRef })] }), !hideContext &&
|
|
4162
|
+
!simpleMode &&
|
|
4163
|
+
(isMobile ? (_jsx("div", { className: "border-t border-gray-200 bg-gray-50", "data-testid": "agent-context-panel-tabs", children: _jsx(SimpleTabs, { tabs: [
|
|
4164
|
+
{
|
|
4165
|
+
id: "context",
|
|
4166
|
+
label: "Context",
|
|
4167
|
+
content: renderContextInfoBar(),
|
|
4168
|
+
},
|
|
4169
|
+
...(agent?.id && activeProfile
|
|
4170
|
+
? [
|
|
4171
|
+
{
|
|
4172
|
+
id: "documents",
|
|
4173
|
+
label: "Documents",
|
|
4174
|
+
content: (_jsx(AgentDocumentList, { ref: documentListRef, agentId: agent.id, maxFileSizeMB: activeProfile.maxDocumentSizeMB ?? 10, enabled: activeProfile.enableDocumentUpload ?? false, profileId: activeProfile.id }, `${agent.id}-${agent.updatedDate || ""}-${activeProfile.id}`)),
|
|
4175
|
+
},
|
|
4176
|
+
]
|
|
4177
|
+
: []),
|
|
4178
|
+
...(hasTodoContent
|
|
4179
|
+
? [
|
|
4180
|
+
{
|
|
4181
|
+
id: "todos",
|
|
4182
|
+
label: "Todos",
|
|
4183
|
+
content: (_jsx(TodoListPanel, { messages: messages, agentMetadata: agentMetadata })),
|
|
4184
|
+
},
|
|
4185
|
+
]
|
|
4186
|
+
: []),
|
|
4187
|
+
...(hasSpawnedAgents
|
|
4188
|
+
? [
|
|
4189
|
+
{
|
|
4190
|
+
id: "agents",
|
|
4191
|
+
label: "Spawned",
|
|
4192
|
+
content: (_jsx(SpawnedAgentsPanel, { agentMetadata: agentMetadata })),
|
|
4193
|
+
},
|
|
4194
|
+
]
|
|
4195
|
+
: []),
|
|
4196
|
+
...(agent?.id && hasHistoryContent
|
|
4197
|
+
? [
|
|
4198
|
+
{
|
|
4199
|
+
id: "history",
|
|
4200
|
+
label: "History",
|
|
4201
|
+
content: (_jsx(AgentEditOperationsPanel, { agentId: agent.id })),
|
|
4202
|
+
},
|
|
4203
|
+
]
|
|
4204
|
+
: []),
|
|
4205
|
+
], activeTab: Math.max(0, Math.min(contextPanelsActiveTab, [
|
|
4206
|
+
true,
|
|
4207
|
+
agent?.id && activeProfile,
|
|
4208
|
+
hasTodoContent,
|
|
4209
|
+
hasSpawnedAgents,
|
|
4210
|
+
agent?.id && hasHistoryContent,
|
|
4211
|
+
].filter(Boolean).length - 1)), setActiveTab: setContextPanelsActiveTab, className: "justify-start px-4" }) })) : (_jsxs(_Fragment, { children: [renderContextInfoBar(), agent?.id && activeProfile && (_jsx(AgentDocumentList, { ref: documentListRef, agentId: agent.id, maxFileSizeMB: activeProfile.maxDocumentSizeMB ?? 10, enabled: activeProfile.enableDocumentUpload ?? false, profileId: activeProfile.id }, `${agent.id}-${agent.updatedDate || ""}-${activeProfile.id}`)), _jsx(TodoListPanel, { messages: messages, agentMetadata: agentMetadata }), _jsx(SpawnedAgentsPanel, { agentMetadata: agentMetadata }), agent?.id && _jsx(AgentEditOperationsPanel, { agentId: agent.id })] }))), queuedPrompts.length > 0 && !simpleMode && (_jsx("div", { className: "border-t border-gray-200 bg-amber-50/50", "data-testid": "queued-prompts-section", children: _jsxs("div", { className: "px-4 pt-3 pb-2", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx("div", { className: "h-2 w-2 animate-pulse rounded-full bg-amber-500" }), _jsxs("span", { className: "text-[11px] font-semibold text-amber-900", "data-testid": "queued-prompts-count", children: ["Queued Messages (", queuedPrompts.length, ")"] })] }), _jsx("div", { className: "max-h-64 space-y-2 overflow-y-auto", children: queuedPrompts.map((qp) => (_jsx("div", { className: "rounded-md border border-amber-200 bg-white p-2.5 text-[11px]", "data-testid": "queued-prompt-item", children: _jsx("div", { className: "flex items-start justify-between gap-2", children: _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "mb-1 flex items-center gap-1.5", children: qp.sourceAgentName ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "font-medium text-gray-700", children: ["From ", qp.sourceAgentName] }), qp.priority > 5 && (_jsx("span", { className: "rounded bg-red-100 px-1.5 py-0.5 text-[11px] font-medium text-red-700", children: "High Priority" }))] })) : (_jsx("span", { className: "font-medium text-gray-700", children: "From User" })) }), _jsx("div", { className: "wrap-break-word whitespace-pre-wrap text-gray-600", "data-testid": "queued-prompt-text", children: qp.prompt }), _jsxs("div", { className: "mt-1.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[11px] text-gray-400", children: [qp.createdDate && (_jsxs("span", { children: ["Queued ", formatTime(new Date(qp.createdDate))] })), qp.scheduledFor &&
|
|
3925
4212
|
new Date(qp.scheduledFor).getTime() >
|
|
3926
4213
|
new Date(qp.createdDate || 0).getTime() + 1000 && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-gray-300", children: "\u2022" }), _jsxs("span", { className: "font-medium text-amber-600", children: ["Scheduled for", " ", new Date(qp.scheduledFor).toDateString() ===
|
|
3927
4214
|
new Date().toDateString()
|
|
@@ -4020,10 +4307,10 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
|
|
|
4020
4307
|
return (_jsxs("div", { className: cn("mt-2 flex items-stretch gap-2", hideBottomControls || simpleMode || isInPlaceholderMode
|
|
4021
4308
|
? "justify-end"
|
|
4022
4309
|
: "justify-between"), children: [!hideBottomControls && !simpleMode && !isInPlaceholderMode && (_jsxs("div", { className: "flex flex-wrap items-center justify-start gap-2", children: [_jsx(Select, { size: "xs", maxWidth: 240, className: cn("h-5 w-auto min-w-[95px] rounded border px-1.5 text-[11px] font-normal", mode === "read-only"
|
|
4023
|
-
? "border-green-300
|
|
4310
|
+
? "border-green-300 bg-green-50! text-green-700 hover:bg-green-100!"
|
|
4024
4311
|
: mode === "supervised"
|
|
4025
|
-
? "border-amber-300
|
|
4026
|
-
: "border-red-300
|
|
4312
|
+
? "border-amber-300 bg-amber-50! text-amber-700 hover:bg-amber-100!"
|
|
4313
|
+
: "border-red-300 bg-red-50! text-red-700 hover:bg-red-100!"), value: mode, options: modeOptions, onValueChange: async (val) => {
|
|
4027
4314
|
const nextMode = val || "supervised";
|
|
4028
4315
|
// Optimistic UI update
|
|
4029
4316
|
setMode(nextMode);
|