@tylertech/forge-ai 0.13.0 → 0.13.2

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 (91) hide show
  1. package/custom-elements.json +5083 -3159
  2. package/dist/ai-agent-info/ai-agent-info.d.ts +1 -1
  3. package/dist/ai-agent-info/ai-agent-info.mjs +17 -62
  4. package/dist/ai-agent-info/ai-agent-info.scss.mjs +1 -1
  5. package/dist/ai-assistant-response/ai-assistant-response.scss.mjs +1 -1
  6. package/dist/ai-chat-header/ai-chat-header.d.ts +7 -0
  7. package/dist/ai-chat-header/ai-chat-header.mjs +52 -7
  8. package/dist/ai-chat-header/ai-chat-header.scss.mjs +1 -1
  9. package/dist/ai-chatbot/ai-chatbot-base.d.ts +37 -3
  10. package/dist/ai-chatbot/ai-chatbot-base.mjs +83 -24
  11. package/dist/ai-chatbot/ai-chatbot.d.ts +41 -1
  12. package/dist/ai-chatbot/ai-chatbot.mjs +242 -43
  13. package/dist/ai-chatbot/ai-chatbot.scss.mjs +1 -1
  14. package/dist/ai-chatbot/index.d.ts +1 -1
  15. package/dist/ai-chatbot/types.d.ts +39 -0
  16. package/dist/ai-chatbot/utils.d.ts +5 -0
  17. package/dist/ai-chatbot/utils.mjs +28 -0
  18. package/dist/ai-chatbot-launcher/ai-chatbot-launcher.d.ts +29 -2
  19. package/dist/ai-chatbot-launcher/ai-chatbot-launcher.mjs +156 -10
  20. package/dist/ai-chatbot-launcher/ai-chatbot-launcher.scss.mjs +1 -1
  21. package/dist/ai-confirmation-prompt/ai-confirmation-prompt.d.ts +6 -0
  22. package/dist/ai-confirmation-prompt/ai-confirmation-prompt.mjs +64 -19
  23. package/dist/ai-confirmation-prompt/ai-confirmation-prompt.scss.mjs +1 -1
  24. package/dist/ai-context-chip/ai-context-chip.d.ts +45 -0
  25. package/dist/ai-context-chip/ai-context-chip.mjs +169 -0
  26. package/dist/ai-context-chip/ai-context-chip.scss.mjs +4 -0
  27. package/dist/ai-context-chip/index.d.ts +2 -0
  28. package/dist/ai-context-chip/index.mjs +5 -0
  29. package/dist/ai-context-items/ai-context-items.d.ts +20 -0
  30. package/dist/ai-context-items/ai-context-items.mjs +78 -0
  31. package/dist/ai-context-items/ai-context-items.scss.mjs +4 -0
  32. package/dist/ai-context-items/index.d.ts +1 -0
  33. package/dist/ai-context-items/index.mjs +5 -0
  34. package/dist/ai-conversations-panel/ai-conversations-panel.d.ts +86 -0
  35. package/dist/ai-conversations-panel/ai-conversations-panel.mjs +558 -0
  36. package/dist/ai-conversations-panel/ai-conversations-panel.scss.mjs +4 -0
  37. package/dist/ai-conversations-panel/index.d.ts +2 -0
  38. package/dist/ai-conversations-panel/index.mjs +5 -0
  39. package/dist/ai-copy-button/ai-copy-button.d.ts +32 -0
  40. package/dist/ai-copy-button/ai-copy-button.mjs +116 -0
  41. package/dist/ai-copy-button/ai-copy-button.scss.mjs +4 -0
  42. package/dist/ai-copy-button/index.d.ts +1 -0
  43. package/dist/ai-copy-button/index.mjs +5 -0
  44. package/dist/ai-dialog/ai-dialog.scss.mjs +1 -1
  45. package/dist/ai-dropdown-menu/ai-dropdown-menu-item.scss.mjs +1 -1
  46. package/dist/ai-dropdown-menu/ai-dropdown-menu.d.ts +6 -1
  47. package/dist/ai-dropdown-menu/ai-dropdown-menu.mjs +20 -8
  48. package/dist/ai-dropdown-menu/ai-dropdown-menu.scss.mjs +1 -1
  49. package/dist/ai-edit-thread/ai-edit-thread.d.ts +34 -0
  50. package/dist/ai-edit-thread/ai-edit-thread.mjs +130 -0
  51. package/dist/ai-edit-thread/ai-edit-thread.scss.mjs +4 -0
  52. package/dist/ai-edit-thread/index.d.ts +1 -0
  53. package/dist/ai-edit-thread/index.mjs +5 -0
  54. package/dist/ai-message-thread/ai-message-thread.scss.mjs +1 -1
  55. package/dist/ai-modal/ai-modal.d.ts +11 -2
  56. package/dist/ai-modal/ai-modal.mjs +31 -6
  57. package/dist/ai-prompt/ai-prompt.d.ts +7 -1
  58. package/dist/ai-prompt/ai-prompt.mjs +29 -2
  59. package/dist/ai-sidebar/ai-sidebar.d.ts +11 -0
  60. package/dist/ai-sidebar/ai-sidebar.mjs +94 -4
  61. package/dist/ai-sidebar/ai-sidebar.scss.mjs +1 -1
  62. package/dist/ai-sidebar-chat/ai-sidebar-chat.d.ts +1 -0
  63. package/dist/ai-sidebar-chat/ai-sidebar-chat.mjs +5 -0
  64. package/dist/ai-spinner/ai-spinner.d.ts +1 -1
  65. package/dist/ai-spinner/ai-spinner.scss.mjs +1 -1
  66. package/dist/ai-thread-actions-menu/ai-thread-actions-menu.d.ts +44 -0
  67. package/dist/ai-thread-actions-menu/ai-thread-actions-menu.mjs +136 -0
  68. package/dist/ai-thread-actions-menu/ai-thread-actions-menu.scss.mjs +4 -0
  69. package/dist/ai-thread-actions-menu/index.d.ts +1 -0
  70. package/dist/ai-thread-actions-menu/index.mjs +5 -0
  71. package/dist/ai-threads/ai-threads.d.ts +45 -16
  72. package/dist/ai-threads/ai-threads.mjs +256 -98
  73. package/dist/ai-threads/ai-threads.scss.mjs +1 -1
  74. package/dist/ai-threads-search/ai-threads-search.d.ts +81 -0
  75. package/dist/ai-threads-search/ai-threads-search.mjs +414 -0
  76. package/dist/ai-threads-search/ai-threads-search.scss.mjs +4 -0
  77. package/dist/ai-threads-search/index.d.ts +1 -0
  78. package/dist/ai-threads-search/index.mjs +5 -0
  79. package/dist/core/index.d.ts +1 -0
  80. package/dist/core/index.mjs +3 -1
  81. package/dist/core/resize-controller.d.ts +25 -0
  82. package/dist/core/resize-controller.mjs +144 -0
  83. package/dist/index.d.ts +7 -0
  84. package/dist/index.mjs +21 -0
  85. package/dist/utils/delete-thread-controller.d.ts +14 -0
  86. package/dist/utils/delete-thread-controller.mjs +80 -0
  87. package/dist/utils/index.d.ts +3 -0
  88. package/dist/utils/index.mjs +8 -0
  89. package/dist/utils/infinite-scroll-controller.d.ts +33 -0
  90. package/dist/utils/infinite-scroll-controller.mjs +95 -0
  91. package/package.json +15 -14
@@ -1,11 +1,13 @@
1
- import { unsafeCSS, html, nothing } from "lit";
2
- import { property, customElement } from "lit/decorators.js";
1
+ import { unsafeCSS, html } from "lit";
2
+ import { property, state, customElement } from "lit/decorators.js";
3
3
  import { createRef, ref } from "lit/directives/ref.js";
4
4
  import { when } from "lit/directives/when.js";
5
5
  import { AiChatbotBase } from "./ai-chatbot-base.mjs";
6
6
  import "../ai-attachment/ai-attachment.mjs";
7
7
  import "../ai-chat-header/ai-chat-header.mjs";
8
8
  import "../ai-chat-interface/ai-chat-interface.mjs";
9
+ import "../ai-context-chip/ai-context-chip.mjs";
10
+ import "../ai-conversations-panel/ai-conversations-panel.mjs";
9
11
  import "../ai-file-picker/ai-file-picker.mjs";
10
12
  import "../ai-message-thread/ai-message-thread.mjs";
11
13
  import "../ai-prompt/ai-prompt.mjs";
@@ -30,7 +32,7 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot
30
32
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
31
33
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
32
34
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
33
- var _chatInterfaceRef, _headerRef, _AiChatbotComponent_instances, handleHeaderExpand_fn, handleHeaderMinimize_fn, handleHeaderClear_fn, handleHeaderInfo_fn, sessionFilesTemplate_get, promptSlot_get, messageThread_get, _defaultEmptyStateIcon;
35
+ var _chatInterfaceRef, _headerRef, _conversationsPanelRef, _conversationsDialogRef, _boundEscapeHandler, _AiChatbotComponent_instances, handleHeaderExpand_fn, handleHeaderMinimize_fn, handleHeaderClear_fn, handleHeaderInfo_fn, handleConversationsDialogClose_fn, handleEscapeKey_fn, handleBackdropClick_fn, handleConversationsToggle_fn, handleThreadSelect_fn, handleNewChat_fn, handlePanelClose_fn, _handleConversationSearch, _handleConversationLoadMore, _handleConversationRename, _handleConversationDelete, promptSlot_get, messageThread_get, _defaultEmptyStateIcon;
34
36
  const AiChatbotComponentTagName = "forge-ai-chatbot";
35
37
  let AiChatbotComponent = class extends AiChatbotBase {
36
38
  constructor() {
@@ -40,10 +42,65 @@ let AiChatbotComponent = class extends AiChatbotBase {
40
42
  this.showMinimizeButton = false;
41
43
  this.expanded = false;
42
44
  this.minimizeIcon = "default";
45
+ this.showConversationsButton = false;
46
+ this.recentThreads = [];
47
+ this.conversationsOpen = false;
48
+ this.showConversationRename = false;
49
+ this.showConversationDelete = false;
50
+ this._selectedThreadId = null;
43
51
  __privateAdd(this, _chatInterfaceRef, createRef());
44
52
  this._messageThreadRef = createRef();
45
53
  this._promptRef = createRef();
46
54
  __privateAdd(this, _headerRef, createRef());
55
+ __privateAdd(this, _conversationsPanelRef, createRef());
56
+ __privateAdd(this, _conversationsDialogRef, createRef());
57
+ __privateAdd(this, _boundEscapeHandler, __privateMethod(this, _AiChatbotComponent_instances, handleEscapeKey_fn).bind(this));
58
+ __privateAdd(this, _handleConversationSearch, (e) => {
59
+ const event = new CustomEvent("forge-ai-chatbot-conversation-search", {
60
+ detail: e.detail,
61
+ bubbles: true,
62
+ composed: true,
63
+ cancelable: true
64
+ });
65
+ if (!this.dispatchEvent(event)) {
66
+ e.preventDefault();
67
+ }
68
+ });
69
+ __privateAdd(this, _handleConversationLoadMore, (e) => {
70
+ const event = new CustomEvent(
71
+ "forge-ai-chatbot-conversation-load-more",
72
+ {
73
+ detail: e.detail,
74
+ bubbles: true,
75
+ composed: true
76
+ }
77
+ );
78
+ this.dispatchEvent(event);
79
+ });
80
+ __privateAdd(this, _handleConversationRename, (e) => {
81
+ const event = new CustomEvent("forge-ai-chatbot-conversation-rename", {
82
+ detail: e.detail,
83
+ bubbles: true,
84
+ composed: true,
85
+ cancelable: true
86
+ });
87
+ const dispatched = this.dispatchEvent(event);
88
+ if (!dispatched) {
89
+ e.preventDefault();
90
+ }
91
+ });
92
+ __privateAdd(this, _handleConversationDelete, (e) => {
93
+ const event = new CustomEvent("forge-ai-chatbot-conversation-delete", {
94
+ detail: e.detail,
95
+ bubbles: true,
96
+ composed: true,
97
+ cancelable: true
98
+ });
99
+ const dispatched = this.dispatchEvent(event);
100
+ if (!dispatched) {
101
+ e.preventDefault();
102
+ }
103
+ });
47
104
  __privateAdd(this, _defaultEmptyStateIcon, html`
48
105
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" class="empty-state-icon">
49
106
  <defs>
@@ -313,47 +370,127 @@ let AiChatbotComponent = class extends AiChatbotBase {
313
370
  focus() {
314
371
  this._promptRef.value?.focus();
315
372
  }
373
+ showConversations() {
374
+ const dialog = __privateGet(this, _conversationsDialogRef).value;
375
+ if (dialog && !dialog.open) {
376
+ dialog.show();
377
+ this.conversationsOpen = true;
378
+ window.addEventListener("keydown", __privateGet(this, _boundEscapeHandler), { capture: true });
379
+ this._dispatchHostEvent({ type: "forge-ai-chatbot-conversations-open" });
380
+ }
381
+ }
382
+ hideConversations() {
383
+ const dialog = __privateGet(this, _conversationsDialogRef).value;
384
+ if (dialog && dialog.open) {
385
+ window.removeEventListener("keydown", __privateGet(this, _boundEscapeHandler), { capture: true });
386
+ dialog.close();
387
+ setTimeout(() => {
388
+ __privateGet(this, _conversationsPanelRef).value?.resetToMainView();
389
+ }, 150);
390
+ }
391
+ }
392
+ /**
393
+ * Starts a new chat conversation by clearing messages and resetting conversation state.
394
+ *
395
+ * This method:
396
+ * - Clears all messages via the controller
397
+ * - Resets the selected thread ID
398
+ *
399
+ * Does not fire events - meant for programmatic use.
400
+ * For user-initiated actions, the event handler fires the event before calling this.
401
+ */
402
+ startNewChat() {
403
+ super.startNewChat();
404
+ this._selectedThreadId = null;
405
+ }
406
+ toggleConversations() {
407
+ if (this.conversationsOpen) {
408
+ this.hideConversations();
409
+ } else {
410
+ this.showConversations();
411
+ }
412
+ }
316
413
  render() {
317
414
  return html`
318
- <forge-ai-chat-interface
319
- ${ref(__privateGet(this, _chatInterfaceRef))}
320
- role="region"
321
- aria-label="AI chatbot"
322
- aria-live="polite"
323
- aria-busy=${this._isStreaming}>
324
- <forge-ai-chat-header
325
- ${ref(__privateGet(this, _headerRef))}
326
- slot="header"
327
- ?show-expand-button=${this.showExpandButton}
328
- ?show-minimize-button=${this.showMinimizeButton}
329
- ?expanded=${this.expanded}
330
- ?disable-agent-selector=${this._isStreaming}
331
- export-option=${this._hasMessages ? "enabled" : "off"}
332
- clear-option=${this._hasMessages ? "enabled" : "off"}
333
- .minimizeIcon=${this.minimizeIcon}
334
- .agentInfo=${this.agentInfo}
335
- .headingLevel=${this.headingLevel}
336
- .titleText=${this.titleText}
337
- .agents=${this.agents}
338
- .selectedAgentId=${this.selectedAgentId}
339
- @forge-ai-chat-header-expand=${__privateMethod(this, _AiChatbotComponent_instances, handleHeaderExpand_fn)}
340
- @forge-ai-chat-header-minimize=${__privateMethod(this, _AiChatbotComponent_instances, handleHeaderMinimize_fn)}
341
- @forge-ai-chat-header-clear=${__privateMethod(this, _AiChatbotComponent_instances, handleHeaderClear_fn)}
342
- @forge-ai-chat-header-export=${this._handleExport}
343
- @forge-ai-chat-header-info=${__privateMethod(this, _AiChatbotComponent_instances, handleHeaderInfo_fn)}
344
- @forge-ai-chat-header-agent-change=${this._handleAgentChange}>
345
- <slot name="icon" slot="icon">
346
- <forge-ai-icon></forge-ai-icon>
347
- </slot>
348
- </forge-ai-chat-header>
349
- ${__privateGet(this, _AiChatbotComponent_instances, sessionFilesTemplate_get)} ${__privateGet(this, _AiChatbotComponent_instances, messageThread_get)} ${__privateGet(this, _AiChatbotComponent_instances, promptSlot_get)}
350
- ${when(this.disclaimerText, () => html`<div class="disclaimer" slot="disclaimer">${this.disclaimerText}</div>`)}
351
- </forge-ai-chat-interface>
415
+ <div class="chatbot-container">
416
+ <forge-ai-chat-interface
417
+ ${ref(__privateGet(this, _chatInterfaceRef))}
418
+ role="region"
419
+ aria-label="AI chatbot"
420
+ aria-live="polite"
421
+ aria-busy=${this._isStreaming}>
422
+ <forge-ai-chat-header
423
+ ${ref(__privateGet(this, _headerRef))}
424
+ slot="header"
425
+ ?show-expand-button=${this.showExpandButton}
426
+ ?show-minimize-button=${this.showMinimizeButton}
427
+ ?show-conversations-button=${this.showConversationsButton}
428
+ ?expanded=${this.expanded}
429
+ ?disable-agent-selector=${this._isStreaming}
430
+ export-option=${this._hasMessages ? "enabled" : "off"}
431
+ clear-option=${this._hasMessages ? "enabled" : "off"}
432
+ .minimizeIcon=${this.minimizeIcon}
433
+ .agentInfo=${this.agentInfo}
434
+ .headingLevel=${this.headingLevel}
435
+ .titleText=${this.titleText}
436
+ .agents=${this.agents}
437
+ .selectedAgentId=${this.selectedAgentId}
438
+ @forge-ai-chat-header-expand=${__privateMethod(this, _AiChatbotComponent_instances, handleHeaderExpand_fn)}
439
+ @forge-ai-chat-header-minimize=${__privateMethod(this, _AiChatbotComponent_instances, handleHeaderMinimize_fn)}
440
+ @forge-ai-chat-header-clear=${__privateMethod(this, _AiChatbotComponent_instances, handleHeaderClear_fn)}
441
+ @forge-ai-chat-header-export=${this._handleExport}
442
+ @forge-ai-chat-header-info=${__privateMethod(this, _AiChatbotComponent_instances, handleHeaderInfo_fn)}
443
+ @forge-ai-chat-header-agent-change=${this._handleAgentChange}
444
+ @forge-ai-chat-header-conversations-toggle=${__privateMethod(this, _AiChatbotComponent_instances, handleConversationsToggle_fn)}>
445
+ <slot name="icon" slot="icon">
446
+ <forge-ai-icon></forge-ai-icon>
447
+ </slot>
448
+ <slot name="header-actions" slot="header-actions"></slot>
449
+ </forge-ai-chat-header>
450
+ ${__privateGet(this, _AiChatbotComponent_instances, messageThread_get)} ${__privateGet(this, _AiChatbotComponent_instances, promptSlot_get)}
451
+ ${when(
452
+ this.disclaimerText,
453
+ () => html`<div class="disclaimer" slot="disclaimer">${this.disclaimerText}</div>`
454
+ )}
455
+ </forge-ai-chat-interface>
456
+ ${when(
457
+ this.showConversationsButton,
458
+ () => html`
459
+ ${when(
460
+ this.conversationsOpen,
461
+ () => html` <div class="conversations-backdrop" @click=${__privateMethod(this, _AiChatbotComponent_instances, handleBackdropClick_fn)}></div> `
462
+ )}
463
+ <dialog
464
+ ${ref(__privateGet(this, _conversationsDialogRef))}
465
+ class="conversations-dialog forge-dialog forge-dialog--modal forge-dialog--left-sheet"
466
+ @close=${__privateMethod(this, _AiChatbotComponent_instances, handleConversationsDialogClose_fn)}>
467
+ <forge-ai-conversations-panel
468
+ ${ref(__privateGet(this, _conversationsPanelRef))}
469
+ .recentThreads=${this.recentThreads}
470
+ .selectedThreadId=${this._selectedThreadId}
471
+ ?show-back-button=${true}
472
+ ?show-conversation-rename=${this.showConversationRename}
473
+ ?show-conversation-delete=${this.showConversationDelete}
474
+ @forge-ai-conversations-panel-select=${__privateMethod(this, _AiChatbotComponent_instances, handleThreadSelect_fn)}
475
+ @forge-ai-conversations-panel-new-chat=${__privateMethod(this, _AiChatbotComponent_instances, handleNewChat_fn)}
476
+ @forge-ai-conversations-panel-close=${__privateMethod(this, _AiChatbotComponent_instances, handlePanelClose_fn)}
477
+ @forge-ai-conversations-panel-search=${__privateGet(this, _handleConversationSearch)}
478
+ @forge-ai-conversations-panel-load-more=${__privateGet(this, _handleConversationLoadMore)}
479
+ @forge-ai-conversations-panel-rename=${__privateGet(this, _handleConversationRename)}
480
+ @forge-ai-conversations-panel-delete=${__privateGet(this, _handleConversationDelete)}>
481
+ </forge-ai-conversations-panel>
482
+ </dialog>
483
+ `
484
+ )}
485
+ </div>
352
486
  `;
353
487
  }
354
488
  };
355
489
  _chatInterfaceRef = /* @__PURE__ */ new WeakMap();
356
490
  _headerRef = /* @__PURE__ */ new WeakMap();
491
+ _conversationsPanelRef = /* @__PURE__ */ new WeakMap();
492
+ _conversationsDialogRef = /* @__PURE__ */ new WeakMap();
493
+ _boundEscapeHandler = /* @__PURE__ */ new WeakMap();
357
494
  _AiChatbotComponent_instances = /* @__PURE__ */ new WeakSet();
358
495
  handleHeaderExpand_fn = function() {
359
496
  this._dispatchHostEvent({ type: "forge-ai-chatbot-expand" });
@@ -367,13 +504,55 @@ handleHeaderClear_fn = function() {
367
504
  handleHeaderInfo_fn = function() {
368
505
  this._handleInfo();
369
506
  };
370
- sessionFilesTemplate_get = function() {
371
- const content = this._sessionFilesTemplate;
372
- if (content === nothing) {
373
- return nothing;
507
+ handleConversationsDialogClose_fn = function() {
508
+ window.removeEventListener("keydown", __privateGet(this, _boundEscapeHandler), { capture: true });
509
+ this.conversationsOpen = false;
510
+ this._dispatchHostEvent({ type: "forge-ai-chatbot-conversations-close" });
511
+ };
512
+ handleEscapeKey_fn = function(event) {
513
+ if (event.key === "Escape" && this.conversationsOpen) {
514
+ const path = event.composedPath();
515
+ const hasEscapeHandler = path.some((el) => el instanceof HTMLElement && el.hasAttribute("data-handles-escape"));
516
+ if (hasEscapeHandler) {
517
+ return;
518
+ }
519
+ event.stopPropagation();
520
+ event.preventDefault();
521
+ this.hideConversations();
522
+ }
523
+ };
524
+ handleBackdropClick_fn = function() {
525
+ this.hideConversations();
526
+ };
527
+ handleConversationsToggle_fn = function() {
528
+ this.toggleConversations();
529
+ };
530
+ handleThreadSelect_fn = function(evt) {
531
+ const { id, title } = evt.detail;
532
+ this._selectedThreadId = id;
533
+ this._dispatchHostEvent({
534
+ type: "forge-ai-chatbot-conversation-select",
535
+ detail: { id, title }
536
+ });
537
+ this.hideConversations();
538
+ };
539
+ handleNewChat_fn = function(event) {
540
+ if (event.defaultPrevented) {
541
+ return;
542
+ }
543
+ const hostEvent = this._dispatchHostEvent({ type: "forge-ai-chatbot-new-chat", cancelable: true });
544
+ if (!hostEvent.defaultPrevented) {
545
+ this.startNewChat();
374
546
  }
375
- return html`<div class="session-files" slot="attachments">${content}</div>`;
547
+ this.hideConversations();
548
+ };
549
+ handlePanelClose_fn = function() {
550
+ this.hideConversations();
376
551
  };
552
+ _handleConversationSearch = /* @__PURE__ */ new WeakMap();
553
+ _handleConversationLoadMore = /* @__PURE__ */ new WeakMap();
554
+ _handleConversationRename = /* @__PURE__ */ new WeakMap();
555
+ _handleConversationDelete = /* @__PURE__ */ new WeakMap();
377
556
  promptSlot_get = function() {
378
557
  const isUploading = this._isUploading;
379
558
  return html`
@@ -383,13 +562,15 @@ promptSlot_get = function() {
383
562
  .placeholder=${this.placeholder}
384
563
  .running=${this._isStreaming || isUploading}
385
564
  .slashCommands=${this._slashCommands}
565
+ .contextItems=${this._allContextItems}
386
566
  ?disabled=${isUploading}
387
567
  ?debug-mode=${this.debugMode}
388
568
  @forge-ai-prompt-send=${this._handleSend}
389
569
  @forge-ai-prompt-stop=${this._handleStop}
390
570
  @forge-ai-prompt-cancel=${this._handleCancel}
391
571
  @forge-ai-prompt-debug-toggle=${this._handleDebugToggle}
392
- @forge-ai-prompt-command=${this._handleSlashCommand}>
572
+ @forge-ai-prompt-command=${this._handleSlashCommand}
573
+ @forge-ai-prompt-context-remove=${this._handlePromptContextRemove}>
393
574
  ${when(
394
575
  this.fileUpload === "on",
395
576
  () => html`
@@ -457,6 +638,24 @@ __decorateClass([
457
638
  __decorateClass([
458
639
  property({ attribute: "minimize-icon" })
459
640
  ], AiChatbotComponent.prototype, "minimizeIcon", 2);
641
+ __decorateClass([
642
+ property({ type: Boolean, attribute: "show-conversations-button" })
643
+ ], AiChatbotComponent.prototype, "showConversationsButton", 2);
644
+ __decorateClass([
645
+ property({ type: Array, attribute: false })
646
+ ], AiChatbotComponent.prototype, "recentThreads", 2);
647
+ __decorateClass([
648
+ property({ type: Boolean, attribute: "conversations-open", reflect: true })
649
+ ], AiChatbotComponent.prototype, "conversationsOpen", 2);
650
+ __decorateClass([
651
+ property({ type: Boolean, attribute: "show-conversation-rename" })
652
+ ], AiChatbotComponent.prototype, "showConversationRename", 2);
653
+ __decorateClass([
654
+ property({ type: Boolean, attribute: "show-conversation-delete" })
655
+ ], AiChatbotComponent.prototype, "showConversationDelete", 2);
656
+ __decorateClass([
657
+ state()
658
+ ], AiChatbotComponent.prototype, "_selectedThreadId", 2);
460
659
  AiChatbotComponent = __decorateClass([
461
660
  customElement(AiChatbotComponentTagName)
462
661
  ], AiChatbotComponent);
@@ -1,4 +1,4 @@
1
- const styles = '/* prettier-ignore */\n:host {\n display: block;\n width: 100%;\n height: 100%;\n --_ai-chatbot-icon-shape: var(--forge-ai-chatbot-icon-shape, calc(var(--forge-shape-round, 50%) * var(--forge-shape-factor, 1)));\n}\n\nforge-ai-chat-interface::part(messages) {\n overflow: hidden;\n}\nforge-ai-chat-interface forge-ai-message-thread {\n min-height: 0;\n}\n\n.session-files {\n display: flex;\n flex-direction: column;\n gap: var(--forge-spacing-xsmall, 8px);\n min-width: 0;\n}\n.session-files .session-files-header {\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n font-family: var(--forge-typography-label1-font-family, var(--forge-typography-font-family, "Roboto", sans-serif));\n font-size: var(--forge-typography-label1-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-label-font-size-scale, 0.75)));\n font-weight: var(--forge-typography-label1-font-weight, 400);\n line-height: var(--forge-typography-label1-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-label-line-height-scale, 1.25)));\n letter-spacing: var(--forge-typography-label1-letter-spacing, 0.0357142857em);\n text-transform: var(--forge-typography-label1-text-transform, inherit);\n text-decoration: var(--forge-typography-label1-text-decoration, inherit);\n color: var(--forge-theme-text-medium, rgba(0, 0, 0, 0.6));\n}\n.session-files .session-files-list::-webkit-scrollbar {\n height: var(--forge-scrollbar-height, 16px);\n width: var(--forge-scrollbar-width, 16px);\n}\n.session-files .session-files-list::-webkit-scrollbar-track {\n background-color: var(--forge-scrollbar-track-container, var(--forge-theme-surface-container-low, #ebebeb));\n}\n.session-files .session-files-list::-webkit-scrollbar-track:hover {\n background-color: var(--forge-scrollbar-track-container-hover, var(--forge-theme-surface-container-low, #ebebeb));\n}\n.session-files .session-files-list::-webkit-scrollbar-corner {\n background-color: var(--forge-scrollbar-track-container, var(--forge-theme-surface-container-low, #ebebeb));\n}\n.session-files .session-files-list::-webkit-scrollbar-thumb {\n height: var(--forge-scrollbar-thumb-min-height, 32px);\n width: var(--forge-scrollbar-thumb-min-width, 32px);\n border-radius: var(--forge-scrollbar-border-radius, calc(var(--forge-shape-full, 9999px) * var(--forge-shape-factor, 1)));\n border-width: var(--forge-scrollbar-border-width, 3px);\n border-style: solid;\n border-color: transparent;\n background-color: var(--forge-scrollbar-thumb-container, var(--forge-theme-surface-container-medium, #c2c2c2));\n background-clip: content-box;\n}\n.session-files .session-files-list::-webkit-scrollbar-thumb:hover {\n background-color: var(--forge-scrollbar-thumb-container-hover, var(--forge-theme-surface-container-high, #9e9e9e));\n}\n.session-files .session-files-list {\n display: flex;\n gap: var(--forge-spacing-small, 12px);\n overflow-x: auto;\n padding-block-end: var(--forge-spacing-xsmall, 8px);\n}\n\n.disclaimer {\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n font-family: var(--forge-typography-label1-font-family, var(--forge-typography-font-family, "Roboto", sans-serif));\n font-size: var(--forge-typography-label1-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-label-font-size-scale, 0.75)));\n font-weight: var(--forge-typography-label1-font-weight, 400);\n line-height: var(--forge-typography-label1-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-label-line-height-scale, 1.25)));\n letter-spacing: var(--forge-typography-label1-letter-spacing, 0.0357142857em);\n text-transform: var(--forge-typography-label1-text-transform, inherit);\n text-decoration: var(--forge-typography-label1-text-decoration, inherit);\n color: var(--forge-theme-text-medium, rgba(0, 0, 0, 0.6));\n text-align: center;\n margin-block-start: var(--forge-spacing-xxsmall, 4px);\n margin-block-end: calc(var(--forge-spacing-small, 12px) * -1);\n}\n\n.suggestions-container {\n width: 100%;\n align-self: start;\n}\n\n.empty-state-icon,\n::slotted([slot=empty-state-icon]) {\n height: 200px;\n width: 200px;\n border-radius: var(--_ai-chatbot-icon-shape);\n}';
1
+ const styles = '/* prettier-ignore */\n/**\n * @license\n * Copyright Tyler Technologies, Inc.\n * License: Apache-2.0\n */\n@keyframes forge-dialog-zoom-in {\n from {\n opacity: var(--_dialog-zoom-opacity);\n scale: var(--_dialog-zoom-scale);\n }\n to {\n opacity: 1;\n scale: 1;\n }\n}\n@keyframes forge-dialog-zoom-out {\n from {\n opacity: 1;\n scale: 1;\n }\n to {\n opacity: var(--_dialog-zoom-opacity);\n scale: var(--_dialog-zoom-scale);\n }\n}\n@keyframes forge-dialog-fade-in {\n from {\n opacity: var(--_dialog-fade-opacity);\n }\n to {\n opacity: 1;\n }\n}\n@keyframes forge-dialog-fade-out {\n from {\n opacity: 1;\n }\n to {\n opacity: var(--_dialog-fade-opacity);\n }\n}\n@keyframes forge-dialog-slide-in {\n from {\n opacity: var(--_dialog-slide-opacity);\n translate: var(--_dialog-slide-translate);\n }\n to {\n opacity: 1;\n translate: 0 0;\n }\n}\n@keyframes forge-dialog-slide-out {\n from {\n opacity: 1;\n translate: 0 0;\n }\n to {\n opacity: var(--_dialog-slide-opacity);\n translate: var(--_dialog-slide-translate);\n }\n}\n.forge-dialog {\n --_dialog-background:var(--forge-dialog-background, var(--forge-theme-surface-bright, #ffffff));\n --_dialog-shape:var(--forge-dialog-shape, calc(var(--forge-shape-medium, 4px) * var(--forge-shape-factor, 1)));\n --_dialog-elevation:var(--forge-dialog-elevation, 0px 11px 15px -7px rgba(0, 0, 0, 0.2), 0px 24px 38px 3px rgba(0, 0, 0, 0.14), 0px 9px 46px 8px rgba(0, 0, 0, 0.12));\n --_dialog-spacing:var(--forge-dialog-spacing, auto);\n --_dialog-block-start-spacing:var(--forge-dialog-block-start-spacing, var(--_dialog-spacing));\n --_dialog-block-end-spacing:var(--forge-dialog-block-end-spacing, var(--_dialog-spacing));\n --_dialog-inline-start-spacing:var(--forge-dialog-inline-start-spacing, var(--_dialog-spacing));\n --_dialog-inline-end-spacing:var(--forge-dialog-inline-end-spacing, var(--_dialog-spacing));\n --_dialog-padding:var(--forge-dialog-padding, 0);\n --_dialog-width:var(--forge-dialog-width, fit-content);\n --_dialog-height:var(--forge-dialog-height, fit-content);\n --_dialog-min-width:var(--forge-dialog-min-width, 0);\n --_dialog-max-width:var(--forge-dialog-max-width, calc(100% - var(--forge-spacing-xxlarge, 48px)));\n --_dialog-min-height:var(--forge-dialog-min-height, 0);\n --_dialog-max-height:var(--forge-dialog-max-height, calc(100% - var(--forge-spacing-xxlarge, 48px)));\n --_dialog-z-index:var(--forge-dialog-z-index, var(--forge-z-index-dialog, 8));\n --_dialog-move-handle-color:var(--forge-dialog-move-handle-color, currentColor);\n --_dialog-move-handle-size:var(--forge-dialog-move-handle-size, 24px);\n --_dialog-move-handle-hover-cursor:var(--forge-dialog-move-handle-hover-cursor, grab);\n --_dialog-move-handle-active-cursor:var(--forge-dialog-move-handle-active-cursor, grabbing);\n --_dialog-move-handle-spacing:var(--forge-dialog-move-handle-spacing, calc(var(--forge-spacing-xxsmall, 4px) * -1) 0 0);\n --_dialog-move-transition-duration:var(--forge-dialog-move-transition-duration, var(--forge-animation-duration-short4, 200ms));\n --_dialog-move-transition-easing:var(--forge-dialog-move-transition-easing, var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1)));\n --_dialog-moving-opacity:var(--forge-dialog-moving-opacity, 0.54);\n --_dialog-enter-animation-duration:var(--forge-dialog-enter-animation-duration, var(--forge-animation-duration-medium1, 250ms));\n --_dialog-enter-animation-easing:var(--forge-dialog-enter-animation-easing, var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1)));\n --_dialog-exit-animation-duration:var(--forge-dialog-exit-animation-duration, var(--forge-animation-duration-short2, 100ms));\n --_dialog-exit-animation-easing:var(--forge-dialog-exit-animation-easing, var(--forge-animation-easing-emphasized-accelerate, cubic-bezier(0.3, 0, 0.8, 0.15)));\n --_dialog-zoom-opacity:var(--forge-dialog-zoom-opacity, 0);\n --_dialog-zoom-scale:var(--forge-dialog-zoom-scale, 0.8);\n --_dialog-fade-opacity:var(--forge-dialog-fade-opacity, 0);\n --_dialog-slide-opacity:var(--forge-dialog-slide-opacity, 0);\n --_dialog-slide-translate:var(--forge-dialog-slide-translate, 0 -30%);\n --_dialog-backdrop-opacity:var(--forge-dialog-backdrop-opacity, var(--forge-backdrop-opacity, 0.54));\n --_dialog-nonmodal-elevation:var(--forge-dialog-nonmodal-elevation, 0px 2px 4px -1px rgba(0, 0, 0, 0.2), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12));\n --_dialog-fullscreen-enter-animation-duration:var(--forge-dialog-fullscreen-enter-animation-duration, var(--forge-animation-duration-medium1, 250ms));\n --_dialog-fullscreen-exit-animation-duration:var(--forge-dialog-fullscreen-exit-animation-duration, var(--forge-animation-duration-short2, 100ms));\n --_dialog-position-x:var(--forge-dialog-position-x, 0);\n --_dialog-position-y:var(--forge-dialog-position-y, 0);\n --_dialog-preset-sheet-enter-animation-duration:var(--forge-dialog-preset-sheet-enter-animation-duration, var(--forge-animation-duration-medium1, 250ms));\n --_dialog-preset-sheet-exit-animation-duration:var(--forge-dialog-preset-sheet-exit-animation-duration, var(--forge-animation-duration-short3, 150ms));\n --_backdrop-background:var(--forge-backdrop-background, #000);\n --_backdrop-opacity:var(--forge-backdrop-opacity, 0.54);\n --_backdrop-z-index:var(--forge-backdrop-z-index, var(--forge-z-index-backdrop, 7));\n --_backdrop-enter-animation-duration:var(--forge-backdrop-enter-animation-duration, var(--forge-animation-duration-short4, 200ms));\n --_backdrop-enter-animation-easing:var(--forge-backdrop-enter-animation-easing, var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1)));\n --_backdrop-exit-animation-duration:var(--forge-backdrop-exit-animation-duration, var(--forge-animation-duration-short1, 50ms));\n --_backdrop-exit-animation-easing:var(--forge-backdrop-exit-animation-easing, var(--forge-animation-easing-emphasized-accelerate, cubic-bezier(0.3, 0, 0.8, 0.15)));\n --forge-theme-surface: var(--forge-theme-surface-bright, #ffffff);\n}\n\n.forge-dialog {\n position: fixed;\n inset: 0;\n z-index: var(--_dialog-z-index);\n background-color: rgba(0, 0, 0, 0);\n color: inherit;\n border: none;\n width: auto;\n height: auto;\n padding: 0;\n margin: 0;\n overflow: visible;\n max-width: 100%;\n max-height: 100%;\n box-sizing: border-box;\n position: absolute;\n inset: 0;\n display: flex;\n background: var(--_dialog-background);\n box-shadow: var(--_dialog-elevation);\n z-index: var(--_dialog-z-index);\n overflow: hidden;\n border-radius: var(--_dialog-shape);\n margin-block-start: var(--_dialog-block-start-spacing);\n margin-block-end: var(--_dialog-block-end-spacing);\n margin-inline-start: var(--_dialog-inline-start-spacing);\n margin-inline-end: var(--_dialog-inline-end-spacing);\n padding: var(--_dialog-padding);\n width: var(--_dialog-width);\n height: var(--_dialog-height);\n min-width: var(--_dialog-min-width);\n max-width: var(--_dialog-max-width);\n min-height: var(--_dialog-min-height);\n max-height: var(--_dialog-max-height);\n box-sizing: border-box;\n animation-duration: var(--_dialog-exit-animation-duration);\n animation-timing-function: var(--_dialog-exit-animation-easing);\n position: fixed;\n transition-property: display, opacity, overlay, scale;\n transition-behavior: allow-discrete;\n}\n\n.forge-dialog > forge-scaffold {\n height: auto;\n}\n\n.forge-dialog--fullscreen {\n --_dialog-enter-animation-duration:var(--_dialog-fullscreen-enter-animation-duration);\n --_dialog-exit-animation-duration:var(--_dialog-fullscreen-exit-animation-duration);\n height: 100%;\n width: 100%;\n max-width: none;\n max-height: none;\n border-radius: 0;\n box-shadow: none;\n}\n\n.forge-dialog:not(:modal) {\n --_dialog-elevation:var(--_dialog-nonmodal-elevation);\n pointer-events: all;\n}\n\n.forge-dialog--moveable {\n user-select: none;\n transition-property: opacity;\n transition-duration: var(--_dialog-move-transition-duration);\n transition-timing-function: var(--_dialog-move-transition-easing);\n}\n\n.forge-dialog--moved {\n margin: 0;\n}\n\n.forge-dialog--moving {\n opacity: var(--_dialog-moving-opacity);\n}\n\n.forge-dialog__move-handle {\n fill: var(--_dialog-move-handle-color);\n height: var(--_dialog-move-handle-size);\n width: var(--_dialog-move-handle-size);\n margin: var(--_dialog-move-handle-spacing);\n touch-action: none;\n}\n\n.forge-dialog__move-handle:hover {\n cursor: var(--_dialog-move-handle-hover-cursor);\n}\n\n.forge-dialog__move-handle:active {\n cursor: var(--_dialog-move-handle-active-cursor);\n}\n\n.forge-dialog__move-handle-container {\n position: absolute;\n top: 0;\n z-index: 1;\n display: flex;\n justify-content: center;\n width: 100%;\n}\n\n.forge-dialog--top {\n --_dialog-block-start-spacing:var(--forge-dialog-block-start-spacing, 0);\n top: 0;\n bottom: auto;\n}\n\n.forge-dialog--top-right {\n --_dialog-spacing:var(--forge-dialog-spacing, 0);\n top: 0;\n left: auto;\n right: 0;\n bottom: auto;\n}\n\n.forge-dialog--top-left {\n --_dialog-spacing:var(--forge-dialog-spacing, 0);\n top: 0;\n left: 0;\n right: auto;\n bottom: auto;\n}\n\n.forge-dialog--bottom {\n --_dialog-block-end-spacing:var(--forge-dialog-block-end-spacing, 0);\n top: auto;\n bottom: 0;\n}\n\n.forge-dialog--bottom-right {\n --_dialog-spacing:var(--forge-dialog-spacing, 0);\n top: auto;\n left: auto;\n right: 0;\n bottom: 0;\n}\n\n.forge-dialog--bottom-left {\n --_dialog-spacing:var(--forge-dialog-spacing, 0);\n top: auto;\n left: 0;\n right: auto;\n bottom: 0;\n}\n\n.forge-dialog--right {\n --_dialog-spacing:var(--forge-dialog-spacing, 0);\n top: auto;\n left: auto;\n right: 0;\n bottom: auto;\n}\n\n.forge-dialog--left {\n --_dialog-spacing:var(--forge-dialog-spacing, 0);\n top: auto;\n left: 0;\n right: auto;\n bottom: auto;\n}\n\n.forge-dialog--custom {\n margin: 0;\n top: var(--_dialog-position-x);\n left: var(--_dialog-position-y);\n}\n\n.forge-dialog--bottom-sheet {\n --_dialog-enter-animation-duration:var(--_dialog-preset-sheet-enter-animation-duration);\n --_dialog-exit-animation-duration:var(--_dialog-preset-sheet-exit-animation-duration);\n --_dialog-max-width:var(--forge-dialog-max-width, none);\n --_dialog-max-height:var(--forge-dialog-max-height, none);\n inset: auto;\n display: inline-flex;\n bottom: 0;\n left: 0;\n right: 0;\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n --_dialog-slide-translate:var(--forge-dialog-slide-translate, 0 100%);\n}\n\n.forge-dialog--bottom-sheet.forge-dialog {\n transition-property: display, opacity, overlay, translate;\n}\n\n.forge-dialog--bottom-sheet.forge-dialog[open] {\n translate: 0 0;\n}\n\n@starting-style {\n .forge-dialog--bottom-sheet.forge-dialog[open] {\n opacity: var(--_dialog-slide-opacity);\n translate: var(--_dialog-slide-translate);\n }\n}\n.forge-dialog--bottom-sheet.forge-dialog:not([open]) {\n opacity: var(--_dialog-slide-opacity);\n scale: 1;\n translate: var(--_dialog-slide-translate);\n}\n\n.forge-dialog--left-sheet {\n --_dialog-enter-animation-duration:var(--_dialog-preset-sheet-enter-animation-duration);\n --_dialog-exit-animation-duration:var(--_dialog-preset-sheet-exit-animation-duration);\n --_dialog-max-width:var(--forge-dialog-max-width, none);\n --_dialog-max-height:var(--forge-dialog-max-height, none);\n inset: auto;\n display: inline-flex;\n left: 0;\n bottom: 0;\n top: 0;\n height: 100%;\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n --_dialog-slide-translate:var(--forge-dialog-slide-translate, -100% 0);\n}\n\n.forge-dialog--left-sheet.forge-dialog {\n transition-property: display, opacity, overlay, translate;\n}\n\n.forge-dialog--left-sheet.forge-dialog[open] {\n translate: 0 0;\n}\n\n@starting-style {\n .forge-dialog--left-sheet.forge-dialog[open] {\n opacity: var(--_dialog-slide-opacity);\n translate: var(--_dialog-slide-translate);\n }\n}\n.forge-dialog--left-sheet.forge-dialog:not([open]) {\n opacity: var(--_dialog-slide-opacity);\n scale: 1;\n translate: var(--_dialog-slide-translate);\n}\n\n.forge-dialog--right-sheet {\n --_dialog-enter-animation-duration:var(--_dialog-preset-sheet-enter-animation-duration);\n --_dialog-exit-animation-duration:var(--_dialog-preset-sheet-exit-animation-duration);\n --_dialog-max-width:var(--forge-dialog-max-width, none);\n --_dialog-max-height:var(--forge-dialog-max-height, none);\n inset: auto;\n display: inline-flex;\n right: 0;\n bottom: 0;\n top: 0;\n height: 100%;\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n --_dialog-slide-translate:var(--forge-dialog-slide-translate, 100% 0);\n}\n\n.forge-dialog--right-sheet.forge-dialog {\n transition-property: display, opacity, overlay, translate;\n}\n\n.forge-dialog--right-sheet.forge-dialog[open] {\n translate: 0 0;\n}\n\n@starting-style {\n .forge-dialog--right-sheet.forge-dialog[open] {\n opacity: var(--_dialog-slide-opacity);\n translate: var(--_dialog-slide-translate);\n }\n}\n.forge-dialog--right-sheet.forge-dialog:not([open]) {\n opacity: var(--_dialog-slide-opacity);\n scale: 1;\n translate: var(--_dialog-slide-translate);\n}\n\n.forge-dialog--top-sheet {\n --_dialog-enter-animation-duration:var(--_dialog-preset-sheet-enter-animation-duration);\n --_dialog-exit-animation-duration:var(--_dialog-preset-sheet-exit-animation-duration);\n --_dialog-max-width:var(--forge-dialog-max-width, none);\n --_dialog-max-height:var(--forge-dialog-max-height, none);\n inset: auto;\n display: inline-flex;\n top: 0;\n left: 0;\n right: 0;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n --_dialog-slide-translate:var(--forge-dialog-slide-translate, 0 -100%);\n}\n\n.forge-dialog--top-sheet.forge-dialog {\n transition-property: display, opacity, overlay, translate;\n}\n\n.forge-dialog--top-sheet.forge-dialog[open] {\n translate: 0 0;\n}\n\n@starting-style {\n .forge-dialog--top-sheet.forge-dialog[open] {\n opacity: var(--_dialog-slide-opacity);\n translate: var(--_dialog-slide-translate);\n }\n}\n.forge-dialog--top-sheet.forge-dialog:not([open]) {\n opacity: var(--_dialog-slide-opacity);\n scale: 1;\n translate: var(--_dialog-slide-translate);\n}\n\n.forge-dialog::backdrop {\n --forge-backdrop-opacity: var(--_backdrop-opacity);\n --forge-backdrop-enter-animation-duration: var(--_backdrop-enter-animation-duration);\n --forge-backdrop-enter-animation-easing: var(--_backdrop-enter-animation-easing);\n --forge-backdrop-exit-animation-duration: var(--_backdrop-exit-animation-duration);\n --forge-backdrop-exit-animation-easing: var(--_backdrop-exit-animation-easing);\n position: absolute;\n inset: 0;\n z-index: var(--_backdrop-z-index);\n background: var(--_backdrop-background);\n opacity: 0;\n animation-fill-mode: forwards;\n transition-property: display, opacity, overlay;\n}\n\n.forge-dialog[open] {\n opacity: 1;\n scale: 1;\n transition-duration: var(--_dialog-enter-animation-duration);\n transition-timing-function: var(--_dialog-enter-animation-easing);\n}\n\n@starting-style {\n .forge-dialog[open] {\n opacity: var(--_dialog-zoom-opacity);\n scale: var(--_dialog-zoom-scale);\n }\n}\n.forge-dialog[open]::backdrop {\n opacity: var(--_backdrop-opacity);\n transition-duration: var(--_backdrop-enter-animation-duration);\n transition-timing-function: var(--_backdrop-enter-animation-easing);\n}\n\n@starting-style {\n .forge-dialog[open]::backdrop {\n opacity: 0;\n }\n}\n.forge-dialog:not([open]) {\n animation-duration: var(--_dialog-enter-animation-duration);\n animation-timing-function: var(--_dialog-enter-animation-easing);\n display: none;\n opacity: var(--_dialog-zoom-opacity);\n scale: var(--_dialog-zoom-scale);\n transition-duration: var(--_dialog-exit-animation-duration);\n transition-timing-function: var(--_dialog-exit-animation-easing);\n}\n\n.forge-dialog:not([open])::backdrop {\n transition-duration: var(--_backdrop-exit-animation-duration);\n transition-timing-function: var(--_backdrop-exit-animation-easing);\n}\n\n.forge-dialog--animation-fade.forge-dialog {\n transition-property: display, opacity, overlay;\n}\n\n@starting-style {\n .forge-dialog--animation-fade.forge-dialog[open] {\n opacity: var(--_dialog-fade-opacity);\n }\n}\n.forge-dialog--animation-fade.forge-dialog:not([open]) {\n opacity: var(--_dialog-fade-opacity);\n scale: 1;\n}\n\n.forge-dialog--animation-slide.forge-dialog {\n transition-property: display, opacity, overlay, translate;\n}\n\n.forge-dialog--animation-slide.forge-dialog[open] {\n translate: 0 0;\n}\n\n@starting-style {\n .forge-dialog--animation-slide.forge-dialog[open] {\n opacity: var(--_dialog-slide-opacity);\n translate: var(--_dialog-slide-translate);\n }\n}\n.forge-dialog--animation-slide.forge-dialog:not([open]) {\n opacity: var(--_dialog-slide-opacity);\n scale: 1;\n translate: var(--_dialog-slide-translate);\n}\n\n.forge-dialog--animation-none {\n --_dialog-enter-animation-duration:var(--forge-dialog-enter-animation-duration, 0s);\n --_dialog-exit-animation-duration:var(--forge-dialog-exit-animation-duration, 0s);\n --_backdrop-enter-animation-duration:var(--forge-backdrop-enter-animation-duration, 0s);\n --_backdrop-exit-animation-duration:var(--forge-backdrop-exit-animation-duration, 0s);\n}\n\n@media (prefers-reduced-motion) {\n .forge-dialog.forge-dialog {\n transition-property: display, opacity, overlay;\n }\n @starting-style {\n .forge-dialog.forge-dialog[open] {\n opacity: var(--_dialog-fade-opacity);\n }\n }\n .forge-dialog.forge-dialog:not([open]) {\n opacity: var(--_dialog-fade-opacity);\n scale: 1;\n }\n}\n:host {\n display: block;\n width: 100%;\n height: 100%;\n --_ai-chatbot-icon-shape: var(--forge-ai-chatbot-icon-shape, calc(var(--forge-shape-round, 50%) * var(--forge-shape-factor, 1)));\n}\n\n.chatbot-container {\n position: relative;\n display: grid;\n height: 100%;\n overflow: hidden;\n}\n\nforge-ai-chat-interface::part(messages) {\n overflow: hidden;\n}\nforge-ai-chat-interface forge-ai-message-thread {\n min-height: 0;\n}\n\n.disclaimer {\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n font-family: var(--forge-typography-label1-font-family, var(--forge-typography-font-family, "Roboto", sans-serif));\n font-size: var(--forge-typography-label1-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-label-font-size-scale, 0.75)));\n font-weight: var(--forge-typography-label1-font-weight, 400);\n line-height: var(--forge-typography-label1-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-label-line-height-scale, 1.25)));\n letter-spacing: var(--forge-typography-label1-letter-spacing, 0.0357142857em);\n text-transform: var(--forge-typography-label1-text-transform, inherit);\n text-decoration: var(--forge-typography-label1-text-decoration, inherit);\n color: var(--forge-theme-text-medium, rgba(0, 0, 0, 0.6));\n text-align: center;\n margin-block-start: var(--forge-spacing-xxsmall, 4px);\n margin-block-end: calc(var(--forge-spacing-small, 12px) * -1);\n}\n\n.suggestions-container {\n width: 100%;\n align-self: start;\n}\n\n.empty-state-icon,\n::slotted([slot=empty-state-icon]) {\n height: 200px;\n width: 200px;\n border-radius: var(--_ai-chatbot-icon-shape);\n}\n\n.conversations-backdrop {\n position: absolute;\n inset: 0;\n background-color: transparent;\n z-index: 1;\n}\n\n.conversations-dialog {\n display: grid;\n width: min(90%, 360px);\n padding: 0;\n border: 0;\n position: absolute;\n z-index: 2;\n --forge-dialog-shape: 0;\n --forge-dialog-nonmodal-elevation: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);\n}';
2
2
  export {
3
3
  styles as default
4
4
  };
@@ -4,7 +4,7 @@ export type { ForgeAiChatbotMessageEventData, ForgeAiChatbotToolCallEventData, F
4
4
  export { AiChatbotToolCallComponent, AiChatbotToolCallComponentTagName } from './ai-chatbot-tool-call.js';
5
5
  export type { Suggestion } from '../ai-suggestions/index.js';
6
6
  export { AgentAdapter, type MessageStartEvent, type MessageDeltaEvent, type MessageEndEvent, type ToolCallEvent, type ToolCallStartEvent, type ToolCallArgsEvent, type ToolCallEndEvent, type FileUploadEvent, type FileRemoveEvent, type AdapterState, type ErrorEvent, type CustomAgentEvent, type RawAgentEvent, type RunStartedAgentEvent, type StepStartedAgentEvent, type StepFinishedAgentEvent, type StateSnapshotAgentEvent, type StateDeltaAgentEvent, type ActivitySnapshotAgentEvent, type ActivityDeltaAgentEvent } from './agent-adapter.js';
7
- export type { Agent, ChatMessage, ToolDefinition, ToolCall, ToolRenderer, IToolRenderer, HandlerContext, ToolStartContext, ToolDeltaContext, ToolEndContext, FileAttachment, UploadedFileMetadata, FileUploadCallbacks, FileUploadHandler, FileRemoveCallbacks, ThreadState, FeedbackType, ResponseFeedback } from './types.js';
7
+ export type { Agent, ChatMessage, ContextItem, ToolDefinition, ToolCall, ToolRenderer, IToolRenderer, HandlerContext, ToolStartContext, ToolDeltaContext, ToolEndContext, FileAttachment, UploadedFileMetadata, FileUploadCallbacks, FileUploadHandler, FileRemoveCallbacks, ThreadState, FeedbackType, ResponseFeedback, ForgeAiChatbotContextRemoveEventData } from './types.js';
8
8
  export * from './ag-ui-adapter.js';
9
9
  export * from './http-agent-with-credentials.js';
10
10
  export * from './event-emitter.js';
@@ -1,3 +1,4 @@
1
+ import { Thread } from '../ai-threads';
1
2
  /**
2
3
  * Valid HTML heading levels for accessibility and semantic structure
3
4
  */
@@ -277,3 +278,41 @@ export interface ThreadState {
277
278
  timestamp?: number;
278
279
  selectedAgentId?: string;
279
280
  }
281
+ export interface ForgeAiChatbotConversationSelectEventData {
282
+ id: string;
283
+ title: string;
284
+ }
285
+ export interface ForgeAiChatbotConversationSearchEventData {
286
+ query: string;
287
+ setResults: (results: Thread[]) => void;
288
+ }
289
+ export interface ForgeAiChatbotConversationLoadMoreEventData {
290
+ query: string;
291
+ appendResults: (results: Thread[]) => void;
292
+ }
293
+ export interface ForgeAiChatbotConversationRenameEventData {
294
+ id: string;
295
+ oldTitle: string;
296
+ newTitle: string;
297
+ onSuccess: () => void;
298
+ onError: (error?: string) => void;
299
+ }
300
+ export interface ForgeAiChatbotConversationDeleteEventData {
301
+ id: string;
302
+ thread: Thread;
303
+ onSuccess: () => void;
304
+ onError: (error?: string) => void;
305
+ }
306
+ export interface ContextItem {
307
+ id: string;
308
+ label: string;
309
+ removable?: boolean;
310
+ sublabel?: string;
311
+ loading?: boolean;
312
+ type?: 'file' | 'context';
313
+ }
314
+ export interface ForgeAiChatbotContextRemoveEventData {
315
+ id: string;
316
+ item: ContextItem;
317
+ }
318
+ export type { Thread };
@@ -1,3 +1,4 @@
1
+ import { FileAttachment, ContextItem } from './types.js';
1
2
  /**
2
3
  * Generates a unique ID using UUID v4
3
4
  */
@@ -10,3 +11,7 @@ export declare function renderMarkdown(content: string): string;
10
11
  * Downloads content as a file with specified MIME type
11
12
  */
12
13
  export declare function downloadFile(content: string, filename: string, mimeType?: string): void;
14
+ /**
15
+ * Converts file attachments to context items
16
+ */
17
+ export declare function fileAttachmentsToContextItems(completedAttachments: FileAttachment[], pendingAttachments: FileAttachment[]): ContextItem[];
@@ -36,8 +36,36 @@ function downloadFile(content, filename, mimeType = "text/plain") {
36
36
  document.body.removeChild(link);
37
37
  URL.revokeObjectURL(url);
38
38
  }
39
+ function fileAttachmentsToContextItems(completedAttachments, pendingAttachments) {
40
+ const pending = pendingAttachments.map((file) => ({
41
+ id: file.id,
42
+ label: file.filename,
43
+ sublabel: formatBytes(file.size),
44
+ loading: file.uploading ?? true,
45
+ removable: true,
46
+ type: "file"
47
+ }));
48
+ const completed = completedAttachments.map((file) => ({
49
+ id: file.id,
50
+ label: file.filename,
51
+ sublabel: formatBytes(file.size),
52
+ removable: true,
53
+ type: "file"
54
+ }));
55
+ return [...pending, ...completed];
56
+ }
57
+ function formatBytes(bytes) {
58
+ if (bytes === 0) {
59
+ return "0 B";
60
+ }
61
+ const k = 1024;
62
+ const sizes = ["B", "KB", "MB", "GB"];
63
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
64
+ return `${Math.round(bytes / Math.pow(k, i) * 100) / 100} ${sizes[i]}`;
65
+ }
39
66
  export {
40
67
  downloadFile,
68
+ fileAttachmentsToContextItems,
41
69
  generateId,
42
70
  renderMarkdown
43
71
  };
@@ -4,14 +4,30 @@ import { AiPromptComponent, ForgeAiPromptSendEventData } from '../ai-prompt';
4
4
  import { ForgeAiSuggestionsEventData } from '../ai-suggestions';
5
5
  import { AiChatbotBase } from '../ai-chatbot/ai-chatbot-base.js';
6
6
  import { ChatMessage, ThreadState } from '../ai-chatbot/types.js';
7
+ import { Thread } from '../ai-threads/ai-threads';
7
8
  import { Ref } from 'lit/directives/ref.js';
8
9
  export type LauncherViewState = 'welcome' | 'conversation';
10
+ export interface ForgeAiChatbotLauncherThreadRenameEventData {
11
+ id: string;
12
+ oldTitle: string;
13
+ newTitle: string;
14
+ onSuccess: () => void;
15
+ onError: (error?: string) => void;
16
+ }
17
+ export interface ForgeAiChatbotLauncherThreadDeleteEventData {
18
+ id: string;
19
+ thread: Thread;
20
+ onSuccess: () => void;
21
+ onError: (error?: string) => void;
22
+ }
9
23
  declare global {
10
24
  interface HTMLElementTagNameMap {
11
25
  'forge-ai-chatbot-launcher': AiChatbotLauncherComponent;
12
26
  }
13
27
  interface HTMLElementEventMap {
14
28
  'forge-ai-chatbot-launcher-conversation-start': CustomEvent<void>;
29
+ 'forge-ai-chatbot-launcher-thread-rename': CustomEvent<ForgeAiChatbotLauncherThreadRenameEventData>;
30
+ 'forge-ai-chatbot-launcher-thread-delete': CustomEvent<ForgeAiChatbotLauncherThreadDeleteEventData>;
15
31
  }
16
32
  }
17
33
  export declare const AiChatbotLauncherComponentTagName: keyof HTMLElementTagNameMap;
@@ -26,8 +42,9 @@ export declare const AiChatbotLauncherComponentTagName: keyof HTMLElementTagName
26
42
  * In conversation mode, a header is displayed with options for clear, export, and agent selection.
27
43
  *
28
44
  * @slot icon - Slot for custom icon (used in both welcome view and conversation header)
29
- * @slot heading - Slot for custom heading content
30
- * @slot description - Slot for custom description/welcome message below the title
45
+ * @slot heading - Slot for custom heading content (welcome view only)
46
+ * @slot description - Slot for custom description/welcome message below the title (welcome view only)
47
+ * @slot header-actions - Slot for custom header action buttons in conversation mode (rendered before built-in header actions)
31
48
  *
32
49
  * @property {string} titleText - The title text to display in the welcome view and header (default: 'AI Assistant')
33
50
  * @property {string} descriptionText - The description text displayed below the title in the welcome view.
@@ -36,6 +53,9 @@ export declare const AiChatbotLauncherComponentTagName: keyof HTMLElementTagName
36
53
  * @property {AgentInfo} agentInfo - Agent metadata for info dialog
37
54
  * @property {Agent[]} agents - List of available agents for selector
38
55
  * @property {string} selectedAgentId - Currently selected agent ID
56
+ * @property {string} threadName - The name of the current thread (shown in conversation view breadcrumb)
57
+ * @property {boolean} showThreadRename - Whether to show the rename option in thread actions menu
58
+ * @property {boolean} showThreadDelete - Whether to show the delete option in thread actions menu
39
59
  *
40
60
  * @cssproperty --forge-ai-chatbot-launcher-icon-color - The fill color for the AI icon.
41
61
  *
@@ -48,14 +68,20 @@ export declare const AiChatbotLauncherComponentTagName: keyof HTMLElementTagName
48
68
  * @event {CustomEvent<ForgeAiChatbotResponseFeedbackEventData>} forge-ai-chatbot-response-feedback - Fired when user provides feedback on a response
49
69
  * @event {CustomEvent<void>} forge-ai-chatbot-info - Fired when header info option is selected
50
70
  * @event {CustomEvent<ForgeAiChatbotAgentChangeEventData>} forge-ai-chatbot-agent-change - Fired when agent selection changes
71
+ * @event {CustomEvent<ForgeAiChatbotLauncherThreadRenameEventData>} forge-ai-chatbot-launcher-thread-rename - Fired when thread rename is saved. Parent should update threadName property and call onSuccess() or onError()
72
+ * @event {CustomEvent<ForgeAiChatbotLauncherThreadDeleteEventData>} forge-ai-chatbot-launcher-thread-delete - Fired when thread deletion is confirmed. Parent should delete thread and call onSuccess() or onError()
51
73
  */
52
74
  export declare class AiChatbotLauncherComponent extends AiChatbotBase {
53
75
  #private;
54
76
  static styles: CSSResult;
55
77
  placeholder: string;
56
78
  descriptionText?: string;
79
+ threadName?: string;
80
+ showThreadRename: boolean;
81
+ showThreadDelete: boolean;
57
82
  private _viewState;
58
83
  private _skipAnimation;
84
+ private _editingThreadId;
59
85
  protected _messageThreadRef: Ref<AiMessageThreadComponent>;
60
86
  protected _promptRef: Ref<AiPromptComponent>;
61
87
  constructor();
@@ -65,6 +91,7 @@ export declare class AiChatbotLauncherComponent extends AiChatbotBase {
65
91
  protected _handleSend(evt: CustomEvent<ForgeAiPromptSendEventData>): Promise<void>;
66
92
  protected _handleSuggestionSelect(evt: CustomEvent<ForgeAiSuggestionsEventData>): Promise<void>;
67
93
  clearMessages(): boolean;
94
+ startNewChat(): void;
68
95
  setMessages(messages: ChatMessage[]): void;
69
96
  sendMessage(content: string, files?: File[]): Promise<void>;
70
97
  setThreadState(threadState: ThreadState, options?: {