feat: 添加 ccw-litellm 安装和卸载后的缓存失效处理,确保数据更新

This commit is contained in:
catlog22
2026-01-12 14:39:37 +08:00
parent 96f0d2a8f1
commit 5ec9ad01a3
2 changed files with 110 additions and 20 deletions

View File

@@ -415,6 +415,11 @@ function handleNotification(data) {
'CodexLens'
);
}
// Invalidate CodexLens page cache to ensure fresh data on next visit
if (typeof window.invalidateCodexLensCache === 'function') {
window.invalidateCodexLensCache();
console.log('[CodexLens] Cache invalidated after installation');
}
// Refresh CLI status if active
if (typeof loadCodexLensStatus === 'function') {
loadCodexLensStatus().then(() => {
@@ -438,6 +443,11 @@ function handleNotification(data) {
'CodexLens'
);
}
// Invalidate CodexLens page cache to ensure fresh data on next visit
if (typeof window.invalidateCodexLensCache === 'function') {
window.invalidateCodexLensCache();
console.log('[CodexLens] Cache invalidated after uninstallation');
}
// Refresh CLI status if active
if (typeof loadCodexLensStatus === 'function') {
loadCodexLensStatus().then(() => {
@@ -531,6 +541,48 @@ function handleNotification(data) {
console.log('[CodexLens] Index complete:', payload.result?.files_indexed, 'files indexed');
break;
case 'CCW_LITELLM_INSTALLED':
// Handle ccw-litellm installation completion
if (typeof addGlobalNotification === 'function') {
addGlobalNotification(
'success',
`ccw-litellm installed successfully`,
{
'Time': new Date(payload.timestamp).toLocaleTimeString()
},
'LiteLLM'
);
}
// Invalidate ccw-litellm status cache
if (typeof window.checkCcwLitellmStatus === 'function') {
window.checkCcwLitellmStatus(true);
}
console.log('[ccw-litellm] Installation completed:', payload);
break;
case 'CCW_LITELLM_UNINSTALLED':
// Handle ccw-litellm uninstallation completion
if (typeof addGlobalNotification === 'function') {
addGlobalNotification(
'success',
`ccw-litellm uninstalled successfully`,
{
'Time': new Date(payload.timestamp).toLocaleTimeString()
},
'LiteLLM'
);
}
// Invalidate ccw-litellm status cache and refresh UI
if (typeof window.checkCcwLitellmStatus === 'function') {
window.checkCcwLitellmStatus(true).then(function() {
if (typeof window.renderCcwLitellmStatusCard === 'function') {
window.renderCcwLitellmStatusCard();
}
});
}
console.log('[ccw-litellm] Uninstallation completed:', payload);
break;
default:
console.log('[WS] Unknown notification type:', type);
}

View File

@@ -329,32 +329,70 @@ async function ensureLiteLLMEmbedderReady(): Promise<BootstrapResult> {
return { success: true };
}
console.log('[CodexLens] Installing ccw-litellm for LiteLLM embedding backend...');
// Find local ccw-litellm package path
const possiblePaths = [
join(process.cwd(), 'ccw-litellm'),
join(__dirname, '..', '..', '..', 'ccw-litellm'), // ccw/src/tools -> project root
join(homedir(), 'ccw-litellm'),
];
let localPath: string | null = null;
for (const p of possiblePaths) {
if (existsSync(join(p, 'pyproject.toml'))) {
localPath = p;
break;
}
}
// Priority: Use UV if available (faster, better dependency resolution)
if (await isUvAvailable()) {
console.log('[CodexLens] Using UV for ccw-litellm installation...');
try {
const uv = createCodexLensUvManager();
// Ensure venv exists
if (!uv.isVenvValid()) {
const venvResult = await uv.createVenv();
if (!venvResult.success) {
console.log('[CodexLens] UV venv creation failed, falling back to pip:', venvResult.error);
// Fall through to pip fallback
}
}
if (uv.isVenvValid()) {
let uvResult;
if (localPath) {
console.log(`[CodexLens] Installing ccw-litellm from local path with UV: ${localPath}`);
uvResult = await uv.installFromProject(localPath);
} else {
console.log('[CodexLens] Installing ccw-litellm from PyPI with UV...');
uvResult = await uv.install(['ccw-litellm']);
}
if (uvResult.success) {
return { success: true };
}
console.log('[CodexLens] UV install failed, falling back to pip:', uvResult.error);
}
} catch (uvErr) {
console.log('[CodexLens] UV error, falling back to pip:', (uvErr as Error).message);
}
}
// Fallback: Use pip for installation
const pipPath =
process.platform === 'win32'
? join(CODEXLENS_VENV, 'Scripts', 'pip.exe')
: join(CODEXLENS_VENV, 'bin', 'pip');
try {
console.log('[CodexLens] Installing ccw-litellm for LiteLLM embedding backend...');
const possiblePaths = [
join(process.cwd(), 'ccw-litellm'),
join(__dirname, '..', '..', '..', 'ccw-litellm'), // ccw/src/tools -> project root
join(homedir(), 'ccw-litellm'),
];
let installed = false;
for (const localPath of possiblePaths) {
if (existsSync(join(localPath, 'pyproject.toml'))) {
console.log(`[CodexLens] Installing ccw-litellm from local path: ${localPath}`);
execSync(`"${pipPath}" install -e "${localPath}"`, { stdio: 'inherit', timeout: EXEC_TIMEOUTS.PACKAGE_INSTALL });
installed = true;
break;
}
}
if (!installed) {
console.log('[CodexLens] Installing ccw-litellm from PyPI...');
if (localPath) {
console.log(`[CodexLens] Installing ccw-litellm from local path with pip: ${localPath}`);
execSync(`"${pipPath}" install -e "${localPath}"`, { stdio: 'inherit', timeout: EXEC_TIMEOUTS.PACKAGE_INSTALL });
} else {
console.log('[CodexLens] Installing ccw-litellm from PyPI with pip...');
execSync(`"${pipPath}" install ccw-litellm`, { stdio: 'inherit', timeout: EXEC_TIMEOUTS.PACKAGE_INSTALL });
}