mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-15 02:16:27 +00:00
fix(cursor): deprecate legacy bridge and harden gitlab auth
This commit is contained in:
1 parent
93afdb50bf
commit
87d93b651b
13 files changed
+334
-95
No files matched your search
@@ -69,6 +69,7 @@ import {
|
||||
warnPossible403Ban,
|
||||
} from '../account-safety';
|
||||
import { ensureCliAntigravityResponsibility } from '../antigravity-responsibility';
|
||||
import { InteractivePrompt } from '../../utils/prompt';
|
||||
|
||||
interface PasteCallbackStartData {
|
||||
url?: string;
|
||||
@@ -153,20 +154,21 @@ function normalizeGitLabBaseUrl(baseUrl: string | undefined): string | undefined
|
||||
return normalized ? normalized : undefined;
|
||||
}
|
||||
|
||||
async function promptGitLabPersonalAccessToken(): Promise<string | null> {
|
||||
const readline = await import('readline');
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
|
||||
return new Promise<string | null>((resolve) => {
|
||||
rl.question('GitLab Personal Access Token: ', (answer) => {
|
||||
rl.close();
|
||||
const token = answer.trim();
|
||||
resolve(token.length > 0 ? token : null);
|
||||
});
|
||||
});
|
||||
export async function promptGitLabPersonalAccessToken(): Promise<string | null> {
|
||||
try {
|
||||
const token = (await InteractivePrompt.password('GitLab Personal Access Token')).trim();
|
||||
return token.length > 0 ? token : null;
|
||||
} catch (error) {
|
||||
if ((error as Error).message.includes('TTY')) {
|
||||
console.log(
|
||||
fail(
|
||||
'GitLab Personal Access Token prompt requires an interactive TTY. Set the token explicitly or use Browser OAuth.'
|
||||
)
|
||||
);
|
||||
return null;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export function findNewTokenSnapshotForManualAuth(
|
||||
|
||||
@@ -152,6 +152,14 @@ export function readOptionValue(
|
||||
return { present: true, value: next.trim(), missingValue: false };
|
||||
}
|
||||
|
||||
export function hasGitLabTokenLoginFlag(args: string[]): boolean {
|
||||
return args.includes('--gitlab-token-login') || args.includes('--token-login');
|
||||
}
|
||||
|
||||
function getGitLabTokenLoginFlagName(args: string[]): '--gitlab-token-login' | '--token-login' {
|
||||
return args.includes('--gitlab-token-login') ? '--gitlab-token-login' : '--token-login';
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute Claude CLI with CLIProxy (main entry point)
|
||||
*
|
||||
@@ -353,7 +361,7 @@ export async function execClaudeWithCLIProxy(
|
||||
const addAccount = argsWithoutProxy.includes('--add');
|
||||
const showAccounts = argsWithoutProxy.includes('--accounts');
|
||||
const forceImport = argsWithoutProxy.includes('--import');
|
||||
const gitlabTokenLogin = argsWithoutProxy.includes('--token-login');
|
||||
const gitlabTokenLogin = hasGitLabTokenLoginFlag(argsWithoutProxy);
|
||||
const acceptAgyRisk = hasAntigravityRiskAcceptanceFlag(argsWithoutProxy);
|
||||
|
||||
const incognitoFlag = argsWithoutProxy.includes('--incognito');
|
||||
@@ -503,7 +511,9 @@ export async function execClaudeWithCLIProxy(
|
||||
}
|
||||
|
||||
if ((gitlabTokenLogin || gitlabBaseUrl) && provider !== 'gitlab') {
|
||||
const flagName = gitlabTokenLogin ? '--token-login' : '--gitlab-url';
|
||||
const flagName = gitlabTokenLogin
|
||||
? getGitLabTokenLoginFlagName(argsWithoutProxy)
|
||||
: '--gitlab-url';
|
||||
console.error(fail(`${flagName} is only valid for ccs gitlab`));
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
|
||||
@@ -12,37 +12,46 @@ function printLines(lines: string[]): void {
|
||||
|
||||
export function renderCursorHelp(): number {
|
||||
printLines([
|
||||
'Cursor IDE Integration',
|
||||
'Legacy Cursor Compatibility',
|
||||
'',
|
||||
'Deprecated: prefer CLIProxy-backed Cursor auth and account management.',
|
||||
'Supported auth path: ccs cursor --auth',
|
||||
'Supported dashboard path: ccs config -> CLIProxy -> Cursor',
|
||||
'',
|
||||
'Usage: ccs cursor <subcommand>',
|
||||
'',
|
||||
'Subcommands:',
|
||||
' auth Import Cursor IDE authentication token',
|
||||
' status Show integration, authentication, and daemon status',
|
||||
'Subcommands (deprecated compatibility for the local reverse-engineered bridge):',
|
||||
' auth Import Cursor IDE authentication token (deprecated)',
|
||||
' status Show legacy integration, authentication, and daemon status',
|
||||
' probe Run a live authenticated runtime probe',
|
||||
' models List available models',
|
||||
' start Start cursor daemon',
|
||||
' stop Stop cursor daemon',
|
||||
' enable Enable cursor integration in unified config',
|
||||
' disable Disable cursor integration in unified config',
|
||||
' start Start local cursor daemon',
|
||||
' stop Stop local cursor daemon',
|
||||
' enable Enable legacy cursor integration in unified config',
|
||||
' disable Disable legacy cursor integration in unified config',
|
||||
' help Show this help message',
|
||||
'',
|
||||
'Runtime entry:',
|
||||
' ccs cursor [claude args] # Run Claude via the local Cursor proxy',
|
||||
'Supported CLIProxy path:',
|
||||
' ccs cursor --auth # Authenticate Cursor via CLIProxy',
|
||||
' ccs cursor --accounts # Manage CLIProxy Cursor accounts',
|
||||
' ccs cursor --config # Open CLIProxy Cursor settings',
|
||||
'',
|
||||
'Auth options:',
|
||||
' ccs cursor auth # Auto-detect from Cursor SQLite',
|
||||
'Legacy runtime entry (deprecated compatibility):',
|
||||
' ccs cursor [claude args] # Run Claude via the local Cursor bridge',
|
||||
'',
|
||||
'Legacy auth options:',
|
||||
' ccs cursor auth # Auto-detect from Cursor SQLite (deprecated)',
|
||||
' ccs cursor auth --manual --token <t> --machine-id <id>',
|
||||
'',
|
||||
'Quick start:',
|
||||
' 1. ccs cursor enable # Enable integration',
|
||||
' 2. ccs cursor auth # Import Cursor IDE token',
|
||||
' 3. ccs cursor start # Start daemon',
|
||||
'Legacy bridge quick start:',
|
||||
' 1. ccs cursor enable # Deprecated compatibility: enable local bridge',
|
||||
' 2. ccs cursor auth # Deprecated compatibility: import Cursor IDE token',
|
||||
' 3. ccs cursor start # Start local daemon',
|
||||
' 4. ccs cursor probe # Verify live runtime health',
|
||||
' 5. ccs cursor "task" # Run Claude through Cursor',
|
||||
' 5. ccs cursor "task" # Run Claude through the local bridge',
|
||||
' 6. ccs cursor status # Inspect auth/daemon wiring',
|
||||
'',
|
||||
'Or use the web UI: ccs config -> Cursor page',
|
||||
'Web UI: ccs config -> Deprecated -> Cursor IDE',
|
||||
'',
|
||||
]);
|
||||
|
||||
@@ -100,7 +109,8 @@ export function renderCursorStatus(
|
||||
console.log('');
|
||||
console.log('Client setup:');
|
||||
console.log(` Raw settings: ${dirDisplay}/cursor.settings.json`);
|
||||
console.log(' Runtime entry: ccs cursor [claude args]');
|
||||
console.log(' Runtime entry: ccs cursor [claude args] (deprecated compatibility)');
|
||||
console.log(' Supported auth: ccs cursor --auth');
|
||||
console.log(' Live probe: ccs cursor probe');
|
||||
console.log(' Status command: ccs cursor status');
|
||||
console.log(' Help command: ccs cursor help');
|
||||
@@ -116,7 +126,8 @@ export function renderCursorStatus(
|
||||
console.log(' - Enable: ccs cursor enable');
|
||||
}
|
||||
if (!authStatus.authenticated || authStatus.expired) {
|
||||
console.log(' - Auth: ccs cursor auth');
|
||||
console.log(' - Supported: ccs cursor --auth');
|
||||
console.log(' - Legacy auth: ccs cursor auth');
|
||||
}
|
||||
if (!daemonStatus.running) {
|
||||
console.log(' - Start: ccs cursor start');
|
||||
|
||||
@@ -26,6 +26,15 @@ import {
|
||||
} from './cursor-command-display';
|
||||
import { ok, fail, info } from '../utils/ui';
|
||||
|
||||
function printLegacyCursorDeprecationNotice(): void {
|
||||
console.log(
|
||||
info(
|
||||
'Deprecated compatibility path. Prefer CLIProxy-backed Cursor auth via `ccs cursor --auth` or the CLIProxy dashboard.'
|
||||
)
|
||||
);
|
||||
console.log('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle cursor subcommand.
|
||||
*/
|
||||
@@ -114,6 +123,7 @@ function printAutoDetectFailure(result: {
|
||||
* Handle auth subcommand.
|
||||
*/
|
||||
async function handleAuth(args: string[]): Promise<number> {
|
||||
printLegacyCursorDeprecationNotice();
|
||||
const manual = args.includes('--manual');
|
||||
|
||||
if (manual) {
|
||||
@@ -146,6 +156,7 @@ async function handleAuth(args: string[]): Promise<number> {
|
||||
console.log(ok('Cursor credentials imported (manual mode)'));
|
||||
console.log('');
|
||||
console.log('Next steps:');
|
||||
console.log(' 0. Preferred auth: ccs cursor --auth');
|
||||
console.log(' 1. Enable integration: ccs cursor enable');
|
||||
console.log(' 2. Start daemon: ccs cursor start');
|
||||
return 0;
|
||||
@@ -168,6 +179,7 @@ async function handleAuth(args: string[]): Promise<number> {
|
||||
console.log(ok('Auto-detected Cursor credentials'));
|
||||
console.log('');
|
||||
console.log('Next steps:');
|
||||
console.log(' 0. Preferred auth: ccs cursor --auth');
|
||||
console.log(' 1. Enable integration: ccs cursor enable');
|
||||
console.log(' 2. Start daemon: ccs cursor start');
|
||||
console.log(' 3. Check status: ccs cursor status');
|
||||
@@ -185,6 +197,7 @@ async function handleAuth(args: string[]): Promise<number> {
|
||||
}
|
||||
|
||||
async function handleStatus(): Promise<number> {
|
||||
printLegacyCursorDeprecationNotice();
|
||||
const cursorConfig = getCursorConfig();
|
||||
const authStatus = checkAuthStatus();
|
||||
const daemonStatus = await getDaemonStatus(cursorConfig.port);
|
||||
@@ -193,6 +206,7 @@ async function handleStatus(): Promise<number> {
|
||||
}
|
||||
|
||||
async function handleProbe(): Promise<number> {
|
||||
printLegacyCursorDeprecationNotice();
|
||||
const cursorConfig = getCursorConfig();
|
||||
const result = await probeCursorRuntime(cursorConfig);
|
||||
renderCursorProbe(result);
|
||||
@@ -200,6 +214,7 @@ async function handleProbe(): Promise<number> {
|
||||
}
|
||||
|
||||
async function handleModels(): Promise<number> {
|
||||
printLegacyCursorDeprecationNotice();
|
||||
const cursorConfig = getCursorConfig();
|
||||
const models = await getAvailableModels(cursorConfig.port);
|
||||
const defaultModel = getDefaultModel();
|
||||
@@ -211,6 +226,7 @@ async function handleModels(): Promise<number> {
|
||||
* Handle start subcommand.
|
||||
*/
|
||||
async function handleStart(): Promise<number> {
|
||||
printLegacyCursorDeprecationNotice();
|
||||
const cursorConfig = getCursorConfig();
|
||||
|
||||
if (!cursorConfig.enabled) {
|
||||
@@ -248,6 +264,7 @@ async function handleStart(): Promise<number> {
|
||||
* Handle stop subcommand.
|
||||
*/
|
||||
async function handleStop(): Promise<number> {
|
||||
printLegacyCursorDeprecationNotice();
|
||||
console.log(info('Stopping cursor daemon...'));
|
||||
|
||||
const result = await stopDaemon();
|
||||
@@ -265,6 +282,7 @@ async function handleStop(): Promise<number> {
|
||||
* Handle enable subcommand.
|
||||
*/
|
||||
async function handleEnable(): Promise<number> {
|
||||
printLegacyCursorDeprecationNotice();
|
||||
mutateUnifiedConfig((config) => {
|
||||
if (!config.cursor) {
|
||||
config.cursor = { ...DEFAULT_CURSOR_CONFIG };
|
||||
@@ -276,6 +294,7 @@ async function handleEnable(): Promise<number> {
|
||||
console.log(ok('Cursor integration enabled'));
|
||||
console.log('');
|
||||
console.log('Next steps:');
|
||||
console.log(' 0. Preferred auth: ccs cursor --auth');
|
||||
console.log(' 1. Authenticate: ccs cursor auth');
|
||||
console.log(' 2. Start daemon: ccs cursor start');
|
||||
console.log(' 3. Check status: ccs cursor status');
|
||||
@@ -287,6 +306,7 @@ async function handleEnable(): Promise<number> {
|
||||
* Handle disable subcommand.
|
||||
*/
|
||||
async function handleDisable(): Promise<number> {
|
||||
printLegacyCursorDeprecationNotice();
|
||||
mutateUnifiedConfig((config) => {
|
||||
if (config.cursor) {
|
||||
config.cursor.enabled = false;
|
||||
|
||||
Reference in new issue
Block a user