// src/mcp-client-manager/mcp-protocol-version.ts
var MCP_PROTOCOL_VERSIONS = [
  "2025-03-26",
  "2025-06-18",
  "2025-11-25",
  "2026-07-28"
];
var STATEFUL_PROTOCOL_VERSIONS = /* @__PURE__ */ new Set([
  "2024-10-07",
  "2024-11-05",
  "2025-03-26",
  "2025-06-18",
  "2025-11-25"
]);
function isKnownProtocolVersion(v) {
  return MCP_PROTOCOL_VERSIONS.includes(v);
}
function isStatelessProtocolVersion(v) {
  return v.length > 0 && !STATEFUL_PROTOCOL_VERSIONS.has(v);
}

// src/host-config/types.ts
var HOST_CONFIG_SCHEMA_VERSION_V2 = 2;
var SEP_1865_PERMISSION_FEATURES = [
  "camera",
  "microphone",
  "geolocation",
  "clipboard-write"
];

// src/host-config/canonicalize.ts
var OPENAI_APPS_CAPABILITY_KEYS = [
  "callTool",
  "sendFollowUpMessage",
  "setWidgetState",
  "requestDisplayMode",
  "notifyIntrinsicHeight",
  "openExternal",
  "setOpenInAppUrl",
  "requestModal",
  "uploadFile",
  "selectFiles",
  "getFileDownloadUrl",
  "requestCheckout",
  "requestClose"
];
var OPENAI_APPS_CAPABILITY_KEY_SET = new Set(
  OPENAI_APPS_CAPABILITY_KEYS
);
var OPENAI_APPS_REQUEST_DISPLAY_MODE_VALUES = [
  "all",
  "fullscreen-only",
  "none"
];
var MCP_APPS_CAPABILITY_KEYS = [
  "availableDisplayModes",
  "toolInputPartial",
  "toolCancelled",
  "hostContextChanged",
  "resourceTeardown",
  "toolInfo",
  "openLinks",
  "serverTools",
  "serverResources",
  "logging",
  "updateModelContext",
  "message",
  "sandboxPermissions",
  "cspFrameDomains",
  "cspBaseUriDomains",
  "resourcePrefersBorder",
  "downloadFile",
  "requestTeardown",
  "widgetDisplayModeRequests"
];
var MCP_APPS_CAPABILITY_KEY_SET = new Set(
  MCP_APPS_CAPABILITY_KEYS
);
var MCP_APPS_DISPLAY_MODE_VALUES = ["inline", "fullscreen", "pip"];
var MCP_APPS_WIDGET_DISPLAY_MODE_REQUEST_VALUES = [
  "accept",
  "user-initiated-only",
  "decline"
];
var MCP_APPS_DISPLAY_MODE_VALUE_SET = new Set(
  MCP_APPS_DISPLAY_MODE_VALUES
);
function sortStringKeys(input) {
  const out = {};
  for (const k of Object.keys(input).sort()) out[k] = input[k];
  return out;
}
function requireRecord(value, fieldName) {
  if (value === void 0) {
    throw new Error(`hostConfigV2: ${fieldName} is required`);
  }
  if (!isPlainObject(value)) {
    throw new Error(`hostConfigV2: ${fieldName} must be a plain object`);
  }
  return deepSortStringKeys(value);
}
function deepSortStringKeys(input) {
  if (Array.isArray(input)) {
    return input.map((v) => deepSortStringKeys(v));
  }
  if (input && typeof input === "object") {
    const out = {};
    const src = input;
    for (const k of Object.keys(src).sort()) {
      out[k] = deepSortStringKeys(src[k]);
    }
    return out;
  }
  return input;
}
function sortUniqueServerIds(ids) {
  return Array.from(new Set(ids ?? [])).sort();
}
function isPlainObject(value) {
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
    return false;
  }
  const proto = Object.getPrototypeOf(value);
  return proto === Object.prototype || proto === null;
}
function canonicalizeCspDomainList(value) {
  if (value === void 0) return void 0;
  if (!Array.isArray(value)) {
    throw new Error(
      "hostConfigV2: mcpProfile CSP domain list must be a string[]"
    );
  }
  const seen = /* @__PURE__ */ new Set();
  for (const entry of value) {
    if (typeof entry !== "string") {
      throw new Error(
        "hostConfigV2: mcpProfile CSP domain list entries must be strings"
      );
    }
    const trimmed = entry.trim();
    if (trimmed === "") continue;
    seen.add(trimmed);
  }
  return Array.from(seen).sort();
}
function canonicalizeCspDomainSet(value) {
  if (value === void 0) return void 0;
  if (!isPlainObject(value)) {
    throw new Error(
      "hostConfigV2: mcpProfile CSP restrictTo must be a plain object"
    );
  }
  const out = {};
  const src = value;
  for (const key of [
    "connectDomains",
    "resourceDomains",
    "frameDomains",
    "baseUriDomains"
  ]) {
    const canonical = canonicalizeCspDomainList(src[key]);
    if (canonical !== void 0) out[key] = canonical;
  }
  for (const key of Object.keys(src).sort()) {
    if (key === "connectDomains" || key === "resourceDomains" || key === "frameDomains" || key === "baseUriDomains") {
      continue;
    }
    out[key] = deepSortStringKeys(src[key]);
  }
  const sorted = {};
  for (const key of Object.keys(out).sort()) {
    sorted[key] = out[key];
  }
  return sorted;
}
function canonicalizeAllowFeatures(value) {
  if (value === void 0) return void 0;
  if (!isPlainObject(value)) {
    throw new Error(
      "hostConfigV2: mcpProfile.apps.sandbox.allowFeatures must be a plain object"
    );
  }
  const dropped = new Set(SEP_1865_PERMISSION_FEATURES);
  const out = {};
  for (const k of Object.keys(value).sort()) {
    if (!/^[a-z][a-z0-9-]*$/.test(k)) {
      throw new Error(
        `hostConfigV2: mcpProfile.apps.sandbox.allowFeatures key "${k}" must be a lowercase kebab-case Permissions Policy token (^[a-z][a-z0-9-]*$)`
      );
    }
    if (dropped.has(k)) continue;
    const v = value[k];
    if (typeof v !== "string") {
      throw new Error(
        `hostConfigV2: mcpProfile.apps.sandbox.allowFeatures.${k} must be a string`
      );
    }
    if (/[;,]/.test(v)) {
      throw new Error(
        `hostConfigV2: mcpProfile.apps.sandbox.allowFeatures.${k} must not contain ';' or ',' (Permissions Policy directive separators)`
      );
    }
    out[k] = v;
  }
  if (Object.keys(out).length === 0) return void 0;
  return out;
}
function canonicalizeCspDirectives(value) {
  if (value === void 0) return void 0;
  if (!isPlainObject(value)) {
    throw new Error(
      "hostConfigV2: mcpProfile.apps.sandbox.csp.cspDirectives must be a plain object"
    );
  }
  const out = {};
  for (const k of Object.keys(value).sort()) {
    if (!/^[a-z][a-z0-9-]*$/.test(k)) {
      throw new Error(
        `hostConfigV2: mcpProfile.apps.sandbox.csp.cspDirectives key "${k}" must be a lowercase kebab-case CSP directive name (^[a-z][a-z0-9-]*$)`
      );
    }
    const arr = value[k];
    if (!Array.isArray(arr)) {
      throw new Error(
        `hostConfigV2: mcpProfile.apps.sandbox.csp.cspDirectives.${k} must be a string[]`
      );
    }
    const seen = /* @__PURE__ */ new Set();
    for (const entry of arr) {
      if (typeof entry !== "string") {
        throw new Error(
          `hostConfigV2: mcpProfile.apps.sandbox.csp.cspDirectives.${k} entries must be strings`
        );
      }
      const trimmed = entry.trim();
      if (trimmed === "") continue;
      if (/[;,]/.test(trimmed)) {
        throw new Error(
          `hostConfigV2: mcpProfile.apps.sandbox.csp.cspDirectives.${k} entry "${trimmed}" must not contain ';' or ',' (CSP directive separators \u2014 injection guard)`
        );
      }
      seen.add(trimmed);
    }
    out[k] = Array.from(seen).sort();
  }
  return out;
}
function canonicalizeMcpProfile(input) {
  if (input === void 0) return void 0;
  if (!isPlainObject(input)) {
    throw new Error("hostConfigV2: mcpProfile must be a plain object");
  }
  if (input.profileVersion !== 1) {
    throw new Error("hostConfigV2: mcpProfile.profileVersion must be 1");
  }
  const out = { profileVersion: 1 };
  if (input.mcpProtocolVersion !== void 0) {
    if (!isKnownProtocolVersion(input.mcpProtocolVersion)) {
      throw new Error(
        `hostConfigV2: mcpProfile.mcpProtocolVersion must be one of ${MCP_PROTOCOL_VERSIONS.join(", ")} (got "${String(input.mcpProtocolVersion)}")`
      );
    }
    out.mcpProtocolVersion = input.mcpProtocolVersion;
  }
  if (input.initialize !== void 0) {
    if (!isPlainObject(input.initialize)) {
      throw new Error(
        "hostConfigV2: mcpProfile.initialize must be a plain object"
      );
    }
    const initOut = {};
    if (input.initialize.supportedProtocolVersions !== void 0) {
      const versions = input.initialize.supportedProtocolVersions;
      if (!Array.isArray(versions)) {
        throw new Error(
          "hostConfigV2: mcpProfile.initialize.supportedProtocolVersions must be a string[]"
        );
      }
      if (versions.length === 0) {
        throw new Error(
          "hostConfigV2: mcpProfile.initialize.supportedProtocolVersions must be a non-empty array when set (omit the field to use SDK defaults)"
        );
      }
      for (const v of versions) {
        if (typeof v !== "string") {
          throw new Error(
            "hostConfigV2: mcpProfile.initialize.supportedProtocolVersions entries must be strings"
          );
        }
        if (v.trim() === "") {
          throw new Error(
            "hostConfigV2: mcpProfile.initialize.supportedProtocolVersions entries must be non-empty strings"
          );
        }
      }
      initOut.supportedProtocolVersions = [...versions];
    }
    if (input.initialize.clientInfo !== void 0) {
      const ci = input.initialize.clientInfo;
      if (!isPlainObject(ci)) {
        throw new Error(
          "hostConfigV2: mcpProfile.initialize.clientInfo must be a plain object"
        );
      }
      const name = ci.name;
      const version = ci.version;
      if (typeof name !== "string" || name.trim() === "") {
        throw new Error(
          "hostConfigV2: mcpProfile.initialize.clientInfo.name must be a non-empty string"
        );
      }
      if (typeof version !== "string" || version.trim() === "") {
        throw new Error(
          "hostConfigV2: mcpProfile.initialize.clientInfo.version must be a non-empty string"
        );
      }
      initOut.clientInfo = deepSortStringKeys(ci);
    }
    if (Object.keys(initOut).length > 0) {
      const sortedInit = {};
      for (const k of Object.keys(initOut).sort()) {
        sortedInit[k] = initOut[k];
      }
      out.initialize = sortedInit;
    }
  }
  if (out.mcpProtocolVersion !== void 0 && !isStatelessProtocolVersion(out.mcpProtocolVersion)) {
    const advertised = out.initialize?.supportedProtocolVersions;
    if (advertised === void 0) {
      const initBase = out.initialize ?? {};
      const initWithDerived = {
        ...initBase,
        supportedProtocolVersions: [out.mcpProtocolVersion]
      };
      const sortedInit = {};
      for (const k of Object.keys(initWithDerived).sort()) {
        sortedInit[k] = initWithDerived[k];
      }
      out.initialize = sortedInit;
    } else if (!advertised.includes(out.mcpProtocolVersion)) {
      throw new Error(
        `hostConfigV2: ConflictingProtocolVersionPin \u2014 mcpProtocolVersion "${out.mcpProtocolVersion}" is not in initialize.supportedProtocolVersions [${advertised.join(", ")}]. Either omit one or align them.`
      );
    }
  }
  if (input.apps !== void 0) {
    if (!isPlainObject(input.apps)) {
      throw new Error("hostConfigV2: mcpProfile.apps must be a plain object");
    }
    const appsOut = {};
    if (input.apps.sandbox !== void 0) {
      if (!isPlainObject(input.apps.sandbox)) {
        throw new Error(
          "hostConfigV2: mcpProfile.apps.sandbox must be a plain object"
        );
      }
      const sandboxIn = input.apps.sandbox;
      const sandboxOut = {};
      if (sandboxIn.csp !== void 0) {
        if (!isPlainObject(sandboxIn.csp)) {
          throw new Error(
            "hostConfigV2: mcpProfile.apps.sandbox.csp must be a plain object"
          );
        }
        const cspOut = {};
        if (sandboxIn.csp.mode !== void 0) {
          if (sandboxIn.csp.mode !== "host-default" && sandboxIn.csp.mode !== "declared" && sandboxIn.csp.mode !== "relaxed") {
            throw new Error(
              "hostConfigV2: mcpProfile.apps.sandbox.csp.mode must be 'host-default' | 'declared' | 'relaxed'"
            );
          }
          cspOut.mode = sandboxIn.csp.mode;
        }
        const restrictTo = canonicalizeCspDomainSet(sandboxIn.csp.restrictTo);
        if (restrictTo !== void 0) cspOut.restrictTo = restrictTo;
        const cspDirectives = canonicalizeCspDirectives(
          sandboxIn.csp.cspDirectives
        );
        if (cspDirectives !== void 0)
          cspOut.cspDirectives = cspDirectives;
        if (sandboxIn.csp.extensions !== void 0) {
          if (!isPlainObject(sandboxIn.csp.extensions)) {
            throw new Error(
              "hostConfigV2: mcpProfile.apps.sandbox.csp.extensions must be a plain object"
            );
          }
          cspOut.extensions = deepSortStringKeys(sandboxIn.csp.extensions);
        }
        const sortedCsp = {};
        for (const k of Object.keys(cspOut).sort()) {
          sortedCsp[k] = cspOut[k];
        }
        sandboxOut.csp = sortedCsp;
      }
      if (sandboxIn.permissions !== void 0) {
        if (!isPlainObject(sandboxIn.permissions)) {
          throw new Error(
            "hostConfigV2: mcpProfile.apps.sandbox.permissions must be a plain object"
          );
        }
        const permsIn = sandboxIn.permissions;
        const permsOut = {};
        if (permsIn.mode !== void 0) {
          if (permsIn.mode !== "resource-declared" && permsIn.mode !== "deny-all" && permsIn.mode !== "custom") {
            throw new Error(
              "hostConfigV2: mcpProfile.apps.sandbox.permissions.mode must be 'resource-declared' | 'deny-all' | 'custom'"
            );
          }
          permsOut.mode = permsIn.mode;
        }
        if (permsIn.allow !== void 0) {
          if (!isPlainObject(permsIn.allow)) {
            throw new Error(
              "hostConfigV2: mcpProfile.apps.sandbox.permissions.allow must be a plain object"
            );
          }
          const allowOut = {};
          for (const k of Object.keys(permsIn.allow).sort()) {
            const v = permsIn.allow[k];
            if (typeof v !== "boolean") {
              throw new Error(
                `hostConfigV2: mcpProfile.apps.sandbox.permissions.allow.${k} must be a boolean`
              );
            }
            allowOut[k] = v;
          }
          permsOut.allow = allowOut;
        }
        if (permsIn.extensions !== void 0) {
          if (!isPlainObject(permsIn.extensions)) {
            throw new Error(
              "hostConfigV2: mcpProfile.apps.sandbox.permissions.extensions must be a plain object"
            );
          }
          permsOut.extensions = deepSortStringKeys(permsIn.extensions);
        }
        const sortedPerms = {};
        for (const k of Object.keys(permsOut).sort()) {
          sortedPerms[k] = permsOut[k];
        }
        sandboxOut.permissions = sortedPerms;
      }
      if (sandboxIn.sandboxAttrs !== void 0) {
        const sandboxAttrs = canonicalizeCspDomainList(
          sandboxIn.sandboxAttrs
        );
        if (sandboxAttrs !== void 0) {
          sandboxOut.sandboxAttrs = sandboxAttrs;
        }
      }
      if (sandboxIn.allowFeatures !== void 0) {
        const allowFeatures = canonicalizeAllowFeatures(
          sandboxIn.allowFeatures
        );
        if (allowFeatures !== void 0) {
          sandboxOut.allowFeatures = allowFeatures;
        }
      }
      if (Object.keys(sandboxOut).length > 0) {
        const sortedSandbox = {};
        for (const k of Object.keys(sandboxOut).sort()) {
          sortedSandbox[k] = sandboxOut[k];
        }
        appsOut.sandbox = sortedSandbox;
      }
    }
    if (input.apps.uiInitialize !== void 0) {
      if (!isPlainObject(input.apps.uiInitialize)) {
        throw new Error(
          "hostConfigV2: mcpProfile.apps.uiInitialize must be a plain object"
        );
      }
      const uiInitOut = {};
      if (input.apps.uiInitialize.hostInfo !== void 0) {
        const hi = input.apps.uiInitialize.hostInfo;
        if (!isPlainObject(hi)) {
          throw new Error(
            "hostConfigV2: mcpProfile.apps.uiInitialize.hostInfo must be a plain object"
          );
        }
        const name = hi.name;
        if (typeof name !== "string" || name.trim() === "") {
          throw new Error(
            "hostConfigV2: mcpProfile.apps.uiInitialize.hostInfo.name must be a non-empty string"
          );
        }
        const version = hi.version;
        if (typeof version !== "string" || version.trim() === "") {
          throw new Error(
            "hostConfigV2: mcpProfile.apps.uiInitialize.hostInfo.version must be a non-empty string"
          );
        }
        uiInitOut.hostInfo = deepSortStringKeys(hi);
      }
      if (Object.keys(uiInitOut).length > 0) {
        const sortedUiInit = {};
        for (const k of Object.keys(uiInitOut).sort()) {
          sortedUiInit[k] = uiInitOut[k];
        }
        appsOut.uiInitialize = sortedUiInit;
      }
    }
    if (input.apps.compatRuntime !== void 0) {
      const compatRuntimeIn = input.apps.compatRuntime;
      if (!isPlainObject(compatRuntimeIn)) {
        throw new Error(
          "hostConfigV2: mcpProfile.apps.compatRuntime must be a plain object"
        );
      }
      const compatRuntimeOut = {};
      const compatRecord = compatRuntimeIn;
      const openaiApps = compatRecord.openaiApps;
      if (openaiApps !== void 0) {
        if (typeof openaiApps !== "boolean") {
          throw new Error(
            "hostConfigV2: mcpProfile.apps.compatRuntime.openaiApps must be a boolean"
          );
        }
        compatRuntimeOut.openaiApps = openaiApps;
      }
      const openaiAppsOverridesIn = compatRecord.openaiAppsOverrides;
      if (openaiAppsOverridesIn !== void 0) {
        if (!isPlainObject(openaiAppsOverridesIn)) {
          throw new Error(
            "hostConfigV2: mcpProfile.apps.compatRuntime.openaiAppsOverrides must be a plain object"
          );
        }
        const overridesOut = {};
        for (const [key, value] of Object.entries(openaiAppsOverridesIn)) {
          if (!OPENAI_APPS_CAPABILITY_KEY_SET.has(key)) {
            throw new Error(
              `hostConfigV2: mcpProfile.apps.compatRuntime.openaiAppsOverrides has unknown key "${key}"`
            );
          }
          if (key === "requestDisplayMode") {
            if (typeof value !== "string" || !OPENAI_APPS_REQUEST_DISPLAY_MODE_VALUES.includes(value)) {
              throw new Error(
                'hostConfigV2: mcpProfile.apps.compatRuntime.openaiAppsOverrides.requestDisplayMode must be "all" | "fullscreen-only" | "none"'
              );
            }
            overridesOut.requestDisplayMode = value;
          } else {
            if (typeof value !== "boolean") {
              throw new Error(
                `hostConfigV2: mcpProfile.apps.compatRuntime.openaiAppsOverrides.${key} must be a boolean`
              );
            }
            overridesOut[key] = value;
          }
        }
        if (Object.keys(overridesOut).length > 0 && compatRuntimeOut.openaiApps !== false) {
          const sortedOverrides = {};
          for (const k of Object.keys(overridesOut).sort()) {
            sortedOverrides[k] = overridesOut[k];
          }
          compatRuntimeOut.openaiAppsOverrides = sortedOverrides;
        }
      }
      if (Object.keys(compatRuntimeOut).length > 0) {
        const sortedCompat = {};
        for (const k of Object.keys(compatRuntimeOut).sort()) {
          sortedCompat[k] = compatRuntimeOut[k];
        }
        appsOut.compatRuntime = sortedCompat;
      }
    }
    if (input.apps.mcpAppsOverrides !== void 0) {
      const mcpAppsOverridesIn = input.apps.mcpAppsOverrides;
      if (!isPlainObject(mcpAppsOverridesIn)) {
        throw new Error(
          "hostConfigV2: mcpProfile.apps.mcpAppsOverrides must be a plain object"
        );
      }
      const mcpAppsOverridesOut = {};
      for (const [key, value] of Object.entries(mcpAppsOverridesIn)) {
        if (!MCP_APPS_CAPABILITY_KEY_SET.has(key)) {
          throw new Error(
            `hostConfigV2: mcpProfile.apps.mcpAppsOverrides has unknown key "${key}"`
          );
        }
        if (key === "availableDisplayModes") {
          if (!Array.isArray(value)) {
            throw new Error(
              "hostConfigV2: mcpProfile.apps.mcpAppsOverrides.availableDisplayModes must be an array"
            );
          }
          if (value.length === 0) {
            throw new Error(
              "hostConfigV2: mcpProfile.apps.mcpAppsOverrides.availableDisplayModes must contain at least one mode"
            );
          }
          const seen = /* @__PURE__ */ new Set();
          for (const entry of value) {
            if (typeof entry !== "string" || !MCP_APPS_DISPLAY_MODE_VALUE_SET.has(entry)) {
              throw new Error(
                'hostConfigV2: mcpProfile.apps.mcpAppsOverrides.availableDisplayModes entries must be "inline" | "fullscreen" | "pip"'
              );
            }
            seen.add(entry);
          }
          mcpAppsOverridesOut.availableDisplayModes = MCP_APPS_DISPLAY_MODE_VALUES.filter(
            (m) => seen.has(m)
          );
        } else if (key === "widgetDisplayModeRequests") {
          if (typeof value !== "string" || !MCP_APPS_WIDGET_DISPLAY_MODE_REQUEST_VALUES.includes(value)) {
            throw new Error(
              'hostConfigV2: mcpProfile.apps.mcpAppsOverrides.widgetDisplayModeRequests must be "accept" | "user-initiated-only" | "decline"'
            );
          }
          mcpAppsOverridesOut.widgetDisplayModeRequests = value;
        } else {
          if (typeof value !== "boolean") {
            throw new Error(
              `hostConfigV2: mcpProfile.apps.mcpAppsOverrides.${key} must be a boolean`
            );
          }
          mcpAppsOverridesOut[key] = value;
        }
      }
      if (Object.keys(mcpAppsOverridesOut).length > 0) {
        const sortedMcpApps = {};
        for (const k of Object.keys(mcpAppsOverridesOut).sort()) {
          sortedMcpApps[k] = mcpAppsOverridesOut[k];
        }
        appsOut.mcpAppsOverrides = sortedMcpApps;
      }
    }
    if (Object.keys(appsOut).length > 0) {
      const sortedApps = {};
      for (const k of Object.keys(appsOut).sort()) {
        sortedApps[k] = appsOut[k];
      }
      out.apps = sortedApps;
    }
  }
  if (input.extensions !== void 0) {
    if (!isPlainObject(input.extensions)) {
      throw new Error(
        "hostConfigV2: mcpProfile.extensions must be a plain object"
      );
    }
    out.extensions = deepSortStringKeys(input.extensions);
  }
  const sorted = { profileVersion: 1 };
  for (const k of Object.keys(out).sort()) {
    if (k === "profileVersion") continue;
    sorted[k] = out[k];
  }
  return sorted;
}
function canonicalizeServerConnectionOverrides(serverIds, optionalServerIds, overrides) {
  if (!overrides || Object.keys(overrides).length === 0) return void 0;
  const allowedIds = /* @__PURE__ */ new Set([...serverIds, ...optionalServerIds]);
  const result = {};
  for (const [serverId, entry] of Object.entries(overrides)) {
    if (!allowedIds.has(serverId)) {
      throw new Error(
        `hostConfigV2: serverConnectionOverrides key "${serverId}" is not in serverIds or optionalServerIds`
      );
    }
    if (!entry) continue;
    const normalizedHeaders = entry.headersOverride && Object.keys(entry.headersOverride).length > 0 ? sortStringKeys(entry.headersOverride) : void 0;
    let mcpProtocolVersionOverride;
    if (entry.mcpProtocolVersionOverride !== void 0) {
      if (!isKnownProtocolVersion(entry.mcpProtocolVersionOverride)) {
        throw new Error(
          `hostConfigV2: serverConnectionOverrides["${serverId}"].mcpProtocolVersionOverride must be one of ${MCP_PROTOCOL_VERSIONS.join(", ")} (got "${String(entry.mcpProtocolVersionOverride)}")`
        );
      }
      mcpProtocolVersionOverride = entry.mcpProtocolVersionOverride;
    }
    if (entry.requestTimeoutOverride !== void 0 && !Number.isFinite(entry.requestTimeoutOverride)) {
      throw new Error(
        `hostConfigV2: serverConnectionOverrides["${serverId}"].requestTimeoutOverride must be finite`
      );
    }
    const hasContent = normalizedHeaders !== void 0 || entry.requestTimeoutOverride !== void 0 || mcpProtocolVersionOverride !== void 0;
    if (hasContent) {
      const entryOut = {
        ...normalizedHeaders !== void 0 ? { headersOverride: normalizedHeaders } : {},
        ...entry.requestTimeoutOverride !== void 0 ? { requestTimeoutOverride: entry.requestTimeoutOverride } : {},
        ...mcpProtocolVersionOverride !== void 0 ? { mcpProtocolVersionOverride } : {}
      };
      result[serverId] = sortStringKeys(entryOut);
    }
  }
  if (Object.keys(result).length === 0) return void 0;
  return sortStringKeys(
    result
  );
}
function canonicalizeHostConfigV2(input) {
  if (!Number.isFinite(input.temperature)) {
    throw new Error("hostConfigV2: temperature must be finite");
  }
  if (!Number.isFinite(input.connectionDefaults.requestTimeout)) {
    throw new Error(
      "hostConfigV2: connectionDefaults.requestTimeout must be finite"
    );
  }
  if (input.hostCapabilitiesOverride !== void 0 && (input.hostCapabilitiesOverride === null || typeof input.hostCapabilitiesOverride !== "object" || Array.isArray(input.hostCapabilitiesOverride))) {
    throw new Error(
      "hostConfigV2: hostCapabilitiesOverride must be a plain object"
    );
  }
  if (input.chatUiOverride !== void 0 && (input.chatUiOverride === null || typeof input.chatUiOverride !== "object" || Array.isArray(input.chatUiOverride))) {
    throw new Error("hostConfigV2: chatUiOverride must be a plain object");
  }
  const serverIds = sortUniqueServerIds(input.serverIds);
  const optionalServerIds = sortUniqueServerIds(input.optionalServerIds);
  return {
    schemaVersion: HOST_CONFIG_SCHEMA_VERSION_V2,
    hostStyle: input.hostStyle,
    modelId: input.modelId,
    systemPrompt: input.systemPrompt,
    temperature: input.temperature,
    requireToolApproval: input.requireToolApproval,
    // Preserve undefined-vs-set: absent hashes byte-identically to a
    // pre-feature row; explicit `false` writes a key and hashes distinctly.
    progressiveToolDiscovery: input.progressiveToolDiscovery,
    respectToolVisibility: input.respectToolVisibility,
    // Normalize undefined → [] and dedupe before sort so canonical/hash output
    // is identical for semantically equivalent server lists.
    serverIds,
    optionalServerIds,
    connectionDefaults: {
      headers: sortStringKeys(input.connectionDefaults.headers),
      requestTimeout: input.connectionDefaults.requestTimeout
    },
    // Deep-sort: nested key order shouldn't leak into the hash. Shallow
    // sort would let `{ extensions: { ui: { a, b } } }` and the same with
    // `{ b, a }` produce distinct hashes for identical capabilities.
    // Fail-fast on missing: HostConfigInputV2 requires both fields; a
    // `?? {}` fallback hides write-path bugs that would silently dedupe
    // distinct callers' configs into a stray empty-capability row.
    clientCapabilities: requireRecord(input.clientCapabilities, "clientCapabilities"),
    hostContext: requireRecord(input.hostContext, "hostContext"),
    // Preserve undefined (omitted → dedupes with preset) vs {} (explicit empty
    // → hashes distinctly).
    hostCapabilitiesOverride: input.hostCapabilitiesOverride === void 0 ? void 0 : deepSortStringKeys(input.hostCapabilitiesOverride),
    chatUiOverride: input.chatUiOverride === void 0 ? void 0 : deepSortStringKeys(input.chatUiOverride),
    mcpProfile: canonicalizeMcpProfile(input.mcpProfile),
    serverConnectionOverrides: canonicalizeServerConnectionOverrides(
      serverIds,
      optionalServerIds,
      input.serverConnectionOverrides
    )
  };
}

// src/host-config/hash.ts
function toHex(buffer) {
  const bytes = new Uint8Array(buffer);
  let hex = "";
  for (let i = 0; i < bytes.length; i++) {
    hex += bytes[i].toString(16).padStart(2, "0");
  }
  return hex;
}
async function sha256Hex(input) {
  const encoder = new TextEncoder();
  const data = encoder.encode(input);
  const digest = await crypto.subtle.digest("SHA-256", data);
  return toHex(digest);
}
async function computeHostConfigHashV2(input) {
  return sha256Hex(JSON.stringify(canonicalizeHostConfigV2(input)));
}

// src/host-config/defaults.ts
var DEFAULT_TEMPERATURE_V2 = 0.7;
function resolveEffectiveMcpProtocolVersion(serverOverride, hostDefault) {
  return serverOverride ?? hostDefault;
}

// src/host-config/app-only-tool.ts
function isAppOnlyTool(toolMeta) {
  if (!toolMeta) return false;
  const visibility = toolMeta.ui?.visibility;
  if (!Array.isArray(visibility)) return false;
  return visibility.length === 1 && visibility[0] === "app";
}

// src/host-config/tool-visibility.ts
function filterAppOnlyTools(tools, source) {
  const metaByServer = /* @__PURE__ */ new Map();
  const getMeta = (serverId) => {
    let cached = metaByServer.get(serverId);
    if (!cached) {
      cached = source.getAllToolsMetadata(serverId);
      metaByServer.set(serverId, cached);
    }
    return cached;
  };
  for (const [name, tool] of Object.entries(tools)) {
    const serverId = tool._serverId;
    if (typeof serverId !== "string") continue;
    const meta = getMeta(serverId)[name];
    if (isAppOnlyTool(meta)) {
      delete tools[name];
    }
  }
}
function applyVisibilityPolicyAndCountSignals(tools, source, policy) {
  const toolsTotalBefore = Object.keys(tools).length;
  if (policy.respectToolVisibility !== false) {
    filterAppOnlyTools(tools, source);
  }
  const toolsExposed = Object.keys(tools).length;
  return {
    toolsTotalBefore,
    toolsExposed,
    toolsDroppedVisibility: toolsTotalBefore - toolsExposed
  };
}

// src/host-config/host-policy.ts
function isRecord(value) {
  return value !== null && typeof value === "object" && !Array.isArray(value);
}
function readHostStyle(hostConfig) {
  if (typeof hostConfig.hostStyle === "string") return hostConfig.hostStyle;
  if (typeof hostConfig.style === "string") return hostConfig.style;
  return void 0;
}
function extractHostExecutionPolicy(hostConfig, namedHostId) {
  if (!hostConfig) {
    return {
      requireToolApproval: false,
      respectToolVisibility: void 0,
      progressiveDiscoveryEnabled: false,
      hostStyle: void 0,
      namedHostId
    };
  }
  const requireToolApproval = typeof hostConfig.requireToolApproval === "boolean" ? hostConfig.requireToolApproval : false;
  const respectToolVisibility = typeof hostConfig.respectToolVisibility === "boolean" ? hostConfig.respectToolVisibility : void 0;
  const discoveryRaw = hostConfig.progressiveToolDiscovery;
  const progressiveDiscoveryEnabled = typeof discoveryRaw === "boolean" ? discoveryRaw : isRecord(discoveryRaw) && discoveryRaw.enabled === true;
  const hostStyle = readHostStyle(hostConfig);
  return {
    requireToolApproval,
    respectToolVisibility,
    progressiveDiscoveryEnabled,
    hostStyle,
    namedHostId
  };
}
function buildHostSnapshotMetadata(hostConfig) {
  const policy = extractHostExecutionPolicy(hostConfig);
  const meta = {};
  if (policy.progressiveDiscoveryEnabled) {
    meta.progressive_discovery_enabled = true;
  }
  if (policy.namedHostId) {
    meta.host_id = policy.namedHostId;
  }
  if (policy.hostStyle) {
    meta.host_style = policy.hostStyle;
  }
  return meta;
}
function buildHostIterationMetadata(policy, signals, approvalsWouldRequire, injectOpenAiCompat) {
  const meta = {
    tools_total_before: signals.toolsTotalBefore,
    tools_exposed: signals.toolsExposed
  };
  if (signals.toolsDroppedVisibility > 0) {
    meta.tools_dropped_visibility = signals.toolsDroppedVisibility;
  }
  if (policy.requireToolApproval && approvalsWouldRequire > 0) {
    meta.approvals_would_require = approvalsWouldRequire;
  }
  if (policy.progressiveDiscoveryEnabled) {
    meta.progressive_discovery_enabled = true;
  }
  if (injectOpenAiCompat) {
    meta.openai_compat_injected = true;
  }
  if (policy.namedHostId) {
    meta.host_id = policy.namedHostId;
  }
  if (policy.hostStyle) {
    meta.host_style = policy.hostStyle;
  }
  return meta;
}

// src/host-config/compat-runtime.ts
function isRecord2(value) {
  return value !== null && typeof value === "object" && !Array.isArray(value);
}
function readHostStyle2(value) {
  if (!isRecord2(value)) return void 0;
  return value.hostStyle ?? value.style;
}
function readMcpProfileOrMcp(value) {
  if (!isRecord2(value)) return void 0;
  if (isRecord2(value.mcpProfile)) return value.mcpProfile;
  if (isRecord2(value.mcp)) return value.mcp;
  return void 0;
}
function readOpenAiCompatOverride(value) {
  const profile = readMcpProfileOrMcp(value);
  const apps = isRecord2(profile?.apps) ? profile.apps : void 0;
  const compatRuntime = isRecord2(apps?.compatRuntime) ? apps.compatRuntime : void 0;
  return typeof compatRuntime?.openaiApps === "boolean" ? compatRuntime.openaiApps : void 0;
}
function compatPresetForHostStyle(hostStyle) {
  switch (hostStyle) {
    case "chatgpt":
    case "copilot":
    case "mcpjam":
      return true;
    case "claude":
    case "cursor":
    case "codex":
      return false;
    default:
      return void 0;
  }
}
function resolveOpenAiCompatForHostConfig(hostConfig, hostConfigOverride) {
  const explicitOverride = readOpenAiCompatOverride(hostConfigOverride);
  if (explicitOverride !== void 0) return explicitOverride;
  const overridePreset = compatPresetForHostStyle(
    readHostStyle2(hostConfigOverride)
  );
  if (overridePreset !== void 0) return overridePreset;
  const explicitBase = readOpenAiCompatOverride(hostConfig);
  if (explicitBase !== void 0) return explicitBase;
  return compatPresetForHostStyle(readHostStyle2(hostConfig)) ?? false;
}

// src/host-config/sdk-evals-normalizer.ts
function isHostConfigInputShape(value) {
  if (!value || typeof value !== "object") return false;
  return typeof value.hostStyle === "string";
}
function isHostJsonShape(value) {
  if (!value || typeof value !== "object") return false;
  const v = value;
  return typeof v.style === "string" && typeof v.hostStyle !== "string";
}
function hostMcpToProfile(mcp) {
  const profile = { profileVersion: 1 };
  if (mcp.protocolVersion !== void 0) {
    profile.mcpProtocolVersion = mcp.protocolVersion;
  }
  if (mcp.initialize !== void 0) profile.initialize = mcp.initialize;
  if (mcp.apps !== void 0) profile.apps = mcp.apps;
  if (mcp.extensions !== void 0) profile.extensions = mcp.extensions;
  return profile;
}
function hostJsonToStrippedInput(json) {
  const input = {
    hostStyle: json.style,
    modelId: json.model,
    systemPrompt: json.systemPrompt,
    temperature: json.temperature,
    requireToolApproval: json.requireToolApproval,
    connectionDefaults: json.connectionDefaults,
    clientCapabilities: json.clientCapabilities,
    hostContext: json.hostContext
  };
  if (json.progressiveToolDiscovery !== void 0) {
    input.progressiveToolDiscovery = json.progressiveToolDiscovery;
  }
  if (json.respectToolVisibility !== void 0) {
    input.respectToolVisibility = json.respectToolVisibility;
  }
  if (json.hostCapabilitiesOverride !== void 0) {
    input.hostCapabilitiesOverride = json.hostCapabilitiesOverride;
  }
  if (json.chatUiOverride !== void 0) {
    input.chatUiOverride = json.chatUiOverride;
  }
  if (json.mcp !== void 0) {
    input.mcpProfile = hostMcpToProfile(json.mcp);
  }
  return input;
}
function stripRuntimeIdsFromCanonical(input) {
  const {
    // Intentionally destructured out so the rest spread drops them.
    serverIds: _serverIds,
    optionalServerIds: _optionalServerIds,
    serverConnectionOverrides: _serverConnectionOverrides,
    ...rest
  } = input;
  return { ...rest };
}
function normalizeSdkEvalHostConfigForWire(source) {
  if (isHostConfigInputShape(source)) {
    return stripRuntimeIdsFromCanonical(source);
  }
  if (isHostJsonShape(source)) {
    return hostJsonToStrippedInput(source);
  }
  const minimal = source;
  return stripRuntimeIdsFromCanonical(minimal);
}

export { DEFAULT_TEMPERATURE_V2, HOST_CONFIG_SCHEMA_VERSION_V2, SEP_1865_PERMISSION_FEATURES, applyVisibilityPolicyAndCountSignals, buildHostIterationMetadata, buildHostSnapshotMetadata, canonicalizeHostConfigV2, compatPresetForHostStyle, computeHostConfigHashV2, extractHostExecutionPolicy, filterAppOnlyTools, isAppOnlyTool, normalizeSdkEvalHostConfigForWire, readOpenAiCompatOverride, resolveEffectiveMcpProtocolVersion, resolveOpenAiCompatForHostConfig, sha256Hex };
//# sourceMappingURL=internal.js.map
//# sourceMappingURL=internal.js.map