Compare commits
7 Commits
dev
...
feat/encry
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce9c8fe1cf | ||
|
|
38bdfd51ba | ||
|
|
cf62729cd0 | ||
|
|
583a9bb7af | ||
|
|
c63604ac55 | ||
|
|
22a7547e6c | ||
|
|
5363022634 |
@ -51,6 +51,7 @@
|
|||||||
"@types/uuid": "10.0.0",
|
"@types/uuid": "10.0.0",
|
||||||
"@uiw/react-textarea-code-editor": "3.1.1",
|
"@uiw/react-textarea-code-editor": "3.1.1",
|
||||||
"class-variance-authority": "0.7.1",
|
"class-variance-authority": "0.7.1",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"culori": "4.0.1",
|
"culori": "4.0.1",
|
||||||
"emoji-picker-react": "4.12.2",
|
"emoji-picker-react": "4.12.2",
|
||||||
"framer-motion": "12.23.12",
|
"framer-motion": "12.23.12",
|
||||||
@ -97,6 +98,7 @@
|
|||||||
"@testing-library/jest-dom": "6.8.0",
|
"@testing-library/jest-dom": "6.8.0",
|
||||||
"@testing-library/react": "16.3.0",
|
"@testing-library/react": "16.3.0",
|
||||||
"@testing-library/user-event": "14.6.1",
|
"@testing-library/user-event": "14.6.1",
|
||||||
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/culori": "2.1.1",
|
"@types/culori": "2.1.1",
|
||||||
"@types/istanbul-lib-report": "3.0.3",
|
"@types/istanbul-lib-report": "3.0.3",
|
||||||
"@types/istanbul-reports": "3.0.4",
|
"@types/istanbul-reports": "3.0.4",
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import CryptoJS from 'crypto-js'
|
||||||
import {
|
import {
|
||||||
ContentType,
|
ContentType,
|
||||||
ChatCompletionRole,
|
ChatCompletionRole,
|
||||||
@ -168,9 +169,31 @@ export const sendCompletion = async (
|
|||||||
if (!Object.keys(models).some((key) => key === providerName))
|
if (!Object.keys(models).some((key) => key === providerName))
|
||||||
providerName = 'openai-compatible'
|
providerName = 'openai-compatible'
|
||||||
|
|
||||||
|
// Decrypt API key if it exists and is encrypted
|
||||||
|
const secretKey = await getServiceHub().core().getAppToken()
|
||||||
|
const decryptApiKey = (encryptedKey: string, key: string): string => {
|
||||||
|
try {
|
||||||
|
const bytes = CryptoJS.AES.decrypt(encryptedKey, key)
|
||||||
|
const decryptedKey = bytes.toString(CryptoJS.enc.Utf8)
|
||||||
|
if (!decryptedKey) {
|
||||||
|
throw new Error('Failed to decrypt API key: result is empty')
|
||||||
|
}
|
||||||
|
return decryptedKey
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to decrypt API key:', error)
|
||||||
|
throw new Error('Failed to decrypt API key')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!secretKey) {
|
||||||
|
throw new Error('Encryption key unavailable: cannot decrypt API key.')
|
||||||
|
}
|
||||||
|
if (!provider.api_key) {
|
||||||
|
throw new Error('API key is missing for the selected provider.');
|
||||||
|
}
|
||||||
|
const apiKey = decryptApiKey(provider.api_key, secretKey);
|
||||||
|
|
||||||
const tokenJS = new TokenJS({
|
const tokenJS = new TokenJS({
|
||||||
apiKey:
|
apiKey,
|
||||||
provider.api_key ?? (await getServiceHub().core().getAppToken()) ?? '',
|
|
||||||
// TODO: Retrieve from extension settings
|
// TODO: Retrieve from extension settings
|
||||||
baseURL: provider.base_url,
|
baseURL: provider.base_url,
|
||||||
// Use Tauri's fetch to avoid CORS issues only for openai-compatible provider
|
// Use Tauri's fetch to avoid CORS issues only for openai-compatible provider
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import CryptoJS from 'crypto-js'
|
||||||
import { Card, CardItem } from '@/containers/Card'
|
import { Card, CardItem } from '@/containers/Card'
|
||||||
import HeaderPage from '@/containers/HeaderPage'
|
import HeaderPage from '@/containers/HeaderPage'
|
||||||
import SettingsMenu from '@/containers/SettingsMenu'
|
import SettingsMenu from '@/containers/SettingsMenu'
|
||||||
import { useModelProvider } from '@/hooks/useModelProvider'
|
import { useModelProvider } from '@/hooks/useModelProvider'
|
||||||
import { cn, getProviderTitle, getModelDisplayName } from '@/lib/utils'
|
import { getServiceHub } from '@/hooks/useServiceHub'
|
||||||
|
import { cn, getProviderTitle } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
createFileRoute,
|
createFileRoute,
|
||||||
Link,
|
Link,
|
||||||
@ -497,7 +499,7 @@ function ProviderDetail() {
|
|||||||
'third-step-setup-remote-provider',
|
'third-step-setup-remote-provider',
|
||||||
setting.key === 'device' && 'hidden'
|
setting.key === 'device' && 'hidden'
|
||||||
)}
|
)}
|
||||||
onChange={(newValue) => {
|
onChange={async (newValue) => {
|
||||||
if (provider) {
|
if (provider) {
|
||||||
const newSettings = [...provider.settings]
|
const newSettings = [...provider.settings]
|
||||||
// Handle different value types by forcing the type
|
// Handle different value types by forcing the type
|
||||||
@ -520,7 +522,14 @@ function ProviderDetail() {
|
|||||||
settingKey === 'api-key' &&
|
settingKey === 'api-key' &&
|
||||||
typeof newValue === 'string'
|
typeof newValue === 'string'
|
||||||
) {
|
) {
|
||||||
updateObj.api_key = newValue
|
const secretKey = await getServiceHub()
|
||||||
|
.core()
|
||||||
|
.getAppToken()
|
||||||
|
if (secretKey)
|
||||||
|
updateObj.api_key = CryptoJS.AES.encrypt(
|
||||||
|
newValue,
|
||||||
|
secretKey
|
||||||
|
).toString()
|
||||||
} else if (
|
} else if (
|
||||||
settingKey === 'base-url' &&
|
settingKey === 'base-url' &&
|
||||||
typeof newValue === 'string'
|
typeof newValue === 'string'
|
||||||
@ -536,7 +545,7 @@ function ProviderDetail() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (deviceSettingIndex !== -1) {
|
if (deviceSettingIndex !== -1) {
|
||||||
(
|
;(
|
||||||
newSettings[deviceSettingIndex]
|
newSettings[deviceSettingIndex]
|
||||||
.controller_props as {
|
.controller_props as {
|
||||||
value: string
|
value: string
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user