@burdenoff/microfe-vibecontrols 2026.613.1 → 2026.618.1
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/agents/AgentConnectionRecovery.js +100 -94
- package/dist/components/agents/AgentConnectionRecovery.js.map +1 -1
- package/dist/components/agents/AgentMaintenanceTab.js +177 -160
- package/dist/components/agents/AgentMaintenanceTab.js.map +1 -1
- package/dist/components/agents/OpenInBrowserEditorButton.js +102 -94
- package/dist/components/agents/OpenInBrowserEditorButton.js.map +1 -1
- package/dist/components/assistant/AssistantChatArea.js +1 -0
- package/dist/components/assistant/AssistantChatArea.js.map +1 -1
- package/dist/components/assistant/AssistantModeSelector.js +20 -19
- package/dist/components/assistant/AssistantModeSelector.js.map +1 -1
- package/dist/components/tunnels/TunnelCard.js +3 -3
- package/dist/components/tunnels/TunnelCard.js.map +1 -1
- package/dist/components/tunnels/TunnelPublicAccessPanel.js +36 -36
- package/dist/components/tunnels/TunnelPublicAccessPanel.js.map +1 -1
- package/dist/config/assistantUsecases.js +11 -0
- package/dist/config/assistantUsecases.js.map +1 -1
- package/dist/constants/permissions.js +38 -6
- package/dist/constants/permissions.js.map +1 -1
- package/dist/index.js +4 -3
- package/dist/pages/CatalogDetailPage.js +155 -155
- package/dist/pages/CatalogDetailPage.js.map +1 -1
- package/dist/pages/CatalogPage.js +110 -109
- package/dist/pages/CatalogPage.js.map +1 -1
- package/dist/pages/ComponentDetailPage.js +338 -338
- package/dist/pages/ComponentDetailPage.js.map +1 -1
- package/dist/pages/ComponentsPage.js +104 -103
- package/dist/pages/ComponentsPage.js.map +1 -1
- package/dist/pages/TargetDetailsPage.js +140 -132
- package/dist/pages/TargetDetailsPage.js.map +1 -1
- package/dist/pages/TemplateDetailPage.js +201 -199
- package/dist/pages/TemplateDetailPage.js.map +1 -1
- package/dist/pages/TemplatesPage.js +62 -61
- package/dist/pages/TemplatesPage.js.map +1 -1
- package/dist/pages/VibeDetailsPage.js +568 -555
- package/dist/pages/VibeDetailsPage.js.map +1 -1
- package/dist/pages/ai/AIBookmarksPage.js +104 -89
- package/dist/pages/ai/AIBookmarksPage.js.map +1 -1
- package/dist/pages/ai/AIPage.js +116 -107
- package/dist/pages/ai/AIPage.js.map +1 -1
- package/dist/pages/ai/AISessionDetailPage.js +46 -34
- package/dist/pages/ai/AISessionDetailPage.js.map +1 -1
- package/dist/pages/ai/AgentManagerPage.js +112 -100
- package/dist/pages/ai/AgentManagerPage.js.map +1 -1
- package/dist/pages/tunnels/TunnelDetailsPage.js +177 -153
- package/dist/pages/tunnels/TunnelDetailsPage.js.map +1 -1
- package/dist/pages/tunnels/TunnelsTab.js +119 -111
- package/dist/pages/tunnels/TunnelsTab.js.map +1 -1
- package/dist/pages/tunnels/tabs/TunnelDomainsTab.js +24 -24
- package/dist/pages/tunnels/tabs/TunnelDomainsTab.js.map +1 -1
- package/dist/pages/tunnels/tabs/TunnelOverviewTab.js +9 -8
- package/dist/pages/tunnels/tabs/TunnelOverviewTab.js.map +1 -1
- package/dist/pages/tunnels/tabs/TunnelSessionsTab.js +13 -13
- package/dist/pages/tunnels/tabs/TunnelSessionsTab.js.map +1 -1
- package/dist/pages/tunnels/tabs/TunnelSettingsTab.js +19 -15
- package/dist/pages/tunnels/tabs/TunnelSettingsTab.js.map +1 -1
- package/dist/services/assistantApi.js +9 -3
- package/dist/services/assistantApi.js.map +1 -1
- package/dist/services/createSandboxAssistantTransport.js +120 -0
- package/dist/services/createSandboxAssistantTransport.js.map +1 -0
- package/dist/store/assistantStore.js +1 -1
- package/dist/store/assistantStore.js.map +1 -1
- package/package.json +5 -1
|
@@ -6,74 +6,77 @@ import ee from "../../hooks/useCachedInitialData.js";
|
|
|
6
6
|
import { LoadingState as i } from "../../components/shared/LoadingState.js";
|
|
7
7
|
import { ErrorState as a } from "../../components/shared/ErrorState.js";
|
|
8
8
|
import { EmptyState as te } from "../../components/shared/EmptyState.js";
|
|
9
|
-
import { usePluginAvailability as
|
|
10
|
-
import { AI_CORE_PACKAGE as
|
|
11
|
-
import { PluginGate as
|
|
12
|
-
import { RequireAgentReachable as
|
|
13
|
-
import { useActiveAgentProfile as
|
|
14
|
-
import { AgentSelector as
|
|
9
|
+
import { usePluginAvailability as o } from "../../hooks/usePluginAvailability.js";
|
|
10
|
+
import { AI_CORE_PACKAGE as s, AI_PROVIDER_PACKAGES as c } from "../../constants/pluginCatalog.js";
|
|
11
|
+
import { PluginGate as l } from "../../components/shared/PluginGate.js";
|
|
12
|
+
import { RequireAgentReachable as u } from "../../components/shared/RequireAgentReachable.js";
|
|
13
|
+
import { useActiveAgentProfile as d } from "../../hooks/useActiveAgentProfile.js";
|
|
14
|
+
import { AgentSelector as f } from "../../components/shared/AgentSelector.js";
|
|
15
15
|
import "../../components/shared/index.js";
|
|
16
|
-
import { isNative as
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
16
|
+
import { isNative as p, nativeNotify as m } from "../../utils/nativeBridge.js";
|
|
17
|
+
import { VIBE_PERMISSIONS as ne } from "../../constants/permissions.js";
|
|
18
|
+
import { bulkDeleteSessions as re, terminateSession as ie } from "../../services/aiApi.js";
|
|
19
|
+
import { useAgentManagerStore as h } from "../../store/agentManagerStore.js";
|
|
20
|
+
import { AgentManagerLayout as ae } from "../../components/agent-manager/AgentManagerLayout.js";
|
|
21
|
+
import { AgentManagerSidebar as oe } from "../../components/agent-manager/AgentManagerSidebar.js";
|
|
22
|
+
import { BridleConfigPanel as se } from "../../components/agent-manager/BridleConfigPanel.js";
|
|
23
|
+
import { AgentManagerCenter as ce } from "../../components/agent-manager/AgentManagerCenter.js";
|
|
24
|
+
import { AgentManagerDetailPanel as g } from "../../components/agent-manager/AgentManagerDetailPanel.js";
|
|
25
|
+
import { AiSectionTabs as le } from "../../components/ai/AiSectionTabs.js";
|
|
26
|
+
import { ClaudeCredentialsCard as _ } from "../../components/ai/ClaudeCredentialsCard.js";
|
|
27
|
+
import { AIModeToggle as v } from "../../components/ai/AIModeToggle.js";
|
|
28
|
+
import { useAgentManagerKeyboard as y } from "../../hooks/useAgentManagerKeyboard.js";
|
|
29
|
+
import { Suspense as b, useCallback as x, useEffect as S, useMemo as C, useRef as w } from "react";
|
|
30
|
+
import { MessagesSquare as ue } from "lucide-react";
|
|
31
|
+
import { useParams as de, useSearchParams as fe } from "react-router-dom";
|
|
32
|
+
import { useApolloClient as pe } from "@apollo/client/react";
|
|
33
|
+
import { usePermissions as me } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
34
|
+
import { jsx as T, jsxs as E } from "react/jsx-runtime";
|
|
35
|
+
import { AccessDenied as D } from "@burdenoff/fe-libs/shared/components";
|
|
36
|
+
import { MotionPage as O } from "@burdenoff/fe-libs/shared/motion";
|
|
34
37
|
//#region src/pages/ai/AgentManagerPage.tsx
|
|
35
|
-
function
|
|
36
|
-
let { tab:
|
|
38
|
+
function k() {
|
|
39
|
+
let { tab: k, sessionId: A } = de(), j = t(), M = n(), { hasPermission: N, isLoading: P } = me(), F = N(ne.AGENT_READ), { agents: I, loading: L, error: R } = ee(), z = r((e) => e.activeAgentId), B = C(() => {
|
|
37
40
|
if (z) {
|
|
38
41
|
let e = I.find((e) => e.id === z);
|
|
39
42
|
if (e) return e;
|
|
40
43
|
}
|
|
41
44
|
return I.find((e) => e.isActive && e.tunnelUrl) ?? null;
|
|
42
|
-
}, [I, z]), V = B?.id ?? "", { active: H } =
|
|
45
|
+
}, [I, z]), V = B?.id ?? "", { active: H } = d(B?.id ?? null), U = C(() => ({
|
|
43
46
|
id: V,
|
|
44
47
|
profile: H
|
|
45
|
-
}), [V, H]), W =
|
|
46
|
-
|
|
48
|
+
}), [V, H]), W = h((e) => e.openSession), G = h((e) => e.closeTab), K = h((e) => e.clearSelection), q = h((e) => e.bumpSessionsRefresh), J = h((e) => e.activeTabSessionId), Y = h((e) => e.setActiveChatContext), [X] = fe();
|
|
49
|
+
S(() => {
|
|
47
50
|
let e = X.get("vibeId");
|
|
48
51
|
Y({
|
|
49
52
|
contextLevel: e ? "vibe" : "agent",
|
|
50
53
|
vibeId: e ?? null
|
|
51
54
|
});
|
|
52
55
|
}, [X, Y]);
|
|
53
|
-
let { initialLoading:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
let { initialLoading: he, refetch: Z } = o(C(() => [s, ...c], []), V || null), Q = pe(), $ = w(!1);
|
|
57
|
+
S(() => {
|
|
58
|
+
A && V && W(A, `Session ${A.slice(0, 8)}`);
|
|
56
59
|
}, [
|
|
57
|
-
|
|
60
|
+
A,
|
|
58
61
|
V,
|
|
59
62
|
W
|
|
60
63
|
]);
|
|
61
|
-
let
|
|
64
|
+
let ge = x(async (e) => {
|
|
62
65
|
if (V) try {
|
|
63
|
-
await
|
|
66
|
+
await ie(U, e), G(e), q(), p() && m("success");
|
|
64
67
|
} catch {
|
|
65
|
-
|
|
68
|
+
p() && m("error");
|
|
66
69
|
}
|
|
67
70
|
}, [
|
|
68
71
|
V,
|
|
69
72
|
U,
|
|
70
73
|
q,
|
|
71
74
|
G
|
|
72
|
-
]),
|
|
75
|
+
]), _e = x(async (e) => {
|
|
73
76
|
if (V) try {
|
|
74
|
-
await
|
|
77
|
+
await re(U, e), e.forEach((e) => G(e)), K(), q(), p() && m("success");
|
|
75
78
|
} catch {
|
|
76
|
-
|
|
79
|
+
p() && m("error");
|
|
77
80
|
}
|
|
78
81
|
}, [
|
|
79
82
|
V,
|
|
@@ -81,7 +84,7 @@ function M() {
|
|
|
81
84
|
q,
|
|
82
85
|
K,
|
|
83
86
|
G
|
|
84
|
-
]),
|
|
87
|
+
]), ve = x(async () => {
|
|
85
88
|
if ($.current || !V) return;
|
|
86
89
|
$.current = !0;
|
|
87
90
|
let t = () => {
|
|
@@ -90,7 +93,7 @@ function M() {
|
|
|
90
93
|
query: e,
|
|
91
94
|
variables: { agentId: V }
|
|
92
95
|
}), n = new Set((t?.agentPlugins?.installed ?? []).map((e) => e.packageName));
|
|
93
|
-
return
|
|
96
|
+
return c.some((e) => n.has(e));
|
|
94
97
|
} catch {
|
|
95
98
|
return !1;
|
|
96
99
|
}
|
|
@@ -105,7 +108,7 @@ function M() {
|
|
|
105
108
|
variables: { agentId: V },
|
|
106
109
|
fetchPolicy: "network-only"
|
|
107
110
|
}), n = t?.agentPlugins?.installed ?? [], r = new Set(n.map((e) => e.packageName));
|
|
108
|
-
if (
|
|
111
|
+
if (c.some((e) => r.has(e))) break;
|
|
109
112
|
} catch (e) {
|
|
110
113
|
console.warn("[ai] provider poll attempt failed", e);
|
|
111
114
|
}
|
|
@@ -119,123 +122,132 @@ function M() {
|
|
|
119
122
|
Q,
|
|
120
123
|
Z
|
|
121
124
|
]);
|
|
122
|
-
return
|
|
125
|
+
return y(), P ? /* @__PURE__ */ T(O, {
|
|
123
126
|
className: "flex items-center justify-center h-full bg-bg-surface",
|
|
124
|
-
children: /* @__PURE__ */
|
|
125
|
-
}) :
|
|
127
|
+
children: /* @__PURE__ */ T(i, { message: j("common.loadingPermissions", "Loading permissions…") })
|
|
128
|
+
}) : F ? L || V && he ? /* @__PURE__ */ T(O, {
|
|
126
129
|
className: "flex items-center justify-center h-full bg-bg-surface",
|
|
127
|
-
children: /* @__PURE__ */
|
|
130
|
+
children: /* @__PURE__ */ T(i, { message: j("vibecontrols.pages.ai.detectingAgent", "Detecting agent and plugin availability…") })
|
|
131
|
+
}) : R ? /* @__PURE__ */ T(O, {
|
|
132
|
+
className: "flex items-center justify-center h-full bg-bg-surface",
|
|
133
|
+
children: /* @__PURE__ */ T(a, {
|
|
128
134
|
title: "Failed to load agents",
|
|
129
135
|
message: R.message
|
|
130
136
|
})
|
|
131
|
-
}) : I.length === 0 ? /* @__PURE__ */
|
|
137
|
+
}) : I.length === 0 ? /* @__PURE__ */ T(O, {
|
|
132
138
|
className: "flex items-center justify-center h-full bg-bg-surface p-8",
|
|
133
|
-
children: /* @__PURE__ */
|
|
134
|
-
icon: /* @__PURE__ */
|
|
135
|
-
title:
|
|
136
|
-
description:
|
|
137
|
-
action: /* @__PURE__ */
|
|
139
|
+
children: /* @__PURE__ */ T(te, {
|
|
140
|
+
icon: /* @__PURE__ */ T(ue, { className: "size-8 text-text-secondary" }),
|
|
141
|
+
title: j("vibecontrols.pages.ai.noActiveAgentAvailable", "No agents available"),
|
|
142
|
+
description: j("vibecontrols.pages.ai.agentManagerRequiresAgent", "The Agent Manager needs at least one vibecontrols agent. Add one or start an existing one."),
|
|
143
|
+
action: /* @__PURE__ */ T("button", {
|
|
138
144
|
type: "button",
|
|
139
|
-
onClick: () =>
|
|
145
|
+
onClick: () => M("/agents"),
|
|
140
146
|
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",
|
|
141
|
-
children:
|
|
147
|
+
children: j("vibecontrols.pages.ai.goToAgents", "Go to Agents")
|
|
142
148
|
})
|
|
143
149
|
})
|
|
144
|
-
}) :
|
|
150
|
+
}) : k === "config" ? /* @__PURE__ */ E(O, {
|
|
145
151
|
className: "flex flex-col h-[calc(100vh-6.5rem)] bg-bg-surface overflow-hidden",
|
|
146
|
-
children: [/* @__PURE__ */
|
|
152
|
+
children: [/* @__PURE__ */ E("div", {
|
|
147
153
|
className: "flex items-center justify-between gap-3 border-b border-border-default px-4 sm:px-6 py-3",
|
|
148
|
-
children: [/* @__PURE__ */
|
|
154
|
+
children: [/* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T("p", {
|
|
149
155
|
className: "text-xs uppercase tracking-wide text-text-secondary",
|
|
150
|
-
children:
|
|
151
|
-
}), /* @__PURE__ */
|
|
156
|
+
children: j("vibecontrols.pages.ai.contextLabel", "Active context")
|
|
157
|
+
}), /* @__PURE__ */ T("h2", {
|
|
152
158
|
className: "text-sm font-semibold text-text-primary mt-0.5",
|
|
153
|
-
children:
|
|
154
|
-
})] }), /* @__PURE__ */
|
|
159
|
+
children: j("vibecontrols.pages.ai.configHeading", "AI configuration")
|
|
160
|
+
})] }), /* @__PURE__ */ E("div", {
|
|
155
161
|
className: "flex items-center gap-3",
|
|
156
|
-
children: [/* @__PURE__ */
|
|
162
|
+
children: [/* @__PURE__ */ T(v, {
|
|
157
163
|
aiHref: "/ai",
|
|
158
164
|
activeMode: "ai"
|
|
159
|
-
}), /* @__PURE__ */
|
|
160
|
-
label:
|
|
165
|
+
}), /* @__PURE__ */ T(f, {
|
|
166
|
+
label: j("vibecontrols.pages.ai.agentSelectorLabel", "Agent"),
|
|
161
167
|
compact: !0
|
|
162
168
|
})]
|
|
163
169
|
})]
|
|
164
|
-
}), /* @__PURE__ */
|
|
170
|
+
}), /* @__PURE__ */ T("div", {
|
|
165
171
|
className: "flex-1 overflow-auto p-4 sm:p-6 space-y-6",
|
|
166
|
-
children: /* @__PURE__ */
|
|
172
|
+
children: /* @__PURE__ */ E(u, {
|
|
167
173
|
agentId: V || null,
|
|
168
|
-
children: [/* @__PURE__ */
|
|
174
|
+
children: [/* @__PURE__ */ T(_, { agent: U }), /* @__PURE__ */ T(se, { agent: U })]
|
|
169
175
|
})
|
|
170
176
|
})]
|
|
171
|
-
}) : /* @__PURE__ */
|
|
177
|
+
}) : /* @__PURE__ */ E(O, {
|
|
172
178
|
className: "flex flex-col h-[calc(100vh-6.5rem)] bg-bg-surface overflow-hidden",
|
|
173
179
|
children: [
|
|
174
|
-
/* @__PURE__ */
|
|
180
|
+
/* @__PURE__ */ E("div", {
|
|
175
181
|
className: "flex items-center justify-between gap-3 border-b border-border-default px-4 sm:px-6 py-3",
|
|
176
|
-
children: [/* @__PURE__ */
|
|
182
|
+
children: [/* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T("p", {
|
|
177
183
|
className: "text-xs uppercase tracking-wide text-text-secondary",
|
|
178
|
-
children:
|
|
179
|
-
}), /* @__PURE__ */
|
|
184
|
+
children: j("vibecontrols.pages.ai.contextLabel", "Active context")
|
|
185
|
+
}), /* @__PURE__ */ T("h2", {
|
|
180
186
|
className: "text-sm font-semibold text-text-primary mt-0.5",
|
|
181
|
-
children:
|
|
182
|
-
})] }), /* @__PURE__ */
|
|
187
|
+
children: j("vibecontrols.pages.ai.contextHeading", "AI workbench")
|
|
188
|
+
})] }), /* @__PURE__ */ E("div", {
|
|
183
189
|
className: "flex items-center gap-3",
|
|
184
|
-
children: [/* @__PURE__ */
|
|
190
|
+
children: [/* @__PURE__ */ T(v, {
|
|
185
191
|
aiHref: "/ai",
|
|
186
192
|
activeMode: "ai"
|
|
187
|
-
}), /* @__PURE__ */
|
|
188
|
-
label:
|
|
193
|
+
}), /* @__PURE__ */ T(f, {
|
|
194
|
+
label: j("vibecontrols.pages.ai.agentSelectorLabel", "Agent"),
|
|
189
195
|
compact: !0
|
|
190
196
|
})]
|
|
191
197
|
})]
|
|
192
198
|
}),
|
|
193
|
-
/* @__PURE__ */
|
|
194
|
-
/* @__PURE__ */
|
|
199
|
+
/* @__PURE__ */ T(le, { active: "workbench" }),
|
|
200
|
+
/* @__PURE__ */ T("div", {
|
|
195
201
|
className: "flex-1 min-h-0 overflow-auto p-4 sm:p-6 lg:p-0",
|
|
196
|
-
children: /* @__PURE__ */
|
|
202
|
+
children: /* @__PURE__ */ T(u, {
|
|
197
203
|
agentId: V || null,
|
|
198
|
-
children: /* @__PURE__ */
|
|
204
|
+
children: /* @__PURE__ */ T(l, {
|
|
199
205
|
agentId: V || null,
|
|
200
|
-
onInstalled: () => void
|
|
206
|
+
onInstalled: () => void ve(),
|
|
201
207
|
requirements: [{
|
|
202
|
-
packages: [
|
|
208
|
+
packages: [s],
|
|
203
209
|
mode: "all",
|
|
204
|
-
eyebrow:
|
|
205
|
-
title:
|
|
206
|
-
description:
|
|
210
|
+
eyebrow: j("vibecontrols.pages.ai.pluginRequiredEyebrow", "AI plugin required"),
|
|
211
|
+
title: j("vibecontrols.pages.ai.coreTitle", "Install the AI orchestrator"),
|
|
212
|
+
description: j("vibecontrols.pages.ai.coreDescription", "The AI page routes prompts and sessions through the AI orchestrator plugin on your agent. Install it to continue.")
|
|
207
213
|
}, {
|
|
208
|
-
packages:
|
|
214
|
+
packages: c,
|
|
209
215
|
mode: "any",
|
|
210
|
-
eyebrow:
|
|
211
|
-
title:
|
|
212
|
-
description:
|
|
216
|
+
eyebrow: j("vibecontrols.pages.ai.providerEyebrow", "AI provider required"),
|
|
217
|
+
title: j("vibecontrols.pages.ai.providerTitle", "Install at least one AI provider"),
|
|
218
|
+
description: j("vibecontrols.pages.ai.providerDescription", "Pick the AI harness you want to use. You can install more providers later from the Plugins tab on your agent.")
|
|
213
219
|
}],
|
|
214
|
-
children: /* @__PURE__ */
|
|
215
|
-
fallback: /* @__PURE__ */
|
|
220
|
+
children: /* @__PURE__ */ T(b, {
|
|
221
|
+
fallback: /* @__PURE__ */ T("div", {
|
|
216
222
|
className: "flex items-center justify-center h-full",
|
|
217
|
-
children: /* @__PURE__ */
|
|
223
|
+
children: /* @__PURE__ */ T(i, { message: "Loading..." })
|
|
218
224
|
}),
|
|
219
|
-
children: /* @__PURE__ */
|
|
220
|
-
sidebar: /* @__PURE__ */
|
|
225
|
+
children: /* @__PURE__ */ T(ae, {
|
|
226
|
+
sidebar: /* @__PURE__ */ T(oe, {
|
|
221
227
|
agent: U,
|
|
222
|
-
onDeleteSession:
|
|
223
|
-
onDeleteSelected:
|
|
228
|
+
onDeleteSession: ge,
|
|
229
|
+
onDeleteSelected: _e
|
|
224
230
|
}),
|
|
225
|
-
detailPanel: J ? /* @__PURE__ */
|
|
231
|
+
detailPanel: J ? /* @__PURE__ */ T(g, {
|
|
226
232
|
sessionId: J,
|
|
227
233
|
agent: U
|
|
228
234
|
}) : void 0,
|
|
229
|
-
children: /* @__PURE__ */
|
|
235
|
+
children: /* @__PURE__ */ T(ce, { agent: U })
|
|
230
236
|
})
|
|
231
237
|
})
|
|
232
238
|
})
|
|
233
239
|
})
|
|
234
240
|
})
|
|
235
241
|
]
|
|
242
|
+
}) : /* @__PURE__ */ T(O, {
|
|
243
|
+
className: "flex items-center justify-center h-full bg-bg-surface",
|
|
244
|
+
children: /* @__PURE__ */ T(D, {
|
|
245
|
+
title: j("vibecontrols.pages.ai.denied.title", "Access Denied"),
|
|
246
|
+
description: j("vibecontrols.pages.ai.denied.description", "You do not have permission to view AI features.")
|
|
247
|
+
})
|
|
236
248
|
});
|
|
237
249
|
}
|
|
238
250
|
//#endregion
|
|
239
|
-
export {
|
|
251
|
+
export { k as AgentManagerPage };
|
|
240
252
|
|
|
241
253
|
//# sourceMappingURL=AgentManagerPage.js.map
|
|
@@ -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, useRef } from 'react';\nimport { useParams, useSearchParams } from 'react-router-dom';\nimport { useApolloClient } from '@apollo/client/react';\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 { AgentPluginsDocument, type AgentPluginsQuery } from '@/generated/wspace-operations';\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) ?? 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 closeTab = useAgentManagerStore((s) => s.closeTab);\n const clearSelection = useAgentManagerStore((s) => s.clearSelection);\n const bumpSessionsRefresh = useAgentManagerStore((s) => s.bumpSessionsRefresh);\n const activeTabSessionId = useAgentManagerStore((s) => s.activeTabSessionId);\n const setActiveChatContext = useAgentManagerStore((s) => s.setActiveChatContext);\n\n // Launch \"in context\": the /ai route accepts ?vibeId=…&contextLevel=vibe\n // (from a vibe's \"Open AI chat\") or ?contextLevel=agent. This sets the active\n // bucket so new sessions are tagged + the sidebar list is filtered to it.\n const [searchParams] = useSearchParams();\n useEffect(() => {\n const vibeIdParam = searchParams.get('vibeId');\n setActiveChatContext({\n contextLevel: vibeIdParam ? 'vibe' : 'agent',\n vibeId: vibeIdParam ?? null,\n });\n }, [searchParams, setActiveChatContext]);\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, refetch: refetchPlugins } = usePluginAvailability(\n detectionPackages,\n agentId || null\n );\n\n const apollo = useApolloClient();\n // Guards onInstalled against re-entrancy if the gate fires the transition\n // more than once while a poll is still in flight.\n const completingInstallRef = useRef(false);\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 closeTab(sessionId);\n bumpSessionsRefresh();\n if (isNative()) void nativeNotify('success');\n } catch {\n if (isNative()) void nativeNotify('error');\n }\n },\n [agentId, agentRef, bumpSessionsRefresh, closeTab]\n );\n\n const handleDeleteSelected = useCallback(\n async (sessionIds: string[]) => {\n if (!agentId) return;\n try {\n await bulkDeleteSessions(agentRef, sessionIds);\n sessionIds.forEach((sessionId) => closeTab(sessionId));\n clearSelection();\n bumpSessionsRefresh();\n if (isNative()) void nativeNotify('success');\n } catch {\n if (isNative()) void nativeNotify('error');\n }\n },\n [agentId, agentRef, bumpSessionsRefresh, clearSelection, closeTab]\n );\n\n // Smart completion after the first provider install resolves the gate.\n // Replaces the old window.location.reload() (BOFF-2671): instead of nuking\n // the SPA, we make sure every consumer of `agentPlugins` (gate,\n // AgentManagerCenter, harness/provider selectors) sees the freshly-installed\n // provider. The agent-side npm install is async (~10–30s) and the gate only\n // fires this once it has already detected the provider, but the surrounding\n // surfaces read the Apollo cache directly — so we refetch, then poll\n // network-only until at least one provider package is present in the cached\n // list, capping the wait so we never spin forever.\n const handleProviderInstalled = useCallback(async () => {\n if (completingInstallRef.current || !agentId) return;\n completingInstallRef.current = true;\n // Reads the authoritative provider-present state from the Apollo cache,\n // which refetchPlugins() / the network-only poll both write through. Avoids\n // a stale React-state closure (installedPlugins captured at callback build).\n const providerPresentInCache = (): boolean => {\n try {\n const cached = apollo.readQuery<AgentPluginsQuery>({\n query: AgentPluginsDocument,\n variables: { agentId },\n });\n const names = new Set((cached?.agentPlugins?.installed ?? []).map((p) => p.packageName));\n return AI_PROVIDER_PACKAGES.some((pkg) => names.has(pkg));\n } catch {\n return false;\n }\n };\n try {\n // Fast path: the optimistic + subscription-driven cache may already show a\n // provider. Refetch once to write the authoritative list into the cache.\n await refetchPlugins();\n if (providerPresentInCache()) return;\n\n // Slow path: poll the agent directly until the provider lands or we give\n // up (15 attempts × ~2s ≈ 30s, matching the worst-case npm install).\n for (let attempt = 0; attempt < 15; attempt += 1) {\n await new Promise((resolve) => setTimeout(resolve, 2000));\n try {\n const { data } = await apollo.query<AgentPluginsQuery>({\n query: AgentPluginsDocument,\n variables: { agentId },\n fetchPolicy: 'network-only',\n });\n const installedList = data?.agentPlugins?.installed ?? [];\n const names = new Set(installedList.map((p) => p.packageName));\n if (AI_PROVIDER_PACKAGES.some((pkg) => names.has(pkg))) break;\n } catch (err) {\n // Transient agent-not-ready errors are expected mid-install; keep\n // polling. Surface only for debuggability.\n console.warn('[ai] provider poll attempt failed', err);\n }\n }\n // Final refetch so the hook's installed map + cache reflect the result.\n await refetchPlugins();\n } finally {\n completingInstallRef.current = false;\n }\n }, [agentId, apollo, refetchPlugins]);\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=\"size-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 type=\"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 // Smart completion instead of window.location.reload() (BOFF-2671).\n // PluginGate fires this on the unsatisfied → satisfied transition,\n // i.e. once the first provider is detected. We then refetch +\n // network-only-poll the agent's plugin list so the gate's children\n // (AgentManagerCenter and every provider/harness selector) read the\n // freshly-installed provider from the Apollo cache — no full reload,\n // no empty chat surface waiting on a manual refresh.\n onInstalled={() => void handleProviderInstalled()}\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, useRef } from 'react';\nimport { useParams, useSearchParams } from 'react-router-dom';\nimport { useApolloClient } from '@apollo/client/react';\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 { AccessDenied } from '@burdenoff/fe-libs/shared/components';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '@/constants/permissions';\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 { AgentPluginsDocument, type AgentPluginsQuery } from '@/generated/wspace-operations';\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 // Agent-centric page — gate on `agent:read` (defense-in-depth).\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canReadAgents = hasPermission(VIBE_PERMISSIONS.AGENT_READ);\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) ?? 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 closeTab = useAgentManagerStore((s) => s.closeTab);\n const clearSelection = useAgentManagerStore((s) => s.clearSelection);\n const bumpSessionsRefresh = useAgentManagerStore((s) => s.bumpSessionsRefresh);\n const activeTabSessionId = useAgentManagerStore((s) => s.activeTabSessionId);\n const setActiveChatContext = useAgentManagerStore((s) => s.setActiveChatContext);\n\n // Launch \"in context\": the /ai route accepts ?vibeId=…&contextLevel=vibe\n // (from a vibe's \"Open AI chat\") or ?contextLevel=agent. This sets the active\n // bucket so new sessions are tagged + the sidebar list is filtered to it.\n const [searchParams] = useSearchParams();\n useEffect(() => {\n const vibeIdParam = searchParams.get('vibeId');\n setActiveChatContext({\n contextLevel: vibeIdParam ? 'vibe' : 'agent',\n vibeId: vibeIdParam ?? null,\n });\n }, [searchParams, setActiveChatContext]);\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, refetch: refetchPlugins } = usePluginAvailability(\n detectionPackages,\n agentId || null\n );\n\n const apollo = useApolloClient();\n // Guards onInstalled against re-entrancy if the gate fires the transition\n // more than once while a poll is still in flight.\n const completingInstallRef = useRef(false);\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 closeTab(sessionId);\n bumpSessionsRefresh();\n if (isNative()) void nativeNotify('success');\n } catch {\n if (isNative()) void nativeNotify('error');\n }\n },\n [agentId, agentRef, bumpSessionsRefresh, closeTab]\n );\n\n const handleDeleteSelected = useCallback(\n async (sessionIds: string[]) => {\n if (!agentId) return;\n try {\n await bulkDeleteSessions(agentRef, sessionIds);\n sessionIds.forEach((sessionId) => closeTab(sessionId));\n clearSelection();\n bumpSessionsRefresh();\n if (isNative()) void nativeNotify('success');\n } catch {\n if (isNative()) void nativeNotify('error');\n }\n },\n [agentId, agentRef, bumpSessionsRefresh, clearSelection, closeTab]\n );\n\n // Smart completion after the first provider install resolves the gate.\n // Replaces the old window.location.reload() (BOFF-2671): instead of nuking\n // the SPA, we make sure every consumer of `agentPlugins` (gate,\n // AgentManagerCenter, harness/provider selectors) sees the freshly-installed\n // provider. The agent-side npm install is async (~10–30s) and the gate only\n // fires this once it has already detected the provider, but the surrounding\n // surfaces read the Apollo cache directly — so we refetch, then poll\n // network-only until at least one provider package is present in the cached\n // list, capping the wait so we never spin forever.\n const handleProviderInstalled = useCallback(async () => {\n if (completingInstallRef.current || !agentId) return;\n completingInstallRef.current = true;\n // Reads the authoritative provider-present state from the Apollo cache,\n // which refetchPlugins() / the network-only poll both write through. Avoids\n // a stale React-state closure (installedPlugins captured at callback build).\n const providerPresentInCache = (): boolean => {\n try {\n const cached = apollo.readQuery<AgentPluginsQuery>({\n query: AgentPluginsDocument,\n variables: { agentId },\n });\n const names = new Set((cached?.agentPlugins?.installed ?? []).map((p) => p.packageName));\n return AI_PROVIDER_PACKAGES.some((pkg) => names.has(pkg));\n } catch {\n return false;\n }\n };\n try {\n // Fast path: the optimistic + subscription-driven cache may already show a\n // provider. Refetch once to write the authoritative list into the cache.\n await refetchPlugins();\n if (providerPresentInCache()) return;\n\n // Slow path: poll the agent directly until the provider lands or we give\n // up (15 attempts × ~2s ≈ 30s, matching the worst-case npm install).\n for (let attempt = 0; attempt < 15; attempt += 1) {\n await new Promise((resolve) => setTimeout(resolve, 2000));\n try {\n const { data } = await apollo.query<AgentPluginsQuery>({\n query: AgentPluginsDocument,\n variables: { agentId },\n fetchPolicy: 'network-only',\n });\n const installedList = data?.agentPlugins?.installed ?? [];\n const names = new Set(installedList.map((p) => p.packageName));\n if (AI_PROVIDER_PACKAGES.some((pkg) => names.has(pkg))) break;\n } catch (err) {\n // Transient agent-not-ready errors are expected mid-install; keep\n // polling. Surface only for debuggability.\n console.warn('[ai] provider poll attempt failed', err);\n }\n }\n // Final refetch so the hook's installed map + cache reflect the result.\n await refetchPlugins();\n } finally {\n completingInstallRef.current = false;\n }\n }, [agentId, apollo, refetchPlugins]);\n\n // Activate keyboard shortcuts (Ctrl+Shift+N, Ctrl+K, Ctrl+F, Escape)\n useAgentManagerKeyboard();\n\n if (permissionsLoading) {\n return (\n <MotionPage className=\"flex items-center justify-center h-full bg-bg-surface\">\n <LoadingState message={tr('common.loadingPermissions', 'Loading permissions…')} />\n </MotionPage>\n );\n }\n\n if (!canReadAgents) {\n return (\n <MotionPage className=\"flex items-center justify-center h-full bg-bg-surface\">\n <AccessDenied\n title={tr('vibecontrols.pages.ai.denied.title', 'Access Denied')}\n description={tr(\n 'vibecontrols.pages.ai.denied.description',\n 'You do not have permission to view AI features.'\n )}\n />\n </MotionPage>\n );\n }\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=\"size-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 type=\"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 // Smart completion instead of window.location.reload() (BOFF-2671).\n // PluginGate fires this on the unsatisfied → satisfied transition,\n // i.e. once the first provider is detected. We then refetch +\n // network-only-poll the agent's plugin list so the gate's children\n // (AgentManagerCenter and every provider/harness selector) read the\n // freshly-installed provider from the Apollo cache — no full reload,\n // no empty chat surface waiting on a manual refresh.\n onInstalled={() => void handleProviderInstalled()}\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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"}
|