@truefoundry/trueforge-ui 0.3.0-rc.1 → 0.3.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +7 -0
  3. package/dist/{AgentCodeSnippets-NZOFJE57.js → AgentCodeSnippets-637HQUXD.js} +7 -7
  4. package/dist/AgentMetricChart-4FYECRIN.js +15 -0
  5. package/dist/{AgentOverview-EEBHJC32.js → AgentOverview-3FJ5EE6N.js} +7 -7
  6. package/dist/{AgentSessionEventTimeline-26Z6IB3B.js → AgentSessionEventTimeline-VELWUYPR.js} +18 -9
  7. package/dist/AgentSessionEventTimeline-VELWUYPR.js.map +1 -0
  8. package/dist/{AgentSessionEventTimelineChart-CGCU7WBK.js → AgentSessionEventTimelineChart-CUKETHWM.js} +140 -53
  9. package/dist/AgentSessionEventTimelineChart-CUKETHWM.js.map +1 -0
  10. package/dist/{AgentSessions-3MPDZASK.js → AgentSessions-T7MOGOTZ.js} +8 -8
  11. package/dist/{ConnectorSettings-MXFRWWR6.js → ConnectorSettings-ESZ2RSRG.js} +18 -22
  12. package/dist/ConnectorSettings-ESZ2RSRG.js.map +1 -0
  13. package/dist/{DockLayout-LM4AFMFY.js → DockLayout-NLFNU6F2.js} +10 -10
  14. package/dist/{DrawerLayout-JR3O6RRB.js → DrawerLayout-PR3SMKA6.js} +12 -12
  15. package/dist/DrawerLayout-PR3SMKA6.js.map +1 -0
  16. package/dist/{ModelSettings-G7IFNC2Y.js → ModelSettings-LYW64IRR.js} +19 -25
  17. package/dist/ModelSettings-LYW64IRR.js.map +1 -0
  18. package/dist/OpenUiFenceBlock-JEPNPJ7U.js +9 -0
  19. package/dist/{SandboxSettings-NXAANMAX.js → SandboxSettings-DF64LHYI.js} +15 -19
  20. package/dist/SandboxSettings-DF64LHYI.js.map +1 -0
  21. package/dist/SchedulesPage-WQU4H25F.js +15 -0
  22. package/dist/{SettingsBuilder-L34IQ56S.js → SettingsBuilder-LSXK2VN4.js} +8 -8
  23. package/dist/{ShellRouteSync-CEBETGEJ.js → ShellRouteSync-B22IAV2W.js} +19 -9
  24. package/dist/ShellRouteSync-B22IAV2W.js.map +1 -0
  25. package/dist/{SidebarLayout-A2HJPPHS.js → SidebarLayout-XW6LXB7R.js} +17 -16
  26. package/dist/SidebarLayout-XW6LXB7R.js.map +1 -0
  27. package/dist/{SkillSettings-FGGMSUNO.js → SkillSettings-64VXUO6J.js} +13 -16
  28. package/dist/SkillSettings-64VXUO6J.js.map +1 -0
  29. package/dist/{TrueForgeUIWithRouter-MZVJWJMB.js → TrueForgeUIWithRouter-3TSLV22Q.js} +9 -9
  30. package/dist/{WidgetLayout-6QM45OQQ.js → WidgetLayout-Q5P7PYSJ.js} +10 -10
  31. package/dist/{chunk-ZKNUMH2M.js → chunk-5I2COQNL.js} +2 -2
  32. package/dist/chunk-BWHOZFIV.js +587 -0
  33. package/dist/chunk-BWHOZFIV.js.map +1 -0
  34. package/dist/{chunk-U7KURWW3.js → chunk-FQK2XVVE.js} +66 -26
  35. package/dist/chunk-FQK2XVVE.js.map +1 -0
  36. package/dist/{chunk-M62XY4NC.js → chunk-G2TUAD65.js} +6 -6
  37. package/dist/{chunk-M62XY4NC.js.map → chunk-G2TUAD65.js.map} +1 -1
  38. package/dist/{chunk-6O6FWUDW.js → chunk-GXYAOAK5.js} +23 -42
  39. package/dist/chunk-GXYAOAK5.js.map +1 -0
  40. package/dist/{chunk-XAU7QFG3.js → chunk-H6WTY5PM.js} +60 -38
  41. package/dist/chunk-H6WTY5PM.js.map +1 -0
  42. package/dist/{chunk-FJW36PD7.js → chunk-I3AL54MA.js} +10 -10
  43. package/dist/{chunk-FJW36PD7.js.map → chunk-I3AL54MA.js.map} +1 -1
  44. package/dist/{chunk-CYHJDKFB.js → chunk-LGRHHFHN.js} +16 -11
  45. package/dist/{chunk-CYHJDKFB.js.map → chunk-LGRHHFHN.js.map} +1 -1
  46. package/dist/{chunk-2XPPBEYF.js → chunk-NHHSZB5N.js} +2 -2
  47. package/dist/{chunk-WVE3F724.js → chunk-SQGT43Z3.js} +3 -3
  48. package/dist/{chunk-MPNSO7E6.js → chunk-VJ7BZGAF.js} +2 -2
  49. package/dist/{chunk-DMMZSZTN.js → chunk-VUMGMGKZ.js} +13 -13
  50. package/dist/chunk-VUMGMGKZ.js.map +1 -0
  51. package/dist/{chunk-ZTMKFZQ3.js → chunk-YQO2NMJ3.js} +447 -320
  52. package/dist/chunk-YQO2NMJ3.js.map +1 -0
  53. package/dist/index.d.ts +27 -7
  54. package/dist/index.js +13 -11
  55. package/dist/index.js.map +1 -1
  56. package/dist/plugins/trueforge-agent-server-adapter/index.js +2 -1
  57. package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
  58. package/dist/styles.css +1 -1
  59. package/package.json +3 -3
  60. package/dist/AgentMetricChart-JPU3MFQ2.js +0 -15
  61. package/dist/AgentSessionEventTimeline-26Z6IB3B.js.map +0 -1
  62. package/dist/AgentSessionEventTimelineChart-CGCU7WBK.js.map +0 -1
  63. package/dist/ConnectorSettings-MXFRWWR6.js.map +0 -1
  64. package/dist/DrawerLayout-JR3O6RRB.js.map +0 -1
  65. package/dist/ModelSettings-G7IFNC2Y.js.map +0 -1
  66. package/dist/OpenUiFenceBlock-2TV5TQ6P.js +0 -9
  67. package/dist/SandboxSettings-NXAANMAX.js.map +0 -1
  68. package/dist/SchedulesPage-KKLUDO6B.js +0 -15
  69. package/dist/ShellRouteSync-CEBETGEJ.js.map +0 -1
  70. package/dist/SidebarLayout-A2HJPPHS.js.map +0 -1
  71. package/dist/SkillSettings-FGGMSUNO.js.map +0 -1
  72. package/dist/chunk-6O6FWUDW.js.map +0 -1
  73. package/dist/chunk-7Z2C2K7F.js +0 -578
  74. package/dist/chunk-7Z2C2K7F.js.map +0 -1
  75. package/dist/chunk-DMMZSZTN.js.map +0 -1
  76. package/dist/chunk-U7KURWW3.js.map +0 -1
  77. package/dist/chunk-XAU7QFG3.js.map +0 -1
  78. package/dist/chunk-ZTMKFZQ3.js.map +0 -1
  79. /package/dist/{AgentCodeSnippets-NZOFJE57.js.map → AgentCodeSnippets-637HQUXD.js.map} +0 -0
  80. /package/dist/{AgentMetricChart-JPU3MFQ2.js.map → AgentMetricChart-4FYECRIN.js.map} +0 -0
  81. /package/dist/{AgentOverview-EEBHJC32.js.map → AgentOverview-3FJ5EE6N.js.map} +0 -0
  82. /package/dist/{AgentSessions-3MPDZASK.js.map → AgentSessions-T7MOGOTZ.js.map} +0 -0
  83. /package/dist/{DockLayout-LM4AFMFY.js.map → DockLayout-NLFNU6F2.js.map} +0 -0
  84. /package/dist/{OpenUiFenceBlock-2TV5TQ6P.js.map → OpenUiFenceBlock-JEPNPJ7U.js.map} +0 -0
  85. /package/dist/{SchedulesPage-KKLUDO6B.js.map → SchedulesPage-WQU4H25F.js.map} +0 -0
  86. /package/dist/{SettingsBuilder-L34IQ56S.js.map → SettingsBuilder-LSXK2VN4.js.map} +0 -0
  87. /package/dist/{TrueForgeUIWithRouter-MZVJWJMB.js.map → TrueForgeUIWithRouter-3TSLV22Q.js.map} +0 -0
  88. /package/dist/{WidgetLayout-6QM45OQQ.js.map → WidgetLayout-Q5P7PYSJ.js.map} +0 -0
  89. /package/dist/{chunk-ZKNUMH2M.js.map → chunk-5I2COQNL.js.map} +0 -0
  90. /package/dist/{chunk-2XPPBEYF.js.map → chunk-NHHSZB5N.js.map} +0 -0
  91. /package/dist/{chunk-WVE3F724.js.map → chunk-SQGT43Z3.js.map} +0 -0
  92. /package/dist/{chunk-MPNSO7E6.js.map → chunk-VJ7BZGAF.js.map} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truefoundry/trueforge-ui",
3
- "version": "0.3.0-rc.1",
3
+ "version": "0.3.0-rc.2",
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",
@@ -95,7 +95,7 @@
95
95
  "tailwind-merge": "^3.6.0",
96
96
  "truefoundry-gateway-sdk": "^0.4.2",
97
97
  "zod": "^4.4.3",
98
- "@truefoundry/trueforge-sdk": "0.1.4-rc.1"
98
+ "@truefoundry/trueforge-sdk": "0.1.4-rc.2"
99
99
  },
100
100
  "devDependencies": {
101
101
  "@eslint/js": "^9.39.0",
@@ -125,7 +125,7 @@
125
125
  },
126
126
  "scripts": {
127
127
  "prebuild": "pnpm -w run sdk:types",
128
- "build": "rm -rf dist && tailwindcss --input src/build-styles.css --output dist/styles.css --minify && tsup",
128
+ "build": "node ../../scripts/rm-path.mjs dist && tailwindcss --input src/build-styles.css --output dist/styles.css --minify && tsup",
129
129
  "dev:watch": "pnpm run \"/^(dev:watch:js|dev:watch:css)$/\"",
130
130
  "dev:watch:js": "tsup --watch",
131
131
  "dev:watch:css": "tailwindcss --input src/build-styles.css --output dist/styles.css --watch",
@@ -1,15 +0,0 @@
1
- "use client";
2
- import {
3
- AgentMetricChart
4
- } from "./chunk-ZKNUMH2M.js";
5
- import "./chunk-ZTMKFZQ3.js";
6
- import "./chunk-2XPPBEYF.js";
7
- import "./chunk-XAU7QFG3.js";
8
- import "./chunk-U7KURWW3.js";
9
- import "./chunk-M6MHLVSO.js";
10
- import "./chunk-MPNSO7E6.js";
11
- import "./chunk-7Z2C2K7F.js";
12
- export {
13
- AgentMetricChart
14
- };
15
- //# sourceMappingURL=AgentMetricChart-JPU3MFQ2.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/atoms/agent-details/AgentSessionEventTimeline.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useMemo, useState, type ComponentType } from 'react';\n\nimport { useSlot } from '../../theme/SlotsProvider.js';\nimport { SESSION_EVENT_TYPES, type SessionEventType } from '../../utils/sessionEventTimeline.js';\nimport { cn } from '../lib/cn.js';\nimport type { AgentSessionEventTimelineProps } from './types.js';\n\nexport function AgentSessionEventTimeline({ turns, segments, onSelectTurn }: AgentSessionEventTimelineProps) {\n const AgentSessionEventTimelineChart = useSlot('AgentSessionEventTimelineChart');\n const [hiddenTypes, setHiddenTypes] = useState<Set<SessionEventType>>(() => new Set());\n\n const availableEventTypes = useMemo(() => {\n const available = new Set(segments.map(segment => segment.type));\n return SESSION_EVENT_TYPES.filter(eventType => available.has(eventType.id));\n }, [segments]);\n\n const handleToggleType = useCallback((type: SessionEventType) => {\n setHiddenTypes(previous => {\n const next = new Set(previous);\n if (next.has(type)) next.delete(type);\n else next.add(type);\n return next;\n });\n }, []);\n\n if (segments.length === 0) return null;\n\n return (\n <div className=\"w-full\" data-slot=\"agent-session-event-timeline\">\n <div\n className=\"flex flex-wrap items-center gap-2 border-b border-border px-3 py-2\"\n data-slot=\"agent-session-event-types\"\n >\n <span className=\"text-xs font-medium uppercase text-text-secondary\">Event types</span>\n <div className=\"flex flex-wrap items-center gap-1\">\n {availableEventTypes.map(eventType => {\n const isVisible = !hiddenTypes.has(eventType.id);\n return (\n <button\n key={eventType.id}\n type=\"button\"\n aria-pressed={isVisible}\n className={cn(\n 'flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-xs font-medium',\n isVisible ? 'border-border text-text-primary' : 'border-transparent text-text-secondary opacity-80',\n )}\n onClick={() => handleToggleType(eventType.id)}\n >\n <span className=\"size-2 rounded-sm\" style={{ backgroundColor: eventType.color }} />\n {eventType.label}\n </button>\n );\n })}\n </div>\n </div>\n <div className=\"w-full py-2\">\n <AgentSessionEventTimelineChart\n turns={turns}\n segments={segments}\n hiddenTypes={hiddenTypes}\n onSelectTurn={onSelectTurn}\n />\n </div>\n </div>\n );\n}\n\ndeclare module '../../theme/SlotsProvider.js' {\n interface AtomSlots {\n AgentSessionEventTimeline: ComponentType<AgentSessionEventTimelineProps>;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAEA,SAAS,aAAa,SAAS,gBAAoC;AAiC3D,cAKM,YALN;AA1BD,SAAS,0BAA0B,EAAE,OAAO,UAAU,aAAa,GAAmC;AAC3G,QAAM,iCAAiC,QAAQ,gCAAgC;AAC/E,QAAM,CAAC,aAAa,cAAc,IAAI,SAAgC,MAAM,oBAAI,IAAI,CAAC;AAErF,QAAM,sBAAsB,QAAQ,MAAM;AACxC,UAAM,YAAY,IAAI,IAAI,SAAS,IAAI,aAAW,QAAQ,IAAI,CAAC;AAC/D,WAAO,oBAAoB,OAAO,eAAa,UAAU,IAAI,UAAU,EAAE,CAAC;AAAA,EAC5E,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,mBAAmB,YAAY,CAAC,SAA2B;AAC/D,mBAAe,cAAY;AACzB,YAAM,OAAO,IAAI,IAAI,QAAQ;AAC7B,UAAI,KAAK,IAAI,IAAI,EAAG,MAAK,OAAO,IAAI;AAAA,UAC/B,MAAK,IAAI,IAAI;AAClB,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,MAAI,SAAS,WAAW,EAAG,QAAO;AAElC,SACE,qBAAC,SAAI,WAAU,UAAS,aAAU,gCAChC;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,aAAU;AAAA,QAEV;AAAA,8BAAC,UAAK,WAAU,qDAAoD,yBAAW;AAAA,UAC/E,oBAAC,SAAI,WAAU,qCACZ,8BAAoB,IAAI,eAAa;AACpC,kBAAM,YAAY,CAAC,YAAY,IAAI,UAAU,EAAE;AAC/C,mBACE;AAAA,cAAC;AAAA;AAAA,gBAEC,MAAK;AAAA,gBACL,gBAAc;AAAA,gBACd,WAAW;AAAA,kBACT;AAAA,kBACA,YAAY,oCAAoC;AAAA,gBAClD;AAAA,gBACA,SAAS,MAAM,iBAAiB,UAAU,EAAE;AAAA,gBAE5C;AAAA,sCAAC,UAAK,WAAU,qBAAoB,OAAO,EAAE,iBAAiB,UAAU,MAAM,GAAG;AAAA,kBAChF,UAAU;AAAA;AAAA;AAAA,cAVN,UAAU;AAAA,YAWjB;AAAA,UAEJ,CAAC,GACH;AAAA;AAAA;AAAA,IACF;AAAA,IACA,oBAAC,SAAI,WAAU,eACb;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF,GACF;AAAA,KACF;AAEJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/atoms/agent-details/AgentSessionEventTimelineChart.tsx","../src/atoms/agent-details/AgentSessionTimelineTooltip.tsx"],"sourcesContent":["'use client';\n\nimport {\n BarElement,\n Chart as ChartJS,\n LinearScale,\n Tooltip,\n type ChartData,\n type ChartOptions,\n type Plugin,\n} from 'chart.js';\nimport { useCallback, useEffect, useMemo, useRef, useState, type ComponentType, type CSSProperties } from 'react';\nimport { Bar } from 'react-chartjs-2';\n\nimport { useThemeMode } from '../../theme/SlotsProvider.js';\nimport {\n formatTimelineDuration,\n getSessionEventColor,\n getSessionEventHoverColor,\n getSessionEventLabel,\n MAIN_THREAD_ID,\n type SessionEventTimelineSegment,\n} from '../../utils/sessionEventTimeline.js';\nimport {\n buildTimelineAxisTicks,\n getActiveTimelineMs,\n getSubAgentHoverGroups,\n getSubAgentLanes,\n getTimelineHoverTargetId,\n getTimelineLayout,\n getTimelineRange,\n groupOverlappingToolCalls,\n pickLongestNonOverlappingSegments,\n TIMELINE_TYPE,\n type TimelineGap,\n type TimelineHoverTarget,\n type TimelineTurnBar,\n} from '../../utils/sessionEventTimelineChart.js';\nimport { LightTooltip } from '../primitives/Tooltip.js';\nimport {\n hasSessionEventTooltip,\n SessionEventTooltip,\n SessionSubAgentGroupTooltip,\n SessionToolCallGroupTooltip,\n SessionTurnTooltip,\n} from './AgentSessionTimelineTooltip.js';\nimport type { AgentSessionEventTimelineChartProps } from './types.js';\n\nChartJS.register(LinearScale, BarElement, Tooltip);\n\nconst MARKER_PX = 4;\nconst TURN_GAP_PX = 12;\nconst END_PAD_PX = 12;\nconst BAR_RADIUS_PX = 2;\nconst ROW_GAP_PX = 8;\nconst OVERHEAD_PX = 30;\n\ntype BarPoint = { x: [number, number]; y: number };\n\nfunction rowCenters(heights: number[], gap: number): { centers: number[]; band: number } {\n const centers: number[] = [];\n let offset = 0;\n for (const height of heights) {\n centers.push(offset + height / 2);\n offset += height + gap;\n }\n return { centers, band: Math.max(0, offset - gap) };\n}\n\nfunction eventOrder(type: SessionEventTimelineSegment['type']): number {\n if (type === 'sub_agent') return 0;\n if (type === 'model') return 2;\n return 1;\n}\n\nfunction turnBarLabelPoint(element: object): { x: number; y: number } | null {\n if (!('x' in element) || !('y' in element) || !('base' in element)) return null;\n const { x, y, base } = element;\n if (typeof x !== 'number' || typeof y !== 'number' || typeof base !== 'number') return null;\n return { x: (x + base) / 2, y };\n}\n\nexport function AgentSessionEventTimelineChart({\n turns,\n segments,\n hiddenTypes,\n onSelectTurn,\n}: AgentSessionEventTimelineChartProps) {\n const mode = useThemeMode();\n const isDark = mode === 'dark';\n const axis = isDark ? '#8c8c92' : '#71717a';\n const grid = isDark ? '#27272a' : '#e4e4e7';\n const turnFill = isDark ? '#3f3f46' : '#e4e4e7';\n const turnHover = isDark ? '#52525b' : '#d4d4d8';\n const wrapperRef = useRef<HTMLDivElement>(null);\n const [widthPx, setWidthPx] = useState(0);\n const [overheadPx, setOverheadPx] = useState(OVERHEAD_PX);\n const [tooltipTarget, setTooltipTarget] = useState<TimelineHoverTarget | null>(null);\n const [tooltipAnchor, setTooltipAnchor] = useState<{ left: number; top: number } | null>(null);\n const tooltipIdRef = useRef('');\n const tooltipCursorXRef = useRef<number | null>(null);\n\n useEffect(() => {\n const wrapper = wrapperRef.current;\n if (wrapper == null) return undefined;\n const update = () => setWidthPx(wrapper.clientWidth);\n update();\n const observer = new ResizeObserver(update);\n observer.observe(wrapper);\n return () => observer.disconnect();\n }, []);\n\n const refreshTooltipAnchor = useCallback(() => {\n const wrapper = wrapperRef.current;\n const left = tooltipCursorXRef.current;\n if (wrapper == null || left == null) return;\n setTooltipAnchor({ left, top: wrapper.getBoundingClientRect().bottom });\n }, []);\n\n const clearTooltip = useCallback(() => {\n tooltipIdRef.current = '';\n tooltipCursorXRef.current = null;\n setTooltipTarget(null);\n setTooltipAnchor(null);\n }, []);\n\n useEffect(() => {\n if (tooltipTarget == null) return undefined;\n // Anchors use viewport coordinates, so remeasure the chart whenever any\n // scroll ancestor or the viewport moves it.\n refreshTooltipAnchor();\n window.addEventListener('scroll', refreshTooltipAnchor, true);\n window.addEventListener('resize', refreshTooltipAnchor);\n return () => {\n window.removeEventListener('scroll', refreshTooltipAnchor, true);\n window.removeEventListener('resize', refreshTooltipAnchor);\n };\n }, [refreshTooltipAnchor, tooltipTarget]);\n\n const activeTotalMs = Math.max(1, ...segments.map(segment => segment.endMs));\n const { turnStartsMs, turnOrdinals, turnRanges } = useMemo(() => getTimelineLayout(segments), [segments]);\n const gapCount = Math.max(0, turnStartsMs.length - 1);\n const scaleWidthPx = Math.max(widthPx / 2, widthPx - TURN_GAP_PX * gapCount - END_PAD_PX);\n const msPerPx = activeTotalMs / Math.max(1, scaleWidthPx);\n const turnGapMs = TURN_GAP_PX * msPerPx;\n const totalMs = activeTotalMs + gapCount * turnGapMs;\n const timelineMaxMs = totalMs + END_PAD_PX * msPerPx;\n const timelineGaps = useMemo<TimelineGap[]>(\n () =>\n turnStartsMs\n .slice(1)\n .map((startMs, index) => ({ startMs: startMs + index * turnGapMs, endMs: startMs + (index + 1) * turnGapMs })),\n [turnGapMs, turnStartsMs],\n );\n\n const visibleSegments = useMemo(\n () =>\n segments.flatMap(segment => {\n if (hiddenTypes.has(segment.type)) return [];\n const shiftMs = (turnOrdinals.get(segment.turnIndex) ?? 0) * turnGapMs;\n return [{ ...segment, startMs: segment.startMs + shiftMs, endMs: segment.endMs + shiftMs }];\n }),\n [hiddenTypes, segments, turnGapMs, turnOrdinals],\n );\n const turnBars = useMemo<TimelineTurnBar[]>(\n () =>\n turnRanges.length < 2\n ? []\n : turnRanges.map(range => ({\n ...range,\n id: `turn-${range.turnIndex}`,\n durationMs: range.endMs - range.startMs,\n startMs: range.startMs + range.ordinal * turnGapMs,\n endMs: range.endMs + range.ordinal * turnGapMs + MARKER_PX * msPerPx,\n })),\n [msPerPx, turnGapMs, turnRanges],\n );\n const subAgentSegments = useMemo(\n () => visibleSegments.filter(segment => segment.type === 'sub_agent'),\n [visibleSegments],\n );\n const mainSubAgents = useMemo(() => pickLongestNonOverlappingSegments(subAgentSegments), [subAgentSegments]);\n const subAgentGroups = useMemo(\n () => getSubAgentHoverGroups({ bars: mainSubAgents, subAgentSegments }),\n [mainSubAgents, subAgentSegments],\n );\n const subAgentLanes = useMemo(\n () => getSubAgentLanes({ subAgentSegments, threadSegments: visibleSegments, minWidthMs: MARKER_PX * msPerPx }),\n [msPerPx, subAgentSegments, visibleSegments],\n );\n const mainCandidates = useMemo(() => {\n const kept = new Set(mainSubAgents.map(segment => segment.id));\n return visibleSegments.filter(\n segment => segment.threadId === MAIN_THREAD_ID || (segment.type === 'sub_agent' && kept.has(segment.id)),\n );\n }, [mainSubAgents, visibleSegments]);\n const toolCallGroups = useMemo(\n () =>\n groupOverlappingToolCalls(mainCandidates.filter(segment => segment.type === 'tool_call')).filter(\n group => group.segments.length > 1,\n ),\n [mainCandidates],\n );\n const groupedIds = useMemo(\n () => new Set(toolCallGroups.flatMap(group => group.segments.map(segment => segment.id))),\n [toolCallGroups],\n );\n const mainEventSegments = useMemo(\n () => mainCandidates.filter(segment => !groupedIds.has(segment.id)),\n [groupedIds, mainCandidates],\n );\n const laneCount = subAgentLanes.reduce((count, lane) => Math.max(count, lane.lane + 1), 0);\n const hasTurnRow = turnBars.length > 0;\n const eventRow = hasTurnRow ? 1 : 0;\n const { centers, band } = useMemo(\n () => rowCenters([...(hasTurnRow ? [16] : []), 28, ...Array.from({ length: laneCount }, () => 12)], ROW_GAP_PX),\n [hasTurnRow, laneCount],\n );\n\n const chartTargets = useMemo<Array<TimelineHoverTarget | null>>(\n () => [\n ...turnBars.map((bar): TimelineHoverTarget => ({ type: TIMELINE_TYPE.turn, bar })),\n ...subAgentLanes.flatMap(lane =>\n lane.segments.map((segment): TimelineHoverTarget => ({ type: TIMELINE_TYPE.event, segment })),\n ),\n ...mainEventSegments.map((segment): TimelineHoverTarget | null => {\n if (segment.type !== 'sub_agent') return { type: TIMELINE_TYPE.event, segment };\n const group = subAgentGroups.find(candidate => candidate.barId === segment.id);\n return group == null ? { type: TIMELINE_TYPE.event, segment } : { type: TIMELINE_TYPE.subAgentGroup, group };\n }),\n ...toolCallGroups.map((group): TimelineHoverTarget => ({ type: TIMELINE_TYPE.toolCallGroup, group })),\n ],\n [mainEventSegments, subAgentGroups, subAgentLanes, toolCallGroups, turnBars],\n );\n\n const barDataset = ({\n label,\n range,\n y,\n color,\n hover,\n thickness,\n order = 1,\n inflateAmount,\n }: {\n label: string;\n range: TimelineGap;\n y: number;\n color: string;\n hover: string;\n thickness: number;\n order?: number;\n inflateAmount?: number;\n }) => ({\n label,\n data: [{ x: getTimelineRange(range), y }] satisfies BarPoint[],\n backgroundColor: color,\n hoverBackgroundColor: hover,\n hoverBorderColor: hover,\n borderWidth: 0,\n borderSkipped: false,\n borderRadius: BAR_RADIUS_PX,\n minBarLength: MARKER_PX,\n barThickness: thickness,\n grouped: false,\n order,\n ...(inflateAmount == null ? {} : { inflateAmount }),\n });\n\n const chartData = useMemo<ChartData<'bar', BarPoint[], string>>(\n () => ({\n datasets: [\n ...turnBars.map(bar =>\n barDataset({\n label: `Turn ${bar.ordinal + 1}`,\n range: bar,\n y: centers[0] ?? 0,\n color: turnFill,\n hover: turnHover,\n thickness: 16,\n }),\n ),\n ...subAgentLanes.flatMap(lane =>\n lane.segments.map(segment =>\n barDataset({\n label: `${getSessionEventLabel(segment.type)}: ${segment.title}`,\n range: segment,\n y: centers[eventRow + 1 + lane.lane] ?? 0,\n color: getSessionEventColor(segment.type),\n hover: getSessionEventHoverColor(segment.type),\n thickness: 12,\n order: eventOrder(segment.type),\n inflateAmount: 0.5,\n }),\n ),\n ),\n ...mainEventSegments.map(segment =>\n barDataset({\n label: `${getSessionEventLabel(segment.type)}: ${segment.title}`,\n range: segment,\n y: centers[eventRow] ?? 0,\n color: getSessionEventColor(segment.type),\n hover: getSessionEventHoverColor(segment.type),\n thickness: 28,\n order: eventOrder(segment.type),\n inflateAmount: 0.5,\n }),\n ),\n ...toolCallGroups.map(group =>\n barDataset({\n label: 'Parallel tool calls',\n range: group,\n y: centers[eventRow] ?? 0,\n color: getSessionEventColor('tool_call'),\n hover: getSessionEventHoverColor('tool_call'),\n thickness: 28,\n order: eventOrder('tool_call'),\n inflateAmount: 0.5,\n }),\n ),\n ],\n }),\n [centers, eventRow, mainEventSegments, subAgentLanes, toolCallGroups, turnBars, turnFill, turnHover],\n );\n\n const turnLabelPlugin = useMemo<Plugin<'bar'>>(\n () => ({\n id: 'turnLabels',\n afterDatasetsDraw(chart) {\n const { ctx } = chart;\n ctx.save();\n ctx.fillStyle = axis;\n ctx.font = '500 10px sans-serif';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n turnBars.forEach((bar, index) => {\n const element = chart.getDatasetMeta(index).data[0];\n if (element == null) return;\n const point = turnBarLabelPoint(element);\n if (point) ctx.fillText(`T${bar.ordinal + 1}`, point.x, point.y);\n });\n ctx.restore();\n },\n }),\n [axis, turnBars],\n );\n const overheadPlugin = useMemo<Plugin<'bar'>>(\n () => ({\n id: 'timelineOverhead',\n afterLayout(chart) {\n const next = Math.round(chart.height - chart.chartArea.height);\n setOverheadPx(previous => (previous === next ? previous : next));\n },\n }),\n [],\n );\n\n const chartOptions = useMemo<ChartOptions<'bar'>>(\n () => ({\n indexAxis: 'y',\n animation: false,\n responsive: true,\n maintainAspectRatio: false,\n onClick: (_event, elements) => {\n const target = chartTargets[elements[0]?.datasetIndex ?? -1];\n if (target?.type === TIMELINE_TYPE.turn) onSelectTurn?.(target.bar.turnIndex);\n },\n onHover: (event, elements) => {\n const hoveredDatasetIndex = elements[0]?.datasetIndex;\n const next = hoveredDatasetIndex == null ? null : (chartTargets[hoveredDatasetIndex] ?? null);\n const native = event.native;\n if (native?.target instanceof HTMLElement) {\n native.target.style.cursor = next?.type === TIMELINE_TYPE.turn ? 'pointer' : 'default';\n }\n if (native instanceof MouseEvent) {\n tooltipCursorXRef.current = native.clientX;\n refreshTooltipAnchor();\n }\n // Pointer between bars keeps the current tooltip; a bar without a tooltip dismisses it.\n if (hoveredDatasetIndex == null) return;\n const nextId = getTimelineHoverTargetId(next);\n if (tooltipIdRef.current === nextId) return;\n tooltipIdRef.current = nextId;\n setTooltipTarget(next);\n if (next == null) {\n setTooltipAnchor(null);\n return;\n }\n refreshTooltipAnchor();\n },\n plugins: { legend: { display: false }, tooltip: { enabled: false } },\n scales: {\n x: {\n type: 'linear',\n position: 'top',\n min: 0,\n max: timelineMaxMs,\n grid: { color: grid },\n border: { color: grid },\n afterBuildTicks: scale => {\n scale.ticks = buildTimelineAxisTicks({\n ticks: scale.ticks,\n totalMs,\n timelineMaxMs,\n });\n },\n ticks: {\n color: axis,\n autoSkip: false,\n includeBounds: true,\n maxTicksLimit: 9,\n stepSize: timelineMaxMs / 8,\n callback: value => {\n const timelineMs = Number(value);\n return timelineMs <= totalMs ? formatTimelineDuration(getActiveTimelineMs(timelineMs, timelineGaps)) : '';\n },\n },\n },\n y: {\n type: 'linear',\n display: false,\n reverse: true,\n offset: false,\n min: 0,\n max: band,\n grid: { display: false },\n },\n },\n }),\n [axis, band, chartTargets, grid, onSelectTurn, refreshTooltipAnchor, timelineGaps, timelineMaxMs, totalMs],\n );\n\n const tooltipTurn = tooltipTarget?.type === TIMELINE_TYPE.turn ? turns[tooltipTarget.bar.turnIndex] : undefined;\n const containerStyle = useMemo<CSSProperties>(() => ({ height: band + overheadPx }), [band, overheadPx]);\n const tooltipContent =\n tooltipTarget?.type === TIMELINE_TYPE.turn && tooltipTurn != null ? (\n <SessionTurnTooltip\n turn={tooltipTurn}\n turnNumber={tooltipTarget.bar.ordinal + 1}\n durationMs={tooltipTarget.bar.durationMs}\n segments={segments.filter(segment => segment.turnIndex === tooltipTarget.bar.turnIndex)}\n />\n ) : tooltipTarget?.type === TIMELINE_TYPE.event && hasSessionEventTooltip(tooltipTarget.segment) ? (\n <SessionEventTooltip\n segment={tooltipTarget.segment}\n subAgentLabel={\n tooltipTarget.segment.type === 'sub_agent'\n ? undefined\n : subAgentLanes.find(lane => lane.threadId === tooltipTarget.segment.threadId)?.track.description\n }\n />\n ) : tooltipTarget?.type === TIMELINE_TYPE.toolCallGroup ? (\n <SessionToolCallGroupTooltip group={tooltipTarget.group} />\n ) : tooltipTarget?.type === TIMELINE_TYPE.subAgentGroup ? (\n <SessionSubAgentGroupTooltip group={tooltipTarget.group} />\n ) : null;\n\n return (\n <div ref={wrapperRef} className=\"w-full\" data-slot=\"agent-session-event-timeline-chart\">\n <LightTooltip\n title={tooltipContent}\n side=\"bottom\"\n triggerClassName=\"block w-full\"\n followCursor\n open={tooltipTarget != null && tooltipContent != null}\n className=\"max-w-[min(25rem,calc(100vw-1rem))] whitespace-normal\"\n anchor={tooltipAnchor}\n >\n <div className=\"w-full\" style={containerStyle} onMouseLeave={clearTooltip}>\n <Bar data={chartData} options={chartOptions} plugins={[turnLabelPlugin, overheadPlugin]} />\n </div>\n </LightTooltip>\n </div>\n );\n}\n\ndeclare module '../../theme/SlotsProvider.js' {\n interface AtomSlots {\n AgentSessionEventTimelineChart: ComponentType<AgentSessionEventTimelineChartProps>;\n }\n}\n","'use client';\n\nimport { formatCostUsd, formatDurationMs, formatTokenCount } from '../../utils/sessionDisplayFormat.js';\nimport {\n formatTimelineDuration,\n getSessionEventColor,\n getSessionEventTooltipHeading,\n SESSION_EVENT_TOOLTIP_HIDE_DURATION,\n type SessionEventTimelineSegment,\n} from '../../utils/sessionEventTimeline.js';\nimport type { TimelineSubAgentGroup, TimelineToolCallGroup } from '../../utils/sessionEventTimelineChart.js';\nimport type { SessionTurnView } from '../../utils/sessionTurnViews.js';\n\nexport function hasSessionEventTooltip(segment: SessionEventTimelineSegment): boolean {\n return segment.type !== 'system' || segment.description.trim().length > 0;\n}\n\nexport function SessionEventTooltip({\n segment,\n subAgentLabel,\n}: {\n segment: SessionEventTimelineSegment;\n subAgentLabel?: string;\n}) {\n const showDuration = !segment.isMarker && !SESSION_EVENT_TOOLTIP_HIDE_DURATION.has(segment.type);\n const content = segment.description.trim();\n if (segment.type === 'system') {\n if (content.length === 0) return null;\n return (\n <p className=\"max-w-[25rem] whitespace-normal break-words text-xs font-medium text-text-primary\">{content}</p>\n );\n }\n\n return (\n <div className=\"max-h-72 max-w-[25rem] overflow-auto whitespace-normal break-words text-xs\">\n {subAgentLabel != null ? (\n <div className=\"border-b border-border py-1.5 text-text-secondary\">{`Sub-Agent: ${subAgentLabel}`}</div>\n ) : null}\n <div className=\"flex items-center justify-between gap-3 pt-1\">\n <span className={segment.type === 'error' ? 'font-medium text-failure-bg' : 'font-medium text-text-secondary'}>\n {getSessionEventTooltipHeading(segment.type)}\n </span>\n {showDuration ? (\n <span className=\"tabular-nums text-text-secondary\">\n {formatTimelineDuration(segment.endMs - segment.startMs)}\n </span>\n ) : null}\n </div>\n {content.length > 0 ? <p className=\"mt-1.5 line-clamp-6 font-medium text-text-primary\">{content}</p> : null}\n </div>\n );\n}\n\nexport function SessionTurnTooltip({\n turn,\n turnNumber,\n durationMs,\n segments,\n}: {\n turn: SessionTurnView;\n turnNumber: number;\n durationMs: number;\n segments: SessionEventTimelineSegment[];\n}) {\n return (\n <div className=\"max-h-72 w-72 max-w-full overflow-auto text-xs text-text-primary\">\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"font-semibold\">{`Turn ${turnNumber}`}</span>\n <span className=\"tabular-nums text-text-secondary\">{formatDurationMs(durationMs)}</span>\n </div>\n <div className=\"mt-1 flex flex-col text-text-secondary\">\n {turn.totalCostInUsd != null ? <span>{`Cost: ${formatCostUsd(turn.totalCostInUsd)}`}</span> : null}\n {turn.totalTokens != null ? <span>{`Tokens: ${formatTokenCount(turn.totalTokens)}`}</span> : null}\n </div>\n <div className=\"mt-2 border-t border-border pt-2\">\n {segments.map(segment => {\n const label =\n segment.type === 'tool_call' || segment.type === 'sub_agent' ? segment.description : segment.title;\n return (\n <div key={segment.id} className=\"flex min-w-0 items-center gap-1.5\">\n <span\n className=\"size-1.5 shrink-0 rounded-full\"\n style={{ backgroundColor: getSessionEventColor(segment.type) }}\n />\n <span className=\"min-w-0 flex-1 truncate\">{label}</span>\n {segment.isMarker ? null : (\n <span className=\"ml-auto shrink-0 tabular-nums text-text-secondary\">\n {formatTimelineDuration(segment.endMs - segment.startMs)}\n </span>\n )}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nexport function SessionToolCallGroupTooltip({ group }: { group: TimelineToolCallGroup }) {\n return (\n <div className=\"max-h-72 w-80 max-w-full overflow-auto text-xs\">\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"font-medium text-text-secondary\">Tool calls</span>\n <span className=\"tabular-nums text-text-secondary\">{formatTimelineDuration(group.endMs - group.startMs)}</span>\n </div>\n <div className=\"mt-1.5 border-t border-border pt-1.5\">\n {group.segments.map(segment => (\n <div key={segment.id} className=\"flex items-center justify-between gap-2 py-0.5\">\n <span className=\"min-w-0 truncate font-medium text-text-primary\">\n {segment.description || segment.title}\n </span>\n <span className=\"shrink-0 tabular-nums text-text-secondary\">\n {formatTimelineDuration(segment.endMs - segment.startMs)}\n </span>\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nexport function SessionSubAgentGroupTooltip({ group }: { group: TimelineSubAgentGroup }) {\n return (\n <div className=\"max-h-72 w-80 max-w-full overflow-auto text-xs\">\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"font-medium text-text-secondary\">Sub-agents</span>\n <span className=\"tabular-nums text-text-secondary\">{formatTimelineDuration(group.endMs - group.startMs)}</span>\n </div>\n <div className=\"mt-1.5 border-t border-border pt-1.5\">\n {group.segments.map((segment, index) => (\n <div key={segment.id} className=\"flex items-center justify-between gap-2 py-0.5\">\n <span className=\"min-w-0 truncate font-medium text-text-primary\">\n {`Sub-agent ${index + 1}: ${segment.description || segment.title}`}\n </span>\n <span className=\"shrink-0 tabular-nums text-text-secondary\">\n {formatTimelineDuration(segment.endMs - segment.startMs)}\n </span>\n </div>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["jsx"]}
@@ -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 description: entry.description ?? entry.url,\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 description: existingConnector.description,\n url: existingConnector.url,\n auth,\n });\n } else {\n await createFromCatalog(entry, auth);\n }\n closeApiKeyModal();\n setTimeout(() => {\n toaster?.showSuccess({\n title: `${entry.name} ${existingConnector ? 'updated' : 'connected'}`,\n });\n }, 100);\n }, setFormError).catch(() => {});\n };\n\n const handleAddMcpServer = async (draft: AddMcpServerDraft) => {\n setFormError(null);\n await runMutation(async () => {\n await connectorCatalog.createConnector({ ...draft });\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 description: 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 [description, setDescription] = 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 setDescription('');\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() && !!description.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 description: description.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-description\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Description\n <RequiredMark />\n </label>\n <textarea\n id=\"mcp-server-description\"\n value={description}\n onChange={event => {\n setDescription(event.target.value);\n }}\n placeholder=\"Query analytics from Postgres\"\n required\n rows={3}\n className={auiInputClass('resize-y py-2.5 shadow-sm')}\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":";;;;;;;;;;;;;;;;;;;;;;;;;AAEA,SAAS,aAAa,aAAAA,YAAW,SAAS,YAAAC,iBAAgC;;;ACA1E,SAAS,gBAAgC;AAkCvC,SA2KU,UA3KV,KA2EU,YA3EV;AATF,IAAM,eAA6D;AAAA,EACjE,EAAE,OAAO,OAAO,OAAO,QAAQ;AAAA,EAC/B,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,EAC/B,EAAE,OAAO,UAAU,OAAO,UAAU;AACtC;AAEA,IAAM,iBAAiB,cAAc,gBAAgB;AAErD,IAAM,eAAe,MACnB,oBAAC,UAAK,WAAU,0BAAyB,eAAW,MAAC,eAErD;AAGF,IAAM,mBAAmB,CAAC,EAAE,MAAM,cAAc,OAAO,OAAO,OAAO,MAAM,MAA6B;AACtG,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,EAAE;AACnC,QAAM,CAAC,KAAK,MAAM,IAAI,SAAS,EAAE;AACjC,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,EAAE;AACjD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAsB,KAAK;AAC3D,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,EAAE;AACvC,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,EAAE;AAE/C,QAAM,YAAY,MAAM;AACtB,YAAQ,EAAE;AACV,WAAO,EAAE;AACT,mBAAe,EAAE;AACjB,gBAAY,KAAK;AACjB,cAAU,EAAE;AACZ,kBAAc,EAAE;AAAA,EAClB;AAEA,QAAM,mBAAmB,CAAC,aAAsB;AAC9C,QAAI,CAAC,SAAU,WAAU;AACzB,iBAAa,QAAQ;AAAA,EACvB;AAEA,QAAM,UAAU,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,YAAY,KAAK,KAAK,CAAC,CAAC,IAAI,KAAK,MAAM,aAAa,YAAY,CAAC,CAAC,OAAO,KAAK;AAEjH,QAAM,eAAe,OAAO,UAAsC;AAChE,UAAM,eAAe;AACrB,QAAI,CAAC,WAAW,KAAM;AAEtB,UAAM,OACJ,aAAa,WACT;AAAA,MACE,MAAM;AAAA,MACN,QAAQ,OAAO,KAAK;AAAA,MACpB,GAAI,WAAW,KAAK,IAAI,EAAE,YAAY,WAAW,KAAK,EAAE,IAAI,CAAC;AAAA,IAC/D,IACA,EAAE,MAAM,SAAS;AAEvB,QAAI;AACF,YAAM,MAAM;AAAA,QACV,MAAM,KAAK,KAAK;AAAA,QAChB,KAAK,IAAI,KAAK;AAAA,QACd,aAAa,YAAY,KAAK;AAAA,QAC9B;AAAA,MACF,CAAC;AACD,gBAAU;AACV,mBAAa,KAAK;AAAA,IACpB,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,cAAc;AAAA,MACd,OAAM;AAAA,MACN,aAAY;AAAA,MACZ,cAAY;AAAA,MACZ,YACE;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,eAAW;AAAA,UAEX,8BAAC,QAAK,MAAK,cAAa,WAAU,UAAS;AAAA;AAAA,MAC7C;AAAA,MAGF,+BAAC,UAAK,WAAU,4CAA2C,UAAU,OAAK,KAAK,aAAa,CAAC,GAC3F;AAAA,6BAAC,SAAI,WAAU,aACb;AAAA,+BAAC,SACC;AAAA,iCAAC,WAAM,SAAQ,mBAAkB,WAAU,sDAAqD;AAAA;AAAA,cAE9F,oBAAC,gBAAa;AAAA,eAChB;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,IAAG;AAAA,gBACH,MAAK;AAAA,gBACL,UAAQ;AAAA,gBACR,OAAO;AAAA,gBACP,UAAU,WAAS;AACjB,0BAAQ,MAAM,OAAO,KAAK;AAAA,gBAC5B;AAAA,gBACA,aAAY;AAAA,gBACZ,WAAS;AAAA,gBACT,WAAW;AAAA;AAAA,YACb;AAAA,aACF;AAAA,UAEA,qBAAC,SACC;AAAA,iCAAC,WAAM,SAAQ,0BAAyB,WAAU,sDAAqD;AAAA;AAAA,cAErG,oBAAC,gBAAa;AAAA,eAChB;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,IAAG;AAAA,gBACH,OAAO;AAAA,gBACP,UAAU,WAAS;AACjB,iCAAe,MAAM,OAAO,KAAK;AAAA,gBACnC;AAAA,gBACA,aAAY;AAAA,gBACZ,UAAQ;AAAA,gBACR,MAAM;AAAA,gBACN,WAAW,cAAc,2BAA2B;AAAA;AAAA,YACtD;AAAA,aACF;AAAA,UAEA,qBAAC,SACC;AAAA,iCAAC,WAAM,SAAQ,kBAAiB,WAAU,sDAAqD;AAAA;AAAA,cAE7F,oBAAC,gBAAa;AAAA,eAChB;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,IAAG;AAAA,gBACH,MAAK;AAAA,gBACL,UAAQ;AAAA,gBACR,OAAO;AAAA,gBACP,UAAU,WAAS;AACjB,yBAAO,MAAM,OAAO,KAAK;AAAA,gBAC3B;AAAA,gBACA,aAAY;AAAA,gBACZ,WAAW;AAAA;AAAA,YACb;AAAA,aACF;AAAA,UAEA,qBAAC,cACC;AAAA,iCAAC,YAAO,WAAU,gDAA+C;AAAA;AAAA,cAE/D,oBAAC,gBAAa;AAAA,eAChB;AAAA,YACA,oBAAC,SAAI,WAAU,+EACZ,uBAAa,IAAI,YAChB;AAAA,cAAC;AAAA;AAAA,gBAEC,WAAW,+GACT,aAAa,OAAO,QAChB,4EACA,6CACN;AAAA,gBAEA;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,MAAK;AAAA,sBACL,OAAO,OAAO;AAAA,sBACd,SAAS,aAAa,OAAO;AAAA,sBAC7B,UAAU,MAAM;AACd,oCAAY,OAAO,KAAK;AAAA,sBAC1B;AAAA,sBACA,WAAU;AAAA;AAAA,kBACZ;AAAA,kBACC,OAAO;AAAA;AAAA;AAAA,cAjBH,OAAO;AAAA,YAkBd,CACD,GACH;AAAA,aACF;AAAA,UAEC,aAAa,QACZ,qBAAC,SAAI,WAAU,kDACb;AAAA,gCAAC,QAAK,MAAK,QAAO,WAAU,qCAAoC;AAAA,YAChE,oBAAC,SAAI,WAAU,2CAA0C,6IAGzD;AAAA,aACF,IACE;AAAA,UAEH,aAAa,WACZ,iCACE;AAAA,iCAAC,SACC;AAAA,mCAAC,WAAM,SAAQ,sBAAqB,WAAU,sDAAqD;AAAA;AAAA,gBAEjG,oBAAC,gBAAa;AAAA,iBAChB;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,IAAG;AAAA,kBACH,MAAK;AAAA,kBACL,UAAQ;AAAA,kBACR,OAAO;AAAA,kBACP,UAAU,WAAS;AACjB,8BAAU,MAAM,OAAO,KAAK;AAAA,kBAC9B;AAAA,kBACA,aAAY;AAAA,kBACZ,WAAW;AAAA;AAAA,cACb;AAAA,eACF;AAAA,YAEA,qBAAC,SACC;AAAA,mCAAC,WAAM,SAAQ,0BAAyB,WAAU,sDAAqD;AAAA;AAAA,gBACzF,oBAAC,UAAK,WAAU,mCAAkC,wBAAU;AAAA,iBAC1E;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,IAAG;AAAA,kBACH,MAAK;AAAA,kBACL,OAAO;AAAA,kBACP,UAAU,WAAS;AACjB,kCAAc,MAAM,OAAO,KAAK;AAAA,kBAClC;AAAA,kBACA,aAAY;AAAA,kBACZ,WAAW;AAAA;AAAA,cACb;AAAA,eACF;AAAA,aACF,IACE;AAAA,WACN;AAAA,QAEA,qBAAC,SAAI,WAAU,kBACZ;AAAA,kBAAQ,oBAAC,OAAE,WAAU,2BAA2B,iBAAM,IAAO;AAAA,UAC9D,oBAAC,UAAO,MAAK,UAAS,MAAK,MAAK,UAAU,CAAC,WAAW,MAAM,WAAU,mBAAkB,iBAExF;AAAA,WACF;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,2BAAQ;;;AC/PR,IAAM,mBAA2C;AAAA,EACtD,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AACR;;;ACHA,SAAS,WAAW,iBAAiB,QAAQ,YAAAC,iBAAgB;AAgEnD,qBAAAC,WAEE,OAAAC,MAFF,QAAAC,aAAA;AA5CV,SAAS,sBAAsB,EAAE,KAAK,GAAqB;AACzD,QAAM,aAAa,OAA6B,IAAI;AACpD,QAAM,CAAC,UAAU,WAAW,IAAIC,UAAS,KAAK;AAC9C,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,KAAK;AAChD,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,EAAE;AAE7C,kBAAgB,MAAM;AACpB,gBAAY,KAAK;AACjB,iBAAa,EAAE;AAAA,EACjB,GAAG,CAAC,IAAI,CAAC;AAET,kBAAgB,MAAM;AACpB,UAAM,KAAK,WAAW;AACtB,QAAI,CAAC,GAAI;AAET,QAAI,CAAC,UAAU;AACb,mBAAa,EAAE;AACf,mBAAa,GAAG,cAAc,GAAG,cAAc,CAAC;AAChD;AAAA,IACF;AAGA,iBAAa,EAAE;AACf,UAAM,QAAQ,sBAAsB,MAAM;AACxC,mBAAa,GAAG,YAAY;AAAA,IAC9B,CAAC;AACD,WAAO,MAAM,qBAAqB,KAAK;AAAA,EACzC,GAAG,CAAC,MAAM,QAAQ,CAAC;AAEnB,MAAI,CAAC,KAAM,QAAO;AAElB,SACE,gBAAAD,MAAC,SAAI,WAAU,oBACb;AAAA,oBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,OAAO,EAAE,UAAU;AAAA,QACnB,WAAW;AAAA,UACT;AAAA,UACA,CAAC,YAAY;AAAA,UACb,CAAC,YAAY,aAAa;AAAA,QAC5B;AAAA,QAEC;AAAA;AAAA,UACA,YAAY,YACX,gBAAAA,MAAAF,WAAA,EACG;AAAA;AAAA,YACD,gBAAAC;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,iBAAa;AAAA,gBACb,SAAS,MAAM,YAAY,KAAK;AAAA,gBACjC;AAAA;AAAA,YAED;AAAA,aACF,IACE;AAAA;AAAA;AAAA,IACN;AAAA,IACC,CAAC,YAAY,YACZ,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,iBAAe;AAAA,QACf,SAAS,MAAM,YAAY,IAAI;AAAA,QAE/B;AAAA,0BAAAD,KAAC,UAAK,eAAW,MAAC,WAAU,uBAAsB,oBAElD;AAAA,UACA,gBAAAA,KAAC,UAAK,WAAU,QAAO,uBAAS;AAAA;AAAA;AAAA,IAClC,IACE;AAAA,KACN;AAEJ;AAEA,IAAM,mBAAmB,CAAC;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AACT,MAA6B;AAC3B,QAAM,EAAE,iBAAiB,IAAI,iBAAiB;AAC9C,QAAM,EAAE,iBAAiB,eAAe,IAAI,WAAW;AACvD,QAAM,CAAC,OAAO,QAAQ,IAAIE,UAAqB,CAAC,CAAC;AACjD,QAAM,CAAC,cAAc,eAAe,IAAIA,UAAS,IAAI;AACrD,QAAM,CAAC,YAAY,aAAa,IAAIA,UAAwB,IAAI;AAChE,QAAM,CAAC,qBAAqB,sBAAsB,IAAIA,UAAS,KAAK;AAEpE,YAAU,MAAM;AACd,QAAI,YAAY;AAChB,aAAS,CAAC,CAAC;AACX,kBAAc,IAAI;AAClB,oBAAgB,IAAI;AAEpB,SAAK,iBACF,sBAAsB,EAAE,IAAI,UAAU,GAAG,CAAC,EAC1C,KAAK,YAAU;AACd,UAAI,CAAC,UAAW,UAAS,MAAM;AAAA,IACjC,CAAC,EACA,MAAM,CAAC,QAAiB;AACvB,UAAI,CAAC,WAAW;AACd,sBAAc,gBAAgB,KAAK,gCAAgC,CAAC;AAAA,MACtE;AAAA,IACF,CAAC,EACA,QAAQ,MAAM;AACb,UAAI,CAAC,UAAW,iBAAgB,KAAK;AAAA,IACvC,CAAC;AAEH,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,UAAU,eAAe,UAAU,IAAI,gBAAgB,CAAC;AAE5D,QAAM,6BAA6B,YAAY;AAC7C,2BAAuB,IAAI;AAC3B,kBAAc,IAAI;AAElB,QAAI;AACF,YAAM,qBAAqB,MAAM,iBAAiB,aAAa,EAAE,IAAI,UAAU,GAAG,CAAC;AACnF,2BAAqB,kBAAkB;AAAA,IACzC,SAAS,KAAc;AACrB,oBAAc,gBAAgB,KAAK,qCAAqC,CAAC;AAAA,IAC3E,UAAE;AACA,6BAAuB,KAAK;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,aAAa,kBAAkB;AAErC,SACE,gBAAAD,MAAC,SAAI,WAAU,wCACb;AAAA,oBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS;AAAA,QACT,WAAU;AAAA,QAEV;AAAA,0BAAAD,KAAC,QAAK,MAAK,gBAAe,WAAU,YAAW;AAAA,UAAE;AAAA;AAAA;AAAA,IAEnD;AAAA,IAEA,gBAAAC,MAAC,SAAI,WAAU,6CACb;AAAA,sBAAAA,MAAC,YAAO,WAAU,0BAChB;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,eAAW;AAAA,YAEX,0BAAAA,KAAC,QAAK,MAAK,cAAa,WAAU,4BAA2B;AAAA;AAAA,QAC/D;AAAA,QAEA,gBAAAC,MAAC,SAAI,WAAU,kBACb;AAAA,0BAAAD,KAAC,QAAG,WAAU,2CAA2C,oBAAU,MAAK;AAAA,UACxE,gBAAAC,MAAC,SAAI,WAAU,8DACb;AAAA,4BAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAW;AAAA,kBACT;AAAA,kBACA,UAAU,gBAAgB,oBAAoB;AAAA,gBAChD;AAAA,gBAEA;AAAA,kCAAAD;AAAA,oBAAC;AAAA;AAAA,sBACC,WAAW;AAAA,wBACT;AAAA,wBACA,UAAU,gBAAgB,kBAAkB;AAAA,sBAC9C;AAAA;AAAA,kBACD;AAAA,kBACA,UAAU,gBAAgB,cAAc;AAAA;AAAA;AAAA,YAC3C;AAAA,YACA,gBAAAC,MAAC,UAAK,WAAU,uBAAsB;AAAA;AAAA,cAAG,UAAU;AAAA,eAAY;AAAA,aACjE;AAAA,UACA,gBAAAD,KAAC,UAAK,WAAU,0IACb,2BAAiB,UAAU,KAAK,IAAI,KAAK,iBAAiB,MAC7D;AAAA,WACF;AAAA,QAEC,UAAU,KAAK,SAAS,SAAS,CAAC,UAAU,gBAC3C,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,MAAK;AAAA,YACL,UAAU,QAAQ;AAAA,YAClB,SAAS,MAAM;AACb,mBAAK,gBAAgB,UAAU,IAAI,eAAa;AAC9C,oBAAI,UAAW,MAAK,2BAA2B;AAAA,cACjD,CAAC;AAAA,YACH;AAAA,YAEC,uBAAa,qBAAgB;AAAA;AAAA,QAChC,IACE,UAAU,KAAK,SAAS,SAAS,CAAC,UAAU,eAC9C,gBAAAA,KAAC,UAAO,SAAQ,WAAU,MAAK,MAAK,MAAK,UAAS,UAAU,MAAM,SAAS,cAAc,wBAEzF,IACE;AAAA,SACN;AAAA,MAEA,gBAAAA,KAAC,aAAQ,WAAU,QAAO,mBAAgB,2BACvC,yBACC,gBAAAA,KAAC,SAAI,WAAU,6FAA4F,iCAE3G,IACE,aACF,gBAAAC,MAAC,SAAI,WAAU,mGACZ;AAAA;AAAA,QACA,UAAU,KAAK,SAAS,SAAS,CAAC,UAAU,iBAC3C,gBAAAD,KAAC,SAAI,WAAU,kBAAiB,wEAA0D;AAAA,SAE9F,IACE,MAAM,SAAS,IACjB,gBAAAC,MAAAF,WAAA,EACE;AAAA,wBAAAE,MAAC,QAAG,IAAG,2BAA0B,WAAU,yDAAwD;AAAA;AAAA,UAC3F,gBAAAA,MAAC,UAAK,WAAU,mCAAkC;AAAA;AAAA,YAAG,MAAM;AAAA,aAAO;AAAA,WAC1E;AAAA,QACA,gBAAAD,KAAC,SAAI,WAAU,8DACZ,gBAAM,IAAI,UACT,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC,WAAU;AAAA,YAEV,0BAAAC,MAAC,SAAI,WAAU,kBACb;AAAA,8BAAAD,KAAC,QAAG,WAAU,yCAAyC,eAAK,MAAK;AAAA,cACjE,gBAAAA,KAAC,yBAAsB,MAAM,KAAK,aAAa;AAAA,eACjD;AAAA;AAAA,UANK,KAAK;AAAA,QAOZ,CACD,GACH;AAAA,SACF,IAEA,gBAAAA,KAAC,SAAI,WAAU,6FAA4F,mDAE3G,GAEJ;AAAA,OACF;AAAA,KACF;AAEJ;AAEA,IAAO,2BAAQ;;;AHTT,qBAAAG,WAMM,OAAAC,MAMJ,QAAAC,aAZF;AA9NN,IAAM,oBAAoB,MAAM;AAC9B,QAAM,EAAE,iBAAiB,IAAI,iBAAiB;AAC9C,QAAM,UAAU,mBAAmB;AAEnC,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAS,EAAE;AACrC,QAAM,CAAC,YAAY,aAAa,IAAIA,UAA0B;AAAA,IAC5D,SAAS,CAAC;AAAA,IACV,gBAAgB,oBAAI,IAAI;AAAA,EAC1B,CAAC;AACD,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,IAAI;AAC3C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAwB,IAAI;AACtD,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAwB,IAAI;AAC9D,QAAM,CAAC,MAAM,OAAO,IAAIA,UAAS,KAAK;AAEtC,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAkC,CAAC,CAAC;AAClE,QAAM,CAAC,sBAAsB,uBAAuB,IAAIA,UAAS,KAAK;AACtE,QAAM,CAAC,sBAAsB,uBAAuB,IAAIA,UAAuC,IAAI;AACnG,QAAM,CAAC,mBAAmB,oBAAoB,IAAIA,UAA+B,IAAI;AACrF,QAAM,CAAC,QAAQ,SAAS,IAAIA,UAAS,EAAE;AAEvC,QAAM,mBAAmB,QAAQ,MAAM;AACrC,YAAQ,WAAW,CAAC,GAAG;AAAA,MACrB,CAAC,KAAK,UAAU;AACd,YAAI,MAAM,IAAI,IAAI,MAAM,QAAQ;AAChC,eAAO;AAAA,MACT;AAAA,MACA,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,UAAU,YAAY,YAAY;AACtC,eAAW,IAAI;AACf,aAAS,IAAI;AACb,QAAI;AACF,YAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,QAC5C,iBAAiB,eAAe;AAAA,QAChC,iBAAiB,oBAAoB;AAAA,MACvC,CAAC;AACD,iBAAW,SAAS;AACpB,YAAM,aAAa,UAAU,CAAC;AAC9B,YAAM,UAAU,IAAI,IAAI,WAAW,IAAI,eAAa,UAAU,EAAE,CAAC;AACjE,YAAM,UAA+B;AAAA,QACnC,GAAG,WAAW,IAAuB,gBAAc,EAAE,WAAW,cAAc,KAAK,EAAE;AAAA,QACrF,GAAG,UACA,OAAO,eAAa,CAAC,QAAQ,IAAI,UAAU,EAAE,CAAC,EAC9C,IAAuB,gBAAc,EAAE,WAAW,cAAc,MAAM,EAAE;AAAA,MAC7E;AACA,oBAAc;AAAA,QACZ;AAAA,QACA,gBAAgB,IAAI;AAAA,UAClB,QAAQ,IAAI,UAAQ,CAAC,KAAK,UAAU,IAAI,KAAK,eAAe,KAAK,UAAU,gBAAgB,KAAK,CAAC;AAAA,QACnG;AAAA,MACF,CAAC;AACD,2BAAqB,aAAY,UAAW,OAAO,KAAK,UAAQ,KAAK,OAAO,QAAQ,EAAE,KAAK,OAAQ,IAAK;AAAA,IAC1G,SAAS,KAAK;AACZ,eAAS,gBAAgB,KAAK,2BAA2B,CAAC;AAAA,IAC5D,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,gBAAgB,CAAC;AAErB,EAAAC,WAAU,MAAM;AACd,SAAK,QAAQ;AAAA,EACf,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,kBAAkB,MAAM,KAAK,EAAE,YAAY;AAEjD,QAAM,qBAAqB,QAAQ,MAAM;AACvC,QAAI,CAAC,gBAAiB,QAAO,WAAW;AACxC,WAAO,WAAW,QAAQ,OAAO,CAAC,EAAE,UAAU,MAAM;AAClD,aACE,UAAU,KAAK,YAAY,EAAE,SAAS,eAAe,MACpD,UAAU,aAAa,YAAY,EAAE,SAAS,eAAe,KAAK,UACnE,UAAU,IAAI,YAAY,EAAE,SAAS,eAAe;AAAA,IAExD,CAAC;AAAA,EACH,GAAG,CAAC,WAAW,SAAS,eAAe,CAAC;AAExC,QAAM,oBAAoB,QAAQ,MAAM;AACtC,UAAM,SAA0B,CAAC;AACjC,eAAW,QAAQ,oBAAoB;AACrC,UAAI,KAAK,cAAc;AACrB,cAAM,gBAAgB,WAAW,eAAe,IAAI,KAAK,UAAU,EAAE,KAAK,KAAK,UAAU;AACzF,eAAO;AAAA,UACL,kBAAkB,KAAK,UAAU,gBAAgB,KAAK,YAAY,EAAE,GAAG,KAAK,WAAW,cAAc;AAAA,QACvG;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,WAAW,gBAAgB,kBAAkB,CAAC;AAElD,QAAM,sBAAsB,QAAQ,MAAM;AACxC,UAAM,SAAkC,CAAC;AACzC,eAAW,QAAQ,oBAAoB;AACrC,UAAI,CAAC,KAAK,aAAc,QAAO,KAAK,KAAK,SAAS;AAAA,IACpD;AACA,WAAO;AAAA,EACT,GAAG,CAAC,kBAAkB,CAAC;AAEvB,QAAM,cAAc,OAAO,IAAyB,mBAAmB,aAAa;AAClF,YAAQ,IAAI;AACZ,aAAS,IAAI;AACb,QAAI;AACF,YAAM,GAAG;AACT,YAAM,QAAQ;AAAA,IAChB,SAAS,KAAK;AACZ,uBAAiB,gBAAgB,KAAK,gBAAgB,CAAC;AACvD,YAAM;AAAA,IACR,UAAE;AACA,cAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAEA,QAAM,mBAAmB,MAAM;AAC7B,4BAAwB,IAAI;AAC5B,cAAU,EAAE;AACZ,iBAAa,IAAI;AAAA,EACnB;AAEA,QAAM,oBAAoB,OAAO,OAA8B,iBAAiC;AAC9F,UAAM,OACJ,iBACC,MAAM,KAAK,SAAS,WACjB;AAAA,MACE,MAAM;AAAA,MACN,GAAI,MAAM,KAAK,aAAa,EAAE,YAAY,MAAM,KAAK,WAAW,IAAI,CAAC;AAAA,IACvE,IACA,MAAM,KAAK,SAAS,QAClB,EAAE,MAAM,MAAM,IACd,EAAE,MAAM,OAAO;AACvB,UAAM,iBAAiB,gBAAgB;AAAA,MACrC,MAAM,MAAM;AAAA,MACZ,aAAa,MAAM,eAAe,MAAM;AAAA,MACxC,KAAK,MAAM;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,gBAAgB,CAAC,UAAiC;AACtD,QAAI,MAAM,KAAK,SAAS,UAAU;AAChC,gBAAU,EAAE;AACZ,mBAAa,IAAI;AACjB,8BAAwB,KAAK;AAC7B;AAAA,IACF;AAEA,SAAK,YAAY,YAAY;AAC3B,YAAM,kBAAkB,KAAK;AAAA,IAC/B,CAAC,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACnB;AAEA,QAAM,qBAAqB,CAAC,UAAsC;AAChE,UAAM,eAAe;AACrB,QAAI,CAAC,wBAAwB,CAAC,OAAO,KAAK,EAAG;AAE7C,UAAM,QAAQ;AACd,iBAAa,IAAI;AACjB,SAAK,YAAY,YAAY;AAC3B,YAAM,OAAsB;AAAA,QAC1B,MAAM;AAAA,QACN,QAAQ,OAAO,KAAK;AAAA,QACpB,GAAI,MAAM,KAAK,SAAS,YAAY,MAAM,KAAK,aAAa,EAAE,YAAY,MAAM,KAAK,WAAW,IAAI,CAAC;AAAA,MACvG;AACA,YAAM,WAAW,WAAW,QAAQ,KAAK,CAAC,EAAE,UAAU,MAAM,UAAU,OAAO,MAAM,EAAE;AACrF,YAAM,oBAAoB,UAAU,eAAe,SAAS,YAAY;AACxE,UAAI,mBAAmB;AACrB,cAAM,iBAAiB,gBAAgB;AAAA,UACrC,IAAI,kBAAkB;AAAA,UACtB,MAAM,kBAAkB;AAAA,UACxB,aAAa,kBAAkB;AAAA,UAC/B,KAAK,kBAAkB;AAAA,UACvB;AAAA,QACF,CAAC;AAAA,MACH,OAAO;AACL,cAAM,kBAAkB,OAAO,IAAI;AAAA,MACrC;AACA,uBAAiB;AACjB,iBAAW,MAAM;AACf,iBAAS,YAAY;AAAA,UACnB,OAAO,GAAG,MAAM,IAAI,IAAI,oBAAoB,YAAY,WAAW;AAAA,QACrE,CAAC;AAAA,MACH,GAAG,GAAG;AAAA,IACR,GAAG,YAAY,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACjC;AAEA,QAAM,qBAAqB,OAAO,UAA6B;AAC7D,iBAAa,IAAI;AACjB,UAAM,YAAY,YAAY;AAC5B,YAAM,iBAAiB,gBAAgB,EAAE,GAAG,MAAM,CAAC;AAAA,IACrD,GAAG,YAAY;AACf,eAAW,MAAM;AACf,eAAS,YAAY,EAAE,OAAO,GAAG,MAAM,IAAI,SAAS,CAAC;AAAA,IACvD,GAAG,CAAC;AAAA,EACN;AAEA,QAAM,mBAAmB,CAAC,cAA6B;AACrD,SAAK,YAAY,YAAY;AAC3B,YAAM,iBAAiB,oBAAoB,EAAE,IAAI,UAAU,GAAG,CAAC;AAC/D,2BAAqB,IAAI;AAAA,IAC3B,CAAC,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACnB;AAEA,QAAM,2BAA2B,CAAC,uBAAsC;AACtE,yBAAqB,aAAY,SAAS,OAAO,mBAAmB,KAAK,qBAAqB,OAAQ;AACtG,kBAAc,aAAW;AACvB,YAAM,iBAAiB,IAAI,IAAI,QAAQ,cAAc;AACrD,qBAAe,IAAI,mBAAmB,IAAI,mBAAmB,aAAa;AAE1E,aAAO;AAAA,QACL,SAAS,QAAQ,QAAQ;AAAA,UAAI,UAC3B,KAAK,gBAAgB,KAAK,UAAU,OAAO,mBAAmB,KAC1D,EAAE,WAAW,oBAAoB,cAAc,KAAK,IACpD;AAAA,QACN;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,kBAAkB,CAAC,WAA0B,gBAAyB;AAC1E,UAAM,UAAU,iBAAiB,UAAU,IAAI;AAC/C,UAAM,UACJ,gBAAAF,MAAAF,WAAA,EACE;AAAA,sBAAAC;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,eAAW;AAAA,UAEV,oBACC,gBAAAA,KAAC,eAAY,KAAK,SAAS,KAAK,UAAU,MAAM,WAAU,YAAW,IAErE,gBAAAA,KAAC,QAAK,MAAK,cAAa,WAAU,8BAA6B;AAAA;AAAA,MAEnE;AAAA,MAEA,gBAAAC,MAAC,SAAI,WAAU,kBACb;AAAA,wBAAAD,KAAC,QAAG,WAAU,kDAAkD,oBAAU,MAAK;AAAA,QAC/E,gBAAAA,KAAC,OAAE,WAAU,+DAA+D,oBAAU,aAAY;AAAA,SACpG;AAAA,OACF;AAGF,UAAM,eAAe;AAErB,QAAI,aAAa;AACf,aACE,gBAAAC;AAAA,QAAC;AAAA;AAAA,UAEC,WAAW,GAAG,YAAY;AAAA,UAC1B,SAAS,MAAM;AACb,iCAAqB,SAAS;AAAA,UAChC;AAAA,UAEA;AAAA,4BAAAD,KAAC,SAAI,WAAU,0CAA0C,mBAAQ;AAAA,YAEjE,gBAAAC,MAAC,SAAI,WAAU,2BACb;AAAA,8BAAAD,KAAC,SAAI,WAAU,2BACb,0BAAAC;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAW;AAAA,oBACT;AAAA,oBACA,UAAU,gBAAgB,oBAAoB;AAAA,kBAChD;AAAA,kBAEA;AAAA,oCAAAD;AAAA,sBAAC;AAAA;AAAA,wBACC,WAAW;AAAA,0BACT;AAAA,0BACA,UAAU,gBAAgB,kBAAkB;AAAA,wBAC9C;AAAA;AAAA,oBACD;AAAA,oBACA,UAAU,gBAAgB,cAAc;AAAA;AAAA;AAAA,cAC3C,GACF;AAAA,cACC,UAAU,KAAK,SAAS,WACvB,gBAAAC;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,MAAK;AAAA,kBACL,UAAU;AAAA,kBACV,SAAS,WAAS;AAChB,0BAAM,gBAAgB;AACtB,8BAAU,EAAE;AACZ,4CAAwB,SAAS;AAAA,kBACnC;AAAA,kBAEA;AAAA,oCAAAD,KAAC,QAAK,MAAK,UAAS,WAAU,UAAS;AAAA,oBAAE;AAAA;AAAA;AAAA,cAE3C,IACE;AAAA,cACJ,gBAAAA,KAAC,QAAK,MAAK,iBAAgB,WAAU,UAAS;AAAA,eAChD;AAAA;AAAA;AAAA,QA1CK,UAAU;AAAA,MA2CjB;AAAA,IAEJ;AAEA,WACE,gBAAAA,KAAC,aAA2B,WAAW,cACpC,qBADW,UAAU,EAExB;AAAA,EAEJ;AAEA,QAAM,qBAAqB,CAAC,UAAiC;AAC3D,UAAM,UAAU,iBAAiB,MAAM,IAAI;AAC3C,WACE,gBAAAC;AAAA,MAAC;AAAA;AAAA,QAEC,WAAU;AAAA,QAEV;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,eAAW;AAAA,cAEV,oBACC,gBAAAA,KAAC,eAAY,KAAK,SAAS,KAAK,MAAM,MAAM,WAAU,YAAW,IAEjE,gBAAAA,KAAC,QAAK,MAAK,cAAa,WAAU,8BAA6B;AAAA;AAAA,UAEnE;AAAA,UAEA,gBAAAC,MAAC,SAAI,WAAU,kBACb;AAAA,4BAAAD,KAAC,QAAG,WAAU,kDAAkD,gBAAM,MAAK;AAAA,YAC3E,gBAAAA,KAAC,OAAE,WAAU,+DACV,gBAAM,eAAe,MAAM,KAC9B;AAAA,aACF;AAAA,UAEA,gBAAAC,MAAC,SAAI,WAAU,oCACb;AAAA,4BAAAD,KAAC,UAAK,WAAU,gDACb,2BAAiB,MAAM,KAAK,IAAI,KAAK,iBAAiB,MACzD;AAAA,YACA,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,MAAK;AAAA,gBACL,UAAU;AAAA,gBACV,SAAS,MAAM;AACb,gCAAc,KAAK;AAAA,gBACrB;AAAA,gBAEC,gBAAM,KAAK,SAAS,QAAQ,QAAQ;AAAA;AAAA,YACvC;AAAA,aACF;AAAA;AAAA;AAAA,MApCK,MAAM;AAAA,IAqCb;AAAA,EAEJ;AAEA,QAAM,iBAAiB,QAAQ,MAAM;AACnC,WACE,yBAAyB,QACzB,WAAW,QAAQ;AAAA,MACjB,CAAC,SAA4B,KAAK,gBAAgB,KAAK,UAAU,OAAO,qBAAqB;AAAA,IAC/F;AAAA,EAEJ,GAAG,CAAC,sBAAsB,WAAW,OAAO,CAAC;AAE7C,MAAI,mBAAmB;AACrB,WACE,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,QACX;AAAA,QACA,QAAQ,MAAM;AACZ,+BAAqB,IAAI;AAAA,QAC3B;AAAA,QACA,sBAAsB;AAAA,QACtB,cAAc,MAAM;AAClB,2BAAiB,iBAAiB;AAAA,QACpC;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,QAAM,aAAa,kBAAkB,SAAS,KAAK,oBAAoB,SAAS;AAEhF,SACE,gBAAAC,MAAAF,WAAA,EACE;AAAA,oBAAAC,KAAC,QAAG,WAAU,0DAAyD,wBAAU;AAAA,IACjF,gBAAAA,KAAC,OAAE,WAAU,oCAAmC,gDAAkC;AAAA,IAEjF,QACC,gBAAAA,KAAC,OAAE,WAAU,kGACV,iBACH,IACE;AAAA,IAEJ,gBAAAA,KAAC,SAAI,WAAU,iCACb,0BAAAC,MAAC,SAAI,WAAU,8BACb;AAAA,sBAAAA,MAAC,SAAI,WAAU,cACb;AAAA,wBAAAD,KAAC,SAAI,WAAU,UACb,0BAAAA,KAAC,uBAAY,OAAc,UAAoB,aAAY,qBAAoB,GACjF;AAAA,QACA,gBAAAC;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,SAAS,MAAM;AACb,2BAAa,IAAI;AACjB,sCAAwB,IAAI;AAAA,YAC9B;AAAA,YAEA;AAAA,8BAAAD,KAAC,QAAK,MAAK,QAAO,MAAK,QAAO,WAAU,QAAO;AAAA,cAAE;AAAA;AAAA;AAAA,QAEnD;AAAA,SACF;AAAA,MAEA,gBAAAC,MAAC,SAAI,WAAU,mDACZ;AAAA,kBAAU,gBAAAD,KAAC,OAAE,WAAU,gDAA+C,2BAAQ,IAAO;AAAA,QAErF,CAAC,WAAW,kBAAkB,SAAS,IACtC,gBAAAC,MAAC,aAAQ,mBAAgB,gCACvB;AAAA,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,IAAG;AAAA,cACH,WAAU;AAAA,cACX;AAAA;AAAA,gBACe,kBAAkB;AAAA;AAAA;AAAA,UAClC;AAAA,UACA,gBAAAD,KAAC,SAAI,WAAU,8DACZ,4BAAkB,IAAI,eAAa,gBAAgB,WAAW,IAAI,CAAC,GACtE;AAAA,WACF,IACE;AAAA,QAEH,CAAC,WAAW,oBAAoB,SAAS,IACxC,gBAAAC,MAAC,aAAQ,mBAAgB,gCACvB;AAAA,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,IAAG;AAAA,cACH,WAAU;AAAA,cACX;AAAA;AAAA,gBACc,oBAAoB;AAAA;AAAA;AAAA,UACnC;AAAA,UACA,gBAAAD,KAAC,SAAI,WAAU,8DACZ,8BAAoB,IAAI,WAAS,mBAAmB,KAAK,CAAC,GAC7D;AAAA,WACF,IACE;AAAA,QAEH,CAAC,WAAW,CAAC,aACZ,gBAAAA,KAAC,SAAI,WAAU,qIACZ,gBAAM,KAAK,IAAI,6BAAwB,MAAM,KAAK,CAAC,YAAO,sBAC7D,IACE;AAAA,SACN;AAAA,MAEA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,yBAAyB;AAAA,UAC/B,cAAc,UAAQ;AACpB,gBAAI,CAAC,KAAM,kBAAiB;AAAA,UAC9B;AAAA,UACA,OAAO,GAAG,iBAAiB,oBAAoB,SAAS,IAAI,sBAAsB,QAAQ,WAAW;AAAA,UACrG,aAAa,sBAAsB;AAAA,UACnC,cAAY;AAAA,UACZ,WAAU;AAAA,UAEV,0BAAAC,MAAC,UAAK,UAAU,oBACd;AAAA,4BAAAA,MAAC,SAAI,WAAU,uBACb;AAAA,8BAAAA,MAAC,SAAI,WAAU,2BACb;AAAA,gCAAAD;AAAA,kBAAC;AAAA;AAAA,oBACC,WAAU;AAAA,oBACV,eAAW;AAAA,oBAEX,0BAAAA,KAAC,QAAK,MAAK,cAAa,WAAU,4BAA2B;AAAA;AAAA,gBAC/D;AAAA,gBACA,gBAAAC,MAAC,SAAI,WAAU,WACb;AAAA,kCAAAD,KAAC,OAAE,WAAU,iCAAiC,gCAAsB,MAAK;AAAA,kBACzE,gBAAAA,KAAC,OAAE,WAAU,wCAAwC,gCAAsB,aAAY;AAAA,mBACzF;AAAA,iBACF;AAAA,cAEA,gBAAAC,MAAC,SACC;AAAA,gCAAAD;AAAA,kBAAC;AAAA;AAAA,oBACC,SAAQ;AAAA,oBACR,WAAU;AAAA,oBACX;AAAA;AAAA,gBAED;AAAA,gBACA,gBAAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,IAAG;AAAA,oBACH,MAAK;AAAA,oBACL,OAAO;AAAA,oBACP,UAAU,WAAS;AACjB,gCAAU,MAAM,OAAO,KAAK;AAAA,oBAC9B;AAAA,oBACA,aAAa,wBAAwB,sBAAsB,QAAQ,cAAc;AAAA,oBACjF,WAAS;AAAA,oBACT,UAAQ;AAAA,oBACR,WAAW,cAAc,MAAM;AAAA;AAAA,gBACjC;AAAA,iBACF;AAAA,cACC,YAAY,gBAAAA,KAAC,OAAE,WAAU,2BAA2B,qBAAU,IAAO;AAAA,eACxE;AAAA,YAEA,gBAAAC,MAAC,YAAO,WAAU,2DAChB;AAAA,8BAAAD,KAAC,UAAO,SAAQ,SAAQ,MAAK,UAAS,SAAS,kBAAkB,UAAU,MAAM,oBAEjF;AAAA,cACA,gBAAAA,KAAC,UAAO,MAAK,UAAS,UAAU,CAAC,OAAO,KAAK,KAAK,MAC/C,2BAAiB,gBAAgB,WACpC;AAAA,eACF;AAAA,aACF;AAAA;AAAA,MACF;AAAA,MAEA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAM;AAAA,UACN,cAAc,UAAQ;AACpB,oCAAwB,IAAI;AAC5B,gBAAI,CAAC,KAAM,cAAa,IAAI;AAAA,UAC9B;AAAA,UACA,OAAO;AAAA,UACP;AAAA,UACA,OAAO;AAAA;AAAA,MACT;AAAA,OACF,GACF;AAAA,KACF;AAEJ;AAEA,IAAO,4BAAQ;","names":["useEffect","useState","useState","Fragment","jsx","jsxs","useState","Fragment","jsx","jsxs","useState","useEffect"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/layouts/DrawerLayout.tsx"],"sourcesContent":["'use client';\n\nimport { lazy, Suspense, useRef } from 'react';\n\nimport { useAui } from '../assistant-ui.js';\nimport { NamedAgentHeaderLabel } from '../atoms/NamedAgentHeaderLabel.js';\nimport { PageHeader } from '../atoms/PageHeader.js';\nimport { ShellActions } from '../atoms/ShellActions.js';\nimport { auiButtonClass } from '../atoms/lib/buttonClasses.js';\nimport { cn } from '../atoms/lib/cn.js';\nimport { useIsMobile } from '../atoms/lib/useIsMobile.js';\nimport { Spinner } from '../atoms/primitives/Spinner.js';\nimport { AgentConfigDrawerContainer } from '../containers/AgentConfigDrawerContainer.js';\nimport { Thread } from '../containers/Thread.js';\nimport { Icon } from '../icons/Icon.js';\nimport { shellIsCreateAgent, useOptionalShellMode } from '../server/ShellModeContext.js';\nimport { useSlot } from '../theme/SlotsProvider.js';\n\nconst TruefoundrySettingsBuilder = lazy(() => import('../containers/SettingsBuilder/index.js'));\nconst SchedulesPage = lazy(() =>\n import('../atoms/schedules/SchedulesPage.js').then(m => ({ default: m.SchedulesPage })),\n);\n\nexport function DrawerLayout({ className }: { className?: string }) {\n const aui = useAui();\n const shell = useOptionalShellMode();\n const isMobile = useIsMobile();\n const ClearChatButton = useSlot('ClearChatButton');\n const AgentDetailsPage = useSlot('AgentDetailsPage');\n const AgentsLibrary = useSlot('AgentsLibrary');\n const SessionsPage = useSlot('SessionsPage');\n const SaveAgentButton = useSlot('SaveAgentButton');\n const SelectAgentEmptyState = useSlot('SelectAgentEmptyState');\n const mainRef = useRef<HTMLDivElement>(null);\n const isIdle = shell?.mode.status === 'idle';\n const settingsOpen = shell?.settingsOpen === true;\n const libraryOpen = shell?.libraryOpen === true;\n const sessionsOpen = shell?.sessionsOpen === true;\n const schedulesOpen = shell?.schedulesOpen === true;\n const overlayOpen = settingsOpen || libraryOpen || sessionsOpen || schedulesOpen;\n const showAgentConfig =\n shell != null && shellIsCreateAgent(shell.mode) && !overlayOpen && (!isMobile || shell.agentConfigOpen);\n const showNewActions = shell?.isNewChatEnabled !== false;\n\n const handleNewChat = () => {\n shell?.setLibraryOpen(false);\n shell?.setSessionsOpen(false);\n if (shell?.isComposerEnabled) {\n shell.openDraft();\n return;\n }\n shell?.setSettingsOpen(false);\n shell?.setSchedulesOpen(false);\n void Promise.resolve(aui.threads().switchToNewThread()).catch(() => undefined);\n };\n\n const handleNewAgent = () => {\n shell?.setLibraryOpen(false);\n shell?.setSessionsOpen(false);\n if (shell?.isComposerEnabled) {\n shell.openAgentBuilder();\n }\n };\n\n return (\n <div className={cn('relative flex h-full min-h-0 w-full bg-primary-bg', className)}>\n {showAgentConfig ? (\n <aside\n role=\"dialog\"\n aria-label=\"Agent Config\"\n className=\"absolute inset-y-0 left-0 z-20 w-full max-w-sm border-r border-border shadow-xl md:static md:z-auto md:w-88 md:max-w-none md:shrink-0 md:shadow-none\"\n >\n <AgentConfigDrawerContainer showClose={isMobile} />\n </aside>\n ) : null}\n\n <div className=\"flex min-h-0 min-w-0 flex-1 flex-col\">\n {/* Keep ShellActions mounted across Settings open/close so host action-slot state persists. */}\n <PageHeader\n className=\"bg-topbar-bg\"\n title={\n !overlayOpen ? (\n <NamedAgentHeaderLabel />\n ) : libraryOpen || schedulesOpen ? (\n <button\n type=\"button\"\n className={auiButtonClass({ variant: 'ghost', size: 'sm' })}\n onClick={() => {\n shell?.setLibraryOpen(false);\n shell?.setSchedulesOpen(false);\n }}\n >\n <Icon name=\"arrow-left\" />\n Back to chat\n </button>\n ) : null\n }\n end={\n <>\n {!overlayOpen ? (\n <>\n <ClearChatButton />\n <SaveAgentButton />\n </>\n ) : null}\n <ShellActions key=\"shell-actions\" />\n {!overlayOpen ? (\n <>\n {showNewActions ? (\n <button\n type=\"button\"\n aria-label=\"New Chat\"\n title=\"New Chat\"\n className={auiButtonClass({ variant: 'ghost', size: 'icon' })}\n onClick={handleNewChat}\n >\n <Icon name=\"square-pen\" />\n </button>\n ) : null}\n {showNewActions && shell?.isComposerEnabled ? (\n <button\n type=\"button\"\n aria-label=\"New Agent\"\n title=\"New Agent\"\n className={auiButtonClass({ variant: 'ghost', size: 'icon' })}\n onClick={handleNewAgent}\n >\n <Icon name=\"agent-2\" />\n </button>\n ) : null}\n </>\n ) : null}\n </>\n }\n />\n <div ref={mainRef} className=\"min-h-0 min-w-0 flex-1\">\n {settingsOpen ? (\n <Suspense\n fallback={\n <div\n className=\"flex h-full items-center justify-center\"\n role=\"status\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n >\n <Spinner size={28} className=\"text-text-primary\" />\n <span className=\"sr-only\">Loading</span>\n </div>\n }\n >\n <TruefoundrySettingsBuilder />\n </Suspense>\n ) : sessionsOpen ? (\n <SessionsPage />\n ) : libraryOpen && shell?.libraryAgentId != null ? (\n <AgentDetailsPage key={shell.libraryAgentId} agentId={shell.libraryAgentId} />\n ) : libraryOpen ? (\n <AgentsLibrary />\n ) : schedulesOpen ? (\n <Suspense\n fallback={\n <div\n className=\"flex h-full items-center justify-center\"\n role=\"status\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n >\n <Spinner size={28} className=\"text-text-primary\" />\n <span className=\"sr-only\">Loading</span>\n </div>\n }\n >\n <SchedulesPage />\n </Suspense>\n ) : isIdle ? (\n <SelectAgentEmptyState />\n ) : (\n <Thread />\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/containers/SettingsBuilder/ModelSettings.tsx","../src/containers/SettingsBuilder/ConfigureModelProviderForm.tsx","../src/containers/SettingsBuilder/CustomModelProviderForm.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport { Button } from '@/atoms/primitives/Button.js';\nimport { CatalogLogo } from '@/atoms/primitives/CatalogLogo.js';\nimport SearchInput from '@/atoms/primitives/SearchInput.js';\nimport ConfigureModelProviderForm, {\n type ModelProviderKeyDraft,\n} from '@/containers/SettingsBuilder/ConfigureModelProviderForm.js';\nimport CustomModelProviderForm, {\n type CustomProviderDraft,\n} from '@/containers/SettingsBuilder/CustomModelProviderForm.js';\nimport { useToasterOptional } from '@/containers/ToasterContainer.js';\nimport { Icon } from '@/icons/Icon.js';\nimport { useCatalogServer } from '@/server/ServerContext.js';\nimport type { ModelEntry, ModelProviderBase, ModelProviderCatalogEntry } from '@/server/types.js';\nimport { getErrorMessage } from '@/utils/getErrorMessage.js';\n\nfunction catalogBaseUrl(provider: ModelProviderCatalogEntry): string {\n if ('baseUrl' in provider && typeof provider.baseUrl === 'string') {\n return provider.baseUrl;\n }\n return '';\n}\n\nconst ModelSettings = () => {\n const { modelCatalog } = useCatalogServer();\n const toaster = useToasterOptional();\n\n const [query, setQuery] = useState('');\n const [configured, setConfigured] = useState<ModelProviderBase[]>([]);\n const [catalog, setCatalog] = useState<ModelProviderCatalogEntry[]>([]);\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 [editingProviderId, setEditingProviderId] = useState<string | null>(null);\n const [editingCatalogType, setEditingCatalogType] = useState<string | null>(null);\n const [keyError, setKeyError] = useState<string | null>(null);\n const [customProviderOpen, setCustomProviderOpen] = useState(false);\n const [customProviderToEdit, setCustomProviderToEdit] = useState<ModelProviderBase | null>(null);\n\n const modelProviderIconMap = 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 normalizedQuery = query.trim().toLowerCase();\n\n const refresh = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const [listed, available] = await Promise.all([\n modelCatalog.listModelProviders(),\n modelCatalog.getModelProviderCatalog(),\n ]);\n setConfigured(listed);\n setCatalog(available);\n } catch (err) {\n setError(getErrorMessage(err, 'Failed to load model providers'));\n } finally {\n setLoading(false);\n }\n }, [modelCatalog]);\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n const configuredTypes = useMemo(() => new Set(configured.map(provider => provider.type)), [configured]);\n\n const matchingConfigured = useMemo(\n () =>\n configured.filter(\n provider =>\n provider.name?.toLowerCase().includes(normalizedQuery) ||\n provider.models.some(\n model =>\n model.name.toLowerCase().includes(normalizedQuery) || model.id.toLowerCase().includes(normalizedQuery),\n ),\n ),\n [configured, normalizedQuery],\n );\n\n const matchingAvailable = useMemo(\n () =>\n catalog.filter(\n provider =>\n provider.type !== 'custom' &&\n !configuredTypes.has(provider.type) &&\n (provider.name.toLowerCase().includes(normalizedQuery) ||\n provider.models.some(\n model =>\n model.name.toLowerCase().includes(normalizedQuery) || model.id.toLowerCase().includes(normalizedQuery),\n )),\n ),\n [catalog, configuredTypes, normalizedQuery],\n );\n\n const supportedReasoningEfforts = useMemo(() => {\n return catalog.find(provider => provider.type === 'custom')?.supportedReasoningEfforts;\n }, [catalog]);\n\n const catalogModelsByType = useMemo(() => {\n const map = new Map<string, ModelEntry[]>();\n for (const entry of catalog) {\n map.set(entry.type, entry.models);\n }\n return map;\n }, [catalog]);\n\n const closeKeyEditor = () => {\n setEditingProviderId(null);\n setEditingCatalogType(null);\n setKeyError(null);\n };\n\n const runMutation = async (fn: () => Promise<void>, onError?: (error: unknown) => void) => {\n setBusy(true);\n setError(null);\n try {\n await fn();\n await refresh();\n closeKeyEditor();\n } catch (err) {\n if (onError) {\n onError(err);\n } else if (toaster == null) {\n setError(getErrorMessage(err, 'Request failed'));\n } else {\n toaster.showError(err);\n }\n throw err;\n } finally {\n setBusy(false);\n }\n };\n\n // The key/endpoint modal owns the draft and awaits these handlers: on failure runMutation\n // re-throws so the modal stays open and shows `keyError`; on success it closes the editor.\n const handleCreateFromCatalog = async (entry: ModelProviderCatalogEntry, draft: ModelProviderKeyDraft) => {\n setKeyError(null);\n await runMutation(\n async () => {\n await modelCatalog.createModelProvider({\n type: entry.type,\n name: entry.name,\n ...(draft.baseUrl ? { baseUrl: draft.baseUrl } : {}),\n apiKey: draft.apiKey,\n models: entry.models,\n });\n },\n err => setKeyError(getErrorMessage(err, 'Request failed')),\n );\n };\n\n const handleReplaceKey = async (provider: ModelProviderBase, draft: ModelProviderKeyDraft) => {\n setKeyError(null);\n await runMutation(\n async () => {\n await modelCatalog.updateModelProvider({\n id: provider.id,\n type: provider.type,\n name: provider.name,\n ...(draft.baseUrl ? { baseUrl: draft.baseUrl } : {}),\n // Empty key means \"keep the existing one\" for hosts that support it.\n apiKey: draft.apiKey,\n models: provider.models,\n });\n },\n err => setKeyError(getErrorMessage(err, 'Request failed')),\n );\n toaster?.showSuccess({ title: `${provider.name} updated` });\n };\n\n const handleRemoveProvider = (provider: ModelProviderBase) => {\n if (!modelCatalog.deleteModelProvider) return;\n\n void runMutation(async () => {\n await modelCatalog.deleteModelProvider!({ id: provider.id });\n }).catch(() => {});\n };\n\n const handleUpdateModels = (provider: ModelProviderBase, models: ModelEntry[]) => {\n void runMutation(async () => {\n // apiKey required on update; empty means \"keep existing\" for hosts that support it.\n await modelCatalog.updateModelProvider({\n id: provider.id,\n type: provider.type,\n name: provider.name,\n ...(provider.baseUrl ? { baseUrl: provider.baseUrl } : {}),\n apiKey: '',\n models,\n });\n }).catch(() => {});\n };\n\n const handleAddCustomProvider = async (draft: CustomProviderDraft) => {\n setFormError(null);\n await runMutation(\n async () => {\n await modelCatalog.createModelProvider({\n type: 'custom',\n name: draft.name,\n baseUrl: draft.baseUrl,\n apiKey: draft.apiKey,\n models: draft.models,\n });\n },\n err => setFormError(getErrorMessage(err, 'Request failed')),\n );\n setTimeout(() => {\n toaster?.showSuccess({ title: `${draft.name} added` });\n }, 0);\n };\n\n const handleUpdateCustomProvider = async (draft: CustomProviderDraft) => {\n if (!customProviderToEdit) return;\n\n const provider = customProviderToEdit;\n setFormError(null);\n await runMutation(\n async () => {\n await modelCatalog.updateModelProvider({\n id: provider.id,\n type: provider.type,\n name: provider.name,\n baseUrl: draft.baseUrl,\n apiKey: draft.apiKey,\n models: draft.models,\n });\n },\n err => setFormError(getErrorMessage(err, 'Request failed')),\n );\n setTimeout(() => {\n toaster?.showSuccess({\n title: 'Model provider updated',\n description: `${provider.name} was updated successfully.`,\n });\n }, 0);\n };\n\n const customProviderInitialValues = customProviderToEdit\n ? {\n name: customProviderToEdit.name,\n baseUrl: customProviderToEdit.baseUrl ?? '',\n models: customProviderToEdit.models,\n }\n : undefined;\n\n // The key/endpoint editor is a single centered modal driven by which entry is being edited.\n const editingProvider =\n editingProviderId != null ? (configured.find(item => item.id === editingProviderId) ?? null) : null;\n const editingCatalogEntry =\n editingCatalogType != null ? (catalog.find(item => item.type === editingCatalogType) ?? null) : null;\n const keyModalOpen = editingProvider != null || editingCatalogEntry != null;\n\n return (\n <>\n <h3 className=\"text-xl font-semibold tracking-tight text-text-primary\">Models</h3>\n <p className=\"mt-1 text-sm text-text-secondary\">Connect providers and choose which models are available.</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 providers and models\" />\n </div>\n <Button\n variant=\"secondary\"\n type=\"button\"\n onClick={() => {\n setFormError(null);\n setCustomProviderToEdit(null);\n setCustomProviderOpen(true);\n }}\n >\n <Icon name=\"plus\" size=\"1rem\" className=\"mr-1\" />\n Add Custom Provider\n </Button>\n </div>\n\n <div className=\"flex flex-1 flex-col gap-2 overflow-y-auto\">\n {loading ? <p className=\"py-8 text-center text-sm text-text-secondary\">Loading…</p> : null}\n\n {!loading && matchingConfigured.length > 0 ? (\n <section aria-labelledby=\"configured-providers-heading\">\n <div\n id=\"configured-providers-heading\"\n className=\"mb-2 text-[0.8125rem] font-semibold uppercase text-text-secondary\"\n >\n Configured\n </div>\n\n <div className=\"overflow-hidden rounded-xl border border-border bg-card-bg\">\n {matchingConfigured.map(provider => {\n const catalogModels = catalogModelsByType.get(provider.type) ?? [];\n const configuredIds = new Set(provider.models.map(model => model.id));\n const availableModels = catalogModels.filter(model => !configuredIds.has(model.id));\n const logoSrc = modelProviderIconMap[provider.name];\n\n return (\n <article key={provider.id} className=\"border-b border-border p-3 last:border-b-0\">\n <header className=\"flex flex-col gap-3 sm:flex-row sm:items-center\">\n <div className=\"flex min-w-0 flex-1 items-center gap-3\">\n <div\n className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary\"\n aria-hidden\n >\n {logoSrc ? (\n <CatalogLogo src={logoSrc} alt={provider.name} className=\"size-4.5\" />\n ) : (\n <Icon name=\"cpu\" className=\"size-4.5\" />\n )}\n </div>\n <h5 className=\"truncate text-base font-medium text-text-primary\">{provider.name}</h5>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2.5 sm:justify-end\">\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 <Button\n variant=\"secondary\"\n size=\"sm\"\n className=\"text-[0.8125rem]\"\n type=\"button\"\n aria-label={`Edit ${provider.name}`}\n title={`Edit ${provider.name}`}\n disabled={busy}\n onClick={() => {\n if (provider.type === 'custom') {\n closeKeyEditor();\n setFormError(null);\n setCustomProviderToEdit(provider);\n setCustomProviderOpen(true);\n } else {\n setKeyError(null);\n setEditingCatalogType(null);\n setEditingProviderId(provider.id);\n }\n }}\n >\n <Icon name=\"wrench\" className=\"size-3.5\" />\n Edit\n </Button>\n {modelCatalog.deleteModelProvider ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"transition-colors hover:bg-failure-bg/10 hover:text-failure-bg\"\n type=\"button\"\n disabled={busy}\n onClick={() => {\n handleRemoveProvider(provider);\n }}\n >\n Remove\n </Button>\n ) : null}\n </div>\n </header>\n\n <div className=\"mt-3 overflow-hidden rounded-lg border border-border bg-secondary-bg/30\">\n {provider.models.map(model => (\n <div\n key={model.id}\n className=\"flex min-h-10 items-center gap-3 border-b border-border px-3 py-2 text-sm text-text-primary last:border-b-0\"\n >\n <span className=\"min-w-0 flex-1 truncate\">{model.name}</span>\n <button\n type=\"button\"\n aria-label={`Remove ${model.name}`}\n disabled={busy}\n className=\"inline-flex size-7 shrink-0 items-center justify-center rounded-md text-text-secondary hover:bg-ghost-button-hover hover:text-ghost-button-text focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus-ring disabled:opacity-50\"\n onClick={() => {\n handleUpdateModels(\n provider,\n provider.models.filter(item => item.id !== model.id),\n );\n }}\n >\n <Icon name=\"trash\" className=\"size-3.5\" />\n </button>\n </div>\n ))}\n\n {availableModels.length > 0 ? (\n <section>\n <div className=\"border-b border-border bg-secondary-bg/40 px-3 py-2 text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n Available to add · {availableModels.length}\n </div>\n {availableModels.map(model => (\n <div\n key={model.id}\n className=\"flex min-h-12 items-center gap-3 border-b border-border px-3 py-2 text-sm text-text-primary last:border-b-0\"\n >\n <span className=\"min-w-0 flex-1 truncate\">{model.name}</span>\n <Button\n variant=\"outline\"\n size=\"sm\"\n type=\"button\"\n disabled={busy}\n onClick={() => {\n handleUpdateModels(provider, [...provider.models, model]);\n }}\n >\n Add\n </Button>\n </div>\n ))}\n </section>\n ) : null}\n </div>\n </article>\n );\n })}\n </div>\n </section>\n ) : null}\n\n {!loading && matchingAvailable.length > 0 ? (\n <section aria-labelledby=\"available-providers-heading\" className=\"mt-2\">\n <div\n id=\"available-providers-heading\"\n className=\"mb-2 text-[0.8125rem] font-semibold uppercase text-text-secondary\"\n >\n Available\n </div>\n\n <div className=\"overflow-hidden rounded-xl border border-border bg-card-bg\">\n {matchingAvailable.map(provider => {\n const logoSrc = modelProviderIconMap[provider.name];\n return (\n <article key={provider.type} className=\"border-b border-border p-3 last:border-b-0\">\n <header className=\"flex flex-col gap-3 sm:flex-row sm:items-center\">\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 {logoSrc ? (\n <CatalogLogo src={logoSrc} alt={provider.name} className=\"size-4.5\" />\n ) : (\n <Icon name=\"cpu\" className=\"size-4.5\" />\n )}\n </span>\n <div className=\"min-w-0\">\n <h5 className=\"truncate text-base font-medium text-text-primary\">{provider.name}</h5>\n <p className=\"truncate text-sm text-text-secondary\">\n {provider.models.map(model => model.name).join(' · ')}\n </p>\n </div>\n </div>\n <Button\n variant=\"secondary\"\n type=\"button\"\n disabled={busy}\n onClick={() => {\n setKeyError(null);\n setEditingProviderId(null);\n setEditingCatalogType(provider.type);\n }}\n >\n <Icon name=\"wrench\" className=\"size-4\" />\n Configure\n </Button>\n </header>\n </article>\n );\n })}\n </div>\n </section>\n ) : null}\n\n {!loading && matchingConfigured.length === 0 && matchingAvailable.length === 0 ? (\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 {normalizedQuery ? `No providers match “${query.trim()}”.` : 'No model providers yet.'}\n </div>\n ) : null}\n </div>\n\n <ConfigureModelProviderForm\n open={keyModalOpen}\n onOpenChange={open => {\n if (!open) closeKeyEditor();\n }}\n onSave={draft => {\n if (editingProvider) return handleReplaceKey(editingProvider, draft);\n if (editingCatalogEntry) return handleCreateFromCatalog(editingCatalogEntry, draft);\n }}\n title={editingProvider ? 'Edit Provider Details' : 'Configure Provider Details'}\n initialBaseUrl={\n editingProvider\n ? (editingProvider.baseUrl ?? '')\n : editingCatalogEntry\n ? catalogBaseUrl(editingCatalogEntry)\n : ''\n }\n requireApiKey={editingProvider == null}\n submitLabel={editingProvider ? 'Save' : 'Create'}\n busy={busy}\n error={keyError}\n />\n\n <CustomModelProviderForm\n key={customProviderToEdit?.id ?? 'add-custom-provider'}\n open={customProviderOpen}\n onOpenChange={open => {\n setCustomProviderOpen(open);\n if (!open) {\n setFormError(null);\n setCustomProviderToEdit(null);\n }\n }}\n isEditMode={customProviderToEdit !== null}\n initialValues={customProviderInitialValues}\n onSubmit={customProviderToEdit ? handleUpdateCustomProvider : handleAddCustomProvider}\n reasoningEffortOptions={supportedReasoningEfforts}\n busy={busy}\n error={formError}\n />\n </div>\n </div>\n </>\n );\n};\n\nexport default ModelSettings;\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';\n\nexport type ModelProviderKeyDraft = { apiKey: string; baseUrl: string };\n\ntype ConfigureModelProviderFormProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSave: (draft: ModelProviderKeyDraft) => void | Promise<void>;\n title: string;\n description?: string;\n /** Prefills the Base URL (endpoint). The API key is never autofilled. */\n initialBaseUrl?: string;\n baseUrlPlaceholder?: string;\n /** When false (editing), a blank API key keeps the existing one; a value replaces it. */\n requireApiKey?: boolean;\n submitLabel?: string;\n busy?: boolean;\n error?: string | null;\n};\n\nconst inputClassName = auiInputClass('h-11 shadow-sm');\n\nconst ConfigureModelProviderForm = ({\n open,\n onOpenChange,\n onSave,\n title,\n description,\n initialBaseUrl = '',\n baseUrlPlaceholder = 'https://api.openai.com/v1',\n requireApiKey = true,\n submitLabel = 'Save',\n busy = false,\n error,\n}: ConfigureModelProviderFormProps) => {\n const [apiKey, setApiKey] = useState('');\n const [baseUrl, setBaseUrl] = useState('');\n const [advancedOpen, setAdvancedOpen] = useState(false);\n\n const resetForm = () => {\n setApiKey('');\n setBaseUrl('');\n setAdvancedOpen(false);\n };\n\n // Prefill the endpoint when the modal opens; the API key is always blank (never echoed back).\n useEffect(() => {\n if (!open) return;\n setApiKey('');\n setBaseUrl(initialBaseUrl);\n setAdvancedOpen(false);\n }, [open, initialBaseUrl]);\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (!nextOpen) resetForm();\n onOpenChange(nextOpen);\n };\n\n const trimmedKey = apiKey.trim();\n const isValid = !requireApiKey || !!trimmedKey;\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!isValid || busy) return;\n try {\n await onSave({ apiKey: trimmedKey, baseUrl: baseUrl.trim() });\n resetForm();\n onOpenChange(false);\n } catch {\n // Parent surfaces the error via the `error` prop; keep the modal open.\n }\n };\n\n return (\n <CenteredModal open={open} onOpenChange={handleOpenChange} title={title} description={description} contentSized>\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=\"model-provider-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=\"model-provider-api-key\"\n type=\"password\"\n required={requireApiKey}\n value={apiKey}\n onChange={event => {\n setApiKey(event.target.value);\n }}\n placeholder={requireApiKey ? 'Enter API key' : 'Enter a new key'}\n autoFocus\n className={inputClassName}\n />\n {!requireApiKey ? (\n <p className=\"mt-1.5 text-xs text-text-secondary\">\n Leave blank to keep the current key; enter a new one to replace it.\n </p>\n ) : null}\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 · custom endpoint\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-1.5 border-t border-border px-3 pb-3 pt-4\">\n <label htmlFor=\"model-provider-base-url\" className=\"block text-sm font-medium text-text-primary\">\n Base URL\n </label>\n <input\n id=\"model-provider-base-url\"\n type=\"url\"\n value={baseUrl}\n onChange={event => {\n setBaseUrl(event.target.value);\n }}\n placeholder={baseUrlPlaceholder}\n className={inputClassName}\n />\n <p className=\"text-xs text-text-secondary\">Leave blank unless you use a regional or proxy endpoint.</p>\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 {submitLabel}\n </Button>\n </div>\n </form>\n </CenteredModal>\n );\n};\n\nexport default ConfigureModelProviderForm;\n","'use client';\n\nimport { useState, type ReactNode } from 'react';\n\nimport { cn } from '../../atoms/lib/cn.js';\nimport { Button } from '../../atoms/primitives/Button.js';\nimport { CenteredModal } from '../../atoms/primitives/CenteredModal.js';\nimport { Icon } from '../../icons/Icon.js';\n\nexport type CustomProviderDraft = {\n name: string;\n baseUrl: string;\n apiKey: string;\n models: Array<{\n id: string;\n name: string;\n properties?: {\n reasoningEfforts?: string[];\n contextLength?: number;\n maxOutputTokens?: number;\n };\n }>;\n};\n\nexport type CustomProviderInitialValues = Omit<CustomProviderDraft, 'apiKey'>;\n\ntype CustomModelProviderFormProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSubmit: (draft: CustomProviderDraft) => void | Promise<void>;\n isEditMode?: boolean;\n initialValues?: CustomProviderInitialValues;\n reasoningEffortOptions?: readonly string[];\n busy?: boolean;\n error?: string | null;\n};\n\ntype ModelRow = {\n name: string;\n advancedExpanded: boolean;\n reasoningEfforts?: string[];\n contextLength: string;\n maxOutputTokens: string;\n idTouched?: boolean;\n contextTouched?: boolean;\n maxTouched?: boolean;\n // Set once the user edits the model name by hand, so auto-derive from the id stops.\n nameDirty?: boolean;\n // `id` is the upstream model_id; kept last so object-shorthand stays readable.\n id: string;\n};\n\n// Shown only as greyed placeholders — never prefilled, since real limits vary per model\n// and a wrong-looking default reads as \"already correct\".\nconst PLACEHOLDER_CONTEXT_LENGTH = '128000';\nconst PLACEHOLDER_MAX_OUTPUT_TOKENS = '4096';\n\nconst createEmptyModelRow = (): ModelRow => ({\n id: '',\n name: '',\n // Expanded by default: Context length and Max output tokens are required, so they\n // shouldn't be hidden behind a collapsed section.\n advancedExpanded: true,\n contextLength: '',\n maxOutputTokens: '',\n});\n\nconst createModelRows = (initialValues?: CustomProviderInitialValues): ModelRow[] =>\n initialValues?.models.map(model => ({\n id: model.id,\n name: model.name,\n advancedExpanded: true,\n reasoningEfforts: model.properties?.reasoningEfforts,\n contextLength: model.properties?.contextLength?.toString() ?? '',\n maxOutputTokens: model.properties?.maxOutputTokens?.toString() ?? '',\n nameDirty: true,\n })) ?? [createEmptyModelRow()];\n\n// Flat, de-boxed input with enough contrast to read as editable: a slightly\n// deeper fill, a subtle hairline, and a clear focus ring.\nconst inputClassName =\n 'h-11 w-full rounded-md border border-border/70 bg-secondary-bg px-3 text-sm text-text-primary outline-none transition-colors placeholder:text-text-secondary/70 focus-visible:border-focus-ring focus-visible:ring-2 focus-visible:ring-focus-ring/50';\nconst inputErrorClassName = 'border-failure-bg focus-visible:border-failure-bg focus-visible:ring-failure-bg';\n\n/** Parse an optional positive integer; returns null when empty or invalid (so it's simply omitted). */\nfunction parsePositiveInt(raw: string): number | null {\n const trimmed = raw.trim();\n if (trimmed === '') return null;\n const n = Number(trimmed);\n return Number.isInteger(n) && n > 0 ? n : null;\n}\n\n/** Derive a NameSchema-valid slug from an upstream model id, e.g. \"llama3.1:70b\" -> \"llama-3-1-70b\". */\nfunction slugifyModelId(raw: string): string {\n return raw\n .replace(/([a-zA-Z])(\\d)/g, '$1-$2') // split letter→digit boundaries\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-') // separators → single hyphen\n .replace(/^[^a-z]+/, '') // must start with a letter\n .slice(0, 64) // enforce max length first…\n .replace(/-+$/g, ''); // …then trim any separator truncation left at the end\n}\n\nconst RequiredMark = () => (\n <span className=\"ml-0.5 text-failure-bg\" aria-hidden>\n *\n </span>\n);\n\nconst FieldError = ({ children }: { children: ReactNode }) => (\n <p className=\"mt-1 text-xs text-failure-bg\">{children}</p>\n);\n\nconst FieldHelp = ({ children }: { children: ReactNode }) => (\n <p className=\"mt-1 text-xs text-text-secondary\">{children}</p>\n);\n\nconst CustomModelProviderForm = ({\n open,\n onOpenChange,\n onSubmit,\n reasoningEffortOptions,\n busy = false,\n error,\n isEditMode = false,\n initialValues,\n}: CustomModelProviderFormProps) => {\n const [name, setName] = useState(initialValues?.name ?? '');\n const [baseUrl, setBaseUrl] = useState(initialValues?.baseUrl ?? '');\n const [apiKey, setApiKey] = useState('');\n const [models, setModels] = useState<ModelRow[]>(() => createModelRows(initialValues));\n const [nameTouched, setNameTouched] = useState(false);\n const [baseUrlTouched, setBaseUrlTouched] = useState(false);\n\n const resetForm = () => {\n setName(initialValues?.name ?? '');\n setBaseUrl(initialValues?.baseUrl ?? '');\n setApiKey('');\n setModels(createModelRows(initialValues));\n setNameTouched(false);\n setBaseUrlTouched(false);\n };\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (!nextOpen) resetForm();\n onOpenChange(nextOpen);\n };\n\n const updateModel = (index: number, patch: Partial<ModelRow>) => {\n setModels(current => current.map((model, i) => (i === index ? { ...model, ...patch } : model)));\n };\n\n // On a submit attempt, reveal errors for every field that already exists. We flip\n // per-field `touched` flags rather than keeping a single global \"submitted\" flag, so\n // a model added *after* the attempt starts clean instead of showing errors for inputs\n // the user has never touched.\n const markAllTouched = () => {\n setNameTouched(true);\n setBaseUrlTouched(true);\n setModels(current =>\n current.map(model => ({\n ...model,\n idTouched: true,\n contextTouched: true,\n maxTouched: true,\n })),\n );\n };\n\n // ── Validation ── Client checks stay backend-agnostic: presence only. Name *format*\n // rules (slug pattern, length) belong to the server, which may differ per deployment;\n // violations surface via the `error` prop on submit rather than being second-guessed here.\n const trimmedName = name.trim();\n const nameError = trimmedName ? null : 'Name is required.';\n\n const trimmedBaseUrl = baseUrl.trim();\n let baseUrlError: string | null = null;\n if (!trimmedBaseUrl) {\n baseUrlError = 'Base URL is required.';\n } else {\n try {\n new URL(trimmedBaseUrl);\n } catch {\n baseUrlError = 'Enter a valid URL.';\n }\n }\n\n const modelIdError = (model: ModelRow): string | null => (model.id.trim() ? null : 'Model ID is required.');\n const modelNameError = (model: ModelRow): string | null => (model.name.trim() ? null : 'Model name is required.');\n\n // Both limits are required: the harness budgets a run as input + reserved output ≤ context window.\n const modelContextError = (model: ModelRow): string | null =>\n parsePositiveInt(model.contextLength) == null ? \"Set the model's context window.\" : null;\n const modelMaxOutputError = (model: ModelRow): string | null =>\n parsePositiveInt(model.maxOutputTokens) == null ? 'Set the max output tokens.' : null;\n\n // The Add-provider button gates on the always-visible fields. The collapsed per-model\n // limits are enforced on submit — auto-expanding and focusing the first offender.\n const visibleValid =\n !nameError && !baseUrlError && models.every(model => !modelIdError(model) && !modelNameError(model));\n\n const showNameError = nameTouched && nameError;\n const showBaseUrlError = baseUrlTouched && baseUrlError;\n\n const handleSubmit = async () => {\n markAllTouched();\n if (!visibleValid || busy) return;\n\n // A required per-model limit is missing: reveal it rather than silently blocking.\n // Expand that model's Advanced section, then scroll to and focus the first empty field.\n const incompleteIndex = models.findIndex(model => modelContextError(model) || modelMaxOutputError(model));\n if (incompleteIndex !== -1) {\n updateModel(incompleteIndex, { advancedExpanded: true });\n const target = models[incompleteIndex];\n const field = target && modelContextError(target) ? 'context-length' : 'max-output-tokens';\n setTimeout(() => {\n const el = document.getElementById(`custom-provider-model-${incompleteIndex}-${field}`);\n // scrollIntoView is unimplemented in jsdom; guard the method so tests don't throw.\n el?.scrollIntoView?.({ block: 'center', behavior: 'smooth' });\n (el as HTMLInputElement | null)?.focus();\n }, 0);\n return;\n }\n\n try {\n await onSubmit({\n name: trimmedName,\n baseUrl: trimmedBaseUrl,\n apiKey: apiKey.trim(),\n models: models.map(model => {\n const properties: NonNullable<CustomProviderDraft['models'][number]['properties']> = {};\n if (model.reasoningEfforts?.length) properties.reasoningEfforts = model.reasoningEfforts;\n const contextLength = parsePositiveInt(model.contextLength);\n if (contextLength != null) properties.contextLength = contextLength;\n const maxOutputTokens = parsePositiveInt(model.maxOutputTokens);\n if (maxOutputTokens != null) properties.maxOutputTokens = maxOutputTokens;\n return {\n id: model.id.trim(),\n name: model.name.trim(),\n ...(Object.keys(properties).length > 0 ? { properties } : {}),\n };\n }),\n });\n handleOpenChange(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={isEditMode ? `Edit ${initialValues?.name ?? name}` : 'Add custom provider'}\n description={\n isEditMode\n ? 'Update the endpoint, credentials, and models for this provider.'\n : \"Connect any OpenAI-compatible endpoint, whether it's a local model, a proxy, or your own hosted service.\"\n }\n contentSized\n >\n <form\n className=\"flex min-h-0 flex-1 flex-col\"\n onSubmit={event => {\n event.preventDefault();\n void handleSubmit();\n }}\n >\n {/* Scrollable body — generous bottom padding keeps expanded Advanced clear of the pinned footer */}\n <div className=\"min-h-0 flex-1 space-y-4 overflow-y-auto px-5 pt-4 pb-8\">\n <div>\n <label htmlFor=\"custom-provider-name\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Name\n <RequiredMark />\n </label>\n <input\n id=\"custom-provider-name\"\n type=\"text\"\n value={name}\n onChange={event => setName(event.target.value)}\n onBlur={() => setNameTouched(true)}\n placeholder=\"local-llama\"\n autoFocus={!isEditMode}\n readOnly={isEditMode}\n aria-readonly={isEditMode}\n aria-invalid={showNameError ? true : undefined}\n className={cn(\n inputClassName,\n isEditMode && 'cursor-not-allowed bg-secondary-bg/60 text-text-secondary',\n showNameError && inputErrorClassName,\n )}\n />\n {isEditMode ? <FieldHelp>Provider names cannot be changed after creation.</FieldHelp> : null}\n {showNameError ? <FieldError>{nameError}</FieldError> : null}\n </div>\n\n <div>\n <label htmlFor=\"custom-provider-base-url\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Base URL\n <RequiredMark />\n </label>\n <input\n id=\"custom-provider-base-url\"\n type=\"text\"\n value={baseUrl}\n onChange={event => setBaseUrl(event.target.value)}\n onBlur={() => setBaseUrlTouched(true)}\n placeholder=\"http://localhost:11434/v1\"\n autoFocus={isEditMode}\n aria-invalid={showBaseUrlError ? true : undefined}\n className={cn(inputClassName, showBaseUrlError && inputErrorClassName)}\n />\n {showBaseUrlError ? (\n <FieldError>{baseUrlError}</FieldError>\n ) : !trimmedBaseUrl ? (\n <FieldHelp>OpenAI-compatible endpoint, usually ending in /v1.</FieldHelp>\n ) : null}\n </div>\n\n <div>\n <label htmlFor=\"custom-provider-api-key\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n API key\n <span className=\"font-normal text-text-secondary\"> (optional)</span>\n </label>\n <input\n id=\"custom-provider-api-key\"\n type=\"password\"\n value={apiKey}\n onChange={event => setApiKey(event.target.value)}\n placeholder=\"sk-…\"\n className={inputClassName}\n />\n <FieldHelp>\n {isEditMode\n ? 'Leave blank to keep the saved key, or enter a new key to replace it.'\n : 'Leave blank if your endpoint needs no key (e.g. a local model).'}\n </FieldHelp>\n </div>\n\n <fieldset className=\"m-0 min-w-0 border-0 p-0\">\n <legend className=\"float-left mb-2 w-full p-0 text-sm font-medium text-text-primary\">\n Models\n <RequiredMark />\n </legend>\n\n <div className=\"clear-both\">\n {models.map((model, index) => {\n const idError = modelIdError(model);\n const showIdError = model.idTouched && idError;\n const nameFieldError = modelNameError(model);\n // The Model name is auto-derived from the Model ID and is editable. Never flag an\n // auto-derived value: if the id yields no usable name, stay silent and let the user\n // type one. Only surface an error once they have hand-edited the name themselves.\n const showNameFieldError = !!nameFieldError && model.nameDirty;\n const contextError = modelContextError(model);\n const maxError = modelMaxOutputError(model);\n const showContextError = model.contextTouched && contextError;\n const showMaxError = model.maxTouched && maxError;\n return (\n <div\n key={index}\n className={cn('pb-6', index > 0 ? 'border-t border-border pt-6' : 'pt-1')}\n style={index > 0 ? { borderTopWidth: '0.5px' } : undefined}\n >\n <div className=\"grid grid-cols-[1fr_1fr_2rem] items-end gap-2\">\n <div className=\"min-w-0\">\n <label\n htmlFor={`custom-provider-model-${index}-id`}\n className=\"mb-1 block text-xs font-normal text-text-secondary\"\n >\n Model ID\n </label>\n <input\n id={`custom-provider-model-${index}-id`}\n type=\"text\"\n value={model.id}\n onChange={event => {\n const id = event.target.value;\n // Keep the model name in sync with the id until the user edits it by hand.\n updateModel(index, {\n id,\n ...(model.nameDirty ? {} : { name: slugifyModelId(id) }),\n });\n }}\n onBlur={() => updateModel(index, { idTouched: true })}\n placeholder=\"llama3.1:70b\"\n aria-invalid={showIdError ? true : undefined}\n className={cn(inputClassName, 'font-mono', showIdError && inputErrorClassName)}\n />\n </div>\n <div className=\"min-w-0\">\n <label\n htmlFor={`custom-provider-model-${index}-name`}\n className=\"mb-1 block text-xs font-normal text-text-secondary\"\n >\n Model name\n </label>\n <input\n id={`custom-provider-model-${index}-name`}\n type=\"text\"\n value={model.name}\n onChange={event => updateModel(index, { name: event.target.value, nameDirty: true })}\n placeholder=\"llama-3-1-70b\"\n aria-invalid={showNameFieldError ? true : undefined}\n className={cn(inputClassName, showNameFieldError && inputErrorClassName)}\n />\n </div>\n <button\n type=\"button\"\n aria-label={`Remove model ${index + 1}`}\n disabled={models.length === 1 || busy}\n className=\"mb-0.5 flex size-9 items-center justify-center rounded-md text-text-secondary transition-colors hover:text-text-primary disabled:opacity-40\"\n onClick={() => setModels(current => current.filter((_, i) => i !== index))}\n >\n <Icon name=\"trash\" className=\"size-4\" />\n </button>\n </div>\n {showIdError ? <FieldError>{idError}</FieldError> : null}\n {showNameFieldError ? <FieldError>{nameFieldError}</FieldError> : null}\n\n {/* Advanced (plain text toggle, no surrounding box) */}\n <div className=\"mt-2\">\n <button\n type=\"button\"\n aria-expanded={model.advancedExpanded}\n aria-controls={`custom-provider-model-${index}-advanced`}\n className=\"flex cursor-pointer items-center gap-1.5 text-sm font-medium text-text-primary\"\n onClick={() => updateModel(index, { advancedExpanded: !model.advancedExpanded })}\n >\n <Icon\n name=\"chevron-down\"\n className={cn(\n 'size-4 text-text-secondary transition-transform',\n model.advancedExpanded ? '' : '-rotate-90',\n )}\n />\n Advanced\n </button>\n\n {model.advancedExpanded ? (\n <div id={`custom-provider-model-${index}-advanced`} className=\"mt-3 space-y-4 pl-6\">\n <div>\n <label\n htmlFor={`custom-provider-model-${index}-context-length`}\n className=\"mb-1.5 block text-xs font-medium text-text-secondary\"\n >\n Context length\n <RequiredMark />\n </label>\n <input\n id={`custom-provider-model-${index}-context-length`}\n type=\"number\"\n min={1}\n inputMode=\"numeric\"\n value={model.contextLength}\n onChange={event => updateModel(index, { contextLength: event.target.value })}\n onBlur={() => updateModel(index, { contextTouched: true })}\n placeholder={PLACEHOLDER_CONTEXT_LENGTH}\n aria-invalid={showContextError ? true : undefined}\n className={cn(inputClassName, showContextError && inputErrorClassName)}\n />\n {showContextError ? (\n <FieldError>{contextError}</FieldError>\n ) : model.contextLength.trim() === '' ? (\n <FieldHelp>Model&apos;s total token window.</FieldHelp>\n ) : null}\n </div>\n\n <div>\n <label\n htmlFor={`custom-provider-model-${index}-max-output-tokens`}\n className=\"mb-1.5 block text-xs font-medium text-text-secondary\"\n >\n Max output tokens\n <RequiredMark />\n </label>\n <input\n id={`custom-provider-model-${index}-max-output-tokens`}\n type=\"number\"\n min={1}\n inputMode=\"numeric\"\n value={model.maxOutputTokens}\n onChange={event => updateModel(index, { maxOutputTokens: event.target.value })}\n onBlur={() => updateModel(index, { maxTouched: true })}\n placeholder={PLACEHOLDER_MAX_OUTPUT_TOKENS}\n aria-invalid={showMaxError ? true : undefined}\n className={cn(inputClassName, showMaxError && inputErrorClassName)}\n />\n {showMaxError ? (\n <FieldError>{maxError}</FieldError>\n ) : model.maxOutputTokens.trim() === '' ? (\n <FieldHelp>Longest reply the model allows — use its real limit.</FieldHelp>\n ) : null}\n </div>\n\n {reasoningEffortOptions && reasoningEffortOptions.length > 0 ? (\n <div>\n <label className=\"flex w-fit cursor-pointer items-center gap-2 select-none\">\n <input\n type=\"checkbox\"\n className=\"size-4 shrink-0 cursor-pointer accent-primary-button-bg disabled:cursor-not-allowed disabled:opacity-50\"\n checked={model.reasoningEfforts !== undefined}\n aria-label={`Enable reasoning effort for model ${index + 1}`}\n disabled={busy}\n onChange={event =>\n updateModel(index, {\n reasoningEfforts: event.target.checked ? [] : undefined,\n })\n }\n />\n <span className=\"text-text-secondary text-xs font-medium\">Reasoning effort</span>\n </label>\n {model.reasoningEfforts !== undefined ? (\n <div\n role=\"group\"\n aria-label={`Supported reasoning efforts for model ${index + 1}`}\n className=\"mt-2 flex flex-wrap gap-2\"\n >\n {reasoningEffortOptions.map(effort => {\n const selected = model.reasoningEfforts?.includes(effort) ?? false;\n return (\n <button\n key={effort}\n type=\"button\"\n aria-pressed={selected}\n disabled={busy}\n className={cn(\n 'rounded-full border px-3 py-1 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring/40 disabled:opacity-50',\n selected\n ? 'border-primary-button-bg bg-primary-button-bg text-primary-button-text'\n : 'border-border text-text-secondary hover:bg-ghost-button-hover',\n )}\n onClick={() =>\n updateModel(index, {\n reasoningEfforts: selected\n ? model.reasoningEfforts?.filter(item => item !== effort)\n : [...(model.reasoningEfforts ?? []), effort],\n })\n }\n >\n {effort}\n </button>\n );\n })}\n </div>\n ) : null}\n </div>\n ) : null}\n </div>\n ) : null}\n </div>\n </div>\n );\n })}\n </div>\n\n <Button\n variant=\"secondary\"\n size=\"sm\"\n type=\"button\"\n className=\"mt-4 w-fit\"\n onClick={() => setModels(current => [...current, createEmptyModelRow()])}\n >\n <Icon name=\"plus\" className=\"size-3.5\" />\n Add model\n </Button>\n </fieldset>\n </div>\n\n {/* Sticky footer */}\n <div className=\"shrink-0 space-y-3 border-t border-border px-5 py-4\">\n {error ? <p className=\"text-failure-bg text-sm\">{error}</p> : null}\n <Button type=\"submit\" size=\"lg\" disabled={!visibleValid || busy} className=\"w-full\">\n {isEditMode ? 'Save changes' : 'Add provider'}\n </Button>\n </div>\n </form>\n </CenteredModal>\n );\n};\n\nexport default CustomModelProviderForm;\n"],"mappings":"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","names":["useEffect","useState","useState","jsx","jsxs","inputClassName","useState","jsx","jsxs","useState","useEffect"]}
@@ -1,9 +0,0 @@
1
- "use client";
2
- import {
3
- OpenUiFenceBlock
4
- } from "./chunk-MPNSO7E6.js";
5
- import "./chunk-7Z2C2K7F.js";
6
- export {
7
- OpenUiFenceBlock
8
- };
9
- //# sourceMappingURL=OpenUiFenceBlock-2TV5TQ6P.js.map