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