mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-20 00:14:58 +00:00
refactor(copilot): use local installation from package manager
- copilot-auth: use getCopilotApiBinPath() instead of npx - copilot-daemon: move PID file to ~/.ccs/copilot/daemon.pid - copilot-executor: auto-install copilot-api on first use - index: export package manager functions
This commit is contained in:
1 parent
ecdad1d6d0
commit
9a8eea82c5
4 files changed
+54
-28
No files matched your search
+15
-14
@@ -2,25 +2,22 @@
|
|||||||
* Copilot Auth Handler
|
* Copilot Auth Handler
|
||||||
*
|
*
|
||||||
* Handles GitHub OAuth authentication for copilot-api.
|
* Handles GitHub OAuth authentication for copilot-api.
|
||||||
|
* Uses local installation from ~/.ccs/copilot/ (managed by copilot-package-manager).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { spawn, spawnSync } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import { CopilotAuthStatus, CopilotDebugInfo } from './types';
|
import { CopilotAuthStatus, CopilotDebugInfo } from './types';
|
||||||
|
import {
|
||||||
|
isCopilotApiInstalled as checkInstalled,
|
||||||
|
getCopilotApiBinPath,
|
||||||
|
} from './copilot-package-manager';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if copilot-api is installed (available via npx).
|
* Check if copilot-api is installed locally.
|
||||||
|
* Uses copilot-package-manager to check ~/.ccs/copilot/node_modules/.bin/copilot-api
|
||||||
*/
|
*/
|
||||||
export function isCopilotApiInstalled(): boolean {
|
export function isCopilotApiInstalled(): boolean {
|
||||||
try {
|
return checkInstalled();
|
||||||
const result = spawnSync('npx', ['copilot-api', '--version'], {
|
|
||||||
stdio: 'pipe',
|
|
||||||
timeout: 10000,
|
|
||||||
shell: process.platform === 'win32',
|
|
||||||
});
|
|
||||||
return result.status === 0;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,9 +25,11 @@ export function isCopilotApiInstalled(): boolean {
|
|||||||
* Returns authentication status and version info.
|
* Returns authentication status and version info.
|
||||||
*/
|
*/
|
||||||
export async function getCopilotDebugInfo(): Promise<CopilotDebugInfo | null> {
|
export async function getCopilotDebugInfo(): Promise<CopilotDebugInfo | null> {
|
||||||
|
const binPath = getCopilotApiBinPath();
|
||||||
|
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
try {
|
try {
|
||||||
const proc = spawn('npx', ['copilot-api', 'debug', '--json'], {
|
const proc = spawn(binPath, ['debug', '--json'], {
|
||||||
stdio: ['ignore', 'pipe', 'pipe'],
|
stdio: ['ignore', 'pipe', 'pipe'],
|
||||||
shell: process.platform === 'win32',
|
shell: process.platform === 'win32',
|
||||||
timeout: 15000,
|
timeout: 15000,
|
||||||
@@ -100,12 +99,14 @@ export async function checkAuthStatus(): Promise<CopilotAuthStatus> {
|
|||||||
* @returns Promise that resolves when auth flow completes
|
* @returns Promise that resolves when auth flow completes
|
||||||
*/
|
*/
|
||||||
export function startAuthFlow(): Promise<{ success: boolean; error?: string }> {
|
export function startAuthFlow(): Promise<{ success: boolean; error?: string }> {
|
||||||
|
const binPath = getCopilotApiBinPath();
|
||||||
|
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
console.log('[i] Starting GitHub authentication for Copilot...');
|
console.log('[i] Starting GitHub authentication for Copilot...');
|
||||||
console.log('[i] A browser window will open for GitHub OAuth.');
|
console.log('[i] A browser window will open for GitHub OAuth.');
|
||||||
console.log('');
|
console.log('');
|
||||||
|
|
||||||
const proc = spawn('npx', ['copilot-api', 'auth'], {
|
const proc = spawn(binPath, ['auth'], {
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
shell: process.platform === 'win32',
|
shell: process.platform === 'win32',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,18 +2,18 @@
|
|||||||
* Copilot Daemon Manager
|
* Copilot Daemon Manager
|
||||||
*
|
*
|
||||||
* Manages the copilot-api daemon lifecycle (start/stop/status).
|
* Manages the copilot-api daemon lifecycle (start/stop/status).
|
||||||
* Only used when auto_start is enabled in config.
|
* Uses local installation from ~/.ccs/copilot/ (managed by copilot-package-manager).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { spawn, ChildProcess } from 'child_process';
|
import { spawn, ChildProcess } from 'child_process';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as os from 'os';
|
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
import { CopilotDaemonStatus } from './types';
|
import { CopilotDaemonStatus } from './types';
|
||||||
import { CopilotConfig } from '../config/unified-config-types';
|
import { CopilotConfig } from '../config/unified-config-types';
|
||||||
|
import { getCopilotDir, getCopilotApiBinPath } from './copilot-package-manager';
|
||||||
|
|
||||||
const PID_FILE = path.join(os.homedir(), '.ccs', 'copilot.pid');
|
const PID_FILE = path.join(getCopilotDir(), 'daemon.pid');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if copilot-api daemon is running on the specified port.
|
* Check if copilot-api daemon is running on the specified port.
|
||||||
@@ -118,7 +118,8 @@ export async function startDaemon(
|
|||||||
return { success: true, pid: getPidFromFile() ?? undefined };
|
return { success: true, pid: getPidFromFile() ?? undefined };
|
||||||
}
|
}
|
||||||
|
|
||||||
const args = ['copilot-api', 'start', '--port', config.port.toString()];
|
const binPath = getCopilotApiBinPath();
|
||||||
|
const args = ['start', '--port', config.port.toString()];
|
||||||
|
|
||||||
// Add account type
|
// Add account type
|
||||||
if (config.account_type !== 'individual') {
|
if (config.account_type !== 'individual') {
|
||||||
@@ -137,7 +138,7 @@ export async function startDaemon(
|
|||||||
let proc: ChildProcess;
|
let proc: ChildProcess;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
proc = spawn('npx', args, {
|
proc = spawn(binPath, args, {
|
||||||
stdio: ['ignore', 'pipe', 'pipe'],
|
stdio: ['ignore', 'pipe', 'pipe'],
|
||||||
detached: true,
|
detached: true,
|
||||||
shell: process.platform === 'win32',
|
shell: process.platform === 'win32',
|
||||||
|
|||||||
@@ -2,13 +2,14 @@
|
|||||||
* Copilot Executor
|
* Copilot Executor
|
||||||
*
|
*
|
||||||
* Main execution flow for running Claude Code with copilot-api proxy.
|
* Main execution flow for running Claude Code with copilot-api proxy.
|
||||||
* Similar to CLIProxy executor but for GitHub Copilot.
|
* Uses local installation from ~/.ccs/copilot/ (managed by copilot-package-manager).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import { CopilotConfig } from '../config/unified-config-types';
|
import { CopilotConfig } from '../config/unified-config-types';
|
||||||
import { checkAuthStatus, isCopilotApiInstalled } from './copilot-auth';
|
import { checkAuthStatus, isCopilotApiInstalled } from './copilot-auth';
|
||||||
import { isDaemonRunning, startDaemon } from './copilot-daemon';
|
import { isDaemonRunning, startDaemon } from './copilot-daemon';
|
||||||
|
import { ensureCopilotApi } from './copilot-package-manager';
|
||||||
import { CopilotStatus } from './types';
|
import { CopilotStatus } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,12 +66,24 @@ export async function executeCopilotProfile(
|
|||||||
config: CopilotConfig,
|
config: CopilotConfig,
|
||||||
claudeArgs: string[]
|
claudeArgs: string[]
|
||||||
): Promise<number> {
|
): Promise<number> {
|
||||||
// Check if copilot-api is installed
|
// Ensure copilot-api is installed (auto-install if missing, auto-update if outdated)
|
||||||
|
try {
|
||||||
|
await ensureCopilotApi();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[X] Failed to install copilot-api.');
|
||||||
|
console.error('');
|
||||||
|
console.error(`Error: ${(error as Error).message}`);
|
||||||
|
console.error('');
|
||||||
|
console.error('Try installing manually:');
|
||||||
|
console.error(' npm install -g copilot-api');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if copilot-api is installed (should be after ensureCopilotApi)
|
||||||
if (!isCopilotApiInstalled()) {
|
if (!isCopilotApiInstalled()) {
|
||||||
console.error('[X] copilot-api is not installed.');
|
console.error('[X] copilot-api is not installed.');
|
||||||
console.error('');
|
console.error('');
|
||||||
console.error('Install with: npm install -g copilot-api');
|
console.error('Install with: ccs copilot --install');
|
||||||
console.error('Or run via npx: npx copilot-api auth');
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-5
@@ -7,13 +7,24 @@
|
|||||||
// Types
|
// Types
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
|
||||||
// Auth
|
// Package Manager (self-managed installation)
|
||||||
export {
|
export {
|
||||||
|
getCopilotDir,
|
||||||
|
getCopilotApiBinPath,
|
||||||
isCopilotApiInstalled,
|
isCopilotApiInstalled,
|
||||||
checkAuthStatus,
|
getInstalledVersion,
|
||||||
startAuthFlow,
|
getPinnedVersion,
|
||||||
getCopilotDebugInfo,
|
savePinnedVersion,
|
||||||
} from './copilot-auth';
|
clearPinnedVersion,
|
||||||
|
checkForUpdates,
|
||||||
|
ensureCopilotApi,
|
||||||
|
installCopilotApiVersion,
|
||||||
|
uninstallCopilotApi,
|
||||||
|
getCopilotApiInfo,
|
||||||
|
} from './copilot-package-manager';
|
||||||
|
|
||||||
|
// Auth
|
||||||
|
export { checkAuthStatus, startAuthFlow, getCopilotDebugInfo } from './copilot-auth';
|
||||||
|
|
||||||
// Daemon
|
// Daemon
|
||||||
export { isDaemonRunning, getDaemonStatus, startDaemon, stopDaemon } from './copilot-daemon';
|
export { isDaemonRunning, getDaemonStatus, startDaemon, stopDaemon } from './copilot-daemon';
|
||||||
|
|||||||
Reference in new issue
Block a user