diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index a32cb7ef..5647eb74 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -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 diff --git a/packages/ai/src/api/openai-codex-responses.ts b/packages/ai/src/api/openai-codex-responses.ts index 62886e0c..67db7a93 100644 --- a/packages/ai/src/api/openai-codex-responses.ts +++ b/packages/ai/src/api/openai-codex-responses.ts @@ -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; - -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 {