mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-12 02:37:45 +08:00
feat: enhance internationalization support and improve GPU mode selector with Python environment checks
This commit is contained in:
@@ -1734,7 +1734,9 @@ const i18n = {
|
|||||||
'discovery.title': 'Issue Discovery',
|
'discovery.title': 'Issue Discovery',
|
||||||
'discovery.description': 'Discover potential issues from multiple perspectives',
|
'discovery.description': 'Discover potential issues from multiple perspectives',
|
||||||
'discovery.noSessions': 'No discovery sessions',
|
'discovery.noSessions': 'No discovery sessions',
|
||||||
|
'discovery.noDiscoveries': 'No discoveries yet',
|
||||||
'discovery.runHint': 'Run /issue:discover to start discovering issues',
|
'discovery.runHint': 'Run /issue:discover to start discovering issues',
|
||||||
|
'discovery.runCommand': 'Run /issue:discover to start discovering issues',
|
||||||
'discovery.sessions': 'Sessions',
|
'discovery.sessions': 'Sessions',
|
||||||
'discovery.findings': 'Findings',
|
'discovery.findings': 'Findings',
|
||||||
'discovery.phase': 'Phase',
|
'discovery.phase': 'Phase',
|
||||||
@@ -1769,10 +1771,18 @@ const i18n = {
|
|||||||
'discovery.confidence': 'Confidence',
|
'discovery.confidence': 'Confidence',
|
||||||
'discovery.suggestedIssue': 'Suggested Issue',
|
'discovery.suggestedIssue': 'Suggested Issue',
|
||||||
'discovery.externalRef': 'External Reference',
|
'discovery.externalRef': 'External Reference',
|
||||||
'discovery.noFindings': 'No findings in this session',
|
'discovery.noFindings': 'No findings match your filters',
|
||||||
'discovery.filterPerspective': 'Filter by Perspective',
|
'discovery.filterPerspective': 'Filter by Perspective',
|
||||||
'discovery.filterPriority': 'Filter by Priority',
|
'discovery.filterPriority': 'Filter by Priority',
|
||||||
'discovery.filterAll': 'All',
|
'discovery.filterAll': 'All',
|
||||||
|
'discovery.allPerspectives': 'All Perspectives',
|
||||||
|
'discovery.allPriorities': 'All Priorities',
|
||||||
|
'discovery.selectFinding': 'Select a finding to preview',
|
||||||
|
'discovery.location': 'Location',
|
||||||
|
'discovery.code': 'Code',
|
||||||
|
'discovery.impact': 'Impact',
|
||||||
|
'discovery.recommendation': 'Recommendation',
|
||||||
|
'discovery.exportAsIssues': 'Export as Issues',
|
||||||
'discovery.deleteSession': 'Delete Session',
|
'discovery.deleteSession': 'Delete Session',
|
||||||
'discovery.confirmDelete': 'Are you sure you want to delete this discovery session?',
|
'discovery.confirmDelete': 'Are you sure you want to delete this discovery session?',
|
||||||
'discovery.deleted': 'Discovery session deleted',
|
'discovery.deleted': 'Discovery session deleted',
|
||||||
@@ -3649,7 +3659,9 @@ const i18n = {
|
|||||||
'discovery.title': '议题发现',
|
'discovery.title': '议题发现',
|
||||||
'discovery.description': '从多个视角发现潜在问题',
|
'discovery.description': '从多个视角发现潜在问题',
|
||||||
'discovery.noSessions': '暂无发现会话',
|
'discovery.noSessions': '暂无发现会话',
|
||||||
|
'discovery.noDiscoveries': '暂无发现',
|
||||||
'discovery.runHint': '运行 /issue:discover 开始发现问题',
|
'discovery.runHint': '运行 /issue:discover 开始发现问题',
|
||||||
|
'discovery.runCommand': '运行 /issue:discover 开始发现问题',
|
||||||
'discovery.sessions': '会话',
|
'discovery.sessions': '会话',
|
||||||
'discovery.findings': '发现',
|
'discovery.findings': '发现',
|
||||||
'discovery.phase': '阶段',
|
'discovery.phase': '阶段',
|
||||||
@@ -3684,10 +3696,18 @@ const i18n = {
|
|||||||
'discovery.confidence': '置信度',
|
'discovery.confidence': '置信度',
|
||||||
'discovery.suggestedIssue': '建议议题',
|
'discovery.suggestedIssue': '建议议题',
|
||||||
'discovery.externalRef': '外部参考',
|
'discovery.externalRef': '外部参考',
|
||||||
'discovery.noFindings': '此会话暂无发现',
|
'discovery.noFindings': '没有匹配的发现',
|
||||||
'discovery.filterPerspective': '按视角筛选',
|
'discovery.filterPerspective': '按视角筛选',
|
||||||
'discovery.filterPriority': '按优先级筛选',
|
'discovery.filterPriority': '按优先级筛选',
|
||||||
'discovery.filterAll': '全部',
|
'discovery.filterAll': '全部',
|
||||||
|
'discovery.allPerspectives': '所有视角',
|
||||||
|
'discovery.allPriorities': '所有优先级',
|
||||||
|
'discovery.selectFinding': '选择一个发现以预览',
|
||||||
|
'discovery.location': '位置',
|
||||||
|
'discovery.code': '代码',
|
||||||
|
'discovery.impact': '影响',
|
||||||
|
'discovery.recommendation': '建议',
|
||||||
|
'discovery.exportAsIssues': '导出为议题',
|
||||||
'discovery.deleteSession': '删除会话',
|
'discovery.deleteSession': '删除会话',
|
||||||
'discovery.confirmDelete': '确定要删除此发现会话吗?',
|
'discovery.confirmDelete': '确定要删除此发现会话吗?',
|
||||||
'discovery.deleted': '发现会话已删除',
|
'discovery.deleted': '发现会话已删除',
|
||||||
|
|||||||
@@ -446,6 +446,12 @@ async function loadSemanticDepsStatus() {
|
|||||||
* Build GPU mode selector HTML
|
* Build GPU mode selector HTML
|
||||||
*/
|
*/
|
||||||
function buildGpuModeSelector(gpuInfo) {
|
function buildGpuModeSelector(gpuInfo) {
|
||||||
|
// Check if DirectML is unavailable due to Python environment
|
||||||
|
var directmlUnavailableReason = null;
|
||||||
|
if (!gpuInfo.available.includes('directml') && gpuInfo.pythonEnv && gpuInfo.pythonEnv.error) {
|
||||||
|
directmlUnavailableReason = gpuInfo.pythonEnv.error;
|
||||||
|
}
|
||||||
|
|
||||||
var modes = [
|
var modes = [
|
||||||
{
|
{
|
||||||
id: 'cpu',
|
id: 'cpu',
|
||||||
@@ -457,10 +463,13 @@ function buildGpuModeSelector(gpuInfo) {
|
|||||||
{
|
{
|
||||||
id: 'directml',
|
id: 'directml',
|
||||||
label: 'DirectML',
|
label: 'DirectML',
|
||||||
desc: t('codexlens.directmlModeDesc') || 'Windows GPU (NVIDIA/AMD/Intel)',
|
desc: directmlUnavailableReason
|
||||||
|
? directmlUnavailableReason
|
||||||
|
: (t('codexlens.directmlModeDesc') || 'Windows GPU (NVIDIA/AMD/Intel)'),
|
||||||
icon: 'cpu',
|
icon: 'cpu',
|
||||||
available: gpuInfo.available.includes('directml'),
|
available: gpuInfo.available.includes('directml'),
|
||||||
recommended: gpuInfo.mode === 'directml'
|
recommended: gpuInfo.mode === 'directml',
|
||||||
|
warning: directmlUnavailableReason
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'cuda',
|
id: 'cuda',
|
||||||
@@ -487,6 +496,7 @@ function buildGpuModeSelector(gpuInfo) {
|
|||||||
var isDisabled = !mode.available;
|
var isDisabled = !mode.available;
|
||||||
var isRecommended = mode.recommended;
|
var isRecommended = mode.recommended;
|
||||||
var isDefault = mode.id === gpuInfo.mode;
|
var isDefault = mode.id === gpuInfo.mode;
|
||||||
|
var hasWarning = mode.warning;
|
||||||
|
|
||||||
html +=
|
html +=
|
||||||
'<label class="flex items-center gap-3 p-2 rounded border cursor-pointer hover:bg-muted/50 transition-colors ' +
|
'<label class="flex items-center gap-3 p-2 rounded border cursor-pointer hover:bg-muted/50 transition-colors ' +
|
||||||
@@ -502,7 +512,7 @@ function buildGpuModeSelector(gpuInfo) {
|
|||||||
(isRecommended ? '<span class="text-xs bg-primary/20 text-primary px-1.5 py-0.5 rounded">' + (t('common.recommended') || 'Recommended') + '</span>' : '') +
|
(isRecommended ? '<span class="text-xs bg-primary/20 text-primary px-1.5 py-0.5 rounded">' + (t('common.recommended') || 'Recommended') + '</span>' : '') +
|
||||||
(isDisabled ? '<span class="text-xs text-muted-foreground">(' + (t('common.unavailable') || 'Unavailable') + ')</span>' : '') +
|
(isDisabled ? '<span class="text-xs text-muted-foreground">(' + (t('common.unavailable') || 'Unavailable') + ')</span>' : '') +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div class="text-xs text-muted-foreground">' + mode.desc + '</div>' +
|
'<div class="text-xs ' + (hasWarning ? 'text-warning' : 'text-muted-foreground') + '">' + mode.desc + '</div>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'</label>';
|
'</label>';
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -379,11 +379,63 @@ async function ensureLiteLLMEmbedderReady(): Promise<BootstrapResult> {
|
|||||||
*/
|
*/
|
||||||
type GpuMode = 'cpu' | 'cuda' | 'directml';
|
type GpuMode = 'cpu' | 'cuda' | 'directml';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Python environment info for compatibility checks
|
||||||
|
*/
|
||||||
|
interface PythonEnvInfo {
|
||||||
|
version: string; // e.g., "3.11.5"
|
||||||
|
majorMinor: string; // e.g., "3.11"
|
||||||
|
architecture: number; // 32 or 64
|
||||||
|
compatible: boolean; // true if 64-bit and Python 3.8-3.12
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check Python environment in venv for DirectML compatibility
|
||||||
|
* DirectML requires: 64-bit Python, version 3.8-3.12
|
||||||
|
*/
|
||||||
|
async function checkPythonEnvForDirectML(): Promise<PythonEnvInfo> {
|
||||||
|
const pythonPath =
|
||||||
|
process.platform === 'win32'
|
||||||
|
? join(CODEXLENS_VENV, 'Scripts', 'python.exe')
|
||||||
|
: join(CODEXLENS_VENV, 'bin', 'python');
|
||||||
|
|
||||||
|
if (!existsSync(pythonPath)) {
|
||||||
|
return { version: '', majorMinor: '', architecture: 0, compatible: false, error: 'Python not found in venv' };
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get Python version and architecture in one call
|
||||||
|
const checkScript = `import sys, struct; print(f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}|{struct.calcsize('P') * 8}")`;
|
||||||
|
const result = execSync(`"${pythonPath}" -c "${checkScript}"`, { encoding: 'utf-8', timeout: 10000 }).trim();
|
||||||
|
const [version, archStr] = result.split('|');
|
||||||
|
const architecture = parseInt(archStr, 10);
|
||||||
|
const [major, minor] = version.split('.').map(Number);
|
||||||
|
const majorMinor = `${major}.${minor}`;
|
||||||
|
|
||||||
|
// DirectML wheels available for Python 3.8-3.12, 64-bit only
|
||||||
|
const versionCompatible = major === 3 && minor >= 8 && minor <= 12;
|
||||||
|
const archCompatible = architecture === 64;
|
||||||
|
const compatible = versionCompatible && archCompatible;
|
||||||
|
|
||||||
|
let error: string | undefined;
|
||||||
|
if (!archCompatible) {
|
||||||
|
error = `Python is ${architecture}-bit. onnxruntime-directml requires 64-bit Python. Please reinstall Python as 64-bit.`;
|
||||||
|
} else if (!versionCompatible) {
|
||||||
|
error = `Python ${majorMinor} is not supported. onnxruntime-directml requires Python 3.8-3.12.`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { version, majorMinor, architecture, compatible, error };
|
||||||
|
} catch (e) {
|
||||||
|
return { version: '', majorMinor: '', architecture: 0, compatible: false, error: `Failed to check Python: ${(e as Error).message}` };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detect available GPU acceleration
|
* Detect available GPU acceleration
|
||||||
* @returns Detected GPU mode and info
|
* @returns Detected GPU mode and info
|
||||||
*/
|
*/
|
||||||
async function detectGpuSupport(): Promise<{ mode: GpuMode; available: GpuMode[]; info: string }> {
|
async function detectGpuSupport(): Promise<{ mode: GpuMode; available: GpuMode[]; info: string; pythonEnv?: PythonEnvInfo }> {
|
||||||
const available: GpuMode[] = ['cpu'];
|
const available: GpuMode[] = ['cpu'];
|
||||||
let detectedInfo = 'CPU only';
|
let detectedInfo = 'CPU only';
|
||||||
|
|
||||||
@@ -402,19 +454,20 @@ async function detectGpuSupport(): Promise<{ mode: GpuMode; available: GpuMode[]
|
|||||||
// NVIDIA not available
|
// NVIDIA not available
|
||||||
}
|
}
|
||||||
|
|
||||||
// On Windows, DirectML is always available if DirectX 12 is supported
|
// On Windows, DirectML requires 64-bit Python 3.8-3.12
|
||||||
|
let pythonEnv: PythonEnvInfo | undefined;
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
try {
|
pythonEnv = await checkPythonEnvForDirectML();
|
||||||
// Check for DirectX 12 support via dxdiag or registry
|
if (pythonEnv.compatible) {
|
||||||
// DirectML works on most modern Windows 10/11 systems
|
|
||||||
available.push('directml');
|
available.push('directml');
|
||||||
if (available.includes('cuda')) {
|
if (available.includes('cuda')) {
|
||||||
detectedInfo = 'NVIDIA GPU detected (CUDA & DirectML available)';
|
detectedInfo = 'NVIDIA GPU detected (CUDA & DirectML available)';
|
||||||
} else {
|
} else {
|
||||||
detectedInfo = 'DirectML available (Windows GPU acceleration)';
|
detectedInfo = 'DirectML available (Windows GPU acceleration)';
|
||||||
}
|
}
|
||||||
} catch {
|
} else if (pythonEnv.error) {
|
||||||
// DirectML check failed
|
// DirectML not available due to Python environment
|
||||||
|
console.log(`[CodexLens] DirectML unavailable: ${pythonEnv.error}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,7 +479,7 @@ async function detectGpuSupport(): Promise<{ mode: GpuMode; available: GpuMode[]
|
|||||||
recommendedMode = 'cuda';
|
recommendedMode = 'cuda';
|
||||||
}
|
}
|
||||||
|
|
||||||
return { mode: recommendedMode, available, info: detectedInfo };
|
return { mode: recommendedMode, available, info: detectedInfo, pythonEnv };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -441,6 +494,19 @@ async function installSemantic(gpuMode: GpuMode = 'cpu'): Promise<BootstrapResul
|
|||||||
return { success: false, error: 'CodexLens not installed. Install CodexLens first.' };
|
return { success: false, error: 'CodexLens not installed. Install CodexLens first.' };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check Python environment compatibility for DirectML
|
||||||
|
if (gpuMode === 'directml') {
|
||||||
|
const pythonEnv = await checkPythonEnvForDirectML();
|
||||||
|
if (!pythonEnv.compatible) {
|
||||||
|
const errorDetails = pythonEnv.error || 'Unknown compatibility issue';
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: `DirectML installation failed: ${errorDetails}\n\nTo fix this:\n1. Uninstall current Python\n2. Install 64-bit Python 3.10, 3.11, or 3.12 from python.org\n3. Delete ~/.codexlens/venv folder\n4. Reinstall CodexLens`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log(`[CodexLens] Python ${pythonEnv.version} (${pythonEnv.architecture}-bit) - DirectML compatible`);
|
||||||
|
}
|
||||||
|
|
||||||
const pipPath =
|
const pipPath =
|
||||||
process.platform === 'win32'
|
process.platform === 'win32'
|
||||||
? join(CODEXLENS_VENV, 'Scripts', 'pip.exe')
|
? join(CODEXLENS_VENV, 'Scripts', 'pip.exe')
|
||||||
@@ -1411,7 +1477,7 @@ export {
|
|||||||
cancelIndexing,
|
cancelIndexing,
|
||||||
isIndexingInProgress,
|
isIndexingInProgress,
|
||||||
};
|
};
|
||||||
export type { GpuMode };
|
export type { GpuMode, PythonEnvInfo };
|
||||||
|
|
||||||
// Backward-compatible export for tests
|
// Backward-compatible export for tests
|
||||||
export const codexLensTool = {
|
export const codexLensTool = {
|
||||||
|
|||||||
Reference in New Issue
Block a user