@parhelia/core 0.1.12844 → 0.1.12868
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/AgentCard.d.ts +1 -2
- package/dist/agents-view/AgentCard.js +10 -15
- package/dist/agents-view/AgentCard.js.map +1 -1
- package/dist/agents-view/AgentsSidebar.d.ts +1 -3
- package/dist/agents-view/AgentsSidebar.js +2 -3
- package/dist/agents-view/AgentsSidebar.js.map +1 -1
- package/dist/agents-view/AgentsView.js +19 -39
- package/dist/agents-view/AgentsView.js.map +1 -1
- package/dist/agents-view/AgentsWorkspaceView.js +6 -16
- package/dist/agents-view/AgentsWorkspaceView.js.map +1 -1
- package/dist/agents-view/DateAgentsGroup.d.ts +1 -2
- package/dist/agents-view/DateAgentsGroup.js +2 -2
- package/dist/agents-view/DateAgentsGroup.js.map +1 -1
- package/dist/agents-view/ProfileAgentsGroup.d.ts +1 -2
- package/dist/agents-view/ProfileAgentsGroup.js +4 -4
- package/dist/agents-view/ProfileAgentsGroup.js.map +1 -1
- package/dist/components/MarkdownDisplay.js +6 -6
- package/dist/components/MarkdownDisplay.js.map +1 -1
- package/dist/components/ui/LanguageSelectionGrid.d.ts +3 -1
- package/dist/components/ui/LanguageSelectionGrid.js +2 -2
- package/dist/components/ui/LanguageSelectionGrid.js.map +1 -1
- package/dist/components/ui/avatar.d.ts +1 -1
- package/dist/components/ui/avatar.js +1 -1
- package/dist/components/ui/avatar.js.map +1 -1
- package/dist/components/ui/sonner.js +27 -1
- package/dist/components/ui/sonner.js.map +1 -1
- package/dist/config/config.js +8 -4
- package/dist/config/config.js.map +1 -1
- package/dist/config/types/sidebar.d.ts +2 -0
- package/dist/config/types.d.ts +2 -0
- package/dist/config/types.js.map +1 -1
- package/dist/editor/ConfirmationDialog.js +2 -2
- package/dist/editor/ConfirmationDialog.js.map +1 -1
- package/dist/editor/Editor.js +19 -3
- package/dist/editor/Editor.js.map +1 -1
- package/dist/editor/ai/AgentProfileSelector.d.ts +1 -0
- package/dist/editor/ai/AgentProfileSelector.js +4 -4
- package/dist/editor/ai/AgentProfileSelector.js.map +1 -1
- package/dist/editor/ai/Agents.js +103 -390
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentGreeting.js +2 -5
- package/dist/editor/ai/terminal/components/AgentGreeting.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentSummaryAssistantResponse.d.ts +1 -1
- package/dist/editor/ai/terminal/components/AgentSummaryAssistantResponse.js +1 -1
- package/dist/editor/ai/terminal/components/AgentSummaryAssistantResponse.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalFullUpperContent.js +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalFullUpperContent.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalMessageGroups.d.ts +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalMessageGroups.js +4 -2
- package/dist/editor/ai/terminal/components/AgentTerminalMessageGroups.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalSummaryLayout.js +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalSummaryLayout.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentThinkingDots.d.ts +1 -1
- package/dist/editor/ai/terminal/components/AgentThinkingDots.js +4 -8
- package/dist/editor/ai/terminal/components/AgentThinkingDots.js.map +1 -1
- package/dist/editor/ai/terminal/components/AiResponseMessage.d.ts +2 -2
- package/dist/editor/ai/terminal/components/AiResponseMessage.js +366 -196
- package/dist/editor/ai/terminal/components/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/terminal/components/InitialThinkingSplash.d.ts +1 -3
- package/dist/editor/ai/terminal/components/InitialThinkingSplash.js +2 -6
- package/dist/editor/ai/terminal/components/InitialThinkingSplash.js.map +1 -1
- package/dist/editor/ai/terminal/components/ToolCallDisplay.js +26 -52
- package/dist/editor/ai/terminal/components/ToolCallDisplay.js.map +1 -1
- package/dist/editor/ai/terminal/components/UserMessage.d.ts +2 -1
- package/dist/editor/ai/terminal/components/UserMessage.js +25 -6
- package/dist/editor/ai/terminal/components/UserMessage.js.map +1 -1
- package/dist/editor/client/AboutDialog.js +3 -3
- package/dist/editor/client/AboutDialog.js.map +1 -1
- package/dist/editor/client/EditorShell.d.ts +2 -1
- package/dist/editor/client/EditorShell.js +7 -5
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/hooks/useEditorWebSocket.d.ts +1 -0
- package/dist/editor/client/hooks/useEditorWebSocket.js +5 -2
- package/dist/editor/client/hooks/useEditorWebSocket.js.map +1 -1
- package/dist/editor/client/pageModelBuilder.d.ts +1 -0
- package/dist/editor/client/pageModelBuilder.js +54 -11
- package/dist/editor/client/pageModelBuilder.js.map +1 -1
- package/dist/editor/client/ui/EditorChrome.js +1 -1
- package/dist/editor/client/ui/EditorChrome.js.map +1 -1
- package/dist/editor/context-menu/InsertMenu.js +2 -2
- package/dist/editor/context-menu/InsertMenu.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.d.ts +7 -0
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.js +160 -15
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/UtilityControls.js +2 -2
- package/dist/editor/menubar/toolbar-sections/UtilityControls.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/ViewportControls.js +2 -1
- package/dist/editor/menubar/toolbar-sections/ViewportControls.js.map +1 -1
- package/dist/editor/page-editor-chrome/CommentHighlightings.js +108 -94
- package/dist/editor/page-editor-chrome/CommentHighlightings.js.map +1 -1
- package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.d.ts +17 -0
- package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.js +33 -0
- package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.js.map +1 -0
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +5 -12
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
- package/dist/editor/page-editor-chrome/SuggestionHighlightings.js +50 -17
- package/dist/editor/page-editor-chrome/SuggestionHighlightings.js.map +1 -1
- package/dist/editor/page-viewer/PageViewer.js +43 -4
- package/dist/editor/page-viewer/PageViewer.js.map +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.js +84 -13
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.js +377 -21
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.js.map +1 -1
- package/dist/editor/pageModel.d.ts +3 -0
- package/dist/editor/pageModel.js +12 -1
- package/dist/editor/pageModel.js.map +1 -1
- package/dist/editor/reviews/CommentDisplayPopover.js +3 -2
- package/dist/editor/reviews/CommentDisplayPopover.js.map +1 -1
- package/dist/editor/reviews/CommentEditor.d.ts +3 -1
- package/dist/editor/reviews/CommentEditor.js +36 -8
- package/dist/editor/reviews/CommentEditor.js.map +1 -1
- package/dist/editor/reviews/CommentPopover.js +3 -2
- package/dist/editor/reviews/CommentPopover.js.map +1 -1
- package/dist/editor/reviews/CommentView.js +7 -9
- package/dist/editor/reviews/CommentView.js.map +1 -1
- package/dist/editor/reviews/Comments.js +6 -5
- package/dist/editor/reviews/Comments.js.map +1 -1
- package/dist/editor/reviews/FeedbackCard.d.ts +2 -1
- package/dist/editor/reviews/FeedbackCard.js +8 -4
- package/dist/editor/reviews/FeedbackCard.js.map +1 -1
- package/dist/editor/reviews/LatestFeedback.js +2 -3
- package/dist/editor/reviews/LatestFeedback.js.map +1 -1
- package/dist/editor/reviews/MentionText.js +2 -1
- package/dist/editor/reviews/MentionText.js.map +1 -1
- package/dist/editor/reviews/SuggestedEdit.js +47 -27
- package/dist/editor/reviews/SuggestedEdit.js.map +1 -1
- package/dist/editor/reviews/SuggestionCommentThread.js +3 -3
- package/dist/editor/reviews/SuggestionCommentThread.js.map +1 -1
- package/dist/editor/reviews/SuggestionDisplayPopover.js +7 -16
- package/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -1
- package/dist/editor/reviews/feedbackAvatar.d.ts +7 -0
- package/dist/editor/reviews/feedbackAvatar.js +41 -0
- package/dist/editor/reviews/feedbackAvatar.js.map +1 -1
- package/dist/editor/reviews/feedbackSidebarText.d.ts +2 -0
- package/dist/editor/reviews/feedbackSidebarText.js +3 -0
- package/dist/editor/reviews/feedbackSidebarText.js.map +1 -0
- package/dist/editor/services/contentService.js +5 -18
- package/dist/editor/services/contentService.js.map +1 -1
- package/dist/editor/settings/SettingsView.js +1 -1
- package/dist/editor/settings/SettingsView.js.map +1 -1
- package/dist/editor/settings/panels/AgentsPanel.js +3 -3
- package/dist/editor/settings/panels/AgentsPanel.js.map +1 -1
- package/dist/editor/settings/panels/NotificationSubscriptionsPanel.js +2 -2
- package/dist/editor/settings/panels/NotificationSubscriptionsPanel.js.map +1 -1
- package/dist/editor/settings/panels/ProjectTemplateAgentPanel.d.ts +2 -1
- package/dist/editor/settings/panels/ProjectTemplateAgentPanel.js +3 -2
- package/dist/editor/settings/panels/ProjectTemplateAgentPanel.js.map +1 -1
- package/dist/editor/settings/panels/ProjectTemplateSelectorList.js +4 -4
- package/dist/editor/settings/panels/ProjectTemplateSelectorList.js.map +1 -1
- package/dist/editor/settings/panels/ProjectTemplatesPanel.js +9 -1
- package/dist/editor/settings/panels/ProjectTemplatesPanel.js.map +1 -1
- package/dist/editor/settings/status/coreStatusChecks.js +52 -2
- package/dist/editor/settings/status/coreStatusChecks.js.map +1 -1
- package/dist/editor/sidebar/SidebarPanel.js +2 -2
- package/dist/editor/sidebar/SidebarPanel.js.map +1 -1
- package/dist/editor/sidebar/SidebarStack.js +1 -0
- package/dist/editor/sidebar/SidebarStack.js.map +1 -1
- package/dist/editor/ui/Icons.d.ts +1 -1
- package/dist/editor/ui/Icons.js +2 -2
- package/dist/editor/ui/Icons.js.map +1 -1
- package/dist/editor/ui/PublishItemDialog.js +36 -71
- package/dist/editor/ui/PublishItemDialog.js.map +1 -1
- package/dist/editor/ui/SimpleIconButton.d.ts +1 -0
- package/dist/editor/ui/SimpleIconButton.js +2 -2
- package/dist/editor/ui/SimpleIconButton.js.map +1 -1
- package/dist/editor/ui/SimpleMenu.js +1 -1
- package/dist/editor/ui/SimpleMenu.js.map +1 -1
- package/dist/editor/ui/SimpleTabs.d.ts +2 -1
- package/dist/editor/ui/SimpleTabs.js +2 -2
- package/dist/editor/ui/SimpleTabs.js.map +1 -1
- package/dist/editor/ui/Splitter.d.ts +1 -0
- package/dist/editor/ui/Splitter.js +4 -3
- package/dist/editor/ui/Splitter.js.map +1 -1
- package/dist/editor/utils.d.ts +8 -2
- package/dist/editor/utils.js +46 -35
- package/dist/editor/utils.js.map +1 -1
- package/dist/editor/version-diff/versionDiffTargets.js +8 -15
- package/dist/editor/version-diff/versionDiffTargets.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/splash-screen/DialogWrappers.js +2 -2
- package/dist/splash-screen/DialogWrappers.js.map +1 -1
- package/dist/splash-screen/RecentPages.js +7 -7
- package/dist/splash-screen/RecentPages.js.map +1 -1
- package/dist/task-board/TaskBoardWorkspace.js +1 -1
- package/dist/task-board/TaskBoardWorkspace.js.map +1 -1
- package/dist/tour/Tour.js +1 -1
- package/dist/tour/Tour.js.map +1 -1
- package/package.json +1 -1
- package/styles.css +5 -0
package/dist/editor/ai/Agents.js
CHANGED
|
@@ -1,25 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import React, { useState, useRef, useEffect
|
|
2
|
+
import React, { useState, useRef, useEffect } from "react";
|
|
3
3
|
import { SimpleIconButton } from "../ui/SimpleIconButton";
|
|
4
|
-
import {
|
|
4
|
+
import { ArrowLeft, List, Plus } from "lucide-react";
|
|
5
|
+
import { CloseButton } from "../../components/ui/close-button";
|
|
5
6
|
import { cn } from "../../lib/utils";
|
|
6
7
|
import { sanitizeSvg } from "../../lib/sanitize";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { CloseButton } from "../../components/ui/close-button";
|
|
10
|
-
import { Popover, PopoverContent, PopoverTrigger, } from "../../components/ui/popover";
|
|
11
|
-
import { getActiveAgents, closeAgent as closeAgentService, } from "../services/agentService";
|
|
12
|
-
import { isExecutingAgentStatus, isRunningAgentStatus, needsAgentAttention, parseAgentRunStatusData, parseAgentStatus, shouldIgnoreReplayRunStart, } from "../services/agentStatus";
|
|
13
|
-
import { toUserFacingAgentErrorMessage } from "../services/agentErrorMessage";
|
|
8
|
+
import { getActiveAgents, } from "../services/agentService";
|
|
9
|
+
import { isExecutingAgentStatus, parseAgentRunStatusData, parseAgentStatus, shouldIgnoreReplayRunStart, } from "../services/agentStatus";
|
|
14
10
|
import { AgentTerminal } from "./AgentTerminal";
|
|
15
11
|
import { useEditContext } from "../client/editContext";
|
|
16
|
-
import { Tooltip, TooltipContent, TooltipTrigger, } from "../../components/ui/tooltip";
|
|
17
|
-
// import { Button } from "../../components/ui/button";
|
|
18
12
|
import { loadAiProfiles } from "../services/aiService";
|
|
19
|
-
import { ChevronDown, List } from "lucide-react";
|
|
20
13
|
import { AgentProfileSelector } from "./AgentProfileSelector";
|
|
21
14
|
import { AgentsView } from "../../agents-view/AgentsView";
|
|
22
|
-
import {
|
|
15
|
+
import { ParheliaAgentIcon } from "../ui/Icons";
|
|
23
16
|
import { Spinner } from "../ui/Spinner";
|
|
24
17
|
import { localStorageService } from "../services/localStorageService";
|
|
25
18
|
import { LicenseFeatures, useFeature } from "../../licensing";
|
|
@@ -48,14 +41,6 @@ import { LicenseFeatures, useFeature } from "../../licensing";
|
|
|
48
41
|
// }
|
|
49
42
|
const ACTIVE_AGENT_STORAGE_KEY = "editor.activeAgentId";
|
|
50
43
|
const TASKBOARD_PROJECT_QUERY_KEY = "tbProjectId";
|
|
51
|
-
function AgentStatusIndicator({ status, label, size = "sm", }) {
|
|
52
|
-
if (status === "running") {
|
|
53
|
-
const dotClass = size === "md" ? "h-1.5 w-1.5" : "h-1 w-1";
|
|
54
|
-
return (_jsxs("div", { className: "flex flex-shrink-0 items-center gap-0.5", title: label, "aria-label": label, children: [_jsx("div", { className: cn(dotClass, "bg-highlight-100 animate-bounce rounded-full [animation-delay:-0.3s]") }), _jsx("div", { className: cn(dotClass, "bg-highlight-100 animate-bounce rounded-full [animation-delay:-0.15s]") }), _jsx("div", { className: cn(dotClass, "bg-highlight-100 animate-bounce rounded-full") })] }));
|
|
55
|
-
}
|
|
56
|
-
const statusConfig = getAgentStatusConfig({ status });
|
|
57
|
-
return (_jsx("div", { className: cn(size === "md" ? "h-2 w-2" : "h-1.5 w-1.5", "flex-shrink-0 rounded-full", statusConfig.color, statusConfig.shouldPulse && "animate-pulse"), title: label, "aria-label": label }));
|
|
58
|
-
}
|
|
59
44
|
const TASKBOARD_TASK_QUERY_KEY = "tbTaskId";
|
|
60
45
|
function readTaskboardLinkageFromUrl() {
|
|
61
46
|
if (typeof window === "undefined") {
|
|
@@ -74,9 +59,10 @@ export const Agents = React.memo(function Agents({ closeButton, }) {
|
|
|
74
59
|
const [activeAgentId, setActiveAgentId] = useState(""); // "" = show profile selector, null = show overview, string = agent ID
|
|
75
60
|
const activeAgentIdRef = useRef("");
|
|
76
61
|
const singleAgentModeRef = useRef(false);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const
|
|
62
|
+
// Remembers the agent to return to when dismissing the agents-list or
|
|
63
|
+
// profile-selector overlay via the X button.
|
|
64
|
+
const returnAgentIdRef = useRef(null);
|
|
65
|
+
const [loadingAgents, setLoadingAgents] = useState(true);
|
|
80
66
|
const [inactiveAgents, setInactiveAgents] = useState([]);
|
|
81
67
|
const [initialMetadataMap, setInitialMetadataMap] = useState({});
|
|
82
68
|
const [availableProfiles, setAvailableProfiles] = useState([]);
|
|
@@ -84,36 +70,15 @@ export const Agents = React.memo(function Agents({ closeButton, }) {
|
|
|
84
70
|
const [loadingProfiles, setLoadingProfiles] = useState(false);
|
|
85
71
|
const editContext = useEditContext();
|
|
86
72
|
const canUseAi = useFeature(LicenseFeatures.AI);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
profileId,
|
|
97
|
-
profileName: agent.profileName || "General",
|
|
98
|
-
profileSvgIcon: profile?.svgIcon,
|
|
99
|
-
agents: [],
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
// Update icon if current group doesn't have one but this agent does
|
|
104
|
-
const group = profileMap.get(profileKey);
|
|
105
|
-
if (!group.profileSvgIcon && profile?.svgIcon) {
|
|
106
|
-
group.profileSvgIcon = profile?.svgIcon;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
profileMap.get(profileKey).agents.push(agent);
|
|
110
|
-
});
|
|
111
|
-
return profileMap;
|
|
112
|
-
}, [agents, availableProfiles]);
|
|
113
|
-
// Calculate inbox count (agents needing attention, excluding currently open agent)
|
|
114
|
-
const inboxCount = useMemo(() => {
|
|
115
|
-
return agents.filter((agent) => needsAgentAttention(agent.status) && agent.id !== activeAgentId).length;
|
|
116
|
-
}, [agents, activeAgentId]);
|
|
73
|
+
const defaultCloseButton = (_jsx(CloseButton, { onClick: () => {
|
|
74
|
+
editContext?.setShowAgentsPanel(false);
|
|
75
|
+
if (editContext?.openSidebars.includes("agents-panel")) {
|
|
76
|
+
editContext.toggleSidebar("agents-panel", { forceClose: true });
|
|
77
|
+
}
|
|
78
|
+
}, label: "Close Agents Panel", showTooltip: false }));
|
|
79
|
+
// Resolve the profile SVG icon for the active/return agent shown in the header.
|
|
80
|
+
const getAgentIcon = (agent) => availableProfiles.find((p) => p.id === agent.profileId)?.svgIcon ||
|
|
81
|
+
agent.profileSvgIcon;
|
|
117
82
|
// Detect single-agent mode from query parameter once on mount
|
|
118
83
|
useEffect(() => {
|
|
119
84
|
try {
|
|
@@ -134,37 +99,13 @@ export const Agents = React.memo(function Agents({ closeButton, }) {
|
|
|
134
99
|
: mostRecent;
|
|
135
100
|
});
|
|
136
101
|
};
|
|
137
|
-
// Helper function to get highest priority status for a group of agents
|
|
138
|
-
const getHighestPriorityStatus = (agentList) => {
|
|
139
|
-
const statusPriority = {
|
|
140
|
-
waitingForApproval: 5,
|
|
141
|
-
error: 4,
|
|
142
|
-
running: 3,
|
|
143
|
-
idle: 2,
|
|
144
|
-
completed: 1,
|
|
145
|
-
closed: 0,
|
|
146
|
-
new: 0,
|
|
147
|
-
};
|
|
148
|
-
let highestPriority = -1;
|
|
149
|
-
let highestStatus = "idle";
|
|
150
|
-
agentList.forEach((agent) => {
|
|
151
|
-
const statusKey = typeof agent.status === "string" ? agent.status : "idle";
|
|
152
|
-
const priority = statusPriority[statusKey] ?? 0;
|
|
153
|
-
if (priority > highestPriority) {
|
|
154
|
-
highestPriority = priority;
|
|
155
|
-
highestStatus = agent.status;
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
return highestStatus;
|
|
159
|
-
};
|
|
160
102
|
// Helper function to set active agent and persist to localStorage.
|
|
161
|
-
//
|
|
162
|
-
//
|
|
103
|
+
// Keep this as a plain React update: the embedded panel can contain long
|
|
104
|
+
// transcripts, profile grids, and hidden running terminals, and browser View
|
|
105
|
+
// Transition snapshots have proven too expensive here.
|
|
163
106
|
const setActiveAgentIdWithStorage = (agentId) => {
|
|
164
107
|
activeAgentIdRef.current = agentId;
|
|
165
|
-
|
|
166
|
-
setActiveAgentId(agentId);
|
|
167
|
-
});
|
|
108
|
+
setActiveAgentId(agentId);
|
|
168
109
|
if (agentId) {
|
|
169
110
|
localStorageService.setString(ACTIVE_AGENT_STORAGE_KEY, agentId);
|
|
170
111
|
}
|
|
@@ -172,6 +113,34 @@ export const Agents = React.memo(function Agents({ closeButton, }) {
|
|
|
172
113
|
localStorageService.removeItem(ACTIVE_AGENT_STORAGE_KEY);
|
|
173
114
|
}
|
|
174
115
|
};
|
|
116
|
+
// Remember the currently open agent (if any) so the overlay X can return to it.
|
|
117
|
+
const rememberReturnAgent = () => {
|
|
118
|
+
const current = activeAgentIdRef.current;
|
|
119
|
+
if (typeof current === "string" && current) {
|
|
120
|
+
returnAgentIdRef.current = current;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
// The "+" button: open the profile selector to start a new agent.
|
|
124
|
+
const showNewAgentProfileSelector = () => {
|
|
125
|
+
rememberReturnAgent();
|
|
126
|
+
setActiveAgentIdWithStorage("");
|
|
127
|
+
};
|
|
128
|
+
// Clicking the agent title: open the full agents list to switch agents.
|
|
129
|
+
const openAgentsList = () => {
|
|
130
|
+
rememberReturnAgent();
|
|
131
|
+
setActiveAgentIdWithStorage(null);
|
|
132
|
+
};
|
|
133
|
+
// The overlay X: return to the previously open agent, falling back to the
|
|
134
|
+
// most recent agent, or the agents list when nothing is open.
|
|
135
|
+
const dismissOverlay = () => {
|
|
136
|
+
const ret = returnAgentIdRef.current;
|
|
137
|
+
if (ret && agents.some((a) => a.id === ret)) {
|
|
138
|
+
setActiveAgentIdWithStorage(ret);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const mostRecent = getMostRecentAgent(agents);
|
|
142
|
+
setActiveAgentIdWithStorage(mostRecent ? mostRecent.id : null);
|
|
143
|
+
};
|
|
175
144
|
// Open an agent from history (or switch to it if already open)
|
|
176
145
|
const openAgentFromHistory = React.useCallback(async (agent) => {
|
|
177
146
|
if (!canUseAi) {
|
|
@@ -688,30 +657,24 @@ export const Agents = React.memo(function Agents({ closeButton, }) {
|
|
|
688
657
|
selectedAgentId = mostRecentAgent?.id || null;
|
|
689
658
|
}
|
|
690
659
|
}
|
|
691
|
-
// If there are no active agents after load,
|
|
660
|
+
// If there are no active agents after load, show the agents list/empty
|
|
661
|
+
// state. The profile selector is heavier and should only mount when the
|
|
662
|
+
// user explicitly clicks + New Agent.
|
|
692
663
|
if (activeAgentsResult.length === 0) {
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
setSelectedProfileId("");
|
|
700
|
-
}
|
|
701
|
-
return prev;
|
|
702
|
-
});
|
|
664
|
+
if (!activeAgentIdRef.current) {
|
|
665
|
+
setActiveAgentId(null);
|
|
666
|
+
activeAgentIdRef.current = null;
|
|
667
|
+
localStorage.removeItem(ACTIVE_AGENT_STORAGE_KEY);
|
|
668
|
+
setSelectedProfileId("");
|
|
669
|
+
}
|
|
703
670
|
}
|
|
704
671
|
else {
|
|
705
672
|
// Only restore from backend/storage if no new agent is currently active
|
|
706
673
|
// This prevents overwriting a newly created agent from a comment (especially on mobile)
|
|
707
674
|
const currentActiveId = activeAgentIdRef.current;
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
setActiveAgentIdWithStorage(selectedAgentId);
|
|
712
|
-
}
|
|
713
|
-
return prev;
|
|
714
|
-
});
|
|
675
|
+
if (!currentActiveId) {
|
|
676
|
+
setActiveAgentIdWithStorage(selectedAgentId);
|
|
677
|
+
}
|
|
715
678
|
}
|
|
716
679
|
}
|
|
717
680
|
catch (error) {
|
|
@@ -802,297 +765,44 @@ export const Agents = React.memo(function Agents({ closeButton, }) {
|
|
|
802
765
|
const handleAgentUpdate = React.useCallback((agentId, updates) => {
|
|
803
766
|
setAgents((prev) => prev.map((agent) => agent.id === agentId ? { ...agent, ...updates } : agent));
|
|
804
767
|
}, []);
|
|
805
|
-
const closeAgent = async (agentId) => {
|
|
806
|
-
try {
|
|
807
|
-
// Permanently close the agent in the backend
|
|
808
|
-
await closeAgentService(agentId);
|
|
809
|
-
}
|
|
810
|
-
catch (error) {
|
|
811
|
-
console.error("Failed to close agent:", error);
|
|
812
|
-
// Continue with UI cleanup even if backend call fails
|
|
813
|
-
}
|
|
814
|
-
setAgents((prev) => {
|
|
815
|
-
const filtered = prev.filter((a) => a.id !== agentId);
|
|
816
|
-
// Find the closed agent to add to history
|
|
817
|
-
const closedAgent = prev.find((a) => a.id === agentId);
|
|
818
|
-
if (closedAgent) {
|
|
819
|
-
// Add the closed agent to the inactive agents list (history) if it doesn't already exist
|
|
820
|
-
setInactiveAgents((prevInactive) => {
|
|
821
|
-
// Check if this agent is already in the history
|
|
822
|
-
const alreadyExists = prevInactive.some((a) => a.id === agentId);
|
|
823
|
-
if (alreadyExists) {
|
|
824
|
-
return prevInactive;
|
|
825
|
-
}
|
|
826
|
-
return [
|
|
827
|
-
{
|
|
828
|
-
...closedAgent,
|
|
829
|
-
status: "closed",
|
|
830
|
-
updatedDate: new Date().toISOString(),
|
|
831
|
-
},
|
|
832
|
-
...prevInactive,
|
|
833
|
-
];
|
|
834
|
-
});
|
|
835
|
-
}
|
|
836
|
-
// If we're closing the active terminal, switch to the most recent remaining one or show profile selector
|
|
837
|
-
if (activeAgentIdRef.current === agentId) {
|
|
838
|
-
if (filtered.length > 0) {
|
|
839
|
-
const mostRecentAgent = getMostRecentAgent(filtered);
|
|
840
|
-
setActiveAgentIdWithStorage(mostRecentAgent?.id || null);
|
|
841
|
-
}
|
|
842
|
-
else {
|
|
843
|
-
// No agents left, show profile selector
|
|
844
|
-
setActiveAgentId("");
|
|
845
|
-
activeAgentIdRef.current = "";
|
|
846
|
-
localStorage.removeItem(ACTIVE_AGENT_STORAGE_KEY);
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
// If no agents remain, reset profile selection to placeholder
|
|
850
|
-
if (filtered.length === 0) {
|
|
851
|
-
setSelectedProfileId("");
|
|
852
|
-
}
|
|
853
|
-
return filtered;
|
|
854
|
-
});
|
|
855
|
-
};
|
|
856
|
-
const handleCloseAgent = (agentId, e) => {
|
|
857
|
-
e.stopPropagation();
|
|
858
|
-
// Find the agent to check its status
|
|
859
|
-
const agent = agents.find((a) => a.id === agentId);
|
|
860
|
-
if (!agent) {
|
|
861
|
-
// Agent not found, close anyway
|
|
862
|
-
closeAgent(agentId);
|
|
863
|
-
return;
|
|
864
|
-
}
|
|
865
|
-
const isActivelyRunning = agent.status === "running" || agent.status === "waitingForApproval";
|
|
866
|
-
// If agent is actively running, show confirmation dialog
|
|
867
|
-
if (isActivelyRunning) {
|
|
868
|
-
if (editContext?.confirm) {
|
|
869
|
-
editContext.confirm({
|
|
870
|
-
header: "Abort Agent",
|
|
871
|
-
message: "This agent is currently running. Are you sure you want to abort it?",
|
|
872
|
-
acceptLabel: "Abort Agent",
|
|
873
|
-
accept: () => {
|
|
874
|
-
closeAgent(agentId);
|
|
875
|
-
},
|
|
876
|
-
showCancel: true,
|
|
877
|
-
});
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
else {
|
|
881
|
-
// Agent is not actively running, close immediately
|
|
882
|
-
closeAgent(agentId);
|
|
883
|
-
}
|
|
884
|
-
};
|
|
885
|
-
const handleCloseProfileAgents = async (profileAgents, profileName, e) => {
|
|
886
|
-
e.stopPropagation();
|
|
887
|
-
const agentCount = profileAgents.length;
|
|
888
|
-
const hasActiveAgents = profileAgents.some((agent) => isExecutingAgentStatus(agent.status));
|
|
889
|
-
if (editContext?.confirm) {
|
|
890
|
-
editContext.confirm({
|
|
891
|
-
header: `Close ${agentCount} Agent${agentCount > 1 ? "s" : ""}`,
|
|
892
|
-
message: hasActiveAgents
|
|
893
|
-
? `This will close all ${agentCount} ${profileName} agent${agentCount > 1 ? "s" : ""}, including ${profileAgents.filter((a) => isRunningAgentStatus(a.status)).length} running agent(s). Are you sure?`
|
|
894
|
-
: `Are you sure you want to close all ${agentCount} ${profileName} agent${agentCount > 1 ? "s" : ""}?`,
|
|
895
|
-
acceptLabel: `Close ${agentCount > 1 ? "All" : "Agent"}`,
|
|
896
|
-
accept: async () => {
|
|
897
|
-
// Close all agents in this profile
|
|
898
|
-
const closePromises = profileAgents.map((agent) => closeAgentService(agent.id).catch((error) => {
|
|
899
|
-
console.error(`Failed to close agent ${agent.id}:`, error);
|
|
900
|
-
}));
|
|
901
|
-
await Promise.all(closePromises);
|
|
902
|
-
// Update UI state
|
|
903
|
-
setAgents((prev) => {
|
|
904
|
-
const agentIds = new Set(profileAgents.map((a) => a.id));
|
|
905
|
-
const filtered = prev.filter((a) => !agentIds.has(a.id));
|
|
906
|
-
// Add closed agents to history
|
|
907
|
-
const closedAgents = profileAgents.map((agent) => ({
|
|
908
|
-
...agent,
|
|
909
|
-
status: "closed",
|
|
910
|
-
updatedDate: new Date().toISOString(),
|
|
911
|
-
}));
|
|
912
|
-
setInactiveAgents((prevInactive) => {
|
|
913
|
-
const newAgents = closedAgents.filter((closedAgent) => !prevInactive.some((a) => a.id === closedAgent.id));
|
|
914
|
-
return [...newAgents, ...prevInactive];
|
|
915
|
-
});
|
|
916
|
-
// If we're closing the active agent, switch to most recent remaining or show profile selector
|
|
917
|
-
if (activeAgentIdRef.current &&
|
|
918
|
-
agentIds.has(activeAgentIdRef.current)) {
|
|
919
|
-
if (filtered.length > 0) {
|
|
920
|
-
const mostRecentAgent = getMostRecentAgent(filtered);
|
|
921
|
-
setActiveAgentIdWithStorage(mostRecentAgent?.id || null);
|
|
922
|
-
}
|
|
923
|
-
else {
|
|
924
|
-
// No agents left, show profile selector
|
|
925
|
-
setActiveAgentId("");
|
|
926
|
-
activeAgentIdRef.current = "";
|
|
927
|
-
localStorageService.removeItem(ACTIVE_AGENT_STORAGE_KEY);
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
// Reset profile selection if no agents remain
|
|
931
|
-
if (filtered.length === 0) {
|
|
932
|
-
setSelectedProfileId("");
|
|
933
|
-
}
|
|
934
|
-
return filtered;
|
|
935
|
-
});
|
|
936
|
-
},
|
|
937
|
-
showCancel: true,
|
|
938
|
-
});
|
|
939
|
-
}
|
|
940
|
-
};
|
|
941
|
-
const closeOtherAgents = async () => {
|
|
942
|
-
if (!activeAgentIdRef.current)
|
|
943
|
-
return;
|
|
944
|
-
// Get agents to close (all except active)
|
|
945
|
-
const agentsToClose = agents.filter((a) => a.id !== activeAgentIdRef.current);
|
|
946
|
-
// Permanently close each agent in the backend
|
|
947
|
-
const closePromises = agentsToClose.map(async (agent) => {
|
|
948
|
-
try {
|
|
949
|
-
await closeAgentService(agent.id);
|
|
950
|
-
}
|
|
951
|
-
catch (error) {
|
|
952
|
-
console.error(`Failed to close agent ${agent.id}:`, error);
|
|
953
|
-
}
|
|
954
|
-
});
|
|
955
|
-
// Wait for all close operations to complete
|
|
956
|
-
await Promise.all(closePromises);
|
|
957
|
-
// Add closed agents to history (deduplicate to prevent duplicates)
|
|
958
|
-
if (agentsToClose.length > 0) {
|
|
959
|
-
const closedAgents = agentsToClose.map((agent) => ({
|
|
960
|
-
...agent,
|
|
961
|
-
status: "closed",
|
|
962
|
-
updatedDate: new Date().toISOString(),
|
|
963
|
-
}));
|
|
964
|
-
setInactiveAgents((prevInactive) => {
|
|
965
|
-
// Filter out agents that already exist in history
|
|
966
|
-
const newAgents = closedAgents.filter((closedAgent) => !prevInactive.some((a) => a.id === closedAgent.id));
|
|
967
|
-
return [...newAgents, ...prevInactive];
|
|
968
|
-
});
|
|
969
|
-
}
|
|
970
|
-
setAgents((prev) => {
|
|
971
|
-
return prev.filter((a) => a.id === activeAgentIdRef.current);
|
|
972
|
-
});
|
|
973
|
-
setMenuPopoverOpen(false);
|
|
974
|
-
};
|
|
975
|
-
const getTabsMenuItems = () => {
|
|
976
|
-
return [
|
|
977
|
-
{
|
|
978
|
-
id: "close-other",
|
|
979
|
-
label: "Close Other",
|
|
980
|
-
command: async () => {
|
|
981
|
-
await closeOtherAgents();
|
|
982
|
-
},
|
|
983
|
-
disabled: agents.length <= 1,
|
|
984
|
-
},
|
|
985
|
-
];
|
|
986
|
-
};
|
|
987
768
|
if (!canUseAi) {
|
|
988
769
|
return (_jsx("div", { className: "text-neutral-grey-50 flex h-full items-center justify-center p-4 text-center text-sm", children: "AI features are unavailable with the current license." }));
|
|
989
770
|
}
|
|
990
771
|
if (loadingAgents) {
|
|
991
772
|
return (_jsxs("div", { className: "flex h-full items-center justify-center gap-2", children: [_jsx(Spinner, { size: "sm" }), _jsx("div", { className: "text-neutral-grey-50 text-xs", children: "Loading agents..." })] }));
|
|
992
773
|
}
|
|
993
|
-
//
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
const profileKey = profileGroup.profileId || "general";
|
|
1026
|
-
const activeAgent = profileGroup.agents.find((a) => a.id === activeAgentId);
|
|
1027
|
-
const isActive = !!activeAgent;
|
|
1028
|
-
const agentCount = profileGroup.agents.length;
|
|
1029
|
-
const singleAgent = agentCount === 1 ? profileGroup.agents[0] : null;
|
|
1030
|
-
const highestStatus = getHighestPriorityStatus(profileGroup.agents);
|
|
1031
|
-
const statusConfig = getAgentStatusConfig({
|
|
1032
|
-
status: highestStatus,
|
|
1033
|
-
});
|
|
1034
|
-
const singleAgentErrorMessage = toUserFacingAgentErrorMessage(singleAgent?.statusMessage) ||
|
|
1035
|
-
singleAgent?.statusMessage;
|
|
1036
|
-
const activeAgentErrorMessage = toUserFacingAgentErrorMessage(activeAgent?.statusMessage) ||
|
|
1037
|
-
activeAgent?.statusMessage;
|
|
1038
|
-
// Use agent name if: single agent OR active agent from this profile
|
|
1039
|
-
const displayName = activeAgent
|
|
1040
|
-
? activeAgent.name
|
|
1041
|
-
: singleAgent
|
|
1042
|
-
? singleAgent.name
|
|
1043
|
-
: profileGroup.profileName;
|
|
1044
|
-
// Always use profile group icon since all agents in the group share the same profile
|
|
1045
|
-
const displayIcon = profileGroup.profileSvgIcon;
|
|
1046
|
-
// For data-agent-id: prioritize singleAgent, then activeAgent
|
|
1047
|
-
// This ensures a single agent always has its ID on the tab
|
|
1048
|
-
const tabAgentId = singleAgent?.id || activeAgent?.id || "";
|
|
1049
|
-
return (_jsx("div", { className: "min-w-0 shrink", "data-active": isActive ? "true" : "false", "data-agent-id": tabAgentId, children: _jsxs(Popover, { open: profileTabDropdownOpen === profileKey, onOpenChange: (open) => {
|
|
1050
|
-
setProfileTabDropdownOpen(open ? profileKey : null);
|
|
1051
|
-
if (open) {
|
|
1052
|
-
setMenuPopoverOpen(false);
|
|
1053
|
-
}
|
|
1054
|
-
}, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("div", { className: cn("border-border-default flex min-w-0 cursor-pointer items-center gap-2 overflow-hidden border-r p-2 text-xs", isActive
|
|
1055
|
-
? "border-b-white bg-white"
|
|
1056
|
-
: "hover:bg-neutral-grey-5"), onClick: () => {
|
|
1057
|
-
if (singleAgent) {
|
|
1058
|
-
// Single agent: switch directly
|
|
1059
|
-
setActiveAgentIdWithStorage(singleAgent.id);
|
|
1060
|
-
}
|
|
1061
|
-
// Multiple agents: popover will open via PopoverTrigger
|
|
1062
|
-
}, children: [_jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2 overflow-hidden", children: [_jsx("div", { className: "flex-shrink-0", children: displayIcon ? (_jsx("div", { className: "text-neutral-grey-50 flex h-[18px] w-[18px] items-center justify-center [&>svg]:h-full [&>svg]:w-full", dangerouslySetInnerHTML: {
|
|
1063
|
-
__html: sanitizeSvg(displayIcon),
|
|
1064
|
-
} })) : (_jsx(SecretAgentIcon, { size: 18, strokeWidth: 1, className: "text-neutral-grey-50" })) }), _jsx("span", { className: "min-w-0 flex-1 truncate font-medium", children: displayName }), agentCount > 1 && (_jsx("div", { className: "bg-neutral-grey-10 badge-pad-sm text-neutral-grey-100 flex-shrink-0 rounded-full text-[10px] leading-none font-medium", children: agentCount })), _jsxs(Tooltip, { delayDuration: 1000, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("div", { className: "flex flex-shrink-0 items-center", title: statusConfig.label, children: _jsx(AgentStatusIndicator, { status: highestStatus, label: statusConfig.label }) }) }), _jsx(TooltipContent, { children: _jsxs("div", { children: [_jsx("div", { children: statusConfig.label }), singleAgent?.status === "error" ? (singleAgentErrorMessage ? (_jsx("div", { className: "text-feedback-red mt-1 text-xs", children: singleAgentErrorMessage })) : null) : activeAgent?.status === "error" ? (activeAgentErrorMessage ? (_jsx("div", { className: "text-feedback-red mt-1 text-xs", children: activeAgentErrorMessage })) : null) : null] }) })] }), agentCount > 1 && (_jsx(ChevronDown, { className: "text-neutral-grey-50 size-3 flex-shrink-0", strokeWidth: 1 }))] }), _jsx(CloseButton, { onClick: (e) => singleAgent
|
|
1065
|
-
? handleCloseAgent(singleAgent.id, e)
|
|
1066
|
-
: handleCloseProfileAgents(profileGroup.agents, profileGroup.profileName, e), label: agentCount > 1
|
|
1067
|
-
? `Close all ${agentCount} agents`
|
|
1068
|
-
: "Close", className: "flex-shrink-0 opacity-60 hover:opacity-100", showTooltip: false })] }) }), agentCount > 1 && (_jsxs(PopoverContent, { className: "w-80 p-0", align: "start", children: [_jsxs("div", { className: "border-border-default text-neutral-grey-50 border-b px-3 py-2 text-xs font-medium", children: [profileGroup.profileName, " Agents"] }), _jsx("div", { className: "max-h-64 overflow-y-auto", children: profileGroup.agents.map((agent) => {
|
|
1069
|
-
const agentStatusConfig = getAgentStatusConfig(agent);
|
|
1070
|
-
const agentErrorMessage = toUserFacingAgentErrorMessage(agent.statusMessage) || agent.statusMessage;
|
|
1071
|
-
return (_jsx("div", { "data-agent-id": agent.id, className: cn("border-border-default hover:bg-neutral-grey-5 cursor-pointer border-b px-3 py-2", activeAgentId === agent.id &&
|
|
1072
|
-
"bg-highlight-10/50"), onClick: () => {
|
|
1073
|
-
setActiveAgentIdWithStorage(agent.id);
|
|
1074
|
-
setProfileTabDropdownOpen(null);
|
|
1075
|
-
}, children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(AgentStatusIndicator, { status: agent.status, label: agentStatusConfig.label, size: "md" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-neutral-grey-100 truncate text-xs font-medium", children: agent.name }), _jsx("div", { className: "text-neutral-grey-50 font-mono text-[9px]", children: agent.id }), agent.status === "error" ? (agentErrorMessage ? (_jsx("div", { className: "text-feedback-red truncate text-[11px] leading-tight", children: agentErrorMessage })) : (agent.description && (_jsx("div", { className: "text-neutral-grey-50 truncate text-[11px] leading-tight", children: agent.description })))) : (agent.description && (_jsx("div", { className: "text-neutral-grey-50 truncate text-[11px] leading-tight", children: agent.description })))] }), _jsx(CloseButton, { onClick: (e) => handleCloseAgent(agent.id, e), label: "Close", className: "opacity-60 hover:opacity-100" })] }) }, agent.id));
|
|
1076
|
-
}) })] }))] }) }, profileKey));
|
|
1077
|
-
})] }), activeAgentId !== null && (_jsx("div", { className: "flex items-center px-1", children: _jsx(SimpleIconButton, { onClick: () => setActiveAgentIdWithStorage(null), icon: _jsxs("div", { className: "relative", children: [_jsx(List, { className: "size-4", strokeWidth: 1 }), inboxCount > 0 && (_jsx("span", { className: "bg-feedback-orange absolute -top-1.5 -right-1.5 flex h-3.5 min-w-3.5 items-center justify-center rounded-full px-1 text-[9px] font-bold text-white", children: inboxCount > 9 ? "9+" : inboxCount }))] }), label: `Agent Overview${inboxCount > 0 ? ` (${inboxCount} need attention)` : ""}`, className: "text-neutral-grey-50 hover:text-neutral-grey-100" }) })), activeAgentId === null && (_jsx("div", { className: "flex items-center px-1", children: _jsxs("div", { className: cn("border-border-default flex min-w-0 cursor-default items-center gap-2 border-r p-2 text-xs", "border-b-white bg-white"), children: [_jsxs("div", { className: "relative", children: [_jsx(List, { className: "text-neutral-grey-50 size-4 flex-shrink-0", strokeWidth: 1 }), inboxCount > 0 && (_jsx("span", { className: "bg-feedback-orange absolute -top-1.5 -right-1.5 flex h-3.5 min-w-3.5 items-center justify-center rounded-full px-1 text-[9px] font-bold text-white", children: inboxCount > 9 ? "9+" : inboxCount }))] }), _jsx("span", { className: "truncate font-medium", children: "Overview" })] }) })), agents.length > 0 && (_jsx("div", { className: "flex items-center px-1", children: _jsxs(Popover, { open: menuPopoverOpen, onOpenChange: (open) => {
|
|
1078
|
-
setMenuPopoverOpen(open);
|
|
1079
|
-
if (open) {
|
|
1080
|
-
setProfileTabDropdownOpen(null);
|
|
1081
|
-
}
|
|
1082
|
-
}, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(SimpleIconButton, { onClick: (e) => {
|
|
1083
|
-
setMenuPopoverOpen(!menuPopoverOpen);
|
|
1084
|
-
if (!menuPopoverOpen) {
|
|
1085
|
-
setProfileTabDropdownOpen(null);
|
|
1086
|
-
}
|
|
1087
|
-
}, icon: _jsx(MoreVertical, { className: "size-4", strokeWidth: 1 }), label: "Menu", className: "text-neutral-grey-50 hover:text-neutral-grey-100", showTooltip: false }) }), _jsx(PopoverContent, { className: "w-48 p-0", align: "end", children: _jsx("div", { className: "py-1", children: getTabsMenuItems().map((item) => item.separator ? (_jsx("div", { className: "bg-border-default my-1 h-px" }, item.id)) : (_jsx("button", { onClick: async (e) => {
|
|
1088
|
-
if (item.command)
|
|
1089
|
-
await item.command(e);
|
|
1090
|
-
setMenuPopoverOpen(false);
|
|
1091
|
-
}, disabled: !!item.disabled, className: "hover:bg-neutral-grey-5 disabled:text-neutral-grey-50 w-full px-3 py-2 text-left text-xs disabled:cursor-not-allowed", children: item.label }, item.id))) }) })] }) })), _jsx("div", { className: "flex items-center px-1", children: _jsx(SimpleIconButton, { onClick: () => {
|
|
1092
|
-
setActiveAgentId("");
|
|
1093
|
-
activeAgentIdRef.current = "";
|
|
1094
|
-
localStorage.removeItem(ACTIVE_AGENT_STORAGE_KEY);
|
|
1095
|
-
}, icon: _jsx(Plus, { className: "size-4", strokeWidth: 1 }), label: agents.length === 0 ? "Create Agent" : "Add Agent", className: cn("text-neutral-grey-50 hover:text-neutral-grey-100", activeAgentId === "" && "bg-highlight-10 text-highlight-100"), showTooltip: false, "data-testid": "add-agent-button" }) }), closeButton && (_jsx("div", { className: "flex items-center px-2", children: closeButton }))] }), _jsx("div", { className: "relative flex-1", children: (() => {
|
|
774
|
+
// Derived display state for the header.
|
|
775
|
+
const activeAgent = agents.find((a) => a.id === activeAgentId);
|
|
776
|
+
const returnAgent = returnAgentIdRef.current &&
|
|
777
|
+
agents.find((agent) => agent.id === returnAgentIdRef.current);
|
|
778
|
+
// Overlay modes shown instead of an agent terminal:
|
|
779
|
+
// null = agents list, "" = profile selector, string = an agent.
|
|
780
|
+
const showingList = activeAgentId === null;
|
|
781
|
+
const showingSelector = activeAgentId === "";
|
|
782
|
+
const inOverlay = showingList || showingSelector;
|
|
783
|
+
// The return button can go back to an agent only when at least one is open.
|
|
784
|
+
const canDismissToAgent = agents.length > 0;
|
|
785
|
+
const headerActsAsBack = inOverlay && canDismissToAgent;
|
|
786
|
+
const contextLabel = showingSelector
|
|
787
|
+
? "Choose an agent profile"
|
|
788
|
+
: showingList
|
|
789
|
+
? "Select an agent"
|
|
790
|
+
: activeAgent
|
|
791
|
+
? activeAgent.name
|
|
792
|
+
: "Agents";
|
|
793
|
+
const headerAgent = !inOverlay ? activeAgent : null;
|
|
794
|
+
const headerAgentIcon = headerAgent ? getAgentIcon(headerAgent) : undefined;
|
|
795
|
+
return (_jsxs("div", { className: "flex h-full flex-col", children: [_jsxs("div", { className: cn("border-border-default flex min-h-12 items-center gap-1.5 border-b bg-white px-2.5 py-2", headerActsAsBack && "cursor-pointer"), onClick: headerActsAsBack ? dismissOverlay : undefined, children: [_jsxs("button", { type: "button", "data-active": !inOverlay ? "true" : undefined, "data-agent-id": typeof activeAgentId === "string" ? activeAgentId : "", "data-testid": "agent-title", "aria-label": headerActsAsBack ? "Return to agent" : "Open agents list", onClick: (event) => {
|
|
796
|
+
if (headerActsAsBack) {
|
|
797
|
+
event.stopPropagation();
|
|
798
|
+
dismissOverlay();
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
openAgentsList();
|
|
802
|
+
}, className: "flex min-w-0 flex-1 cursor-pointer items-center gap-1.5 rounded-md px-1.5 py-1 text-left", children: [headerActsAsBack && (_jsx(ArrowLeft, { className: "text-neutral-grey-50 size-4 shrink-0", strokeWidth: 1.5 })), headerAgent &&
|
|
803
|
+
(headerAgentIcon ? (_jsx("div", { className: "text-neutral-grey-100 flex size-[22px] shrink-0 items-center justify-center [&>svg]:h-full [&>svg]:w-full", dangerouslySetInnerHTML: {
|
|
804
|
+
__html: sanitizeSvg(headerAgentIcon),
|
|
805
|
+
} })) : (_jsx(ParheliaAgentIcon, { size: 22, strokeWidth: 1.35, className: "text-neutral-grey-100 shrink-0" }))), headerAgent && (_jsx("span", { className: "text-neutral-grey-50 shrink-0 text-xs", children: "-" })), _jsx("span", { className: "text-neutral-grey-100 min-w-0 flex-1 truncate text-xs font-medium", children: contextLabel })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", onClick: (event) => event.stopPropagation(), children: [!showingList && agents.length > 0 && (_jsx(SimpleIconButton, { onClick: openAgentsList, icon: _jsx(List, { className: "size-4", strokeWidth: 1.5 }), label: "Switch Agent", className: "text-neutral-grey-50 hover:text-neutral-grey-100", "data-testid": "switch-agent-button" })), !showingSelector && (_jsx(SimpleIconButton, { onClick: showNewAgentProfileSelector, icon: _jsx(Plus, { className: "size-4", strokeWidth: 1.5 }), label: agents.length === 0 ? "Create Agent" : "New Agent", className: "text-neutral-grey-50 hover:text-neutral-grey-100", "data-testid": "add-agent-button" })), _jsx("div", { className: "flex items-center pl-0.5", children: closeButton ?? defaultCloseButton })] })] }), _jsx("div", { className: "relative flex-1", children: (() => {
|
|
1096
806
|
const shouldKeepMounted = (agent) => {
|
|
1097
807
|
const parsedStatus = parseAgentStatus(agent.status);
|
|
1098
808
|
return (agent.id === activeAgentId ||
|
|
@@ -1111,11 +821,14 @@ export const Agents = React.memo(function Agents({ closeButton, }) {
|
|
|
1111
821
|
return (_jsx("div", { className: cn("absolute inset-0", !isSelected && "hidden"), style: isSelected
|
|
1112
822
|
? { viewTransitionName: "agents-tab-pane" }
|
|
1113
823
|
: undefined, children: _jsx(AgentTerminal, { agentStub: agent, initialMetadata: initialMetadataMap[agent.id], profiles: availableProfiles, onReloadProfiles: reloadProfiles, isActive: isSelected, isVisible: keepStreaming, isFocused: isSelected, onAgentUpdate: (updates) => handleAgentUpdate(agent.id, updates) }) }, agent.id));
|
|
1114
|
-
}),
|
|
1115
|
-
//
|
|
1116
|
-
_jsx("div", { className: "absolute inset-0", children: _jsx(AgentsView, {
|
|
1117
|
-
|
|
1118
|
-
|
|
824
|
+
}), showingList ? (
|
|
825
|
+
// Agents list — pick an agent to switch, or create a new one.
|
|
826
|
+
_jsx("div", { className: "absolute inset-0", children: _jsx(AgentsView, { compact: true, hideNewAgentButton: true, selectedAgentId: returnAgentIdRef.current &&
|
|
827
|
+
agents.some((a) => a.id === returnAgentIdRef.current)
|
|
828
|
+
? returnAgentIdRef.current
|
|
829
|
+
: undefined, onSelectAgent: (agent) => openAgentFromHistory(agent), onRequestCreateAgent: showNewAgentProfileSelector }) })) : showingSelector ? (
|
|
830
|
+
// Profile selector — its heading lives in the header instead.
|
|
831
|
+
_jsx("div", { className: "absolute inset-0 flex items-start justify-center overflow-y-auto p-2", children: _jsx("div", { className: "w-full max-w-5xl", children: _jsx(AgentProfileSelector, { profiles: availableProfiles, onSelectProfile: createAgentWithSelectedProfile, loading: loadingProfiles, title: "" }) }) })) : null] }));
|
|
1119
832
|
})() })] }));
|
|
1120
833
|
});
|
|
1121
834
|
//# sourceMappingURL=Agents.js.map
|