feat: extend G14 runtime automation

This commit is contained in:
Codex
2026-06-09 03:00:48 +00:00
parent 46dc43c618
commit 97f19d462f
9 changed files with 1967 additions and 132 deletions
+848
View File
@@ -0,0 +1,848 @@
import { createHash } from "node:crypto";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
import type { UniDeskConfig } from "./config";
import { runSshCommandCapture, type SshCaptureResult } from "./ssh";
const g14K3sRoute = "G14: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 poolGroupName = "unidesk-codex-pool";
const poolApiKeyName = "unidesk-codex-pool-api-key";
const poolApiKeySecretName = "sub2api-codex-pool-api-key";
const poolApiKeySecretKey = "API_KEY";
interface DisclosureOptions {
full: boolean;
raw: boolean;
}
interface SyncOptions extends DisclosureOptions {
confirm: boolean;
}
interface CodexProfile {
profile: string;
accountName: string;
configFile: string;
authFile: string;
provider: string;
baseUrl: string;
wireApi: string | null;
model: string | null;
envKey: string | null;
apiKey: string | null;
apiKeySource: "auth-json" | "env" | null;
authOpenAIKeyShape: string;
ok: boolean;
error: string | null;
}
export function codexPoolHelp(): unknown {
return {
command: "platform-infra sub2api codex-pool plan|sync|validate",
output: "json",
usage: [
"bun scripts/cli.ts platform-infra sub2api codex-pool plan",
"bun scripts/cli.ts platform-infra sub2api codex-pool sync --confirm",
"bun scripts/cli.ts platform-infra sub2api codex-pool validate [--full|--raw]",
],
description: "Import ~/.codex/config.toml plus config.toml.* API-key profiles into one Sub2API OpenAI pool and expose one internal API_KEY stored in a k3s Secret.",
target: {
route: g14K3sRoute,
namespace,
serviceDns,
poolGroupName,
poolApiKeySecretName,
poolApiKeySecretKey,
secretValuesPrinted: false,
},
};
}
export async function runCodexPoolCommand(config: UniDeskConfig, args: string[]): Promise<Record<string, unknown>> {
const [action = "plan"] = args;
if (action === "plan") return codexPoolPlan();
if (action === "sync") return await codexPoolSync(config, parseSyncOptions(args.slice(1)));
if (action === "validate") return await codexPoolValidate(config, parseDisclosureOptions(args.slice(1)));
return {
ok: false,
error: "unsupported-platform-infra-sub2api-codex-pool-command",
args,
help: codexPoolHelp(),
};
}
function parseSyncOptions(args: string[]): SyncOptions {
validateOptions(args, new Set(["--confirm", "--full", "--raw"]));
const disclosure = parseDisclosureOptions(args.filter((arg) => arg !== "--confirm"));
return { ...disclosure, confirm: args.includes("--confirm") };
}
function parseDisclosureOptions(args: string[]): DisclosureOptions {
validateOptions(args, new Set(["--full", "--raw"]));
const raw = args.includes("--raw");
return { full: raw || args.includes("--full"), raw };
}
function validateOptions(args: string[], booleanOptions: Set<string>): void {
for (const arg of args) {
if (booleanOptions.has(arg)) continue;
throw new Error(`unsupported option: ${arg}`);
}
}
function codexPoolPlan(): Record<string, unknown> {
const profiles = collectCodexProfiles();
const ok = profiles.length > 0 && profiles.every((profile) => profile.ok);
return {
ok,
action: "platform-infra-sub2api-codex-pool-plan",
source: {
directory: join(homedir(), ".codex"),
configPattern: "config.toml and config.toml.*",
authPattern: "auth.json and auth.json.*",
valuesPrinted: false,
},
target: poolTarget(),
profiles: profiles.map(redactProfile),
decision: {
accountType: "openai/apikey",
grouping: `All discovered Codex profiles are bound to one Sub2API group named ${poolGroupName}.`,
unifiedApiKey: `The client-facing API_KEY is controlled by k3s Secret ${namespace}/${poolApiKeySecretName}.${poolApiKeySecretKey}.`,
idempotency: "sync reuses the group, account names, and k3s Secret when they already exist; credentials are updated from the current local Codex files.",
configPolicy: "UniDesk-owned durable configuration remains YAML-first; local ~/.codex files and runtime Secrets are not committed.",
},
next: ok
? { sync: "bun scripts/cli.ts platform-infra sub2api codex-pool sync --confirm" }
: { fix: "Ensure every discovered config.toml profile has a base_url and either auth.json OPENAI_API_KEY or the configured env_key present in this shell." },
};
}
async function codexPoolSync(config: UniDeskConfig, options: SyncOptions): Promise<Record<string, unknown>> {
const profiles = collectCodexProfiles();
const planOk = profiles.length > 0 && profiles.every((profile) => profile.ok);
if (!options.confirm || !planOk) {
return {
...codexPoolPlan(),
ok: !options.confirm ? planOk : false,
mode: options.confirm ? "blocked-invalid-local-profile" : "dry-run",
next: options.confirm
? { fix: "Repair invalid local Codex profiles, then rerun sync --confirm." }
: { confirm: "bun scripts/cli.ts platform-infra sub2api codex-pool sync --confirm" },
};
}
const payload = {
pool: {
groupName: poolGroupName,
apiKeyName: poolApiKeyName,
apiKeySecretName: poolApiKeySecretName,
apiKeySecretKey: poolApiKeySecretKey,
},
profiles: profiles.map((profile) => ({
profile: profile.profile,
accountName: profile.accountName,
configFile: profile.configFile,
authFile: profile.authFile,
provider: profile.provider,
baseUrl: profile.baseUrl,
wireApi: profile.wireApi,
model: profile.model,
apiKey: profile.apiKey,
apiKeySource: profile.apiKeySource,
apiKeyFingerprint: fingerprint(profile.apiKey ?? ""),
})),
};
const result = await capture(config, g14K3sRoute, ["script"], syncScript(payload));
const parsed = parseJsonOutput(result.stdout);
if (options.raw) {
return {
ok: result.exitCode === 0 && boolField(parsed, "ok", false),
action: "platform-infra-sub2api-codex-pool-sync",
remote: compactCapture(result, { full: true }),
parsed,
};
}
return {
ok: result.exitCode === 0 && boolField(parsed, "ok", false),
action: "platform-infra-sub2api-codex-pool-sync",
local: {
profiles: profiles.map(redactProfile),
valuesPrinted: false,
},
remote: parsed ?? compactCapture(result, { full: options.full || result.exitCode !== 0 }),
next: {
validate: "bun scripts/cli.ts platform-infra sub2api codex-pool validate",
},
};
}
async function codexPoolValidate(config: UniDeskConfig, options: DisclosureOptions): Promise<Record<string, unknown>> {
const result = await capture(config, g14K3sRoute, ["script"], validateScript());
const parsed = parseJsonOutput(result.stdout);
if (options.raw) {
return {
ok: result.exitCode === 0 && boolField(parsed, "ok", false),
action: "platform-infra-sub2api-codex-pool-validate",
remote: compactCapture(result, { full: true }),
parsed,
};
}
return {
ok: result.exitCode === 0 && boolField(parsed, "ok", false),
action: "platform-infra-sub2api-codex-pool-validate",
summary: parsed,
remote: compactCapture(result, { full: options.full || result.exitCode !== 0 }),
};
}
function collectCodexProfiles(): CodexProfile[] {
const codexDir = join(homedir(), ".codex");
if (!existsSync(codexDir)) return [];
const configFiles = readdirSync(codexDir)
.filter((file) => file === "config.toml" || file.startsWith("config.toml."))
.sort((a, b) => {
if (a === "config.toml") return -1;
if (b === "config.toml") return 1;
return a.localeCompare(b);
});
const seenAccountNames = new Set<string>();
return configFiles.map((configFile) => {
const suffix = configFile === "config.toml" ? "" : configFile.slice("config.toml.".length);
const profile = suffix === "" ? "default" : suffix;
const accountName = uniqueAccountName(profile, seenAccountNames);
const authFile = suffix === "" ? "auth.json" : `auth.json.${suffix}`;
const configPath = join(codexDir, configFile);
const authPath = join(codexDir, authFile);
const base: CodexProfile = {
profile,
accountName,
configFile,
authFile,
provider: "",
baseUrl: "",
wireApi: null,
model: null,
envKey: null,
apiKey: null,
apiKeySource: null,
authOpenAIKeyShape: existsSync(authPath) ? "unknown" : "missing",
ok: false,
error: null,
};
try {
const parsed = Bun.TOML.parse(readFileSync(configPath, "utf8")) as unknown;
if (!isRecord(parsed)) throw new Error("config is not a TOML object");
const providers = parsed.model_providers;
if (!isRecord(providers)) throw new Error("model_providers is missing");
const provider = stringValue(parsed.model_provider) ?? Object.keys(providers)[0] ?? "";
if (provider === "") throw new Error("model_provider is missing");
const providerConfig = providers[provider];
if (!isRecord(providerConfig)) throw new Error(`model provider ${provider} is missing`);
const baseUrl = normalizeBaseUrl(stringValue(providerConfig.base_url));
if (baseUrl === null) throw new Error(`model provider ${provider} base_url is missing or invalid`);
base.provider = provider;
base.baseUrl = baseUrl;
base.envKey = stringValue(providerConfig.env_key);
base.wireApi = stringValue(providerConfig.wire_api);
base.model = stringValue(parsed.model);
const auth = readAuthAPIKey(authPath);
base.authOpenAIKeyShape = auth.shape;
if (auth.apiKey !== null) {
base.apiKey = auth.apiKey;
base.apiKeySource = "auth-json";
} else if (base.envKey !== null && typeof process.env[base.envKey] === "string" && process.env[base.envKey]!.length > 0) {
base.apiKey = process.env[base.envKey]!;
base.apiKeySource = "env";
}
if (base.apiKey === null || base.apiKey.length === 0) {
throw new Error(base.envKey === null ? "auth OPENAI_API_KEY is missing or empty" : `auth OPENAI_API_KEY is missing and env ${base.envKey} is not present`);
}
base.ok = true;
return base;
} catch (error) {
base.error = error instanceof Error ? error.message : String(error);
return base;
}
});
}
function readAuthAPIKey(authPath: string): { apiKey: string | null; shape: string } {
if (!existsSync(authPath)) return { apiKey: null, shape: "missing" };
const parsed = JSON.parse(readFileSync(authPath, "utf8")) as unknown;
if (!isRecord(parsed)) return { apiKey: null, shape: "non-object" };
const value = parsed.OPENAI_API_KEY;
const shape = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
if (typeof value === "string" && value.length > 0) return { apiKey: value, shape };
return { apiKey: null, shape };
}
function uniqueAccountName(profile: string, seen: Set<string>): string {
const normalized = profile
.toLowerCase()
.replace(/[^a-z0-9._-]+/gu, "-")
.replace(/^-+|-+$/gu, "") || "default";
let candidate = `unidesk-codex-${normalized}`;
let counter = 2;
while (seen.has(candidate)) {
candidate = `unidesk-codex-${normalized}-${counter}`;
counter += 1;
}
seen.add(candidate);
return candidate;
}
function redactProfile(profile: CodexProfile): Record<string, unknown> {
return {
profile: profile.profile,
accountName: profile.accountName,
configFile: profile.configFile,
authFile: profile.authFile,
provider: profile.provider || null,
baseUrl: profile.baseUrl || null,
wireApi: profile.wireApi,
model: profile.model,
envKey: profile.envKey,
apiKeySource: profile.apiKeySource,
apiKeyPresent: profile.apiKey !== null && profile.apiKey.length > 0,
apiKeyBytes: profile.apiKey === null ? 0 : Buffer.byteLength(profile.apiKey, "utf8"),
apiKeyFingerprint: profile.apiKey === null ? null : fingerprint(profile.apiKey),
authOpenAIKeyShape: profile.authOpenAIKeyShape,
ok: profile.ok,
error: profile.error,
valuesPrinted: false,
};
}
function poolTarget(): Record<string, unknown> {
return {
route: g14K3sRoute,
namespace,
service: serviceName,
serviceDns,
groupName: poolGroupName,
apiKeyName: poolApiKeyName,
apiKeySecret: `${namespace}/${poolApiKeySecretName}.${poolApiKeySecretKey}`,
valuesPrinted: false,
};
}
function normalizeBaseUrl(value: string | null): string | null {
if (value === null) return null;
const trimmed = value.trim().replace(/\/+$/u, "");
if (trimmed.length === 0) return null;
try {
const parsed = new URL(trimmed);
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return null;
return parsed.toString().replace(/\/+$/u, "");
} catch {
return null;
}
}
function stringValue(value: unknown): string | null {
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function fingerprint(value: string): string {
return createHash("sha256").update(value).digest("hex").slice(0, 12);
}
function syncScript(payload: unknown): string {
const encoded = Buffer.from(JSON.stringify(payload), "utf8").toString("base64");
return remotePythonScript("sync", encoded);
}
function validateScript(): string {
return remotePythonScript("validate", "");
}
function remotePythonScript(mode: "sync" | "validate", encodedPayload: string): string {
return `
set -u
python3 - <<'PY'
import base64
import json
import secrets
import string
import subprocess
import sys
import time
from urllib.parse import quote
NAMESPACE = "${namespace}"
SERVICE_NAME = "${serviceName}"
SERVICE_DNS = "${serviceDns}"
FIELD_MANAGER = "${fieldManager}"
APP_SECRET_NAME = "${appSecretName}"
POOL_GROUP_NAME = "${poolGroupName}"
POOL_API_KEY_NAME = "${poolApiKeyName}"
POOL_API_KEY_SECRET_NAME = "${poolApiKeySecretName}"
POOL_API_KEY_SECRET_KEY = "${poolApiKeySecretKey}"
MODE = "${mode}"
PAYLOAD_B64 = "${encodedPayload}"
def run(cmd, input_bytes=None):
return subprocess.run(cmd, input=input_bytes, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def text(data, limit=4000):
if isinstance(data, bytes):
data = data.decode("utf-8", errors="replace")
return data[-limit:]
def kubectl(args, input_obj=None):
if isinstance(input_obj, str):
input_bytes = input_obj.encode("utf-8")
else:
input_bytes = input_obj
return run(["kubectl", *args], input_bytes)
def require_kubectl(args, input_obj=None, label="kubectl"):
proc = kubectl(args, input_obj)
if proc.returncode != 0:
raise RuntimeError(f"{label} failed: {text(proc.stderr, 1000)}")
return proc.stdout
def kube_json(args, label):
raw = require_kubectl([*args, "-o", "json"], label=label)
return json.loads(raw.decode("utf-8"))
def decode_secret_value(name, key):
data = kube_json(["-n", NAMESPACE, "get", "secret", name], f"secret/{name}").get("data") or {}
if key not in data:
return None
return base64.b64decode(data[key]).decode("utf-8")
def get_config_value(name, key):
data = kube_json(["-n", NAMESPACE, "get", "configmap", name], f"configmap/{name}").get("data") or {}
value = data.get(key)
return value if isinstance(value, str) and value else None
def select_app_pod():
pods = kube_json(["-n", NAMESPACE, "get", "pods", "-l", "app.kubernetes.io/name=sub2api"], "sub2api pods").get("items") or []
for pod in pods:
status = pod.get("status") or {}
if status.get("phase") != "Running":
continue
statuses = status.get("containerStatuses") or []
if statuses and all(item.get("ready") is True for item in statuses):
return pod["metadata"]["name"]
if pods:
return pods[0]["metadata"]["name"]
raise RuntimeError("sub2api app pod not found")
APP_POD = select_app_pod()
def parse_curl_output(proc):
stdout = proc.stdout.decode("utf-8", errors="replace")
marker = "\\n__HTTP_CODE__:"
pos = stdout.rfind(marker)
if pos < 0:
return {
"ok": False,
"httpStatus": 0,
"json": None,
"body": stdout,
"stderr": text(proc.stderr, 1000),
"transportExitCode": proc.returncode,
}
body = stdout[:pos]
status_text = stdout[pos + len(marker):].strip()
try:
http_status = int(status_text[-3:])
except ValueError:
http_status = 0
try:
parsed = json.loads(body) if body.strip() else None
except json.JSONDecodeError:
parsed = None
return {
"ok": proc.returncode == 0 and 200 <= http_status < 300,
"httpStatus": http_status,
"json": parsed,
"body": body,
"stderr": text(proc.stderr, 1000),
"transportExitCode": proc.returncode,
}
def curl_api(method, path, bearer=None, payload=None):
body = b"" if payload is None else json.dumps(payload, separators=(",", ":")).encode("utf-8")
script = r'''
set -eu
method="$1"
url="$2"
token="\${3:-}"
tmp="$(mktemp)"
trap 'rm -f "$tmp"' EXIT
cat > "$tmp"
if [ -n "$token" ]; then
if [ "$method" = "GET" ] && [ ! -s "$tmp" ]; then
curl -sS -w '\\n__HTTP_CODE__:%{http_code}' -X "$method" -H "Authorization: Bearer $token" "$url"
else
curl -sS -w '\\n__HTTP_CODE__:%{http_code}' -X "$method" -H 'Content-Type: application/json' -H "Authorization: Bearer $token" --data-binary @"$tmp" "$url"
fi
else
if [ "$method" = "GET" ] && [ ! -s "$tmp" ]; then
curl -sS -w '\\n__HTTP_CODE__:%{http_code}' -X "$method" "$url"
else
curl -sS -w '\\n__HTTP_CODE__:%{http_code}' -X "$method" -H 'Content-Type: application/json' --data-binary @"$tmp" "$url"
fi
fi
'''
proc = run([
"kubectl", "-n", NAMESPACE, "exec", "-i", APP_POD,
"--", "sh", "-c", script, "sh", method, f"http://127.0.0.1:8080{path}", bearer or "",
], body)
return parse_curl_output(proc)
def envelope_data(parsed):
if isinstance(parsed, dict) and "data" in parsed:
return parsed.get("data")
return parsed
def ensure_success(resp, label):
parsed = resp.get("json")
code = parsed.get("code") if isinstance(parsed, dict) else None
if not resp.get("ok") or (code is not None and code != 0):
message = parsed.get("message") if isinstance(parsed, dict) else text(resp.get("body", ""), 500)
raise RuntimeError(f"{label} failed: http={resp.get('httpStatus')} message={message}")
return envelope_data(parsed)
def extract_items(data):
if isinstance(data, list):
return data
if isinstance(data, dict):
if isinstance(data.get("items"), list):
return data["items"]
for key in ("groups", "accounts", "api_keys", "keys"):
if isinstance(data.get(key), list):
return data[key]
return []
def find_access_token(data):
if isinstance(data, dict):
for key in ("access_token", "token"):
if isinstance(data.get(key), str) and data[key]:
return data[key]
for value in data.values():
token = find_access_token(value)
if token:
return token
return None
def login():
admin_email = get_config_value("sub2api-config", "ADMIN_EMAIL") or "admin@sub2api.platform-infra.local"
admin_password = decode_secret_value(APP_SECRET_NAME, "ADMIN_PASSWORD")
if not admin_password:
raise RuntimeError("ADMIN_PASSWORD missing from sub2api-secrets")
data = ensure_success(curl_api("POST", "/api/v1/auth/login", payload={"email": admin_email, "password": admin_password}), "admin login")
token = find_access_token(data)
if not token:
raise RuntimeError("admin login response did not contain access_token")
return admin_email, token
def group_payload():
return {
"name": POOL_GROUP_NAME,
"description": "UniDesk-managed Codex API-key pool for G14 k3s internal Sub2API clients.",
"platform": "openai",
"rate_multiplier": 1,
"is_exclusive": False,
"subscription_type": "standard",
"allow_messages_dispatch": True,
"require_oauth_only": False,
"require_privacy_set": False,
"rpm_limit": 0,
}
def ensure_group(token):
existing_data = ensure_success(curl_api("GET", "/api/v1/admin/groups/all?platform=openai", bearer=token), "list groups")
existing = next((item for item in extract_items(existing_data) if item.get("name") == POOL_GROUP_NAME), None)
payload = group_payload()
if existing is None:
created = ensure_success(curl_api("POST", "/api/v1/admin/groups", bearer=token, payload=payload), "create group")
return created, "created"
group_id = existing.get("id")
if group_id is None:
raise RuntimeError("existing group has no id")
payload["status"] = "active"
updated = ensure_success(curl_api("PUT", f"/api/v1/admin/groups/{group_id}", bearer=token, payload=payload), "update group")
return updated if isinstance(updated, dict) else existing, "updated"
def list_accounts(token):
path = "/api/v1/admin/accounts?page=1&page_size=200&platform=openai&type=apikey&search=" + quote("unidesk-codex-")
data = ensure_success(curl_api("GET", path, bearer=token), "list accounts")
return extract_items(data)
def account_payload(profile, group_id):
return {
"name": profile["accountName"],
"notes": f"UniDesk-managed Codex profile {profile['profile']} from {profile['configFile']} and {profile['authFile']}; secret source={profile['apiKeySource']}; fingerprint={profile['apiKeyFingerprint']}.",
"platform": "openai",
"type": "apikey",
"credentials": {
"api_key": profile["apiKey"],
"base_url": profile["baseUrl"],
},
"extra": {
"openai_responses_mode": "force_responses",
"unidesk_codex_profile": profile["profile"],
"unidesk_managed": True,
},
"concurrency": 1,
"priority": 1,
"rate_multiplier": 1,
"load_factor": 1,
"group_ids": [group_id],
"confirm_mixed_channel_risk": True,
}
def ensure_accounts(token, profiles, group_id):
existing = {item.get("name"): item for item in list_accounts(token)}
results = []
for profile in profiles:
payload = account_payload(profile, group_id)
current = existing.get(profile["accountName"])
if current and current.get("id") is not None:
account_id = current["id"]
update_payload = dict(payload)
update_payload.pop("platform", None)
update_payload["status"] = "active"
data = ensure_success(curl_api("PUT", f"/api/v1/admin/accounts/{account_id}", bearer=token, payload=update_payload), f"update account {profile['accountName']}")
action = "updated"
else:
data = ensure_success(curl_api("POST", "/api/v1/admin/accounts", bearer=token, payload=payload), f"create account {profile['accountName']}")
action = "created"
results.append({
"profile": profile["profile"],
"accountName": profile["accountName"],
"accountId": data.get("id") if isinstance(data, dict) else None,
"action": action,
"baseUrl": profile["baseUrl"],
"apiKeySource": profile["apiKeySource"],
"apiKeyFingerprint": profile["apiKeyFingerprint"],
"valuesPrinted": False,
})
return results
def generate_api_key():
alphabet = string.ascii_letters + string.digits
return "sk-unidesk-codex-" + "".join(secrets.choice(alphabet) for _ in range(48))
def ensure_api_key_secret(group_id):
existing = None
try:
existing = decode_secret_value(POOL_API_KEY_SECRET_NAME, POOL_API_KEY_SECRET_KEY)
except Exception:
existing = None
api_key = existing if existing else generate_api_key()
secret_action = "kept-existing" if existing else "created"
manifest = {
"apiVersion": "v1",
"kind": "Secret",
"metadata": {
"name": POOL_API_KEY_SECRET_NAME,
"namespace": NAMESPACE,
"labels": {
"app.kubernetes.io/name": "sub2api",
"app.kubernetes.io/part-of": "platform-infra",
"app.kubernetes.io/managed-by": "unidesk",
"unidesk.ai/secret-purpose": "sub2api-codex-pool-api-key",
},
},
"type": "Opaque",
"stringData": {
POOL_API_KEY_SECRET_KEY: api_key,
"GROUP_ID": str(group_id),
"GROUP_NAME": POOL_GROUP_NAME,
"SERVICE_DNS": SERVICE_DNS,
},
}
proc = kubectl(["apply", "--server-side", "--force-conflicts", f"--field-manager={FIELD_MANAGER}", "-f", "-"], json.dumps(manifest))
if proc.returncode != 0:
raise RuntimeError(f"apply API key secret failed: {text(proc.stderr, 1000)}")
return api_key, secret_action, text(proc.stdout, 1000)
def list_user_keys(token):
data = ensure_success(curl_api("GET", "/api/v1/keys?page=1&page_size=200", bearer=token), "list user keys")
return extract_items(data)
def ensure_sub2api_api_key(token, api_key, group_id):
keys = list_user_keys(token)
existing = next((item for item in keys if item.get("key") == api_key), None)
action = "kept-existing"
if existing is None:
existing = next((item for item in keys if item.get("name") == POOL_API_KEY_NAME), None)
if existing is None or existing.get("key") != api_key:
payload = {
"name": POOL_API_KEY_NAME,
"group_id": group_id,
"custom_key": api_key,
"quota": 0,
"rate_limit_5h": 0,
"rate_limit_1d": 0,
"rate_limit_7d": 0,
}
created = ensure_success(curl_api("POST", "/api/v1/keys", bearer=token, payload=payload), "create pool API key")
existing = created if isinstance(created, dict) else existing
action = "created"
elif existing.get("id") is not None and existing.get("group_id") != group_id:
updated = ensure_success(curl_api("PUT", f"/api/v1/keys/{existing['id']}", bearer=token, payload={"name": POOL_API_KEY_NAME, "group_id": group_id}), "update pool API key group")
existing = updated if isinstance(updated, dict) else existing
action = "updated-group"
return {
"action": action,
"id": existing.get("id") if isinstance(existing, dict) else None,
"name": existing.get("name") if isinstance(existing, dict) else POOL_API_KEY_NAME,
"groupId": existing.get("group_id") if isinstance(existing, dict) else group_id,
}
def validate_gateway(api_key):
resp = curl_api("GET", "/v1/models", bearer=api_key)
parsed = resp.get("json")
model_count = None
if isinstance(parsed, dict) and isinstance(parsed.get("data"), list):
model_count = len(parsed["data"])
return {
"ok": resp.get("ok"),
"httpStatus": resp.get("httpStatus"),
"transportExitCode": resp.get("transportExitCode"),
"modelCount": model_count,
"bodyPreview": text(resp.get("body", ""), 500) if not resp.get("ok") else "",
"stderr": resp.get("stderr", ""),
"method": "GET /v1/models",
"serviceDns": SERVICE_DNS,
"valuesPrinted": False,
}
def api_key_preview(api_key):
if len(api_key) <= 14:
return "***"
return api_key[:10] + "..." + api_key[-4:]
def run_sync():
payload = json.loads(base64.b64decode(PAYLOAD_B64).decode("utf-8"))
profiles = payload.get("profiles") or []
if not profiles:
raise RuntimeError("sync payload has no profiles")
admin_email, token = login()
group, group_action = ensure_group(token)
group_id = group.get("id") if isinstance(group, dict) else None
if group_id is None:
raise RuntimeError("pool group id missing after ensure")
account_results = ensure_accounts(token, profiles, group_id)
api_key, secret_action, secret_apply_stdout = ensure_api_key_secret(group_id)
api_key_result = ensure_sub2api_api_key(token, api_key, group_id)
gateway = validate_gateway(api_key)
return {
"ok": gateway["ok"] is True,
"mode": "sync",
"namespace": NAMESPACE,
"serviceDns": SERVICE_DNS,
"appPod": APP_POD,
"admin": {"email": admin_email, "tokenPrinted": False},
"pool": {"name": POOL_GROUP_NAME, "id": group_id, "action": group_action, "platform": group.get("platform") if isinstance(group, dict) else "openai"},
"accounts": {
"desired": len(profiles),
"created": sum(1 for item in account_results if item["action"] == "created"),
"updated": sum(1 for item in account_results if item["action"] == "updated"),
"items": account_results,
"valuesPrinted": False,
},
"apiKey": {
"name": POOL_API_KEY_NAME,
"secret": f"{NAMESPACE}/{POOL_API_KEY_SECRET_NAME}.{POOL_API_KEY_SECRET_KEY}",
"secretAction": secret_action,
"secretApply": secret_apply_stdout,
"sub2apiAction": api_key_result["action"],
"sub2apiId": api_key_result["id"],
"groupId": api_key_result["groupId"],
"keyPreview": api_key_preview(api_key),
"valuesPrinted": False,
},
"validation": {"gatewayModels": gateway},
}
def run_validate():
api_key = decode_secret_value(POOL_API_KEY_SECRET_NAME, POOL_API_KEY_SECRET_KEY)
if not api_key:
raise RuntimeError(f"{POOL_API_KEY_SECRET_NAME}.{POOL_API_KEY_SECRET_KEY} missing")
gateway = validate_gateway(api_key)
return {
"ok": gateway["ok"] is True,
"mode": "validate",
"namespace": NAMESPACE,
"serviceDns": SERVICE_DNS,
"appPod": APP_POD,
"apiKey": {
"secret": f"{NAMESPACE}/{POOL_API_KEY_SECRET_NAME}.{POOL_API_KEY_SECRET_KEY}",
"keyPreview": api_key_preview(api_key),
"valuesPrinted": False,
},
"validation": {"gatewayModels": gateway},
}
try:
result = run_sync() if MODE == "sync" else run_validate()
except Exception as exc:
result = {
"ok": False,
"mode": MODE,
"namespace": NAMESPACE,
"serviceDns": SERVICE_DNS,
"appPod": globals().get("APP_POD"),
"error": str(exc),
"valuesPrinted": False,
}
print(json.dumps(result, ensure_ascii=False, indent=2))
sys.exit(0 if result.get("ok") else 1)
PY
`;
}
async function capture(config: UniDeskConfig, target: string, args: string[], input?: string): Promise<SshCaptureResult> {
return await runSshCommandCapture(config, target, args, input);
}
function parseJsonOutput(stdout: string): Record<string, unknown> | null {
const trimmed = stdout.trim();
if (trimmed.length === 0) return null;
const start = trimmed.indexOf("{");
const end = trimmed.lastIndexOf("}");
if (start === -1 || end === -1 || end <= start) return null;
try {
const parsed = JSON.parse(trimmed.slice(start, end + 1)) as unknown;
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed as Record<string, unknown> : null;
} catch {
return null;
}
}
function boolField(value: Record<string, unknown> | null, key: string, defaultValue: boolean): boolean {
if (value === null) return defaultValue;
const field = value[key];
return typeof field === "boolean" ? field : defaultValue;
}
function compactCapture(result: SshCaptureResult, options: { full?: boolean } = {}): Record<string, unknown> {
const full = options.full ?? false;
return {
exitCode: result.exitCode,
stdoutBytes: Buffer.byteLength(result.stdout, "utf8"),
stderrBytes: Buffer.byteLength(result.stderr, "utf8"),
stdoutTail: full || result.exitCode !== 0 ? result.stdout.slice(-8000) : "",
stderrTail: full || result.exitCode !== 0 ? result.stderr.slice(-4000) : "",
};
}