@burdenoff/microfe-vibecontrols 2026.526.1 → 2026.526.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ai/PluginHarnessPicker.js +64 -65
- package/dist/components/ai/PluginHarnessPicker.js.map +1 -1
- package/dist/components/shared/PluginGate.js +70 -71
- package/dist/components/shared/PluginGate.js.map +1 -1
- package/dist/generated/wspace-operations.js +4 -4
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/hooks/usePluginAvailability.js +59 -83
- package/dist/hooks/usePluginAvailability.js.map +1 -1
- package/dist/pages/AgentDetailsPage.js +486 -508
- package/dist/pages/AgentDetailsPage.js.map +1 -1
- package/dist/pages/VibeDetailsPage.js +457 -457
- package/dist/pages/VibeDetailsPage.js.map +1 -1
- package/dist/pages/ai/AIPage.js +10 -10
- package/dist/pages/ai/AISessionDetailPage.js +4 -4
- package/dist/pages/ai/AgentManagerPage.js +11 -11
- package/dist/pages/ai/AgentManagerPage.js.map +1 -1
- package/package.json +1 -1
package/dist/pages/ai/AIPage.js
CHANGED
|
@@ -3,10 +3,10 @@ import t from "../../hooks/useCachedInitialData.js";
|
|
|
3
3
|
import { PageHeader as n } from "../../components/shared/PageHeader.js";
|
|
4
4
|
import { ErrorState as r } from "../../components/shared/ErrorState.js";
|
|
5
5
|
import { EmptyState as i } from "../../components/shared/EmptyState.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
6
|
+
import { AI_CORE_PACKAGE as a, AI_PROVIDER_PACKAGES as o } from "../../constants/pluginCatalog.js";
|
|
7
|
+
import { PluginGate as s } from "../../components/shared/PluginGate.js";
|
|
8
|
+
import { RequireAgentReachable as c } from "../../components/shared/RequireAgentReachable.js";
|
|
9
|
+
import { useActiveAgentProfile as l } from "../../hooks/useActiveAgentProfile.js";
|
|
10
10
|
import "../../components/shared/index.js";
|
|
11
11
|
import { PageSkeleton as u } from "../../components/shared/PageSkeleton.js";
|
|
12
12
|
import { PluginHarnessPicker as d } from "../../components/ai/PluginHarnessPicker.js";
|
|
@@ -86,7 +86,7 @@ function V() {
|
|
|
86
86
|
}
|
|
87
87
|
}, [j]), { agents: V, loading: H, error: U, refetch: W } = t();
|
|
88
88
|
U && console.error("[ai] failed to load initial workspace data", U);
|
|
89
|
-
let G = T(() => V.find((e) => e.isActive && e.tunnelUrl && e.agentApiKey) ?? null, [V]), K = G?.id ?? "", { active: q } =
|
|
89
|
+
let G = T(() => V.find((e) => e.isActive && e.tunnelUrl && e.agentApiKey) ?? null, [V]), K = G?.id ?? "", { active: q } = l(G?.id ?? null), J = T(() => ({
|
|
90
90
|
id: K,
|
|
91
91
|
profile: q
|
|
92
92
|
}), [K, q]), Y = w((e) => {
|
|
@@ -133,18 +133,18 @@ function V() {
|
|
|
133
133
|
title: j("ai.loadFailed.title", "Could not load the AI workspace"),
|
|
134
134
|
message: j("ai.loadFailed.message", "We couldn't load the AI workspace. Please try again in a moment."),
|
|
135
135
|
onRetry: W
|
|
136
|
-
}) : Z ? O === "plan" ? /* @__PURE__ */ I(
|
|
136
|
+
}) : Z ? O === "plan" ? /* @__PURE__ */ I(c, {
|
|
137
137
|
agentId: K,
|
|
138
138
|
children: /* @__PURE__ */ I(S, {
|
|
139
139
|
agent: J,
|
|
140
140
|
agentApiKey: G?.agentApiKey ?? null,
|
|
141
141
|
tunnelUrl: G?.tunnelUrl ?? null
|
|
142
142
|
})
|
|
143
|
-
}) : /* @__PURE__ */ I(
|
|
143
|
+
}) : /* @__PURE__ */ I(c, {
|
|
144
144
|
agentId: K,
|
|
145
|
-
children: /* @__PURE__ */ I(
|
|
145
|
+
children: /* @__PURE__ */ I(s, {
|
|
146
146
|
agentId: K,
|
|
147
|
-
required: [
|
|
147
|
+
required: [a],
|
|
148
148
|
mode: "all",
|
|
149
149
|
eyebrow: j("ai.pluginRequired", "AI plugin required"),
|
|
150
150
|
title: j("ai.installOrchestrator", "Install the AI orchestrator"),
|
|
@@ -160,7 +160,7 @@ function V() {
|
|
|
160
160
|
}),
|
|
161
161
|
/* @__PURE__ */ I(d, {
|
|
162
162
|
agentId: K,
|
|
163
|
-
packages:
|
|
163
|
+
packages: o,
|
|
164
164
|
title: j("ai.harnessesTitle", "AI harnesses"),
|
|
165
165
|
description: j("ai.harnessesDesc", "Install and manage the coding-agent harnesses available on this agent. You can install multiple and switch between them per-session."),
|
|
166
166
|
onChange: re
|
|
@@ -7,8 +7,8 @@ import { ErrorState as a } from "../../components/shared/ErrorState.js";
|
|
|
7
7
|
import { EmptyState as o } from "../../components/shared/EmptyState.js";
|
|
8
8
|
import { Card as s } from "../../components/shared/Card.js";
|
|
9
9
|
import { StatCard as c } from "../../components/shared/StatCard.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { RequireAgentReachable as ee } from "../../components/shared/RequireAgentReachable.js";
|
|
11
|
+
import { useActiveAgentProfile as te } from "../../hooks/useActiveAgentProfile.js";
|
|
12
12
|
import "../../components/shared/index.js";
|
|
13
13
|
import { fetchSessionLogs as ne, fetchSessionStats as re, sendPromptToSession as ie, terminateSession as ae, updateSessionConfig as oe } from "../../services/aiApi.js";
|
|
14
14
|
import { isSessionNotFoundError as l } from "../../utils/aiSessionNotFound.js";
|
|
@@ -54,7 +54,7 @@ var fe = [
|
|
|
54
54
|
response: "bg-action-primary-bg/20 text-action-primary-bg"
|
|
55
55
|
};
|
|
56
56
|
function S() {
|
|
57
|
-
let S = e(), { sessionId: C } = de(), w = t(), { agents: T, loading: he } = n(), E = f(() => T.find((e) => e.isActive && e.tunnelUrl && e.agentApiKey) ?? null, [T]), D = E?.id ?? "", O = !!D, { active: k } =
|
|
57
|
+
let S = e(), { sessionId: C } = de(), w = t(), { agents: T, loading: he } = n(), E = f(() => T.find((e) => e.isActive && e.tunnelUrl && e.agentApiKey) ?? null, [T]), D = E?.id ?? "", O = !!D, { active: k } = te(E?.id ?? null), A = f(() => ({
|
|
58
58
|
id: D,
|
|
59
59
|
profile: k
|
|
60
60
|
}), [D, k]), [j, ge] = se(fe, "chat"), [M, N] = p([]), [P, F] = p(""), [I, L] = p(!1), R = async () => {
|
|
@@ -170,7 +170,7 @@ function S() {
|
|
|
170
170
|
})
|
|
171
171
|
})
|
|
172
172
|
}),
|
|
173
|
-
/* @__PURE__ */ b(
|
|
173
|
+
/* @__PURE__ */ b(ee, {
|
|
174
174
|
agentId: D || null,
|
|
175
175
|
children: [
|
|
176
176
|
j === "chat" && /* @__PURE__ */ b("div", {
|
|
@@ -7,10 +7,10 @@ import { ErrorState as a } from "../../components/shared/ErrorState.js";
|
|
|
7
7
|
import { isNative as o, nativeNotify as s } from "../../utils/nativeBridge.js";
|
|
8
8
|
import { EmptyState as c } from "../../components/shared/EmptyState.js";
|
|
9
9
|
import { usePluginAvailability as l } from "../../hooks/usePluginAvailability.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
10
|
+
import { AI_CORE_PACKAGE as u, AI_PROVIDER_PACKAGES as d } from "../../constants/pluginCatalog.js";
|
|
11
|
+
import { PluginGate as f } from "../../components/shared/PluginGate.js";
|
|
12
|
+
import { RequireAgentReachable as p } from "../../components/shared/RequireAgentReachable.js";
|
|
13
|
+
import { useActiveAgentProfile as m } from "../../hooks/useActiveAgentProfile.js";
|
|
14
14
|
import { AgentSelector as h } from "../../components/shared/AgentSelector.js";
|
|
15
15
|
import "../../components/shared/index.js";
|
|
16
16
|
import { bulkDeleteSessions as g, terminateSession as _ } from "../../services/aiApi.js";
|
|
@@ -37,10 +37,10 @@ function L() {
|
|
|
37
37
|
if (e) return e;
|
|
38
38
|
}
|
|
39
39
|
return V.find((e) => e.isActive && e.tunnelUrl && e.agentApiKey) ?? null;
|
|
40
|
-
}, [V, W]), K = G?.id ?? "", { active: q } =
|
|
40
|
+
}, [V, W]), K = G?.id ?? "", { active: q } = m(G?.id ?? null), J = j(() => ({
|
|
41
41
|
id: K,
|
|
42
42
|
profile: q
|
|
43
|
-
}), [K, q]), Y = v((e) => e.openSession), X = v((e) => e.activeTabSessionId), { initialLoading: Z } = l(j(() => [
|
|
43
|
+
}), [K, q]), Y = v((e) => e.openSession), X = v((e) => e.activeTabSessionId), { initialLoading: Z } = l(j(() => [u, ...d], []), K || null);
|
|
44
44
|
A(() => {
|
|
45
45
|
R && K && Y(R, `Session ${R.slice(0, 8)}`);
|
|
46
46
|
}, [
|
|
@@ -104,7 +104,7 @@ function L() {
|
|
|
104
104
|
})]
|
|
105
105
|
}), /* @__PURE__ */ P("div", {
|
|
106
106
|
className: "flex-1 overflow-auto p-4 sm:p-6 space-y-6",
|
|
107
|
-
children: /* @__PURE__ */ F(
|
|
107
|
+
children: /* @__PURE__ */ F(p, {
|
|
108
108
|
agentId: K || null,
|
|
109
109
|
children: [/* @__PURE__ */ P(T, { agent: J }), /* @__PURE__ */ P(x, { agent: J })]
|
|
110
110
|
})
|
|
@@ -134,18 +134,18 @@ function L() {
|
|
|
134
134
|
/* @__PURE__ */ P(w, { active: "workbench" }),
|
|
135
135
|
/* @__PURE__ */ P("div", {
|
|
136
136
|
className: "flex-1 min-h-0 overflow-auto p-4 sm:p-6 lg:p-0",
|
|
137
|
-
children: /* @__PURE__ */ P(
|
|
137
|
+
children: /* @__PURE__ */ P(p, {
|
|
138
138
|
agentId: K || null,
|
|
139
|
-
children: /* @__PURE__ */ P(
|
|
139
|
+
children: /* @__PURE__ */ P(f, {
|
|
140
140
|
agentId: K || null,
|
|
141
141
|
requirements: [{
|
|
142
|
-
packages: [
|
|
142
|
+
packages: [u],
|
|
143
143
|
mode: "all",
|
|
144
144
|
eyebrow: z("vibecontrols.pages.ai.pluginRequiredEyebrow", "AI plugin required"),
|
|
145
145
|
title: z("vibecontrols.pages.ai.coreTitle", "Install the AI orchestrator"),
|
|
146
146
|
description: z("vibecontrols.pages.ai.coreDescription", "The AI page routes prompts and sessions through the AI orchestrator plugin on your agent. Install it to continue.")
|
|
147
147
|
}, {
|
|
148
|
-
packages:
|
|
148
|
+
packages: d,
|
|
149
149
|
mode: "any",
|
|
150
150
|
eyebrow: z("vibecontrols.pages.ai.providerEyebrow", "AI provider required"),
|
|
151
151
|
title: z("vibecontrols.pages.ai.providerTitle", "Install at least one AI provider"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentManagerPage.js","names":[],"sources":["../../../src/pages/ai/AgentManagerPage.tsx"],"sourcesContent":["/**\n * AgentManagerPage — top-level page for the multi-session Agent Manager.\n *\n * Reads URL params (:tab, :sessionId), resolves the active agent via\n * useCachedInitialData(), auto-opens a session tab if the URL has a\n * sessionId, and renders the three-pane layout.\n */\n\nimport { Suspense, useCallback, useEffect, useMemo } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { MessagesSquare } from 'lucide-react';\nimport { isNative, nativeNotify } from '../../utils/nativeBridge';\nimport { MotionPage } from '@burdenoff/fe-libs/shared/motion';\nimport {\n LoadingState,\n EmptyState,\n ErrorState,\n PluginGate,\n AgentSelector,\n RequireAgentReachable,\n} from '@/components/shared';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useCachedInitialData } from '@/hooks/useCachedInitialData';\nimport { useActiveAgentProfile } from '@/hooks/useActiveAgentProfile';\nimport { usePluginAvailability } from '@/hooks/usePluginAvailability';\nimport { useVibeControlsStore } from '@/store/vibeControlsStore';\nimport { useAgentManagerStore } from '@/store/agentManagerStore';\nimport { useAgentManagerKeyboard } from '@/hooks/useAgentManagerKeyboard';\nimport { terminateSession, bulkDeleteSessions } from '@/services/aiApi';\nimport { AgentManagerLayout } from '@/components/agent-manager/AgentManagerLayout';\nimport { AgentManagerSidebar } from '@/components/agent-manager/AgentManagerSidebar';\nimport { AgentManagerCenter } from '@/components/agent-manager/AgentManagerCenter';\nimport { AgentManagerDetailPanel } from '@/components/agent-manager/AgentManagerDetailPanel';\nimport { BridleConfigPanel } from '@/components/agent-manager/BridleConfigPanel';\nimport { ClaudeCredentialsCard } from '@/components/ai/ClaudeCredentialsCard';\nimport { AIModeToggle } from '@/components/ai/AIModeToggle';\nimport { AiSectionTabs } from '@/components/ai/AiSectionTabs';\nimport { AI_CORE_PACKAGE, AI_PROVIDER_PACKAGES } from '@/constants/pluginCatalog';\n\ninterface AgentManagerParams {\n tab?: string;\n sessionId?: string;\n}\n\nexport function AgentManagerPage() {\n const { tab: tabParam, sessionId: sessionIdParam } = useParams<\n AgentManagerParams & Record<string, string | undefined>\n >();\n const tr = useTr();\n const handleNavigate = useVibeNavigate();\n\n const { agents, loading: agentsLoading, error: agentsError } = useCachedInitialData();\n const selectedAgentId = useVibeControlsStore((s) => s.activeAgentId);\n\n // Prefer the user-selected agent from the store; fall back to the first\n // healthy one so the page works on first visit before the selector commits.\n const activeAgent = useMemo(() => {\n if (selectedAgentId) {\n const match = agents.find((a) => a.id === selectedAgentId);\n if (match) return match;\n }\n return agents.find((a) => a.isActive && a.tunnelUrl && a.agentApiKey) ?? null;\n }, [agents, selectedAgentId]);\n\n const agentId = activeAgent?.id ?? '';\n // AgentRef for canonical aiApi calls — agent → profile → plugins/data.\n const { active: activeProfile } = useActiveAgentProfile(activeAgent?.id ?? null);\n const agentRef = useMemo(\n () => ({ id: agentId, profile: activeProfile }),\n [agentId, activeProfile]\n );\n const openSession = useAgentManagerStore((s) => s.openSession);\n const activeTabSessionId = useAgentManagerStore((s) => s.activeTabSessionId);\n\n // Pre-fetch plugin availability at the page level so the detection phase\n // overlaps with the agents query's resolution. This collapses the two\n // sequential loading states (\"Loading agents...\" → \"Checking plugin\n // availability...\") into one unified wait, eliminating the flicker the\n // user saw between them.\n const detectionPackages = useMemo(() => [AI_CORE_PACKAGE, ...AI_PROVIDER_PACKAGES], []);\n const { initialLoading: pluginsInitialLoading } = usePluginAvailability(\n detectionPackages,\n agentId || null,\n activeProfile\n );\n\n // Auto-open session from URL param\n useEffect(() => {\n if (sessionIdParam && agentId) {\n openSession(sessionIdParam, `Session ${sessionIdParam.slice(0, 8)}`);\n }\n }, [sessionIdParam, agentId, openSession]);\n\n const handleDeleteSession = useCallback(\n async (sessionId: string) => {\n if (!agentId) return;\n try {\n await terminateSession(agentRef, sessionId);\n if (isNative()) void nativeNotify('success');\n } catch {\n if (isNative()) void nativeNotify('error');\n }\n },\n [agentRef]\n );\n\n const handleDeleteSelected = useCallback(\n async (sessionIds: string[]) => {\n if (!agentId) return;\n try {\n await bulkDeleteSessions(agentRef, sessionIds);\n if (isNative()) void nativeNotify('success');\n } catch {\n if (isNative()) void nativeNotify('error');\n }\n },\n [agentRef]\n );\n\n // Activate keyboard shortcuts (Ctrl+Shift+N, Ctrl+K, Ctrl+F, Escape)\n useAgentManagerKeyboard();\n\n // Single unified wait: show one LoadingState while either the agents\n // query or the plugin-availability probe is still in flight. Prevents\n // the two-step \"Loading agents...\" → \"Checking plugin availability...\"\n // cascade. `agentId && pluginsInitialLoading` also catches the case\n // where agents resolved but the plugin probe hasn't fired/settled yet.\n if (agentsLoading || (agentId && pluginsInitialLoading)) {\n return (\n <MotionPage className=\"flex items-center justify-center h-full bg-bg-surface\">\n <LoadingState\n message={tr(\n 'vibecontrols.pages.ai.detectingAgent',\n 'Detecting agent and plugin availability…'\n )}\n />\n </MotionPage>\n );\n }\n\n if (agentsError) {\n return (\n <MotionPage className=\"flex items-center justify-center h-full bg-bg-surface\">\n <ErrorState title=\"Failed to load agents\" message={agentsError.message} />\n </MotionPage>\n );\n }\n\n if (agents.length === 0) {\n return (\n <MotionPage className=\"flex items-center justify-center h-full bg-bg-surface p-8\">\n <EmptyState\n icon={<MessagesSquare className=\"w-8 h-8 text-text-secondary\" />}\n title={tr('vibecontrols.pages.ai.noActiveAgentAvailable', 'No agents available')}\n description={tr(\n 'vibecontrols.pages.ai.agentManagerRequiresAgent',\n 'The Agent Manager needs at least one vibecontrols agent. Add one or start an existing one.'\n )}\n action={\n <button\n onClick={() => handleNavigate('/agents')}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors text-sm\"\n >\n {tr('vibecontrols.pages.ai.goToAgents', 'Go to Agents')}\n </button>\n }\n />\n </MotionPage>\n );\n }\n\n if (tabParam === 'config') {\n return (\n <MotionPage className=\"flex flex-col h-[calc(100vh-6.5rem)] bg-bg-surface overflow-hidden\">\n <div className=\"flex items-center justify-between gap-3 border-b border-border-default px-4 sm:px-6 py-3\">\n <div>\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">\n {tr('vibecontrols.pages.ai.contextLabel', 'Active context')}\n </p>\n <h2 className=\"text-sm font-semibold text-text-primary mt-0.5\">\n {tr('vibecontrols.pages.ai.configHeading', 'AI configuration')}\n </h2>\n </div>\n <div className=\"flex items-center gap-3\">\n <AIModeToggle aiHref=\"/ai\" activeMode=\"ai\" />\n <AgentSelector\n label={tr('vibecontrols.pages.ai.agentSelectorLabel', 'Agent')}\n compact\n />\n </div>\n </div>\n\n <div className=\"flex-1 overflow-auto p-4 sm:p-6 space-y-6\">\n <RequireAgentReachable agentId={agentId || null}>\n <ClaudeCredentialsCard agent={agentRef} />\n <BridleConfigPanel agent={agentRef} />\n </RequireAgentReachable>\n </div>\n </MotionPage>\n );\n }\n\n return (\n <MotionPage className=\"flex flex-col h-[calc(100vh-6.5rem)] bg-bg-surface overflow-hidden\">\n <div className=\"flex items-center justify-between gap-3 border-b border-border-default px-4 sm:px-6 py-3\">\n <div>\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">\n {tr('vibecontrols.pages.ai.contextLabel', 'Active context')}\n </p>\n <h2 className=\"text-sm font-semibold text-text-primary mt-0.5\">\n {tr('vibecontrols.pages.ai.contextHeading', 'AI workbench')}\n </h2>\n </div>\n <div className=\"flex items-center gap-3\">\n {/* Plan toggle navigates to the canonical /ai-tools/plan\n workspace; the AI side stays on this AgentManagerPage. */}\n <AIModeToggle aiHref=\"/ai\" activeMode=\"ai\" />\n <AgentSelector label={tr('vibecontrols.pages.ai.agentSelectorLabel', 'Agent')} compact />\n </div>\n </div>\n\n <AiSectionTabs active=\"workbench\" />\n\n <div className=\"flex-1 min-h-0 overflow-auto p-4 sm:p-6 lg:p-0\">\n <RequireAgentReachable agentId={agentId || null}>\n <PluginGate\n agentId={agentId || null}\n requirements={[\n {\n packages: [AI_CORE_PACKAGE],\n mode: 'all',\n eyebrow: tr('vibecontrols.pages.ai.pluginRequiredEyebrow', 'AI plugin required'),\n title: tr('vibecontrols.pages.ai.coreTitle', 'Install the AI orchestrator'),\n description: tr(\n 'vibecontrols.pages.ai.coreDescription',\n 'The AI page routes prompts and sessions through the AI orchestrator plugin on your agent. Install it to continue.'\n ),\n },\n {\n packages: AI_PROVIDER_PACKAGES,\n mode: 'any',\n eyebrow: tr('vibecontrols.pages.ai.providerEyebrow', 'AI provider required'),\n title: tr(\n 'vibecontrols.pages.ai.providerTitle',\n 'Install at least one AI provider'\n ),\n description: tr(\n 'vibecontrols.pages.ai.providerDescription',\n 'Pick the AI harness you want to use. You can install more providers later from the Plugins tab on your agent.'\n ),\n },\n ]}\n >\n <Suspense\n fallback={\n <div className=\"flex items-center justify-center h-full\">\n <LoadingState message=\"Loading...\" />\n </div>\n }\n >\n <AgentManagerLayout\n sidebar={\n <AgentManagerSidebar\n agent={agentRef}\n onDeleteSession={handleDeleteSession}\n onDeleteSelected={handleDeleteSelected}\n />\n }\n detailPanel={\n activeTabSessionId ? (\n <AgentManagerDetailPanel sessionId={activeTabSessionId} agent={agentRef} />\n ) : undefined\n }\n >\n <AgentManagerCenter agent={agentRef} />\n </AgentManagerLayout>\n </Suspense>\n </PluginGate>\n </RequireAgentReachable>\n </div>\n </MotionPage>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AgentManagerPage.js","names":[],"sources":["../../../src/pages/ai/AgentManagerPage.tsx"],"sourcesContent":["/**\n * AgentManagerPage — top-level page for the multi-session Agent Manager.\n *\n * Reads URL params (:tab, :sessionId), resolves the active agent via\n * useCachedInitialData(), auto-opens a session tab if the URL has a\n * sessionId, and renders the three-pane layout.\n */\n\nimport { Suspense, useCallback, useEffect, useMemo } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { MessagesSquare } from 'lucide-react';\nimport { isNative, nativeNotify } from '../../utils/nativeBridge';\nimport { MotionPage } from '@burdenoff/fe-libs/shared/motion';\nimport {\n LoadingState,\n EmptyState,\n ErrorState,\n PluginGate,\n AgentSelector,\n RequireAgentReachable,\n} from '@/components/shared';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useCachedInitialData } from '@/hooks/useCachedInitialData';\nimport { useActiveAgentProfile } from '@/hooks/useActiveAgentProfile';\nimport { usePluginAvailability } from '@/hooks/usePluginAvailability';\nimport { useVibeControlsStore } from '@/store/vibeControlsStore';\nimport { useAgentManagerStore } from '@/store/agentManagerStore';\nimport { useAgentManagerKeyboard } from '@/hooks/useAgentManagerKeyboard';\nimport { terminateSession, bulkDeleteSessions } from '@/services/aiApi';\nimport { AgentManagerLayout } from '@/components/agent-manager/AgentManagerLayout';\nimport { AgentManagerSidebar } from '@/components/agent-manager/AgentManagerSidebar';\nimport { AgentManagerCenter } from '@/components/agent-manager/AgentManagerCenter';\nimport { AgentManagerDetailPanel } from '@/components/agent-manager/AgentManagerDetailPanel';\nimport { BridleConfigPanel } from '@/components/agent-manager/BridleConfigPanel';\nimport { ClaudeCredentialsCard } from '@/components/ai/ClaudeCredentialsCard';\nimport { AIModeToggle } from '@/components/ai/AIModeToggle';\nimport { AiSectionTabs } from '@/components/ai/AiSectionTabs';\nimport { AI_CORE_PACKAGE, AI_PROVIDER_PACKAGES } from '@/constants/pluginCatalog';\n\ninterface AgentManagerParams {\n tab?: string;\n sessionId?: string;\n}\n\nexport function AgentManagerPage() {\n const { tab: tabParam, sessionId: sessionIdParam } = useParams<\n AgentManagerParams & Record<string, string | undefined>\n >();\n const tr = useTr();\n const handleNavigate = useVibeNavigate();\n\n const { agents, loading: agentsLoading, error: agentsError } = useCachedInitialData();\n const selectedAgentId = useVibeControlsStore((s) => s.activeAgentId);\n\n // Prefer the user-selected agent from the store; fall back to the first\n // healthy one so the page works on first visit before the selector commits.\n const activeAgent = useMemo(() => {\n if (selectedAgentId) {\n const match = agents.find((a) => a.id === selectedAgentId);\n if (match) return match;\n }\n return agents.find((a) => a.isActive && a.tunnelUrl && a.agentApiKey) ?? null;\n }, [agents, selectedAgentId]);\n\n const agentId = activeAgent?.id ?? '';\n // AgentRef for canonical aiApi calls — agent → profile → plugins/data.\n const { active: activeProfile } = useActiveAgentProfile(activeAgent?.id ?? null);\n const agentRef = useMemo(\n () => ({ id: agentId, profile: activeProfile }),\n [agentId, activeProfile]\n );\n const openSession = useAgentManagerStore((s) => s.openSession);\n const activeTabSessionId = useAgentManagerStore((s) => s.activeTabSessionId);\n\n // Pre-fetch plugin availability at the page level so the detection phase\n // overlaps with the agents query's resolution. This collapses the two\n // sequential loading states (\"Loading agents...\" → \"Checking plugin\n // availability...\") into one unified wait, eliminating the flicker the\n // user saw between them.\n const detectionPackages = useMemo(() => [AI_CORE_PACKAGE, ...AI_PROVIDER_PACKAGES], []);\n // Plugins are agent-wide (BOFF-2612). `activeProfile` is still resolved\n // above for non-plugin concerns (aiApi agentRef).\n const { initialLoading: pluginsInitialLoading } = usePluginAvailability(\n detectionPackages,\n agentId || null\n );\n\n // Auto-open session from URL param\n useEffect(() => {\n if (sessionIdParam && agentId) {\n openSession(sessionIdParam, `Session ${sessionIdParam.slice(0, 8)}`);\n }\n }, [sessionIdParam, agentId, openSession]);\n\n const handleDeleteSession = useCallback(\n async (sessionId: string) => {\n if (!agentId) return;\n try {\n await terminateSession(agentRef, sessionId);\n if (isNative()) void nativeNotify('success');\n } catch {\n if (isNative()) void nativeNotify('error');\n }\n },\n [agentRef]\n );\n\n const handleDeleteSelected = useCallback(\n async (sessionIds: string[]) => {\n if (!agentId) return;\n try {\n await bulkDeleteSessions(agentRef, sessionIds);\n if (isNative()) void nativeNotify('success');\n } catch {\n if (isNative()) void nativeNotify('error');\n }\n },\n [agentRef]\n );\n\n // Activate keyboard shortcuts (Ctrl+Shift+N, Ctrl+K, Ctrl+F, Escape)\n useAgentManagerKeyboard();\n\n // Single unified wait: show one LoadingState while either the agents\n // query or the plugin-availability probe is still in flight. Prevents\n // the two-step \"Loading agents...\" → \"Checking plugin availability...\"\n // cascade. `agentId && pluginsInitialLoading` also catches the case\n // where agents resolved but the plugin probe hasn't fired/settled yet.\n if (agentsLoading || (agentId && pluginsInitialLoading)) {\n return (\n <MotionPage className=\"flex items-center justify-center h-full bg-bg-surface\">\n <LoadingState\n message={tr(\n 'vibecontrols.pages.ai.detectingAgent',\n 'Detecting agent and plugin availability…'\n )}\n />\n </MotionPage>\n );\n }\n\n if (agentsError) {\n return (\n <MotionPage className=\"flex items-center justify-center h-full bg-bg-surface\">\n <ErrorState title=\"Failed to load agents\" message={agentsError.message} />\n </MotionPage>\n );\n }\n\n if (agents.length === 0) {\n return (\n <MotionPage className=\"flex items-center justify-center h-full bg-bg-surface p-8\">\n <EmptyState\n icon={<MessagesSquare className=\"w-8 h-8 text-text-secondary\" />}\n title={tr('vibecontrols.pages.ai.noActiveAgentAvailable', 'No agents available')}\n description={tr(\n 'vibecontrols.pages.ai.agentManagerRequiresAgent',\n 'The Agent Manager needs at least one vibecontrols agent. Add one or start an existing one.'\n )}\n action={\n <button\n onClick={() => handleNavigate('/agents')}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors text-sm\"\n >\n {tr('vibecontrols.pages.ai.goToAgents', 'Go to Agents')}\n </button>\n }\n />\n </MotionPage>\n );\n }\n\n if (tabParam === 'config') {\n return (\n <MotionPage className=\"flex flex-col h-[calc(100vh-6.5rem)] bg-bg-surface overflow-hidden\">\n <div className=\"flex items-center justify-between gap-3 border-b border-border-default px-4 sm:px-6 py-3\">\n <div>\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">\n {tr('vibecontrols.pages.ai.contextLabel', 'Active context')}\n </p>\n <h2 className=\"text-sm font-semibold text-text-primary mt-0.5\">\n {tr('vibecontrols.pages.ai.configHeading', 'AI configuration')}\n </h2>\n </div>\n <div className=\"flex items-center gap-3\">\n <AIModeToggle aiHref=\"/ai\" activeMode=\"ai\" />\n <AgentSelector\n label={tr('vibecontrols.pages.ai.agentSelectorLabel', 'Agent')}\n compact\n />\n </div>\n </div>\n\n <div className=\"flex-1 overflow-auto p-4 sm:p-6 space-y-6\">\n <RequireAgentReachable agentId={agentId || null}>\n <ClaudeCredentialsCard agent={agentRef} />\n <BridleConfigPanel agent={agentRef} />\n </RequireAgentReachable>\n </div>\n </MotionPage>\n );\n }\n\n return (\n <MotionPage className=\"flex flex-col h-[calc(100vh-6.5rem)] bg-bg-surface overflow-hidden\">\n <div className=\"flex items-center justify-between gap-3 border-b border-border-default px-4 sm:px-6 py-3\">\n <div>\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">\n {tr('vibecontrols.pages.ai.contextLabel', 'Active context')}\n </p>\n <h2 className=\"text-sm font-semibold text-text-primary mt-0.5\">\n {tr('vibecontrols.pages.ai.contextHeading', 'AI workbench')}\n </h2>\n </div>\n <div className=\"flex items-center gap-3\">\n {/* Plan toggle navigates to the canonical /ai-tools/plan\n workspace; the AI side stays on this AgentManagerPage. */}\n <AIModeToggle aiHref=\"/ai\" activeMode=\"ai\" />\n <AgentSelector label={tr('vibecontrols.pages.ai.agentSelectorLabel', 'Agent')} compact />\n </div>\n </div>\n\n <AiSectionTabs active=\"workbench\" />\n\n <div className=\"flex-1 min-h-0 overflow-auto p-4 sm:p-6 lg:p-0\">\n <RequireAgentReachable agentId={agentId || null}>\n <PluginGate\n agentId={agentId || null}\n requirements={[\n {\n packages: [AI_CORE_PACKAGE],\n mode: 'all',\n eyebrow: tr('vibecontrols.pages.ai.pluginRequiredEyebrow', 'AI plugin required'),\n title: tr('vibecontrols.pages.ai.coreTitle', 'Install the AI orchestrator'),\n description: tr(\n 'vibecontrols.pages.ai.coreDescription',\n 'The AI page routes prompts and sessions through the AI orchestrator plugin on your agent. Install it to continue.'\n ),\n },\n {\n packages: AI_PROVIDER_PACKAGES,\n mode: 'any',\n eyebrow: tr('vibecontrols.pages.ai.providerEyebrow', 'AI provider required'),\n title: tr(\n 'vibecontrols.pages.ai.providerTitle',\n 'Install at least one AI provider'\n ),\n description: tr(\n 'vibecontrols.pages.ai.providerDescription',\n 'Pick the AI harness you want to use. You can install more providers later from the Plugins tab on your agent.'\n ),\n },\n ]}\n >\n <Suspense\n fallback={\n <div className=\"flex items-center justify-center h-full\">\n <LoadingState message=\"Loading...\" />\n </div>\n }\n >\n <AgentManagerLayout\n sidebar={\n <AgentManagerSidebar\n agent={agentRef}\n onDeleteSession={handleDeleteSession}\n onDeleteSelected={handleDeleteSelected}\n />\n }\n detailPanel={\n activeTabSessionId ? (\n <AgentManagerDetailPanel sessionId={activeTabSessionId} agent={agentRef} />\n ) : undefined\n }\n >\n <AgentManagerCenter agent={agentRef} />\n </AgentManagerLayout>\n </Suspense>\n </PluginGate>\n </RequireAgentReachable>\n </div>\n </MotionPage>\n );\n}\n"],"mappings":"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"}
|