Files
pikasTech-unidesk/scripts/src/platform-infra-sub2api-codex/runtime.ts
T
2026-07-22 10:18:08 +02:00

273 lines
12 KiB
TypeScript

import type { UniDeskConfig } from "../config";
import type { RenderedCliResult } from "../output";
import { desiredAccountNames } from "./accounts";
import { readCodexPoolConfig } from "./config";
import { isRecord } from "./config-utils";
import { protectedManualAccountsForTarget } from "./public-exposure";
import { renderSub2ApiTempUnschedulableCredentials } from "./redaction";
import { boolField, compactCapture, parseJsonOutput, runRemoteCodexPoolScript } from "./remote";
import { compactRuntimeErrors, renderRuntimeResult } from "./runtime-render";
import { runtimeScript } from "./runtime-remote-script";
import { parseRuntimeOptions, type RuntimeOptions } from "./runtime-options";
import { renderRuntimeMutationResult } from "./runtime-mutation-render";
import { codexPoolRuntimeTarget } from "./runtime-target";
export async function codexPoolRuntime(config: UniDeskConfig, args: string[]): Promise<Record<string, unknown> | RenderedCliResult> {
if (args.includes("--help") || args.includes("-h") || args[0] === "help") return renderRuntimeHelp(args);
const options = parseRuntimeOptions(args);
const pool = readCodexPoolConfig();
const target = codexPoolRuntimeTarget(options.targetId);
const selectedTemplate = options.kind !== "temp-unschedulable" || options.template === null ? null : pool.runtime.templatesById[options.template];
if (options.template !== null && selectedTemplate === undefined) {
throw new Error(`unknown runtime template ${options.template}; available: ${pool.runtime.templates.map((item) => item.id).join(", ")}`);
}
const payload = {
action: options.action,
account: options.account,
accounts: options.accounts,
selectConfiguredPolicy: options.selectConfiguredPolicy,
accountType: options.accountType,
excludeAccounts: options.excludeAccounts,
group: options.group,
allGroups: options.allGroups,
platform: options.platform,
pageToken: options.pageToken,
kind: options.kind,
priority: options.priority,
capacity: options.capacity,
name: options.name,
confirm: options.confirm,
full: options.full,
recent: options.recent,
since: options.since,
tail: options.tail,
groupName: pool.groupName,
adminEmailDefault: pool.adminEmailDefault,
managedAccountNames: desiredAccountNames(pool),
protectedManualAccountNames: protectedManualAccountsForTarget(pool, target).map((item) => item.accountName),
templates: pool.runtime.templates.map((template) => ({
id: template.id,
kind: template.kind,
description: template.description,
credentials: renderSub2ApiTempUnschedulableCredentials(template.tempUnschedulable),
})),
selectedTemplate: selectedTemplate === null || selectedTemplate === undefined ? null : {
id: selectedTemplate.id,
kind: selectedTemplate.kind,
credentials: renderSub2ApiTempUnschedulableCredentials(selectedTemplate.tempUnschedulable),
},
};
const result = await runRemoteCodexPoolScript(config, "runtime", runtimeScript(payload, target), target);
const parsed = parseJsonOutput(result.stdout);
const ok = result.exitCode === 0 && boolField(parsed, "ok", false);
if (!options.full && !options.raw && !options.json && (options.action === "apply" || options.action === "delete")) {
return renderRuntimeMutationResult(ok, options, parsed, result.exitCode);
}
if (options.raw) {
return {
ok,
action: "platform-infra-sub2api-codex-pool-runtime",
remote: compactCapture(result, { full: parsed === null || result.exitCode !== 0 }),
parsed,
valuesPrinted: false,
};
}
const response = {
ok,
action: "platform-infra-sub2api-codex-pool-runtime",
target: {
id: target.id,
route: target.route,
namespace: target.namespace,
runtimeMode: target.runtimeMode,
endpoint: target.serviceDns,
},
request: {
operation: options.action,
account: options.account,
accounts: options.accounts,
selectConfiguredPolicy: options.selectConfiguredPolicy,
accountType: options.accountType,
excludeAccounts: options.excludeAccounts,
group: options.group,
allGroups: options.allGroups,
platform: options.platform,
pageToken: options.pageToken,
template: options.template,
kind: options.kind,
priority: options.priority,
capacity: options.capacity,
name: options.name,
confirm: options.confirm,
recent: options.recent,
since: options.action === "errors" || options.action === "events" || options.action === "infrastructure" ? options.since : undefined,
tail: options.action === "errors" || options.action === "events" || options.action === "infrastructure" ? options.tail : undefined,
},
runtime: options.action === "events"
? compactRuntimeEvents(parsed)
: options.json && (options.action === "apply" || options.action === "delete")
? compactRuntimeMutationJson(parsed)
: compactRuntimeErrors(parsed, options),
remote: compactCapture(result, { full: result.exitCode !== 0 || parsed === null }),
disclosure: options.action === "list"
? {
get: "bun scripts/cli.ts platform-infra sub2api codex-pool runtime get --account <name-or-id>",
errors: "bun scripts/cli.ts platform-infra sub2api codex-pool runtime errors [--account <name-or-id>] [--since 24h]",
}
: undefined,
valuesPrinted: false,
};
return options.full || options.json ? response : renderRuntimeResult(response, options);
}
function renderRuntimeHelp(args: string[]): RenderedCliResult {
const actions = ["list", "get", "errors", "events", "infrastructure", "apply", "delete"] as const;
const requested = actions.includes(args[0] as typeof actions[number]) ? args[0] as typeof actions[number] : null;
const command = `platform-infra sub2api codex-pool runtime${requested === null ? "" : ` ${requested}`} --help`;
const common = [
" --target <id> YAML-selected Sub2API target",
" --json | --full | --raw Explicit structured or expanded disclosure",
];
const actionHelp: Record<typeof actions[number], string[]> = {
list: [
"Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime list [--recent <duration>] [--target <id>] [--json|--full|--raw]",
"",
"Options:",
" --recent <duration> Show accounts created in the recent m/h/d window",
...common,
],
get: [
"Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime get --account <name-or-id> [--target <id>] [--json|--full|--raw]",
"",
"Options:",
" --account <name-or-id> Exact account selector",
...common,
],
errors: [
"Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime errors [--group <name-or-id>|--all-groups] [--account <name-or-id>] [--platform <name>] [--since <duration>] [--target <id>] [--json|--full|--raw]",
"",
"Options:",
" --group <name-or-id> Analyze one group",
" --all-groups List every group summary; use --page-token to continue",
" --account <name-or-id> Drill into one account after selecting a group",
" --platform <name> Filter by platform",
" --page-token <group-id> Continue --all-groups pagination",
" --since <duration> Analysis window such as 30m, 8h, or 7d",
" --tail <count> Bounded runtime event tail (100..200000)",
...common,
"",
"Next: rerun with --group <name-or-id>, then --account <name-or-id> or trace --request-id <id>.",
],
events: [
"Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime events [--since <duration>] [--tail <count>] [--target <id>] [--json|--full|--raw]",
"",
"Options:",
" --since <duration> Policy-event window such as 30m or 8h",
" --tail <count> Bounded runtime event tail (100..200000)",
...common,
],
infrastructure: [
"Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime infrastructure --account <name-or-id> [--group <name-or-id>] [--platform <name>] [--since <duration>] [--target <id>] [--json|--full|--raw]",
"",
"Options:",
" --account <name-or-id> Exact account selector",
" --group <name-or-id> Optional group context",
" --platform <name> Optional platform context",
" --since <duration> Recent infrastructure error window",
...common,
],
apply: [
"Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime apply (--account <selector>|--accounts <selectors>|--select-configured-policy --account-type apikey) --kind <kind> [kind options] [--confirm] [--target <id>]",
"",
"Kinds:",
" temp-unschedulable Requires --template <id>",
" priority Requires --priority <1-1000>; lower is higher",
" capacity Requires --capacity <1-100000>; account concurrency guard",
" account-name Requires one --account and --name <new-name>",
"",
"Selection:",
" --exclude-accounts <selectors> Exclude explicit exceptions from configured-policy selection",
" --confirm Write after reviewing the default dry-run",
...common,
],
delete: [
"Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime delete (--account <selector>|--accounts <selectors>|--select-configured-policy --account-type apikey) --kind temp-unschedulable [--confirm] [--target <id>]",
"",
"Options:",
" --exclude-accounts <selectors> Exclude explicit exceptions from configured-policy selection",
" --confirm Write after reviewing the default dry-run",
...common,
],
};
const lines = requested === null
? [
"Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime <action> [options]",
"",
`Actions: ${actions.join(", ")}`,
"",
"Run runtime <action> --help for action-specific options. Help is local and does not submit a remote job.",
]
: actionHelp[requested];
lines.push("", "STATE mutation=false remoteJobSubmitted=false");
return {
ok: true,
command,
renderedText: lines.join("\n"),
contentType: "text/plain",
projection: { ok: true, mutation: false, remoteJobSubmitted: false, action: requested },
};
}
function compactRuntimeEvents(parsed: Record<string, unknown> | null): Record<string, unknown> | null {
if (parsed === null) return null;
return {
ok: parsed.ok,
error: parsed.error,
operation: parsed.operation,
source: parsed.source,
window: parsed.window,
tail: parsed.tail,
scannedLineCount: parsed.scannedLineCount,
policyEventCount: parsed.policyEventCount,
completionEventCount: parsed.completionEventCount,
eventCount: parsed.eventCount,
events: Array.isArray(parsed.events) ? parsed.events : [],
mutation: false,
valuesPrinted: false,
};
}
function compactRuntimeMutationJson(parsed: Record<string, unknown> | null): Record<string, unknown> | null {
if (parsed === null) return null;
const items = Array.isArray(parsed.items) ? parsed.items.filter(isRecord) : [];
const confirmed = parsed.mode === "confirmed";
return {
ok: parsed.ok,
operation: parsed.operation,
mode: parsed.mode,
mutation: parsed.mutation,
partialWrite: parsed.partialWrite,
selection: parsed.selection,
summary: parsed.summary,
items: items.map((item) => {
const write = isRecord(item.write) ? item.write : {};
const desiredDiffers = JSON.stringify(item.desired) !== JSON.stringify(item.before);
return {
accountName: item.accountName,
accountId: item.accountId,
selectionReason: item.selectionReason,
change: item.change,
template: item.template,
before: item.before,
desired: desiredDiffers ? item.desired : null,
actual: confirmed ? item.actual : undefined,
writeStatus: write.status,
writeError: write.error,
reconciled: item.reconciled,
reconcileError: item.reconcileError,
};
}),
credentialsPrinted: false,
valuesPrinted: false,
};
}