@tylertech/forge-ai 0.14.0 → 0.15.0
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.
- package/custom-elements.json +520 -278
- package/dist/ai-agent-selector/ai-agent-selector.mjs +1 -1
- package/dist/ai-chat-header/ai-chat-header.d.ts +5 -0
- package/dist/ai-chat-header/ai-chat-header.mjs +9 -3
- package/dist/ai-chat-header/ai-chat-header.scss.mjs +1 -1
- package/dist/ai-chatbot/agent-adapter.d.ts +1 -0
- package/dist/ai-chatbot/ai-chatbot-base.mjs +0 -1
- package/dist/ai-chatbot/ai-chatbot.d.ts +5 -1
- package/dist/ai-chatbot/ai-chatbot.mjs +18 -5
- package/dist/ai-chatbot/index.d.ts +1 -0
- package/dist/ai-chatbot/index.mjs +4 -1
- package/dist/ai-chatbot/message-state-controller.d.ts +8 -11
- package/dist/ai-chatbot/message-state-controller.mjs +7 -129
- package/dist/ai-chatbot/request-serialization.d.ts +33 -0
- package/dist/ai-chatbot/request-serialization.mjs +31 -0
- package/dist/ai-chatbot/types.d.ts +0 -73
- package/dist/ai-chatbot-launcher/ai-chatbot-launcher.d.ts +14 -2
- package/dist/ai-chatbot-launcher/ai-chatbot-launcher.mjs +47 -11
- package/dist/ai-chatbot-launcher/ai-chatbot-launcher.scss.mjs +1 -1
- package/dist/ai-conversations-panel/ai-conversations-panel.d.ts +10 -0
- package/dist/ai-conversations-panel/ai-conversations-panel.mjs +68 -7
- package/dist/ai-conversations-panel/ai-conversations-panel.scss.mjs +1 -1
- package/dist/ai-dialog/ai-dialog.mjs +1 -1
- package/dist/ai-dropdown-menu/ai-dropdown-menu.mjs +1 -1
- package/dist/ai-dropdown-menu/index.d.ts +1 -1
- package/dist/ai-edit-thread/ai-edit-thread.d.ts +5 -0
- package/dist/ai-edit-thread/ai-edit-thread.mjs +16 -9
- package/dist/ai-error-message/ai-error-message.d.ts +7 -1
- package/dist/ai-error-message/ai-error-message.mjs +40 -5
- package/dist/ai-error-message/ai-error-message.scss.mjs +1 -1
- package/dist/ai-error-message/index.d.ts +1 -0
- package/dist/ai-fab/ai-fab.d.ts +2 -0
- package/dist/ai-fab/ai-fab.mjs +5 -1
- package/dist/ai-icon-button/ai-icon-button.mjs +4 -1
- package/dist/ai-message-thread/ai-message-thread.mjs +1 -1
- package/dist/ai-sidebar/ai-sidebar.mjs +2 -2
- package/dist/ai-thread-actions-menu/ai-thread-actions-menu.d.ts +5 -0
- package/dist/ai-thread-actions-menu/ai-thread-actions-menu.mjs +6 -2
- package/dist/ai-threads-search/ai-threads-search.d.ts +13 -1
- package/dist/ai-threads-search/ai-threads-search.mjs +87 -30
- package/dist/ai-threads-search/ai-threads-search.scss.mjs +1 -1
- package/dist/ai-tool-call-indicator/ai-tool-call-indicator.scss.mjs +1 -1
- package/dist/ai-voice-input/ai-voice-input.mjs +2 -2
- package/dist/core/chatbot-core-controller.mjs +6 -8
- package/dist/index.mjs +4 -1
- package/package.json +1 -1
|
@@ -58,7 +58,7 @@ class MessageStateController {
|
|
|
58
58
|
this.#updateResponseInItems();
|
|
59
59
|
this.#notifyStateChange();
|
|
60
60
|
}
|
|
61
|
-
addTextToResponse(messageId, content
|
|
61
|
+
addTextToResponse(messageId, content) {
|
|
62
62
|
const response = this._activeResponse ?? this.startResponse();
|
|
63
63
|
response.isThinking = false;
|
|
64
64
|
const lastChild = response.children[response.children.length - 1];
|
|
@@ -68,18 +68,10 @@ class MessageStateController {
|
|
|
68
68
|
} else {
|
|
69
69
|
response.children.push({ type: "text", messageId, content, status: "streaming" });
|
|
70
70
|
}
|
|
71
|
-
if (event) {
|
|
72
|
-
this.#appendEventToResponse({
|
|
73
|
-
type: "message-start",
|
|
74
|
-
timestamp: Date.now(),
|
|
75
|
-
data: event,
|
|
76
|
-
rawEvent: event.rawEvent
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
71
|
this.#updateResponseInItems();
|
|
80
72
|
this.#notifyStateChange();
|
|
81
73
|
}
|
|
82
|
-
appendTextDelta(messageId, delta
|
|
74
|
+
appendTextDelta(messageId, delta) {
|
|
83
75
|
const response = this._activeResponse ?? this.startResponse();
|
|
84
76
|
response.isThinking = false;
|
|
85
77
|
const lastChild = response.children[response.children.length - 1];
|
|
@@ -88,18 +80,10 @@ class MessageStateController {
|
|
|
88
80
|
} else {
|
|
89
81
|
response.children.push({ type: "text", messageId, content: delta, status: "streaming" });
|
|
90
82
|
}
|
|
91
|
-
if (event) {
|
|
92
|
-
this.#appendEventToResponse({
|
|
93
|
-
type: "message-delta",
|
|
94
|
-
timestamp: Date.now(),
|
|
95
|
-
data: event,
|
|
96
|
-
rawEvent: event.rawEvent
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
83
|
this.#updateResponseInItems();
|
|
100
84
|
this.#notifyStateChange();
|
|
101
85
|
}
|
|
102
|
-
markTextComplete(messageId
|
|
86
|
+
markTextComplete(messageId) {
|
|
103
87
|
if (!this._activeResponse) {
|
|
104
88
|
return;
|
|
105
89
|
}
|
|
@@ -107,37 +91,19 @@ class MessageStateController {
|
|
|
107
91
|
if (textChild && textChild.type === "text") {
|
|
108
92
|
textChild.status = "complete";
|
|
109
93
|
}
|
|
110
|
-
if (event) {
|
|
111
|
-
this.#appendEventToResponse({
|
|
112
|
-
type: "message-end",
|
|
113
|
-
timestamp: Date.now(),
|
|
114
|
-
data: event,
|
|
115
|
-
rawEvent: event.rawEvent
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
94
|
this.#updateResponseInItems();
|
|
119
95
|
this.#notifyStateChange();
|
|
120
96
|
}
|
|
121
|
-
addToolCallToResponse(toolCall
|
|
97
|
+
addToolCallToResponse(toolCall) {
|
|
122
98
|
const response = this._activeResponse ?? this.startResponse();
|
|
123
99
|
response.isThinking = false;
|
|
124
100
|
const toolCallWithTimestamp = { ...toolCall, startTimestamp: Date.now() };
|
|
125
101
|
this._toolCalls.set(toolCall.id, toolCallWithTimestamp);
|
|
126
102
|
response.children.push({ type: "toolCall", data: toolCallWithTimestamp });
|
|
127
|
-
if (event) {
|
|
128
|
-
const streamEvent = {
|
|
129
|
-
type: "tool-call-start",
|
|
130
|
-
timestamp: Date.now(),
|
|
131
|
-
data: event,
|
|
132
|
-
rawEvent: event.rawEvent
|
|
133
|
-
};
|
|
134
|
-
this.#appendEventToResponse(streamEvent);
|
|
135
|
-
this.#appendEventToToolCallInResponse(toolCall.id, streamEvent);
|
|
136
|
-
}
|
|
137
103
|
this.#updateResponseInItems();
|
|
138
104
|
this.#notifyStateChange();
|
|
139
105
|
}
|
|
140
|
-
updateToolCallInResponse(toolCallId, updates
|
|
106
|
+
updateToolCallInResponse(toolCallId, updates) {
|
|
141
107
|
const toolCall = this._toolCalls.get(toolCallId);
|
|
142
108
|
if (!toolCall) {
|
|
143
109
|
return;
|
|
@@ -157,29 +123,6 @@ class MessageStateController {
|
|
|
157
123
|
}
|
|
158
124
|
}
|
|
159
125
|
}
|
|
160
|
-
if (eventData) {
|
|
161
|
-
if (eventData.eventType === "tool-call-args") {
|
|
162
|
-
const argsEvent = eventData.event;
|
|
163
|
-
const streamEvent = {
|
|
164
|
-
type: "tool-call-args",
|
|
165
|
-
timestamp: Date.now(),
|
|
166
|
-
data: argsEvent,
|
|
167
|
-
rawEvent: argsEvent.rawEvent
|
|
168
|
-
};
|
|
169
|
-
this.#appendEventToResponse(streamEvent);
|
|
170
|
-
this.#appendEventToToolCallInResponse(toolCallId, streamEvent);
|
|
171
|
-
} else {
|
|
172
|
-
const endEvent = eventData.event;
|
|
173
|
-
const streamEvent = {
|
|
174
|
-
type: "tool-call-end",
|
|
175
|
-
timestamp: Date.now(),
|
|
176
|
-
data: endEvent,
|
|
177
|
-
rawEvent: endEvent.rawEvent
|
|
178
|
-
};
|
|
179
|
-
this.#appendEventToResponse(streamEvent);
|
|
180
|
-
this.#appendEventToToolCallInResponse(toolCallId, streamEvent);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
126
|
this.#updateResponseInItems();
|
|
184
127
|
this.#notifyStateChange();
|
|
185
128
|
}
|
|
@@ -188,16 +131,6 @@ class MessageStateController {
|
|
|
188
131
|
result,
|
|
189
132
|
status: event?.isError === true ? "error" : "complete"
|
|
190
133
|
});
|
|
191
|
-
if (event) {
|
|
192
|
-
const streamEvent = {
|
|
193
|
-
type: "tool-result",
|
|
194
|
-
timestamp: Date.now(),
|
|
195
|
-
data: event,
|
|
196
|
-
rawEvent: event.rawEvent
|
|
197
|
-
};
|
|
198
|
-
this.#appendEventToResponse(streamEvent);
|
|
199
|
-
this.#appendEventToToolCallInResponse(toolCallId, streamEvent);
|
|
200
|
-
}
|
|
201
134
|
}
|
|
202
135
|
tryFinalizeResponse() {
|
|
203
136
|
if (!this._activeResponse) {
|
|
@@ -221,29 +154,6 @@ class MessageStateController {
|
|
|
221
154
|
return item;
|
|
222
155
|
});
|
|
223
156
|
}
|
|
224
|
-
#appendEventToResponse(event) {
|
|
225
|
-
if (!this._activeResponse) {
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
this._activeResponse.eventStream = [...this._activeResponse.eventStream || [], event];
|
|
229
|
-
}
|
|
230
|
-
#appendEventToToolCallInResponse(toolCallId, event) {
|
|
231
|
-
const toolCall = this._toolCalls.get(toolCallId);
|
|
232
|
-
if (!toolCall) {
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
const eventStream = [...toolCall.eventStream || [], event];
|
|
236
|
-
const updated = { ...toolCall, eventStream };
|
|
237
|
-
this._toolCalls.set(toolCallId, updated);
|
|
238
|
-
if (this._activeResponse) {
|
|
239
|
-
for (const child of this._activeResponse.children) {
|
|
240
|
-
if (child.type === "toolCall" && child.data.id === toolCallId) {
|
|
241
|
-
child.data = updated;
|
|
242
|
-
break;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
157
|
#notifyStateChange() {
|
|
248
158
|
this._host.requestUpdate();
|
|
249
159
|
}
|
|
@@ -251,21 +161,13 @@ class MessageStateController {
|
|
|
251
161
|
this._messageItems = [...this._messageItems, item];
|
|
252
162
|
this.#notifyStateChange();
|
|
253
163
|
}
|
|
254
|
-
addMessage(message
|
|
164
|
+
addMessage(message) {
|
|
255
165
|
this.tryFinalizeResponse();
|
|
256
166
|
const existing = this.getMessage(message.id);
|
|
257
167
|
if (existing) {
|
|
258
168
|
return;
|
|
259
169
|
}
|
|
260
170
|
this.addMessageItem({ type: "message", data: message });
|
|
261
|
-
if (event) {
|
|
262
|
-
this.#appendEventToMessage(message.id, {
|
|
263
|
-
type: "message-start",
|
|
264
|
-
timestamp: Date.now(),
|
|
265
|
-
data: event,
|
|
266
|
-
rawEvent: event.rawEvent
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
171
|
if (message.status === "complete" || message.status === "error") {
|
|
270
172
|
this._config.onThreadSettled?.();
|
|
271
173
|
}
|
|
@@ -308,21 +210,13 @@ class MessageStateController {
|
|
|
308
210
|
this._messageItems = this._messageItems.filter((item) => !(item.type === "message" && item.data.id === id));
|
|
309
211
|
this.#notifyStateChange();
|
|
310
212
|
}
|
|
311
|
-
updateMessageStatus(id, status
|
|
213
|
+
updateMessageStatus(id, status) {
|
|
312
214
|
this._messageItems = this._messageItems.map((item) => {
|
|
313
215
|
if (item.type === "message" && item.data.id === id) {
|
|
314
216
|
return { ...item, data: { ...item.data, status } };
|
|
315
217
|
}
|
|
316
218
|
return item;
|
|
317
219
|
});
|
|
318
|
-
if (event) {
|
|
319
|
-
this.#appendEventToMessage(id, {
|
|
320
|
-
type: "message-end",
|
|
321
|
-
timestamp: Date.now(),
|
|
322
|
-
data: event,
|
|
323
|
-
rawEvent: event.rawEvent
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
220
|
this.#notifyStateChange();
|
|
327
221
|
if (status === "complete" || status === "error") {
|
|
328
222
|
this._config.onThreadSettled?.();
|
|
@@ -373,7 +267,6 @@ class MessageStateController {
|
|
|
373
267
|
timestamp: response.timestamp,
|
|
374
268
|
status: response.status === "streaming" ? "streaming" : response.status === "error" ? "error" : "complete",
|
|
375
269
|
toolCalls: toolCalls.length ? toolCalls : void 0,
|
|
376
|
-
eventStream: response.eventStream,
|
|
377
270
|
feedback: response.feedback,
|
|
378
271
|
children: response.children
|
|
379
272
|
};
|
|
@@ -418,7 +311,6 @@ class MessageStateController {
|
|
|
418
311
|
children,
|
|
419
312
|
status: msg.status === "streaming" ? "streaming" : "complete",
|
|
420
313
|
timestamp: msg.timestamp,
|
|
421
|
-
eventStream: msg.eventStream,
|
|
422
314
|
feedback: msg.feedback
|
|
423
315
|
};
|
|
424
316
|
messageItems.push({ type: "assistant", data: response });
|
|
@@ -436,20 +328,6 @@ class MessageStateController {
|
|
|
436
328
|
this.#notifyStateChange();
|
|
437
329
|
}
|
|
438
330
|
}
|
|
439
|
-
#appendEventToMessage(id, event) {
|
|
440
|
-
const messageExists = this._messageItems.some((item) => item.type === "message" && item.data.id === id);
|
|
441
|
-
if (!messageExists) {
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
|
-
this._messageItems = this._messageItems.map((item) => {
|
|
445
|
-
if (item.type === "message" && item.data.id === id) {
|
|
446
|
-
const eventStream = [...item.data.eventStream || [], event];
|
|
447
|
-
return { ...item, data: { ...item.data, eventStream } };
|
|
448
|
-
}
|
|
449
|
-
return item;
|
|
450
|
-
});
|
|
451
|
-
this.#notifyStateChange();
|
|
452
|
-
}
|
|
453
331
|
}
|
|
454
332
|
export {
|
|
455
333
|
MessageStateController
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ChatMessage, ToolCall } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Wire shape for a tool call sent back to an agent endpoint: the final `args`
|
|
4
|
+
* and its `result`, and nothing else. Local-only fields (`eventStream`,
|
|
5
|
+
* `argsBuffer`, `children`, timing metadata) are deliberately absent - no
|
|
6
|
+
* backend reads them and they grow without bound across turns.
|
|
7
|
+
*/
|
|
8
|
+
export interface RequestToolCall {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
args: Record<string, unknown>;
|
|
12
|
+
status: ToolCall['status'];
|
|
13
|
+
result?: unknown;
|
|
14
|
+
}
|
|
15
|
+
/** Wire shape for a single message sent to an agent endpoint. */
|
|
16
|
+
export interface RequestMessage {
|
|
17
|
+
role: ChatMessage['role'];
|
|
18
|
+
content: string;
|
|
19
|
+
toolCallId?: string;
|
|
20
|
+
toolCalls?: RequestToolCall[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Projects a tool call onto its wire shape. This is the single boundary at which
|
|
24
|
+
* local state is dropped, so adapters never have to remember to omit it.
|
|
25
|
+
*/
|
|
26
|
+
export declare function toRequestToolCall(toolCall: ToolCall): RequestToolCall;
|
|
27
|
+
/**
|
|
28
|
+
* Projects the thread onto the messages an agent endpoint is sent: client-only
|
|
29
|
+
* messages and empty assistant turns are dropped, and every remaining message is
|
|
30
|
+
* rebuilt field by field rather than spread, so no local state can leak into a
|
|
31
|
+
* request body.
|
|
32
|
+
*/
|
|
33
|
+
export declare function toRequestMessages(messages: ChatMessage[]): RequestMessage[];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
function toRequestToolCall(toolCall) {
|
|
2
|
+
const { id, name, args, status, result } = toolCall;
|
|
3
|
+
return {
|
|
4
|
+
id,
|
|
5
|
+
name,
|
|
6
|
+
args,
|
|
7
|
+
status,
|
|
8
|
+
...result === void 0 ? {} : { result }
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
function toRequestMessages(messages) {
|
|
12
|
+
return messages.filter(isSendableMessage).map((message) => ({
|
|
13
|
+
role: message.role,
|
|
14
|
+
content: message.content,
|
|
15
|
+
...message.toolCallId ? { toolCallId: message.toolCallId } : {},
|
|
16
|
+
...message.toolCalls?.length ? { toolCalls: message.toolCalls.map(toRequestToolCall) } : {}
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
function isSendableMessage(message) {
|
|
20
|
+
if (message.clientOnly) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
if (message.role === "assistant") {
|
|
24
|
+
return message.content.trim().length > 0 || !!message.toolCalls?.length;
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
toRequestMessages,
|
|
30
|
+
toRequestToolCall
|
|
31
|
+
};
|
|
@@ -100,76 +100,6 @@ export interface ToolDefinition<THandlerArgs = Record<string, unknown>> {
|
|
|
100
100
|
*/
|
|
101
101
|
handler?: (context: HandlerContext<THandlerArgs>) => Promise<string | Record<string, unknown> | void> | string | Record<string, unknown> | void;
|
|
102
102
|
}
|
|
103
|
-
export interface MessageStartEvent {
|
|
104
|
-
messageId: string;
|
|
105
|
-
}
|
|
106
|
-
export interface MessageDeltaEvent {
|
|
107
|
-
messageId: string;
|
|
108
|
-
delta: string;
|
|
109
|
-
}
|
|
110
|
-
export interface MessageEndEvent {
|
|
111
|
-
messageId: string;
|
|
112
|
-
}
|
|
113
|
-
export interface ToolCallStartEvent {
|
|
114
|
-
id: string;
|
|
115
|
-
messageId: string;
|
|
116
|
-
name: string;
|
|
117
|
-
}
|
|
118
|
-
export interface ToolCallArgsEvent {
|
|
119
|
-
id: string;
|
|
120
|
-
messageId: string;
|
|
121
|
-
name: string;
|
|
122
|
-
argsBuffer: string;
|
|
123
|
-
partialArgs?: Record<string, unknown>;
|
|
124
|
-
}
|
|
125
|
-
export interface ToolCallEndEvent {
|
|
126
|
-
id: string;
|
|
127
|
-
messageId: string;
|
|
128
|
-
name: string;
|
|
129
|
-
args: Record<string, unknown>;
|
|
130
|
-
}
|
|
131
|
-
export interface ToolResultEvent {
|
|
132
|
-
toolCallId: string;
|
|
133
|
-
result: unknown;
|
|
134
|
-
message: ChatMessage;
|
|
135
|
-
isError?: boolean;
|
|
136
|
-
}
|
|
137
|
-
export type StreamEvent = {
|
|
138
|
-
type: 'message-start';
|
|
139
|
-
timestamp: number;
|
|
140
|
-
data: MessageStartEvent;
|
|
141
|
-
rawEvent?: unknown;
|
|
142
|
-
} | {
|
|
143
|
-
type: 'message-delta';
|
|
144
|
-
timestamp: number;
|
|
145
|
-
data: MessageDeltaEvent;
|
|
146
|
-
rawEvent?: unknown;
|
|
147
|
-
} | {
|
|
148
|
-
type: 'message-end';
|
|
149
|
-
timestamp: number;
|
|
150
|
-
data: MessageEndEvent;
|
|
151
|
-
rawEvent?: unknown;
|
|
152
|
-
} | {
|
|
153
|
-
type: 'tool-call-start';
|
|
154
|
-
timestamp: number;
|
|
155
|
-
data: ToolCallStartEvent;
|
|
156
|
-
rawEvent?: unknown;
|
|
157
|
-
} | {
|
|
158
|
-
type: 'tool-call-args';
|
|
159
|
-
timestamp: number;
|
|
160
|
-
data: ToolCallArgsEvent;
|
|
161
|
-
rawEvent?: unknown;
|
|
162
|
-
} | {
|
|
163
|
-
type: 'tool-call-end';
|
|
164
|
-
timestamp: number;
|
|
165
|
-
data: ToolCallEndEvent;
|
|
166
|
-
rawEvent?: unknown;
|
|
167
|
-
} | {
|
|
168
|
-
type: 'tool-result';
|
|
169
|
-
timestamp: number;
|
|
170
|
-
data: ToolResultEvent;
|
|
171
|
-
rawEvent?: unknown;
|
|
172
|
-
};
|
|
173
103
|
export interface ChatMessage {
|
|
174
104
|
id: string;
|
|
175
105
|
role: 'user' | 'assistant' | 'system' | 'tool';
|
|
@@ -178,7 +108,6 @@ export interface ChatMessage {
|
|
|
178
108
|
status: 'pending' | 'streaming' | 'complete' | 'error';
|
|
179
109
|
toolCalls?: ToolCall[];
|
|
180
110
|
toolCallId?: string;
|
|
181
|
-
eventStream?: StreamEvent[];
|
|
182
111
|
feedback?: ResponseFeedback;
|
|
183
112
|
children?: ResponseItem[];
|
|
184
113
|
clientOnly?: boolean;
|
|
@@ -217,7 +146,6 @@ export interface ToolCall<TArgs = Record<string, unknown>> {
|
|
|
217
146
|
result?: unknown;
|
|
218
147
|
status: 'pending' | 'parsing' | 'executing' | 'complete' | 'error';
|
|
219
148
|
type: ToolType;
|
|
220
|
-
eventStream?: StreamEvent[];
|
|
221
149
|
startTimestamp?: number;
|
|
222
150
|
endTimestamp?: number;
|
|
223
151
|
}
|
|
@@ -240,7 +168,6 @@ export interface AssistantResponse {
|
|
|
240
168
|
children: ResponseItem[];
|
|
241
169
|
status: 'streaming' | 'complete' | 'error';
|
|
242
170
|
timestamp: number;
|
|
243
|
-
eventStream?: StreamEvent[];
|
|
244
171
|
feedback?: ResponseFeedback;
|
|
245
172
|
isThinking?: boolean;
|
|
246
173
|
}
|
|
@@ -46,6 +46,7 @@ declare global {
|
|
|
46
46
|
'forge-ai-chatbot-launcher-thread-search': CustomEvent<ForgeAiChatbotLauncherThreadSearchEventData>;
|
|
47
47
|
'forge-ai-chatbot-launcher-thread-load-more': CustomEvent<ForgeAiChatbotLauncherThreadLoadMoreEventData>;
|
|
48
48
|
'forge-ai-chatbot-launcher-new-chat': CustomEvent<void>;
|
|
49
|
+
'forge-ai-chatbot-launcher-thread-retry': CustomEvent<void>;
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
export declare const AiChatbotLauncherComponentTagName: keyof HTMLElementTagNameMap;
|
|
@@ -72,11 +73,13 @@ export declare const AiChatbotLauncherComponentTagName: keyof HTMLElementTagName
|
|
|
72
73
|
* @property {Agent[]} agents - List of available agents for selector
|
|
73
74
|
* @property {string} selectedAgentId - Currently selected agent ID
|
|
74
75
|
* @property {string} threadName - The name of the current thread (shown in conversation view breadcrumb)
|
|
76
|
+
* @property {boolean} showHistoryButton - Controls the prompt bar's chat history button and its popover (default: false). Visibility is yours to decide - the component never infers it from whether chats are loaded, so an empty `threads` shows "No chats yet" rather than removing the entry point
|
|
75
77
|
* @property {boolean} showThreadRename - Whether to show the rename option in thread actions menu
|
|
76
78
|
* @property {boolean} showThreadDelete - Whether to show the delete option in thread actions menu
|
|
77
79
|
* @property {Thread[]} threads - The list of chats shown in the history popover and full history view
|
|
78
80
|
* @property {number} totalThreads - Total number of chats available. When greater than the number of loaded threads, infinite scroll is enabled (0 disables it)
|
|
79
|
-
* @property {boolean} threadsLoading - Whether chats are currently loading, used to
|
|
81
|
+
* @property {boolean} threadsLoading - Whether chats are currently loading, used to show a spinner on the history button and disable it
|
|
82
|
+
* @property {string | undefined} threadsError - Message describing a failed chat history load. When set, the history popover/view shows the message with a retry button instead of the empty state, and the history button shows an error badge so the failure is visible with the popover closed. If chats are already loaded the list stays visible and the message renders as a compact single line with a retry - at the bottom of the list when a page was in flight, otherwise above it. Clear it once a load succeeds.
|
|
80
83
|
* @property {string | null} selectedThreadId - The id of the currently selected thread, highlighted in the history popover/view. Updated internally when a thread is selected or a new chat starts.
|
|
81
84
|
*
|
|
82
85
|
* @cssproperty --forge-ai-chatbot-launcher-icon-color - The fill color for the AI icon.
|
|
@@ -94,10 +97,11 @@ export declare const AiChatbotLauncherComponentTagName: keyof HTMLElementTagName
|
|
|
94
97
|
* @event {CustomEvent<ForgeAiChatbotAgentChangeEventData>} forge-ai-chatbot-agent-change - Fired when agent selection changes
|
|
95
98
|
* @event {CustomEvent<ForgeAiChatbotLauncherThreadRenameEventData>} forge-ai-chatbot-launcher-thread-rename - Fired when thread rename is saved. Parent should update threadName property and call onSuccess() or onError()
|
|
96
99
|
* @event {CustomEvent<ForgeAiChatbotLauncherThreadDeleteEventData>} forge-ai-chatbot-launcher-thread-delete - Fired when thread deletion is confirmed. Parent should delete thread and call onSuccess() or onError()
|
|
97
|
-
* @event {CustomEvent<ForgeAiChatbotLauncherThreadSelectEventData>} forge-ai-chatbot-launcher-thread-select - Fired when a thread is selected from the history popover or full history view
|
|
100
|
+
* @event {CustomEvent<ForgeAiChatbotLauncherThreadSelectEventData>} forge-ai-chatbot-launcher-thread-select - Fired when a thread is selected from the history popover or full history view. Cancelable - prevents selectedThreadId from being set and the transition to the conversation view, leaving the host to commit both once its own load resolves
|
|
98
101
|
* @event {CustomEvent<ForgeAiChatbotLauncherThreadSearchEventData>} forge-ai-chatbot-launcher-thread-search - Fired when the history search query changes (debounced). Cancelable - call setResults() with the results
|
|
99
102
|
* @event {CustomEvent<ForgeAiChatbotLauncherThreadLoadMoreEventData>} forge-ai-chatbot-launcher-thread-load-more - Fired when scrolling near the bottom of the history list for pagination. Call appendResults() with the next page (empty array signals no more results)
|
|
100
103
|
* @event {CustomEvent<void>} forge-ai-chatbot-launcher-new-chat - Fired when "New chat" is clicked from the full history view. Cancelable - prevents startNewChat() from being called
|
|
104
|
+
* @event {CustomEvent<void>} forge-ai-chatbot-launcher-thread-retry - Fired when the retry button in the history error state is clicked. Re-request the chats and clear threadsError once the load succeeds
|
|
101
105
|
*/
|
|
102
106
|
export declare class AiChatbotLauncherComponent extends AiChatbotBase {
|
|
103
107
|
#private;
|
|
@@ -105,11 +109,13 @@ export declare class AiChatbotLauncherComponent extends AiChatbotBase {
|
|
|
105
109
|
placeholder: string;
|
|
106
110
|
descriptionText?: string;
|
|
107
111
|
threadName?: string;
|
|
112
|
+
showHistoryButton: boolean;
|
|
108
113
|
showThreadRename: boolean;
|
|
109
114
|
showThreadDelete: boolean;
|
|
110
115
|
threads: Thread[];
|
|
111
116
|
totalThreads: number;
|
|
112
117
|
threadsLoading: boolean;
|
|
118
|
+
threadsError?: string;
|
|
113
119
|
selectedThreadId: string | null;
|
|
114
120
|
private _viewState;
|
|
115
121
|
private _skipAnimation;
|
|
@@ -120,6 +126,12 @@ export declare class AiChatbotLauncherComponent extends AiChatbotBase {
|
|
|
120
126
|
constructor();
|
|
121
127
|
protected _onConnected(): void;
|
|
122
128
|
startConversation(): void;
|
|
129
|
+
/**
|
|
130
|
+
* Returns to the welcome view without touching conversation state. Unlike `startNewChat()`, this
|
|
131
|
+
* leaves messages, `selectedThreadId`, and the adapter's thread untouched, so an abandoned thread
|
|
132
|
+
* selection can be undone without discarding the conversation the user was already in.
|
|
133
|
+
*/
|
|
134
|
+
showWelcome(): void;
|
|
123
135
|
/**
|
|
124
136
|
* Navigates directly to the full history view (not the history popover).
|
|
125
137
|
*/
|
|
@@ -40,7 +40,7 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
|
|
|
40
40
|
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);
|
|
41
41
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
42
42
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
43
|
-
var _headerRef, _gradientContainerRef, _internals, _pendingThreadDeleteSource, _deleteThreadController, _AiChatbotLauncherComponent_instances, setViewState_fn, transitionToConversation_fn, commitConversationTransition_fn, transitionToWelcome_fn, transitionToHistory_fn, handleHistoryBack_fn, handleHeaderClear_fn, handleHeaderInfo_fn, handleThreadRename_fn, handleEditSave_fn, handleEditCancel_fn, handleThreadNameClick_fn, handleThreadDelete_fn, handleHistoryButtonClick_fn, handleHistoryPopoverToggle_fn, handleViewAllClick_fn, handleThreadsSearchQuery_fn, handleThreadsSearchLoadMore_fn, handleThreadsSearchSelect_fn, handleThreadsSearchNewChat_fn, handleThreadsSearchRename_fn, handleThreadsSearchDelete_fn, handleThreadsSearchDeleteConfirm_fn, headingElement_get, promptTemplate_get, welcomeHeaderTemplate_get, welcomeSuggestionsTemplate_get, threadName_get, threadActionsMenu_get, conversationContentTemplate_get, historyContentTemplate_get, mainContentTemplate_get, historyButtonTemplate_get, historyPopoverTemplate_get, promptSectionTemplate_get;
|
|
43
|
+
var _headerRef, _gradientContainerRef, _internals, _pendingThreadDeleteSource, _deleteThreadController, _AiChatbotLauncherComponent_instances, setViewState_fn, transitionToConversation_fn, commitConversationTransition_fn, transitionToWelcome_fn, transitionToHistory_fn, handleHistoryBack_fn, handleHeaderClear_fn, handleHeaderInfo_fn, handleThreadRename_fn, handleEditSave_fn, handleEditCancel_fn, handleThreadNameClick_fn, handleThreadDelete_fn, handleHistoryButtonClick_fn, handleHistoryPopoverToggle_fn, handleViewAllClick_fn, handleThreadsSearchQuery_fn, handleThreadsSearchLoadMore_fn, handleThreadsSearchSelect_fn, handleThreadsSearchRetry_fn, handleThreadsSearchNewChat_fn, handleThreadsSearchRename_fn, handleThreadsSearchDelete_fn, handleThreadsSearchDeleteConfirm_fn, headingElement_get, promptTemplate_get, welcomeHeaderTemplate_get, welcomeSuggestionsTemplate_get, threadName_get, threadActionsMenu_get, conversationContentTemplate_get, historyContentTemplate_get, mainContentTemplate_get, showThreadsLoading_get, historyButtonTemplate_get, historyPopoverTemplate_get, promptSectionTemplate_get;
|
|
44
44
|
const HISTORY_POPOVER_INSET = 48;
|
|
45
45
|
const AiChatbotLauncherComponentTagName = "forge-ai-chatbot-launcher";
|
|
46
46
|
let AiChatbotLauncherComponent = class extends AiChatbotBase {
|
|
@@ -48,6 +48,7 @@ let AiChatbotLauncherComponent = class extends AiChatbotBase {
|
|
|
48
48
|
super();
|
|
49
49
|
__privateAdd(this, _AiChatbotLauncherComponent_instances);
|
|
50
50
|
this.placeholder = "How can I help you today?";
|
|
51
|
+
this.showHistoryButton = false;
|
|
51
52
|
this.showThreadRename = false;
|
|
52
53
|
this.showThreadDelete = false;
|
|
53
54
|
this.threads = [];
|
|
@@ -102,6 +103,15 @@ let AiChatbotLauncherComponent = class extends AiChatbotBase {
|
|
|
102
103
|
startConversation() {
|
|
103
104
|
__privateMethod(this, _AiChatbotLauncherComponent_instances, commitConversationTransition_fn).call(this);
|
|
104
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Returns to the welcome view without touching conversation state. Unlike `startNewChat()`, this
|
|
108
|
+
* leaves messages, `selectedThreadId`, and the adapter's thread untouched, so an abandoned thread
|
|
109
|
+
* selection can be undone without discarding the conversation the user was already in.
|
|
110
|
+
*/
|
|
111
|
+
showWelcome() {
|
|
112
|
+
this._historyPopoverOpen = false;
|
|
113
|
+
__privateMethod(this, _AiChatbotLauncherComponent_instances, transitionToWelcome_fn).call(this);
|
|
114
|
+
}
|
|
105
115
|
/**
|
|
106
116
|
* Navigates directly to the full history view (not the history popover).
|
|
107
117
|
*/
|
|
@@ -169,7 +179,7 @@ let AiChatbotLauncherComponent = class extends AiChatbotBase {
|
|
|
169
179
|
${__privateGet(this, _AiChatbotLauncherComponent_instances, mainContentTemplate_get)} ${__privateGet(this, _AiChatbotLauncherComponent_instances, promptSectionTemplate_get)}
|
|
170
180
|
${this._viewState === "welcome" ? __privateGet(this, _AiChatbotLauncherComponent_instances, welcomeSuggestionsTemplate_get) : nothing}
|
|
171
181
|
</div>
|
|
172
|
-
${__privateGet(this, _AiChatbotLauncherComponent_instances, historyPopoverTemplate_get)} ${__privateGet(this, _deleteThreadController).template}
|
|
182
|
+
${when(this.showHistoryButton, () => __privateGet(this, _AiChatbotLauncherComponent_instances, historyPopoverTemplate_get))} ${__privateGet(this, _deleteThreadController).template}
|
|
173
183
|
`;
|
|
174
184
|
}
|
|
175
185
|
};
|
|
@@ -287,13 +297,20 @@ handleThreadsSearchLoadMore_fn = function(evt) {
|
|
|
287
297
|
};
|
|
288
298
|
handleThreadsSearchSelect_fn = function(evt) {
|
|
289
299
|
this._historyPopoverOpen = false;
|
|
290
|
-
|
|
291
|
-
this._dispatchHostEvent({
|
|
300
|
+
const event = this._dispatchHostEvent({
|
|
292
301
|
type: "forge-ai-chatbot-launcher-thread-select",
|
|
293
|
-
detail: evt.detail
|
|
302
|
+
detail: evt.detail,
|
|
303
|
+
cancelable: true
|
|
294
304
|
});
|
|
305
|
+
if (event.defaultPrevented) {
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
this.selectedThreadId = evt.detail.id;
|
|
295
309
|
__privateMethod(this, _AiChatbotLauncherComponent_instances, setViewState_fn).call(this, "conversation");
|
|
296
310
|
};
|
|
311
|
+
handleThreadsSearchRetry_fn = function() {
|
|
312
|
+
this._dispatchHostEvent({ type: "forge-ai-chatbot-launcher-thread-retry" });
|
|
313
|
+
};
|
|
297
314
|
handleThreadsSearchNewChat_fn = function() {
|
|
298
315
|
this._historyPopoverOpen = false;
|
|
299
316
|
const event = this._dispatchHostEvent({ type: "forge-ai-chatbot-launcher-new-chat", cancelable: true });
|
|
@@ -416,6 +433,7 @@ threadName_get = function() {
|
|
|
416
433
|
isEditing,
|
|
417
434
|
() => html`
|
|
418
435
|
<forge-ai-edit-thread
|
|
436
|
+
density="medium"
|
|
419
437
|
.thread=${{
|
|
420
438
|
id: threadId,
|
|
421
439
|
title: this.threadName || "",
|
|
@@ -458,6 +476,7 @@ threadActionsMenu_get = function() {
|
|
|
458
476
|
};
|
|
459
477
|
return html`
|
|
460
478
|
<forge-ai-thread-actions-menu
|
|
479
|
+
density="medium"
|
|
461
480
|
.thread=${thread}
|
|
462
481
|
?show-rename=${this.showThreadRename}
|
|
463
482
|
?show-delete=${this.showThreadDelete}
|
|
@@ -525,6 +544,7 @@ historyContentTemplate_get = function() {
|
|
|
525
544
|
.threads=${this.threads}
|
|
526
545
|
.totalChats=${this.totalThreads}
|
|
527
546
|
.selectedThreadId=${this.selectedThreadId}
|
|
547
|
+
.errorMessage=${this.threadsError}
|
|
528
548
|
?show-thread-rename=${this.showThreadRename}
|
|
529
549
|
?show-thread-delete=${this.showThreadDelete}
|
|
530
550
|
@forge-ai-threads-search-back=${__privateMethod(this, _AiChatbotLauncherComponent_instances, handleHistoryBack_fn)}
|
|
@@ -534,6 +554,7 @@ historyContentTemplate_get = function() {
|
|
|
534
554
|
@forge-ai-threads-search-new-chat=${__privateMethod(this, _AiChatbotLauncherComponent_instances, handleThreadsSearchNewChat_fn)}
|
|
535
555
|
@forge-ai-threads-search-rename=${__privateMethod(this, _AiChatbotLauncherComponent_instances, handleThreadsSearchRename_fn)}
|
|
536
556
|
@forge-ai-threads-search-delete=${__privateMethod(this, _AiChatbotLauncherComponent_instances, handleThreadsSearchDelete_fn)}
|
|
557
|
+
@forge-ai-threads-search-retry=${__privateMethod(this, _AiChatbotLauncherComponent_instances, handleThreadsSearchRetry_fn)}
|
|
537
558
|
@forge-ai-threads-search-delete-confirm=${__privateMethod(this, _AiChatbotLauncherComponent_instances, handleThreadsSearchDeleteConfirm_fn)}>
|
|
538
559
|
</forge-ai-threads-search>
|
|
539
560
|
</div>
|
|
@@ -549,8 +570,11 @@ mainContentTemplate_get = function() {
|
|
|
549
570
|
return __privateGet(this, _AiChatbotLauncherComponent_instances, conversationContentTemplate_get);
|
|
550
571
|
}
|
|
551
572
|
};
|
|
573
|
+
showThreadsLoading_get = function() {
|
|
574
|
+
return this.threadsLoading && !this.threadsError;
|
|
575
|
+
};
|
|
552
576
|
historyButtonTemplate_get = function() {
|
|
553
|
-
if (
|
|
577
|
+
if (!this.showHistoryButton) {
|
|
554
578
|
return nothing;
|
|
555
579
|
}
|
|
556
580
|
return html`
|
|
@@ -558,13 +582,13 @@ historyButtonTemplate_get = function() {
|
|
|
558
582
|
id="history-button"
|
|
559
583
|
slot="actions-start"
|
|
560
584
|
type="button"
|
|
561
|
-
class="forge-icon-button forge-icon-button--medium ai-icon-button"
|
|
562
|
-
aria-label
|
|
585
|
+
class="forge-icon-button forge-icon-button--medium ai-icon-button history-button"
|
|
586
|
+
aria-label=${this.threadsError ? "Chat history - failed to load" : "Chat history"}
|
|
563
587
|
aria-expanded=${this._historyPopoverOpen}
|
|
564
|
-
?disabled=${this
|
|
588
|
+
?disabled=${__privateGet(this, _AiChatbotLauncherComponent_instances, showThreadsLoading_get)}
|
|
565
589
|
@click=${__privateMethod(this, _AiChatbotLauncherComponent_instances, handleHistoryButtonClick_fn)}>
|
|
566
590
|
${when(
|
|
567
|
-
this
|
|
591
|
+
__privateGet(this, _AiChatbotLauncherComponent_instances, showThreadsLoading_get),
|
|
568
592
|
() => html`<forge-ai-spinner size="extra-small"></forge-ai-spinner>`,
|
|
569
593
|
() => html`
|
|
570
594
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
|
|
@@ -572,10 +596,14 @@ historyButtonTemplate_get = function() {
|
|
|
572
596
|
d="M13.5 8H12v5l4.28 2.54.72-1.21-3.5-2.08zM13 3a9 9 0 0 0-9 9H1l3.96 4.03L9 12H6a7 7 0 0 1 7-7 7 7 0 0 1 7 7 7 7 0 0 1-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42A8.9 8.9 0 0 0 13 21a9 9 0 0 0 9-9 9 9 0 0 0-9-9" />
|
|
573
597
|
</svg>
|
|
574
598
|
`
|
|
599
|
+
)}
|
|
600
|
+
${when(
|
|
601
|
+
this.threadsError,
|
|
602
|
+
() => html`<span class="forge-badge forge-badge--dot history-button__error-badge"></span>`
|
|
575
603
|
)}
|
|
576
604
|
</button>
|
|
577
605
|
${when(
|
|
578
|
-
!this
|
|
606
|
+
!__privateGet(this, _AiChatbotLauncherComponent_instances, showThreadsLoading_get),
|
|
579
607
|
() => html`<forge-ai-tooltip slot="actions-start" for="history-button" placement="top"
|
|
580
608
|
>Chat history</forge-ai-tooltip
|
|
581
609
|
>`
|
|
@@ -603,6 +631,7 @@ historyPopoverTemplate_get = function() {
|
|
|
603
631
|
.threads=${this.threads}
|
|
604
632
|
.totalChats=${this.totalThreads}
|
|
605
633
|
.selectedThreadId=${this.selectedThreadId}
|
|
634
|
+
.errorMessage=${this.threadsError}
|
|
606
635
|
?show-thread-rename=${this.showThreadRename}
|
|
607
636
|
?show-thread-delete=${this.showThreadDelete}
|
|
608
637
|
@forge-ai-threads-search-query=${__privateMethod(this, _AiChatbotLauncherComponent_instances, handleThreadsSearchQuery_fn)}
|
|
@@ -610,6 +639,7 @@ historyPopoverTemplate_get = function() {
|
|
|
610
639
|
@forge-ai-threads-search-select=${__privateMethod(this, _AiChatbotLauncherComponent_instances, handleThreadsSearchSelect_fn)}
|
|
611
640
|
@forge-ai-threads-search-rename=${__privateMethod(this, _AiChatbotLauncherComponent_instances, handleThreadsSearchRename_fn)}
|
|
612
641
|
@forge-ai-threads-search-delete=${__privateMethod(this, _AiChatbotLauncherComponent_instances, handleThreadsSearchDelete_fn)}
|
|
642
|
+
@forge-ai-threads-search-retry=${__privateMethod(this, _AiChatbotLauncherComponent_instances, handleThreadsSearchRetry_fn)}
|
|
613
643
|
@forge-ai-threads-search-delete-confirm=${__privateMethod(this, _AiChatbotLauncherComponent_instances, handleThreadsSearchDeleteConfirm_fn)}>
|
|
614
644
|
<button
|
|
615
645
|
slot="header-actions"
|
|
@@ -644,6 +674,9 @@ __decorateClass([
|
|
|
644
674
|
__decorateClass([
|
|
645
675
|
property({ attribute: "thread-name" })
|
|
646
676
|
], AiChatbotLauncherComponent.prototype, "threadName", 2);
|
|
677
|
+
__decorateClass([
|
|
678
|
+
property({ type: Boolean, attribute: "show-history-button" })
|
|
679
|
+
], AiChatbotLauncherComponent.prototype, "showHistoryButton", 2);
|
|
647
680
|
__decorateClass([
|
|
648
681
|
property({ type: Boolean, attribute: "show-thread-rename" })
|
|
649
682
|
], AiChatbotLauncherComponent.prototype, "showThreadRename", 2);
|
|
@@ -659,6 +692,9 @@ __decorateClass([
|
|
|
659
692
|
__decorateClass([
|
|
660
693
|
property({ type: Boolean, attribute: "threads-loading" })
|
|
661
694
|
], AiChatbotLauncherComponent.prototype, "threadsLoading", 2);
|
|
695
|
+
__decorateClass([
|
|
696
|
+
property({ type: String, attribute: "threads-error" })
|
|
697
|
+
], AiChatbotLauncherComponent.prototype, "threadsError", 2);
|
|
662
698
|
__decorateClass([
|
|
663
699
|
property({ type: String, attribute: "selected-thread-id" })
|
|
664
700
|
], AiChatbotLauncherComponent.prototype, "selectedThreadId", 2);
|