1 line
24 KiB
JSON
1 line
24 KiB
JSON
{"repo": "bitan-del/gods-eye", "files": {"apps/desktop/src/renderer/utils/model/modelPlatforms.ts": {"f8e9982f62ba0222b57d1a8ea2ccf45ca2da9e27": {"t": 1785595484.6008902, "n": 9335, "h": "7fa1d387b9144871", "c": "/**\n * @license\n * Copyright 2025 Gods Eye (gods-eye.org)\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * 模型平台配置模块\n * Model Platform Configuration Module\n *\n * 集中管理所有模型平台的配置信息,便于扩展和维护\n * Centralized management of all model platform configurations for extensibility and maintainability\n */\n\n// Provider Logo imports\nimport GeminiLogo from '@/renderer/assets/logos/ai-major/gemini.svg';\nimport OpenAILogo from '@/renderer/assets/logos/ai-major/openai.svg';\nimport AnthropicLogo from '@/renderer/assets/logos/ai-major/anthropic.svg';\nimport BedrockLogo from '@/renderer/assets/logos/ai-cloud/bedrock.svg';\nimport DeepSeekLogo from '@/renderer/assets/logos/ai-major/deepseek.svg';\nimport OpenRouterLogo from '@/renderer/assets/logos/ai-cloud/openrouter.svg';\nimport SiliconFlowLogo from '@/renderer/assets/logos/ai-cloud/siliconflow.png';\nimport QwenLogo from '@/renderer/assets/logos/ai-china/qwen.svg';\nimport KimiLogo from '@/renderer/assets/logos/ai-china/kimi.svg';\nimport ZhipuLogo from '@/renderer/assets/logos/ai-china/zhipu.svg';\nimport XaiLogo from '@/renderer/assets/logos/ai-major/xai.svg';\nimport VolcengineLogo from '@/renderer/assets/logos/ai-china/volcengine.svg';\nimport BaiduLogo from '@/renderer/assets/logos/ai-china/baidu.svg';\nimport TencentLogo from '@/renderer/assets/logos/ai-china/tencent.svg';\nimport LingyiLogo from '@/renderer/assets/logos/ai-china/lingyiwanwu.svg';\nimport PoeLogo from '@/renderer/assets/logos/ai-cloud/poe.svg';\nimport ModelScopeLogo from '@/renderer/assets/logos/ai-cloud/modelscope.svg';\nimport InfiniAILogo from '@/renderer/assets/logos/ai-cloud/infiniai.svg';\nimport CtyunLogo from '@/renderer/assets/logos/ai-cloud/ctyun.svg';\nimport StepFunLogo from '@/renderer/assets/logos/ai-china/stepfun.svg';\nimport MiniMaxLogo from '@/renderer/assets/logos/ai-china/minimax.png';\nimport NewApiLogo from '@/renderer/assets/logos/ai-cloud/newapi.svg';\nimport NovitaLogo from '@/renderer/assets/logos/ai-cloud/novita.svg';\nimport PPIOLogo from '@/renderer/assets/logos/ai-cloud/ppio.svg';\n\n/**\n * 平台类型\n * Platform type\n */\nexport type PlatformType = 'gemini' | 'gemini-vertex-ai' | 'anthropic' | 'custom' | 'new-api' | 'bedrock';\n\n/**\n * 模型平台配置接口\n * Model Platform Configuration Interface\n */\nexport interface PlatformConfig {\n /** 平台名称 / Platform name */\n name: string;\n /** 平台值(用于表单) / Platform value (for form) */\n value: string;\n /** Logo 路径 / Logo path */\n logo: string | null;\n /** 平台标识 / Platform identifier */\n platform: PlatformType;\n /** Base URL(预设供应商使用) / Base URL (for preset providers) */\n baseUrl?: string;\n /** 国际化 key(可选,用于需要翻译的平台名称) / i18n key (optional, for platform names that need translation) */\n i18nKey?: string;\n}\n\n/**\n * 模型平台选项列表\n * Model Platform options list\n *\n * 顺序:\n * 1. Gemini (官方)\n * 2. Gemini Vertex AI\n * 3. 自定义(需要用户输入 base url)\n * 4+ 预设供应商\n */\nexport const MODEL_PLATFORMS: PlatformConfig[] = [\n // 自定义选项(需要用户输入 base url)/ Custom option (requires user to input base url)\n { name: 'Custom', value: 'custom', logo: null, platform: 'custom', i18nKey: 'settings.platformCustom' },\n\n // New API 多模型网关 / New API multi-model gateway\n { name: 'New API', value: 'new-api', logo: NewApiLogo, platform: 'new-api', i18nKey: 'settings.platformNewApi' },\n\n // 官方 Gemini 平台\n {\n name: 'Gemini',\n value: 'gemini',\n logo: GeminiLogo,\n platform: 'gemini',\n baseUrl: 'https://generativelanguage.googleapis.com',\n },\n { name: 'Gemini (Vertex AI)', value: 'gemini-vertex-ai', logo: GeminiLogo, platform: 'gemini-vertex-ai' },\n\n // 预设供应商(按字母顺序排列)\n { name: 'OpenAI', value: 'OpenAI', logo: OpenAILogo, platform: 'custom', baseUrl: 'https://api.openai.com/v1' },\n {\n name: 'Anthropic',\n value: 'Anthropic',\n logo: AnthropicLogo,\n platform: 'anthropic',\n baseUrl: 'https://api.anthropic.com',\n },\n {\n name: 'AWS Bedrock',\n value: 'AWS-Bedrock',\n logo: BedrockLogo,\n platform: 'bedrock',\n i18nKey: 'settings.platformBedrock',\n },\n {\n name: 'DeepSeek',\n value: 'DeepSeek',\n logo: DeepSeekLogo,\n platform: 'custom',\n baseUrl: 'https://api.deepseek.com/v1',\n },\n { name: 'MiniMax', value: 'MiniMax', logo: MiniMaxLogo, platform: 'custom', baseUrl: 'https://api.minimaxi.com/v1' },\n {\n name: 'Novita',\n value: 'Novita',\n logo: NovitaLogo,\n platform: 'custom',\n baseUrl: 'https://api.novita.ai/openai/v1',\n },\n {\n name: 'OpenRouter',\n value: 'OpenRouter',\n logo: OpenRouterLogo,\n platform: 'custom',\n baseUrl: 'https://openrouter.ai/api/v1',\n },\n {\n name: 'Dashscope',\n value: 'Dashscope',\n logo: QwenLogo,\n platform: 'custom',\n baseUrl: 'https://dashscope.aliyuncs.com/compatible-mode/v1',\n },\n {\n name: 'Dashscope Coding Plan',\n value: 'Dashscope-Coding',\n logo: QwenLogo,\n platform: 'custom',\n baseUrl: 'https://coding.dashscope.aliyuncs.com/v1',\n },\n {\n name: 'SiliconFlow-CN',\n value: 'SiliconFlow-CN',\n logo: SiliconFlowLogo,\n platform: 'custom',\n baseUrl: 'https://api.siliconflow.cn/v1',\n },\n {\n name: 'SiliconFlow',\n value: 'SiliconFlow',\n logo: SiliconFlowLogo,\n platform: 'custom',\n baseUrl: 'https://api.siliconflow.com/v1',\n },\n {\n name: 'Zhipu',\n value: 'Zhipu',\n logo: ZhipuLogo,\n platform: 'custom',\n baseUrl: 'https://open.bigmodel.cn/api/paas/v4',\n },\n {\n name: 'Moonshot (China)',\n value: 'Moonshot',\n logo: KimiLogo,\n platform: 'custom',\n baseUrl: 'https://api.moonshot.cn/v1',\n },\n {\n name: 'Moonshot (Global)',\n value: 'Moonshot-Global',\n logo: KimiLogo,\n platform: 'custom',\n baseUrl: 'https://api.moonshot.ai/v1',\n },\n { name: 'xAI', value: 'xAI', logo: XaiLogo, platform: 'custom', baseUrl: 'https://api.x.ai/v1' },\n {\n name: 'Ark',\n value: 'Ark',\n logo: VolcengineLogo,\n platform: 'custom',\n baseUrl: 'https://ark.cn-beijing.volces.com/api/v3',\n },\n {\n name: 'Qianfan',\n value: 'Qianfan',\n logo: BaiduLogo,\n platform: 'custom',\n baseUrl: 'https://qianfan.baidubce.com/v2',\n },\n {\n name: 'Hunyuan',\n value: 'Hunyuan',\n logo: TencentLogo,\n platform: 'custom',\n baseUrl: 'https://api.hunyuan.cloud.tencent.com/v1',\n },\n { name: 'Lingyi', value: 'Lingyi', logo: LingyiLogo, platform: 'custom', baseUrl: 'https://api.lingyiwanwu.com/v1' },\n { name: 'Poe', value: 'Poe', logo: PoeLogo, platform: 'custom', baseUrl: 'https://api.poe.com/v1' },\n { name: 'PPIO', value: 'PPIO', logo: PPIOLogo, platform: 'custom', baseUrl: 'https://api.ppinfra.com/v3/openai' },\n {\n name: 'ModelScope',\n value: 'ModelScope',\n logo: ModelScopeLogo,\n platform: 'custom',\n baseUrl: 'https://api-inference.modelscope.cn/v1',\n },\n {\n name: 'InfiniAI',\n value: 'InfiniAI',\n logo: InfiniAILogo,\n platform: 'custom',\n baseUrl: 'https://cloud.infini-ai.com/maas/v1',\n },\n { name: 'Ctyun', value: 'Ctyun', logo: CtyunLogo, platform: 'custom', baseUrl: 'https://wishub-x1.ctyun.cn/v1' },\n { name: 'StepFun', value: 'StepFun', logo: StepFunLogo, platform: 'custom', baseUrl: 'https://api.stepfun.com/v1' },\n];\n\n/**\n * New API 协议选项\n * New API protocol options for per-model protocol configuration\n */\nexport const NEW_API_PROTOCOL_OPTIONS = [\n { label: 'OpenAI', value: 'openai' },\n { label: 'Gemini', value: 'gemini' },\n { label: 'Anthropic', value: 'anthropic' },\n];\n\n/**\n * 根据模型名称自动推断 New API 协议类型\n * Auto-detect New API protocol type based on model name\n */\nexport const detectNewApiProtocol = (modelName: string): string => {\n const name = modelName.toLowerCase();\n if (name.startsWith('claude') || name.startsWith('anthropic')) return 'anthropic';\n if (name.startsWith('gemini') || name.startsWith('models/gemini')) return 'gemini';\n // Default to openai (covers gpt, deepseek, qwen, o1, o3, etc.)\n return 'openai';\n};\n\n// ============ 工具函数 / Utility Functions ============\n\n/**\n * 根据 value 获取平台配置\n * Get platform config by value\n */\nexport const getPlatformByValue = (value: string): PlatformConfig | undefined => {\n return MODEL_PLATFORMS.find((p) => p.value === value);\n};\n\n/**\n * 获取所有预设供应商(有 baseUrl 的)\n * Get all preset providers (with baseUrl)\n */\nexport const getPresetProviders = (): PlatformConfig[] => {\n return MODEL_PLATFORMS.filter((p) => p.baseUrl);\n};\n\n/**\n * 获取官方 Gemini 平台\n * Get official Gemini platforms\n */\nexport const getGeminiPlatforms = (): PlatformConfig[] => {\n return MODEL_PLATFORMS.filter((p) => p.platform === 'gemini' || p.platform === 'gemini-vertex-ai');\n};\n\n/**\n * 检查平台是否为 Gemini 类型\n * Check if platform is Gemini type\n */\nexport const isGeminiPlatform = (platform: PlatformType): boolean => {\n return platform === 'gemini' || platform === 'gemini-vertex-ai';\n};\n\n/**\n * 检查是否为自定义选项(无预设 baseUrl)\n * Check if it's custom option (no preset baseUrl)\n */\nexport const isCustomOption = (value: string): boolean => {\n const platform = getPlatformByValue(value);\n return value === 'custom' && !platform?.baseUrl;\n};\n\n// Re-export from common for renderer convenience\nexport { isNewApiPlatform } from '@/common/utils/platformConstants';\n\n/**\n * 根据名称搜索平台(不区分大小写)\n * Search platforms by name (case-insensitive)\n */\nexport const searchPlatformsByName = (keyword: string): PlatformConfig[] => {\n const lowerKeyword = keyword.toLowerCase();\n return MODEL_PLATFORMS.filter((p) => p.name.toLowerCase().includes(lowerKeyword));\n};\n"}}, "extensions/minimax/web-search-contract-api.ts": {"f8e9982f62ba0222b57d1a8ea2ccf45ca2da9e27": {"t": 1785674021.1499662, "n": 1062, "h": "992bd1bf217d34c2", "c": "import {\n createWebSearchProviderContractFields,\n type WebSearchProviderPlugin,\n} from \"godseye/plugin-sdk/provider-web-search-config-contract\";\n\nconst MINIMAX_CODING_PLAN_ENV_VARS = [\"MINIMAX_CODE_PLAN_KEY\", \"MINIMAX_CODING_API_KEY\"] as const;\n\nexport function createMiniMaxWebSearchProvider(): WebSearchProviderPlugin {\n const credentialPath = \"plugins.entries.minimax.config.webSearch.apiKey\";\n\n return {\n id: \"minimax\",\n label: \"MiniMax Search\",\n hint: \"Structured results via MiniMax Coding Plan search API\",\n credentialLabel: \"MiniMax Coding Plan key\",\n envVars: [...MINIMAX_CODING_PLAN_ENV_VARS],\n placeholder: \"sk-cp-...\",\n signupUrl: \"https://platform.minimax.io/user-center/basic-information/interface-key\",\n docsUrl: \"https://docs.openclaw.ai/tools/minimax-search\",\n autoDetectOrder: 15,\n credentialPath,\n ...createWebSearchProviderContractFields({\n credentialPath,\n searchCredential: { type: \"top-level\" },\n configuredCredential: { pluginId: \"minimax\" },\n }),\n createTool: () => null,\n };\n}\n"}}, "extensions/minimax/src/minimax-web-search-provider.ts": {"f8e9982f62ba0222b57d1a8ea2ccf45ca2da9e27": {"t": 1785674023.276232, "n": 9972, "h": "f57772513fb75838", "c": "import { Type } from \"@sinclair/typebox\";\nimport {\n DEFAULT_SEARCH_COUNT,\n MAX_SEARCH_COUNT,\n buildSearchCacheKey,\n formatCliCommand,\n mergeScopedSearchConfig,\n readCachedSearchPayload,\n readConfiguredSecretString,\n readNumberParam,\n readProviderEnvValue,\n readStringParam,\n resolveProviderWebSearchPluginConfig,\n resolveSearchCacheTtlMs,\n resolveSearchCount,\n resolveSearchTimeoutSeconds,\n resolveSiteName,\n setProviderWebSearchPluginConfigValue,\n setTopLevelCredentialValue,\n withTrustedWebSearchEndpoint,\n wrapWebContent,\n writeCachedSearchPayload,\n type SearchConfigRecord,\n type WebSearchProviderPlugin,\n type WebSearchProviderToolDefinition,\n} from \"godseye/plugin-sdk/provider-web-search\";\nimport { normalizeOptionalString } from \"godseye/plugin-sdk/text-runtime\";\n\nconst MINIMAX_SEARCH_ENDPOINT_GLOBAL = \"https://api.minimax.io/v1/coding_plan/search\";\nconst MINIMAX_SEARCH_ENDPOINT_CN = \"https://api.minimaxi.com/v1/coding_plan/search\";\nconst MINIMAX_CODING_PLAN_ENV_VARS = [\"MINIMAX_CODE_PLAN_KEY\", \"MINIMAX_CODING_API_KEY\"] as const;\n\ntype MiniMaxSearchResult = {\n title?: string;\n link?: string;\n snippet?: string;\n date?: string;\n};\n\ntype MiniMaxRelatedSearch = {\n query?: string;\n};\n\ntype MiniMaxSearchResponse = {\n organic?: MiniMaxSearchResult[];\n related_searches?: MiniMaxRelatedSearch[];\n base_resp?: {\n status_code?: number;\n status_msg?: string;\n };\n};\n\nfunction resolveMiniMaxApiKey(searchConfig?: SearchConfigRecord): string | undefined {\n return (\n readConfiguredSecretString(searchConfig?.apiKey, \"tools.web.search.apiKey\") ??\n readProviderEnvValue([...MINIMAX_CODING_PLAN_ENV_VARS, \"MINIMAX_API_KEY\"])\n );\n}\n\nfunction isMiniMaxCnHost(value: string | undefined): boolean {\n const trimmed = normalizeOptionalString(value);\n if (!trimmed) {\n return false;\n }\n try {\n return new URL(trimmed).hostname.endsWith(\"minimaxi.com\");\n } catch {\n return trimmed.includes(\"minimaxi.com\");\n }\n}\n\nfunction resolveMiniMaxRegion(\n searchConfig?: SearchConfigRecord,\n config?: Record<string, unknown>,\n): \"cn\" | \"global\" {\n // 1. Explicit region in search config takes priority\n const minimax =\n typeof searchConfig?.minimax === \"object\" &&\n searchConfig.minimax !== null &&\n !Array.isArray(searchConfig.minimax)\n ? (searchConfig.minimax as Record<string, unknown>)\n : undefined;\n const configuredRegion =\n typeof minimax?.region === \"string\" ? normalizeOptionalString(minimax.region) : undefined;\n if (configuredRegion) {\n return configuredRegion === \"cn\" ? \"cn\" : \"global\";\n }\n\n // 2. Infer from the shared MiniMax host override.\n if (isMiniMaxCnHost(process.env.MINIMAX_API_HOST)) {\n return \"cn\";\n }\n\n // 3. Infer from model provider base URL (set by CN onboarding)\n const models = config?.models as Record<string, unknown> | undefined;\n const providers = models?.providers as Record<string, unknown> | undefined;\n const minimaxProvider = providers?.minimax as Record<string, unknown> | undefined;\n const portalProvider = providers?.[\"minimax-portal\"] as Record<string, unknown> | undefined;\n const baseUrl = typeof minimaxProvider?.baseUrl === \"string\" ? minimaxProvider.baseUrl : \"\";\n const portalBaseUrl = typeof portalProvider?.baseUrl === \"string\" ? portalProvider.baseUrl : \"\";\n if (isMiniMaxCnHost(baseUrl) || isMiniMaxCnHost(portalBaseUrl)) {\n return \"cn\";\n }\n\n return \"global\";\n}\n\nfunction resolveMiniMaxEndpoint(\n searchConfig?: SearchConfigRecord,\n config?: Record<string, unknown>,\n): string {\n return resolveMiniMaxRegion(searchConfig, config) === \"cn\"\n ? MINIMAX_SEARCH_ENDPOINT_CN\n : MINIMAX_SEARCH_ENDPOINT_GLOBAL;\n}\n\nasync function runMiniMaxSearch(params: {\n query: string;\n count: number;\n apiKey: string;\n endpoint: string;\n timeoutSeconds: number;\n}): Promise<{\n results: Array<Record<string, unknown>>;\n relatedSearches?: string[];\n}> {\n return withTrustedWebSearchEndpoint(\n {\n url: params.endpoint,\n timeoutSeconds: params.timeoutSeconds,\n init: {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${params.apiKey}`,\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: JSON.stringify({ q: params.query }),\n },\n },\n async (res) => {\n if (!res.ok) {\n const detail = await res.text();\n throw new Error(`MiniMax Search API error (${res.status}): ${detail || res.statusText}`);\n }\n\n const data = (await res.json()) as MiniMaxSearchResponse;\n\n if (data.base_resp?.status_code && data.base_resp.status_code !== 0) {\n throw new Error(\n `MiniMax Search API error (${data.base_resp.status_code}): ${data.base_resp.status_msg || \"unknown error\"}`,\n );\n }\n\n const organic = Array.isArray(data.organic) ? data.organic : [];\n const results = organic.slice(0, params.count).map((entry) => {\n const title = entry.title ?? \"\";\n const url = entry.link ?? \"\";\n const snippet = entry.snippet ?? \"\";\n return {\n title: title ? wrapWebContent(title, \"web_search\") : \"\",\n url,\n description: snippet ? wrapWebContent(snippet, \"web_search\") : \"\",\n published: entry.date || undefined,\n siteName: resolveSiteName(url) || undefined,\n };\n });\n\n const relatedSearches = Array.isArray(data.related_searches)\n ? data.related_searches\n .map((r) => r.query)\n .filter((q): q is string => typeof q === \"string\" && q.length > 0)\n .map((q) => wrapWebContent(q, \"web_search\"))\n : undefined;\n\n return { results, relatedSearches };\n },\n );\n}\n\nconst MiniMaxSearchSchema = Type.Object({\n query: Type.String({ description: \"Search query string.\" }),\n count: Type.Optional(\n Type.Number({\n description: \"Number of results to return (1-10).\",\n minimum: 1,\n maximum: MAX_SEARCH_COUNT,\n }),\n ),\n});\n\nfunction missingMiniMaxKeyPayload() {\n return {\n error: \"missing_minimax_api_key\",\n message: `web_search (minimax) needs a MiniMax Coding Plan key. Run \\`${formatCliCommand(\"openclaw configure --section web\")}\\` to store it, or set MINIMAX_CODE_PLAN_KEY, MINIMAX_CODING_API_KEY, or MINIMAX_API_KEY in the Gateway environment.`,\n docs: \"https://docs.openclaw.ai/tools/web\",\n };\n}\n\nfunction createMiniMaxToolDefinition(\n searchConfig?: SearchConfigRecord,\n config?: Record<string, unknown>,\n): WebSearchProviderToolDefinition {\n return {\n description:\n \"Search the web using MiniMax Search API. Returns titles, URLs, snippets, and related search suggestions.\",\n parameters: MiniMaxSearchSchema,\n execute: async (args) => {\n const apiKey = resolveMiniMaxApiKey(searchConfig);\n if (!apiKey) {\n return missingMiniMaxKeyPayload();\n }\n\n const params = args;\n const query = readStringParam(params, \"query\", { required: true });\n const count =\n readNumberParam(params, \"count\", { integer: true }) ??\n searchConfig?.maxResults ??\n undefined;\n\n const resolvedCount = resolveSearchCount(count, DEFAULT_SEARCH_COUNT);\n const endpoint = resolveMiniMaxEndpoint(searchConfig, config);\n\n const cacheKey = buildSearchCacheKey([\"minimax\", endpoint, query, resolvedCount]);\n const cached = readCachedSearchPayload(cacheKey);\n if (cached) {\n return cached;\n }\n\n const start = Date.now();\n const timeoutSeconds = resolveSearchTimeoutSeconds(searchConfig);\n const cacheTtlMs = resolveSearchCacheTtlMs(searchConfig);\n\n const { results, relatedSearches } = await runMiniMaxSearch({\n query,\n count: resolvedCount,\n apiKey,\n endpoint,\n timeoutSeconds,\n });\n\n const payload: Record<string, unknown> = {\n query,\n provider: \"minimax\",\n count: results.length,\n tookMs: Date.now() - start,\n externalContent: {\n untrusted: true,\n source: \"web_search\",\n provider: \"minimax\",\n wrapped: true,\n },\n results,\n };\n\n if (relatedSearches && relatedSearches.length > 0) {\n payload.relatedSearches = relatedSearches;\n }\n\n writeCachedSearchPayload(cacheKey, payload, cacheTtlMs);\n return payload;\n },\n };\n}\n\nexport const __testing = {\n MINIMAX_SEARCH_ENDPOINT_GLOBAL,\n MINIMAX_SEARCH_ENDPOINT_CN,\n resolveMiniMaxApiKey,\n resolveMiniMaxEndpoint,\n resolveMiniMaxRegion,\n} as const;\n\nexport function createMiniMaxWebSearchProvider(): WebSearchProviderPlugin {\n return {\n id: \"minimax\",\n label: \"MiniMax Search\",\n hint: \"Structured results via MiniMax Coding Plan search API\",\n credentialLabel: \"MiniMax Coding Plan key\",\n envVars: [...MINIMAX_CODING_PLAN_ENV_VARS],\n placeholder: \"sk-cp-...\",\n signupUrl: \"https://platform.minimax.io/user-center/basic-information/interface-key\",\n docsUrl: \"https://docs.openclaw.ai/tools/minimax-search\",\n autoDetectOrder: 15,\n credentialPath: \"plugins.entries.minimax.config.webSearch.apiKey\",\n inactiveSecretPaths: [\"plugins.entries.minimax.config.webSearch.apiKey\"],\n getCredentialValue: (searchConfig) => searchConfig?.apiKey,\n setCredentialValue: setTopLevelCredentialValue,\n getConfiguredCredentialValue: (config) =>\n resolveProviderWebSearchPluginConfig(config, \"minimax\")?.apiKey,\n setConfiguredCredentialValue: (configTarget, value) => {\n setProviderWebSearchPluginConfigValue(configTarget, \"minimax\", \"apiKey\", value);\n },\n createTool: (ctx) =>\n createMiniMaxToolDefinition(\n mergeScopedSearchConfig(\n ctx.searchConfig as SearchConfigRecord | undefined,\n \"minimax\",\n resolveProviderWebSearchPluginConfig(ctx.config, \"minimax\"),\n { mirrorApiKeyToTopLevel: true },\n ) as SearchConfigRecord | undefined,\n ctx.config as Record<string, unknown> | undefined,\n ),\n };\n}\n"}}, "extensions/together/godseye.plugin.json": {"f8e9982f62ba0222b57d1a8ea2ccf45ca2da9e27": {"t": 1785674487.6677961, "n": 765, "h": "42a527b6f7207d64", "c": "{\n \"id\": \"together\",\n \"enabledByDefault\": true,\n \"providers\": [\"together\"],\n \"providerAuthEnvVars\": {\n \"together\": [\"TOGETHER_API_KEY\"]\n },\n \"providerAuthChoices\": [\n {\n \"provider\": \"together\",\n \"method\": \"api-key\",\n \"choiceId\": \"together-api-key\",\n \"choiceLabel\": \"Together AI API key\",\n \"groupId\": \"together\",\n \"groupLabel\": \"Together AI\",\n \"groupHint\": \"API key\",\n \"optionKey\": \"togetherApiKey\",\n \"cliFlag\": \"--together-api-key\",\n \"cliOption\": \"--together-api-key <key>\",\n \"cliDescription\": \"Together AI API key\"\n }\n ],\n \"contracts\": {\n \"videoGenerationProviders\": [\"together\"]\n },\n \"configSchema\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {}\n }\n}\n"}}, "docs/providers/mistral.md": {"f8e9982f62ba0222b57d1a8ea2ccf45ca2da9e27": {"t": 1785674507.6019387, "n": 1381, "h": "940a53cfa0858788", "c": "---\nsummary: \"Use Mistral models and Voxtral transcription with Gods Eye\"\nread_when:\n - You want to use Mistral models in Gods Eye\n - You need Mistral API key onboarding and model refs\ntitle: \"Mistral\"\n---\n\n# Mistral\n\nGods Eye supports Mistral for both text/image model routing (`mistral/...`) and\naudio transcription via Voxtral in media understanding.\nMistral can also be used for memory embeddings (`memorySearch.provider = \"mistral\"`).\n\n## CLI setup\n\n```bash\ngodseye onboard --auth-choice mistral-api-key\n# or non-interactive\ngodseye onboard --mistral-api-key \"$MISTRAL_API_KEY\"\n```\n\n## Config snippet (LLM provider)\n\n```json5\n{\n env: { MISTRAL_API_KEY: \"sk-...\" },\n agents: { defaults: { model: { primary: \"mistral/mistral-large-latest\" } } },\n}\n```\n\n## Config snippet (audio transcription with Voxtral)\n\n```json5\n{\n tools: {\n media: {\n audio: {\n enabled: true,\n models: [{ provider: \"mistral\", model: \"voxtral-mini-latest\" }],\n },\n },\n },\n}\n```\n\n## Notes\n\n- Mistral auth uses `MISTRAL_API_KEY`.\n- Provider base URL defaults to `https://api.mistral.ai/v1`.\n- Onboarding default model is `mistral/mistral-large-latest`.\n- Media-understanding default audio model for Mistral is `voxtral-mini-latest`.\n- Media transcription path uses `/v1/audio/transcriptions`.\n- Memory embeddings path uses `/v1/embeddings` (default model: `mistral-embed`).\n"}}}} |