fix: stabilize sub2api codex pool operations

This commit is contained in:
Codex
2026-07-01 15:52:22 +00:00
parent 8f54b591d7
commit 113b6809d1
16 changed files with 509 additions and 59 deletions
@@ -26,11 +26,11 @@ import { desiredAccountNames } from "./accounts";
import { collectCodexProfiles, readCodexPoolConfig } from "./config";
import { codexPoolSentinelProbeConfigFingerprint, fingerprint } from "./config-utils";
import { apiKeyPreview, codexConsumerBaseUrl, fetchPoolApiKey, probePublicModels, validatePublicGatewayWithKey, writeLocalCodexConfig } from "./local-codex";
import { manualBindingSourcePlan, poolTarget, prepareTargetPublicExposureSecret, resolvedManualAccountProtections, secretMaterialSummary, sentinelProfileSecrets, targetFrpPublicExposure, targetPublicExposureApplyScript, targetPublicExposureSummary } from "./public-exposure";
import { manualBindingSourcePlan, poolTarget, prepareTargetPublicExposureSecret, protectedManualAccountNamesForTarget, resolvedManualAccountProtections, secretMaterialSummary, sentinelProfileSecrets, targetFrpPublicExposure, targetPublicExposureApplyScript, targetPublicExposureSummary } from "./public-exposure";
import { codexPoolConfigSummary, compactProfile, compactSentinelProbeResult, redactProfile, renderSub2ApiTempUnschedulableCredentials } from "./redaction";
import { boolField, capture, compactCapture, parseJsonOutput, runRemoteCodexPoolScript } from "./remote";
import { cleanupProbesScript, sentinelProbeScript, sentinelReportScript, syncScript, traceScript, validateScript } from "./remote-scripts";
import { codexPoolSyncSummary, codexPoolValidationSummary, renderSentinelReport, renderTraceReport, renderedCliResult } from "./render";
import { cleanupProbesScript, sentinelImageBuildScript, sentinelImageStatusScript, sentinelProbeScript, sentinelReportScript, syncScript, traceScript, validateScript } from "./remote-scripts";
import { codexPoolSyncSummary, codexPoolValidationSummary, renderCodexPoolPlan, renderCodexPoolSentinelProbeResult, renderCodexPoolSyncResult, renderCodexPoolValidateResult, renderSentinelReport, renderTraceReport, renderedCliResult } from "./render";
import { codexPoolRuntimeTarget, defaultCodexPoolRuntimeTargetId, targetFlag } from "./runtime-target";
import { codexPoolConfigPath, serviceName, sub2apiConfigPath } from "./types";
@@ -84,7 +84,7 @@ export function codexPoolPlan(options?: DisclosureOptions): Record<string, unkno
};
}
export async function codexPoolSync(config: UniDeskConfig, options: SyncOptions): Promise<Record<string, unknown>> {
export async function codexPoolSync(config: UniDeskConfig, options: SyncOptions): Promise<Record<string, unknown> | RenderedCliResult> {
const pool = readCodexPoolConfig();
const runtimeTarget = codexPoolRuntimeTarget(options.targetId);
const profiles = collectCodexProfiles();
@@ -108,7 +108,7 @@ export async function codexPoolSync(config: UniDeskConfig, options: SyncOptions)
};
}
if (!options.confirm || !planOk) {
return {
const plan = {
...codexPoolPlan(options),
ok: !options.confirm ? planOk : false,
mode: options.confirm ? "blocked-invalid-local-profile" : "dry-run",
@@ -116,6 +116,7 @@ export async function codexPoolSync(config: UniDeskConfig, options: SyncOptions)
? { fix: "Repair invalid local Codex profiles, then rerun sync --confirm." }
: { confirm: "bun scripts/cli.ts platform-infra sub2api codex-pool sync --confirm" },
};
return options.full || options.raw ? plan : renderCodexPoolPlan(plan);
}
const sentinelImage = pool.sentinel.monitor.enabled && runtimeTarget.sentinelEnabled
@@ -138,7 +139,7 @@ export async function codexPoolSync(config: UniDeskConfig, options: SyncOptions)
sentinel: {
enabledForTarget: runtimeTarget.sentinelEnabled,
manifest: runtimeTarget.sentinelEnabled
? renderCodexPoolSentinelManifest(pool.sentinel, sentinelProfileSecrets(profiles), {
? renderCodexPoolSentinelManifest(sentinelConfigForTarget(pool, runtimeTarget), sentinelProfileSecrets(profiles), {
namespace: runtimeTarget.namespace,
serviceName: runtimeTarget.serviceName,
serviceDns: runtimeTarget.serviceDns,
@@ -150,7 +151,7 @@ export async function codexPoolSync(config: UniDeskConfig, options: SyncOptions)
} : null,
})
: null,
summary: codexPoolSentinelSummary(pool.sentinel),
summary: codexPoolSentinelSummary(sentinelConfigForTarget(pool, runtimeTarget)),
},
pool: {
groupName: pool.groupName,
@@ -213,9 +214,14 @@ export async function codexPoolSync(config: UniDeskConfig, options: SyncOptions)
parsed,
};
}
return {
const response = {
ok: result.exitCode === 0 && boolField(parsed, "ok", false),
action: "platform-infra-sub2api-codex-pool-sync",
target: {
id: runtimeTarget.id,
route: runtimeTarget.route,
namespace: runtimeTarget.namespace,
},
local: {
profileCount: profiles.length,
pruneRemoved: options.pruneRemoved,
@@ -231,6 +237,7 @@ export async function codexPoolSync(config: UniDeskConfig, options: SyncOptions)
validate: `bun scripts/cli.ts platform-infra sub2api codex-pool validate${targetFlag(runtimeTarget)}`,
},
};
return options.full ? response : renderCodexPoolSyncResult(response);
}
export async function codexPoolSentinelImage(config: UniDeskConfig, options: SentinelImageOptions): Promise<Record<string, unknown>> {
@@ -258,7 +265,7 @@ export async function runCodexPoolSentinelImage(config: UniDeskConfig, pool: Cod
}
const summary = {
ok: true,
mode: options.action === "status" ? "base-image-runtime" : options.dryRun ? "dry-run-base-image-runtime" : "skipped-build-base-image-runtime",
mode: options.action === "status" ? "status" : options.dryRun ? "dry-run" : "build",
target: {
id: runtimeTarget.id,
namespace: runtimeTarget.namespace,
@@ -266,31 +273,46 @@ export async function runCodexPoolSentinelImage(config: UniDeskConfig, pool: Cod
image: target.runtimeImage,
baseImage: target.baseImage,
openaiPythonVersion: pool.sentinel.sdk.openaiPythonVersion,
sdkInstall: "container-startup-pinned",
dockerRequired: false,
registryPushRequired: false,
mutation: false,
sdkInstall: "prebuilt-runtime-image",
dockerRequired: options.action === "status" || !options.dryRun,
registryPushRequired: options.action === "build" && !options.dryRun,
mutation: options.action === "build" && !options.dryRun,
valuesPrinted: false,
};
const script = options.action === "build" && !options.dryRun
? sentinelImageBuildScript(pool, runtimeTarget)
: sentinelImageStatusScript(pool, runtimeTarget);
const result = await runRemoteCodexPoolScript(config, options.action === "build" && !options.dryRun ? "sentinel-image-build" : "sentinel-image-status", script, runtimeTarget);
const parsed = parseJsonOutput(result.stdout);
const ok = result.exitCode === 0 && boolField(parsed, "ok", options.dryRun);
if (options.raw) {
return {
ok: true,
ok,
action: "platform-infra-sub2api-codex-pool-sentinel-image",
mode: options.action,
mode: summary.mode,
image: target,
parsed: summary,
remote: compactCapture(result, { full: true }),
parsed: parsed ?? summary,
};
}
return {
ok: true,
ok,
action: "platform-infra-sub2api-codex-pool-sentinel-image",
mode: options.action,
mode: summary.mode,
image: target,
summary,
summary: parsed === null ? summary : { ...summary, ...parsed },
remote: compactCapture(result, { full: options.full || result.exitCode !== 0 }),
};
}
export async function codexPoolValidate(config: UniDeskConfig, options: DisclosureOptions): Promise<Record<string, unknown>> {
function sentinelConfigForTarget(pool: CodexPoolConfig, target: ReturnType<typeof codexPoolRuntimeTarget>): CodexPoolConfig["sentinel"] {
return {
...pool.sentinel,
protectedManualAccounts: protectedManualAccountNamesForTarget(pool, target),
};
}
export async function codexPoolValidate(config: UniDeskConfig, options: DisclosureOptions): Promise<Record<string, unknown> | RenderedCliResult> {
const pool = readCodexPoolConfig();
const runtimeTarget = codexPoolRuntimeTarget(options.targetId);
const result = await runRemoteCodexPoolScript(config, "validate", validateScript(pool, runtimeTarget), runtimeTarget);
@@ -303,12 +325,18 @@ export async function codexPoolValidate(config: UniDeskConfig, options: Disclosu
parsed,
};
}
return {
const response = {
ok: result.exitCode === 0 && boolField(parsed, "ok", false),
action: "platform-infra-sub2api-codex-pool-validate",
target: {
id: runtimeTarget.id,
route: runtimeTarget.route,
namespace: runtimeTarget.namespace,
},
summary: options.full ? parsed : codexPoolValidationSummary(parsed),
remote: compactCapture(result, { full: options.full || result.exitCode !== 0 }),
};
return options.full ? response : renderCodexPoolValidateResult(response);
}
export async function codexPoolTrace(config: UniDeskConfig, options: TraceOptions): Promise<Record<string, unknown> | RenderedCliResult> {
@@ -357,10 +385,10 @@ export async function codexPoolSentinelReport(config: UniDeskConfig, options: Se
return renderedCliResult(ok, "platform-infra sub2api codex-pool sentinel-report", text);
}
export async function codexPoolSentinelProbe(config: UniDeskConfig, options: SentinelProbeOptions): Promise<Record<string, unknown>> {
export async function codexPoolSentinelProbe(config: UniDeskConfig, options: SentinelProbeOptions): Promise<Record<string, unknown> | RenderedCliResult> {
const pool = readCodexPoolConfig();
const runtimeTarget = codexPoolRuntimeTarget(options.targetId);
const protectedNames = new Set(pool.manualAccounts.protected.map((account) => account.accountName.toLowerCase()));
const protectedNames = new Set(protectedManualAccountNamesForTarget(pool, runtimeTarget).map((account) => account.toLowerCase()));
const protectedRequested = options.accounts.filter((account) => protectedNames.has(account.toLowerCase()));
if (protectedRequested.length > 0) {
return {
@@ -403,20 +431,28 @@ export async function codexPoolSentinelProbe(config: UniDeskConfig, options: Sen
};
const result = await runRemoteCodexPoolScript(config, "sentinel-probe", sentinelProbeScript(payload, pool, runtimeTarget), runtimeTarget);
const parsed = parseJsonOutput(result.stdout);
const summary = compactSentinelProbeResult(parsed);
const ok = summary?.ok === true || (result.exitCode === 0 && boolField(parsed, "ok", false));
if (options.raw) {
return {
ok: result.exitCode === 0 && boolField(parsed, "ok", false),
ok,
action: "platform-infra-sub2api-codex-pool-sentinel-probe",
remote: compactCapture(result, { full: true }),
parsed,
};
}
return {
ok: result.exitCode === 0 && boolField(parsed, "ok", false),
const response = {
ok,
action: "platform-infra-sub2api-codex-pool-sentinel-probe",
summary: options.full ? parsed : compactSentinelProbeResult(parsed),
target: {
id: runtimeTarget.id,
route: runtimeTarget.route,
namespace: runtimeTarget.namespace,
},
summary: options.full ? parsed : summary,
remote: compactCapture(result, { full: options.full || result.exitCode !== 0 }),
};
return options.full ? response : renderCodexPoolSentinelProbeResult(response);
}
export async function codexPoolCleanupProbes(config: UniDeskConfig, options: ConfirmOptions): Promise<Record<string, unknown>> {