Skip to content

Conversation

@notlikejuice
Copy link
Owner

Summary

  • handle login via GitHub device flow
  • save Copilot token in auth.json
  • create GithubCopilotClient for Copilot API requests
  • initialize Copilot client in agent loop
  • expose githubcopilot provider configuration
  • ensure aborted rawExec kills entire process group and return PID

Testing

  • pnpm --filter @openai/codex run format
  • pnpm --filter @openai/codex run lint
  • pnpm --filter @openai/codex run typecheck
  • pnpm --filter @openai/codex run test

https://chatgpt.com/codex/tasks/task_e_684f272bac248326a07facb43efee33f

Copilot AI review requested due to automatic review settings June 15, 2025 20:29
@notlikejuice notlikejuice merged commit 8cbc7f1 into main Jun 15, 2025
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces full GitHub Copilot provider support by adding a dedicated client, handling device-flow login, persisting tokens, and updating process execution logic to track and assert PIDs.

  • Added pid to ExecResult and updated rawExec and related tests to validate process group termination.
  • Implemented GithubCopilotClient with token fetching, integrated it in CLI, and exposed new githubcopilot provider configuration.
  • Updated CLI to initiate device-flow login for Copilot, persist credentials in auth.json, and dynamically handle API keys.

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
codex-cli/tests/raw-exec-process-group.test.ts Updated test to assert root PID and extended ensureProcessGone.
codex-cli/src/utils/providers.ts Exposed githubcopilot provider with updated name, baseURL, envKey.
codex-cli/src/utils/openai-client.ts Added GithubCopilotClient for Copilot API token management.
codex-cli/src/utils/get-api-key.tsx Introduced getGithubCopilotApiKey device-flow login function.
codex-cli/src/utils/agent/sandbox/raw-exec.ts Added PID tracking and faster kill escalation in rawExec.
codex-cli/src/cli.tsx Integrated Copilot login flow, env var persistence, dynamic API key handling.
Comments suppressed due to low confidence (2)

codex-cli/src/utils/providers.ts:56

  • [nitpick] Provider name property and envKey use inconsistent casing and separators; consider renaming to GitHubCopilot and GITHUB_COPILOT_API_KEY for consistency.
name: "GithubCopilot",

codex-cli/src/utils/openai-client.ts:65

  • Add unit tests covering GithubCopilotClient, including token fetching, header merging, and OAuth device flow methods.
export class GithubCopilotClient extends OpenAI {

Comment on lines +205 to +207
copy["User-Agent"] = "GithubCopilot/1.155.0";
copy["editor-version"] = "vscode/1.85.1";
copy["editor-plugin-version"] = "copilot/1.155.0";
Copy link

Copilot AI Jun 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Extract hard-coded version strings (User-Agent, editor-version, etc.) into constants or configuration to improve maintainability.

Suggested change
copy["User-Agent"] = "GithubCopilot/1.155.0";
copy["editor-version"] = "vscode/1.85.1";
copy["editor-plugin-version"] = "copilot/1.155.0";
copy["User-Agent"] = GITHUB_COPILOT_USER_AGENT;
copy["editor-version"] = EDITOR_VERSION;
copy["editor-plugin-version"] = EDITOR_PLUGIN_VERSION;

Copilot uses AI. Check for mistakes.
"GitHub OAuth login is not yet implemented for Codex. " +
"Please generate a token manually and set it as GITHUB_COPILOT_TOKEN." +
"\n"
export async function getGithubCopilotApiKey(): Promise<string> {
Copy link

Copilot AI Jun 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Provide a fallback for manual API key entry or prompt when device flow isn't available, as removing the previous manual entry option may limit usability.

Suggested change
export async function getGithubCopilotApiKey(): Promise<string> {
export async function getGithubCopilotApiKey(): Promise<string> {
const choice = await promptUserForChoice();
if (choice.type === "apikey") {
process.env["GITHUBCOPILOT_API_KEY"] = choice.key;
return choice.key;
}

Copilot uses AI. Check for mistakes.
}
// Ensure the API key is available as an environment variable for legacy code
process.env["OPENAI_API_KEY"] = apiKey;
process.env[`${provider.toUpperCase()}_API_KEY`] = apiKey;
Copy link

Copilot AI Jun 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dynamic assignment of process.env[${provider}_API_KEY] overrides the expected OPENAI_API_KEY for non-openai providers (e.g., Azure); consider special-casing openai/azure to maintain compatibility.

Suggested change
process.env[`${provider.toUpperCase()}_API_KEY`] = apiKey;
if (provider.toLowerCase() === "openai") {
process.env["OPENAI_API_KEY"] = apiKey;
} else if (provider.toLowerCase() === "azure") {
process.env["AZURE_API_KEY"] = apiKey;
} else {
process.env[`${provider.toUpperCase()}_API_KEY`] = apiKey;
}

Copilot uses AI. Check for mistakes.
Comment on lines +337 to 359
if (provider.toLowerCase() === "githubcopilot" && !apiKey) {
apiKey = await fetchGithubCopilotApiKey();
try {
const home = os.homedir();
const authDir = path.join(home, ".codex");
const authFile = path.join(authDir, "auth.json");
fs.writeFileSync(
authFile,
JSON.stringify(
{
GITHUBCOPILOT_API_KEY: apiKey,
},
null,
2,
),
"utf-8",
);
} catch {
/* ignore */
}
} else if (cli.flags.login) {
if (provider.toLowerCase() === "githubcopilot") {
apiKey = await fetchGithubCopilotApiKey();
Copy link

Copilot AI Jun 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The initial githubcopilot login block will always take precedence, making the subsequent cli.flags.login branch unreachable for Copilot; consider merging or removing redundant logic.

Suggested change
if (provider.toLowerCase() === "githubcopilot" && !apiKey) {
apiKey = await fetchGithubCopilotApiKey();
try {
const home = os.homedir();
const authDir = path.join(home, ".codex");
const authFile = path.join(authDir, "auth.json");
fs.writeFileSync(
authFile,
JSON.stringify(
{
GITHUBCOPILOT_API_KEY: apiKey,
},
null,
2,
),
"utf-8",
);
} catch {
/* ignore */
}
} else if (cli.flags.login) {
if (provider.toLowerCase() === "githubcopilot") {
apiKey = await fetchGithubCopilotApiKey();
if ((provider.toLowerCase() === "githubcopilot" && !apiKey) || cli.flags.login) {
if (provider.toLowerCase() === "githubcopilot") {
apiKey = await fetchGithubCopilotApiKey();
try {
const home = os.homedir();
const authDir = path.join(home, ".codex");
const authFile = path.join(authDir, "auth.json");
fs.writeFileSync(
authFile,
JSON.stringify(
{
GITHUBCOPILOT_API_KEY: apiKey,
},
null,
2,
),
"utf-8",
);
} catch {
/* ignore */
}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants