@burdenoff/microfe-vibecontrols 2026.531.1 → 2026.531.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.
@@ -235,7 +235,17 @@ function Et() {
235
235
  let { t: ne } = ze(), { id: m } = vt(), { basePath: ht } = de(), Et = ht || "", C = fe(), { hasPermission: Dt, isLoading: Ot, permissions: kt } = yt(), w = u((e, t, n) => {
236
236
  let r = ne(e, n), i = r === e ? t : r;
237
237
  return n ? Object.entries(n).reduce((e, [t, n]) => e.replace(`{{${t}}}`, String(n)), i) : i;
238
- }, [ne]), [At] = ae({ refetchQueries: ["GetAgent"] }), [jt] = i(), [Mt] = n({ refetchQueries: ["GetAgent"] }), [Nt] = re(), [Pt] = ie(), [T, Ft] = p(null), [It, Lt] = p(null), Rt = pe((e) => e.setActiveAgentId);
238
+ }, [ne]), [At] = ae({ refetchQueries: ["GetAgent"] }), [jt] = i({
239
+ refetchQueries: ["ListAgents", "VibeControlsInitialData"],
240
+ awaitRefetchQueries: !0,
241
+ update(e, t, { variables: n }) {
242
+ let r = n?.id;
243
+ r && (e.evict({ id: e.identify({
244
+ __typename: "VibecontrolsAgent",
245
+ id: r
246
+ }) }), e.gc());
247
+ }
248
+ }), [Mt] = n({ refetchQueries: ["GetAgent"] }), [Nt] = re(), [Pt] = ie(), [T, Ft] = p(null), [It, Lt] = p(null), Rt = pe((e) => e.setActiveAgentId);
239
249
  d(() => {
240
250
  m && Rt(m);
241
251
  }, [m, Rt]);
@@ -1 +1 @@
1
- {"version":3,"file":"AgentDetailsPage.js","names":[],"sources":["../../src/pages/AgentDetailsPage.tsx"],"sourcesContent":["import { useState, useRef, useEffect, useCallback, useMemo } from 'react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { PermissionButton } from '@burdenoff/fe-libs/shared/components';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { isNative, nativeCopyText, nativeToast } from '../utils/nativeBridge';\nimport { EntityTagPicker } from '@/components/shared/EntityTagPicker';\nimport { PageSkeleton } from '@/components/shared/PageSkeleton';\nimport { useParams } from 'react-router-dom';\nimport { MotionPage } from '@burdenoff/fe-libs/shared/motion';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport { useVibeControlsStore } from '@/store/vibeControlsStore';\nimport { AgentBackupTab } from '@/components/agents/backup/AgentBackupTab';\nimport { ConnectionLogPanel } from '@/components/agents/ConnectionLogPanel';\nimport { AliasManager } from '@/components/aliases/AliasManager';\nimport {\n ArrowLeft,\n Database,\n Server,\n Play,\n Square,\n Settings,\n Trash2,\n Terminal,\n Zap,\n Cpu,\n HardDrive,\n Clock,\n CheckCircle2,\n RefreshCw,\n Eye,\n EyeOff,\n Key,\n Copy,\n Check,\n Info,\n Puzzle,\n Download,\n X,\n Loader2,\n Shield,\n Link2,\n Unlink,\n Search,\n Monitor,\n FileText,\n Tag,\n ScrollText,\n Command,\n Users,\n Plus,\n Edit3,\n Bot,\n} from 'lucide-react';\nimport {\n PageHeader,\n Card,\n StatusBadge,\n EmptyState,\n ErrorState,\n QuotaExhaustedDialog,\n} from '@/components/shared';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n PluginUIPanel,\n type UIPluginOption,\n OpenInBrowserEditorButton,\n AgentStatusBadge,\n} from '@/components/agents';\nimport { deriveAgentStatus, type AgentHealthProbe } from '@/utils/agentStatus';\nimport { LogViewer } from '@/components/logs/LogViewer';\nimport { useActiveAgentProfile } from '@/hooks/useActiveAgentProfile';\nimport { ProfilesPanel } from '@/components/agent-manager';\nimport { NotesTabPanel } from '@/components/notes';\nimport { useVibeControls, useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useQueryBackedTab } from '@/hooks/useQueryBackedTab';\nimport {\n isQuotaExhaustedError,\n markQuotaHandledLocally,\n getQuotaDialogContent,\n} from '@/utils/quotaUtils';\nimport { useFeatureFlagDetails } from '@burdenoff/fe-libs/shared/feature-flags';\nimport {\n PluginIframe,\n type DiscoveredContribution,\n type MountTunnel,\n usePluginContributions,\n} from '@burdenoff/fe-libs/shared/plugins';\nimport { mintScopedIframeToken } from '@/services/iframeToken';\nimport { AddTabDialog } from '@/components/plugins/AddTabDialog';\nimport { PluginIframeMount } from '@/components/plugins/PluginIframeMount';\nimport {\n useGetAgentQuery,\n useUpdateAgentMutation,\n useDeleteAgentMutation,\n useCheckSessionHealthMutation,\n useAgentPluginsLazyQuery,\n useInstallAgentPluginMutation,\n useRemoveAgentPluginMutation,\n useSetupAgentGatewayAuthMutation,\n usePushAgentGatewayAuthMutation,\n useVibecontrolsAgentHealthProbesQuery,\n useVibecontrolsAgentHealthProbeStreamSubscription,\n useStartVibecontrolsAgentMutation,\n useStopVibecontrolsAgentMutation,\n useCreateSessionMutation,\n useAgentSecretRevealLazyQuery,\n} from '@/generated/wspace-operations';\n\n// ─── Gateway Auth Card ─────────────────────────────────────────────────────\n// Shows whether the agent has a linked OAuth2 app for gateway communication.\n// Allows creating a new app via auth-svc and pushing credentials to the agent.\n\ninterface GatewayAuthAgent {\n id: string;\n name: string;\n appId?: string | null;\n appClientId?: string | null;\n tunnelUrl?: string | null;\n metadata?: Record<string, unknown> | null;\n}\n\nfunction GatewayAuthCard({ agent, onUpdate }: { agent: GatewayAuthAgent; onUpdate: () => void }) {\n const { t } = useI18n();\n const [updateAgent] = useUpdateAgentMutation();\n const [setupGatewayAuth] = useSetupAgentGatewayAuthMutation();\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [showSecret, setShowSecret] = useState(false);\n const [oneTimeSecret, setOneTimeSecret] = useState<string | null>(null);\n const [secretCopied, setSecretCopied] = useState(false);\n const [clientIdCopied, setClientIdCopied] = useState(false);\n const [unlinking, setUnlinking] = useState(false);\n\n const hasApp = Boolean(agent.appId && agent.appClientId);\n\n const tr = (key: string, fallback: string, params?: Record<string, string | number>): string => {\n const translated = t(key, params);\n const template = translated === key ? fallback : translated;\n\n if (!params) return template;\n\n return Object.entries(params).reduce(\n (acc, [paramKey, paramValue]) => acc.replace(`{{${paramKey}}}`, String(paramValue)),\n template\n );\n };\n const devportalAppId = (agent.metadata as Record<string, unknown> | null)\n ?.devportalApplicationId as string | undefined;\n\n // Single backend-orchestrated mutation: creates auth-svc app + devportal app + pushes creds to agent\n const handleSetupGatewayAuth = async () => {\n setLoading(true);\n setError(null);\n\n try {\n const { data } = await setupGatewayAuth({\n variables: {\n input: {\n agentId: agent.id,\n },\n },\n });\n\n const result = data?.setupAgentGatewayAuth;\n if (!result) {\n throw new Error(\n tr(\n 'agentDetails.gatewayAuthNoResultError',\n 'No result returned from setupAgentGatewayAuth'\n )\n );\n }\n\n // Show the one-time secret\n setOneTimeSecret(result.clientSecret);\n\n // Show warning if push to agent failed (creds still created)\n if (result.error) {\n setError(result.error);\n }\n\n onUpdate();\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : tr('agentDetails.failedSetupGatewayAuth', 'Failed to set up gateway auth')\n );\n } finally {\n setLoading(false);\n }\n };\n\n // Unlink the app (remove appId/appClientId from agent record)\n const handleUnlink = async () => {\n if (\n !window.confirm(\n tr(\n 'agentDetails.confirmUnlinkOauthApp',\n 'Remove the linked OAuth app from this agent? The app will still exist in auth-svc.'\n )\n )\n )\n return;\n setUnlinking(true);\n setError(null);\n try {\n await updateAgent({\n variables: {\n id: agent.id,\n input: { appId: null, appClientId: null },\n },\n });\n setOneTimeSecret(null);\n onUpdate();\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : tr('agentDetails.failedUnlinkApp', 'Failed to unlink app')\n );\n } finally {\n setUnlinking(false);\n }\n };\n\n const handleCopyClientId = async () => {\n if (!agent.appClientId) return;\n try {\n await nativeCopyText(agent.appClientId);\n if (isNative()) void nativeToast('Copied');\n setClientIdCopied(true);\n setTimeout(() => setClientIdCopied(false), 2000);\n } catch {\n // Non-HTTPS fallback\n }\n };\n\n const handleCopySecret = async () => {\n if (!oneTimeSecret) return;\n try {\n await nativeCopyText(oneTimeSecret);\n if (isNative()) void nativeToast('Secret copied');\n setSecretCopied(true);\n setTimeout(() => setSecretCopied(false), 2000);\n } catch {\n // Non-HTTPS fallback\n }\n };\n\n return (\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Shield className=\"size-5\" />\n {tr('agentDetails.gatewayAuthTitle', 'Gateway Auth (OAuth2)')}\n </h3>\n </div>\n <div className=\"p-4 space-y-3\">\n {error && (\n <div className=\"flex items-center gap-2 p-3 bg-status-error-bg text-status-error-text rounded-md text-sm\">\n <X className=\"size-4 flex-shrink-0\" />\n <span className=\"flex-1\">{error}</span>\n <button\n type=\"button\"\n onClick={() => setError(null)}\n className=\"flex-shrink-0 p-0.5 hover:bg-status-error-text/10 rounded\"\n >\n <X className=\"size-3.5\" />\n </button>\n </div>\n )}\n\n {hasApp ? (\n <>\n {/* Linked app info */}\n <div className=\"flex items-start gap-3\">\n <div className=\"size-8 rounded-lg bg-status-success-bg flex items-center justify-center flex-shrink-0 mt-0.5\">\n <Link2 className=\"size-4 text-status-success-text\" />\n </div>\n <div className=\"flex-1 min-w-0 space-y-2\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tr('agentDetails.linkedToOauthApp', 'Linked to OAuth App')}\n </p>\n <p className=\"text-xs text-text-muted\">\n {tr(\n 'agentDetails.gatewayAuthLinkedDescription',\n 'This agent can authenticate with the API gateway using Client Credentials.'\n )}\n </p>\n </div>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3\">\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">\n {tr('agentDetails.clientId', 'Client ID')}\n </p>\n <div className=\"flex items-center gap-2\">\n <code className=\"text-xs font-mono text-text-primary bg-bg-sunken px-2 py-1 rounded truncate block flex-1\">\n {agent.appClientId}\n </code>\n <button\n type=\"button\"\n onClick={handleCopyClientId}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n title={tr('agentDetails.copyClientId', 'Copy Client ID')}\n >\n {clientIdCopied ? (\n <Check className=\"size-3.5 text-status-success-text\" />\n ) : (\n <Copy className=\"size-3.5 text-text-secondary\" />\n )}\n </button>\n </div>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">\n {tr('agentDetails.appId', 'App ID')}\n </p>\n <code className=\"text-xs font-mono text-text-muted bg-bg-sunken px-2 py-1 rounded truncate block\">\n {agent.appId}\n </code>\n </div>\n </div>\n </div>\n </div>\n\n {/* One-time secret display */}\n {oneTimeSecret && (\n <div className=\"p-3 bg-status-warning-bg/20 border border-status-warning-text/20 rounded-lg space-y-2\">\n <p className=\"text-sm font-medium text-status-warning-text\">\n {tr('agentDetails.clientSecretOneTimeTitle', 'Client Secret (one-time display)')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'agentDetails.clientSecretOneTimeDescription',\n \"This secret has been automatically sent to the agent. Save it now if you need it — it won't be shown again.\"\n )}\n </p>\n <div className=\"flex items-center gap-2\">\n <code className=\"text-xs font-mono text-text-primary bg-bg-sunken px-2 py-1 rounded flex-1 truncate\">\n {showSecret ? oneTimeSecret : '\\u2022'.repeat(32)}\n </code>\n <button\n type=\"button\"\n onClick={() => setShowSecret(!showSecret)}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n >\n {showSecret ? (\n <EyeOff className=\"size-3.5 text-text-secondary\" />\n ) : (\n <Eye className=\"size-3.5 text-text-secondary\" />\n )}\n </button>\n <button\n type=\"button\"\n onClick={handleCopySecret}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n >\n {secretCopied ? (\n <Check className=\"size-3.5 text-status-success-text\" />\n ) : (\n <Copy className=\"size-3.5 text-text-secondary\" />\n )}\n </button>\n </div>\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex items-center gap-2\">\n {devportalAppId && (\n <a\n href={`/devportal/apps/${devportalAppId}`}\n className=\"flex items-center gap-2 px-3 py-1.5 text-xs text-action-primary-bg bg-action-primary-bg/10 hover:bg-action-primary-bg/20 rounded-md transition-colors\"\n >\n <Monitor className=\"size-3\" />\n {tr('agentDetails.viewInDeveloperPortal', 'View in Developer Portal')}\n </a>\n )}\n {/* Re-push: rotates the OAuth secret on auth-svc + POSTs the\n fresh creds to the agent's /api/agent/gateway-auth so a\n degraded agent stuck in awaiting-config (DB never opened,\n no session provider registered) can recover without\n unlinking + re-creating the app. Backend already handles\n the rotate path inside setupGatewayAuth when an app is\n already linked. */}\n <button\n type=\"button\"\n onClick={handleSetupGatewayAuth}\n disabled={loading}\n className=\"flex items-center gap-2 px-3 py-1.5 text-xs text-action-primary-bg bg-action-primary-bg/10 hover:bg-action-primary-bg/20 rounded-md transition-colors disabled:opacity-50\"\n title={tr(\n 'agentDetails.repushCredentialsTitle',\n 'Rotate the OAuth secret and push it to the agent. Use this if the agent shows degraded with \"boot state awaiting-config\".'\n )}\n >\n {loading ? (\n <Loader2 className=\"size-3 animate-spin\" />\n ) : (\n <RefreshCw className=\"size-3\" />\n )}\n {tr('agentDetails.repushCredentials', 'Re-push credentials')}\n </button>\n <button\n type=\"button\"\n onClick={handleUnlink}\n disabled={unlinking}\n className=\"flex items-center gap-2 px-3 py-1.5 text-xs text-status-error-text hover:bg-status-error-bg rounded-md transition-colors disabled:opacity-50\"\n >\n {unlinking ? (\n <Loader2 className=\"size-3 animate-spin\" />\n ) : (\n <Unlink className=\"size-3\" />\n )}\n {tr('agentDetails.unlinkApp', 'Unlink App')}\n </button>\n </div>\n </>\n ) : (\n <>\n {/* No app linked */}\n <div className=\"flex items-start gap-3\">\n <div className=\"size-8 rounded-lg bg-bg-sunken flex items-center justify-center flex-shrink-0 mt-0.5\">\n <Shield className=\"size-4 text-text-muted\" />\n </div>\n <div className=\"flex-1\">\n <p className=\"text-sm font-medium text-text-primary\">\n {tr('agentDetails.noOauthAppLinked', 'No OAuth App Linked')}\n </p>\n <p className=\"text-xs text-text-muted mt-0.5\">\n {tr(\n 'agentDetails.gatewayAuthSetupDescription',\n 'Set up gateway auth to allow this agent to communicate with the API gateways using OAuth2 Client Credentials. This creates an OAuth app, registers it in the Developer Portal, and pushes the credentials to the agent.'\n )}\n </p>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={handleSetupGatewayAuth}\n disabled={loading}\n className=\"flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {loading ? (\n <>\n <Loader2 className=\"size-4 animate-spin\" />\n {tr('agentDetails.settingUp', 'Setting up...')}\n </>\n ) : (\n <>\n <Link2 className=\"size-4\" />\n {tr('agentDetails.setupGatewayAuth', 'Setup Gateway Auth')}\n </>\n )}\n </button>\n </>\n )}\n </div>\n </Card>\n );\n}\n\n// `AgentPluginIframeBody` was the page-local helper that minted a\n// token + rendered an iframe without refresh / error handling. The\n// consolidated logic now lives in `@/components/plugins/PluginIframeMount`.\n\n/**\n * Agent details page - shows comprehensive information about a single agent\n */\nexport function AgentDetailsPage() {\n const { t } = useI18n();\n const { id } = useParams<{ id: string }>();\n const { basePath: basePathProp } = useVibeControls();\n const basePath = basePathProp || '';\n const navigate = useVibeNavigate();\n const { hasPermission, isLoading: permissionsLoading, permissions } = usePermissions();\n\n const tr = useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>): string => {\n const translated = t(key, params);\n const template = translated === key ? fallback : translated;\n\n if (!params) return template;\n\n return Object.entries(params).reduce(\n (acc, [paramKey, paramValue]) => acc.replace(`{{${paramKey}}}`, String(paramValue)),\n template\n );\n },\n [t]\n );\n\n const [updateAgent] = useUpdateAgentMutation({ refetchQueries: ['GetAgent'] });\n const [deleteAgent] = useDeleteAgentMutation();\n const [checkSessionHealth] = useCheckSessionHealthMutation({ refetchQueries: ['GetAgent'] });\n const [startVibecontrolsAgent] = useStartVibecontrolsAgentMutation();\n const [stopVibecontrolsAgent] = useStopVibecontrolsAgentMutation();\n // Per-action in-flight state so the Start/Stop button can show a spinner +\n // disable while the lifecycle call is running (it can take a few seconds to\n // reach the agent over its tunnel).\n const [lifecycleAction, setLifecycleAction] = useState<'start' | 'stop' | null>(null);\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n\n // ── Sync active context ────────────────────────────────────────────────\n const setActiveAgentId = useVibeControlsStore((s) => s.setActiveAgentId);\n useEffect(() => {\n if (id) setActiveAgentId(id);\n }, [id, setActiveAgentId]);\n\n // ── Tab Navigation ───────────────────────────────────────────────────\n type AgentTab =\n | 'overview'\n | 'profiles'\n | 'security'\n | 'plugins'\n | 'sessions'\n | 'logs'\n | 'connection'\n | 'vibes'\n | 'notes'\n | 'aliases'\n | 'backup';\n const agentTabIds: readonly AgentTab[] = [\n 'overview',\n 'profiles',\n 'security',\n 'plugins',\n 'sessions',\n 'logs',\n 'connection',\n 'vibes',\n 'notes',\n 'aliases',\n 'backup',\n ];\n // Active-tab declaration is deferred to after `iframeContributions`\n // (further down in this component) so the valid id set can include\n // both the static `agentTabIds` AND discovered plugin ids — see\n // the same pattern in VibeDetailsPage.\n\n // Configuration modal state\n const [showConfigModal, setShowConfigModal] = useState(false);\n const [configError, setConfigError] = useState<string | null>(null);\n const [configLoading, setConfigLoading] = useState(false);\n const [successMessage, setSuccessMessage] = useState<string | null>(null);\n const [showAiContextInfo, setShowAiContextInfo] = useState(false);\n\n // Inline rename state — lets operators rename the agent from the page\n // header without opening the full Configure modal. Click the pencil →\n // input swaps in. Cancel reverts to the stored name; Save fires the\n // existing UpdateAgent mutation and refetches GetAgent so every reader\n // on the page reflects the new name in the same render.\n const [renaming, setRenaming] = useState(false);\n const [renameValue, setRenameValue] = useState('');\n const [renameSaving, setRenameSaving] = useState(false);\n const [renameError, setRenameError] = useState<string | null>(null);\n const renameInputRef = useRef<HTMLInputElement>(null);\n\n // Config form refs\n const agentNameRef = useRef<HTMLInputElement>(null);\n const agentTunnelUrlRef = useRef<HTMLInputElement>(null);\n const agentAiContextRef = useRef<HTMLTextAreaElement>(null);\n const agentMetadataRef = useRef<HTMLTextAreaElement>(null);\n const [showApiKey, setShowApiKey] = useState(false);\n const [apiKeyCopied, setApiKeyCopied] = useState(false);\n // F4 Wave B: the long-lived agent secret is no longer prefetched with\n // every GetAgent. Reveal lazily on operator click; svc-side RBAC +\n // audit gates the read.\n const [revealedApiKey, setRevealedApiKey] = useState<string | null>(null);\n const [revealLoading, setRevealLoading] = useState(false);\n const [revealError, setRevealError] = useState<string | null>(null);\n const [fetchAgentSecret] = useAgentSecretRevealLazyQuery({ fetchPolicy: 'network-only' });\n\n // Create Session modal state\n const [showSessionModal, setShowSessionModal] = useState(false);\n const [sessionCreateError, setSessionCreateError] = useState<string | null>(null);\n const [sessionCreateLoading, setSessionCreateLoading] = useState(false);\n const sessionNameRef = useRef<HTMLInputElement>(null);\n const sessionTypeRef = useRef<HTMLSelectElement>(null);\n const sessionCommandRef = useRef<HTMLInputElement>(null);\n const sessionWorkDirRef = useRef<HTMLInputElement>(null);\n const [createSession] = useCreateSessionMutation({\n refetchQueries: ['GetAgent', 'ListSessions'],\n });\n\n // Dismiss the Create Session modal on Escape, matching the a11y contract\n // for role=\"dialog\" / aria-modal=\"true\".\n useEffect(() => {\n if (!showSessionModal) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && !sessionCreateLoading) setShowSessionModal(false);\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [showSessionModal, sessionCreateLoading]);\n\n // Move keyboard focus to the session name input when the modal opens —\n // satisfies the aria-modal contract so users tabbing don't land on\n // elements behind the overlay. rAF defers past the mount paint.\n useEffect(() => {\n if (!showSessionModal) return;\n const id = requestAnimationFrame(() => sessionNameRef.current?.focus());\n return () => cancelAnimationFrame(id);\n }, [showSessionModal]);\n\n // Fetch agent by ID from GraphQL API\n const { data, loading, error, refetch } = useGetAgentQuery({\n variables: { id: id || '' },\n skip: !id,\n fetchPolicy: 'cache-and-network',\n });\n\n // Get agent from response\n const agent = data?.vibecontrolsAgent;\n\n // Live deep-health probe — same source the agent cards use, so the detail\n // page's status badge matches the list. Without this the badge derived from\n // the sticky `isActive` flag, showing \"Active\" for an agent the card (and\n // reality) reports DEGRADED/stopped. Workspace-scoped query primes the cache;\n // the subscription pushes sub-second updates.\n const probeQuery = useVibecontrolsAgentHealthProbesQuery({\n fetchPolicy: 'cache-and-network',\n nextFetchPolicy: 'cache-first',\n notifyOnNetworkStatusChange: true,\n skip: !id,\n pollInterval: 30_000,\n });\n const { data: probeStreamData } = useVibecontrolsAgentHealthProbeStreamSubscription({\n skip: !id,\n });\n const probesLoading = probeQuery.data === undefined && probeStreamData === undefined;\n const probesById = useMemo(() => {\n const m = new Map<string, AgentHealthProbe>();\n const probes =\n probeStreamData?.vibecontrolsAgentHealthProbeStream ??\n probeQuery.data?.vibecontrolsAgentHealthProbes ??\n [];\n for (const p of probes) {\n m.set(p.agentId, { agentId: p.agentId, healthy: p.healthy, errorMessage: p.errorMessage });\n }\n return m;\n }, [probeQuery.data, probeStreamData]);\n\n // Single source of truth for the agent's displayed status — live /health/ready\n // probe + lifecycleState, NOT the sticky isActive flag. Drives both the status\n // badge and the Start/Stop toggle so they always agree with the agent cards.\n const derivedStatus = useMemo(\n () =>\n agent\n ? deriveAgentStatus(\n {\n id: agent.id,\n isActive: agent.isActive,\n metadata: agent.metadata as Record<string, unknown> | null,\n },\n probesById,\n { probesLoading }\n )\n : 'REGISTERING',\n [agent, probesById, probesLoading]\n );\n\n // Only offer Start when the agent is known NOT to be running (STOPPED or\n // OFFLINE). For ACTIVE — and also DEGRADED / REGISTERING, where the process\n // can still be live during probe warm-up or transport errors — show Stop, so\n // an operator can always stop a live-but-unhealthy agent instead of firing a\n // start that fails as \"already running\".\n const showStartButton = derivedStatus === 'STOPPED' || derivedStatus === 'OFFLINE';\n\n // Phase 5B — resolve the active profile name for this agent. Used to\n // build canonical `/api/profiles/<name>/<rest>` paths in child tabs\n // (LogViewer, OpenInBrowserEditorButton, AgentBackupTab).\n const { active: activeProfile } = useActiveAgentProfile(agent?.id ?? null);\n\n // Plugins are agent-wide (BOFF-2612): the npm package install and the\n // \"available\" catalog are already shared across all profiles on the\n // agent; only plugin DATA (notes/sessions/etc.) stays per-profile.\n // No per-profile gate on Install/Remove anymore.\n\n // ── iframe-mount discovery (PR-8) ────────────────────────────────────\n // Gated by `vibes.tabs.iframe-host` (same flag the VibeDetailsPage\n // uses — one switch for both surfaces). When on, the host queries the\n // agent's tunnel for contributions targeting the `agent.detailTab`\n // mount point and renders them as additional tabs.\n const iframeHostFlag = useFeatureFlagDetails('vibes.tabs.iframe-host');\n const enableIframeHost = iframeHostFlag?.value === true;\n\n const iframePluginTunnels = useMemo<MountTunnel[]>(() => {\n if (!enableIframeHost || !agent?.tunnelUrl) return [];\n const agentIdForToken = agent.id;\n const profile = activeProfile ?? 'default';\n return [\n {\n tunnelUrl: agent.tunnelUrl,\n profile,\n label: agent.name ?? agent.id,\n mintIframeToken: async ({ pathPrefixes }) => {\n return mintScopedIframeToken(agentIdForToken, profile, pathPrefixes);\n },\n },\n ];\n }, [enableIframeHost, agent?.id, agent?.tunnelUrl, agent?.name, activeProfile]);\n\n const iframeContributions = usePluginContributions(iframePluginTunnels, {\n mountPoint: 'agent.detailTab',\n enabled: enableIframeHost && iframePluginTunnels.length > 0,\n });\n\n // Active-tab id set = static agentTabIds ∪ discovered plugin ids.\n // See VibeDetailsPage for the rationale.\n const validAgentTabIds = useMemo<readonly string[]>(() => {\n const fromContribs = iframeContributions.data\n .filter((c) => c.contribution.mountPoint === 'agent.detailTab')\n .map((c) => c.contribution.id);\n return [...(agentTabIds as readonly string[]), ...fromContribs];\n }, [iframeContributions.data, agentTabIds]);\n const [activeTab, setActiveTab] = useQueryBackedTab<string>(validAgentTabIds, 'overview');\n\n const [addTabOpen, setAddTabOpen] = useState(false);\n\n // On mount, run a health check to sync stale session states with agent reality\n const healthCheckRanRef = useRef(false);\n useEffect(() => {\n if (agent && !healthCheckRanRef.current) {\n healthCheckRanRef.current = true;\n checkSessionHealth().catch(() => {\n // Best-effort — don't block the page if health check fails\n });\n }\n }, [agent, checkSessionHealth]);\n\n // Auto-recovery for agents stuck in `awaiting-config`.\n //\n // Symptom (why this exists): a freshly-booted agent loads its plugin\n // catalog but defers `onServerStart` — and therefore session-provider\n // registration — until the dashboard POSTs OAuth credentials to\n // /api/agent/gateway-auth. If the initial push failed (network blip,\n // auth-svc transient, page closed mid-flight) the agent stays stuck\n // and the badge reads \"Degraded — no session provider registered\".\n //\n // Fix: when the page loads and finds (a) an agent linked to an OAuth\n // app already, (b) reachable via tunnelUrl + agentApiKey, and (c)\n // unhealthy, fire `pushAgentGatewayAuth` once. The mutation re-pushes\n // the existing OAuth credentials to the agent — idempotent and safe;\n // the agent will finalize and register providers on receipt.\n // Self-heals the page without a manual \"Re-push credentials\" click.\n const [pushGatewayAuth] = usePushAgentGatewayAuthMutation();\n const autoRecoveryRanRef = useRef(false);\n useEffect(() => {\n if (!agent || autoRecoveryRanRef.current) return;\n const hasApp = Boolean(agent.appId && agent.appClientId);\n const reachable = Boolean(agent.tunnelUrl);\n if (!hasApp || !reachable) return;\n autoRecoveryRanRef.current = true;\n pushGatewayAuth({ variables: { input: { agentId: agent.id } } })\n .then(() => {\n // Re-fetch so badge + reason update once the agent finalizes.\n refetch().catch(() => {\n /* badge will refresh on next heartbeat */\n });\n })\n .catch(() => {\n // Silent — manual \"Re-push credentials\" button remains available.\n });\n }, [agent, pushGatewayAuth, refetch]);\n\n // ── Plugin Management (via backend GraphQL proxy) ──────────────────\n interface InstalledPlugin {\n packageName: string;\n pluginName: string;\n version: string;\n installedAt: string;\n loaded: boolean;\n description?: string;\n tags?: string[];\n isCore: boolean;\n cliCommand?: string;\n apiPrefix?: string;\n hasUI: boolean;\n hasCliSetup: boolean;\n hasServerStart: boolean;\n hasServerStop: boolean;\n hasServerReady: boolean;\n hasProviders: boolean;\n }\n interface AvailablePlugin {\n packageName: string;\n name: string;\n description: string;\n version: string;\n tags: string[];\n installed: boolean;\n }\n\n const [installedPlugins, setInstalledPlugins] = useState<InstalledPlugin[]>([]);\n const [availablePlugins, setAvailablePlugins] = useState<AvailablePlugin[]>([]);\n const [pluginsLoading, setPluginsLoading] = useState(true);\n const [pluginActionLoading, setPluginActionLoading] = useState<string | null>(null);\n const [pluginError, setPluginError] = useState<string | null>(null);\n const [showQuotaExhausted, setShowQuotaExhausted] = useState(false);\n // Which quota the open dialog is reporting on. The plugin-install flow\n // opens the same dialog and was here first, so it's the default.\n const [quotaKind, setQuotaKind] = useState<'plugin' | 'session'>('plugin');\n // Tracks the last (agent, profile) pair we fetched plugins for, so a\n // profile switch re-fetches the profile-scoped plugin list instead of\n // showing the previous profile's plugins.\n const pluginsFetchedRef = useRef<string | null>(null);\n\n // ── Plugin Sub-Tabs & Search ──────────────────────────────────────\n type PluginSubTab = 'installed' | 'available' | 'store' | 'ui-plugins';\n const [pluginSubTab, setPluginSubTab] = useState<PluginSubTab>('installed');\n const [pluginSearchQuery, setPluginSearchQuery] = useState('');\n\n // ── Store Plugins ─────────────────────────────────────────────────\n type StoreEntitlement = {\n id: string;\n productId: string;\n licenseKey: string | null;\n product: {\n id: string;\n name: string;\n slug: string;\n icon: string | null;\n description: string | null;\n manifest: Record<string, unknown> | null;\n } | null;\n };\n const [storePlugins, setStorePlugins] = useState<StoreEntitlement[]>([]);\n const [storePluginsLoading, setStorePluginsLoading] = useState(false);\n const [storePluginsError, setStorePluginsError] = useState<string | null>(null);\n const [storeInstallingId, setStoreInstallingId] = useState<string | null>(null);\n\n // Backend-proxied plugin operations\n const [fetchAgentPlugins] = useAgentPluginsLazyQuery();\n const [installPluginMutation] = useInstallAgentPluginMutation();\n const [removePluginMutation] = useRemoveAgentPluginMutation();\n\n const fetchPlugins = useCallback(async () => {\n if (!agent?.id) return;\n setPluginsLoading(true);\n setPluginError(null);\n try {\n const { data } = await fetchAgentPlugins({\n variables: { agentId: agent.id, profile: activeProfile },\n });\n const result = data?.agentPlugins;\n if (result) {\n const installed = (result.installed || []).map(\n (p: {\n packageName: string;\n pluginName: string;\n version: string;\n installedAt?: string | null;\n loaded: boolean;\n description?: string | null;\n tags?: (string | null)[] | null;\n isCore: boolean;\n cliCommand?: string | null;\n apiPrefix?: string | null;\n hasUI: boolean;\n hasCliSetup: boolean;\n hasServerStart: boolean;\n hasServerStop: boolean;\n hasServerReady: boolean;\n hasProviders: boolean;\n }) => ({\n packageName: p.packageName,\n pluginName: p.pluginName,\n version: p.version,\n installedAt: p.installedAt || '',\n loaded: p.loaded,\n description: p.description ?? undefined,\n tags: (p.tags?.filter(Boolean) as string[]) ?? undefined,\n isCore: p.isCore,\n cliCommand: p.cliCommand ?? undefined,\n apiPrefix: p.apiPrefix ?? undefined,\n hasUI: p.hasUI,\n hasCliSetup: p.hasCliSetup,\n hasServerStart: p.hasServerStart,\n hasServerStop: p.hasServerStop,\n hasServerReady: p.hasServerReady,\n hasProviders: p.hasProviders,\n })\n );\n const available = (result.available || []).map(\n (p: {\n packageName: string;\n name: string;\n description: string;\n version: string;\n tags: string[];\n installed: boolean;\n }) => ({\n packageName: p.packageName,\n name: p.name,\n description: p.description,\n version: p.version,\n tags: [...p.tags],\n installed: p.installed,\n })\n );\n setInstalledPlugins(installed);\n setAvailablePlugins(available);\n if (result.error) {\n setPluginError(result.error);\n }\n }\n } catch {\n // Agent unreachable — show error state\n setPluginError('Agent unreachable — unable to fetch plugin list');\n } finally {\n setPluginsLoading(false);\n }\n }, [agent?.id, fetchAgentPlugins, activeProfile]);\n\n // Attempt to fetch live plugins when agent data loads.\n // If the agent is unreachable, an error state is shown instead of fake data.\n useEffect(() => {\n if (!agent?.id) return;\n const fetchKey = `${agent.id}:${activeProfile}`;\n if (pluginsFetchedRef.current !== fetchKey) {\n pluginsFetchedRef.current = fetchKey;\n fetchPlugins();\n }\n }, [agent?.id, activeProfile, fetchPlugins]);\n\n const handleInstallPlugin = useCallback(\n async (packageName: string) => {\n if (!agent?.id) return;\n setPluginActionLoading(packageName);\n try {\n const { data } = await installPluginMutation({\n variables: { agentId: agent.id, packageName },\n });\n if (data?.installAgentPlugin?.success) {\n await fetchPlugins();\n } else {\n throw new Error(\n data?.installAgentPlugin?.error || tr('agentDetails.installFailed', 'Install failed')\n );\n }\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n markQuotaHandledLocally();\n setQuotaKind('plugin');\n setShowQuotaExhausted(true);\n return;\n }\n\n setPluginError(\n err instanceof Error\n ? err.message\n : tr('agentDetails.pluginInstallFailed', 'Failed to install plugin')\n );\n setTimeout(() => setPluginError(null), 5000);\n } finally {\n setPluginActionLoading(null);\n }\n },\n [agent?.id, installPluginMutation, fetchPlugins, tr]\n );\n\n const handleRemovePlugin = useCallback(\n async (packageName: string) => {\n if (!agent?.id) return;\n if (\n !window.confirm(\n tr('agentDetails.removePluginConfirm', 'Remove plugin {{packageName}}?', { packageName })\n )\n )\n return;\n setPluginActionLoading(packageName);\n try {\n const { data } = await removePluginMutation({\n variables: { agentId: agent.id, packageName },\n });\n if (data?.removeAgentPlugin?.success) {\n await fetchPlugins();\n } else {\n throw new Error(\n data?.removeAgentPlugin?.error || tr('agentDetails.removeFailed', 'Remove failed')\n );\n }\n } catch (err) {\n setPluginError(\n err instanceof Error\n ? err.message\n : tr('agentDetails.pluginRemoveFailed', 'Failed to remove plugin')\n );\n setTimeout(() => setPluginError(null), 5000);\n } finally {\n setPluginActionLoading(null);\n }\n },\n [agent?.id, removePluginMutation, fetchPlugins, tr]\n );\n\n // Get sessions and vibes from the agent response (already included in the query)\n const agentSessions = agent?.sessions || [];\n const agentVibes = agent?.vibes || [];\n\n // ── Store plugin fetch / install ──────────────────────────────────\n const fetchStorePlugins = useCallback(async () => {\n setStorePluginsLoading(true);\n setStorePluginsError(null);\n try {\n const response = await fetch(\n (typeof window !== 'undefined' &&\n (window as { __BURDENOFF_GLOBAL_GATEWAY__?: string }).__BURDENOFF_GLOBAL_GATEWAY__) ||\n '/global/graphql',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify({\n query: `query MyStorePlugins {\n myEntitlements {\n id\n productId\n licenseKey\n product {\n id\n name\n slug\n icon\n description\n manifest\n }\n }\n }`,\n }),\n }\n );\n const body = (await response.json()) as {\n data?: { myEntitlements?: StoreEntitlement[] };\n errors?: Array<{ message: string }>;\n };\n if (body.errors?.length)\n throw new Error(body.errors[0]?.message ?? 'Failed to load store plugins');\n const plugins = (body.data?.myEntitlements ?? []).filter((e) => {\n const manifest = e.product?.manifest as Record<string, unknown> | null;\n if (!manifest) return false;\n const itemType = (manifest['itemType'] as string | undefined)?.toLowerCase();\n return itemType === 'vibemodule' || itemType === 'plugin';\n });\n setStorePlugins(plugins);\n } catch (err) {\n setStorePluginsError(err instanceof Error ? err.message : 'Failed to load store plugins');\n } finally {\n setStorePluginsLoading(false);\n }\n }, []);\n\n useEffect(() => {\n if (pluginSubTab === 'store' && storePlugins.length === 0 && !storePluginsLoading) {\n void fetchStorePlugins();\n }\n }, [pluginSubTab, storePlugins.length, storePluginsLoading, fetchStorePlugins]);\n\n const handleInstallStorePlugin = useCallback(\n async (productId: string, licenseKey: string | null) => {\n if (!agent?.id) return;\n setStoreInstallingId(productId);\n try {\n const response = await fetch(\n (typeof window !== 'undefined' &&\n (window as { __BURDENOFF_WSPACE_GATEWAY__?: string }).__BURDENOFF_WSPACE_GATEWAY__) ||\n '/workspaces/graphql',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify({\n query: `mutation InstallStorePlugin($agentId: ID!, $productId: ID!, $licenseKey: String) {\n installStorePluginOnAgent(agentId: $agentId, productId: $productId, licenseKey: $licenseKey) {\n success\n error\n }\n }`,\n variables: { agentId: agent.id, productId, licenseKey },\n }),\n }\n );\n const body = (await response.json()) as {\n data?: {\n installStorePluginOnAgent?: { success: boolean; error: string | null };\n };\n errors?: Array<{ message: string }>;\n };\n if (body.errors?.length) throw new Error(body.errors[0]?.message ?? 'Install failed');\n const result = body.data?.installStorePluginOnAgent;\n if (!result?.success) {\n throw new Error(result?.error ?? 'Install failed');\n }\n await fetchPlugins();\n setPluginSubTab('installed');\n } catch (err) {\n setStorePluginsError(err instanceof Error ? err.message : 'Install failed');\n } finally {\n setStoreInstallingId(null);\n }\n },\n [agent?.id, fetchPlugins]\n );\n\n // Handle ?install=<productId>&licenseKey=... on page load — automatic install flow\n // when the user arrives here from OrderConfirmationPage\n useEffect(() => {\n if (typeof window === 'undefined' || !agent?.id) return;\n const params = new URLSearchParams(window.location.search);\n const productId = params.get('install');\n const licenseKey = params.get('licenseKey');\n if (productId && productId !== storeInstallingId) {\n setPluginSubTab('store');\n void handleInstallStorePlugin(productId, licenseKey);\n // Clear the query params after initiating\n const url = new URL(window.location.href);\n url.searchParams.delete('install');\n url.searchParams.delete('licenseKey');\n window.history.replaceState({}, '', url.toString());\n }\n }, [agent?.id, handleInstallStorePlugin, storeInstallingId]);\n\n const handleRevealApiKey = useCallback(async (): Promise<string | null> => {\n if (!agent?.id) return null;\n if (revealedApiKey) return revealedApiKey;\n setRevealLoading(true);\n setRevealError(null);\n try {\n const res = await fetchAgentSecret({ variables: { agentId: agent.id } });\n const key = res.data?.vibecontrolsAgentSecretReveal ?? null;\n if (!key) {\n setRevealError('No API key configured');\n return null;\n }\n setRevealedApiKey(key);\n return key;\n } catch (err) {\n setRevealError(err instanceof Error ? err.message : 'Reveal failed');\n return null;\n } finally {\n setRevealLoading(false);\n }\n }, [agent?.id, revealedApiKey, fetchAgentSecret]);\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions…</p>\n </div>\n );\n if (\n permissions &&\n (permissions.permissionStrings?.length ?? 0) > 0 &&\n !hasPermission(VIBE_PERMISSIONS.AGENT_READ)\n )\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n const handleBack = () => {\n navigate('/agents');\n };\n\n // Real lifecycle control: start/stop the agent process via the backend proxy\n // (POST /agent/lifecycle/{start,stop} on the agent), not a metadata write.\n // Shows a spinner + disables the button while in flight and surfaces the\n // outcome as a toast; refreshes the agent record + live health probe so the\n // badge and the Start/Stop toggle flip immediately.\n const runLifecycle = async (action: 'start' | 'stop') => {\n if (!agent?.id || lifecycleAction) return;\n setLifecycleAction(action);\n setErrorMessage(null);\n try {\n const res =\n action === 'start'\n ? await startVibecontrolsAgent({ variables: { agentId: agent.id } })\n : await stopVibecontrolsAgent({ variables: { agentId: agent.id } });\n const payload =\n action === 'start' ? res.data?.startVibecontrolsAgent : res.data?.stopVibecontrolsAgent;\n // Only treat an explicitly-successful payload as success. A null payload\n // (network hiccup / unexpected schema shape) must not fall through to the\n // success toast.\n if (!payload || payload.success === false) {\n throw new Error(payload?.error || `Failed to ${action} agent`);\n }\n setSuccessMessage(\n action === 'start'\n ? tr('agentDetails.agentStarted', 'Agent started')\n : tr('agentDetails.agentStopped', 'Agent stopped')\n );\n setTimeout(() => setSuccessMessage(null), 3000);\n // Snappy refresh — don't wait for the 30s probe poll / heartbeat sweep.\n await Promise.all([refetch(), probeQuery.refetch()]).catch(() => {});\n } catch (err) {\n const raw = err instanceof Error ? err.message : '';\n // The backend reaches the agent only over its tunnel. If the tunnel is\n // down (common after a stop, or if the host went away) the call can't\n // land — surface an actionable message instead of a raw fetch error.\n const unreachable =\n /unable to connect|fetch failed|timed? ?out|ECONN|agent returned 5|network/i.test(raw);\n setErrorMessage(\n unreachable\n ? tr(\n 'agentDetails.agentUnreachable',\n `Couldn't reach the agent to ${action} it — it may be offline or its tunnel is down. Start it from the host with: vibe start`\n )\n : raw || tr('agentDetails.lifecycleFailed', `Failed to ${action} agent`)\n );\n setTimeout(() => setErrorMessage(null), 6000);\n } finally {\n setLifecycleAction(null);\n }\n };\n\n const handleStartAgent = () => void runLifecycle('start');\n const handleStopAgent = () => void runLifecycle('stop');\n\n const handleConfigureAgent = () => {\n setConfigError(null);\n setShowConfigModal(true);\n };\n\n const handleRenameSave = async (): Promise<void> => {\n if (!agent?.id) return;\n const next = renameValue.trim();\n if (!next || next === agent.name) {\n setRenaming(false);\n return;\n }\n setRenameSaving(true);\n setRenameError(null);\n try {\n const result = await updateAgent({\n variables: { id: agent.id, input: { name: next } },\n });\n if (result.error) {\n throw result.error;\n }\n setRenaming(false);\n } catch (err) {\n // Most common failure mode: the (workspaceId, name) unique\n // constraint in wspace-vibecontrols-svc rejects a duplicate.\n // Surface the message inline so the operator can pick a\n // different name without losing what they typed.\n setRenameError(err instanceof Error ? err.message : String(err));\n } finally {\n setRenameSaving(false);\n }\n };\n\n const handleRenameCancel = (): void => {\n setRenaming(false);\n setRenameValue('');\n setRenameError(null);\n };\n\n const handleSubmitConfig = async () => {\n if (!agent?.id) return;\n\n const name = agentNameRef.current?.value?.trim();\n const tunnelUrl = agentTunnelUrlRef.current?.value?.trim();\n const aiContext = agentAiContextRef.current?.value?.trim();\n const metadataStr = agentMetadataRef.current?.value?.trim();\n\n if (!name) {\n setConfigError(tr('agentDetails.agentNameRequired', 'Agent name is required'));\n return;\n }\n\n let metadata: Record<string, unknown> | undefined;\n if (metadataStr) {\n try {\n metadata = JSON.parse(metadataStr);\n } catch {\n setConfigError(tr('agentDetails.metadataJsonRequired', 'Metadata must be valid JSON'));\n return;\n }\n }\n\n setConfigLoading(true);\n setConfigError(null);\n try {\n // TODO(svc): the deprecated `UpdateVibecontrolsAgentInput.agentApiKey`\n // field was dropped by F4 Wave B. A dedicated rotate-API-key svc\n // mutation needs to land before we can re-expose key rotation in\n // this Configure dialog. The form input is hidden until then.\n await updateAgent({\n variables: {\n id: agent.id,\n input: {\n name,\n ...(tunnelUrl !== undefined ? { tunnelUrl: tunnelUrl || null } : {}),\n aiContext: aiContext || null,\n metadata,\n },\n },\n });\n setShowConfigModal(false);\n setSuccessMessage(\n tr('agentDetails.configurationUpdated', 'Agent configuration updated successfully')\n );\n setTimeout(() => setSuccessMessage(null), 3000);\n } catch (err) {\n setConfigError(\n err instanceof Error\n ? err.message\n : tr('agentDetails.configurationUpdateFailed', 'Failed to update agent configuration')\n );\n } finally {\n setConfigLoading(false);\n }\n };\n\n const handleCopyApiKey = async () => {\n const key = await handleRevealApiKey();\n if (!key) return;\n try {\n await nativeCopyText(key);\n if (isNative()) void nativeToast('API key copied');\n setApiKeyCopied(true);\n setTimeout(() => setApiKeyCopied(false), 2000);\n } catch {\n // Fallback for non-HTTPS contexts\n console.error('Failed to copy API key');\n }\n };\n\n const handleToggleShowApiKey = async () => {\n if (!showApiKey) {\n await handleRevealApiKey();\n }\n setShowApiKey((v) => !v);\n };\n\n const handleRemoveAgent = async () => {\n if (!agent?.id) return;\n if (\n !window.confirm(\n tr('agentDetails.removeAgentConfirm', 'Are you sure you want to remove agent \"{{name}}\"?', {\n name: agent.name,\n })\n )\n )\n return;\n try {\n await deleteAgent({ variables: { id: agent.id } });\n handleBack();\n } catch (err) {\n console.error('Failed to remove agent:', err);\n }\n };\n\n const handleSessionClick = (sessionId: string) => {\n navigate(`/sessions/${sessionId}`);\n };\n\n const handleStartSession = () => {\n setSessionCreateError(null);\n setShowSessionModal(true);\n };\n\n const handleSubmitCreateSession = async () => {\n const name = sessionNameRef.current?.value?.trim();\n const type = sessionTypeRef.current?.value as 'TERMINAL' | 'TMUX' | 'SSH' | 'SCRIPT' | 'CUSTOM';\n const command = sessionCommandRef.current?.value?.trim() || undefined;\n const workingDirectory = sessionWorkDirRef.current?.value?.trim() || undefined;\n\n if (!name) {\n setSessionCreateError(tr('vibeDetails.sessionNameRequired', 'Session name is required'));\n return;\n }\n if (!agent?.id) {\n setSessionCreateError(tr('agentDetails.noAgent', 'Agent not loaded'));\n return;\n }\n\n // Block create when the agent's live deep-health probe is not green —\n // otherwise the create succeeds (PENDING row) but terminal-start fails\n // later with a tunnel-URL error. Matches the gate in SessionsPage.\n const probeRow = probesById.get(agent.id);\n if (probeRow && !probeRow.healthy) {\n setSessionCreateError(\n tr(\n 'sessions.agentNotHealthy',\n 'The selected agent isn’t fully reachable right now. Please wait for the agent badge to turn green and retry.'\n ) + (probeRow.errorMessage ? ` (${probeRow.errorMessage})` : '')\n );\n return;\n }\n\n setSessionCreateLoading(true);\n setSessionCreateError(null);\n try {\n await createSession({\n variables: {\n input: {\n name,\n type: type || 'TERMINAL',\n agentId: agent.id,\n command,\n workingDirectory,\n },\n },\n });\n setShowSessionModal(false);\n if (sessionNameRef.current) sessionNameRef.current.value = '';\n if (sessionTypeRef.current) sessionTypeRef.current.selectedIndex = 0;\n if (sessionCommandRef.current) sessionCommandRef.current.value = '';\n if (sessionWorkDirRef.current) sessionWorkDirRef.current.value = '';\n setSuccessMessage(tr('sessions.createdSuccess', 'Session created successfully'));\n setTimeout(() => setSuccessMessage(null), 3000);\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowSessionModal(false);\n markQuotaHandledLocally();\n setQuotaKind('session');\n setShowQuotaExhausted(true);\n return;\n }\n setSessionCreateError(\n err instanceof Error ? err.message : tr('sessions.failedCreate', 'Failed to create session')\n );\n } finally {\n setSessionCreateLoading(false);\n }\n };\n\n const handleVibeClick = (vibeId: string) => {\n navigate(`/vibes/${vibeId}`);\n };\n\n const formatTimestamp = (timestamp: string | null | undefined) => {\n if (!timestamp) return tr('health.never', 'Never');\n const diff = Date.now() - new Date(timestamp).getTime();\n if (diff < 60000) return tr('health.justNow', 'Just now');\n if (diff < 3600000) {\n return tr('agentDetails.minutesAgo', '{{count}}m ago', {\n count: Math.floor(diff / 60000),\n });\n }\n if (diff < 86400000) {\n return tr('agentDetails.hoursAgo', '{{count}}h ago', {\n count: Math.floor(diff / 3600000),\n });\n }\n return new Date(timestamp).toLocaleDateString();\n };\n\n // Loading state - wrapped in MotionPage to prevent unmount/remount animation replay\n if (loading && !agent) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('agentDetails.backToAgents', 'Back to Agents')}\n </button>\n <PageSkeleton variant=\"detail\" />\n </MotionPage>\n );\n }\n\n // Error state\n if (error && !agent) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('agentDetails.backToAgents', 'Back to Agents')}\n </button>\n <ErrorState\n title={tr('agentDetails.failedLoad', 'Failed to load agent')}\n message={error.message}\n onRetry={() => refetch()}\n />\n </MotionPage>\n );\n }\n\n // Not found state\n if (!agent) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('agentDetails.backToAgents', 'Back to Agents')}\n </button>\n <EmptyState\n icon={<Server className=\"size-8 text-text-secondary\" />}\n title={tr('agentDetails.notFound', 'Agent not found')}\n description={`${tr('agentDetails.notFoundDescriptionPrefix', 'No agent with ID')} \"${id}\" ${tr('agentDetails.notFoundDescriptionSuffix', 'exists')}`}\n action={\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n {tr('agentDetails.backToAgents', 'Back to Agents')}\n </button>\n }\n />\n </MotionPage>\n );\n }\n\n const agentTabs: { id: AgentTab; label: string; icon: typeof Server; badge?: string }[] = [\n { id: 'overview', label: tr('nav.overview', 'Overview'), icon: Server },\n { id: 'profiles', label: tr('agentDetails.profiles', 'Profiles'), icon: Users },\n { id: 'security', label: tr('agentDetails.security', 'Security'), icon: Shield },\n {\n id: 'plugins',\n label: tr('agentDetails.plugins', 'Plugins'),\n icon: Puzzle,\n badge: `${installedPlugins.length}`,\n },\n {\n id: 'sessions',\n label: tr('nav.sessions', 'Sessions'),\n icon: Terminal,\n badge: `${agentSessions.length}`,\n },\n {\n id: 'logs',\n label: tr('nav.logs', 'Logs'),\n icon: ScrollText,\n },\n {\n id: 'connection',\n label: tr('agentDetails.connection', 'Connection Log'),\n icon: ScrollText,\n },\n {\n id: 'vibes',\n label: tr('nav.vibes', 'Vibes'),\n icon: Zap,\n badge: `${agentVibes.length}`,\n },\n {\n id: 'notes',\n label: tr('vibeDetails.notes', 'Notes'),\n icon: FileText,\n },\n {\n id: 'aliases',\n label: tr('agentDetails.aliases', 'Aliases'),\n icon: Command,\n },\n {\n id: 'backup',\n label: tr('agentDetails.backup', 'Backup'),\n icon: Database,\n },\n ];\n\n // Types for sessions and vibes from the query\n type SessionItem = NonNullable<typeof agentSessions>[number];\n type VibeItem = NonNullable<typeof agentVibes>[number];\n\n // Stats\n const runningSessions = agentSessions.filter((s: SessionItem) => s.status === 'RUNNING').length;\n // Declared here (rather than inside JSX) because it's used in the backup tab panel below.\n const backupTunnelUrl = agent?.tunnelUrl;\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n {/* Success Toast */}\n {successMessage && (\n <div className=\"fixed top-4 left-4 right-4 sm:left-auto z-50 bg-status-success-bg text-status-success-text px-4 py-3 rounded-md shadow-lg\">\n {successMessage}\n </div>\n )}\n\n {/* Error Toast — offset below the success toast so the two never overlap\n when a 3s success auto-dismiss races a fresh 6s error. */}\n {errorMessage && (\n <div className=\"fixed top-16 left-4 right-4 sm:left-auto z-50 bg-status-error-bg text-status-error-text px-4 py-3 rounded-md shadow-lg\">\n {errorMessage}\n </div>\n )}\n\n {/* Back Button */}\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('agentDetails.backToAgents', 'Back to Agents')}\n </button>\n\n {/* Header */}\n <PageHeader\n title={agent.name}\n description={\n agent.hostname || tr('agentDetails.noHostnameConfigured', 'No hostname configured')\n }\n breadcrumb={[\n { label: tr('nav.agents', 'Agents'), path: basePath ? `${basePath}/agents` : '/agents' },\n { label: agent.name },\n ]}\n actions={\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => navigate('/ai?contextLevel=agent')}\n className=\"flex items-center gap-2 px-3 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors\"\n title={tr('agentDetails.openAiChat', 'Open AI chat with this agent')}\n data-testid=\"agent-open-ai-chat\"\n >\n <Bot className=\"size-4\" />\n <span className=\"hidden sm:inline\">{tr('agentDetails.aiChat', 'AI Chat')}</span>\n </button>\n <button\n type=\"button\"\n onClick={() => refetch()}\n disabled={loading}\n className=\"flex items-center gap-2 px-3 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors disabled:opacity-50\"\n title={tr('common.refresh', 'Refresh')}\n >\n <RefreshCw className={`size-4 ${loading ? 'animate-spin' : ''}`} />\n </button>\n {!showStartButton ? (\n <button\n type=\"button\"\n onClick={handleStopAgent}\n disabled={lifecycleAction !== null}\n aria-busy={lifecycleAction === 'stop'}\n className=\"flex items-center gap-2 px-3 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors disabled:opacity-60 disabled:cursor-not-allowed\"\n >\n {lifecycleAction === 'stop' ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Square className=\"size-4\" />\n )}\n {lifecycleAction === 'stop'\n ? tr('agentDetails.stopping', 'Stopping…')\n : tr('sessions.stop', 'Stop')}\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={handleStartAgent}\n disabled={lifecycleAction !== null}\n aria-busy={lifecycleAction === 'start'}\n className=\"flex items-center gap-2 px-3 py-2 bg-status-success-bg text-status-success-text rounded-md hover:opacity-80 transition-colors disabled:opacity-60 disabled:cursor-not-allowed\"\n >\n {lifecycleAction === 'start' ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Play className=\"size-4\" />\n )}\n {lifecycleAction === 'start'\n ? tr('agentDetails.starting', 'Starting…')\n : tr('agentDetails.start', 'Start')}\n </button>\n )}\n {derivedStatus === 'DEGRADED' && (\n // BOFF-2628 — Reconnect on Degraded. Fires the same lifecycle\n // start as a fresh start; svc-side that POSTs lifecycle/start\n // to the agent's tunnel, which typically clears transient\n // failures (tunnel hiccup, finalize retry). The button is\n // labelled \"Reconnect\" so the user knows it's a recovery\n // action — not a fresh start that might collide.\n <button\n type=\"button\"\n onClick={handleStartAgent}\n disabled={lifecycleAction !== null}\n aria-busy={lifecycleAction === 'start'}\n className=\"flex items-center gap-2 px-3 py-2 bg-status-warning-bg text-status-warning-text rounded-md hover:opacity-80 transition-colors disabled:opacity-60 disabled:cursor-not-allowed\"\n title={\n probesById.get(agent.id)?.errorMessage\n ? `Retry lifecycle/start — last error: ${probesById.get(agent.id)?.errorMessage}`\n : 'Retry lifecycle/start'\n }\n >\n {lifecycleAction === 'start' ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <RefreshCw className=\"size-4\" />\n )}\n {lifecycleAction === 'start'\n ? tr('agentDetails.reconnecting', 'Reconnecting…')\n : tr('agentDetails.reconnect', 'Reconnect')}\n </button>\n )}\n <OpenInBrowserEditorButton\n agentId={agent.id}\n tunnelUrl={agent.tunnelUrl || null}\n profile={activeProfile}\n />\n <button\n type=\"button\"\n onClick={handleConfigureAgent}\n className=\"flex items-center gap-2 px-3 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors\"\n >\n <Settings className=\"size-4\" />\n {tr('agentDetails.configure', 'Configure')}\n </button>\n <button\n type=\"button\"\n onClick={handleRemoveAgent}\n className=\"flex items-center gap-2 px-3 py-2 bg-status-error-bg text-status-error-text rounded-md hover:opacity-80 transition-colors\"\n >\n <Trash2 className=\"size-4\" />\n {tr('sessions.remove', 'Remove')}\n </button>\n </div>\n }\n />\n\n {/* Inline rename row — quick edit for the agent's display name.\n The Configure modal still owns the full edit (tunnel URL,\n ai-context, metadata, etc.); this is the one-click affordance\n for the common case of \"I just want to rename this thing\". */}\n <div className=\"flex items-center gap-2 -mt-2\">\n {renaming ? (\n <>\n <input\n ref={renameInputRef}\n type=\"text\"\n value={renameValue}\n onChange={(e) => setRenameValue(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !renameSaving) {\n void handleRenameSave();\n } else if (e.key === 'Escape') {\n handleRenameCancel();\n }\n }}\n disabled={renameSaving}\n maxLength={120}\n aria-label={tr('agentDetails.renameInput', 'New agent name')}\n className=\"flex-1 max-w-md px-3 py-1.5 text-sm bg-bg-surface border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n placeholder={agent.name}\n data-testid=\"agent-details-rename-input\"\n />\n <button\n type=\"button\"\n onClick={() => void handleRenameSave()}\n disabled={!renameValue.trim() || renameValue.trim() === agent.name || renameSaving}\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-60 disabled:cursor-not-allowed\"\n data-testid=\"agent-details-rename-save\"\n >\n {renameSaving ? (\n <Loader2 className=\"size-3.5 animate-spin\" />\n ) : (\n <Check className=\"size-3.5\" />\n )}\n {tr('agentDetails.saveName', 'Save')}\n </button>\n <button\n type=\"button\"\n onClick={handleRenameCancel}\n disabled={renameSaving}\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-xs text-text-secondary hover:text-text-primary disabled:opacity-60\"\n data-testid=\"agent-details-rename-cancel\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n {renameError && (\n <span className=\"text-xs text-status-error-text\" role=\"alert\">\n {renameError}\n </span>\n )}\n </>\n ) : (\n <button\n type=\"button\"\n onClick={() => {\n setRenameError(null);\n setRenameValue(agent.name);\n setRenaming(true);\n requestAnimationFrame(() => renameInputRef.current?.select());\n }}\n className=\"inline-flex items-center gap-1.5 text-xs text-text-secondary hover:text-text-primary transition-colors\"\n title={tr('agentDetails.renameTooltip', 'Rename this agent')}\n data-testid=\"agent-details-rename-trigger\"\n >\n <Edit3 className=\"size-3.5\" />\n {tr('agentDetails.rename', 'Rename')}\n </button>\n )}\n </div>\n\n {/* Status Cards */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4\">\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Server className=\"size-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">{tr('sessions.filterStatus', 'Status')}</p>\n <AgentStatusBadge\n status={derivedStatus}\n reason={\n probesById.get(agent.id)?.errorMessage ??\n (agent.lastGatewayAuthPushStatus === 'failed'\n ? (agent.lastGatewayAuthPushError ?? 'Gateway-auth push failed')\n : null)\n }\n linkTo={`?tab=connection`}\n onClick={(event) => {\n event.preventDefault();\n setActiveTab('connection');\n }}\n />\n </div>\n </div>\n </Card>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Cpu className=\"size-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">{tr('analytics.platform', 'Platform')}</p>\n <p className=\"font-semibold text-text-primary\">\n {agent.platform}/{agent.architecture}\n </p>\n </div>\n </div>\n </Card>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <HardDrive className=\"size-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">{tr('agentDetails.version', 'Version')}</p>\n <p className=\"font-semibold text-text-primary\">v{agent.version}</p>\n </div>\n </div>\n </Card>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Terminal className=\"size-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">{tr('nav.sessions', 'Sessions')}</p>\n <p className=\"font-semibold text-text-primary\">\n {runningSessions} {tr('health.active', 'active')}\n </p>\n </div>\n </div>\n </Card>\n </div>\n\n {/* ── Tab Navigation Bar ─────────────────────────────────────────── */}\n <div className=\"border-b border-border-default\">\n <nav\n className=\"flex gap-1 -mb-px overflow-x-auto pb-1\"\n aria-label={tr('agentDetails.tabsAriaLabel', 'Agent tabs')}\n >\n {agentTabs.map((tab) => {\n const Icon = tab.icon;\n const isActive = activeTab === tab.id;\n return (\n <button\n type=\"button\"\n key={tab.id}\n onClick={() => setActiveTab(tab.id)}\n className={`flex shrink-0 items-center gap-1.5 px-3 py-2.5 text-xs sm:gap-2 sm:px-4 sm:text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${\n isActive\n ? // text-action-primary-bg is the brand blue — used intentionally for text\n // to match the active border color. text-action-primary-text is white,\n // which is invisible on light backgrounds.\n 'border-action-primary-bg text-action-primary-bg'\n : 'border-transparent text-text-secondary hover:text-text-primary hover:border-border-default'\n }`}\n aria-selected={isActive}\n role=\"tab\"\n >\n <Icon className=\"size-4\" />\n {tab.label}\n {tab.badge && (\n <span\n className={`hidden rounded-full px-1.5 py-0.5 text-[10px] sm:inline-flex sm:text-xs ${\n isActive\n ? 'bg-action-primary-bg/10 text-action-primary-bg'\n : 'bg-bg-sunken text-text-muted'\n }`}\n >\n {tab.badge}\n </span>\n )}\n </button>\n );\n })}\n {/* PR-8 iframe-mounted tabs for the `agent.detailTab` mount.\n Same gate as VibeDetailsPage — feature-flagged off by\n default. */}\n {enableIframeHost &&\n iframeContributions.data.map((c) => {\n const isActive = activeTab === c.contribution.id;\n return (\n <button\n type=\"button\"\n key={`plugin-${c.contribution.id}`}\n onClick={() => setActiveTab(c.contribution.id)}\n className={`flex shrink-0 items-center gap-1.5 px-3 py-2.5 text-xs sm:gap-2 sm:px-4 sm:text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${\n isActive\n ? 'border-action-primary-bg text-action-primary-bg'\n : 'border-transparent text-text-secondary hover:text-text-primary hover:border-border-default'\n }`}\n aria-selected={isActive}\n role=\"tab\"\n title={`${c.contribution.title} (plugin: ${c.pluginKey})`}\n >\n {c.contribution.title}\n </button>\n );\n })}\n {/* \"+ Add tab\" — placed at the trailing end of the strip. */}\n {enableIframeHost && agent && (\n <button\n type=\"button\"\n onClick={() => setAddTabOpen(true)}\n className=\"flex shrink-0 items-center gap-1 p-2 text-xs sm:text-sm border-b-2 border-transparent text-text-secondary hover:text-text-primary hover:border-border-default\"\n title=\"Install a UI plugin tab\"\n aria-label=\"Add tab\"\n >\n <span aria-hidden>+</span>\n <span className=\"hidden sm:inline\">Add tab</span>\n </button>\n )}\n </nav>\n </div>\n\n {/* ── Tab Panels ─────────────────────────────────────────────────── */}\n <AnimatePresence mode=\"wait\">\n {/* Overview Tab */}\n {activeTab === 'overview' && (\n <motion.div\n key=\"overview\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n {/* Capabilities */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <CheckCircle2 className=\"size-5\" />\n {tr('agentDetails.capabilities', 'Capabilities')}\n </h3>\n </div>\n <div className=\"p-4\">\n <div className=\"flex flex-wrap gap-2\">\n {agent.capabilities &&\n typeof agent.capabilities === 'object' &&\n (Array.isArray(agent.capabilities)\n ? agent.capabilities.length > 0\n : Object.keys(agent.capabilities).length > 0) ? (\n (Array.isArray(agent.capabilities)\n ? (agent.capabilities as string[])\n : (() => {\n const obj = agent.capabilities as Record<string, unknown>;\n const keys = Object.keys(obj);\n const hasNumericKeys =\n keys.length > 0 && keys.every((k) => /^\\d+$/.test(k));\n return hasNumericKeys\n ? (Object.values(obj) as string[])\n : (keys as string[]);\n })()\n ).map((cap) => (\n <span\n key={cap}\n className=\"px-3 py-1 bg-bg-sunken text-text-primary text-sm rounded-full\"\n >\n {cap}\n </span>\n ))\n ) : (\n <div className=\"space-y-2 text-sm text-text-secondary\">\n <p>\n {tr('agentDetails.noCapabilitiesConfigured', 'No capabilities configured')}\n </p>\n <p className=\"text-xs\">\n Capabilities are feature tags the agent advertises to vibes (e.g.{' '}\n <code className=\"text-text-primary\">docker</code>,{' '}\n <code className=\"text-text-primary\">gpu</code>,{' '}\n <code className=\"text-text-primary\">node20</code>,{' '}\n <code className=\"text-text-primary\">git</code>). Vibes use them to pick an\n agent that can run their workloads.\n </p>\n <p className=\"text-xs\">\n Add from the agent host CLI:{' '}\n <code className=\"text-text-primary\">vibe agent caps add docker gpu</code>.\n The agent re-publishes its capability set on next heartbeat.\n </p>\n </div>\n )}\n </div>\n </div>\n </Card>\n\n {/* Tags */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Tag className=\"size-5\" />\n Tags\n </h3>\n </div>\n <div className=\"p-4\">\n <EntityTagPicker entityType=\"VIBECONTROLS_AGENT\" entityId={agent.id} />\n </div>\n </Card>\n\n {/* Tunnel Info */}\n {agent.tunnelUrl && (\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Zap className=\"size-5\" />\n {tr('health.tunnel', 'Tunnel')}\n </h3>\n </div>\n <div className=\"p-4\">\n {/*\n * Tunnel URL is a plain info field — no status chip\n * here. The agent's canonical status lives in the\n * top \"Status\" card above; rendering tunnelStatus\n * here was a redundant (and frequently stale)\n * second status surface.\n */}\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm text-text-secondary mb-1\">\n {tr('agentDetails.tunnelUrl', 'Tunnel URL')}\n </p>\n <a\n href={agent.tunnelUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-action-primary-text hover:underline break-all\"\n >\n {agent.tunnelUrl}\n </a>\n </div>\n </div>\n </Card>\n )}\n\n {/* Configuration */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Settings className=\"size-5\" />\n {tr('agentDetails.configuration', 'Configuration')}\n </h3>\n </div>\n <div className=\"p-4 space-y-4\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('analytics.platform', 'Platform')}\n </p>\n <p className=\"font-medium text-text-primary\">{agent.platform}</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('analytics.architecture', 'Architecture')}\n </p>\n <p className=\"font-medium text-text-primary\">{agent.architecture}</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('agentDetails.version', 'Version')}\n </p>\n <p className=\"font-medium text-text-primary\">{agent.version}</p>\n </div>\n </div>\n {agent.aiContext && (\n <div>\n <p className=\"text-sm text-text-secondary mb-1\">AI Context</p>\n <pre className=\"text-sm text-text-primary bg-bg-sunken border border-border-default rounded-md p-3 whitespace-pre-wrap font-sans\">\n {agent.aiContext}\n </pre>\n </div>\n )}\n </div>\n </Card>\n\n {/* Timeline */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Clock className=\"size-5\" />\n {tr('vibeDetails.timeline', 'Timeline')}\n </h3>\n </div>\n <div className=\"p-4\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 text-sm\">\n <div>\n <p className=\"text-text-secondary\">\n {tr('health.lastHeartbeat', 'Last Heartbeat')}\n </p>\n <p className=\"font-medium text-text-primary\">\n {formatTimestamp(agent.lastHeartbeat)}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">{tr('vibeDetails.created', 'Created')}</p>\n <p className=\"font-medium text-text-primary\">\n {formatTimestamp(agent.createdAt)}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">{tr('vibeDetails.updated', 'Updated')}</p>\n <p className=\"font-medium text-text-primary\">\n {formatTimestamp(agent.updatedAt)}\n </p>\n </div>\n </div>\n </div>\n </Card>\n </motion.div>\n )}\n\n {/* Profiles Tab — Phase 5B (multi-profile-per-daemon) */}\n {activeTab === 'profiles' && (\n <motion.div\n key=\"profiles\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <ProfilesPanel agentId={agent.id} />\n </motion.div>\n )}\n\n {/* Security Tab */}\n {activeTab === 'security' && (\n <motion.div\n key=\"security\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n {/* Agent API Key */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Key className=\"size-5\" />\n {tr('agentDetails.agentApiKey', 'Agent API Key')}\n </h3>\n </div>\n <div className=\"p-4\">\n {agent.tunnelUrl ? (\n <div className=\"flex items-center gap-3\">\n <div className=\"flex-1 min-w-0\">\n <code className=\"text-sm font-mono text-text-primary bg-bg-sunken px-3 py-2 rounded-md block truncate\">\n {showApiKey && revealedApiKey\n ? revealedApiKey\n : revealLoading\n ? tr('agentDetails.revealLoading', 'Revealing\\u2026')\n : '\\u2022'.repeat(32)}\n </code>\n {revealError && (\n <p className=\"text-xs text-status-error-text mt-1\">{revealError}</p>\n )}\n </div>\n <button\n type=\"button\"\n onClick={() => void handleToggleShowApiKey()}\n disabled={revealLoading}\n className=\"p-2 rounded hover:bg-bg-sunken transition-colors flex-shrink-0 disabled:opacity-50\"\n title={\n showApiKey\n ? tr('agentDetails.hideApiKey', 'Hide API key')\n : tr('agentDetails.showApiKey', 'Show API key')\n }\n >\n {showApiKey ? (\n <EyeOff className=\"size-4 text-text-secondary\" />\n ) : (\n <Eye className=\"size-4 text-text-secondary\" />\n )}\n </button>\n <button\n type=\"button\"\n onClick={handleCopyApiKey}\n className=\"p-2 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n title={tr('agentDetails.copyApiKey', 'Copy API key')}\n >\n {apiKeyCopied ? (\n <Check className=\"size-4 text-status-success-text\" />\n ) : (\n <Copy className=\"size-4 text-text-secondary\" />\n )}\n </button>\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Agent tunnel not configured. Bring the agent online first.\n </p>\n )}\n <p className=\"mt-2 text-xs text-text-muted\">\n This key authenticates requests sent to the agent. The key is revealed only on\n explicit operator action and every read is audited.\n </p>\n </div>\n </Card>\n\n {/* Gateway Auth (OAuth2 App) */}\n <GatewayAuthCard agent={agent} onUpdate={() => refetch()} />\n </motion.div>\n )}\n\n {/* Plugins Tab */}\n {activeTab === 'plugins' &&\n (() => {\n const searchLower = pluginSearchQuery.toLowerCase();\n const filteredInstalled = installedPlugins.filter(\n (p) =>\n !searchLower ||\n p.pluginName.toLowerCase().includes(searchLower) ||\n p.packageName.toLowerCase().includes(searchLower) ||\n p.description?.toLowerCase().includes(searchLower) ||\n p.tags?.some((t) => t.toLowerCase().includes(searchLower))\n );\n const filteredAvailable = availablePlugins.filter(\n (p) =>\n !p.installed &&\n (!searchLower ||\n p.name.toLowerCase().includes(searchLower) ||\n p.packageName.toLowerCase().includes(searchLower) ||\n p.description.toLowerCase().includes(searchLower))\n );\n const uiPlugins = installedPlugins.filter((p) => p.hasUI);\n const filteredUIPlugins = uiPlugins.filter(\n (p) =>\n !searchLower ||\n p.pluginName.toLowerCase().includes(searchLower) ||\n p.packageName.toLowerCase().includes(searchLower)\n );\n\n const pluginSubTabs: {\n id: PluginSubTab;\n label: string;\n count: number;\n icon: typeof Puzzle;\n }[] = [\n {\n id: 'installed',\n label: 'Installed',\n count: filteredInstalled.length,\n icon: Puzzle,\n },\n {\n id: 'available',\n label: 'Available',\n count: filteredAvailable.length,\n icon: Download,\n },\n {\n id: 'store',\n label: 'Store',\n count: storePlugins.length,\n icon: Download,\n },\n {\n id: 'ui-plugins',\n label: 'UI Plugins',\n count: filteredUIPlugins.length,\n icon: Monitor,\n },\n ];\n\n return (\n <motion.div\n key=\"plugins\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n <Card>\n {/* Header with title, search, and refresh */}\n <div className=\"p-4 border-b border-border-default space-y-3\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Puzzle className=\"size-5\" />\n Plugins\n {installedPlugins.length > 0 && (\n <span className=\"text-sm font-normal text-text-secondary\">\n ({installedPlugins.filter((p) => p.isCore).length} core,{' '}\n {installedPlugins.filter((p) => !p.isCore).length} external)\n </span>\n )}\n </h3>\n <button\n type=\"button\"\n onClick={fetchPlugins}\n disabled={pluginsLoading}\n className=\"p-1.5 text-text-secondary hover:bg-bg-sunken rounded transition-colors disabled:opacity-50\"\n title={tr('agentDetails.refreshPlugins', 'Refresh plugins')}\n >\n <RefreshCw className={`size-4 ${pluginsLoading ? 'animate-spin' : ''}`} />\n </button>\n </div>\n\n {/* Search bar */}\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 size-4 text-text-muted\" />\n <input\n aria-label=\"control\"\n type=\"text\"\n value={pluginSearchQuery}\n onChange={(e) => setPluginSearchQuery(e.target.value)}\n placeholder={tr(\n 'agentDetails.searchPluginsPlaceholder',\n 'Search plugins by name, package, description, or tag...'\n )}\n className=\"w-full pl-9 pr-8 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-muted focus:outline-none focus:ring-1 focus:ring-action-primary-bg focus:border-action-primary-bg\"\n />\n {pluginSearchQuery && (\n <button\n type=\"button\"\n onClick={() => setPluginSearchQuery('')}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 p-0.5 text-text-muted hover:text-text-secondary rounded\"\n >\n <X className=\"size-3.5\" />\n </button>\n )}\n </div>\n\n {/* Sub-tabs */}\n <div className=\"flex gap-1 border-b border-border-default -mx-4 overflow-x-auto px-4 pb-1\">\n {pluginSubTabs.map((st) => {\n const isActive = pluginSubTab === st.id;\n const TabIcon = st.icon;\n return (\n <button\n type=\"button\"\n key={st.id}\n onClick={() => setPluginSubTab(st.id)}\n className={`flex shrink-0 items-center gap-1.5 px-3 py-2 text-xs sm:text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${\n isActive\n ? // text-action-primary-bg is the brand color and matches the active\n // border. text-action-primary-text is white — invisible on light bg.\n 'border-action-primary-bg text-action-primary-bg'\n : 'border-transparent text-text-secondary hover:text-text-primary hover:border-border-default'\n }`}\n >\n <TabIcon className=\"size-3.5\" />\n {st.label}\n <span\n className={`text-xs px-1.5 py-0.5 rounded-full ${\n isActive\n ? 'bg-action-primary-bg/15 text-action-primary-bg'\n : 'bg-bg-secondary text-text-muted'\n }`}\n >\n {st.count}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n\n <div className=\"p-4 space-y-4\">\n {/* Plugin Error */}\n {pluginError && (\n <div className=\"flex items-center gap-2 p-3 bg-status-error-bg text-status-error-text rounded-md text-sm\">\n <X className=\"size-4 flex-shrink-0\" />\n <span className=\"flex-1\">{pluginError}</span>\n <button\n type=\"button\"\n onClick={() => setPluginError(null)}\n className=\"flex-shrink-0 p-0.5 hover:bg-status-error-text/10 rounded\"\n >\n <X className=\"size-3.5\" />\n </button>\n </div>\n )}\n\n {/* Not reachable banner */}\n {!agent?.isActive && (\n <p className=\"text-sm text-text-muted flex items-center gap-1.5\">\n <Info className=\"size-4 flex-shrink-0\" />\n Agent is offline — showing known plugin catalog. Live data will load when\n the agent is reachable.\n </p>\n )}\n\n {/* Plugins are agent-wide (BOFF-2612). No per-profile\n gating: a single install/remove action applies to the\n whole agent. Only plugin DATA stays per-profile. */}\n\n {/* ── Installed Sub-Tab ────────────────────────────────── */}\n {pluginSubTab === 'installed' && (\n <>\n {filteredInstalled.length > 0 ? (\n <div className=\"space-y-2\">\n {filteredInstalled.map((plugin) => (\n <div\n key={plugin.packageName}\n className=\"flex flex-col sm:flex-row sm:items-center justify-between gap-2 p-3 bg-bg-sunken rounded-lg\"\n >\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium text-text-primary flex items-center gap-1.5 flex-wrap\">\n {plugin.pluginName}\n <span className=\"text-xs text-text-muted font-normal\">\n {plugin.version === 'latest'\n ? plugin.version\n : `v${plugin.version}`}\n </span>\n {plugin.isCore && (\n <span className=\"inline-flex items-center px-1.5 py-0.5 text-xs bg-action-primary-bg/10 text-action-primary-bg rounded border border-action-primary-bg/20\">\n core\n </span>\n )}\n {plugin.loaded && (\n <span className=\"inline-flex items-center px-1.5 py-0.5 text-xs bg-status-success-bg text-status-success-text rounded\">\n loaded\n </span>\n )}\n {plugin.hasProviders && (\n <span className=\"inline-flex items-center px-1.5 py-0.5 text-xs bg-status-warning-bg-subtle text-status-warning-text rounded\">\n provider\n </span>\n )}\n {plugin.hasUI && (\n <span className=\"inline-flex items-center px-1.5 py-0.5 text-xs bg-accent-purple-subtle text-accent-purple rounded\">\n ui\n </span>\n )}\n </p>\n {plugin.description && (\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {plugin.description}\n </p>\n )}\n <div className=\"flex items-center gap-2 mt-0.5 flex-wrap\">\n {!plugin.isCore && (\n <span className=\"text-xs text-text-muted font-mono\">\n {plugin.packageName}\n </span>\n )}\n {plugin.cliCommand && (\n <span className=\"text-xs text-text-muted\">\n cli:{' '}\n <code className=\"text-xs font-mono\">\n vibe {plugin.cliCommand}\n </code>\n </span>\n )}\n {plugin.apiPrefix && (\n <span className=\"text-xs text-text-muted\">\n api:{' '}\n <code className=\"text-xs font-mono\">\n {plugin.apiPrefix}\n </code>\n </span>\n )}\n </div>\n {plugin.tags && plugin.tags.length > 0 && (\n <div className=\"flex gap-1 mt-1 flex-wrap\">\n {plugin.tags.map((tag) => (\n <span\n key={tag}\n className=\"inline-flex px-1.5 py-0.5 text-[10px] bg-bg-secondary text-text-muted rounded\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-2 flex-shrink-0 sm:ml-3\">\n {plugin.hasUI && (\n <button\n type=\"button\"\n onClick={() => setPluginSubTab('ui-plugins')}\n className=\"flex items-center gap-1.5 px-2.5 py-1.5 text-xs text-action-primary-bg bg-action-primary-bg/10 rounded-md hover:bg-action-primary-bg/20 transition-colors border border-action-primary-bg/20\"\n title={`Open ${plugin.pluginName} UI`}\n >\n <Monitor className=\"size-3\" />\n Open UI\n </button>\n )}\n {!plugin.isCore && (\n <button\n type=\"button\"\n onClick={() => handleRemovePlugin(plugin.packageName)}\n disabled={pluginActionLoading === plugin.packageName}\n className=\"flex items-center gap-1.5 px-2.5 py-1.5 text-xs font-medium text-status-error-text bg-status-error-bg/15 border border-status-error-border/40 rounded-md hover:bg-status-error-bg/25 transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {pluginActionLoading === plugin.packageName ? (\n <Loader2 className=\"size-3 animate-spin\" />\n ) : (\n <Trash2 className=\"size-3\" />\n )}\n Remove\n </button>\n )}\n </div>\n </div>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-text-muted\">\n {pluginSearchQuery\n ? 'No installed plugins match your search.'\n : 'No plugin data available. Check agent connectivity or refresh.'}\n </p>\n )}\n </>\n )}\n\n {/* ── Available Sub-Tab ────────────────────────────────── */}\n {pluginSubTab === 'available' && (\n <>\n {filteredAvailable.length > 0 ? (\n <div className=\"space-y-2\">\n {filteredAvailable.map((plugin) => (\n <div\n key={plugin.packageName}\n className=\"flex flex-col sm:flex-row sm:items-center justify-between gap-2 p-3 bg-bg-sunken rounded-lg\"\n >\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium text-text-primary\">\n {plugin.name}\n </p>\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {plugin.description}\n </p>\n <p className=\"text-xs text-text-muted font-mono mt-0.5\">\n {plugin.packageName}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => handleInstallPlugin(plugin.packageName)}\n disabled={pluginActionLoading === plugin.packageName}\n className=\"flex items-center gap-1.5 px-2.5 py-1.5 text-xs text-action-primary-text bg-action-primary-bg rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex-shrink-0 sm:ml-3\"\n >\n {pluginActionLoading === plugin.packageName ? (\n <Loader2 className=\"size-3 animate-spin\" />\n ) : (\n <Download className=\"size-3\" />\n )}\n Install\n </button>\n </div>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-text-muted\">\n {pluginSearchQuery\n ? 'No available plugins match your search.'\n : availablePlugins.every((p) => p.installed)\n ? 'All available plugins are already installed.'\n : 'No available plugins found.'}\n </p>\n )}\n </>\n )}\n\n {/* ── Store Sub-Tab (Burdenoff Store purchased plugins) ── */}\n {pluginSubTab === 'store' && (\n <>\n {storePluginsError && (\n <div className=\"flex items-center gap-2 p-3 bg-status-error-bg text-status-error-text rounded-md text-sm\">\n <X className=\"size-4 flex-shrink-0\" />\n <span className=\"flex-1\">{storePluginsError}</span>\n </div>\n )}\n {storePluginsLoading ? (\n <p className=\"text-sm text-text-muted\">Loading purchased plugins…</p>\n ) : storePlugins.length === 0 ? (\n <div className=\"py-8 text-center\">\n <p className=\"text-sm text-text-muted\">\n No plugins purchased from the Burdenoff store yet.\n </p>\n <a\n href=\"/store/marketplace\"\n className=\"mt-2 inline-flex items-center gap-1 text-xs font-semibold text-action-primary-text hover:underline\"\n >\n Browse the store →\n </a>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {storePlugins.map((ent) => {\n const manifest =\n (ent.product?.manifest as Record<string, unknown> | null) ?? {};\n const digital = manifest['digital'] as\n | Record<string, unknown>\n | undefined;\n const install = digital?.['install'] as\n | Record<string, unknown>\n | undefined;\n const packageName =\n typeof install?.['packageName'] === 'string'\n ? (install['packageName'] as string)\n : null;\n const isAlreadyInstalled = installedPlugins.some(\n (p) => p.packageName === packageName\n );\n return (\n <div\n key={ent.id}\n className=\"flex flex-col sm:flex-row sm:items-center justify-between gap-2 p-3 bg-bg-sunken rounded-lg\"\n >\n <div className=\"flex items-start gap-3 min-w-0 flex-1\">\n {ent.product?.icon ? (\n <img\n src={ent.product.icon}\n alt=\"\"\n className=\"size-10 rounded-md object-cover flex-shrink-0\"\n />\n ) : (\n <div className=\"size-10 flex-shrink-0 rounded-md bg-bg-secondary flex items-center justify-center\">\n <Puzzle className=\"size-5 text-text-muted\" />\n </div>\n )}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <h4 className=\"text-sm font-semibold text-text-primary truncate\">\n {ent.product?.name ?? 'Unknown'}\n </h4>\n {ent.licenseKey && (\n <span className=\"text-[10px] bg-status-success-bg text-status-success-text px-1.5 py-0.5 rounded-full\">\n Licensed\n </span>\n )}\n </div>\n {packageName && (\n <p className=\"text-xs text-text-muted font-mono truncate\">\n {packageName}\n </p>\n )}\n {ent.product?.description && (\n <p className=\"text-xs text-text-secondary line-clamp-2 mt-1\">\n {ent.product.description}\n </p>\n )}\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() =>\n void handleInstallStorePlugin(ent.productId, ent.licenseKey)\n }\n disabled={\n isAlreadyInstalled ||\n storeInstallingId === ent.productId ||\n !packageName\n }\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-semibold rounded-md bg-action-primary-bg text-action-primary-text hover:opacity-90 disabled:opacity-60 flex-shrink-0\"\n >\n {isAlreadyInstalled\n ? 'Installed'\n : storeInstallingId === ent.productId\n ? 'Installing…'\n : 'Install'}\n </button>\n </div>\n );\n })}\n </div>\n )}\n </>\n )}\n\n {/* ── UI Plugins Sub-Tab (Embedded Browser) ────────────── */}\n {pluginSubTab === 'ui-plugins' && (\n <>\n {uiPlugins.length > 0 || agent?.tunnelUrl ? (\n <PluginUIPanel\n availablePlugins={[\n // Synthetic code-server entry (proxied, not a standard UI plugin)\n ...(agent?.tunnelUrl\n ? [\n {\n pluginName: 'code-server',\n displayName: 'Code Server (VS Code)',\n description: 'Browser-based VS Code editor',\n version: 'latest',\n customUrl: '/code-server/',\n } satisfies UIPluginOption,\n ]\n : []),\n ...uiPlugins.map(\n (p): UIPluginOption => ({\n pluginName: p.pluginName,\n displayName: p.pluginName\n .replace(/^ui-/, '')\n .replace(/-/g, ' ')\n .replace(/\\b\\w/g, (c) => c.toUpperCase()),\n description: p.description,\n version: p.version,\n })\n ),\n ]}\n tunnelUrl={agent?.tunnelUrl || null}\n agentId={agent?.id ?? null}\n profile={activeProfile}\n />\n ) : (\n <p className=\"text-sm text-text-muted\">\n {pluginSearchQuery\n ? 'No UI plugins match your search.'\n : 'No plugins with UI are currently installed.'}\n </p>\n )}\n </>\n )}\n\n {/* Loading */}\n {pluginsLoading && installedPlugins.length === 0 && (\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <Loader2 className=\"size-4 animate-spin\" />\n Loading plugins...\n </div>\n )}\n </div>\n </Card>\n </motion.div>\n );\n })()}\n\n {/* Sessions Tab */}\n {activeTab === 'sessions' && (\n <motion.div\n key=\"sessions\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <Card>\n <div className=\"p-4 border-b border-border-default flex items-center justify-between gap-3 flex-wrap\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Terminal className=\"size-5\" />\n {tr('nav.sessions', 'Sessions')} ({agentSessions.length})\n </h3>\n <PermissionButton\n permission={VIBE_PERMISSIONS.SESSION_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip=\"You don't have permission to create sessions\"\n >\n <button\n data-testid=\"create-session-btn\"\n onClick={handleStartSession}\n className=\"inline-flex items-center gap-2 px-3 py-1.5 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <Plus className=\"w-4 h-4\" />\n {tr('sessions.createSession', 'Create Session')}\n </button>\n </PermissionButton>\n </div>\n {agentSessions.length > 0 ? (\n <div className=\"divide-y divide-border-primary\">\n {agentSessions.map((session: SessionItem) => (\n <div\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (() => handleSessionClick(session.id))();\n }\n }}\n key={session.id}\n onClick={() => handleSessionClick(session.id)}\n className=\"p-4 flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 cursor-pointer hover:bg-bg-sunken/50 transition-colors\"\n >\n <div className=\"flex items-center gap-3 min-w-0\">\n <Terminal className=\"size-5 text-text-secondary flex-shrink-0\" />\n <div className=\"min-w-0\">\n <p className=\"font-medium text-text-primary truncate\">{session.name}</p>\n <p className=\"text-sm text-text-secondary truncate\">{session.type}</p>\n </div>\n </div>\n <StatusBadge status={session.status} />\n </div>\n ))}\n </div>\n ) : (\n <div className=\"p-6 text-center text-text-secondary flex flex-col items-center gap-3\">\n <span>{tr('agentDetails.noSessionsOnAgent', 'No sessions on this agent')}</span>\n <PermissionButton\n permission={VIBE_PERMISSIONS.SESSION_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip=\"You don't have permission to create sessions\"\n >\n <button\n data-testid=\"create-session-empty-btn\"\n onClick={handleStartSession}\n className=\"inline-flex items-center gap-2 px-3 py-1.5 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <Plus className=\"w-4 h-4\" />\n {tr('sessions.createSession', 'Create Session')}\n </button>\n </PermissionButton>\n </div>\n )}\n </Card>\n </motion.div>\n )}\n\n {activeTab === 'connection' && (\n <motion.div\n key=\"connection\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <Card className=\"min-h-[60vh]\">\n <ConnectionLogPanel agentId={agent.id} agentName={agent.name} />\n </Card>\n </motion.div>\n )}\n\n {activeTab === 'logs' && (\n <motion.div\n key=\"logs\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <Card>\n <div className=\"p-4 border-b border-border-default flex items-center justify-between\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <ScrollText className=\"size-5\" />\n {tr('nav.logs', 'Logs')}\n </h3>\n </div>\n <div className=\"p-4\">\n <LogViewer agentId={agent.id} profile={activeProfile} className=\"min-h-[28rem]\" />\n </div>\n </Card>\n </motion.div>\n )}\n\n {/* Vibes Tab */}\n {activeTab === 'vibes' && (\n <motion.div\n key=\"vibes\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <Card>\n <div className=\"p-4 border-b border-border-default flex items-center justify-between\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Zap className=\"size-5\" />\n {tr('nav.vibes', 'Vibes')} ({agentVibes.length})\n </h3>\n </div>\n {agentVibes.length > 0 ? (\n <div className=\"divide-y divide-border-primary\">\n {agentVibes.map((vibe: VibeItem) => (\n <div\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (() => handleVibeClick(vibe.id))();\n }\n }}\n key={vibe.id}\n onClick={() => handleVibeClick(vibe.id)}\n className=\"p-4 flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 cursor-pointer hover:bg-bg-sunken/50 transition-colors\"\n >\n <div className=\"flex items-center gap-3 min-w-0\">\n <Zap className=\"size-5 text-text-secondary flex-shrink-0\" />\n <div className=\"min-w-0\">\n <p className=\"font-medium text-text-primary truncate\">{vibe.name}</p>\n <p className=\"text-sm text-text-secondary truncate\">{vibe.type}</p>\n </div>\n </div>\n <StatusBadge status={vibe.status} />\n </div>\n ))}\n </div>\n ) : (\n <div className=\"p-6 text-center text-text-secondary\">\n {tr('agentDetails.noVibesUsingAgent', 'No vibes using this agent')}\n </div>\n )}\n </Card>\n </motion.div>\n )}\n\n {/* Notes Tab */}\n {activeTab === 'notes' && (\n <motion.div\n key=\"notes\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n <NotesTabPanel\n context=\"agent\"\n agentVibes={agentVibes.map((v: VibeItem) => ({ id: v.id, name: v.name }))}\n />\n </motion.div>\n )}\n\n {/* Aliases Tab */}\n {activeTab === 'aliases' && (\n <motion.div\n key=\"aliases\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n <AliasManager\n agent={{\n id: agent.id,\n profile:\n ((agent.metadata as Record<string, unknown> | null)?.profile as\n | string\n | undefined) ?? 'default',\n }}\n />\n </motion.div>\n )}\n\n {activeTab === 'backup' && agent.tunnelUrl && (\n <motion.div\n key=\"backup\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <AgentBackupTab agentId={agent.id} profile={activeProfile} />\n </motion.div>\n )}\n\n {activeTab === 'backup' && !agent.tunnelUrl && (\n <motion.div\n key=\"backup-no-tunnel\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <Card className=\"p-6 text-center text-text-secondary\">\n <Database className=\"size-8 mx-auto mb-2 text-text-muted\" />\n <p>\n {tr(\n 'agentDetails.backupRequiresTunnelAndApiKey',\n 'Agent tunnel URL and API key are required for backup management.'\n )}\n </p>\n <p className=\"text-sm mt-1\">\n {tr(\n 'agentDetails.configureConnectionInOverview',\n 'Configure the agent connection in the Overview tab.'\n )}\n </p>\n </Card>\n </motion.div>\n )}\n {/* PR-8 iframe-mounted tab body. Mirrors the VibeDetailsPage\n implementation; both pages currently use the same helper\n component (inline in VibeDetailsPage), but for now we\n duplicate the mount logic here for clarity. PR-11+ unifies\n via `useMountTabStrip`. */}\n {enableIframeHost &&\n (() => {\n const active: DiscoveredContribution | undefined = iframeContributions.data.find(\n (c) => c.contribution.id === activeTab\n );\n if (!active || !agent) return null;\n return (\n <motion.div\n key={`plugin-${active.contribution.id}`}\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n <Card>\n <div className=\"p-0 h-[600px]\">\n <PluginIframeMount\n contribution={active}\n tunnel={active.tunnel}\n restPaths={\n active.capabilities.restPaths.length > 0\n ? active.capabilities.restPaths\n : [`/ui/${active.pluginKey}`]\n }\n context={{ agentId: agent.id }}\n agentId={agent.id}\n profile={active.tunnel.profile}\n theme={{ colorMode: 'light', tokens: {} }}\n locale=\"en\"\n featureFlags={{}}\n hostVersion=\"1.0.0\"\n />\n </div>\n </Card>\n </motion.div>\n );\n })()}\n </AnimatePresence>\n\n {/* PR-10 \"+ Add tab\" picker. */}\n {enableIframeHost && agent && (\n <AddTabDialog\n isOpen={addTabOpen}\n onClose={() => setAddTabOpen(false)}\n mountPoint=\"agent.detailTab\"\n agentId={agent.id}\n profile={activeProfile ?? 'default'}\n onInstalled={() => {\n void iframeContributions.refetch();\n }}\n />\n )}\n\n {/* Configure Agent Modal */}\n {showConfigModal && (\n <div className=\"fixed inset-0 bg-bg-overlay flex items-center justify-center z-[100] p-4\">\n <div className=\"bg-bg-surface rounded-lg w-full max-w-lg max-h-[90vh] flex flex-col\">\n <div className=\"px-6 pt-6 pb-3 border-b border-border-default flex-shrink-0\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('agentDetails.configure', 'Configure')} {agent.name}\n </h2>\n </div>\n <div className=\"px-6 py-4 overflow-y-auto flex-1\">\n {configError && (\n <div className=\"mb-4 p-3 bg-status-error-bg text-status-error-text rounded-md text-sm\">\n {configError}\n </div>\n )}\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('webhooks.name', 'Name')}\n </label>\n <input\n aria-label=\"control\"\n ref={agentNameRef}\n type=\"text\"\n defaultValue={agent.name}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('analytics.platform', 'Platform')}\n </label>\n <input\n aria-label=\"control\"\n type=\"text\"\n value={`${agent.platform} / ${agent.architecture}`}\n disabled\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-secondary\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('agentDetails.version', 'Version')}\n </label>\n <input\n aria-label=\"control\"\n type=\"text\"\n value={agent.version}\n disabled\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-secondary\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('agentDetails.tunnelUrl', 'Tunnel URL')}\n </label>\n <input\n aria-label=\"control\"\n ref={agentTunnelUrlRef}\n type=\"text\"\n defaultValue={agent.tunnelUrl ?? ''}\n placeholder={tr(\n 'agentDetails.tunnelUrlPlaceholder',\n 'https://xxx.trycloudflare.com'\n )}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary font-mono text-sm\"\n />\n <p className=\"mt-1 text-xs text-text-muted\">\n {tr(\n 'agentDetails.tunnelUrlHint',\n 'The public URL for accessing this agent remotely. Auto-updates when gateway auth is configured.'\n )}\n </p>\n </div>\n {/* F4 Wave B: API key rotation is no longer part of\n `updateVibecontrolsAgent`. The field was dropped from\n `UpdateVibecontrolsAgentInput`. A dedicated rotate-key\n svc mutation is the path forward; until it lands, this\n field is intentionally omitted. */}\n <div>\n <div className=\"flex items-center gap-1.5 mb-1\">\n <label\n htmlFor=\"agentdetailspage-58\"\n className=\"text-sm font-medium text-text-primary\"\n >\n AI Context\n </label>\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setShowAiContextInfo((v) => !v)}\n className=\"p-0.5 rounded-full text-text-muted hover:text-text-secondary transition-colors\"\n aria-label=\"What is AI Context?\"\n >\n <Info className=\"size-3.5\" />\n </button>\n {showAiContextInfo && (\n <>\n <div\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (() => setShowAiContextInfo(false))();\n }\n }}\n className=\"fixed inset-0 z-10\"\n onClick={() => setShowAiContextInfo(false)}\n />\n <div className=\"absolute left-0 top-6 z-20 w-72 bg-bg-elevated border border-border-default rounded-lg shadow-xl p-3 text-xs text-text-secondary space-y-1.5\">\n <p className=\"font-semibold text-text-primary\">What is AI Context?</p>\n <p>\n A short description (Markdown supported) that AI tools running on this\n agent will read to understand the environment — e.g. what the machine\n is for, what services it runs, or any constraints to follow.\n </p>\n <p className=\"text-text-muted\">\n Example: &quot;Production billing server. Do not modify files outside\n /src. Node 20, Docker installed.&quot;\n </p>\n </div>\n </>\n )}\n </div>\n </div>\n <textarea\n id=\"agentdetailspage-58\"\n aria-label=\"e.g. This agent runs on the billing server. Node 20, Docker installed. Do not modify files outside /src.\"\n ref={agentAiContextRef}\n defaultValue={agent.aiContext ?? ''}\n rows={4}\n placeholder=\"e.g. This agent runs on the billing server. Node 20, Docker installed. Do not modify files outside /src.\"\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary text-sm\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('agentDetails.metadataLabel', 'Metadata (JSON)')}\n </label>\n <textarea\n aria-label=\"control\"\n ref={agentMetadataRef}\n defaultValue={agent.metadata ? JSON.stringify(agent.metadata, null, 2) : '{}'}\n rows={4}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary font-mono text-sm\"\n />\n </div>\n </div>\n </div>\n <div className=\"px-6 py-4 border-t border-border-default flex-shrink-0 flex flex-wrap justify-end gap-3\">\n <button\n type=\"button\"\n onClick={() => setShowConfigModal(false)}\n disabled={configLoading}\n className=\"px-4 py-2 text-text-primary hover:bg-bg-sunken rounded-md transition-colors disabled:opacity-50\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n onClick={handleSubmitConfig}\n disabled={configLoading}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {configLoading\n ? tr('agentDetails.saving', 'Saving...')\n : tr('agentDetails.saveConfiguration', 'Save Configuration')}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Create Session Modal */}\n {showSessionModal && (\n <div\n className=\"fixed inset-0 bg-bg-overlay flex items-center justify-center z-[100] p-4\"\n onClick={() => {\n if (!sessionCreateLoading) setShowSessionModal(false);\n }}\n >\n <div\n className=\"bg-bg-surface rounded-lg p-6 w-full max-w-lg\"\n data-testid=\"create-session-modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"create-session-title\"\n onClick={(e) => e.stopPropagation()}\n >\n <h2 id=\"create-session-title\" className=\"text-lg font-semibold text-text-primary mb-4\">\n {tr('agentDetails.newSessionFor', 'New Session for')} {agent.name}\n </h2>\n {sessionCreateError && (\n <div className=\"mb-4 p-3 bg-status-error-bg text-status-error-text rounded-md text-sm\">\n {sessionCreateError}\n </div>\n )}\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibeDetails.sessionName', 'Session Name')}\n </label>\n <input\n data-testid=\"session-name-input\"\n ref={sessionNameRef}\n type=\"text\"\n placeholder={tr('vibeDetails.sessionNamePlaceholder', 'dev-terminal')}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('sessions.filterType', 'Type')}\n </label>\n <select\n ref={sessionTypeRef}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary\"\n >\n <option value=\"TERMINAL\">{tr('sessions.typeTerminal', 'Terminal')}</option>\n <option value=\"TMUX\">{tr('sessions.typeTmux', 'TMUX')}</option>\n <option value=\"SSH\">{tr('sessions.typeSsh', 'SSH')}</option>\n <option value=\"SCRIPT\">{tr('sessions.typeScript', 'Script')}</option>\n <option value=\"CUSTOM\">{tr('sessions.typeCustom', 'Custom')}</option>\n </select>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('sessions.command', 'Command')}\n </label>\n <input\n ref={sessionCommandRef}\n type=\"text\"\n placeholder={tr('vibeDetails.sessionCommandPlaceholder', 'bash')}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibeDetails.workingDirectory', 'Working Directory')}\n </label>\n <input\n ref={sessionWorkDirRef}\n type=\"text\"\n placeholder=\"/home/user\"\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder\"\n />\n </div>\n </div>\n <div className=\"flex flex-col sm:flex-row justify-end gap-3 mt-6\">\n <button\n onClick={() => setShowSessionModal(false)}\n disabled={sessionCreateLoading}\n className=\"px-4 py-2 text-text-primary hover:bg-bg-sunken rounded-md transition-colors disabled:opacity-50\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n <button\n data-testid=\"create-session-submit\"\n onClick={handleSubmitCreateSession}\n disabled={sessionCreateLoading}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {sessionCreateLoading\n ? tr('sessions.creating', 'Creating...')\n : tr('sessions.createSession', 'Create Session')}\n </button>\n </div>\n </div>\n </div>\n )}\n\n <QuotaExhaustedDialog\n isOpen={showQuotaExhausted}\n onClose={() => setShowQuotaExhausted(false)}\n onConfirm={() => {\n setShowQuotaExhausted(false);\n navigate('/billing');\n }}\n title={getQuotaDialogContent(quotaKind).title}\n message={getQuotaDialogContent(quotaKind).message}\n />\n </MotionPage>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AgentDetailsPage.js","names":[],"sources":["../../src/pages/AgentDetailsPage.tsx"],"sourcesContent":["import { useState, useRef, useEffect, useCallback, useMemo } from 'react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { PermissionButton } from '@burdenoff/fe-libs/shared/components';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { isNative, nativeCopyText, nativeToast } from '../utils/nativeBridge';\nimport { EntityTagPicker } from '@/components/shared/EntityTagPicker';\nimport { PageSkeleton } from '@/components/shared/PageSkeleton';\nimport { useParams } from 'react-router-dom';\nimport { MotionPage } from '@burdenoff/fe-libs/shared/motion';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport { useVibeControlsStore } from '@/store/vibeControlsStore';\nimport { AgentBackupTab } from '@/components/agents/backup/AgentBackupTab';\nimport { ConnectionLogPanel } from '@/components/agents/ConnectionLogPanel';\nimport { AliasManager } from '@/components/aliases/AliasManager';\nimport {\n ArrowLeft,\n Database,\n Server,\n Play,\n Square,\n Settings,\n Trash2,\n Terminal,\n Zap,\n Cpu,\n HardDrive,\n Clock,\n CheckCircle2,\n RefreshCw,\n Eye,\n EyeOff,\n Key,\n Copy,\n Check,\n Info,\n Puzzle,\n Download,\n X,\n Loader2,\n Shield,\n Link2,\n Unlink,\n Search,\n Monitor,\n FileText,\n Tag,\n ScrollText,\n Command,\n Users,\n Plus,\n Edit3,\n Bot,\n} from 'lucide-react';\nimport {\n PageHeader,\n Card,\n StatusBadge,\n EmptyState,\n ErrorState,\n QuotaExhaustedDialog,\n} from '@/components/shared';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n PluginUIPanel,\n type UIPluginOption,\n OpenInBrowserEditorButton,\n AgentStatusBadge,\n} from '@/components/agents';\nimport { deriveAgentStatus, type AgentHealthProbe } from '@/utils/agentStatus';\nimport { LogViewer } from '@/components/logs/LogViewer';\nimport { useActiveAgentProfile } from '@/hooks/useActiveAgentProfile';\nimport { ProfilesPanel } from '@/components/agent-manager';\nimport { NotesTabPanel } from '@/components/notes';\nimport { useVibeControls, useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useQueryBackedTab } from '@/hooks/useQueryBackedTab';\nimport {\n isQuotaExhaustedError,\n markQuotaHandledLocally,\n getQuotaDialogContent,\n} from '@/utils/quotaUtils';\nimport { useFeatureFlagDetails } from '@burdenoff/fe-libs/shared/feature-flags';\nimport {\n PluginIframe,\n type DiscoveredContribution,\n type MountTunnel,\n usePluginContributions,\n} from '@burdenoff/fe-libs/shared/plugins';\nimport { mintScopedIframeToken } from '@/services/iframeToken';\nimport { AddTabDialog } from '@/components/plugins/AddTabDialog';\nimport { PluginIframeMount } from '@/components/plugins/PluginIframeMount';\nimport {\n useGetAgentQuery,\n useUpdateAgentMutation,\n useDeleteAgentMutation,\n useCheckSessionHealthMutation,\n useAgentPluginsLazyQuery,\n useInstallAgentPluginMutation,\n useRemoveAgentPluginMutation,\n useSetupAgentGatewayAuthMutation,\n usePushAgentGatewayAuthMutation,\n useVibecontrolsAgentHealthProbesQuery,\n useVibecontrolsAgentHealthProbeStreamSubscription,\n useStartVibecontrolsAgentMutation,\n useStopVibecontrolsAgentMutation,\n useCreateSessionMutation,\n useAgentSecretRevealLazyQuery,\n} from '@/generated/wspace-operations';\n\n// ─── Gateway Auth Card ─────────────────────────────────────────────────────\n// Shows whether the agent has a linked OAuth2 app for gateway communication.\n// Allows creating a new app via auth-svc and pushing credentials to the agent.\n\ninterface GatewayAuthAgent {\n id: string;\n name: string;\n appId?: string | null;\n appClientId?: string | null;\n tunnelUrl?: string | null;\n metadata?: Record<string, unknown> | null;\n}\n\nfunction GatewayAuthCard({ agent, onUpdate }: { agent: GatewayAuthAgent; onUpdate: () => void }) {\n const { t } = useI18n();\n const [updateAgent] = useUpdateAgentMutation();\n const [setupGatewayAuth] = useSetupAgentGatewayAuthMutation();\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [showSecret, setShowSecret] = useState(false);\n const [oneTimeSecret, setOneTimeSecret] = useState<string | null>(null);\n const [secretCopied, setSecretCopied] = useState(false);\n const [clientIdCopied, setClientIdCopied] = useState(false);\n const [unlinking, setUnlinking] = useState(false);\n\n const hasApp = Boolean(agent.appId && agent.appClientId);\n\n const tr = (key: string, fallback: string, params?: Record<string, string | number>): string => {\n const translated = t(key, params);\n const template = translated === key ? fallback : translated;\n\n if (!params) return template;\n\n return Object.entries(params).reduce(\n (acc, [paramKey, paramValue]) => acc.replace(`{{${paramKey}}}`, String(paramValue)),\n template\n );\n };\n const devportalAppId = (agent.metadata as Record<string, unknown> | null)\n ?.devportalApplicationId as string | undefined;\n\n // Single backend-orchestrated mutation: creates auth-svc app + devportal app + pushes creds to agent\n const handleSetupGatewayAuth = async () => {\n setLoading(true);\n setError(null);\n\n try {\n const { data } = await setupGatewayAuth({\n variables: {\n input: {\n agentId: agent.id,\n },\n },\n });\n\n const result = data?.setupAgentGatewayAuth;\n if (!result) {\n throw new Error(\n tr(\n 'agentDetails.gatewayAuthNoResultError',\n 'No result returned from setupAgentGatewayAuth'\n )\n );\n }\n\n // Show the one-time secret\n setOneTimeSecret(result.clientSecret);\n\n // Show warning if push to agent failed (creds still created)\n if (result.error) {\n setError(result.error);\n }\n\n onUpdate();\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : tr('agentDetails.failedSetupGatewayAuth', 'Failed to set up gateway auth')\n );\n } finally {\n setLoading(false);\n }\n };\n\n // Unlink the app (remove appId/appClientId from agent record)\n const handleUnlink = async () => {\n if (\n !window.confirm(\n tr(\n 'agentDetails.confirmUnlinkOauthApp',\n 'Remove the linked OAuth app from this agent? The app will still exist in auth-svc.'\n )\n )\n )\n return;\n setUnlinking(true);\n setError(null);\n try {\n await updateAgent({\n variables: {\n id: agent.id,\n input: { appId: null, appClientId: null },\n },\n });\n setOneTimeSecret(null);\n onUpdate();\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : tr('agentDetails.failedUnlinkApp', 'Failed to unlink app')\n );\n } finally {\n setUnlinking(false);\n }\n };\n\n const handleCopyClientId = async () => {\n if (!agent.appClientId) return;\n try {\n await nativeCopyText(agent.appClientId);\n if (isNative()) void nativeToast('Copied');\n setClientIdCopied(true);\n setTimeout(() => setClientIdCopied(false), 2000);\n } catch {\n // Non-HTTPS fallback\n }\n };\n\n const handleCopySecret = async () => {\n if (!oneTimeSecret) return;\n try {\n await nativeCopyText(oneTimeSecret);\n if (isNative()) void nativeToast('Secret copied');\n setSecretCopied(true);\n setTimeout(() => setSecretCopied(false), 2000);\n } catch {\n // Non-HTTPS fallback\n }\n };\n\n return (\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Shield className=\"size-5\" />\n {tr('agentDetails.gatewayAuthTitle', 'Gateway Auth (OAuth2)')}\n </h3>\n </div>\n <div className=\"p-4 space-y-3\">\n {error && (\n <div className=\"flex items-center gap-2 p-3 bg-status-error-bg text-status-error-text rounded-md text-sm\">\n <X className=\"size-4 flex-shrink-0\" />\n <span className=\"flex-1\">{error}</span>\n <button\n type=\"button\"\n onClick={() => setError(null)}\n className=\"flex-shrink-0 p-0.5 hover:bg-status-error-text/10 rounded\"\n >\n <X className=\"size-3.5\" />\n </button>\n </div>\n )}\n\n {hasApp ? (\n <>\n {/* Linked app info */}\n <div className=\"flex items-start gap-3\">\n <div className=\"size-8 rounded-lg bg-status-success-bg flex items-center justify-center flex-shrink-0 mt-0.5\">\n <Link2 className=\"size-4 text-status-success-text\" />\n </div>\n <div className=\"flex-1 min-w-0 space-y-2\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tr('agentDetails.linkedToOauthApp', 'Linked to OAuth App')}\n </p>\n <p className=\"text-xs text-text-muted\">\n {tr(\n 'agentDetails.gatewayAuthLinkedDescription',\n 'This agent can authenticate with the API gateway using Client Credentials.'\n )}\n </p>\n </div>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3\">\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">\n {tr('agentDetails.clientId', 'Client ID')}\n </p>\n <div className=\"flex items-center gap-2\">\n <code className=\"text-xs font-mono text-text-primary bg-bg-sunken px-2 py-1 rounded truncate block flex-1\">\n {agent.appClientId}\n </code>\n <button\n type=\"button\"\n onClick={handleCopyClientId}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n title={tr('agentDetails.copyClientId', 'Copy Client ID')}\n >\n {clientIdCopied ? (\n <Check className=\"size-3.5 text-status-success-text\" />\n ) : (\n <Copy className=\"size-3.5 text-text-secondary\" />\n )}\n </button>\n </div>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">\n {tr('agentDetails.appId', 'App ID')}\n </p>\n <code className=\"text-xs font-mono text-text-muted bg-bg-sunken px-2 py-1 rounded truncate block\">\n {agent.appId}\n </code>\n </div>\n </div>\n </div>\n </div>\n\n {/* One-time secret display */}\n {oneTimeSecret && (\n <div className=\"p-3 bg-status-warning-bg/20 border border-status-warning-text/20 rounded-lg space-y-2\">\n <p className=\"text-sm font-medium text-status-warning-text\">\n {tr('agentDetails.clientSecretOneTimeTitle', 'Client Secret (one-time display)')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'agentDetails.clientSecretOneTimeDescription',\n \"This secret has been automatically sent to the agent. Save it now if you need it — it won't be shown again.\"\n )}\n </p>\n <div className=\"flex items-center gap-2\">\n <code className=\"text-xs font-mono text-text-primary bg-bg-sunken px-2 py-1 rounded flex-1 truncate\">\n {showSecret ? oneTimeSecret : '\\u2022'.repeat(32)}\n </code>\n <button\n type=\"button\"\n onClick={() => setShowSecret(!showSecret)}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n >\n {showSecret ? (\n <EyeOff className=\"size-3.5 text-text-secondary\" />\n ) : (\n <Eye className=\"size-3.5 text-text-secondary\" />\n )}\n </button>\n <button\n type=\"button\"\n onClick={handleCopySecret}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n >\n {secretCopied ? (\n <Check className=\"size-3.5 text-status-success-text\" />\n ) : (\n <Copy className=\"size-3.5 text-text-secondary\" />\n )}\n </button>\n </div>\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex items-center gap-2\">\n {devportalAppId && (\n <a\n href={`/devportal/apps/${devportalAppId}`}\n className=\"flex items-center gap-2 px-3 py-1.5 text-xs text-action-primary-bg bg-action-primary-bg/10 hover:bg-action-primary-bg/20 rounded-md transition-colors\"\n >\n <Monitor className=\"size-3\" />\n {tr('agentDetails.viewInDeveloperPortal', 'View in Developer Portal')}\n </a>\n )}\n {/* Re-push: rotates the OAuth secret on auth-svc + POSTs the\n fresh creds to the agent's /api/agent/gateway-auth so a\n degraded agent stuck in awaiting-config (DB never opened,\n no session provider registered) can recover without\n unlinking + re-creating the app. Backend already handles\n the rotate path inside setupGatewayAuth when an app is\n already linked. */}\n <button\n type=\"button\"\n onClick={handleSetupGatewayAuth}\n disabled={loading}\n className=\"flex items-center gap-2 px-3 py-1.5 text-xs text-action-primary-bg bg-action-primary-bg/10 hover:bg-action-primary-bg/20 rounded-md transition-colors disabled:opacity-50\"\n title={tr(\n 'agentDetails.repushCredentialsTitle',\n 'Rotate the OAuth secret and push it to the agent. Use this if the agent shows degraded with \"boot state awaiting-config\".'\n )}\n >\n {loading ? (\n <Loader2 className=\"size-3 animate-spin\" />\n ) : (\n <RefreshCw className=\"size-3\" />\n )}\n {tr('agentDetails.repushCredentials', 'Re-push credentials')}\n </button>\n <button\n type=\"button\"\n onClick={handleUnlink}\n disabled={unlinking}\n className=\"flex items-center gap-2 px-3 py-1.5 text-xs text-status-error-text hover:bg-status-error-bg rounded-md transition-colors disabled:opacity-50\"\n >\n {unlinking ? (\n <Loader2 className=\"size-3 animate-spin\" />\n ) : (\n <Unlink className=\"size-3\" />\n )}\n {tr('agentDetails.unlinkApp', 'Unlink App')}\n </button>\n </div>\n </>\n ) : (\n <>\n {/* No app linked */}\n <div className=\"flex items-start gap-3\">\n <div className=\"size-8 rounded-lg bg-bg-sunken flex items-center justify-center flex-shrink-0 mt-0.5\">\n <Shield className=\"size-4 text-text-muted\" />\n </div>\n <div className=\"flex-1\">\n <p className=\"text-sm font-medium text-text-primary\">\n {tr('agentDetails.noOauthAppLinked', 'No OAuth App Linked')}\n </p>\n <p className=\"text-xs text-text-muted mt-0.5\">\n {tr(\n 'agentDetails.gatewayAuthSetupDescription',\n 'Set up gateway auth to allow this agent to communicate with the API gateways using OAuth2 Client Credentials. This creates an OAuth app, registers it in the Developer Portal, and pushes the credentials to the agent.'\n )}\n </p>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={handleSetupGatewayAuth}\n disabled={loading}\n className=\"flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {loading ? (\n <>\n <Loader2 className=\"size-4 animate-spin\" />\n {tr('agentDetails.settingUp', 'Setting up...')}\n </>\n ) : (\n <>\n <Link2 className=\"size-4\" />\n {tr('agentDetails.setupGatewayAuth', 'Setup Gateway Auth')}\n </>\n )}\n </button>\n </>\n )}\n </div>\n </Card>\n );\n}\n\n// `AgentPluginIframeBody` was the page-local helper that minted a\n// token + rendered an iframe without refresh / error handling. The\n// consolidated logic now lives in `@/components/plugins/PluginIframeMount`.\n\n/**\n * Agent details page - shows comprehensive information about a single agent\n */\nexport function AgentDetailsPage() {\n const { t } = useI18n();\n const { id } = useParams<{ id: string }>();\n const { basePath: basePathProp } = useVibeControls();\n const basePath = basePathProp || '';\n const navigate = useVibeNavigate();\n const { hasPermission, isLoading: permissionsLoading, permissions } = usePermissions();\n\n const tr = useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>): string => {\n const translated = t(key, params);\n const template = translated === key ? fallback : translated;\n\n if (!params) return template;\n\n return Object.entries(params).reduce(\n (acc, [paramKey, paramValue]) => acc.replace(`{{${paramKey}}}`, String(paramValue)),\n template\n );\n },\n [t]\n );\n\n const [updateAgent] = useUpdateAgentMutation({ refetchQueries: ['GetAgent'] });\n // refetchQueries + awaitRefetchQueries make sure the agents list\n // (and the cached initial-data slice the AgentsPage falls back to\n // before the live query loads) drop the deleted row BEFORE we\n // navigate back, so the list doesn't briefly re-render with the\n // gone agent. cache.evict on the normalized entry covers other\n // queries that happen to reference this agent ID.\n const [deleteAgent] = useDeleteAgentMutation({\n refetchQueries: ['ListAgents', 'VibeControlsInitialData'],\n awaitRefetchQueries: true,\n update(cache, _result, { variables }) {\n const id = variables?.id;\n if (!id) return;\n cache.evict({ id: cache.identify({ __typename: 'VibecontrolsAgent', id }) });\n cache.gc();\n },\n });\n const [checkSessionHealth] = useCheckSessionHealthMutation({ refetchQueries: ['GetAgent'] });\n const [startVibecontrolsAgent] = useStartVibecontrolsAgentMutation();\n const [stopVibecontrolsAgent] = useStopVibecontrolsAgentMutation();\n // Per-action in-flight state so the Start/Stop button can show a spinner +\n // disable while the lifecycle call is running (it can take a few seconds to\n // reach the agent over its tunnel).\n const [lifecycleAction, setLifecycleAction] = useState<'start' | 'stop' | null>(null);\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n\n // ── Sync active context ────────────────────────────────────────────────\n const setActiveAgentId = useVibeControlsStore((s) => s.setActiveAgentId);\n useEffect(() => {\n if (id) setActiveAgentId(id);\n }, [id, setActiveAgentId]);\n\n // ── Tab Navigation ───────────────────────────────────────────────────\n type AgentTab =\n | 'overview'\n | 'profiles'\n | 'security'\n | 'plugins'\n | 'sessions'\n | 'logs'\n | 'connection'\n | 'vibes'\n | 'notes'\n | 'aliases'\n | 'backup';\n const agentTabIds: readonly AgentTab[] = [\n 'overview',\n 'profiles',\n 'security',\n 'plugins',\n 'sessions',\n 'logs',\n 'connection',\n 'vibes',\n 'notes',\n 'aliases',\n 'backup',\n ];\n // Active-tab declaration is deferred to after `iframeContributions`\n // (further down in this component) so the valid id set can include\n // both the static `agentTabIds` AND discovered plugin ids — see\n // the same pattern in VibeDetailsPage.\n\n // Configuration modal state\n const [showConfigModal, setShowConfigModal] = useState(false);\n const [configError, setConfigError] = useState<string | null>(null);\n const [configLoading, setConfigLoading] = useState(false);\n const [successMessage, setSuccessMessage] = useState<string | null>(null);\n const [showAiContextInfo, setShowAiContextInfo] = useState(false);\n\n // Inline rename state — lets operators rename the agent from the page\n // header without opening the full Configure modal. Click the pencil →\n // input swaps in. Cancel reverts to the stored name; Save fires the\n // existing UpdateAgent mutation and refetches GetAgent so every reader\n // on the page reflects the new name in the same render.\n const [renaming, setRenaming] = useState(false);\n const [renameValue, setRenameValue] = useState('');\n const [renameSaving, setRenameSaving] = useState(false);\n const [renameError, setRenameError] = useState<string | null>(null);\n const renameInputRef = useRef<HTMLInputElement>(null);\n\n // Config form refs\n const agentNameRef = useRef<HTMLInputElement>(null);\n const agentTunnelUrlRef = useRef<HTMLInputElement>(null);\n const agentAiContextRef = useRef<HTMLTextAreaElement>(null);\n const agentMetadataRef = useRef<HTMLTextAreaElement>(null);\n const [showApiKey, setShowApiKey] = useState(false);\n const [apiKeyCopied, setApiKeyCopied] = useState(false);\n // F4 Wave B: the long-lived agent secret is no longer prefetched with\n // every GetAgent. Reveal lazily on operator click; svc-side RBAC +\n // audit gates the read.\n const [revealedApiKey, setRevealedApiKey] = useState<string | null>(null);\n const [revealLoading, setRevealLoading] = useState(false);\n const [revealError, setRevealError] = useState<string | null>(null);\n const [fetchAgentSecret] = useAgentSecretRevealLazyQuery({ fetchPolicy: 'network-only' });\n\n // Create Session modal state\n const [showSessionModal, setShowSessionModal] = useState(false);\n const [sessionCreateError, setSessionCreateError] = useState<string | null>(null);\n const [sessionCreateLoading, setSessionCreateLoading] = useState(false);\n const sessionNameRef = useRef<HTMLInputElement>(null);\n const sessionTypeRef = useRef<HTMLSelectElement>(null);\n const sessionCommandRef = useRef<HTMLInputElement>(null);\n const sessionWorkDirRef = useRef<HTMLInputElement>(null);\n const [createSession] = useCreateSessionMutation({\n refetchQueries: ['GetAgent', 'ListSessions'],\n });\n\n // Dismiss the Create Session modal on Escape, matching the a11y contract\n // for role=\"dialog\" / aria-modal=\"true\".\n useEffect(() => {\n if (!showSessionModal) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && !sessionCreateLoading) setShowSessionModal(false);\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [showSessionModal, sessionCreateLoading]);\n\n // Move keyboard focus to the session name input when the modal opens —\n // satisfies the aria-modal contract so users tabbing don't land on\n // elements behind the overlay. rAF defers past the mount paint.\n useEffect(() => {\n if (!showSessionModal) return;\n const id = requestAnimationFrame(() => sessionNameRef.current?.focus());\n return () => cancelAnimationFrame(id);\n }, [showSessionModal]);\n\n // Fetch agent by ID from GraphQL API\n const { data, loading, error, refetch } = useGetAgentQuery({\n variables: { id: id || '' },\n skip: !id,\n fetchPolicy: 'cache-and-network',\n });\n\n // Get agent from response\n const agent = data?.vibecontrolsAgent;\n\n // Live deep-health probe — same source the agent cards use, so the detail\n // page's status badge matches the list. Without this the badge derived from\n // the sticky `isActive` flag, showing \"Active\" for an agent the card (and\n // reality) reports DEGRADED/stopped. Workspace-scoped query primes the cache;\n // the subscription pushes sub-second updates.\n const probeQuery = useVibecontrolsAgentHealthProbesQuery({\n fetchPolicy: 'cache-and-network',\n nextFetchPolicy: 'cache-first',\n notifyOnNetworkStatusChange: true,\n skip: !id,\n pollInterval: 30_000,\n });\n const { data: probeStreamData } = useVibecontrolsAgentHealthProbeStreamSubscription({\n skip: !id,\n });\n const probesLoading = probeQuery.data === undefined && probeStreamData === undefined;\n const probesById = useMemo(() => {\n const m = new Map<string, AgentHealthProbe>();\n const probes =\n probeStreamData?.vibecontrolsAgentHealthProbeStream ??\n probeQuery.data?.vibecontrolsAgentHealthProbes ??\n [];\n for (const p of probes) {\n m.set(p.agentId, { agentId: p.agentId, healthy: p.healthy, errorMessage: p.errorMessage });\n }\n return m;\n }, [probeQuery.data, probeStreamData]);\n\n // Single source of truth for the agent's displayed status — live /health/ready\n // probe + lifecycleState, NOT the sticky isActive flag. Drives both the status\n // badge and the Start/Stop toggle so they always agree with the agent cards.\n const derivedStatus = useMemo(\n () =>\n agent\n ? deriveAgentStatus(\n {\n id: agent.id,\n isActive: agent.isActive,\n metadata: agent.metadata as Record<string, unknown> | null,\n },\n probesById,\n { probesLoading }\n )\n : 'REGISTERING',\n [agent, probesById, probesLoading]\n );\n\n // Only offer Start when the agent is known NOT to be running (STOPPED or\n // OFFLINE). For ACTIVE — and also DEGRADED / REGISTERING, where the process\n // can still be live during probe warm-up or transport errors — show Stop, so\n // an operator can always stop a live-but-unhealthy agent instead of firing a\n // start that fails as \"already running\".\n const showStartButton = derivedStatus === 'STOPPED' || derivedStatus === 'OFFLINE';\n\n // Phase 5B — resolve the active profile name for this agent. Used to\n // build canonical `/api/profiles/<name>/<rest>` paths in child tabs\n // (LogViewer, OpenInBrowserEditorButton, AgentBackupTab).\n const { active: activeProfile } = useActiveAgentProfile(agent?.id ?? null);\n\n // Plugins are agent-wide (BOFF-2612): the npm package install and the\n // \"available\" catalog are already shared across all profiles on the\n // agent; only plugin DATA (notes/sessions/etc.) stays per-profile.\n // No per-profile gate on Install/Remove anymore.\n\n // ── iframe-mount discovery (PR-8) ────────────────────────────────────\n // Gated by `vibes.tabs.iframe-host` (same flag the VibeDetailsPage\n // uses — one switch for both surfaces). When on, the host queries the\n // agent's tunnel for contributions targeting the `agent.detailTab`\n // mount point and renders them as additional tabs.\n const iframeHostFlag = useFeatureFlagDetails('vibes.tabs.iframe-host');\n const enableIframeHost = iframeHostFlag?.value === true;\n\n const iframePluginTunnels = useMemo<MountTunnel[]>(() => {\n if (!enableIframeHost || !agent?.tunnelUrl) return [];\n const agentIdForToken = agent.id;\n const profile = activeProfile ?? 'default';\n return [\n {\n tunnelUrl: agent.tunnelUrl,\n profile,\n label: agent.name ?? agent.id,\n mintIframeToken: async ({ pathPrefixes }) => {\n return mintScopedIframeToken(agentIdForToken, profile, pathPrefixes);\n },\n },\n ];\n }, [enableIframeHost, agent?.id, agent?.tunnelUrl, agent?.name, activeProfile]);\n\n const iframeContributions = usePluginContributions(iframePluginTunnels, {\n mountPoint: 'agent.detailTab',\n enabled: enableIframeHost && iframePluginTunnels.length > 0,\n });\n\n // Active-tab id set = static agentTabIds ∪ discovered plugin ids.\n // See VibeDetailsPage for the rationale.\n const validAgentTabIds = useMemo<readonly string[]>(() => {\n const fromContribs = iframeContributions.data\n .filter((c) => c.contribution.mountPoint === 'agent.detailTab')\n .map((c) => c.contribution.id);\n return [...(agentTabIds as readonly string[]), ...fromContribs];\n }, [iframeContributions.data, agentTabIds]);\n const [activeTab, setActiveTab] = useQueryBackedTab<string>(validAgentTabIds, 'overview');\n\n const [addTabOpen, setAddTabOpen] = useState(false);\n\n // On mount, run a health check to sync stale session states with agent reality\n const healthCheckRanRef = useRef(false);\n useEffect(() => {\n if (agent && !healthCheckRanRef.current) {\n healthCheckRanRef.current = true;\n checkSessionHealth().catch(() => {\n // Best-effort — don't block the page if health check fails\n });\n }\n }, [agent, checkSessionHealth]);\n\n // Auto-recovery for agents stuck in `awaiting-config`.\n //\n // Symptom (why this exists): a freshly-booted agent loads its plugin\n // catalog but defers `onServerStart` — and therefore session-provider\n // registration — until the dashboard POSTs OAuth credentials to\n // /api/agent/gateway-auth. If the initial push failed (network blip,\n // auth-svc transient, page closed mid-flight) the agent stays stuck\n // and the badge reads \"Degraded — no session provider registered\".\n //\n // Fix: when the page loads and finds (a) an agent linked to an OAuth\n // app already, (b) reachable via tunnelUrl + agentApiKey, and (c)\n // unhealthy, fire `pushAgentGatewayAuth` once. The mutation re-pushes\n // the existing OAuth credentials to the agent — idempotent and safe;\n // the agent will finalize and register providers on receipt.\n // Self-heals the page without a manual \"Re-push credentials\" click.\n const [pushGatewayAuth] = usePushAgentGatewayAuthMutation();\n const autoRecoveryRanRef = useRef(false);\n useEffect(() => {\n if (!agent || autoRecoveryRanRef.current) return;\n const hasApp = Boolean(agent.appId && agent.appClientId);\n const reachable = Boolean(agent.tunnelUrl);\n if (!hasApp || !reachable) return;\n autoRecoveryRanRef.current = true;\n pushGatewayAuth({ variables: { input: { agentId: agent.id } } })\n .then(() => {\n // Re-fetch so badge + reason update once the agent finalizes.\n refetch().catch(() => {\n /* badge will refresh on next heartbeat */\n });\n })\n .catch(() => {\n // Silent — manual \"Re-push credentials\" button remains available.\n });\n }, [agent, pushGatewayAuth, refetch]);\n\n // ── Plugin Management (via backend GraphQL proxy) ──────────────────\n interface InstalledPlugin {\n packageName: string;\n pluginName: string;\n version: string;\n installedAt: string;\n loaded: boolean;\n description?: string;\n tags?: string[];\n isCore: boolean;\n cliCommand?: string;\n apiPrefix?: string;\n hasUI: boolean;\n hasCliSetup: boolean;\n hasServerStart: boolean;\n hasServerStop: boolean;\n hasServerReady: boolean;\n hasProviders: boolean;\n }\n interface AvailablePlugin {\n packageName: string;\n name: string;\n description: string;\n version: string;\n tags: string[];\n installed: boolean;\n }\n\n const [installedPlugins, setInstalledPlugins] = useState<InstalledPlugin[]>([]);\n const [availablePlugins, setAvailablePlugins] = useState<AvailablePlugin[]>([]);\n const [pluginsLoading, setPluginsLoading] = useState(true);\n const [pluginActionLoading, setPluginActionLoading] = useState<string | null>(null);\n const [pluginError, setPluginError] = useState<string | null>(null);\n const [showQuotaExhausted, setShowQuotaExhausted] = useState(false);\n // Which quota the open dialog is reporting on. The plugin-install flow\n // opens the same dialog and was here first, so it's the default.\n const [quotaKind, setQuotaKind] = useState<'plugin' | 'session'>('plugin');\n // Tracks the last (agent, profile) pair we fetched plugins for, so a\n // profile switch re-fetches the profile-scoped plugin list instead of\n // showing the previous profile's plugins.\n const pluginsFetchedRef = useRef<string | null>(null);\n\n // ── Plugin Sub-Tabs & Search ──────────────────────────────────────\n type PluginSubTab = 'installed' | 'available' | 'store' | 'ui-plugins';\n const [pluginSubTab, setPluginSubTab] = useState<PluginSubTab>('installed');\n const [pluginSearchQuery, setPluginSearchQuery] = useState('');\n\n // ── Store Plugins ─────────────────────────────────────────────────\n type StoreEntitlement = {\n id: string;\n productId: string;\n licenseKey: string | null;\n product: {\n id: string;\n name: string;\n slug: string;\n icon: string | null;\n description: string | null;\n manifest: Record<string, unknown> | null;\n } | null;\n };\n const [storePlugins, setStorePlugins] = useState<StoreEntitlement[]>([]);\n const [storePluginsLoading, setStorePluginsLoading] = useState(false);\n const [storePluginsError, setStorePluginsError] = useState<string | null>(null);\n const [storeInstallingId, setStoreInstallingId] = useState<string | null>(null);\n\n // Backend-proxied plugin operations\n const [fetchAgentPlugins] = useAgentPluginsLazyQuery();\n const [installPluginMutation] = useInstallAgentPluginMutation();\n const [removePluginMutation] = useRemoveAgentPluginMutation();\n\n const fetchPlugins = useCallback(async () => {\n if (!agent?.id) return;\n setPluginsLoading(true);\n setPluginError(null);\n try {\n const { data } = await fetchAgentPlugins({\n variables: { agentId: agent.id, profile: activeProfile },\n });\n const result = data?.agentPlugins;\n if (result) {\n const installed = (result.installed || []).map(\n (p: {\n packageName: string;\n pluginName: string;\n version: string;\n installedAt?: string | null;\n loaded: boolean;\n description?: string | null;\n tags?: (string | null)[] | null;\n isCore: boolean;\n cliCommand?: string | null;\n apiPrefix?: string | null;\n hasUI: boolean;\n hasCliSetup: boolean;\n hasServerStart: boolean;\n hasServerStop: boolean;\n hasServerReady: boolean;\n hasProviders: boolean;\n }) => ({\n packageName: p.packageName,\n pluginName: p.pluginName,\n version: p.version,\n installedAt: p.installedAt || '',\n loaded: p.loaded,\n description: p.description ?? undefined,\n tags: (p.tags?.filter(Boolean) as string[]) ?? undefined,\n isCore: p.isCore,\n cliCommand: p.cliCommand ?? undefined,\n apiPrefix: p.apiPrefix ?? undefined,\n hasUI: p.hasUI,\n hasCliSetup: p.hasCliSetup,\n hasServerStart: p.hasServerStart,\n hasServerStop: p.hasServerStop,\n hasServerReady: p.hasServerReady,\n hasProviders: p.hasProviders,\n })\n );\n const available = (result.available || []).map(\n (p: {\n packageName: string;\n name: string;\n description: string;\n version: string;\n tags: string[];\n installed: boolean;\n }) => ({\n packageName: p.packageName,\n name: p.name,\n description: p.description,\n version: p.version,\n tags: [...p.tags],\n installed: p.installed,\n })\n );\n setInstalledPlugins(installed);\n setAvailablePlugins(available);\n if (result.error) {\n setPluginError(result.error);\n }\n }\n } catch {\n // Agent unreachable — show error state\n setPluginError('Agent unreachable — unable to fetch plugin list');\n } finally {\n setPluginsLoading(false);\n }\n }, [agent?.id, fetchAgentPlugins, activeProfile]);\n\n // Attempt to fetch live plugins when agent data loads.\n // If the agent is unreachable, an error state is shown instead of fake data.\n useEffect(() => {\n if (!agent?.id) return;\n const fetchKey = `${agent.id}:${activeProfile}`;\n if (pluginsFetchedRef.current !== fetchKey) {\n pluginsFetchedRef.current = fetchKey;\n fetchPlugins();\n }\n }, [agent?.id, activeProfile, fetchPlugins]);\n\n const handleInstallPlugin = useCallback(\n async (packageName: string) => {\n if (!agent?.id) return;\n setPluginActionLoading(packageName);\n try {\n const { data } = await installPluginMutation({\n variables: { agentId: agent.id, packageName },\n });\n if (data?.installAgentPlugin?.success) {\n await fetchPlugins();\n } else {\n throw new Error(\n data?.installAgentPlugin?.error || tr('agentDetails.installFailed', 'Install failed')\n );\n }\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n markQuotaHandledLocally();\n setQuotaKind('plugin');\n setShowQuotaExhausted(true);\n return;\n }\n\n setPluginError(\n err instanceof Error\n ? err.message\n : tr('agentDetails.pluginInstallFailed', 'Failed to install plugin')\n );\n setTimeout(() => setPluginError(null), 5000);\n } finally {\n setPluginActionLoading(null);\n }\n },\n [agent?.id, installPluginMutation, fetchPlugins, tr]\n );\n\n const handleRemovePlugin = useCallback(\n async (packageName: string) => {\n if (!agent?.id) return;\n if (\n !window.confirm(\n tr('agentDetails.removePluginConfirm', 'Remove plugin {{packageName}}?', { packageName })\n )\n )\n return;\n setPluginActionLoading(packageName);\n try {\n const { data } = await removePluginMutation({\n variables: { agentId: agent.id, packageName },\n });\n if (data?.removeAgentPlugin?.success) {\n await fetchPlugins();\n } else {\n throw new Error(\n data?.removeAgentPlugin?.error || tr('agentDetails.removeFailed', 'Remove failed')\n );\n }\n } catch (err) {\n setPluginError(\n err instanceof Error\n ? err.message\n : tr('agentDetails.pluginRemoveFailed', 'Failed to remove plugin')\n );\n setTimeout(() => setPluginError(null), 5000);\n } finally {\n setPluginActionLoading(null);\n }\n },\n [agent?.id, removePluginMutation, fetchPlugins, tr]\n );\n\n // Get sessions and vibes from the agent response (already included in the query)\n const agentSessions = agent?.sessions || [];\n const agentVibes = agent?.vibes || [];\n\n // ── Store plugin fetch / install ──────────────────────────────────\n const fetchStorePlugins = useCallback(async () => {\n setStorePluginsLoading(true);\n setStorePluginsError(null);\n try {\n const response = await fetch(\n (typeof window !== 'undefined' &&\n (window as { __BURDENOFF_GLOBAL_GATEWAY__?: string }).__BURDENOFF_GLOBAL_GATEWAY__) ||\n '/global/graphql',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify({\n query: `query MyStorePlugins {\n myEntitlements {\n id\n productId\n licenseKey\n product {\n id\n name\n slug\n icon\n description\n manifest\n }\n }\n }`,\n }),\n }\n );\n const body = (await response.json()) as {\n data?: { myEntitlements?: StoreEntitlement[] };\n errors?: Array<{ message: string }>;\n };\n if (body.errors?.length)\n throw new Error(body.errors[0]?.message ?? 'Failed to load store plugins');\n const plugins = (body.data?.myEntitlements ?? []).filter((e) => {\n const manifest = e.product?.manifest as Record<string, unknown> | null;\n if (!manifest) return false;\n const itemType = (manifest['itemType'] as string | undefined)?.toLowerCase();\n return itemType === 'vibemodule' || itemType === 'plugin';\n });\n setStorePlugins(plugins);\n } catch (err) {\n setStorePluginsError(err instanceof Error ? err.message : 'Failed to load store plugins');\n } finally {\n setStorePluginsLoading(false);\n }\n }, []);\n\n useEffect(() => {\n if (pluginSubTab === 'store' && storePlugins.length === 0 && !storePluginsLoading) {\n void fetchStorePlugins();\n }\n }, [pluginSubTab, storePlugins.length, storePluginsLoading, fetchStorePlugins]);\n\n const handleInstallStorePlugin = useCallback(\n async (productId: string, licenseKey: string | null) => {\n if (!agent?.id) return;\n setStoreInstallingId(productId);\n try {\n const response = await fetch(\n (typeof window !== 'undefined' &&\n (window as { __BURDENOFF_WSPACE_GATEWAY__?: string }).__BURDENOFF_WSPACE_GATEWAY__) ||\n '/workspaces/graphql',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify({\n query: `mutation InstallStorePlugin($agentId: ID!, $productId: ID!, $licenseKey: String) {\n installStorePluginOnAgent(agentId: $agentId, productId: $productId, licenseKey: $licenseKey) {\n success\n error\n }\n }`,\n variables: { agentId: agent.id, productId, licenseKey },\n }),\n }\n );\n const body = (await response.json()) as {\n data?: {\n installStorePluginOnAgent?: { success: boolean; error: string | null };\n };\n errors?: Array<{ message: string }>;\n };\n if (body.errors?.length) throw new Error(body.errors[0]?.message ?? 'Install failed');\n const result = body.data?.installStorePluginOnAgent;\n if (!result?.success) {\n throw new Error(result?.error ?? 'Install failed');\n }\n await fetchPlugins();\n setPluginSubTab('installed');\n } catch (err) {\n setStorePluginsError(err instanceof Error ? err.message : 'Install failed');\n } finally {\n setStoreInstallingId(null);\n }\n },\n [agent?.id, fetchPlugins]\n );\n\n // Handle ?install=<productId>&licenseKey=... on page load — automatic install flow\n // when the user arrives here from OrderConfirmationPage\n useEffect(() => {\n if (typeof window === 'undefined' || !agent?.id) return;\n const params = new URLSearchParams(window.location.search);\n const productId = params.get('install');\n const licenseKey = params.get('licenseKey');\n if (productId && productId !== storeInstallingId) {\n setPluginSubTab('store');\n void handleInstallStorePlugin(productId, licenseKey);\n // Clear the query params after initiating\n const url = new URL(window.location.href);\n url.searchParams.delete('install');\n url.searchParams.delete('licenseKey');\n window.history.replaceState({}, '', url.toString());\n }\n }, [agent?.id, handleInstallStorePlugin, storeInstallingId]);\n\n const handleRevealApiKey = useCallback(async (): Promise<string | null> => {\n if (!agent?.id) return null;\n if (revealedApiKey) return revealedApiKey;\n setRevealLoading(true);\n setRevealError(null);\n try {\n const res = await fetchAgentSecret({ variables: { agentId: agent.id } });\n const key = res.data?.vibecontrolsAgentSecretReveal ?? null;\n if (!key) {\n setRevealError('No API key configured');\n return null;\n }\n setRevealedApiKey(key);\n return key;\n } catch (err) {\n setRevealError(err instanceof Error ? err.message : 'Reveal failed');\n return null;\n } finally {\n setRevealLoading(false);\n }\n }, [agent?.id, revealedApiKey, fetchAgentSecret]);\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions…</p>\n </div>\n );\n if (\n permissions &&\n (permissions.permissionStrings?.length ?? 0) > 0 &&\n !hasPermission(VIBE_PERMISSIONS.AGENT_READ)\n )\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n const handleBack = () => {\n navigate('/agents');\n };\n\n // Real lifecycle control: start/stop the agent process via the backend proxy\n // (POST /agent/lifecycle/{start,stop} on the agent), not a metadata write.\n // Shows a spinner + disables the button while in flight and surfaces the\n // outcome as a toast; refreshes the agent record + live health probe so the\n // badge and the Start/Stop toggle flip immediately.\n const runLifecycle = async (action: 'start' | 'stop') => {\n if (!agent?.id || lifecycleAction) return;\n setLifecycleAction(action);\n setErrorMessage(null);\n try {\n const res =\n action === 'start'\n ? await startVibecontrolsAgent({ variables: { agentId: agent.id } })\n : await stopVibecontrolsAgent({ variables: { agentId: agent.id } });\n const payload =\n action === 'start' ? res.data?.startVibecontrolsAgent : res.data?.stopVibecontrolsAgent;\n // Only treat an explicitly-successful payload as success. A null payload\n // (network hiccup / unexpected schema shape) must not fall through to the\n // success toast.\n if (!payload || payload.success === false) {\n throw new Error(payload?.error || `Failed to ${action} agent`);\n }\n setSuccessMessage(\n action === 'start'\n ? tr('agentDetails.agentStarted', 'Agent started')\n : tr('agentDetails.agentStopped', 'Agent stopped')\n );\n setTimeout(() => setSuccessMessage(null), 3000);\n // Snappy refresh — don't wait for the 30s probe poll / heartbeat sweep.\n await Promise.all([refetch(), probeQuery.refetch()]).catch(() => {});\n } catch (err) {\n const raw = err instanceof Error ? err.message : '';\n // The backend reaches the agent only over its tunnel. If the tunnel is\n // down (common after a stop, or if the host went away) the call can't\n // land — surface an actionable message instead of a raw fetch error.\n const unreachable =\n /unable to connect|fetch failed|timed? ?out|ECONN|agent returned 5|network/i.test(raw);\n setErrorMessage(\n unreachable\n ? tr(\n 'agentDetails.agentUnreachable',\n `Couldn't reach the agent to ${action} it — it may be offline or its tunnel is down. Start it from the host with: vibe start`\n )\n : raw || tr('agentDetails.lifecycleFailed', `Failed to ${action} agent`)\n );\n setTimeout(() => setErrorMessage(null), 6000);\n } finally {\n setLifecycleAction(null);\n }\n };\n\n const handleStartAgent = () => void runLifecycle('start');\n const handleStopAgent = () => void runLifecycle('stop');\n\n const handleConfigureAgent = () => {\n setConfigError(null);\n setShowConfigModal(true);\n };\n\n const handleRenameSave = async (): Promise<void> => {\n if (!agent?.id) return;\n const next = renameValue.trim();\n if (!next || next === agent.name) {\n setRenaming(false);\n return;\n }\n setRenameSaving(true);\n setRenameError(null);\n try {\n const result = await updateAgent({\n variables: { id: agent.id, input: { name: next } },\n });\n if (result.error) {\n throw result.error;\n }\n setRenaming(false);\n } catch (err) {\n // Most common failure mode: the (workspaceId, name) unique\n // constraint in wspace-vibecontrols-svc rejects a duplicate.\n // Surface the message inline so the operator can pick a\n // different name without losing what they typed.\n setRenameError(err instanceof Error ? err.message : String(err));\n } finally {\n setRenameSaving(false);\n }\n };\n\n const handleRenameCancel = (): void => {\n setRenaming(false);\n setRenameValue('');\n setRenameError(null);\n };\n\n const handleSubmitConfig = async () => {\n if (!agent?.id) return;\n\n const name = agentNameRef.current?.value?.trim();\n const tunnelUrl = agentTunnelUrlRef.current?.value?.trim();\n const aiContext = agentAiContextRef.current?.value?.trim();\n const metadataStr = agentMetadataRef.current?.value?.trim();\n\n if (!name) {\n setConfigError(tr('agentDetails.agentNameRequired', 'Agent name is required'));\n return;\n }\n\n let metadata: Record<string, unknown> | undefined;\n if (metadataStr) {\n try {\n metadata = JSON.parse(metadataStr);\n } catch {\n setConfigError(tr('agentDetails.metadataJsonRequired', 'Metadata must be valid JSON'));\n return;\n }\n }\n\n setConfigLoading(true);\n setConfigError(null);\n try {\n // TODO(svc): the deprecated `UpdateVibecontrolsAgentInput.agentApiKey`\n // field was dropped by F4 Wave B. A dedicated rotate-API-key svc\n // mutation needs to land before we can re-expose key rotation in\n // this Configure dialog. The form input is hidden until then.\n await updateAgent({\n variables: {\n id: agent.id,\n input: {\n name,\n ...(tunnelUrl !== undefined ? { tunnelUrl: tunnelUrl || null } : {}),\n aiContext: aiContext || null,\n metadata,\n },\n },\n });\n setShowConfigModal(false);\n setSuccessMessage(\n tr('agentDetails.configurationUpdated', 'Agent configuration updated successfully')\n );\n setTimeout(() => setSuccessMessage(null), 3000);\n } catch (err) {\n setConfigError(\n err instanceof Error\n ? err.message\n : tr('agentDetails.configurationUpdateFailed', 'Failed to update agent configuration')\n );\n } finally {\n setConfigLoading(false);\n }\n };\n\n const handleCopyApiKey = async () => {\n const key = await handleRevealApiKey();\n if (!key) return;\n try {\n await nativeCopyText(key);\n if (isNative()) void nativeToast('API key copied');\n setApiKeyCopied(true);\n setTimeout(() => setApiKeyCopied(false), 2000);\n } catch {\n // Fallback for non-HTTPS contexts\n console.error('Failed to copy API key');\n }\n };\n\n const handleToggleShowApiKey = async () => {\n if (!showApiKey) {\n await handleRevealApiKey();\n }\n setShowApiKey((v) => !v);\n };\n\n const handleRemoveAgent = async () => {\n if (!agent?.id) return;\n if (\n !window.confirm(\n tr('agentDetails.removeAgentConfirm', 'Are you sure you want to remove agent \"{{name}}\"?', {\n name: agent.name,\n })\n )\n )\n return;\n try {\n await deleteAgent({ variables: { id: agent.id } });\n handleBack();\n } catch (err) {\n console.error('Failed to remove agent:', err);\n }\n };\n\n const handleSessionClick = (sessionId: string) => {\n navigate(`/sessions/${sessionId}`);\n };\n\n const handleStartSession = () => {\n setSessionCreateError(null);\n setShowSessionModal(true);\n };\n\n const handleSubmitCreateSession = async () => {\n const name = sessionNameRef.current?.value?.trim();\n const type = sessionTypeRef.current?.value as 'TERMINAL' | 'TMUX' | 'SSH' | 'SCRIPT' | 'CUSTOM';\n const command = sessionCommandRef.current?.value?.trim() || undefined;\n const workingDirectory = sessionWorkDirRef.current?.value?.trim() || undefined;\n\n if (!name) {\n setSessionCreateError(tr('vibeDetails.sessionNameRequired', 'Session name is required'));\n return;\n }\n if (!agent?.id) {\n setSessionCreateError(tr('agentDetails.noAgent', 'Agent not loaded'));\n return;\n }\n\n // Block create when the agent's live deep-health probe is not green —\n // otherwise the create succeeds (PENDING row) but terminal-start fails\n // later with a tunnel-URL error. Matches the gate in SessionsPage.\n const probeRow = probesById.get(agent.id);\n if (probeRow && !probeRow.healthy) {\n setSessionCreateError(\n tr(\n 'sessions.agentNotHealthy',\n 'The selected agent isn’t fully reachable right now. Please wait for the agent badge to turn green and retry.'\n ) + (probeRow.errorMessage ? ` (${probeRow.errorMessage})` : '')\n );\n return;\n }\n\n setSessionCreateLoading(true);\n setSessionCreateError(null);\n try {\n await createSession({\n variables: {\n input: {\n name,\n type: type || 'TERMINAL',\n agentId: agent.id,\n command,\n workingDirectory,\n },\n },\n });\n setShowSessionModal(false);\n if (sessionNameRef.current) sessionNameRef.current.value = '';\n if (sessionTypeRef.current) sessionTypeRef.current.selectedIndex = 0;\n if (sessionCommandRef.current) sessionCommandRef.current.value = '';\n if (sessionWorkDirRef.current) sessionWorkDirRef.current.value = '';\n setSuccessMessage(tr('sessions.createdSuccess', 'Session created successfully'));\n setTimeout(() => setSuccessMessage(null), 3000);\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowSessionModal(false);\n markQuotaHandledLocally();\n setQuotaKind('session');\n setShowQuotaExhausted(true);\n return;\n }\n setSessionCreateError(\n err instanceof Error ? err.message : tr('sessions.failedCreate', 'Failed to create session')\n );\n } finally {\n setSessionCreateLoading(false);\n }\n };\n\n const handleVibeClick = (vibeId: string) => {\n navigate(`/vibes/${vibeId}`);\n };\n\n const formatTimestamp = (timestamp: string | null | undefined) => {\n if (!timestamp) return tr('health.never', 'Never');\n const diff = Date.now() - new Date(timestamp).getTime();\n if (diff < 60000) return tr('health.justNow', 'Just now');\n if (diff < 3600000) {\n return tr('agentDetails.minutesAgo', '{{count}}m ago', {\n count: Math.floor(diff / 60000),\n });\n }\n if (diff < 86400000) {\n return tr('agentDetails.hoursAgo', '{{count}}h ago', {\n count: Math.floor(diff / 3600000),\n });\n }\n return new Date(timestamp).toLocaleDateString();\n };\n\n // Loading state - wrapped in MotionPage to prevent unmount/remount animation replay\n if (loading && !agent) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('agentDetails.backToAgents', 'Back to Agents')}\n </button>\n <PageSkeleton variant=\"detail\" />\n </MotionPage>\n );\n }\n\n // Error state\n if (error && !agent) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('agentDetails.backToAgents', 'Back to Agents')}\n </button>\n <ErrorState\n title={tr('agentDetails.failedLoad', 'Failed to load agent')}\n message={error.message}\n onRetry={() => refetch()}\n />\n </MotionPage>\n );\n }\n\n // Not found state\n if (!agent) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('agentDetails.backToAgents', 'Back to Agents')}\n </button>\n <EmptyState\n icon={<Server className=\"size-8 text-text-secondary\" />}\n title={tr('agentDetails.notFound', 'Agent not found')}\n description={`${tr('agentDetails.notFoundDescriptionPrefix', 'No agent with ID')} \"${id}\" ${tr('agentDetails.notFoundDescriptionSuffix', 'exists')}`}\n action={\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n {tr('agentDetails.backToAgents', 'Back to Agents')}\n </button>\n }\n />\n </MotionPage>\n );\n }\n\n const agentTabs: { id: AgentTab; label: string; icon: typeof Server; badge?: string }[] = [\n { id: 'overview', label: tr('nav.overview', 'Overview'), icon: Server },\n { id: 'profiles', label: tr('agentDetails.profiles', 'Profiles'), icon: Users },\n { id: 'security', label: tr('agentDetails.security', 'Security'), icon: Shield },\n {\n id: 'plugins',\n label: tr('agentDetails.plugins', 'Plugins'),\n icon: Puzzle,\n badge: `${installedPlugins.length}`,\n },\n {\n id: 'sessions',\n label: tr('nav.sessions', 'Sessions'),\n icon: Terminal,\n badge: `${agentSessions.length}`,\n },\n {\n id: 'logs',\n label: tr('nav.logs', 'Logs'),\n icon: ScrollText,\n },\n {\n id: 'connection',\n label: tr('agentDetails.connection', 'Connection Log'),\n icon: ScrollText,\n },\n {\n id: 'vibes',\n label: tr('nav.vibes', 'Vibes'),\n icon: Zap,\n badge: `${agentVibes.length}`,\n },\n {\n id: 'notes',\n label: tr('vibeDetails.notes', 'Notes'),\n icon: FileText,\n },\n {\n id: 'aliases',\n label: tr('agentDetails.aliases', 'Aliases'),\n icon: Command,\n },\n {\n id: 'backup',\n label: tr('agentDetails.backup', 'Backup'),\n icon: Database,\n },\n ];\n\n // Types for sessions and vibes from the query\n type SessionItem = NonNullable<typeof agentSessions>[number];\n type VibeItem = NonNullable<typeof agentVibes>[number];\n\n // Stats\n const runningSessions = agentSessions.filter((s: SessionItem) => s.status === 'RUNNING').length;\n // Declared here (rather than inside JSX) because it's used in the backup tab panel below.\n const backupTunnelUrl = agent?.tunnelUrl;\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n {/* Success Toast */}\n {successMessage && (\n <div className=\"fixed top-4 left-4 right-4 sm:left-auto z-50 bg-status-success-bg text-status-success-text px-4 py-3 rounded-md shadow-lg\">\n {successMessage}\n </div>\n )}\n\n {/* Error Toast — offset below the success toast so the two never overlap\n when a 3s success auto-dismiss races a fresh 6s error. */}\n {errorMessage && (\n <div className=\"fixed top-16 left-4 right-4 sm:left-auto z-50 bg-status-error-bg text-status-error-text px-4 py-3 rounded-md shadow-lg\">\n {errorMessage}\n </div>\n )}\n\n {/* Back Button */}\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('agentDetails.backToAgents', 'Back to Agents')}\n </button>\n\n {/* Header */}\n <PageHeader\n title={agent.name}\n description={\n agent.hostname || tr('agentDetails.noHostnameConfigured', 'No hostname configured')\n }\n breadcrumb={[\n { label: tr('nav.agents', 'Agents'), path: basePath ? `${basePath}/agents` : '/agents' },\n { label: agent.name },\n ]}\n actions={\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => navigate('/ai?contextLevel=agent')}\n className=\"flex items-center gap-2 px-3 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors\"\n title={tr('agentDetails.openAiChat', 'Open AI chat with this agent')}\n data-testid=\"agent-open-ai-chat\"\n >\n <Bot className=\"size-4\" />\n <span className=\"hidden sm:inline\">{tr('agentDetails.aiChat', 'AI Chat')}</span>\n </button>\n <button\n type=\"button\"\n onClick={() => refetch()}\n disabled={loading}\n className=\"flex items-center gap-2 px-3 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors disabled:opacity-50\"\n title={tr('common.refresh', 'Refresh')}\n >\n <RefreshCw className={`size-4 ${loading ? 'animate-spin' : ''}`} />\n </button>\n {!showStartButton ? (\n <button\n type=\"button\"\n onClick={handleStopAgent}\n disabled={lifecycleAction !== null}\n aria-busy={lifecycleAction === 'stop'}\n className=\"flex items-center gap-2 px-3 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors disabled:opacity-60 disabled:cursor-not-allowed\"\n >\n {lifecycleAction === 'stop' ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Square className=\"size-4\" />\n )}\n {lifecycleAction === 'stop'\n ? tr('agentDetails.stopping', 'Stopping…')\n : tr('sessions.stop', 'Stop')}\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={handleStartAgent}\n disabled={lifecycleAction !== null}\n aria-busy={lifecycleAction === 'start'}\n className=\"flex items-center gap-2 px-3 py-2 bg-status-success-bg text-status-success-text rounded-md hover:opacity-80 transition-colors disabled:opacity-60 disabled:cursor-not-allowed\"\n >\n {lifecycleAction === 'start' ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Play className=\"size-4\" />\n )}\n {lifecycleAction === 'start'\n ? tr('agentDetails.starting', 'Starting…')\n : tr('agentDetails.start', 'Start')}\n </button>\n )}\n {derivedStatus === 'DEGRADED' && (\n // BOFF-2628 — Reconnect on Degraded. Fires the same lifecycle\n // start as a fresh start; svc-side that POSTs lifecycle/start\n // to the agent's tunnel, which typically clears transient\n // failures (tunnel hiccup, finalize retry). The button is\n // labelled \"Reconnect\" so the user knows it's a recovery\n // action — not a fresh start that might collide.\n <button\n type=\"button\"\n onClick={handleStartAgent}\n disabled={lifecycleAction !== null}\n aria-busy={lifecycleAction === 'start'}\n className=\"flex items-center gap-2 px-3 py-2 bg-status-warning-bg text-status-warning-text rounded-md hover:opacity-80 transition-colors disabled:opacity-60 disabled:cursor-not-allowed\"\n title={\n probesById.get(agent.id)?.errorMessage\n ? `Retry lifecycle/start — last error: ${probesById.get(agent.id)?.errorMessage}`\n : 'Retry lifecycle/start'\n }\n >\n {lifecycleAction === 'start' ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <RefreshCw className=\"size-4\" />\n )}\n {lifecycleAction === 'start'\n ? tr('agentDetails.reconnecting', 'Reconnecting…')\n : tr('agentDetails.reconnect', 'Reconnect')}\n </button>\n )}\n <OpenInBrowserEditorButton\n agentId={agent.id}\n tunnelUrl={agent.tunnelUrl || null}\n profile={activeProfile}\n />\n <button\n type=\"button\"\n onClick={handleConfigureAgent}\n className=\"flex items-center gap-2 px-3 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors\"\n >\n <Settings className=\"size-4\" />\n {tr('agentDetails.configure', 'Configure')}\n </button>\n <button\n type=\"button\"\n onClick={handleRemoveAgent}\n className=\"flex items-center gap-2 px-3 py-2 bg-status-error-bg text-status-error-text rounded-md hover:opacity-80 transition-colors\"\n >\n <Trash2 className=\"size-4\" />\n {tr('sessions.remove', 'Remove')}\n </button>\n </div>\n }\n />\n\n {/* Inline rename row — quick edit for the agent's display name.\n The Configure modal still owns the full edit (tunnel URL,\n ai-context, metadata, etc.); this is the one-click affordance\n for the common case of \"I just want to rename this thing\". */}\n <div className=\"flex items-center gap-2 -mt-2\">\n {renaming ? (\n <>\n <input\n ref={renameInputRef}\n type=\"text\"\n value={renameValue}\n onChange={(e) => setRenameValue(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !renameSaving) {\n void handleRenameSave();\n } else if (e.key === 'Escape') {\n handleRenameCancel();\n }\n }}\n disabled={renameSaving}\n maxLength={120}\n aria-label={tr('agentDetails.renameInput', 'New agent name')}\n className=\"flex-1 max-w-md px-3 py-1.5 text-sm bg-bg-surface border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n placeholder={agent.name}\n data-testid=\"agent-details-rename-input\"\n />\n <button\n type=\"button\"\n onClick={() => void handleRenameSave()}\n disabled={!renameValue.trim() || renameValue.trim() === agent.name || renameSaving}\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-60 disabled:cursor-not-allowed\"\n data-testid=\"agent-details-rename-save\"\n >\n {renameSaving ? (\n <Loader2 className=\"size-3.5 animate-spin\" />\n ) : (\n <Check className=\"size-3.5\" />\n )}\n {tr('agentDetails.saveName', 'Save')}\n </button>\n <button\n type=\"button\"\n onClick={handleRenameCancel}\n disabled={renameSaving}\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-xs text-text-secondary hover:text-text-primary disabled:opacity-60\"\n data-testid=\"agent-details-rename-cancel\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n {renameError && (\n <span className=\"text-xs text-status-error-text\" role=\"alert\">\n {renameError}\n </span>\n )}\n </>\n ) : (\n <button\n type=\"button\"\n onClick={() => {\n setRenameError(null);\n setRenameValue(agent.name);\n setRenaming(true);\n requestAnimationFrame(() => renameInputRef.current?.select());\n }}\n className=\"inline-flex items-center gap-1.5 text-xs text-text-secondary hover:text-text-primary transition-colors\"\n title={tr('agentDetails.renameTooltip', 'Rename this agent')}\n data-testid=\"agent-details-rename-trigger\"\n >\n <Edit3 className=\"size-3.5\" />\n {tr('agentDetails.rename', 'Rename')}\n </button>\n )}\n </div>\n\n {/* Status Cards */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4\">\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Server className=\"size-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">{tr('sessions.filterStatus', 'Status')}</p>\n <AgentStatusBadge\n status={derivedStatus}\n reason={\n probesById.get(agent.id)?.errorMessage ??\n (agent.lastGatewayAuthPushStatus === 'failed'\n ? (agent.lastGatewayAuthPushError ?? 'Gateway-auth push failed')\n : null)\n }\n linkTo={`?tab=connection`}\n onClick={(event) => {\n event.preventDefault();\n setActiveTab('connection');\n }}\n />\n </div>\n </div>\n </Card>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Cpu className=\"size-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">{tr('analytics.platform', 'Platform')}</p>\n <p className=\"font-semibold text-text-primary\">\n {agent.platform}/{agent.architecture}\n </p>\n </div>\n </div>\n </Card>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <HardDrive className=\"size-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">{tr('agentDetails.version', 'Version')}</p>\n <p className=\"font-semibold text-text-primary\">v{agent.version}</p>\n </div>\n </div>\n </Card>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Terminal className=\"size-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">{tr('nav.sessions', 'Sessions')}</p>\n <p className=\"font-semibold text-text-primary\">\n {runningSessions} {tr('health.active', 'active')}\n </p>\n </div>\n </div>\n </Card>\n </div>\n\n {/* ── Tab Navigation Bar ─────────────────────────────────────────── */}\n <div className=\"border-b border-border-default\">\n <nav\n className=\"flex gap-1 -mb-px overflow-x-auto pb-1\"\n aria-label={tr('agentDetails.tabsAriaLabel', 'Agent tabs')}\n >\n {agentTabs.map((tab) => {\n const Icon = tab.icon;\n const isActive = activeTab === tab.id;\n return (\n <button\n type=\"button\"\n key={tab.id}\n onClick={() => setActiveTab(tab.id)}\n className={`flex shrink-0 items-center gap-1.5 px-3 py-2.5 text-xs sm:gap-2 sm:px-4 sm:text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${\n isActive\n ? // text-action-primary-bg is the brand blue — used intentionally for text\n // to match the active border color. text-action-primary-text is white,\n // which is invisible on light backgrounds.\n 'border-action-primary-bg text-action-primary-bg'\n : 'border-transparent text-text-secondary hover:text-text-primary hover:border-border-default'\n }`}\n aria-selected={isActive}\n role=\"tab\"\n >\n <Icon className=\"size-4\" />\n {tab.label}\n {tab.badge && (\n <span\n className={`hidden rounded-full px-1.5 py-0.5 text-[10px] sm:inline-flex sm:text-xs ${\n isActive\n ? 'bg-action-primary-bg/10 text-action-primary-bg'\n : 'bg-bg-sunken text-text-muted'\n }`}\n >\n {tab.badge}\n </span>\n )}\n </button>\n );\n })}\n {/* PR-8 iframe-mounted tabs for the `agent.detailTab` mount.\n Same gate as VibeDetailsPage — feature-flagged off by\n default. */}\n {enableIframeHost &&\n iframeContributions.data.map((c) => {\n const isActive = activeTab === c.contribution.id;\n return (\n <button\n type=\"button\"\n key={`plugin-${c.contribution.id}`}\n onClick={() => setActiveTab(c.contribution.id)}\n className={`flex shrink-0 items-center gap-1.5 px-3 py-2.5 text-xs sm:gap-2 sm:px-4 sm:text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${\n isActive\n ? 'border-action-primary-bg text-action-primary-bg'\n : 'border-transparent text-text-secondary hover:text-text-primary hover:border-border-default'\n }`}\n aria-selected={isActive}\n role=\"tab\"\n title={`${c.contribution.title} (plugin: ${c.pluginKey})`}\n >\n {c.contribution.title}\n </button>\n );\n })}\n {/* \"+ Add tab\" — placed at the trailing end of the strip. */}\n {enableIframeHost && agent && (\n <button\n type=\"button\"\n onClick={() => setAddTabOpen(true)}\n className=\"flex shrink-0 items-center gap-1 p-2 text-xs sm:text-sm border-b-2 border-transparent text-text-secondary hover:text-text-primary hover:border-border-default\"\n title=\"Install a UI plugin tab\"\n aria-label=\"Add tab\"\n >\n <span aria-hidden>+</span>\n <span className=\"hidden sm:inline\">Add tab</span>\n </button>\n )}\n </nav>\n </div>\n\n {/* ── Tab Panels ─────────────────────────────────────────────────── */}\n <AnimatePresence mode=\"wait\">\n {/* Overview Tab */}\n {activeTab === 'overview' && (\n <motion.div\n key=\"overview\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n {/* Capabilities */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <CheckCircle2 className=\"size-5\" />\n {tr('agentDetails.capabilities', 'Capabilities')}\n </h3>\n </div>\n <div className=\"p-4\">\n <div className=\"flex flex-wrap gap-2\">\n {agent.capabilities &&\n typeof agent.capabilities === 'object' &&\n (Array.isArray(agent.capabilities)\n ? agent.capabilities.length > 0\n : Object.keys(agent.capabilities).length > 0) ? (\n (Array.isArray(agent.capabilities)\n ? (agent.capabilities as string[])\n : (() => {\n const obj = agent.capabilities as Record<string, unknown>;\n const keys = Object.keys(obj);\n const hasNumericKeys =\n keys.length > 0 && keys.every((k) => /^\\d+$/.test(k));\n return hasNumericKeys\n ? (Object.values(obj) as string[])\n : (keys as string[]);\n })()\n ).map((cap) => (\n <span\n key={cap}\n className=\"px-3 py-1 bg-bg-sunken text-text-primary text-sm rounded-full\"\n >\n {cap}\n </span>\n ))\n ) : (\n <div className=\"space-y-2 text-sm text-text-secondary\">\n <p>\n {tr('agentDetails.noCapabilitiesConfigured', 'No capabilities configured')}\n </p>\n <p className=\"text-xs\">\n Capabilities are feature tags the agent advertises to vibes (e.g.{' '}\n <code className=\"text-text-primary\">docker</code>,{' '}\n <code className=\"text-text-primary\">gpu</code>,{' '}\n <code className=\"text-text-primary\">node20</code>,{' '}\n <code className=\"text-text-primary\">git</code>). Vibes use them to pick an\n agent that can run their workloads.\n </p>\n <p className=\"text-xs\">\n Add from the agent host CLI:{' '}\n <code className=\"text-text-primary\">vibe agent caps add docker gpu</code>.\n The agent re-publishes its capability set on next heartbeat.\n </p>\n </div>\n )}\n </div>\n </div>\n </Card>\n\n {/* Tags */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Tag className=\"size-5\" />\n Tags\n </h3>\n </div>\n <div className=\"p-4\">\n <EntityTagPicker entityType=\"VIBECONTROLS_AGENT\" entityId={agent.id} />\n </div>\n </Card>\n\n {/* Tunnel Info */}\n {agent.tunnelUrl && (\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Zap className=\"size-5\" />\n {tr('health.tunnel', 'Tunnel')}\n </h3>\n </div>\n <div className=\"p-4\">\n {/*\n * Tunnel URL is a plain info field — no status chip\n * here. The agent's canonical status lives in the\n * top \"Status\" card above; rendering tunnelStatus\n * here was a redundant (and frequently stale)\n * second status surface.\n */}\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm text-text-secondary mb-1\">\n {tr('agentDetails.tunnelUrl', 'Tunnel URL')}\n </p>\n <a\n href={agent.tunnelUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-action-primary-text hover:underline break-all\"\n >\n {agent.tunnelUrl}\n </a>\n </div>\n </div>\n </Card>\n )}\n\n {/* Configuration */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Settings className=\"size-5\" />\n {tr('agentDetails.configuration', 'Configuration')}\n </h3>\n </div>\n <div className=\"p-4 space-y-4\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('analytics.platform', 'Platform')}\n </p>\n <p className=\"font-medium text-text-primary\">{agent.platform}</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('analytics.architecture', 'Architecture')}\n </p>\n <p className=\"font-medium text-text-primary\">{agent.architecture}</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('agentDetails.version', 'Version')}\n </p>\n <p className=\"font-medium text-text-primary\">{agent.version}</p>\n </div>\n </div>\n {agent.aiContext && (\n <div>\n <p className=\"text-sm text-text-secondary mb-1\">AI Context</p>\n <pre className=\"text-sm text-text-primary bg-bg-sunken border border-border-default rounded-md p-3 whitespace-pre-wrap font-sans\">\n {agent.aiContext}\n </pre>\n </div>\n )}\n </div>\n </Card>\n\n {/* Timeline */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Clock className=\"size-5\" />\n {tr('vibeDetails.timeline', 'Timeline')}\n </h3>\n </div>\n <div className=\"p-4\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 text-sm\">\n <div>\n <p className=\"text-text-secondary\">\n {tr('health.lastHeartbeat', 'Last Heartbeat')}\n </p>\n <p className=\"font-medium text-text-primary\">\n {formatTimestamp(agent.lastHeartbeat)}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">{tr('vibeDetails.created', 'Created')}</p>\n <p className=\"font-medium text-text-primary\">\n {formatTimestamp(agent.createdAt)}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">{tr('vibeDetails.updated', 'Updated')}</p>\n <p className=\"font-medium text-text-primary\">\n {formatTimestamp(agent.updatedAt)}\n </p>\n </div>\n </div>\n </div>\n </Card>\n </motion.div>\n )}\n\n {/* Profiles Tab — Phase 5B (multi-profile-per-daemon) */}\n {activeTab === 'profiles' && (\n <motion.div\n key=\"profiles\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <ProfilesPanel agentId={agent.id} />\n </motion.div>\n )}\n\n {/* Security Tab */}\n {activeTab === 'security' && (\n <motion.div\n key=\"security\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n {/* Agent API Key */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Key className=\"size-5\" />\n {tr('agentDetails.agentApiKey', 'Agent API Key')}\n </h3>\n </div>\n <div className=\"p-4\">\n {agent.tunnelUrl ? (\n <div className=\"flex items-center gap-3\">\n <div className=\"flex-1 min-w-0\">\n <code className=\"text-sm font-mono text-text-primary bg-bg-sunken px-3 py-2 rounded-md block truncate\">\n {showApiKey && revealedApiKey\n ? revealedApiKey\n : revealLoading\n ? tr('agentDetails.revealLoading', 'Revealing\\u2026')\n : '\\u2022'.repeat(32)}\n </code>\n {revealError && (\n <p className=\"text-xs text-status-error-text mt-1\">{revealError}</p>\n )}\n </div>\n <button\n type=\"button\"\n onClick={() => void handleToggleShowApiKey()}\n disabled={revealLoading}\n className=\"p-2 rounded hover:bg-bg-sunken transition-colors flex-shrink-0 disabled:opacity-50\"\n title={\n showApiKey\n ? tr('agentDetails.hideApiKey', 'Hide API key')\n : tr('agentDetails.showApiKey', 'Show API key')\n }\n >\n {showApiKey ? (\n <EyeOff className=\"size-4 text-text-secondary\" />\n ) : (\n <Eye className=\"size-4 text-text-secondary\" />\n )}\n </button>\n <button\n type=\"button\"\n onClick={handleCopyApiKey}\n className=\"p-2 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n title={tr('agentDetails.copyApiKey', 'Copy API key')}\n >\n {apiKeyCopied ? (\n <Check className=\"size-4 text-status-success-text\" />\n ) : (\n <Copy className=\"size-4 text-text-secondary\" />\n )}\n </button>\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Agent tunnel not configured. Bring the agent online first.\n </p>\n )}\n <p className=\"mt-2 text-xs text-text-muted\">\n This key authenticates requests sent to the agent. The key is revealed only on\n explicit operator action and every read is audited.\n </p>\n </div>\n </Card>\n\n {/* Gateway Auth (OAuth2 App) */}\n <GatewayAuthCard agent={agent} onUpdate={() => refetch()} />\n </motion.div>\n )}\n\n {/* Plugins Tab */}\n {activeTab === 'plugins' &&\n (() => {\n const searchLower = pluginSearchQuery.toLowerCase();\n const filteredInstalled = installedPlugins.filter(\n (p) =>\n !searchLower ||\n p.pluginName.toLowerCase().includes(searchLower) ||\n p.packageName.toLowerCase().includes(searchLower) ||\n p.description?.toLowerCase().includes(searchLower) ||\n p.tags?.some((t) => t.toLowerCase().includes(searchLower))\n );\n const filteredAvailable = availablePlugins.filter(\n (p) =>\n !p.installed &&\n (!searchLower ||\n p.name.toLowerCase().includes(searchLower) ||\n p.packageName.toLowerCase().includes(searchLower) ||\n p.description.toLowerCase().includes(searchLower))\n );\n const uiPlugins = installedPlugins.filter((p) => p.hasUI);\n const filteredUIPlugins = uiPlugins.filter(\n (p) =>\n !searchLower ||\n p.pluginName.toLowerCase().includes(searchLower) ||\n p.packageName.toLowerCase().includes(searchLower)\n );\n\n const pluginSubTabs: {\n id: PluginSubTab;\n label: string;\n count: number;\n icon: typeof Puzzle;\n }[] = [\n {\n id: 'installed',\n label: 'Installed',\n count: filteredInstalled.length,\n icon: Puzzle,\n },\n {\n id: 'available',\n label: 'Available',\n count: filteredAvailable.length,\n icon: Download,\n },\n {\n id: 'store',\n label: 'Store',\n count: storePlugins.length,\n icon: Download,\n },\n {\n id: 'ui-plugins',\n label: 'UI Plugins',\n count: filteredUIPlugins.length,\n icon: Monitor,\n },\n ];\n\n return (\n <motion.div\n key=\"plugins\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n <Card>\n {/* Header with title, search, and refresh */}\n <div className=\"p-4 border-b border-border-default space-y-3\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Puzzle className=\"size-5\" />\n Plugins\n {installedPlugins.length > 0 && (\n <span className=\"text-sm font-normal text-text-secondary\">\n ({installedPlugins.filter((p) => p.isCore).length} core,{' '}\n {installedPlugins.filter((p) => !p.isCore).length} external)\n </span>\n )}\n </h3>\n <button\n type=\"button\"\n onClick={fetchPlugins}\n disabled={pluginsLoading}\n className=\"p-1.5 text-text-secondary hover:bg-bg-sunken rounded transition-colors disabled:opacity-50\"\n title={tr('agentDetails.refreshPlugins', 'Refresh plugins')}\n >\n <RefreshCw className={`size-4 ${pluginsLoading ? 'animate-spin' : ''}`} />\n </button>\n </div>\n\n {/* Search bar */}\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 size-4 text-text-muted\" />\n <input\n aria-label=\"control\"\n type=\"text\"\n value={pluginSearchQuery}\n onChange={(e) => setPluginSearchQuery(e.target.value)}\n placeholder={tr(\n 'agentDetails.searchPluginsPlaceholder',\n 'Search plugins by name, package, description, or tag...'\n )}\n className=\"w-full pl-9 pr-8 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-muted focus:outline-none focus:ring-1 focus:ring-action-primary-bg focus:border-action-primary-bg\"\n />\n {pluginSearchQuery && (\n <button\n type=\"button\"\n onClick={() => setPluginSearchQuery('')}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 p-0.5 text-text-muted hover:text-text-secondary rounded\"\n >\n <X className=\"size-3.5\" />\n </button>\n )}\n </div>\n\n {/* Sub-tabs */}\n <div className=\"flex gap-1 border-b border-border-default -mx-4 overflow-x-auto px-4 pb-1\">\n {pluginSubTabs.map((st) => {\n const isActive = pluginSubTab === st.id;\n const TabIcon = st.icon;\n return (\n <button\n type=\"button\"\n key={st.id}\n onClick={() => setPluginSubTab(st.id)}\n className={`flex shrink-0 items-center gap-1.5 px-3 py-2 text-xs sm:text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${\n isActive\n ? // text-action-primary-bg is the brand color and matches the active\n // border. text-action-primary-text is white — invisible on light bg.\n 'border-action-primary-bg text-action-primary-bg'\n : 'border-transparent text-text-secondary hover:text-text-primary hover:border-border-default'\n }`}\n >\n <TabIcon className=\"size-3.5\" />\n {st.label}\n <span\n className={`text-xs px-1.5 py-0.5 rounded-full ${\n isActive\n ? 'bg-action-primary-bg/15 text-action-primary-bg'\n : 'bg-bg-secondary text-text-muted'\n }`}\n >\n {st.count}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n\n <div className=\"p-4 space-y-4\">\n {/* Plugin Error */}\n {pluginError && (\n <div className=\"flex items-center gap-2 p-3 bg-status-error-bg text-status-error-text rounded-md text-sm\">\n <X className=\"size-4 flex-shrink-0\" />\n <span className=\"flex-1\">{pluginError}</span>\n <button\n type=\"button\"\n onClick={() => setPluginError(null)}\n className=\"flex-shrink-0 p-0.5 hover:bg-status-error-text/10 rounded\"\n >\n <X className=\"size-3.5\" />\n </button>\n </div>\n )}\n\n {/* Not reachable banner */}\n {!agent?.isActive && (\n <p className=\"text-sm text-text-muted flex items-center gap-1.5\">\n <Info className=\"size-4 flex-shrink-0\" />\n Agent is offline — showing known plugin catalog. Live data will load when\n the agent is reachable.\n </p>\n )}\n\n {/* Plugins are agent-wide (BOFF-2612). No per-profile\n gating: a single install/remove action applies to the\n whole agent. Only plugin DATA stays per-profile. */}\n\n {/* ── Installed Sub-Tab ────────────────────────────────── */}\n {pluginSubTab === 'installed' && (\n <>\n {filteredInstalled.length > 0 ? (\n <div className=\"space-y-2\">\n {filteredInstalled.map((plugin) => (\n <div\n key={plugin.packageName}\n className=\"flex flex-col sm:flex-row sm:items-center justify-between gap-2 p-3 bg-bg-sunken rounded-lg\"\n >\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium text-text-primary flex items-center gap-1.5 flex-wrap\">\n {plugin.pluginName}\n <span className=\"text-xs text-text-muted font-normal\">\n {plugin.version === 'latest'\n ? plugin.version\n : `v${plugin.version}`}\n </span>\n {plugin.isCore && (\n <span className=\"inline-flex items-center px-1.5 py-0.5 text-xs bg-action-primary-bg/10 text-action-primary-bg rounded border border-action-primary-bg/20\">\n core\n </span>\n )}\n {plugin.loaded && (\n <span className=\"inline-flex items-center px-1.5 py-0.5 text-xs bg-status-success-bg text-status-success-text rounded\">\n loaded\n </span>\n )}\n {plugin.hasProviders && (\n <span className=\"inline-flex items-center px-1.5 py-0.5 text-xs bg-status-warning-bg-subtle text-status-warning-text rounded\">\n provider\n </span>\n )}\n {plugin.hasUI && (\n <span className=\"inline-flex items-center px-1.5 py-0.5 text-xs bg-accent-purple-subtle text-accent-purple rounded\">\n ui\n </span>\n )}\n </p>\n {plugin.description && (\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {plugin.description}\n </p>\n )}\n <div className=\"flex items-center gap-2 mt-0.5 flex-wrap\">\n {!plugin.isCore && (\n <span className=\"text-xs text-text-muted font-mono\">\n {plugin.packageName}\n </span>\n )}\n {plugin.cliCommand && (\n <span className=\"text-xs text-text-muted\">\n cli:{' '}\n <code className=\"text-xs font-mono\">\n vibe {plugin.cliCommand}\n </code>\n </span>\n )}\n {plugin.apiPrefix && (\n <span className=\"text-xs text-text-muted\">\n api:{' '}\n <code className=\"text-xs font-mono\">\n {plugin.apiPrefix}\n </code>\n </span>\n )}\n </div>\n {plugin.tags && plugin.tags.length > 0 && (\n <div className=\"flex gap-1 mt-1 flex-wrap\">\n {plugin.tags.map((tag) => (\n <span\n key={tag}\n className=\"inline-flex px-1.5 py-0.5 text-[10px] bg-bg-secondary text-text-muted rounded\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-2 flex-shrink-0 sm:ml-3\">\n {plugin.hasUI && (\n <button\n type=\"button\"\n onClick={() => setPluginSubTab('ui-plugins')}\n className=\"flex items-center gap-1.5 px-2.5 py-1.5 text-xs text-action-primary-bg bg-action-primary-bg/10 rounded-md hover:bg-action-primary-bg/20 transition-colors border border-action-primary-bg/20\"\n title={`Open ${plugin.pluginName} UI`}\n >\n <Monitor className=\"size-3\" />\n Open UI\n </button>\n )}\n {!plugin.isCore && (\n <button\n type=\"button\"\n onClick={() => handleRemovePlugin(plugin.packageName)}\n disabled={pluginActionLoading === plugin.packageName}\n className=\"flex items-center gap-1.5 px-2.5 py-1.5 text-xs font-medium text-status-error-text bg-status-error-bg/15 border border-status-error-border/40 rounded-md hover:bg-status-error-bg/25 transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {pluginActionLoading === plugin.packageName ? (\n <Loader2 className=\"size-3 animate-spin\" />\n ) : (\n <Trash2 className=\"size-3\" />\n )}\n Remove\n </button>\n )}\n </div>\n </div>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-text-muted\">\n {pluginSearchQuery\n ? 'No installed plugins match your search.'\n : 'No plugin data available. Check agent connectivity or refresh.'}\n </p>\n )}\n </>\n )}\n\n {/* ── Available Sub-Tab ────────────────────────────────── */}\n {pluginSubTab === 'available' && (\n <>\n {filteredAvailable.length > 0 ? (\n <div className=\"space-y-2\">\n {filteredAvailable.map((plugin) => (\n <div\n key={plugin.packageName}\n className=\"flex flex-col sm:flex-row sm:items-center justify-between gap-2 p-3 bg-bg-sunken rounded-lg\"\n >\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium text-text-primary\">\n {plugin.name}\n </p>\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {plugin.description}\n </p>\n <p className=\"text-xs text-text-muted font-mono mt-0.5\">\n {plugin.packageName}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => handleInstallPlugin(plugin.packageName)}\n disabled={pluginActionLoading === plugin.packageName}\n className=\"flex items-center gap-1.5 px-2.5 py-1.5 text-xs text-action-primary-text bg-action-primary-bg rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex-shrink-0 sm:ml-3\"\n >\n {pluginActionLoading === plugin.packageName ? (\n <Loader2 className=\"size-3 animate-spin\" />\n ) : (\n <Download className=\"size-3\" />\n )}\n Install\n </button>\n </div>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-text-muted\">\n {pluginSearchQuery\n ? 'No available plugins match your search.'\n : availablePlugins.every((p) => p.installed)\n ? 'All available plugins are already installed.'\n : 'No available plugins found.'}\n </p>\n )}\n </>\n )}\n\n {/* ── Store Sub-Tab (Burdenoff Store purchased plugins) ── */}\n {pluginSubTab === 'store' && (\n <>\n {storePluginsError && (\n <div className=\"flex items-center gap-2 p-3 bg-status-error-bg text-status-error-text rounded-md text-sm\">\n <X className=\"size-4 flex-shrink-0\" />\n <span className=\"flex-1\">{storePluginsError}</span>\n </div>\n )}\n {storePluginsLoading ? (\n <p className=\"text-sm text-text-muted\">Loading purchased plugins…</p>\n ) : storePlugins.length === 0 ? (\n <div className=\"py-8 text-center\">\n <p className=\"text-sm text-text-muted\">\n No plugins purchased from the Burdenoff store yet.\n </p>\n <a\n href=\"/store/marketplace\"\n className=\"mt-2 inline-flex items-center gap-1 text-xs font-semibold text-action-primary-text hover:underline\"\n >\n Browse the store →\n </a>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {storePlugins.map((ent) => {\n const manifest =\n (ent.product?.manifest as Record<string, unknown> | null) ?? {};\n const digital = manifest['digital'] as\n | Record<string, unknown>\n | undefined;\n const install = digital?.['install'] as\n | Record<string, unknown>\n | undefined;\n const packageName =\n typeof install?.['packageName'] === 'string'\n ? (install['packageName'] as string)\n : null;\n const isAlreadyInstalled = installedPlugins.some(\n (p) => p.packageName === packageName\n );\n return (\n <div\n key={ent.id}\n className=\"flex flex-col sm:flex-row sm:items-center justify-between gap-2 p-3 bg-bg-sunken rounded-lg\"\n >\n <div className=\"flex items-start gap-3 min-w-0 flex-1\">\n {ent.product?.icon ? (\n <img\n src={ent.product.icon}\n alt=\"\"\n className=\"size-10 rounded-md object-cover flex-shrink-0\"\n />\n ) : (\n <div className=\"size-10 flex-shrink-0 rounded-md bg-bg-secondary flex items-center justify-center\">\n <Puzzle className=\"size-5 text-text-muted\" />\n </div>\n )}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <h4 className=\"text-sm font-semibold text-text-primary truncate\">\n {ent.product?.name ?? 'Unknown'}\n </h4>\n {ent.licenseKey && (\n <span className=\"text-[10px] bg-status-success-bg text-status-success-text px-1.5 py-0.5 rounded-full\">\n Licensed\n </span>\n )}\n </div>\n {packageName && (\n <p className=\"text-xs text-text-muted font-mono truncate\">\n {packageName}\n </p>\n )}\n {ent.product?.description && (\n <p className=\"text-xs text-text-secondary line-clamp-2 mt-1\">\n {ent.product.description}\n </p>\n )}\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() =>\n void handleInstallStorePlugin(ent.productId, ent.licenseKey)\n }\n disabled={\n isAlreadyInstalled ||\n storeInstallingId === ent.productId ||\n !packageName\n }\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-semibold rounded-md bg-action-primary-bg text-action-primary-text hover:opacity-90 disabled:opacity-60 flex-shrink-0\"\n >\n {isAlreadyInstalled\n ? 'Installed'\n : storeInstallingId === ent.productId\n ? 'Installing…'\n : 'Install'}\n </button>\n </div>\n );\n })}\n </div>\n )}\n </>\n )}\n\n {/* ── UI Plugins Sub-Tab (Embedded Browser) ────────────── */}\n {pluginSubTab === 'ui-plugins' && (\n <>\n {uiPlugins.length > 0 || agent?.tunnelUrl ? (\n <PluginUIPanel\n availablePlugins={[\n // Synthetic code-server entry (proxied, not a standard UI plugin)\n ...(agent?.tunnelUrl\n ? [\n {\n pluginName: 'code-server',\n displayName: 'Code Server (VS Code)',\n description: 'Browser-based VS Code editor',\n version: 'latest',\n customUrl: '/code-server/',\n } satisfies UIPluginOption,\n ]\n : []),\n ...uiPlugins.map(\n (p): UIPluginOption => ({\n pluginName: p.pluginName,\n displayName: p.pluginName\n .replace(/^ui-/, '')\n .replace(/-/g, ' ')\n .replace(/\\b\\w/g, (c) => c.toUpperCase()),\n description: p.description,\n version: p.version,\n })\n ),\n ]}\n tunnelUrl={agent?.tunnelUrl || null}\n agentId={agent?.id ?? null}\n profile={activeProfile}\n />\n ) : (\n <p className=\"text-sm text-text-muted\">\n {pluginSearchQuery\n ? 'No UI plugins match your search.'\n : 'No plugins with UI are currently installed.'}\n </p>\n )}\n </>\n )}\n\n {/* Loading */}\n {pluginsLoading && installedPlugins.length === 0 && (\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <Loader2 className=\"size-4 animate-spin\" />\n Loading plugins...\n </div>\n )}\n </div>\n </Card>\n </motion.div>\n );\n })()}\n\n {/* Sessions Tab */}\n {activeTab === 'sessions' && (\n <motion.div\n key=\"sessions\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <Card>\n <div className=\"p-4 border-b border-border-default flex items-center justify-between gap-3 flex-wrap\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Terminal className=\"size-5\" />\n {tr('nav.sessions', 'Sessions')} ({agentSessions.length})\n </h3>\n <PermissionButton\n permission={VIBE_PERMISSIONS.SESSION_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip=\"You don't have permission to create sessions\"\n >\n <button\n data-testid=\"create-session-btn\"\n onClick={handleStartSession}\n className=\"inline-flex items-center gap-2 px-3 py-1.5 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <Plus className=\"w-4 h-4\" />\n {tr('sessions.createSession', 'Create Session')}\n </button>\n </PermissionButton>\n </div>\n {agentSessions.length > 0 ? (\n <div className=\"divide-y divide-border-primary\">\n {agentSessions.map((session: SessionItem) => (\n <div\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (() => handleSessionClick(session.id))();\n }\n }}\n key={session.id}\n onClick={() => handleSessionClick(session.id)}\n className=\"p-4 flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 cursor-pointer hover:bg-bg-sunken/50 transition-colors\"\n >\n <div className=\"flex items-center gap-3 min-w-0\">\n <Terminal className=\"size-5 text-text-secondary flex-shrink-0\" />\n <div className=\"min-w-0\">\n <p className=\"font-medium text-text-primary truncate\">{session.name}</p>\n <p className=\"text-sm text-text-secondary truncate\">{session.type}</p>\n </div>\n </div>\n <StatusBadge status={session.status} />\n </div>\n ))}\n </div>\n ) : (\n <div className=\"p-6 text-center text-text-secondary flex flex-col items-center gap-3\">\n <span>{tr('agentDetails.noSessionsOnAgent', 'No sessions on this agent')}</span>\n <PermissionButton\n permission={VIBE_PERMISSIONS.SESSION_CREATE}\n deniedBehavior=\"disable\"\n deniedTooltip=\"You don't have permission to create sessions\"\n >\n <button\n data-testid=\"create-session-empty-btn\"\n onClick={handleStartSession}\n className=\"inline-flex items-center gap-2 px-3 py-1.5 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <Plus className=\"w-4 h-4\" />\n {tr('sessions.createSession', 'Create Session')}\n </button>\n </PermissionButton>\n </div>\n )}\n </Card>\n </motion.div>\n )}\n\n {activeTab === 'connection' && (\n <motion.div\n key=\"connection\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <Card className=\"min-h-[60vh]\">\n <ConnectionLogPanel agentId={agent.id} agentName={agent.name} />\n </Card>\n </motion.div>\n )}\n\n {activeTab === 'logs' && (\n <motion.div\n key=\"logs\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <Card>\n <div className=\"p-4 border-b border-border-default flex items-center justify-between\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <ScrollText className=\"size-5\" />\n {tr('nav.logs', 'Logs')}\n </h3>\n </div>\n <div className=\"p-4\">\n <LogViewer agentId={agent.id} profile={activeProfile} className=\"min-h-[28rem]\" />\n </div>\n </Card>\n </motion.div>\n )}\n\n {/* Vibes Tab */}\n {activeTab === 'vibes' && (\n <motion.div\n key=\"vibes\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <Card>\n <div className=\"p-4 border-b border-border-default flex items-center justify-between\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Zap className=\"size-5\" />\n {tr('nav.vibes', 'Vibes')} ({agentVibes.length})\n </h3>\n </div>\n {agentVibes.length > 0 ? (\n <div className=\"divide-y divide-border-primary\">\n {agentVibes.map((vibe: VibeItem) => (\n <div\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (() => handleVibeClick(vibe.id))();\n }\n }}\n key={vibe.id}\n onClick={() => handleVibeClick(vibe.id)}\n className=\"p-4 flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 cursor-pointer hover:bg-bg-sunken/50 transition-colors\"\n >\n <div className=\"flex items-center gap-3 min-w-0\">\n <Zap className=\"size-5 text-text-secondary flex-shrink-0\" />\n <div className=\"min-w-0\">\n <p className=\"font-medium text-text-primary truncate\">{vibe.name}</p>\n <p className=\"text-sm text-text-secondary truncate\">{vibe.type}</p>\n </div>\n </div>\n <StatusBadge status={vibe.status} />\n </div>\n ))}\n </div>\n ) : (\n <div className=\"p-6 text-center text-text-secondary\">\n {tr('agentDetails.noVibesUsingAgent', 'No vibes using this agent')}\n </div>\n )}\n </Card>\n </motion.div>\n )}\n\n {/* Notes Tab */}\n {activeTab === 'notes' && (\n <motion.div\n key=\"notes\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n <NotesTabPanel\n context=\"agent\"\n agentVibes={agentVibes.map((v: VibeItem) => ({ id: v.id, name: v.name }))}\n />\n </motion.div>\n )}\n\n {/* Aliases Tab */}\n {activeTab === 'aliases' && (\n <motion.div\n key=\"aliases\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n <AliasManager\n agent={{\n id: agent.id,\n profile:\n ((agent.metadata as Record<string, unknown> | null)?.profile as\n | string\n | undefined) ?? 'default',\n }}\n />\n </motion.div>\n )}\n\n {activeTab === 'backup' && agent.tunnelUrl && (\n <motion.div\n key=\"backup\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <AgentBackupTab agentId={agent.id} profile={activeProfile} />\n </motion.div>\n )}\n\n {activeTab === 'backup' && !agent.tunnelUrl && (\n <motion.div\n key=\"backup-no-tunnel\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <Card className=\"p-6 text-center text-text-secondary\">\n <Database className=\"size-8 mx-auto mb-2 text-text-muted\" />\n <p>\n {tr(\n 'agentDetails.backupRequiresTunnelAndApiKey',\n 'Agent tunnel URL and API key are required for backup management.'\n )}\n </p>\n <p className=\"text-sm mt-1\">\n {tr(\n 'agentDetails.configureConnectionInOverview',\n 'Configure the agent connection in the Overview tab.'\n )}\n </p>\n </Card>\n </motion.div>\n )}\n {/* PR-8 iframe-mounted tab body. Mirrors the VibeDetailsPage\n implementation; both pages currently use the same helper\n component (inline in VibeDetailsPage), but for now we\n duplicate the mount logic here for clarity. PR-11+ unifies\n via `useMountTabStrip`. */}\n {enableIframeHost &&\n (() => {\n const active: DiscoveredContribution | undefined = iframeContributions.data.find(\n (c) => c.contribution.id === activeTab\n );\n if (!active || !agent) return null;\n return (\n <motion.div\n key={`plugin-${active.contribution.id}`}\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n <Card>\n <div className=\"p-0 h-[600px]\">\n <PluginIframeMount\n contribution={active}\n tunnel={active.tunnel}\n restPaths={\n active.capabilities.restPaths.length > 0\n ? active.capabilities.restPaths\n : [`/ui/${active.pluginKey}`]\n }\n context={{ agentId: agent.id }}\n agentId={agent.id}\n profile={active.tunnel.profile}\n theme={{ colorMode: 'light', tokens: {} }}\n locale=\"en\"\n featureFlags={{}}\n hostVersion=\"1.0.0\"\n />\n </div>\n </Card>\n </motion.div>\n );\n })()}\n </AnimatePresence>\n\n {/* PR-10 \"+ Add tab\" picker. */}\n {enableIframeHost && agent && (\n <AddTabDialog\n isOpen={addTabOpen}\n onClose={() => setAddTabOpen(false)}\n mountPoint=\"agent.detailTab\"\n agentId={agent.id}\n profile={activeProfile ?? 'default'}\n onInstalled={() => {\n void iframeContributions.refetch();\n }}\n />\n )}\n\n {/* Configure Agent Modal */}\n {showConfigModal && (\n <div className=\"fixed inset-0 bg-bg-overlay flex items-center justify-center z-[100] p-4\">\n <div className=\"bg-bg-surface rounded-lg w-full max-w-lg max-h-[90vh] flex flex-col\">\n <div className=\"px-6 pt-6 pb-3 border-b border-border-default flex-shrink-0\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('agentDetails.configure', 'Configure')} {agent.name}\n </h2>\n </div>\n <div className=\"px-6 py-4 overflow-y-auto flex-1\">\n {configError && (\n <div className=\"mb-4 p-3 bg-status-error-bg text-status-error-text rounded-md text-sm\">\n {configError}\n </div>\n )}\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('webhooks.name', 'Name')}\n </label>\n <input\n aria-label=\"control\"\n ref={agentNameRef}\n type=\"text\"\n defaultValue={agent.name}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('analytics.platform', 'Platform')}\n </label>\n <input\n aria-label=\"control\"\n type=\"text\"\n value={`${agent.platform} / ${agent.architecture}`}\n disabled\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-secondary\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('agentDetails.version', 'Version')}\n </label>\n <input\n aria-label=\"control\"\n type=\"text\"\n value={agent.version}\n disabled\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-secondary\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('agentDetails.tunnelUrl', 'Tunnel URL')}\n </label>\n <input\n aria-label=\"control\"\n ref={agentTunnelUrlRef}\n type=\"text\"\n defaultValue={agent.tunnelUrl ?? ''}\n placeholder={tr(\n 'agentDetails.tunnelUrlPlaceholder',\n 'https://xxx.trycloudflare.com'\n )}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary font-mono text-sm\"\n />\n <p className=\"mt-1 text-xs text-text-muted\">\n {tr(\n 'agentDetails.tunnelUrlHint',\n 'The public URL for accessing this agent remotely. Auto-updates when gateway auth is configured.'\n )}\n </p>\n </div>\n {/* F4 Wave B: API key rotation is no longer part of\n `updateVibecontrolsAgent`. The field was dropped from\n `UpdateVibecontrolsAgentInput`. A dedicated rotate-key\n svc mutation is the path forward; until it lands, this\n field is intentionally omitted. */}\n <div>\n <div className=\"flex items-center gap-1.5 mb-1\">\n <label\n htmlFor=\"agentdetailspage-58\"\n className=\"text-sm font-medium text-text-primary\"\n >\n AI Context\n </label>\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setShowAiContextInfo((v) => !v)}\n className=\"p-0.5 rounded-full text-text-muted hover:text-text-secondary transition-colors\"\n aria-label=\"What is AI Context?\"\n >\n <Info className=\"size-3.5\" />\n </button>\n {showAiContextInfo && (\n <>\n <div\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (() => setShowAiContextInfo(false))();\n }\n }}\n className=\"fixed inset-0 z-10\"\n onClick={() => setShowAiContextInfo(false)}\n />\n <div className=\"absolute left-0 top-6 z-20 w-72 bg-bg-elevated border border-border-default rounded-lg shadow-xl p-3 text-xs text-text-secondary space-y-1.5\">\n <p className=\"font-semibold text-text-primary\">What is AI Context?</p>\n <p>\n A short description (Markdown supported) that AI tools running on this\n agent will read to understand the environment — e.g. what the machine\n is for, what services it runs, or any constraints to follow.\n </p>\n <p className=\"text-text-muted\">\n Example: &quot;Production billing server. Do not modify files outside\n /src. Node 20, Docker installed.&quot;\n </p>\n </div>\n </>\n )}\n </div>\n </div>\n <textarea\n id=\"agentdetailspage-58\"\n aria-label=\"e.g. This agent runs on the billing server. Node 20, Docker installed. Do not modify files outside /src.\"\n ref={agentAiContextRef}\n defaultValue={agent.aiContext ?? ''}\n rows={4}\n placeholder=\"e.g. This agent runs on the billing server. Node 20, Docker installed. Do not modify files outside /src.\"\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary text-sm\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('agentDetails.metadataLabel', 'Metadata (JSON)')}\n </label>\n <textarea\n aria-label=\"control\"\n ref={agentMetadataRef}\n defaultValue={agent.metadata ? JSON.stringify(agent.metadata, null, 2) : '{}'}\n rows={4}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary font-mono text-sm\"\n />\n </div>\n </div>\n </div>\n <div className=\"px-6 py-4 border-t border-border-default flex-shrink-0 flex flex-wrap justify-end gap-3\">\n <button\n type=\"button\"\n onClick={() => setShowConfigModal(false)}\n disabled={configLoading}\n className=\"px-4 py-2 text-text-primary hover:bg-bg-sunken rounded-md transition-colors disabled:opacity-50\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n onClick={handleSubmitConfig}\n disabled={configLoading}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {configLoading\n ? tr('agentDetails.saving', 'Saving...')\n : tr('agentDetails.saveConfiguration', 'Save Configuration')}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Create Session Modal */}\n {showSessionModal && (\n <div\n className=\"fixed inset-0 bg-bg-overlay flex items-center justify-center z-[100] p-4\"\n onClick={() => {\n if (!sessionCreateLoading) setShowSessionModal(false);\n }}\n >\n <div\n className=\"bg-bg-surface rounded-lg p-6 w-full max-w-lg\"\n data-testid=\"create-session-modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"create-session-title\"\n onClick={(e) => e.stopPropagation()}\n >\n <h2 id=\"create-session-title\" className=\"text-lg font-semibold text-text-primary mb-4\">\n {tr('agentDetails.newSessionFor', 'New Session for')} {agent.name}\n </h2>\n {sessionCreateError && (\n <div className=\"mb-4 p-3 bg-status-error-bg text-status-error-text rounded-md text-sm\">\n {sessionCreateError}\n </div>\n )}\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibeDetails.sessionName', 'Session Name')}\n </label>\n <input\n data-testid=\"session-name-input\"\n ref={sessionNameRef}\n type=\"text\"\n placeholder={tr('vibeDetails.sessionNamePlaceholder', 'dev-terminal')}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('sessions.filterType', 'Type')}\n </label>\n <select\n ref={sessionTypeRef}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary\"\n >\n <option value=\"TERMINAL\">{tr('sessions.typeTerminal', 'Terminal')}</option>\n <option value=\"TMUX\">{tr('sessions.typeTmux', 'TMUX')}</option>\n <option value=\"SSH\">{tr('sessions.typeSsh', 'SSH')}</option>\n <option value=\"SCRIPT\">{tr('sessions.typeScript', 'Script')}</option>\n <option value=\"CUSTOM\">{tr('sessions.typeCustom', 'Custom')}</option>\n </select>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('sessions.command', 'Command')}\n </label>\n <input\n ref={sessionCommandRef}\n type=\"text\"\n placeholder={tr('vibeDetails.sessionCommandPlaceholder', 'bash')}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibeDetails.workingDirectory', 'Working Directory')}\n </label>\n <input\n ref={sessionWorkDirRef}\n type=\"text\"\n placeholder=\"/home/user\"\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder\"\n />\n </div>\n </div>\n <div className=\"flex flex-col sm:flex-row justify-end gap-3 mt-6\">\n <button\n onClick={() => setShowSessionModal(false)}\n disabled={sessionCreateLoading}\n className=\"px-4 py-2 text-text-primary hover:bg-bg-sunken rounded-md transition-colors disabled:opacity-50\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n <button\n data-testid=\"create-session-submit\"\n onClick={handleSubmitCreateSession}\n disabled={sessionCreateLoading}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {sessionCreateLoading\n ? tr('sessions.creating', 'Creating...')\n : tr('sessions.createSession', 'Create Session')}\n </button>\n </div>\n </div>\n </div>\n )}\n\n <QuotaExhaustedDialog\n isOpen={showQuotaExhausted}\n onClose={() => setShowQuotaExhausted(false)}\n onConfirm={() => {\n setShowQuotaExhausted(false);\n navigate('/billing');\n }}\n title={getQuotaDialogContent(quotaKind).title}\n message={getQuotaDialogContent(quotaKind).message}\n />\n </MotionPage>\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-vibecontrols",
3
- "version": "2026.531.1",
3
+ "version": "2026.531.2",
4
4
  "description": "VibeControls microfrontend for Burdenoff products",
5
5
  "type": "module",
6
6
  "files": [