@athenaintel/react 0.54.0 → 0.56.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.
- package/README.md +32 -0
- package/dist/agent-runtime/src/answer-label.cjs +8 -2
- package/dist/agent-runtime/src/answer-label.cjs.map +1 -1
- package/dist/agent-runtime/src/answer-label.d.ts +10 -4
- package/dist/agent-runtime/src/answer-label.js +8 -2
- package/dist/agent-runtime/src/answer-label.js.map +1 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs +6 -3
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs.map +1 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js +6 -3
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -1
- package/dist/agent-runtime/src/edit-command.cjs +42 -15
- package/dist/agent-runtime/src/edit-command.cjs.map +1 -1
- package/dist/agent-runtime/src/edit-command.d.ts +2 -0
- package/dist/agent-runtime/src/edit-command.js +43 -16
- package/dist/agent-runtime/src/edit-command.js.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs +12 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +21 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.js +12 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
- package/dist/agent-runtime/src/history-store.cjs +426 -0
- package/dist/agent-runtime/src/history-store.cjs.map +1 -0
- package/dist/agent-runtime/src/history-store.d.ts +282 -0
- package/dist/agent-runtime/src/history-store.js +426 -0
- package/dist/agent-runtime/src/history-store.js.map +1 -0
- package/dist/agent-runtime/src/index.d.ts +3 -2
- package/dist/agent-runtime/src/message-window.cjs +43 -5
- package/dist/agent-runtime/src/message-window.cjs.map +1 -1
- package/dist/agent-runtime/src/message-window.d.ts +26 -2
- package/dist/agent-runtime/src/message-window.js +44 -6
- package/dist/agent-runtime/src/message-window.js.map +1 -1
- package/dist/agent-runtime/src/offline-status.cjs.map +1 -1
- package/dist/agent-runtime/src/offline-status.d.ts +115 -5
- package/dist/agent-runtime/src/offline-status.js.map +1 -1
- package/dist/agent-runtime/src/runtime.d.ts +1 -0
- package/dist/agent-runtime/src/tool-metadata.cjs +8 -0
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.js +8 -0
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs +7 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.js +8 -2
- package/dist/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs +73 -14
- package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-window-sync.d.ts +2 -2
- package/dist/agent-runtime/src/use-deep-agent-window-sync.js +75 -16
- package/dist/agent-runtime/src/use-deep-agent-window-sync.js.map +1 -1
- package/dist/chat/super-grouping/CollapsibleGroup.cjs +1 -1
- package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
- package/dist/chat/super-grouping/CollapsibleGroup.d.ts +6 -5
- package/dist/chat/super-grouping/CollapsibleGroup.js +1 -1
- package/dist/chat/super-grouping/CollapsibleGroup.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.cjs +51 -43
- package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.js +51 -43
- package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +9 -4
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.js +9 -4
- package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.cjs +7 -4
- package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.d.ts +10 -1
- package/dist/chat/super-grouping/activity-timeline.js +7 -4
- package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
- package/dist/chat/super-grouping/earlier-steps-button.cjs +49 -0
- package/dist/chat/super-grouping/earlier-steps-button.cjs.map +1 -0
- package/dist/chat/super-grouping/earlier-steps-button.d.ts +11 -0
- package/dist/chat/super-grouping/earlier-steps-button.js +49 -0
- package/dist/chat/super-grouping/earlier-steps-button.js.map +1 -0
- package/dist/chat/super-grouping/toolkit-map.cjs +1 -0
- package/dist/chat/super-grouping/toolkit-map.cjs.map +1 -1
- package/dist/chat/super-grouping/toolkit-map.js +1 -0
- package/dist/chat/super-grouping/toolkit-map.js.map +1 -1
- package/dist/chat/super-grouping/use-turn-steps.cjs +28 -0
- package/dist/chat/super-grouping/use-turn-steps.cjs.map +1 -0
- package/dist/chat/super-grouping/use-turn-steps.d.ts +23 -0
- package/dist/chat/super-grouping/use-turn-steps.js +28 -0
- package/dist/chat/super-grouping/use-turn-steps.js.map +1 -0
- package/dist/chat-ui/statewire.cjs +6 -0
- package/dist/chat-ui/statewire.cjs.map +1 -1
- package/dist/chat-ui/statewire.d.ts +3 -1
- package/dist/chat-ui/statewire.js +7 -1
- package/dist/chat-ui/statewire.js.map +1 -1
- package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
- package/dist/chat-ui/thread/statewire-history-edge.d.ts +8 -0
- package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
- package/dist/collab/client.cjs +40 -1
- package/dist/collab/client.cjs.map +1 -1
- package/dist/collab/client.d.ts +17 -0
- package/dist/collab/client.js +40 -1
- package/dist/collab/client.js.map +1 -1
- package/dist/composer/QuoteContext.cjs +3 -3
- package/dist/composer/QuoteContext.cjs.map +1 -1
- package/dist/composer/QuoteContext.js +3 -3
- package/dist/composer/QuoteContext.js.map +1 -1
- package/dist/provider/AthenaProvider.cjs +13 -4
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.js +11 -2
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/provider/statewire-window-context.cjs +6 -0
- package/dist/provider/statewire-window-context.cjs.map +1 -1
- package/dist/provider/statewire-window-context.d.ts +9 -0
- package/dist/provider/statewire-window-context.js +6 -0
- package/dist/provider/statewire-window-context.js.map +1 -1
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.d.ts +6 -0
- package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/threads/sessions-query.cjs +2 -0
- package/dist/threads/sessions-query.cjs.map +1 -1
- package/dist/threads/sessions-query.js +2 -0
- package/dist/threads/sessions-query.js.map +1 -1
- package/package.json +1 -1
|
@@ -41,8 +41,9 @@ export interface CollapsibleGroupProps {
|
|
|
41
41
|
*/
|
|
42
42
|
forceOpen?: boolean;
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
44
|
+
* Keep the live group collapsed while its turn runs, so only its header's
|
|
45
|
+
* count moves as calls land (default). Pass `false` to open the last grouped
|
|
46
|
+
* block while the run is live and close it when the run settles.
|
|
46
47
|
*/
|
|
47
48
|
compactWhileRunning?: boolean;
|
|
48
49
|
/**
|
|
@@ -61,9 +62,9 @@ export interface CollapsibleGroupProps {
|
|
|
61
62
|
/**
|
|
62
63
|
* Per-toolkit collapsible block inside the grouped details panel — "Using
|
|
63
64
|
* Spreadsheet Toolkit · 4 tool calls" — used by the SDK, Olympus, and the
|
|
64
|
-
* Chrome extension.
|
|
65
|
-
*
|
|
66
|
-
* mounted block.
|
|
65
|
+
* Chrome extension. A live group stays collapsed and counts its calls up
|
|
66
|
+
* (unless `compactWhileRunning` is off); the user's toggle is remembered for
|
|
67
|
+
* the mounted block.
|
|
67
68
|
*
|
|
68
69
|
* The group's tool UIs (the tool calls `GroupedMessageParts` renders through
|
|
69
70
|
* `GroupToolUI`) mount the first time they are needed — the group opens, its
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollapsibleGroup.js","sources":["../../../src/chat/super-grouping/CollapsibleGroup.tsx"],"sourcesContent":["import { useAuiState } from '@assistant-ui/react';\nimport { ChevronDown, ChevronUp } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { createContext, useContext, useId, useMemo, useState } from 'react';\nimport { cn } from '../../lib/utils';\nimport { createToolBasedGroupingFunction, type GroupingFunction } from './grouping-function';\nimport { defaultGetToolGroupKey } from './toolkit-map';\n\n/**\n * Per-toolkit theme: the brand color that tints the group header, and an\n * optional icon URL a host serves (Olympus ships toolkit SVGs; the SDK does\n * not bundle images, so it tints only).\n */\nexport type ToolkitTheme = {\n /** Hex brand color for this toolkit. */\n color: string;\n /** Absolute or root-relative URL of the toolkit icon, when the host has one. */\n icon?: string;\n};\n\n/** Brand colors keyed by toolkit display name — the group keys the grouping function emits. */\nexport const TOOLKIT_THEMES: Record<string, ToolkitTheme> = {\n Web: { color: '#7BCCFA' },\n Document: { color: '#4586F9' },\n 'Document (Word)': { color: '#4586F9' },\n Notebook: { color: '#FFAB00' },\n Python: { color: '#00A76F' },\n Spreadsheet: { color: '#00A76F' },\n Email: { color: '#B584FF' },\n AOP: { color: '#336DFF' },\n App: { color: '#7336F5' },\n Presentation: { color: '#F56B36' },\n 'User Interface': { color: '#7336F5' },\n Canvas: { color: '#002542' },\n Computer: { color: '#3E0042' },\n Database: { color: '#7336F5' },\n 'Chrome Browser': { color: '#4285F4' },\n};\n\nexport const DEFAULT_TOOLKIT_THEME: ToolkitTheme = { color: '#919EAB' };\n\nconst DEFAULT_GROUPING = createToolBasedGroupingFunction(defaultGetToolGroupKey);\n\n/**\n * The grouping in force for the message being rendered. `SuperGroupingCard`\n * provides it so each `CollapsibleGroup` can tell whether it is the last\n * grouped block (the one that opens by default while the run is live) without\n * being handed the function as a prop through `GroupedMessageParts`, and\n * whether the card keeps its tool UIs mounted while hidden (`mountHidden`:\n * its turn is active, or a deep link targets it).\n */\nconst SuperGroupingContext = createContext<{\n groupingFunction: GroupingFunction;\n mountHidden?: boolean;\n} | null>(null);\n\nexport const SuperGroupingProvider = SuperGroupingContext.Provider;\n\n/** Whether the group a tool UI renders in has mounted its tool UIs; outside a group, always. */\nconst GroupToolUIsMountedContext = createContext(true);\n\n/**\n * A tool call's UI inside a `CollapsibleGroup`: rendered once the group first\n * needs its tool UIs (see `CollapsibleGroup`). `GroupedMessageParts` renders\n * every tool call through it.\n */\nexport function GroupToolUI({ children }: { children: ReactNode }) {\n return useContext(GroupToolUIsMountedContext) ? <>{children}</> : null;\n}\n\nexport interface CollapsibleGroupProps {\n /** Group key from the grouping function (toolkit display name); `undefined` for ungrouped parts. */\n groupKey: string | undefined;\n /** Indices of the parts belonging to this group. */\n indices: number[];\n children?: ReactNode;\n /** Host toolkit themes (colors, icons), merged over the built-in colors. */\n themes?: Record<string, ToolkitTheme>;\n /**\n * Keep the group open regardless of the run state — a host rule such as\n * \"an unsubmitted email draft stays visible\". The user's own toggle still\n * wins once used.\n */\n forceOpen?: boolean;\n /**\n * Do not open the live group by default (screenshot-heavy browser-control\n * runs hold hundreds of actions); the user can still expand it.\n */\n compactWhileRunning?: boolean;\n /**\n * Mount the tool UIs while collapsed (hidden), so a host that needs to find\n * one — a deep link into one of its tool calls — can. The card a group\n * renders in asks the same while its turn is active or its `mountDetails` is\n * set.\n */\n mountHidden?: boolean;\n /** Extra header controls, rendered as siblings of the toggle (never nested buttons). */\n headerActions?: ReactNode;\n /** The grouping used to find the last grouped block; defaults to the card's, then the SDK's. */\n groupingFunction?: GroupingFunction;\n className?: string;\n}\n\n/**\n * Per-toolkit collapsible block inside the grouped details panel — \"Using\n * Spreadsheet Toolkit · 4 tool calls\" — used by the SDK, Olympus, and the\n * Chrome extension. The last grouped block opens by default while the message\n * is running and settles closed; the user's toggle is remembered for the\n * mounted block.\n *\n * The group's tool UIs (the tool calls `GroupedMessageParts` renders through\n * `GroupToolUI`) mount the first time they are needed — the group opens, its\n * turn is running (live tool UIs run their effects), or a host asks\n * (`mountHidden`) — and stay mounted after. A finished turn's collapsed groups\n * mount none of their tool UIs, which a long run holds hundreds of. The rest\n * of the body renders from the start: the agent's text between the calls is\n * part of the message that selections, in-page find and links into the\n * message count.\n *\n * Selector discipline: one raw `s.message.content` read; every per-group\n * derivation (grouping, counts) runs in `useMemo` off it, so the grouping\n * pass happens once per content change instead of once per selector pass.\n */\nexport const CollapsibleGroup = ({\n groupKey,\n indices,\n children,\n themes,\n forceOpen = false,\n compactWhileRunning = false,\n mountHidden = false,\n headerActions,\n groupingFunction,\n className,\n}: CollapsibleGroupProps) => {\n const panelId = useId();\n const isMessageRunning = useAuiState((s) => s.message.status?.type === 'running');\n const messageContent = useAuiState((s) =>\n s.message.role === 'assistant' ? s.message.content : undefined,\n );\n const superGrouping = useContext(SuperGroupingContext);\n const grouping = groupingFunction ?? superGrouping?.groupingFunction ?? DEFAULT_GROUPING;\n\n const lastIndex = indices.at(-1);\n const isLastGroup = useMemo(() => {\n if (!messageContent) return false;\n const lastGroup = grouping(messageContent)\n .filter((group) => group.indices.length > 1)\n .at(-1);\n return lastGroup?.indices.at(-1) === lastIndex;\n }, [messageContent, grouping, lastIndex]);\n\n const toolCallCount = useMemo(\n () =>\n messageContent\n ? indices.reduce(\n (count, index) => (messageContent[index]?.type === 'tool-call' ? count + 1 : count),\n 0,\n )\n : 0,\n [messageContent, indices],\n );\n\n const theme = useMemo<ToolkitTheme>(\n () => (groupKey ? { ...TOOLKIT_THEMES, ...themes }[groupKey] ?? DEFAULT_TOOLKIT_THEME : DEFAULT_TOOLKIT_THEME),\n [groupKey, themes],\n );\n\n const [userOpened, setOpen] = useState<boolean>();\n const autoOpen = isLastGroup && isMessageRunning && !compactWhileRunning;\n const open = userOpened ?? (autoOpen || forceOpen);\n\n const mountToolUIs =\n open || isMessageRunning || mountHidden || superGrouping?.mountHidden === true;\n const [toolUIsMounted, setToolUIsMounted] = useState(mountToolUIs);\n // Adjusting state during render is React's sanctioned derived-state pattern.\n if (mountToolUIs && !toolUIsMounted) setToolUIsMounted(true);\n\n if (!groupKey || indices.length <= 1) return <>{children}</>;\n\n const toggle = () => setOpen(!open);\n\n return (\n <div\n data-slot=\"collapsible-group\"\n data-group-key={groupKey}\n className={cn('my-4 rounded-2xl border shadow-sm', className)}\n style={{\n borderColor: `${theme.color}33`,\n background: `linear-gradient(to right, ${theme.color}0d, transparent, ${theme.color}0d)`,\n }}\n >\n <div className=\"flex w-full items-center rounded-2xl\">\n <button\n type=\"button\"\n onClick={toggle}\n aria-expanded={open}\n aria-controls={panelId}\n className=\"flex min-w-0 flex-1 items-center justify-between gap-3 rounded-2xl px-5 py-3 text-left transition-colors hover:bg-black/5 dark:hover:bg-white/5\"\n >\n <span className=\"flex min-w-0 items-center gap-3 text-foreground/90\">\n {theme.icon ? (\n <img src={theme.icon} alt=\"\" aria-hidden=\"true\" className=\"size-5 shrink-0\" />\n ) : (\n <span\n className=\"inline-block size-2 shrink-0 rounded-full\"\n style={{ backgroundColor: theme.color }}\n aria-hidden=\"true\"\n />\n )}\n <span className=\"truncate text-sm font-semibold\">\n {isMessageRunning ? 'Using ' : 'Used '}\n {groupKey} Toolkit\n </span>\n </span>\n <span className=\"shrink-0 text-xs font-medium text-muted-foreground\">\n {toolCallCount} tool {toolCallCount === 1 ? 'call' : 'calls'}\n </span>\n </button>\n <div className=\"flex shrink-0 items-center gap-1 pr-3 pl-1\">\n {headerActions}\n <button\n type=\"button\"\n onClick={toggle}\n aria-label={open ? 'Collapse toolkit group' : 'Expand toolkit group'}\n aria-expanded={open}\n aria-controls={panelId}\n className=\"flex items-center justify-center rounded-md p-1 text-muted-foreground transition-colors hover:bg-black/5 dark:hover:bg-white/5\"\n >\n {open ? <ChevronUp size={16} /> : <ChevronDown size={16} />}\n </button>\n </div>\n </div>\n\n <div\n id={panelId}\n className={cn(\n 'grid overflow-hidden border-t transition-[grid-template-rows] duration-200 ease-in-out motion-reduce:transition-none',\n open ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',\n )}\n style={{ borderColor: `${theme.color}33` }}\n >\n <div className=\"overflow-hidden\">\n <GroupToolUIsMountedContext.Provider value={toolUIsMounted}>\n <div className=\"flex flex-col gap-2 px-5 py-4\">{children}</div>\n </GroupToolUIsMountedContext.Provider>\n </div>\n </div>\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CollapsibleGroup.js","sources":["../../../src/chat/super-grouping/CollapsibleGroup.tsx"],"sourcesContent":["import { useAuiState } from '@assistant-ui/react';\nimport { ChevronDown, ChevronUp } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { createContext, useContext, useId, useMemo, useState } from 'react';\nimport { cn } from '../../lib/utils';\nimport { createToolBasedGroupingFunction, type GroupingFunction } from './grouping-function';\nimport { defaultGetToolGroupKey } from './toolkit-map';\n\n/**\n * Per-toolkit theme: the brand color that tints the group header, and an\n * optional icon URL a host serves (Olympus ships toolkit SVGs; the SDK does\n * not bundle images, so it tints only).\n */\nexport type ToolkitTheme = {\n /** Hex brand color for this toolkit. */\n color: string;\n /** Absolute or root-relative URL of the toolkit icon, when the host has one. */\n icon?: string;\n};\n\n/** Brand colors keyed by toolkit display name — the group keys the grouping function emits. */\nexport const TOOLKIT_THEMES: Record<string, ToolkitTheme> = {\n Web: { color: '#7BCCFA' },\n Document: { color: '#4586F9' },\n 'Document (Word)': { color: '#4586F9' },\n Notebook: { color: '#FFAB00' },\n Python: { color: '#00A76F' },\n Spreadsheet: { color: '#00A76F' },\n Email: { color: '#B584FF' },\n AOP: { color: '#336DFF' },\n App: { color: '#7336F5' },\n Presentation: { color: '#F56B36' },\n 'User Interface': { color: '#7336F5' },\n Canvas: { color: '#002542' },\n Computer: { color: '#3E0042' },\n Database: { color: '#7336F5' },\n 'Chrome Browser': { color: '#4285F4' },\n};\n\nexport const DEFAULT_TOOLKIT_THEME: ToolkitTheme = { color: '#919EAB' };\n\nconst DEFAULT_GROUPING = createToolBasedGroupingFunction(defaultGetToolGroupKey);\n\n/**\n * The grouping in force for the message being rendered. `SuperGroupingCard`\n * provides it so each `CollapsibleGroup` can tell whether it is the last\n * grouped block (the one that opens while the run is live, when a host turns\n * `compactWhileRunning` off) without\n * being handed the function as a prop through `GroupedMessageParts`, and\n * whether the card keeps its tool UIs mounted while hidden (`mountHidden`:\n * its turn is active, or a deep link targets it).\n */\nconst SuperGroupingContext = createContext<{\n groupingFunction: GroupingFunction;\n mountHidden?: boolean;\n} | null>(null);\n\nexport const SuperGroupingProvider = SuperGroupingContext.Provider;\n\n/** Whether the group a tool UI renders in has mounted its tool UIs; outside a group, always. */\nconst GroupToolUIsMountedContext = createContext(true);\n\n/**\n * A tool call's UI inside a `CollapsibleGroup`: rendered once the group first\n * needs its tool UIs (see `CollapsibleGroup`). `GroupedMessageParts` renders\n * every tool call through it.\n */\nexport function GroupToolUI({ children }: { children: ReactNode }) {\n return useContext(GroupToolUIsMountedContext) ? <>{children}</> : null;\n}\n\nexport interface CollapsibleGroupProps {\n /** Group key from the grouping function (toolkit display name); `undefined` for ungrouped parts. */\n groupKey: string | undefined;\n /** Indices of the parts belonging to this group. */\n indices: number[];\n children?: ReactNode;\n /** Host toolkit themes (colors, icons), merged over the built-in colors. */\n themes?: Record<string, ToolkitTheme>;\n /**\n * Keep the group open regardless of the run state — a host rule such as\n * \"an unsubmitted email draft stays visible\". The user's own toggle still\n * wins once used.\n */\n forceOpen?: boolean;\n /**\n * Keep the live group collapsed while its turn runs, so only its header's\n * count moves as calls land (default). Pass `false` to open the last grouped\n * block while the run is live and close it when the run settles.\n */\n compactWhileRunning?: boolean;\n /**\n * Mount the tool UIs while collapsed (hidden), so a host that needs to find\n * one — a deep link into one of its tool calls — can. The card a group\n * renders in asks the same while its turn is active or its `mountDetails` is\n * set.\n */\n mountHidden?: boolean;\n /** Extra header controls, rendered as siblings of the toggle (never nested buttons). */\n headerActions?: ReactNode;\n /** The grouping used to find the last grouped block; defaults to the card's, then the SDK's. */\n groupingFunction?: GroupingFunction;\n className?: string;\n}\n\n/**\n * Per-toolkit collapsible block inside the grouped details panel — \"Using\n * Spreadsheet Toolkit · 4 tool calls\" — used by the SDK, Olympus, and the\n * Chrome extension. A live group stays collapsed and counts its calls up\n * (unless `compactWhileRunning` is off); the user's toggle is remembered for\n * the mounted block.\n *\n * The group's tool UIs (the tool calls `GroupedMessageParts` renders through\n * `GroupToolUI`) mount the first time they are needed — the group opens, its\n * turn is running (live tool UIs run their effects), or a host asks\n * (`mountHidden`) — and stay mounted after. A finished turn's collapsed groups\n * mount none of their tool UIs, which a long run holds hundreds of. The rest\n * of the body renders from the start: the agent's text between the calls is\n * part of the message that selections, in-page find and links into the\n * message count.\n *\n * Selector discipline: one raw `s.message.content` read; every per-group\n * derivation (grouping, counts) runs in `useMemo` off it, so the grouping\n * pass happens once per content change instead of once per selector pass.\n */\nexport const CollapsibleGroup = ({\n groupKey,\n indices,\n children,\n themes,\n forceOpen = false,\n compactWhileRunning = true,\n mountHidden = false,\n headerActions,\n groupingFunction,\n className,\n}: CollapsibleGroupProps) => {\n const panelId = useId();\n const isMessageRunning = useAuiState((s) => s.message.status?.type === 'running');\n const messageContent = useAuiState((s) =>\n s.message.role === 'assistant' ? s.message.content : undefined,\n );\n const superGrouping = useContext(SuperGroupingContext);\n const grouping = groupingFunction ?? superGrouping?.groupingFunction ?? DEFAULT_GROUPING;\n\n const lastIndex = indices.at(-1);\n const isLastGroup = useMemo(() => {\n if (!messageContent) return false;\n const lastGroup = grouping(messageContent)\n .filter((group) => group.indices.length > 1)\n .at(-1);\n return lastGroup?.indices.at(-1) === lastIndex;\n }, [messageContent, grouping, lastIndex]);\n\n const toolCallCount = useMemo(\n () =>\n messageContent\n ? indices.reduce(\n (count, index) => (messageContent[index]?.type === 'tool-call' ? count + 1 : count),\n 0,\n )\n : 0,\n [messageContent, indices],\n );\n\n const theme = useMemo<ToolkitTheme>(\n () => (groupKey ? { ...TOOLKIT_THEMES, ...themes }[groupKey] ?? DEFAULT_TOOLKIT_THEME : DEFAULT_TOOLKIT_THEME),\n [groupKey, themes],\n );\n\n const [userOpened, setOpen] = useState<boolean>();\n const autoOpen = isLastGroup && isMessageRunning && !compactWhileRunning;\n const open = userOpened ?? (autoOpen || forceOpen);\n\n const mountToolUIs =\n open || isMessageRunning || mountHidden || superGrouping?.mountHidden === true;\n const [toolUIsMounted, setToolUIsMounted] = useState(mountToolUIs);\n // Adjusting state during render is React's sanctioned derived-state pattern.\n if (mountToolUIs && !toolUIsMounted) setToolUIsMounted(true);\n\n if (!groupKey || indices.length <= 1) return <>{children}</>;\n\n const toggle = () => setOpen(!open);\n\n return (\n <div\n data-slot=\"collapsible-group\"\n data-group-key={groupKey}\n className={cn('my-4 rounded-2xl border shadow-sm', className)}\n style={{\n borderColor: `${theme.color}33`,\n background: `linear-gradient(to right, ${theme.color}0d, transparent, ${theme.color}0d)`,\n }}\n >\n <div className=\"flex w-full items-center rounded-2xl\">\n <button\n type=\"button\"\n onClick={toggle}\n aria-expanded={open}\n aria-controls={panelId}\n className=\"flex min-w-0 flex-1 items-center justify-between gap-3 rounded-2xl px-5 py-3 text-left transition-colors hover:bg-black/5 dark:hover:bg-white/5\"\n >\n <span className=\"flex min-w-0 items-center gap-3 text-foreground/90\">\n {theme.icon ? (\n <img src={theme.icon} alt=\"\" aria-hidden=\"true\" className=\"size-5 shrink-0\" />\n ) : (\n <span\n className=\"inline-block size-2 shrink-0 rounded-full\"\n style={{ backgroundColor: theme.color }}\n aria-hidden=\"true\"\n />\n )}\n <span className=\"truncate text-sm font-semibold\">\n {isMessageRunning ? 'Using ' : 'Used '}\n {groupKey} Toolkit\n </span>\n </span>\n <span className=\"shrink-0 text-xs font-medium text-muted-foreground\">\n {toolCallCount} tool {toolCallCount === 1 ? 'call' : 'calls'}\n </span>\n </button>\n <div className=\"flex shrink-0 items-center gap-1 pr-3 pl-1\">\n {headerActions}\n <button\n type=\"button\"\n onClick={toggle}\n aria-label={open ? 'Collapse toolkit group' : 'Expand toolkit group'}\n aria-expanded={open}\n aria-controls={panelId}\n className=\"flex items-center justify-center rounded-md p-1 text-muted-foreground transition-colors hover:bg-black/5 dark:hover:bg-white/5\"\n >\n {open ? <ChevronUp size={16} /> : <ChevronDown size={16} />}\n </button>\n </div>\n </div>\n\n <div\n id={panelId}\n className={cn(\n 'grid overflow-hidden border-t transition-[grid-template-rows] duration-200 ease-in-out motion-reduce:transition-none',\n open ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',\n )}\n style={{ borderColor: `${theme.color}33` }}\n >\n <div className=\"overflow-hidden\">\n <GroupToolUIsMountedContext.Provider value={toolUIsMounted}>\n <div className=\"flex flex-col gap-2 px-5 py-4\">{children}</div>\n </GroupToolUIsMountedContext.Provider>\n </div>\n </div>\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,7 @@ const timelineStep = require("./timeline-step.cjs");
|
|
|
16
16
|
const toolkitMap = require("./toolkit-map.cjs");
|
|
17
17
|
const toolPartPlacement = require("./tool-part-placement.cjs");
|
|
18
18
|
const useEarlierStepsUnloaded = require("./use-earlier-steps-unloaded.cjs");
|
|
19
|
+
const useTurnSteps = require("./use-turn-steps.cjs");
|
|
19
20
|
const cnfast = require("cnfast");
|
|
20
21
|
const DEFAULT_MAX_VISIBLE_STEPS = 3;
|
|
21
22
|
const MAX_REMEMBERED_EXPANSIONS = 200;
|
|
@@ -128,6 +129,9 @@ const SuperGroupingCard = require$$0.memo(function SuperGroupingCard2({
|
|
|
128
129
|
}) {
|
|
129
130
|
const messageId = react.useAuiState((s) => s.message.id);
|
|
130
131
|
const earlierStepsUnloaded = useEarlierStepsUnloaded.useEarlierStepsUnloaded();
|
|
132
|
+
const stepsMarker = useTurnSteps.useTurnStepsMarker();
|
|
133
|
+
const TurnStepsControl = useTurnSteps.useTurnStepsControl();
|
|
134
|
+
const hiddenSteps = stepsMarker ? { tools: stepsMarker.hiddenTools, delegations: stepsMarker.hiddenDelegations } : void 0;
|
|
131
135
|
const [selectActivityContent] = require$$0.useState(createActivityContentSelector);
|
|
132
136
|
const messageContent = react.useAuiState(selectActivityContent);
|
|
133
137
|
const messageStatus = react.useAuiState((s) => s.message.status);
|
|
@@ -143,9 +147,10 @@ const SuperGroupingCard = require$$0.memo(function SuperGroupingCard2({
|
|
|
143
147
|
() => activityTimeline.resolveActivityPhase(messageStatus, timeline, { waitingForInput }),
|
|
144
148
|
[messageStatus, timeline, waitingForInput]
|
|
145
149
|
);
|
|
146
|
-
const toolCount = activityTimeline.countActivityTools(timeline);
|
|
150
|
+
const toolCount = activityTimeline.countActivityTools(timeline) + ((hiddenSteps == null ? void 0 : hiddenSteps.tools) ?? 0);
|
|
151
|
+
const expansionBase = expansionKeyProp ?? (stepsMarker ? `turn:${stepsMarker.turn}` : messageId);
|
|
147
152
|
const { expanded, toggleExpanded } = useActivityExpansion({
|
|
148
|
-
expansionKey:
|
|
153
|
+
expansionKey: expansionBase,
|
|
149
154
|
phase,
|
|
150
155
|
expandWhileWaiting
|
|
151
156
|
});
|
|
@@ -153,7 +158,7 @@ const SuperGroupingCard = require$$0.memo(function SuperGroupingCard2({
|
|
|
153
158
|
const detailsPanelId = `aui-sg-details-${generatedId}`;
|
|
154
159
|
const statusId = `aui-sg-status-${generatedId}`;
|
|
155
160
|
const { expanded: detailsExpanded, toggleExpanded: toggleDetails } = useActivityExpansion({
|
|
156
|
-
expansionKey: `${
|
|
161
|
+
expansionKey: `${expansionBase}:details`,
|
|
157
162
|
phase,
|
|
158
163
|
expandWhileWaiting
|
|
159
164
|
});
|
|
@@ -199,7 +204,7 @@ const SuperGroupingCard = require$$0.memo(function SuperGroupingCard2({
|
|
|
199
204
|
}),
|
|
200
205
|
[toolUIs, ToolFallbackComponent, TextComponent, ReasoningComponent, GroupComponent]
|
|
201
206
|
);
|
|
202
|
-
const hasActivity = timeline.length > 0 || phase !== "complete" || earlierStepsUnloaded;
|
|
207
|
+
const hasActivity = timeline.length > 0 || phase !== "complete" || earlierStepsUnloaded || ((stepsMarker == null ? void 0 : stepsMarker.hiddenSteps) ?? 0) > 0;
|
|
203
208
|
if (!hasActivity) return null;
|
|
204
209
|
const detailsMounted = isActive || mountDetails || expanded && detailsExpanded;
|
|
205
210
|
const activeSteps = steps.filter((step) => step.state === "running");
|
|
@@ -208,7 +213,7 @@ const SuperGroupingCard = require$$0.memo(function SuperGroupingCard2({
|
|
|
208
213
|
currentStep.verb,
|
|
209
214
|
currentStep.chip,
|
|
210
215
|
activeSteps.length > 1 ? `${activeSteps.length} in progress` : null
|
|
211
|
-
].filter(Boolean).join(" · ") : steps.length > 0 ? "Preparing response" : "Thinking" : activityTimeline.getActivitySummary(timeline, { earlierStepsUnloaded });
|
|
216
|
+
].filter(Boolean).join(" · ") : steps.length > 0 ? "Preparing response" : "Thinking" : activityTimeline.getActivitySummary(timeline, { earlierStepsUnloaded, hiddenSteps });
|
|
212
217
|
const label = [latestStatus, ...isActive ? [] : summaryDetails ?? []].join(" · ");
|
|
213
218
|
const renderStepRow = stepRowParts.size > 0 ? (step) => {
|
|
214
219
|
const index = step.kind === "tool" ? stepRowParts.get(step.id) : void 0;
|
|
@@ -224,7 +229,7 @@ const SuperGroupingCard = require$$0.memo(function SuperGroupingCard2({
|
|
|
224
229
|
"aria-busy": phase === "running" ? "true" : "false",
|
|
225
230
|
"aria-describedby": statusId,
|
|
226
231
|
children: [
|
|
227
|
-
/* @__PURE__ */ jsxRuntime.
|
|
232
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
228
233
|
ToolTimeline.ToolTimeline,
|
|
229
234
|
{
|
|
230
235
|
steps,
|
|
@@ -239,44 +244,47 @@ const SuperGroupingCard = require$$0.memo(function SuperGroupingCard2({
|
|
|
239
244
|
renderStepIcon,
|
|
240
245
|
renderStepRow,
|
|
241
246
|
showSourceFavicons,
|
|
242
|
-
children:
|
|
243
|
-
/* @__PURE__ */ jsxRuntime.
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
"
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
247
|
+
children: [
|
|
248
|
+
stepsMarker && stepsMarker.hiddenSteps > 0 && TurnStepsControl ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 pl-5", children: /* @__PURE__ */ jsxRuntime.jsx(TurnStepsControl, { marker: stepsMarker, autoLoad: expanded }) }) : null,
|
|
249
|
+
hasDetails ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 pl-5", children: [
|
|
250
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
251
|
+
"button",
|
|
252
|
+
{
|
|
253
|
+
type: "button",
|
|
254
|
+
onClick: toggleDetails,
|
|
255
|
+
"aria-expanded": detailsExpanded,
|
|
256
|
+
"aria-controls": detailsPanelId,
|
|
257
|
+
className: "flex items-center gap-1.5 rounded py-1 text-xs text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
258
|
+
children: [
|
|
259
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
260
|
+
lucideReact.ChevronRight,
|
|
261
|
+
{
|
|
262
|
+
"aria-hidden": "true",
|
|
263
|
+
className: cnfast.cn(
|
|
264
|
+
"size-3 transition-transform motion-reduce:transition-none",
|
|
265
|
+
detailsExpanded && "rotate-90"
|
|
266
|
+
)
|
|
267
|
+
}
|
|
268
|
+
),
|
|
269
|
+
detailsExpanded ? "Hide tool details" : "Show tool details"
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
),
|
|
273
|
+
detailsMounted ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
274
|
+
"section",
|
|
275
|
+
{
|
|
276
|
+
id: detailsPanelId,
|
|
277
|
+
"aria-label": "Run details",
|
|
278
|
+
hidden: !expanded || !detailsExpanded,
|
|
279
|
+
className: cnfast.cn(
|
|
280
|
+
"min-w-0 overflow-hidden border-l border-border/60 py-2 pl-3",
|
|
281
|
+
classNames == null ? void 0 : classNames.details
|
|
261
282
|
),
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
"section",
|
|
268
|
-
{
|
|
269
|
-
id: detailsPanelId,
|
|
270
|
-
"aria-label": "Run details",
|
|
271
|
-
hidden: !expanded || !detailsExpanded,
|
|
272
|
-
className: cnfast.cn(
|
|
273
|
-
"min-w-0 overflow-hidden border-l border-border/60 py-2 pl-3",
|
|
274
|
-
classNames == null ? void 0 : classNames.details
|
|
275
|
-
),
|
|
276
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cnfast.cn("flex flex-col gap-2", classNames == null ? void 0 : classNames.detailsParts), children: /* @__PURE__ */ jsxRuntime.jsx(CollapsibleGroup.SuperGroupingProvider, { value: groupingContext, children: /* @__PURE__ */ jsxRuntime.jsx(toolPartPlacement.ToolPartPlacementProvider, { value: null, children: /* @__PURE__ */ jsxRuntime.jsx(GroupedMessageParts.GroupedMessageParts, { groupingFunction: grouping, components }) }) }) })
|
|
277
|
-
}
|
|
278
|
-
) : null
|
|
279
|
-
] }) : null
|
|
283
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cnfast.cn("flex flex-col gap-2", classNames == null ? void 0 : classNames.detailsParts), children: /* @__PURE__ */ jsxRuntime.jsx(CollapsibleGroup.SuperGroupingProvider, { value: groupingContext, children: /* @__PURE__ */ jsxRuntime.jsx(toolPartPlacement.ToolPartPlacementProvider, { value: null, children: /* @__PURE__ */ jsxRuntime.jsx(GroupedMessageParts.GroupedMessageParts, { groupingFunction: grouping, components }) }) }) })
|
|
284
|
+
}
|
|
285
|
+
) : null
|
|
286
|
+
] }) : null
|
|
287
|
+
]
|
|
280
288
|
}
|
|
281
289
|
),
|
|
282
290
|
inlineParts.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SuperGroupingCard.cjs","sources":["../../../src/chat/super-grouping/SuperGroupingCard.tsx"],"sourcesContent":["'use client';\n\nimport type {\n AssistantState,\n ReasoningMessagePartComponent,\n TextMessagePartComponent,\n ThreadAssistantMessagePart,\n ToolCallMessagePart,\n ToolCallMessagePartComponent,\n ToolCallMessagePartProps,\n} from '@assistant-ui/react';\nimport { MessagePrimitive, useAuiState } from '@assistant-ui/react';\nimport { ChevronRight } from 'lucide-react';\nimport { type ComponentType, memo, type ReactNode, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { cn } from '../../lib/utils';\nimport { isSdkInlineTool } from '../../tools/inline-tools';\nimport { ToolFallback } from '../../tools/tool-fallback';\nimport { collectAssetTitles } from '../../tools/tool-summary';\nimport {\n type ActivityItem,\n type ActivityPhase,\n buildActivityTimeline,\n countActivityTools,\n excludeFinalTextFromGroups,\n excludePartsFromGroups,\n getActivitySummary,\n getFinalTextParts,\n resolveActivityPhase,\n} from './activity-timeline';\nimport { CollapsibleGroup, type CollapsibleGroupProps, SuperGroupingProvider } from './CollapsibleGroup';\nimport { GroupedMessageParts } from './GroupedMessageParts';\nimport { createToolBasedGroupingFunction, type GroupingFunction, isGroupedToolCallPart } from './grouping-function';\nimport { ToolTimeline } from './ToolTimeline';\nimport { type TimelineStep, toTimelineStep } from './timeline-step';\nimport { defaultGetToolGroupKey, type GetToolGroupKey } from './toolkit-map';\nimport { ToolPartPlacementProvider } from './tool-part-placement';\nimport { useEarlierStepsUnloaded } from './use-earlier-steps-unloaded';\n\nconst DEFAULT_MAX_VISIBLE_STEPS = 3;\nconst MAX_REMEMBERED_EXPANSIONS = 200;\nconst EMPTY_TIMELINE: ActivityItem[] = [];\nconst EMPTY_CONTENT: readonly ThreadAssistantMessagePart[] = [];\nconst NO_STEP_ROW_TOOLS = (): boolean => false;\n\n/**\n * Whether `next` differs from `previous` only in the words of its last part, a text or reasoning\n * part that is still being written: same length, every earlier part the identical object, and the\n * last parts of the same kind.\n */\nfunction onlyLastPartGrew({\n previous,\n next,\n}: {\n previous: readonly ThreadAssistantMessagePart[];\n next: readonly ThreadAssistantMessagePart[];\n}): boolean {\n if (previous === next) return true;\n if (previous.length === 0 || previous.length !== next.length) return false;\n const lastIndex = next.length - 1;\n const kind = next[lastIndex]?.type;\n if ((kind !== 'text' && kind !== 'reasoning') || previous[lastIndex]?.type !== kind) return false;\n for (let index = 0; index < lastIndex; index += 1) {\n if (previous[index] !== next[index]) return false;\n }\n return true;\n}\n\n/**\n * The card's read of its message's content: the content itself, except that while the message is\n * generating it keeps the previous array when only the last text or reasoning part grew. The card\n * builds its steps from tool calls, their results and reasoning steps, never from those words (the\n * answer renders below it, `SuperGroupingFinalText`), and the turn being generated changes its last\n * part on every streamed token; earlier parts keep their objects across a token (the runtime's\n * conversion cache), so the card re-renders when a step changes, not per token. Any other change,\n * and the run ending, hand over the current content.\n */\nfunction createActivityContentSelector(): (\n state: AssistantState,\n) => readonly ThreadAssistantMessagePart[] {\n let last: readonly ThreadAssistantMessagePart[] = EMPTY_CONTENT;\n return (state) => {\n const message = state.message;\n const content = message.role === 'assistant' ? message.content : EMPTY_CONTENT;\n if (message.status?.type === 'running' && onlyLastPartGrew({ previous: last, next: content })) {\n return last;\n }\n last = content;\n return content;\n };\n}\nconst RUNNING_STATUS = { type: 'running' } as const;\nconst COMPLETE_STATUS = { type: 'complete' } as const;\n\n// ─── Disclosure memory ─────────────────────────────────────────────────\n\n/**\n * Session-local memory of which cards the user opened, keyed by the host's\n * expansion key (the message id by default; the Chrome extension keys by\n * thread + position so a streaming message keeps its choice when it receives\n * its stable id). Bounded so a long session cannot grow it without limit.\n */\nconst rememberedExpansions = new Map<string, boolean>();\n\nfunction rememberExpansion(key: string, expanded: boolean): void {\n rememberedExpansions.delete(key);\n rememberedExpansions.set(key, expanded);\n while (rememberedExpansions.size > MAX_REMEMBERED_EXPANSIONS) {\n const oldestKey = rememberedExpansions.keys().next().value;\n if (oldestKey === undefined) break;\n rememberedExpansions.delete(oldestKey);\n }\n}\n\nexport function resetRememberedExpansionsForTests(): void {\n rememberedExpansions.clear();\n}\n\n/**\n * The details disclosure: remembered per expansion key, and — when the host\n * opts in — opened once when the turn starts waiting on the person, so the\n * approval controls inside the details are visible without a click.\n */\nexport function useActivityExpansion({\n expansionKey,\n phase,\n expandWhileWaiting = false,\n}: {\n expansionKey: string;\n phase: ActivityPhase;\n expandWhileWaiting?: boolean;\n}) {\n const [userExpanded, setUserExpanded] = useState<boolean | undefined>(() =>\n rememberedExpansions.get(expansionKey),\n );\n const [waitingAutoExpanded, setWaitingAutoExpanded] = useState(false);\n const previousRef = useRef({ expansionKey, phase });\n\n useEffect(() => {\n setUserExpanded(rememberedExpansions.get(expansionKey));\n setWaitingAutoExpanded(false);\n }, [expansionKey]);\n\n useEffect(() => {\n const previous = previousRef.current;\n if (expandWhileWaiting && previous.expansionKey === expansionKey) {\n if (previous.phase !== 'waiting' && phase === 'waiting') {\n setWaitingAutoExpanded(true);\n } else if (previous.phase === 'waiting' && phase !== 'waiting') {\n setWaitingAutoExpanded(false);\n }\n }\n previousRef.current = { expansionKey, phase };\n }, [expansionKey, phase, expandWhileWaiting]);\n\n const expanded = waitingAutoExpanded || (userExpanded ?? (expandWhileWaiting && phase === 'waiting'));\n const toggleExpanded = () => {\n const next = !expanded;\n setWaitingAutoExpanded(false);\n rememberExpansion(expansionKey, next);\n setUserExpanded(next);\n };\n\n return { expanded, toggleExpanded };\n}\n\n// ─── Card ──────────────────────────────────────────────────────────────\n\nexport interface SuperGroupingCardProps {\n /** Tool UIs to render inside the details panel, by tool name (registered tool UIs still apply). */\n toolUIs?: Record<string, ToolCallMessagePartComponent>;\n /** Fallback for tools without a UI; the SDK's `ToolFallback` by default. */\n ToolFallback?: ComponentType<ToolCallMessagePartProps>;\n /** Text renderer for the details panel. */\n TextComponent: TextMessagePartComponent;\n /** Reasoning renderer for the details panel. */\n ReasoningComponent?: ReasoningMessagePartComponent;\n /** Per-toolkit block inside the details panel; the SDK's `CollapsibleGroup` by default. */\n GroupComponent?: ComponentType<CollapsibleGroupProps>;\n /** Toolkit lookup driving the per-toolkit sub-grouping; the SDK's static map by default. */\n getToolGroupKey?: GetToolGroupKey;\n /** A complete grouping function, when the host builds its own (overrides `getToolGroupKey`). */\n groupingFunction?: GroupingFunction;\n /** Tools whose unresolved call means the turn is waiting on the person (see `buildActivityTimeline`). */\n waitingTools?: ReadonlySet<string>;\n /**\n * Calls the run is parked on, by tool-call id: each one still without its\n * real result reads as waiting (see `buildActivityTimeline`). Keep the set's\n * identity stable while its ids are unchanged.\n */\n waitingToolCallIds?: ReadonlySet<string>;\n /** Tools whose result is a relayed application payload (see `buildActivityTimeline`). */\n passThroughTools?: ReadonlySet<string>;\n /**\n * Tools whose card renders below the header, outside both disclosures, and\n * stays mounted (an editable email draft, a UI test report). `isSdkInlineTool`\n * by default: the registry's `inline` flag plus the SDK's own report cards.\n * The call itself comes second, for a host whose choice depends on what the\n * call did (Olympus keeps an `eval` there only when it dispatched subagents).\n * The card renders it under `useToolPartPlacement()` `'inline'`.\n */\n isInlineTool?: (toolName: string, part: ToolCallMessagePart) => boolean;\n /**\n * Tools whose card is their own step's row in the step list, drawn in place\n * of the status line (Olympus's one-line code runs) and kept out of the\n * details. The card renders it under `useToolPartPlacement()` `'step'`, kept\n * mounted while the step list is (the turn is live, or `mountDetails`); a\n * call that is inline too renders in both places. None by default.\n */\n isStepRowTool?: (toolName: string) => boolean;\n /**\n * Host assertion that the turn is waiting on the person. The SDK derives waiting\n * from `requires-action` and waiting tools itself; no in-repo host passes this.\n */\n waitingForInput?: boolean;\n /** Names tools the shared registry has no entry for (Olympus's tool catalog). */\n resolveToolDisplayName?: (toolName: string) => string | undefined;\n /** Key the disclosure choice is remembered under; the message id by default. */\n expansionKey?: string;\n /** Open the details once when the turn starts waiting on the person. */\n expandWhileWaiting?: boolean;\n /**\n * Keep the details panel mounted (hidden) while collapsed, so a host that\n * needs to find content inside it (a deep link into the run's steps) can.\n */\n mountDetails?: boolean;\n /** Latest steps shown when expanded; unresolved parallel calls always remain visible. */\n maxVisibleSteps?: number;\n /** Extra segments after the collapsed summary (\"1m 23s\", \"12.4k tokens\"), joined with \" · \". */\n summaryDetails?: readonly string[];\n /** Header controls beside the title (a stop button while running, a changes button once done). */\n renderHeaderActions?: (context: {\n phase: ActivityPhase;\n messageContent: readonly ThreadAssistantMessagePart[];\n }) => ReactNode;\n /**\n * Inline on the header row, right of the status, while the turn is running\n * (an elapsed counter). Not rendered while the turn waits on the person.\n */\n renderRunningMeta?: (context: { phase: ActivityPhase }) => ReactNode;\n /** The host's icon for a step's tool, shown on its status row (see `ToolTimeline`). */\n renderStepIcon?: (step: TimelineStep) => ReactNode;\n /** Show the favicons of the sites a finished step's result lists. */\n showSourceFavicons?: boolean;\n className?: string;\n classNames?: {\n root?: string;\n details?: string;\n /** The flex column the run's parts render in; override its gap here. */\n detailsParts?: string;\n /** The flex column the inline tool calls render in, below the header; override its gap here. */\n inlineTools?: string;\n };\n}\n\n/**\n * The collapsed view (previously called the conversational view) of an\n * assistant turn: a compact current action, an expandable tool timeline, and\n * the original interactive tool UIs behind a separate details disclosure. The\n * answer itself renders below the card (`SuperGroupingFinalText`). Shared by\n * the SDK's `AthenaChat`, Olympus, and the Chrome extension, which supply\n * their own text/tool renderers and the host-specific controls through the\n * slots.\n *\n * The details panel stays mounted (visually hidden) while the turn is live so\n * the tool UIs inside run their effects — an asset-streaming card's follow\n * mode must not wait for \"Show details\". A host can take a call out of the\n * details to render its tool UI in the open (`isInlineTool`) or as its step's\n * row (`isStepRowTool`); the tool UI reads which (`useToolPartPlacement`).\n *\n * Selector discipline: raw reads only (`message.status`, `message.id`, and the\n * content through `createActivityContentSelector`, which hands back the\n * message's own array or the previous one, never a new array); every\n * derivation runs in `useMemo` — a selector that returned a fresh array would\n * tear through `useSyncExternalStore`.\n */\nexport const SuperGroupingCard = memo(function SuperGroupingCard({\n toolUIs,\n ToolFallback: ToolFallbackComponent = ToolFallback,\n TextComponent,\n ReasoningComponent,\n GroupComponent = CollapsibleGroup,\n getToolGroupKey = defaultGetToolGroupKey,\n groupingFunction,\n waitingTools,\n waitingToolCallIds,\n passThroughTools,\n isInlineTool = isSdkInlineTool,\n isStepRowTool = NO_STEP_ROW_TOOLS,\n waitingForInput = false,\n resolveToolDisplayName,\n expansionKey: expansionKeyProp,\n expandWhileWaiting = false,\n mountDetails = false,\n maxVisibleSteps = DEFAULT_MAX_VISIBLE_STEPS,\n summaryDetails,\n renderStepIcon,\n showSourceFavicons,\n renderHeaderActions,\n renderRunningMeta,\n className,\n classNames,\n}: SuperGroupingCardProps) {\n const messageId = useAuiState((s) => s.message.id);\n const earlierStepsUnloaded = useEarlierStepsUnloaded();\n const [selectActivityContent] = useState(createActivityContentSelector);\n const messageContent = useAuiState(selectActivityContent);\n const messageStatus = useAuiState((s) => s.message.status);\n\n const timeline = useMemo(() => {\n const items = buildActivityTimeline(messageContent, messageStatus, {\n waitingTools,\n waitingToolCallIds,\n passThroughTools,\n });\n return items.length > 0 ? items : EMPTY_TIMELINE;\n }, [messageContent, messageStatus, waitingTools, waitingToolCallIds, passThroughTools]);\n const phase = useMemo(\n () => resolveActivityPhase(messageStatus, timeline, { waitingForInput }),\n [messageStatus, timeline, waitingForInput],\n );\n const toolCount = countActivityTools(timeline);\n\n const { expanded, toggleExpanded } = useActivityExpansion({\n expansionKey: expansionKeyProp ?? messageId,\n phase,\n expandWhileWaiting,\n });\n const generatedId = useId().replace(/[^A-Za-z0-9_-]/g, '');\n const detailsPanelId = `aui-sg-details-${generatedId}`;\n const statusId = `aui-sg-status-${generatedId}`;\n const { expanded: detailsExpanded, toggleExpanded: toggleDetails } = useActivityExpansion({\n expansionKey: `${expansionKeyProp ?? messageId}:details`,\n phase,\n expandWhileWaiting,\n });\n const assetTitles = useMemo(() => collectAssetTitles(messageContent), [messageContent]);\n const steps = useMemo(\n () =>\n timeline.map((item, index) =>\n toTimelineStep({ item, index, resolveToolDisplayName, assetTitles, withSourceUrls: showSourceFavicons }),\n ),\n [timeline, resolveToolDisplayName, assetTitles, showSourceFavicons],\n );\n\n // The calls rendered outside the details: inline below the header, and as\n // their own step's row (by tool-call id, a tool step's id).\n const { inlineParts, stepRowParts } = useMemo(() => {\n const inline: { index: number; key: string }[] = [];\n const stepRows = new Map<string, number>();\n messageContent.forEach((part, index) => {\n if (part.type !== 'tool-call') return;\n if (isInlineTool(part.toolName, part)) inline.push({ index, key: part.toolCallId });\n if (isStepRowTool(part.toolName)) stepRows.set(part.toolCallId, index);\n });\n return { inlineParts: inline, stepRowParts: stepRows };\n }, [messageContent, isInlineTool, isStepRowTool]);\n const grouping = useMemo(\n () =>\n excludePartsFromGroups(\n excludeFinalTextFromGroups(groupingFunction ?? createToolBasedGroupingFunction(getToolGroupKey)),\n (part) =>\n isGroupedToolCallPart(part) && (isStepRowTool(part.toolName) || isInlineTool(part.toolName, part)),\n ),\n [groupingFunction, getToolGroupKey, isInlineTool, isStepRowTool],\n );\n const hasDetails = useMemo(() => grouping(messageContent).length > 0, [grouping, messageContent]);\n const isActive = phase === 'running' || phase === 'waiting';\n // The toolkit groups inside keep their tool UIs mounted when the details do.\n const groupingContext = useMemo(\n () => ({ groupingFunction: grouping, mountHidden: isActive || mountDetails }),\n [grouping, isActive, mountDetails],\n );\n const components = useMemo(\n () => ({\n tools: {\n ...(toolUIs ? { by_name: toolUIs } : {}),\n Fallback: ToolFallbackComponent,\n },\n Text: TextComponent,\n ...(ReasoningComponent ? { Reasoning: ReasoningComponent } : {}),\n Group: GroupComponent,\n }),\n [toolUIs, ToolFallbackComponent, TextComponent, ReasoningComponent, GroupComponent],\n );\n\n // A turn whose earlier steps have not loaded says so even when only its\n // answer has: its steps (and prompt) are older than the window.\n const hasActivity = timeline.length > 0 || phase !== 'complete' || earlierStepsUnloaded;\n if (!hasActivity) return null;\n\n // Tool UIs perform live subscriptions and asset-follow effects. Collapsing\n // either disclosure must only hide them while active or targeted by a deep link.\n const detailsMounted = isActive || mountDetails || (expanded && detailsExpanded);\n const activeSteps = steps.filter((step) => step.state === 'running');\n const currentStep = activeSteps.at(-1);\n const latestStatus =\n phase === 'waiting'\n ? 'Waiting for you'\n : phase === 'error'\n ? messageStatus?.type === 'incomplete' && messageStatus.reason === 'cancelled'\n ? 'Run stopped'\n : 'Something went wrong'\n : phase === 'running'\n ? currentStep\n ? [\n currentStep.verb,\n currentStep.chip,\n activeSteps.length > 1 ? `${activeSteps.length} in progress` : null,\n ]\n .filter(Boolean)\n .join(' · ')\n : steps.length > 0\n ? 'Preparing response'\n : 'Thinking'\n : getActivitySummary(timeline, { earlierStepsUnloaded });\n const label = [latestStatus, ...(isActive ? [] : (summaryDetails ?? []))].join(' · ');\n // A step-row call's own card is its step's row.\n const renderStepRow =\n stepRowParts.size > 0\n ? (step: TimelineStep) => {\n const index = step.kind === 'tool' ? stepRowParts.get(step.id) : undefined;\n return index === undefined ? null : (\n <ToolPartPlacementProvider value=\"step\">\n <MessagePrimitive.PartByIndex index={index} components={components} />\n </ToolPartPlacementProvider>\n );\n }\n : undefined;\n\n return (\n <section\n data-slot=\"super-grouping-card\"\n data-phase={phase}\n data-tool-count={toolCount}\n className={cn('my-3 min-w-0', className, classNames?.root)}\n aria-busy={phase === 'running' ? 'true' : 'false'}\n aria-describedby={statusId}\n >\n <ToolTimeline\n steps={steps}\n open={expanded}\n onOpenChange={toggleExpanded}\n label={label}\n phase={phase}\n maxVisibleSteps={maxVisibleSteps}\n keepMounted={isActive || mountDetails}\n actions={renderHeaderActions?.({ phase, messageContent })}\n meta={phase === 'running' ? renderRunningMeta?.({ phase }) : null}\n renderStepIcon={renderStepIcon}\n renderStepRow={renderStepRow}\n showSourceFavicons={showSourceFavicons}\n >\n {hasDetails ? (\n <div className=\"min-w-0 pl-5\">\n <button\n type=\"button\"\n onClick={toggleDetails}\n aria-expanded={detailsExpanded}\n aria-controls={detailsPanelId}\n className=\"flex items-center gap-1.5 rounded py-1 text-xs text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronRight\n aria-hidden=\"true\"\n className={cn(\n 'size-3 transition-transform motion-reduce:transition-none',\n detailsExpanded && 'rotate-90',\n )}\n />\n {detailsExpanded ? 'Hide tool details' : 'Show tool details'}\n </button>\n {detailsMounted ? (\n <section\n id={detailsPanelId}\n aria-label=\"Run details\"\n hidden={!expanded || !detailsExpanded}\n className={cn(\n 'min-w-0 overflow-hidden border-l border-border/60 py-2 pl-3',\n classNames?.details,\n )}\n >\n <div className={cn('flex flex-col gap-2', classNames?.detailsParts)}>\n <SuperGroupingProvider value={groupingContext}>\n <ToolPartPlacementProvider value={null}>\n <GroupedMessageParts groupingFunction={grouping} components={components} />\n </ToolPartPlacementProvider>\n </SuperGroupingProvider>\n </div>\n </section>\n ) : null}\n </div>\n ) : null}\n </ToolTimeline>\n {inlineParts.length > 0 ? (\n <div\n data-slot=\"super-grouping-inline-tools\"\n className={cn('mt-2 flex min-w-0 flex-col gap-2', classNames?.inlineTools)}\n >\n <ToolPartPlacementProvider value=\"inline\">\n {inlineParts.map(({ index, key }) => (\n <MessagePrimitive.PartByIndex key={key} index={index} components={components} />\n ))}\n </ToolPartPlacementProvider>\n </div>\n ) : null}\n <output id={statusId} aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {phase === 'waiting' ? 'Waiting for your input' : latestStatus}\n </output>\n </section>\n );\n});\n\n/**\n * The turn's visible answer, rendered below the card: the text after the last\n * tool call (all of it when the turn called no tools) and the words of any\n * spoken voice turn the message holds (`getFinalTextParts`), streaming while\n * the turn is live so the person reads the answer as it arrives.\n *\n * Each part renders through its own `TextComponent`, keyed by its content\n * index, so a part only ever grows at its end: a spoken turn streaming while\n * the run's reply streams after it would otherwise change one joined string in\n * the middle, and a streaming reveal restarts from empty on every word. Only\n * the last part carries the running status (and its caret).\n */\nexport const SuperGroupingFinalText = memo(function SuperGroupingFinalText({\n TextComponent,\n}: {\n TextComponent: TextMessagePartComponent;\n}) {\n const messageContent = useAuiState((s) =>\n s.message.role === 'assistant' ? s.message.content : EMPTY_CONTENT,\n );\n const statusType = useAuiState((s) => s.message.status?.type);\n const parts = useMemo(() => getFinalTextParts(messageContent), [messageContent]);\n\n if (parts.length === 0) return null;\n const running = statusType === 'running' || statusType === 'requires-action';\n return (\n <div data-slot=\"super-grouping-final-text\" className=\"flex min-w-0 flex-col gap-1.5\">\n {parts.map((part, position) => (\n <TextComponent\n key={part.index}\n type=\"text\"\n text={part.text}\n status={running && position === parts.length - 1 ? RUNNING_STATUS : COMPLETE_STATUS}\n />\n ))}\n </div>\n );\n});\n"],"names":["useState","useRef","useEffect","memo","SuperGroupingCard","ToolFallback","CollapsibleGroup","defaultGetToolGroupKey","groupingFunction","isSdkInlineTool","useAuiState","useEarlierStepsUnloaded","useMemo","buildActivityTimeline","resolveActivityPhase","countActivityTools","useId","collectAssetTitles","toTimelineStep","excludePartsFromGroups","excludeFinalTextFromGroups","createToolBasedGroupingFunction","isGroupedToolCallPart","getActivitySummary","jsx","ToolPartPlacementProvider","MessagePrimitive","jsxs","cn","ToolTimeline","ChevronRight","SuperGroupingProvider","GroupedMessageParts","SuperGroupingFinalText","getFinalTextParts"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SuperGroupingCard.cjs","sources":["../../../src/chat/super-grouping/SuperGroupingCard.tsx"],"sourcesContent":["'use client';\n\nimport type {\n AssistantState,\n ReasoningMessagePartComponent,\n TextMessagePartComponent,\n ThreadAssistantMessagePart,\n ToolCallMessagePart,\n ToolCallMessagePartComponent,\n ToolCallMessagePartProps,\n} from '@assistant-ui/react';\nimport { MessagePrimitive, useAuiState } from '@assistant-ui/react';\nimport { ChevronRight } from 'lucide-react';\nimport { type ComponentType, memo, type ReactNode, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { cn } from '../../lib/utils';\nimport { isSdkInlineTool } from '../../tools/inline-tools';\nimport { ToolFallback } from '../../tools/tool-fallback';\nimport { collectAssetTitles } from '../../tools/tool-summary';\nimport {\n type ActivityItem,\n type ActivityPhase,\n buildActivityTimeline,\n countActivityTools,\n excludeFinalTextFromGroups,\n excludePartsFromGroups,\n getActivitySummary,\n getFinalTextParts,\n resolveActivityPhase,\n} from './activity-timeline';\nimport { CollapsibleGroup, type CollapsibleGroupProps, SuperGroupingProvider } from './CollapsibleGroup';\nimport { GroupedMessageParts } from './GroupedMessageParts';\nimport { createToolBasedGroupingFunction, type GroupingFunction, isGroupedToolCallPart } from './grouping-function';\nimport { ToolTimeline } from './ToolTimeline';\nimport { type TimelineStep, toTimelineStep } from './timeline-step';\nimport { defaultGetToolGroupKey, type GetToolGroupKey } from './toolkit-map';\nimport { ToolPartPlacementProvider } from './tool-part-placement';\nimport { useEarlierStepsUnloaded } from './use-earlier-steps-unloaded';\nimport { useTurnStepsControl, useTurnStepsMarker } from './use-turn-steps';\n\nconst DEFAULT_MAX_VISIBLE_STEPS = 3;\nconst MAX_REMEMBERED_EXPANSIONS = 200;\nconst EMPTY_TIMELINE: ActivityItem[] = [];\nconst EMPTY_CONTENT: readonly ThreadAssistantMessagePart[] = [];\nconst NO_STEP_ROW_TOOLS = (): boolean => false;\n\n/**\n * Whether `next` differs from `previous` only in the words of its last part, a text or reasoning\n * part that is still being written: same length, every earlier part the identical object, and the\n * last parts of the same kind.\n */\nfunction onlyLastPartGrew({\n previous,\n next,\n}: {\n previous: readonly ThreadAssistantMessagePart[];\n next: readonly ThreadAssistantMessagePart[];\n}): boolean {\n if (previous === next) return true;\n if (previous.length === 0 || previous.length !== next.length) return false;\n const lastIndex = next.length - 1;\n const kind = next[lastIndex]?.type;\n if ((kind !== 'text' && kind !== 'reasoning') || previous[lastIndex]?.type !== kind) return false;\n for (let index = 0; index < lastIndex; index += 1) {\n if (previous[index] !== next[index]) return false;\n }\n return true;\n}\n\n/**\n * The card's read of its message's content: the content itself, except that while the message is\n * generating it keeps the previous array when only the last text or reasoning part grew. The card\n * builds its steps from tool calls, their results and reasoning steps, never from those words (the\n * answer renders below it, `SuperGroupingFinalText`), and the turn being generated changes its last\n * part on every streamed token; earlier parts keep their objects across a token (the runtime's\n * conversion cache), so the card re-renders when a step changes, not per token. Any other change,\n * and the run ending, hand over the current content.\n */\nfunction createActivityContentSelector(): (\n state: AssistantState,\n) => readonly ThreadAssistantMessagePart[] {\n let last: readonly ThreadAssistantMessagePart[] = EMPTY_CONTENT;\n return (state) => {\n const message = state.message;\n const content = message.role === 'assistant' ? message.content : EMPTY_CONTENT;\n if (message.status?.type === 'running' && onlyLastPartGrew({ previous: last, next: content })) {\n return last;\n }\n last = content;\n return content;\n };\n}\nconst RUNNING_STATUS = { type: 'running' } as const;\nconst COMPLETE_STATUS = { type: 'complete' } as const;\n\n// ─── Disclosure memory ─────────────────────────────────────────────────\n\n/**\n * Session-local memory of which cards the user opened, keyed by the host's\n * expansion key (the message id by default; the Chrome extension keys by\n * thread + position so a streaming message keeps its choice when it receives\n * its stable id). Bounded so a long session cannot grow it without limit.\n */\nconst rememberedExpansions = new Map<string, boolean>();\n\nfunction rememberExpansion(key: string, expanded: boolean): void {\n rememberedExpansions.delete(key);\n rememberedExpansions.set(key, expanded);\n while (rememberedExpansions.size > MAX_REMEMBERED_EXPANSIONS) {\n const oldestKey = rememberedExpansions.keys().next().value;\n if (oldestKey === undefined) break;\n rememberedExpansions.delete(oldestKey);\n }\n}\n\nexport function resetRememberedExpansionsForTests(): void {\n rememberedExpansions.clear();\n}\n\n/**\n * The details disclosure: remembered per expansion key, and — when the host\n * opts in — opened once when the turn starts waiting on the person, so the\n * approval controls inside the details are visible without a click.\n */\nexport function useActivityExpansion({\n expansionKey,\n phase,\n expandWhileWaiting = false,\n}: {\n expansionKey: string;\n phase: ActivityPhase;\n expandWhileWaiting?: boolean;\n}) {\n const [userExpanded, setUserExpanded] = useState<boolean | undefined>(() =>\n rememberedExpansions.get(expansionKey),\n );\n const [waitingAutoExpanded, setWaitingAutoExpanded] = useState(false);\n const previousRef = useRef({ expansionKey, phase });\n\n useEffect(() => {\n setUserExpanded(rememberedExpansions.get(expansionKey));\n setWaitingAutoExpanded(false);\n }, [expansionKey]);\n\n useEffect(() => {\n const previous = previousRef.current;\n if (expandWhileWaiting && previous.expansionKey === expansionKey) {\n if (previous.phase !== 'waiting' && phase === 'waiting') {\n setWaitingAutoExpanded(true);\n } else if (previous.phase === 'waiting' && phase !== 'waiting') {\n setWaitingAutoExpanded(false);\n }\n }\n previousRef.current = { expansionKey, phase };\n }, [expansionKey, phase, expandWhileWaiting]);\n\n const expanded = waitingAutoExpanded || (userExpanded ?? (expandWhileWaiting && phase === 'waiting'));\n const toggleExpanded = () => {\n const next = !expanded;\n setWaitingAutoExpanded(false);\n rememberExpansion(expansionKey, next);\n setUserExpanded(next);\n };\n\n return { expanded, toggleExpanded };\n}\n\n// ─── Card ──────────────────────────────────────────────────────────────\n\nexport interface SuperGroupingCardProps {\n /** Tool UIs to render inside the details panel, by tool name (registered tool UIs still apply). */\n toolUIs?: Record<string, ToolCallMessagePartComponent>;\n /** Fallback for tools without a UI; the SDK's `ToolFallback` by default. */\n ToolFallback?: ComponentType<ToolCallMessagePartProps>;\n /** Text renderer for the details panel. */\n TextComponent: TextMessagePartComponent;\n /** Reasoning renderer for the details panel. */\n ReasoningComponent?: ReasoningMessagePartComponent;\n /** Per-toolkit block inside the details panel; the SDK's `CollapsibleGroup` by default. */\n GroupComponent?: ComponentType<CollapsibleGroupProps>;\n /** Toolkit lookup driving the per-toolkit sub-grouping; the SDK's static map by default. */\n getToolGroupKey?: GetToolGroupKey;\n /** A complete grouping function, when the host builds its own (overrides `getToolGroupKey`). */\n groupingFunction?: GroupingFunction;\n /** Tools whose unresolved call means the turn is waiting on the person (see `buildActivityTimeline`). */\n waitingTools?: ReadonlySet<string>;\n /**\n * Calls the run is parked on, by tool-call id: each one still without its\n * real result reads as waiting (see `buildActivityTimeline`). Keep the set's\n * identity stable while its ids are unchanged.\n */\n waitingToolCallIds?: ReadonlySet<string>;\n /** Tools whose result is a relayed application payload (see `buildActivityTimeline`). */\n passThroughTools?: ReadonlySet<string>;\n /**\n * Tools whose card renders below the header, outside both disclosures, and\n * stays mounted (an editable email draft, a UI test report). `isSdkInlineTool`\n * by default: the registry's `inline` flag plus the SDK's own report cards.\n * The call itself comes second, for a host whose choice depends on what the\n * call did (Olympus keeps an `eval` there only when it dispatched subagents).\n * The card renders it under `useToolPartPlacement()` `'inline'`.\n */\n isInlineTool?: (toolName: string, part: ToolCallMessagePart) => boolean;\n /**\n * Tools whose card is their own step's row in the step list, drawn in place\n * of the status line (Olympus's one-line code runs) and kept out of the\n * details. The card renders it under `useToolPartPlacement()` `'step'`, kept\n * mounted while the step list is (the turn is live, or `mountDetails`); a\n * call that is inline too renders in both places. None by default.\n */\n isStepRowTool?: (toolName: string) => boolean;\n /**\n * Host assertion that the turn is waiting on the person. The SDK derives waiting\n * from `requires-action` and waiting tools itself; no in-repo host passes this.\n */\n waitingForInput?: boolean;\n /** Names tools the shared registry has no entry for (Olympus's tool catalog). */\n resolveToolDisplayName?: (toolName: string) => string | undefined;\n /** Key the disclosure choice is remembered under; the message id by default. */\n expansionKey?: string;\n /** Open the details once when the turn starts waiting on the person. */\n expandWhileWaiting?: boolean;\n /**\n * Keep the details panel mounted (hidden) while collapsed, so a host that\n * needs to find content inside it (a deep link into the run's steps) can.\n */\n mountDetails?: boolean;\n /** Latest steps shown when expanded; unresolved parallel calls always remain visible. */\n maxVisibleSteps?: number;\n /** Extra segments after the collapsed summary (\"1m 23s\", \"12.4k tokens\"), joined with \" · \". */\n summaryDetails?: readonly string[];\n /** Header controls beside the title (a stop button while running, a changes button once done). */\n renderHeaderActions?: (context: {\n phase: ActivityPhase;\n messageContent: readonly ThreadAssistantMessagePart[];\n }) => ReactNode;\n /**\n * Inline on the header row, right of the status, while the turn is running\n * (an elapsed counter). Not rendered while the turn waits on the person.\n */\n renderRunningMeta?: (context: { phase: ActivityPhase }) => ReactNode;\n /** The host's icon for a step's tool, shown on its status row (see `ToolTimeline`). */\n renderStepIcon?: (step: TimelineStep) => ReactNode;\n /** Show the favicons of the sites a finished step's result lists. */\n showSourceFavicons?: boolean;\n className?: string;\n classNames?: {\n root?: string;\n details?: string;\n /** The flex column the run's parts render in; override its gap here. */\n detailsParts?: string;\n /** The flex column the inline tool calls render in, below the header; override its gap here. */\n inlineTools?: string;\n };\n}\n\n/**\n * The collapsed view (previously called the conversational view) of an\n * assistant turn: a compact current action, an expandable tool timeline, and\n * the original interactive tool UIs behind a separate details disclosure. The\n * answer itself renders below the card (`SuperGroupingFinalText`). Shared by\n * the SDK's `AthenaChat`, Olympus, and the Chrome extension, which supply\n * their own text/tool renderers and the host-specific controls through the\n * slots.\n *\n * The details panel stays mounted (visually hidden) while the turn is live so\n * the tool UIs inside run their effects — an asset-streaming card's follow\n * mode must not wait for \"Show details\". A host can take a call out of the\n * details to render its tool UI in the open (`isInlineTool`) or as its step's\n * row (`isStepRowTool`); the tool UI reads which (`useToolPartPlacement`).\n *\n * Selector discipline: raw reads only (`message.status`, `message.id`, and the\n * content through `createActivityContentSelector`, which hands back the\n * message's own array or the previous one, never a new array); every\n * derivation runs in `useMemo` — a selector that returned a fresh array would\n * tear through `useSyncExternalStore`.\n */\nexport const SuperGroupingCard = memo(function SuperGroupingCard({\n toolUIs,\n ToolFallback: ToolFallbackComponent = ToolFallback,\n TextComponent,\n ReasoningComponent,\n GroupComponent = CollapsibleGroup,\n getToolGroupKey = defaultGetToolGroupKey,\n groupingFunction,\n waitingTools,\n waitingToolCallIds,\n passThroughTools,\n isInlineTool = isSdkInlineTool,\n isStepRowTool = NO_STEP_ROW_TOOLS,\n waitingForInput = false,\n resolveToolDisplayName,\n expansionKey: expansionKeyProp,\n expandWhileWaiting = false,\n mountDetails = false,\n maxVisibleSteps = DEFAULT_MAX_VISIBLE_STEPS,\n summaryDetails,\n renderStepIcon,\n showSourceFavicons,\n renderHeaderActions,\n renderRunningMeta,\n className,\n classNames,\n}: SuperGroupingCardProps) {\n const messageId = useAuiState((s) => s.message.id);\n const earlierStepsUnloaded = useEarlierStepsUnloaded();\n const stepsMarker = useTurnStepsMarker();\n const TurnStepsControl = useTurnStepsControl();\n const hiddenSteps = stepsMarker\n ? { tools: stepsMarker.hiddenTools, delegations: stepsMarker.hiddenDelegations }\n : undefined;\n const [selectActivityContent] = useState(createActivityContentSelector);\n const messageContent = useAuiState(selectActivityContent);\n const messageStatus = useAuiState((s) => s.message.status);\n\n const timeline = useMemo(() => {\n const items = buildActivityTimeline(messageContent, messageStatus, {\n waitingTools,\n waitingToolCallIds,\n passThroughTools,\n });\n return items.length > 0 ? items : EMPTY_TIMELINE;\n }, [messageContent, messageStatus, waitingTools, waitingToolCallIds, passThroughTools]);\n const phase = useMemo(\n () => resolveActivityPhase(messageStatus, timeline, { waitingForInput }),\n [messageStatus, timeline, waitingForInput],\n );\n const toolCount = countActivityTools(timeline) + (hiddenSteps?.tools ?? 0);\n\n // A turn of older history paged by command changes its message id as its\n // steps load (the first step leads the reply), so it is remembered by the\n // turn: otherwise opening it would fetch its steps and close it again.\n const expansionBase = expansionKeyProp ?? (stepsMarker ? `turn:${stepsMarker.turn}` : messageId);\n const { expanded, toggleExpanded } = useActivityExpansion({\n expansionKey: expansionBase,\n phase,\n expandWhileWaiting,\n });\n const generatedId = useId().replace(/[^A-Za-z0-9_-]/g, '');\n const detailsPanelId = `aui-sg-details-${generatedId}`;\n const statusId = `aui-sg-status-${generatedId}`;\n const { expanded: detailsExpanded, toggleExpanded: toggleDetails } = useActivityExpansion({\n expansionKey: `${expansionBase}:details`,\n phase,\n expandWhileWaiting,\n });\n const assetTitles = useMemo(() => collectAssetTitles(messageContent), [messageContent]);\n const steps = useMemo(\n () =>\n timeline.map((item, index) =>\n toTimelineStep({ item, index, resolveToolDisplayName, assetTitles, withSourceUrls: showSourceFavicons }),\n ),\n [timeline, resolveToolDisplayName, assetTitles, showSourceFavicons],\n );\n\n // The calls rendered outside the details: inline below the header, and as\n // their own step's row (by tool-call id, a tool step's id).\n const { inlineParts, stepRowParts } = useMemo(() => {\n const inline: { index: number; key: string }[] = [];\n const stepRows = new Map<string, number>();\n messageContent.forEach((part, index) => {\n if (part.type !== 'tool-call') return;\n if (isInlineTool(part.toolName, part)) inline.push({ index, key: part.toolCallId });\n if (isStepRowTool(part.toolName)) stepRows.set(part.toolCallId, index);\n });\n return { inlineParts: inline, stepRowParts: stepRows };\n }, [messageContent, isInlineTool, isStepRowTool]);\n const grouping = useMemo(\n () =>\n excludePartsFromGroups(\n excludeFinalTextFromGroups(groupingFunction ?? createToolBasedGroupingFunction(getToolGroupKey)),\n (part) =>\n isGroupedToolCallPart(part) && (isStepRowTool(part.toolName) || isInlineTool(part.toolName, part)),\n ),\n [groupingFunction, getToolGroupKey, isInlineTool, isStepRowTool],\n );\n const hasDetails = useMemo(() => grouping(messageContent).length > 0, [grouping, messageContent]);\n const isActive = phase === 'running' || phase === 'waiting';\n // The toolkit groups inside keep their tool UIs mounted when the details do.\n const groupingContext = useMemo(\n () => ({ groupingFunction: grouping, mountHidden: isActive || mountDetails }),\n [grouping, isActive, mountDetails],\n );\n const components = useMemo(\n () => ({\n tools: {\n ...(toolUIs ? { by_name: toolUIs } : {}),\n Fallback: ToolFallbackComponent,\n },\n Text: TextComponent,\n ...(ReasoningComponent ? { Reasoning: ReasoningComponent } : {}),\n Group: GroupComponent,\n }),\n [toolUIs, ToolFallbackComponent, TextComponent, ReasoningComponent, GroupComponent],\n );\n\n // A turn whose earlier steps have not loaded says so even when only its\n // answer has: its steps (and prompt) are older than the window.\n const hasActivity =\n timeline.length > 0 || phase !== 'complete' || earlierStepsUnloaded || (stepsMarker?.hiddenSteps ?? 0) > 0;\n if (!hasActivity) return null;\n\n // Tool UIs perform live subscriptions and asset-follow effects. Collapsing\n // either disclosure must only hide them while active or targeted by a deep link.\n const detailsMounted = isActive || mountDetails || (expanded && detailsExpanded);\n const activeSteps = steps.filter((step) => step.state === 'running');\n const currentStep = activeSteps.at(-1);\n const latestStatus =\n phase === 'waiting'\n ? 'Waiting for you'\n : phase === 'error'\n ? messageStatus?.type === 'incomplete' && messageStatus.reason === 'cancelled'\n ? 'Run stopped'\n : 'Something went wrong'\n : phase === 'running'\n ? currentStep\n ? [\n currentStep.verb,\n currentStep.chip,\n activeSteps.length > 1 ? `${activeSteps.length} in progress` : null,\n ]\n .filter(Boolean)\n .join(' · ')\n : steps.length > 0\n ? 'Preparing response'\n : 'Thinking'\n : getActivitySummary(timeline, { earlierStepsUnloaded, hiddenSteps });\n const label = [latestStatus, ...(isActive ? [] : (summaryDetails ?? []))].join(' · ');\n // A step-row call's own card is its step's row.\n const renderStepRow =\n stepRowParts.size > 0\n ? (step: TimelineStep) => {\n const index = step.kind === 'tool' ? stepRowParts.get(step.id) : undefined;\n return index === undefined ? null : (\n <ToolPartPlacementProvider value=\"step\">\n <MessagePrimitive.PartByIndex index={index} components={components} />\n </ToolPartPlacementProvider>\n );\n }\n : undefined;\n\n return (\n <section\n data-slot=\"super-grouping-card\"\n data-phase={phase}\n data-tool-count={toolCount}\n className={cn('my-3 min-w-0', className, classNames?.root)}\n aria-busy={phase === 'running' ? 'true' : 'false'}\n aria-describedby={statusId}\n >\n <ToolTimeline\n steps={steps}\n open={expanded}\n onOpenChange={toggleExpanded}\n label={label}\n phase={phase}\n maxVisibleSteps={maxVisibleSteps}\n keepMounted={isActive || mountDetails}\n actions={renderHeaderActions?.({ phase, messageContent })}\n meta={phase === 'running' ? renderRunningMeta?.({ phase }) : null}\n renderStepIcon={renderStepIcon}\n renderStepRow={renderStepRow}\n showSourceFavicons={showSourceFavicons}\n >\n {/* Opening a turn of older history fetches its newest steps (once). */}\n {stepsMarker && stepsMarker.hiddenSteps > 0 && TurnStepsControl ? (\n <div className=\"min-w-0 pl-5\">\n <TurnStepsControl marker={stepsMarker} autoLoad={expanded} />\n </div>\n ) : null}\n {hasDetails ? (\n <div className=\"min-w-0 pl-5\">\n <button\n type=\"button\"\n onClick={toggleDetails}\n aria-expanded={detailsExpanded}\n aria-controls={detailsPanelId}\n className=\"flex items-center gap-1.5 rounded py-1 text-xs text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronRight\n aria-hidden=\"true\"\n className={cn(\n 'size-3 transition-transform motion-reduce:transition-none',\n detailsExpanded && 'rotate-90',\n )}\n />\n {detailsExpanded ? 'Hide tool details' : 'Show tool details'}\n </button>\n {detailsMounted ? (\n <section\n id={detailsPanelId}\n aria-label=\"Run details\"\n hidden={!expanded || !detailsExpanded}\n className={cn(\n 'min-w-0 overflow-hidden border-l border-border/60 py-2 pl-3',\n classNames?.details,\n )}\n >\n <div className={cn('flex flex-col gap-2', classNames?.detailsParts)}>\n <SuperGroupingProvider value={groupingContext}>\n <ToolPartPlacementProvider value={null}>\n <GroupedMessageParts groupingFunction={grouping} components={components} />\n </ToolPartPlacementProvider>\n </SuperGroupingProvider>\n </div>\n </section>\n ) : null}\n </div>\n ) : null}\n </ToolTimeline>\n {inlineParts.length > 0 ? (\n <div\n data-slot=\"super-grouping-inline-tools\"\n className={cn('mt-2 flex min-w-0 flex-col gap-2', classNames?.inlineTools)}\n >\n <ToolPartPlacementProvider value=\"inline\">\n {inlineParts.map(({ index, key }) => (\n <MessagePrimitive.PartByIndex key={key} index={index} components={components} />\n ))}\n </ToolPartPlacementProvider>\n </div>\n ) : null}\n <output id={statusId} aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {phase === 'waiting' ? 'Waiting for your input' : latestStatus}\n </output>\n </section>\n );\n});\n\n/**\n * The turn's visible answer, rendered below the card: the text after the last\n * tool call (all of it when the turn called no tools) and the words of any\n * spoken voice turn the message holds (`getFinalTextParts`), streaming while\n * the turn is live so the person reads the answer as it arrives.\n *\n * Each part renders through its own `TextComponent`, keyed by its content\n * index, so a part only ever grows at its end: a spoken turn streaming while\n * the run's reply streams after it would otherwise change one joined string in\n * the middle, and a streaming reveal restarts from empty on every word. Only\n * the last part carries the running status (and its caret).\n */\nexport const SuperGroupingFinalText = memo(function SuperGroupingFinalText({\n TextComponent,\n}: {\n TextComponent: TextMessagePartComponent;\n}) {\n const messageContent = useAuiState((s) =>\n s.message.role === 'assistant' ? s.message.content : EMPTY_CONTENT,\n );\n const statusType = useAuiState((s) => s.message.status?.type);\n const parts = useMemo(() => getFinalTextParts(messageContent), [messageContent]);\n\n if (parts.length === 0) return null;\n const running = statusType === 'running' || statusType === 'requires-action';\n return (\n <div data-slot=\"super-grouping-final-text\" className=\"flex min-w-0 flex-col gap-1.5\">\n {parts.map((part, position) => (\n <TextComponent\n key={part.index}\n type=\"text\"\n text={part.text}\n status={running && position === parts.length - 1 ? RUNNING_STATUS : COMPLETE_STATUS}\n />\n ))}\n </div>\n );\n});\n"],"names":["useState","useRef","useEffect","memo","SuperGroupingCard","ToolFallback","CollapsibleGroup","defaultGetToolGroupKey","groupingFunction","isSdkInlineTool","useAuiState","useEarlierStepsUnloaded","useTurnStepsMarker","useTurnStepsControl","useMemo","buildActivityTimeline","resolveActivityPhase","countActivityTools","useId","collectAssetTitles","toTimelineStep","excludePartsFromGroups","excludeFinalTextFromGroups","createToolBasedGroupingFunction","isGroupedToolCallPart","getActivitySummary","jsx","ToolPartPlacementProvider","MessagePrimitive","jsxs","cn","ToolTimeline","ChevronRight","SuperGroupingProvider","GroupedMessageParts","SuperGroupingFinalText","getFinalTextParts"],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ import { toTimelineStep } from "./timeline-step.js";
|
|
|
14
14
|
import { defaultGetToolGroupKey } from "./toolkit-map.js";
|
|
15
15
|
import { ToolPartPlacementProvider } from "./tool-part-placement.js";
|
|
16
16
|
import { useEarlierStepsUnloaded } from "./use-earlier-steps-unloaded.js";
|
|
17
|
+
import { useTurnStepsMarker, useTurnStepsControl } from "./use-turn-steps.js";
|
|
17
18
|
import { cn } from "cnfast";
|
|
18
19
|
const DEFAULT_MAX_VISIBLE_STEPS = 3;
|
|
19
20
|
const MAX_REMEMBERED_EXPANSIONS = 200;
|
|
@@ -126,6 +127,9 @@ const SuperGroupingCard = memo(function SuperGroupingCard2({
|
|
|
126
127
|
}) {
|
|
127
128
|
const messageId = useAuiState((s) => s.message.id);
|
|
128
129
|
const earlierStepsUnloaded = useEarlierStepsUnloaded();
|
|
130
|
+
const stepsMarker = useTurnStepsMarker();
|
|
131
|
+
const TurnStepsControl = useTurnStepsControl();
|
|
132
|
+
const hiddenSteps = stepsMarker ? { tools: stepsMarker.hiddenTools, delegations: stepsMarker.hiddenDelegations } : void 0;
|
|
129
133
|
const [selectActivityContent] = useState(createActivityContentSelector);
|
|
130
134
|
const messageContent = useAuiState(selectActivityContent);
|
|
131
135
|
const messageStatus = useAuiState((s) => s.message.status);
|
|
@@ -141,9 +145,10 @@ const SuperGroupingCard = memo(function SuperGroupingCard2({
|
|
|
141
145
|
() => resolveActivityPhase(messageStatus, timeline, { waitingForInput }),
|
|
142
146
|
[messageStatus, timeline, waitingForInput]
|
|
143
147
|
);
|
|
144
|
-
const toolCount = countActivityTools(timeline);
|
|
148
|
+
const toolCount = countActivityTools(timeline) + ((hiddenSteps == null ? void 0 : hiddenSteps.tools) ?? 0);
|
|
149
|
+
const expansionBase = expansionKeyProp ?? (stepsMarker ? `turn:${stepsMarker.turn}` : messageId);
|
|
145
150
|
const { expanded, toggleExpanded } = useActivityExpansion({
|
|
146
|
-
expansionKey:
|
|
151
|
+
expansionKey: expansionBase,
|
|
147
152
|
phase,
|
|
148
153
|
expandWhileWaiting
|
|
149
154
|
});
|
|
@@ -151,7 +156,7 @@ const SuperGroupingCard = memo(function SuperGroupingCard2({
|
|
|
151
156
|
const detailsPanelId = `aui-sg-details-${generatedId}`;
|
|
152
157
|
const statusId = `aui-sg-status-${generatedId}`;
|
|
153
158
|
const { expanded: detailsExpanded, toggleExpanded: toggleDetails } = useActivityExpansion({
|
|
154
|
-
expansionKey: `${
|
|
159
|
+
expansionKey: `${expansionBase}:details`,
|
|
155
160
|
phase,
|
|
156
161
|
expandWhileWaiting
|
|
157
162
|
});
|
|
@@ -197,7 +202,7 @@ const SuperGroupingCard = memo(function SuperGroupingCard2({
|
|
|
197
202
|
}),
|
|
198
203
|
[toolUIs, ToolFallbackComponent, TextComponent, ReasoningComponent, GroupComponent]
|
|
199
204
|
);
|
|
200
|
-
const hasActivity = timeline.length > 0 || phase !== "complete" || earlierStepsUnloaded;
|
|
205
|
+
const hasActivity = timeline.length > 0 || phase !== "complete" || earlierStepsUnloaded || ((stepsMarker == null ? void 0 : stepsMarker.hiddenSteps) ?? 0) > 0;
|
|
201
206
|
if (!hasActivity) return null;
|
|
202
207
|
const detailsMounted = isActive || mountDetails || expanded && detailsExpanded;
|
|
203
208
|
const activeSteps = steps.filter((step) => step.state === "running");
|
|
@@ -206,7 +211,7 @@ const SuperGroupingCard = memo(function SuperGroupingCard2({
|
|
|
206
211
|
currentStep.verb,
|
|
207
212
|
currentStep.chip,
|
|
208
213
|
activeSteps.length > 1 ? `${activeSteps.length} in progress` : null
|
|
209
|
-
].filter(Boolean).join(" · ") : steps.length > 0 ? "Preparing response" : "Thinking" : getActivitySummary(timeline, { earlierStepsUnloaded });
|
|
214
|
+
].filter(Boolean).join(" · ") : steps.length > 0 ? "Preparing response" : "Thinking" : getActivitySummary(timeline, { earlierStepsUnloaded, hiddenSteps });
|
|
210
215
|
const label = [latestStatus, ...isActive ? [] : summaryDetails ?? []].join(" · ");
|
|
211
216
|
const renderStepRow = stepRowParts.size > 0 ? (step) => {
|
|
212
217
|
const index = step.kind === "tool" ? stepRowParts.get(step.id) : void 0;
|
|
@@ -222,7 +227,7 @@ const SuperGroupingCard = memo(function SuperGroupingCard2({
|
|
|
222
227
|
"aria-busy": phase === "running" ? "true" : "false",
|
|
223
228
|
"aria-describedby": statusId,
|
|
224
229
|
children: [
|
|
225
|
-
/* @__PURE__ */
|
|
230
|
+
/* @__PURE__ */ jsxs(
|
|
226
231
|
ToolTimeline,
|
|
227
232
|
{
|
|
228
233
|
steps,
|
|
@@ -237,44 +242,47 @@ const SuperGroupingCard = memo(function SuperGroupingCard2({
|
|
|
237
242
|
renderStepIcon,
|
|
238
243
|
renderStepRow,
|
|
239
244
|
showSourceFavicons,
|
|
240
|
-
children:
|
|
241
|
-
/* @__PURE__ */
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
"
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
245
|
+
children: [
|
|
246
|
+
stepsMarker && stepsMarker.hiddenSteps > 0 && TurnStepsControl ? /* @__PURE__ */ jsx("div", { className: "min-w-0 pl-5", children: /* @__PURE__ */ jsx(TurnStepsControl, { marker: stepsMarker, autoLoad: expanded }) }) : null,
|
|
247
|
+
hasDetails ? /* @__PURE__ */ jsxs("div", { className: "min-w-0 pl-5", children: [
|
|
248
|
+
/* @__PURE__ */ jsxs(
|
|
249
|
+
"button",
|
|
250
|
+
{
|
|
251
|
+
type: "button",
|
|
252
|
+
onClick: toggleDetails,
|
|
253
|
+
"aria-expanded": detailsExpanded,
|
|
254
|
+
"aria-controls": detailsPanelId,
|
|
255
|
+
className: "flex items-center gap-1.5 rounded py-1 text-xs text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
256
|
+
children: [
|
|
257
|
+
/* @__PURE__ */ jsx(
|
|
258
|
+
ChevronRight,
|
|
259
|
+
{
|
|
260
|
+
"aria-hidden": "true",
|
|
261
|
+
className: cn(
|
|
262
|
+
"size-3 transition-transform motion-reduce:transition-none",
|
|
263
|
+
detailsExpanded && "rotate-90"
|
|
264
|
+
)
|
|
265
|
+
}
|
|
266
|
+
),
|
|
267
|
+
detailsExpanded ? "Hide tool details" : "Show tool details"
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
),
|
|
271
|
+
detailsMounted ? /* @__PURE__ */ jsx(
|
|
272
|
+
"section",
|
|
273
|
+
{
|
|
274
|
+
id: detailsPanelId,
|
|
275
|
+
"aria-label": "Run details",
|
|
276
|
+
hidden: !expanded || !detailsExpanded,
|
|
277
|
+
className: cn(
|
|
278
|
+
"min-w-0 overflow-hidden border-l border-border/60 py-2 pl-3",
|
|
279
|
+
classNames == null ? void 0 : classNames.details
|
|
259
280
|
),
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
)
|
|
264
|
-
|
|
265
|
-
"section",
|
|
266
|
-
{
|
|
267
|
-
id: detailsPanelId,
|
|
268
|
-
"aria-label": "Run details",
|
|
269
|
-
hidden: !expanded || !detailsExpanded,
|
|
270
|
-
className: cn(
|
|
271
|
-
"min-w-0 overflow-hidden border-l border-border/60 py-2 pl-3",
|
|
272
|
-
classNames == null ? void 0 : classNames.details
|
|
273
|
-
),
|
|
274
|
-
children: /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-2", classNames == null ? void 0 : classNames.detailsParts), children: /* @__PURE__ */ jsx(SuperGroupingProvider, { value: groupingContext, children: /* @__PURE__ */ jsx(ToolPartPlacementProvider, { value: null, children: /* @__PURE__ */ jsx(GroupedMessageParts, { groupingFunction: grouping, components }) }) }) })
|
|
275
|
-
}
|
|
276
|
-
) : null
|
|
277
|
-
] }) : null
|
|
281
|
+
children: /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-2", classNames == null ? void 0 : classNames.detailsParts), children: /* @__PURE__ */ jsx(SuperGroupingProvider, { value: groupingContext, children: /* @__PURE__ */ jsx(ToolPartPlacementProvider, { value: null, children: /* @__PURE__ */ jsx(GroupedMessageParts, { groupingFunction: grouping, components }) }) }) })
|
|
282
|
+
}
|
|
283
|
+
) : null
|
|
284
|
+
] }) : null
|
|
285
|
+
]
|
|
278
286
|
}
|
|
279
287
|
),
|
|
280
288
|
inlineParts.length > 0 ? /* @__PURE__ */ jsx(
|