@serhii.olishevskyi/docs 1.2.13 → 1.2.15

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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  UserPopoverComponent,
3
3
  UserPopoverComponent_default
4
- } from "./chunk-EW4DX6YG.mjs";
4
+ } from "./chunk-4NEOJ5KZ.mjs";
5
5
  export {
6
6
  UserPopoverComponent,
7
7
  UserPopoverComponent_default as default
@@ -1,5 +1,5 @@
1
1
  // src/UI/components/data.display/UserPopoverComponent.tsx
2
- import { useEffect as useEffect9, useState as useState13 } from "react";
2
+ import { useEffect as useEffect10, useState as useState14 } from "react";
3
3
  import {
4
4
  Popover,
5
5
  Box as Box4,
@@ -1070,7 +1070,7 @@ var useToast = () => {
1070
1070
  };
1071
1071
 
1072
1072
  // src/context/ConfirmationProvider.tsx
1073
- import { createContext as createContext10, useContext as useContext10, useState as useState9, useCallback as useCallback4 } from "react";
1073
+ import { createContext as createContext10, useContext as useContext10, useState as useState10, useCallback as useCallback5 } from "react";
1074
1074
  import {
1075
1075
  Button as Button2,
1076
1076
  Dialog as Dialog2,
@@ -1088,14 +1088,14 @@ import {
1088
1088
  } from "@mui/icons-material";
1089
1089
 
1090
1090
  // src/i18n/TranslateText.tsx
1091
- import { useState as useState8, useRef as useRef2, useEffect as useEffect6 } from "react";
1091
+ import { useState as useState9, useRef as useRef2, useEffect as useEffect7 } from "react";
1092
1092
  import { useTranslation as useTranslation2 } from "react-i18next";
1093
1093
  import { Box as Box2, Popper, Paper as Paper2, MenuList, MenuItem, ListItemIcon, ListItemText } from "@mui/material";
1094
1094
  import TranslateIcon2 from "@mui/icons-material/Translate";
1095
1095
  import LaunchIcon from "@mui/icons-material/Launch";
1096
1096
 
1097
1097
  // src/i18n/TranslationDialog.tsx
1098
- import { useEffect as useEffect5, useState as useState7 } from "react";
1098
+ import { useEffect as useEffect6, useState as useState8 } from "react";
1099
1099
  import {
1100
1100
  Dialog,
1101
1101
  DialogTitle,
@@ -1244,24 +1244,66 @@ ${params.contextHint ? `Context Hint: "${params.contextHint}"` : ""}`;
1244
1244
  };
1245
1245
 
1246
1246
  // src/context/AIProvider.tsx
1247
- import { createContext as createContext9, useContext as useContext9, useMemo as useMemo5 } from "react";
1247
+ import { createContext as createContext9, useContext as useContext9, useEffect as useEffect5, useMemo as useMemo5, useState as useState7, useCallback as useCallback4 } from "react";
1248
1248
  import { GoogleGenAI } from "@google/genai";
1249
1249
  import { jsx as jsx9 } from "react/jsx-runtime";
1250
1250
  var AIContext = createContext9(null);
1251
- var AIProvider = ({
1252
- children,
1253
- config = {},
1254
- apiKey: legacyApiKey,
1255
- provider: legacyProvider
1256
- }) => {
1257
- const activeProvider = config.provider || legacyProvider || "gemini";
1251
+ var AIProvider = ({ children, config: initialConfig = {} }) => {
1252
+ const supabase = useSupabase();
1253
+ const [dbConfig, setDbConfig] = useState7({});
1254
+ const loadSettingsFromDb = useCallback4(async () => {
1255
+ try {
1256
+ const { data } = await supabase.from("app_settings").select("key, value").in("key", [
1257
+ "ai_provider",
1258
+ "gemini_api_key",
1259
+ "gemini_model",
1260
+ "openai_api_key",
1261
+ "openai_model"
1262
+ ]);
1263
+ if (!data) return;
1264
+ const parseVal = (val) => {
1265
+ if (typeof val === "string") return val;
1266
+ return JSON.stringify(val).replace(/^"|"$/g, "");
1267
+ };
1268
+ let provider;
1269
+ let geminiApiKey;
1270
+ let geminiModel;
1271
+ let openaiApiKey;
1272
+ let openaiModel;
1273
+ data.forEach((item) => {
1274
+ const val = parseVal(item.value);
1275
+ if (item.key === "ai_provider" && (val === "gemini" || val === "openai")) {
1276
+ provider = val;
1277
+ }
1278
+ if (item.key === "gemini_api_key") geminiApiKey = val;
1279
+ if (item.key === "gemini_model") geminiModel = val;
1280
+ if (item.key === "openai_api_key") openaiApiKey = val;
1281
+ if (item.key === "openai_model") openaiModel = val;
1282
+ });
1283
+ setDbConfig({
1284
+ provider,
1285
+ gemini: { apiKey: geminiApiKey, modelName: geminiModel },
1286
+ openai: { apiKey: openaiApiKey, modelName: openaiModel }
1287
+ });
1288
+ } catch (err) {
1289
+ console.warn("[AIProvider]: Failed to load AI settings from app_settings", err);
1290
+ }
1291
+ }, [supabase]);
1292
+ useEffect5(() => {
1293
+ loadSettingsFromDb();
1294
+ }, [loadSettingsFromDb]);
1295
+ const activeProvider = dbConfig.provider || initialConfig.provider || "gemini";
1258
1296
  const geminiConfig = {
1259
- apiKey: config.gemini?.apiKey || (activeProvider === "gemini" ? legacyApiKey : void 0),
1260
- modelName: config.gemini?.modelName || "gemini-2.5-flash"
1297
+ apiKey: dbConfig.gemini?.apiKey || initialConfig.gemini?.apiKey || "",
1298
+ //import.meta.env.VITE_GEMINI_API_KEY,
1299
+ modelName: dbConfig.gemini?.modelName || initialConfig.gemini?.modelName || "" || //import.meta.env.VITE_GEMINI_MODEL ||
1300
+ "gemini-2.5-flash"
1261
1301
  };
1262
1302
  const openaiConfig = {
1263
- apiKey: config.openai?.apiKey || (activeProvider === "openai" ? legacyApiKey : void 0),
1264
- modelName: config.openai?.modelName || "gpt-4o-mini"
1303
+ apiKey: dbConfig.openai?.apiKey || initialConfig.openai?.apiKey || "",
1304
+ //import.meta.env.VITE_OPENAI_API_KEY,
1305
+ modelName: dbConfig.openai?.modelName || initialConfig.openai?.modelName || "" || //import.meta.env.VITE_OPENAI_MODEL ||
1306
+ "gpt-4o-mini"
1265
1307
  };
1266
1308
  const contextValue = useMemo5(() => {
1267
1309
  return {
@@ -1271,6 +1313,7 @@ var AIProvider = ({
1271
1313
  gemini: geminiConfig,
1272
1314
  openai: openaiConfig
1273
1315
  },
1316
+ reloadConfig: loadSettingsFromDb,
1274
1317
  generate: async ({
1275
1318
  prompt,
1276
1319
  systemInstruction,
@@ -1291,7 +1334,6 @@ var AIProvider = ({
1291
1334
  const ai = new GoogleGenAI({ apiKey: key });
1292
1335
  const response = await ai.models.generateContent({
1293
1336
  model,
1294
- // Теперь гарантированно string
1295
1337
  contents: prompt,
1296
1338
  config: {
1297
1339
  systemInstruction,
@@ -1312,7 +1354,7 @@ var AIProvider = ({
1312
1354
  }
1313
1355
  if (targetProvider === "openai") {
1314
1356
  const key = openaiConfig.apiKey;
1315
- const model = overrideModelName || openaiConfig.modelName;
1357
+ const model = overrideModelName || openaiConfig.modelName || "gpt-4o-mini";
1316
1358
  if (!key) {
1317
1359
  console.warn("[AIProvider]: API Key \u0434\u043B\u044F OpenAI \u043D\u0435 \u0437\u0430\u0434\u0430\u043D.");
1318
1360
  return null;
@@ -1359,7 +1401,8 @@ var AIProvider = ({
1359
1401
  geminiConfig.apiKey,
1360
1402
  geminiConfig.modelName,
1361
1403
  openaiConfig.apiKey,
1362
- openaiConfig.modelName
1404
+ openaiConfig.modelName,
1405
+ loadSettingsFromDb
1363
1406
  ]);
1364
1407
  return /* @__PURE__ */ jsx9(AIContext.Provider, { value: contextValue, children });
1365
1408
  };
@@ -1382,16 +1425,21 @@ var TranslationDialog = ({
1382
1425
  }) => {
1383
1426
  const supabase = useSupabase();
1384
1427
  const { generate, activeProvider: defaultProvider } = useAI();
1385
- const [languages, setLanguages] = useState7([]);
1386
- const [values, setValues] = useState7({});
1387
- const [contextHint, setContextHint] = useState7("");
1388
- const [selectedProvider, setSelectedProvider] = useState7("auto");
1389
- const [loading, setLoading] = useState7(false);
1390
- const [saving, setSaving] = useState7(false);
1391
- const [translatingCode, setTranslatingCode] = useState7(null);
1392
- const [isTranslatingAll, setIsTranslatingAll] = useState7(false);
1393
- const [error, setError] = useState7(null);
1394
- useEffect5(() => {
1428
+ const [languages, setLanguages] = useState8([]);
1429
+ const [values, setValues] = useState8({});
1430
+ const [contextHint, setContextHint] = useState8("");
1431
+ const [selectedProvider, setSelectedProvider] = useState8("auto");
1432
+ const [loading, setLoading] = useState8(false);
1433
+ const [saving, setSaving] = useState8(false);
1434
+ const [translatingCode, setTranslatingCode] = useState8(null);
1435
+ const [isTranslatingAll, setIsTranslatingAll] = useState8(false);
1436
+ const [error, setError] = useState8(null);
1437
+ useEffect6(() => {
1438
+ if (open) {
1439
+ setSelectedProvider(defaultProvider || "auto");
1440
+ }
1441
+ }, [open, defaultProvider]);
1442
+ useEffect6(() => {
1395
1443
  if (!open) return;
1396
1444
  const fetchData = async () => {
1397
1445
  setLoading(true);
@@ -1421,7 +1469,7 @@ var TranslationDialog = ({
1421
1469
  }
1422
1470
  };
1423
1471
  fetchData();
1424
- }, [open, translationKey, namespace]);
1472
+ }, [open, translationKey, namespace, supabase]);
1425
1473
  const effectiveProvider = selectedProvider === "auto" ? void 0 : selectedProvider;
1426
1474
  const handleAutoTranslate = async (e, targetLang) => {
1427
1475
  e.preventDefault();
@@ -1559,13 +1607,15 @@ var TranslationDialog = ({
1559
1607
  onChange: (_, val) => val && setSelectedProvider(val),
1560
1608
  disabled: isBusy,
1561
1609
  children: [
1562
- /* @__PURE__ */ jsxs3(ToggleButton, { value: "auto", sx: { px: 1.5, py: 0.2, fontSize: "0.75rem" }, children: [
1563
- "Auto (",
1564
- defaultProvider,
1565
- ")"
1610
+ /* @__PURE__ */ jsx10(ToggleButton, { value: "auto", sx: { px: 1.5, py: 0.2, fontSize: "0.75rem" }, children: "Auto" }),
1611
+ /* @__PURE__ */ jsxs3(ToggleButton, { value: "gemini", sx: { px: 1.5, py: 0.2, fontSize: "0.75rem" }, children: [
1612
+ "Gemini ",
1613
+ defaultProvider === "gemini" && "(Default)"
1566
1614
  ] }),
1567
- /* @__PURE__ */ jsx10(ToggleButton, { value: "gemini", sx: { px: 1.5, py: 0.2, fontSize: "0.75rem" }, children: "Gemini" }),
1568
- /* @__PURE__ */ jsx10(ToggleButton, { value: "openai", sx: { px: 1.5, py: 0.2, fontSize: "0.75rem" }, children: "OpenAI" })
1615
+ /* @__PURE__ */ jsxs3(ToggleButton, { value: "openai", sx: { px: 1.5, py: 0.2, fontSize: "0.75rem" }, children: [
1616
+ "OpenAI ",
1617
+ defaultProvider === "openai" && "(Default)"
1618
+ ] })
1569
1619
  ]
1570
1620
  }
1571
1621
  )
@@ -1651,11 +1701,11 @@ var TranslateText = ({
1651
1701
  const { t, i18n: i18n2 } = useTranslation2(namespace);
1652
1702
  const { isTranslationMode, canEdit } = useTranslationEdit();
1653
1703
  const supabase = useSupabase();
1654
- const [anchorEl, setAnchorEl] = useState8(null);
1655
- const [isDialogOpen, setIsDialogOpen] = useState8(false);
1704
+ const [anchorEl, setAnchorEl] = useState9(null);
1705
+ const [isDialogOpen, setIsDialogOpen] = useState9(false);
1656
1706
  const timeoutRef = useRef2(null);
1657
1707
  const translatedValue = t(children, values);
1658
- useEffect6(() => {
1708
+ useEffect7(() => {
1659
1709
  return () => {
1660
1710
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
1661
1711
  };
@@ -1821,10 +1871,10 @@ var SEVERITY_ICONS = {
1821
1871
  success: /* @__PURE__ */ jsx12(SuccessIcon, { color: "success", sx: { fontSize: 40 } })
1822
1872
  };
1823
1873
  var ConfirmationProvider = ({ overrideNamespace, children }) => {
1824
- const [open, setOpen] = useState9(false);
1825
- const [options, setOptions] = useState9(null);
1826
- const [resolver, setResolver] = useState9(null);
1827
- const confirm = useCallback4((opts) => {
1874
+ const [open, setOpen] = useState10(false);
1875
+ const [options, setOptions] = useState10(null);
1876
+ const [resolver, setResolver] = useState10(null);
1877
+ const confirm = useCallback5((opts) => {
1828
1878
  setOptions(opts);
1829
1879
  setOpen(true);
1830
1880
  return new Promise((resolve) => {
@@ -1899,7 +1949,7 @@ var useConfirmation = () => {
1899
1949
  };
1900
1950
 
1901
1951
  // src/context/AppSettingsProvider.tsx
1902
- import { createContext as createContext11, useContext as useContext11, useEffect as useEffect7, useState as useState10, useCallback as useCallback5 } from "react";
1952
+ import { createContext as createContext11, useContext as useContext11, useEffect as useEffect8, useState as useState11, useCallback as useCallback6 } from "react";
1903
1953
  import { jsx as jsx13 } from "react/jsx-runtime";
1904
1954
  var DEFAULT_SETTINGS = {
1905
1955
  max_group_members: 100
@@ -1907,10 +1957,10 @@ var DEFAULT_SETTINGS = {
1907
1957
  var AppSettingsContext = createContext11(void 0);
1908
1958
  var AppSettingsProvider = ({ children }) => {
1909
1959
  const supabase = useSupabase();
1910
- const [settings, setSettings] = useState10(DEFAULT_SETTINGS);
1911
- const [loading, setLoading] = useState10(true);
1912
- const [error, setError] = useState10(null);
1913
- const fetchSettings = useCallback5(async () => {
1960
+ const [settings, setSettings] = useState11(DEFAULT_SETTINGS);
1961
+ const [loading, setLoading] = useState11(true);
1962
+ const [error, setError] = useState11(null);
1963
+ const fetchSettings = useCallback6(async () => {
1914
1964
  try {
1915
1965
  setLoading(true);
1916
1966
  setError(null);
@@ -1930,10 +1980,10 @@ var AppSettingsProvider = ({ children }) => {
1930
1980
  setLoading(false);
1931
1981
  }
1932
1982
  }, []);
1933
- useEffect7(() => {
1983
+ useEffect8(() => {
1934
1984
  fetchSettings();
1935
1985
  }, [fetchSettings]);
1936
- const getSetting = useCallback5((key, defaultValue) => {
1986
+ const getSetting = useCallback6((key, defaultValue) => {
1937
1987
  if (key in settings && settings[key] !== null && settings[key] !== void 0) {
1938
1988
  return settings[key];
1939
1989
  }
@@ -1962,7 +2012,7 @@ var useAppSettings = () => {
1962
2012
  };
1963
2013
 
1964
2014
  // src/context/UserSettingsProvider.tsx
1965
- import { createContext as createContext12, useContext as useContext12, useEffect as useEffect8, useState as useState11, useCallback as useCallback6 } from "react";
2015
+ import { createContext as createContext12, useContext as useContext12, useEffect as useEffect9, useState as useState12, useCallback as useCallback7 } from "react";
1966
2016
 
1967
2017
  // src/types/user.types.ts
1968
2018
  var defaultUserSettings = {
@@ -1979,14 +2029,14 @@ var UserSettingsProvider = ({ children }) => {
1979
2029
  const supabase = useSupabase();
1980
2030
  const { user, isAuthenticated, loading: isAuthLoading } = useAuth();
1981
2031
  const userId = user?.id;
1982
- const [settings, setSettings] = useState11({
2032
+ const [settings, setSettings] = useState12({
1983
2033
  id: "",
1984
2034
  ...defaultUserSettings
1985
2035
  });
1986
- const [loading, setLoading] = useState11(true);
1987
- const [error, setError] = useState11(null);
1988
- const [activeChatUserId, setActiveChatUserId] = useState11(null);
1989
- const fetchSettings = useCallback6(async () => {
2036
+ const [loading, setLoading] = useState12(true);
2037
+ const [error, setError] = useState12(null);
2038
+ const [activeChatUserId, setActiveChatUserId] = useState12(null);
2039
+ const fetchSettings = useCallback7(async () => {
1990
2040
  if (isAuthLoading) return;
1991
2041
  if (!isAuthenticated || !userId) {
1992
2042
  setSettings({ id: "", ...defaultUserSettings });
@@ -2039,10 +2089,10 @@ var UserSettingsProvider = ({ children }) => {
2039
2089
  setLoading(false);
2040
2090
  }
2041
2091
  }, [isAuthenticated, isAuthLoading, userId]);
2042
- useEffect8(() => {
2092
+ useEffect9(() => {
2043
2093
  fetchSettings();
2044
2094
  }, [fetchSettings]);
2045
- const toggleSidebar = useCallback6(
2095
+ const toggleSidebar = useCallback7(
2046
2096
  async (open) => {
2047
2097
  const isExplicitBoolean = typeof open === "boolean";
2048
2098
  const nextState = isExplicitBoolean ? open : !settings.sidebar_open;
@@ -2058,7 +2108,7 @@ var UserSettingsProvider = ({ children }) => {
2058
2108
  },
2059
2109
  [settings.sidebar_open, userId]
2060
2110
  );
2061
- const toggleChat = useCallback6(
2111
+ const toggleChat = useCallback7(
2062
2112
  async (open) => {
2063
2113
  const isExplicitBoolean = typeof open === "boolean";
2064
2114
  const nextState = isExplicitBoolean ? open : !settings.chat_open;
@@ -2074,7 +2124,7 @@ var UserSettingsProvider = ({ children }) => {
2074
2124
  },
2075
2125
  [settings.chat_open, userId]
2076
2126
  );
2077
- const openChatWithUser = useCallback6(
2127
+ const openChatWithUser = useCallback7(
2078
2128
  async (targetUserId) => {
2079
2129
  setActiveChatUserId(targetUserId);
2080
2130
  if (!settings.chat_open) {
@@ -2083,7 +2133,7 @@ var UserSettingsProvider = ({ children }) => {
2083
2133
  },
2084
2134
  [settings.chat_open, toggleChat]
2085
2135
  );
2086
- const setLanguage = useCallback6(
2136
+ const setLanguage = useCallback7(
2087
2137
  async (newLanguage) => {
2088
2138
  const previousLanguage = settings.language;
2089
2139
  setSettings((prev) => ({ ...prev, language: newLanguage }));
@@ -2098,7 +2148,7 @@ var UserSettingsProvider = ({ children }) => {
2098
2148
  },
2099
2149
  [settings.language, userId]
2100
2150
  );
2101
- const setThemeMode = useCallback6(
2151
+ const setThemeMode = useCallback7(
2102
2152
  async (newMode) => {
2103
2153
  const previousMode = settings.theme_mode;
2104
2154
  setSettings((prev) => ({ ...prev, theme_mode: newMode }));
@@ -2273,7 +2323,7 @@ var UserRoleChipComponent = ({ overrideNamespace, role }) => {
2273
2323
  };
2274
2324
 
2275
2325
  // src/UI/components/buttons/CopyClipboardButtonComponent.tsx
2276
- import { useState as useState12 } from "react";
2326
+ import { useState as useState13 } from "react";
2277
2327
  import { IconButton as IconButton3 } from "@mui/material";
2278
2328
  import CheckIcon from "@mui/icons-material/Check";
2279
2329
  import CopyIcon from "@mui/icons-material/ContentCopy";
@@ -2325,7 +2375,7 @@ var CopyClipboardButtonComponent = ({
2325
2375
  sx,
2326
2376
  ...iconButtonProps
2327
2377
  }) => {
2328
- const [copied, setCopied] = useState12(false);
2378
+ const [copied, setCopied] = useState13(false);
2329
2379
  const handleCopy = async (e) => {
2330
2380
  e.stopPropagation();
2331
2381
  if (!textToCopy) return;
@@ -2358,9 +2408,9 @@ var CopyClipboardButtonComponent = ({
2358
2408
  // src/UI/components/data.display/UserPopoverComponent.tsx
2359
2409
  import { Fragment as Fragment2, jsx as jsx20, jsxs as jsxs6 } from "react/jsx-runtime";
2360
2410
  var useUserStatus = (supabase, userId, open) => {
2361
- const [lastSeenAt, setLastSeenAt] = useState13(null);
2362
- const [loading, setLoading] = useState13(true);
2363
- useEffect9(() => {
2411
+ const [lastSeenAt, setLastSeenAt] = useState14(null);
2412
+ const [loading, setLoading] = useState14(true);
2413
+ useEffect10(() => {
2364
2414
  if (!userId || !open) {
2365
2415
  setLastSeenAt(null);
2366
2416
  setLoading(false);
@@ -2409,13 +2459,13 @@ var UserPopoverComponent = ({
2409
2459
  const { activeCompanyId, membership: currentMembership } = useAuth();
2410
2460
  const { openChatWithUser } = useUserSettings();
2411
2461
  const { formatDate, formatRelativeTime } = useLocalization();
2412
- const [profileData, setProfileData] = useState13(null);
2413
- const [membershipData, setMembershipData] = useState13(null);
2414
- const [avatarUrl, setAvatarUrl] = useState13(null);
2415
- const [coverUrl, setCoverUrl] = useState13(null);
2416
- const [loading, setLoading] = useState13(true);
2462
+ const [profileData, setProfileData] = useState14(null);
2463
+ const [membershipData, setMembershipData] = useState14(null);
2464
+ const [avatarUrl, setAvatarUrl] = useState14(null);
2465
+ const [coverUrl, setCoverUrl] = useState14(null);
2466
+ const [loading, setLoading] = useState14(true);
2417
2467
  const { lastSeenAt, isOnline } = useUserStatus(supabase, userId, open);
2418
- useEffect9(() => {
2468
+ useEffect10(() => {
2419
2469
  if (!open || !userId || !activeCompanyId) return;
2420
2470
  let isMounted = true;
2421
2471
  setLoading(true);
package/dist/index.d.mts CHANGED
@@ -413,11 +413,8 @@ interface AIServiceConfig {
413
413
  modelName?: string;
414
414
  }
415
415
  interface AIConfig {
416
- /** Активный провайдер по умолчанию */
417
416
  provider?: AIProviderType;
418
- /** Конфигурация для Gemini */
419
417
  gemini?: AIServiceConfig;
420
- /** Конфигурация для OpenAI */
421
418
  openai?: AIServiceConfig;
422
419
  }
423
420
  interface AIGenerateOptions {
@@ -425,24 +422,19 @@ interface AIGenerateOptions {
425
422
  systemInstruction?: string;
426
423
  jsonMode?: boolean;
427
424
  temperature?: number;
428
- /** Возможность переопределить провайдера для конкретного запроса */
429
425
  provider?: AIProviderType;
430
- /** Возможность переопределить модель для конкретного запроса */
431
426
  modelName?: string;
432
427
  }
433
428
  interface AIContextType {
434
429
  activeProvider: AIProviderType;
435
430
  config: AIConfig;
436
- /** Универсальный метод генерации (текст или JSON) */
437
431
  generate: <T = string>(options: AIGenerateOptions) => Promise<T | null>;
432
+ /** Метод для перезагрузки настроек из базы данных */
433
+ reloadConfig: () => Promise<void>;
438
434
  }
439
435
  interface AIProviderProps {
440
436
  children: React__default.ReactNode;
441
437
  config?: AIConfig;
442
- /** Устаревшая прямая передача ключа (для обратной совместимости) */
443
- apiKey?: string;
444
- /** Устаревший выбор провайдера (для обратной совместимости) */
445
- provider?: AIProviderType;
446
438
  }
447
439
  declare const AIProvider: React__default.FC<AIProviderProps>;
448
440
  declare const useAI: () => AIContextType;
package/dist/index.d.ts CHANGED
@@ -413,11 +413,8 @@ interface AIServiceConfig {
413
413
  modelName?: string;
414
414
  }
415
415
  interface AIConfig {
416
- /** Активный провайдер по умолчанию */
417
416
  provider?: AIProviderType;
418
- /** Конфигурация для Gemini */
419
417
  gemini?: AIServiceConfig;
420
- /** Конфигурация для OpenAI */
421
418
  openai?: AIServiceConfig;
422
419
  }
423
420
  interface AIGenerateOptions {
@@ -425,24 +422,19 @@ interface AIGenerateOptions {
425
422
  systemInstruction?: string;
426
423
  jsonMode?: boolean;
427
424
  temperature?: number;
428
- /** Возможность переопределить провайдера для конкретного запроса */
429
425
  provider?: AIProviderType;
430
- /** Возможность переопределить модель для конкретного запроса */
431
426
  modelName?: string;
432
427
  }
433
428
  interface AIContextType {
434
429
  activeProvider: AIProviderType;
435
430
  config: AIConfig;
436
- /** Универсальный метод генерации (текст или JSON) */
437
431
  generate: <T = string>(options: AIGenerateOptions) => Promise<T | null>;
432
+ /** Метод для перезагрузки настроек из базы данных */
433
+ reloadConfig: () => Promise<void>;
438
434
  }
439
435
  interface AIProviderProps {
440
436
  children: React__default.ReactNode;
441
437
  config?: AIConfig;
442
- /** Устаревшая прямая передача ключа (для обратной совместимости) */
443
- apiKey?: string;
444
- /** Устаревший выбор провайдера (для обратной совместимости) */
445
- provider?: AIProviderType;
446
438
  }
447
439
  declare const AIProvider: React__default.FC<AIProviderProps>;
448
440
  declare const useAI: () => AIContextType;
package/dist/index.js CHANGED
@@ -827,22 +827,65 @@ var init_AIProvider = __esm({
827
827
  "use strict";
828
828
  import_react4 = require("react");
829
829
  import_genai = require("@google/genai");
830
+ init_SupabaseProvider();
830
831
  import_jsx_runtime4 = require("react/jsx-runtime");
831
832
  AIContext = (0, import_react4.createContext)(null);
832
- AIProvider = ({
833
- children,
834
- config = {},
835
- apiKey: legacyApiKey,
836
- provider: legacyProvider
837
- }) => {
838
- const activeProvider = config.provider || legacyProvider || "gemini";
833
+ AIProvider = ({ children, config: initialConfig = {} }) => {
834
+ const supabase = useSupabase();
835
+ const [dbConfig, setDbConfig] = (0, import_react4.useState)({});
836
+ const loadSettingsFromDb = (0, import_react4.useCallback)(async () => {
837
+ try {
838
+ const { data } = await supabase.from("app_settings").select("key, value").in("key", [
839
+ "ai_provider",
840
+ "gemini_api_key",
841
+ "gemini_model",
842
+ "openai_api_key",
843
+ "openai_model"
844
+ ]);
845
+ if (!data) return;
846
+ const parseVal = (val) => {
847
+ if (typeof val === "string") return val;
848
+ return JSON.stringify(val).replace(/^"|"$/g, "");
849
+ };
850
+ let provider;
851
+ let geminiApiKey;
852
+ let geminiModel;
853
+ let openaiApiKey;
854
+ let openaiModel;
855
+ data.forEach((item) => {
856
+ const val = parseVal(item.value);
857
+ if (item.key === "ai_provider" && (val === "gemini" || val === "openai")) {
858
+ provider = val;
859
+ }
860
+ if (item.key === "gemini_api_key") geminiApiKey = val;
861
+ if (item.key === "gemini_model") geminiModel = val;
862
+ if (item.key === "openai_api_key") openaiApiKey = val;
863
+ if (item.key === "openai_model") openaiModel = val;
864
+ });
865
+ setDbConfig({
866
+ provider,
867
+ gemini: { apiKey: geminiApiKey, modelName: geminiModel },
868
+ openai: { apiKey: openaiApiKey, modelName: openaiModel }
869
+ });
870
+ } catch (err) {
871
+ console.warn("[AIProvider]: Failed to load AI settings from app_settings", err);
872
+ }
873
+ }, [supabase]);
874
+ (0, import_react4.useEffect)(() => {
875
+ loadSettingsFromDb();
876
+ }, [loadSettingsFromDb]);
877
+ const activeProvider = dbConfig.provider || initialConfig.provider || "gemini";
839
878
  const geminiConfig = {
840
- apiKey: config.gemini?.apiKey || (activeProvider === "gemini" ? legacyApiKey : void 0),
841
- modelName: config.gemini?.modelName || "gemini-2.5-flash"
879
+ apiKey: dbConfig.gemini?.apiKey || initialConfig.gemini?.apiKey || "",
880
+ //import.meta.env.VITE_GEMINI_API_KEY,
881
+ modelName: dbConfig.gemini?.modelName || initialConfig.gemini?.modelName || "" || //import.meta.env.VITE_GEMINI_MODEL ||
882
+ "gemini-2.5-flash"
842
883
  };
843
884
  const openaiConfig = {
844
- apiKey: config.openai?.apiKey || (activeProvider === "openai" ? legacyApiKey : void 0),
845
- modelName: config.openai?.modelName || "gpt-4o-mini"
885
+ apiKey: dbConfig.openai?.apiKey || initialConfig.openai?.apiKey || "",
886
+ //import.meta.env.VITE_OPENAI_API_KEY,
887
+ modelName: dbConfig.openai?.modelName || initialConfig.openai?.modelName || "" || //import.meta.env.VITE_OPENAI_MODEL ||
888
+ "gpt-4o-mini"
846
889
  };
847
890
  const contextValue = (0, import_react4.useMemo)(() => {
848
891
  return {
@@ -852,6 +895,7 @@ var init_AIProvider = __esm({
852
895
  gemini: geminiConfig,
853
896
  openai: openaiConfig
854
897
  },
898
+ reloadConfig: loadSettingsFromDb,
855
899
  generate: async ({
856
900
  prompt,
857
901
  systemInstruction,
@@ -872,7 +916,6 @@ var init_AIProvider = __esm({
872
916
  const ai = new import_genai.GoogleGenAI({ apiKey: key });
873
917
  const response = await ai.models.generateContent({
874
918
  model,
875
- // Теперь гарантированно string
876
919
  contents: prompt,
877
920
  config: {
878
921
  systemInstruction,
@@ -893,7 +936,7 @@ var init_AIProvider = __esm({
893
936
  }
894
937
  if (targetProvider === "openai") {
895
938
  const key = openaiConfig.apiKey;
896
- const model = overrideModelName || openaiConfig.modelName;
939
+ const model = overrideModelName || openaiConfig.modelName || "gpt-4o-mini";
897
940
  if (!key) {
898
941
  console.warn("[AIProvider]: API Key \u0434\u043B\u044F OpenAI \u043D\u0435 \u0437\u0430\u0434\u0430\u043D.");
899
942
  return null;
@@ -940,7 +983,8 @@ var init_AIProvider = __esm({
940
983
  geminiConfig.apiKey,
941
984
  geminiConfig.modelName,
942
985
  openaiConfig.apiKey,
943
- openaiConfig.modelName
986
+ openaiConfig.modelName,
987
+ loadSettingsFromDb
944
988
  ]);
945
989
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AIContext.Provider, { value: contextValue, children });
946
990
  };
@@ -987,6 +1031,11 @@ var init_TranslationDialog = __esm({
987
1031
  const [translatingCode, setTranslatingCode] = (0, import_react5.useState)(null);
988
1032
  const [isTranslatingAll, setIsTranslatingAll] = (0, import_react5.useState)(false);
989
1033
  const [error, setError] = (0, import_react5.useState)(null);
1034
+ (0, import_react5.useEffect)(() => {
1035
+ if (open) {
1036
+ setSelectedProvider(defaultProvider || "auto");
1037
+ }
1038
+ }, [open, defaultProvider]);
990
1039
  (0, import_react5.useEffect)(() => {
991
1040
  if (!open) return;
992
1041
  const fetchData = async () => {
@@ -1017,7 +1066,7 @@ var init_TranslationDialog = __esm({
1017
1066
  }
1018
1067
  };
1019
1068
  fetchData();
1020
- }, [open, translationKey, namespace]);
1069
+ }, [open, translationKey, namespace, supabase]);
1021
1070
  const effectiveProvider = selectedProvider === "auto" ? void 0 : selectedProvider;
1022
1071
  const handleAutoTranslate = async (e, targetLang) => {
1023
1072
  e.preventDefault();
@@ -1155,13 +1204,15 @@ var init_TranslationDialog = __esm({
1155
1204
  onChange: (_, val) => val && setSelectedProvider(val),
1156
1205
  disabled: isBusy,
1157
1206
  children: [
1158
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_material.ToggleButton, { value: "auto", sx: { px: 1.5, py: 0.2, fontSize: "0.75rem" }, children: [
1159
- "Auto (",
1160
- defaultProvider,
1161
- ")"
1207
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_material.ToggleButton, { value: "auto", sx: { px: 1.5, py: 0.2, fontSize: "0.75rem" }, children: "Auto" }),
1208
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_material.ToggleButton, { value: "gemini", sx: { px: 1.5, py: 0.2, fontSize: "0.75rem" }, children: [
1209
+ "Gemini ",
1210
+ defaultProvider === "gemini" && "(Default)"
1162
1211
  ] }),
1163
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_material.ToggleButton, { value: "gemini", sx: { px: 1.5, py: 0.2, fontSize: "0.75rem" }, children: "Gemini" }),
1164
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_material.ToggleButton, { value: "openai", sx: { px: 1.5, py: 0.2, fontSize: "0.75rem" }, children: "OpenAI" })
1212
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_material.ToggleButton, { value: "openai", sx: { px: 1.5, py: 0.2, fontSize: "0.75rem" }, children: [
1213
+ "OpenAI ",
1214
+ defaultProvider === "openai" && "(Default)"
1215
+ ] })
1165
1216
  ]
1166
1217
  }
1167
1218
  )
package/dist/index.mjs CHANGED
@@ -43,7 +43,7 @@ import {
43
43
  useTranslationEdit,
44
44
  useTranslationNamespace,
45
45
  useUserSettings
46
- } from "./chunk-EW4DX6YG.mjs";
46
+ } from "./chunk-4NEOJ5KZ.mjs";
47
47
 
48
48
  // src/UI/components/inputs/TextFieldComponent.tsx
49
49
  import { useState } from "react";
@@ -741,7 +741,7 @@ var EmailInputComponent = ({
741
741
  import { useState as useState5, useEffect as useEffect2, lazy, Suspense } from "react";
742
742
  import { Avatar, Tooltip as Tooltip3, Typography as Typography2 } from "@mui/material";
743
743
  import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
744
- var LazyUserPopover = lazy(() => import("./UserPopoverComponent-LI5272PW.mjs"));
744
+ var LazyUserPopover = lazy(() => import("./UserPopoverComponent-RAEPOSIE.mjs"));
745
745
  var getInitials = (name) => {
746
746
  if (!name) return "?";
747
747
  const parts = name.trim().split(" ");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serhii.olishevskyi/docs",
3
- "version": "1.2.13",
3
+ "version": "1.2.15",
4
4
  "description": "DOCS.UA react packages",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",