@tylertech/forge-ai 0.13.11 → 0.13.12

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 (32) hide show
  1. package/custom-elements.json +463 -49
  2. package/dist/ai-assistant-response/ai-assistant-response.mjs +8 -5
  3. package/dist/ai-chatbot/agent-adapter.d.ts +1 -0
  4. package/dist/ai-chatbot/ai-chatbot-base.d.ts +23 -1
  5. package/dist/ai-chatbot/ai-chatbot-base.mjs +28 -9
  6. package/dist/ai-chatbot/ai-chatbot.d.ts +2 -0
  7. package/dist/ai-chatbot/ai-chatbot.mjs +5 -0
  8. package/dist/ai-chatbot/index.d.ts +1 -1
  9. package/dist/ai-chatbot/message-state-controller.d.ts +11 -1
  10. package/dist/ai-chatbot/message-state-controller.mjs +54 -1
  11. package/dist/ai-chatbot/types.d.ts +27 -0
  12. package/dist/ai-client-message/ai-client-message.d.ts +28 -0
  13. package/dist/ai-client-message/ai-client-message.mjs +112 -0
  14. package/dist/ai-client-message/ai-client-message.scss.mjs +4 -0
  15. package/dist/ai-client-message/index.d.ts +1 -0
  16. package/dist/ai-client-message/index.mjs +5 -0
  17. package/dist/ai-conversations-panel/ai-conversations-panel.d.ts +1 -0
  18. package/dist/ai-conversations-panel/ai-conversations-panel.mjs +15 -2
  19. package/dist/ai-conversations-panel/ai-conversations-panel.scss.mjs +1 -1
  20. package/dist/ai-empty-state/ai-empty-state.scss.mjs +1 -1
  21. package/dist/ai-message-thread/ai-message-thread.mjs +9 -1
  22. package/dist/ai-message-thread/ai-message-thread.scss.mjs +1 -1
  23. package/dist/ai-tool-call-indicator/ai-tool-call-indicator.mjs +2 -1
  24. package/dist/core/chatbot-core-controller.d.ts +5 -1
  25. package/dist/core/chatbot-core-controller.mjs +25 -10
  26. package/dist/index.d.ts +1 -0
  27. package/dist/index.mjs +3 -0
  28. package/dist/tools/ai-data-table/ai-data-table.d.ts +0 -1
  29. package/dist/tools/ai-data-table/ai-data-table.mjs +1 -13
  30. package/dist/tools/ai-data-table/ai-data-table.scss.mjs +1 -1
  31. package/dist/utils/markdown.mjs +1 -1
  32. package/package.json +2 -2
@@ -166,11 +166,14 @@ thinkingIndicator_get = function() {
166
166
  if (!this.showThinking) {
167
167
  return nothing;
168
168
  }
169
- const lastChild = this.response.children[this.response.children.length - 1];
170
- if (lastChild?.type === "text" && lastChild.status === "streaming") {
171
- const content = typeof lastChild.content === "string" ? lastChild.content : "";
172
- if (content.trim().length > 0) {
173
- return nothing;
169
+ const isThinking = this.response.status === "streaming" && this.response.isThinking === true;
170
+ if (!isThinking) {
171
+ const lastChild = this.response.children[this.response.children.length - 1];
172
+ if (lastChild?.type === "text" && lastChild.status === "streaming") {
173
+ const content = typeof lastChild.content === "string" ? lastChild.content : "";
174
+ if (content.trim().length > 0) {
175
+ return nothing;
176
+ }
174
177
  }
175
178
  }
176
179
  const hasActiveToolCall = this.response.children.some((child) => {
@@ -45,6 +45,7 @@ export interface ToolResultEvent {
45
45
  toolCallId: string;
46
46
  result: unknown;
47
47
  message: ChatMessage;
48
+ isError?: boolean;
48
49
  rawEvent?: unknown;
49
50
  }
50
51
  export interface AdapterState {
@@ -10,7 +10,7 @@ import { ForgeAiSuggestionsEventData, Suggestion } from '../ai-suggestions';
10
10
  import { ForgeAiVoiceInputResultEvent } from '../ai-voice-input';
11
11
  import { AgentAdapter } from './agent-adapter.js';
12
12
  import { ChatbotCoreController } from '../core/chatbot-core-controller.js';
13
- import { Agent, ChatMessage, ContextItem, HeadingLevel, MessageItem, SlashCommand, ThreadState, ToolDefinition } from './types.js';
13
+ import { Agent, ChatMessage, ClientMessageInput, ContextItem, HeadingLevel, MessageItem, SlashCommand, ThreadState, ToolDefinition } from './types.js';
14
14
  export type FeatureToggle = 'on' | 'off';
15
15
  export declare abstract class AiChatbotBase extends LitElement {
16
16
  protected abstract _messageThreadRef: Ref<AiMessageThreadComponent>;
@@ -112,6 +112,28 @@ export declare abstract class AiChatbotBase extends LitElement {
112
112
  startNewChat(): void;
113
113
  getMessages(): ChatMessage[];
114
114
  setMessages(messages: ChatMessage[]): void;
115
+ /**
116
+ * Inserts or upserts a client-only status message into the thread - never sent to
117
+ * the agent adapter and never included in the conversation history the adapter sees.
118
+ * Use this for host-driven UI feedback (e.g. "Your session expired", upload progress)
119
+ * instead of splicing {@link getMessages}/{@link setMessages} directly.
120
+ *
121
+ * Safe to call at any time, including while a response is streaming - it never
122
+ * finalizes or otherwise touches the in-progress response.
123
+ *
124
+ * @param message - Content and optional kind ('text' | 'info' | 'warning' | 'error' | 'success'),
125
+ * header, and actions. Pass the same `id` on a later call to upsert (replace) a
126
+ * previously added message.
127
+ * @returns The message id (generated if not provided).
128
+ */
129
+ addClientMessage(message: ClientMessageInput): string;
130
+ /**
131
+ * Removes a client-only message previously added via {@link addClientMessage}.
132
+ * No-ops if no message with that id exists. Safe to call at any time, including
133
+ * while a response is streaming. Removal is never automatic - call this when your
134
+ * host logic determines the message is no longer relevant.
135
+ */
136
+ removeClientMessage(id: string): void;
115
137
  sendMessage(content: string, files?: File[]): Promise<void>;
116
138
  abort(): void;
117
139
  scrollToBottom({ behavior }?: {
@@ -125,15 +125,8 @@ class AiChatbotBase extends LitElement {
125
125
  }
126
126
  if (this._hasMessages) {
127
127
  const agentName = agent?.name ?? this.titleText;
128
- const systemMessage = {
129
- id: generateId(),
130
- role: "system",
131
- content: `Switched to ${agentName}`,
132
- timestamp: Date.now(),
133
- status: "complete",
134
- clientOnly: true
135
- };
136
- this._coreController.addMessage(systemMessage);
128
+ this._coreController.finalizeActiveResponse();
129
+ this._coreController.addClientMessage({ content: `Switched to ${agentName}` });
137
130
  }
138
131
  }
139
132
  }
@@ -381,6 +374,32 @@ class AiChatbotBase extends LitElement {
381
374
  setMessages(messages) {
382
375
  this._coreController.setMessages(messages);
383
376
  }
377
+ /**
378
+ * Inserts or upserts a client-only status message into the thread - never sent to
379
+ * the agent adapter and never included in the conversation history the adapter sees.
380
+ * Use this for host-driven UI feedback (e.g. "Your session expired", upload progress)
381
+ * instead of splicing {@link getMessages}/{@link setMessages} directly.
382
+ *
383
+ * Safe to call at any time, including while a response is streaming - it never
384
+ * finalizes or otherwise touches the in-progress response.
385
+ *
386
+ * @param message - Content and optional kind ('text' | 'info' | 'warning' | 'error' | 'success'),
387
+ * header, and actions. Pass the same `id` on a later call to upsert (replace) a
388
+ * previously added message.
389
+ * @returns The message id (generated if not provided).
390
+ */
391
+ addClientMessage(message) {
392
+ return this._coreController.addClientMessage(message);
393
+ }
394
+ /**
395
+ * Removes a client-only message previously added via {@link addClientMessage}.
396
+ * No-ops if no message with that id exists. Safe to call at any time, including
397
+ * while a response is streaming. Removal is never automatic - call this when your
398
+ * host logic determines the message is no longer relevant.
399
+ */
400
+ removeClientMessage(id) {
401
+ this._coreController.removeClientMessage(id);
402
+ }
384
403
  async sendMessage(content, files) {
385
404
  if (!this._coreController.adapter) {
386
405
  console.warn("No adapter configured.");
@@ -100,6 +100,7 @@ export declare const AiChatbotComponentTagName: keyof HTMLElementTagNameMap;
100
100
  * @property {FeatureToggle} clearOption - Controls the clear-conversation header action. `'on'` (default) shows it when messages exist; `'off'` hides it entirely.
101
101
  * @property {FeatureToggle} exportOption - Controls the export-conversation header action. `'on'` (default) shows it when messages exist; `'off'` hides it entirely.
102
102
  * @property {string | null} selectedThreadId - The id of the currently selected conversation thread. Set this to highlight a thread in the conversations panel (e.g. when restoring a conversation loaded from the backend). Updated internally when a thread is selected or a new chat starts.
103
+ * @property {boolean} threadsLoading - When true, shows a loading indicator in the conversations panel's recent chats list while threads are loading (default: false)
103
104
  *
104
105
  * @cssproperty --forge-ai-chatbot-icon-color - The fill color for the AI icon. Defaults to `tertiary`.
105
106
  * @cssproperty --forge-ai-chatbot-suggestion-background - The background color for suggestion buttons. Defaults to `tertiary-container`.
@@ -142,6 +143,7 @@ export declare class AiChatbotComponent extends AiChatbotBase {
142
143
  showConversationRename: boolean;
143
144
  showConversationDelete: boolean;
144
145
  selectedThreadId: string | null;
146
+ threadsLoading: boolean;
145
147
  protected _messageThreadRef: Ref<AiMessageThreadComponent>;
146
148
  protected _promptRef: Ref<AiPromptComponent>;
147
149
  protected _handleInfo(): void;
@@ -48,6 +48,7 @@ let AiChatbotComponent = class extends AiChatbotBase {
48
48
  this.showConversationRename = false;
49
49
  this.showConversationDelete = false;
50
50
  this.selectedThreadId = null;
51
+ this.threadsLoading = false;
51
52
  __privateAdd(this, _chatInterfaceRef, createRef());
52
53
  this._messageThreadRef = createRef();
53
54
  this._promptRef = createRef();
@@ -214,6 +215,7 @@ let AiChatbotComponent = class extends AiChatbotBase {
214
215
  ${ref(__privateGet(this, _conversationsPanelRef))}
215
216
  .recentThreads=${this.recentThreads}
216
217
  .selectedThreadId=${this.selectedThreadId}
218
+ ?loading=${this.threadsLoading}
217
219
  ?show-back-button=${true}
218
220
  ?show-conversation-rename=${this.showConversationRename}
219
221
  ?show-conversation-delete=${this.showConversationDelete}
@@ -403,6 +405,9 @@ __decorateClass([
403
405
  __decorateClass([
404
406
  property({ type: String, attribute: "selected-thread-id" })
405
407
  ], AiChatbotComponent.prototype, "selectedThreadId", 2);
408
+ __decorateClass([
409
+ property({ type: Boolean, attribute: "threads-loading" })
410
+ ], AiChatbotComponent.prototype, "threadsLoading", 2);
406
411
  AiChatbotComponent = __decorateClass([
407
412
  customElement(AiChatbotComponentTagName)
408
413
  ], AiChatbotComponent);
@@ -4,7 +4,7 @@ export type { ForgeAiChatbotMessageEventData, ForgeAiChatbotToolCallEventData, F
4
4
  export { AiChatbotToolCallComponent, AiChatbotToolCallComponentTagName } from './ai-chatbot-tool-call.js';
5
5
  export type { Suggestion } from '../ai-suggestions/index.js';
6
6
  export { AgentAdapter, type MessageStartEvent, type MessageDeltaEvent, type MessageEndEvent, type ToolCallEvent, type ToolCallStartEvent, type ToolCallArgsEvent, type ToolCallEndEvent, type FileUploadEvent, type FileRemoveEvent, type AdapterState, type ErrorEvent, type CustomAgentEvent, type RawAgentEvent, type RunStartedAgentEvent, type StepStartedAgentEvent, type StepFinishedAgentEvent, type StateSnapshotAgentEvent, type StateDeltaAgentEvent, type ActivitySnapshotAgentEvent, type ActivityDeltaAgentEvent } from './agent-adapter.js';
7
- export type { Agent, ChatMessage, ContextItem, ToolDefinition, ToolCall, ToolRenderer, IToolRenderer, HandlerContext, ToolStartContext, ToolDeltaContext, ToolEndContext, FileAttachment, UploadedFileMetadata, FileUploadCallbacks, FileUploadHandler, FileRemoveCallbacks, ThreadState, FeedbackType, ResponseFeedback, MessageItem, ForgeAiChatbotContextRemoveEventData, ForgeAiChatbotConversationSelectEventData, ForgeAiChatbotConversationSearchEventData, ForgeAiChatbotConversationLoadMoreEventData, ForgeAiChatbotConversationRenameEventData, ForgeAiChatbotConversationDeleteEventData } from './types.js';
7
+ export type { Agent, ChatMessage, ClientMessageAction, ClientMessageInput, ClientMessageKind, ContextItem, ToolDefinition, ToolCall, ToolRenderer, IToolRenderer, HandlerContext, ToolStartContext, ToolDeltaContext, ToolEndContext, FileAttachment, UploadedFileMetadata, FileUploadCallbacks, FileUploadHandler, FileRemoveCallbacks, ThreadState, FeedbackType, ResponseFeedback, MessageItem, ForgeAiChatbotContextRemoveEventData, ForgeAiChatbotConversationSelectEventData, ForgeAiChatbotConversationSearchEventData, ForgeAiChatbotConversationLoadMoreEventData, ForgeAiChatbotConversationRenameEventData, ForgeAiChatbotConversationDeleteEventData } from './types.js';
8
8
  export * from './ag-ui-adapter.js';
9
9
  export * from './http-agent-with-credentials.js';
10
10
  export * from './event-emitter.js';
@@ -1,5 +1,5 @@
1
1
  import { ReactiveController, ReactiveControllerHost } from 'lit';
2
- import { ChatMessage, MessageItem, ToolCall, AssistantResponse, ResponseFeedback } from './types.js';
2
+ import { ChatMessage, ClientMessageInput, MessageItem, ToolCall, AssistantResponse, ResponseFeedback } from './types.js';
3
3
  import { MessageStartEvent, MessageDeltaEvent, MessageEndEvent, ToolCallStartEvent, ToolCallArgsEvent, ToolCallEndEvent, ToolResultEvent } from './agent-adapter.js';
4
4
  export interface MessageStateControllerConfig {
5
5
  onThreadSettled?: () => void;
@@ -28,6 +28,8 @@ export declare class MessageStateController implements ReactiveController {
28
28
  getToolCall(id: string): ToolCall | undefined;
29
29
  getActiveResponse(): AssistantResponse | null;
30
30
  startResponse(): AssistantResponse;
31
+ markResponseThinking(): void;
32
+ clearResponseThinking(): void;
31
33
  addTextToResponse(messageId: string, content: string, event?: MessageStartEvent): void;
32
34
  appendTextDelta(messageId: string, delta: string, event?: MessageDeltaEvent): void;
33
35
  markTextComplete(messageId: string, event?: MessageEndEvent): void;
@@ -41,6 +43,14 @@ export declare class MessageStateController implements ReactiveController {
41
43
  addMessageItem(item: MessageItem): void;
42
44
  addMessage(message: ChatMessage, event?: MessageStartEvent): void;
43
45
  getMessage(id: string): ChatMessage | undefined;
46
+ /**
47
+ * Inserts or upserts a client-only message, never touching `_activeResponse`.
48
+ * Unlike {@link addMessage}, this never finalizes an in-progress response -
49
+ * safe to call while a real reply is streaming.
50
+ */
51
+ addClientMessage(message: ClientMessageInput): string;
52
+ /** Removes a client message by id. No-ops if not found. Safe to call at any time. */
53
+ removeClientMessage(id: string): void;
44
54
  updateMessageStatus(id: string, status: ChatMessage['status'], event?: MessageEndEvent): void;
45
55
  updateMessageContent(id: string, content: string): void;
46
56
  removeMessageItem(index: number): void;
@@ -42,8 +42,25 @@ class MessageStateController {
42
42
  this.#notifyStateChange();
43
43
  return response;
44
44
  }
45
+ markResponseThinking() {
46
+ if (!this._activeResponse || this._activeResponse.isThinking) {
47
+ return;
48
+ }
49
+ this._activeResponse.isThinking = true;
50
+ this.#updateResponseInItems();
51
+ this.#notifyStateChange();
52
+ }
53
+ clearResponseThinking() {
54
+ if (!this._activeResponse || !this._activeResponse.isThinking) {
55
+ return;
56
+ }
57
+ this._activeResponse.isThinking = false;
58
+ this.#updateResponseInItems();
59
+ this.#notifyStateChange();
60
+ }
45
61
  addTextToResponse(messageId, content, event) {
46
62
  const response = this._activeResponse ?? this.startResponse();
63
+ response.isThinking = false;
47
64
  const lastChild = response.children[response.children.length - 1];
48
65
  if (lastChild?.type === "text" && lastChild.messageId === messageId) {
49
66
  lastChild.content = content;
@@ -64,6 +81,7 @@ class MessageStateController {
64
81
  }
65
82
  appendTextDelta(messageId, delta, event) {
66
83
  const response = this._activeResponse ?? this.startResponse();
84
+ response.isThinking = false;
67
85
  const lastChild = response.children[response.children.length - 1];
68
86
  if (lastChild?.type === "text" && lastChild.messageId === messageId) {
69
87
  lastChild.content += delta;
@@ -102,6 +120,7 @@ class MessageStateController {
102
120
  }
103
121
  addToolCallToResponse(toolCall, event) {
104
122
  const response = this._activeResponse ?? this.startResponse();
123
+ response.isThinking = false;
105
124
  const toolCallWithTimestamp = { ...toolCall, startTimestamp: Date.now() };
106
125
  this._toolCalls.set(toolCall.id, toolCallWithTimestamp);
107
126
  response.children.push({ type: "toolCall", data: toolCallWithTimestamp });
@@ -167,7 +186,7 @@ class MessageStateController {
167
186
  completeToolCallInResponse(toolCallId, result, event) {
168
187
  this.updateToolCallInResponse(toolCallId, {
169
188
  result,
170
- status: "complete"
189
+ status: event?.isError === true ? "error" : "complete"
171
190
  });
172
191
  if (event) {
173
192
  const streamEvent = {
@@ -255,6 +274,40 @@ class MessageStateController {
255
274
  const item = this._messageItems.find((i) => i.type === "message" && i.data.id === id);
256
275
  return item?.type === "message" ? item.data : void 0;
257
276
  }
277
+ /**
278
+ * Inserts or upserts a client-only message, never touching `_activeResponse`.
279
+ * Unlike {@link addMessage}, this never finalizes an in-progress response -
280
+ * safe to call while a real reply is streaming.
281
+ */
282
+ addClientMessage(message) {
283
+ const id = message.id ?? generateId();
284
+ const chatMessage = {
285
+ id,
286
+ role: "system",
287
+ content: message.content,
288
+ timestamp: Date.now(),
289
+ status: "complete",
290
+ clientOnly: true,
291
+ kind: message.kind,
292
+ header: message.header,
293
+ actions: message.actions
294
+ };
295
+ this._messageItems = [
296
+ ...this._messageItems.filter((item) => !(item.type === "message" && item.data.id === id)),
297
+ { type: "message", data: chatMessage }
298
+ ];
299
+ this.#notifyStateChange();
300
+ return id;
301
+ }
302
+ /** Removes a client message by id. No-ops if not found. Safe to call at any time. */
303
+ removeClientMessage(id) {
304
+ const hasMessage = this._messageItems.some((item) => item.type === "message" && item.data.id === id);
305
+ if (!hasMessage) {
306
+ return;
307
+ }
308
+ this._messageItems = this._messageItems.filter((item) => !(item.type === "message" && item.data.id === id));
309
+ this.#notifyStateChange();
310
+ }
258
311
  updateMessageStatus(id, status, event) {
259
312
  this._messageItems = this._messageItems.map((item) => {
260
313
  if (item.type === "message" && item.data.id === id) {
@@ -132,6 +132,7 @@ export interface ToolResultEvent {
132
132
  toolCallId: string;
133
133
  result: unknown;
134
134
  message: ChatMessage;
135
+ isError?: boolean;
135
136
  }
136
137
  export type StreamEvent = {
137
138
  type: 'message-start';
@@ -181,6 +182,31 @@ export interface ChatMessage {
181
182
  feedback?: ResponseFeedback;
182
183
  children?: ResponseItem[];
183
184
  clientOnly?: boolean;
185
+ kind?: ClientMessageKind;
186
+ header?: string;
187
+ actions?: ClientMessageAction[];
188
+ }
189
+ /**
190
+ * Visual treatment for a client-only message. `text` matches the plain,
191
+ * italic system-message style; the others render as a Forge inline-message
192
+ * banner with a matching icon.
193
+ */
194
+ export type ClientMessageKind = 'text' | 'info' | 'warning' | 'error' | 'success';
195
+ export interface ClientMessageAction {
196
+ id: string;
197
+ label: string;
198
+ onClick: () => void;
199
+ }
200
+ /**
201
+ * Input to {@link AiChatbotBase.addClientMessage}. Pass the same `id` on a
202
+ * later call to upsert (replace) a previously added client message.
203
+ */
204
+ export interface ClientMessageInput {
205
+ id?: string;
206
+ content: string;
207
+ kind?: ClientMessageKind;
208
+ header?: string;
209
+ actions?: ClientMessageAction[];
184
210
  }
185
211
  export interface ToolCall<TArgs = Record<string, unknown>> {
186
212
  id: string;
@@ -216,6 +242,7 @@ export interface AssistantResponse {
216
242
  timestamp: number;
217
243
  eventStream?: StreamEvent[];
218
244
  feedback?: ResponseFeedback;
245
+ isThinking?: boolean;
219
246
  }
220
247
  export interface FileAttachment {
221
248
  id: string;
@@ -0,0 +1,28 @@
1
+ import { LitElement, TemplateResult, CSSResult } from 'lit';
2
+ import { ClientMessageAction, ClientMessageKind } from '../ai-chatbot/types.js';
3
+ declare global {
4
+ interface HTMLElementTagNameMap {
5
+ 'forge-ai-client-message': AiClientMessageComponent;
6
+ }
7
+ }
8
+ export declare const AiClientMessageComponentTagName: keyof HTMLElementTagNameMap;
9
+ /**
10
+ * @tag forge-ai-client-message
11
+ *
12
+ * @summary Renders a client-only status message (never sent to the agent adapter) as
13
+ * either plain system-message text or a Forge inline-message banner, depending on `kind`.
14
+ *
15
+ * @description
16
+ * Used internally by `forge-ai-message-thread` to render messages added via
17
+ * `AiChatbotBase.addClientMessage()`. Not intended to be used standalone outside a
18
+ * message thread, but exported for direct Storybook/testing use.
19
+ */
20
+ export declare class AiClientMessageComponent extends LitElement {
21
+ #private;
22
+ static styles: CSSResult;
23
+ kind: ClientMessageKind;
24
+ header?: string;
25
+ content: string;
26
+ actions: ClientMessageAction[];
27
+ render(): TemplateResult;
28
+ }
@@ -0,0 +1,112 @@
1
+ import { unsafeCSS, LitElement, html, nothing } from "lit";
2
+ import { property, customElement } from "lit/decorators.js";
3
+ import { when } from "lit/directives/when.js";
4
+ import styles from "./ai-client-message.scss.mjs";
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __typeError = (msg) => {
8
+ throw TypeError(msg);
9
+ };
10
+ var __decorateClass = (decorators, target, key, kind) => {
11
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
12
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
13
+ if (decorator = decorators[i])
14
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
15
+ if (kind && result) __defProp(target, key, result);
16
+ return result;
17
+ };
18
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
19
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
20
+ 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);
21
+ var _AiClientMessageComponent_instances, icon_get, actions_get;
22
+ const AiClientMessageComponentTagName = "forge-ai-client-message";
23
+ const KIND_ICON_PATHS = {
24
+ info: "M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8",
25
+ warning: "M12 2 1 21h22zm0 3.99L19.53 19H4.47zM11 10v4h2v-4zm0 6v2h2v-2z",
26
+ error: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m1 15h-2v-2h2zm0-4h-2V7h2z",
27
+ success: "M21 7 9 19l-5.5-5.5 1.41-1.41L9 16.17 19.59 5.59z"
28
+ };
29
+ let AiClientMessageComponent = class extends LitElement {
30
+ constructor() {
31
+ super(...arguments);
32
+ __privateAdd(this, _AiClientMessageComponent_instances);
33
+ this.kind = "text";
34
+ this.content = "";
35
+ this.actions = [];
36
+ }
37
+ render() {
38
+ if (this.kind === "text") {
39
+ return html`
40
+ <div class="client-message--text">
41
+ <span>${this.content}</span>
42
+ ${__privateGet(this, _AiClientMessageComponent_instances, actions_get)}
43
+ </div>
44
+ `;
45
+ }
46
+ return html`
47
+ <div class="forge-inline-message">
48
+ ${__privateGet(this, _AiClientMessageComponent_instances, icon_get)} ${when(this.header, () => html`<div class="forge-inline-message__title">${this.header}</div>`)}
49
+ <div class="forge-inline-message__content">
50
+ <span>${this.content}</span>
51
+ ${__privateGet(this, _AiClientMessageComponent_instances, actions_get)}
52
+ </div>
53
+ </div>
54
+ `;
55
+ }
56
+ };
57
+ _AiClientMessageComponent_instances = /* @__PURE__ */ new WeakSet();
58
+ icon_get = function() {
59
+ if (this.kind === "text") {
60
+ return nothing;
61
+ }
62
+ return html`
63
+ <svg
64
+ class="forge-inline-message__icon"
65
+ xmlns="http://www.w3.org/2000/svg"
66
+ viewBox="0 0 24 24"
67
+ height="24"
68
+ width="24"
69
+ fill="currentColor"
70
+ aria-hidden="true">
71
+ <path fill="none" d="M0 0h24v24H0z" />
72
+ <path d="${KIND_ICON_PATHS[this.kind]}" />
73
+ </svg>
74
+ `;
75
+ };
76
+ actions_get = function() {
77
+ return when(
78
+ this.actions.length > 0,
79
+ () => html`
80
+ <div class="client-message__actions">
81
+ ${this.actions.map(
82
+ (action) => html`<button
83
+ type="button"
84
+ class="forge-button forge-button--outlined forge-button--dense"
85
+ @click=${() => action.onClick()}>
86
+ ${action.label}
87
+ </button>`
88
+ )}
89
+ </div>
90
+ `
91
+ );
92
+ };
93
+ AiClientMessageComponent.styles = unsafeCSS(styles);
94
+ __decorateClass([
95
+ property({ type: String, reflect: true })
96
+ ], AiClientMessageComponent.prototype, "kind", 2);
97
+ __decorateClass([
98
+ property({ type: String })
99
+ ], AiClientMessageComponent.prototype, "header", 2);
100
+ __decorateClass([
101
+ property({ type: String })
102
+ ], AiClientMessageComponent.prototype, "content", 2);
103
+ __decorateClass([
104
+ property({ attribute: false })
105
+ ], AiClientMessageComponent.prototype, "actions", 2);
106
+ AiClientMessageComponent = __decorateClass([
107
+ customElement(AiClientMessageComponentTagName)
108
+ ], AiClientMessageComponent);
109
+ export {
110
+ AiClientMessageComponent,
111
+ AiClientMessageComponentTagName
112
+ };
@@ -0,0 +1,4 @@
1
+ const styles = '/* prettier-ignore */\n/**\n * @license\n * Copyright Tyler Technologies, Inc.\n * License: Apache-2.0\n */\n.forge-inline-message {\n --_inline-message-background:var(--forge-inline-message-background, var(--forge-theme-info-container-low, #e3edf7));\n --_inline-message-color:var(--forge-inline-message-color, var(--forge-theme-text-high, rgba(0, 0, 0, 0.87)));\n --_inline-message-shape:var(--forge-inline-message-shape, calc(var(--forge-shape-medium, 4px) * var(--forge-shape-factor, 1)));\n --_inline-message-padding:var(--forge-inline-message-padding, var(--forge-spacing-small, 12px));\n --_inline-message-padding-inline:var(--forge-inline-message-padding-inline, var(--_inline-message-padding));\n --_inline-message-padding-block:var(--forge-inline-message-padding-block, var(--_inline-message-padding));\n --_inline-message-border-width:var(--forge-inline-message-border-width, var(--forge-border-thin, 1px));\n --_inline-message-border-style:var(--forge-inline-message-border-style, none);\n --_inline-message-border-color:var(--forge-inline-message-border-color, var(--forge-theme-info-container, #c7daf0));\n --_inline-message-gap:var(--forge-inline-message-gap, var(--forge-spacing-small, 12px));\n --_inline-message-icon-gap:var(--forge-inline-message-icon-gap, var(--_inline-message-gap));\n --_inline-message-content-gap:var(--forge-inline-message-content-gap, var(--_inline-message-gap));\n --_inline-message-icon-color:var(--forge-inline-message-icon-color, var(--forge-theme-on-info-container-low, #0b3768));\n}\n\n.forge-inline-message {\n display: block;\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 background: var(--_inline-message-background);\n color: var(--_inline-message-color);\n border-radius: var(--_inline-message-shape);\n border-width: var(--_inline-message-border-width);\n border-style: var(--_inline-message-border-style);\n border-color: var(--_inline-message-border-color);\n display: flex;\n align-items: center;\n gap: var(--_inline-message-icon-gap);\n box-sizing: border-box;\n padding-inline: var(--_inline-message-padding-inline);\n padding-block: var(--_inline-message-padding-block);\n display: grid;\n grid-template-columns: auto 1fr;\n grid-template-rows: auto 1fr;\n}\n\n.forge-inline-message:not(:has(.forge-inline-message__icon)) {\n grid-template-columns: 1fr;\n}\n\n.forge-inline-message__title {\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n font-family: var(--forge-typography-heading1-font-family, var(--forge-typography-font-family, "Roboto", sans-serif));\n font-size: var(--forge-typography-heading1-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-heading1-font-size-scale, 0.875)));\n font-weight: var(--forge-typography-heading1-font-weight, 500);\n line-height: var(--forge-typography-heading1-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-heading1-line-height-scale, 1.125)));\n letter-spacing: var(--forge-typography-heading1-letter-spacing, 0.0178571429em);\n text-transform: var(--forge-typography-heading1-text-transform, inherit);\n text-decoration: var(--forge-typography-heading1-text-decoration, inherit);\n}\n\n.forge-inline-message__icon {\n color: var(--_inline-message-icon-color);\n align-self: start;\n grid-row: 1/span 2;\n}\n\n/**\n * @license\n * Copyright Tyler Technologies, Inc.\n * License: Apache-2.0\n */\n.forge-button {\n --_button-primary-color:var(--forge-button-primary-color, var(--forge-theme-primary, #3f51b5));\n --_button-text-color:var(--forge-button-text-color, var(--_button-primary-color));\n --_button-disabled-color:var(--forge-button-disabled-color, var(--forge-theme-surface-container, #e0e0e0));\n --_button-padding:var(--forge-button-padding, var(--forge-spacing-medium, 16px));\n --_button-display:var(--forge-button-display, inline-grid);\n --_button-justify:var(--forge-button-justify, center);\n --_button-shape:var(--forge-button-shape, calc(var(--forge-shape-medium, 4px) * var(--forge-shape-factor, 1)));\n --_button-height:var(--forge-button-height, 36px);\n --_button-min-width:var(--forge-button-min-width, 64px);\n --_button-spacing:var(--forge-button-spacing, var(--forge-spacing-xsmall, 8px));\n --_button-border-width:var(--forge-button-border-width, medium);\n --_button-border-style:var(--forge-button-border-style, none);\n --_button-border-color:var(--forge-button-border-color, currentColor);\n --_button-shape-start-start-radius:var(--forge-button-shape-start-start-radius, var(--_button-shape));\n --_button-shape-start-end-radius:var(--forge-button-shape-start-end-radius, var(--_button-shape));\n --_button-shape-end-start-radius:var(--forge-button-shape-end-start-radius, var(--_button-shape));\n --_button-shape-end-end-radius:var(--forge-button-shape-end-end-radius, var(--_button-shape));\n --_button-padding-block:var(--forge-button-padding-block, var(--_button-0));\n --_button-padding-inline:var(--forge-button-padding-inline, var(--_button-padding));\n --_button-background:var(--forge-button-background, transparent);\n --_button-hover-background:var(--forge-button-hover-background, var(--_button-background));\n --_button-active-background:var(--forge-button-active-background, var(--_button-background));\n --_button-color:var(--forge-button-color, var(--_button-text-color));\n --_button-icon-size:var(--forge-button-icon-size, calc(var(--forge-typography-font-size, 1rem) * 1.125));\n --_button-shadow:var(--forge-button-shadow, none);\n --_button-hover-shadow:var(--forge-button-hover-shadow, none);\n --_button-active-shadow:var(--forge-button-active-shadow, none);\n --_button-cursor:var(--forge-button-cursor, pointer);\n --_button-transition-duration:var(--forge-button-transition-duration, var(--forge-animation-duration-short3, 150ms));\n --_button-transition-timing:var(--forge-button-transition-timing, var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1)));\n --_button-text-padding-inline:var(--forge-button-text-padding-inline, var(--forge-spacing-xsmall, 8px));\n --_button-outlined-background:var(--forge-button-outlined-background, transparent);\n --_button-outlined-color:var(--forge-button-outlined-color, var(--_button-primary-color));\n --_button-outlined-border-width:var(--forge-button-outlined-border-width, var(--forge-border-thin, 1px));\n --_button-outlined-border-style:var(--forge-button-outlined-border-style, solid);\n --_button-outlined-border-color:var(--forge-button-outlined-border-color, var(--_button-primary-color));\n --_button-tonal-background:var(--forge-button-tonal-background, var(--forge-theme-primary-container, #d1d5ed));\n --_button-tonal-disabled-background:var(--forge-button-tonal-disabled-background, var(--_button-disabled-color));\n --_button-tonal-color:var(--forge-button-tonal-color, var(--forge-theme-on-primary-container, #222c62));\n --_button-tonal-disabled-color:var(--forge-button-tonal-disabled-color, var(--_button-disabled-text-color));\n --_button-filled-background:var(--forge-button-filled-background, var(--_button-primary-color));\n --_button-filled-disabled-background:var(--forge-button-filled-disabled-background, var(--_button-disabled-color));\n --_button-filled-color:var(--forge-button-filled-color, var(--forge-theme-on-primary, #ffffff));\n --_button-filled-disabled-color:var(--forge-button-filled-disabled-color, var(--_button-disabled-text-color));\n --_button-raised-background:var(--forge-button-raised-background, var(--_button-primary-color));\n --_button-raised-disabled-background:var(--forge-button-raised-disabled-background, var(--_button-disabled-color));\n --_button-raised-color:var(--forge-button-raised-color, var(--forge-theme-on-primary, #ffffff));\n --_button-raised-disabled-color:var(--forge-button-raised-disabled-color, var(--_button-disabled-text-color));\n --_button-raised-shadow:var(--forge-button-raised-shadow, 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12));\n --_button-raised-hover-shadow:var(--forge-button-raised-hover-shadow, 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 --_button-raised-active-shadow:var(--forge-button-raised-active-shadow, 0px 5px 5px -3px rgba(0, 0, 0, 0.2), 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12));\n --_button-raised-disabled-shadow:var(--forge-button-raised-disabled-shadow, none);\n --_button-link-color:var(--forge-button-link-color, var(--_button-primary-color));\n --_button-link-text-decoration:var(--forge-button-link-text-decoration, underline);\n --_button-link-height:var(--forge-button-link-height, auto);\n --_button-link-padding:var(--forge-button-link-padding, 0);\n --_button-link-line-height:var(--forge-button-link-line-height, normal);\n --_button-link-width:var(--forge-button-link-width, auto);\n --_button-link-hover-text-decoration:var(--forge-button-link-hover-text-decoration, none);\n --_button-link-active-opacity:var(--forge-button-link-active-opacity, 0.65);\n --_button-link-transition-duration:var(--forge-button-link-transition-duration, var(--forge-animation-duration-short3, 150ms));\n --_button-link-transition-timing:var(--forge-button-link-transition-timing, var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1)));\n --_button-disabled-cursor:var(--forge-button-disabled-cursor, not-allowed);\n --_button-disabled-text-color:var(--forge-button-disabled-text-color, var(--forge-theme-text-low, rgba(0, 0, 0, 0.38)));\n --_button-disabled-background:var(--forge-button-disabled-background, transparent);\n --_button-disabled-border-color:var(--forge-button-disabled-border-color, var(--_button-disabled-color));\n --_button-disabled-shadow:var(--forge-button-disabled-shadow, none);\n --_button-dense-height:var(--forge-button-dense-height, 24px);\n --_button-pill-shape:var(--forge-button-pill-shape, calc(var(--forge-shape-full, 9999px) * var(--forge-shape-factor, 1)));\n --_button-pill-padding-inline:var(--forge-button-pill-padding-inline, var(--forge-spacing-small, 12px));\n --_button-focus-indicator-offset:var(--forge-button-focus-indicator-offset, 4px);\n --_button-text-focus-indicator-offset:var(--forge-button-text-focus-indicator-offset, 0px);\n --_button-link-focus-indicator-offset:var(--forge-button-link-focus-indicator-offset, 2px);\n --_button-popover-icon-transition-duration:var(--forge-button-popover-icon-transition-duration, var(--forge-animation-duration-short3, 150ms));\n --_button-popover-icon-transition-timing:var(--forge-button-popover-icon-transition-timing, var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1)));\n --_button-popover-icon-open-rotation:var(--forge-button-popover-icon-open-rotation, 180deg);\n}\n\n.forge-button {\n display: var(--_button-display);\n position: relative;\n outline: none;\n vertical-align: middle;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n font-family: var(--forge-typography-button-font-family, var(--forge-typography-font-family, "Roboto", sans-serif));\n font-size: var(--forge-typography-button-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-button-font-size-scale, 0.875)));\n font-weight: var(--forge-typography-button-font-weight, 500);\n line-height: var(--forge-typography-button-line-height, normal);\n letter-spacing: var(--forge-typography-button-letter-spacing, 0.0714285714em);\n text-transform: var(--forge-typography-button-text-transform, inherit);\n text-decoration: var(--forge-typography-button-text-decoration, inherit);\n position: relative;\n display: var(--_button-display);\n grid-auto-flow: column;\n align-items: center;\n justify-content: var(--_button-justify);\n gap: var(--_button-spacing);\n z-index: 0;\n box-sizing: border-box;\n min-inline-size: var(--_button-min-width);\n height: var(--_button-height);\n inline-size: 100%;\n border-width: var(--_button-border-width);\n border-style: var(--_button-border-style);\n border-color: var(--_button-border-color);\n border-start-start-radius: var(--_button-shape-start-start-radius);\n border-start-end-radius: var(--_button-shape-start-end-radius);\n border-end-start-radius: var(--_button-shape-end-start-radius);\n border-end-end-radius: var(--_button-shape-end-end-radius);\n padding-block: var(--_button-padding-block);\n padding-inline: var(--_button-padding-inline);\n box-shadow: var(--_button-shadow);\n outline: none;\n user-select: none;\n -webkit-appearance: none;\n vertical-align: middle;\n text-decoration: none;\n white-space: nowrap;\n background: var(--_button-background);\n color: var(--_button-color);\n cursor: var(--_button-cursor);\n transition-property: box-shadow, background;\n transition-duration: var(--_button-transition-duration);\n transition-timing-function: var(--_button-transition-timing);\n}\n\n.forge-button::-moz-focus-inner {\n padding: 0;\n border: 0;\n}\n\n.forge-button:hover {\n --_button-shadow:var(--_button-hover-shadow);\n background: var(--_button-hover-background);\n}\n\n.forge-button:active {\n --_button-shadow:var(--_button-active-shadow);\n background: var(--_button-active-background);\n}\n\n.forge-button {\n position: relative;\n inline-size: auto;\n}\n\n.forge-button:not(:disabled):not(.forge-button--link) {\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\n.forge-button:not(:disabled):not(.forge-button--link)::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\n.forge-button:not(:disabled):not(.forge-button--link):hover::before {\n background-color: var(--_state-layer-hover-color);\n opacity: var(--_state-layer-hover-opacity);\n}\n\n.forge-button:not(:disabled):not(.forge-button--link):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@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.forge-button:not(:disabled) {\n outline: none;\n}\n\n.forge-button:not(:disabled):focus-visible::after {\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}\n\n.forge-button:not(:disabled):focus-visible::after {\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-outward-grow, forge-focus-indicator-outward-shrink;\n border-end-end-radius: calc(var(--_focus-indicator-shape-end-end) + var(--_focus-indicator-outward-offset));\n border-end-start-radius: calc(var(--_focus-indicator-shape-end-start) + var(--_focus-indicator-outward-offset));\n border-start-end-radius: calc(var(--_focus-indicator-shape-start-end) + var(--_focus-indicator-outward-offset));\n border-start-start-radius: calc(var(--_focus-indicator-shape-start-start) + var(--_focus-indicator-outward-offset));\n inset: calc(-1 * var(--_focus-indicator-outward-offset));\n outline: var(--_focus-indicator-width) solid currentColor;\n content: "";\n display: block;\n}\n\n.forge-button:not(:disabled) {\n --forge-focus-indicator-color: var(--_button-primary-color);\n}\n\n.forge-button:disabled {\n cursor: var(--_button-disabled-cursor);\n --_button-background:var(--_button-disabled-background);\n --_button-color:var(--_button-disabled-text-color);\n --_button-shadow:var(--_button-disabled-shadow);\n pointer-events: none;\n pointer-events: initial;\n}\n\n.forge-button:where(:not(.forge-button--outlined, .forge-button--tonal, .forge-button--filled, .forge-button--raised, .forge-button--link)), .forge-button--text {\n --_button-padding-inline:var(--_button-text-padding-inline);\n}\n\n.forge-button--outlined {\n --_button-background:var(--_button-outlined-background);\n --_button-color:var(--_button-outlined-color);\n --_button-border-width:var(--_button-outlined-border-width);\n --_button-border-style:var(--_button-outlined-border-style);\n --_button-border-color:var(--_button-outlined-border-color);\n}\n\n.forge-button--outlined:disabled {\n --_button-border-color:var(--_button-disabled-border-color);\n}\n\n.forge-button--tonal {\n --_button-background:var(--_button-tonal-background);\n --_button-color:var(--_button-tonal-color);\n}\n\n.forge-button--tonal:disabled {\n --_button-background:var(--_button-tonal-disabled-background);\n --_button-color:var(--_button-tonal-disabled-color);\n}\n\n.forge-button--filled, .forge-button--raised {\n --_button-background:var(--_button-filled-background);\n --_button-color:var(--_button-filled-color);\n --forge-state-layer-color: var(--_button-filled-color);\n}\n\n.forge-button--filled:disabled, .forge-button--raised:disabled {\n --_button-background:var(--_button-filled-disabled-background);\n --_button-color:var(--_button-filled-disabled-color);\n}\n\n.forge-button--raised {\n --_button-background:var(--_button-raised-background);\n --_button-color:var(--_button-raised-color);\n --_button-shadow:var(--_button-raised-shadow);\n}\n\n.forge-button--raised:hover {\n --_button-shadow:var(--_button-raised-hover-shadow);\n}\n\n.forge-button--raised:active {\n --_button-shadow:var(--_button-raised-active-shadow);\n}\n\n.forge-button--raised:disabled {\n --_button-background:var(--_button-raised-disabled-background);\n --_button-color:var(--_button-raised-disabled-color);\n --_button-shadow:var(--_button-raised-disabled-shadow);\n}\n\n.forge-button--link {\n --_button-color:var(--_button-link-color);\n --_button-height:var(--_button-link-height);\n --_button-padding:var(--_button-link-padding);\n --_button-focus-indicator-offset:var(--_button-link-focus-indicator-offset);\n text-decoration: var(--_button-link-text-decoration);\n line-height: var(--_button-link-line-height);\n transition: opacity var(--_button-link-transition-duration) var(--_button-link-transition-timing);\n inline-size: var(--_button-link-width);\n}\n\n.forge-button--link:hover {\n text-decoration: var(--_button-link-hover-text-decoration);\n}\n\n.forge-button--link:active {\n opacity: var(--_button-link-active-opacity);\n}\n\n.forge-button--pill {\n --_button-shape:var(--_button-pill-shape);\n --_button-padding-inline:var(--_button-pill-padding-inline);\n --forge-focus-indicator-shape: var(--_button-pill-shape);\n}\n\n.forge-button {\n --forge-icon-font-size: var(--_button-icon-size);\n}\n\n.forge-button--dense {\n --_button-height:var(--_button-dense-height);\n}\n\n:host {\n display: block;\n}\n\n.forge-inline-message {\n --forge-inline-message-border-style: solid;\n}\n.forge-inline-message__title {\n font-weight: bold;\n}\n.forge-inline-message__content {\n display: flex;\n flex-direction: column;\n gap: var(--forge-spacing-xsmall, 8px);\n overflow-wrap: anywhere;\n}\n.forge-inline-message:not(:has(.forge-inline-message__title)) .forge-inline-message__icon {\n align-self: center;\n}\n.forge-inline-message:not(:has(.forge-inline-message__title)) .forge-inline-message__content {\n grid-row: 1/-1;\n align-self: center;\n}\n\n:host([kind=info]) .forge-inline-message {\n --forge-inline-message-background: var(--forge-theme-info-container-low, #e3edf7);\n --forge-inline-message-color: var(--forge-theme-on-info-container-low, #0b3768);\n --forge-inline-message-icon-color: var(--forge-theme-on-info-container-low, #0b3768);\n --forge-inline-message-border-color: var(--forge-theme-info-container, #c7daf0);\n}\n\n:host([kind=warning]) .forge-inline-message {\n --forge-inline-message-background: var(--forge-theme-warning-container-low, #f9e9e0);\n --forge-inline-message-color: var(--forge-theme-on-warning-container-low, #712700);\n --forge-inline-message-icon-color: var(--forge-theme-on-warning-container-low, #712700);\n --forge-inline-message-border-color: var(--forge-theme-warning-container, #f4d3c2);\n}\n\n:host([kind=error]) .forge-inline-message {\n --forge-inline-message-background: var(--forge-theme-error-container-low, #f6e0e4);\n --forge-inline-message-color: var(--forge-theme-on-error-container-low, #5f0011);\n --forge-inline-message-icon-color: var(--forge-theme-on-error-container-low, #5f0011);\n --forge-inline-message-border-color: var(--forge-theme-error-container, #ecc2c9);\n}\n\n:host([kind=success]) .forge-inline-message {\n --forge-inline-message-background: var(--forge-theme-success-container-low, #e6efe6);\n --forge-inline-message-color: var(--forge-theme-on-success-container-low, #19441b);\n --forge-inline-message-icon-color: var(--forge-theme-on-success-container-low, #19441b);\n --forge-inline-message-border-color: var(--forge-theme-success-container, #cde0ce);\n}\n\n.client-message--text {\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n font-family: var(--forge-typography-subheading2-font-family, var(--forge-typography-font-family, "Roboto", sans-serif));\n font-size: var(--forge-typography-subheading2-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-subheading2-font-size-scale, 1)));\n font-weight: var(--forge-typography-subheading2-font-weight, 400);\n line-height: var(--forge-typography-subheading2-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-subheading2-line-height-scale, 1.25)));\n letter-spacing: var(--forge-typography-subheading2-letter-spacing, normal);\n text-transform: var(--forge-typography-subheading2-text-transform, inherit);\n text-decoration: var(--forge-typography-subheading2-text-decoration, inherit);\n display: flex;\n flex-direction: column;\n gap: var(--forge-spacing-xxsmall, 4px);\n padding-block: var(--forge-spacing-small, 12px);\n color: var(--forge-theme-text-medium, rgba(0, 0, 0, 0.6));\n font-style: italic;\n}\n\n.client-message__actions {\n display: flex;\n gap: var(--forge-spacing-xsmall, 8px);\n font-style: normal;\n}\n.client-message__actions .forge-button {\n --forge-button-outlined-color: currentColor;\n --forge-button-outlined-border-color: currentColor;\n}';
2
+ export {
3
+ styles as default
4
+ };
@@ -0,0 +1 @@
1
+ export { AiClientMessageComponent, AiClientMessageComponentTagName } from './ai-client-message.js';
@@ -0,0 +1,5 @@
1
+ import { AiClientMessageComponent, AiClientMessageComponentTagName } from "./ai-client-message.mjs";
2
+ export {
3
+ AiClientMessageComponent,
4
+ AiClientMessageComponentTagName
5
+ };
@@ -67,6 +67,7 @@ export declare class AiConversationsPanelComponent extends LitElement {
67
67
  selectedThreadId: string | null;
68
68
  showConversationRename: boolean;
69
69
  showConversationDelete: boolean;
70
+ loading: boolean;
70
71
  private _viewState;
71
72
  private _isSearching;
72
73
  private _searchResults;
@@ -27,7 +27,7 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
27
27
  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);
28
28
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
29
29
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
30
- var _searchDebounceTimeout, _deleteThreadController, _recentChatsScrollController, _searchChatsScrollController, _AiConversationsPanelComponent_instances, shouldEnableRecentPagination_get, shouldEnableSearchPagination_get, attachScrollController_fn, displayedThreads_get, handleSearch_fn, handleSearchInput_fn, handleRecentChatsLoadMore_fn, handleSearchChatsLoadMore_fn, transitionToSearch_fn, transitionToMain_fn, handleBackClick_fn, handleThreadSelect_fn, handleNewChatClick_fn, handleSearchChatsClick_fn, handleCloseClick_fn, handleMenuRename_fn, handleMenuOpen_fn, handleMenuClose_fn, handleMenuDeleteClick_fn, handleEditSave_fn, handleEditCancel_fn, _header, headerSearch_get, _chatsLabel, searchFieldSearch_get, emptyState_get, loadingMoreIndicator_get, threadList_get, threadListContainer_get, _chatActionsList;
30
+ var _searchDebounceTimeout, _deleteThreadController, _recentChatsScrollController, _searchChatsScrollController, _AiConversationsPanelComponent_instances, shouldEnableRecentPagination_get, shouldEnableSearchPagination_get, attachScrollController_fn, displayedThreads_get, handleSearch_fn, handleSearchInput_fn, handleRecentChatsLoadMore_fn, handleSearchChatsLoadMore_fn, transitionToSearch_fn, transitionToMain_fn, handleBackClick_fn, handleThreadSelect_fn, handleNewChatClick_fn, handleSearchChatsClick_fn, handleCloseClick_fn, handleMenuRename_fn, handleMenuOpen_fn, handleMenuClose_fn, handleMenuDeleteClick_fn, handleEditSave_fn, handleEditCancel_fn, _header, headerSearch_get, _chatsLabel, searchFieldSearch_get, emptyState_get, loadingMoreIndicator_get, _loadingIndicator, threadList_get, threadListContainer_get, _chatActionsList;
31
31
  const AiConversationsPanelComponentTagName = "forge-ai-conversations-panel";
32
32
  let AiConversationsPanelComponent = class extends LitElement {
33
33
  constructor() {
@@ -38,6 +38,7 @@ let AiConversationsPanelComponent = class extends LitElement {
38
38
  this.selectedThreadId = null;
39
39
  this.showConversationRename = false;
40
40
  this.showConversationDelete = false;
41
+ this.loading = false;
41
42
  this._viewState = "main";
42
43
  this._isSearching = false;
43
44
  this._searchResults = [];
@@ -94,6 +95,11 @@ let AiConversationsPanelComponent = class extends LitElement {
94
95
  </div>
95
96
  `);
96
97
  __privateAdd(this, _chatsLabel, html`<div class="chats-label">Recent chats</div>`);
98
+ __privateAdd(this, _loadingIndicator, html`
99
+ <div class="loading-indicator">
100
+ <forge-ai-spinner size="small"></forge-ai-spinner>
101
+ </div>
102
+ `);
97
103
  __privateAdd(this, _chatActionsList, html`
98
104
  <ul class="forge-list forge-list--dense forge-list--navlist chat-actions-list" role="list">
99
105
  <li class="forge-list-item new-chat-item" role="listitem">
@@ -427,7 +433,7 @@ searchFieldSearch_get = function() {
427
433
  `;
428
434
  };
429
435
  emptyState_get = function() {
430
- const message = this._viewState === "search" && this._searchQuery.trim() ? "No conversations found" : "No conversations yet";
436
+ const message = this._viewState === "search" && this._searchQuery.trim() ? "No chats found" : "No chats yet";
431
437
  return html`
432
438
  <div class="empty-state">
433
439
  <p>${message}</p>
@@ -445,9 +451,13 @@ loadingMoreIndicator_get = function() {
445
451
  </div>
446
452
  `;
447
453
  };
454
+ _loadingIndicator = /* @__PURE__ */ new WeakMap();
448
455
  threadList_get = function() {
449
456
  const threads = __privateGet(this, _AiConversationsPanelComponent_instances, displayedThreads_get);
450
457
  if (threads.length === 0) {
458
+ if (this.loading && this._viewState === "main") {
459
+ return __privateGet(this, _loadingIndicator);
460
+ }
451
461
  return __privateGet(this, _AiConversationsPanelComponent_instances, emptyState_get);
452
462
  }
453
463
  return html`
@@ -519,6 +529,9 @@ __decorateClass([
519
529
  __decorateClass([
520
530
  property({ type: Boolean, attribute: "show-conversation-delete" })
521
531
  ], AiConversationsPanelComponent.prototype, "showConversationDelete", 2);
532
+ __decorateClass([
533
+ property({ type: Boolean, reflect: true })
534
+ ], AiConversationsPanelComponent.prototype, "loading", 2);
522
535
  __decorateClass([
523
536
  state()
524
537
  ], AiConversationsPanelComponent.prototype, "_viewState", 2);