UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

69 lines (68 loc) 3.37 kB
import { c as normalizeOptionalLowercaseString, o as normalizeLowercaseStringOrEmpty } from "./string-coerce-CIXf7egm.js"; //#region src/agents/agent-bundle-mcp-names.ts /** Sanitizes MCP server/tool names into stable model-facing tool ids. */ const TOOL_NAME_SAFE_RE = /[^A-Za-z0-9_-]/g; const TOOL_NAME_MAX_PREFIX = 30; const TOOL_NAME_MAX_TOTAL = 64; /** Builds stable node-ID prefixes capped at 32 characters. */ function sanitizeNodeIdFragment(value) { const fragment = value.trim().toLowerCase().replace(/[^a-z0-9_]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 32); if (!fragment) return "node"; return /^[a-z]/.test(fragment) ? fragment : `node_${fragment}`.slice(0, 32); } function sanitizeToolFragment(raw, fallback, maxChars) { const normalized = raw.trim().replace(TOOL_NAME_SAFE_RE, "-") || fallback; const providerSafe = /^[A-Za-z]/.test(normalized) ? normalized : `${fallback}-${normalized}`; if (!maxChars) return providerSafe; return providerSafe.length > maxChars ? providerSafe.slice(0, maxChars) : providerSafe; } /** Sanitize one MCP server name and reserve it in the provided set. */ function sanitizeServerName(raw, usedNames) { const base = sanitizeToolFragment(raw, "mcp", TOOL_NAME_MAX_PREFIX); let candidate = base; let n = 2; while (usedNames.has(normalizeLowercaseStringOrEmpty(candidate))) { const suffix = `-${n}`; candidate = `${base.slice(0, Math.max(1, TOOL_NAME_MAX_PREFIX - suffix.length))}${suffix}`; n += 1; } usedNames.add(normalizeLowercaseStringOrEmpty(candidate)); return candidate; } /** * Assign safe server names from the full declared set in declaration order, * independent of which servers resolve for a requester. Declaration order * preserves legacy collision-suffix ownership for existing static configs; * sorting here would silently swap safe names between colliding servers. */ function assignSafeServerNames(serverNames) { const usedNames = /* @__PURE__ */ new Set(); const assignments = /* @__PURE__ */ new Map(); for (const serverName of serverNames) assignments.set(serverName, sanitizeServerName(serverName, usedNames)); return assignments; } function sanitizeToolName(raw) { return sanitizeToolFragment(raw, "tool"); } /** Normalizes reserved tool names for collision checks. */ function normalizeReservedToolNames(names) { return new Set(Array.from(names ?? [], (name) => normalizeOptionalLowercaseString(name)).filter((name) => Boolean(name))); } /** Build a safe model-facing tool name from server and tool fragments. */ function buildSafeToolName(params) { const cleanedToolName = sanitizeToolName(params.toolName); const maxToolChars = Math.max(1, TOOL_NAME_MAX_TOTAL - params.serverName.length - 2); const truncatedToolName = cleanedToolName.slice(0, maxToolChars); let candidateToolName = truncatedToolName || "tool"; let candidate = `${params.serverName}__${candidateToolName}`; let n = 2; while (params.reservedNames.has(normalizeLowercaseStringOrEmpty(candidate))) { const suffix = `-${n}`; candidateToolName = `${(truncatedToolName || "tool").slice(0, Math.max(1, maxToolChars - suffix.length))}${suffix}`; candidate = `${params.serverName}__${candidateToolName}`; n += 1; } return candidate; } //#endregion export { sanitizeServerName as a, sanitizeNodeIdFragment as i, buildSafeToolName as n, normalizeReservedToolNames as r, assignSafeServerNames as t };