@cntyclub/agent-react 0.14.4 → 0.16.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/components/agent-voice-recorder.d.ts.map +1 -1
- package/dist/components/thinking-indicator.d.ts +4 -2
- package/dist/components/thinking-indicator.d.ts.map +1 -1
- package/dist/index.js +52 -34
- package/dist/index.js.map +1 -1
- package/dist/message-group.d.ts.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/use-agent-chat.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-voice-recorder.d.ts","sourceRoot":"","sources":["../../src/components/agent-voice-recorder.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,uBAAuB;IACtC,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,UAAU,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,4EAA4E;IAC5E,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,sEAAsE;IACtE,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;
|
|
1
|
+
{"version":3,"file":"agent-voice-recorder.d.ts","sourceRoot":"","sources":["../../src/components/agent-voice-recorder.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,uBAAuB;IACtC,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,UAAU,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,4EAA4E;IAC5E,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,sEAAsE;IACtE,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AA8BD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,uBAAuB,qBAiShH"}
|
|
@@ -7,8 +7,10 @@ export interface ThinkingIndicatorProps {
|
|
|
7
7
|
className?: string;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
* A muted "typing" bubble: a
|
|
11
|
-
* every ~1.8s, so a long tool run reads as active progress
|
|
10
|
+
* A muted "typing" bubble: a monochrome thinking orb plus an aurora-gradient
|
|
11
|
+
* phrase that rotates every ~1.8s, so a long tool run reads as active progress
|
|
12
|
+
* instead of a frozen "…". The aurora treatment lives on the TEXT only — the
|
|
13
|
+
* orb keeps the stock theme ink.
|
|
12
14
|
*/
|
|
13
15
|
export declare function ThinkingIndicator({ className, intervalMs, phrases }: ThinkingIndicatorProps): React.JSX.Element;
|
|
14
16
|
//# sourceMappingURL=thinking-indicator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thinking-indicator.d.ts","sourceRoot":"","sources":["../../src/components/thinking-indicator.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,MAAM,WAAW,sBAAsB;IACrC,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED
|
|
1
|
+
{"version":3,"file":"thinking-indicator.d.ts","sourceRoot":"","sources":["../../src/components/thinking-indicator.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,MAAM,WAAW,sBAAsB;IACrC,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,SAAS,EAAE,UAAiB,EAAE,OAAO,EAAE,EAAE,sBAAsB,qBAoClG"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { cn, Button, Tooltip, TooltipTrigger, TooltipContent, ChatMessage, ChatMessageBubble, Markdown, AuroraText, Spinner, Checkbox, Collapsible, CollapsibleTrigger, ChatToolChip, CollapsiblePanel, ChatToolCard, ChatToolCardHeader, ChatToolCardActions, Group, Menu, MenuTrigger, MenuPopup, MenuItem, ChatHeader, ChatHeaderAvatar, ChatHeaderTitle, ChatHeaderActions, Chat, ChatEmptyState, ChatEmptyStateIcon, ChatEmptyStateTitle, ChatEmptyStateDescription, ChatSuggestions, ChatSuggestion, useMediaQuery, TooltipProvider, DataTablePaged } from '@cntyclub/ui-react';
|
|
2
|
-
import { XIcon, Trash2Icon, SquareIcon, PauseIcon, PlayIcon, CheckIcon,
|
|
1
|
+
import { cn, Button, ThinkingOrb, Tooltip, TooltipTrigger, TooltipContent, ChatMessage, ChatMessageBubble, Markdown, AuroraText, Spinner, Checkbox, Collapsible, CollapsibleTrigger, ChatToolChip, CollapsiblePanel, ChatToolCard, ChatToolCardHeader, ChatToolCardActions, Group, Menu, MenuTrigger, MenuPopup, MenuItem, ChatHeader, ChatHeaderAvatar, ChatHeaderTitle, ChatHeaderActions, Chat, ChatEmptyState, ChatEmptyStateIcon, ChatEmptyStateTitle, ChatEmptyStateDescription, ChatSuggestions, ChatSuggestion, useMediaQuery, TooltipProvider, DataTablePaged } from '@cntyclub/ui-react';
|
|
2
|
+
import { XIcon, Trash2Icon, SquareIcon, PauseIcon, PlayIcon, CheckIcon, FileTextIcon, PaperclipIcon, MicIcon, ArrowUpIcon, CopyIcon, Maximize2Icon, ListChecksIcon, ChevronDownIcon, ShieldAlertIcon, CheckCheckIcon, UploadCloudIcon, HistoryIcon, SquarePenIcon, Minimize2Icon, ChevronsRightIcon, SparklesIcon, DownloadIcon, CodeIcon } from 'lucide-react';
|
|
3
3
|
import * as React11 from 'react';
|
|
4
4
|
import { AnimatePresence, motion } from 'motion/react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
@@ -312,7 +312,10 @@ function AgentImageLightbox({ src, alt, onClose }) {
|
|
|
312
312
|
document.body
|
|
313
313
|
);
|
|
314
314
|
}
|
|
315
|
-
var
|
|
315
|
+
var BAR_WIDTH = 2;
|
|
316
|
+
var BAR_GAP = 3;
|
|
317
|
+
var MAX_BARS = 1024;
|
|
318
|
+
var FADE_BARS = 12;
|
|
316
319
|
function formatClock(totalSeconds) {
|
|
317
320
|
const minutes = Math.floor(totalSeconds / 60);
|
|
318
321
|
const seconds = totalSeconds % 60;
|
|
@@ -340,7 +343,7 @@ function AgentVoiceRecorder({ maxSeconds, transcribe, onDone, onCancel, onError
|
|
|
340
343
|
const audioContextRef = React11.useRef(null);
|
|
341
344
|
const analyserRef = React11.useRef(null);
|
|
342
345
|
const rafRef = React11.useRef(null);
|
|
343
|
-
const levelsRef = React11.useRef(new Array(
|
|
346
|
+
const levelsRef = React11.useRef(new Array(MAX_BARS).fill(0));
|
|
344
347
|
const onErrorRef = React11.useRef(onError);
|
|
345
348
|
onErrorRef.current = onError;
|
|
346
349
|
const stopMeter = React11.useCallback(() => {
|
|
@@ -379,7 +382,7 @@ function AgentVoiceRecorder({ maxSeconds, transcribe, onDone, onCancel, onError
|
|
|
379
382
|
analyser.smoothingTimeConstant = 0.75;
|
|
380
383
|
source.connect(analyser);
|
|
381
384
|
analyserRef.current = analyser;
|
|
382
|
-
levelsRef.current = new Array(
|
|
385
|
+
levelsRef.current = new Array(MAX_BARS).fill(0);
|
|
383
386
|
const buffer = new Uint8Array(analyser.fftSize);
|
|
384
387
|
const draw = () => {
|
|
385
388
|
const canvas = canvasRef.current;
|
|
@@ -407,16 +410,19 @@ function AgentVoiceRecorder({ maxSeconds, transcribe, onDone, onCancel, onError
|
|
|
407
410
|
if (canvas.height !== pxHeight) canvas.height = pxHeight;
|
|
408
411
|
ctx2d.clearRect(0, 0, pxWidth, pxHeight);
|
|
409
412
|
ctx2d.fillStyle = getComputedStyle(canvas).color || "currentColor";
|
|
410
|
-
const
|
|
411
|
-
const
|
|
413
|
+
const barWidth = BAR_WIDTH * dpr;
|
|
414
|
+
const slot = (BAR_WIDTH + BAR_GAP) * dpr;
|
|
415
|
+
const count = Math.max(1, Math.min(MAX_BARS, Math.floor((pxWidth + BAR_GAP * dpr) / slot)));
|
|
412
416
|
const midY = pxHeight / 2;
|
|
413
|
-
const minBar =
|
|
417
|
+
const minBar = barWidth;
|
|
418
|
+
const maxBar = pxHeight * 0.92;
|
|
414
419
|
const radius = barWidth / 2;
|
|
415
|
-
for (let i = 0; i <
|
|
416
|
-
const value = levels[i];
|
|
417
|
-
const barHeight = Math.max(minBar, value *
|
|
418
|
-
const x =
|
|
420
|
+
for (let i = 0; i < count; i += 1) {
|
|
421
|
+
const value = levels[levels.length - count + i];
|
|
422
|
+
const barHeight = Math.max(minBar, value * maxBar);
|
|
423
|
+
const x = pxWidth - barWidth - (count - 1 - i) * slot;
|
|
419
424
|
const y = midY - barHeight / 2;
|
|
425
|
+
ctx2d.globalAlpha = Math.min(1, (i + 1) / FADE_BARS);
|
|
420
426
|
if (typeof ctx2d.roundRect === "function") {
|
|
421
427
|
ctx2d.beginPath();
|
|
422
428
|
ctx2d.roundRect(x, y, barWidth, barHeight, Math.min(radius, barHeight / 2));
|
|
@@ -425,6 +431,7 @@ function AgentVoiceRecorder({ maxSeconds, transcribe, onDone, onCancel, onError
|
|
|
425
431
|
ctx2d.fillRect(x, y, barWidth, barHeight);
|
|
426
432
|
}
|
|
427
433
|
}
|
|
434
|
+
ctx2d.globalAlpha = 1;
|
|
428
435
|
rafRef.current = requestAnimationFrame(draw);
|
|
429
436
|
};
|
|
430
437
|
rafRef.current = requestAnimationFrame(draw);
|
|
@@ -540,7 +547,7 @@ function AgentVoiceRecorder({ maxSeconds, transcribe, onDone, onCancel, onError
|
|
|
540
547
|
),
|
|
541
548
|
/* @__PURE__ */ jsx("span", { className: "font-medium tabular-nums", children: formatClock(elapsed) })
|
|
542
549
|
] }),
|
|
543
|
-
/* @__PURE__ */ jsx("canvas", { "aria-hidden": true, className: "h-6 min-w-0 flex-1 text-foreground/
|
|
550
|
+
/* @__PURE__ */ jsx("canvas", { "aria-hidden": true, className: "h-6 min-w-0 flex-1 text-foreground/70", ref: canvasRef }),
|
|
544
551
|
/* @__PURE__ */ jsx(Button, { "aria-label": "Discard recording", onClick: onCancel, size: "icon-sm", type: "button", variant: "ghost", children: /* @__PURE__ */ jsx(Trash2Icon, {}) }),
|
|
545
552
|
/* @__PURE__ */ jsx(Button, { "aria-label": "Stop recording", onClick: stopRecording, size: "icon-sm", type: "button", children: /* @__PURE__ */ jsx(SquareIcon, {}) })
|
|
546
553
|
] }) : null,
|
|
@@ -552,8 +559,8 @@ function AgentVoiceRecorder({ maxSeconds, transcribe, onDone, onCancel, onError
|
|
|
552
559
|
/* @__PURE__ */ jsx(Button, { "aria-label": "Discard recording", onClick: onCancel, size: "icon-sm", type: "button", variant: "ghost", children: /* @__PURE__ */ jsx(Trash2Icon, {}) }),
|
|
553
560
|
/* @__PURE__ */ jsx(Button, { "aria-label": "Use recording", className: "rounded-full before:rounded-full", onClick: () => void confirm(), size: "icon-sm", type: "button", children: /* @__PURE__ */ jsx(CheckIcon, {}) })
|
|
554
561
|
] }) : null,
|
|
555
|
-
phase === "transcribing" ? /* @__PURE__ */ jsxs("span", { className:
|
|
556
|
-
/* @__PURE__ */ jsx(
|
|
562
|
+
phase === "transcribing" ? /* @__PURE__ */ jsxs("span", { className: "flex flex-1 items-center gap-2 text-muted-foreground text-sm", children: [
|
|
563
|
+
/* @__PURE__ */ jsx(ThinkingOrb, { className: "shrink-0", size: 20, speed: 1, state: "working" }),
|
|
557
564
|
"Transcribing\u2026"
|
|
558
565
|
] }) : null
|
|
559
566
|
]
|
|
@@ -809,14 +816,14 @@ function groupMessages(messages) {
|
|
|
809
816
|
for (const message of messages) {
|
|
810
817
|
if (message.role === "user") {
|
|
811
818
|
flush();
|
|
812
|
-
items.push({ key: message.id, kind: "user", message });
|
|
819
|
+
items.push({ key: message.client_key ?? message.id, kind: "user", message });
|
|
813
820
|
continue;
|
|
814
821
|
}
|
|
815
822
|
if (message.role === "assistant") {
|
|
816
823
|
const hasText = Boolean(message.content && message.content.trim());
|
|
817
824
|
if (hasText) {
|
|
818
825
|
flush();
|
|
819
|
-
items.push({ key: message.id, kind: "assistant-text", message });
|
|
826
|
+
items.push({ key: message.client_key ?? message.id, kind: "assistant-text", message });
|
|
820
827
|
}
|
|
821
828
|
for (const toolCall of message.tool_calls ?? []) {
|
|
822
829
|
const callId2 = toolCall.id ?? `${message.id}-${toolCall.name}`;
|
|
@@ -1029,18 +1036,7 @@ function ThinkingIndicator({ className, intervalMs = 1800, phrases }) {
|
|
|
1029
1036
|
"data-slot": "thinking-indicator",
|
|
1030
1037
|
role: "status",
|
|
1031
1038
|
children: [
|
|
1032
|
-
/* @__PURE__ */ jsx(
|
|
1033
|
-
"span",
|
|
1034
|
-
{
|
|
1035
|
-
"aria-hidden": "true",
|
|
1036
|
-
className: "size-4 shrink-0 animate-spin rounded-full [animation-duration:900ms]",
|
|
1037
|
-
style: {
|
|
1038
|
-
background: "conic-gradient(from 0deg, #FF0080, #7928CA, #0070F3, #38bdf8, #FF0080)",
|
|
1039
|
-
WebkitMask: "radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px))",
|
|
1040
|
-
mask: "radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px))"
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
),
|
|
1039
|
+
/* @__PURE__ */ jsx(ThinkingOrb, { className: "shrink-0", size: 20, speed: 0.7, state: "solving" }),
|
|
1044
1040
|
/* @__PURE__ */ jsx(
|
|
1045
1041
|
"span",
|
|
1046
1042
|
{
|
|
@@ -1897,8 +1893,16 @@ function useAgentChat(config) {
|
|
|
1897
1893
|
if (response.messages?.length) {
|
|
1898
1894
|
setMessages((current) => {
|
|
1899
1895
|
const settled = current.filter((message) => !message.id.startsWith(OPTIMISTIC_ID_PREFIX));
|
|
1896
|
+
const optimistic = current.filter((message) => message.id.startsWith(OPTIMISTIC_ID_PREFIX));
|
|
1900
1897
|
const seen = new Set(settled.map((message) => message.id));
|
|
1901
1898
|
const fresh = response.messages?.filter((message) => !seen.has(message.id)) ?? [];
|
|
1899
|
+
const placeholder = optimistic[optimistic.length - 1];
|
|
1900
|
+
if (placeholder) {
|
|
1901
|
+
const echoIndex = fresh.findIndex((message) => message.role === "user");
|
|
1902
|
+
if (echoIndex !== -1) {
|
|
1903
|
+
fresh[echoIndex] = { ...fresh[echoIndex], client_key: placeholder.client_key ?? placeholder.id };
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1902
1906
|
return [...settled, ...fresh];
|
|
1903
1907
|
});
|
|
1904
1908
|
}
|
|
@@ -1918,8 +1922,13 @@ function useAgentChat(config) {
|
|
|
1918
1922
|
case "user_message":
|
|
1919
1923
|
setMessages((current) => {
|
|
1920
1924
|
const settled = current.filter((message) => !message.id.startsWith(OPTIMISTIC_ID_PREFIX));
|
|
1921
|
-
|
|
1922
|
-
|
|
1925
|
+
if (settled.some((message) => message.id === event.message.id)) return settled;
|
|
1926
|
+
const optimistic = current.filter((message) => message.id.startsWith(OPTIMISTIC_ID_PREFIX));
|
|
1927
|
+
const placeholder = optimistic[optimistic.length - 1];
|
|
1928
|
+
if (!placeholder) return [...settled, event.message];
|
|
1929
|
+
return current.filter((message) => !message.id.startsWith(OPTIMISTIC_ID_PREFIX) || message.id === placeholder.id).map(
|
|
1930
|
+
(message) => message.id === placeholder.id ? { ...event.message, client_key: placeholder.client_key ?? placeholder.id } : message
|
|
1931
|
+
);
|
|
1923
1932
|
});
|
|
1924
1933
|
break;
|
|
1925
1934
|
case "text_delta": {
|
|
@@ -1947,9 +1956,18 @@ function useAgentChat(config) {
|
|
|
1947
1956
|
const streamingId = ctx.streamingId;
|
|
1948
1957
|
ctx.streamingId = null;
|
|
1949
1958
|
setMessages((current) => {
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1959
|
+
if (current.some((message) => message.id === event.message.id)) {
|
|
1960
|
+
return streamingId ? current.filter((message) => message.id !== streamingId) : current;
|
|
1961
|
+
}
|
|
1962
|
+
if (streamingId) {
|
|
1963
|
+
const index = current.findIndex((message) => message.id === streamingId);
|
|
1964
|
+
if (index !== -1) {
|
|
1965
|
+
const next = [...current];
|
|
1966
|
+
next[index] = { ...event.message, client_key: streamingId };
|
|
1967
|
+
return next;
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
return [...current, event.message];
|
|
1953
1971
|
});
|
|
1954
1972
|
break;
|
|
1955
1973
|
}
|