@tylertech/forge-ai 0.15.3-dev.0 → 0.15.3-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/custom-elements.json +7733 -6803
  2. package/dist/ai-assistant-response/ai-assistant-response.d.ts +2 -2
  3. package/dist/ai-assistant-response/ai-assistant-response.mjs +4 -3
  4. package/dist/ai-canvas/ai-canvas.d.ts +43 -0
  5. package/dist/ai-canvas/ai-canvas.mjs +95 -0
  6. package/dist/ai-canvas/ai-canvas.scss.mjs +4 -0
  7. package/dist/ai-canvas/index.d.ts +1 -0
  8. package/dist/ai-canvas/index.mjs +5 -0
  9. package/dist/ai-chatbot/ag-ui-adapter.d.ts +2 -2
  10. package/dist/ai-chatbot/agent-adapter.d.ts +5 -5
  11. package/dist/ai-chatbot/agent-runner.d.ts +2 -2
  12. package/dist/ai-chatbot/ai-chatbot-base.d.ts +3 -2
  13. package/dist/ai-chatbot/ai-chatbot-base.mjs +11 -0
  14. package/dist/ai-chatbot/ai-chatbot-tool-call.d.ts +2 -2
  15. package/dist/ai-chatbot/ai-chatbot-tool-call.mjs +88 -10
  16. package/dist/ai-chatbot/ai-chatbot.d.ts +24 -1
  17. package/dist/ai-chatbot/ai-chatbot.mjs +102 -2
  18. package/dist/ai-chatbot/ai-chatbot.scss.mjs +1 -1
  19. package/dist/ai-chatbot/create-tool-renderer.d.ts +5 -5
  20. package/dist/ai-chatbot/index.d.ts +2 -1
  21. package/dist/ai-chatbot/index.mjs +3 -0
  22. package/dist/ai-chatbot/message-state-controller.d.ts +2 -2
  23. package/dist/ai-chatbot/message-state-controller.mjs +11 -11
  24. package/dist/ai-chatbot/tool-canvas.d.ts +60 -0
  25. package/dist/ai-chatbot/tool-canvas.mjs +128 -0
  26. package/dist/ai-chatbot/types.d.ts +128 -16
  27. package/dist/ai-chatbot/utils.d.ts +8 -3
  28. package/dist/ai-chatbot/utils.mjs +4 -0
  29. package/dist/ai-chatbot-launcher/ai-chatbot-launcher.d.ts +40 -2
  30. package/dist/ai-chatbot-launcher/ai-chatbot-launcher.mjs +224 -5
  31. package/dist/ai-chatbot-launcher/ai-chatbot-launcher.scss.mjs +1 -1
  32. package/dist/ai-embedded-chat/ai-embedded-chat.mjs +1 -0
  33. package/dist/ai-message-thread/ai-message-thread.d.ts +2 -2
  34. package/dist/ai-message-thread/ai-message-thread.mjs +3 -2
  35. package/dist/ai-tool-call-indicator/ai-tool-call-indicator.d.ts +2 -2
  36. package/dist/core/canvas-controller.d.ts +81 -0
  37. package/dist/core/canvas-controller.mjs +221 -0
  38. package/dist/core/chatbot-core-controller.d.ts +2 -2
  39. package/dist/core/chatbot-core-controller.mjs +44 -22
  40. package/dist/core/index.d.ts +2 -1
  41. package/dist/core/index.mjs +2 -0
  42. package/dist/core/resize-controller.d.ts +5 -0
  43. package/dist/core/resize-controller.mjs +7 -5
  44. package/dist/index.d.ts +1 -0
  45. package/dist/index.mjs +6 -0
  46. package/dist/tools/ai-data-table/ai-data-table-definition.mjs +1 -0
  47. package/dist/tools/ai-mcp-app/ai-mcp-app.d.ts +2 -1
  48. package/dist/tools/ai-mcp-app/ai-mcp-app.mjs +16 -1
  49. package/dist/tools/ai-mcp-app/ai-mcp-app.scss.mjs +1 -1
  50. package/dist/tools/ai-mcp-app/mcp-app-bridge-controller.d.ts +3 -4
  51. package/dist/tools/ai-mcp-app/mcp-app-bridge-controller.mjs +12 -21
  52. package/dist/tools/ai-mcp-app/mcp-app-bridge-types.d.ts +2 -1
  53. package/dist/tools/ai-steps/ai-steps-definition.mjs +1 -0
  54. package/package.json +1 -1
@@ -3,14 +3,17 @@ import { property, 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
+ import { CanvasController } from "../core/canvas-controller.mjs";
6
7
  import { forwardCancelableEvent } from "../utils.mjs";
7
8
  import "../ai-attachment/ai-attachment.mjs";
9
+ import "../ai-canvas/ai-canvas.mjs";
8
10
  import "../ai-chat-header/ai-chat-header.mjs";
9
11
  import "../ai-chat-interface/ai-chat-interface.mjs";
10
12
  import "../ai-context-chip/ai-context-chip.mjs";
11
13
  import "../ai-conversations-panel/ai-conversations-panel.mjs";
12
14
  import "../ai-file-picker/ai-file-picker.mjs";
13
15
  import "../ai-message-thread/ai-message-thread.mjs";
16
+ import "../ai-modal/ai-modal.mjs";
14
17
  import "../ai-prompt/ai-prompt.mjs";
15
18
  import "../ai-spinner/ai-spinner.mjs";
16
19
  import "../ai-suggestions/ai-suggestions.mjs";
@@ -33,7 +36,7 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot
33
36
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
34
37
  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);
35
38
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
36
- 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, handleThreadRetry_fn, handleNewChat_fn, handlePanelClose_fn, _handleThreadSearch, _handleThreadLoadMore, _handleThreadRename, _handleThreadDelete, promptSlot_get, messageThread_get;
39
+ var _canvasModalRef, _canvasRef, _canvas, _chatInterfaceRef, _headerRef, _conversationsPanelRef, _conversationsDialogRef, _boundEscapeHandler, _AiChatbotComponent_instances, handleHeaderExpand_fn, handleHeaderMinimize_fn, handleHeaderClear_fn, handleHeaderInfo_fn, syncCanvasModal_fn, handleCanvasModalClose_fn, canvasModal_get, handleCanvasCloseClick_fn, handleConversationsDialogClose_fn, handleEscapeKey_fn, handleBackdropClick_fn, handleConversationsToggle_fn, handleThreadSelect_fn, handleThreadRetry_fn, handleNewChat_fn, handlePanelClose_fn, _handleThreadSearch, _handleThreadLoadMore, _handleThreadRename, _handleThreadDelete, promptSlot_get, messageThread_get;
37
40
  const AiChatbotComponentTagName = "forge-ai-chatbot";
38
41
  let AiChatbotComponent = class extends AiChatbotBase {
39
42
  constructor() {
@@ -50,6 +53,18 @@ let AiChatbotComponent = class extends AiChatbotBase {
50
53
  this.showThreadDelete = false;
51
54
  this.selectedThreadId = null;
52
55
  this.threadsLoading = false;
56
+ __privateAdd(this, _canvasModalRef, createRef());
57
+ __privateAdd(this, _canvasRef, createRef());
58
+ __privateAdd(this, _canvas, new CanvasController(this, {
59
+ openEvent: "forge-ai-chatbot-canvas-open",
60
+ closeEvent: "forge-ai-chatbot-canvas-close",
61
+ dispatchHostEvent: (config) => this._dispatchHostEvent(config),
62
+ getToolCalls: () => this._toolCalls,
63
+ getTools: () => this._tools,
64
+ // A modal opened while the chat is hidden (closed floating chat, collapsed sidebar) is invisible but still makes the page inert.
65
+ canOpen: () => this.checkVisibility() && this.getBoundingClientRect().width > 0,
66
+ onRefocus: () => __privateGet(this, _canvasRef).value?.focus()
67
+ }));
53
68
  __privateAdd(this, _chatInterfaceRef, createRef());
54
69
  this._messageThreadRef = createRef();
55
70
  this._promptRef = createRef();
@@ -89,6 +104,42 @@ let AiChatbotComponent = class extends AiChatbotBase {
89
104
  focus() {
90
105
  this._promptRef.value?.focus();
91
106
  }
107
+ willUpdate(changedProperties) {
108
+ super.willUpdate(changedProperties);
109
+ __privateGet(this, _canvas).syncToolCall();
110
+ }
111
+ // No `canvas.open: 'auto'` here: a modal popping over the chat mid-conversation is too disruptive, so only the launcher auto-opens.
112
+ updated(changedProperties) {
113
+ super.updated(changedProperties);
114
+ __privateMethod(this, _AiChatbotComponent_instances, syncCanvasModal_fn).call(this);
115
+ }
116
+ get canvasOpen() {
117
+ return __privateGet(this, _canvas).isOpen;
118
+ }
119
+ /**
120
+ * Opens the artifact canvas in a modal over the chatbot, or swaps its content if already open.
121
+ * Returns false when the open event is prevented.
122
+ */
123
+ openCanvas(options = {}) {
124
+ return __privateGet(this, _canvas).open(options);
125
+ }
126
+ /**
127
+ * Closes the artifact canvas. Returns false if it was not open or the close event was prevented.
128
+ */
129
+ closeCanvas() {
130
+ return __privateGet(this, _canvas).close();
131
+ }
132
+ clearMessages() {
133
+ if (super.clearMessages()) {
134
+ __privateGet(this, _canvas).reset();
135
+ return true;
136
+ }
137
+ return false;
138
+ }
139
+ setMessages(messages) {
140
+ __privateGet(this, _canvas).reset();
141
+ super.setMessages(messages);
142
+ }
92
143
  showConversations() {
93
144
  const dialog = __privateGet(this, _conversationsDialogRef).value;
94
145
  if (dialog && !dialog.open) {
@@ -121,6 +172,7 @@ let AiChatbotComponent = class extends AiChatbotBase {
121
172
  startNewChat() {
122
173
  super.startNewChat();
123
174
  this.selectedThreadId = null;
175
+ __privateGet(this, _canvas).reset();
124
176
  }
125
177
  toggleConversations() {
126
178
  if (this.conversationsOpen) {
@@ -131,7 +183,10 @@ let AiChatbotComponent = class extends AiChatbotBase {
131
183
  }
132
184
  render() {
133
185
  return html`
134
- <div class="chatbot-container">
186
+ <div
187
+ class="chatbot-container"
188
+ @forge-ai-canvas-open-request=${__privateGet(this, _canvas).handleOpenRequest}
189
+ @forge-ai-canvas-close-request=${__privateGet(this, _canvas).handleCloseRequest}>
135
190
  <forge-ai-chat-interface
136
191
  ${ref(__privateGet(this, _chatInterfaceRef))}
137
192
  role="region"
@@ -205,10 +260,14 @@ let AiChatbotComponent = class extends AiChatbotBase {
205
260
  </dialog>
206
261
  `
207
262
  )}
263
+ ${__privateGet(this, _AiChatbotComponent_instances, canvasModal_get)}
208
264
  </div>
209
265
  `;
210
266
  }
211
267
  };
268
+ _canvasModalRef = /* @__PURE__ */ new WeakMap();
269
+ _canvasRef = /* @__PURE__ */ new WeakMap();
270
+ _canvas = /* @__PURE__ */ new WeakMap();
212
271
  _chatInterfaceRef = /* @__PURE__ */ new WeakMap();
213
272
  _headerRef = /* @__PURE__ */ new WeakMap();
214
273
  _conversationsPanelRef = /* @__PURE__ */ new WeakMap();
@@ -227,6 +286,44 @@ handleHeaderClear_fn = function() {
227
286
  handleHeaderInfo_fn = function() {
228
287
  this._handleInfo();
229
288
  };
289
+ syncCanvasModal_fn = function() {
290
+ const modal = __privateGet(this, _canvasModalRef).value;
291
+ if (modal && modal.open !== __privateGet(this, _canvas).isOpen) {
292
+ modal.open = __privateGet(this, _canvas).isOpen;
293
+ }
294
+ };
295
+ handleCanvasModalClose_fn = function(evt) {
296
+ evt.stopPropagation();
297
+ if (evt.detail.reason === "programmatic" || !__privateGet(this, _canvas).isOpen) {
298
+ return;
299
+ }
300
+ if (!__privateGet(this, _canvas).close()) {
301
+ __privateMethod(this, _AiChatbotComponent_instances, syncCanvasModal_fn).call(this);
302
+ }
303
+ };
304
+ canvasModal_get = function() {
305
+ const title = __privateGet(this, _canvas).content?.title ?? this.canvasTitle ?? "";
306
+ return html`
307
+ <forge-ai-modal
308
+ ${ref(__privateGet(this, _canvasModalRef))}
309
+ class="canvas-modal"
310
+ label=${title || "Canvas"}
311
+ @forge-ai-modal-close=${__privateMethod(this, _AiChatbotComponent_instances, handleCanvasModalClose_fn)}>
312
+ <forge-ai-canvas
313
+ ${ref(__privateGet(this, _canvasRef))}
314
+ class="canvas"
315
+ .titleText=${title}
316
+ .headingLevel=${this.headingLevel}
317
+ @forge-ai-canvas-close=${__privateMethod(this, _AiChatbotComponent_instances, handleCanvasCloseClick_fn)}>
318
+ <slot name="canvas-actions" slot="actions"></slot>
319
+ ${__privateGet(this, _canvas).content?.node ?? html`<slot name="canvas"></slot>`}
320
+ </forge-ai-canvas>
321
+ </forge-ai-modal>
322
+ `;
323
+ };
324
+ handleCanvasCloseClick_fn = function() {
325
+ __privateGet(this, _canvas).close();
326
+ };
230
327
  handleConversationsDialogClose_fn = function() {
231
328
  window.removeEventListener("keydown", __privateGet(this, _boundEscapeHandler), { capture: true });
232
329
  this.conversationsOpen = false;
@@ -393,6 +490,9 @@ __decorateClass([
393
490
  __decorateClass([
394
491
  property({ type: String, attribute: "threads-error" })
395
492
  ], AiChatbotComponent.prototype, "threadsError", 2);
493
+ __decorateClass([
494
+ property({ attribute: "canvas-title" })
495
+ ], AiChatbotComponent.prototype, "canvasTitle", 2);
396
496
  AiChatbotComponent = __decorateClass([
397
497
  customElement(AiChatbotComponentTagName)
398
498
  ], AiChatbotComponent);
@@ -1,4 +1,4 @@
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, 0);\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\nforge-ai-chat-header {\n --forge-ai-chat-header-title-color: var(--forge-ai-chatbot-header-title-color, currentColor);\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::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}';
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, 0);\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\nforge-ai-chat-header {\n --forge-ai-chat-header-title-color: var(--forge-ai-chatbot-header-title-color, currentColor);\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::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}\n\n.canvas-modal {\n --forge-ai-modal-width: var(--forge-ai-chatbot-canvas-width, 80vw);\n --forge-ai-modal-height: var(--forge-ai-chatbot-canvas-height, 80vh);\n}\n\n.canvas {\n --forge-ai-canvas-border-inline-start: none;\n flex: 1;\n min-inline-size: 0;\n}';
2
2
  export {
3
3
  styles as default
4
4
  };
@@ -1,9 +1,9 @@
1
- import { ToolCall, ToolRenderer } from './types.js';
1
+ import { ToolRenderFunction, ToolRenderer } from './types.js';
2
2
  export interface CreateToolRendererElementConfig {
3
3
  elementTag: keyof HTMLElementTagNameMap;
4
4
  }
5
- export interface CreateToolRendererFunctionConfig {
6
- render: (toolCall: ToolCall) => HTMLElement | DocumentFragment;
5
+ export interface CreateToolRendererFunctionConfig<TArgs = Record<string, unknown>, TResult = unknown> {
6
+ render: ToolRenderFunction<TArgs, TResult>;
7
7
  }
8
- export type CreateToolRendererConfig = CreateToolRendererElementConfig | CreateToolRendererFunctionConfig;
9
- export declare function createToolRenderer(config: CreateToolRendererConfig): ToolRenderer;
8
+ export type CreateToolRendererConfig<TArgs = Record<string, unknown>, TResult = unknown> = CreateToolRendererElementConfig | CreateToolRendererFunctionConfig<TArgs, TResult>;
9
+ export declare function createToolRenderer<TArgs = Record<string, unknown>, TResult = unknown>(config: CreateToolRendererConfig<TArgs, TResult>): ToolRenderer<TArgs, TResult>;
@@ -4,12 +4,13 @@ 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, type McpUiResourceEvent, type McpToolCallParams, type McpResourceReadParams, type McpAppResourceResolveParams, type McpModelContextUpdateParams, type ToolResultEvent } from './agent-adapter.js';
7
- export type { Agent, ChatMessage, ClientMessageAction, ClientMessageInput, ClientMessageKind, ContextItem, ToolDefinition, ToolCall, ToolCallStatus, ToolRenderer, IToolRenderer, HandlerContext, ToolStartContext, ToolDeltaContext, ToolEndContext, FileAttachment, UploadedFileMetadata, FileUploadCallbacks, FileUploadHandler, FileRemoveCallbacks, ThreadState, FeedbackType, ResponseFeedback, MessageItem, ForgeAiChatbotContextRemoveEventData, ForgeAiChatbotThreadSelectEventData, ForgeAiChatbotThreadSearchEventData, ForgeAiChatbotThreadLoadMoreEventData, ForgeAiChatbotThreadRenameEventData, ForgeAiChatbotThreadDeleteEventData, McpAppUiResource, McpAppResourceCsp, McpAppResourcePermissions, McpAppHostContext, McpAppHostStyles, McpAppHostCapabilities, McpAppContainerDimensions, McpAppContentModalities, McpAppToolInfo, McpAppSandboxCapabilities, McpAppDisplayMode, McpToolResult } from './types.js';
7
+ export type { Agent, ChatMessage, ClientMessageAction, ClientMessageInput, ClientMessageKind, ContextItem, ToolDefinition, AnyToolDefinition, ToolCall, ToolCallStatus, ToolRenderer, ToolPresentation, ToolCanvas, ToolRenderContext, ToolRenderFunction, ToolCanvasConfig, ToolCanvasInline, ToolCanvasIcon, ToolCanvasActionLabel, ToolCallMapper, ToolCallValue, IToolRenderer, HandlerContext, ToolStartContext, ToolDeltaContext, ToolEndContext, FileAttachment, UploadedFileMetadata, FileUploadCallbacks, FileUploadHandler, FileRemoveCallbacks, ThreadState, FeedbackType, ResponseFeedback, MessageItem, ForgeAiChatbotContextRemoveEventData, ForgeAiChatbotThreadSelectEventData, ForgeAiChatbotThreadSearchEventData, ForgeAiChatbotThreadLoadMoreEventData, ForgeAiChatbotThreadRenameEventData, ForgeAiChatbotThreadDeleteEventData, McpAppUiResource, McpAppUiResourceStatus, McpAppResourceCsp, McpAppResourcePermissions, McpAppHostContext, McpAppHostStyles, McpAppHostCapabilities, McpAppContainerDimensions, McpAppContentModalities, McpAppToolInfo, McpAppSandboxCapabilities, McpAppDisplayMode, McpToolResult } 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';
11
11
  export * from './agent-runner.js';
12
12
  export * from './create-tool-renderer.js';
13
+ export { requestCanvasOpen, requestCanvasClose, type ForgeAiCanvasOpenRequestEventData, type ForgeAiCanvasCloseRequestEventData } from './tool-canvas.js';
13
14
  export { MessageStateController, type MessageStateControllerConfig } from './message-state-controller.js';
14
15
  export { FileUploadManager, type FileUploadManagerConfig } from './file-upload-manager.js';
15
16
  export { MarkdownStreamController } from './markdown-stream-controller.js';
@@ -7,6 +7,7 @@ import { HttpAgentWithCredentials } from "./http-agent-with-credentials.mjs";
7
7
  import { EventEmitter, SubscriptionManager } from "./event-emitter.mjs";
8
8
  import { AgentRunner } from "./agent-runner.mjs";
9
9
  import { createToolRenderer } from "./create-tool-renderer.mjs";
10
+ import { requestCanvasClose, requestCanvasOpen } from "./tool-canvas.mjs";
10
11
  import { MessageStateController } from "./message-state-controller.mjs";
11
12
  import { FileUploadManager } from "./file-upload-manager.mjs";
12
13
  import { MarkdownStreamController } from "./markdown-stream-controller.mjs";
@@ -32,6 +33,8 @@ export {
32
33
  generateId,
33
34
  renderInlineMarkdown,
34
35
  renderMarkdown,
36
+ requestCanvasClose,
37
+ requestCanvasOpen,
35
38
  toRequestMessages,
36
39
  toRequestToolCall
37
40
  };
@@ -63,8 +63,8 @@ export declare class MessageStateController implements ReactiveController {
63
63
  /**
64
64
  * Reconstructs the message hierarchy for API compatibility.
65
65
  * Converts assistant responses back to ChatMessage format with tool calls.
66
- * MCP-app `uiResource`s are stripped: they are re-resolved via the adapter on restore,
67
- * never persisted or sent back to the agent.
66
+ * MCP-app `uiResource`/`uiResourceStatus` are stripped: resources are re-resolved via the
67
+ * adapter on restore, never persisted or sent back to the agent.
68
68
  */
69
69
  getMessages(): ChatMessage[];
70
70
  setMessages(messages: ChatMessage[]): void;
@@ -1,13 +1,13 @@
1
1
  import { generateId } from "./utils.mjs";
2
- function withoutUiResource(toolCall) {
3
- if (!toolCall.uiResource) {
2
+ function withoutMcpAppResource(toolCall) {
3
+ if (!toolCall.uiResource && !toolCall.uiResourceStatus) {
4
4
  return toolCall;
5
5
  }
6
- const { uiResource: _uiResource, ...rest } = toolCall;
6
+ const { uiResource: _uiResource, uiResourceStatus: _uiResourceStatus, ...rest } = toolCall;
7
7
  return rest;
8
8
  }
9
- function responseItemWithoutUiResource(item) {
10
- return item.type === "toolCall" ? { type: "toolCall", data: withoutUiResource(item.data) } : item;
9
+ function responseItemWithoutMcpAppResource(item) {
10
+ return item.type === "toolCall" ? { type: "toolCall", data: withoutMcpAppResource(item.data) } : item;
11
11
  }
12
12
  class MessageStateController {
13
13
  constructor(_host, _config) {
@@ -304,8 +304,8 @@ class MessageStateController {
304
304
  /**
305
305
  * Reconstructs the message hierarchy for API compatibility.
306
306
  * Converts assistant responses back to ChatMessage format with tool calls.
307
- * MCP-app `uiResource`s are stripped: they are re-resolved via the adapter on restore,
308
- * never persisted or sent back to the agent.
307
+ * MCP-app `uiResource`/`uiResourceStatus` are stripped: resources are re-resolved via the
308
+ * adapter on restore, never persisted or sent back to the agent.
309
309
  */
310
310
  getMessages() {
311
311
  const messages = [];
@@ -314,7 +314,7 @@ class MessageStateController {
314
314
  messages.push({ ...item.data, toolCalls: [] });
315
315
  } else if (item.type === "assistant") {
316
316
  const response = item.data;
317
- const children = response.children.map(responseItemWithoutUiResource);
317
+ const children = response.children.map(responseItemWithoutMcpAppResource);
318
318
  const textContent = children.filter((c) => c.type === "text").map((c) => c.content).join("");
319
319
  const toolCalls = children.filter((c) => c.type === "toolCall").map((c) => c.data);
320
320
  const message = {
@@ -331,7 +331,7 @@ class MessageStateController {
331
331
  } else if (item.type === "toolCall") {
332
332
  const lastMsg = messages[messages.length - 1];
333
333
  if (lastMsg && lastMsg.role === "assistant") {
334
- lastMsg.toolCalls = [...lastMsg.toolCalls || [], withoutUiResource(item.data)];
334
+ lastMsg.toolCalls = [...lastMsg.toolCalls || [], withoutMcpAppResource(item.data)];
335
335
  }
336
336
  }
337
337
  }
@@ -346,7 +346,7 @@ class MessageStateController {
346
346
  let children;
347
347
  if (msg.children?.length) {
348
348
  children = msg.children.map((child) => {
349
- const restored = responseItemWithoutUiResource(child);
349
+ const restored = responseItemWithoutMcpAppResource(child);
350
350
  if (restored.type === "toolCall") {
351
351
  this._toolCalls.set(restored.data.id, restored.data);
352
352
  }
@@ -358,7 +358,7 @@ class MessageStateController {
358
358
  children.push({ type: "text", messageId: msg.id, content: msg.content, status: "complete" });
359
359
  }
360
360
  if (msg.toolCalls) {
361
- for (const toolCall of msg.toolCalls.map(withoutUiResource)) {
361
+ for (const toolCall of msg.toolCalls.map(withoutMcpAppResource)) {
362
362
  children.push({ type: "toolCall", data: toolCall });
363
363
  this._toolCalls.set(toolCall.id, toolCall);
364
364
  }
@@ -0,0 +1,60 @@
1
+ import { ToolCall, ToolCanvas, ToolCanvasInline, AnyToolDefinition, ToolPresentation } from './types.js';
2
+ export interface ForgeAiCanvasOpenRequestEventData {
3
+ toolCallId: string;
4
+ toolName: string;
5
+ title?: string;
6
+ /** Set to true by the host once the tool call is showing in the canvas. */
7
+ handled?: boolean;
8
+ }
9
+ export interface ForgeAiCanvasCloseRequestEventData {
10
+ toolCallId: string;
11
+ /** Set to true by the host once the canvas has closed. */
12
+ handled?: boolean;
13
+ }
14
+ declare global {
15
+ interface HTMLElementEventMap {
16
+ 'forge-ai-canvas-open-request': CustomEvent<ForgeAiCanvasOpenRequestEventData>;
17
+ 'forge-ai-canvas-close-request': CustomEvent<ForgeAiCanvasCloseRequestEventData>;
18
+ }
19
+ }
20
+ /** State a canvas host shares with the tool calls rendered in its thread. */
21
+ export interface ToolCanvasHostState {
22
+ /** Presentation assigned to inline renderers of canvas-enabled tools. */
23
+ presentation: ToolPresentation;
24
+ /** Tool call currently shown in the canvas, if any. */
25
+ openToolCallId?: string;
26
+ }
27
+ /**
28
+ * Provided by hosts that render tool calls next to a canvas panel. Without a provider, inline
29
+ * renderers get `inline`.
30
+ */
31
+ export declare const toolCanvasHostContext: {
32
+ __context__: ToolCanvasHostState;
33
+ };
34
+ /**
35
+ * Asks the nearest canvas host to show the given tool call. Hosts without a canvas leave the event
36
+ * unhandled. Returns whether the tool call is now showing.
37
+ */
38
+ export declare function requestCanvasOpen(target: EventTarget, detail: ForgeAiCanvasOpenRequestEventData): boolean;
39
+ /** Asks the nearest canvas host to close the canvas if it is showing the given tool call. Returns whether it closed. */
40
+ export declare function requestCanvasClose(target: EventTarget, detail: ForgeAiCanvasCloseRequestEventData): boolean;
41
+ export interface CreateToolCanvasConfig {
42
+ available: boolean;
43
+ /** Read live by `toggle()`; `isOpen` on the result is a snapshot taken when the controls are built. */
44
+ isOpen: () => boolean;
45
+ open: (options?: {
46
+ title?: string;
47
+ }) => boolean;
48
+ close: () => boolean;
49
+ }
50
+ /** Builds the `canvas` controls a host injects into a tool renderer. */
51
+ export declare function createToolCanvas({ available, isOpen, open, close }: CreateToolCanvasConfig): ToolCanvas;
52
+ export declare function resolveToolCanvasTitle(toolCall: ToolCall, toolDefinition: AnyToolDefinition): string;
53
+ export declare function resolveToolCanvasSubtitle(toolCall: ToolCall, toolDefinition: AnyToolDefinition): string | undefined;
54
+ export declare function resolveToolCanvasActionLabel(toolCall: ToolCall, toolDefinition: AnyToolDefinition, active: boolean): string;
55
+ /**
56
+ * Resolves the artifact card icon to a fresh `<svg>` element, or undefined for the card's default glyph.
57
+ * Markup strings are parsed and reduced to an allowlist of shape elements and presentation attributes.
58
+ */
59
+ export declare function resolveToolCanvasIcon(toolCall: ToolCall, toolDefinition: AnyToolDefinition): SVGElement | undefined;
60
+ export declare function resolveToolCanvasInline(toolDefinition: AnyToolDefinition): ToolCanvasInline;
@@ -0,0 +1,128 @@
1
+ import { createContext } from "@lit/context";
2
+ const toolCanvasHostContext = createContext(/* @__PURE__ */ Symbol("forge-ai-tool-canvas-host"));
3
+ function requestCanvasOpen(target, detail) {
4
+ const request = { ...detail, handled: false };
5
+ target.dispatchEvent(
6
+ new CustomEvent("forge-ai-canvas-open-request", {
7
+ detail: request,
8
+ bubbles: true,
9
+ composed: true
10
+ })
11
+ );
12
+ return request.handled;
13
+ }
14
+ function requestCanvasClose(target, detail) {
15
+ const request = { ...detail, handled: false };
16
+ target.dispatchEvent(
17
+ new CustomEvent("forge-ai-canvas-close-request", {
18
+ detail: request,
19
+ bubbles: true,
20
+ composed: true
21
+ })
22
+ );
23
+ return request.handled;
24
+ }
25
+ function createToolCanvas({ available, isOpen, open, close }) {
26
+ return {
27
+ available,
28
+ isOpen: isOpen(),
29
+ open: (options) => available && open(options),
30
+ close: () => available && close(),
31
+ toggle: () => available && (isOpen() ? close() : open())
32
+ };
33
+ }
34
+ const DEFAULT_ACTION_LABEL = { open: "Open in canvas", collapse: "Collapse canvas" };
35
+ function resolveToolCallValue(value, toolCall) {
36
+ if (typeof value === "function") {
37
+ return value(toolCall);
38
+ }
39
+ return value;
40
+ }
41
+ function resolveToolCanvasTitle(toolCall, toolDefinition) {
42
+ return resolveToolCallValue(toolDefinition.canvas?.title, toolCall) ?? toolDefinition.displayName ?? toolDefinition.name;
43
+ }
44
+ function resolveToolCanvasSubtitle(toolCall, toolDefinition) {
45
+ return resolveToolCallValue(toolDefinition.canvas?.subtitle, toolCall);
46
+ }
47
+ function resolveToolCanvasActionLabel(toolCall, toolDefinition, active) {
48
+ const labels = resolveToolCallValue(toolDefinition.canvas?.actionLabel, toolCall) ?? DEFAULT_ACTION_LABEL;
49
+ return active ? labels.collapse : labels.open;
50
+ }
51
+ function resolveToolCanvasIcon(toolCall, toolDefinition) {
52
+ const icon = resolveToolCallValue(toolDefinition.canvas?.icon, toolCall);
53
+ if (!icon) {
54
+ return void 0;
55
+ }
56
+ if (typeof icon !== "string") {
57
+ return icon.cloneNode(true);
58
+ }
59
+ const template = document.createElement("template");
60
+ template.innerHTML = icon;
61
+ const svg = template.content.querySelector("svg");
62
+ if (!svg) {
63
+ return void 0;
64
+ }
65
+ sanitizeSvg(svg);
66
+ return svg;
67
+ }
68
+ const SVG_ICON_ELEMENTS = /* @__PURE__ */ new Set(["svg", "g", "path", "circle", "ellipse", "rect", "line", "polyline", "polygon"]);
69
+ const SVG_ICON_ATTRIBUTES = /* @__PURE__ */ new Set([
70
+ "xmlns",
71
+ "viewBox",
72
+ "width",
73
+ "height",
74
+ "d",
75
+ "fill",
76
+ "fill-rule",
77
+ "clip-rule",
78
+ "stroke",
79
+ "stroke-width",
80
+ "stroke-linecap",
81
+ "stroke-linejoin",
82
+ "opacity",
83
+ "transform",
84
+ "cx",
85
+ "cy",
86
+ "r",
87
+ "rx",
88
+ "ry",
89
+ "x",
90
+ "y",
91
+ "x1",
92
+ "y1",
93
+ "x2",
94
+ "y2",
95
+ "points",
96
+ "aria-hidden"
97
+ ]);
98
+ function sanitizeSvg(svg) {
99
+ for (const element of [svg, ...svg.querySelectorAll("*")]) {
100
+ if (!SVG_ICON_ELEMENTS.has(element.localName)) {
101
+ element.remove();
102
+ continue;
103
+ }
104
+ for (const attribute of [...element.attributes]) {
105
+ if (!SVG_ICON_ATTRIBUTES.has(attribute.name)) {
106
+ element.removeAttribute(attribute.name);
107
+ }
108
+ }
109
+ }
110
+ }
111
+ function resolveToolCanvasInline(toolDefinition) {
112
+ const canvas = toolDefinition.canvas;
113
+ if (canvas?.inline) {
114
+ return canvas.inline;
115
+ }
116
+ return canvas?.open === "auto" ? "card" : "renderer";
117
+ }
118
+ export {
119
+ createToolCanvas,
120
+ requestCanvasClose,
121
+ requestCanvasOpen,
122
+ resolveToolCanvasActionLabel,
123
+ resolveToolCanvasIcon,
124
+ resolveToolCanvasInline,
125
+ resolveToolCanvasSubtitle,
126
+ resolveToolCanvasTitle,
127
+ toolCanvasHostContext
128
+ };