Files

62 lines
2.7 KiB
TypeScript

/*
* SPEC: PJ2026-010103 HWPOD 服务。
* 实现引用: draft-2026-07-20-hwpod-temporal-split。
* 责任: 独立 HWPOD API、worker 和 Web 共用的稳定输入输出合同。
*/
export type HwpodOperationInput = {
operationId: string;
plan: Record<string, unknown>;
runtimeApiUrl: string;
authorization?: string;
};
export type HwpodOperationResult = {
ok: boolean;
status: string;
operationId: string;
workflowId: string;
workflowRunId: string | null;
result?: Record<string, unknown> | null;
error?: { code: string; message: string } | null;
};
export const HWPOD_WEB_OPERATION_INTENTS = new Set([
"workspace.ls",
"workspace.cat",
"debug.build",
"debug.download",
"debug.reset",
"io.uart.open",
"io.uart.close",
"io.uart.read",
"io.uart.write",
]);
export function validateHwpodOperationInput(value: unknown): HwpodOperationInput {
if (!value || typeof value !== "object" || Array.isArray(value)) throw codedError("hwpod_operation_input_invalid", "HWPOD operation input must be an object");
const input = value as Record<string, unknown>;
const operationId = text(input.operationId);
const runtimeApiUrl = text(input.runtimeApiUrl);
const plan = input.plan;
if (!operationId) throw codedError("hwpod_operation_id_required", "operationId is required");
if (!runtimeApiUrl) throw codedError("hwpod_runtime_api_url_required", "runtimeApiUrl is required");
if (!plan || typeof plan !== "object" || Array.isArray(plan)) throw codedError("hwpod_operation_plan_required", "plan must be an object");
return { operationId, runtimeApiUrl: runtimeApiUrl.replace(/\/+$/u, ""), plan: plan as Record<string, unknown>, authorization: text(input.authorization) || undefined };
}
export function validateHwpodWebOperationRequest(value: unknown) {
if (!value || typeof value !== "object" || Array.isArray(value)) throw codedError("hwpod_operation_request_invalid", "HWPOD operation request must be an object");
const input = value as Record<string, unknown>;
const hwpodId = text(input.hwpodId);
const intent = text(input.intent);
if (!hwpodId) throw codedError("hwpod_id_required", "hwpodId is required");
if (!HWPOD_WEB_OPERATION_INTENTS.has(intent)) throw codedError("hwpod_operation_intent_unsupported", `unsupported HWPOD Web operation intent: ${intent}`);
const args = input.args === undefined ? {} : input.args;
if (!args || typeof args !== "object" || Array.isArray(args)) throw codedError("hwpod_operation_args_invalid", "HWPOD operation args must be an object");
return { hwpodId, intent, args: args as Record<string, unknown> };
}
function text(value: unknown) { return typeof value === "string" ? value.trim() : ""; }
function codedError(code: string, message: string) { return Object.assign(new Error(message), { code }); }