@mcp-b/char 0.0.1 → 0.0.3

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 CHANGED
@@ -1,4 +1,4 @@
1
- # @mcp-b/embedded-agent
1
+ # @mcp-b/char
2
2
 
3
3
  An Intercom-like AI chat widget with MCP tool support and voice mode. Drop it into your app and you're done.
4
4
 
@@ -6,12 +6,12 @@ Styles are isolated using Shadow DOM. Customize appearance by setting CSS variab
6
6
 
7
7
  ## Build Architecture
8
8
 
9
- This package provides the `` custom element in two formats:
9
+ This package provides the `<char-agent>` custom element in two formats:
10
10
 
11
11
  | Export | Format | Use Case |
12
12
  |--------|--------|----------|
13
- | `@mcp-b/embedded-agent` / `@mcp-b/embedded-agent/web-component` | ESM web component | Bundlers, monorepo dev |
14
- | `@mcp-b/embedded-agent/standalone` | IIFE web component | `<script>` tag embeds |
13
+ | `@mcp-b/char` / `@mcp-b/char/web-component` | ESM web component | Bundlers, monorepo dev |
14
+ | `@mcp-b/char/standalone` | IIFE web component | `<script>` tag embeds |
15
15
 
16
16
  ### Bundle Sizes
17
17
 
@@ -49,7 +49,7 @@ Host Page (React 18)
49
49
  ├── <div id="root"> ← Host's React
50
50
  │ └── ... host app ...
51
51
 
52
- └──
52
+ └── <char-agent>
53
53
  └── #shadow-root ← Isolation boundary
54
54
  └── <div> ← Bundled React 19
55
55
  └── ... widget ...
@@ -58,12 +58,12 @@ Host Page (React 18)
58
58
  ## Installation
59
59
 
60
60
  ```bash
61
- npm install @mcp-b/embedded-agent
61
+ npm install @mcp-b/char
62
62
  ```
63
63
 
64
64
  ## Usage
65
65
 
66
- `` renders as a full-viewport overlay.
66
+ `<char-agent>` renders as a full-viewport overlay.
67
67
 
68
68
  ### Recommended: Imperative Authentication (Secure)
69
69
 
@@ -71,12 +71,12 @@ The `connect()` method is the recommended way to authenticate. It keeps tokens o
71
71
 
72
72
  ```tsx
73
73
  import { useRef, useEffect } from "react";
74
- import "@mcp-b/embedded-agent/web-component";
75
- import type { WebMCPAgentElement } from "@mcp-b/embedded-agent/web-component";
74
+ import "@mcp-b/char/web-component";
75
+ import type { CharAgentElement } from "@mcp-b/char/web-component";
76
76
 
77
77
  function App() {
78
78
  const { session } = useOktaAuth(); // or Azure, Auth0, Google, etc.
79
- const agentRef = useRef<WebMCPAgentElement>(null);
79
+ const agentRef = useRef<CharAgentElement>(null);
80
80
 
81
81
  useEffect(() => {
82
82
  if (agentRef.current && session?.idToken) {
@@ -91,10 +91,10 @@ function App() {
91
91
  ### Vanilla JavaScript
92
92
 
93
93
  ```html
94
- </char-agent>
94
+ <char-agent></char-agent>
95
95
 
96
96
  <script type="module">
97
- import "@mcp-b/embedded-agent/web-component";
97
+ import "@mcp-b/char/web-component";
98
98
 
99
99
  const agent = document.querySelector("char-agent");
100
100
  // Call connect() when you have the token
@@ -106,11 +106,11 @@ function App() {
106
106
 
107
107
  ```tsx
108
108
  import { useRef, useEffect } from "react";
109
- import "@mcp-b/embedded-agent/web-component";
110
- import type { WebMCPAgentElement } from "@mcp-b/embedded-agent/web-component";
109
+ import "@mcp-b/char/web-component";
110
+ import type { CharAgentElement } from "@mcp-b/char/web-component";
111
111
 
112
112
  const authToken = session?.idToken ?? "";
113
- const agentRef = useRef<WebMCPAgentElement>(null);
113
+ const agentRef = useRef<CharAgentElement>(null);
114
114
 
115
115
  useEffect(() => {
116
116
  const agent = agentRef.current ?? document.querySelector("char-agent");
@@ -119,9 +119,9 @@ useEffect(() => {
119
119
  const newAgent = document.createElement("char-agent");
120
120
  document.body.appendChild(newAgent);
121
121
  // Connect after element is in DOM
122
- (newAgent as WebMCPAgentElement).connect({ idToken: authToken });
122
+ (newAgent as CharAgentElement).connect({ idToken: authToken });
123
123
  } else if (authToken) {
124
- (agent as WebMCPAgentElement).connect({ idToken: authToken });
124
+ (agent as CharAgentElement).connect({ idToken: authToken });
125
125
  }
126
126
 
127
127
  // Set other attributes (these don't contain sensitive data)
@@ -138,8 +138,8 @@ Use `defer` for best performance - it loads the script without blocking page ren
138
138
 
139
139
  ```html
140
140
  <!-- Recommended: defer loads async, executes after DOM ready -->
141
- <script src="https://unpkg.com/@mcp-b/embedded-agent/dist/web-component-standalone.iife.js" defer></script>
142
- </char-agent>
141
+ <script src="https://unpkg.com/@mcp-b/char/dist/web-component-standalone.iife.js" defer></script>
142
+ <char-agent></char-agent>
143
143
 
144
144
  <script>
145
145
  // Authenticate after the page loads (tokens not in DOM attributes)
@@ -154,13 +154,13 @@ Use `defer` for best performance - it loads the script without blocking page ren
154
154
  Alternative CDN (jsdelivr):
155
155
 
156
156
  ```html
157
- <script src="https://cdn.jsdelivr.net/npm/@mcp-b/embedded-agent/dist/web-component-standalone.iife.js" defer></script>
157
+ <script src="https://cdn.jsdelivr.net/npm/@mcp-b/char/dist/web-component-standalone.iife.js" defer></script>
158
158
  ```
159
159
 
160
160
  Pin to a specific version for production:
161
161
 
162
162
  ```html
163
- <script src="https://unpkg.com/@mcp-b/embedded-agent@1.2.7/dist/web-component-standalone.iife.js" defer></script>
163
+ <script src="https://unpkg.com/@mcp-b/char@0.0.2/dist/web-component-standalone.iife.js" defer></script>
164
164
  ```
165
165
 
166
166
  ### Web Component Attributes
@@ -178,6 +178,44 @@ Pin to a specific version for production:
178
178
  </script>
179
179
  ```
180
180
 
181
+ ## SSR Frameworks (Astro, Next.js, etc.)
182
+
183
+ Char requires a browser environment — it uses Shadow DOM, custom elements, and other browser APIs. In SSR frameworks, you must ensure Char only renders on the client.
184
+
185
+ ### Astro
186
+
187
+ Use `client:only="react"` to skip server-side rendering entirely:
188
+
189
+ ```astro
190
+ ---
191
+ import { Char } from '@mcp-b/char'
192
+ ---
193
+
194
+ <Char
195
+ client:only="react"
196
+ devMode={{ anthropicApiKey: import.meta.env.PUBLIC_ANTHROPIC_API_KEY }}
197
+ open={true}
198
+ />
199
+ ```
200
+
201
+ `client:load` or `client:visible` will not work because Astro still attempts to render the component on the server first. `client:only="react"` skips SSR entirely and renders only in the browser.
202
+
203
+ ### Next.js
204
+
205
+ Use dynamic imports with `ssr: false`:
206
+
207
+ ```tsx
208
+ import dynamic from 'next/dynamic'
209
+
210
+ const Char = dynamic(() => import('@mcp-b/char').then(m => ({ default: m.Char })), {
211
+ ssr: false,
212
+ })
213
+
214
+ export default function Page() {
215
+ return <Char open={true} devMode={{ anthropicApiKey: process.env.NEXT_PUBLIC_ANTHROPIC_API_KEY }} />
216
+ }
217
+ ```
218
+
181
219
  ## Props / Attributes
182
220
 
183
221
  | Prop | Attribute | Type | Description |
@@ -194,7 +232,7 @@ Pin to a specific version for production:
194
232
  Customize appearance by setting CSS variables on the host page:
195
233
 
196
234
  ```css
197
- char {
235
+ char-agent {
198
236
  /* Brand colors */
199
237
  --wm-color-primary: #8b5cf6;
200
238
  --wm-color-primary-foreground: #ffffff;
@@ -237,7 +275,7 @@ char {
237
275
  }
238
276
 
239
277
  /* Dark mode */
240
- char.dark {
278
+ char-agent.dark {
241
279
  --wm-color-background: #1a1a1a;
242
280
  --wm-color-foreground: #ffffff;
243
281
  --wm-color-muted: #2a2a2a;
@@ -273,13 +311,13 @@ Always use `defer` or `async` when embedding the standalone script to avoid bloc
273
311
 
274
312
  ```html
275
313
  <!-- GOOD: defer - loads in parallel, executes after DOM ready -->
276
- <script src="https://unpkg.com/@mcp-b/embedded-agent/dist/web-component-standalone.iife.js" defer></script>
314
+ <script src="https://unpkg.com/@mcp-b/char/dist/web-component-standalone.iife.js" defer></script>
277
315
 
278
316
  <!-- GOOD: async - loads in parallel, executes ASAP -->
279
- <script src="https://unpkg.com/@mcp-b/embedded-agent/dist/web-component-standalone.iife.js" async></script>
317
+ <script src="https://unpkg.com/@mcp-b/char/dist/web-component-standalone.iife.js" async></script>
280
318
 
281
319
  <!-- BAD: blocks page rendering until script loads -->
282
- <script src="https://unpkg.com/@mcp-b/embedded-agent/dist/web-component-standalone.iife.js"></script>
320
+ <script src="https://unpkg.com/@mcp-b/char/dist/web-component-standalone.iife.js"></script>
283
321
  ```
284
322
 
285
323
  **When to use which:**
@@ -328,7 +366,7 @@ Speed up loading by adding a preconnect hint in your `<head>`:
328
366
  ></char-agent>
329
367
 
330
368
  <!-- NEW (SSO-first with connect method): -->
331
- </char-agent>
369
+ <char-agent></char-agent>
332
370
  <script>
333
371
  const agent = document.querySelector('char-agent');
334
372
  agent.connect({ idToken: 'eyJhbGciOi...' });
@@ -339,10 +377,10 @@ Speed up loading by adding a preconnect hint in your `<head>`:
339
377
 
340
378
  <!-- Customize via CSS: -->
341
379
  <style>
342
- char {
380
+ char-agent {
343
381
  --wm-color-primary: #ff0000;
344
382
  }
345
- char.dark {
383
+ char-agent.dark {
346
384
  --wm-color-background: #1a1a1a;
347
385
  }
348
386
  </style>
@@ -358,10 +396,10 @@ Speed up loading by adding a preconnect hint in your `<head>`:
358
396
  ## Development
359
397
 
360
398
  ```bash
361
- pnpm --filter @mcp-b/embedded-agent dev # Watch TS build
362
- pnpm --filter @mcp-b/embedded-agent dev:css # Watch Tailwind CSS
363
- pnpm --filter @mcp-b/embedded-agent storybook # http://localhost:6006
364
- pnpm --filter @mcp-b/embedded-agent build
365
- pnpm --filter @mcp-b/embedded-agent check:types
366
- pnpm --filter @mcp-b/embedded-agent test
399
+ pnpm --filter @mcp-b/char dev # Watch TS build
400
+ pnpm --filter @mcp-b/char dev:css # Watch Tailwind CSS
401
+ pnpm --filter @mcp-b/char storybook # http://localhost:6006
402
+ pnpm --filter @mcp-b/char build
403
+ pnpm --filter @mcp-b/char check:types
404
+ pnpm --filter @mcp-b/char test
367
405
  ```
@@ -0,0 +1,52 @@
1
+ # Third-Party Notices
2
+
3
+ This package (@mcp-b/char) bundles the following third-party software.
4
+ Each is listed with its license type. Full license texts are available
5
+ in the respective packages' source repositories.
6
+
7
+ ## MIT License
8
+
9
+ - **@assistant-ui/react** - Chat UI primitives
10
+ - **@assistant-ui/react-markdown** - Markdown rendering for assistant-ui
11
+ - **@cloudflare/ai-chat** - Cloudflare AI chat client
12
+ - **@modelcontextprotocol/sdk** - Model Context Protocol SDK
13
+ - **@r2wc/react-to-web-component** - React to Web Component bridge
14
+ - **@rjsf/shadcn** - JSON Schema Form shadcn theme
15
+ - **agents** - Cloudflare Agents SDK
16
+ - **assistant-stream** - Streaming utilities for assistant-ui
17
+ - **clsx** - Utility for constructing className strings
18
+ - **date-fns** - Date utility library
19
+ - **fast-json-stable-stringify** - Deterministic JSON.stringify
20
+ - **motion** - Animation library (Framer Motion)
21
+ - **react-day-picker** - Date picker component
22
+ - **react-error-boundary** - React error boundary component
23
+ - **react-markdown** - Markdown renderer for React
24
+ - **remark-gfm** - GitHub Flavored Markdown support
25
+ - **sonner** - Toast notification library
26
+ - **tailwind-merge** - Tailwind CSS class merging
27
+ - **tw-animate-css** - Tailwind CSS animations
28
+ - **zod** - TypeScript-first schema validation
29
+ - **zustand** - State management
30
+
31
+ ## Apache-2.0 License
32
+
33
+ - **@ai-sdk/react** - Vercel AI SDK React bindings
34
+ - **ai** - Vercel AI SDK
35
+ - **@cloudflare/realtimekit-react** - Cloudflare RealtimeKit React bindings
36
+ - **@cloudflare/realtimekit-react-ui** - Cloudflare RealtimeKit UI components
37
+ - **@rjsf/core** - React JSON Schema Form core
38
+ - **@rjsf/utils** - React JSON Schema Form utilities
39
+ - **@rjsf/validator-ajv8** - JSON Schema Form AJV8 validator
40
+ - **class-variance-authority** - CSS variant utility
41
+
42
+ ## ISC License
43
+
44
+ - **jsonrepair** - JSON repair utility
45
+ - **lucide-react** - Icon library
46
+
47
+ ## Peer Dependencies (not bundled in ESM build)
48
+
49
+ - **react** - MIT License - Copyright (c) Meta Platforms, Inc. and affiliates
50
+ - **react-dom** - MIT License - Copyright (c) Meta Platforms, Inc. and affiliates
51
+
52
+ Note: The standalone IIFE build bundles React and ReactDOM.
@@ -0,0 +1,253 @@
1
+ /*! @mcp-b/char | Copyright (c) 2025 Kukumis Inc. All rights reserved. | UNLICENSED */
2
+ import { r as cn, t as Button } from "./button-BLnLZvxR.js";
3
+ import { c } from "react-compiler-runtime";
4
+ import { useCallback, useEffect, useMemo, useRef } from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { RealtimeKitProvider, useRealtimeKitClient } from "@cloudflare/realtimekit-react";
7
+ import { RtkMeeting } from "@cloudflare/realtimekit-react-ui";
8
+
9
+ //#region src/components/voice/RealtimeKitCallPanel.tsx
10
+ const RealtimeKitCallPanel = ({ authToken, meetingId, onEnded, showSetupScreen = true, debugLabel = "rtk:customer" }) => {
11
+ const [meeting, initMeeting] = useRealtimeKitClient();
12
+ const onEndedRef = useRef(onEnded);
13
+ const lastMeetingStateRef = useRef(null);
14
+ const debugEnabled = useMemo(() => {
15
+ if (typeof window === "undefined") return false;
16
+ try {
17
+ return window.__CHAR_RTK_DEBUG__ === true || window.localStorage.getItem("char:rtk-debug") === "true";
18
+ } catch {
19
+ return false;
20
+ }
21
+ }, []);
22
+ const logDebug = useCallback((message, payload) => {
23
+ if (!debugEnabled) return;
24
+ if (payload) console.debug(`[${debugLabel}] ${message}`, payload);
25
+ else console.debug(`[${debugLabel}] ${message}`);
26
+ }, [debugEnabled, debugLabel]);
27
+ useEffect(() => {
28
+ onEndedRef.current = onEnded;
29
+ }, [onEnded]);
30
+ useEffect(() => {
31
+ if (!authToken) return;
32
+ let cancelled = false;
33
+ logDebug("initMeeting:start", {
34
+ meetingId,
35
+ hasToken: Boolean(authToken),
36
+ tokenLength: authToken.length
37
+ });
38
+ initMeeting({
39
+ authToken,
40
+ defaults: {
41
+ audio: true,
42
+ video: false
43
+ }
44
+ }).then((client) => {
45
+ if (cancelled) return;
46
+ if (client) logDebug("initMeeting:success", { meetingId });
47
+ else logDebug("initMeeting:undefined", { meetingId });
48
+ }).catch((error) => {
49
+ if (cancelled) return;
50
+ logDebug("initMeeting:error", {
51
+ meetingId,
52
+ error: error instanceof Error ? error.message : String(error)
53
+ });
54
+ });
55
+ return () => {
56
+ cancelled = true;
57
+ };
58
+ }, [
59
+ authToken,
60
+ initMeeting,
61
+ logDebug,
62
+ meetingId
63
+ ]);
64
+ const handleStatesUpdate = useCallback((event) => {
65
+ const nextState = event.detail?.meeting ?? null;
66
+ const prevState = lastMeetingStateRef.current;
67
+ lastMeetingStateRef.current = nextState;
68
+ logDebug("meeting:state", {
69
+ meetingId,
70
+ state: nextState
71
+ });
72
+ if (prevState && nextState === "ended" && prevState !== "ended") onEndedRef.current?.();
73
+ }, [logDebug, meetingId]);
74
+ if (!meeting) return /* @__PURE__ */ jsx("div", {
75
+ className: "flex h-full items-center justify-center text-sm text-muted-foreground",
76
+ children: "Connecting to the call..."
77
+ });
78
+ return /* @__PURE__ */ jsx(RealtimeKitProvider, {
79
+ value: meeting,
80
+ children: /* @__PURE__ */ jsx(RtkMeeting, {
81
+ mode: "fill",
82
+ meeting,
83
+ showSetupScreen,
84
+ onRtkStatesUpdate: handleStatesUpdate
85
+ })
86
+ });
87
+ };
88
+ var RealtimeKitCallPanel_default = RealtimeKitCallPanel;
89
+
90
+ //#endregion
91
+ //#region src/components/voice/VoiceHandoffPanel.tsx
92
+ const AI_ONLY_HANDOFF_STATUS = "ai_only";
93
+ const HANDOFF_PENDING_STATUS = "handoff_pending";
94
+ const HUMAN_ACTIVE_STATUS = "human_active";
95
+ const VoiceHandoffPanel = (t0) => {
96
+ const $ = c(36);
97
+ const { handoffStatus, joinResult, isRequesting, error, onRequestToken, onEnd } = t0;
98
+ let t1;
99
+ if ($[0] !== onRequestToken) {
100
+ t1 = () => {
101
+ onRequestToken().catch(_temp);
102
+ };
103
+ $[0] = onRequestToken;
104
+ $[1] = t1;
105
+ } else t1 = $[1];
106
+ const requestToken = t1;
107
+ let t2;
108
+ if ($[2] !== onEnd) {
109
+ t2 = () => {
110
+ onEnd().catch(_temp2);
111
+ };
112
+ $[2] = onEnd;
113
+ $[3] = t2;
114
+ } else t2 = $[3];
115
+ const endCall = t2;
116
+ let t3;
117
+ let t4;
118
+ if ($[4] !== error || $[5] !== handoffStatus || $[6] !== isRequesting || $[7] !== joinResult || $[8] !== requestToken) {
119
+ t3 = () => {
120
+ if (handoffStatus === AI_ONLY_HANDOFF_STATUS) return;
121
+ if (joinResult || isRequesting || error) return;
122
+ requestToken();
123
+ };
124
+ t4 = [
125
+ handoffStatus,
126
+ joinResult,
127
+ isRequesting,
128
+ error,
129
+ requestToken
130
+ ];
131
+ $[4] = error;
132
+ $[5] = handoffStatus;
133
+ $[6] = isRequesting;
134
+ $[7] = joinResult;
135
+ $[8] = requestToken;
136
+ $[9] = t3;
137
+ $[10] = t4;
138
+ } else {
139
+ t3 = $[9];
140
+ t4 = $[10];
141
+ }
142
+ useEffect(t3, t4);
143
+ if (handoffStatus === AI_ONLY_HANDOFF_STATUS) return null;
144
+ const isLive = handoffStatus === HUMAN_ACTIVE_STATUS;
145
+ const t5 = isLive ? "bg-emerald-500" : "bg-amber-500 animate-pulse";
146
+ let t6;
147
+ if ($[11] !== t5) {
148
+ t6 = cn("h-2 w-2 rounded-full", t5);
149
+ $[11] = t5;
150
+ $[12] = t6;
151
+ } else t6 = $[12];
152
+ let t7;
153
+ if ($[13] !== t6) {
154
+ t7 = /* @__PURE__ */ jsx("span", { className: t6 });
155
+ $[13] = t6;
156
+ $[14] = t7;
157
+ } else t7 = $[14];
158
+ const t8 = isLive ? "Live support" : "Connecting support";
159
+ let t9;
160
+ if ($[15] !== t7 || $[16] !== t8) {
161
+ t9 = /* @__PURE__ */ jsxs("div", {
162
+ className: "flex items-center gap-2 text-xs font-medium uppercase tracking-wide text-muted-foreground",
163
+ children: [t7, t8]
164
+ });
165
+ $[15] = t7;
166
+ $[16] = t8;
167
+ $[17] = t9;
168
+ } else t9 = $[17];
169
+ let t10;
170
+ if ($[18] !== endCall || $[19] !== isRequesting) {
171
+ t10 = /* @__PURE__ */ jsx(Button, {
172
+ type: "button",
173
+ variant: "outline",
174
+ size: "sm",
175
+ onClick: endCall,
176
+ disabled: isRequesting,
177
+ children: "End call"
178
+ });
179
+ $[18] = endCall;
180
+ $[19] = isRequesting;
181
+ $[20] = t10;
182
+ } else t10 = $[20];
183
+ let t11;
184
+ if ($[21] !== t10 || $[22] !== t9) {
185
+ t11 = /* @__PURE__ */ jsxs("div", {
186
+ className: "flex items-center justify-between gap-2 pb-2",
187
+ children: [t9, t10]
188
+ });
189
+ $[21] = t10;
190
+ $[22] = t9;
191
+ $[23] = t11;
192
+ } else t11 = $[23];
193
+ let t12;
194
+ if ($[24] !== error) {
195
+ t12 = error ? /* @__PURE__ */ jsx("div", {
196
+ className: "mb-2 text-xs text-destructive",
197
+ children: error
198
+ }) : null;
199
+ $[24] = error;
200
+ $[25] = t12;
201
+ } else t12 = $[25];
202
+ let t13;
203
+ if ($[26] !== endCall || $[27] !== joinResult) {
204
+ t13 = /* @__PURE__ */ jsx("div", {
205
+ className: "h-56 overflow-hidden rounded-xl border border-border/60 bg-background md:h-64",
206
+ children: joinResult ? /* @__PURE__ */ jsx(RealtimeKitCallPanel_default, {
207
+ authToken: joinResult.authToken,
208
+ meetingId: joinResult.meetingId,
209
+ onEnded: endCall
210
+ }) : /* @__PURE__ */ jsx("div", {
211
+ className: "flex h-full items-center justify-center text-sm text-muted-foreground",
212
+ children: "Preparing the call..."
213
+ })
214
+ });
215
+ $[26] = endCall;
216
+ $[27] = joinResult;
217
+ $[28] = t13;
218
+ } else t13 = $[28];
219
+ let t14;
220
+ if ($[29] !== handoffStatus) {
221
+ t14 = handoffStatus === HANDOFF_PENDING_STATUS ? /* @__PURE__ */ jsx("p", {
222
+ className: "mt-2 text-xs text-muted-foreground",
223
+ children: "Waiting for a support agent to join…"
224
+ }) : null;
225
+ $[29] = handoffStatus;
226
+ $[30] = t14;
227
+ } else t14 = $[30];
228
+ let t15;
229
+ if ($[31] !== t11 || $[32] !== t12 || $[33] !== t13 || $[34] !== t14) {
230
+ t15 = /* @__PURE__ */ jsxs("div", {
231
+ className: "rounded-2xl border border-border bg-muted/30 p-3 shadow-sm",
232
+ children: [
233
+ t11,
234
+ t12,
235
+ t13,
236
+ t14
237
+ ]
238
+ });
239
+ $[31] = t11;
240
+ $[32] = t12;
241
+ $[33] = t13;
242
+ $[34] = t14;
243
+ $[35] = t15;
244
+ } else t15 = $[35];
245
+ return t15;
246
+ };
247
+ var VoiceHandoffPanel_default = VoiceHandoffPanel;
248
+ function _temp() {}
249
+ function _temp2() {}
250
+
251
+ //#endregion
252
+ export { VoiceHandoffPanel_default as default };
253
+ //# sourceMappingURL=VoiceHandoffPanel-DWAZTOLa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceHandoffPanel-DWAZTOLa.js","names":["RealtimeKitProvider","useRealtimeKitClient","RtkMeeting","useCallback","useEffect","useMemo","useRef","FC","RtkMeetingState","meeting","RealtimeKitCallPanelProps","authToken","meetingId","onEnded","showSetupScreen","debugLabel","RealtimeKitCallPanel","initMeeting","onEndedRef","lastMeetingStateRef","debugEnabled","window","globalWindow","Window","__CHAR_RTK_DEBUG__","localStorage","getItem","logDebug","message","payload","Record","console","debug","current","cancelled","hasToken","Boolean","tokenLength","length","defaults","audio","video","then","client","catch","error","Error","String","handleStatesUpdate","event","CustomEvent","nextState","detail","prevState","state","Button","cn","useCallback","useEffect","FC","RealtimeKitCallPanel","RealtimeKitJoinResult","VoiceSessionState","HandoffStatus","AI_ONLY_HANDOFF_STATUS","HANDOFF_PENDING_STATUS","HUMAN_ACTIVE_STATUS","VoiceHandoffPanelProps","handoffStatus","joinResult","isRequesting","error","onRequestToken","Promise","onEnd","VoiceHandoffPanel","t0","$","_c","t1","catch","_temp","requestToken","t2","_temp2","endCall","t3","t4","isLive","t5","t6","t7","t8","t9","t10","t11","t12","t13","authToken","meetingId","t14","t15"],"sources":["../src/components/voice/RealtimeKitCallPanel.tsx","../src/components/voice/VoiceHandoffPanel.tsx"],"sourcesContent":["import { RealtimeKitProvider, useRealtimeKitClient } from '@cloudflare/realtimekit-react'\nimport { RtkMeeting } from '@cloudflare/realtimekit-react-ui'\nimport { useCallback, useEffect, useMemo, useRef, type FC } from 'react'\n\ntype RtkMeetingState = {\n\tmeeting?: 'idle' | 'setup' | 'joined' | 'ended' | 'waiting'\n}\n\ninterface RealtimeKitCallPanelProps {\n\tauthToken: string\n\tmeetingId?: string\n\tonEnded?: () => void\n\tshowSetupScreen?: boolean\n\tdebugLabel?: string\n}\n\nconst RealtimeKitCallPanel: FC<RealtimeKitCallPanelProps> = ({\n\tauthToken,\n\tmeetingId,\n\tonEnded,\n\tshowSetupScreen = true,\n\tdebugLabel = 'rtk:customer',\n}) => {\n\tconst [meeting, initMeeting] = useRealtimeKitClient()\n\tconst onEndedRef = useRef(onEnded)\n\tconst lastMeetingStateRef = useRef<RtkMeetingState['meeting'] | null>(null)\n\tconst debugEnabled = useMemo(() => {\n\t\tif (typeof window === 'undefined') return false\n\t\ttry {\n\t\t\tconst globalWindow = window as Window & { __CHAR_RTK_DEBUG__?: boolean }\n\t\t\treturn (\n\t\t\t\tglobalWindow.__CHAR_RTK_DEBUG__ === true ||\n\t\t\t\twindow.localStorage.getItem('char:rtk-debug') === 'true'\n\t\t\t)\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}, [])\n\n\tconst logDebug = useCallback(\n\t\t(message: string, payload?: Record<string, unknown>) => {\n\t\t\tif (!debugEnabled) return\n\t\t\tif (payload) {\n\t\t\t\tconsole.debug(`[${debugLabel}] ${message}`, payload)\n\t\t\t} else {\n\t\t\t\tconsole.debug(`[${debugLabel}] ${message}`)\n\t\t\t}\n\t\t},\n\t\t[debugEnabled, debugLabel],\n\t)\n\n\tuseEffect(() => {\n\t\tonEndedRef.current = onEnded\n\t}, [onEnded])\n\n\tuseEffect(() => {\n\t\tif (!authToken) return\n\t\tlet cancelled = false\n\t\tlogDebug('initMeeting:start', {\n\t\t\tmeetingId,\n\t\t\thasToken: Boolean(authToken),\n\t\t\ttokenLength: authToken.length,\n\t\t})\n\t\tvoid initMeeting({\n\t\t\tauthToken,\n\t\t\tdefaults: {\n\t\t\t\taudio: true,\n\t\t\t\tvideo: false,\n\t\t\t},\n\t\t})\n\t\t\t.then((client) => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tif (client) {\n\t\t\t\t\tlogDebug('initMeeting:success', { meetingId })\n\t\t\t\t} else {\n\t\t\t\t\tlogDebug('initMeeting:undefined', { meetingId })\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tif (cancelled) return\n\t\t\t\tlogDebug('initMeeting:error', {\n\t\t\t\t\tmeetingId,\n\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t})\n\t\t\t})\n\n\t\treturn () => {\n\t\t\tcancelled = true\n\t\t}\n\t}, [authToken, initMeeting, logDebug, meetingId])\n\n\tconst handleStatesUpdate = useCallback((event: CustomEvent<RtkMeetingState>) => {\n\t\tconst nextState = event.detail?.meeting ?? null\n\t\tconst prevState = lastMeetingStateRef.current\n\t\tlastMeetingStateRef.current = nextState\n\t\tlogDebug('meeting:state', { meetingId, state: nextState })\n\n\t\tif (prevState && nextState === 'ended' && prevState !== 'ended') {\n\t\t\tonEndedRef.current?.()\n\t\t}\n\t}, [logDebug, meetingId])\n\n\tif (!meeting) {\n\t\treturn (\n\t\t\t<div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n\t\t\t\tConnecting to the call...\n\t\t\t</div>\n\t\t)\n\t}\n\n\treturn (\n\t\t<RealtimeKitProvider value={meeting}>\n\t\t\t<RtkMeeting\n\t\t\t\tmode=\"fill\"\n\t\t\t\tmeeting={meeting}\n\t\t\t\tshowSetupScreen={showSetupScreen}\n\t\t\t\tonRtkStatesUpdate={handleStatesUpdate}\n\t\t\t/>\n\t\t</RealtimeKitProvider>\n\t)\n}\n\nexport default RealtimeKitCallPanel\n","import { Button } from '@/components/ui/button'\nimport { cn } from '@/utils/cn'\nimport { useCallback, useEffect, type FC } from 'react'\n\nimport RealtimeKitCallPanel from './RealtimeKitCallPanel'\n\nimport type { RealtimeKitJoinResult, VoiceSessionState } from '@mcp-b/shared-types'\n\ntype HandoffStatus = VoiceSessionState['handoffStatus']\nconst AI_ONLY_HANDOFF_STATUS: HandoffStatus = 'ai_only'\nconst HANDOFF_PENDING_STATUS: HandoffStatus = 'handoff_pending'\nconst HUMAN_ACTIVE_STATUS: HandoffStatus = 'human_active'\n\ninterface VoiceHandoffPanelProps {\n\thandoffStatus: HandoffStatus\n\tjoinResult: RealtimeKitJoinResult | null\n\tisRequesting: boolean\n\terror: string | null\n\tonRequestToken: () => Promise<void>\n\tonEnd: () => Promise<void>\n}\n\nconst VoiceHandoffPanel: FC<VoiceHandoffPanelProps> = ({\n\thandoffStatus,\n\tjoinResult,\n\tisRequesting,\n\terror,\n\tonRequestToken,\n\tonEnd,\n}) => {\n\tconst requestToken = useCallback(() => {\n\t\tonRequestToken().catch(() => undefined)\n\t}, [onRequestToken])\n\n\tconst endCall = useCallback(() => {\n\t\tonEnd().catch(() => undefined)\n\t}, [onEnd])\n\n\tuseEffect(() => {\n\t\tif (handoffStatus === AI_ONLY_HANDOFF_STATUS) return\n\t\tif (joinResult || isRequesting || error) return\n\t\trequestToken()\n\t}, [handoffStatus, joinResult, isRequesting, error, requestToken])\n\n\tif (handoffStatus === AI_ONLY_HANDOFF_STATUS) {\n\t\treturn null\n\t}\n\n\tconst isLive = handoffStatus === HUMAN_ACTIVE_STATUS\n\n\treturn (\n\t\t<div className=\"rounded-2xl border border-border bg-muted/30 p-3 shadow-sm\">\n\t\t\t<div className=\"flex items-center justify-between gap-2 pb-2\">\n\t\t\t\t<div className=\"flex items-center gap-2 text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'h-2 w-2 rounded-full',\n\t\t\t\t\t\t\tisLive ? 'bg-emerald-500' : 'bg-amber-500 animate-pulse',\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t\t{isLive ? 'Live support' : 'Connecting support'}\n\t\t\t\t</div>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tonClick={endCall}\n\t\t\t\t\t\tdisabled={isRequesting}\n\t\t\t\t\t>\n\t\t\t\t\tEnd call\n\t\t\t\t</Button>\n\t\t\t</div>\n\n\t\t\t{error ? (\n\t\t\t\t<div className=\"mb-2 text-xs text-destructive\">{error}</div>\n\t\t\t) : null}\n\n\t\t\t<div className=\"h-56 overflow-hidden rounded-xl border border-border/60 bg-background md:h-64\">\n\t\t\t\t{joinResult ? (\n\t\t\t\t\t\t<RealtimeKitCallPanel\n\t\t\t\t\t\t\tauthToken={joinResult.authToken}\n\t\t\t\t\t\t\tmeetingId={joinResult.meetingId}\n\t\t\t\t\t\t\tonEnded={endCall}\n\t\t\t\t\t\t/>\n\t\t\t\t) : (\n\t\t\t\t\t<div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n\t\t\t\t\t\tPreparing the call...\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{handoffStatus === HANDOFF_PENDING_STATUS ? (\n\t\t\t\t<p className=\"mt-2 text-xs text-muted-foreground\">\n\t\t\t\t\tWaiting for a support agent to join…\n\t\t\t\t</p>\n\t\t\t) : null}\n\t\t</div>\n\t)\n}\n\nexport default VoiceHandoffPanel\n"],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ /*! @mcp-b/char | Copyright (c) 2025 Kukumis Inc. All rights reserved. | UNLICENSED */
2
+ import { c } from "react-compiler-runtime";
3
+ import "react";
4
+ import { clsx } from "clsx";
5
+ import { twMerge } from "tailwind-merge";
6
+ import { jsx } from "react/jsx-runtime";
7
+ import { Slot } from "@radix-ui/react-slot";
8
+ import { cva } from "class-variance-authority";
9
+
10
+ //#region src/utils/cn.ts
11
+ /**
12
+ * Merges Tailwind CSS classes with proper precedence handling.
13
+ * Combines clsx for conditional classes and tailwind-merge for deduplication.
14
+ */
15
+ function cn(...inputs) {
16
+ return twMerge(clsx(inputs));
17
+ }
18
+
19
+ //#endregion
20
+ //#region src/components/ui/button.tsx
21
+ const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
22
+ variants: {
23
+ variant: {
24
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
25
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
26
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
27
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
28
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
29
+ link: "text-primary underline-offset-4 hover:underline"
30
+ },
31
+ size: {
32
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
33
+ xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
34
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
35
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
36
+ icon: "size-9",
37
+ "icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
38
+ "icon-sm": "size-8",
39
+ "icon-lg": "size-10"
40
+ }
41
+ },
42
+ defaultVariants: {
43
+ variant: "default",
44
+ size: "default"
45
+ }
46
+ });
47
+ function Button(t0) {
48
+ const $ = c(16);
49
+ let className;
50
+ let props;
51
+ let t1;
52
+ let t2;
53
+ let t3;
54
+ if ($[0] !== t0) {
55
+ ({className, variant: t1, size: t2, asChild: t3, ...props} = t0);
56
+ $[0] = t0;
57
+ $[1] = className;
58
+ $[2] = props;
59
+ $[3] = t1;
60
+ $[4] = t2;
61
+ $[5] = t3;
62
+ } else {
63
+ className = $[1];
64
+ props = $[2];
65
+ t1 = $[3];
66
+ t2 = $[4];
67
+ t3 = $[5];
68
+ }
69
+ const variant = t1 === void 0 ? "default" : t1;
70
+ const size = t2 === void 0 ? "default" : t2;
71
+ const Comp = (t3 === void 0 ? false : t3) ? Slot : "button";
72
+ let t4;
73
+ if ($[6] !== className || $[7] !== size || $[8] !== variant) {
74
+ t4 = cn(buttonVariants({
75
+ variant,
76
+ size,
77
+ className
78
+ }));
79
+ $[6] = className;
80
+ $[7] = size;
81
+ $[8] = variant;
82
+ $[9] = t4;
83
+ } else t4 = $[9];
84
+ let t5;
85
+ if ($[10] !== Comp || $[11] !== props || $[12] !== size || $[13] !== t4 || $[14] !== variant) {
86
+ t5 = /* @__PURE__ */ jsx(Comp, {
87
+ "data-slot": "button",
88
+ "data-variant": variant,
89
+ "data-size": size,
90
+ className: t4,
91
+ ...props
92
+ });
93
+ $[10] = Comp;
94
+ $[11] = props;
95
+ $[12] = size;
96
+ $[13] = t4;
97
+ $[14] = variant;
98
+ $[15] = t5;
99
+ } else t5 = $[15];
100
+ return t5;
101
+ }
102
+
103
+ //#endregion
104
+ export { buttonVariants as n, cn as r, Button as t };
105
+ //# sourceMappingURL=button-BLnLZvxR.js.map