@tylertech/forge-ai 0.13.1 → 0.13.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/custom-elements.json +4030 -2118
  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 +6 -0
  7. package/dist/ai-chat-header/ai-chat-header.mjs +51 -7
  8. package/dist/ai-chat-header/ai-chat-header.scss.mjs +1 -1
  9. package/dist/ai-chat-interface/ai-chat-interface.scss.mjs +1 -1
  10. package/dist/ai-chatbot/ai-chatbot-base.d.ts +37 -3
  11. package/dist/ai-chatbot/ai-chatbot-base.mjs +83 -24
  12. package/dist/ai-chatbot/ai-chatbot.d.ts +40 -1
  13. package/dist/ai-chatbot/ai-chatbot.mjs +242 -44
  14. package/dist/ai-chatbot/ai-chatbot.scss.mjs +1 -1
  15. package/dist/ai-chatbot/index.d.ts +1 -1
  16. package/dist/ai-chatbot/types.d.ts +39 -0
  17. package/dist/ai-chatbot/utils.d.ts +5 -0
  18. package/dist/ai-chatbot/utils.mjs +28 -0
  19. package/dist/ai-chatbot-launcher/ai-chatbot-launcher.d.ts +26 -0
  20. package/dist/ai-chatbot-launcher/ai-chatbot-launcher.mjs +155 -10
  21. package/dist/ai-chatbot-launcher/ai-chatbot-launcher.scss.mjs +1 -1
  22. package/dist/ai-confirmation-prompt/ai-confirmation-prompt.d.ts +6 -0
  23. package/dist/ai-confirmation-prompt/ai-confirmation-prompt.mjs +64 -19
  24. package/dist/ai-confirmation-prompt/ai-confirmation-prompt.scss.mjs +1 -1
  25. package/dist/ai-context-chip/ai-context-chip.d.ts +45 -0
  26. package/dist/ai-context-chip/ai-context-chip.mjs +169 -0
  27. package/dist/ai-context-chip/ai-context-chip.scss.mjs +4 -0
  28. package/dist/ai-context-chip/index.d.ts +2 -0
  29. package/dist/ai-context-chip/index.mjs +5 -0
  30. package/dist/ai-context-items/ai-context-items.d.ts +20 -0
  31. package/dist/ai-context-items/ai-context-items.mjs +78 -0
  32. package/dist/ai-context-items/ai-context-items.scss.mjs +4 -0
  33. package/dist/ai-context-items/index.d.ts +1 -0
  34. package/dist/ai-context-items/index.mjs +5 -0
  35. package/dist/ai-conversations-panel/ai-conversations-panel.d.ts +86 -0
  36. package/dist/ai-conversations-panel/ai-conversations-panel.mjs +558 -0
  37. package/dist/ai-conversations-panel/ai-conversations-panel.scss.mjs +4 -0
  38. package/dist/ai-conversations-panel/index.d.ts +2 -0
  39. package/dist/ai-conversations-panel/index.mjs +5 -0
  40. package/dist/ai-copy-button/ai-copy-button.d.ts +32 -0
  41. package/dist/ai-copy-button/ai-copy-button.mjs +116 -0
  42. package/dist/ai-copy-button/ai-copy-button.scss.mjs +4 -0
  43. package/dist/ai-copy-button/index.d.ts +1 -0
  44. package/dist/ai-copy-button/index.mjs +5 -0
  45. package/dist/ai-dialog/ai-dialog.scss.mjs +1 -1
  46. package/dist/ai-dropdown-menu/ai-dropdown-menu-item.scss.mjs +1 -1
  47. package/dist/ai-dropdown-menu/ai-dropdown-menu.d.ts +6 -1
  48. package/dist/ai-dropdown-menu/ai-dropdown-menu.mjs +14 -2
  49. package/dist/ai-dropdown-menu/ai-dropdown-menu.scss.mjs +1 -1
  50. package/dist/ai-edit-thread/ai-edit-thread.d.ts +34 -0
  51. package/dist/ai-edit-thread/ai-edit-thread.mjs +130 -0
  52. package/dist/ai-edit-thread/ai-edit-thread.scss.mjs +4 -0
  53. package/dist/ai-edit-thread/index.d.ts +1 -0
  54. package/dist/ai-edit-thread/index.mjs +5 -0
  55. package/dist/ai-message-thread/ai-message-thread.scss.mjs +1 -1
  56. package/dist/ai-modal/ai-modal.d.ts +11 -2
  57. package/dist/ai-modal/ai-modal.mjs +31 -6
  58. package/dist/ai-prompt/ai-prompt.d.ts +7 -1
  59. package/dist/ai-prompt/ai-prompt.mjs +29 -2
  60. package/dist/ai-sidebar/ai-sidebar.d.ts +11 -0
  61. package/dist/ai-sidebar/ai-sidebar.mjs +94 -4
  62. package/dist/ai-sidebar/ai-sidebar.scss.mjs +1 -1
  63. package/dist/ai-sidebar-chat/ai-sidebar-chat.d.ts +1 -0
  64. package/dist/ai-sidebar-chat/ai-sidebar-chat.mjs +5 -0
  65. package/dist/ai-spinner/ai-spinner.d.ts +1 -1
  66. package/dist/ai-spinner/ai-spinner.scss.mjs +1 -1
  67. package/dist/ai-thread-actions-menu/ai-thread-actions-menu.d.ts +44 -0
  68. package/dist/ai-thread-actions-menu/ai-thread-actions-menu.mjs +136 -0
  69. package/dist/ai-thread-actions-menu/ai-thread-actions-menu.scss.mjs +4 -0
  70. package/dist/ai-thread-actions-menu/index.d.ts +1 -0
  71. package/dist/ai-thread-actions-menu/index.mjs +5 -0
  72. package/dist/ai-threads/ai-threads.d.ts +45 -16
  73. package/dist/ai-threads/ai-threads.mjs +256 -98
  74. package/dist/ai-threads/ai-threads.scss.mjs +1 -1
  75. package/dist/ai-threads-search/ai-threads-search.d.ts +81 -0
  76. package/dist/ai-threads-search/ai-threads-search.mjs +414 -0
  77. package/dist/ai-threads-search/ai-threads-search.scss.mjs +4 -0
  78. package/dist/ai-threads-search/index.d.ts +1 -0
  79. package/dist/ai-threads-search/index.mjs +5 -0
  80. package/dist/core/index.d.ts +1 -0
  81. package/dist/core/index.mjs +3 -1
  82. package/dist/core/resize-controller.d.ts +25 -0
  83. package/dist/core/resize-controller.mjs +144 -0
  84. package/dist/index.d.ts +7 -0
  85. package/dist/index.mjs +21 -0
  86. package/dist/utils/delete-thread-controller.d.ts +14 -0
  87. package/dist/utils/delete-thread-controller.mjs +80 -0
  88. package/dist/utils/index.d.ts +3 -0
  89. package/dist/utils/index.mjs +8 -0
  90. package/dist/utils/infinite-scroll-controller.d.ts +33 -0
  91. package/dist/utils/infinite-scroll-controller.mjs +95 -0
  92. package/package.json +14 -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,48 +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
- <slot name="header-actions" slot="header-actions"></slot>
349
- </forge-ai-chat-header>
350
- ${__privateGet(this, _AiChatbotComponent_instances, sessionFilesTemplate_get)} ${__privateGet(this, _AiChatbotComponent_instances, messageThread_get)} ${__privateGet(this, _AiChatbotComponent_instances, promptSlot_get)}
351
- ${when(this.disclaimerText, () => html`<div class="disclaimer" slot="disclaimer">${this.disclaimerText}</div>`)}
352
- </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>
353
486
  `;
354
487
  }
355
488
  };
356
489
  _chatInterfaceRef = /* @__PURE__ */ new WeakMap();
357
490
  _headerRef = /* @__PURE__ */ new WeakMap();
491
+ _conversationsPanelRef = /* @__PURE__ */ new WeakMap();
492
+ _conversationsDialogRef = /* @__PURE__ */ new WeakMap();
493
+ _boundEscapeHandler = /* @__PURE__ */ new WeakMap();
358
494
  _AiChatbotComponent_instances = /* @__PURE__ */ new WeakSet();
359
495
  handleHeaderExpand_fn = function() {
360
496
  this._dispatchHostEvent({ type: "forge-ai-chatbot-expand" });
@@ -368,13 +504,55 @@ handleHeaderClear_fn = function() {
368
504
  handleHeaderInfo_fn = function() {
369
505
  this._handleInfo();
370
506
  };
371
- sessionFilesTemplate_get = function() {
372
- const content = this._sessionFilesTemplate;
373
- if (content === nothing) {
374
- 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();
375
546
  }
376
- return html`<div class="session-files" slot="attachments">${content}</div>`;
547
+ this.hideConversations();
548
+ };
549
+ handlePanelClose_fn = function() {
550
+ this.hideConversations();
377
551
  };
552
+ _handleConversationSearch = /* @__PURE__ */ new WeakMap();
553
+ _handleConversationLoadMore = /* @__PURE__ */ new WeakMap();
554
+ _handleConversationRename = /* @__PURE__ */ new WeakMap();
555
+ _handleConversationDelete = /* @__PURE__ */ new WeakMap();
378
556
  promptSlot_get = function() {
379
557
  const isUploading = this._isUploading;
380
558
  return html`
@@ -384,13 +562,15 @@ promptSlot_get = function() {
384
562
  .placeholder=${this.placeholder}
385
563
  .running=${this._isStreaming || isUploading}
386
564
  .slashCommands=${this._slashCommands}
565
+ .contextItems=${this._allContextItems}
387
566
  ?disabled=${isUploading}
388
567
  ?debug-mode=${this.debugMode}
389
568
  @forge-ai-prompt-send=${this._handleSend}
390
569
  @forge-ai-prompt-stop=${this._handleStop}
391
570
  @forge-ai-prompt-cancel=${this._handleCancel}
392
571
  @forge-ai-prompt-debug-toggle=${this._handleDebugToggle}
393
- @forge-ai-prompt-command=${this._handleSlashCommand}>
572
+ @forge-ai-prompt-command=${this._handleSlashCommand}
573
+ @forge-ai-prompt-context-remove=${this._handlePromptContextRemove}>
394
574
  ${when(
395
575
  this.fileUpload === "on",
396
576
  () => html`
@@ -458,6 +638,24 @@ __decorateClass([
458
638
  __decorateClass([
459
639
  property({ attribute: "minimize-icon" })
460
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);
461
659
  AiChatbotComponent = __decorateClass([
462
660
  customElement(AiChatbotComponentTagName)
463
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 border-radius: inherit;\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;
@@ -37,6 +53,9 @@ export declare const AiChatbotLauncherComponentTagName: keyof HTMLElementTagName
37
53
  * @property {AgentInfo} agentInfo - Agent metadata for info dialog
38
54
  * @property {Agent[]} agents - List of available agents for selector
39
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
40
59
  *
41
60
  * @cssproperty --forge-ai-chatbot-launcher-icon-color - The fill color for the AI icon.
42
61
  *
@@ -49,14 +68,20 @@ export declare const AiChatbotLauncherComponentTagName: keyof HTMLElementTagName
49
68
  * @event {CustomEvent<ForgeAiChatbotResponseFeedbackEventData>} forge-ai-chatbot-response-feedback - Fired when user provides feedback on a response
50
69
  * @event {CustomEvent<void>} forge-ai-chatbot-info - Fired when header info option is selected
51
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()
52
73
  */
53
74
  export declare class AiChatbotLauncherComponent extends AiChatbotBase {
54
75
  #private;
55
76
  static styles: CSSResult;
56
77
  placeholder: string;
57
78
  descriptionText?: string;
79
+ threadName?: string;
80
+ showThreadRename: boolean;
81
+ showThreadDelete: boolean;
58
82
  private _viewState;
59
83
  private _skipAnimation;
84
+ private _editingThreadId;
60
85
  protected _messageThreadRef: Ref<AiMessageThreadComponent>;
61
86
  protected _promptRef: Ref<AiPromptComponent>;
62
87
  constructor();
@@ -66,6 +91,7 @@ export declare class AiChatbotLauncherComponent extends AiChatbotBase {
66
91
  protected _handleSend(evt: CustomEvent<ForgeAiPromptSendEventData>): Promise<void>;
67
92
  protected _handleSuggestionSelect(evt: CustomEvent<ForgeAiSuggestionsEventData>): Promise<void>;
68
93
  clearMessages(): boolean;
94
+ startNewChat(): void;
69
95
  setMessages(messages: ChatMessage[]): void;
70
96
  sendMessage(content: string, files?: File[]): Promise<void>;
71
97
  setThreadState(threadState: ThreadState, options?: {