openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
74 lines (73 loc) • 4.1 kB
JavaScript
import { l as normalizeOptionalString } from "./string-coerce-CIXf7egm.js";
import { d as normalizeStringEntries } from "./string-normalization-DsCfAx8q.js";
import { t as formatCliCommand } from "./command-format-C7YfyMTd.js";
import { i as normalizeChatChannelId } from "./ids-BVZRYG0I.js";
import "./message-channel-constants-2zSoJXQC.js";
import { t as note } from "./note-DqHk3fA1.js";
//#region src/commands/doctor-command-owner.ts
/** Doctor warning for missing command owners on privileged channel commands. */
/** Persist legacy channel-qualified owners before runtime compares native sender IDs. */
function migrateLegacyCommandOwners(cfg, changes) {
const owners = cfg.commands?.ownerAllowFrom;
if (!Array.isArray(owners)) return cfg;
let changed = false;
const ownerAllowFrom = owners.map((entry, index) => {
const legacy = typeof entry === "string" ? /^([^:]+):user:([^:\s*]+)$/i.exec(entry.trim()) : null;
const channel = legacy && normalizeChatChannelId(legacy[1]);
if (!channel || !legacy) return entry;
changed = true;
changes.push(`Normalized commands.ownerAllowFrom[${index}] from ${channel}:user:id to ${channel}:id.`);
return `${channel}:${legacy[2]}`;
});
return changed ? {
...cfg,
commands: {
...cfg.commands,
ownerAllowFrom
}
} : cfg;
}
function resolveConfiguredCommandOwners(cfg) {
const owners = cfg.commands?.ownerAllowFrom;
if (!Array.isArray(owners)) return [];
return normalizeStringEntries(owners.map((entry) => String(entry ?? ""))).filter((entry) => entry !== "*" && !entry.endsWith(":*"));
}
/** Returns true when at least one owner sender id is configured. */
function hasConfiguredCommandOwners(cfg) {
return resolveConfiguredCommandOwners(cfg).length > 0;
}
/** Formats a channel sender id into the commands.ownerAllowFrom entry shape. */
function formatCommandOwnerFromChannelSender(params) {
const id = normalizeOptionalString(params.id);
if (!id) return null;
const separatorIndex = id.indexOf(":");
if (separatorIndex > 0) {
if (id.slice(0, separatorIndex).toLowerCase() === String(params.channel).toLowerCase()) return id;
}
return `${params.channel}:${id}`;
}
/** Gives admitted senders an operator-run command without granting owner authority. */
function formatCommandOwnerHint(params) {
if (params.channel === "webchat") return "Ask the operator to grant this Gateway client operator.admin access.";
const owner = params.channel && params.id ? formatCommandOwnerFromChannelSender({
channel: params.channel,
id: params.id
}) : null;
if (!owner) return "Ask the operator to set commands.ownerAllowFrom to your channel user id.";
if (!params.cfg) return `Ask the operator to add \`${owner}\` to \`commands.ownerAllowFrom\`.`;
const owners = JSON.stringify([.../* @__PURE__ */ new Set([...resolveConfiguredCommandOwners(params.cfg), owner])]).replaceAll("'", process.platform === "win32" ? "''" : "'\\''");
return `Ask the operator to run \`${formatCliCommand("openclaw config set commands.ownerAllowFrom")} '${owners}'\` in a terminal to make this sender a command owner.`;
}
/** Emits setup guidance when privileged command ownership is not configured. */
function noteCommandOwnerHealth(cfg) {
if (hasConfiguredCommandOwners(cfg)) return;
note([
"No command owner is configured.",
"A command owner is the human operator account allowed to run owner-only commands and approve dangerous actions, including /diagnostics, /export-session, /export-trajectory, /config, and exec approvals.",
"CLI pairing approval records the first command owner. Control UI approval has an owner checkbox; otherwise set commands.ownerAllowFrom.",
`Fix: set commands.ownerAllowFrom to your channel user id, for example ${formatCliCommand("openclaw config set commands.ownerAllowFrom '[\"telegram:123456789\"]'")}`,
"Restart the gateway after changing this if it is already running."
].join("\n"), "Command owner");
}
//#endregion
export { noteCommandOwnerHealth as a, migrateLegacyCommandOwners as i, formatCommandOwnerHint as n, hasConfiguredCommandOwners as r, formatCommandOwnerFromChannelSender as t };