fix: resolve GitHub issues #63, #66, #67, #68, #69, #70

- #70: Fix API Key Tester URL handling - normalize trailing slashes before
  version suffix detection to prevent double-slash URLs like //models
- #69: Fix memory embedder ignoring CodexLens config - add error handling
  for CodexLensConfig.load() with fallback to defaults
- #68: Fix ccw cli using wrong Python environment - add getCodexLensVenvPython()
  to resolve correct venv path on Windows/Unix
- #67: Fix LiteLLM API Provider test endpoint - actually test API key connection
  instead of just checking ccw-litellm installation
- #66: Fix help-routes.ts path configuration - use correct 'ccw-help' directory
  name and refactor getIndexDir to pure function
- #63: Fix CodexLens install state refresh - add cache invalidation after
  config save in codexlens-manager.js

Also includes targeted unit tests for the URL normalization logic.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
catlog22
2026-01-13 18:20:54 +08:00
parent 61cef8019a
commit 340137d347
12 changed files with 546 additions and 29 deletions

View File

@@ -346,3 +346,45 @@ describe('LiteLLM client bridge', () => {
assert.ok(String(status.error).includes('ccw_litellm not installed'));
});
});
describe('getCodexLensVenvPython (Issue #68 fix)', () => {
it('should be exported from the module', async () => {
assert.ok(typeof mod.getCodexLensVenvPython === 'function');
});
it('should return a string path', async () => {
const pythonPath = mod.getCodexLensVenvPython();
assert.equal(typeof pythonPath, 'string');
assert.ok(pythonPath.length > 0);
});
it('should return correct path structure for CodexLens venv', async () => {
const pythonPath = mod.getCodexLensVenvPython();
// On Windows: should contain Scripts/python.exe
// On Unix: should contain bin/python
const isWindows = process.platform === 'win32';
if (isWindows) {
// Either it's the venv path with Scripts, or fallback to 'python'
const isVenvPath = pythonPath.includes('Scripts') && pythonPath.includes('python');
const isFallback = pythonPath === 'python';
assert.ok(isVenvPath || isFallback, `Expected venv path or 'python' fallback, got: ${pythonPath}`);
} else {
// On Unix: either venv path with bin/python, or fallback
const isVenvPath = pythonPath.includes('bin') && pythonPath.includes('python');
const isFallback = pythonPath === 'python';
assert.ok(isVenvPath || isFallback, `Expected venv path or 'python' fallback, got: ${pythonPath}`);
}
});
it('should include .codexlens/venv in path when venv exists', async () => {
const pythonPath = mod.getCodexLensVenvPython();
// If not falling back to 'python', should contain .codexlens/venv
if (pythonPath !== 'python') {
assert.ok(pythonPath.includes('.codexlens'), `Expected .codexlens in path, got: ${pythonPath}`);
assert.ok(pythonPath.includes('venv'), `Expected venv in path, got: ${pythonPath}`);
}
});
});