@kodaris/krubble-app-components 1.0.73 → 1.0.75
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 +41 -23
- package/dist/chatbot.d.ts.map +1 -1
- package/dist/chatbot.js +102 -57
- package/dist/chatbot.js.map +1 -1
- package/dist/krubble-app.bundled.js +102 -57
- package/dist/krubble-app.bundled.js.map +1 -1
- package/dist/krubble-app.bundled.min.js +23 -23
- package/dist/krubble-app.bundled.min.js.map +1 -1
- package/dist/krubble-app.umd.js +102 -57
- package/dist/krubble-app.umd.js.map +1 -1
- package/dist/krubble-app.umd.min.js +19 -19
- package/dist/krubble-app.umd.min.js.map +1 -1
- package/package.json +1 -1
package/dist/krubble-app.umd.js
CHANGED
|
@@ -5609,6 +5609,11 @@
|
|
|
5609
5609
|
this._dragDepth = 0;
|
|
5610
5610
|
/** Monotonic id source for pending attachments. */
|
|
5611
5611
|
this._pendingSeq = 0;
|
|
5612
|
+
/**
|
|
5613
|
+
* Request-id guard for skill searches — bumped on each search so out-of-order
|
|
5614
|
+
* responses are dropped (mirrors the kr-combo-box `_requestId` pattern).
|
|
5615
|
+
*/
|
|
5616
|
+
this._skillRequestId = 0;
|
|
5612
5617
|
// --- @property (public API) ---
|
|
5613
5618
|
/**
|
|
5614
5619
|
* Callback function for sending messages. Receives the user's message and
|
|
@@ -5647,12 +5652,6 @@
|
|
|
5647
5652
|
* Input placeholder text.
|
|
5648
5653
|
*/
|
|
5649
5654
|
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 = [];
|
|
5656
5655
|
/**
|
|
5657
5656
|
* Whether the chat panel is open. Only relevant in floating mode.
|
|
5658
5657
|
*/
|
|
@@ -5684,17 +5683,25 @@
|
|
|
5684
5683
|
this._isDraggingFile = false;
|
|
5685
5684
|
/** Whether the `/` skill menu is open above the composer. */
|
|
5686
5685
|
this._skillMenuOpened = false;
|
|
5687
|
-
/** Current `/` query (text after the slash),
|
|
5686
|
+
/** Current `/` query (text after the slash), sent to `_searchSkills`. */
|
|
5688
5687
|
this._skillQuery = '';
|
|
5688
|
+
/**
|
|
5689
|
+
* Latest skill search results. Shared by the `/` menu and the browse dialog —
|
|
5690
|
+
* they're mutually exclusive (opening browse closes the menu), so one buffer.
|
|
5691
|
+
*/
|
|
5692
|
+
this._skillResults = [];
|
|
5689
5693
|
/** Highlighted item in the skill menu for keyboard navigation (-1 = none). */
|
|
5690
5694
|
this._skillHighlighted = 0;
|
|
5691
5695
|
/** Index of the message whose copy button just flashed "Copied" (-1 = none). */
|
|
5692
5696
|
this._copiedIndex = -1;
|
|
5693
5697
|
/** Whether the "Browse all skills" dialog is open. */
|
|
5694
5698
|
this._skillBrowseOpened = false;
|
|
5695
|
-
/**
|
|
5699
|
+
/**
|
|
5700
|
+
* Active tab in the browse dialog. `org` lists this org's skills (searched via
|
|
5701
|
+
* `_searchSkills`); `kodaris` is the shared global catalog, added later.
|
|
5702
|
+
*/
|
|
5696
5703
|
this._skillBrowseSource = 'org';
|
|
5697
|
-
/** Search text in the browse dialog
|
|
5704
|
+
/** Search text in the browse dialog, sent to `_searchSkills`. */
|
|
5698
5705
|
this._skillBrowseQuery = '';
|
|
5699
5706
|
this._handleMouseMove = (e) => {
|
|
5700
5707
|
if (this._isDragging) {
|
|
@@ -6037,12 +6044,14 @@
|
|
|
6037
6044
|
textarea.style.height = 'auto';
|
|
6038
6045
|
textarea.style.height = Math.min(textarea.scrollHeight, 120) + 'px';
|
|
6039
6046
|
// 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
|
|
6047
|
+
// leading slash with no space yet). The text after the slash is the search
|
|
6048
|
+
// query, run server-side via `_searchSkills`.
|
|
6041
6049
|
const slashMatch = this._inputValue.match(/^\/(\S*)$/);
|
|
6042
|
-
if (slashMatch
|
|
6050
|
+
if (slashMatch) {
|
|
6043
6051
|
this._skillMenuOpened = true;
|
|
6044
6052
|
this._skillQuery = slashMatch[1];
|
|
6045
6053
|
this._skillHighlighted = 0;
|
|
6054
|
+
this._searchSkills(this._skillQuery);
|
|
6046
6055
|
}
|
|
6047
6056
|
else {
|
|
6048
6057
|
this._skillMenuOpened = false;
|
|
@@ -6053,7 +6062,7 @@
|
|
|
6053
6062
|
// top actions (Attach Files, Browse All Skills) are index 0 and 1, then the
|
|
6054
6063
|
// filtered skills follow — all navigable as one list.
|
|
6055
6064
|
if (this._skillMenuOpened) {
|
|
6056
|
-
const count = 2 + this.
|
|
6065
|
+
const count = 2 + this._skillResults.length;
|
|
6057
6066
|
if (e.key === 'ArrowDown') {
|
|
6058
6067
|
e.preventDefault();
|
|
6059
6068
|
this._skillHighlighted = (this._skillHighlighted + 1) % count;
|
|
@@ -6090,19 +6099,64 @@
|
|
|
6090
6099
|
this._handleSkillBrowseOpen();
|
|
6091
6100
|
return;
|
|
6092
6101
|
}
|
|
6093
|
-
const skill = this.
|
|
6102
|
+
const skill = this._skillResults[index - 2];
|
|
6094
6103
|
if (skill) {
|
|
6095
6104
|
this._handleSkillSelect(skill);
|
|
6096
6105
|
}
|
|
6097
6106
|
}
|
|
6098
6107
|
// --- Skills ---
|
|
6099
|
-
/**
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6108
|
+
/**
|
|
6109
|
+
* Search the Kodaris AI skills index and store the results in `_skillResults`.
|
|
6110
|
+
* The `/` menu and the browse dialog both call this; results are shared since
|
|
6111
|
+
* the two are never open at once. Mirrors the backend's own skill search (BM25
|
|
6112
|
+
* over name^3/description^2/instructions, active-only) so the menu ranks skills
|
|
6113
|
+
* the way the model does. An empty query uses match_all — multi_match with an
|
|
6114
|
+
* empty string matches nothing, so the "show everything" case needs it.
|
|
6115
|
+
*
|
|
6116
|
+
* Follows the kr-combo-box `_fetch` pattern: a request-id guard drops responses
|
|
6117
|
+
* that arrive out of order. `/aiskills/search` returns a raw OpenSearch response,
|
|
6118
|
+
* so we lift each hit's `_source` (already in KRChatbotSkill shape) out.
|
|
6119
|
+
*/
|
|
6120
|
+
_searchSkills(query) {
|
|
6121
|
+
this._skillRequestId++;
|
|
6122
|
+
const requestId = this._skillRequestId;
|
|
6123
|
+
const trimmed = query.trim();
|
|
6124
|
+
// multi_match with an empty string matches nothing, so an empty query falls
|
|
6125
|
+
// back to match_all to show everything.
|
|
6126
|
+
let must = { match_all: {} };
|
|
6127
|
+
if (trimmed) {
|
|
6128
|
+
must = {
|
|
6129
|
+
multi_match: {
|
|
6130
|
+
query: trimmed,
|
|
6131
|
+
fields: ['name^3', 'description^2', 'instructions'],
|
|
6132
|
+
type: 'best_fields',
|
|
6133
|
+
},
|
|
6134
|
+
};
|
|
6135
|
+
}
|
|
6136
|
+
krubbleHttp.Http.fetch({
|
|
6137
|
+
url: '/api/system/opensearch/aiskills/search',
|
|
6138
|
+
method: 'POST',
|
|
6139
|
+
body: {
|
|
6140
|
+
size: 100,
|
|
6141
|
+
query: {
|
|
6142
|
+
bool: {
|
|
6143
|
+
must: [must],
|
|
6144
|
+
filter: [{ term: { active: true } }],
|
|
6145
|
+
},
|
|
6146
|
+
},
|
|
6147
|
+
},
|
|
6148
|
+
})
|
|
6149
|
+
.then((r) => r.json())
|
|
6150
|
+
.then((res) => {
|
|
6151
|
+
// Ignore a stale response superseded by a newer search.
|
|
6152
|
+
if (requestId !== this._skillRequestId) {
|
|
6153
|
+
return;
|
|
6154
|
+
}
|
|
6155
|
+
this._skillResults = (res?.data?.hits?.hits || []).map((hit) => hit._source);
|
|
6156
|
+
})
|
|
6157
|
+
.catch((error) => {
|
|
6158
|
+
console.error('kr-chatbot: skill search failed', error);
|
|
6159
|
+
});
|
|
6106
6160
|
}
|
|
6107
6161
|
/** The `+` button toggles the skill/attachment menu open (showing all skills). */
|
|
6108
6162
|
_handlePlusClick() {
|
|
@@ -6113,10 +6167,11 @@
|
|
|
6113
6167
|
this._skillQuery = '';
|
|
6114
6168
|
this._skillHighlighted = 0;
|
|
6115
6169
|
this._skillMenuOpened = true;
|
|
6170
|
+
this._searchSkills('');
|
|
6116
6171
|
}
|
|
6117
|
-
/** Insert `/
|
|
6172
|
+
/** Insert `/code ` into the composer and focus it, ready for the message. */
|
|
6118
6173
|
_handleSkillSelect(skill) {
|
|
6119
|
-
this._inputValue = `/${skill.
|
|
6174
|
+
this._inputValue = `/${skill.code} `;
|
|
6120
6175
|
this._skillMenuOpened = false;
|
|
6121
6176
|
this._skillBrowseOpened = false;
|
|
6122
6177
|
this._inputEl?.focus();
|
|
@@ -6136,29 +6191,18 @@
|
|
|
6136
6191
|
this._skillMenuOpened = false;
|
|
6137
6192
|
this._skillBrowseQuery = '';
|
|
6138
6193
|
this._skillBrowseOpened = true;
|
|
6194
|
+
this._searchSkills('');
|
|
6139
6195
|
}
|
|
6140
6196
|
_handleSkillBrowseClose() {
|
|
6141
6197
|
this._skillBrowseOpened = false;
|
|
6142
6198
|
}
|
|
6143
6199
|
_handleSkillBrowseSearch(e) {
|
|
6144
6200
|
this._skillBrowseQuery = e.target.value;
|
|
6201
|
+
this._searchSkills(this._skillBrowseQuery);
|
|
6145
6202
|
}
|
|
6146
6203
|
_handleSkillBrowseTabChange(e) {
|
|
6147
6204
|
this._skillBrowseSource = e.detail.activeTabId;
|
|
6148
6205
|
}
|
|
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
|
-
}
|
|
6162
6206
|
// --- Attachments ---
|
|
6163
6207
|
_openFilePicker() {
|
|
6164
6208
|
this._fileInputEl?.click();
|
|
@@ -6518,7 +6562,7 @@
|
|
|
6518
6562
|
// --- Render ---
|
|
6519
6563
|
/** The `/` skill menu shown above the composer while typing a slash command. */
|
|
6520
6564
|
_renderSkillMenu() {
|
|
6521
|
-
const skills = this.
|
|
6565
|
+
const skills = this._skillResults;
|
|
6522
6566
|
return b `
|
|
6523
6567
|
<div class="skill-menu">
|
|
6524
6568
|
<div class="skill-menu__actions">
|
|
@@ -6552,7 +6596,7 @@
|
|
|
6552
6596
|
})}
|
|
6553
6597
|
@click=${() => this._handleSkillSelect(skill)}
|
|
6554
6598
|
>
|
|
6555
|
-
<span class="skill-menu__name">${skill.
|
|
6599
|
+
<span class="skill-menu__name">${skill.name}</span>
|
|
6556
6600
|
${skill.description ? b `
|
|
6557
6601
|
<span class="skill-menu__desc">${skill.description}</span>
|
|
6558
6602
|
` : A}
|
|
@@ -6560,9 +6604,7 @@
|
|
|
6560
6604
|
</li>
|
|
6561
6605
|
`)}
|
|
6562
6606
|
</ul>
|
|
6563
|
-
` :
|
|
6564
|
-
<div class="skill-menu__empty">No matching skills</div>
|
|
6565
|
-
`}
|
|
6607
|
+
` : A}
|
|
6566
6608
|
</div>
|
|
6567
6609
|
`;
|
|
6568
6610
|
}
|
|
@@ -6589,18 +6631,20 @@
|
|
|
6589
6631
|
${this._renderSkillGrid()}
|
|
6590
6632
|
</kr-tab>
|
|
6591
6633
|
<kr-tab id="kodaris" label="Kodaris">
|
|
6592
|
-
|
|
6634
|
+
<div class="skill-browse__empty">
|
|
6635
|
+
Shared Kodaris skills are coming soon.
|
|
6636
|
+
</div>
|
|
6593
6637
|
</kr-tab>
|
|
6594
6638
|
</kr-tab-group>
|
|
6595
6639
|
</div>
|
|
6596
6640
|
</kr-dialog>
|
|
6597
6641
|
`;
|
|
6598
6642
|
}
|
|
6599
|
-
/** The card grid for the browse dialog
|
|
6643
|
+
/** The card grid of this org's skill search results for the browse dialog. */
|
|
6600
6644
|
_renderSkillGrid() {
|
|
6601
|
-
const skills = this.
|
|
6645
|
+
const skills = this._skillResults;
|
|
6602
6646
|
if (!skills.length) {
|
|
6603
|
-
return
|
|
6647
|
+
return A;
|
|
6604
6648
|
}
|
|
6605
6649
|
return b `
|
|
6606
6650
|
<div class="skill-browse__grid">
|
|
@@ -6609,7 +6653,7 @@
|
|
|
6609
6653
|
class="skill-card"
|
|
6610
6654
|
@click=${() => this._handleSkillSelect(skill)}
|
|
6611
6655
|
>
|
|
6612
|
-
<span class="skill-card__name">${skill.
|
|
6656
|
+
<span class="skill-card__name">${skill.name}</span>
|
|
6613
6657
|
${skill.description ? b `
|
|
6614
6658
|
<span class="skill-card__desc">${skill.description}</span>
|
|
6615
6659
|
` : A}
|
|
@@ -6619,12 +6663,13 @@
|
|
|
6619
6663
|
`;
|
|
6620
6664
|
}
|
|
6621
6665
|
/**
|
|
6622
|
-
* Render a user message, highlighting a leading `/skill-
|
|
6623
|
-
*
|
|
6666
|
+
* Render a user message, highlighting a leading `/skill-code` token (like the
|
|
6667
|
+
* way Claude highlights slash commands). The composer only inserts valid skill
|
|
6668
|
+
* codes, so any leading slash token is treated as one.
|
|
6624
6669
|
*/
|
|
6625
6670
|
_renderUserContent(content) {
|
|
6626
6671
|
const match = content.match(/^\/(\S+)(\s[\s\S]*)?$/);
|
|
6627
|
-
if (match
|
|
6672
|
+
if (match) {
|
|
6628
6673
|
return b `<span class="message-skill">/${match[1]}</span>${match[2] || ''}`;
|
|
6629
6674
|
}
|
|
6630
6675
|
return content;
|
|
@@ -7730,12 +7775,6 @@
|
|
|
7730
7775
|
white-space: nowrap;
|
|
7731
7776
|
}
|
|
7732
7777
|
|
|
7733
|
-
.skill-menu__empty {
|
|
7734
|
-
padding: 16px;
|
|
7735
|
-
text-align: center;
|
|
7736
|
-
color: #000000;
|
|
7737
|
-
}
|
|
7738
|
-
|
|
7739
7778
|
.skill-menu__actions {
|
|
7740
7779
|
display: flex;
|
|
7741
7780
|
flex-direction: column;
|
|
@@ -7826,6 +7865,12 @@
|
|
|
7826
7865
|
.skill-card__desc {
|
|
7827
7866
|
font-size: 12px;
|
|
7828
7867
|
color: #000000;
|
|
7868
|
+
/* Clamp to 3 lines so a long description doesn't make one card tower over
|
|
7869
|
+
its row-mates in the grid. */
|
|
7870
|
+
display: -webkit-box;
|
|
7871
|
+
-webkit-line-clamp: 3;
|
|
7872
|
+
-webkit-box-orient: vertical;
|
|
7873
|
+
overflow: hidden;
|
|
7829
7874
|
}
|
|
7830
7875
|
|
|
7831
7876
|
.skill-browse__empty {
|
|
@@ -7934,9 +7979,6 @@
|
|
|
7934
7979
|
__decorate([
|
|
7935
7980
|
n({ type: String })
|
|
7936
7981
|
], exports.Chatbot.prototype, "placeholder", void 0);
|
|
7937
|
-
__decorate([
|
|
7938
|
-
n({ attribute: false })
|
|
7939
|
-
], exports.Chatbot.prototype, "skills", void 0);
|
|
7940
7982
|
__decorate([
|
|
7941
7983
|
n({
|
|
7942
7984
|
type: Boolean,
|
|
@@ -7977,6 +8019,9 @@
|
|
|
7977
8019
|
__decorate([
|
|
7978
8020
|
r()
|
|
7979
8021
|
], exports.Chatbot.prototype, "_skillQuery", void 0);
|
|
8022
|
+
__decorate([
|
|
8023
|
+
r()
|
|
8024
|
+
], exports.Chatbot.prototype, "_skillResults", void 0);
|
|
7980
8025
|
__decorate([
|
|
7981
8026
|
r()
|
|
7982
8027
|
], exports.Chatbot.prototype, "_skillHighlighted", void 0);
|