@truefoundry/trueforge-ui 0.3.0-rc.2 → 0.3.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +17 -9
- package/dist/{AgentCodeSnippets-637HQUXD.js → AgentCodeSnippets-N546FNNS.js} +38 -23
- package/dist/AgentCodeSnippets-N546FNNS.js.map +1 -0
- package/dist/AgentMetricChart-YWJYVYYA.js +15 -0
- package/dist/{AgentOverview-3FJ5EE6N.js → AgentOverview-VF74XC7I.js} +7 -7
- package/dist/{AgentSessionEventTimeline-VELWUYPR.js → AgentSessionEventTimeline-RFR6LQMY.js} +8 -8
- package/dist/{AgentSessionEventTimeline-VELWUYPR.js.map → AgentSessionEventTimeline-RFR6LQMY.js.map} +1 -1
- package/dist/{AgentSessionEventTimelineChart-CUKETHWM.js → AgentSessionEventTimelineChart-27CQF6FX.js} +12 -12
- package/dist/AgentSessionEventTimelineChart-27CQF6FX.js.map +1 -0
- package/dist/{AgentSessions-T7MOGOTZ.js → AgentSessions-4IVX2SGD.js} +36 -12
- package/dist/AgentSessions-4IVX2SGD.js.map +1 -0
- package/dist/{ConnectorSettings-ESZ2RSRG.js → ConnectorSettings-R5VEP7BO.js} +156 -116
- package/dist/ConnectorSettings-R5VEP7BO.js.map +1 -0
- package/dist/{DockLayout-NLFNU6F2.js → DockLayout-F44RWGEY.js} +10 -10
- package/dist/{DrawerLayout-PR3SMKA6.js → DrawerLayout-SQ323AVM.js} +13 -11
- package/dist/DrawerLayout-SQ323AVM.js.map +1 -0
- package/dist/{ModelSettings-LYW64IRR.js → ModelSettings-6QLS63HM.js} +10 -10
- package/dist/{ModelSettings-LYW64IRR.js.map → ModelSettings-6QLS63HM.js.map} +1 -1
- package/dist/OpenUiFenceBlock-4ROX3G4X.js +9 -0
- package/dist/{SandboxSettings-DF64LHYI.js → SandboxSettings-OLKDXIQS.js} +9 -9
- package/dist/SchedulesPage-TMOTK6DR.js +15 -0
- package/dist/{SettingsBuilder-LSXK2VN4.js → SettingsBuilder-GISAH2WU.js} +8 -8
- package/dist/{ShellRouteSync-B22IAV2W.js → ShellRouteSync-EN33DUQ7.js} +157 -22
- package/dist/ShellRouteSync-EN33DUQ7.js.map +1 -0
- package/dist/{SidebarLayout-XW6LXB7R.js → SidebarLayout-35K4AKTC.js} +74 -53
- package/dist/SidebarLayout-35K4AKTC.js.map +1 -0
- package/dist/{SkillSettings-64VXUO6J.js → SkillSettings-JSX2BTII.js} +18 -13
- package/dist/SkillSettings-JSX2BTII.js.map +1 -0
- package/dist/{TrueForgeUIWithRouter-3TSLV22Q.js → TrueForgeUIWithRouter-6VCR7ES3.js} +9 -9
- package/dist/{WidgetLayout-Q5P7PYSJ.js → WidgetLayout-RKBSN2FZ.js} +10 -10
- package/dist/{chunk-YQO2NMJ3.js → chunk-2O5EJ6QS.js} +4096 -2825
- package/dist/chunk-2O5EJ6QS.js.map +1 -0
- package/dist/chunk-6WCIL3H2.js +517 -0
- package/dist/chunk-6WCIL3H2.js.map +1 -0
- package/dist/{chunk-SQGT43Z3.js → chunk-73FQVITT.js} +21 -4
- package/dist/chunk-73FQVITT.js.map +1 -0
- package/dist/{chunk-QC42MLAK.js → chunk-7AAO4UDQ.js} +4 -3
- package/dist/chunk-7AAO4UDQ.js.map +1 -0
- package/dist/{chunk-LGRHHFHN.js → chunk-F5QVQIBH.js} +166 -45
- package/dist/chunk-F5QVQIBH.js.map +1 -0
- package/dist/{chunk-I3AL54MA.js → chunk-GIPFF6FZ.js} +28 -24
- package/dist/chunk-GIPFF6FZ.js.map +1 -0
- package/dist/{chunk-GXYAOAK5.js → chunk-GSJAYYLR.js} +219 -162
- package/dist/chunk-GSJAYYLR.js.map +1 -0
- package/dist/{chunk-VJ7BZGAF.js → chunk-J5BPHEDT.js} +2 -2
- package/dist/chunk-KR7WYHVF.js +195 -0
- package/dist/chunk-KR7WYHVF.js.map +1 -0
- package/dist/{chunk-VUMGMGKZ.js → chunk-LUG7E6BL.js} +52 -8
- package/dist/chunk-LUG7E6BL.js.map +1 -0
- package/dist/chunk-LXJMINS6.js +587 -0
- package/dist/chunk-LXJMINS6.js.map +1 -0
- package/dist/{chunk-FQK2XVVE.js → chunk-PT4EENB3.js} +224 -72
- package/dist/chunk-PT4EENB3.js.map +1 -0
- package/dist/{chunk-H6WTY5PM.js → chunk-Q6TCT7ZJ.js} +17 -227
- package/dist/chunk-Q6TCT7ZJ.js.map +1 -0
- package/dist/{chunk-5I2COQNL.js → chunk-XLFOXQKZ.js} +13 -11
- package/dist/chunk-XLFOXQKZ.js.map +1 -0
- package/dist/{chunk-G2TUAD65.js → chunk-XY6LZQES.js} +235 -108
- package/dist/chunk-XY6LZQES.js.map +1 -0
- package/dist/{createTrueFoundryServer-CmZnBh_l.d.ts → createTrueFoundryServer-B_FYhSdn.d.ts} +8 -5
- package/dist/index.d.ts +291 -89
- package/dist/index.js +63 -488
- package/dist/index.js.map +1 -1
- package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +36 -13
- package/dist/plugins/trueforge-agent-server-adapter/index.js +69 -35
- package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +3 -3
- package/dist/AgentCodeSnippets-637HQUXD.js.map +0 -1
- package/dist/AgentMetricChart-4FYECRIN.js +0 -15
- package/dist/AgentSessionEventTimelineChart-CUKETHWM.js.map +0 -1
- package/dist/AgentSessions-T7MOGOTZ.js.map +0 -1
- package/dist/ConnectorSettings-ESZ2RSRG.js.map +0 -1
- package/dist/DrawerLayout-PR3SMKA6.js.map +0 -1
- package/dist/OpenUiFenceBlock-JEPNPJ7U.js +0 -9
- package/dist/SchedulesPage-WQU4H25F.js +0 -15
- package/dist/ShellRouteSync-B22IAV2W.js.map +0 -1
- package/dist/SidebarLayout-XW6LXB7R.js.map +0 -1
- package/dist/SkillSettings-64VXUO6J.js.map +0 -1
- package/dist/chunk-5I2COQNL.js.map +0 -1
- package/dist/chunk-BWHOZFIV.js +0 -587
- package/dist/chunk-BWHOZFIV.js.map +0 -1
- package/dist/chunk-FQK2XVVE.js.map +0 -1
- package/dist/chunk-G2TUAD65.js.map +0 -1
- package/dist/chunk-GXYAOAK5.js.map +0 -1
- package/dist/chunk-H6WTY5PM.js.map +0 -1
- package/dist/chunk-I3AL54MA.js.map +0 -1
- package/dist/chunk-LGRHHFHN.js.map +0 -1
- package/dist/chunk-NHHSZB5N.js +0 -74
- package/dist/chunk-NHHSZB5N.js.map +0 -1
- package/dist/chunk-QC42MLAK.js.map +0 -1
- package/dist/chunk-SFZNIO6U.js +0 -18
- package/dist/chunk-SFZNIO6U.js.map +0 -1
- package/dist/chunk-SQGT43Z3.js.map +0 -1
- package/dist/chunk-VUMGMGKZ.js.map +0 -1
- package/dist/chunk-YQO2NMJ3.js.map +0 -1
- /package/dist/{AgentMetricChart-4FYECRIN.js.map → AgentMetricChart-YWJYVYYA.js.map} +0 -0
- /package/dist/{AgentOverview-3FJ5EE6N.js.map → AgentOverview-VF74XC7I.js.map} +0 -0
- /package/dist/{DockLayout-NLFNU6F2.js.map → DockLayout-F44RWGEY.js.map} +0 -0
- /package/dist/{OpenUiFenceBlock-JEPNPJ7U.js.map → OpenUiFenceBlock-4ROX3G4X.js.map} +0 -0
- /package/dist/{SandboxSettings-DF64LHYI.js.map → SandboxSettings-OLKDXIQS.js.map} +0 -0
- /package/dist/{SchedulesPage-WQU4H25F.js.map → SchedulesPage-TMOTK6DR.js.map} +0 -0
- /package/dist/{SettingsBuilder-LSXK2VN4.js.map → SettingsBuilder-GISAH2WU.js.map} +0 -0
- /package/dist/{TrueForgeUIWithRouter-3TSLV22Q.js.map → TrueForgeUIWithRouter-6VCR7ES3.js.map} +0 -0
- /package/dist/{WidgetLayout-Q5P7PYSJ.js.map → WidgetLayout-RKBSN2FZ.js.map} +0 -0
- /package/dist/{chunk-VJ7BZGAF.js.map → chunk-J5BPHEDT.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.
|
|
3
|
+
"version": "0.3.0-rc.3",
|
|
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",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"@openuidev/react-headless": "^0.9.4",
|
|
81
81
|
"@openuidev/react-lang": "^0.2.9",
|
|
82
82
|
"@openuidev/react-ui": "^0.13.2",
|
|
83
|
-
"@truefoundry/assistant-ui-runtime": "0.1.
|
|
83
|
+
"@truefoundry/assistant-ui-runtime": "0.1.35",
|
|
84
84
|
"chart.js": "^4.5.1",
|
|
85
85
|
"clsx": "^2.1.1",
|
|
86
86
|
"lucide-react": "^0.562.0",
|
|
@@ -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.
|
|
98
|
+
"@truefoundry/trueforge-sdk": "0.2.0-rc.3"
|
|
99
99
|
},
|
|
100
100
|
"devDependencies": {
|
|
101
101
|
"@eslint/js": "^9.39.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/atoms/agent-details/AgentCodeSnippets.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState, type ComponentType } from 'react';\nimport { Icon } from '../../icons/Icon.js';\nimport { useSlot } from '../../theme/SlotsProvider.js';\nimport { cn } from '../lib/cn.js';\nimport type { AgentCodeSnippetsProps } from './types.js';\n\ntype SnippetMode = 'stream' | 'nonStream';\n\nexport default function AgentCodeSnippets({ snippets }: AgentCodeSnippetsProps) {\n const AgentCodeBlock = useSlot('AgentCodeBlock');\n const [selectedLanguage, setSelectedLanguage] = useState(snippets[0]?.language);\n const [mode, setMode] = useState<SnippetMode>('stream');\n\n useEffect(() => {\n setSelectedLanguage(snippets[0]?.language);\n setMode('stream');\n }, [snippets]);\n\n const selected = snippets.find(snippet => snippet.language === selectedLanguage) ?? snippets[0];\n\n if (selected === undefined) {\n return (\n <div className=\"flex h-full min-h-64 items-center justify-center px-6 text-sm text-text-secondary\">\n No code samples for this agent.\n </div>\n );\n }\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col gap-3 p-3 md:flex-row\">\n <nav aria-label=\"Code sample languages\" className=\"flex shrink-0 gap-1 overflow-auto md:w-44 md:flex-col\">\n {snippets.map(snippet => (\n <button\n key={snippet.language}\n type=\"button\"\n aria-current={selected.language === snippet.language ? 'page' : undefined}\n className={cn(\n 'flex h-9 shrink-0 cursor-pointer items-center gap-2 rounded-md px-2.5 text-left text-xs text-text-secondary',\n 'hover:bg-ghost-button-hover hover:text-text-primary',\n selected.language === snippet.language && 'bg-primary-button-bg/10 font-medium text-primary-button-bg',\n )}\n onClick={() => setSelectedLanguage(snippet.language)}\n >\n {snippet.icon ? (\n <img src={snippet.icon} alt=\"\" className=\"size-4 shrink-0 object-contain\" />\n ) : (\n <Icon name=\"code\" className=\"size-4 shrink-0\" />\n )}\n {snippet.labelName}\n </button>\n ))}\n </nav>\n\n <section className=\"flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-lg border border-border bg-card-bg\">\n <div className=\"flex h-10 shrink-0 items-end gap-1 border-b border-border px-3\">\n {(\n [\n ['stream', 'Stream'],\n ['nonStream', 'Non-stream'],\n ] satisfies Array<[SnippetMode, string]>\n ).map(([id, label]) => (\n <button\n key={id}\n type=\"button\"\n className={cn(\n 'relative h-10 cursor-pointer px-3 text-xs font-medium text-text-secondary',\n mode === id &&\n 'text-primary-button-bg after:absolute after:inset-x-0 after:bottom-0 after:h-0.5 after:bg-primary-button-bg',\n )}\n onClick={() => setMode(id)}\n >\n {label}\n </button>\n ))}\n </div>\n <div className=\"min-h-0 flex-1 overflow-auto\">\n <AgentCodeBlock code={selected.sampleCode[mode]} language={selected.language} />\n </div>\n </section>\n </div>\n );\n}\n\ndeclare module '../../theme/SlotsProvider.js' {\n interface AtomSlots {\n AgentCodeSnippets: ComponentType<AgentCodeSnippetsProps>;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAEA,SAAS,WAAW,gBAAoC;AAsBlD,cAUI,YAVJ;AAdS,SAAR,kBAAmC,EAAE,SAAS,GAA2B;AAC9E,QAAM,iBAAiB,QAAQ,gBAAgB;AAC/C,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAAS,SAAS,CAAC,GAAG,QAAQ;AAC9E,QAAM,CAAC,MAAM,OAAO,IAAI,SAAsB,QAAQ;AAEtD,YAAU,MAAM;AACd,wBAAoB,SAAS,CAAC,GAAG,QAAQ;AACzC,YAAQ,QAAQ;AAAA,EAClB,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,WAAW,SAAS,KAAK,aAAW,QAAQ,aAAa,gBAAgB,KAAK,SAAS,CAAC;AAE9F,MAAI,aAAa,QAAW;AAC1B,WACE,oBAAC,SAAI,WAAU,qFAAoF,6CAEnG;AAAA,EAEJ;AAEA,SACE,qBAAC,SAAI,WAAU,sDACb;AAAA,wBAAC,SAAI,cAAW,yBAAwB,WAAU,yDAC/C,mBAAS,IAAI,aACZ;AAAA,MAAC;AAAA;AAAA,QAEC,MAAK;AAAA,QACL,gBAAc,SAAS,aAAa,QAAQ,WAAW,SAAS;AAAA,QAChE,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA,SAAS,aAAa,QAAQ,YAAY;AAAA,QAC5C;AAAA,QACA,SAAS,MAAM,oBAAoB,QAAQ,QAAQ;AAAA,QAElD;AAAA,kBAAQ,OACP,oBAAC,SAAI,KAAK,QAAQ,MAAM,KAAI,IAAG,WAAU,kCAAiC,IAE1E,oBAAC,QAAK,MAAK,QAAO,WAAU,mBAAkB;AAAA,UAE/C,QAAQ;AAAA;AAAA;AAAA,MAfJ,QAAQ;AAAA,IAgBf,CACD,GACH;AAAA,IAEA,qBAAC,aAAQ,WAAU,mGACjB;AAAA,0BAAC,SAAI,WAAU,kEAEX;AAAA,QACE,CAAC,UAAU,QAAQ;AAAA,QACnB,CAAC,aAAa,YAAY;AAAA,MAC5B,EACA,IAAI,CAAC,CAAC,IAAI,KAAK,MACf;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL,WAAW;AAAA,YACT;AAAA,YACA,SAAS,MACP;AAAA,UACJ;AAAA,UACA,SAAS,MAAM,QAAQ,EAAE;AAAA,UAExB;AAAA;AAAA,QATI;AAAA,MAUP,CACD,GACH;AAAA,MACA,oBAAC,SAAI,WAAU,gCACb,8BAAC,kBAAe,MAAM,SAAS,WAAW,IAAI,GAAG,UAAU,SAAS,UAAU,GAChF;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import {
|
|
3
|
-
AgentMetricChart
|
|
4
|
-
} from "./chunk-5I2COQNL.js";
|
|
5
|
-
import "./chunk-YQO2NMJ3.js";
|
|
6
|
-
import "./chunk-NHHSZB5N.js";
|
|
7
|
-
import "./chunk-H6WTY5PM.js";
|
|
8
|
-
import "./chunk-FQK2XVVE.js";
|
|
9
|
-
import "./chunk-M6MHLVSO.js";
|
|
10
|
-
import "./chunk-VJ7BZGAF.js";
|
|
11
|
-
import "./chunk-BWHOZFIV.js";
|
|
12
|
-
export {
|
|
13
|
-
AgentMetricChart
|
|
14
|
-
};
|
|
15
|
-
//# sourceMappingURL=AgentMetricChart-4FYECRIN.js.map
|
|
@@ -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 BarController,\n BarElement,\n Chart as ChartJS,\n LinearScale,\n PointElement,\n ScatterController,\n Tooltip,\n type ChartData,\n type ChartDataset,\n type ChartOptions,\n type Plugin,\n} from 'chart.js';\nimport { useCallback, useEffect, useMemo, useRef, useState, type ComponentType, type CSSProperties } from 'react';\nimport { Chart } from 'react-chartjs-2';\n\nimport { useThemeMode } from '../../theme/SlotsProvider.js';\nimport { roundDurationMsToSecond } from '../../utils/sessionDisplayFormat.js';\nimport {\n getSessionEventColor,\n getSessionEventHoverColor,\n getSessionEventLabel,\n MAIN_THREAD_ID,\n type SessionEventTimelineSegment,\n} from '../../utils/sessionEventTimeline.js';\nimport {\n buildTimelineAxisTicks,\n formatTimelineAxisDuration,\n getActiveTimelineMs,\n getSubAgentHoverGroups,\n getSubAgentLanes,\n getTimelineHoverTargetId,\n getTimelineLayout,\n getTimelineRange,\n groupCoincidentTimelineMarkers,\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 SessionMarkerGroupTooltip,\n SessionSubAgentGroupTooltip,\n SessionToolCallGroupTooltip,\n SessionTurnTooltip,\n} from './AgentSessionTimelineTooltip.js';\nimport type { AgentSessionEventTimelineChartProps } from './types.js';\n\nChartJS.register(BarController, BarElement, LinearScale, PointElement, ScatterController, 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 MARKER_EVENT_GAP_PX = 2;\nconst OVERHEAD_PX = 30;\n\ntype BarPoint = { x: [number, number]; y: number };\ntype MarkerPoint = { x: number; y: number };\ntype TimelineChartType = 'bar' | 'scatter';\n\nfunction rowCenters({ heights, gaps }: { heights: number[]; gaps: number[] }): { centers: number[]; band: number } {\n const centers: number[] = [];\n let offset = 0;\n heights.forEach((height, index) => {\n centers.push(offset + height / 2);\n offset += height + (gaps[index] ?? 0);\n });\n return { centers, band: offset };\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' : '#E0ECFD';\n const turnHover = isDark ? '#52525b' : '#E0ECFD';\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 segmentTotalMs = Math.max(0, ...segments.map(segment => segment.endMs));\n const activeTotalMs = Math.max(1, roundDurationMsToSecond(segmentTotalMs));\n const { turnStartsMs, turnOrdinals, turnRanges } = useMemo(() => getTimelineLayout(segments), [segments]);\n const activeTurnStartsMs = useMemo(\n () => turnStartsMs.filter((startMs, index) => index === 0 || startMs <= activeTotalMs),\n [activeTotalMs, turnStartsMs],\n );\n const gapCount = Math.max(0, activeTurnStartsMs.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 activeTurnStartsMs\n .slice(1)\n .map((startMs, index) => ({ startMs: startMs + index * turnGapMs, endMs: startMs + (index + 1) * turnGapMs })),\n [activeTurnStartsMs, turnGapMs],\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 markerGroups = useMemo(() => groupCoincidentTimelineMarkers(visibleSegments), [visibleSegments]);\n const durationSegments = useMemo(() => visibleSegments.filter(segment => !segment.isMarker), [visibleSegments]);\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 () => durationSegments.filter(segment => segment.type === 'sub_agent'),\n [durationSegments],\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: durationSegments, minWidthMs: MARKER_PX * msPerPx }),\n [durationSegments, msPerPx, subAgentSegments],\n );\n const mainCandidates = useMemo(() => {\n const kept = new Set(mainSubAgents.map(segment => segment.id));\n return durationSegments.filter(\n segment => segment.threadId === MAIN_THREAD_ID || (segment.type === 'sub_agent' && kept.has(segment.id)),\n );\n }, [durationSegments, mainSubAgents]);\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 markerRow = hasTurnRow ? 1 : 0;\n const eventRow = markerRow + 1;\n const { centers, band } = useMemo(() => {\n const heights = [...(hasTurnRow ? [16] : []), 10, 28, ...Array.from({ length: laneCount }, () => 12)];\n const gaps = heights.map((_, index) => {\n if (index === heights.length - 1) return 0;\n return index === markerRow ? MARKER_EVENT_GAP_PX : ROW_GAP_PX;\n });\n return rowCenters({ heights, gaps });\n }, [hasTurnRow, laneCount, markerRow]);\n\n const chartTargets = useMemo<Array<TimelineHoverTarget | null>>(\n () => [\n ...turnBars.map((bar): TimelineHoverTarget => ({ type: TIMELINE_TYPE.turn, bar })),\n ...markerGroups.map((group): TimelineHoverTarget => ({ type: TIMELINE_TYPE.markerGroup, group })),\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, markerGroups, 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<TimelineChartType, Array<BarPoint | MarkerPoint>, 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 ...markerGroups.map(group => {\n const type = group.segments.length === 1 ? group.segments[0]?.type : 'system';\n const color = getSessionEventColor(type ?? 'system', isDark);\n return {\n type: 'scatter' as const,\n label: group.segments.map(segment => getSessionEventLabel(segment.type)).join(', '),\n data: [{ x: group.startMs, y: centers[markerRow] ?? 0 }] satisfies MarkerPoint[],\n pointStyle: 'rectRot' as const,\n pointRadius: 5,\n pointHoverRadius: 6,\n clip: false,\n backgroundColor: color,\n hoverBackgroundColor: getSessionEventHoverColor(type ?? 'system', isDark),\n borderWidth: 0,\n order: 0,\n } satisfies ChartDataset<'scatter', MarkerPoint[]>;\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, isDark),\n hover: getSessionEventHoverColor(segment.type, isDark),\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, isDark),\n hover: getSessionEventHoverColor(segment.type, isDark),\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', isDark),\n hover: getSessionEventHoverColor('tool_call', isDark),\n thickness: 28,\n order: eventOrder('tool_call'),\n inflateAmount: 0.5,\n }),\n ),\n ],\n }),\n [\n centers,\n eventRow,\n isDark,\n mainEventSegments,\n markerGroups,\n markerRow,\n subAgentLanes,\n toolCallGroups,\n turnBars,\n turnFill,\n turnHover,\n ],\n );\n\n const turnLabelPlugin = useMemo<Plugin<TimelineChartType>>(\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<TimelineChartType>>(\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<TimelineChartType>>(\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({ activeTotalMs, turnStartsMs: activeTurnStartsMs, turnGapMs });\n },\n ticks: {\n color: axis,\n autoSkip: false,\n includeBounds: false,\n maxTicksLimit: 9,\n callback: value => {\n const timelineMs = Number(value);\n return timelineMs <= totalMs\n ? formatTimelineAxisDuration(getActiveTimelineMs(timelineMs, timelineGaps))\n : '';\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 [\n activeTotalMs,\n activeTurnStartsMs,\n axis,\n band,\n chartTargets,\n grid,\n onSelectTurn,\n refreshTooltipAnchor,\n timelineGaps,\n timelineMaxMs,\n totalMs,\n turnGapMs,\n ],\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.markerGroup ? (\n <SessionMarkerGroupTooltip 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 <Chart<TimelineChartType, Array<BarPoint | MarkerPoint>, string>\n type=\"bar\"\n data={chartData}\n options={chartOptions}\n plugins={[turnLabelPlugin, overheadPlugin]}\n />\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 { useThemeMode } from '../../theme/SlotsProvider.js';\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 {\n TimelineMarkerGroup,\n TimelineSubAgentGroup,\n TimelineToolCallGroup,\n} 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 const isDark = useThemeMode() === 'dark';\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, isDark) }}\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 SessionMarkerGroupTooltip({ group }: { group: TimelineMarkerGroup }) {\n const isDark = useThemeMode() === 'dark';\n const singleSegment = group.segments.length === 1 ? group.segments[0] : undefined;\n if (singleSegment != null) return <SessionEventTooltip segment={singleSegment} />;\n\n return (\n <div className=\"max-h-72 w-80 max-w-full overflow-auto text-xs\">\n <span className=\"font-medium text-text-secondary\">Events</span>\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 min-w-0 items-start gap-1.5 py-0.5\">\n <span\n className=\"mt-1 size-1.5 shrink-0 rounded-full\"\n style={{ backgroundColor: getSessionEventColor(segment.type, isDark) }}\n />\n <div className=\"min-w-0\">\n <div className=\"font-medium text-text-secondary\">{getSessionEventTooltipHeading(segment.type)}</div>\n <div className=\"wrap-break-word font-medium text-text-primary\">\n {segment.description.trim() || segment.title}\n </div>\n </div>\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 {group.segments.length === 1\n ? segment.description || segment.title\n : `Sub-agent ${index + 1}: ${segment.description || segment.title}`}\n </span>\n {group.segments.length === 1 ? null : (\n <span className=\"shrink-0 tabular-nums text-text-secondary\">\n {formatTimelineDuration(segment.endMs - segment.startMs)}\n </span>\n )}\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/atoms/agent-details/AgentSessions.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useRef, useState, type ComponentType } from 'react';\nimport { Group, Panel, Separator } from 'react-resizable-panels';\n\nimport { useSessionShareSearch } from '../../hooks/useSessionShareSearch.js';\nimport { Icon } from '../../icons/Icon.js';\nimport { buildSessionResumeHref } from '../../routing/paths.js';\nimport { useOptionalResolvedRoutes } from '../../routing/ResolvedRoutesContext.js';\nimport { useAgentSessionsServer, useServer } from '../../server/ServerContext.js';\nimport { useOptionalShellMode } from '../../server/ShellModeContext.js';\nimport type { Session, SessionEventItem, SessionListEntry } from '../../server/types.js';\nimport { useSlot } from '../../theme/SlotsProvider.js';\nimport { drainListPages } from '../../utils/drainListPages.js';\nimport { sessionTimeRangeFromCreatedAt } from '../../utils/sessionShareUrl.js';\nimport { EmptyScreen } from '../EmptyScreen.js';\nimport { cn } from '../lib/cn.js';\nimport { sessionIsCreateAgent } from '../lib/sessionCreateAgent.js';\nimport { Skeleton } from '../primitives/Skeleton.js';\nimport type { AgentSessionsProps } from './types.js';\n\nfunction sessionTitle(entry: Pick<SessionListEntry, 'title'>): string {\n const title = entry.title?.trim();\n return title != null && title.length > 0 ? title : 'Untitled session';\n}\n\nfunction entryIsMutable(entry: SessionListEntry): boolean {\n if ('isMutable' in entry && typeof Reflect.get(entry, 'isMutable') === 'boolean') {\n return Reflect.get(entry, 'isMutable') === true;\n }\n return entry.agentName == null;\n}\n\nexport function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }: AgentSessionsProps) {\n const sessionsServer = useAgentSessionsServer();\n const chatServer = useServer();\n const shell = useOptionalShellMode();\n const routes = useOptionalResolvedRoutes();\n const { sessionId: selectedSessionId, updateShareSearch } = useSessionShareSearch();\n\n const AgentSessionListRow = useSlot('AgentSessionListRow');\n const AgentSessionDetailHeader = useSlot('AgentSessionDetailHeader');\n const AgentSessionTimelineContainer = useSlot('AgentSessionTimelineContainer');\n\n const [entries, setEntries] = useState<SessionListEntry[]>([]);\n const [nextPageToken, setNextPageToken] = useState<string | undefined>();\n const [listLoading, setListLoading] = useState(true);\n const [listLoadingMore, setListLoadingMore] = useState(false);\n const [listFailed, setListFailed] = useState(false);\n const listRequestIdRef = useRef(0);\n const [detailEvents, setDetailEvents] = useState<SessionEventItem[]>();\n const [detailSession, setDetailSession] = useState<Session>();\n const [detailLoading, setDetailLoading] = useState(false);\n const [detailFailed, setDetailFailed] = useState(false);\n\n const listRequest = useMemo(\n () => ({\n order: 'desc' as const,\n limit: 20,\n ...(agentId == null || agentId.length === 0 ? {} : { agentId }),\n ...(startTimestamp == null ? {} : { startTimestamp }),\n ...(endTimestamp == null ? {} : { endTimestamp }),\n }),\n [agentId, endTimestamp, startTimestamp],\n );\n\n useEffect(() => {\n const requestId = ++listRequestIdRef.current;\n let cancelled = false;\n setListLoading(true);\n setListLoadingMore(false);\n setListFailed(false);\n void sessionsServer\n .listSessions(listRequest)\n .then(page => {\n if (cancelled || listRequestIdRef.current !== requestId) return;\n setEntries(page.data);\n setNextPageToken(page.nextPageToken);\n })\n .catch(() => {\n if (cancelled || listRequestIdRef.current !== requestId) return;\n setEntries([]);\n setNextPageToken(undefined);\n setListFailed(true);\n })\n .finally(() => {\n if (!cancelled && listRequestIdRef.current === requestId) setListLoading(false);\n });\n\n return () => {\n cancelled = true;\n };\n }, [listRequest, sessionsServer]);\n\n const loadMore = useCallback(async () => {\n if (nextPageToken == null || listLoadingMore) return;\n const requestId = listRequestIdRef.current;\n setListLoadingMore(true);\n try {\n const page = await sessionsServer.listSessions({ ...listRequest, pageToken: nextPageToken });\n if (listRequestIdRef.current !== requestId) return;\n setEntries(current => [...current, ...page.data]);\n setNextPageToken(page.nextPageToken);\n } catch {\n // Keep the current page and token visible so the user can retry.\n } finally {\n if (listRequestIdRef.current === requestId) setListLoadingMore(false);\n }\n }, [listLoadingMore, listRequest, nextPageToken, sessionsServer]);\n\n useEffect(() => {\n if (selectedSessionId == null || selectedSessionId.length === 0) {\n setDetailEvents(undefined);\n setDetailSession(undefined);\n setDetailFailed(false);\n setDetailLoading(false);\n return;\n }\n\n let cancelled = false;\n setDetailLoading(true);\n setDetailFailed(false);\n setDetailEvents(undefined);\n setDetailSession(undefined);\n\n void Promise.all([\n drainListPages({\n fetchPage: pageToken =>\n sessionsServer.listSessionEvents({\n sessionId: selectedSessionId,\n limit: 100,\n ...(pageToken == null ? {} : { pageToken }),\n }),\n }),\n chatServer.getSession({ sessionId: selectedSessionId }).catch(() => undefined),\n ])\n .then(([itemsNewestFirst, session]) => {\n if (cancelled) return;\n setDetailEvents([...itemsNewestFirst].reverse());\n setDetailSession(session);\n })\n .catch(() => {\n if (!cancelled) setDetailFailed(true);\n })\n .finally(() => {\n if (!cancelled) setDetailLoading(false);\n });\n\n return () => {\n cancelled = true;\n };\n }, [chatServer, selectedSessionId, sessionsServer]);\n\n const selectSession = (entry: SessionListEntry) => {\n const pinned = shareView === 'sessions' ? sessionTimeRangeFromCreatedAt(entry.createdAt) : null;\n updateShareSearch({\n sessionId: entry.id,\n ...(shareView === 'sessions'\n ? { view: 'sessions', ...(pinned == null ? {} : { timeRange: pinned }) }\n : { agentId: agentId ?? null, tab: 'sessions', view: null, timeRange: null }),\n });\n };\n\n const clearSelectedSession = () => {\n if (selectedSessionId == null) return;\n updateShareSearch({ sessionId: null });\n };\n\n const selectedEntry = entries.find(entry => entry.id === selectedSessionId);\n const selectedTitle =\n detailSession != null\n ? sessionTitle(detailSession)\n : selectedEntry != null\n ? sessionTitle(selectedEntry)\n : (selectedSessionId ?? 'Untitled session');\n\n const resumeIsCreateAgent =\n detailSession != null\n ? sessionIsCreateAgent(detailSession)\n : selectedEntry != null\n ? sessionIsCreateAgent(selectedEntry)\n : false;\n const resumeIsMutable =\n detailSession != null ? detailSession.isMutable : selectedEntry != null ? entryIsMutable(selectedEntry) : true;\n const resumeLabel = resumeIsCreateAgent ? 'Resume Agent building' : 'Resume Chat';\n const resumeHref =\n selectedSessionId != null && routes != null\n ? buildSessionResumeHref({ sessionId: selectedSessionId, routes })\n : null;\n\n const handleResume = () => {\n if (selectedSessionId == null || shell == null) return;\n const agentName = detailSession?.agentName ?? selectedEntry?.agentName;\n shell.openHistorySession({\n sessionId: selectedSessionId,\n isMutable: resumeIsMutable,\n isCreateAgent: resumeIsCreateAgent,\n ...(agentName != null && agentName.length > 0 ? { agentName } : {}),\n });\n };\n\n const resumeProps =\n resumeHref != null ? { resumeHref, resumeLabel } : shell != null ? { onResume: handleResume, resumeLabel } : {};\n\n // Full empty only when nothing is selected — keep the detail pane for deep-linked sessionIds\n // (filters/time range can empty the list while share state still points at a session).\n if (\n !listLoading &&\n !listFailed &&\n entries.length === 0 &&\n (selectedSessionId == null || selectedSessionId.length === 0)\n ) {\n return (\n <EmptyScreen\n title=\"No Sessions Found\"\n description=\"There are no sessions available at the moment.\"\n className=\"bg-primary-bg\"\n />\n );\n }\n\n return (\n <Group\n id=\"agent-sessions-split\"\n orientation=\"horizontal\"\n className=\"h-full min-h-0 w-full\"\n resizeTargetMinimumSize={{ coarse: 24, fine: 11 }}\n >\n <Panel id=\"agent-sessions-list\" defaultSize=\"35%\" minSize=\"20%\" maxSize=\"50%\">\n <aside className=\"flex h-full min-h-0 w-full flex-col bg-sidebar-bg\">\n <div className=\"scrollbar-none min-h-0 flex-1 overflow-y-auto\">\n {listLoading ? (\n <div className=\"space-y-2 p-3\" role=\"status\" aria-label=\"Loading sessions\">\n {['a', 'b', 'c'].map(key => (\n <Skeleton key={key} className=\"h-16 rounded-md\" />\n ))}\n </div>\n ) : listFailed ? (\n <p className=\"px-3 py-6 text-center text-xs text-text-secondary\">Sessions could not be loaded.</p>\n ) : (\n entries.map(entry => (\n <AgentSessionListRow\n key={entry.id}\n title={sessionTitle(entry)}\n agentName={entry.agentName ?? undefined}\n lastActivityAt={entry.lastActivityAt}\n metrics={entry.metrics}\n active={entry.id === selectedSessionId}\n onSelect={() => selectSession(entry)}\n />\n ))\n )}\n </div>\n\n {nextPageToken != null && !listLoading ? (\n <div className=\"shrink-0 border-t border-border p-3\">\n <button\n type=\"button\"\n disabled={listLoadingMore}\n onClick={() => void loadMore()}\n className=\"h-8 w-full rounded-md border border-border text-xs font-medium text-text-primary hover:bg-ghost-button-hover disabled:opacity-60\"\n >\n {listLoadingMore ? 'Loading…' : 'Load more'}\n </button>\n </div>\n ) : null}\n </aside>\n </Panel>\n\n <Separator\n id=\"agent-sessions-resizer\"\n aria-label=\"Resize session list\"\n className=\"group/resizer relative z-10 w-0 cursor-col-resize focus-visible:outline-none\"\n >\n <div aria-hidden className=\"absolute inset-y-0 -left-1.25 w-2.75\" />\n <div aria-hidden className=\"absolute inset-y-0 left-0 w-px bg-border transition-colors\" />\n <div\n aria-hidden\n className={cn(\n 'absolute top-1/2 left-0 z-10 flex h-4 w-2 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-xs shadow-sm transition-colors',\n 'bg-secondary-button-bg text-text-secondary',\n 'group-hover/resizer:bg-primary-button-bg group-hover/resizer:text-primary-button-text',\n 'group-active/resizer:bg-primary-button-bg group-active/resizer:text-primary-button-text',\n 'group-focus-visible/resizer:bg-primary-button-bg group-focus-visible/resizer:text-primary-button-text',\n )}\n >\n <Icon name=\"grip-vertical\" size={10} />\n </div>\n </Separator>\n\n <Panel id=\"agent-session-detail\" defaultSize=\"65%\" minSize=\"30%\">\n <section className=\"flex h-full min-w-0 flex-col bg-primary-bg\">\n {selectedSessionId == null ? (\n <div className=\"flex flex-1 items-center justify-center px-6 text-sm text-text-secondary\">\n Select a session to view details\n </div>\n ) : detailFailed ? (\n <div className=\"flex flex-1 items-center justify-center px-6 text-sm text-text-secondary\">\n Session details could not be loaded.\n </div>\n ) : (\n <>\n <AgentSessionDetailHeader\n title={selectedTitle}\n sessionId={selectedSessionId}\n agentId={agentId}\n createdAt={detailSession?.createdAt ?? selectedEntry?.createdAt}\n view={shareView}\n onClose={clearSelectedSession}\n {...resumeProps}\n />\n {detailLoading || detailEvents === undefined ? (\n <div className=\"flex flex-1 flex-col p-4\" role=\"status\" aria-label=\"Loading session details\">\n <Skeleton className=\"min-h-64 flex-1 rounded-lg\" />\n </div>\n ) : (\n <AgentSessionTimelineContainer\n sessionId={selectedSessionId}\n events={detailEvents}\n listMetrics={selectedEntry?.metrics}\n />\n )}\n </>\n )}\n </section>\n </Panel>\n </Group>\n );\n}\n\ndeclare module '../../theme/SlotsProvider.js' {\n interface AtomSlots {\n AgentSessions: ComponentType<AgentSessionsProps>;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -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.Secondary\n size=\"small\"\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.Secondary>\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.Secondary\n size=\"small\"\n type=\"button\"\n disabled={busy}\n onClick={() => {\n handleConnect(entry);\n }}\n >\n {entry.auth.type === 'dcr' ? 'Add' : 'Connect'}\n </Button.Secondary>\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.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.Secondary>\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.Ghost type=\"button\" onClick={closeApiKeyModal} disabled={busy}>\n Cancel\n </Button.Ghost>\n <Button.Primary type=\"submit\" disabled={!apiKey.trim() || busy}>\n {isReplacingKey ? 'Replace Key' : 'Connect'}\n </Button.Primary>\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.Primary type=\"submit\" size=\"large\" disabled={!isValid || busy} className=\"w-full shrink-0\">\n Add\n </Button.Primary>\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.Secondary\n size=\"small\"\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.Secondary>\n ) : connector.auth.type === 'dcr' && !connector.requiresAuth ? (\n <Button.Secondary size=\"small\" type=\"button\" disabled={busy} onClick={onDisconnect}>\n Disconnect\n </Button.Secondary>\n ) : null}\n </header>\n\n <section className=\"mt-6\" aria-labelledby=\"connector-tools-heading\">\n {toolsLoading ? (\n <div className=\"rounded-xl border border-dashed border-border p-6 text-center text-sm text-text-secondary\">\n Loading tools…\n </div>\n ) : toolsError ? (\n <div className=\"rounded-xl border border-failure-bg/30 bg-failure-bg/10 p-6 text-center text-sm text-failure-bg\">\n {toolsError}\n {connector.auth.type === 'dcr' && !connector.authenticated && (\n <div className=\"font-bold mt-1\">Click Connect and authenticate successfully to view tools.</div>\n )}\n </div>\n ) : tools.length > 0 ? (\n <>\n <h5 id=\"connector-tools-heading\" className=\"mb-2 text-[0.8125rem] font-semibold text-text-primary\">\n Tools <span className=\"font-normal text-text-secondary\">· {tools.length}</span>\n </h5>\n <div className=\"overflow-hidden rounded-xl border border-border bg-card-bg\">\n {tools.map(tool => (\n <article\n key={tool.id}\n className=\"flex min-h-12 items-start gap-3 border-b border-border px-3 py-2 last:border-b-0\"\n >\n <div className=\"min-w-0 flex-1\">\n <h6 className=\"text-sm font-medium text-text-primary\">{tool.name}</h6>\n <ExpandableDescription text={tool.description} />\n </div>\n </article>\n ))}\n </div>\n </>\n ) : (\n <div className=\"rounded-xl border border-dashed border-border p-6 text-center text-sm text-text-secondary\">\n No tools reported for this connector.\n </div>\n )}\n </section>\n </div>\n </div>\n );\n};\n\nexport default ConnectorDetails;\n"],"mappings":"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","names":["useEffect","useState","useState","Fragment","jsx","jsxs","useState","Fragment","jsx","jsxs","useState","useEffect"]}
|
|
@@ -1 +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: 'small' })}\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,15 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import {
|
|
3
|
-
SchedulesPage
|
|
4
|
-
} from "./chunk-GXYAOAK5.js";
|
|
5
|
-
import "./chunk-YQO2NMJ3.js";
|
|
6
|
-
import "./chunk-NHHSZB5N.js";
|
|
7
|
-
import "./chunk-H6WTY5PM.js";
|
|
8
|
-
import "./chunk-FQK2XVVE.js";
|
|
9
|
-
import "./chunk-M6MHLVSO.js";
|
|
10
|
-
import "./chunk-VJ7BZGAF.js";
|
|
11
|
-
import "./chunk-BWHOZFIV.js";
|
|
12
|
-
export {
|
|
13
|
-
SchedulesPage
|
|
14
|
-
};
|
|
15
|
-
//# sourceMappingURL=SchedulesPage-WQU4H25F.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routing/ShellRouteSync.tsx","../src/routing/derivePlace.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\nimport { useLocation, useNavigate } from 'react-router-dom';\n\nimport { sessionIsCreateAgent } from '../atoms/lib/sessionCreateAgent.js';\nimport {\n useOptionalAgentSessionsServer,\n useOptionalCatalogServer,\n useOptionalScheduleServer,\n useOptionalServer,\n useServerCapabilities,\n} from '../server/ServerContext.js';\nimport { useShellMode } from '../server/ShellModeContext.js';\nimport { toEffectiveRoutes } from '../server/serverChrome.js';\nimport { deriveChatPlace, derivePlace } from './derivePlace.js';\nimport { buildPath, matchLocation, placesEqual, sanitizeSearchForPlace } from './paths.js';\nimport type { ResolvedRoutes, RoutePlace, ShellSnapshot } from './types.js';\n\n/**\n * Single bidirectional bridge between shell state and the URL. Mounted under\n * `ShellModeProvider` but outside the keyed chat runtime so boot applies once.\n */\nexport function ShellRouteSync({\n routes,\n activeRemoteId,\n initialSettingsOpen,\n}: {\n routes: ResolvedRoutes;\n activeRemoteId: string | undefined;\n initialSettingsOpen: boolean;\n}) {\n const shell = useShellMode();\n const server = useOptionalServer();\n const catalog = useOptionalCatalogServer();\n const sessions = useOptionalAgentSessionsServer();\n const schedules = useOptionalScheduleServer();\n const capabilities = useServerCapabilities();\n const navigate = useNavigate();\n const location = useLocation();\n // Same gates as sidebar chrome: missing optional ports unregister their paths.\n const effectiveRoutes = useMemo(\n () => toEffectiveRoutes({ routes, catalog, capabilities, sessions, schedules }),\n [routes, catalog, capabilities, sessions, schedules],\n );\n const settingsChromeEnabled = effectiveRoutes.settings != null;\n // Gate identity only — avoid re-syncing when capabilities object identity churns\n // without changing which paths are registered (would clobber window share query).\n const routeGatesKey = [\n effectiveRoutes.settings,\n effectiveRoutes.sessionsBrowser,\n effectiveRoutes.libraryAgent,\n effectiveRoutes.schedules,\n ].join('\\0');\n\n const snapshot: ShellSnapshot = {\n settingsOpen: shell.settingsOpen,\n libraryOpen: shell.libraryOpen,\n sessionsOpen: shell.sessionsOpen,\n libraryAgentId: shell.libraryAgentId,\n schedulesOpen: shell.schedulesOpen,\n pendingSessionId: shell.pendingSessionId,\n activeRemoteId,\n mode: shell.mode,\n agentConfigMode: shell.agentConfigMode,\n };\n\n const place = derivePlace(snapshot);\n const placeKey = JSON.stringify(place);\n\n // Guards. `selfNavPathRef` marks a path we navigated to ourselves so the\n // URL->shell effect does not re-apply it. `prevPlaceRef` powers push/replace.\n const selfNavPathRef = useRef<string | null>(null);\n const prevPlaceRef = useRef<RoutePlace | null>(null);\n const bootedRef = useRef(false);\n // Latest session id the URL asked for, so slower lookups cannot bind over it.\n const requestedSessionRef = useRef<string | null>(null);\n // Boot owns the first URL; the ongoing effects skip their initial commit so\n // they do not fight boot with the stale first-render place.\n const shellSyncStartedRef = useRef(false);\n const urlSyncStartedRef = useRef(false);\n\n /**\n * A URL carries only the id, so ask the server whether it names a mutable\n * draft or an agent chat; guessing \"mutable\" opens an agent session as a\n * blank draft. `requestedSessionRef` drops replies a later place superseded.\n */\n const openSession = useCallback(\n (sessionId: string) => {\n requestedSessionRef.current = sessionId;\n if (server == null) {\n shell.openHistorySession({ sessionId });\n return;\n }\n void server\n .getSession({ sessionId })\n .then(session => {\n if (requestedSessionRef.current !== sessionId) return;\n shell.openHistorySession({\n sessionId,\n isMutable: session.isMutable,\n isCreateAgent: sessionIsCreateAgent(session),\n ...(session.agentName != null ? { agentName: session.agentName } : {}),\n });\n })\n .catch(() => {\n if (requestedSessionRef.current !== sessionId) return;\n // Unreachable session: bind by id alone rather than stranding the shell.\n shell.openHistorySession({ sessionId });\n });\n },\n [server, shell],\n );\n\n const applyPlace = useCallback(\n (target: RoutePlace) => {\n switch (target.type) {\n case 'settings':\n shell.setSettingsOpen(true);\n return;\n case 'library':\n shell.setLibraryOpen(true);\n return;\n case 'sessionsBrowser':\n shell.setSessionsOpen(true);\n return;\n case 'libraryAgent':\n shell.openLibraryAgent(target.agentId);\n return;\n case 'schedules':\n shell.setSchedulesOpen(true);\n return;\n case 'session':\n shell.setLibraryOpen(false);\n if (shell.pendingSessionId === target.sessionId || activeRemoteId === target.sessionId) return;\n openSession(target.sessionId);\n return;\n case 'agent':\n shell.setLibraryOpen(false);\n shell.selectLibraryAgent({ isMutable: false, agentName: target.agentName });\n return;\n case 'root':\n shell.setSettingsOpen(false);\n shell.setLibraryOpen(false);\n shell.setSchedulesOpen(false);\n switch (shell.agentConfigMode) {\n case 'AgentLibrary':\n shell.openLibraryHome();\n return;\n case 'AgentComposer':\n case 'AgentLibraryWithComposer':\n shell.openDraft();\n return;\n case 'SingleAgent':\n shell.clearChat();\n return;\n }\n }\n },\n [shell, activeRemoteId, openSession],\n );\n\n // Boot: URL wins, except an explicit `initialSettingsOpen` overlay. Boot is the\n // sole authority for the first commit and sets the final URL + `prevPlaceRef`.\n useEffect(() => {\n if (bootedRef.current) return;\n bootedRef.current = true;\n\n const urlPlace = matchLocation({\n pathname: location.pathname,\n search: location.search,\n routes: effectiveRoutes,\n }) ?? { type: 'root' };\n const settingsOnBoot = settingsChromeEnabled && (initialSettingsOpen || urlPlace.type === 'settings');\n\n if (urlPlace.type === 'settings') {\n if (settingsChromeEnabled) shell.setSettingsOpen(true);\n } else if (urlPlace.type === 'library') {\n shell.setLibraryOpen(true);\n } else if (urlPlace.type === 'sessionsBrowser') {\n shell.setSessionsOpen(true);\n } else if (urlPlace.type === 'libraryAgent') {\n shell.openLibraryAgent(urlPlace.agentId);\n } else if (urlPlace.type === 'schedules') {\n shell.setSchedulesOpen(true);\n } else {\n const chatPlace = deriveChatPlace(snapshot);\n if (!placesEqual(chatPlace, urlPlace)) applyPlace(urlPlace);\n if (settingsOnBoot) shell.setSettingsOpen(true);\n }\n\n const desiredPlace: RoutePlace = settingsOnBoot ? { type: 'settings' } : urlPlace;\n const desiredPath = buildPath(desiredPlace, effectiveRoutes);\n const desiredSearch = sanitizeSearchForPlace(desiredPlace, location.search);\n prevPlaceRef.current = desiredPlace;\n if (desiredPath != null && (desiredPath !== location.pathname || desiredSearch !== location.search)) {\n selfNavPathRef.current = desiredPath !== location.pathname ? desiredPath : null;\n navigate({ pathname: desiredPath, search: desiredSearch, hash: location.hash }, { replace: true });\n }\n // Boot runs once; snapshot is read imperatively here.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Shell -> URL: mirror the derived place. Skip the first commit (boot owns it).\n useEffect(() => {\n if (!bootedRef.current) return;\n if (!shellSyncStartedRef.current) {\n shellSyncStartedRef.current = true;\n return;\n }\n const target = buildPath(place, effectiveRoutes);\n if (target == null) return; // place has no configured URL (e.g. settings disabled)\n const basename = effectiveRoutes.basename.endsWith('/')\n ? effectiveRoutes.basename.slice(0, -1)\n : effectiveRoutes.basename;\n const browserPathname = `${basename}${location.pathname}` || '/';\n const latestSearch = window.location.pathname === browserPathname ? window.location.search : location.search;\n const targetSearch = sanitizeSearchForPlace(place, latestSearch);\n\n const prev = prevPlaceRef.current;\n prevPlaceRef.current = place;\n\n if (target === location.pathname && targetSearch === location.search) return;\n\n // Replace when a fresh chat just acquired its session id (same place, new id).\n const replace =\n place.type === 'session' && shell.pendingSessionId == null && prev != null && prev.type !== 'session';\n\n selfNavPathRef.current = target !== location.pathname ? target : null;\n // Query keys owned by other shell places are removed; host keys and hash survive.\n navigate({ pathname: target, search: targetSearch, hash: location.hash }, { replace });\n // location.pathname intentionally excluded: only react to shell-derived place changes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [placeKey, routeGatesKey]);\n\n // URL -> shell: apply on genuine location changes (Back/Forward, manual edits).\n useEffect(() => {\n if (!bootedRef.current) return;\n if (!urlSyncStartedRef.current) {\n urlSyncStartedRef.current = true;\n return;\n }\n if (selfNavPathRef.current === location.pathname) {\n selfNavPathRef.current = null;\n return;\n }\n const urlPlace = matchLocation({\n pathname: location.pathname,\n search: location.search,\n routes: effectiveRoutes,\n });\n if (urlPlace == null) {\n // Unknown path: normalize to root.\n const rootPath = effectiveRoutes.root;\n const rootSearch = sanitizeSearchForPlace({ type: 'root' }, location.search);\n selfNavPathRef.current = rootPath;\n navigate({ pathname: rootPath, search: rootSearch, hash: location.hash }, { replace: true });\n applyPlace({ type: 'root' });\n return;\n }\n if (urlPlace.type !== 'settings' && shell.settingsOpen) {\n // Leaving settings via Back to a chat place.\n shell.setSettingsOpen(false);\n }\n if (urlPlace.type !== 'library' && urlPlace.type !== 'libraryAgent' && shell.libraryOpen) {\n shell.setLibraryOpen(false);\n }\n if (urlPlace.type !== 'sessionsBrowser' && shell.sessionsOpen) {\n shell.setSessionsOpen(false);\n }\n if (urlPlace.type !== 'schedules' && shell.schedulesOpen) {\n // Leaving schedules via Back to a chat place.\n shell.setSchedulesOpen(false);\n }\n applyPlace(urlPlace);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [location.pathname]);\n\n return null;\n}\n","import type { RoutePlace, ShellSnapshot } from './types.js';\n\n/**\n * The chat place implied by shell state, ignoring settings, schedules,\n * sessions-browser, and library overlays.\n * SingleAgent canonicalizes to `root` so `/` and `/agents/{name}` alias.\n */\nexport function deriveChatPlace(snapshot: ShellSnapshot): RoutePlace {\n // The live thread wins: reusing a mutable shell switches thread without a\n // remount, leaving `pendingSessionId` on the session the shell last opened.\n // It only leads while a requested session has not reported its thread yet.\n const sessionId = snapshot.activeRemoteId ?? snapshot.pendingSessionId;\n if (sessionId != null) return { type: 'session', sessionId };\n\n const { mode, agentConfigMode } = snapshot;\n if (mode.status === 'active' && !mode.isMutable && agentConfigMode !== 'SingleAgent') {\n const agentName = mode.agentName ?? mode.agentId;\n if (agentName != null) return { type: 'agent', agentName };\n }\n return { type: 'root' };\n}\n\n/** Full place with overlay priority: settings, schedules, sessions, library, chat. */\nexport function derivePlace(snapshot: ShellSnapshot): RoutePlace {\n if (snapshot.settingsOpen) return { type: 'settings' };\n if (snapshot.schedulesOpen) return { type: 'schedules' };\n if (snapshot.sessionsOpen) return { type: 'sessionsBrowser' };\n if (snapshot.libraryOpen && snapshot.libraryAgentId != null) {\n return { type: 'libraryAgent', agentId: snapshot.libraryAgentId };\n }\n if (snapshot.libraryOpen) return { type: 'library' };\n return deriveChatPlace(snapshot);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/layouts/SidebarLayout.tsx"],"sourcesContent":["'use client';\n\nimport {\n lazy,\n Suspense,\n useEffect,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type ReactNode,\n type Ref,\n} from 'react';\n\nimport { useAui } from '../assistant-ui.js';\nimport { auiButtonClass, sidebarRailButtonClassName } from '../atoms/lib/buttonClasses.js';\nimport { cn } from '../atoms/lib/cn.js';\nimport { useIsMobile } from '../atoms/lib/useIsMobile.js';\nimport { NamedAgentHeaderLabel } from '../atoms/NamedAgentHeaderLabel.js';\nimport { PageHeader } from '../atoms/PageHeader.js';\nimport { Spinner } from '../atoms/primitives/Spinner.js';\nimport { ShellActions } from '../atoms/ShellActions.js';\nimport { AgentConfigDrawerContainer } from '../containers/AgentConfigDrawerContainer.js';\nimport { Thread } from '../containers/Thread.js';\nimport { useChatHeaderContentVisible } from '../hooks/useChatChromeActionsVisible.js';\nimport { Icon } from '../icons/Icon.js';\nimport { shellIsCreateAgent, useOptionalShellMode } from '../server/ShellModeContext.js';\nimport { resolveBrandChrome } from '../theme/brand.js';\nimport { useSlot } from '../theme/SlotsProvider.js';\nimport { useBrand } from '../theme/ThemeProvider.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\nconst brandLogoClassName = 'h-5 w-5 max-w-40 shrink-0 object-contain';\nconst railWidthClassName = 'w-18';\n\nconst railActionButtonClassName = cn(sidebarRailButtonClassName, 'text-sidebar-text');\n\nconst railSelectedClassName =\n 'bg-primary-button-bg font-medium text-primary-button-text hover:bg-primary-button-hover hover:text-primary-button-text';\n\nfunction SidebarNav(): ReactNode {\n const aui = useAui();\n const shell = useOptionalShellMode();\n const AgentsLibraryButton = useSlot('AgentsLibraryButton');\n const SessionsBrowserButton = useSlot('SessionsBrowserButton');\n const SchedulesButton = useSlot('SchedulesButton');\n const showNewActions = shell?.isNewChatEnabled !== false;\n const overlayOpen =\n shell?.settingsOpen === true ||\n shell?.libraryOpen === true ||\n shell?.sessionsOpen === true ||\n shell?.schedulesOpen === true;\n const mode = shell?.mode;\n const newChatSelected = !overlayOpen && mode?.status === 'active' && mode.isMutable && !mode.isCreateAgent;\n const newAgentSelected = !overlayOpen && mode != null && shellIsCreateAgent(mode);\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 <nav className=\"flex min-h-0 flex-1 flex-col items-center gap-1 p-1\" aria-label=\"Sidebar\">\n {showNewActions ? (\n <button\n type=\"button\"\n aria-label=\"Start new chat\"\n title=\"New chat\"\n aria-current={newChatSelected ? 'page' : undefined}\n className={auiButtonClass({\n variant: 'ghost',\n className: cn(railActionButtonClassName, newChatSelected && railSelectedClassName),\n })}\n onClick={handleNewChat}\n >\n <Icon name=\"square-pen\" size={14} />\n <span className=\"text-center\">New Chat</span>\n </button>\n ) : null}\n {showNewActions && shell?.isComposerEnabled ? (\n <button\n type=\"button\"\n aria-label=\"Start new agent\"\n title=\"New Agent\"\n aria-current={newAgentSelected ? 'page' : undefined}\n className={auiButtonClass({\n variant: 'ghost',\n className: cn(railActionButtonClassName, newAgentSelected && railSelectedClassName),\n })}\n onClick={handleNewAgent}\n >\n <Icon name=\"agent-2\" size={14} />\n <span className=\"text-center\">New Agent</span>\n </button>\n ) : null}\n <AgentsLibraryButton compact />\n <SessionsBrowserButton compact />\n <SchedulesButton compact />\n </nav>\n );\n}\n\n/** Shared desktop + mobile icon+label rail (brand, nav, footer actions). */\nfunction SidebarRail({\n onNavigate,\n className,\n railRef,\n ...dialogProps\n}: {\n onNavigate?: () => void;\n className?: string;\n railRef?: Ref<HTMLElement>;\n} & Omit<ComponentPropsWithoutRef<'aside'>, 'children' | 'className'>): ReactNode {\n const brand = useBrand();\n const chrome = resolveBrandChrome(brand);\n const BrandLogo = useSlot('BrandLogo');\n\n return (\n <aside\n ref={railRef}\n className={cn(\n railWidthClassName,\n 'flex min-h-0 shrink-0 flex-col border-r border-border bg-sidebar-bg',\n className,\n )}\n onClick={event => {\n if (onNavigate == null) return;\n const target = event.target;\n if (!(target instanceof Element)) return;\n if (target.closest('button') != null) onNavigate();\n }}\n {...dialogProps}\n >\n <div className=\"flex h-14 w-full shrink-0 items-center justify-center text-text-primary\">\n <BrandLogo variant={chrome.collapsedVariant} className={brandLogoClassName} />\n </div>\n <SidebarNav />\n <footer className=\"flex shrink-0 flex-col items-center border-border p-2\">\n <ShellActions labeled className=\"flex-col\" />\n </footer>\n </aside>\n );\n}\n\nexport function SidebarLayout({ className }: { className?: string }) {\n const shell = useOptionalShellMode();\n const isMobile = useIsMobile();\n const AgentDetailsPage = useSlot('AgentDetailsPage');\n const AgentsLibrary = useSlot('AgentsLibrary');\n const SessionsPage = useSlot('SessionsPage');\n const ClearChatButton = useSlot('ClearChatButton');\n const SaveAgentButton = useSlot('SaveAgentButton');\n const SelectAgentEmptyState = useSlot('SelectAgentEmptyState');\n const [mobileNavOpen, setMobileNavOpen] = useState(false);\n const menuBtnRef = useRef<HTMLButtonElement>(null);\n const dialogRef = useRef<HTMLElement>(null);\n const mainRef = useRef<HTMLDivElement>(null);\n const wasOpen = useRef(false);\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 hasChatHeaderContent = useChatHeaderContentVisible();\n\n useEffect(() => {\n if (!mobileNavOpen) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') setMobileNavOpen(false);\n };\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [mobileNavOpen]);\n\n useEffect(() => {\n const main = mainRef.current;\n if (mobileNavOpen) {\n wasOpen.current = true;\n if (main) main.inert = true;\n dialogRef.current?.focus();\n return;\n }\n if (wasOpen.current) {\n if (main) main.inert = false;\n menuBtnRef.current?.focus();\n wasOpen.current = false;\n }\n }, [mobileNavOpen]);\n\n return (\n <div className={cn('relative flex h-full min-h-0 w-full min-w-0', className)}>\n <SidebarRail className=\"hidden md:flex\" />\n\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 bg-primary-bg\">\n {/* Desktop keeps shell chrome in the rail footer (always mounted, including\n when visually hidden on small screens so host action-slot state persists).\n Mobile reaches theme/settings via the nav drawer rail. */}\n <PageHeader\n className={cn(\n 'bg-topbar-bg',\n // Desktop: hide when settings/idle or the thread header has nothing to show\n // (empty untitled draft). Mobile still needs the menu button.\n // Builder mode keeps New Agent and its actions beside the persistent config.\n (overlayOpen || isIdle || !hasChatHeaderContent) && 'md:hidden',\n )}\n start={\n !overlayOpen ? (\n <button\n ref={menuBtnRef}\n type=\"button\"\n aria-label=\"Navigation\"\n aria-expanded={mobileNavOpen}\n className={cn(auiButtonClass({ variant: 'ghost', size: 'icon' }), 'md:hidden')}\n onClick={() => setMobileNavOpen(true)}\n >\n <Icon name=\"bars\" />\n </button>\n ) : null\n }\n title={!overlayOpen ? <NamedAgentHeaderLabel /> : null}\n end={\n !overlayOpen ? (\n <>\n <ClearChatButton />\n <SaveAgentButton />\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 onSelectAgent={() => setMobileNavOpen(false)} />\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\n {/* Mobile: same narrow rail as desktop */}\n {mobileNavOpen ? (\n <>\n <button\n type=\"button\"\n aria-label=\"Close navigation\"\n className=\"absolute inset-0 z-[9] cursor-pointer bg-[var(--overlay)] md:hidden\"\n onClick={() => setMobileNavOpen(false)}\n />\n <SidebarRail\n railRef={dialogRef}\n role=\"dialog\"\n aria-label=\"Navigation\"\n tabIndex={-1}\n onNavigate={() => setMobileNavOpen(false)}\n className=\"absolute inset-y-0 left-0 z-10 shadow-lg outline-none md:hidden\"\n />\n </>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/containers/SettingsBuilder/SkillSettings.tsx","../src/containers/SettingsBuilder/ImportGithubSkillForm.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useState, type ReactNode } from 'react';\n\nimport { Button } from '@/atoms/primitives/Button.js';\nimport SearchInput from '@/atoms/primitives/SearchInput.js';\nimport { Icon } from '@/icons/Icon.js';\nimport { useCatalogServer } from '../../server/ServerContext.js';\nimport type { RegistrySkill, SkillBase, SkillCatalogEntry, SkillConfigBase } from '../../server/types.js';\nimport { getErrorMessage } from '../../utils/getErrorMessage.js';\nimport { useToasterOptional } from '../ToasterContainer.js';\nimport ImportGithubSkillForm from './ImportGithubSkillForm.js';\n\nconst matchesQuery = (query: string, name: string, description: string) =>\n !query || name.toLowerCase().includes(query) || description.toLowerCase().includes(query);\n\nconst isRegistrySkill = (skill: SkillBase): skill is RegistrySkill => 'catalogId' in skill;\n\nconst SkillSettings = () => {\n const { skillCatalog } = useCatalogServer();\n const toaster = useToasterOptional();\n\n const [query, setQuery] = useState('');\n const [skills, setSkills] = useState<SkillBase[]>([]);\n const [catalog, setCatalog] = useState<SkillCatalogEntry[]>([]);\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 const [importOpen, setImportOpen] = useState(false);\n\n const refresh = useCallback(async () => {\n if (!skillCatalog) return;\n setLoading(true);\n setError(null);\n try {\n const [defined, available] = await Promise.all([skillCatalog.listSkills(), skillCatalog.getSkillCatalog()]);\n setSkills(defined);\n setCatalog(available);\n } catch (err) {\n setError(getErrorMessage(err, 'Failed to load skills'));\n } finally {\n setLoading(false);\n }\n }, [skillCatalog]);\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n const normalizedQuery = query.trim().toLowerCase();\n\n const selectedSkills = useMemo(\n () => skills.filter(skill => matchesQuery(normalizedQuery, skill.name, skill.description)),\n [skills, normalizedQuery],\n );\n\n const availableSkills = useMemo(() => {\n const selectedCatalogIds = new Set(skills.flatMap(skill => (isRegistrySkill(skill) ? [skill.catalogId] : [])));\n return catalog.filter(\n entry => !selectedCatalogIds.has(entry.id) && matchesQuery(normalizedQuery, entry.name, entry.description),\n );\n }, [catalog, skills, normalizedQuery]);\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 if (!skillCatalog) {\n return <p className=\"text-sm text-text-secondary\">Skills catalog is not available.</p>;\n }\n\n const handleSelect = (entry: SkillCatalogEntry) => {\n void runMutation(async () => {\n await skillCatalog.createSkill({\n catalogId: entry.id,\n name: entry.name,\n description: entry.description,\n repoURL: entry.repoURL,\n path: entry.path,\n ref: entry.ref,\n });\n }).catch(() => {});\n };\n\n const handleRemove = (skill: SkillBase) => {\n const deleteSkill = skillCatalog.deleteSkill;\n if (!deleteSkill) return;\n void runMutation(async () => {\n await deleteSkill({ id: skill.id });\n }).catch(() => {});\n };\n\n const handleImport = async (draft: SkillConfigBase) => {\n setFormError(null);\n await runMutation(async () => {\n await skillCatalog.createSkill(draft);\n }, setFormError);\n setTimeout(() => {\n toaster?.showSuccess({ title: `${draft.name} imported` });\n }, 0);\n };\n\n const renderRow = ({\n key,\n name,\n description,\n action,\n }: {\n key: string;\n name: string;\n description: string;\n action: ReactNode;\n }) => (\n <article key={key} className=\"flex min-h-16 items-center gap-3 border-b border-border p-3 last:border-b-0\">\n <span\n className=\"flex size-9 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg\"\n aria-hidden\n >\n <Icon name=\"lightbulb\" className=\"size-4.5 text-text-primary\" />\n </span>\n\n <div className=\"min-w-0 flex-1\">\n <h5 className=\"truncate text-sm font-medium text-text-primary\">{name}</h5>\n {description ? <p className=\"mt-0.5 truncate text-sm text-text-secondary\">{description}</p> : null}\n </div>\n\n {action}\n </article>\n );\n\n const hasMatches = selectedSkills.length > 0 || availableSkills.length > 0;\n\n return (\n <>\n <h3 className=\"text-xl font-semibold tracking-tight text-text-primary\">Skills</h3>\n <p className=\"mt-1 text-sm text-text-secondary\">Use built-in skills or import custom skills from GitHub.</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 min-h-0 flex-1 flex-col gap-3\">\n <div className=\"flex flex-col gap-2 sm:flex-row\">\n <div className=\"min-w-0 flex-1\">\n <SearchInput query={query} setQuery={setQuery} placeholder=\"Search skills\" />\n </div>\n <Button.Secondary\n type=\"button\"\n className=\"shrink-0\"\n disabled={busy}\n onClick={() => {\n setFormError(null);\n setImportOpen(true);\n }}\n >\n <Icon name=\"github\" className=\"size-4\" />\n Import from GitHub\n </Button.Secondary>\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 && selectedSkills.length > 0 ? (\n <section aria-labelledby=\"enabled-skills-heading\">\n <h4\n id=\"enabled-skills-heading\"\n className=\"mb-2 text-[0.8125rem] font-semibold uppercase text-text-secondary\"\n >\n Enabled · {selectedSkills.length}\n </h4>\n <div className=\"overflow-hidden rounded-xl border border-border bg-card-bg\">\n {selectedSkills.map(skill =>\n renderRow({\n key: skill.id,\n name: skill.name,\n description: skill.description,\n action: skillCatalog.deleteSkill ? (\n <Button.Secondary\n size=\"small\"\n type=\"button\"\n disabled={busy}\n aria-label={`Remove ${skill.name}`}\n onClick={() => {\n handleRemove(skill);\n }}\n >\n Remove\n </Button.Secondary>\n ) : null,\n }),\n )}\n </div>\n </section>\n ) : null}\n\n {!loading && availableSkills.length > 0 ? (\n <section aria-labelledby=\"available-skills-heading\">\n <h4\n id=\"available-skills-heading\"\n className=\"mb-2 text-[0.8125rem] font-semibold uppercase text-text-secondary\"\n >\n Available · {availableSkills.length}\n </h4>\n <div className=\"overflow-hidden rounded-xl border border-border bg-card-bg\">\n {availableSkills.map(entry =>\n renderRow({\n key: entry.id,\n name: entry.name,\n description: entry.description,\n action: (\n <Button.Secondary\n size=\"small\"\n type=\"button\"\n disabled={busy}\n aria-label={`Enable ${entry.name}`}\n onClick={() => {\n handleSelect(entry);\n }}\n >\n Enable\n </Button.Secondary>\n ),\n }),\n )}\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 {normalizedQuery ? `No skills match “${query.trim()}”.` : 'No skills yet.'}\n </div>\n ) : null}\n </div>\n </div>\n\n <ImportGithubSkillForm\n open={importOpen}\n onOpenChange={open => {\n setImportOpen(open);\n if (!open) setFormError(null);\n }}\n onImport={handleImport}\n busy={busy}\n error={formError}\n />\n </>\n );\n};\n\nexport default SkillSettings;\n","'use client';\n\nimport { useState, type SyntheticEvent } 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 { SkillConfigBase } from '../../server/types.js';\n\ntype ImportGithubSkillFormProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onImport: (draft: SkillConfigBase) => void | Promise<void>;\n busy?: boolean;\n error?: string | null;\n};\n\nconst ImportGithubSkillForm = ({ open, onOpenChange, onImport, busy = false, error }: ImportGithubSkillFormProps) => {\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [repoURL, setRepoURL] = useState('');\n const [path, setPath] = useState('');\n const [ref, setRef] = useState('');\n\n const reset = () => {\n setName('');\n setDescription('');\n setRepoURL('');\n setPath('');\n setRef('');\n };\n\n const close = () => {\n reset();\n onOpenChange(false);\n };\n\n const handleSubmit = async (event: SyntheticEvent<HTMLFormElement, SubmitEvent>) => {\n event.preventDefault();\n if (!name.trim() || !description.trim() || !repoURL.trim() || !path.trim() || !ref.trim() || busy) return;\n\n try {\n await onImport({\n name: name.trim(),\n description: description.trim(),\n repoURL: repoURL.trim(),\n path: path.trim(),\n ref: ref.trim(),\n });\n close();\n } catch {\n // Parent surfaces error; keep form open.\n }\n };\n\n const canImport = Boolean(name.trim() && description.trim() && repoURL.trim() && path.trim() && ref.trim()) && !busy;\n\n return (\n <CenteredModal\n open={open}\n onOpenChange={nextOpen => {\n if (!nextOpen) close();\n }}\n title=\"Import from GitHub\"\n description=\"Import a skill from a SKILL.md file in a GitHub repository.\"\n headerIcon={\n <span className=\"flex size-11 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary\">\n <Icon name=\"github\" className=\"size-5\" />\n </span>\n }\n contentSized\n className=\"md:max-w-2xl\"\n >\n <form onSubmit={e => void handleSubmit(e)}>\n <div className=\"space-y-5 px-5 py-5 md:px-6\">\n <div>\n <label htmlFor=\"skill-name\" className=\"mb-2 block text-sm font-semibold text-text-primary\">\n Name\n </label>\n <input\n id=\"skill-name\"\n value={name}\n onChange={event => {\n setName(event.target.value);\n }}\n placeholder=\"release-notes\"\n autoFocus\n required\n className={auiInputClass('h-11')}\n />\n </div>\n\n <div>\n <label htmlFor=\"skill-description\" className=\"mb-2 block text-sm font-semibold text-text-primary\">\n Description\n </label>\n <textarea\n id=\"skill-description\"\n value={description}\n onChange={event => {\n setDescription(event.target.value);\n }}\n placeholder=\"Generate release notes from merged pull requests\"\n required\n rows={3}\n className={auiInputClass('resize-y py-2.5')}\n />\n </div>\n\n <div>\n <label htmlFor=\"skill-repo-url\" className=\"mb-2 block text-sm font-semibold text-text-primary\">\n Repository URL\n </label>\n <input\n id=\"skill-repo-url\"\n type=\"url\"\n value={repoURL}\n onChange={event => {\n setRepoURL(event.target.value);\n }}\n placeholder=\"https://github.com/org/repo\"\n required\n className={auiInputClass('h-11')}\n />\n </div>\n\n <div>\n <label htmlFor=\"skill-path\" className=\"mb-2 block text-sm font-semibold text-text-primary\">\n Folder containing the SKILL.md\n </label>\n <input\n id=\"skill-path\"\n value={path}\n onChange={event => {\n setPath(event.target.value);\n }}\n placeholder=\"skills/release-notes\"\n required\n className={auiInputClass('h-11')}\n />\n </div>\n\n <div>\n <label htmlFor=\"skill-ref\" className=\"mb-2 block text-sm font-semibold text-text-primary\">\n Branch\n </label>\n <input\n id=\"skill-ref\"\n value={ref}\n onChange={event => {\n setRef(event.target.value);\n }}\n placeholder=\"main\"\n required\n className={auiInputClass('h-11')}\n />\n </div>\n\n <div className=\"space-y-3\">\n {error ? <p className=\"text-failure-bg text-sm\">{error}</p> : null}\n <Button.Primary type=\"submit\" disabled={!canImport} className=\"w-full\">\n Import\n </Button.Primary>\n </div>\n </div>\n </form>\n </CenteredModal>\n );\n};\n\nexport default ImportGithubSkillForm;\n"],"mappings":"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","names":["useState","jsx","jsxs","useState"]}
|