@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 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
- * Field names mirror the backend AI skill document (the `_source` of an
142
- * `/aiskills/search` hit) so loaded skills pass through without remapping.
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 this skill is installed (turned on) on this instance. Only set for
153
- * shared Kodaris global skills (from `/aiskills/global/search`), where the
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, and the
162
- * files attached to this message (each paired with its `aiAnalyze` flag). Must
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
- * Search the Kodaris AI skills index and store the results in `_orgSkills` — the
498
- * browse dialog's "Your Org" tab. Mirrors the backend's own skill search (BM25
499
- * over name^3/description^2/instructions, active-only). An empty query uses
500
- * match_all — multi_match with an empty string matches nothing, so the "show
501
- * everything" case needs it.
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
- * Follows the kr-combo-box `_fetch` pattern: a request-id guard drops responses
504
- * that arrive out of order. `/aiskills/search` returns a raw OpenSearch response,
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 full Kodaris
524
- * catalog, installed or not, each row carrying `enabled` = installed here.
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/globalSkillCatalog` rather than the `/aiskills/global/search`
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
- * Both return the same catalog in `KRChatbotSkill` shape
529
- * (`data: [{ code, name, description, enabled }]`), so no `_source` lifting is needed.
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
- /** The "Browse all skills" dialog — a searchable grid of Org / Kodaris cards. */
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 Enabled toggle that installs/removes the
615
- * skill on this instance.
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
  /**
@@ -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
- * Search the Kodaris AI skills index and store the results in `_orgSkills` — the
847
- * browse dialog's "Your Org" tab. Mirrors the backend's own skill search (BM25
848
- * over name^3/description^2/instructions, active-only). An empty query uses
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
- * Follows the kr-combo-box `_fetch` pattern: a request-id guard drops responses
853
- * that arrive out of order. `/aiskills/search` returns a raw OpenSearch response,
854
- * so we lift each hit's `_source` (already in KRChatbotSkill shape) out.
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/opensearch/aiskills/search',
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?.hits?.hits || []).map((hit) => hit._source);
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 full Kodaris
964
- * catalog, installed or not, each row carrying `enabled` = installed here.
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/globalSkillCatalog` rather than the `/aiskills/global/search`
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
- * Both return the same catalog in `KRChatbotSkill` shape
969
- * (`data: [{ code, name, description, enabled }]`), so no `_source` lifting is needed.
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/globalSkillCatalog',
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
- // A global skill must be installed before it can be chosen — inserting /code
1128
- // for one not enabled on this instance would just fail. `enabled` is only set
1129
- // on global skills (false = not installed); org skills leave it undefined and
1130
- // are always selectable. So an uninstalled global card click does nothing.
1131
- if (skill.enabled === false) {
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._searchGlobalSkills('');
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
- this._searchGlobalSkills(this._skillBrowseQuery);
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
- /** The "Browse all skills" dialog — a searchable grid of Org / Kodaris cards. */
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
- <kr-tab id="kodaris" label="Kodaris">
1878
- ${this._renderSkillGrid(true)}
1879
- </kr-tab>
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 Enabled toggle that installs/removes the
1889
- * skill on this instance.
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="skill-card"
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