返回 DeepSeek-Reasonix
contract.ts
根目录 / desktop / electron / src / main / contract.ts
1 import { readFileSync } from "node:fs";
2 import type { ContractInfo } from "../shared/ipc.js";
3
4 export interface LoadedContract extends ContractInfo {
5 readonly commandSet: ReadonlySet<string>;
6 }
7
8 function commandNames(value: unknown): string[] {
9 if (Array.isArray(value)) {
10 return value.flatMap((entry) => {
11 if (typeof entry === "string") return [entry];
12 if (entry && typeof entry === "object" && typeof (entry as { name?: unknown }).name === "string") {
13 return [(entry as { name: string }).name];
14 }
15 return [];
16 });
17 }
18 if (value && typeof value === "object") return Object.keys(value as Record<string, unknown>);
19 return [];
20 }
21
22 export function parseContract(json: unknown): LoadedContract {
23 if (!json || typeof json !== "object") throw new Error("contract must be a JSON object");
24 const record = json as Record<string, unknown>;
25 const digest = typeof record.digest === "string" ? record.digest : "";
26 if (digest === "") throw new Error("contract has no digest");
27 const commands = commandNames(record.commands).filter((name) => name !== "");
28 if (commands.length === 0) throw new Error("contract lists no commands");
29 const protocolVersion = typeof record.protocolVersion === "number" ? record.protocolVersion : 1;
30 return { protocolVersion, digest, commands: Object.freeze([...commands]), commandSet: new Set(commands) };
31 }
32
33 export function emptyContract(): LoadedContract {
34 return { protocolVersion: 1, digest: "", commands: Object.freeze([]), commandSet: new Set() };
35 }
36
37 export function loadContract(path: string): LoadedContract {
38 return parseContract(JSON.parse(readFileSync(path, "utf8")) as unknown);
39 }
40
41 export function isAllowedCommand(contract: LoadedContract, method: unknown): method is string {
42 return typeof method === "string" && method !== "" && contract.commandSet.has(method);
43 }
44
44 lines TYPESCRIPT