@athenaintel/react 0.39.0 → 0.40.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/README.md +39 -3
- package/dist/agent-runtime/src/errors.cjs +8 -0
- package/dist/agent-runtime/src/errors.cjs.map +1 -1
- package/dist/agent-runtime/src/errors.js +8 -0
- package/dist/agent-runtime/src/errors.js.map +1 -1
- package/dist/agent-runtime/src/messages.cjs +76 -16
- package/dist/agent-runtime/src/messages.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.js +76 -16
- package/dist/agent-runtime/src/messages.js.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.cjs +15 -0
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.js +15 -0
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/assets/use-asset-content.cjs +127 -0
- package/dist/assets/use-asset-content.cjs.map +1 -0
- package/dist/assets/use-asset-content.d.ts +60 -0
- package/dist/assets/use-asset-content.js +127 -0
- package/dist/assets/use-asset-content.js.map +1 -0
- package/dist/chat/AthenaChat.cjs +24 -10
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.js +25 -11
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/run-activity.cjs +29 -10
- package/dist/chat/run-activity.cjs.map +1 -1
- package/dist/chat/run-activity.d.ts +30 -4
- package/dist/chat/run-activity.js +29 -10
- package/dist/chat/run-activity.js.map +1 -1
- package/dist/chat/super-grouping/CollapsibleGroup.cjs +16 -8
- package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
- package/dist/chat/super-grouping/CollapsibleGroup.d.ts +26 -1
- package/dist/chat/super-grouping/CollapsibleGroup.js +16 -8
- package/dist/chat/super-grouping/CollapsibleGroup.js.map +1 -1
- package/dist/chat/super-grouping/GroupedMessageParts.cjs +59 -0
- package/dist/chat/super-grouping/GroupedMessageParts.cjs.map +1 -0
- package/dist/chat/super-grouping/GroupedMessageParts.d.ts +25 -0
- package/dist/chat/super-grouping/GroupedMessageParts.js +59 -0
- package/dist/chat/super-grouping/GroupedMessageParts.js.map +1 -0
- package/dist/chat/super-grouping/SuperGroupingCard.cjs +9 -5
- package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.d.ts +2 -1
- package/dist/chat/super-grouping/SuperGroupingCard.js +13 -9
- package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +10 -6
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.js +14 -10
- package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
- package/dist/chat/super-grouping/grouped-part-keys.cjs +104 -0
- package/dist/chat/super-grouping/grouped-part-keys.cjs.map +1 -0
- package/dist/chat/super-grouping/grouped-part-keys.d.ts +37 -0
- package/dist/chat/super-grouping/grouped-part-keys.js +104 -0
- package/dist/chat/super-grouping/grouped-part-keys.js.map +1 -0
- package/dist/chat/super-grouping/index.cjs +2 -0
- package/dist/chat/super-grouping/index.cjs.map +1 -1
- package/dist/chat/super-grouping/index.d.ts +3 -1
- package/dist/chat/super-grouping/index.js +2 -0
- package/dist/chat/super-grouping/index.js.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.cjs +25 -19
- package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.d.ts +5 -0
- package/dist/chat-ui/composer/tiptap-composer.js +26 -20
- package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
- package/dist/composer/clipboard.cjs +16 -0
- package/dist/composer/clipboard.cjs.map +1 -1
- package/dist/composer/clipboard.d.ts +9 -0
- package/dist/composer/clipboard.js +17 -1
- package/dist/composer/clipboard.js.map +1 -1
- package/dist/diagnostics/errors.cjs +6 -0
- package/dist/diagnostics/errors.cjs.map +1 -1
- package/dist/diagnostics/errors.d.ts +6 -0
- package/dist/diagnostics/errors.js +6 -0
- package/dist/diagnostics/errors.js.map +1 -1
- package/dist/index.cjs +23 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/use-document-active.cjs +40 -0
- package/dist/lib/use-document-active.cjs.map +1 -0
- package/dist/lib/use-document-active.d.ts +9 -0
- package/dist/lib/use-document-active.js +40 -0
- package/dist/lib/use-document-active.js.map +1 -0
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/runtime/statewire-lifecycle.cjs +8 -0
- package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
- package/dist/runtime/statewire-lifecycle.js +9 -1
- package/dist/runtime/statewire-lifecycle.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/threads/Inbox.cjs +6 -2
- package/dist/threads/Inbox.cjs.map +1 -1
- package/dist/threads/Inbox.js +6 -2
- package/dist/threads/Inbox.js.map +1 -1
- package/dist/threads/mark-viewed-thread-read.cjs +97 -0
- package/dist/threads/mark-viewed-thread-read.cjs.map +1 -0
- package/dist/threads/mark-viewed-thread-read.d.ts +7 -0
- package/dist/threads/mark-viewed-thread-read.js +97 -0
- package/dist/threads/mark-viewed-thread-read.js.map +1 -0
- package/dist/tools/index.cjs +7 -0
- package/dist/tools/index.cjs.map +1 -1
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.js +7 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/inline-tools.cjs +10 -0
- package/dist/tools/inline-tools.cjs.map +1 -0
- package/dist/tools/inline-tools.d.ts +2 -0
- package/dist/tools/inline-tools.js +10 -0
- package/dist/tools/inline-tools.js.map +1 -0
- package/dist/tools/test-recording-report.cjs +175 -0
- package/dist/tools/test-recording-report.cjs.map +1 -0
- package/dist/tools/test-recording-report.d.ts +82 -0
- package/dist/tools/test-recording-report.js +175 -0
- package/dist/tools/test-recording-report.js.map +1 -0
- package/dist/tools/test-recording-tool-uis.cjs +498 -0
- package/dist/tools/test-recording-tool-uis.cjs.map +1 -0
- package/dist/tools/test-recording-tool-uis.d.ts +32 -0
- package/dist/tools/test-recording-tool-uis.js +498 -0
- package/dist/tools/test-recording-tool-uis.js.map +1 -0
- package/dist/tools/tool-summary.cjs +49 -1
- package/dist/tools/tool-summary.cjs.map +1 -1
- package/dist/tools/tool-summary.js +49 -1
- package/dist/tools/tool-summary.js.map +1 -1
- package/dist/tools/tool-uis.cjs +6 -1
- package/dist/tools/tool-uis.cjs.map +1 -1
- package/dist/tools/tool-uis.js +6 -1
- package/dist/tools/tool-uis.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx, Fragment, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useAuiState, MessagePrimitive, MessagePartPrimitive } from "@assistant-ui/react";
|
|
3
|
+
import { useMemo, useState } from "react";
|
|
4
|
+
import { GroupToolUI } from "./CollapsibleGroup.js";
|
|
5
|
+
import { carryGroupedPartKeys } from "./grouped-part-keys.js";
|
|
6
|
+
const NO_GROUPS = [];
|
|
7
|
+
const DefaultText = () => /* @__PURE__ */ jsxs("p", { style: { whiteSpace: "pre-line" }, children: [
|
|
8
|
+
/* @__PURE__ */ jsx(MessagePartPrimitive.Text, {}),
|
|
9
|
+
/* @__PURE__ */ jsx(MessagePartPrimitive.InProgress, { children: /* @__PURE__ */ jsx("span", { style: { fontFamily: "revert" }, children: " ●" }) })
|
|
10
|
+
] });
|
|
11
|
+
const DefaultImage = () => /* @__PURE__ */ jsx(MessagePartPrimitive.Image, {});
|
|
12
|
+
const PassThroughGroup = ({ children }) => /* @__PURE__ */ jsx(Fragment, { children });
|
|
13
|
+
function useGroupedPartKeys({
|
|
14
|
+
parts,
|
|
15
|
+
groups
|
|
16
|
+
}) {
|
|
17
|
+
const [keys, setKeys] = useState(null);
|
|
18
|
+
if (keys !== null && keys.parts === parts && keys.groups === groups) return keys;
|
|
19
|
+
const next = carryGroupedPartKeys({ previous: keys, parts, groups });
|
|
20
|
+
setKeys(next);
|
|
21
|
+
return next;
|
|
22
|
+
}
|
|
23
|
+
const GroupedMessageParts = ({ groupingFunction, components }) => {
|
|
24
|
+
const parts = useAuiState((s) => s.message.parts);
|
|
25
|
+
const groups = useMemo(
|
|
26
|
+
() => parts.length === 0 ? NO_GROUPS : groupingFunction(parts),
|
|
27
|
+
[parts, groupingFunction]
|
|
28
|
+
);
|
|
29
|
+
const keys = useGroupedPartKeys({ parts, groups });
|
|
30
|
+
const elements = useMemo(() => {
|
|
31
|
+
const leafComponents = {
|
|
32
|
+
...components,
|
|
33
|
+
Text: (components == null ? void 0 : components.Text) ?? DefaultText,
|
|
34
|
+
Image: (components == null ? void 0 : components.Image) ?? DefaultImage
|
|
35
|
+
};
|
|
36
|
+
const Group = (components == null ? void 0 : components.Group) ?? PassThroughGroup;
|
|
37
|
+
return groups.map((group, groupIndex) => /* @__PURE__ */ jsx(Group, { groupKey: group.groupKey, indices: group.indices, children: group.indices.map(
|
|
38
|
+
(partIndex) => {
|
|
39
|
+
var _a;
|
|
40
|
+
return ((_a = parts[partIndex]) == null ? void 0 : _a.type) === "tool-call" ? /* @__PURE__ */ jsx(GroupToolUI, { children: /* @__PURE__ */ jsx(MessagePrimitive.PartByIndex, { index: partIndex, components: leafComponents }) }, keys.partKeys[partIndex]) : /* @__PURE__ */ jsx(
|
|
41
|
+
MessagePrimitive.PartByIndex,
|
|
42
|
+
{
|
|
43
|
+
index: partIndex,
|
|
44
|
+
components: leafComponents
|
|
45
|
+
},
|
|
46
|
+
keys.partKeys[partIndex]
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
) }, keys.groupKeys[groupIndex]));
|
|
50
|
+
}, [components, groups, keys, parts]);
|
|
51
|
+
if (parts.length === 0) {
|
|
52
|
+
return /* @__PURE__ */ jsx(MessagePrimitive.Unstable_PartsGrouped, { groupingFunction, components });
|
|
53
|
+
}
|
|
54
|
+
return /* @__PURE__ */ jsx(Fragment, { children: elements });
|
|
55
|
+
};
|
|
56
|
+
export {
|
|
57
|
+
GroupedMessageParts
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=GroupedMessageParts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GroupedMessageParts.js","sources":["../../../src/chat/super-grouping/GroupedMessageParts.tsx"],"sourcesContent":["import {\n type ImageMessagePartComponent,\n MessagePartPrimitive,\n MessagePrimitive,\n type TextMessagePartComponent,\n useAuiState,\n} from '@assistant-ui/react';\nimport { type ComponentProps, type FC, type ReactNode, useMemo, useState } from 'react';\nimport { GroupToolUI } from './CollapsibleGroup';\nimport { carryGroupedPartKeys, type GroupedPartKeys, type KeyablePart } from './grouped-part-keys';\nimport type { GroupingFunction, MessagePartGroup } from './grouping-function';\n\nexport interface GroupedMessagePartsProps {\n /** Groups the message's parts; each group renders through `components.Group`. */\n groupingFunction: GroupingFunction;\n /** The part and group renderers, as `MessagePrimitive.Unstable_PartsGrouped` takes them. */\n components: ComponentProps<typeof MessagePrimitive.Unstable_PartsGrouped>['components'];\n}\n\nconst NO_GROUPS: readonly MessagePartGroup[] = [];\n\n/** assistant-ui's grouped-parts defaults for the leaves a host does not render. */\nconst DefaultText: TextMessagePartComponent = () => (\n <p style={{ whiteSpace: 'pre-line' }}>\n <MessagePartPrimitive.Text />\n <MessagePartPrimitive.InProgress>\n <span style={{ fontFamily: 'revert' }}>{' ●'}</span>\n </MessagePartPrimitive.InProgress>\n </p>\n);\nconst DefaultImage: ImageMessagePartComponent = () => <MessagePartPrimitive.Image />;\nconst PassThroughGroup = ({ children }: { children?: ReactNode }) => <>{children}</>;\n\n/**\n * The keys of the last render, carried into this one (see\n * {@link carryGroupedPartKeys}). Kept as state, React's way of storing\n * information from previous renders: a render whose parts or groups changed\n * stores the new keys, and React renders again with them before committing.\n */\nfunction useGroupedPartKeys({\n parts,\n groups,\n}: {\n parts: readonly KeyablePart[];\n groups: readonly MessagePartGroup[];\n}): GroupedPartKeys {\n const [keys, setKeys] = useState<GroupedPartKeys | null>(null);\n if (keys !== null && keys.parts === parts && keys.groups === groups) return keys;\n const next = carryGroupedPartKeys({ previous: keys, parts, groups });\n setKeys(next);\n return next;\n}\n\n/**\n * A message's parts grouped by `groupingFunction`, each group through\n * `components.Group` — `MessagePrimitive.Unstable_PartsGrouped` with two\n * differences:\n *\n * - What is mounted stays mounted when the message grows at its head (a page\n * of older steps folding into the first loaded turn) as well as at its tail:\n * groups and parts keep their React keys across renders (see\n * {@link carryGroupedPartKeys}), where assistant-ui keys a group by its\n * first part and a text part by its index.\n * - A tool call's UI renders through {@link GroupToolUI}, so a collapsed\n * `CollapsibleGroup` of a finished turn mounts it only when first needed.\n *\n * An empty message renders as `Unstable_PartsGrouped` renders it.\n */\nexport const GroupedMessageParts: FC<GroupedMessagePartsProps> = ({ groupingFunction, components }) => {\n const parts = useAuiState((s) => s.message.parts);\n const groups = useMemo(\n () => (parts.length === 0 ? NO_GROUPS : groupingFunction(parts)),\n [parts, groupingFunction],\n );\n const keys = useGroupedPartKeys({ parts, groups });\n\n const elements = useMemo(() => {\n const leafComponents = {\n ...components,\n Text: components?.Text ?? DefaultText,\n Image: components?.Image ?? DefaultImage,\n };\n const Group = components?.Group ?? PassThroughGroup;\n return groups.map((group, groupIndex) => (\n <Group key={keys.groupKeys[groupIndex]} groupKey={group.groupKey} indices={group.indices}>\n {group.indices.map((partIndex) =>\n parts[partIndex]?.type === 'tool-call' ? (\n <GroupToolUI key={keys.partKeys[partIndex]}>\n <MessagePrimitive.PartByIndex index={partIndex} components={leafComponents} />\n </GroupToolUI>\n ) : (\n <MessagePrimitive.PartByIndex\n key={keys.partKeys[partIndex]}\n index={partIndex}\n components={leafComponents}\n />\n ),\n )}\n </Group>\n ));\n }, [components, groups, keys, parts]);\n\n if (parts.length === 0) {\n return <MessagePrimitive.Unstable_PartsGrouped groupingFunction={groupingFunction} components={components} />;\n }\n return <>{elements}</>;\n};\n"],"names":[],"mappings":";;;;;AAmBA,MAAM,YAAyC,CAAA;AAG/C,MAAM,cAAwC,MAC5C,qBAAC,KAAA,EAAE,OAAO,EAAE,YAAY,cACtB,UAAA;AAAA,EAAA,oBAAC,qBAAqB,MAArB,EAA0B;AAAA,EAC3B,oBAAC,qBAAqB,YAArB,EACC,UAAA,oBAAC,QAAA,EAAK,OAAO,EAAE,YAAY,SAAA,GAAa,UAAA,KAAA,CAAK,EAAA,CAC/C;AAAA,GACF;AAEF,MAAM,eAA0C,MAAM,oBAAC,qBAAqB,OAArB,CAAA,CAA2B;AAClF,MAAM,mBAAmB,CAAC,EAAE,SAAA,sCAA4C,UAAS;AAQjF,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AACF,GAGoB;AAClB,QAAM,CAAC,MAAM,OAAO,IAAI,SAAiC,IAAI;AAC7D,MAAI,SAAS,QAAQ,KAAK,UAAU,SAAS,KAAK,WAAW,OAAQ,QAAO;AAC5E,QAAM,OAAO,qBAAqB,EAAE,UAAU,MAAM,OAAO,QAAQ;AACnE,UAAQ,IAAI;AACZ,SAAO;AACT;AAiBO,MAAM,sBAAoD,CAAC,EAAE,kBAAkB,iBAAiB;AACrG,QAAM,QAAQ,YAAY,CAAC,MAAM,EAAE,QAAQ,KAAK;AAChD,QAAM,SAAS;AAAA,IACb,MAAO,MAAM,WAAW,IAAI,YAAY,iBAAiB,KAAK;AAAA,IAC9D,CAAC,OAAO,gBAAgB;AAAA,EAAA;AAE1B,QAAM,OAAO,mBAAmB,EAAE,OAAO,QAAQ;AAEjD,QAAM,WAAW,QAAQ,MAAM;AAC7B,UAAM,iBAAiB;AAAA,MACrB,GAAG;AAAA,MACH,OAAM,yCAAY,SAAQ;AAAA,MAC1B,QAAO,yCAAY,UAAS;AAAA,IAAA;AAE9B,UAAM,SAAQ,yCAAY,UAAS;AACnC,WAAO,OAAO,IAAI,CAAC,OAAO,eACxB,oBAAC,OAAA,EAAuC,UAAU,MAAM,UAAU,SAAS,MAAM,SAC9E,gBAAM,QAAQ;AAAA,MAAI,CAAC;;AAClB,4BAAM,SAAS,MAAf,mBAAkB,UAAS,cACzB,oBAAC,aAAA,EACC,UAAA,oBAAC,iBAAiB,aAAjB,EAA6B,OAAO,WAAW,YAAY,eAAA,CAAgB,KAD5D,KAAK,SAAS,SAAS,CAEzC,IAEA;AAAA,UAAC,iBAAiB;AAAA,UAAjB;AAAA,YAEC,OAAO;AAAA,YACP,YAAY;AAAA,UAAA;AAAA,UAFP,KAAK,SAAS,SAAS;AAAA,QAAA;AAAA;AAAA,IAG9B,EAEJ,GAbU,KAAK,UAAU,UAAU,CAcrC,CACD;AAAA,EACH,GAAG,CAAC,YAAY,QAAQ,MAAM,KAAK,CAAC;AAEpC,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,oBAAC,iBAAiB,uBAAjB,EAAuC,kBAAoC,WAAA,CAAwB;AAAA,EAC7G;AACA,yCAAU,UAAA,SAAA,CAAS;AACrB;"}
|
|
@@ -4,15 +4,16 @@ const jsxRuntime = require("react/jsx-runtime");
|
|
|
4
4
|
const react$1 = require("@assistant-ui/react");
|
|
5
5
|
const lucideReact = require("lucide-react");
|
|
6
6
|
const react = require("react");
|
|
7
|
+
const inlineTools = require("../../tools/inline-tools.cjs");
|
|
7
8
|
const toolFallback = require("../../tools/tool-fallback.cjs");
|
|
8
9
|
const toolSummary = require("../../tools/tool-summary.cjs");
|
|
9
10
|
const activityTimeline = require("./activity-timeline.cjs");
|
|
10
11
|
const CollapsibleGroup = require("./CollapsibleGroup.cjs");
|
|
12
|
+
const GroupedMessageParts = require("./GroupedMessageParts.cjs");
|
|
11
13
|
const groupingFunction = require("./grouping-function.cjs");
|
|
12
14
|
const ToolTimeline = require("./ToolTimeline.cjs");
|
|
13
15
|
const timelineStep = require("./timeline-step.cjs");
|
|
14
16
|
const toolkitMap = require("./toolkit-map.cjs");
|
|
15
|
-
const toolMetadata = require("../../agent-runtime/src/tool-metadata.cjs");
|
|
16
17
|
const cnfast = require("cnfast");
|
|
17
18
|
const DEFAULT_MAX_VISIBLE_STEPS = 3;
|
|
18
19
|
const MAX_REMEMBERED_EXPANSIONS = 200;
|
|
@@ -105,7 +106,7 @@ const SuperGroupingCard = react.memo(function SuperGroupingCard2({
|
|
|
105
106
|
groupingFunction: groupingFunction$1,
|
|
106
107
|
waitingTools,
|
|
107
108
|
passThroughTools,
|
|
108
|
-
isInlineTool =
|
|
109
|
+
isInlineTool = inlineTools.isSdkInlineTool,
|
|
109
110
|
waitingForInput = false,
|
|
110
111
|
resolveToolDisplayName,
|
|
111
112
|
expansionKey: expansionKeyProp,
|
|
@@ -169,7 +170,11 @@ const SuperGroupingCard = react.memo(function SuperGroupingCard2({
|
|
|
169
170
|
[groupingFunction$1, getToolGroupKey, isInlineTool]
|
|
170
171
|
);
|
|
171
172
|
const hasDetails = react.useMemo(() => grouping(messageContent).length > 0, [grouping, messageContent]);
|
|
172
|
-
const
|
|
173
|
+
const isActive = phase === "running" || phase === "waiting";
|
|
174
|
+
const groupingContext = react.useMemo(
|
|
175
|
+
() => ({ groupingFunction: grouping, mountHidden: isActive || mountDetails }),
|
|
176
|
+
[grouping, isActive, mountDetails]
|
|
177
|
+
);
|
|
173
178
|
const components = react.useMemo(
|
|
174
179
|
() => ({
|
|
175
180
|
tools: {
|
|
@@ -182,7 +187,6 @@ const SuperGroupingCard = react.memo(function SuperGroupingCard2({
|
|
|
182
187
|
}),
|
|
183
188
|
[toolUIs, ToolFallbackComponent, TextComponent, ReasoningComponent, GroupComponent]
|
|
184
189
|
);
|
|
185
|
-
const isActive = phase === "running" || phase === "waiting";
|
|
186
190
|
const hasActivity = timeline.length > 0 || phase !== "complete";
|
|
187
191
|
if (!hasActivity) return null;
|
|
188
192
|
const detailsMounted = isActive || mountDetails || expanded && detailsExpanded;
|
|
@@ -250,7 +254,7 @@ const SuperGroupingCard = react.memo(function SuperGroupingCard2({
|
|
|
250
254
|
"min-w-0 overflow-hidden border-l border-border/60 py-2 pl-3",
|
|
251
255
|
classNames == null ? void 0 : classNames.details
|
|
252
256
|
),
|
|
253
|
-
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(
|
|
257
|
+
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(GroupedMessageParts.GroupedMessageParts, { groupingFunction: grouping, components }) }) })
|
|
254
258
|
}
|
|
255
259
|
) : null
|
|
256
260
|
] }) : null
|
|
@@ -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 ToolCallMessagePartComponent,\n ToolCallMessagePartProps,\n} from '@assistant-ui/react';\nimport { MessagePrimitive, useAuiState } from '@assistant-ui/react';\nimport { isInlineTool as isRegistryInlineTool } from '@athenaintel/agent-runtime';\nimport { ChevronRight } from 'lucide-react';\nimport { type ComponentType, memo, type ReactNode, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { cn } from '../../lib/utils';\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 { createToolBasedGroupingFunction, type GroupingFunction } from './grouping-function';\nimport { ToolTimeline } from './ToolTimeline';\nimport { toTimelineStep } from './timeline-step';\nimport { defaultGetToolGroupKey, type GetToolGroupKey } from './toolkit-map';\n\nconst DEFAULT_MAX_VISIBLE_STEPS = 3;\nconst MAX_REMEMBERED_EXPANSIONS = 200;\nconst EMPTY_TIMELINE: ActivityItem[] = [];\nconst EMPTY_CONTENT: readonly ThreadAssistantMessagePart[] = [];\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 /** 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). The registry's `inline` flag by default.\n */\n isInlineTool?: (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 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 };\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\".\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 passThroughTools,\n isInlineTool = isRegistryInlineTool,\n waitingForInput = false,\n resolveToolDisplayName,\n expansionKey: expansionKeyProp,\n expandWhileWaiting = false,\n mountDetails = false,\n maxVisibleSteps = DEFAULT_MAX_VISIBLE_STEPS,\n summaryDetails,\n renderHeaderActions,\n renderRunningMeta,\n className,\n classNames,\n}: SuperGroupingCardProps) {\n const messageId = useAuiState((s) => s.message.id);\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 passThroughTools,\n });\n return items.length > 0 ? items : EMPTY_TIMELINE;\n }, [messageContent, messageStatus, waitingTools, 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) => toTimelineStep({ item, index, resolveToolDisplayName, assetTitles })),\n [timeline, resolveToolDisplayName, assetTitles],\n );\n\n const inlineParts = useMemo(() => {\n const parts: { index: number; key: string }[] = [];\n messageContent.forEach((part, index) => {\n if (part.type === 'tool-call' && isInlineTool(part.toolName)) {\n parts.push({ index, key: part.toolCallId });\n }\n });\n return parts;\n }, [messageContent, isInlineTool]);\n const grouping = useMemo(\n () =>\n excludePartsFromGroups(\n excludeFinalTextFromGroups(groupingFunction ?? createToolBasedGroupingFunction(getToolGroupKey)),\n (part) => part.type === 'tool-call' && part.toolName !== undefined && isInlineTool(part.toolName),\n ),\n [groupingFunction, getToolGroupKey, isInlineTool],\n );\n const hasDetails = useMemo(() => grouping(messageContent).length > 0, [grouping, messageContent]);\n const groupingContext = useMemo(() => ({ groupingFunction: grouping }), [grouping]);\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 const isActive = phase === 'running' || phase === 'waiting';\n const hasActivity = timeline.length > 0 || phase !== 'complete';\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);\n const label = [latestStatus, ...(isActive ? [] : (summaryDetails ?? []))].join(' · ');\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 >\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 <MessagePrimitive.Unstable_PartsGrouped groupingFunction={grouping} components={components} />\n </SuperGroupingProvider>\n </div>\n </section>\n ) : null}\n </div>\n ) : null}\n </ToolTimeline>\n {inlineParts.length > 0 ? (\n <div data-slot=\"super-grouping-inline-tools\" className=\"mt-2 flex min-w-0 flex-col gap-2\">\n {inlineParts.map(({ index, key }) => (\n <MessagePrimitive.PartByIndex key={key} index={index} components={components} />\n ))}\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","isRegistryInlineTool","useAuiState","useMemo","buildActivityTimeline","resolveActivityPhase","countActivityTools","useId","collectAssetTitles","toTimelineStep","excludePartsFromGroups","excludeFinalTextFromGroups","createToolBasedGroupingFunction","getActivitySummary","jsxs","cn","jsx","ToolTimeline","ChevronRight","SuperGroupingProvider","MessagePrimitive","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 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 } from './grouping-function';\nimport { ToolTimeline } from './ToolTimeline';\nimport { toTimelineStep } from './timeline-step';\nimport { defaultGetToolGroupKey, type GetToolGroupKey } from './toolkit-map';\n\nconst DEFAULT_MAX_VISIBLE_STEPS = 3;\nconst MAX_REMEMBERED_EXPANSIONS = 200;\nconst EMPTY_TIMELINE: ActivityItem[] = [];\nconst EMPTY_CONTENT: readonly ThreadAssistantMessagePart[] = [];\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 /** 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 */\n isInlineTool?: (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 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 };\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\".\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 passThroughTools,\n isInlineTool = isSdkInlineTool,\n waitingForInput = false,\n resolveToolDisplayName,\n expansionKey: expansionKeyProp,\n expandWhileWaiting = false,\n mountDetails = false,\n maxVisibleSteps = DEFAULT_MAX_VISIBLE_STEPS,\n summaryDetails,\n renderHeaderActions,\n renderRunningMeta,\n className,\n classNames,\n}: SuperGroupingCardProps) {\n const messageId = useAuiState((s) => s.message.id);\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 passThroughTools,\n });\n return items.length > 0 ? items : EMPTY_TIMELINE;\n }, [messageContent, messageStatus, waitingTools, 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) => toTimelineStep({ item, index, resolveToolDisplayName, assetTitles })),\n [timeline, resolveToolDisplayName, assetTitles],\n );\n\n const inlineParts = useMemo(() => {\n const parts: { index: number; key: string }[] = [];\n messageContent.forEach((part, index) => {\n if (part.type === 'tool-call' && isInlineTool(part.toolName)) {\n parts.push({ index, key: part.toolCallId });\n }\n });\n return parts;\n }, [messageContent, isInlineTool]);\n const grouping = useMemo(\n () =>\n excludePartsFromGroups(\n excludeFinalTextFromGroups(groupingFunction ?? createToolBasedGroupingFunction(getToolGroupKey)),\n (part) => part.type === 'tool-call' && part.toolName !== undefined && isInlineTool(part.toolName),\n ),\n [groupingFunction, getToolGroupKey, isInlineTool],\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 const hasActivity = timeline.length > 0 || phase !== 'complete';\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);\n const label = [latestStatus, ...(isActive ? [] : (summaryDetails ?? []))].join(' · ');\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 >\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 <GroupedMessageParts groupingFunction={grouping} components={components} />\n </SuperGroupingProvider>\n </div>\n </section>\n ) : null}\n </div>\n ) : null}\n </ToolTimeline>\n {inlineParts.length > 0 ? (\n <div data-slot=\"super-grouping-inline-tools\" className=\"mt-2 flex min-w-0 flex-col gap-2\">\n {inlineParts.map(({ index, key }) => (\n <MessagePrimitive.PartByIndex key={key} index={index} components={components} />\n ))}\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","useMemo","buildActivityTimeline","resolveActivityPhase","countActivityTools","useId","collectAssetTitles","toTimelineStep","excludePartsFromGroups","excludeFinalTextFromGroups","createToolBasedGroupingFunction","getActivitySummary","jsxs","cn","jsx","ToolTimeline","ChevronRight","SuperGroupingProvider","GroupedMessageParts","MessagePrimitive","SuperGroupingFinalText","getFinalTextParts"],"mappings":"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"}
|
|
@@ -39,7 +39,8 @@ export interface SuperGroupingCardProps {
|
|
|
39
39
|
passThroughTools?: ReadonlySet<string>;
|
|
40
40
|
/**
|
|
41
41
|
* Tools whose card renders below the header, outside both disclosures, and
|
|
42
|
-
* stays mounted (an editable email draft).
|
|
42
|
+
* stays mounted (an editable email draft, a UI test report). `isSdkInlineTool`
|
|
43
|
+
* by default: the registry's `inline` flag plus the SDK's own report cards.
|
|
43
44
|
*/
|
|
44
45
|
isInlineTool?: (toolName: string) => boolean;
|
|
45
46
|
/**
|
|
@@ -2,15 +2,16 @@ import { jsxs, jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { useAuiState, MessagePrimitive } from "@assistant-ui/react";
|
|
3
3
|
import { ChevronRight } from "lucide-react";
|
|
4
4
|
import { memo, useState, useMemo, useId, useRef, useEffect } from "react";
|
|
5
|
+
import { isSdkInlineTool } from "../../tools/inline-tools.js";
|
|
5
6
|
import { ToolFallback } from "../../tools/tool-fallback.js";
|
|
6
7
|
import { collectAssetTitles } from "../../tools/tool-summary.js";
|
|
7
8
|
import { buildActivityTimeline, resolveActivityPhase, countActivityTools, excludePartsFromGroups, getActivitySummary, getFinalTextParts, excludeFinalTextFromGroups } from "./activity-timeline.js";
|
|
8
9
|
import { CollapsibleGroup, SuperGroupingProvider } from "./CollapsibleGroup.js";
|
|
10
|
+
import { GroupedMessageParts } from "./GroupedMessageParts.js";
|
|
9
11
|
import { createToolBasedGroupingFunction } from "./grouping-function.js";
|
|
10
12
|
import { ToolTimeline } from "./ToolTimeline.js";
|
|
11
13
|
import { toTimelineStep } from "./timeline-step.js";
|
|
12
14
|
import { defaultGetToolGroupKey } from "./toolkit-map.js";
|
|
13
|
-
import { isInlineTool } from "../../agent-runtime/src/tool-metadata.js";
|
|
14
15
|
import { cn } from "cnfast";
|
|
15
16
|
const DEFAULT_MAX_VISIBLE_STEPS = 3;
|
|
16
17
|
const MAX_REMEMBERED_EXPANSIONS = 200;
|
|
@@ -103,7 +104,7 @@ const SuperGroupingCard = memo(function SuperGroupingCard2({
|
|
|
103
104
|
groupingFunction,
|
|
104
105
|
waitingTools,
|
|
105
106
|
passThroughTools,
|
|
106
|
-
isInlineTool
|
|
107
|
+
isInlineTool = isSdkInlineTool,
|
|
107
108
|
waitingForInput = false,
|
|
108
109
|
resolveToolDisplayName,
|
|
109
110
|
expansionKey: expansionKeyProp,
|
|
@@ -153,21 +154,25 @@ const SuperGroupingCard = memo(function SuperGroupingCard2({
|
|
|
153
154
|
const inlineParts = useMemo(() => {
|
|
154
155
|
const parts = [];
|
|
155
156
|
messageContent.forEach((part, index) => {
|
|
156
|
-
if (part.type === "tool-call" && isInlineTool
|
|
157
|
+
if (part.type === "tool-call" && isInlineTool(part.toolName)) {
|
|
157
158
|
parts.push({ index, key: part.toolCallId });
|
|
158
159
|
}
|
|
159
160
|
});
|
|
160
161
|
return parts;
|
|
161
|
-
}, [messageContent, isInlineTool
|
|
162
|
+
}, [messageContent, isInlineTool]);
|
|
162
163
|
const grouping = useMemo(
|
|
163
164
|
() => excludePartsFromGroups(
|
|
164
165
|
excludeFinalTextFromGroups(groupingFunction ?? createToolBasedGroupingFunction(getToolGroupKey)),
|
|
165
|
-
(part) => part.type === "tool-call" && part.toolName !== void 0 && isInlineTool
|
|
166
|
+
(part) => part.type === "tool-call" && part.toolName !== void 0 && isInlineTool(part.toolName)
|
|
166
167
|
),
|
|
167
|
-
[groupingFunction, getToolGroupKey, isInlineTool
|
|
168
|
+
[groupingFunction, getToolGroupKey, isInlineTool]
|
|
168
169
|
);
|
|
169
170
|
const hasDetails = useMemo(() => grouping(messageContent).length > 0, [grouping, messageContent]);
|
|
170
|
-
const
|
|
171
|
+
const isActive = phase === "running" || phase === "waiting";
|
|
172
|
+
const groupingContext = useMemo(
|
|
173
|
+
() => ({ groupingFunction: grouping, mountHidden: isActive || mountDetails }),
|
|
174
|
+
[grouping, isActive, mountDetails]
|
|
175
|
+
);
|
|
171
176
|
const components = useMemo(
|
|
172
177
|
() => ({
|
|
173
178
|
tools: {
|
|
@@ -180,7 +185,6 @@ const SuperGroupingCard = memo(function SuperGroupingCard2({
|
|
|
180
185
|
}),
|
|
181
186
|
[toolUIs, ToolFallbackComponent, TextComponent, ReasoningComponent, GroupComponent]
|
|
182
187
|
);
|
|
183
|
-
const isActive = phase === "running" || phase === "waiting";
|
|
184
188
|
const hasActivity = timeline.length > 0 || phase !== "complete";
|
|
185
189
|
if (!hasActivity) return null;
|
|
186
190
|
const detailsMounted = isActive || mountDetails || expanded && detailsExpanded;
|
|
@@ -248,7 +252,7 @@ const SuperGroupingCard = memo(function SuperGroupingCard2({
|
|
|
248
252
|
"min-w-0 overflow-hidden border-l border-border/60 py-2 pl-3",
|
|
249
253
|
classNames == null ? void 0 : classNames.details
|
|
250
254
|
),
|
|
251
|
-
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(
|
|
255
|
+
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(GroupedMessageParts, { groupingFunction: grouping, components }) }) })
|
|
252
256
|
}
|
|
253
257
|
) : null
|
|
254
258
|
] }) : null
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SuperGroupingCard.js","sources":["../../../src/chat/super-grouping/SuperGroupingCard.tsx"],"sourcesContent":["'use client';\n\nimport type {\n AssistantState,\n ReasoningMessagePartComponent,\n TextMessagePartComponent,\n ThreadAssistantMessagePart,\n ToolCallMessagePartComponent,\n ToolCallMessagePartProps,\n} from '@assistant-ui/react';\nimport { MessagePrimitive, useAuiState } from '@assistant-ui/react';\nimport { isInlineTool as isRegistryInlineTool } from '@athenaintel/agent-runtime';\nimport { ChevronRight } from 'lucide-react';\nimport { type ComponentType, memo, type ReactNode, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { cn } from '../../lib/utils';\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 { createToolBasedGroupingFunction, type GroupingFunction } from './grouping-function';\nimport { ToolTimeline } from './ToolTimeline';\nimport { toTimelineStep } from './timeline-step';\nimport { defaultGetToolGroupKey, type GetToolGroupKey } from './toolkit-map';\n\nconst DEFAULT_MAX_VISIBLE_STEPS = 3;\nconst MAX_REMEMBERED_EXPANSIONS = 200;\nconst EMPTY_TIMELINE: ActivityItem[] = [];\nconst EMPTY_CONTENT: readonly ThreadAssistantMessagePart[] = [];\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 /** 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). The registry's `inline` flag by default.\n */\n isInlineTool?: (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 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 };\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\".\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 passThroughTools,\n isInlineTool = isRegistryInlineTool,\n waitingForInput = false,\n resolveToolDisplayName,\n expansionKey: expansionKeyProp,\n expandWhileWaiting = false,\n mountDetails = false,\n maxVisibleSteps = DEFAULT_MAX_VISIBLE_STEPS,\n summaryDetails,\n renderHeaderActions,\n renderRunningMeta,\n className,\n classNames,\n}: SuperGroupingCardProps) {\n const messageId = useAuiState((s) => s.message.id);\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 passThroughTools,\n });\n return items.length > 0 ? items : EMPTY_TIMELINE;\n }, [messageContent, messageStatus, waitingTools, 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) => toTimelineStep({ item, index, resolveToolDisplayName, assetTitles })),\n [timeline, resolveToolDisplayName, assetTitles],\n );\n\n const inlineParts = useMemo(() => {\n const parts: { index: number; key: string }[] = [];\n messageContent.forEach((part, index) => {\n if (part.type === 'tool-call' && isInlineTool(part.toolName)) {\n parts.push({ index, key: part.toolCallId });\n }\n });\n return parts;\n }, [messageContent, isInlineTool]);\n const grouping = useMemo(\n () =>\n excludePartsFromGroups(\n excludeFinalTextFromGroups(groupingFunction ?? createToolBasedGroupingFunction(getToolGroupKey)),\n (part) => part.type === 'tool-call' && part.toolName !== undefined && isInlineTool(part.toolName),\n ),\n [groupingFunction, getToolGroupKey, isInlineTool],\n );\n const hasDetails = useMemo(() => grouping(messageContent).length > 0, [grouping, messageContent]);\n const groupingContext = useMemo(() => ({ groupingFunction: grouping }), [grouping]);\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 const isActive = phase === 'running' || phase === 'waiting';\n const hasActivity = timeline.length > 0 || phase !== 'complete';\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);\n const label = [latestStatus, ...(isActive ? [] : (summaryDetails ?? []))].join(' · ');\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 >\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 <MessagePrimitive.Unstable_PartsGrouped groupingFunction={grouping} components={components} />\n </SuperGroupingProvider>\n </div>\n </section>\n ) : null}\n </div>\n ) : null}\n </ToolTimeline>\n {inlineParts.length > 0 ? (\n <div data-slot=\"super-grouping-inline-tools\" className=\"mt-2 flex min-w-0 flex-col gap-2\">\n {inlineParts.map(({ index, key }) => (\n <MessagePrimitive.PartByIndex key={key} index={index} components={components} />\n ))}\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":["SuperGroupingCard","isInlineTool","isRegistryInlineTool","SuperGroupingFinalText"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SuperGroupingCard.js","sources":["../../../src/chat/super-grouping/SuperGroupingCard.tsx"],"sourcesContent":["'use client';\n\nimport type {\n AssistantState,\n ReasoningMessagePartComponent,\n TextMessagePartComponent,\n ThreadAssistantMessagePart,\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 } from './grouping-function';\nimport { ToolTimeline } from './ToolTimeline';\nimport { toTimelineStep } from './timeline-step';\nimport { defaultGetToolGroupKey, type GetToolGroupKey } from './toolkit-map';\n\nconst DEFAULT_MAX_VISIBLE_STEPS = 3;\nconst MAX_REMEMBERED_EXPANSIONS = 200;\nconst EMPTY_TIMELINE: ActivityItem[] = [];\nconst EMPTY_CONTENT: readonly ThreadAssistantMessagePart[] = [];\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 /** 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 */\n isInlineTool?: (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 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 };\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\".\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 passThroughTools,\n isInlineTool = isSdkInlineTool,\n waitingForInput = false,\n resolveToolDisplayName,\n expansionKey: expansionKeyProp,\n expandWhileWaiting = false,\n mountDetails = false,\n maxVisibleSteps = DEFAULT_MAX_VISIBLE_STEPS,\n summaryDetails,\n renderHeaderActions,\n renderRunningMeta,\n className,\n classNames,\n}: SuperGroupingCardProps) {\n const messageId = useAuiState((s) => s.message.id);\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 passThroughTools,\n });\n return items.length > 0 ? items : EMPTY_TIMELINE;\n }, [messageContent, messageStatus, waitingTools, 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) => toTimelineStep({ item, index, resolveToolDisplayName, assetTitles })),\n [timeline, resolveToolDisplayName, assetTitles],\n );\n\n const inlineParts = useMemo(() => {\n const parts: { index: number; key: string }[] = [];\n messageContent.forEach((part, index) => {\n if (part.type === 'tool-call' && isInlineTool(part.toolName)) {\n parts.push({ index, key: part.toolCallId });\n }\n });\n return parts;\n }, [messageContent, isInlineTool]);\n const grouping = useMemo(\n () =>\n excludePartsFromGroups(\n excludeFinalTextFromGroups(groupingFunction ?? createToolBasedGroupingFunction(getToolGroupKey)),\n (part) => part.type === 'tool-call' && part.toolName !== undefined && isInlineTool(part.toolName),\n ),\n [groupingFunction, getToolGroupKey, isInlineTool],\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 const hasActivity = timeline.length > 0 || phase !== 'complete';\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);\n const label = [latestStatus, ...(isActive ? [] : (summaryDetails ?? []))].join(' · ');\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 >\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 <GroupedMessageParts groupingFunction={grouping} components={components} />\n </SuperGroupingProvider>\n </div>\n </section>\n ) : null}\n </div>\n ) : null}\n </ToolTimeline>\n {inlineParts.length > 0 ? (\n <div data-slot=\"super-grouping-inline-tools\" className=\"mt-2 flex min-w-0 flex-col gap-2\">\n {inlineParts.map(({ index, key }) => (\n <MessagePrimitive.PartByIndex key={key} index={index} components={components} />\n ))}\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":["SuperGroupingCard","SuperGroupingFinalText"],"mappings":"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"}
|
|
@@ -5,11 +5,13 @@ const react$1 = require("@assistant-ui/react");
|
|
|
5
5
|
const lucideReact = require("lucide-react");
|
|
6
6
|
const react = require("react");
|
|
7
7
|
const stepText = require("../../tools/step-text.cjs");
|
|
8
|
+
const inlineTools = require("../../tools/inline-tools.cjs");
|
|
8
9
|
const toolFallback = require("../../tools/tool-fallback.cjs");
|
|
9
10
|
const toolSummary = require("../../tools/tool-summary.cjs");
|
|
10
11
|
const messageTime = require("../message-time.cjs");
|
|
11
12
|
const activityTimeline = require("./activity-timeline.cjs");
|
|
12
13
|
const CollapsibleGroup = require("./CollapsibleGroup.cjs");
|
|
14
|
+
const GroupedMessageParts = require("./GroupedMessageParts.cjs");
|
|
13
15
|
const groupingFunction = require("./grouping-function.cjs");
|
|
14
16
|
const SuperGroupingCard = require("./SuperGroupingCard.cjs");
|
|
15
17
|
const ToolTimeline = require("./ToolTimeline.cjs");
|
|
@@ -17,7 +19,6 @@ const timelineStep = require("./timeline-step.cjs");
|
|
|
17
19
|
const toolkitMap = require("./toolkit-map.cjs");
|
|
18
20
|
const turnSegments = require("./turn-segments.cjs");
|
|
19
21
|
const turnTiming = require("./turn-timing.cjs");
|
|
20
|
-
const toolMetadata = require("../../agent-runtime/src/tool-metadata.cjs");
|
|
21
22
|
const cnfast = require("cnfast");
|
|
22
23
|
const DEFAULT_MAX_VISIBLE_STEPS = 6;
|
|
23
24
|
const EMPTY_CONTENT = [];
|
|
@@ -135,14 +136,17 @@ function ActivitySegment({
|
|
|
135
136
|
() => turnSegments.scopeGroupingToSegment(grouping, indicesKey.split(",").map(Number)),
|
|
136
137
|
[grouping, indicesKey]
|
|
137
138
|
);
|
|
138
|
-
const groupingContext = react.useMemo(() => ({ groupingFunction: scopedGrouping }), [scopedGrouping]);
|
|
139
|
-
const detailsPanelId = `aui-sg-segment-${react.useId().replace(/[^A-Za-z0-9_-]/g, "")}`;
|
|
140
139
|
const isTurnActive = turnPhase === "running" || turnPhase === "waiting";
|
|
140
|
+
const groupingContext = react.useMemo(
|
|
141
|
+
() => ({ groupingFunction: scopedGrouping, mountHidden: isTurnActive || mountDetails }),
|
|
142
|
+
[scopedGrouping, isTurnActive, mountDetails]
|
|
143
|
+
);
|
|
144
|
+
const detailsPanelId = `aui-sg-segment-${react.useId().replace(/[^A-Za-z0-9_-]/g, "")}`;
|
|
141
145
|
const detailsMounted = isTurnActive || mountDetails || expanded && detailsExpanded;
|
|
142
146
|
const hasToolSteps = steps.some((step) => step.kind === "tool");
|
|
143
147
|
const meta = [(_a = summary.step) == null ? void 0 : _a.chip, summary.meta].filter(Boolean).join(" · ");
|
|
144
148
|
if (steps.length === 0) {
|
|
145
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "transcript-parts", className: cnfast.cn("flex min-w-0 flex-col gap-2", classNames == null ? void 0 : classNames.detailsParts), children: /* @__PURE__ */ jsxRuntime.jsx(CollapsibleGroup.SuperGroupingProvider, { value: groupingContext, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
149
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "transcript-parts", className: cnfast.cn("flex min-w-0 flex-col gap-2", classNames == null ? void 0 : classNames.detailsParts), children: /* @__PURE__ */ jsxRuntime.jsx(CollapsibleGroup.SuperGroupingProvider, { value: groupingContext, children: /* @__PURE__ */ jsxRuntime.jsx(GroupedMessageParts.GroupedMessageParts, { groupingFunction: scopedGrouping, components }) }) });
|
|
146
150
|
}
|
|
147
151
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "activity-segment", "data-phase": phase, "data-segment-key": segment.key, className: "min-w-0", children: [
|
|
148
152
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -191,7 +195,7 @@ function ActivitySegment({
|
|
|
191
195
|
"min-w-0 overflow-hidden border-l border-border/60 py-2 pl-3",
|
|
192
196
|
classNames == null ? void 0 : classNames.details
|
|
193
197
|
),
|
|
194
|
-
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(
|
|
198
|
+
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(GroupedMessageParts.GroupedMessageParts, { groupingFunction: scopedGrouping, components }) }) })
|
|
195
199
|
}
|
|
196
200
|
) : null
|
|
197
201
|
] }) : null
|
|
@@ -208,7 +212,7 @@ const SuperGroupingTranscript = react.memo(function SuperGroupingTranscript2({
|
|
|
208
212
|
GroupComponent = CollapsibleGroup.CollapsibleGroup,
|
|
209
213
|
getToolGroupKey = toolkitMap.defaultGetToolGroupKey,
|
|
210
214
|
groupingFunction: groupingFunction$1,
|
|
211
|
-
isInlineTool =
|
|
215
|
+
isInlineTool = inlineTools.isSdkInlineTool,
|
|
212
216
|
waitingTools,
|
|
213
217
|
passThroughTools,
|
|
214
218
|
waitingForInput = false,
|