@oxy-hq/sdk 2.11.0 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +44 -4
  2. package/dist/function-context-D8eyZuw_.d.cts +720 -0
  3. package/dist/function-context-D8eyZuw_.d.cts.map +1 -0
  4. package/dist/function-context-D8eyZuw_.d.mts +720 -0
  5. package/dist/function-context-D8eyZuw_.d.mts.map +1 -0
  6. package/dist/index.cjs +156 -11
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +338 -638
  9. package/dist/index.d.cts.map +1 -1
  10. package/dist/index.d.mts +338 -638
  11. package/dist/index.d.mts.map +1 -1
  12. package/dist/index.mjs +155 -12
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/ops.cjs +85 -0
  15. package/dist/ops.cjs.map +1 -0
  16. package/dist/ops.d.cts +61 -0
  17. package/dist/ops.d.cts.map +1 -0
  18. package/dist/ops.d.mts +61 -0
  19. package/dist/ops.d.mts.map +1 -0
  20. package/dist/ops.mjs +79 -0
  21. package/dist/ops.mjs.map +1 -0
  22. package/dist/{react-DqnINwTi.mjs → react-BXGyzgz0.mjs} +8 -3
  23. package/dist/react-BXGyzgz0.mjs.map +1 -0
  24. package/dist/{react-CLONxcnA.d.cts → react-DW7Z96sD.d.cts} +8 -1
  25. package/dist/{react-CLONxcnA.d.cts.map → react-DW7Z96sD.d.cts.map} +1 -1
  26. package/dist/{react-CLONxcnA.d.mts → react-DW7Z96sD.d.mts} +8 -1
  27. package/dist/{react-CLONxcnA.d.mts.map → react-DW7Z96sD.d.mts.map} +1 -1
  28. package/dist/{react-riTxd9ce.cjs → react-DcT-mUPj.cjs} +8 -3
  29. package/dist/react-DcT-mUPj.cjs.map +1 -0
  30. package/dist/shell.cjs +34 -4
  31. package/dist/shell.cjs.map +1 -1
  32. package/dist/shell.d.cts +39 -7
  33. package/dist/shell.d.cts.map +1 -1
  34. package/dist/shell.d.mts +39 -7
  35. package/dist/shell.d.mts.map +1 -1
  36. package/dist/shell.mjs +34 -5
  37. package/dist/shell.mjs.map +1 -1
  38. package/package.json +12 -1
  39. package/dist/react-DqnINwTi.mjs.map +0 -1
  40. package/dist/react-riTxd9ce.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"shell.cjs","names":["React","useState","useMemo","useOxyApp","React","useAgentRun","useOxyApp","React","OxyAnswer","React","React","TooltipPrimitive","useState","Fragment","useOxyApp","React","useState","useMemo","useState","useOxyApp","useResolvedManifest","useState"],"sources":["../src/shell/cx.ts","../src/shell/AnswerChart.tsx","../src/shell/marks.tsx","../src/shell/trace.ts","../src/shell/ReasoningTrace.tsx","../src/shell/threadHistory.ts","../src/shell/AskDock.tsx","../src/shell/logoUrl.ts","../src/shell/portal.tsx","../src/shell/Tooltip.tsx","../src/shell/ShellRail.tsx","../src/shell/shellContext.ts","../src/shell/TopBar.tsx","../src/shell/WorkspaceTile.tsx","../src/shell/OxyShell.tsx"],"sourcesContent":["/** Join truthy class names. Local minimal `clsx` — the shell uses fixed\n * namespaced classes, so no Tailwind-style merge logic is needed. */\nexport function cx(...parts: Array<string | false | null | undefined>): string {\n return parts.filter(Boolean).join(\" \");\n}\n","// Renderer for the analytics pipeline's `chart_rendered` blocks — the same\n// payload the main web-app charts. Uses the host app's ECharts (optional\n// peer, dynamic import) for interactive charts matching the web-app, and\n// falls back to a dependency-free SVG render when echarts isn't installed.\n// Payload shape (see web-app AnalyticsDisplayBlock / ChartConfig):\n// { config: { chart_type, x, y, series, name, value, title, … },\n// columns: string[], rows: unknown[][] }\n\nimport type { ReactNode } from \"react\";\nimport * as React from \"react\";\nimport { cx } from \"./cx\";\n\nexport interface ChartBlockConfig {\n chart_type: \"line_chart\" | \"bar_chart\" | \"pie_chart\" | \"table\";\n x?: string;\n y?: string;\n series?: string;\n name?: string;\n value?: string;\n title?: string;\n x_axis_label?: string;\n y_axis_label?: string;\n}\n\nexport interface ChartBlock {\n config: ChartBlockConfig;\n columns: string[];\n rows: unknown[][];\n}\n\nconst PALETTE = [\"#3b82f6\", \"#22c55e\", \"#eab308\", \"#a855f7\", \"#06b6d4\", \"#f97316\"];\n\nconst compact = new Intl.NumberFormat(\"en\", { notation: \"compact\", maximumFractionDigits: 1 });\nconst toNum = (v: unknown): number => {\n const n = typeof v === \"number\" ? v : Number(v);\n return Number.isFinite(n) ? n : 0;\n};\nconst toStr = (v: unknown): string => (v === null || v === undefined ? \"\" : String(v));\n\n/** \"sales_daily__total_net_sales\" → \"Total Net Sales\" — a friendly series\n * label instead of the raw semantic column id. */\nexport function humanizeCol(name: string | undefined): string {\n const leaf = (name ?? \"\").split(\"__\").pop() ?? \"\";\n return leaf\n .replace(/_/g, \" \")\n .trim()\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\ninterface Pivoted {\n categories: string[];\n series: Array<{ name: string; values: number[] }>;\n}\n\n/** Pivot rows into per-series value arrays aligned on x categories. */\nexport function pivotChart(block: ChartBlock): Pivoted {\n const { config, columns, rows } = block;\n const xi = config.x ? columns.indexOf(config.x) : 0;\n const yi = config.y ? columns.indexOf(config.y) : columns.length > 1 ? 1 : 0;\n const si = config.series ? columns.indexOf(config.series) : -1;\n\n const categories: string[] = [];\n const catIndex = new Map<string, number>();\n for (const row of rows) {\n const cat = toStr(row[xi]);\n if (!catIndex.has(cat)) {\n catIndex.set(cat, categories.length);\n categories.push(cat);\n }\n }\n\n if (si === -1) {\n const values = new Array<number>(categories.length).fill(0);\n for (const row of rows) {\n const idx = catIndex.get(toStr(row[xi]));\n if (idx !== undefined) values[idx] = toNum(row[yi]);\n }\n return { categories, series: [{ name: config.y ?? \"value\", values }] };\n }\n\n const seriesIndex = new Map<string, number[]>();\n for (const row of rows) {\n const name = toStr(row[si]);\n let values = seriesIndex.get(name);\n if (!values) {\n values = new Array<number>(categories.length).fill(0);\n seriesIndex.set(name, values);\n }\n const idx = catIndex.get(toStr(row[xi]));\n if (idx !== undefined) values[idx] = toNum(row[yi]);\n }\n return {\n categories,\n series: [...seriesIndex.entries()].map(([name, values]) => ({ name, values }))\n };\n}\n\n/** A \"nice\" axis ceiling so tick labels land on round numbers. */\nexport function niceCeil(max: number): number {\n if (max <= 0) return 1;\n const pow = 10 ** Math.floor(Math.log10(max));\n const unit = max / pow;\n const nice = unit <= 1 ? 1 : unit <= 2 ? 2 : unit <= 5 ? 5 : 10;\n return nice * pow;\n}\n\n/** Axis domain `[lo, hi]` that always includes zero, with nice round\n * bounds. Signed measures (profit, net change) must render below a zero\n * baseline instead of being clamped to an invisible 0..max axis. */\nexport function axisDomain(values: number[]): { lo: number; hi: number } {\n const rawMax = Math.max(...values, 0);\n const rawMin = Math.min(...values, 0);\n const hi = rawMax > 0 ? niceCeil(rawMax) : 0;\n const lo = rawMin < 0 ? -niceCeil(-rawMin) : 0;\n // Degenerate all-zero data: keep a unit span so ticks still render.\n return hi === lo ? { lo: 0, hi: 1 } : { lo, hi };\n}\n\nconst W = 360;\nconst H = 190;\nconst M = { top: 8, right: 8, bottom: 34, left: 42 };\nconst IW = W - M.left - M.right;\nconst IH = H - M.top - M.bottom;\nconst TICKS = 4;\n\nfunction truncate(label: string, max: number): string {\n return label.length > max ? `${label.slice(0, max - 1)}…` : label;\n}\n\n/** Map a value to its y pixel within the plot area for domain `[lo, hi]`. */\nconst yFor = (v: number, lo: number, hi: number): number =>\n M.top + IH * (1 - (v - lo) / (hi - lo || 1));\n\nfunction Axes({ lo, hi }: { lo: number; hi: number }) {\n const span = hi - lo || 1;\n return (\n <g className='oxy-chart__grid'>\n {Array.from({ length: TICKS + 1 }, (_, i) => {\n const y = M.top + (IH * i) / TICKS;\n const value = hi - (span * i) / TICKS;\n return (\n <g key={i}>\n <line x1={M.left} x2={M.left + IW} y1={y} y2={y} />\n <text x={M.left - 5} y={y + 3} textAnchor='end' className='oxy-chart__tick'>\n {compact.format(value)}\n </text>\n </g>\n );\n })}\n </g>\n );\n}\n\nfunction XLabels({ categories }: { categories: string[] }) {\n const slot = IW / categories.length;\n const maxChars = Math.max(4, Math.floor(slot / 5.5));\n return (\n <g>\n {categories.map((cat, i) => (\n <text\n key={cat}\n x={M.left + slot * (i + 0.5)}\n y={H - M.bottom + 12}\n textAnchor='middle'\n className='oxy-chart__tick'\n >\n <title>{cat}</title>\n {truncate(cat, maxChars)}\n </text>\n ))}\n </g>\n );\n}\n\nfunction BarChart({ data }: { data: Pivoted }) {\n const { lo, hi } = axisDomain(data.series.flatMap((s) => s.values));\n const zeroY = yFor(0, lo, hi);\n const slot = IW / data.categories.length;\n const group = slot * 0.7;\n const barW = group / data.series.length;\n return (\n <svg viewBox={`0 0 ${W} ${H}`} className='oxy-chart__svg' role='img'>\n <Axes lo={lo} hi={hi} />\n {data.series.map((s, si) =>\n s.values.map((v, ci) => {\n // Bars grow from the zero baseline: up for positive values, down\n // for negative — so signed measures stay visible.\n const vy = yFor(v, lo, hi);\n return (\n <rect\n key={`${s.name}-${data.categories[ci]}`}\n x={M.left + slot * ci + (slot - group) / 2 + barW * si}\n y={Math.min(zeroY, vy)}\n width={Math.max(1, barW - 1)}\n height={Math.max(0, Math.abs(vy - zeroY))}\n rx={1.5}\n fill={PALETTE[si % PALETTE.length]}\n >\n <title>{`${data.categories[ci]}${data.series.length > 1 ? ` · ${s.name}` : \"\"}: ${compact.format(v)}`}</title>\n </rect>\n );\n })\n )}\n {lo < 0 && (\n <line className='oxy-chart__grid-zero' x1={M.left} x2={M.left + IW} y1={zeroY} y2={zeroY} />\n )}\n <XLabels categories={data.categories} />\n </svg>\n );\n}\n\nfunction LineChart({ data }: { data: Pivoted }) {\n const { lo, hi } = axisDomain(data.series.flatMap((s) => s.values));\n const zeroY = yFor(0, lo, hi);\n const slot = IW / Math.max(1, data.categories.length - 1 || 1);\n const px = (ci: number) => (data.categories.length === 1 ? M.left + IW / 2 : M.left + slot * ci);\n const py = (v: number) => yFor(v, lo, hi);\n return (\n <svg viewBox={`0 0 ${W} ${H}`} className='oxy-chart__svg' role='img'>\n <Axes lo={lo} hi={hi} />\n {lo < 0 && (\n <line className='oxy-chart__grid-zero' x1={M.left} x2={M.left + IW} y1={zeroY} y2={zeroY} />\n )}\n {data.series.map((s, si) => (\n <g key={s.name}>\n <polyline\n points={s.values.map((v, ci) => `${px(ci)},${py(v)}`).join(\" \")}\n fill='none'\n stroke={PALETTE[si % PALETTE.length]}\n strokeWidth={1.8}\n />\n {s.values.map((v, ci) => (\n <circle\n key={data.categories[ci]}\n cx={px(ci)}\n cy={py(v)}\n r={2.2}\n fill={PALETTE[si % PALETTE.length]}\n >\n <title>{`${data.categories[ci]}${data.series.length > 1 ? ` · ${s.name}` : \"\"}: ${compact.format(v)}`}</title>\n </circle>\n ))}\n </g>\n ))}\n <XLabels categories={data.categories} />\n </svg>\n );\n}\n\nfunction PieChart({ block }: { block: ChartBlock }) {\n const { config, columns, rows } = block;\n const ni = config.name ? columns.indexOf(config.name) : config.x ? columns.indexOf(config.x) : 0;\n const vi = config.value\n ? columns.indexOf(config.value)\n : config.y\n ? columns.indexOf(config.y)\n : 1;\n const slices = rows.map((r) => ({ name: toStr(r[ni]), value: Math.max(0, toNum(r[vi])) }));\n const total = slices.reduce((sum, s) => sum + s.value, 0) || 1;\n\n const cxp = W / 2;\n const cyp = H / 2;\n const r = Math.min(W, H) / 2 - 14;\n let angle = -Math.PI / 2;\n const paths = slices.map((s, i) => {\n const sweep = (s.value / total) * Math.PI * 2;\n const title = `${s.name}: ${compact.format(s.value)} (${Math.round((s.value / total) * 100)}%)`;\n const fill = PALETTE[i % PALETTE.length];\n // A slice covering the whole circle (single slice, or one category at\n // 100%) has coincident arc endpoints, which SVG drops — collapsing the\n // path to a zero-area sliver that renders blank. Draw a full circle\n // instead.\n if (sweep >= Math.PI * 2 - 1e-6) {\n angle += sweep;\n return (\n <circle\n key={s.name}\n cx={cxp}\n cy={cyp}\n r={r}\n fill={fill}\n stroke='var(--oxy-shell-background, #fff)'\n strokeWidth={1}\n >\n <title>{title}</title>\n </circle>\n );\n }\n const x1 = cxp + r * Math.cos(angle);\n const y1 = cyp + r * Math.sin(angle);\n angle += sweep;\n const x2 = cxp + r * Math.cos(angle);\n const y2 = cyp + r * Math.sin(angle);\n const large = sweep > Math.PI ? 1 : 0;\n return (\n <path\n key={s.name}\n d={`M ${cxp} ${cyp} L ${x1} ${y1} A ${r} ${r} 0 ${large} 1 ${x2} ${y2} Z`}\n fill={fill}\n stroke='var(--oxy-shell-background, #fff)'\n strokeWidth={1}\n >\n <title>{title}</title>\n </path>\n );\n });\n return (\n <svg viewBox={`0 0 ${W} ${H}`} className='oxy-chart__svg' role='img'>\n {paths}\n </svg>\n );\n}\n\nconst TABLE_MAX_ROWS = 10;\n\nfunction TableChart({ block }: { block: ChartBlock }) {\n const visible = block.rows.slice(0, TABLE_MAX_ROWS);\n return (\n <div className='oxy-chart__table-wrap'>\n <table className='oxy-chart__table'>\n <thead>\n <tr>\n {block.columns.map((c) => (\n <th key={c}>{c}</th>\n ))}\n </tr>\n </thead>\n <tbody>\n {visible.map((row, i) => (\n <tr key={row.map(toStr).join(\"|\") || i}>\n {block.columns.map((c, j) => (\n <td key={c}>{toStr(row[j])}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n {block.rows.length > TABLE_MAX_ROWS && (\n <div className='oxy-chart__note'>+{block.rows.length - TABLE_MAX_ROWS} more rows</div>\n )}\n </div>\n );\n}\n\n/** Dependency-free SVG rendering — the fallback when the host app has no\n * `echarts`. */\nfunction SvgChart({ block }: { block: ChartBlock }) {\n const data =\n block.config.chart_type === \"bar_chart\" || block.config.chart_type === \"line_chart\"\n ? pivotChart(block)\n : null;\n let body: ReactNode;\n switch (block.config.chart_type) {\n case \"bar_chart\":\n body = data && <BarChart data={data} />;\n break;\n case \"line_chart\":\n body = data && <LineChart data={data} />;\n break;\n case \"pie_chart\":\n body = <PieChart block={block} />;\n break;\n default:\n body = <TableChart block={block} />;\n }\n const multiSeries = data && data.series.length > 1;\n return (\n <>\n {body}\n {multiSeries && (\n <div className='oxy-chart__legend'>\n {data.series.map((s, i) => (\n <span key={s.name} className='oxy-chart__legend-item'>\n <span\n className='oxy-chart__legend-dot'\n style={{ background: PALETTE[i % PALETTE.length] }}\n />\n {s.name}\n </span>\n ))}\n </div>\n )}\n </>\n );\n}\n\n/** Read the shell's design tokens off an element so the ECharts chart\n * matches the surrounding light/dark theme. */\nfunction tokenColors(el: HTMLElement) {\n const cs = getComputedStyle(el);\n const pick = (name: string, fallback: string) => cs.getPropertyValue(name).trim() || fallback;\n return {\n fg: pick(\"--oxy-shell-foreground\", \"#0a0a0a\"),\n muted: pick(\"--oxy-shell-muted-fg\", \"#71717a\"),\n border: pick(\"--oxy-shell-border\", \"#d4d4d8\"),\n bg: pick(\"--oxy-shell-background\", \"#ffffff\")\n };\n}\n\n/** Build the ECharts option for a `chart_rendered` block — the analytics\n * pipeline's `{chart_type, x, y, series, …}` config, the same shape the\n * main web-app charts. Interactive: axis/item tooltips, legend, hover. */\nfunction buildEchartsOption(block: ChartBlock, el: HTMLElement): Record<string, unknown> {\n const { fg, muted, border } = tokenColors(el);\n const axisLabel = { color: muted, fontSize: 10 };\n const ct = block.config.chart_type;\n\n if (ct === \"pie_chart\") {\n const { config, columns, rows } = block;\n const ni = config.name\n ? columns.indexOf(config.name)\n : config.x\n ? columns.indexOf(config.x)\n : 0;\n const vi = config.value\n ? columns.indexOf(config.value)\n : config.y\n ? columns.indexOf(config.y)\n : 1;\n const data = rows.map((r) => ({ name: toStr(r[ni]), value: Math.max(0, toNum(r[vi])) }));\n return {\n color: PALETTE,\n tooltip: { trigger: \"item\", formatter: \"{b}: {c} ({d}%)\" },\n legend: { bottom: 0, textStyle: { color: muted, fontSize: 10 }, type: \"scroll\" },\n series: [\n {\n type: \"pie\",\n radius: [\"38%\", \"66%\"],\n center: [\"50%\", \"44%\"],\n data,\n label: { color: fg, fontSize: 10 },\n labelLine: { lineStyle: { color: border } }\n }\n ]\n };\n }\n\n const pivot = pivotChart(block);\n const multi = pivot.series.length > 1;\n // Friendly single-series label: the axis label, else the humanized y col\n // (never the raw \"table__column\" id that shows in the tooltip/legend).\n const singleName = block.config.y_axis_label || humanizeCol(block.config.y) || \"Value\";\n // Long / many categories overlap on a horizontal axis → show every label\n // rotated + truncated so no bar is left unlabeled.\n const longLabels = pivot.categories.length > 4 || pivot.categories.some((c) => c.length > 10);\n return {\n color: PALETTE,\n tooltip: {\n trigger: \"axis\",\n valueFormatter: (v: unknown) => (typeof v === \"number\" ? compact.format(v) : String(v))\n },\n grid: { left: 6, right: 12, top: multi ? 30 : 12, bottom: 4, containLabel: true },\n legend: multi\n ? { top: 0, textStyle: { color: muted, fontSize: 10 }, type: \"scroll\" }\n : undefined,\n xAxis: {\n type: \"category\",\n data: pivot.categories,\n name: block.config.x_axis_label,\n nameLocation: \"middle\",\n nameGap: longLabels ? 42 : 24,\n nameTextStyle: { color: muted, fontSize: 10 },\n axisLabel: {\n ...axisLabel,\n interval: 0,\n rotate: longLabels ? 30 : 0,\n formatter: (v: string) => (v.length > 18 ? `${v.slice(0, 17)}…` : v)\n },\n axisTick: { show: false },\n axisLine: { lineStyle: { color: border } }\n },\n yAxis: {\n type: \"value\",\n name: block.config.y_axis_label,\n nameTextStyle: { color: muted, fontSize: 10 },\n axisLabel: { ...axisLabel, formatter: (v: number) => compact.format(v) },\n splitLine: { lineStyle: { color: border, opacity: 0.5 } }\n },\n series: pivot.series.map((s, i) => ({\n name: multi ? s.name : singleName,\n type: ct === \"bar_chart\" ? \"bar\" : \"line\",\n data: s.values,\n itemStyle: { color: PALETTE[i % PALETTE.length] },\n ...(ct === \"line_chart\" ? { lineStyle: { width: 2 }, symbolSize: 5, smooth: false } : {}),\n barMaxWidth: 32\n }))\n };\n}\n\nexport interface AnswerChartProps {\n block: ChartBlock;\n className?: string;\n}\n\n/** Renders one `chart_rendered` block. Uses ECharts (interactive, matching\n * the main web-app) when the host app has it installed; otherwise falls\n * back to a dependency-free SVG render. Table type always uses SVG. */\nexport function AnswerChart({ block, className }: AnswerChartProps) {\n const ref = React.useRef<HTMLDivElement>(null);\n // \"pending\" while we try ECharts; \"svg\" once we know it isn't available\n // (or for the table type, which ECharts doesn't draw).\n const [engine, setEngine] = React.useState<\"pending\" | \"svg\">(\n block.config.chart_type === \"table\" ? \"svg\" : \"pending\"\n );\n\n React.useEffect(() => {\n if (engine === \"svg\") return;\n let disposed = false;\n let chart: { setOption: (o: unknown) => void; resize: () => void; dispose: () => void } | null =\n null;\n let ro: ResizeObserver | null = null;\n // `@vite-ignore` keeps the specifier out of the consumer's static build\n // graph: echarts is an OPTIONAL peer, so a bundle that doesn't install it\n // must still `vite build`. Without this, Rollup tries to resolve \"echarts\"\n // at build time and aborts — the runtime `.catch()` SVG fallback below\n // never gets a chance to run. Ignored here → resolved at runtime → the\n // catch fires and we fall back to SVG when echarts is absent.\n import(/* @vite-ignore */ \"echarts\")\n .then((echarts) => {\n const el = ref.current;\n if (disposed || !el) return;\n chart = echarts.init(el, undefined, { renderer: \"canvas\" });\n chart.setOption(buildEchartsOption(block, el));\n ro = new ResizeObserver(() => chart?.resize());\n ro.observe(el);\n })\n .catch(() => {\n // echarts not installed in the host app → SVG fallback.\n if (!disposed) setEngine(\"svg\");\n });\n return () => {\n disposed = true;\n ro?.disconnect();\n chart?.dispose();\n };\n }, [block, engine]);\n\n return (\n <figure className={cx(\"oxy-chart\", className)} data-testid='askdock-chart'>\n {block.config.title && (\n <figcaption className='oxy-chart__title'>{block.config.title}</figcaption>\n )}\n {engine === \"svg\" ? (\n <SvgChart block={block} />\n ) : (\n <div ref={ref} className='oxy-chart__echarts' style={{ width: \"100%\", height: 240 }} />\n )}\n </figure>\n );\n}\n","// Inline brand marks so external bundles don't need the web-app's static\n// assets. Path data is copied from web-app (OxyMark.tsx and\n// public/oxygen-factory-mark-{light,dark}.svg) — keep in sync on rebrands.\n\n/** The Oxygen \"O\" glyph path, in a 0 0 44 44 viewBox, used by `OxyMark`. */\nexport const OXY_MARK_PATH =\n \"M38.4 22C39.2837 22 40.0074 22.7178 39.9289 23.5979C39.6619 26.5942 38.6471 29.485 36.9665 32.0003C34.9886 34.9603 32.1774 37.2674 28.8883 38.6298C25.5992 39.9922 21.98 40.3487 18.4884 39.6541C14.9967 38.9596 11.7894 37.2453 9.27209 34.7279C6.75474 32.2106 5.04041 29.0033 4.34587 25.5116C3.65134 22.02 4.0078 18.4008 5.37018 15.1117C6.73255 11.8226 9.03966 9.0114 11.9997 7.03353C14.515 5.35287 17.4058 4.33807 20.4021 4.07104C21.2822 3.9926 22 4.71633 22 5.59998L22 11.2C22 12.0837 22.7163 12.8 23.6 12.8H29.2C30.0837 12.8 30.8 12.0837 30.8 11.2V5.6C30.8 4.71634 31.5163 4 32.4 4H38.4C39.2836 4 40 4.71634 40 5.6V11.6C40 12.4837 39.2836 13.2 38.4 13.2H32.8C31.9163 13.2 31.2 13.9163 31.2 14.8V20.4C31.2 21.2837 31.9163 22 32.8 22L38.4 22ZM23.6 22C22.7163 22 22 21.2837 22 20.4L22 14.8371C22 13.9534 21.2778 13.2223 20.4089 13.3827C19.2427 13.5981 18.1268 14.0489 17.1316 14.7139C15.6905 15.6768 14.5674 17.0454 13.9041 18.6466C13.2409 20.2478 13.0674 22.0097 13.4055 23.7095C13.7436 25.4094 14.5782 26.9708 15.8037 28.1963C17.0292 29.4218 18.5906 30.2564 20.2904 30.5945C21.9903 30.9326 23.7522 30.7591 25.3534 30.0959C26.9546 29.4326 28.3232 28.3095 29.2861 26.8684C29.9511 25.8732 30.4019 24.7573 30.6172 23.5911C30.7777 22.7222 30.0466 22 29.1629 22L23.6 22Z\";\n\n/** The Oxygen \"O\" mark as an inline SVG that inherits `currentColor`, so it\n * reads correctly on any surface in light or dark mode. */\nexport function OxyMark({ className }: { className?: string }) {\n return (\n <svg\n viewBox='0 0 44 44'\n fill='currentColor'\n xmlns='http://www.w3.org/2000/svg'\n className={className}\n aria-hidden='true'\n >\n <path fillRule='evenodd' clipRule='evenodd' d={OXY_MARK_PATH} />\n </svg>\n );\n}\n\nconst FACTORY_PATHS = [\n \"M64.7079 60.8981C66.2159 61.5769 66.42 63.424 64.8831 64.0349C53.9237 68.3911 22.4112 68.2339 12.6945 62.9613C11.4576 62.2901 11.6244 60.6958 12.7979 59.9191C17.3748 56.8895 25.3973 51.7874 31.0332 48.4864C31.9361 47.9575 33.0153 47.8364 34.0043 48.1784C41.0152 50.6027 55.7832 56.8809 64.7079 60.8981Z\",\n \"M40.8612 14.4068C40.6005 13.1343 41.6723 12.0367 42.847 12.591C53.7523 17.7375 68.2377 45.3963 68.9964 57.4238C69.0787 58.7282 67.7002 59.4009 66.5675 58.7485C62.2989 56.2901 53.2249 51.0848 48.6689 48.6258C47.5323 48.0123 46.7649 46.8912 46.5938 45.611C45.4688 37.1953 42.1634 20.7629 40.8612 14.4068Z\",\n \"M39.2805 32.7689C39.2947 33.8426 38.8352 34.8657 38.0314 35.5777C28.4104 44.1006 18.5237 51.9152 13.0125 56.3133C11.7919 57.2874 10.0954 56.4483 10.3571 54.9087C12.5527 41.9933 25.758 17.8554 35.9571 12.7314C36.9805 12.2172 38.0789 12.9771 38.1857 14.1175C38.5311 17.8049 39.186 25.6228 39.2805 32.7689Z\"\n];\n\n/** The Oxygen Factory mark (three-shard glyph) as an inline SVG in\n * `currentColor`, so it follows the shell foreground in either theme.\n * (The web-app's asset files are fixed-color; this inline variant frees\n * external bundles from carrying those assets.) Decorative — the rail\n * button supplies the \"Oxygen Factory\" aria-label. */\nexport function OxygenFactoryMark({ className }: { className?: string }) {\n return (\n <svg\n viewBox='0 0 80 80'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n className={className}\n aria-hidden='true'\n >\n {FACTORY_PATHS.map((d) => (\n <path key={d.slice(0, 16)} d={d} fill='currentColor' />\n ))}\n </svg>\n );\n}\n","// Reasoning-trace builder for the Ask dock: folds the raw agent-run SSE\n// events (`useAgentRun().events`) into the same step/tool/SQL shape the\n// main web-app's AnalyticsReasoningTrace renders — the bundle stream goes\n// through the same server-side EventRegistry processor, so the event\n// vocabulary matches (`step_start`/`step_end`, `tool_call`/`tool_result`,\n// `query_executed`, …). Deliberately lighter than the web-app hook: no\n// fan-out cards, no thinking token stream, no artifact sidebar — labels,\n// statuses, and result summaries only.\n\nimport type { AgentRunEvent } from \"../custom-app/react\";\n\nexport type TraceStepStatus = \"running\" | \"done\" | \"failed\" | \"suspended\";\n\nexport interface TraceItem {\n id: string;\n kind: \"tool\" | \"sql\" | \"note\" | \"thinking\";\n label: string;\n /** Muted inline preview of the tool input / query intent. */\n preview?: string;\n /** Right-aligned detail, e.g. \"22 rows · 1.4s\". */\n detail?: string;\n /** Body text (thinking items) — rendered as a wrapped paragraph. */\n text?: string;\n /** Full tool input / SQL, pretty-printed — the expandable detail body. */\n input?: string;\n /** Full tool output / result summary, pretty-printed. */\n output?: string;\n error?: boolean;\n running?: boolean;\n}\n\nexport interface TraceStep {\n id: string;\n label: string;\n summary?: string;\n status: TraceStepStatus;\n items: TraceItem[];\n}\n\nconst str = (v: unknown): string | undefined => (typeof v === \"string\" ? v : undefined);\nconst num = (v: unknown): number | undefined => (typeof v === \"number\" ? v : undefined);\n\n/** \"search_catalog\" -> \"Search Catalog\" — matches the web-app pill labels. */\nexport function prettyToolName(name: string): string {\n return name\n .split(/[_-]+/)\n .filter(Boolean)\n .map((w) => w[0].toUpperCase() + w.slice(1))\n .join(\" \");\n}\n\n/** Compact one-line preview of a tool input (string arg or first string\n * field of an object), truncated for the trace row. */\nfunction inputPreview(input: unknown, max = 60): string | undefined {\n // The stream often pre-serializes the tool input — unwrap JSON strings so\n // the preview shows the human part (\"top stores by revenue\"), not braces.\n if (typeof input === \"string\" && /^[[{]/.test(input.trim())) {\n try {\n return inputPreview(JSON.parse(input), max);\n } catch {\n // fall through — treat as plain text\n }\n }\n let text: string | undefined;\n if (typeof input === \"string\") text = input;\n else if (Array.isArray(input)) {\n const first = input.find((v) => typeof v === \"string\" && v.trim());\n text = typeof first === \"string\" ? first : JSON.stringify(input);\n } else if (input && typeof input === \"object\") {\n for (const v of Object.values(input as Record<string, unknown>)) {\n if (typeof v === \"string\" && v.trim()) {\n text = v;\n break;\n }\n }\n if (!text) {\n const json = JSON.stringify(input);\n text = json === \"{}\" ? undefined : json;\n }\n }\n if (!text) return undefined;\n text = text.replace(/\\s+/g, \" \").trim();\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\n/** Full pretty-printed payload for the expandable row detail: unwraps\n * pre-serialized JSON strings, indents objects, caps runaway sizes. */\nfunction prettyPayload(v: unknown, max = 2000): string | undefined {\n if (v === null || v === undefined) return undefined;\n let val: unknown = v;\n if (typeof val === \"string\") {\n const t = val.trim();\n if (!t) return undefined;\n if (/^[[{]/.test(t)) {\n try {\n val = JSON.parse(t);\n } catch {\n // keep the raw string\n }\n }\n }\n const text = typeof val === \"string\" ? val : JSON.stringify(val, null, 2);\n if (!text || text === \"{}\" || text === \"[]\") return undefined;\n return text.length > max ? `${text.slice(0, max)}\\n…` : text;\n}\n\nexport function formatMs(ms: number): string {\n return ms >= 1000 ? `${(ms / 1000).toFixed(1)}s` : `${ms}ms`;\n}\n\n/** Header meta, same as the web-app trace: LLM call count + total LLM time\n * folded from `llm_usage` events. */\nexport function aggregateLlmStats(events: AgentRunEvent[]): { calls: number; totalMs: number } {\n let calls = 0;\n let totalMs = 0;\n for (const ev of events) {\n if (ev.type !== \"llm_usage\") continue;\n calls++;\n const d = (ev.data ?? {}) as Record<string, unknown>;\n totalMs += num(d.duration_ms) ?? 0;\n }\n return { calls, totalMs };\n}\n\n/** Reconstruct the streamed answer markdown from persisted events —\n * concatenate the `text_delta` tokens, the same accumulation the live\n * `useAgentRun` does. Used to rebuild a turn's answer on history restore. */\nexport function extractAnswer(events: AgentRunEvent[]): string {\n let out = \"\";\n for (const ev of events) {\n if (ev.type !== \"text_delta\") continue;\n const d = (ev.data ?? {}) as Record<string, unknown>;\n if (typeof d.token === \"string\") out += d.token;\n }\n return out;\n}\n\n/** Pull the clarifying-question prompt from a persisted `awaiting_input`\n * event (`{ questions: [{ prompt, suggestions }] }`) so a turn that ended\n * in a suspension restores with its question instead of a blank answer.\n * Mirrors the live `useAgentRun` clarification parse. */\nexport function extractClarification(events: AgentRunEvent[]): string | null {\n for (const ev of events) {\n if (ev.type !== \"awaiting_input\") continue;\n const d = (ev.data ?? {}) as Record<string, unknown>;\n const questions = Array.isArray(d.questions) ? d.questions : [];\n const first = questions[0] as Record<string, unknown> | undefined;\n if (first && typeof first.prompt === \"string\") return first.prompt;\n // Older single-question shape: `{ question: \"…\" }`.\n if (typeof d.question === \"string\") return d.question;\n }\n return null;\n}\n\nfunction sqlDetail(d: Record<string, unknown>): string | undefined {\n const parts: string[] = [];\n const rows = num(d.row_count) ?? (Array.isArray(d.rows) ? d.rows.length : undefined);\n if (rows !== undefined) parts.push(`${rows} row${rows === 1 ? \"\" : \"s\"}`);\n const ms = num(d.duration_ms);\n if (ms !== undefined) parts.push(formatMs(ms));\n return parts.length ? parts.join(\" · \") : undefined;\n}\n\n/** Mark any still-running items in a step as settled — called when the step\n * closes so a tool/SQL/semantic row whose matching result never arrived\n * (cancel, error mid-flight, terminal event) doesn't spin forever on a\n * finished turn. */\nfunction settleStepItems(step: TraceStep, asError = false): void {\n for (const item of step.items) {\n if (item.running) {\n item.running = false;\n if (asError) item.error = true;\n }\n }\n}\n\n/** Fold raw SSE events into display steps. Pure — safe to re-run on every\n * render over the accumulated event array. */\nexport function buildTraceSteps(events: AgentRunEvent[]): TraceStep[] {\n const steps: TraceStep[] = [];\n let open: TraceStep | null = null;\n let n = 0;\n const id = (prefix: string) => `${prefix}-${n++}`;\n\n const ensureStep = (): TraceStep => {\n if (open) return open;\n open = { id: id(\"step\"), label: \"Working\", status: \"running\", items: [] };\n steps.push(open);\n return open;\n };\n const lastRunning = (kind: TraceItem[\"kind\"]): TraceItem | undefined => {\n for (let i = steps.length - 1; i >= 0; i--) {\n const items = steps[i].items;\n for (let j = items.length - 1; j >= 0; j--) {\n const item = items[j];\n if (item.kind === kind && item.running) return item;\n }\n }\n return undefined;\n };\n\n for (const ev of events) {\n const d = (ev.data ?? {}) as Record<string, unknown>;\n switch (ev.type) {\n case \"step_start\": {\n // A dangling open step means its step_end never arrived (crash /\n // recovery) — close it as done rather than leaving a spinner.\n if (open) {\n settleStepItems(open);\n open.status = \"done\";\n }\n open = {\n id: id(\"step\"),\n label: str(d.label) ?? \"Step\",\n summary: str(d.summary),\n status: \"running\",\n items: []\n };\n steps.push(open);\n break;\n }\n case \"step_end\": {\n if (!open) break;\n const outcome = str(d.outcome);\n open.status =\n outcome === \"failed\" ? \"failed\" : outcome === \"suspended\" ? \"suspended\" : \"done\";\n settleStepItems(open, open.status === \"failed\");\n open = null;\n break;\n }\n case \"step_summary_update\": {\n const summary = str(d.summary);\n if (open && summary) open.summary = summary;\n break;\n }\n\n case \"tool_call\": {\n const name = str(d.name) ?? \"tool\";\n ensureStep().items.push({\n id: id(\"tool\"),\n kind: \"tool\",\n label: prettyToolName(name),\n preview: inputPreview(d.input),\n input: prettyPayload(d.input),\n running: true\n });\n break;\n }\n case \"tool_result\": {\n const item = lastRunning(\"tool\");\n if (item) {\n item.running = false;\n item.error = d.is_error === true;\n item.output = prettyPayload(d.output);\n const ms = num(d.duration_ms);\n if (ms !== undefined) item.detail = formatMs(ms);\n }\n break;\n }\n\n case \"thinking_start\":\n ensureStep().items.push({\n id: id(\"think\"),\n kind: \"thinking\",\n label: \"Thinking\",\n text: \"\",\n running: true\n });\n break;\n case \"thinking_token\": {\n const item = lastRunning(\"thinking\");\n if (item) item.text = (item.text ?? \"\") + (str(d.token) ?? \"\");\n break;\n }\n case \"thinking_end\": {\n const item = lastRunning(\"thinking\");\n if (item) item.running = false;\n break;\n }\n\n case \"semantic_shortcut_attempted\":\n ensureStep().items.push({\n id: id(\"sem\"),\n kind: \"tool\",\n label: \"Compile semantic query\",\n input: prettyPayload(d),\n running: true\n });\n break;\n case \"semantic_shortcut_resolved\": {\n const item = lastRunning(\"tool\");\n if (item) {\n item.running = false;\n item.output = prettyPayload(d.sql ?? d);\n }\n break;\n }\n\n case \"query_executed\": {\n const failed = d.success === false;\n ensureStep().items.push({\n id: id(\"sql\"),\n kind: \"sql\",\n label: failed ? \"Query failed\" : \"Query\",\n detail: failed ? (str(d.error) ?? undefined) : sqlDetail(d),\n input: prettyPayload(d.query ?? d.sql),\n output: failed ? prettyPayload(d.error) : undefined,\n error: failed\n });\n break;\n }\n case \"verified_sql\":\n ensureStep().items.push({\n id: id(\"sql\"),\n kind: \"sql\",\n label: \"Verified query\",\n detail: sqlDetail(d),\n input: prettyPayload(d.query ?? d.sql)\n });\n break;\n\n case \"schema_resolved\": {\n const tables = Array.isArray(d.tables) ? d.tables.length : undefined;\n ensureStep().items.push({\n id: id(\"schema\"),\n kind: \"note\",\n label: \"Schema resolved\",\n detail: tables ? `${tables} table${tables === 1 ? \"\" : \"s\"}` : undefined\n });\n break;\n }\n\n case \"recovery_resumed\": {\n if (open) {\n settleStepItems(open);\n open.status = \"done\";\n open = null;\n }\n steps.push({\n id: id(\"step\"),\n label: \"Resuming\",\n summary: str(d.message) ?? \"Resuming from server restart\",\n status: \"done\",\n items: []\n });\n break;\n }\n\n case \"awaiting_input\": {\n // Suspension for a clarifying question — close the open step so its\n // tool/SQL rows stop spinning while the run waits on the user.\n if (open) {\n settleStepItems(open);\n open.status = \"suspended\";\n open = null;\n }\n break;\n }\n\n case \"error\":\n case \"failed\": {\n if (open) {\n settleStepItems(open, true);\n open.status = \"failed\";\n open = null;\n }\n break;\n }\n case \"done\":\n case \"cancelled\": {\n if (open) {\n settleStepItems(open);\n open.status = \"done\";\n open = null;\n }\n break;\n }\n default:\n break;\n }\n }\n return steps;\n}\n","// Reasoning trace for the Ask dock — the compact cousin of the web-app's\n// AnalyticsReasoningTrace: header meta (LLM calls · time · steps), one row\n// per step (status icon · label · summary), and indented item rows —\n// tool calls with input previews and durations, thinking text, queries\n// with row counts.\n//\n// Collapse model: the whole trace is expanded while the run streams and\n// collapses to the header line when it settles. Within the trace, each\n// step shows its item rows while it RUNS and auto-collapses to its header\n// once it ends; clicking a step (any time, including after the run) takes\n// over that step's toggle.\n\nimport { useMemo, useState } from \"react\";\nimport { cx } from \"./cx\";\nimport { formatMs, type TraceStep } from \"./trace\";\n\nfunction StatusIcon({ status }: { status: TraceStep[\"status\"] }) {\n if (status === \"running\")\n return <span role='status' className='oxy-trace__spin' aria-label='running' />;\n if (status === \"failed\") return <span className='oxy-trace__icon oxy-trace__icon--fail'>✕</span>;\n if (status === \"suspended\")\n return <span className='oxy-trace__icon oxy-trace__icon--wait'>…</span>;\n return <span className='oxy-trace__icon oxy-trace__icon--ok'>✓</span>;\n}\n\nfunction ChevronIcon({ open }: { open: boolean }) {\n return (\n <svg\n width='12'\n height='12'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n style={{ transform: open ? \"rotate(90deg)\" : undefined, transition: \"transform 0.15s\" }}\n >\n <path d='m9 18 6-6-6-6' />\n </svg>\n );\n}\n\nfunction TraceItemRows({\n step,\n itemToggles,\n onToggleItem\n}: {\n step: TraceStep;\n itemToggles: Record<string, boolean>;\n onToggleItem: (id: string, open: boolean) => void;\n}) {\n return (\n <div className='oxy-trace__items'>\n {step.items.map((item) => {\n if (item.kind === \"thinking\") {\n return (item.text ?? \"\").trim() ? (\n <p key={item.id} className='oxy-trace__think'>\n {item.text}\n </p>\n ) : null;\n }\n const hasDetail = Boolean(item.input || item.output);\n // Same collapse model as steps: detail is visible while the action\n // runs, folds when it completes, and a click wins from then on.\n const itemOpen = hasDetail && (itemToggles[item.id] ?? item.running === true);\n const row = (\n <>\n {item.running && (\n <span\n role='status'\n className='oxy-trace__spin oxy-trace__spin--sm'\n aria-label='running'\n />\n )}\n <span className='oxy-trace__row-label'>{item.label}</span>\n {item.preview && <span className='oxy-trace__row-preview'>{item.preview}</span>}\n {item.detail && <span className='oxy-trace__row-detail'>{item.detail}</span>}\n </>\n );\n return (\n <div key={item.id} className='oxy-trace__item'>\n {hasDetail ? (\n <button\n type='button'\n className={cx(\n \"oxy-trace__row\",\n \"oxy-trace__row--btn\",\n item.error && \"oxy-trace__row--error\"\n )}\n onClick={() => onToggleItem(item.id, !itemOpen)}\n aria-expanded={itemOpen}\n data-testid={`reasoning-pill-${item.label.toLowerCase().replace(/[^a-z0-9]+/g, \"-\")}`}\n >\n {row}\n <span className='oxy-trace__step-chevron'>\n <ChevronIcon open={itemOpen} />\n </span>\n </button>\n ) : (\n <div\n className={cx(\"oxy-trace__row\", item.error && \"oxy-trace__row--error\")}\n data-testid={`reasoning-pill-${item.label.toLowerCase().replace(/[^a-z0-9]+/g, \"-\")}`}\n >\n {row}\n </div>\n )}\n {itemOpen && (\n <div className='oxy-trace__payloads'>\n {item.input && <pre className='oxy-trace__payload'>{item.input}</pre>}\n {item.output && (\n <pre className='oxy-trace__payload oxy-trace__payload--out'>{item.output}</pre>\n )}\n </div>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n\nexport interface ReasoningTraceProps {\n steps: TraceStep[];\n /** True while the run is still streaming — keeps the trace expanded. */\n streaming?: boolean;\n /** Header meta from `aggregateLlmStats` (LLM call count + total time). */\n llm?: { calls: number; totalMs: number };\n className?: string;\n}\n\n/** Renders nothing when there are no steps (runs whose stream carries no\n * step events degrade to the plain answer, same as before). */\nexport function ReasoningTrace({ steps, streaming = false, llm, className }: ReasoningTraceProps) {\n const [userToggled, setUserToggled] = useState<boolean | null>(null);\n // Per-step / per-action overrides: absent → automatic (open while\n // running, collapsed once ended); present → the user's choice wins.\n const [stepToggles, setStepToggles] = useState<Record<string, boolean>>({});\n const [itemToggles, setItemToggles] = useState<Record<string, boolean>>({});\n\n // A new run (first step identity changes) returns every toggle to\n // automatic — render-time reset, the React-documented pattern for\n // adjusting state when a prop changes.\n const runKey = steps[0]?.id ?? \"\";\n const [prevRunKey, setPrevRunKey] = useState(runKey);\n if (prevRunKey !== runKey) {\n setPrevRunKey(runKey);\n setUserToggled(null);\n setStepToggles({});\n setItemToggles({});\n }\n\n // Expanded while streaming; collapses when the run settles — unless the\n // user has taken over the toggle.\n const open = userToggled ?? streaming;\n\n const meta = useMemo(() => {\n const parts: string[] = [];\n if (llm && llm.calls > 0) {\n parts.push(`${llm.calls} LLM ${llm.calls === 1 ? \"call\" : \"calls\"}`);\n if (llm.totalMs > 0) parts.push(formatMs(llm.totalMs));\n }\n parts.push(`${steps.length} step${steps.length === 1 ? \"\" : \"s\"}`);\n if (steps.some((s) => s.status === \"failed\")) parts.push(\"failed\");\n return parts.join(\" · \");\n }, [llm, steps]);\n\n if (steps.length === 0) return null;\n\n return (\n <div className={cx(\"oxy-trace\", className)} data-run={runKey}>\n <button\n type='button'\n className='oxy-trace__head'\n onClick={() => setUserToggled(!open)}\n aria-expanded={open}\n >\n <ChevronIcon open={open} />\n <span className='oxy-trace__title'>Reasoning trace</span>\n <span className='oxy-trace__meta'>{meta}</span>\n {streaming && <span role='status' className='oxy-trace__spin' aria-label='running' />}\n </button>\n {open && (\n <div className='oxy-trace__body'>\n {steps.map((step) => {\n const stepOpen = stepToggles[step.id] ?? step.status === \"running\";\n if (step.items.length === 0) {\n return (\n <div key={step.id} className='oxy-trace__step'>\n <div className='oxy-trace__step-row'>\n <StatusIcon status={step.status} />\n <span className='oxy-trace__label'>{step.label}</span>\n {step.summary && <span className='oxy-trace__summary'>{step.summary}</span>}\n </div>\n </div>\n );\n }\n return (\n <div key={step.id} className='oxy-trace__step'>\n <button\n type='button'\n className='oxy-trace__step-row oxy-trace__step-row--btn'\n onClick={() => setStepToggles((t) => ({ ...t, [step.id]: !stepOpen }))}\n aria-expanded={stepOpen}\n >\n <StatusIcon status={step.status} />\n <span className='oxy-trace__label'>{step.label}</span>\n {step.summary && <span className='oxy-trace__summary'>{step.summary}</span>}\n {!stepOpen && (\n <span className='oxy-trace__count'>\n {step.items.length} action{step.items.length === 1 ? \"\" : \"s\"}\n </span>\n )}\n <span className='oxy-trace__step-chevron'>\n <ChevronIcon open={stepOpen} />\n </span>\n </button>\n {stepOpen && (\n <TraceItemRows\n step={step}\n itemToggles={itemToggles}\n onToggleItem={(id, next) => setItemToggles((t) => ({ ...t, [id]: next }))}\n />\n )}\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n","// API-backed chat history for the Ask dock. Two bundle-gated reads:\n//\n// GET /api/projects/:id/threads → the viewer's recent threads\n// GET /api/projects/:id/threads/:tid → a thread's transcript\n//\n// The transcript returns each turn's events already run through the same\n// processor the live SSE stream uses, so the dock rebuilds the reasoning\n// trace, charts, and answer with `buildTraceSteps` / the chart filter /\n// `extractAnswer` — identical to a live run. See\n// `crates/app/src/server/api/custom_apps_threads.rs`.\n\nimport * as React from \"react\";\nimport { getOxyAppLogger } from \"../custom-app/logger\";\nimport { type AgentRunEvent, type AppFetcher, useOxyApp } from \"../custom-app/react\";\n\nexport interface ThreadSummary {\n id: string;\n title: string;\n created_at: string;\n}\n\nexport interface TranscriptTurn {\n question: string;\n events: AgentRunEvent[];\n}\n\nexport interface ThreadTranscript {\n title: string;\n turns: TranscriptTurn[];\n}\n\nexport interface UseThreadHistoryResult {\n threads: ThreadSummary[];\n loading: boolean;\n error: Error | null;\n /** Re-fetch the list (call after a new chat is archived server-side). */\n refetch: () => void;\n}\n\n/**\n * List the viewer's persistent chat threads for the current project.\n * Non-fatal on failure (older server / no session): returns an empty\n * list so the dock falls back to session-only history.\n */\nexport function useThreadHistory(): UseThreadHistoryResult {\n const { projectId, fetcher } = useOxyApp();\n const [state, setState] = React.useState<{\n threads: ThreadSummary[];\n loading: boolean;\n error: Error | null;\n }>({ threads: [], loading: false, error: null });\n const [nonce, setNonce] = React.useState(0);\n const refetch = React.useCallback(() => setNonce((n) => n + 1), []);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: `nonce` is a manual refetch trigger — not read inside the effect, but bumping it must re-run the fetch (projectId/fetcher are stable across a session)\n React.useEffect(() => {\n if (!projectId) {\n setState({ threads: [], loading: false, error: null });\n return;\n }\n let cancelled = false;\n setState((s) => ({ ...s, loading: true }));\n fetcher(`/api/projects/${projectId}/threads`, { method: \"GET\" })\n .then(async (resp) => {\n if (!resp.ok) throw new Error(`threads list failed: HTTP ${resp.status}`);\n const threads = (await resp.json()) as ThreadSummary[];\n if (!cancelled) setState({ threads, loading: false, error: null });\n })\n .catch((e: unknown) => {\n const error = e instanceof Error ? e : new Error(String(e));\n getOxyAppLogger().log(\"warn\", \"thread history unavailable\", { error: error.message });\n if (!cancelled) setState({ threads: [], loading: false, error });\n });\n return () => {\n cancelled = true;\n };\n }, [projectId, fetcher, nonce]);\n\n return { ...state, refetch };\n}\n\n/**\n * Fetch a thread's transcript for restore. Throws on failure so the\n * caller can surface a toast / fall back.\n */\nexport async function fetchThreadTranscript(\n fetcher: AppFetcher,\n projectId: string,\n threadId: string\n): Promise<ThreadTranscript> {\n const resp = await fetcher(`/api/projects/${projectId}/threads/${threadId}`, { method: \"GET\" });\n if (!resp.ok) throw new Error(`thread transcript failed: HTTP ${resp.status}`);\n return (await resp.json()) as ThreadTranscript;\n}\n","// Ask Oxygen inside a custom app: the same right-side dock the main\n// web-app opens with ⌘K, powered by the SDK's bundle-gated agent-run\n// stream (`useAgentRun`). Multi-turn: follow-ups reuse the run's thread.\n//\n// History is session-scoped: bundles have no server list-threads endpoint,\n// so \"History\" lists chats started in this dock session (restoring one\n// resumes its server thread for follow-ups via the SSE resume). Beyond a\n// quick ask, the header links to the product Chat surface. No\n// extended-thinking toggle — the bundle ask API doesn't carry it.\n\nimport * as React from \"react\";\nimport { type AgentRunEvent, OxyAnswer, useAgentRun, useOxyApp } from \"../custom-app/react\";\nimport { AnswerChart, type ChartBlock } from \"./AnswerChart\";\nimport { cx } from \"./cx\";\nimport { OxyMark } from \"./marks\";\nimport { ReasoningTrace } from \"./ReasoningTrace\";\nimport { fetchThreadTranscript, useThreadHistory } from \"./threadHistory\";\nimport {\n aggregateLlmStats,\n buildTraceSteps,\n extractAnswer,\n extractClarification,\n type TraceStep\n} from \"./trace\";\n\nfunction CloseIcon() {\n return (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='M18 6 6 18' />\n <path d='m6 6 12 12' />\n </svg>\n );\n}\n\nfunction PlusIcon() {\n return (\n <svg\n width='15'\n height='15'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='M5 12h14' />\n <path d='M12 5v14' />\n </svg>\n );\n}\n\nfunction HistoryIcon() {\n return (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8' />\n <path d='M3 3v5h5' />\n <path d='M12 7v5l4 2' />\n </svg>\n );\n}\n\nfunction SearchIcon() {\n return (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <circle cx='11' cy='11' r='8' />\n <path d='m21 21-4.3-4.3' />\n </svg>\n );\n}\n\nfunction ThreadIcon() {\n return (\n <svg\n width='15'\n height='15'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='M14 9a2 2 0 0 1-2 2H6l-4 4V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2z' />\n <path d='M18 9h2a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1' />\n </svg>\n );\n}\n\nfunction ExternalIcon() {\n return (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='M15 3h6v6' />\n <path d='M10 14 21 3' />\n <path d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6' />\n </svg>\n );\n}\n\nfunction ArrowUpIcon() {\n return (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='m5 12 7-7 7 7' />\n <path d='M12 19V5' />\n </svg>\n );\n}\n\nfunction StopIcon() {\n return (\n <svg width='12' height='12' viewBox='0 0 24 24' fill='currentColor' aria-hidden='true'>\n <rect x='6' y='6' width='12' height='12' rx='2' />\n </svg>\n );\n}\n\nexport interface AskDockProps {\n /** Agent the panel asks (the app manifest's `ask.agent`). */\n agentId: string;\n /** Workspace display name for the composer placeholder. */\n workspaceName?: string;\n /** Suggested-question chips shown before the first ask. */\n suggestions?: string[];\n /** \"Open chat in Oxygen\" header link target (product Chat surface). */\n threadsHref?: string;\n open: boolean;\n onClose: () => void;\n className?: string;\n}\n\ninterface CompletedTurn {\n question: string;\n answer: string | null;\n charts: ChartBlock[];\n steps: TraceStep[];\n llm: { calls: number; totalMs: number };\n}\n\ninterface Conversation {\n /** Stable key — the server thread id, or the first question when the\n * thread never got assigned (e.g. a run that failed before starting). */\n id: string;\n title: string;\n turns: CompletedTurn[];\n threadId: string | null;\n /** ISO timestamp the conversation was started — the server thread's\n * `created_at` when restored, else when its first question was asked.\n * Drives the history list's time label and its created_at ordering. */\n createdAt: string;\n}\n\nfunction chartsFrom(events: AgentRunEvent[]): ChartBlock[] {\n return events\n .filter((ev) => ev.type === \"chart_rendered\")\n .map((ev) => ev.data as ChartBlock)\n .filter((b) => b?.config && Array.isArray(b.columns) && Array.isArray(b.rows));\n}\n\n/** History label: a relative \"N minutes/hours/days ago\" for when the\n * conversation was started. */\nfunction formatHistoryTime(iso: string): string {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return \"\";\n const s = Math.max(0, Math.round((Date.now() - d.getTime()) / 1000));\n if (s < 45) return \"just now\";\n const min = Math.round(s / 60);\n if (min < 60) return `${min} minute${min === 1 ? \"\" : \"s\"} ago`;\n const hr = Math.round(s / 3600);\n if (hr < 24) return `${hr} hour${hr === 1 ? \"\" : \"s\"} ago`;\n const day = Math.round(s / 86400);\n if (day < 30) return `${day} day${day === 1 ? \"\" : \"s\"} ago`;\n const mo = Math.round(day / 30);\n if (mo < 12) return `${mo} month${mo === 1 ? \"\" : \"s\"} ago`;\n const yr = Math.round(day / 365);\n return `${yr} year${yr === 1 ? \"\" : \"s\"} ago`;\n}\n\n/** How many history rows to show before the \"Show more\" button. */\nconst HISTORY_PAGE_SIZE = 12;\n\n/** Rebuild a completed turn from a transcript turn's processed events —\n * identical to what the live dock accumulates during a run. */\nfunction turnFromEvents(question: string, events: AgentRunEvent[]): CompletedTurn {\n // A turn that ended in a clarifying question has no `text_delta` answer —\n // fall back to the suspension prompt so it doesn't restore as a blank bubble.\n return {\n question,\n answer: extractAnswer(events) || extractClarification(events) || null,\n charts: chartsFrom(events),\n steps: buildTraceSteps(events),\n llm: aggregateLlmStats(events)\n };\n}\n\n/**\n * The Ask Oxygen drawer. Keep it mounted and toggle `open` — the\n * transcript survives close/reopen, matching the web-app dock.\n */\nexport function AskDock({\n agentId,\n workspaceName,\n suggestions = [],\n threadsHref,\n open,\n onClose,\n className\n}: AskDockProps) {\n const run = useAgentRun({ agentId });\n const { projectId, fetcher } = useOxyApp();\n // Persistent, per-account history (bundle-gated API). Merged with the\n // richer in-session conversations below; empty on older servers.\n const { threads: serverThreads, refetch: refetchHistory } = useThreadHistory();\n const [turns, setTurns] = React.useState<CompletedTurn[]>([]);\n const [pending, setPending] = React.useState<string | null>(null);\n const [draft, setDraft] = React.useState(\"\");\n // Thread of the active conversation. Mirrors run.threadId while a chat is\n // live but is cleared on \"new chat\" so the next ask starts a fresh thread.\n const [threadId, setThreadId] = React.useState<string | null>(null);\n const [history, setHistory] = React.useState<Conversation[]>([]);\n const [historyOpen, setHistoryOpen] = React.useState(false);\n // History panel search text + how many rows are revealed (\"Show more\").\n const [historyQuery, setHistoryQuery] = React.useState(\"\");\n const [historyShown, setHistoryShown] = React.useState(HISTORY_PAGE_SIZE);\n const [restoring, setRestoring] = React.useState(false);\n const scrollRef = React.useRef<HTMLDivElement>(null);\n // Generation guard for the async transcript restore: any conversation\n // switch bumps this, and an in-flight `openServerThread` fetch that\n // resolves afterwards checks it and bails instead of clobbering the now-\n // current turns (which would leave the visible transcript and the resumed\n // thread pointing at different conversations).\n const restoreGenRef = React.useRef(0);\n // Start time of the active conversation, captured once so the history\n // entry keeps a stable created_at (set on the first ask, or to the server\n // thread's created_at when one is restored; cleared on \"new chat\").\n const startedAtRef = React.useRef<string | null>(null);\n\n const busy = run.state === \"running\";\n\n // The reasoning trace mirrors the web-app's analytics view: fold the raw\n // SSE events into step rows + tool/SQL items as they stream. Charts come\n // straight from the pipeline's chart_rendered blocks, rendered natively.\n const liveSteps = React.useMemo(() => buildTraceSteps(run.events), [run.events]);\n const liveLlm = React.useMemo(() => aggregateLlmStats(run.events), [run.events]);\n const liveCharts = React.useMemo(() => chartsFrom(run.events), [run.events]);\n\n // Adopt the server-assigned thread id as it arrives; \"new chat\" resets the\n // local value to null and the old run.threadId won't re-trigger this.\n React.useEffect(() => {\n if (run.threadId) setThreadId(run.threadId);\n }, [run.threadId]);\n\n const finalizedPendingTurn = (): CompletedTurn | null =>\n pending === null\n ? null\n : {\n question: pending,\n answer: run.answer ?? run.clarification,\n charts: liveCharts,\n steps: liveSteps,\n llm: liveLlm\n };\n\n /** The current conversation as a snapshot, or null when it's empty. */\n const snapshotCurrent = (): Conversation | null => {\n const finalized = finalizedPendingTurn();\n const all = finalized ? [...turns, finalized] : turns;\n if (all.length === 0) return null;\n return {\n id: threadId ?? all[0].question,\n title: all[0].question,\n turns: all,\n threadId,\n createdAt: startedAtRef.current ?? new Date().toISOString()\n };\n };\n\n const resetToEmpty = () => {\n restoreGenRef.current += 1;\n run.cancel();\n setTurns([]);\n setPending(null);\n setDraft(\"\");\n setThreadId(null);\n startedAtRef.current = null;\n };\n\n const newChat = () => {\n const snap = snapshotCurrent();\n if (snap) setHistory((h) => [snap, ...h.filter((c) => c.id !== snap.id)]);\n resetToEmpty();\n setHistoryOpen(false);\n };\n\n const openConversation = (conv: Conversation) => {\n restoreGenRef.current += 1;\n const snap = snapshotCurrent();\n setHistory((h) => {\n const rest = h.filter((c) => c.id !== conv.id && (!snap || c.id !== snap.id));\n return snap && snap.id !== conv.id ? [snap, ...rest] : rest;\n });\n run.cancel();\n setTurns(conv.turns);\n setPending(null);\n setDraft(\"\");\n setThreadId(conv.threadId);\n setHistoryOpen(false);\n };\n\n /** Restore a persistent (server) thread: archive the current chat, then\n * fetch + rebuild the transcript. Follow-ups resume the same thread. */\n const openServerThread = async (id: string) => {\n if (!projectId) return;\n const gen = (restoreGenRef.current += 1);\n const snap = snapshotCurrent();\n if (snap && snap.id !== id) {\n setHistory((h) => [snap, ...h.filter((c) => c.id !== snap.id)]);\n }\n run.cancel();\n setTurns([]);\n setPending(null);\n setDraft(\"\");\n setThreadId(id);\n // Preserve the restored thread's own created_at for its history label.\n startedAtRef.current =\n serverThreads.find((t) => t.id === id)?.created_at ?? new Date().toISOString();\n setHistoryOpen(false);\n setRestoring(true);\n try {\n const transcript = await fetchThreadTranscript(fetcher, projectId, id);\n // The user switched conversations while this fetch was in flight —\n // drop the stale result rather than overwrite the current turns.\n if (restoreGenRef.current !== gen) return;\n setTurns(transcript.turns.map((t) => turnFromEvents(t.question, t.events)));\n } catch {\n // Non-fatal: leave the transcript empty; the thread still resumes on\n // the next question (the server has its full context).\n } finally {\n if (restoreGenRef.current === gen) setRestoring(false);\n }\n };\n\n const send = (raw: string) => {\n const question = raw.trim();\n if (!question || busy) return;\n // A new question supersedes any in-flight restore for the prior context.\n restoreGenRef.current += 1;\n // First ask of a fresh chat stamps its start time.\n if (startedAtRef.current === null) startedAtRef.current = new Date().toISOString();\n if (pending !== null) {\n // Archive the finished turn before the hook resets for the next run.\n // A clarification prompt stands in for the answer so the exchange\n // stays readable in the transcript.\n const finalized = finalizedPendingTurn();\n if (finalized) setTurns((t) => [...t, finalized]);\n }\n setPending(question);\n setDraft(\"\");\n run.ask(question, threadId ? { threadId } : undefined);\n };\n\n // Follow the stream: after every render, pin the scroll to the bottom —\n // unless the user has scrolled up to read something, in which case leave\n // them alone. Deliberately no dependency array: tokens arrive on most\n // renders while streaming, and the near-bottom check makes it a no-op\n // otherwise.\n React.useEffect(() => {\n const el = scrollRef.current;\n if (!el) return;\n const nearBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 120;\n if (nearBottom) el.scrollTo({ top: el.scrollHeight });\n });\n\n const empty = pending === null && turns.length === 0;\n const canNewChat = !empty;\n\n // History panel: the active conversation plus every past one — the active\n // one stays in the list (flagged `active` so the UI highlights it rather\n // than hiding it). Matches snapshotCurrent()'s id so it dedupes cleanly.\n const currentId = threadId ?? turns[0]?.question ?? pending ?? null;\n const historyEntries: Array<{\n id: string;\n title: string;\n createdAt: string;\n active: boolean;\n onOpen: () => void;\n }> = [\n ...history.map((c) => ({\n id: c.id,\n title: c.title,\n createdAt: c.createdAt,\n active: c.id === currentId,\n onOpen: c.id === currentId ? () => setHistoryOpen(false) : () => openConversation(c)\n })),\n ...serverThreads\n .filter((t) => !history.some((c) => c.id === t.id))\n .map((t) => ({\n id: t.id,\n title: t.title,\n createdAt: t.created_at,\n active: t.id === currentId,\n onOpen: t.id === currentId ? () => setHistoryOpen(false) : () => void openServerThread(t.id)\n }))\n ];\n // A brand-new chat isn't in the server list yet — surface it so the active\n // conversation is always present (and highlightable).\n if (!empty && currentId != null && !historyEntries.some((e) => e.id === currentId)) {\n historyEntries.push({\n id: currentId,\n title: turns[0]?.question ?? pending ?? currentId,\n createdAt: startedAtRef.current ?? new Date().toISOString(),\n active: true,\n onOpen: () => setHistoryOpen(false)\n });\n }\n // Order strictly by creation time (newest first) — not by which chat was\n // last opened. ISO-8601 strings sort chronologically as plain text.\n historyEntries.sort((a, b) => b.createdAt.localeCompare(a.createdAt));\n\n // Search filter, then reveal up to `historyShown` rows (\"Show more\").\n const q = historyQuery.trim().toLowerCase();\n const filteredEntries = q\n ? historyEntries.filter((e) => e.title.toLowerCase().includes(q))\n : historyEntries;\n const visibleEntries = filteredEntries.slice(0, historyShown);\n\n const placeholder =\n run.state === \"needs_clarification\"\n ? \"Reply…\"\n : pending !== null\n ? \"Ask a follow-up…\"\n : `Ask Oxygen anything about ${workspaceName ?? \"your workspace\"}…`;\n\n return (\n <aside\n className={cx(\"oxy-shell-scope oxy-askdock\", !open && \"oxy-askdock--closed\", className)}\n aria-label='Ask Oxygen'\n aria-hidden={!open}\n >\n <header className='oxy-askdock__head'>\n <OxyMark className='oxy-askdock__mark' />\n <span className='oxy-askdock__title'>Ask Oxygen</span>\n <span className='oxy-askdock__actions'>\n <button\n type='button'\n className='oxy-askdock__iconbtn'\n onClick={newChat}\n disabled={!canNewChat}\n data-testid='askdock-new-chat'\n aria-label='New chat'\n title='New chat'\n >\n <PlusIcon />\n </button>\n <button\n type='button'\n className={cx(\"oxy-askdock__iconbtn\", historyOpen && \"oxy-askdock__iconbtn--active\")}\n onClick={() => {\n const next = !historyOpen;\n setHistoryOpen(next);\n if (next) {\n refetchHistory();\n setHistoryQuery(\"\");\n setHistoryShown(HISTORY_PAGE_SIZE);\n }\n }}\n data-testid='askdock-history'\n aria-label='Chat history'\n aria-expanded={historyOpen}\n title='Chat history'\n >\n <HistoryIcon />\n </button>\n {threadsHref && (\n <a\n className='oxy-askdock__iconbtn'\n href={threadsHref}\n aria-label='Open chat in Oxygen'\n title='Open chat in Oxygen'\n >\n <ExternalIcon />\n </a>\n )}\n <button\n type='button'\n className='oxy-askdock__iconbtn'\n onClick={onClose}\n aria-label='Close Ask Oxygen'\n >\n <CloseIcon />\n </button>\n </span>\n </header>\n\n {historyOpen ? (\n <div className='oxy-askdock__history' data-testid='askdock-history-panel'>\n <div className='oxy-askdock__history-search'>\n <SearchIcon />\n <input\n type='text'\n className='oxy-askdock__history-searchinput'\n placeholder='Search threads…'\n value={historyQuery}\n onChange={(e) => {\n setHistoryQuery(e.target.value);\n setHistoryShown(HISTORY_PAGE_SIZE);\n }}\n aria-label='Search threads'\n />\n </div>\n {visibleEntries.length === 0 ? (\n <p className='oxy-askdock__history-empty'>\n {historyQuery ? \"No matching chats.\" : \"No previous chats yet.\"}\n </p>\n ) : (\n <>\n {visibleEntries.map((entry) => (\n <button\n key={entry.id}\n type='button'\n className={cx(\n \"oxy-askdock__history-item\",\n entry.active && \"oxy-askdock__history-item--active\"\n )}\n onClick={entry.onOpen}\n title={entry.title}\n aria-current={entry.active ? \"true\" : undefined}\n >\n <span className='oxy-askdock__history-icon'>\n <ThreadIcon />\n </span>\n <span className='oxy-askdock__history-title'>{entry.title}</span>\n <span className='oxy-askdock__history-time'>\n {formatHistoryTime(entry.createdAt)}\n </span>\n </button>\n ))}\n {filteredEntries.length > visibleEntries.length && (\n <button\n type='button'\n className='oxy-askdock__history-more'\n onClick={() => setHistoryShown((n) => n + HISTORY_PAGE_SIZE)}\n >\n Show more\n </button>\n )}\n </>\n )}\n </div>\n ) : (\n <>\n <div className='oxy-askdock__scroll' ref={scrollRef}>\n {restoring && <p className='oxy-askdock__history-empty'>Loading conversation…</p>}\n {empty && !restoring && suggestions.length > 0 && (\n <div className='oxy-askdock__chips'>\n {suggestions.map((s) => (\n <button\n key={s}\n type='button'\n className='oxy-askdock__chip'\n onClick={() => send(s)}\n >\n {s}\n </button>\n ))}\n </div>\n )}\n {turns.map((t, i) => (\n <div key={`${i}-${t.question}`} className='oxy-askdock__turn'>\n <div className='oxy-askdock__q'>{t.question}</div>\n <ReasoningTrace steps={t.steps} llm={t.llm} />\n {t.charts.map((c, ci) => (\n <AnswerChart key={`${ci}-${c.config.title ?? c.config.chart_type}`} block={c} />\n ))}\n {/* No artifacts prop: the SQL details live in the reasoning\n trace and the chart — the QUERY block would triple up. */}\n <OxyAnswer answer={t.answer} state='done' threadUrl={null} />\n </div>\n ))}\n {pending !== null && (\n <div className='oxy-askdock__turn'>\n <div className='oxy-askdock__q'>{pending}</div>\n <ReasoningTrace steps={liveSteps} streaming={busy} llm={liveLlm} />\n {liveCharts.map((c, ci) => (\n <AnswerChart key={`${ci}-${c.config.title ?? c.config.chart_type}`} block={c} />\n ))}\n <OxyAnswer\n answer={run.answer}\n state={run.state}\n clarification={run.clarification}\n error={run.error}\n threadUrl={null}\n />\n </div>\n )}\n </div>\n\n <form\n className='oxy-askdock__composer'\n onSubmit={(e) => {\n e.preventDefault();\n send(draft);\n }}\n >\n <textarea\n className='oxy-askdock__input'\n rows={3}\n placeholder={placeholder}\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n send(draft);\n }\n }}\n />\n <div className='oxy-askdock__composer-row'>\n {busy ? (\n <button\n type='button'\n className='oxy-askdock__send'\n onClick={run.cancel}\n aria-label='Stop generating'\n >\n <StopIcon />\n </button>\n ) : (\n <button\n type='submit'\n className='oxy-askdock__send'\n disabled={!draft.trim()}\n aria-label='Send'\n >\n <ArrowUpIcon />\n </button>\n )}\n </div>\n </form>\n </>\n )}\n </aside>\n );\n}\n","/** URL of the workspace logo endpoint (org-uploaded logo, falling back to\n * the code-first file). Consumers render an `<img>` and fall back on error.\n * `apiBaseUrl` is the API root (e.g. `\"/api\"` same-origin, or an absolute\n * base in dev); pass `version` (the org's `updated_at`) to bust the cache\n * after an upload/remove. */\nexport const workspaceLogoUrl = (apiBaseUrl: string, workspaceId: string, version?: string) => {\n const base = `${apiBaseUrl.replace(/\\/$/, \"\")}/${workspaceId}/logo`;\n return version ? `${base}?v=${encodeURIComponent(version)}` : base;\n};\n","import * as React from \"react\";\n\n/**\n * Floating shell content (tooltips) portals into the nearest shell scope\n * element instead of `document.body`, so the `oxy-shell-scope` tokens and a\n * host-applied `.dark` ancestor keep applying to it. Falls back to the\n * default body portal when no provider is mounted (standalone `ShellRail`\n * under a host that themes `<body>` itself).\n */\nexport const ShellPortalContext = React.createContext<HTMLElement | null>(null);\n\n/** Track the portal container element for descendants of a shell root. */\nexport function useShellPortalContainer(): {\n container: HTMLElement | null;\n setContainer: (el: HTMLElement | null) => void;\n} {\n const [container, setContainer] = React.useState<HTMLElement | null>(null);\n return { container, setContainer };\n}\n","import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { ShellPortalContext } from \"./portal\";\n\n/**\n * Hover tooltip for shell controls. Mirrors the web-app's Radix tooltip\n * (zero delay, side arrow, `--zinc-200`/muted surface) but portals into the\n * shell scope so the namespaced tokens and dark-mode class reach it.\n */\nexport function ShellTooltip({\n content,\n side = \"right\",\n children\n}: {\n content: React.ReactNode;\n side?: \"top\" | \"right\" | \"bottom\" | \"left\";\n children: React.ReactNode;\n}) {\n const container = React.useContext(ShellPortalContext);\n return (\n <TooltipPrimitive.Provider delayDuration={0}>\n <TooltipPrimitive.Root>\n <TooltipPrimitive.Trigger asChild>{children}</TooltipPrimitive.Trigger>\n <TooltipPrimitive.Portal container={container ?? undefined}>\n <TooltipPrimitive.Content\n side={side}\n sideOffset={0}\n className='oxy-shell-scope oxy-shell-tooltip'\n >\n {content}\n <TooltipPrimitive.Arrow className='oxy-shell-tooltip__arrow' />\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n </TooltipPrimitive.Root>\n </TooltipPrimitive.Provider>\n );\n}\n","// The 48px icon rail — sole chrome of the workspace shell. Ported from\n// web-app/src/components/Shell/ShellRail.tsx, which was written router-free\n// for exactly this move; the web-app now consumes this component. Keep the\n// two visually identical: this file is the source of truth.\n\nimport { Fragment, type ReactNode, useState } from \"react\";\nimport { cx } from \"./cx\";\nimport { ShellPortalContext, useShellPortalContainer } from \"./portal\";\nimport { ShellTooltip } from \"./Tooltip\";\n\n/** One rail entry. Provide `imageUrl` (custom app mark, falls back to\n * `letter` on load error), `icon` (any SVG node), or `letter`.\n * `href` renders a real anchor (full-page nav — custom apps live outside\n * the SPA); `onSelect` renders a button (SPA nav, wired by the caller). */\nexport type RailItem = {\n key: string;\n label: string;\n /** Hover-tooltip text; defaults to `label`. Use for a richer description\n * while keeping `label` short for the aria-label. */\n tooltip?: string;\n testId?: string;\n active?: boolean;\n icon?: ReactNode;\n letter?: string;\n imageUrl?: string;\n href?: string;\n onSelect?: () => void;\n};\n\nfunction RailEntry({ item }: { item: RailItem }) {\n // Track the URL that failed (not a boolean) so a new imageUrl retries\n // instead of latching the letter fallback forever.\n const [failedUrl, setFailedUrl] = useState<string | null>(null);\n const content =\n item.imageUrl && failedUrl !== item.imageUrl ? (\n <img\n src={item.imageUrl}\n alt=''\n onError={() => setFailedUrl(item.imageUrl ?? null)}\n className='oxy-rail__item-img'\n />\n ) : (\n (item.icon ?? <span className='oxy-rail__item-letter'>{item.letter}</span>)\n );\n const className = cx(\"oxy-rail__item\", item.active && \"oxy-rail__item--active\");\n const ariaCurrent = item.active ? (\"page\" as const) : undefined;\n const entry = item.href ? (\n <a\n href={item.href}\n data-testid={item.testId}\n aria-label={item.label}\n aria-current={ariaCurrent}\n className={className}\n >\n {content}\n </a>\n ) : (\n <button\n type='button'\n onClick={item.onSelect}\n data-testid={item.testId}\n aria-label={item.label}\n aria-current={ariaCurrent}\n className={className}\n >\n {content}\n </button>\n );\n return <ShellTooltip content={item.tooltip ?? item.label}>{entry}</ShellTooltip>;\n}\n\n/** A hairline divider between conceptual rail groups. */\nfunction RailDivider() {\n return <div className='oxy-rail__divider' />;\n}\n\n/** The icon rail. `groups` are the conceptual sections (HQ · Apps ·\n * Intelligence), rendered top-down with a hairline divider between them.\n * `footerItems` pin to the bottom of the scroll area as a distinct\n * \"system\" zone (Oxygen Factory), above the `bottom` account slot\n * (workspace switch · user menu — injected by the host app). */\nexport function ShellRail({\n top,\n groups,\n footerItems,\n bottom,\n className\n}: {\n top?: ReactNode;\n groups: RailItem[][];\n footerItems?: RailItem[];\n bottom?: ReactNode;\n className?: string;\n}) {\n const { container, setContainer } = useShellPortalContainer();\n return (\n <ShellPortalContext.Provider value={container}>\n <div\n ref={setContainer}\n data-testid='shell-rail'\n className={cx(\"oxy-shell-scope oxy-rail\", className)}\n >\n {top && <div className='oxy-rail__top'>{top}</div>}\n <div className='oxy-rail__nav'>\n {groups.map((group, i) => (\n <Fragment key={group[0]?.key ?? i}>\n {i > 0 && <RailDivider />}\n {group.map((item) => (\n <RailEntry key={item.key} item={item} />\n ))}\n </Fragment>\n ))}\n {footerItems && footerItems.length > 0 && (\n <div className='oxy-rail__footer'>\n <RailDivider />\n {footerItems.map((item) => (\n <RailEntry key={item.key} item={item} />\n ))}\n </div>\n )}\n </div>\n {bottom && <div className='oxy-rail__bottom'>{bottom}</div>}\n </div>\n </ShellPortalContext.Provider>\n );\n}\n","// Shell bootstrap data for the wired OxyShell. One bundle-gated request:\n//\n// GET /api/projects/:id/shell-context\n//\n// The server builds every URL in the response (`apps[].url`, `links.*`,\n// `logo_url`) because only it knows which host scheme is in play — an org\n// subdomain serves apps at `/a/<slug>/` same-origin, while a dedicated\n// custom-app subdomain needs absolute product-host URLs. Never derive\n// product URLs client-side. See\n// `crates/app/src/server/api/custom_apps_shell_context.rs`.\n\nimport * as React from \"react\";\nimport { getOxyAppLogger } from \"../custom-app/logger\";\nimport { useOxyApp } from \"../custom-app/react\";\n\nexport interface ShellContextApp {\n id: string;\n name: string;\n slug: string;\n /** Ready-to-navigate URL (relative on the same host, absolute across hosts). */\n url: string;\n icon_url?: string | null;\n /** Agent ref the app's Ask Oxygen panel binds to (manifest `ask.agent`).\n * Absent → the shell hides the Ask surface for this app. */\n default_agent?: string | null;\n /** Composer chips for the Ask panel (manifest `ask.suggestedQuestions`). */\n suggested_questions?: string[];\n}\n\nexport interface ShellContextData {\n workspace: { id: string; name: string };\n org: { id: string; slug: string; name: string };\n /** Workspace logo endpoint URL, or null when no logo is configured. */\n logo_url: string | null;\n /** Published custom apps in this workspace, including the current one. */\n apps: ShellContextApp[];\n /** Product-surface navigation targets, host-aware. `settings` opens the\n * Unified Settings Dialog via the SPA's `?settings=<section>` deep link\n * (optional: absent on servers older than the link). */\n links: { home: string; threads: string; settings?: string };\n /** Viewer display identity; null on unauthenticated/local modes. */\n user: { name: string; email: string; picture?: string | null } | null;\n}\n\nexport interface UseShellContextResult {\n data: ShellContextData | null;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Fetch the shell bootstrap payload for the current custom app. Must be\n * called inside `<OxyAppProvider>`. Failure is non-fatal by design: the\n * shell degrades to chrome-less rendering (older servers don't have the\n * endpoint), so errors are surfaced on the result, never thrown.\n */\nexport function useShellContext(): UseShellContextResult {\n const { projectId, fetcher } = useOxyApp();\n const [state, setState] = React.useState<UseShellContextResult>({\n data: null,\n loading: true,\n error: null\n });\n\n React.useEffect(() => {\n if (!projectId) {\n // No project identity (dev without a server / manifest hint) — nothing\n // to fetch; settle immediately so the shell degrades instead of\n // spinning forever.\n setState({ data: null, loading: false, error: new Error(\"no projectId resolved\") });\n return;\n }\n let cancelled = false;\n fetcher(`/api/projects/${projectId}/shell-context`, { method: \"GET\" })\n .then(async (resp) => {\n if (!resp.ok) {\n throw new Error(`shell-context failed: HTTP ${resp.status}`);\n }\n const data = (await resp.json()) as ShellContextData;\n if (!cancelled) setState({ data, loading: false, error: null });\n })\n .catch((e: unknown) => {\n const error = e instanceof Error ? e : new Error(String(e));\n getOxyAppLogger().log(\"warn\", \"shell-context unavailable, rendering without chrome\", {\n error: error.message\n });\n if (!cancelled) setState({ data: null, loading: false, error });\n });\n return () => {\n cancelled = true;\n };\n }, [projectId, fetcher]);\n\n return state;\n}\n","// The universal top bar: breadcrumb (left) + status, clock, and host-provided\n// actions (right). Ported from web-app/src/components/Shell/TopBar — this is\n// now the source of truth; the web-app composes it with its own Ask Oxygen\n// toggle in the `right` slot.\n\nimport { type ReactNode, useEffect, useMemo, useState } from \"react\";\nimport { cx } from \"./cx\";\nimport { ShellPortalContext, useShellPortalContainer } from \"./portal\";\n\n/** Frame only: left content + right cluster. Mirrors the rail's\n * `--sidebar-background` so the two read as one 48px-tall frame. */\nexport function TopBar({\n left,\n right,\n className\n}: {\n left?: ReactNode;\n right?: ReactNode;\n className?: string;\n}) {\n const { container, setContainer } = useShellPortalContainer();\n return (\n <ShellPortalContext.Provider value={container}>\n <header\n ref={setContainer}\n data-testid='workspace-topbar'\n className={cx(\"oxy-shell-scope oxy-topbar\", className)}\n >\n {left}\n <div className='oxy-topbar__right'>{right}</div>\n </header>\n </ShellPortalContext.Provider>\n );\n}\n\n/**\n * \"<Workspace> / <Page>\" — e.g. \"Poke House / HQ\". The workspace name links\n * back to the HQ home; pass `onHomeNavigate` to intercept for SPA routing\n * (the anchor still carries `homeHref` for middle-click/new-tab).\n */\nexport function Breadcrumb({\n workspaceLabel,\n pageLabel,\n homeHref,\n onHomeNavigate\n}: {\n workspaceLabel: string;\n pageLabel: string;\n homeHref: string;\n onHomeNavigate?: () => void;\n}) {\n return (\n <div className='oxy-breadcrumb'>\n <a\n href={homeHref}\n data-testid='topbar-workspace-link'\n className='oxy-breadcrumb__workspace'\n onClick={\n onHomeNavigate\n ? (e) => {\n // Let modified clicks (new tab, download, …) fall through to\n // the browser; plain left-clicks stay in the SPA.\n if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) return;\n e.preventDefault();\n onHomeNavigate();\n }\n : undefined\n }\n >\n {workspaceLabel}\n </a>\n <span className='oxy-breadcrumb__sep'>/</span>\n <span className='oxy-breadcrumb__page'>{pageLabel}</span>\n </div>\n );\n}\n\n/** `navigator.onLine` + online/offline events. */\nfunction useOnlineStatus(): boolean {\n const [online, setOnline] = useState(() =>\n typeof navigator === \"undefined\" ? true : navigator.onLine\n );\n useEffect(() => {\n const up = () => setOnline(true);\n const down = () => setOnline(false);\n window.addEventListener(\"online\", up);\n window.addEventListener(\"offline\", down);\n return () => {\n window.removeEventListener(\"online\", up);\n window.removeEventListener(\"offline\", down);\n };\n }, []);\n return online;\n}\n\n/**\n * Universal \"Sys: Connected\" indicator — a pulsing green dot when the browser\n * is online, red when offline. Presentational connectivity signal; a real\n * backend health ping can replace `useOnlineStatus` later without touching\n * consumers.\n */\nexport function SystemIndicator() {\n const online = useOnlineStatus();\n return (\n <span data-testid='topbar-system' className='oxy-shell-scope oxy-sysind'>\n <span>Sys:</span>\n <span\n className={cx(\n \"oxy-sysind__state\",\n online ? \"oxy-sysind__state--online\" : \"oxy-sysind__state--offline\"\n )}\n >\n <span className='oxy-sysind__dot-wrap'>\n {online && <span className='oxy-sysind__ping' />}\n <span\n className={cx(\n \"oxy-sysind__dot\",\n online ? \"oxy-sysind__dot--online\" : \"oxy-sysind__dot--offline\"\n )}\n />\n </span>\n {online ? \"Connected\" : \"Offline\"}\n </span>\n </span>\n );\n}\n\n/**\n * Live clock in the given IANA timezone (viewer-local when omitted or\n * invalid). Updates each half-minute (minute precision), pausing while the\n * tab is hidden.\n */\nexport function WorkspaceClock({ timezone }: { timezone?: string }) {\n const [now, setNow] = useState(() => new Date());\n\n useEffect(() => {\n const update = () => setNow(new Date());\n const id = setInterval(() => {\n if (!document.hidden) update();\n }, 30_000);\n // Re-show: tick immediately so the clock isn't up to 30s stale after the\n // tab was backgrounded (interval ticks are skipped while hidden).\n const onVisible = () => {\n if (!document.hidden) update();\n };\n document.addEventListener(\"visibilitychange\", onVisible);\n return () => {\n clearInterval(id);\n document.removeEventListener(\"visibilitychange\", onVisible);\n };\n }, []);\n\n const text = useMemo(() => {\n try {\n return new Intl.DateTimeFormat(undefined, {\n timeZone: timezone,\n hour: \"numeric\",\n minute: \"2-digit\",\n timeZoneName: timezone ? \"short\" : undefined\n }).format(now);\n } catch {\n // Invalid IANA name → local time without a zone label rather than crash.\n return new Intl.DateTimeFormat(undefined, {\n hour: \"numeric\",\n minute: \"2-digit\"\n }).format(now);\n }\n }, [now, timezone]);\n\n return (\n <span data-testid='topbar-clock' className='oxy-shell-scope oxy-clock'>\n {text}\n </span>\n );\n}\n","import { useState } from \"react\";\nimport { cx } from \"./cx\";\n\n/** Rail-top workspace identity: the org/code-first logo when present, the\n * name initial otherwise. Pure branding — switching workspaces is the host\n * app's concern (the rail `bottom` slot). */\nexport function WorkspaceTile({ name, logoUrl }: { name: string; logoUrl?: string }) {\n // Track the URL that failed (not a boolean) so a changed logoUrl —\n // workspace switch, cache-busted re-upload — retries instead of\n // latching the initial fallback for the component's lifetime.\n const [failedUrl, setFailedUrl] = useState<string | null>(null);\n const showLogo = !!logoUrl && failedUrl !== logoUrl;\n\n return (\n <span\n data-testid='rail-workspace'\n title={name}\n // The tile's fill backs the letter fallback; a real logo (often a\n // transparent PNG) sits on its own, so the fill would show through as a\n // grey square. The `--logo` modifier drops it — see shell.css.\n className={cx(\"oxy-shell-scope oxy-workspace-tile\", showLogo && \"oxy-workspace-tile--logo\")}\n >\n {showLogo ? (\n <img\n src={logoUrl}\n alt={name}\n onError={() => setFailedUrl(logoUrl ?? null)}\n className='oxy-workspace-tile__img'\n />\n ) : (\n <span className='oxy-workspace-tile__letter'>{name.slice(0, 1).toUpperCase()}</span>\n )}\n </span>\n );\n}\n","// The wired workspace shell for custom-app bundles: the same icon rail +\n// universal top bar the main web-app renders, fed by the bundle-gated\n// shell-context endpoint. Wrap the app's content with it inside\n// <OxyAppProvider>:\n//\n// <OxyAppProvider>\n// <OxyShell>\n// <Dashboard />\n// </OxyShell>\n// </OxyAppProvider>\n//\n// Degradation contract: chrome must never take the app down. While the\n// bootstrap request is in flight the frame renders with placeholders; if it\n// fails (older server, unauthenticated viewer), the children render bare.\n\nimport { type CSSProperties, type ReactNode, useEffect, useState } from \"react\";\nimport { useOxyApp, useResolvedManifest } from \"../custom-app/react\";\nimport { AskDock } from \"./AskDock\";\nimport { cx } from \"./cx\";\nimport { OxyMark } from \"./marks\";\nimport { ShellPortalContext, useShellPortalContainer } from \"./portal\";\nimport { type RailItem, ShellRail } from \"./ShellRail\";\nimport { type ShellContextData, useShellContext } from \"./shellContext\";\nimport { Breadcrumb, SystemIndicator, TopBar, WorkspaceClock } from \"./TopBar\";\nimport { WorkspaceTile } from \"./WorkspaceTile\";\n\n/** Home/HQ glyph (lucide \"house\" outline, inlined). */\nfunction HouseIcon() {\n return (\n <svg\n width='16'\n height='16'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8' />\n <path d='M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z' />\n </svg>\n );\n}\n\n/** Chat glyph (lucide \"messages-square\" outline, inlined). */\nfunction MessagesIcon() {\n return (\n <svg\n width='16'\n height='16'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='M16 10a2 2 0 0 1-2 2H6l-4 4V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z' />\n <path d='M20 9a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1' />\n </svg>\n );\n}\n\nexport interface OxyShellProps {\n children: ReactNode;\n /** Breadcrumb page label; defaults to this app's registered name. */\n pageLabel?: string;\n /** Replace the top bar's left side (the default workspace/page\n * breadcrumb) with the app's own brand/header content. Host-provided\n * slots keep rendering even when the shell bootstrap is unavailable,\n * so the app never loses its header by adopting the shell. */\n topBarLeft?: ReactNode;\n /** Extra right-side top bar content, rendered after the status cluster\n * (Sys · clock) and before the Ask Oxygen button. */\n topBarExtra?: ReactNode;\n /** Rail bottom slot content. The shell adds no built-in entries here —\n * a bundle that wants a Settings link supplies its own. */\n railBottom?: ReactNode;\n /** Drop the top bar and keep only the rail. */\n hideTopBar?: boolean;\n /** Bind ⌘K / Ctrl+K to toggle the Ask dock (default true). Set false\n * when the host app owns that shortcut; the top-bar button still works. */\n askHotkey?: boolean;\n /** Origin of the Oxygen product (e.g. `https://app.oxygen-hq.com`).\n * shell-context returns product links as relative paths, which resolve\n * correctly when oxy serves the bundle (production, org subdomain). In\n * local dev the bundle runs on its own Vite origin, so those paths would\n * resolve to the app's origin, not oxy's — set this to the oxy origin\n * and the shell rewrites Home / Chat / Settings / app links to absolute\n * URLs. Leave unset in production. */\n productBaseUrl?: string;\n className?: string;\n /** Background of the shell chrome — the icon rail, the top bar, and the\n * AskDock (they share one token). Any CSS color, including `var(--…)` to\n * track a host token (e.g. `var(--background)` to match the app's canvas).\n * Overrides the theme's default; leave unset to keep it. */\n chromeBackground?: string;\n /** Text/icon color on the chrome, paired with `chromeBackground` for\n * contrast when using a background outside the current light/dark family.\n * Unset keeps the theme's foreground. */\n chromeForeground?: string;\n}\n\n/** Rewrite a shell-context relative product path to an absolute URL against\n * the oxy origin, when one is configured. `/api/*` paths are left relative\n * — they ride the host's same-origin fetch / dev proxy (which attaches\n * auth), so absolutizing them would drop the credentials the proxy adds. */\nfunction makeAbs(base: string | undefined) {\n const origin = base?.replace(/\\/$/, \"\");\n return (url?: string | null): string | undefined => {\n if (!url) return undefined;\n if (!origin || !url.startsWith(\"/\") || url.startsWith(\"/api/\")) return url;\n return `${origin}${url}`;\n };\n}\n\nfunction buildRailGroups(\n data: ShellContextData,\n currentAppSlug: string | undefined,\n abs: (url?: string | null) => string | undefined\n): RailItem[][] {\n const hq: RailItem = {\n key: \"hq\",\n label: \"HQ\",\n testId: \"rail-hq\",\n icon: <HouseIcon />,\n href: abs(data.links.home)\n };\n const chat: RailItem = {\n key: \"chat\",\n label: \"Chat\",\n testId: \"rail-chat\",\n icon: <MessagesIcon />,\n href: abs(data.links.threads)\n };\n const appItems: RailItem[] = data.apps.map((app) => ({\n key: app.id,\n label: app.name,\n testId: `rail-app-${app.slug}`,\n letter: app.name.slice(0, 1).toUpperCase(),\n imageUrl: abs(app.icon_url),\n // Every app entry is a real anchor — same as the main web-app's rail.\n // The current app gets `active` (RailEntry adds aria-current=\"page\");\n // re-clicking it is a same-page reload, standard anchor semantics.\n active: app.slug === currentAppSlug,\n href: abs(app.url)\n }));\n return appItems.length ? [[hq, chat], appItems] : [[hq, chat]];\n}\n\n/**\n * The workspace chrome around a custom app: icon rail + universal top bar\n * + content column — visually identical to the main web-app shell.\n */\nexport function OxyShell({\n children,\n pageLabel,\n topBarLeft,\n topBarExtra,\n railBottom,\n hideTopBar,\n askHotkey = true,\n productBaseUrl,\n className,\n chromeBackground,\n chromeForeground\n}: OxyShellProps) {\n const abs = makeAbs(productBaseUrl);\n // Chrome color overrides. We set the HOST tokens (--sidebar-background,\n // --foreground, --muted-foreground) rather than the derived --oxy-shell-*\n // ones: every sub-component (rail, top bar, AskDock…) is its own\n // `.oxy-shell-scope` and re-derives `--oxy-shell-*` from these host tokens,\n // so overriding a derived token here wouldn't reach them — overriding the\n // host token (which they all read via `var()`) does. Only the tokens the\n // caller provides are set; the theme keeps the rest.\n const chromeStyle = {\n ...(chromeBackground ? { \"--sidebar-background\": chromeBackground } : {}),\n ...(chromeForeground\n ? {\n \"--foreground\": chromeForeground,\n \"--muted-foreground\": `color-mix(in srgb, ${chromeForeground} 65%, transparent)`\n }\n : {})\n } as CSSProperties;\n const { appSlug } = useOxyApp();\n // Safe here: OxyAppProvider only renders children once the manifest is\n // resolved, and OxyShell must sit inside the provider.\n const { manifest } = useResolvedManifest();\n const { data, loading } = useShellContext();\n const { container, setContainer } = useShellPortalContainer();\n\n // Bootstrap failed (old server / no session) → degraded: no chrome. The\n // wrapper tree stays MOUNTED in every state (loading → data/degraded) and\n // only the rail/top-bar siblings toggle, so the app's component tree is\n // never reparented — reparenting would remount the whole app and drop its\n // state (queries, form input) exactly when the shell resolves.\n const degraded = !loading && !data;\n\n // `resolved.appSlug` is \"\" (not undefined) when running without server\n // injection — fall back to the manifest's own slug for matching/labels.\n const effectiveSlug = appSlug || manifest.slug;\n const currentApp = data?.apps.find((app) => app.slug === effectiveSlug);\n const workspaceLabel = data ? data.org.name || data.workspace.name : \"\";\n const page = pageLabel ?? currentApp?.name ?? manifest.name ?? effectiveSlug ?? \"\";\n\n // Ask Oxygen: available when this app's manifest binds an agent\n // (`ask.agent`, surfaced by shell-context as `default_agent`). The dock\n // stays mounted once available so its transcript survives close/reopen;\n // ⌘K / Ctrl+K toggles it, same binding as the main web-app.\n const askAgent = currentApp?.default_agent ?? manifest.ask?.agent ?? undefined;\n const askSuggestions = currentApp?.suggested_questions?.length\n ? currentApp.suggested_questions\n : (manifest.ask?.suggestedQuestions ?? []);\n const [askOpen, setAskOpen] = useState(false);\n useEffect(() => {\n if (!askAgent || !askHotkey) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key.toLowerCase() !== \"k\" || !(e.metaKey || e.ctrlKey)) return;\n e.preventDefault();\n setAskOpen((o) => !o);\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [askAgent, askHotkey]);\n\n // Bottom rail slot: the host app's custom content only. The built-in\n // Settings link was removed — a bundle that wants one can supply it via\n // `railBottom`.\n const bottom = railBottom;\n\n return (\n <ShellPortalContext.Provider value={container}>\n <div\n ref={setContainer}\n className={cx(\"oxy-shell-scope oxy-shell\", degraded && \"oxy-shell--degraded\", className)}\n style={chromeStyle}\n >\n {!degraded && (\n <ShellRail\n top={\n data ? (\n <WorkspaceTile name={data.workspace.name} logoUrl={data.logo_url ?? undefined} />\n ) : (\n <span className='oxy-workspace-tile'>\n <OxyMark className='oxy-rail__item-img' />\n </span>\n )\n }\n groups={data ? buildRailGroups(data, effectiveSlug, abs) : [[]]}\n bottom={bottom}\n />\n )}\n <div className='oxy-shell__content-col'>\n {/* The top bar renders in degraded mode too when the host passed\n its own slot content — an app that moved its header into the\n shell must never lose it to a failed bootstrap. Only the\n data-driven pieces (breadcrumb, Ask) hide. */}\n {!hideTopBar && (!degraded || topBarLeft || topBarExtra) && (\n <TopBar\n left={\n topBarLeft ??\n (data ? (\n <Breadcrumb\n workspaceLabel={workspaceLabel}\n pageLabel={page}\n homeHref={abs(data.links.home) ?? data.links.home}\n />\n ) : undefined)\n }\n right={\n <>\n <SystemIndicator />\n <WorkspaceClock />\n {topBarExtra}\n {askAgent && !degraded && (\n <button\n type='button'\n data-testid='ask-oxygen-button'\n onClick={() => setAskOpen((o) => !o)}\n className={cx(\"oxy-askbtn\", askOpen && \"oxy-askbtn--open\")}\n >\n <OxyMark className='oxy-askbtn__mark' />\n <span className='oxy-askbtn__label'>Ask Oxygen</span>\n <kbd className='oxy-askbtn__kbd'>⌘K</kbd>\n </button>\n )}\n </>\n }\n />\n )}\n {/* A div, not <main>: the app's own content very likely carries\n its own main landmark (the scaffolded template does). */}\n <div className='oxy-shell__main'>{children}</div>\n </div>\n {/* Flex sibling of the content column — opening the dock compacts\n the app (Cursor-style) rather than floating over it, matching\n the web-app AskDock. */}\n {askAgent && !degraded && (\n <AskDock\n agentId={askAgent}\n open={askOpen}\n onClose={() => setAskOpen(false)}\n workspaceName={data?.workspace.name}\n suggestions={askSuggestions}\n threadsHref={abs(data?.links.threads)}\n />\n )}\n </div>\n </ShellPortalContext.Provider>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"shell.cjs","names":["React","useState","useMemo","useOxyApp","React","useAgentRun","useOxyApp","React","OxyAnswer","React","React","TooltipPrimitive","useState","Fragment","useOxyApp","React","useState","useMemo","useState","useOxyApp","useResolvedManifest","useState"],"sources":["../src/shell/cx.ts","../src/shell/AnswerChart.tsx","../src/shell/marks.tsx","../src/shell/trace.ts","../src/shell/ReasoningTrace.tsx","../src/shell/threadHistory.ts","../src/shell/AskDock.tsx","../src/shell/logoUrl.ts","../src/shell/portal.tsx","../src/shell/Tooltip.tsx","../src/shell/ShellRail.tsx","../src/shell/shellContext.ts","../src/shell/TopBar.tsx","../src/shell/WorkspaceTile.tsx","../src/shell/OxyShell.tsx"],"sourcesContent":["/** Join truthy class names. Local minimal `clsx` — the shell uses fixed\n * namespaced classes, so no Tailwind-style merge logic is needed. */\nexport function cx(...parts: Array<string | false | null | undefined>): string {\n return parts.filter(Boolean).join(\" \");\n}\n","// Renderer for the analytics pipeline's `chart_rendered` blocks — the same\n// payload the main web-app charts. Uses the host app's ECharts (optional\n// peer, dynamic import) for interactive charts matching the web-app, and\n// falls back to a dependency-free SVG render when echarts isn't installed.\n// Payload shape (see web-app AnalyticsDisplayBlock / ChartConfig):\n// { config: { chart_type, x, y, series, name, value, title, … },\n// columns: string[], rows: unknown[][] }\n\nimport type { ReactNode } from \"react\";\nimport * as React from \"react\";\nimport { cx } from \"./cx\";\n\nexport interface ChartBlockConfig {\n chart_type: \"line_chart\" | \"bar_chart\" | \"pie_chart\" | \"table\";\n x?: string;\n y?: string;\n series?: string;\n name?: string;\n value?: string;\n title?: string;\n x_axis_label?: string;\n y_axis_label?: string;\n}\n\nexport interface ChartBlock {\n config: ChartBlockConfig;\n columns: string[];\n rows: unknown[][];\n}\n\nconst PALETTE = [\"#3b82f6\", \"#22c55e\", \"#eab308\", \"#a855f7\", \"#06b6d4\", \"#f97316\"];\n\nconst compact = new Intl.NumberFormat(\"en\", { notation: \"compact\", maximumFractionDigits: 1 });\nconst toNum = (v: unknown): number => {\n const n = typeof v === \"number\" ? v : Number(v);\n return Number.isFinite(n) ? n : 0;\n};\nconst toStr = (v: unknown): string => (v === null || v === undefined ? \"\" : String(v));\n\n/** \"sales_daily__total_net_sales\" → \"Total Net Sales\" — a friendly series\n * label instead of the raw semantic column id. */\nexport function humanizeCol(name: string | undefined): string {\n const leaf = (name ?? \"\").split(\"__\").pop() ?? \"\";\n return leaf\n .replace(/_/g, \" \")\n .trim()\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\ninterface Pivoted {\n categories: string[];\n series: Array<{ name: string; values: number[] }>;\n}\n\n/** Pivot rows into per-series value arrays aligned on x categories. */\nexport function pivotChart(block: ChartBlock): Pivoted {\n const { config, columns, rows } = block;\n const xi = config.x ? columns.indexOf(config.x) : 0;\n const yi = config.y ? columns.indexOf(config.y) : columns.length > 1 ? 1 : 0;\n const si = config.series ? columns.indexOf(config.series) : -1;\n\n const categories: string[] = [];\n const catIndex = new Map<string, number>();\n for (const row of rows) {\n const cat = toStr(row[xi]);\n if (!catIndex.has(cat)) {\n catIndex.set(cat, categories.length);\n categories.push(cat);\n }\n }\n\n if (si === -1) {\n const values = new Array<number>(categories.length).fill(0);\n for (const row of rows) {\n const idx = catIndex.get(toStr(row[xi]));\n if (idx !== undefined) values[idx] = toNum(row[yi]);\n }\n return { categories, series: [{ name: config.y ?? \"value\", values }] };\n }\n\n const seriesIndex = new Map<string, number[]>();\n for (const row of rows) {\n const name = toStr(row[si]);\n let values = seriesIndex.get(name);\n if (!values) {\n values = new Array<number>(categories.length).fill(0);\n seriesIndex.set(name, values);\n }\n const idx = catIndex.get(toStr(row[xi]));\n if (idx !== undefined) values[idx] = toNum(row[yi]);\n }\n return {\n categories,\n series: [...seriesIndex.entries()].map(([name, values]) => ({ name, values }))\n };\n}\n\n/** A \"nice\" axis ceiling so tick labels land on round numbers. */\nexport function niceCeil(max: number): number {\n if (max <= 0) return 1;\n const pow = 10 ** Math.floor(Math.log10(max));\n const unit = max / pow;\n const nice = unit <= 1 ? 1 : unit <= 2 ? 2 : unit <= 5 ? 5 : 10;\n return nice * pow;\n}\n\n/** Axis domain `[lo, hi]` that always includes zero, with nice round\n * bounds. Signed measures (profit, net change) must render below a zero\n * baseline instead of being clamped to an invisible 0..max axis. */\nexport function axisDomain(values: number[]): { lo: number; hi: number } {\n const rawMax = Math.max(...values, 0);\n const rawMin = Math.min(...values, 0);\n const hi = rawMax > 0 ? niceCeil(rawMax) : 0;\n const lo = rawMin < 0 ? -niceCeil(-rawMin) : 0;\n // Degenerate all-zero data: keep a unit span so ticks still render.\n return hi === lo ? { lo: 0, hi: 1 } : { lo, hi };\n}\n\nconst W = 360;\nconst H = 190;\nconst M = { top: 8, right: 8, bottom: 34, left: 42 };\nconst IW = W - M.left - M.right;\nconst IH = H - M.top - M.bottom;\nconst TICKS = 4;\n\nfunction truncate(label: string, max: number): string {\n return label.length > max ? `${label.slice(0, max - 1)}…` : label;\n}\n\n/** Map a value to its y pixel within the plot area for domain `[lo, hi]`. */\nconst yFor = (v: number, lo: number, hi: number): number =>\n M.top + IH * (1 - (v - lo) / (hi - lo || 1));\n\nfunction Axes({ lo, hi }: { lo: number; hi: number }) {\n const span = hi - lo || 1;\n return (\n <g className='oxy-chart__grid'>\n {Array.from({ length: TICKS + 1 }, (_, i) => {\n const y = M.top + (IH * i) / TICKS;\n const value = hi - (span * i) / TICKS;\n return (\n <g key={i}>\n <line x1={M.left} x2={M.left + IW} y1={y} y2={y} />\n <text x={M.left - 5} y={y + 3} textAnchor='end' className='oxy-chart__tick'>\n {compact.format(value)}\n </text>\n </g>\n );\n })}\n </g>\n );\n}\n\nfunction XLabels({ categories }: { categories: string[] }) {\n const slot = IW / categories.length;\n const maxChars = Math.max(4, Math.floor(slot / 5.5));\n return (\n <g>\n {categories.map((cat, i) => (\n <text\n key={cat}\n x={M.left + slot * (i + 0.5)}\n y={H - M.bottom + 12}\n textAnchor='middle'\n className='oxy-chart__tick'\n >\n <title>{cat}</title>\n {truncate(cat, maxChars)}\n </text>\n ))}\n </g>\n );\n}\n\nfunction BarChart({ data }: { data: Pivoted }) {\n const { lo, hi } = axisDomain(data.series.flatMap((s) => s.values));\n const zeroY = yFor(0, lo, hi);\n const slot = IW / data.categories.length;\n const group = slot * 0.7;\n const barW = group / data.series.length;\n return (\n <svg viewBox={`0 0 ${W} ${H}`} className='oxy-chart__svg' role='img'>\n <Axes lo={lo} hi={hi} />\n {data.series.map((s, si) =>\n s.values.map((v, ci) => {\n // Bars grow from the zero baseline: up for positive values, down\n // for negative — so signed measures stay visible.\n const vy = yFor(v, lo, hi);\n return (\n <rect\n key={`${s.name}-${data.categories[ci]}`}\n x={M.left + slot * ci + (slot - group) / 2 + barW * si}\n y={Math.min(zeroY, vy)}\n width={Math.max(1, barW - 1)}\n height={Math.max(0, Math.abs(vy - zeroY))}\n rx={1.5}\n fill={PALETTE[si % PALETTE.length]}\n >\n <title>{`${data.categories[ci]}${data.series.length > 1 ? ` · ${s.name}` : \"\"}: ${compact.format(v)}`}</title>\n </rect>\n );\n })\n )}\n {lo < 0 && (\n <line className='oxy-chart__grid-zero' x1={M.left} x2={M.left + IW} y1={zeroY} y2={zeroY} />\n )}\n <XLabels categories={data.categories} />\n </svg>\n );\n}\n\nfunction LineChart({ data }: { data: Pivoted }) {\n const { lo, hi } = axisDomain(data.series.flatMap((s) => s.values));\n const zeroY = yFor(0, lo, hi);\n const slot = IW / Math.max(1, data.categories.length - 1 || 1);\n const px = (ci: number) => (data.categories.length === 1 ? M.left + IW / 2 : M.left + slot * ci);\n const py = (v: number) => yFor(v, lo, hi);\n return (\n <svg viewBox={`0 0 ${W} ${H}`} className='oxy-chart__svg' role='img'>\n <Axes lo={lo} hi={hi} />\n {lo < 0 && (\n <line className='oxy-chart__grid-zero' x1={M.left} x2={M.left + IW} y1={zeroY} y2={zeroY} />\n )}\n {data.series.map((s, si) => (\n <g key={s.name}>\n <polyline\n points={s.values.map((v, ci) => `${px(ci)},${py(v)}`).join(\" \")}\n fill='none'\n stroke={PALETTE[si % PALETTE.length]}\n strokeWidth={1.8}\n />\n {s.values.map((v, ci) => (\n <circle\n key={data.categories[ci]}\n cx={px(ci)}\n cy={py(v)}\n r={2.2}\n fill={PALETTE[si % PALETTE.length]}\n >\n <title>{`${data.categories[ci]}${data.series.length > 1 ? ` · ${s.name}` : \"\"}: ${compact.format(v)}`}</title>\n </circle>\n ))}\n </g>\n ))}\n <XLabels categories={data.categories} />\n </svg>\n );\n}\n\nfunction PieChart({ block }: { block: ChartBlock }) {\n const { config, columns, rows } = block;\n const ni = config.name ? columns.indexOf(config.name) : config.x ? columns.indexOf(config.x) : 0;\n const vi = config.value\n ? columns.indexOf(config.value)\n : config.y\n ? columns.indexOf(config.y)\n : 1;\n const slices = rows.map((r) => ({ name: toStr(r[ni]), value: Math.max(0, toNum(r[vi])) }));\n const total = slices.reduce((sum, s) => sum + s.value, 0) || 1;\n\n const cxp = W / 2;\n const cyp = H / 2;\n const r = Math.min(W, H) / 2 - 14;\n let angle = -Math.PI / 2;\n const paths = slices.map((s, i) => {\n const sweep = (s.value / total) * Math.PI * 2;\n const title = `${s.name}: ${compact.format(s.value)} (${Math.round((s.value / total) * 100)}%)`;\n const fill = PALETTE[i % PALETTE.length];\n // A slice covering the whole circle (single slice, or one category at\n // 100%) has coincident arc endpoints, which SVG drops — collapsing the\n // path to a zero-area sliver that renders blank. Draw a full circle\n // instead.\n if (sweep >= Math.PI * 2 - 1e-6) {\n angle += sweep;\n return (\n <circle\n key={s.name}\n cx={cxp}\n cy={cyp}\n r={r}\n fill={fill}\n stroke='var(--oxy-shell-background, #fff)'\n strokeWidth={1}\n >\n <title>{title}</title>\n </circle>\n );\n }\n const x1 = cxp + r * Math.cos(angle);\n const y1 = cyp + r * Math.sin(angle);\n angle += sweep;\n const x2 = cxp + r * Math.cos(angle);\n const y2 = cyp + r * Math.sin(angle);\n const large = sweep > Math.PI ? 1 : 0;\n return (\n <path\n key={s.name}\n d={`M ${cxp} ${cyp} L ${x1} ${y1} A ${r} ${r} 0 ${large} 1 ${x2} ${y2} Z`}\n fill={fill}\n stroke='var(--oxy-shell-background, #fff)'\n strokeWidth={1}\n >\n <title>{title}</title>\n </path>\n );\n });\n return (\n <svg viewBox={`0 0 ${W} ${H}`} className='oxy-chart__svg' role='img'>\n {paths}\n </svg>\n );\n}\n\nconst TABLE_MAX_ROWS = 10;\n\nfunction TableChart({ block }: { block: ChartBlock }) {\n const visible = block.rows.slice(0, TABLE_MAX_ROWS);\n return (\n <div className='oxy-chart__table-wrap'>\n <table className='oxy-chart__table'>\n <thead>\n <tr>\n {block.columns.map((c) => (\n <th key={c}>{c}</th>\n ))}\n </tr>\n </thead>\n <tbody>\n {visible.map((row, i) => (\n <tr key={row.map(toStr).join(\"|\") || i}>\n {block.columns.map((c, j) => (\n <td key={c}>{toStr(row[j])}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n {block.rows.length > TABLE_MAX_ROWS && (\n <div className='oxy-chart__note'>+{block.rows.length - TABLE_MAX_ROWS} more rows</div>\n )}\n </div>\n );\n}\n\n/** Dependency-free SVG rendering — the fallback when the host app has no\n * `echarts`. */\nfunction SvgChart({ block }: { block: ChartBlock }) {\n const data =\n block.config.chart_type === \"bar_chart\" || block.config.chart_type === \"line_chart\"\n ? pivotChart(block)\n : null;\n let body: ReactNode;\n switch (block.config.chart_type) {\n case \"bar_chart\":\n body = data && <BarChart data={data} />;\n break;\n case \"line_chart\":\n body = data && <LineChart data={data} />;\n break;\n case \"pie_chart\":\n body = <PieChart block={block} />;\n break;\n default:\n body = <TableChart block={block} />;\n }\n const multiSeries = data && data.series.length > 1;\n return (\n <>\n {body}\n {multiSeries && (\n <div className='oxy-chart__legend'>\n {data.series.map((s, i) => (\n <span key={s.name} className='oxy-chart__legend-item'>\n <span\n className='oxy-chart__legend-dot'\n style={{ background: PALETTE[i % PALETTE.length] }}\n />\n {s.name}\n </span>\n ))}\n </div>\n )}\n </>\n );\n}\n\n/** Read the shell's design tokens off an element so the ECharts chart\n * matches the surrounding light/dark theme. */\nfunction tokenColors(el: HTMLElement) {\n const cs = getComputedStyle(el);\n const pick = (name: string, fallback: string) => cs.getPropertyValue(name).trim() || fallback;\n return {\n fg: pick(\"--oxy-shell-foreground\", \"#0a0a0a\"),\n muted: pick(\"--oxy-shell-muted-fg\", \"#71717a\"),\n border: pick(\"--oxy-shell-border\", \"#d4d4d8\"),\n bg: pick(\"--oxy-shell-background\", \"#ffffff\")\n };\n}\n\n/** Build the ECharts option for a `chart_rendered` block — the analytics\n * pipeline's `{chart_type, x, y, series, …}` config, the same shape the\n * main web-app charts. Interactive: axis/item tooltips, legend, hover. */\nfunction buildEchartsOption(block: ChartBlock, el: HTMLElement): Record<string, unknown> {\n const { fg, muted, border } = tokenColors(el);\n const axisLabel = { color: muted, fontSize: 10 };\n const ct = block.config.chart_type;\n\n if (ct === \"pie_chart\") {\n const { config, columns, rows } = block;\n const ni = config.name\n ? columns.indexOf(config.name)\n : config.x\n ? columns.indexOf(config.x)\n : 0;\n const vi = config.value\n ? columns.indexOf(config.value)\n : config.y\n ? columns.indexOf(config.y)\n : 1;\n const data = rows.map((r) => ({ name: toStr(r[ni]), value: Math.max(0, toNum(r[vi])) }));\n return {\n color: PALETTE,\n tooltip: { trigger: \"item\", formatter: \"{b}: {c} ({d}%)\" },\n legend: { bottom: 0, textStyle: { color: muted, fontSize: 10 }, type: \"scroll\" },\n series: [\n {\n type: \"pie\",\n radius: [\"38%\", \"66%\"],\n center: [\"50%\", \"44%\"],\n data,\n label: { color: fg, fontSize: 10 },\n labelLine: { lineStyle: { color: border } }\n }\n ]\n };\n }\n\n const pivot = pivotChart(block);\n const multi = pivot.series.length > 1;\n // Friendly single-series label: the axis label, else the humanized y col\n // (never the raw \"table__column\" id that shows in the tooltip/legend).\n const singleName = block.config.y_axis_label || humanizeCol(block.config.y) || \"Value\";\n // Long / many categories overlap on a horizontal axis → show every label\n // rotated + truncated so no bar is left unlabeled.\n const longLabels = pivot.categories.length > 4 || pivot.categories.some((c) => c.length > 10);\n return {\n color: PALETTE,\n tooltip: {\n trigger: \"axis\",\n valueFormatter: (v: unknown) => (typeof v === \"number\" ? compact.format(v) : String(v))\n },\n grid: { left: 6, right: 12, top: multi ? 30 : 12, bottom: 4, containLabel: true },\n legend: multi\n ? { top: 0, textStyle: { color: muted, fontSize: 10 }, type: \"scroll\" }\n : undefined,\n xAxis: {\n type: \"category\",\n data: pivot.categories,\n name: block.config.x_axis_label,\n nameLocation: \"middle\",\n nameGap: longLabels ? 42 : 24,\n nameTextStyle: { color: muted, fontSize: 10 },\n axisLabel: {\n ...axisLabel,\n interval: 0,\n rotate: longLabels ? 30 : 0,\n formatter: (v: string) => (v.length > 18 ? `${v.slice(0, 17)}…` : v)\n },\n axisTick: { show: false },\n axisLine: { lineStyle: { color: border } }\n },\n yAxis: {\n type: \"value\",\n name: block.config.y_axis_label,\n nameTextStyle: { color: muted, fontSize: 10 },\n axisLabel: { ...axisLabel, formatter: (v: number) => compact.format(v) },\n splitLine: { lineStyle: { color: border, opacity: 0.5 } }\n },\n series: pivot.series.map((s, i) => ({\n name: multi ? s.name : singleName,\n type: ct === \"bar_chart\" ? \"bar\" : \"line\",\n data: s.values,\n itemStyle: { color: PALETTE[i % PALETTE.length] },\n ...(ct === \"line_chart\" ? { lineStyle: { width: 2 }, symbolSize: 5, smooth: false } : {}),\n barMaxWidth: 32\n }))\n };\n}\n\nexport interface AnswerChartProps {\n block: ChartBlock;\n className?: string;\n}\n\n/** Renders one `chart_rendered` block. Uses ECharts (interactive, matching\n * the main web-app) when the host app has it installed; otherwise falls\n * back to a dependency-free SVG render. Table type always uses SVG. */\nexport function AnswerChart({ block, className }: AnswerChartProps) {\n const ref = React.useRef<HTMLDivElement>(null);\n // \"pending\" while we try ECharts; \"svg\" once we know it isn't available\n // (or for the table type, which ECharts doesn't draw).\n const [engine, setEngine] = React.useState<\"pending\" | \"svg\">(\n block.config.chart_type === \"table\" ? \"svg\" : \"pending\"\n );\n\n React.useEffect(() => {\n if (engine === \"svg\") return;\n let disposed = false;\n let chart: { setOption: (o: unknown) => void; resize: () => void; dispose: () => void } | null =\n null;\n let ro: ResizeObserver | null = null;\n // `@vite-ignore` keeps the specifier out of the consumer's static build\n // graph: echarts is an OPTIONAL peer, so a bundle that doesn't install it\n // must still `vite build`. Without this, Rollup tries to resolve \"echarts\"\n // at build time and aborts — the runtime `.catch()` SVG fallback below\n // never gets a chance to run. Ignored here → resolved at runtime → the\n // catch fires and we fall back to SVG when echarts is absent.\n import(/* @vite-ignore */ \"echarts\")\n .then((echarts) => {\n const el = ref.current;\n if (disposed || !el) return;\n chart = echarts.init(el, undefined, { renderer: \"canvas\" });\n chart.setOption(buildEchartsOption(block, el));\n ro = new ResizeObserver(() => chart?.resize());\n ro.observe(el);\n })\n .catch(() => {\n // echarts not installed in the host app → SVG fallback.\n if (!disposed) setEngine(\"svg\");\n });\n return () => {\n disposed = true;\n ro?.disconnect();\n chart?.dispose();\n };\n }, [block, engine]);\n\n return (\n <figure className={cx(\"oxy-chart\", className)} data-testid='askdock-chart'>\n {block.config.title && (\n <figcaption className='oxy-chart__title'>{block.config.title}</figcaption>\n )}\n {engine === \"svg\" ? (\n <SvgChart block={block} />\n ) : (\n <div ref={ref} className='oxy-chart__echarts' style={{ width: \"100%\", height: 240 }} />\n )}\n </figure>\n );\n}\n","// Inline brand marks so external bundles don't need the web-app's static\n// assets. Path data is copied from web-app (OxyMark.tsx and\n// public/oxygen-factory-mark-{light,dark}.svg) — keep in sync on rebrands.\n\n/** The Oxygen \"O\" glyph path, in a 0 0 44 44 viewBox, used by `OxyMark`. */\nexport const OXY_MARK_PATH =\n \"M38.4 22C39.2837 22 40.0074 22.7178 39.9289 23.5979C39.6619 26.5942 38.6471 29.485 36.9665 32.0003C34.9886 34.9603 32.1774 37.2674 28.8883 38.6298C25.5992 39.9922 21.98 40.3487 18.4884 39.6541C14.9967 38.9596 11.7894 37.2453 9.27209 34.7279C6.75474 32.2106 5.04041 29.0033 4.34587 25.5116C3.65134 22.02 4.0078 18.4008 5.37018 15.1117C6.73255 11.8226 9.03966 9.0114 11.9997 7.03353C14.515 5.35287 17.4058 4.33807 20.4021 4.07104C21.2822 3.9926 22 4.71633 22 5.59998L22 11.2C22 12.0837 22.7163 12.8 23.6 12.8H29.2C30.0837 12.8 30.8 12.0837 30.8 11.2V5.6C30.8 4.71634 31.5163 4 32.4 4H38.4C39.2836 4 40 4.71634 40 5.6V11.6C40 12.4837 39.2836 13.2 38.4 13.2H32.8C31.9163 13.2 31.2 13.9163 31.2 14.8V20.4C31.2 21.2837 31.9163 22 32.8 22L38.4 22ZM23.6 22C22.7163 22 22 21.2837 22 20.4L22 14.8371C22 13.9534 21.2778 13.2223 20.4089 13.3827C19.2427 13.5981 18.1268 14.0489 17.1316 14.7139C15.6905 15.6768 14.5674 17.0454 13.9041 18.6466C13.2409 20.2478 13.0674 22.0097 13.4055 23.7095C13.7436 25.4094 14.5782 26.9708 15.8037 28.1963C17.0292 29.4218 18.5906 30.2564 20.2904 30.5945C21.9903 30.9326 23.7522 30.7591 25.3534 30.0959C26.9546 29.4326 28.3232 28.3095 29.2861 26.8684C29.9511 25.8732 30.4019 24.7573 30.6172 23.5911C30.7777 22.7222 30.0466 22 29.1629 22L23.6 22Z\";\n\n/** The Oxygen \"O\" mark as an inline SVG that inherits `currentColor`, so it\n * reads correctly on any surface in light or dark mode. */\nexport function OxyMark({ className }: { className?: string }) {\n return (\n <svg\n viewBox='0 0 44 44'\n fill='currentColor'\n xmlns='http://www.w3.org/2000/svg'\n className={className}\n aria-hidden='true'\n >\n <path fillRule='evenodd' clipRule='evenodd' d={OXY_MARK_PATH} />\n </svg>\n );\n}\n\nconst FACTORY_PATHS = [\n \"M64.7079 60.8981C66.2159 61.5769 66.42 63.424 64.8831 64.0349C53.9237 68.3911 22.4112 68.2339 12.6945 62.9613C11.4576 62.2901 11.6244 60.6958 12.7979 59.9191C17.3748 56.8895 25.3973 51.7874 31.0332 48.4864C31.9361 47.9575 33.0153 47.8364 34.0043 48.1784C41.0152 50.6027 55.7832 56.8809 64.7079 60.8981Z\",\n \"M40.8612 14.4068C40.6005 13.1343 41.6723 12.0367 42.847 12.591C53.7523 17.7375 68.2377 45.3963 68.9964 57.4238C69.0787 58.7282 67.7002 59.4009 66.5675 58.7485C62.2989 56.2901 53.2249 51.0848 48.6689 48.6258C47.5323 48.0123 46.7649 46.8912 46.5938 45.611C45.4688 37.1953 42.1634 20.7629 40.8612 14.4068Z\",\n \"M39.2805 32.7689C39.2947 33.8426 38.8352 34.8657 38.0314 35.5777C28.4104 44.1006 18.5237 51.9152 13.0125 56.3133C11.7919 57.2874 10.0954 56.4483 10.3571 54.9087C12.5527 41.9933 25.758 17.8554 35.9571 12.7314C36.9805 12.2172 38.0789 12.9771 38.1857 14.1175C38.5311 17.8049 39.186 25.6228 39.2805 32.7689Z\"\n];\n\n/** The Oxygen Factory mark (three-shard glyph) as an inline SVG in\n * `currentColor`, so it follows the shell foreground in either theme.\n * (The web-app's asset files are fixed-color; this inline variant frees\n * external bundles from carrying those assets.) Decorative — the rail\n * button supplies the \"Oxygen Factory\" aria-label. */\nexport function OxygenFactoryMark({ className }: { className?: string }) {\n return (\n <svg\n viewBox='0 0 80 80'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n className={className}\n aria-hidden='true'\n >\n {FACTORY_PATHS.map((d) => (\n <path key={d.slice(0, 16)} d={d} fill='currentColor' />\n ))}\n </svg>\n );\n}\n","// Reasoning-trace builder for the Ask dock: folds the raw agent-run SSE\n// events (`useAgentRun().events`) into the same step/tool/SQL shape the\n// main web-app's AnalyticsReasoningTrace renders — the bundle stream goes\n// through the same server-side EventRegistry processor, so the event\n// vocabulary matches (`step_start`/`step_end`, `tool_call`/`tool_result`,\n// `query_executed`, …). Deliberately lighter than the web-app hook: no\n// fan-out cards, no thinking token stream, no artifact sidebar — labels,\n// statuses, and result summaries only.\n\nimport type { AgentRunEvent } from \"../custom-app/react\";\n\nexport type TraceStepStatus = \"running\" | \"done\" | \"failed\" | \"suspended\";\n\nexport interface TraceItem {\n id: string;\n kind: \"tool\" | \"sql\" | \"note\" | \"thinking\";\n label: string;\n /** Muted inline preview of the tool input / query intent. */\n preview?: string;\n /** Right-aligned detail, e.g. \"22 rows · 1.4s\". */\n detail?: string;\n /** Body text (thinking items) — rendered as a wrapped paragraph. */\n text?: string;\n /** Full tool input / SQL, pretty-printed — the expandable detail body. */\n input?: string;\n /** Full tool output / result summary, pretty-printed. */\n output?: string;\n error?: boolean;\n running?: boolean;\n}\n\nexport interface TraceStep {\n id: string;\n label: string;\n summary?: string;\n status: TraceStepStatus;\n items: TraceItem[];\n}\n\nconst str = (v: unknown): string | undefined => (typeof v === \"string\" ? v : undefined);\nconst num = (v: unknown): number | undefined => (typeof v === \"number\" ? v : undefined);\n\n/** \"search_catalog\" -> \"Search Catalog\" — matches the web-app pill labels. */\nexport function prettyToolName(name: string): string {\n return name\n .split(/[_-]+/)\n .filter(Boolean)\n .map((w) => w[0].toUpperCase() + w.slice(1))\n .join(\" \");\n}\n\n/** Compact one-line preview of a tool input (string arg or first string\n * field of an object), truncated for the trace row. */\nfunction inputPreview(input: unknown, max = 60): string | undefined {\n // The stream often pre-serializes the tool input — unwrap JSON strings so\n // the preview shows the human part (\"top stores by revenue\"), not braces.\n if (typeof input === \"string\" && /^[[{]/.test(input.trim())) {\n try {\n return inputPreview(JSON.parse(input), max);\n } catch {\n // fall through — treat as plain text\n }\n }\n let text: string | undefined;\n if (typeof input === \"string\") text = input;\n else if (Array.isArray(input)) {\n const first = input.find((v) => typeof v === \"string\" && v.trim());\n text = typeof first === \"string\" ? first : JSON.stringify(input);\n } else if (input && typeof input === \"object\") {\n for (const v of Object.values(input as Record<string, unknown>)) {\n if (typeof v === \"string\" && v.trim()) {\n text = v;\n break;\n }\n }\n if (!text) {\n const json = JSON.stringify(input);\n text = json === \"{}\" ? undefined : json;\n }\n }\n if (!text) return undefined;\n text = text.replace(/\\s+/g, \" \").trim();\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\n/** Full pretty-printed payload for the expandable row detail: unwraps\n * pre-serialized JSON strings, indents objects, caps runaway sizes. */\nfunction prettyPayload(v: unknown, max = 2000): string | undefined {\n if (v === null || v === undefined) return undefined;\n let val: unknown = v;\n if (typeof val === \"string\") {\n const t = val.trim();\n if (!t) return undefined;\n if (/^[[{]/.test(t)) {\n try {\n val = JSON.parse(t);\n } catch {\n // keep the raw string\n }\n }\n }\n const text = typeof val === \"string\" ? val : JSON.stringify(val, null, 2);\n if (!text || text === \"{}\" || text === \"[]\") return undefined;\n return text.length > max ? `${text.slice(0, max)}\\n…` : text;\n}\n\nexport function formatMs(ms: number): string {\n return ms >= 1000 ? `${(ms / 1000).toFixed(1)}s` : `${ms}ms`;\n}\n\n/** Header meta, same as the web-app trace: LLM call count + total LLM time\n * folded from `llm_usage` events. */\nexport function aggregateLlmStats(events: AgentRunEvent[]): { calls: number; totalMs: number } {\n let calls = 0;\n let totalMs = 0;\n for (const ev of events) {\n if (ev.type !== \"llm_usage\") continue;\n calls++;\n const d = (ev.data ?? {}) as Record<string, unknown>;\n totalMs += num(d.duration_ms) ?? 0;\n }\n return { calls, totalMs };\n}\n\n/** Reconstruct the streamed answer markdown from persisted events —\n * concatenate the `text_delta` tokens, the same accumulation the live\n * `useAgentRun` does. Used to rebuild a turn's answer on history restore. */\nexport function extractAnswer(events: AgentRunEvent[]): string {\n let out = \"\";\n for (const ev of events) {\n if (ev.type !== \"text_delta\") continue;\n const d = (ev.data ?? {}) as Record<string, unknown>;\n if (typeof d.token === \"string\") out += d.token;\n }\n return out;\n}\n\n/** Pull the clarifying-question prompt from a persisted `awaiting_input`\n * event (`{ questions: [{ prompt, suggestions }] }`) so a turn that ended\n * in a suspension restores with its question instead of a blank answer.\n * Mirrors the live `useAgentRun` clarification parse. */\nexport function extractClarification(events: AgentRunEvent[]): string | null {\n for (const ev of events) {\n if (ev.type !== \"awaiting_input\") continue;\n const d = (ev.data ?? {}) as Record<string, unknown>;\n const questions = Array.isArray(d.questions) ? d.questions : [];\n const first = questions[0] as Record<string, unknown> | undefined;\n if (first && typeof first.prompt === \"string\") return first.prompt;\n // Older single-question shape: `{ question: \"…\" }`.\n if (typeof d.question === \"string\") return d.question;\n }\n return null;\n}\n\nfunction sqlDetail(d: Record<string, unknown>): string | undefined {\n const parts: string[] = [];\n const rows = num(d.row_count) ?? (Array.isArray(d.rows) ? d.rows.length : undefined);\n if (rows !== undefined) parts.push(`${rows} row${rows === 1 ? \"\" : \"s\"}`);\n const ms = num(d.duration_ms);\n if (ms !== undefined) parts.push(formatMs(ms));\n return parts.length ? parts.join(\" · \") : undefined;\n}\n\n/** Mark any still-running items in a step as settled — called when the step\n * closes so a tool/SQL/semantic row whose matching result never arrived\n * (cancel, error mid-flight, terminal event) doesn't spin forever on a\n * finished turn. */\nfunction settleStepItems(step: TraceStep, asError = false): void {\n for (const item of step.items) {\n if (item.running) {\n item.running = false;\n if (asError) item.error = true;\n }\n }\n}\n\n/** Fold raw SSE events into display steps. Pure — safe to re-run on every\n * render over the accumulated event array. */\nexport function buildTraceSteps(events: AgentRunEvent[]): TraceStep[] {\n const steps: TraceStep[] = [];\n let open: TraceStep | null = null;\n let n = 0;\n const id = (prefix: string) => `${prefix}-${n++}`;\n\n const ensureStep = (): TraceStep => {\n if (open) return open;\n open = { id: id(\"step\"), label: \"Working\", status: \"running\", items: [] };\n steps.push(open);\n return open;\n };\n const lastRunning = (kind: TraceItem[\"kind\"]): TraceItem | undefined => {\n for (let i = steps.length - 1; i >= 0; i--) {\n const items = steps[i].items;\n for (let j = items.length - 1; j >= 0; j--) {\n const item = items[j];\n if (item.kind === kind && item.running) return item;\n }\n }\n return undefined;\n };\n\n for (const ev of events) {\n const d = (ev.data ?? {}) as Record<string, unknown>;\n switch (ev.type) {\n case \"step_start\": {\n // A dangling open step means its step_end never arrived (crash /\n // recovery) — close it as done rather than leaving a spinner.\n if (open) {\n settleStepItems(open);\n open.status = \"done\";\n }\n open = {\n id: id(\"step\"),\n label: str(d.label) ?? \"Step\",\n summary: str(d.summary),\n status: \"running\",\n items: []\n };\n steps.push(open);\n break;\n }\n case \"step_end\": {\n if (!open) break;\n const outcome = str(d.outcome);\n open.status =\n outcome === \"failed\" ? \"failed\" : outcome === \"suspended\" ? \"suspended\" : \"done\";\n settleStepItems(open, open.status === \"failed\");\n open = null;\n break;\n }\n case \"step_summary_update\": {\n const summary = str(d.summary);\n if (open && summary) open.summary = summary;\n break;\n }\n\n case \"tool_call\": {\n const name = str(d.name) ?? \"tool\";\n ensureStep().items.push({\n id: id(\"tool\"),\n kind: \"tool\",\n label: prettyToolName(name),\n preview: inputPreview(d.input),\n input: prettyPayload(d.input),\n running: true\n });\n break;\n }\n case \"tool_result\": {\n const item = lastRunning(\"tool\");\n if (item) {\n item.running = false;\n item.error = d.is_error === true;\n item.output = prettyPayload(d.output);\n const ms = num(d.duration_ms);\n if (ms !== undefined) item.detail = formatMs(ms);\n }\n break;\n }\n\n case \"thinking_start\":\n ensureStep().items.push({\n id: id(\"think\"),\n kind: \"thinking\",\n label: \"Thinking\",\n text: \"\",\n running: true\n });\n break;\n case \"thinking_token\": {\n const item = lastRunning(\"thinking\");\n if (item) item.text = (item.text ?? \"\") + (str(d.token) ?? \"\");\n break;\n }\n case \"thinking_end\": {\n const item = lastRunning(\"thinking\");\n if (item) item.running = false;\n break;\n }\n\n case \"semantic_shortcut_attempted\":\n ensureStep().items.push({\n id: id(\"sem\"),\n kind: \"tool\",\n label: \"Compile semantic query\",\n input: prettyPayload(d),\n running: true\n });\n break;\n case \"semantic_shortcut_resolved\": {\n const item = lastRunning(\"tool\");\n if (item) {\n item.running = false;\n item.output = prettyPayload(d.sql ?? d);\n }\n break;\n }\n\n case \"query_executed\": {\n const failed = d.success === false;\n ensureStep().items.push({\n id: id(\"sql\"),\n kind: \"sql\",\n label: failed ? \"Query failed\" : \"Query\",\n detail: failed ? (str(d.error) ?? undefined) : sqlDetail(d),\n input: prettyPayload(d.query ?? d.sql),\n output: failed ? prettyPayload(d.error) : undefined,\n error: failed\n });\n break;\n }\n case \"verified_sql\":\n ensureStep().items.push({\n id: id(\"sql\"),\n kind: \"sql\",\n label: \"Verified query\",\n detail: sqlDetail(d),\n input: prettyPayload(d.query ?? d.sql)\n });\n break;\n\n case \"schema_resolved\": {\n const tables = Array.isArray(d.tables) ? d.tables.length : undefined;\n ensureStep().items.push({\n id: id(\"schema\"),\n kind: \"note\",\n label: \"Schema resolved\",\n detail: tables ? `${tables} table${tables === 1 ? \"\" : \"s\"}` : undefined\n });\n break;\n }\n\n case \"recovery_resumed\": {\n if (open) {\n settleStepItems(open);\n open.status = \"done\";\n open = null;\n }\n steps.push({\n id: id(\"step\"),\n label: \"Resuming\",\n summary: str(d.message) ?? \"Resuming from server restart\",\n status: \"done\",\n items: []\n });\n break;\n }\n\n case \"awaiting_input\": {\n // Suspension for a clarifying question — close the open step so its\n // tool/SQL rows stop spinning while the run waits on the user.\n if (open) {\n settleStepItems(open);\n open.status = \"suspended\";\n open = null;\n }\n break;\n }\n\n case \"error\":\n case \"failed\": {\n if (open) {\n settleStepItems(open, true);\n open.status = \"failed\";\n open = null;\n }\n break;\n }\n case \"done\":\n case \"cancelled\": {\n if (open) {\n settleStepItems(open);\n open.status = \"done\";\n open = null;\n }\n break;\n }\n default:\n break;\n }\n }\n return steps;\n}\n","// Reasoning trace for the Ask dock — the compact cousin of the web-app's\n// AnalyticsReasoningTrace: header meta (LLM calls · time · steps), one row\n// per step (status icon · label · summary), and indented item rows —\n// tool calls with input previews and durations, thinking text, queries\n// with row counts.\n//\n// Collapse model: the whole trace is expanded while the run streams and\n// collapses to the header line when it settles. Within the trace, each\n// step shows its item rows while it RUNS and auto-collapses to its header\n// once it ends; clicking a step (any time, including after the run) takes\n// over that step's toggle.\n\nimport { useMemo, useState } from \"react\";\nimport { cx } from \"./cx\";\nimport { formatMs, type TraceStep } from \"./trace\";\n\nfunction StatusIcon({ status }: { status: TraceStep[\"status\"] }) {\n if (status === \"running\")\n return <span role='status' className='oxy-trace__spin' aria-label='running' />;\n if (status === \"failed\") return <span className='oxy-trace__icon oxy-trace__icon--fail'>✕</span>;\n if (status === \"suspended\")\n return <span className='oxy-trace__icon oxy-trace__icon--wait'>…</span>;\n return <span className='oxy-trace__icon oxy-trace__icon--ok'>✓</span>;\n}\n\nfunction ChevronIcon({ open }: { open: boolean }) {\n return (\n <svg\n width='12'\n height='12'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n style={{ transform: open ? \"rotate(90deg)\" : undefined, transition: \"transform 0.15s\" }}\n >\n <path d='m9 18 6-6-6-6' />\n </svg>\n );\n}\n\nfunction TraceItemRows({\n step,\n itemToggles,\n onToggleItem\n}: {\n step: TraceStep;\n itemToggles: Record<string, boolean>;\n onToggleItem: (id: string, open: boolean) => void;\n}) {\n return (\n <div className='oxy-trace__items'>\n {step.items.map((item) => {\n if (item.kind === \"thinking\") {\n return (item.text ?? \"\").trim() ? (\n <p key={item.id} className='oxy-trace__think'>\n {item.text}\n </p>\n ) : null;\n }\n const hasDetail = Boolean(item.input || item.output);\n // Same collapse model as steps: detail is visible while the action\n // runs, folds when it completes, and a click wins from then on.\n const itemOpen = hasDetail && (itemToggles[item.id] ?? item.running === true);\n const row = (\n <>\n {item.running && (\n <span\n role='status'\n className='oxy-trace__spin oxy-trace__spin--sm'\n aria-label='running'\n />\n )}\n <span className='oxy-trace__row-label'>{item.label}</span>\n {item.preview && <span className='oxy-trace__row-preview'>{item.preview}</span>}\n {item.detail && <span className='oxy-trace__row-detail'>{item.detail}</span>}\n </>\n );\n return (\n <div key={item.id} className='oxy-trace__item'>\n {hasDetail ? (\n <button\n type='button'\n className={cx(\n \"oxy-trace__row\",\n \"oxy-trace__row--btn\",\n item.error && \"oxy-trace__row--error\"\n )}\n onClick={() => onToggleItem(item.id, !itemOpen)}\n aria-expanded={itemOpen}\n data-testid={`reasoning-pill-${item.label.toLowerCase().replace(/[^a-z0-9]+/g, \"-\")}`}\n >\n {row}\n <span className='oxy-trace__step-chevron'>\n <ChevronIcon open={itemOpen} />\n </span>\n </button>\n ) : (\n <div\n className={cx(\"oxy-trace__row\", item.error && \"oxy-trace__row--error\")}\n data-testid={`reasoning-pill-${item.label.toLowerCase().replace(/[^a-z0-9]+/g, \"-\")}`}\n >\n {row}\n </div>\n )}\n {itemOpen && (\n <div className='oxy-trace__payloads'>\n {item.input && <pre className='oxy-trace__payload'>{item.input}</pre>}\n {item.output && (\n <pre className='oxy-trace__payload oxy-trace__payload--out'>{item.output}</pre>\n )}\n </div>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n\nexport interface ReasoningTraceProps {\n steps: TraceStep[];\n /** True while the run is still streaming — keeps the trace expanded. */\n streaming?: boolean;\n /** Header meta from `aggregateLlmStats` (LLM call count + total time). */\n llm?: { calls: number; totalMs: number };\n className?: string;\n}\n\n/** Renders nothing when there are no steps (runs whose stream carries no\n * step events degrade to the plain answer, same as before). */\nexport function ReasoningTrace({ steps, streaming = false, llm, className }: ReasoningTraceProps) {\n const [userToggled, setUserToggled] = useState<boolean | null>(null);\n // Per-step / per-action overrides: absent → automatic (open while\n // running, collapsed once ended); present → the user's choice wins.\n const [stepToggles, setStepToggles] = useState<Record<string, boolean>>({});\n const [itemToggles, setItemToggles] = useState<Record<string, boolean>>({});\n\n // A new run (first step identity changes) returns every toggle to\n // automatic — render-time reset, the React-documented pattern for\n // adjusting state when a prop changes.\n const runKey = steps[0]?.id ?? \"\";\n const [prevRunKey, setPrevRunKey] = useState(runKey);\n if (prevRunKey !== runKey) {\n setPrevRunKey(runKey);\n setUserToggled(null);\n setStepToggles({});\n setItemToggles({});\n }\n\n // Expanded while streaming; collapses when the run settles — unless the\n // user has taken over the toggle.\n const open = userToggled ?? streaming;\n\n const meta = useMemo(() => {\n const parts: string[] = [];\n if (llm && llm.calls > 0) {\n parts.push(`${llm.calls} LLM ${llm.calls === 1 ? \"call\" : \"calls\"}`);\n if (llm.totalMs > 0) parts.push(formatMs(llm.totalMs));\n }\n parts.push(`${steps.length} step${steps.length === 1 ? \"\" : \"s\"}`);\n if (steps.some((s) => s.status === \"failed\")) parts.push(\"failed\");\n return parts.join(\" · \");\n }, [llm, steps]);\n\n if (steps.length === 0) return null;\n\n return (\n <div className={cx(\"oxy-trace\", className)} data-run={runKey}>\n <button\n type='button'\n className='oxy-trace__head'\n onClick={() => setUserToggled(!open)}\n aria-expanded={open}\n >\n <ChevronIcon open={open} />\n <span className='oxy-trace__title'>Reasoning trace</span>\n <span className='oxy-trace__meta'>{meta}</span>\n {streaming && <span role='status' className='oxy-trace__spin' aria-label='running' />}\n </button>\n {open && (\n <div className='oxy-trace__body'>\n {steps.map((step) => {\n const stepOpen = stepToggles[step.id] ?? step.status === \"running\";\n if (step.items.length === 0) {\n return (\n <div key={step.id} className='oxy-trace__step'>\n <div className='oxy-trace__step-row'>\n <StatusIcon status={step.status} />\n <span className='oxy-trace__label'>{step.label}</span>\n {step.summary && <span className='oxy-trace__summary'>{step.summary}</span>}\n </div>\n </div>\n );\n }\n return (\n <div key={step.id} className='oxy-trace__step'>\n <button\n type='button'\n className='oxy-trace__step-row oxy-trace__step-row--btn'\n onClick={() => setStepToggles((t) => ({ ...t, [step.id]: !stepOpen }))}\n aria-expanded={stepOpen}\n >\n <StatusIcon status={step.status} />\n <span className='oxy-trace__label'>{step.label}</span>\n {step.summary && <span className='oxy-trace__summary'>{step.summary}</span>}\n {!stepOpen && (\n <span className='oxy-trace__count'>\n {step.items.length} action{step.items.length === 1 ? \"\" : \"s\"}\n </span>\n )}\n <span className='oxy-trace__step-chevron'>\n <ChevronIcon open={stepOpen} />\n </span>\n </button>\n {stepOpen && (\n <TraceItemRows\n step={step}\n itemToggles={itemToggles}\n onToggleItem={(id, next) => setItemToggles((t) => ({ ...t, [id]: next }))}\n />\n )}\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n","// API-backed chat history for the Ask dock. Two bundle-gated reads:\n//\n// GET /api/projects/:id/threads → the viewer's recent threads\n// GET /api/projects/:id/threads/:tid → a thread's transcript\n//\n// The transcript returns each turn's events already run through the same\n// processor the live SSE stream uses, so the dock rebuilds the reasoning\n// trace, charts, and answer with `buildTraceSteps` / the chart filter /\n// `extractAnswer` — identical to a live run. See\n// `crates/app/src/server/api/custom_apps_threads.rs`.\n\nimport * as React from \"react\";\nimport { getOxyAppLogger } from \"../custom-app/logger\";\nimport { type AgentRunEvent, type AppFetcher, useOxyApp } from \"../custom-app/react\";\n\nexport interface ThreadSummary {\n id: string;\n title: string;\n created_at: string;\n}\n\nexport interface TranscriptTurn {\n question: string;\n events: AgentRunEvent[];\n}\n\nexport interface ThreadTranscript {\n title: string;\n turns: TranscriptTurn[];\n}\n\nexport interface UseThreadHistoryResult {\n threads: ThreadSummary[];\n loading: boolean;\n error: Error | null;\n /** Re-fetch the list (call after a new chat is archived server-side). */\n refetch: () => void;\n}\n\n/**\n * List the viewer's persistent chat threads for the current project.\n * Non-fatal on failure (older server / no session): returns an empty\n * list so the dock falls back to session-only history.\n */\nexport function useThreadHistory(): UseThreadHistoryResult {\n const { projectId, fetcher } = useOxyApp();\n const [state, setState] = React.useState<{\n threads: ThreadSummary[];\n loading: boolean;\n error: Error | null;\n }>({ threads: [], loading: false, error: null });\n const [nonce, setNonce] = React.useState(0);\n const refetch = React.useCallback(() => setNonce((n) => n + 1), []);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: `nonce` is a manual refetch trigger — not read inside the effect, but bumping it must re-run the fetch (projectId/fetcher are stable across a session)\n React.useEffect(() => {\n if (!projectId) {\n setState({ threads: [], loading: false, error: null });\n return;\n }\n let cancelled = false;\n setState((s) => ({ ...s, loading: true }));\n fetcher(`/api/projects/${projectId}/threads`, { method: \"GET\" })\n .then(async (resp) => {\n if (!resp.ok) throw new Error(`threads list failed: HTTP ${resp.status}`);\n const threads = (await resp.json()) as ThreadSummary[];\n if (!cancelled) setState({ threads, loading: false, error: null });\n })\n .catch((e: unknown) => {\n const error = e instanceof Error ? e : new Error(String(e));\n getOxyAppLogger().log(\"warn\", \"thread history unavailable\", { error: error.message });\n if (!cancelled) setState({ threads: [], loading: false, error });\n });\n return () => {\n cancelled = true;\n };\n }, [projectId, fetcher, nonce]);\n\n return { ...state, refetch };\n}\n\n/**\n * Fetch a thread's transcript for restore. Throws on failure so the\n * caller can surface a toast / fall back.\n */\nexport async function fetchThreadTranscript(\n fetcher: AppFetcher,\n projectId: string,\n threadId: string\n): Promise<ThreadTranscript> {\n const resp = await fetcher(`/api/projects/${projectId}/threads/${threadId}`, { method: \"GET\" });\n if (!resp.ok) throw new Error(`thread transcript failed: HTTP ${resp.status}`);\n return (await resp.json()) as ThreadTranscript;\n}\n","// Ask Oxygen inside a custom app: the same right-side dock the main\n// web-app opens with ⌘K, powered by the SDK's bundle-gated agent-run\n// stream (`useAgentRun`). Multi-turn: follow-ups reuse the run's thread.\n//\n// History is session-scoped: bundles have no server list-threads endpoint,\n// so \"History\" lists chats started in this dock session (restoring one\n// resumes its server thread for follow-ups via the SSE resume). Beyond a\n// quick ask, the header links to the product Chat surface. No\n// extended-thinking toggle — the bundle ask API doesn't carry it.\n\nimport * as React from \"react\";\nimport { type AgentRunEvent, OxyAnswer, useAgentRun, useOxyApp } from \"../custom-app/react\";\nimport { AnswerChart, type ChartBlock } from \"./AnswerChart\";\nimport { cx } from \"./cx\";\nimport { OxyMark } from \"./marks\";\nimport { ReasoningTrace } from \"./ReasoningTrace\";\nimport { fetchThreadTranscript, useThreadHistory } from \"./threadHistory\";\nimport {\n aggregateLlmStats,\n buildTraceSteps,\n extractAnswer,\n extractClarification,\n type TraceStep\n} from \"./trace\";\n\nfunction CloseIcon() {\n return (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='M18 6 6 18' />\n <path d='m6 6 12 12' />\n </svg>\n );\n}\n\nfunction PlusIcon() {\n return (\n <svg\n width='15'\n height='15'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='M5 12h14' />\n <path d='M12 5v14' />\n </svg>\n );\n}\n\nfunction HistoryIcon() {\n return (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8' />\n <path d='M3 3v5h5' />\n <path d='M12 7v5l4 2' />\n </svg>\n );\n}\n\nfunction SearchIcon() {\n return (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <circle cx='11' cy='11' r='8' />\n <path d='m21 21-4.3-4.3' />\n </svg>\n );\n}\n\nfunction ThreadIcon() {\n return (\n <svg\n width='15'\n height='15'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='M14 9a2 2 0 0 1-2 2H6l-4 4V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2z' />\n <path d='M18 9h2a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1' />\n </svg>\n );\n}\n\nfunction ExternalIcon() {\n return (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='M15 3h6v6' />\n <path d='M10 14 21 3' />\n <path d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6' />\n </svg>\n );\n}\n\nfunction ArrowUpIcon() {\n return (\n <svg\n width='14'\n height='14'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='m5 12 7-7 7 7' />\n <path d='M12 19V5' />\n </svg>\n );\n}\n\nfunction StopIcon() {\n return (\n <svg width='12' height='12' viewBox='0 0 24 24' fill='currentColor' aria-hidden='true'>\n <rect x='6' y='6' width='12' height='12' rx='2' />\n </svg>\n );\n}\n\nexport interface AskDockProps {\n /** Agent the panel asks (the app manifest's `ask.agent`). */\n agentId: string;\n /** Workspace display name for the composer placeholder. */\n workspaceName?: string;\n /** Suggested-question chips shown before the first ask. */\n suggestions?: string[];\n /** \"Open chat in Oxygen\" header link target (product Chat surface). */\n threadsHref?: string;\n open: boolean;\n onClose: () => void;\n className?: string;\n}\n\ninterface CompletedTurn {\n question: string;\n answer: string | null;\n charts: ChartBlock[];\n steps: TraceStep[];\n llm: { calls: number; totalMs: number };\n}\n\ninterface Conversation {\n /** Stable key — the server thread id, or the first question when the\n * thread never got assigned (e.g. a run that failed before starting). */\n id: string;\n title: string;\n turns: CompletedTurn[];\n threadId: string | null;\n /** ISO timestamp the conversation was started — the server thread's\n * `created_at` when restored, else when its first question was asked.\n * Drives the history list's time label and its created_at ordering. */\n createdAt: string;\n}\n\nfunction chartsFrom(events: AgentRunEvent[]): ChartBlock[] {\n return events\n .filter((ev) => ev.type === \"chart_rendered\")\n .map((ev) => ev.data as ChartBlock)\n .filter((b) => b?.config && Array.isArray(b.columns) && Array.isArray(b.rows));\n}\n\n/** History label: a relative \"N minutes/hours/days ago\" for when the\n * conversation was started. */\nfunction formatHistoryTime(iso: string): string {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return \"\";\n const s = Math.max(0, Math.round((Date.now() - d.getTime()) / 1000));\n if (s < 45) return \"just now\";\n const min = Math.round(s / 60);\n if (min < 60) return `${min} minute${min === 1 ? \"\" : \"s\"} ago`;\n const hr = Math.round(s / 3600);\n if (hr < 24) return `${hr} hour${hr === 1 ? \"\" : \"s\"} ago`;\n const day = Math.round(s / 86400);\n if (day < 30) return `${day} day${day === 1 ? \"\" : \"s\"} ago`;\n const mo = Math.round(day / 30);\n if (mo < 12) return `${mo} month${mo === 1 ? \"\" : \"s\"} ago`;\n const yr = Math.round(day / 365);\n return `${yr} year${yr === 1 ? \"\" : \"s\"} ago`;\n}\n\n/** How many history rows to show before the \"Show more\" button. */\nconst HISTORY_PAGE_SIZE = 12;\n\n/** Rebuild a completed turn from a transcript turn's processed events —\n * identical to what the live dock accumulates during a run. */\nfunction turnFromEvents(question: string, events: AgentRunEvent[]): CompletedTurn {\n // A turn that ended in a clarifying question has no `text_delta` answer —\n // fall back to the suspension prompt so it doesn't restore as a blank bubble.\n return {\n question,\n answer: extractAnswer(events) || extractClarification(events) || null,\n charts: chartsFrom(events),\n steps: buildTraceSteps(events),\n llm: aggregateLlmStats(events)\n };\n}\n\n/**\n * The Ask Oxygen drawer. Keep it mounted and toggle `open` — the\n * transcript survives close/reopen, matching the web-app dock.\n */\nexport function AskDock({\n agentId,\n workspaceName,\n suggestions = [],\n threadsHref,\n open,\n onClose,\n className\n}: AskDockProps) {\n const run = useAgentRun({ agentId });\n const { projectId, fetcher } = useOxyApp();\n // Persistent, per-account history (bundle-gated API). Merged with the\n // richer in-session conversations below; empty on older servers.\n const { threads: serverThreads, refetch: refetchHistory } = useThreadHistory();\n const [turns, setTurns] = React.useState<CompletedTurn[]>([]);\n const [pending, setPending] = React.useState<string | null>(null);\n const [draft, setDraft] = React.useState(\"\");\n // Thread of the active conversation. Mirrors run.threadId while a chat is\n // live but is cleared on \"new chat\" so the next ask starts a fresh thread.\n const [threadId, setThreadId] = React.useState<string | null>(null);\n const [history, setHistory] = React.useState<Conversation[]>([]);\n const [historyOpen, setHistoryOpen] = React.useState(false);\n // History panel search text + how many rows are revealed (\"Show more\").\n const [historyQuery, setHistoryQuery] = React.useState(\"\");\n const [historyShown, setHistoryShown] = React.useState(HISTORY_PAGE_SIZE);\n const [restoring, setRestoring] = React.useState(false);\n const scrollRef = React.useRef<HTMLDivElement>(null);\n // Generation guard for the async transcript restore: any conversation\n // switch bumps this, and an in-flight `openServerThread` fetch that\n // resolves afterwards checks it and bails instead of clobbering the now-\n // current turns (which would leave the visible transcript and the resumed\n // thread pointing at different conversations).\n const restoreGenRef = React.useRef(0);\n // Start time of the active conversation, captured once so the history\n // entry keeps a stable created_at (set on the first ask, or to the server\n // thread's created_at when one is restored; cleared on \"new chat\").\n const startedAtRef = React.useRef<string | null>(null);\n\n const busy = run.state === \"running\";\n\n // The reasoning trace mirrors the web-app's analytics view: fold the raw\n // SSE events into step rows + tool/SQL items as they stream. Charts come\n // straight from the pipeline's chart_rendered blocks, rendered natively.\n const liveSteps = React.useMemo(() => buildTraceSteps(run.events), [run.events]);\n const liveLlm = React.useMemo(() => aggregateLlmStats(run.events), [run.events]);\n const liveCharts = React.useMemo(() => chartsFrom(run.events), [run.events]);\n\n // Adopt the server-assigned thread id as it arrives; \"new chat\" resets the\n // local value to null and the old run.threadId won't re-trigger this.\n React.useEffect(() => {\n if (run.threadId) setThreadId(run.threadId);\n }, [run.threadId]);\n\n const finalizedPendingTurn = (): CompletedTurn | null =>\n pending === null\n ? null\n : {\n question: pending,\n answer: run.answer ?? run.clarification,\n charts: liveCharts,\n steps: liveSteps,\n llm: liveLlm\n };\n\n /** The current conversation as a snapshot, or null when it's empty. */\n const snapshotCurrent = (): Conversation | null => {\n const finalized = finalizedPendingTurn();\n const all = finalized ? [...turns, finalized] : turns;\n if (all.length === 0) return null;\n return {\n id: threadId ?? all[0].question,\n title: all[0].question,\n turns: all,\n threadId,\n createdAt: startedAtRef.current ?? new Date().toISOString()\n };\n };\n\n const resetToEmpty = () => {\n restoreGenRef.current += 1;\n run.cancel();\n setTurns([]);\n setPending(null);\n setDraft(\"\");\n setThreadId(null);\n startedAtRef.current = null;\n };\n\n const newChat = () => {\n const snap = snapshotCurrent();\n if (snap) setHistory((h) => [snap, ...h.filter((c) => c.id !== snap.id)]);\n resetToEmpty();\n setHistoryOpen(false);\n };\n\n const openConversation = (conv: Conversation) => {\n restoreGenRef.current += 1;\n const snap = snapshotCurrent();\n setHistory((h) => {\n const rest = h.filter((c) => c.id !== conv.id && (!snap || c.id !== snap.id));\n return snap && snap.id !== conv.id ? [snap, ...rest] : rest;\n });\n run.cancel();\n setTurns(conv.turns);\n setPending(null);\n setDraft(\"\");\n setThreadId(conv.threadId);\n setHistoryOpen(false);\n };\n\n /** Restore a persistent (server) thread: archive the current chat, then\n * fetch + rebuild the transcript. Follow-ups resume the same thread. */\n const openServerThread = async (id: string) => {\n if (!projectId) return;\n const gen = (restoreGenRef.current += 1);\n const snap = snapshotCurrent();\n if (snap && snap.id !== id) {\n setHistory((h) => [snap, ...h.filter((c) => c.id !== snap.id)]);\n }\n run.cancel();\n setTurns([]);\n setPending(null);\n setDraft(\"\");\n setThreadId(id);\n // Preserve the restored thread's own created_at for its history label.\n startedAtRef.current =\n serverThreads.find((t) => t.id === id)?.created_at ?? new Date().toISOString();\n setHistoryOpen(false);\n setRestoring(true);\n try {\n const transcript = await fetchThreadTranscript(fetcher, projectId, id);\n // The user switched conversations while this fetch was in flight —\n // drop the stale result rather than overwrite the current turns.\n if (restoreGenRef.current !== gen) return;\n setTurns(transcript.turns.map((t) => turnFromEvents(t.question, t.events)));\n } catch {\n // Non-fatal: leave the transcript empty; the thread still resumes on\n // the next question (the server has its full context).\n } finally {\n if (restoreGenRef.current === gen) setRestoring(false);\n }\n };\n\n const send = (raw: string) => {\n const question = raw.trim();\n if (!question || busy) return;\n // A new question supersedes any in-flight restore for the prior context.\n restoreGenRef.current += 1;\n // First ask of a fresh chat stamps its start time.\n if (startedAtRef.current === null) startedAtRef.current = new Date().toISOString();\n if (pending !== null) {\n // Archive the finished turn before the hook resets for the next run.\n // A clarification prompt stands in for the answer so the exchange\n // stays readable in the transcript.\n const finalized = finalizedPendingTurn();\n if (finalized) setTurns((t) => [...t, finalized]);\n }\n setPending(question);\n setDraft(\"\");\n run.ask(question, threadId ? { threadId } : undefined);\n };\n\n // Follow the stream: after every render, pin the scroll to the bottom —\n // unless the user has scrolled up to read something, in which case leave\n // them alone. Deliberately no dependency array: tokens arrive on most\n // renders while streaming, and the near-bottom check makes it a no-op\n // otherwise.\n React.useEffect(() => {\n const el = scrollRef.current;\n if (!el) return;\n const nearBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 120;\n if (nearBottom) el.scrollTo({ top: el.scrollHeight });\n });\n\n const empty = pending === null && turns.length === 0;\n const canNewChat = !empty;\n\n // History panel: the active conversation plus every past one — the active\n // one stays in the list (flagged `active` so the UI highlights it rather\n // than hiding it). Matches snapshotCurrent()'s id so it dedupes cleanly.\n const currentId = threadId ?? turns[0]?.question ?? pending ?? null;\n const historyEntries: Array<{\n id: string;\n title: string;\n createdAt: string;\n active: boolean;\n onOpen: () => void;\n }> = [\n ...history.map((c) => ({\n id: c.id,\n title: c.title,\n createdAt: c.createdAt,\n active: c.id === currentId,\n onOpen: c.id === currentId ? () => setHistoryOpen(false) : () => openConversation(c)\n })),\n ...serverThreads\n .filter((t) => !history.some((c) => c.id === t.id))\n .map((t) => ({\n id: t.id,\n title: t.title,\n createdAt: t.created_at,\n active: t.id === currentId,\n onOpen: t.id === currentId ? () => setHistoryOpen(false) : () => void openServerThread(t.id)\n }))\n ];\n // A brand-new chat isn't in the server list yet — surface it so the active\n // conversation is always present (and highlightable).\n if (!empty && currentId != null && !historyEntries.some((e) => e.id === currentId)) {\n historyEntries.push({\n id: currentId,\n title: turns[0]?.question ?? pending ?? currentId,\n createdAt: startedAtRef.current ?? new Date().toISOString(),\n active: true,\n onOpen: () => setHistoryOpen(false)\n });\n }\n // Order strictly by creation time (newest first) — not by which chat was\n // last opened. ISO-8601 strings sort chronologically as plain text.\n historyEntries.sort((a, b) => b.createdAt.localeCompare(a.createdAt));\n\n // Search filter, then reveal up to `historyShown` rows (\"Show more\").\n const q = historyQuery.trim().toLowerCase();\n const filteredEntries = q\n ? historyEntries.filter((e) => e.title.toLowerCase().includes(q))\n : historyEntries;\n const visibleEntries = filteredEntries.slice(0, historyShown);\n\n const placeholder =\n run.state === \"needs_clarification\"\n ? \"Reply…\"\n : pending !== null\n ? \"Ask a follow-up…\"\n : `Ask Oxygen anything about ${workspaceName ?? \"your workspace\"}…`;\n\n return (\n <aside\n className={cx(\"oxy-shell-scope oxy-askdock\", !open && \"oxy-askdock--closed\", className)}\n aria-label='Ask Oxygen'\n aria-hidden={!open}\n >\n <header className='oxy-askdock__head'>\n <OxyMark className='oxy-askdock__mark' />\n <span className='oxy-askdock__title'>Ask Oxygen</span>\n <span className='oxy-askdock__actions'>\n <button\n type='button'\n className='oxy-askdock__iconbtn'\n onClick={newChat}\n disabled={!canNewChat}\n data-testid='askdock-new-chat'\n aria-label='New chat'\n title='New chat'\n >\n <PlusIcon />\n </button>\n <button\n type='button'\n className={cx(\"oxy-askdock__iconbtn\", historyOpen && \"oxy-askdock__iconbtn--active\")}\n onClick={() => {\n const next = !historyOpen;\n setHistoryOpen(next);\n if (next) {\n refetchHistory();\n setHistoryQuery(\"\");\n setHistoryShown(HISTORY_PAGE_SIZE);\n }\n }}\n data-testid='askdock-history'\n aria-label='Chat history'\n aria-expanded={historyOpen}\n title='Chat history'\n >\n <HistoryIcon />\n </button>\n {threadsHref && (\n <a\n className='oxy-askdock__iconbtn'\n href={threadsHref}\n aria-label='Open chat in Oxygen'\n title='Open chat in Oxygen'\n >\n <ExternalIcon />\n </a>\n )}\n <button\n type='button'\n className='oxy-askdock__iconbtn'\n onClick={onClose}\n aria-label='Close Ask Oxygen'\n >\n <CloseIcon />\n </button>\n </span>\n </header>\n\n {historyOpen ? (\n <div className='oxy-askdock__history' data-testid='askdock-history-panel'>\n <div className='oxy-askdock__history-search'>\n <SearchIcon />\n <input\n type='text'\n className='oxy-askdock__history-searchinput'\n placeholder='Search threads…'\n value={historyQuery}\n onChange={(e) => {\n setHistoryQuery(e.target.value);\n setHistoryShown(HISTORY_PAGE_SIZE);\n }}\n aria-label='Search threads'\n />\n </div>\n {visibleEntries.length === 0 ? (\n <p className='oxy-askdock__history-empty'>\n {historyQuery ? \"No matching chats.\" : \"No previous chats yet.\"}\n </p>\n ) : (\n <>\n {visibleEntries.map((entry) => (\n <button\n key={entry.id}\n type='button'\n className={cx(\n \"oxy-askdock__history-item\",\n entry.active && \"oxy-askdock__history-item--active\"\n )}\n onClick={entry.onOpen}\n title={entry.title}\n aria-current={entry.active ? \"true\" : undefined}\n >\n <span className='oxy-askdock__history-icon'>\n <ThreadIcon />\n </span>\n <span className='oxy-askdock__history-title'>{entry.title}</span>\n <span className='oxy-askdock__history-time'>\n {formatHistoryTime(entry.createdAt)}\n </span>\n </button>\n ))}\n {filteredEntries.length > visibleEntries.length && (\n <button\n type='button'\n className='oxy-askdock__history-more'\n onClick={() => setHistoryShown((n) => n + HISTORY_PAGE_SIZE)}\n >\n Show more\n </button>\n )}\n </>\n )}\n </div>\n ) : (\n <>\n <div className='oxy-askdock__scroll' ref={scrollRef}>\n {restoring && <p className='oxy-askdock__history-empty'>Loading conversation…</p>}\n {empty && !restoring && suggestions.length > 0 && (\n <div className='oxy-askdock__chips'>\n {suggestions.map((s) => (\n <button\n key={s}\n type='button'\n className='oxy-askdock__chip'\n onClick={() => send(s)}\n >\n {s}\n </button>\n ))}\n </div>\n )}\n {turns.map((t, i) => (\n <div key={`${i}-${t.question}`} className='oxy-askdock__turn'>\n <div className='oxy-askdock__q'>{t.question}</div>\n <ReasoningTrace steps={t.steps} llm={t.llm} />\n {t.charts.map((c, ci) => (\n <AnswerChart key={`${ci}-${c.config.title ?? c.config.chart_type}`} block={c} />\n ))}\n {/* No artifacts prop: the SQL details live in the reasoning\n trace and the chart — the QUERY block would triple up. */}\n <OxyAnswer answer={t.answer} state='done' threadUrl={null} />\n </div>\n ))}\n {pending !== null && (\n <div className='oxy-askdock__turn'>\n <div className='oxy-askdock__q'>{pending}</div>\n <ReasoningTrace steps={liveSteps} streaming={busy} llm={liveLlm} />\n {liveCharts.map((c, ci) => (\n <AnswerChart key={`${ci}-${c.config.title ?? c.config.chart_type}`} block={c} />\n ))}\n <OxyAnswer\n answer={run.answer}\n state={run.state}\n clarification={run.clarification}\n error={run.error}\n threadUrl={null}\n />\n </div>\n )}\n </div>\n\n <form\n className='oxy-askdock__composer'\n onSubmit={(e) => {\n e.preventDefault();\n send(draft);\n }}\n >\n <textarea\n className='oxy-askdock__input'\n rows={3}\n placeholder={placeholder}\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n send(draft);\n }\n }}\n />\n <div className='oxy-askdock__composer-row'>\n {busy ? (\n <button\n type='button'\n className='oxy-askdock__send'\n onClick={run.cancel}\n aria-label='Stop generating'\n >\n <StopIcon />\n </button>\n ) : (\n <button\n type='submit'\n className='oxy-askdock__send'\n disabled={!draft.trim()}\n aria-label='Send'\n >\n <ArrowUpIcon />\n </button>\n )}\n </div>\n </form>\n </>\n )}\n </aside>\n );\n}\n","/** URL of the workspace logo endpoint (org-uploaded logo, falling back to\n * the code-first file). Consumers render an `<img>` and fall back on error.\n * `apiBaseUrl` is the API root (e.g. `\"/api\"` same-origin, or an absolute\n * base in dev); pass `version` (the org's `updated_at`) to bust the cache\n * after an upload/remove. */\nexport const workspaceLogoUrl = (apiBaseUrl: string, workspaceId: string, version?: string) => {\n const base = `${apiBaseUrl.replace(/\\/$/, \"\")}/${workspaceId}/logo`;\n return version ? `${base}?v=${encodeURIComponent(version)}` : base;\n};\n","import * as React from \"react\";\n\n/**\n * Floating shell content (tooltips) portals into the nearest shell scope\n * element instead of `document.body`, so the `oxy-shell-scope` tokens and a\n * host-applied `.dark` ancestor keep applying to it. Falls back to the\n * default body portal when no provider is mounted (standalone `ShellRail`\n * under a host that themes `<body>` itself).\n */\nexport const ShellPortalContext = React.createContext<HTMLElement | null>(null);\n\n/** Track the portal container element for descendants of a shell root. */\nexport function useShellPortalContainer(): {\n container: HTMLElement | null;\n setContainer: (el: HTMLElement | null) => void;\n} {\n const [container, setContainer] = React.useState<HTMLElement | null>(null);\n return { container, setContainer };\n}\n","import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { ShellPortalContext } from \"./portal\";\n\n/**\n * Hover tooltip for shell controls. Mirrors the web-app's Radix tooltip\n * (zero delay, side arrow, `--zinc-200`/muted surface) but portals into the\n * shell scope so the namespaced tokens and dark-mode class reach it.\n */\nexport function ShellTooltip({\n content,\n side = \"right\",\n children\n}: {\n content: React.ReactNode;\n side?: \"top\" | \"right\" | \"bottom\" | \"left\";\n children: React.ReactNode;\n}) {\n const container = React.useContext(ShellPortalContext);\n return (\n <TooltipPrimitive.Provider delayDuration={0}>\n <TooltipPrimitive.Root>\n <TooltipPrimitive.Trigger asChild>{children}</TooltipPrimitive.Trigger>\n <TooltipPrimitive.Portal container={container ?? undefined}>\n <TooltipPrimitive.Content\n side={side}\n sideOffset={0}\n className='oxy-shell-scope oxy-shell-tooltip'\n >\n {content}\n <TooltipPrimitive.Arrow className='oxy-shell-tooltip__arrow' />\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n </TooltipPrimitive.Root>\n </TooltipPrimitive.Provider>\n );\n}\n","// The 48px icon rail — sole chrome of the workspace shell. Ported from\n// web-app/src/components/Shell/ShellRail.tsx, which was written router-free\n// for exactly this move; the web-app now consumes this component. Keep the\n// two visually identical: this file is the source of truth.\n\nimport { Fragment, type ReactNode, useState } from \"react\";\nimport { cx } from \"./cx\";\nimport { ShellPortalContext, useShellPortalContainer } from \"./portal\";\nimport { ShellTooltip } from \"./Tooltip\";\n\n/** One rail entry. Provide `imageUrl` (custom app mark, falls back to\n * `letter` on load error), `icon` (any SVG node), or `letter`.\n * `href` renders a real anchor (full-page nav — custom apps live outside\n * the SPA); `onSelect` renders a button (SPA nav, wired by the caller). */\nexport type RailItem = {\n key: string;\n label: string;\n /** Hover-tooltip text; defaults to `label`. Use for a richer description\n * while keeping `label` short for the aria-label. */\n tooltip?: string;\n testId?: string;\n active?: boolean;\n icon?: ReactNode;\n letter?: string;\n imageUrl?: string;\n href?: string;\n onSelect?: () => void;\n};\n\nfunction RailEntry({ item }: { item: RailItem }) {\n // Track the URL that failed (not a boolean) so a new imageUrl retries\n // instead of latching the letter fallback forever.\n const [failedUrl, setFailedUrl] = useState<string | null>(null);\n const content =\n item.imageUrl && failedUrl !== item.imageUrl ? (\n <img\n src={item.imageUrl}\n alt=''\n onError={() => setFailedUrl(item.imageUrl ?? null)}\n className='oxy-rail__item-img'\n />\n ) : (\n (item.icon ?? <span className='oxy-rail__item-letter'>{item.letter}</span>)\n );\n const className = cx(\"oxy-rail__item\", item.active && \"oxy-rail__item--active\");\n const ariaCurrent = item.active ? (\"page\" as const) : undefined;\n const entry = item.href ? (\n <a\n href={item.href}\n data-testid={item.testId}\n aria-label={item.label}\n aria-current={ariaCurrent}\n className={className}\n >\n {content}\n </a>\n ) : (\n <button\n type='button'\n onClick={item.onSelect}\n data-testid={item.testId}\n aria-label={item.label}\n aria-current={ariaCurrent}\n className={className}\n >\n {content}\n </button>\n );\n return <ShellTooltip content={item.tooltip ?? item.label}>{entry}</ShellTooltip>;\n}\n\n/** A hairline divider between conceptual rail groups. */\nfunction RailDivider() {\n return <div className='oxy-rail__divider' />;\n}\n\n/** The icon rail. `groups` are the conceptual sections (HQ · Apps ·\n * Intelligence), rendered top-down with a hairline divider between them.\n * `footerItems` pin to the bottom of the scroll area as a distinct\n * \"system\" zone (Oxygen Factory), above the `bottom` account slot\n * (workspace switch · user menu — injected by the host app). */\nexport function ShellRail({\n top,\n groups,\n footerItems,\n bottom,\n className\n}: {\n top?: ReactNode;\n groups: RailItem[][];\n footerItems?: RailItem[];\n bottom?: ReactNode;\n className?: string;\n}) {\n const { container, setContainer } = useShellPortalContainer();\n return (\n <ShellPortalContext.Provider value={container}>\n <div\n ref={setContainer}\n data-testid='shell-rail'\n className={cx(\"oxy-shell-scope oxy-rail\", className)}\n >\n {top && <div className='oxy-rail__top'>{top}</div>}\n <div className='oxy-rail__nav'>\n {groups.map((group, i) => (\n <Fragment key={group[0]?.key ?? i}>\n {i > 0 && <RailDivider />}\n {group.map((item) => (\n <RailEntry key={item.key} item={item} />\n ))}\n </Fragment>\n ))}\n {footerItems && footerItems.length > 0 && (\n <div className='oxy-rail__footer'>\n <RailDivider />\n {footerItems.map((item) => (\n <RailEntry key={item.key} item={item} />\n ))}\n </div>\n )}\n </div>\n {bottom && <div className='oxy-rail__bottom'>{bottom}</div>}\n </div>\n </ShellPortalContext.Provider>\n );\n}\n","// Shell bootstrap data for the wired OxyShell. One bundle-gated request:\n//\n// GET /api/projects/:id/shell-context\n//\n// The server builds every URL in the response (`apps[].url`, `links.*`,\n// `logo_url`) because only it knows which host scheme is in play — an org\n// subdomain serves apps at `/a/<slug>/` same-origin, while a dedicated\n// custom-app subdomain needs absolute product-host URLs. Never derive\n// product URLs client-side. See\n// `crates/app/src/server/api/custom_apps_shell_context.rs`.\n\nimport * as React from \"react\";\nimport type { OxyReach } from \"../custom-app/function-context\";\nimport { getOxyAppLogger } from \"../custom-app/logger\";\nimport { useOxyApp } from \"../custom-app/react\";\n\nexport interface ShellContextApp {\n id: string;\n name: string;\n slug: string;\n /** Ready-to-navigate URL (relative on the same host, absolute across hosts). */\n url: string;\n icon_url?: string | null;\n /** Agent ref the app's Ask Oxygen panel binds to (manifest `ask.agent`).\n * Absent → the shell hides the Ask surface for this app. */\n default_agent?: string | null;\n /** Composer chips for the Ask panel (manifest `ask.suggestedQuestions`). */\n suggested_questions?: string[];\n}\n\nexport interface ShellContextData {\n workspace: { id: string; name: string };\n org: { id: string; slug: string; name: string };\n /** Workspace logo endpoint URL, or null when no logo is configured. */\n logo_url: string | null;\n /** Published custom apps in this workspace, including the current one. */\n apps: ShellContextApp[];\n /** Product-surface navigation targets, host-aware. `settings` opens the\n * Unified Settings Dialog via the SPA's `?settings=<section>` deep link\n * (optional: absent on servers older than the link). */\n links: { home: string; threads: string; settings?: string };\n /** Viewer display identity; null on unauthenticated/local modes. */\n user: ShellContextUser | null;\n}\n\n/**\n * The viewer, for display. `id`, `kind` and `reach` arrive on servers that\n * carry the operating graph (2026-09-07 on) and are absent before — read them\n * through `useIdentity()`, which fills the gaps with the fail-closed answer.\n * None of this is a gate: the function's `ctx.user` is.\n */\nexport interface ShellContextUser {\n name: string;\n /** Empty for a frontline worker, who has no mailbox. */\n email: string;\n picture?: string | null;\n id?: string;\n /** `member` holds an org membership; `frontline` is a crew member. */\n kind?: \"member\" | \"frontline\";\n reach?: OxyReach | null;\n}\n\nexport interface UseShellContextResult {\n data: ShellContextData | null;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Fetch the shell bootstrap payload for the current custom app. Must be\n * called inside `<OxyAppProvider>`. Failure is non-fatal by design: the\n * shell degrades to chrome-less rendering (older servers don't have the\n * endpoint), so errors are surfaced on the result, never thrown.\n */\nexport function useShellContext(): UseShellContextResult {\n const { projectId, appId, fetcher } = useOxyApp();\n const [state, setState] = React.useState<UseShellContextResult>({\n data: null,\n loading: true,\n error: null\n });\n\n React.useEffect(() => {\n if (!projectId) {\n // No project identity (dev without a server / manifest hint) — nothing\n // to fetch; settle immediately so the shell degrades instead of\n // spinning forever.\n setState({ data: null, loading: false, error: new Error(\"no projectId resolved\") });\n return;\n }\n let cancelled = false;\n // The bundle names its own app so the viewer's app-admin standing can be\n // part of the display reach; an older server ignores the parameter.\n const query = appId ? `?app=${encodeURIComponent(appId)}` : \"\";\n fetcher(`/api/projects/${projectId}/shell-context${query}`, { method: \"GET\" })\n .then(async (resp) => {\n if (!resp.ok) {\n throw new Error(`shell-context failed: HTTP ${resp.status}`);\n }\n const data = (await resp.json()) as ShellContextData;\n if (!cancelled) setState({ data, loading: false, error: null });\n })\n .catch((e: unknown) => {\n const error = e instanceof Error ? e : new Error(String(e));\n getOxyAppLogger().log(\"warn\", \"shell-context unavailable, rendering without chrome\", {\n error: error.message\n });\n if (!cancelled) setState({ data: null, loading: false, error });\n });\n return () => {\n cancelled = true;\n };\n }, [projectId, appId, fetcher]);\n\n return state;\n}\n\n/** What `useIdentity()` returns. */\nexport interface ViewerIdentity {\n id: string | null;\n name: string;\n /** `null` for a frontline worker — the crew signal, as in `ctx.user.email`. */\n email: string | null;\n picture: string | null;\n kind: \"member\" | \"frontline\" | null;\n /** Display-only reach; the fail-closed answer until the server says otherwise. */\n reach: OxyReach;\n loading: boolean;\n}\n\nconst NOWHERE: OxyReach = { everywhere: false, via: null, locations: [] };\n\n/**\n * The viewer, in one shape, on every server version: who is signed in, the\n * crew-or-office signal, and where they work — for a greeting, a \"your\n * store\" default, or hiding a tab. Never for authorization: a browser can\n * edit what it renders, and the function's `ctx.user.reach` is the gate.\n */\nexport function useIdentity(): ViewerIdentity {\n const { data, loading } = useShellContext();\n const u = data?.user ?? null;\n return {\n id: u?.id ?? null,\n name: u?.name ?? \"\",\n email: u?.email ? u.email : null,\n picture: u?.picture ?? null,\n kind: u?.kind ?? null,\n reach: u?.reach ?? NOWHERE,\n loading\n };\n}\n","// The universal top bar: breadcrumb (left) + status, clock, and host-provided\n// actions (right). Ported from web-app/src/components/Shell/TopBar — this is\n// now the source of truth; the web-app composes it with its own Ask Oxygen\n// toggle in the `right` slot.\n\nimport { type ReactNode, useEffect, useMemo, useState } from \"react\";\nimport { cx } from \"./cx\";\nimport { ShellPortalContext, useShellPortalContainer } from \"./portal\";\n\n/** Frame only: left content + right cluster. Mirrors the rail's\n * `--sidebar-background` so the two read as one 48px-tall frame. */\nexport function TopBar({\n left,\n right,\n className\n}: {\n left?: ReactNode;\n right?: ReactNode;\n className?: string;\n}) {\n const { container, setContainer } = useShellPortalContainer();\n return (\n <ShellPortalContext.Provider value={container}>\n <header\n ref={setContainer}\n data-testid='workspace-topbar'\n className={cx(\"oxy-shell-scope oxy-topbar\", className)}\n >\n {left}\n <div className='oxy-topbar__right'>{right}</div>\n </header>\n </ShellPortalContext.Provider>\n );\n}\n\n/**\n * \"<Workspace> / <Page>\" — e.g. \"Poke House / HQ\". The workspace name links\n * back to the HQ home; pass `onHomeNavigate` to intercept for SPA routing\n * (the anchor still carries `homeHref` for middle-click/new-tab).\n */\nexport function Breadcrumb({\n workspaceLabel,\n pageLabel,\n homeHref,\n onHomeNavigate\n}: {\n workspaceLabel: string;\n pageLabel: string;\n homeHref: string;\n onHomeNavigate?: () => void;\n}) {\n return (\n <div className='oxy-breadcrumb'>\n <a\n href={homeHref}\n data-testid='topbar-workspace-link'\n className='oxy-breadcrumb__workspace'\n onClick={\n onHomeNavigate\n ? (e) => {\n // Let modified clicks (new tab, download, …) fall through to\n // the browser; plain left-clicks stay in the SPA.\n if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) return;\n e.preventDefault();\n onHomeNavigate();\n }\n : undefined\n }\n >\n {workspaceLabel}\n </a>\n <span className='oxy-breadcrumb__sep'>/</span>\n <span className='oxy-breadcrumb__page'>{pageLabel}</span>\n </div>\n );\n}\n\n/** `navigator.onLine` + online/offline events. */\nfunction useOnlineStatus(): boolean {\n const [online, setOnline] = useState(() =>\n typeof navigator === \"undefined\" ? true : navigator.onLine\n );\n useEffect(() => {\n const up = () => setOnline(true);\n const down = () => setOnline(false);\n window.addEventListener(\"online\", up);\n window.addEventListener(\"offline\", down);\n return () => {\n window.removeEventListener(\"online\", up);\n window.removeEventListener(\"offline\", down);\n };\n }, []);\n return online;\n}\n\n/**\n * Universal \"Sys: Connected\" indicator — a pulsing green dot when the browser\n * is online, red when offline. Presentational connectivity signal; a real\n * backend health ping can replace `useOnlineStatus` later without touching\n * consumers.\n */\nexport function SystemIndicator() {\n const online = useOnlineStatus();\n return (\n <span data-testid='topbar-system' className='oxy-shell-scope oxy-sysind'>\n <span>Sys:</span>\n <span\n className={cx(\n \"oxy-sysind__state\",\n online ? \"oxy-sysind__state--online\" : \"oxy-sysind__state--offline\"\n )}\n >\n <span className='oxy-sysind__dot-wrap'>\n {online && <span className='oxy-sysind__ping' />}\n <span\n className={cx(\n \"oxy-sysind__dot\",\n online ? \"oxy-sysind__dot--online\" : \"oxy-sysind__dot--offline\"\n )}\n />\n </span>\n {online ? \"Connected\" : \"Offline\"}\n </span>\n </span>\n );\n}\n\n/**\n * Live clock in the given IANA timezone (viewer-local when omitted or\n * invalid). Updates each half-minute (minute precision), pausing while the\n * tab is hidden.\n */\nexport function WorkspaceClock({ timezone }: { timezone?: string }) {\n const [now, setNow] = useState(() => new Date());\n\n useEffect(() => {\n const update = () => setNow(new Date());\n const id = setInterval(() => {\n if (!document.hidden) update();\n }, 30_000);\n // Re-show: tick immediately so the clock isn't up to 30s stale after the\n // tab was backgrounded (interval ticks are skipped while hidden).\n const onVisible = () => {\n if (!document.hidden) update();\n };\n document.addEventListener(\"visibilitychange\", onVisible);\n return () => {\n clearInterval(id);\n document.removeEventListener(\"visibilitychange\", onVisible);\n };\n }, []);\n\n const text = useMemo(() => {\n try {\n return new Intl.DateTimeFormat(undefined, {\n timeZone: timezone,\n hour: \"numeric\",\n minute: \"2-digit\",\n timeZoneName: timezone ? \"short\" : undefined\n }).format(now);\n } catch {\n // Invalid IANA name → local time without a zone label rather than crash.\n return new Intl.DateTimeFormat(undefined, {\n hour: \"numeric\",\n minute: \"2-digit\"\n }).format(now);\n }\n }, [now, timezone]);\n\n return (\n <span data-testid='topbar-clock' className='oxy-shell-scope oxy-clock'>\n {text}\n </span>\n );\n}\n","import { useState } from \"react\";\nimport { cx } from \"./cx\";\n\n/** Rail-top workspace identity: the org/code-first logo when present, the\n * name initial otherwise. Pure branding — switching workspaces is the host\n * app's concern (the rail `bottom` slot). */\nexport function WorkspaceTile({ name, logoUrl }: { name: string; logoUrl?: string }) {\n // Track the URL that failed (not a boolean) so a changed logoUrl —\n // workspace switch, cache-busted re-upload — retries instead of\n // latching the initial fallback for the component's lifetime.\n const [failedUrl, setFailedUrl] = useState<string | null>(null);\n const showLogo = !!logoUrl && failedUrl !== logoUrl;\n\n return (\n <span\n data-testid='rail-workspace'\n title={name}\n // The tile's fill backs the letter fallback; a real logo (often a\n // transparent PNG) sits on its own, so the fill would show through as a\n // grey square. The `--logo` modifier drops it — see shell.css.\n className={cx(\"oxy-shell-scope oxy-workspace-tile\", showLogo && \"oxy-workspace-tile--logo\")}\n >\n {showLogo ? (\n <img\n src={logoUrl}\n alt={name}\n onError={() => setFailedUrl(logoUrl ?? null)}\n className='oxy-workspace-tile__img'\n />\n ) : (\n <span className='oxy-workspace-tile__letter'>{name.slice(0, 1).toUpperCase()}</span>\n )}\n </span>\n );\n}\n","// The wired workspace shell for custom-app bundles: the same icon rail +\n// universal top bar the main web-app renders, fed by the bundle-gated\n// shell-context endpoint. Wrap the app's content with it inside\n// <OxyAppProvider>:\n//\n// <OxyAppProvider>\n// <OxyShell>\n// <Dashboard />\n// </OxyShell>\n// </OxyAppProvider>\n//\n// Degradation contract: chrome must never take the app down. While the\n// bootstrap request is in flight the frame renders with placeholders; if it\n// fails (older server, unauthenticated viewer), the children render bare.\n\nimport { type CSSProperties, type ReactNode, useEffect, useState } from \"react\";\nimport { useOxyApp, useResolvedManifest } from \"../custom-app/react\";\nimport { AskDock } from \"./AskDock\";\nimport { cx } from \"./cx\";\nimport { OxyMark } from \"./marks\";\nimport { ShellPortalContext, useShellPortalContainer } from \"./portal\";\nimport { type RailItem, ShellRail } from \"./ShellRail\";\nimport { type ShellContextData, useShellContext } from \"./shellContext\";\nimport { Breadcrumb, SystemIndicator, TopBar, WorkspaceClock } from \"./TopBar\";\nimport { WorkspaceTile } from \"./WorkspaceTile\";\n\n/** Home/HQ glyph (lucide \"house\" outline, inlined). */\nfunction HouseIcon() {\n return (\n <svg\n width='16'\n height='16'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8' />\n <path d='M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z' />\n </svg>\n );\n}\n\n/** Chat glyph (lucide \"messages-square\" outline, inlined). */\nfunction MessagesIcon() {\n return (\n <svg\n width='16'\n height='16'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'\n >\n <path d='M16 10a2 2 0 0 1-2 2H6l-4 4V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z' />\n <path d='M20 9a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1' />\n </svg>\n );\n}\n\nexport interface OxyShellProps {\n children: ReactNode;\n /** Breadcrumb page label; defaults to this app's registered name. */\n pageLabel?: string;\n /** Replace the top bar's left side (the default workspace/page\n * breadcrumb) with the app's own brand/header content. Host-provided\n * slots keep rendering even when the shell bootstrap is unavailable,\n * so the app never loses its header by adopting the shell. */\n topBarLeft?: ReactNode;\n /** Extra right-side top bar content, rendered after the status cluster\n * (Sys · clock) and before the Ask Oxygen button. */\n topBarExtra?: ReactNode;\n /** Rail bottom slot content. The shell adds no built-in entries here —\n * a bundle that wants a Settings link supplies its own. */\n railBottom?: ReactNode;\n /** Drop the top bar and keep only the rail. */\n hideTopBar?: boolean;\n /** Bind ⌘K / Ctrl+K to toggle the Ask dock (default true). Set false\n * when the host app owns that shortcut; the top-bar button still works. */\n askHotkey?: boolean;\n /** Origin of the Oxygen product (e.g. `https://app.oxygen-hq.com`).\n * shell-context returns product links as relative paths, which resolve\n * correctly when oxy serves the bundle (production, org subdomain). In\n * local dev the bundle runs on its own Vite origin, so those paths would\n * resolve to the app's origin, not oxy's — set this to the oxy origin\n * and the shell rewrites Home / Chat / Settings / app links to absolute\n * URLs. Leave unset in production. */\n productBaseUrl?: string;\n className?: string;\n /** Background of the shell chrome — the icon rail, the top bar, and the\n * AskDock (they share one token). Any CSS color, including `var(--…)` to\n * track a host token (e.g. `var(--background)` to match the app's canvas).\n * Overrides the theme's default; leave unset to keep it. */\n chromeBackground?: string;\n /** Text/icon color on the chrome, paired with `chromeBackground` for\n * contrast when using a background outside the current light/dark family.\n * Unset keeps the theme's foreground. */\n chromeForeground?: string;\n}\n\n/** Rewrite a shell-context relative product path to an absolute URL against\n * the oxy origin, when one is configured. `/api/*` paths are left relative\n * — they ride the host's same-origin fetch / dev proxy (which attaches\n * auth), so absolutizing them would drop the credentials the proxy adds. */\nfunction makeAbs(base: string | undefined) {\n const origin = base?.replace(/\\/$/, \"\");\n return (url?: string | null): string | undefined => {\n if (!url) return undefined;\n if (!origin || !url.startsWith(\"/\") || url.startsWith(\"/api/\")) return url;\n return `${origin}${url}`;\n };\n}\n\nfunction buildRailGroups(\n data: ShellContextData,\n currentAppSlug: string | undefined,\n abs: (url?: string | null) => string | undefined\n): RailItem[][] {\n const hq: RailItem = {\n key: \"hq\",\n label: \"HQ\",\n testId: \"rail-hq\",\n icon: <HouseIcon />,\n href: abs(data.links.home)\n };\n const chat: RailItem = {\n key: \"chat\",\n label: \"Chat\",\n testId: \"rail-chat\",\n icon: <MessagesIcon />,\n href: abs(data.links.threads)\n };\n const appItems: RailItem[] = data.apps.map((app) => ({\n key: app.id,\n label: app.name,\n testId: `rail-app-${app.slug}`,\n letter: app.name.slice(0, 1).toUpperCase(),\n imageUrl: abs(app.icon_url),\n // Every app entry is a real anchor — same as the main web-app's rail.\n // The current app gets `active` (RailEntry adds aria-current=\"page\");\n // re-clicking it is a same-page reload, standard anchor semantics.\n active: app.slug === currentAppSlug,\n href: abs(app.url)\n }));\n return appItems.length ? [[hq, chat], appItems] : [[hq, chat]];\n}\n\n/**\n * The workspace chrome around a custom app: icon rail + universal top bar\n * + content column — visually identical to the main web-app shell.\n */\nexport function OxyShell({\n children,\n pageLabel,\n topBarLeft,\n topBarExtra,\n railBottom,\n hideTopBar,\n askHotkey = true,\n productBaseUrl,\n className,\n chromeBackground,\n chromeForeground\n}: OxyShellProps) {\n const abs = makeAbs(productBaseUrl);\n // Chrome color overrides. We set the HOST tokens (--sidebar-background,\n // --foreground, --muted-foreground) rather than the derived --oxy-shell-*\n // ones: every sub-component (rail, top bar, AskDock…) is its own\n // `.oxy-shell-scope` and re-derives `--oxy-shell-*` from these host tokens,\n // so overriding a derived token here wouldn't reach them — overriding the\n // host token (which they all read via `var()`) does. Only the tokens the\n // caller provides are set; the theme keeps the rest.\n const chromeStyle = {\n ...(chromeBackground ? { \"--sidebar-background\": chromeBackground } : {}),\n ...(chromeForeground\n ? {\n \"--foreground\": chromeForeground,\n \"--muted-foreground\": `color-mix(in srgb, ${chromeForeground} 65%, transparent)`\n }\n : {})\n } as CSSProperties;\n const { appSlug } = useOxyApp();\n // Safe here: OxyAppProvider only renders children once the manifest is\n // resolved, and OxyShell must sit inside the provider.\n const { manifest } = useResolvedManifest();\n const { data, loading } = useShellContext();\n const { container, setContainer } = useShellPortalContainer();\n\n // Bootstrap failed (old server / no session) → degraded: no chrome. The\n // wrapper tree stays MOUNTED in every state (loading → data/degraded) and\n // only the rail/top-bar siblings toggle, so the app's component tree is\n // never reparented — reparenting would remount the whole app and drop its\n // state (queries, form input) exactly when the shell resolves.\n const degraded = !loading && !data;\n\n // `resolved.appSlug` is \"\" (not undefined) when running without server\n // injection — fall back to the manifest's own slug for matching/labels.\n const effectiveSlug = appSlug || manifest.slug;\n const currentApp = data?.apps.find((app) => app.slug === effectiveSlug);\n const workspaceLabel = data ? data.org.name || data.workspace.name : \"\";\n const page = pageLabel ?? currentApp?.name ?? manifest.name ?? effectiveSlug ?? \"\";\n\n // Ask Oxygen: available when this app's manifest binds an agent\n // (`ask.agent`, surfaced by shell-context as `default_agent`). The dock\n // stays mounted once available so its transcript survives close/reopen;\n // ⌘K / Ctrl+K toggles it, same binding as the main web-app.\n const askAgent = currentApp?.default_agent ?? manifest.ask?.agent ?? undefined;\n const askSuggestions = currentApp?.suggested_questions?.length\n ? currentApp.suggested_questions\n : (manifest.ask?.suggestedQuestions ?? []);\n const [askOpen, setAskOpen] = useState(false);\n useEffect(() => {\n if (!askAgent || !askHotkey) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key.toLowerCase() !== \"k\" || !(e.metaKey || e.ctrlKey)) return;\n e.preventDefault();\n setAskOpen((o) => !o);\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [askAgent, askHotkey]);\n\n // Bottom rail slot: the host app's custom content only. The built-in\n // Settings link was removed — a bundle that wants one can supply it via\n // `railBottom`.\n const bottom = railBottom;\n\n return (\n <ShellPortalContext.Provider value={container}>\n <div\n ref={setContainer}\n className={cx(\"oxy-shell-scope oxy-shell\", degraded && \"oxy-shell--degraded\", className)}\n style={chromeStyle}\n >\n {!degraded && (\n <ShellRail\n top={\n data ? (\n <WorkspaceTile name={data.workspace.name} logoUrl={data.logo_url ?? undefined} />\n ) : (\n <span className='oxy-workspace-tile'>\n <OxyMark className='oxy-rail__item-img' />\n </span>\n )\n }\n groups={data ? buildRailGroups(data, effectiveSlug, abs) : [[]]}\n bottom={bottom}\n />\n )}\n <div className='oxy-shell__content-col'>\n {/* The top bar renders in degraded mode too when the host passed\n its own slot content — an app that moved its header into the\n shell must never lose it to a failed bootstrap. Only the\n data-driven pieces (breadcrumb, Ask) hide. */}\n {!hideTopBar && (!degraded || topBarLeft || topBarExtra) && (\n <TopBar\n left={\n topBarLeft ??\n (data ? (\n <Breadcrumb\n workspaceLabel={workspaceLabel}\n pageLabel={page}\n homeHref={abs(data.links.home) ?? data.links.home}\n />\n ) : undefined)\n }\n right={\n <>\n <SystemIndicator />\n <WorkspaceClock />\n {topBarExtra}\n {askAgent && !degraded && (\n <button\n type='button'\n data-testid='ask-oxygen-button'\n onClick={() => setAskOpen((o) => !o)}\n className={cx(\"oxy-askbtn\", askOpen && \"oxy-askbtn--open\")}\n >\n <OxyMark className='oxy-askbtn__mark' />\n <span className='oxy-askbtn__label'>Ask Oxygen</span>\n <kbd className='oxy-askbtn__kbd'>⌘K</kbd>\n </button>\n )}\n </>\n }\n />\n )}\n {/* A div, not <main>: the app's own content very likely carries\n its own main landmark (the scaffolded template does). */}\n <div className='oxy-shell__main'>{children}</div>\n </div>\n {/* Flex sibling of the content column — opening the dock compacts\n the app (Cursor-style) rather than floating over it, matching\n the web-app AskDock. */}\n {askAgent && !degraded && (\n <AskDock\n agentId={askAgent}\n open={askOpen}\n onClose={() => setAskOpen(false)}\n workspaceName={data?.workspace.name}\n suggestions={askSuggestions}\n threadsHref={abs(data?.links.threads)}\n />\n )}\n </div>\n </ShellPortalContext.Provider>\n );\n}\n"],"mappings":"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"}