refactor: normalize sub2api target defaults (#352)
Co-authored-by: Codex <codex@noreply.local>
This commit is contained in:
@@ -18,13 +18,8 @@ import {
|
||||
import { runSshCommandCapture, type SshCaptureResult } from "./ssh";
|
||||
|
||||
const g14K3sRoute = "G14:k3s";
|
||||
const defaultTargetId = "D601";
|
||||
const defaultTargetRoute = "D601:k3s";
|
||||
const namespace = "platform-infra";
|
||||
const serviceName = "sub2api";
|
||||
const serviceDns = `${serviceName}.${namespace}.svc.cluster.local:8080`;
|
||||
const fieldManager = "unidesk-platform-infra";
|
||||
const appSecretName = "sub2api-secrets";
|
||||
const sub2apiConfigPath = rootPath("config", "platform-infra", "sub2api.yaml");
|
||||
const codexPoolConfigPath = rootPath("config", "platform-infra", "sub2api-codex-pool.yaml");
|
||||
const sentinelImageDockerfilePath = rootPath("src", "components", "platform-infra", "sub2api", "sentinel.Dockerfile");
|
||||
@@ -242,6 +237,7 @@ interface CodexLocalConsumerTomlOptions {
|
||||
|
||||
export function codexPoolHelp(): unknown {
|
||||
const pool = readCodexPoolConfig();
|
||||
const runtimeTarget = codexPoolRuntimeTarget();
|
||||
return {
|
||||
command: "platform-infra sub2api codex-pool plan|sync|validate|trace|sentinel-image|sentinel-probe|sentinel-report|cleanup-probes|expose|configure-local",
|
||||
output: "json, except trace and sentinel-report default to low-noise text tables",
|
||||
@@ -261,14 +257,15 @@ export function codexPoolHelp(): unknown {
|
||||
],
|
||||
description: "Import YAML-selected ~/.codex API-key profiles into one Sub2API OpenAI pool, expose one unified API_KEY, and optionally configure this master server's ~/.codex consumer endpoint.",
|
||||
target: {
|
||||
route: g14K3sRoute,
|
||||
namespace,
|
||||
serviceDns,
|
||||
default: runtimeTarget.id,
|
||||
route: runtimeTarget.route,
|
||||
namespace: runtimeTarget.namespace,
|
||||
serviceDns: runtimeTarget.serviceDns,
|
||||
configPath: codexPoolConfigPath,
|
||||
poolGroupName: pool.groupName,
|
||||
poolApiKeySecretName: pool.apiKeySecretName,
|
||||
poolApiKeySecretKey: pool.apiKeySecretKey,
|
||||
publicBaseUrl: pool.publicExposure.enabled ? pool.publicExposure.publicBaseUrl : null,
|
||||
publicBaseUrl: pool.publicExposure.enabled ? pool.publicExposure.publicBaseUrl : runtimeTarget.publicBaseUrl,
|
||||
masterBaseUrl: pool.publicExposure.enabled ? pool.publicExposure.masterBaseUrl : null,
|
||||
sentinelMonitorEnabled: pool.sentinel.monitor.enabled,
|
||||
sentinelActionsEnabled: pool.sentinel.actions.enabled,
|
||||
@@ -527,7 +524,7 @@ function parseDisclosureOptions(args: string[]): DisclosureOptions {
|
||||
}
|
||||
|
||||
function parseTargetId(args: string[]): string {
|
||||
let targetId = defaultTargetId;
|
||||
let targetId: string | null = null;
|
||||
for (let index = 0; index < args.length; index += 1) {
|
||||
const arg = args[index]!;
|
||||
if (arg === "--target") {
|
||||
@@ -539,8 +536,9 @@ function parseTargetId(args: string[]): string {
|
||||
}
|
||||
if (arg.startsWith("--target=")) targetId = arg.slice("--target=".length);
|
||||
}
|
||||
if (!/^[A-Za-z0-9._-]+$/u.test(targetId)) throw new Error("--target must be a simple target id");
|
||||
return targetId;
|
||||
const resolvedTargetId = targetId ?? defaultCodexPoolRuntimeTargetId();
|
||||
if (!/^[A-Za-z0-9._-]+$/u.test(resolvedTargetId)) throw new Error("--target must be a simple target id");
|
||||
return resolvedTargetId;
|
||||
}
|
||||
|
||||
function splitAccountNames(value: string): string[] {
|
||||
@@ -564,15 +562,45 @@ function stripBooleanOptions(args: string[], stripped: Set<string>): string[] {
|
||||
return args.filter((arg) => !stripped.has(arg));
|
||||
}
|
||||
|
||||
function codexPoolRuntimeTarget(targetId: string = defaultTargetId): CodexPoolRuntimeTarget {
|
||||
interface Sub2ApiRuntimeConfig {
|
||||
defaultTargetId: string;
|
||||
appSecretName: string;
|
||||
targets: Record<string, unknown>[];
|
||||
}
|
||||
|
||||
function readSub2ApiRuntimeConfig(): Sub2ApiRuntimeConfig {
|
||||
const parsed = Bun.YAML.parse(readFileSync(sub2apiConfigPath, "utf8")) as unknown;
|
||||
if (!isRecord(parsed) || !Array.isArray(parsed.targets)) throw new Error(`${sub2apiConfigPath}.targets must be a list`);
|
||||
const raw = parsed.targets.find((item) => isRecord(item) && String(item.id ?? "").toLowerCase() === targetId.toLowerCase());
|
||||
if (!isRecord(parsed)) throw new Error(`${sub2apiConfigPath} must contain a YAML object`);
|
||||
const defaults = isRecord(parsed.defaults) ? parsed.defaults : null;
|
||||
const defaultTargetId = defaults === null ? null : stringValue(defaults.targetId);
|
||||
if (defaultTargetId === null || !/^[A-Za-z0-9._-]+$/u.test(defaultTargetId)) throw new Error(`${sub2apiConfigPath}.defaults.targetId must be a simple target id`);
|
||||
const runtime = isRecord(parsed.runtime) ? parsed.runtime : null;
|
||||
const database = runtime !== null && isRecord(runtime.database) ? runtime.database : null;
|
||||
const appSecretName = database === null ? null : stringValue(database.secretName);
|
||||
if (appSecretName === null) throw new Error(`${sub2apiConfigPath}.runtime.database.secretName is required`);
|
||||
validateKubernetesName(appSecretName, `${sub2apiConfigPath}.runtime.database.secretName`, true);
|
||||
if (!Array.isArray(parsed.targets) || !parsed.targets.every(isRecord)) throw new Error(`${sub2apiConfigPath}.targets must be a list`);
|
||||
return {
|
||||
defaultTargetId,
|
||||
appSecretName,
|
||||
targets: parsed.targets,
|
||||
};
|
||||
}
|
||||
|
||||
function defaultCodexPoolRuntimeTargetId(): string {
|
||||
return readSub2ApiRuntimeConfig().defaultTargetId;
|
||||
}
|
||||
|
||||
function codexPoolRuntimeTarget(targetId?: string): CodexPoolRuntimeTarget {
|
||||
const runtimeConfig = readSub2ApiRuntimeConfig();
|
||||
const resolvedTargetId = targetId ?? runtimeConfig.defaultTargetId;
|
||||
const raw = runtimeConfig.targets.find((item) => String(item.id ?? "").toLowerCase() === resolvedTargetId.toLowerCase());
|
||||
if (!isRecord(raw)) throw new Error(`${sub2apiConfigPath}.targets does not contain target ${targetId}`);
|
||||
const id = stringValue(raw.id) ?? targetId;
|
||||
const route = stringValue(raw.route) ?? (id === defaultTargetId ? defaultTargetRoute : "");
|
||||
const targetNamespace = stringValue(raw.namespace) ?? namespace;
|
||||
const id = stringValue(raw.id) ?? resolvedTargetId;
|
||||
const route = stringValue(raw.route) ?? "";
|
||||
const targetNamespace = stringValue(raw.namespace);
|
||||
if (route.length === 0) throw new Error(`${sub2apiConfigPath}.targets[${id}].route is required`);
|
||||
if (targetNamespace === null) throw new Error(`${sub2apiConfigPath}.targets[${id}].namespace is required`);
|
||||
validateKubernetesName(targetNamespace, `${sub2apiConfigPath}.targets[${id}].namespace`, true);
|
||||
|
||||
let egressProxy: CodexPoolRuntimeTarget["egressProxy"] = null;
|
||||
@@ -605,18 +633,19 @@ function codexPoolRuntimeTarget(targetId: string = defaultTargetId): CodexPoolRu
|
||||
serviceName,
|
||||
serviceDns: `${serviceName}.${targetNamespace}.svc.cluster.local:8080`,
|
||||
publicBaseUrl,
|
||||
appSecretName,
|
||||
appSecretName: runtimeConfig.appSecretName,
|
||||
egressProxy,
|
||||
};
|
||||
}
|
||||
|
||||
function targetFlag(target: CodexPoolRuntimeTarget): string {
|
||||
return target.id === defaultTargetId ? "" : ` --target ${target.id}`;
|
||||
return target.id === defaultCodexPoolRuntimeTargetId() ? "" : ` --target ${target.id}`;
|
||||
}
|
||||
|
||||
function codexPoolPlan(options: DisclosureOptions = { full: false, raw: false, targetId: defaultTargetId }): Record<string, unknown> {
|
||||
function codexPoolPlan(options?: DisclosureOptions): Record<string, unknown> {
|
||||
const resolvedOptions = options ?? { full: false, raw: false, targetId: defaultCodexPoolRuntimeTargetId() };
|
||||
const pool = readCodexPoolConfig();
|
||||
const runtimeTarget = codexPoolRuntimeTarget(options.targetId);
|
||||
const runtimeTarget = codexPoolRuntimeTarget(resolvedOptions.targetId);
|
||||
const profiles = collectCodexProfiles();
|
||||
const ok = profiles.length > 0 && profiles.every((profile) => profile.ok);
|
||||
const consumerBaseUrl = codexConsumerBaseUrl(pool, runtimeTarget);
|
||||
@@ -973,12 +1002,13 @@ async function codexPoolCleanupProbes(config: UniDeskConfig, options: ConfirmOpt
|
||||
|
||||
async function codexPoolExpose(config: UniDeskConfig, options: ConfirmOptions): Promise<Record<string, unknown>> {
|
||||
const pool = readCodexPoolConfig();
|
||||
const runtimeTarget = codexPoolRuntimeTarget(options.targetId);
|
||||
if (!pool.publicExposure.enabled) {
|
||||
return {
|
||||
ok: true,
|
||||
action: "platform-infra-sub2api-codex-pool-expose",
|
||||
mode: "disabled-by-yaml",
|
||||
target: poolTarget(pool),
|
||||
target: poolTarget(pool, runtimeTarget),
|
||||
};
|
||||
}
|
||||
if (!options.confirm) {
|
||||
@@ -986,16 +1016,16 @@ async function codexPoolExpose(config: UniDeskConfig, options: ConfirmOptions):
|
||||
ok: true,
|
||||
action: "platform-infra-sub2api-codex-pool-expose",
|
||||
mode: "dry-run",
|
||||
target: poolTarget(pool),
|
||||
publicExposure: publicExposureSummary(pool),
|
||||
target: poolTarget(pool, runtimeTarget),
|
||||
publicExposure: publicExposureSummary(pool, runtimeTarget),
|
||||
next: {
|
||||
confirm: "bun scripts/cli.ts platform-infra sub2api codex-pool expose --confirm",
|
||||
confirm: `bun scripts/cli.ts platform-infra sub2api codex-pool expose${targetFlag(runtimeTarget)} --confirm`,
|
||||
},
|
||||
};
|
||||
}
|
||||
const masterResult = await applyMasterFrpsAllowPort(pool);
|
||||
const caddyResult = await applyMasterCaddySite(pool);
|
||||
const remoteResult = await capture(config, g14K3sRoute, ["script"], exposeScript(pool));
|
||||
const remoteResult = await capture(config, runtimeTarget.route, ["script"], exposeScript(pool, runtimeTarget));
|
||||
const parsed = parseJsonOutput(remoteResult.stdout);
|
||||
const publicProbe = await probePublicModels(pool, "without-api-key", undefined, "public");
|
||||
const ok = masterResult.ok && caddyResult.ok && remoteResult.exitCode === 0 && boolField(parsed, "ok", false) && publicProbe.httpStatus === 401;
|
||||
@@ -1014,7 +1044,7 @@ async function codexPoolExpose(config: UniDeskConfig, options: ConfirmOptions):
|
||||
ok,
|
||||
action: "platform-infra-sub2api-codex-pool-expose",
|
||||
mode: "confirmed",
|
||||
publicExposure: publicExposureSummary(pool),
|
||||
publicExposure: publicExposureSummary(pool, runtimeTarget),
|
||||
masterFrps: masterResult,
|
||||
masterCaddy: caddyResult,
|
||||
remote: parsed ?? compactCapture(remoteResult, { full: options.full || remoteResult.exitCode !== 0 }),
|
||||
@@ -1283,6 +1313,7 @@ function readCodexPoolConfig(): CodexPoolConfig {
|
||||
}
|
||||
|
||||
function defaultCodexPoolConfig(): CodexPoolConfig {
|
||||
const runtimeTarget = codexPoolRuntimeTarget();
|
||||
return {
|
||||
version: 1,
|
||||
kind: "platform-infra-sub2api-codex-pool",
|
||||
@@ -1313,7 +1344,7 @@ function defaultCodexPoolConfig(): CodexPoolConfig {
|
||||
serverAddr: "74.48.78.17",
|
||||
serverPort: 7000,
|
||||
remotePort: 21880,
|
||||
localIP: serviceDns.split(":")[0],
|
||||
localIP: runtimeTarget.serviceDns.split(":")[0],
|
||||
localPort: 8080,
|
||||
publicBaseUrl: "http://74.48.78.17:21880",
|
||||
masterBaseUrl: "http://127.0.0.1:21880",
|
||||
@@ -2423,7 +2454,7 @@ function renderSentinelReport(
|
||||
`schedule=${cronJob.schedule ?? "-"}`,
|
||||
`last=${shortIso(cronJob.lastScheduleTime)}`,
|
||||
`active=${cronJob.active ?? "-"}`,
|
||||
`state=${metadata.namespace ?? namespace}/${metadata.stateConfigMapName ?? "-"}`,
|
||||
`state=${metadata.namespace ?? "-"}/${metadata.stateConfigMapName ?? "-"}`,
|
||||
`ledger=req:${globalLedger.requestCount ?? 0} tok:${formatNumber(globalLedger.totalTokens)} cost:$${formatCost(globalLedger.estimatedCostUsd)}`,
|
||||
].join(" "));
|
||||
lines.push("");
|
||||
@@ -2767,7 +2798,7 @@ function codexPoolSyncSummary(parsed: Record<string, unknown> | null): Record<st
|
||||
};
|
||||
}
|
||||
|
||||
function poolTarget(pool = readCodexPoolConfig(), target = codexPoolRuntimeTarget(defaultTargetId)): Record<string, unknown> {
|
||||
function poolTarget(pool = readCodexPoolConfig(), target = codexPoolRuntimeTarget()): Record<string, unknown> {
|
||||
return {
|
||||
id: target.id,
|
||||
route: target.route,
|
||||
@@ -2817,11 +2848,11 @@ function sentinelProfileSecrets(profiles: CodexProfile[]): CodexPoolSentinelProf
|
||||
}));
|
||||
}
|
||||
|
||||
function publicExposureSummary(pool: CodexPoolConfig): Record<string, unknown> {
|
||||
function publicExposureSummary(pool: CodexPoolConfig, target = codexPoolRuntimeTarget()): Record<string, unknown> {
|
||||
return {
|
||||
enabled: pool.publicExposure.enabled,
|
||||
proxyName: pool.publicExposure.proxyName,
|
||||
namespace,
|
||||
namespace: target.namespace,
|
||||
configMapName: pool.publicExposure.configMapName,
|
||||
deploymentName: pool.publicExposure.deploymentName,
|
||||
frpcImage: pool.publicExposure.frpcImage,
|
||||
@@ -2844,7 +2875,7 @@ function publicExposureSummary(pool: CodexPoolConfig): Record<string, unknown> {
|
||||
upstream: {
|
||||
localIP: pool.publicExposure.localIP,
|
||||
localPort: pool.publicExposure.localPort,
|
||||
serviceDns,
|
||||
serviceDns: target.serviceDns,
|
||||
},
|
||||
urls: {
|
||||
publicBaseUrl: pool.publicExposure.publicBaseUrl,
|
||||
@@ -2968,8 +2999,8 @@ function frpsAllowPortExists(toml: string, port: number): boolean {
|
||||
});
|
||||
}
|
||||
|
||||
function exposeScript(pool: CodexPoolConfig): string {
|
||||
const manifest = frpcManifest(pool);
|
||||
function exposeScript(pool: CodexPoolConfig, target: CodexPoolRuntimeTarget): string {
|
||||
const manifest = frpcManifest(pool, target);
|
||||
const encoded = Buffer.from(manifest, "utf8").toString("base64");
|
||||
return `
|
||||
set -u
|
||||
@@ -2983,7 +3014,7 @@ apply_out="$tmp/apply.out"
|
||||
apply_err="$tmp/apply.err"
|
||||
rollout_out="$tmp/rollout.out"
|
||||
rollout_err="$tmp/rollout.err"
|
||||
kubectl get namespace ${namespace} >"$ns_out" 2>"$ns_err"
|
||||
kubectl get namespace ${target.namespace} >"$ns_out" 2>"$ns_err"
|
||||
ns_rc=$?
|
||||
apply_rc=1
|
||||
rollout_rc=1
|
||||
@@ -2991,7 +3022,7 @@ if [ "$ns_rc" -eq 0 ]; then
|
||||
kubectl apply --server-side --force-conflicts --field-manager=${fieldManager} -f "$manifest" >"$apply_out" 2>"$apply_err"
|
||||
apply_rc=$?
|
||||
if [ "$apply_rc" -eq 0 ]; then
|
||||
kubectl -n ${namespace} rollout status deployment/${pool.publicExposure.deploymentName} --timeout=30s >"$rollout_out" 2>"$rollout_err"
|
||||
kubectl -n ${target.namespace} rollout status deployment/${pool.publicExposure.deploymentName} --timeout=30s >"$rollout_out" 2>"$rollout_err"
|
||||
rollout_rc=$?
|
||||
else
|
||||
printf '%s\\n' 'skipped because apply failed' >"$rollout_err"
|
||||
@@ -3004,11 +3035,11 @@ else
|
||||
fi
|
||||
pods_json="$tmp/pods.json"
|
||||
pods_err="$tmp/pods.err"
|
||||
kubectl -n ${namespace} get pods -l app.kubernetes.io/name=${pool.publicExposure.deploymentName} -o json >"$pods_json" 2>"$pods_err"
|
||||
kubectl -n ${target.namespace} get pods -l app.kubernetes.io/name=${pool.publicExposure.deploymentName} -o json >"$pods_json" 2>"$pods_err"
|
||||
pods_rc=$?
|
||||
logs_out="$tmp/logs.out"
|
||||
logs_err="$tmp/logs.err"
|
||||
kubectl -n ${namespace} logs deployment/${pool.publicExposure.deploymentName} --tail=80 >"$logs_out" 2>"$logs_err"
|
||||
kubectl -n ${target.namespace} logs deployment/${pool.publicExposure.deploymentName} --tail=80 >"$logs_out" 2>"$logs_err"
|
||||
logs_rc=$?
|
||||
python3 - "$tmp" "$ns_rc" "$apply_rc" "$rollout_rc" "$pods_rc" "$logs_rc" <<'PY'
|
||||
import json
|
||||
@@ -3048,7 +3079,7 @@ if isinstance(pods_obj, dict):
|
||||
logs = text("logs.out", 4000)
|
||||
payload = {
|
||||
"ok": ns_rc == 0 and apply_rc == 0 and rollout_rc == 0 and pods_rc == 0 and len(pods) > 0 and all(p["ready"] for p in pods),
|
||||
"namespace": "${namespace}",
|
||||
"namespace": "${target.namespace}",
|
||||
"proxy": {
|
||||
"name": "${pool.publicExposure.proxyName}",
|
||||
"remotePort": ${JSON.stringify(pool.publicExposure.remotePort)},
|
||||
@@ -3081,12 +3112,12 @@ PY
|
||||
`;
|
||||
}
|
||||
|
||||
function frpcManifest(pool: CodexPoolConfig): string {
|
||||
function frpcManifest(pool: CodexPoolConfig, target: CodexPoolRuntimeTarget): string {
|
||||
return `apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: ${pool.publicExposure.configMapName}
|
||||
namespace: ${namespace}
|
||||
namespace: ${target.namespace}
|
||||
labels:
|
||||
app.kubernetes.io/name: ${pool.publicExposure.deploymentName}
|
||||
app.kubernetes.io/part-of: platform-infra
|
||||
@@ -3108,7 +3139,7 @@ apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ${pool.publicExposure.deploymentName}
|
||||
namespace: ${namespace}
|
||||
namespace: ${target.namespace}
|
||||
labels:
|
||||
app.kubernetes.io/name: ${pool.publicExposure.deploymentName}
|
||||
app.kubernetes.io/part-of: platform-infra
|
||||
@@ -3143,7 +3174,7 @@ spec:
|
||||
`;
|
||||
}
|
||||
|
||||
async function fetchPoolApiKey(config: UniDeskConfig, pool: CodexPoolConfig, target = codexPoolRuntimeTarget(defaultTargetId)): Promise<{ apiKey: string | null; error: string | null }> {
|
||||
async function fetchPoolApiKey(config: UniDeskConfig, pool: CodexPoolConfig, target = codexPoolRuntimeTarget()): Promise<{ apiKey: string | null; error: string | null }> {
|
||||
const result = await capture(config, target.route, ["script"], `
|
||||
set -u
|
||||
kubectl -n ${target.namespace} get secret ${pool.apiKeySecretName} -o json
|
||||
@@ -3163,7 +3194,7 @@ kubectl -n ${target.namespace} get secret ${pool.apiKeySecretName} -o json
|
||||
}
|
||||
}
|
||||
|
||||
function writeLocalCodexConfig(pool: CodexPoolConfig, apiKey: string, target = codexPoolRuntimeTarget(defaultTargetId)): Record<string, unknown> {
|
||||
function writeLocalCodexConfig(pool: CodexPoolConfig, apiKey: string, target = codexPoolRuntimeTarget()): Record<string, unknown> {
|
||||
const codexDir = join(homedir(), ".codex");
|
||||
mkdirSync(codexDir, { recursive: true, mode: 0o700 });
|
||||
const configPath = join(codexDir, "config.toml");
|
||||
@@ -3221,7 +3252,7 @@ function copyIfMissing(source: string, target: string): "created" | "kept-existi
|
||||
return "created";
|
||||
}
|
||||
|
||||
function updateCodexConfigToml(current: string, pool: CodexPoolConfig, target = codexPoolRuntimeTarget(defaultTargetId)): string {
|
||||
function updateCodexConfigToml(current: string, pool: CodexPoolConfig, target = codexPoolRuntimeTarget()): string {
|
||||
return renderCodexLocalConsumerToml(current, {
|
||||
providerName: pool.localCodex.providerName,
|
||||
baseUrl: codexConsumerBaseUrl(pool, target),
|
||||
@@ -3233,7 +3264,7 @@ function updateCodexConfigToml(current: string, pool: CodexPoolConfig, target =
|
||||
});
|
||||
}
|
||||
|
||||
function codexConsumerBaseUrl(pool: CodexPoolConfig, target = codexPoolRuntimeTarget(defaultTargetId)): string {
|
||||
function codexConsumerBaseUrl(pool: CodexPoolConfig, target = codexPoolRuntimeTarget()): string {
|
||||
const baseUrl = target.publicBaseUrl ?? pool.publicExposure.publicBaseUrl;
|
||||
return `${baseUrl.replace(/\/+$/u, "")}/`;
|
||||
}
|
||||
@@ -3331,7 +3362,7 @@ function upsertTomlSectionBoolean(text: string, sectionName: string, key: string
|
||||
return [...lines.slice(0, start + 1), assignment, ...lines.slice(start + 1)].join("\n");
|
||||
}
|
||||
|
||||
async function validatePublicGatewayWithKey(pool: CodexPoolConfig, apiKey: string, target = codexPoolRuntimeTarget(defaultTargetId)): Promise<Record<string, unknown>> {
|
||||
async function validatePublicGatewayWithKey(pool: CodexPoolConfig, apiKey: string, target = codexPoolRuntimeTarget()): Promise<Record<string, unknown>> {
|
||||
const probeBase = target.publicBaseUrl === null ? "public" : "target-public";
|
||||
const probe = await probePublicModels(pool, "with-api-key", apiKey, probeBase, target);
|
||||
return {
|
||||
@@ -3343,7 +3374,7 @@ async function validatePublicGatewayWithKey(pool: CodexPoolConfig, apiKey: strin
|
||||
};
|
||||
}
|
||||
|
||||
async function probePublicModels(pool: CodexPoolConfig, mode: "with-api-key" | "without-api-key", apiKey?: string, base: "master" | "public" | "target-public" = "master", target = codexPoolRuntimeTarget(defaultTargetId)): Promise<Record<string, unknown>> {
|
||||
async function probePublicModels(pool: CodexPoolConfig, mode: "with-api-key" | "without-api-key", apiKey?: string, base: "master" | "public" | "target-public" = "master", target = codexPoolRuntimeTarget()): Promise<Record<string, unknown>> {
|
||||
const baseUrl = base === "target-public"
|
||||
? (target.publicBaseUrl ?? pool.publicExposure.publicBaseUrl)
|
||||
: base === "public"
|
||||
@@ -6543,7 +6574,7 @@ async function capture(config: UniDeskConfig, target: string, args: string[], in
|
||||
|
||||
type RemoteCodexPoolMode = "sync" | "validate" | "sentinel-probe" | "sentinel-image-status" | "sentinel-image-build";
|
||||
|
||||
async function runRemoteCodexPoolScript(config: UniDeskConfig, mode: RemoteCodexPoolMode, script: string, target = codexPoolRuntimeTarget(defaultTargetId)): Promise<SshCaptureResult> {
|
||||
async function runRemoteCodexPoolScript(config: UniDeskConfig, mode: RemoteCodexPoolMode, script: string, target = codexPoolRuntimeTarget()): Promise<SshCaptureResult> {
|
||||
const jobName = `codex-pool-${mode}-${Date.now().toString(36)}`.slice(0, 63);
|
||||
const startedAtMs = Date.now();
|
||||
const start = await capture(config, target.route, ["script"], remoteJobStartScript(jobName, script));
|
||||
|
||||
Reference in New Issue
Block a user