@syntrologie/adapt-chatbot 2.8.0-canary.9 → 2.8.0-canary.91

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 (37) hide show
  1. package/dist/ChatAssistantLit.d.ts +69 -0
  2. package/dist/ChatAssistantLit.d.ts.map +1 -0
  3. package/dist/ChatAssistantLit.js +383 -0
  4. package/dist/SyntroChatbot.d.ts +14 -0
  5. package/dist/SyntroChatbot.d.ts.map +1 -0
  6. package/dist/SyntroChatbot.js +56 -0
  7. package/dist/editor.d.ts.map +1 -1
  8. package/dist/editor.js +2 -2
  9. package/dist/runtime-lit.d.ts +29 -0
  10. package/dist/runtime-lit.d.ts.map +1 -0
  11. package/dist/runtime-lit.js +32 -0
  12. package/dist/runtime.d.ts.map +1 -1
  13. package/dist/runtime.js +10 -0
  14. package/dist/tools/bridge.d.ts +26 -0
  15. package/dist/tools/bridge.d.ts.map +1 -0
  16. package/dist/tools/bridge.js +25 -0
  17. package/dist/tools/expanders.d.ts +17 -0
  18. package/dist/tools/expanders.d.ts.map +1 -0
  19. package/dist/tools/expanders.js +41 -0
  20. package/dist/tools/index.d.ts +14 -0
  21. package/dist/tools/index.d.ts.map +1 -0
  22. package/dist/tools/index.js +11 -0
  23. package/dist/tools/registrations/GetContextTool.d.ts +7 -0
  24. package/dist/tools/registrations/GetContextTool.d.ts.map +1 -0
  25. package/dist/tools/registrations/GetContextTool.js +18 -0
  26. package/dist/tools/registrations/ScrollToTool.d.ts +7 -0
  27. package/dist/tools/registrations/ScrollToTool.d.ts.map +1 -0
  28. package/dist/tools/registrations/ScrollToTool.js +38 -0
  29. package/dist/tools/registrations/ShowOverlayTool.d.ts +7 -0
  30. package/dist/tools/registrations/ShowOverlayTool.d.ts.map +1 -0
  31. package/dist/tools/registrations/ShowOverlayTool.js +47 -0
  32. package/dist/tools/registrations/index.d.ts +19 -0
  33. package/dist/tools/registrations/index.d.ts.map +1 -0
  34. package/dist/tools/registrations/index.js +7 -0
  35. package/dist/types.d.ts +9 -0
  36. package/dist/types.d.ts.map +1 -1
  37. package/package.json +29 -11
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Adaptive Chatbot - ChatAssistantLit
3
+ *
4
+ * Lit web component equivalent of ChatAssistant.tsx.
5
+ * Renders a message list with auto-scroll, typing indicator, error banner,
6
+ * and a composer input — all without React or Shadow DOM.
7
+ *
8
+ * Custom element: <syntro-chat-assistant>
9
+ *
10
+ * Decorator-free: uses `static override properties` (tsconfig has no
11
+ * experimentalDecorators).
12
+ *
13
+ * Light DOM (createRenderRoot returns `this`) so host-page CSS variables
14
+ * and the widget's inline styles both apply without :host() friction.
15
+ */
16
+ import { LitElement } from 'lit';
17
+ import type { ChatbotConfig, ChatbotWidgetRuntime, ChatMessage } from './types.js';
18
+ export interface ChatAssistantLitProps {
19
+ config: ChatbotConfig;
20
+ runtime: ChatbotWidgetRuntime;
21
+ tileId?: string;
22
+ }
23
+ export declare class ChatAssistantElement extends LitElement {
24
+ #private;
25
+ createRenderRoot(): this;
26
+ static properties: {
27
+ config: {
28
+ attribute: boolean;
29
+ };
30
+ runtime: {
31
+ attribute: boolean;
32
+ };
33
+ tileId: {
34
+ type: StringConstructor;
35
+ };
36
+ _messages: {
37
+ state: boolean;
38
+ };
39
+ _isLoading: {
40
+ state: boolean;
41
+ };
42
+ _error: {
43
+ state: boolean;
44
+ };
45
+ };
46
+ config: ChatbotConfig | undefined;
47
+ runtime: ChatbotWidgetRuntime | undefined;
48
+ tileId: string;
49
+ /** @internal */ _messages: ChatMessage[];
50
+ /** @internal */ _isLoading: boolean;
51
+ /** @internal */ _error: string | null;
52
+ connectedCallback(): void;
53
+ disconnectedCallback(): void;
54
+ firstUpdated(): void;
55
+ updated(changed: Map<string, unknown>): void;
56
+ render(): import("lit-html").TemplateResult<1>;
57
+ /** Programmatically clear the conversation (mirrors useChat.clearMessages) */
58
+ clearMessages(): void;
59
+ }
60
+ export declare const registerChatAssistantElement: () => void;
61
+ declare global {
62
+ interface HTMLElementTagNameMap {
63
+ 'syntro-chat-assistant': ChatAssistantElement;
64
+ }
65
+ }
66
+ export declare const ChatAssistantLitMountable: {
67
+ mount(container: HTMLElement, mountConfig?: Record<string, unknown>): () => void;
68
+ };
69
+ //# sourceMappingURL=ChatAssistantLit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatAssistantLit.d.ts","sourceRoot":"","sources":["../src/ChatAssistantLit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAQ,UAAU,EAAW,MAAM,KAAK,CAAC;AAKhD,OAAO,KAAK,EAEV,aAAa,EACb,oBAAoB,EACpB,WAAW,EACZ,MAAM,YAAY,CAAC;AAgIpB,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAMD,qBAAa,oBAAqB,SAAQ,UAAU;;IAGzC,gBAAgB;IAMzB,OAAgB,UAAU;;;;;;;;;;;;;;;;;;;MAUxB;IAIF,MAAM,EAAE,aAAa,GAAG,SAAS,CAAa;IAC9C,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAa;IACtD,MAAM,SAAoB;IAI1B,gBAAgB,CAAC,SAAS,EAAE,WAAW,EAAE,CAAM;IAC/C,gBAAgB,CAAC,UAAU,UAAS;IACpC,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAQ;IAUrC,iBAAiB,IAAI,IAAI;IAMzB,oBAAoB,IAAI,IAAI;IAc5B,YAAY,IAAI,IAAI;IAQpB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAuB5C,MAAM;IAqJf,8EAA8E;IAC9E,aAAa,IAAI,IAAI;CAWtB;AAQD,eAAO,MAAM,4BAA4B,QAAO,IAK/C,CAAC;AAEF,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,uBAAuB,EAAE,oBAAoB,CAAC;KAC/C;CACF;AAMD,eAAO,MAAM,yBAAyB;qBACnB,WAAW,gBAAgB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAiCpE,CAAC"}
@@ -0,0 +1,383 @@
1
+ /**
2
+ * Adaptive Chatbot - ChatAssistantLit
3
+ *
4
+ * Lit web component equivalent of ChatAssistant.tsx.
5
+ * Renders a message list with auto-scroll, typing indicator, error banner,
6
+ * and a composer input — all without React or Shadow DOM.
7
+ *
8
+ * Custom element: <syntro-chat-assistant>
9
+ *
10
+ * Decorator-free: uses `static override properties` (tsconfig has no
11
+ * experimentalDecorators).
12
+ *
13
+ * Light DOM (createRenderRoot returns `this`) so host-page CSS variables
14
+ * and the widget's inline styles both apply without :host() friction.
15
+ */
16
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
17
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
18
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
19
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
20
+ };
21
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
22
+ if (kind === "m") throw new TypeError("Private method is not writable");
23
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
24
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
25
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
26
+ };
27
+ var _ChatAssistantElement_instances, _ChatAssistantElement_batchHandle, _ChatAssistantElement_inputEl, _ChatAssistantElement_messageListEl, _ChatAssistantElement_renderBubble, _ChatAssistantElement_handleSubmit, _ChatAssistantElement_sendMessage;
28
+ import { html, LitElement, nothing } from 'lit';
29
+ import { styleMap } from 'lit/directives/style-map.js';
30
+ import { parseActions } from './actionParser.js';
31
+ import { sendMessage } from './apiClient.js';
32
+ // ============================================================================
33
+ // Design-system color tokens (inlined to avoid a runtime import chain)
34
+ // purple[4]=#6a59ce base.white=#ffffff slateGrey[10]=#cbd0d7
35
+ // slateGrey[12]=#f6f7f9 slateGrey[8]=#87919f slateGrey[7]=#677384
36
+ // red[4]=#ff2524
37
+ // ============================================================================
38
+ const PURPLE_4 = '#6a59ce';
39
+ const WHITE = '#ffffff';
40
+ const SLATE_10 = '#cbd0d7';
41
+ const SLATE_12 = '#f6f7f9';
42
+ const SLATE_8 = '#87919f';
43
+ const SLATE_7 = '#677384';
44
+ const RED_4 = '#ff2524';
45
+ // ============================================================================
46
+ // ID generator (matches the one in useChat.ts)
47
+ // ============================================================================
48
+ let _nextId = 0;
49
+ function generateId() {
50
+ return `msg-${Date.now()}-${++_nextId}`;
51
+ }
52
+ // ============================================================================
53
+ // Style objects (mirrors ChatAssistant.tsx styles const)
54
+ // ============================================================================
55
+ const containerStyle = {
56
+ display: 'flex',
57
+ flexDirection: 'column',
58
+ height: '100%',
59
+ fontFamily: 'system-ui, -apple-system, sans-serif',
60
+ fontSize: '14px',
61
+ touchAction: 'none',
62
+ };
63
+ const messageListStyle = {
64
+ flex: '1',
65
+ overflowY: 'auto',
66
+ padding: '12px',
67
+ display: 'flex',
68
+ flexDirection: 'column',
69
+ gap: '8px',
70
+ };
71
+ const bubbleBaseStyle = {
72
+ maxWidth: '85%',
73
+ padding: '8px 12px',
74
+ borderRadius: '12px',
75
+ lineHeight: '1.5',
76
+ wordBreak: 'break-word',
77
+ };
78
+ const userBubbleExtra = {
79
+ alignSelf: 'flex-end',
80
+ backgroundColor: PURPLE_4,
81
+ color: WHITE,
82
+ borderBottomRightRadius: '4px',
83
+ };
84
+ const assistantBubbleExtra = {
85
+ alignSelf: 'flex-start',
86
+ backgroundColor: 'rgba(255, 255, 255, 0.08)',
87
+ color: SLATE_10,
88
+ borderBottomLeftRadius: '4px',
89
+ };
90
+ const loadingDotsStyle = {
91
+ alignSelf: 'flex-start',
92
+ padding: '8px 16px',
93
+ backgroundColor: 'rgba(255, 255, 255, 0.05)',
94
+ borderRadius: '12px',
95
+ color: SLATE_8,
96
+ fontSize: '13px',
97
+ };
98
+ const errorBannerStyle = {
99
+ padding: '8px 12px',
100
+ backgroundColor: 'rgba(239, 68, 68, 0.1)',
101
+ color: RED_4,
102
+ fontSize: '13px',
103
+ borderRadius: '8px',
104
+ margin: '0 12px',
105
+ };
106
+ const inputFormStyle = {
107
+ display: 'flex',
108
+ gap: '8px',
109
+ padding: '12px',
110
+ borderTop: '1px solid rgba(255, 255, 255, 0.06)',
111
+ };
112
+ const inputStyle = {
113
+ flex: '1',
114
+ padding: '8px 12px',
115
+ borderRadius: '8px',
116
+ border: '1px solid rgba(255, 255, 255, 0.1)',
117
+ backgroundColor: 'rgba(0, 0, 0, 0.2)',
118
+ color: SLATE_12,
119
+ fontSize: '14px',
120
+ outline: 'none',
121
+ fontFamily: 'inherit',
122
+ };
123
+ const sendButtonStyle = {
124
+ padding: '8px 16px',
125
+ borderRadius: '8px',
126
+ border: 'none',
127
+ backgroundColor: PURPLE_4,
128
+ color: WHITE,
129
+ fontWeight: '600',
130
+ fontSize: '13px',
131
+ cursor: 'pointer',
132
+ whiteSpace: 'nowrap',
133
+ };
134
+ const sendButtonDisabledExtra = {
135
+ opacity: '0.5',
136
+ cursor: 'not-allowed',
137
+ };
138
+ // ============================================================================
139
+ // ChatAssistantElement — Lit element
140
+ // ============================================================================
141
+ export class ChatAssistantElement extends LitElement {
142
+ constructor() {
143
+ // ---------- Light DOM: inherit host styles, no shadow boundary ----------
144
+ super(...arguments);
145
+ _ChatAssistantElement_instances.add(this);
146
+ // ---------- Public input properties --------------------------------------
147
+ this.config = undefined;
148
+ this.runtime = undefined;
149
+ this.tileId = 'chatbot-widget';
150
+ // ---------- Internal reactive state -------------------------------------
151
+ /** @internal */ this._messages = [];
152
+ /** @internal */ this._isLoading = false;
153
+ /** @internal */ this._error = null;
154
+ // ---------- Private (non-reactive) fields --------------------------------
155
+ _ChatAssistantElement_batchHandle.set(this, null);
156
+ _ChatAssistantElement_inputEl.set(this, null);
157
+ _ChatAssistantElement_messageListEl.set(this, null);
158
+ // ---------- Event handlers ----------------------------------------------
159
+ _ChatAssistantElement_handleSubmit.set(this, (e) => {
160
+ e.preventDefault();
161
+ const input = __classPrivateFieldGet(this, _ChatAssistantElement_inputEl, "f") ?? this.querySelector('[data-chat-input]');
162
+ if (!input || !input.value.trim() || this._isLoading)
163
+ return;
164
+ const text = input.value;
165
+ input.value = '';
166
+ __classPrivateFieldGet(this, _ChatAssistantElement_instances, "m", _ChatAssistantElement_sendMessage).call(this, text);
167
+ });
168
+ }
169
+ createRenderRoot() {
170
+ return this;
171
+ }
172
+ // ---------- Lifecycle: connectedCallback --------------------------------
173
+ connectedCallback() {
174
+ super.connectedCallback();
175
+ }
176
+ // ---------- Lifecycle: disconnectedCallback -----------------------------
177
+ disconnectedCallback() {
178
+ super.disconnectedCallback();
179
+ // Revert any active actions on unmount (mirrors useChat cleanup)
180
+ if (__classPrivateFieldGet(this, _ChatAssistantElement_batchHandle, "f")?.isApplied()) {
181
+ __classPrivateFieldGet(this, _ChatAssistantElement_batchHandle, "f").revertAll().catch((err) => {
182
+ console.error('[ChatAssistantElement] Failed to revert actions on disconnect:', err);
183
+ });
184
+ __classPrivateFieldSet(this, _ChatAssistantElement_batchHandle, null, "f");
185
+ }
186
+ }
187
+ // ---------- Lifecycle: firstUpdated -------------------------------------
188
+ firstUpdated() {
189
+ // Cache references to imperative DOM nodes once (elements never change identity)
190
+ __classPrivateFieldSet(this, _ChatAssistantElement_inputEl, this.querySelector('[data-chat-input]'), "f");
191
+ __classPrivateFieldSet(this, _ChatAssistantElement_messageListEl, this.querySelector('[data-message-list]'), "f");
192
+ }
193
+ // ---------- Lifecycle: updated ------------------------------------------
194
+ updated(changed) {
195
+ // Auto-scroll to bottom when messages change
196
+ if (changed.has('_messages') || changed.has('_isLoading')) {
197
+ if (__classPrivateFieldGet(this, _ChatAssistantElement_messageListEl, "f")) {
198
+ __classPrivateFieldGet(this, _ChatAssistantElement_messageListEl, "f").scrollTop = __classPrivateFieldGet(this, _ChatAssistantElement_messageListEl, "f").scrollHeight;
199
+ }
200
+ }
201
+ // Seed greeting when config is set after construction
202
+ if (changed.has('config') && this.config?.greeting && this._messages.length === 0) {
203
+ this._messages = [
204
+ {
205
+ id: generateId(),
206
+ role: 'assistant',
207
+ text: this.config.greeting,
208
+ timestamp: Date.now(),
209
+ },
210
+ ];
211
+ }
212
+ }
213
+ // ---------- Render -------------------------------------------------------
214
+ render() {
215
+ return html `
216
+ <div style=${styleMap(containerStyle)} data-testid="chat-assistant">
217
+ <!-- Message list -->
218
+ <div style=${styleMap(messageListStyle)} data-message-list>
219
+ ${this._messages.map((msg) => __classPrivateFieldGet(this, _ChatAssistantElement_instances, "m", _ChatAssistantElement_renderBubble).call(this, msg))}
220
+ ${this._isLoading ? html `<div style=${styleMap(loadingDotsStyle)}>Thinking...</div>` : nothing}
221
+ </div>
222
+
223
+ <!-- Error banner -->
224
+ ${this._error
225
+ ? html `<div style=${styleMap(errorBannerStyle)}>${this._error}</div>`
226
+ : nothing}
227
+
228
+ <!-- Composer -->
229
+ <form
230
+ style=${styleMap(inputFormStyle)}
231
+ @submit=${__classPrivateFieldGet(this, _ChatAssistantElement_handleSubmit, "f")}
232
+ >
233
+ <input
234
+ data-chat-input
235
+ style=${styleMap(inputStyle)}
236
+ placeholder="Ask anything..."
237
+ ?disabled=${this._isLoading}
238
+ data-testid="chat-input"
239
+ />
240
+ <button
241
+ type="submit"
242
+ ?disabled=${this._isLoading}
243
+ style=${styleMap(this._isLoading ? { ...sendButtonStyle, ...sendButtonDisabledExtra } : sendButtonStyle)}
244
+ data-testid="chat-send"
245
+ >
246
+ Send
247
+ </button>
248
+ </form>
249
+ </div>
250
+ `;
251
+ }
252
+ // ---------- Public API --------------------------------------------------
253
+ /** Programmatically clear the conversation (mirrors useChat.clearMessages) */
254
+ clearMessages() {
255
+ this._messages = [];
256
+ this._error = null;
257
+ if (__classPrivateFieldGet(this, _ChatAssistantElement_batchHandle, "f")?.isApplied()) {
258
+ __classPrivateFieldGet(this, _ChatAssistantElement_batchHandle, "f").revertAll().catch((err) => {
259
+ console.error('[ChatAssistantElement] Failed to revert actions on clear:', err);
260
+ });
261
+ __classPrivateFieldSet(this, _ChatAssistantElement_batchHandle, null, "f");
262
+ }
263
+ sessionStorage.removeItem(`syntro:chatbot:history:${this.tileId}`);
264
+ }
265
+ }
266
+ _ChatAssistantElement_batchHandle = new WeakMap(), _ChatAssistantElement_inputEl = new WeakMap(), _ChatAssistantElement_messageListEl = new WeakMap(), _ChatAssistantElement_handleSubmit = new WeakMap(), _ChatAssistantElement_instances = new WeakSet(), _ChatAssistantElement_renderBubble = function _ChatAssistantElement_renderBubble(msg) {
267
+ const isUser = msg.role === 'user';
268
+ const bubbleStyle = isUser
269
+ ? { ...bubbleBaseStyle, ...userBubbleExtra }
270
+ : { ...bubbleBaseStyle, ...assistantBubbleExtra };
271
+ return html `<div style=${styleMap(bubbleStyle)}>${msg.text}</div>`;
272
+ }, _ChatAssistantElement_sendMessage =
273
+ // ---------- Message sending logic (replaces useChat) --------------------
274
+ async function _ChatAssistantElement_sendMessage(text) {
275
+ const trimmed = text.trim();
276
+ if (!trimmed || !this.config || !this.runtime)
277
+ return;
278
+ this._error = null;
279
+ const userMessage = {
280
+ id: generateId(),
281
+ role: 'user',
282
+ text: trimmed,
283
+ timestamp: Date.now(),
284
+ };
285
+ this._messages = [...this._messages, userMessage];
286
+ this._isLoading = true;
287
+ // Fire custom event so parent components / SDK can observe submission
288
+ this.dispatchEvent(new CustomEvent('chat-message-sent', {
289
+ detail: { text: trimmed },
290
+ bubbles: true,
291
+ }));
292
+ try {
293
+ const maxHistory = this.config.maxHistory ?? 20;
294
+ const historySlice = [...this._messages].slice(-maxHistory).map((m) => ({
295
+ role: m.role,
296
+ content: m.text,
297
+ }));
298
+ const response = await sendMessage(this.config.backendUrl, {
299
+ message: trimmed,
300
+ history: historySlice,
301
+ mlflow_run_id: this.config.mlflowRunId,
302
+ });
303
+ const { displayText, actions } = parseActions(response.response);
304
+ const assistantMessage = {
305
+ id: generateId(),
306
+ role: 'assistant',
307
+ text: displayText,
308
+ timestamp: Date.now(),
309
+ };
310
+ this._messages = [...this._messages, assistantMessage];
311
+ // Execute actions if present (mirrors useChat action lifecycle)
312
+ if (actions.length > 0) {
313
+ if (__classPrivateFieldGet(this, _ChatAssistantElement_batchHandle, "f")?.isApplied()) {
314
+ await __classPrivateFieldGet(this, _ChatAssistantElement_batchHandle, "f").revertAll();
315
+ }
316
+ __classPrivateFieldSet(this, _ChatAssistantElement_batchHandle, await this.runtime.actions.applyBatch(actions), "f");
317
+ this.runtime.events.publish('chatbot.actions_applied', {
318
+ count: actions.length,
319
+ kinds: actions.map((a) => a.kind),
320
+ tileId: this.tileId,
321
+ });
322
+ }
323
+ // Fire custom event with the assistant reply
324
+ this.dispatchEvent(new CustomEvent('chat-response-received', {
325
+ detail: { text: displayText, actions },
326
+ bubbles: true,
327
+ }));
328
+ }
329
+ catch (err) {
330
+ const message = err instanceof Error ? err.message : 'An unexpected error occurred';
331
+ this._error = message;
332
+ }
333
+ finally {
334
+ this._isLoading = false;
335
+ }
336
+ };
337
+ // ---------- Reactive property declarations (no decorators) ---------------
338
+ ChatAssistantElement.properties = {
339
+ // Public inputs
340
+ config: { attribute: false },
341
+ runtime: { attribute: false },
342
+ tileId: { type: String },
343
+ // Internal reactive state
344
+ _messages: { state: true },
345
+ _isLoading: { state: true },
346
+ _error: { state: true },
347
+ };
348
+ // ============================================================================
349
+ // Custom element registration
350
+ // ============================================================================
351
+ const TAG_NAME = 'syntro-chat-assistant';
352
+ export const registerChatAssistantElement = () => {
353
+ if (typeof window === 'undefined')
354
+ return;
355
+ if (!customElements.get(TAG_NAME)) {
356
+ customElements.define(TAG_NAME, ChatAssistantElement);
357
+ }
358
+ };
359
+ // ============================================================================
360
+ // Mountable Widget Interface (Lit version — no React dependency)
361
+ // ============================================================================
362
+ export const ChatAssistantLitMountable = {
363
+ mount(container, mountConfig) {
364
+ const { config, runtime, tileId = 'chatbot-widget', } = (mountConfig ?? {});
365
+ if (!config || !runtime) {
366
+ container.innerHTML = `<div style="padding: 16px; color: ${SLATE_8};">Chat widget requires config and runtime.</div>`;
367
+ return () => {
368
+ container.innerHTML = '';
369
+ };
370
+ }
371
+ registerChatAssistantElement();
372
+ const el = document.createElement('syntro-chat-assistant');
373
+ el.config = config;
374
+ el.runtime = runtime;
375
+ el.tileId = tileId;
376
+ // Stretch to fill the container
377
+ el.style.cssText = 'display:flex;flex-direction:column;height:100%;width:100%;';
378
+ container.appendChild(el);
379
+ return () => {
380
+ el.remove();
381
+ };
382
+ },
383
+ };
@@ -0,0 +1,14 @@
1
+ import type { ChatbotWidgetRuntime } from './types';
2
+ export interface SyntroChatbotConfig {
3
+ /** Backend URL that returns Vercel AI SDK streaming response format */
4
+ backendUrl: string;
5
+ /** Greeting shown in the empty thread state */
6
+ greeting?: string;
7
+ }
8
+ export interface SyntroChatbotProps {
9
+ runtime: ChatbotWidgetRuntime;
10
+ config: SyntroChatbotConfig;
11
+ }
12
+ export declare function SyntroChatbot({ runtime, config }: SyntroChatbotProps): import("react/jsx-runtime").JSX.Element;
13
+ export default SyntroChatbot;
14
+ //# sourceMappingURL=SyntroChatbot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SyntroChatbot.d.ts","sourceRoot":"","sources":["../src/SyntroChatbot.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEpD,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,oBAAoB,CAAC;IAC9B,MAAM,EAAE,mBAAmB,CAAC;CAC7B;AA6BD,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,kBAAkB,2CAgEpE;AAED,eAAe,aAAa,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * SyntroChatbot — Supply Mode
4
+ *
5
+ * Convenience component for clients who want Syntro to provide the chat shell.
6
+ * Uses AssistantChatTransport (from @assistant-ui/react-ai-sdk) pointing at
7
+ * backendUrl. The backend must return Vercel AI SDK streaming format
8
+ * (toDataStreamResponse() from the `ai` package).
9
+ *
10
+ * For integration mode (client owns the shell), use SyntroTools instead:
11
+ * import { SyntroTools } from '@syntrologie/adapt-chatbot/tools'
12
+ */
13
+ import { AssistantRuntimeProvider, ComposerPrimitive, MessagePrimitive, ThreadPrimitive, useMessage, } from '@assistant-ui/react';
14
+ import { AssistantChatTransport, useChatRuntime } from '@assistant-ui/react-ai-sdk';
15
+ import { useMemo } from 'react';
16
+ import { SyntroTools } from './tools/registrations';
17
+ function ChatBubble() {
18
+ const message = useMessage();
19
+ const textParts = message.content?.filter((part) => part.type === 'text');
20
+ return (_jsx(MessagePrimitive.Root, { children: _jsx("div", { style: {
21
+ padding: '8px 12px',
22
+ borderRadius: '8px',
23
+ background: message.role === 'user' ? 'rgba(107, 70, 193, 0.15)' : 'rgba(255,255,255,0.05)',
24
+ alignSelf: message.role === 'user' ? 'flex-end' : 'flex-start',
25
+ maxWidth: '80%',
26
+ fontSize: '14px',
27
+ }, children: textParts?.map((part, i) => (_jsx("span", { children: part.text }, i))) }) }));
28
+ }
29
+ export function SyntroChatbot({ runtime, config }) {
30
+ const transport = useMemo(() => new AssistantChatTransport({ api: config.backendUrl }), [config.backendUrl]);
31
+ const chatRuntime = useChatRuntime({ transport });
32
+ return (_jsxs(AssistantRuntimeProvider, { runtime: chatRuntime, children: [_jsx(SyntroTools, { runtime: runtime }), _jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%' }, children: [_jsx(ThreadPrimitive.Root, { style: { flex: 1, overflowY: 'auto' }, children: _jsxs(ThreadPrimitive.Viewport, { style: { padding: '12px', display: 'flex', flexDirection: 'column', gap: '8px' }, children: [_jsx(ThreadPrimitive.Empty, { children: _jsx("div", { style: { padding: '24px', textAlign: 'center', fontSize: '14px', opacity: 0.7 }, children: config.greeting ?? 'Hi! How can I help?' }) }), _jsx(ThreadPrimitive.Messages, { components: {
33
+ UserMessage: ChatBubble,
34
+ AssistantMessage: ChatBubble,
35
+ } })] }) }), _jsx("div", { style: { borderTop: '1px solid rgba(255,255,255,0.1)', padding: '12px' }, children: _jsxs(ComposerPrimitive.Root, { style: { display: 'flex', gap: '8px' }, children: [_jsx(ComposerPrimitive.Input, { placeholder: "Ask me anything...", style: {
36
+ flex: 1,
37
+ padding: '8px 12px',
38
+ borderRadius: '8px',
39
+ border: '1px solid rgba(255,255,255,0.15)',
40
+ background: 'rgba(255,255,255,0.05)',
41
+ color: 'inherit',
42
+ fontSize: '14px',
43
+ fontFamily: 'inherit',
44
+ resize: 'none',
45
+ }, rows: 1 }), _jsx(ComposerPrimitive.Send, { style: {
46
+ padding: '8px 16px',
47
+ borderRadius: '8px',
48
+ border: 'none',
49
+ background: 'var(--syntro-purple-4, #6b46c1)',
50
+ color: 'white',
51
+ fontSize: '14px',
52
+ fontWeight: 600,
53
+ cursor: 'pointer',
54
+ }, children: "Send" })] }) })] })] }));
55
+ }
56
+ export default SyntroChatbot;
@@ -1 +1 @@
1
- {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAaH,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAM/D,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAoF3E;AAED;;GAEG;AACH,eAAO,MAAM,WAAW;;;;CAIvB,CAAC;AAEF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAM/D,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAkF3E;AAED;;GAEG;AACH,eAAO,MAAM,WAAW;;;;CAIvB,CAAC;AAEF,eAAe,aAAa,CAAC"}
package/dist/editor.js CHANGED
@@ -4,7 +4,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
4
  *
5
5
  * Visual editor panel for configuring chatbot tile props.
6
6
  */
7
- import { EditorBody, EditorFooter, EditorHeader, EditorInput, EditorLayout, EditorTextarea, } from '@syntrologie/shared-editor-ui';
7
+ import { EditorBody, EditorHeader, EditorInput, EditorLayout, EditorTextarea, } from '@syntrologie/shared-editor-ui';
8
8
  import { useEffect, useRef } from 'react';
9
9
  // ============================================================================
10
10
  // ChatbotEditor Component
@@ -23,7 +23,7 @@ export function ChatbotEditor({ config, onChange, editor }) {
23
23
  onChange({ ...config, [field]: value });
24
24
  editor.setDirty(true);
25
25
  };
26
- return (_jsxs(EditorLayout, { children: [_jsx(EditorHeader, { title: "Chat Assistant", subtitle: "Configure AI chat assistant", onBack: () => editor.navigateHome() }), _jsxs(EditorBody, { children: [_jsxs("div", { className: "se-mb-6", children: [_jsx("div", { className: "se-text-xs se-font-semibold se-text-slate-grey-8 se-uppercase se-tracking-wide se-mb-3", children: "API Configuration" }), _jsx(EditorInput, { label: "Backend URL", type: "text", value: typedConfig.backendUrl || '', onChange: (e) => handleChange('backendUrl', e.target.value), placeholder: "/api/chat/message" }), _jsx(EditorInput, { label: "MLflow Run ID (optional)", type: "text", value: typedConfig.mlflowRunId || '', onChange: (e) => handleChange('mlflowRunId', e.target.value), placeholder: "e.g., abc123" })] }), _jsxs("div", { className: "se-mb-6", children: [_jsx("div", { className: "se-text-xs se-font-semibold se-text-slate-grey-8 se-uppercase se-tracking-wide se-mb-3", children: "Chat Settings" }), _jsx(EditorTextarea, { label: "Greeting Message", value: typedConfig.greeting || '', onChange: (e) => handleChange('greeting', e.target.value), placeholder: "Hi! How can I help?" }), _jsx(EditorInput, { label: "Max History (messages sent to backend)", type: "number", value: typedConfig.maxHistory || 20, onChange: (e) => handleChange('maxHistory', parseInt(e.target.value, 10)), min: 1, max: 100 })] })] }), _jsx(EditorFooter, { onSave: () => editor.save(), onPublish: () => editor.publish() })] }));
26
+ return (_jsxs(EditorLayout, { children: [_jsx(EditorHeader, { title: "Chat Assistant", subtitle: "Configure AI chat assistant", onBack: () => editor.navigateHome() }), _jsxs(EditorBody, { children: [_jsxs("div", { className: "se-mb-6", children: [_jsx("div", { className: "se-text-xs se-font-semibold se-text-slate-grey-8 se-uppercase se-tracking-wide se-mb-3", children: "API Configuration" }), _jsx(EditorInput, { label: "Backend URL", type: "text", value: typedConfig.backendUrl || '', onChange: (e) => handleChange('backendUrl', e.target.value), placeholder: "/api/chat/message" }), _jsx(EditorInput, { label: "MLflow Run ID (optional)", type: "text", value: typedConfig.mlflowRunId || '', onChange: (e) => handleChange('mlflowRunId', e.target.value), placeholder: "e.g., abc123" })] }), _jsxs("div", { className: "se-mb-6", children: [_jsx("div", { className: "se-text-xs se-font-semibold se-text-slate-grey-8 se-uppercase se-tracking-wide se-mb-3", children: "Chat Settings" }), _jsx(EditorTextarea, { label: "Greeting Message", value: typedConfig.greeting || '', onChange: (e) => handleChange('greeting', e.target.value), placeholder: "Hi! How can I help?" }), _jsx(EditorInput, { label: "Max History (messages sent to backend)", type: "number", value: typedConfig.maxHistory || 20, onChange: (e) => handleChange('maxHistory', parseInt(e.target.value, 10)), min: 1, max: 100 })] })] })] }));
27
27
  }
28
28
  /**
29
29
  * Editor panel configuration for the app registry.
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Adaptive Chatbot - Runtime Module (Lit)
3
+ *
4
+ * Runtime manifest for the AI chat assistant adaptive.
5
+ * Uses the Lit web component mountable instead of the React one.
6
+ * This is a widget-based adaptive with no action executors.
7
+ */
8
+ export declare const runtime: {
9
+ id: string;
10
+ version: string;
11
+ name: string;
12
+ description: string;
13
+ /** No action executors — chatbot uses existing action kinds via applyBatch */
14
+ executors: never[];
15
+ /** Widget definitions for the runtime's WidgetRegistry */
16
+ widgets: {
17
+ id: string;
18
+ component: {
19
+ mount(container: HTMLElement, mountConfig?: Record<string, unknown>): () => void;
20
+ };
21
+ metadata: {
22
+ name: string;
23
+ description: string;
24
+ icon: string;
25
+ };
26
+ }[];
27
+ };
28
+ export default runtime;
29
+ //# sourceMappingURL=runtime-lit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-lit.d.ts","sourceRoot":"","sources":["../src/runtime-lit.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,eAAO,MAAM,OAAO;;;;;IAMlB,8EAA8E;;IAG9E,0DAA0D;;;;;;;;;;;;CAY3D,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Adaptive Chatbot - Runtime Module (Lit)
3
+ *
4
+ * Runtime manifest for the AI chat assistant adaptive.
5
+ * Uses the Lit web component mountable instead of the React one.
6
+ * This is a widget-based adaptive with no action executors.
7
+ */
8
+ import { ChatAssistantLitMountable } from './ChatAssistantLit';
9
+ // ============================================================================
10
+ // App Runtime Manifest
11
+ // ============================================================================
12
+ export const runtime = {
13
+ id: 'adaptive-chatbot',
14
+ version: '1.0.0',
15
+ name: 'Chat Assistant',
16
+ description: 'AI chat assistant with action execution capabilities',
17
+ /** No action executors — chatbot uses existing action kinds via applyBatch */
18
+ executors: [],
19
+ /** Widget definitions for the runtime's WidgetRegistry */
20
+ widgets: [
21
+ {
22
+ id: 'adaptive-chatbot:assistant',
23
+ component: ChatAssistantLitMountable,
24
+ metadata: {
25
+ name: 'Chat Assistant',
26
+ description: 'AI-powered chat assistant that can execute DOM actions',
27
+ icon: '💬',
28
+ },
29
+ },
30
+ ],
31
+ };
32
+ export default runtime;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,eAAO,MAAM,OAAO;;;;;IAMlB,8EAA8E;;IAG9E,0DAA0D;;;;;;;;;;;;CAY3D,CAAC;AAEF,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,eAAO,MAAM,OAAO;;;;;IAMlB,8EAA8E;;IAG9E,0DAA0D;;;;;;;;;;;;CAqB3D,CAAC;AAEF,eAAe,OAAO,CAAC"}
package/dist/runtime.js CHANGED
@@ -5,6 +5,7 @@
5
5
  * This is a widget-based adaptive with no action executors.
6
6
  */
7
7
  import { ChatAssistantMountableWidget } from './ChatAssistant';
8
+ import { ChatAssistantLitMountable } from './ChatAssistantLit';
8
9
  // ============================================================================
9
10
  // App Runtime Manifest
10
11
  // ============================================================================
@@ -26,6 +27,15 @@ export const runtime = {
26
27
  icon: '💬',
27
28
  },
28
29
  },
30
+ {
31
+ id: 'adaptive-chatbot:assistant-lit',
32
+ component: ChatAssistantLitMountable,
33
+ metadata: {
34
+ name: 'Chat Assistant (Lit)',
35
+ description: 'Lit web component chat assistant — no React dependency',
36
+ icon: '💬',
37
+ },
38
+ },
29
39
  ],
30
40
  };
31
41
  export default runtime;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Tool Bridge — Dispatch
3
+ *
4
+ * executeTool: translates an AI tool call to an ActionStep and fires applyBatch().
5
+ * getContext: reads session state from the runtime (no page effect).
6
+ */
7
+ import type { ChatbotWidgetRuntime } from '../types';
8
+ export interface ToolCall {
9
+ name: string;
10
+ args: Record<string, unknown>;
11
+ }
12
+ export interface ContextResult {
13
+ page: string;
14
+ signals: ReturnType<ChatbotWidgetRuntime['getActiveSignals']>;
15
+ config: ReturnType<ChatbotWidgetRuntime['getContextConfig']>;
16
+ }
17
+ /**
18
+ * Execute a tool call. For action tools (show_overlay, scroll_to):
19
+ * expands args to ActionStep and calls applyBatch(). Throws for unknown tools.
20
+ */
21
+ export declare function executeTool(call: ToolCall, runtime: ChatbotWidgetRuntime): Promise<void>;
22
+ /**
23
+ * Read current session context. Never calls applyBatch.
24
+ */
25
+ export declare function getContext(runtime: ChatbotWidgetRuntime): ContextResult;
26
+ //# sourceMappingURL=bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/tools/bridge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAGrD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,UAAU,CAAC,oBAAoB,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAC9D,MAAM,EAAE,UAAU,CAAC,oBAAoB,CAAC,kBAAkB,CAAC,CAAC,CAAC;CAC9D;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9F;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CAMvE"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Tool Bridge — Dispatch
3
+ *
4
+ * executeTool: translates an AI tool call to an ActionStep and fires applyBatch().
5
+ * getContext: reads session state from the runtime (no page effect).
6
+ */
7
+ import { expand } from './expanders';
8
+ /**
9
+ * Execute a tool call. For action tools (show_overlay, scroll_to):
10
+ * expands args to ActionStep and calls applyBatch(). Throws for unknown tools.
11
+ */
12
+ export async function executeTool(call, runtime) {
13
+ const step = expand(call.name, call.args);
14
+ await runtime.actions.applyBatch([step]);
15
+ }
16
+ /**
17
+ * Read current session context. Never calls applyBatch.
18
+ */
19
+ export function getContext(runtime) {
20
+ return {
21
+ page: window.location.pathname,
22
+ signals: runtime.getActiveSignals(),
23
+ config: runtime.getContextConfig(),
24
+ };
25
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Tool Bridge — Expanders
3
+ *
4
+ * Translates simplified AI tool arguments into full ActionStep objects.
5
+ * The AI sees small, constrained arg schemas. Expanders fill in all
6
+ * schema defaults the AI doesn't need to reason about.
7
+ */
8
+ export interface ActionStep {
9
+ kind: string;
10
+ config: Record<string, unknown>;
11
+ }
12
+ /**
13
+ * Expand a tool call into a full ActionStep.
14
+ * Throws for unknown tool names — do not silently ignore.
15
+ */
16
+ export declare function expand(toolName: string, args: Record<string, unknown>): ActionStep;
17
+ //# sourceMappingURL=expanders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expanders.d.ts","sourceRoot":"","sources":["../../src/tools/expanders.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AA6BD;;;GAGG;AACH,wBAAgB,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAMlF"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Tool Bridge — Expanders
3
+ *
4
+ * Translates simplified AI tool arguments into full ActionStep objects.
5
+ * The AI sees small, constrained arg schemas. Expanders fill in all
6
+ * schema defaults the AI doesn't need to reason about.
7
+ */
8
+ const expanders = {
9
+ show_overlay: (args) => ({
10
+ kind: 'show_overlay',
11
+ config: {
12
+ headline: args['headline'],
13
+ body: args['body'],
14
+ cta_label: args['cta'] ?? null,
15
+ // Schema defaults — AI does not control these
16
+ position: 'center',
17
+ dismissible: true,
18
+ },
19
+ }),
20
+ scroll_to: (args) => ({
21
+ kind: 'scroll_to',
22
+ config: {
23
+ // Passed through as-is. The runtime SDK's scroll_to executor resolves
24
+ // the target string: first as a CSS selector / anchor ID, then by
25
+ // case-insensitive heading text match. The expander does no DOM lookup.
26
+ target: args['section'],
27
+ behavior: 'smooth',
28
+ },
29
+ }),
30
+ };
31
+ /**
32
+ * Expand a tool call into a full ActionStep.
33
+ * Throws for unknown tool names — do not silently ignore.
34
+ */
35
+ export function expand(toolName, args) {
36
+ const expander = expanders[toolName];
37
+ if (!expander) {
38
+ throw new Error(`Unknown tool: ${toolName}`);
39
+ }
40
+ return expander(args);
41
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Tool Bridge — public API
3
+ *
4
+ * Integration mode (client owns the chat shell):
5
+ * import { SyntroTools } from '@syntrologie/adapt-chatbot/tools'
6
+ * // Render <SyntroTools runtime={syntroRuntime} /> inside AssistantRuntimeProvider
7
+ *
8
+ * Supply mode: use <SyntroChatbot /> from '@syntrologie/adapt-chatbot' instead.
9
+ */
10
+ export type { ContextResult, ToolCall } from './bridge';
11
+ export { executeTool, getContext } from './bridge';
12
+ export type { ActionStep } from './expanders';
13
+ export { SyntroTools } from './registrations';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACnD,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Tool Bridge — public API
3
+ *
4
+ * Integration mode (client owns the chat shell):
5
+ * import { SyntroTools } from '@syntrologie/adapt-chatbot/tools'
6
+ * // Render <SyntroTools runtime={syntroRuntime} /> inside AssistantRuntimeProvider
7
+ *
8
+ * Supply mode: use <SyntroChatbot /> from '@syntrologie/adapt-chatbot' instead.
9
+ */
10
+ export { executeTool, getContext } from './bridge';
11
+ export { SyntroTools } from './registrations';
@@ -0,0 +1,7 @@
1
+ import type { ChatbotWidgetRuntime } from '../../types';
2
+ interface Props {
3
+ runtime: ChatbotWidgetRuntime;
4
+ }
5
+ export declare function GetContextTool({ runtime }: Props): null;
6
+ export {};
7
+ //# sourceMappingURL=GetContextTool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GetContextTool.d.ts","sourceRoot":"","sources":["../../../src/tools/registrations/GetContextTool.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGxD,UAAU,KAAK;IACb,OAAO,EAAE,oBAAoB,CAAC;CAC/B;AAED,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,QAUhD"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * GetContextTool — registers the get_context tool with assistant-ui.
3
+ *
4
+ * This is a silent tool: it has no render output. When the AI calls it,
5
+ * execute() reads session state and returns the context. No applyBatch call.
6
+ */
7
+ import { useAssistantTool } from '@assistant-ui/react';
8
+ import { getContext } from '../bridge';
9
+ export function GetContextTool({ runtime }) {
10
+ useAssistantTool({
11
+ toolName: 'get_context',
12
+ type: 'frontend',
13
+ description: "Get current context about the user: what page they're on and what behavioral signals have fired in this session.",
14
+ parameters: { type: 'object', properties: {}, required: [] },
15
+ execute: async () => getContext(runtime),
16
+ });
17
+ return null;
18
+ }
@@ -0,0 +1,7 @@
1
+ import type { ChatbotWidgetRuntime } from '../../types';
2
+ interface Props {
3
+ runtime: ChatbotWidgetRuntime;
4
+ }
5
+ export declare function ScrollToTool({ runtime }: Props): null;
6
+ export {};
7
+ //# sourceMappingURL=ScrollToTool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScrollToTool.d.ts","sourceRoot":"","sources":["../../../src/tools/registrations/ScrollToTool.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAOxD,UAAU,KAAK;IACb,OAAO,EAAE,oBAAoB,CAAC;CAC/B;AAED,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,QAuC9C"}
@@ -0,0 +1,38 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * ScrollToTool — registers the scroll_to tool with assistant-ui.
4
+ */
5
+ import { useAssistantTool } from '@assistant-ui/react';
6
+ import { executeTool } from '../bridge';
7
+ export function ScrollToTool({ runtime }) {
8
+ useAssistantTool({
9
+ toolName: 'scroll_to',
10
+ type: 'frontend',
11
+ description: "Scroll the page to a named section. Use the section's visible heading text or a known anchor ID.",
12
+ parameters: {
13
+ type: 'object',
14
+ properties: {
15
+ section: {
16
+ type: 'string',
17
+ description: "The section to scroll to. Use the section's visible heading text or a known anchor ID.",
18
+ },
19
+ },
20
+ required: ['section'],
21
+ },
22
+ execute: async (args) => {
23
+ await executeTool({ name: 'scroll_to', args }, runtime);
24
+ },
25
+ render: ({ args, status }) => {
26
+ if (status.type !== 'complete')
27
+ return null;
28
+ return (_jsxs("div", { style: {
29
+ padding: '8px 12px',
30
+ borderRadius: '6px',
31
+ background: 'rgba(99, 179, 237, 0.08)',
32
+ border: '1px solid rgba(99, 179, 237, 0.2)',
33
+ fontSize: '12px',
34
+ }, children: [_jsx("span", { style: { color: '#63b3ed', fontWeight: 600 }, children: "Scrolled to \u2014 " }), _jsx("span", { style: { color: '#90cdf4' }, children: args.section })] }));
35
+ },
36
+ });
37
+ return null;
38
+ }
@@ -0,0 +1,7 @@
1
+ import type { ChatbotWidgetRuntime } from '../../types';
2
+ interface Props {
3
+ runtime: ChatbotWidgetRuntime;
4
+ }
5
+ export declare function ShowOverlayTool({ runtime }: Props): null;
6
+ export {};
7
+ //# sourceMappingURL=ShowOverlayTool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ShowOverlayTool.d.ts","sourceRoot":"","sources":["../../../src/tools/registrations/ShowOverlayTool.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AASxD,UAAU,KAAK;IACb,OAAO,EAAE,oBAAoB,CAAC;CAC/B;AAED,wBAAgB,eAAe,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,QAwCjD"}
@@ -0,0 +1,47 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * ShowOverlayTool — registers the show_overlay tool with assistant-ui.
4
+ *
5
+ * execute() fires immediately (type: 'frontend'), dispatching the overlay
6
+ * action via applyBatch(). The render prop shows a compact confirmation card
7
+ * inline in the chat thread after the tool completes.
8
+ *
9
+ * React 18+ strict mode double-fires useEffect in dev. applyBatch is
10
+ * idempotent for the same action within a session, so this is benign.
11
+ */
12
+ import { useAssistantTool } from '@assistant-ui/react';
13
+ import { executeTool } from '../bridge';
14
+ export function ShowOverlayTool({ runtime }) {
15
+ useAssistantTool({
16
+ toolName: 'show_overlay',
17
+ type: 'frontend',
18
+ description: 'Show a modal overlay on the page with a headline, body message, and optional call-to-action button.',
19
+ parameters: {
20
+ type: 'object',
21
+ properties: {
22
+ headline: { type: 'string', description: 'Short headline for the overlay.' },
23
+ body: { type: 'string', description: 'Main message body.' },
24
+ cta: {
25
+ type: 'string',
26
+ description: 'Button label. Omit if no action needed.',
27
+ },
28
+ },
29
+ required: ['headline', 'body'],
30
+ },
31
+ execute: async (args) => {
32
+ await executeTool({ name: 'show_overlay', args }, runtime);
33
+ },
34
+ render: ({ args, status }) => {
35
+ if (status.type !== 'complete')
36
+ return null;
37
+ return (_jsxs("div", { style: {
38
+ padding: '8px 12px',
39
+ borderRadius: '6px',
40
+ background: 'rgba(104, 211, 145, 0.08)',
41
+ border: '1px solid rgba(104, 211, 145, 0.2)',
42
+ fontSize: '12px',
43
+ }, children: [_jsx("span", { style: { color: '#68d391', fontWeight: 600 }, children: "Overlay shown \u2014 " }), _jsx("span", { style: { color: '#9ae6b4' }, children: args.headline })] }));
44
+ },
45
+ });
46
+ return null;
47
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * SyntroTools — renders all tool registration components.
3
+ *
4
+ * Render this inside an AssistantRuntimeProvider. Each child registers
5
+ * one tool with assistant-ui via useAssistantTool.
6
+ *
7
+ * Integration mode:
8
+ * <AssistantRuntimeProvider runtime={myRuntime}>
9
+ * <SyntroTools runtime={syntroRuntime} />
10
+ * <Thread />
11
+ * </AssistantRuntimeProvider>
12
+ */
13
+ import type { ChatbotWidgetRuntime } from '../../types';
14
+ interface Props {
15
+ runtime: ChatbotWidgetRuntime;
16
+ }
17
+ export declare function SyntroTools({ runtime }: Props): import("react/jsx-runtime").JSX.Element;
18
+ export {};
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/registrations/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAKxD,UAAU,KAAK;IACb,OAAO,EAAE,oBAAoB,CAAC;CAC/B;AAED,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,2CAQ7C"}
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { GetContextTool } from './GetContextTool';
3
+ import { ScrollToTool } from './ScrollToTool';
4
+ import { ShowOverlayTool } from './ShowOverlayTool';
5
+ export function SyntroTools({ runtime }) {
6
+ return (_jsxs(_Fragment, { children: [_jsx(GetContextTool, { runtime: runtime }), _jsx(ShowOverlayTool, { runtime: runtime }), _jsx(ScrollToTool, { runtime: runtime })] }));
7
+ }
package/dist/types.d.ts CHANGED
@@ -57,6 +57,15 @@ export interface ChatbotWidgetRuntime {
57
57
  events: {
58
58
  publish: (name: string, props?: Record<string, unknown>) => void;
59
59
  };
60
+ getActiveSignals: () => ActiveSignal[];
61
+ getContextConfig: () => ContextConfig;
60
62
  }
63
+ /** A behavioral signal that has fired in the current browser session */
64
+ export interface ActiveSignal {
65
+ name: string;
66
+ firedAt: number;
67
+ }
68
+ /** Workspace-configured key/value pairs injected into get_context responses */
69
+ export type ContextConfig = Record<string, unknown>;
61
70
  export type { EditorPanelProps } from '@syntrologie/sdk-contracts';
62
71
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,CAAC;AAE/C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAMD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAMD,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAMD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,SAAS,EAAE,MAAM,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAClD,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE;QACN,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;KAClE,CAAC;CACH;AAMD,YAAY,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,CAAC;AAE/C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAMD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAMD,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAMD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,SAAS,EAAE,MAAM,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAClD,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE;QACN,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;KAClE,CAAC;IAEF,gBAAgB,EAAE,MAAM,YAAY,EAAE,CAAC;IACvC,gBAAgB,EAAE,MAAM,aAAa,CAAC;CACvC;AAMD,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,+EAA+E;AAC/E,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAMpD,YAAY,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syntrologie/adapt-chatbot",
3
- "version": "2.8.0-canary.9",
3
+ "version": "2.8.0-canary.91",
4
4
  "description": "Adaptive Chatbot - AI chat assistant widget with action execution",
5
5
  "license": "Proprietary",
6
6
  "private": false,
@@ -15,10 +15,22 @@
15
15
  },
16
16
  "type": "module",
17
17
  "exports": {
18
+ ".": {
19
+ "types": "./dist/SyntroChatbot.d.ts",
20
+ "import": "./dist/SyntroChatbot.js"
21
+ },
22
+ "./tools": {
23
+ "types": "./dist/tools/index.d.ts",
24
+ "import": "./dist/tools/index.js"
25
+ },
18
26
  "./runtime": {
19
27
  "types": "./dist/runtime.d.ts",
20
28
  "import": "./dist/runtime.js"
21
29
  },
30
+ "./runtime-lit": {
31
+ "types": "./src/runtime-lit.ts",
32
+ "import": "./src/runtime-lit.ts"
33
+ },
22
34
  "./schema": {
23
35
  "types": "./dist/schema.d.ts",
24
36
  "import": "./dist/schema.js"
@@ -44,6 +56,8 @@
44
56
  "test:watch": "vitest"
45
57
  },
46
58
  "dependencies": {
59
+ "@assistant-ui/react": "0.12.22",
60
+ "@assistant-ui/react-ai-sdk": "1.3.17",
47
61
  "@syntrologie/shared-editor-ui": "*",
48
62
  "@syntro/design-system": "*"
49
63
  },
@@ -53,16 +67,20 @@
53
67
  "zod": "^3.0.0"
54
68
  },
55
69
  "devDependencies": {
56
- "@syntro/design-system": "^1.0.0",
70
+ "@assistant-ui/react": "0.12.22",
71
+ "@open-wc/testing": "4.0.0",
72
+ "@open-wc/testing-helpers": "3.0.1",
73
+ "@syntro/design-system": "1.0.0",
57
74
  "@syntrologie/shared-editor-ui": "*",
58
- "@testing-library/react": "^16.3.2",
59
- "@types/react": "^19.2.0",
60
- "@types/react-dom": "^19.2.0",
61
- "jsdom": "^26.1.0",
62
- "react": "^19.2.0",
63
- "react-dom": "^19.2.0",
64
- "typescript": "^5.9.3",
65
- "vitest": "^4.0.18",
66
- "zod": "^3.25.76"
75
+ "@testing-library/react": "16.3.2",
76
+ "@types/react": "19.2.14",
77
+ "@types/react-dom": "19.2.3",
78
+ "jsdom": "26.1.0",
79
+ "lit": "3.3.2",
80
+ "react": "19.2.1",
81
+ "react-dom": "19.2.1",
82
+ "typescript": "5.9.3",
83
+ "vitest": "4.0.18",
84
+ "zod": "3.25.76"
67
85
  }
68
86
  }