@neuronection/assistant-ui 0.28.1 → 0.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/dist/about.d.ts +2 -1
- package/dist/badge.d.ts +1 -1
- package/dist/button.d.ts +1 -1
- package/dist/chat-branch-tree.d.ts +2 -2
- package/dist/chat-core.d.ts +3 -3
- package/dist/chat-message.d.ts +1 -1
- package/dist/chat-session-list.js +1 -1
- package/dist/chat-tools-catalog.js +1 -1
- package/dist/chat-trace-timeline.d.ts +12 -0
- package/dist/chat-trace-timeline.js +1 -1
- package/dist/chat-transcript.d.ts +1 -1
- package/dist/{chunk-NKYPNEOX.js → chunk-66K355IZ.js} +3 -3
- package/dist/chunk-66K355IZ.js.map +1 -0
- package/dist/chunk-HC6DBXYJ.js +236 -0
- package/dist/chunk-HC6DBXYJ.js.map +1 -0
- package/dist/{chunk-ZSCL34WT.js → chunk-TC4NQL3H.js} +12 -5
- package/dist/chunk-TC4NQL3H.js.map +1 -0
- package/dist/chunk-U5WSPZLX.js +133 -0
- package/dist/chunk-U5WSPZLX.js.map +1 -0
- package/dist/index.d.ts +2526 -91
- package/dist/index.js +7 -137
- package/dist/index.js.map +1 -1
- package/dist/logo.d.ts +9 -3
- package/dist/styles.css +1 -1
- package/dist/task-assignment-picker.d.ts +14 -1
- package/dist/theme-scope.d.ts +7 -1
- package/dist/{tree-YaIz73vo.d.ts → tree-4Hv9stjF.d.ts} +2 -2
- package/dist/{types-DZwzmyKE.d.ts → types-LhE1KFBf.d.ts} +1 -1
- package/dist/upload-dropzone.d.ts +24 -0
- package/dist/upload-dropzone.js +3 -0
- package/dist/upload-dropzone.js.map +1 -0
- package/package.json +3 -2
- package/dist/Logo-D8DEBUoL.d.ts +0 -11
- package/dist/chunk-5KFOQEOG.js +0 -154
- package/dist/chunk-5KFOQEOG.js.map +0 -1
- package/dist/chunk-NKYPNEOX.js.map +0 -1
- package/dist/chunk-ZSCL34WT.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @neuronection/assistant-ui
|
|
2
2
|
|
|
3
|
+
## 0.29.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`6c8882c`](https://github.com/neuronection/assistant-ui/commit/6c8882cfc951a167b728b3977b5e1cffdda87a0b) Thanks [@constLiakos](https://github.com/constLiakos)! - fix(a11y): ChatSessionList and ChatToolsCatalog no longer render their empty/no-matches `<p>` states as children of `role="list"` (aria-required-children, critical — a list expects listitem children). The `role="list"` container now renders only when there are items to show; empty and no-results states render standalone with unchanged copy and styling. Found by desktop-assistant's new exclusion-free axe scans of the chat desktop window; regression axe tests for both components and a SessionListEmpty Ladle story added.
|
|
8
|
+
|
|
9
|
+
## 0.29.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [`e73579a`](https://github.com/neuronection/assistant-ui/commit/e73579ad0ab9795e7111a309d852b6042f2f5c2f) Thanks [@constLiakos](https://github.com/constLiakos)! - ChatTraceTimeline: full tool-call observability. `ChatTraceTimelineEntry`
|
|
14
|
+
gains optional `status` (`'ok' | 'error'` — renders a status dot after
|
|
15
|
+
the duration), `args` and `response` (pretty-printed strings) — `tool`
|
|
16
|
+
rows with `args`/`response` render a labelled, expandable detail region
|
|
17
|
+
(`Arguments` / `Response` blocks, `chat-trace-detail-toggle` button +
|
|
18
|
+
`chat-trace-detail` region, accessible name `"<tool> details"`). Labels
|
|
19
|
+
gain `arguments`, `response`, `details`. All fields optional — existing
|
|
20
|
+
usage renders unchanged.
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- [`5f06c3e`](https://github.com/neuronection/assistant-ui/commit/5f06c3e7fd9ca2cf419ad7dc5b79148edff4022d) Thanks [@constLiakos](https://github.com/constLiakos)! - fix(chat-tools-catalog): sentence-length scope values can no longer break the header row — the scope chip is capped at 40% of the row width with an ellipsis and exposes the full text via a native `title` tooltip, and the name/title slot wraps (`break-words`) instead of painting over the chip and chevron. Docs page, accessibility row, LongScopeAndName story, and a regression test added.
|
|
25
|
+
|
|
26
|
+
- [`732f29e`](https://github.com/neuronection/assistant-ui/commit/732f29e91edad217b7aa47edcdbd20ead7af75cc) Thanks [@constLiakos](https://github.com/constLiakos)! - fix(build): un-block the release gate — `pnpm build` no longer dies with `ERR_WORKER_OUT_OF_MEMORY` in tsup's dts worker (CI's 7 GB runner and memory-capped machines both hit it once the entry count reached ~80). Declaration emission now runs as sequential `dts: { only: true }` shards (`build:dts`, one tsup invocation + one dts worker each, `DTS_SHARD=0..N` over `tsup.dts.config.ts`, ~10 entries per shard) instead of one worker accumulating all 80 entries; JS output still builds as a single config, so chunk sharing is unchanged. tsup is `pnpm patch`ed to give the dts worker an explicit 3 GB heap (`resourceLimits.maxOldGenerationSizeMb`, overridable via `TSUP_DTS_WORKER_HEAP_MB`) because tsup spawns it without limits and Node sizes the default from total RAM, not cgroup/runner limits. Verified end-to-end under a 7 GB memory cap.
|
|
27
|
+
|
|
28
|
+
- [`487a853`](https://github.com/neuronection/assistant-ui/commit/487a853ded7d93440851392d00acafcba157da31) Thanks [@constLiakos](https://github.com/constLiakos)! - Fix the `./upload-dropzone` subpath export: the module shipped in the main barrel and was listed in the package `exports` map, but had no tsup entry, so `dist/upload-dropzone.*` was never built and subpath imports failed to resolve in consumer apps. Career-assistant imports it from the main barrel until the next release.
|
|
29
|
+
|
|
3
30
|
## 0.28.1
|
|
4
31
|
|
|
5
32
|
### Patch Changes
|
package/dist/about.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
|
-
import { a as LogoTheme } from './Logo-D8DEBUoL.js';
|
|
5
4
|
|
|
6
5
|
interface AboutCardProps extends Omit<React.ComponentProps<'div'>, 'title'> {
|
|
7
6
|
icon?: React.ReactNode;
|
|
@@ -43,6 +42,8 @@ interface AboutFooterLineProps extends React.ComponentProps<'p'> {
|
|
|
43
42
|
}
|
|
44
43
|
declare const AboutFooterLine: React.ForwardRefExoticComponent<Omit<AboutFooterLineProps, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
|
|
45
44
|
|
|
45
|
+
type LogoTheme = 'light' | 'dark';
|
|
46
|
+
|
|
46
47
|
type FamilyApp = 'health' | 'career' | 'study';
|
|
47
48
|
interface FamilyMember {
|
|
48
49
|
app: FamilyApp;
|
package/dist/badge.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const badgeVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "warning" | "success" | "danger" | "default" | "secondary" | "outline" | "ai" | null | undefined;
|
|
7
7
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
8
8
|
interface BadgeProps extends React.ComponentProps<'span'>, VariantProps<typeof badgeVariants> {
|
|
9
9
|
}
|
package/dist/button.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
6
|
variant?: "default" | "secondary" | "outline" | "ghost" | "destructive" | null | undefined;
|
|
7
|
-
size?: "
|
|
7
|
+
size?: "sm" | "lg" | "default" | "icon" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface ButtonProps extends React.ComponentProps<'button'>, VariantProps<typeof buttonVariants> {
|
|
10
10
|
asChild?: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { LucideIcon } from 'lucide-react';
|
|
3
|
-
import {
|
|
4
|
-
import './types-
|
|
3
|
+
import { B as BranchTree } from './tree-4Hv9stjF.js';
|
|
4
|
+
import './types-LhE1KFBf.js';
|
|
5
5
|
|
|
6
6
|
interface ChatBranchTreeIcons {
|
|
7
7
|
user: LucideIcon;
|
package/dist/chat-core.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { a as ChatAttachmentView,
|
|
3
|
-
export {
|
|
1
|
+
import { C as ChatError } from './types-LhE1KFBf.js';
|
|
2
|
+
export { a as ChatAttachmentView, b as ChatMessageStatus, c as ChatMessageVariants, d as ChatMessageView, e as ChatRole } from './types-LhE1KFBf.js';
|
|
3
|
+
export { a as BranchNode, b as BranchNodeInput, B as BranchTree, c as activePathSet, d as buildBranchTree, l as linearTree, v as variantInfo, w as walkActivePath } from './tree-4Hv9stjF.js';
|
|
4
4
|
|
|
5
5
|
interface FlowStepInfo {
|
|
6
6
|
id: string;
|
package/dist/chat-message.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { LucideIcon } from 'lucide-react';
|
|
3
|
-
import {
|
|
3
|
+
import { c as ChatMessageVariants, e as ChatRole, C as ChatError } from './types-LhE1KFBf.js';
|
|
4
4
|
|
|
5
5
|
interface ChatMessageEditorLabels {
|
|
6
6
|
save: string;
|
|
@@ -9,6 +9,12 @@ interface ChatTraceTimelineEntry {
|
|
|
9
9
|
detail?: string | null;
|
|
10
10
|
startMs?: number | null;
|
|
11
11
|
durationMs?: number | null;
|
|
12
|
+
/** Outcome of a tool execution (`tool` rows); renders a status dot. */
|
|
13
|
+
status?: 'ok' | 'error' | null;
|
|
14
|
+
/** Pretty-printed call arguments (expandable block on `tool` rows). */
|
|
15
|
+
args?: string | null;
|
|
16
|
+
/** Tool response text (expandable block on `tool` rows). */
|
|
17
|
+
response?: string | null;
|
|
12
18
|
}
|
|
13
19
|
interface ChatTraceTimelineTrace {
|
|
14
20
|
model?: string | null;
|
|
@@ -29,6 +35,12 @@ interface ChatTraceTimelineLabels {
|
|
|
29
35
|
/** Suffix of the token count, e.g. `tokens`. */
|
|
30
36
|
tokens: string;
|
|
31
37
|
reasoning: string;
|
|
38
|
+
/** Header of the expandable arguments block. */
|
|
39
|
+
arguments: string;
|
|
40
|
+
/** Header of the expandable response block. */
|
|
41
|
+
response: string;
|
|
42
|
+
/** Accessible name of a tool row's detail disclosure. */
|
|
43
|
+
details: string;
|
|
32
44
|
}
|
|
33
45
|
interface ChatTraceTimelineProps {
|
|
34
46
|
trace: ChatTraceTimelineTrace;
|
|
@@ -111,7 +111,7 @@ var ChatSessionList = React.forwardRef(
|
|
|
111
111
|
}
|
|
112
112
|
) : null
|
|
113
113
|
] }),
|
|
114
|
-
|
|
114
|
+
sessions.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-2 py-3 text-xs text-[var(--as-muted-fg)]", children: labels?.empty ?? "No conversations yet" }) : filtered.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-2 py-3 text-xs text-[var(--as-muted-fg)]", children: labels?.noResults ?? "No matches" }) : /* @__PURE__ */ jsx("div", { role: "list", "aria-label": labels?.search ?? "Conversations", className: "min-h-0 flex-1 overflow-y-auto", children: groups.map((group) => /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
|
|
115
115
|
group.label ? /* @__PURE__ */ jsx("p", { className: "px-2 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-[var(--as-muted-fg)]", children: group.label }) : null,
|
|
116
116
|
group.sessions.map((session) => {
|
|
117
117
|
const isActive = session.id === activeId;
|
|
@@ -194,5 +194,5 @@ var ChatSessionList = React.forwardRef(
|
|
|
194
194
|
);
|
|
195
195
|
|
|
196
196
|
export { ChatSessionList };
|
|
197
|
-
//# sourceMappingURL=chunk-
|
|
198
|
-
//# sourceMappingURL=chunk-
|
|
197
|
+
//# sourceMappingURL=chunk-66K355IZ.js.map
|
|
198
|
+
//# sourceMappingURL=chunk-66K355IZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/chat-session-list/ChatSessionList.tsx"],"names":["ChatSessionList"],"mappings":"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","file":"chunk-66K355IZ.js","sourcesContent":["import * as React from 'react'\nimport { Download, MessageSquarePlus, Pencil, Search, Trash2 } from 'lucide-react'\nimport type { LucideIcon } from 'lucide-react'\nimport { formatDistanceToNow, isToday, isYesterday, parseISO } from 'date-fns'\n\nimport { cn } from '../../lib/utils'\nimport { searchScore } from '../../lib/fuzzy'\n\nexport interface ChatSessionView {\n id: string\n title: string\n updatedAt?: string | number | Date\n meta?: Record<string, unknown>\n}\n\nexport interface ChatSessionListLabels {\n search: string\n searchPlaceholder: string\n newChat: string\n rename: string\n delete: string\n export: string\n today: string\n yesterday: string\n earlier: string\n empty: string\n noResults: string\n}\n\nexport interface ChatSessionListIcons {\n newChat: LucideIcon\n rename: LucideIcon\n delete: LucideIcon\n export: LucideIcon\n}\n\nexport interface ChatSessionListProps {\n sessions: ChatSessionView[]\n activeId?: string | null\n onSelect: (id: string) => void\n onNew?: () => void\n onRename?: (id: string) => void\n onDelete?: (id: string) => void\n onExport?: (id: string) => void\n searchable?: boolean\n groupByDate?: boolean\n labels?: Partial<ChatSessionListLabels>\n icons?: Partial<ChatSessionListIcons>\n className?: string\n}\n\nfunction toDate(value: string | number | Date | undefined): Date | undefined {\n if (value === undefined) {\n return undefined\n }\n if (value instanceof Date) {\n return value\n }\n if (typeof value === 'number') {\n return new Date(value)\n }\n return parseISO(value)\n}\n\nfunction bucketOf(date: Date | undefined): 'today' | 'yesterday' | 'earlier' | 'none' {\n if (date === undefined) {\n return 'none'\n }\n if (isToday(date)) {\n return 'today'\n }\n if (isYesterday(date)) {\n return 'yesterday'\n }\n return 'earlier'\n}\n\n/**\n * The session list beside a full-page chat (study's `ChatSessionList` +\n * health's history overlay, generalized): fuzzy search, date grouping,\n * active marking, per-session actions (rename/delete/export) via the\n * menu when handlers are provided. All actions stay app-side.\n */\nexport const ChatSessionList = React.forwardRef<HTMLDivElement, ChatSessionListProps>(\n function ChatSessionList(\n {\n sessions,\n activeId,\n onSelect,\n onNew,\n onRename,\n onDelete,\n onExport,\n searchable = true,\n groupByDate = true,\n labels,\n icons,\n className,\n },\n ref,\n ) {\n const [query, setQuery] = React.useState('')\n const NewIcon = icons?.newChat ?? MessageSquarePlus\n const RenameIcon = icons?.rename ?? Pencil\n const DeleteIcon = icons?.delete ?? Trash2\n const ExportIcon = icons?.export ?? Download\n\n const filtered = React.useMemo(() => {\n const trimmed = query.trim()\n if (trimmed === '') {\n return sessions\n }\n return sessions\n .map((session) => ({\n session,\n score: searchScore(trimmed, session.title),\n }))\n .filter((entry) => entry.score !== null)\n .sort((a, b) => (b.score ?? 0) - (a.score ?? 0))\n .map((entry) => entry.session)\n }, [sessions, query])\n\n const groups = React.useMemo(() => {\n if (!groupByDate) {\n return [{ key: 'all', label: null as string | null, sessions: filtered }]\n }\n const ordered = [...filtered].sort((a, b) => {\n const dateA = toDate(a.updatedAt)?.getTime() ?? 0\n const dateB = toDate(b.updatedAt)?.getTime() ?? 0\n return dateB - dateA\n })\n const byBucket = new Map<string, ChatSessionView[]>()\n for (const session of ordered) {\n const bucket = bucketOf(toDate(session.updatedAt))\n const list = byBucket.get(bucket) ?? []\n list.push(session)\n byBucket.set(bucket, list)\n }\n const order = ['today', 'yesterday', 'earlier', 'none']\n return order\n .filter((bucket) => byBucket.has(bucket))\n .map((bucket) => ({\n key: bucket,\n label:\n bucket === 'today'\n ? (labels?.today ?? 'Today')\n : bucket === 'yesterday'\n ? (labels?.yesterday ?? 'Yesterday')\n : bucket === 'earlier'\n ? (labels?.earlier ?? 'Earlier')\n : null,\n sessions: byBucket.get(bucket) ?? [],\n }))\n }, [filtered, groupByDate, labels])\n\n return (\n <div ref={ref} data-as=\"chat-session-list\" className={cn('flex h-full min-h-0 w-full flex-col gap-2', className)}>\n <div className=\"flex items-center gap-2\">\n {searchable ? (\n <div className=\"relative min-w-0 flex-1\">\n <Search className=\"pointer-events-none absolute start-2 top-1/2 size-3.5 -translate-y-1/2 text-[var(--as-muted-fg)]\" aria-hidden />\n <input\n type=\"search\"\n role=\"searchbox\"\n value={query}\n aria-label={labels?.search ?? 'Search conversations'}\n placeholder={labels?.searchPlaceholder ?? 'Search…'}\n onChange={(event) => setQuery(event.target.value)}\n className=\"w-full rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] py-1.5 pe-2 ps-8 text-xs text-[var(--as-fg)] placeholder:text-[var(--as-muted-fg)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]\"\n />\n </div>\n ) : null}\n {onNew ? (\n <button\n type=\"button\"\n onClick={onNew}\n aria-label={labels?.newChat ?? 'New conversation'}\n title={labels?.newChat ?? 'New conversation'}\n className=\"flex size-7 shrink-0 items-center justify-center rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] text-[var(--as-fg)] transition-colors hover:bg-[var(--as-secondary)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <NewIcon className=\"size-4\" aria-hidden />\n </button>\n ) : null}\n </div>\n {sessions.length === 0 ? (\n <p className=\"px-2 py-3 text-xs text-[var(--as-muted-fg)]\">{labels?.empty ?? 'No conversations yet'}</p>\n ) : filtered.length === 0 ? (\n <p className=\"px-2 py-3 text-xs text-[var(--as-muted-fg)]\">{labels?.noResults ?? 'No matches'}</p>\n ) : (\n <div role=\"list\" aria-label={labels?.search ?? 'Conversations'} className=\"min-h-0 flex-1 overflow-y-auto\">\n {groups.map((group) => (\n <div key={group.key} className=\"mb-2\">\n {group.label ? (\n <p className=\"px-2 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-[var(--as-muted-fg)]\">\n {group.label}\n </p>\n ) : null}\n {group.sessions.map((session) => {\n const isActive = session.id === activeId\n const date = toDate(session.updatedAt)\n const actions =\n onRename || onDelete || onExport\n ? [\n onRename\n ? {\n key: 'rename',\n label: labels?.rename ?? 'Rename',\n icon: <RenameIcon className=\"size-3.5\" aria-hidden />,\n onSelect: () => onRename(session.id),\n }\n : null,\n onExport\n ? {\n key: 'export',\n label: labels?.export ?? 'Export',\n icon: <ExportIcon className=\"size-3.5\" aria-hidden />,\n onSelect: () => onExport(session.id),\n }\n : null,\n onDelete\n ? {\n key: 'delete',\n label: labels?.delete ?? 'Delete',\n icon: <DeleteIcon className=\"size-3.5\" aria-hidden />,\n onSelect: () => onDelete(session.id),\n danger: true,\n }\n : null,\n ].filter((item): item is NonNullable<typeof item> => item !== null)\n : []\n return (\n <div\n key={session.id}\n role=\"listitem\"\n aria-current={isActive ? 'true' : undefined}\n data-active={isActive || undefined}\n className={cn(\n 'group/session flex cursor-pointer items-center gap-2 rounded-[var(--as-radius)] px-2 py-1.5 text-xs transition-colors hover:bg-[var(--as-surface-raised)]',\n isActive && 'bg-[var(--as-surface-raised)] font-medium text-[var(--as-fg)]',\n )}\n onClick={() => onSelect(session.id)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n onSelect(session.id)\n }\n }}\n tabIndex={0}\n >\n <span className=\"min-w-0 flex-1 truncate text-[var(--as-fg)]\">{session.title}</span>\n {date ? (\n <span className=\"shrink-0 text-[10px] text-[var(--as-muted-fg)]\">\n {formatDistanceToNow(date, { addSuffix: true })}\n </span>\n ) : null}\n {actions.length > 0 ? (\n <span\n role=\"group\"\n aria-label={labels?.rename ?? 'Conversation actions'}\n className=\"flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity focus-within:opacity-100 group-hover/session:opacity-100\"\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n >\n {actions.map((action) => (\n <button\n key={action.key}\n type=\"button\"\n aria-label={action.label}\n title={action.label}\n onClick={action.onSelect}\n className={cn(\n 'rounded-[var(--as-radius-sm)] p-1 text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-surface)] hover:text-[var(--as-fg)] focus-visible:opacity-100 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]',\n action.danger && 'hover:text-[var(--as-danger)]',\n )}\n >\n {action.icon}\n </button>\n ))}\n </span>\n ) : null}\n </div>\n )\n })}\n </div>\n ))\n }\n </div>\n )}\n </div>\n )\n },\n)\n"]}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { cn } from './chunk-BLJWR4ZV.js';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Timer, ChevronDown, ChevronRight, Brain } from 'lucide-react';
|
|
4
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
function formatDuration(ms) {
|
|
7
|
+
if (ms < 1e3) {
|
|
8
|
+
return `${Math.round(ms)} ms`;
|
|
9
|
+
}
|
|
10
|
+
return `${(ms / 1e3).toFixed(1)} s`;
|
|
11
|
+
}
|
|
12
|
+
var ChatTraceTimeline = React.forwardRef(
|
|
13
|
+
function ChatTraceTimeline2({ trace, entries, defaultOpen = false, labels, className }, ref) {
|
|
14
|
+
const [open, setOpen] = React.useState(defaultOpen);
|
|
15
|
+
const totalMs = Math.max(1, trace.latencyMs ?? 0);
|
|
16
|
+
const duration = formatDuration(trace.latencyMs ?? 0);
|
|
17
|
+
const toolsLabel = labels?.tools ?? "tools";
|
|
18
|
+
const toolCount = entries.filter((entry) => entry.kind === "tool").length;
|
|
19
|
+
const items = [...entries].sort(
|
|
20
|
+
(a, b) => (a.startMs ?? 0) - (b.startMs ?? 0)
|
|
21
|
+
);
|
|
22
|
+
return /* @__PURE__ */ jsxs(
|
|
23
|
+
"div",
|
|
24
|
+
{
|
|
25
|
+
ref,
|
|
26
|
+
"data-as": "chat-trace-timeline",
|
|
27
|
+
className: cn("w-full max-w-[92%]", className),
|
|
28
|
+
children: [
|
|
29
|
+
/* @__PURE__ */ jsxs(
|
|
30
|
+
"button",
|
|
31
|
+
{
|
|
32
|
+
type: "button",
|
|
33
|
+
onClick: () => setOpen((value) => !value),
|
|
34
|
+
"aria-expanded": open,
|
|
35
|
+
"aria-label": labels?.toggle ?? "Show response trace",
|
|
36
|
+
className: "flex items-center gap-1.5 text-[11px] text-[var(--as-muted-fg)] transition-colors hover:text-[var(--as-fg)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]",
|
|
37
|
+
children: [
|
|
38
|
+
/* @__PURE__ */ jsx(Timer, { className: "size-3.5 shrink-0", "aria-hidden": true }),
|
|
39
|
+
/* @__PURE__ */ jsx("span", { children: `${duration} \xB7 ${toolCount} ${toolsLabel}` }),
|
|
40
|
+
trace.model ? /* @__PURE__ */ jsxs("span", { className: "font-mono text-[10px]", children: [
|
|
41
|
+
"\xB7 ",
|
|
42
|
+
trace.model
|
|
43
|
+
] }) : null,
|
|
44
|
+
/* @__PURE__ */ jsx(
|
|
45
|
+
ChevronDown,
|
|
46
|
+
{
|
|
47
|
+
className: cn(
|
|
48
|
+
"size-3.5 shrink-0 transition-transform duration-150",
|
|
49
|
+
open && "rotate-180"
|
|
50
|
+
),
|
|
51
|
+
"aria-hidden": true
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
),
|
|
57
|
+
open ? /* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-col gap-1.5 overflow-hidden", children: [
|
|
58
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-[11px] text-[var(--as-muted-fg)]", children: [
|
|
59
|
+
/* @__PURE__ */ jsx("span", { children: `${labels?.total ?? "Total"} ${duration}` }),
|
|
60
|
+
/* @__PURE__ */ jsx("span", { children: `${trace.outputTokens ?? 0} ${labels?.tokens ?? "tokens"}` })
|
|
61
|
+
] }),
|
|
62
|
+
items.map((item, index) => /* @__PURE__ */ jsx(TraceRow, { item, totalMs, labels }, `${item.kind}-${index}`)),
|
|
63
|
+
trace.thinking ? /* @__PURE__ */ jsx(
|
|
64
|
+
ThinkingDisclosure,
|
|
65
|
+
{
|
|
66
|
+
thinking: trace.thinking,
|
|
67
|
+
label: labels?.reasoning ?? "Reasoning"
|
|
68
|
+
}
|
|
69
|
+
) : null
|
|
70
|
+
] }) : null
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
function TraceRow({
|
|
77
|
+
item,
|
|
78
|
+
totalMs,
|
|
79
|
+
labels
|
|
80
|
+
}) {
|
|
81
|
+
const [open, setOpen] = React.useState(false);
|
|
82
|
+
const regionId = React.useId();
|
|
83
|
+
const expandable = Boolean(item.args || item.response);
|
|
84
|
+
const width = Math.max(2, Math.min(100, (item.durationMs ?? 0) / totalMs * 100));
|
|
85
|
+
return /* @__PURE__ */ jsxs("div", { "data-kind": item.kind, "data-status": item.status ?? void 0, children: [
|
|
86
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[11px]", children: [
|
|
87
|
+
expandable ? /* @__PURE__ */ jsx(
|
|
88
|
+
"button",
|
|
89
|
+
{
|
|
90
|
+
type: "button",
|
|
91
|
+
"aria-expanded": open,
|
|
92
|
+
"aria-controls": regionId,
|
|
93
|
+
title: item.detail ?? void 0,
|
|
94
|
+
className: "w-16 shrink-0 truncate text-left text-[11px] text-[var(--as-fg)] transition-colors hover:text-[var(--as-primary)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
|
|
95
|
+
onClick: () => setOpen((value) => !value),
|
|
96
|
+
children: item.label
|
|
97
|
+
}
|
|
98
|
+
) : /* @__PURE__ */ jsx(
|
|
99
|
+
"span",
|
|
100
|
+
{
|
|
101
|
+
className: "w-16 shrink-0 truncate text-[var(--as-muted-fg)]",
|
|
102
|
+
title: item.detail ?? void 0,
|
|
103
|
+
children: item.label
|
|
104
|
+
}
|
|
105
|
+
),
|
|
106
|
+
/* @__PURE__ */ jsx("div", { className: "h-1.5 min-w-0 flex-1 overflow-hidden rounded-full bg-[var(--as-surface-raised)]", children: /* @__PURE__ */ jsx(
|
|
107
|
+
"div",
|
|
108
|
+
{
|
|
109
|
+
className: cn(
|
|
110
|
+
"h-full rounded-full",
|
|
111
|
+
item.kind === "phase" ? "bg-[var(--as-primary)]" : "bg-[var(--as-warning)]"
|
|
112
|
+
),
|
|
113
|
+
style: { width: `${width}%` }
|
|
114
|
+
}
|
|
115
|
+
) }),
|
|
116
|
+
/* @__PURE__ */ jsx("span", { className: "w-12 shrink-0 text-right font-mono text-[10px] text-[var(--as-muted-fg)]", children: formatDuration(item.durationMs ?? 0) }),
|
|
117
|
+
item.status ? /* @__PURE__ */ jsx(
|
|
118
|
+
"span",
|
|
119
|
+
{
|
|
120
|
+
"data-as": "chat-trace-status",
|
|
121
|
+
title: item.status,
|
|
122
|
+
className: cn(
|
|
123
|
+
"size-2 shrink-0 rounded-full",
|
|
124
|
+
item.status === "error" ? "bg-[var(--as-danger)]" : "bg-[var(--as-success)]"
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
) : /* @__PURE__ */ jsx("span", { className: "size-2 shrink-0" }),
|
|
128
|
+
expandable ? /* @__PURE__ */ jsx(
|
|
129
|
+
"button",
|
|
130
|
+
{
|
|
131
|
+
type: "button",
|
|
132
|
+
"data-as": "chat-trace-detail-toggle",
|
|
133
|
+
"aria-expanded": open,
|
|
134
|
+
"aria-controls": regionId,
|
|
135
|
+
"aria-label": `${item.label} ${labels?.details ?? "details"}`,
|
|
136
|
+
onClick: () => setOpen((value) => !value),
|
|
137
|
+
className: "flex size-5 shrink-0 items-center justify-center rounded text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-muted)] hover:text-[var(--as-fg)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
|
|
138
|
+
children: open ? /* @__PURE__ */ jsx(ChevronDown, { className: "size-3", "aria-hidden": true }) : /* @__PURE__ */ jsx(ChevronRight, { className: "size-3", "aria-hidden": true })
|
|
139
|
+
}
|
|
140
|
+
) : /* @__PURE__ */ jsx("span", { className: "w-5 shrink-0" })
|
|
141
|
+
] }),
|
|
142
|
+
expandable && open ? /* @__PURE__ */ jsxs(
|
|
143
|
+
"div",
|
|
144
|
+
{
|
|
145
|
+
id: regionId,
|
|
146
|
+
"data-as": "chat-trace-detail",
|
|
147
|
+
"data-open": "true",
|
|
148
|
+
className: "mb-1.5 ml-[4.5rem] border-l border-[var(--as-border)] pl-2",
|
|
149
|
+
children: [
|
|
150
|
+
item.args ? /* @__PURE__ */ jsx(DetailBlock, { label: labels?.arguments ?? "Arguments", text: item.args }) : null,
|
|
151
|
+
item.response ? /* @__PURE__ */ jsx(DetailBlock, { label: labels?.response ?? "Response", text: item.response }) : null
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
) : null
|
|
155
|
+
] });
|
|
156
|
+
}
|
|
157
|
+
function detailEntries(text) {
|
|
158
|
+
try {
|
|
159
|
+
const parsed = JSON.parse(text);
|
|
160
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
161
|
+
const entries = Object.entries(parsed).map(([key, value]) => ({
|
|
162
|
+
key,
|
|
163
|
+
value: typeof value === "string" ? value : JSON.stringify(value)
|
|
164
|
+
}));
|
|
165
|
+
return entries.length > 0 ? entries : null;
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
} catch {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function DetailBlock({
|
|
173
|
+
label,
|
|
174
|
+
text
|
|
175
|
+
}) {
|
|
176
|
+
const entries = detailEntries(text);
|
|
177
|
+
return /* @__PURE__ */ jsxs("div", { className: "pt-1", children: [
|
|
178
|
+
/* @__PURE__ */ jsx("p", { className: "text-[10px] font-semibold uppercase tracking-wide text-[var(--as-muted-fg)]", children: label }),
|
|
179
|
+
entries ? /* @__PURE__ */ jsx("dl", { className: "mt-0.5 space-y-0.5", children: entries.map((entry) => /* @__PURE__ */ jsxs(
|
|
180
|
+
"div",
|
|
181
|
+
{
|
|
182
|
+
className: "flex items-baseline justify-between gap-2 rounded-md bg-[var(--as-muted)] px-2 py-1",
|
|
183
|
+
children: [
|
|
184
|
+
/* @__PURE__ */ jsx("dt", { className: "text-[10px] uppercase tracking-wide text-[var(--as-muted-fg)]", children: entry.key }),
|
|
185
|
+
/* @__PURE__ */ jsx("dd", { className: "min-w-0 break-words text-right text-[11px] font-medium text-[var(--as-fg)]", children: entry.value })
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
entry.key
|
|
189
|
+
)) }) : /* @__PURE__ */ jsx("p", { className: "mt-0.5 whitespace-pre-wrap break-words text-[11px] text-[var(--as-fg)]", children: text })
|
|
190
|
+
] });
|
|
191
|
+
}
|
|
192
|
+
function ThinkingDisclosure({
|
|
193
|
+
thinking,
|
|
194
|
+
label
|
|
195
|
+
}) {
|
|
196
|
+
const [open, setOpen] = React.useState(false);
|
|
197
|
+
const regionId = React.useId();
|
|
198
|
+
return /* @__PURE__ */ jsxs("div", { className: "rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)]", children: [
|
|
199
|
+
/* @__PURE__ */ jsxs(
|
|
200
|
+
"button",
|
|
201
|
+
{
|
|
202
|
+
type: "button",
|
|
203
|
+
onClick: () => setOpen((value) => !value),
|
|
204
|
+
"aria-expanded": open,
|
|
205
|
+
"aria-controls": regionId,
|
|
206
|
+
className: "flex w-full items-center gap-1.5 rounded-[var(--as-radius)] px-2 py-1.5 text-left text-[11px] text-[var(--as-muted-fg)] transition-colors hover:text-[var(--as-fg)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]",
|
|
207
|
+
children: [
|
|
208
|
+
/* @__PURE__ */ jsx(Brain, { className: "size-3.5 shrink-0", "aria-hidden": true }),
|
|
209
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1", children: label }),
|
|
210
|
+
/* @__PURE__ */ jsx(
|
|
211
|
+
ChevronDown,
|
|
212
|
+
{
|
|
213
|
+
className: cn(
|
|
214
|
+
"size-3.5 shrink-0 transition-transform duration-150",
|
|
215
|
+
open && "rotate-180"
|
|
216
|
+
),
|
|
217
|
+
"aria-hidden": true
|
|
218
|
+
}
|
|
219
|
+
)
|
|
220
|
+
]
|
|
221
|
+
}
|
|
222
|
+
),
|
|
223
|
+
open ? /* @__PURE__ */ jsx(
|
|
224
|
+
"p",
|
|
225
|
+
{
|
|
226
|
+
id: regionId,
|
|
227
|
+
className: "whitespace-pre-wrap px-2.5 pb-2 text-[11px] text-[var(--as-muted-fg)]",
|
|
228
|
+
children: thinking
|
|
229
|
+
}
|
|
230
|
+
) : null
|
|
231
|
+
] });
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export { ChatTraceTimeline };
|
|
235
|
+
//# sourceMappingURL=chunk-HC6DBXYJ.js.map
|
|
236
|
+
//# sourceMappingURL=chunk-HC6DBXYJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/chat-trace-timeline/ChatTraceTimeline.tsx"],"names":["ChatTraceTimeline"],"mappings":"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","file":"chunk-HC6DBXYJ.js","sourcesContent":["import * as React from 'react'\nimport { Brain, ChevronDown, ChevronRight, Timer } from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\n\nexport interface ChatTraceTimelineEntry {\n /** `phase` = model/flow round (primary bar); `tool` = tool call (warning bar). */\n kind: 'phase' | 'tool'\n /** Phase label or tool name (translated at the call site). */\n label: string\n /** Secondary detail, e.g. the tool arguments summary (title tooltip). */\n detail?: string | null\n startMs?: number | null\n durationMs?: number | null\n /** Outcome of a tool execution (`tool` rows); renders a status dot. */\n status?: 'ok' | 'error' | null\n /** Pretty-printed call arguments (expandable block on `tool` rows). */\n args?: string | null\n /** Tool response text (expandable block on `tool` rows). */\n response?: string | null\n}\n\nexport interface ChatTraceTimelineTrace {\n model?: string | null\n /** Total turn latency the bars are proportional to. */\n latencyMs?: number | null\n inputTokens?: number | null\n outputTokens?: number | null\n /** Raw model reasoning, shown in a nested disclosure. */\n thinking?: string | null\n}\n\nexport interface ChatTraceTimelineLabels {\n /** Accessible name of the toggle (summary is composed from data). */\n toggle: string\n /** Word appended to the tool count, e.g. `tools`. */\n tools: string\n /** Prefix of the expanded total row, e.g. `Total`. */\n total: string\n /** Suffix of the token count, e.g. `tokens`. */\n tokens: string\n reasoning: string\n /** Header of the expandable arguments block. */\n arguments: string\n /** Header of the expandable response block. */\n response: string\n /** Accessible name of a tool row's detail disclosure. */\n details: string\n}\n\nexport interface ChatTraceTimelineProps {\n trace: ChatTraceTimelineTrace\n entries: ChatTraceTimelineEntry[]\n defaultOpen?: boolean\n labels?: Partial<ChatTraceTimelineLabels>\n className?: string\n}\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${Math.round(ms)} ms`\n }\n return `${(ms / 1000).toFixed(1)} s`\n}\n\n/**\n * Collapsible per-turn trace timeline (study's `TraceTimeline`,\n * generalized): collapsed summary (duration · N tools · model), expanded\n * duration-proportional bar rows for flow phases and tool calls plus a\n * raw-reasoning disclosure. Presentational — persisted or live trace data\n * is mapped to `entries` app-side.\n */\nexport const ChatTraceTimeline = React.forwardRef<HTMLDivElement, ChatTraceTimelineProps>(\n function ChatTraceTimeline(\n { trace, entries, defaultOpen = false, labels, className },\n ref,\n ) {\n const [open, setOpen] = React.useState(defaultOpen)\n const totalMs = Math.max(1, trace.latencyMs ?? 0)\n const duration = formatDuration(trace.latencyMs ?? 0)\n const toolsLabel = labels?.tools ?? 'tools'\n const toolCount = entries.filter((entry) => entry.kind === 'tool').length\n const items = [...entries].sort(\n (a, b) => (a.startMs ?? 0) - (b.startMs ?? 0),\n )\n\n return (\n <div\n ref={ref}\n data-as=\"chat-trace-timeline\"\n className={cn('w-full max-w-[92%]', className)}\n >\n <button\n type=\"button\"\n onClick={() => setOpen((value) => !value)}\n aria-expanded={open}\n aria-label={labels?.toggle ?? 'Show response trace'}\n className=\"flex items-center gap-1.5 text-[11px] text-[var(--as-muted-fg)] transition-colors hover:text-[var(--as-fg)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <Timer className=\"size-3.5 shrink-0\" aria-hidden />\n <span>\n {`${duration} · ${toolCount} ${toolsLabel}`}\n </span>\n {trace.model ? (\n <span className=\"font-mono text-[10px]\">· {trace.model}</span>\n ) : null}\n <ChevronDown\n className={cn(\n 'size-3.5 shrink-0 transition-transform duration-150',\n open && 'rotate-180',\n )}\n aria-hidden\n />\n </button>\n {open ? (\n <div className=\"mt-2 flex flex-col gap-1.5 overflow-hidden\">\n <div className=\"flex items-center justify-between text-[11px] text-[var(--as-muted-fg)]\">\n <span>{`${labels?.total ?? 'Total'} ${duration}`}</span>\n <span>\n {`${trace.outputTokens ?? 0} ${labels?.tokens ?? 'tokens'}`}\n </span>\n </div>\n {items.map((item, index) => (\n <TraceRow key={`${item.kind}-${index}`} item={item} totalMs={totalMs} labels={labels} />\n ))}\n {trace.thinking ? (\n <ThinkingDisclosure\n thinking={trace.thinking}\n label={labels?.reasoning ?? 'Reasoning'}\n />\n ) : null}\n </div>\n ) : null}\n </div>\n )\n },\n)\n\nfunction TraceRow({\n item,\n totalMs,\n labels,\n}: {\n item: ChatTraceTimelineEntry\n totalMs: number\n labels?: Partial<ChatTraceTimelineLabels>\n}) {\n const [open, setOpen] = React.useState(false)\n const regionId = React.useId()\n const expandable = Boolean(item.args || item.response)\n const width = Math.max(2, Math.min(100, ((item.durationMs ?? 0) / totalMs) * 100))\n return (\n <div data-kind={item.kind} data-status={item.status ?? undefined}>\n <div className=\"flex items-center gap-2 text-[11px]\">\n {expandable ? (\n <button\n type=\"button\"\n aria-expanded={open}\n aria-controls={regionId}\n title={item.detail ?? undefined}\n className=\"w-16 shrink-0 truncate text-left text-[11px] text-[var(--as-fg)] transition-colors hover:text-[var(--as-primary)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]\"\n onClick={() => setOpen((value) => !value)}\n >\n {item.label}\n </button>\n ) : (\n <span\n className=\"w-16 shrink-0 truncate text-[var(--as-muted-fg)]\"\n title={item.detail ?? undefined}\n >\n {item.label}\n </span>\n )}\n <div className=\"h-1.5 min-w-0 flex-1 overflow-hidden rounded-full bg-[var(--as-surface-raised)]\">\n <div\n className={cn(\n 'h-full rounded-full',\n item.kind === 'phase'\n ? 'bg-[var(--as-primary)]'\n : 'bg-[var(--as-warning)]',\n )}\n style={{ width: `${width}%` }}\n />\n </div>\n <span className=\"w-12 shrink-0 text-right font-mono text-[10px] text-[var(--as-muted-fg)]\">\n {formatDuration(item.durationMs ?? 0)}\n </span>\n {item.status ? (\n <span\n data-as=\"chat-trace-status\"\n title={item.status}\n className={cn(\n 'size-2 shrink-0 rounded-full',\n item.status === 'error'\n ? 'bg-[var(--as-danger)]'\n : 'bg-[var(--as-success)]',\n )}\n />\n ) : (\n <span className=\"size-2 shrink-0\" />\n )}\n {expandable ? (\n <button\n type=\"button\"\n data-as=\"chat-trace-detail-toggle\"\n aria-expanded={open}\n aria-controls={regionId}\n aria-label={`${item.label} ${labels?.details ?? 'details'}`}\n onClick={() => setOpen((value) => !value)}\n className=\"flex size-5 shrink-0 items-center justify-center rounded text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-muted)] hover:text-[var(--as-fg)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n {open ? (\n <ChevronDown className=\"size-3\" aria-hidden />\n ) : (\n <ChevronRight className=\"size-3\" aria-hidden />\n )}\n </button>\n ) : (\n <span className=\"w-5 shrink-0\" />\n )}\n </div>\n {expandable && open ? (\n <div\n id={regionId}\n data-as=\"chat-trace-detail\"\n data-open=\"true\"\n className=\"mb-1.5 ml-[4.5rem] border-l border-[var(--as-border)] pl-2\"\n >\n {item.args ? (\n <DetailBlock label={labels?.arguments ?? 'Arguments'} text={item.args} />\n ) : null}\n {item.response ? (\n <DetailBlock label={labels?.response ?? 'Response'} text={item.response} />\n ) : null}\n </div>\n ) : null}\n </div>\n )\n}\n\nfunction detailEntries(text: string): Array<{ key: string; value: string }> | null {\n try {\n const parsed = JSON.parse(text) as unknown\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n const entries = Object.entries(parsed as Record<string, unknown>).map(([key, value]) => ({\n key,\n value: typeof value === 'string' ? value : JSON.stringify(value),\n }))\n return entries.length > 0 ? entries : null\n }\n return null\n } catch {\n return null\n }\n}\n\nfunction DetailBlock({\n label,\n text,\n}: {\n label: string\n text: string\n}) {\n const entries = detailEntries(text)\n return (\n <div className=\"pt-1\">\n <p className=\"text-[10px] font-semibold uppercase tracking-wide text-[var(--as-muted-fg)]\">\n {label}\n </p>\n {entries ? (\n <dl className=\"mt-0.5 space-y-0.5\">\n {entries.map((entry) => (\n <div\n key={entry.key}\n className=\"flex items-baseline justify-between gap-2 rounded-md bg-[var(--as-muted)] px-2 py-1\"\n >\n <dt className=\"text-[10px] uppercase tracking-wide text-[var(--as-muted-fg)]\">\n {entry.key}\n </dt>\n <dd className=\"min-w-0 break-words text-right text-[11px] font-medium text-[var(--as-fg)]\">\n {entry.value}\n </dd>\n </div>\n ))}\n </dl>\n ) : (\n <p className=\"mt-0.5 whitespace-pre-wrap break-words text-[11px] text-[var(--as-fg)]\">\n {text}\n </p>\n )}\n </div>\n )\n}\n\nfunction ThinkingDisclosure({\n thinking,\n label,\n}: {\n thinking: string\n label: string\n}) {\n const [open, setOpen] = React.useState(false)\n const regionId = React.useId()\n return (\n <div className=\"rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)]\">\n <button\n type=\"button\"\n onClick={() => setOpen((value) => !value)}\n aria-expanded={open}\n aria-controls={regionId}\n className=\"flex w-full items-center gap-1.5 rounded-[var(--as-radius)] px-2 py-1.5 text-left text-[11px] text-[var(--as-muted-fg)] transition-colors hover:text-[var(--as-fg)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <Brain className=\"size-3.5 shrink-0\" aria-hidden />\n <span className=\"flex-1\">{label}</span>\n <ChevronDown\n className={cn(\n 'size-3.5 shrink-0 transition-transform duration-150',\n open && 'rotate-180',\n )}\n aria-hidden\n />\n </button>\n {open ? (\n <p\n id={regionId}\n className=\"whitespace-pre-wrap px-2.5 pb-2 text-[11px] text-[var(--as-muted-fg)]\"\n >\n {thinking}\n </p>\n ) : null}\n </div>\n )\n}\n"]}
|
|
@@ -58,7 +58,7 @@ var ChatToolsCatalog = React.forwardRef(
|
|
|
58
58
|
}
|
|
59
59
|
)
|
|
60
60
|
] }) : null,
|
|
61
|
-
|
|
61
|
+
tools.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-1 py-3 text-xs text-[var(--as-muted-fg)]", children: labels?.empty ?? "No tools available" }) : filtered.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-1 py-3 text-xs text-[var(--as-muted-fg)]", children: labels?.noResults ?? "No matching tools" }) : /* @__PURE__ */ jsx("div", { role: "list", "aria-label": labels?.tools ?? "Tools", className: "flex flex-col gap-2", children: filtered.map((tool) => {
|
|
62
62
|
const open = openOverrides[tool.name] ?? defaultOpen;
|
|
63
63
|
const regionId = `${uid}-${tool.name}`;
|
|
64
64
|
const toggle = () => setOpenOverrides((current) => ({ ...current, [tool.name]: !open }));
|
|
@@ -80,11 +80,18 @@ var ChatToolsCatalog = React.forwardRef(
|
|
|
80
80
|
className: "flex w-full items-center gap-2 px-2.5 py-1.5 text-left focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]",
|
|
81
81
|
children: [
|
|
82
82
|
/* @__PURE__ */ jsx(Icon, { className: "size-3.5 shrink-0 text-[var(--as-muted-fg)]", "aria-hidden": true }),
|
|
83
|
-
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
83
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 break-words", children: [
|
|
84
84
|
/* @__PURE__ */ jsx("span", { className: "font-mono font-medium text-[var(--as-fg)]", children: tool.name }),
|
|
85
85
|
tool.title ? /* @__PURE__ */ jsx("span", { className: "ml-1.5 text-[var(--as-muted-fg)]", children: tool.title }) : null
|
|
86
86
|
] }),
|
|
87
|
-
tool.scope ? /* @__PURE__ */ jsx(
|
|
87
|
+
tool.scope ? /* @__PURE__ */ jsx(
|
|
88
|
+
"span",
|
|
89
|
+
{
|
|
90
|
+
title: tool.scope,
|
|
91
|
+
className: "max-w-[40%] shrink-0 truncate rounded-full bg-[var(--as-surface-raised)] px-1.5 py-0.5 text-[10px] uppercase tracking-wide text-[var(--as-muted-fg)]",
|
|
92
|
+
children: tool.scope
|
|
93
|
+
}
|
|
94
|
+
) : null,
|
|
88
95
|
/* @__PURE__ */ jsx(
|
|
89
96
|
ChevronDown,
|
|
90
97
|
{
|
|
@@ -145,5 +152,5 @@ var ChatToolsCatalog = React.forwardRef(
|
|
|
145
152
|
);
|
|
146
153
|
|
|
147
154
|
export { ChatToolsCatalog };
|
|
148
|
-
//# sourceMappingURL=chunk-
|
|
149
|
-
//# sourceMappingURL=chunk-
|
|
155
|
+
//# sourceMappingURL=chunk-TC4NQL3H.js.map
|
|
156
|
+
//# sourceMappingURL=chunk-TC4NQL3H.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/chat-tools-catalog/ChatToolsCatalog.tsx"],"names":["ChatToolsCatalog"],"mappings":"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","file":"chunk-TC4NQL3H.js","sourcesContent":["import * as React from 'react'\nimport { ChevronDown, Search, Wrench } from 'lucide-react'\nimport type { LucideIcon } from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\nimport { searchScore } from '../../lib/fuzzy'\n\nexport interface ChatToolCatalogArgument {\n name: string\n type?: string\n required?: boolean\n description?: string | null\n}\n\nexport interface ChatToolCatalogEntry {\n /** Stable tool identifier (rendered mono). */\n name: string\n /** Human title; falls back to `name`. */\n title?: string\n description?: string\n arguments?: ChatToolCatalogArgument[]\n example?: string | null\n response?: string | null\n scope?: string | null\n}\n\nexport interface ChatToolsCatalogLabels {\n /** Accessible name of the tool list. */\n tools: string\n search: string\n searchPlaceholder: string\n arguments: string\n response: string\n required: string\n optional: string\n empty: string\n noResults: string\n}\n\nexport interface ChatToolsCatalogProps {\n tools: ChatToolCatalogEntry[]\n searchable?: boolean\n /** Expand every entry's details initially (uncontrolled per entry after that). */\n defaultOpen?: boolean\n labels?: Partial<ChatToolsCatalogLabels>\n icon?: LucideIcon\n className?: string\n}\n\n/**\n * Catalog of the tools an assistant can use (study's `ToolsDialog` body,\n * generalized): searchable disclosure cards with description, argument\n * list, example and response shape. Presentational only — fetching and\n * the surrounding modal/popover stay app-side.\n */\nexport const ChatToolsCatalog = React.forwardRef<HTMLDivElement, ChatToolsCatalogProps>(\n function ChatToolsCatalog(\n {\n tools,\n searchable = true,\n defaultOpen = false,\n labels,\n icon: Icon = Wrench,\n className,\n },\n ref,\n ) {\n const uid = React.useId()\n const [query, setQuery] = React.useState('')\n const [openOverrides, setOpenOverrides] = React.useState<Record<string, boolean>>({})\n\n const filtered = React.useMemo(() => {\n const trimmed = query.trim()\n if (trimmed === '') {\n return tools\n }\n return tools\n .map((tool) => ({\n tool,\n score: Math.max(\n searchScore(trimmed, tool.title ?? tool.name) ?? -1,\n searchScore(trimmed, tool.name) ?? -1,\n searchScore(trimmed, tool.description ?? '') ?? -1,\n ),\n }))\n .filter((entry) => entry.score >= 0)\n .sort((a, b) => b.score - a.score)\n .map((entry) => entry.tool)\n }, [tools, query])\n\n return (\n <div\n ref={ref}\n data-as=\"chat-tools-catalog\"\n className={cn('flex min-h-0 w-full flex-col gap-2', className)}\n >\n {searchable ? (\n <div className=\"relative shrink-0\">\n <Search\n className=\"pointer-events-none absolute start-2 top-1/2 size-3.5 -translate-y-1/2 text-[var(--as-muted-fg)]\"\n aria-hidden\n />\n <input\n type=\"search\"\n role=\"searchbox\"\n value={query}\n aria-label={labels?.search ?? 'Search tools'}\n placeholder={labels?.searchPlaceholder ?? 'Search…'}\n onChange={(event) => setQuery(event.target.value)}\n className=\"w-full rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] py-1.5 pe-2 ps-8 text-xs text-[var(--as-fg)] placeholder:text-[var(--as-muted-fg)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]\"\n />\n </div>\n ) : null}\n {tools.length === 0 ? (\n <p className=\"px-1 py-3 text-xs text-[var(--as-muted-fg)]\">\n {labels?.empty ?? 'No tools available'}\n </p>\n ) : filtered.length === 0 ? (\n <p className=\"px-1 py-3 text-xs text-[var(--as-muted-fg)]\">\n {labels?.noResults ?? 'No matching tools'}\n </p>\n ) : (\n <div role=\"list\" aria-label={labels?.tools ?? 'Tools'} className=\"flex flex-col gap-2\">\n {filtered.map((tool) => {\n const open = openOverrides[tool.name] ?? defaultOpen\n const regionId = `${uid}-${tool.name}`\n const toggle = () =>\n setOpenOverrides((current) => ({ ...current, [tool.name]: !open }))\n return (\n <div\n key={tool.name}\n role=\"listitem\"\n data-as=\"chat-tools-catalog-entry\"\n data-open={open || undefined}\n className=\"rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] text-xs\"\n >\n <button\n type=\"button\"\n aria-expanded={open}\n aria-controls={regionId}\n onClick={toggle}\n className=\"flex w-full items-center gap-2 px-2.5 py-1.5 text-left focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <Icon className=\"size-3.5 shrink-0 text-[var(--as-muted-fg)]\" aria-hidden />\n <span className=\"min-w-0 flex-1 break-words\">\n <span className=\"font-mono font-medium text-[var(--as-fg)]\">{tool.name}</span>\n {tool.title ? (\n <span className=\"ml-1.5 text-[var(--as-muted-fg)]\">{tool.title}</span>\n ) : null}\n </span>\n {tool.scope ? (\n <span\n title={tool.scope}\n className=\"max-w-[40%] shrink-0 truncate rounded-full bg-[var(--as-surface-raised)] px-1.5 py-0.5 text-[10px] uppercase tracking-wide text-[var(--as-muted-fg)]\"\n >\n {tool.scope}\n </span>\n ) : null}\n <ChevronDown\n className={cn(\n 'size-3.5 shrink-0 text-[var(--as-muted-fg)] transition-transform',\n open && 'rotate-180',\n )}\n aria-hidden\n />\n </button>\n {open ? (\n <div id={regionId} className=\"flex flex-col gap-2 border-t border-[var(--as-border)] px-2.5 py-2\">\n {tool.description ? (\n <p className=\"text-[var(--as-fg)]\">{tool.description}</p>\n ) : null}\n {tool.arguments && tool.arguments.length > 0 ? (\n <div>\n <p className=\"mb-1 font-medium uppercase tracking-wide text-[var(--as-muted-fg)]\">\n {labels?.arguments ?? 'Arguments'}\n </p>\n <ul className=\"flex flex-col gap-1.5\">\n {tool.arguments.map((argument) => (\n <li\n key={argument.name}\n className=\"rounded-[var(--as-radius-sm)] border border-[var(--as-border)] bg-[var(--as-surface-raised)] px-2 py-1.5\"\n >\n <div className=\"flex flex-wrap items-center gap-x-2 gap-y-1\">\n <span className=\"font-mono font-medium text-[var(--as-fg)]\">\n {argument.name}\n </span>\n {argument.type ? (\n <span className=\"rounded-full border border-[var(--as-border)] bg-[var(--as-surface)] px-1.5 py-px font-mono text-[10px] leading-4 text-[var(--as-muted-fg)]\">\n {argument.type}\n </span>\n ) : null}\n <span\n className={cn(\n 'text-[10px] font-medium uppercase tracking-wide',\n argument.required\n ? 'text-[var(--as-warning)]'\n : 'text-[var(--as-muted-fg)]',\n )}\n >\n {argument.required\n ? (labels?.required ?? 'required')\n : (labels?.optional ?? 'optional')}\n </span>\n </div>\n {argument.description ? (\n <p className=\"mt-0.5 leading-snug text-[var(--as-muted-fg)]\">\n {argument.description}\n </p>\n ) : null}\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n {tool.example ? (\n <pre className=\"max-h-40 overflow-auto whitespace-pre-wrap break-words rounded-[var(--as-radius-sm)] bg-[var(--as-surface-raised)] p-2 font-mono text-[11px] leading-relaxed\">\n {tool.example}\n </pre>\n ) : null}\n {tool.response ? (\n <div>\n <p className=\"mb-1 font-medium uppercase tracking-wide text-[var(--as-muted-fg)]\">\n {labels?.response ?? 'Response'}\n </p>\n <p className=\"text-[var(--as-fg)]\">{tool.response}</p>\n </div>\n ) : null}\n </div>\n ) : null}\n </div>\n )\n })}\n </div>\n )}\n </div>\n )\n },\n)\n"]}
|