feat: 升级至 v0.2.2 — 工作空间路径注入、Provider 切换修复、编码与样式优化
功能增强: - System Prompt 注入当前工作空间路径到动态区(LLM 可使用绝对路径调用工具) - ContextBuilder.buildSystemPrompt 新增 workspacePath 参数 Provider 切换修复: - reloadAdapter 返回 boolean,失败时 sendMessage 中止发送 - 切换 Provider 时自动清空 apiKey(不同 Provider key 不通用) - apiKey 为空时显示警告提示 - Provider 切换事件加 sessionId 字段 编码修复: - run_command 使用 encoding: 'buffer' 获取原始字节 - 新增 decodeBuffer 智能解码:UTF-8 严格 → GBK → UTF-8 宽松 - 修复不响应 chcp 的 Windows 命令中文乱码问题 样式优化: - 代码块底色改用主题变量(灰底主题色文字,双主题适配) - 表格标题 th/td 底色和文字色改用主题变量 - CodeBlock 组件 pre 背景从 secondary.main 改为 background.default - 设置面板已自动执行工具行 opacity 0.8→0.15(淡绿底,文字清晰) 版本号 0.2.1 → 0.2.2
This commit is contained in:
@@ -7,6 +7,7 @@ import { Dialog, DialogContent, DialogTitle, Button, TextField, Select, MenuItem
|
||||
import { X, Settings, Bot, Wrench, Server, Palette, FileText, Eye, EyeOff, FolderOpen, Globe } from 'lucide-react';
|
||||
import { useUIStore, type ThemeMode } from '@renderer/stores/ui-store';
|
||||
import { useAgentStore } from '@renderer/stores/agent-store';
|
||||
import { PROVIDER_LABELS } from '@renderer/lib/constants';
|
||||
|
||||
type SettingsTab = 'workspace' | 'llm' | 'agent' | 'tools' | 'mcp' | 'searxng' | 'appearance' | 'logs';
|
||||
const TABS: { id: SettingsTab; label: string; icon: typeof Settings }[] = [
|
||||
@@ -118,11 +119,13 @@ function LLMSettings() {
|
||||
}
|
||||
}, [provider, numCtx]);
|
||||
|
||||
// 切换 Provider 时自动填充默认 URL + 清空 Ollama 的 apiKey
|
||||
// 切换 Provider 时自动填充默认 URL + 清空 apiKey(不同 Provider 的 key 不通用)
|
||||
const handleProviderChange = (newProvider: string) => {
|
||||
const oldProvider = provider;
|
||||
setProvider(newProvider);
|
||||
// Ollama 不需要 API Key,切换到 Ollama 时清空旧 key
|
||||
if (newProvider === 'ollama' && apiKey) {
|
||||
// 切换 Provider 时清空 apiKey(不同 Provider 的 key 格式不同,避免用旧 key 调用新 API 导致 401)
|
||||
// Ollama 不需要 apiKey,也一并清空
|
||||
if (oldProvider !== newProvider && apiKey) {
|
||||
setApiKey('');
|
||||
}
|
||||
// 自动填充默认 URL(仅在 URL 为空或与旧 provider 默认 URL 匹配时)
|
||||
@@ -146,9 +149,16 @@ function LLMSettings() {
|
||||
<TextField size="small" label="API Base URL" value={baseURL} onChange={(e) => setBaseURL(e.target.value)} placeholder="如 https://api.deepseek.com" />
|
||||
<TextField size="small" label="模型名称" value={model} onChange={(e) => setModel(e.target.value)} placeholder="如 deepseek-v4-pro、qwen3:latest" />
|
||||
{provider !== 'ollama' && (
|
||||
<TextField size="small" label="API Key" type={showKey ? 'text' : 'password'} value={apiKey} onChange={(e) => setApiKey(e.target.value)} placeholder="sk-..."
|
||||
slotProps={{ input: { endAdornment: <IconButton size="small" onClick={() => setShowKey(!showKey)}>{showKey ? <EyeOff size={14} /> : <Eye size={14} />}</IconButton> } }}
|
||||
/>
|
||||
<>
|
||||
<TextField size="small" label="API Key" type={showKey ? 'text' : 'password'} value={apiKey} onChange={(e) => setApiKey(e.target.value)} placeholder="sk-..."
|
||||
slotProps={{ input: { endAdornment: <IconButton size="small" onClick={() => setShowKey(!showKey)}>{showKey ? <EyeOff size={14} /> : <Eye size={14} />}</IconButton> } }}
|
||||
/>
|
||||
{!apiKey && (
|
||||
<Typography variant="caption" sx={{ color: 'warning.main', fontSize: 11 }}>
|
||||
⚠ 请输入 {PROVIDER_LABELS[provider] ?? provider} 的 API Key,否则发送消息会报错
|
||||
</Typography>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{provider === 'ollama' && (
|
||||
<TextField
|
||||
@@ -292,9 +302,9 @@ function ToolsSettings() {
|
||||
</Typography>
|
||||
) : (
|
||||
autoExecToolDetails.map((t) => (
|
||||
<Stack key={t.name} direction="row" sx={{ py: 1, px: 1.5, borderRadius: 1.5, bgcolor: 'success.main', opacity: 0.8, justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Stack key={t.name} direction="row" sx={{ py: 1, px: 1.5, borderRadius: 1.5, bgcolor: 'success.main', opacity: 0.15, justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Stack direction="row" spacing={1} sx={{ alignItems: 'center', minWidth: 0, flex: 1 }}>
|
||||
<Typography variant="body2" sx={{ fontFamily: 'monospace', fontSize: 12 }}>{t.name}</Typography>
|
||||
<Typography variant="body2" sx={{ fontFamily: 'monospace', fontSize: 12, color: 'text.primary' }}>{t.name}</Typography>
|
||||
<Chip label="自动" size="small" color="success" sx={{ height: 16, fontSize: 9 }} />
|
||||
</Stack>
|
||||
<Button size="small" color="warning" variant="outlined" sx={{ fontSize: 10, minWidth: 70 }} onClick={() => handleSetAutoExec(t.name, false)}>
|
||||
|
||||
Reference in New Issue
Block a user