fix(ai): avoid codex user-agent race
The Codex provider previously loaded node:os asynchronously during module evaluation. A fresh process that imports the provider and immediately starts an SSE request can build headers before that promise callback runs, so the first request reports User-Agent: pi (browser) in Node/Bun.
Reproduced against parent fd6659dd with a stubbed-fetch harness: 50/50 immediate first requests reported pi (browser) in both Node and Bun. The same harness on this fix reports the OS-specific user agent 50/50 in both runtimes.
Use process.getBuiltinModule("node:os") behind the existing Node/Bun runtime guard so OS metadata is available synchronously while still avoiding top-level runtime Node builtin imports that break browser/Vite builds.
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed OpenAI Codex user-agent construction to synchronously load Node OS metadata, avoiding a startup race that could report `pi (browser)` in Node/Bun.
|
||||
|
||||
## [0.80.3] - 2026-06-30
|
||||
|
||||
### Added
|
||||
|
||||
@@ -6,20 +6,20 @@ import type {
|
||||
ResponseStreamEvent,
|
||||
} from "openai/resources/responses/responses.js";
|
||||
|
||||
// NEVER convert to top-level runtime imports - breaks browser/Vite builds
|
||||
let _os: typeof NodeOs | null = null;
|
||||
type ProcessWithOsBuiltinModule = typeof process & {
|
||||
getBuiltinModule?: (id: "node:os") => typeof NodeOs;
|
||||
};
|
||||
|
||||
type DynamicImport = (specifier: string) => Promise<unknown>;
|
||||
|
||||
const dynamicImport: DynamicImport = (specifier) => import(specifier);
|
||||
const NODE_OS_SPECIFIER = "node:" + "os";
|
||||
|
||||
if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) {
|
||||
dynamicImport(NODE_OS_SPECIFIER).then((m) => {
|
||||
_os = m as typeof NodeOs;
|
||||
});
|
||||
function loadNodeOs(): typeof NodeOs | null {
|
||||
if (typeof process === "undefined" || !(process.versions?.node || process.versions?.bun)) {
|
||||
return null;
|
||||
}
|
||||
return (process as ProcessWithOsBuiltinModule).getBuiltinModule?.("node:os") ?? null;
|
||||
}
|
||||
|
||||
// NEVER convert to top-level runtime imports - breaks browser/Vite builds
|
||||
const _os: typeof NodeOs | null = loadNodeOs();
|
||||
|
||||
import { clampThinkingLevel } from "../models.ts";
|
||||
import { registerSessionResourceCleanup } from "../session-resources.ts";
|
||||
import type {
|
||||
|
||||
Reference in New Issue
Block a user