| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- package main
- import (
- "encoding/json"
- "flag"
- "fmt"
- "io"
- "log"
- "net/http"
- "os"
- "strings"
- )
- type ModelsResponse struct {
- Object string `json:"object"`
- Data []Model `json:"data"`
- }
- type Model struct {
- ID string `json:"id"`
- Object string `json:"object"`
- Created int64 `json:"created,omitempty"`
- OwnedBy string `json:"owned_by,omitempty"`
- Metadata map[string]interface{} `json:"metadata,omitempty"`
- }
- type Limit struct {
- Context int `json:"context"`
- Output int `json:"output"`
- }
- type OpencodeModel struct {
- Name string `json:"name"`
- Limit Limit `json:"limit"`
- }
- type DynamicProvider struct {
- Npm string `json:"npm"`
- Name string `json:"name"`
- Options map[string]string `json:"options"`
- Models map[string]OpencodeModel `json:"models"`
- }
- type OpencodeConfig struct {
- Schema string `json:"$schema"`
- Provider map[string]DynamicProvider `json:"provider"`
- }
- func getIntFromMetadata(md map[string]interface{}, key string, defaultVal int) int {
- if md == nil {
- return defaultVal
- }
- if v, ok := md[key]; ok {
- if i, ok := v.(float64); ok {
- return int(i)
- }
- }
- return defaultVal
- }
- func main() {
- var providerName, baseURL, apiURL, outputFile string
- flag.StringVar(&providerName, "provider", "Myprovider", "Name of the provider (default: Myprovider)")
- flag.StringVar(&baseURL, "baseurl", "", "Base URL for the provider (required, e.g., http://localhost:8080/v1)")
- flag.StringVar(&apiURL, "apiurl", "", "API URL to fetch models from (default: <baseurl>/models)")
- flag.StringVar(&outputFile, "output", "opencode.jsonc", "Output file name (default: opencode.jsonc)")
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, "Usage: %s [options]\n\n", os.Args[0])
- fmt.Fprintf(os.Stderr, "Example:\n")
- fmt.Fprintf(os.Stderr, " %s --provider Myprovider --baseurl http://localhost:8080/v1\n\n", os.Args[0])
- flag.PrintDefaults()
- }
- flag.Parse()
- if baseURL == "" {
- log.Fatal("--baseurl is required")
- }
- if apiURL == "" {
- apiURL = strings.TrimSuffix(baseURL, "/") + "/models"
- }
- if baseURL == "" || apiURL == "" {
- log.Fatal("Both --baseurl and --apiurl are required")
- }
- resp, err := http.Get(apiURL)
- if err != nil {
- log.Fatalf("Failed to fetch %s: %v", apiURL, err)
- }
- defer resp.Body.Close()
- if resp.StatusCode != http.StatusOK {
- log.Fatalf("Unexpected status code: %d", resp.StatusCode)
- }
- body, err := io.ReadAll(resp.Body)
- if err != nil {
- log.Fatalf("Failed to read response: %v", err)
- }
- var modelsResp ModelsResponse
- if err := json.Unmarshal(body, &modelsResp); err != nil {
- log.Fatalf("Failed to parse models response: %v", err)
- }
- config := OpencodeConfig{
- Schema: "https://opencode.ai/config.json",
- Provider: map[string]DynamicProvider{
- providerName: {
- Npm: "@ai-sdk/openai-compatible",
- Name: providerName,
- Options: map[string]string{
- "baseURL": baseURL,
- "apiKey": "noneneeded",
- },
- Models: make(map[string]OpencodeModel),
- },
- },
- }
- for _, m := range modelsResp.Data {
- ctx := getIntFromMetadata(m.Metadata, "context_window", 131072)
- out := getIntFromMetadata(m.Metadata, "max_output_tokens", 8192)
- config.Provider[providerName].Models[m.ID] = OpencodeModel{
- Name: m.ID,
- Limit: Limit{
- Context: ctx,
- Output: out,
- },
- }
- }
- out, err := json.MarshalIndent(config, "", " ")
- if err != nil {
- log.Fatalf("Failed to marshal config: %v", err)
- }
- if err := os.WriteFile(outputFile, out, 0644); err != nil {
- log.Fatalf("Failed to write %s: %v", outputFile, err)
- }
- fmt.Printf("Successfully wrote %s with %d models for provider %s\n", outputFile, len(config.Provider[providerName].Models), providerName)
- }
|