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 | 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 ", errors: "bun scripts/cli.ts platform-infra sub2api codex-pool runtime errors [--account ] [--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 YAML-selected Sub2API target", " --json | --full | --raw Explicit structured or expanded disclosure", ]; const actionHelp: Record = { list: [ "Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime list [--recent ] [--target ] [--json|--full|--raw]", "", "Options:", " --recent 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 [--target ] [--json|--full|--raw]", "", "Options:", " --account Exact account selector", ...common, ], errors: [ "Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime errors [--group |--all-groups] [--account ] [--platform ] [--since ] [--target ] [--json|--full|--raw]", "", "Options:", " --group Analyze one group", " --all-groups List every group summary; use --page-token to continue", " --account Drill into one account after selecting a group", " --platform Filter by platform", " --page-token Continue --all-groups pagination", " --since Analysis window such as 30m, 8h, or 7d", " --tail Bounded runtime event tail (100..200000)", ...common, "", "Next: rerun with --group , then --account or trace --request-id .", ], events: [ "Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime events [--since ] [--tail ] [--target ] [--json|--full|--raw]", "", "Options:", " --since Policy-event window such as 30m or 8h", " --tail Bounded runtime event tail (100..200000)", ...common, ], infrastructure: [ "Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime infrastructure --account [--group ] [--platform ] [--since ] [--target ] [--json|--full|--raw]", "", "Options:", " --account Exact account selector", " --group Optional group context", " --platform Optional platform context", " --since Recent infrastructure error window", ...common, ], apply: [ "Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime apply (--account |--accounts |--select-configured-policy --account-type apikey) --kind [kind options] [--confirm] [--target ]", "", "Kinds:", " temp-unschedulable Requires --template ", " priority Requires --priority <1-1000>; lower is higher", " capacity Requires --capacity <1-100000>; account concurrency guard", " account-name Requires one --account and --name ", "", "Selection:", " --exclude-accounts 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 |--accounts |--select-configured-policy --account-type apikey) --kind temp-unschedulable [--confirm] [--target ]", "", "Options:", " --exclude-accounts 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 [options]", "", `Actions: ${actions.join(", ")}`, "", "Run runtime --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 | null): Record | 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 | null): Record | 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, }; }