export interface ProviderDef {
  name: string;
  label: string;
  transport: 'native' | 'acp' | 'pty';
  modelSource: 'llama-swap' | 'static' | 'probe';
  staticModels?: Array<{ id: string; label: string }>;
  /** Merge llama-swap models into probed list (OpenCode). */
  mergeLlamaSwap?: boolean;
}

/**
 * Model discovery rules (see provider-snapshot.ts):
 * - boocode: llama-swap only
 * - opencode: ACP probe + mergeLlamaSwap (prefixed llama-swap/* ids)
 * - qwen: ACP probe + merge ~/.qwen/settings.json; PTY fallback reads settings only
 * - goose: ACP probe only
 * - reasonix: ACP probe only
 * - claude: static manifest models + thinking options
 */
export const PROVIDERS: ProviderDef[] = [
  {
    name: 'boocode',
    label: 'BooCoder',
    transport: 'native',
    modelSource: 'llama-swap',
  },
  {
    name: 'opencode',
    label: 'OpenCode',
    transport: 'acp',
    modelSource: 'probe',
    mergeLlamaSwap: true,
  },
  {
    name: 'goose',
    label: 'Goose',
    transport: 'acp',
    modelSource: 'probe',
  },
  {
    name: 'reasonix',
    label: 'Reasonix',
    transport: 'acp',
    modelSource: 'probe',
  },
  {
    name: 'claude',
    // transport stays 'pty' — the DEFAULT dispatch path (one-shot `claude
    // --output-format stream-json`). claude-sdk-sessionstore #9 (Part 2) adds a warm
    // Claude-Agent-SDK backend (services/backends/claude-sdk.ts) routed ONLY when the
    // `CLAUDE_SDK_BACKEND` env flag is truthy AND the task is a chat tab; with the flag
    // off (production default) claude always uses this PTY path, so the transport label
    // is left unchanged. Flip the env var on a host (after a live smoke) to opt in.
    label: 'Claude Code',
    transport: 'pty',
    modelSource: 'static',
    // Passed verbatim to `claude --model <id>` (PTY dispatch). Pinned full
    // names; the `[1m]` suffix selects the 1M-context variant of that model
    // (e.g. `claude --model claude-opus-4-8[1m]`). First entry is the default
    // (the snapshot carries no isDefault, so the frontend falls back to
    // models[0]). Extend/replace per-install via data/coder-providers.json
    // (models / additionalModels) without a code change.
    staticModels: [
      { id: 'claude-opus-4-8[1m]', label: 'Opus 4.8 1M' },
      { id: 'claude-opus-4-8', label: 'Opus 4.8' },
      { id: 'claude-sonnet-4-6[1m]', label: 'Sonnet 4.6 1M' },
      { id: 'claude-sonnet-4-6', label: 'Sonnet 4.6' },
      { id: 'claude-haiku-4-5-20251001[1m]', label: 'Haiku 4.5 1M' },
      { id: 'claude-haiku-4-5-20251001', label: 'Haiku 4.5' },
    ],
  },
  {
    name: 'qwen',
    label: 'Qwen Code',
    transport: 'acp',
    modelSource: 'probe',
  },
];

export const PROVIDERS_BY_NAME = new Map(PROVIDERS.map((p) => [p.name, p]));

/** External agents probed on host (excludes native boocode). */
export const PROBED_AGENT_NAMES = PROVIDERS.filter((p) => p.name !== 'boocode').map((p) => p.name);
