From 64afe05084147ee07251080a5dbdb4c3836f04de Mon Sep 17 00:00:00 2001 From: kevinlin-openai Date: Wed, 6 May 2026 09:19:01 -0700 Subject: [PATCH] docs(codex): keep plugin flow in mem --- docs/flows/codex-native-plugin-apps.md | 437 ------------------------- 1 file changed, 437 deletions(-) delete mode 100644 docs/flows/codex-native-plugin-apps.md diff --git a/docs/flows/codex-native-plugin-apps.md b/docs/flows/codex-native-plugin-apps.md deleted file mode 100644 index a14142b2823..00000000000 --- a/docs/flows/codex-native-plugin-apps.md +++ /dev/null @@ -1,437 +0,0 @@ ---- -created: 2026-05-06 -updated: 2026-05-06 -last_updated_session: codex/019dfbd4-fa58-7050-9ac1-1fa0ac8cfce8 ---- - -# Codex Native Plugin Apps Flow - -## Overview - -This flow describes how OpenClaw uses native Codex plugin/app support instead of registering OpenClaw `codex_plugin_*` bridge tools. It covers two related paths: runtime plugin invocation through the existing bound Codex app-server thread, and migration-time activation of source-installed Codex plugins through app-server control RPCs. - -## Entry Points - -- `extensions/codex/src/conversation-binding.ts:handleCodexConversationInboundClaim` -- `extensions/codex/src/migration/plan.ts:buildCodexMigrationPlan` -- `extensions/codex/src/migration/apply.ts:applyCodexMigrationPlan` - -## Sequence Diagram - -```mermaid -graph TD - user["User sends Codex-mode message"] --> inbound["Gateway inbound_claim"] - inbound --> binding{"Codex conversation binding exists?"} - binding -- no --> pass["Return undefined for other handlers"] - binding -- yes --> auth{"Command authorized?"} - auth -- no --> unauthorized["Handle without starting a Codex turn"] - auth -- yes --> prompt{"Prompt text present?"} - prompt -- no --> empty["Handle without starting a Codex turn"] - prompt -- yes --> enqueue["enqueueBoundTurn"] - enqueue --> run["runBoundTurnWithMissingThreadRecovery"] - run --> thread["Codex app-server bound thread"] - thread --> mention{"Prompt contains native plugin mention?"} - mention -- yes --> native["Codex app-server resolves plugin/app tools in same thread"] - mention -- no --> normal["Codex app-server runs ordinary turn in same thread"] - native --> reply["OpenClaw sends final Codex reply"] - normal --> reply - run --> drift["thread start/resume permission profile schema drift"] - drift --> normalize["normalize unknown special filesystem path kinds"] - normalize --> thread - run --> turn_error["Codex app-server turn error"] - turn_error --> error_reply["OpenClaw sends error reply"] - - cli["openclaw migrate codex --plugin name"] --> discover["discoverCodexSource"] - discover --> list_plugins["app-server plugin/list"] - discover --> list_apps["app-server app/list pages"] - list_plugins --> installed{"Installed openai-curated plugin found?"} - list_apps --> access["Map plugin to app accessibility"] - installed -- no --> unknown["Unknown selection throws with available plugins"] - installed -- yes --> plan["Build native plugin install plan item"] - access --> plan - discover --> discovery_error["Discovery RPC error"] - discovery_error --> warning["Plan includes manual-review warning"] - - plan --> apply["applyCodexMigrationPlan"] - apply --> target_list["Target app-server plugin/list"] - target_list --> ready{"Plugin installed, enabled, and app accessible?"} - ready -- yes --> migrated["Mark item migrated"] - ready -- installed but inaccessible --> reauth_error["Mark item error requiring reauth"] - ready -- no --> install["app-server plugin/install"] - install --> needs_auth{"appsNeedingAuth returned?"} - needs_auth -- yes --> auth_error["Mark item error requiring reauth"] - needs_auth -- no --> refresh["Refresh plugin, skills, MCP server, and app inventory"] - refresh --> report["Write migration report"] - migrated --> report -``` - -## Execution Trace - -### 1. Runtime Turns Stay In The Bound Codex Thread - -OpenClaw receives the user message through the existing Codex conversation binding and forwards the prompt text to the same Codex app-server thread. Native plugin mentions such as `[@Google Calendar](plugin://google-calendar)` remain in the prompt for Codex app-server to resolve; OpenClaw does not synthesize a `codex_plugin_*` tool. - -#### 1.1 Register The Bound Conversation Handler - -The Codex extension resolves the live plugin configuration and registers an inbound claim handler for Codex-bound conversations. - -- `extensions/codex/index.ts:register` - -```ts -register(api) - livePluginConfig := resolveLivePluginConfigObject(openClawConfig) - api.conversation.registerInboundClaimHandler(event, ctx => - handleCodexConversationInboundClaim(event, ctx, { - pluginConfig: livePluginConfig, - }) - ) -``` - -#### 1.2 Claim Authorized Codex Messages - -The handler requires an existing Codex conversation binding, command authorization, and non-empty prompt text before starting a Codex turn. - -- `extensions/codex/src/conversation-binding.ts:handleCodexConversationInboundClaim` - -```ts -handleCodexConversationInboundClaim(event, ctx, options) - data := readCodexConversationBindingData(ctx.pluginBinding) - if not data - return undefined - - if event.commandAuthorized !== true - return { handled: true } - - prompt := trim(event.bodyForAgent) || trim(event.content) || "" - if prompt is empty - return { handled: true } - - result := enqueueBoundTurn(data.sessionFile, () => - runBoundTurnWithMissingThreadRecovery({ - data, - prompt, - event, - pluginConfig: options.pluginConfig, - timeoutMs: options.timeoutMs, - }) - ) - - return { handled: true, reply: result.reply } -``` - -#### 1.3 Let Codex App-Server Own Native Plugin Execution - -The bound turn passes the prompt to the app-server thread. If the prompt includes a native plugin mention, app-server plugin/app support owns tool discovery, activation semantics, auth, transcript semantics, and final assistant output in that same thread. - -- `extensions/codex/src/conversation-binding.ts:runBoundTurnWithMissingThreadRecovery` - -```ts -runBoundTurnWithMissingThreadRecovery(args) - try - return runBoundTurn(args) - catch missingThread - recover or recreate the bound app-server thread - return runBoundTurn(args) - -runBoundTurn(args) - response := requestCodexAppServerJson("thread/turn/start", { - threadId: args.data.threadId, - prompt: args.prompt, - cwd: args.data.cwd, - }) - return response.finalMessage -``` - -### 2. The App-Server Protocol Exposes Native Plugin Control - -OpenClaw uses typed app-server methods for plugin/app listing and installation. The protocol validators also tolerate known live schema drift in thread permission profiles so app-server thread start/resume remains the compatibility boundary, not OpenClaw plugin execution. - -#### 2.1 Declare Plugin And App Control RPCs - -The app-server protocol map records the response type for native plugin and app methods that migration code calls. - -- `extensions/codex/src/app-server/protocol.ts:CodexAppServerRequestResultMap` - -```ts -CodexAppServerRequestResultMap := { - "plugin/list": PluginListResponse, - "plugin/install": PluginInstallResponse, - "app/list": AppsListResponse, - "skills/list": SkillsListResponse, - "config/mcpServer/reload": undefined, - "thread/turn/start": ThreadTurnStartResponse, -} -``` - -#### 2.2 Normalize Permission Profile Drift - -Thread start and resume responses are normalized before schema assertion so an unknown app-server `special` filesystem path kind is represented as an explicit unknown value. - -- `extensions/codex/src/app-server/protocol-validators.ts:assertCodexThreadStartResponse` - -```ts -assertCodexThreadStartResponse(value) - normalized := normalizeThreadPermissionProfile(value) - return assertCodexShape(validateThreadStartResponse, normalized, "thread/start response") - -normalizePermissionProfileFileSystemPath(value) - if value.type !== "special" - return value - if value.value.kind is known - return value - return value with value := { - kind: "unknown", - path: value.value.kind, - subpath: value.value.subpath ?? null, - } -``` - -### 3. Migration Discovery Reads Native Codex Inventory - -When the user asks migration to include Codex plugins, discovery reads the source Codex home for skills and archived config, and asks Codex app-server which `openai-curated` plugins and apps are currently installed. - -#### 3.1 Discover Codex Home Sources - -The source scan discovers Codex skills, personal AgentSkills, cached plugin bundles for manual review, archiveable Codex config paths, and native plugin inventory returned by app-server. - -- `extensions/codex/src/migration/source.ts:discoverCodexSource` - -```ts -discoverCodexSource(input, options) - codexHome := resolveHomePath(trim(input) || defaultCodexHome()) - codexSkills := discoverSkillDirs({ root: codexHome / "skills", excludeSystem: true }) - personalAgentSkills := discoverSkillDirs({ root: personalAgentsSkillsDir() }) - nativePlugins := discoverInstalledOpenAiCuratedPlugins({ - codexHome, - pluginConfig: readCodexPluginConfigFromOpenClawConfig(options.config), - config: options.config, - appServerRequest: options.appServerRequest, - }) - cachedPluginDirs := discoverPluginDirs(codexHome) - archivePaths := existing config.toml and hooks/hooks.json - return CodexSource with skills, nativePlugins, plugins, archivePaths, and warnings -``` - -#### 3.2 Map Installed Curated Plugins To App Accessibility - -The app-server plugin inventory provides installed plugin metadata. The paginated app inventory lets migration warn when an already installed plugin is not currently accessible because app auth or availability is missing. - -- `extensions/codex/src/migration/source.ts:discoverInstalledOpenAiCuratedPlugins` - -```ts -discoverInstalledOpenAiCuratedPlugins(params) - request := params.appServerRequest ?? defaultAppServerRequest(params) - listed := request("plugin/list", { cwds: [] }) - apps := listAllApps(request) - marketplace := listed.marketplaces.find(entry => entry.name === "openai-curated") - if not marketplace - return { plugins: [] } - - return marketplace.plugins - .filter(plugin => plugin.installed) - .map(plugin => ({ - marketplaceName: marketplace.name, - marketplacePath: marketplace.path, - pluginName: plugin.name, - displayName: plugin.title || plugin.name, - sourceInstalled: plugin.installed, - sourceEnabled: plugin.enabled, - accessible: pluginAccessible(plugin, apps), - })) -``` - -### 4. Migration Planning Emits Native Plugin Activation Items - -The migration plan turns selected native source plugins into `kind: "plugin"` install items with native-thread metadata. It also adds only the OpenClaw configuration necessary for the Codex extension itself to run. - -#### 4.1 Select Requested Source Plugins - -Selected plugin names are matched against source inventory by plugin name, display name, ids, and scoped `@openai-curated` names. Unknown selections fail at plan time with available plugin names. - -- `extensions/codex/src/migration/plan.ts:selectCodexPlugins` - -```ts -selectCodexPlugins({ plugins, selected }) - if selected is empty - return [] - - for ref in selected - match := plugins.find(plugin => - ref matches plugin.name or plugin.id or displayName or scoped openai-curated name - ) - if not match - throw Error("Unknown Codex plugin selection") - selectedPlugins.push(match) - - return selectedPlugins -``` - -#### 4.2 Build Native Plugin Items - -Each selected source-installed plugin becomes a native activation item. The item deliberately describes app-server installation, not an OpenClaw dynamic tool registration. - -- `extensions/codex/src/migration/plan.ts:buildCodexPluginItems` - -```ts -buildCodexPluginItems({ ctx, plugins }) - items := [] - for plugin in plugins - items.push(createMigrationItem({ - kind: "plugin", - action: "install", - status: "planned", - source: plugin.id, - target: "codex app-server plugin", - details: { - marketplaceName: plugin.marketplaceName, - marketplacePath: plugin.marketplacePath, - pluginName: plugin.pluginName, - nativeThreadPlugin: true, - sourceInstalled: plugin.sourceInstalled, - sourceEnabled: plugin.sourceEnabled, - accessible: plugin.accessible, - }, - })) - - items.push(...buildCodexPluginConfigItems({ ctx })) - return items -``` - -#### 4.3 Add Only Codex Extension Config - -The migration enables the OpenClaw Codex extension and, when the user's config uses a restrictive plugin allowlist, appends only `codex` to that allowlist. - -- `extensions/codex/src/migration/plan.ts:buildCodexPluginConfigItems` - -```ts -buildCodexPluginConfigItems({ ctx }) - items := [ - config merge item for plugins.entries.codex.enabled = true, - ] - - if ctx.config.plugins.allow is string array and does not include "codex" - items.push(config merge item appending "codex") - - return items -``` - -### 5. Migration Apply Installs Through Codex App-Server - -Apply resolves the current target app-server marketplace, installs selected plugins through `plugin/install`, refreshes the app-server runtime inventories, then writes the migration report. - -#### 5.1 Build The Target App-Server Request - -The default request path launches or contacts Codex app-server using the target OpenClaw Codex plugin configuration while pointing `CODEX_HOME` at the selected source home when provided. - -- `extensions/codex/src/migration/apply.ts:defaultAppServerRequest` - -```ts -defaultAppServerRequest(ctx) - runtimeOptions := resolveCodexAppServerRuntimeOptions({ - pluginConfig: readCodexPluginConfigFromOpenClawConfig(ctx.config), - }) - env := process.env - if ctx.source is set - env.CODEX_HOME := ctx.source - return (method, params) => - requestCodexAppServerJson(method, params, { - ...runtimeOptions, - env, - }) -``` - -#### 5.2 Activate Selected Plugins - -The activation loop validates each plan item's marketplace and app accessibility, skips already installed and enabled plugins, installs missing plugins, and converts app auth requirements into item-level errors. - -- `extensions/codex/src/migration/apply.ts:applyCodexPluginActivationItems` - -```ts -applyCodexPluginActivationItems({ ctx, items }) - request := appServerRequestForTests ?? defaultAppServerRequest(ctx) - listed := request("plugin/list", { cwds: [] }) - marketplace := listed.marketplaces.find(entry => entry.name === "openai-curated") - - for item in items - detail := readPluginDetail(item) - plugin := marketplace.plugins.find(entry => entry.name === detail.pluginName) - - if detail is invalid or marketplace missing or plugin missing - mark item as error - else if plugin.installed and plugin.enabled and detail.accessible === false - mark item as error requiring app reauth - else if plugin.installed and plugin.enabled - mark item as migrated - else - response := request("plugin/install", { - marketplacePath: marketplace.path, - pluginName: detail.pluginName, - }) - if response.appsNeedingAuth is not empty - mark item as error requiring app auth - else - mark item as migrated - - if any install changed app-server state - refreshCodexPluginRuntime(request) -``` - -#### 5.3 Refresh Runtime Inventory And Write The Report - -After an install changes app-server state, apply forces plugin, skills, MCP server, and app inventory refreshes before writing the final report. - -- `extensions/codex/src/migration/apply.ts:refreshCodexPluginRuntime` - -```ts -refreshCodexPluginRuntime(request) - request("plugin/list", { forceReload: true, cwds: [] }) - request("skills/list", { forceReload: true }) - request("config/mcpServer/reload", {}) - request("app/list", { forceRefetch: true, limit: 50 }) - -applyCodexMigrationPlan(input) - plan := input.plan ?? buildCodexMigrationPlan(input.ctx) - pluginItems := applyCodexPluginActivationItems({ ctx: input.ctx, items: plannedPluginItems }) - configItems := apply config merge items, including the codex allowlist merge - archiveItems := copy or archive source files - result := MigrationApplyResult(pluginItems + configItems + archiveItems) - writeMigrationReport(result, { title: "Codex Migration Report" }) - return result -``` - -## Notes - -- OpenClaw no longer keeps a backwards-compatible `codex_plugin_*` dynamic tool bridge. Runtime plugin calls use native Codex mention text in the existing bound thread. -- Codex app-server owns plugin execution semantics: app auth, permission prompts, app/tool transcript shape, and plugin availability all remain native Codex behavior. -- Migration auto-activates only source-installed `openai-curated` plugins discovered through app-server inventory. Cached plugin bundle directories under `CODEX_HOME/plugins/cache` remain manual-review migration items. -- `plugins.allow` migration is limited to enabling the OpenClaw `codex` extension when the user's config already has a restrictive allowlist. It does not add OpenClaw dynamic tools for each selected Codex plugin. -- If app-server plugin discovery fails, the plan still reports skills and archiveable Codex files when available, and includes a manual-review warning for native plugin setup. -- If a selected plugin is already installed and enabled but its related app is inaccessible, apply marks that item as an error rather than silently treating it as usable. -- Unknown `special` filesystem path kinds in app-server permission profiles are normalized before validation so live app-server schema drift does not block thread start or resume. - -## Observability - -Metrics: - -- None identified in this flow. The implementation relies on app-server responses, migration item statuses, and test/showboat evidence rather than dedicated counters. - -Logs: - -- `extensions/codex/src/conversation-binding.ts:handleCodexConversationInboundClaim` sends a user-visible error reply when a bound Codex app-server turn fails. -- `extensions/codex/src/migration/apply.ts:applyCodexMigrationPlan` writes a `Codex Migration Report` with migrated, skipped, conflict, and error item statuses. - -## Related docs - -- [Codex native plugin app spec](../plan/codex-native-plugin-apps.md) -- [Codex harness docs](../plugins/codex-harness.md) -- [openclaw migrate docs](../cli/migrate.md) -- [Configure and invoke plugins PR](https://github.com/openclaw/openclaw/pull/78443) -- [Codex plugin migration PR](https://github.com/openclaw/openclaw/pull/78444) - -## Manual Notes - -[keep this for the user to add notes. do not change between edits] - -## Changelog - -- 2026-05-06: Created Codex native plugin apps flow doc. (codex/019dfbd4-fa58-7050-9ac1-1fa0ac8cfce8 - 6beeff01c9)