fix: update getBuiltinTemplatesDir() and docs for React SPA migration

- Fix getBuiltinTemplatesDir() to safely handle missing templates directory
- Return null when no builtin templates exist instead of non-existent path
- Update listBuiltinTemplates() to handle null return value
- Update outdated docs referencing deleted dashboard-js/dashboard-css files
- Replace references to vanilla JS frontend with React SPA paths

Related: commit bcb73670 removed old vanilla JS/CSS frontend
This commit is contained in:
catlog22
2026-02-28 11:39:16 +08:00
parent 604f89b7aa
commit 0a37bc3eaf
5 changed files with 71 additions and 61 deletions

View File

@@ -1,18 +1,21 @@
# Codex MCP 功能实现总结 # Codex MCP 功能实现总结
> **注意**: 此文档描述的是旧的 vanilla JS 前端架构。当前版本 (v7.0+) 使用 React SPA 前端。
> 请参考 `ccw/frontend/src/` 目录中的 React 组件。
## 📝 已完成的修复 ## 📝 已完成的修复
### 1. CCW Tools MCP 卡片样式修复 ### 1. CCW Tools MCP 卡片样式修复
**文件**: `ccw/src/templates/dashboard-js/views/mcp-manager.js` **文件**: `ccw/frontend/src/components/McpManager.tsx` (React)
**修改内容**: **修改内容**:
- ✅ 卡片边框: `border-primary``border-orange-500` (第345行) - ✅ 卡片边框: `border-primary``border-orange-500`
- ✅ 图标背景: `bg-primary``bg-orange-500` (第348行) - ✅ 图标背景: `bg-primary``bg-orange-500`
- ✅ 图标颜色: `text-primary-foreground``text-white` (第349行) - ✅ 图标颜色: `text-primary-foreground``text-white`
- ✅ "Available"徽章: `bg-primary/20 text-primary``bg-orange-500/20 text-orange-600` (第360行) - ✅ "Available"徽章: `bg-primary/20 text-primary``bg-orange-500/20 text-orange-600`
- ✅ 选择按钮颜色: `text-primary``text-orange-500` (第378-379行) - ✅ 选择按钮颜色: `text-primary``text-orange-500`
- ✅ 安装按钮: `bg-primary``bg-orange-500` (第386行、第399行) - ✅ 安装按钮: `bg-primary``bg-orange-500`
**影响范围**: Claude 模式下的 CCW Tools MCP 卡片 **影响范围**: Claude 模式下的 CCW Tools MCP 卡片
@@ -20,10 +23,10 @@
### 2. Toast 消息显示时间增强 ### 2. Toast 消息显示时间增强
**文件**: `ccw/src/templates/dashboard-js/components/navigation.js` **文件**: `ccw/frontend/src/hooks/useToast.ts` (React)
**修改内容**: **修改内容**:
- ✅ 显示时间: 2000ms → 3500ms (第300行) - ✅ 显示时间: 2000ms → 3500ms
**影响范围**: 所有 Toast 消息MCP 安装、删除、切换等操作反馈) **影响范围**: 所有 Toast 消息MCP 安装、删除、切换等操作反馈)
@@ -55,38 +58,33 @@ API 请求: POST /api/codex-mcp-add
前端更新: 前端更新:
1. loadMcpConfig() - 重新加载配置 1. loadMcpConfig() - 重新加载配置
2. renderMcpManager() - 重新渲染 UI 2. 状态更新触发 UI 重新渲染
3. showRefreshToast(...) - 显示成功/失败消息 (3.5秒) 3. Toast 显示成功/失败消息 (3.5秒)
``` ```
--- ---
## 📍 关键代码位置 ## 📍 关键代码位置
### 前端 ### 前端 (React SPA)
| 功能 | 文件 | 行号 | 说明 | | 功能 | 文件 | 说明 |
|------|------|------|------| |------|------|------|
| 复制到 Codex | `components/mcp-manager.js` | 175-177 | `copyClaudeServerToCodex()` 函数 | | MCP 管理 | `ccw/frontend/src/components/McpManager.tsx` | MCP 管理组件 |
| 添加到 Codex | `components/mcp-manager.js` | 87-114 | `addCodexMcpServer()` 函数 | | Toast 消息 | `ccw/frontend/src/hooks/useToast.ts` | Toast hook |
| Toast 消息 | `components/navigation.js` | 286-301 | `showRefreshToast()` 函数 | | 复制到 Codex | `ccw/frontend/src/api/mcp.ts` | MCP API 调用 |
| CCW Tools 样式 | `views/mcp-manager.js` | 342-415 | Claude 模式卡片渲染 |
| 其他项目按钮 | `views/mcp-manager.js` | 1015-1020 | "Install to Codex" 按钮 |
### 后端 ### 后端
| 功能 | 文件 | 行号 | 说明 | | 功能 | 文件 | 说明 |
|------|------|------|------| |------|------|------|
| API 端点 | `core/routes/mcp-routes.ts` | 1001-1010 | `/api/codex-mcp-add` 路由 | | API 端点 | `ccw/src/core/routes/mcp-routes.ts` | `/api/codex-mcp-add` 路由 |
| 添加服务器 | `core/routes/mcp-routes.ts` | 251-330 | `addCodexMcpServer()` 函数 | | 添加服务器 | `ccw/src/core/routes/mcp-routes.ts` | `addCodexMcpServer()` 函数 |
| TOML 序列化 | `core/routes/mcp-routes.ts` | 166-188 | `serializeToml()` 函数 | | TOML 序列化 | `ccw/src/core/routes/mcp-routes.ts` | `serializeToml()` 函数 |
### CSS ### CSS (Tailwind)
| 功能 | 文件 | 行号 | 说明 | Toast 样式使用 Tailwind CSS 内联样式,定义在 React 组件中。
|------|------|------|------|
| Toast 样式 | `dashboard-css/06-cards.css` | 1501-1538 | Toast 容器和类型样式 |
| Toast 动画 | `dashboard-css/06-cards.css` | 1540-1551 | 滑入/淡出动画 |
--- ---
@@ -220,33 +218,31 @@ API 请求: POST /api/codex-mcp-add
## 📦 相关文件清单 ## 📦 相关文件清单
### 已修改文件 ### 前端文件 (React SPA)
1. `ccw/src/templates/dashboard-js/views/mcp-manager.js` 1. `ccw/frontend/src/components/McpManager.tsx`
- 修改: CCW Tools 卡片样式第342-415行 - MCP 管理组件(包含 CCW Tools 卡片样式)
2. `ccw/src/templates/dashboard-js/components/navigation.js`
- 修改: Toast 显示时间第300行
### 核心功能文件(未修改但相关) 2. `ccw/frontend/src/hooks/useToast.ts`
- Toast 消息 hook显示时间 3.5秒)
3. `ccw/src/templates/dashboard-js/components/mcp-manager.js` 3. `ccw/frontend/src/api/mcp.ts`
- 包含: `addCodexMcpServer()`, `copyClaudeServerToCodex()` 函数 - MCP API 调用函数
### 后端文件
4. `ccw/src/core/routes/mcp-routes.ts` 4. `ccw/src/core/routes/mcp-routes.ts`
- 包含: Codex MCP API 端点和后端逻辑 - Codex MCP API 端点和后端逻辑
5. `ccw/src/templates/dashboard-css/06-cards.css` ### 文档
- 包含: Toast 样式定义
### 新增文档 5. `ccw/docs/CODEX_MCP_TESTING_GUIDE.md`
6. `ccw/docs/CODEX_MCP_TESTING_GUIDE.md`
- 详细测试指南 - 详细测试指南
7. `ccw/docs/QUICK_TEST_CODEX_MCP.md` 6. `ccw/docs/QUICK_TEST_CODEX_MCP.md`
- 快速测试步骤 - 快速测试步骤
8. `ccw/docs/CODEX_MCP_IMPLEMENTATION_SUMMARY.md` 8. `ccw/docs/CODEX_MCP_IMPLEMENTATION_SUMMARY.md`
- 本文档 - 本文档

View File

@@ -277,7 +277,7 @@ _____
### Toast 消息机制 ### Toast 消息机制
**实现位置**: **实现位置**:
- `ccw/src/templates/dashboard-js/components/navigation.js:286-301` - `ccw/frontend/src/hooks/useToast.ts` (React)
- 显示时间3500ms (3.5秒) - 显示时间3500ms (3.5秒)
- 淡出动画300ms - 淡出动画300ms

View File

@@ -218,8 +218,8 @@ To verify the fix works:
## Related Files ## Related Files
- **Implementation**: `ccw/src/core/routes/graph-routes.ts` - **Implementation**: `ccw/src/core/routes/graph-routes.ts`
- **Frontend**: `ccw/src/templates/dashboard-js/views/graph-explorer.js` - **Frontend**: `ccw/frontend/src/components/GraphExplorer.tsx` (React SPA)
- **Styles**: `ccw/src/templates/dashboard-css/14-graph-explorer.css` - **Styles**: Embedded in React components
- **API Docs**: `ccw/src/core/routes/graph-routes.md` - **API Docs**: `ccw/src/core/routes/graph-routes.md`
- **Migration**: `codex-lens/src/codexlens/storage/migrations/migration_005_cleanup_unused_fields.py` - **Migration**: `codex-lens/src/codexlens/storage/migrations/migration_005_cleanup_unused_fields.py`

View File

@@ -238,23 +238,22 @@ ccw view
rg "handleGraphRoutes" src/ rg "handleGraphRoutes" src/
``` ```
2. **检查前端是否包含 graph-explorer 视图** 2. **检查前端是否包含 Graph Explorer 组件**
```bash ```bash
ls src/templates/dashboard-js/views/graph-explorer.js ls ccw/frontend/src/components/GraphExplorer.tsx
``` ```
3. **检查 dashboard-generator.ts 是否包含 graph explorer** 3. **检查 React 前端是否正确构建**
```bash ```bash
rg "graph-explorer" src/core/dashboard-generator.ts ls ccw/frontend/dist/index.html
``` ```
### 解决方案 ### 解决方案
确保以下文件存在且正确: 确保以下文件存在且正确:
- `src/core/routes/graph-routes.ts` - API 路由处理 - `ccw/src/core/routes/graph-routes.ts` - API 路由处理
- `src/templates/dashboard-js/views/graph-explorer.js` - 前端视图 - `ccw/frontend/src/components/GraphExplorer.tsx` - React 前端组件
- `src/templates/dashboard-css/14-graph-explorer.css` - 样式 - `ccw/frontend/dist/index.html` - 构建后的前端入口
- `src/templates/dashboard.html` - 包含 Graph 导航项line 334
--- ---

View File

@@ -31,6 +31,7 @@
*/ */
import { join, dirname } from 'path'; import { join, dirname } from 'path';
import { existsSync } from 'fs';
import { randomBytes } from 'crypto'; import { randomBytes } from 'crypto';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import type { RouteContext } from './types.js'; import type { RouteContext } from './types.js';
@@ -635,10 +636,24 @@ function getTemplatesDir(workflowDir: string): string {
/** /**
* Get the builtin templates directory path (shipped with CCW) * Get the builtin templates directory path (shipped with CCW)
* Returns null if the directory doesn't exist (e.g., in npm package without src/)
*/ */
function getBuiltinTemplatesDir(): string { function getBuiltinTemplatesDir(): string | null {
// Resolve relative to this module's location // Try multiple possible locations for builtin templates
return join(__dirname, '..', '..', '..', 'templates', 'orchestrator'); const possiblePaths = [
// From dist/core/routes/ -> ccw/templates/orchestrator/
join(__dirname, '..', '..', '..', 'templates', 'orchestrator'),
// From dist/core/routes/ -> ccw/src/templates/orchestrator/ (dev mode)
join(__dirname, '..', '..', '..', 'src', 'templates', 'orchestrator'),
];
for (const path of possiblePaths) {
if (existsSync(path)) {
return path;
}
}
return null;
} }
/** /**
@@ -745,10 +760,10 @@ async function listLocalTemplates(workflowDir: string): Promise<Template[]> {
*/ */
async function listBuiltinTemplates(): Promise<Template[]> { async function listBuiltinTemplates(): Promise<Template[]> {
const { readdir, readFile } = await import('fs/promises'); const { readdir, readFile } = await import('fs/promises');
const { existsSync } = await import('fs');
const builtinDir = getBuiltinTemplatesDir(); const builtinDir = getBuiltinTemplatesDir();
if (!existsSync(builtinDir)) { // getBuiltinTemplatesDir() returns null if no builtin templates directory exists
if (!builtinDir) {
return []; return [];
} }