import { llmProviderRegistry } from "@open-mercato/shared/lib/ai/llm-provider-registry";
import {
  applyAgentOverrideMap,
  composeAgentExtensionEntries,
  composeAgentOverrideMap
} from "./ai-overrides.js";
import { TASK_PLAN_TOOL_NAME } from "./task-plan-labels.js";
const agentsById = /* @__PURE__ */ new Map();
let loaded = false;
function isStringArray(value) {
  return Array.isArray(value) && value.every((item) => typeof item === "string");
}
function isAiAgentSuggestion(value) {
  if (!value || typeof value !== "object") return false;
  const candidate = value;
  return typeof candidate.label === "string" && typeof candidate.prompt === "string";
}
function isAiAgentExtension(value) {
  if (!value || typeof value !== "object") return false;
  const candidate = value;
  return typeof candidate.targetAgentId === "string" && (!("replaceAllowedTools" in candidate) || isStringArray(candidate.replaceAllowedTools)) && (!("deleteAllowedTools" in candidate) || isStringArray(candidate.deleteAllowedTools)) && (!("appendAllowedTools" in candidate) || isStringArray(candidate.appendAllowedTools)) && (!("taskPlan" in candidate) || candidate.taskPlan != null && typeof candidate.taskPlan === "object" && (!("enabled" in candidate.taskPlan) || typeof candidate.taskPlan.enabled === "boolean")) && (!("replaceSystemPrompt" in candidate) || typeof candidate.replaceSystemPrompt === "string") && (!("appendSystemPrompt" in candidate) || typeof candidate.appendSystemPrompt === "string") && (!("replaceSuggestions" in candidate) || Array.isArray(candidate.replaceSuggestions) && candidate.replaceSuggestions.every(isAiAgentSuggestion)) && (!("deleteSuggestions" in candidate) || isStringArray(candidate.deleteSuggestions)) && (!("appendSuggestions" in candidate) || Array.isArray(candidate.appendSuggestions) && candidate.appendSuggestions.every(isAiAgentSuggestion)) && (!("suggestions" in candidate) || Array.isArray(candidate.suggestions) && candidate.suggestions.every(isAiAgentSuggestion));
}
function isAiAgentDefinition(value) {
  if (!value || typeof value !== "object") return false;
  const candidate = value;
  return typeof candidate.id === "string" && typeof candidate.moduleId === "string" && typeof candidate.label === "string" && typeof candidate.description === "string" && typeof candidate.systemPrompt === "string" && isStringArray(candidate.allowedTools);
}
function uniqueStrings(values) {
  return Array.from(new Set(values.filter((value) => typeof value === "string" && value.length > 0)));
}
function isAgentTaskPlanEnabled(agent) {
  return agent.taskPlan?.enabled === true;
}
function normalizeTaskPlanTool(agent) {
  const enabled = isAgentTaskPlanEnabled(agent);
  const withoutInternalTool = agent.allowedTools.filter((toolName) => toolName !== TASK_PLAN_TOOL_NAME);
  const allowedTools = enabled ? uniqueStrings([...withoutInternalTool, TASK_PLAN_TOOL_NAME]) : uniqueStrings(withoutInternalTool);
  if (allowedTools.length === agent.allowedTools.length && allowedTools.every((toolName, index) => toolName === agent.allowedTools[index])) {
    return agent;
  }
  return {
    ...agent,
    allowedTools
  };
}
function applyStringListPatch(current, patch) {
  const deleted = new Set(patch.delete ?? []);
  return uniqueStrings([
    ...(patch.replace ?? current).filter((value) => !deleted.has(value)),
    ...patch.append ?? []
  ]);
}
function suggestionDeleteKey(suggestion) {
  return [suggestion.label, suggestion.prompt].filter((value) => value.length > 0);
}
function applySuggestionPatch(current, patch) {
  const deleted = new Set(patch.delete ?? []);
  const base = patch.replace ?? current;
  const out = [];
  const seen = /* @__PURE__ */ new Set();
  for (const suggestion of base) {
    if (suggestionDeleteKey(suggestion).some((key2) => deleted.has(key2))) continue;
    const key = `${suggestion.label}
${suggestion.prompt}`;
    if (seen.has(key)) continue;
    seen.add(key);
    out.push(suggestion);
  }
  for (const suggestion of patch.append ?? []) {
    const key = `${suggestion.label}
${suggestion.prompt}`;
    if (seen.has(key)) continue;
    seen.add(key);
    out.push(suggestion);
  }
  return out;
}
function validateAndNormalizeAgent(candidate) {
  const taskPlanNormalized = normalizeTaskPlanTool(candidate);
  const rawProvider = candidate.defaultProvider;
  if (typeof rawProvider !== "string" || rawProvider.trim().length === 0) {
    return taskPlanNormalized;
  }
  const providerHint = rawProvider.trim();
  const registered = llmProviderRegistry.get(providerHint);
  if (!registered) {
    console.warn(
      `[AI Agents] Agent "${candidate.id}" declares defaultProvider "${providerHint}" which is not registered in llmProviderRegistry. The agent will be registered with defaultProvider: undefined so the resolution chain still works. Built-in provider ids: anthropic, google, openai, deepinfra, groq, together, fireworks, azure, litellm, ollama.`
    );
    return { ...taskPlanNormalized, defaultProvider: void 0 };
  }
  return taskPlanNormalized;
}
function populateFromAgents(agents) {
  for (const candidate of agents) {
    if (!isAiAgentDefinition(candidate)) {
      console.warn("[AI Agents] Skipping malformed agent entry in ai-agents.generated.ts");
      continue;
    }
    const existing = agentsById.get(candidate.id);
    if (existing) {
      throw new Error(
        `[AI Agents] Duplicate agent id "${candidate.id}" \u2014 already registered by module "${existing.moduleId}", conflicts with module "${candidate.moduleId}". Export \`aiAgentOverrides\` from your module's \`ai-agents.ts\` (or set it on the modules.ts entry) to replace an agent across modules.`
      );
    }
    agentsById.set(candidate.id, validateAndNormalizeAgent(candidate));
  }
}
async function loadOverrideEntries() {
  try {
    const mod = await import("@/.mercato/generated/ai-agents.generated");
    return Array.isArray(mod.aiAgentOverrideEntries) ? mod.aiAgentOverrideEntries : [];
  } catch {
    return [];
  }
}
function applyOverridesToRegistry(entries) {
  const overrideMap = composeAgentOverrideMap(entries);
  if (Object.keys(overrideMap).length === 0) return;
  const overridden = applyAgentOverrideMap(Array.from(agentsById.values()), overrideMap);
  agentsById.clear();
  for (const agent of overridden) agentsById.set(agent.id, agent);
  for (const [id, value] of Object.entries(overrideMap)) {
    const verb = value === null ? "disabled" : "replaced";
    console.info(`[AI Overrides] Agent "${id}" ${verb} by override.`);
  }
}
async function loadExtensionEntries() {
  try {
    const mod = await import("@/.mercato/generated/ai-agents.generated");
    const entries = Array.isArray(mod.aiAgentExtensionEntries) ? mod.aiAgentExtensionEntries : [];
    return composeAgentExtensionEntries(entries).filter(isAiAgentExtension);
  } catch {
    return [];
  }
}
function applyExtensionsToRegistry(extensions) {
  if (extensions.length === 0) return;
  for (const extension of extensions) {
    const agent = agentsById.get(extension.targetAgentId);
    if (!agent) {
      console.warn(
        `[AI Agents] Skipping extension for unknown agent "${extension.targetAgentId}".`
      );
      continue;
    }
    const replacementSystemPrompt = extension.replaceSystemPrompt?.trim();
    const appendSystemPrompt = extension.appendSystemPrompt?.trim();
    const systemPrompt = replacementSystemPrompt ?? agent.systemPrompt.trim();
    const patchedAgent = {
      ...agent,
      allowedTools: applyStringListPatch(agent.allowedTools, {
        replace: extension.replaceAllowedTools,
        delete: extension.deleteAllowedTools,
        append: extension.appendAllowedTools
      }),
      taskPlan: extension.taskPlan !== void 0 ? extension.taskPlan : agent.taskPlan,
      systemPrompt: appendSystemPrompt ? `${systemPrompt}

${appendSystemPrompt}` : systemPrompt,
      suggestions: applySuggestionPatch(agent.suggestions ?? [], {
        replace: extension.replaceSuggestions,
        delete: extension.deleteSuggestions,
        append: [
          ...extension.appendSuggestions ?? [],
          ...extension.suggestions ?? []
        ]
      })
    };
    agentsById.set(agent.id, validateAndNormalizeAgent(patchedAgent));
  }
}
async function loadAgentRegistry() {
  if (loaded) return;
  try {
    const mod = await import("@/.mercato/generated/ai-agents.generated");
    const agents = Array.isArray(mod.allAiAgents) ? mod.allAiAgents : [];
    populateFromAgents(agents);
  } catch (error) {
    console.error(
      "[AI Agents] Could not load ai-agents.generated.ts (agent registry empty):",
      error
    );
  } finally {
    try {
      const overrideEntries = await loadOverrideEntries();
      applyOverridesToRegistry(overrideEntries);
      const extensionEntries = await loadExtensionEntries();
      applyExtensionsToRegistry(extensionEntries);
    } catch (error) {
      console.error("[AI Agents] Failed to apply agent overrides/extensions:", error);
    }
    loaded = true;
  }
}
function getAgent(id) {
  return agentsById.get(id);
}
function listAgents() {
  return Array.from(agentsById.values()).sort((a, b) => a.id.localeCompare(b.id));
}
function listAgentsByModule(moduleId) {
  return listAgents().filter((agent) => agent.moduleId === moduleId);
}
function resetAgentRegistryForTests() {
  agentsById.clear();
  loaded = false;
}
function seedAgentRegistryForTests(agents) {
  agentsById.clear();
  populateFromAgents(agents);
  loaded = true;
}
function applyAgentOverrideEntriesForTests(entries) {
  applyOverridesToRegistry(entries);
}
function applyAgentExtensionEntriesForTests(entries) {
  applyExtensionsToRegistry(entries);
}
export {
  applyAgentExtensionEntriesForTests,
  applyAgentOverrideEntriesForTests,
  getAgent,
  isAgentTaskPlanEnabled,
  listAgents,
  listAgentsByModule,
  loadAgentRegistry,
  resetAgentRegistryForTests,
  seedAgentRegistryForTests
};
//# sourceMappingURL=agent-registry.js.map
