import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { existsSync, readFileSync } from "fs";
import { join } from "path";
import { homedir } from "os";
import { writeFileSecure, ensureSecureDir } from "../../hooks/secure-fs.js";
import {
  ModelRouterConfigSchema,
  parseConfigSafe
} from "../../hooks/schemas.js";
const CONFIG_PATH = join(homedir(), ".stackmemory", "model-router.json");
const DEFAULT_CONFIG = {
  enabled: false,
  defaultProvider: "anthropic",
  taskRouting: {},
  fallback: {
    enabled: true,
    // Fallback enabled by default
    provider: "qwen",
    onRateLimit: true,
    onError: true,
    onTimeout: true,
    maxRetries: 2,
    retryDelayMs: 1e3
  },
  providers: {
    anthropic: {
      provider: "anthropic",
      model: "claude-sonnet-4-20250514",
      apiKeyEnv: "ANTHROPIC_API_KEY"
    },
    qwen: {
      provider: "qwen",
      model: "qwen3-max-2025-01-23",
      baseUrl: "https://dashscope.aliyuncs.com/compatible-mode/v1",
      apiKeyEnv: "DASHSCOPE_API_KEY",
      params: {
        enable_thinking: true,
        thinking_budget: 1e4
      }
    }
  },
  thinkingMode: {
    enabled: true,
    budget: 1e4,
    temperature: 0.6,
    topP: 0.95
  }
};
function loadModelRouterConfig() {
  try {
    if (existsSync(CONFIG_PATH)) {
      const data = JSON.parse(readFileSync(CONFIG_PATH, "utf8"));
      return parseConfigSafe(
        ModelRouterConfigSchema,
        { ...DEFAULT_CONFIG, ...data },
        DEFAULT_CONFIG,
        "model-router"
      );
    }
  } catch {
  }
  return { ...DEFAULT_CONFIG };
}
function saveModelRouterConfig(config) {
  try {
    ensureSecureDir(join(homedir(), ".stackmemory"));
    writeFileSecure(CONFIG_PATH, JSON.stringify(config, null, 2));
  } catch {
  }
}
function getModelForTask(taskType) {
  const config = loadModelRouterConfig();
  if (!config.enabled) {
    return null;
  }
  const routedProvider = config.taskRouting[taskType];
  const provider = routedProvider || config.defaultProvider;
  return config.providers[provider] || null;
}
function buildModelEnv(modelConfig) {
  const env = {};
  const apiKey = process.env[modelConfig.apiKeyEnv];
  if (!apiKey) {
    console.warn(`[model-router] API key not found: ${modelConfig.apiKeyEnv}`);
    return env;
  }
  env["ANTHROPIC_MODEL"] = modelConfig.model;
  env["ANTHROPIC_SMALL_FAST_MODEL"] = modelConfig.model;
  env["ANTHROPIC_AUTH_TOKEN"] = apiKey;
  if (modelConfig.baseUrl) {
    env["ANTHROPIC_BASE_URL"] = modelConfig.baseUrl;
  }
  return env;
}
function isPlanningContext(input) {
  const planPatterns = [
    /\bplan\b/i,
    /\barchitect/i,
    /\bdesign\b/i,
    /\bstrateg/i,
    /\bimplement.*approach/i,
    /\bhow.*should.*we/i,
    /\bthink.*through/i,
    /\breason.*about/i,
    /\banalyze.*options/i,
    /\btrade-?offs?/i
  ];
  return planPatterns.some((pattern) => pattern.test(input));
}
function requiresDeepThinking(input) {
  const thinkPatterns = [
    /\bcomplex/i,
    /\bdifficult/i,
    /\btricky/i,
    /\bcareful/i,
    /\bstep.*by.*step/i,
    /\bthink.*hard/i,
    /\bultrathink/i,
    /\b--think/i,
    /\b--think-hard/i
  ];
  return thinkPatterns.some((pattern) => pattern.test(input));
}
class ModelRouter {
  config;
  currentProvider;
  inFallbackMode = false;
  fallbackReason;
  constructor() {
    this.config = loadModelRouterConfig();
    this.currentProvider = this.config.defaultProvider;
  }
  /**
   * Route a task to the appropriate model
   */
  route(taskType, input) {
    if (!this.config.enabled) {
      return { provider: "anthropic", env: {}, switched: false };
    }
    let detectedType = taskType;
    if (input && taskType === "default") {
      if (isPlanningContext(input)) {
        detectedType = "plan";
      } else if (requiresDeepThinking(input)) {
        detectedType = "think";
      }
    }
    const modelConfig = getModelForTask(detectedType);
    if (!modelConfig) {
      return { provider: "anthropic", env: {}, switched: false };
    }
    const switched = modelConfig.provider !== this.currentProvider;
    this.currentProvider = modelConfig.provider;
    return {
      provider: modelConfig.provider,
      env: buildModelEnv(modelConfig),
      switched
    };
  }
  /**
   * Get current provider
   */
  getCurrentProvider() {
    return this.currentProvider;
  }
  /**
   * Force switch to a specific provider
   */
  switchTo(provider) {
    const modelConfig = this.config.providers[provider];
    if (!modelConfig) {
      console.warn(`[model-router] Provider not configured: ${provider}`);
      return {};
    }
    this.currentProvider = provider;
    return buildModelEnv(modelConfig);
  }
  /**
   * Reset to default provider
   */
  reset() {
    this.currentProvider = this.config.defaultProvider;
    this.inFallbackMode = false;
    this.fallbackReason = void 0;
  }
  /**
   * Check if fallback is enabled and configured
   */
  isFallbackEnabled() {
    if (!this.config.fallback?.enabled) return false;
    const fallbackProvider = this.config.providers[this.config.fallback.provider];
    if (!fallbackProvider) return false;
    const apiKey = process.env[fallbackProvider.apiKeyEnv];
    return !!apiKey;
  }
  /**
   * Check if error should trigger fallback
   */
  shouldFallback(error) {
    if (!this.isFallbackEnabled()) return false;
    if (this.inFallbackMode) return false;
    const fallback = this.config.fallback;
    if (fallback.onRateLimit && error.status === 429) {
      return true;
    }
    if (fallback.onError && error.status && error.status >= 500) {
      return true;
    }
    if (fallback.onTimeout) {
      const isTimeout = error.code === "ETIMEDOUT" || error.code === "ESOCKETTIMEDOUT" || error.message?.toLowerCase().includes("timeout");
      if (isTimeout) return true;
    }
    if (error.message?.toLowerCase().includes("overloaded")) {
      return true;
    }
    return false;
  }
  /**
   * Activate fallback mode
   */
  activateFallback(reason) {
    if (!this.isFallbackEnabled()) {
      console.warn("[model-router] Fallback not available");
      return {};
    }
    const fallbackProvider = this.config.fallback.provider;
    const modelConfig = this.config.providers[fallbackProvider];
    if (!modelConfig) {
      console.warn(
        `[model-router] Fallback provider not configured: ${fallbackProvider}`
      );
      return {};
    }
    this.inFallbackMode = true;
    this.fallbackReason = reason;
    this.currentProvider = fallbackProvider;
    console.log(
      `[model-router] Fallback activated: ${reason} -> ${fallbackProvider}`
    );
    return buildModelEnv(modelConfig);
  }
  /**
   * Get fallback configuration
   */
  getFallbackConfig() {
    return this.config.fallback;
  }
  /**
   * Check if currently in fallback mode
   */
  isInFallbackMode() {
    return this.inFallbackMode;
  }
  /**
   * Get reason for fallback
   */
  getFallbackReason() {
    return this.fallbackReason;
  }
  /**
   * Get fallback environment variables (for pre-configuring)
   */
  getFallbackEnv() {
    if (!this.isFallbackEnabled()) return {};
    const fallbackProvider = this.config.fallback.provider;
    const modelConfig = this.config.providers[fallbackProvider];
    if (!modelConfig) return {};
    return buildModelEnv(modelConfig);
  }
}
let routerInstance = null;
function getModelRouter() {
  if (!routerInstance) {
    routerInstance = new ModelRouter();
  }
  return routerInstance;
}
function getPlanModeEnv() {
  const router = getModelRouter();
  const result = router.route("plan");
  return result.env;
}
function getThinkingModeEnv() {
  const router = getModelRouter();
  const result = router.route("think");
  return result.env;
}
function isFallbackAvailable() {
  const router = getModelRouter();
  return router.isFallbackEnabled();
}
function getFallbackStatus() {
  const router = getModelRouter();
  const config = loadModelRouterConfig();
  if (!config.fallback?.enabled) {
    return {
      enabled: false,
      provider: null,
      hasApiKey: false,
      inFallback: false
    };
  }
  const fallbackProvider = config.providers[config.fallback.provider];
  const hasApiKey = fallbackProvider ? !!process.env[fallbackProvider.apiKeyEnv] : false;
  return {
    enabled: true,
    provider: config.fallback.provider,
    hasApiKey,
    inFallback: router.isInFallbackMode(),
    reason: router.getFallbackReason()
  };
}
function triggerFallback(reason = "manual") {
  const router = getModelRouter();
  return router.activateFallback(reason);
}
function resetFallback() {
  const router = getModelRouter();
  router.reset();
}
export {
  ModelRouter,
  buildModelEnv,
  getFallbackStatus,
  getModelForTask,
  getModelRouter,
  getPlanModeEnv,
  getThinkingModeEnv,
  isFallbackAvailable,
  isPlanningContext,
  loadModelRouterConfig,
  requiresDeepThinking,
  resetFallback,
  saveModelRouterConfig,
  triggerFallback
};
//# sourceMappingURL=model-router.js.map
