File size: 2,651 Bytes
064bfd6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38d7632
064bfd6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import type { ModelOption } from './modelOptions.js'

let openRouterModelsCache: ModelOption[] | null = null
let cacheTimestamp: number = 0
let isFetching = false
const CACHE_DURATION = 5 * 60 * 1000 // 5 minutes

export interface OpenRouterModel {
  id: string
  name: string
  description: string
  context_length: number
  pricing: {
    prompt: string
    completion: string
  }
}

function formatPrice(price: string): string {
  const numPrice = parseFloat(price)
  if (numPrice === 0) return 'Free'
  if (numPrice < 0.000001) return '$<0.000001'
  return `$${price}`
}

export async function fetchOpenRouterModels(
  apiKey?: string,
): Promise<ModelOption[]> {
  // Check cache
  if (
    openRouterModelsCache !== null &&
    Date.now() - cacheTimestamp < CACHE_DURATION
  ) {
    return openRouterModelsCache
  }

  // Prevent concurrent fetches
  if (isFetching) {
    return []
  }

  isFetching = true

  // Import auth utilities to get API key
  const { getGlobalConfig } = await import('../config.js')
  const config = getGlobalConfig()
  const key = apiKey || config.openRouterApiKey

  if (!key) {
    isFetching = false
    return []
  }

  try {
    const response = await fetch('https://openrouter.ai/api/v1/models', {
      headers: {
        Authorization: `Bearer ${key}`,
      },
    })

    if (!response.ok) {
      throw new Error(`Failed to fetch models: ${response.statusText}`)
    }

    const data = await response.json()
    const models: OpenRouterModel[] = data.data || []

    // Convert to ModelOption format
    const options: ModelOption[] = models.map(model => {
      // Truncate description if too long
      let description = model.description || model.id
      if (description.length > 100) {
        description = description.substring(0, 97) + '...'
      }

      return {
        value: model.id,
        label: model.name,
        description: description,
      }
    })

    // Update cache
    openRouterModelsCache = options
    cacheTimestamp = Date.now()

    return options
  } catch (error) {
    console.error('Failed to fetch OpenRouter models:', error)
    return []
  } finally {
    isFetching = false
  }
}

export function getCachedOpenRouterModels(): ModelOption[] {
  return openRouterModelsCache || []
}

export function hasOpenRouterModelsCache(): boolean {
  return openRouterModelsCache !== null
}

export function clearOpenRouterModelsCache(): void {
  openRouterModelsCache = null
  cacheTimestamp = 0
}

// Start background fetch if OpenRouter is configured
export function startOpenRouterModelsFetch(): void {
  // Non-blocking background fetch
  void fetchOpenRouterModels()
}