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