fix: stabilize sub2api codex pool operations
This commit is contained in:
@@ -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>> {
|
||||
|
||||
Reference in New Issue
Block a user