Files
openclaw/extensions/codex/harness.ts
Kaspre 69a0c925b8 fix(codex): cover side-question native hooks (#82559)
* fix(codex): cover side-question native hooks

* fix(codex): enforce native approvals for app-server requests

* fix(codex): preserve approval fallback after native relay noop

* fix(codex): satisfy approval relay json typing

* fix(codex): run approval relay in report mode

* fix(codex): keep relay pre-tool decisions deny-only

* fix(codex): remove dead relay approval branch

* fix(codex): dedupe app-server relay approvals

* fix(codex): fail closed on native relay rewrites

* fix(codex): preserve side-question provider context

* fix(codex): route side-question replies to origin

* fix(codex): preserve native hook channel context

* test(codex): align native relay rewrite assertion

* fix(codex): align side-question hook config

* fix(codex): route side-question approvals safely

* test(codex): fix side-question hook typing

* fix(codex): preserve side-question hook policy context

* fix(codex): close native hook relay review gaps

* fix(codex): keep dynamic tool hook channel context

* fix(codex): preserve native finalize hook channel context

* fix(codex): scope dynamic tool result hooks by channel

* fix(codex): drop stale deadcode allowlist entry

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-17 12:02:17 +01:00

70 lines
2.4 KiB
TypeScript

import type { AgentHarness } from "openclaw/plugin-sdk/agent-harness-runtime";
import type {
CodexAppServerListModelsOptions,
CodexAppServerModel,
CodexAppServerModelListResult,
} from "./src/app-server/models.js";
const DEFAULT_CODEX_HARNESS_PROVIDER_IDS = new Set(["codex"]);
export type { CodexAppServerListModelsOptions, CodexAppServerModel, CodexAppServerModelListResult };
export function createCodexAppServerAgentHarness(options?: {
id?: string;
label?: string;
providerIds?: Iterable<string>;
pluginConfig?: unknown;
}): AgentHarness {
const providerIds = new Set(
[...(options?.providerIds ?? DEFAULT_CODEX_HARNESS_PROVIDER_IDS)].map((id) =>
id.trim().toLowerCase(),
),
);
return {
id: options?.id ?? "codex",
label: options?.label ?? "Codex agent harness",
deliveryDefaults: {
sourceVisibleReplies: "message_tool",
},
supports: (ctx) => {
const provider = ctx.provider.trim().toLowerCase();
if (providerIds.has(provider)) {
return { supported: true, priority: 100 };
}
return {
supported: false,
reason: `provider is not one of: ${[...providerIds].toSorted().join(", ")}`,
};
},
runAttempt: async (params) => {
const { runCodexAppServerAttempt } = await import("./src/app-server/run-attempt.js");
return runCodexAppServerAttempt(params, {
pluginConfig: options?.pluginConfig,
nativeHookRelay: { enabled: true },
});
},
runSideQuestion: async (params) => {
const { runCodexAppServerSideQuestion } = await import("./src/app-server/side-question.js");
return runCodexAppServerSideQuestion(params, {
pluginConfig: options?.pluginConfig,
nativeHookRelay: { enabled: true },
});
},
compact: async (params) => {
const { maybeCompactCodexAppServerSession } = await import("./src/app-server/compact.js");
return maybeCompactCodexAppServerSession(params, { pluginConfig: options?.pluginConfig });
},
reset: async (params) => {
if (params.sessionFile) {
const { clearCodexAppServerBinding } = await import("./src/app-server/session-binding.js");
await clearCodexAppServerBinding(params.sessionFile);
}
},
dispose: async () => {
const { clearSharedCodexAppServerClientAndWait } =
await import("./src/app-server/shared-client.js");
await clearSharedCodexAppServerClientAndWait();
},
};
}