refactor: 消除硬编码,扩展语言支持,优化性能

This commit is contained in:
adnaan
2025-12-19 19:31:53 +08:00
parent 98595a120e
commit da027a93e4
11 changed files with 532 additions and 140 deletions
+11
View File
@@ -0,0 +1,11 @@
* text=auto eol=lf
*.ts text eol=lf
*.tsx text eol=lf
*.js text eol=lf
*.jsx text eol=lf
*.json text eol=lf
*.css text eol=lf
*.html text eol=lf
*.md text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
+63 -62
View File
@@ -11,6 +11,31 @@ import { registerAllHandlers, cleanupAllHandlers, updateLLMServiceWindow } from
import { lspManager } from './lspManager'
import { securityManager, updateWhitelist } from './security'
// 共享安全常量(与 renderer 保持一致)
const SECURITY_DEFAULTS = {
SHELL_COMMANDS: [
// 包管理器
'npm', 'yarn', 'pnpm', 'bun',
// 运行时
'node', 'npx', 'deno',
// 版本控制
'git',
// 编程语言
'python', 'python3', 'pip', 'pip3',
'java', 'javac', 'mvn', 'gradle',
'go', 'rust', 'cargo',
// 构建工具
'make', 'gcc', 'clang', 'cmake',
// 常用命令
'pwd', 'ls', 'dir', 'cat', 'type', 'echo', 'mkdir', 'touch', 'rm', 'mv', 'cp', 'cd',
],
GIT_SUBCOMMANDS: [
'status', 'log', 'diff', 'add', 'commit', 'push', 'pull',
'branch', 'checkout', 'merge', 'rebase', 'clone', 'remote',
'fetch', 'show', 'rev-parse', 'init', 'stash', 'tag',
],
} as const
// ==========================================
// Store 初始化
// ==========================================
@@ -29,41 +54,37 @@ function initStore() {
}
}
// 初始化 store
initStore()
// ==========================================
// 全局状态
// 窗口管理
// ==========================================
const windows = new Map<number, BrowserWindow>()
let lastActiveWindow: BrowserWindow | null = null
let isQuitting = false
const windows = new Set<BrowserWindow>()
let mainWindow: BrowserWindow | null = null
function getMainWindow() {
return lastActiveWindow || Array.from(windows.values())[0] || null
function getMainWindow(): BrowserWindow | null {
return mainWindow
}
// ==========================================
// 窗口创建
// ==========================================
function createWindow(isEmpty: boolean = false) {
// 图标路径:开发环境用 public,生产环境用 resources
const iconPath = app.isPackaged
? path.join(process.resourcesPath, 'icon.png')
: path.join(__dirname, '../../public/icon.png')
// 单例锁定
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
app.quit()
}
function createWindow(isEmpty = true): BrowserWindow {
const win = new BrowserWindow({
width: 1600,
height: 1000,
minWidth: 1200,
minHeight: 700,
frame: false,
titleBarStyle: 'hidden',
icon: iconPath,
trafficLightPosition: { x: 15, y: 15 },
backgroundColor: '#09090b',
show: false,
show: false, // 等待渲染完成后显示
titleBarStyle: 'hidden',
titleBarOverlay: false,
autoHideMenuBar: true,
webPreferences: {
preload: path.join(__dirname, '../preload/preload.js'),
contextIsolation: true,
@@ -71,51 +92,30 @@ function createWindow(isEmpty: boolean = false) {
},
})
const windowId = win.id
windows.set(windowId, win)
lastActiveWindow = win
windows.add(win)
if (!mainWindow) {
mainWindow = win
}
win.on('focus', () => {
lastActiveWindow = win
updateLLMServiceWindow(win)
})
// 每个窗口都需要更新 LLM service 的引用
updateLLMServiceWindow(win)
win.once('ready-to-show', () => {
win.show()
console.log(`[Main] Window ${windowId} shown`)
if (!app.isPackaged) {
win.webContents.openDevTools({ mode: 'detach' })
}
})
win.on('close', async (e) => {
if (windows.size === 1 && !isQuitting) {
// 最后一个窗口关闭时,执行全局清理
isQuitting = true
e.preventDefault()
console.log('[Main] Last window closing, starting cleanup...')
try {
cleanupAllHandlers()
await lspManager.stopAllServers()
console.log('[Main] Cleanup completed')
} catch (err) {
console.error('[Main] Cleanup error:', err)
}
win.destroy()
app.quit()
win.on('closed', () => {
windows.delete(win)
if (windows.size === 0) {
mainWindow = null
cleanupAllHandlers()
lspManager.stopAllServers()
} else {
// 非最后一个窗口,直接移除引用
windows.delete(windowId)
if (lastActiveWindow === win) {
lastActiveWindow = Array.from(windows.values())[0] || null
// 如果关闭的是 mainWindow,选择一个新的
if (mainWindow === win) {
mainWindow = windows.values().next().value ?? null
}
}
})
// 加载页面
const query = isEmpty ? '?empty=1' : ''
if (!app.isPackaged) {
win.loadURL(`http://localhost:5173${query}`)
if (process.env.NODE_ENV === 'development' || !app.isPackaged) {
win.loadURL(`http://localhost:5173${isEmpty ? '?empty=1' : ''}`)
} else {
win.loadFile(path.join(__dirname, '../renderer/index.html'), { query: isEmpty ? { empty: '1' } : undefined })
}
@@ -130,19 +130,20 @@ function createWindow(isEmpty: boolean = false) {
app.whenReady().then(() => {
console.log('[Security] 🔒 初始化安全模块...')
// 使用共享常量作为默认值
const securityConfig = mainStore.get('securitySettings', {
enablePermissionConfirm: true,
enableAuditLog: true,
strictWorkspaceMode: true,
allowedShellCommands: ['npm', 'yarn', 'pnpm', 'node', 'npx', 'git', 'python', 'python3', 'java', 'go', 'rust', 'cargo', 'make', 'gcc', 'clang', 'pwd', 'ls', 'cat', 'echo', 'mkdir', 'touch', 'rm', 'mv', 'cd'],
allowedGitSubcommands: ['status', 'log', 'diff', 'add', 'commit', 'push', 'pull', 'branch', 'checkout', 'merge', 'rebase', 'clone', 'remote', 'fetch', 'show', 'rev-parse', 'init'],
allowedShellCommands: [...SECURITY_DEFAULTS.SHELL_COMMANDS],
allowedGitSubcommands: [...SECURITY_DEFAULTS.GIT_SUBCOMMANDS],
}) as any
securityManager.updateConfig(securityConfig)
// 初始化白名单
const shellCommands = securityConfig.allowedShellCommands || ['npm', 'yarn', 'pnpm', 'node', 'npx', 'git']
const gitCommands = securityConfig.allowedGitSubcommands || ['status', 'log', 'diff', 'add', 'commit', 'push', 'pull', 'branch', 'checkout', 'merge', 'rebase', 'clone', 'remote', 'fetch', 'show', 'rev-parse', 'init']
const shellCommands = securityConfig.allowedShellCommands || [...SECURITY_DEFAULTS.SHELL_COMMANDS]
const gitCommands = securityConfig.allowedGitSubcommands || [...SECURITY_DEFAULTS.GIT_SUBCOMMANDS]
updateWhitelist(shellCommands, gitCommands)
console.log('[Security] ✅ 安全模块已初始化')
+16 -9
View File
@@ -1,4 +1,4 @@
import { useEffect, useState, useCallback } from 'react'
import { useEffect, useState, useCallback, lazy, Suspense } from 'react'
import { useStore } from './store'
import TitleBar from './components/TitleBar'
import Sidebar from './components/Sidebar'
@@ -11,8 +11,6 @@ import KeyboardShortcuts from './components/KeyboardShortcuts'
import QuickOpen from './components/QuickOpen'
import ActivityBar from './components/ActivityBar'
import StatusBar from './components/StatusBar'
import ComposerPanel from './components/ComposerPanel'
import OnboardingWizard from './components/OnboardingWizard'
import { ToastProvider, useToast, setGlobalToast } from './components/Toast'
import { GlobalConfirmDialog } from './components/ConfirmDialog'
import { ErrorBoundary } from './components/ErrorBoundary'
@@ -26,8 +24,13 @@ import { checkpointService } from './agent/checkpointService'
import { useAgentStore } from './agent/core/AgentStore'
import { keybindingService } from './services/keybindingService'
import { registerCoreCommands } from './config/commands'
import { LAYOUT_LIMITS } from '../shared/constants'
import noiseSvg from './assets/images/noise.svg'
// 懒加载大组件以优化首屏性能
const ComposerPanel = lazy(() => import('./components/ComposerPanel'))
const OnboardingWizard = lazy(() => import('./components/OnboardingWizard'))
// 暴露 store 给插件系统
; (window as any).__ADNIFY_STORE__ = { getState: () => useStore.getState() }
@@ -195,20 +198,20 @@ function AppContent() {
return cleanup
}, [])
// Resize Logic
// Resize Logic - 使用共享常量
useEffect(() => {
if (!isResizingSidebar && !isResizingChat) return
const handleMouseMove = (e: MouseEvent) => {
if (isResizingSidebar) {
const newWidth = e.clientX - 48 // 48 is ActivityBar width
if (newWidth > 150 && newWidth < 600) {
const newWidth = e.clientX - LAYOUT_LIMITS.ACTIVITY_BAR_WIDTH
if (newWidth > LAYOUT_LIMITS.SIDEBAR_MIN_WIDTH && newWidth < LAYOUT_LIMITS.SIDEBAR_MAX_WIDTH) {
setSidebarWidth(newWidth)
}
}
if (isResizingChat) {
const newWidth = window.innerWidth - e.clientX
if (newWidth > 300 && newWidth < 800) {
if (newWidth > LAYOUT_LIMITS.CHAT_MIN_WIDTH && newWidth < LAYOUT_LIMITS.CHAT_MAX_WIDTH) {
setChatWidth(newWidth)
}
}
@@ -355,10 +358,14 @@ function AppContent() {
<QuickOpen onClose={() => setShowQuickOpen(false)} />
)}
{showComposer && (
<ComposerPanel onClose={() => setShowComposer(false)} />
<Suspense fallback={null}>
<ComposerPanel onClose={() => setShowComposer(false)} />
</Suspense>
)}
{showOnboarding && isInitialized && (
<OnboardingWizard onComplete={() => setShowOnboarding(false)} />
<Suspense fallback={null}>
<OnboardingWizard onComplete={() => setShowOnboarding(false)} />
</Suspense>
)}
{showAbout && <AboutDialog onClose={() => setShowAbout(false)} />}
<GlobalConfirmDialog />
+8 -7
View File
@@ -5,18 +5,19 @@
import { ChatMode } from '../store'
import { rulesService } from './rulesService'
import { FILE_LIMITS } from '../../shared/constants'
// Search/Replace 块格式 (Git 风格,LLM 更熟悉)
export const ORIGINAL = '<<<<<<< SEARCH'
export const DIVIDER = '======='
export const FINAL = '>>>>>>> REPLACE'
// 限制常量(与 editorConfig.ts 保持一致
export const MAX_FILE_CHARS = 60000
export const MAX_DIR_ITEMS = 150
export const MAX_SEARCH_RESULTS = 30
export const MAX_TERMINAL_OUTPUT = 3000
export const MAX_CONTEXT_CHARS = 30000
// 限制常量(从共享配置导入
export const MAX_FILE_CHARS = FILE_LIMITS.MAX_FILE_CHARS
export const MAX_DIR_ITEMS = FILE_LIMITS.MAX_DIR_ITEMS
export const MAX_SEARCH_RESULTS = FILE_LIMITS.MAX_SEARCH_RESULTS
export const MAX_TERMINAL_OUTPUT = FILE_LIMITS.MAX_TERMINAL_OUTPUT
export const MAX_CONTEXT_CHARS = FILE_LIMITS.MAX_CONTEXT_CHARS
// Search/Replace 块模板
const searchReplaceBlockTemplate = `\
@@ -161,7 +162,7 @@ export async function buildSystemPrompt(
// 获取提示词模板
const { getPromptTemplateById, getDefaultPromptTemplate } = await import('./promptTemplates')
const template = promptTemplateId
const template = promptTemplateId
? getPromptTemplateById(promptTemplateId) || getDefaultPromptTemplate()
: getDefaultPromptTemplate()
+4 -14
View File
@@ -4,6 +4,8 @@
* 双重存储:localStorage(快速读取)+ 文件(持久化备份)
*/
import { IGNORED_DIRECTORIES } from '../../shared/languages'
export interface EditorConfig {
// 编辑器外观
fontSize: number
@@ -118,20 +120,8 @@ export const defaultEditorConfig: EditorConfig = {
maxSingleFileChars: 6000, // 单文件最多 6000 字符
},
// 忽略的目录
ignoredDirectories: [
'node_modules',
'dist',
'build',
'.git',
'.next',
'coverage',
'__pycache__',
'.cache',
'out',
'.vscode',
'.idea',
],
// 忽略的目录(使用共享常量)
ignoredDirectories: [...IGNORED_DIRECTORIES],
}
// 存储 key
+5 -26
View File
@@ -12,6 +12,7 @@
import { useStore } from '../store'
import { getEditorConfig } from '../config/editorConfig'
import { FIM_CAPABLE_MODELS, getLanguageFromPath as sharedGetLanguageFromPath } from '../../shared/languages'
// ============ Interfaces ============
@@ -69,16 +70,8 @@ export interface CompletionOptions {
maxCandidates: number // Max candidates to generate
}
// FIM-capable models
const FIM_MODELS = [
'deepseek-coder',
'codellama',
'starcoder',
'code-llama',
'deepseek',
'qwen-coder',
'yi-coder',
]
// FIM-capable models (from shared config)
const FIM_MODELS = FIM_CAPABLE_MODELS
// 从配置获取默认选项
@@ -221,22 +214,8 @@ function debounce<T extends (...args: Parameters<T>) => ReturnType<T>>(
// ============ Language Detection ============
const LANGUAGE_MAP: Record<string, string> = {
ts: 'typescript', tsx: 'typescript',
js: 'javascript', jsx: 'javascript', mjs: 'javascript', cjs: 'javascript',
py: 'python', rs: 'rust', go: 'go', java: 'java',
cpp: 'cpp', c: 'c', h: 'c', hpp: 'cpp',
css: 'css', scss: 'scss', less: 'less',
html: 'html', htm: 'html', vue: 'html', svelte: 'html',
json: 'json', yaml: 'yaml', yml: 'yaml',
md: 'markdown', sql: 'sql', sh: 'shell', bash: 'shell',
}
function getLanguageFromPath(path: string): string {
const ext = path.split('.').pop()?.toLowerCase() || ''
return LANGUAGE_MAP[ext] || 'plaintext'
}
// Use shared language configuration
const getLanguageFromPath = sharedGetLanguageFromPath
// ============ Import Analysis ============
+3 -21
View File
@@ -4,6 +4,7 @@
*/
import { useStore } from '../store'
import { EXTENSION_TO_LANGUAGE, LSP_SUPPORTED_LANGUAGES } from '../../shared/languages'
// 文档版本追踪
const documentVersions = new Map<string, number>()
@@ -37,33 +38,14 @@ export function getFileWorkspaceRoot(filePath: string): string | null {
*/
export function getLanguageId(filePath: string): string {
const ext = filePath.split('.').pop()?.toLowerCase() || ''
const languageMap: Record<string, string> = {
ts: 'typescript',
tsx: 'typescriptreact',
js: 'javascript',
jsx: 'javascriptreact',
mjs: 'javascript',
cjs: 'javascript',
html: 'html',
htm: 'html',
css: 'css',
scss: 'scss',
less: 'less',
json: 'json',
jsonc: 'jsonc',
}
return languageMap[ext] || 'plaintext'
return EXTENSION_TO_LANGUAGE[ext] || 'plaintext'
}
/**
* 检查语言是否支持 LSP
*/
export function isLanguageSupported(languageId: string): boolean {
const supported = [
'typescript', 'typescriptreact', 'javascript', 'javascriptreact',
'html', 'css', 'scss', 'less', 'json', 'jsonc',
]
return supported.includes(languageId)
return (LSP_SUPPORTED_LANGUAGES as readonly string[]).includes(languageId)
}
/**
+3 -1
View File
@@ -2,6 +2,7 @@
* 设置相关状态切片
*/
import { StateCreator } from 'zustand'
import { SECURITY_DEFAULTS } from '../../../shared/constants'
export type ProviderType = 'openai' | 'anthropic' | 'gemini' | 'deepseek' | 'groq' | 'mistral' | 'ollama' | 'custom'
@@ -77,11 +78,12 @@ const defaultProviderConfigs: Record<string, ProviderModelConfig> = {
custom: { customModels: [] },
}
// 使用共享常量作为默认安全设置
const defaultSecuritySettings: SecuritySettings = {
enablePermissionConfirm: true,
enableAuditLog: true,
strictWorkspaceMode: true,
allowedShellCommands: ['npm', 'yarn', 'pnpm', 'node', 'npx', 'git', 'ls', 'cat', 'echo', 'pwd'],
allowedShellCommands: [...SECURITY_DEFAULTS.SHELL_COMMANDS],
showSecurityWarnings: true,
}
+116
View File
@@ -0,0 +1,116 @@
/**
* 共享常量配置
* 集中管理所有硬编码值,实现定制化
*/
// ==========================================
// 文件和搜索限制(原 prompts.ts 硬编码)
// ==========================================
export const FILE_LIMITS = {
/** 单个文件最大字符数 */
MAX_FILE_CHARS: 60000,
/** 目录列表最大条目数 */
MAX_DIR_ITEMS: 150,
/** 搜索结果最大数量 */
MAX_SEARCH_RESULTS: 30,
/** 终端输出最大字符数 */
MAX_TERMINAL_OUTPUT: 3000,
/** AI 上下文最大字符数 */
MAX_CONTEXT_CHARS: 30000,
} as const
// ==========================================
// 布局限制(原 App.tsx 硬编码)
// ==========================================
export const LAYOUT_LIMITS = {
/** ActivityBar 宽度 */
ACTIVITY_BAR_WIDTH: 48,
/** 侧边栏最小宽度 */
SIDEBAR_MIN_WIDTH: 150,
/** 侧边栏最大宽度 */
SIDEBAR_MAX_WIDTH: 600,
/** 聊天面板最小宽度 */
CHAT_MIN_WIDTH: 300,
/** 聊天面板最大宽度 */
CHAT_MAX_WIDTH: 800,
} as const
// ==========================================
// 窗口默认值(原 main.ts 硬编码)
// ==========================================
export const WINDOW_DEFAULTS = {
WIDTH: 1600,
HEIGHT: 1000,
MIN_WIDTH: 1200,
MIN_HEIGHT: 700,
BACKGROUND_COLOR: '#09090b',
} as const
// ==========================================
// 安全设置默认值(统一 main.ts 和 settingsSlice.ts
// ==========================================
export const SECURITY_DEFAULTS = {
/** 允许的 Shell 命令 */
SHELL_COMMANDS: [
// 包管理器
'npm', 'yarn', 'pnpm', 'bun',
// 运行时
'node', 'npx', 'deno',
// 版本控制
'git',
// 编程语言
'python', 'python3', 'pip', 'pip3',
'java', 'javac', 'mvn', 'gradle',
'go', 'rust', 'cargo',
// 构建工具
'make', 'gcc', 'clang', 'cmake',
// 常用命令
'pwd', 'ls', 'dir', 'cat', 'type', 'echo', 'mkdir', 'touch', 'rm', 'mv', 'cp', 'cd',
],
/** 允许的 Git 子命令 */
GIT_SUBCOMMANDS: [
'status', 'log', 'diff', 'add', 'commit', 'push', 'pull',
'branch', 'checkout', 'merge', 'rebase', 'clone', 'remote',
'fetch', 'show', 'rev-parse', 'init', 'stash', 'tag',
],
} as const
// ==========================================
// AI 相关默认值(原 editorConfig.ts 和 settingsSlice.ts
// ==========================================
export const AI_DEFAULTS = {
/** 默认提供商 */
DEFAULT_PROVIDER: 'openai' as const,
/** 默认模型 */
DEFAULT_MODEL: 'gpt-4o',
/** 最大工具调用循环数 */
MAX_TOOL_LOOPS: 15,
/** 补全最大 token 数 */
COMPLETION_MAX_TOKENS: 256,
/** 补全温度 */
COMPLETION_TEMPERATURE: 0.1,
} as const
// ==========================================
// 性能相关默认值
// ==========================================
export const PERFORMANCE_DEFAULTS = {
/** 文件变化防抖延迟 (ms) */
FILE_CHANGE_DEBOUNCE_MS: 300,
/** 代码补全防抖延迟 (ms) */
COMPLETION_DEBOUNCE_MS: 300,
/** 搜索防抖延迟 (ms) */
SEARCH_DEBOUNCE_MS: 200,
/** Git 状态刷新间隔 (ms) */
GIT_STATUS_INTERVAL_MS: 5000,
/** API 请求超时 (ms) */
REQUEST_TIMEOUT_MS: 120000,
/** 命令执行超时 (ms) */
COMMAND_TIMEOUT_MS: 30000,
} as const
+299
View File
@@ -0,0 +1,299 @@
/**
* 语言配置
* 统一管理文件扩展名到语言 ID 的映射,避免重复定义
*/
// ==========================================
// 文件扩展名 -> 语言 ID 映射
// ==========================================
export const EXTENSION_TO_LANGUAGE: Record<string, string> = {
// JavaScript / TypeScript
ts: 'typescript',
tsx: 'typescriptreact',
js: 'javascript',
jsx: 'javascriptreact',
mjs: 'javascript',
cjs: 'javascript',
// Python
py: 'python',
pyw: 'python',
pyi: 'python',
pyx: 'python',
// Rust
rs: 'rust',
// Go
go: 'go',
// Java / Kotlin / Scala
java: 'java',
kt: 'kotlin',
kts: 'kotlin',
scala: 'scala',
// C / C++
c: 'c',
h: 'c',
cpp: 'cpp',
hpp: 'cpp',
cc: 'cpp',
cxx: 'cpp',
hxx: 'cpp',
// C#
cs: 'csharp',
// Web - Markup
html: 'html',
htm: 'html',
vue: 'vue',
svelte: 'svelte',
// Web - Styles
css: 'css',
scss: 'scss',
sass: 'sass',
less: 'less',
styl: 'stylus',
// Data formats
json: 'json',
jsonc: 'jsonc',
json5: 'json5',
yaml: 'yaml',
yml: 'yaml',
toml: 'toml',
xml: 'xml',
svg: 'xml',
// Shell
sh: 'shell',
bash: 'shell',
zsh: 'shell',
fish: 'shell',
ps1: 'powershell',
psm1: 'powershell',
bat: 'batch',
cmd: 'batch',
// Markdown / Documentation
md: 'markdown',
mdx: 'mdx',
rst: 'restructuredtext',
tex: 'latex',
// Database
sql: 'sql',
mysql: 'sql',
pgsql: 'sql',
// Other languages
rb: 'ruby',
php: 'php',
swift: 'swift',
dart: 'dart',
lua: 'lua',
r: 'r',
R: 'r',
jl: 'julia',
ex: 'elixir',
exs: 'elixir',
erl: 'erlang',
hrl: 'erlang',
hs: 'haskell',
lhs: 'haskell',
ml: 'ocaml',
mli: 'ocaml',
clj: 'clojure',
cljs: 'clojure',
fs: 'fsharp',
fsx: 'fsharp',
nim: 'nim',
zig: 'zig',
v: 'v',
sol: 'solidity',
// Config files
dockerfile: 'dockerfile',
makefile: 'makefile',
cmake: 'cmake',
gradle: 'groovy',
groovy: 'groovy',
// GraphQL
graphql: 'graphql',
gql: 'graphql',
// Protocol Buffers
proto: 'protobuf',
}
// ==========================================
// LSP 支持的语言
// ==========================================
export const LSP_SUPPORTED_LANGUAGES = [
// 完全支持(内置 LSP
'typescript',
'typescriptreact',
'javascript',
'javascriptreact',
'html',
'css',
'scss',
'less',
'json',
'jsonc',
] as const
// 可扩展支持(需要额外 LSP 服务器)
export const LSP_EXTENSIBLE_LANGUAGES = [
'python', // pylsp / pyright
'rust', // rust-analyzer
'go', // gopls
'java', // jdtls
'csharp', // omnisharp
] as const
// ==========================================
// 忽略目录(完整列表)
// ==========================================
export const IGNORED_DIRECTORIES = [
// Node.js / JavaScript
'node_modules',
'.npm',
'.yarn',
'.pnpm-store',
'bower_components',
// Build outputs
'dist',
'build',
'out',
'.next',
'.nuxt',
'.output',
'.svelte-kit',
'.parcel-cache',
'.turbo',
// Caches
'.cache',
'__pycache__',
'.pytest_cache',
'.mypy_cache',
'.ruff_cache',
'.tox',
// Version control
'.git',
'.svn',
'.hg',
'.bzr',
// IDE / Editor
'.vscode',
'.idea',
'.vs',
'.fleet',
// Language-specific
'vendor', // Go, PHP, Ruby
'target', // Rust, Java (Maven)
'.venv', // Python
'venv', // Python
'env', // Python
'.virtualenv', // Python
'__pypackages__', // Python (PDM)
'.gradle', // Java (Gradle)
'.maven', // Java (Maven)
'Pods', // iOS (CocoaPods)
'DerivedData', // iOS (Xcode)
'.dart_tool', // Dart
'.pub-cache', // Dart
'zig-cache', // Zig
'_build', // Elixir
'deps', // Elixir
// Coverage / Testing
'coverage',
'.nyc_output',
'htmlcov',
'.coverage',
// Misc
'tmp',
'temp',
'logs',
'.DS_Store',
'Thumbs.db',
] as const
// ==========================================
// FIM (Fill-in-the-Middle) 支持的模型
// ==========================================
export const FIM_CAPABLE_MODELS = [
'deepseek-coder',
'deepseek-coder-v2',
'codellama',
'code-llama',
'starcoder',
'starcoder2',
'qwen-coder',
'qwen2.5-coder',
'yi-coder',
'codestral',
'codegemma',
] as const
// ==========================================
// 语言 ID -> LSP 语言 ID 映射 (用于 LSP 通信)
// ==========================================
export const LANGUAGE_TO_LSP_ID: Record<string, string> = {
typescript: 'typescript',
typescriptreact: 'typescriptreact',
javascript: 'javascript',
javascriptreact: 'javascriptreact',
html: 'html',
css: 'css',
scss: 'scss',
less: 'less',
json: 'json',
jsonc: 'jsonc',
python: 'python',
rust: 'rust',
go: 'go',
java: 'java',
}
// ==========================================
// 辅助函数
// ==========================================
/**
* 根据文件路径获取语言 ID
*/
export function getLanguageFromPath(filePath: string): string {
const ext = filePath.split('.').pop()?.toLowerCase() || ''
return EXTENSION_TO_LANGUAGE[ext] || 'plaintext'
}
/**
* 检查语言是否支持 LSP
*/
export function isLspSupported(languageId: string): boolean {
return (LSP_SUPPORTED_LANGUAGES as readonly string[]).includes(languageId)
}
/**
* 检查目录是否应被忽略
*/
export function shouldIgnoreDirectory(dirName: string): boolean {
return IGNORED_DIRECTORIES.includes(dirName as any)
}
+4
View File
@@ -95,6 +95,10 @@ export default defineConfig({
'state': ['zustand'],
// UI 图标
'icons': ['lucide-react'],
// 终端相关 - 懒加载优化
'terminal': ['@xterm/xterm', '@xterm/addon-fit', '@xterm/addon-webgl', '@xterm/addon-web-links'],
// Markdown 渲染 - 懒加载优化
'markdown': ['react-markdown', 'react-syntax-highlighter'],
},
},
},