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.
Files changed (208) hide show
  1. package/.claude/CLAUDE.md +16 -1
  2. package/.claude/workflows/cli-templates/protocols/analysis-protocol.md +11 -4
  3. package/.claude/workflows/cli-templates/protocols/write-protocol.md +10 -75
  4. package/.claude/workflows/cli-tools-usage.md +14 -24
  5. package/.codex/AGENTS.md +51 -1
  6. package/.codex/prompts/compact.md +378 -0
  7. package/.gemini/GEMINI.md +57 -20
  8. package/ccw/dist/cli.d.ts.map +1 -1
  9. package/ccw/dist/cli.js +21 -8
  10. package/ccw/dist/cli.js.map +1 -1
  11. package/ccw/dist/commands/cli.d.ts +2 -0
  12. package/ccw/dist/commands/cli.d.ts.map +1 -1
  13. package/ccw/dist/commands/cli.js +129 -8
  14. package/ccw/dist/commands/cli.js.map +1 -1
  15. package/ccw/dist/commands/hook.d.ts.map +1 -1
  16. package/ccw/dist/commands/hook.js +3 -2
  17. package/ccw/dist/commands/hook.js.map +1 -1
  18. package/ccw/dist/config/litellm-api-config-manager.d.ts +180 -0
  19. package/ccw/dist/config/litellm-api-config-manager.d.ts.map +1 -0
  20. package/ccw/dist/config/litellm-api-config-manager.js +770 -0
  21. package/ccw/dist/config/litellm-api-config-manager.js.map +1 -0
  22. package/ccw/dist/config/provider-models.d.ts +73 -0
  23. package/ccw/dist/config/provider-models.d.ts.map +1 -0
  24. package/ccw/dist/config/provider-models.js +172 -0
  25. package/ccw/dist/config/provider-models.js.map +1 -0
  26. package/ccw/dist/core/cache-manager.d.ts.map +1 -1
  27. package/ccw/dist/core/cache-manager.js +3 -5
  28. package/ccw/dist/core/cache-manager.js.map +1 -1
  29. package/ccw/dist/core/dashboard-generator.d.ts.map +1 -1
  30. package/ccw/dist/core/dashboard-generator.js +3 -1
  31. package/ccw/dist/core/dashboard-generator.js.map +1 -1
  32. package/ccw/dist/core/routes/cli-routes.d.ts.map +1 -1
  33. package/ccw/dist/core/routes/cli-routes.js +169 -0
  34. package/ccw/dist/core/routes/cli-routes.js.map +1 -1
  35. package/ccw/dist/core/routes/codexlens-routes.d.ts.map +1 -1
  36. package/ccw/dist/core/routes/codexlens-routes.js +234 -18
  37. package/ccw/dist/core/routes/codexlens-routes.js.map +1 -1
  38. package/ccw/dist/core/routes/hooks-routes.d.ts.map +1 -1
  39. package/ccw/dist/core/routes/hooks-routes.js +30 -32
  40. package/ccw/dist/core/routes/hooks-routes.js.map +1 -1
  41. package/ccw/dist/core/routes/litellm-api-routes.d.ts +21 -0
  42. package/ccw/dist/core/routes/litellm-api-routes.d.ts.map +1 -0
  43. package/ccw/dist/core/routes/litellm-api-routes.js +780 -0
  44. package/ccw/dist/core/routes/litellm-api-routes.js.map +1 -0
  45. package/ccw/dist/core/routes/litellm-routes.d.ts +20 -0
  46. package/ccw/dist/core/routes/litellm-routes.d.ts.map +1 -0
  47. package/ccw/dist/core/routes/litellm-routes.js +85 -0
  48. package/ccw/dist/core/routes/litellm-routes.js.map +1 -0
  49. package/ccw/dist/core/routes/mcp-routes.js +2 -2
  50. package/ccw/dist/core/routes/mcp-routes.js.map +1 -1
  51. package/ccw/dist/core/routes/status-routes.d.ts.map +1 -1
  52. package/ccw/dist/core/routes/status-routes.js +39 -0
  53. package/ccw/dist/core/routes/status-routes.js.map +1 -1
  54. package/ccw/dist/core/routes/system-routes.js +1 -1
  55. package/ccw/dist/core/routes/system-routes.js.map +1 -1
  56. package/ccw/dist/core/server.d.ts.map +1 -1
  57. package/ccw/dist/core/server.js +15 -1
  58. package/ccw/dist/core/server.js.map +1 -1
  59. package/ccw/dist/mcp-server/index.js +1 -1
  60. package/ccw/dist/mcp-server/index.js.map +1 -1
  61. package/ccw/dist/tools/claude-cli-tools.d.ts +82 -0
  62. package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -0
  63. package/ccw/dist/tools/claude-cli-tools.js +216 -0
  64. package/ccw/dist/tools/claude-cli-tools.js.map +1 -0
  65. package/ccw/dist/tools/cli-executor.d.ts.map +1 -1
  66. package/ccw/dist/tools/cli-executor.js +76 -14
  67. package/ccw/dist/tools/cli-executor.js.map +1 -1
  68. package/ccw/dist/tools/codex-lens.d.ts +9 -2
  69. package/ccw/dist/tools/codex-lens.d.ts.map +1 -1
  70. package/ccw/dist/tools/codex-lens.js +114 -9
  71. package/ccw/dist/tools/codex-lens.js.map +1 -1
  72. package/ccw/dist/tools/context-cache-store.d.ts +136 -0
  73. package/ccw/dist/tools/context-cache-store.d.ts.map +1 -0
  74. package/ccw/dist/tools/context-cache-store.js +256 -0
  75. package/ccw/dist/tools/context-cache-store.js.map +1 -0
  76. package/ccw/dist/tools/context-cache.d.ts +56 -0
  77. package/ccw/dist/tools/context-cache.d.ts.map +1 -0
  78. package/ccw/dist/tools/context-cache.js +294 -0
  79. package/ccw/dist/tools/context-cache.js.map +1 -0
  80. package/ccw/dist/tools/core-memory.d.ts.map +1 -1
  81. package/ccw/dist/tools/core-memory.js +33 -19
  82. package/ccw/dist/tools/core-memory.js.map +1 -1
  83. package/ccw/dist/tools/index.d.ts.map +1 -1
  84. package/ccw/dist/tools/index.js +2 -0
  85. package/ccw/dist/tools/index.js.map +1 -1
  86. package/ccw/dist/tools/litellm-client.d.ts +85 -0
  87. package/ccw/dist/tools/litellm-client.d.ts.map +1 -0
  88. package/ccw/dist/tools/litellm-client.js +188 -0
  89. package/ccw/dist/tools/litellm-client.js.map +1 -0
  90. package/ccw/dist/tools/litellm-executor.d.ts +34 -0
  91. package/ccw/dist/tools/litellm-executor.d.ts.map +1 -0
  92. package/ccw/dist/tools/litellm-executor.js +192 -0
  93. package/ccw/dist/tools/litellm-executor.js.map +1 -0
  94. package/ccw/dist/tools/pattern-parser.d.ts +55 -0
  95. package/ccw/dist/tools/pattern-parser.d.ts.map +1 -0
  96. package/ccw/dist/tools/pattern-parser.js +237 -0
  97. package/ccw/dist/tools/pattern-parser.js.map +1 -0
  98. package/ccw/dist/tools/smart-search.d.ts +1 -0
  99. package/ccw/dist/tools/smart-search.d.ts.map +1 -1
  100. package/ccw/dist/tools/smart-search.js +117 -41
  101. package/ccw/dist/tools/smart-search.js.map +1 -1
  102. package/ccw/dist/types/litellm-api-config.d.ts +294 -0
  103. package/ccw/dist/types/litellm-api-config.d.ts.map +1 -0
  104. package/ccw/dist/types/litellm-api-config.js +8 -0
  105. package/ccw/dist/types/litellm-api-config.js.map +1 -0
  106. package/ccw/src/cli.ts +258 -244
  107. package/ccw/src/commands/cli.ts +153 -9
  108. package/ccw/src/commands/hook.ts +3 -2
  109. package/ccw/src/config/.litellm-api-config-manager.ts.2025-12-23T11-57-43-727Z.bak +441 -0
  110. package/ccw/src/config/litellm-api-config-manager.ts +1012 -0
  111. package/ccw/src/config/provider-models.ts +222 -0
  112. package/ccw/src/core/cache-manager.ts +292 -294
  113. package/ccw/src/core/dashboard-generator.ts +3 -1
  114. package/ccw/src/core/routes/cli-routes.ts +192 -0
  115. package/ccw/src/core/routes/codexlens-routes.ts +241 -19
  116. package/ccw/src/core/routes/hooks-routes.ts +399 -405
  117. package/ccw/src/core/routes/litellm-api-routes.ts +930 -0
  118. package/ccw/src/core/routes/litellm-routes.ts +107 -0
  119. package/ccw/src/core/routes/mcp-routes.ts +1271 -1271
  120. package/ccw/src/core/routes/status-routes.ts +51 -0
  121. package/ccw/src/core/routes/system-routes.ts +1 -1
  122. package/ccw/src/core/server.ts +15 -1
  123. package/ccw/src/mcp-server/index.ts +1 -1
  124. package/ccw/src/templates/dashboard-css/12-cli-legacy.css +44 -0
  125. package/ccw/src/templates/dashboard-css/31-api-settings.css +2265 -0
  126. package/ccw/src/templates/dashboard-js/components/cli-history.js +15 -8
  127. package/ccw/src/templates/dashboard-js/components/cli-status.js +323 -9
  128. package/ccw/src/templates/dashboard-js/components/navigation.js +329 -313
  129. package/ccw/src/templates/dashboard-js/i18n.js +583 -1
  130. package/ccw/src/templates/dashboard-js/views/api-settings.js +3362 -0
  131. package/ccw/src/templates/dashboard-js/views/cli-manager.js +199 -24
  132. package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +1265 -27
  133. package/ccw/src/templates/dashboard.html +840 -831
  134. package/ccw/src/tools/claude-cli-tools.ts +300 -0
  135. package/ccw/src/tools/cli-executor.ts +83 -14
  136. package/ccw/src/tools/codex-lens.ts +146 -9
  137. package/ccw/src/tools/context-cache-store.ts +368 -0
  138. package/ccw/src/tools/context-cache.ts +393 -0
  139. package/ccw/src/tools/core-memory.ts +33 -19
  140. package/ccw/src/tools/index.ts +2 -0
  141. package/ccw/src/tools/litellm-client.ts +246 -0
  142. package/ccw/src/tools/litellm-executor.ts +241 -0
  143. package/ccw/src/tools/pattern-parser.ts +329 -0
  144. package/ccw/src/tools/smart-search.ts +142 -41
  145. package/ccw/src/types/litellm-api-config.ts +402 -0
  146. package/ccw-litellm/README.md +180 -0
  147. package/ccw-litellm/pyproject.toml +35 -0
  148. package/ccw-litellm/src/ccw_litellm/__init__.py +47 -0
  149. package/ccw-litellm/src/ccw_litellm/__pycache__/__init__.cpython-313.pyc +0 -0
  150. package/ccw-litellm/src/ccw_litellm/__pycache__/cli.cpython-313.pyc +0 -0
  151. package/ccw-litellm/src/ccw_litellm/cli.py +108 -0
  152. package/ccw-litellm/src/ccw_litellm/clients/__init__.py +12 -0
  153. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/__init__.cpython-313.pyc +0 -0
  154. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_embedder.cpython-313.pyc +0 -0
  155. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_llm.cpython-313.pyc +0 -0
  156. package/ccw-litellm/src/ccw_litellm/clients/litellm_embedder.py +251 -0
  157. package/ccw-litellm/src/ccw_litellm/clients/litellm_llm.py +165 -0
  158. package/ccw-litellm/src/ccw_litellm/config/__init__.py +22 -0
  159. package/ccw-litellm/src/ccw_litellm/config/__pycache__/__init__.cpython-313.pyc +0 -0
  160. package/ccw-litellm/src/ccw_litellm/config/__pycache__/loader.cpython-313.pyc +0 -0
  161. package/ccw-litellm/src/ccw_litellm/config/__pycache__/models.cpython-313.pyc +0 -0
  162. package/ccw-litellm/src/ccw_litellm/config/loader.py +316 -0
  163. package/ccw-litellm/src/ccw_litellm/config/models.py +130 -0
  164. package/ccw-litellm/src/ccw_litellm/interfaces/__init__.py +14 -0
  165. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/__init__.cpython-313.pyc +0 -0
  166. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/embedder.cpython-313.pyc +0 -0
  167. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/llm.cpython-313.pyc +0 -0
  168. package/ccw-litellm/src/ccw_litellm/interfaces/embedder.py +52 -0
  169. package/ccw-litellm/src/ccw_litellm/interfaces/llm.py +45 -0
  170. package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
  171. package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-313.pyc +0 -0
  172. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
  173. package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-313.pyc +0 -0
  174. package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-313.pyc +0 -0
  175. package/codex-lens/src/codexlens/cli/commands.py +378 -23
  176. package/codex-lens/src/codexlens/cli/embedding_manager.py +660 -56
  177. package/codex-lens/src/codexlens/cli/model_manager.py +31 -18
  178. package/codex-lens/src/codexlens/cli/output.py +12 -1
  179. package/codex-lens/src/codexlens/config.py +93 -0
  180. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
  181. package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
  182. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
  183. package/codex-lens/src/codexlens/search/chain_search.py +6 -2
  184. package/codex-lens/src/codexlens/search/hybrid_search.py +44 -21
  185. package/codex-lens/src/codexlens/search/ranking.py +1 -1
  186. package/codex-lens/src/codexlens/semantic/__init__.py +42 -0
  187. package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-313.pyc +0 -0
  188. package/codex-lens/src/codexlens/semantic/__pycache__/base.cpython-313.pyc +0 -0
  189. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
  190. package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-313.pyc +0 -0
  191. package/codex-lens/src/codexlens/semantic/__pycache__/factory.cpython-313.pyc +0 -0
  192. package/codex-lens/src/codexlens/semantic/__pycache__/gpu_support.cpython-313.pyc +0 -0
  193. package/codex-lens/src/codexlens/semantic/__pycache__/litellm_embedder.cpython-313.pyc +0 -0
  194. package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
  195. package/codex-lens/src/codexlens/semantic/base.py +61 -0
  196. package/codex-lens/src/codexlens/semantic/chunker.py +43 -20
  197. package/codex-lens/src/codexlens/semantic/embedder.py +60 -13
  198. package/codex-lens/src/codexlens/semantic/factory.py +98 -0
  199. package/codex-lens/src/codexlens/semantic/gpu_support.py +225 -3
  200. package/codex-lens/src/codexlens/semantic/litellm_embedder.py +144 -0
  201. package/codex-lens/src/codexlens/semantic/rotational_embedder.py +434 -0
  202. package/codex-lens/src/codexlens/semantic/vector_store.py +33 -8
  203. package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-313.pyc +0 -0
  204. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_004_dual_fts.cpython-313.pyc +0 -0
  205. package/codex-lens/src/codexlens/storage/path_mapper.py +27 -1
  206. package/package.json +15 -5
  207. package/.codex/prompts.zip +0 -0
  208. package/ccw/package.json +0 -65
@@ -9,6 +9,26 @@ var ccwEndpointTools = [];
9
9
  var cliToolConfig = null; // Store loaded CLI config
10
10
  var predefinedModels = {}; // Store predefined models per tool
11
11
 
12
+ // ========== Navigation Helpers ==========
13
+
14
+ /**
15
+ * Navigate to CodexLens Manager page
16
+ */
17
+ function navigateToCodexLensManager() {
18
+ var navItem = document.querySelector('.nav-item[data-view="codexlens-manager"]');
19
+ if (navItem) {
20
+ navItem.click();
21
+ } else {
22
+ // Fallback: try to render directly
23
+ if (typeof renderCodexLensManager === 'function') {
24
+ currentView = 'codexlens-manager';
25
+ renderCodexLensManager();
26
+ } else {
27
+ showRefreshToast(t('common.error') + ': CodexLens Manager not available', 'error');
28
+ }
29
+ }
30
+ }
31
+
12
32
  // ========== CCW Installations ==========
13
33
  async function loadCcwInstallations() {
14
34
  try {
@@ -39,6 +59,91 @@ async function loadCcwEndpointTools() {
39
59
  }
40
60
  }
41
61
 
62
+ // ========== LiteLLM API Endpoints ==========
63
+ var litellmApiEndpoints = [];
64
+ var cliCustomEndpoints = [];
65
+
66
+ async function loadLitellmApiEndpoints() {
67
+ try {
68
+ var response = await fetch('/api/litellm-api/config');
69
+ if (!response.ok) throw new Error('Failed to load LiteLLM endpoints');
70
+ var data = await response.json();
71
+ litellmApiEndpoints = data.endpoints || [];
72
+ window.litellmApiConfig = data;
73
+ return litellmApiEndpoints;
74
+ } catch (err) {
75
+ console.error('Failed to load LiteLLM endpoints:', err);
76
+ litellmApiEndpoints = [];
77
+ return [];
78
+ }
79
+ }
80
+
81
+ async function loadCliCustomEndpoints() {
82
+ try {
83
+ var response = await fetch('/api/cli/endpoints');
84
+ if (!response.ok) throw new Error('Failed to load CLI custom endpoints');
85
+ var data = await response.json();
86
+ cliCustomEndpoints = data.endpoints || [];
87
+ return cliCustomEndpoints;
88
+ } catch (err) {
89
+ console.error('Failed to load CLI custom endpoints:', err);
90
+ cliCustomEndpoints = [];
91
+ return [];
92
+ }
93
+ }
94
+
95
+ async function toggleEndpointEnabled(endpointId, enabled) {
96
+ try {
97
+ var response = await fetch('/api/cli/endpoints/' + endpointId, {
98
+ method: 'PUT',
99
+ headers: { 'Content-Type': 'application/json' },
100
+ body: JSON.stringify({ enabled: enabled })
101
+ });
102
+ if (!response.ok) throw new Error('Failed to update endpoint');
103
+ var data = await response.json();
104
+ if (data.success) {
105
+ // Update local state
106
+ var idx = cliCustomEndpoints.findIndex(function(e) { return e.id === endpointId; });
107
+ if (idx >= 0) {
108
+ cliCustomEndpoints[idx].enabled = enabled;
109
+ }
110
+ showRefreshToast((enabled ? 'Enabled' : 'Disabled') + ' endpoint: ' + endpointId, 'success');
111
+ }
112
+ return data;
113
+ } catch (err) {
114
+ showRefreshToast('Failed to update endpoint: ' + err.message, 'error');
115
+ throw err;
116
+ }
117
+ }
118
+
119
+ async function syncEndpointToCliTools(endpoint) {
120
+ try {
121
+ var response = await fetch('/api/cli/endpoints', {
122
+ method: 'POST',
123
+ headers: { 'Content-Type': 'application/json' },
124
+ body: JSON.stringify({
125
+ id: endpoint.id,
126
+ name: endpoint.name,
127
+ enabled: true
128
+ })
129
+ });
130
+ if (!response.ok) throw new Error('Failed to sync endpoint');
131
+ var data = await response.json();
132
+ if (data.success) {
133
+ cliCustomEndpoints = data.endpoints;
134
+ showRefreshToast('Endpoint synced to CLI tools: ' + endpoint.id, 'success');
135
+ renderToolsSection();
136
+ }
137
+ return data;
138
+ } catch (err) {
139
+ showRefreshToast('Failed to sync endpoint: ' + err.message, 'error');
140
+ throw err;
141
+ }
142
+ }
143
+
144
+ window.toggleEndpointEnabled = toggleEndpointEnabled;
145
+ window.syncEndpointToCliTools = syncEndpointToCliTools;
146
+
42
147
  // ========== CLI Tool Configuration ==========
43
148
  async function loadCliToolConfig() {
44
149
  try {
@@ -302,7 +407,9 @@ async function renderCliManager() {
302
407
  loadCliToolStatus(),
303
408
  loadCodexLensStatus(),
304
409
  loadCcwInstallations(),
305
- loadCcwEndpointTools()
410
+ loadCcwEndpointTools(),
411
+ loadLitellmApiEndpoints(),
412
+ loadCliCustomEndpoints()
306
413
  ]);
307
414
 
308
415
  container.innerHTML = '<div class="status-manager">' +
@@ -314,8 +421,7 @@ async function renderCliManager() {
314
421
  '<div class="cli-settings-section" id="cli-settings-section" style="margin-top: 1.5rem;"></div>' +
315
422
  '<div class="cli-section" id="ccw-endpoint-tools-section" style="margin-top: 1.5rem;"></div>' +
316
423
  '</div>' +
317
- '<section id="storageCard" class="mb-6"></section>' +
318
- '<section id="indexCard" class="mb-6"></section>';
424
+ '<section id="storageCard" class="mb-6"></section>';
319
425
 
320
426
  // Render sub-panels
321
427
  renderToolsSection();
@@ -329,11 +435,6 @@ async function renderCliManager() {
329
435
  initStorageManager();
330
436
  }
331
437
 
332
- // Initialize index manager card
333
- if (typeof initIndexManager === 'function') {
334
- initIndexManager();
335
- }
336
-
337
438
  // Initialize Lucide icons
338
439
  if (window.lucide) lucide.createIcons();
339
440
  }
@@ -434,28 +535,22 @@ function renderToolsSection() {
434
535
  '</div>';
435
536
  }).join('');
436
537
 
437
- // CodexLens item
438
- var codexLensHtml = '<div class="tool-item clickable ' + (codexLensStatus.ready ? 'available' : 'unavailable') + '" onclick="showCodexLensConfigModal()">' +
538
+ // CodexLens item - simplified view with link to manager page
539
+ var codexLensHtml = '<div class="tool-item clickable ' + (codexLensStatus.ready ? 'available' : 'unavailable') + '" onclick="navigateToCodexLensManager()">' +
439
540
  '<div class="tool-item-left">' +
440
541
  '<span class="tool-status-dot ' + (codexLensStatus.ready ? 'status-available' : 'status-unavailable') + '"></span>' +
441
542
  '<div class="tool-item-info">' +
442
543
  '<div class="tool-item-name">CodexLens <span class="tool-type-badge">Index</span>' +
443
- '<i data-lucide="settings" class="w-3 h-3 tool-config-icon"></i></div>' +
544
+ '<i data-lucide="external-link" class="w-3 h-3 tool-config-icon"></i></div>' +
444
545
  '<div class="tool-item-desc">' + (codexLensStatus.ready ? t('cli.codexLensDesc') : t('cli.codexLensDescFull')) + '</div>' +
445
546
  '</div>' +
446
547
  '</div>' +
447
548
  '<div class="tool-item-right">' +
448
549
  (codexLensStatus.ready
449
550
  ? '<span class="tool-status-text success"><i data-lucide="check-circle" class="w-3.5 h-3.5"></i> v' + (codexLensStatus.version || 'installed') + '</span>' +
450
- '<select id="codexlensModelSelect" class="btn-sm bg-muted border border-border rounded text-xs" onclick="event.stopPropagation()" title="' + (t('index.selectModel') || 'Select embedding model') + '">' +
451
- buildModelSelectOptions() +
452
- '</select>' +
453
- '<button class="btn-sm btn-primary" onclick="event.stopPropagation(); initCodexLensIndex(\'full\', getSelectedModel())" title="' + (t('index.fullDesc') || 'FTS + Semantic search (recommended)') + '"><i data-lucide="layers" class="w-3 h-3"></i> ' + (t('index.fullIndex') || '全部索引') + '</button>' +
454
- '<button class="btn-sm btn-outline" onclick="event.stopPropagation(); initCodexLensIndex(\'vector\', getSelectedModel())" title="' + (t('index.vectorDesc') || 'Semantic search with embeddings') + '"><i data-lucide="sparkles" class="w-3 h-3"></i> ' + (t('index.vectorIndex') || '向量索引') + '</button>' +
455
- '<button class="btn-sm btn-outline" onclick="event.stopPropagation(); initCodexLensIndex(\'normal\')" title="' + (t('index.normalDesc') || 'Fast full-text search only') + '"><i data-lucide="file-text" class="w-3 h-3"></i> ' + (t('index.normalIndex') || 'FTS索引') + '</button>' +
456
- '<button class="btn-sm btn-outline btn-danger" onclick="event.stopPropagation(); uninstallCodexLens()"><i data-lucide="trash-2" class="w-3 h-3"></i> ' + t('cli.uninstall') + '</button>'
551
+ '<button class="btn-sm btn-primary" onclick="event.stopPropagation(); navigateToCodexLensManager()"><i data-lucide="settings" class="w-3 h-3"></i> ' + t('cli.openManager') + '</button>'
457
552
  : '<span class="tool-status-text muted"><i data-lucide="circle-dashed" class="w-3.5 h-3.5"></i> ' + t('cli.notInstalled') + '</span>' +
458
- '<button class="btn-sm btn-primary" onclick="event.stopPropagation(); installCodexLens()"><i data-lucide="download" class="w-3 h-3"></i> ' + t('cli.install') + '</button>') +
553
+ '<button class="btn-sm btn-primary" onclick="event.stopPropagation(); navigateToCodexLensManager()"><i data-lucide="settings" class="w-3 h-3"></i> ' + t('cli.openManager') + '</button>') +
459
554
  '</div>' +
460
555
  '</div>';
461
556
 
@@ -479,6 +574,51 @@ function renderToolsSection() {
479
574
  '</div>';
480
575
  }
481
576
 
577
+ // API Endpoints section
578
+ var apiEndpointsHtml = '';
579
+ if (litellmApiEndpoints.length > 0) {
580
+ var endpointItems = litellmApiEndpoints.map(function(endpoint) {
581
+ // Check if endpoint is synced to CLI tools
582
+ var cliEndpoint = cliCustomEndpoints.find(function(e) { return e.id === endpoint.id; });
583
+ var isSynced = !!cliEndpoint;
584
+ var isEnabled = cliEndpoint ? cliEndpoint.enabled : false;
585
+
586
+ // Find provider info
587
+ var provider = (window.litellmApiConfig?.providers || []).find(function(p) { return p.id === endpoint.providerId; });
588
+ var providerName = provider ? provider.name : endpoint.providerId;
589
+
590
+ return '<div class="tool-item ' + (isSynced && isEnabled ? 'available' : 'unavailable') + '">' +
591
+ '<div class="tool-item-left">' +
592
+ '<span class="tool-status-dot ' + (isSynced && isEnabled ? 'status-available' : 'status-unavailable') + '"></span>' +
593
+ '<div class="tool-item-info">' +
594
+ '<div class="tool-item-name">' + endpoint.id + ' <span class="tool-type-badge">API</span></div>' +
595
+ '<div class="tool-item-desc">' + endpoint.model + ' (' + providerName + ')</div>' +
596
+ '</div>' +
597
+ '</div>' +
598
+ '<div class="tool-item-right">' +
599
+ (isSynced
600
+ ? '<label class="toggle-switch" onclick="event.stopPropagation()">' +
601
+ '<input type="checkbox" ' + (isEnabled ? 'checked' : '') + ' onchange="toggleEndpointEnabled(\'' + endpoint.id + '\', this.checked); renderToolsSection();">' +
602
+ '<span class="toggle-slider"></span>' +
603
+ '</label>'
604
+ : '<button class="btn-sm btn-primary" onclick="event.stopPropagation(); syncEndpointToCliTools({id: \'' + endpoint.id + '\', name: \'' + endpoint.name + '\'})">' +
605
+ '<i data-lucide="plus" class="w-3 h-3"></i> ' + (t('cli.addToCli') || 'Add to CLI') +
606
+ '</button>') +
607
+ '</div>' +
608
+ '</div>';
609
+ }).join('');
610
+
611
+ apiEndpointsHtml = '<div class="tools-subsection" style="margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--border);">' +
612
+ '<div class="section-header-left" style="margin-bottom: 0.5rem;">' +
613
+ '<h4 style="font-size: 0.875rem; font-weight: 600; display: flex; align-items: center; gap: 0.5rem;">' +
614
+ '<i data-lucide="cloud" class="w-4 h-4"></i> ' + (t('cli.apiEndpoints') || 'API Endpoints') +
615
+ '</h4>' +
616
+ '<span class="section-count">' + litellmApiEndpoints.length + ' ' + (t('cli.configured') || 'configured') + '</span>' +
617
+ '</div>' +
618
+ '<div class="tools-list">' + endpointItems + '</div>' +
619
+ '</div>';
620
+ }
621
+
482
622
  container.innerHTML = '<div class="section-header">' +
483
623
  '<div class="section-header-left">' +
484
624
  '<h3><i data-lucide="terminal" class="w-4 h-4"></i> ' + t('cli.tools') + '</h3>' +
@@ -492,7 +632,8 @@ function renderToolsSection() {
492
632
  toolsHtml +
493
633
  codexLensHtml +
494
634
  semanticHtml +
495
- '</div>';
635
+ '</div>' +
636
+ apiEndpointsHtml;
496
637
 
497
638
  if (window.lucide) lucide.createIcons();
498
639
  }
@@ -606,6 +747,16 @@ async function loadWindowsPlatformSettings() {
606
747
 
607
748
  async function toggleChineseResponse(enabled) {
608
749
  if (chineseResponseLoading) return;
750
+
751
+ // Pre-check: verify CCW workflows are installed (only when enabling)
752
+ if (enabled && typeof ccwInstallStatus !== 'undefined' && !ccwInstallStatus.installed) {
753
+ var missingFile = ccwInstallStatus.missingFiles.find(function(f) { return f === 'chinese-response.md'; });
754
+ if (missingFile) {
755
+ showRefreshToast(t('lang.installRequired'), 'warning');
756
+ return;
757
+ }
758
+ }
759
+
609
760
  chineseResponseLoading = true;
610
761
 
611
762
  try {
@@ -617,7 +768,14 @@ async function toggleChineseResponse(enabled) {
617
768
 
618
769
  if (!response.ok) {
619
770
  var errData = await response.json();
620
- throw new Error(errData.error || 'Failed to update setting');
771
+ // Show specific error message from backend
772
+ var errorMsg = errData.error || 'Failed to update setting';
773
+ if (errorMsg.includes('not found')) {
774
+ showRefreshToast(t('lang.installRequired'), 'warning');
775
+ } else {
776
+ showRefreshToast((enabled ? t('lang.enableFailed') : t('lang.disableFailed')) + ': ' + errorMsg, 'error');
777
+ }
778
+ throw new Error(errorMsg);
621
779
  }
622
780
 
623
781
  var data = await response.json();
@@ -630,7 +788,7 @@ async function toggleChineseResponse(enabled) {
630
788
  showRefreshToast(enabled ? t('lang.enableSuccess') : t('lang.disableSuccess'), 'success');
631
789
  } catch (err) {
632
790
  console.error('Failed to toggle Chinese response:', err);
633
- showRefreshToast(enabled ? t('lang.enableFailed') : t('lang.disableFailed'), 'error');
791
+ // Error already shown in the !response.ok block
634
792
  } finally {
635
793
  chineseResponseLoading = false;
636
794
  }
@@ -638,6 +796,16 @@ async function toggleChineseResponse(enabled) {
638
796
 
639
797
  async function toggleWindowsPlatform(enabled) {
640
798
  if (windowsPlatformLoading) return;
799
+
800
+ // Pre-check: verify CCW workflows are installed (only when enabling)
801
+ if (enabled && typeof ccwInstallStatus !== 'undefined' && !ccwInstallStatus.installed) {
802
+ var missingFile = ccwInstallStatus.missingFiles.find(function(f) { return f === 'windows-platform.md'; });
803
+ if (missingFile) {
804
+ showRefreshToast(t('lang.installRequired'), 'warning');
805
+ return;
806
+ }
807
+ }
808
+
641
809
  windowsPlatformLoading = true;
642
810
 
643
811
  try {
@@ -649,7 +817,14 @@ async function toggleWindowsPlatform(enabled) {
649
817
 
650
818
  if (!response.ok) {
651
819
  var errData = await response.json();
652
- throw new Error(errData.error || 'Failed to update setting');
820
+ // Show specific error message from backend
821
+ var errorMsg = errData.error || 'Failed to update setting';
822
+ if (errorMsg.includes('not found')) {
823
+ showRefreshToast(t('lang.installRequired'), 'warning');
824
+ } else {
825
+ showRefreshToast((enabled ? t('lang.windowsEnableFailed') : t('lang.windowsDisableFailed')) + ': ' + errorMsg, 'error');
826
+ }
827
+ throw new Error(errorMsg);
653
828
  }
654
829
 
655
830
  var data = await response.json();
@@ -662,7 +837,7 @@ async function toggleWindowsPlatform(enabled) {
662
837
  showRefreshToast(enabled ? t('lang.windowsEnableSuccess') : t('lang.windowsDisableSuccess'), 'success');
663
838
  } catch (err) {
664
839
  console.error('Failed to toggle Windows platform:', err);
665
- showRefreshToast(enabled ? t('lang.windowsEnableFailed') : t('lang.windowsDisableFailed'), 'error');
840
+ // Error already shown in the !response.ok block
666
841
  } finally {
667
842
  windowsPlatformLoading = false;
668
843
  }