mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
fix(extensions): revert openai codex auth plugin (PR #18009)
This commit is contained in:
@@ -1,82 +0,0 @@
|
|||||||
# OpenAI Codex CLI Auth (OpenClaw plugin)
|
|
||||||
|
|
||||||
Use OpenAI models with your **ChatGPT Plus/Pro subscription** via the Codex CLI OAuth tokens.
|
|
||||||
|
|
||||||
This plugin reads authentication from the [OpenAI Codex CLI](https://github.com/openai/codex) and uses those OAuth credentials to access OpenAI models — no separate API key required.
|
|
||||||
|
|
||||||
## Enable
|
|
||||||
|
|
||||||
Bundled plugins are disabled by default. Enable this one:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
openclaw plugins enable openai-codex-auth
|
|
||||||
```
|
|
||||||
|
|
||||||
Restart the Gateway after enabling.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
1. **ChatGPT Plus or Pro subscription** — required for Codex CLI access
|
|
||||||
2. **Codex CLI installed and authenticated**:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install Codex CLI
|
|
||||||
npm install -g @openai/codex
|
|
||||||
|
|
||||||
# Authenticate (opens browser for OAuth)
|
|
||||||
codex login
|
|
||||||
```
|
|
||||||
|
|
||||||
This creates `~/.codex/auth.json` with your OAuth tokens.
|
|
||||||
|
|
||||||
## Authenticate with OpenClaw
|
|
||||||
|
|
||||||
After Codex CLI is authenticated:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
openclaw models auth login --provider openai-codex --set-default
|
|
||||||
```
|
|
||||||
|
|
||||||
## Available Models
|
|
||||||
|
|
||||||
The following models are available through Codex CLI authentication:
|
|
||||||
|
|
||||||
- `openai/gpt-4.1`, `openai/gpt-4.1-mini`, `openai/gpt-4.1-nano`
|
|
||||||
- `openai/gpt-4o`, `openai/gpt-4o-mini`
|
|
||||||
- `openai/o1`, `openai/o1-mini`, `openai/o1-pro`
|
|
||||||
- `openai/o3`, `openai/o3-mini`
|
|
||||||
- `openai/o4-mini`
|
|
||||||
|
|
||||||
Default model: `openai/o3`
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
1. The plugin reads `~/.codex/auth.json` created by `codex login`
|
|
||||||
2. OAuth tokens from your ChatGPT subscription are extracted
|
|
||||||
3. OpenClaw uses these tokens to authenticate with OpenAI's API
|
|
||||||
4. Tokens auto-refresh when needed (handled by OpenClaw's credential system)
|
|
||||||
|
|
||||||
## Why Use This?
|
|
||||||
|
|
||||||
- **No separate API key** — use your existing ChatGPT Plus/Pro subscription
|
|
||||||
- **No usage-based billing** — covered by your subscription
|
|
||||||
- **Access to latest models** — same models available in ChatGPT
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### "No Codex auth found"
|
|
||||||
|
|
||||||
Run `codex login` to authenticate the Codex CLI first.
|
|
||||||
|
|
||||||
### Tokens expired
|
|
||||||
|
|
||||||
Re-run `codex login` to refresh your tokens, then re-authenticate:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
codex login
|
|
||||||
openclaw models auth login --provider openai-codex --set-default
|
|
||||||
```
|
|
||||||
|
|
||||||
### Model not available
|
|
||||||
|
|
||||||
Some models may require specific subscription tiers (e.g., o1-pro requires ChatGPT Pro).
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
import * as fs from "node:fs";
|
|
||||||
import * as os from "node:os";
|
|
||||||
import * as path from "node:path";
|
|
||||||
import {
|
|
||||||
emptyPluginConfigSchema,
|
|
||||||
type OpenClawPluginApi,
|
|
||||||
type ProviderAuthContext,
|
|
||||||
type ProviderAuthResult,
|
|
||||||
} from "openclaw/plugin-sdk";
|
|
||||||
|
|
||||||
const PROVIDER_ID = "openai-codex-import";
|
|
||||||
const PROVIDER_LABEL = "OpenAI Codex CLI Import";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolve the Codex auth file path, respecting CODEX_HOME env var like core does.
|
|
||||||
* Called lazily to pick up env var changes.
|
|
||||||
*/
|
|
||||||
function getAuthFilePath(): string {
|
|
||||||
const codexHome = process.env.CODEX_HOME
|
|
||||||
? path.resolve(process.env.CODEX_HOME)
|
|
||||||
: path.join(os.homedir(), ".codex");
|
|
||||||
return path.join(codexHome, "auth.json");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OpenAI Codex models available via ChatGPT Plus/Pro subscription.
|
|
||||||
* Uses openai-codex/ prefix to match core provider namespace and avoid
|
|
||||||
* conflicts with the standard openai/ API key-based provider.
|
|
||||||
*/
|
|
||||||
const CODEX_MODELS = [
|
|
||||||
"openai-codex/gpt-5.3-codex",
|
|
||||||
"openai-codex/gpt-5.3-codex-spark",
|
|
||||||
"openai-codex/gpt-5.2-codex",
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
const DEFAULT_MODEL = "openai-codex/gpt-5.3-codex";
|
|
||||||
|
|
||||||
interface CodexAuthTokens {
|
|
||||||
access_token: string;
|
|
||||||
refresh_token?: string;
|
|
||||||
account_id?: string;
|
|
||||||
expires_at?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CodexAuthFile {
|
|
||||||
tokens?: CodexAuthTokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the Codex CLI auth.json file, respecting CODEX_HOME env var.
|
|
||||||
*/
|
|
||||||
function readCodexAuth(): CodexAuthFile | null {
|
|
||||||
try {
|
|
||||||
const authFile = getAuthFilePath();
|
|
||||||
if (!fs.existsSync(authFile)) return null;
|
|
||||||
const content = fs.readFileSync(authFile, "utf-8");
|
|
||||||
return JSON.parse(content) as CodexAuthFile;
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode JWT expiry timestamp from access token
|
|
||||||
*/
|
|
||||||
function decodeJwtExpiry(token: string): number | undefined {
|
|
||||||
try {
|
|
||||||
const payload = token.split(".")[1];
|
|
||||||
if (!payload) return undefined;
|
|
||||||
const decoded = JSON.parse(Buffer.from(payload, "base64").toString()) as { exp?: number };
|
|
||||||
return decoded.exp ? decoded.exp * 1000 : undefined;
|
|
||||||
} catch {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const openaiCodexPlugin = {
|
|
||||||
id: "openai-codex-auth",
|
|
||||||
name: "OpenAI Codex Auth",
|
|
||||||
description: "Use OpenAI models via Codex CLI authentication (ChatGPT Plus/Pro)",
|
|
||||||
configSchema: emptyPluginConfigSchema(),
|
|
||||||
|
|
||||||
register(api: OpenClawPluginApi) {
|
|
||||||
api.registerProvider({
|
|
||||||
id: PROVIDER_ID,
|
|
||||||
label: PROVIDER_LABEL,
|
|
||||||
docsPath: "/providers/models",
|
|
||||||
aliases: ["codex-import"],
|
|
||||||
|
|
||||||
auth: [
|
|
||||||
{
|
|
||||||
id: "codex-cli",
|
|
||||||
label: "Codex CLI Auth",
|
|
||||||
hint: "Import existing Codex CLI authentication (respects CODEX_HOME env var)",
|
|
||||||
kind: "custom",
|
|
||||||
|
|
||||||
run: async (ctx: ProviderAuthContext): Promise<ProviderAuthResult> => {
|
|
||||||
const spin = ctx.prompter.progress("Reading Codex CLI auth…");
|
|
||||||
|
|
||||||
try {
|
|
||||||
const auth = readCodexAuth();
|
|
||||||
|
|
||||||
if (!auth?.tokens?.access_token) {
|
|
||||||
spin.stop("No Codex auth found");
|
|
||||||
await ctx.prompter.note(
|
|
||||||
"Run 'codex login' first to authenticate with OpenAI.\n\n" +
|
|
||||||
"Install Codex CLI: npm install -g @openai/codex\n" +
|
|
||||||
"Then run: codex login",
|
|
||||||
"Setup required",
|
|
||||||
);
|
|
||||||
throw new Error("Codex CLI not authenticated. Run: codex login");
|
|
||||||
}
|
|
||||||
|
|
||||||
spin.stop("Codex auth loaded");
|
|
||||||
|
|
||||||
const profileId = `openai-codex-import:${auth.tokens.account_id ?? "default"}`;
|
|
||||||
const expires = auth.tokens.expires_at
|
|
||||||
? auth.tokens.expires_at * 1000
|
|
||||||
: decodeJwtExpiry(auth.tokens.access_token);
|
|
||||||
|
|
||||||
const modelsConfig: Record<string, object> = {};
|
|
||||||
for (const model of CODEX_MODELS) {
|
|
||||||
modelsConfig[model] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate refresh token - empty/missing refresh tokens cause silent failures
|
|
||||||
if (!auth.tokens.refresh_token) {
|
|
||||||
spin.stop("Invalid Codex auth");
|
|
||||||
await ctx.prompter.note(
|
|
||||||
"Your Codex CLI auth is missing a refresh token.\n\n" +
|
|
||||||
"Please re-authenticate: codex logout && codex login",
|
|
||||||
"Re-authentication required",
|
|
||||||
);
|
|
||||||
throw new Error(
|
|
||||||
"Codex CLI auth missing refresh token. Run: codex logout && codex login",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
profiles: [
|
|
||||||
{
|
|
||||||
profileId,
|
|
||||||
credential: {
|
|
||||||
type: "oauth",
|
|
||||||
provider: PROVIDER_ID,
|
|
||||||
access: auth.tokens.access_token,
|
|
||||||
refresh: auth.tokens.refresh_token,
|
|
||||||
expires: expires ?? Date.now() + 3600000,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
configPatch: {
|
|
||||||
agents: {
|
|
||||||
defaults: {
|
|
||||||
models: modelsConfig,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
defaultModel: DEFAULT_MODEL,
|
|
||||||
notes: [
|
|
||||||
`Using Codex CLI auth from ${getAuthFilePath()}`,
|
|
||||||
`Available models: ${CODEX_MODELS.join(", ")}`,
|
|
||||||
"Tokens auto-refresh when needed.",
|
|
||||||
],
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
spin.stop("Failed to load Codex auth");
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default openaiCodexPlugin;
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"id": "openai-codex-auth",
|
|
||||||
"providers": ["openai-codex"],
|
|
||||||
"configSchema": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@openclaw/openai-codex-auth",
|
|
||||||
"version": "2026.2.16",
|
|
||||||
"private": true,
|
|
||||||
"description": "OpenAI Codex CLI auth provider plugin - use ChatGPT Plus/Pro subscription for OpenAI models",
|
|
||||||
"type": "module",
|
|
||||||
"devDependencies": {
|
|
||||||
"openclaw": "workspace:*"
|
|
||||||
},
|
|
||||||
"openclaw": {
|
|
||||||
"extensions": [
|
|
||||||
"./index.ts"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@@ -469,12 +469,6 @@ importers:
|
|||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../..
|
version: link:../..
|
||||||
|
|
||||||
extensions/openai-codex-auth:
|
|
||||||
devDependencies:
|
|
||||||
openclaw:
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../..
|
|
||||||
|
|
||||||
extensions/signal:
|
extensions/signal:
|
||||||
devDependencies:
|
devDependencies:
|
||||||
openclaw:
|
openclaw:
|
||||||
|
|||||||
Reference in New Issue
Block a user