import type { Plugin, PluginModule, Hooks } from "@kilocode/plugin";
import { fetchModelsFromBridge } from "./bridge";
import { sanitizeRequest } from "./anonymizer";

/**
 * CyberBrain26 FreeAuto — Kilo plugin.
 *
 * Responsibilities:
 * 1. Egress sanitization — strip PII and the synthetic CB26_MARKER_ from the
 *    full outbound payload (message history + system prompt) before it is sent
 *    to the model provider. Idempotent, so it is safe when Kilo invokes the
 *    transform twice (payloads > 1.25 MB).
 * 2. Dynamic model provider (PoC) — exposes free/efficient models from the
 *    CyberBrain26 registry via the provider hook.
 *
 * Known limitations (verified against the Kilo plugin API, 2026-10-04):
 * - A plugin cannot introduce a brand-new provider ID; the provider must
 *   already exist in the models.dev catalog, so registering
 *   "cyberbrain26-freeauto" is a demonstration of the hook, not a guaranteed
 *   registration path.
 * - Response-side sanitization (experimental.text.complete) covers text parts
 *   only and runs post-streaming; it is NOT relied on for security.
 * - The bridge returns a simplified ModelMetadata shape; adapting it to the
 *   SDK ModelV2 type is follow-up work (the cast below is a PoC simplification).
 */
/** Exact return type of ProviderHook.models — Record<string, ModelV2>.
 *  Derived from the Hooks interface so the cast names the real target
 *  type without importing the SDK Model type (not a declared dependency). */
type ProviderModelRecord = Awaited<
  ReturnType<NonNullable<NonNullable<Hooks["provider"]>["models"]>>
>;

const server: Plugin = async () => {
  const hooks: Hooks = {
    provider: {
      id: "cyberbrain26-freeauto",
      models: async () => {
        const models = await fetchModelsFromBridge();
        // Bridge returns Map<model_id, ModelMetadata>; ProviderHook.models
        // expects Record<string, ModelV2>. This is a PoC simplification - casting
        // from ModelMetadata to ModelV2 requires SDK types not available here.
        return Object.fromEntries(models) as unknown as ProviderModelRecord;
      },
    },
    // Egress — full message history, before conversion to provider format.
    "experimental.chat.messages.transform": async (_input, output) => {
      output.messages = sanitizeRequest(output.messages) as typeof output.messages;
    },
    // Egress — system prompt (array of strings).
    "experimental.chat.system.transform": async (_input, output) => {
      output.system = sanitizeRequest(output.system) as typeof output.system;
    },
  };
  return hooks;
};

const plugin: PluginModule = {
  id: "cyberbrain26-freeauto",
  server,
};

export default plugin;
