docs: document codex app-server utilities

This commit is contained in:
Peter Steinberger
2026-06-04 08:35:15 -04:00
parent 121ee3f555
commit 2ff83d3023
6 changed files with 46 additions and 0 deletions

View File

@@ -1,3 +1,7 @@
/**
* Correlates Codex app-server notifications with the active thread/turn so
* projectors can ignore global or stale events without losing diagnostics.
*/
import {
isJsonObject,
type CodexServerNotification,
@@ -5,6 +9,7 @@ import {
type JsonValue,
} from "./protocol.js";
/** Debug-friendly correlation summary for a Codex app-server notification. */
export type CodexNotificationCorrelation = {
method: string;
paramsKeys?: string[];
@@ -20,6 +25,7 @@ export type CodexNotificationCorrelation = {
matchesActiveTurn?: boolean;
};
/** Returns true when a notification payload belongs to the exact active thread and turn. */
export function isCodexNotificationForTurn(
value: JsonValue | undefined,
threadId: string,
@@ -34,14 +40,17 @@ export function isCodexNotificationForTurn(
);
}
/** Reads a thread id from either top-level notification params or nested turn payloads. */
export function readCodexNotificationThreadId(record: JsonObject): string | undefined {
return readNestedTurnThreadId(record) ?? readString(record, "threadId");
}
/** Reads a turn id from either top-level notification params or nested turn payloads. */
export function readCodexNotificationTurnId(record: JsonObject): string | undefined {
return readNestedTurnId(record) ?? readString(record, "turnId");
}
/** Builds structured correlation details for logs when notification routing is ambiguous. */
export function describeCodexNotificationCorrelation(
notification: CodexServerNotification,
active: { threadId: string; turnId?: string },

View File

@@ -1,3 +1,7 @@
/**
* Builds stable Codex plugin/app inventory cache keys from app-server startup,
* auth, account, and version inputs without storing secret material.
*/
import { createHash } from "node:crypto";
import {
buildCodexAppInventoryCacheKey,
@@ -6,6 +10,7 @@ import {
import { resolveCodexAppServerHomeDir } from "./auth-bridge.js";
import type { CodexAppServerRuntimeOptions, CodexAppServerStartOptions } from "./config.js";
/** Inputs that identify the Codex app inventory cache scope for one runtime. */
export type CodexPluginAppCacheKeyParams = Omit<
CodexAppInventoryCacheKeyInput,
"codexHome" | "endpoint"
@@ -14,6 +19,7 @@ export type CodexPluginAppCacheKeyParams = Omit<
agentDir?: string;
};
/** Builds the full app inventory cache key for Codex plugin/app discovery. */
export function buildCodexPluginAppCacheKey(params: CodexPluginAppCacheKeyParams): string {
return buildCodexAppInventoryCacheKey({
codexHome: resolveCodexPluginAppCacheCodexHome(params.appServer, params.agentDir),
@@ -25,6 +31,7 @@ export function buildCodexPluginAppCacheKey(params: CodexPluginAppCacheKeyParams
});
}
/** Serializes app-server endpoint identity, including credential fingerprints. */
export function resolveCodexPluginAppCacheEndpoint(
appServer: Pick<CodexAppServerRuntimeOptions, "start">,
): string {
@@ -37,6 +44,7 @@ export function resolveCodexPluginAppCacheEndpoint(
});
}
/** Resolves the CODEX_HOME value that scopes local app-server inventory. */
export function resolveCodexPluginAppCacheCodexHome(
appServer: Pick<CodexAppServerRuntimeOptions, "start">,
agentDir?: string,

View File

@@ -1,8 +1,13 @@
/**
* Resolves whether Codex app-server profiling instrumentation is enabled by
* OpenClaw diagnostic flags.
*/
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
import { isDiagnosticFlagEnabled } from "openclaw/plugin-sdk/diagnostic-runtime";
const PROFILER_FLAGS = ["profiler", "codex.profiler"] as const;
/** Checks the generic and Codex-specific profiler diagnostic flags. */
export function isCodexAppServerProfilerEnabled(
config?: OpenClawConfig,
env: NodeJS.ProcessEnv = process.env,

View File

@@ -1,3 +1,7 @@
/**
* Keeps the latest Codex app-server rate-limit payload in process-global state
* so failure handling can enrich later usage-limit errors.
*/
import type { JsonValue } from "./protocol.js";
const DEFAULT_CODEX_RATE_LIMIT_CACHE_MAX_AGE_MS = 10 * 60_000;
@@ -16,6 +20,7 @@ function getCodexRateLimitCacheState(): CodexRateLimitCacheState {
return globalState[CODEX_RATE_LIMIT_CACHE_STATE];
}
/** Stores a non-empty Codex rate-limit payload with its observation time. */
export function rememberCodexRateLimits(value: JsonValue | undefined, nowMs = Date.now()): void {
if (value === undefined) {
return;
@@ -25,6 +30,7 @@ export function rememberCodexRateLimits(value: JsonValue | undefined, nowMs = Da
state.updatedAtMs = nowMs;
}
/** Reads the cached Codex rate-limit payload when it is still within the max-age window. */
export function readRecentCodexRateLimits(options?: {
nowMs?: number;
maxAgeMs?: number;
@@ -41,6 +47,7 @@ export function readRecentCodexRateLimits(options?: {
return state.value;
}
/** Clears the process-global rate-limit cache for deterministic tests. */
export function resetCodexRateLimitCacheForTests(): void {
const state = getCodexRateLimitCacheState();
state.value = undefined;

View File

@@ -1,3 +1,7 @@
/**
* Parses Codex account rate-limit payloads into user-facing usage summaries,
* reset hints, and enriched usage-limit error messages.
*/
import {
MAX_DATE_TIMESTAMP_MS,
resolveExpiresAtMsFromEpochSeconds,
@@ -25,6 +29,7 @@ type RateLimitWindowEntry = {
window: RateLimitReset;
};
/** Human-readable Codex account usage state derived from rate-limit snapshots. */
export type CodexAccountUsageSummary = {
usageLine?: string;
blocked: boolean;
@@ -35,6 +40,7 @@ export type CodexAccountUsageSummary = {
blockingReason?: string;
};
/** Enriches Codex usage-limit failures with reset timing and recovery guidance. */
export function formatCodexUsageLimitErrorMessage(params: {
message?: string | null;
codexErrorInfo?: JsonValue | null;
@@ -74,6 +80,7 @@ export function formatCodexUsageLimitErrorMessage(params: {
return parts.join(" ");
}
/** Detects usage-limit messages that need a fresh rate-limit query before display. */
export function shouldRefreshCodexRateLimitsForUsageLimitMessage(
message: string | null | undefined,
): boolean {
@@ -84,6 +91,7 @@ export function shouldRefreshCodexRateLimitsForUsageLimitMessage(
);
}
/** Formats compact summaries for raw Codex rate-limit snapshot payloads. */
export function summarizeCodexRateLimits(
value: JsonValue | undefined,
nowMs = Date.now(),
@@ -99,10 +107,12 @@ export function summarizeCodexRateLimits(
return summaries.length > 0 ? summaries.join("; ") : undefined;
}
/** Returns true when a value contains any recognizable Codex rate-limit snapshots. */
export function hasCodexRateLimitSnapshots(value: JsonValue | undefined): boolean {
return collectCodexRateLimitSnapshots(value).length > 0;
}
/** Builds short account availability lines suitable for status surfaces. */
export function summarizeCodexAccountRateLimits(
value: JsonValue | undefined,
nowMs = Date.now(),
@@ -124,6 +134,7 @@ export function summarizeCodexAccountRateLimits(
];
}
/** Returns the reset timestamp for the currently blocking Codex usage limit. */
export function resolveCodexUsageLimitResetAtMs(
value: JsonValue | undefined,
nowMs = Date.now(),
@@ -131,6 +142,7 @@ export function resolveCodexUsageLimitResetAtMs(
return selectBlockingRateLimitReset(value, nowMs)?.resetsAtMs;
}
/** Summarizes account availability, blocking reason, and reset time from rate-limit data. */
export function summarizeCodexAccountUsage(
value: JsonValue | undefined,
nowMs = Date.now(),

View File

@@ -1,3 +1,7 @@
/**
* Sends typed JSON-RPC requests to the Codex app-server with sandbox guard
* checks, shared-client leasing, and isolated-client shutdown handling.
*/
import type { resolveCodexAppServerAuthProfileIdForAgent } from "./auth-bridge.js";
import type { CodexAppServerStartOptions } from "./config.js";
import type {
@@ -14,6 +18,7 @@ import {
} from "./shared-client.js";
import { withTimeout } from "./timeout.js";
/** Sends a typed Codex app-server request and returns the method-specific response shape. */
export async function requestCodexAppServerJson<M extends CodexAppServerRequestMethod>(params: {
method: M;
requestParams: CodexAppServerRequestParams<M>;