mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
docs: document codex app-server runtime utilities
This commit is contained in:
@@ -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<boolean>;
|
||||
};
|
||||
|
||||
/** 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<string, unknown> {
|
||||
return typeof value === "object" && value !== null;
|
||||
}
|
||||
|
||||
/** Internal helpers exposed for managed-binary path-resolution tests. */
|
||||
export const testing = {
|
||||
resolveDefaultCodexPluginRoot,
|
||||
};
|
||||
|
||||
@@ -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<string>([
|
||||
"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;
|
||||
|
||||
@@ -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<typeof resolveProviderIdForAuth>[1];
|
||||
type ProviderAuthAliasConfig = NonNullable<ProviderAuthAliasLookupParams>["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<CodexAppServerAuthProfileLookup, "authProfileId"> = {},
|
||||
@@ -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<CodexAppServerAuthProfileLookup, "authProfileId"> = {},
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<CodexAppServerStartOptions, "env" | "clearEnv">,
|
||||
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, {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 } = {},
|
||||
|
||||
Reference in New Issue
Block a user