@tylertech/forge-ai 0.10.1 → 0.11.1

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.
@@ -0,0 +1,92 @@
1
+ import { nothing, LitElement, PropertyValues, TemplateResult } from 'lit';
2
+ import { Ref } from 'lit/directives/ref.js';
3
+ import { AgentInfo } from '../ai-agent-info';
4
+ import { ForgeAiChatHeaderAgentChangeEventData } from '../ai-chat-header';
5
+ import { AiMessageThreadComponent, ForgeAiMessageThreadThumbsEventData } from '../ai-message-thread';
6
+ import { ForgeAiAttachmentRemoveEventData } from '../ai-attachment';
7
+ import { ForgeAiFilePickerChangeEventData, ForgeAiFilePickerErrorEventData } from '../ai-file-picker';
8
+ import { AiPromptComponent, ForgeAiPromptCommandEventData, ForgeAiPromptSendEventData } from '../ai-prompt';
9
+ import { ForgeAiSuggestionsEventData, Suggestion } from '../ai-suggestions';
10
+ import { ForgeAiVoiceInputResultEvent } from '../ai-voice-input';
11
+ import { AgentAdapter } from './agent-adapter.js';
12
+ import { ChatbotCoreController } from '../core/chatbot-core-controller.js';
13
+ import { Agent, ChatMessage, HeadingLevel, MessageItem, SlashCommand, ThreadState, ToolCall, ToolDefinition } from './types.js';
14
+ export type FeatureToggle = 'on' | 'off';
15
+ export declare abstract class AiChatbotBase extends LitElement {
16
+ protected abstract _messageThreadRef: Ref<AiMessageThreadComponent>;
17
+ protected abstract _promptRef: Ref<AiPromptComponent>;
18
+ adapter?: AgentAdapter;
19
+ fileUpload: FeatureToggle;
20
+ voiceInput: FeatureToggle;
21
+ placeholder: string;
22
+ suggestions?: Suggestion[];
23
+ enableReactions: boolean;
24
+ titleText: string;
25
+ headingLevel: HeadingLevel;
26
+ debugMode: boolean;
27
+ disclaimerText: string | null | undefined;
28
+ debugCommand: FeatureToggle;
29
+ agentInfo?: AgentInfo;
30
+ agents: Agent[];
31
+ selectedAgentId?: string;
32
+ protected _coreController: ChatbotCoreController;
33
+ protected get _isStreaming(): boolean;
34
+ protected get _isUploading(): boolean;
35
+ protected get _tools(): Map<string, ToolDefinition>;
36
+ protected get _messageItems(): MessageItem[];
37
+ protected get _hasMessages(): boolean;
38
+ connectedCallback(): void;
39
+ willUpdate(changedProperties: PropertyValues<this>): void;
40
+ protected _onConnected(): void;
41
+ protected get _slashCommands(): SlashCommand[];
42
+ protected _handleSlashCommand(evt: CustomEvent<ForgeAiPromptCommandEventData>): void;
43
+ protected _handleInfo(): void;
44
+ protected _handleAgentChange(event: CustomEvent<ForgeAiChatHeaderAgentChangeEventData>): void;
45
+ protected _handleDebugToggle(): void;
46
+ protected _handleAttachmentRemove(evt: CustomEvent<ForgeAiAttachmentRemoveEventData>): void;
47
+ protected get _sessionFilesTemplate(): TemplateResult | typeof nothing;
48
+ protected _handleSend(evt: CustomEvent<ForgeAiPromptSendEventData>): Promise<void>;
49
+ protected _handleStop(): void;
50
+ protected _handleCancel(): void;
51
+ protected _handleCopy(evt: CustomEvent<{
52
+ messageId: string;
53
+ }>): Promise<void>;
54
+ protected _handleUserCopy(evt: CustomEvent<{
55
+ messageId: string;
56
+ }>): Promise<void>;
57
+ protected _handleUserResend(evt: CustomEvent<{
58
+ messageId: string;
59
+ }>): void;
60
+ protected _handleUserEdit(evt: CustomEvent<{
61
+ messageId: string;
62
+ content: string;
63
+ }>): void;
64
+ protected _handleResend(evt: CustomEvent<{
65
+ messageId: string;
66
+ }>): void;
67
+ protected _handleFeedback(evt: CustomEvent<ForgeAiMessageThreadThumbsEventData>, type: 'positive' | 'negative'): void;
68
+ protected _handleThumbsUp(evt: CustomEvent<ForgeAiMessageThreadThumbsEventData>): void;
69
+ protected _handleThumbsDown(evt: CustomEvent<ForgeAiMessageThreadThumbsEventData>): void;
70
+ protected _handleFileSelect(evt: CustomEvent<ForgeAiFilePickerChangeEventData>): void;
71
+ protected _handleFileError(evt: CustomEvent<ForgeAiFilePickerErrorEventData>): void;
72
+ protected _handleSuggestionSelect(evt: CustomEvent<ForgeAiSuggestionsEventData>): Promise<void>;
73
+ protected _handleVoiceInputResult(evt: CustomEvent<ForgeAiVoiceInputResultEvent>): void;
74
+ clearMessages(): boolean;
75
+ getMessages(): ChatMessage[];
76
+ setMessages(messages: ChatMessage[]): void;
77
+ sendMessage(content: string, files?: File[]): Promise<void>;
78
+ abort(): void;
79
+ scrollToBottom({ behavior }?: {
80
+ behavior?: ScrollBehavior;
81
+ }): Promise<void>;
82
+ getThreadState(): ThreadState;
83
+ getSelectedAgent(): Agent | undefined;
84
+ setThreadState(threadState: ThreadState): Promise<void>;
85
+ protected _dispatchHostEvent(config: {
86
+ type: string;
87
+ detail?: unknown;
88
+ cancelable?: boolean;
89
+ }): CustomEvent;
90
+ protected _formatToolCallForExport(toolCall: ToolCall): string;
91
+ protected _handleExport(): void;
92
+ }
@@ -0,0 +1,467 @@
1
+ import { LitElement, nothing, html } from "lit";
2
+ import { property } from "lit/decorators.js";
3
+ import { ChatbotCoreController } from "../core/chatbot-core-controller.mjs";
4
+ import { generateId, downloadFile } from "./utils.mjs";
5
+ var __defProp = Object.defineProperty;
6
+ var __decorateClass = (decorators, target, key, kind) => {
7
+ var result = void 0;
8
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
9
+ if (decorator = decorators[i])
10
+ result = decorator(target, key, result) || result;
11
+ if (result) __defProp(target, key, result);
12
+ return result;
13
+ };
14
+ class AiChatbotBase extends LitElement {
15
+ constructor() {
16
+ super(...arguments);
17
+ this.fileUpload = "off";
18
+ this.voiceInput = "on";
19
+ this.placeholder = "Ask a question...";
20
+ this.enableReactions = false;
21
+ this.titleText = "AI Assistant";
22
+ this.headingLevel = 2;
23
+ this.debugMode = false;
24
+ this.disclaimerText = "AI can make mistakes. Always verify responses.";
25
+ this.debugCommand = "on";
26
+ this.agents = [];
27
+ }
28
+ get _isStreaming() {
29
+ return this._coreController?.isStreaming ?? false;
30
+ }
31
+ get _isUploading() {
32
+ return this._coreController?.isUploading ?? false;
33
+ }
34
+ get _tools() {
35
+ return this._coreController?.tools ?? /* @__PURE__ */ new Map();
36
+ }
37
+ get _messageItems() {
38
+ return this._coreController?.messageItems ?? [];
39
+ }
40
+ get _hasMessages() {
41
+ return this._coreController?.hasMessages ?? false;
42
+ }
43
+ connectedCallback() {
44
+ super.connectedCallback();
45
+ this._coreController = new ChatbotCoreController(this, {
46
+ callbacks: {
47
+ onRequestUpdate: () => this.requestUpdate(),
48
+ onScrollToBottom: () => this.scrollToBottom(),
49
+ onDispatchEvent: (type, detail, cancelable) => this._dispatchHostEvent({ type, detail, cancelable })
50
+ }
51
+ });
52
+ if (this.adapter) {
53
+ this._coreController.adapter = this.adapter;
54
+ }
55
+ this._onConnected();
56
+ }
57
+ willUpdate(changedProperties) {
58
+ if (changedProperties.has("adapter") && this._coreController) {
59
+ this._coreController.adapter = this.adapter;
60
+ }
61
+ }
62
+ _onConnected() {
63
+ }
64
+ get _slashCommands() {
65
+ const commands = [];
66
+ if (this._hasMessages) {
67
+ commands.push({ id: "clear", name: "Clear", group: "Conversation" });
68
+ commands.push({ id: "export", name: "Export", group: "Conversation" });
69
+ }
70
+ commands.push({ id: "info", name: "Info", group: "Help" });
71
+ if (this.debugCommand === "on") {
72
+ commands.push({
73
+ id: "debug",
74
+ name: `${this.debugMode ? "Disable debug mode" : "Enable debug mode"}`,
75
+ group: "Help"
76
+ });
77
+ }
78
+ return commands;
79
+ }
80
+ _handleSlashCommand(evt) {
81
+ const commandId = evt.detail.commandId;
82
+ switch (commandId) {
83
+ case "clear":
84
+ this.clearMessages();
85
+ break;
86
+ case "export":
87
+ this._handleExport();
88
+ break;
89
+ case "info":
90
+ this._handleInfo();
91
+ break;
92
+ case "debug":
93
+ this._handleDebugToggle();
94
+ break;
95
+ }
96
+ }
97
+ _handleInfo() {
98
+ this._dispatchHostEvent({ type: "forge-ai-chatbot-info" });
99
+ }
100
+ _handleAgentChange(event) {
101
+ const { agent, previousAgentId } = event.detail;
102
+ const changeEvt = this._dispatchHostEvent({
103
+ type: "forge-ai-chatbot-agent-change",
104
+ detail: { agent, previousAgentId }
105
+ });
106
+ if (!changeEvt.defaultPrevented) {
107
+ this.selectedAgentId = agent?.id;
108
+ const adapter = this._coreController.adapter;
109
+ if (adapter) {
110
+ adapter.threadId = generateId();
111
+ }
112
+ if (this._hasMessages) {
113
+ const agentName = agent?.name ?? this.titleText;
114
+ const systemMessage = {
115
+ id: generateId(),
116
+ role: "system",
117
+ content: `Switched to ${agentName}`,
118
+ timestamp: Date.now(),
119
+ status: "complete",
120
+ clientOnly: true
121
+ };
122
+ this._coreController.addMessage(systemMessage);
123
+ }
124
+ }
125
+ }
126
+ _handleDebugToggle() {
127
+ this.debugMode = !this.debugMode;
128
+ }
129
+ _handleAttachmentRemove(evt) {
130
+ const { filename } = evt.detail;
131
+ const pendingAttachment = this._coreController.pendingAttachments.find((a) => a.filename === filename);
132
+ if (pendingAttachment) {
133
+ this._coreController.abortFileUpload(pendingAttachment.id);
134
+ return;
135
+ }
136
+ const completedAttachment = this._coreController.completedAttachments.find((a) => a.filename === filename);
137
+ if (completedAttachment) {
138
+ this._coreController.removeCompletedAttachment(completedAttachment.id);
139
+ }
140
+ }
141
+ get _sessionFilesTemplate() {
142
+ const completed = this._coreController?.completedAttachments ?? [];
143
+ const uploading = this._coreController?.pendingAttachments ?? [];
144
+ const allFiles = [...uploading, ...completed];
145
+ if (allFiles.length === 0) {
146
+ return nothing;
147
+ }
148
+ return html`
149
+ <div class="session-files-header">Session Files (${allFiles.length})</div>
150
+ <div class="session-files-list">
151
+ ${allFiles.map(
152
+ (attachment) => html`
153
+ <forge-ai-attachment
154
+ .filename=${attachment.filename}
155
+ .size=${attachment.size}
156
+ ?uploading=${attachment.uploading ?? false}
157
+ removable
158
+ @forge-ai-attachment-remove=${this._handleAttachmentRemove}>
159
+ </forge-ai-attachment>
160
+ `
161
+ )}
162
+ </div>
163
+ `;
164
+ }
165
+ async _handleSend(evt) {
166
+ const pendingAttachments = [...this._coreController.pendingAttachments];
167
+ await this._coreController.sendMessage({
168
+ content: evt.detail.value,
169
+ timestamp: evt.detail.date.getTime(),
170
+ attachments: pendingAttachments
171
+ });
172
+ }
173
+ _handleStop() {
174
+ this._coreController.abort();
175
+ }
176
+ _handleCancel() {
177
+ this._handleStop();
178
+ }
179
+ async _handleCopy(evt) {
180
+ const responseId = evt.detail.messageId;
181
+ const responseItem = this._messageItems.find((item) => item.type === "assistant" && item.data.id === responseId);
182
+ if (!responseItem || responseItem.type !== "assistant") {
183
+ return;
184
+ }
185
+ const textContent = responseItem.data.children.filter(
186
+ (c) => c.type === "text"
187
+ ).map((c) => c.content).join("\n\n");
188
+ try {
189
+ await navigator.clipboard.writeText(textContent);
190
+ } catch {
191
+ }
192
+ }
193
+ async _handleUserCopy(evt) {
194
+ const messageId = evt.detail.messageId;
195
+ const message = this._coreController.getMessage(messageId);
196
+ if (!message || message.role !== "user") {
197
+ return;
198
+ }
199
+ try {
200
+ await navigator.clipboard.writeText(message.content);
201
+ } catch {
202
+ }
203
+ }
204
+ _handleUserResend(evt) {
205
+ const adapter = this._coreController.adapter;
206
+ if (!adapter) {
207
+ return;
208
+ }
209
+ const messageId = evt.detail.messageId;
210
+ const messageIndex = this._messageItems.findIndex((item) => item.type === "message" && item.data.id === messageId);
211
+ if (messageIndex === -1) {
212
+ return;
213
+ }
214
+ const responseIndex = messageIndex + 1;
215
+ if (responseIndex < this._messageItems.length) {
216
+ this._coreController.removeMessageItemsFrom(responseIndex);
217
+ }
218
+ adapter.sendMessage(this.getMessages());
219
+ }
220
+ _handleUserEdit(evt) {
221
+ const adapter = this._coreController.adapter;
222
+ if (!adapter) {
223
+ return;
224
+ }
225
+ const { messageId, content } = evt.detail;
226
+ const messageIndex = this._messageItems.findIndex((item) => item.type === "message" && item.data.id === messageId);
227
+ if (messageIndex === -1) {
228
+ return;
229
+ }
230
+ this._coreController.updateMessageContent(messageId, content);
231
+ const responseIndex = messageIndex + 1;
232
+ if (responseIndex < this._messageItems.length) {
233
+ this._coreController.removeMessageItemsFrom(responseIndex);
234
+ }
235
+ adapter.sendMessage(this.getMessages());
236
+ }
237
+ _handleResend(evt) {
238
+ const adapter = this._coreController.adapter;
239
+ if (!adapter) {
240
+ return;
241
+ }
242
+ const responseId = evt.detail.messageId;
243
+ const responseIndex = this._messageItems.findIndex(
244
+ (item) => item.type === "assistant" && item.data.id === responseId
245
+ );
246
+ if (responseIndex === -1) {
247
+ return;
248
+ }
249
+ this._coreController.removeMessageItemsFrom(responseIndex);
250
+ adapter.sendMessage(this.getMessages());
251
+ }
252
+ _handleFeedback(evt, type) {
253
+ this._coreController.setResponseFeedback(evt.detail.messageId, {
254
+ type,
255
+ reason: evt.detail.feedback
256
+ });
257
+ this._dispatchHostEvent({
258
+ type: "forge-ai-chatbot-response-feedback",
259
+ detail: {
260
+ messageId: evt.detail.messageId,
261
+ type,
262
+ feedback: evt.detail.feedback
263
+ }
264
+ });
265
+ }
266
+ _handleThumbsUp(evt) {
267
+ this._handleFeedback(evt, "positive");
268
+ }
269
+ _handleThumbsDown(evt) {
270
+ this._handleFeedback(evt, "negative");
271
+ }
272
+ _handleFileSelect(evt) {
273
+ const { file, timestamp } = evt.detail;
274
+ const fileId = this._coreController.processFileUpload(file, timestamp);
275
+ const callbacks = this._coreController.createFileUploadCallbacks(fileId);
276
+ this._dispatchHostEvent({
277
+ type: "forge-ai-chatbot-file-select",
278
+ detail: {
279
+ fileId,
280
+ file,
281
+ filename: file.name,
282
+ size: file.size,
283
+ mimeType: file.type,
284
+ timestamp,
285
+ ...callbacks
286
+ }
287
+ });
288
+ }
289
+ _handleFileError(evt) {
290
+ const errorMessage = {
291
+ id: generateId(),
292
+ role: "assistant",
293
+ content: evt.detail.message,
294
+ timestamp: Date.now(),
295
+ status: "error"
296
+ };
297
+ this._coreController.addMessage(errorMessage);
298
+ }
299
+ async _handleSuggestionSelect(evt) {
300
+ this._promptRef.value?.addToHistory(evt.detail.text);
301
+ await this.sendMessage(evt.detail.text);
302
+ this._promptRef.value?.focus();
303
+ }
304
+ _handleVoiceInputResult(evt) {
305
+ const { transcript } = evt.detail;
306
+ if (transcript && this._promptRef.value) {
307
+ this._promptRef.value.value = transcript;
308
+ }
309
+ }
310
+ clearMessages() {
311
+ const event = this._dispatchHostEvent({ type: "forge-ai-chatbot-clear", cancelable: true });
312
+ if (event.defaultPrevented) {
313
+ return false;
314
+ }
315
+ this._coreController.clearMessages();
316
+ return true;
317
+ }
318
+ getMessages() {
319
+ return this._coreController.getMessages();
320
+ }
321
+ setMessages(messages) {
322
+ this._coreController.setMessages(messages);
323
+ }
324
+ async sendMessage(content, files) {
325
+ if (!this._coreController.adapter) {
326
+ console.warn("No adapter configured.");
327
+ return;
328
+ }
329
+ if (files) {
330
+ const timestamp = Date.now();
331
+ for (const file of files) {
332
+ const fileId = this._coreController.processFileUpload(file, timestamp);
333
+ const callbacks = this._coreController.createFileUploadCallbacks(fileId);
334
+ this._dispatchHostEvent({
335
+ type: "forge-ai-chatbot-file-select",
336
+ detail: {
337
+ fileId,
338
+ file,
339
+ filename: file.name,
340
+ size: file.size,
341
+ mimeType: file.type,
342
+ timestamp,
343
+ ...callbacks
344
+ }
345
+ });
346
+ }
347
+ }
348
+ await this._coreController.sendMessage({
349
+ content,
350
+ attachments: this._coreController.pendingAttachments
351
+ });
352
+ }
353
+ abort() {
354
+ this._handleStop();
355
+ }
356
+ async scrollToBottom({ behavior } = {}) {
357
+ await this._messageThreadRef.value?.updateComplete;
358
+ await new Promise(requestAnimationFrame);
359
+ this._messageThreadRef.value?.scrollToBottom({ behavior });
360
+ }
361
+ getThreadState() {
362
+ return {
363
+ threadId: this._coreController.adapter?.threadId,
364
+ messages: this.getMessages(),
365
+ timestamp: Date.now(),
366
+ selectedAgentId: this.selectedAgentId
367
+ };
368
+ }
369
+ getSelectedAgent() {
370
+ return this.agents.find((a) => a.id === this.selectedAgentId);
371
+ }
372
+ async setThreadState(threadState) {
373
+ this.setMessages(threadState.messages);
374
+ this.selectedAgentId = threadState.selectedAgentId;
375
+ if (threadState.threadId && this._coreController.adapter) {
376
+ this._coreController.adapter.threadId = threadState.threadId;
377
+ }
378
+ await this.updateComplete;
379
+ const userMessages = threadState.messages.filter((msg) => msg.role === "user").map((msg) => msg.content);
380
+ this._promptRef.value?.setHistory(userMessages);
381
+ this.scrollToBottom({ behavior: "instant" });
382
+ }
383
+ _dispatchHostEvent(config) {
384
+ const event = new CustomEvent(config.type, {
385
+ detail: config.detail,
386
+ bubbles: true,
387
+ composed: true,
388
+ cancelable: config.cancelable ?? false
389
+ });
390
+ this.dispatchEvent(event);
391
+ return event;
392
+ }
393
+ _formatToolCallForExport(toolCall) {
394
+ const lines = [` Tool: ${toolCall.name}`, ` Args: ${JSON.stringify(toolCall.args)}`];
395
+ if (toolCall.status === "error") {
396
+ const errorMsg = typeof toolCall.result === "object" && toolCall.result !== null && "error" in toolCall.result ? toolCall.result.error : "Unknown error";
397
+ lines.push(` Error: ${errorMsg}`);
398
+ } else if (toolCall.result !== void 0) {
399
+ lines.push(` Result: ${JSON.stringify(toolCall.result)}`);
400
+ }
401
+ return lines.join("\n");
402
+ }
403
+ _handleExport() {
404
+ const messages = this.getMessages();
405
+ if (messages.length === 0) {
406
+ return;
407
+ }
408
+ const chatText = messages.map((message) => {
409
+ const timestamp = new Date(message.timestamp).toLocaleString();
410
+ const role = message.role === "user" ? "You" : "Assistant";
411
+ let output = `[${timestamp}] ${role}:
412
+ ${message.content}
413
+ `;
414
+ if (message.toolCalls?.length) {
415
+ output += "\n" + message.toolCalls.map((tc) => this._formatToolCallForExport(tc)).join("\n\n") + "\n";
416
+ }
417
+ return output;
418
+ }).join("\n");
419
+ const filename = `chat-history-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace(/:/g, "-")}.txt`;
420
+ downloadFile(chatText, filename, "text/plain");
421
+ }
422
+ }
423
+ __decorateClass([
424
+ property({ attribute: false })
425
+ ], AiChatbotBase.prototype, "adapter");
426
+ __decorateClass([
427
+ property({ attribute: "file-upload" })
428
+ ], AiChatbotBase.prototype, "fileUpload");
429
+ __decorateClass([
430
+ property({ attribute: "voice-input" })
431
+ ], AiChatbotBase.prototype, "voiceInput");
432
+ __decorateClass([
433
+ property()
434
+ ], AiChatbotBase.prototype, "placeholder");
435
+ __decorateClass([
436
+ property({ attribute: false })
437
+ ], AiChatbotBase.prototype, "suggestions");
438
+ __decorateClass([
439
+ property({ type: Boolean, attribute: "enable-reactions" })
440
+ ], AiChatbotBase.prototype, "enableReactions");
441
+ __decorateClass([
442
+ property({ attribute: "title-text" })
443
+ ], AiChatbotBase.prototype, "titleText");
444
+ __decorateClass([
445
+ property({ attribute: "heading-level", type: Number })
446
+ ], AiChatbotBase.prototype, "headingLevel");
447
+ __decorateClass([
448
+ property({ type: Boolean, attribute: "debug-mode" })
449
+ ], AiChatbotBase.prototype, "debugMode");
450
+ __decorateClass([
451
+ property({ attribute: "disclaimer-text" })
452
+ ], AiChatbotBase.prototype, "disclaimerText");
453
+ __decorateClass([
454
+ property({ attribute: "debug-command" })
455
+ ], AiChatbotBase.prototype, "debugCommand");
456
+ __decorateClass([
457
+ property({ type: Object, attribute: false })
458
+ ], AiChatbotBase.prototype, "agentInfo");
459
+ __decorateClass([
460
+ property({ attribute: false })
461
+ ], AiChatbotBase.prototype, "agents");
462
+ __decorateClass([
463
+ property({ attribute: "selected-agent-id" })
464
+ ], AiChatbotBase.prototype, "selectedAgentId");
465
+ export {
466
+ AiChatbotBase
467
+ };
@@ -1,9 +1,8 @@
1
- import { LitElement, PropertyValues, TemplateResult } from 'lit';
2
- import { AgentInfo } from '../ai-agent-info';
3
- import { Suggestion } from '../ai-suggestions';
4
- import { ForgeAiVoiceInputResultEvent } from '../ai-voice-input';
5
- import { AgentAdapter } from './agent-adapter.js';
6
- import { Agent, ChatMessage, ForgeAiChatbotFileSelectEventData, HeadingLevel, ThreadState } from './types.js';
1
+ import { TemplateResult } from 'lit';
2
+ import { AiMessageThreadComponent } from '../ai-message-thread';
3
+ import { AiPromptComponent } from '../ai-prompt';
4
+ import { AiChatbotBase } from './ai-chatbot-base.js';
5
+ import { Agent, ChatMessage } from './types.js';
7
6
  declare global {
8
7
  interface HTMLElementTagNameMap {
9
8
  'forge-ai-chatbot': AiChatbotComponent;
@@ -20,7 +19,6 @@ declare global {
20
19
  'forge-ai-chatbot-clear': CustomEvent<void>;
21
20
  'forge-ai-chatbot-info': CustomEvent<void>;
22
21
  'forge-ai-chatbot-file-select': CustomEvent<ForgeAiChatbotFileSelectEventData>;
23
- 'forge-ai-voice-input-result': CustomEvent<ForgeAiVoiceInputResultEvent>;
24
22
  'forge-ai-chatbot-file-remove': CustomEvent<ForgeAiChatbotFileRemoveEventData>;
25
23
  'forge-ai-chatbot-response-feedback': CustomEvent<ForgeAiChatbotResponseFeedbackEventData>;
26
24
  'forge-ai-chatbot-agent-change': CustomEvent<ForgeAiChatbotAgentChangeEventData>;
@@ -38,6 +36,20 @@ export interface ForgeAiChatbotToolCallEventData {
38
36
  export interface ForgeAiChatbotErrorEventData {
39
37
  error: string;
40
38
  }
39
+ export interface ForgeAiChatbotFileSelectEventData {
40
+ fileId: string;
41
+ file: File;
42
+ filename: string;
43
+ size: number;
44
+ mimeType: string;
45
+ timestamp: number;
46
+ onProgress: (progress: number) => void;
47
+ onComplete: (result: {
48
+ url?: string;
49
+ error?: string;
50
+ }) => void;
51
+ onAbort: () => void;
52
+ }
41
53
  export interface ForgeAiChatbotFileRemoveEventData {
42
54
  fileId: string;
43
55
  }
@@ -51,19 +63,15 @@ export interface ForgeAiChatbotAgentChangeEventData {
51
63
  previousAgentId: string | undefined;
52
64
  }
53
65
  export declare const AiChatbotComponentTagName: keyof HTMLElementTagNameMap;
54
- /**
55
- * Type for feature toggle values
56
- */
57
- export type FeatureToggle = 'on' | 'off';
58
66
  /**
59
67
  * @tag forge-ai-chatbot
60
68
  *
61
- * @summary A complete, self-contained AI chatbot component that implements the AG-UI protocol using an adapter pattern.
69
+ * @summary A complete, self-contained AI chatbot component.
62
70
  *
63
71
  * @description
64
72
  * The AI Chatbot component provides a full-featured chat interface with support for streaming responses,
65
73
  * client-side tool execution, file attachments, markdown rendering, and programmatic control.
66
- * It uses an adapter pattern to abstract communication, allowing for AG-UI or custom protocol implementations.
74
+ * It uses an adapter pattern to abstract communication, allowing for any protocol implementation.
67
75
  *
68
76
  * @slot header - Slot for custom header content
69
77
  * @slot icon - Slot for custom header icon (default: forge-ai-icon)
@@ -89,74 +97,17 @@ export type FeatureToggle = 'on' | 'off';
89
97
  * @event {CustomEvent<void>} forge-ai-chatbot-info - Fired when header info option is selected
90
98
  * @event {CustomEvent<ForgeAiChatbotResponseFeedbackEventData>} forge-ai-chatbot-response-feedback - Fired when user provides feedback on a response (thumbs up/down)
91
99
  */
92
- export declare class AiChatbotComponent extends LitElement {
100
+ export declare class AiChatbotComponent extends AiChatbotBase {
93
101
  #private;
94
102
  static styles: import('lit').CSSResult;
95
- adapter?: AgentAdapter;
96
- fileUpload: FeatureToggle;
97
- voiceInput: FeatureToggle;
98
- debugCommand: FeatureToggle;
99
- placeholder: string;
100
- suggestions?: Suggestion[];
101
103
  showExpandButton: boolean;
102
104
  showMinimizeButton: boolean;
103
105
  expanded: boolean;
104
106
  minimizeIcon: 'default' | 'panel';
105
- enableReactions: boolean;
106
- agentInfo?: AgentInfo;
107
- titleText: string;
108
- headingLevel: HeadingLevel;
109
- debugMode: boolean;
110
- disclaimerText: string | null | undefined;
111
- agents: Agent[];
112
- selectedAgentId?: string;
113
- connectedCallback(): void;
114
- disconnectedCallback(): void;
115
- willUpdate(changedProperties: PropertyValues<this>): void;
116
- /**
117
- * Clears all messages from the chat history.
118
- */
119
- clearMessages(): void;
120
- /**
121
- * Gets the current message history.
122
- * @returns Array of chat messages
123
- */
124
- getMessages(): ChatMessage[];
125
- /**
126
- * Sets the message history. Useful for restoring conversation state.
127
- * @param messages - Array of chat messages to set
128
- */
129
- setMessages(messages: ChatMessage[]): void;
130
- /**
131
- * Gets the currently selected agent.
132
- * @returns The selected agent or undefined if none selected
133
- */
134
- getSelectedAgent(): Agent | undefined;
135
- /**
136
- * Programmatically sends a message as the user.
137
- * @param content - The message content to send
138
- * @param files - Optional file objects to attach
139
- */
107
+ protected _messageThreadRef: import('lit/directives/ref').Ref<AiMessageThreadComponent>;
108
+ protected _promptRef: import('lit/directives/ref').Ref<AiPromptComponent>;
109
+ protected _handleInfo(): void;
140
110
  sendMessage(content: string, files?: File[]): Promise<void>;
141
- /**
142
- * Aborts the current streaming response.
143
- */
144
- abort(): void;
145
- /**
146
- * Scrolls the chat interface to the bottom.
147
- */
148
- scrollToBottom({ behavior }?: {
149
- behavior?: ScrollBehavior;
150
- }): Promise<void>;
151
- /**
152
- * Gets the complete serializable thread state including threadId and messages.
153
- * @returns ThreadState object containing threadId, messages, and timestamp
154
- */
155
- getThreadState(): ThreadState;
156
- /**
157
- * Restores thread state from a serialized ThreadState object.
158
- * @param state - ThreadState object to restore
159
- */
160
- setThreadState(state: ThreadState): Promise<void>;
161
111
  render(): TemplateResult;
162
112
  }
113
+ export type { FeatureToggle } from './ai-chatbot-base.js';