@@ -83,6 +83,10 @@ const {
8383const {
8484 createBuiltinClaudeProxyRuntimeController
8585} = require ( './cli/claude-proxy' ) ;
86+ const {
87+ createOpenaiBridgeHttpHandler,
88+ upsertOpenaiBridgeProvider
89+ } = require ( './cli/openai-bridge' ) ;
8690const {
8791 createOpenclawConfigController
8892} = require ( './cli/openclaw-config' ) ;
@@ -160,6 +164,7 @@ const CURRENT_MODELS_FILE = path.join(CONFIG_DIR, 'provider-current-models.json'
160164const INIT_MARK_FILE = path . join ( CONFIG_DIR , 'codexmate-init.json' ) ;
161165const BUILTIN_PROXY_SETTINGS_FILE = path . join ( CONFIG_DIR , 'codexmate-proxy.json' ) ;
162166const BUILTIN_CLAUDE_PROXY_SETTINGS_FILE = path . join ( CONFIG_DIR , 'codexmate-claude-proxy.json' ) ;
167+ const OPENAI_BRIDGE_SETTINGS_FILE = path . join ( CONFIG_DIR , 'codexmate-openai-bridge.json' ) ;
163168const CODEX_SESSIONS_DIR = path . join ( CONFIG_DIR , 'sessions' ) ;
164169const SESSION_TRASH_DIR = path . join ( CONFIG_DIR , 'codexmate-session-trash' ) ;
165170const SESSION_TRASH_FILES_DIR = path . join ( SESSION_TRASH_DIR , 'files' ) ;
@@ -261,6 +266,14 @@ const CLI_INSTALL_TARGETS = Object.freeze([
261266const HTTP_KEEP_ALIVE_AGENT = new http . Agent ( { keepAlive : true } ) ;
262267const HTTPS_KEEP_ALIVE_AGENT = new https . Agent ( { keepAlive : true } ) ;
263268
269+ const openaiBridgeHandler = createOpenaiBridgeHttpHandler ( {
270+ settingsFile : OPENAI_BRIDGE_SETTINGS_FILE ,
271+ expectedToken : 'codexmate' ,
272+ maxBodySize : MAX_API_BODY_SIZE ,
273+ httpAgent : HTTP_KEEP_ALIVE_AGENT ,
274+ httpsAgent : HTTPS_KEEP_ALIVE_AGENT
275+ } ) ;
276+
264277function resolveWebPort ( ) {
265278 const raw = process . env . CODEXMATE_PORT ;
266279 if ( ! raw ) return DEFAULT_WEB_PORT ;
@@ -1824,6 +1837,7 @@ function addProviderToConfig(params = {}) {
18241837 const name = typeof params . name === 'string' ? params . name . trim ( ) : '' ;
18251838 const url = typeof params . url === 'string' ? params . url . trim ( ) : '' ;
18261839 const key = typeof params . key === 'string' ? params . key . trim ( ) : '' ;
1840+ const useTransform = ! ! params . useTransform ;
18271841 const allowManaged = ! ! params . allowManaged ;
18281842 const normalizedUrl = normalizeBaseUrl ( url ) ;
18291843
@@ -1876,15 +1890,35 @@ function addProviderToConfig(params = {}) {
18761890
18771891 const lineEnding = content . includes ( '\r\n' ) ? '\r\n' : '\n' ;
18781892 const safeName = escapeTomlBasicString ( name ) ;
1879- const safeUrl = escapeTomlBasicString ( normalizedUrl ) ;
1880- const safeKey = escapeTomlBasicString ( key ) ;
1893+ let baseUrlForConfig = normalizedUrl ;
1894+ let authKeyForConfig = key ;
1895+ const extraLines = [ ] ;
1896+
1897+ if ( useTransform ) {
1898+ const saveRes = upsertOpenaiBridgeProvider ( OPENAI_BRIDGE_SETTINGS_FILE , name , normalizedUrl , key ) ;
1899+ if ( saveRes && saveRes . error ) {
1900+ return { error : String ( saveRes . error ) } ;
1901+ }
1902+ const port = resolveWebPort ( ) ;
1903+ // 通过 URL 构造避免出现重复 /(例如 /bridge/openai//v1)
1904+ baseUrlForConfig = new URL (
1905+ `/bridge/openai/${ encodeURIComponent ( name ) } /v1` ,
1906+ `http://${ DEFAULT_WEB_OPEN_HOST } :${ port } `
1907+ ) . toString ( ) . replace ( / \/ + $ / g, '' ) ;
1908+ authKeyForConfig = 'codexmate' ;
1909+ extraLines . push ( `codexmate_bridge = "openai"` ) ;
1910+ }
1911+
1912+ const safeUrl = escapeTomlBasicString ( baseUrlForConfig ) ;
1913+ const safeKey = escapeTomlBasicString ( authKeyForConfig ) ;
18811914 const block = [
18821915 buildModelProviderTableHeader ( name ) ,
18831916 `name = "${ safeName } "` ,
18841917 `base_url = "${ safeUrl } "` ,
18851918 `wire_api = "responses"` ,
18861919 `requires_openai_auth = false` ,
18871920 `preferred_auth_method = "${ safeKey } "` ,
1921+ ...extraLines ,
18881922 `request_max_retries = 4` ,
18891923 `stream_max_retries = 10` ,
18901924 `stream_idle_timeout_ms = 300000`
@@ -8163,6 +8197,9 @@ function createWebServer({ htmlPath, assetsDir, webDir, host, port, openBrowser
81638197
81648198 const server = http . createServer ( ( req , res ) => {
81658199 const requestPath = ( req . url || '/' ) . split ( '?' ) [ 0 ] ;
8200+ if ( typeof openaiBridgeHandler === 'function' && openaiBridgeHandler ( req , res ) ) {
8201+ return ;
8202+ }
81668203 if ( requestPath === '/api/import-skills-zip' ) {
81678204 void handleImportSkillsZipUpload ( req , res ) ;
81688205 return ;
0 commit comments