claude-code-workflow 6.2.7 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +16 -1
- package/.claude/workflows/cli-templates/protocols/analysis-protocol.md +11 -4
- package/.claude/workflows/cli-templates/protocols/write-protocol.md +10 -75
- package/.claude/workflows/cli-tools-usage.md +14 -24
- package/.codex/AGENTS.md +51 -1
- package/.codex/prompts/compact.md +378 -0
- package/.gemini/GEMINI.md +57 -20
- package/ccw/dist/cli.d.ts.map +1 -1
- package/ccw/dist/cli.js +21 -8
- package/ccw/dist/cli.js.map +1 -1
- package/ccw/dist/commands/cli.d.ts +2 -0
- package/ccw/dist/commands/cli.d.ts.map +1 -1
- package/ccw/dist/commands/cli.js +129 -8
- package/ccw/dist/commands/cli.js.map +1 -1
- package/ccw/dist/commands/hook.d.ts.map +1 -1
- package/ccw/dist/commands/hook.js +3 -2
- package/ccw/dist/commands/hook.js.map +1 -1
- package/ccw/dist/config/litellm-api-config-manager.d.ts +180 -0
- package/ccw/dist/config/litellm-api-config-manager.d.ts.map +1 -0
- package/ccw/dist/config/litellm-api-config-manager.js +770 -0
- package/ccw/dist/config/litellm-api-config-manager.js.map +1 -0
- package/ccw/dist/config/provider-models.d.ts +73 -0
- package/ccw/dist/config/provider-models.d.ts.map +1 -0
- package/ccw/dist/config/provider-models.js +172 -0
- package/ccw/dist/config/provider-models.js.map +1 -0
- package/ccw/dist/core/cache-manager.d.ts.map +1 -1
- package/ccw/dist/core/cache-manager.js +3 -5
- package/ccw/dist/core/cache-manager.js.map +1 -1
- package/ccw/dist/core/dashboard-generator.d.ts.map +1 -1
- package/ccw/dist/core/dashboard-generator.js +3 -1
- package/ccw/dist/core/dashboard-generator.js.map +1 -1
- package/ccw/dist/core/routes/cli-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/cli-routes.js +169 -0
- package/ccw/dist/core/routes/cli-routes.js.map +1 -1
- package/ccw/dist/core/routes/codexlens-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/codexlens-routes.js +234 -18
- package/ccw/dist/core/routes/codexlens-routes.js.map +1 -1
- package/ccw/dist/core/routes/hooks-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/hooks-routes.js +30 -32
- package/ccw/dist/core/routes/hooks-routes.js.map +1 -1
- package/ccw/dist/core/routes/litellm-api-routes.d.ts +21 -0
- package/ccw/dist/core/routes/litellm-api-routes.d.ts.map +1 -0
- package/ccw/dist/core/routes/litellm-api-routes.js +780 -0
- package/ccw/dist/core/routes/litellm-api-routes.js.map +1 -0
- package/ccw/dist/core/routes/litellm-routes.d.ts +20 -0
- package/ccw/dist/core/routes/litellm-routes.d.ts.map +1 -0
- package/ccw/dist/core/routes/litellm-routes.js +85 -0
- package/ccw/dist/core/routes/litellm-routes.js.map +1 -0
- package/ccw/dist/core/routes/mcp-routes.js +2 -2
- package/ccw/dist/core/routes/mcp-routes.js.map +1 -1
- package/ccw/dist/core/routes/status-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/status-routes.js +39 -0
- package/ccw/dist/core/routes/status-routes.js.map +1 -1
- package/ccw/dist/core/routes/system-routes.js +1 -1
- package/ccw/dist/core/routes/system-routes.js.map +1 -1
- package/ccw/dist/core/server.d.ts.map +1 -1
- package/ccw/dist/core/server.js +15 -1
- package/ccw/dist/core/server.js.map +1 -1
- package/ccw/dist/mcp-server/index.js +1 -1
- package/ccw/dist/mcp-server/index.js.map +1 -1
- package/ccw/dist/tools/claude-cli-tools.d.ts +82 -0
- package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -0
- package/ccw/dist/tools/claude-cli-tools.js +216 -0
- package/ccw/dist/tools/claude-cli-tools.js.map +1 -0
- package/ccw/dist/tools/cli-executor.d.ts.map +1 -1
- package/ccw/dist/tools/cli-executor.js +76 -14
- package/ccw/dist/tools/cli-executor.js.map +1 -1
- package/ccw/dist/tools/codex-lens.d.ts +9 -2
- package/ccw/dist/tools/codex-lens.d.ts.map +1 -1
- package/ccw/dist/tools/codex-lens.js +114 -9
- package/ccw/dist/tools/codex-lens.js.map +1 -1
- package/ccw/dist/tools/context-cache-store.d.ts +136 -0
- package/ccw/dist/tools/context-cache-store.d.ts.map +1 -0
- package/ccw/dist/tools/context-cache-store.js +256 -0
- package/ccw/dist/tools/context-cache-store.js.map +1 -0
- package/ccw/dist/tools/context-cache.d.ts +56 -0
- package/ccw/dist/tools/context-cache.d.ts.map +1 -0
- package/ccw/dist/tools/context-cache.js +294 -0
- package/ccw/dist/tools/context-cache.js.map +1 -0
- package/ccw/dist/tools/core-memory.d.ts.map +1 -1
- package/ccw/dist/tools/core-memory.js +33 -19
- package/ccw/dist/tools/core-memory.js.map +1 -1
- package/ccw/dist/tools/index.d.ts.map +1 -1
- package/ccw/dist/tools/index.js +2 -0
- package/ccw/dist/tools/index.js.map +1 -1
- package/ccw/dist/tools/litellm-client.d.ts +85 -0
- package/ccw/dist/tools/litellm-client.d.ts.map +1 -0
- package/ccw/dist/tools/litellm-client.js +188 -0
- package/ccw/dist/tools/litellm-client.js.map +1 -0
- package/ccw/dist/tools/litellm-executor.d.ts +34 -0
- package/ccw/dist/tools/litellm-executor.d.ts.map +1 -0
- package/ccw/dist/tools/litellm-executor.js +192 -0
- package/ccw/dist/tools/litellm-executor.js.map +1 -0
- package/ccw/dist/tools/pattern-parser.d.ts +55 -0
- package/ccw/dist/tools/pattern-parser.d.ts.map +1 -0
- package/ccw/dist/tools/pattern-parser.js +237 -0
- package/ccw/dist/tools/pattern-parser.js.map +1 -0
- package/ccw/dist/tools/smart-search.d.ts +1 -0
- package/ccw/dist/tools/smart-search.d.ts.map +1 -1
- package/ccw/dist/tools/smart-search.js +117 -41
- package/ccw/dist/tools/smart-search.js.map +1 -1
- package/ccw/dist/types/litellm-api-config.d.ts +294 -0
- package/ccw/dist/types/litellm-api-config.d.ts.map +1 -0
- package/ccw/dist/types/litellm-api-config.js +8 -0
- package/ccw/dist/types/litellm-api-config.js.map +1 -0
- package/ccw/src/cli.ts +258 -244
- package/ccw/src/commands/cli.ts +153 -9
- package/ccw/src/commands/hook.ts +3 -2
- package/ccw/src/config/.litellm-api-config-manager.ts.2025-12-23T11-57-43-727Z.bak +441 -0
- package/ccw/src/config/litellm-api-config-manager.ts +1012 -0
- package/ccw/src/config/provider-models.ts +222 -0
- package/ccw/src/core/cache-manager.ts +292 -294
- package/ccw/src/core/dashboard-generator.ts +3 -1
- package/ccw/src/core/routes/cli-routes.ts +192 -0
- package/ccw/src/core/routes/codexlens-routes.ts +241 -19
- package/ccw/src/core/routes/hooks-routes.ts +399 -405
- package/ccw/src/core/routes/litellm-api-routes.ts +930 -0
- package/ccw/src/core/routes/litellm-routes.ts +107 -0
- package/ccw/src/core/routes/mcp-routes.ts +1271 -1271
- package/ccw/src/core/routes/status-routes.ts +51 -0
- package/ccw/src/core/routes/system-routes.ts +1 -1
- package/ccw/src/core/server.ts +15 -1
- package/ccw/src/mcp-server/index.ts +1 -1
- package/ccw/src/templates/dashboard-css/12-cli-legacy.css +44 -0
- package/ccw/src/templates/dashboard-css/31-api-settings.css +2265 -0
- package/ccw/src/templates/dashboard-js/components/cli-history.js +15 -8
- package/ccw/src/templates/dashboard-js/components/cli-status.js +323 -9
- package/ccw/src/templates/dashboard-js/components/navigation.js +329 -313
- package/ccw/src/templates/dashboard-js/i18n.js +583 -1
- package/ccw/src/templates/dashboard-js/views/api-settings.js +3362 -0
- package/ccw/src/templates/dashboard-js/views/cli-manager.js +199 -24
- package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +1265 -27
- package/ccw/src/templates/dashboard.html +840 -831
- package/ccw/src/tools/claude-cli-tools.ts +300 -0
- package/ccw/src/tools/cli-executor.ts +83 -14
- package/ccw/src/tools/codex-lens.ts +146 -9
- package/ccw/src/tools/context-cache-store.ts +368 -0
- package/ccw/src/tools/context-cache.ts +393 -0
- package/ccw/src/tools/core-memory.ts +33 -19
- package/ccw/src/tools/index.ts +2 -0
- package/ccw/src/tools/litellm-client.ts +246 -0
- package/ccw/src/tools/litellm-executor.ts +241 -0
- package/ccw/src/tools/pattern-parser.ts +329 -0
- package/ccw/src/tools/smart-search.ts +142 -41
- package/ccw/src/types/litellm-api-config.ts +402 -0
- package/ccw-litellm/README.md +180 -0
- package/ccw-litellm/pyproject.toml +35 -0
- package/ccw-litellm/src/ccw_litellm/__init__.py +47 -0
- package/ccw-litellm/src/ccw_litellm/__pycache__/__init__.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/__pycache__/cli.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/cli.py +108 -0
- package/ccw-litellm/src/ccw_litellm/clients/__init__.py +12 -0
- package/ccw-litellm/src/ccw_litellm/clients/__pycache__/__init__.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_embedder.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_llm.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/clients/litellm_embedder.py +251 -0
- package/ccw-litellm/src/ccw_litellm/clients/litellm_llm.py +165 -0
- package/ccw-litellm/src/ccw_litellm/config/__init__.py +22 -0
- package/ccw-litellm/src/ccw_litellm/config/__pycache__/__init__.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/config/__pycache__/loader.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/config/__pycache__/models.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/config/loader.py +316 -0
- package/ccw-litellm/src/ccw_litellm/config/models.py +130 -0
- package/ccw-litellm/src/ccw_litellm/interfaces/__init__.py +14 -0
- package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/__init__.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/embedder.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/llm.cpython-313.pyc +0 -0
- package/ccw-litellm/src/ccw_litellm/interfaces/embedder.py +52 -0
- package/ccw-litellm/src/ccw_litellm/interfaces/llm.py +45 -0
- package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/commands.py +378 -23
- package/codex-lens/src/codexlens/cli/embedding_manager.py +660 -56
- package/codex-lens/src/codexlens/cli/model_manager.py +31 -18
- package/codex-lens/src/codexlens/cli/output.py +12 -1
- package/codex-lens/src/codexlens/config.py +93 -0
- package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/chain_search.py +6 -2
- package/codex-lens/src/codexlens/search/hybrid_search.py +44 -21
- package/codex-lens/src/codexlens/search/ranking.py +1 -1
- package/codex-lens/src/codexlens/semantic/__init__.py +42 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/base.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/factory.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/gpu_support.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/litellm_embedder.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/base.py +61 -0
- package/codex-lens/src/codexlens/semantic/chunker.py +43 -20
- package/codex-lens/src/codexlens/semantic/embedder.py +60 -13
- package/codex-lens/src/codexlens/semantic/factory.py +98 -0
- package/codex-lens/src/codexlens/semantic/gpu_support.py +225 -3
- package/codex-lens/src/codexlens/semantic/litellm_embedder.py +144 -0
- package/codex-lens/src/codexlens/semantic/rotational_embedder.py +434 -0
- package/codex-lens/src/codexlens/semantic/vector_store.py +33 -8
- package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_004_dual_fts.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/path_mapper.py +27 -1
- package/package.json +15 -5
- package/.codex/prompts.zip +0 -0
- package/ccw/package.json +0 -65
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude CLI Tools Configuration Manager
|
|
3
|
+
* Manages .claude/cli-tools.json with fallback:
|
|
4
|
+
* 1. Project workspace: {projectDir}/.claude/cli-tools.json (priority)
|
|
5
|
+
* 2. Global: ~/.claude/cli-tools.json (fallback)
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import * as os from 'os';
|
|
10
|
+
|
|
11
|
+
// ========== Types ==========
|
|
12
|
+
|
|
13
|
+
export interface ClaudeCliTool {
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
isBuiltin: boolean;
|
|
16
|
+
command: string;
|
|
17
|
+
description: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ClaudeCacheSettings {
|
|
21
|
+
injectionMode: 'auto' | 'manual' | 'disabled';
|
|
22
|
+
defaultPrefix: string;
|
|
23
|
+
defaultSuffix: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ClaudeCliToolsConfig {
|
|
27
|
+
$schema?: string;
|
|
28
|
+
version: string;
|
|
29
|
+
tools: Record<string, ClaudeCliTool>;
|
|
30
|
+
customEndpoints: Array<{
|
|
31
|
+
id: string;
|
|
32
|
+
name: string;
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
}>;
|
|
35
|
+
defaultTool: string;
|
|
36
|
+
settings: {
|
|
37
|
+
promptFormat: 'plain' | 'yaml' | 'json';
|
|
38
|
+
smartContext: {
|
|
39
|
+
enabled: boolean;
|
|
40
|
+
maxFiles: number;
|
|
41
|
+
};
|
|
42
|
+
nativeResume: boolean;
|
|
43
|
+
recursiveQuery: boolean;
|
|
44
|
+
cache: ClaudeCacheSettings;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ========== Default Config ==========
|
|
49
|
+
|
|
50
|
+
const DEFAULT_CONFIG: ClaudeCliToolsConfig = {
|
|
51
|
+
version: '1.0.0',
|
|
52
|
+
tools: {
|
|
53
|
+
gemini: {
|
|
54
|
+
enabled: true,
|
|
55
|
+
isBuiltin: true,
|
|
56
|
+
command: 'gemini',
|
|
57
|
+
description: 'Google AI for code analysis'
|
|
58
|
+
},
|
|
59
|
+
qwen: {
|
|
60
|
+
enabled: true,
|
|
61
|
+
isBuiltin: true,
|
|
62
|
+
command: 'qwen',
|
|
63
|
+
description: 'Alibaba AI assistant'
|
|
64
|
+
},
|
|
65
|
+
codex: {
|
|
66
|
+
enabled: true,
|
|
67
|
+
isBuiltin: true,
|
|
68
|
+
command: 'codex',
|
|
69
|
+
description: 'OpenAI code generation'
|
|
70
|
+
},
|
|
71
|
+
claude: {
|
|
72
|
+
enabled: true,
|
|
73
|
+
isBuiltin: true,
|
|
74
|
+
command: 'claude',
|
|
75
|
+
description: 'Anthropic AI assistant'
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
customEndpoints: [],
|
|
79
|
+
defaultTool: 'gemini',
|
|
80
|
+
settings: {
|
|
81
|
+
promptFormat: 'plain',
|
|
82
|
+
smartContext: {
|
|
83
|
+
enabled: false,
|
|
84
|
+
maxFiles: 10
|
|
85
|
+
},
|
|
86
|
+
nativeResume: true,
|
|
87
|
+
recursiveQuery: true,
|
|
88
|
+
cache: {
|
|
89
|
+
injectionMode: 'auto',
|
|
90
|
+
defaultPrefix: '',
|
|
91
|
+
defaultSuffix: ''
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// ========== Helper Functions ==========
|
|
97
|
+
|
|
98
|
+
function getProjectConfigPath(projectDir: string): string {
|
|
99
|
+
return path.join(projectDir, '.claude', 'cli-tools.json');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function getGlobalConfigPath(): string {
|
|
103
|
+
return path.join(os.homedir(), '.claude', 'cli-tools.json');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Resolve config path with fallback:
|
|
108
|
+
* 1. Project: {projectDir}/.claude/cli-tools.json
|
|
109
|
+
* 2. Global: ~/.claude/cli-tools.json
|
|
110
|
+
* Returns { path, source } where source is 'project' | 'global' | 'default'
|
|
111
|
+
*/
|
|
112
|
+
function resolveConfigPath(projectDir: string): { path: string; source: 'project' | 'global' | 'default' } {
|
|
113
|
+
const projectPath = getProjectConfigPath(projectDir);
|
|
114
|
+
if (fs.existsSync(projectPath)) {
|
|
115
|
+
return { path: projectPath, source: 'project' };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const globalPath = getGlobalConfigPath();
|
|
119
|
+
if (fs.existsSync(globalPath)) {
|
|
120
|
+
return { path: globalPath, source: 'global' };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return { path: projectPath, source: 'default' };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function ensureClaudeDir(projectDir: string): void {
|
|
127
|
+
const claudeDir = path.join(projectDir, '.claude');
|
|
128
|
+
if (!fs.existsSync(claudeDir)) {
|
|
129
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ========== Main Functions ==========
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Load CLI tools configuration with fallback:
|
|
137
|
+
* 1. Project: {projectDir}/.claude/cli-tools.json
|
|
138
|
+
* 2. Global: ~/.claude/cli-tools.json
|
|
139
|
+
* 3. Default config
|
|
140
|
+
*/
|
|
141
|
+
export function loadClaudeCliTools(projectDir: string): ClaudeCliToolsConfig & { _source?: string } {
|
|
142
|
+
const resolved = resolveConfigPath(projectDir);
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
if (resolved.source === 'default') {
|
|
146
|
+
// No config file found, return defaults
|
|
147
|
+
return { ...DEFAULT_CONFIG, _source: 'default' };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const content = fs.readFileSync(resolved.path, 'utf-8');
|
|
151
|
+
const parsed = JSON.parse(content) as Partial<ClaudeCliToolsConfig>;
|
|
152
|
+
|
|
153
|
+
// Merge with defaults
|
|
154
|
+
const config = {
|
|
155
|
+
...DEFAULT_CONFIG,
|
|
156
|
+
...parsed,
|
|
157
|
+
tools: { ...DEFAULT_CONFIG.tools, ...(parsed.tools || {}) },
|
|
158
|
+
settings: {
|
|
159
|
+
...DEFAULT_CONFIG.settings,
|
|
160
|
+
...(parsed.settings || {}),
|
|
161
|
+
smartContext: {
|
|
162
|
+
...DEFAULT_CONFIG.settings.smartContext,
|
|
163
|
+
...(parsed.settings?.smartContext || {})
|
|
164
|
+
},
|
|
165
|
+
cache: {
|
|
166
|
+
...DEFAULT_CONFIG.settings.cache,
|
|
167
|
+
...(parsed.settings?.cache || {})
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
_source: resolved.source
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
console.log(`[claude-cli-tools] Loaded config from ${resolved.source}: ${resolved.path}`);
|
|
174
|
+
return config;
|
|
175
|
+
} catch (err) {
|
|
176
|
+
console.error('[claude-cli-tools] Error loading config:', err);
|
|
177
|
+
return { ...DEFAULT_CONFIG, _source: 'default' };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Save CLI tools configuration to project .claude/cli-tools.json
|
|
183
|
+
* Always saves to project directory (not global)
|
|
184
|
+
*/
|
|
185
|
+
export function saveClaudeCliTools(projectDir: string, config: ClaudeCliToolsConfig & { _source?: string }): void {
|
|
186
|
+
ensureClaudeDir(projectDir);
|
|
187
|
+
const configPath = getProjectConfigPath(projectDir);
|
|
188
|
+
|
|
189
|
+
// Remove internal _source field before saving
|
|
190
|
+
const { _source, ...configToSave } = config;
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
fs.writeFileSync(configPath, JSON.stringify(configToSave, null, 2), 'utf-8');
|
|
194
|
+
console.log(`[claude-cli-tools] Saved config to project: ${configPath}`);
|
|
195
|
+
} catch (err) {
|
|
196
|
+
console.error('[claude-cli-tools] Error saving config:', err);
|
|
197
|
+
throw new Error(`Failed to save CLI tools config: ${err}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Update enabled status for a specific tool
|
|
203
|
+
*/
|
|
204
|
+
export function updateClaudeToolEnabled(
|
|
205
|
+
projectDir: string,
|
|
206
|
+
toolName: string,
|
|
207
|
+
enabled: boolean
|
|
208
|
+
): ClaudeCliToolsConfig {
|
|
209
|
+
const config = loadClaudeCliTools(projectDir);
|
|
210
|
+
|
|
211
|
+
if (config.tools[toolName]) {
|
|
212
|
+
config.tools[toolName].enabled = enabled;
|
|
213
|
+
saveClaudeCliTools(projectDir, config);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return config;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Update cache settings
|
|
221
|
+
*/
|
|
222
|
+
export function updateClaudeCacheSettings(
|
|
223
|
+
projectDir: string,
|
|
224
|
+
cacheSettings: Partial<ClaudeCacheSettings>
|
|
225
|
+
): ClaudeCliToolsConfig {
|
|
226
|
+
const config = loadClaudeCliTools(projectDir);
|
|
227
|
+
|
|
228
|
+
config.settings.cache = {
|
|
229
|
+
...config.settings.cache,
|
|
230
|
+
...cacheSettings
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
saveClaudeCliTools(projectDir, config);
|
|
234
|
+
return config;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Update default tool
|
|
239
|
+
*/
|
|
240
|
+
export function updateClaudeDefaultTool(
|
|
241
|
+
projectDir: string,
|
|
242
|
+
defaultTool: string
|
|
243
|
+
): ClaudeCliToolsConfig {
|
|
244
|
+
const config = loadClaudeCliTools(projectDir);
|
|
245
|
+
config.defaultTool = defaultTool;
|
|
246
|
+
saveClaudeCliTools(projectDir, config);
|
|
247
|
+
return config;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Add custom endpoint
|
|
252
|
+
*/
|
|
253
|
+
export function addClaudeCustomEndpoint(
|
|
254
|
+
projectDir: string,
|
|
255
|
+
endpoint: { id: string; name: string; enabled: boolean }
|
|
256
|
+
): ClaudeCliToolsConfig {
|
|
257
|
+
const config = loadClaudeCliTools(projectDir);
|
|
258
|
+
|
|
259
|
+
// Check if endpoint already exists
|
|
260
|
+
const existingIndex = config.customEndpoints.findIndex(e => e.id === endpoint.id);
|
|
261
|
+
if (existingIndex >= 0) {
|
|
262
|
+
config.customEndpoints[existingIndex] = endpoint;
|
|
263
|
+
} else {
|
|
264
|
+
config.customEndpoints.push(endpoint);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
saveClaudeCliTools(projectDir, config);
|
|
268
|
+
return config;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Remove custom endpoint
|
|
273
|
+
*/
|
|
274
|
+
export function removeClaudeCustomEndpoint(
|
|
275
|
+
projectDir: string,
|
|
276
|
+
endpointId: string
|
|
277
|
+
): ClaudeCliToolsConfig {
|
|
278
|
+
const config = loadClaudeCliTools(projectDir);
|
|
279
|
+
config.customEndpoints = config.customEndpoints.filter(e => e.id !== endpointId);
|
|
280
|
+
saveClaudeCliTools(projectDir, config);
|
|
281
|
+
return config;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Get config source info
|
|
286
|
+
*/
|
|
287
|
+
export function getClaudeCliToolsInfo(projectDir: string): {
|
|
288
|
+
projectPath: string;
|
|
289
|
+
globalPath: string;
|
|
290
|
+
activePath: string;
|
|
291
|
+
source: 'project' | 'global' | 'default';
|
|
292
|
+
} {
|
|
293
|
+
const resolved = resolveConfigPath(projectDir);
|
|
294
|
+
return {
|
|
295
|
+
projectPath: getProjectConfigPath(projectDir),
|
|
296
|
+
globalPath: getGlobalConfigPath(),
|
|
297
|
+
activePath: resolved.path,
|
|
298
|
+
source: resolved.source
|
|
299
|
+
};
|
|
300
|
+
}
|
|
@@ -10,6 +10,10 @@ import { spawn, ChildProcess } from 'child_process';
|
|
|
10
10
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, readdirSync, statSync } from 'fs';
|
|
11
11
|
import { join, relative } from 'path';
|
|
12
12
|
|
|
13
|
+
// LiteLLM integration
|
|
14
|
+
import { executeLiteLLMEndpoint } from './litellm-executor.js';
|
|
15
|
+
import { findEndpointById } from '../config/litellm-api-config-manager.js';
|
|
16
|
+
|
|
13
17
|
// Native resume support
|
|
14
18
|
import {
|
|
15
19
|
trackNewSession,
|
|
@@ -63,7 +67,7 @@ const ParamsSchema = z.object({
|
|
|
63
67
|
model: z.string().optional(),
|
|
64
68
|
cd: z.string().optional(),
|
|
65
69
|
includeDirs: z.string().optional(),
|
|
66
|
-
timeout: z.number().default(
|
|
70
|
+
timeout: z.number().default(0), // 0 = no internal timeout, controlled by external caller (e.g., bash timeout)
|
|
67
71
|
resume: z.union([z.boolean(), z.string()]).optional(), // true = last, string = single ID or comma-separated IDs
|
|
68
72
|
id: z.string().optional(), // Custom execution ID (e.g., IMPL-001-step1)
|
|
69
73
|
noNative: z.boolean().optional(), // Force prompt concatenation instead of native resume
|
|
@@ -592,6 +596,66 @@ async function executeCliTool(
|
|
|
592
596
|
const workingDir = cd || process.cwd();
|
|
593
597
|
ensureHistoryDir(workingDir); // Ensure history directory exists
|
|
594
598
|
|
|
599
|
+
// NEW: Check if model is a custom LiteLLM endpoint ID
|
|
600
|
+
if (model && !['gemini', 'qwen', 'codex'].includes(tool)) {
|
|
601
|
+
const endpoint = findEndpointById(workingDir, model);
|
|
602
|
+
if (endpoint) {
|
|
603
|
+
// Route to LiteLLM executor
|
|
604
|
+
if (onOutput) {
|
|
605
|
+
onOutput({ type: 'stderr', data: `[Routing to LiteLLM endpoint: ${model}]\n` });
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
const result = await executeLiteLLMEndpoint({
|
|
609
|
+
prompt,
|
|
610
|
+
endpointId: model,
|
|
611
|
+
baseDir: workingDir,
|
|
612
|
+
cwd: cd,
|
|
613
|
+
includeDirs: includeDirs ? includeDirs.split(',').map(d => d.trim()) : undefined,
|
|
614
|
+
enableCache: true,
|
|
615
|
+
onOutput: onOutput || undefined,
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
// Convert LiteLLM result to ExecutionOutput format
|
|
619
|
+
const startTime = Date.now();
|
|
620
|
+
const endTime = Date.now();
|
|
621
|
+
const duration = endTime - startTime;
|
|
622
|
+
|
|
623
|
+
const execution: ExecutionRecord = {
|
|
624
|
+
id: customId || `${Date.now()}-litellm`,
|
|
625
|
+
timestamp: new Date(startTime).toISOString(),
|
|
626
|
+
tool: 'litellm',
|
|
627
|
+
model: result.model,
|
|
628
|
+
mode,
|
|
629
|
+
prompt,
|
|
630
|
+
status: result.success ? 'success' : 'error',
|
|
631
|
+
exit_code: result.success ? 0 : 1,
|
|
632
|
+
duration_ms: duration,
|
|
633
|
+
output: {
|
|
634
|
+
stdout: result.output,
|
|
635
|
+
stderr: result.error || '',
|
|
636
|
+
truncated: false,
|
|
637
|
+
},
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
const conversation = convertToConversation(execution);
|
|
641
|
+
|
|
642
|
+
// Try to save to history
|
|
643
|
+
try {
|
|
644
|
+
saveConversation(workingDir, conversation);
|
|
645
|
+
} catch (err) {
|
|
646
|
+
console.error('[CLI Executor] Failed to save LiteLLM history:', (err as Error).message);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
return {
|
|
650
|
+
success: result.success,
|
|
651
|
+
execution,
|
|
652
|
+
conversation,
|
|
653
|
+
stdout: result.output,
|
|
654
|
+
stderr: result.error || '',
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
595
659
|
// Get SQLite store for native session lookup
|
|
596
660
|
const store = await getSqliteStore(workingDir);
|
|
597
661
|
|
|
@@ -994,19 +1058,24 @@ async function executeCliTool(
|
|
|
994
1058
|
reject(new Error(`Failed to spawn ${tool}: ${error.message}`));
|
|
995
1059
|
});
|
|
996
1060
|
|
|
997
|
-
// Timeout handling
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1061
|
+
// Timeout handling (timeout=0 disables internal timeout, controlled by external caller)
|
|
1062
|
+
let timeoutId: NodeJS.Timeout | null = null;
|
|
1063
|
+
if (timeout > 0) {
|
|
1064
|
+
timeoutId = setTimeout(() => {
|
|
1065
|
+
timedOut = true;
|
|
1066
|
+
child.kill('SIGTERM');
|
|
1067
|
+
setTimeout(() => {
|
|
1068
|
+
if (!child.killed) {
|
|
1069
|
+
child.kill('SIGKILL');
|
|
1070
|
+
}
|
|
1071
|
+
}, 5000);
|
|
1072
|
+
}, timeout);
|
|
1073
|
+
}
|
|
1007
1074
|
|
|
1008
1075
|
child.on('close', () => {
|
|
1009
|
-
|
|
1076
|
+
if (timeoutId) {
|
|
1077
|
+
clearTimeout(timeoutId);
|
|
1078
|
+
}
|
|
1010
1079
|
});
|
|
1011
1080
|
});
|
|
1012
1081
|
}
|
|
@@ -1051,8 +1120,8 @@ Modes:
|
|
|
1051
1120
|
},
|
|
1052
1121
|
timeout: {
|
|
1053
1122
|
type: 'number',
|
|
1054
|
-
description: 'Timeout in milliseconds (default:
|
|
1055
|
-
default:
|
|
1123
|
+
description: 'Timeout in milliseconds (default: 0 = disabled, controlled by external caller)',
|
|
1124
|
+
default: 0
|
|
1056
1125
|
}
|
|
1057
1126
|
},
|
|
1058
1127
|
required: ['tool', 'prompt']
|
|
@@ -33,6 +33,14 @@ const VENV_PYTHON =
|
|
|
33
33
|
let bootstrapChecked = false;
|
|
34
34
|
let bootstrapReady = false;
|
|
35
35
|
|
|
36
|
+
// Venv status cache with TTL
|
|
37
|
+
interface VenvStatusCache {
|
|
38
|
+
status: ReadyStatus;
|
|
39
|
+
timestamp: number;
|
|
40
|
+
}
|
|
41
|
+
let venvStatusCache: VenvStatusCache | null = null;
|
|
42
|
+
const VENV_STATUS_TTL = 5 * 60 * 1000; // 5 minutes TTL
|
|
43
|
+
|
|
36
44
|
// Track running indexing process for cancellation
|
|
37
45
|
let currentIndexingProcess: ReturnType<typeof spawn> | null = null;
|
|
38
46
|
let currentIndexingAborted = false;
|
|
@@ -77,6 +85,7 @@ interface SemanticStatus {
|
|
|
77
85
|
backend?: string;
|
|
78
86
|
accelerator?: string;
|
|
79
87
|
providers?: string[];
|
|
88
|
+
litellmAvailable?: boolean;
|
|
80
89
|
error?: string;
|
|
81
90
|
}
|
|
82
91
|
|
|
@@ -115,6 +124,13 @@ interface ProgressInfo {
|
|
|
115
124
|
totalFiles?: number;
|
|
116
125
|
}
|
|
117
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Clear venv status cache (call after install/uninstall operations)
|
|
129
|
+
*/
|
|
130
|
+
function clearVenvStatusCache(): void {
|
|
131
|
+
venvStatusCache = null;
|
|
132
|
+
}
|
|
133
|
+
|
|
118
134
|
/**
|
|
119
135
|
* Detect available Python 3 executable
|
|
120
136
|
* @returns Python executable command
|
|
@@ -137,17 +153,27 @@ function getSystemPython(): string {
|
|
|
137
153
|
|
|
138
154
|
/**
|
|
139
155
|
* Check if CodexLens venv exists and has required packages
|
|
156
|
+
* @param force - Force refresh cache (default: false)
|
|
140
157
|
* @returns Ready status
|
|
141
158
|
*/
|
|
142
|
-
async function checkVenvStatus(): Promise<ReadyStatus> {
|
|
159
|
+
async function checkVenvStatus(force = false): Promise<ReadyStatus> {
|
|
160
|
+
// Use cached result if available and not expired
|
|
161
|
+
if (!force && venvStatusCache && (Date.now() - venvStatusCache.timestamp < VENV_STATUS_TTL)) {
|
|
162
|
+
return venvStatusCache.status;
|
|
163
|
+
}
|
|
164
|
+
|
|
143
165
|
// Check venv exists
|
|
144
166
|
if (!existsSync(CODEXLENS_VENV)) {
|
|
145
|
-
|
|
167
|
+
const result = { ready: false, error: 'Venv not found' };
|
|
168
|
+
venvStatusCache = { status: result, timestamp: Date.now() };
|
|
169
|
+
return result;
|
|
146
170
|
}
|
|
147
171
|
|
|
148
172
|
// Check python executable exists
|
|
149
173
|
if (!existsSync(VENV_PYTHON)) {
|
|
150
|
-
|
|
174
|
+
const result = { ready: false, error: 'Python executable not found in venv' };
|
|
175
|
+
venvStatusCache = { status: result, timestamp: Date.now() };
|
|
176
|
+
return result;
|
|
151
177
|
}
|
|
152
178
|
|
|
153
179
|
// Check codexlens is importable
|
|
@@ -168,15 +194,21 @@ async function checkVenvStatus(): Promise<ReadyStatus> {
|
|
|
168
194
|
});
|
|
169
195
|
|
|
170
196
|
child.on('close', (code) => {
|
|
197
|
+
let result: ReadyStatus;
|
|
171
198
|
if (code === 0) {
|
|
172
|
-
|
|
199
|
+
result = { ready: true, version: stdout.trim() };
|
|
173
200
|
} else {
|
|
174
|
-
|
|
201
|
+
result = { ready: false, error: `CodexLens not installed: ${stderr}` };
|
|
175
202
|
}
|
|
203
|
+
// Cache the result
|
|
204
|
+
venvStatusCache = { status: result, timestamp: Date.now() };
|
|
205
|
+
resolve(result);
|
|
176
206
|
});
|
|
177
207
|
|
|
178
208
|
child.on('error', (err) => {
|
|
179
|
-
|
|
209
|
+
const result = { ready: false, error: `Failed to check venv: ${err.message}` };
|
|
210
|
+
venvStatusCache = { status: result, timestamp: Date.now() };
|
|
211
|
+
resolve(result);
|
|
180
212
|
});
|
|
181
213
|
});
|
|
182
214
|
}
|
|
@@ -198,8 +230,15 @@ async function checkSemanticStatus(): Promise<SemanticStatus> {
|
|
|
198
230
|
import sys
|
|
199
231
|
import json
|
|
200
232
|
try:
|
|
201
|
-
|
|
202
|
-
|
|
233
|
+
import codexlens.semantic as semantic
|
|
234
|
+
SEMANTIC_AVAILABLE = bool(getattr(semantic, "SEMANTIC_AVAILABLE", False))
|
|
235
|
+
SEMANTIC_BACKEND = getattr(semantic, "SEMANTIC_BACKEND", None)
|
|
236
|
+
LITELLM_AVAILABLE = bool(getattr(semantic, "LITELLM_AVAILABLE", False))
|
|
237
|
+
result = {
|
|
238
|
+
"available": SEMANTIC_AVAILABLE,
|
|
239
|
+
"backend": SEMANTIC_BACKEND if SEMANTIC_AVAILABLE else None,
|
|
240
|
+
"litellm_available": LITELLM_AVAILABLE,
|
|
241
|
+
}
|
|
203
242
|
|
|
204
243
|
# Get ONNX providers for accelerator info
|
|
205
244
|
try:
|
|
@@ -250,6 +289,7 @@ except Exception as e:
|
|
|
250
289
|
backend: result.backend,
|
|
251
290
|
accelerator: result.accelerator || 'CPU',
|
|
252
291
|
providers: result.providers || [],
|
|
292
|
+
litellmAvailable: result.litellm_available || false,
|
|
253
293
|
error: result.error
|
|
254
294
|
});
|
|
255
295
|
} catch {
|
|
@@ -263,6 +303,77 @@ except Exception as e:
|
|
|
263
303
|
});
|
|
264
304
|
}
|
|
265
305
|
|
|
306
|
+
/**
|
|
307
|
+
* Ensure LiteLLM embedder dependencies are available in the CodexLens venv.
|
|
308
|
+
* Installs ccw-litellm into the venv if needed.
|
|
309
|
+
*/
|
|
310
|
+
async function ensureLiteLLMEmbedderReady(): Promise<BootstrapResult> {
|
|
311
|
+
// Ensure CodexLens venv exists and CodexLens is installed.
|
|
312
|
+
const readyStatus = await ensureReady();
|
|
313
|
+
if (!readyStatus.ready) {
|
|
314
|
+
return { success: false, error: readyStatus.error || 'CodexLens not ready' };
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Check if ccw_litellm can be imported
|
|
318
|
+
const importStatus = await new Promise<{ ok: boolean; error?: string }>((resolve) => {
|
|
319
|
+
const child = spawn(VENV_PYTHON, ['-c', 'import ccw_litellm; print("OK")'], {
|
|
320
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
321
|
+
timeout: 15000,
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
let stderr = '';
|
|
325
|
+
child.stderr.on('data', (data) => {
|
|
326
|
+
stderr += data.toString();
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
child.on('close', (code) => {
|
|
330
|
+
resolve({ ok: code === 0, error: stderr.trim() || undefined });
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
child.on('error', (err) => {
|
|
334
|
+
resolve({ ok: false, error: err.message });
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
if (importStatus.ok) {
|
|
339
|
+
return { success: true };
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const pipPath =
|
|
343
|
+
process.platform === 'win32'
|
|
344
|
+
? join(CODEXLENS_VENV, 'Scripts', 'pip.exe')
|
|
345
|
+
: join(CODEXLENS_VENV, 'bin', 'pip');
|
|
346
|
+
|
|
347
|
+
try {
|
|
348
|
+
console.log('[CodexLens] Installing ccw-litellm for LiteLLM embedding backend...');
|
|
349
|
+
|
|
350
|
+
const possiblePaths = [
|
|
351
|
+
join(process.cwd(), 'ccw-litellm'),
|
|
352
|
+
join(__dirname, '..', '..', '..', 'ccw-litellm'), // ccw/src/tools -> project root
|
|
353
|
+
join(homedir(), 'ccw-litellm'),
|
|
354
|
+
];
|
|
355
|
+
|
|
356
|
+
let installed = false;
|
|
357
|
+
for (const localPath of possiblePaths) {
|
|
358
|
+
if (existsSync(join(localPath, 'pyproject.toml'))) {
|
|
359
|
+
console.log(`[CodexLens] Installing ccw-litellm from local path: ${localPath}`);
|
|
360
|
+
execSync(`"${pipPath}" install -e "${localPath}"`, { stdio: 'inherit' });
|
|
361
|
+
installed = true;
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (!installed) {
|
|
367
|
+
console.log('[CodexLens] Installing ccw-litellm from PyPI...');
|
|
368
|
+
execSync(`"${pipPath}" install ccw-litellm`, { stdio: 'inherit' });
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return { success: true };
|
|
372
|
+
} catch (err) {
|
|
373
|
+
return { success: false, error: `Failed to install ccw-litellm: ${(err as Error).message}` };
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
266
377
|
/**
|
|
267
378
|
* GPU acceleration mode for semantic search
|
|
268
379
|
*/
|
|
@@ -421,6 +532,17 @@ async function installSemantic(gpuMode: GpuMode = 'cpu'): Promise<BootstrapResul
|
|
|
421
532
|
|
|
422
533
|
child.on('close', (code) => {
|
|
423
534
|
if (code === 0) {
|
|
535
|
+
// IMPORTANT: fastembed installs onnxruntime (CPU) as dependency, which conflicts
|
|
536
|
+
// with onnxruntime-directml/gpu. Reinstall the GPU version to ensure it takes precedence.
|
|
537
|
+
if (gpuMode !== 'cpu') {
|
|
538
|
+
try {
|
|
539
|
+
console.log(`[CodexLens] Reinstalling ${onnxPackage} to ensure GPU provider works...`);
|
|
540
|
+
execSync(`"${pipPath}" install --force-reinstall ${onnxPackage}`, { stdio: 'pipe', timeout: 300000 });
|
|
541
|
+
console.log(`[CodexLens] ${onnxPackage} reinstalled successfully`);
|
|
542
|
+
} catch (e) {
|
|
543
|
+
console.warn(`[CodexLens] Warning: Failed to reinstall ${onnxPackage}: ${(e as Error).message}`);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
424
546
|
console.log(`[CodexLens] Semantic dependencies installed successfully (${gpuMode} mode)`);
|
|
425
547
|
resolve({ success: true, message: `Installed with ${modeDescription}` });
|
|
426
548
|
} else {
|
|
@@ -490,6 +612,8 @@ async function bootstrapVenv(): Promise<BootstrapResult> {
|
|
|
490
612
|
execSync(`"${pipPath}" install codexlens`, { stdio: 'inherit' });
|
|
491
613
|
}
|
|
492
614
|
|
|
615
|
+
// Clear cache after successful installation
|
|
616
|
+
clearVenvStatusCache();
|
|
493
617
|
return { success: true };
|
|
494
618
|
} catch (err) {
|
|
495
619
|
return { success: false, error: `Failed to install codexlens: ${(err as Error).message}` };
|
|
@@ -1209,6 +1333,7 @@ async function uninstallCodexLens(): Promise<BootstrapResult> {
|
|
|
1209
1333
|
// Reset bootstrap cache
|
|
1210
1334
|
bootstrapChecked = false;
|
|
1211
1335
|
bootstrapReady = false;
|
|
1336
|
+
clearVenvStatusCache();
|
|
1212
1337
|
|
|
1213
1338
|
console.log('[CodexLens] CodexLens uninstalled successfully');
|
|
1214
1339
|
return { success: true, message: 'CodexLens uninstalled successfully' };
|
|
@@ -1273,7 +1398,19 @@ function isIndexingInProgress(): boolean {
|
|
|
1273
1398
|
export type { ProgressInfo, ExecuteOptions };
|
|
1274
1399
|
|
|
1275
1400
|
// Export for direct usage
|
|
1276
|
-
export {
|
|
1401
|
+
export {
|
|
1402
|
+
ensureReady,
|
|
1403
|
+
executeCodexLens,
|
|
1404
|
+
checkVenvStatus,
|
|
1405
|
+
bootstrapVenv,
|
|
1406
|
+
checkSemanticStatus,
|
|
1407
|
+
ensureLiteLLMEmbedderReady,
|
|
1408
|
+
installSemantic,
|
|
1409
|
+
detectGpuSupport,
|
|
1410
|
+
uninstallCodexLens,
|
|
1411
|
+
cancelIndexing,
|
|
1412
|
+
isIndexingInProgress,
|
|
1413
|
+
};
|
|
1277
1414
|
export type { GpuMode };
|
|
1278
1415
|
|
|
1279
1416
|
// Backward-compatible export for tests
|