import { getAgent } from "./agent-registry.js";
import { hasRequiredFeatures } from "./auth.js";
import { toolRegistry } from "./tool-registry.js";
const POLICY_RESTRICTIVENESS = {
  "read-only": 0,
  "destructive-confirm-required": 1,
  "confirm-required": 2
};
function isKnownMutationPolicy(value) {
  return value === "read-only" || value === "confirm-required" || value === "destructive-confirm-required";
}
function resolveEffectiveMutationPolicy(codeDeclared, override, agentId) {
  const base = codeDeclared && isKnownMutationPolicy(codeDeclared) ? codeDeclared : "read-only";
  if (override === void 0 || override === null) return base;
  if (!isKnownMutationPolicy(override)) {
    console.warn(
      `[AI Agents] Ignoring corrupt mutationPolicy override for agent "${agentId ?? "<unknown>"}": ${String(
        override
      )}. Falling back to code-declared policy "${base}".`
    );
    return base;
  }
  const baseRank = POLICY_RESTRICTIVENESS[base];
  const overrideRank = POLICY_RESTRICTIVENESS[override];
  return overrideRank < baseRank ? override : base;
}
function isMutationPolicyEscalation(codeDeclared, candidate) {
  const base = codeDeclared && isKnownMutationPolicy(codeDeclared) ? codeDeclared : "read-only";
  return POLICY_RESTRICTIVENESS[candidate] > POLICY_RESTRICTIVENESS[base];
}
function classifyMediaType(value) {
  const normalized = value.trim().toLowerCase();
  if (normalized.startsWith("image/")) return "image";
  if (normalized === "application/pdf") return "pdf";
  return "file";
}
function isAgentReadOnly(agent) {
  if (typeof agent.readOnly === "boolean") return agent.readOnly;
  return true;
}
function resolvePolicyCheckMutationPolicy(agent, override) {
  return resolveEffectiveMutationPolicy(agent.mutationPolicy, override, agent.id);
}
function hasAgentStructuredOutput(agent) {
  return Boolean(agent.output);
}
function agentExecutionMode(agent) {
  return agent.executionMode ?? "chat";
}
function checkAgentPolicy(input) {
  const {
    agentId,
    authContext,
    toolName,
    attachmentMediaTypes,
    requestedExecutionMode,
    mutationPolicyOverride
  } = input;
  const agent = getAgent(agentId);
  if (!agent) {
    return {
      ok: false,
      code: "agent_unknown",
      message: `Agent "${agentId}" is not registered.`
    };
  }
  const agentFeatures = agent.requiredFeatures ?? [];
  if (!hasRequiredFeatures(agentFeatures, authContext.userFeatures, authContext.isSuperAdmin)) {
    return {
      ok: false,
      code: "agent_features_denied",
      message: `Access to agent "${agentId}" requires features: ${agentFeatures.join(", ")}`
    };
  }
  let resolvedTool;
  if (typeof toolName === "string") {
    if (!agent.allowedTools.includes(toolName)) {
      return {
        ok: false,
        code: "tool_not_whitelisted",
        message: `Tool "${toolName}" is not whitelisted for agent "${agentId}".`
      };
    }
    const toolRecord = toolRegistry.getTool(toolName);
    if (!toolRecord) {
      return {
        ok: false,
        code: "tool_unknown",
        message: `Tool "${toolName}" is not registered in the tool registry.`
      };
    }
    const toolFeatures = toolRecord.requiredFeatures ?? [];
    if (!hasRequiredFeatures(toolFeatures, authContext.userFeatures, authContext.isSuperAdmin)) {
      return {
        ok: false,
        code: "tool_features_denied",
        message: `Access to tool "${toolName}" requires features: ${toolFeatures.join(", ")}`
      };
    }
    if (toolRecord.isMutation === true) {
      if (isAgentReadOnly(agent)) {
        return {
          ok: false,
          code: "mutation_blocked_by_readonly",
          message: `Mutation tool "${toolName}" cannot be executed by read-only agent "${agentId}".`
        };
      }
      const effectivePolicy = resolvePolicyCheckMutationPolicy(agent, mutationPolicyOverride);
      if (effectivePolicy === "read-only") {
        return {
          ok: false,
          code: "mutation_blocked_by_policy",
          message: `Mutation tool "${toolName}" is blocked by agent "${agentId}" mutationPolicy=read-only.`
        };
      }
    }
    resolvedTool = toolRecord;
  }
  if (requestedExecutionMode) {
    const declaredMode = agentExecutionMode(agent);
    if (requestedExecutionMode === "object") {
      if (declaredMode !== "object" && !hasAgentStructuredOutput(agent)) {
        return {
          ok: false,
          code: "execution_mode_not_supported",
          message: `Agent "${agentId}" does not support execution mode "object" (no output schema declared).`
        };
      }
    } else if (requestedExecutionMode === "chat") {
      if (declaredMode === "object" && hasAgentStructuredOutput(agent)) {
        return {
          ok: false,
          code: "execution_mode_not_supported",
          message: `Agent "${agentId}" is declared as object-mode and cannot run via chat transport.`
        };
      }
    }
  }
  if (Array.isArray(attachmentMediaTypes) && attachmentMediaTypes.length > 0) {
    const accepted = agent.acceptedMediaTypes;
    if (!accepted || accepted.length === 0) {
      return {
        ok: false,
        code: "attachment_type_not_accepted",
        message: `Agent "${agentId}" does not accept attachments.`
      };
    }
    const acceptedSet = new Set(accepted);
    for (const raw of attachmentMediaTypes) {
      const kind = classifyMediaType(raw);
      if (!acceptedSet.has(kind)) {
        return {
          ok: false,
          code: "attachment_type_not_accepted",
          message: `Agent "${agentId}" does not accept media type "${raw}" (classified as "${kind}").`
        };
      }
    }
  }
  return { ok: true, agent, tool: resolvedTool };
}
export {
  checkAgentPolicy,
  isKnownMutationPolicy,
  isMutationPolicyEscalation,
  resolveEffectiveMutationPolicy
};
//# sourceMappingURL=agent-policy.js.map
