Files
openclaw/src/plugins/cli-gateway-nodes-runtime.ts
Peter Steinberger 49cc59b1e8 refactor: consolidate markdown code fences, error coercion, and byte-identical helper pairs (#99932)
* refactor(shared): add markdown code span/fence helpers and migrate seven call sites

* refactor(normalization-core): add canonical toErrorObject and migrate six copies

* refactor: consolidate byte-identical helper pairs onto owner modules

* refactor: reuse canonical path and token helpers in session tools and credentials

* refactor(packages): dedupe compaction summarization tail and session dir parsing

* fix(security): keep missing extensions dir silent in shared plugin dir lister

* refactor: reuse media-core chunk reader and shared dreaming session key helper

* fix(plugins): register error-coercion subpath in sdk alias table

* chore(plugin-sdk): re-pin callable export count after rebase

* chore(plugin-sdk): re-pin callable export count after rebase
2026-07-04 08:40:41 -04:00

78 lines
2.9 KiB
TypeScript

/** Provides plugin CLI node APIs by forwarding calls to the Gateway. */
import { randomUUID } from "node:crypto";
import { addTimerTimeoutGraceMs } from "@openclaw/normalization-core/number-coercion";
import {
GATEWAY_CLIENT_MODES,
GATEWAY_CLIENT_NAMES,
} from "../../packages/gateway-protocol/src/client-info.js";
import { callGateway } from "../gateway/call.js";
import { normalizeOperatorScopeList } from "../gateway/operator-scopes.js";
import { getPluginRuntimeGatewayRequestScope } from "./runtime/gateway-request-scope.js";
import type { PluginRuntime } from "./runtime/types.js";
/** Adds Gateway timer grace for plugin CLI node invoke calls. */
export function resolvePluginCliNodeInvokeGatewayTimeoutMs(
timeoutMs: number | undefined,
): number | undefined {
return typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0
? addTimerTimeoutGraceMs(timeoutMs)
: undefined;
}
function canPluginCliRuntimeRequestScopes(): boolean {
const scope = getPluginRuntimeGatewayRequestScope();
return Boolean(
scope?.pluginId &&
(scope.pluginOrigin === "bundled" || scope.pluginTrustedOfficialInstall === true),
);
}
function resolvePluginCliRuntimeNodeInvokeScopes(scopes: string[] | undefined) {
const normalizedScopes = normalizeOperatorScopeList(scopes);
return normalizedScopes && canPluginCliRuntimeRequestScopes() ? normalizedScopes : undefined;
}
/** Creates the `runtime.nodes` implementation exposed to CLI plugin code. */
export function createPluginCliGatewayNodesRuntime(): PluginRuntime["nodes"] {
return {
async list(params) {
const payload = await callGateway({
method: "node.list",
params: {},
clientName: GATEWAY_CLIENT_NAMES.CLI,
mode: GATEWAY_CLIENT_MODES.CLI,
});
const nodes = Array.isArray(payload?.nodes) ? payload.nodes : [];
const filteredNodes =
params?.connected === true
? nodes.filter(
(node) =>
node !== null &&
typeof node === "object" &&
(node as { connected?: unknown }).connected === true,
)
: nodes;
return {
nodes: filteredNodes as Awaited<ReturnType<PluginRuntime["nodes"]["list"]>>["nodes"],
};
},
async invoke(params) {
const scopes = resolvePluginCliRuntimeNodeInvokeScopes(params.scopes);
return await callGateway({
method: "node.invoke",
params: {
nodeId: params.nodeId,
command: params.command,
...(params.params !== undefined && { params: params.params }),
timeoutMs: params.timeoutMs,
idempotencyKey: params.idempotencyKey || randomUUID(),
},
timeoutMs: resolvePluginCliNodeInvokeGatewayTimeoutMs(params.timeoutMs),
clientName: GATEWAY_CLIENT_NAMES.CLI,
mode: GATEWAY_CLIENT_MODES.CLI,
...(scopes ? { scopes } : {}),
});
},
};
}