@burdenoff/microfe-vibecontrols 2026.522.7 → 2026.522.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/agents/OpenInBrowserEditorButton.js +65 -66
- package/dist/components/agents/OpenInBrowserEditorButton.js.map +1 -1
- package/dist/components/ai/AIProviderCredentialsCard.js.map +1 -1
- package/dist/components/security/SecurityProviderDrawer.js +106 -31
- package/dist/components/security/SecurityProviderDrawer.js.map +1 -1
- package/dist/components/vibe/VibeAgentSwitcher.js +237 -0
- package/dist/components/vibe/VibeAgentSwitcher.js.map +1 -0
- package/dist/components/vibes/VibeCard.js +2 -2
- package/dist/components/vibes/VibeCard.js.map +1 -1
- package/dist/components/vibes/VibeList.js +12 -30
- package/dist/components/vibes/VibeList.js.map +1 -1
- package/dist/pages/AgentDetailsPage.js +172 -123
- package/dist/pages/AgentDetailsPage.js.map +1 -1
- package/dist/pages/VibeDetailsPage.js +383 -397
- package/dist/pages/VibeDetailsPage.js.map +1 -1
- package/dist/pages/VibesPage.js +155 -190
- package/dist/pages/VibesPage.js.map +1 -1
- package/dist/services/aiApi.js +1 -1
- package/dist/services/aiApi.js.map +1 -1
- package/package.json +3 -1
|
@@ -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 { 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 { 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} 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 { PluginUIPanel, type UIPluginOption, OpenInBrowserEditorButton } from '@/components/agents';\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 { isQuotaExhaustedError } 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 useAgentHeartbeatMutation,\n useUpdateAgentMutation,\n useDeleteAgentMutation,\n useCheckSessionHealthMutation,\n useAgentPluginsLazyQuery,\n useInstallAgentPluginMutation,\n useRemoveAgentPluginMutation,\n useSetupAgentGatewayAuthMutation,\n usePushAgentGatewayAuthMutation,\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 agentApiKey?: 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=\"w-5 h-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=\"w-4 h-4 flex-shrink-0\" />\n <span className=\"flex-1\">{error}</span>\n <button\n onClick={() => setError(null)}\n className=\"flex-shrink-0 p-0.5 hover:bg-status-error-text/10 rounded\"\n >\n <X className=\"w-3.5 h-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=\"w-8 h-8 rounded-lg bg-status-success-bg flex items-center justify-center flex-shrink-0 mt-0.5\">\n <Link2 className=\"w-4 h-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 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=\"w-3.5 h-3.5 text-status-success-text\" />\n ) : (\n <Copy className=\"w-3.5 h-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 onClick={() => setShowSecret(!showSecret)}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n >\n {showSecret ? (\n <EyeOff className=\"w-3.5 h-3.5 text-text-secondary\" />\n ) : (\n <Eye className=\"w-3.5 h-3.5 text-text-secondary\" />\n )}\n </button>\n <button\n onClick={handleCopySecret}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n >\n {secretCopied ? (\n <Check className=\"w-3.5 h-3.5 text-status-success-text\" />\n ) : (\n <Copy className=\"w-3.5 h-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=\"w-3 h-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 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=\"w-3 h-3 animate-spin\" />\n ) : (\n <RefreshCw className=\"w-3 h-3\" />\n )}\n {tr('agentDetails.repushCredentials', 'Re-push credentials')}\n </button>\n <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=\"w-3 h-3 animate-spin\" />\n ) : (\n <Unlink className=\"w-3 h-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=\"w-8 h-8 rounded-lg bg-bg-sunken flex items-center justify-center flex-shrink-0 mt-0.5\">\n <Shield className=\"w-4 h-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 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=\"w-4 h-4 animate-spin\" />\n {tr('agentDetails.settingUp', 'Setting up...')}\n </>\n ) : (\n <>\n <Link2 className=\"w-4 h-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 } = 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 [agentHeartbeat] = useAgentHeartbeatMutation({ refetchQueries: ['GetAgent'] });\n const [updateAgent] = useUpdateAgentMutation({ refetchQueries: ['GetAgent'] });\n const [deleteAgent] = useDeleteAgentMutation();\n const [checkSessionHealth] = useCheckSessionHealthMutation({ refetchQueries: ['GetAgent'] });\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 | '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 '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 // Config form refs\n const agentNameRef = useRef<HTMLInputElement>(null);\n const agentTunnelUrlRef = useRef<HTMLInputElement>(null);\n const agentApiKeyRef = 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\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 // 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 // ── 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 && agent.agentApiKey);\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 const pluginsFetchedRef = useRef(false);\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({ variables: { agentId: agent.id } });\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]);\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 && !pluginsFetchedRef.current) {\n pluginsFetchedRef.current = true;\n fetchPlugins();\n }\n }, [agent?.id, 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 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 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 (!hasPermission(VIBE_PERMISSIONS.AGENT_READ))\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 const handleStartAgent = async () => {\n if (!agent?.id) return;\n try {\n await agentHeartbeat({ variables: { id: agent.id } });\n } catch (err) {\n console.error('Failed to start agent:', err);\n }\n };\n\n const handleStopAgent = async () => {\n if (!agent?.id) return;\n try {\n await updateAgent({\n variables: { id: agent.id, input: { metadata: { status: 'inactive' } } },\n });\n } catch (err) {\n console.error('Failed to stop agent:', err);\n }\n };\n\n const handleConfigureAgent = () => {\n setConfigError(null);\n setShowConfigModal(true);\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 agentApiKey = agentApiKeyRef.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 await updateAgent({\n variables: {\n id: agent.id,\n input: {\n name,\n ...(tunnelUrl !== undefined ? { tunnelUrl: tunnelUrl || null } : {}),\n ...(agentApiKey !== undefined ? { agentApiKey: agentApiKey || 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 if (!agent?.agentApiKey) return;\n try {\n await nativeCopyText(agent.agentApiKey);\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 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 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 onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-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 onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-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 onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-4\" />\n {tr('agentDetails.backToAgents', 'Back to Agents')}\n </button>\n <EmptyState\n icon={<Server className=\"w-8 h-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 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: '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 {/* Back Button */}\n <button\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-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 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={`w-4 h-4 ${loading ? 'animate-spin' : ''}`} />\n </button>\n {agent.isActive ? (\n <button\n onClick={handleStopAgent}\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 <Square className=\"w-4 h-4\" />\n {tr('sessions.stop', 'Stop')}\n </button>\n ) : (\n <button\n onClick={handleStartAgent}\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\"\n >\n <Play className=\"w-4 h-4\" />\n {tr('agentDetails.start', 'Start')}\n </button>\n )}\n <OpenInBrowserEditorButton\n tunnelUrl={agent.tunnelUrl || null}\n agentApiKey={agent.agentApiKey || null}\n profile={activeProfile}\n />\n <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=\"w-4 h-4\" />\n {tr('agentDetails.configure', 'Configure')}\n </button>\n <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=\"w-4 h-4\" />\n {tr('sessions.remove', 'Remove')}\n </button>\n </div>\n }\n />\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=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Server className=\"w-5 h-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">{tr('sessions.filterStatus', 'Status')}</p>\n <StatusBadge status={agent.isActive ? 'ACTIVE' : 'OFFLINE'} size=\"md\" />\n </div>\n </div>\n </Card>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Cpu className=\"w-5 h-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=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <HardDrive className=\"w-5 h-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=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Terminal className=\"w-5 h-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 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=\"w-4 h-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 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 px-2 py-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=\"w-5 h-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 <p className=\"text-text-secondary\">\n {tr('agentDetails.noCapabilitiesConfigured', 'No capabilities configured')}\n </p>\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=\"w-5 h-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=\"w-5 h-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=\"w-5 h-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=\"w-5 h-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 {/* Tunnel API Key Usage */}\n {agent.tunnelUrl && agent.agentApiKey && (\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 <Info className=\"w-5 h-5\" />\n {tr('agentDetails.apiAuthentication', 'API Authentication')}\n </h3>\n </div>\n <div className=\"p-4 space-y-3\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\n 'agentDetails.apiAuthenticationDescription',\n 'All requests to the agent (except health checks) require authentication. You can pass the API key in two ways:'\n )}\n </p>\n <div className=\"space-y-2\">\n <div>\n <p className=\"text-xs font-medium text-text-primary mb-1\">\n {tr('agentDetails.authHeaderRecommended', 'Header (recommended)')}\n </p>\n <code className=\"block text-xs font-mono bg-bg-sunken px-3 py-2 rounded-md text-text-primary overflow-x-auto\">\n x-agent-api-key: {agent.agentApiKey.slice(0, 12)}...\n </code>\n </div>\n <div>\n <p className=\"text-xs font-medium text-text-primary mb-1\">\n {tr('agentDetails.authQueryParameter', 'URL query parameter')}\n </p>\n <code className=\"block text-xs font-mono bg-bg-sunken px-3 py-2 rounded-md text-text-primary overflow-x-auto break-all\">\n {agent.tunnelUrl}/api/health?apiKey={agent.agentApiKey.slice(0, 12)}...\n </code>\n </div>\n </div>\n <p className=\"text-xs text-text-muted\">\n {tr('agentDetails.authExemptPrefix', 'The')}{' '}\n <code className=\"font-mono\">/health</code>{' '}\n {tr('agentDetails.authExemptAnd', 'and')}{' '}\n <code className=\"font-mono\">/api/agent/identity</code>{' '}\n {tr(\n 'agentDetails.authExemptSuffix',\n 'endpoints are exempt from authentication. The key changes on each agent restart unless a static key is configured.'\n )}\n </p>\n </div>\n </Card>\n )}\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=\"w-5 h-5\" />\n {tr('agentDetails.agentApiKey', 'Agent API Key')}\n </h3>\n </div>\n <div className=\"p-4\">\n {agent.agentApiKey ? (\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\n ? agent.agentApiKey\n : '\\u2022'.repeat(Math.min(agent.agentApiKey.length, 32))}\n </code>\n </div>\n <button\n onClick={() => setShowApiKey(!showApiKey)}\n className=\"p-2 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\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=\"w-4 h-4 text-text-secondary\" />\n ) : (\n <Eye className=\"w-4 h-4 text-text-secondary\" />\n )}\n </button>\n <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=\"w-4 h-4 text-status-success-text\" />\n ) : (\n <Copy className=\"w-4 h-4 text-text-secondary\" />\n )}\n </button>\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n No API key configured. Set one via the Configure button or agent CLI.\n </p>\n )}\n <p className=\"mt-2 text-xs text-text-muted\">\n This key authenticates requests sent to the agent. It typically changes on each\n agent restart.\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=\"w-5 h-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 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={`w-4 h-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 w-4 h-4 text-text-muted\" />\n <input\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 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=\"w-3.5 h-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 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 ? 'border-action-primary-bg text-action-primary-text'\n : 'border-transparent text-text-secondary hover:text-text-primary hover:border-border-default'\n }`}\n >\n <TabIcon className=\"w-3.5 h-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=\"w-4 h-4 flex-shrink-0\" />\n <span className=\"flex-1\">{pluginError}</span>\n <button\n onClick={() => setPluginError(null)}\n className=\"flex-shrink-0 p-0.5 hover:bg-status-error-text/10 rounded\"\n >\n <X className=\"w-3.5 h-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=\"w-4 h-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 {/* ── 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 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=\"w-3 h-3\" />\n Open UI\n </button>\n )}\n {!plugin.isCore && (\n <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 text-status-error-text bg-status-error-bg rounded-md hover:bg-status-error-bg/80 transition-colors disabled:opacity-50\"\n >\n {pluginActionLoading === plugin.packageName ? (\n <Loader2 className=\"w-3 h-3 animate-spin\" />\n ) : (\n <Trash2 className=\"w-3 h-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 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 flex-shrink-0 sm:ml-3\"\n >\n {pluginActionLoading === plugin.packageName ? (\n <Loader2 className=\"w-3 h-3 animate-spin\" />\n ) : (\n <Download className=\"w-3 h-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=\"w-4 h-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=\"w-10 h-10 rounded-md object-cover flex-shrink-0\"\n />\n ) : (\n <div className=\"w-10 h-10 flex-shrink-0 rounded-md bg-bg-secondary flex items-center justify-center\">\n <Puzzle className=\"w-5 h-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 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 agentApiKey={agent?.agentApiKey}\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=\"w-4 h-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\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Terminal className=\"w-5 h-5\" />\n {tr('nav.sessions', 'Sessions')} ({agentSessions.length})\n </h3>\n </div>\n {agentSessions.length > 0 ? (\n <div className=\"divide-y divide-border-primary\">\n {agentSessions.map((session: SessionItem) => (\n <div\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=\"w-5 h-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\">\n {tr('agentDetails.noSessionsOnAgent', 'No sessions on this agent')}\n </div>\n )}\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=\"w-5 h-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=\"w-5 h-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 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=\"w-5 h-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 && agent.agentApiKey && (\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\n agentTunnelUrl={agent.tunnelUrl}\n agentApiKey={agent.agentApiKey}\n profile={activeProfile}\n />\n </motion.div>\n )}\n\n {activeTab === 'backup' && (!agent.tunnelUrl || !agent.agentApiKey) && (\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=\"w-8 h-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-50 p-4\">\n <div className=\"bg-bg-surface rounded-lg p-6 w-full max-w-lg\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">\n {tr('agentDetails.configure', 'Configure')} {agent.name}\n </h2>\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 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 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 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 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 <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('agentDetails.agentApiKey', 'Agent API Key')}\n </label>\n <input\n ref={agentApiKeyRef}\n type=\"text\"\n defaultValue={agent.agentApiKey ?? ''}\n placeholder={tr('agentDetails.agentApiKeyPlaceholder', 'sk-agent-...')}\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.agentApiKeyHint',\n 'Used to authenticate requests to the agent. Leave empty to clear.'\n )}\n </p>\n </div>\n <div>\n <div className=\"flex items-center gap-1.5 mb-1\">\n <label className=\"text-sm font-medium text-text-primary\">AI Context</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=\"w-3.5 h-3.5\" />\n </button>\n {showAiContextInfo && (\n <>\n <div\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 is\n for, what services it runs, or any constraints to follow.\n </p>\n <p className=\"text-text-muted\">\n Example: "Production billing server. Do not modify files outside\n /src. Node 20, Docker installed."\n </p>\n </div>\n </>\n )}\n </div>\n </div>\n <textarea\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 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 className=\"flex flex-wrap justify-end gap-3 mt-6\">\n <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 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 <QuotaExhaustedDialog\n isOpen={showQuotaExhausted}\n onClose={() => setShowQuotaExhausted(false)}\n onConfirm={() => {\n setShowQuotaExhausted(false);\n navigate('/billing');\n }}\n title=\"Plugin Install Quota Reached\"\n message=\"You have used the plugin installation quota for your current plan. Upgrade to install more plugins.\"\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 { 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 { 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} 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 { PluginUIPanel, type UIPluginOption, OpenInBrowserEditorButton } from '@/components/agents';\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 { isQuotaExhaustedError } 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 useAgentHeartbeatMutation,\n useUpdateAgentMutation,\n useDeleteAgentMutation,\n useCheckSessionHealthMutation,\n useAgentPluginsLazyQuery,\n useInstallAgentPluginMutation,\n useRemoveAgentPluginMutation,\n useSetupAgentGatewayAuthMutation,\n usePushAgentGatewayAuthMutation,\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 agentApiKey?: 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=\"w-5 h-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=\"w-4 h-4 flex-shrink-0\" />\n <span className=\"flex-1\">{error}</span>\n <button\n onClick={() => setError(null)}\n className=\"flex-shrink-0 p-0.5 hover:bg-status-error-text/10 rounded\"\n >\n <X className=\"w-3.5 h-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=\"w-8 h-8 rounded-lg bg-status-success-bg flex items-center justify-center flex-shrink-0 mt-0.5\">\n <Link2 className=\"w-4 h-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 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=\"w-3.5 h-3.5 text-status-success-text\" />\n ) : (\n <Copy className=\"w-3.5 h-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 onClick={() => setShowSecret(!showSecret)}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n >\n {showSecret ? (\n <EyeOff className=\"w-3.5 h-3.5 text-text-secondary\" />\n ) : (\n <Eye className=\"w-3.5 h-3.5 text-text-secondary\" />\n )}\n </button>\n <button\n onClick={handleCopySecret}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n >\n {secretCopied ? (\n <Check className=\"w-3.5 h-3.5 text-status-success-text\" />\n ) : (\n <Copy className=\"w-3.5 h-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=\"w-3 h-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 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=\"w-3 h-3 animate-spin\" />\n ) : (\n <RefreshCw className=\"w-3 h-3\" />\n )}\n {tr('agentDetails.repushCredentials', 'Re-push credentials')}\n </button>\n <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=\"w-3 h-3 animate-spin\" />\n ) : (\n <Unlink className=\"w-3 h-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=\"w-8 h-8 rounded-lg bg-bg-sunken flex items-center justify-center flex-shrink-0 mt-0.5\">\n <Shield className=\"w-4 h-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 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=\"w-4 h-4 animate-spin\" />\n {tr('agentDetails.settingUp', 'Setting up...')}\n </>\n ) : (\n <>\n <Link2 className=\"w-4 h-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 } = 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 [agentHeartbeat] = useAgentHeartbeatMutation({ refetchQueries: ['GetAgent'] });\n const [updateAgent] = useUpdateAgentMutation({ refetchQueries: ['GetAgent'] });\n const [deleteAgent] = useDeleteAgentMutation();\n const [checkSessionHealth] = useCheckSessionHealthMutation({ refetchQueries: ['GetAgent'] });\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 | '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 '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 // Config form refs\n const agentNameRef = useRef<HTMLInputElement>(null);\n const agentTunnelUrlRef = useRef<HTMLInputElement>(null);\n const agentApiKeyRef = 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\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 // 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 // ── 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 && agent.agentApiKey);\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 const pluginsFetchedRef = useRef(false);\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({ variables: { agentId: agent.id } });\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]);\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 && !pluginsFetchedRef.current) {\n pluginsFetchedRef.current = true;\n fetchPlugins();\n }\n }, [agent?.id, 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 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 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 (!hasPermission(VIBE_PERMISSIONS.AGENT_READ))\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 const handleStartAgent = async () => {\n if (!agent?.id) return;\n try {\n await agentHeartbeat({ variables: { id: agent.id } });\n } catch (err) {\n console.error('Failed to start agent:', err);\n }\n };\n\n const handleStopAgent = async () => {\n if (!agent?.id) return;\n try {\n await updateAgent({\n variables: { id: agent.id, input: { metadata: { status: 'inactive' } } },\n });\n } catch (err) {\n console.error('Failed to stop agent:', err);\n }\n };\n\n const handleConfigureAgent = () => {\n setConfigError(null);\n setShowConfigModal(true);\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 agentApiKey = agentApiKeyRef.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 await updateAgent({\n variables: {\n id: agent.id,\n input: {\n name,\n ...(tunnelUrl !== undefined ? { tunnelUrl: tunnelUrl || null } : {}),\n ...(agentApiKey !== undefined ? { agentApiKey: agentApiKey || 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 if (!agent?.agentApiKey) return;\n try {\n await nativeCopyText(agent.agentApiKey);\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 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 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 onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-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 onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-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 onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-4\" />\n {tr('agentDetails.backToAgents', 'Back to Agents')}\n </button>\n <EmptyState\n icon={<Server className=\"w-8 h-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 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: '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 {/* Back Button */}\n <button\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-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 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={`w-4 h-4 ${loading ? 'animate-spin' : ''}`} />\n </button>\n {agent.isActive ? (\n <button\n onClick={handleStopAgent}\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 <Square className=\"w-4 h-4\" />\n {tr('sessions.stop', 'Stop')}\n </button>\n ) : (\n <button\n onClick={handleStartAgent}\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\"\n >\n <Play className=\"w-4 h-4\" />\n {tr('agentDetails.start', 'Start')}\n </button>\n )}\n <OpenInBrowserEditorButton\n tunnelUrl={agent.tunnelUrl || null}\n agentApiKey={agent.agentApiKey || null}\n profile={activeProfile}\n />\n <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=\"w-4 h-4\" />\n {tr('agentDetails.configure', 'Configure')}\n </button>\n <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=\"w-4 h-4\" />\n {tr('sessions.remove', 'Remove')}\n </button>\n </div>\n }\n />\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=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Server className=\"w-5 h-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">{tr('sessions.filterStatus', 'Status')}</p>\n <StatusBadge status={agent.isActive ? 'ACTIVE' : 'OFFLINE'} size=\"md\" />\n </div>\n </div>\n </Card>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Cpu className=\"w-5 h-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=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <HardDrive className=\"w-5 h-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=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Terminal className=\"w-5 h-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 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=\"w-4 h-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 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 px-2 py-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=\"w-5 h-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=\"w-5 h-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=\"w-5 h-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=\"w-5 h-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=\"w-5 h-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 {/* Tunnel API Key Usage */}\n {agent.tunnelUrl && agent.agentApiKey && (\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 <Info className=\"w-5 h-5\" />\n {tr('agentDetails.apiAuthentication', 'API Authentication')}\n </h3>\n </div>\n <div className=\"p-4 space-y-3\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\n 'agentDetails.apiAuthenticationDescription',\n 'All requests to the agent (except health checks) require authentication. You can pass the API key in two ways:'\n )}\n </p>\n <div className=\"space-y-2\">\n <div>\n <p className=\"text-xs font-medium text-text-primary mb-1\">\n {tr('agentDetails.authHeaderRecommended', 'Header (recommended)')}\n </p>\n <code className=\"block text-xs font-mono bg-bg-sunken px-3 py-2 rounded-md text-text-primary overflow-x-auto\">\n x-agent-api-key: {agent.agentApiKey.slice(0, 12)}...\n </code>\n </div>\n <div>\n <p className=\"text-xs font-medium text-text-primary mb-1\">\n {tr('agentDetails.authQueryParameter', 'URL query parameter')}\n </p>\n <code className=\"block text-xs font-mono bg-bg-sunken px-3 py-2 rounded-md text-text-primary overflow-x-auto break-all\">\n {agent.tunnelUrl}/api/health?apiKey={agent.agentApiKey.slice(0, 12)}...\n </code>\n </div>\n </div>\n <p className=\"text-xs text-text-muted\">\n {tr('agentDetails.authExemptPrefix', 'The')}{' '}\n <code className=\"font-mono\">/health</code>{' '}\n {tr('agentDetails.authExemptAnd', 'and')}{' '}\n <code className=\"font-mono\">/api/agent/identity</code>{' '}\n {tr(\n 'agentDetails.authExemptSuffix',\n 'endpoints are exempt from authentication. The key changes on each agent restart unless a static key is configured.'\n )}\n </p>\n </div>\n </Card>\n )}\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=\"w-5 h-5\" />\n {tr('agentDetails.agentApiKey', 'Agent API Key')}\n </h3>\n </div>\n <div className=\"p-4\">\n {agent.agentApiKey ? (\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\n ? agent.agentApiKey\n : '\\u2022'.repeat(Math.min(agent.agentApiKey.length, 32))}\n </code>\n </div>\n <button\n onClick={() => setShowApiKey(!showApiKey)}\n className=\"p-2 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\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=\"w-4 h-4 text-text-secondary\" />\n ) : (\n <Eye className=\"w-4 h-4 text-text-secondary\" />\n )}\n </button>\n <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=\"w-4 h-4 text-status-success-text\" />\n ) : (\n <Copy className=\"w-4 h-4 text-text-secondary\" />\n )}\n </button>\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n No API key configured. Set one via the Configure button or agent CLI.\n </p>\n )}\n <p className=\"mt-2 text-xs text-text-muted\">\n This key authenticates requests sent to the agent. It typically changes on each\n agent restart.\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=\"w-5 h-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 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={`w-4 h-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 w-4 h-4 text-text-muted\" />\n <input\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 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=\"w-3.5 h-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 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 ? 'border-action-primary-bg text-action-primary-text'\n : 'border-transparent text-text-secondary hover:text-text-primary hover:border-border-default'\n }`}\n >\n <TabIcon className=\"w-3.5 h-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=\"w-4 h-4 flex-shrink-0\" />\n <span className=\"flex-1\">{pluginError}</span>\n <button\n onClick={() => setPluginError(null)}\n className=\"flex-shrink-0 p-0.5 hover:bg-status-error-text/10 rounded\"\n >\n <X className=\"w-3.5 h-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=\"w-4 h-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 {/* ── 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 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=\"w-3 h-3\" />\n Open UI\n </button>\n )}\n {!plugin.isCore && (\n <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 text-status-error-text bg-status-error-bg rounded-md hover:bg-status-error-bg/80 transition-colors disabled:opacity-50\"\n >\n {pluginActionLoading === plugin.packageName ? (\n <Loader2 className=\"w-3 h-3 animate-spin\" />\n ) : (\n <Trash2 className=\"w-3 h-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 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 flex-shrink-0 sm:ml-3\"\n >\n {pluginActionLoading === plugin.packageName ? (\n <Loader2 className=\"w-3 h-3 animate-spin\" />\n ) : (\n <Download className=\"w-3 h-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=\"w-4 h-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=\"w-10 h-10 rounded-md object-cover flex-shrink-0\"\n />\n ) : (\n <div className=\"w-10 h-10 flex-shrink-0 rounded-md bg-bg-secondary flex items-center justify-center\">\n <Puzzle className=\"w-5 h-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 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 agentApiKey={agent?.agentApiKey}\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=\"w-4 h-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\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Terminal className=\"w-5 h-5\" />\n {tr('nav.sessions', 'Sessions')} ({agentSessions.length})\n </h3>\n </div>\n {agentSessions.length > 0 ? (\n <div className=\"divide-y divide-border-primary\">\n {agentSessions.map((session: SessionItem) => (\n <div\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=\"w-5 h-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\">\n {tr('agentDetails.noSessionsOnAgent', 'No sessions on this agent')}\n </div>\n )}\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=\"w-5 h-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=\"w-5 h-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 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=\"w-5 h-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 && agent.agentApiKey && (\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\n agentTunnelUrl={agent.tunnelUrl}\n agentApiKey={agent.agentApiKey}\n profile={activeProfile}\n />\n </motion.div>\n )}\n\n {activeTab === 'backup' && (!agent.tunnelUrl || !agent.agentApiKey) && (\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=\"w-8 h-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 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 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 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 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 <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('agentDetails.agentApiKey', 'Agent API Key')}\n </label>\n <input\n ref={agentApiKeyRef}\n type=\"text\"\n defaultValue={agent.agentApiKey ?? ''}\n placeholder={tr('agentDetails.agentApiKeyPlaceholder', 'sk-agent-...')}\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.agentApiKeyHint',\n 'Used to authenticate requests to the agent. Leave empty to clear.'\n )}\n </p>\n </div>\n <div>\n <div className=\"flex items-center gap-1.5 mb-1\">\n <label className=\"text-sm font-medium text-text-primary\">AI Context</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=\"w-3.5 h-3.5\" />\n </button>\n {showAiContextInfo && (\n <>\n <div\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: "Production billing server. Do not modify files outside\n /src. Node 20, Docker installed."\n </p>\n </div>\n </>\n )}\n </div>\n </div>\n <textarea\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 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 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 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 <QuotaExhaustedDialog\n isOpen={showQuotaExhausted}\n onClose={() => setShowQuotaExhausted(false)}\n onConfirm={() => {\n setShowQuotaExhausted(false);\n navigate('/billing');\n }}\n title=\"Plugin Install Quota Reached\"\n message=\"You have used the plugin installation quota for your current plan. Upgrade to install more plugins.\"\n />\n </MotionPage>\n );\n}\n"],"mappings":"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"}
|