Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/desktop/src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,14 +332,14 @@ declare global {
refreshTokens(): Promise<SubscriptionActionResult>;
logout(): Promise<SubscriptionActionResult>;
};
codexSubscription: {
openAiCodex: {
isExperimentalEnabled(): Promise<boolean>;
getAuthUrl(): Promise<AuthorizationUrlPayload | SubscriptionActionResult>;
openAuthUrl(authRequestId: string): Promise<SubscriptionActionResult>;
completeAuthorization(authRequestId: string): Promise<SubscriptionActionResult>;
cancelAuthorization(authRequestId?: string): Promise<{ ok: true }>;
getAccountState(): Promise<{
provider: 'codex-subscription';
provider: 'openai-codex';
runtimeState:
| 'not_logged_in'
| 'authorizing'
Expand Down
16 changes: 8 additions & 8 deletions apps/desktop/src/main/__tests__/chat-readiness.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,38 +152,38 @@ describe('chat readiness guard', () => {

test('allows Codex OAuth once its subscription send path is wired', async () => {
const ready = await requireReadyConnection(
'codex-subscription',
'openai-codex',
deps({
connection: connection({
slug: 'codex-subscription',
slug: 'openai-codex',
name: 'Codex Subscription',
providerType: 'codex-subscription',
providerType: 'openai-codex',
defaultModel: 'gpt-5.5',
}),
apiKey: 'codex-oauth-secret',
}),
);
assert.equal(ready.connection.slug, 'codex-subscription');
assert.equal(ready.connection.slug, 'openai-codex');
assert.equal(ready.apiKey, 'codex-oauth-secret');
assert.equal(ready.model, 'gpt-5.5');
});

test('normalizes stale Codex OAuth session model away from unsupported ChatGPT-account model', async () => {
const ready = await requireReadyConnection(
'codex-subscription',
'openai-codex',
deps({
connection: connection({
slug: 'codex-subscription',
slug: 'openai-codex',
name: 'Codex Subscription',
providerType: 'codex-subscription',
providerType: 'openai-codex',
defaultModel: 'gpt-5.5',
models: [{ id: 'gpt-5.5' }, { id: 'gpt-5.4' }],
}),
apiKey: 'codex-oauth-secret',
}),
'gpt-5-codex',
);
assert.equal(ready.connection.slug, 'codex-subscription');
assert.equal(ready.connection.slug, 'openai-codex');
assert.equal(ready.model, 'gpt-5.5');
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ describe('cloaked request module isolation (xuan G-X4)', () => {

it('main delegates Codex OAuth request construction to runtime', async () => {
const src = await readMainProcessCombinedSource();
assert.match(src, /providerType === 'codex-subscription'[\s\S]*buildRuntimeSubscriptionModelFetch\(\{[\s\S]*connection[\s\S]*sessionId[\s\S]*modelId/);
assert.doesNotMatch(src, /function buildCodexSubscriptionFetch/, 'desktop must not duplicate the Codex fetch adapter');
assert.match(src, /providerType === 'openai-codex'[\s\S]*buildRuntimeSubscriptionModelFetch\(\{[\s\S]*connection[\s\S]*sessionId[\s\S]*modelId/);
assert.doesNotMatch(src, /function buildOpenAiCodexFetch/, 'desktop must not duplicate the Codex fetch adapter');
assert.doesNotMatch(src, /codexInstructionsFromBody/, 'Codex instruction mapping belongs in runtime');
assert.doesNotMatch(src, /OpenAI-Beta/, 'Codex subscription headers belong in runtime');
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ const SERVICE_SOURCE = resolve(
'oauth',
'claude-subscription-service.ts',
);
const CLAUDE_HELPERS_SOURCE = resolve(
REPO_ROOT,
'apps',
'desktop',
'src',
'main',
'oauth',
'claude-subscription-helpers.ts',
);
const SETTINGS_SOURCE = resolve(
REPO_ROOT,
'apps',
Expand All @@ -44,17 +53,23 @@ const SETTINGS_SOURCE = resolve(
const CORE_TYPES_SOURCE = resolve(REPO_ROOT, 'packages', 'core', 'src', 'oauth-subscription.ts');

describe('experimental kill-switch (kenji 1da909d5 + 45b31e16)', () => {
it('service exports isSubscriptionExperimentalEnabled tied to the env flag', async () => {
const src = await readFile(SERVICE_SOURCE, 'utf8');
it('exports isSubscriptionExperimentalEnabled tied to the env flag', async () => {
const helpersSrc = await readFile(CLAUDE_HELPERS_SOURCE, 'utf8');
assert.match(
src,
helpersSrc,
/export function isSubscriptionExperimentalEnabled\(\)/,
'service must export isSubscriptionExperimentalEnabled() for main + tests to consume',
'helpers must declare the gate function',
);
assert.match(
src,
helpersSrc,
/MAKA_CLAUDE_SUBSCRIPTION_EXPERIMENTAL/,
'service must reference the MAKA_CLAUDE_SUBSCRIPTION_EXPERIMENTAL env var',
'helpers must reference the MAKA_CLAUDE_SUBSCRIPTION_EXPERIMENTAL env var',
);
const serviceSrc = await readFile(SERVICE_SOURCE, 'utf8');
assert.match(
serviceSrc,
/isSubscriptionExperimentalEnabled.*from.*claude-subscription-helpers/,
'service must re-export the gate from helpers (single source of truth)',
);
});

Expand Down Expand Up @@ -256,7 +271,7 @@ describe('experimental kill-switch (kenji 1da909d5 + 45b31e16)', () => {

it('ProvidersPanel keeps OAuth login out of CATALOG_PROVIDER_TYPES and surfaces it as account connections', async () => {
const src = await readProviderSettingsCombinedSource();
for (const provider of ['claude-subscription', 'codex-subscription', 'gemini-cli']) {
for (const provider of ['claude-subscription', 'openai-codex', 'gemini-cli']) {
assert.equal(
CATALOG_PROVIDER_TYPES.includes(provider as (typeof CATALOG_PROVIDER_TYPES)[number]),
false,
Expand Down Expand Up @@ -327,7 +342,7 @@ describe('Claude OAuth model connection bridge', () => {
assert.ok(syncMatch, 'syncOAuthModelConnections helper must exist');
assert.match(
syncMatch[0],
/Promise\.allSettled\(\[[\s\S]*syncClaudeSubscriptionConnection\(\),[\s\S]*syncCodexSubscriptionConnection\(\),[\s\S]*\]\)/,
/Promise\.allSettled\(\[[\s\S]*syncClaudeSubscriptionConnection\(\),[\s\S]*syncOpenAiCodexConnection\(\),[\s\S]*\]\)/,
'one OAuth provider state failure must not reject the whole model connection list read',
);
assert.doesNotMatch(
Expand Down Expand Up @@ -366,8 +381,8 @@ describe('Claude OAuth model connection bridge', () => {
);
assert.match(
fnBody,
/providerType === 'codex-subscription'[\s\S]*codexSubscription\.hasStoredCredential\(\)/,
'hasConnectionSecret must route codex-subscription through the read-only hasStoredCredential(), not getAccessTokenInternal()',
/providerType === 'openai-codex'[\s\S]*openAiCodex\.hasStoredCredential\(\)/,
'hasConnectionSecret must route openai-codex through the read-only hasStoredCredential(), not getAccessTokenInternal()',
);
assert.doesNotMatch(
fnBody,
Expand Down Expand Up @@ -409,40 +424,40 @@ describe('Claude OAuth model connection bridge', () => {
const src = await readMainProcessCombinedSource();
assert.match(
src,
/async function syncCodexSubscriptionConnection\(\)/,
/async function syncOpenAiCodexConnection\(\)/,
'main.ts must turn Codex OAuth account state into a model connection',
);
assert.match(
src,
/slug:\s*CODEX_SUBSCRIPTION_CONNECTION_SLUG[\s\S]*providerType:\s*'codex-subscription'[\s\S]*enabled:\s*true[\s\S]*lastTestStatus:\s*'verified'/,
'sync helper must upsert an enabled codex-subscription connection after login',
/slug:\s*CODEX_SUBSCRIPTION_CONNECTION_SLUG[\s\S]*providerType:\s*'openai-codex'[\s\S]*enabled:\s*true[\s\S]*lastTestStatus:\s*'verified'/,
'sync helper must upsert an enabled openai-codex connection after login',
);
assert.match(
src,
/normalizeCodexSubscriptionModels\(existing\?\.models, fallbackModels\)/,
/normalizeOpenAiCodexModels\(existing\.models, fallbackModels\)/,
'Codex OAuth sync must migrate stale unsupported model lists',
);
assert.match(
src,
/normalizeCodexSubscriptionDefaultModel\([\s\S]*existing\?\.defaultModel[\s\S]*defaults\.fallbackModels\[0\]/,
/normalizeOpenAiCodexDefaultModel\([\s\S]*existing\?\.defaultModel[\s\S]*defaults\.fallbackModels\[0\]/,
'Codex OAuth sync must migrate stale unsupported default models',
);
assert.match(
src,
/CODEX_SUBSCRIPTION_UNSUPPORTED_CHATGPT_MODELS\.has\(existingDefaultModel\)/,
'Codex OAuth migration must explicitly reject ChatGPT-account-unsupported model ids',
);
const completeIdx = src.indexOf("codex-subscription:complete-authorization");
const completeIdx = src.indexOf("openai-codex:complete-authorization");
assert.notEqual(completeIdx, -1, 'codex complete-authorization handler must exist');
const completeRegion = src.slice(completeIdx, completeIdx + 1200);
assert.match(
completeRegion,
/if\s*\(\s*result\.ok\s*\)\s*\{[\s\S]*await (?:deps\.)?syncCodexSubscriptionConnection\(\);[\s\S]*(?:deps\.)?emitConnectionListChanged\(\);/,
/if\s*\(\s*result\.ok\s*\)\s*\{[\s\S]*await (?:deps\.)?syncOpenAiCodexConnection\(\);[\s\S]*(?:deps\.)?emitConnectionListChanged\(\);/,
'successful Codex OAuth completion must sync the connection and notify renderer',
);
assert.match(
src,
/providerType === 'codex-subscription'[\s\S]*codexSubscription\.getAccessTokenInternal\(\)/,
/providerType === 'openai-codex'[\s\S]*openAiCodex\.getAccessTokenInternal\(\)/,
'resolveConnectionSecret must let the Codex OAuth service apply its normal refresh policy before handing the access token to the send path',
);
});
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe('connection credential IPC hardening contract', () => {
/(^|[^\w])\.\.(?!\.)|includes\('\\.\\.'\)|includes\("\.\."\)|traversal|path traversal/i,
'slug validator must explicitly reject traversal-looking ".." slugs even though dots are otherwise allowed for compatibility',
);
for (const validSlug of ['claude-subscription', 'codex-subscription', 'zai-coding-plan', 'env-openai']) {
for (const validSlug of ['claude-subscription', 'openai-codex', 'zai-coding-plan', 'env-openai']) {
assert.doesNotMatch(validSlug, /[\u0000-\u001F\u007F/:\\]/, `${validSlug} should stay representative-valid`);
assert.ok(validSlug.length <= 64, `${validSlug} should stay under the IPC slug cap`);
}
Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/main/__tests__/context-budget-policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,14 @@ describe('desktop activeToolResultPrune policy', () => {

test('uses provider-specific metadata for Codex subscription models', () => {
const policy = buildDefaultContextBudgetPolicy({
providerType: 'codex-subscription',
providerType: 'openai-codex',
defaultModel: 'gpt-5.5',
models: [{ id: 'gpt-5.5' }],
} as unknown as LlmConnection, {
name: 'desktop-default-history-budget',
modelId: 'gpt-5.5',
});
assert.equal(policy?.maxHistoryEstimatedTokens, 400_000 - 16_384);
assert.equal(policy?.maxHistoryEstimatedTokens, 272_000 - 16_384);
});

test('uses metadata for known DeepSeek models but keeps unknown DeepSeek models unbounded', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ describe('GitHubCopilotSubscriptionService', () => {
);
const syncBody = source.slice(
source.indexOf('async function syncGitHubCopilotConnection'),
source.indexOf('async function syncCodexSubscriptionConnection'),
source.indexOf('async function syncOpenAiCodexConnection'),
);
const failureBody = syncBody.slice(syncBody.indexOf('} catch {'), syncBody.indexOf('const enabledIds'));
assert.match(syncBody, /const failDiscovery = \(\) => \{[\s\S]*if \(!existing\) return null;[\s\S]*enabled: false,[\s\S]*lastTestStatus: 'error'/);
Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/main/__tests__/model-catalog-choices.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ describe('model catalog picker helpers', () => {
const choices = buildCatalogChatModelChoices([
connection({
slug: 'codex-account',
providerType: 'codex-subscription',
providerType: 'openai-codex',
models: [{ id: 'gpt-5-codex' }, { id: 'gpt-5.5' }],
modelSource: 'fetched',
}),
Expand Down Expand Up @@ -177,7 +177,7 @@ describe('model catalog picker helpers', () => {
connection({
slug: 'codex-account',
name: 'person@example.com',
providerType: 'codex-subscription',
providerType: 'openai-codex',
models: [{ id: 'gpt-5.5' }],
modelSource: 'fetched',
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ describe('Model OAuth catalog contract (PR-MODEL-OAUTH-ALL-0 + PR-CLAUDE-CARD-MO
assert.match(src, /智谱 · OpenAI 兼容/);
assert.match(
src,
/case 'codex-subscription':\s*return \{ name: 'OpenAI OAuth', description: 'ChatGPT \/ Codex 账号登录;登录后自动成为可用模型连接。' \}/,
/case 'openai-codex':\s*return \{ name: 'OpenAI OAuth', description: 'ChatGPT \/ Codex 账号登录;登录后自动成为可用模型连接。' \}/,
'OpenAI OAuth account path should not be presented as a Codex subscription in provider settings',
);
assert.doesNotMatch(
Expand Down Expand Up @@ -1011,7 +1011,7 @@ describe('Model OAuth catalog contract (PR-MODEL-OAUTH-ALL-0 + PR-CLAUDE-CARD-MO
assert.ok(fnMatch, 'pickSubscriptionBridge helper must exist');
const body = fnMatch[0];
assert.doesNotMatch(body, /case 'claude'/, 'Claude has a paste-code modal and must not use the loopback generic bridge');
assert.match(body, /case 'codex'[\s\S]*?window\.maka\.codexSubscription/);
assert.match(body, /case 'codex'[\s\S]*?window\.maka\.openAiCodex/);
assert.match(body, /case 'cursor'[\s\S]*?window\.maka\.cursorSubscription/);
assert.match(body, /case 'antigravity'[\s\S]*?window\.maka\.antigravitySubscription/);
});
Expand Down Expand Up @@ -1248,7 +1248,7 @@ describe('Model OAuth catalog contract (PR-MODEL-OAUTH-ALL-0 + PR-CLAUDE-CARD-MO
// Loopback services (Codex, Antigravity) get a bridge; Claude's paste flow
// and plain API-key providers fall through to null so the notice renders
// prose, never a dead button.
assert.match(mapping, /case 'codex-subscription':[\s\S]*window\.maka\.codexSubscription as unknown as OAuthLoginFlowBridge/);
assert.match(mapping, /case 'openai-codex':[\s\S]*window\.maka\.openAiCodex as unknown as OAuthLoginFlowBridge/);
assert.match(mapping, /case 'gemini-cli':[\s\S]*window\.maka\.antigravitySubscription as unknown as OAuthLoginFlowBridge/);
assert.match(mapping, /default:\s*return null;/);
assert.doesNotMatch(mapping, /case 'claude-subscription'/, 'Claude uses a paste-code flow and must not be routed through the one-button loopback hook');
Expand Down Expand Up @@ -1282,7 +1282,7 @@ describe('Model OAuth catalog contract (PR-MODEL-OAUTH-ALL-0 + PR-CLAUDE-CARD-MO

it('preload exposes every subscription namespace alongside claudeSubscription', async () => {
const src = await readFile(PRELOAD_SOURCE, 'utf8');
assert.match(src, /codexSubscription:\s*\{/, 'preload must expose window.maka.codexSubscription');
assert.match(src, /openAiCodex:\s*\{/, 'preload must expose window.maka.openAiCodex');
assert.match(src, /cursorSubscription:\s*\{/, 'preload must expose window.maka.cursorSubscription');
assert.match(src, /githubCopilotSubscription:\s*\{/, 'preload must expose window.maka.githubCopilotSubscription');
assert.match(
Expand All @@ -1291,10 +1291,10 @@ describe('Model OAuth catalog contract (PR-MODEL-OAUTH-ALL-0 + PR-CLAUDE-CARD-MO
'preload must expose window.maka.antigravitySubscription',
);
for (const channel of [
'codex-subscription:get-auth-url',
'codex-subscription:complete-authorization',
'codex-subscription:get-account-state',
'codex-subscription:logout',
'openai-codex:get-auth-url',
'openai-codex:complete-authorization',
'openai-codex:get-account-state',
'openai-codex:logout',
'cursor-subscription:get-auth-url',
'cursor-subscription:complete-authorization',
'cursor-subscription:get-account-state',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ const OAUTH_DIR = resolve(REPO_ROOT, 'apps', 'desktop', 'src', 'main', 'oauth');
const RUNTIME_BOTS_DIR = resolve(REPO_ROOT, 'packages', 'runtime', 'src', 'bots');

const SERVICES_WITH_LOOPBACK_SERVER = [
'codex-subscription-service.ts',
'openai-codex-service.ts',
'antigravity-subscription-service.ts',
];

const SERVICES_WITH_LOAD_TOKENS = [
'claude-subscription-service.ts',
'codex-subscription-service.ts',
'openai-codex-service.ts',
'cursor-subscription-service.ts',
'antigravity-subscription-service.ts',
];

const WIRED_OAUTH_SEND_SERVICES = [
'claude-subscription-service.ts',
'codex-subscription-service.ts',
'openai-codex-service.ts',
];

describe('OAuth callback server: drains sockets + timeout (B-SWEEP-1, B-SWEEP-2)', () => {
Expand Down
Loading
Loading