mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-13 08:15:17 +00:00
fix(cursor): harden stopDaemon PID validation, tighten regex, add lifecycle test
- Validate PID belongs to cursor daemon via /proc before signaling - Tighten detectProvider regex to avoid over-matching o-prefixed models - Add integration test for daemon start→health→stop lifecycle - Add void cast on discarded handleHelp() return value - Update model catalog date comment
This commit is contained in:
1 parent
934238740e
commit
760a5c3ca4
4 files changed
+38
-3
No files matched your search
@@ -60,7 +60,7 @@ export async function handleCursorCommand(args: string[]): Promise<number> {
|
|||||||
default:
|
default:
|
||||||
console.error(fail(`Unknown subcommand: ${subcommand}`));
|
console.error(fail(`Unknown subcommand: ${subcommand}`));
|
||||||
console.error('');
|
console.error('');
|
||||||
handleHelp();
|
void handleHelp(); // Print help but keep exit code 1
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,6 +264,18 @@ export async function stopDaemon(): Promise<{ success: boolean; error?: string }
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Verify the PID belongs to our daemon before signaling
|
||||||
|
try {
|
||||||
|
const cmdline = fs.readFileSync(`/proc/${pid}/cmdline`, 'utf8');
|
||||||
|
if (!cmdline.includes('cursor') && !cmdline.includes('/health')) {
|
||||||
|
// PID was reused by an unrelated process
|
||||||
|
removePidFile();
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// /proc not available (macOS/Windows) or process gone — proceed with kill
|
||||||
|
}
|
||||||
|
|
||||||
// Send SIGTERM to the process
|
// Send SIGTERM to the process
|
||||||
process.kill(pid, 'SIGTERM');
|
process.kill(pid, 'SIGTERM');
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Cursor Model Catalog
|
* Cursor Model Catalog
|
||||||
*
|
*
|
||||||
* Manages available models from Cursor IDE.
|
* Manages available models from Cursor IDE.
|
||||||
* Based on Cursor's supported models as of Feb 2025.
|
* Based on Cursor's supported models catalog.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
@@ -165,7 +165,7 @@ export function getDefaultModel(): string {
|
|||||||
*/
|
*/
|
||||||
export function detectProvider(modelId: string): string {
|
export function detectProvider(modelId: string): string {
|
||||||
if (modelId.includes('claude')) return 'anthropic';
|
if (modelId.includes('claude')) return 'anthropic';
|
||||||
if (modelId.includes('gpt') || /^o\d/.test(modelId)) return 'openai';
|
if (modelId.includes('gpt') || /^o[1-9]\d*(-|$)/.test(modelId)) return 'openai';
|
||||||
if (modelId.includes('gemini')) return 'google';
|
if (modelId.includes('gemini')) return 'google';
|
||||||
if (modelId.includes('cursor')) return 'cursor';
|
if (modelId.includes('cursor')) return 'cursor';
|
||||||
return 'unknown';
|
return 'unknown';
|
||||||
|
|||||||
@@ -137,6 +137,29 @@ describe('startDaemon', () => {
|
|||||||
expect(result.success).toBe(false);
|
expect(result.success).toBe(false);
|
||||||
expect(result.error).toContain('Invalid port');
|
expect(result.error).toContain('Invalid port');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it(
|
||||||
|
'starts and stops daemon successfully',
|
||||||
|
async () => {
|
||||||
|
const port = 18765;
|
||||||
|
const result = await startDaemon({ port, model: 'test' });
|
||||||
|
expect(result.success).toBe(true);
|
||||||
|
expect(result.pid).toBeDefined();
|
||||||
|
|
||||||
|
// Verify health
|
||||||
|
const running = await isDaemonRunning(port);
|
||||||
|
expect(running).toBe(true);
|
||||||
|
|
||||||
|
// Stop
|
||||||
|
const stopResult = await stopDaemon();
|
||||||
|
expect(stopResult.success).toBe(true);
|
||||||
|
|
||||||
|
// Verify stopped
|
||||||
|
const stillRunning = await isDaemonRunning(port);
|
||||||
|
expect(stillRunning).toBe(false);
|
||||||
|
},
|
||||||
|
35000
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('isDaemonRunning', () => {
|
describe('isDaemonRunning', () => {
|
||||||
|
|||||||
Reference in new issue
Block a user