@kodaris/krubble-app-components 1.0.70 → 1.0.71
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/dist/chatbot.d.ts +72 -26
- package/dist/chatbot.d.ts.map +1 -1
- package/dist/chatbot.js +299 -203
- package/dist/chatbot.js.map +1 -1
- package/dist/krubble-app.bundled.js +298 -203
- package/dist/krubble-app.bundled.js.map +1 -1
- package/dist/krubble-app.bundled.min.js +195 -147
- package/dist/krubble-app.bundled.min.js.map +1 -1
- package/dist/krubble-app.umd.js +298 -203
- package/dist/krubble-app.umd.js.map +1 -1
- package/dist/krubble-app.umd.min.js +226 -178
- package/dist/krubble-app.umd.min.js.map +1 -1
- package/package.json +1 -1
package/dist/krubble-app.umd.js
CHANGED
|
@@ -5570,7 +5570,7 @@
|
|
|
5570
5570
|
* ## Usage
|
|
5571
5571
|
* ```html
|
|
5572
5572
|
* <kr-chatbot
|
|
5573
|
-
*
|
|
5573
|
+
* label="AI Assistant"
|
|
5574
5574
|
* .send=${(params) => {
|
|
5575
5575
|
* return fetch('/api/ai/chat/stream', {
|
|
5576
5576
|
* method: 'POST',
|
|
@@ -5613,16 +5613,25 @@
|
|
|
5613
5613
|
/**
|
|
5614
5614
|
* Callback function for sending messages. Receives the user's message and
|
|
5615
5615
|
* current conversation history. Must return a Response with a streaming SSE body.
|
|
5616
|
+
*
|
|
5617
|
+
* Optional — when not set, the chatbot uses its built-in default that streams
|
|
5618
|
+
* from the Kodaris Bedrock conversation endpoints. Set this to override.
|
|
5616
5619
|
*/
|
|
5617
5620
|
this.send = null;
|
|
5618
5621
|
/**
|
|
5619
5622
|
* Callback function called when the user clears the conversation.
|
|
5620
5623
|
* Must return a Promise — messages are only cleared if it resolves.
|
|
5624
|
+
*
|
|
5625
|
+
* Optional — when not set, the chatbot uses its built-in default that clears
|
|
5626
|
+
* the Kodaris Bedrock conversation state. Set this to override.
|
|
5621
5627
|
*/
|
|
5622
5628
|
this.clear = null;
|
|
5623
5629
|
/**
|
|
5624
5630
|
* Callback function called on init to load existing conversation messages.
|
|
5625
5631
|
* Must return a Promise that resolves with an array of KRChatbotMessage.
|
|
5632
|
+
*
|
|
5633
|
+
* Optional — when not set, the chatbot uses its built-in default that loads
|
|
5634
|
+
* existing messages from the Kodaris Bedrock conversation. Set this to override.
|
|
5626
5635
|
*/
|
|
5627
5636
|
this.load = null;
|
|
5628
5637
|
/**
|
|
@@ -5631,13 +5640,9 @@
|
|
|
5631
5640
|
*/
|
|
5632
5641
|
this.messages = [];
|
|
5633
5642
|
/**
|
|
5634
|
-
* Header
|
|
5643
|
+
* Header label text.
|
|
5635
5644
|
*/
|
|
5636
|
-
this.
|
|
5637
|
-
/**
|
|
5638
|
-
* Header subtitle text (shown below title with a green status dot).
|
|
5639
|
-
*/
|
|
5640
|
-
this.subtitle = '';
|
|
5645
|
+
this.label = 'Kat';
|
|
5641
5646
|
/**
|
|
5642
5647
|
* Input placeholder text.
|
|
5643
5648
|
*/
|
|
@@ -5652,13 +5657,23 @@
|
|
|
5652
5657
|
* then driven via the `open()` / `close()` / `toggle()` methods.
|
|
5653
5658
|
*/
|
|
5654
5659
|
this.hideToggle = false;
|
|
5660
|
+
/**
|
|
5661
|
+
* Layout mode.
|
|
5662
|
+
* - `'floating'` (default): the chatbot is a fixed bottom-right widget with a
|
|
5663
|
+
* toggle button, and the panel can be dragged and resized. This is the
|
|
5664
|
+
* traditional chat-widget appearance.
|
|
5665
|
+
* - `'inline'`: the chatbot drops its fixed positioning and fills its parent
|
|
5666
|
+
* container (100% width/height, no border radius/shadow, no toggle, no
|
|
5667
|
+
* drag/resize). The panel is always open. Use this to embed the chat as a
|
|
5668
|
+
* full page or panel region.
|
|
5669
|
+
*/
|
|
5670
|
+
this.variant = 'floating';
|
|
5655
5671
|
// --- @state (internal) ---
|
|
5656
5672
|
this._inputValue = '';
|
|
5657
5673
|
this._isStreaming = false;
|
|
5658
|
-
this._statusText = '';
|
|
5659
5674
|
this._error = '';
|
|
5660
5675
|
/** Images staged in the composer, before the message is sent. */
|
|
5661
|
-
this.
|
|
5676
|
+
this._pendingInternalFiles = [];
|
|
5662
5677
|
/** True while a file is being dragged over the panel (shows the drop overlay). */
|
|
5663
5678
|
this._isDraggingFile = false;
|
|
5664
5679
|
this._handleMouseMove = (e) => {
|
|
@@ -5722,12 +5737,27 @@
|
|
|
5722
5737
|
// --- Lifecycle ---
|
|
5723
5738
|
connectedCallback() {
|
|
5724
5739
|
super.connectedCallback();
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5740
|
+
// Default to loading existing messages from the Kodaris Bedrock conversation
|
|
5741
|
+
// when the consumer hasn't provided their own `load`. The endpoint returns
|
|
5742
|
+
// messages already in KRChatbotMessage shape ({ type, content, images }), so
|
|
5743
|
+
// they pass straight through.
|
|
5744
|
+
if (!this.load) {
|
|
5745
|
+
this.load = () => krubbleHttp.Http.fetch({
|
|
5746
|
+
url: '/api/system/integration/aws/bedrock/getConversationMessages',
|
|
5747
|
+
})
|
|
5748
|
+
.then((r) => r.json())
|
|
5749
|
+
.then((res) => res.data || []);
|
|
5750
|
+
}
|
|
5751
|
+
this.load().then((messages) => {
|
|
5752
|
+
if (messages && messages.length) {
|
|
5753
|
+
this.messages = messages;
|
|
5754
|
+
}
|
|
5755
|
+
}).catch(() => { });
|
|
5756
|
+
// Inline mode fills its container and is always open — the floating widget's
|
|
5757
|
+
// toggle/drag/resize state (including any persisted layout) doesn't apply.
|
|
5758
|
+
if (this.variant === 'inline') {
|
|
5759
|
+
this.opened = true;
|
|
5760
|
+
return;
|
|
5731
5761
|
}
|
|
5732
5762
|
this._restoreState();
|
|
5733
5763
|
}
|
|
@@ -5740,10 +5770,10 @@
|
|
|
5740
5770
|
document.removeEventListener('mousemove', this._handleMouseMove);
|
|
5741
5771
|
document.removeEventListener('mouseup', this._handleMouseUp);
|
|
5742
5772
|
// Release any object URLs still held by staged attachments.
|
|
5743
|
-
this.
|
|
5773
|
+
this._pendingInternalFiles.forEach((p) => URL.revokeObjectURL(p.previewUrl));
|
|
5744
5774
|
}
|
|
5745
5775
|
updated(changed) {
|
|
5746
|
-
if (changed.has('messages')
|
|
5776
|
+
if (changed.has('messages')) {
|
|
5747
5777
|
if (!this._userHasScrolledUp && !this._isStreaming && this._messagesEl) {
|
|
5748
5778
|
requestAnimationFrame(() => {
|
|
5749
5779
|
if (this._messagesEl) {
|
|
@@ -5817,6 +5847,10 @@
|
|
|
5817
5847
|
}
|
|
5818
5848
|
}
|
|
5819
5849
|
_handleHeaderMouseDown(e) {
|
|
5850
|
+
// Inline mode fills its parent — dragging the panel doesn't apply.
|
|
5851
|
+
if (this.variant === 'inline') {
|
|
5852
|
+
return;
|
|
5853
|
+
}
|
|
5820
5854
|
// Ignore clicks on buttons inside the header
|
|
5821
5855
|
if (e.target.closest('button')) {
|
|
5822
5856
|
return;
|
|
@@ -5842,6 +5876,10 @@
|
|
|
5842
5876
|
document.addEventListener('mouseup', this._handleMouseUp);
|
|
5843
5877
|
}
|
|
5844
5878
|
_handleResizeMouseDown(e) {
|
|
5879
|
+
// Inline mode fills its parent — resizing the panel doesn't apply.
|
|
5880
|
+
if (this.variant === 'inline') {
|
|
5881
|
+
return;
|
|
5882
|
+
}
|
|
5845
5883
|
if (!this._panelEl) {
|
|
5846
5884
|
return;
|
|
5847
5885
|
}
|
|
@@ -6034,54 +6072,49 @@
|
|
|
6034
6072
|
name: file.name,
|
|
6035
6073
|
previewUrl: URL.createObjectURL(file),
|
|
6036
6074
|
};
|
|
6037
|
-
this.
|
|
6075
|
+
this._pendingInternalFiles = [...this._pendingInternalFiles, pending];
|
|
6038
6076
|
});
|
|
6039
6077
|
}
|
|
6040
6078
|
_removePending(localId) {
|
|
6041
|
-
const target = this.
|
|
6079
|
+
const target = this._pendingInternalFiles.find((p) => p.localId === localId);
|
|
6042
6080
|
if (target) {
|
|
6043
6081
|
URL.revokeObjectURL(target.previewUrl);
|
|
6044
6082
|
}
|
|
6045
|
-
this.
|
|
6083
|
+
this._pendingInternalFiles = this._pendingInternalFiles.filter((p) => p.localId !== localId);
|
|
6046
6084
|
}
|
|
6047
6085
|
_clearPending() {
|
|
6048
|
-
this.
|
|
6049
|
-
this.
|
|
6086
|
+
this._pendingInternalFiles.forEach((p) => URL.revokeObjectURL(p.previewUrl));
|
|
6087
|
+
this._pendingInternalFiles = [];
|
|
6050
6088
|
}
|
|
6051
|
-
/** Open the shared full-screen previewer for
|
|
6052
|
-
|
|
6089
|
+
/** Open the shared full-screen previewer for a message image. */
|
|
6090
|
+
_openImage(img) {
|
|
6053
6091
|
krubbleComponents.FilePreview.open({
|
|
6054
|
-
src:
|
|
6055
|
-
name:
|
|
6092
|
+
src: `/api/system/integration/aws/bedrock/conversationImage/${img.internalFileID}/view`,
|
|
6093
|
+
name: img.niceName || 'image',
|
|
6056
6094
|
});
|
|
6057
6095
|
}
|
|
6058
6096
|
/** Whether the send button is active: needs text or at least one image. */
|
|
6059
6097
|
_canSend() {
|
|
6060
|
-
return Boolean(this._inputValue.trim()) || this.
|
|
6098
|
+
return Boolean(this._inputValue.trim()) || this._pendingInternalFiles.length > 0;
|
|
6061
6099
|
}
|
|
6062
6100
|
_handleSubmit() {
|
|
6063
|
-
if (
|
|
6101
|
+
if (this._isStreaming) {
|
|
6064
6102
|
return;
|
|
6065
6103
|
}
|
|
6066
6104
|
const messageText = this._inputValue.trim();
|
|
6067
|
-
const pending = this.
|
|
6105
|
+
const pending = this._pendingInternalFiles;
|
|
6068
6106
|
// Allow sending an image with no text, but require at least one of them.
|
|
6069
6107
|
if (!messageText && !pending.length) {
|
|
6070
6108
|
return;
|
|
6071
6109
|
}
|
|
6072
|
-
// The raw files sent to the backend
|
|
6073
|
-
//
|
|
6074
|
-
//
|
|
6075
|
-
const
|
|
6076
|
-
const attachments = pending.map((p) => ({
|
|
6077
|
-
url: p.previewUrl,
|
|
6078
|
-
name: p.name,
|
|
6079
|
-
mimeType: p.file.type,
|
|
6080
|
-
}));
|
|
6110
|
+
// The raw files sent to the backend. Sent images are shown once the
|
|
6111
|
+
// conversation reloads and they come back as stored internal files; the
|
|
6112
|
+
// just-sent message itself carries text only.
|
|
6113
|
+
const internalFiles = pending.map((p) => p.file);
|
|
6081
6114
|
const submitEvent = new CustomEvent('message-submit', {
|
|
6082
6115
|
detail: {
|
|
6083
6116
|
message: messageText,
|
|
6084
|
-
|
|
6117
|
+
internalFiles,
|
|
6085
6118
|
},
|
|
6086
6119
|
bubbles: true,
|
|
6087
6120
|
composed: true,
|
|
@@ -6092,30 +6125,26 @@
|
|
|
6092
6125
|
return;
|
|
6093
6126
|
}
|
|
6094
6127
|
const userMessage = {
|
|
6095
|
-
|
|
6128
|
+
type: 'user',
|
|
6096
6129
|
content: messageText,
|
|
6097
6130
|
};
|
|
6098
|
-
if (attachments.length) {
|
|
6099
|
-
userMessage.attachments = attachments;
|
|
6100
|
-
}
|
|
6101
6131
|
this.messages = [...this.messages, userMessage];
|
|
6102
6132
|
this._inputValue = '';
|
|
6103
6133
|
this._error = '';
|
|
6104
6134
|
this._userHasScrolledUp = false;
|
|
6105
|
-
// Clear the composer
|
|
6106
|
-
|
|
6107
|
-
this.
|
|
6135
|
+
// Clear the composer and release its preview object URLs.
|
|
6136
|
+
this._pendingInternalFiles.forEach((p) => URL.revokeObjectURL(p.previewUrl));
|
|
6137
|
+
this._pendingInternalFiles = [];
|
|
6108
6138
|
// Reset textarea height
|
|
6109
6139
|
if (this._inputEl) {
|
|
6110
6140
|
this._inputEl.style.height = 'auto';
|
|
6111
6141
|
}
|
|
6112
6142
|
// Add empty assistant message to stream into
|
|
6113
6143
|
this.messages = [...this.messages, {
|
|
6114
|
-
|
|
6144
|
+
type: 'assistant',
|
|
6115
6145
|
content: '',
|
|
6116
6146
|
}];
|
|
6117
6147
|
this._isStreaming = true;
|
|
6118
|
-
this._statusText = '';
|
|
6119
6148
|
// Scroll user's message to the top (Gemini-style).
|
|
6120
6149
|
// Set min-height on the assistant message = container height so there's enough
|
|
6121
6150
|
// scroll room below the user message to push it to the top.
|
|
@@ -6137,10 +6166,34 @@
|
|
|
6137
6166
|
this._messagesEl.scrollTop = userMsgEl.offsetTop - this._messagesEl.offsetTop - 24;
|
|
6138
6167
|
}
|
|
6139
6168
|
});
|
|
6169
|
+
// Default to streaming from the Kodaris Bedrock conversation endpoints when
|
|
6170
|
+
// the consumer hasn't provided their own `send`.
|
|
6171
|
+
if (!this.send) {
|
|
6172
|
+
this.send = (params) => {
|
|
6173
|
+
// With images, post text + files as multipart; without, post plain JSON.
|
|
6174
|
+
if (params.internalFiles.length) {
|
|
6175
|
+
const form = new FormData();
|
|
6176
|
+
form.append('userText', params.message);
|
|
6177
|
+
params.internalFiles.forEach((file) => form.append('images', file));
|
|
6178
|
+
return krubbleHttp.Http.fetch({
|
|
6179
|
+
url: '/api/system/integration/aws/bedrock/stream/invokeModelForConversationWithImages',
|
|
6180
|
+
method: 'POST',
|
|
6181
|
+
headers: { Accept: 'text/event-stream' },
|
|
6182
|
+
body: form,
|
|
6183
|
+
});
|
|
6184
|
+
}
|
|
6185
|
+
return krubbleHttp.Http.fetch({
|
|
6186
|
+
url: '/api/system/integration/aws/bedrock/stream/invokeModelForConversationWithState',
|
|
6187
|
+
method: 'POST',
|
|
6188
|
+
headers: { Accept: 'text/event-stream' },
|
|
6189
|
+
body: { userText: params.message },
|
|
6190
|
+
});
|
|
6191
|
+
};
|
|
6192
|
+
}
|
|
6140
6193
|
this.send({
|
|
6141
6194
|
message: messageText,
|
|
6142
6195
|
messages: this.messages.slice(0, -1),
|
|
6143
|
-
|
|
6196
|
+
internalFiles,
|
|
6144
6197
|
}).then((response) => {
|
|
6145
6198
|
if (!response.ok) {
|
|
6146
6199
|
this._handleStreamError('Request failed: ' + response.status);
|
|
@@ -6166,11 +6219,15 @@
|
|
|
6166
6219
|
this._reader = null;
|
|
6167
6220
|
}
|
|
6168
6221
|
this._isStreaming = false;
|
|
6169
|
-
this._statusText = '';
|
|
6170
6222
|
}
|
|
6171
6223
|
_handleClear() {
|
|
6224
|
+
// Default to clearing the Kodaris Bedrock conversation state when the consumer
|
|
6225
|
+
// hasn't provided their own `clear`.
|
|
6172
6226
|
if (!this.clear) {
|
|
6173
|
-
|
|
6227
|
+
this.clear = () => krubbleHttp.Http.fetch({
|
|
6228
|
+
url: '/api/system/integration/aws/bedrock/clearConversationWithState',
|
|
6229
|
+
method: 'POST',
|
|
6230
|
+
});
|
|
6174
6231
|
}
|
|
6175
6232
|
this.clear().then(() => {
|
|
6176
6233
|
if (this._reader) {
|
|
@@ -6179,7 +6236,6 @@
|
|
|
6179
6236
|
}
|
|
6180
6237
|
this.messages = [];
|
|
6181
6238
|
this._isStreaming = false;
|
|
6182
|
-
this._statusText = '';
|
|
6183
6239
|
this._error = '';
|
|
6184
6240
|
this._inputValue = '';
|
|
6185
6241
|
this._userHasScrolledUp = false;
|
|
@@ -6205,7 +6261,6 @@
|
|
|
6205
6261
|
this._reader.read().then((result) => {
|
|
6206
6262
|
if (result.done) {
|
|
6207
6263
|
this._isStreaming = false;
|
|
6208
|
-
this._statusText = '';
|
|
6209
6264
|
this._reader = null;
|
|
6210
6265
|
return;
|
|
6211
6266
|
}
|
|
@@ -6238,15 +6293,10 @@
|
|
|
6238
6293
|
bubbles: true,
|
|
6239
6294
|
composed: true,
|
|
6240
6295
|
}));
|
|
6241
|
-
if (data.type === '
|
|
6242
|
-
if (data.message) {
|
|
6243
|
-
this._statusText = String(data.message);
|
|
6244
|
-
}
|
|
6245
|
-
}
|
|
6246
|
-
else if (data.type === 'REASONING_PART') {
|
|
6296
|
+
if (data.type === 'REASONING_PART') {
|
|
6247
6297
|
if (data.message) {
|
|
6248
6298
|
const lastIndex = this.messages.length - 1;
|
|
6249
|
-
if (lastIndex >= 0 && this.messages[lastIndex].
|
|
6299
|
+
if (lastIndex >= 0 && this.messages[lastIndex].type === 'assistant') {
|
|
6250
6300
|
if (!this.messages[lastIndex].reasoning) {
|
|
6251
6301
|
this.messages[lastIndex].reasoning = '';
|
|
6252
6302
|
}
|
|
@@ -6257,9 +6307,8 @@
|
|
|
6257
6307
|
}
|
|
6258
6308
|
else if (data.type === 'RESPONSE_PART') {
|
|
6259
6309
|
if (data.message) {
|
|
6260
|
-
this._statusText = '';
|
|
6261
6310
|
const lastIndex = this.messages.length - 1;
|
|
6262
|
-
if (lastIndex >= 0 && this.messages[lastIndex].
|
|
6311
|
+
if (lastIndex >= 0 && this.messages[lastIndex].type === 'assistant') {
|
|
6263
6312
|
this.messages[lastIndex].content += String(data.message);
|
|
6264
6313
|
this.requestUpdate();
|
|
6265
6314
|
}
|
|
@@ -6270,7 +6319,6 @@
|
|
|
6270
6319
|
}
|
|
6271
6320
|
if (data.finished) {
|
|
6272
6321
|
this._isStreaming = false;
|
|
6273
|
-
this._statusText = '';
|
|
6274
6322
|
this._reader = null;
|
|
6275
6323
|
}
|
|
6276
6324
|
}
|
|
@@ -6284,7 +6332,6 @@
|
|
|
6284
6332
|
}
|
|
6285
6333
|
_handleStreamError(message) {
|
|
6286
6334
|
this._isStreaming = false;
|
|
6287
|
-
this._statusText = '';
|
|
6288
6335
|
this._error = message;
|
|
6289
6336
|
if (this._reader) {
|
|
6290
6337
|
this._reader.cancel();
|
|
@@ -6293,7 +6340,7 @@
|
|
|
6293
6340
|
// Remove the empty assistant message if it has no content
|
|
6294
6341
|
if (this.messages.length > 0) {
|
|
6295
6342
|
const lastMessage = this.messages[this.messages.length - 1];
|
|
6296
|
-
if (lastMessage.
|
|
6343
|
+
if (lastMessage.type === 'assistant' && !lastMessage.content) {
|
|
6297
6344
|
this.messages = this.messages.slice(0, -1);
|
|
6298
6345
|
}
|
|
6299
6346
|
}
|
|
@@ -6301,7 +6348,7 @@
|
|
|
6301
6348
|
// --- Render ---
|
|
6302
6349
|
render() {
|
|
6303
6350
|
return b `
|
|
6304
|
-
${this.hideToggle ? A : b `
|
|
6351
|
+
${(this.hideToggle || this.variant === 'inline') ? A : b `
|
|
6305
6352
|
<button
|
|
6306
6353
|
class=${e({
|
|
6307
6354
|
'toggle': true,
|
|
@@ -6352,53 +6399,52 @@
|
|
|
6352
6399
|
<span>Drop images to attach</span>
|
|
6353
6400
|
</div>
|
|
6354
6401
|
` : A}
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
|
|
6402
|
+
${this.variant === 'inline' ? A : b `
|
|
6403
|
+
<div
|
|
6404
|
+
class="resize resize--n"
|
|
6405
|
+
data-dir="n"
|
|
6406
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6407
|
+
></div>
|
|
6408
|
+
<div
|
|
6409
|
+
class="resize resize--s"
|
|
6410
|
+
data-dir="s"
|
|
6411
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6412
|
+
></div>
|
|
6413
|
+
<div
|
|
6414
|
+
class="resize resize--w"
|
|
6415
|
+
data-dir="w"
|
|
6416
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6417
|
+
></div>
|
|
6418
|
+
<div
|
|
6419
|
+
class="resize resize--e"
|
|
6420
|
+
data-dir="e"
|
|
6421
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6422
|
+
></div>
|
|
6423
|
+
<div
|
|
6424
|
+
class="resize resize--nw"
|
|
6425
|
+
data-dir="nw"
|
|
6426
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6427
|
+
></div>
|
|
6428
|
+
<div
|
|
6429
|
+
class="resize resize--ne"
|
|
6430
|
+
data-dir="ne"
|
|
6431
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6432
|
+
></div>
|
|
6433
|
+
<div
|
|
6434
|
+
class="resize resize--sw"
|
|
6435
|
+
data-dir="sw"
|
|
6436
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6437
|
+
></div>
|
|
6438
|
+
<div
|
|
6439
|
+
class="resize resize--se"
|
|
6440
|
+
data-dir="se"
|
|
6441
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6442
|
+
></div>
|
|
6443
|
+
`}
|
|
6395
6444
|
<div class="header" @mousedown=${this._handleHeaderMouseDown}>
|
|
6396
6445
|
<div class="header-left">
|
|
6397
6446
|
<div class="header-info">
|
|
6398
|
-
<span class="header-title">${this.
|
|
6399
|
-
${this.subtitle ? b `
|
|
6400
|
-
<span class="header-subtitle">${this.subtitle}</span>
|
|
6401
|
-
` : A}
|
|
6447
|
+
<span class="header-title">${this.label}</span>
|
|
6402
6448
|
</div>
|
|
6403
6449
|
</div>
|
|
6404
6450
|
<div class="header-actions">
|
|
@@ -6424,77 +6470,84 @@
|
|
|
6424
6470
|
</svg>
|
|
6425
6471
|
</button>
|
|
6426
6472
|
` : A}
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
<svg
|
|
6433
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
6434
|
-
fill="none"
|
|
6435
|
-
viewBox="0 0 24 24"
|
|
6436
|
-
stroke-width="2"
|
|
6437
|
-
stroke="currentColor"
|
|
6438
|
-
class="header-action-icon"
|
|
6473
|
+
${this.variant === 'inline' ? A : b `
|
|
6474
|
+
<button
|
|
6475
|
+
class="header-action"
|
|
6476
|
+
@click=${this._handleToggle}
|
|
6477
|
+
title="Close"
|
|
6439
6478
|
>
|
|
6440
|
-
<
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6479
|
+
<svg
|
|
6480
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
6481
|
+
fill="none"
|
|
6482
|
+
viewBox="0 0 24 24"
|
|
6483
|
+
stroke-width="2"
|
|
6484
|
+
stroke="currentColor"
|
|
6485
|
+
class="header-action-icon"
|
|
6486
|
+
>
|
|
6487
|
+
<path
|
|
6488
|
+
stroke-linecap="round"
|
|
6489
|
+
stroke-linejoin="round"
|
|
6490
|
+
d="M6 18 18 6M6 6l12 12"
|
|
6491
|
+
/>
|
|
6492
|
+
</svg>
|
|
6493
|
+
</button>
|
|
6494
|
+
`}
|
|
6447
6495
|
</div>
|
|
6448
6496
|
</div>
|
|
6449
6497
|
|
|
6450
6498
|
<div class="messages" @scroll=${this._handleMessagesScroll}>
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
<
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6499
|
+
<div class="messages-inner">
|
|
6500
|
+
${this.messages.length === 0 ? b `
|
|
6501
|
+
<div class="empty">
|
|
6502
|
+
<span class="empty-text">What can I help you with?</span>
|
|
6503
|
+
</div>
|
|
6504
|
+
` : A}
|
|
6505
|
+
${this.messages.map((msg) => b `
|
|
6506
|
+
<div class=${e({
|
|
6458
6507
|
'message': true,
|
|
6459
|
-
'message--user': msg.
|
|
6460
|
-
'message--assistant': msg.
|
|
6508
|
+
'message--user': msg.type === 'user',
|
|
6509
|
+
'message--assistant': msg.type === 'assistant',
|
|
6461
6510
|
})}>
|
|
6462
|
-
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6511
|
+
${msg.reasoning ? b `
|
|
6512
|
+
<details class="reasoning">
|
|
6513
|
+
<summary>Thinking</summary>
|
|
6514
|
+
<div class="reasoning-content">${msg.reasoning}</div>
|
|
6515
|
+
</details>
|
|
6516
|
+
` : A}
|
|
6517
|
+
${msg.internalFiles && msg.internalFiles.length ? b `
|
|
6518
|
+
<div class="attachments">
|
|
6519
|
+
${msg.internalFiles.map((img) => b `
|
|
6520
|
+
<button
|
|
6521
|
+
class="attachment"
|
|
6522
|
+
type="button"
|
|
6523
|
+
title=${img.niceName || 'View image'}
|
|
6524
|
+
@click=${() => this._openImage(img)}
|
|
6525
|
+
>
|
|
6526
|
+
<img
|
|
6527
|
+
src="/api/system/integration/aws/bedrock/conversationImage/${img.internalFileID}/view"
|
|
6528
|
+
alt=${img.niceName || ''}
|
|
6529
|
+
/>
|
|
6530
|
+
</button>
|
|
6531
|
+
`)}
|
|
6532
|
+
</div>
|
|
6533
|
+
` : A}
|
|
6534
|
+
${msg.content ? b `
|
|
6535
|
+
<div class="message-content">
|
|
6536
|
+
${msg.type === 'user'
|
|
6485
6537
|
? msg.content
|
|
6486
6538
|
: o(marked.parse(msg.content, { breaks: true }))}
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6539
|
+
</div>
|
|
6540
|
+
` : A}
|
|
6541
|
+
${msg.type === 'assistant' && this._isStreaming && msg === this.messages[this.messages.length - 1] ? b `
|
|
6542
|
+
<div class="typing">
|
|
6543
|
+
<span></span>
|
|
6544
|
+
<span></span>
|
|
6545
|
+
<span></span>
|
|
6546
|
+
</div>
|
|
6547
|
+
` : A}
|
|
6548
|
+
</div>
|
|
6549
|
+
`)}
|
|
6550
|
+
</div>
|
|
6498
6551
|
</div>
|
|
6499
6552
|
|
|
6500
6553
|
${this._error ? b `
|
|
@@ -6520,9 +6573,9 @@
|
|
|
6520
6573
|
` : A}
|
|
6521
6574
|
|
|
6522
6575
|
<div class="footer">
|
|
6523
|
-
${this.
|
|
6576
|
+
${this._pendingInternalFiles.length ? b `
|
|
6524
6577
|
<div class="composer-attachments">
|
|
6525
|
-
${c(this.
|
|
6578
|
+
${c(this._pendingInternalFiles, (p) => p.localId, (p) => b `
|
|
6526
6579
|
<div class="chip">
|
|
6527
6580
|
<img src=${p.previewUrl} alt=${p.name} />
|
|
6528
6581
|
<button
|
|
@@ -6711,6 +6764,28 @@
|
|
|
6711
6764
|
display: flex;
|
|
6712
6765
|
}
|
|
6713
6766
|
|
|
6767
|
+
/* Inline mode: fill the parent container instead of floating bottom-right. */
|
|
6768
|
+
:host([variant='inline']) {
|
|
6769
|
+
position: static;
|
|
6770
|
+
bottom: auto;
|
|
6771
|
+
right: auto;
|
|
6772
|
+
z-index: auto;
|
|
6773
|
+
height: 100%;
|
|
6774
|
+
}
|
|
6775
|
+
|
|
6776
|
+
:host([variant='inline']) .panel {
|
|
6777
|
+
position: relative;
|
|
6778
|
+
bottom: auto;
|
|
6779
|
+
right: auto;
|
|
6780
|
+
width: 100%;
|
|
6781
|
+
height: 100%;
|
|
6782
|
+
max-height: none;
|
|
6783
|
+
border-radius: 0;
|
|
6784
|
+
box-shadow: none;
|
|
6785
|
+
border: none;
|
|
6786
|
+
animation: none;
|
|
6787
|
+
}
|
|
6788
|
+
|
|
6714
6789
|
@keyframes chatbot-panel-in {
|
|
6715
6790
|
from {
|
|
6716
6791
|
opacity: 0;
|
|
@@ -6741,7 +6816,7 @@
|
|
|
6741
6816
|
gap: 10px;
|
|
6742
6817
|
}
|
|
6743
6818
|
|
|
6744
|
-
.header-info {
|
|
6819
|
+
.header-info {
|
|
6745
6820
|
display: flex;
|
|
6746
6821
|
flex-direction: column;
|
|
6747
6822
|
}
|
|
@@ -6751,22 +6826,6 @@
|
|
|
6751
6826
|
font-weight: 600;
|
|
6752
6827
|
}
|
|
6753
6828
|
|
|
6754
|
-
.header-subtitle {
|
|
6755
|
-
color: rgba(255, 255, 255, 0.5);
|
|
6756
|
-
font-size: 11px;
|
|
6757
|
-
display: flex;
|
|
6758
|
-
align-items: center;
|
|
6759
|
-
gap: 4px;
|
|
6760
|
-
}
|
|
6761
|
-
|
|
6762
|
-
.header-subtitle::before {
|
|
6763
|
-
content: '';
|
|
6764
|
-
width: 5px;
|
|
6765
|
-
height: 5px;
|
|
6766
|
-
background: var(--kr-chatbot-success);
|
|
6767
|
-
border-radius: 50%;
|
|
6768
|
-
}
|
|
6769
|
-
|
|
6770
6829
|
.header-actions {
|
|
6771
6830
|
display: flex;
|
|
6772
6831
|
align-items: center;
|
|
@@ -6798,17 +6857,29 @@
|
|
|
6798
6857
|
}
|
|
6799
6858
|
|
|
6800
6859
|
/* Messages */
|
|
6860
|
+
/* Full-width scroll container — keeps the scrollbar at the panel edge. */
|
|
6801
6861
|
.messages {
|
|
6802
6862
|
flex: 1;
|
|
6803
6863
|
overflow-y: auto;
|
|
6804
|
-
padding: 32px;
|
|
6805
6864
|
display: flex;
|
|
6806
6865
|
flex-direction: column;
|
|
6807
|
-
gap: 24px;
|
|
6808
6866
|
scroll-behavior: smooth;
|
|
6809
6867
|
background: white;
|
|
6810
6868
|
}
|
|
6811
6869
|
|
|
6870
|
+
/* Centered, width-capped column that actually holds the messages. */
|
|
6871
|
+
.messages-inner {
|
|
6872
|
+
flex: 1;
|
|
6873
|
+
display: flex;
|
|
6874
|
+
flex-direction: column;
|
|
6875
|
+
gap: 24px;
|
|
6876
|
+
padding: 32px;
|
|
6877
|
+
width: 100%;
|
|
6878
|
+
max-width: 768px;
|
|
6879
|
+
margin-left: auto;
|
|
6880
|
+
margin-right: auto;
|
|
6881
|
+
}
|
|
6882
|
+
|
|
6812
6883
|
.messages::-webkit-scrollbar {
|
|
6813
6884
|
width: 4px;
|
|
6814
6885
|
}
|
|
@@ -6832,7 +6903,7 @@
|
|
|
6832
6903
|
gap: 8px;
|
|
6833
6904
|
}
|
|
6834
6905
|
|
|
6835
|
-
.empty-text {
|
|
6906
|
+
.empty-text {
|
|
6836
6907
|
font-size: 14px;
|
|
6837
6908
|
color: rgb(0 0 0 / 80%);
|
|
6838
6909
|
}
|
|
@@ -6944,7 +7015,7 @@
|
|
|
6944
7015
|
word-wrap: break-word;
|
|
6945
7016
|
}
|
|
6946
7017
|
|
|
6947
|
-
.typing {
|
|
7018
|
+
.typing {
|
|
6948
7019
|
display: flex;
|
|
6949
7020
|
gap: 4px;
|
|
6950
7021
|
padding: 4px 0;
|
|
@@ -7012,6 +7083,15 @@
|
|
|
7012
7083
|
padding: 16px 16px 16px;
|
|
7013
7084
|
flex-shrink: 0;
|
|
7014
7085
|
background: white;
|
|
7086
|
+
width: 100%;
|
|
7087
|
+
max-width: 768px;
|
|
7088
|
+
margin-left: auto;
|
|
7089
|
+
margin-right: auto;
|
|
7090
|
+
}
|
|
7091
|
+
|
|
7092
|
+
/* Inline mode: keep the composer clear of the bottom edge. */
|
|
7093
|
+
:host([variant='inline']) .footer {
|
|
7094
|
+
padding-bottom: 40px;
|
|
7015
7095
|
}
|
|
7016
7096
|
|
|
7017
7097
|
.input-wrapper {
|
|
@@ -7030,6 +7110,15 @@
|
|
|
7030
7110
|
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.04);
|
|
7031
7111
|
}
|
|
7032
7112
|
|
|
7113
|
+
/* Inline mode: keep the border and add a soft floating shadow (ChatGPT/Gemini style). */
|
|
7114
|
+
:host([variant='inline']) .input-wrapper {
|
|
7115
|
+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06), 0 8px 24px rgba(0, 0, 0, 0.1);
|
|
7116
|
+
}
|
|
7117
|
+
|
|
7118
|
+
:host([variant='inline']) .input-wrapper:focus-within {
|
|
7119
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08), 0 12px 32px rgba(0, 0, 0, 0.14);
|
|
7120
|
+
}
|
|
7121
|
+
|
|
7033
7122
|
.input-plus {
|
|
7034
7123
|
width: 34px;
|
|
7035
7124
|
height: 34px;
|
|
@@ -7137,6 +7226,12 @@
|
|
|
7137
7226
|
cursor: grabbing;
|
|
7138
7227
|
}
|
|
7139
7228
|
|
|
7229
|
+
/* Inline mode isn't draggable — don't show the grab/hand cursor. */
|
|
7230
|
+
:host([variant='inline']) .header,
|
|
7231
|
+
:host([variant='inline']) .header:active {
|
|
7232
|
+
cursor: default;
|
|
7233
|
+
}
|
|
7234
|
+
|
|
7140
7235
|
/* Drag / Resize states */
|
|
7141
7236
|
.panel--dragging,
|
|
7142
7237
|
.panel--resizing {
|
|
@@ -7288,10 +7383,7 @@
|
|
|
7288
7383
|
], exports.Chatbot.prototype, "messages", void 0);
|
|
7289
7384
|
__decorate([
|
|
7290
7385
|
n({ type: String })
|
|
7291
|
-
], exports.Chatbot.prototype, "
|
|
7292
|
-
__decorate([
|
|
7293
|
-
n({ type: String })
|
|
7294
|
-
], exports.Chatbot.prototype, "subtitle", void 0);
|
|
7386
|
+
], exports.Chatbot.prototype, "label", void 0);
|
|
7295
7387
|
__decorate([
|
|
7296
7388
|
n({ type: String })
|
|
7297
7389
|
], exports.Chatbot.prototype, "placeholder", void 0);
|
|
@@ -7308,21 +7400,24 @@
|
|
|
7308
7400
|
reflect: true
|
|
7309
7401
|
})
|
|
7310
7402
|
], exports.Chatbot.prototype, "hideToggle", void 0);
|
|
7403
|
+
__decorate([
|
|
7404
|
+
n({
|
|
7405
|
+
type: String,
|
|
7406
|
+
reflect: true
|
|
7407
|
+
})
|
|
7408
|
+
], exports.Chatbot.prototype, "variant", void 0);
|
|
7311
7409
|
__decorate([
|
|
7312
7410
|
r()
|
|
7313
7411
|
], exports.Chatbot.prototype, "_inputValue", void 0);
|
|
7314
7412
|
__decorate([
|
|
7315
7413
|
r()
|
|
7316
7414
|
], exports.Chatbot.prototype, "_isStreaming", void 0);
|
|
7317
|
-
__decorate([
|
|
7318
|
-
r()
|
|
7319
|
-
], exports.Chatbot.prototype, "_statusText", void 0);
|
|
7320
7415
|
__decorate([
|
|
7321
7416
|
r()
|
|
7322
7417
|
], exports.Chatbot.prototype, "_error", void 0);
|
|
7323
7418
|
__decorate([
|
|
7324
7419
|
r()
|
|
7325
|
-
], exports.Chatbot.prototype, "
|
|
7420
|
+
], exports.Chatbot.prototype, "_pendingInternalFiles", void 0);
|
|
7326
7421
|
__decorate([
|
|
7327
7422
|
r()
|
|
7328
7423
|
], exports.Chatbot.prototype, "_isDraggingFile", void 0);
|