@truefoundry/trueforge-ui 0.1.0-rc.1 → 0.1.0

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/dist/{ConnectorSettings-ADACLWQI.js → ConnectorSettings-H37ZFC6Z.js} +35 -12
  3. package/dist/ConnectorSettings-H37ZFC6Z.js.map +1 -0
  4. package/dist/{DockLayout-BH5XX2AQ.js → DockLayout-KEMFRWIR.js} +8 -8
  5. package/dist/{DrawerLayout-O2XZQCG4.js → DrawerLayout-ZVWCKEIS.js} +8 -8
  6. package/dist/{ModelSettings-LKFJVUYQ.js → ModelSettings-QJMYHCMD.js} +5 -5
  7. package/dist/OpenUiFenceBlock-XFBUGPKQ.js +9 -0
  8. package/dist/{SandboxSettings-H5MDAE47.js → SandboxSettings-BUBMLW7Q.js} +159 -65
  9. package/dist/SandboxSettings-BUBMLW7Q.js.map +1 -0
  10. package/dist/{SettingsBuilder-3JOLC56Z.js → SettingsBuilder-26XSGIHK.js} +7 -7
  11. package/dist/{SidebarLayout-G6BGD7EY.js → SidebarLayout-F3XFXW7B.js} +8 -8
  12. package/dist/{SkillSettings-4VB42CVG.js → SkillSettings-IRMGDFRG.js} +5 -5
  13. package/dist/{WidgetLayout-ABSXZUSQ.js → WidgetLayout-SZMABKIR.js} +8 -8
  14. package/dist/{chunk-EFGSH3MO.js → chunk-7EEOWDLE.js} +7 -7
  15. package/dist/chunk-DTF7ZMUJ.js +567 -0
  16. package/dist/chunk-DTF7ZMUJ.js.map +1 -0
  17. package/dist/{chunk-3PTFNAQK.js → chunk-H7DR64W3.js} +46 -31
  18. package/dist/chunk-H7DR64W3.js.map +1 -0
  19. package/dist/{chunk-FDBJNXH2.js → chunk-HT5HKQXE.js} +2 -2
  20. package/dist/{chunk-VJTCFZNM.js → chunk-LRQHHZDX.js} +4 -4
  21. package/dist/{chunk-Z27F4LBZ.js → chunk-QGNLP2EE.js} +163 -71
  22. package/dist/chunk-QGNLP2EE.js.map +1 -0
  23. package/dist/{chunk-U5GBGEGN.js → chunk-XAZ5HJXV.js} +83 -9
  24. package/dist/chunk-XAZ5HJXV.js.map +1 -0
  25. package/dist/index.d.ts +6 -2
  26. package/dist/index.js +112 -17
  27. package/dist/index.js.map +1 -1
  28. package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +42 -28
  29. package/dist/plugins/trueforge-agent-server-adapter/index.js +27 -16
  30. package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
  31. package/dist/styles.css +1 -1
  32. package/package.json +4 -4
  33. package/dist/ConnectorSettings-ADACLWQI.js.map +0 -1
  34. package/dist/OpenUiFenceBlock-A2CWCPOP.js +0 -9
  35. package/dist/SandboxSettings-H5MDAE47.js.map +0 -1
  36. package/dist/chunk-3PTFNAQK.js.map +0 -1
  37. package/dist/chunk-U5GBGEGN.js.map +0 -1
  38. package/dist/chunk-WMRZSULD.js +0 -567
  39. package/dist/chunk-WMRZSULD.js.map +0 -1
  40. package/dist/chunk-Z27F4LBZ.js.map +0 -1
  41. /package/dist/{DockLayout-BH5XX2AQ.js.map → DockLayout-KEMFRWIR.js.map} +0 -0
  42. /package/dist/{DrawerLayout-O2XZQCG4.js.map → DrawerLayout-ZVWCKEIS.js.map} +0 -0
  43. /package/dist/{ModelSettings-LKFJVUYQ.js.map → ModelSettings-QJMYHCMD.js.map} +0 -0
  44. /package/dist/{OpenUiFenceBlock-A2CWCPOP.js.map → OpenUiFenceBlock-XFBUGPKQ.js.map} +0 -0
  45. /package/dist/{SettingsBuilder-3JOLC56Z.js.map → SettingsBuilder-26XSGIHK.js.map} +0 -0
  46. /package/dist/{SidebarLayout-G6BGD7EY.js.map → SidebarLayout-F3XFXW7B.js.map} +0 -0
  47. /package/dist/{SkillSettings-4VB42CVG.js.map → SkillSettings-IRMGDFRG.js.map} +0 -0
  48. /package/dist/{WidgetLayout-ABSXZUSQ.js.map → WidgetLayout-SZMABKIR.js.map} +0 -0
  49. /package/dist/{chunk-EFGSH3MO.js.map → chunk-7EEOWDLE.js.map} +0 -0
  50. /package/dist/{chunk-FDBJNXH2.js.map → chunk-HT5HKQXE.js.map} +0 -0
  51. /package/dist/{chunk-VJTCFZNM.js.map → chunk-LRQHHZDX.js.map} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truefoundry/trueforge-ui",
3
- "version": "0.1.0-rc.1",
3
+ "version": "0.1.0",
4
4
  "description": "TrueForge Agent Chat UI (atoms + containers) built on assistant-ui, with owned theming, presets, and swappable slots.",
5
5
  "author": "TrueFoundry",
6
6
  "license": "MIT",
@@ -77,7 +77,7 @@
77
77
  "@openuidev/react-headless": "^0.9.4",
78
78
  "@openuidev/react-lang": "^0.2.9",
79
79
  "@openuidev/react-ui": "^0.13.2",
80
- "@truefoundry/assistant-ui-runtime": "0.1.16",
80
+ "@truefoundry/assistant-ui-runtime": "0.1.18",
81
81
  "clsx": "^2.1.1",
82
82
  "lucide-react": "^0.562.0",
83
83
  "monaco-editor": "^0.56.0",
@@ -86,9 +86,9 @@
86
86
  "react-syntax-highlighter": "^16.1.1",
87
87
  "remark-gfm": "^4.0.1",
88
88
  "tailwind-merge": "^3.6.0",
89
- "truefoundry-gateway-sdk": "^0.4.0-rc.6",
89
+ "truefoundry-gateway-sdk": "^0.4.0",
90
90
  "zod": "^4.4.3",
91
- "@truefoundry/trueforge-sdk": "0.1.0-rc.1"
91
+ "@truefoundry/trueforge-sdk": "0.1.0"
92
92
  },
93
93
  "devDependencies": {
94
94
  "@eslint/js": "^9.39.0",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/containers/SettingsBuilder/ConnectorSettings.tsx","../src/containers/SettingsBuilder/AddMcpServerForm.tsx","../src/containers/SettingsBuilder/authTypeLabels.ts","../src/containers/SettingsBuilder/ConnectorDetails.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useState, type FormEvent } from 'react';\n\nimport { cn } from '@/atoms/lib/cn.js';\nimport { auiInputClass } from '@/atoms/lib/inputClasses.js';\nimport { Button } from '@/atoms/primitives/Button.js';\nimport { CatalogLogo } from '@/atoms/primitives/CatalogLogo.js';\nimport { CenteredModal } from '@/atoms/primitives/CenteredModal.js';\nimport SearchInput from '@/atoms/primitives/SearchInput.js';\nimport { Icon } from '@/icons/Icon.js';\nimport { useCatalogServer } from '@/server/ServerContext.js';\nimport type { ConnectorAuth, ConnectorBase, ConnectorCatalogEntry } from '@/server/types.js';\nimport { getErrorMessage } from '@/utils/getErrorMessage.js';\nimport { useToasterOptional } from '../ToasterContainer.js';\nimport AddMcpServerForm, { type AddMcpServerDraft } from './AddMcpServerForm.js';\nimport { AUTH_TYPE_LABELS } from './authTypeLabels.js';\nimport ConnectorDetails from './ConnectorDetails.js';\n\ntype ConnectorListItem =\n { connector: ConnectorBase; isConfigured: true } | { connector: ConnectorCatalogEntry; isConfigured: false };\n\ntype ConnectorsState = {\n ordered: ConnectorListItem[];\n authStatusById: Map<string, boolean>;\n};\n\nconst ConnectorSettings = () => {\n const { connectorCatalog } = useCatalogServer();\n const toaster = useToasterOptional();\n\n const [query, setQuery] = useState('');\n const [connectors, setConnectors] = useState<ConnectorsState>({\n ordered: [],\n authStatusById: new Map(),\n });\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [formError, setFormError] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n\n const [catalog, setCatalog] = useState<ConnectorCatalogEntry[]>([]);\n const [addMcpServerFormOpen, setAddMcpServerFormOpen] = useState(false);\n const [connectorAwaitingKey, setConnectorAwaitingKey] = useState<ConnectorCatalogEntry | null>(null);\n const [selectedConnector, setSelectedConnector] = useState<ConnectorBase | null>(null);\n const [apiKey, setApiKey] = useState('');\n\n const connectorIconMap = useMemo(() => {\n return (catalog ?? []).reduce(\n (acc, entry) => {\n acc[entry.name] = entry.logo ?? '';\n return acc;\n },\n {} as Record<string, string>,\n );\n }, [catalog]);\n\n const refresh = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const [listed, available] = await Promise.all([\n connectorCatalog.listConnectors(),\n connectorCatalog.getConnectorCatalog(),\n ]);\n setCatalog(available);\n const configured = listed ?? [];\n const seenIds = new Set(configured.map(connector => connector.id));\n const ordered: ConnectorListItem[] = [\n ...configured.map<ConnectorListItem>(connector => ({ connector, isConfigured: true })),\n ...available\n .filter(connector => !seenIds.has(connector.id))\n .map<ConnectorListItem>(connector => ({ connector, isConfigured: false })),\n ];\n setConnectors({\n ordered,\n authStatusById: new Map(\n ordered.map(item => [item.connector.id, item.isConfigured ? item.connector.authenticated : false]),\n ),\n });\n setSelectedConnector(current => (current ? (listed.find(item => item.id === current.id) ?? null) : null));\n } catch (err) {\n setError(getErrorMessage(err, 'Failed to load connectors'));\n } finally {\n setLoading(false);\n }\n }, [connectorCatalog]);\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n const normalizedQuery = query.trim().toLowerCase();\n\n const matchingConnectors = useMemo(() => {\n if (!normalizedQuery) return connectors.ordered;\n return connectors.ordered.filter(({ connector }) => {\n return (\n connector.name.toLowerCase().includes(normalizedQuery) ||\n (connector.description?.toLowerCase().includes(normalizedQuery) ?? false) ||\n connector.url.toLowerCase().includes(normalizedQuery)\n );\n });\n }, [connectors.ordered, normalizedQuery]);\n\n const matchingConnected = useMemo(() => {\n const result: ConnectorBase[] = [];\n for (const item of matchingConnectors) {\n if (item.isConfigured) {\n const authenticated = connectors.authStatusById.get(item.connector.id) ?? item.connector.authenticated;\n result.push(\n authenticated === item.connector.authenticated ? item.connector : { ...item.connector, authenticated },\n );\n }\n }\n return result;\n }, [connectors.authStatusById, matchingConnectors]);\n\n const availableConnectors = useMemo(() => {\n const result: ConnectorCatalogEntry[] = [];\n for (const item of matchingConnectors) {\n if (!item.isConfigured) result.push(item.connector);\n }\n return result;\n }, [matchingConnectors]);\n\n const runMutation = async (fn: () => Promise<void>, setMutationError = setError) => {\n setBusy(true);\n setError(null);\n try {\n await fn();\n await refresh();\n } catch (err) {\n setMutationError(getErrorMessage(err, 'Request failed'));\n throw err;\n } finally {\n setBusy(false);\n }\n };\n\n const closeApiKeyModal = () => {\n setConnectorAwaitingKey(null);\n setApiKey('');\n setFormError(null);\n };\n\n const createFromCatalog = async (entry: ConnectorCatalogEntry, authOverride?: ConnectorAuth) => {\n const auth: ConnectorAuth =\n authOverride ??\n (entry.auth.type === 'header'\n ? {\n type: 'header',\n ...(entry.auth.headerName ? { headerName: entry.auth.headerName } : {}),\n }\n : entry.auth.type === 'dcr'\n ? { type: 'dcr' }\n : { type: 'none' });\n await connectorCatalog.createConnector({\n name: entry.name,\n url: entry.url,\n auth,\n });\n };\n\n const handleConnect = (entry: ConnectorCatalogEntry) => {\n if (entry.auth.type === 'header') {\n setApiKey('');\n setFormError(null);\n setConnectorAwaitingKey(entry);\n return;\n }\n\n void runMutation(async () => {\n await createFromCatalog(entry);\n }).catch(() => {});\n };\n\n const handleApiKeySubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!connectorAwaitingKey || !apiKey.trim()) return;\n\n const entry = connectorAwaitingKey;\n setFormError(null);\n void runMutation(async () => {\n const auth: ConnectorAuth = {\n type: 'header',\n apiKey: apiKey.trim(),\n ...(entry.auth.type === 'header' && entry.auth.headerName ? { headerName: entry.auth.headerName } : {}),\n };\n const existing = connectors.ordered.find(({ connector }) => connector.id === entry.id);\n const existingConnector = existing?.isConfigured ? existing.connector : undefined;\n if (existingConnector) {\n await connectorCatalog.updateConnector({\n id: existingConnector.id,\n name: existingConnector.name,\n url: existingConnector.url,\n auth,\n });\n } else {\n await createFromCatalog(entry, auth);\n }\n closeApiKeyModal();\n setTimeout(() => {\n toaster?.showSuccess({ title: `${entry.name} ${existingConnector ? 'updated' : 'connected'}` });\n }, 100);\n }, setFormError).catch(() => {});\n };\n\n const handleAddMcpServer = async (draft: AddMcpServerDraft) => {\n setFormError(null);\n await runMutation(async () => {\n await connectorCatalog.createConnector({\n name: draft.name,\n url: draft.url,\n auth: draft.auth,\n });\n }, setFormError);\n setTimeout(() => {\n toaster?.showSuccess({ title: `${draft.name} added` });\n }, 0);\n };\n\n const handleDisconnect = (connector: ConnectorBase) => {\n void runMutation(async () => {\n await connectorCatalog.disconnectConnector({ id: connector.id });\n setSelectedConnector(null);\n }).catch(() => {});\n };\n\n const handleConnectorRefreshed = (refreshedConnector: ConnectorBase) => {\n setSelectedConnector(current => (current?.id === refreshedConnector.id ? refreshedConnector : current));\n setConnectors(current => {\n const authStatusById = new Map(current.authStatusById);\n authStatusById.set(refreshedConnector.id, refreshedConnector.authenticated);\n\n return {\n ordered: current.ordered.map(item =>\n item.isConfigured && item.connector.id === refreshedConnector.id\n ? { connector: refreshedConnector, isConfigured: true }\n : item,\n ),\n authStatusById,\n };\n });\n };\n\n const renderConnector = (connector: ConnectorBase, isConnected: boolean) => {\n const logoSrc = connectorIconMap[connector.name];\n const content = (\n <>\n <span\n className=\"flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border bg-secondary-bg\"\n aria-hidden\n >\n {logoSrc ? (\n <CatalogLogo src={logoSrc} alt={connector.name} className=\"size-4.5\" />\n ) : (\n <Icon name=\"mcp-server\" className=\"size-4.5 text-text-primary\" />\n )}\n </span>\n\n <div className=\"min-w-0 flex-1\">\n <h5 className=\"truncate text-sm font-medium text-text-primary\">{connector.name}</h5>\n <p className=\"mt-0.5 line-clamp-2 text-sm text-text-secondary sm:truncate\">{connector.description}</p>\n </div>\n </>\n );\n\n const rowClassName = 'flex min-h-16 w-full items-center gap-3 border-b border-border p-3 text-left last:border-b-0';\n\n if (isConnected) {\n return (\n <article\n key={connector.id}\n className={`${rowClassName} cursor-pointer transition-colors hover:bg-ghost-button-hover/60`}\n onClick={() => {\n setSelectedConnector(connector);\n }}\n >\n <div className=\"flex min-w-0 flex-1 items-center gap-3\">{content}</div>\n\n <div className=\"flex items-center gap-2\">\n <div className=\"flex items-center gap-2\">\n <span\n className={cn(\n 'flex items-center gap-1.5 rounded-full border border-border bg-secondary-bg/40 px-2 py-0.5 text-xs font-medium',\n connector.authenticated ? 'text-success-bg' : 'text-text-primary',\n )}\n >\n <span\n className={cn(\n 'h-1.5 w-1.5 rounded-full',\n connector.authenticated ? 'bg-success-bg' : 'bg-primary-button-bg',\n )}\n ></span>\n {connector.authenticated ? 'Connected' : 'Added'}\n </span>\n </div>\n {connector.auth.type === 'header' ? (\n <Button\n variant=\"secondary\"\n size=\"sm\"\n type=\"button\"\n disabled={busy}\n onClick={event => {\n event.stopPropagation();\n setApiKey('');\n setConnectorAwaitingKey(connector);\n }}\n >\n <Icon name=\"wrench\" className=\"size-3\" />\n Replace Key\n </Button>\n ) : null}\n <Icon name=\"chevron-right\" className=\"size-4\" />\n </div>\n </article>\n );\n }\n\n return (\n <article key={connector.id} className={rowClassName}>\n {content}\n </article>\n );\n };\n\n const renderCatalogEntry = (entry: ConnectorCatalogEntry) => {\n const logoSrc = connectorIconMap[entry.name];\n return (\n <article\n key={entry.id}\n className=\"flex min-h-16 w-full items-center gap-3 border-b border-border p-3 text-left last:border-b-0\"\n >\n <span\n className=\"flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border bg-secondary-bg\"\n aria-hidden\n >\n {logoSrc ? (\n <CatalogLogo src={logoSrc} alt={entry.name} className=\"size-4.5\" />\n ) : (\n <Icon name=\"mcp-server\" className=\"size-4.5 text-text-primary\" />\n )}\n </span>\n\n <div className=\"min-w-0 flex-1\">\n <h5 className=\"truncate text-sm font-medium text-text-primary\">{entry.name}</h5>\n <p className=\"mt-0.5 line-clamp-2 text-sm text-text-secondary sm:truncate\">\n {entry.description ?? entry.url}\n </p>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-2\">\n <span className=\"hidden text-xs text-text-secondary sm:inline\">\n {AUTH_TYPE_LABELS[entry.auth.type] ?? AUTH_TYPE_LABELS.none}\n </span>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n type=\"button\"\n disabled={busy}\n onClick={() => {\n handleConnect(entry);\n }}\n >\n {entry.auth.type === 'dcr' ? 'Add' : 'Connect'}\n </Button>\n </div>\n </article>\n );\n };\n\n const isReplacingKey = useMemo(() => {\n return (\n connectorAwaitingKey !== null &&\n connectors.ordered.some(\n (item: ConnectorListItem) => item.isConfigured && item.connector.id === connectorAwaitingKey.id,\n )\n );\n }, [connectorAwaitingKey, connectors.ordered]);\n\n if (selectedConnector) {\n return (\n <ConnectorDetails\n connector={selectedConnector}\n busy={busy}\n onBack={() => {\n setSelectedConnector(null);\n }}\n onConnectorRefreshed={handleConnectorRefreshed}\n onDisconnect={() => {\n handleDisconnect(selectedConnector);\n }}\n />\n );\n }\n\n const hasMatches = matchingConnected.length > 0 || availableConnectors.length > 0;\n\n return (\n <>\n <h3 className=\"text-xl font-semibold tracking-tight text-text-primary\">Connectors</h3>\n <p className=\"mt-1 text-sm text-text-secondary\">Connect tools your agents can use.</p>\n\n {error ? (\n <p className=\"mt-3 rounded-md border border-failure-bg/30 bg-failure-bg/10 px-3 py-2 text-sm text-failure-bg\">\n {error}\n </p>\n ) : null}\n\n <div className=\"mt-4 flex-1 overflow-y-hidden\">\n <div className=\"flex h-full flex-col gap-3\">\n <div className=\"flex gap-2\">\n <div className=\"flex-1\">\n <SearchInput query={query} setQuery={setQuery} placeholder=\"Search connectors\" />\n </div>\n <Button\n variant=\"secondary\"\n type=\"button\"\n onClick={() => {\n setFormError(null);\n setAddMcpServerFormOpen(true);\n }}\n >\n <Icon name=\"plus\" size=\"1rem\" className=\"mr-1\" />\n Add MCP Server\n </Button>\n </div>\n\n <div className=\"flex flex-1 flex-col gap-5 overflow-y-auto pb-1\">\n {loading ? <p className=\"py-8 text-center text-sm text-text-secondary\">Loading…</p> : null}\n\n {!loading && matchingConnected.length > 0 ? (\n <section aria-labelledby=\"connected-connectors-heading\">\n <h4\n id=\"connected-connectors-heading\"\n className=\"mb-2 text-[0.8125rem] font-semibold uppercase text-text-secondary\"\n >\n Configured · {matchingConnected.length}\n </h4>\n <div className=\"overflow-hidden rounded-xl border border-border bg-card-bg\">\n {matchingConnected.map(connector => renderConnector(connector, true))}\n </div>\n </section>\n ) : null}\n\n {!loading && availableConnectors.length > 0 ? (\n <section aria-labelledby=\"available-connectors-heading\">\n <h4\n id=\"available-connectors-heading\"\n className=\"mb-2 text-[0.8125rem] font-semibold uppercase text-text-secondary\"\n >\n Available · {availableConnectors.length}\n </h4>\n <div className=\"overflow-hidden rounded-xl border border-border bg-card-bg\">\n {availableConnectors.map(entry => renderCatalogEntry(entry))}\n </div>\n </section>\n ) : null}\n\n {!loading && !hasMatches ? (\n <div className=\"flex flex-1 items-center justify-center rounded-xl border border-dashed border-border p-8 text-center text-sm text-text-secondary\">\n {query.trim() ? `No connectors match “${query.trim()}”.` : 'No connectors yet.'}\n </div>\n ) : null}\n </div>\n\n <CenteredModal\n open={connectorAwaitingKey !== null}\n onOpenChange={open => {\n if (!open) closeApiKeyModal();\n }}\n title={`${isReplacingKey ? 'Replace key for' : 'Connect'} ${connectorAwaitingKey?.name ?? 'connector'}`}\n description={connectorAwaitingKey?.url}\n contentSized\n className=\"md:max-w-xl\"\n >\n <form onSubmit={handleApiKeySubmit}>\n <div className=\"space-y-5 px-5 py-5\">\n <div className=\"flex items-center gap-3\">\n <span\n className=\"flex size-12 shrink-0 items-center justify-center overflow-hidden rounded-xl border border-border bg-secondary-bg\"\n aria-hidden\n >\n <Icon name=\"mcp-server\" className=\"size-6 text-text-primary\" />\n </span>\n <div className=\"min-w-0\">\n <p className=\"font-medium text-text-primary\">{connectorAwaitingKey?.name}</p>\n <p className=\"truncate text-sm text-text-secondary\">{connectorAwaitingKey?.description}</p>\n </div>\n </div>\n\n <div>\n <label\n htmlFor=\"connector-api-key\"\n className=\"mb-2 block text-xs font-semibold uppercase tracking-wide text-text-secondary\"\n >\n API key / token\n </label>\n <input\n id=\"connector-api-key\"\n type=\"password\"\n value={apiKey}\n onChange={event => {\n setApiKey(event.target.value);\n }}\n placeholder={`Paste the token from ${connectorAwaitingKey?.name ?? 'the provider'}`}\n autoFocus\n required\n className={auiInputClass('h-11')}\n />\n </div>\n {formError ? <p className=\"text-failure-bg text-sm\">{formError}</p> : null}\n </div>\n\n <footer className=\"flex justify-end gap-2 border-t border-border px-5 py-4\">\n <Button variant=\"ghost\" type=\"button\" onClick={closeApiKeyModal} disabled={busy}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={!apiKey.trim() || busy}>\n {isReplacingKey ? 'Replace Key' : 'Connect'}\n </Button>\n </footer>\n </form>\n </CenteredModal>\n\n <AddMcpServerForm\n open={addMcpServerFormOpen}\n onOpenChange={open => {\n setAddMcpServerFormOpen(open);\n if (!open) setFormError(null);\n }}\n onAdd={handleAddMcpServer}\n busy={busy}\n error={formError}\n />\n </div>\n </div>\n </>\n );\n};\n\nexport default ConnectorSettings;\n","'use client';\n\nimport { useState, type FormEvent } from 'react';\n\nimport { auiInputClass } from '../../atoms/lib/inputClasses.js';\nimport { Button } from '../../atoms/primitives/Button.js';\nimport { CenteredModal } from '../../atoms/primitives/CenteredModal.js';\nimport { Icon } from '../../icons/Icon.js';\nimport type { ConnectorAuth, ConnectorAuthType } from '../../server/types.js';\n\nexport type McpAuthType = ConnectorAuthType;\n\nexport type AddMcpServerDraft = {\n name: string;\n url: string;\n auth: ConnectorAuth;\n};\n\ntype AddMcpServerFormProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onAdd: (draft: AddMcpServerDraft) => void | Promise<void>;\n busy?: boolean;\n error?: string | null;\n};\n\nconst AUTH_OPTIONS: Array<{ value: McpAuthType; label: string }> = [\n { value: 'dcr', label: 'OAuth' },\n { value: 'none', label: 'None' },\n { value: 'header', label: 'API Key' },\n];\n\nconst inputClassName = auiInputClass('h-11 shadow-sm');\n\nconst RequiredMark = () => (\n <span className=\"ml-0.5 text-failure-bg\" aria-hidden>\n *\n </span>\n);\n\nconst AddMcpServerForm = ({ open, onOpenChange, onAdd, busy = false, error }: AddMcpServerFormProps) => {\n const [name, setName] = useState('');\n const [url, setUrl] = useState('');\n const [authType, setAuthType] = useState<McpAuthType>('dcr');\n const [apiKey, setApiKey] = useState('');\n const [headerName, setHeaderName] = useState('');\n\n const resetForm = () => {\n setName('');\n setUrl('');\n setAuthType('dcr');\n setApiKey('');\n setHeaderName('');\n };\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (!nextOpen) resetForm();\n onOpenChange(nextOpen);\n };\n\n const isValid = !!name.trim() && !!url.trim() && (authType !== 'header' || !!apiKey.trim());\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!isValid || busy) return;\n\n const auth: ConnectorAuth =\n authType === 'header'\n ? {\n type: 'header',\n apiKey: apiKey.trim(),\n ...(headerName.trim() ? { headerName: headerName.trim() } : {}),\n }\n : { type: authType };\n\n try {\n await onAdd({\n name: name.trim(),\n url: url.trim(),\n auth,\n });\n resetForm();\n onOpenChange(false);\n } catch {\n // Parent surfaces error; keep form open.\n }\n };\n\n return (\n <CenteredModal\n open={open}\n onOpenChange={handleOpenChange}\n title=\"Add MCP server\"\n description=\"Point at a remote MCP endpoint. It then behaves like any other connector.\"\n contentSized\n headerIcon={\n <span\n className=\"flex size-11 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary\"\n aria-hidden\n >\n <Icon name=\"mcp-server\" className=\"size-6\" />\n </span>\n }\n >\n <form className=\"flex flex-col overflow-y-auto p-5 md:p-6\" onSubmit={e => void handleSubmit(e)}>\n <div className=\"space-y-4\">\n <div>\n <label htmlFor=\"mcp-server-name\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Name\n <RequiredMark />\n </label>\n <input\n id=\"mcp-server-name\"\n type=\"text\"\n required\n value={name}\n onChange={event => {\n setName(event.target.value);\n }}\n placeholder=\"analytics-postgres-mcp\"\n autoFocus\n className={inputClassName}\n />\n </div>\n\n <div>\n <label htmlFor=\"mcp-server-url\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n URL\n <RequiredMark />\n </label>\n <input\n id=\"mcp-server-url\"\n type=\"url\"\n required\n value={url}\n onChange={event => {\n setUrl(event.target.value);\n }}\n placeholder=\"https://mcp.example.com/mcp\"\n className={inputClassName}\n />\n </div>\n\n <fieldset>\n <legend className=\"mb-1.5 text-sm font-medium text-text-primary\">\n Auth type\n <RequiredMark />\n </legend>\n <div className=\"flex w-full flex-row rounded-md border border-border bg-secondary-bg/40 p-1\">\n {AUTH_OPTIONS.map(option => (\n <label\n key={option.value}\n className={`flex h-8 flex-1 cursor-pointer items-center justify-center rounded-sm text-sm font-medium transition-colors ${\n authType === option.value\n ? 'bg-dropdown-selected-item-bg text-dropdown-selected-item-text shadow-sm'\n : 'text-text-secondary hover:text-text-primary'\n }`}\n >\n <input\n type=\"radio\"\n name=\"mcp-auth-type\"\n value={option.value}\n checked={authType === option.value}\n onChange={() => {\n setAuthType(option.value);\n }}\n className=\"sr-only\"\n />\n {option.label}\n </label>\n ))}\n </div>\n </fieldset>\n\n {authType === 'dcr' ? (\n <div className=\"flex gap-1.5 bg-secondary-bg/40 p-2 rounded-md\">\n <Icon name=\"info\" className=\"size-3.5 mt-1 text-text-secondary\" />\n <div className=\"text-xs text-text-secondary leading-5.5\">\n Sign-in only — the server must support dynamic client registration. Manual OAuth (client ID / secret)\n isn't supported yet.\n </div>\n </div>\n ) : null}\n\n {authType === 'header' ? (\n <>\n <div>\n <label htmlFor=\"mcp-server-api-key\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n API key\n <RequiredMark />\n </label>\n <input\n id=\"mcp-server-api-key\"\n type=\"password\"\n required\n value={apiKey}\n onChange={event => {\n setApiKey(event.target.value);\n }}\n placeholder=\"Paste the server token\"\n className={inputClassName}\n />\n </div>\n\n <div>\n <label htmlFor=\"mcp-server-header-name\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Header name <span className=\"font-normal text-text-secondary\">(optional)</span>\n </label>\n <input\n id=\"mcp-server-header-name\"\n type=\"text\"\n value={headerName}\n onChange={event => {\n setHeaderName(event.target.value);\n }}\n placeholder=\"Authorization\"\n className={inputClassName}\n />\n </div>\n </>\n ) : null}\n </div>\n\n <div className=\"mt-6 space-y-3\">\n {error ? <p className=\"text-failure-bg text-sm\">{error}</p> : null}\n <Button type=\"submit\" size=\"lg\" disabled={!isValid || busy} className=\"w-full shrink-0\">\n Add\n </Button>\n </div>\n </form>\n </CenteredModal>\n );\n};\n\nexport default AddMcpServerForm;\n","/** Display labels for connector auth types (catalog + details). */\nexport const AUTH_TYPE_LABELS: Record<string, string> = {\n dcr: 'OAuth2',\n header: 'API Key',\n none: 'No Auth',\n};\n","'use client';\n\nimport { useEffect, useLayoutEffect, useRef, useState } from 'react';\n\nimport { cn } from '../../atoms/lib/cn.js';\nimport { Button } from '../../atoms/primitives/Button.js';\nimport { useMCPAuth } from '../../hooks/useMcpAuth.js';\nimport { Icon } from '../../icons/Icon.js';\nimport { useCatalogServer } from '../../server/ServerContext.js';\nimport type { ConnectorBase, ToolBase } from '../../server/types.js';\nimport { getErrorMessage } from '../../utils/getErrorMessage.js';\nimport { AUTH_TYPE_LABELS } from './authTypeLabels.js';\n\ntype ConnectorDetailsProps = {\n connector: ConnectorBase;\n onBack: () => void;\n onConnectorRefreshed: (connector: ConnectorBase) => void;\n onDisconnect: () => void;\n busy?: boolean;\n};\n\n/** One-line clamp with animated expand; toggle only when content actually overflows. */\nfunction ExpandableDescription({ text }: { text: string }) {\n const contentRef = useRef<HTMLParagraphElement>(null);\n const [expanded, setExpanded] = useState(false);\n const [canExpand, setCanExpand] = useState(false);\n const [maxHeight, setMaxHeight] = useState(16);\n\n useLayoutEffect(() => {\n setExpanded(false);\n setMaxHeight(16);\n }, [text]);\n\n useLayoutEffect(() => {\n const el = contentRef.current;\n if (!el) return;\n\n if (!expanded) {\n setMaxHeight(16);\n setCanExpand(el.scrollWidth > el.clientWidth + 1);\n return;\n }\n\n // Keep collapsed height for one frame (wrap enabled), then grow so max-height can transition.\n setMaxHeight(16);\n const frame = requestAnimationFrame(() => {\n setMaxHeight(el.scrollHeight);\n });\n return () => cancelAnimationFrame(frame);\n }, [text, expanded]);\n\n if (!text) return null;\n\n return (\n <div className=\"relative min-w-0\">\n <p\n ref={contentRef}\n style={{ maxHeight }}\n className={cn(\n 'mt-0.5 overflow-hidden font-mono text-xs leading-4 text-text-secondary transition-[max-height] duration-300 ease-in-out',\n !expanded && 'whitespace-nowrap',\n !expanded && canExpand && 'pr-[5.75rem]',\n )}\n >\n {text}\n {expanded && canExpand ? (\n <>\n {' '}\n <button\n type=\"button\"\n className=\"cursor-pointer font-mono text-xs font-medium text-text-primary/80 hover:text-text-primary focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus-ring\"\n aria-expanded\n onClick={() => setExpanded(false)}\n >\n Show less\n </button>\n </>\n ) : null}\n </p>\n {!expanded && canExpand ? (\n <button\n type=\"button\"\n className=\"absolute top-0.5 right-0 cursor-pointer bg-card-bg pl-1.5 font-mono text-xs font-medium leading-4 text-text-primary/80 hover:text-text-primary focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus-ring\"\n aria-expanded={false}\n onClick={() => setExpanded(true)}\n >\n <span aria-hidden className=\"text-text-secondary\">\n …\n </span>\n <span className=\"ml-1\">Read more</span>\n </button>\n ) : null}\n </div>\n );\n}\n\nconst ConnectorDetails = ({\n connector,\n onBack,\n onConnectorRefreshed,\n onDisconnect,\n busy = false,\n}: ConnectorDetailsProps) => {\n const { connectorCatalog } = useCatalogServer();\n const { handleAuthorize, isOAuthLoading } = useMCPAuth();\n const [tools, setTools] = useState<ToolBase[]>([]);\n const [toolsLoading, setToolsLoading] = useState(true);\n const [toolsError, setToolsError] = useState<string | null>(null);\n const [refreshingAfterAuth, setRefreshingAfterAuth] = useState(false);\n\n useEffect(() => {\n let cancelled = false;\n setTools([]);\n setToolsError(null);\n setToolsLoading(true);\n\n void connectorCatalog\n .getToolsByConnectorId({ id: connector.id })\n .then(result => {\n if (!cancelled) setTools(result);\n })\n .catch((err: unknown) => {\n if (!cancelled) {\n setToolsError(getErrorMessage(err, 'Failed to load connector tools'));\n }\n })\n .finally(() => {\n if (!cancelled) setToolsLoading(false);\n });\n\n return () => {\n cancelled = true;\n };\n }, [connector.authenticated, connector.id, connectorCatalog]);\n\n const refreshAfterAuthentication = async () => {\n setRefreshingAfterAuth(true);\n setToolsError(null);\n\n try {\n const refreshedConnector = await connectorCatalog.getConnector({ id: connector.id });\n onConnectorRefreshed(refreshedConnector);\n } catch (err: unknown) {\n setToolsError(getErrorMessage(err, 'Failed to refresh connector details'));\n } finally {\n setRefreshingAfterAuth(false);\n }\n };\n\n const connecting = isOAuthLoading || refreshingAfterAuth;\n\n return (\n <div className=\"flex h-full flex-col overflow-hidden\">\n <button\n type=\"button\"\n onClick={onBack}\n className=\"mb-3 inline-flex w-fit items-center gap-1 rounded-md py-1 pr-2 text-sm text-text-secondary hover:text-text-primary focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus-ring\"\n >\n <Icon name=\"chevron-left\" className=\"size-3.5\" />\n Connectors\n </button>\n\n <div className=\"flex flex-1 flex-col overflow-y-auto pb-1\">\n <header className=\"flex items-start gap-3\">\n <span\n className=\"flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border bg-secondary-bg\"\n aria-hidden\n >\n <Icon name=\"mcp-server\" className=\"size-5 text-text-primary\" />\n </span>\n\n <div className=\"min-w-0 flex-1\">\n <h4 className=\"text-lg font-semibold text-text-primary\">{connector.name}</h4>\n <div className=\"mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-sm\">\n <span\n className={cn(\n 'flex items-center gap-1.5 text-xs font-medium',\n connector.authenticated ? 'text-success-bg' : 'text-text-primary',\n )}\n >\n <span\n className={cn(\n 'h-1.5 w-1.5 rounded-full',\n connector.authenticated ? 'bg-success-bg' : 'bg-primary-button-bg',\n )}\n ></span>\n {connector.authenticated ? 'Connected' : 'Not authenticated'}\n </span>\n <span className=\"text-text-secondary\">· {connector.description}</span>\n </div>\n <span className=\"mt-2 inline-flex items-center rounded-full border border-border bg-secondary-bg/40 px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {AUTH_TYPE_LABELS[connector.auth.type] ?? AUTH_TYPE_LABELS.none}\n </span>\n </div>\n\n {connector.auth.type === 'dcr' && !connector.authenticated ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n type=\"button\"\n disabled={busy || connecting}\n onClick={() => {\n void handleAuthorize(connector.id, isSuccess => {\n if (isSuccess) void refreshAfterAuthentication();\n });\n }}\n >\n {connecting ? 'Connecting…' : 'Connect'}\n </Button>\n ) : connector.auth.type === 'dcr' && !connector.requiresAuth ? (\n <Button variant=\"outline\" size=\"sm\" type=\"button\" disabled={busy} onClick={onDisconnect}>\n Disconnect\n </Button>\n ) : null}\n </header>\n\n <section className=\"mt-6\" aria-labelledby=\"connector-tools-heading\">\n {toolsLoading ? (\n <div className=\"rounded-xl border border-dashed border-border p-6 text-center text-sm text-text-secondary\">\n Loading tools…\n </div>\n ) : toolsError ? (\n <div className=\"rounded-xl border border-failure-bg/30 bg-failure-bg/10 p-6 text-center text-sm text-failure-bg\">\n {toolsError}\n {connector.auth.type === 'dcr' && !connector.authenticated && (\n <div className=\"font-bold mt-1\">Click Connect and authenticate successfully to view tools.</div>\n )}\n </div>\n ) : tools.length > 0 ? (\n <>\n <h5 id=\"connector-tools-heading\" className=\"mb-2 text-[0.8125rem] font-semibold text-text-primary\">\n Tools <span className=\"font-normal text-text-secondary\">· {tools.length}</span>\n </h5>\n <div className=\"overflow-hidden rounded-xl border border-border bg-card-bg\">\n {tools.map(tool => (\n <article\n key={tool.id}\n className=\"flex min-h-12 items-start gap-3 border-b border-border px-3 py-2 last:border-b-0\"\n >\n <div className=\"min-w-0 flex-1\">\n <h6 className=\"text-sm font-medium text-text-primary\">{tool.name}</h6>\n <ExpandableDescription text={tool.description} />\n </div>\n </article>\n ))}\n </div>\n </>\n ) : (\n <div className=\"rounded-xl border border-dashed border-border p-6 text-center text-sm text-text-secondary\">\n No tools reported for this connector.\n </div>\n )}\n </section>\n </div>\n </div>\n );\n};\n\nexport default ConnectorDetails;\n"],"mappings":"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","names":["useEffect","useState","useState","Fragment","jsx","jsxs","useState","Fragment","jsx","jsxs","useState","useEffect"]}
@@ -1,9 +0,0 @@
1
- "use client";
2
- import {
3
- OpenUiFenceBlock
4
- } from "./chunk-FDBJNXH2.js";
5
- import "./chunk-WMRZSULD.js";
6
- export {
7
- OpenUiFenceBlock
8
- };
9
- //# sourceMappingURL=OpenUiFenceBlock-A2CWCPOP.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/containers/SettingsBuilder/SandboxSettings.tsx","../src/containers/SettingsBuilder/ConfigureSandboxForm.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport { Button } from '../../atoms/primitives/Button.js';\nimport { Icon } from '../../icons/Icon.js';\nimport { useCatalogServer } from '../../server/ServerContext.js';\nimport type { SandboxProviderBase, SandboxProviderCatalogEntry, SandboxProviderConfig } from '../../server/types.js';\nimport { getErrorMessage } from '../../utils/getErrorMessage.js';\nimport { useToasterOptional } from '../ToasterContainer.js';\nimport ConfigureSandboxForm, { type SandboxConfigDraft } from './ConfigureSandboxForm.js';\n\nconst configFrom = ({\n snapshotName,\n execTimeoutMs,\n autoStopIntervalInMinutes,\n autoArchiveIntervalInMinutes,\n autoDeleteIntervalInMinutes,\n}: SandboxProviderConfig): SandboxProviderConfig => ({\n snapshotName,\n execTimeoutMs,\n autoStopIntervalInMinutes,\n autoArchiveIntervalInMinutes,\n autoDeleteIntervalInMinutes,\n});\n\nconst SandboxSettings = () => {\n const { sandboxCatalog } = useCatalogServer();\n const toaster = useToasterOptional();\n\n const [providers, setProviders] = useState<SandboxProviderBase[]>([]);\n const [catalog, setCatalog] = useState<SandboxProviderCatalogEntry[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [formError, setFormError] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n\n const [createEntry, setCreateEntry] = useState<SandboxProviderCatalogEntry | null>(null);\n const [updateProvider, setUpdateProvider] = useState<SandboxProviderBase | null>(null);\n\n const refresh = useCallback(\n async ({ quiet = false }: { quiet?: boolean } = {}) => {\n if (!sandboxCatalog) return;\n if (!quiet) setLoading(true);\n setError(null);\n try {\n const [listed, available] = await Promise.all([\n sandboxCatalog.listSandboxProviders(),\n sandboxCatalog.getSandboxProviderCatalog(),\n ]);\n setProviders(listed);\n setCatalog(available);\n } catch (err) {\n setError(getErrorMessage(err, 'Failed to load sandbox providers'));\n } finally {\n if (!quiet) setLoading(false);\n }\n },\n [sandboxCatalog],\n );\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n // Tenant/UI-wide: only one sandbox provider may be configured at a time.\n const hasConfiguredProvider = providers.length > 0;\n const availableEntries = useMemo(() => {\n if (hasConfiguredProvider) return [];\n const connectedCatalogIds = new Set(providers.map(provider => provider.catalogId));\n return catalog.filter(entry => !connectedCatalogIds.has(entry.id));\n }, [catalog, providers, hasConfiguredProvider]);\n\n const formInitialConfig = useMemo(\n () => (updateProvider ? configFrom(updateProvider) : createEntry ? configFrom(createEntry) : null),\n [updateProvider, createEntry],\n );\n\n if (!sandboxCatalog) {\n return <p className=\"text-sm text-text-secondary\">Sandbox provider catalog is not available.</p>;\n }\n\n const runMutation = async (fn: () => Promise<void>, setMutationError = setError) => {\n setBusy(true);\n setError(null);\n try {\n await fn();\n await refresh({ quiet: true });\n } catch (err) {\n setMutationError(getErrorMessage(err, 'Request failed'));\n throw err;\n } finally {\n setBusy(false);\n }\n };\n\n const handleCreate = async (draft: SandboxConfigDraft) => {\n if (!createEntry) return;\n setFormError(null);\n await runMutation(async () => {\n await sandboxCatalog.createSandboxProvider({\n catalogId: createEntry.id,\n name: createEntry.name,\n type: createEntry.type,\n ...configFrom(draft),\n apiKey: draft.apiKey,\n });\n }, setFormError);\n setCreateEntry(null);\n setTimeout(() => {\n toaster?.showSuccess({ title: `${createEntry.name} configured` });\n }, 0);\n };\n\n const handleUpdate = async (draft: SandboxConfigDraft) => {\n if (!updateProvider) return;\n setFormError(null);\n await runMutation(async () => {\n await sandboxCatalog.updateSandboxProvider({\n id: updateProvider.id,\n ...configFrom(draft),\n ...(draft.apiKey ? { apiKey: draft.apiKey } : {}),\n });\n }, setFormError);\n setUpdateProvider(null);\n setTimeout(() => {\n toaster?.showSuccess({ title: `${updateProvider.name} updated` });\n }, 0);\n };\n\n const handleRemove = (provider: SandboxProviderBase) => {\n const deleteSandboxProvider = sandboxCatalog.deleteSandboxProvider;\n if (!deleteSandboxProvider) return;\n void runMutation(async () => {\n await deleteSandboxProvider({ id: provider.id });\n }).catch(() => {});\n };\n\n const formOpen = createEntry != null || updateProvider != null;\n const isUpdate = updateProvider != null;\n const formTitle = updateProvider\n ? `Update ${updateProvider.name}`\n : createEntry\n ? `Configure ${createEntry.name}`\n : 'Configure sandbox provider';\n\n return (\n <>\n <h3 className=\"text-xl font-semibold tracking-tight text-text-primary\">Sandbox providers</h3>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Choose a provider that runs sandboxes for code, files and shell commands. Only one can be active at a time.\n </p>\n\n {error ? (\n <p className=\"mt-3 rounded-md border border-failure-bg/30 bg-failure-bg/10 px-3 py-2 text-sm text-failure-bg\">\n {error}\n </p>\n ) : null}\n\n <div className=\"mt-4 flex-1 overflow-y-auto\">\n {loading ? (\n <p className=\"text-sm text-text-secondary\">Loading sandbox providers…</p>\n ) : (\n <div className=\"space-y-6\">\n {providers.length > 0 ? (\n <section>\n <h4 className=\"mb-2 text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n Configured · {providers.length}\n </h4>\n <div className=\"overflow-hidden rounded-xl border border-border bg-card-bg\">\n {providers.map(provider => (\n <article\n key={provider.id}\n className=\"flex flex-col gap-3 border-b border-border p-3 last:border-b-0 sm:flex-row sm:items-center\"\n >\n <div className=\"flex min-w-0 flex-1 items-center gap-3\">\n <span\n className=\"flex size-9 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary\"\n aria-hidden\n >\n <Icon name=\"cube\" className=\"size-4.5\" />\n </span>\n <div className=\"min-w-0\">\n <h5 className=\"truncate text-sm font-medium text-text-primary\">{provider.name}</h5>\n </div>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2.5 sm:justify-end\">\n {provider.isConnected ? (\n <span className=\"flex items-center gap-1.5 rounded-full border border-border bg-secondary-bg/40 px-2 py-0.5 text-xs font-medium text-success-bg\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-success-bg\"></span>\n Connected\n </span>\n ) : null}\n <Button\n variant=\"secondary\"\n size=\"sm\"\n type=\"button\"\n disabled={busy}\n onClick={() => {\n setFormError(null);\n setCreateEntry(null);\n setUpdateProvider(provider);\n }}\n >\n Update\n </Button>\n {sandboxCatalog.deleteSandboxProvider ? (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-text-secondary\"\n type=\"button\"\n disabled={busy}\n onClick={() => {\n handleRemove(provider);\n }}\n >\n Remove\n </Button>\n ) : null}\n </div>\n </article>\n ))}\n </div>\n </section>\n ) : null}\n\n {!hasConfiguredProvider ? (\n <section>\n <h4 className=\"mb-2 text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n Available · {availableEntries.length}\n </h4>\n {availableEntries.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {catalog.length > 0\n ? 'All catalog providers are configured.'\n : 'No sandbox providers in the catalog.'}\n </p>\n ) : (\n <div className=\"overflow-hidden rounded-xl border border-border bg-card-bg\">\n {availableEntries.map(entry => (\n <article\n key={entry.id}\n className=\"flex flex-col gap-3 border-b border-border p-3 last:border-b-0 sm:flex-row sm:items-center\"\n >\n <div className=\"flex min-w-0 flex-1 items-center gap-3\">\n <span\n className=\"flex size-9 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary\"\n aria-hidden\n >\n <Icon name=\"cube\" className=\"size-4.5\" />\n </span>\n <div className=\"min-w-0\">\n <h5 className=\"truncate text-sm font-medium text-text-primary\">{entry.name}</h5>\n </div>\n </div>\n\n <Button\n variant=\"secondary\"\n type=\"button\"\n disabled={busy}\n onClick={() => {\n setFormError(null);\n setUpdateProvider(null);\n setCreateEntry(entry);\n }}\n >\n Configure\n </Button>\n </article>\n ))}\n </div>\n )}\n </section>\n ) : null}\n </div>\n )}\n </div>\n\n <ConfigureSandboxForm\n open={formOpen}\n onOpenChange={open => {\n if (!open) {\n setFormError(null);\n setCreateEntry(null);\n setUpdateProvider(null);\n }\n }}\n onSave={isUpdate ? handleUpdate : handleCreate}\n title={formTitle}\n description={\n isUpdate\n ? 'Update this sandbox provider. Leave API key blank to keep the existing key.'\n : 'Configure this sandbox provider. API key is never stored in the catalog.'\n }\n initialConfig={formInitialConfig}\n requireApiKey={!isUpdate}\n busy={busy}\n error={formError}\n />\n </>\n );\n};\n\nexport default SandboxSettings;\n","'use client';\n\nimport { useEffect, useState, type FormEvent } from 'react';\n\nimport { cn } from '../../atoms/lib/cn.js';\nimport { auiInputClass } from '../../atoms/lib/inputClasses.js';\nimport { Accordion, AccordionDetails, AccordionSummary } from '../../atoms/primitives/Accordion.js';\nimport { Button } from '../../atoms/primitives/Button.js';\nimport { CenteredModal } from '../../atoms/primitives/CenteredModal.js';\nimport { Icon } from '../../icons/Icon.js';\nimport type { SandboxProviderConfig } from '../../server/types.js';\n\nexport type SandboxConfigDraft = SandboxProviderConfig & {\n apiKey: string;\n};\n\ntype ConfigureSandboxFormProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSave: (draft: SandboxConfigDraft) => void | Promise<void>;\n title: string;\n description?: string;\n /** Prefills config fields; apiKey is never autofilled. */\n initialConfig?: SandboxProviderConfig | null;\n /** When false (updates), empty apiKey means keep the existing key. */\n requireApiKey?: boolean;\n busy?: boolean;\n error?: string | null;\n};\n\n/** Sensible defaults so the advanced fields are never blank, even without a catalog preset. */\nconst EMPTY_CONFIG: SandboxProviderConfig = {\n // Snapshot/image is release-owned now; kept only to satisfy the external SandboxProviderConfig type.\n snapshotName: '',\n execTimeoutMs: 300000,\n autoStopIntervalInMinutes: 15,\n autoArchiveIntervalInMinutes: 10080,\n autoDeleteIntervalInMinutes: 43200,\n};\n\nconst inputClassName = auiInputClass('h-11 shadow-sm');\n\nfunction parseNonNegInt(raw: string): number | null {\n if (raw.trim() === '') return null;\n const n = Number(raw);\n if (!Number.isFinite(n) || n < 0) return null;\n return n;\n}\n\nconst ConfigureSandboxForm = ({\n open,\n onOpenChange,\n onSave,\n title,\n description,\n initialConfig = null,\n requireApiKey = true,\n busy = false,\n error,\n}: ConfigureSandboxFormProps) => {\n const [execTimeoutMs, setExecTimeoutMs] = useState('');\n const [autoStopIntervalInMinutes, setAutoStopIntervalInMinutes] = useState('');\n const [autoArchiveIntervalInMinutes, setAutoArchiveIntervalInMinutes] = useState('');\n const [autoDeleteIntervalInMinutes, setAutoDeleteIntervalInMinutes] = useState('');\n const [apiKey, setApiKey] = useState('');\n const [advancedOpen, setAdvancedOpen] = useState(false);\n\n const resetForm = () => {\n setExecTimeoutMs('');\n setAutoStopIntervalInMinutes('');\n setAutoArchiveIntervalInMinutes('');\n setAutoDeleteIntervalInMinutes('');\n setApiKey('');\n setAdvancedOpen(false);\n };\n\n useEffect(() => {\n if (!open) return;\n const config = initialConfig ?? EMPTY_CONFIG;\n setExecTimeoutMs(String(config.execTimeoutMs));\n setAutoStopIntervalInMinutes(String(config.autoStopIntervalInMinutes));\n setAutoArchiveIntervalInMinutes(String(config.autoArchiveIntervalInMinutes));\n setAutoDeleteIntervalInMinutes(String(config.autoDeleteIntervalInMinutes));\n setApiKey('');\n setAdvancedOpen(false);\n }, [open, initialConfig]);\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (!nextOpen) resetForm();\n onOpenChange(nextOpen);\n };\n\n const execTimeout = parseNonNegInt(execTimeoutMs);\n const autoStop = parseNonNegInt(autoStopIntervalInMinutes);\n const autoArchive = parseNonNegInt(autoArchiveIntervalInMinutes);\n const autoDelete = parseNonNegInt(autoDeleteIntervalInMinutes);\n const trimmedKey = apiKey.trim();\n\n const isValid =\n (!requireApiKey || !!trimmedKey) &&\n execTimeout != null &&\n autoStop != null &&\n autoArchive != null &&\n autoDelete != null;\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!isValid || busy || execTimeout == null || autoStop == null || autoArchive == null || autoDelete == null) {\n return;\n }\n\n try {\n await onSave({\n // Snapshot/image is release-owned; the field is retained only for the external type.\n snapshotName: '',\n execTimeoutMs: execTimeout,\n autoStopIntervalInMinutes: autoStop,\n autoArchiveIntervalInMinutes: autoArchive,\n autoDeleteIntervalInMinutes: autoDelete,\n apiKey: trimmedKey,\n });\n resetForm();\n onOpenChange(false);\n } catch {\n // Parent surfaces error; keep form open.\n }\n };\n\n return (\n <CenteredModal\n open={open}\n onOpenChange={handleOpenChange}\n title={title}\n description={description}\n contentSized\n headerIcon={\n <span\n className=\"flex size-11 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary\"\n aria-hidden\n >\n <Icon name=\"cube\" className=\"size-6\" />\n </span>\n }\n >\n <form className=\"flex flex-col overflow-y-auto p-5 md:p-6\" onSubmit={handleSubmit}>\n <div className=\"space-y-4\">\n <div>\n <label htmlFor=\"sandbox-api-key\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n API key\n {!requireApiKey ? <span className=\"font-normal text-text-secondary\"> (optional)</span> : null}\n </label>\n <input\n id=\"sandbox-api-key\"\n type=\"password\"\n required={requireApiKey}\n value={apiKey}\n onChange={event => {\n setApiKey(event.target.value);\n }}\n placeholder={requireApiKey ? 'dtn_...' : 'Leave blank to keep existing'}\n autoFocus\n className={inputClassName}\n />\n </div>\n\n <Accordion\n expanded={advancedOpen}\n onChange={(_event, next) => setAdvancedOpen(next)}\n className=\"rounded-md border border-border\"\n >\n <AccordionSummary className=\"px-3 py-2.5\">\n <span className=\"flex w-full items-center justify-between text-sm font-medium text-text-primary\">\n Advanced settings\n <Icon\n name=\"chevron-down\"\n className={cn(\n 'size-4 shrink-0 text-text-secondary transition-transform duration-200',\n advancedOpen ? 'rotate-0' : '-rotate-90',\n )}\n />\n </span>\n </AccordionSummary>\n <AccordionDetails className=\"space-y-4 border-t border-border px-3 pb-3 pt-4\">\n <div>\n <label htmlFor=\"sandbox-exec-timeout\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Exec timeout (ms)\n </label>\n <input\n id=\"sandbox-exec-timeout\"\n type=\"number\"\n min={0}\n required\n value={execTimeoutMs}\n onChange={event => {\n setExecTimeoutMs(event.target.value);\n }}\n placeholder=\"300000\"\n className={inputClassName}\n />\n </div>\n\n <div>\n <label htmlFor=\"sandbox-auto-stop\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Auto-stop interval (minutes)\n </label>\n <input\n id=\"sandbox-auto-stop\"\n type=\"number\"\n min={0}\n required\n value={autoStopIntervalInMinutes}\n onChange={event => {\n setAutoStopIntervalInMinutes(event.target.value);\n }}\n placeholder=\"15\"\n className={inputClassName}\n />\n </div>\n\n <div>\n <label htmlFor=\"sandbox-auto-archive\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Auto-archive interval (minutes)\n </label>\n <input\n id=\"sandbox-auto-archive\"\n type=\"number\"\n min={0}\n required\n value={autoArchiveIntervalInMinutes}\n onChange={event => {\n setAutoArchiveIntervalInMinutes(event.target.value);\n }}\n placeholder=\"10080\"\n className={inputClassName}\n />\n </div>\n\n <div>\n <label htmlFor=\"sandbox-auto-delete\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Auto-delete interval (minutes)\n </label>\n <input\n id=\"sandbox-auto-delete\"\n type=\"number\"\n min={0}\n required\n value={autoDeleteIntervalInMinutes}\n onChange={event => {\n setAutoDeleteIntervalInMinutes(event.target.value);\n }}\n placeholder=\"43200\"\n className={inputClassName}\n />\n </div>\n </AccordionDetails>\n </Accordion>\n </div>\n\n <div className=\"mt-6 space-y-3\">\n {error ? <p className=\"text-failure-bg text-sm\">{error}</p> : null}\n <Button type=\"submit\" size=\"lg\" disabled={!isValid || busy} className=\"w-full shrink-0\">\n Save\n </Button>\n </div>\n </form>\n </CenteredModal>\n );\n};\n\nexport default ConfigureSandboxForm;\n"],"mappings":"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","names":["useEffect","useState","jsx","jsxs","useState","useEffect"]}