feat(codex): enable native plugin app support (#78733)

* feat(codex): add native plugin config schema

* feat(codex): add native plugin inventory activation

* feat(codex): configure native plugin apps for threads

* feat(codex): enforce plugin elicitation policy

* feat(codex): migrate native plugins

* docs(codex): document native plugin support

* fix(codex): harden plugin migration refresh

* fix(codex): satisfy plugin activation lint

* fix: stabilize codex plugin app config

* fix: address codex plugin review feedback

* fix: key codex plugin app cache by websocket credentials

* fix: keep codex plugin app fingerprints stable

* fix: refresh codex plugin cache test fixtures

* fix: refresh plugin app readiness after activation

* fix: support remote codex plugin activation

* fix: recover plugin app bindings after cache refresh

* fix: force codex app refresh after plugin activation

* fix: recover partial codex plugin app bindings

* fix: sync codex plugin selection config

* fix: keep codex plugin activation fail closed

* fix: align codex plugin protocol types with main

* fix: refresh partial codex plugin app bindings

* fix: key codex app cache by env api key

* fix: skip failed codex plugin migration config

* test: update codex prompt snapshots

* fix: fail closed on missing codex app inventory entries

* fix(codex): enforce native plugin policy gates

* fix(codex): normalize native plugin policy types

* fix(codex): fail closed on plugin refresh errors

* fix(codex): use native plugin destructive policy

* fix(codex): key plugin cache by api-key profiles

* fix(codex): drop unshipped plugin fingerprint compat

* fix(codex): let native app policy gate plugin tools

* fix(codex): allow open-world plugin app tools

* fix(codex): revalidate native plugin app bindings

* fix(codex): preserve plugin binding on recheck failure

* docs(codex): clarify plugin harness scope

* fix(codex): return activation report state exhaustively

* test(codex): refresh prompt snapshots after rebase

* fix(codex): match namespaced plugin ids
This commit is contained in:
Kevin Lin
2026-05-07 17:20:28 -07:00
committed by GitHub
parent b75e5c50bf
commit a1ac559ed7
40 changed files with 7198 additions and 78 deletions

View File

@@ -14,6 +14,10 @@ function collectMigrationSkill(value: string, previous: string[] | undefined): s
return [...(previous ?? []), value];
}
function collectMigrationPlugin(value: string, previous: string[] | undefined): string[] {
return [...(previous ?? []), value];
}
function readMigrationSkills(value: unknown): string[] | undefined {
if (!Array.isArray(value)) {
return undefined;
@@ -25,6 +29,17 @@ function readMigrationSkills(value: unknown): string[] | undefined {
return skills.length > 0 ? skills : undefined;
}
function readMigrationPlugins(value: unknown): string[] | undefined {
if (!Array.isArray(value)) {
return undefined;
}
const plugins = value
.filter((item): item is string => typeof item === "string")
.map((item) => item.trim())
.filter((item) => item.length > 0);
return plugins.length > 0 ? plugins : undefined;
}
function addMigrationSkillOption(command: Command): Command {
return command.option(
"--skill <name>",
@@ -33,13 +48,23 @@ function addMigrationSkillOption(command: Command): Command {
);
}
function addMigrationPluginOption(command: Command): Command {
return command.option(
"--plugin <name>",
"Select one Codex plugin to migrate by name or item id; repeat for multiple plugins",
collectMigrationPlugin,
);
}
function addMigrationOptions(command: Command): Command {
return addMigrationSkillOption(
command
.option("--from <path>", "Source directory to migrate from")
.option("--include-secrets", "Import supported credentials and secrets", false)
.option("--overwrite", "Overwrite conflicting target files after item-level backups", false)
.option("--json", "Output JSON", false),
return addMigrationPluginOption(
addMigrationSkillOption(
command
.option("--from <path>", "Source directory to migrate from")
.option("--include-secrets", "Import supported credentials and secrets", false)
.option("--overwrite", "Overwrite conflicting target files after item-level backups", false)
.option("--json", "Output JSON", false),
),
);
}
@@ -58,6 +83,11 @@ export function registerMigrateCommand(program: Command) {
"Select one skill to migrate by name or item id; repeat for multiple skills",
collectMigrationSkill,
)
.option(
"--plugin <name>",
"Select one Codex plugin to migrate by name or item id; repeat for multiple plugins",
collectMigrationPlugin,
)
.option("--backup-output <path>", "Pre-migration backup archive path or directory")
.option("--no-backup", "Skip the pre-migration OpenClaw backup")
.option("--force", "Allow dangerous options such as --no-backup", false)
@@ -87,6 +117,7 @@ export function registerMigrateCommand(program: Command) {
includeSecrets: Boolean(opts.includeSecrets),
overwrite: Boolean(opts.overwrite),
skills: readMigrationSkills(opts.skill),
plugins: readMigrationPlugins(opts.plugin),
dryRun: Boolean(opts.dryRun),
yes: Boolean(opts.yes),
backupOutput: opts.backupOutput as string | undefined,
@@ -119,6 +150,7 @@ export function registerMigrateCommand(program: Command) {
includeSecrets: Boolean(opts.includeSecrets),
overwrite: Boolean(opts.overwrite),
skills: readMigrationSkills(opts.skill),
plugins: readMigrationPlugins(opts.plugin),
json: Boolean(opts.json),
});
});
@@ -139,6 +171,7 @@ export function registerMigrateCommand(program: Command) {
includeSecrets: Boolean(opts.includeSecrets),
overwrite: Boolean(opts.overwrite),
skills: readMigrationSkills(opts.skill),
plugins: readMigrationPlugins(opts.plugin),
yes: Boolean(opts.yes),
backupOutput: opts.backupOutput as string | undefined,
noBackup: opts.backup === false,