@apteva/apteva-linux-x64 0.4.31
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/apteva +0 -0
- package/dist/ActivityPage.41nbye4r.js +3 -0
- package/dist/ActivityPage.41nbye4r.js.map +9 -0
- package/dist/ApiDocsPage.4smnt8m3.js +4 -0
- package/dist/ApiDocsPage.4smnt8m3.js.map +10 -0
- package/dist/App.0sbax9et.js +4 -0
- package/dist/App.0sbax9et.js.map +10 -0
- package/dist/App.0ws427h8.js +4 -0
- package/dist/App.0ws427h8.js.map +10 -0
- package/dist/App.6q6bar8b.js +4 -0
- package/dist/App.6q6bar8b.js.map +10 -0
- package/dist/App.80301vdb.js +4 -0
- package/dist/App.80301vdb.js.map +10 -0
- package/dist/App.af2wg84v.js +267 -0
- package/dist/App.af2wg84v.js.map +35 -0
- package/dist/App.ca1rz1ph.js +4 -0
- package/dist/App.ca1rz1ph.js.map +14 -0
- package/dist/App.ensa6z0r.js +4 -0
- package/dist/App.ensa6z0r.js.map +10 -0
- package/dist/App.f8g7tych.js +13 -0
- package/dist/App.f8g7tych.js.map +10 -0
- package/dist/App.mvtqv6qc.js +20 -0
- package/dist/App.mvtqv6qc.js.map +14 -0
- package/dist/App.ncgc9cxy.js +4 -0
- package/dist/App.ncgc9cxy.js.map +10 -0
- package/dist/App.p02f4ret.js +1 -0
- package/dist/App.p0fb1pds.js +4 -0
- package/dist/App.p0fb1pds.js.map +10 -0
- package/dist/App.pmaq48sj.js +4 -0
- package/dist/App.pmaq48sj.js.map +10 -0
- package/dist/App.yv87t9m5.js +4 -0
- package/dist/App.yv87t9m5.js.map +10 -0
- package/dist/App.zjmfm8p6.js +4 -0
- package/dist/App.zjmfm8p6.js.map +10 -0
- package/dist/ConnectionsPage.anb3rv9a.js +3 -0
- package/dist/ConnectionsPage.anb3rv9a.js.map +9 -0
- package/dist/McpPage.y396h6fy.js +3 -0
- package/dist/McpPage.y396h6fy.js.map +9 -0
- package/dist/SettingsPage.p1hc60gk.js +3 -0
- package/dist/SettingsPage.p1hc60gk.js.map +9 -0
- package/dist/SkillsPage.yj3xdsay.js +3 -0
- package/dist/SkillsPage.yj3xdsay.js.map +9 -0
- package/dist/TasksPage.sjv0khtv.js +3 -0
- package/dist/TasksPage.sjv0khtv.js.map +9 -0
- package/dist/TelemetryPage.2qm4w16r.js +3 -0
- package/dist/TelemetryPage.2qm4w16r.js.map +9 -0
- package/dist/TestsPage.zzs4qfj8.js +3 -0
- package/dist/TestsPage.zzs4qfj8.js.map +9 -0
- package/dist/apteva-kit.css +1 -0
- package/dist/icon.png +0 -0
- package/dist/index.html +16 -0
- package/dist/styles.css +1 -0
- package/index.js +1 -0
- package/package.json +10 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/web/components/mcp/McpPage.tsx"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import React, { useState, useEffect } from \"react\";\nimport { McpIcon } from \"../common/Icons\";\nimport { useAuth, useProjects } from \"../../context\";\nimport { useConfirm, useAlert } from \"../common/Modal\";\nimport { Select } from \"../common/Select\";\nimport type { McpTool, McpToolCallResult } from \"../../types\";\nimport { IntegrationsPanel } from \"./IntegrationsPanel\";\n\ninterface McpServer {\n id: string;\n name: string;\n type: \"npm\" | \"pip\" | \"github\" | \"http\" | \"custom\";\n package: string | null;\n pip_module: string | null; // For pip type: module to run (e.g., \"late.mcp\")\n command: string | null;\n args: string | null;\n env: Record<string, string>;\n url: string | null;\n headers: Record<string, string>;\n port: number | null;\n status: \"stopped\" | \"running\";\n source: string | null; // \"composio\", \"smithery\", or null for local\n project_id: string | null; // null = global\n created_at: string;\n}\n\ninterface RegistryServer {\n id: string;\n name: string;\n fullName: string;\n description: string;\n version?: string;\n repository?: string;\n npmPackage: string | null;\n remoteUrl: string | null;\n transport: string;\n}\n\nexport function McpPage() {\n const { authFetch } = useAuth();\n const { projects, currentProjectId } = useProjects();\n const [servers, setServers] = useState<McpServer[]>([]);\n const [loading, setLoading] = useState(true);\n const [showAdd, setShowAdd] = useState(false);\n const [editingServer, setEditingServer] = useState<McpServer | null>(null);\n const [selectedServer, setSelectedServer] = useState<McpServer | null>(null);\n const [activeTab, setActiveTab] = useState<\"servers\" | \"hosted\" | \"registry\">(\"servers\");\n const { confirm, ConfirmDialog } = useConfirm();\n\n const hasProjects = projects.length > 0;\n\n const fetchServers = async () => {\n try {\n const res = await authFetch(\"/api/mcp/servers\");\n const data = await res.json();\n setServers(data.servers || []);\n } catch (e) {\n console.error(\"Failed to fetch MCP servers:\", e);\n }\n setLoading(false);\n };\n\n useEffect(() => {\n fetchServers();\n }, [authFetch]);\n\n // Filter servers based on global project selector\n // When a project is selected, show global + that project's servers\n const filteredServers = servers.filter(server => {\n if (!currentProjectId) return true; // \"All Projects\" - show everything\n if (currentProjectId === \"unassigned\") return server.project_id === null; // Only global\n // Project selected: show global + project-specific\n return server.project_id === null || server.project_id === currentProjectId;\n });\n\n const startServer = async (id: string) => {\n try {\n await authFetch(`/api/mcp/servers/${id}/start`, { method: \"POST\" });\n fetchServers();\n } catch (e) {\n console.error(\"Failed to start server:\", e);\n }\n };\n\n const stopServer = async (id: string) => {\n try {\n await authFetch(`/api/mcp/servers/${id}/stop`, { method: \"POST\" });\n fetchServers();\n } catch (e) {\n console.error(\"Failed to stop server:\", e);\n }\n };\n\n const deleteServer = async (id: string) => {\n const confirmed = await confirm(\"Delete this MCP server?\", { confirmText: \"Delete\", title: \"Delete Server\" });\n if (!confirmed) return;\n try {\n await authFetch(`/api/mcp/servers/${id}`, { method: \"DELETE\" });\n if (selectedServer?.id === id) {\n setSelectedServer(null);\n }\n fetchServers();\n } catch (e) {\n console.error(\"Failed to delete server:\", e);\n }\n };\n\n const renameServer = async (id: string, newName: string) => {\n try {\n await authFetch(`/api/mcp/servers/${id}`, {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ name: newName }),\n });\n fetchServers();\n } catch (e) {\n console.error(\"Failed to rename server:\", e);\n }\n };\n\n const updateServer = async (id: string, updates: Partial<McpServer>) => {\n try {\n await authFetch(`/api/mcp/servers/${id}`, {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(updates),\n });\n fetchServers();\n } catch (e) {\n console.error(\"Failed to update server:\", e);\n throw e;\n }\n };\n\n return (\n <>\n {ConfirmDialog}\n <div className=\"flex-1 overflow-auto p-6\">\n <div className=\"max-w-6xl\">\n {/* Header */}\n <div className=\"flex items-center justify-between mb-6\">\n <div>\n <h1 className=\"text-2xl font-semibold mb-1\">MCP Servers</h1>\n <p className=\"text-[#666]\">\n Manage Model Context Protocol servers for tool integrations.\n </p>\n </div>\n {activeTab === \"servers\" && (\n <button\n onClick={() => setShowAdd(true)}\n className=\"bg-[#f97316] hover:bg-[#fb923c] text-black px-4 py-2 rounded font-medium transition\"\n >\n + Add Server\n </button>\n )}\n </div>\n\n {/* Tabs */}\n <div className=\"flex gap-1 mb-6 bg-[#111] border border-[#1a1a1a] rounded-lg p-1 w-fit\">\n <button\n onClick={() => setActiveTab(\"servers\")}\n className={`px-4 py-2 rounded text-sm font-medium transition ${\n activeTab === \"servers\"\n ? \"bg-[#1a1a1a] text-white\"\n : \"text-[#666] hover:text-[#888]\"\n }`}\n >\n My Servers\n </button>\n <button\n onClick={() => setActiveTab(\"hosted\")}\n className={`px-4 py-2 rounded text-sm font-medium transition ${\n activeTab === \"hosted\"\n ? \"bg-[#1a1a1a] text-white\"\n : \"text-[#666] hover:text-[#888]\"\n }`}\n >\n Hosted Services\n </button>\n <button\n onClick={() => setActiveTab(\"registry\")}\n className={`px-4 py-2 rounded text-sm font-medium transition ${\n activeTab === \"registry\"\n ? \"bg-[#1a1a1a] text-white\"\n : \"text-[#666] hover:text-[#888]\"\n }`}\n >\n Browse Registry\n </button>\n </div>\n\n {/* My Servers Tab */}\n {activeTab === \"servers\" && (\n <>\n {/* Loading */}\n {loading && (\n <div className=\"text-center py-8 text-[#666]\">Loading...</div>\n )}\n\n {/* Empty State */}\n {!loading && filteredServers.length === 0 && servers.length === 0 && (\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-8 text-center\">\n <McpIcon className=\"w-12 h-12 text-[#333] mx-auto mb-4\" />\n <h3 className=\"text-lg font-medium mb-2\">No MCP servers configured</h3>\n <p className=\"text-[#666] mb-6 max-w-md mx-auto\">\n MCP servers extend your agents with tools like file access, web browsing,\n database connections, and more.\n </p>\n <div className=\"flex gap-3 justify-center\">\n <button\n onClick={() => setShowAdd(true)}\n className=\"bg-[#f97316] hover:bg-[#fb923c] text-black px-4 py-2 rounded font-medium transition\"\n >\n Add Manually\n </button>\n <button\n onClick={() => setActiveTab(\"registry\")}\n className=\"border border-[#333] hover:border-[#666] px-4 py-2 rounded font-medium transition\"\n >\n Browse Registry\n </button>\n </div>\n </div>\n )}\n\n {/* Empty filter state */}\n {!loading && filteredServers.length === 0 && servers.length > 0 && (\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-6 text-center\">\n <p className=\"text-[#666]\">No servers match this filter.</p>\n </div>\n )}\n\n {/* Main content with server list and tools panel */}\n {!loading && filteredServers.length > 0 && (\n <div className=\"flex gap-6\">\n {/* Server List */}\n <div className={`space-y-3 ${selectedServer ? \"w-1/2\" : \"w-full\"}`}>\n {filteredServers.map(server => {\n const isRemote = server.type === \"http\" && server.url;\n const isAvailable = isRemote || server.status === \"running\";\n const project = hasProjects && server.project_id\n ? projects.find(p => p.id === server.project_id)\n : null;\n return (\n <McpServerCard\n key={server.id}\n server={server}\n project={project}\n selected={selectedServer?.id === server.id}\n onSelect={() => setSelectedServer(isAvailable ? server : null)}\n onStart={() => startServer(server.id)}\n onStop={() => stopServer(server.id)}\n onDelete={() => deleteServer(server.id)}\n onEdit={() => setEditingServer(server)}\n />\n );\n })}\n </div>\n\n {/* Tools Panel */}\n {selectedServer && (\n <div className=\"w-1/2\">\n <ToolsPanel\n server={selectedServer}\n onClose={() => setSelectedServer(null)}\n />\n </div>\n )}\n </div>\n )}\n </>\n )}\n\n {/* Hosted Services Tab */}\n {activeTab === \"hosted\" && (\n <HostedServices onServerAdded={fetchServers} projectId={currentProjectId} />\n )}\n\n {/* Browse Registry Tab */}\n {activeTab === \"registry\" && (\n <RegistryBrowser\n onInstall={(server) => {\n // After installing, switch to servers tab and refresh\n fetchServers();\n setActiveTab(\"servers\");\n }}\n />\n )}\n\n {/* Info - only show on servers tab */}\n {activeTab === \"servers\" && (\n <div className=\"mt-8 p-4 bg-[#111] border border-[#1a1a1a] rounded-lg\">\n <h3 className=\"font-medium mb-2\">Quick Start</h3>\n <p className=\"text-sm text-[#666] mb-3\">\n Add an MCP server by providing its npm package name. For example:\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {[\n { name: \"filesystem\", pkg: \"@modelcontextprotocol/server-filesystem\" },\n { name: \"fetch\", pkg: \"@modelcontextprotocol/server-fetch\" },\n { name: \"memory\", pkg: \"@modelcontextprotocol/server-memory\" },\n ].map(s => (\n <code key={s.name} className=\"text-xs bg-[#0a0a0a] px-2 py-1 rounded\">\n {s.pkg}\n </code>\n ))}\n </div>\n </div>\n )}\n </div>\n\n {/* Add Server Modal */}\n {showAdd && (\n <AddServerModal\n onClose={() => setShowAdd(false)}\n onAdded={() => {\n setShowAdd(false);\n fetchServers();\n }}\n projects={hasProjects ? projects : undefined}\n defaultProjectId={currentProjectId && currentProjectId !== \"unassigned\" ? currentProjectId : null}\n />\n )}\n\n {editingServer && (\n <EditServerModal\n server={editingServer}\n projects={hasProjects ? projects : undefined}\n onClose={() => setEditingServer(null)}\n onSaved={() => {\n setEditingServer(null);\n fetchServers();\n }}\n />\n )}\n </div>\n </>\n );\n}\n\nfunction McpServerCard({\n server,\n project,\n selected,\n onSelect,\n onStart,\n onStop,\n onDelete,\n onEdit,\n}: {\n server: McpServer;\n project?: { id: string; name: string; color: string } | null;\n selected: boolean;\n onSelect: () => void;\n onStart: () => void;\n onStop: () => void;\n onDelete: () => void;\n onEdit: () => void;\n}) {\n // Remote/hosted servers (http type with url) are always available\n const isRemote = server.type === \"http\" && server.url;\n const isAvailable = isRemote || server.status === \"running\";\n\n // Determine what to show as the server info\n const getServerInfo = () => {\n if (isRemote) {\n // Show source (composio, smithery) or just \"remote\"\n const source = server.source || \"remote\";\n return `${source} • http`;\n }\n return `${server.type} • ${server.package || server.command || \"custom\"}${\n server.status === \"running\" && server.port ? ` • :${server.port}` : \"\"\n }`;\n };\n\n // Scope badge: Global or Project name\n const getScopeBadge = () => {\n if (project) {\n return (\n <span\n className=\"text-xs px-1.5 py-0.5 rounded\"\n style={{ backgroundColor: `${project.color}20`, color: project.color }}\n >\n {project.name}\n </span>\n );\n }\n if (server.project_id === null) {\n return (\n <span className=\"text-xs text-[#666] bg-[#1a1a1a] px-1.5 py-0.5 rounded\">\n Global\n </span>\n );\n }\n return null;\n };\n\n return (\n <div\n className={`bg-[#111] border rounded-lg p-4 cursor-pointer transition ${\n selected ? \"border-[#f97316]\" : \"border-[#1a1a1a] hover:border-[#333]\"\n }`}\n onClick={isAvailable ? onSelect : undefined}\n >\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className={`w-2 h-2 rounded-full ${\n isAvailable ? \"bg-green-400\" : \"bg-[#444]\"\n }`} />\n <div>\n <div className=\"flex items-center gap-2\">\n <h3 className=\"font-medium\">{server.name}</h3>\n {getScopeBadge()}\n </div>\n <p className=\"text-sm text-[#666]\">{getServerInfo()}</p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={(e) => { e.stopPropagation(); onEdit(); }}\n className=\"text-sm text-[#666] hover:text-[#888] px-3 py-1 transition\"\n title=\"Edit server settings\"\n >\n Edit\n </button>\n {isRemote ? (\n // Remote servers: no start/stop, just delete\n <button\n onClick={(e) => { e.stopPropagation(); onDelete(); }}\n className=\"text-sm text-[#666] hover:text-red-400 px-3 py-1 transition\"\n >\n Remove\n </button>\n ) : server.status === \"running\" ? (\n // Local running server: tools + stop + delete\n <>\n <button\n onClick={(e) => { e.stopPropagation(); onSelect(); }}\n className=\"text-sm text-[#f97316] hover:text-[#fb923c] px-3 py-1 transition\"\n >\n Tools\n </button>\n <button\n onClick={(e) => { e.stopPropagation(); onStop(); }}\n className=\"text-sm text-[#666] hover:text-red-400 px-3 py-1 transition\"\n >\n Stop\n </button>\n <button\n onClick={(e) => { e.stopPropagation(); onDelete(); }}\n className=\"text-sm text-[#666] hover:text-red-400 px-3 py-1 transition\"\n >\n Delete\n </button>\n </>\n ) : (\n // Local stopped server: start + delete\n <>\n <button\n onClick={(e) => { e.stopPropagation(); onStart(); }}\n className=\"text-sm text-[#666] hover:text-green-400 px-3 py-1 transition\"\n >\n Start\n </button>\n <button\n onClick={(e) => { e.stopPropagation(); onDelete(); }}\n className=\"text-sm text-[#666] hover:text-red-400 px-3 py-1 transition\"\n >\n Delete\n </button>\n </>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction ToolsPanel({\n server,\n onClose,\n}: {\n server: McpServer;\n onClose: () => void;\n}) {\n const { authFetch } = useAuth();\n const [tools, setTools] = useState<McpTool[]>([]);\n const [serverInfo, setServerInfo] = useState<{ name: string; version: string } | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [selectedTool, setSelectedTool] = useState<McpTool | null>(null);\n\n useEffect(() => {\n const fetchTools = async () => {\n setLoading(true);\n setError(null);\n try {\n const res = await authFetch(`/api/mcp/servers/${server.id}/tools`);\n const data = await res.json();\n if (!res.ok) {\n setError(data.error || \"Failed to fetch tools\");\n return;\n }\n setTools(data.tools || []);\n setServerInfo(data.serverInfo || null);\n } catch (e) {\n setError(`Failed to fetch tools: ${e}`);\n } finally {\n setLoading(false);\n }\n };\n\n fetchTools();\n }, [server.id, authFetch]);\n\n return (\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg overflow-hidden\">\n {/* Header */}\n <div className=\"p-4 border-b border-[#1a1a1a] flex items-center justify-between\">\n <div>\n <h3 className=\"font-medium\">{server.name} Tools</h3>\n {serverInfo && (\n <p className=\"text-xs text-[#666]\">\n {serverInfo.name} v{serverInfo.version}\n </p>\n )}\n </div>\n <button\n onClick={onClose}\n className=\"text-[#666] hover:text-[#888] text-xl leading-none\"\n >\n ×\n </button>\n </div>\n\n {/* Content */}\n <div className=\"p-4 max-h-[500px] overflow-auto\">\n {loading && <p className=\"text-[#666]\">Loading tools...</p>}\n\n {error && (\n <div className=\"text-red-400 text-sm p-3 bg-red-500/10 rounded\">\n {error}\n </div>\n )}\n\n {!loading && !error && tools.length === 0 && (\n <p className=\"text-[#666]\">No tools available from this server.</p>\n )}\n\n {!loading && !error && tools.length > 0 && !selectedTool && (\n <div className=\"space-y-2\">\n {tools.map(tool => (\n <button\n key={tool.name}\n onClick={() => setSelectedTool(tool)}\n className=\"w-full text-left p-3 bg-[#0a0a0a] hover:bg-[#1a1a1a] border border-[#222] hover:border-[#333] rounded transition\"\n >\n <div className=\"font-medium text-sm\">{tool.name}</div>\n {tool.description && (\n <div className=\"text-xs text-[#666] mt-1\">{tool.description}</div>\n )}\n </button>\n ))}\n </div>\n )}\n\n {selectedTool && (\n <ToolTester\n serverId={server.id}\n tool={selectedTool}\n onBack={() => setSelectedTool(null)}\n />\n )}\n </div>\n </div>\n );\n}\n\nfunction ToolTester({\n serverId,\n tool,\n onBack,\n}: {\n serverId: string;\n tool: McpTool;\n onBack: () => void;\n}) {\n const { authFetch } = useAuth();\n const [args, setArgs] = useState<string>(\"{}\");\n const [result, setResult] = useState<McpToolCallResult | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n\n // Generate default args from schema\n useEffect(() => {\n const schema = tool.inputSchema;\n if (schema && typeof schema === \"object\" && \"properties\" in schema) {\n const properties = schema.properties as Record<string, { type?: string; default?: unknown }>;\n const defaultArgs: Record<string, unknown> = {};\n for (const [key, prop] of Object.entries(properties)) {\n if (prop.default !== undefined) {\n defaultArgs[key] = prop.default;\n } else if (prop.type === \"string\") {\n defaultArgs[key] = \"\";\n } else if (prop.type === \"number\" || prop.type === \"integer\") {\n defaultArgs[key] = 0;\n } else if (prop.type === \"boolean\") {\n defaultArgs[key] = false;\n } else if (prop.type === \"array\") {\n defaultArgs[key] = [];\n } else if (prop.type === \"object\") {\n defaultArgs[key] = {};\n }\n }\n setArgs(JSON.stringify(defaultArgs, null, 2));\n }\n }, [tool]);\n\n const callTool = async () => {\n setLoading(true);\n setError(null);\n setResult(null);\n\n try {\n const parsedArgs = JSON.parse(args);\n const res = await authFetch(`/api/mcp/servers/${serverId}/tools/${encodeURIComponent(tool.name)}/call`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ arguments: parsedArgs }),\n });\n const data = await res.json();\n\n if (!res.ok) {\n setError(data.error || \"Failed to call tool\");\n return;\n }\n\n setResult(data.result);\n } catch (e) {\n setError(`Error: ${e}`);\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <div className=\"space-y-4\">\n {/* Header */}\n <div className=\"flex items-center gap-2\">\n <button\n onClick={onBack}\n className=\"text-[#666] hover:text-[#888] text-sm\"\n >\n ← Back\n </button>\n <span className=\"text-[#444]\">/</span>\n <span className=\"font-medium\">{tool.name}</span>\n </div>\n\n {/* Description */}\n {tool.description && (\n <p className=\"text-sm text-[#666]\">{tool.description}</p>\n )}\n\n {/* Schema info */}\n {tool.inputSchema && (\n <div className=\"text-xs\">\n <details className=\"cursor-pointer\">\n <summary className=\"text-[#666] hover:text-[#888]\">Input Schema</summary>\n <pre className=\"mt-2 p-2 bg-[#0a0a0a] rounded text-[#888] overflow-auto max-h-32\">\n {JSON.stringify(tool.inputSchema, null, 2)}\n </pre>\n </details>\n </div>\n )}\n\n {/* Arguments input */}\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Arguments (JSON)</label>\n <textarea\n value={args}\n onChange={(e) => setArgs(e.target.value)}\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 h-32 font-mono text-sm focus:outline-none focus:border-[#f97316] resize-none\"\n placeholder=\"{}\"\n />\n </div>\n\n {/* Call button */}\n <button\n onClick={callTool}\n disabled={loading}\n className=\"w-full bg-[#f97316] hover:bg-[#fb923c] disabled:opacity-50 text-black px-4 py-2 rounded font-medium transition\"\n >\n {loading ? \"Calling...\" : \"Call Tool\"}\n </button>\n\n {/* Error */}\n {error && (\n <div className=\"text-red-400 text-sm p-3 bg-red-500/10 rounded\">\n {error}\n </div>\n )}\n\n {/* Result */}\n {result && (\n <div className=\"space-y-2\">\n <div className=\"text-sm text-[#666]\">\n Result {result.isError && <span className=\"text-red-400\">(error)</span>}\n </div>\n <div className={`p-3 rounded text-sm ${result.isError ? \"bg-red-500/10\" : \"bg-green-500/10\"}`}>\n {result.content.map((block, i) => (\n <div key={i} className=\"mb-2 last:mb-0\">\n {block.type === \"text\" && (\n <pre className=\"whitespace-pre-wrap font-mono text-xs\">\n {block.text}\n </pre>\n )}\n {block.type === \"image\" && block.data && (\n <img\n src={`data:${block.mimeType || \"image/png\"};base64,${block.data}`}\n alt=\"Tool result\"\n className=\"max-w-full rounded\"\n />\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n}\n\nfunction RegistryBrowser({\n onInstall,\n}: {\n onInstall: (server: RegistryServer) => void;\n}) {\n const { authFetch } = useAuth();\n const [search, setSearch] = useState(\"\");\n const [servers, setServers] = useState<RegistryServer[]>([]);\n const [loading, setLoading] = useState(false);\n const [searched, setSearched] = useState(false);\n const [installing, setInstalling] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const searchRegistry = async (query: string) => {\n setLoading(true);\n setError(null);\n try {\n const res = await authFetch(`/api/mcp/registry?search=${encodeURIComponent(query)}&limit=20`);\n const data = await res.json();\n if (!res.ok) {\n setError(data.error || \"Failed to search registry\");\n setServers([]);\n } else {\n setServers(data.servers || []);\n }\n } catch (e) {\n setError(`Failed to search: ${e}`);\n setServers([]);\n } finally {\n setLoading(false);\n setSearched(true);\n }\n };\n\n const handleSearch = (e: React.FormEvent) => {\n e.preventDefault();\n if (search.trim()) {\n searchRegistry(search.trim());\n }\n };\n\n // Load popular servers on mount\n useEffect(() => {\n searchRegistry(\"\");\n }, []);\n\n const installServer = async (server: RegistryServer) => {\n if (!server.npmPackage) {\n setError(\"This server does not have an npm package\");\n return;\n }\n\n setInstalling(server.id);\n setError(null);\n\n try {\n const res = await authFetch(\"/api/mcp/servers\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n name: server.name,\n type: \"npm\",\n package: server.npmPackage,\n }),\n });\n\n if (!res.ok) {\n const data = await res.json();\n setError(data.error || \"Failed to add server\");\n return;\n }\n\n onInstall(server);\n } catch (e) {\n setError(`Failed to add server: ${e}`);\n } finally {\n setInstalling(null);\n }\n };\n\n return (\n <div className=\"space-y-6\">\n {/* Search */}\n <form onSubmit={handleSearch} className=\"flex gap-2\">\n <input\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search MCP servers (e.g., filesystem, github, slack...)\"\n className=\"flex-1 bg-[#111] border border-[#333] rounded-lg px-4 py-3 focus:outline-none focus:border-[#f97316]\"\n />\n <button\n type=\"submit\"\n disabled={loading}\n className=\"bg-[#f97316] hover:bg-[#fb923c] disabled:opacity-50 text-black px-6 py-3 rounded-lg font-medium transition\"\n >\n {loading ? \"...\" : \"Search\"}\n </button>\n </form>\n\n {/* Error */}\n {error && (\n <div className=\"text-red-400 text-sm p-3 bg-red-500/10 border border-red-500/20 rounded-lg\">\n {error}\n </div>\n )}\n\n {/* Results */}\n {!loading && searched && servers.length === 0 && (\n <div className=\"text-center py-8 text-[#666]\">\n No servers found. Try a different search term.\n </div>\n )}\n\n {servers.length > 0 && (\n <div className=\"grid gap-4 md:grid-cols-2\">\n {servers.map((server) => (\n <div\n key={server.id}\n className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-4 hover:border-[#333] transition\"\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"font-medium truncate\">{server.name}</h3>\n <p className=\"text-sm text-[#666] mt-1 line-clamp-2\">\n {server.description || \"No description\"}\n </p>\n <div className=\"flex items-center gap-2 mt-2 text-xs text-[#555]\">\n {server.version && <span>v{server.version}</span>}\n <span className={`px-1.5 py-0.5 rounded ${\n server.npmPackage ? \"bg-green-500/10 text-green-400\" : \"bg-blue-500/10 text-blue-400\"\n }`}>\n {server.npmPackage ? \"npm\" : \"remote\"}\n </span>\n </div>\n <code className=\"text-xs text-[#555] bg-[#0a0a0a] px-2 py-0.5 rounded mt-2 inline-block truncate max-w-full\">\n {server.npmPackage || server.fullName}\n </code>\n </div>\n <div className=\"flex-shrink-0\">\n {server.npmPackage ? (\n <button\n onClick={() => installServer(server)}\n disabled={installing === server.id}\n className=\"text-sm bg-[#1a1a1a] hover:bg-[#222] border border-[#333] hover:border-[#f97316] px-3 py-1.5 rounded transition disabled:opacity-50\"\n >\n {installing === server.id ? \"Adding...\" : \"Add\"}\n </button>\n ) : server.repository ? (\n <a\n href={server.repository}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-[#666] hover:text-[#f97316] transition\"\n >\n View →\n </a>\n ) : null}\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Loading */}\n {loading && (\n <div className=\"text-center py-8 text-[#666]\">\n Searching registry...\n </div>\n )}\n\n {/* Registry info */}\n <div className=\"p-4 bg-[#111] border border-[#1a1a1a] rounded-lg text-sm text-[#666]\">\n <p>\n Servers are sourced from the{\" \"}\n <a\n href=\"https://github.com/modelcontextprotocol/servers\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-[#f97316] hover:underline\"\n >\n official MCP registry\n </a>\n . Not all servers have npm packages - some require manual setup.\n </p>\n </div>\n </div>\n );\n}\n\n// Hosted MCP Services (Composio, Smithery, etc.)\ninterface ComposioConfig {\n id: string;\n name: string;\n toolkits: string[];\n toolsCount: number;\n mcpUrl: string;\n createdAt?: string;\n}\n\nfunction HostedServices({ onServerAdded, projectId }: { onServerAdded?: () => void; projectId?: string | null }) {\n const { authFetch } = useAuth();\n const [activeProvider, setActiveProvider] = useState<\"composio\" | \"smithery\" | \"agentdojo\">(\"composio\");\n const [subTab, setSubTab] = useState<\"configs\" | \"connect\">(\"configs\");\n const [composioConnected, setComposioConnected] = useState(false);\n const [smitheryConnected, setSmitheryConnected] = useState(false);\n const [agentDojoConnected, setAgentDojoConnected] = useState(false);\n const [composioConfigs, setComposioConfigs] = useState<ComposioConfig[]>([]);\n const [addedServers, setAddedServers] = useState<Set<string>>(new Set());\n const [loading, setLoading] = useState(true);\n const [loadingConfigs, setLoadingConfigs] = useState(false);\n const [addingConfig, setAddingConfig] = useState<string | null>(null);\n const { alert, AlertDialog } = useAlert();\n\n const fetchStatus = async () => {\n try {\n const serversUrl = projectId && projectId !== \"unassigned\"\n ? `/api/mcp/servers?project=${encodeURIComponent(projectId)}`\n : \"/api/mcp/servers\";\n const [providersRes, serversRes] = await Promise.all([\n authFetch(\"/api/providers\"),\n authFetch(serversUrl),\n ]);\n const providersData = await providersRes.json();\n const serversData = await serversRes.json();\n\n const providers = providersData.providers || [];\n const servers = serversData.servers || [];\n\n // Track which Composio config IDs are already added as servers\n // Extract config ID from URLs like https://backend.composio.dev/v3/mcp/{configId}/mcp?user_id=...\n const composioConfigIds = new Set(\n servers\n .filter((s: any) => s.source === \"composio\" && s.url)\n .map((s: any) => {\n const match = s.url.match(/\\/v3\\/mcp\\/([^/]+)/);\n return match ? match[1] : null;\n })\n .filter(Boolean)\n );\n setAddedServers(composioConfigIds);\n\n const composio = providers.find((p: any) => p.id === \"composio\");\n const smithery = providers.find((p: any) => p.id === \"smithery\");\n const agentdojo = providers.find((p: any) => p.id === \"agentdojo\");\n const composioHasKey = composio?.hasKey || false;\n const smitheryHasKey = smithery?.hasKey || false;\n const agentdojoHasKey = agentdojo?.hasKey || false;\n\n setComposioConnected(composioHasKey);\n setSmitheryConnected(smitheryHasKey);\n setAgentDojoConnected(agentdojoHasKey);\n\n // Set initial active provider to first connected one\n if (composioHasKey) {\n setActiveProvider(\"composio\");\n fetchComposioConfigs();\n } else if (smitheryHasKey) {\n setActiveProvider(\"smithery\");\n } else if (agentdojoHasKey) {\n setActiveProvider(\"agentdojo\");\n }\n } catch (e) {\n console.error(\"Failed to fetch providers:\", e);\n }\n setLoading(false);\n };\n\n const fetchComposioConfigs = async () => {\n setLoadingConfigs(true);\n try {\n const projectParam = projectId && projectId !== \"unassigned\" ? `?project_id=${projectId}` : \"\";\n const res = await authFetch(`/api/integrations/composio/configs${projectParam}`);\n const data = await res.json();\n setComposioConfigs(data.configs || []);\n } catch (e) {\n console.error(\"Failed to fetch Composio configs:\", e);\n }\n setLoadingConfigs(false);\n };\n\n const addComposioConfig = async (configId: string) => {\n setAddingConfig(configId);\n try {\n const projectParam = projectId && projectId !== \"unassigned\" ? `?project_id=${projectId}` : \"\";\n const res = await authFetch(`/api/integrations/composio/configs/${configId}/add${projectParam}`, {\n method: \"POST\",\n });\n if (res.ok) {\n // Mark as added by config ID\n setAddedServers(prev => new Set([...prev, configId]));\n onServerAdded?.();\n } else {\n const data = await res.json();\n await alert(data.error || \"Failed to add config\", { title: \"Error\", variant: \"error\" });\n }\n } catch (e) {\n console.error(\"Failed to add config:\", e);\n }\n setAddingConfig(null);\n };\n\n const isConfigAdded = (configId: string) => {\n return addedServers.has(configId);\n };\n\n useEffect(() => {\n fetchStatus();\n }, [authFetch, projectId]);\n\n if (loading) {\n return <div className=\"text-center py-8 text-[#666]\">Loading...</div>;\n }\n\n const hasAnyConnection = composioConnected || smitheryConnected || agentDojoConnected;\n const connectedCount = [composioConnected, smitheryConnected, agentDojoConnected].filter(Boolean).length;\n\n if (!hasAnyConnection) {\n return (\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-8 text-center\">\n <p className=\"text-[#888] mb-2\">No hosted MCP services connected</p>\n <p className=\"text-sm text-[#666] mb-4\">\n Connect Composio, Smithery, or AgentDojo in Settings to access cloud-based MCP servers.\n </p>\n <a\n href=\"/settings\"\n className=\"inline-block bg-[#1a1a1a] hover:bg-[#222] border border-[#333] hover:border-[#f97316] px-4 py-2 rounded text-sm font-medium transition\"\n >\n Go to Settings →\n </a>\n </div>\n );\n }\n\n return (\n <>\n {AlertDialog}\n <div className=\"space-y-6\">\n {/* Provider Tabs - show when multiple providers are connected */}\n {connectedCount > 1 && (\n <div className=\"flex gap-1 bg-[#0a0a0a] border border-[#222] rounded-lg p-1 w-fit\">\n {composioConnected && (\n <button\n onClick={() => { setActiveProvider(\"composio\"); setSubTab(\"configs\"); }}\n className={`px-4 py-2 rounded text-sm font-medium transition flex items-center gap-2 ${\n activeProvider === \"composio\"\n ? \"bg-[#1a1a1a] text-white\"\n : \"text-[#666] hover:text-[#888]\"\n }`}\n >\n <span className=\"w-2 h-2 rounded-full bg-purple-500\" />\n Composio\n </button>\n )}\n {smitheryConnected && (\n <button\n onClick={() => setActiveProvider(\"smithery\")}\n className={`px-4 py-2 rounded text-sm font-medium transition flex items-center gap-2 ${\n activeProvider === \"smithery\"\n ? \"bg-[#1a1a1a] text-white\"\n : \"text-[#666] hover:text-[#888]\"\n }`}\n >\n <span className=\"w-2 h-2 rounded-full bg-blue-500\" />\n Smithery\n </button>\n )}\n {agentDojoConnected && (\n <button\n onClick={() => setActiveProvider(\"agentdojo\")}\n className={`px-4 py-2 rounded text-sm font-medium transition flex items-center gap-2 ${\n activeProvider === \"agentdojo\"\n ? \"bg-[#1a1a1a] text-white\"\n : \"text-[#666] hover:text-[#888]\"\n }`}\n >\n <span className=\"w-2 h-2 rounded-full bg-green-500\" />\n AgentDojo\n </button>\n )}\n </div>\n )}\n\n {/* Composio Content */}\n {composioConnected && (connectedCount === 1 || activeProvider === \"composio\") && (\n <>\n {/* Sub-tabs for Composio */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex gap-1 bg-[#0a0a0a] border border-[#222] rounded-lg p-1\">\n <button\n onClick={() => setSubTab(\"configs\")}\n className={`px-4 py-2 rounded text-sm font-medium transition ${\n subTab === \"configs\"\n ? \"bg-[#1a1a1a] text-white\"\n : \"text-[#666] hover:text-[#888]\"\n }`}\n >\n MCP Configs\n </button>\n <button\n onClick={() => setSubTab(\"connect\")}\n className={`px-4 py-2 rounded text-sm font-medium transition ${\n subTab === \"connect\"\n ? \"bg-[#1a1a1a] text-white\"\n : \"text-[#666] hover:text-[#888]\"\n }`}\n >\n Connect Apps\n </button>\n </div>\n {connectedCount === 1 && (\n <div className=\"flex items-center gap-2 text-xs text-[#666]\">\n <span className=\"w-2 h-2 rounded-full bg-purple-500\" />\n Composio\n <span className=\"text-green-400\">Connected</span>\n </div>\n )}\n </div>\n\n {/* Connect Apps Tab */}\n {subTab === \"connect\" && (\n <div>\n <p className=\"text-sm text-[#666] mb-4\">\n Connect your accounts to enable tools in MCP configs\n </p>\n <IntegrationsPanel\n providerId=\"composio\"\n projectId={projectId}\n onConnectionComplete={() => {\n // Refresh configs after connecting an app\n fetchComposioConfigs();\n }}\n />\n </div>\n )}\n\n {/* MCP Configs Tab */}\n {subTab === \"configs\" && (\n <div>\n <div className=\"flex items-center justify-between mb-3\">\n <p className=\"text-sm text-[#666]\">\n Your MCP configs from Composio\n </p>\n <div className=\"flex items-center gap-3\">\n <button\n onClick={fetchComposioConfigs}\n disabled={loadingConfigs}\n className=\"text-xs text-[#666] hover:text-[#888] transition\"\n >\n {loadingConfigs ? \"Loading...\" : \"Refresh\"}\n </button>\n <a\n href=\"https://app.composio.dev/mcp_configs\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-xs text-[#666] hover:text-[#f97316] transition\"\n >\n Create Config →\n </a>\n </div>\n </div>\n\n {loadingConfigs ? (\n <div className=\"text-center py-6 text-[#666]\">Loading configs...</div>\n ) : composioConfigs.length === 0 ? (\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-4 text-center\">\n <p className=\"text-sm text-[#666]\">No MCP configs found</p>\n <p className=\"text-xs text-[#555] mt-2\">\n First <button onClick={() => setSubTab(\"connect\")} className=\"text-[#f97316] hover:text-[#fb923c]\">connect some apps</button>, then create a config.\n </p>\n <a\n href=\"https://app.composio.dev/mcp_configs\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-xs text-[#f97316] hover:text-[#fb923c] mt-2 inline-block\"\n >\n Create in Composio →\n </a>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {composioConfigs.map((config) => {\n const added = isConfigAdded(config.id);\n const isAdding = addingConfig === config.id;\n return (\n <div\n key={config.id}\n className={`bg-[#111] border rounded-lg p-3 transition flex items-center justify-between ${\n added ? \"border-green-500/30\" : \"border-[#1a1a1a] hover:border-[#333]\"\n }`}\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium text-sm\">{config.name}</span>\n <span className=\"text-xs text-[#555]\">{config.toolsCount} tools</span>\n {added && (\n <span className=\"text-xs text-green-400\">Added</span>\n )}\n </div>\n {config.toolkits.length > 0 && (\n <div className=\"flex flex-wrap gap-1 mt-1\">\n {config.toolkits.slice(0, 4).map((toolkit) => (\n <span\n key={toolkit}\n className=\"text-xs bg-[#1a1a1a] text-[#666] px-1.5 py-0.5 rounded\"\n >\n {toolkit}\n </span>\n ))}\n {config.toolkits.length > 4 && (\n <span className=\"text-xs text-[#555]\">+{config.toolkits.length - 4}</span>\n )}\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-2 ml-3\">\n {added ? (\n <span className=\"text-xs text-[#555] px-2 py-1\">In Servers</span>\n ) : (\n <button\n onClick={() => addComposioConfig(config.id)}\n disabled={isAdding}\n className=\"text-xs bg-[#f97316] hover:bg-[#fb923c] text-black px-3 py-1 rounded font-medium transition disabled:opacity-50\"\n >\n {isAdding ? \"Adding...\" : \"Add\"}\n </button>\n )}\n <a\n href={`https://app.composio.dev/mcp_configs/${config.id}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-xs text-[#666] hover:text-[#888] transition\"\n >\n Edit\n </a>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n )}\n </>\n )}\n\n {/* Smithery Content */}\n {smitheryConnected && (connectedCount === 1 || activeProvider === \"smithery\") && (\n <div>\n {connectedCount === 1 && (\n <div className=\"flex items-center gap-2 text-xs text-[#666] mb-4\">\n <span className=\"w-2 h-2 rounded-full bg-blue-500\" />\n Smithery\n <span className=\"text-green-400\">Connected</span>\n </div>\n )}\n <div className=\"flex items-center justify-between mb-3\">\n <p className=\"text-sm text-[#666]\">\n Add MCP servers from the Smithery registry\n </p>\n <a\n href=\"https://smithery.ai/servers\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-xs text-[#666] hover:text-[#f97316] transition\"\n >\n Browse Smithery →\n </a>\n </div>\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-4 text-center\">\n <p className=\"text-sm text-[#666]\">\n Smithery servers can be added from the <strong>Browse Registry</strong> tab.\n </p>\n <p className=\"text-xs text-[#555] mt-2\">\n Your API key will be used automatically when adding Smithery servers.\n </p>\n </div>\n </div>\n )}\n\n {/* AgentDojo Content */}\n {agentDojoConnected && (connectedCount === 1 || activeProvider === \"agentdojo\") && (\n <AgentDojoContent\n projectId={projectId}\n onServerAdded={onServerAdded}\n showProviderBadge={connectedCount === 1}\n />\n )}\n\n <div className=\"p-3 bg-[#0a0a0a] border border-[#222] rounded text-xs text-[#666]\">\n <strong className=\"text-[#888]\">Tip:</strong> Connect apps first, then add MCP configs to make tools available to your agents.\n {\" · \"}\n <a href=\"/settings\" className=\"text-[#f97316] hover:text-[#fb923c]\">Add more providers in Settings</a>\n </div>\n </div>\n </>\n );\n}\n\n// AgentDojo Content Component\ninterface AgentDojoConfig {\n id: string;\n name: string;\n slug: string;\n toolkits: string[];\n toolsCount: number;\n mcpUrl: string;\n createdAt?: string;\n}\n\nfunction AgentDojoContent({\n projectId,\n onServerAdded,\n showProviderBadge,\n}: {\n projectId?: string | null;\n onServerAdded?: () => void;\n showProviderBadge?: boolean;\n}) {\n const { authFetch } = useAuth();\n const [subTab, setSubTab] = useState<\"configs\" | \"toolkits\">(\"configs\");\n const [configs, setConfigs] = useState<AgentDojoConfig[]>([]);\n const [addedServers, setAddedServers] = useState<Set<string>>(new Set());\n const [loadingConfigs, setLoadingConfigs] = useState(false);\n const [addingConfig, setAddingConfig] = useState<string | null>(null);\n const { alert, AlertDialog } = useAlert();\n\n const fetchConfigs = async () => {\n setLoadingConfigs(true);\n try {\n const projectParam = projectId && projectId !== \"unassigned\" ? `?project_id=${projectId}` : \"\";\n const serversUrl = projectId && projectId !== \"unassigned\"\n ? `/api/mcp/servers?project=${encodeURIComponent(projectId)}`\n : \"/api/mcp/servers\";\n console.log(`[AgentDojo:fetchConfigs] projectId=${projectId} serversUrl=${serversUrl}`);\n const [configsRes, serversRes] = await Promise.all([\n authFetch(`/api/integrations/agentdojo/configs${projectParam}`),\n authFetch(serversUrl),\n ]);\n const configsData = await configsRes.json();\n const serversData = await serversRes.json();\n\n console.log(`[AgentDojo:fetchConfigs] configs=${(configsData.configs || []).length} servers=${(serversData.servers || []).length}`);\n setConfigs(configsData.configs || []);\n\n // Track which configs are already added as local servers\n const agentdojoServers = (serversData.servers || []).filter((s: any) => s.source === \"agentdojo\");\n console.log(`[AgentDojo:fetchConfigs] agentdojo servers found: ${agentdojoServers.length}`);\n for (const s of agentdojoServers) {\n const match = s.url?.match(/\\/mcp\\/([^/?]+)/);\n console.log(`[AgentDojo:fetchConfigs] server: id=${s.id} name=${s.name} project_id=${s.project_id} url=${s.url?.substring(0, 80)} extracted=${match ? match[1] : s.name}`);\n }\n const agentdojoServerIds = new Set(\n agentdojoServers.map((s: any) => {\n // Extract config ID from URL or match by name\n const match = s.url?.match(/\\/mcp\\/([^/?]+)/);\n return match ? match[1] : s.name;\n })\n );\n console.log(`[AgentDojo:fetchConfigs] addedServers set:`, [...agentdojoServerIds]);\n setAddedServers(agentdojoServerIds);\n } catch (e) {\n console.error(\"Failed to fetch AgentDojo configs:\", e);\n }\n setLoadingConfigs(false);\n };\n\n const addConfig = async (configId: string) => {\n setAddingConfig(configId);\n try {\n const projectParam = projectId && projectId !== \"unassigned\" ? `?project_id=${projectId}` : \"\";\n console.log(`[AgentDojo:addConfig] configId=${configId} projectParam=${projectParam}`);\n const res = await authFetch(`/api/integrations/agentdojo/configs/${configId}/add${projectParam}`, {\n method: \"POST\",\n });\n const data = await res.json();\n console.log(`[AgentDojo:addConfig] response status=${res.status} ok=${res.ok} message=${data.message} server.id=${data.server?.id} server.project_id=${data.server?.project_id}`);\n if (res.ok) {\n const config = configs.find(c => c.id === configId);\n const addKey = config?.slug || configId;\n console.log(`[AgentDojo:addConfig] marking as added: key=${addKey} config.slug=${config?.slug} config.id=${config?.id} config.name=${config?.name}`);\n setAddedServers(prev => new Set([...prev, addKey]));\n onServerAdded?.();\n } else {\n await alert(data.error || \"Failed to add config\", { title: \"Error\", variant: \"error\" });\n }\n } catch (e) {\n console.error(\"Failed to add config:\", e);\n }\n setAddingConfig(null);\n };\n\n const isConfigAdded = (config: AgentDojoConfig) => {\n return addedServers.has(config.slug) || addedServers.has(config.id) || addedServers.has(config.name);\n };\n\n useEffect(() => {\n fetchConfigs();\n }, [authFetch, projectId]);\n\n return (\n <>\n {AlertDialog}\n <div>\n {showProviderBadge && (\n <div className=\"flex items-center gap-2 text-xs text-[#666] mb-4\">\n <span className=\"w-2 h-2 rounded-full bg-green-500\" />\n AgentDojo\n <span className=\"text-green-400\">Connected</span>\n </div>\n )}\n\n {/* Sub-tabs */}\n <div className=\"flex items-center justify-between mb-4\">\n <div className=\"flex gap-1 bg-[#0a0a0a] border border-[#222] rounded-lg p-1\">\n <button\n onClick={() => setSubTab(\"configs\")}\n className={`px-4 py-2 rounded text-sm font-medium transition ${\n subTab === \"configs\"\n ? \"bg-[#1a1a1a] text-white\"\n : \"text-[#666] hover:text-[#888]\"\n }`}\n >\n MCP Servers\n </button>\n <button\n onClick={() => setSubTab(\"toolkits\")}\n className={`px-4 py-2 rounded text-sm font-medium transition ${\n subTab === \"toolkits\"\n ? \"bg-[#1a1a1a] text-white\"\n : \"text-[#666] hover:text-[#888]\"\n }`}\n >\n Browse Toolkits\n </button>\n </div>\n </div>\n\n {/* MCP Servers Tab */}\n {subTab === \"configs\" && (\n <div>\n <div className=\"flex items-center justify-between mb-3\">\n <p className=\"text-sm text-[#666]\">\n Your MCP servers from AgentDojo\n </p>\n <button\n onClick={fetchConfigs}\n disabled={loadingConfigs}\n className=\"text-xs text-[#666] hover:text-[#888] transition\"\n >\n {loadingConfigs ? \"Loading...\" : \"Refresh\"}\n </button>\n </div>\n\n {loadingConfigs ? (\n <div className=\"text-center py-6 text-[#666]\">Loading servers...</div>\n ) : configs.length === 0 ? (\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg p-4 text-center\">\n <p className=\"text-sm text-[#666]\">No MCP servers found</p>\n <p className=\"text-xs text-[#555] mt-2\">\n <button onClick={() => setSubTab(\"toolkits\")} className=\"text-[#f97316] hover:text-[#fb923c]\">\n Browse toolkits\n </button>\n {\" \"}to create a new MCP server.\n </p>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {configs.map((config) => {\n const added = isConfigAdded(config);\n const isAdding = addingConfig === config.id;\n return (\n <div\n key={config.id}\n className={`bg-[#111] border rounded-lg p-3 transition flex items-center justify-between ${\n added ? \"border-green-500/30\" : \"border-[#1a1a1a] hover:border-[#333]\"\n }`}\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium text-sm\">{config.name}</span>\n <span className=\"text-xs text-[#555]\">{config.toolsCount} tools</span>\n {added && (\n <span className=\"text-xs text-green-400\">Added</span>\n )}\n </div>\n {config.mcpUrl && (\n <code className=\"text-xs text-[#555] mt-1 block truncate\">\n {config.mcpUrl}\n </code>\n )}\n {!config.mcpUrl && config.slug && (\n <code className=\"text-xs text-[#555] mt-1 block truncate\">\n {config.slug}\n </code>\n )}\n </div>\n <div className=\"flex items-center gap-2 ml-3\">\n {added ? (\n <span className=\"text-xs text-[#555] px-2 py-1\">In Servers</span>\n ) : (\n <button\n onClick={() => addConfig(config.id)}\n disabled={isAdding}\n className=\"text-xs bg-[#f97316] hover:bg-[#fb923c] text-black px-3 py-1 rounded font-medium transition disabled:opacity-50\"\n >\n {isAdding ? \"Adding...\" : \"Add\"}\n </button>\n )}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n )}\n\n {/* Browse Toolkits Tab */}\n {subTab === \"toolkits\" && (\n <div>\n <p className=\"text-sm text-[#666] mb-4\">\n Browse available toolkits and create MCP servers\n </p>\n <IntegrationsPanel\n providerId=\"agentdojo\"\n projectId={projectId}\n onConnectionComplete={() => {\n fetchConfigs();\n }}\n />\n </div>\n )}\n </div>\n </>\n );\n}\n\n// Parse command and extract credential placeholders\nfunction parseCommandForCredentials(cmd: string): {\n cleanCommand: string;\n credentials: Array<{ key: string; flag: string }>;\n serverName: string | null;\n} {\n const credentials: Array<{ key: string; flag: string }> = [];\n let cleanCommand = cmd;\n let serverName: string | null = null;\n\n // Try to extract server name from package (e.g., pushover-mcp@latest -> pushover)\n const pkgMatch = cmd.match(/(?:npx\\s+-y\\s+)?(@?[\\w-]+\\/)?(@?[\\w-]+)(?:@[\\w.-]+)?/);\n if (pkgMatch) {\n const pkg = pkgMatch[2] || pkgMatch[1];\n if (pkg) {\n // Extract name: \"pushover-mcp\" -> \"pushover\", \"@org/server-github\" -> \"github\"\n serverName = pkg\n .replace(/^@/, '')\n .replace(/-mcp$/, '')\n .replace(/-server$/, '')\n .replace(/^server-/, '')\n .replace(/^mcp-/, '');\n }\n }\n\n // Pattern: --flag YOUR_VALUE, --flag <value>, --flag {value}, --flag $VALUE\n // Matches: --token YOUR_TOKEN, --user YOUR_USER, --api-key <API_KEY>, etc.\n const argPattern = /--(\\w+[-\\w]*)\\s+(YOUR_\\w+|<[\\w_]+>|\\{[\\w_]+\\}|\\$[\\w_]+|[\\w_]*(?:TOKEN|KEY|SECRET|PASSWORD|USER|ID|APIKEY)[\\w_]*)/gi;\n\n let match;\n while ((match = argPattern.exec(cmd)) !== null) {\n const flag = match[1];\n const placeholder = match[2];\n\n // Convert flag to env var name: api-key -> API_KEY, token -> TOKEN\n const envKey = flag.toUpperCase().replace(/-/g, '_');\n\n // Add prefix based on server name if available\n const fullKey = serverName\n ? `${serverName.toUpperCase().replace(/-/g, '_')}_${envKey}`\n : envKey;\n\n credentials.push({ key: fullKey, flag });\n\n // Replace placeholder with $ENV_VAR reference in command\n cleanCommand = cleanCommand.replace(\n new RegExp(`(--${flag}\\\\s+)${placeholder.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}`, 'i'),\n `--${flag} $${fullKey}`\n );\n }\n\n return { cleanCommand, credentials, serverName };\n}\n\nfunction AddServerModal({\n onClose,\n onAdded,\n projects,\n defaultProjectId,\n}: {\n onClose: () => void;\n onAdded: () => void;\n projects?: Array<{ id: string; name: string; color: string }>;\n defaultProjectId?: string | null;\n}) {\n const { authFetch } = useAuth();\n const [mode, setMode] = useState<\"npm\" | \"pip\" | \"command\" | \"http\">(\"npm\");\n const [name, setName] = useState(\"\");\n const [pkg, setPkg] = useState(\"\");\n const [pipModule, setPipModule] = useState(\"\");\n const [command, setCommand] = useState(\"\");\n const [url, setUrl] = useState(\"\");\n const [username, setUsername] = useState(\"\");\n const [password, setPassword] = useState(\"\");\n const [envVars, setEnvVars] = useState<Array<{ key: string; value: string }>>([]);\n const [projectId, setProjectId] = useState<string | null>(defaultProjectId || null);\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const hasProjects = projects && projects.length > 0;\n\n const addEnvVar = () => {\n setEnvVars([...envVars, { key: \"\", value: \"\" }]);\n };\n\n const updateEnvVar = (index: number, field: \"key\" | \"value\", value: string) => {\n const updated = [...envVars];\n updated[index][field] = value;\n setEnvVars(updated);\n };\n\n const removeEnvVar = (index: number) => {\n setEnvVars(envVars.filter((_, i) => i !== index));\n };\n\n // Handle command input - parse and extract credentials\n const handleCommandChange = (value: string) => {\n setCommand(value);\n\n // Only parse if it looks like a full command with placeholders\n if (value.includes('YOUR_') || value.includes('<') || value.includes('{') ||\n /TOKEN|KEY|SECRET|PASSWORD/i.test(value)) {\n const { cleanCommand, credentials, serverName } = parseCommandForCredentials(value);\n\n // Auto-set name if empty\n if (!name && serverName) {\n setName(serverName);\n }\n\n // Add any new credentials that don't already exist\n if (credentials.length > 0) {\n const existingKeys = new Set(envVars.map(e => e.key));\n const newVars = credentials\n .filter(c => !existingKeys.has(c.key))\n .map(c => ({ key: c.key, value: \"\" }));\n\n if (newVars.length > 0) {\n setEnvVars([...envVars, ...newVars]);\n // Update command to use clean version with env var references\n setCommand(cleanCommand);\n }\n }\n }\n };\n\n // Handle package input - detect if user pasted a full command\n const handlePackageChange = (value: string) => {\n // Check if this looks like a full command (has npx, spaces with args, or credential placeholders)\n const looksLikeCommand =\n value.startsWith('npx ') ||\n value.includes(' --') ||\n value.includes('YOUR_') ||\n value.includes('<') ||\n /\\s+(TOKEN|KEY|SECRET|PASSWORD)/i.test(value);\n\n if (looksLikeCommand) {\n // Switch to command mode and parse\n setMode(\"command\");\n handleCommandChange(value);\n } else {\n // Just a package name\n setPkg(value);\n\n // Try to auto-set name from package\n if (!name && value) {\n const serverName = value\n .replace(/^@[\\w-]+\\//, '') // Remove org prefix\n .replace(/@[\\w.-]+$/, '') // Remove version\n .replace(/^server-/, '')\n .replace(/-server$/, '')\n .replace(/^mcp-/, '')\n .replace(/-mcp$/, '');\n if (serverName && serverName !== value) {\n setName(serverName);\n }\n }\n }\n };\n\n const handleAdd = async () => {\n if (!name) {\n setError(\"Name is required\");\n return;\n }\n\n if (mode === \"npm\" && !pkg) {\n setError(\"npm package is required\");\n return;\n }\n\n if (mode === \"pip\" && !pkg) {\n setError(\"pip package is required\");\n return;\n }\n\n if (mode === \"command\" && !command) {\n setError(\"Command is required\");\n return;\n }\n\n if (mode === \"http\" && !url) {\n setError(\"URL is required\");\n return;\n }\n\n setSaving(true);\n setError(null);\n\n // Build env object from envVars array\n const env: Record<string, string> = {};\n for (const { key, value } of envVars) {\n if (key.trim()) {\n env[key.trim()] = value;\n }\n }\n\n try {\n const body: Record<string, unknown> = { name };\n\n if (mode === \"npm\") {\n body.type = \"npm\";\n body.package = pkg;\n } else if (mode === \"pip\") {\n body.type = \"pip\";\n body.package = pkg;\n if (pipModule) {\n body.pip_module = pipModule;\n }\n } else if (mode === \"http\") {\n body.type = \"http\";\n body.url = url;\n // Build headers with Basic Auth if credentials provided\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (username && password) {\n // Base64 encode username:password for Basic Auth\n const credentials = btoa(`${username}:${password}`);\n headers[\"Authorization\"] = `Basic ${credentials}`;\n }\n body.headers = headers;\n } else {\n // Parse command into parts\n const parts = command.trim().split(/\\s+/);\n body.type = \"custom\";\n body.command = parts[0];\n body.args = parts.slice(1).join(\" \");\n }\n\n if (Object.keys(env).length > 0) {\n body.env = env;\n }\n\n // Add project_id if selected\n if (projectId) {\n body.project_id = projectId;\n }\n\n const res = await authFetch(\"/api/mcp/servers\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const data = await res.json();\n setError(data.error || \"Failed to add server\");\n setSaving(false);\n return;\n }\n\n onAdded();\n } catch (e) {\n setError(\"Failed to add server\");\n setSaving(false);\n }\n };\n\n const quickAdd = (serverName: string, serverPkg: string) => {\n setMode(\"npm\");\n setName(serverName);\n setPkg(serverPkg);\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 backdrop-blur-[2px] z-50 flex items-center justify-center p-4\">\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg w-full max-w-lg max-h-[90vh] overflow-y-auto\">\n <div className=\"p-4 border-b border-[#1a1a1a] flex items-center justify-between sticky top-0 bg-[#111]\">\n <h2 className=\"text-lg font-semibold\">Add MCP Server</h2>\n <button onClick={onClose} className=\"text-[#666] hover:text-[#888]\">\n ✕\n </button>\n </div>\n\n <div className=\"p-4 space-y-4\">\n {/* Quick picks */}\n <div>\n <p className=\"text-sm text-[#666] mb-2\">Quick add:</p>\n <div className=\"flex flex-wrap gap-2\">\n {[\n { name: \"filesystem\", pkg: \"@modelcontextprotocol/server-filesystem\", type: \"npm\" as const },\n { name: \"fetch\", pkg: \"@modelcontextprotocol/server-fetch\", type: \"npm\" as const },\n { name: \"memory\", pkg: \"@modelcontextprotocol/server-memory\", type: \"npm\" as const },\n { name: \"github\", pkg: \"@modelcontextprotocol/server-github\", type: \"npm\" as const },\n { name: \"time\", pkg: \"mcp-server-time\", module: \"mcp_server_time\", type: \"pip\" as const },\n ].map(s => (\n <button\n key={s.name}\n onClick={() => {\n setMode(s.type);\n setName(s.name);\n setPkg(s.pkg);\n if (s.type === \"pip\" && \"module\" in s) {\n setPipModule(s.module || \"\");\n } else {\n setPipModule(\"\");\n }\n }}\n className=\"text-sm bg-[#1a1a1a] hover:bg-[#222] px-3 py-1 rounded transition\"\n >\n {s.name}\n </button>\n ))}\n </div>\n </div>\n\n {/* Mode toggle */}\n <div className=\"flex gap-1 bg-[#0a0a0a] border border-[#222] rounded p-1\">\n <button\n onClick={() => setMode(\"npm\")}\n className={`flex-1 px-2 py-1.5 rounded text-sm transition ${\n mode === \"npm\"\n ? \"bg-[#1a1a1a] text-white\"\n : \"text-[#666] hover:text-[#888]\"\n }`}\n >\n npm\n </button>\n <button\n onClick={() => setMode(\"pip\")}\n className={`flex-1 px-2 py-1.5 rounded text-sm transition ${\n mode === \"pip\"\n ? \"bg-[#1a1a1a] text-white\"\n : \"text-[#666] hover:text-[#888]\"\n }`}\n >\n pip\n </button>\n <button\n onClick={() => setMode(\"command\")}\n className={`flex-1 px-2 py-1.5 rounded text-sm transition ${\n mode === \"command\"\n ? \"bg-[#1a1a1a] text-white\"\n : \"text-[#666] hover:text-[#888]\"\n }`}\n >\n Command\n </button>\n <button\n onClick={() => setMode(\"http\")}\n className={`flex-1 px-2 py-1.5 rounded text-sm transition ${\n mode === \"http\"\n ? \"bg-[#1a1a1a] text-white\"\n : \"text-[#666] hover:text-[#888]\"\n }`}\n >\n HTTP\n </button>\n </div>\n\n {/* Name */}\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Name</label>\n <input\n type=\"text\"\n value={name}\n onChange={e => setName(e.target.value)}\n placeholder=\"e.g., pushover\"\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n\n {/* Project Scope - only show when projects exist */}\n {hasProjects && (\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Scope</label>\n <Select\n value={projectId || \"\"}\n onChange={(value) => setProjectId(value || null)}\n options={[\n { value: \"\", label: \"Global (all projects)\" },\n ...projects!.map(p => ({ value: p.id, label: p.name }))\n ]}\n placeholder=\"Select scope...\"\n />\n <p className=\"text-xs text-[#555] mt-1\">\n Global servers are available to all agents. Project-scoped servers are only available to agents in that project.\n </p>\n </div>\n )}\n\n {/* npm Package */}\n {mode === \"npm\" && (\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">npm Package</label>\n <input\n type=\"text\"\n value={pkg}\n onChange={e => handlePackageChange(e.target.value)}\n placeholder=\"e.g., @modelcontextprotocol/server-filesystem or paste full command\"\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n />\n <p className=\"text-xs text-[#555] mt-1\">\n Package name or paste a full npx command with credentials\n </p>\n </div>\n )}\n\n {/* pip Package (Python) */}\n {mode === \"pip\" && (\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">pip Package</label>\n <input\n type=\"text\"\n value={pkg}\n onChange={e => {\n setPkg(e.target.value);\n // Auto-set module from package name\n if (!pipModule && e.target.value) {\n const basePkg = e.target.value.split(\"[\")[0].replace(/-/g, \".\");\n setPipModule(basePkg);\n }\n }}\n placeholder=\"e.g., late-sdk[mcp]\"\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n />\n <p className=\"text-xs text-[#555] mt-1\">\n Python package with extras, e.g., late-sdk[mcp] or mcp-server-time\n </p>\n </div>\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Module (optional)</label>\n <input\n type=\"text\"\n value={pipModule}\n onChange={e => setPipModule(e.target.value)}\n placeholder=\"e.g., late.mcp\"\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 font-mono text-sm focus:outline-none focus:border-[#f97316]\"\n />\n <p className=\"text-xs text-[#555] mt-1\">\n Python module to run with -m. Auto-detected from package name if not specified.\n </p>\n </div>\n </div>\n )}\n\n {/* Custom Command */}\n {mode === \"command\" && (\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Command</label>\n <input\n type=\"text\"\n value={command}\n onChange={e => handleCommandChange(e.target.value)}\n placeholder=\"e.g., npx -y pushover-mcp@latest start --token YOUR_TOKEN\"\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 font-mono text-sm focus:outline-none focus:border-[#f97316]\"\n />\n <p className=\"text-xs text-[#555] mt-1\">\n Paste the full command - credentials like YOUR_TOKEN will be auto-extracted\n </p>\n </div>\n )}\n\n {/* HTTP Endpoint */}\n {mode === \"http\" && (\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">URL</label>\n <input\n type=\"text\"\n value={url}\n onChange={e => setUrl(e.target.value)}\n placeholder=\"e.g., https://example.com/wp-json/mcp/v1/messages\"\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 font-mono text-sm focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n <div className=\"p-3 bg-[#0a0a0a] border border-[#222] rounded\">\n <p className=\"text-xs text-[#666] mb-3\">\n Optional: Basic Auth credentials (will be encoded and stored securely)\n </p>\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-xs text-[#555] mb-1\">Username</label>\n <input\n type=\"text\"\n value={username}\n onChange={e => setUsername(e.target.value)}\n placeholder=\"username\"\n className=\"w-full bg-[#111] border border-[#333] rounded px-3 py-2 text-sm focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-[#555] mb-1\">Password</label>\n <input\n type=\"password\"\n value={password}\n onChange={e => setPassword(e.target.value)}\n placeholder=\"password or app key\"\n className=\"w-full bg-[#111] border border-[#333] rounded px-3 py-2 text-sm focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n </div>\n </div>\n </div>\n )}\n\n {/* Environment Variables / Credentials */}\n <div>\n <div className=\"flex items-center justify-between mb-2\">\n <label className=\"text-sm text-[#666]\">\n Environment Variables / Credentials\n </label>\n <button\n onClick={addEnvVar}\n className=\"text-xs text-[#f97316] hover:text-[#fb923c] transition\"\n >\n + Add Variable\n </button>\n </div>\n\n {envVars.length === 0 && (\n <p className=\"text-xs text-[#555] bg-[#0a0a0a] border border-[#222] rounded p-3\">\n Add environment variables for API tokens and credentials.\n These are stored encrypted and passed to the server at startup.\n </p>\n )}\n\n {envVars.length > 0 && (\n <div className=\"space-y-2\">\n {envVars.map((env, index) => (\n <div key={index} className=\"flex gap-2\">\n <input\n type=\"text\"\n value={env.key}\n onChange={e => updateEnvVar(index, \"key\", e.target.value)}\n placeholder=\"KEY\"\n className=\"w-1/3 bg-[#0a0a0a] border border-[#333] rounded px-2 py-1.5 text-sm font-mono focus:outline-none focus:border-[#f97316]\"\n />\n <input\n type=\"password\"\n value={env.value}\n onChange={e => updateEnvVar(index, \"value\", e.target.value)}\n placeholder=\"value\"\n className=\"flex-1 bg-[#0a0a0a] border border-[#333] rounded px-2 py-1.5 text-sm font-mono focus:outline-none focus:border-[#f97316]\"\n />\n <button\n onClick={() => removeEnvVar(index)}\n className=\"text-[#666] hover:text-red-400 px-2 transition\"\n >\n ✕\n </button>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {error && <p className=\"text-red-400 text-sm\">{error}</p>}\n </div>\n\n <div className=\"p-4 border-t border-[#1a1a1a] flex justify-end gap-2 sticky bottom-0 bg-[#111]\">\n <button\n onClick={onClose}\n className=\"px-4 py-2 border border-[#333] hover:border-[#666] rounded transition\"\n >\n Cancel\n </button>\n <button\n onClick={handleAdd}\n disabled={saving || !name || (mode === \"npm\" ? !pkg : mode === \"pip\" ? !pkg : mode === \"http\" ? !url : !command)}\n className=\"px-4 py-2 bg-[#f97316] hover:bg-[#fb923c] text-black rounded font-medium transition disabled:opacity-50\"\n >\n {saving ? \"Adding...\" : \"Add Server\"}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\nfunction EditServerModal({\n server,\n projects,\n onClose,\n onSaved,\n}: {\n server: McpServer;\n projects?: Array<{ id: string; name: string; color: string }>;\n onClose: () => void;\n onSaved: () => void;\n}) {\n const { authFetch } = useAuth();\n const [name, setName] = useState(server.name);\n const [pkg, setPkg] = useState(server.package || \"\");\n const [command, setCommand] = useState(server.command || \"\");\n const [args, setArgs] = useState(server.args || \"\");\n const [url, setUrl] = useState(server.url || \"\");\n // Extract username/password from existing Basic Auth header\n const [username, setUsername] = useState(() => {\n const authHeader = server.headers?.[\"Authorization\"] || \"\";\n if (authHeader.startsWith(\"Basic \")) {\n try {\n const decoded = atob(authHeader.slice(6));\n return decoded.split(\":\")[0] || \"\";\n } catch { return \"\"; }\n }\n return \"\";\n });\n const [password, setPassword] = useState(() => {\n const authHeader = server.headers?.[\"Authorization\"] || \"\";\n if (authHeader.startsWith(\"Basic \")) {\n try {\n const decoded = atob(authHeader.slice(6));\n const parts = decoded.split(\":\");\n return parts.slice(1).join(\":\") || \"\";\n } catch { return \"\"; }\n }\n return \"\";\n });\n const [envVars, setEnvVars] = useState<Array<{ key: string; value: string }>>(() => {\n // Convert env object to array format\n return Object.entries(server.env || {}).map(([key, value]) => ({ key, value }));\n });\n const [projectId, setProjectId] = useState<string | null>(server.project_id);\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const hasProjects = projects && projects.length > 0;\n const isRemote = server.type === \"http\";\n\n const addEnvVar = () => {\n setEnvVars([...envVars, { key: \"\", value: \"\" }]);\n };\n\n const updateEnvVar = (index: number, field: \"key\" | \"value\", value: string) => {\n const updated = [...envVars];\n updated[index][field] = value;\n setEnvVars(updated);\n };\n\n const removeEnvVar = (index: number) => {\n setEnvVars(envVars.filter((_, i) => i !== index));\n };\n\n const handleSave = async () => {\n if (!name.trim()) {\n setError(\"Name is required\");\n return;\n }\n\n setSaving(true);\n setError(null);\n\n // Build env object from envVars array\n const env: Record<string, string> = {};\n for (const { key, value } of envVars) {\n if (key.trim()) {\n env[key.trim()] = value;\n }\n }\n\n try {\n const updates: Record<string, unknown> = {\n name: name.trim(),\n env,\n };\n\n // Only include fields that are relevant to the server type\n if (isRemote) {\n // HTTP server - update URL and headers\n if (url.trim()) {\n updates.url = url.trim();\n }\n // Build headers with Basic Auth if credentials provided\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (username && password) {\n const credentials = btoa(`${username}:${password}`);\n headers[\"Authorization\"] = `Basic ${credentials}`;\n }\n updates.headers = headers;\n } else {\n if (server.type === \"npm\" && pkg.trim()) {\n updates.package = pkg.trim();\n }\n if (server.type === \"pip\" && pkg.trim()) {\n updates.package = pkg.trim();\n }\n if (server.type === \"custom\") {\n if (command.trim()) updates.command = command.trim();\n if (args.trim()) updates.args = args.trim();\n }\n }\n\n // Include project_id update\n updates.project_id = projectId;\n\n const res = await authFetch(`/api/mcp/servers/${server.id}`, {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(updates),\n });\n\n if (!res.ok) {\n const data = await res.json();\n setError(data.error || \"Failed to save changes\");\n setSaving(false);\n return;\n }\n\n // If server was running, restart it to apply new env vars\n if (server.status === \"running\" && !isRemote) {\n try {\n // Stop the server\n await authFetch(`/api/mcp/servers/${server.id}/stop`, { method: \"POST\" });\n // Start it again\n await authFetch(`/api/mcp/servers/${server.id}/start`, { method: \"POST\" });\n } catch (e) {\n console.error(\"Failed to restart server:\", e);\n // Don't fail the save, just log the error\n }\n }\n\n onSaved();\n } catch (e) {\n setError(\"Failed to save changes\");\n setSaving(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 backdrop-blur-[2px] z-50 flex items-center justify-center p-4\">\n <div className=\"bg-[#111] border border-[#1a1a1a] rounded-lg w-full max-w-lg max-h-[90vh] overflow-y-auto\">\n <div className=\"p-4 border-b border-[#1a1a1a] flex items-center justify-between sticky top-0 bg-[#111]\">\n <h2 className=\"text-lg font-semibold\">Edit MCP Server</h2>\n <button onClick={onClose} className=\"text-[#666] hover:text-[#888]\">\n ✕\n </button>\n </div>\n\n <div className=\"p-4 space-y-4\">\n {/* Server Type Info */}\n <div className=\"text-sm text-[#666] bg-[#0a0a0a] border border-[#222] rounded p-3\">\n Type: <span className=\"text-[#888]\">{server.type}</span>\n {server.package && <> • Package: <span className=\"text-[#888] font-mono\">{server.package}</span></>}\n {server.command && <> • Command: <span className=\"text-[#888] font-mono\">{server.command}</span></>}\n </div>\n\n {/* Name */}\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Name</label>\n <input\n type=\"text\"\n value={name}\n onChange={e => setName(e.target.value)}\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n\n {/* Project Scope */}\n {hasProjects && (\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Scope</label>\n <Select\n value={projectId || \"\"}\n onChange={(value) => setProjectId(value || null)}\n options={[\n { value: \"\", label: \"Global (all projects)\" },\n ...projects!.map(p => ({ value: p.id, label: p.name }))\n ]}\n placeholder=\"Select scope...\"\n />\n </div>\n )}\n\n {/* Package (for npm type) */}\n {server.type === \"npm\" && (\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">npm Package</label>\n <input\n type=\"text\"\n value={pkg}\n onChange={e => setPkg(e.target.value)}\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 font-mono text-sm focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n )}\n\n {/* Package (for pip type) */}\n {server.type === \"pip\" && (\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">pip Package</label>\n <input\n type=\"text\"\n value={pkg}\n onChange={e => setPkg(e.target.value)}\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 font-mono text-sm focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n )}\n\n {/* URL & Credentials (for http type) */}\n {isRemote && (\n <>\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Server URL</label>\n <input\n type=\"text\"\n value={url}\n onChange={e => setUrl(e.target.value)}\n placeholder=\"https://example.com/mcp\"\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 font-mono text-sm focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Authentication (Basic Auth)</label>\n <div className=\"flex gap-2\">\n <input\n type=\"text\"\n value={username}\n onChange={e => setUsername(e.target.value)}\n placeholder=\"Username\"\n className=\"flex-1 bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 text-sm focus:outline-none focus:border-[#f97316]\"\n />\n <input\n type=\"password\"\n value={password}\n onChange={e => setPassword(e.target.value)}\n placeholder=\"Password / App Password\"\n className=\"flex-1 bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 text-sm focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n <p className=\"text-xs text-[#555] mt-1\">\n Leave empty if no authentication required\n </p>\n </div>\n </>\n )}\n\n {/* Command & Args (for custom type) */}\n {server.type === \"custom\" && (\n <>\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Command</label>\n <input\n type=\"text\"\n value={command}\n onChange={e => setCommand(e.target.value)}\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 font-mono text-sm focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n <div>\n <label className=\"block text-sm text-[#666] mb-1\">Arguments</label>\n <input\n type=\"text\"\n value={args}\n onChange={e => setArgs(e.target.value)}\n placeholder=\"e.g., --token $TOKEN --verbose\"\n className=\"w-full bg-[#0a0a0a] border border-[#333] rounded px-3 py-2 font-mono text-sm focus:outline-none focus:border-[#f97316]\"\n />\n </div>\n </>\n )}\n\n {/* Environment Variables */}\n {!isRemote && (\n <div>\n <div className=\"flex items-center justify-between mb-2\">\n <label className=\"text-sm text-[#666]\">\n Environment Variables / Credentials\n </label>\n <button\n onClick={addEnvVar}\n className=\"text-xs text-[#f97316] hover:text-[#fb923c] transition\"\n >\n + Add Variable\n </button>\n </div>\n\n {envVars.length === 0 && (\n <p className=\"text-xs text-[#555] bg-[#0a0a0a] border border-[#222] rounded p-3\">\n No environment variables configured.\n </p>\n )}\n\n {envVars.length > 0 && (\n <div className=\"space-y-2\">\n {envVars.map((env, index) => (\n <div key={index} className=\"flex gap-2\">\n <input\n type=\"text\"\n value={env.key}\n onChange={e => updateEnvVar(index, \"key\", e.target.value)}\n placeholder=\"KEY\"\n className=\"w-1/3 bg-[#0a0a0a] border border-[#333] rounded px-2 py-1.5 text-sm font-mono focus:outline-none focus:border-[#f97316]\"\n />\n <input\n type=\"password\"\n value={env.value}\n onChange={e => updateEnvVar(index, \"value\", e.target.value)}\n placeholder=\"value\"\n className=\"flex-1 bg-[#0a0a0a] border border-[#333] rounded px-2 py-1.5 text-sm font-mono focus:outline-none focus:border-[#f97316]\"\n />\n <button\n onClick={() => removeEnvVar(index)}\n className=\"text-[#666] hover:text-red-400 px-2 transition\"\n >\n ✕\n </button>\n </div>\n ))}\n </div>\n )}\n\n <p className=\"text-xs text-[#555] mt-2\">\n {server.status === \"running\" ? \"Server will be automatically restarted to apply changes.\" : \"Changes will take effect when the server is started.\"}\n </p>\n </div>\n )}\n\n {error && <p className=\"text-red-400 text-sm\">{error}</p>}\n </div>\n\n <div className=\"p-4 border-t border-[#1a1a1a] flex justify-end gap-2 sticky bottom-0 bg-[#111]\">\n <button\n onClick={onClose}\n className=\"px-4 py-2 border border-[#333] hover:border-[#666] rounded transition\"\n >\n Cancel\n </button>\n <button\n onClick={handleSave}\n disabled={saving || !name.trim()}\n className=\"px-4 py-2 bg-[#f97316] hover:bg-[#fb923c] text-black rounded font-medium transition disabled:opacity-50\"\n >\n {saving ? \"Saving...\" : \"Save Changes\"}\n </button>\n </div>\n </div>\n </div>\n );\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "99C261B73617894664756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer components{@keyframes blink{0%,to{opacity:1}50%{opacity:0}}@keyframes slideUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.animate-slideUp{animation:.2s ease-out slideUp}.apteva-scrollbar-hidden{-ms-overflow-style:none;scrollbar-width:none}.apteva-scrollbar-hidden::-webkit-scrollbar{display:none}.apteva-md{white-space:pre-wrap!important;color:inherit!important;word-wrap:break-word!important;overflow-wrap:break-word!important;font-size:.875rem!important;line-height:1.625!important}.apteva-md-h2{all:unset!important;margin-top:.75rem!important;margin-bottom:.25rem!important;font-size:1.125rem!important;font-weight:600!important;line-height:1.3!important;display:block!important}.apteva-md-h3{all:unset!important;margin-top:.5rem!important;margin-bottom:.125rem!important;font-size:1rem!important;font-weight:600!important;line-height:1.3!important;display:block!important}.apteva-md-ul{all:unset!important;margin-top:.5rem!important;margin-bottom:.5rem!important;padding-left:1.5rem!important;list-style-type:disc!important;list-style-position:outside!important;display:block!important}.apteva-md-ol{all:unset!important;margin-top:.5rem!important;margin-bottom:.5rem!important;padding-left:1.5rem!important;list-style-type:decimal!important;list-style-position:outside!important;display:block!important}.apteva-md-li{all:unset!important;margin-bottom:.25rem!important;padding-left:.25rem!important;display:list-item!important}.apteva-tool-call{all:unset!important;background-color:#8080801a!important;border:1px solid #80808033!important;border-radius:.5rem!important;align-items:center!important;gap:.5rem!important;margin:.5rem 0!important;padding:.5rem .75rem!important;font-size:.875rem!important;display:flex!important}.apteva-tool-call-dot{all:unset!important;border-radius:50%!important;flex-shrink:0!important;width:.5rem!important;height:.5rem!important;display:block!important}.apteva-tool-call-dot-running{background-color:#3b82f6!important;animation:1s infinite blink!important}.apteva-tool-call-dot-completed{background-color:#22c55e!important}.apteva-tool-call-dot-error{background-color:#ef4444!important}.apteva-tool-call-name{all:unset!important;color:inherit!important;font-family:ui-monospace,monospace!important}.apteva-tool-call-status{all:unset!important;color:#808080cc!important;margin-left:auto!important}.apteva-tool-call-status-completed{color:#22c55e!important}.apteva-tool-call-status-error{color:#ef4444!important}.apteva-md-table-wrapper{margin:.75rem 0!important;overflow-x:auto!important}.apteva-md-table{border-collapse:collapse!important;width:100%!important;font-size:.8125rem!important;line-height:1.4!important}.apteva-md-th{text-align:left!important;white-space:nowrap!important;border-bottom:2px solid #8080804d!important;padding:.5rem .75rem!important;font-weight:600!important}.apteva-md-td{border-bottom:1px solid #80808026!important;padding:.5rem .75rem!important}.apteva-md-table tbody tr:hover{background-color:#8080800d!important}.apteva-md-table tbody tr:last-child .apteva-md-td{border-bottom:none!important}.apteva-md-img{border-radius:.5rem!important;max-width:100%!important;height:auto!important;margin:.5rem 0!important;display:block!important}.apteva-md-link{color:#3b82f6!important;text-underline-offset:2px!important;text-decoration:underline!important}.apteva-md-link:hover{color:#2563eb!important}.apteva-md-inline-code{background-color:#80808026!important;border-radius:.25rem!important;padding:.125rem .375rem!important;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace!important;font-size:.8125rem!important}.apteva-typing-indicator{align-items:center!important;gap:2px!important;display:inline-flex!important}.apteva-typing-indicator span{opacity:.4!important;background-color:currentColor!important;border-radius:50%!important;width:6px!important;height:6px!important;animation:1.4s infinite both apteva-typing-blink!important}.apteva-typing-indicator span:nth-child(2){animation-delay:.2s!important}.apteva-typing-indicator span:nth-child(3){animation-delay:.4s!important}@keyframes apteva-typing-blink{0%,80%,to{opacity:.4}40%{opacity:1}}.apteva-chat-header{all:unset!important;box-sizing:border-box!important;justify-content:space-between!important;align-items:center!important;padding:.75rem 1rem!important;display:flex!important}.apteva-chat-title{all:unset!important;color:#111827!important;font-size:1.125rem!important;font-weight:600!important;line-height:1.4!important;display:block!important}@media (prefers-color-scheme:dark){.apteva-chat-title{color:#fff!important}}.dark .apteva-chat-title{color:#fff!important}.apteva-chat-status{all:unset!important;margin-top:.125rem!important;font-size:.75rem!important;line-height:1.4!important;display:block!important}.apteva-chat-status-ready,.apteva-chat-status-thinking{color:#737373!important}.apteva-chat-status-tool{color:#3b82f6!important}@media (prefers-color-scheme:dark){.apteva-chat-status-ready,.apteva-chat-status-thinking{color:#525252!important}.apteva-chat-status-tool{color:#60a5fa!important}}.dark .apteva-chat-status-ready,.dark .apteva-chat-status-thinking{color:#525252!important}.dark .apteva-chat-status-tool{color:#60a5fa!important}.apteva-message-list{box-sizing:border-box!important;flex:1!important;padding:1rem!important;display:block!important;overflow-y:auto!important}.apteva-message-row-user{justify-content:flex-end!important;margin-bottom:.75rem!important;display:flex!important}.apteva-message-row-assistant{justify-content:flex-start!important;margin-bottom:.75rem!important;display:flex!important}.apteva-message-bubble{box-sizing:border-box!important;border-radius:1rem!important;max-width:95%!important;padding:.625rem 1rem!important;font-size:.875rem!important;line-height:1.5!important;display:block!important}.apteva-message-user{color:#fff!important;background-color:#2563eb!important;border-bottom-right-radius:.375rem!important}.apteva-message-assistant{color:#0a0a0a!important;background-color:#fafafa!important;border-bottom-left-radius:.375rem!important}@media (prefers-color-scheme:dark){.apteva-message-assistant{color:#fafafa!important;background-color:#262626!important}}.dark .apteva-message-assistant{color:#fafafa!important;background-color:#262626!important}.apteva-message-content-user,.apteva-message-content-assistant{display:block!important}.apteva-message-text{white-space:pre-wrap!important;color:inherit!important;font-size:.875rem!important;line-height:1.625!important;display:block!important}.apteva-message-widgets{margin-top:.5rem!important;display:block!important}.apteva-message-timestamp{margin-top:.375rem!important;font-size:.75rem!important;display:block!important}.apteva-message-timestamp-user{color:#bfdbfe!important}.apteva-message-timestamp-assistant{color:#737373!important}.apteva-message-segmented{flex-direction:column!important;gap:.5rem!important;width:95%!important;max-width:95%!important;display:flex!important}.apteva-message-segmented .apteva-message-bubble{width:fit-content!important;max-width:100%!important}.apteva-tool-call-standalone,.apteva-widget-standalone{display:block!important}.apteva-widget{color:#171717!important;font-family:system-ui,-apple-system,sans-serif!important;font-size:.875rem!important;line-height:1.5!important}.apteva-widget *{box-sizing:border-box!important}.apteva-widget-skeleton{font-family:system-ui,-apple-system,sans-serif!important}.apteva-widget-skeleton *{box-sizing:border-box!important}.apteva-widget-skeleton [class*=bg-neutral-200]{background-color:#e5e5e5!important}.apteva-widget-skeleton [class*=bg-neutral-100]{background-color:#f5f5f5!important}.apteva-widget-skeleton [class*=bg-neutral-300]{background-color:#d4d4d4!important}.apteva-widget-skeleton [class*=border-neutral]{border-color:#e5e5e5!important}@media (prefers-color-scheme:dark){.apteva-widget-skeleton [class*=bg-neutral-700]{background-color:#404040!important}.apteva-widget-skeleton [class*=bg-neutral-800]{background-color:#262626!important}.apteva-widget-skeleton [class*=bg-neutral-600]{background-color:#525252!important}.apteva-widget-skeleton [class*=border-neutral]{border-color:#262626!important}}.dark .apteva-widget-skeleton [class*=bg-neutral-700]{background-color:#404040!important}.dark .apteva-widget-skeleton [class*=bg-neutral-800]{background-color:#262626!important}.dark .apteva-widget-skeleton [class*=bg-neutral-600]{background-color:#525252!important}.dark .apteva-widget-skeleton [class*=border-neutral]{border-color:#262626!important}.apteva-widget>div{background-color:#fff!important}.apteva-widget h3,.apteva-widget h4{color:#171717!important}.apteva-widget p,.apteva-widget span{color:#525252!important}.apteva-widget>div[class*=border]{border-color:#e5e5e5!important}@media (prefers-color-scheme:dark){.apteva-widget{color:#fafafa!important}.apteva-widget>div{background-color:#171717!important}.apteva-widget h3,.apteva-widget h4{color:#fafafa!important}.apteva-widget p,.apteva-widget span{color:#a3a3a3!important}.apteva-widget>div[class*=border]{border-color:#262626!important}}.dark .apteva-widget{color:#fafafa!important}.dark .apteva-widget>div{background-color:#171717!important}.dark .apteva-widget h3,.dark .apteva-widget h4{color:#fafafa!important}.dark .apteva-widget p,.dark .apteva-widget span{color:#a3a3a3!important}.dark .apteva-widget>div[class*=border]{border-color:#262626!important}@media (prefers-color-scheme:dark){.apteva-message-timestamp-assistant{color:#525252!important}}.dark .apteva-message-timestamp-assistant{color:#525252!important}.apteva-tool-card{box-sizing:border-box!important;border-style:solid!important;border-width:1px!important;border-radius:.75rem!important;align-items:center!important;gap:.5rem!important;padding:.5rem .75rem!important;font-size:.875rem!important;display:flex!important}.apteva-tool-card-running{color:#1d4ed8!important;background-color:#eff6ff!important;border-color:#bfdbfe!important}.apteva-tool-card-completed{color:#15803d!important;background-color:#f0fdf4!important;border-color:#bbf7d0!important}.apteva-tool-card-error{color:#b91c1c!important;background-color:#fef2f2!important;border-color:#fecaca!important}@media (prefers-color-scheme:dark){.apteva-tool-card-running{color:#60a5fa!important;background-color:#3b82f61a!important;border-color:#3b82f64d!important}.apteva-tool-card-completed{color:#4ade80!important;background-color:#22c55e1a!important;border-color:#22c55e4d!important}.apteva-tool-card-error{color:#f87171!important;background-color:#ef44441a!important;border-color:#ef44444d!important}}.dark .apteva-tool-card-running{color:#60a5fa!important;background-color:#3b82f61a!important;border-color:#3b82f64d!important}.dark .apteva-tool-card-completed{color:#4ade80!important;background-color:#22c55e1a!important;border-color:#22c55e4d!important}.dark .apteva-tool-card-error{color:#f87171!important;background-color:#ef44441a!important;border-color:#ef44444d!important}.apteva-tool-icon{flex-shrink:0!important;width:1rem!important;height:1rem!important}.apteva-tool-icon-spin{animation:1s linear infinite apteva-spin!important}.apteva-tool-spinner-track{opacity:.25!important}.apteva-tool-spinner-fill{opacity:.75!important}.apteva-tool-label{font-size:inherit!important}.apteva-tool-label strong{font-weight:600!important}@keyframes apteva-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.apteva-tool-card-preparing{color:#92400e!important;background-color:#fef3c7!important;border-color:#fcd34d!important}@media (prefers-color-scheme:dark){.apteva-tool-card-preparing{color:#fbbf24!important;background-color:#fbbf2426!important;border-color:#fbbf2466!important}}.dark .apteva-tool-card-preparing{color:#fbbf24!important;background-color:#fbbf2426!important;border-color:#fbbf2466!important}@keyframes apteva-pulse-glow{0%,to{box-shadow:0 0 #fbbf2400}50%{box-shadow:0 0 8px 2px #fbbf2480}}.apteva-tool-receiving{animation:.4s ease-in-out apteva-pulse-glow!important}.apteva-tool-status-text{opacity:.7!important;font-weight:400!important}.apteva-tool-char-count{opacity:.6!important;font-variant-numeric:tabular-nums!important;font-size:.85em!important;font-weight:400!important}.apteva-tool-dots{margin-left:1px!important;display:inline-flex!important}.apteva-tool-dots span{opacity:.3!important;animation:1.4s ease-in-out infinite apteva-dot-pulse!important}.apteva-tool-dots span:first-child{animation-delay:0s!important}.apteva-tool-dots span:nth-child(2){animation-delay:.2s!important}.apteva-tool-dots span:nth-child(3){animation-delay:.4s!important}@keyframes apteva-dot-pulse{0%,60%,to{opacity:.3}30%{opacity:1}}.apteva-tool-stream-separator{opacity:.5!important}.apteva-tool-stream-output{opacity:.85!important;white-space:nowrap!important;text-overflow:ellipsis!important;vertical-align:bottom!important;max-width:300px!important;font-weight:400!important;display:inline-block!important;overflow:hidden!important}.apteva-composer{background-color:#fff!important;border:2px solid #d4d4d4!important;border-radius:1rem!important;gap:.5rem .75rem!important;padding:.5rem .75rem!important;transition:all .3s!important;display:grid!important;position:relative!important}.apteva-composer textarea{color:#171717!important;background-color:#0000!important}.apteva-composer textarea::placeholder{color:#a3a3a3!important}button.apteva-composer-menu-btn{background:0 0!important;border:none!important}.apteva-composer-menu{background-color:#262626!important}.apteva-composer-menu button{color:#fff!important;background-color:#0000!important}.apteva-composer-menu button:hover{background-color:#404040!important}.apteva-composer-send-btn{color:#404040!important;background-color:#fff!important;border:1px solid #d4d4d4!important}.apteva-composer-send-btn svg{stroke:currentColor!important}.apteva-composer-stop-btn{all:unset!important;box-sizing:border-box!important;cursor:pointer!important;color:#dc2626!important;background-color:#fef2f2!important;border:1px solid #f87171!important;border-radius:.5rem!important;flex-shrink:0!important;justify-content:center!important;align-items:center!important;width:2rem!important;height:2rem!important;margin:0!important;padding:0!important;transition:background-color .15s!important;display:flex!important}.apteva-composer-stop-btn:hover{background-color:#fee2e2!important}.apteva-composer-stop-btn svg{fill:currentColor!important;width:14px!important;height:14px!important}@media (prefers-color-scheme:dark){.apteva-composer{background-color:#171717!important;border-color:#404040!important}.apteva-composer textarea{color:#fafafa!important}.apteva-composer textarea::placeholder{color:#525252!important}button.apteva-composer-menu-btn{background:0 0!important}.apteva-composer-send-btn{color:#d4d4d4!important;background-color:#262626!important;border-color:#404040!important}.apteva-composer-stop-btn{color:#f87171!important;background-color:#7f1d1d4d!important;border-color:#f87171!important}.apteva-composer-stop-btn:hover{background-color:#7f1d1d80!important}}.dark .apteva-composer{background-color:#171717!important;border-color:#404040!important}.dark .apteva-composer textarea{color:#fafafa!important}.dark .apteva-composer textarea::placeholder{color:#525252!important}.dark button.apteva-composer-menu-btn{background:0 0!important}.dark .apteva-composer-send-btn{color:#d4d4d4!important;background-color:#262626!important;border-color:#404040!important}.dark .apteva-composer-stop-btn{color:#f87171!important;background-color:#7f1d1d4d!important;border-color:#f87171!important}.dark .apteva-composer-stop-btn:hover{background-color:#7f1d1d80!important}.apteva-file-preview{flex-wrap:wrap!important;gap:.5rem!important;margin-bottom:.5rem!important;display:flex!important}.apteva-file-item{all:unset!important;box-sizing:border-box!important;background-color:#f5f5f5!important;border:1px solid #e5e5e5!important;border-radius:.5rem!important;align-items:center!important;gap:.5rem!important;padding:.5rem .75rem!important;font-family:system-ui,-apple-system,sans-serif!important;display:flex!important;position:relative!important}.apteva-file-item:hover .apteva-file-remove{opacity:1!important}.apteva-file-thumb{object-fit:cover!important;border-radius:.25rem!important;flex-shrink:0!important;width:2rem!important;height:2rem!important}.apteva-file-icon{color:#737373!important;background-color:#e5e5e5!important;border-radius:.25rem!important;flex-shrink:0!important;justify-content:center!important;align-items:center!important;width:2rem!important;height:2rem!important;display:flex!important}.apteva-file-icon svg{width:1rem!important;height:1rem!important}.apteva-file-info{flex-direction:column!important;min-width:0!important;display:flex!important}.apteva-file-name{color:#404040!important;text-overflow:ellipsis!important;white-space:nowrap!important;max-width:120px!important;font-size:.75rem!important;font-weight:500!important;overflow:hidden!important}.apteva-file-size{color:#737373!important;font-size:.75rem!important}.apteva-file-remove{all:unset!important;box-sizing:border-box!important;color:#fff!important;opacity:0!important;cursor:pointer!important;background-color:#737373!important;border-radius:50%!important;justify-content:center!important;align-items:center!important;width:1.25rem!important;height:1.25rem!important;transition:opacity .15s,background-color .15s!important;display:flex!important;position:absolute!important;top:-.375rem!important;right:-.375rem!important}.apteva-file-remove:hover{background-color:#ef4444!important}.apteva-file-remove svg{width:.75rem!important;height:.75rem!important}.apteva-file-error{all:unset!important;box-sizing:border-box!important;z-index:20!important;background-color:#fef2f2!important;border:1px solid #fecaca!important;border-radius:.5rem!important;margin-bottom:.5rem!important;padding:.75rem!important;position:absolute!important;bottom:100%!important;left:1rem!important;right:1rem!important}.apteva-file-error-content{color:#b91c1c!important;align-items:center!important;gap:.5rem!important;font-size:.875rem!important;display:flex!important}.apteva-file-error-content svg{flex-shrink:0!important;width:1rem!important;height:1rem!important}@media (prefers-color-scheme:dark){.apteva-file-item{background-color:#262626!important;border-color:#404040!important}.apteva-file-icon{color:#a3a3a3!important;background-color:#404040!important}.apteva-file-name{color:#d4d4d4!important}.apteva-file-size{color:#a3a3a3!important}.apteva-file-error{background-color:#7f1d1d4d!important;border-color:#f87171!important}.apteva-file-error-content{color:#fca5a5!important}}.dark .apteva-file-item{background-color:#262626!important;border-color:#404040!important}.dark .apteva-file-icon{color:#a3a3a3!important;background-color:#404040!important}.dark .apteva-file-name{color:#d4d4d4!important}.dark .apteva-file-size{color:#a3a3a3!important}.dark .apteva-file-error{background-color:#7f1d1d4d!important;border-color:#f87171!important}.dark .apteva-file-error-content{color:#fca5a5!important}.apteva-file-badges{flex-shrink:0!important;align-items:center!important;gap:.25rem!important;display:flex!important}.apteva-file-badge{all:unset!important;box-sizing:border-box!important;background-color:#f5f5f5!important;border-radius:.25rem!important;justify-content:center!important;align-items:center!important;width:1.5rem!important;height:1.5rem!important;display:flex!important;position:relative!important;overflow:hidden!important}.apteva-file-badge:hover .apteva-file-badge-remove{opacity:1!important}.apteva-file-badge-img{object-fit:cover!important;width:1.5rem!important;height:1.5rem!important}.apteva-file-badge-icon{color:#737373!important;font-size:.75rem!important}.apteva-file-badge-icon svg{width:1rem!important;height:1rem!important}.apteva-file-badge-remove{all:unset!important;box-sizing:border-box!important;opacity:0!important;cursor:pointer!important;background-color:#00000080!important;justify-content:center!important;align-items:center!important;transition:opacity .15s!important;display:flex!important;position:absolute!important;inset:0!important}.apteva-file-badge-remove svg{color:#fff!important;width:.75rem!important;height:.75rem!important}@media (prefers-color-scheme:dark){.apteva-file-badge{background-color:#262626!important}.apteva-file-badge-icon{color:#a3a3a3!important}}.dark .apteva-file-badge{background-color:#262626!important}.dark .apteva-file-badge-icon{color:#a3a3a3!important}.apteva-composer-textarea{-ms-overflow-style:none!important;scrollbar-width:none!important}.apteva-composer-textarea::-webkit-scrollbar{display:none!important}.apteva-chat{background-color:#fff!important}.apteva-chat-header{background-color:#fff!important;border-color:#e5e5e5!important}.apteva-message-list{background-color:#f5f5f5!important}@media (prefers-color-scheme:dark){.apteva-chat{background-color:#0a0a0a!important}.apteva-chat-header{background-color:#171717!important;border-color:#262626!important}.apteva-message-list{background-color:#0a0a0a!important}}.dark .apteva-chat{background-color:#0a0a0a!important}.dark .apteva-chat-header{background-color:#171717!important;border-color:#262626!important}.dark .apteva-message-list{background-color:#0a0a0a!important}@keyframes apteva-slide-in{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes apteva-highlight-fade{0%{background-color:#3b82f626}to{background-color:#0000}}.apteva-list-item-new,.apteva-table-row-new{animation:.3s ease-out apteva-slide-in,.5s ease-out .3s apteva-highlight-fade!important}.apteva-table-row-new td{background-color:#3b82f61a!important}.apteva-list-streaming,.apteva-table-streaming{border-top:1px dashed #8080804d!important}@media (prefers-color-scheme:dark){.apteva-list-item-new,.apteva-table-row-new{animation:.3s ease-out apteva-slide-in,.5s ease-out .3s apteva-highlight-fade-dark!important}.apteva-table-row-new td{background-color:#3b82f626!important}}.dark .apteva-list-item-new,.dark .apteva-table-row-new{animation:.3s ease-out apteva-slide-in,.5s ease-out .3s apteva-highlight-fade-dark!important}.dark .apteva-table-row-new td{background-color:#3b82f626!important}@keyframes apteva-highlight-fade-dark{0%{background-color:#3b82f633}to{background-color:#0000}}.apteva-chat-minimal{background-color:#0000!important}.apteva-chat-minimal .apteva-chat-header{background-color:#0000!important;border:none!important}.apteva-chat-minimal .apteva-message-list{background-color:#0000!important}.apteva-chat-minimal .apteva-composer{background-color:#0000!important;border:1px solid #80808033!important}.apteva-chat-minimal .apteva-message-assistant{background-color:#80808014!important}.apteva-chat-minimal .apteva-message-user{color:inherit!important;background-color:#3b82f626!important}.apteva-chat-terminal{background-color:#0a0a0a!important;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,monospace!important}.apteva-chat-terminal *{font-family:inherit!important}.apteva-chat-terminal .apteva-chat-header{background-color:#0a0a0a!important;border-color:#1a1a1a!important}.apteva-chat-terminal .apteva-chat-title{color:#e0e0e0!important;font-size:.875rem!important}.apteva-chat-terminal .apteva-chat-status{color:#666!important}.apteva-chat-terminal .apteva-chat-status-tool{color:#f97316!important}.apteva-chat-terminal .apteva-message-list{background-color:#0a0a0a!important}.apteva-chat-terminal .apteva-message-user{color:#e0e0e0!important;background-color:#1a1a1a!important;border-radius:4px!important}.apteva-chat-terminal .apteva-message-assistant{color:#e0e0e0!important;background-color:#111!important;border:1px solid #1a1a1a!important;border-radius:4px!important}.apteva-chat-terminal .apteva-message-timestamp{color:#444!important}.apteva-chat-terminal .apteva-message-timestamp-user{color:#666!important}.apteva-chat-terminal .apteva-composer{background-color:#111!important;border:1px solid #1a1a1a!important;border-radius:4px!important}.apteva-chat-terminal .apteva-composer textarea{color:#e0e0e0!important}.apteva-chat-terminal .apteva-composer textarea::placeholder{color:#666!important}.apteva-chat-terminal .apteva-composer-send-btn{color:#888!important;background-color:#1a1a1a!important;border-color:#333!important}.apteva-chat-terminal .apteva-composer-send-btn:hover{color:#f97316!important;border-color:#f97316!important}.apteva-chat-terminal .apteva-composer-stop-btn{color:#f97316!important;background-color:#f9731626!important;border-color:#f97316!important}.apteva-chat-terminal .apteva-composer-menu-btn{color:#666!important}.apteva-chat-terminal .apteva-composer-menu-btn:hover{color:#f97316!important;background-color:#1a1a1a!important}.apteva-chat-terminal .apteva-tool-card-running{color:#f97316!important;background-color:#f973161a!important;border-color:#f973164d!important}.apteva-chat-terminal .apteva-tool-card-completed{color:#4ade80!important;background-color:#22c55e1a!important;border-color:#22c55e4d!important}.apteva-chat-terminal .apteva-tool-card-preparing{color:#f97316!important;background-color:#f973161a!important;border-color:#f973164d!important}.apteva-chat-terminal .apteva-md-link{color:#f97316!important}.apteva-chat-terminal .apteva-md-link:hover{color:#fb923c!important}.apteva-chat-terminal .apteva-md-inline-code{color:#3b82f6!important;background-color:#1a1a1a!important}}
|
package/dist/icon.png
ADDED
|
Binary file
|
package/dist/index.html
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Apteva</title>
|
|
7
|
+
<link rel="icon" type="image/png" href="/icon.png">
|
|
8
|
+
<link rel="apple-touch-icon" href="/icon.png">
|
|
9
|
+
<link rel="stylesheet" href="/styles.css">
|
|
10
|
+
<link rel="stylesheet" href="/apteva-kit.css">
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="root"></div>
|
|
14
|
+
<script type="module" src="/App.af2wg84v.js"></script>
|
|
15
|
+
</body>
|
|
16
|
+
</html>
|