@kodaris/krubble-app-components 1.0.70 → 1.0.72
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 +137 -26
- package/dist/chatbot.d.ts.map +1 -1
- package/dist/chatbot.js +881 -206
- package/dist/chatbot.js.map +1 -1
- package/dist/krubble-app.bundled.js +878 -206
- package/dist/krubble-app.bundled.js.map +1 -1
- package/dist/krubble-app.bundled.min.js +563 -175
- package/dist/krubble-app.bundled.min.js.map +1 -1
- package/dist/krubble-app.umd.js +878 -206
- package/dist/krubble-app.umd.js.map +1 -1
- package/dist/krubble-app.umd.min.js +579 -191
- 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,17 +5640,19 @@
|
|
|
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
|
*/
|
|
5644
5649
|
this.placeholder = 'Type a message...';
|
|
5650
|
+
/**
|
|
5651
|
+
* Skills the user can invoke by typing `/` in the composer. Selecting one
|
|
5652
|
+
* inserts `/name ` into the message. The `/` menu shows the first 15 (filtered
|
|
5653
|
+
* as the user types); "Browse all skills" opens a dialog with the full list.
|
|
5654
|
+
*/
|
|
5655
|
+
this.skills = [];
|
|
5645
5656
|
/**
|
|
5646
5657
|
* Whether the chat panel is open. Only relevant in floating mode.
|
|
5647
5658
|
*/
|
|
@@ -5652,15 +5663,39 @@
|
|
|
5652
5663
|
* then driven via the `open()` / `close()` / `toggle()` methods.
|
|
5653
5664
|
*/
|
|
5654
5665
|
this.hideToggle = false;
|
|
5666
|
+
/**
|
|
5667
|
+
* Layout mode.
|
|
5668
|
+
* - `'floating'` (default): the chatbot is a fixed bottom-right widget with a
|
|
5669
|
+
* toggle button, and the panel can be dragged and resized. This is the
|
|
5670
|
+
* traditional chat-widget appearance.
|
|
5671
|
+
* - `'inline'`: the chatbot drops its fixed positioning and fills its parent
|
|
5672
|
+
* container (100% width/height, no border radius/shadow, no toggle, no
|
|
5673
|
+
* drag/resize). The panel is always open. Use this to embed the chat as a
|
|
5674
|
+
* full page or panel region.
|
|
5675
|
+
*/
|
|
5676
|
+
this.variant = 'floating';
|
|
5655
5677
|
// --- @state (internal) ---
|
|
5656
5678
|
this._inputValue = '';
|
|
5657
5679
|
this._isStreaming = false;
|
|
5658
|
-
this._statusText = '';
|
|
5659
5680
|
this._error = '';
|
|
5660
5681
|
/** Images staged in the composer, before the message is sent. */
|
|
5661
|
-
this.
|
|
5682
|
+
this._pendingInternalFiles = [];
|
|
5662
5683
|
/** True while a file is being dragged over the panel (shows the drop overlay). */
|
|
5663
5684
|
this._isDraggingFile = false;
|
|
5685
|
+
/** Whether the `/` skill menu is open above the composer. */
|
|
5686
|
+
this._skillMenuOpened = false;
|
|
5687
|
+
/** Current `/` query (text after the slash), used to filter the skill menu. */
|
|
5688
|
+
this._skillQuery = '';
|
|
5689
|
+
/** Highlighted item in the skill menu for keyboard navigation (-1 = none). */
|
|
5690
|
+
this._skillHighlighted = 0;
|
|
5691
|
+
/** Index of the message whose copy button just flashed "Copied" (-1 = none). */
|
|
5692
|
+
this._copiedIndex = -1;
|
|
5693
|
+
/** Whether the "Browse all skills" dialog is open. */
|
|
5694
|
+
this._skillBrowseOpened = false;
|
|
5695
|
+
/** Active tab in the browse dialog. */
|
|
5696
|
+
this._skillBrowseSource = 'org';
|
|
5697
|
+
/** Search text in the browse dialog. */
|
|
5698
|
+
this._skillBrowseQuery = '';
|
|
5664
5699
|
this._handleMouseMove = (e) => {
|
|
5665
5700
|
if (this._isDragging) {
|
|
5666
5701
|
let newLeft = this._dragStartLeft + (e.clientX - this._dragStartX);
|
|
@@ -5722,12 +5757,27 @@
|
|
|
5722
5757
|
// --- Lifecycle ---
|
|
5723
5758
|
connectedCallback() {
|
|
5724
5759
|
super.connectedCallback();
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5760
|
+
// Default to loading existing messages from the Kodaris Bedrock conversation
|
|
5761
|
+
// when the consumer hasn't provided their own `load`. The endpoint returns
|
|
5762
|
+
// messages already in KRChatbotMessage shape ({ type, content, images }), so
|
|
5763
|
+
// they pass straight through.
|
|
5764
|
+
if (!this.load) {
|
|
5765
|
+
this.load = () => krubbleHttp.Http.fetch({
|
|
5766
|
+
url: '/api/system/integration/aws/bedrock/getConversationMessages',
|
|
5767
|
+
})
|
|
5768
|
+
.then((r) => r.json())
|
|
5769
|
+
.then((res) => res.data || []);
|
|
5770
|
+
}
|
|
5771
|
+
this.load().then((messages) => {
|
|
5772
|
+
if (messages && messages.length) {
|
|
5773
|
+
this.messages = messages;
|
|
5774
|
+
}
|
|
5775
|
+
}).catch(() => { });
|
|
5776
|
+
// Inline mode fills its container and is always open — the floating widget's
|
|
5777
|
+
// toggle/drag/resize state (including any persisted layout) doesn't apply.
|
|
5778
|
+
if (this.variant === 'inline') {
|
|
5779
|
+
this.opened = true;
|
|
5780
|
+
return;
|
|
5731
5781
|
}
|
|
5732
5782
|
this._restoreState();
|
|
5733
5783
|
}
|
|
@@ -5740,10 +5790,10 @@
|
|
|
5740
5790
|
document.removeEventListener('mousemove', this._handleMouseMove);
|
|
5741
5791
|
document.removeEventListener('mouseup', this._handleMouseUp);
|
|
5742
5792
|
// Release any object URLs still held by staged attachments.
|
|
5743
|
-
this.
|
|
5793
|
+
this._pendingInternalFiles.forEach((p) => URL.revokeObjectURL(p.previewUrl));
|
|
5744
5794
|
}
|
|
5745
5795
|
updated(changed) {
|
|
5746
|
-
if (changed.has('messages')
|
|
5796
|
+
if (changed.has('messages')) {
|
|
5747
5797
|
if (!this._userHasScrolledUp && !this._isStreaming && this._messagesEl) {
|
|
5748
5798
|
requestAnimationFrame(() => {
|
|
5749
5799
|
if (this._messagesEl) {
|
|
@@ -5759,6 +5809,40 @@
|
|
|
5759
5809
|
}
|
|
5760
5810
|
}, 200);
|
|
5761
5811
|
}
|
|
5812
|
+
// Position the fixed skill menu above the composer, following the krubble
|
|
5813
|
+
// select-field pattern (fixed element positioned from the trigger's rect).
|
|
5814
|
+
if (this._skillMenuOpened) {
|
|
5815
|
+
this._positionSkillMenu();
|
|
5816
|
+
}
|
|
5817
|
+
// Keep the keyboard-highlighted skill scrolled into view.
|
|
5818
|
+
if (changed.has('_skillHighlighted') && this._skillMenuOpened) {
|
|
5819
|
+
this._skillMenuEl
|
|
5820
|
+
?.querySelector('.skill-menu__item--highlighted')
|
|
5821
|
+
?.scrollIntoView({ block: 'nearest' });
|
|
5822
|
+
}
|
|
5823
|
+
}
|
|
5824
|
+
/** Anchor the fixed skill menu to the composer, opening upward above it. */
|
|
5825
|
+
_positionSkillMenu() {
|
|
5826
|
+
requestAnimationFrame(() => {
|
|
5827
|
+
if (!this._skillMenuEl || !this._inputWrapperEl) {
|
|
5828
|
+
return;
|
|
5829
|
+
}
|
|
5830
|
+
const inputRect = this._inputWrapperEl.getBoundingClientRect();
|
|
5831
|
+
this._skillMenuEl.style.left = inputRect.left + 'px';
|
|
5832
|
+
this._skillMenuEl.style.width = inputRect.width + 'px';
|
|
5833
|
+
// Bound the menu by the chat panel's own top edge so it stays within the
|
|
5834
|
+
// widget. In floating mode that keeps it inside the card; in inline mode the
|
|
5835
|
+
// panel top sits just below the app header/breadcrumb, so it stays clear of
|
|
5836
|
+
// those too. An 8px gap keeps it off both edges.
|
|
5837
|
+
const topLimit = this._panelEl.getBoundingClientRect().top + 8;
|
|
5838
|
+
const spaceAbove = inputRect.top - 8 - topLimit;
|
|
5839
|
+
this._skillMenuEl.style.maxHeight = spaceAbove + 'px';
|
|
5840
|
+
// Measure after the cap is applied so the upward anchor uses the real
|
|
5841
|
+
// height, then clamp the top edge to the panel bound.
|
|
5842
|
+
const menuRect = this._skillMenuEl.getBoundingClientRect();
|
|
5843
|
+
const top = Math.max(topLimit, inputRect.top - menuRect.height - 8);
|
|
5844
|
+
this._skillMenuEl.style.top = top + 'px';
|
|
5845
|
+
});
|
|
5762
5846
|
}
|
|
5763
5847
|
// --- Public methods ---
|
|
5764
5848
|
/**
|
|
@@ -5817,6 +5901,10 @@
|
|
|
5817
5901
|
}
|
|
5818
5902
|
}
|
|
5819
5903
|
_handleHeaderMouseDown(e) {
|
|
5904
|
+
// Inline mode fills its parent — dragging the panel doesn't apply.
|
|
5905
|
+
if (this.variant === 'inline') {
|
|
5906
|
+
return;
|
|
5907
|
+
}
|
|
5820
5908
|
// Ignore clicks on buttons inside the header
|
|
5821
5909
|
if (e.target.closest('button')) {
|
|
5822
5910
|
return;
|
|
@@ -5842,6 +5930,10 @@
|
|
|
5842
5930
|
document.addEventListener('mouseup', this._handleMouseUp);
|
|
5843
5931
|
}
|
|
5844
5932
|
_handleResizeMouseDown(e) {
|
|
5933
|
+
// Inline mode fills its parent — resizing the panel doesn't apply.
|
|
5934
|
+
if (this.variant === 'inline') {
|
|
5935
|
+
return;
|
|
5936
|
+
}
|
|
5845
5937
|
if (!this._panelEl) {
|
|
5846
5938
|
return;
|
|
5847
5939
|
}
|
|
@@ -5944,13 +6036,129 @@
|
|
|
5944
6036
|
const textarea = e.target;
|
|
5945
6037
|
textarea.style.height = 'auto';
|
|
5946
6038
|
textarea.style.height = Math.min(textarea.scrollHeight, 120) + 'px';
|
|
6039
|
+
// Open the skill menu while the message is a `/` command being typed (a
|
|
6040
|
+
// leading slash with no space yet). The text after the slash filters it.
|
|
6041
|
+
const slashMatch = this._inputValue.match(/^\/(\S*)$/);
|
|
6042
|
+
if (slashMatch && this.skills.length) {
|
|
6043
|
+
this._skillMenuOpened = true;
|
|
6044
|
+
this._skillQuery = slashMatch[1];
|
|
6045
|
+
this._skillHighlighted = 0;
|
|
6046
|
+
}
|
|
6047
|
+
else {
|
|
6048
|
+
this._skillMenuOpened = false;
|
|
6049
|
+
}
|
|
5947
6050
|
}
|
|
5948
6051
|
_handleKeyDown(e) {
|
|
6052
|
+
// When the skill menu is open, arrow keys / Enter / Escape drive it. The two
|
|
6053
|
+
// top actions (Attach Files, Browse All Skills) are index 0 and 1, then the
|
|
6054
|
+
// filtered skills follow — all navigable as one list.
|
|
6055
|
+
if (this._skillMenuOpened) {
|
|
6056
|
+
const count = 2 + this._filteredSkills().length;
|
|
6057
|
+
if (e.key === 'ArrowDown') {
|
|
6058
|
+
e.preventDefault();
|
|
6059
|
+
this._skillHighlighted = (this._skillHighlighted + 1) % count;
|
|
6060
|
+
return;
|
|
6061
|
+
}
|
|
6062
|
+
if (e.key === 'ArrowUp') {
|
|
6063
|
+
e.preventDefault();
|
|
6064
|
+
this._skillHighlighted = (this._skillHighlighted - 1 + count) % count;
|
|
6065
|
+
return;
|
|
6066
|
+
}
|
|
6067
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
6068
|
+
e.preventDefault();
|
|
6069
|
+
this._activateSkillMenuItem(this._skillHighlighted);
|
|
6070
|
+
return;
|
|
6071
|
+
}
|
|
6072
|
+
if (e.key === 'Escape') {
|
|
6073
|
+
e.preventDefault();
|
|
6074
|
+
this._skillMenuOpened = false;
|
|
6075
|
+
return;
|
|
6076
|
+
}
|
|
6077
|
+
}
|
|
5949
6078
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
5950
6079
|
e.preventDefault();
|
|
5951
6080
|
this._handleSubmit();
|
|
5952
6081
|
}
|
|
5953
6082
|
}
|
|
6083
|
+
/** Run the skill-menu item at the given flat index (0/1 = actions, then skills). */
|
|
6084
|
+
_activateSkillMenuItem(index) {
|
|
6085
|
+
if (index === 0) {
|
|
6086
|
+
this._openFilePicker();
|
|
6087
|
+
return;
|
|
6088
|
+
}
|
|
6089
|
+
if (index === 1) {
|
|
6090
|
+
this._handleSkillBrowseOpen();
|
|
6091
|
+
return;
|
|
6092
|
+
}
|
|
6093
|
+
const skill = this._filteredSkills()[index - 2];
|
|
6094
|
+
if (skill) {
|
|
6095
|
+
this._handleSkillSelect(skill);
|
|
6096
|
+
}
|
|
6097
|
+
}
|
|
6098
|
+
// --- Skills ---
|
|
6099
|
+
/** Skills matching the current `/` query, capped at the first 15. */
|
|
6100
|
+
_filteredSkills() {
|
|
6101
|
+
const query = this._skillQuery.toLowerCase();
|
|
6102
|
+
return this.skills
|
|
6103
|
+
.filter((skill) => skill.name.toLowerCase().includes(query) ||
|
|
6104
|
+
skill.label.toLowerCase().includes(query))
|
|
6105
|
+
.slice(0, 15);
|
|
6106
|
+
}
|
|
6107
|
+
/** The `+` button toggles the skill/attachment menu open (showing all skills). */
|
|
6108
|
+
_handlePlusClick() {
|
|
6109
|
+
if (this._skillMenuOpened) {
|
|
6110
|
+
this._skillMenuOpened = false;
|
|
6111
|
+
return;
|
|
6112
|
+
}
|
|
6113
|
+
this._skillQuery = '';
|
|
6114
|
+
this._skillHighlighted = 0;
|
|
6115
|
+
this._skillMenuOpened = true;
|
|
6116
|
+
}
|
|
6117
|
+
/** Insert `/name ` into the composer and focus it, ready for the message. */
|
|
6118
|
+
_handleSkillSelect(skill) {
|
|
6119
|
+
this._inputValue = `/${skill.name} `;
|
|
6120
|
+
this._skillMenuOpened = false;
|
|
6121
|
+
this._skillBrowseOpened = false;
|
|
6122
|
+
this._inputEl?.focus();
|
|
6123
|
+
}
|
|
6124
|
+
/** Copy a message's text to the clipboard and briefly flash "Copied". */
|
|
6125
|
+
_handleCopyMessage(content, index) {
|
|
6126
|
+
navigator.clipboard.writeText(content).then(() => {
|
|
6127
|
+
this._copiedIndex = index;
|
|
6128
|
+
setTimeout(() => {
|
|
6129
|
+
if (this._copiedIndex === index) {
|
|
6130
|
+
this._copiedIndex = -1;
|
|
6131
|
+
}
|
|
6132
|
+
}, 2000);
|
|
6133
|
+
}).catch(() => { });
|
|
6134
|
+
}
|
|
6135
|
+
_handleSkillBrowseOpen() {
|
|
6136
|
+
this._skillMenuOpened = false;
|
|
6137
|
+
this._skillBrowseQuery = '';
|
|
6138
|
+
this._skillBrowseOpened = true;
|
|
6139
|
+
}
|
|
6140
|
+
_handleSkillBrowseClose() {
|
|
6141
|
+
this._skillBrowseOpened = false;
|
|
6142
|
+
}
|
|
6143
|
+
_handleSkillBrowseSearch(e) {
|
|
6144
|
+
this._skillBrowseQuery = e.target.value;
|
|
6145
|
+
}
|
|
6146
|
+
_handleSkillBrowseTabChange(e) {
|
|
6147
|
+
this._skillBrowseSource = e.detail.activeTabId;
|
|
6148
|
+
}
|
|
6149
|
+
/** Skills for the browse dialog's active tab, filtered by its search box. */
|
|
6150
|
+
_browseSkills() {
|
|
6151
|
+
const query = this._skillBrowseQuery.toLowerCase();
|
|
6152
|
+
return this.skills.filter((skill) => {
|
|
6153
|
+
const source = skill.source || 'org';
|
|
6154
|
+
if (source !== this._skillBrowseSource) {
|
|
6155
|
+
return false;
|
|
6156
|
+
}
|
|
6157
|
+
return skill.name.toLowerCase().includes(query) ||
|
|
6158
|
+
skill.label.toLowerCase().includes(query) ||
|
|
6159
|
+
(skill.description || '').toLowerCase().includes(query);
|
|
6160
|
+
});
|
|
6161
|
+
}
|
|
5954
6162
|
// --- Attachments ---
|
|
5955
6163
|
_openFilePicker() {
|
|
5956
6164
|
this._fileInputEl?.click();
|
|
@@ -6034,54 +6242,49 @@
|
|
|
6034
6242
|
name: file.name,
|
|
6035
6243
|
previewUrl: URL.createObjectURL(file),
|
|
6036
6244
|
};
|
|
6037
|
-
this.
|
|
6245
|
+
this._pendingInternalFiles = [...this._pendingInternalFiles, pending];
|
|
6038
6246
|
});
|
|
6039
6247
|
}
|
|
6040
6248
|
_removePending(localId) {
|
|
6041
|
-
const target = this.
|
|
6249
|
+
const target = this._pendingInternalFiles.find((p) => p.localId === localId);
|
|
6042
6250
|
if (target) {
|
|
6043
6251
|
URL.revokeObjectURL(target.previewUrl);
|
|
6044
6252
|
}
|
|
6045
|
-
this.
|
|
6253
|
+
this._pendingInternalFiles = this._pendingInternalFiles.filter((p) => p.localId !== localId);
|
|
6046
6254
|
}
|
|
6047
6255
|
_clearPending() {
|
|
6048
|
-
this.
|
|
6049
|
-
this.
|
|
6256
|
+
this._pendingInternalFiles.forEach((p) => URL.revokeObjectURL(p.previewUrl));
|
|
6257
|
+
this._pendingInternalFiles = [];
|
|
6050
6258
|
}
|
|
6051
|
-
/** Open the shared full-screen previewer for
|
|
6052
|
-
|
|
6259
|
+
/** Open the shared full-screen previewer for a message image. */
|
|
6260
|
+
_openImage(img) {
|
|
6053
6261
|
krubbleComponents.FilePreview.open({
|
|
6054
|
-
src:
|
|
6055
|
-
name:
|
|
6262
|
+
src: `/api/system/integration/aws/bedrock/conversationImage/${img.internalFileID}/view`,
|
|
6263
|
+
name: img.niceName || 'image',
|
|
6056
6264
|
});
|
|
6057
6265
|
}
|
|
6058
6266
|
/** Whether the send button is active: needs text or at least one image. */
|
|
6059
6267
|
_canSend() {
|
|
6060
|
-
return Boolean(this._inputValue.trim()) || this.
|
|
6268
|
+
return Boolean(this._inputValue.trim()) || this._pendingInternalFiles.length > 0;
|
|
6061
6269
|
}
|
|
6062
6270
|
_handleSubmit() {
|
|
6063
|
-
if (
|
|
6271
|
+
if (this._isStreaming) {
|
|
6064
6272
|
return;
|
|
6065
6273
|
}
|
|
6066
6274
|
const messageText = this._inputValue.trim();
|
|
6067
|
-
const pending = this.
|
|
6275
|
+
const pending = this._pendingInternalFiles;
|
|
6068
6276
|
// Allow sending an image with no text, but require at least one of them.
|
|
6069
6277
|
if (!messageText && !pending.length) {
|
|
6070
6278
|
return;
|
|
6071
6279
|
}
|
|
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
|
-
}));
|
|
6280
|
+
// The raw files sent to the backend. Sent images are shown once the
|
|
6281
|
+
// conversation reloads and they come back as stored internal files; the
|
|
6282
|
+
// just-sent message itself carries text only.
|
|
6283
|
+
const internalFiles = pending.map((p) => p.file);
|
|
6081
6284
|
const submitEvent = new CustomEvent('message-submit', {
|
|
6082
6285
|
detail: {
|
|
6083
6286
|
message: messageText,
|
|
6084
|
-
|
|
6287
|
+
internalFiles,
|
|
6085
6288
|
},
|
|
6086
6289
|
bubbles: true,
|
|
6087
6290
|
composed: true,
|
|
@@ -6092,30 +6295,26 @@
|
|
|
6092
6295
|
return;
|
|
6093
6296
|
}
|
|
6094
6297
|
const userMessage = {
|
|
6095
|
-
|
|
6298
|
+
type: 'user',
|
|
6096
6299
|
content: messageText,
|
|
6097
6300
|
};
|
|
6098
|
-
if (attachments.length) {
|
|
6099
|
-
userMessage.attachments = attachments;
|
|
6100
|
-
}
|
|
6101
6301
|
this.messages = [...this.messages, userMessage];
|
|
6102
6302
|
this._inputValue = '';
|
|
6103
6303
|
this._error = '';
|
|
6104
6304
|
this._userHasScrolledUp = false;
|
|
6105
|
-
// Clear the composer
|
|
6106
|
-
|
|
6107
|
-
this.
|
|
6305
|
+
// Clear the composer and release its preview object URLs.
|
|
6306
|
+
this._pendingInternalFiles.forEach((p) => URL.revokeObjectURL(p.previewUrl));
|
|
6307
|
+
this._pendingInternalFiles = [];
|
|
6108
6308
|
// Reset textarea height
|
|
6109
6309
|
if (this._inputEl) {
|
|
6110
6310
|
this._inputEl.style.height = 'auto';
|
|
6111
6311
|
}
|
|
6112
6312
|
// Add empty assistant message to stream into
|
|
6113
6313
|
this.messages = [...this.messages, {
|
|
6114
|
-
|
|
6314
|
+
type: 'assistant',
|
|
6115
6315
|
content: '',
|
|
6116
6316
|
}];
|
|
6117
6317
|
this._isStreaming = true;
|
|
6118
|
-
this._statusText = '';
|
|
6119
6318
|
// Scroll user's message to the top (Gemini-style).
|
|
6120
6319
|
// Set min-height on the assistant message = container height so there's enough
|
|
6121
6320
|
// scroll room below the user message to push it to the top.
|
|
@@ -6137,10 +6336,34 @@
|
|
|
6137
6336
|
this._messagesEl.scrollTop = userMsgEl.offsetTop - this._messagesEl.offsetTop - 24;
|
|
6138
6337
|
}
|
|
6139
6338
|
});
|
|
6339
|
+
// Default to streaming from the Kodaris Bedrock conversation endpoints when
|
|
6340
|
+
// the consumer hasn't provided their own `send`.
|
|
6341
|
+
if (!this.send) {
|
|
6342
|
+
this.send = (params) => {
|
|
6343
|
+
// With images, post text + files as multipart; without, post plain JSON.
|
|
6344
|
+
if (params.internalFiles.length) {
|
|
6345
|
+
const form = new FormData();
|
|
6346
|
+
form.append('userText', params.message);
|
|
6347
|
+
params.internalFiles.forEach((file) => form.append('images', file));
|
|
6348
|
+
return krubbleHttp.Http.fetch({
|
|
6349
|
+
url: '/api/system/integration/aws/bedrock/stream/invokeModelForConversationWithImages',
|
|
6350
|
+
method: 'POST',
|
|
6351
|
+
headers: { Accept: 'text/event-stream' },
|
|
6352
|
+
body: form,
|
|
6353
|
+
});
|
|
6354
|
+
}
|
|
6355
|
+
return krubbleHttp.Http.fetch({
|
|
6356
|
+
url: '/api/system/integration/aws/bedrock/stream/invokeModelForConversationWithState',
|
|
6357
|
+
method: 'POST',
|
|
6358
|
+
headers: { Accept: 'text/event-stream' },
|
|
6359
|
+
body: { userText: params.message },
|
|
6360
|
+
});
|
|
6361
|
+
};
|
|
6362
|
+
}
|
|
6140
6363
|
this.send({
|
|
6141
6364
|
message: messageText,
|
|
6142
6365
|
messages: this.messages.slice(0, -1),
|
|
6143
|
-
|
|
6366
|
+
internalFiles,
|
|
6144
6367
|
}).then((response) => {
|
|
6145
6368
|
if (!response.ok) {
|
|
6146
6369
|
this._handleStreamError('Request failed: ' + response.status);
|
|
@@ -6166,11 +6389,15 @@
|
|
|
6166
6389
|
this._reader = null;
|
|
6167
6390
|
}
|
|
6168
6391
|
this._isStreaming = false;
|
|
6169
|
-
this._statusText = '';
|
|
6170
6392
|
}
|
|
6171
6393
|
_handleClear() {
|
|
6394
|
+
// Default to clearing the Kodaris Bedrock conversation state when the consumer
|
|
6395
|
+
// hasn't provided their own `clear`.
|
|
6172
6396
|
if (!this.clear) {
|
|
6173
|
-
|
|
6397
|
+
this.clear = () => krubbleHttp.Http.fetch({
|
|
6398
|
+
url: '/api/system/integration/aws/bedrock/clearConversationWithState',
|
|
6399
|
+
method: 'POST',
|
|
6400
|
+
});
|
|
6174
6401
|
}
|
|
6175
6402
|
this.clear().then(() => {
|
|
6176
6403
|
if (this._reader) {
|
|
@@ -6179,7 +6406,6 @@
|
|
|
6179
6406
|
}
|
|
6180
6407
|
this.messages = [];
|
|
6181
6408
|
this._isStreaming = false;
|
|
6182
|
-
this._statusText = '';
|
|
6183
6409
|
this._error = '';
|
|
6184
6410
|
this._inputValue = '';
|
|
6185
6411
|
this._userHasScrolledUp = false;
|
|
@@ -6205,7 +6431,6 @@
|
|
|
6205
6431
|
this._reader.read().then((result) => {
|
|
6206
6432
|
if (result.done) {
|
|
6207
6433
|
this._isStreaming = false;
|
|
6208
|
-
this._statusText = '';
|
|
6209
6434
|
this._reader = null;
|
|
6210
6435
|
return;
|
|
6211
6436
|
}
|
|
@@ -6238,15 +6463,10 @@
|
|
|
6238
6463
|
bubbles: true,
|
|
6239
6464
|
composed: true,
|
|
6240
6465
|
}));
|
|
6241
|
-
if (data.type === '
|
|
6242
|
-
if (data.message) {
|
|
6243
|
-
this._statusText = String(data.message);
|
|
6244
|
-
}
|
|
6245
|
-
}
|
|
6246
|
-
else if (data.type === 'REASONING_PART') {
|
|
6466
|
+
if (data.type === 'REASONING_PART') {
|
|
6247
6467
|
if (data.message) {
|
|
6248
6468
|
const lastIndex = this.messages.length - 1;
|
|
6249
|
-
if (lastIndex >= 0 && this.messages[lastIndex].
|
|
6469
|
+
if (lastIndex >= 0 && this.messages[lastIndex].type === 'assistant') {
|
|
6250
6470
|
if (!this.messages[lastIndex].reasoning) {
|
|
6251
6471
|
this.messages[lastIndex].reasoning = '';
|
|
6252
6472
|
}
|
|
@@ -6257,9 +6477,8 @@
|
|
|
6257
6477
|
}
|
|
6258
6478
|
else if (data.type === 'RESPONSE_PART') {
|
|
6259
6479
|
if (data.message) {
|
|
6260
|
-
this._statusText = '';
|
|
6261
6480
|
const lastIndex = this.messages.length - 1;
|
|
6262
|
-
if (lastIndex >= 0 && this.messages[lastIndex].
|
|
6481
|
+
if (lastIndex >= 0 && this.messages[lastIndex].type === 'assistant') {
|
|
6263
6482
|
this.messages[lastIndex].content += String(data.message);
|
|
6264
6483
|
this.requestUpdate();
|
|
6265
6484
|
}
|
|
@@ -6270,7 +6489,6 @@
|
|
|
6270
6489
|
}
|
|
6271
6490
|
if (data.finished) {
|
|
6272
6491
|
this._isStreaming = false;
|
|
6273
|
-
this._statusText = '';
|
|
6274
6492
|
this._reader = null;
|
|
6275
6493
|
}
|
|
6276
6494
|
}
|
|
@@ -6284,7 +6502,6 @@
|
|
|
6284
6502
|
}
|
|
6285
6503
|
_handleStreamError(message) {
|
|
6286
6504
|
this._isStreaming = false;
|
|
6287
|
-
this._statusText = '';
|
|
6288
6505
|
this._error = message;
|
|
6289
6506
|
if (this._reader) {
|
|
6290
6507
|
this._reader.cancel();
|
|
@@ -6293,15 +6510,128 @@
|
|
|
6293
6510
|
// Remove the empty assistant message if it has no content
|
|
6294
6511
|
if (this.messages.length > 0) {
|
|
6295
6512
|
const lastMessage = this.messages[this.messages.length - 1];
|
|
6296
|
-
if (lastMessage.
|
|
6513
|
+
if (lastMessage.type === 'assistant' && !lastMessage.content) {
|
|
6297
6514
|
this.messages = this.messages.slice(0, -1);
|
|
6298
6515
|
}
|
|
6299
6516
|
}
|
|
6300
6517
|
}
|
|
6301
6518
|
// --- Render ---
|
|
6519
|
+
/** The `/` skill menu shown above the composer while typing a slash command. */
|
|
6520
|
+
_renderSkillMenu() {
|
|
6521
|
+
const skills = this._filteredSkills();
|
|
6522
|
+
return b `
|
|
6523
|
+
<div class="skill-menu">
|
|
6524
|
+
<div class="skill-menu__actions">
|
|
6525
|
+
<button
|
|
6526
|
+
class=${e({
|
|
6527
|
+
'skill-menu__action': true,
|
|
6528
|
+
'skill-menu__item--highlighted': this._skillHighlighted === 0,
|
|
6529
|
+
})}
|
|
6530
|
+
@click=${this._openFilePicker}
|
|
6531
|
+
>
|
|
6532
|
+
Attach Files
|
|
6533
|
+
</button>
|
|
6534
|
+
<button
|
|
6535
|
+
class=${e({
|
|
6536
|
+
'skill-menu__action': true,
|
|
6537
|
+
'skill-menu__item--highlighted': this._skillHighlighted === 1,
|
|
6538
|
+
})}
|
|
6539
|
+
@click=${this._handleSkillBrowseOpen}
|
|
6540
|
+
>
|
|
6541
|
+
Browse All Skills
|
|
6542
|
+
</button>
|
|
6543
|
+
</div>
|
|
6544
|
+
${skills.length ? b `
|
|
6545
|
+
<ul class="skill-menu__list">
|
|
6546
|
+
${skills.map((skill, index) => b `
|
|
6547
|
+
<li>
|
|
6548
|
+
<button
|
|
6549
|
+
class=${e({
|
|
6550
|
+
'skill-menu__item': true,
|
|
6551
|
+
'skill-menu__item--highlighted': index + 2 === this._skillHighlighted,
|
|
6552
|
+
})}
|
|
6553
|
+
@click=${() => this._handleSkillSelect(skill)}
|
|
6554
|
+
>
|
|
6555
|
+
<span class="skill-menu__name">${skill.label}</span>
|
|
6556
|
+
${skill.description ? b `
|
|
6557
|
+
<span class="skill-menu__desc">${skill.description}</span>
|
|
6558
|
+
` : A}
|
|
6559
|
+
</button>
|
|
6560
|
+
</li>
|
|
6561
|
+
`)}
|
|
6562
|
+
</ul>
|
|
6563
|
+
` : b `
|
|
6564
|
+
<div class="skill-menu__empty">No matching skills</div>
|
|
6565
|
+
`}
|
|
6566
|
+
</div>
|
|
6567
|
+
`;
|
|
6568
|
+
}
|
|
6569
|
+
/** The "Browse all skills" dialog — a searchable grid of Org / Kodaris cards. */
|
|
6570
|
+
_renderSkillBrowse() {
|
|
6571
|
+
return b `
|
|
6572
|
+
<kr-dialog
|
|
6573
|
+
opened
|
|
6574
|
+
label="Browse Skills"
|
|
6575
|
+
width="720px"
|
|
6576
|
+
@close=${this._handleSkillBrowseClose}
|
|
6577
|
+
>
|
|
6578
|
+
<div class="skill-browse">
|
|
6579
|
+
<kr-text-field
|
|
6580
|
+
placeholder="Search skills..."
|
|
6581
|
+
.value=${this._skillBrowseQuery}
|
|
6582
|
+
@input=${this._handleSkillBrowseSearch}
|
|
6583
|
+
></kr-text-field>
|
|
6584
|
+
<kr-tab-group
|
|
6585
|
+
active-tab-id=${this._skillBrowseSource}
|
|
6586
|
+
@tab-change=${this._handleSkillBrowseTabChange}
|
|
6587
|
+
>
|
|
6588
|
+
<kr-tab id="org" label="Your Org">
|
|
6589
|
+
${this._renderSkillGrid()}
|
|
6590
|
+
</kr-tab>
|
|
6591
|
+
<kr-tab id="kodaris" label="Kodaris">
|
|
6592
|
+
${this._renderSkillGrid()}
|
|
6593
|
+
</kr-tab>
|
|
6594
|
+
</kr-tab-group>
|
|
6595
|
+
</div>
|
|
6596
|
+
</kr-dialog>
|
|
6597
|
+
`;
|
|
6598
|
+
}
|
|
6599
|
+
/** The card grid for the browse dialog's active tab. */
|
|
6600
|
+
_renderSkillGrid() {
|
|
6601
|
+
const skills = this._browseSkills();
|
|
6602
|
+
if (!skills.length) {
|
|
6603
|
+
return b `<div class="skill-browse__empty">No matching skills</div>`;
|
|
6604
|
+
}
|
|
6605
|
+
return b `
|
|
6606
|
+
<div class="skill-browse__grid">
|
|
6607
|
+
${skills.map((skill) => b `
|
|
6608
|
+
<button
|
|
6609
|
+
class="skill-card"
|
|
6610
|
+
@click=${() => this._handleSkillSelect(skill)}
|
|
6611
|
+
>
|
|
6612
|
+
<span class="skill-card__name">${skill.label}</span>
|
|
6613
|
+
${skill.description ? b `
|
|
6614
|
+
<span class="skill-card__desc">${skill.description}</span>
|
|
6615
|
+
` : A}
|
|
6616
|
+
</button>
|
|
6617
|
+
`)}
|
|
6618
|
+
</div>
|
|
6619
|
+
`;
|
|
6620
|
+
}
|
|
6621
|
+
/**
|
|
6622
|
+
* Render a user message, highlighting a leading `/skill-name` token when it
|
|
6623
|
+
* matches a known skill (like the way Claude highlights slash commands).
|
|
6624
|
+
*/
|
|
6625
|
+
_renderUserContent(content) {
|
|
6626
|
+
const match = content.match(/^\/(\S+)(\s[\s\S]*)?$/);
|
|
6627
|
+
if (match && this.skills.some((skill) => skill.name === match[1])) {
|
|
6628
|
+
return b `<span class="message-skill">/${match[1]}</span>${match[2] || ''}`;
|
|
6629
|
+
}
|
|
6630
|
+
return content;
|
|
6631
|
+
}
|
|
6302
6632
|
render() {
|
|
6303
6633
|
return b `
|
|
6304
|
-
${this.hideToggle ? A : b `
|
|
6634
|
+
${(this.hideToggle || this.variant === 'inline') ? A : b `
|
|
6305
6635
|
<button
|
|
6306
6636
|
class=${e({
|
|
6307
6637
|
'toggle': true,
|
|
@@ -6352,53 +6682,52 @@
|
|
|
6352
6682
|
<span>Drop images to attach</span>
|
|
6353
6683
|
</div>
|
|
6354
6684
|
` : 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
|
-
|
|
6685
|
+
${this.variant === 'inline' ? A : b `
|
|
6686
|
+
<div
|
|
6687
|
+
class="resize resize--n"
|
|
6688
|
+
data-dir="n"
|
|
6689
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6690
|
+
></div>
|
|
6691
|
+
<div
|
|
6692
|
+
class="resize resize--s"
|
|
6693
|
+
data-dir="s"
|
|
6694
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6695
|
+
></div>
|
|
6696
|
+
<div
|
|
6697
|
+
class="resize resize--w"
|
|
6698
|
+
data-dir="w"
|
|
6699
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6700
|
+
></div>
|
|
6701
|
+
<div
|
|
6702
|
+
class="resize resize--e"
|
|
6703
|
+
data-dir="e"
|
|
6704
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6705
|
+
></div>
|
|
6706
|
+
<div
|
|
6707
|
+
class="resize resize--nw"
|
|
6708
|
+
data-dir="nw"
|
|
6709
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6710
|
+
></div>
|
|
6711
|
+
<div
|
|
6712
|
+
class="resize resize--ne"
|
|
6713
|
+
data-dir="ne"
|
|
6714
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6715
|
+
></div>
|
|
6716
|
+
<div
|
|
6717
|
+
class="resize resize--sw"
|
|
6718
|
+
data-dir="sw"
|
|
6719
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6720
|
+
></div>
|
|
6721
|
+
<div
|
|
6722
|
+
class="resize resize--se"
|
|
6723
|
+
data-dir="se"
|
|
6724
|
+
@mousedown=${this._handleResizeMouseDown}
|
|
6725
|
+
></div>
|
|
6726
|
+
`}
|
|
6395
6727
|
<div class="header" @mousedown=${this._handleHeaderMouseDown}>
|
|
6396
6728
|
<div class="header-left">
|
|
6397
6729
|
<div class="header-info">
|
|
6398
|
-
<span class="header-title">${this.
|
|
6399
|
-
${this.subtitle ? b `
|
|
6400
|
-
<span class="header-subtitle">${this.subtitle}</span>
|
|
6401
|
-
` : A}
|
|
6730
|
+
<span class="header-title">${this.label}</span>
|
|
6402
6731
|
</div>
|
|
6403
6732
|
</div>
|
|
6404
6733
|
<div class="header-actions">
|
|
@@ -6424,77 +6753,124 @@
|
|
|
6424
6753
|
</svg>
|
|
6425
6754
|
</button>
|
|
6426
6755
|
` : 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"
|
|
6756
|
+
${this.variant === 'inline' ? A : b `
|
|
6757
|
+
<button
|
|
6758
|
+
class="header-action"
|
|
6759
|
+
@click=${this._handleToggle}
|
|
6760
|
+
title="Close"
|
|
6439
6761
|
>
|
|
6440
|
-
<
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6762
|
+
<svg
|
|
6763
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
6764
|
+
fill="none"
|
|
6765
|
+
viewBox="0 0 24 24"
|
|
6766
|
+
stroke-width="2"
|
|
6767
|
+
stroke="currentColor"
|
|
6768
|
+
class="header-action-icon"
|
|
6769
|
+
>
|
|
6770
|
+
<path
|
|
6771
|
+
stroke-linecap="round"
|
|
6772
|
+
stroke-linejoin="round"
|
|
6773
|
+
d="M6 18 18 6M6 6l12 12"
|
|
6774
|
+
/>
|
|
6775
|
+
</svg>
|
|
6776
|
+
</button>
|
|
6777
|
+
`}
|
|
6447
6778
|
</div>
|
|
6448
6779
|
</div>
|
|
6449
6780
|
|
|
6450
6781
|
<div class="messages" @scroll=${this._handleMessagesScroll}>
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
<
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6782
|
+
<div class="messages-inner">
|
|
6783
|
+
${this.messages.length === 0 ? b `
|
|
6784
|
+
<div class="empty">
|
|
6785
|
+
<span class="empty-text">What can I help you with?</span>
|
|
6786
|
+
</div>
|
|
6787
|
+
` : A}
|
|
6788
|
+
${this.messages.map((msg, index) => b `
|
|
6789
|
+
<div class=${e({
|
|
6458
6790
|
'message': true,
|
|
6459
|
-
'message--user': msg.
|
|
6460
|
-
'message--assistant': msg.
|
|
6791
|
+
'message--user': msg.type === 'user',
|
|
6792
|
+
'message--assistant': msg.type === 'assistant',
|
|
6461
6793
|
})}>
|
|
6462
|
-
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6794
|
+
${msg.reasoning ? b `
|
|
6795
|
+
<details class="reasoning">
|
|
6796
|
+
<summary>Thinking</summary>
|
|
6797
|
+
<div class="reasoning-content">${msg.reasoning}</div>
|
|
6798
|
+
</details>
|
|
6799
|
+
` : A}
|
|
6800
|
+
${msg.internalFiles && msg.internalFiles.length ? b `
|
|
6801
|
+
<div class="attachments">
|
|
6802
|
+
${msg.internalFiles.map((img) => b `
|
|
6803
|
+
<button
|
|
6804
|
+
class="attachment"
|
|
6805
|
+
type="button"
|
|
6806
|
+
title=${img.niceName || 'View image'}
|
|
6807
|
+
@click=${() => this._openImage(img)}
|
|
6808
|
+
>
|
|
6809
|
+
<img
|
|
6810
|
+
src="/api/system/integration/aws/bedrock/conversationImage/${img.internalFileID}/view"
|
|
6811
|
+
alt=${img.niceName || ''}
|
|
6812
|
+
/>
|
|
6813
|
+
</button>
|
|
6814
|
+
`)}
|
|
6815
|
+
</div>
|
|
6816
|
+
` : A}
|
|
6817
|
+
${msg.content ? b `
|
|
6818
|
+
<div class="message-content">
|
|
6819
|
+
${msg.type === 'user'
|
|
6820
|
+
? this._renderUserContent(msg.content)
|
|
6486
6821
|
: o(marked.parse(msg.content, { breaks: true }))}
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6822
|
+
</div>
|
|
6823
|
+
` : A}
|
|
6824
|
+
${msg.type === 'assistant' && this._isStreaming && msg === this.messages[this.messages.length - 1] ? b `
|
|
6825
|
+
<div class="typing">
|
|
6826
|
+
<span></span>
|
|
6827
|
+
<span></span>
|
|
6828
|
+
<span></span>
|
|
6829
|
+
</div>
|
|
6830
|
+
` : A}
|
|
6831
|
+
${msg.content ? b `
|
|
6832
|
+
<button
|
|
6833
|
+
class="message-copy"
|
|
6834
|
+
title="Copy"
|
|
6835
|
+
@click=${() => this._handleCopyMessage(msg.content, index)}
|
|
6836
|
+
>
|
|
6837
|
+
${this._copiedIndex === index ? b `
|
|
6838
|
+
<svg
|
|
6839
|
+
viewBox="0 0 24 24"
|
|
6840
|
+
fill="none"
|
|
6841
|
+
stroke="currentColor"
|
|
6842
|
+
stroke-width="1.5"
|
|
6843
|
+
stroke-linecap="round"
|
|
6844
|
+
stroke-linejoin="round"
|
|
6845
|
+
>
|
|
6846
|
+
<path d="M20 6 9 17l-5-5" />
|
|
6847
|
+
</svg>
|
|
6848
|
+
Copied
|
|
6849
|
+
` : b `
|
|
6850
|
+
<svg
|
|
6851
|
+
viewBox="0 0 24 24"
|
|
6852
|
+
fill="none"
|
|
6853
|
+
stroke="currentColor"
|
|
6854
|
+
stroke-width="1.5"
|
|
6855
|
+
stroke-linecap="round"
|
|
6856
|
+
stroke-linejoin="round"
|
|
6857
|
+
>
|
|
6858
|
+
<rect
|
|
6859
|
+
x="9"
|
|
6860
|
+
y="9"
|
|
6861
|
+
width="13"
|
|
6862
|
+
height="13"
|
|
6863
|
+
rx="2"
|
|
6864
|
+
/>
|
|
6865
|
+
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
|
|
6866
|
+
</svg>
|
|
6867
|
+
Copy
|
|
6868
|
+
`}
|
|
6869
|
+
</button>
|
|
6870
|
+
` : A}
|
|
6871
|
+
</div>
|
|
6872
|
+
`)}
|
|
6873
|
+
</div>
|
|
6498
6874
|
</div>
|
|
6499
6875
|
|
|
6500
6876
|
${this._error ? b `
|
|
@@ -6520,9 +6896,9 @@
|
|
|
6520
6896
|
` : A}
|
|
6521
6897
|
|
|
6522
6898
|
<div class="footer">
|
|
6523
|
-
${this.
|
|
6899
|
+
${this._pendingInternalFiles.length ? b `
|
|
6524
6900
|
<div class="composer-attachments">
|
|
6525
|
-
${c(this.
|
|
6901
|
+
${c(this._pendingInternalFiles, (p) => p.localId, (p) => b `
|
|
6526
6902
|
<div class="chip">
|
|
6527
6903
|
<img src=${p.previewUrl} alt=${p.name} />
|
|
6528
6904
|
<button
|
|
@@ -6556,11 +6932,11 @@
|
|
|
6556
6932
|
hidden
|
|
6557
6933
|
@change=${this._handleFileInputChange}
|
|
6558
6934
|
/>
|
|
6935
|
+
${this._skillMenuOpened ? this._renderSkillMenu() : A}
|
|
6559
6936
|
<div class="input-wrapper">
|
|
6560
6937
|
<button
|
|
6561
6938
|
class="input-plus"
|
|
6562
|
-
|
|
6563
|
-
@click=${this._openFilePicker}
|
|
6939
|
+
@click=${this._handlePlusClick}
|
|
6564
6940
|
>+</button>
|
|
6565
6941
|
<textarea
|
|
6566
6942
|
class="input"
|
|
@@ -6617,6 +6993,7 @@
|
|
|
6617
6993
|
`}
|
|
6618
6994
|
</div>
|
|
6619
6995
|
</div>
|
|
6996
|
+
${this._skillBrowseOpened ? this._renderSkillBrowse() : A}
|
|
6620
6997
|
</div>
|
|
6621
6998
|
`;
|
|
6622
6999
|
}
|
|
@@ -6711,6 +7088,28 @@
|
|
|
6711
7088
|
display: flex;
|
|
6712
7089
|
}
|
|
6713
7090
|
|
|
7091
|
+
/* Inline mode: fill the parent container instead of floating bottom-right. */
|
|
7092
|
+
:host([variant='inline']) {
|
|
7093
|
+
position: static;
|
|
7094
|
+
bottom: auto;
|
|
7095
|
+
right: auto;
|
|
7096
|
+
z-index: auto;
|
|
7097
|
+
height: 100%;
|
|
7098
|
+
}
|
|
7099
|
+
|
|
7100
|
+
:host([variant='inline']) .panel {
|
|
7101
|
+
position: relative;
|
|
7102
|
+
bottom: auto;
|
|
7103
|
+
right: auto;
|
|
7104
|
+
width: 100%;
|
|
7105
|
+
height: 100%;
|
|
7106
|
+
max-height: none;
|
|
7107
|
+
border-radius: 0;
|
|
7108
|
+
box-shadow: none;
|
|
7109
|
+
border: none;
|
|
7110
|
+
animation: none;
|
|
7111
|
+
}
|
|
7112
|
+
|
|
6714
7113
|
@keyframes chatbot-panel-in {
|
|
6715
7114
|
from {
|
|
6716
7115
|
opacity: 0;
|
|
@@ -6741,7 +7140,7 @@
|
|
|
6741
7140
|
gap: 10px;
|
|
6742
7141
|
}
|
|
6743
7142
|
|
|
6744
|
-
.header-info {
|
|
7143
|
+
.header-info {
|
|
6745
7144
|
display: flex;
|
|
6746
7145
|
flex-direction: column;
|
|
6747
7146
|
}
|
|
@@ -6751,22 +7150,6 @@
|
|
|
6751
7150
|
font-weight: 600;
|
|
6752
7151
|
}
|
|
6753
7152
|
|
|
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
7153
|
.header-actions {
|
|
6771
7154
|
display: flex;
|
|
6772
7155
|
align-items: center;
|
|
@@ -6798,17 +7181,29 @@
|
|
|
6798
7181
|
}
|
|
6799
7182
|
|
|
6800
7183
|
/* Messages */
|
|
7184
|
+
/* Full-width scroll container — keeps the scrollbar at the panel edge. */
|
|
6801
7185
|
.messages {
|
|
6802
7186
|
flex: 1;
|
|
6803
7187
|
overflow-y: auto;
|
|
6804
|
-
padding: 32px;
|
|
6805
7188
|
display: flex;
|
|
6806
7189
|
flex-direction: column;
|
|
6807
|
-
gap: 24px;
|
|
6808
7190
|
scroll-behavior: smooth;
|
|
6809
7191
|
background: white;
|
|
6810
7192
|
}
|
|
6811
7193
|
|
|
7194
|
+
/* Centered, width-capped column that actually holds the messages. */
|
|
7195
|
+
.messages-inner {
|
|
7196
|
+
flex: 1;
|
|
7197
|
+
display: flex;
|
|
7198
|
+
flex-direction: column;
|
|
7199
|
+
gap: 24px;
|
|
7200
|
+
padding: 32px;
|
|
7201
|
+
width: 100%;
|
|
7202
|
+
max-width: 768px;
|
|
7203
|
+
margin-left: auto;
|
|
7204
|
+
margin-right: auto;
|
|
7205
|
+
}
|
|
7206
|
+
|
|
6812
7207
|
.messages::-webkit-scrollbar {
|
|
6813
7208
|
width: 4px;
|
|
6814
7209
|
}
|
|
@@ -6832,12 +7227,13 @@
|
|
|
6832
7227
|
gap: 8px;
|
|
6833
7228
|
}
|
|
6834
7229
|
|
|
6835
|
-
.empty-text {
|
|
7230
|
+
.empty-text {
|
|
6836
7231
|
font-size: 14px;
|
|
6837
7232
|
color: rgb(0 0 0 / 80%);
|
|
6838
7233
|
}
|
|
6839
7234
|
|
|
6840
7235
|
.message {
|
|
7236
|
+
position: relative;
|
|
6841
7237
|
display: flex;
|
|
6842
7238
|
flex-direction: column;
|
|
6843
7239
|
max-width: 100%;
|
|
@@ -6882,6 +7278,58 @@
|
|
|
6882
7278
|
font-size: 14px;
|
|
6883
7279
|
}
|
|
6884
7280
|
|
|
7281
|
+
/* Highlighted leading /skill token in a sent user message. Monospace + a
|
|
7282
|
+
stronger color makes it read as a distinct command without a pill. */
|
|
7283
|
+
.message-skill {
|
|
7284
|
+
font-family: 'SF Mono', SFMono-Regular, ui-monospace, Menlo, Consolas, monospace;
|
|
7285
|
+
font-weight: 600;
|
|
7286
|
+
color: #b45309;
|
|
7287
|
+
}
|
|
7288
|
+
|
|
7289
|
+
/* Per-message copy button. Kept in flow with a fixed height that is always
|
|
7290
|
+
reserved (via a negative bottom margin that cancels it) so message spacing
|
|
7291
|
+
is identical whether or not it's shown; only its opacity toggles on hover. */
|
|
7292
|
+
.message-copy {
|
|
7293
|
+
align-self: flex-start;
|
|
7294
|
+
margin-top: 4px;
|
|
7295
|
+
margin-bottom: -27px;
|
|
7296
|
+
display: inline-flex;
|
|
7297
|
+
align-items: center;
|
|
7298
|
+
gap: 4px;
|
|
7299
|
+
height: 23px;
|
|
7300
|
+
padding: 4px 8px;
|
|
7301
|
+
background: none;
|
|
7302
|
+
border: none;
|
|
7303
|
+
border-radius: 6px;
|
|
7304
|
+
font: inherit;
|
|
7305
|
+
font-size: 12px;
|
|
7306
|
+
color: #64668b;
|
|
7307
|
+
cursor: pointer;
|
|
7308
|
+
opacity: 0;
|
|
7309
|
+
pointer-events: none;
|
|
7310
|
+
transition: opacity 0.15s, background-color 0.15s, color 0.15s;
|
|
7311
|
+
}
|
|
7312
|
+
|
|
7313
|
+
.message--user .message-copy {
|
|
7314
|
+
align-self: flex-end;
|
|
7315
|
+
}
|
|
7316
|
+
|
|
7317
|
+
.message:hover .message-copy,
|
|
7318
|
+
.message-copy:focus-visible {
|
|
7319
|
+
opacity: 1;
|
|
7320
|
+
pointer-events: auto;
|
|
7321
|
+
}
|
|
7322
|
+
|
|
7323
|
+
.message-copy:hover {
|
|
7324
|
+
background: rgba(0, 0, 0, 0.06);
|
|
7325
|
+
color: #1a1a2e;
|
|
7326
|
+
}
|
|
7327
|
+
|
|
7328
|
+
.message-copy svg {
|
|
7329
|
+
width: 14px;
|
|
7330
|
+
height: 14px;
|
|
7331
|
+
}
|
|
7332
|
+
|
|
6885
7333
|
.message--assistant .message-content {
|
|
6886
7334
|
background: transparent;
|
|
6887
7335
|
color: #000000;
|
|
@@ -6944,7 +7392,7 @@
|
|
|
6944
7392
|
word-wrap: break-word;
|
|
6945
7393
|
}
|
|
6946
7394
|
|
|
6947
|
-
.typing {
|
|
7395
|
+
.typing {
|
|
6948
7396
|
display: flex;
|
|
6949
7397
|
gap: 4px;
|
|
6950
7398
|
padding: 4px 0;
|
|
@@ -7012,6 +7460,15 @@
|
|
|
7012
7460
|
padding: 16px 16px 16px;
|
|
7013
7461
|
flex-shrink: 0;
|
|
7014
7462
|
background: white;
|
|
7463
|
+
width: 100%;
|
|
7464
|
+
max-width: 768px;
|
|
7465
|
+
margin-left: auto;
|
|
7466
|
+
margin-right: auto;
|
|
7467
|
+
}
|
|
7468
|
+
|
|
7469
|
+
/* Inline mode: keep the composer clear of the bottom edge. */
|
|
7470
|
+
:host([variant='inline']) .footer {
|
|
7471
|
+
padding-bottom: 40px;
|
|
7015
7472
|
}
|
|
7016
7473
|
|
|
7017
7474
|
.input-wrapper {
|
|
@@ -7030,6 +7487,15 @@
|
|
|
7030
7487
|
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.04);
|
|
7031
7488
|
}
|
|
7032
7489
|
|
|
7490
|
+
/* Inline mode: keep the border and add a soft floating shadow (ChatGPT/Gemini style). */
|
|
7491
|
+
:host([variant='inline']) .input-wrapper {
|
|
7492
|
+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06), 0 8px 24px rgba(0, 0, 0, 0.1);
|
|
7493
|
+
}
|
|
7494
|
+
|
|
7495
|
+
:host([variant='inline']) .input-wrapper:focus-within {
|
|
7496
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08), 0 12px 32px rgba(0, 0, 0, 0.14);
|
|
7497
|
+
}
|
|
7498
|
+
|
|
7033
7499
|
.input-plus {
|
|
7034
7500
|
width: 34px;
|
|
7035
7501
|
height: 34px;
|
|
@@ -7137,6 +7603,12 @@
|
|
|
7137
7603
|
cursor: grabbing;
|
|
7138
7604
|
}
|
|
7139
7605
|
|
|
7606
|
+
/* Inline mode isn't draggable — don't show the grab/hand cursor. */
|
|
7607
|
+
:host([variant='inline']) .header,
|
|
7608
|
+
:host([variant='inline']) .header:active {
|
|
7609
|
+
cursor: default;
|
|
7610
|
+
}
|
|
7611
|
+
|
|
7140
7612
|
/* Drag / Resize states */
|
|
7141
7613
|
.panel--dragging,
|
|
7142
7614
|
.panel--resizing {
|
|
@@ -7193,6 +7665,176 @@
|
|
|
7193
7665
|
display: block;
|
|
7194
7666
|
}
|
|
7195
7667
|
|
|
7668
|
+
/* Skill menu (opened by typing '/'). Fixed + JS-positioned above the
|
|
7669
|
+
composer, following the krubble select-field dropdown pattern. */
|
|
7670
|
+
.skill-menu {
|
|
7671
|
+
position: fixed;
|
|
7672
|
+
z-index: 10000;
|
|
7673
|
+
background: white;
|
|
7674
|
+
border: 1px solid #9ba7b6;
|
|
7675
|
+
border-radius: 8px;
|
|
7676
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
7677
|
+
overflow: hidden;
|
|
7678
|
+
display: flex;
|
|
7679
|
+
flex-direction: column;
|
|
7680
|
+
/* max-height is set dynamically to the space above the composer. */
|
|
7681
|
+
}
|
|
7682
|
+
|
|
7683
|
+
/* Floating mode is a compact card — use a lighter shadow and softer border. */
|
|
7684
|
+
:host(:not([variant='inline'])) .skill-menu {
|
|
7685
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
7686
|
+
border-color: #b0b0b0;
|
|
7687
|
+
}
|
|
7688
|
+
|
|
7689
|
+
.skill-menu__list {
|
|
7690
|
+
list-style: none;
|
|
7691
|
+
margin: 0;
|
|
7692
|
+
padding: 8px 0;
|
|
7693
|
+
overflow-y: auto;
|
|
7694
|
+
}
|
|
7695
|
+
|
|
7696
|
+
.skill-menu__item {
|
|
7697
|
+
display: flex;
|
|
7698
|
+
flex-direction: column;
|
|
7699
|
+
gap: 2px;
|
|
7700
|
+
width: 100%;
|
|
7701
|
+
padding: 8px 16px;
|
|
7702
|
+
background: none;
|
|
7703
|
+
border: none;
|
|
7704
|
+
text-align: left;
|
|
7705
|
+
cursor: pointer;
|
|
7706
|
+
font: inherit;
|
|
7707
|
+
color: #000000;
|
|
7708
|
+
}
|
|
7709
|
+
|
|
7710
|
+
|
|
7711
|
+
/* Floating mode is a compact card — tighten name/description spacing. */
|
|
7712
|
+
:host(:not([variant='inline'])) .skill-menu__item {
|
|
7713
|
+
gap: 1px;
|
|
7714
|
+
}
|
|
7715
|
+
|
|
7716
|
+
.skill-menu__name {
|
|
7717
|
+
font-weight: 500;
|
|
7718
|
+
}
|
|
7719
|
+
|
|
7720
|
+
/* Floating mode is a compact card — shrink the skill name a touch. */
|
|
7721
|
+
:host(:not([variant='inline'])) .skill-menu__name {
|
|
7722
|
+
font-size: 13px;
|
|
7723
|
+
}
|
|
7724
|
+
|
|
7725
|
+
.skill-menu__desc {
|
|
7726
|
+
font-size: 12px;
|
|
7727
|
+
color: #000000;
|
|
7728
|
+
overflow: hidden;
|
|
7729
|
+
text-overflow: ellipsis;
|
|
7730
|
+
white-space: nowrap;
|
|
7731
|
+
}
|
|
7732
|
+
|
|
7733
|
+
.skill-menu__empty {
|
|
7734
|
+
padding: 16px;
|
|
7735
|
+
text-align: center;
|
|
7736
|
+
color: #000000;
|
|
7737
|
+
}
|
|
7738
|
+
|
|
7739
|
+
.skill-menu__actions {
|
|
7740
|
+
display: flex;
|
|
7741
|
+
flex-direction: column;
|
|
7742
|
+
padding: 8px 0;
|
|
7743
|
+
border-bottom: 1px solid #eee;
|
|
7744
|
+
flex-shrink: 0;
|
|
7745
|
+
}
|
|
7746
|
+
|
|
7747
|
+
.skill-menu__action {
|
|
7748
|
+
width: 100%;
|
|
7749
|
+
padding: 6px 16px;
|
|
7750
|
+
background: transparent;
|
|
7751
|
+
border: none;
|
|
7752
|
+
text-align: left;
|
|
7753
|
+
cursor: pointer;
|
|
7754
|
+
font: inherit;
|
|
7755
|
+
font-size: 13px;
|
|
7756
|
+
color: var(--kr-chatbot-primary);
|
|
7757
|
+
font-weight: 500;
|
|
7758
|
+
}
|
|
7759
|
+
|
|
7760
|
+
/* Highlight (keyboard) and hover (mouse) are independent — either shades the
|
|
7761
|
+
row. Declared after the base rules so it wins the cascade for both the
|
|
7762
|
+
action buttons and the skill items. */
|
|
7763
|
+
.skill-menu__action.skill-menu__item--highlighted,
|
|
7764
|
+
.skill-menu__item.skill-menu__item--highlighted,
|
|
7765
|
+
.skill-menu__action:hover,
|
|
7766
|
+
.skill-menu__item:hover {
|
|
7767
|
+
background: #f3f4f6;
|
|
7768
|
+
}
|
|
7769
|
+
|
|
7770
|
+
/* Browse-all dialog body. Owns the height so the dialog is the same size on
|
|
7771
|
+
every tab; the search is fixed and the card grid flexes/scrolls to fill. */
|
|
7772
|
+
.skill-browse {
|
|
7773
|
+
display: flex;
|
|
7774
|
+
flex-direction: column;
|
|
7775
|
+
height: 70vh;
|
|
7776
|
+
}
|
|
7777
|
+
|
|
7778
|
+
.skill-browse kr-text-field {
|
|
7779
|
+
display: block;
|
|
7780
|
+
margin: 20px 20px 16px;
|
|
7781
|
+
flex-shrink: 0;
|
|
7782
|
+
}
|
|
7783
|
+
|
|
7784
|
+
.skill-browse kr-tab-group {
|
|
7785
|
+
flex: 1;
|
|
7786
|
+
min-height: 0;
|
|
7787
|
+
}
|
|
7788
|
+
|
|
7789
|
+
/* The grid is the scroller and spans the full width, so its scrollbar sits
|
|
7790
|
+
flush against the dialog edge; padding-right insets the cards from it. */
|
|
7791
|
+
.skill-browse__grid {
|
|
7792
|
+
height: 100%;
|
|
7793
|
+
overflow-y: auto;
|
|
7794
|
+
display: grid;
|
|
7795
|
+
grid-template-columns: repeat(3, 1fr);
|
|
7796
|
+
grid-auto-rows: min-content;
|
|
7797
|
+
align-content: start;
|
|
7798
|
+
gap: 12px;
|
|
7799
|
+
padding: 16px 20px 20px;
|
|
7800
|
+
}
|
|
7801
|
+
|
|
7802
|
+
.skill-card {
|
|
7803
|
+
display: flex;
|
|
7804
|
+
flex-direction: column;
|
|
7805
|
+
gap: 6px;
|
|
7806
|
+
padding: 14px;
|
|
7807
|
+
background: white;
|
|
7808
|
+
border: 1px solid #e5e7eb;
|
|
7809
|
+
border-radius: 10px;
|
|
7810
|
+
text-align: left;
|
|
7811
|
+
cursor: pointer;
|
|
7812
|
+
font: inherit;
|
|
7813
|
+
color: #000000;
|
|
7814
|
+
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
|
7815
|
+
}
|
|
7816
|
+
|
|
7817
|
+
.skill-card:hover {
|
|
7818
|
+
border-color: var(--kr-chatbot-primary);
|
|
7819
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
7820
|
+
}
|
|
7821
|
+
|
|
7822
|
+
.skill-card__name {
|
|
7823
|
+
font-weight: 600;
|
|
7824
|
+
}
|
|
7825
|
+
|
|
7826
|
+
.skill-card__desc {
|
|
7827
|
+
font-size: 12px;
|
|
7828
|
+
color: #000000;
|
|
7829
|
+
}
|
|
7830
|
+
|
|
7831
|
+
.skill-browse__empty {
|
|
7832
|
+
height: 100%;
|
|
7833
|
+
padding: 32px;
|
|
7834
|
+
text-align: center;
|
|
7835
|
+
color: #000000;
|
|
7836
|
+
}
|
|
7837
|
+
|
|
7196
7838
|
/* Composer attachment chips (pre-send) */
|
|
7197
7839
|
.composer-attachments {
|
|
7198
7840
|
display: flex;
|
|
@@ -7288,13 +7930,13 @@
|
|
|
7288
7930
|
], exports.Chatbot.prototype, "messages", void 0);
|
|
7289
7931
|
__decorate([
|
|
7290
7932
|
n({ type: String })
|
|
7291
|
-
], exports.Chatbot.prototype, "
|
|
7292
|
-
__decorate([
|
|
7293
|
-
n({ type: String })
|
|
7294
|
-
], exports.Chatbot.prototype, "subtitle", void 0);
|
|
7933
|
+
], exports.Chatbot.prototype, "label", void 0);
|
|
7295
7934
|
__decorate([
|
|
7296
7935
|
n({ type: String })
|
|
7297
7936
|
], exports.Chatbot.prototype, "placeholder", void 0);
|
|
7937
|
+
__decorate([
|
|
7938
|
+
n({ attribute: false })
|
|
7939
|
+
], exports.Chatbot.prototype, "skills", void 0);
|
|
7298
7940
|
__decorate([
|
|
7299
7941
|
n({
|
|
7300
7942
|
type: Boolean,
|
|
@@ -7308,24 +7950,48 @@
|
|
|
7308
7950
|
reflect: true
|
|
7309
7951
|
})
|
|
7310
7952
|
], exports.Chatbot.prototype, "hideToggle", void 0);
|
|
7953
|
+
__decorate([
|
|
7954
|
+
n({
|
|
7955
|
+
type: String,
|
|
7956
|
+
reflect: true
|
|
7957
|
+
})
|
|
7958
|
+
], exports.Chatbot.prototype, "variant", void 0);
|
|
7311
7959
|
__decorate([
|
|
7312
7960
|
r()
|
|
7313
7961
|
], exports.Chatbot.prototype, "_inputValue", void 0);
|
|
7314
7962
|
__decorate([
|
|
7315
7963
|
r()
|
|
7316
7964
|
], exports.Chatbot.prototype, "_isStreaming", void 0);
|
|
7317
|
-
__decorate([
|
|
7318
|
-
r()
|
|
7319
|
-
], exports.Chatbot.prototype, "_statusText", void 0);
|
|
7320
7965
|
__decorate([
|
|
7321
7966
|
r()
|
|
7322
7967
|
], exports.Chatbot.prototype, "_error", void 0);
|
|
7323
7968
|
__decorate([
|
|
7324
7969
|
r()
|
|
7325
|
-
], exports.Chatbot.prototype, "
|
|
7970
|
+
], exports.Chatbot.prototype, "_pendingInternalFiles", void 0);
|
|
7326
7971
|
__decorate([
|
|
7327
7972
|
r()
|
|
7328
7973
|
], exports.Chatbot.prototype, "_isDraggingFile", void 0);
|
|
7974
|
+
__decorate([
|
|
7975
|
+
r()
|
|
7976
|
+
], exports.Chatbot.prototype, "_skillMenuOpened", void 0);
|
|
7977
|
+
__decorate([
|
|
7978
|
+
r()
|
|
7979
|
+
], exports.Chatbot.prototype, "_skillQuery", void 0);
|
|
7980
|
+
__decorate([
|
|
7981
|
+
r()
|
|
7982
|
+
], exports.Chatbot.prototype, "_skillHighlighted", void 0);
|
|
7983
|
+
__decorate([
|
|
7984
|
+
r()
|
|
7985
|
+
], exports.Chatbot.prototype, "_copiedIndex", void 0);
|
|
7986
|
+
__decorate([
|
|
7987
|
+
r()
|
|
7988
|
+
], exports.Chatbot.prototype, "_skillBrowseOpened", void 0);
|
|
7989
|
+
__decorate([
|
|
7990
|
+
r()
|
|
7991
|
+
], exports.Chatbot.prototype, "_skillBrowseSource", void 0);
|
|
7992
|
+
__decorate([
|
|
7993
|
+
r()
|
|
7994
|
+
], exports.Chatbot.prototype, "_skillBrowseQuery", void 0);
|
|
7329
7995
|
__decorate([
|
|
7330
7996
|
e$3('.panel')
|
|
7331
7997
|
], exports.Chatbot.prototype, "_panelEl", void 0);
|
|
@@ -7338,6 +8004,12 @@
|
|
|
7338
8004
|
__decorate([
|
|
7339
8005
|
e$3('.file-input')
|
|
7340
8006
|
], exports.Chatbot.prototype, "_fileInputEl", void 0);
|
|
8007
|
+
__decorate([
|
|
8008
|
+
e$3('.input-wrapper')
|
|
8009
|
+
], exports.Chatbot.prototype, "_inputWrapperEl", void 0);
|
|
8010
|
+
__decorate([
|
|
8011
|
+
e$3('.skill-menu')
|
|
8012
|
+
], exports.Chatbot.prototype, "_skillMenuEl", void 0);
|
|
7341
8013
|
exports.Chatbot = __decorate([
|
|
7342
8014
|
t$2('kr-chatbot')
|
|
7343
8015
|
], exports.Chatbot);
|