mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-06-01 06:00:19 +00:00
fix: address Codex OAuth review feedback
- Save CODEX_OAUTH_TOKEN marker config after OAuth to track install state - Check marker config instead of OPENAI_API_KEY for install detection - Avoid mutating input dict in CodexOAuthManager.save_token() - Add CODEX_OAUTH_TOKEN to Codex env_vars whitelist in server config - Prioritize named integration descriptions over env_vars fallback
This commit is contained in:
parent
2601f197ed
commit
009e8e27ef
5 changed files with 92 additions and 22 deletions
|
|
@ -250,6 +250,7 @@ class CodexOAuthManager:
|
|||
True on success.
|
||||
"""
|
||||
path = cls._token_path()
|
||||
token_data = token_data.copy()
|
||||
try:
|
||||
if "saved_at" not in token_data:
|
||||
token_data["saved_at"] = int(time.time())
|
||||
|
|
|
|||
|
|
@ -168,12 +168,11 @@ class ConfigInfo:
|
|||
"env_vars": ["OPENAI_API_KEY"],
|
||||
"toolkit": "rag_toolkit",
|
||||
},
|
||||
# Codex OAuth is a model-provider integration (obtains an
|
||||
# OpenAI API key). After OAuth the key is stored via the
|
||||
# Provider API, not here. The entry is kept only for
|
||||
# install-state detection in the integration list UI.
|
||||
# TODO: Codex is a model-provider integration, not a toolkit.
|
||||
# Its OAuth entry point should move to the Model/Provider settings
|
||||
# page. Keeping it here temporarily for install-state detection.
|
||||
ConfigGroup.CODEX.value: {
|
||||
"env_vars": [],
|
||||
"env_vars": ["CODEX_OAUTH_TOKEN"],
|
||||
"toolkit": None,
|
||||
"type": "provider",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -268,11 +268,45 @@ const ToolSelect = forwardRef<
|
|||
}
|
||||
};
|
||||
|
||||
const saveCodexMarkerConfig = async () => {
|
||||
try {
|
||||
const existingConfigs = await proxyFetchGet('/api/configs');
|
||||
const existing = Array.isArray(existingConfigs)
|
||||
? existingConfigs.find(
|
||||
(c: any) =>
|
||||
c.config_group?.toLowerCase() === 'codex' &&
|
||||
c.config_name === 'CODEX_OAUTH_TOKEN'
|
||||
)
|
||||
: null;
|
||||
|
||||
const configPayload = {
|
||||
config_group: 'Codex',
|
||||
config_name: 'CODEX_OAUTH_TOKEN',
|
||||
config_value: 'exists',
|
||||
};
|
||||
|
||||
if (existing) {
|
||||
await proxyFetchPut(
|
||||
`/api/configs/${existing.id}`,
|
||||
configPayload
|
||||
);
|
||||
} else {
|
||||
await proxyFetchPost('/api/configs', configPayload);
|
||||
}
|
||||
} catch (configError) {
|
||||
console.warn(
|
||||
'Failed to persist Codex marker config',
|
||||
configError
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
onInstall = async () => {
|
||||
try {
|
||||
const response = await fetchPost('/install/tool/codex');
|
||||
if (response.success) {
|
||||
await saveCodexAsProvider(response);
|
||||
await saveCodexMarkerConfig();
|
||||
const codexItem = {
|
||||
id: 0,
|
||||
key: key,
|
||||
|
|
@ -295,6 +329,7 @@ const ToolSelect = forwardRef<
|
|||
);
|
||||
if (retryResponse.success) {
|
||||
await saveCodexAsProvider(retryResponse);
|
||||
await saveCodexMarkerConfig();
|
||||
fetchIntegrationsData();
|
||||
const codexItem = {
|
||||
id: 0,
|
||||
|
|
@ -342,16 +377,16 @@ const ToolSelect = forwardRef<
|
|||
env_vars: value.env_vars,
|
||||
toolkit: value.toolkit,
|
||||
desc:
|
||||
value.env_vars && value.env_vars.length > 0
|
||||
? `${t('layout.environmental-variables-required')} ${value.env_vars.join(
|
||||
', '
|
||||
)}`
|
||||
key.toLowerCase() === 'codex'
|
||||
? t('layout.codex-integration')
|
||||
: key.toLowerCase() === 'notion'
|
||||
? t('layout.notion-workspace-integration')
|
||||
: key.toLowerCase() === 'google calendar'
|
||||
? t('layout.google-calendar-integration')
|
||||
: key.toLowerCase() === 'codex'
|
||||
? t('layout.codex-integration')
|
||||
: value.env_vars && value.env_vars.length > 0
|
||||
? `${t('layout.environmental-variables-required')} ${value.env_vars.join(
|
||||
', '
|
||||
)}`
|
||||
: '',
|
||||
onInstall,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -98,15 +98,15 @@ export function useIntegrationManagement(items: IntegrationItem[]) {
|
|||
);
|
||||
map[item.key] = hasAccessToken;
|
||||
} else if (item.key === 'Codex') {
|
||||
// Codex: check if OPENAI_API_KEY config is present
|
||||
const hasApiKey = configs.some(
|
||||
// Codex: check if CODEX_OAUTH_TOKEN marker config is present
|
||||
const hasOAuthToken = configs.some(
|
||||
(c: any) =>
|
||||
c.config_group?.toLowerCase() === 'codex' &&
|
||||
c.config_name === 'OPENAI_API_KEY' &&
|
||||
c.config_name === 'CODEX_OAUTH_TOKEN' &&
|
||||
c.config_value &&
|
||||
String(c.config_value).length > 0
|
||||
);
|
||||
map[item.key] = hasApiKey;
|
||||
map[item.key] = hasOAuthToken;
|
||||
} else {
|
||||
// For other integrations, use config_group presence
|
||||
const hasConfig = configs.some(
|
||||
|
|
|
|||
|
|
@ -347,11 +347,11 @@ export default function SettingMCP() {
|
|||
);
|
||||
}
|
||||
};
|
||||
} else if (key.toLowerCase() === 'codex') {
|
||||
// Codex OAuth obtains an OpenAI API key for model access.
|
||||
// After a successful flow we save it as an OpenAI *Provider*
|
||||
// (not a toolkit config) so it integrates with the model
|
||||
// configuration system.
|
||||
} else if (key.toLowerCase() === 'codex') {
|
||||
const saveCodexAsProvider = async (installResponse: any) => {
|
||||
if (!installResponse?.access_token) return;
|
||||
try {
|
||||
|
|
@ -391,12 +391,46 @@ export default function SettingMCP() {
|
|||
}
|
||||
};
|
||||
|
||||
const saveCodexMarkerConfig = async () => {
|
||||
try {
|
||||
const existingConfigs = await proxyFetchGet('/api/configs');
|
||||
const existing = Array.isArray(existingConfigs)
|
||||
? existingConfigs.find(
|
||||
(c: any) =>
|
||||
c.config_group?.toLowerCase() === 'codex' &&
|
||||
c.config_name === 'CODEX_OAUTH_TOKEN'
|
||||
)
|
||||
: null;
|
||||
|
||||
const configPayload = {
|
||||
config_group: 'Codex',
|
||||
config_name: 'CODEX_OAUTH_TOKEN',
|
||||
config_value: 'exists',
|
||||
};
|
||||
|
||||
if (existing) {
|
||||
await proxyFetchPut(
|
||||
`/api/configs/${existing.id}`,
|
||||
configPayload
|
||||
);
|
||||
} else {
|
||||
await proxyFetchPost('/api/configs', configPayload);
|
||||
}
|
||||
} catch (configError) {
|
||||
console.warn(
|
||||
'Failed to persist Codex marker config',
|
||||
configError
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
onInstall = async () => {
|
||||
try {
|
||||
const response = await fetchPost('/install/tool/codex');
|
||||
if (response.success) {
|
||||
toast.success(t('setting.codex-installed-successfully'));
|
||||
await saveCodexAsProvider(response);
|
||||
await saveCodexMarkerConfig();
|
||||
fetchList();
|
||||
setRefreshKey((prev) => prev + 1);
|
||||
} else if (response.status === 'authorizing') {
|
||||
|
|
@ -412,6 +446,7 @@ export default function SettingMCP() {
|
|||
const finalize = await fetchPost('/install/tool/codex');
|
||||
if (finalize?.success) {
|
||||
await saveCodexAsProvider(finalize);
|
||||
await saveCodexMarkerConfig();
|
||||
toast.success(
|
||||
t('setting.codex-installed-successfully')
|
||||
);
|
||||
|
|
@ -462,16 +497,16 @@ export default function SettingMCP() {
|
|||
name: key,
|
||||
env_vars: value.env_vars,
|
||||
desc:
|
||||
value.env_vars && value.env_vars.length > 0
|
||||
? `${t(
|
||||
'setting.environmental-variables-required'
|
||||
)}: ${value.env_vars.join(', ')}`
|
||||
key.toLowerCase() === 'codex'
|
||||
? t('setting.codex-integration')
|
||||
: key.toLowerCase() === 'notion'
|
||||
? t('setting.notion-workspace-integration')
|
||||
: key.toLowerCase() === 'google calendar'
|
||||
? t('setting.google-calendar-integration')
|
||||
: key.toLowerCase() === 'codex'
|
||||
? t('setting.codex-integration')
|
||||
: value.env_vars && value.env_vars.length > 0
|
||||
? `${t(
|
||||
'setting.environmental-variables-required'
|
||||
)}: ${value.env_vars.join(', ')}`
|
||||
: '',
|
||||
onInstall,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue