mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 04:15:48 -06:00
b68c136609
* feat(codex): upgrade app-server integration to 0.149.0 Co-authored-by: Vincent Koc <vincentkoc@ieee.org> * fix(codex): harden full app-server integration and lifecycle * fix(codex): scope guardian trust and satisfy integration gates * fix(codex): keep guardian startup and router tests within gates * chore(codex): tighten guardian assertion safety baseline * fix(ui): preserve sidebar icon path contracts * test(codex): align side-question auth fixture Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com> * style(codex): format transcript mirror imports Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com> * test(codex): preserve native approval decisions Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com> * test(codex): isolate app cache and catalog fixtures Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com> * fix(ui): render guardian review and system notices Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com> * test(codex): isolate native approval decisions Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com> * fix(codex): revalidate reviewer config trust Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com> * chore(codex): update app-server to 0.149.1 Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com> * test(codex): align desktop version warning Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com> * fix(ui): scope notices to the active run Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com> * fix(codex): isolate review, hosted app, and auth ownership Co-authored-by: Vito Cappello <hixvac@gmail.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org> Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com> * chore(codex): keep release notes out of the release-owned changelog * test(codex): reject reviewer cancellation with its explicit error --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org> Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com> Co-authored-by: roboclaw-bot <309084314+roboclaw-bot@users.noreply.github.com> Co-authored-by: Vito Cappello <hixvac@gmail.com>
138 lines
5.0 KiB
TypeScript
138 lines
5.0 KiB
TypeScript
/**
|
|
* Doctor contract hooks for Codex plugin config and state migrations.
|
|
*/
|
|
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
|
|
import { asNullableRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
|
|
type LegacyConfigRule = {
|
|
path: string[];
|
|
message: string;
|
|
match: (value: unknown) => boolean;
|
|
};
|
|
|
|
function hasRetiredDynamicToolsProfile(value: unknown): boolean {
|
|
return Object.hasOwn(asNullableRecord(value) ?? {}, "codexDynamicToolsProfile");
|
|
}
|
|
|
|
function hasLegacyPluginDestructivePolicy(value: unknown): boolean {
|
|
const codexPlugins = asNullableRecord(value);
|
|
if (!codexPlugins) {
|
|
return false;
|
|
}
|
|
if (codexPlugins.allow_destructive_actions === "on-request") {
|
|
return true;
|
|
}
|
|
const plugins = asNullableRecord(codexPlugins.plugins);
|
|
return Object.values(plugins ?? {}).some(
|
|
(plugin) => asNullableRecord(plugin)?.allow_destructive_actions === "on-request",
|
|
);
|
|
}
|
|
|
|
function hasRetiredApprovalPolicy(value: unknown): boolean {
|
|
const approvalPolicy = asNullableRecord(value)?.approvalPolicy;
|
|
return approvalPolicy === "on-failure" || approvalPolicy === "untrusted";
|
|
}
|
|
|
|
/** Legacy Codex config keys that doctor should report or repair. */
|
|
export const legacyConfigRules: LegacyConfigRule[] = [
|
|
{
|
|
path: ["plugins", "entries", "codex", "config"],
|
|
message:
|
|
'plugins.entries.codex.config.codexDynamicToolsProfile is retired; Codex app-server always keeps Codex-native workspace tools native. Run "openclaw doctor --fix".',
|
|
match: hasRetiredDynamicToolsProfile,
|
|
},
|
|
{
|
|
path: ["plugins", "entries", "codex", "config", "codexPlugins"],
|
|
message:
|
|
'plugins.entries.codex.config.codexPlugins.allow_destructive_actions="on-request" was renamed to "auto". Run "openclaw doctor --fix".',
|
|
match: hasLegacyPluginDestructivePolicy,
|
|
},
|
|
{
|
|
path: ["plugins", "entries", "codex", "config", "appServer"],
|
|
message:
|
|
'plugins.entries.codex.config.appServer.approvalPolicy values "on-failure" and "untrusted" are retired; use "on-request". Run "openclaw doctor --fix".',
|
|
match: hasRetiredApprovalPolicy,
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Removes retired Codex plugin config keys while preserving unrelated config.
|
|
*/
|
|
export function normalizeCompatibilityConfig({ cfg }: { cfg: OpenClawConfig }): {
|
|
config: OpenClawConfig;
|
|
changes: string[];
|
|
} {
|
|
const rawEntry = asNullableRecord(cfg.plugins?.entries?.codex);
|
|
const rawPluginConfig = asNullableRecord(rawEntry?.config);
|
|
const rawCodexPlugins = asNullableRecord(rawPluginConfig?.codexPlugins);
|
|
const rawAppServer = asNullableRecord(rawPluginConfig?.appServer);
|
|
const shouldRemoveDynamicToolsProfile =
|
|
rawPluginConfig !== null && hasRetiredDynamicToolsProfile(rawPluginConfig);
|
|
const shouldRewriteDestructivePolicy = hasLegacyPluginDestructivePolicy(rawCodexPlugins);
|
|
const shouldRewriteApprovalPolicy = hasRetiredApprovalPolicy(rawAppServer);
|
|
if (
|
|
!rawPluginConfig ||
|
|
(!shouldRemoveDynamicToolsProfile &&
|
|
!shouldRewriteDestructivePolicy &&
|
|
!shouldRewriteApprovalPolicy)
|
|
) {
|
|
return { config: cfg, changes: [] };
|
|
}
|
|
|
|
const nextConfig = structuredClone(cfg) as OpenClawConfig & {
|
|
plugins?: Record<string, unknown>;
|
|
};
|
|
const nextPlugins = asNullableRecord(nextConfig.plugins);
|
|
const nextEntries = asNullableRecord(nextPlugins?.entries);
|
|
const nextEntry = asNullableRecord(nextEntries?.codex);
|
|
const nextPluginConfig = asNullableRecord(nextEntry?.config);
|
|
if (!nextPluginConfig) {
|
|
return { config: cfg, changes: [] };
|
|
}
|
|
|
|
const changes: string[] = [];
|
|
if (shouldRemoveDynamicToolsProfile) {
|
|
delete nextPluginConfig.codexDynamicToolsProfile;
|
|
changes.push(
|
|
"Removed retired plugins.entries.codex.config.codexDynamicToolsProfile; Codex app-server always keeps Codex-native workspace tools native.",
|
|
);
|
|
}
|
|
|
|
if (shouldRewriteDestructivePolicy) {
|
|
const nextCodexPlugins = asNullableRecord(nextPluginConfig.codexPlugins);
|
|
if (nextCodexPlugins?.allow_destructive_actions === "on-request") {
|
|
nextCodexPlugins.allow_destructive_actions = "auto";
|
|
}
|
|
const nextPluginPolicies = asNullableRecord(nextCodexPlugins?.plugins);
|
|
for (const plugin of Object.values(nextPluginPolicies ?? {})) {
|
|
const nextPlugin = asNullableRecord(plugin);
|
|
if (nextPlugin?.allow_destructive_actions === "on-request") {
|
|
nextPlugin.allow_destructive_actions = "auto";
|
|
}
|
|
}
|
|
changes.push(
|
|
'Renamed plugins.entries.codex.config.codexPlugins allow_destructive_actions="on-request" values to "auto".',
|
|
);
|
|
}
|
|
|
|
if (shouldRewriteApprovalPolicy) {
|
|
const nextAppServer = asNullableRecord(nextPluginConfig.appServer);
|
|
if (
|
|
nextAppServer?.approvalPolicy === "on-failure" ||
|
|
nextAppServer?.approvalPolicy === "untrusted"
|
|
) {
|
|
nextAppServer.approvalPolicy = "on-request";
|
|
}
|
|
changes.push(
|
|
'Renamed retired plugins.entries.codex.config.appServer.approvalPolicy to "on-request".',
|
|
);
|
|
}
|
|
|
|
return {
|
|
config: nextConfig,
|
|
changes,
|
|
};
|
|
}
|
|
|
|
export { stateMigrations } from "./src/migration/session-binding-sidecars.js";
|