From d99268ae514adae9cb61a9c76332cb2dfd27ba6f Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 4 Jun 2026 08:46:41 -0400 Subject: [PATCH] docs: document codex plugin app config --- .../codex/src/app-server/plugin-activation.ts | 13 +++++++++++++ .../codex/src/app-server/plugin-inventory.ts | 15 +++++++++++++++ .../codex/src/app-server/plugin-thread-config.ts | 16 ++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/extensions/codex/src/app-server/plugin-activation.ts b/extensions/codex/src/app-server/plugin-activation.ts index 70129db1f152..42b6dc4d2502 100644 --- a/extensions/codex/src/app-server/plugin-activation.ts +++ b/extensions/codex/src/app-server/plugin-activation.ts @@ -1,3 +1,7 @@ +/** + * Activates configured Codex marketplace plugins and refreshes runtime state so + * plugin-owned apps/tools are visible to native Codex turns. + */ import fs from "node:fs/promises"; import path from "node:path"; import type { CodexAppInventoryCache, CodexAppInventoryRequest } from "./app-inventory-cache.js"; @@ -10,6 +14,7 @@ import { } from "./plugin-inventory.js"; import type { v2 } from "./protocol.js"; +/** Terminal reason reported after trying to activate one Codex plugin policy. */ export type CodexPluginActivationReason = | "already_active" | "installed" @@ -19,10 +24,12 @@ export type CodexPluginActivationReason = | "auth_required" | "refresh_failed"; +/** Human-readable diagnostic emitted during Codex plugin activation. */ export type CodexPluginActivationDiagnostic = { message: string; }; +/** Result of ensuring one configured Codex plugin is installed and enabled. */ export type CodexPluginActivationResult = { identity: ResolvedCodexPluginPolicy; ok: boolean; @@ -33,6 +40,7 @@ export type CodexPluginActivationResult = { diagnostics: CodexPluginActivationDiagnostic[]; }; +/** Inputs for activating one resolved Codex plugin policy. */ export type EnsureCodexPluginActivationParams = { identity: ResolvedCodexPluginPolicy; request: CodexPluginRuntimeRequest; @@ -41,10 +49,12 @@ export type EnsureCodexPluginActivationParams = { installEvenIfActive?: boolean; }; +/** Diagnostics from refreshing Codex runtime surfaces after plugin activation. */ export type CodexPluginRuntimeRefreshResult = { diagnostics: CodexPluginActivationDiagnostic[]; }; +/** Installs/enables a configured Codex plugin and refreshes plugin/app state. */ export async function ensureCodexPluginActivation( params: EnsureCodexPluginActivationParams, ): Promise { @@ -130,6 +140,7 @@ export async function ensureCodexPluginActivation( }; } +/** Forces Codex plugin, skill, hook, MCP, and app inventory refreshes after activation. */ export async function refreshCodexPluginRuntimeState(params: { request: CodexPluginRuntimeRequest; appCache?: CodexAppInventoryCache; @@ -176,6 +187,7 @@ export async function refreshCodexPluginRuntimeState(params: { return { diagnostics }; } +/** Ensures the Codex config enables app substrate support needed by plugin-owned apps. */ export async function ensureCodexAppsSubstrateConfig(params: { codexHome: string; readFile?: (filePath: string, encoding: "utf8") => Promise; @@ -211,6 +223,7 @@ export async function ensureCodexAppsSubstrateConfig(params: { return { changed: true, configPath }; } +/** Upserts a boolean key in a TOML section while preserving the rest of the file. */ export function upsertTomlBoolean( source: string, section: string, diff --git a/extensions/codex/src/app-server/plugin-inventory.ts b/extensions/codex/src/app-server/plugin-inventory.ts index aaa7a00d35c9..f347df3c98ab 100644 --- a/extensions/codex/src/app-server/plugin-inventory.ts +++ b/extensions/codex/src/app-server/plugin-inventory.ts @@ -1,3 +1,7 @@ +/** + * Reads Codex plugin marketplace state and app inventory to decide which + * plugin-owned apps can be exposed to a native Codex thread. + */ import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime"; import type { CodexAppInventoryCache, @@ -12,14 +16,17 @@ import { } from "./config.js"; import type { v2 } from "./protocol.js"; +/** Request callback used to call Codex app-server plugin/app methods. */ export type CodexPluginRuntimeRequest = (method: string, params?: unknown) => Promise; +/** Stable reference to the OpenAI curated Codex plugin marketplace. */ export type CodexPluginMarketplaceRef = { name: typeof CODEX_PLUGINS_MARKETPLACE_NAME; path?: string; remoteMarketplaceName?: string; }; +/** Machine-readable inventory diagnostic code used by thread config builders. */ export type CodexPluginInventoryDiagnosticCode = | "disabled" | "marketplace_missing" @@ -30,12 +37,14 @@ export type CodexPluginInventoryDiagnosticCode = | "app_inventory_stale" | "app_ownership_ambiguous"; +/** Diagnostic explaining why a configured plugin or app cannot be exposed. */ export type CodexPluginInventoryDiagnostic = { code: CodexPluginInventoryDiagnosticCode; plugin?: ResolvedCodexPluginPolicy; message: string; }; +/** App owned by a Codex plugin with current accessibility/auth state. */ export type CodexPluginOwnedApp = { id: string; name: string; @@ -44,6 +53,7 @@ export type CodexPluginOwnedApp = { needsAuth: boolean; }; +/** Inventory record for one configured Codex plugin policy. */ export type CodexPluginInventoryRecord = { policy: ResolvedCodexPluginPolicy; summary: v2.PluginSummary; @@ -55,6 +65,7 @@ export type CodexPluginInventoryRecord = { apps: CodexPluginOwnedApp[]; }; +/** Complete inventory result for configured Codex plugins and owned apps. */ export type CodexPluginInventory = { policy: ResolvedCodexPluginsPolicy; marketplace?: CodexPluginMarketplaceRef; @@ -63,6 +74,7 @@ export type CodexPluginInventory = { appInventory?: CodexAppInventoryCacheRead; }; +/** Inputs for reading plugin marketplace/detail state and cached app inventory. */ export type ReadCodexPluginInventoryParams = { pluginConfig?: unknown; policy?: ResolvedCodexPluginsPolicy; @@ -74,6 +86,7 @@ export type ReadCodexPluginInventoryParams = { suppressAppInventoryRefresh?: boolean; }; +/** Reads configured Codex plugin state and maps owned apps to readiness diagnostics. */ export async function readCodexPluginInventory( params: ReadCodexPluginInventoryParams, ): Promise { @@ -195,6 +208,7 @@ export async function readCodexPluginInventory( return inventory; } +/** Finds one plugin summary in the OpenAI curated marketplace response. */ export function findOpenAiCuratedPluginSummary( listed: v2.PluginListResponse, pluginName: string, @@ -209,6 +223,7 @@ export function findOpenAiCuratedPluginSummary( return summary ? { marketplace: marketplaceRef(marketplaceEntry), summary } : undefined; } +/** Builds plugin/read or plugin/install params from a marketplace reference. */ export function pluginReadParams( marketplace: CodexPluginMarketplaceRef, pluginName: string, diff --git a/extensions/codex/src/app-server/plugin-thread-config.ts b/extensions/codex/src/app-server/plugin-thread-config.ts index a76f0207de84..67dbff6b2e80 100644 --- a/extensions/codex/src/app-server/plugin-thread-config.ts +++ b/extensions/codex/src/app-server/plugin-thread-config.ts @@ -1,3 +1,7 @@ +/** + * Builds Codex thread config patches that expose only policy-approved + * plugin-owned apps for native Codex turns. + */ import crypto from "node:crypto"; import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime"; import { @@ -26,6 +30,7 @@ import { } from "./plugin-inventory.js"; import type { JsonObject, JsonValue } from "./protocol.js"; +/** Policy context for one app id exposed by a configured Codex plugin. */ export type PluginAppPolicyContextEntry = { configKey: string; marketplaceName: ResolvedCodexPluginPolicy["marketplaceName"]; @@ -34,12 +39,14 @@ export type PluginAppPolicyContextEntry = { mcpServerNames: string[]; }; +/** Stable app-to-plugin ownership context persisted with Codex thread bindings. */ export type PluginAppPolicyContext = { fingerprint: string; apps: Record; pluginAppIds: Record; }; +/** Diagnostic emitted while building app config for a native Codex thread. */ export type CodexPluginThreadConfigDiagnostic = | CodexPluginInventoryDiagnostic | { @@ -48,6 +55,7 @@ export type CodexPluginThreadConfigDiagnostic = message: string; }; +/** Complete Codex thread config patch plus inventory and policy fingerprints. */ export type CodexPluginThreadConfig = { enabled: boolean; configPatch?: JsonObject; @@ -58,6 +66,7 @@ export type CodexPluginThreadConfig = { diagnostics: CodexPluginThreadConfigDiagnostic[]; }; +/** Inputs for building a Codex thread app/plugin config patch. */ export type BuildCodexPluginThreadConfigParams = { pluginConfig?: unknown; request: CodexPluginRuntimeRequest; @@ -69,10 +78,12 @@ export type BuildCodexPluginThreadConfigParams = { const CODEX_PLUGIN_THREAD_CONFIG_INPUT_FINGERPRINT_VERSION = 1; const CODEX_PLUGIN_THREAD_CONFIG_FINGERPRINT_VERSION = 1; +/** Returns true when plugin config exists and thread config may need app patches. */ export function shouldBuildCodexPluginThreadConfig(pluginConfig?: unknown): boolean { return resolveCodexPluginsPolicy(pluginConfig).configured; } +/** Fingerprints policy and app-cache identity before runtime inventory is read. */ export function buildCodexPluginThreadConfigInputFingerprint(params: { pluginConfig?: unknown; appCacheKey?: string; @@ -85,6 +96,7 @@ export function buildCodexPluginThreadConfigInputFingerprint(params: { }); } +/** Builds the Codex apps config patch and policy context for a native thread. */ export async function buildCodexPluginThreadConfig( params: BuildCodexPluginThreadConfigParams, ): Promise { @@ -257,6 +269,7 @@ export async function buildCodexPluginThreadConfig( }; } +/** Deep-merges optional Codex thread config patches, returning undefined when empty. */ export function mergeCodexThreadConfigs( ...configs: Array ): JsonObject | undefined { @@ -270,6 +283,7 @@ export function mergeCodexThreadConfigs( return merged && Object.keys(merged).length > 0 ? merged : undefined; } +/** Detects when a stored thread binding no longer matches current plugin policy inputs. */ export function isCodexPluginThreadBindingStale(params: { codexPluginsEnabled: boolean; bindingFingerprint?: string; @@ -442,6 +456,8 @@ function fingerprintJson(value: JsonValue): string { } function stableStringify(value: JsonValue | undefined): string { + // Fingerprints must be process-stable across object insertion order so prompt + // cache and thread-binding comparisons do not churn between runs. if (Array.isArray(value)) { return `[${value.map((item) => stableStringify(item)).join(",")}]`; }