Compare commits
17 Commits
copilot/ad
...
copilot/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
038da0de63 | ||
|
|
8924f954dd | ||
|
|
06b108c40d | ||
|
|
b1e63470a5 | ||
|
|
ea9e7fccda | ||
|
|
97ab200657 | ||
|
|
7a49042d7f | ||
|
|
33983c26f4 | ||
|
|
abd5d3b96f | ||
|
|
49bd298d37 | ||
|
|
714a28ac29 | ||
|
|
0cf81c04c8 | ||
|
|
4186e9c990 | ||
|
|
d8f68a6056 | ||
|
|
11bf50e722 | ||
|
|
32a84311aa | ||
|
|
6eaa2b2461 |
@@ -21,6 +21,8 @@ files:
|
||||
- "**/*"
|
||||
- "!**/{.vscode,.yarn,.yarn-lock,.github,.cursorrules,.prettierrc}"
|
||||
- "!electron.vite.config.{js,ts,mjs,cjs}}"
|
||||
- "!.*"
|
||||
- "!components.json"
|
||||
- "!**/{.eslintignore,.eslintrc.js,.eslintrc.json,.eslintcache,root.eslint.config.js,eslint.config.js,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,eslint.config.mjs,dev-app-update.yml,CHANGELOG.md,README.md,biome.jsonc}"
|
||||
- "!**/{.env,.env.*,.npmrc,pnpm-lock.yaml}"
|
||||
- "!**/{tsconfig.json,tsconfig.tsbuildinfo,tsconfig.node.json,tsconfig.web.json}"
|
||||
|
||||
@@ -113,9 +113,9 @@
|
||||
"@ant-design/v5-patch-for-react-19": "^1.0.3",
|
||||
"@anthropic-ai/sdk": "^0.41.0",
|
||||
"@anthropic-ai/vertex-sdk": "patch:@anthropic-ai/vertex-sdk@npm%3A0.11.4#~/.yarn/patches/@anthropic-ai-vertex-sdk-npm-0.11.4-c19cb41edb.patch",
|
||||
"@aws-sdk/client-bedrock": "^3.840.0",
|
||||
"@aws-sdk/client-bedrock-runtime": "^3.840.0",
|
||||
"@aws-sdk/client-s3": "^3.840.0",
|
||||
"@aws-sdk/client-bedrock": "^3.910.0",
|
||||
"@aws-sdk/client-bedrock-runtime": "^3.910.0",
|
||||
"@aws-sdk/client-s3": "^3.910.0",
|
||||
"@biomejs/biome": "2.2.4",
|
||||
"@cherrystudio/ai-core": "workspace:^1.0.0-alpha.18",
|
||||
"@cherrystudio/embedjs": "^0.1.31",
|
||||
|
||||
@@ -115,9 +115,6 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
|
||||
const appUpdater = new AppUpdater()
|
||||
const notificationService = new NotificationService()
|
||||
|
||||
// Initialize Python service with main window
|
||||
pythonService.setMainWindow(mainWindow)
|
||||
|
||||
const checkMainWindow = () => {
|
||||
if (!mainWindow || mainWindow.isDestroyed()) {
|
||||
throw new Error('Main window does not exist or has been destroyed')
|
||||
|
||||
@@ -33,6 +33,7 @@ class BackupManager {
|
||||
accessKeyId: string
|
||||
secretAccessKey: string
|
||||
root?: string
|
||||
bypassProxy?: boolean
|
||||
} | null = null
|
||||
|
||||
private cachedWebdavConnectionConfig: {
|
||||
@@ -120,7 +121,8 @@ class BackupManager {
|
||||
cachedConfig.bucket === config.bucket &&
|
||||
cachedConfig.accessKeyId === config.accessKeyId &&
|
||||
cachedConfig.secretAccessKey === config.secretAccessKey &&
|
||||
cachedConfig.root === config.root
|
||||
cachedConfig.root === config.root &&
|
||||
cachedConfig.bypassProxy === config.bypassProxy
|
||||
)
|
||||
}
|
||||
|
||||
@@ -147,6 +149,11 @@ class BackupManager {
|
||||
const configChanged = !this.isS3ConfigEqual(this.cachedS3ConnectionConfig, config)
|
||||
|
||||
if (configChanged || !this.s3Storage) {
|
||||
// Destroy old instance to clean up bypass rules
|
||||
if (this.s3Storage) {
|
||||
this.s3Storage.destroy()
|
||||
}
|
||||
|
||||
this.s3Storage = new S3Storage(config)
|
||||
// 只缓存连接相关的配置字段
|
||||
this.cachedS3ConnectionConfig = {
|
||||
@@ -155,7 +162,8 @@ class BackupManager {
|
||||
bucket: config.bucket,
|
||||
accessKeyId: config.accessKeyId,
|
||||
secretAccessKey: config.secretAccessKey,
|
||||
root: config.root
|
||||
root: config.root,
|
||||
bypassProxy: config.bypassProxy
|
||||
}
|
||||
logger.debug('[BackupManager] Created new S3Storage instance')
|
||||
} else {
|
||||
|
||||
@@ -12,6 +12,8 @@ import { Dispatcher, EnvHttpProxyAgent, getGlobalDispatcher, setGlobalDispatcher
|
||||
|
||||
const logger = loggerService.withContext('ProxyManager')
|
||||
let byPassRules: string[] = []
|
||||
// Dynamic bypass rules that can be added/removed at runtime (e.g., for S3 endpoints)
|
||||
const dynamicBypassRules: string[] = []
|
||||
|
||||
type HostnameMatchType = 'exact' | 'wildcardSubdomain' | 'generalWildcard'
|
||||
|
||||
@@ -222,7 +224,10 @@ export const updateByPassRules = (rules: string[]): void => {
|
||||
byPassRules = rules
|
||||
parsedByPassRules = []
|
||||
|
||||
for (const rule of rules) {
|
||||
// Combine static bypass rules with dynamic ones
|
||||
const allRules = [...rules, ...dynamicBypassRules]
|
||||
|
||||
for (const rule of allRules) {
|
||||
const parsedRule = parseProxyBypassRule(rule)
|
||||
if (parsedRule) {
|
||||
parsedByPassRules.push(parsedRule)
|
||||
@@ -232,6 +237,33 @@ export const updateByPassRules = (rules: string[]): void => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a dynamic bypass rule at runtime (e.g., for S3 endpoints)
|
||||
* @param rule - The bypass rule to add (e.g., hostname or domain pattern)
|
||||
*/
|
||||
export const addDynamicBypassRule = (rule: string): void => {
|
||||
if (!dynamicBypassRules.includes(rule)) {
|
||||
dynamicBypassRules.push(rule)
|
||||
// Re-parse all rules with the new dynamic rule
|
||||
updateByPassRules(byPassRules)
|
||||
logger.info(`Added dynamic bypass rule: ${rule}`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a dynamic bypass rule
|
||||
* @param rule - The bypass rule to remove
|
||||
*/
|
||||
export const removeDynamicBypassRule = (rule: string): void => {
|
||||
const index = dynamicBypassRules.indexOf(rule)
|
||||
if (index !== -1) {
|
||||
dynamicBypassRules.splice(index, 1)
|
||||
// Re-parse all rules without the removed dynamic rule
|
||||
updateByPassRules(byPassRules)
|
||||
logger.info(`Removed dynamic bypass rule: ${rule}`)
|
||||
}
|
||||
}
|
||||
|
||||
export const isByPass = (url: string) => {
|
||||
if (parsedByPassRules.length === 0) {
|
||||
return false
|
||||
@@ -586,6 +618,22 @@ export class ProxyManager {
|
||||
// set proxy for electron
|
||||
app.setProxy(config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a dynamic bypass rule for a specific endpoint
|
||||
* @param rule - The bypass rule to add (e.g., hostname or domain pattern)
|
||||
*/
|
||||
addDynamicBypassRule(rule: string): void {
|
||||
addDynamicBypassRule(rule)
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a dynamic bypass rule
|
||||
* @param rule - The bypass rule to remove
|
||||
*/
|
||||
removeDynamicBypassRule(rule: string): void {
|
||||
removeDynamicBypassRule(rule)
|
||||
}
|
||||
}
|
||||
|
||||
export const proxyManager = new ProxyManager()
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
|
||||
import type { BrowserWindow } from 'electron'
|
||||
import { ipcMain } from 'electron'
|
||||
|
||||
import { windowService } from './WindowService'
|
||||
|
||||
interface PythonExecutionRequest {
|
||||
id: string
|
||||
script: string
|
||||
@@ -21,7 +22,6 @@ interface PythonExecutionResponse {
|
||||
*/
|
||||
export class PythonService {
|
||||
private static instance: PythonService | null = null
|
||||
private mainWindow: BrowserWindow | null = null
|
||||
private pendingRequests = new Map<string, { resolve: (value: string) => void; reject: (error: Error) => void }>()
|
||||
|
||||
private constructor() {
|
||||
@@ -51,10 +51,6 @@ export class PythonService {
|
||||
})
|
||||
}
|
||||
|
||||
public setMainWindow(mainWindow: BrowserWindow) {
|
||||
this.mainWindow = mainWindow
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute Python code by sending request to renderer PyodideService
|
||||
*/
|
||||
@@ -63,8 +59,8 @@ export class PythonService {
|
||||
context: Record<string, any> = {},
|
||||
timeout: number = 60000
|
||||
): Promise<string> {
|
||||
if (!this.mainWindow) {
|
||||
throw new Error('Main window not set in PythonService')
|
||||
if (!windowService.getMainWindow()) {
|
||||
throw new Error('Main window not found')
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -95,7 +91,7 @@ export class PythonService {
|
||||
|
||||
// Send request to renderer
|
||||
const request: PythonExecutionRequest = { id: requestId, script, context, timeout }
|
||||
this.mainWindow?.webContents.send('python-execution-request', request)
|
||||
windowService.getMainWindow()?.webContents.send('python-execution-request', request)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import type { S3Config } from '@types'
|
||||
import * as net from 'net'
|
||||
import { Readable } from 'stream'
|
||||
|
||||
import { proxyManager } from './ProxyManager'
|
||||
|
||||
const logger = loggerService.withContext('S3Storage')
|
||||
|
||||
/**
|
||||
@@ -35,9 +37,12 @@ export default class S3Storage {
|
||||
private client: S3Client
|
||||
private bucket: string
|
||||
private root: string
|
||||
private endpoint: string
|
||||
|
||||
constructor(config: S3Config) {
|
||||
const { endpoint, region, accessKeyId, secretAccessKey, bucket, root } = config
|
||||
const { endpoint, region, accessKeyId, secretAccessKey, bucket, root, bypassProxy = true } = config
|
||||
|
||||
this.endpoint = endpoint
|
||||
|
||||
const usePathStyle = (() => {
|
||||
if (!endpoint) return false
|
||||
@@ -57,6 +62,22 @@ export default class S3Storage {
|
||||
}
|
||||
})()
|
||||
|
||||
// Use ProxyManager's dynamic bypass rules instead of custom dispatcher
|
||||
// When bypassProxy is true (default), add the S3 endpoint to proxy bypass rules
|
||||
// to avoid proxy interference with large file uploads that can cause incomplete transfers
|
||||
// Error example: "Io error: put_object write size < data.size(), w_size=15728640, data.size=16396159"
|
||||
if (bypassProxy && endpoint) {
|
||||
try {
|
||||
const url = new URL(endpoint)
|
||||
const hostname = url.hostname
|
||||
// Add the hostname to dynamic bypass rules
|
||||
proxyManager.addDynamicBypassRule(hostname)
|
||||
logger.debug(`[S3Storage] Added S3 endpoint to bypass rules: ${hostname}`)
|
||||
} catch (e) {
|
||||
logger.warn(`[S3Storage] Failed to add endpoint to bypass rules: ${endpoint}`, e as Error)
|
||||
}
|
||||
}
|
||||
|
||||
this.client = new S3Client({
|
||||
region,
|
||||
endpoint: endpoint || undefined,
|
||||
@@ -77,6 +98,22 @@ export default class S3Storage {
|
||||
this.checkConnection = this.checkConnection.bind(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up resources and remove bypass rules
|
||||
*/
|
||||
destroy(): void {
|
||||
if (this.endpoint) {
|
||||
try {
|
||||
const url = new URL(this.endpoint)
|
||||
const hostname = url.hostname
|
||||
proxyManager.removeDynamicBypassRule(hostname)
|
||||
logger.debug(`[S3Storage] Removed S3 endpoint from bypass rules: ${hostname}`)
|
||||
} catch (e) {
|
||||
logger.warn(`[S3Storage] Failed to remove endpoint from bypass rules: ${this.endpoint}`, e as Error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部辅助方法,用来拼接带 root 的对象 key
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { BedrockClient, ListFoundationModelsCommand, ListInferenceProfilesCommand } from '@aws-sdk/client-bedrock'
|
||||
import {
|
||||
BedrockRuntimeClient,
|
||||
type BedrockRuntimeClientConfig,
|
||||
ConverseCommand,
|
||||
InvokeModelCommand,
|
||||
InvokeModelWithResponseStreamCommand
|
||||
@@ -11,6 +12,8 @@ import { DEFAULT_MAX_TOKENS } from '@renderer/config/constant'
|
||||
import { findTokenLimit, isReasoningModel } from '@renderer/config/models'
|
||||
import {
|
||||
getAwsBedrockAccessKeyId,
|
||||
getAwsBedrockApiKey,
|
||||
getAwsBedrockAuthType,
|
||||
getAwsBedrockRegion,
|
||||
getAwsBedrockSecretAccessKey
|
||||
} from '@renderer/hooks/useAwsBedrock'
|
||||
@@ -75,32 +78,48 @@ export class AwsBedrockAPIClient extends BaseApiClient<
|
||||
}
|
||||
|
||||
const region = getAwsBedrockRegion()
|
||||
const accessKeyId = getAwsBedrockAccessKeyId()
|
||||
const secretAccessKey = getAwsBedrockSecretAccessKey()
|
||||
const authType = getAwsBedrockAuthType()
|
||||
|
||||
if (!region) {
|
||||
throw new Error('AWS region is required. Please configure AWS-Region in extra headers.')
|
||||
throw new Error('AWS region is required. Please configure AWS region in settings.')
|
||||
}
|
||||
|
||||
if (!accessKeyId || !secretAccessKey) {
|
||||
throw new Error('AWS credentials are required. Please configure AWS-Access-Key-ID and AWS-Secret-Access-Key.')
|
||||
// Build client configuration based on auth type
|
||||
let clientConfig: BedrockRuntimeClientConfig
|
||||
|
||||
if (authType === 'iam') {
|
||||
// IAM credentials authentication
|
||||
const accessKeyId = getAwsBedrockAccessKeyId()
|
||||
const secretAccessKey = getAwsBedrockSecretAccessKey()
|
||||
|
||||
if (!accessKeyId || !secretAccessKey) {
|
||||
throw new Error('AWS credentials are required. Please configure Access Key ID and Secret Access Key.')
|
||||
}
|
||||
|
||||
clientConfig = {
|
||||
region,
|
||||
credentials: {
|
||||
accessKeyId,
|
||||
secretAccessKey
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// API Key authentication
|
||||
const awsBedrockApiKey = getAwsBedrockApiKey()
|
||||
|
||||
if (!awsBedrockApiKey) {
|
||||
throw new Error('AWS Bedrock API Key is required. Please configure API Key in settings.')
|
||||
}
|
||||
|
||||
clientConfig = {
|
||||
region,
|
||||
token: { token: awsBedrockApiKey },
|
||||
authSchemePreference: ['httpBearerAuth']
|
||||
}
|
||||
}
|
||||
|
||||
const client = new BedrockRuntimeClient({
|
||||
region,
|
||||
credentials: {
|
||||
accessKeyId,
|
||||
secretAccessKey
|
||||
}
|
||||
})
|
||||
|
||||
const bedrockClient = new BedrockClient({
|
||||
region,
|
||||
credentials: {
|
||||
accessKeyId,
|
||||
secretAccessKey
|
||||
}
|
||||
})
|
||||
const client = new BedrockRuntimeClient(clientConfig)
|
||||
const bedrockClient = new BedrockClient(clientConfig)
|
||||
|
||||
this.sdkInstance = { client, bedrockClient, region }
|
||||
return this.sdkInstance
|
||||
|
||||
@@ -85,6 +85,19 @@ export function supportsLargeFileUpload(model: Model): boolean {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查模型是否支持TopP
|
||||
*/
|
||||
export function supportsTopP(model: Model): boolean {
|
||||
const provider = getProviderByModel(model)
|
||||
|
||||
if (provider?.type === 'anthropic' || model?.endpoint_type === 'anthropic') {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取提供商特定的文件大小限制
|
||||
*/
|
||||
|
||||
@@ -34,6 +34,7 @@ import { setupToolsConfig } from '../utils/mcp'
|
||||
import { buildProviderOptions } from '../utils/options'
|
||||
import { getAnthropicThinkingBudget } from '../utils/reasoning'
|
||||
import { buildProviderBuiltinWebSearchConfig } from '../utils/websearch'
|
||||
import { supportsTopP } from './modelCapabilities'
|
||||
import { getTemperature, getTopP } from './modelParameters'
|
||||
|
||||
const logger = loggerService.withContext('parameterBuilder')
|
||||
@@ -176,20 +177,27 @@ export async function buildStreamTextParams(
|
||||
messages: sdkMessages,
|
||||
maxOutputTokens: maxTokens,
|
||||
temperature: getTemperature(assistant, model),
|
||||
topP: getTopP(assistant, model),
|
||||
abortSignal: options.requestOptions?.signal,
|
||||
headers: options.requestOptions?.headers,
|
||||
providerOptions,
|
||||
stopWhen: stepCountIs(20),
|
||||
maxRetries: 0
|
||||
}
|
||||
|
||||
if (supportsTopP(model)) {
|
||||
params.topP = getTopP(assistant, model)
|
||||
}
|
||||
|
||||
if (tools) {
|
||||
params.tools = tools
|
||||
}
|
||||
|
||||
if (assistant.prompt) {
|
||||
params.system = await replacePromptVariables(assistant.prompt, model.name)
|
||||
}
|
||||
|
||||
logger.debug('params', params)
|
||||
|
||||
return {
|
||||
params,
|
||||
modelId: model.id,
|
||||
|
||||
@@ -14,6 +14,8 @@ import {
|
||||
} from '@renderer/config/providers'
|
||||
import {
|
||||
getAwsBedrockAccessKeyId,
|
||||
getAwsBedrockApiKey,
|
||||
getAwsBedrockAuthType,
|
||||
getAwsBedrockRegion,
|
||||
getAwsBedrockSecretAccessKey
|
||||
} from '@renderer/hooks/useAwsBedrock'
|
||||
@@ -192,9 +194,15 @@ export function providerToAiSdkConfig(
|
||||
|
||||
// bedrock
|
||||
if (aiSdkProviderId === 'bedrock') {
|
||||
const authType = getAwsBedrockAuthType()
|
||||
extraOptions.region = getAwsBedrockRegion()
|
||||
extraOptions.accessKeyId = getAwsBedrockAccessKeyId()
|
||||
extraOptions.secretAccessKey = getAwsBedrockSecretAccessKey()
|
||||
|
||||
if (authType === 'apiKey') {
|
||||
extraOptions.apiKey = getAwsBedrockApiKey()
|
||||
} else {
|
||||
extraOptions.accessKeyId = getAwsBedrockAccessKeyId()
|
||||
extraOptions.secretAccessKey = getAwsBedrockSecretAccessKey()
|
||||
}
|
||||
}
|
||||
// google-vertex
|
||||
if (aiSdkProviderId === 'google-vertex' || aiSdkProviderId === 'google-vertex-anthropic') {
|
||||
|
||||
@@ -17,6 +17,7 @@ import { getAiSdkProviderId } from '../provider/factory'
|
||||
import { buildGeminiGenerateImageParams } from './image'
|
||||
import {
|
||||
getAnthropicReasoningParams,
|
||||
getBedrockReasoningParams,
|
||||
getCustomParameters,
|
||||
getGeminiReasoningParams,
|
||||
getOpenAIReasoningParams,
|
||||
@@ -127,6 +128,9 @@ export function buildProviderOptions(
|
||||
case 'google-vertex-anthropic':
|
||||
providerSpecificOptions = buildAnthropicProviderOptions(assistant, model, capabilities)
|
||||
break
|
||||
case 'bedrock':
|
||||
providerSpecificOptions = buildBedrockProviderOptions(assistant, model, capabilities)
|
||||
break
|
||||
default:
|
||||
// 对于其他 provider,使用通用的构建逻辑
|
||||
providerSpecificOptions = {
|
||||
@@ -266,6 +270,32 @@ function buildXAIProviderOptions(
|
||||
return providerOptions
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Bedrock providerOptions
|
||||
*/
|
||||
function buildBedrockProviderOptions(
|
||||
assistant: Assistant,
|
||||
model: Model,
|
||||
capabilities: {
|
||||
enableReasoning: boolean
|
||||
enableWebSearch: boolean
|
||||
enableGenerateImage: boolean
|
||||
}
|
||||
): Record<string, any> {
|
||||
const { enableReasoning } = capabilities
|
||||
let providerOptions: Record<string, any> = {}
|
||||
|
||||
if (enableReasoning) {
|
||||
const reasoningParams = getBedrockReasoningParams(assistant, model)
|
||||
providerOptions = {
|
||||
...providerOptions,
|
||||
...reasoningParams
|
||||
}
|
||||
}
|
||||
|
||||
return providerOptions
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建通用的 providerOptions(用于其他 provider)
|
||||
*/
|
||||
|
||||
@@ -485,6 +485,34 @@ export function getXAIReasoningParams(assistant: Assistant, model: Model): Recor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Bedrock reasoning parameters
|
||||
*/
|
||||
export function getBedrockReasoningParams(assistant: Assistant, model: Model): Record<string, any> {
|
||||
if (!isReasoningModel(model)) {
|
||||
return {}
|
||||
}
|
||||
|
||||
const reasoningEffort = assistant?.settings?.reasoning_effort
|
||||
|
||||
if (reasoningEffort === undefined) {
|
||||
return {}
|
||||
}
|
||||
|
||||
// Only apply thinking budget for Claude reasoning models
|
||||
if (!isSupportedThinkingTokenClaudeModel(model)) {
|
||||
return {}
|
||||
}
|
||||
|
||||
const budgetTokens = getAnthropicThinkingBudget(assistant, model)
|
||||
return {
|
||||
reasoningConfig: {
|
||||
type: 'enabled',
|
||||
budgetTokens: budgetTokens
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自定义参数
|
||||
* 从 assistant 设置中提取自定义参数
|
||||
|
||||
13
src/renderer/src/assets/images/providers/sophnet.svg
Normal file
13
src/renderer/src/assets/images/providers/sophnet.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="33" height="38" viewBox="0 0 33 38" fill="none">
|
||||
<g clip-path="url(#clip0_4321_9943)">
|
||||
<path d="M1.51221 6.59813C1.51221 4.09263 3.54331 2.06152 6.04881 2.06152H27.9757C30.4812 2.06152 32.5123 4.09263 32.5123 6.59813C32.5123 9.10362 30.4812 11.1347 27.9757 11.1347H6.04881C3.54331 11.1347 1.51221 9.10362 1.51221 6.59813Z" fill="#6200EE"/>
|
||||
<path d="M3.38905 3.56467C5.26076 1.89906 8.12831 2.06615 9.79391 3.93785L22.1493 17.8221C23.8149 19.6938 23.6478 22.5614 21.7761 24.227C19.9044 25.8926 17.0369 25.7255 15.3713 23.8538L3.01586 9.96953C1.35026 8.09782 1.51734 5.23027 3.38905 3.56467Z" fill="#6200EE"/>
|
||||
<path d="M1.51221 20.9643C1.51221 18.4588 3.54331 16.4277 6.04881 16.4277H18.9025C21.408 16.4277 23.4391 18.4588 23.4391 20.9643C23.4391 23.4698 21.408 25.5009 18.9025 25.5009H6.04881C3.54331 25.5009 1.51221 23.4698 1.51221 20.9643Z" fill="#6200EE"/>
|
||||
<path d="M10.5854 32.3052C10.5854 34.8107 8.55431 36.8418 6.04881 36.8418C3.54331 36.8418 1.51221 34.8107 1.51221 32.3052C1.51221 29.7997 3.54331 27.7686 6.04881 27.7686C8.55431 27.7686 10.5854 29.7997 10.5854 32.3052Z" fill="#BF7AFF"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_4321_9943">
|
||||
<rect width="32.5124" height="36.9029" fill="white" transform="translate(0 0.548828)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -64,6 +64,7 @@ export type QuickPanelListItem = {
|
||||
isSelected?: boolean
|
||||
isMenu?: boolean
|
||||
disabled?: boolean
|
||||
hidden?: boolean
|
||||
/**
|
||||
* 固定显示项:不参与过滤,始终出现在列表顶部。
|
||||
* 例如“清除”按钮可设置为 alwaysVisible,从而在有匹配项时始终可见;
|
||||
|
||||
@@ -143,7 +143,8 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
||||
prevSymbolRef.current = ctx.symbol
|
||||
|
||||
// 固定项置顶 + 过滤后的普通项
|
||||
return [...pinnedItems, ...filteredNormalItems]
|
||||
const pinnedFiltered = [...pinnedItems, ...filteredNormalItems]
|
||||
return pinnedFiltered.filter((item) => !item.hidden)
|
||||
}, [ctx.isVisible, ctx.symbol, ctx.list, searchText])
|
||||
|
||||
const canForwardAndBackward = useMemo(() => {
|
||||
|
||||
@@ -27,6 +27,7 @@ export const SYSTEM_MODELS: Record<SystemProviderId | 'defaultModel', Model[]> =
|
||||
],
|
||||
cherryin: [],
|
||||
vertexai: [],
|
||||
sophnet: [],
|
||||
'302ai': [
|
||||
{
|
||||
id: 'deepseek-chat',
|
||||
|
||||
@@ -46,6 +46,7 @@ import Ph8ProviderLogo from '@renderer/assets/images/providers/ph8.png'
|
||||
import PPIOProviderLogo from '@renderer/assets/images/providers/ppio.png'
|
||||
import QiniuProviderLogo from '@renderer/assets/images/providers/qiniu.webp'
|
||||
import SiliconFlowProviderLogo from '@renderer/assets/images/providers/silicon.png'
|
||||
import SophnetProviderLogo from '@renderer/assets/images/providers/sophnet.svg'
|
||||
import StepProviderLogo from '@renderer/assets/images/providers/step.png'
|
||||
import TencentCloudProviderLogo from '@renderer/assets/images/providers/tencent-cloud-ti.png'
|
||||
import TogetherProviderLogo from '@renderer/assets/images/providers/together.png'
|
||||
@@ -246,6 +247,16 @@ export const SYSTEM_PROVIDERS_CONFIG: Record<SystemProviderId, SystemProvider> =
|
||||
isSystem: true,
|
||||
enabled: false
|
||||
},
|
||||
sophnet: {
|
||||
id: 'sophnet',
|
||||
name: 'SophNet',
|
||||
type: 'openai',
|
||||
apiKey: '',
|
||||
apiHost: 'https://www.sophnet.com/api/open-apis/v1',
|
||||
models: [],
|
||||
isSystem: true,
|
||||
enabled: false
|
||||
},
|
||||
ppio: {
|
||||
id: 'ppio',
|
||||
name: 'PPIO',
|
||||
@@ -729,7 +740,8 @@ export const PROVIDER_LOGO_MAP: AtLeast<SystemProviderId, string> = {
|
||||
poe: 'poe', // use svg icon component
|
||||
aionly: AiOnlyProviderLogo,
|
||||
longcat: LongCatProviderLogo,
|
||||
huggingface: HuggingfaceProviderLogo
|
||||
huggingface: HuggingfaceProviderLogo,
|
||||
sophnet: SophnetProviderLogo
|
||||
} as const
|
||||
|
||||
export function getProviderLogo(providerId: string) {
|
||||
@@ -808,6 +820,17 @@ export const PROVIDER_URLS: Record<SystemProviderId, ProviderUrls> = {
|
||||
models: 'https://ai.burncloud.com/pricing'
|
||||
}
|
||||
},
|
||||
sophnet: {
|
||||
api: {
|
||||
url: 'https://www.sophnet.com/api/open-apis/v1'
|
||||
},
|
||||
websites: {
|
||||
official: 'https://sophnet.com',
|
||||
apiKey: 'https://sophnet.com/#/project/key',
|
||||
docs: 'https://sophnet.com/docs/component/introduce.html',
|
||||
models: 'https://sophnet.com/#/model/list'
|
||||
}
|
||||
},
|
||||
ppio: {
|
||||
api: {
|
||||
url: 'https://api.ppinfra.com/v3/openai'
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import store, { useAppSelector } from '@renderer/store'
|
||||
import { setAwsBedrockAccessKeyId, setAwsBedrockRegion, setAwsBedrockSecretAccessKey } from '@renderer/store/llm'
|
||||
import {
|
||||
setAwsBedrockAccessKeyId,
|
||||
setAwsBedrockApiKey,
|
||||
setAwsBedrockAuthType,
|
||||
setAwsBedrockRegion,
|
||||
setAwsBedrockSecretAccessKey
|
||||
} from '@renderer/store/llm'
|
||||
import type { AwsBedrockAuthType } from '@renderer/types'
|
||||
import { useDispatch } from 'react-redux'
|
||||
|
||||
export function useAwsBedrockSettings() {
|
||||
@@ -8,8 +15,10 @@ export function useAwsBedrockSettings() {
|
||||
|
||||
return {
|
||||
...settings,
|
||||
setAuthType: (authType: AwsBedrockAuthType) => dispatch(setAwsBedrockAuthType(authType)),
|
||||
setAccessKeyId: (accessKeyId: string) => dispatch(setAwsBedrockAccessKeyId(accessKeyId)),
|
||||
setSecretAccessKey: (secretAccessKey: string) => dispatch(setAwsBedrockSecretAccessKey(secretAccessKey)),
|
||||
setApiKey: (apiKey: string) => dispatch(setAwsBedrockApiKey(apiKey)),
|
||||
setRegion: (region: string) => dispatch(setAwsBedrockRegion(region))
|
||||
}
|
||||
}
|
||||
@@ -18,6 +27,10 @@ export function getAwsBedrockSettings() {
|
||||
return store.getState().llm.settings.awsBedrock
|
||||
}
|
||||
|
||||
export function getAwsBedrockAuthType() {
|
||||
return store.getState().llm.settings.awsBedrock.authType
|
||||
}
|
||||
|
||||
export function getAwsBedrockAccessKeyId() {
|
||||
return store.getState().llm.settings.awsBedrock.accessKeyId
|
||||
}
|
||||
@@ -26,6 +39,10 @@ export function getAwsBedrockSecretAccessKey() {
|
||||
return store.getState().llm.settings.awsBedrock.secretAccessKey
|
||||
}
|
||||
|
||||
export function getAwsBedrockApiKey() {
|
||||
return store.getState().llm.settings.awsBedrock.apiKey
|
||||
}
|
||||
|
||||
export function getAwsBedrockRegion() {
|
||||
return store.getState().llm.settings.awsBedrock.region
|
||||
}
|
||||
|
||||
@@ -85,7 +85,8 @@ const providerKeyMap = {
|
||||
poe: 'provider.poe',
|
||||
aionly: 'provider.aionly',
|
||||
longcat: 'provider.longcat',
|
||||
huggingface: 'provider.huggingface'
|
||||
huggingface: 'provider.huggingface',
|
||||
sophnet: 'provider.sophnet'
|
||||
} as const
|
||||
|
||||
/**
|
||||
@@ -238,7 +239,7 @@ const paintingsImageSizeOptionsKeyMap = {
|
||||
} as const
|
||||
|
||||
export const getPaintingsImageSizeOptionsLabel = (key: string): string => {
|
||||
return getLabel(paintingsImageSizeOptionsKeyMap, key)
|
||||
return paintingsImageSizeOptionsKeyMap[key] ? getLabel(paintingsImageSizeOptionsKeyMap, key) : key
|
||||
}
|
||||
|
||||
const paintingsQualityOptionsKeyMap = {
|
||||
|
||||
@@ -2482,6 +2482,7 @@
|
||||
"qiniu": "Qiniu AI",
|
||||
"qwenlm": "QwenLM",
|
||||
"silicon": "SiliconFlow",
|
||||
"sophnet": "SophNet",
|
||||
"stepfun": "StepFun",
|
||||
"tencent-cloud-ti": "Tencent Cloud TI",
|
||||
"together": "Together",
|
||||
@@ -3335,6 +3336,10 @@
|
||||
"label": "Bucket",
|
||||
"placeholder": "Bucket, e.g: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "When enabled, S3 requests bypass the application proxy to prevent data corruption during large file uploads. Recommended to keep enabled unless your S3 endpoint requires proxy access.",
|
||||
"label": "Bypass Proxy"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "API Endpoint",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4259,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "AWS Access Key ID",
|
||||
"access_key_id_help": "Your AWS Access Key ID for accessing AWS Bedrock services",
|
||||
"api_key": "Bedrock API Key",
|
||||
"api_key_help": "Your AWS Bedrock API Key for authentication",
|
||||
"auth_type": "Authentication Type",
|
||||
"auth_type_api_key": "Bedrock API Key",
|
||||
"auth_type_help": "Choose between IAM credentials or Bedrock API Key authentication",
|
||||
"auth_type_iam": "IAM Credentials",
|
||||
"description": "AWS Bedrock is Amazon's fully managed foundation model service that supports various advanced large language models",
|
||||
"region": "AWS Region",
|
||||
"region_help": "Your AWS service region, e.g., us-east-1",
|
||||
|
||||
@@ -2482,6 +2482,7 @@
|
||||
"qiniu": "七牛云 AI 推理",
|
||||
"qwenlm": "QwenLM",
|
||||
"silicon": "硅基流动",
|
||||
"sophnet": "SophNet",
|
||||
"stepfun": "阶跃星辰",
|
||||
"tencent-cloud-ti": "腾讯云 TI",
|
||||
"together": "Together",
|
||||
@@ -3335,6 +3336,10 @@
|
||||
"label": "存储桶",
|
||||
"placeholder": "Bucket, 例如: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "开启后,S3 请求将绕过应用程序代理,以防止大文件上传时的数据损坏。建议保持开启,除非您的 S3 端点需要通过代理访问。",
|
||||
"label": "绕过代理"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "API 地址",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4259,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "AWS 访问密钥 ID",
|
||||
"access_key_id_help": "您的 AWS 访问密钥 ID,用于访问 AWS Bedrock 服务",
|
||||
"api_key": "Bedrock API 密钥",
|
||||
"api_key_help": "您的 AWS Bedrock API 密钥,用于身份验证",
|
||||
"auth_type": "认证方式",
|
||||
"auth_type_api_key": "Bedrock API 密钥",
|
||||
"auth_type_help": "选择使用 IAM 凭证或 Bedrock API 密钥进行身份验证",
|
||||
"auth_type_iam": "IAM 凭证",
|
||||
"description": "AWS Bedrock 是亚马逊提供的全托管基础模型服务,支持多种先进的大语言模型",
|
||||
"region": "AWS 区域",
|
||||
"region_help": "您的 AWS 服务区域,例如 us-east-1",
|
||||
|
||||
@@ -2482,6 +2482,7 @@
|
||||
"qiniu": "七牛雲 AI 推理",
|
||||
"qwenlm": "QwenLM",
|
||||
"silicon": "SiliconFlow",
|
||||
"sophnet": "SophNet",
|
||||
"stepfun": "StepFun",
|
||||
"tencent-cloud-ti": "騰訊雲 TI",
|
||||
"together": "Together",
|
||||
@@ -3335,6 +3336,10 @@
|
||||
"label": "儲存桶",
|
||||
"placeholder": "Bucket,例如: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "開啟後,S3 請求將繞過應用程式代理,以防止大檔案上傳時的資料損壞。建議保持開啟,除非您的 S3 端點需要透過代理存取。",
|
||||
"label": "繞過代理"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "API 位址",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4259,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "AWS 存取密鑰 ID",
|
||||
"access_key_id_help": "您的 AWS 存取密鑰 ID,用於存取 AWS Bedrock 服務",
|
||||
"api_key": "Bedrock API 金鑰",
|
||||
"api_key_help": "您的 AWS Bedrock API 金鑰,用於身份驗證",
|
||||
"auth_type": "認證方式",
|
||||
"auth_type_api_key": "Bedrock API 金鑰",
|
||||
"auth_type_help": "選擇使用 IAM 憑證或 Bedrock API 金鑰進行身份驗證",
|
||||
"auth_type_iam": "IAM 憑證",
|
||||
"description": "AWS Bedrock 是亞馬遜提供的全托管基础模型服務,支持多種先進的大語言模型",
|
||||
"region": "AWS 區域",
|
||||
"region_help": "您的 AWS 服務區域,例如 us-east-1",
|
||||
|
||||
@@ -2476,12 +2476,13 @@
|
||||
"openrouter": "OpenRouter",
|
||||
"ovms": "Intel OVMS",
|
||||
"perplexity": "Perplexity",
|
||||
"ph8": "PH8 Großmodell-Plattform",
|
||||
"ph8": "PH8",
|
||||
"poe": "Poe",
|
||||
"ppio": "PPIO Cloud",
|
||||
"qiniu": "Qiniu Cloud KI-Inferenz",
|
||||
"qwenlm": "QwenLM",
|
||||
"silicon": "SiliconFlow",
|
||||
"sophnet": "SophNet",
|
||||
"stepfun": "StepFun",
|
||||
"tencent-cloud-ti": "Tencent Cloud TI",
|
||||
"together": "Together",
|
||||
@@ -3335,6 +3336,10 @@
|
||||
"label": "Bucket",
|
||||
"placeholder": "Bucket, z. B.: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "Wenn aktiviert, umgehen S3-Anfragen den Anwendungs-Proxy, um Datenbeschädigung beim Hochladen großer Dateien zu verhindern. Es wird empfohlen, diese Option aktiviert zu lassen, es sei denn, Ihr S3-Endpunkt erfordert Proxy-Zugriff.",
|
||||
"label": "Proxy umgehen"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "API-Adresse",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4259,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "AWS-Zugriffsschlüssel-ID",
|
||||
"access_key_id_help": "Ihre AWS-Zugriffsschlüssel-ID, um auf AWS Bedrock-Dienste zuzugreifen",
|
||||
"api_key": "Bedrock-API-Schlüssel",
|
||||
"api_key_help": "Ihr AWS-Bedrock-API-Schlüssel für die Authentifizierung",
|
||||
"auth_type": "Authentifizierungstyp",
|
||||
"auth_type_api_key": "Bedrock-API-Schlüssel",
|
||||
"auth_type_help": "Wähle zwischen IAM-Anmeldeinformationen oder Bedrock-API-Schlüssel-Authentifizierung",
|
||||
"auth_type_iam": "IAM-Anmeldeinformationen",
|
||||
"description": "AWS Bedrock ist ein vollständig verwalteter Basismodell-Dienst von Amazon, der eine Vielzahl moderner großer Sprachmodelle unterstützt",
|
||||
"region": "AWS-Region",
|
||||
"region_help": "Ihre AWS-Serviceregion, z.B. us-east-1",
|
||||
|
||||
@@ -2476,12 +2476,13 @@
|
||||
"openrouter": "OpenRouter",
|
||||
"ovms": "Intel OVMS",
|
||||
"perplexity": "Perplexity",
|
||||
"ph8": "Πλατφόρμα Ανοιχτής Μεγάλης Μοντέλου PH8",
|
||||
"ph8": "PH8",
|
||||
"poe": "Poe",
|
||||
"ppio": "PPIO Piao Yun",
|
||||
"qiniu": "Qiniu AI",
|
||||
"qwenlm": "QwenLM",
|
||||
"silicon": "Σιδηρική Παρουσία",
|
||||
"sophnet": "SophNet",
|
||||
"stepfun": "Βήμα Ουράς",
|
||||
"tencent-cloud-ti": "Tencent Cloud TI",
|
||||
"together": "Together",
|
||||
@@ -3335,6 +3336,10 @@
|
||||
"label": "Δοχείο",
|
||||
"placeholder": "Bucket, π.χ.: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "Όταν είναι ενεργοποιημένο, τα αιτήματα S3 παρακάμπτουν τον διαμεσολαβητή εφαρμογής για να αποτρέψουν τη διαφθορά δεδομένων κατά τη μεταφόρτωση μεγάλων αρχείων. Συνιστάται να παραμένει ενεργοποιημένο, εκτός εάν το τελικό σημείο S3 απαιτεί πρόσβαση μέσω διαμεσολαβητή.",
|
||||
"label": "Παράκαμψη διαμεσολαβητή"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "Διεύθυνση API",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4259,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "Αναγνωριστικό κλειδιού πρόσβασης AWS",
|
||||
"access_key_id_help": "Το ID του κλειδιού πρόσβασης AWS που χρησιμοποιείται για την πρόσβαση στην υπηρεσία AWS Bedrock",
|
||||
"api_key": "Κλειδί API Bedrock",
|
||||
"api_key_help": "Το κλειδί API του AWS Bedrock για έλεγχο ταυτότητας",
|
||||
"auth_type": "Τύπος Πιστοποίησης",
|
||||
"auth_type_api_key": "Κλειδί API Bedrock",
|
||||
"auth_type_help": "Επιλέξτε μεταξύ πιστοποιητικών IAM ή πιστοποίησης με κλειδί API Bedrock",
|
||||
"auth_type_iam": "Διαπιστευτήρια IAM",
|
||||
"description": "Η AWS Bedrock είναι μια πλήρως διαχειριζόμενη υπηρεσία βασικών μοντέλων που παρέχεται από την Amazon και υποστηρίζει διάφορα προηγμένα μεγάλα γλωσσικά μοντέλα.",
|
||||
"region": "Περιοχές AWS",
|
||||
"region_help": "Η περιοχή υπηρεσίας AWS σας, για παράδειγμα us-east-1",
|
||||
|
||||
@@ -2476,12 +2476,13 @@
|
||||
"openrouter": "OpenRouter",
|
||||
"ovms": "Intel OVMS",
|
||||
"perplexity": "Perplejidad",
|
||||
"ph8": "Plataforma Abierta de Grandes Modelos PH8",
|
||||
"ph8": "PH8",
|
||||
"poe": "Poe",
|
||||
"ppio": "PPIO Cloud Piao",
|
||||
"qiniu": "Qiniu AI",
|
||||
"qwenlm": "QwenLM",
|
||||
"silicon": "Silicio Fluido",
|
||||
"sophnet": "SophNet",
|
||||
"stepfun": "Función Salto",
|
||||
"tencent-cloud-ti": "Tencent Nube TI",
|
||||
"together": "Juntos",
|
||||
@@ -3335,6 +3336,10 @@
|
||||
"label": "Bucket",
|
||||
"placeholder": "Bucket, por ejemplo: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "Cuando está habilitado, las solicitudes a S3 omiten el proxy de la aplicación para evitar la corrupción de datos durante las cargas de archivos grandes. Se recomienda mantenerlo habilitado a menos que tu punto de enlace de S3 requiera acceso al proxy.",
|
||||
"label": "Omitir Proxy"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "Dirección API",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4259,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "ID de clave de acceso de AWS",
|
||||
"access_key_id_help": "Su ID de clave de acceso de AWS, utilizado para acceder al servicio AWS Bedrock",
|
||||
"api_key": "Clave de API de Bedrock",
|
||||
"api_key_help": "Tu clave de API de AWS Bedrock para la autenticación",
|
||||
"auth_type": "Tipo de autenticación",
|
||||
"auth_type_api_key": "Clave de API de Bedrock",
|
||||
"auth_type_help": "Elige entre credenciales IAM o autenticación con clave API de Bedrock",
|
||||
"auth_type_iam": "Credenciales IAM",
|
||||
"description": "AWS Bedrock es un servicio de modelos fundamentales completamente gestionado proporcionado por Amazon, que admite diversos modelos avanzados de lenguaje de gran tamaño.",
|
||||
"region": "Región de AWS",
|
||||
"region_help": "Su región de servicio AWS, por ejemplo us-east-1",
|
||||
|
||||
@@ -2476,12 +2476,13 @@
|
||||
"openrouter": "OpenRouter",
|
||||
"ovms": "Intel OVMS",
|
||||
"perplexity": "Perplexité",
|
||||
"ph8": "Plateforme ouverte de grands modèles PH8",
|
||||
"ph8": "PH8",
|
||||
"poe": "Poe",
|
||||
"ppio": "PPIO Cloud Piou",
|
||||
"qiniu": "Qiniu AI",
|
||||
"qwenlm": "QwenLM",
|
||||
"silicon": "Silicium Fluide",
|
||||
"sophnet": "SophNet",
|
||||
"stepfun": "Échelon Étoile",
|
||||
"tencent-cloud-ti": "Tencent Cloud TI",
|
||||
"together": "Ensemble",
|
||||
@@ -3335,6 +3336,10 @@
|
||||
"label": "Bucket",
|
||||
"placeholder": "Bucket, par exemple : example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "Lorsqu’il est activé, les requêtes S3 contournent le proxy de l’application pour éviter la corruption des données lors du téléversement de gros fichiers. Il est recommandé de le laisser activé sauf si votre point de terminaison S3 nécessite un accès par proxy.",
|
||||
"label": "Contourner le proxy"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "Adresse API",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4259,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "Identifiant de clé d'accès AWS",
|
||||
"access_key_id_help": "Votre identifiant de clé d'accès AWS, utilisé pour accéder au service AWS Bedrock",
|
||||
"api_key": "Clé API Bedrock",
|
||||
"api_key_help": "Votre clé API AWS Bedrock pour l'authentification",
|
||||
"auth_type": "Type d'authentification",
|
||||
"auth_type_api_key": "Clé API Bedrock",
|
||||
"auth_type_help": "Choisissez entre l'authentification par identifiants IAM ou par clé API Bedrock",
|
||||
"auth_type_iam": "Identifiants IAM",
|
||||
"description": "AWS Bedrock est un service de modèles de base entièrement géré proposé par Amazon, prenant en charge divers grands modèles linguistiques avancés.",
|
||||
"region": "Région AWS",
|
||||
"region_help": "Votre région de service AWS, par exemple us-east-1",
|
||||
|
||||
@@ -2482,6 +2482,7 @@
|
||||
"qiniu": "七牛云 AI 推理",
|
||||
"qwenlm": "QwenLM",
|
||||
"silicon": "SiliconFlow",
|
||||
"sophnet": "SophNet",
|
||||
"stepfun": "StepFun",
|
||||
"tencent-cloud-ti": "Tencent Cloud TI",
|
||||
"together": "Together",
|
||||
@@ -3335,6 +3336,10 @@
|
||||
"label": "バケット",
|
||||
"placeholder": "Bucket、例: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "有効にすると、S3リクエストはアプリケーションプロキシをバイパスし、大容量ファイルのアップロード中のデータ破損を防ぎます。S3エンドポイントがプロキシアクセスを必要としない限り、有効のままにすることを推奨します。",
|
||||
"label": "プロキシをバイパス"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "APIエンドポイント",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4259,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "AWS アクセスキー ID",
|
||||
"access_key_id_help": "あなたの AWS アクセスキー ID は、AWS Bedrock サービスへのアクセスに使用されます",
|
||||
"api_key": "Bedrock APIキー",
|
||||
"api_key_help": "認証用のAWS Bedrock APIキー",
|
||||
"auth_type": "認証タイプ",
|
||||
"auth_type_api_key": "Bedrock APIキー",
|
||||
"auth_type_help": "IAM認証情報とBedrock APIキー認証のどちらかを選択してください",
|
||||
"auth_type_iam": "IAM認証情報",
|
||||
"description": "AWS Bedrock は、Amazon が提供する完全に管理されたベースモデルサービスで、さまざまな最先端の大言語モデルをサポートしています",
|
||||
"region": "AWS リージョン",
|
||||
"region_help": "あなたの AWS サービスリージョン、例:us-east-1",
|
||||
|
||||
@@ -2476,12 +2476,13 @@
|
||||
"openrouter": "OpenRouter",
|
||||
"ovms": "Intel OVMS",
|
||||
"perplexity": "Perplexidade",
|
||||
"ph8": "Plataforma Aberta de Grandes Modelos PH8",
|
||||
"ph8": "PH8",
|
||||
"poe": "Poe",
|
||||
"ppio": "PPIO Nuvem Piao",
|
||||
"qiniu": "Qiniu AI",
|
||||
"qwenlm": "QwenLM",
|
||||
"silicon": "Silício em Fluxo",
|
||||
"sophnet": "SophNet",
|
||||
"stepfun": "Função de Passo Estelar",
|
||||
"tencent-cloud-ti": "Nuvem TI da Tencent",
|
||||
"together": "Juntos",
|
||||
@@ -3335,6 +3336,10 @@
|
||||
"label": "Bucket",
|
||||
"placeholder": "Bucket, por exemplo: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "Quando ativado, as solicitações S3 ignoram o proxy da aplicação para evitar corrupção de dados durante uploads de arquivos grandes. Recomenda-se manter ativado, a menos que seu endpoint S3 exija acesso por proxy.",
|
||||
"label": "Ignorar Proxy"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "Endereço da API",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4259,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "ID da chave de acesso da AWS",
|
||||
"access_key_id_help": "O seu ID da chave de acesso AWS, utilizado para aceder ao serviço AWS Bedrock",
|
||||
"api_key": "Chave de API do Bedrock",
|
||||
"api_key_help": "Sua Chave de API AWS Bedrock para autenticação",
|
||||
"auth_type": "Tipo de Autenticação",
|
||||
"auth_type_api_key": "Chave de API do Bedrock",
|
||||
"auth_type_help": "Escolha entre credenciais IAM ou autenticação por chave de API do Bedrock",
|
||||
"auth_type_iam": "Credenciais IAM",
|
||||
"description": "A AWS Bedrock é um serviço de modelos fundamentais totalmente gerido fornecido pela Amazon, que suporta diversos modelos avançados de linguagem.",
|
||||
"region": "Região da AWS",
|
||||
"region_help": "A sua região de serviço da AWS, por exemplo, us-east-1",
|
||||
|
||||
@@ -2482,6 +2482,7 @@
|
||||
"qiniu": "Qiniu AI",
|
||||
"qwenlm": "QwenLM",
|
||||
"silicon": "SiliconFlow",
|
||||
"sophnet": "SophNet",
|
||||
"stepfun": "StepFun",
|
||||
"tencent-cloud-ti": "Tencent Cloud TI",
|
||||
"together": "Together",
|
||||
@@ -3335,6 +3336,10 @@
|
||||
"label": "Корзина",
|
||||
"placeholder": "Корзина, например: example"
|
||||
},
|
||||
"bypassProxy": {
|
||||
"help": "При включении запросы к S3 обходят прокси-приложение, чтобы предотвратить повреждение данных при загрузке больших файлов. Рекомендуется оставить включённым, если только ваш S3-эндпоинт не требует доступа через прокси.",
|
||||
"label": "Обход прокси"
|
||||
},
|
||||
"endpoint": {
|
||||
"label": "Конечная точка API",
|
||||
"placeholder": "https://s3.example.com"
|
||||
@@ -4259,6 +4264,12 @@
|
||||
"aws-bedrock": {
|
||||
"access_key_id": "AWS Ключ доступа ID",
|
||||
"access_key_id_help": "Ваш AWS Ключ доступа ID для доступа к AWS Bedrock",
|
||||
"api_key": "Ключ API Bedrock",
|
||||
"api_key_help": "Ваш API-ключ AWS Bedrock для аутентификации",
|
||||
"auth_type": "Тип аутентификации",
|
||||
"auth_type_api_key": "Ключ API Bedrock",
|
||||
"auth_type_help": "Выберите между аутентификацией с помощью учетных данных IAM или ключа API Bedrock",
|
||||
"auth_type_iam": "Учетные данные IAM",
|
||||
"description": "AWS Bedrock — это полное управляемое сервисное предложение для моделей, поддерживающее различные современные модели языка",
|
||||
"region": "AWS регион",
|
||||
"region_help": "Ваш регион AWS, например us-east-1",
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { DropResult } from '@hello-pangea/dnd'
|
||||
import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd'
|
||||
import { loggerService } from '@logger'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { MdiLightbulbOn } from '@renderer/components/Icons'
|
||||
import type { QuickPanelListItem } from '@renderer/components/QuickPanel'
|
||||
import {
|
||||
isAnthropicModel,
|
||||
@@ -230,6 +231,15 @@ const InputbarTools = ({
|
||||
quickPhrasesButtonRef.current?.openQuickPanel()
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t('assistants.settings.reasoning_effort.label'),
|
||||
description: '',
|
||||
icon: <MdiLightbulbOn />,
|
||||
isMenu: true,
|
||||
action: () => {
|
||||
thinkingButtonRef.current?.openQuickPanel()
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t('assistants.presets.edit.model.select.title'),
|
||||
description: '',
|
||||
@@ -245,6 +255,7 @@ const InputbarTools = ({
|
||||
icon: <FileSearch />,
|
||||
isMenu: true,
|
||||
disabled: files.length > 0,
|
||||
hidden: !showKnowledgeBaseButton,
|
||||
action: () => {
|
||||
knowledgeBaseButtonRef.current?.openQuickPanel()
|
||||
}
|
||||
@@ -312,7 +323,7 @@ const InputbarTools = ({
|
||||
translate()
|
||||
}
|
||||
}
|
||||
]
|
||||
] satisfies QuickPanelListItem[]
|
||||
}
|
||||
|
||||
const handleDragEnd = (result: DropResult) => {
|
||||
|
||||
@@ -482,6 +482,13 @@ const NewApiPage: FC<{ Options: string[] }> = ({ Options }) => {
|
||||
}
|
||||
}, [])
|
||||
|
||||
// if painting.model is not set, set it to the first model in modelOptions
|
||||
useEffect(() => {
|
||||
if (!painting.model && modelOptions.length > 0) {
|
||||
updatePaintingState({ model: modelOptions[0].value })
|
||||
}
|
||||
}, [modelOptions, painting.model, updatePaintingState])
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Navbar>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { isNewApiProvider } from '@renderer/config/providers'
|
||||
import { useAllProviders } from '@renderer/hooks/useProvider'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import { setDefaultPaintingProvider } from '@renderer/store/settings'
|
||||
import { updateTab } from '@renderer/store/tabs'
|
||||
import type { PaintingProvider, SystemProviderId } from '@renderer/types'
|
||||
import type { FC } from 'react'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
@@ -25,11 +26,11 @@ const PaintingsRoutePage: FC = () => {
|
||||
const provider = params['*']
|
||||
const dispatch = useAppDispatch()
|
||||
const providers = useAllProviders()
|
||||
const Options = useMemo(() => {
|
||||
return [...BASE_OPTIONS, ...providers.filter((p) => isNewApiProvider(p)).map((p) => p.id)]
|
||||
}, [providers])
|
||||
const [ovmsStatus, setOvmsStatus] = useState<'not-installed' | 'not-running' | 'running'>('not-running')
|
||||
|
||||
const Options = useMemo(() => [...BASE_OPTIONS, ...providers.filter(isNewApiProvider).map((p) => p.id)], [providers])
|
||||
const newApiProviders = useMemo(() => providers.filter(isNewApiProvider), [providers])
|
||||
|
||||
useEffect(() => {
|
||||
const checkStatus = async () => {
|
||||
const status = await window.api.ovms.getStatus()
|
||||
@@ -44,25 +45,24 @@ const PaintingsRoutePage: FC = () => {
|
||||
logger.debug(`defaultPaintingProvider: ${provider}`)
|
||||
if (provider && validOptions.includes(provider)) {
|
||||
dispatch(setDefaultPaintingProvider(provider as PaintingProvider))
|
||||
dispatch(updateTab({ id: 'paintings', updates: { path: `/paintings/${provider}` } }))
|
||||
}
|
||||
}, [provider, dispatch, validOptions])
|
||||
|
||||
return (
|
||||
<Routes>
|
||||
<Route path="*" element={<ZhipuPage Options={validOptions} />} />
|
||||
<Route path="*" element={<NewApiPage Options={validOptions} />} />
|
||||
<Route path="/zhipu" element={<ZhipuPage Options={validOptions} />} />
|
||||
<Route path="/aihubmix" element={<AihubmixPage Options={validOptions} />} />
|
||||
<Route path="/silicon" element={<SiliconPage Options={validOptions} />} />
|
||||
<Route path="/dmxapi" element={<DmxapiPage Options={validOptions} />} />
|
||||
<Route path="/tokenflux" element={<TokenFluxPage Options={validOptions} />} />
|
||||
<Route path="/ovms" element={<OvmsPage Options={validOptions} />} />
|
||||
{/* new-api family providers are mounted dynamically below */}
|
||||
{providers
|
||||
.filter((p) => isNewApiProvider(p))
|
||||
.map((p) => (
|
||||
<Route key={p.id} path={`/${p.id}`} element={<NewApiPage Options={validOptions} />} />
|
||||
))}
|
||||
<Route path="/new-api" element={<NewApiPage Options={validOptions} />} />
|
||||
{/* new-api family providers are mounted dynamically below */}
|
||||
{newApiProviders.map((p) => (
|
||||
<Route key={p.id} path={`/${p.id}`} element={<NewApiPage Options={validOptions} />} />
|
||||
))}
|
||||
</Routes>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,8 @@ const S3Settings: FC = () => {
|
||||
root: s3RootInit = '',
|
||||
syncInterval: s3SyncIntervalInit = 0,
|
||||
maxBackups: s3MaxBackupsInit = 5,
|
||||
skipBackupFile: s3SkipBackupFileInit = false
|
||||
skipBackupFile: s3SkipBackupFileInit = false,
|
||||
bypassProxy: s3BypassProxyInit = true
|
||||
} = s3
|
||||
|
||||
const [endpoint, setEndpoint] = useState<string | undefined>(s3EndpointInit)
|
||||
@@ -41,6 +42,7 @@ const S3Settings: FC = () => {
|
||||
const [secretAccessKey, setSecretAccessKey] = useState<string | undefined>(s3SecretAccessKeyInit)
|
||||
const [root, setRoot] = useState<string | undefined>(s3RootInit)
|
||||
const [skipBackupFile, setSkipBackupFile] = useState<boolean>(s3SkipBackupFileInit)
|
||||
const [bypassProxy, setBypassProxy] = useState<boolean>(s3BypassProxyInit)
|
||||
const [backupManagerVisible, setBackupManagerVisible] = useState(false)
|
||||
|
||||
const [syncInterval, setSyncInterval] = useState<number>(s3SyncIntervalInit)
|
||||
@@ -82,6 +84,11 @@ const S3Settings: FC = () => {
|
||||
dispatch(setS3Partial({ skipBackupFile: value }))
|
||||
}
|
||||
|
||||
const onBypassProxyChange = (value: boolean) => {
|
||||
setBypassProxy(value)
|
||||
dispatch(setS3Partial({ bypassProxy: value }))
|
||||
}
|
||||
|
||||
const renderSyncStatus = () => {
|
||||
if (!endpoint) return null
|
||||
|
||||
@@ -261,6 +268,14 @@ const S3Settings: FC = () => {
|
||||
<SettingRow>
|
||||
<SettingHelpText>{t('settings.data.s3.skipBackupFile.help')}</SettingHelpText>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.data.s3.bypassProxy.label')}</SettingRowTitle>
|
||||
<Switch checked={bypassProxy} onChange={onBypassProxyChange} />
|
||||
</SettingRow>
|
||||
<SettingRow>
|
||||
<SettingHelpText>{t('settings.data.s3.bypassProxy.help')}</SettingHelpText>
|
||||
</SettingRow>
|
||||
{syncInterval > 0 && (
|
||||
<>
|
||||
<SettingDivider />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import { PROVIDER_URLS } from '@renderer/config/providers'
|
||||
import { useAwsBedrockSettings } from '@renderer/hooks/useAwsBedrock'
|
||||
import { Alert, Input } from 'antd'
|
||||
import { Alert, Input, Radio } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -10,14 +10,25 @@ import { SettingHelpLink, SettingHelpText, SettingHelpTextRow, SettingSubtitle }
|
||||
|
||||
const AwsBedrockSettings: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const { accessKeyId, secretAccessKey, region, setAccessKeyId, setSecretAccessKey, setRegion } =
|
||||
useAwsBedrockSettings()
|
||||
const {
|
||||
authType,
|
||||
accessKeyId,
|
||||
secretAccessKey,
|
||||
apiKey,
|
||||
region,
|
||||
setAuthType,
|
||||
setAccessKeyId,
|
||||
setSecretAccessKey,
|
||||
setApiKey,
|
||||
setRegion
|
||||
} = useAwsBedrockSettings()
|
||||
|
||||
const providerConfig = PROVIDER_URLS['aws-bedrock']
|
||||
const apiKeyWebsite = providerConfig?.websites?.apiKey
|
||||
|
||||
const [localAccessKeyId, setLocalAccessKeyId] = useState(accessKeyId)
|
||||
const [localSecretAccessKey, setLocalSecretAccessKey] = useState(secretAccessKey)
|
||||
const [localApiKey, setLocalApiKey] = useState(apiKey)
|
||||
const [localRegion, setLocalRegion] = useState(region)
|
||||
|
||||
return (
|
||||
@@ -25,39 +36,75 @@ const AwsBedrockSettings: FC = () => {
|
||||
<SettingSubtitle style={{ marginTop: 5 }}>{t('settings.provider.aws-bedrock.title')}</SettingSubtitle>
|
||||
<Alert type="info" style={{ marginTop: 5 }} message={t('settings.provider.aws-bedrock.description')} showIcon />
|
||||
|
||||
<SettingSubtitle style={{ marginTop: 5 }}>{t('settings.provider.aws-bedrock.access_key_id')}</SettingSubtitle>
|
||||
<Input
|
||||
value={localAccessKeyId}
|
||||
placeholder="Access Key ID"
|
||||
onChange={(e) => setLocalAccessKeyId(e.target.value)}
|
||||
onBlur={() => setAccessKeyId(localAccessKeyId)}
|
||||
style={{ marginTop: 5 }}
|
||||
/>
|
||||
{/* Authentication Type Selector */}
|
||||
<SettingSubtitle style={{ marginTop: 15 }}>{t('settings.provider.aws-bedrock.auth_type')}</SettingSubtitle>
|
||||
<Radio.Group value={authType} onChange={(e) => setAuthType(e.target.value)} style={{ marginTop: 5 }}>
|
||||
<Radio value="iam">{t('settings.provider.aws-bedrock.auth_type_iam')}</Radio>
|
||||
<Radio value="apiKey">{t('settings.provider.aws-bedrock.auth_type_api_key')}</Radio>
|
||||
</Radio.Group>
|
||||
<SettingHelpTextRow>
|
||||
<SettingHelpText>{t('settings.provider.aws-bedrock.access_key_id_help')}</SettingHelpText>
|
||||
<SettingHelpText>{t('settings.provider.aws-bedrock.auth_type_help')}</SettingHelpText>
|
||||
</SettingHelpTextRow>
|
||||
|
||||
<SettingSubtitle style={{ marginTop: 5 }}>{t('settings.provider.aws-bedrock.secret_access_key')}</SettingSubtitle>
|
||||
<Input.Password
|
||||
value={localSecretAccessKey}
|
||||
placeholder="Secret Access Key"
|
||||
onChange={(e) => setLocalSecretAccessKey(e.target.value)}
|
||||
onBlur={() => setSecretAccessKey(localSecretAccessKey)}
|
||||
style={{ marginTop: 5 }}
|
||||
spellCheck={false}
|
||||
/>
|
||||
{apiKeyWebsite && (
|
||||
<SettingHelpTextRow style={{ justifyContent: 'space-between' }}>
|
||||
<HStack>
|
||||
<SettingHelpLink target="_blank" href={apiKeyWebsite}>
|
||||
{t('settings.provider.get_api_key')}
|
||||
</SettingHelpLink>
|
||||
</HStack>
|
||||
<SettingHelpText>{t('settings.provider.aws-bedrock.secret_access_key_help')}</SettingHelpText>
|
||||
</SettingHelpTextRow>
|
||||
{/* IAM Credentials Fields */}
|
||||
{authType === 'iam' && (
|
||||
<>
|
||||
<SettingSubtitle style={{ marginTop: 15 }}>
|
||||
{t('settings.provider.aws-bedrock.access_key_id')}
|
||||
</SettingSubtitle>
|
||||
<Input
|
||||
value={localAccessKeyId}
|
||||
placeholder="Access Key ID"
|
||||
onChange={(e) => setLocalAccessKeyId(e.target.value)}
|
||||
onBlur={() => setAccessKeyId(localAccessKeyId)}
|
||||
style={{ marginTop: 5 }}
|
||||
/>
|
||||
<SettingHelpTextRow>
|
||||
<SettingHelpText>{t('settings.provider.aws-bedrock.access_key_id_help')}</SettingHelpText>
|
||||
</SettingHelpTextRow>
|
||||
|
||||
<SettingSubtitle style={{ marginTop: 15 }}>
|
||||
{t('settings.provider.aws-bedrock.secret_access_key')}
|
||||
</SettingSubtitle>
|
||||
<Input.Password
|
||||
value={localSecretAccessKey}
|
||||
placeholder="Secret Access Key"
|
||||
onChange={(e) => setLocalSecretAccessKey(e.target.value)}
|
||||
onBlur={() => setSecretAccessKey(localSecretAccessKey)}
|
||||
style={{ marginTop: 5 }}
|
||||
spellCheck={false}
|
||||
/>
|
||||
{apiKeyWebsite && (
|
||||
<SettingHelpTextRow style={{ justifyContent: 'space-between' }}>
|
||||
<HStack>
|
||||
<SettingHelpLink target="_blank" href={apiKeyWebsite}>
|
||||
{t('settings.provider.get_api_key')}
|
||||
</SettingHelpLink>
|
||||
</HStack>
|
||||
<SettingHelpText>{t('settings.provider.aws-bedrock.secret_access_key_help')}</SettingHelpText>
|
||||
</SettingHelpTextRow>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
<SettingSubtitle style={{ marginTop: 5 }}>{t('settings.provider.aws-bedrock.region')}</SettingSubtitle>
|
||||
{authType === 'apiKey' && (
|
||||
<>
|
||||
<SettingSubtitle style={{ marginTop: 15 }}>{t('settings.provider.aws-bedrock.api_key')}</SettingSubtitle>
|
||||
<Input.Password
|
||||
value={localApiKey}
|
||||
placeholder="Bedrock API Key"
|
||||
onChange={(e) => setLocalApiKey(e.target.value)}
|
||||
onBlur={() => setApiKey(localApiKey)}
|
||||
style={{ marginTop: 5 }}
|
||||
spellCheck={false}
|
||||
/>
|
||||
<SettingHelpTextRow>
|
||||
<SettingHelpText>{t('settings.provider.aws-bedrock.api_key_help')}</SettingHelpText>
|
||||
</SettingHelpTextRow>
|
||||
</>
|
||||
)}
|
||||
|
||||
<SettingSubtitle style={{ marginTop: 15 }}>{t('settings.provider.aws-bedrock.region')}</SettingSubtitle>
|
||||
<Input
|
||||
value={localRegion}
|
||||
placeholder="us-east-1"
|
||||
|
||||
@@ -131,10 +131,11 @@ const PopupContainer: React.FC<Props> = ({ providerId, resolve }) => {
|
||||
(model: Model) => {
|
||||
if (!isEmpty(model.name)) {
|
||||
if (isNewApiProvider(provider)) {
|
||||
if (model.supported_endpoint_types && model.supported_endpoint_types.length > 0) {
|
||||
const endpointTypes = model.supported_endpoint_types
|
||||
if (endpointTypes && endpointTypes.length > 0) {
|
||||
addModel({
|
||||
...model,
|
||||
endpoint_type: model.supported_endpoint_types[0],
|
||||
endpoint_type: endpointTypes.includes('image-generation') ? 'image-generation' : endpointTypes[0],
|
||||
supported_text_delta: !isNotSupportedTextDelta(model)
|
||||
})
|
||||
} else {
|
||||
|
||||
@@ -230,8 +230,10 @@ vi.mock('@renderer/store/llm.ts', () => {
|
||||
location: ''
|
||||
},
|
||||
awsBedrock: {
|
||||
authType: 'iam',
|
||||
accessKeyId: '',
|
||||
secretAccessKey: '',
|
||||
apiKey: '',
|
||||
region: ''
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ const persistedReducer = persistReducer(
|
||||
{
|
||||
key: 'cherry-studio',
|
||||
storage,
|
||||
version: 169,
|
||||
version: 171,
|
||||
blacklist: ['runtime', 'messages', 'messageBlocks', 'tabs', 'toolPermissions'],
|
||||
migrate
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createSlice } from '@reduxjs/toolkit'
|
||||
import { isLocalAi } from '@renderer/config/env'
|
||||
import { SYSTEM_MODELS } from '@renderer/config/models'
|
||||
import { SYSTEM_PROVIDERS } from '@renderer/config/providers'
|
||||
import type { Model, Provider } from '@renderer/types'
|
||||
import type { AwsBedrockAuthType, Model, Provider } from '@renderer/types'
|
||||
import { uniqBy } from 'lodash'
|
||||
|
||||
type LlmSettings = {
|
||||
@@ -25,8 +25,10 @@ type LlmSettings = {
|
||||
location: string
|
||||
}
|
||||
awsBedrock: {
|
||||
authType: AwsBedrockAuthType
|
||||
accessKeyId: string
|
||||
secretAccessKey: string
|
||||
apiKey: string
|
||||
region: string
|
||||
}
|
||||
}
|
||||
@@ -68,8 +70,10 @@ export const initialState: LlmState = {
|
||||
location: ''
|
||||
},
|
||||
awsBedrock: {
|
||||
authType: 'iam',
|
||||
accessKeyId: '',
|
||||
secretAccessKey: '',
|
||||
apiKey: '',
|
||||
region: ''
|
||||
}
|
||||
}
|
||||
@@ -197,12 +201,18 @@ const llmSlice = createSlice({
|
||||
setVertexAIServiceAccountClientEmail: (state, action: PayloadAction<string>) => {
|
||||
state.settings.vertexai.serviceAccount.clientEmail = action.payload
|
||||
},
|
||||
setAwsBedrockAuthType: (state, action: PayloadAction<AwsBedrockAuthType>) => {
|
||||
state.settings.awsBedrock.authType = action.payload
|
||||
},
|
||||
setAwsBedrockAccessKeyId: (state, action: PayloadAction<string>) => {
|
||||
state.settings.awsBedrock.accessKeyId = action.payload
|
||||
},
|
||||
setAwsBedrockSecretAccessKey: (state, action: PayloadAction<string>) => {
|
||||
state.settings.awsBedrock.secretAccessKey = action.payload
|
||||
},
|
||||
setAwsBedrockApiKey: (state, action: PayloadAction<string>) => {
|
||||
state.settings.awsBedrock.apiKey = action.payload
|
||||
},
|
||||
setAwsBedrockRegion: (state, action: PayloadAction<string>) => {
|
||||
state.settings.awsBedrock.region = action.payload
|
||||
},
|
||||
@@ -242,8 +252,10 @@ export const {
|
||||
setVertexAILocation,
|
||||
setVertexAIServiceAccountPrivateKey,
|
||||
setVertexAIServiceAccountClientEmail,
|
||||
setAwsBedrockAuthType,
|
||||
setAwsBedrockAccessKeyId,
|
||||
setAwsBedrockSecretAccessKey,
|
||||
setAwsBedrockApiKey,
|
||||
setAwsBedrockRegion,
|
||||
updateModel
|
||||
} = llmSlice.actions
|
||||
|
||||
@@ -2783,6 +2783,28 @@ const migrateConfig = {
|
||||
logger.error('migrate 169 error', error as Error)
|
||||
return state
|
||||
}
|
||||
},
|
||||
'170': (state: RootState) => {
|
||||
try {
|
||||
addProvider(state, 'sophnet')
|
||||
state.llm.providers = moveProvider(state.llm.providers, 'sophnet', 17)
|
||||
state.settings.defaultPaintingProvider = 'cherryin'
|
||||
return state
|
||||
} catch (error) {
|
||||
logger.error('migrate 170 error', error as Error)
|
||||
return state
|
||||
}
|
||||
},
|
||||
'171': (state: RootState) => {
|
||||
try {
|
||||
addProvider(state, 'sophnet')
|
||||
state.llm.providers = moveProvider(state.llm.providers, 'sophnet', 17)
|
||||
state.settings.defaultPaintingProvider = 'cherryin'
|
||||
return state
|
||||
} catch (error) {
|
||||
logger.error('migrate 171 error', error as Error)
|
||||
return state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -390,7 +390,7 @@ export const initialState: SettingsState = {
|
||||
localBackupSyncInterval: 0,
|
||||
localBackupMaxBackups: 0,
|
||||
localBackupSkipBackupFile: false,
|
||||
defaultPaintingProvider: 'zhipu',
|
||||
defaultPaintingProvider: 'cherryin',
|
||||
s3: {
|
||||
endpoint: '',
|
||||
region: '',
|
||||
@@ -401,7 +401,8 @@ export const initialState: SettingsState = {
|
||||
autoSync: false,
|
||||
syncInterval: 0,
|
||||
maxBackups: 0,
|
||||
skipBackupFile: false
|
||||
skipBackupFile: false,
|
||||
bypassProxy: true
|
||||
},
|
||||
|
||||
// Developer mode
|
||||
|
||||
@@ -36,6 +36,7 @@ export type Assistant = {
|
||||
description?: string
|
||||
model?: Model
|
||||
defaultModel?: Model
|
||||
// This field should be considered as not Partial and not optional in v2
|
||||
settings?: Partial<AssistantSettings>
|
||||
messages?: AssistantMessage[]
|
||||
/** enableWebSearch 代表使用模型内置网络搜索功能 */
|
||||
@@ -280,7 +281,7 @@ export type PaintingParams = {
|
||||
providerId?: string
|
||||
}
|
||||
|
||||
export type PaintingProvider = 'zhipu' | 'aihubmix' | 'silicon' | 'dmxapi' | 'new-api' | 'ovms'
|
||||
export type PaintingProvider = 'zhipu' | 'aihubmix' | 'silicon' | 'dmxapi' | 'new-api' | 'ovms' | 'cherryin'
|
||||
|
||||
export interface Painting extends PaintingParams {
|
||||
model?: string
|
||||
@@ -882,6 +883,7 @@ export type S3Config = {
|
||||
autoSync: boolean
|
||||
syncInterval: number
|
||||
maxBackups: number
|
||||
bypassProxy?: boolean // Whether to bypass proxy for S3 requests (default: true)
|
||||
}
|
||||
|
||||
export type { Message } from './newMessage'
|
||||
|
||||
@@ -73,6 +73,17 @@ export function isServiceTier(tier: string): tier is ServiceTier {
|
||||
return isGroqServiceTier(tier) || isOpenAIServiceTier(tier)
|
||||
}
|
||||
|
||||
export const AwsBedrockAuthTypes = {
|
||||
iam: 'iam',
|
||||
apiKey: 'apiKey'
|
||||
} as const
|
||||
|
||||
export type AwsBedrockAuthType = keyof typeof AwsBedrockAuthTypes
|
||||
|
||||
export function isAwsBedrockAuthType(type: string): type is AwsBedrockAuthType {
|
||||
return Object.hasOwn(AwsBedrockAuthTypes, type)
|
||||
}
|
||||
|
||||
export type Provider = {
|
||||
id: string
|
||||
type: ProviderType
|
||||
@@ -123,6 +134,7 @@ export const SystemProviderIds = {
|
||||
cephalon: 'cephalon',
|
||||
lanyun: 'lanyun',
|
||||
ph8: 'ph8',
|
||||
sophnet: 'sophnet',
|
||||
openrouter: 'openrouter',
|
||||
ollama: 'ollama',
|
||||
ovms: 'ovms',
|
||||
|
||||
Reference in New Issue
Block a user