Tighten Codex MCP schema normalization

This commit is contained in:
Mohamed Boudra
2025-12-25 01:04:25 +07:00
parent e546009190
commit 4221df1e2d
4 changed files with 744 additions and 268 deletions
@@ -2,6 +2,8 @@ import type { Options as ClaudeAgentOptions } from "@anthropic-ai/claude-agent-s
export type AgentProvider = "codex" | "codex-mcp" | "claude";
export type AgentMetadata = { [key: string]: unknown };
export type AgentMode = {
id: string;
label: string;
@@ -14,7 +16,7 @@ export type AgentModelDefinition = {
label: string;
description?: string;
isDefault?: boolean;
metadata?: Record<string, unknown>;
metadata?: AgentMetadata;
};
export type AgentCapabilityFlags = {
@@ -31,7 +33,7 @@ export type AgentPersistenceHandle = {
sessionId: string;
/** Provider specific handle (Codex thread id, Claude resume token, etc). */
nativeHandle?: string;
metadata?: Record<string, unknown>;
metadata?: AgentMetadata;
};
export type AgentPromptInput = string | { type: "text"; text: string }[];
@@ -91,7 +93,7 @@ export type AgentStreamEvent =
export type AgentPermissionRequestKind = "tool" | "plan" | "mode" | "other";
export type AgentPermissionUpdate = Record<string, unknown>;
export type AgentPermissionUpdate = AgentMetadata;
export type AgentPermissionRequest = {
id: string;
@@ -100,15 +102,15 @@ export type AgentPermissionRequest = {
kind: AgentPermissionRequestKind;
title?: string;
description?: string;
input?: Record<string, unknown>;
input?: AgentMetadata;
suggestions?: AgentPermissionUpdate[];
metadata?: Record<string, unknown>;
metadata?: AgentMetadata;
};
export type AgentPermissionResponse =
| {
behavior: "allow";
updatedInput?: Record<string, unknown>;
updatedInput?: AgentMetadata;
updatedPermissions?: AgentPermissionUpdate[];
}
| {
@@ -129,7 +131,7 @@ export type AgentRuntimeInfo = {
sessionId: string | null;
model?: string | null;
modeId?: string | null;
extra?: Record<string, unknown>;
extra?: AgentMetadata;
};
export type AgentControlMcpConfig = {
@@ -164,10 +166,10 @@ export type AgentSessionConfig = {
reasoningEffort?: string;
agentControlMcp?: AgentControlMcpConfig;
extra?: {
codex?: Record<string, unknown>;
codex?: AgentMetadata;
claude?: Partial<ClaudeAgentOptions>;
};
mcpServers?: Record<string, unknown>;
mcpServers?: AgentMetadata;
parentAgentId?: string;
};
@@ -110,22 +110,19 @@ function providerFromEvent(event: AgentStreamEvent): string | undefined {
return event.provider;
}
function firstNumber(values: Array<number | undefined>): number | undefined {
for (const value of values) {
if (value !== undefined) {
return value;
}
function resolveExclusiveValue<T>(
label: string,
entries: Array<{ key: string; value: T | undefined }>
): T | undefined {
const present = entries.filter((entry) => entry.value !== undefined);
if (present.length === 0) {
return undefined;
}
return undefined;
}
function firstString(values: Array<string | undefined>): string | undefined {
for (const value of values) {
if (value !== undefined) {
return value;
}
if (present.length > 1) {
const keys = present.map((entry) => entry.key).join(", ");
throw new Error(`${label} provided multiple times (${keys})`);
}
return undefined;
return present[0].value;
}
const CommandInputSchema = z.object({
@@ -152,7 +149,10 @@ function extractExitCode(output: unknown): number | undefined {
if (!parsed.success) {
return undefined;
}
const direct = firstNumber([parsed.data.exitCode, parsed.data.exit_code]);
const direct = resolveExclusiveValue("exit code", [
{ key: "exitCode", value: parsed.data.exitCode },
{ key: "exit_code", value: parsed.data.exit_code },
]);
if (direct !== undefined) {
return direct;
}
@@ -160,7 +160,10 @@ function extractExitCode(output: unknown): number | undefined {
if (!metaParsed.success) {
return undefined;
}
return firstNumber([metaParsed.data.exitCode, metaParsed.data.exit_code]);
return resolveExclusiveValue("exit code metadata", [
{ key: "exitCode", value: metaParsed.data.exitCode },
{ key: "exit_code", value: metaParsed.data.exit_code },
]);
}
function commandTextFromInput(input: unknown): string | null {
@@ -187,7 +190,11 @@ function commandOutputText(output: unknown): string | null {
if (!record.success) {
return null;
}
const text = firstString([record.data.output, record.data.stdout, record.data.stderr]);
const text = resolveExclusiveValue("command output text", [
{ key: "output", value: record.data.output },
{ key: "stdout", value: record.data.stdout },
{ key: "stderr", value: record.data.stderr },
]);
return text ? text : null;
}
File diff suppressed because it is too large Load Diff