Files
pikasTech-HWLAB/internal/cloud/server.ts
T
2026-06-19 01:16:00 +08:00

1877 lines
76 KiB
TypeScript

/*
* SPEC: PJ2026-010403 API契约 draft-2026-06-17-r0; PJ2026-010401 Web工作台 draft-2026-06-17-r0; PJ2026-01060505 Workbench Performance draft-2026-06-17-p0
* 职责: Cloud API REST/SSE route dispatcher。Workbench 新资源路由应委托 read model / compat wrapper,不在 dispatcher 内写业务事实。
*/
import { createServer } from "node:http";
import { randomUUID } from "node:crypto";
import { copyFileSync, existsSync, lstatSync, mkdirSync, symlinkSync } from "node:fs";
import path from "node:path";
import {
buildMetadataFromEnv,
normalizeIsoTimestamp
} from "../build-metadata.mjs";
import { DEV_ENDPOINT, ENVIRONMENT_DEV, ERROR_CODES, SERVICE_IDS } from "../protocol/index.mjs";
import {
AUDIT_FIELD_NAMES,
CLOUD_API_SERVICE_ID,
createAuditRecord
} from "../audit/index.mjs";
import {
SUPPORTED_RPC_METHODS,
createErrorEnvelope,
createResultEnvelope,
handleJsonRpcRequest
} from "./json-rpc.ts";
import {
describeCodeAgentAvailability,
handleCodeAgentChat
} from "./code-agent-chat.ts";
import { createDurableCodeAgentTraceStore, defaultCodeAgentTraceStore } from "./code-agent-trace-store.ts";
import { createCodeAgentSessionRegistry } from "./code-agent-session-registry.ts";
import { codeAgentSessionLifecycleSummary } from "./code-agent-session-lifecycle.ts";
import { createCodexStdioSessionManager } from "./codex-stdio-session.ts";
import { buildGateDiagnosticsRows } from "./gate-diagnostics.ts";
import {
applyRuntimeDbReadinessLayers,
buildDbRuntimeReadiness
} from "./db-contract.ts";
import { buildCloudApiReadiness } from "./health-contract.ts";
import {
M3_IO_CONTROL_ROUTE,
M3_STATUS_ROUTE,
describeM3IoControl,
describeM3IoControlLive,
describeM3StatusLive,
handleM3IoControl
} from "./m3-io-control.ts";
import { createConfiguredCloudRuntimeStore } from "../db/runtime-store.ts";
import { createAccessController } from "./access-control.ts";
import { createGatewayDemoRegistry } from "./gateway-demo-registry.ts";
import { buildLiveBuildsPayload } from "./server-rest-payloads.ts";
import {
createWebPerformanceStore,
handleWebPerformanceIngestHttp,
handleWebPerformanceMetricsHttp,
handleWebPerformanceSummaryHttp
} from "./web-performance.ts";
import { createBackendPerformanceStore, withBackendPerformanceContext } from "./backend-performance.ts";
import {
createCodeAgentChatResultStore,
handleCodeAgentCancelHttp,
handleCodeAgentChatHttp,
handleCodeAgentChatResultHttp,
handleCodeAgentInspectHttp,
handleCodeAgentSessionsHttp,
handleCodeAgentSteerHttp,
handleCodeAgentTurnHttp,
handleCodeAgentTraceHttp
} from "./server-code-agent-http.ts";
import { handleWorkbenchReadModelHttp, handleWorkbenchRealtimeHttp } from "./server-workbench-http.ts";
import { startWorkbenchEmptySessionGc } from "./workbench-empty-session-gc.ts";
import { handleM3IoControlHttp } from "./server-m3-http.ts";
import { handleSkillsHttp } from "./server-skills-http.ts";
import { handleProviderProfileCatalogHttp, handleProviderProfilesHttp } from "./provider-profile-management.ts";
import {
configureSkillRuntime,
ensureCodexSkillsAggregationSync
} from "./skills-store.ts";
import { createHwpodNodeWsRegistry } from "./hwpod-node-ws-registry.ts";
import {
discoverHwpodSpecs,
hwpodSpecDiscoveryPayload,
hwpodSpecWorkspaceProbePlan
} from "./hwpod-spec-discovery.ts";
import { HWPOD_NODE_OPS, HWPOD_NODE_OPS_CONTRACT_VERSION } from "../../tools/src/hwpod-node-ops-contract.ts";
const DEFAULT_BODY_LIMIT_BYTES = 1024 * 1024;
const HWLAB_WEB_SESSION_COOKIE = "hwlab_session";
function runtimeEnvironment(env = process.env) {
const value = env.HWLAB_GITOPS_PROFILE || env.HWLAB_ENVIRONMENT || ENVIRONMENT_DEV;
return typeof value === "string" && value.trim() ? value.trim() : ENVIRONMENT_DEV;
}
export function createCloudApiServer(options = {}) {
const env = options.env ?? process.env;
ensureCodeAgentRuntimeBase(env);
const sessionRegistry = options.sessionRegistry || createCodeAgentSessionRegistry();
const runtimeStore = options.runtimeStore || createConfiguredCloudRuntimeStore({ ...options, env });
const traceStore = createDurableCodeAgentTraceStore({
traceStore: options.traceStore || defaultCodeAgentTraceStore,
traceEventStore: runtimeStore
});
const codexStdioManager = options.codexStdioManager || createCodexStdioSessionManager({ traceStore });
const codeAgentChatResults = options.codeAgentChatResults || createCodeAgentChatResultStore({
maxResults: parsePositiveInteger(env.HWLAB_CODE_AGENT_CHAT_RESULT_CACHE_SIZE, 256)
});
const webPerformanceStore = options.webPerformanceStore || createWebPerformanceStore({ env });
const backendPerformanceStore = options.backendPerformanceStore || createBackendPerformanceStore({ env });
const gatewayRegistry = options.gatewayRegistry || createGatewayDemoRegistry({
staleMs: parsePositiveInteger(env.HWLAB_GATEWAY_DEMO_STALE_MS, 30000),
dispatchTimeoutMs: parsePositiveInteger(env.HWLAB_GATEWAY_DISPATCH_TIMEOUT_MS, 120000)
});
const hwpodNodeWsRegistry = options.hwpodNodeWsRegistry || createHwpodNodeWsRegistry({ ...options, env });
const accessController = options.accessController || createAccessController({ ...options, env, runtimeStore, gatewayRegistry, traceStore, codeAgentChatResults });
if (typeof accessController.configureCodeAgentWorkspaceContext === "function") {
accessController.configureCodeAgentWorkspaceContext({ env, fetchImpl: options.fetchImpl, traceStore, codeAgentChatResults });
}
const workbenchEmptySessionGc = startWorkbenchEmptySessionGc({ env, accessController, logger: console });
const server = createServer(async (request, response) => {
const backendPerformance = backendPerformanceStore.beginHttpRequest(request, response);
await withBackendPerformanceContext(backendPerformance, async () => {
try {
await routeRequest(request, response, { ...options, env, runtimeStore, gatewayRegistry, hwpodNodeWsRegistry, accessController, sessionRegistry, traceStore, codexStdioManager, codeAgentChatResults, webPerformanceStore, backendPerformanceStore, backendPerformance });
} catch (error) {
if (error?.alreadySent) return;
backendPerformance.recordPhase({ phase: "route_exception", durationMs: 0, outcome: "error" });
sendJson(response, 500, {
error: {
code: "internal_error",
message: "hwlab-cloud-api request handling failed",
reason: error.message
}
});
}
});
});
server.on("close", () => workbenchEmptySessionGc.stop());
return server;
}
export function ensureCodeAgentRuntimeBase(env = process.env) {
const codeAgentAdapter = String(env.HWLAB_CODE_AGENT_ADAPTER ?? env.HWLAB_CODE_AGENT_PROVIDER ?? "").trim().toLowerCase();
const useCodexStdioRuntime = !codeAgentAdapter || codeAgentAdapter === "codex-stdio";
const skillRuntime = configureSkillRuntime(env);
if (!useCodexStdioRuntime) return;
const workspace = env.HWLAB_CODE_AGENT_CODEX_WORKSPACE || env.HWLAB_CODE_AGENT_WORKSPACE || "/workspace/hwlab";
const codexHome = env.CODEX_HOME || env.HWLAB_CODE_AGENT_CODEX_HOME || "/codex-home";
const appCodexCommand = "/app/node_modules/.bin/codex";
const localCodexCommand = path.join(process.cwd(), "node_modules", ".bin", "codex");
const codexCommand = existsSync(appCodexCommand)
? appCodexCommand
: existsSync(localCodexCommand)
? localCodexCommand
: appCodexCommand;
env.HWLAB_CODE_AGENT_WORKSPACE ||= workspace;
env.HWLAB_CODE_AGENT_CODEX_WORKSPACE ||= workspace;
env.HWLAB_CODE_AGENT_CODEX_SANDBOX ||= "danger-full-access";
env.HWLAB_CODE_AGENT_CODEX_STDIO_ENABLED ||= "1";
env.HWLAB_CODE_AGENT_CODEX_STDIO_SUPERVISOR ||= "repo-owned";
env.CODEX_HOME ||= codexHome;
env.HWLAB_CODE_AGENT_CODEX_COMMAND ||= codexCommand;
for (const target of [path.dirname(workspace), codexHome]) {
try {
mkdirSync(target, { recursive: true });
} catch {
// Runtime health reports the concrete missing/writable blocker.
}
}
try {
if (!existsSync(workspace)) {
if (workspace === "/workspace/hwlab" && existsSync("/app")) {
symlinkSync("/app", workspace, "dir");
} else {
mkdirSync(workspace, { recursive: true });
}
}
lstatSync(workspace);
ensurePreinstalledHwpodSpec({ workspace });
ensureCodexSkillsAggregationSync(skillRuntime);
} catch {
// Runtime health reports the concrete missing/writable blocker.
}
}
function ensurePreinstalledHwpodSpec({ workspace }) {
const source = path.resolve(process.cwd(), ".hwlab/hwpod-spec.yaml");
const target = path.join(workspace, ".hwlab/hwpod-spec.yaml");
const sourceMeta = path.resolve(process.cwd(), ".hwlab/hwpod-spec.meta.json");
const targetMeta = path.join(workspace, ".hwlab/hwpod-spec.meta.json");
if (!existsSync(source)) return;
mkdirSync(path.dirname(target), { recursive: true });
if (!existsSync(target)) copyFileSync(source, target);
if (existsSync(sourceMeta) && !existsSync(targetMeta)) copyFileSync(sourceMeta, targetMeta);
}
export async function buildHealthPayload(options = {}) {
const serviceId = CLOUD_API_SERVICE_ID;
const env = options.env ?? process.env;
ensureCodeAgentRuntimeBase(env);
const metadata = buildMetadataFromEnv(env, {
serviceId,
fallbackImageRepository: "ghcr.io/pikastech/hwlab-cloud-api"
});
const dbProbe = await buildDbRuntimeReadiness(env, options.dbProbe);
const codeAgent = await describeCodeAgentAvailability(env, options);
const runtime = await runtimeReadiness(options.runtimeStore ?? createConfiguredCloudRuntimeStore({ ...options, env }));
const db = applyRuntimeDbReadinessLayers(dbProbe, runtime);
const readiness = buildCloudApiReadiness({ db, codeAgent, runtime });
return {
serviceId,
environment: runtimeEnvironment(env),
status: readiness.status,
ready: readiness.ready,
revision: metadata.revision,
readiness,
blockers: readiness.blockers,
blockerCodes: readiness.blockerCodes,
service: {
id: serviceId,
role: "cloud-api",
healthPath: "/health",
livePath: "/health/live"
},
commit: metadata.commit,
image: metadata.image,
build: metadata.build,
runtimeIdentity: metadata.runtime,
endpoint: env.HWLAB_PUBLIC_ENDPOINT || DEV_ENDPOINT,
observedAt: new Date().toISOString(),
db,
codeAgent,
runtime
};
}
async function routeRequest(request, response, options) {
const url = new URL(request.url || "/", "http://hwlab-cloud-api.local");
if (request.method === "GET" && (url.pathname === "/health" || url.pathname === "/health/live")) {
sendJson(response, 200, await buildHealthPayload(options));
return;
}
if (request.method === "GET" && url.pathname === "/live") {
sendJson(response, 200, {
serviceId: CLOUD_API_SERVICE_ID,
status: "live"
});
return;
}
if (url.pathname === "/auth" || url.pathname.startsWith("/auth/")) {
await options.accessController.handleAuthRoute(request, response, url);
return;
}
if (request.method === "POST" && (url.pathname === "/rpc" || url.pathname === "/json-rpc")) {
await handleRpcHttpRequest(request, response, options);
return;
}
if (url.pathname === "/v1" || url.pathname.startsWith("/v1/")) {
await handleRestAdapter(request, response, url, options);
return;
}
sendRestError(request, response, 404, "not_found", "Route is not part of the L1 cloud-api runtime", {
operation: `${request.method || "GET"} ${url.pathname}`,
target: {
type: "route",
id: url.pathname
}
});
}
async function handleRpcHttpRequest(request, response, options) {
const body = await readBody(request, options.bodyLimitBytes);
let envelope;
try {
envelope = body ? JSON.parse(body) : {};
} catch (error) {
sendJson(
response,
400,
createErrorEnvelope({
id: "req_unassigned",
code: ERROR_CODES.parseError,
message: "Invalid JSON body",
data: {
reason: error.message
},
context: {
operation: "json_rpc.parse",
target: {
type: "http_route",
id: request.url || "/rpc"
},
result: "rejected"
}
})
);
return;
}
const rpcResponse = await handleJsonRpcRequest(envelope, {
adapter: "json-rpc",
runtimeStore: options.runtimeStore,
env: options.env,
dbProbe: options.dbProbe,
m3IoRequestJson: options.m3IoRequestJson,
gatewayRegistry: options.gatewayRegistry
});
sendJson(response, statusForRpcResponse(rpcResponse), rpcResponse);
}
async function handleRestAdapter(request, response, url, options) {
if (url.pathname === "/v1/web-performance" && request.method === "POST") {
await handleWebPerformanceIngestHttp(request, response, { store: options.webPerformanceStore });
return;
}
if (url.pathname === "/v1/web-performance/metrics" && request.method === "GET") {
handleWebPerformanceMetricsHttp(request, response, { store: options.webPerformanceStore, extraMetricsText: () => options.backendPerformanceStore.metricsText() });
return;
}
if (url.pathname === "/v1/web-performance/summary" && request.method === "GET") {
handleWebPerformanceSummaryHttp(request, response, { store: options.webPerformanceStore });
return;
}
if ((url.pathname === "/v1/usage/summary" || url.pathname === "/v1/billing/summary") && request.method === "GET") {
await handleUsageSummaryHttp(request, response, url, options);
return;
}
if (url.pathname === "/v1/redeem" && request.method === "POST") {
await handleRedeemHttp(request, response, options);
return;
}
if (url.pathname === "/v1/subscription/summary" && request.method === "GET") {
await handleSubscriptionSummaryHttp(request, response, options);
return;
}
if (url.pathname === "/v1/payments/summary" && request.method === "GET") {
await handlePaymentSummaryHttp(request, response, options);
return;
}
if (url.pathname === "/v1/admin/billing/summary" && request.method === "GET") {
await handleAdminBillingSummaryHttp(request, response, url, options);
return;
}
if (url.pathname === "/v1/admin/billing/plans" && request.method === "GET") {
await handleAdminBillingPlansHttp(request, response, options);
return;
}
if (url.pathname === "/v1/admin/billing/usage" && request.method === "GET") {
await handleAdminBillingUsageHttp(request, response, url, options);
return;
}
if (url.pathname === "/v1/admin/billing/usage/export" && request.method === "GET") {
await handleAdminBillingUsageExportHttp(request, response, url, options);
return;
}
if (url.pathname === "/v1/admin/billing/ledger" && request.method === "GET") {
await handleAdminBillingLedgerHttp(request, response, url, options);
return;
}
if (url.pathname === "/v1/admin/billing/ledger/export" && request.method === "GET") {
await handleAdminBillingLedgerExportHttp(request, response, url, options);
return;
}
if (url.pathname === "/v1/admin/billing/redeem-codes" && (request.method === "GET" || request.method === "POST")) {
await handleAdminBillingRedeemCodesHttp(request, response, url, options);
return;
}
const adminBillingRedeemCodeMatch = url.pathname.match(/^\/v1\/admin\/billing\/redeem-codes\/([^/]+)$/u);
if (adminBillingRedeemCodeMatch && request.method === "PATCH") {
await handleAdminBillingRedeemCodeHttp(request, response, decodeURIComponent(adminBillingRedeemCodeMatch[1]), options);
return;
}
if (url.pathname === "/v1/admin/billing/redeem-redemptions" && request.method === "GET") {
await handleAdminBillingRedeemRedemptionsHttp(request, response, url, options);
return;
}
if (url.pathname === "/v1/admin/billing/users" && (request.method === "GET" || request.method === "POST")) {
await handleAdminBillingUsersHttp(request, response, url, options);
return;
}
const adminBillingUserMatch = url.pathname.match(/^\/v1\/admin\/billing\/users\/([^/]+)$/u);
if (adminBillingUserMatch && (request.method === "GET" || request.method === "PATCH")) {
await handleAdminBillingUserHttp(request, response, url, decodeURIComponent(adminBillingUserMatch[1]), options);
return;
}
const adminBillingUserCreditsMatch = url.pathname.match(/^\/v1\/admin\/billing\/users\/([^/]+)\/credits\/adjust$/u);
if (adminBillingUserCreditsMatch && request.method === "POST") {
await handleAdminBillingCreditAdjustHttp(request, response, decodeURIComponent(adminBillingUserCreditsMatch[1]), options);
return;
}
const adminBillingUserStatusMatch = url.pathname.match(/^\/v1\/admin\/billing\/users\/([^/]+)\/status$/u);
if (adminBillingUserStatusMatch && request.method === "PATCH") {
await handleAdminBillingUserStatusHttp(request, response, decodeURIComponent(adminBillingUserStatusMatch[1]), options);
return;
}
if (request.method === "GET" && url.pathname === "/v1") {
const dbProbe = await buildDbRuntimeReadiness(options.env ?? process.env, options.dbProbe);
const codeAgent = await describeCodeAgentAvailability(options.env ?? process.env, options);
const runtime = await runtimeReadiness(options.runtimeStore);
const db = applyRuntimeDbReadinessLayers(dbProbe, runtime);
const readiness = buildCloudApiReadiness({ db, codeAgent, runtime });
sendJson(response, 200, {
serviceId: CLOUD_API_SERVICE_ID,
adapter: "rest",
status: readiness.status,
ready: readiness.ready,
rpcBridge: "POST /v1/rpc/{method}",
codeAgent,
methods: SUPPORTED_RPC_METHODS,
auditFields: AUDIT_FIELD_NAMES,
db,
runtime,
readiness,
blockers: readiness.blockers,
blockerCodes: readiness.blockerCodes,
hwpod: {
route: "/v1/hwpod-node-ops",
specDiscoveryRoute: "/v1/hwpod/specs",
contractVersion: HWPOD_NODE_OPS_CONTRACT_VERSION,
specAuthority: "workspace-or-registry",
compiler: "hwpod-compiler-cli",
apiRole: "node-ops-forwarder",
nodeRole: "thin-hwpod-node-executor",
supportedOps: Array.from(HWPOD_NODE_OPS)
},
m3IoControl: describeM3IoControl(options)
});
return;
}
if (url.pathname === "/v1/auth/session" || url.pathname === "/v1/auth/login" || url.pathname === "/v1/auth/logout" || url.pathname === "/v1/auth/register") {
const authUrl = new URL(url.href);
authUrl.pathname = url.pathname.replace(/^\/v1\/auth/u, "/auth");
await options.accessController.handleAuthRoute(request, response, authUrl);
return;
}
if (url.pathname === "/v1/skills" || url.pathname.startsWith("/v1/skills/")) {
await handleSkillsHttp(request, response, url, options);
return;
}
if (url.pathname === "/v1/users/me") {
await options.accessController.handleUserRoute(request, response, url);
return;
}
if (url.pathname === "/v1/users/me/profile" && request.method === "PATCH") {
await handleUserBillingProfileHttp(request, response, options);
return;
}
if (url.pathname === "/v1/users/me/password" && request.method === "POST") {
await handleUserBillingPasswordHttp(request, response, options);
return;
}
if (url.pathname === "/v1/api-keys" || url.pathname === "/v1/api-keys/default" || url.pathname.startsWith("/v1/api-keys/")) {
if (await maybeHandleUserBillingApiKeysHttp(request, response, url, options)) return;
await options.accessController.handleUserRoute(request, response, url);
return;
}
if (url.pathname === "/v1/workbench/events") {
await handleWorkbenchRealtimeHttp(request, response, url, options);
return;
}
if (url.pathname === "/v1/workbench/sessions" || url.pathname.startsWith("/v1/workbench/sessions/") || url.pathname.startsWith("/v1/workbench/turns/") || url.pathname.startsWith("/v1/workbench/traces/")) {
await handleWorkbenchReadModelHttp(request, response, url, options);
return;
}
if (url.pathname === "/v1/access/status" || url.pathname === "/v1/setup/status") {
await options.accessController.handleAccessStatusRoute(request, response, url);
return;
}
if (url.pathname === "/v1/setup/first-admin") {
await options.accessController.handleSetupRoute(request, response, url);
return;
}
if (url.pathname === "/v1/admin/provider-profiles" || url.pathname.startsWith("/v1/admin/provider-profiles/")) {
await handleProviderProfilesHttp(request, response, url, options);
return;
}
if (url.pathname === "/v1/provider-profiles" && request.method === "GET") {
await handleProviderProfileCatalogHttp(request, response, options);
return;
}
if (url.pathname.startsWith("/v1/admin/")) {
await options.accessController.handleAdminRoute(request, response, url);
return;
}
if (url.pathname === "/v1/hwpod-node-ops") {
await handleHwpodNodeOpsHttp(request, response, options);
return;
}
if (request.method === "GET" && url.pathname === "/v1/hwpod/specs") {
await handleHwpodSpecDiscoveryHttp(request, response, url, options);
return;
}
if (request.method === "GET" && url.pathname === "/v1/hwpod-node/ws") {
sendJson(response, 426, { ok: false, status: "upgrade_required", route: "/v1/hwpod-node/ws", websocket: options.hwpodNodeWsRegistry.describe() });
return;
}
if (request.method === "GET" && url.pathname === M3_IO_CONTROL_ROUTE) {
sendJson(response, 200, await describeM3IoControlLive(options));
return;
}
if (request.method === "GET" && url.pathname === M3_STATUS_ROUTE) {
sendJson(response, 200, await describeM3StatusLive(options));
return;
}
if (request.method === "GET" && url.pathname === "/v1/diagnostics/gate") {
sendJson(response, 200, await buildGateDiagnosticsRows(options));
return;
}
if (request.method === "GET" && url.pathname === "/v1/live-builds") {
sendJson(response, 200, await buildLiveBuildsPayload(options, { buildHealthPayload, runtimeEnvironment }));
return;
}
if (request.method === "GET" && url.pathname === "/v1/gateway/sessions") {
sendJson(response, 200, options.gatewayRegistry.describe());
return;
}
if (request.method === "POST" && url.pathname === "/v1/gateway/poll") {
await handleGatewayPollHttp(request, response, options);
return;
}
if (request.method === "POST" && url.pathname === "/v1/gateway/result") {
await handleGatewayResultHttp(request, response, options);
return;
}
if (request.method === "POST" && url.pathname === M3_IO_CONTROL_ROUTE) {
await handleM3IoControlHttp(request, response, options);
return;
}
if (request.method === "POST" && url.pathname === "/v1/agent/chat") {
const nextOptions = await codeAgentOptions(request, response, options);
if (!nextOptions) return;
await handleCodeAgentChatHttp(request, response, nextOptions);
return;
}
if (url.pathname === "/v1/agent/sessions" || url.pathname.startsWith("/v1/agent/sessions/")) {
const nextOptions = await codeAgentOptions(request, response, options, { required: true });
if (!nextOptions) return;
await handleCodeAgentSessionsHttp(request, response, url, nextOptions);
return;
}
if (request.method === "GET" && url.pathname === "/v1/agent/chat/inspect") {
const nextOptions = await codeAgentOptions(request, response, options);
if (!nextOptions) return;
await handleCodeAgentInspectHttp(request, response, url, nextOptions);
return;
}
if (request.method === "GET" && url.pathname.startsWith("/v1/agent/chat/result/")) {
const nextOptions = await codeAgentOptions(request, response, options);
if (!nextOptions) return;
await handleCodeAgentChatResultHttp(request, response, url, nextOptions);
return;
}
if (request.method === "GET" && url.pathname.startsWith("/v1/agent/turns/")) {
const nextOptions = await codeAgentOptions(request, response, options);
if (!nextOptions) return;
await handleCodeAgentTurnHttp(request, response, url, nextOptions);
return;
}
if (request.method === "GET" && url.pathname.startsWith("/v1/agent/traces/")) {
const nextOptions = await codeAgentOptions(request, response, options);
if (!nextOptions) return;
await handleCodeAgentTraceHttp(request, response, url, nextOptions);
return;
}
if (request.method === "POST" && url.pathname === "/v1/agent/chat/cancel") {
const nextOptions = await codeAgentOptions(request, response, options);
if (!nextOptions) return;
await handleCodeAgentCancelHttp(request, response, nextOptions);
return;
}
if (request.method === "POST" && url.pathname === "/v1/agent/chat/steer") {
const nextOptions = await codeAgentOptions(request, response, options);
if (!nextOptions) return;
await handleCodeAgentSteerHttp(request, response, nextOptions);
return;
}
if (request.method !== "POST" || !url.pathname.startsWith("/v1/rpc/")) {
sendRestError(request, response, 404, "not_found", "REST route is not implemented in the L1 cloud-api runtime", {
operation: `${request.method || "GET"} ${url.pathname}`,
target: {
type: "route",
id: url.pathname
}
});
return;
}
const method = decodeURIComponent(url.pathname.slice("/v1/rpc/".length));
const body = await readBody(request, options.bodyLimitBytes);
let params = {};
try {
params = body ? JSON.parse(body) : {};
} catch (error) {
sendRestError(request, response, 400, "parse_error", "Invalid JSON body", {
operation: method,
target: {
type: "rpc_method",
id: method
},
result: "rejected",
reason: error.message
});
return;
}
if (!params || typeof params !== "object" || Array.isArray(params)) {
sendRestError(request, response, 400, "invalid_params", "REST RPC bridge body must be a JSON object", {
operation: method,
target: {
type: "rpc_method",
id: method
},
result: "rejected"
});
return;
}
const rpcResponse = await handleJsonRpcRequest(
{
jsonrpc: "2.0",
id: getHeader(request, "x-request-id") || `req_${randomUUID()}`,
method,
params,
meta: {
traceId: getHeader(request, "x-trace-id") || `trc_${randomUUID()}`,
actorId: getHeader(request, "x-actor-id"),
serviceId: getHeader(request, "x-source-service-id") || CLOUD_API_SERVICE_ID,
environment: runtimeEnvironment(options.env ?? process.env)
}
},
{
adapter: "rest",
runtimeStore: options.runtimeStore,
env: options.env,
dbProbe: options.dbProbe,
m3IoRequestJson: options.m3IoRequestJson,
gatewayRegistry: options.gatewayRegistry
}
);
sendJson(response, statusForRpcResponse(rpcResponse), rpcResponse);
}
async function handleHwpodNodeOpsHttp(request, response, options) {
if (request.method === "GET") {
sendJson(response, 200, {
ok: true,
status: "ready",
contractVersion: HWPOD_NODE_OPS_CONTRACT_VERSION,
route: "/v1/hwpod-node-ops",
specAuthority: "code-agent-workspace",
compiler: "hwpod-compiler-cli",
apiRole: "node-ops-forwarder",
nodeRole: "thin-hwpod-node-executor",
supportedOps: Array.from(HWPOD_NODE_OPS),
websocket: options.hwpodNodeWsRegistry.describe()
});
return;
}
if (request.method !== "POST") {
sendJson(response, 405, { ok: false, error: { code: "method_not_allowed", message: "hwpod-node-ops only supports GET and POST" } });
return;
}
const body = await readJsonObject(request, options.bodyLimitBytes);
if (!body.ok) {
sendJson(response, 400, body.error);
return;
}
const validation = validateHwpodNodeOpsPlan(body.value);
if (!validation.ok) {
sendJson(response, 400, {
ok: false,
status: "rejected",
contractVersion: HWPOD_NODE_OPS_CONTRACT_VERSION,
error: validation.error
});
return;
}
const plan = validation.plan;
const requestMeta = {
requestId: getHeader(request, "x-request-id") || `req_hwpod_${randomUUID()}`,
traceId: getHeader(request, "x-trace-id") || `trc_hwpod_${randomUUID()}`,
serviceId: getHeader(request, "x-source-service-id") || CLOUD_API_SERVICE_ID,
environment: runtimeEnvironment(options.env ?? process.env)
};
try {
const handled = await dispatchHwpodNodeOpsPlan(plan, requestMeta, options, { request });
sendJson(response, handled.httpStatus, handled.payload);
} catch (error) {
sendJson(response, 200, hwpodNodeOpsBlockedPayload(plan, requestMeta, error?.message ?? "hwpod-node-ops handler failed"));
}
}
async function handleHwpodSpecDiscoveryHttp(request, response, url, options) {
const probe = truthyFlag(url.searchParams.get("probe"));
const observedAt = new Date().toISOString();
let specs = await discoverHwpodSpecs(options);
if (probe) {
specs = await Promise.all(specs.map((spec) => probeDiscoveredHwpodSpec(spec, { request, options, observedAt })));
}
sendJson(response, 200, hwpodSpecDiscoveryPayload(specs, { observedAt }));
}
async function probeDiscoveredHwpodSpec(spec, { request, options, observedAt }) {
if (spec.ok === false) return spec;
const plan = hwpodSpecWorkspaceProbePlan(spec);
const validation = validateHwpodNodeOpsPlan(plan);
if (!validation.ok) {
return {
...spec,
availability: {
ok: false,
status: "invalid_probe_plan",
checkedAt: observedAt,
blocker: validation.error
}
};
}
const requestMeta = {
requestId: getHeader(request, "x-request-id") || `req_hwpod_spec_${randomUUID()}`,
traceId: getHeader(request, "x-trace-id") || `trc_hwpod_spec_${randomUUID()}`,
serviceId: getHeader(request, "x-source-service-id") || CLOUD_API_SERVICE_ID,
environment: runtimeEnvironment(options.env ?? process.env)
};
const handled = await dispatchHwpodNodeOpsPlan(validation.plan, requestMeta, options, { request });
const payload = handled.payload;
return {
...spec,
availability: {
ok: payload.ok === true,
status: payload.ok === true ? "available" : "blocked",
checkedAt: observedAt,
probePlanId: payload.planId,
nodeOpsRoute: "/v1/hwpod-node-ops",
results: payload.results ?? [],
blocker: payload.blocker ?? null,
httpStatus: handled.httpStatus
}
};
}
async function dispatchHwpodNodeOpsPlan(plan, requestMeta, options, context = {}) {
const hwpodNodeOpsUrl = normalizedHwpodNodeOpsUrl(options.env ?? process.env);
const hwpodNodeWsRegistry = options.hwpodNodeWsRegistry;
const hasWsNode = hwpodNodeWsRegistry?.hasNode?.(plan.nodeId);
if (typeof options.hwpodNodeOpsHandler !== "function" && !hasWsNode && !hwpodNodeOpsUrl) {
return {
httpStatus: 200,
payload: hwpodNodeOpsBlockedPayload(plan, requestMeta, "no outbound WebSocket hwpod-node is connected and HWLAB_HWPOD_NODE_OPS_URL is not configured; cloud-api is only validating the hwpod-node-ops contract")
};
}
const handled = typeof options.hwpodNodeOpsHandler === "function"
? await options.hwpodNodeOpsHandler(plan, { request: context.request, requestMeta, env: options.env ?? process.env })
: hasWsNode
? await hwpodNodeWsRegistry.dispatch(plan, requestMeta, { timeoutMs: parsePositiveInteger(options.env?.HWLAB_HWPOD_NODE_OPS_TIMEOUT_MS, 30000) })
: await forwardHwpodNodeOpsPlan(hwpodNodeOpsUrl, plan, requestMeta, options);
const results = Array.isArray(handled?.results) ? handled.results : [];
const failed = results.some((item) => item?.ok === false);
const payload = {
ok: handled?.ok ?? !failed,
status: handled?.status ?? (failed ? "failed" : "completed"),
contractVersion: HWPOD_NODE_OPS_CONTRACT_VERSION,
planId: plan.planId,
hwpodId: plan.hwpodId,
nodeId: plan.nodeId,
acceptedOps: plan.ops.length,
results,
blocker: handled?.blocker ?? null,
requestMeta
};
return { httpStatus: handled?.httpStatus ?? (failed ? 409 : 200), payload };
}
async function forwardHwpodNodeOpsPlan(targetUrl, plan, requestMeta, options) {
const target = await describeDirectHwpodNode(targetUrl, options);
if (!target.ok || !target.nodeId) {
return directHwpodNodeBlocked(plan, "hwpod_node_identity_unverified", "configured hwpod-node URL did not expose a verifiable nodeId", {
requestedNodeId: plan.nodeId,
targetUrl: redactNodeOpsUrl(targetUrl),
dispatchMode: "direct-url",
targetStatus: target.status ?? null,
error: target.error ?? null
});
}
if (target.ok && target.nodeId && target.nodeId !== plan.nodeId) {
return directHwpodNodeBlocked(plan, "hwpod_node_not_connected", `${plan.nodeId} is not connected via WebSocket and HWLAB_HWPOD_NODE_OPS_URL points to ${target.nodeId}`, {
requestedNodeId: plan.nodeId,
targetNodeId: target.nodeId,
targetUrl: redactNodeOpsUrl(targetUrl),
dispatchMode: "direct-url"
});
}
const response = await fetch(targetUrl, {
method: "POST",
headers: {
"content-type": "application/json",
"x-request-id": requestMeta.requestId,
"x-trace-id": requestMeta.traceId,
"x-source-service-id": CLOUD_API_SERVICE_ID
},
body: JSON.stringify(plan),
signal: AbortSignal.timeout(parsePositiveInteger(options.env?.HWLAB_HWPOD_NODE_OPS_TIMEOUT_MS, 30000))
});
const body = await response.json().catch(() => null);
if (!body || typeof body !== "object") {
return {
ok: false,
status: "blocked",
httpStatus: 200,
results: [],
blocker: {
code: "hwpod_node_response_invalid",
layer: "hwpod-node",
retryable: true,
summary: `hwpod-node returned HTTP ${response.status} without a JSON object payload`
}
};
}
return {
ok: body.ok,
status: body.status,
httpStatus: response.status,
results: body.results,
blocker: body.blocker ?? null
};
}
function directHwpodNodeBlocked(plan, code, summary, details) {
const blocker = { code, layer: "hwpod-node", retryable: true, summary, details };
return {
ok: false,
status: "blocked",
httpStatus: 200,
results: plan.ops.map((op) => ({ opId: op.opId, op: op.op, ok: false, status: "blocked", blocker })),
blocker
};
}
async function describeDirectHwpodNode(targetUrl, options) {
try {
const response = await fetch(targetUrl, {
method: "GET",
signal: AbortSignal.timeout(parsePositiveInteger(options.env?.HWLAB_HWPOD_NODE_OPS_TIMEOUT_MS, 30000))
});
const body = await response.json().catch(() => null);
return { ok: response.ok && body && typeof body === "object", status: response.status, nodeId: safeOpaqueId(body?.nodeId), body };
} catch (error) {
return { ok: false, error: error instanceof Error ? error.message : String(error), nodeId: "" };
}
}
function redactNodeOpsUrl(value) {
try {
const parsed = new URL(value);
parsed.username = "";
parsed.password = "";
parsed.search = parsed.search ? "?redacted=1" : "";
return parsed.toString();
} catch {
return "<invalid-url>";
}
}
function normalizedHwpodNodeOpsUrl(env = process.env) {
const direct = String(env.HWLAB_HWPOD_NODE_OPS_URL ?? "").trim();
if (direct) return direct;
const base = String(env.HWLAB_HWPOD_NODE_URL ?? "").trim().replace(/\/+$/u, "");
return base ? `${base}/v1/hwpod-node-ops` : "";
}
function validateHwpodNodeOpsPlan(value) {
if (!value || typeof value !== "object" || Array.isArray(value)) {
return { ok: false, error: { code: "invalid_hwpod_node_ops_plan", message: "hwpod-node-ops body must be a JSON object" } };
}
if (value.contractVersion !== HWPOD_NODE_OPS_CONTRACT_VERSION) {
return { ok: false, error: { code: "invalid_hwpod_node_ops_contract", message: `contractVersion must be ${HWPOD_NODE_OPS_CONTRACT_VERSION}`, actual: value.contractVersion ?? null } };
}
const planId = safeOpaqueId(value.planId) || `hwpod_plan_${randomUUID()}`;
const nodeId = safeOpaqueId(value.nodeId);
const hwpodId = safeOpaqueId(value.hwpodId);
if (!nodeId) return { ok: false, error: { code: "invalid_hwpod_node_id", message: "nodeId is required" } };
if (!hwpodId) return { ok: false, error: { code: "invalid_hwpod_id", message: "hwpodId is required" } };
if (!Array.isArray(value.ops) || value.ops.length === 0) {
return { ok: false, error: { code: "invalid_hwpod_node_ops", message: "ops must be a non-empty array" } };
}
const ops = [];
for (const [index, item] of value.ops.entries()) {
if (!item || typeof item !== "object" || Array.isArray(item)) {
return { ok: false, error: { code: "invalid_hwpod_node_op", message: `ops[${index}] must be a JSON object` } };
}
const op = typeof item.op === "string" ? item.op.trim() : "";
if (!HWPOD_NODE_OPS.has(op)) {
return { ok: false, error: { code: "unsupported_hwpod_node_op", message: `unsupported hwpod-node op: ${op || "<empty>"}`, supportedOps: Array.from(HWPOD_NODE_OPS) } };
}
ops.push({
opId: safeOpaqueId(item.opId) || `op_${index + 1}`,
op,
args: item.args && typeof item.args === "object" && !Array.isArray(item.args) ? item.args : {}
});
}
return {
ok: true,
plan: {
...value,
planId,
hwpodId,
nodeId,
ops
}
};
}
function hwpodNodeOpsBlockedPayload(plan, requestMeta, summary) {
return {
ok: false,
status: "blocked",
contractVersion: HWPOD_NODE_OPS_CONTRACT_VERSION,
planId: plan.planId,
hwpodId: plan.hwpodId,
nodeId: plan.nodeId,
acceptedOps: plan.ops.length,
results: plan.ops.map((op) => ({
opId: op.opId,
op: op.op,
ok: false,
status: "blocked",
blocker: {
code: "hwpod_node_unavailable",
layer: "hwpod-node",
retryable: true,
summary,
userMessage: "hwpod-node 尚未接入执行面;cloud-api 已完成 hwpod-node-ops 合同校验。"
}
})),
blocker: {
code: "hwpod_node_unavailable",
layer: "hwpod-node",
retryable: true,
summary
},
requestMeta
};
}
async function codeAgentOptions(request, response, options, authOptions = {}) {
const auth = await options.accessController.authenticate(request, { required: authOptions.required ?? options.accessController.required });
if (!auth.ok) {
sendJson(response, auth.status, auth);
return null;
}
return {
...options,
actor: auth.actor ?? null,
authSession: auth.session ?? null,
authApiKey: auth.apiKey ?? null,
actorApiKeySecret: auth.apiKey?.displaySecret ?? null,
userBillingAuth: auth.userBilling ?? null,
userBillingToken: userBillingTokenFromAuth(auth),
userBillingClient: options.userBillingClient ?? options.accessController?.userBilling ?? null
};
}
async function handleUsageSummaryHttp(request, response, url, options) {
const route = url.pathname === "/v1/billing/summary" ? "/v1/billing/summary" : "/v1/usage/summary";
const nextOptions = await codeAgentOptions(request, response, options, { required: true });
if (!nextOptions) return;
const client = nextOptions.userBillingClient;
const token = nextOptions.userBillingToken;
if (nextOptions.userBillingAuth?.active !== true || !token) {
sendRestError(request, response, 403, "user_billing_auth_required", "usage summary requires a user-billing session or API key", {
operation: `GET ${route}`,
target: { type: "route", id: route },
result: "rejected"
});
return;
}
if (!client?.configured || typeof client.billingSummary !== "function") {
sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing summary is not configured", {
operation: `GET ${route}`,
target: { type: "service", id: "hwlab-user-billing" }
});
return;
}
const limit = parsePositiveInteger(url.searchParams.get("limit"), 20);
const result = await client.billingSummary(token, { limit: Math.min(limit, 100) });
if (!result.ok) {
sendRestError(request, response, result.status ?? 502, result.error?.code ?? "user_billing_summary_failed", result.error?.message ?? "user-billing summary request failed", {
operation: `GET ${route}`,
target: { type: "service", id: "hwlab-user-billing" },
reason: result.error?.code,
result: "failed"
});
return;
}
sendJson(response, 200, {
...(result.body ?? {}),
proxy: {
serviceId: CLOUD_API_SERVICE_ID,
route,
source: "hwlab-user-billing",
valuesRedacted: true
}
});
}
async function handleAdminBillingSummaryHttp(request, response, url, options) {
const auth = await options.accessController.authenticate(request, { required: true });
if (!auth.ok) {
sendJson(response, auth.status, auth);
return;
}
if (auth.actor?.role !== "admin") {
sendRestError(request, response, 403, "admin_required", "Only admin users can read billing summaries", {
operation: "GET /v1/admin/billing/summary",
target: { type: "route", id: "/v1/admin/billing/summary" },
result: "rejected"
});
return;
}
const client = options.userBillingClient ?? options.accessController?.userBilling ?? null;
if (!client?.configured || typeof client.adminBillingSummary !== "function") {
sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin summary is not configured", {
operation: "GET /v1/admin/billing/summary",
target: { type: "service", id: "hwlab-user-billing" }
});
return;
}
const limit = parsePositiveInteger(url.searchParams.get("limit"), 50);
const result = await client.adminBillingSummary({ limit: Math.min(limit, 100) });
if (!result.ok) {
sendRestError(request, response, result.status ?? 502, result.error?.code ?? "user_billing_admin_summary_failed", result.error?.message ?? "user-billing admin summary request failed", {
operation: "GET /v1/admin/billing/summary",
target: { type: "service", id: "hwlab-user-billing" },
reason: result.error?.code,
result: "failed"
});
return;
}
sendJson(response, 200, {
...(result.body ?? {}),
actor: adminActorSummary(auth.actor),
proxy: {
serviceId: CLOUD_API_SERVICE_ID,
route: "/v1/admin/billing/summary",
source: "hwlab-user-billing",
valuesRedacted: true
}
});
}
async function requireAdminBillingClient(request, response, options, operation) {
const auth = await options.accessController.authenticate(request, { required: true });
if (!auth.ok) {
sendJson(response, auth.status, auth);
return null;
}
if (auth.actor?.role !== "admin") {
sendRestError(request, response, 403, "admin_required", "Only admin users can call user billing admin APIs", {
operation,
target: { type: "route", id: operation },
result: "rejected"
});
return null;
}
const client = options.userBillingClient ?? options.accessController?.userBilling ?? null;
if (!client?.configured) {
sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin API is not configured", {
operation,
target: { type: "service", id: "hwlab-user-billing" }
});
return null;
}
return { auth, client };
}
async function requireUserBillingClient(request, response, options, operation) {
const nextOptions = await codeAgentOptions(request, response, options, { required: true });
if (!nextOptions) return null;
const client = nextOptions.userBillingClient;
const token = nextOptions.userBillingToken;
if (nextOptions.userBillingAuth?.active !== true || !token) {
sendRestError(request, response, 403, "user_billing_auth_required", "user-billing session or API key is required", {
operation,
target: { type: "route", id: operation },
result: "rejected"
});
return null;
}
if (!client?.configured) {
sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing API is not configured", {
operation,
target: { type: "service", id: "hwlab-user-billing" }
});
return null;
}
return { auth: nextOptions, client, token };
}
async function handleRedeemHttp(request, response, options) {
const context = await requireUserBillingClient(request, response, options, "POST /v1/redeem");
if (!context) return;
const { auth, client, token } = context;
if (typeof client.redeem !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing redeem API is not configured", { operation: "POST /v1/redeem", target: { type: "service", id: "hwlab-user-billing" } });
}
const parsed = await readJsonObject(request, DEFAULT_BODY_LIMIT_BYTES);
if (!parsed.ok) return sendJson(response, 400, parsed.error);
const result = await client.redeem(token, parsed.value);
sendUserBillingProxyResult({ request, response, result, operation: "POST /v1/redeem", route: "/v1/redeem", actor: adminActorSummary(auth.actor) });
}
async function handleSubscriptionSummaryHttp(request, response, options) {
const context = await requireUserBillingClient(request, response, options, "GET /v1/subscription/summary");
if (!context) return;
const { auth, client, token } = context;
if (typeof client.subscriptionSummary !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing subscription API is not configured", { operation: "GET /v1/subscription/summary", target: { type: "service", id: "hwlab-user-billing" } });
}
const result = await client.subscriptionSummary(token);
sendUserBillingProxyResult({ request, response, result, operation: "GET /v1/subscription/summary", route: "/v1/subscription/summary", actor: adminActorSummary(auth.actor) });
}
async function handlePaymentSummaryHttp(request, response, options) {
const context = await requireUserBillingClient(request, response, options, "GET /v1/payments/summary");
if (!context) return;
const { auth, client, token } = context;
if (typeof client.paymentSummary !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing payment API is not configured", { operation: "GET /v1/payments/summary", target: { type: "service", id: "hwlab-user-billing" } });
}
const result = await client.paymentSummary(token);
sendUserBillingProxyResult({ request, response, result, operation: "GET /v1/payments/summary", route: "/v1/payments/summary", actor: adminActorSummary(auth.actor) });
}
async function handleAdminBillingUsersHttp(request, response, url, options) {
const context = await requireAdminBillingClient(request, response, options, `${request.method} /v1/admin/billing/users`);
if (!context) return;
const { auth, client } = context;
let result;
if (request.method === "GET") {
if (typeof client.adminUsers !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin users API is not configured", { operation: "GET /v1/admin/billing/users", target: { type: "service", id: "hwlab-user-billing" } });
}
result = await client.adminUsers({
page: parsePositiveInteger(url.searchParams.get("page"), 1),
pageSize: Math.min(parsePositiveInteger(url.searchParams.get("pageSize") || url.searchParams.get("limit"), 50), 100),
search: url.searchParams.get("search") ?? "",
status: url.searchParams.get("status") ?? "",
role: url.searchParams.get("role") ?? ""
});
} else {
if (typeof client.createAdminUser !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin user create API is not configured", { operation: "POST /v1/admin/billing/users", target: { type: "service", id: "hwlab-user-billing" } });
}
const parsed = await readJsonObject(request, DEFAULT_BODY_LIMIT_BYTES);
if (!parsed.ok) return sendJson(response, 400, parsed.error);
result = await client.createAdminUser(parsed.value);
}
sendUserBillingProxyResult({ request, response, result, operation: `${request.method} /v1/admin/billing/users`, route: "/v1/admin/billing/users", actor: adminActorSummary(auth.actor) });
}
async function handleAdminBillingPlansHttp(request, response, options) {
const context = await requireAdminBillingClient(request, response, options, "GET /v1/admin/billing/plans");
if (!context) return;
const { auth, client } = context;
if (typeof client.adminBillingPlans !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin plans API is not configured", { operation: "GET /v1/admin/billing/plans", target: { type: "service", id: "hwlab-user-billing" } });
}
const result = await client.adminBillingPlans();
sendUserBillingProxyResult({ request, response, result, operation: "GET /v1/admin/billing/plans", route: "/v1/admin/billing/plans", actor: adminActorSummary(auth.actor) });
}
async function handleAdminBillingUsageHttp(request, response, url, options) {
const context = await requireAdminBillingClient(request, response, options, "GET /v1/admin/billing/usage");
if (!context) return;
const { auth, client } = context;
if (typeof client.adminUsage !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin usage API is not configured", { operation: "GET /v1/admin/billing/usage", target: { type: "service", id: "hwlab-user-billing" } });
}
const result = await client.adminUsage(adminAuditParams(url));
sendUserBillingProxyResult({ request, response, result, operation: "GET /v1/admin/billing/usage", route: "/v1/admin/billing/usage", actor: adminActorSummary(auth.actor) });
}
async function handleAdminBillingUsageExportHttp(request, response, url, options) {
const context = await requireAdminBillingClient(request, response, options, "GET /v1/admin/billing/usage/export");
if (!context) return;
const { client } = context;
if (typeof client.adminUsageExport !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin usage export API is not configured", { operation: "GET /v1/admin/billing/usage/export", target: { type: "service", id: "hwlab-user-billing" } });
}
const result = await client.adminUsageExport(adminAuditParams(url));
sendUserBillingCsvProxyResult({ request, response, result, operation: "GET /v1/admin/billing/usage/export", filename: "hwlab-admin-usage.csv" });
}
async function handleAdminBillingLedgerHttp(request, response, url, options) {
const context = await requireAdminBillingClient(request, response, options, "GET /v1/admin/billing/ledger");
if (!context) return;
const { auth, client } = context;
if (typeof client.adminLedger !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin ledger API is not configured", { operation: "GET /v1/admin/billing/ledger", target: { type: "service", id: "hwlab-user-billing" } });
}
const result = await client.adminLedger(adminAuditParams(url));
sendUserBillingProxyResult({ request, response, result, operation: "GET /v1/admin/billing/ledger", route: "/v1/admin/billing/ledger", actor: adminActorSummary(auth.actor) });
}
async function handleAdminBillingLedgerExportHttp(request, response, url, options) {
const context = await requireAdminBillingClient(request, response, options, "GET /v1/admin/billing/ledger/export");
if (!context) return;
const { client } = context;
if (typeof client.adminLedgerExport !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin ledger export API is not configured", { operation: "GET /v1/admin/billing/ledger/export", target: { type: "service", id: "hwlab-user-billing" } });
}
const result = await client.adminLedgerExport(adminAuditParams(url));
sendUserBillingCsvProxyResult({ request, response, result, operation: "GET /v1/admin/billing/ledger/export", filename: "hwlab-admin-ledger.csv" });
}
async function handleAdminBillingRedeemCodesHttp(request, response, url, options) {
const context = await requireAdminBillingClient(request, response, options, `${request.method} /v1/admin/billing/redeem-codes`);
if (!context) return;
const { auth, client } = context;
let result;
if (request.method === "GET") {
if (typeof client.adminRedeemCodes !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin redeem code API is not configured", { operation: "GET /v1/admin/billing/redeem-codes", target: { type: "service", id: "hwlab-user-billing" } });
}
result = await client.adminRedeemCodes(adminRedeemParams(url));
} else {
if (typeof client.createAdminRedeemCode !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin redeem code create API is not configured", { operation: "POST /v1/admin/billing/redeem-codes", target: { type: "service", id: "hwlab-user-billing" } });
}
const parsed = await readJsonObject(request, DEFAULT_BODY_LIMIT_BYTES);
if (!parsed.ok) return sendJson(response, 400, parsed.error);
result = await client.createAdminRedeemCode({
...parsed.value,
createdByUserId: String(auth.actor?.id ?? ""),
createdByUsername: String(auth.actor?.username ?? ""),
metadata: { ...(parsed.value?.metadata && typeof parsed.value.metadata === "object" && !Array.isArray(parsed.value.metadata) ? parsed.value.metadata : {}), operator: adminActorSummary(auth.actor) }
});
}
sendUserBillingProxyResult({ request, response, result, operation: `${request.method} /v1/admin/billing/redeem-codes`, route: "/v1/admin/billing/redeem-codes", actor: adminActorSummary(auth.actor) });
}
async function handleAdminBillingRedeemCodeHttp(request, response, codeId, options) {
const context = await requireAdminBillingClient(request, response, options, "PATCH /v1/admin/billing/redeem-codes/{codeId}");
if (!context) return;
const { auth, client } = context;
if (typeof client.updateAdminRedeemCode !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin redeem code update API is not configured", { operation: "PATCH /v1/admin/billing/redeem-codes/{codeId}", target: { type: "service", id: "hwlab-user-billing" } });
}
const parsed = await readJsonObject(request, DEFAULT_BODY_LIMIT_BYTES);
if (!parsed.ok) return sendJson(response, 400, parsed.error);
const result = await client.updateAdminRedeemCode(codeId, parsed.value);
sendUserBillingProxyResult({ request, response, result, operation: "PATCH /v1/admin/billing/redeem-codes/{codeId}", route: "/v1/admin/billing/redeem-codes/{codeId}", actor: adminActorSummary(auth.actor) });
}
async function handleAdminBillingRedeemRedemptionsHttp(request, response, url, options) {
const context = await requireAdminBillingClient(request, response, options, "GET /v1/admin/billing/redeem-redemptions");
if (!context) return;
const { auth, client } = context;
if (typeof client.adminRedeemRedemptions !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin redeem redemptions API is not configured", { operation: "GET /v1/admin/billing/redeem-redemptions", target: { type: "service", id: "hwlab-user-billing" } });
}
const result = await client.adminRedeemRedemptions(adminRedeemParams(url));
sendUserBillingProxyResult({ request, response, result, operation: "GET /v1/admin/billing/redeem-redemptions", route: "/v1/admin/billing/redeem-redemptions", actor: adminActorSummary(auth.actor) });
}
async function handleAdminBillingUserHttp(request, response, url, userId, options) {
const context = await requireAdminBillingClient(request, response, options, `${request.method} /v1/admin/billing/users/{userId}`);
if (!context) return;
const { auth, client } = context;
let result;
if (request.method === "GET") {
if (typeof client.adminUser !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin user detail API is not configured", { operation: "GET /v1/admin/billing/users/{userId}", target: { type: "service", id: "hwlab-user-billing" } });
}
result = await client.adminUser(userId);
} else {
if (typeof client.updateAdminUser !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin user update API is not configured", { operation: "PATCH /v1/admin/billing/users/{userId}", target: { type: "service", id: "hwlab-user-billing" } });
}
const parsed = await readJsonObject(request, DEFAULT_BODY_LIMIT_BYTES);
if (!parsed.ok) return sendJson(response, 400, parsed.error);
result = await client.updateAdminUser(userId, parsed.value);
}
sendUserBillingProxyResult({ request, response, result, operation: `${request.method} /v1/admin/billing/users/{userId}`, route: "/v1/admin/billing/users/{userId}", actor: adminActorSummary(auth.actor) });
}
async function handleAdminBillingCreditAdjustHttp(request, response, userId, options) {
const context = await requireAdminBillingClient(request, response, options, "POST /v1/admin/billing/users/{userId}/credits/adjust");
if (!context) return;
const { auth, client } = context;
if (typeof client.adjustAdminCredits !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin credit adjust API is not configured", { operation: "POST /v1/admin/billing/users/{userId}/credits/adjust", target: { type: "service", id: "hwlab-user-billing" } });
}
const parsed = await readJsonObject(request, DEFAULT_BODY_LIMIT_BYTES);
if (!parsed.ok) return sendJson(response, 400, parsed.error);
const result = await client.adjustAdminCredits({
...parsed.value,
userId,
metadata: { ...(parsed.value?.metadata && typeof parsed.value.metadata === "object" && !Array.isArray(parsed.value.metadata) ? parsed.value.metadata : {}), operator: adminActorSummary(auth.actor) }
});
sendUserBillingProxyResult({ request, response, result, operation: "POST /v1/admin/billing/users/{userId}/credits/adjust", route: "/v1/admin/billing/users/{userId}/credits/adjust", actor: adminActorSummary(auth.actor) });
}
async function handleAdminBillingUserStatusHttp(request, response, userId, options) {
const auth = await options.accessController.authenticate(request, { required: true });
if (!auth.ok) {
sendJson(response, auth.status, auth);
return;
}
if (auth.actor?.role !== "admin") {
sendRestError(request, response, 403, "admin_required", "Only admin users can update user status", {
operation: "PATCH /v1/admin/billing/users/{userId}/status",
target: { type: "route", id: "/v1/admin/billing/users/{userId}/status" },
result: "rejected"
});
return;
}
const client = options.userBillingClient ?? options.accessController?.userBilling ?? null;
if (!client?.configured || typeof client.updateAdminUserStatus !== "function") {
sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing admin user status API is not configured", {
operation: "PATCH /v1/admin/billing/users/{userId}/status",
target: { type: "service", id: "hwlab-user-billing" }
});
return;
}
const parsed = await readJsonObject(request, DEFAULT_BODY_LIMIT_BYTES);
if (!parsed.ok) {
sendJson(response, 400, parsed.error);
return;
}
const status = String(parsed.value?.status ?? "").trim().toLowerCase();
if (!["active", "disabled", "pending"].includes(status)) {
sendRestError(request, response, 400, "invalid_status", "status must be active, disabled or pending", {
operation: "PATCH /v1/admin/billing/users/{userId}/status",
target: { type: "user", id: userId },
result: "rejected"
});
return;
}
const result = await client.updateAdminUserStatus(userId, status);
if (!result.ok) {
sendRestError(request, response, result.status ?? 502, result.error?.code ?? "user_billing_admin_user_status_failed", result.error?.message ?? "user-billing admin user status request failed", {
operation: "PATCH /v1/admin/billing/users/{userId}/status",
target: { type: "service", id: "hwlab-user-billing" },
reason: result.error?.code,
result: "failed"
});
return;
}
sendJson(response, 200, {
...(result.body ?? {}),
actor: adminActorSummary(auth.actor),
proxy: {
serviceId: CLOUD_API_SERVICE_ID,
route: "/v1/admin/billing/users/{userId}/status",
source: "hwlab-user-billing",
valuesRedacted: true
},
valuesRedacted: true
});
}
async function maybeHandleUserBillingApiKeysHttp(request, response, url, options) {
const client = options.userBillingClient ?? options.accessController?.userBilling ?? null;
if (!client?.configured) return false;
const auth = await options.accessController.authenticate(request, { required: true });
if (!auth.ok || !String(auth.authMethod ?? "").startsWith("user-billing")) return false;
const token = userBillingTokenFromAuth(auth);
if (!token) return false;
if (url.pathname === "/v1/api-keys/default") {
sendRestError(request, response, 404, "user_billing_default_key_unsupported", "user-billing API keys do not support legacy default-key regeneration", {
operation: `${request.method} /v1/api-keys/default`,
target: { type: "route", id: "/v1/api-keys/default" },
result: "rejected"
});
return true;
}
let result = null;
const path = url.pathname;
if (request.method === "GET" && path === "/v1/api-keys" && typeof client.listApiKeys === "function") {
result = await client.listApiKeys(token);
} else if (request.method === "POST" && path === "/v1/api-keys" && typeof client.createApiKey === "function") {
const parsed = await readJsonObject(request, DEFAULT_BODY_LIMIT_BYTES);
if (!parsed.ok) {
sendJson(response, 400, parsed.error);
return true;
}
result = await client.createApiKey(token, parsed.value);
} else {
const match = path.match(/^\/v1\/api-keys\/([^/]+)$/u);
if (match && request.method === "PATCH" && typeof client.updateApiKey === "function") {
const parsed = await readJsonObject(request, DEFAULT_BODY_LIMIT_BYTES);
if (!parsed.ok) {
sendJson(response, 400, parsed.error);
return true;
}
result = await client.updateApiKey(token, decodeURIComponent(match[1]), parsed.value);
} else if (match && request.method === "DELETE" && typeof client.revokeApiKey === "function") {
result = await client.revokeApiKey(token, decodeURIComponent(match[1]));
}
}
if (!result) return false;
sendUserBillingProxyResult({ request, response, result, operation: `${request.method} /v1/api-keys`, route: path, actor: adminActorSummary(auth.actor) });
return true;
}
async function handleUserBillingProfileHttp(request, response, options) {
const client = options.userBillingClient ?? options.accessController?.userBilling ?? null;
const auth = await options.accessController.authenticate(request, { required: true });
if (!auth.ok) return sendJson(response, auth.status, auth);
const token = userBillingTokenFromAuth(auth);
if (!String(auth.authMethod ?? "").startsWith("user-billing")) {
return sendRestError(request, response, 403, "user_billing_auth_required", "profile update requires a user-billing bearer token", { operation: "PATCH /v1/users/me/profile", target: { type: "route", id: "/v1/users/me/profile" } });
}
if (!token || !client?.configured || typeof client.updateProfile !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing profile API is not configured", { operation: "PATCH /v1/users/me/profile", target: { type: "service", id: "hwlab-user-billing" } });
}
const parsed = await readJsonObject(request, DEFAULT_BODY_LIMIT_BYTES);
if (!parsed.ok) return sendJson(response, 400, parsed.error);
const result = await client.updateProfile(token, parsed.value);
sendUserBillingProxyResult({ request, response, result, operation: "PATCH /v1/users/me/profile", route: "/v1/users/me/profile", actor: adminActorSummary(auth.actor) });
}
async function handleUserBillingPasswordHttp(request, response, options) {
const client = options.userBillingClient ?? options.accessController?.userBilling ?? null;
const auth = await options.accessController.authenticate(request, { required: true });
if (!auth.ok) return sendJson(response, auth.status, auth);
const token = userBillingTokenFromAuth(auth);
if (auth.authMethod !== "user-billing-session") {
return sendRestError(request, response, 403, "user_billing_session_required", "password update requires a user-billing session token", { operation: "POST /v1/users/me/password", target: { type: "route", id: "/v1/users/me/password" } });
}
if (!token || !client?.configured || typeof client.changePassword !== "function") {
return sendRestError(request, response, 503, "user_billing_not_configured", "HWLAB user-billing password API is not configured", { operation: "POST /v1/users/me/password", target: { type: "service", id: "hwlab-user-billing" } });
}
const parsed = await readJsonObject(request, DEFAULT_BODY_LIMIT_BYTES);
if (!parsed.ok) return sendJson(response, 400, parsed.error);
const result = await client.changePassword(token, parsed.value);
sendUserBillingProxyResult({ request, response, result, operation: "POST /v1/users/me/password", route: "/v1/users/me/password", actor: adminActorSummary(auth.actor) });
}
function sendUserBillingProxyResult({ request, response, result, operation, route, actor = null }) {
if (!result?.ok) {
sendRestError(request, response, result?.status ?? 502, result?.error?.code ?? "user_billing_request_failed", result?.error?.message ?? "user-billing request failed", {
operation,
target: { type: "service", id: "hwlab-user-billing" },
reason: result?.error?.code,
result: "failed"
});
return;
}
sendJson(response, result.status ?? 200, {
...(result.body ?? {}),
actor,
proxy: {
serviceId: CLOUD_API_SERVICE_ID,
route,
source: "hwlab-user-billing",
valuesRedacted: true
},
valuesRedacted: true
});
}
function sendUserBillingCsvProxyResult({ request, response, result, operation, filename }) {
if (!result?.ok) {
sendRestError(request, response, result?.status ?? 502, result?.error?.code ?? "user_billing_request_failed", result?.error?.message ?? "user-billing export request failed", {
operation,
target: { type: "service", id: "hwlab-user-billing" },
reason: result?.error?.code,
result: "failed"
});
return;
}
response.writeHead(result.status ?? 200, {
"content-type": "text/csv; charset=utf-8",
"cache-control": "no-store",
"content-disposition": `attachment; filename="${filename}"`
});
response.end(String(result.body ?? ""));
}
function adminAuditParams(url) {
const params = {};
for (const key of ["page", "pageSize", "limit", "userId", "search", "serviceId", "resourceType", "apiKeyId", "status", "kind", "source", "idempotencyKey", "from", "to"]) {
const value = String(url.searchParams.get(key) ?? "").trim();
if (value) params[key] = value;
}
return params;
}
function adminRedeemParams(url) {
const params = {};
for (const key of ["limit", "status", "userId", "codeId"]) {
const value = String(url.searchParams.get(key) ?? "").trim();
if (value) params[key] = value;
}
return params;
}
function adminActorSummary(actor) {
return actor ? {
id: String(actor.id ?? ""),
username: String(actor.username ?? ""),
displayName: String(actor.displayName ?? ""),
role: String(actor.role ?? ""),
status: String(actor.status ?? ""),
valuesRedacted: true
} : null;
}
function bearerTokenFromRequest(request) {
const header = String(getHeader(request, "authorization") ?? "").trim();
return header.toLowerCase().startsWith("bearer ") ? header.slice(7).trim() : "";
}
function userBillingTokenFromRequest(request) {
const bearer = bearerTokenFromRequest(request);
if (bearer) return bearer;
const cookieToken = cookieValueFromRequest(request, HWLAB_WEB_SESSION_COOKIE);
return cookieToken.startsWith("hws_") ? cookieToken : "";
}
function userBillingTokenFromAuth(auth) {
const token = String(auth?.userBilling?.token ?? "").trim();
return token ? token : "";
}
function cookieValueFromRequest(request, name) {
const target = String(name ?? "");
if (!target) return "";
for (const part of String(getHeader(request, "cookie") ?? "").split(";")) {
const trimmed = part.trim();
const index = trimmed.indexOf("=");
if (index <= 0) continue;
if (trimmed.slice(0, index) !== target) continue;
try {
return decodeURIComponent(trimmed.slice(index + 1));
} catch {
return trimmed.slice(index + 1);
}
}
return "";
}
async function readJsonObject(request, limitBytes) {
const body = await readBody(request, limitBytes);
try {
const value = body ? JSON.parse(body) : {};
if (!value || typeof value !== "object" || Array.isArray(value)) {
return { ok: false, error: { accepted: false, error: { code: "invalid_params", message: "body must be a JSON object" } } };
}
return { ok: true, value };
} catch (error) {
return { ok: false, error: { accepted: false, error: { code: "parse_error", message: "Invalid JSON body", reason: error.message } } };
}
}
async function handleGatewayPollHttp(request, response, options) {
const body = await readBody(request, options.bodyLimitBytes);
let params = {};
try {
params = body ? JSON.parse(body) : {};
} catch (error) {
sendJson(response, 400, {
accepted: false,
error: {
code: "parse_error",
message: "Invalid JSON body",
reason: error.message
}
});
return;
}
if (!params || typeof params !== "object" || Array.isArray(params)) {
sendJson(response, 400, {
accepted: false,
error: {
code: "invalid_params",
message: "gateway poll body must be a JSON object"
}
});
return;
}
const session = options.gatewayRegistry.updateSession(params);
await persistGatewayDemoSession({
runtimeStore: options.runtimeStore,
session,
request,
env: options.env
});
const outbound = options.gatewayRegistry.nextRequest(session.gatewaySessionId);
sendJson(response, 200, {
accepted: true,
serviceId: CLOUD_API_SERVICE_ID,
mode: "gateway-outbound-poll-demo",
gatewayId: session.gatewayId,
gatewaySessionId: session.gatewaySessionId,
queueDepth: session.queue.length,
request: outbound,
type: outbound ? "request" : "noop",
observedAt: new Date().toISOString()
});
}
async function handleGatewayResultHttp(request, response, options) {
const body = await readBody(request, options.bodyLimitBytes);
let params = {};
try {
params = body ? JSON.parse(body) : {};
} catch (error) {
sendJson(response, 400, {
accepted: false,
error: {
code: "parse_error",
message: "Invalid JSON body",
reason: error.message
}
});
return;
}
const result = options.gatewayRegistry.complete(params);
sendJson(response, result.accepted ? 200 : 404, {
...result,
serviceId: CLOUD_API_SERVICE_ID,
mode: "gateway-outbound-poll-demo",
observedAt: new Date().toISOString()
});
}
async function persistGatewayDemoSession({ runtimeStore, session, request, env = process.env }) {
if (!runtimeStore) return;
const refreshMs = parsePositiveInteger(env.HWLAB_GATEWAY_REGISTRATION_REFRESH_MS, 60000);
if (session.runtimeRegisteredEpochMs && Date.now() - session.runtimeRegisteredEpochMs < refreshMs) {
return;
}
const meta = {
traceId: getHeader(request, "x-trace-id") || `trc_gateway_poll_${randomUUID()}`,
actorId: `svc_${session.serviceId}`,
serviceId: CLOUD_API_SERVICE_ID,
environment: runtimeEnvironment(env)
};
try {
await runtimeStore.registerGatewaySession?.({
projectId: session.projectId,
gatewaySessionId: session.gatewaySessionId,
serviceId: "hwlab-gateway",
gatewayId: session.gatewayId,
endpoint: session.endpoint,
status: "connected",
labels: {
demoOutboundPoll: "true",
os: String(session.system?.platform ?? "unknown")
}
}, meta);
await runtimeStore.registerBoxResource?.({
projectId: session.projectId,
gatewaySessionId: session.gatewaySessionId,
resourceId: session.resourceId,
boxId: session.boxId,
resourceType: "simulator_endpoint",
state: "available",
metadata: {
serviceId: "hwlab-gateway",
demoShellHost: true
}
}, meta);
if (session.capabilities.length > 0) {
await runtimeStore.reportBoxCapabilities?.({
capabilities: session.capabilities.map((capability) => ({
...capability,
resourceId: capability.resourceId ?? session.resourceId,
projectId: capability.projectId ?? session.projectId
}))
}, meta);
}
session.runtimeRegisteredAt = new Date().toISOString();
session.runtimeRegisteredEpochMs = Date.now();
} catch {
// Demo polling must keep the gateway online even when durable runtime writes are not ready.
}
}
function sendRestError(request, response, statusCode, code, message, context = {}) {
const requestId = getHeader(request, "x-request-id") || "req_unassigned";
const environment = context.environment || runtimeEnvironment(context.env ?? process.env);
sendJson(response, statusCode, {
error: {
code,
message,
reason: context.reason,
audit: createAuditRecord({
requestId,
actor: {
type: "user",
id: getHeader(request, "x-actor-id") || `system_${CLOUD_API_SERVICE_ID}`
},
source: {
serviceId: CLOUD_API_SERVICE_ID,
environment,
traceId: getHeader(request, "x-trace-id"),
adapter: "rest"
},
operation: context.operation || `${request.method || "GET"} ${request.url || "/"}`,
target: context.target || {
type: "route",
id: request.url || "/"
},
result: context.result || "failed"
})
}
});
}
function statusForRpcResponse(rpcResponse) {
if (!rpcResponse.error) {
return 200;
}
if (rpcResponse.error.code === ERROR_CODES.invalidRequest || rpcResponse.error.code === ERROR_CODES.parseError) {
return 400;
}
if (rpcResponse.error.code === ERROR_CODES.methodNotFound) {
return 404;
}
return 200;
}
function readBody(request, limitBytes = DEFAULT_BODY_LIMIT_BYTES) {
const limit = Number.isInteger(limitBytes) && limitBytes > 0 ? limitBytes : DEFAULT_BODY_LIMIT_BYTES;
return new Promise((resolve, reject) => {
let body = "";
request.setEncoding("utf8");
request.on("data", (chunk) => {
body += chunk;
if (Buffer.byteLength(body, "utf8") > limit) {
request.destroy(new Error(`request body exceeds ${limit} bytes`));
}
});
request.on("end", () => resolve(body));
request.on("error", reject);
});
}
function sendJson(response, statusCode, body) {
response.writeHead(statusCode, {
"content-type": "application/json; charset=utf-8",
"cache-control": "no-store"
});
response.end(`${JSON.stringify(body)}\n`);
}
function getHeader(request, name) {
const value = request.headers[name.toLowerCase()];
if (Array.isArray(value)) {
return value[0];
}
return value;
}
function firstHeaderValue(request, name) {
return getHeader(request, name);
}
function truthyFlag(value) {
return /^(?:1|true|yes|on|enabled)$/iu.test(String(value ?? "").trim());
}
function safeTraceId(value) {
const text = String(value ?? "").trim();
return /^trc_[A-Za-z0-9_.:-]+$/u.test(text) ? text : null;
}
function safeSessionId(value) {
const text = String(value ?? "").trim();
return /^ses_[A-Za-z0-9_.:-]+$/u.test(text) ? text : null;
}
function safeOpaqueId(value) {
const text = String(value ?? "").trim();
return /^[A-Za-z0-9_.:-]{3,180}$/u.test(text) ? text : null;
}
function parsePositiveInteger(value, fallback) {
const parsed = Number.parseInt(value ?? "", 10);
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
}
function positiveInteger(value, fallback) {
const parsed = Number.parseInt(value ?? "", 10);
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
}
async function runtimeReadiness(runtimeStore) {
if (typeof runtimeStore?.readiness === "function") {
return runtimeStore.readiness();
}
return runtimeStore.summary();
}