@kodaris/krubble-app-components 1.0.107 → 1.0.109
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 +91 -24
- package/dist/chatbot.d.ts.map +1 -1
- package/dist/chatbot.js +188 -85
- package/dist/chatbot.js.map +1 -1
- package/dist/krubble-app.bundled.js +188 -85
- package/dist/krubble-app.bundled.js.map +1 -1
- package/dist/krubble-app.bundled.min.js +178 -149
- package/dist/krubble-app.bundled.min.js.map +1 -1
- package/dist/krubble-app.umd.js +187 -84
- package/dist/krubble-app.umd.js.map +1 -1
- package/dist/krubble-app.umd.min.js +47 -18
- package/dist/krubble-app.umd.min.js.map +1 -1
- package/package.json +1 -1
package/dist/chatbot.d.ts
CHANGED
|
@@ -138,8 +138,9 @@ export interface KRChatbotCacheCheckpoint {
|
|
|
138
138
|
* A skill the user can invoke from the composer. Selecting one inserts
|
|
139
139
|
* `/code ` into the message body — there is no persistent skill state.
|
|
140
140
|
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
141
|
+
* Mirrors the backend `AvailableSkill` DTO returned by all three conversation
|
|
142
|
+
* skill endpoints (`/availableSkills`, `/localSkillList`, `/globalSkillList`),
|
|
143
|
+
* so results pass through without remapping.
|
|
143
144
|
*/
|
|
144
145
|
export interface KRChatbotSkill {
|
|
145
146
|
/** Skill code — the slash name inserted into the message (e.g. `invoice-auditor`). */
|
|
@@ -149,23 +150,47 @@ export interface KRChatbotSkill {
|
|
|
149
150
|
/** Short description shown in the browse dialog cards. */
|
|
150
151
|
description?: string;
|
|
151
152
|
/**
|
|
152
|
-
* Whether
|
|
153
|
-
*
|
|
154
|
-
* `+` button toggles it via `/aiskills/global/{code}/enabled`. Undefined for
|
|
155
|
-
* this org's own skills.
|
|
153
|
+
* Whether the skill is globally published — from the central Kodaris registry, or on
|
|
154
|
+
* kodaris.com one of that server's own published skills.
|
|
156
155
|
*/
|
|
156
|
+
global?: boolean;
|
|
157
|
+
/** Whether the skill is installed on this instance. Drives the Install/Uninstall button. */
|
|
157
158
|
enabled?: boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Whether the current user may turn this skill on/off for the instance (holds
|
|
161
|
+
* `administrator` / `superuser` / `skillEdit`).
|
|
162
|
+
*/
|
|
163
|
+
canEnable?: boolean;
|
|
164
|
+
/** Whether the user's roles satisfy the skill's roles, so they could invoke it. */
|
|
165
|
+
canRun?: boolean;
|
|
166
|
+
/**
|
|
167
|
+
* The skill's allowed roles — holding any one of them grants access. Lets the UX name
|
|
168
|
+
* the role to request when `canRun` is false. Empty when the skill is open to everyone.
|
|
169
|
+
*/
|
|
170
|
+
allowedRoles?: string[];
|
|
158
171
|
}
|
|
159
172
|
/**
|
|
160
173
|
* Callback function type for sending messages.
|
|
161
|
-
* Receives the user's message text, the current conversation history,
|
|
162
|
-
*
|
|
174
|
+
* Receives the user's message text, the current conversation history, the files
|
|
175
|
+
* attached to this message (each paired with its `aiAnalyze` flag), and the
|
|
176
|
+
* ambient page context captured at send time (see `_captureContext`). Must
|
|
163
177
|
* return a Response with a streaming body (SSE format).
|
|
164
178
|
*/
|
|
165
179
|
export type KRChatbotSend = (params: {
|
|
166
180
|
message: string;
|
|
167
181
|
messages: KRChatbotMessage[];
|
|
168
182
|
conversationFiles: KRChatbotSendFile[];
|
|
183
|
+
/**
|
|
184
|
+
* Where the user is, captured on this turn: a JSON string of the page URL,
|
|
185
|
+
* title, and (when the page renders one) the `#kodaris-page` island. Empty
|
|
186
|
+
* only if capture failed. The built-in send forwards it as `pageContext`.
|
|
187
|
+
*/
|
|
188
|
+
pageContext: string;
|
|
189
|
+
/**
|
|
190
|
+
* What the user currently has highlighted (selected text), captured on this
|
|
191
|
+
* turn. Empty when nothing is selected. Forwarded as `selectionContext`.
|
|
192
|
+
*/
|
|
193
|
+
selectionContext: string;
|
|
169
194
|
}) => Promise<Response>;
|
|
170
195
|
/**
|
|
171
196
|
* A file being sent with a message, paired with its analyze flag. Passed to the
|
|
@@ -494,15 +519,22 @@ export declare class KRChatbot extends LitElement {
|
|
|
494
519
|
/** Run the skill-menu item at the given flat index (actions first, then skills). */
|
|
495
520
|
private _activateSkillMenuItem;
|
|
496
521
|
/**
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
*
|
|
500
|
-
*
|
|
501
|
-
*
|
|
522
|
+
* Load the browse dialog's "Your Org" tab into `_orgSkills` from
|
|
523
|
+
* `/conversation/localSkillList` — this instance's own active skills, already
|
|
524
|
+
* role-filtered to what the caller may run and ranked by the server.
|
|
525
|
+
*
|
|
526
|
+
* Not the `aiskills` search endpoint: that requires a skill-authoring role
|
|
527
|
+
* (`skillView`/`skillEdit`), so an ordinary chat user got a 403 and an empty
|
|
528
|
+
* tab. This one only needs a logged-in employee. It also means the query
|
|
529
|
+
* matching, active-only filter and "exclude globally-published" rule all live
|
|
530
|
+
* server-side instead of being rebuilt as OpenSearch DSL here.
|
|
531
|
+
*
|
|
532
|
+
* EXCEPTION — on kodaris.com this list also carries that instance's own
|
|
533
|
+
* globally-published skills (flagged `global: true`), because there is no
|
|
534
|
+
* Kodaris tab there for them to appear on.
|
|
502
535
|
*
|
|
503
|
-
*
|
|
504
|
-
*
|
|
505
|
-
* so we lift each hit's `_source` (already in KRChatbotSkill shape) out.
|
|
536
|
+
* Request-id guard drops responses that arrive out of order (kr-combo-box
|
|
537
|
+
* `_fetch` pattern).
|
|
506
538
|
*/
|
|
507
539
|
private _searchOrgSkills;
|
|
508
540
|
/**
|
|
@@ -520,13 +552,17 @@ export declare class KRChatbot extends LitElement {
|
|
|
520
552
|
*/
|
|
521
553
|
private _searchInvocableSkills;
|
|
522
554
|
/**
|
|
523
|
-
* Load the browse dialog's "Kodaris" tab into `_globalSkills` — the
|
|
524
|
-
* catalog, installed or not,
|
|
555
|
+
* Load the browse dialog's "Kodaris" tab into `_globalSkills` — the whole
|
|
556
|
+
* published Kodaris catalog for discovery, installed or not, runnable by this
|
|
557
|
+
* user or not. Each row carries `enabled` (installed here), `canEnable` (may
|
|
558
|
+
* install it) and `canRun` (roles allow invoking it).
|
|
525
559
|
*
|
|
526
|
-
* Uses `/conversation/
|
|
560
|
+
* Uses `/conversation/globalSkillList` rather than the `/aiskills/global/search`
|
|
527
561
|
* twin, which requires a skill-authoring role an ordinary chat user doesn't have.
|
|
528
|
-
*
|
|
529
|
-
*
|
|
562
|
+
*
|
|
563
|
+
* Returns `[]` — not an error — when there's no reachable registry, and always
|
|
564
|
+
* on kodaris.com, which IS the catalog source and so has no remote to pull. The
|
|
565
|
+
* tab itself is hidden there (see `_renderSkillBrowse`).
|
|
530
566
|
*/
|
|
531
567
|
private _searchGlobalSkills;
|
|
532
568
|
/**
|
|
@@ -547,6 +583,7 @@ export declare class KRChatbot extends LitElement {
|
|
|
547
583
|
* there's no backend call or cost on our side.
|
|
548
584
|
*/
|
|
549
585
|
private _handleMicClick;
|
|
586
|
+
/**
|
|
550
587
|
/** Insert `/code ` into the composer and focus it, ready for the message. */
|
|
551
588
|
private _handleSkillSelect;
|
|
552
589
|
/** Activate a skill card via keyboard (Enter/Space), since it's a div role=button. */
|
|
@@ -594,6 +631,24 @@ export declare class KRChatbot extends LitElement {
|
|
|
594
631
|
* firing the cancelable `message-submit` event; this owns the send + stream.
|
|
595
632
|
*/
|
|
596
633
|
private _send;
|
|
634
|
+
/**
|
|
635
|
+
* Capture ambient "where is the user / what are they looking at" context at
|
|
636
|
+
* send time, so the AI is grounded without the host passing anything in.
|
|
637
|
+
*
|
|
638
|
+
* Two universal sources that exist on every page the chatbot mounts in:
|
|
639
|
+
* - `pageContext` — the location (full url, which already carries the path and
|
|
640
|
+
* query) and title, plus, when the page renders the server-side
|
|
641
|
+
* `#kodaris-page` JSON island (storefront content pages do), its parsed
|
|
642
|
+
* contents (page name/type/ids). A page without the island still yields url
|
|
643
|
+
* + title, so context is never empty on a real page.
|
|
644
|
+
* - `selectionContext` — the text the user currently has highlighted, read
|
|
645
|
+
* live here because a selection is transient (it may be gone a moment later).
|
|
646
|
+
*
|
|
647
|
+
* Both are returned as strings because that's what the backend `ModelForText`
|
|
648
|
+
* fields (`pageContext` / `selectionContext`) accept. Capture is best-effort:
|
|
649
|
+
* any failure yields an empty string for that field rather than blocking send.
|
|
650
|
+
*/
|
|
651
|
+
private _captureContext;
|
|
597
652
|
private _handleStop;
|
|
598
653
|
private _handleMessagesScroll;
|
|
599
654
|
private _handleErrorDismiss;
|
|
@@ -606,13 +661,25 @@ export declare class KRChatbot extends LitElement {
|
|
|
606
661
|
private _handleStreamError;
|
|
607
662
|
/** The `/` skill menu shown above the composer while typing a slash command. */
|
|
608
663
|
private _renderSkillMenu;
|
|
609
|
-
/**
|
|
664
|
+
/**
|
|
665
|
+
* The "Browse all skills" dialog — a searchable grid of Org / Kodaris cards.
|
|
666
|
+
*
|
|
667
|
+
* The Kodaris tab is omitted on the registry server (kodaris.com): that instance
|
|
668
|
+
* IS the catalog source, so `globalSkillList` has no remote to pull and always
|
|
669
|
+
* returns `[]`. Its own published skills appear on the Your Org tab instead,
|
|
670
|
+
* carrying a "Global" badge.
|
|
671
|
+
*/
|
|
610
672
|
private _renderSkillBrowse;
|
|
611
673
|
/**
|
|
612
674
|
* The card grid of skill search results for the browse dialog. Clicking a card
|
|
613
675
|
* inserts `/code ` into the composer. In the shared-Kodaris (`global`) tab each
|
|
614
|
-
* card also gets a footer row with an
|
|
615
|
-
*
|
|
676
|
+
* card also gets a footer row with an Install/Uninstall button.
|
|
677
|
+
*
|
|
678
|
+
* The Kodaris tab is the whole published catalog, deliberately NOT role-filtered so
|
|
679
|
+
* users can discover skills they don't have yet. So a card there can be in one of two
|
|
680
|
+
* non-runnable states — the user's roles don't allow it (`canRun: false`), or it isn't
|
|
681
|
+
* installed here (not `enabled`). Neither looks clickable; clicking either explains
|
|
682
|
+
* why via `_handleSkillSelect`.
|
|
616
683
|
*/
|
|
617
684
|
private _renderSkillGrid;
|
|
618
685
|
/**
|
package/dist/chatbot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chatbot.d.ts","sourceRoot":"","sources":["../src/chatbot.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"chatbot.d.ts","sourceRoot":"","sources":["../src/chatbot.ts"],"names":[],"mappings":"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"}
|
package/dist/chatbot.js
CHANGED
|
@@ -13,7 +13,7 @@ import { repeat } from 'lit/directives/repeat.js';
|
|
|
13
13
|
import { marked } from 'marked';
|
|
14
14
|
// Importing these named exports also registers their custom elements
|
|
15
15
|
// (kr-dialog, kr-tab-group, kr-tab, kr-text-field) used by the browse dialog.
|
|
16
|
-
import { KRFilePreview } from '@kodaris/krubble-components';
|
|
16
|
+
import { KRFilePreview, KRSnackbar } from '@kodaris/krubble-components';
|
|
17
17
|
import { KRHttp } from '@kodaris/krubble-http';
|
|
18
18
|
/** Image extensions the chatbot renders as thumbnails (used when MIME is absent). */
|
|
19
19
|
const IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
|
@@ -843,76 +843,30 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
843
843
|
}
|
|
844
844
|
// --- Skills ---
|
|
845
845
|
/**
|
|
846
|
-
*
|
|
847
|
-
*
|
|
848
|
-
*
|
|
849
|
-
* match_all — multi_match with an empty string matches nothing, so the "show
|
|
850
|
-
* everything" case needs it.
|
|
846
|
+
* Load the browse dialog's "Your Org" tab into `_orgSkills` from
|
|
847
|
+
* `/conversation/localSkillList` — this instance's own active skills, already
|
|
848
|
+
* role-filtered to what the caller may run and ranked by the server.
|
|
851
849
|
*
|
|
852
|
-
*
|
|
853
|
-
*
|
|
854
|
-
*
|
|
850
|
+
* Not the `aiskills` search endpoint: that requires a skill-authoring role
|
|
851
|
+
* (`skillView`/`skillEdit`), so an ordinary chat user got a 403 and an empty
|
|
852
|
+
* tab. This one only needs a logged-in employee. It also means the query
|
|
853
|
+
* matching, active-only filter and "exclude globally-published" rule all live
|
|
854
|
+
* server-side instead of being rebuilt as OpenSearch DSL here.
|
|
855
|
+
*
|
|
856
|
+
* EXCEPTION — on kodaris.com this list also carries that instance's own
|
|
857
|
+
* globally-published skills (flagged `global: true`), because there is no
|
|
858
|
+
* Kodaris tab there for them to appear on.
|
|
859
|
+
*
|
|
860
|
+
* Request-id guard drops responses that arrive out of order (kr-combo-box
|
|
861
|
+
* `_fetch` pattern).
|
|
855
862
|
*/
|
|
856
863
|
_searchOrgSkills(query) {
|
|
857
864
|
this._orgSkillRequestId++;
|
|
858
865
|
const requestId = this._orgSkillRequestId;
|
|
859
|
-
const trimmed = query.trim();
|
|
860
|
-
// An empty query matches everything; otherwise substring-match the query
|
|
861
|
-
// against name/code/description. We use case-insensitive wildcard queries on
|
|
862
|
-
// the `.raw` keyword subfields so "ord" matches anywhere in "Create Order"
|
|
863
|
-
// (a plain match/multi_match only matches whole tokens). Escape the wildcard
|
|
864
|
-
// specials so user input is treated literally, then wrap with `*...*`.
|
|
865
|
-
let must = { match_all: {} };
|
|
866
|
-
if (trimmed) {
|
|
867
|
-
must = {
|
|
868
|
-
bool: {
|
|
869
|
-
should: [
|
|
870
|
-
{
|
|
871
|
-
wildcard: {
|
|
872
|
-
'name.raw': {
|
|
873
|
-
value: `*${trimmed.replace(/([*?\\])/g, '\\$1')}*`,
|
|
874
|
-
case_insensitive: true,
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
},
|
|
878
|
-
{
|
|
879
|
-
wildcard: {
|
|
880
|
-
'code.raw': {
|
|
881
|
-
value: `*${trimmed.replace(/([*?\\])/g, '\\$1')}*`,
|
|
882
|
-
case_insensitive: true,
|
|
883
|
-
}
|
|
884
|
-
}
|
|
885
|
-
},
|
|
886
|
-
{
|
|
887
|
-
wildcard: {
|
|
888
|
-
'description.raw': {
|
|
889
|
-
value: `*${trimmed.replace(/([*?\\])/g, '\\$1')}*`,
|
|
890
|
-
case_insensitive: true,
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
},
|
|
894
|
-
],
|
|
895
|
-
minimum_should_match: 1,
|
|
896
|
-
},
|
|
897
|
-
};
|
|
898
|
-
}
|
|
899
866
|
KRHttp.fetch({
|
|
900
|
-
url: '/api/system/
|
|
867
|
+
url: '/api/system/conversation/localSkillList',
|
|
901
868
|
method: 'POST',
|
|
902
|
-
body: {
|
|
903
|
-
size: 100,
|
|
904
|
-
query: {
|
|
905
|
-
bool: {
|
|
906
|
-
must: [must],
|
|
907
|
-
filter: [{ term: { active: true } }],
|
|
908
|
-
// The "Your Org" tab lists only this instance's own skills. Globally-
|
|
909
|
-
// published skills belong to the "Kodaris" tab (fed by the registry),
|
|
910
|
-
// so exclude them here. Documents without the field aren't matched by
|
|
911
|
-
// the term, so ordinary org skills are kept.
|
|
912
|
-
must_not: [{ term: { globalPublished: true } }],
|
|
913
|
-
},
|
|
914
|
-
},
|
|
915
|
-
},
|
|
869
|
+
body: { query: query.trim() },
|
|
916
870
|
})
|
|
917
871
|
.then((r) => r.json())
|
|
918
872
|
.then((res) => {
|
|
@@ -920,7 +874,7 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
920
874
|
if (requestId !== this._orgSkillRequestId) {
|
|
921
875
|
return;
|
|
922
876
|
}
|
|
923
|
-
this._orgSkills = (res?.data
|
|
877
|
+
this._orgSkills = (res?.data || []);
|
|
924
878
|
})
|
|
925
879
|
.catch((error) => {
|
|
926
880
|
console.error('kr-chatbot: skill search failed', error);
|
|
@@ -960,19 +914,23 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
960
914
|
});
|
|
961
915
|
}
|
|
962
916
|
/**
|
|
963
|
-
* Load the browse dialog's "Kodaris" tab into `_globalSkills` — the
|
|
964
|
-
* catalog, installed or not,
|
|
917
|
+
* Load the browse dialog's "Kodaris" tab into `_globalSkills` — the whole
|
|
918
|
+
* published Kodaris catalog for discovery, installed or not, runnable by this
|
|
919
|
+
* user or not. Each row carries `enabled` (installed here), `canEnable` (may
|
|
920
|
+
* install it) and `canRun` (roles allow invoking it).
|
|
965
921
|
*
|
|
966
|
-
* Uses `/conversation/
|
|
922
|
+
* Uses `/conversation/globalSkillList` rather than the `/aiskills/global/search`
|
|
967
923
|
* twin, which requires a skill-authoring role an ordinary chat user doesn't have.
|
|
968
|
-
*
|
|
969
|
-
*
|
|
924
|
+
*
|
|
925
|
+
* Returns `[]` — not an error — when there's no reachable registry, and always
|
|
926
|
+
* on kodaris.com, which IS the catalog source and so has no remote to pull. The
|
|
927
|
+
* tab itself is hidden there (see `_renderSkillBrowse`).
|
|
970
928
|
*/
|
|
971
929
|
_searchGlobalSkills(query) {
|
|
972
930
|
this._globalSkillRequestId++;
|
|
973
931
|
const requestId = this._globalSkillRequestId;
|
|
974
932
|
KRHttp.fetch({
|
|
975
|
-
url: '/api/system/conversation/
|
|
933
|
+
url: '/api/system/conversation/globalSkillList',
|
|
976
934
|
method: 'POST',
|
|
977
935
|
body: { query: query.trim() },
|
|
978
936
|
})
|
|
@@ -996,6 +954,17 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
996
954
|
_handleGlobalSkillEnable(skill, e) {
|
|
997
955
|
// The card body inserts the skill; the install button must not also do that.
|
|
998
956
|
e.stopPropagation();
|
|
957
|
+
// The button is shown to everyone so the catalog reads the same for all users,
|
|
958
|
+
// but the enable endpoint requires administrator/superuser/skillEdit. Without
|
|
959
|
+
// it, say who to ask instead of firing a request that comes back 403.
|
|
960
|
+
if (!skill.canEnable) {
|
|
961
|
+
KRSnackbar.show({
|
|
962
|
+
title: 'Permission Required',
|
|
963
|
+
message: 'You do not have permission to install skills. Please contact your site administrator.',
|
|
964
|
+
type: 'error',
|
|
965
|
+
});
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
999
968
|
if (this._globalSkillPending.has(skill.code)) {
|
|
1000
969
|
return;
|
|
1001
970
|
}
|
|
@@ -1122,13 +1091,33 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
1122
1091
|
recognition.start();
|
|
1123
1092
|
this._inputEl?.focus();
|
|
1124
1093
|
}
|
|
1094
|
+
/**
|
|
1125
1095
|
/** Insert `/code ` into the composer and focus it, ready for the message. */
|
|
1126
1096
|
_handleSkillSelect(skill) {
|
|
1127
|
-
//
|
|
1128
|
-
//
|
|
1129
|
-
//
|
|
1130
|
-
|
|
1131
|
-
|
|
1097
|
+
// The user's roles don't allow this skill — inserting /code would just fail in the
|
|
1098
|
+
// chat. Name the roles that would grant it, so the user knows what to ask for and
|
|
1099
|
+
// whoever grants it knows what to give.
|
|
1100
|
+
if (skill.canRun === false) {
|
|
1101
|
+
let message = `You do not have access to "${skill.name}". Ask your site administrator to grant it.`;
|
|
1102
|
+
if (skill.allowedRoles?.length) {
|
|
1103
|
+
message = `"${skill.name}" requires the ${skill.allowedRoles.join(' or ')} role. Ask your site administrator to grant it.`;
|
|
1104
|
+
}
|
|
1105
|
+
KRSnackbar.show({
|
|
1106
|
+
title: 'Access Required',
|
|
1107
|
+
message: message,
|
|
1108
|
+
type: 'error',
|
|
1109
|
+
});
|
|
1110
|
+
return;
|
|
1111
|
+
}
|
|
1112
|
+
// A global skill nobody has installed here yet isn't runnable either — point at the
|
|
1113
|
+
// Install button rather than appearing to ignore the click. Local skills carry no
|
|
1114
|
+
// install state, so this only applies to global ones.
|
|
1115
|
+
if (skill.global && !skill.enabled) {
|
|
1116
|
+
KRSnackbar.show({
|
|
1117
|
+
title: 'Not Installed',
|
|
1118
|
+
message: `"${skill.name}" has to be installed on this site before you can use it — use the Install button on the card.`,
|
|
1119
|
+
type: 'info',
|
|
1120
|
+
});
|
|
1132
1121
|
return;
|
|
1133
1122
|
}
|
|
1134
1123
|
this._inputValue = `/${skill.code} `;
|
|
@@ -1160,8 +1149,11 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
1160
1149
|
this._skillBrowseQuery = '';
|
|
1161
1150
|
this._skillBrowseOpened = true;
|
|
1162
1151
|
// Fill both tabs up front so switching between them is instant, not stale.
|
|
1152
|
+
// The Kodaris tab isn't rendered on the registry server, so skip its fetch there.
|
|
1163
1153
|
this._searchOrgSkills('');
|
|
1164
|
-
this.
|
|
1154
|
+
if (this._aiFrameworkConfig.registryServer !== true) {
|
|
1155
|
+
this._searchGlobalSkills('');
|
|
1156
|
+
}
|
|
1165
1157
|
}
|
|
1166
1158
|
_handleSkillBrowseClose() {
|
|
1167
1159
|
this._skillBrowseOpened = false;
|
|
@@ -1170,7 +1162,9 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
1170
1162
|
this._skillBrowseQuery = e.target.value;
|
|
1171
1163
|
// Filter both catalogs so whichever tab the user switches to is already current.
|
|
1172
1164
|
this._searchOrgSkills(this._skillBrowseQuery);
|
|
1173
|
-
|
|
1165
|
+
if (this._aiFrameworkConfig.registryServer !== true) {
|
|
1166
|
+
this._searchGlobalSkills(this._skillBrowseQuery);
|
|
1167
|
+
}
|
|
1174
1168
|
}
|
|
1175
1169
|
_handleSkillBrowseTabChange(e) {
|
|
1176
1170
|
// Both buffers are kept current by open/search, so switching just swaps which
|
|
@@ -1512,6 +1506,15 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
1512
1506
|
userText: params.message,
|
|
1513
1507
|
fileIds: files.map((f) => f.conversationFileID),
|
|
1514
1508
|
};
|
|
1509
|
+
// Ground the model in where the user is and what they've highlighted.
|
|
1510
|
+
// Only sent when present so an empty selection / failed capture doesn't
|
|
1511
|
+
// add noise to the request.
|
|
1512
|
+
if (params.pageContext) {
|
|
1513
|
+
body.pageContext = params.pageContext;
|
|
1514
|
+
}
|
|
1515
|
+
if (params.selectionContext) {
|
|
1516
|
+
body.selectionContext = params.selectionContext;
|
|
1517
|
+
}
|
|
1515
1518
|
if (this.conversationId != null) {
|
|
1516
1519
|
body.conversationID = this.conversationId;
|
|
1517
1520
|
}
|
|
@@ -1556,10 +1559,16 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
1556
1559
|
});
|
|
1557
1560
|
};
|
|
1558
1561
|
}
|
|
1562
|
+
// Capture where the user is and what they've highlighted at send time (not
|
|
1563
|
+
// earlier — selection is transient and the route may have changed since the
|
|
1564
|
+
// panel opened), so every turn grounds the model in the user's current spot.
|
|
1565
|
+
const context = this._captureContext();
|
|
1559
1566
|
this.send({
|
|
1560
1567
|
message: params.message,
|
|
1561
1568
|
messages: this.messages.slice(0, -1),
|
|
1562
1569
|
conversationFiles: params.conversationFiles,
|
|
1570
|
+
pageContext: context.pageContext,
|
|
1571
|
+
selectionContext: context.selectionContext,
|
|
1563
1572
|
}).then((response) => {
|
|
1564
1573
|
if (!response.ok) {
|
|
1565
1574
|
this._handleStreamError('Request failed: ' + response.status);
|
|
@@ -1579,6 +1588,56 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
1579
1588
|
}
|
|
1580
1589
|
});
|
|
1581
1590
|
}
|
|
1591
|
+
/**
|
|
1592
|
+
* Capture ambient "where is the user / what are they looking at" context at
|
|
1593
|
+
* send time, so the AI is grounded without the host passing anything in.
|
|
1594
|
+
*
|
|
1595
|
+
* Two universal sources that exist on every page the chatbot mounts in:
|
|
1596
|
+
* - `pageContext` — the location (full url, which already carries the path and
|
|
1597
|
+
* query) and title, plus, when the page renders the server-side
|
|
1598
|
+
* `#kodaris-page` JSON island (storefront content pages do), its parsed
|
|
1599
|
+
* contents (page name/type/ids). A page without the island still yields url
|
|
1600
|
+
* + title, so context is never empty on a real page.
|
|
1601
|
+
* - `selectionContext` — the text the user currently has highlighted, read
|
|
1602
|
+
* live here because a selection is transient (it may be gone a moment later).
|
|
1603
|
+
*
|
|
1604
|
+
* Both are returned as strings because that's what the backend `ModelForText`
|
|
1605
|
+
* fields (`pageContext` / `selectionContext`) accept. Capture is best-effort:
|
|
1606
|
+
* any failure yields an empty string for that field rather than blocking send.
|
|
1607
|
+
*/
|
|
1608
|
+
_captureContext() {
|
|
1609
|
+
let pageContext = '';
|
|
1610
|
+
try {
|
|
1611
|
+
const page = {
|
|
1612
|
+
url: window.location.href,
|
|
1613
|
+
title: document.title,
|
|
1614
|
+
};
|
|
1615
|
+
// Structured page context is opt-in by convention: a page that renders the
|
|
1616
|
+
// `#kodaris-page` island gets its name/type/ids folded in for free. The
|
|
1617
|
+
// island's text is JSON; a malformed/absent island just leaves it out.
|
|
1618
|
+
const island = document.getElementById('kodaris-page');
|
|
1619
|
+
if (island && island.textContent) {
|
|
1620
|
+
try {
|
|
1621
|
+
page.page = JSON.parse(island.textContent);
|
|
1622
|
+
}
|
|
1623
|
+
catch { /* island present but not valid JSON — location context still stands */ }
|
|
1624
|
+
}
|
|
1625
|
+
pageContext = JSON.stringify(page);
|
|
1626
|
+
}
|
|
1627
|
+
catch { /* leave pageContext empty — never block a send on context capture */ }
|
|
1628
|
+
let selectionContext = '';
|
|
1629
|
+
try {
|
|
1630
|
+
const selection = window.getSelection();
|
|
1631
|
+
if (selection) {
|
|
1632
|
+
selectionContext = selection.toString().trim();
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
catch { /* leave selectionContext empty */ }
|
|
1636
|
+
return {
|
|
1637
|
+
pageContext,
|
|
1638
|
+
selectionContext,
|
|
1639
|
+
};
|
|
1640
|
+
}
|
|
1582
1641
|
_handleStop() {
|
|
1583
1642
|
if (this._reader) {
|
|
1584
1643
|
this._reader.cancel();
|
|
@@ -1852,7 +1911,14 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
1852
1911
|
</div>
|
|
1853
1912
|
`;
|
|
1854
1913
|
}
|
|
1855
|
-
/**
|
|
1914
|
+
/**
|
|
1915
|
+
* The "Browse all skills" dialog — a searchable grid of Org / Kodaris cards.
|
|
1916
|
+
*
|
|
1917
|
+
* The Kodaris tab is omitted on the registry server (kodaris.com): that instance
|
|
1918
|
+
* IS the catalog source, so `globalSkillList` has no remote to pull and always
|
|
1919
|
+
* returns `[]`. Its own published skills appear on the Your Org tab instead,
|
|
1920
|
+
* carrying a "Global" badge.
|
|
1921
|
+
*/
|
|
1856
1922
|
_renderSkillBrowse() {
|
|
1857
1923
|
return html `
|
|
1858
1924
|
<kr-dialog
|
|
@@ -1874,9 +1940,11 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
1874
1940
|
<kr-tab id="org" label="Your Org">
|
|
1875
1941
|
${this._renderSkillGrid()}
|
|
1876
1942
|
</kr-tab>
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1943
|
+
${this._aiFrameworkConfig.registryServer === true ? nothing : html `
|
|
1944
|
+
<kr-tab id="kodaris" label="Kodaris">
|
|
1945
|
+
${this._renderSkillGrid(true)}
|
|
1946
|
+
</kr-tab>
|
|
1947
|
+
`}
|
|
1880
1948
|
</kr-tab-group>
|
|
1881
1949
|
</div>
|
|
1882
1950
|
</kr-dialog>
|
|
@@ -1885,8 +1953,13 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
1885
1953
|
/**
|
|
1886
1954
|
* The card grid of skill search results for the browse dialog. Clicking a card
|
|
1887
1955
|
* inserts `/code ` into the composer. In the shared-Kodaris (`global`) tab each
|
|
1888
|
-
* card also gets a footer row with an
|
|
1889
|
-
*
|
|
1956
|
+
* card also gets a footer row with an Install/Uninstall button.
|
|
1957
|
+
*
|
|
1958
|
+
* The Kodaris tab is the whole published catalog, deliberately NOT role-filtered so
|
|
1959
|
+
* users can discover skills they don't have yet. So a card there can be in one of two
|
|
1960
|
+
* non-runnable states — the user's roles don't allow it (`canRun: false`), or it isn't
|
|
1961
|
+
* installed here (not `enabled`). Neither looks clickable; clicking either explains
|
|
1962
|
+
* why via `_handleSkillSelect`.
|
|
1890
1963
|
*/
|
|
1891
1964
|
_renderSkillGrid(global = false) {
|
|
1892
1965
|
let skills = this._orgSkills;
|
|
@@ -1900,7 +1973,10 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
1900
1973
|
<div class="skill-browse__grid">
|
|
1901
1974
|
${skills.map((skill) => html `
|
|
1902
1975
|
<div
|
|
1903
|
-
class
|
|
1976
|
+
class=${classMap({
|
|
1977
|
+
'skill-card': true,
|
|
1978
|
+
'skill-card--unavailable': skill.canRun === false || (!!skill.global && !skill.enabled),
|
|
1979
|
+
})}
|
|
1904
1980
|
role="button"
|
|
1905
1981
|
tabindex="0"
|
|
1906
1982
|
@click=${() => this._handleSkillSelect(skill)}
|
|
@@ -1910,6 +1986,9 @@ let KRChatbot = class KRChatbot extends LitElement {
|
|
|
1910
1986
|
${skill.description ? html `
|
|
1911
1987
|
<span class="skill-card__desc">${skill.description}</span>
|
|
1912
1988
|
` : nothing}
|
|
1989
|
+
${!global && skill.global ? html `
|
|
1990
|
+
<span class="skill-card__badge">Global</span>
|
|
1991
|
+
` : nothing}
|
|
1913
1992
|
${global ? html `
|
|
1914
1993
|
<div class="skill-card__footer">
|
|
1915
1994
|
<span class="skill-card__price">Free</span>
|
|
@@ -3779,6 +3858,30 @@ KRChatbot.styles = css `
|
|
|
3779
3858
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
3780
3859
|
}
|
|
3781
3860
|
|
|
3861
|
+
/* A Kodaris-tab card the user can't invoke — not in their roles, or not installed
|
|
3862
|
+
here yet. Clicking it does nothing, so it drops the pointer cursor and the hover
|
|
3863
|
+
highlight. The Install button inside keeps its own pointer cursor. */
|
|
3864
|
+
.skill-card--unavailable {
|
|
3865
|
+
cursor: default;
|
|
3866
|
+
}
|
|
3867
|
+
|
|
3868
|
+
.skill-card--unavailable:hover {
|
|
3869
|
+
border-color: #e5e7eb;
|
|
3870
|
+
box-shadow: none;
|
|
3871
|
+
}
|
|
3872
|
+
|
|
3873
|
+
/* Marks a globally-published skill listed on the Your Org tab — only happens on
|
|
3874
|
+
kodaris.com, which has no Kodaris tab for its own published skills. */
|
|
3875
|
+
.skill-card__badge {
|
|
3876
|
+
align-self: flex-start;
|
|
3877
|
+
padding: 2px 8px;
|
|
3878
|
+
border-radius: 10px;
|
|
3879
|
+
background: #f3f4f6;
|
|
3880
|
+
font-size: 11px;
|
|
3881
|
+
font-weight: 600;
|
|
3882
|
+
color: #000000;
|
|
3883
|
+
}
|
|
3884
|
+
|
|
3782
3885
|
/* Footer row on global skill cards: install button on the left, price on the
|
|
3783
3886
|
right. margin-top:auto pins it to the bottom so cards in a row align their
|
|
3784
3887
|
footers regardless of description length. Negative horizontal margins
|