@alexkroman1/aai-ui 5.5.1 → 5.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chat-view-CqRGHImR.js → chat-view-DFBmX5eX.js} +1 -1
- package/dist/components/chat-view.js +1 -1
- package/dist/components/markdown.d.ts +12 -2
- package/dist/components/message-list.d.ts +1 -1
- package/dist/components/message-list.js +1 -1
- package/dist/components/tool-call-block.d.ts +5 -4
- package/dist/components/tool-call-block.js +1 -1
- package/dist/components/tool-call-row.d.ts +51 -0
- package/dist/default-client/assets/{audio-CQHMQr4-.js → audio-v_cWeUOV.js} +1 -1
- package/dist/default-client/assets/{capture-processor-BRTP9wp5.js → capture-processor-kAhuEwHv.js} +1 -1
- package/dist/default-client/assets/index-CuPmIAbL.css +2 -0
- package/dist/default-client/assets/index-fLjOiK97.js +192 -0
- package/dist/default-client/assets/{playback-processor-D2xR7szm.js → playback-processor-X5id-na1.js} +1 -1
- package/dist/default-client/index.html +2 -2
- package/dist/define-client.js +3 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.js +5 -5
- package/dist/{message-list-CdtrNi4w.js → message-list-DkAHoB3A.js} +38 -66
- package/dist/{session-core-KY9B5nqn.js → session-core-DqibBzJz.js} +6 -1
- package/dist/session-core-types.d.ts +11 -0
- package/dist/session-core.js +1 -1
- package/dist/{tool-call-block-C--Bj04_.js → tool-call-block-BjemDFB9.js} +116 -73
- package/package.json +3 -2
- package/dist/default-client/assets/index-C99SRlSn.js +0 -192
- package/dist/default-client/assets/index-CRfdZPH1.css +0 -2
package/dist/default-client/assets/{playback-processor-D2xR7szm.js → playback-processor-X5id-na1.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{i as e}from"./index-
|
|
1
|
+
import{i as e}from"./index-fLjOiK97.js";import{t}from"./_module-url-BX0RuRU2.js";var n=t(`
|
|
2
2
|
class PlaybackProcessor extends AudioWorkletProcessor {
|
|
3
3
|
constructor(options) {
|
|
4
4
|
super();
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
<title>aai</title>
|
|
7
7
|
<link rel="icon" href="./favicon.ico" />
|
|
8
8
|
<style>html, body { background: #FBF8F2; margin: 0; }</style>
|
|
9
|
-
<script type="module" crossorigin src="./assets/index-
|
|
10
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
9
|
+
<script type="module" crossorigin src="./assets/index-fLjOiK97.js"></script>
|
|
10
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CuPmIAbL.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
13
13
|
<main id="app"></main>
|
package/dist/define-client.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { r as fetchClientConfig, t as createSessionCore } from "./session-core-
|
|
1
|
+
import { r as fetchClientConfig, t as createSessionCore } from "./session-core-DqibBzJz.js";
|
|
2
2
|
import { SessionProvider, ThemeProvider } from "./context.js";
|
|
3
|
-
import { t as ChatView } from "./chat-view-
|
|
3
|
+
import { t as ChatView } from "./chat-view-DFBmX5eX.js";
|
|
4
4
|
import { t as pageBaseUrl } from "./_utils-CsqbIVGI.js";
|
|
5
|
-
import { n as ToolConfigContext } from "./tool-call-block-
|
|
5
|
+
import { n as ToolConfigContext } from "./tool-call-block-BjemDFB9.js";
|
|
6
6
|
import { SidebarLayout } from "./components/sidebar-layout.js";
|
|
7
7
|
import { StartScreen } from "./components/start-screen.js";
|
|
8
8
|
import { createElement, useEffect, useState } from "react";
|
package/dist/index.d.ts
CHANGED
|
@@ -2,10 +2,11 @@ export { buildAgentUrl, type ClientConfigResponse, fetchClientConfig, loadClient
|
|
|
2
2
|
export { Button, type ButtonSize, type ButtonVariant } from "./components/button.tsx";
|
|
3
3
|
export { ChatView } from "./components/chat-view.tsx";
|
|
4
4
|
export { Controls } from "./components/controls.tsx";
|
|
5
|
-
export { Markdown } from "./components/markdown.tsx";
|
|
5
|
+
export { Markdown, type MarkdownVariant } from "./components/markdown.tsx";
|
|
6
6
|
export { MessageList } from "./components/message-list.tsx";
|
|
7
7
|
export { SidebarLayout } from "./components/sidebar-layout.tsx";
|
|
8
8
|
export { StartScreen } from "./components/start-screen.tsx";
|
|
9
|
+
export { ToolCallRow, type ToolCallRowProps, type ToolCallRowVariant, } from "./components/tool-call-row.tsx";
|
|
9
10
|
export type { ToolDisplayConfig } from "./components/tool-config-context.ts";
|
|
10
11
|
export { ToolConfigContext } from "./components/tool-config-context.ts";
|
|
11
12
|
export { ApiUrlChip, SessionUrlChips, UiUrlChip } from "./components/url-chips.tsx";
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { i as loadClientConfig, n as buildAgentUrl, r as fetchClientConfig, t as createSessionCore } from "./session-core-
|
|
1
|
+
import { i as loadClientConfig, n as buildAgentUrl, r as fetchClientConfig, t as createSessionCore } from "./session-core-DqibBzJz.js";
|
|
2
2
|
import { SessionProvider, ThemeProvider, useSession, useSessionSelector, useTheme } from "./context.js";
|
|
3
3
|
import { Button } from "./components/button.js";
|
|
4
|
-
import { t as ChatView } from "./chat-view-
|
|
4
|
+
import { t as ChatView } from "./chat-view-DFBmX5eX.js";
|
|
5
5
|
import { i as UiUrlChip, n as ApiUrlChip, r as SessionUrlChips, t as Controls } from "./controls-CoBO6sId.js";
|
|
6
|
-
import { n as Markdown, t as MessageList } from "./message-list-
|
|
7
|
-
import { n as ToolConfigContext } from "./tool-call-block-
|
|
6
|
+
import { n as Markdown, t as MessageList } from "./message-list-DkAHoB3A.js";
|
|
7
|
+
import { n as ToolConfigContext, r as ToolCallRow } from "./tool-call-block-BjemDFB9.js";
|
|
8
8
|
import { SidebarLayout } from "./components/sidebar-layout.js";
|
|
9
9
|
import { StartScreen } from "./components/start-screen.js";
|
|
10
10
|
import { VOICE_CAPTURE_CONSTRAINTS } from "./types.js";
|
|
11
11
|
import { client } from "./define-client.js";
|
|
12
12
|
import { useAgentState, useEvent, useToolCallStart, useToolResult } from "./hooks.js";
|
|
13
|
-
export { ApiUrlChip, Button, ChatView, Controls, Markdown, MessageList, SessionProvider, SessionUrlChips, SidebarLayout, StartScreen, ThemeProvider, ToolConfigContext, UiUrlChip, VOICE_CAPTURE_CONSTRAINTS, buildAgentUrl, client, createSessionCore, fetchClientConfig, loadClientConfig, useAgentState, useEvent, useSession, useSessionSelector, useTheme, useToolCallStart, useToolResult };
|
|
13
|
+
export { ApiUrlChip, Button, ChatView, Controls, Markdown, MessageList, SessionProvider, SessionUrlChips, SidebarLayout, StartScreen, ThemeProvider, ToolCallRow, ToolConfigContext, UiUrlChip, VOICE_CAPTURE_CONSTRAINTS, buildAgentUrl, client, createSessionCore, fetchClientConfig, loadClientConfig, useAgentState, useEvent, useSession, useSessionSelector, useTheme, useToolCallStart, useToolResult };
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { useSessionSelector, useTheme } from "./context.js";
|
|
2
2
|
import { i as TEXT_MUTED, n as SURFACE_TINT, o as primaryTint, r as TEXT_FAINT } from "./_colors-Bfh3-BVE.js";
|
|
3
|
-
import { t as ToolCallBlock } from "./tool-call-block-
|
|
3
|
+
import { t as ToolCallBlock } from "./tool-call-block-BjemDFB9.js";
|
|
4
4
|
import clsx from "clsx";
|
|
5
|
-
import { memo,
|
|
5
|
+
import { memo, useMemo } from "react";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { StickToBottom } from "use-stick-to-bottom";
|
|
7
8
|
import ReactMarkdown from "react-markdown";
|
|
8
9
|
import remarkGfm from "remark-gfm";
|
|
9
10
|
//#region components/markdown.tsx
|
|
@@ -34,6 +35,22 @@ function escapeBareListMarkers(text) {
|
|
|
34
35
|
return line;
|
|
35
36
|
}).join("\n");
|
|
36
37
|
}
|
|
38
|
+
const SCALE_CLASSES = {
|
|
39
|
+
default: {
|
|
40
|
+
h1: "mt-3 mb-1.5 text-[17px] font-semibold",
|
|
41
|
+
h2: "mt-3 mb-1.5 text-[16px] font-semibold",
|
|
42
|
+
h3: "mt-3 mb-1.5 text-[15px] font-semibold",
|
|
43
|
+
code: "text-[12.5px]",
|
|
44
|
+
table: "my-1.5 w-full border-collapse text-sm"
|
|
45
|
+
},
|
|
46
|
+
compact: {
|
|
47
|
+
h1: "mt-3 mb-1.5 text-[15px] font-medium",
|
|
48
|
+
h2: "mt-3 mb-1.5 text-[14px] font-medium",
|
|
49
|
+
h3: "mt-3 mb-1.5 text-[13px] font-medium",
|
|
50
|
+
code: "text-[11px]",
|
|
51
|
+
table: "my-1.5 w-full border-collapse text-[12px]"
|
|
52
|
+
}
|
|
53
|
+
};
|
|
37
54
|
/**
|
|
38
55
|
* Agent prose, rendered as Markdown.
|
|
39
56
|
*
|
|
@@ -41,6 +58,8 @@ function escapeBareListMarkers(text) {
|
|
|
41
58
|
* this they arrived as literal asterisks and backticks. Styling is
|
|
42
59
|
* per-element (theme colors via inline styles, spacing via Tailwind) so it
|
|
43
60
|
* stays on the default client's type scale and follows custom themes.
|
|
61
|
+
* The optional `variant` selects the type scale (see
|
|
62
|
+
* {@link MarkdownVariant}).
|
|
44
63
|
* GFM is on for tables and strikethrough. react-markdown does not render
|
|
45
64
|
* raw HTML unless rehype-raw is added — keep it that way, this text comes
|
|
46
65
|
* from a model.
|
|
@@ -50,8 +69,9 @@ function escapeBareListMarkers(text) {
|
|
|
50
69
|
*
|
|
51
70
|
* @public
|
|
52
71
|
*/
|
|
53
|
-
const Markdown = memo(function Markdown({ text }) {
|
|
72
|
+
const Markdown = memo(function Markdown({ text, variant = "default" }) {
|
|
54
73
|
const theme = useTheme();
|
|
74
|
+
const scale = SCALE_CLASSES[variant];
|
|
55
75
|
const components = useMemo(() => ({
|
|
56
76
|
p: (props) => /* @__PURE__ */ jsx("p", {
|
|
57
77
|
className: "my-1.5 first:mt-0 last:mb-0",
|
|
@@ -70,15 +90,15 @@ const Markdown = memo(function Markdown({ text }) {
|
|
|
70
90
|
...props
|
|
71
91
|
}),
|
|
72
92
|
h1: (props) => /* @__PURE__ */ jsx("h1", {
|
|
73
|
-
className:
|
|
93
|
+
className: scale.h1,
|
|
74
94
|
...props
|
|
75
95
|
}),
|
|
76
96
|
h2: (props) => /* @__PURE__ */ jsx("h2", {
|
|
77
|
-
className:
|
|
97
|
+
className: scale.h2,
|
|
78
98
|
...props
|
|
79
99
|
}),
|
|
80
100
|
h3: (props) => /* @__PURE__ */ jsx("h3", {
|
|
81
|
-
className:
|
|
101
|
+
className: scale.h3,
|
|
82
102
|
...props
|
|
83
103
|
}),
|
|
84
104
|
a: ({ style, ...props }) => /* @__PURE__ */ jsx("a", {
|
|
@@ -93,11 +113,11 @@ const Markdown = memo(function Markdown({ text }) {
|
|
|
93
113
|
}),
|
|
94
114
|
code: ({ className, style, children, ...rest }) => {
|
|
95
115
|
return /language-/.test(className ?? "") ? /* @__PURE__ */ jsx("code", {
|
|
96
|
-
className: "font-aai-mono
|
|
116
|
+
className: clsx("font-aai-mono", scale.code),
|
|
97
117
|
...rest,
|
|
98
118
|
children
|
|
99
119
|
}) : /* @__PURE__ */ jsx("code", {
|
|
100
|
-
className: "rounded-sm border px-1 py-0.5 font-aai-mono
|
|
120
|
+
className: clsx("rounded-sm border px-1 py-0.5 font-aai-mono", scale.code),
|
|
101
121
|
style: {
|
|
102
122
|
borderColor: theme.border,
|
|
103
123
|
background: SURFACE_TINT,
|
|
@@ -126,7 +146,7 @@ const Markdown = memo(function Markdown({ text }) {
|
|
|
126
146
|
...props
|
|
127
147
|
}),
|
|
128
148
|
table: (props) => /* @__PURE__ */ jsx("table", {
|
|
129
|
-
className:
|
|
149
|
+
className: scale.table,
|
|
130
150
|
...props
|
|
131
151
|
}),
|
|
132
152
|
th: ({ style, ...props }) => /* @__PURE__ */ jsx("th", {
|
|
@@ -153,7 +173,7 @@ const Markdown = memo(function Markdown({ text }) {
|
|
|
153
173
|
},
|
|
154
174
|
...props
|
|
155
175
|
})
|
|
156
|
-
}), [theme]);
|
|
176
|
+
}), [theme, scale]);
|
|
157
177
|
return /* @__PURE__ */ jsx(ReactMarkdown, {
|
|
158
178
|
remarkPlugins: [remarkGfm],
|
|
159
179
|
components,
|
|
@@ -233,53 +253,6 @@ const MessageBubble = memo(function MessageBubble({ message, theme }) {
|
|
|
233
253
|
});
|
|
234
254
|
});
|
|
235
255
|
/**
|
|
236
|
-
* How close to the bottom (px) the container must be for auto-scroll to stay
|
|
237
|
-
* engaged. Generous enough that an in-flight smooth scroll doesn't unpin.
|
|
238
|
-
*/
|
|
239
|
-
const NEAR_BOTTOM_PX = 96;
|
|
240
|
-
/**
|
|
241
|
-
* Smooth-scroll to the anchor whenever the content version advances — but
|
|
242
|
-
* only while the container is pinned near the bottom. A user who scrolled up
|
|
243
|
-
* to read history isn't yanked back down by streaming updates; scrolling back
|
|
244
|
-
* to the bottom re-engages the auto-scroll.
|
|
245
|
-
*
|
|
246
|
-
* The scroll runs inside `requestAnimationFrame` and is deduped per frame:
|
|
247
|
-
* several snapshot updates in one frame (transcript + message + tool call)
|
|
248
|
-
* trigger a single scroll after layout instead of one forced layout each.
|
|
249
|
-
*
|
|
250
|
-
* While a partial transcript is streaming, updates arrive faster than a
|
|
251
|
-
* smooth scroll finishes — each restart leaves the animation perpetually
|
|
252
|
-
* mid-flight — so `streaming` switches to an instant jump; committed-content
|
|
253
|
-
* updates keep the smooth animation.
|
|
254
|
-
*/
|
|
255
|
-
function useAutoScroll(contentVersion, streaming) {
|
|
256
|
-
const anchorRef = useRef(null);
|
|
257
|
-
const pinnedRef = useRef(true);
|
|
258
|
-
const scheduledRef = useRef(false);
|
|
259
|
-
const streamingRef = useRef(streaming);
|
|
260
|
-
streamingRef.current = streaming;
|
|
261
|
-
const onScroll = useCallback((event) => {
|
|
262
|
-
const el = event.currentTarget;
|
|
263
|
-
pinnedRef.current = el.scrollTop + el.clientHeight >= el.scrollHeight - NEAR_BOTTOM_PX;
|
|
264
|
-
}, []);
|
|
265
|
-
useEffect(() => {
|
|
266
|
-
if (contentVersion === 0 || scheduledRef.current || !pinnedRef.current) return;
|
|
267
|
-
scheduledRef.current = true;
|
|
268
|
-
requestAnimationFrame(() => {
|
|
269
|
-
scheduledRef.current = false;
|
|
270
|
-
if (!pinnedRef.current) return;
|
|
271
|
-
anchorRef.current?.scrollIntoView({
|
|
272
|
-
behavior: streamingRef.current ? "instant" : "smooth",
|
|
273
|
-
block: "end"
|
|
274
|
-
});
|
|
275
|
-
});
|
|
276
|
-
}, [contentVersion]);
|
|
277
|
-
return {
|
|
278
|
-
anchorRef,
|
|
279
|
-
onScroll
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
256
|
* Interleave messages and tool calls into render items, ordered by insertion
|
|
284
257
|
* time. Each tool call renders immediately after its anchor message
|
|
285
258
|
* (`afterMessageId`); tool calls whose anchor slid out of the retained window
|
|
@@ -323,7 +296,7 @@ function interleave(messages, toolCalls, renderMessage, renderToolCall) {
|
|
|
323
296
|
* }
|
|
324
297
|
* ```
|
|
325
298
|
*
|
|
326
|
-
* @param className - Additional CSS class names applied to the
|
|
299
|
+
* @param className - Additional CSS class names applied to the outer list container.
|
|
327
300
|
*
|
|
328
301
|
* @public
|
|
329
302
|
*/
|
|
@@ -333,7 +306,6 @@ const MessageList = memo(function MessageList({ className }) {
|
|
|
333
306
|
const toolCalls = useSessionSelector((s) => s.toolCalls);
|
|
334
307
|
const userTranscript = useSessionSelector((s) => s.userTranscript);
|
|
335
308
|
const agentTranscript = useSessionSelector((s) => s.agentTranscript);
|
|
336
|
-
const contentVersion = useSessionSelector((s) => s.contentVersion);
|
|
337
309
|
const theme = useTheme();
|
|
338
310
|
const showThinking = useMemo(() => {
|
|
339
311
|
if (state !== "thinking") return false;
|
|
@@ -346,7 +318,6 @@ const MessageList = memo(function MessageList({ className }) {
|
|
|
346
318
|
toolCalls,
|
|
347
319
|
messages
|
|
348
320
|
]);
|
|
349
|
-
const { anchorRef, onScroll } = useAutoScroll(contentVersion, userTranscript !== null);
|
|
350
321
|
const streamingMessage = useMemo(() => agentTranscript ? {
|
|
351
322
|
role: "assistant",
|
|
352
323
|
content: agentTranscript
|
|
@@ -359,12 +330,14 @@ const MessageList = memo(function MessageList({ className }) {
|
|
|
359
330
|
toolCalls,
|
|
360
331
|
theme
|
|
361
332
|
]);
|
|
362
|
-
return /* @__PURE__ */ jsx(
|
|
333
|
+
return /* @__PURE__ */ jsx(StickToBottom, {
|
|
363
334
|
role: "log",
|
|
364
|
-
className: clsx("flex-1
|
|
335
|
+
className: clsx("flex-1 min-h-0", className),
|
|
365
336
|
style: { background: theme.surface },
|
|
366
|
-
|
|
367
|
-
|
|
337
|
+
initial: "instant",
|
|
338
|
+
resize: "smooth",
|
|
339
|
+
children: /* @__PURE__ */ jsxs(StickToBottom.Content, {
|
|
340
|
+
scrollClassName: "overflow-y-auto [scrollbar-width:none]",
|
|
368
341
|
className: "flex flex-col gap-4 p-7",
|
|
369
342
|
children: [
|
|
370
343
|
items,
|
|
@@ -377,8 +350,7 @@ const MessageList = memo(function MessageList({ className }) {
|
|
|
377
350
|
color: "#6F6A60",
|
|
378
351
|
children: userTranscript ? userTranscript : /* @__PURE__ */ jsx(ThinkingDots, {})
|
|
379
352
|
}),
|
|
380
|
-
showThinking && /* @__PURE__ */ jsx(ThinkingDots, {})
|
|
381
|
-
/* @__PURE__ */ jsx("div", { ref: anchorRef })
|
|
353
|
+
showThinking && /* @__PURE__ */ jsx(ThinkingDots, {})
|
|
382
354
|
]
|
|
383
355
|
})
|
|
384
356
|
});
|
|
@@ -375,6 +375,9 @@ function createMessageHandlers(deps) {
|
|
|
375
375
|
case "error":
|
|
376
376
|
handleErrorEvent(e);
|
|
377
377
|
break;
|
|
378
|
+
case "idle_timeout":
|
|
379
|
+
deps.conn.retiredByServer = true;
|
|
380
|
+
break;
|
|
378
381
|
default: break;
|
|
379
382
|
}
|
|
380
383
|
}
|
|
@@ -591,6 +594,7 @@ function createSessionCore(options) {
|
|
|
591
594
|
}
|
|
592
595
|
const conn = {
|
|
593
596
|
ws: null,
|
|
597
|
+
retiredByServer: false,
|
|
594
598
|
voiceIO: null,
|
|
595
599
|
audioSetupInFlight: false,
|
|
596
600
|
generation: createEpoch(),
|
|
@@ -714,6 +718,7 @@ function createSessionCore(options) {
|
|
|
714
718
|
loadAudioModules().catch(() => {});
|
|
715
719
|
teardownConnection();
|
|
716
720
|
conn.generation.bump();
|
|
721
|
+
conn.retiredByServer = false;
|
|
717
722
|
const controller = new AbortController();
|
|
718
723
|
connectionController = controller;
|
|
719
724
|
const { signal: sig } = controller;
|
|
@@ -735,7 +740,7 @@ function createSessionCore(options) {
|
|
|
735
740
|
socket.addEventListener("close", () => {
|
|
736
741
|
if (sig.aborted) return;
|
|
737
742
|
cleanupAudio();
|
|
738
|
-
if (reconnectPending(socket)) {
|
|
743
|
+
if (!conn.retiredByServer && reconnectPending(socket)) {
|
|
739
744
|
conn.generation.bump();
|
|
740
745
|
socketErrored = false;
|
|
741
746
|
updateState({
|
|
@@ -140,6 +140,17 @@ export type SessionCoreOptions = VoiceSessionOptions;
|
|
|
140
140
|
*/
|
|
141
141
|
export type ConnState = {
|
|
142
142
|
ws: InstanceType<WebSocketConstructor> | null;
|
|
143
|
+
/**
|
|
144
|
+
* The server retired this session for idleness (`idle_timeout`), so the
|
|
145
|
+
* close that follows is EXPECTED and must not be retried.
|
|
146
|
+
*
|
|
147
|
+
* Without this the automatic reconnect would immediately re-open the
|
|
148
|
+
* session the server just reclaimed — a tab left open would cycle forever
|
|
149
|
+
* and the guest would never see zero sessions, which is the whole point of
|
|
150
|
+
* the timeout. Reconnecting is the user's call from here (the controls
|
|
151
|
+
* reconnect on demand).
|
|
152
|
+
*/
|
|
153
|
+
retiredByServer: boolean;
|
|
143
154
|
voiceIO: VoiceIO | null;
|
|
144
155
|
audioSetupInFlight: boolean;
|
|
145
156
|
/** Connection epoch, bumped on each connect()/retry (see `createEpoch`).
|
package/dist/session-core.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createSessionCore } from "./session-core-
|
|
1
|
+
import { t as createSessionCore } from "./session-core-DqibBzJz.js";
|
|
2
2
|
export { createSessionCore };
|
|
@@ -4,7 +4,92 @@ import { t as Eyebrow } from "./eyebrow-C6ZFuiz6.js";
|
|
|
4
4
|
import { n as truncate, r as tryParseJSON } from "./_utils-CsqbIVGI.js";
|
|
5
5
|
import clsx from "clsx";
|
|
6
6
|
import { createContext, memo, useContext, useMemo, useState } from "react";
|
|
7
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
//#region components/tool-call-row.tsx
|
|
9
|
+
/** @jsxImportSource react */
|
|
10
|
+
const VARIANT_CLASSES = {
|
|
11
|
+
default: {
|
|
12
|
+
button: "gap-2.5 px-3.5 py-2.5",
|
|
13
|
+
title: "text-[13px]",
|
|
14
|
+
chevron: "text-[10px]"
|
|
15
|
+
},
|
|
16
|
+
compact: {
|
|
17
|
+
button: "gap-2 px-3 py-2",
|
|
18
|
+
title: "text-[11px]",
|
|
19
|
+
chevron: "text-[9px]"
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The design system's console row for one tool invocation: a small outlined
|
|
24
|
+
* "TOOL" chip (or a custom `icon`), the tool title in mono, a truncated
|
|
25
|
+
* detail preview, and a rotating chevron that expands to the panel content.
|
|
26
|
+
*
|
|
27
|
+
* Purely presentational — callers own the mapping from their tool-call data
|
|
28
|
+
* to `title`/`detail`/`pending` and the expanded panel. The deployed agent
|
|
29
|
+
* UI's message list renders it via its tool-call block, and the studio's
|
|
30
|
+
* chat transcript renders it with `variant="compact"`, so the two surfaces
|
|
31
|
+
* read as one component.
|
|
32
|
+
*
|
|
33
|
+
* Colors come from the nearest theme context (see {@link useTheme}); without
|
|
34
|
+
* a provider the default AssemblyAI theme applies.
|
|
35
|
+
*
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
38
|
+
function ToolCallRow({ title, detail, pending = false, icon, variant = "default", className, children }) {
|
|
39
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
40
|
+
const theme = useTheme();
|
|
41
|
+
const sizes = VARIANT_CLASSES[variant];
|
|
42
|
+
const canExpand = children != null;
|
|
43
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
44
|
+
className: clsx("flex flex-col rounded-md border overflow-hidden", className),
|
|
45
|
+
style: {
|
|
46
|
+
borderColor: theme.border,
|
|
47
|
+
background: theme.bg
|
|
48
|
+
},
|
|
49
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
50
|
+
type: "button",
|
|
51
|
+
"aria-expanded": canExpand ? isOpen : void 0,
|
|
52
|
+
disabled: !canExpand,
|
|
53
|
+
className: clsx("flex items-center select-none text-left w-full appearance-none border-none bg-transparent", sizes.button, canExpand && "cursor-pointer"),
|
|
54
|
+
onClick: () => {
|
|
55
|
+
if (canExpand) setIsOpen(!isOpen);
|
|
56
|
+
},
|
|
57
|
+
children: [
|
|
58
|
+
icon ? /* @__PURE__ */ jsx("span", {
|
|
59
|
+
className: "w-4 h-4 shrink-0 text-center leading-4",
|
|
60
|
+
children: icon
|
|
61
|
+
}) : /* @__PURE__ */ jsx(Eyebrow, {
|
|
62
|
+
className: "shrink-0",
|
|
63
|
+
style: { color: TEXT_FAINT },
|
|
64
|
+
children: "Tool"
|
|
65
|
+
}),
|
|
66
|
+
/* @__PURE__ */ jsx("span", {
|
|
67
|
+
className: clsx("shrink-0 font-aai-mono font-medium", sizes.title, pending && "tool-shimmer"),
|
|
68
|
+
style: { color: theme.text },
|
|
69
|
+
children: title
|
|
70
|
+
}),
|
|
71
|
+
/* @__PURE__ */ jsx("span", {
|
|
72
|
+
className: clsx("font-aai-mono truncate flex-1 min-w-0", sizes.title),
|
|
73
|
+
style: { color: TEXT_FAINT },
|
|
74
|
+
children: detail
|
|
75
|
+
}),
|
|
76
|
+
canExpand && /* @__PURE__ */ jsx("span", {
|
|
77
|
+
className: clsx("shrink-0 transition-transform duration-150", sizes.chevron, isOpen && "rotate-90"),
|
|
78
|
+
style: { color: "#6F6A60" },
|
|
79
|
+
children: "▶"
|
|
80
|
+
})
|
|
81
|
+
]
|
|
82
|
+
}), isOpen && canExpand && /* @__PURE__ */ jsx("div", {
|
|
83
|
+
className: "border-t max-h-64 overflow-auto",
|
|
84
|
+
style: {
|
|
85
|
+
borderColor: theme.border,
|
|
86
|
+
background: theme.surface
|
|
87
|
+
},
|
|
88
|
+
children
|
|
89
|
+
})]
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
8
93
|
//#region components/tool-config-context.ts
|
|
9
94
|
/**
|
|
10
95
|
* Context for tool display configuration. Installed by `client()` from
|
|
@@ -29,10 +114,10 @@ function formatResult(result) {
|
|
|
29
114
|
return parsed === result ? result : JSON.stringify(parsed, null, 2);
|
|
30
115
|
}
|
|
31
116
|
/**
|
|
32
|
-
* Renders a tool invocation as the design system's console row
|
|
33
|
-
* outlined "TOOL" chip (or the tool's configured
|
|
34
|
-
* mono, a truncated args preview, and a rotating
|
|
35
|
-
* formatted result.
|
|
117
|
+
* Renders a tool invocation as the design system's console row (see
|
|
118
|
+
* `ToolCallRow`): a small outlined "TOOL" chip (or the tool's configured
|
|
119
|
+
* icon), the tool name in mono, a truncated args preview, and a rotating
|
|
120
|
+
* chevron that expands the formatted result.
|
|
36
121
|
*
|
|
37
122
|
* Tool display is configured via `ToolConfigContext`. If no config is found
|
|
38
123
|
* for a tool name, the raw tool name is shown as the title.
|
|
@@ -50,7 +135,6 @@ function formatResult(result) {
|
|
|
50
135
|
* @internal Not exported from the package — rendered by `MessageList`.
|
|
51
136
|
*/
|
|
52
137
|
const ToolCallBlock = memo(function ToolCallBlock({ toolCall, className }) {
|
|
53
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
54
138
|
const theme = useTheme();
|
|
55
139
|
const toolConfig = useToolConfig();
|
|
56
140
|
const config = Object.hasOwn(toolConfig, toolCall.name) ? toolConfig[toolCall.name] : void 0;
|
|
@@ -59,75 +143,34 @@ const ToolCallBlock = memo(function ToolCallBlock({ toolCall, className }) {
|
|
|
59
143
|
const icon = config?.icon;
|
|
60
144
|
const canExpand = !isPending && Boolean(toolCall.result);
|
|
61
145
|
const formatted = useMemo(() => toolCall.result ? formatResult(toolCall.result) : "", [toolCall.result]);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
type: "button",
|
|
80
|
-
"aria-expanded": canExpand ? isOpen : void 0,
|
|
81
|
-
disabled: isPending,
|
|
82
|
-
className: clsx("flex items-center gap-2.5 px-3.5 py-2.5 select-none text-left w-full appearance-none border-none bg-transparent", canExpand && "cursor-pointer"),
|
|
83
|
-
onClick: () => {
|
|
84
|
-
if (canExpand) setIsOpen(!isOpen);
|
|
85
|
-
},
|
|
86
|
-
children: [
|
|
87
|
-
icon ? /* @__PURE__ */ jsx("span", {
|
|
88
|
-
className: "w-4 h-4 shrink-0 text-center leading-4",
|
|
89
|
-
children: icon
|
|
90
|
-
}) : /* @__PURE__ */ jsx(Eyebrow, {
|
|
91
|
-
className: "shrink-0",
|
|
92
|
-
style: { color: TEXT_FAINT },
|
|
93
|
-
children: "Tool"
|
|
94
|
-
}),
|
|
95
|
-
/* @__PURE__ */ jsx("span", {
|
|
96
|
-
className: clsx("font-aai-mono text-[13px] font-medium", isPending && "tool-shimmer"),
|
|
97
|
-
style: { color: theme.text },
|
|
98
|
-
children: title
|
|
99
|
-
}),
|
|
100
|
-
/* @__PURE__ */ jsx("span", {
|
|
101
|
-
className: "font-aai-mono text-[13px] truncate flex-1 min-w-0",
|
|
102
|
-
style: { color: TEXT_FAINT },
|
|
103
|
-
children: subtitle
|
|
104
|
-
}),
|
|
105
|
-
canExpand && /* @__PURE__ */ jsx("span", {
|
|
106
|
-
className: clsx("text-[10px] shrink-0 transition-transform duration-150", isOpen && "rotate-90"),
|
|
107
|
-
style: { color: "#6F6A60" },
|
|
108
|
-
children: "▶"
|
|
109
|
-
})
|
|
110
|
-
]
|
|
111
|
-
}), isOpen && /* @__PURE__ */ jsxs("div", {
|
|
112
|
-
className: "border-t max-h-64 overflow-auto",
|
|
146
|
+
return /* @__PURE__ */ jsx(ToolCallRow, {
|
|
147
|
+
title,
|
|
148
|
+
detail: useMemo(() => {
|
|
149
|
+
const args = toolCall.args;
|
|
150
|
+
if (toolCall.name === "run_code" && args.code) return truncate(String(args.code).split("\n")[0] ?? "");
|
|
151
|
+
for (const key of [
|
|
152
|
+
"query",
|
|
153
|
+
"url",
|
|
154
|
+
"question"
|
|
155
|
+
]) if (args[key]) return String(args[key]);
|
|
156
|
+
return truncate(JSON.stringify(args));
|
|
157
|
+
}, [toolCall.name, toolCall.args]),
|
|
158
|
+
pending: isPending,
|
|
159
|
+
icon,
|
|
160
|
+
className,
|
|
161
|
+
children: canExpand ? /* @__PURE__ */ jsxs(Fragment, { children: [toolCall.name === "run_code" && Boolean(toolCall.args.code) && /* @__PURE__ */ jsx("pre", {
|
|
162
|
+
className: "font-aai-mono text-xs px-3.5 py-3 m-0 whitespace-pre-wrap wrap-break-word border-b",
|
|
113
163
|
style: {
|
|
114
|
-
|
|
115
|
-
|
|
164
|
+
color: theme.text,
|
|
165
|
+
borderColor: theme.border
|
|
116
166
|
},
|
|
117
|
-
children:
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
children: String(toolCall.args.code)
|
|
124
|
-
}), formatted && /* @__PURE__ */ jsx("pre", {
|
|
125
|
-
className: "font-aai-mono text-xs px-3.5 py-3 m-0 whitespace-pre-wrap wrap-break-word",
|
|
126
|
-
style: { color: "#57534B" },
|
|
127
|
-
children: formatted
|
|
128
|
-
})]
|
|
129
|
-
})]
|
|
167
|
+
children: String(toolCall.args.code)
|
|
168
|
+
}), formatted && /* @__PURE__ */ jsx("pre", {
|
|
169
|
+
className: "font-aai-mono text-xs px-3.5 py-3 m-0 whitespace-pre-wrap wrap-break-word",
|
|
170
|
+
style: { color: "#57534B" },
|
|
171
|
+
children: formatted
|
|
172
|
+
})] }) : void 0
|
|
130
173
|
});
|
|
131
174
|
});
|
|
132
175
|
//#endregion
|
|
133
|
-
export { ToolConfigContext as n, ToolCallBlock as t };
|
|
176
|
+
export { ToolConfigContext as n, ToolCallRow as r, ToolCallBlock as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alexkroman1/aai-ui",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -21,8 +21,9 @@
|
|
|
21
21
|
"partysocket": "^1.3.0",
|
|
22
22
|
"react-markdown": "^10.1.0",
|
|
23
23
|
"remark-gfm": "^4.0.1",
|
|
24
|
+
"use-stick-to-bottom": "^1.1.6",
|
|
24
25
|
"use-sync-external-store": "^1.6.0",
|
|
25
|
-
"@alexkroman1/aai": "5.
|
|
26
|
+
"@alexkroman1/aai": "5.7.0"
|
|
26
27
|
},
|
|
27
28
|
"peerDependencies": {
|
|
28
29
|
"react": "^19.0.0",
|