mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-31 08:29:07 +08:00
Merge branch 'main' of github.com:CherryHQ/cherry-studio into v2
This commit is contained in:
commit
182ac3bc98
5
.vscode/extensions.json
vendored
5
.vscode/extensions.json
vendored
@ -3,7 +3,10 @@
|
||||
"dbaeumer.vscode-eslint",
|
||||
"editorconfig.editorconfig",
|
||||
"lokalise.i18n-ally",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"vitest.explorer",
|
||||
"oxc.oxc-vscode",
|
||||
"biomejs.biome"
|
||||
"biomejs.biome",
|
||||
"typescriptteam.native-preview"
|
||||
]
|
||||
}
|
||||
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -48,5 +48,6 @@
|
||||
"search.exclude": {
|
||||
"**/dist/**": true,
|
||||
".yarn/releases/**": true
|
||||
}
|
||||
},
|
||||
"typescript.experimental.useTsgo": true
|
||||
}
|
||||
|
||||
@ -5,3 +5,5 @@ httpTimeout: 300000
|
||||
nodeLinker: node-modules
|
||||
|
||||
yarnPath: .yarn/releases/yarn-4.9.1.cjs
|
||||
npmRegistryServer: https://registry.npmjs.org
|
||||
npmPublishRegistry: https://registry.npmjs.org
|
||||
|
||||
@ -9,6 +9,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
- **Prerequisites**: Node.js v22.x.x or higher, Yarn 4.9.1
|
||||
- **Setup Yarn**: `corepack enable && corepack prepare yarn@4.9.1 --activate`
|
||||
- **Install Dependencies**: `yarn install`
|
||||
- **Add New Dependencies**: `yarn add -D` for renderer-specific dependencies, `yarn add` for others.
|
||||
|
||||
### Development
|
||||
|
||||
|
||||
23
package.json
23
package.json
@ -48,8 +48,8 @@
|
||||
"analyze:renderer": "VISUALIZER_RENDERER=true yarn build",
|
||||
"analyze:main": "VISUALIZER_MAIN=true yarn build",
|
||||
"typecheck": "concurrently -n \"node,web\" -c \"cyan,magenta\" \"npm run typecheck:node\" \"npm run typecheck:web\"",
|
||||
"typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
|
||||
"typecheck:web": "tsc --noEmit -p tsconfig.web.json --composite false",
|
||||
"typecheck:node": "tsgo --noEmit -p tsconfig.node.json --composite false",
|
||||
"typecheck:web": "tsgo --noEmit -p tsconfig.web.json --composite false",
|
||||
"check:i18n": "tsx scripts/check-i18n.ts",
|
||||
"sync:i18n": "tsx scripts/sync-i18n.ts",
|
||||
"update:i18n": "dotenv -e .env -- tsx scripts/update-i18n.ts",
|
||||
@ -70,7 +70,10 @@
|
||||
"format:check": "biome format && biome lint",
|
||||
"prepare": "git config blame.ignoreRevsFile .git-blame-ignore-revs && husky",
|
||||
"claude": "dotenv -e .env -- claude",
|
||||
"migrations:generate": "drizzle-kit generate --config ./migrations/sqlite-drizzle.config.ts"
|
||||
"migrations:generate": "drizzle-kit generate --config ./migrations/sqlite-drizzle.config.ts",
|
||||
"release:aicore:alpha": "yarn workspace @cherrystudio/ai-core version prerelease --immediate && yarn workspace @cherrystudio/ai-core npm publish --tag alpha --access public",
|
||||
"release:aicore:beta": "yarn workspace @cherrystudio/ai-core version prerelease --immediate && yarn workspace @cherrystudio/ai-core npm publish --tag beta --access public",
|
||||
"release:aicore": "yarn workspace @cherrystudio/ai-core version patch --immediate && yarn workspace @cherrystudio/ai-core npm publish --access public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@libsql/client": "0.14.0",
|
||||
@ -95,10 +98,10 @@
|
||||
"@agentic/exa": "^7.3.3",
|
||||
"@agentic/searxng": "^7.3.3",
|
||||
"@agentic/tavily": "^7.3.3",
|
||||
"@ai-sdk/amazon-bedrock": "^3.0.0",
|
||||
"@ai-sdk/google-vertex": "^3.0.25",
|
||||
"@ai-sdk/mistral": "^2.0.0",
|
||||
"@ai-sdk/perplexity": "^2.0.8",
|
||||
"@ai-sdk/amazon-bedrock": "^3.0.21",
|
||||
"@ai-sdk/google-vertex": "^3.0.27",
|
||||
"@ai-sdk/mistral": "^2.0.14",
|
||||
"@ai-sdk/perplexity": "^2.0.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",
|
||||
@ -106,7 +109,7 @@
|
||||
"@aws-sdk/client-bedrock-runtime": "^3.840.0",
|
||||
"@aws-sdk/client-s3": "^3.840.0",
|
||||
"@biomejs/biome": "2.2.4",
|
||||
"@cherrystudio/ai-core": "workspace:*",
|
||||
"@cherrystudio/ai-core": "workspace:^1.0.0-alpha.16",
|
||||
"@cherrystudio/embedjs": "^0.1.31",
|
||||
"@cherrystudio/embedjs-libsql": "^0.1.31",
|
||||
"@cherrystudio/embedjs-loader-csv": "^0.1.31",
|
||||
@ -202,6 +205,7 @@
|
||||
"@types/tinycolor2": "^1",
|
||||
"@types/turndown": "^5.0.5",
|
||||
"@types/word-extractor": "^1",
|
||||
"@typescript/native-preview": "latest",
|
||||
"@uiw/codemirror-extensions-langs": "^4.25.1",
|
||||
"@uiw/codemirror-themes-all": "^4.25.1",
|
||||
"@uiw/react-codemirror": "^4.25.1",
|
||||
@ -213,7 +217,7 @@
|
||||
"@viz-js/lang-dot": "^1.0.5",
|
||||
"@viz-js/viz": "^3.14.0",
|
||||
"@xyflow/react": "^12.4.4",
|
||||
"ai": "^5.0.38",
|
||||
"ai": "^5.0.44",
|
||||
"antd": "patch:antd@npm%3A5.27.0#~/.yarn/patches/antd-npm-5.27.0-aa91c36546.patch",
|
||||
"archiver": "^7.0.1",
|
||||
"async-mutex": "^0.5.0",
|
||||
@ -235,6 +239,7 @@
|
||||
"diff": "^8.0.2",
|
||||
"docx": "^9.0.2",
|
||||
"dompurify": "^3.2.6",
|
||||
"dotenv": "^17.2.2",
|
||||
"dotenv-cli": "^7.4.2",
|
||||
"drizzle-kit": "^0.31.4",
|
||||
"drizzle-orm": "^0.44.2",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@cherrystudio/ai-core",
|
||||
"version": "1.0.0-alpha.14",
|
||||
"version": "1.0.0-alpha.16",
|
||||
"description": "Cherry Studio AI Core - Unified AI Provider Interface Based on Vercel AI SDK",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs",
|
||||
@ -13,7 +13,15 @@
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest"
|
||||
},
|
||||
"keywords": ["ai", "sdk", "openai", "anthropic", "google", "cherry-studio", "vercel-ai-sdk"],
|
||||
"keywords": [
|
||||
"ai",
|
||||
"sdk",
|
||||
"openai",
|
||||
"anthropic",
|
||||
"google",
|
||||
"cherry-studio",
|
||||
"vercel-ai-sdk"
|
||||
],
|
||||
"author": "Cherry Studio",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@ -28,15 +36,15 @@
|
||||
"ai": "^5.0.26"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "^2.0.5",
|
||||
"@ai-sdk/azure": "^2.0.16",
|
||||
"@ai-sdk/deepseek": "^1.0.9",
|
||||
"@ai-sdk/google": "^2.0.13",
|
||||
"@ai-sdk/openai": "^2.0.26",
|
||||
"@ai-sdk/openai-compatible": "^1.0.9",
|
||||
"@ai-sdk/anthropic": "^2.0.17",
|
||||
"@ai-sdk/azure": "^2.0.30",
|
||||
"@ai-sdk/deepseek": "^1.0.17",
|
||||
"@ai-sdk/google": "^2.0.14",
|
||||
"@ai-sdk/openai": "^2.0.30",
|
||||
"@ai-sdk/openai-compatible": "^1.0.17",
|
||||
"@ai-sdk/provider": "^2.0.0",
|
||||
"@ai-sdk/provider-utils": "^3.0.4",
|
||||
"@ai-sdk/xai": "^2.0.9",
|
||||
"@ai-sdk/provider-utils": "^3.0.9",
|
||||
"@ai-sdk/xai": "^2.0.18",
|
||||
"zod": "^4.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -48,7 +56,9 @@
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"files": ["dist"],
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
|
||||
@ -14,11 +14,10 @@ import { SpanEntity, TokenUsage } from '@mcp-trace/trace-core'
|
||||
import { MIN_WINDOW_HEIGHT, MIN_WINDOW_WIDTH } from '@shared/config/constant'
|
||||
import { UpgradeChannel } from '@shared/data/preference/preferenceTypes'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import { FileMetadata, OcrProvider, Provider, Shortcut, SupportedOcrFile } from '@types'
|
||||
import { FileMetadata, Notification, OcrProvider, Provider, Shortcut, SupportedOcrFile } from '@types'
|
||||
import checkDiskSpace from 'check-disk-space'
|
||||
import { BrowserWindow, dialog, ipcMain, ProxyConfig, session, shell, systemPreferences, webContents } from 'electron'
|
||||
import fontList from 'font-list'
|
||||
import { Notification } from 'src/renderer/src/types/notification'
|
||||
|
||||
import { apiServerService } from './services/ApiServerService'
|
||||
import appService from './services/AppService'
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Notification } from '@types'
|
||||
import { Notification as ElectronNotification } from 'electron'
|
||||
import { Notification } from 'src/renderer/src/types/notification'
|
||||
|
||||
import { windowService } from './WindowService'
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ import type {
|
||||
} from '@shared/data/preference/preferenceTypes'
|
||||
import { UpgradeChannel } from '@shared/data/preference/preferenceTypes'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import type { Notification } from '@types'
|
||||
import {
|
||||
AddMemoryOptions,
|
||||
AssistantMessage,
|
||||
@ -33,7 +34,6 @@ import {
|
||||
WebDavConfig
|
||||
} from '@types'
|
||||
import { contextBridge, ipcRenderer, OpenDialogOptions, shell, webUtils } from 'electron'
|
||||
import { Notification } from 'src/renderer/src/types/notification'
|
||||
import { CreateDirectoryOptions } from 'webdav'
|
||||
|
||||
export function tracedInvoke(channel: string, spanContext: SpanContext | undefined, ...args: any[]) {
|
||||
|
||||
@ -18,7 +18,7 @@ import {
|
||||
import { getAssistantSettings, getDefaultModel } from '@renderer/services/AssistantService'
|
||||
import { type Assistant, type MCPTool, type Provider } from '@renderer/types'
|
||||
import type { StreamTextParams } from '@renderer/types/aiCoreTypes'
|
||||
import type { ModelMessage } from 'ai'
|
||||
import type { ModelMessage, Tool } from 'ai'
|
||||
import { stepCountIs } from 'ai'
|
||||
|
||||
import { getAiSdkProviderId } from '../provider/factory'
|
||||
@ -29,6 +29,8 @@ import { getTemperature, getTopP } from './modelParameters'
|
||||
|
||||
const logger = loggerService.withContext('parameterBuilder')
|
||||
|
||||
type ProviderDefinedTool = Extract<Tool<any, any>, { type: 'provider-defined' }>
|
||||
|
||||
/**
|
||||
* 构建 AI SDK 流式参数
|
||||
* 这是主要的参数构建函数,整合所有转换逻辑
|
||||
@ -113,9 +115,9 @@ export async function buildStreamTextParams(
|
||||
tools = {}
|
||||
}
|
||||
if (aiSdkProviderId === 'google-vertex') {
|
||||
tools.google_search = vertex.tools.googleSearch({})
|
||||
tools.google_search = vertex.tools.googleSearch({}) as ProviderDefinedTool
|
||||
} else if (aiSdkProviderId === 'google-vertex-anthropic') {
|
||||
tools.web_search = vertexAnthropic.tools.webSearch_20250305({})
|
||||
tools.web_search = vertexAnthropic.tools.webSearch_20250305({}) as ProviderDefinedTool
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,7 +126,7 @@ export async function buildStreamTextParams(
|
||||
if (!tools) {
|
||||
tools = {}
|
||||
}
|
||||
tools.url_context = vertex.tools.urlContext({})
|
||||
tools.url_context = vertex.tools.urlContext({}) as ProviderDefinedTool
|
||||
}
|
||||
|
||||
// 构建基础参数
|
||||
|
||||
@ -9,7 +9,7 @@ import { JSONSchema7 } from 'json-schema'
|
||||
const logger = loggerService.withContext('MCP-utils')
|
||||
|
||||
// Setup tools configuration based on provided parameters
|
||||
export function setupToolsConfig(mcpTools?: MCPTool[]): Record<string, Tool> | undefined {
|
||||
export function setupToolsConfig(mcpTools?: MCPTool[]): Record<string, Tool<any, any>> | undefined {
|
||||
let tools: ToolSet = {}
|
||||
|
||||
if (!mcpTools?.length) {
|
||||
|
||||
@ -121,6 +121,7 @@
|
||||
border-radius: 5px;
|
||||
word-break: keep-all;
|
||||
white-space: pre;
|
||||
text-wrap: wrap;
|
||||
}
|
||||
|
||||
.markdown code {
|
||||
|
||||
@ -53,6 +53,7 @@
|
||||
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--sidebar-border: oklch(0.92 0.004 286.32);
|
||||
--sidebar-ring: oklch(0.705 0.015 286.067);
|
||||
--icon: #00000099;
|
||||
}
|
||||
|
||||
.dark {
|
||||
@ -87,6 +88,7 @@
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.552 0.016 285.938);
|
||||
--icon: #ffffff99;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
@ -128,6 +130,7 @@
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--animate-marquee: marquee var(--duration) infinite linear;
|
||||
--animate-marquee-vertical: marquee-vertical var(--duration) linear infinite;
|
||||
--color-icon: var(--icon);
|
||||
@keyframes marquee {
|
||||
from {
|
||||
transform: translateX(0);
|
||||
|
||||
30
src/renderer/src/components/Buttons/ActionIconButton.tsx
Normal file
30
src/renderer/src/components/Buttons/ActionIconButton.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import { cn } from '@heroui/react'
|
||||
import { Button, ButtonProps } from 'antd'
|
||||
import React, { memo } from 'react'
|
||||
|
||||
interface ActionIconButtonProps extends ButtonProps {
|
||||
children: React.ReactNode
|
||||
active?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple action button rendered as an icon
|
||||
*/
|
||||
const ActionIconButton: React.FC<ActionIconButtonProps> = ({ children, active = false, className, ...props }) => {
|
||||
return (
|
||||
<Button
|
||||
type="text"
|
||||
shape="circle"
|
||||
className={cn(
|
||||
'flex h-[30px] w-[30px] cursor-pointer flex-row items-center justify-center border-none p-0 text-base transition-all duration-300 ease-in-out [&_.anticon]:text-icon [&_.icon-a-addchat]:mb-[-2px] [&_.icon-a-addchat]:text-lg [&_.icon]:text-icon [&_.iconfont]:text-icon [&_.lucide]:text-icon',
|
||||
active &&
|
||||
'[&_.anticon]:text-primary! [&_.icon]:text-primary! [&_.iconfont]:text-primary! [&_.lucide]:text-primary!',
|
||||
className
|
||||
)}
|
||||
{...props}>
|
||||
{children}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(ActionIconButton)
|
||||
1
src/renderer/src/components/Buttons/index.ts
Normal file
1
src/renderer/src/components/Buttons/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default as ActionIconButton } from './ActionIconButton'
|
||||
@ -1,4 +1,4 @@
|
||||
import { ToolbarButton } from '@renderer/pages/home/Inputbar/Inputbar'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import NarrowLayout from '@renderer/pages/home/Messages/NarrowLayout'
|
||||
import { Tooltip } from 'antd'
|
||||
import { debounce } from 'lodash'
|
||||
@ -364,23 +364,23 @@ export const ContentSearch = React.forwardRef<ContentSearchRef, Props>(
|
||||
<ToolBar>
|
||||
{showUserToggle && (
|
||||
<Tooltip title={t('button.includes_user_questions')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<ToolbarButton type="text" onClick={userOutlinedButtonOnClick}>
|
||||
<ActionIconButton onClick={userOutlinedButtonOnClick}>
|
||||
<User size={18} style={{ color: includeUser ? 'var(--color-link)' : 'var(--color-icon)' }} />
|
||||
</ToolbarButton>
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip title={t('button.case_sensitive')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<ToolbarButton type="text" onClick={caseSensitiveButtonOnClick}>
|
||||
<ActionIconButton onClick={caseSensitiveButtonOnClick}>
|
||||
<CaseSensitive
|
||||
size={18}
|
||||
style={{ color: isCaseSensitive ? 'var(--color-link)' : 'var(--color-icon)' }}
|
||||
/>
|
||||
</ToolbarButton>
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('button.whole_word')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<ToolbarButton type="text" onClick={wholeWordButtonOnClick}>
|
||||
<ActionIconButton onClick={wholeWordButtonOnClick}>
|
||||
<WholeWord size={18} style={{ color: isWholeWord ? 'var(--color-link)' : 'var(--color-icon)' }} />
|
||||
</ToolbarButton>
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
</ToolBar>
|
||||
</InputWrapper>
|
||||
@ -397,15 +397,15 @@ export const ContentSearch = React.forwardRef<ContentSearchRef, Props>(
|
||||
)}
|
||||
</SearchResults>
|
||||
<ToolBar>
|
||||
<ToolbarButton type="text" onClick={prevButtonOnClick} disabled={allRanges.length === 0}>
|
||||
<ActionIconButton onClick={prevButtonOnClick} disabled={allRanges.length === 0}>
|
||||
<ChevronUp size={18} />
|
||||
</ToolbarButton>
|
||||
<ToolbarButton type="text" onClick={nextButtonOnClick} disabled={allRanges.length === 0}>
|
||||
</ActionIconButton>
|
||||
<ActionIconButton onClick={nextButtonOnClick} disabled={allRanges.length === 0}>
|
||||
<ChevronDown size={18} />
|
||||
</ToolbarButton>
|
||||
<ToolbarButton type="text" onClick={closeButtonOnClick}>
|
||||
</ActionIconButton>
|
||||
<ActionIconButton onClick={closeButtonOnClick}>
|
||||
<X size={18} />
|
||||
</ToolbarButton>
|
||||
</ActionIconButton>
|
||||
</ToolBar>
|
||||
</SearchBarContainer>
|
||||
</NarrowLayout>
|
||||
|
||||
@ -1,5 +1,18 @@
|
||||
import React from 'react'
|
||||
|
||||
export enum QuickPanelReservedSymbol {
|
||||
Root = '/',
|
||||
File = 'file',
|
||||
KnowledgeBase = '#',
|
||||
MentionModels = '@',
|
||||
QuickPhrases = 'quick-phrases',
|
||||
Thinking = 'thinking',
|
||||
WebSearch = '?',
|
||||
Mcp = 'mcp',
|
||||
McpPrompt = 'mcp-prompt',
|
||||
McpResource = 'mcp-resource'
|
||||
}
|
||||
|
||||
export type QuickPanelCloseAction = 'enter' | 'click' | 'esc' | 'outsideclick' | 'enter_empty' | string | undefined
|
||||
export type QuickPanelTriggerInfo = {
|
||||
type: 'input' | 'button'
|
||||
|
||||
@ -172,7 +172,7 @@ export function useAssistant(id: string) {
|
||||
(model: Model) => assistant && dispatch(setModel({ assistantId: assistant?.id, model })),
|
||||
[assistant, dispatch]
|
||||
),
|
||||
updateAssistant: (assistant: Assistant) => dispatch(updateAssistant(assistant)),
|
||||
updateAssistant: useCallback((assistant: Partial<Assistant>) => dispatch(updateAssistant(assistant)), [dispatch]),
|
||||
updateAssistantSettings
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,8 +362,9 @@
|
||||
"translate": "Translate to {{target_language}}",
|
||||
"translating": "Translating...",
|
||||
"upload": {
|
||||
"attachment": "Upload attachment",
|
||||
"document": "Upload document file (model does not support images)",
|
||||
"label": "Upload image or document file",
|
||||
"image_or_document": "Upload image or document file",
|
||||
"upload_from_local": "Upload local file..."
|
||||
},
|
||||
"url_context": "URL Context",
|
||||
|
||||
@ -363,8 +363,9 @@
|
||||
"translate": "翻译成 {{target_language}}",
|
||||
"translating": "翻译中...",
|
||||
"upload": {
|
||||
"attachment": "上传附件",
|
||||
"document": "上传文档(模型不支持图片)",
|
||||
"label": "上传图片或文档",
|
||||
"image_or_document": "上传图片或文档",
|
||||
"upload_from_local": "上传本地文件..."
|
||||
},
|
||||
"url_context": "网页上下文",
|
||||
|
||||
@ -362,8 +362,9 @@
|
||||
"translate": "翻譯成 {{target_language}}",
|
||||
"translating": "翻譯中...",
|
||||
"upload": {
|
||||
"attachment": "上傳附件",
|
||||
"document": "上傳文件(模型不支援圖片)",
|
||||
"label": "上傳圖片或文件",
|
||||
"image_or_document": "上傳圖片或文件",
|
||||
"upload_from_local": "上傳本地文件..."
|
||||
},
|
||||
"url_context": "網頁上下文",
|
||||
|
||||
@ -1,12 +1,17 @@
|
||||
import { FileType } from '@renderer/types'
|
||||
import { filterSupportedFiles } from '@renderer/utils/file'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { QuickPanelReservedSymbol, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { useKnowledgeBases } from '@renderer/hooks/useKnowledge'
|
||||
import { FileType, KnowledgeBase, KnowledgeItem } from '@renderer/types'
|
||||
import { filterSupportedFiles, formatFileSize } from '@renderer/utils/file'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Paperclip } from 'lucide-react'
|
||||
import { FC, useCallback, useImperativeHandle, useState } from 'react'
|
||||
import dayjs from 'dayjs'
|
||||
import { FileSearch, FileText, Paperclip, Upload } from 'lucide-react'
|
||||
import { Dispatch, FC, SetStateAction, useCallback, useImperativeHandle, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export interface AttachmentButtonRef {
|
||||
openQuickPanel: () => void
|
||||
openFileSelectDialog: () => void
|
||||
}
|
||||
|
||||
interface Props {
|
||||
@ -14,24 +19,17 @@ interface Props {
|
||||
couldAddImageFile: boolean
|
||||
extensions: string[]
|
||||
files: FileType[]
|
||||
setFiles: (files: FileType[]) => void
|
||||
ToolbarButton: any
|
||||
setFiles: Dispatch<SetStateAction<FileType[]>>
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
const AttachmentButton: FC<Props> = ({
|
||||
ref,
|
||||
couldAddImageFile,
|
||||
extensions,
|
||||
files,
|
||||
setFiles,
|
||||
ToolbarButton,
|
||||
disabled
|
||||
}) => {
|
||||
const AttachmentButton: FC<Props> = ({ ref, couldAddImageFile, extensions, files, setFiles, disabled }) => {
|
||||
const { t } = useTranslation()
|
||||
const quickPanel = useQuickPanel()
|
||||
const { bases: knowledgeBases } = useKnowledgeBases()
|
||||
const [selecting, setSelecting] = useState<boolean>(false)
|
||||
|
||||
const onSelectFile = useCallback(async () => {
|
||||
const openFileSelectDialog = useCallback(async () => {
|
||||
if (selecting) {
|
||||
return
|
||||
}
|
||||
@ -70,23 +68,88 @@ const AttachmentButton: FC<Props> = ({
|
||||
}
|
||||
}, [extensions, files, selecting, setFiles, t])
|
||||
|
||||
const openKnowledgeFileList = useCallback(
|
||||
(base: KnowledgeBase) => {
|
||||
quickPanel.open({
|
||||
title: base.name,
|
||||
list: base.items
|
||||
.filter((file): file is KnowledgeItem => ['file'].includes(file.type))
|
||||
.map((file) => {
|
||||
const fileContent = file.content as FileType
|
||||
return {
|
||||
label: fileContent.origin_name || fileContent.name,
|
||||
description:
|
||||
formatFileSize(fileContent.size) + ' · ' + dayjs(fileContent.created_at).format('YYYY-MM-DD HH:mm'),
|
||||
icon: <FileText />,
|
||||
isSelected: files.some((f) => f.path === fileContent.path),
|
||||
action: async ({ item }) => {
|
||||
item.isSelected = !item.isSelected
|
||||
if (fileContent.path) {
|
||||
setFiles((prevFiles) => {
|
||||
const fileExists = prevFiles.some((f) => f.path === fileContent.path)
|
||||
if (fileExists) {
|
||||
return prevFiles.filter((f) => f.path !== fileContent.path)
|
||||
} else {
|
||||
return fileContent ? [...prevFiles, fileContent] : prevFiles
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
symbol: QuickPanelReservedSymbol.File,
|
||||
multiple: true
|
||||
})
|
||||
},
|
||||
[files, quickPanel, setFiles]
|
||||
)
|
||||
|
||||
const items = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
label: t('chat.input.upload.upload_from_local'),
|
||||
description: '',
|
||||
icon: <Upload />,
|
||||
action: () => openFileSelectDialog()
|
||||
},
|
||||
...knowledgeBases.map((base) => {
|
||||
const length = base.items?.filter(
|
||||
(item): item is KnowledgeItem => ['file', 'note'].includes(item.type) && typeof item.content !== 'string'
|
||||
).length
|
||||
return {
|
||||
label: base.name,
|
||||
description: `${length} ${t('files.count')}`,
|
||||
icon: <FileSearch />,
|
||||
disabled: length === 0,
|
||||
isMenu: true,
|
||||
action: () => openKnowledgeFileList(base)
|
||||
}
|
||||
})
|
||||
]
|
||||
}, [knowledgeBases, openFileSelectDialog, openKnowledgeFileList, t])
|
||||
|
||||
const openQuickPanel = useCallback(() => {
|
||||
onSelectFile()
|
||||
}, [onSelectFile])
|
||||
quickPanel.open({
|
||||
title: t('chat.input.upload.attachment'),
|
||||
list: items,
|
||||
symbol: QuickPanelReservedSymbol.File
|
||||
})
|
||||
}, [items, quickPanel, t])
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
openQuickPanel
|
||||
openQuickPanel,
|
||||
openFileSelectDialog
|
||||
}))
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={couldAddImageFile ? t('chat.input.upload.label') : t('chat.input.upload.document')}
|
||||
title={couldAddImageFile ? t('chat.input.upload.image_or_document') : t('chat.input.upload.document')}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ToolbarButton type="text" onClick={onSelectFile} disabled={disabled}>
|
||||
<Paperclip size={18} style={{ color: files.length ? 'var(--color-primary)' : 'var(--color-icon)' }} />
|
||||
</ToolbarButton>
|
||||
<ActionIconButton onClick={openFileSelectDialog} active={files.length > 0} disabled={disabled}>
|
||||
<Paperclip size={18} />
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { isGenerateImageModel } from '@renderer/config/models'
|
||||
import { Assistant, Model } from '@renderer/types'
|
||||
import { Tooltip } from 'antd'
|
||||
@ -8,11 +9,10 @@ import { useTranslation } from 'react-i18next'
|
||||
interface Props {
|
||||
assistant: Assistant
|
||||
model: Model
|
||||
ToolbarButton: any
|
||||
onEnableGenerateImage: () => void
|
||||
}
|
||||
|
||||
const GenerateImageButton: FC<Props> = ({ model, ToolbarButton, assistant, onEnableGenerateImage }) => {
|
||||
const GenerateImageButton: FC<Props> = ({ model, assistant, onEnableGenerateImage }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
@ -23,9 +23,12 @@ const GenerateImageButton: FC<Props> = ({ model, ToolbarButton, assistant, onEna
|
||||
}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ToolbarButton type="text" disabled={!isGenerateImageModel(model)} onClick={onEnableGenerateImage}>
|
||||
<Image size={18} color={assistant.enableGenerateImage ? 'var(--color-primary)' : 'var(--color-icon)'} />
|
||||
</ToolbarButton>
|
||||
<ActionIconButton
|
||||
onClick={onEnableGenerateImage}
|
||||
active={assistant.enableGenerateImage}
|
||||
disabled={!isGenerateImageModel(model)}>
|
||||
<Image size={18} />
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -2,25 +2,23 @@ import { HolderOutlined } from '@ant-design/icons'
|
||||
import { useCache } from '@data/hooks/useCache'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import { QuickPanelView, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { QuickPanelReservedSymbol, QuickPanelView, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import TranslateButton from '@renderer/components/TranslateButton'
|
||||
import {
|
||||
isAutoEnableImageGenerationModel,
|
||||
isGenerateImageModel,
|
||||
isGenerateImageModels,
|
||||
isMandatoryWebSearchModel,
|
||||
isSupportedReasoningEffortModel,
|
||||
isSupportedThinkingTokenModel,
|
||||
isVisionModel,
|
||||
isVisionModels,
|
||||
isWebSearchModel
|
||||
} from '@renderer/config/models'
|
||||
import db from '@renderer/databases'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useKnowledgeBases } from '@renderer/hooks/useKnowledge'
|
||||
import { useMessageOperations, useTopicLoading } from '@renderer/hooks/useMessageOperations'
|
||||
import { modelGenerating } from '@renderer/hooks/useModel'
|
||||
import { useShortcut, useShortcutDisplay } from '@renderer/hooks/useShortcuts'
|
||||
import { useShortcut } from '@renderer/hooks/useShortcuts'
|
||||
import { useSidebarIconShow } from '@renderer/hooks/useSidebarIcon'
|
||||
import { useTimer } from '@renderer/hooks/useTimer'
|
||||
import useTranslate from '@renderer/hooks/useTranslate'
|
||||
@ -28,7 +26,6 @@ import { getDefaultTopic } from '@renderer/services/AssistantService'
|
||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||
import FileManager from '@renderer/services/FileManager'
|
||||
import { checkRateLimit, getUserMessage } from '@renderer/services/MessagesService'
|
||||
import { getModelUniqId } from '@renderer/services/ModelService'
|
||||
import PasteService from '@renderer/services/PasteService'
|
||||
import { spanManagerService } from '@renderer/services/SpanManagerService'
|
||||
import { estimateTextTokens as estimateTxtTokens, estimateUserPromptUsage } from '@renderer/services/TokenService'
|
||||
@ -36,9 +33,9 @@ import { translateText } from '@renderer/services/TranslateService'
|
||||
import WebSearchService from '@renderer/services/WebSearchService'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import { sendMessage as _sendMessage } from '@renderer/store/thunk/messageThunk'
|
||||
import { Assistant, FileType, FileTypes, KnowledgeBase, KnowledgeItem, Model, Topic } from '@renderer/types'
|
||||
import { Assistant, FileType, KnowledgeBase, Model, Topic } from '@renderer/types'
|
||||
import type { MessageInputBaseParams } from '@renderer/types/newMessage'
|
||||
import { classNames, delay, filterSupportedFiles, formatFileSize } from '@renderer/utils'
|
||||
import { classNames, delay, filterSupportedFiles } from '@renderer/utils'
|
||||
import { formatQuotedText } from '@renderer/utils/formats'
|
||||
import {
|
||||
getFilesFromDropEvent,
|
||||
@ -46,14 +43,12 @@ import {
|
||||
getTextFromDropEvent,
|
||||
isSendMessageKeyPressed
|
||||
} from '@renderer/utils/input'
|
||||
import { isPromptToolUse, isSupportedToolUse } from '@renderer/utils/mcp-tools'
|
||||
import { documentExts, imageExts, textExts } from '@shared/config/constant'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import { Button, Tooltip } from 'antd'
|
||||
import { Tooltip } from 'antd'
|
||||
import TextArea, { TextAreaRef } from 'antd/es/input/TextArea'
|
||||
import dayjs from 'dayjs'
|
||||
import { debounce, isEmpty } from 'lodash'
|
||||
import { CirclePause, FileSearch, FileText, Upload } from 'lucide-react'
|
||||
import { CirclePause } from 'lucide-react'
|
||||
import React, { CSSProperties, FC, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -114,7 +109,6 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
const [textareaHeight, setTextareaHeight] = useState<number>()
|
||||
const startDragY = useRef<number>(0)
|
||||
const startHeight = useRef<number>(0)
|
||||
const { bases: knowledgeBases } = useKnowledgeBases()
|
||||
const [isMultiSelectMode] = useCache('chat.multi_select_mode')
|
||||
const isVisionAssistant = useMemo(() => isVisionModel(model), [model])
|
||||
const isGenerateImageAssistant = useMemo(() => isGenerateImageModel(model), [model])
|
||||
@ -134,11 +128,6 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
[mentionedModels, isGenerateImageAssistant]
|
||||
)
|
||||
|
||||
// 仅允许在不含图片文件时mention非视觉模型
|
||||
const couldMentionNotVisionModel = useMemo(() => {
|
||||
return !files.some((file) => file.type === FileTypes.IMAGE)
|
||||
}, [files])
|
||||
|
||||
// 允许在支持视觉或生成图片时添加图片文件
|
||||
const couldAddImageFile = useMemo(() => {
|
||||
return isVisionSupported || isGenerateImageSupported
|
||||
@ -185,8 +174,6 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
|
||||
const inputTokenCount = showInputEstimatedTokens ? tokenCount : 0
|
||||
|
||||
const newTopicShortcut = useShortcutDisplay('new_topic')
|
||||
const cleanTopicShortcut = useShortcutDisplay('clear_topic')
|
||||
const inputEmpty = isEmpty(text.trim()) && files.length === 0
|
||||
|
||||
_text = text
|
||||
@ -279,72 +266,6 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
}
|
||||
}, [isTranslating, text, getLanguageByLangcode, targetLanguage, setTimeoutTimer, resizeTextArea])
|
||||
|
||||
const openKnowledgeFileList = useCallback(
|
||||
(base: KnowledgeBase) => {
|
||||
quickPanel.open({
|
||||
title: base.name,
|
||||
list: base.items
|
||||
.filter((file): file is KnowledgeItem => ['file'].includes(file.type))
|
||||
.map((file) => {
|
||||
const fileContent = file.content as FileType
|
||||
return {
|
||||
label: fileContent.origin_name || fileContent.name,
|
||||
description:
|
||||
formatFileSize(fileContent.size) + ' · ' + dayjs(fileContent.created_at).format('YYYY-MM-DD HH:mm'),
|
||||
icon: <FileText />,
|
||||
isSelected: files.some((f) => f.path === fileContent.path),
|
||||
action: async ({ item }) => {
|
||||
item.isSelected = !item.isSelected
|
||||
if (fileContent.path) {
|
||||
setFiles((prevFiles) => {
|
||||
const fileExists = prevFiles.some((f) => f.path === fileContent.path)
|
||||
if (fileExists) {
|
||||
return prevFiles.filter((f) => f.path !== fileContent.path)
|
||||
} else {
|
||||
return fileContent ? [...prevFiles, fileContent] : prevFiles
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
symbol: 'file',
|
||||
multiple: true
|
||||
})
|
||||
},
|
||||
[files, quickPanel]
|
||||
)
|
||||
|
||||
const openSelectFileMenu = useCallback(() => {
|
||||
quickPanel.open({
|
||||
title: t('chat.input.upload.label'),
|
||||
list: [
|
||||
{
|
||||
label: t('chat.input.upload.upload_from_local'),
|
||||
description: '',
|
||||
icon: <Upload />,
|
||||
action: () => {
|
||||
inputbarToolsRef.current?.openAttachmentQuickPanel()
|
||||
}
|
||||
},
|
||||
...knowledgeBases.map((base) => {
|
||||
const length = base.items?.filter(
|
||||
(item): item is KnowledgeItem => ['file', 'note'].includes(item.type) && typeof item.content !== 'string'
|
||||
).length
|
||||
return {
|
||||
label: base.name,
|
||||
description: `${length} ${t('files.count')}`,
|
||||
icon: <FileSearch />,
|
||||
disabled: length === 0,
|
||||
isMenu: true,
|
||||
action: () => openKnowledgeFileList(base)
|
||||
}
|
||||
})
|
||||
],
|
||||
symbol: 'file'
|
||||
})
|
||||
}, [knowledgeBases, openKnowledgeFileList, quickPanel, t, inputbarToolsRef])
|
||||
|
||||
const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
// 按下Tab键,自动选中${xxx}
|
||||
if (event.key === 'Tab' && inputFocus) {
|
||||
@ -512,35 +433,31 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
const lastSymbol = newText[cursorPosition - 1]
|
||||
|
||||
// 触发符号为 '/':若当前未打开或符号不同,则切换/打开
|
||||
if (enableQuickPanelTriggers && lastSymbol === '/') {
|
||||
if (quickPanel.isVisible && quickPanel.symbol !== '/') {
|
||||
if (enableQuickPanelTriggers && lastSymbol === QuickPanelReservedSymbol.Root) {
|
||||
if (quickPanel.isVisible && quickPanel.symbol !== QuickPanelReservedSymbol.Root) {
|
||||
quickPanel.close('switch-symbol')
|
||||
}
|
||||
if (!quickPanel.isVisible || quickPanel.symbol !== '/') {
|
||||
if (!quickPanel.isVisible || quickPanel.symbol !== QuickPanelReservedSymbol.Root) {
|
||||
const quickPanelMenu =
|
||||
inputbarToolsRef.current?.getQuickPanelMenu({
|
||||
t,
|
||||
files,
|
||||
couldAddImageFile,
|
||||
text: newText,
|
||||
openSelectFileMenu,
|
||||
translate
|
||||
}) || []
|
||||
|
||||
quickPanel.open({
|
||||
title: t('settings.quickPanel.title'),
|
||||
list: quickPanelMenu,
|
||||
symbol: '/'
|
||||
symbol: QuickPanelReservedSymbol.Root
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 触发符号为 '@':若当前未打开或符号不同,则切换/打开
|
||||
if (enableQuickPanelTriggers && lastSymbol === '@') {
|
||||
if (quickPanel.isVisible && quickPanel.symbol !== '@') {
|
||||
if (enableQuickPanelTriggers && lastSymbol === QuickPanelReservedSymbol.MentionModels) {
|
||||
if (quickPanel.isVisible && quickPanel.symbol !== QuickPanelReservedSymbol.MentionModels) {
|
||||
quickPanel.close('switch-symbol')
|
||||
}
|
||||
if (!quickPanel.isVisible || quickPanel.symbol !== '@') {
|
||||
if (!quickPanel.isVisible || quickPanel.symbol !== QuickPanelReservedSymbol.MentionModels) {
|
||||
inputbarToolsRef.current?.openMentionModelsPanel({
|
||||
type: 'input',
|
||||
position: cursorPosition - 1,
|
||||
@ -549,7 +466,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
}
|
||||
}
|
||||
},
|
||||
[enableQuickPanelTriggers, quickPanel, t, files, couldAddImageFile, openSelectFileMenu, translate]
|
||||
[enableQuickPanelTriggers, quickPanel, t, translate]
|
||||
)
|
||||
|
||||
const onPaste = useCallback(
|
||||
@ -765,11 +682,6 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
setSelectedKnowledgeBases(showKnowledgeIcon ? (assistant.knowledge_bases ?? []) : [])
|
||||
}, [assistant.id, assistant.knowledge_bases, showKnowledgeIcon])
|
||||
|
||||
const handleKnowledgeBaseSelect = (bases?: KnowledgeBase[]) => {
|
||||
updateAssistant({ ...assistant, knowledge_bases: bases })
|
||||
setSelectedKnowledgeBases(bases ?? [])
|
||||
}
|
||||
|
||||
const handleRemoveModel = (model: Model) => {
|
||||
setMentionedModels(mentionedModels.filter((m) => m.id !== model.id))
|
||||
}
|
||||
@ -783,10 +695,6 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
setSelectedKnowledgeBases(newKnowledgeBases ?? [])
|
||||
}
|
||||
|
||||
const onEnableGenerateImage = () => {
|
||||
updateAssistant({ ...assistant, enableGenerateImage: !assistant.enableGenerateImage })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!isWebSearchModel(model) && assistant.enableWebSearch) {
|
||||
updateAssistant({ ...assistant, enableWebSearch: false })
|
||||
@ -806,24 +714,6 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
}
|
||||
}, [assistant, model, updateAssistant])
|
||||
|
||||
const onMentionModel = useCallback(
|
||||
(model: Model) => {
|
||||
// 我想应该没有模型是只支持视觉而不支持文本的?
|
||||
if (isVisionModel(model) || couldMentionNotVisionModel) {
|
||||
setMentionedModels((prev) => {
|
||||
const modelId = getModelUniqId(model)
|
||||
const exists = prev.some((m) => getModelUniqId(m) === modelId)
|
||||
return exists ? prev.filter((m) => getModelUniqId(m) !== modelId) : [...prev, model]
|
||||
})
|
||||
} else {
|
||||
logger.error('Cannot add non-vision model when images are uploaded')
|
||||
}
|
||||
},
|
||||
[couldMentionNotVisionModel]
|
||||
)
|
||||
|
||||
const onClearMentionModels = useCallback(() => setMentionedModels([]), [setMentionedModels])
|
||||
|
||||
const onToggleExpanded = () => {
|
||||
const currentlyExpanded = expanded || !!textareaHeight
|
||||
const shouldExpand = !currentlyExpanded
|
||||
@ -848,8 +738,6 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
}
|
||||
|
||||
const isExpanded = expanded || !!textareaHeight
|
||||
const showThinkingButton = isSupportedThinkingTokenModel(model) || isSupportedReasoningEffortModel(model)
|
||||
const showMcpTools = isSupportedToolUse(assistant) || isPromptToolUse(assistant)
|
||||
|
||||
if (isMultiSelectMode) {
|
||||
return null
|
||||
@ -921,47 +809,38 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
<Toolbar>
|
||||
<InputbarTools
|
||||
ref={inputbarToolsRef}
|
||||
assistant={assistant}
|
||||
assistantId={assistant.id}
|
||||
model={model}
|
||||
files={files}
|
||||
extensions={supportedExts}
|
||||
setFiles={setFiles}
|
||||
showThinkingButton={showThinkingButton}
|
||||
showKnowledgeIcon={showKnowledgeIcon && showMcpTools}
|
||||
showMcpTools={showMcpTools}
|
||||
selectedKnowledgeBases={selectedKnowledgeBases}
|
||||
handleKnowledgeBaseSelect={handleKnowledgeBaseSelect}
|
||||
setText={setText}
|
||||
resizeTextArea={resizeTextArea}
|
||||
mentionModels={mentionedModels}
|
||||
onMentionModel={onMentionModel}
|
||||
onClearMentionModels={onClearMentionModels}
|
||||
couldMentionNotVisionModel={couldMentionNotVisionModel}
|
||||
selectedKnowledgeBases={selectedKnowledgeBases}
|
||||
setSelectedKnowledgeBases={setSelectedKnowledgeBases}
|
||||
mentionedModels={mentionedModels}
|
||||
setMentionedModels={setMentionedModels}
|
||||
couldAddImageFile={couldAddImageFile}
|
||||
onEnableGenerateImage={onEnableGenerateImage}
|
||||
isExpanded={isExpanded}
|
||||
onToggleExpanded={onToggleExpanded}
|
||||
addNewTopic={addNewTopic}
|
||||
clearTopic={clearTopic}
|
||||
onNewContext={onNewContext}
|
||||
newTopicShortcut={newTopicShortcut}
|
||||
cleanTopicShortcut={cleanTopicShortcut}
|
||||
/>
|
||||
<ToolbarMenu>
|
||||
<TokenCount
|
||||
estimateTokenCount={estimateTokenCount}
|
||||
inputTokenCount={inputTokenCount}
|
||||
contextCount={contextCount}
|
||||
ToolbarButton={ToolbarButton}
|
||||
onClick={onNewContext}
|
||||
/>
|
||||
<TranslateButton text={text} onTranslated={onTranslated} isLoading={isTranslating} />
|
||||
<SendMessageButton sendMessage={sendMessage} disabled={inputEmpty} />
|
||||
{loading && (
|
||||
<Tooltip placement="top" title={t('chat.input.pause')} mouseLeaveDelay={0} arrow>
|
||||
<ToolbarButton type="text" onClick={onPause} style={{ marginRight: -2 }}>
|
||||
<ActionIconButton onClick={onPause} style={{ marginRight: -2 }}>
|
||||
<CirclePause size={20} color="var(--color-error)" />
|
||||
</ToolbarButton>
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
</ToolbarMenu>
|
||||
@ -1076,45 +955,4 @@ const ToolbarMenu = styled.div`
|
||||
gap: 6px;
|
||||
`
|
||||
|
||||
export const ToolbarButton = styled(Button)`
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
font-size: 16px;
|
||||
border-radius: 50%;
|
||||
transition: all 0.3s ease;
|
||||
color: var(--color-icon);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
&.anticon,
|
||||
&.iconfont {
|
||||
transition: all 0.3s ease;
|
||||
color: var(--color-icon);
|
||||
}
|
||||
.icon-a-addchat {
|
||||
font-size: 18px;
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--color-background-soft);
|
||||
.anticon,
|
||||
.iconfont {
|
||||
color: var(--color-text-1);
|
||||
}
|
||||
}
|
||||
&.active {
|
||||
background-color: var(--color-primary) !important;
|
||||
.anticon,
|
||||
.iconfont,
|
||||
.chevron-icon {
|
||||
color: var(--color-white-soft);
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default Inputbar
|
||||
|
||||
@ -1,12 +1,26 @@
|
||||
import { DragDropContext, Draggable, Droppable, DropResult } from '@hello-pangea/dnd'
|
||||
import { loggerService } from '@logger'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { QuickPanelListItem } from '@renderer/components/QuickPanel'
|
||||
import { isGeminiModel, isGenerateImageModel, isMandatoryWebSearchModel } from '@renderer/config/models'
|
||||
import {
|
||||
isGeminiModel,
|
||||
isGenerateImageModel,
|
||||
isMandatoryWebSearchModel,
|
||||
isSupportedReasoningEffortModel,
|
||||
isSupportedThinkingTokenModel,
|
||||
isVisionModel
|
||||
} from '@renderer/config/models'
|
||||
import { isSupportUrlContextProvider } from '@renderer/config/providers'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useShortcutDisplay } from '@renderer/hooks/useShortcuts'
|
||||
import { useSidebarIconShow } from '@renderer/hooks/useSidebarIcon'
|
||||
import { getProviderByModel } from '@renderer/services/AssistantService'
|
||||
import { getModelUniqId } from '@renderer/services/ModelService'
|
||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
import { setIsCollapsed, setToolOrder } from '@renderer/store/inputTools'
|
||||
import { Assistant, FileType, KnowledgeBase, Model } from '@renderer/types'
|
||||
import { FileType, FileTypes, KnowledgeBase, Model } from '@renderer/types'
|
||||
import { classNames } from '@renderer/utils'
|
||||
import { isPromptToolUse, isSupportedToolUse } from '@renderer/utils/mcp-tools'
|
||||
import { Divider, Dropdown, Tooltip } from 'antd'
|
||||
import { ItemType } from 'antd/es/menu/interface'
|
||||
import {
|
||||
@ -32,7 +46,6 @@ import styled from 'styled-components'
|
||||
|
||||
import AttachmentButton, { AttachmentButtonRef } from './AttachmentButton'
|
||||
import GenerateImageButton from './GenerateImageButton'
|
||||
import { ToolbarButton } from './Inputbar'
|
||||
import KnowledgeBaseButton, { KnowledgeBaseButtonRef } from './KnowledgeBaseButton'
|
||||
import MCPToolsButton, { MCPToolsButtonRef } from './MCPToolsButton'
|
||||
import MentionModelsButton, { MentionModelsButtonRef } from './MentionModelsButton'
|
||||
@ -42,47 +55,33 @@ import ThinkingButton, { ThinkingButtonRef } from './ThinkingButton'
|
||||
import UrlContextButton, { UrlContextButtonRef } from './UrlContextbutton'
|
||||
import WebSearchButton, { WebSearchButtonRef } from './WebSearchButton'
|
||||
|
||||
const logger = loggerService.withContext('InputbarTools')
|
||||
|
||||
export interface InputbarToolsRef {
|
||||
getQuickPanelMenu: (params: {
|
||||
t: (key: string, options?: any) => string
|
||||
files: FileType[]
|
||||
couldAddImageFile: boolean
|
||||
text: string
|
||||
openSelectFileMenu: () => void
|
||||
translate: () => void
|
||||
}) => QuickPanelListItem[]
|
||||
getQuickPanelMenu: (params: { text: string; translate: () => void }) => QuickPanelListItem[]
|
||||
openMentionModelsPanel: (triggerInfo?: { type: 'input' | 'button'; position?: number; originalText?: string }) => void
|
||||
openAttachmentQuickPanel: () => void
|
||||
}
|
||||
|
||||
export interface InputbarToolsProps {
|
||||
assistant: Assistant
|
||||
assistantId: string
|
||||
model: Model
|
||||
files: FileType[]
|
||||
setFiles: (files: FileType[]) => void
|
||||
setFiles: Dispatch<SetStateAction<FileType[]>>
|
||||
extensions: string[]
|
||||
showThinkingButton: boolean
|
||||
showKnowledgeIcon: boolean
|
||||
showMcpTools: boolean
|
||||
selectedKnowledgeBases: KnowledgeBase[]
|
||||
handleKnowledgeBaseSelect: (bases?: KnowledgeBase[]) => void
|
||||
setText: Dispatch<SetStateAction<string>>
|
||||
resizeTextArea: () => void
|
||||
mentionModels: Model[]
|
||||
onMentionModel: (model: Model) => void
|
||||
onClearMentionModels: () => void
|
||||
couldMentionNotVisionModel: boolean
|
||||
selectedKnowledgeBases: KnowledgeBase[]
|
||||
setSelectedKnowledgeBases: Dispatch<SetStateAction<KnowledgeBase[]>>
|
||||
mentionedModels: Model[]
|
||||
setMentionedModels: Dispatch<SetStateAction<Model[]>>
|
||||
couldAddImageFile: boolean
|
||||
onEnableGenerateImage: () => void
|
||||
isExpanded: boolean
|
||||
onToggleExpanded: () => void
|
||||
|
||||
addNewTopic: () => void
|
||||
clearTopic: () => void
|
||||
onNewContext: () => void
|
||||
|
||||
newTopicShortcut: string
|
||||
cleanTopicShortcut: string
|
||||
}
|
||||
|
||||
interface ToolButtonConfig {
|
||||
@ -100,34 +99,27 @@ const DraggablePortal = ({ children, isDragging }) => {
|
||||
|
||||
const InputbarTools = ({
|
||||
ref,
|
||||
assistant,
|
||||
assistantId,
|
||||
model,
|
||||
files,
|
||||
setFiles,
|
||||
showThinkingButton,
|
||||
showKnowledgeIcon,
|
||||
showMcpTools,
|
||||
selectedKnowledgeBases,
|
||||
handleKnowledgeBaseSelect,
|
||||
setText,
|
||||
resizeTextArea,
|
||||
mentionModels,
|
||||
onMentionModel,
|
||||
onClearMentionModels,
|
||||
couldMentionNotVisionModel,
|
||||
selectedKnowledgeBases,
|
||||
setSelectedKnowledgeBases,
|
||||
mentionedModels,
|
||||
setMentionedModels,
|
||||
couldAddImageFile,
|
||||
onEnableGenerateImage,
|
||||
isExpanded: isExpended,
|
||||
onToggleExpanded: onToggleExpended,
|
||||
addNewTopic,
|
||||
clearTopic,
|
||||
onNewContext,
|
||||
newTopicShortcut,
|
||||
cleanTopicShortcut,
|
||||
extensions
|
||||
}: InputbarToolsProps & { ref?: React.RefObject<InputbarToolsRef | null> }) => {
|
||||
const { t } = useTranslation()
|
||||
const dispatch = useAppDispatch()
|
||||
const { assistant, updateAssistant } = useAssistant(assistantId)
|
||||
|
||||
const quickPhrasesButtonRef = useRef<QuickPhrasesButtonRef>(null)
|
||||
const mentionModelsButtonRef = useRef<MentionModelsButtonRef>(null)
|
||||
@ -143,6 +135,54 @@ const InputbarTools = ({
|
||||
|
||||
const [targetTool, setTargetTool] = useState<ToolButtonConfig | null>(null)
|
||||
|
||||
const showThinkingButton = useMemo(
|
||||
() => isSupportedThinkingTokenModel(model) || isSupportedReasoningEffortModel(model),
|
||||
[model]
|
||||
)
|
||||
|
||||
const showMcpServerButton = useMemo(() => isSupportedToolUse(assistant) || isPromptToolUse(assistant), [assistant])
|
||||
|
||||
const knowledgeSidebarEnabled = useSidebarIconShow('knowledge')
|
||||
const showKnowledgeBaseButton = knowledgeSidebarEnabled && showMcpServerButton
|
||||
|
||||
const handleKnowledgeBaseSelect = useCallback(
|
||||
(bases?: KnowledgeBase[]) => {
|
||||
updateAssistant({ knowledge_bases: bases })
|
||||
setSelectedKnowledgeBases(bases ?? [])
|
||||
},
|
||||
[setSelectedKnowledgeBases, updateAssistant]
|
||||
)
|
||||
|
||||
// 仅允许在不含图片文件时mention非视觉模型
|
||||
const couldMentionNotVisionModel = useMemo(() => {
|
||||
return !files.some((file) => file.type === FileTypes.IMAGE)
|
||||
}, [files])
|
||||
|
||||
const onMentionModel = useCallback(
|
||||
(model: Model) => {
|
||||
// 我想应该没有模型是只支持视觉而不支持文本的?
|
||||
if (isVisionModel(model) || couldMentionNotVisionModel) {
|
||||
setMentionedModels((prev) => {
|
||||
const modelId = getModelUniqId(model)
|
||||
const exists = prev.some((m) => getModelUniqId(m) === modelId)
|
||||
return exists ? prev.filter((m) => getModelUniqId(m) !== modelId) : [...prev, model]
|
||||
})
|
||||
} else {
|
||||
logger.error('Cannot add non-vision model when images are uploaded')
|
||||
}
|
||||
},
|
||||
[couldMentionNotVisionModel, setMentionedModels]
|
||||
)
|
||||
|
||||
const onClearMentionModels = useCallback(() => setMentionedModels([]), [setMentionedModels])
|
||||
|
||||
const onEnableGenerateImage = useCallback(() => {
|
||||
updateAssistant({ enableGenerateImage: !assistant.enableGenerateImage })
|
||||
}, [assistant.enableGenerateImage, updateAssistant])
|
||||
|
||||
const newTopicShortcut = useShortcutDisplay('new_topic')
|
||||
const clearTopicShortcut = useShortcutDisplay('clear_topic')
|
||||
|
||||
const toggleToolVisibility = useCallback(
|
||||
(toolKey: string, isVisible: boolean | undefined) => {
|
||||
const newToolOrder = {
|
||||
@ -164,15 +204,8 @@ const InputbarTools = ({
|
||||
[dispatch, toolOrder.hidden, toolOrder.visible]
|
||||
)
|
||||
|
||||
const getQuickPanelMenuImpl = (params: {
|
||||
t: (key: string, options?: any) => string
|
||||
files: FileType[]
|
||||
couldAddImageFile: boolean
|
||||
text: string
|
||||
openSelectFileMenu: () => void
|
||||
translate: () => void
|
||||
}): QuickPanelListItem[] => {
|
||||
const { t, files, couldAddImageFile, text, openSelectFileMenu, translate } = params
|
||||
const getQuickPanelMenuImpl = (params: { text: string; translate: () => void }): QuickPanelListItem[] => {
|
||||
const { text, translate } = params
|
||||
|
||||
return [
|
||||
{
|
||||
@ -249,11 +282,13 @@ const InputbarTools = ({
|
||||
}
|
||||
},
|
||||
{
|
||||
label: couldAddImageFile ? t('chat.input.upload.label') : t('chat.input.upload.document'),
|
||||
label: couldAddImageFile ? t('chat.input.upload.attachment') : t('chat.input.upload.document'),
|
||||
description: '',
|
||||
icon: <Paperclip />,
|
||||
isMenu: true,
|
||||
action: openSelectFileMenu
|
||||
action: () => {
|
||||
attachmentButtonRef.current?.openQuickPanel()
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t('translate.title'),
|
||||
@ -313,15 +348,15 @@ const InputbarTools = ({
|
||||
title={t('chat.input.new_topic', { Command: newTopicShortcut })}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ToolbarButton type="text" onClick={addNewTopic}>
|
||||
<ActionIconButton onClick={addNewTopic}>
|
||||
<MessageSquareDiff size={19} />
|
||||
</ToolbarButton>
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)
|
||||
},
|
||||
{
|
||||
key: 'attachment',
|
||||
label: t('chat.input.upload.label'),
|
||||
label: t('chat.input.upload.image_or_document'),
|
||||
component: (
|
||||
<AttachmentButton
|
||||
ref={attachmentButtonRef}
|
||||
@ -329,28 +364,25 @@ const InputbarTools = ({
|
||||
extensions={extensions}
|
||||
files={files}
|
||||
setFiles={setFiles}
|
||||
ToolbarButton={ToolbarButton}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
key: 'thinking',
|
||||
label: t('chat.input.thinking.label'),
|
||||
component: (
|
||||
<ThinkingButton ref={thinkingButtonRef} model={model} assistant={assistant} ToolbarButton={ToolbarButton} />
|
||||
),
|
||||
component: <ThinkingButton ref={thinkingButtonRef} model={model} assistantId={assistant.id} />,
|
||||
condition: showThinkingButton
|
||||
},
|
||||
{
|
||||
key: 'web_search',
|
||||
label: t('chat.input.web_search.label'),
|
||||
component: <WebSearchButton ref={webSearchButtonRef} assistant={assistant} ToolbarButton={ToolbarButton} />,
|
||||
component: <WebSearchButton ref={webSearchButtonRef} assistantId={assistant.id} />,
|
||||
condition: !isMandatoryWebSearchModel(model)
|
||||
},
|
||||
{
|
||||
key: 'url_context',
|
||||
label: t('chat.input.url_context'),
|
||||
component: <UrlContextButton ref={urlContextButtonRef} assistant={assistant} ToolbarButton={ToolbarButton} />,
|
||||
component: <UrlContextButton ref={urlContextButtonRef} assistantId={assistant.id} />,
|
||||
condition: isGeminiModel(model) && isSupportUrlContextProvider(getProviderByModel(model))
|
||||
},
|
||||
{
|
||||
@ -361,36 +393,29 @@ const InputbarTools = ({
|
||||
ref={knowledgeBaseButtonRef}
|
||||
selectedBases={selectedKnowledgeBases}
|
||||
onSelect={handleKnowledgeBaseSelect}
|
||||
ToolbarButton={ToolbarButton}
|
||||
disabled={files.length > 0}
|
||||
/>
|
||||
),
|
||||
condition: showKnowledgeIcon
|
||||
condition: showKnowledgeBaseButton
|
||||
},
|
||||
{
|
||||
key: 'mcp_tools',
|
||||
label: t('settings.mcp.title'),
|
||||
component: (
|
||||
<MCPToolsButton
|
||||
assistant={assistant}
|
||||
assistantId={assistant.id}
|
||||
ref={mcpToolsButtonRef}
|
||||
ToolbarButton={ToolbarButton}
|
||||
setInputValue={setText}
|
||||
resizeTextArea={resizeTextArea}
|
||||
/>
|
||||
),
|
||||
condition: showMcpTools
|
||||
condition: showMcpServerButton
|
||||
},
|
||||
{
|
||||
key: 'generate_image',
|
||||
label: t('chat.input.generate_image'),
|
||||
component: (
|
||||
<GenerateImageButton
|
||||
model={model}
|
||||
assistant={assistant}
|
||||
onEnableGenerateImage={onEnableGenerateImage}
|
||||
ToolbarButton={ToolbarButton}
|
||||
/>
|
||||
<GenerateImageButton model={model} assistant={assistant} onEnableGenerateImage={onEnableGenerateImage} />
|
||||
),
|
||||
condition: isGenerateImageModel(model)
|
||||
},
|
||||
@ -400,10 +425,9 @@ const InputbarTools = ({
|
||||
component: (
|
||||
<MentionModelsButton
|
||||
ref={mentionModelsButtonRef}
|
||||
mentionedModels={mentionModels}
|
||||
mentionedModels={mentionedModels}
|
||||
onMentionModel={onMentionModel}
|
||||
onClearMentionModels={onClearMentionModels}
|
||||
ToolbarButton={ToolbarButton}
|
||||
couldMentionNotVisionModel={couldMentionNotVisionModel}
|
||||
files={files}
|
||||
setText={setText}
|
||||
@ -418,8 +442,7 @@ const InputbarTools = ({
|
||||
ref={quickPhrasesButtonRef}
|
||||
setInputValue={setText}
|
||||
resizeTextArea={resizeTextArea}
|
||||
ToolbarButton={ToolbarButton}
|
||||
assistantObj={assistant}
|
||||
assistantId={assistant.id}
|
||||
/>
|
||||
)
|
||||
},
|
||||
@ -429,12 +452,12 @@ const InputbarTools = ({
|
||||
component: (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={t('chat.input.clear.label', { Command: cleanTopicShortcut })}
|
||||
title={t('chat.input.clear.label', { Command: clearTopicShortcut })}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ToolbarButton type="text" onClick={clearTopic}>
|
||||
<ActionIconButton onClick={clearTopic}>
|
||||
<PaintbrushVertical size={18} />
|
||||
</ToolbarButton>
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)
|
||||
},
|
||||
@ -447,22 +470,22 @@ const InputbarTools = ({
|
||||
title={isExpended ? t('chat.input.collapse') : t('chat.input.expand')}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ToolbarButton type="text" onClick={onToggleExpended}>
|
||||
<ActionIconButton onClick={onToggleExpended}>
|
||||
{isExpended ? <Minimize size={18} /> : <Maximize size={18} />}
|
||||
</ToolbarButton>
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)
|
||||
},
|
||||
{
|
||||
key: 'new_context',
|
||||
label: t('chat.input.new.context', { Command: '' }),
|
||||
component: <NewContextButton onNewContext={onNewContext} ToolbarButton={ToolbarButton} />
|
||||
component: <NewContextButton onNewContext={onNewContext} />
|
||||
}
|
||||
]
|
||||
}, [
|
||||
addNewTopic,
|
||||
assistant,
|
||||
cleanTopicShortcut,
|
||||
clearTopicShortcut,
|
||||
clearTopic,
|
||||
couldAddImageFile,
|
||||
couldMentionNotVisionModel,
|
||||
@ -470,7 +493,7 @@ const InputbarTools = ({
|
||||
files,
|
||||
handleKnowledgeBaseSelect,
|
||||
isExpended,
|
||||
mentionModels,
|
||||
mentionedModels,
|
||||
model,
|
||||
newTopicShortcut,
|
||||
onClearMentionModels,
|
||||
@ -482,8 +505,8 @@ const InputbarTools = ({
|
||||
selectedKnowledgeBases,
|
||||
setFiles,
|
||||
setText,
|
||||
showKnowledgeIcon,
|
||||
showMcpTools,
|
||||
showKnowledgeBaseButton,
|
||||
showMcpServerButton,
|
||||
showThinkingButton,
|
||||
t
|
||||
])
|
||||
@ -628,14 +651,14 @@ const InputbarTools = ({
|
||||
placement="top"
|
||||
title={isCollapse ? t('chat.input.tools.expand') : t('chat.input.tools.collapse')}
|
||||
arrow>
|
||||
<ToolbarButton type="text" onClick={() => dispatch(setIsCollapsed(!isCollapse))}>
|
||||
<ActionIconButton onClick={() => dispatch(setIsCollapsed(!isCollapse))}>
|
||||
<CircleChevronRight
|
||||
size={18}
|
||||
style={{
|
||||
transform: isCollapse ? 'scaleX(1)' : 'scaleX(-1)'
|
||||
}}
|
||||
/>
|
||||
</ToolbarButton>
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
</ToolsContainer>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { QuickPanelListItem, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { QuickPanelListItem, QuickPanelReservedSymbol, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { useAppSelector } from '@renderer/store'
|
||||
import { KnowledgeBase } from '@renderer/types'
|
||||
import { Tooltip } from 'antd'
|
||||
@ -16,10 +17,9 @@ interface Props {
|
||||
selectedBases?: KnowledgeBase[]
|
||||
onSelect: (bases: KnowledgeBase[]) => void
|
||||
disabled?: boolean
|
||||
ToolbarButton: any
|
||||
}
|
||||
|
||||
const KnowledgeBaseButton: FC<Props> = ({ ref, selectedBases, onSelect, disabled, ToolbarButton }) => {
|
||||
const KnowledgeBaseButton: FC<Props> = ({ ref, selectedBases, onSelect, disabled }) => {
|
||||
const { t } = useTranslation()
|
||||
const navigate = useNavigate()
|
||||
const quickPanel = useQuickPanel()
|
||||
@ -77,7 +77,7 @@ const KnowledgeBaseButton: FC<Props> = ({ ref, selectedBases, onSelect, disabled
|
||||
quickPanel.open({
|
||||
title: t('chat.input.knowledge_base'),
|
||||
list: baseItems,
|
||||
symbol: '#',
|
||||
symbol: QuickPanelReservedSymbol.KnowledgeBase,
|
||||
multiple: true,
|
||||
afterAction({ item }) {
|
||||
item.isSelected = !item.isSelected
|
||||
@ -86,7 +86,7 @@ const KnowledgeBaseButton: FC<Props> = ({ ref, selectedBases, onSelect, disabled
|
||||
}, [baseItems, quickPanel, t])
|
||||
|
||||
const handleOpenQuickPanel = useCallback(() => {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === '#') {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === QuickPanelReservedSymbol.KnowledgeBase) {
|
||||
quickPanel.close()
|
||||
} else {
|
||||
openQuickPanel()
|
||||
@ -95,7 +95,7 @@ const KnowledgeBaseButton: FC<Props> = ({ ref, selectedBases, onSelect, disabled
|
||||
|
||||
// 监听 selectedBases 变化,动态更新已打开的 QuickPanel 列表状态
|
||||
useEffect(() => {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === '#') {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === QuickPanelReservedSymbol.KnowledgeBase) {
|
||||
// 直接使用重新计算的 baseItems,因为它已经包含了最新的 isSelected 状态
|
||||
quickPanel.updateList(baseItems)
|
||||
}
|
||||
@ -107,12 +107,12 @@ const KnowledgeBaseButton: FC<Props> = ({ ref, selectedBases, onSelect, disabled
|
||||
|
||||
return (
|
||||
<Tooltip placement="top" title={t('chat.input.knowledge_base')} mouseLeaveDelay={0} arrow>
|
||||
<ToolbarButton type="text" onClick={handleOpenQuickPanel} disabled={disabled}>
|
||||
<FileSearch
|
||||
size={18}
|
||||
color={selectedBases && selectedBases.length > 0 ? 'var(--color-primary)' : 'var(--color-icon)'}
|
||||
/>
|
||||
</ToolbarButton>
|
||||
<ActionIconButton
|
||||
onClick={handleOpenQuickPanel}
|
||||
active={selectedBases && selectedBases.length > 0}
|
||||
disabled={disabled}>
|
||||
<FileSearch size={18} />
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { QuickPanelListItem, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { QuickPanelListItem, QuickPanelReservedSymbol, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { isGeminiModel } from '@renderer/config/models'
|
||||
import { isGeminiWebSearchProvider, isSupportUrlContextProvider } from '@renderer/config/providers'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
@ -6,7 +7,7 @@ import { useMCPServers } from '@renderer/hooks/useMCPServers'
|
||||
import { useTimer } from '@renderer/hooks/useTimer'
|
||||
import { getProviderByModel } from '@renderer/services/AssistantService'
|
||||
import { EventEmitter } from '@renderer/services/EventService'
|
||||
import { Assistant, MCPPrompt, MCPResource, MCPServer } from '@renderer/types'
|
||||
import { MCPPrompt, MCPResource, MCPServer } from '@renderer/types'
|
||||
import { isToolUseModeFunction } from '@renderer/utils/assistant'
|
||||
import { Form, Input, Tooltip } from 'antd'
|
||||
import { CircleX, Hammer, Plus } from 'lucide-react'
|
||||
@ -21,11 +22,10 @@ export interface MCPToolsButtonRef {
|
||||
}
|
||||
|
||||
interface Props {
|
||||
assistant: Assistant
|
||||
assistantId: string
|
||||
ref?: React.RefObject<MCPToolsButtonRef | null>
|
||||
setInputValue: React.Dispatch<React.SetStateAction<string>>
|
||||
resizeTextArea: () => void
|
||||
ToolbarButton: any
|
||||
}
|
||||
|
||||
// 添加类型定义
|
||||
@ -113,14 +113,14 @@ const extractPromptContent = (response: any): string | null => {
|
||||
return null
|
||||
}
|
||||
|
||||
const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, ToolbarButton, ...props }) => {
|
||||
const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, assistantId }) => {
|
||||
const { activedMcpServers } = useMCPServers()
|
||||
const { t } = useTranslation()
|
||||
const quickPanel = useQuickPanel()
|
||||
const navigate = useNavigate()
|
||||
const [form] = Form.useForm()
|
||||
|
||||
const { updateAssistant, assistant } = useAssistant(props.assistant.id)
|
||||
const { assistant, updateAssistant } = useAssistant(assistantId)
|
||||
const model = assistant.model
|
||||
const { setTimeoutTimer } = useTimer()
|
||||
|
||||
@ -228,7 +228,7 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
|
||||
quickPanel.open({
|
||||
title: t('settings.mcp.title'),
|
||||
list: menuItems,
|
||||
symbol: 'mcp',
|
||||
symbol: QuickPanelReservedSymbol.Mcp,
|
||||
multiple: true,
|
||||
afterAction({ item }) {
|
||||
item.isSelected = !item.isSelected
|
||||
@ -377,7 +377,7 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
|
||||
quickPanel.open({
|
||||
title: t('settings.mcp.title'),
|
||||
list: prompts,
|
||||
symbol: 'mcp-prompt',
|
||||
symbol: QuickPanelReservedSymbol.McpPrompt,
|
||||
multiple: true
|
||||
})
|
||||
}, [promptList, quickPanel, t])
|
||||
@ -465,13 +465,13 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
|
||||
quickPanel.open({
|
||||
title: t('settings.mcp.title'),
|
||||
list: resourcesList,
|
||||
symbol: 'mcp-resource',
|
||||
symbol: QuickPanelReservedSymbol.McpResource,
|
||||
multiple: true
|
||||
})
|
||||
}, [resourcesList, quickPanel, t])
|
||||
|
||||
const handleOpenQuickPanel = useCallback(() => {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === 'mcp') {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === QuickPanelReservedSymbol.Mcp) {
|
||||
quickPanel.close()
|
||||
} else {
|
||||
openQuickPanel()
|
||||
@ -486,12 +486,9 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
|
||||
|
||||
return (
|
||||
<Tooltip placement="top" title={t('settings.mcp.title')} mouseLeaveDelay={0} arrow>
|
||||
<ToolbarButton type="text" onClick={handleOpenQuickPanel}>
|
||||
<Hammer
|
||||
size={18}
|
||||
color={assistant.mcpServers && assistant.mcpServers.length > 0 ? 'var(--color-primary)' : 'var(--color-icon)'}
|
||||
/>
|
||||
</ToolbarButton>
|
||||
<ActionIconButton onClick={handleOpenQuickPanel} active={assistant.mcpServers && assistant.mcpServers.length > 0}>
|
||||
<Hammer size={18} />
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import ModelTagsWithLabel from '@renderer/components/ModelTagsWithLabel'
|
||||
import { useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { QuickPanelListItem } from '@renderer/components/QuickPanel/types'
|
||||
import { type QuickPanelListItem, QuickPanelReservedSymbol, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { getModelLogo, isEmbeddingModel, isRerankModel, isVisionModel } from '@renderer/config/models'
|
||||
import db from '@renderer/databases'
|
||||
import { useProviders } from '@renderer/hooks/useProvider'
|
||||
@ -27,7 +27,6 @@ interface Props {
|
||||
onClearMentionModels: () => void
|
||||
couldMentionNotVisionModel: boolean
|
||||
files: FileType[]
|
||||
ToolbarButton: any
|
||||
setText: React.Dispatch<React.SetStateAction<string>>
|
||||
}
|
||||
|
||||
@ -38,7 +37,6 @@ const MentionModelsButton: FC<Props> = ({
|
||||
onClearMentionModels,
|
||||
couldMentionNotVisionModel,
|
||||
files,
|
||||
ToolbarButton,
|
||||
setText
|
||||
}) => {
|
||||
const { providers } = useProviders()
|
||||
@ -242,7 +240,7 @@ const MentionModelsButton: FC<Props> = ({
|
||||
quickPanel.open({
|
||||
title: t('agents.edit.model.select.title'),
|
||||
list: modelItems,
|
||||
symbol: '@',
|
||||
symbol: QuickPanelReservedSymbol.MentionModels,
|
||||
multiple: true,
|
||||
triggerInfo: triggerInfo || { type: 'button' },
|
||||
afterAction({ item }) {
|
||||
@ -274,7 +272,7 @@ const MentionModelsButton: FC<Props> = ({
|
||||
)
|
||||
|
||||
const handleOpenQuickPanel = useCallback(() => {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === '@') {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === QuickPanelReservedSymbol.MentionModels) {
|
||||
quickPanel.close()
|
||||
} else {
|
||||
openQuickPanel({ type: 'button' })
|
||||
@ -286,7 +284,7 @@ const MentionModelsButton: FC<Props> = ({
|
||||
useEffect(() => {
|
||||
// 检查files是否变化
|
||||
if (filesRef.current !== files) {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === '@') {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === QuickPanelReservedSymbol.MentionModels) {
|
||||
quickPanel.close()
|
||||
}
|
||||
filesRef.current = files
|
||||
@ -295,7 +293,7 @@ const MentionModelsButton: FC<Props> = ({
|
||||
|
||||
// 监听 mentionedModels 变化,动态更新已打开的 QuickPanel 列表状态
|
||||
useEffect(() => {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === '@') {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === QuickPanelReservedSymbol.MentionModels) {
|
||||
// 直接使用重新计算的 modelItems,因为它已经包含了最新的 isSelected 状态
|
||||
quickPanel.updateList(modelItems)
|
||||
}
|
||||
@ -307,9 +305,9 @@ const MentionModelsButton: FC<Props> = ({
|
||||
|
||||
return (
|
||||
<Tooltip placement="top" title={t('agents.edit.model.select.title')} mouseLeaveDelay={0} arrow>
|
||||
<ToolbarButton type="text" onClick={handleOpenQuickPanel}>
|
||||
<AtSign size={18} color={mentionedModels.length > 0 ? 'var(--color-primary)' : 'var(--color-icon)'} />
|
||||
</ToolbarButton>
|
||||
<ActionIconButton onClick={handleOpenQuickPanel} active={mentionedModels.length > 0}>
|
||||
<AtSign size={18} />
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { useShortcut, useShortcutDisplay } from '@renderer/hooks/useShortcuts'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Eraser } from 'lucide-react'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
interface Props {
|
||||
onNewContext: () => void
|
||||
ToolbarButton: any
|
||||
}
|
||||
|
||||
const NewContextButton: FC<Props> = ({ onNewContext, ToolbarButton }) => {
|
||||
const NewContextButton: FC<Props> = ({ onNewContext }) => {
|
||||
const newContextShortcut = useShortcutDisplay('toggle_new_context')
|
||||
const { t } = useTranslation()
|
||||
|
||||
@ -21,9 +20,9 @@ const NewContextButton: FC<Props> = ({ onNewContext, ToolbarButton }) => {
|
||||
title={t('chat.input.new.context', { Command: newContextShortcut })}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ToolbarButton type="text" onClick={onNewContext}>
|
||||
<ActionIconButton onClick={onNewContext}>
|
||||
<Eraser size={18} />
|
||||
</ToolbarButton>
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import {
|
||||
type QuickPanelListItem,
|
||||
type QuickPanelOpenOptions,
|
||||
QuickPanelReservedSymbol
|
||||
} from '@renderer/components/QuickPanel'
|
||||
import { useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { QuickPanelListItem, QuickPanelOpenOptions } from '@renderer/components/QuickPanel/types'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useTimer } from '@renderer/hooks/useTimer'
|
||||
import QuickPhraseService from '@renderer/services/QuickPhraseService'
|
||||
import { useAppSelector } from '@renderer/store'
|
||||
import { QuickPhrase } from '@renderer/types'
|
||||
import { Assistant } from '@renderer/types'
|
||||
import { Input, Modal, Radio, Space, Tooltip } from 'antd'
|
||||
import { BotMessageSquare, Plus, Zap } from 'lucide-react'
|
||||
import { memo, useCallback, useEffect, useImperativeHandle, useMemo, useState } from 'react'
|
||||
@ -20,21 +23,16 @@ interface Props {
|
||||
ref?: React.RefObject<QuickPhrasesButtonRef | null>
|
||||
setInputValue: React.Dispatch<React.SetStateAction<string>>
|
||||
resizeTextArea: () => void
|
||||
ToolbarButton: any
|
||||
assistantObj: Assistant
|
||||
assistantId: string
|
||||
}
|
||||
|
||||
const QuickPhrasesButton = ({ ref, setInputValue, resizeTextArea, ToolbarButton, assistantObj }: Props) => {
|
||||
const QuickPhrasesButton = ({ ref, setInputValue, resizeTextArea, assistantId }: Props) => {
|
||||
const [quickPhrasesList, setQuickPhrasesList] = useState<QuickPhrase[]>([])
|
||||
const [isModalOpen, setIsModalOpen] = useState(false)
|
||||
const [formData, setFormData] = useState({ title: '', content: '', location: 'global' })
|
||||
const { t } = useTranslation()
|
||||
const quickPanel = useQuickPanel()
|
||||
const activeAssistantId = useAppSelector(
|
||||
(state) =>
|
||||
state.assistants.assistants.find((a) => a.id === assistantObj.id)?.id || state.assistants.defaultAssistant.id
|
||||
)
|
||||
const { assistant, updateAssistant } = useAssistant(activeAssistantId)
|
||||
const { assistant, updateAssistant } = useAssistant(assistantId)
|
||||
const { setTimeoutTimer } = useTimer()
|
||||
|
||||
const loadQuickListPhrases = useCallback(
|
||||
@ -135,7 +133,7 @@ const QuickPhrasesButton = ({ ref, setInputValue, resizeTextArea, ToolbarButton,
|
||||
() => ({
|
||||
title: t('settings.quickPhrase.title'),
|
||||
list: phraseItems,
|
||||
symbol: 'quick-phrases'
|
||||
symbol: QuickPanelReservedSymbol.QuickPhrases
|
||||
}),
|
||||
[phraseItems, t]
|
||||
)
|
||||
@ -145,7 +143,7 @@ const QuickPhrasesButton = ({ ref, setInputValue, resizeTextArea, ToolbarButton,
|
||||
}, [quickPanel, quickPanelOpenOptions])
|
||||
|
||||
const handleOpenQuickPanel = useCallback(() => {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === 'quick-phrases') {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === QuickPanelReservedSymbol.QuickPhrases) {
|
||||
quickPanel.close()
|
||||
} else {
|
||||
openQuickPanel()
|
||||
@ -159,9 +157,9 @@ const QuickPhrasesButton = ({ ref, setInputValue, resizeTextArea, ToolbarButton,
|
||||
return (
|
||||
<>
|
||||
<Tooltip placement="top" title={t('settings.quickPhrase.title')} mouseLeaveDelay={0} arrow>
|
||||
<ToolbarButton type="text" onClick={handleOpenQuickPanel}>
|
||||
<ActionIconButton onClick={handleOpenQuickPanel}>
|
||||
<Zap size={18} />
|
||||
</ToolbarButton>
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
|
||||
<Modal
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import {
|
||||
MdiLightbulbAutoOutline,
|
||||
MdiLightbulbOffOutline,
|
||||
@ -6,11 +7,11 @@ import {
|
||||
MdiLightbulbOn50,
|
||||
MdiLightbulbOn80
|
||||
} from '@renderer/components/Icons/SVGIcon'
|
||||
import { useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { QuickPanelReservedSymbol, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { getThinkModelType, isDoubaoThinkingAutoModel, MODEL_SUPPORTED_OPTIONS } from '@renderer/config/models'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { getReasoningEffortOptionsLabel } from '@renderer/i18n/label'
|
||||
import { Assistant, Model, ThinkingOption } from '@renderer/types'
|
||||
import { Model, ThinkingOption } from '@renderer/types'
|
||||
import { Tooltip } from 'antd'
|
||||
import { FC, ReactElement, useCallback, useImperativeHandle, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -22,14 +23,13 @@ export interface ThinkingButtonRef {
|
||||
interface Props {
|
||||
ref?: React.RefObject<ThinkingButtonRef | null>
|
||||
model: Model
|
||||
assistant: Assistant
|
||||
ToolbarButton: any
|
||||
assistantId: string
|
||||
}
|
||||
|
||||
const ThinkingButton: FC<Props> = ({ ref, model, assistant, ToolbarButton }): ReactElement => {
|
||||
const ThinkingButton: FC<Props> = ({ ref, model, assistantId }): ReactElement => {
|
||||
const { t } = useTranslation()
|
||||
const quickPanel = useQuickPanel()
|
||||
const { updateAssistantSettings } = useAssistant(assistant.id)
|
||||
const { assistant, updateAssistantSettings } = useAssistant(assistantId)
|
||||
|
||||
const currentReasoningEffort = useMemo(() => {
|
||||
return assistant.settings?.reasoning_effort || 'off'
|
||||
@ -49,27 +49,6 @@ const ThinkingButton: FC<Props> = ({ ref, model, assistant, ToolbarButton }): Re
|
||||
return MODEL_SUPPORTED_OPTIONS[modelType]
|
||||
}, [model, modelType])
|
||||
|
||||
const createThinkingIcon = useCallback((option?: ThinkingOption, isActive: boolean = false) => {
|
||||
const iconColor = isActive ? 'var(--color-primary)' : 'var(--color-icon)'
|
||||
|
||||
switch (true) {
|
||||
case option === 'minimal':
|
||||
return <MdiLightbulbOn30 width={18} height={18} style={{ color: iconColor, marginTop: -2 }} />
|
||||
case option === 'low':
|
||||
return <MdiLightbulbOn50 width={18} height={18} style={{ color: iconColor, marginTop: -2 }} />
|
||||
case option === 'medium':
|
||||
return <MdiLightbulbOn80 width={18} height={18} style={{ color: iconColor, marginTop: -2 }} />
|
||||
case option === 'high':
|
||||
return <MdiLightbulbOn width={18} height={18} style={{ color: iconColor, marginTop: -2 }} />
|
||||
case option === 'auto':
|
||||
return <MdiLightbulbAutoOutline width={18} height={18} style={{ color: iconColor, marginTop: -2 }} />
|
||||
case option === 'off':
|
||||
return <MdiLightbulbOffOutline width={18} height={18} style={{ color: iconColor, marginTop: -2 }} />
|
||||
default:
|
||||
return <MdiLightbulbOffOutline width={18} height={18} style={{ color: iconColor }} />
|
||||
}
|
||||
}, [])
|
||||
|
||||
const onThinkingChange = useCallback(
|
||||
(option?: ThinkingOption) => {
|
||||
const isEnabled = option !== undefined && option !== 'off'
|
||||
@ -98,11 +77,11 @@ const ThinkingButton: FC<Props> = ({ ref, model, assistant, ToolbarButton }): Re
|
||||
level: option,
|
||||
label: getReasoningEffortOptionsLabel(option),
|
||||
description: '',
|
||||
icon: createThinkingIcon(option),
|
||||
icon: ThinkingIcon(option),
|
||||
isSelected: currentReasoningEffort === option,
|
||||
action: () => onThinkingChange(option)
|
||||
}))
|
||||
}, [createThinkingIcon, currentReasoningEffort, supportedOptions, onThinkingChange])
|
||||
}, [currentReasoningEffort, supportedOptions, onThinkingChange])
|
||||
|
||||
const isThinkingEnabled = currentReasoningEffort !== undefined && currentReasoningEffort !== 'off'
|
||||
|
||||
@ -114,12 +93,12 @@ const ThinkingButton: FC<Props> = ({ ref, model, assistant, ToolbarButton }): Re
|
||||
quickPanel.open({
|
||||
title: t('assistants.settings.reasoning_effort.label'),
|
||||
list: panelItems,
|
||||
symbol: 'thinking'
|
||||
symbol: QuickPanelReservedSymbol.Thinking
|
||||
})
|
||||
}, [quickPanel, panelItems, t])
|
||||
|
||||
const handleOpenQuickPanel = useCallback(() => {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === 'thinking') {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === QuickPanelReservedSymbol.Thinking) {
|
||||
quickPanel.close()
|
||||
return
|
||||
}
|
||||
@ -131,12 +110,6 @@ const ThinkingButton: FC<Props> = ({ ref, model, assistant, ToolbarButton }): Re
|
||||
openQuickPanel()
|
||||
}, [openQuickPanel, quickPanel, isThinkingEnabled, supportedOptions, disableThinking])
|
||||
|
||||
// 获取当前应显示的图标
|
||||
const getThinkingIcon = useCallback(() => {
|
||||
// 不再判断选项是否支持,依赖 useAssistant 更新选项为支持选项的行为
|
||||
return createThinkingIcon(currentReasoningEffort, currentReasoningEffort !== 'off')
|
||||
}, [createThinkingIcon, currentReasoningEffort])
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
openQuickPanel
|
||||
}))
|
||||
@ -151,11 +124,41 @@ const ThinkingButton: FC<Props> = ({ ref, model, assistant, ToolbarButton }): Re
|
||||
}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ToolbarButton type="text" onClick={handleOpenQuickPanel}>
|
||||
{getThinkingIcon()}
|
||||
</ToolbarButton>
|
||||
<ActionIconButton onClick={handleOpenQuickPanel} active={currentReasoningEffort !== 'off'}>
|
||||
{ThinkingIcon(currentReasoningEffort)}
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
const ThinkingIcon = (option?: ThinkingOption) => {
|
||||
let IconComponent: React.FC<React.SVGProps<SVGSVGElement>> | null = null
|
||||
|
||||
switch (option) {
|
||||
case 'minimal':
|
||||
IconComponent = MdiLightbulbOn30
|
||||
break
|
||||
case 'low':
|
||||
IconComponent = MdiLightbulbOn50
|
||||
break
|
||||
case 'medium':
|
||||
IconComponent = MdiLightbulbOn80
|
||||
break
|
||||
case 'high':
|
||||
IconComponent = MdiLightbulbOn
|
||||
break
|
||||
case 'auto':
|
||||
IconComponent = MdiLightbulbAutoOutline
|
||||
break
|
||||
case 'off':
|
||||
IconComponent = MdiLightbulbOffOutline
|
||||
break
|
||||
default:
|
||||
IconComponent = MdiLightbulbOffOutline
|
||||
break
|
||||
}
|
||||
|
||||
return <IconComponent className="icon" width={18} height={18} style={{ marginTop: -2 }} />
|
||||
}
|
||||
|
||||
export default ThinkingButton
|
||||
|
||||
@ -11,7 +11,6 @@ type Props = {
|
||||
estimateTokenCount: number
|
||||
inputTokenCount: number
|
||||
contextCount: { current: number; max: number }
|
||||
ToolbarButton: any
|
||||
} & React.HTMLAttributes<HTMLDivElement>
|
||||
|
||||
const TokenCount: FC<Props> = ({ estimateTokenCount, inputTokenCount, contextCount }) => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useTimer } from '@renderer/hooks/useTimer'
|
||||
import { Assistant } from '@renderer/types'
|
||||
import { isToolUseModeFunction } from '@renderer/utils/assistant'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Link } from 'lucide-react'
|
||||
@ -13,13 +13,12 @@ export interface UrlContextButtonRef {
|
||||
|
||||
interface Props {
|
||||
ref?: React.RefObject<UrlContextButtonRef | null>
|
||||
assistant: Assistant
|
||||
ToolbarButton: any
|
||||
assistantId: string
|
||||
}
|
||||
|
||||
const UrlContextButton: FC<Props> = ({ assistant, ToolbarButton }) => {
|
||||
const UrlContextButton: FC<Props> = ({ assistantId }) => {
|
||||
const { t } = useTranslation()
|
||||
const { updateAssistant } = useAssistant(assistant.id)
|
||||
const { assistant, updateAssistant } = useAssistant(assistantId)
|
||||
const { setTimeoutTimer } = useTimer()
|
||||
|
||||
const urlContentNewState = !assistant.enableUrlContext
|
||||
@ -48,14 +47,9 @@ const UrlContextButton: FC<Props> = ({ assistant, ToolbarButton }) => {
|
||||
|
||||
return (
|
||||
<Tooltip placement="top" title={t('chat.input.url_context')} arrow>
|
||||
<ToolbarButton type="text" onClick={handleToggle}>
|
||||
<Link
|
||||
size={18}
|
||||
style={{
|
||||
color: assistant.enableUrlContext ? 'var(--color-primary)' : 'var(--color-icon)'
|
||||
}}
|
||||
/>
|
||||
</ToolbarButton>
|
||||
<ActionIconButton onClick={handleToggle} active={assistant.enableUrlContext}>
|
||||
<Link size={18} />
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { BaiduOutlined, GoogleOutlined } from '@ant-design/icons'
|
||||
import { loggerService } from '@logger'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { BingLogo, BochaLogo, ExaLogo, SearXNGLogo, TavilyLogo, ZhipuLogo } from '@renderer/components/Icons'
|
||||
import { QuickPanelListItem, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { QuickPanelListItem, QuickPanelReservedSymbol, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { isGeminiModel, isWebSearchModel } from '@renderer/config/models'
|
||||
import { isGeminiWebSearchProvider } from '@renderer/config/providers'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
@ -9,7 +10,7 @@ import { useTimer } from '@renderer/hooks/useTimer'
|
||||
import { useWebSearchProviders } from '@renderer/hooks/useWebSearchProviders'
|
||||
import { getProviderByModel } from '@renderer/services/AssistantService'
|
||||
import WebSearchService from '@renderer/services/WebSearchService'
|
||||
import { Assistant, WebSearchProvider, WebSearchProviderId } from '@renderer/types'
|
||||
import { WebSearchProvider, WebSearchProviderId } from '@renderer/types'
|
||||
import { hasObjectKey } from '@renderer/utils'
|
||||
import { isToolUseModeFunction } from '@renderer/utils/assistant'
|
||||
import { Tooltip } from 'antd'
|
||||
@ -23,17 +24,16 @@ export interface WebSearchButtonRef {
|
||||
|
||||
interface Props {
|
||||
ref?: React.RefObject<WebSearchButtonRef | null>
|
||||
assistant: Assistant
|
||||
ToolbarButton: any
|
||||
assistantId: string
|
||||
}
|
||||
|
||||
const logger = loggerService.withContext('WebSearchButton')
|
||||
|
||||
const WebSearchButton: FC<Props> = ({ ref, assistant, ToolbarButton }) => {
|
||||
const WebSearchButton: FC<Props> = ({ ref, assistantId }) => {
|
||||
const { t } = useTranslation()
|
||||
const quickPanel = useQuickPanel()
|
||||
const { providers } = useWebSearchProviders()
|
||||
const { updateAssistant } = useAssistant(assistant.id)
|
||||
const { assistant, updateAssistant } = useAssistant(assistantId)
|
||||
const { setTimeoutTimer } = useTimer()
|
||||
|
||||
// 注意:assistant.enableWebSearch 有不同的语义
|
||||
@ -44,24 +44,24 @@ const WebSearchButton: FC<Props> = ({ ref, assistant, ToolbarButton }) => {
|
||||
({ pid, size = 18, color }: { pid?: WebSearchProviderId; size?: number; color?: string }) => {
|
||||
switch (pid) {
|
||||
case 'bocha':
|
||||
return <BochaLogo width={size} height={size} color={color} />
|
||||
return <BochaLogo className="icon" width={size} height={size} color={color} />
|
||||
case 'exa':
|
||||
// size微调,视觉上和其他图标平衡一些
|
||||
return <ExaLogo width={size - 2} height={size} color={color} />
|
||||
return <ExaLogo className="icon" width={size - 2} height={size} color={color} />
|
||||
case 'tavily':
|
||||
return <TavilyLogo width={size} height={size} color={color} />
|
||||
return <TavilyLogo className="icon" width={size} height={size} color={color} />
|
||||
case 'zhipu':
|
||||
return <ZhipuLogo width={size} height={size} color={color} />
|
||||
return <ZhipuLogo className="icon" width={size} height={size} color={color} />
|
||||
case 'searxng':
|
||||
return <SearXNGLogo width={size} height={size} color={color} />
|
||||
return <SearXNGLogo className="icon" width={size} height={size} color={color} />
|
||||
case 'local-baidu':
|
||||
return <BaiduOutlined size={size} style={{ color, fontSize: size }} />
|
||||
case 'local-bing':
|
||||
return <BingLogo width={size} height={size} color={color} />
|
||||
return <BingLogo className="icon" width={size} height={size} color={color} />
|
||||
case 'local-google':
|
||||
return <GoogleOutlined size={size} style={{ color, fontSize: size }} />
|
||||
default:
|
||||
return <Globe size={size} style={{ color, fontSize: size }} />
|
||||
return <Globe className="icon" size={size} style={{ color, fontSize: size }} />
|
||||
}
|
||||
},
|
||||
[]
|
||||
@ -165,13 +165,13 @@ const WebSearchButton: FC<Props> = ({ ref, assistant, ToolbarButton }) => {
|
||||
quickPanel.open({
|
||||
title: t('chat.input.web_search.label'),
|
||||
list: providerItems,
|
||||
symbol: '?',
|
||||
symbol: QuickPanelReservedSymbol.WebSearch,
|
||||
pageSize: 9
|
||||
})
|
||||
}, [quickPanel, t, providerItems])
|
||||
|
||||
const handleOpenQuickPanel = useCallback(() => {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === '?') {
|
||||
if (quickPanel.isVisible && quickPanel.symbol === QuickPanelReservedSymbol.WebSearch) {
|
||||
quickPanel.close()
|
||||
} else {
|
||||
openQuickPanel()
|
||||
@ -190,17 +190,15 @@ const WebSearchButton: FC<Props> = ({ ref, assistant, ToolbarButton }) => {
|
||||
openQuickPanel
|
||||
}))
|
||||
|
||||
const color = enableWebSearch ? 'var(--color-primary)' : 'var(--color-icon)'
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={enableWebSearch ? t('common.close') : t('chat.input.web_search.label')}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<ToolbarButton type="text" onClick={onClick}>
|
||||
<WebSearchIcon color={color} pid={assistant.webSearchProviderId} />
|
||||
</ToolbarButton>
|
||||
<ActionIconButton onClick={onClick} active={!!enableWebSearch}>
|
||||
<WebSearchIcon pid={assistant.webSearchProviderId} />
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import CustomTag from '@renderer/components/Tags/CustomTag'
|
||||
import TranslateButton from '@renderer/components/TranslateButton'
|
||||
import { isGenerateImageModel, isVisionModel } from '@renderer/config/models'
|
||||
@ -25,7 +26,6 @@ import styled from 'styled-components'
|
||||
|
||||
import AttachmentButton, { AttachmentButtonRef } from '../Inputbar/AttachmentButton'
|
||||
import { FileNameRender, getFileIcon } from '../Inputbar/AttachmentPreview'
|
||||
import { ToolbarButton } from '../Inputbar/Inputbar'
|
||||
|
||||
interface Props {
|
||||
message: Message
|
||||
@ -349,27 +349,26 @@ const MessageBlockEditor: FC<Props> = ({ message, topicId, onSave, onResend, onC
|
||||
setFiles={setFiles}
|
||||
couldAddImageFile={couldAddImageFile}
|
||||
extensions={extensions}
|
||||
ToolbarButton={ToolbarButton}
|
||||
/>
|
||||
)}
|
||||
</ActionBarLeft>
|
||||
<ActionBarMiddle />
|
||||
<ActionBarRight>
|
||||
<Tooltip title={t('common.cancel')}>
|
||||
<ToolbarButton type="text" onClick={onCancel}>
|
||||
<ActionIconButton onClick={onCancel}>
|
||||
<X size={16} />
|
||||
</ToolbarButton>
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('common.save')}>
|
||||
<ToolbarButton type="text" onClick={handleSave}>
|
||||
<ActionIconButton onClick={handleSave}>
|
||||
<Save size={16} />
|
||||
</ToolbarButton>
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
{message.role === 'user' && (
|
||||
<Tooltip title={t('chat.resend')}>
|
||||
<ToolbarButton type="text" onClick={handleResend}>
|
||||
<ActionIconButton onClick={handleResend}>
|
||||
<Send size={16} />
|
||||
</ToolbarButton>
|
||||
</ActionIconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
</ActionBarRight>
|
||||
|
||||
@ -848,7 +848,8 @@ const ContentContainer = styled.div<{ $historyDrawerVisible: boolean }>`
|
||||
`
|
||||
|
||||
const AreaContainer = styled.div`
|
||||
display: flex;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
flex: 1;
|
||||
gap: 8px;
|
||||
`
|
||||
@ -919,6 +920,11 @@ const OutputContainer = styled.div`
|
||||
border-radius: 10px;
|
||||
padding: 10px 5px;
|
||||
height: calc(100vh - var(--navbar-height) - 70px);
|
||||
overflow: hidden;
|
||||
|
||||
& > div > .markdown > pre {
|
||||
background-color: var(--color-background-mute) !important;
|
||||
}
|
||||
|
||||
&:hover .copy-button {
|
||||
opacity: 1;
|
||||
|
||||
@ -46,8 +46,8 @@ const assistantsSlice = createSlice({
|
||||
removeAssistant: (state, action: PayloadAction<{ id: string }>) => {
|
||||
state.assistants = state.assistants.filter((c) => c.id !== action.payload.id)
|
||||
},
|
||||
updateAssistant: (state, action: PayloadAction<Assistant>) => {
|
||||
state.assistants = state.assistants.map((c) => (c.id === action.payload.id ? action.payload : c))
|
||||
updateAssistant: (state, action: PayloadAction<Partial<Assistant>>) => {
|
||||
state.assistants = state.assistants.map((c) => (c.id === action.payload.id ? { ...c, ...action.payload } : c))
|
||||
},
|
||||
updateAssistantSettings: (
|
||||
state,
|
||||
|
||||
@ -17,6 +17,7 @@ import type { BaseTool, MCPTool } from './tool'
|
||||
|
||||
export * from './knowledge'
|
||||
export * from './mcp'
|
||||
export * from './notification'
|
||||
export * from './ocr'
|
||||
|
||||
export type Assistant = {
|
||||
|
||||
@ -19,15 +19,14 @@
|
||||
"electron-vite/node",
|
||||
"vitest/globals"
|
||||
],
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@logger": ["src/main/services/LoggerService"],
|
||||
"@data/*": ["src/main/data/*"],
|
||||
"@main/*": ["src/main/*"],
|
||||
"@types": ["src/renderer/src/types/index.ts"],
|
||||
"@shared/*": ["packages/shared/*"],
|
||||
"@mcp-trace/*": ["packages/mcp-trace/*"],
|
||||
"@modelcontextprotocol/sdk/*": ["node_modules/@modelcontextprotocol/sdk/dist/esm/*"]
|
||||
"@logger": ["./src/main/services/LoggerService"],
|
||||
"@data/*": ["./src/main/data/*"],
|
||||
"@main/*": ["./src/main/*"],
|
||||
"@types": ["./src/renderer/src/types/index.ts"],
|
||||
"@shared/*": ["./packages/shared/*"],
|
||||
"@mcp-trace/*": ["./packages/mcp-trace/*"],
|
||||
"@modelcontextprotocol/sdk/*": ["./node_modules/@modelcontextprotocol/sdk/dist/esm/*"]
|
||||
},
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
|
||||
@ -17,21 +17,20 @@
|
||||
"incremental": true,
|
||||
"tsBuildInfoFile": ".tsbuildinfo/tsconfig.web.tsbuildinfo",
|
||||
"jsx": "react-jsx",
|
||||
"baseUrl": ".",
|
||||
"moduleResolution": "bundler",
|
||||
"paths": {
|
||||
"@logger": ["src/renderer/src/services/LoggerService"],
|
||||
"@data/*": ["src/renderer/src/data/*"],
|
||||
"@renderer/*": ["src/renderer/src/*"],
|
||||
"@shared/*": ["packages/shared/*"],
|
||||
"@types": ["src/renderer/src/types/index.ts"],
|
||||
"@mcp-trace/*": ["packages/mcp-trace/*"],
|
||||
"@cherrystudio/ai-core/provider": ["packages/aiCore/src/core/providers/index.ts"],
|
||||
"@cherrystudio/ai-core/built-in/plugins": ["packages/aiCore/src/core/plugins/built-in/index.ts"],
|
||||
"@cherrystudio/ai-core/*": ["packages/aiCore/src/*"],
|
||||
"@cherrystudio/ai-core": ["packages/aiCore/src/index.ts"],
|
||||
"@cherrystudio/extension-table-plus": ["packages/extension-table-plus/src/index.ts"],
|
||||
"@cherrystudio/ui": ["packages/ui/src/index.ts"]
|
||||
"@logger": ["./src/renderer/src/services/LoggerService"],
|
||||
"@data/*": ["./src/renderer/src/data/*"],
|
||||
"@renderer/*": ["./src/renderer/src/*"],
|
||||
"@shared/*": ["./packages/shared/*"],
|
||||
"@types": ["./src/renderer/src/types/index.ts"],
|
||||
"@mcp-trace/*": ["./packages/mcp-trace/*"],
|
||||
"@cherrystudio/ai-core/provider": ["./packages/aiCore/src/core/providers/index.ts"],
|
||||
"@cherrystudio/ai-core/built-in/plugins": ["./packages/aiCore/src/core/plugins/built-in/index.ts"],
|
||||
"@cherrystudio/ai-core/*": ["./packages/aiCore/src/*"],
|
||||
"@cherrystudio/ai-core": ["./packages/aiCore/src/index.ts"],
|
||||
"@cherrystudio/extension-table-plus": ["./packages/extension-table-plus/src/index.ts"],
|
||||
"@cherrystudio/ui": ["./packages/ui/src/index.ts"]
|
||||
},
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
|
||||
338
yarn.lock
338
yarn.lock
@ -74,221 +74,157 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/amazon-bedrock@npm:^3.0.0":
|
||||
version: 3.0.8
|
||||
resolution: "@ai-sdk/amazon-bedrock@npm:3.0.8"
|
||||
"@ai-sdk/amazon-bedrock@npm:^3.0.21":
|
||||
version: 3.0.21
|
||||
resolution: "@ai-sdk/amazon-bedrock@npm:3.0.21"
|
||||
dependencies:
|
||||
"@ai-sdk/anthropic": "npm:2.0.4"
|
||||
"@ai-sdk/anthropic": "npm:2.0.17"
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.3"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.9"
|
||||
"@smithy/eventstream-codec": "npm:^4.0.1"
|
||||
"@smithy/util-utf8": "npm:^4.0.0"
|
||||
aws4fetch: "npm:^1.0.20"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/d7b303b8581e9d28e9ac375b3718ef3f7fff3353d18185870f0b90fd542eb9398d029768502981e9e45a6b64137a7029f591993afd0b18e9ef74525f625524f7
|
||||
checksum: 10c0/2d15baaad53e389666cede9673e2b43f5299e2cedb70f5b7afc656b7616e73775a9108c2cc1beee4644ff4c66ad41c8dd0b412373dd05caa4fc3d477c4343ea8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/anthropic@npm:2.0.15":
|
||||
version: 2.0.15
|
||||
resolution: "@ai-sdk/anthropic@npm:2.0.15"
|
||||
"@ai-sdk/anthropic@npm:2.0.17, @ai-sdk/anthropic@npm:^2.0.17":
|
||||
version: 2.0.17
|
||||
resolution: "@ai-sdk/anthropic@npm:2.0.17"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.8"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.9"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/9597b32be8b83dab67b23f162ca66cde385213fb1665f54091d59430789becf73e2b4fcd2be66ceb13020409f59cd8f9da7dae23adf183bc9eb7ce94f55bde96
|
||||
checksum: 10c0/783b6a953f3854c4303ad7c30dd56d4706486c7d1151adb17071d87933418c59c26bce53d5c26d34c4d4728eaac4a856ce49a336caed26a7216f982fea562814
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/anthropic@npm:2.0.4":
|
||||
version: 2.0.4
|
||||
resolution: "@ai-sdk/anthropic@npm:2.0.4"
|
||||
"@ai-sdk/azure@npm:^2.0.30":
|
||||
version: 2.0.30
|
||||
resolution: "@ai-sdk/azure@npm:2.0.30"
|
||||
dependencies:
|
||||
"@ai-sdk/openai": "npm:2.0.30"
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.3"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.9"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/2e5a997b6e2d9a2964c4681418643fd2f347df78ac1f9677a0cc6a3a3454920d05c663e35521d8922f0a382ec77a25e4b92204b3760a1da05876bf00d41adc39
|
||||
checksum: 10c0/22af450e28026547badc891a627bcb3cfa2d030864089947172506810f06cfa4c74c453aabd6a0d5c05ede5ffdee381b9278772ce781eca0c7c826c7d7ae3dc3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/anthropic@npm:^2.0.5":
|
||||
version: 2.0.5
|
||||
resolution: "@ai-sdk/anthropic@npm:2.0.5"
|
||||
"@ai-sdk/deepseek@npm:^1.0.17":
|
||||
version: 1.0.17
|
||||
resolution: "@ai-sdk/deepseek@npm:1.0.17"
|
||||
dependencies:
|
||||
"@ai-sdk/openai-compatible": "npm:1.0.17"
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.4"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.9"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/aaca0d4b2e00715c513a7c688d6b6116eaf29d1d37f005c150f1229200713fb1c393c81a8b01ac29af954fb1ee213f3a537861227051865abe51aa547dca364e
|
||||
checksum: 10c0/c408701343bb28ed0b3e034b8789e6de1dfd6cfc6a9b53feb68f155889e29a9fbbcf05bd99e63f60809cf05ee4b158abaccdf1cbcd9df92c0987094220a61d08
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/azure@npm:^2.0.16":
|
||||
version: 2.0.16
|
||||
resolution: "@ai-sdk/azure@npm:2.0.16"
|
||||
"@ai-sdk/gateway@npm:1.0.23":
|
||||
version: 1.0.23
|
||||
resolution: "@ai-sdk/gateway@npm:1.0.23"
|
||||
dependencies:
|
||||
"@ai-sdk/openai": "npm:2.0.16"
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.4"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.9"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/49bd9d27cba3104ba5d8a82c70a16dd475572585c5187e5bc29c9d46a30a373338181b29f37dfe9f61f50b5b82e86808139c93da225eb1721cb15e1a8b97cceb
|
||||
checksum: 10c0/b1e1a6ab63b9191075eed92c586cd927696f8997ad24f056585aee3f5fffd283d981aa6b071a2560ecda4295445b80a4cfd321fa63c06e7ac54a06bc4c84887f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/deepseek@npm:^1.0.9":
|
||||
version: 1.0.9
|
||||
resolution: "@ai-sdk/deepseek@npm:1.0.9"
|
||||
"@ai-sdk/google-vertex@npm:^3.0.27":
|
||||
version: 3.0.27
|
||||
resolution: "@ai-sdk/google-vertex@npm:3.0.27"
|
||||
dependencies:
|
||||
"@ai-sdk/openai-compatible": "npm:1.0.9"
|
||||
"@ai-sdk/anthropic": "npm:2.0.17"
|
||||
"@ai-sdk/google": "npm:2.0.14"
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.4"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/b02a000a98a6df9808d472bf63640ee96297f9acce7422de0d198ffda40edcbcadc0946ae383464b80a92ac033a3a61cf71fa1bc640c08cac589bebc8d5623b9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/gateway@npm:1.0.20":
|
||||
version: 1.0.20
|
||||
resolution: "@ai-sdk/gateway@npm:1.0.20"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.8"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/c25e98aab2513f783b2b552245b027e5a73b209d974e25bbfae0e69b67fd3468bba0bf57085ca3d7259b4dc8881e7f40fca769f698f0b1eb028a849f587ad09c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/google-vertex@npm:^3.0.25":
|
||||
version: 3.0.25
|
||||
resolution: "@ai-sdk/google-vertex@npm:3.0.25"
|
||||
dependencies:
|
||||
"@ai-sdk/anthropic": "npm:2.0.15"
|
||||
"@ai-sdk/google": "npm:2.0.13"
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.8"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.9"
|
||||
google-auth-library: "npm:^9.15.0"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/ed67a439fc4a446aa7353d258c61497198aecdf0de55500d2abbea86109bbf1ff4570fffdfcf58508db1c887a2095a71322777634f76326a45e259d28ef0b801
|
||||
checksum: 10c0/7017838aef9c04c18ce9acec52eb602ee0a38d68a7496977a3898411f1ac235b2d7776011fa686084b90b0881e65c69596014e5465b8ed0d0e313b5db1f967a7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/google@npm:2.0.13, @ai-sdk/google@npm:^2.0.13":
|
||||
version: 2.0.13
|
||||
resolution: "@ai-sdk/google@npm:2.0.13"
|
||||
"@ai-sdk/google@npm:2.0.14, @ai-sdk/google@npm:^2.0.14":
|
||||
version: 2.0.14
|
||||
resolution: "@ai-sdk/google@npm:2.0.14"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.8"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.9"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/a05210de11d7ab41d49bcd0330c37f4116441b149d8ccc9b6bc5eaa12ea42bae82364dc2cd09502734b15115071f07395525806ea4998930b285b1ce74102186
|
||||
checksum: 10c0/2c04839cf58c33514a54c9de8190c363b5cacfbfc8404fea5d2ec36ad0af5ced4fc571f978e7aa35876bd9afae138f4c700d2bc1f64a78a37d0401f6797bf8f3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/mistral@npm:^2.0.0":
|
||||
version: 2.0.4
|
||||
resolution: "@ai-sdk/mistral@npm:2.0.4"
|
||||
"@ai-sdk/mistral@npm:^2.0.14":
|
||||
version: 2.0.14
|
||||
resolution: "@ai-sdk/mistral@npm:2.0.14"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.3"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.9"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/cca88cba855d4952551ca0be748e21f0d1b54537d0c7e08f30facdfbdbac7e6894ff4a1ceb53657aaf6e4380bbaa39d3cc37d1f734d777cdc1caba004c87221f
|
||||
checksum: 10c0/420be3a039095830aaf59b6f82c1f986ff4800ba5b9438e1dd85530026a42c9454a6e632b6a1a1839816609f4752d0a19140d8943ad78bb976fb5d6a37714e16
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/openai-compatible@npm:1.0.9, @ai-sdk/openai-compatible@npm:^1.0.9":
|
||||
version: 1.0.9
|
||||
resolution: "@ai-sdk/openai-compatible@npm:1.0.9"
|
||||
"@ai-sdk/openai-compatible@npm:1.0.17, @ai-sdk/openai-compatible@npm:^1.0.17":
|
||||
version: 1.0.17
|
||||
resolution: "@ai-sdk/openai-compatible@npm:1.0.17"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.4"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.9"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/a98505438f7a4c0d5c1aee9fb03aae00ff726c1c5ba0eff45d00ddc30ab9f25de634fcfd111a634bd654042150b9f16a131ce3f45887f9661c0241e3807d6ad4
|
||||
checksum: 10c0/53ab6111e0f44437a2e268a51fb747600844d85b0cd0d170fb87a7b68af3eb21d7728d7bbf14d71c9fcf36e7a0f94ad75f0ad6b1070e473c867ab08ef84f6564
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/openai@npm:2.0.16":
|
||||
version: 2.0.16
|
||||
resolution: "@ai-sdk/openai@npm:2.0.16"
|
||||
"@ai-sdk/openai@npm:2.0.30, @ai-sdk/openai@npm:^2.0.30":
|
||||
version: 2.0.30
|
||||
resolution: "@ai-sdk/openai@npm:2.0.30"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.4"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.9"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/1ea694bd096175a67a383e73fd1f4434eeaa7ddc6c378e44f295333d9a7b4153251d405dac2d8da330f95e4d5ef58641cc8533a3e63ff4d250b3cbc66f9abfea
|
||||
checksum: 10c0/90a57c1b10dac46c0bbe7e16cf9202557fb250d9f0e94a2a5fb7d95b5ea77815a56add78b00238d3823f0313c9b2c42abe865478d28a6196f72b341d32dd40af
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/openai@npm:^2.0.26":
|
||||
version: 2.0.26
|
||||
resolution: "@ai-sdk/openai@npm:2.0.26"
|
||||
"@ai-sdk/perplexity@npm:^2.0.9":
|
||||
version: 2.0.9
|
||||
resolution: "@ai-sdk/perplexity@npm:2.0.9"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.8"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.9"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/b8cb01c0c38525c38901f41f1693cd15589932a2aceddea14bed30f44719532a5e74615fb0e974eff1a0513048ac204c27456ff8829a9c811d1461cc635c9cc5
|
||||
checksum: 10c0/2023aadc26c41430571c4897df79074e7a95a12f2238ad57081355484066bcf9e8dfde1da60fa6af12fc9fb2a195899326f753c69f4913dc005a33367f150349
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/perplexity@npm:^2.0.8":
|
||||
version: 2.0.8
|
||||
resolution: "@ai-sdk/perplexity@npm:2.0.8"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.8"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/acfd6c09c4c0ef5af7eeec6e8bc20b90b24d1d3fc2bc8ee9de4e40770fc0c17ca2c8db8f0248ff07264b71e5aa65f64d37a165db2f43fee84c1b3513cb97983c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/provider-utils@npm:3.0.3":
|
||||
version: 3.0.3
|
||||
resolution: "@ai-sdk/provider-utils@npm:3.0.3"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@standard-schema/spec": "npm:^1.0.0"
|
||||
eventsource-parser: "npm:^3.0.3"
|
||||
zod-to-json-schema: "npm:^3.24.1"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/f02e26a6b85ef728862505b150475ef2e52d60130ca64b23316ff7b952f1817b01f959b9e48819dad64d82a96ba4ad538610d69dbbfe5be4b4b38469c16a6ccf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/provider-utils@npm:3.0.4, @ai-sdk/provider-utils@npm:^3.0.4":
|
||||
version: 3.0.4
|
||||
resolution: "@ai-sdk/provider-utils@npm:3.0.4"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@standard-schema/spec": "npm:^1.0.0"
|
||||
eventsource-parser: "npm:^3.0.3"
|
||||
zod-to-json-schema: "npm:^3.24.1"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/6732b99310561d72262cdeef40cc58190afa55248dca0eb3a378ef87fede12086e534c68687e0fe5ef5b092da41f3e745857ce3f9b248a272a78c0dc268dffd4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/provider-utils@npm:3.0.8":
|
||||
version: 3.0.8
|
||||
resolution: "@ai-sdk/provider-utils@npm:3.0.8"
|
||||
"@ai-sdk/provider-utils@npm:3.0.9, @ai-sdk/provider-utils@npm:^3.0.9":
|
||||
version: 3.0.9
|
||||
resolution: "@ai-sdk/provider-utils@npm:3.0.9"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@standard-schema/spec": "npm:^1.0.0"
|
||||
eventsource-parser: "npm:^3.0.5"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/f466657c886cbb9f7ecbcd2dd1abc51a88af9d3f1cff030f7e97e70a4790a99f3338ad886e9c0dccf04dacdcc84522c7d57119b9a4e8e1d84f2dae9c893c397e
|
||||
checksum: 10c0/f8b659343d7e22ae099f7b6fc514591c0408012eb0aa00f7a912798b6d7d7305cafa8f18a07c7adec0bb5d39d9b6256b76d65c5393c3fc843d1361c52f1f8080
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -301,16 +237,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/xai@npm:^2.0.9":
|
||||
version: 2.0.9
|
||||
resolution: "@ai-sdk/xai@npm:2.0.9"
|
||||
"@ai-sdk/xai@npm:^2.0.18":
|
||||
version: 2.0.18
|
||||
resolution: "@ai-sdk/xai@npm:2.0.18"
|
||||
dependencies:
|
||||
"@ai-sdk/openai-compatible": "npm:1.0.9"
|
||||
"@ai-sdk/openai-compatible": "npm:1.0.17"
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.4"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.9"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/15a3ace8e06b42ee148d8d100cdf946919e0763c45fb1b85454e313d4de43426c6d162c333d07ad338a9de415dc9e68c50411a6ec0305dbc5edb7d623c2023da
|
||||
checksum: 10c0/7134501a2d315ec13605558aa24d7f5662885fe8b0491a634abefeb0c5c88517149677d1beff0c8abeec78a6dcd14573a2f57d96fa54a1d63d03820ac7ff827a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -2468,19 +2404,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherrystudio/ai-core@workspace:*, @cherrystudio/ai-core@workspace:packages/aiCore":
|
||||
"@cherrystudio/ai-core@workspace:^1.0.0-alpha.16, @cherrystudio/ai-core@workspace:packages/aiCore":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@cherrystudio/ai-core@workspace:packages/aiCore"
|
||||
dependencies:
|
||||
"@ai-sdk/anthropic": "npm:^2.0.5"
|
||||
"@ai-sdk/azure": "npm:^2.0.16"
|
||||
"@ai-sdk/deepseek": "npm:^1.0.9"
|
||||
"@ai-sdk/google": "npm:^2.0.13"
|
||||
"@ai-sdk/openai": "npm:^2.0.26"
|
||||
"@ai-sdk/openai-compatible": "npm:^1.0.9"
|
||||
"@ai-sdk/anthropic": "npm:^2.0.17"
|
||||
"@ai-sdk/azure": "npm:^2.0.30"
|
||||
"@ai-sdk/deepseek": "npm:^1.0.17"
|
||||
"@ai-sdk/google": "npm:^2.0.14"
|
||||
"@ai-sdk/openai": "npm:^2.0.30"
|
||||
"@ai-sdk/openai-compatible": "npm:^1.0.17"
|
||||
"@ai-sdk/provider": "npm:^2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:^3.0.4"
|
||||
"@ai-sdk/xai": "npm:^2.0.9"
|
||||
"@ai-sdk/provider-utils": "npm:^3.0.9"
|
||||
"@ai-sdk/xai": "npm:^2.0.18"
|
||||
tsdown: "npm:^0.12.9"
|
||||
typescript: "npm:^5.0.0"
|
||||
vitest: "npm:^3.2.4"
|
||||
@ -14115,6 +14051,87 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/native-preview-darwin-arm64@npm:7.0.0-dev.20250915.1":
|
||||
version: 7.0.0-dev.20250915.1
|
||||
resolution: "@typescript/native-preview-darwin-arm64@npm:7.0.0-dev.20250915.1"
|
||||
conditions: os=darwin & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/native-preview-darwin-x64@npm:7.0.0-dev.20250915.1":
|
||||
version: 7.0.0-dev.20250915.1
|
||||
resolution: "@typescript/native-preview-darwin-x64@npm:7.0.0-dev.20250915.1"
|
||||
conditions: os=darwin & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/native-preview-linux-arm64@npm:7.0.0-dev.20250915.1":
|
||||
version: 7.0.0-dev.20250915.1
|
||||
resolution: "@typescript/native-preview-linux-arm64@npm:7.0.0-dev.20250915.1"
|
||||
conditions: os=linux & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/native-preview-linux-arm@npm:7.0.0-dev.20250915.1":
|
||||
version: 7.0.0-dev.20250915.1
|
||||
resolution: "@typescript/native-preview-linux-arm@npm:7.0.0-dev.20250915.1"
|
||||
conditions: os=linux & cpu=arm
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/native-preview-linux-x64@npm:7.0.0-dev.20250915.1":
|
||||
version: 7.0.0-dev.20250915.1
|
||||
resolution: "@typescript/native-preview-linux-x64@npm:7.0.0-dev.20250915.1"
|
||||
conditions: os=linux & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/native-preview-win32-arm64@npm:7.0.0-dev.20250915.1":
|
||||
version: 7.0.0-dev.20250915.1
|
||||
resolution: "@typescript/native-preview-win32-arm64@npm:7.0.0-dev.20250915.1"
|
||||
conditions: os=win32 & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/native-preview-win32-x64@npm:7.0.0-dev.20250915.1":
|
||||
version: 7.0.0-dev.20250915.1
|
||||
resolution: "@typescript/native-preview-win32-x64@npm:7.0.0-dev.20250915.1"
|
||||
conditions: os=win32 & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript/native-preview@npm:latest":
|
||||
version: 7.0.0-dev.20250915.1
|
||||
resolution: "@typescript/native-preview@npm:7.0.0-dev.20250915.1"
|
||||
dependencies:
|
||||
"@typescript/native-preview-darwin-arm64": "npm:7.0.0-dev.20250915.1"
|
||||
"@typescript/native-preview-darwin-x64": "npm:7.0.0-dev.20250915.1"
|
||||
"@typescript/native-preview-linux-arm": "npm:7.0.0-dev.20250915.1"
|
||||
"@typescript/native-preview-linux-arm64": "npm:7.0.0-dev.20250915.1"
|
||||
"@typescript/native-preview-linux-x64": "npm:7.0.0-dev.20250915.1"
|
||||
"@typescript/native-preview-win32-arm64": "npm:7.0.0-dev.20250915.1"
|
||||
"@typescript/native-preview-win32-x64": "npm:7.0.0-dev.20250915.1"
|
||||
dependenciesMeta:
|
||||
"@typescript/native-preview-darwin-arm64":
|
||||
optional: true
|
||||
"@typescript/native-preview-darwin-x64":
|
||||
optional: true
|
||||
"@typescript/native-preview-linux-arm":
|
||||
optional: true
|
||||
"@typescript/native-preview-linux-arm64":
|
||||
optional: true
|
||||
"@typescript/native-preview-linux-x64":
|
||||
optional: true
|
||||
"@typescript/native-preview-win32-arm64":
|
||||
optional: true
|
||||
"@typescript/native-preview-win32-x64":
|
||||
optional: true
|
||||
bin:
|
||||
tsgo: bin/tsgo.js
|
||||
checksum: 10c0/88c8c4d497e610b05ef3a429959364fff7f0fc2b77f191909c15f886b21b06ceabdd9f89d9e5f903ee87076cfeca4d61ee609d2df897326ed115e23e01650fec
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/visitor-keys@npm:8.43.0":
|
||||
version: 8.43.0
|
||||
resolution: "@typescript-eslint/visitor-keys@npm:8.43.0"
|
||||
@ -14878,10 +14895,10 @@ __metadata:
|
||||
"@agentic/exa": "npm:^7.3.3"
|
||||
"@agentic/searxng": "npm:^7.3.3"
|
||||
"@agentic/tavily": "npm:^7.3.3"
|
||||
"@ai-sdk/amazon-bedrock": "npm:^3.0.0"
|
||||
"@ai-sdk/google-vertex": "npm:^3.0.25"
|
||||
"@ai-sdk/mistral": "npm:^2.0.0"
|
||||
"@ai-sdk/perplexity": "npm:^2.0.8"
|
||||
"@ai-sdk/amazon-bedrock": "npm:^3.0.21"
|
||||
"@ai-sdk/google-vertex": "npm:^3.0.27"
|
||||
"@ai-sdk/mistral": "npm:^2.0.14"
|
||||
"@ai-sdk/perplexity": "npm:^2.0.9"
|
||||
"@ant-design/v5-patch-for-react-19": "npm:^1.0.3"
|
||||
"@anthropic-ai/sdk": "npm:^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"
|
||||
@ -14889,7 +14906,7 @@ __metadata:
|
||||
"@aws-sdk/client-bedrock-runtime": "npm:^3.840.0"
|
||||
"@aws-sdk/client-s3": "npm:^3.840.0"
|
||||
"@biomejs/biome": "npm:2.2.4"
|
||||
"@cherrystudio/ai-core": "workspace:*"
|
||||
"@cherrystudio/ai-core": "workspace:^1.0.0-alpha.16"
|
||||
"@cherrystudio/embedjs": "npm:^0.1.31"
|
||||
"@cherrystudio/embedjs-libsql": "npm:^0.1.31"
|
||||
"@cherrystudio/embedjs-loader-csv": "npm:^0.1.31"
|
||||
@ -14989,6 +15006,7 @@ __metadata:
|
||||
"@types/tinycolor2": "npm:^1"
|
||||
"@types/turndown": "npm:^5.0.5"
|
||||
"@types/word-extractor": "npm:^1"
|
||||
"@typescript/native-preview": "npm:latest"
|
||||
"@uiw/codemirror-extensions-langs": "npm:^4.25.1"
|
||||
"@uiw/codemirror-themes-all": "npm:^4.25.1"
|
||||
"@uiw/react-codemirror": "npm:^4.25.1"
|
||||
@ -15000,7 +15018,7 @@ __metadata:
|
||||
"@viz-js/lang-dot": "npm:^1.0.5"
|
||||
"@viz-js/viz": "npm:^3.14.0"
|
||||
"@xyflow/react": "npm:^12.4.4"
|
||||
ai: "npm:^5.0.38"
|
||||
ai: "npm:^5.0.44"
|
||||
antd: "patch:antd@npm%3A5.27.0#~/.yarn/patches/antd-npm-5.27.0-aa91c36546.patch"
|
||||
archiver: "npm:^7.0.1"
|
||||
async-mutex: "npm:^0.5.0"
|
||||
@ -15022,6 +15040,7 @@ __metadata:
|
||||
diff: "npm:^8.0.2"
|
||||
docx: "npm:^9.0.2"
|
||||
dompurify: "npm:^3.2.6"
|
||||
dotenv: "npm:^17.2.2"
|
||||
dotenv-cli: "npm:^7.4.2"
|
||||
drizzle-kit: "npm:^0.31.4"
|
||||
drizzle-orm: "npm:^0.44.2"
|
||||
@ -15261,17 +15280,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ai@npm:^5.0.38":
|
||||
version: 5.0.38
|
||||
resolution: "ai@npm:5.0.38"
|
||||
"ai@npm:^5.0.44":
|
||||
version: 5.0.44
|
||||
resolution: "ai@npm:5.0.44"
|
||||
dependencies:
|
||||
"@ai-sdk/gateway": "npm:1.0.20"
|
||||
"@ai-sdk/gateway": "npm:1.0.23"
|
||||
"@ai-sdk/provider": "npm:2.0.0"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.8"
|
||||
"@ai-sdk/provider-utils": "npm:3.0.9"
|
||||
"@opentelemetry/api": "npm:1.9.0"
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4
|
||||
checksum: 10c0/9ea7a76ae5609574e9edb2f9541e2fe9cf0e7296547c5e9ae30ec000206c967b4c07fbb03b85f9027493f6877e15f6bfbe454faa793fca860826acf306982fc5
|
||||
checksum: 10c0/528c7e165f75715194204051ce0aa341d8dca7d5536c2abcf3df83ccda7399ed5d91deaa45a81340f93d2461b1c2fc5f740f7804dfd396927c71b0667403569b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -18405,6 +18424,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"dotenv@npm:^17.2.2":
|
||||
version: 17.2.2
|
||||
resolution: "dotenv@npm:17.2.2"
|
||||
checksum: 10c0/be66513504590aff6eccb14167625aed9bd42ce80547f4fe5d195860211971a7060949b57108dfaeaf90658f79e40edccd3f233f0a978bff507b5b1565ae162b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"drizzle-kit@npm:^0.31.4":
|
||||
version: 0.31.4
|
||||
resolution: "drizzle-kit@npm:0.31.4"
|
||||
@ -19659,7 +19685,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eventsource-parser@npm:^3.0.0, eventsource-parser@npm:^3.0.3":
|
||||
"eventsource-parser@npm:^3.0.0":
|
||||
version: 3.0.3
|
||||
resolution: "eventsource-parser@npm:3.0.3"
|
||||
checksum: 10c0/2594011630efba56cafafc8ed6bd9a50db8f6d5dd62089b0950346e7961828c16efe07a588bdea3ba79e568fd9246c8163824a2ffaade767e1fdb2270c1fae0b
|
||||
|
||||
Loading…
Reference in New Issue
Block a user