@smooai/smooth-operator 0.1.0 → 0.2.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.
Files changed (81) hide show
  1. package/README.md +18 -4
  2. package/dist/react/components/SmoothChat.d.ts +35 -0
  3. package/dist/react/components/SmoothChat.d.ts.map +1 -0
  4. package/dist/react/components/SmoothChat.js +26 -0
  5. package/dist/react/components/SmoothChat.js.map +1 -0
  6. package/dist/react/components/parts.d.ts +30 -0
  7. package/dist/react/components/parts.d.ts.map +1 -0
  8. package/dist/react/components/parts.js +67 -0
  9. package/dist/react/components/parts.js.map +1 -0
  10. package/dist/react/index.d.ts +27 -0
  11. package/dist/react/index.d.ts.map +1 -0
  12. package/dist/react/index.js +26 -0
  13. package/dist/react/index.js.map +1 -0
  14. package/dist/react/provider.d.ts +27 -0
  15. package/dist/react/provider.d.ts.map +1 -0
  16. package/dist/react/provider.js +25 -0
  17. package/dist/react/provider.js.map +1 -0
  18. package/dist/react/response.d.ts +19 -0
  19. package/dist/react/response.d.ts.map +1 -0
  20. package/dist/react/response.js +53 -0
  21. package/dist/react/response.js.map +1 -0
  22. package/dist/react/theme.d.ts +64 -0
  23. package/dist/react/theme.d.ts.map +1 -0
  24. package/dist/react/theme.js +38 -0
  25. package/dist/react/theme.js.map +1 -0
  26. package/dist/react/types.d.ts +24 -0
  27. package/dist/react/types.d.ts.map +1 -0
  28. package/dist/react/types.js +2 -0
  29. package/dist/react/types.js.map +1 -0
  30. package/dist/react/use-conversation.d.ts +59 -0
  31. package/dist/react/use-conversation.d.ts.map +1 -0
  32. package/dist/react/use-conversation.js +154 -0
  33. package/dist/react/use-conversation.js.map +1 -0
  34. package/dist/widget/chat-widget.iife.js +1301 -0
  35. package/dist/widget/chat-widget.iife.js.map +1 -0
  36. package/dist/widget/config.d.ts +73 -0
  37. package/dist/widget/config.d.ts.map +1 -0
  38. package/dist/widget/config.js +30 -0
  39. package/dist/widget/config.js.map +1 -0
  40. package/dist/widget/conversation.d.ts +50 -0
  41. package/dist/widget/conversation.d.ts.map +1 -0
  42. package/dist/widget/conversation.js +173 -0
  43. package/dist/widget/conversation.js.map +1 -0
  44. package/dist/widget/element.d.ts +94 -0
  45. package/dist/widget/element.d.ts.map +1 -0
  46. package/dist/widget/element.js +377 -0
  47. package/dist/widget/element.js.map +1 -0
  48. package/dist/widget/index.d.ts +25 -0
  49. package/dist/widget/index.d.ts.map +1 -0
  50. package/dist/widget/index.js +24 -0
  51. package/dist/widget/index.js.map +1 -0
  52. package/dist/widget/logo.d.ts +9 -0
  53. package/dist/widget/logo.d.ts.map +1 -0
  54. package/dist/widget/logo.js +10 -0
  55. package/dist/widget/logo.js.map +1 -0
  56. package/dist/widget/standalone.d.ts +25 -0
  57. package/dist/widget/standalone.d.ts.map +1 -0
  58. package/dist/widget/standalone.js +15 -0
  59. package/dist/widget/standalone.js.map +1 -0
  60. package/dist/widget/styles.d.ts +12 -0
  61. package/dist/widget/styles.d.ts.map +1 -0
  62. package/dist/widget/styles.js +262 -0
  63. package/dist/widget/styles.js.map +1 -0
  64. package/package.json +44 -6
  65. package/src/react/components/SmoothChat.tsx +57 -0
  66. package/src/react/components/parts.tsx +141 -0
  67. package/src/react/index.ts +30 -0
  68. package/src/react/provider.tsx +40 -0
  69. package/src/react/response.ts +57 -0
  70. package/src/react/styles.css +231 -0
  71. package/src/react/theme.ts +92 -0
  72. package/src/react/types.ts +27 -0
  73. package/src/react/use-conversation.ts +203 -0
  74. package/src/widget/config.ts +102 -0
  75. package/src/widget/conversation.ts +212 -0
  76. package/src/widget/element.ts +420 -0
  77. package/src/widget/index.ts +37 -0
  78. package/src/widget/logo.ts +9 -0
  79. package/src/widget/smooth-logo.svg +32 -0
  80. package/src/widget/standalone.ts +33 -0
  81. package/src/widget/styles.ts +265 -0
package/README.md CHANGED
@@ -20,12 +20,26 @@ The **native TypeScript client** for the [smooth-operator](../docs/PROTOCOL.md)
20
20
  ## 30-second quickstart
21
21
 
22
22
  ```bash
23
- pnpm add @smooai/smooth-operator # npm publish pending — use a workspace / file: dep today
23
+ pnpm add @smooai/smooth-operator
24
24
  ```
25
25
 
26
- Requires Node ≥ 22, ESM only. Until the package is published, depend on it from a
27
- sibling checkout (`"@smooai/smooth-operator": "workspace:*"` in a pnpm workspace, or
28
- `"file:../smooth-operator/typescript"`).
26
+ Requires Node ≥ 22, ESM only.
27
+
28
+ ### One package, three subpath exports
29
+
30
+ `@smooai/smooth-operator` is the whole TypeScript SDK — install once, import the
31
+ layer you need. `react` / `react-dom` are **optional** peer deps (only the
32
+ `./react` subpath needs them), so a client-only or widget-only consumer never
33
+ pulls React into their bundle.
34
+
35
+ | Import | What |
36
+ | --- | --- |
37
+ | `@smooai/smooth-operator` | the protocol client (`SmoothAgentClient`, streaming turns, HITL) |
38
+ | `@smooai/smooth-operator/react` | React bindings — `useConversation` hook + `<SmoothChat>` (see [the guide](../docs/Guides/React%20Components%20and%20Custom%20UIs.md)) |
39
+ | `@smooai/smooth-operator/react/styles.css` | default stylesheet for the React components |
40
+ | `@smooai/smooth-operator/widget` | the embeddable web-component chat widget (`mountChatWidget`, `<smooth-agent-chat>`) |
41
+ | `@smooai/smooth-operator/widget/standalone` | the prebuilt IIFE bundle for a no-build `<script>` embed |
42
+ | `@smooai/smooth-operator/validate` | the Node-only `ProtocolValidator` (pulls `ajv` + `node:fs`; keep it off the browser path) |
29
43
 
30
44
  ```ts
31
45
  import { SmoothAgentClient } from '@smooai/smooth-operator';
@@ -0,0 +1,35 @@
1
+ /**
2
+ * <SmoothChat> — the opinionated, drop-in chat surface.
3
+ *
4
+ * It wires `useConversation` to the presentational parts and applies the
5
+ * `.smooth-chat` root class whose styling is 100% CSS-variable-driven. Theme it
6
+ * any of three ways (see `theme.ts`): override `--smooth-*` in your CSS/Tailwind,
7
+ * pass a `theme` prop (sets the variables inline), or restyle the
8
+ * `smooth-chat__*` classes outright.
9
+ *
10
+ * Need full control? Skip this component and build your own view over
11
+ * `useConversation` + the exported parts. This is just the batteries-included path.
12
+ *
13
+ * Remember to import the stylesheet once in your app:
14
+ * import '@smooai/smooth-operator/react/styles.css';
15
+ */
16
+ import { type ChatTheme } from '../theme.js';
17
+ import { type UseConversationOptions } from '../use-conversation.js';
18
+ export interface SmoothChatProps extends UseConversationOptions {
19
+ /** Header label for the agent. Default "Assistant". */
20
+ agentName?: string;
21
+ /** Greeting rendered before any messages. */
22
+ greeting?: string;
23
+ /** Placeholder for the input. */
24
+ placeholder?: string;
25
+ /** Per-instance theme overrides (sets `--smooth-*` inline; wins over stylesheet rules). */
26
+ theme?: ChatTheme;
27
+ /** Show the small connection-status label in the header. Default `true`. */
28
+ showStatus?: boolean;
29
+ /** Extra class names on the `.smooth-chat` root (e.g. Tailwind layout utilities). */
30
+ className?: string;
31
+ /** Layout: `panel` (bordered card) or `fullpage` (fills its container). Default `panel`. */
32
+ layout?: 'panel' | 'fullpage';
33
+ }
34
+ export declare function SmoothChat(props: SmoothChatProps): import("react/jsx-runtime").JSX.Element;
35
+ //# sourceMappingURL=SmoothChat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SmoothChat.d.ts","sourceRoot":"","sources":["../../../src/react/components/SmoothChat.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAmB,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAGtF,MAAM,WAAW,eAAgB,SAAQ,sBAAsB;IAC3D,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2FAA2F;IAC3F,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,MAAM,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;CACjC;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,2CAoBhD"}
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * <SmoothChat> — the opinionated, drop-in chat surface.
4
+ *
5
+ * It wires `useConversation` to the presentational parts and applies the
6
+ * `.smooth-chat` root class whose styling is 100% CSS-variable-driven. Theme it
7
+ * any of three ways (see `theme.ts`): override `--smooth-*` in your CSS/Tailwind,
8
+ * pass a `theme` prop (sets the variables inline), or restyle the
9
+ * `smooth-chat__*` classes outright.
10
+ *
11
+ * Need full control? Skip this component and build your own view over
12
+ * `useConversation` + the exported parts. This is just the batteries-included path.
13
+ *
14
+ * Remember to import the stylesheet once in your app:
15
+ * import '@smooai/smooth-operator/react/styles.css';
16
+ */
17
+ import { themeToStyle } from '../theme.js';
18
+ import { useConversation } from '../use-conversation.js';
19
+ import { Composer, ConnectionStatusLabel, MessageList } from './parts.js';
20
+ export function SmoothChat(props) {
21
+ const { agentName = 'Assistant', greeting, placeholder, theme, showStatus = true, className, layout = 'panel', ...conversationOptions } = props;
22
+ const { status, messages, send } = useConversation(conversationOptions);
23
+ const busy = messages.some((m) => m.streaming);
24
+ return (_jsxs("div", { className: ['smooth-chat', `smooth-chat--${layout}`, className].filter(Boolean).join(' '), style: themeToStyle(theme), "data-status": status, children: [_jsxs("header", { className: "smooth-chat__header", children: [_jsx("span", { className: "smooth-chat__title", children: agentName }), showStatus ? _jsx(ConnectionStatusLabel, { status: status }) : null] }), _jsx(MessageList, { messages: messages, greeting: greeting }), _jsx(Composer, { onSend: (text) => void send(text), disabled: status === 'connecting' || busy, placeholder: placeholder })] }));
25
+ }
26
+ //# sourceMappingURL=SmoothChat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SmoothChat.js","sourceRoot":"","sources":["../../../src/react/components/SmoothChat.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,YAAY,EAAkB,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,eAAe,EAA+B,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAmB1E,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC7C,MAAM,EAAE,SAAS,GAAG,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,EAAE,GAAG,mBAAmB,EAAE,GAAG,KAAK,CAAC;IAEhJ,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC,mBAAmB,CAAC,CAAC;IACxE,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAE/C,OAAO,CACH,eACI,SAAS,EAAE,CAAC,aAAa,EAAE,gBAAgB,MAAM,EAAE,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EACzF,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,iBACb,MAAM,aAEnB,kBAAQ,SAAS,EAAC,qBAAqB,aACnC,eAAM,SAAS,EAAC,oBAAoB,YAAE,SAAS,GAAQ,EACtD,UAAU,CAAC,CAAC,CAAC,KAAC,qBAAqB,IAAC,MAAM,EAAE,MAAM,GAAI,CAAC,CAAC,CAAC,IAAI,IACzD,EACT,KAAC,WAAW,IAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,GAAI,EACvD,KAAC,QAAQ,IAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,YAAY,IAAI,IAAI,EAAE,WAAW,EAAE,WAAW,GAAI,IAClH,CACT,CAAC;AACN,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { ChatMessage, Citation, ConnectionStatus } from '../types.js';
2
+ /** A list of grounding sources rendered under an assistant bubble. */
3
+ export declare function Citations({ citations, className }: {
4
+ citations: Citation[];
5
+ className?: string;
6
+ }): import("react/jsx-runtime").JSX.Element | null;
7
+ /** A single message bubble (+ its citations + streaming cursor). */
8
+ export declare function MessageBubble({ message, className }: {
9
+ message: ChatMessage;
10
+ className?: string;
11
+ }): import("react/jsx-runtime").JSX.Element;
12
+ /** The scrollable message column. Renders an optional greeting before any messages. */
13
+ export declare function MessageList({ messages, greeting, className }: {
14
+ messages: ChatMessage[];
15
+ greeting?: string;
16
+ className?: string;
17
+ }): import("react/jsx-runtime").JSX.Element;
18
+ /** The input row. Calls `onSend` on submit / Enter (Shift+Enter inserts a newline). */
19
+ export declare function Composer({ onSend, disabled, placeholder, className, }: {
20
+ onSend: (text: string) => void;
21
+ disabled?: boolean;
22
+ placeholder?: string;
23
+ className?: string;
24
+ }): import("react/jsx-runtime").JSX.Element;
25
+ /** A small connection-status label. */
26
+ export declare function ConnectionStatusLabel({ status, className }: {
27
+ status: ConnectionStatus;
28
+ className?: string;
29
+ }): import("react/jsx-runtime").JSX.Element;
30
+ //# sourceMappingURL=parts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parts.d.ts","sourceRoot":"","sources":["../../../src/react/components/parts.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAM3E,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,kDA4BhG;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,2CAUjG;AAED,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,2CAShI;AAED,uFAAuF;AACvF,wBAAgB,QAAQ,CAAC,EACrB,MAAM,EACN,QAAQ,EACR,WAA+B,EAC/B,SAAS,GACZ,EAAE;IACC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB,2CAsCA;AAUD,uCAAuC;AACvC,wBAAgB,qBAAqB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,2CAM5G"}
@@ -0,0 +1,67 @@
1
+ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * Presentational building blocks.
4
+ *
5
+ * Each part is a thin, styling-light view over the data `useConversation`
6
+ * produces. They render semantic markup with `smooth-chat__*` class names whose
7
+ * styling lives entirely in `styles.css` and is driven by `--smooth-*` CSS
8
+ * variables — so retheming is CSS, never prop-drilling. Every part also forwards
9
+ * `className` so you can layer Tailwind utilities on top, and you can ignore
10
+ * these entirely and render the hook's state yourself.
11
+ */
12
+ import { useState } from 'react';
13
+ import { safeHttpUrl } from '../response.js';
14
+ function cx(...parts) {
15
+ return parts.filter(Boolean).join(' ');
16
+ }
17
+ /** A list of grounding sources rendered under an assistant bubble. */
18
+ export function Citations({ citations, className }) {
19
+ if (!citations.length)
20
+ return null;
21
+ return (_jsx("div", { className: cx('smooth-chat__sources', className), children: _jsxs("details", { children: [_jsxs("summary", { children: [citations.length, " source", citations.length === 1 ? '' : 's'] }), _jsx("ol", { children: citations.map((c) => {
22
+ const href = safeHttpUrl(c.url);
23
+ return (_jsxs("li", { children: [href ? (_jsx("a", { className: "smooth-chat__source-title", href: href, target: "_blank", rel: "noreferrer noopener", children: c.title })) : (_jsx("span", { className: "smooth-chat__source-title", children: c.title })), c.snippet ? _jsx("span", { className: "smooth-chat__source-snippet", children: c.snippet }) : null] }, c.id || c.title));
24
+ }) })] }) }));
25
+ }
26
+ /** A single message bubble (+ its citations + streaming cursor). */
27
+ export function MessageBubble({ message, className }) {
28
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: cx('smooth-chat__bubble', `smooth-chat__bubble--${message.role}`, message.streaming && 'smooth-chat__bubble--streaming', className), children: [message.text, message.streaming ? _jsx("span", { className: "smooth-chat__cursor", "aria-hidden": "true" }) : null] }), message.role === 'assistant' && message.citations?.length ? _jsx(Citations, { citations: message.citations }) : null] }));
29
+ }
30
+ /** The scrollable message column. Renders an optional greeting before any messages. */
31
+ export function MessageList({ messages, greeting, className }) {
32
+ return (_jsxs("div", { className: cx('smooth-chat__messages', className), role: "log", "aria-live": "polite", children: [messages.length === 0 && greeting ? _jsx("div", { className: "smooth-chat__bubble smooth-chat__bubble--assistant smooth-chat__greeting", children: greeting }) : null, messages.map((m) => (_jsx(MessageBubble, { message: m }, m.id)))] }));
33
+ }
34
+ /** The input row. Calls `onSend` on submit / Enter (Shift+Enter inserts a newline). */
35
+ export function Composer({ onSend, disabled, placeholder = 'Type a message…', className, }) {
36
+ const [value, setValue] = useState('');
37
+ const submit = () => {
38
+ const text = value.trim();
39
+ if (!text || disabled)
40
+ return;
41
+ setValue('');
42
+ onSend(text);
43
+ };
44
+ const onSubmit = (e) => {
45
+ e.preventDefault();
46
+ submit();
47
+ };
48
+ const onKeyDown = (e) => {
49
+ if (e.key === 'Enter' && !e.shiftKey) {
50
+ e.preventDefault();
51
+ submit();
52
+ }
53
+ };
54
+ return (_jsxs("form", { className: cx('smooth-chat__composer', className), onSubmit: onSubmit, children: [_jsx("textarea", { className: "smooth-chat__input", value: value, placeholder: placeholder, onChange: (e) => setValue(e.target.value), onKeyDown: onKeyDown, rows: 1, "aria-label": "Message" }), _jsx("button", { className: "smooth-chat__send", type: "submit", disabled: disabled || value.trim().length === 0, children: "Send" })] }));
55
+ }
56
+ const STATUS_LABEL = {
57
+ idle: 'Idle',
58
+ connecting: 'Connecting…',
59
+ ready: 'Online',
60
+ error: 'Connection error',
61
+ closed: 'Disconnected',
62
+ };
63
+ /** A small connection-status label. */
64
+ export function ConnectionStatusLabel({ status, className }) {
65
+ return (_jsx("span", { className: cx('smooth-chat__status', `smooth-chat__status--${status}`, className), "aria-live": "polite", children: STATUS_LABEL[status] }));
66
+ }
67
+ //# sourceMappingURL=parts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parts.js","sourceRoot":"","sources":["../../../src/react/components/parts.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @smooai/smooth-operator/react — React bindings for the smooth-operator
3
+ * WebSocket protocol.
4
+ *
5
+ * Two layers, use whichever you need:
6
+ *
7
+ * • Headless — `useConversation` (+ `SmoothOperatorProvider`) own the whole
8
+ * connect → session → stream lifecycle and expose only state + actions. Build
9
+ * any UI you like on top; this package imposes zero styling.
10
+ *
11
+ * • Batteries-included — `<SmoothChat>` and the `parts` components render a
12
+ * complete, accessible chat surface themed entirely by `--smooth-*` CSS
13
+ * variables. Import the stylesheet once:
14
+ * import '@smooai/smooth-operator/react/styles.css';
15
+ *
16
+ * The protocol client itself lives in `@smooai/smooth-operator`; re-exported here
17
+ * for convenience so you can construct/share a client without a second import.
18
+ */
19
+ export { SmoothAgentClient, MessageTurn, ProtocolError, TurnTimeoutError, type SmoothAgentClientOptions } from '../index.js';
20
+ export { useConversation, type UseConversationOptions, type UseConversationResult } from './use-conversation.js';
21
+ export { SmoothOperatorProvider, useSmoothOperator, type SmoothOperatorProviderProps, type SmoothOperatorContextValue } from './provider.js';
22
+ export { themeToStyle, type ChatTheme } from './theme.js';
23
+ export { safeHttpUrl, extractCitations, extractFinalText } from './response.js';
24
+ export { SmoothChat, type SmoothChatProps } from './components/SmoothChat.js';
25
+ export { MessageList, MessageBubble, Citations, Composer, ConnectionStatusLabel } from './components/parts.js';
26
+ export type { ChatMessage, ConnectionStatus, Role, Citation } from './types.js';
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAE7H,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACjH,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,KAAK,2BAA2B,EAAE,KAAK,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAE7I,OAAO,EAAE,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEhF,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE/G,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @smooai/smooth-operator/react — React bindings for the smooth-operator
3
+ * WebSocket protocol.
4
+ *
5
+ * Two layers, use whichever you need:
6
+ *
7
+ * • Headless — `useConversation` (+ `SmoothOperatorProvider`) own the whole
8
+ * connect → session → stream lifecycle and expose only state + actions. Build
9
+ * any UI you like on top; this package imposes zero styling.
10
+ *
11
+ * • Batteries-included — `<SmoothChat>` and the `parts` components render a
12
+ * complete, accessible chat surface themed entirely by `--smooth-*` CSS
13
+ * variables. Import the stylesheet once:
14
+ * import '@smooai/smooth-operator/react/styles.css';
15
+ *
16
+ * The protocol client itself lives in `@smooai/smooth-operator`; re-exported here
17
+ * for convenience so you can construct/share a client without a second import.
18
+ */
19
+ export { SmoothAgentClient, MessageTurn, ProtocolError, TurnTimeoutError } from '../index.js';
20
+ export { useConversation } from './use-conversation.js';
21
+ export { SmoothOperatorProvider, useSmoothOperator } from './provider.js';
22
+ export { themeToStyle } from './theme.js';
23
+ export { safeHttpUrl, extractCitations, extractFinalText } from './response.js';
24
+ export { SmoothChat } from './components/SmoothChat.js';
25
+ export { MessageList, MessageBubble, Citations, Composer, ConnectionStatusLabel } from './components/parts.js';
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAiC,MAAM,aAAa,CAAC;AAE7H,OAAO,EAAE,eAAe,EAA2D,MAAM,uBAAuB,CAAC;AACjH,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAqE,MAAM,eAAe,CAAC;AAE7I,OAAO,EAAE,YAAY,EAAkB,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEhF,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * SmoothOperatorProvider — optional context that owns a single shared
3
+ * {@link SmoothAgentClient} for a subtree.
4
+ *
5
+ * You don't need this to use the hooks (`useConversation` can take a `url`
6
+ * directly), but a provider is handy when several components share one WS
7
+ * connection, or when you want to construct the client yourself (custom
8
+ * transport, auth-token refresh, etc.) and hand it down.
9
+ */
10
+ import { SmoothAgentClient } from '../client.js';
11
+ import { type ReactNode } from 'react';
12
+ export interface SmoothOperatorContextValue {
13
+ client: SmoothAgentClient | null;
14
+ /** The base WS URL, if the provider was given one (so hooks can construct per-session clients). */
15
+ url: string | null;
16
+ }
17
+ export interface SmoothOperatorProviderProps {
18
+ /** A pre-constructed client to share. Takes precedence over `url`. */
19
+ client?: SmoothAgentClient;
20
+ /** A WS URL the provider memoizes a client from, if no `client` is passed. */
21
+ url?: string;
22
+ children: ReactNode;
23
+ }
24
+ export declare function SmoothOperatorProvider({ client, url, children }: SmoothOperatorProviderProps): import("react").FunctionComponentElement<import("react").ProviderProps<SmoothOperatorContextValue | null>>;
25
+ /** Read the nearest provider value, or `null` if there is no provider. */
26
+ export declare function useSmoothOperator(): SmoothOperatorContextValue | null;
27
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/react/provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAqD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE1F,MAAM,WAAW,0BAA0B;IACvC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACjC,mGAAmG;IACnG,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAID,MAAM,WAAW,2BAA2B;IACxC,sEAAsE;IACtE,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,8EAA8E;IAC9E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;CACvB;AAED,wBAAgB,sBAAsB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,2BAA2B,8GAM5F;AAED,0EAA0E;AAC1E,wBAAgB,iBAAiB,IAAI,0BAA0B,GAAG,IAAI,CAErE"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * SmoothOperatorProvider — optional context that owns a single shared
3
+ * {@link SmoothAgentClient} for a subtree.
4
+ *
5
+ * You don't need this to use the hooks (`useConversation` can take a `url`
6
+ * directly), but a provider is handy when several components share one WS
7
+ * connection, or when you want to construct the client yourself (custom
8
+ * transport, auth-token refresh, etc.) and hand it down.
9
+ */
10
+ import { SmoothAgentClient } from '../client.js';
11
+ import { createContext, createElement, useContext, useMemo } from 'react';
12
+ const SmoothOperatorContext = createContext(null);
13
+ export function SmoothOperatorProvider({ client, url, children }) {
14
+ const value = useMemo(() => {
15
+ if (client)
16
+ return { client, url: url ?? null };
17
+ return { client: null, url: url ?? null };
18
+ }, [client, url]);
19
+ return createElement(SmoothOperatorContext.Provider, { value }, children);
20
+ }
21
+ /** Read the nearest provider value, or `null` if there is no provider. */
22
+ export function useSmoothOperator() {
23
+ return useContext(SmoothOperatorContext);
24
+ }
25
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/react/provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAkB,MAAM,OAAO,CAAC;AAQ1F,MAAM,qBAAqB,GAAG,aAAa,CAAoC,IAAI,CAAC,CAAC;AAUrF,MAAM,UAAU,sBAAsB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAA+B;IACzF,MAAM,KAAK,GAAG,OAAO,CAA6B,GAAG,EAAE;QACnD,IAAI,MAAM;YAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC;QAChD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC;IAC9C,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAClB,OAAO,aAAa,CAAC,qBAAqB,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC9E,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,iBAAiB;IAC7B,OAAO,UAAU,CAAC,qBAAqB,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Defensive readers for the terminal `eventual_response` payload.
3
+ *
4
+ * These mirror the widget's internal helpers: the server's response envelope and
5
+ * citation list are optional and back-compatible, so we tolerate their total
6
+ * absence, non-array shapes, and missing fields rather than letting a slightly
7
+ * different server break rendering.
8
+ */
9
+ import type { Citation } from '../types.js';
10
+ /** Pull the final assistant text out of an `eventual_response` data payload. */
11
+ export declare function extractFinalText(response: unknown): string | null;
12
+ /** Pull the grounding {@link Citation}s out of a terminal `eventual_response`'s inner data. */
13
+ export declare function extractCitations(inner: unknown): Citation[];
14
+ /**
15
+ * Only `http(s)` URLs become anchor hrefs. Mirrors the widget's `safeHttpUrl`
16
+ * XSS guard so a `javascript:`/`data:` citation URL can never become a live link.
17
+ */
18
+ export declare function safeHttpUrl(url: string | undefined): string | undefined;
19
+ //# sourceMappingURL=response.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../src/react/response.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAOjE;AAED,+FAA+F;AAC/F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,EAAE,CAgB3D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAavE"}
@@ -0,0 +1,53 @@
1
+ /** Pull the final assistant text out of an `eventual_response` data payload. */
2
+ export function extractFinalText(response) {
3
+ if (!response || typeof response !== 'object')
4
+ return null;
5
+ const r = response;
6
+ if (Array.isArray(r.responseParts)) {
7
+ return r.responseParts.filter((p) => typeof p === 'string').join('\n\n');
8
+ }
9
+ return null;
10
+ }
11
+ /** Pull the grounding {@link Citation}s out of a terminal `eventual_response`'s inner data. */
12
+ export function extractCitations(inner) {
13
+ if (!inner || typeof inner !== 'object')
14
+ return [];
15
+ const raw = inner.citations;
16
+ if (!Array.isArray(raw))
17
+ return [];
18
+ const out = [];
19
+ for (const c of raw) {
20
+ if (!c || typeof c !== 'object')
21
+ continue;
22
+ const obj = c;
23
+ const id = typeof obj.id === 'string' ? obj.id : '';
24
+ const title = typeof obj.title === 'string' ? obj.title : id || 'Source';
25
+ const snippet = typeof obj.snippet === 'string' ? obj.snippet : '';
26
+ const url = typeof obj.url === 'string' && obj.url ? obj.url : undefined;
27
+ const score = typeof obj.score === 'number' ? obj.score : 0;
28
+ out.push({ id, title, snippet, score, url });
29
+ }
30
+ return out;
31
+ }
32
+ /**
33
+ * Only `http(s)` URLs become anchor hrefs. Mirrors the widget's `safeHttpUrl`
34
+ * XSS guard so a `javascript:`/`data:` citation URL can never become a live link.
35
+ */
36
+ export function safeHttpUrl(url) {
37
+ if (!url)
38
+ return undefined;
39
+ try {
40
+ const parsed = new URL(url, 'http://invalid.local');
41
+ if (parsed.protocol === 'http:' || parsed.protocol === 'https:') {
42
+ // Reject the sentinel base — only keep genuinely absolute http(s) URLs.
43
+ if (!/^https?:/i.test(url))
44
+ return undefined;
45
+ return url;
46
+ }
47
+ }
48
+ catch {
49
+ return undefined;
50
+ }
51
+ return undefined;
52
+ }
53
+ //# sourceMappingURL=response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/react/response.ts"],"names":[],"mappings":"AAUA,gFAAgF;AAChF,MAAM,UAAU,gBAAgB,CAAC,QAAiB;IAC9C,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3D,MAAM,CAAC,GAAG,QAAuC,CAAC;IAClD,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC3C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACnD,MAAM,GAAG,GAAI,KAAiC,CAAC,SAAS,CAAC;IACzD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,SAAS;QAC1C,MAAM,GAAG,GAAG,CAA4B,CAAC;QACzC,MAAM,EAAE,GAAG,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,QAAQ,CAAC;QACzE,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,MAAM,GAAG,GAAG,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QACzE,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,GAAuB;IAC/C,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;QACpD,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC9D,wEAAwE;YACxE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;gBAAE,OAAO,SAAS,CAAC;YAC7C,OAAO,GAAG,CAAC;QACf,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Theming via CSS custom properties.
3
+ *
4
+ * Every color/shape the components use is a `--smooth-*` CSS variable with a
5
+ * default declared in `styles.css` (scoped to `.smooth-chat`, never `:root`, so
6
+ * it can't leak into the host page). There are three ways to retheme, in order
7
+ * of precedence (later wins):
8
+ *
9
+ * 1. **Your own CSS / Tailwind.** Override the variables on `.smooth-chat`
10
+ * (or any ancestor), e.g. in a Tailwind `@layer base` block:
11
+ * .smooth-chat { --smooth-color-primary: theme(colors.indigo.600); }
12
+ * Because they're plain CSS variables, `theme()`, design tokens, and
13
+ * light/dark media queries all just work — no build coupling to this package.
14
+ *
15
+ * 2. **A `theme` prop** on `<SmoothChat>` (or `themeToStyle(theme)` spread onto
16
+ * any element you render the hook into). This sets the variables inline, so
17
+ * it wins over stylesheet rules and is the easiest per-instance override.
18
+ *
19
+ * 3. **Inline `style`** on the element, for one-off tweaks.
20
+ *
21
+ * Keys intentionally match `@smooai/chat-widget`'s `ChatWidgetTheme` so a brand
22
+ * palette ports between the web-component widget and these React components
23
+ * unchanged.
24
+ */
25
+ import type { CSSProperties } from 'react';
26
+ export interface ChatTheme {
27
+ /** Foreground text color. → `--smooth-color-text` */
28
+ text?: string;
29
+ /** Outer surface / page background. → `--smooth-color-bg` */
30
+ background?: string;
31
+ /** Panel (message column) background. → `--smooth-color-surface` */
32
+ surface?: string;
33
+ /** Primary accent (header, send button, user bubble). → `--smooth-color-primary` */
34
+ primary?: string;
35
+ /** Text rendered on top of `primary`. → `--smooth-color-primary-text` */
36
+ primaryText?: string;
37
+ /** Assistant bubble background. → `--smooth-color-assistant-bubble` */
38
+ assistantBubble?: string;
39
+ /** Assistant bubble text. → `--smooth-color-assistant-bubble-text` */
40
+ assistantBubbleText?: string;
41
+ /** User bubble background (defaults to `primary`). → `--smooth-color-user-bubble` */
42
+ userBubble?: string;
43
+ /** User bubble text (defaults to `primaryText`). → `--smooth-color-user-bubble-text` */
44
+ userBubbleText?: string;
45
+ /** Border / divider color. → `--smooth-color-border` */
46
+ border?: string;
47
+ /** Secondary / muted text (status, snippets). → `--smooth-color-muted` */
48
+ muted?: string;
49
+ /** Corner radius for bubbles, inputs, the panel. → `--smooth-radius` */
50
+ radius?: string;
51
+ /** Font family for the whole surface. → `--smooth-font` */
52
+ fontFamily?: string;
53
+ }
54
+ /**
55
+ * Turn a {@link ChatTheme} into a `style` object of CSS custom properties.
56
+ * Only keys you set are emitted; everything else falls back to the defaults in
57
+ * `styles.css`. Spread it onto the root element:
58
+ *
59
+ * ```tsx
60
+ * <div className="smooth-chat" style={themeToStyle({ primary: '#4f46e5' })}>…</div>
61
+ * ```
62
+ */
63
+ export declare function themeToStyle(theme: ChatTheme | undefined): CSSProperties;
64
+ //# sourceMappingURL=theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/react/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,MAAM,WAAW,SAAS;IACtB,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wFAAwF;IACxF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAmBD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,aAAa,CAUxE"}
@@ -0,0 +1,38 @@
1
+ /** Map each `ChatTheme` key to its CSS custom property name. */
2
+ const VAR_BY_KEY = {
3
+ text: '--smooth-color-text',
4
+ background: '--smooth-color-bg',
5
+ surface: '--smooth-color-surface',
6
+ primary: '--smooth-color-primary',
7
+ primaryText: '--smooth-color-primary-text',
8
+ assistantBubble: '--smooth-color-assistant-bubble',
9
+ assistantBubbleText: '--smooth-color-assistant-bubble-text',
10
+ userBubble: '--smooth-color-user-bubble',
11
+ userBubbleText: '--smooth-color-user-bubble-text',
12
+ border: '--smooth-color-border',
13
+ muted: '--smooth-color-muted',
14
+ radius: '--smooth-radius',
15
+ fontFamily: '--smooth-font',
16
+ };
17
+ /**
18
+ * Turn a {@link ChatTheme} into a `style` object of CSS custom properties.
19
+ * Only keys you set are emitted; everything else falls back to the defaults in
20
+ * `styles.css`. Spread it onto the root element:
21
+ *
22
+ * ```tsx
23
+ * <div className="smooth-chat" style={themeToStyle({ primary: '#4f46e5' })}>…</div>
24
+ * ```
25
+ */
26
+ export function themeToStyle(theme) {
27
+ const style = {};
28
+ if (!theme)
29
+ return style;
30
+ for (const key of Object.keys(theme)) {
31
+ const value = theme[key];
32
+ if (typeof value === 'string' && value.length > 0) {
33
+ style[VAR_BY_KEY[key]] = value;
34
+ }
35
+ }
36
+ return style;
37
+ }
38
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/react/theme.ts"],"names":[],"mappings":"AAuDA,gEAAgE;AAChE,MAAM,UAAU,GAAoC;IAChD,IAAI,EAAE,qBAAqB;IAC3B,UAAU,EAAE,mBAAmB;IAC/B,OAAO,EAAE,wBAAwB;IACjC,OAAO,EAAE,wBAAwB;IACjC,WAAW,EAAE,6BAA6B;IAC1C,eAAe,EAAE,iCAAiC;IAClD,mBAAmB,EAAE,sCAAsC;IAC3D,UAAU,EAAE,4BAA4B;IACxC,cAAc,EAAE,iCAAiC;IACjD,MAAM,EAAE,uBAAuB;IAC/B,KAAK,EAAE,sBAAsB;IAC7B,MAAM,EAAE,iBAAiB;IACzB,UAAU,EAAE,eAAe;CAC9B,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,KAA4B;IACrD,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAsB,CAAC;IAC1C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAwB,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChD,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;QACnC,CAAC;IACL,CAAC;IACD,OAAO,KAAsB,CAAC;AAClC,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Shared types for the React bindings.
3
+ *
4
+ * The message + citation shapes mirror `@smooai/chat-widget`'s
5
+ * `ConversationController` exactly, so the two presentation layers stay
6
+ * interchangeable over the same protocol client.
7
+ */
8
+ import type { Citation } from '../types.js';
9
+ export type { Citation };
10
+ export type Role = 'user' | 'assistant';
11
+ /** A single rendered chat message. Assistant messages grow as tokens stream in. */
12
+ export interface ChatMessage {
13
+ id: string;
14
+ role: Role;
15
+ /** Accumulated text (assistant messages grow as `stream_token` events arrive). */
16
+ text: string;
17
+ /** True while an assistant message is still streaming. */
18
+ streaming: boolean;
19
+ /** Grounding sources, present only when the terminal `eventual_response` carried any. */
20
+ citations?: Citation[];
21
+ }
22
+ /** Connection lifecycle of a conversation. */
23
+ export type ConnectionStatus = 'idle' | 'connecting' | 'ready' | 'error' | 'closed';
24
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/react/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,YAAY,EAAE,QAAQ,EAAE,CAAC;AAEzB,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,WAAW,CAAC;AAExC,mFAAmF;AACnF,MAAM,WAAW,WAAW;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,IAAI,CAAC;IACX,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,SAAS,EAAE,OAAO,CAAC;IACnB,yFAAyF;IACzF,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CAC1B;AAED,8CAA8C;AAC9C,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,YAAY,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/react/types.ts"],"names":[],"mappings":""}