@tylertech/forge-ai 0.15.2 → 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 (88) hide show
  1. package/custom-elements.json +4501 -1781
  2. package/dist/ai-artifact-card/ai-artifact-card.d.ts +75 -0
  3. package/dist/ai-artifact-card/ai-artifact-card.mjs +142 -0
  4. package/dist/ai-artifact-card/ai-artifact-card.scss.mjs +283 -0
  5. package/dist/ai-artifact-card/index.d.ts +1 -0
  6. package/dist/ai-artifact-card/index.mjs +5 -0
  7. package/dist/ai-artifact-card-group/ai-artifact-card-group.d.ts +57 -0
  8. package/dist/ai-artifact-card-group/ai-artifact-card-group.mjs +137 -0
  9. package/dist/ai-artifact-card-group/ai-artifact-card-group.scss.mjs +173 -0
  10. package/dist/ai-artifact-card-group/index.d.ts +1 -0
  11. package/dist/ai-artifact-card-group/index.mjs +5 -0
  12. package/dist/ai-assistant-response/ai-assistant-response.d.ts +2 -2
  13. package/dist/ai-assistant-response/ai-assistant-response.mjs +26 -2
  14. package/dist/ai-canvas/ai-canvas.d.ts +43 -0
  15. package/dist/ai-canvas/ai-canvas.mjs +95 -0
  16. package/dist/ai-canvas/ai-canvas.scss.mjs +4 -0
  17. package/dist/ai-canvas/index.d.ts +1 -0
  18. package/dist/ai-canvas/index.mjs +5 -0
  19. package/dist/ai-chatbot/ag-ui-adapter.d.ts +2 -2
  20. package/dist/ai-chatbot/ag-ui-adapter.mjs +1 -1
  21. package/dist/ai-chatbot/agent-adapter.d.ts +111 -4
  22. package/dist/ai-chatbot/agent-adapter.mjs +22 -0
  23. package/dist/ai-chatbot/agent-runner.d.ts +2 -2
  24. package/dist/ai-chatbot/ai-chatbot-base.d.ts +29 -2
  25. package/dist/ai-chatbot/ai-chatbot-base.mjs +147 -3
  26. package/dist/ai-chatbot/ai-chatbot-tool-call.d.ts +2 -2
  27. package/dist/ai-chatbot/ai-chatbot-tool-call.mjs +88 -10
  28. package/dist/ai-chatbot/ai-chatbot.d.ts +24 -1
  29. package/dist/ai-chatbot/ai-chatbot.mjs +102 -2
  30. package/dist/ai-chatbot/ai-chatbot.scss.mjs +1 -1
  31. package/dist/ai-chatbot/create-tool-renderer.d.ts +5 -5
  32. package/dist/ai-chatbot/index.d.ts +3 -2
  33. package/dist/ai-chatbot/index.mjs +3 -0
  34. package/dist/ai-chatbot/message-state-controller.d.ts +10 -1
  35. package/dist/ai-chatbot/message-state-controller.mjs +78 -20
  36. package/dist/ai-chatbot/tool-canvas.d.ts +60 -0
  37. package/dist/ai-chatbot/tool-canvas.mjs +128 -0
  38. package/dist/ai-chatbot/types.d.ts +325 -15
  39. package/dist/ai-chatbot/utils.d.ts +8 -3
  40. package/dist/ai-chatbot/utils.mjs +7 -1
  41. package/dist/ai-chatbot-launcher/ai-chatbot-launcher.d.ts +40 -2
  42. package/dist/ai-chatbot-launcher/ai-chatbot-launcher.mjs +224 -7
  43. package/dist/ai-chatbot-launcher/ai-chatbot-launcher.scss.mjs +1 -1
  44. package/dist/ai-embedded-chat/ai-embedded-chat.mjs +1 -0
  45. package/dist/ai-message-thread/ai-message-thread.d.ts +3 -2
  46. package/dist/ai-message-thread/ai-message-thread.mjs +36 -3
  47. package/dist/ai-steps/ai-steps.d.ts +67 -0
  48. package/dist/ai-steps/ai-steps.mjs +163 -0
  49. package/dist/ai-steps/ai-steps.scss.mjs +4 -0
  50. package/dist/ai-steps/index.d.ts +1 -0
  51. package/dist/ai-steps/index.mjs +5 -0
  52. package/dist/ai-tool-call-indicator/ai-tool-call-indicator.d.ts +2 -2
  53. package/dist/ai-tool-call-indicator/ai-tool-call-indicator.mjs +1 -1
  54. package/dist/core/canvas-controller.d.ts +81 -0
  55. package/dist/core/canvas-controller.mjs +221 -0
  56. package/dist/core/chatbot-core-controller.d.ts +4 -2
  57. package/dist/core/chatbot-core-controller.mjs +121 -4
  58. package/dist/core/index.d.ts +2 -1
  59. package/dist/core/index.mjs +2 -0
  60. package/dist/core/resize-controller.d.ts +5 -0
  61. package/dist/core/resize-controller.mjs +7 -5
  62. package/dist/index.d.ts +4 -0
  63. package/dist/index.mjs +15 -0
  64. package/dist/tools/ai-data-table/ai-data-table-definition.mjs +1 -0
  65. package/dist/tools/ai-mcp-app/ai-mcp-app.d.ts +70 -0
  66. package/dist/tools/ai-mcp-app/ai-mcp-app.mjs +589 -0
  67. package/dist/tools/ai-mcp-app/ai-mcp-app.scss.mjs +4 -0
  68. package/dist/tools/ai-mcp-app/index.d.ts +3 -0
  69. package/dist/tools/ai-mcp-app/index.mjs +6 -0
  70. package/dist/tools/ai-mcp-app/mcp-app-bridge-controller.d.ts +60 -0
  71. package/dist/tools/ai-mcp-app/mcp-app-bridge-controller.mjs +147 -0
  72. package/dist/tools/ai-mcp-app/mcp-app-bridge-types.d.ts +124 -0
  73. package/dist/tools/ai-mcp-app/mcp-app-bridge.d.ts +41 -0
  74. package/dist/tools/ai-mcp-app/mcp-app-bridge.mjs +293 -0
  75. package/dist/tools/ai-mcp-app/mcp-app-context.d.ts +46 -0
  76. package/dist/tools/ai-mcp-app/mcp-app-context.mjs +5 -0
  77. package/dist/tools/ai-steps/ai-steps-definition.d.ts +2 -0
  78. package/dist/tools/ai-steps/ai-steps-definition.mjs +51 -0
  79. package/dist/tools/ai-steps/ai-steps.d.ts +28 -0
  80. package/dist/tools/ai-steps/ai-steps.mjs +49 -0
  81. package/dist/tools/ai-steps/ai-steps.scss.mjs +4 -0
  82. package/dist/tools/ai-steps/index.d.ts +2 -0
  83. package/dist/tools/ai-steps/index.mjs +6 -0
  84. package/dist/tools/index.d.ts +1 -0
  85. package/dist/tools/index.mjs +5 -1
  86. package/dist/utils/inert-outside.d.ts +7 -0
  87. package/dist/utils/inert-outside.mjs +28 -0
  88. package/package.json +4 -1
@@ -1,5 +1,5 @@
1
1
  import { LitElement, TemplateResult, PropertyValues, CSSResult } from 'lit';
2
- import { MessageItem, ToolDefinition } from '../ai-chatbot/types.js';
2
+ import { MessageItem, AnyToolDefinition } from '../ai-chatbot/types.js';
3
3
  import { FeatureToggle } from '../ai-chatbot/ai-chatbot.js';
4
4
  declare global {
5
5
  interface HTMLElementTagNameMap {
@@ -55,12 +55,13 @@ export declare class AiMessageThreadComponent extends LitElement {
55
55
  #private;
56
56
  static styles: CSSResult;
57
57
  messageItems: MessageItem[];
58
- tools?: Map<string, ToolDefinition>;
58
+ tools?: Map<string, AnyToolDefinition>;
59
59
  enableReactions: boolean;
60
60
  showThinking: boolean;
61
61
  debugMode: boolean;
62
62
  autoScroll: FeatureToggle;
63
63
  private _messageThreadContainer;
64
+ private _messageThreadContent;
64
65
  connectedCallback(): void;
65
66
  disconnectedCallback(): void;
66
67
  firstUpdated(): void;
@@ -2,7 +2,9 @@ import { unsafeCSS, LitElement, html, nothing } from "lit";
2
2
  import { property, query, customElement } from "lit/decorators.js";
3
3
  import { unsafeHTML } from "lit/directives/unsafe-html.js";
4
4
  import { when } from "lit/directives/when.js";
5
+ import { keyed } from "lit/directives/keyed.js";
5
6
  import { MarkdownStreamController } from "../ai-chatbot/markdown-stream-controller.mjs";
7
+ import { rendersAsMcpAppWidget } from "../ai-chatbot/utils.mjs";
6
8
  import "../ai-assistant-response/ai-assistant-response.mjs";
7
9
  import "../ai-client-message/ai-client-message.mjs";
8
10
  import "../ai-empty-state/ai-empty-state.mjs";
@@ -12,6 +14,7 @@ import "../ai-thinking-indicator/ai-thinking-indicator.mjs";
12
14
  import "../ai-user-message/ai-user-message.mjs";
13
15
  import "../ai-chatbot/ai-chatbot-tool-call.mjs";
14
16
  import "../core/tooltip/tooltip.mjs";
17
+ import "../tools/ai-mcp-app/ai-mcp-app.mjs";
15
18
  import styles from "./ai-message-thread.scss.mjs";
16
19
  var __defProp = Object.defineProperty;
17
20
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -31,7 +34,7 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
31
34
  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
35
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
33
36
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
34
- var _markdownController, _canAutoScroll, _resizeObserver, _AiMessageThreadComponent_instances, scheduleScroll_fn, checkScrollState_fn, _handleScroll, _handleScrollToBottomClick, scrollToBottomButton_get, handleCopy_fn, handleResend_fn, handleThumbsUp_fn, handleThumbsDown_fn, handleUserCopy_fn, handleUserResend_fn, handleUserEdit_fn, renderToolCall_fn, activeResponse_get, renderAssistantResponse_fn, emptyState_get, thinkingIndicator_get, messages_get, dispatchEvent_fn;
37
+ var _markdownController, _canAutoScroll, _lastScrollTop, _resizeObserver, _contentResizeObserver, _AiMessageThreadComponent_instances, observe_fn, handleContentResize_fn, scheduleScroll_fn, checkScrollState_fn, _handleScroll, _handleScrollToBottomClick, scrollToBottomButton_get, handleCopy_fn, handleResend_fn, handleThumbsUp_fn, handleThumbsDown_fn, handleUserCopy_fn, handleUserResend_fn, handleUserEdit_fn, renderToolCall_fn, activeResponse_get, renderAssistantResponse_fn, emptyState_get, thinkingIndicator_get, messages_get, dispatchEvent_fn;
35
38
  const AiMessageThreadComponentTagName = "forge-ai-message-thread";
36
39
  const SCROLL_THRESHOLD = 100;
37
40
  let AiMessageThreadComponent = class extends LitElement {
@@ -45,7 +48,9 @@ let AiMessageThreadComponent = class extends LitElement {
45
48
  this.autoScroll = "on";
46
49
  __privateAdd(this, _markdownController);
47
50
  __privateAdd(this, _canAutoScroll, true);
51
+ __privateAdd(this, _lastScrollTop, 0);
48
52
  __privateAdd(this, _resizeObserver);
53
+ __privateAdd(this, _contentResizeObserver);
49
54
  __privateAdd(this, _handleScroll, () => {
50
55
  __privateMethod(this, _AiMessageThreadComponent_instances, checkScrollState_fn).call(this);
51
56
  });
@@ -57,13 +62,18 @@ let AiMessageThreadComponent = class extends LitElement {
57
62
  super.connectedCallback();
58
63
  __privateSet(this, _markdownController, new MarkdownStreamController(this));
59
64
  __privateSet(this, _resizeObserver, new ResizeObserver(() => __privateMethod(this, _AiMessageThreadComponent_instances, checkScrollState_fn).call(this)));
65
+ __privateSet(this, _contentResizeObserver, new ResizeObserver(() => __privateMethod(this, _AiMessageThreadComponent_instances, handleContentResize_fn).call(this)));
66
+ if (this.hasUpdated) {
67
+ __privateMethod(this, _AiMessageThreadComponent_instances, observe_fn).call(this);
68
+ }
60
69
  }
61
70
  disconnectedCallback() {
62
71
  super.disconnectedCallback();
63
72
  __privateGet(this, _resizeObserver)?.disconnect();
73
+ __privateGet(this, _contentResizeObserver)?.disconnect();
64
74
  }
65
75
  firstUpdated() {
66
- __privateGet(this, _resizeObserver)?.observe(this._messageThreadContainer);
76
+ __privateMethod(this, _AiMessageThreadComponent_instances, observe_fn).call(this);
67
77
  }
68
78
  updated(changedProperties) {
69
79
  super.updated(changedProperties);
@@ -95,8 +105,19 @@ let AiMessageThreadComponent = class extends LitElement {
95
105
  };
96
106
  _markdownController = /* @__PURE__ */ new WeakMap();
97
107
  _canAutoScroll = /* @__PURE__ */ new WeakMap();
108
+ _lastScrollTop = /* @__PURE__ */ new WeakMap();
98
109
  _resizeObserver = /* @__PURE__ */ new WeakMap();
110
+ _contentResizeObserver = /* @__PURE__ */ new WeakMap();
99
111
  _AiMessageThreadComponent_instances = /* @__PURE__ */ new WeakSet();
112
+ observe_fn = function() {
113
+ __privateGet(this, _resizeObserver)?.observe(this._messageThreadContainer);
114
+ __privateGet(this, _contentResizeObserver)?.observe(this._messageThreadContent);
115
+ };
116
+ handleContentResize_fn = function() {
117
+ if (this.autoScroll === "on") {
118
+ this.scrollToBottom({ behavior: "instant" });
119
+ }
120
+ };
100
121
  scheduleScroll_fn = async function() {
101
122
  await this.updateComplete;
102
123
  await new Promise(requestAnimationFrame);
@@ -108,7 +129,10 @@ checkScrollState_fn = function() {
108
129
  return;
109
130
  }
110
131
  const { scrollTop, scrollHeight, clientHeight } = container;
111
- const canAutoScroll = scrollTop + clientHeight >= scrollHeight - SCROLL_THRESHOLD;
132
+ const isNearBottom = scrollTop + clientHeight >= scrollHeight - SCROLL_THRESHOLD;
133
+ const scrolledUp = scrollTop < __privateGet(this, _lastScrollTop);
134
+ __privateSet(this, _lastScrollTop, scrollTop);
135
+ const canAutoScroll = isNearBottom || __privateGet(this, _canAutoScroll) && !scrolledUp;
112
136
  if (canAutoScroll !== __privateGet(this, _canAutoScroll)) {
113
137
  __privateSet(this, _canAutoScroll, canAutoScroll);
114
138
  this.requestUpdate();
@@ -173,6 +197,9 @@ handleUserEdit_fn = function(messageId, content) {
173
197
  });
174
198
  };
175
199
  renderToolCall_fn = function(toolCall) {
200
+ if (rendersAsMcpAppWidget(toolCall)) {
201
+ return keyed(toolCall.id, html`<forge-ai-mcp-app .toolCall=${toolCall}></forge-ai-mcp-app>`);
202
+ }
176
203
  const toolDefinition = this.tools?.get(toolCall.name);
177
204
  return html`<forge-ai-chatbot-tool-call
178
205
  .toolCall=${toolCall}
@@ -231,6 +258,9 @@ messages_get = function() {
231
258
  return true;
232
259
  }
233
260
  if (item.type === "toolCall") {
261
+ if (rendersAsMcpAppWidget(item.data)) {
262
+ return true;
263
+ }
234
264
  const toolDef = this.tools?.get(item.data.name);
235
265
  return !!toolDef?.renderer;
236
266
  }
@@ -318,6 +348,9 @@ __decorateClass([
318
348
  __decorateClass([
319
349
  query(".message-thread")
320
350
  ], AiMessageThreadComponent.prototype, "_messageThreadContainer", 2);
351
+ __decorateClass([
352
+ query(".message-thread-content")
353
+ ], AiMessageThreadComponent.prototype, "_messageThreadContent", 2);
321
354
  AiMessageThreadComponent = __decorateClass([
322
355
  customElement(AiMessageThreadComponentTagName)
323
356
  ], AiMessageThreadComponent);
@@ -0,0 +1,67 @@
1
+ import { LitElement, PropertyValues, nothing, TemplateResult, CSSResult } from 'lit';
2
+ declare global {
3
+ interface HTMLElementTagNameMap {
4
+ 'forge-ai-steps': AiStepsComponent;
5
+ }
6
+ }
7
+ export declare const AiStepsComponentTagName: keyof HTMLElementTagNameMap;
8
+ /** Lifecycle state of an individual step. */
9
+ export type AiStepStatus = 'pending' | 'running' | 'complete';
10
+ /**
11
+ * A single step in the timeline. Every field is supplied by the agent — the component derives no
12
+ * labels of its own and makes no assumption about how the agent names its work.
13
+ */
14
+ export interface AiStep {
15
+ /**
16
+ * Agent-provided label for the step, e.g. `'Filtered by \`crime_category\`'`. Rendered as inline
17
+ * markdown, so the agent decides which part of its own label to emphasize. Literal `*`, `_` and
18
+ * `` ` `` characters need escaping.
19
+ */
20
+ label: string;
21
+ /**
22
+ * Optional agent-provided elaboration, rendered as a detail card beneath the label. Also rendered
23
+ * as inline markdown.
24
+ */
25
+ detail?: string;
26
+ /** Lifecycle state of this step. Defaults to `'complete'` when omitted. */
27
+ status?: AiStepStatus;
28
+ }
29
+ /**
30
+ * @tag forge-ai-steps
31
+ *
32
+ * @summary Expandable timeline summarizing the steps an agent took while producing a response.
33
+ *
34
+ * @description
35
+ * Collapsed, it shows a step count and a summary of the first couple of step labels. When expanded,
36
+ * it lists each step as a row in a vertical timeline along with its status. Steps carrying a
37
+ * `detail` render as detail cards; steps without one render as a simple labeled row.
38
+ *
39
+ * Labels and details are rendered as sanitized inline markdown, so the agent controls its own
40
+ * emphasis — bold, italic, strikethrough, `code` and links — rather than the component or the
41
+ * consumer prescribing which part of a step matters.
42
+ *
43
+ * This is a presentational primitive: it renders whatever `steps` it is given and knows nothing
44
+ * about tool calls or tool definitions. `forge-ai-tool-steps` is the tool renderer that maps an
45
+ * agent's `displaySteps` tool call onto these properties.
46
+ *
47
+ * While `running` is `true` the timeline stays expanded and the summary row is hidden. When
48
+ * `running` flips back to `false` the timeline auto-collapses, leaving the summary row as the way
49
+ * back in. An element that mounts with `running` already `false` renders expanded, so static usage
50
+ * (a finished run, or a Storybook story) is readable without interaction.
51
+ *
52
+ * @property {AiStep[]} steps - The steps to render as timeline rows
53
+ * @property {boolean} running - Whether the run producing these steps is still in progress
54
+ */
55
+ export declare class AiStepsComponent extends LitElement {
56
+ #private;
57
+ static styles: CSSResult;
58
+ steps: AiStep[];
59
+ /**
60
+ * Whether the run producing these steps is still in progress. While `true` the timeline is held
61
+ * open and the summary row is hidden; the transition back to `false` collapses the timeline.
62
+ */
63
+ running: boolean;
64
+ private _expanded;
65
+ willUpdate(changedProperties: PropertyValues<this>): void;
66
+ render(): TemplateResult | typeof nothing;
67
+ }
@@ -0,0 +1,163 @@
1
+ import { unsafeCSS, LitElement, html, nothing } from "lit";
2
+ import { property, state, customElement } from "lit/decorators.js";
3
+ import { join } from "lit/directives/join.js";
4
+ import { unsafeHTML } from "lit/directives/unsafe-html.js";
5
+ import { when } from "lit/directives/when.js";
6
+ import { renderInlineMarkdown } from "../utils/markdown.mjs";
7
+ import styles from "./ai-steps.scss.mjs";
8
+ var __defProp = Object.defineProperty;
9
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
10
+ var __typeError = (msg) => {
11
+ throw TypeError(msg);
12
+ };
13
+ var __decorateClass = (decorators, target, key, kind) => {
14
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
15
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
16
+ if (decorator = decorators[i])
17
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
18
+ if (kind && result) __defProp(target, key, result);
19
+ return result;
20
+ };
21
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
22
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
23
+ 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);
24
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
25
+ var _chevronIcon, _rowMarker, _AiStepsComponent_instances, renderInline_fn, summaryLabel_get, toggle_fn, renderNoDetailStep_fn, renderStep_fn, isExpanded_get, steps_get, stepsSummary_get, stepsCountLabel_get;
26
+ const AiStepsComponentTagName = "forge-ai-steps";
27
+ const MAX_DETAIL_LENGTH = 2e3;
28
+ let AiStepsComponent = class extends LitElement {
29
+ constructor() {
30
+ super(...arguments);
31
+ __privateAdd(this, _AiStepsComponent_instances);
32
+ this.steps = [];
33
+ this.running = false;
34
+ this._expanded = true;
35
+ __privateAdd(this, _chevronIcon, html`
36
+ <svg
37
+ class="chevron"
38
+ xmlns="http://www.w3.org/2000/svg"
39
+ viewBox="0 0 24 24"
40
+ height="20"
41
+ width="20"
42
+ fill="currentColor"
43
+ aria-hidden="true">
44
+ <path d="M7.41 8.59 12 13.17l4.59-4.58L18 10l-6 6-6-6z" />
45
+ </svg>
46
+ `);
47
+ __privateAdd(this, _rowMarker, html`<span class="row-marker"></span>`);
48
+ }
49
+ willUpdate(changedProperties) {
50
+ if (changedProperties.has("running") && !this.running && changedProperties.get("running") === true) {
51
+ this._expanded = false;
52
+ }
53
+ }
54
+ render() {
55
+ if (this.steps.length === 0) {
56
+ return nothing;
57
+ }
58
+ return html`
59
+ <div class="steps">
60
+ <div class="steps-count">${__privateGet(this, _AiStepsComponent_instances, stepsCountLabel_get)}</div>
61
+ ${__privateGet(this, _AiStepsComponent_instances, stepsSummary_get)} ${__privateGet(this, _AiStepsComponent_instances, steps_get)}
62
+ </div>
63
+ `;
64
+ }
65
+ };
66
+ _chevronIcon = /* @__PURE__ */ new WeakMap();
67
+ _rowMarker = /* @__PURE__ */ new WeakMap();
68
+ _AiStepsComponent_instances = /* @__PURE__ */ new WeakSet();
69
+ renderInline_fn = function(value) {
70
+ return html`${unsafeHTML(renderInlineMarkdown(value))}`;
71
+ };
72
+ summaryLabel_get = function() {
73
+ const stepLabels = this.steps.map((step) => html`<span>${__privateMethod(this, _AiStepsComponent_instances, renderInline_fn).call(this, step.label)}</span>`);
74
+ const visibleLabels = stepLabels.slice(0, 2);
75
+ const remaining = stepLabels.length - visibleLabels.length;
76
+ return remaining > 0 ? html`${join(visibleLabels, html`, `)} +${remaining} more` : html`${join(visibleLabels, html`, `)}`;
77
+ };
78
+ toggle_fn = function() {
79
+ this._expanded = !this._expanded;
80
+ };
81
+ renderNoDetailStep_fn = function(step) {
82
+ return html`
83
+ <div class="timeline-row" data-status=${step.status ?? "complete"}>
84
+ <div class="row-header">
85
+ ${__privateGet(this, _rowMarker)}
86
+ <span class="row-label">
87
+ <span class="row-name">${__privateMethod(this, _AiStepsComponent_instances, renderInline_fn).call(this, step.label)}</span>
88
+ </span>
89
+ </div>
90
+ </div>
91
+ `;
92
+ };
93
+ renderStep_fn = function(step) {
94
+ const detail = step.detail;
95
+ if (!detail) {
96
+ return __privateMethod(this, _AiStepsComponent_instances, renderNoDetailStep_fn).call(this, step);
97
+ }
98
+ const truncated = detail.length > MAX_DETAIL_LENGTH ? `${detail.slice(0, MAX_DETAIL_LENGTH)}… (truncated)` : detail;
99
+ return html`
100
+ <div class="timeline-row" data-status=${step.status ?? "complete"}>
101
+ <div class="row-header">
102
+ ${__privateGet(this, _rowMarker)}
103
+ <div class="step-card">
104
+ <span class="step-card-title">${__privateMethod(this, _AiStepsComponent_instances, renderInline_fn).call(this, step.label)}</span>
105
+ <div class="step-card-body">
106
+ <div class="step-card-result">${__privateMethod(this, _AiStepsComponent_instances, renderInline_fn).call(this, truncated)}</div>
107
+ </div>
108
+ </div>
109
+ </div>
110
+ </div>
111
+ `;
112
+ };
113
+ isExpanded_get = function() {
114
+ return this.running || this._expanded;
115
+ };
116
+ steps_get = function() {
117
+ return html`
118
+ <div
119
+ id="timeline-content"
120
+ class="timeline ${__privateGet(this, _AiStepsComponent_instances, isExpanded_get) ? "expanded" : ""}"
121
+ aria-hidden=${__privateGet(this, _AiStepsComponent_instances, isExpanded_get) ? "false" : "true"}>
122
+ <div class="timeline-content">${this.steps.map((step) => __privateMethod(this, _AiStepsComponent_instances, renderStep_fn).call(this, step))}</div>
123
+ </div>
124
+ `;
125
+ };
126
+ stepsSummary_get = function() {
127
+ return when(
128
+ !this.running,
129
+ () => html`
130
+ <button
131
+ class="summary"
132
+ type="button"
133
+ aria-expanded=${this._expanded}
134
+ aria-controls="timeline-content"
135
+ @click=${__privateMethod(this, _AiStepsComponent_instances, toggle_fn)}>
136
+ ${__privateGet(this, _chevronIcon)}
137
+ <span class="status-text">${__privateGet(this, _AiStepsComponent_instances, summaryLabel_get)}</span>
138
+ <span class="focus-indicator"></span>
139
+ </button>
140
+ `
141
+ );
142
+ };
143
+ stepsCountLabel_get = function() {
144
+ const count = this.steps.length;
145
+ return `${count} step${count === 1 ? "" : "s"}`;
146
+ };
147
+ AiStepsComponent.styles = unsafeCSS(styles);
148
+ __decorateClass([
149
+ property({ attribute: false })
150
+ ], AiStepsComponent.prototype, "steps", 2);
151
+ __decorateClass([
152
+ property({ type: Boolean, reflect: true })
153
+ ], AiStepsComponent.prototype, "running", 2);
154
+ __decorateClass([
155
+ state()
156
+ ], AiStepsComponent.prototype, "_expanded", 2);
157
+ AiStepsComponent = __decorateClass([
158
+ customElement(AiStepsComponentTagName)
159
+ ], AiStepsComponent);
160
+ export {
161
+ AiStepsComponent,
162
+ AiStepsComponentTagName
163
+ };
@@ -0,0 +1,4 @@
1
+ const styles = '/* prettier-ignore */\n@keyframes fadein {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n@keyframes forge-focus-indicator-outward-grow {\n from {\n outline-width: 0;\n }\n to {\n outline-width: var(--_focus-indicator-active-width);\n }\n}\n@keyframes forge-focus-indicator-outward-shrink {\n from {\n outline-width: var(--_focus-indicator-active-width);\n }\n}\n@keyframes forge-focus-indicator-inward-grow {\n from {\n border-width: 0;\n }\n to {\n border-width: var(--_focus-indicator-active-width);\n }\n}\n@keyframes forge-focus-indicator-inward-shrink {\n from {\n border-width: var(--_focus-indicator-active-width);\n }\n}\n:host {\n display: flex;\n flex-direction: column;\n gap: var(--forge-spacing-small, 12px);\n}\n\n.summary {\n display: flex;\n align-items: center;\n gap: var(--forge-spacing-xsmall, 8px);\n padding-block: var(--forge-spacing-xxsmall, 4px);\n padding-inline: var(--forge-spacing-xsmall, 8px);\n border: none;\n background-color: var(--forge-theme-surface-container-minimum, #f5f5f5);\n border-radius: calc(var(--forge-shape-large, 8px) * var(--forge-shape-factor, 1));\n cursor: pointer;\n text-align: start;\n position: relative;\n outline: none;\n --_state-layer-display: var(--forge-state-layer-display, flex);\n --_state-layer-color: var(--forge-state-layer-color, var(--forge-theme-on-surface, #000000));\n --_state-layer-hover-color: var(--forge-state-layer-hover-color, var(--_state-layer-color));\n --_state-layer-hover-opacity: var(--forge-state-layer-hover-opacity, 0.08);\n --_state-layer-pressed-color: var(--forge-state-layer-pressed-color, var(--_state-layer-color));\n --_state-layer-pressed-opacity: var(--forge-state-layer-pressed-opacity, 0.12);\n --_state-layer-hover-duration: var(--forge-state-layer-hover-duration, 15ms);\n --_state-layer-pressed-duration: var(--forge-state-layer-pressed-duration, 105ms);\n --_state-layer-animation-duration: var(--forge-state-layer-animation-duration, 375ms);\n}\n.summary::before {\n opacity: 0;\n position: absolute;\n backface-visibility: hidden;\n transform: translateZ(0);\n background-color: var(--_state-layer-hover-color);\n inset: 0;\n transition: opacity var(--_state-layer-hover-duration) linear, background-color var(--_state-layer-hover-duration) linear;\n --_state-layer-hover-duration: var(--forge-state-layer-hover-duration, 100ms);\n content: "";\n opacity: 0;\n border-radius: inherit;\n}\n.summary:hover::before {\n background-color: var(--_state-layer-hover-color);\n opacity: var(--_state-layer-hover-opacity);\n}\n.summary:active::before {\n opacity: var(--_state-layer-pressed-opacity);\n transition-duration: var(--_state-layer-pressed-duration);\n --_state-layer-pressed-opacity: var(--forge-state-layer-pressed-opacity, 0.18);\n}\n\n.status-text {\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n font-family: var(--forge-typography-body1-font-family, var(--forge-typography-font-family, "Roboto", sans-serif));\n font-size: var(--forge-typography-body1-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-font-size-scale, 0.875)));\n font-weight: var(--forge-typography-body1-font-weight, 400);\n line-height: var(--forge-typography-body1-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-line-height-scale, 1.125)));\n letter-spacing: var(--forge-typography-body1-letter-spacing, 0.0357142857em);\n text-transform: var(--forge-typography-body1-text-transform, inherit);\n text-decoration: var(--forge-typography-body1-text-decoration, inherit);\n}\n\n.chevron {\n flex-shrink: 0;\n transform: rotate(-90deg);\n transition: transform var(--forge-animation-duration-short4, 200ms) var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1));\n}\n\n.summary[aria-expanded=true] .chevron {\n transform: rotate(0deg);\n}\n\n.focus-indicator {\n position: absolute;\n display: none;\n}\n\n:host .summary:focus .focus-indicator {\n --_focus-indicator-display: var(--forge-focus-indicator-display, flex);\n --_focus-indicator-width: var(--forge-focus-indicator-width, var(--forge-border-medium, 2px));\n --_focus-indicator-active-width: var(--forge-focus-indicator-active-width, 6px);\n --_focus-indicator-color: var(--forge-focus-indicator-color, var(--forge-theme-primary, #3f51b5));\n --_focus-indicator-shape: var(--forge-focus-indicator-shape, calc(var(--forge-shape-extra-small, 1px) * var(--forge-shape-factor, 1)));\n --_focus-indicator-duration: var(--forge-focus-indicator-duration, var(--forge-animation-duration-long4, 600ms));\n --_focus-indicator-easing: var(--forge-focus-indicator-easing, var(--forge-animation-easing-emphasized, cubic-bezier(0.2, 0, 0, 1)));\n --_focus-indicator-shape-start-start: var(--forge-focus-indicator-shape-start-start, var(--_focus-indicator-shape));\n --_focus-indicator-shape-start-end: var(--forge-focus-indicator-shape-start-end, var(--_focus-indicator-shape));\n --_focus-indicator-shape-end-end: var(--forge-focus-indicator-shape-end-end, var(--_focus-indicator-shape));\n --_focus-indicator-shape-end-start: var(--forge-focus-indicator-shape-end-start, var(--_focus-indicator-shape));\n --_focus-indicator-outward-offset: var(--forge-focus-indicator-outward-offset, var(--forge-spacing-xxsmall, 4px));\n --_focus-indicator-inward-offset: var(--forge-focus-indicator-inward-offset, 0px);\n --_focus-indicator-offset-block: var(--forge-focus-indicator-offset-block, 0);\n --_focus-indicator-offset-inline: var(--forge-focus-indicator-offset-inline, 0);\n animation-delay: 0s, calc(var(--_focus-indicator-duration) * 0.25);\n animation-duration: calc(var(--_focus-indicator-duration) * 0.25), calc(var(--_focus-indicator-duration) * 0.75);\n animation-timing-function: var(--_focus-indicator-easing);\n box-sizing: border-box;\n color: var(--_focus-indicator-color);\n display: none;\n pointer-events: none;\n position: absolute;\n margin-block: var(--_focus-indicator-offset-block);\n margin-inline: var(--_focus-indicator-offset-inline);\n animation-name: forge-focus-indicator-inward-grow, forge-focus-indicator-inward-shrink;\n border-end-end-radius: calc(var(--_focus-indicator-shape-end-end) - var(--_focus-indicator-inward-offset));\n border-end-start-radius: calc(var(--_focus-indicator-shape-end-start) - var(--_focus-indicator-inward-offset));\n border-start-end-radius: calc(var(--_focus-indicator-shape-start-end) - var(--_focus-indicator-inward-offset));\n border-start-start-radius: calc(var(--_focus-indicator-shape-start-start) - var(--_focus-indicator-inward-offset));\n border: var(--_focus-indicator-width) solid currentColor;\n inset: var(--_focus-indicator-inward-offset);\n}\n:host .summary:focus .focus-indicator::before {\n content: "";\n}\n:host .summary:focus .focus-indicator {\n display: block;\n --forge-focus-indicator-shape: calc(var(--forge-shape-large, 8px) * var(--forge-shape-factor, 1));\n}\n\n.steps {\n display: flex;\n flex-direction: column;\n gap: var(--forge-spacing-xsmall, 8px);\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n font-family: var(--forge-typography-body1-font-family, var(--forge-typography-font-family, "Roboto", sans-serif));\n font-size: var(--forge-typography-body1-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-font-size-scale, 0.875)));\n font-weight: var(--forge-typography-body1-font-weight, 400);\n line-height: var(--forge-typography-body1-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-line-height-scale, 1.125)));\n letter-spacing: var(--forge-typography-body1-letter-spacing, 0.0357142857em);\n text-transform: var(--forge-typography-body1-text-transform, inherit);\n text-decoration: var(--forge-typography-body1-text-decoration, inherit);\n font-size: var(--forge-ai-markdown-font-size, 0.875rem);\n line-height: var(--forge-ai-markdown-line-height, 1.5rem);\n color: var(--forge-theme-on-surface, #000000);\n overflow-wrap: break-word;\n}\n.steps h1,\n.steps h2,\n.steps h3,\n.steps h4,\n.steps h5,\n.steps h6 {\n margin: 1.75rem 0 var(--forge-spacing-small, 12px);\n}\n.steps strong {\n font-weight: 500;\n}\n.steps a {\n color: var(--forge-theme-primary, #3f51b5);\n}\n.steps hr {\n border: none;\n border-top: 1px solid var(--forge-theme-outline, #e0e0e0);\n}\n.steps code {\n color: var(--forge-theme-on-surface-container-low, #000000);\n background-color: var(--forge-theme-surface-container-low, #ebebeb);\n border-radius: calc(var(--forge-shape-medium, 4px) * var(--forge-shape-factor, 1));\n padding: var(--forge-spacing-xxxsmall, 2px) var(--forge-spacing-xxsmall, 4px);\n font-size: 0.75em;\n}\n.steps pre {\n border: 1px solid var(--forge-theme-outline, #e0e0e0);\n border-radius: calc(var(--forge-shape-medium, 4px) * var(--forge-shape-factor, 1));\n margin: 0;\n max-width: 100%;\n overflow-x: auto;\n}\n.steps pre:focus-visible {\n outline: 2px solid var(--forge-theme-primary, #3f51b5);\n outline-offset: 2px;\n}\n.steps pre code {\n display: block;\n padding: var(--forge-spacing-xsmall, 8px) var(--forge-spacing-small, 12px);\n color: var(--forge-theme-on-surface-container-minimum, #000000);\n background: var(--forge-theme-surface-container-minimum, #f5f5f5);\n white-space: pre;\n}\n.steps [data-scroll-region=table] {\n max-width: 100%;\n overflow-x: auto;\n border-radius: calc(var(--forge-shape-large, 8px) * var(--forge-shape-factor, 1));\n margin-block: var(--forge-spacing-medium, 16px);\n}\n.steps [data-scroll-region=table]:focus-visible {\n outline: 2px solid var(--forge-theme-primary, #3f51b5);\n outline-offset: 2px;\n}\n.steps [data-scroll-region=table] table {\n margin-block: 0;\n}\n.steps table {\n width: 100%;\n border-spacing: 0;\n background-color: var(--forge-theme-surface, #ffffff);\n border-radius: calc(var(--forge-shape-large, 8px) * var(--forge-shape-factor, 1));\n overflow: hidden;\n margin-block: var(--forge-spacing-medium, 16px);\n}\n.steps table thead {\n color: var(--forge-theme-text-medium, rgba(0, 0, 0, 0.6));\n font-weight: bold;\n text-align: left;\n font-size: calc(var(--forge-typography-font-size, 1rem) * 0.75);\n box-sizing: border-box;\n}\n.steps table tr {\n height: 36px;\n height: 32px;\n}\n.steps table tr:nth-child(even) {\n background-color: var(--forge-theme-surface-dim, #fafafa);\n}\n.steps table tr:last-child td {\n border-bottom: none;\n}\n.steps table th,\n.steps table td {\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 padding-block: var(--forge-spacing-xsmall, 8px);\n padding-inline-start: var(--forge-spacing-xsmall, 8px);\n padding-inline-end: var(--forge-spacing-medium, 16px);\n border-bottom-width: 1px;\n border-bottom-style: solid;\n border-bottom-color: var(--forge-theme-outline, #e0e0e0);\n}\n.steps table th {\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n font-family: var(--forge-typography-label2-font-family, var(--forge-typography-font-family, "Roboto", sans-serif));\n font-size: var(--forge-typography-label2-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-label-font-size-scale, 0.8125)));\n font-weight: var(--forge-typography-label2-font-weight, 400);\n line-height: var(--forge-typography-label2-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-label-line-height-scale, 1.25)));\n letter-spacing: var(--forge-typography-label2-letter-spacing, 0.0096153846em);\n text-transform: var(--forge-typography-label2-text-transform, inherit);\n text-decoration: var(--forge-typography-label2-text-decoration, inherit);\n font-weight: 600;\n}\n.steps > p:has(+ ol),\n.steps > p:has(+ ul) {\n margin-block-end: var(--forge-spacing-small, 12px);\n}\n.steps > ul {\n list-style-type: disc;\n padding-inline-start: 1.6875rem;\n}\n.steps > ol {\n padding-inline-start: 1.75rem;\n}\n.steps > ol,\n.steps > ul {\n margin: var(--forge-spacing-xsmall, 8px) 0;\n margin-block-end: var(--forge-spacing-medium, 16px);\n}\n.steps > :first-child {\n margin-block-start: 0;\n}\n.steps > p {\n margin-block-end: var(--forge-spacing-medium, 16px);\n overflow-wrap: anywhere;\n}\n.steps > p:first-child {\n margin-block-start: 0;\n}\n.steps > p:last-child {\n margin-block-end: 0;\n}\n.steps-count {\n color: var(--forge-theme-text-medium, rgba(0, 0, 0, 0.6));\n font-weight: 700;\n text-transform: uppercase;\n}\n\n.timeline {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows var(--forge-animation-duration-medium2, 300ms) var(--forge-animation-easing-decelerate, cubic-bezier(0, 0, 0, 1));\n}\n.timeline.expanded {\n grid-template-rows: 1fr;\n}\n\n.timeline-content {\n overflow: hidden;\n min-height: 0;\n padding-inline-start: var(--forge-spacing-small, 12px);\n}\n\n.timeline-row {\n position: relative;\n padding-inline-start: var(--forge-spacing-large, 24px);\n padding-block-end: var(--forge-spacing-medium, 16px);\n}\n.timeline-row::before {\n content: "";\n position: absolute;\n inset-block-start: calc((var(--forge-spacing-medium-large, 20px) - var(--forge-spacing-xsmall, 8px)) / 2);\n inset-block-end: calc(-1 * var(--forge-spacing-xsmall, 8px));\n inset-inline-start: calc((var(--forge-spacing-medium-large, 20px) - 1px) / 2);\n width: 1px;\n background-color: var(--forge-theme-outline, #e0e0e0);\n}\n.timeline-row:last-child::before {\n display: none;\n}\n\n.row-header {\n display: flex;\n align-items: flex-start;\n gap: var(--forge-spacing-small, 12px);\n width: 100%;\n min-height: var(--forge-spacing-medium-large, 20px);\n margin-inline-start: calc(-1 * var(--forge-spacing-large, 24px));\n}\n\n.row-marker {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--forge-spacing-medium-large, 20px);\n height: var(--forge-spacing-medium-large, 20px);\n border-radius: calc(var(--forge-shape-round, 50%) * var(--forge-shape-factor, 1));\n}\n.row-marker::before {\n content: "";\n flex-shrink: 0;\n width: var(--forge-spacing-xsmall, 8px);\n height: var(--forge-spacing-xsmall, 8px);\n border-radius: calc(var(--forge-shape-round, 50%) * var(--forge-shape-factor, 1));\n background-color: currentColor;\n position: relative;\n z-index: 1;\n}\n\n.row-label {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 0;\n gap: var(--forge-spacing-xxxsmall, 2px);\n}\n\n.row-name {\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n font-family: var(--forge-typography-body1-font-family, var(--forge-typography-font-family, "Roboto", sans-serif));\n font-size: var(--forge-typography-body1-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-font-size-scale, 0.875)));\n font-weight: var(--forge-typography-body1-font-weight, 400);\n line-height: var(--forge-typography-body1-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-line-height-scale, 1.125)));\n letter-spacing: var(--forge-typography-body1-letter-spacing, 0.0357142857em);\n text-transform: var(--forge-typography-body1-text-transform, inherit);\n text-decoration: var(--forge-typography-body1-text-decoration, inherit);\n display: flex;\n align-items: center;\n gap: var(--forge-spacing-xsmall, 8px);\n line-height: normal;\n font-weight: 500;\n color: var(--forge-theme-text-high, rgba(0, 0, 0, 0.87));\n}\n\n.step-card {\n width: 100%;\n}\n.step-card-title {\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n font-family: var(--forge-typography-body1-font-family, var(--forge-typography-font-family, "Roboto", sans-serif));\n font-size: var(--forge-typography-body1-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-font-size-scale, 0.875)));\n font-weight: var(--forge-typography-body1-font-weight, 400);\n line-height: var(--forge-typography-body1-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-line-height-scale, 1.125)));\n letter-spacing: var(--forge-typography-body1-letter-spacing, 0.0357142857em);\n text-transform: var(--forge-typography-body1-text-transform, inherit);\n text-decoration: var(--forge-typography-body1-text-decoration, inherit);\n font-weight: 700;\n}\n.step-card-result {\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n font-family: var(--forge-typography-body1-font-family, var(--forge-typography-font-family, "Roboto", sans-serif));\n font-size: var(--forge-typography-body1-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-font-size-scale, 0.875)));\n font-weight: var(--forge-typography-body1-font-weight, 400);\n line-height: var(--forge-typography-body1-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-line-height-scale, 1.125)));\n letter-spacing: var(--forge-typography-body1-letter-spacing, 0.0357142857em);\n text-transform: var(--forge-typography-body1-text-transform, inherit);\n text-decoration: var(--forge-typography-body1-text-decoration, inherit);\n}\n\n.row-name strong,\n.step-card-title strong {\n font-weight: 700;\n}';
2
+ export {
3
+ styles as default
4
+ };
@@ -0,0 +1 @@
1
+ export * from './ai-steps';
@@ -0,0 +1,5 @@
1
+ import { AiStepsComponent, AiStepsComponentTagName } from "./ai-steps.mjs";
2
+ export {
3
+ AiStepsComponent,
4
+ AiStepsComponentTagName
5
+ };
@@ -1,5 +1,5 @@
1
1
  import { LitElement, nothing, PropertyValues, TemplateResult, CSSResult } from 'lit';
2
- import { ToolCall, ToolDefinition } from '../ai-chatbot/types.js';
2
+ import { ToolCall, AnyToolDefinition } from '../ai-chatbot/types.js';
3
3
  declare global {
4
4
  interface HTMLElementTagNameMap {
5
5
  'forge-ai-tool-call-indicator': AiToolCallIndicatorComponent;
@@ -20,7 +20,7 @@ export declare class AiToolCallIndicatorComponent extends LitElement {
20
20
  #private;
21
21
  static styles: CSSResult;
22
22
  toolCalls: ToolCall[];
23
- tools?: Map<string, ToolDefinition>;
23
+ tools?: Map<string, AnyToolDefinition>;
24
24
  debugMode: boolean;
25
25
  private _expanded;
26
26
  private _expandedRows;
@@ -218,7 +218,7 @@ highlightJson_fn = function(value) {
218
218
  return html`${unsafeHTML(highlighted)}`;
219
219
  };
220
220
  statusMarker_fn = function(toolCall) {
221
- if (toolCall.status === "error") {
221
+ if (toolCall.status === "error" || toolCall.status === "cancelled") {
222
222
  return html`<span class="row-marker row-marker--error">${__privateGet(this, _errorIcon)}</span>`;
223
223
  }
224
224
  if (isToolCallSettled(toolCall, this.tools?.get(toolCall.name))) {
@@ -0,0 +1,81 @@
1
+ import { ReactiveController, ReactiveControllerHost } from 'lit';
2
+ import { AnyToolDefinition, ChatMessage, ToolCall } from '../ai-chatbot/types.js';
3
+ import { ForgeAiCanvasCloseRequestEventData, ForgeAiCanvasOpenRequestEventData } from '../ai-chatbot/tool-canvas.js';
4
+ export interface OpenCanvasOptions {
5
+ /** Identifies the artifact; tool-driven opens use the tool call id. */
6
+ id?: string;
7
+ /** Overrides `canvasTitle` while this content is shown. */
8
+ title?: string;
9
+ /** Content mounted in the canvas body. Omit to show the `canvas` slot instead. */
10
+ content?: Node;
11
+ }
12
+ export interface CanvasOpenEventData {
13
+ id?: string;
14
+ title?: string;
15
+ /** Present when the canvas was opened for a tool call. */
16
+ toolCall?: ToolCall;
17
+ }
18
+ /** `auto`: opened by `canvas.open: 'auto'` rather than a user or API request. */
19
+ export type CanvasOpenReason = 'auto' | 'request';
20
+ export interface CanvasContent {
21
+ id?: string;
22
+ title?: string;
23
+ node?: Node;
24
+ toolCall?: ToolCall;
25
+ /** Set for tool-driven content so it can follow the tool call as it updates. */
26
+ toolDefinition?: AnyToolDefinition;
27
+ /** Title supplied with the open request; otherwise the title is re-derived from the tool call. */
28
+ titleOverride?: string;
29
+ }
30
+ export interface CanvasControllerConfig {
31
+ /** Cancelable event dispatched on the host before the canvas opens or swaps content. */
32
+ openEvent: string;
33
+ /** Event dispatched on the host when the canvas closes; cancelable except when the host forces it. */
34
+ closeEvent: string;
35
+ dispatchHostEvent: (config: {
36
+ type: string;
37
+ detail?: unknown;
38
+ cancelable?: boolean;
39
+ }) => CustomEvent;
40
+ getToolCalls: () => ToolCall[];
41
+ getTools: () => Map<string, AnyToolDefinition>;
42
+ /** Whether the host can show the canvas right now. Defaults to always. */
43
+ canOpen?: () => boolean;
44
+ /** Called once the canvas has gone from closed to open, not when its content is swapped. */
45
+ onOpen?: (config: {
46
+ reason: CanvasOpenReason;
47
+ }) => void;
48
+ /** Called after the canvas is hidden for any reason. */
49
+ onClose?: () => void;
50
+ /** Called when the requested tool call is already showing, so the host can draw attention to it. */
51
+ onRefocus?: () => void;
52
+ /** Resolves once the host's collapse presentation has finished; hidden content is released after it. */
53
+ collapsed?: () => Promise<void>;
54
+ }
55
+ /**
56
+ * Owns the artifact canvas state shared by every chatbot form factor: what is shown, the cancelable
57
+ * open/close events, tool call tracking, auto-open, and the `canvas` controls injected into renderers.
58
+ * The host decides how that state is presented (a side panel, a modal, ...).
59
+ */
60
+ export declare class CanvasController implements ReactiveController {
61
+ #private;
62
+ constructor(host: ReactiveControllerHost & HTMLElement, config: CanvasControllerConfig);
63
+ hostConnected(): void;
64
+ get isOpen(): boolean;
65
+ get content(): CanvasContent | null;
66
+ open(options?: OpenCanvasOptions): boolean;
67
+ /** Closes the canvas. Returns false if it was not open or the close event was prevented. */
68
+ close(): boolean;
69
+ /** Closes without asking, for when the host can no longer show the canvas (e.g. it left its conversation view). */
70
+ forceClose(): void;
71
+ /** Forgets the canvas entirely, for when the thread it belonged to is gone. */
72
+ reset(): void;
73
+ /** Tool calls restored from history are marked as seen so loading a thread never auto-opens the canvas. */
74
+ markSeen(messages: ChatMessage[]): void;
75
+ readonly handleOpenRequest: (evt: CustomEvent<ForgeAiCanvasOpenRequestEventData>) => void;
76
+ readonly handleCloseRequest: (evt: CustomEvent<ForgeAiCanvasCloseRequestEventData>) => void;
77
+ /** The tool call object is replaced on every args or status update, so open content follows it by id. */
78
+ syncToolCall(): void;
79
+ /** Opens tools configured with `canvas.open: 'auto'` once their renderer shows. Call after render, not during it. */
80
+ autoOpenPending(): void;
81
+ }