openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
258 lines (257 loc) • 9.66 kB
JavaScript
import { r as resolveMissingRequestedScope } from "./operator-scope-compat-Ci6GBcmU.mjs";
import { t as resolveNodePairApprovalScopes } from "./node-pairing-authz-_-5BGyuw.mjs";
import { D as readDevicePairingStoreStateFromDatabase, I as requestDevicePairingMutationAdmission, T as persistDevicePairingStoreState, c as resolveNodePairingGeneration, k as updatePairedDeviceInTransaction, l as resolveNodePairingState, t as clearNodePairingGenerationState } from "./device-pairing-identity-D10qDl39.mjs";
import { c as toPublicPendingRequest, i as samePendingApprovalSurface, o as toPairedNode, r as refreshPendingNodeSurface, s as toPendingSnapshot, t as buildPendingNodeSurface } from "./device-pairing-node.records-sfc8y2hm.mjs";
import { t as devicePairingMutation } from "./device-pairing-dispatch.worker-DWeohPRb.mjs";
//#region src/infra/device-pairing-node.worker.ts
function mutatePairedDevices(database, operate) {
const state = readDevicePairingStoreStateFromDatabase(database.db);
const result = operate(state.pairedByDeviceId);
if (result.persist) persistDevicePairingStoreState(state, void 0, "paired");
return result.value;
}
function updateNodeSurface(input, update, matches = () => true) {
const { nodeId, expectedPairingGeneration } = input;
return updatePairedDeviceInTransaction(nodeId, (device) => {
const surface = device?.nodeSurface;
if (!device || !surface || expectedPairingGeneration.nodeId !== device.deviceId || resolveNodePairingGeneration(device)?.key !== expectedPairingGeneration.key || !matches(surface)) return { value: false };
requestDevicePairingMutationAdmission({
kind: "node-surface",
nodeId: device.deviceId,
pairingGeneration: expectedPairingGeneration.key
});
return {
value: true,
patch: { nodeSurface: update(surface) }
};
});
}
const nodePairingOperations = {
"node.request": devicePairingMutation((input, { database }) => {
const { req, nowMs } = input;
const nodeId = req.nodeId.trim();
if (!nodeId) throw new Error("nodeId required");
return mutatePairedDevices(database, (paired) => {
const device = paired[nodeId];
if (!device) throw new Error("node pairing requires a paired device");
requestDevicePairingMutationAdmission({
kind: "node-surface",
nodeId
});
const request = {
...req,
nodeId,
silent: req.silent && !device.nodeSurface
};
const existing = device.pendingNodeSurface;
const created = !existing || !samePendingApprovalSurface(existing, request);
const pending = created ? buildPendingNodeSurface({
req: request,
nowMs
}) : refreshPendingNodeSurface(existing, request, nowMs);
device.pendingNodeSurface = pending;
return {
value: {
status: "pending",
request: toPublicPendingRequest(device, pending),
created,
...created && existing ? { superseded: [{
requestId: existing.requestId,
nodeId
}] } : {}
},
persist: true
};
});
}),
"node.finalizeCleanup": devicePairingMutation((input, { database }) => {
const { observed } = input;
return mutatePairedDevices(database, (paired) => {
const device = paired[observed.nodeId.trim()];
const pending = device?.pendingNodeSurface;
if (!device || !pending || observed.requestId !== pending.requestId || observed.revision !== pending.revision) return {
value: [],
persist: false
};
requestDevicePairingMutationAdmission({
kind: "node-pending",
...toPendingSnapshot(device, pending)
});
delete device.pendingNodeSurface;
return {
value: [{
requestId: pending.requestId,
nodeId: device.deviceId
}],
persist: true
};
});
}),
"node.approve": devicePairingMutation((input, { database, recordNodeApproval }) => {
const { requestId, callerScopes, nowMs } = input;
return mutatePairedDevices(database, (paired) => {
const device = Object.values(paired).find((entry) => entry.pendingNodeSurface?.requestId === requestId);
const pending = device?.pendingNodeSurface;
if (!device || !pending || input.initialOnly && device.nodeSurface) return {
value: null,
persist: false
};
requestDevicePairingMutationAdmission({
kind: "node-pending",
...toPendingSnapshot(device, pending)
});
const missingScope = resolveMissingRequestedScope({
role: "operator",
requestedScopes: resolveNodePairApprovalScopes(pending.commands ?? []),
allowedScopes: callerScopes ?? []
});
if (missingScope) return {
value: {
status: "forbidden",
missingScope
},
persist: false
};
const previousPairingGeneration = resolveNodePairingGeneration(device);
const now = Math.max(nowMs, (device.nodeSurface?.approvedAtMs ?? -1) + 1);
device.nodeSurface = {
displayName: device.nodeSurface?.displayName ?? pending.displayName,
version: pending.version,
coreVersion: pending.coreVersion,
uiVersion: pending.uiVersion,
modelIdentifier: pending.modelIdentifier,
caps: pending.caps,
commands: pending.commands,
permissions: pending.permissions,
bins: device.nodeSurface?.bins,
createdAtMs: device.nodeSurface?.createdAtMs ?? now,
approvedAtMs: now,
lastConnectedAtMs: device.nodeSurface?.lastConnectedAtMs,
lastHostStats: device.nodeSurface?.lastHostStats
};
delete device.pendingNodeSurface;
const nextPairingState = resolveNodePairingState(device);
const nextPairingGeneration = nextPairingState?.generation?.key;
if (!nextPairingState || !nextPairingGeneration) return {
value: null,
persist: false
};
clearNodePairingGenerationState(device, previousPairingGeneration);
const node = toPairedNode(device);
if (node) recordNodeApproval({
nodeId: node.nodeId,
pairingIdentity: nextPairingState.identity.key,
previousPairingGeneration: previousPairingGeneration?.key,
nextPairingGeneration,
surface: {
caps: node.caps ?? [],
commands: node.commands ?? [],
permissions: node.permissions
}
});
return node ? {
value: {
requestId,
node,
pairingIdentity: nextPairingState.identity.key,
nextPairingGeneration,
...previousPairingGeneration ? { previousPairingGeneration: previousPairingGeneration.key } : {}
},
persist: true
} : {
value: null,
persist: false
};
});
}),
"node.reject": devicePairingMutation((input, { database }) => {
const { requestId } = input;
return mutatePairedDevices(database, (paired) => {
const device = Object.values(paired).find((entry) => entry.pendingNodeSurface?.requestId === requestId);
const pending = device?.pendingNodeSurface;
if (!device || !pending) return {
value: null,
persist: false
};
requestDevicePairingMutationAdmission({
kind: "node-pending",
...toPendingSnapshot(device, pending)
});
delete device.pendingNodeSurface;
return {
value: {
requestId,
nodeId: device.deviceId
},
persist: true
};
});
}),
"node.rename": devicePairingMutation((input, { database }) => {
const displayName = input.displayName.trim();
if (!displayName) throw new Error("displayName required");
return mutatePairedDevices(database, (paired) => {
const device = paired[input.nodeId.trim()];
if (!device?.nodeSurface) return {
value: null,
persist: false
};
requestDevicePairingMutationAdmission({
kind: "node-surface",
nodeId: device.deviceId,
pairingGeneration: resolveNodePairingGeneration(device)?.key
});
device.nodeSurface = {
...device.nodeSurface,
displayName
};
return {
value: toPairedNode(device),
persist: true
};
});
}),
"node.recordConnection": devicePairingMutation((input) => {
const { nodeId, connectedAtMs, expectedPairingGeneration } = input;
return updatePairedDeviceInTransaction(nodeId, (device) => {
if (!device?.nodeSurface || expectedPairingGeneration && (expectedPairingGeneration.nodeId !== device.deviceId || resolveNodePairingGeneration(device)?.key !== expectedPairingGeneration.key)) return { value: { recorded: false } };
requestDevicePairingMutationAdmission({
kind: "node-surface",
nodeId: device.deviceId,
pairingGeneration: resolveNodePairingGeneration(device)?.key
});
const firstConnection = device.nodeSurface.lastConnectedAtMs === void 0;
const lastConnectedAtMs = Math.max(device.nodeSurface.lastConnectedAtMs ?? connectedAtMs, connectedAtMs);
const clearsDisconnect = device.nodeSurface.lastDisconnectedAtMs !== void 0 && connectedAtMs > device.nodeSurface.lastDisconnectedAtMs;
return {
value: {
recorded: true,
firstConnection
},
patch: { nodeSurface: {
...device.nodeSurface,
lastConnectedAtMs,
...clearsDisconnect ? { lastDisconnectedAtMs: void 0 } : {}
} }
};
});
}),
"node.recordDisconnection": devicePairingMutation((input) => updateNodeSurface(input, (surface) => ({
...surface,
lastDisconnectedAtMs: Math.max(surface.lastDisconnectedAtMs ?? input.disconnectedAtMs, input.disconnectedAtMs)
}), (surface) => surface.lastConnectedAtMs === input.connectedAtMs && !(input.disconnectedAtMs < input.connectedAtMs))),
"node.recordHostStats": devicePairingMutation((input) => updateNodeSurface(input, (surface) => ({
...surface,
lastHostStats: input.hostStats
}))),
"node.updateBins": devicePairingMutation((input) => updateNodeSurface(input, (surface) => ({
...surface,
bins: input.bins
}))),
"node.updateSessionHost": devicePairingMutation((input) => updateNodeSurface(input, (surface) => ({
...surface,
sessionHost: input.sessionHost
})))
};
//#endregion
export { nodePairingOperations };