Files
automaker/plan/cursor-cli-integration/phases/phase-4-routes.md
Kacper 81f35ad6aa chore: Add Cursor CLI integration plan and phases
- Introduced a comprehensive integration plan for the Cursor CLI, including detailed phases for implementation.
- Created initial markdown files for each phase, outlining objectives, tasks, and verification steps.
- Established a global prompt template for starting new sessions with the Cursor CLI.
- Added necessary types and configuration for Cursor models and their integration into the AutoMaker architecture.
- Implemented routing logic to ensure proper model handling between Cursor and Claude providers.
- Developed UI components for setup and settings management related to Cursor integration.
- Included extensive testing and validation plans to ensure robust functionality across all scenarios.
2025-12-27 23:50:17 +01:00

349 lines
9.1 KiB
Markdown

# Phase 4: Setup Routes & Status Endpoints
**Status:** `pending`
**Dependencies:** Phase 3 (Factory)
**Estimated Effort:** Medium (API endpoints)
---
## Objective
Create API endpoints for checking Cursor CLI status and managing configuration.
---
## Tasks
### Task 4.1: Create Cursor Status Route
**Status:** `pending`
**File:** `apps/server/src/routes/setup/routes/cursor-status.ts`
```typescript
import { Router, Request, Response } from 'express';
import { CursorProvider } from '../../../providers/cursor-provider';
import { createLogger } from '@automaker/utils';
// Create logger for this module
const logger = createLogger('CursorStatusRoute');
/**
* GET /api/setup/cursor-status
* Returns Cursor CLI installation and authentication status
*/
export function createCursorStatusHandler() {
return async (req: Request, res: Response) => {
try {
const provider = new CursorProvider();
const [installed, version, auth] = await Promise.all([
provider.isInstalled(),
provider.getVersion(),
provider.checkAuth(),
]);
res.json({
success: true,
installed,
version: version || null,
path: installed ? (provider as any).cliPath : null,
auth: {
authenticated: auth.authenticated,
method: auth.method,
},
installCommand: 'curl https://cursor.com/install -fsS | bash',
loginCommand: 'cursor-agent login',
});
} catch (error) {
logger.error('[cursor-status] Error:', error);
res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
});
}
};
}
export function createCursorStatusRoute(): Router {
const router = Router();
router.get('/cursor-status', createCursorStatusHandler());
return router;
}
```
### Task 4.2: Create Cursor Config Routes
**Status:** `pending`
**File:** `apps/server/src/routes/setup/routes/cursor-config.ts`
```typescript
import { Router, Request, Response } from 'express';
import { CursorConfigManager } from '../../../providers/cursor-config-manager';
import { CURSOR_MODEL_MAP, CursorModelId } from '@automaker/types';
import { createLogger } from '@automaker/utils';
// Create logger for this module
const logger = createLogger('CursorConfigRoute');
export function createCursorConfigRoutes(dataDir: string): Router {
const router = Router();
const configManager = new CursorConfigManager(dataDir);
/**
* GET /api/setup/cursor-config
* Get current Cursor configuration
*/
router.get('/cursor-config', (req: Request, res: Response) => {
try {
res.json({
success: true,
config: configManager.getConfig(),
availableModels: Object.values(CURSOR_MODEL_MAP),
});
} catch (error) {
logger.error('[cursor-config] GET error:', error);
res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
});
}
});
/**
* POST /api/setup/cursor-config/default-model
* Set the default Cursor model
*/
router.post('/cursor-config/default-model', (req: Request, res: Response) => {
try {
const { model } = req.body;
if (!model || !(model in CURSOR_MODEL_MAP)) {
res.status(400).json({
success: false,
error: `Invalid model ID. Valid models: ${Object.keys(CURSOR_MODEL_MAP).join(', ')}`,
});
return;
}
configManager.setDefaultModel(model as CursorModelId);
res.json({ success: true, model });
} catch (error) {
logger.error('[cursor-config] POST default-model error:', error);
res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
});
}
});
/**
* POST /api/setup/cursor-config/models
* Set enabled Cursor models
*/
router.post('/cursor-config/models', (req: Request, res: Response) => {
try {
const { models } = req.body;
if (!Array.isArray(models)) {
res.status(400).json({
success: false,
error: 'Models must be an array',
});
return;
}
// Filter to valid models only
const validModels = models.filter((m): m is CursorModelId => m in CURSOR_MODEL_MAP);
if (validModels.length === 0) {
res.status(400).json({
success: false,
error: 'No valid models provided',
});
return;
}
configManager.setEnabledModels(validModels);
res.json({ success: true, models: validModels });
} catch (error) {
logger.error('[cursor-config] POST models error:', error);
res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
});
}
});
return router;
}
```
### Task 4.3: Register Routes in Setup Index
**Status:** `pending`
**File:** `apps/server/src/routes/setup/index.ts`
Add to existing router:
```typescript
import { createCursorStatusRoute } from './routes/cursor-status';
import { createCursorConfigRoutes } from './routes/cursor-config';
// In the router setup function:
export function createSetupRouter(dataDir: string): Router {
const router = Router();
// Existing routes...
router.get('/claude-status', createClaudeStatusHandler());
// ...
// Add Cursor routes
router.use(createCursorStatusRoute());
router.use(createCursorConfigRoutes(dataDir));
return router;
}
```
### Task 4.4: Update HttpApiClient
**Status:** `pending`
**File:** `apps/ui/src/lib/http-api-client.ts`
Add Cursor methods to the HttpApiClient setup object:
```typescript
// In HttpApiClient class, extend the setup object:
setup = {
// Existing methods...
getClaudeStatus: () => this.get('/api/setup/claude-status'),
// Add Cursor methods
getCursorStatus: () =>
this.get<{
success: boolean;
installed?: boolean;
version?: string;
path?: string;
auth?: {
authenticated: boolean;
method: string;
};
installCommand?: string;
loginCommand?: string;
error?: string;
}>('/api/setup/cursor-status'),
getCursorConfig: () =>
this.get<{
success: boolean;
config?: CursorCliConfig;
availableModels?: CursorModelConfig[];
error?: string;
}>('/api/setup/cursor-config'),
setCursorDefaultModel: (model: CursorModelId) =>
this.post<{ success: boolean; error?: string }>('/api/setup/cursor-config/default-model', {
model,
}),
setCursorModels: (models: CursorModelId[]) =>
this.post<{ success: boolean; error?: string }>('/api/setup/cursor-config/models', { models }),
};
```
This integrates with the existing HttpApiClient pattern used throughout the UI.
---
## Verification
### Test 1: Status Endpoint
```bash
# Start the server, then:
curl http://localhost:3001/api/setup/cursor-status
# Expected response (if installed):
# {
# "success": true,
# "installed": true,
# "version": "0.1.0",
# "path": "/home/user/.local/bin/cursor-agent",
# "auth": { "authenticated": true, "method": "login" }
# }
# Expected response (if not installed):
# {
# "success": true,
# "installed": false,
# "installCommand": "curl https://cursor.com/install -fsS | bash"
# }
```
### Test 2: Config Endpoints
```bash
# Get config
curl http://localhost:3001/api/setup/cursor-config
# Set default model
curl -X POST http://localhost:3001/api/setup/cursor-config/default-model \
-H "Content-Type: application/json" \
-d '{"model": "gpt-4o"}'
# Set enabled models
curl -X POST http://localhost:3001/api/setup/cursor-config/models \
-H "Content-Type: application/json" \
-d '{"models": ["auto", "gpt-4o", "claude-sonnet-4"]}'
```
### Test 3: Error Handling
```bash
# Invalid model should return 400
curl -X POST http://localhost:3001/api/setup/cursor-config/default-model \
-H "Content-Type: application/json" \
-d '{"model": "invalid-model"}'
# Expected: {"success": false, "error": "Invalid model ID..."}
```
---
## Verification Checklist
Before marking this phase complete:
- [ ] `/api/setup/cursor-status` returns installation status
- [ ] `/api/setup/cursor-config` returns current config
- [ ] `/api/setup/cursor-config/default-model` updates default
- [ ] `/api/setup/cursor-config/models` updates enabled models
- [ ] Error responses have correct status codes (400, 500)
- [ ] Config persists to file after changes
- [ ] SetupAPI type updated (if using Electron IPC)
---
## Files Changed
| File | Action | Description |
| ------------------------------------------------------ | ------ | ---------------- |
| `apps/server/src/routes/setup/routes/cursor-status.ts` | Create | Status endpoint |
| `apps/server/src/routes/setup/routes/cursor-config.ts` | Create | Config endpoints |
| `apps/server/src/routes/setup/index.ts` | Modify | Register routes |
| `apps/ui/src/lib/electron.ts` | Modify | Add API types |
---
## Notes
- Config is stored in `.automaker/cursor-config.json`
- The status endpoint is optimized for quick checks (parallel calls)
- Install/login commands are included in response for UI display