Files
openclaw/extensions/codex/src/app-server/binding-connection.ts
Peter Steinberger f94a7dc183 feat(codex): supervise native Codex sessions (#104045)
* feat(codex): add native session supervision

* fix(codex): harden supervision integration

* fix(codex): preserve locked harness ownership

* fix(codex): fence native session archive

* fix(codex): revalidate archive binding ownership

* feat(codex): integrate supervision runtime

* feat(sessions): preserve harness-owned execution

* feat(sessions): persist harness ownership invariants

* feat(gateway): enforce harness-owned sessions

* feat(setup): enable detected Codex supervision

* feat(mac): expose supervised Codex sessions

* feat(ui): make Codex sessions actionable

* docs(codex): document session supervision

* test(codex): cover integration ownership

* chore(i18n): refresh supervision inventories

* fix(setup): finalize Codex activation atomically

* test(codex): narrow binding store update

* fix(sessions): preserve legacy model locks

* test(macos): serialize Codex catalog fixtures

* fix(sessions): preserve legacy lock admission

* chore(i18n): reconcile supervision metadata

* test(sessions): mark legacy lock fixture

* fix(macos): drain final Codex catalog frame

* docs: leave supervision note to release

* style(macos): satisfy Codex catalog type length

* chore: record session accessor seam owners

* fix(macos): honor configured Codex supervision

* fix(codex): preserve harness-owned model locks

* fix(codex): satisfy supervision lint gates

* chore(i18n): refresh native supervision inventory

* fix(codex): align supervision validation contracts

* fix(codex): close supervision boundary gaps

* fix(codex): preserve supervision activation contracts

* fix(codex): dispose standalone supervision runtime

* fix(codex): pin supervised source connection

* fix(plugins): bind delegated runs to exact session target

* fix(codex): scope supervised sessions to configured agents

* fix(codex): fingerprint effective supervision home

* fix(codex): normalize supervision plugin policy

* fix(codex): keep supervised bindings stable across upgrades

* fix(codex): guard all supervised binding connections

* fix(codex): preserve catalog filters and pending CAS identity

* fix(codex): preserve supervision identity for diagnostics

* fix(codex): bind uncertain commits to supervision connection

* fix(codex): satisfy supervision type boundaries

* fix(macos): reconcile current main validation

* fix(codex): handle absent runtime config in supervision

* fix(doctor): own local audio acceleration check

* fix(codex): satisfy integration lint gates

* fix(codex): satisfy lifecycle safety guards
2026-07-11 00:12:08 -07:00

89 lines
3.3 KiB
TypeScript

// Codex helper module selects an app-server connection from private binding ownership.
import {
readCodexPluginConfig,
resolveCodexAppServerRuntimeOptions,
resolveCodexSupervisionAppServerRuntimeOptions,
type CodexAppServerRuntimeOptions,
} from "./config.js";
import { buildCodexAppServerConnectionFingerprint } from "./plugin-app-cache-key.js";
import type { CodexAppServerThreadBinding } from "./session-binding.js";
type CodexAppServerRuntimeOptionsParams = NonNullable<
Parameters<typeof resolveCodexAppServerRuntimeOptions>[0]
>;
export type CodexBindingAppServerConnection = {
appServer: CodexAppServerRuntimeOptions;
usesSupervisionConnection: boolean;
requestAuthProfileId: string | undefined;
clientAuthProfileId: string | null | undefined;
};
export type CodexSupervisionModelSelection = {
model: string;
modelProvider: string;
};
/** Requires the native model pair after a supervised pending branch has materialized. */
export function requireCodexSupervisionModelSelection(
binding: Pick<CodexAppServerThreadBinding, "connectionScope" | "model" | "modelProvider">,
): CodexSupervisionModelSelection {
const model = binding.model?.trim();
const modelProvider = binding.modelProvider?.trim();
if (binding.connectionScope !== "supervision" || !model || !modelProvider) {
throw new Error(
"Codex supervised binding is missing its native model and provider; refusing request selection",
);
}
return { model, modelProvider };
}
/** Resolves connection and auth ownership exclusively from the private thread binding. */
export function resolveCodexBindingAppServerConnection(
params: CodexAppServerRuntimeOptionsParams & {
binding?: Pick<
CodexAppServerThreadBinding,
"appServerRuntimeFingerprint" | "connectionScope" | "pendingSupervisionBranch"
>;
authProfileId?: string;
},
): CodexBindingAppServerConnection {
const { binding, authProfileId, ...runtimeParams } = params;
const usesSupervisionConnection = binding?.connectionScope === "supervision";
if (
usesSupervisionConnection &&
readCodexPluginConfig(runtimeParams.pluginConfig).supervision?.enabled !== true
) {
throw new Error(
"Codex supervision is disabled; refusing to open a native user-home supervised session",
);
}
const appServer = (
usesSupervisionConnection
? resolveCodexSupervisionAppServerRuntimeOptions
: resolveCodexAppServerRuntimeOptions
)(runtimeParams);
if (usesSupervisionConnection) {
// Thread ids are connection-local. Every binding-owned operation must reject
// config drift before a copied id can reach another native Codex store.
const persistedFingerprint =
binding.pendingSupervisionBranch?.connectionFingerprint ??
binding.appServerRuntimeFingerprint;
const currentFingerprint = buildCodexAppServerConnectionFingerprint(
appServer,
runtimeParams.agentDir,
);
if (!persistedFingerprint || persistedFingerprint !== currentFingerprint) {
throw new Error(
"Codex supervision connection changed; refusing to operate on its bound native thread",
);
}
}
return {
appServer,
usesSupervisionConnection,
requestAuthProfileId: usesSupervisionConnection ? undefined : authProfileId,
clientAuthProfileId: usesSupervisionConnection ? null : authProfileId,
};
}