mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-05 08:10:14 +00:00
fix(codex): address @daniel-lxs review — i18n settings, auth.json size guard, remove previous_response_id, avoid as-any reasoning mutation
This commit is contained in:
parent
297956a170
commit
ccaed3debf
4 changed files with 59 additions and 34 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import type { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { promises as fs } from "node:fs"
|
||||
import os from "node:os"
|
||||
import path from "node:path"
|
||||
|
||||
import type { ApiHandlerCreateMessageMetadata } from "../index"
|
||||
import { BaseProvider } from "./base-provider"
|
||||
|
|
@ -64,7 +65,6 @@ export class OpenAiNativeCodexHandler extends BaseProvider {
|
|||
protected options: ApiHandlerOptions
|
||||
private chatgptAccessToken!: string
|
||||
private chatgptAccountId?: string
|
||||
private lastResponseId: string | undefined
|
||||
private lastServiceTier: ServiceTier | undefined
|
||||
|
||||
// Inline-loaded provider prompt (via esbuild text loader for .md files)
|
||||
|
|
@ -134,18 +134,50 @@ export class OpenAiNativeCodexHandler extends BaseProvider {
|
|||
const expandHome = (p: string) => p.replace(/^~(?=\/|\\|$)/, os.homedir())
|
||||
const pathToUse = configured && configured.trim() ? configured.trim() : defaultPath
|
||||
const explicitPath = expandHome(pathToUse)
|
||||
const resolvedPath = path.resolve(explicitPath)
|
||||
|
||||
// Guard file size before reading to prevent loading unexpectedly large files
|
||||
const MAX_OAUTH_SIZE = 1_000_000 // 1 MB
|
||||
try {
|
||||
const stat = await fs.stat(resolvedPath)
|
||||
if (stat.size > MAX_OAUTH_SIZE) {
|
||||
throw new Error(
|
||||
t("common:errors.openaiNativeCodex.oauthFileTooLarge", {
|
||||
path: resolvedPath,
|
||||
size: stat.size,
|
||||
max: MAX_OAUTH_SIZE,
|
||||
}),
|
||||
)
|
||||
}
|
||||
} catch (e: any) {
|
||||
// Surface read failure with localized error (e.g., file missing or inaccessible)
|
||||
const base = t("common:errors.openaiNativeCodex.oauthReadFailed", {
|
||||
path: resolvedPath,
|
||||
error: e?.message || String(e),
|
||||
})
|
||||
throw new Error(base)
|
||||
}
|
||||
|
||||
let raw: string
|
||||
try {
|
||||
raw = await fs.readFile(explicitPath, "utf8")
|
||||
raw = await fs.readFile(resolvedPath, "utf8")
|
||||
} catch (e: any) {
|
||||
const base = t("common:errors.openaiNativeCodex.oauthReadFailed", {
|
||||
path: explicitPath,
|
||||
path: resolvedPath,
|
||||
error: e?.message || String(e),
|
||||
})
|
||||
const tip =
|
||||
" Tip: Authenticate with the Codex CLI to generate auth.json (defaults to ~/.codex/auth.json), then retry."
|
||||
throw new Error(base + tip)
|
||||
throw new Error(base)
|
||||
}
|
||||
|
||||
// Post-read size check using byte length
|
||||
if (Buffer.byteLength(raw, "utf8") > MAX_OAUTH_SIZE) {
|
||||
throw new Error(
|
||||
t("common:errors.openaiNativeCodex.oauthFileTooLarge", {
|
||||
path: resolvedPath,
|
||||
size: Buffer.byteLength(raw, "utf8"),
|
||||
max: MAX_OAUTH_SIZE,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
let j: AuthJson
|
||||
|
|
@ -153,12 +185,10 @@ export class OpenAiNativeCodexHandler extends BaseProvider {
|
|||
j = JSON.parse(raw) as AuthJson
|
||||
} catch (e: any) {
|
||||
const base = t("common:errors.openaiNativeCodex.oauthParseFailed", {
|
||||
path: explicitPath,
|
||||
path: resolvedPath,
|
||||
error: e?.message || String(e),
|
||||
})
|
||||
const tip =
|
||||
" Tip: Ensure the file is valid JSON or re-authenticate via the Codex CLI to regenerate auth.json."
|
||||
throw new Error(base + tip)
|
||||
throw new Error(base)
|
||||
}
|
||||
|
||||
const tokens: AuthTokens = j?.tokens ?? {}
|
||||
|
|
@ -210,21 +240,10 @@ export class OpenAiNativeCodexHandler extends BaseProvider {
|
|||
settings: this.options,
|
||||
})
|
||||
|
||||
const effort =
|
||||
(this.options.reasoningEffort as ReasoningEffortWithMinimal | undefined) ??
|
||||
(info.reasoningEffort as ReasoningEffortWithMinimal | undefined)
|
||||
if (effort) {
|
||||
;(params.reasoning as any) = { reasoning_effort: effort }
|
||||
}
|
||||
|
||||
// Reasoning effort is computed by getModelParams based on model + settings
|
||||
return { id: id as string, info, ...params, verbosity: params.verbosity }
|
||||
}
|
||||
|
||||
// Expose last response id for conversation continuity consumers (e.g., Task.persistGpt5Metadata)
|
||||
getLastResponseId(): string | undefined {
|
||||
return this.lastResponseId
|
||||
}
|
||||
|
||||
override async *createMessage(
|
||||
systemPrompt: string,
|
||||
messages: Anthropic.Messages.MessageParam[],
|
||||
|
|
@ -434,10 +453,7 @@ export class OpenAiNativeCodexHandler extends BaseProvider {
|
|||
}
|
||||
try {
|
||||
const parsed = JSON.parse(data)
|
||||
// Persist ids/tier when available (parity with openai-native)
|
||||
if (parsed.response?.id) {
|
||||
this.lastResponseId = parsed.response.id
|
||||
}
|
||||
// Persist tier when available (parity with openai-native)
|
||||
if (parsed.response?.service_tier) {
|
||||
this.lastServiceTier = parsed.response.service_tier as ServiceTier
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@
|
|||
"openaiNativeCodex": {
|
||||
"oauthReadFailed": "Failed to load ChatGPT OAuth credentials at {{path}}: {{error}}. Tip: authenticate with the Codex CLI (e.g., \"codex login\") to create auth.json.",
|
||||
"oauthParseFailed": "Failed to parse ChatGPT OAuth credentials JSON at {{path}}: {{error}}. Tip: ensure the file is valid JSON or re-authenticate with \"codex login\" to regenerate it.",
|
||||
"oauthFileTooLarge": "OAuth credentials file at {{path}} is too large ({{size}} bytes). Maximum allowed is {{max}} bytes.",
|
||||
"missingAccessToken": "ChatGPT OAuth credentials are missing tokens.access_token.",
|
||||
"httpError": "Codex HTTP {{status}} (req: {{requestId}}) model={{modelId}}: {{message}}",
|
||||
"noResponseBody": "ChatGPT Responses error: No response body",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react"
|
||||
import { VSCodeTextField, VSCodeLink } from "@vscode/webview-ui-toolkit/react"
|
||||
import { type ProviderSettings } from "@roo-code/types"
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
|
||||
interface OpenAiNativeCodexProps {
|
||||
apiConfiguration: ProviderSettings
|
||||
|
|
@ -8,6 +9,7 @@ interface OpenAiNativeCodexProps {
|
|||
}
|
||||
|
||||
export const OpenAiNativeCodex: React.FC<OpenAiNativeCodexProps> = ({ apiConfiguration, setApiConfigurationField }) => {
|
||||
const { t } = useAppTranslation()
|
||||
const defaultPath = "~/.codex/auth.json"
|
||||
|
||||
const handleInputChange = (e: Event | React.FormEvent<HTMLElement>) => {
|
||||
|
|
@ -24,28 +26,27 @@ export const OpenAiNativeCodex: React.FC<OpenAiNativeCodexProps> = ({ apiConfigu
|
|||
type="text"
|
||||
onInput={handleInputChange}
|
||||
placeholder={defaultPath}>
|
||||
OAuth Credentials Path
|
||||
<label className="block font-medium mb-1">
|
||||
{t("settings:providers.openAiNativeCodex.oauthPathLabel")}
|
||||
</label>
|
||||
</VSCodeTextField>
|
||||
|
||||
<p className="text-xs mt-1 text-vscode-descriptionForeground">
|
||||
Path to your ChatGPT Codex auth.json credentials. Defaults to ~/.codex/auth.json if left empty
|
||||
(Windows: C:\\Users\\USERNAME\\.codex\\auth.json).
|
||||
{t("settings:providers.openAiNativeCodex.oauthPathDescription", { defaultPath })}
|
||||
</p>
|
||||
|
||||
<div className="text-xs text-vscode-descriptionForeground mt-3">
|
||||
ChatGPT Codex uses your ChatGPT web credentials via the official Codex CLI. Authenticate with the
|
||||
Codex CLI so that auth.json is created. If you use a custom location, set the full file path here.
|
||||
{t("settings:providers.openAiNativeCodex.oauthCliDescription")}
|
||||
</div>
|
||||
|
||||
<div className="text-xs text-vscode-descriptionForeground mt-2">
|
||||
After authentication, Roo will read the access token from auth.json and connect to ChatGPT Responses
|
||||
(Codex).
|
||||
{t("settings:providers.openAiNativeCodex.oauthConnectDescription")}
|
||||
</div>
|
||||
|
||||
<VSCodeLink
|
||||
href="https://chatgpt.com"
|
||||
className="text-vscode-textLink-foreground mt-2 inline-block text-xs">
|
||||
Learn more about ChatGPT
|
||||
{t("settings:providers.openAiNativeCodex.learnMoreLinkText")}
|
||||
</VSCodeLink>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -449,6 +449,13 @@
|
|||
"authenticatedMessage": "Securely authenticated through your Roo Code Cloud account.",
|
||||
"connectButton": "Connect to Roo Code Cloud"
|
||||
},
|
||||
"openAiNativeCodex": {
|
||||
"oauthPathLabel": "OAuth Credentials Path",
|
||||
"oauthPathDescription": "Path to your ChatGPT Codex auth.json credentials. Defaults to {{defaultPath}} if left empty (Windows: C:\\\\Users\\\\USERNAME\\\\.codex\\\\auth.json).",
|
||||
"oauthCliDescription": "ChatGPT Codex uses your ChatGPT web credentials via the official Codex CLI. Authenticate with the Codex CLI so that auth.json is created. If you use a custom location, set the full file path here.",
|
||||
"oauthConnectDescription": "After authentication, Roo will read the access token from auth.json and connect to ChatGPT Responses (Codex).",
|
||||
"learnMoreLinkText": "Learn more about ChatGPT"
|
||||
},
|
||||
"openRouter": {
|
||||
"providerRouting": {
|
||||
"title": "OpenRouter Provider Routing",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue