// src/harness/index.ts
var KNOWN_HARNESSES = [
  "opencode",
  "claude-code",
  "kimi-code",
  "codex",
  "amp",
  "factory-droids",
  "pi",
  "hermes",
  "forge",
  "openclaw",
  "acp",
  "cursor",
  "cli-base"
];
var DEFAULT_HARNESS = "opencode";
var HARNESS_SET = new Set(KNOWN_HARNESSES);
function isHarness(value) {
  return typeof value === "string" && HARNESS_SET.has(value);
}
function coerceHarness(value, fallback = DEFAULT_HARNESS) {
  return isHarness(value) ? value : fallback;
}
function resolveSessionHarness(input = {}) {
  const fallback = input.fallback ?? DEFAULT_HARNESS;
  if (isHarness(input.sessionHarness)) {
    const locked = input.sessionHarness;
    const swapAttempted = isHarness(input.requested) && input.requested !== locked;
    return { harness: locked, locked: true, swapAttempted };
  }
  const harness = coerceHarness(input.requested, coerceHarness(input.workspaceDefault, fallback));
  return { harness, locked: false, swapAttempted: false };
}
var HARNESS_MODEL_POLICIES = {
  "claude-code": {
    providers: ["anthropic"],
    preferred: [/^anthropic\/claude-opus-[\d.-]+$/, /^anthropic\/claude-sonnet-[\d.-]+$/, /^anthropic\//]
  },
  codex: {
    providers: ["openai"],
    preferred: [/^openai\/gpt-\d+(\.\d+)?$/, /^openai\/gpt/, /^openai\//]
  },
  "kimi-code": { providers: ["moonshot"], preferred: [/^moonshot\//] }
};
var PROVIDER_PREFERRED_HARNESS = {
  anthropic: "claude-code",
  openai: "codex",
  moonshot: "kimi-code"
};
function modelProvider(modelId) {
  const slash = modelId.indexOf("/");
  return slash > 0 ? modelId.slice(0, slash) : null;
}
function isModelCompatibleWithHarness(harness, modelId) {
  const policy = HARNESS_MODEL_POLICIES[harness];
  if (!policy || policy.providers === null) return true;
  const provider = modelProvider(modelId);
  if (!provider) return true;
  return policy.providers.includes(provider);
}
var numericDesc = new Intl.Collator(void 0, { numeric: true, sensitivity: "base" });
function snapModelToHarness(harness, modelId, canonicalIds) {
  if (isModelCompatibleWithHarness(harness, modelId)) return modelId;
  const policy = HARNESS_MODEL_POLICIES[harness];
  if (!policy) return modelId;
  for (const pattern of policy.preferred) {
    const matches = canonicalIds.filter((id) => pattern.test(id)).sort((a, b) => numericDesc.compare(b, a));
    if (matches.length > 0) return matches[0];
  }
  return canonicalIds.find((id) => isModelCompatibleWithHarness(harness, id)) ?? modelId;
}
function snapHarnessToModel(harness, modelId) {
  if (isModelCompatibleWithHarness(harness, modelId)) return harness;
  const provider = modelProvider(modelId);
  return provider && PROVIDER_PREFERRED_HARNESS[provider] || "opencode";
}
function assertHarnessModelCompatible(harness, modelId) {
  if (!isModelCompatibleWithHarness(harness, modelId)) {
    const provider = modelProvider(modelId);
    throw new Error(
      `Harness "${harness}" cannot run model "${modelId}" (provider "${provider}"). Use ${PROVIDER_PREFERRED_HARNESS[provider ?? ""] ?? "a router-backed harness (opencode)"} or an allowed model.`
    );
  }
}

export {
  KNOWN_HARNESSES,
  DEFAULT_HARNESS,
  isHarness,
  coerceHarness,
  resolveSessionHarness,
  HARNESS_MODEL_POLICIES,
  PROVIDER_PREFERRED_HARNESS,
  modelProvider,
  isModelCompatibleWithHarness,
  snapModelToHarness,
  snapHarnessToModel,
  assertHarnessModelCompatible
};
//# sourceMappingURL=chunk-5VXPDXZJ.js.map