From 22efdfa904375a32b1938ff44a8b00c439961648 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 4 Jun 2026 08:45:03 -0400 Subject: [PATCH] docs: document codex app-server runtime utilities --- extensions/codex/src/app-server/managed-binary.ts | 7 +++++++ extensions/codex/src/app-server/sandbox-guard.ts | 7 +++++++ .../codex/src/app-server/session-binding.ts | 15 +++++++++++++++ .../codex/src/app-server/startup-binding.ts | 6 ++++++ .../codex/src/app-server/transport-stdio.ts | 7 +++++++ .../codex/src/app-server/transport-websocket.ts | 5 +++++ extensions/codex/src/app-server/transport.ts | 7 +++++++ 7 files changed, 54 insertions(+) diff --git a/extensions/codex/src/app-server/managed-binary.ts b/extensions/codex/src/app-server/managed-binary.ts index 51bcb857a19a..ab2956d5e6c8 100644 --- a/extensions/codex/src/app-server/managed-binary.ts +++ b/extensions/codex/src/app-server/managed-binary.ts @@ -1,3 +1,7 @@ +/** + * Resolves the managed Codex app-server binary shipped with or installed beside + * the Codex plugin before stdio startup. + */ import { constants as fsConstants, readFileSync } from "node:fs"; import { access } from "node:fs/promises"; import { createRequire } from "node:module"; @@ -20,6 +24,7 @@ type ResolveManagedCodexAppServerOptions = { pathExists?: (filePath: string, platform: NodeJS.Platform) => Promise; }; +/** Rewrites managed stdio start options to point at an executable Codex binary path. */ export async function resolveManagedCodexAppServerStartOptions( startOptions: CodexAppServerStartOptions, options: ResolveManagedCodexAppServerOptions = {}, @@ -47,6 +52,7 @@ export async function resolveManagedCodexAppServerStartOptions( }; } +/** Returns the preferred and fallback managed Codex binary paths for a plugin root. */ export function resolveManagedCodexAppServerPaths(params: { platform?: NodeJS.Platform; pluginRoot?: string; @@ -170,6 +176,7 @@ function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null; } +/** Internal helpers exposed for managed-binary path-resolution tests. */ export const testing = { resolveDefaultCodexPluginRoot, }; diff --git a/extensions/codex/src/app-server/sandbox-guard.ts b/extensions/codex/src/app-server/sandbox-guard.ts index 449ec024e902..f3c32f9a8281 100644 --- a/extensions/codex/src/app-server/sandbox-guard.ts +++ b/extensions/codex/src/app-server/sandbox-guard.ts @@ -1,3 +1,7 @@ +/** + * Blocks direct Codex app-server requests that would bypass OpenClaw sandbox or + * node-exec routing guarantees. + */ import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts"; import { resolveSandboxRuntimeStatus } from "openclaw/plugin-sdk/sandbox"; import { @@ -65,6 +69,7 @@ const NODE_EXEC_BLOCKED_CONTROL_PLANE_METHODS = new Set([ "config/mcpServer/reload", ]); +/** Returns a block message when a direct app-server method would bypass OpenClaw execution policy. */ export function resolveCodexAppServerDirectSandboxBypassBlock(params: { method: string; requestParams?: unknown; @@ -117,6 +122,7 @@ export function resolveCodexAppServerDirectSandboxBypassBlock(params: { return sandboxBlock; } +/** Resolves the generic native-execution block for sandboxed or node-hosted sessions. */ export function resolveCodexNativeExecutionBlock(params: { config?: OpenClawConfig; sessionKey?: string; @@ -126,6 +132,7 @@ export function resolveCodexNativeExecutionBlock(params: { return resolveCodexNativeSandboxBlock(params) ?? resolveCodexNativeNodeExecBlock(params); } +/** Returns a block message when native Codex execution cannot honor active sandboxing. */ export function resolveCodexNativeSandboxBlock(params: { config?: OpenClawConfig; sessionKey?: string; diff --git a/extensions/codex/src/app-server/session-binding.ts b/extensions/codex/src/app-server/session-binding.ts index ff2753c6908c..e5dab60123d3 100644 --- a/extensions/codex/src/app-server/session-binding.ts +++ b/extensions/codex/src/app-server/session-binding.ts @@ -1,3 +1,7 @@ +/** + * Persists and normalizes the Codex app-server thread binding associated with + * an OpenClaw session file. + */ import fs from "node:fs/promises"; import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime"; import { @@ -21,6 +25,7 @@ const PUBLIC_OPENAI_MODEL_PROVIDER = "openai"; type ProviderAuthAliasLookupParams = Parameters[1]; type ProviderAuthAliasConfig = NonNullable["config"]; +/** Inputs needed to resolve whether a binding's auth profile is native Codex/OpenAI auth. */ export type CodexAppServerAuthProfileLookup = { authProfileId?: string; authProfileStore?: AuthProfileStore; @@ -28,6 +33,7 @@ export type CodexAppServerAuthProfileLookup = { config?: ProviderAuthAliasConfig; }; +/** Durable sidecar binding connecting an OpenClaw session file to a Codex thread. */ export type CodexAppServerThreadBinding = { schemaVersion: 1; threadId: string; @@ -53,6 +59,7 @@ export type CodexAppServerThreadBinding = { updatedAt: string; }; +/** Context-engine state persisted with a Codex app-server thread binding. */ export type CodexAppServerContextEngineBinding = { schemaVersion: 1; engineId: string; @@ -60,6 +67,7 @@ export type CodexAppServerContextEngineBinding = { projection?: CodexAppServerContextEngineProjectionBinding; }; +/** Context-engine projection metadata used to guard resumed native threads. */ export type CodexAppServerContextEngineProjectionBinding = { schemaVersion: 1; mode: "thread_bootstrap"; @@ -67,10 +75,12 @@ export type CodexAppServerContextEngineProjectionBinding = { fingerprint?: string; }; +/** Returns the JSON sidecar path for the Codex app-server binding beside a session file. */ export function resolveCodexAppServerBindingPath(sessionFile: string): string { return `${sessionFile}.codex-app-server.json`; } +/** Reads and normalizes a Codex app-server binding sidecar, returning undefined on stale data. */ export async function readCodexAppServerBinding( sessionFile: string, lookup: Omit = {}, @@ -148,6 +158,7 @@ export async function readCodexAppServerBinding( } } +/** Writes the Codex app-server binding sidecar with normalized provider/auth metadata. */ export async function writeCodexAppServerBinding( sessionFile: string, binding: Omit< @@ -293,6 +304,7 @@ function readPluginAppPolicyContext(value: unknown): PluginAppPolicyContext | un }; } +/** Removes the Codex app-server binding sidecar if present. */ export async function clearCodexAppServerBinding( sessionFile: string, _lookup: Omit = {}, @@ -306,6 +318,7 @@ export async function clearCodexAppServerBinding( } } +/** Clears a binding only when it still points at the expected Codex thread id. */ export async function clearCodexAppServerBindingForThread( sessionFile: string, threadId: string, @@ -331,6 +344,7 @@ function isNotFound(error: unknown): boolean { return Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT"); } +/** Returns true when an auth profile uses native Codex/OpenAI app-server auth. */ export function isCodexAppServerNativeAuthProfile( lookup: CodexAppServerAuthProfileLookup, ): boolean { @@ -356,6 +370,7 @@ export function isCodexAppServerNativeAuthProfile( } } +/** Hides redundant OpenAI provider attribution for native Codex auth bindings. */ export function normalizeCodexAppServerBindingModelProvider(params: { authProfileId?: string; modelProvider?: string; diff --git a/extensions/codex/src/app-server/startup-binding.ts b/extensions/codex/src/app-server/startup-binding.ts index 46c175c29ae8..458fd3df7308 100644 --- a/extensions/codex/src/app-server/startup-binding.ts +++ b/extensions/codex/src/app-server/startup-binding.ts @@ -1,3 +1,7 @@ +/** + * Guards Codex app-server thread reuse during startup by rotating bindings when + * native transcripts exceed byte or token budgets. + */ import type { Dirent } from "node:fs"; import fs from "node:fs/promises"; import path from "node:path"; @@ -320,6 +324,7 @@ function hasContextEngineThreadBootstrapProjection(binding: CodexAppServerThread return binding.contextEngine?.projection?.mode === "thread_bootstrap"; } +/** Clears and drops a binding when the native Codex thread is too large to resume safely. */ export async function rotateOversizedCodexAppServerStartupBinding(params: { binding: CodexAppServerThreadBinding | undefined; sessionFile: string; @@ -426,6 +431,7 @@ export async function rotateOversizedCodexAppServerStartupBinding(params: { return binding; } +/** Internal sizing helpers exposed for startup-binding regression tests. */ export const testing = { parseCodexAppServerByteLimit, readCodexAppServerRolloutTokenSnapshotLine, diff --git a/extensions/codex/src/app-server/transport-stdio.ts b/extensions/codex/src/app-server/transport-stdio.ts index 287da8dea940..c3623df81475 100644 --- a/extensions/codex/src/app-server/transport-stdio.ts +++ b/extensions/codex/src/app-server/transport-stdio.ts @@ -1,3 +1,7 @@ +/** + * Creates and configures stdio-backed Codex app-server transports, including + * Windows spawn normalization and environment filtering. + */ import { spawn } from "node:child_process"; import { materializeWindowsSpawnProgram, @@ -20,6 +24,7 @@ const DEFAULT_SPAWN_RUNTIME: CodexAppServerSpawnRuntime = { execPath: process.execPath, }; +/** Resolves the concrete command/argv/shell settings used to spawn Codex app-server. */ export function resolveCodexAppServerSpawnInvocation( options: CodexAppServerStartOptions, runtime: CodexAppServerSpawnRuntime = DEFAULT_SPAWN_RUNTIME, @@ -43,6 +48,7 @@ export function resolveCodexAppServerSpawnInvocation( }; } +/** Merges app-server environment overrides while honoring clearEnv and unsafe key filtering. */ export function resolveCodexAppServerSpawnEnv( options: Pick, baseEnv: NodeJS.ProcessEnv = process.env, @@ -90,6 +96,7 @@ function copySafeEnvironmentEntries( } } +/** Spawns the Codex app-server process and returns the shared transport interface. */ export function createStdioTransport(options: CodexAppServerStartOptions): CodexAppServerTransport { const env = resolveCodexAppServerSpawnEnv(options); const invocation = resolveCodexAppServerSpawnInvocation(options, { diff --git a/extensions/codex/src/app-server/transport-websocket.ts b/extensions/codex/src/app-server/transport-websocket.ts index 41bd3fb4c8fd..0f1f33616a5c 100644 --- a/extensions/codex/src/app-server/transport-websocket.ts +++ b/extensions/codex/src/app-server/transport-websocket.ts @@ -1,9 +1,14 @@ +/** + * Adapts a remote Codex app-server WebSocket endpoint to the shared stdio-like + * transport interface. + */ import { EventEmitter } from "node:events"; import { PassThrough, Writable } from "node:stream"; import WebSocket, { type RawData } from "ws"; import type { CodexAppServerStartOptions } from "./config.js"; import type { CodexAppServerTransport } from "./transport.js"; +/** Opens a WebSocket app-server transport and maps newline-delimited frames to stdout/stdin. */ export function createWebSocketTransport( options: CodexAppServerStartOptions, ): CodexAppServerTransport { diff --git a/extensions/codex/src/app-server/transport.ts b/extensions/codex/src/app-server/transport.ts index a20a0c6e973a..3733b664b764 100644 --- a/extensions/codex/src/app-server/transport.ts +++ b/extensions/codex/src/app-server/transport.ts @@ -1,3 +1,8 @@ +/** + * Shared transport lifecycle helpers for stdio and WebSocket Codex app-server + * connections. + */ +/** Child-process-like transport shape consumed by the Codex app-server client. */ export type CodexAppServerTransport = { stdin: { write: (data: string, callback?: (error?: Error | null) => void) => unknown; @@ -24,6 +29,7 @@ export type CodexAppServerTransport = { off?: (event: string, listener: (...args: unknown[]) => void) => unknown; }; +/** Starts graceful transport shutdown and schedules a force kill fallback. */ export function closeCodexAppServerTransport( child: CodexAppServerTransport, options: { forceKillDelayMs?: number } = {}, @@ -52,6 +58,7 @@ export function closeCodexAppServerTransport( child.stdin.unref?.(); } +/** Closes a transport and waits briefly for an exit event. */ export async function closeCodexAppServerTransportAndWait( child: CodexAppServerTransport, options: { exitTimeoutMs?: number; forceKillDelayMs?: number } = {},