@kodaris/krubble-app-components 1.0.80 → 1.0.82
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 -18
- package/dist/chatbot.d.ts.map +1 -1
- package/dist/chatbot.js +196 -105
- package/dist/chatbot.js.map +1 -1
- package/dist/krubble-app.bundled.js +196 -105
- package/dist/krubble-app.bundled.js.map +1 -1
- package/dist/krubble-app.bundled.min.js +45 -76
- package/dist/krubble-app.bundled.min.js.map +1 -1
- package/dist/krubble-app.umd.js +196 -105
- package/dist/krubble-app.umd.js.map +1 -1
- package/dist/krubble-app.umd.min.js +43 -74
- package/dist/krubble-app.umd.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -5621,8 +5621,9 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
5621
5621
|
* responses are dropped (mirrors the kr-combo-box `_requestId` pattern). Org and
|
|
5622
5622
|
* global searches run concurrently into separate buffers, so each has its own.
|
|
5623
5623
|
*/
|
|
5624
|
-
this.
|
|
5624
|
+
this._orgSkillRequestId = 0;
|
|
5625
5625
|
this._globalSkillRequestId = 0;
|
|
5626
|
+
this._invocableSkillRequestId = 0;
|
|
5626
5627
|
/**
|
|
5627
5628
|
* Codes of global skills with an in-flight enable/disable request. The `+`
|
|
5628
5629
|
* button reads this to show a pending state and ignore repeat clicks. Mutated
|
|
@@ -5731,20 +5732,27 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
5731
5732
|
this._isDraggingFile = false;
|
|
5732
5733
|
/** Whether the `/` skill menu is open above the composer. */
|
|
5733
5734
|
this._skillMenuOpened = false;
|
|
5734
|
-
/** Current `/` query (text after the slash), sent to `
|
|
5735
|
+
/** Current `/` query (text after the slash), sent to `_searchOrgSkills`. */
|
|
5735
5736
|
this._skillQuery = '';
|
|
5736
5737
|
/**
|
|
5737
|
-
* Latest org skill search results (this instance's own skills). Backs the
|
|
5738
|
-
*
|
|
5738
|
+
* Latest org skill search results (this instance's own skills). Backs the
|
|
5739
|
+
* browse dialog's "Your Org" tab only — global skills never appear here.
|
|
5739
5740
|
*/
|
|
5740
|
-
this.
|
|
5741
|
+
this._orgSkills = [];
|
|
5741
5742
|
/**
|
|
5742
5743
|
* Latest shared-Kodaris (global) skill results, for the browse dialog's
|
|
5743
|
-
* "Kodaris" tab. Kept separate from `
|
|
5744
|
+
* "Kodaris" tab. Kept separate from `_orgSkills` so switching tabs shows
|
|
5744
5745
|
* fresh results immediately instead of the other tab's stale list — the browse
|
|
5745
5746
|
* search fills both buffers at once.
|
|
5746
5747
|
*/
|
|
5747
|
-
this.
|
|
5748
|
+
this._globalSkills = [];
|
|
5749
|
+
/**
|
|
5750
|
+
* Latest results for the `/` composer menu: this instance's own org skills PLUS
|
|
5751
|
+
* the global skills installed on it (both are invocable by code). A separate
|
|
5752
|
+
* buffer from the two browse-tab lists so merging installed globals into the
|
|
5753
|
+
* menu never leaks them into the "Your Org" tab.
|
|
5754
|
+
*/
|
|
5755
|
+
this._invocableSkills = [];
|
|
5748
5756
|
/**
|
|
5749
5757
|
* AI framework UI config flags fetched from `aiFrameworkConfig` on connect.
|
|
5750
5758
|
* `debugTelemetryEnabled` (same server-side gate as TOKEN_USAGE emission) turns
|
|
@@ -5759,8 +5767,8 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
5759
5767
|
/** Whether the "Browse all skills" dialog is open. */
|
|
5760
5768
|
this._skillBrowseOpened = false;
|
|
5761
5769
|
/**
|
|
5762
|
-
* Active tab in the browse dialog. `org` shows `
|
|
5763
|
-
* skills); `kodaris` shows `
|
|
5770
|
+
* Active tab in the browse dialog. `org` shows `_orgSkills` (this instance's
|
|
5771
|
+
* skills); `kodaris` shows `_globalSkills` (the shared global catalog).
|
|
5764
5772
|
*/
|
|
5765
5773
|
this._skillBrowseSource = 'org';
|
|
5766
5774
|
/** Search text in the browse dialog, routed to the active tab's search. */
|
|
@@ -6153,13 +6161,14 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6153
6161
|
textarea.style.height = Math.min(textarea.scrollHeight, 120) + 'px';
|
|
6154
6162
|
// Open the skill menu while the message is a `/` command being typed (a
|
|
6155
6163
|
// leading slash with no space yet). The text after the slash is the search
|
|
6156
|
-
// query, run server-side via `
|
|
6164
|
+
// query, run server-side via `_searchInvocableSkills`.
|
|
6165
|
+
// (org skills + installed globals — everything invocable by /code)
|
|
6157
6166
|
const slashMatch = this._inputValue.match(/^\/(\S*)$/);
|
|
6158
6167
|
if (slashMatch) {
|
|
6159
6168
|
this._skillMenuOpened = true;
|
|
6160
6169
|
this._skillQuery = slashMatch[1];
|
|
6161
6170
|
this._skillHighlighted = 0;
|
|
6162
|
-
this.
|
|
6171
|
+
this._searchInvocableSkills(this._skillQuery);
|
|
6163
6172
|
}
|
|
6164
6173
|
else {
|
|
6165
6174
|
this._skillMenuOpened = false;
|
|
@@ -6175,7 +6184,7 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6175
6184
|
if (debugActions) {
|
|
6176
6185
|
actionCount = 4;
|
|
6177
6186
|
}
|
|
6178
|
-
const count = actionCount + this.
|
|
6187
|
+
const count = actionCount + this._invocableSkills.length;
|
|
6179
6188
|
if (e.key === 'ArrowDown') {
|
|
6180
6189
|
e.preventDefault();
|
|
6181
6190
|
this._skillHighlighted = (this._skillHighlighted + 1) % count;
|
|
@@ -6233,14 +6242,14 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6233
6242
|
});
|
|
6234
6243
|
return;
|
|
6235
6244
|
}
|
|
6236
|
-
const skill = this.
|
|
6245
|
+
const skill = this._invocableSkills[index - actionCount];
|
|
6237
6246
|
if (skill) {
|
|
6238
6247
|
this._handleSkillSelect(skill);
|
|
6239
6248
|
}
|
|
6240
6249
|
}
|
|
6241
6250
|
// --- Skills ---
|
|
6242
6251
|
/**
|
|
6243
|
-
* Search the Kodaris AI skills index and store the results in `
|
|
6252
|
+
* Search the Kodaris AI skills index and store the results in `_orgSkills`.
|
|
6244
6253
|
* The `/` menu and the browse dialog both call this; results are shared since
|
|
6245
6254
|
* the two are never open at once. Mirrors the backend's own skill search (BM25
|
|
6246
6255
|
* over name^3/description^2/instructions, active-only) so the menu ranks skills
|
|
@@ -6251,9 +6260,9 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6251
6260
|
* that arrive out of order. `/aiskills/search` returns a raw OpenSearch response,
|
|
6252
6261
|
* so we lift each hit's `_source` (already in KRChatbotSkill shape) out.
|
|
6253
6262
|
*/
|
|
6254
|
-
|
|
6255
|
-
this.
|
|
6256
|
-
const requestId = this.
|
|
6263
|
+
_searchOrgSkills(query) {
|
|
6264
|
+
this._orgSkillRequestId++;
|
|
6265
|
+
const requestId = this._orgSkillRequestId;
|
|
6257
6266
|
const trimmed = query.trim();
|
|
6258
6267
|
// An empty query matches everything; otherwise substring-match the query
|
|
6259
6268
|
// against name/code/description. We use case-insensitive wildcard queries on
|
|
@@ -6303,6 +6312,11 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6303
6312
|
bool: {
|
|
6304
6313
|
must: [must],
|
|
6305
6314
|
filter: [{ term: { active: true } }],
|
|
6315
|
+
// The "Your Org" tab lists only this instance's own skills. Globally-
|
|
6316
|
+
// published skills belong to the "Kodaris" tab (fed by the registry),
|
|
6317
|
+
// so exclude them here. Documents without the field aren't matched by
|
|
6318
|
+
// the term, so ordinary org skills are kept.
|
|
6319
|
+
must_not: [{ term: { globalPublished: true } }],
|
|
6306
6320
|
},
|
|
6307
6321
|
},
|
|
6308
6322
|
},
|
|
@@ -6310,17 +6324,106 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6310
6324
|
.then((r) => r.json())
|
|
6311
6325
|
.then((res) => {
|
|
6312
6326
|
// Ignore a stale response superseded by a newer search.
|
|
6313
|
-
if (requestId !== this.
|
|
6327
|
+
if (requestId !== this._orgSkillRequestId) {
|
|
6314
6328
|
return;
|
|
6315
6329
|
}
|
|
6316
|
-
this.
|
|
6330
|
+
this._orgSkills = (res?.data?.hits?.hits || []).map((hit) => hit._source);
|
|
6317
6331
|
})
|
|
6318
6332
|
.catch((error) => {
|
|
6319
6333
|
console.error('kr-chatbot: skill search failed', error);
|
|
6320
6334
|
});
|
|
6321
6335
|
}
|
|
6322
6336
|
/**
|
|
6323
|
-
* Search the
|
|
6337
|
+
* Search skills for the `/` composer menu into `_invocableSkills`: this instance's
|
|
6338
|
+
* own org skills PLUS the global skills installed on it, since both are
|
|
6339
|
+
* invocable by code. They come from two indexes (the local aiskills search and
|
|
6340
|
+
* the registry search filtered client-side to enabled), so we fire both and
|
|
6341
|
+
* concat — org skills first, then installed globals. Skill codes are unique
|
|
6342
|
+
* across the two, so no dedup is needed. Kept out of `_orgSkills` so
|
|
6343
|
+
* installed globals never leak into the browse dialog's "Your Org" tab.
|
|
6344
|
+
* (Cross-list relevance ranking is a later concern; for now org skills lead.)
|
|
6345
|
+
*/
|
|
6346
|
+
_searchInvocableSkills(query) {
|
|
6347
|
+
this._invocableSkillRequestId++;
|
|
6348
|
+
const requestId = this._invocableSkillRequestId;
|
|
6349
|
+
// Same wildcard matching as _searchOrgSkills (see there for the rationale).
|
|
6350
|
+
let must = { match_all: {} };
|
|
6351
|
+
if (query.trim()) {
|
|
6352
|
+
must = {
|
|
6353
|
+
bool: {
|
|
6354
|
+
should: [
|
|
6355
|
+
{
|
|
6356
|
+
wildcard: {
|
|
6357
|
+
'name.raw': {
|
|
6358
|
+
value: `*${query.trim().replace(/([*?\\])/g, '\\$1')}*`,
|
|
6359
|
+
case_insensitive: true,
|
|
6360
|
+
}
|
|
6361
|
+
}
|
|
6362
|
+
},
|
|
6363
|
+
{
|
|
6364
|
+
wildcard: {
|
|
6365
|
+
'code.raw': {
|
|
6366
|
+
value: `*${query.trim().replace(/([*?\\])/g, '\\$1')}*`,
|
|
6367
|
+
case_insensitive: true,
|
|
6368
|
+
}
|
|
6369
|
+
}
|
|
6370
|
+
},
|
|
6371
|
+
{
|
|
6372
|
+
wildcard: {
|
|
6373
|
+
'description.raw': {
|
|
6374
|
+
value: `*${query.trim().replace(/([*?\\])/g, '\\$1')}*`,
|
|
6375
|
+
case_insensitive: true,
|
|
6376
|
+
}
|
|
6377
|
+
}
|
|
6378
|
+
},
|
|
6379
|
+
],
|
|
6380
|
+
minimum_should_match: 1,
|
|
6381
|
+
},
|
|
6382
|
+
};
|
|
6383
|
+
}
|
|
6384
|
+
// Org skills — this instance's own catalog (globalPublished excluded).
|
|
6385
|
+
const orgSearch = KRHttp.fetch({
|
|
6386
|
+
url: '/api/system/opensearch/aiskills/search',
|
|
6387
|
+
method: 'POST',
|
|
6388
|
+
body: {
|
|
6389
|
+
size: 100,
|
|
6390
|
+
query: {
|
|
6391
|
+
bool: {
|
|
6392
|
+
must: [must],
|
|
6393
|
+
filter: [{ term: { active: true } }],
|
|
6394
|
+
must_not: [{ term: { globalPublished: true } }],
|
|
6395
|
+
},
|
|
6396
|
+
},
|
|
6397
|
+
},
|
|
6398
|
+
})
|
|
6399
|
+
.then((r) => r.json())
|
|
6400
|
+
.then((res) => (res?.data?.hits?.hits || []).map((hit) => hit._source))
|
|
6401
|
+
.catch((error) => {
|
|
6402
|
+
console.error('kr-chatbot: invocable skill search failed', error);
|
|
6403
|
+
return [];
|
|
6404
|
+
});
|
|
6405
|
+
// Installed globals — the registry catalog, kept only where enabled=true.
|
|
6406
|
+
const globalSearch = KRHttp.fetch({
|
|
6407
|
+
url: '/api/system/opensearch/aiskills/global/search',
|
|
6408
|
+
method: 'POST',
|
|
6409
|
+
body: { query: query.trim() },
|
|
6410
|
+
})
|
|
6411
|
+
.then((r) => r.json())
|
|
6412
|
+
.then((res) => (res?.data || []).filter((s) => !!s.enabled))
|
|
6413
|
+
.catch((error) => {
|
|
6414
|
+
console.error('kr-chatbot: installed global skill search failed', error);
|
|
6415
|
+
return [];
|
|
6416
|
+
});
|
|
6417
|
+
Promise.all([orgSearch, globalSearch]).then(([orgSkills, globalSkills]) => {
|
|
6418
|
+
// Ignore a stale response superseded by a newer search.
|
|
6419
|
+
if (requestId !== this._invocableSkillRequestId) {
|
|
6420
|
+
return;
|
|
6421
|
+
}
|
|
6422
|
+
this._invocableSkills = [...orgSkills, ...globalSkills];
|
|
6423
|
+
});
|
|
6424
|
+
}
|
|
6425
|
+
/**
|
|
6426
|
+
* Search the shared Kodaris global-skill registry into `_globalSkills`
|
|
6324
6427
|
* (the browse dialog's "Kodaris" tab). Unlike `/aiskills/search`,
|
|
6325
6428
|
* `/aiskills/global/search` returns a digested list
|
|
6326
6429
|
* (`data: [{ code, name, description, enabled }]`) already in `KRChatbotSkill`
|
|
@@ -6341,7 +6444,7 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6341
6444
|
if (requestId !== this._globalSkillRequestId) {
|
|
6342
6445
|
return;
|
|
6343
6446
|
}
|
|
6344
|
-
this.
|
|
6447
|
+
this._globalSkills = (res?.data || []);
|
|
6345
6448
|
})
|
|
6346
6449
|
.catch((error) => {
|
|
6347
6450
|
console.error('kr-chatbot: global skill search failed', error);
|
|
@@ -6353,13 +6456,16 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6353
6456
|
* matching card. Ignores clicks while a request for the same code is pending.
|
|
6354
6457
|
*/
|
|
6355
6458
|
_handleGlobalSkillEnable(skill, e) {
|
|
6356
|
-
// The card body inserts the skill; the
|
|
6459
|
+
// The card body inserts the skill; the install button must not also do that.
|
|
6357
6460
|
e.stopPropagation();
|
|
6358
6461
|
if (this._globalSkillPending.has(skill.code)) {
|
|
6359
6462
|
return;
|
|
6360
6463
|
}
|
|
6464
|
+
// Drive the clicked button's own spinner (KRButton disables itself while
|
|
6465
|
+
// loading, so a second click can't fire until the request settles).
|
|
6466
|
+
const btn = e.currentTarget;
|
|
6361
6467
|
this._globalSkillPending.add(skill.code);
|
|
6362
|
-
|
|
6468
|
+
btn?.showLoading();
|
|
6363
6469
|
KRHttp.fetch({
|
|
6364
6470
|
url: `/api/system/opensearch/aiskills/global/${encodeURIComponent(skill.code)}/enabled`,
|
|
6365
6471
|
method: 'POST',
|
|
@@ -6367,16 +6473,18 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6367
6473
|
})
|
|
6368
6474
|
.then((r) => r.json())
|
|
6369
6475
|
.then((res) => {
|
|
6370
|
-
// Reflect the server's returned flag on the card.
|
|
6476
|
+
// Reflect the server's returned flag on the card. The button label/style
|
|
6477
|
+
// re-render from skill.enabled; reset() clears the spinner to idle.
|
|
6371
6478
|
skill.enabled = res?.data?.enabled;
|
|
6479
|
+
btn?.reset();
|
|
6372
6480
|
this.requestUpdate();
|
|
6373
6481
|
})
|
|
6374
6482
|
.catch((error) => {
|
|
6375
6483
|
console.error('kr-chatbot: global skill enable failed', error);
|
|
6484
|
+
btn?.showError('Error');
|
|
6376
6485
|
})
|
|
6377
6486
|
.finally(() => {
|
|
6378
6487
|
this._globalSkillPending.delete(skill.code);
|
|
6379
|
-
this.requestUpdate();
|
|
6380
6488
|
});
|
|
6381
6489
|
}
|
|
6382
6490
|
/** The `+` button toggles the skill/attachment menu open (showing all skills). */
|
|
@@ -6388,10 +6496,17 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6388
6496
|
this._skillQuery = '';
|
|
6389
6497
|
this._skillHighlighted = 0;
|
|
6390
6498
|
this._skillMenuOpened = true;
|
|
6391
|
-
this.
|
|
6499
|
+
this._searchInvocableSkills('');
|
|
6392
6500
|
}
|
|
6393
6501
|
/** Insert `/code ` into the composer and focus it, ready for the message. */
|
|
6394
6502
|
_handleSkillSelect(skill) {
|
|
6503
|
+
// A global skill must be installed before it can be chosen — inserting /code
|
|
6504
|
+
// for one not enabled on this instance would just fail. `enabled` is only set
|
|
6505
|
+
// on global skills (false = not installed); org skills leave it undefined and
|
|
6506
|
+
// are always selectable. So an uninstalled global card click does nothing.
|
|
6507
|
+
if (skill.enabled === false) {
|
|
6508
|
+
return;
|
|
6509
|
+
}
|
|
6395
6510
|
this._inputValue = `/${skill.code} `;
|
|
6396
6511
|
this._saveState();
|
|
6397
6512
|
this._skillMenuOpened = false;
|
|
@@ -6421,7 +6536,7 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6421
6536
|
this._skillBrowseQuery = '';
|
|
6422
6537
|
this._skillBrowseOpened = true;
|
|
6423
6538
|
// Fill both tabs up front so switching between them is instant, not stale.
|
|
6424
|
-
this.
|
|
6539
|
+
this._searchOrgSkills('');
|
|
6425
6540
|
this._searchGlobalSkills('');
|
|
6426
6541
|
}
|
|
6427
6542
|
_handleSkillBrowseClose() {
|
|
@@ -6430,7 +6545,7 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6430
6545
|
_handleSkillBrowseSearch(e) {
|
|
6431
6546
|
this._skillBrowseQuery = e.target.value;
|
|
6432
6547
|
// Filter both catalogs so whichever tab the user switches to is already current.
|
|
6433
|
-
this.
|
|
6548
|
+
this._searchOrgSkills(this._skillBrowseQuery);
|
|
6434
6549
|
this._searchGlobalSkills(this._skillBrowseQuery);
|
|
6435
6550
|
}
|
|
6436
6551
|
_handleSkillBrowseTabChange(e) {
|
|
@@ -6875,7 +6990,7 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6875
6990
|
// --- Render ---
|
|
6876
6991
|
/** The `/` skill menu shown above the composer while typing a slash command. */
|
|
6877
6992
|
_renderSkillMenu() {
|
|
6878
|
-
const skills = this.
|
|
6993
|
+
const skills = this._invocableSkills;
|
|
6879
6994
|
// Debug test triggers are extra actions after Attach Files / Browse. The
|
|
6880
6995
|
// flat keyboard index counts actions first, then skills, so the skills'
|
|
6881
6996
|
// index offset is the number of actions shown.
|
|
@@ -6982,13 +7097,13 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
6982
7097
|
/**
|
|
6983
7098
|
* The card grid of skill search results for the browse dialog. Clicking a card
|
|
6984
7099
|
* inserts `/code ` into the composer. In the shared-Kodaris (`global`) tab each
|
|
6985
|
-
* card also gets a
|
|
6986
|
-
*
|
|
7100
|
+
* card also gets a footer row with an Enabled toggle that installs/removes the
|
|
7101
|
+
* skill on this instance.
|
|
6987
7102
|
*/
|
|
6988
7103
|
_renderSkillGrid(global = false) {
|
|
6989
|
-
let skills = this.
|
|
7104
|
+
let skills = this._orgSkills;
|
|
6990
7105
|
if (global) {
|
|
6991
|
-
skills = this.
|
|
7106
|
+
skills = this._globalSkills;
|
|
6992
7107
|
}
|
|
6993
7108
|
if (!skills.length) {
|
|
6994
7109
|
return A;
|
|
@@ -7007,44 +7122,39 @@ let KRChatbot = class KRChatbot extends i$3 {
|
|
|
7007
7122
|
${skill.description ? b `
|
|
7008
7123
|
<span class="skill-card__desc">${skill.description}</span>
|
|
7009
7124
|
` : A}
|
|
7010
|
-
${global ? this.
|
|
7125
|
+
${global ? this._renderSkillToggle(skill) : A}
|
|
7011
7126
|
</div>
|
|
7012
7127
|
`)}
|
|
7013
7128
|
</div>
|
|
7014
7129
|
`;
|
|
7015
7130
|
}
|
|
7131
|
+
/** Keep a click on the card footer from bubbling to the card's insert handler. */
|
|
7132
|
+
_stopFooterClick(e) {
|
|
7133
|
+
e.stopPropagation();
|
|
7134
|
+
}
|
|
7016
7135
|
/**
|
|
7017
|
-
* The install affordance on a global skill card: a
|
|
7018
|
-
*
|
|
7019
|
-
* while the enable/disable request is in flight
|
|
7136
|
+
* The install affordance on a global skill card: a footer row with an
|
|
7137
|
+
* install/remove button. The button owns its own spinner via KRButton's
|
|
7138
|
+
* showLoading()/showError() while the enable/disable request is in flight, so
|
|
7139
|
+
* the async call has clear feedback. Clicks are stopped from bubbling so the
|
|
7140
|
+
* button never also inserts the skill (the card body does that).
|
|
7020
7141
|
*/
|
|
7021
|
-
|
|
7142
|
+
_renderSkillToggle(skill) {
|
|
7143
|
+
const on = !!skill.enabled;
|
|
7022
7144
|
return b `
|
|
7023
|
-
<
|
|
7024
|
-
class
|
|
7025
|
-
|
|
7026
|
-
'skill-card__install--installed': !!skill.enabled,
|
|
7027
|
-
})}
|
|
7028
|
-
?disabled=${this._globalSkillPending.has(skill.code)}
|
|
7029
|
-
title=${!!skill.enabled ? 'Installed — click to remove' : 'Install this skill'}
|
|
7030
|
-
aria-label=${!!skill.enabled ? 'Remove skill' : 'Install skill'}
|
|
7031
|
-
@click=${(e) => this._handleGlobalSkillEnable(skill, e)}
|
|
7145
|
+
<div
|
|
7146
|
+
class="skill-card__footer"
|
|
7147
|
+
@click=${this._stopFooterClick}
|
|
7032
7148
|
>
|
|
7033
|
-
<
|
|
7034
|
-
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
>
|
|
7041
|
-
|
|
7042
|
-
stroke-linecap="round"
|
|
7043
|
-
stroke-linejoin="round"
|
|
7044
|
-
d=${!!skill.enabled ? 'm4.5 12.75 6 6 9-13.5' : 'M12 4.5v15m7.5-7.5h-15'}
|
|
7045
|
-
/>
|
|
7046
|
-
</svg>
|
|
7047
|
-
</button>
|
|
7149
|
+
<span class="skill-card__price">Free</span>
|
|
7150
|
+
<kr-button
|
|
7151
|
+
class="skill-card__install-btn"
|
|
7152
|
+
size="small"
|
|
7153
|
+
variant=${on ? 'outline' : 'flat'}
|
|
7154
|
+
color=${on ? 'secondary' : 'primary'}
|
|
7155
|
+
@click=${(e) => this._handleGlobalSkillEnable(skill, e)}
|
|
7156
|
+
>${on ? 'Uninstall' : 'Install'}</kr-button>
|
|
7157
|
+
</div>
|
|
7048
7158
|
`;
|
|
7049
7159
|
}
|
|
7050
7160
|
/**
|
|
@@ -8672,7 +8782,7 @@ KRChatbot.styles = i$6 `
|
|
|
8672
8782
|
height: 100%;
|
|
8673
8783
|
overflow-y: auto;
|
|
8674
8784
|
display: grid;
|
|
8675
|
-
grid-template-columns: repeat(
|
|
8785
|
+
grid-template-columns: repeat(2, 1fr);
|
|
8676
8786
|
grid-auto-rows: min-content;
|
|
8677
8787
|
align-content: start;
|
|
8678
8788
|
gap: 12px;
|
|
@@ -8700,53 +8810,31 @@ KRChatbot.styles = i$6 `
|
|
|
8700
8810
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
8701
8811
|
}
|
|
8702
8812
|
|
|
8703
|
-
/*
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
display: inline-flex;
|
|
8813
|
+
/* Footer row on global skill cards: install button on the left, price on the
|
|
8814
|
+
right. margin-top:auto pins it to the bottom so cards in a row align their
|
|
8815
|
+
footers regardless of description length. Negative horizontal margins
|
|
8816
|
+
(matching the card's 14px padding) pull the top border out to the full
|
|
8817
|
+
card width; the content is re-padded horizontally to stay inset. */
|
|
8818
|
+
.skill-card__footer {
|
|
8819
|
+
display: flex;
|
|
8711
8820
|
align-items: center;
|
|
8712
|
-
justify-content:
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
|
|
8719
|
-
color: #374151;
|
|
8720
|
-
cursor: pointer;
|
|
8721
|
-
transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
|
|
8722
|
-
}
|
|
8723
|
-
|
|
8724
|
-
.skill-card__install:hover:not(:disabled) {
|
|
8725
|
-
border-color: var(--kr-chatbot-primary);
|
|
8726
|
-
color: var(--kr-chatbot-primary);
|
|
8727
|
-
}
|
|
8728
|
-
|
|
8729
|
-
.skill-card__install:disabled {
|
|
8730
|
-
opacity: 0.5;
|
|
8731
|
-
cursor: default;
|
|
8732
|
-
}
|
|
8733
|
-
|
|
8734
|
-
/* Installed state: filled check. */
|
|
8735
|
-
.skill-card__install--installed {
|
|
8736
|
-
background: var(--kr-chatbot-primary);
|
|
8737
|
-
border-color: var(--kr-chatbot-primary);
|
|
8738
|
-
color: white;
|
|
8821
|
+
justify-content: space-between;
|
|
8822
|
+
gap: 8px;
|
|
8823
|
+
margin-top: 8px;
|
|
8824
|
+
margin-left: -14px;
|
|
8825
|
+
margin-right: -14px;
|
|
8826
|
+
padding: 14px 14px 0;
|
|
8827
|
+
border-top: 1px solid #e5e7eb;
|
|
8739
8828
|
}
|
|
8740
8829
|
|
|
8741
|
-
.skill-
|
|
8742
|
-
|
|
8743
|
-
|
|
8830
|
+
.skill-card__price {
|
|
8831
|
+
font-size: 13px;
|
|
8832
|
+
font-weight: 600;
|
|
8833
|
+
color: #000000;
|
|
8744
8834
|
}
|
|
8745
8835
|
|
|
8746
8836
|
.skill-card__name {
|
|
8747
8837
|
font-weight: 600;
|
|
8748
|
-
/* Leave room for the corner install button on global cards. */
|
|
8749
|
-
padding-right: 28px;
|
|
8750
8838
|
}
|
|
8751
8839
|
|
|
8752
8840
|
.skill-card__desc {
|
|
@@ -8935,10 +9023,13 @@ __decorate([
|
|
|
8935
9023
|
], KRChatbot.prototype, "_skillQuery", void 0);
|
|
8936
9024
|
__decorate([
|
|
8937
9025
|
r()
|
|
8938
|
-
], KRChatbot.prototype, "
|
|
9026
|
+
], KRChatbot.prototype, "_orgSkills", void 0);
|
|
9027
|
+
__decorate([
|
|
9028
|
+
r()
|
|
9029
|
+
], KRChatbot.prototype, "_globalSkills", void 0);
|
|
8939
9030
|
__decorate([
|
|
8940
9031
|
r()
|
|
8941
|
-
], KRChatbot.prototype, "
|
|
9032
|
+
], KRChatbot.prototype, "_invocableSkills", void 0);
|
|
8942
9033
|
__decorate([
|
|
8943
9034
|
r()
|
|
8944
9035
|
], KRChatbot.prototype, "_aiFrameworkConfig", void 0);
|