Files
pikasTech-unidesk/scripts/src/platform-infra-sub2api-codex/accounts.ts
T
2026-06-25 16:16:25 +00:00

82 lines
3.7 KiB
TypeScript

// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. accounts module for scripts/src/platform-infra-sub2api-codex.ts.
// Moved mechanically from scripts/src/platform-infra-sub2api-codex.ts:4209-4264 for #903.
import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
import type { UniDeskConfig } from "../config";
import { rootPath } from "../config";
import type { RenderedCliResult } from "../output";
import { applyPk01CaddyBlock, prepareFrpcSecret, renderFrpcManifest, type PublicServiceExposure, type PublicServiceTarget } from "../platform-infra-public-service";
import { shortSha256Fingerprint } from "../platform-infra-ops-library";
import {
codexPoolSentinelSummary,
codexPoolSentinelRuntimeImage,
readCodexPoolSentinelConfig,
renderCodexPoolSentinelManifest,
type CodexPoolSentinelConfig,
type CodexPoolSentinelProfileSecret,
} from "../platform-infra-sub2api-codex-sentinel";
import { parseEnvFile, readTextFile, redactRepoPath, requiredEnvValue } from "../secrets";
import { runSshCommandCapture, type SshCaptureResult } from "../ssh";
import type { CodexPoolConfig, OpenAIResponsesWebSocketsV2Mode } from "./types";
import { renderSub2ApiTempUnschedulableCredentials, uniqueAccountName } from "./redaction";
export function desiredAccountNames(pool: CodexPoolConfig): string[] {
return Object.keys(desiredAccountCapacityMap(pool)).sort();
}
export function desiredAccountCapacityTotal(pool: CodexPoolConfig): number {
return Object.values(desiredAccountCapacityMap(pool)).reduce((total, value) => total + value, 0);
}
export function desiredAccountCapacityMap(pool: CodexPoolConfig): Record<string, number> {
const codexDir = join(homedir(), ".codex");
const seenAccountNames = new Set<string>();
const capacities: Record<string, number> = {};
for (const entry of pool.profiles) {
const accountName = entry.accountName ?? uniqueAccountName(entry.profile, seenAccountNames);
seenAccountNames.add(accountName);
capacities[accountName] = entry.capacity ?? pool.defaultAccountCapacity;
}
return capacities;
}
export function desiredAccountLoadFactorMap(pool: CodexPoolConfig): Record<string, number> {
const codexDir = join(homedir(), ".codex");
const seenAccountNames = new Set<string>();
const loadFactors: Record<string, number> = {};
for (const entry of pool.profiles) {
const accountName = entry.accountName ?? uniqueAccountName(entry.profile, seenAccountNames);
seenAccountNames.add(accountName);
loadFactors[accountName] = entry.loadFactor ?? pool.defaultAccountLoadFactor;
}
return loadFactors;
}
export function desiredAccountWebSocketsV2ModeMap(pool: CodexPoolConfig): Record<string, OpenAIResponsesWebSocketsV2Mode | null> {
const codexDir = join(homedir(), ".codex");
const seenAccountNames = new Set<string>();
const modes: Record<string, OpenAIResponsesWebSocketsV2Mode | null> = {};
for (const entry of pool.profiles) {
const accountName = entry.accountName ?? uniqueAccountName(entry.profile, seenAccountNames);
seenAccountNames.add(accountName);
modes[accountName] = entry.openaiResponsesWebSocketsV2Mode;
}
return modes;
}
export function desiredAccountTempUnschedulableMap(pool: CodexPoolConfig): Record<string, unknown> {
const codexDir = join(homedir(), ".codex");
const seenAccountNames = new Set<string>();
const policies: Record<string, unknown> = {};
for (const entry of pool.profiles) {
const accountName = entry.accountName ?? uniqueAccountName(entry.profile, seenAccountNames);
seenAccountNames.add(accountName);
policies[accountName] = renderSub2ApiTempUnschedulableCredentials(entry.tempUnschedulable);
}
return policies;
}