mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-04 10:23:41 +00:00
72 lines
3.0 KiB
TypeScript
72 lines
3.0 KiB
TypeScript
// Node list parsing helpers normalize node inventory records from CLI output.
|
|
import { asRecord } from "@openclaw/normalization-core/record-coerce";
|
|
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
|
import type { NodeListNode, PairedNode, PairingList, PendingRequest } from "./node-list-types.js";
|
|
|
|
// pending/paired rows are blind-cast from a permissive pairing file, so any scalar can be
|
|
// non-string. CLI renderers call `.trim()`/`sanitizeTerminalText` on them (these rows bypass
|
|
// the gateway node catalog), so normalize at this shared parse boundary to keep every
|
|
// consumer crash-safe.
|
|
// A pending/paired row needs an addressable string id to be approved, keyed, or rendered. A
|
|
// non-string required id drops the row entirely rather than becoming an empty-string sentinel that
|
|
// downstream consumers would treat as a real id.
|
|
function normalizePendingRequest(row: PendingRequest): PendingRequest | null {
|
|
const requestId = normalizeOptionalString(row.requestId);
|
|
const nodeId = normalizeOptionalString(row.nodeId);
|
|
if (requestId === undefined || nodeId === undefined) {
|
|
return null;
|
|
}
|
|
return {
|
|
...row,
|
|
requestId,
|
|
nodeId,
|
|
displayName: normalizeOptionalString(row.displayName),
|
|
platform: normalizeOptionalString(row.platform),
|
|
version: normalizeOptionalString(row.version),
|
|
coreVersion: normalizeOptionalString(row.coreVersion),
|
|
uiVersion: normalizeOptionalString(row.uiVersion),
|
|
remoteIp: normalizeOptionalString(row.remoteIp),
|
|
};
|
|
}
|
|
|
|
function normalizePairedNode(row: PairedNode): PairedNode | null {
|
|
const nodeId = normalizeOptionalString(row.nodeId);
|
|
if (nodeId === undefined) {
|
|
return null;
|
|
}
|
|
return {
|
|
...row,
|
|
nodeId,
|
|
token: normalizeOptionalString(row.token),
|
|
displayName: normalizeOptionalString(row.displayName),
|
|
platform: normalizeOptionalString(row.platform),
|
|
version: normalizeOptionalString(row.version),
|
|
coreVersion: normalizeOptionalString(row.coreVersion),
|
|
uiVersion: normalizeOptionalString(row.uiVersion),
|
|
remoteIp: normalizeOptionalString(row.remoteIp),
|
|
lastSeenReason: normalizeOptionalString(row.lastSeenReason),
|
|
};
|
|
}
|
|
|
|
/** Extracts pending and paired node arrays from permissive node.pair.list payloads. */
|
|
export function parsePairingList(value: unknown): PairingList {
|
|
const obj = asRecord(value);
|
|
const pending = Array.isArray(obj.pending)
|
|
? (obj.pending as PendingRequest[])
|
|
.map(normalizePendingRequest)
|
|
.filter((row): row is PendingRequest => row !== null)
|
|
: [];
|
|
const paired = Array.isArray(obj.paired)
|
|
? (obj.paired as PairedNode[])
|
|
.map(normalizePairedNode)
|
|
.filter((row): row is PairedNode => row !== null)
|
|
: [];
|
|
return { pending, paired };
|
|
}
|
|
|
|
/** Extracts the nodes array from a node.list response, treating malformed payloads as empty. */
|
|
export function parseNodeList(value: unknown): NodeListNode[] {
|
|
const obj = asRecord(value);
|
|
return Array.isArray(obj.nodes) ? (obj.nodes as NodeListNode[]) : [];
|
|
}
|