@smart-cloud/ai-kit-ui 1.4.11 → 1.4.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smart-cloud/ai-kit-ui",
3
- "version": "1.4.11",
3
+ "version": "1.4.12",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -19,6 +19,7 @@ import {
19
19
  import {
20
20
  AiKitDocSearchIcon,
21
21
  CapabilityDecision,
22
+ type ContextKind,
22
23
  dispatchBackend,
23
24
  resolveBackend,
24
25
  sendSearchMessage,
@@ -51,8 +52,75 @@ I18n.putVocabularies(translations);
51
52
 
52
53
  type Props = DocSearchProps & AiKitShellInjectedProps;
53
54
 
55
+ type MetadataOptions = {
56
+ allowedCategories: Record<string, string[]>;
57
+ allowedTags: string[];
58
+ };
59
+
60
+ const metadataOptionsCache = new Map<string, MetadataOptions>();
61
+ const metadataOptionsRequestCache = new Map<string, Promise<MetadataOptions>>();
62
+
54
63
  const USE_AUDIO = false; // Set to true to enable audio recording feature (requires backend support for audio input)
55
64
 
65
+ async function loadMetadataOptionsFromBackend(
66
+ context: ContextKind,
67
+ ): Promise<MetadataOptions> {
68
+ const cached = metadataOptionsCache.get(context);
69
+ if (cached) {
70
+ return cached;
71
+ }
72
+
73
+ const inFlight = metadataOptionsRequestCache.get(context);
74
+ if (inFlight) {
75
+ return inFlight;
76
+ }
77
+
78
+ const request = (async () => {
79
+ const backend = await resolveBackend();
80
+
81
+ if (!backend.available) {
82
+ throw new Error("Backend not available for metadata options");
83
+ }
84
+
85
+ const decision: CapabilityDecision = {
86
+ feature: "prompt",
87
+ source: "backend",
88
+ mode: "backend-only",
89
+ onDeviceAvailable: false,
90
+ backendAvailable: backend.available,
91
+ backendTransport: backend.transport,
92
+ backendApiName: backend.apiName,
93
+ backendBaseUrl: backend.baseUrl,
94
+ reason: backend.reason ?? "",
95
+ };
96
+
97
+ const data = (await dispatchBackend(
98
+ decision,
99
+ context,
100
+ "/kb/metadata-options",
101
+ "GET",
102
+ null,
103
+ {},
104
+ )) as MetadataOptions;
105
+
106
+ const normalized: MetadataOptions = {
107
+ allowedCategories: data.allowedCategories || {},
108
+ allowedTags: data.allowedTags || [],
109
+ };
110
+
111
+ metadataOptionsCache.set(context, normalized);
112
+ return normalized;
113
+ })();
114
+
115
+ metadataOptionsRequestCache.set(context, request);
116
+
117
+ try {
118
+ return await request;
119
+ } finally {
120
+ metadataOptionsRequestCache.delete(context);
121
+ }
122
+ }
123
+
56
124
  function groupChunksByDoc(result: SearchResult | null) {
57
125
  const docs = result?.citations?.docs ?? [];
58
126
  const chunks = result?.citations?.chunks ?? [];
@@ -157,10 +225,8 @@ const DocSearchBase: FC<Props> = (props) => {
157
225
  );
158
226
  const [selectedTags, setSelectedTags] = useState<string[]>([]);
159
227
  const [tagSearchValue, setTagSearchValue] = useState<string>("");
160
- const [metadataOptions, setMetadataOptions] = useState<{
161
- allowedCategories: Record<string, string[]>;
162
- allowedTags: string[];
163
- } | null>(null);
228
+ const [metadataOptions, setMetadataOptions] =
229
+ useState<MetadataOptions | null>(null);
164
230
  const [loadingMetadata, setLoadingMetadata] = useState(false);
165
231
  const animationFrameRef = useRef<number | null>(null);
166
232
 
@@ -351,6 +417,8 @@ const DocSearchBase: FC<Props> = (props) => {
351
417
  useEffect(() => {
352
418
  if (!enableUserFilters) return;
353
419
 
420
+ if (showOpenButton && !featureOpen) return;
421
+
354
422
  // Use provided options if available
355
423
  if (availableCategories || availableTags) {
356
424
  setMetadataOptions({
@@ -362,43 +430,14 @@ const DocSearchBase: FC<Props> = (props) => {
362
430
 
363
431
  // Otherwise fetch from backend
364
432
  const loadMetadata = async () => {
433
+ const effectiveContext: ContextKind =
434
+ context === "admin" ? "admin" : "frontend";
435
+
365
436
  setLoadingMetadata(true);
366
437
  try {
367
- const backend = await resolveBackend();
368
-
369
- if (!backend.available) {
370
- console.error("Backend not available for metadata options");
371
- return;
372
- }
438
+ const data = await loadMetadataOptionsFromBackend(effectiveContext);
373
439
 
374
- const decision: CapabilityDecision = {
375
- feature: "prompt",
376
- source: "backend",
377
- mode: "backend-only",
378
- onDeviceAvailable: false,
379
- backendAvailable: backend.available,
380
- backendTransport: backend.transport,
381
- backendApiName: backend.apiName,
382
- backendBaseUrl: backend.baseUrl,
383
- reason: backend.reason ?? "",
384
- };
385
-
386
- const data = (await dispatchBackend(
387
- decision,
388
- context ?? "frontend",
389
- "/kb/metadata-options",
390
- "GET",
391
- null,
392
- {},
393
- )) as {
394
- allowedCategories: Record<string, string[]>;
395
- allowedTags: string[];
396
- };
397
-
398
- setMetadataOptions({
399
- allowedCategories: data.allowedCategories || {},
400
- allowedTags: data.allowedTags || [],
401
- });
440
+ setMetadataOptions(data);
402
441
  } catch (error) {
403
442
  console.error("Failed to load metadata options:", error);
404
443
  } finally {
@@ -407,7 +446,14 @@ const DocSearchBase: FC<Props> = (props) => {
407
446
  };
408
447
 
409
448
  void loadMetadata();
410
- }, [enableUserFilters, availableCategories, availableTags, context]);
449
+ }, [
450
+ enableUserFilters,
451
+ availableCategories,
452
+ availableTags,
453
+ context,
454
+ featureOpen,
455
+ showOpenButton,
456
+ ]);
411
457
 
412
458
  const onSearch = useCallback(async () => {
413
459
  let q: string | undefined;