@ensembleapp/client-sdk 0.0.54 → 0.0.56
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 +79 -2
- package/dist/index.d.ts +38 -11
- package/dist/index.js +54 -12
- package/dist/index.js.map +1 -1
- package/dist/widget/widget.global.js +69 -69
- package/dist/widget/widget.global.js.map +1 -1
- package/lib/chat/ChatWidget.css +15 -0
- package/package.json +15 -15
package/README.md
CHANGED
|
@@ -63,6 +63,80 @@ function CustomChat() {
|
|
|
63
63
|
}
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
### Reading token usage
|
|
67
|
+
|
|
68
|
+
The server streams token/usage stats as a `data-usage` part. You can read them
|
|
69
|
+
three ways.
|
|
70
|
+
|
|
71
|
+
**1. `<ChatWidget>`: the `onUsage` callback**
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
import { ChatWidget, type ChatUsageData } from '@ensembleapp/client-sdk'
|
|
75
|
+
|
|
76
|
+
<ChatWidget
|
|
77
|
+
api={{ baseUrl: '/api', token: 'your-jwt-token' }}
|
|
78
|
+
agentId="agent-234"
|
|
79
|
+
threadId="user-123"
|
|
80
|
+
onUsage={(usage: ChatUsageData) => {
|
|
81
|
+
console.log(usage.inputTokens, usage.outputTokens)
|
|
82
|
+
console.log(usage.totalMessageCount, usage.messageHistoryLimit)
|
|
83
|
+
}}
|
|
84
|
+
/>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Or, to render the built-in counter (`↑ N in · ↓ N out`) above the input without
|
|
88
|
+
writing any code, set `showTokenUsage`:
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
<ChatWidget api={/* ... */} agentId="..." threadId="..." showTokenUsage />
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**2. `useChat` hook: the `usage` return value**
|
|
95
|
+
|
|
96
|
+
`usage` is reactive state (the latest turn), so it's the simplest way to render:
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
import { useChat, type ChatUsageData } from '@ensembleapp/client-sdk'
|
|
100
|
+
|
|
101
|
+
function CustomChat() {
|
|
102
|
+
const { messages, sendMessage, usage } = useChat({ /* ...config */ })
|
|
103
|
+
// ^^^^^ ChatUsageData | null
|
|
104
|
+
|
|
105
|
+
return <div>{usage && `${usage.inputTokens} in / ${usage.outputTokens} out`}</div>
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
You can also pass `onUsage` to the hook if you prefer the event style.
|
|
110
|
+
|
|
111
|
+
**3. `extractUsageData`: for custom stream handling**
|
|
112
|
+
|
|
113
|
+
If you handle the stream at a lower level (e.g. via `onData`), pull usage out of
|
|
114
|
+
any data part:
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
import { extractUsageData } from '@ensembleapp/client-sdk'
|
|
118
|
+
|
|
119
|
+
onData: (dataPart) => {
|
|
120
|
+
const usage = extractUsageData(dataPart) // ChatUsageData | null
|
|
121
|
+
if (usage) { /* ... */ }
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**`ChatUsageData` shape**
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
interface ChatUsageData {
|
|
129
|
+
inputTokens: number
|
|
130
|
+
outputTokens: number
|
|
131
|
+
maxInputTokens?: number
|
|
132
|
+
maxOutputTokens?: number
|
|
133
|
+
inputTokensPercent?: number
|
|
134
|
+
outputTokensPercent?: number
|
|
135
|
+
totalMessageCount?: number
|
|
136
|
+
messageHistoryLimit?: number
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
66
140
|
## API Reference
|
|
67
141
|
|
|
68
142
|
### ChatWidget Props
|
|
@@ -72,6 +146,9 @@ function CustomChat() {
|
|
|
72
146
|
- `onMessage?` (function): Callback when a new message is received
|
|
73
147
|
- `onError?` (function): Callback when an error occurs
|
|
74
148
|
- `onFinish?` (function): Callback when a conversation finishes
|
|
149
|
+
- `onUsage?` ((usage: ChatUsageData) => void): Callback with token/usage stats as they stream
|
|
150
|
+
- `onData?` ((dataPart) => void): Callback for every raw stream data part
|
|
151
|
+
- `showTokenUsage?` (boolean): Show the built-in input/output token counter above the input (default: false)
|
|
75
152
|
- `className?` (string): Additional CSS classes
|
|
76
153
|
- `placeholder?` (string): Input placeholder text
|
|
77
154
|
- `welcomeMessage?` (string): Initial welcome message
|
|
@@ -81,10 +158,10 @@ function CustomChat() {
|
|
|
81
158
|
```tsx
|
|
82
159
|
const {
|
|
83
160
|
messages, // Array of chat messages
|
|
84
|
-
|
|
85
|
-
isError, // Boolean indicating if there's an error
|
|
161
|
+
status, // Current request status
|
|
86
162
|
sendMessage, // Function to send a message
|
|
87
163
|
stop, // Function to stop current request
|
|
88
164
|
setMessages, // Function to manually set messages
|
|
165
|
+
usage, // ChatUsageData | null (latest token/usage stats)
|
|
89
166
|
} = useChat(config)
|
|
90
167
|
```
|
package/dist/index.d.ts
CHANGED
|
@@ -63,6 +63,35 @@ interface ApiConfig {
|
|
|
63
63
|
/** Agent version selector: 'latest' (default), 'published', or a specific version number */
|
|
64
64
|
type AgentVersion = 'latest' | 'published' | number;
|
|
65
65
|
type StructuredMessagePayload = Record<string, unknown>;
|
|
66
|
+
/**
|
|
67
|
+
* Usage stats emitted by the server as a `data-usage` stream part and delivered
|
|
68
|
+
* to the {@link UseChatConfig.onUsage} callback.
|
|
69
|
+
*/
|
|
70
|
+
interface ChatUsageData {
|
|
71
|
+
inputTokens: number;
|
|
72
|
+
outputTokens: number;
|
|
73
|
+
maxInputTokens?: number;
|
|
74
|
+
maxOutputTokens?: number;
|
|
75
|
+
inputTokensPercent?: number;
|
|
76
|
+
outputTokensPercent?: number;
|
|
77
|
+
/** Total number of messages in the conversation so far */
|
|
78
|
+
totalMessageCount?: number;
|
|
79
|
+
/** Maximum number of messages allowed in conversation history */
|
|
80
|
+
messageHistoryLimit?: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Extract usage stats from a stream data part. The server wraps usage as
|
|
84
|
+
* `{ type: 'data-usage', data: { ...ChatUsageData } }`; returns the full inner
|
|
85
|
+
* payload (including totalMessageCount / messageHistoryLimit) or null if the
|
|
86
|
+
* part is not a usage part.
|
|
87
|
+
*/
|
|
88
|
+
declare function extractUsageData(dataPart: unknown): ChatUsageData | null;
|
|
89
|
+
/**
|
|
90
|
+
* Build the GET /chat/messages URL for loading initial history. Appends
|
|
91
|
+
* `?limit=<n>` when `messagesToLoad` is provided (a positive number), otherwise
|
|
92
|
+
* returns the base URL so the server default applies.
|
|
93
|
+
*/
|
|
94
|
+
declare function buildMessagesUrl(baseUrl: string, messagesToLoad?: number): string;
|
|
66
95
|
type UseChatConfig = DeprecatedChatConfig & {
|
|
67
96
|
/** The server API configuration */
|
|
68
97
|
api: ApiConfig;
|
|
@@ -74,23 +103,18 @@ type UseChatConfig = DeprecatedChatConfig & {
|
|
|
74
103
|
agentVersion?: AgentVersion;
|
|
75
104
|
/** additional context (anything) that needs to be passed to the LLM */
|
|
76
105
|
dataContext?: unknown;
|
|
106
|
+
/** Number of most-recent messages to load into the chat on open/reload. Defaults to the server's default. */
|
|
107
|
+
messagesToLoad?: number;
|
|
77
108
|
onError?: (error: Error) => void;
|
|
78
109
|
/** Called when API returns 401/unauthorized (e.g., token expiry). Return a new token to retry the request. */
|
|
79
110
|
onAuthError?: () => Promise<string | null>;
|
|
80
111
|
onFinish?: (message: any) => void;
|
|
81
112
|
onData?: (data: any) => void;
|
|
82
113
|
onMessage?: (message: UIMessage) => void;
|
|
83
|
-
/** Called when usage data is received (
|
|
84
|
-
onUsage?: (usage:
|
|
85
|
-
inputTokens: number;
|
|
86
|
-
outputTokens: number;
|
|
87
|
-
maxInputTokens?: number;
|
|
88
|
-
maxOutputTokens?: number;
|
|
89
|
-
inputTokensPercent?: number;
|
|
90
|
-
outputTokensPercent?: number;
|
|
91
|
-
}) => void;
|
|
114
|
+
/** Called when usage data is received (token counts/percentages and message-history stats) */
|
|
115
|
+
onUsage?: (usage: ChatUsageData) => void;
|
|
92
116
|
};
|
|
93
|
-
declare function useChat({ api, threadId, agentId, agentVersion, agentExecutionId, dataContext, onError, onAuthError, onFinish, onData, onMessage, onUsage, }: UseChatConfig): {
|
|
117
|
+
declare function useChat({ api, threadId, agentId, agentVersion, agentExecutionId, dataContext, messagesToLoad, onError, onAuthError, onFinish, onData, onMessage, onUsage, }: UseChatConfig): {
|
|
94
118
|
messages: ChatMessage[];
|
|
95
119
|
status: ai.ChatStatus;
|
|
96
120
|
isLoadingInitial: boolean;
|
|
@@ -121,6 +145,7 @@ declare function useChat({ api, threadId, agentId, agentVersion, agentExecutionI
|
|
|
121
145
|
addToolApprovalResponse: ai.ChatAddToolApproveResponseFunction;
|
|
122
146
|
pendingToolOutput: PendingToolOutput | null;
|
|
123
147
|
pendingToolApproval: PendingToolApproval | null;
|
|
148
|
+
usage: ChatUsageData | null;
|
|
124
149
|
};
|
|
125
150
|
|
|
126
151
|
/** Matches POST /api/tools/:toolId/invoke request body */
|
|
@@ -414,6 +439,8 @@ interface ChatWidgetConfig extends UseChatConfig {
|
|
|
414
439
|
widgets?: AnyUIWidgetDefinition[];
|
|
415
440
|
/** Feedback options for assistant messages. Enabled by default. */
|
|
416
441
|
feedback?: ChatWidgetFeedbackOptions;
|
|
442
|
+
/** Show a compact input/output token counter (from the server's usage data). Default: false. */
|
|
443
|
+
showTokenUsage?: boolean;
|
|
417
444
|
}
|
|
418
445
|
declare const ChatWidget: React.ForwardRefExoticComponent<ChatWidgetConfig & React.RefAttributes<ChatWidgetHandle>>;
|
|
419
446
|
|
|
@@ -642,4 +669,4 @@ declare const getVendorCardsWidget: (isProd?: boolean) => SDKUIWidgetDefinition[
|
|
|
642
669
|
|
|
643
670
|
declare function cn(...inputs: ClassValue[]): string;
|
|
644
671
|
|
|
645
|
-
export { type AgentVersion, type AnyUIWidgetDefinition, type ApiConfig, type ApprovalUIConfig, BriefDisplayMode, BriefDisplayMode as BriefRenderer, type ChatMessage, type ChatMessageSection, ChatWidget, type ChatWidgetFeedbackOptions, type ChatWidgetHandle, type ChatWidgetConfig as ChatWidgetProps, type ChatWidgetSpeechToTextOptions, type ChatWidgetStyles, type ChatWidgetVoiceOptions, type CustomerReactDOM, type DisplayMode, type DisplayModeProps, type EmbeddableChatWidgetConfig, type EnrichedResults, type FeedbackConfig, type FeedbackHandlers, type FetchApprovalConfigOptions, FullDisplayMode, FullDisplayMode as FullRenderer, HideToolsDisplayMode, HideToolsDisplayMode as HideToolsRenderer, type InvokeTool, type MessageContext, MessageRenderer, type MessageRendererProps, type PendingToolApproval, type PendingToolOutput, type PopupAnchorConfig, PopupChatWidget, type PopupChatWidgetProps, type DisplayModeProps as RendererProps, type SDKUIWidgetDefinition, SDK_WIDGET_MARKER, type StructuredMessagePayload, type SubmitFeedbackParams, TagGroupDisplay, type TagGroupDisplayProps, ToolCallDisplay, type ToolCallDisplayProps, type ToolInvokeRequest, type ToolInvokeResult, type ToolPart, type UIMessagePart, type UIWidgetDefinition, type UseChatConfig, type UseFeedbackConfig, type WidgetRenderOptions, cn, createSDKWidget, createWidget, defaultChatWidgets, fetchApprovalConfig, getVendorCardsWidget, isSDKWidget, registerChatWidgets, transformMessage, useChat, useFeedback };
|
|
672
|
+
export { type AgentVersion, type AnyUIWidgetDefinition, type ApiConfig, type ApprovalUIConfig, BriefDisplayMode, BriefDisplayMode as BriefRenderer, type ChatMessage, type ChatMessageSection, type ChatUsageData, ChatWidget, type ChatWidgetFeedbackOptions, type ChatWidgetHandle, type ChatWidgetConfig as ChatWidgetProps, type ChatWidgetSpeechToTextOptions, type ChatWidgetStyles, type ChatWidgetVoiceOptions, type CustomerReactDOM, type DisplayMode, type DisplayModeProps, type EmbeddableChatWidgetConfig, type EnrichedResults, type FeedbackConfig, type FeedbackHandlers, type FetchApprovalConfigOptions, FullDisplayMode, FullDisplayMode as FullRenderer, HideToolsDisplayMode, HideToolsDisplayMode as HideToolsRenderer, type InvokeTool, type MessageContext, MessageRenderer, type MessageRendererProps, type PendingToolApproval, type PendingToolOutput, type PopupAnchorConfig, PopupChatWidget, type PopupChatWidgetProps, type DisplayModeProps as RendererProps, type SDKUIWidgetDefinition, SDK_WIDGET_MARKER, type StructuredMessagePayload, type SubmitFeedbackParams, TagGroupDisplay, type TagGroupDisplayProps, ToolCallDisplay, type ToolCallDisplayProps, type ToolInvokeRequest, type ToolInvokeResult, type ToolPart, type UIMessagePart, type UIWidgetDefinition, type UseChatConfig, type UseFeedbackConfig, type WidgetRenderOptions, buildMessagesUrl, cn, createSDKWidget, createWidget, defaultChatWidgets, extractUsageData, fetchApprovalConfig, getVendorCardsWidget, isSDKWidget, registerChatWidgets, transformMessage, useChat, useFeedback };
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ function styleInject(css, { insertAt } = {}) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
// lib/chat/ChatWidget.css
|
|
24
|
-
styleInject(':root[data-chat-widget],\n[data-chat-widget] {\n --chat-primary: #3b82f6;\n --chat-primary-text: #ffffff;\n --chat-primary-hover: #2563eb;\n --chat-primary-subtle: rgba(59, 130, 246, 0.1);\n --chat-background: #ffffff;\n --chat-background-secondary: #f9fafb;\n --chat-background-tertiary: #f3f4f6;\n --chat-border: #e5e7eb;\n --chat-border-light: #f3f4f6;\n --chat-widget-border-width: 1px;\n --chat-text: #111827;\n --chat-text-secondary: #4b5563;\n --chat-text-muted: #6b7280;\n --chat-text-disabled: #9ca3af;\n --chat-link: #2563eb;\n --chat-link-hover: #1d4ed8;\n --chat-success: #22c55e;\n --chat-success-bg: rgba(34, 197, 94, 0.1);\n --chat-error: #ef4444;\n --chat-error-bg: rgba(239, 68, 68, 0.1);\n --chat-header-text: #ffffff;\n --chat-user-text: #ffffff;\n --chat-assistant-bg: transparent;\n --chat-assistant-text: var(--chat-text);\n --chat-input-bg: var(--chat-background);\n --chat-input-text: var(--chat-text);\n --chat-input-placeholder: var(--chat-text-muted);\n --chat-thought-border: var(--chat-border);\n --chat-font-family:\n "Inter",\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n sans-serif;\n --chat-radius: 0.75rem;\n --chat-font-size: 0.925rem;\n --chat-thought-font-size: 0.75rem;\n --chat-shadow: 0 20px 45px rgba(0, 0, 0, 0.12);\n --chat-shadow-sm: 0 4px 12px rgba(0, 0, 0, 0.1);\n --chat-overlay-bg: rgba(0, 0, 0, 0.3);\n}\n.chat-widget {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 24rem;\n background: var(--chat-background);\n border: var(--chat-widget-border-width) solid var(--chat-border);\n border-radius: 0;\n box-shadow: var(--chat-shadow);\n overflow: hidden;\n font-family: var(--chat-font-family);\n color: var(--chat-assistant-text);\n}\n.chat-widget--popup-content {\n border: 0;\n border-radius: inherit;\n box-shadow: none;\n min-height: 0;\n}\n.chat-widget__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 40px;\n padding: 0.75rem 1rem;\n background: var(--chat-primary);\n color: var(--chat-header-text);\n}\n.chat-widget__title {\n margin: 0;\n font-size: 0.875rem;\n font-weight: 600;\n}\n.chat-widget__messages {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 1rem;\n display: flex;\n flex-direction: column;\n gap: 1rem;\n min-width: 0;\n}\n.chat-widget__message {\n display: flex;\n flex-direction: column;\n gap: 0;\n min-width: 0;\n}\n.chat-widget__message-row {\n display: flex;\n min-width: 0;\n}\n.chat-widget__message-row--user {\n justify-content: flex-end;\n}\n.chat-widget__message-row--assistant {\n justify-content: flex-start;\n}\n.chat-widget__bubble {\n max-width: 90%;\n padding: 0.5rem 0.25rem;\n border-radius: calc(var(--chat-radius) * 0.65);\n font-size: var(--chat-font-size);\n min-width: 0;\n overflow-x: hidden;\n}\n.chat-widget__bubble--user {\n background: var(--chat-primary);\n color: var(--chat-user-text);\n border-bottom-right-radius: 0.35rem;\n padding-left: 0.375rem;\n padding-right: 0.375rem;\n}\n.chat-widget__bubble--assistant {\n width: 90%;\n max-width: 90%;\n background: var(--chat-assistant-bg);\n color: var(--chat-assistant-text);\n border-bottom-left-radius: 0.35rem;\n}\n.chat-widget__widget {\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow-x: hidden;\n}\n.widget-customer-root {\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow-x: hidden;\n}\n.chat-widget__markdown {\n white-space: normal;\n font-size: var(--chat-font-size);\n}\n.chat-widget__markdown h1 {\n font-size: calc(var(--chat-font-size) * 1.4);\n}\n.chat-widget__markdown h2 {\n font-size: calc(var(--chat-font-size) * 1.25);\n}\n.chat-widget__markdown h3 {\n font-size: calc(var(--chat-font-size) * 1.1);\n}\n.chat-widget__markdown h4 {\n font-size: calc(var(--chat-font-size) * 1.05);\n}\n.chat-widget__markdown h5 {\n font-size: calc(var(--chat-font-size) * 1);\n}\n.chat-widget__markdown h6 {\n font-size: calc(var(--chat-font-size) * 0.95);\n}\n.chat-widget__anchor-button {\n position: fixed;\n bottom: 20px;\n right: 20px;\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.65rem 0.85rem;\n background: var(--chat-primary);\n color: var(--chat-primary-text);\n border: none;\n border-radius: 999px;\n box-shadow: var(--chat-shadow);\n cursor: pointer;\n font-weight: 600;\n z-index: 99999;\n}\n.chat-widget__anchor-button:hover {\n background: var(--chat-primary-hover);\n}\n.chat-widget__anchor--left {\n right: auto;\n left: 20px;\n}\n.chat-widget__anchor-icon {\n width: 1.1rem;\n height: 1.1rem;\n}\n.chat-widget__popup {\n position: fixed;\n bottom: 80px;\n right: 20px;\n z-index: 99998;\n}\n.chat-widget__anchor--left.chat-widget__popup {\n right: auto;\n left: 20px;\n}\n.chat-widget__popup-inner {\n width: 384px;\n max-width: calc(100vw - 40px);\n height: 500px;\n max-height: calc(100vh - 140px);\n box-shadow: var(--chat-shadow);\n border-radius: 12px;\n overflow: hidden;\n}\n.chat-widget__markdown a {\n color: var(--chat-link);\n text-decoration: underline;\n}\n.chat-widget__markdown a:hover {\n color: var(--chat-link-hover);\n}\n.chat-widget__markdown table {\n width: 100%;\n border-collapse: collapse;\n margin: 0.5rem 0;\n}\n.chat-widget__markdown th,\n.chat-widget__markdown td {\n border: 1px solid var(--chat-border);\n padding: 0.5rem;\n text-align: left;\n vertical-align: top;\n}\n.chat-widget__markdown thead th {\n background: var(--chat-assistant-bg);\n color: var(--chat-assistant-text);\n font-weight: 600;\n}\n.chat-widget__thoughts {\n min-width: 0;\n --chat-font-size: var(--chat-thought-font-size);\n}\n.chat-widget__details {\n border: 0;\n}\n.chat-widget__thoughts-summary {\n list-style: none;\n display: flex;\n align-items: center;\n gap: 0.35rem;\n cursor: pointer;\n color: var(--chat-text-muted);\n font-size: 0.8125rem;\n}\n.chat-widget__thoughts-summary:hover {\n color: var(--chat-assistant-text);\n}\n.chat-widget__thoughts-icon-container {\n display: flex;\n border: 1px solid var(--chat-border);\n border-radius: 999px;\n align-items: center;\n justify-content: center;\n width: 1rem;\n height: 1rem;\n}\n.chat-widget__thoughts-icon {\n width: 0.75rem;\n height: 0.75rem;\n transition: transform 0.2s ease;\n}\n.chat-widget__details[open] .chat-widget__thoughts-icon {\n transform: rotate(90deg);\n}\n.chat-widget__thoughts-content {\n margin-top: 0.5rem;\n margin-left: 0.4rem;\n padding: 0.75rem;\n border-left: 2px solid var(--chat-thought-border);\n border-color: var(--chat-primary);\n max-width: 100%;\n overflow-x: auto;\n}\n.chat-widget__thoughts-text {\n margin: 0;\n line-height: 1.5;\n color: var(--chat-text-secondary);\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n "Liberation Mono",\n "Courier New",\n monospace;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-wrap: anywhere;\n display: block;\n}\n.chat-widget__loading {\n display: flex;\n justify-content: flex-start;\n}\n.chat-widget__loading-bubble {\n background: var(--chat-assistant-bg);\n color: var(--chat-assistant-text);\n border-radius: calc(var(--chat-radius) * 0.65);\n border-bottom-left-radius: 0.35rem;\n padding: 0.5rem 0.75rem;\n}\n.chat-widget__loading-dots {\n display: flex;\n gap: 0.35rem;\n}\n.chat-widget__loading-dot {\n width: 0.5rem;\n height: 0.5rem;\n border-radius: 999px;\n background: var(--chat-text-disabled);\n animation: chat-widget-bounce 1s infinite ease-in-out;\n}\n.chat-widget__loading-dot[data-delay="1"] {\n animation-delay: 0.1s;\n}\n.chat-widget__loading-dot[data-delay="2"] {\n animation-delay: 0.2s;\n}\n@keyframes chat-widget-bounce {\n 0%, 80%, 100% {\n transform: scale(0.6);\n opacity: 0.4;\n }\n 40% {\n transform: scale(1);\n opacity: 1;\n }\n}\n.chat-widget__input {\n border-top: 1px solid var(--chat-border);\n padding: 0.25rem 0 0.75rem;\n background: var(--chat-input-bg);\n}\n.chat-widget__form {\n position: relative;\n}\n.chat-widget__textarea {\n width: 100%;\n border: 0;\n padding: 0.75rem 5.25rem 0.75rem 0.75rem;\n background: transparent;\n font-size: 0.925rem;\n resize: none;\n color: var(--chat-input-text);\n font-family: inherit;\n}\n.chat-widget__textarea::-moz-placeholder {\n color: var(--chat-input-placeholder);\n}\n.chat-widget__textarea::placeholder {\n color: var(--chat-input-placeholder);\n}\n.chat-widget__textarea:focus-visible {\n outline: none;\n}\n.chat-widget__textarea:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.chat-widget__toolbar {\n position: absolute;\n top: 0;\n right: 3.75rem;\n height: 100%;\n display: flex;\n align-items: center;\n padding: 0 0.5rem;\n border-right: 1px solid var(--chat-border);\n}\n.chat-widget__submit {\n position: absolute;\n top: 50%;\n right: 0.75rem;\n transform: translateY(-50%);\n background: transparent;\n border: 0;\n width: 2.5rem;\n height: 2.5rem;\n display: grid;\n place-items: center;\n color: var(--chat-primary);\n cursor: pointer;\n}\n.chat-widget__submit:disabled {\n color: var(--chat-text-disabled);\n cursor: not-allowed;\n}\n.chat-widget__submit:not(:disabled):hover {\n color: var(--chat-primary-hover);\n}\n.chat-widget__send-icon {\n width: 1.2rem;\n height: 1.2rem;\n}\n.chat-widget__mic-button {\n position: relative;\n border: none;\n background: transparent;\n width: 2.25rem;\n height: 2.25rem;\n display: grid;\n place-items: center;\n color: var(--chat-primary);\n cursor: pointer;\n border-radius: 999px;\n}\n.chat-widget__mic-button:disabled {\n color: var(--chat-text-disabled);\n cursor: not-allowed;\n}\n.chat-widget__mic-button--active {\n color: var(--chat-primary-hover);\n background: var(--chat-primary-subtle);\n}\n.chat-widget__mic-icon {\n width: 1rem;\n height: 1rem;\n}\n.chat-widget__mic-bar {\n position: absolute;\n bottom: 0.1rem;\n left: 50%;\n width: 16px;\n height: 2px;\n border-radius: 999px;\n background: var(--chat-border);\n overflow: hidden;\n display: block;\n transform: translateX(-50%);\n pointer-events: none;\n}\n.chat-widget__mic-bar-fill {\n display: block;\n width: 100%;\n height: 100%;\n background: currentColor;\n transform-origin: left;\n transition: transform 0.12s linear;\n}\n.chat-widget__voice {\n display: flex;\n margin-top: 0.25rem;\n}\n.chat-widget__voice-button {\n border: none;\n background: none;\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.1rem 0;\n font-size: 0.8rem;\n font-weight: 500;\n color: var(--chat-primary);\n cursor: pointer;\n}\n.chat-widget__voice-button:disabled {\n color: var(--chat-text-disabled);\n cursor: not-allowed;\n}\n.chat-widget__voice-button--active {\n color: var(--chat-primary-hover);\n}\n.chat-widget__voice-icon {\n width: 0.95rem;\n height: 0.95rem;\n}\n.chat-widget__voice-icon--spin {\n animation: chat-widget-spin 1s linear infinite;\n}\n@keyframes chat-widget-spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n.chat-widget__collapsed {\n position: relative;\n margin-bottom: 0.25rem;\n}\n.chat-widget__collapsed-content {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows 300ms ease-out;\n}\n.chat-widget__collapsed-content--expanded {\n grid-template-rows: 1fr;\n}\n.chat-widget__collapsed-content-inner {\n overflow: hidden;\n}\n.chat-widget__collapsed-preview {\n position: relative;\n max-height: 1.5em;\n overflow: hidden;\n opacity: 0.6;\n pointer-events: none;\n transition: opacity 300ms ease-out, max-height 300ms ease-out;\n}\n.chat-widget__collapsed-preview--hidden {\n opacity: 0;\n max-height: 0;\n pointer-events: none;\n}\n.chat-widget__collapsed-gradient {\n position: absolute;\n top: 0;\n right: 0;\n width: 70%;\n height: 100%;\n background:\n linear-gradient(\n to right,\n transparent 0%,\n var(--chat-background) 90%);\n pointer-events: none;\n}\n.chat-widget__collapsed-toggle {\n display: inline-block;\n padding: 0;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--chat-primary);\n background: transparent;\n border: none;\n cursor: pointer;\n}\n.chat-widget__collapsed-toggle:hover {\n text-decoration: underline;\n}\n@keyframes chat-widget-slide-up {\n from {\n opacity: 1;\n transform: translateY(0);\n max-height: 200px;\n }\n to {\n opacity: 0.6;\n transform: translateY(-8px);\n max-height: 1.5em;\n }\n}\n.chat-widget__collapsed--animating .chat-widget__collapsed-preview {\n animation: chat-widget-slide-up 300ms ease-out forwards;\n}\n');
|
|
24
|
+
styleInject(':root[data-chat-widget],\n[data-chat-widget] {\n --chat-primary: #3b82f6;\n --chat-primary-text: #ffffff;\n --chat-primary-hover: #2563eb;\n --chat-primary-subtle: rgba(59, 130, 246, 0.1);\n --chat-background: #ffffff;\n --chat-background-secondary: #f9fafb;\n --chat-background-tertiary: #f3f4f6;\n --chat-border: #e5e7eb;\n --chat-border-light: #f3f4f6;\n --chat-widget-border-width: 1px;\n --chat-text: #111827;\n --chat-text-secondary: #4b5563;\n --chat-text-muted: #6b7280;\n --chat-text-disabled: #9ca3af;\n --chat-link: #2563eb;\n --chat-link-hover: #1d4ed8;\n --chat-success: #22c55e;\n --chat-success-bg: rgba(34, 197, 94, 0.1);\n --chat-error: #ef4444;\n --chat-error-bg: rgba(239, 68, 68, 0.1);\n --chat-header-text: #ffffff;\n --chat-user-text: #ffffff;\n --chat-assistant-bg: transparent;\n --chat-assistant-text: var(--chat-text);\n --chat-input-bg: var(--chat-background);\n --chat-input-text: var(--chat-text);\n --chat-input-placeholder: var(--chat-text-muted);\n --chat-thought-border: var(--chat-border);\n --chat-font-family:\n "Inter",\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n sans-serif;\n --chat-radius: 0.75rem;\n --chat-font-size: 0.925rem;\n --chat-thought-font-size: 0.75rem;\n --chat-shadow: 0 20px 45px rgba(0, 0, 0, 0.12);\n --chat-shadow-sm: 0 4px 12px rgba(0, 0, 0, 0.1);\n --chat-overlay-bg: rgba(0, 0, 0, 0.3);\n}\n.chat-widget {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 24rem;\n background: var(--chat-background);\n border: var(--chat-widget-border-width) solid var(--chat-border);\n border-radius: 0;\n box-shadow: var(--chat-shadow);\n overflow: hidden;\n font-family: var(--chat-font-family);\n color: var(--chat-assistant-text);\n}\n.chat-widget--popup-content {\n border: 0;\n border-radius: inherit;\n box-shadow: none;\n min-height: 0;\n}\n.chat-widget__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 40px;\n padding: 0.75rem 1rem;\n background: var(--chat-primary);\n color: var(--chat-header-text);\n}\n.chat-widget__title {\n margin: 0;\n font-size: 0.875rem;\n font-weight: 600;\n}\n.chat-widget__messages {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 1rem;\n display: flex;\n flex-direction: column;\n gap: 1rem;\n min-width: 0;\n}\n.chat-widget__message {\n display: flex;\n flex-direction: column;\n gap: 0;\n min-width: 0;\n}\n.chat-widget__message-row {\n display: flex;\n min-width: 0;\n}\n.chat-widget__message-row--user {\n justify-content: flex-end;\n}\n.chat-widget__message-row--assistant {\n justify-content: flex-start;\n}\n.chat-widget__bubble {\n max-width: 90%;\n padding: 0.5rem 0.25rem;\n border-radius: calc(var(--chat-radius) * 0.65);\n font-size: var(--chat-font-size);\n min-width: 0;\n overflow-x: hidden;\n}\n.chat-widget__bubble--user {\n background: var(--chat-primary);\n color: var(--chat-user-text);\n border-bottom-right-radius: 0.35rem;\n padding-left: 0.375rem;\n padding-right: 0.375rem;\n}\n.chat-widget__bubble--assistant {\n width: 90%;\n max-width: 90%;\n background: var(--chat-assistant-bg);\n color: var(--chat-assistant-text);\n border-bottom-left-radius: 0.35rem;\n}\n.chat-widget__widget {\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow-x: hidden;\n}\n.widget-customer-root {\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow-x: hidden;\n}\n.chat-widget__markdown {\n white-space: normal;\n font-size: var(--chat-font-size);\n}\n.chat-widget__markdown h1 {\n font-size: calc(var(--chat-font-size) * 1.4);\n}\n.chat-widget__markdown h2 {\n font-size: calc(var(--chat-font-size) * 1.25);\n}\n.chat-widget__markdown h3 {\n font-size: calc(var(--chat-font-size) * 1.1);\n}\n.chat-widget__markdown h4 {\n font-size: calc(var(--chat-font-size) * 1.05);\n}\n.chat-widget__markdown h5 {\n font-size: calc(var(--chat-font-size) * 1);\n}\n.chat-widget__markdown h6 {\n font-size: calc(var(--chat-font-size) * 0.95);\n}\n.chat-widget__anchor-button {\n position: fixed;\n bottom: 20px;\n right: 20px;\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.65rem 0.85rem;\n background: var(--chat-primary);\n color: var(--chat-primary-text);\n border: none;\n border-radius: 999px;\n box-shadow: var(--chat-shadow);\n cursor: pointer;\n font-weight: 600;\n z-index: 99999;\n}\n.chat-widget__anchor-button:hover {\n background: var(--chat-primary-hover);\n}\n.chat-widget__anchor--left {\n right: auto;\n left: 20px;\n}\n.chat-widget__anchor-icon {\n width: 1.1rem;\n height: 1.1rem;\n}\n.chat-widget__popup {\n position: fixed;\n bottom: 80px;\n right: 20px;\n z-index: 99998;\n}\n.chat-widget__anchor--left.chat-widget__popup {\n right: auto;\n left: 20px;\n}\n.chat-widget__popup-inner {\n width: 384px;\n max-width: calc(100vw - 40px);\n height: 500px;\n max-height: calc(100vh - 140px);\n box-shadow: var(--chat-shadow);\n border-radius: 12px;\n overflow: hidden;\n}\n.chat-widget__markdown a {\n color: var(--chat-link);\n text-decoration: underline;\n}\n.chat-widget__markdown a:hover {\n color: var(--chat-link-hover);\n}\n.chat-widget__markdown table {\n width: 100%;\n border-collapse: collapse;\n margin: 0.5rem 0;\n}\n.chat-widget__markdown th,\n.chat-widget__markdown td {\n border: 1px solid var(--chat-border);\n padding: 0.5rem;\n text-align: left;\n vertical-align: top;\n}\n.chat-widget__markdown thead th {\n background: var(--chat-assistant-bg);\n color: var(--chat-assistant-text);\n font-weight: 600;\n}\n.chat-widget__thoughts {\n min-width: 0;\n --chat-font-size: var(--chat-thought-font-size);\n}\n.chat-widget__details {\n border: 0;\n}\n.chat-widget__thoughts-summary {\n list-style: none;\n display: flex;\n align-items: center;\n gap: 0.35rem;\n cursor: pointer;\n color: var(--chat-text-muted);\n font-size: 0.8125rem;\n}\n.chat-widget__thoughts-summary:hover {\n color: var(--chat-assistant-text);\n}\n.chat-widget__thoughts-icon-container {\n display: flex;\n border: 1px solid var(--chat-border);\n border-radius: 999px;\n align-items: center;\n justify-content: center;\n width: 1rem;\n height: 1rem;\n}\n.chat-widget__thoughts-icon {\n width: 0.75rem;\n height: 0.75rem;\n transition: transform 0.2s ease;\n}\n.chat-widget__details[open] .chat-widget__thoughts-icon {\n transform: rotate(90deg);\n}\n.chat-widget__thoughts-content {\n margin-top: 0.5rem;\n margin-left: 0.4rem;\n padding: 0.75rem;\n border-left: 2px solid var(--chat-thought-border);\n border-color: var(--chat-primary);\n max-width: 100%;\n overflow-x: auto;\n}\n.chat-widget__thoughts-text {\n margin: 0;\n line-height: 1.5;\n color: var(--chat-text-secondary);\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n "Liberation Mono",\n "Courier New",\n monospace;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-wrap: anywhere;\n display: block;\n}\n.chat-widget__loading {\n display: flex;\n justify-content: flex-start;\n}\n.chat-widget__loading-bubble {\n background: var(--chat-assistant-bg);\n color: var(--chat-assistant-text);\n border-radius: calc(var(--chat-radius) * 0.65);\n border-bottom-left-radius: 0.35rem;\n padding: 0.5rem 0.75rem;\n}\n.chat-widget__loading-dots {\n display: flex;\n gap: 0.35rem;\n}\n.chat-widget__loading-dot {\n width: 0.5rem;\n height: 0.5rem;\n border-radius: 999px;\n background: var(--chat-text-disabled);\n animation: chat-widget-bounce 1s infinite ease-in-out;\n}\n.chat-widget__loading-dot[data-delay="1"] {\n animation-delay: 0.1s;\n}\n.chat-widget__loading-dot[data-delay="2"] {\n animation-delay: 0.2s;\n}\n@keyframes chat-widget-bounce {\n 0%, 80%, 100% {\n transform: scale(0.6);\n opacity: 0.4;\n }\n 40% {\n transform: scale(1);\n opacity: 1;\n }\n}\n.chat-widget__token-usage {\n display: flex;\n justify-content: flex-end;\n gap: 0.75rem;\n padding: 0.25rem 0.25rem 0;\n font-size: 0.6875rem;\n line-height: 1.2;\n color: var(--chat-text-muted);\n}\n.chat-widget__token-usage-item {\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n.chat-widget__input {\n border-top: 1px solid var(--chat-border);\n padding: 0.25rem 0 0.75rem;\n background: var(--chat-input-bg);\n}\n.chat-widget__form {\n position: relative;\n}\n.chat-widget__textarea {\n width: 100%;\n border: 0;\n padding: 0.75rem 5.25rem 0.75rem 0.75rem;\n background: transparent;\n font-size: 0.925rem;\n resize: none;\n color: var(--chat-input-text);\n font-family: inherit;\n}\n.chat-widget__textarea::-moz-placeholder {\n color: var(--chat-input-placeholder);\n}\n.chat-widget__textarea::placeholder {\n color: var(--chat-input-placeholder);\n}\n.chat-widget__textarea:focus-visible {\n outline: none;\n}\n.chat-widget__textarea:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.chat-widget__toolbar {\n position: absolute;\n top: 0;\n right: 3.75rem;\n height: 100%;\n display: flex;\n align-items: center;\n padding: 0 0.5rem;\n border-right: 1px solid var(--chat-border);\n}\n.chat-widget__submit {\n position: absolute;\n top: 50%;\n right: 0.75rem;\n transform: translateY(-50%);\n background: transparent;\n border: 0;\n width: 2.5rem;\n height: 2.5rem;\n display: grid;\n place-items: center;\n color: var(--chat-primary);\n cursor: pointer;\n}\n.chat-widget__submit:disabled {\n color: var(--chat-text-disabled);\n cursor: not-allowed;\n}\n.chat-widget__submit:not(:disabled):hover {\n color: var(--chat-primary-hover);\n}\n.chat-widget__send-icon {\n width: 1.2rem;\n height: 1.2rem;\n}\n.chat-widget__mic-button {\n position: relative;\n border: none;\n background: transparent;\n width: 2.25rem;\n height: 2.25rem;\n display: grid;\n place-items: center;\n color: var(--chat-primary);\n cursor: pointer;\n border-radius: 999px;\n}\n.chat-widget__mic-button:disabled {\n color: var(--chat-text-disabled);\n cursor: not-allowed;\n}\n.chat-widget__mic-button--active {\n color: var(--chat-primary-hover);\n background: var(--chat-primary-subtle);\n}\n.chat-widget__mic-icon {\n width: 1rem;\n height: 1rem;\n}\n.chat-widget__mic-bar {\n position: absolute;\n bottom: 0.1rem;\n left: 50%;\n width: 16px;\n height: 2px;\n border-radius: 999px;\n background: var(--chat-border);\n overflow: hidden;\n display: block;\n transform: translateX(-50%);\n pointer-events: none;\n}\n.chat-widget__mic-bar-fill {\n display: block;\n width: 100%;\n height: 100%;\n background: currentColor;\n transform-origin: left;\n transition: transform 0.12s linear;\n}\n.chat-widget__voice {\n display: flex;\n margin-top: 0.25rem;\n}\n.chat-widget__voice-button {\n border: none;\n background: none;\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.1rem 0;\n font-size: 0.8rem;\n font-weight: 500;\n color: var(--chat-primary);\n cursor: pointer;\n}\n.chat-widget__voice-button:disabled {\n color: var(--chat-text-disabled);\n cursor: not-allowed;\n}\n.chat-widget__voice-button--active {\n color: var(--chat-primary-hover);\n}\n.chat-widget__voice-icon {\n width: 0.95rem;\n height: 0.95rem;\n}\n.chat-widget__voice-icon--spin {\n animation: chat-widget-spin 1s linear infinite;\n}\n@keyframes chat-widget-spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n.chat-widget__collapsed {\n position: relative;\n margin-bottom: 0.25rem;\n}\n.chat-widget__collapsed-content {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows 300ms ease-out;\n}\n.chat-widget__collapsed-content--expanded {\n grid-template-rows: 1fr;\n}\n.chat-widget__collapsed-content-inner {\n overflow: hidden;\n}\n.chat-widget__collapsed-preview {\n position: relative;\n max-height: 1.5em;\n overflow: hidden;\n opacity: 0.6;\n pointer-events: none;\n transition: opacity 300ms ease-out, max-height 300ms ease-out;\n}\n.chat-widget__collapsed-preview--hidden {\n opacity: 0;\n max-height: 0;\n pointer-events: none;\n}\n.chat-widget__collapsed-gradient {\n position: absolute;\n top: 0;\n right: 0;\n width: 70%;\n height: 100%;\n background:\n linear-gradient(\n to right,\n transparent 0%,\n var(--chat-background) 90%);\n pointer-events: none;\n}\n.chat-widget__collapsed-toggle {\n display: inline-block;\n padding: 0;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--chat-primary);\n background: transparent;\n border: none;\n cursor: pointer;\n}\n.chat-widget__collapsed-toggle:hover {\n text-decoration: underline;\n}\n@keyframes chat-widget-slide-up {\n from {\n opacity: 1;\n transform: translateY(0);\n max-height: 200px;\n }\n to {\n opacity: 0.6;\n transform: translateY(-8px);\n max-height: 1.5em;\n }\n}\n.chat-widget__collapsed--animating .chat-widget__collapsed-preview {\n animation: chat-widget-slide-up 300ms ease-out forwards;\n}\n');
|
|
25
25
|
|
|
26
26
|
// lib/chat/ChatWidget.tsx
|
|
27
27
|
import { Send, StopCircle } from "lucide-react";
|
|
@@ -4217,6 +4217,22 @@ function createAuthAwareFetch(tokenRef, onAuthError) {
|
|
|
4217
4217
|
return response;
|
|
4218
4218
|
};
|
|
4219
4219
|
}
|
|
4220
|
+
function extractUsageData(dataPart) {
|
|
4221
|
+
if (dataPart && typeof dataPart === "object") {
|
|
4222
|
+
const part = dataPart;
|
|
4223
|
+
if (part.type === "data-usage" && part.data) {
|
|
4224
|
+
return part.data;
|
|
4225
|
+
}
|
|
4226
|
+
}
|
|
4227
|
+
return null;
|
|
4228
|
+
}
|
|
4229
|
+
function buildMessagesUrl(baseUrl, messagesToLoad) {
|
|
4230
|
+
const base = `${baseUrl}/chat/messages`;
|
|
4231
|
+
if (messagesToLoad != null && Number.isFinite(messagesToLoad) && messagesToLoad > 0) {
|
|
4232
|
+
return `${base}?limit=${messagesToLoad}`;
|
|
4233
|
+
}
|
|
4234
|
+
return base;
|
|
4235
|
+
}
|
|
4220
4236
|
var EMPTY_HEADERS = {};
|
|
4221
4237
|
function useChat({
|
|
4222
4238
|
api,
|
|
@@ -4225,6 +4241,7 @@ function useChat({
|
|
|
4225
4241
|
agentVersion,
|
|
4226
4242
|
agentExecutionId,
|
|
4227
4243
|
dataContext,
|
|
4244
|
+
messagesToLoad,
|
|
4228
4245
|
onError,
|
|
4229
4246
|
onAuthError,
|
|
4230
4247
|
onFinish,
|
|
@@ -4295,11 +4312,10 @@ function useChat({
|
|
|
4295
4312
|
},
|
|
4296
4313
|
onData: (dataPart) => {
|
|
4297
4314
|
onData?.(dataPart);
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
}
|
|
4315
|
+
const usageData = extractUsageData(dataPart);
|
|
4316
|
+
if (usageData) {
|
|
4317
|
+
setUsage(usageData);
|
|
4318
|
+
onUsage?.(usageData);
|
|
4303
4319
|
}
|
|
4304
4320
|
}
|
|
4305
4321
|
});
|
|
@@ -4320,6 +4336,7 @@ function useChat({
|
|
|
4320
4336
|
[sendMessage]
|
|
4321
4337
|
);
|
|
4322
4338
|
const [isLoadingInitial, setIsLoadingInitial] = useState(true);
|
|
4339
|
+
const [usage, setUsage] = useState(null);
|
|
4323
4340
|
const hasFetchedRef = useRef(false);
|
|
4324
4341
|
useEffect(() => {
|
|
4325
4342
|
hasFetchedRef.current = false;
|
|
@@ -4329,7 +4346,7 @@ function useChat({
|
|
|
4329
4346
|
const fetchInitialMessages = async () => {
|
|
4330
4347
|
hasFetchedRef.current = true;
|
|
4331
4348
|
try {
|
|
4332
|
-
const response = await authFetch(
|
|
4349
|
+
const response = await authFetch(buildMessagesUrl(baseUrl, messagesToLoad), {
|
|
4333
4350
|
method: "GET",
|
|
4334
4351
|
headers: {
|
|
4335
4352
|
"thread-id": threadId,
|
|
@@ -4353,7 +4370,7 @@ function useChat({
|
|
|
4353
4370
|
}
|
|
4354
4371
|
};
|
|
4355
4372
|
fetchInitialMessages();
|
|
4356
|
-
}, [agentExecutionId, agentId, authFetch, baseUrl, customHeadersKey, threadId]);
|
|
4373
|
+
}, [agentExecutionId, agentId, authFetch, baseUrl, customHeadersKey, threadId, messagesToLoad]);
|
|
4357
4374
|
useEffect(() => {
|
|
4358
4375
|
if (!onMessage || messages.length === 0) return;
|
|
4359
4376
|
const lastMessage = messages[messages.length - 1];
|
|
@@ -4416,7 +4433,8 @@ function useChat({
|
|
|
4416
4433
|
addToolOutput,
|
|
4417
4434
|
addToolApprovalResponse,
|
|
4418
4435
|
pendingToolOutput,
|
|
4419
|
-
pendingToolApproval
|
|
4436
|
+
pendingToolApproval,
|
|
4437
|
+
usage
|
|
4420
4438
|
};
|
|
4421
4439
|
}
|
|
4422
4440
|
|
|
@@ -9594,6 +9612,8 @@ var classNames2 = {
|
|
|
9594
9612
|
header: "chat-widget__header",
|
|
9595
9613
|
headerTitle: "chat-widget__title",
|
|
9596
9614
|
messagesContainer: "chat-widget__messages",
|
|
9615
|
+
tokenUsage: "chat-widget__token-usage",
|
|
9616
|
+
tokenUsageItem: "chat-widget__token-usage-item",
|
|
9597
9617
|
messageWrapper: "chat-widget__message",
|
|
9598
9618
|
messageRow: "chat-widget__message-row",
|
|
9599
9619
|
userMessageRow: "chat-widget__message-row--user",
|
|
@@ -9713,11 +9733,14 @@ var ChatWidget = forwardRef(function ChatWidget2({
|
|
|
9713
9733
|
agentVersion,
|
|
9714
9734
|
agentExecutionId,
|
|
9715
9735
|
dataContext,
|
|
9736
|
+
messagesToLoad,
|
|
9716
9737
|
displayMode = "brief",
|
|
9717
9738
|
onError,
|
|
9718
9739
|
onAuthError,
|
|
9719
9740
|
onFinish,
|
|
9720
9741
|
onMessage,
|
|
9742
|
+
onUsage,
|
|
9743
|
+
onData,
|
|
9721
9744
|
title,
|
|
9722
9745
|
initialAssistantMessage,
|
|
9723
9746
|
initialUserMessage,
|
|
@@ -9727,7 +9750,8 @@ var ChatWidget = forwardRef(function ChatWidget2({
|
|
|
9727
9750
|
voice,
|
|
9728
9751
|
speechToText,
|
|
9729
9752
|
widgets,
|
|
9730
|
-
feedback
|
|
9753
|
+
feedback,
|
|
9754
|
+
showTokenUsage = false
|
|
9731
9755
|
}, ref) {
|
|
9732
9756
|
const [detectedDarkMode, setDetectedDarkMode] = useState9(() => detectChatWidgetDarkMode());
|
|
9733
9757
|
useEffect6(() => {
|
|
@@ -9809,7 +9833,8 @@ var ChatWidget = forwardRef(function ChatWidget2({
|
|
|
9809
9833
|
addToolOutput,
|
|
9810
9834
|
addToolApprovalResponse,
|
|
9811
9835
|
pendingToolOutput,
|
|
9812
|
-
pendingToolApproval
|
|
9836
|
+
pendingToolApproval,
|
|
9837
|
+
usage
|
|
9813
9838
|
} = useChat({
|
|
9814
9839
|
api,
|
|
9815
9840
|
threadId,
|
|
@@ -9817,10 +9842,13 @@ var ChatWidget = forwardRef(function ChatWidget2({
|
|
|
9817
9842
|
agentVersion,
|
|
9818
9843
|
agentExecutionId: agentExecutionId ?? void 0,
|
|
9819
9844
|
dataContext,
|
|
9845
|
+
messagesToLoad,
|
|
9820
9846
|
onError,
|
|
9821
9847
|
onAuthError,
|
|
9822
9848
|
onFinish,
|
|
9823
|
-
onMessage
|
|
9849
|
+
onMessage,
|
|
9850
|
+
onUsage,
|
|
9851
|
+
onData
|
|
9824
9852
|
});
|
|
9825
9853
|
const handleToolOutput = useCallback7((result) => {
|
|
9826
9854
|
if (pendingToolOutput && addToolOutput) {
|
|
@@ -10121,6 +10149,18 @@ var ChatWidget = forwardRef(function ChatWidget2({
|
|
|
10121
10149
|
]
|
|
10122
10150
|
}
|
|
10123
10151
|
),
|
|
10152
|
+
showTokenUsage && usage && /* @__PURE__ */ jsxs15("div", { className: classNames2.tokenUsage, "aria-label": "Token usage", children: [
|
|
10153
|
+
/* @__PURE__ */ jsxs15("span", { className: classNames2.tokenUsageItem, title: "Input tokens", children: [
|
|
10154
|
+
"\u2191 ",
|
|
10155
|
+
usage.inputTokens.toLocaleString(),
|
|
10156
|
+
" in"
|
|
10157
|
+
] }),
|
|
10158
|
+
/* @__PURE__ */ jsxs15("span", { className: classNames2.tokenUsageItem, title: "Output tokens", children: [
|
|
10159
|
+
"\u2193 ",
|
|
10160
|
+
usage.outputTokens.toLocaleString(),
|
|
10161
|
+
" out"
|
|
10162
|
+
] })
|
|
10163
|
+
] }),
|
|
10124
10164
|
/* @__PURE__ */ jsx18("div", { className: classNames2.inputContainer, children: /* @__PURE__ */ jsxs15("form", { onSubmit: handleSubmit, className: classNames2.inputForm, children: [
|
|
10125
10165
|
/* @__PURE__ */ jsx18(
|
|
10126
10166
|
"textarea",
|
|
@@ -10928,10 +10968,12 @@ export {
|
|
|
10928
10968
|
SDK_WIDGET_MARKER,
|
|
10929
10969
|
TagGroupDisplay,
|
|
10930
10970
|
ToolCallDisplay,
|
|
10971
|
+
buildMessagesUrl,
|
|
10931
10972
|
cn,
|
|
10932
10973
|
createSDKWidget,
|
|
10933
10974
|
createWidget,
|
|
10934
10975
|
defaultChatWidgets,
|
|
10976
|
+
extractUsageData,
|
|
10935
10977
|
fetchApprovalConfig,
|
|
10936
10978
|
getVendorCardsWidget,
|
|
10937
10979
|
isSDKWidget,
|