openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
931 lines (930 loc) • 16.9 kB
JavaScript
//#region src/gateway/methods/descriptor.ts
/** Scope marker for methods that only authenticated node clients may call. */
const NODE_GATEWAY_METHOD_SCOPE = "node";
/** Scope marker for methods whose handler derives the required operator scope at runtime. */
const DYNAMIC_GATEWAY_METHOD_SCOPE = "dynamic";
//#endregion
//#region src/gateway/methods/core-descriptors.ts
const CORE_GATEWAY_METHOD_SPECS = [
{
name: "health",
scope: "operator.read"
},
{
name: "diagnostics.stability",
scope: "operator.read"
},
{
name: "doctor.memory.status",
scope: "operator.read"
},
{
name: "doctor.memory.dreamDiary",
scope: "operator.read"
},
{
name: "doctor.memory.backfillDreamDiary",
scope: "operator.write"
},
{
name: "doctor.memory.resetDreamDiary",
scope: "operator.write"
},
{
name: "doctor.memory.resetGroundedShortTerm",
scope: "operator.write"
},
{
name: "doctor.memory.repairDreamingArtifacts",
scope: "operator.write"
},
{
name: "doctor.memory.dedupeDreamDiary",
scope: "operator.write"
},
{
name: "doctor.memory.remHarness",
scope: "operator.read"
},
{
name: "logs.tail",
scope: "operator.read"
},
{
name: "channels.status",
scope: "operator.read"
},
{
name: "channels.start",
scope: "operator.admin"
},
{
name: "channels.stop",
scope: "operator.admin"
},
{
name: "channels.logout",
scope: "operator.admin"
},
{
name: "status",
scope: "operator.read"
},
{
name: "usage.status",
scope: "operator.read"
},
{
name: "usage.cost",
scope: "operator.read"
},
{
name: "tts.status",
scope: "operator.read"
},
{
name: "tts.providers",
scope: "operator.read"
},
{
name: "tts.personas",
scope: "operator.read"
},
{
name: "tts.enable",
scope: "operator.write"
},
{
name: "tts.disable",
scope: "operator.write"
},
{
name: "tts.convert",
scope: "operator.write"
},
{
name: "tts.setProvider",
scope: "operator.write"
},
{
name: "tts.setPersona",
scope: "operator.write"
},
{
name: "config.get",
scope: "operator.read"
},
{
name: "config.set",
scope: "operator.admin"
},
{
name: "config.apply",
scope: "operator.admin",
controlPlaneWrite: true
},
{
name: "config.patch",
scope: "operator.admin",
controlPlaneWrite: true
},
{
name: "config.schema",
scope: "operator.admin"
},
{
name: "config.schema.lookup",
scope: "operator.read"
},
{
name: "exec.approvals.get",
scope: "operator.admin"
},
{
name: "exec.approvals.set",
scope: "operator.admin"
},
{
name: "exec.approvals.node.get",
scope: "operator.admin"
},
{
name: "exec.approvals.node.set",
scope: "operator.admin"
},
{
name: "exec.approval.get",
scope: "operator.approvals"
},
{
name: "exec.approval.list",
scope: "operator.approvals"
},
{
name: "exec.approval.request",
scope: "operator.approvals"
},
{
name: "exec.approval.waitDecision",
scope: "operator.approvals"
},
{
name: "exec.approval.resolve",
scope: "operator.approvals"
},
{
name: "plugin.approval.list",
scope: "operator.approvals"
},
{
name: "plugin.approval.request",
scope: "operator.approvals"
},
{
name: "plugin.approval.waitDecision",
scope: "operator.approvals"
},
{
name: "plugin.approval.resolve",
scope: "operator.approvals"
},
{
name: "plugins.uiDescriptors",
scope: "operator.read"
},
{
name: "plugins.sessionAction",
scope: "dynamic"
},
{
name: "wizard.start",
scope: "operator.admin"
},
{
name: "wizard.next",
scope: "operator.admin"
},
{
name: "wizard.cancel",
scope: "operator.admin"
},
{
name: "wizard.status",
scope: "operator.admin"
},
{
name: "talk.catalog",
scope: "operator.read"
},
{
name: "talk.config",
scope: "operator.read"
},
{
name: "talk.client.create",
scope: "operator.write"
},
{
name: "talk.client.toolCall",
scope: "operator.write"
},
{
name: "talk.client.steer",
scope: "operator.write"
},
{
name: "talk.session.create",
scope: "operator.write"
},
{
name: "talk.session.join",
scope: "operator.write"
},
{
name: "talk.session.appendAudio",
scope: "operator.write"
},
{
name: "talk.session.startTurn",
scope: "operator.write"
},
{
name: "talk.session.endTurn",
scope: "operator.write"
},
{
name: "talk.session.cancelTurn",
scope: "operator.write"
},
{
name: "talk.session.cancelOutput",
scope: "operator.write"
},
{
name: "talk.session.submitToolResult",
scope: "operator.write"
},
{
name: "talk.session.steer",
scope: "operator.write"
},
{
name: "talk.session.close",
scope: "operator.write"
},
{
name: "talk.speak",
scope: "operator.write"
},
{
name: "talk.mode",
scope: "operator.write"
},
{
name: "commands.list",
scope: "operator.read"
},
{
name: "models.list",
scope: "operator.read",
startup: true
},
{
name: "models.authStatus",
scope: "operator.read"
},
{
name: "models.authLogout",
scope: "operator.admin",
controlPlaneWrite: true
},
{
name: "tools.catalog",
scope: "operator.read"
},
{
name: "tools.effective",
scope: "operator.read",
startup: true
},
{
name: "tools.invoke",
scope: "operator.write"
},
{
name: "tasks.list",
scope: "operator.read"
},
{
name: "tasks.get",
scope: "operator.read"
},
{
name: "tasks.cancel",
scope: "operator.write"
},
{
name: "environments.list",
scope: "operator.read"
},
{
name: "environments.status",
scope: "operator.read"
},
{
name: "agents.list",
scope: "operator.read"
},
{
name: "agents.create",
scope: "operator.admin"
},
{
name: "agents.update",
scope: "operator.admin"
},
{
name: "agents.delete",
scope: "operator.admin"
},
{
name: "agents.files.list",
scope: "operator.read"
},
{
name: "agents.files.get",
scope: "operator.read"
},
{
name: "agents.files.set",
scope: "operator.admin"
},
{
name: "artifacts.list",
scope: "operator.read"
},
{
name: "artifacts.get",
scope: "operator.read"
},
{
name: "artifacts.download",
scope: "operator.read"
},
{
name: "skills.status",
scope: "operator.read"
},
{
name: "skills.search",
scope: "operator.read"
},
{
name: "skills.detail",
scope: "operator.read"
},
{
name: "skills.securityVerdicts",
scope: "operator.read"
},
{
name: "skills.skillCard",
scope: "operator.read"
},
{
name: "skills.bins",
scope: "node"
},
{
name: "skills.upload.begin",
scope: "operator.admin"
},
{
name: "skills.upload.chunk",
scope: "operator.admin"
},
{
name: "skills.upload.commit",
scope: "operator.admin"
},
{
name: "skills.install",
scope: "operator.admin"
},
{
name: "skills.update",
scope: "operator.admin"
},
{
name: "skills.proposals.list",
scope: "operator.read"
},
{
name: "skills.proposals.inspect",
scope: "operator.read"
},
{
name: "skills.proposals.create",
scope: "operator.admin"
},
{
name: "skills.proposals.update",
scope: "operator.admin"
},
{
name: "skills.proposals.revise",
scope: "operator.admin"
},
{
name: "skills.proposals.requestRevision",
scope: "operator.admin"
},
{
name: "skills.proposals.apply",
scope: "operator.admin"
},
{
name: "skills.proposals.reject",
scope: "operator.admin"
},
{
name: "skills.proposals.quarantine",
scope: "operator.admin"
},
{
name: "update.status",
scope: "operator.admin"
},
{
name: "update.run",
scope: "operator.admin",
controlPlaneWrite: true
},
{
name: "voicewake.get",
scope: "operator.read"
},
{
name: "voicewake.set",
scope: "operator.write"
},
{
name: "secrets.reload",
scope: "operator.admin"
},
{
name: "secrets.resolve",
scope: "operator.admin"
},
{
name: "voicewake.routing.get",
scope: "operator.read"
},
{
name: "voicewake.routing.set",
scope: "operator.write"
},
{
name: "sessions.list",
scope: "operator.read",
startup: true
},
{
name: "sessions.subscribe",
scope: "operator.read"
},
{
name: "sessions.unsubscribe",
scope: "operator.read"
},
{
name: "sessions.messages.subscribe",
scope: "operator.read"
},
{
name: "sessions.messages.unsubscribe",
scope: "operator.read"
},
{
name: "sessions.preview",
scope: "operator.read"
},
{
name: "sessions.describe",
scope: "operator.read"
},
{
name: "sessions.compaction.list",
scope: "operator.read"
},
{
name: "sessions.compaction.get",
scope: "operator.read"
},
{
name: "sessions.compaction.branch",
scope: "operator.write"
},
{
name: "sessions.compaction.restore",
scope: "operator.admin"
},
{
name: "sessions.create",
scope: "operator.write",
startup: true
},
{
name: "sessions.send",
scope: "operator.write",
startup: true
},
{
name: "sessions.abort",
scope: "operator.write",
startup: true
},
{
name: "sessions.patch",
scope: "operator.admin"
},
{
name: "sessions.pluginPatch",
scope: "operator.admin"
},
{
name: "sessions.cleanup",
scope: "operator.admin"
},
{
name: "sessions.reset",
scope: "operator.admin"
},
{
name: "sessions.delete",
scope: "operator.admin"
},
{
name: "sessions.compact",
scope: "operator.admin"
},
{
name: "last-heartbeat",
scope: "operator.read"
},
{
name: "set-heartbeats",
scope: "operator.admin"
},
{
name: "wake",
scope: "operator.write"
},
{
name: "node.pair.request",
scope: "operator.pairing"
},
{
name: "node.pair.list",
scope: "operator.pairing"
},
{
name: "node.pair.approve",
scope: "operator.pairing"
},
{
name: "node.pair.reject",
scope: "operator.pairing"
},
{
name: "node.pair.remove",
scope: "operator.pairing"
},
{
name: "node.pair.verify",
scope: "operator.pairing"
},
{
name: "device.pair.list",
scope: "operator.pairing"
},
{
name: "device.pair.approve",
scope: "operator.pairing"
},
{
name: "device.pair.reject",
scope: "operator.pairing"
},
{
name: "device.pair.remove",
scope: "operator.pairing"
},
{
name: "device.token.rotate",
scope: "operator.pairing"
},
{
name: "device.token.revoke",
scope: "operator.pairing"
},
{
name: "node.rename",
scope: "operator.pairing"
},
{
name: "node.list",
scope: "operator.read"
},
{
name: "node.describe",
scope: "operator.read"
},
{
name: "node.pluginSurface.refresh",
scope: "node"
},
{
name: "node.pending.drain",
scope: "node"
},
{
name: "node.pending.enqueue",
scope: "operator.write"
},
{
name: "node.invoke",
scope: "operator.write"
},
{
name: "node.pending.pull",
scope: "node"
},
{
name: "node.pending.ack",
scope: "node"
},
{
name: "node.invoke.result",
scope: "node"
},
{
name: "node.event",
scope: "node"
},
{
name: "cron.get",
scope: "operator.read"
},
{
name: "cron.list",
scope: "operator.read"
},
{
name: "cron.status",
scope: "operator.read"
},
{
name: "cron.add",
scope: "operator.admin"
},
{
name: "cron.update",
scope: "operator.admin"
},
{
name: "cron.remove",
scope: "operator.admin"
},
{
name: "cron.run",
scope: "operator.admin"
},
{
name: "cron.runs",
scope: "operator.read"
},
{
name: "gateway.identity.get",
scope: "operator.read"
},
{
name: "gateway.restart.preflight",
scope: "operator.read"
},
{
name: "gateway.restart.request",
scope: "operator.admin",
controlPlaneWrite: true
},
{
name: "system-presence",
scope: "operator.read"
},
{
name: "system-event",
scope: "operator.admin"
},
{
name: "message.action",
scope: "operator.write"
},
{
name: "send",
scope: "operator.write"
},
{
name: "agent",
scope: "operator.write"
},
{
name: "agent.identity.get",
scope: "operator.read"
},
{
name: "agent.wait",
scope: "operator.write",
startup: true
},
{
name: "chat.history",
scope: "operator.read",
startup: true
},
{
name: "chat.startup",
scope: "operator.read",
startup: true
},
{
name: "chat.metadata",
scope: "operator.read",
startup: true
},
{
name: "chat.message.get",
scope: "operator.read",
startup: true
},
{
name: "chat.abort",
scope: "operator.write"
},
{
name: "chat.send",
scope: "operator.write"
},
{
name: "assistant.media.get",
scope: "operator.read",
advertise: false
},
{
name: "sessions.get",
scope: "operator.read",
advertise: false
},
{
name: "sessions.resolve",
scope: "operator.read",
advertise: false
},
{
name: "sessions.usage",
scope: "operator.read",
advertise: false
},
{
name: "sessions.usage.timeseries",
scope: "operator.read",
advertise: false
},
{
name: "sessions.usage.logs",
scope: "operator.read",
advertise: false
},
{
name: "poll",
scope: "operator.write",
advertise: false
},
{
name: "sessions.steer",
scope: "operator.write",
advertise: false
},
{
name: "push.test",
scope: "operator.write",
advertise: false
},
{
name: "push.web.vapidPublicKey",
scope: "operator.write",
advertise: false
},
{
name: "push.web.subscribe",
scope: "operator.write",
advertise: false
},
{
name: "push.web.unsubscribe",
scope: "operator.write",
advertise: false
},
{
name: "push.web.test",
scope: "operator.write",
advertise: false
},
{
name: "config.openFile",
scope: "operator.admin",
advertise: false
},
{
name: "connect",
scope: "operator.admin",
advertise: false
},
{
name: "chat.inject",
scope: "operator.admin",
advertise: false
},
{
name: "nativeHook.invoke",
scope: "operator.admin",
advertise: false
},
{
name: "web.login.start",
scope: "operator.admin",
advertise: false
},
{
name: "web.login.wait",
scope: "operator.admin",
advertise: false
}
];
const CORE_GATEWAY_METHOD_SPEC_BY_NAME = new Map(CORE_GATEWAY_METHOD_SPECS.map((spec) => [spec.name, spec]));
/** Core methods that are listed early but return retryable unavailable until sidecars are ready. */
const STARTUP_UNAVAILABLE_GATEWAY_METHODS = CORE_GATEWAY_METHOD_SPECS.filter((spec) => spec.startup === true).map((spec) => spec.name);
/** Returns the core methods that should be advertised to external gateway clients. */
function listCoreAdvertisedGatewayMethodNames() {
return CORE_GATEWAY_METHOD_SPECS.filter((spec) => spec.advertise !== false).map((spec) => spec.name);
}
/** Returns all registered core method names, including hidden/internal compatibility methods. */
function listCoreGatewayMethodNames() {
return CORE_GATEWAY_METHOD_SPECS.map((spec) => spec.name);
}
/** Looks up the raw core method scope, including node and dynamic sentinel scopes. */
function resolveCoreGatewayMethodScope(method) {
return CORE_GATEWAY_METHOD_SPEC_BY_NAME.get(method)?.scope;
}
/** Looks up an operator-only core method scope, excluding node and dynamic methods. */
function resolveCoreOperatorGatewayMethodScope(method) {
const scope = resolveCoreGatewayMethodScope(method);
return scope === "node" || scope === "dynamic" ? void 0 : scope;
}
/** Returns true for core methods reserved for authenticated node clients. */
function isCoreNodeGatewayMethod(method) {
return resolveCoreGatewayMethodScope(method) === NODE_GATEWAY_METHOD_SCOPE;
}
/** Returns true for core methods whose required operator scope is resolved by the handler. */
function isDynamicOperatorGatewayMethod(method) {
return resolveCoreGatewayMethodScope(method) === DYNAMIC_GATEWAY_METHOD_SCOPE;
}
/** Returns true when a method name has an explicit core policy entry. */
function isCoreGatewayMethodClassified(method) {
return CORE_GATEWAY_METHOD_SPEC_BY_NAME.has(method);
}
/** Creates dispatch descriptors for core handlers and fails if any handler lacks policy. */
function createCoreGatewayMethodDescriptors(handlers) {
const descriptors = [];
const specNames = /* @__PURE__ */ new Set();
for (const spec of CORE_GATEWAY_METHOD_SPECS) {
specNames.add(spec.name);
const handler = handlers[spec.name];
if (!handler) continue;
descriptors.push({
name: spec.name,
handler,
owner: {
kind: "core",
area: "gateway"
},
scope: spec.scope,
...spec.advertise === false ? { advertise: false } : {},
...spec.startup === true ? { startup: "unavailable-until-sidecars" } : {},
...spec.controlPlaneWrite === true ? { controlPlaneWrite: true } : {}
});
}
for (const name of Object.keys(handlers)) if (!specNames.has(name)) throw new Error(`gateway method handler is missing a descriptor: ${name}`);
return descriptors;
}
//#endregion
export { isDynamicOperatorGatewayMethod as a, resolveCoreOperatorGatewayMethodScope as c, isCoreNodeGatewayMethod as i, DYNAMIC_GATEWAY_METHOD_SCOPE as l, createCoreGatewayMethodDescriptors as n, listCoreAdvertisedGatewayMethodNames as o, isCoreGatewayMethodClassified as r, listCoreGatewayMethodNames as s, STARTUP_UNAVAILABLE_GATEWAY_METHODS as t, NODE_GATEWAY_METHOD_SCOPE as u };