Merge origin/main into codex/provider-profile-recommendations
Preserve provider recommendation workflows while integrating Codex profile support, safer launch isolation, and updated docs/scripts from upstream main.
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import test from 'node:test'
|
||||
|
||||
import {
|
||||
buildCodexProfileEnv,
|
||||
buildLaunchEnv,
|
||||
buildOllamaProfileEnv,
|
||||
buildOpenAIProfileEnv,
|
||||
selectAutoProfile,
|
||||
type ProfileFile,
|
||||
} from './providerProfile.ts'
|
||||
@@ -16,6 +21,8 @@ function profile(profile: ProfileFile['profile'], env: ProfileFile['env']): Prof
|
||||
}
|
||||
}
|
||||
|
||||
const missingCodexAuthPath = join(tmpdir(), 'openclaude-missing-codex-auth.json')
|
||||
|
||||
test('matching persisted ollama env is reused for ollama launch', async () => {
|
||||
const env = await buildLaunchEnv({
|
||||
profile: 'ollama',
|
||||
@@ -45,6 +52,9 @@ test('ollama launch ignores mismatched persisted openai env and shell model fall
|
||||
processEnv: {
|
||||
OPENAI_BASE_URL: 'https://api.deepseek.com/v1',
|
||||
OPENAI_MODEL: 'gpt-4o-mini',
|
||||
OPENAI_API_KEY: 'sk-live',
|
||||
CODEX_API_KEY: 'codex-live',
|
||||
CHATGPT_ACCOUNT_ID: 'acct_live',
|
||||
},
|
||||
getOllamaChatBaseUrl: () => 'http://localhost:11434/v1',
|
||||
resolveOllamaDefaultModel: async () => 'qwen2.5-coder:7b',
|
||||
@@ -52,6 +62,9 @@ test('ollama launch ignores mismatched persisted openai env and shell model fall
|
||||
|
||||
assert.equal(env.OPENAI_BASE_URL, 'http://localhost:11434/v1')
|
||||
assert.equal(env.OPENAI_MODEL, 'qwen2.5-coder:7b')
|
||||
assert.equal(env.OPENAI_API_KEY, undefined)
|
||||
assert.equal(env.CODEX_API_KEY, undefined)
|
||||
assert.equal(env.CHATGPT_ACCOUNT_ID, undefined)
|
||||
})
|
||||
|
||||
test('openai launch ignores mismatched persisted ollama env', async () => {
|
||||
@@ -64,6 +77,8 @@ test('openai launch ignores mismatched persisted ollama env', async () => {
|
||||
goal: 'latency',
|
||||
processEnv: {
|
||||
OPENAI_API_KEY: 'sk-live',
|
||||
CODEX_API_KEY: 'codex-live',
|
||||
CHATGPT_ACCOUNT_ID: 'acct_live',
|
||||
},
|
||||
getOllamaChatBaseUrl: () => 'http://localhost:11434/v1',
|
||||
resolveOllamaDefaultModel: async () => 'llama3.1:8b',
|
||||
@@ -72,6 +87,159 @@ test('openai launch ignores mismatched persisted ollama env', async () => {
|
||||
assert.equal(env.OPENAI_BASE_URL, 'https://api.openai.com/v1')
|
||||
assert.equal(env.OPENAI_MODEL, 'gpt-4o-mini')
|
||||
assert.equal(env.OPENAI_API_KEY, 'sk-live')
|
||||
assert.equal(env.CODEX_API_KEY, undefined)
|
||||
assert.equal(env.CHATGPT_ACCOUNT_ID, undefined)
|
||||
})
|
||||
|
||||
test('openai launch ignores codex shell transport hints', async () => {
|
||||
const env = await buildLaunchEnv({
|
||||
profile: 'openai',
|
||||
persisted: null,
|
||||
goal: 'balanced',
|
||||
processEnv: {
|
||||
OPENAI_API_KEY: 'sk-live',
|
||||
OPENAI_BASE_URL: 'https://chatgpt.com/backend-api/codex',
|
||||
OPENAI_MODEL: 'codexplan',
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(env.OPENAI_BASE_URL, 'https://api.openai.com/v1')
|
||||
assert.equal(env.OPENAI_MODEL, 'gpt-4o')
|
||||
assert.equal(env.OPENAI_API_KEY, 'sk-live')
|
||||
})
|
||||
|
||||
test('openai launch ignores codex persisted transport hints', async () => {
|
||||
const env = await buildLaunchEnv({
|
||||
profile: 'openai',
|
||||
persisted: profile('openai', {
|
||||
OPENAI_BASE_URL: 'https://chatgpt.com/backend-api/codex',
|
||||
OPENAI_MODEL: 'codexplan',
|
||||
OPENAI_API_KEY: 'sk-persisted',
|
||||
}),
|
||||
goal: 'balanced',
|
||||
processEnv: {
|
||||
OPENAI_API_KEY: 'sk-live',
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(env.OPENAI_BASE_URL, 'https://api.openai.com/v1')
|
||||
assert.equal(env.OPENAI_MODEL, 'gpt-4o')
|
||||
assert.equal(env.OPENAI_API_KEY, 'sk-live')
|
||||
})
|
||||
|
||||
test('matching persisted codex env is reused for codex launch', async () => {
|
||||
const env = await buildLaunchEnv({
|
||||
profile: 'codex',
|
||||
persisted: profile('codex', {
|
||||
OPENAI_BASE_URL: 'https://chatgpt.com/backend-api/codex',
|
||||
OPENAI_MODEL: 'codexspark',
|
||||
CODEX_API_KEY: 'codex-persisted',
|
||||
CHATGPT_ACCOUNT_ID: 'acct_persisted',
|
||||
}),
|
||||
goal: 'balanced',
|
||||
processEnv: {
|
||||
CODEX_AUTH_JSON_PATH: missingCodexAuthPath,
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(env.OPENAI_BASE_URL, 'https://chatgpt.com/backend-api/codex')
|
||||
assert.equal(env.OPENAI_MODEL, 'codexspark')
|
||||
assert.equal(env.CODEX_API_KEY, 'codex-persisted')
|
||||
assert.equal(env.CHATGPT_ACCOUNT_ID, 'acct_persisted')
|
||||
})
|
||||
|
||||
test('codex launch normalizes poisoned persisted base urls', async () => {
|
||||
const env = await buildLaunchEnv({
|
||||
profile: 'codex',
|
||||
persisted: profile('codex', {
|
||||
OPENAI_BASE_URL: 'https://api.openai.com/v1',
|
||||
OPENAI_MODEL: 'codexspark',
|
||||
CHATGPT_ACCOUNT_ID: 'acct_persisted',
|
||||
}),
|
||||
goal: 'balanced',
|
||||
processEnv: {
|
||||
CODEX_AUTH_JSON_PATH: missingCodexAuthPath,
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(env.OPENAI_BASE_URL, 'https://chatgpt.com/backend-api/codex')
|
||||
assert.equal(env.OPENAI_MODEL, 'codexspark')
|
||||
})
|
||||
|
||||
test('codex launch ignores mismatched persisted openai env', async () => {
|
||||
const env = await buildLaunchEnv({
|
||||
profile: 'codex',
|
||||
persisted: profile('openai', {
|
||||
OPENAI_BASE_URL: 'https://api.openai.com/v1',
|
||||
OPENAI_MODEL: 'gpt-4o',
|
||||
OPENAI_API_KEY: 'sk-persisted',
|
||||
}),
|
||||
goal: 'balanced',
|
||||
processEnv: {
|
||||
OPENAI_BASE_URL: 'https://api.openai.com/v1',
|
||||
OPENAI_MODEL: 'gpt-4o-mini',
|
||||
OPENAI_API_KEY: 'sk-live',
|
||||
CODEX_API_KEY: 'codex-live',
|
||||
CHATGPT_ACCOUNT_ID: 'acct_live',
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(env.OPENAI_BASE_URL, 'https://chatgpt.com/backend-api/codex')
|
||||
assert.equal(env.OPENAI_MODEL, 'codexplan')
|
||||
assert.equal(env.OPENAI_API_KEY, undefined)
|
||||
assert.equal(env.CODEX_API_KEY, 'codex-live')
|
||||
assert.equal(env.CHATGPT_ACCOUNT_ID, 'acct_live')
|
||||
})
|
||||
|
||||
test('codex launch ignores placeholder codex env keys', async () => {
|
||||
const env = await buildLaunchEnv({
|
||||
profile: 'codex',
|
||||
persisted: profile('codex', {
|
||||
OPENAI_BASE_URL: 'https://chatgpt.com/backend-api/codex',
|
||||
OPENAI_MODEL: 'codexspark',
|
||||
CODEX_API_KEY: 'codex-persisted',
|
||||
CHATGPT_ACCOUNT_ID: 'acct_persisted',
|
||||
}),
|
||||
goal: 'balanced',
|
||||
processEnv: {
|
||||
CODEX_API_KEY: 'SUA_CHAVE',
|
||||
CODEX_AUTH_JSON_PATH: missingCodexAuthPath,
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(env.CODEX_API_KEY, 'codex-persisted')
|
||||
assert.equal(env.CHATGPT_ACCOUNT_ID, 'acct_persisted')
|
||||
})
|
||||
|
||||
test('codex launch prefers auth account id over stale persisted value', async () => {
|
||||
const codexHome = mkdtempSync(join(tmpdir(), 'openclaude-codex-'))
|
||||
try {
|
||||
writeFileSync(
|
||||
join(codexHome, 'auth.json'),
|
||||
JSON.stringify({
|
||||
access_token: 'codex-live',
|
||||
account_id: 'acct_auth',
|
||||
}),
|
||||
'utf8',
|
||||
)
|
||||
|
||||
const env = await buildLaunchEnv({
|
||||
profile: 'codex',
|
||||
persisted: profile('codex', {
|
||||
OPENAI_BASE_URL: 'https://chatgpt.com/backend-api/codex',
|
||||
OPENAI_MODEL: 'codexspark',
|
||||
CHATGPT_ACCOUNT_ID: 'acct_persisted',
|
||||
}),
|
||||
goal: 'balanced',
|
||||
processEnv: {
|
||||
CODEX_HOME: codexHome,
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(env.CHATGPT_ACCOUNT_ID, 'acct_auth')
|
||||
} finally {
|
||||
rmSync(codexHome, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
test('ollama profiles never persist openai api keys', () => {
|
||||
@@ -86,6 +254,53 @@ test('ollama profiles never persist openai api keys', () => {
|
||||
assert.equal('OPENAI_API_KEY' in env, false)
|
||||
})
|
||||
|
||||
test('codex profiles accept explicit codex credentials', () => {
|
||||
const env = buildCodexProfileEnv({
|
||||
model: 'codexspark',
|
||||
apiKey: 'codex-live',
|
||||
processEnv: {
|
||||
CHATGPT_ACCOUNT_ID: 'acct_123',
|
||||
},
|
||||
})
|
||||
|
||||
assert.deepEqual(env, {
|
||||
OPENAI_BASE_URL: 'https://chatgpt.com/backend-api/codex',
|
||||
OPENAI_MODEL: 'codexspark',
|
||||
CODEX_API_KEY: 'codex-live',
|
||||
CHATGPT_ACCOUNT_ID: 'acct_123',
|
||||
})
|
||||
})
|
||||
|
||||
test('codex profiles require a chatgpt account id', () => {
|
||||
const env = buildCodexProfileEnv({
|
||||
model: 'codexspark',
|
||||
apiKey: 'codex-live',
|
||||
processEnv: {
|
||||
CODEX_AUTH_JSON_PATH: missingCodexAuthPath,
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(env, null)
|
||||
})
|
||||
|
||||
test('openai profiles ignore codex shell transport hints', () => {
|
||||
const env = buildOpenAIProfileEnv({
|
||||
goal: 'balanced',
|
||||
apiKey: 'sk-live',
|
||||
processEnv: {
|
||||
OPENAI_BASE_URL: 'https://chatgpt.com/backend-api/codex',
|
||||
OPENAI_MODEL: 'codexplan',
|
||||
OPENAI_API_KEY: 'sk-live',
|
||||
},
|
||||
})
|
||||
|
||||
assert.deepEqual(env, {
|
||||
OPENAI_BASE_URL: 'https://api.openai.com/v1',
|
||||
OPENAI_MODEL: 'gpt-4o',
|
||||
OPENAI_API_KEY: 'sk-live',
|
||||
})
|
||||
})
|
||||
|
||||
test('auto profile falls back to openai when no viable ollama model exists', () => {
|
||||
assert.equal(selectAutoProfile(null), 'openai')
|
||||
assert.equal(selectAutoProfile('qwen2.5-coder:7b'), 'ollama')
|
||||
|
||||
Reference in New Issue
Block a user