diff --git a/cmd/godex/main.go b/cmd/godex/main.go index 38cf976..5b81300 100644 --- a/cmd/godex/main.go +++ b/cmd/godex/main.go @@ -588,8 +588,8 @@ promptLoop: } type promptResult struct { - input string err error + input string } promptCancelCh := make(chan struct{}, 1) promptResultCh := make(chan promptResult, 1) diff --git a/cmd/godex/prompt.go b/cmd/godex/prompt.go index 1ac38ab..a0ae04a 100644 --- a/cmd/godex/prompt.go +++ b/cmd/godex/prompt.go @@ -49,39 +49,39 @@ var commandTips = map[string]string{ } type promptModel struct { - basePrompt string - contPrompt string - input textinput.Model - lines []string - multiline bool - history []string - historyIndex int - historyDraft string - submitted bool - aborted bool - completions []string - completeSeed string - completeIdx int - showCompletions bool - width int - modelName string - contextUsage int - contextLimit int historyDB *history.HistoryDB - wd string - searchMode bool - searchInput textinput.Model - searchIndex int - searchResults []string - statusMessage string - commitList []string - scheduleList []string statusCh <-chan string delegateCh <-chan hive.HiveStats - delegateCount int - delegateLatest string - statusHidden bool Cancelled chan struct{} + basePrompt string + contPrompt string + historyDraft string + completeSeed string + modelName string + wd string + statusMessage string + delegateLatest string + lines []string + history []string + completions []string + searchResults []string + commitList []string + scheduleList []string + input textinput.Model + searchInput textinput.Model + historyIndex int + completeIdx int + width int + contextUsage int + contextLimit int + searchIndex int + delegateCount int + multiline bool + submitted bool + aborted bool + showCompletions bool + searchMode bool + statusHidden bool } func newPromptModel(prompt string, history []string, modelName string, contextUsage int, contextLimit int, historyDB *history.HistoryDB, wd string, statusCh <-chan string, delegateCh <-chan hive.HiveStats) promptModel { @@ -844,8 +844,8 @@ type selectOption struct { type statusMsg string type delegateMsg struct { - Count int Latest string + Count int } func (m *promptModel) applyStatusMessage(msg statusMsg) { diff --git a/internal/config/config.go b/internal/config/config.go index ddbbf83..f9a8c6c 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -19,6 +19,10 @@ type MCPServer struct { // Provider describes a single LLM provider, referenced from the TUI agent. type Provider struct { + Temperature *float64 `yaml:"temperature,omitempty"` + MaxToolRounds *int `yaml:"max_tool_rounds,omitempty"` + ToolTimeout *int `yaml:"tool_timeout,omitempty"` // in seconds, default 180 + Params map[string]string `yaml:"params,omitempty"` Name string `yaml:"name"` Type string `yaml:"type"` Endpoint string `yaml:"endpoint"` @@ -26,20 +30,16 @@ type Provider struct { Description string `yaml:"description,omitempty"` APIKey string `yaml:"api_key,omitempty"` APIKeyEnv string `yaml:"api_key_env,omitempty"` - Temperature *float64 `yaml:"temperature,omitempty"` - MaxToolRounds *int `yaml:"max_tool_rounds,omitempty"` - ToolTimeout *int `yaml:"tool_timeout,omitempty"` // in seconds, default 180 - ContextLimit int `yaml:"context_limit,omitempty"` - Params map[string]string `yaml:"params,omitempty"` - MCPServers []MCPServer `yaml:"mcp_servers,omitempty"` LlamaServerURL string `yaml:"-"` // CLI override for external llama.cpp server (not persisted) + MCPServers []MCPServer `yaml:"mcp_servers,omitempty"` + ContextLimit int `yaml:"context_limit,omitempty"` } // Config is a list of providers, with a default provider name for the CLI. type Config struct { - Providers []Provider `yaml:"providers"` - DefaultProvider string `yaml:"default_provider,omitempty"` VisionEnabled *bool `yaml:"vision_enabled,omitempty"` + DefaultProvider string `yaml:"default_provider,omitempty"` + Providers []Provider `yaml:"providers"` VisionCLIDownloaded bool `yaml:"vision_cli_downloaded,omitempty"` } diff --git a/internal/history/history.go b/internal/history/history.go index f5bd912..cd8227d 100644 --- a/internal/history/history.go +++ b/internal/history/history.go @@ -19,18 +19,18 @@ type HistoryDB struct { } type Entry struct { - ID int64 + Timestamp time.Time WD string Command string - Timestamp time.Time + ID int64 } type Commit struct { - ID int64 + CreatedAt time.Time WD string Ref string Message string - CreatedAt time.Time + ID int64 } func New(dbPath string) (*HistoryDB, error) { diff --git a/internal/hive/manager.go b/internal/hive/manager.go index 707ec62..7c1fb37 100644 --- a/internal/hive/manager.go +++ b/internal/hive/manager.go @@ -23,34 +23,34 @@ const ( ) type Instance struct { + StartedAt time.Time `json:"started_at"` ID string `json:"id"` Name string `json:"name"` Model string `json:"model"` + WorkingDir string `json:"working_dir"` + MCPServers []string `json:"mcp_servers"` MaxTokens int `json:"max_tokens"` Port int `json:"port"` - StartedAt time.Time `json:"started_at"` PID int `json:"pid"` - MCPServers []string `json:"mcp_servers"` - WorkingDir string `json:"working_dir"` InputTokens int `json:"input_tokens"` OutputTokens int `json:"output_tokens"` } type Manager struct { + listener net.Listener + statusCh chan<- string + handler func(context.Context, string) (string, error) + srv *http.Server + closed chan struct{} + results chan HiveResult + statsCh chan HiveStats + stats HiveStats codeHash string code string baseDir string instance Instance - statusCh chan<- string - handler func(context.Context, string) (string, error) - srv *http.Server - listener net.Listener closeOnce sync.Once - closed chan struct{} - results chan HiveResult statsMu sync.Mutex - statsCh chan HiveStats - stats HiveStats } type HiveResult struct { @@ -61,8 +61,8 @@ type HiveResult struct { } type HiveStats struct { - DelegatedCount int LatestCommand string + DelegatedCount int } func (m *Manager) Status(msg string) { diff --git a/internal/mcp/bash.go b/internal/mcp/bash.go index 5270b3e..9bb0e09 100644 --- a/internal/mcp/bash.go +++ b/internal/mcp/bash.go @@ -22,18 +22,18 @@ var runCmdMu sync.Mutex // Job represents a running background job managed by a goroutine type Job struct { - ID string - Command string - PID int + ExitedAt time.Time + Started time.Time Ctx context.Context Cancel context.CancelFunc Done chan struct{} + ID string + Command string Output strings.Builder - Mu sync.Mutex + PID int ExitCode int + Mu sync.Mutex Exited bool - ExitedAt time.Time - Started time.Time } // JobTracker manages all background jobs @@ -169,13 +169,13 @@ func (t *JobTracker) JobStatus(id string) (string, bool) { } type BashServer struct { + jobTracker *JobTracker allowedPaths []string tools []Tool - jobTracker *JobTracker - autoConfirm bool + failedStarts []string mu sync.RWMutex failedMu sync.Mutex - failedStarts []string + autoConfirm bool } var ( diff --git a/internal/mcp/client.go b/internal/mcp/client.go index 1e049c8..ace608e 100644 --- a/internal/mcp/client.go +++ b/internal/mcp/client.go @@ -29,15 +29,16 @@ type Tool struct { InputSchema json.RawMessage } -type MCPToolExecutor struct { - serverName string - server MCPServer - mcpClient *client.Client - tools []Tool - workingDir string +type MCPToolExecutor struct { //betteralign:ignore + lastRequestID int64 // Must be first for 64-bit alignment on 32-bit platforms - it's accessed atomically + mcpClient *client.Client + serverName string + workingDir string - lastRequestID int64 - requestIDMu sync.Mutex + server MCPServer + tools []Tool + + requestIDMu sync.Mutex } func NewMCPServer(ctx context.Context, server MCPServer, workingDir string) (*MCPToolExecutor, error) { diff --git a/internal/mcp/scheduler.go b/internal/mcp/scheduler.go index 7b881b3..b3a720f 100644 --- a/internal/mcp/scheduler.go +++ b/internal/mcp/scheduler.go @@ -34,15 +34,15 @@ type schedulerExt struct { } type TaskInfo struct { - ID string `json:"id"` - Prompt string `json:"prompt"` - IntervalSec int `json:"interval_sec"` - RunAt string `json:"run_at"` - IsRepeating bool `json:"is_repeating"` CreatedAt time.Time `json:"created_at"` LastRun time.Time `json:"last_run"` - RunCount int `json:"run_count"` + ID string `json:"id"` + Prompt string `json:"prompt"` + RunAt string `json:"run_at"` LastError string `json:"last_error"` + IntervalSec int `json:"interval_sec"` + RunCount int `json:"run_count"` + IsRepeating bool `json:"is_repeating"` } func NewSchedulerServer(scheduler interface { diff --git a/internal/mcp/webscraper.go b/internal/mcp/webscraper.go index db1440a..1a40b77 100644 --- a/internal/mcp/webscraper.go +++ b/internal/mcp/webscraper.go @@ -16,18 +16,18 @@ import ( ) type cacheEntry struct { - html string expiresAt time.Time + html string } type WebScraperServer struct { - allowedURLs []string - tools []Tool browserCtx context.Context browserCancel context.CancelFunc - autoConfirm bool cache map[string]cacheEntry + allowedURLs []string + tools []Tool cacheMu sync.Mutex + autoConfirm bool } func NewWebScraperServer(allowedURLs []string, autoConfirm bool) *WebScraperServer { diff --git a/internal/providers/download.go b/internal/providers/download.go index 1c32d39..08606aa 100644 --- a/internal/providers/download.go +++ b/internal/providers/download.go @@ -20,8 +20,8 @@ type hfRepoInfo struct { } type hfFileInfo struct { - Size int64 `json:"size"` BlobHTTPURL string `json:"blobHTTPURL"` + Size int64 `json:"size"` } func getGGUFFiles(ctx context.Context, modelID string) ([]string, error) { @@ -90,9 +90,9 @@ func getDownloadURL(modelID, filename string) string { } type DownloadProgress struct { + Filename string Downloaded int64 Total int64 - Filename string } var quantOrder = map[string]int{ diff --git a/internal/providers/gemini.go b/internal/providers/gemini.go index 6e59b98..dfb4f4e 100644 --- a/internal/providers/gemini.go +++ b/internal/providers/gemini.go @@ -18,17 +18,17 @@ const DefaultGeminiModel = "gemini-2.5-flash" type geminiProvider struct { client *genai.Client cfg *config.Provider - model string temperature *float64 - cancelMu sync.Mutex - mu sync.Mutex cancelFunc context.CancelFunc + statusCh chan<- string + model string + messages []Message cancelGen uint64 contextLimit int promptTokens int completionTokens int - messages []Message - statusCh chan<- string + cancelMu sync.Mutex + mu sync.Mutex } func init() { diff --git a/internal/providers/huggingface.go b/internal/providers/huggingface.go index f8206b4..b9d2ebb 100644 --- a/internal/providers/huggingface.go +++ b/internal/providers/huggingface.go @@ -18,17 +18,17 @@ import ( const defaultHFBaseURL = "https://router.huggingface.co/v1" type huggingfaceProvider struct { + temperature *float64 + client *http.Client + cancelFunc context.CancelFunc + statusCh chan<- string baseURL string model string apiKey string - temperature *float64 - client *http.Client - cancelMu sync.Mutex - cancelFunc context.CancelFunc - cancelGen uint64 messages []Message + cancelGen uint64 + cancelMu sync.Mutex mu sync.Mutex - statusCh chan<- string } func init() { diff --git a/internal/providers/llama.go b/internal/providers/llama.go index 8633f04..48de6f6 100644 --- a/internal/providers/llama.go +++ b/internal/providers/llama.go @@ -37,37 +37,38 @@ func llamaDebug(format string, args ...any) { } type llamaProvider struct { - baseURL string - model string - modelIsHF bool cfg *config.Provider temperature *float64 client *http.Client - messages []map[string]any - mu sync.Mutex - sendMu sync.Mutex OnThink func(string) cancelFunc context.CancelFunc - cancelGen uint64 - contextLimit int - promptTokens int - completionTokens int statusCh chan<- string - tools []map[string]any pendingToolCalls map[string]string - serverCmd *exec.Cmd - serverProcess *os.Process - serverPort int - serverPath string - tokenizePath string - externalServer bool - serverMu sync.Mutex - serverReady bool - serverStarted bool - startMu sync.Mutex + serverCmd *exec.Cmd + serverProcess *os.Process OnDownloadProgress func(DownloadProgress) + baseURL string + model string + serverPath string + tokenizePath string + messages []map[string]any + tools []map[string]any + cancelGen uint64 + contextLimit int + promptTokens int + completionTokens int + serverPort int + mu sync.Mutex + sendMu sync.Mutex + serverMu sync.Mutex + startMu sync.Mutex + + modelIsHF bool + externalServer bool + serverReady bool + serverStarted bool } var ( @@ -475,10 +476,10 @@ func setCachedQuantization(modelID, quant string) { type progressWriter struct { w io.Writer + progressCh chan<- DownloadProgress + filename string total int64 written int64 - filename string - progressCh chan<- DownloadProgress } func (pw *progressWriter) Write(p []byte) (int, error) { @@ -1325,13 +1326,13 @@ func (p *llamaProvider) TokenUsage() (int, int) { } type slotInfo struct { - ID int `json:"id"` - IsProcessing bool `json:"is_processing"` - NCtx int `json:"n_ctx"` - IDTask int `json:"id_task"` - NextToken []struct { + NextToken []struct { NDecoded int `json:"n_decoded"` } `json:"next_token"` + ID int `json:"id"` + NCtx int `json:"n_ctx"` + IDTask int `json:"id_task"` + IsProcessing bool `json:"is_processing"` } func (p *llamaProvider) countTokens(text string) int { diff --git a/internal/providers/ollama.go b/internal/providers/ollama.go index 07e3929..4d4e59d 100644 --- a/internal/providers/ollama.go +++ b/internal/providers/ollama.go @@ -25,22 +25,22 @@ const ( ) type ollamaProvider struct { - baseURL string - model string cfg *config.Provider temperature *float64 client *http.Client - systemPrompt string - messages []map[string]string - mu sync.Mutex - sendMu sync.Mutex OnThink func(string) cancelFunc context.CancelFunc + statusCh chan<- string + baseURL string + model string + systemPrompt string + messages []map[string]string cancelGen uint64 contextLimit int promptTokens int completionTokens int - statusCh chan<- string + mu sync.Mutex + sendMu sync.Mutex visionChecked bool visionSupported bool } @@ -403,8 +403,8 @@ func (o *ollamaProvider) doSend(ctx context.Context, endpoint string, payload [] } type ollamaError struct { - statusCode int message string + statusCode int } func (e *ollamaError) Error() string { diff --git a/internal/providers/openrouter.go b/internal/providers/openrouter.go index df81468..1557d62 100644 --- a/internal/providers/openrouter.go +++ b/internal/providers/openrouter.go @@ -31,13 +31,13 @@ func getMaxHistoryMessages() int { } type openRouterModelInfo struct { - ID string `json:"id"` - CanonicalSlug string `json:"canonical_slug"` - Name string `json:"name"` - ContextLength float64 `json:"context_length"` + ID string `json:"id"` + CanonicalSlug string `json:"canonical_slug"` + Name string `json:"name"` Architecture struct { InputModalities []string `json:"input_modalities"` } `json:"architecture"` + ContextLength float64 `json:"context_length"` } type openRouterModelsResponse struct { @@ -67,26 +67,26 @@ type reasoningDetail struct { } type openRouterProvider struct { + temperature *float64 + client *http.Client + pendingToolCalls map[string]string // tool_call_id -> function_name for tracking + cancelFunc context.CancelFunc + OnThink func(string) + statusCh chan<- string baseURL string model string apiKey string - temperature *float64 - client *http.Client systemPrompt string messages []map[string]any - pendingToolCalls map[string]string // tool_call_id -> function_name for tracking tools []map[string]any - cancelMu sync.Mutex - cancelFunc context.CancelFunc cancelGen uint64 contextLimit int promptTokens int completionTokens int + cancelMu sync.Mutex + mu sync.Mutex visionChecked bool visionSupported bool - OnThink func(string) - mu sync.Mutex - statusCh chan<- string } func (p *openRouterProvider) emitStatus(msg string) { diff --git a/internal/providers/provider.go b/internal/providers/provider.go index f8c728e..fdd57a8 100644 --- a/internal/providers/provider.go +++ b/internal/providers/provider.go @@ -12,9 +12,9 @@ var DebugMode bool // Tool represents an executable tool. type Tool struct { + InputSchema map[string]any Name string Description string - InputSchema map[string]any } type Message struct { diff --git a/internal/rxcache/regexp_cache.go b/internal/rxcache/regexp_cache.go index 2dcc6ea..296f127 100644 --- a/internal/rxcache/regexp_cache.go +++ b/internal/rxcache/regexp_cache.go @@ -13,9 +13,9 @@ const globalCacheLimit = 1000 var globalCache = RegexpCache{m: make(map[string]*regexp.Regexp, globalCacheLimit), limit: globalCacheLimit} type RegexpCache struct { - mu sync.RWMutex m map[string]*regexp.Regexp limit int + mu sync.RWMutex } func (c *RegexpCache) MustCompile(pattern string) *regexp.Regexp { diff --git a/internal/scheduler/scheduler.go b/internal/scheduler/scheduler.go index 3253b5c..d0131f0 100644 --- a/internal/scheduler/scheduler.go +++ b/internal/scheduler/scheduler.go @@ -21,38 +21,38 @@ import ( ) type ScheduledTask struct { - ID string `json:"id"` - Prompt string `json:"prompt"` - IntervalSec int `json:"interval_sec"` - RunAt string `json:"run_at"` - IsRepeating bool `json:"is_repeating"` - WorkingDir string `json:"working_dir"` CreatedAt time.Time `json:"created_at"` LastRun time.Time `json:"last_run"` - RunCount int `json:"run_count"` + ID string `json:"id"` + Prompt string `json:"prompt"` + RunAt string `json:"run_at"` + WorkingDir string `json:"working_dir"` LastError string `json:"last_error"` LastOutput string `json:"last_output"` ProviderType string `json:"provider_type"` ProviderName string `json:"provider_name"` ProviderModel string `json:"provider_model"` + IntervalSec int `json:"interval_sec"` + RunCount int `json:"run_count"` + IsRepeating bool `json:"is_repeating"` } type Scheduler struct { + provider ProviderGetter db *sql.DB tasks map[string]*ScheduledTask - taskMu sync.RWMutex running map[string]context.CancelFunc - runMu sync.RWMutex stopCh chan struct{} - wg sync.WaitGroup - provider ProviderGetter - servers []ToolServer onTaskFinished func(*ScheduledTask) - maxRounds int - toolTimeout int + statusCh chan string wd string os string - statusCh chan string + servers []ToolServer + wg sync.WaitGroup + maxRounds int + toolTimeout int + taskMu sync.RWMutex + runMu sync.RWMutex } type ProviderGetter interface { diff --git a/internal/wizard/modelselect.go b/internal/wizard/modelselect.go index 864d60c..62fa39f 100644 --- a/internal/wizard/modelselect.go +++ b/internal/wizard/modelselect.go @@ -17,17 +17,17 @@ type searchResultMsg struct { } type modelSelectModel struct { - textInput textinput.Model - results []modelquery.Model - cursor int - loading bool + searchCancel context.CancelFunc provider modelquery.Provider - searchDebounce time.Duration - done bool result string defaultValue string currentQuery string - searchCancel context.CancelFunc + results []modelquery.Model + textInput textinput.Model + cursor int + searchDebounce time.Duration + loading bool + done bool pendingSearch bool } diff --git a/internal/wizard/wizard.go b/internal/wizard/wizard.go index 7f27e08..ed0df5b 100644 --- a/internal/wizard/wizard.go +++ b/internal/wizard/wizard.go @@ -349,10 +349,10 @@ type selectOption struct { } type selectModel struct { + result string options []selectOption cursor int done bool - result string allowCancel bool } @@ -437,8 +437,8 @@ func selectPrompt(title string, options []selectOption, defaultVal string, allow } type multiSelectModel struct { - options []selectOption selected map[int]bool + options []selectOption cursor int done bool allowCancel bool @@ -584,9 +584,9 @@ func openBrowser(urlStr string) error { } type oauthCallback struct { - code string err error done chan struct{} + code string received bool } diff --git a/modelquery/gemini.go b/modelquery/gemini.go index 7a24844..d2f6856 100644 --- a/modelquery/gemini.go +++ b/modelquery/gemini.go @@ -14,16 +14,16 @@ type GeminiModelsResponse struct { // GeminiModel represents a model from the Gemini API. type GeminiModel struct { + Temperature *float64 `json:"temperature,omitempty"` + TopP *float64 `json:"topP,omitempty"` + TopK *int `json:"topK,omitempty"` Name string `json:"name"` Version string `json:"version"` DisplayName string `json:"displayName"` Description string `json:"description"` + SupportedGenerationMethods []string `json:"supportedGenerationMethods"` InputTokenLimit int `json:"inputTokenLimit"` OutputTokenLimit int `json:"outputTokenLimit"` - SupportedGenerationMethods []string `json:"supportedGenerationMethods"` - Temperature *float64 `json:"temperature,omitempty"` - TopP *float64 `json:"topP,omitempty"` - TopK *int `json:"topK,omitempty"` } // listGeminiModels queries Google's Gemini API for available models. diff --git a/modelquery/huggingface.go b/modelquery/huggingface.go index 468adbe..9eddda8 100644 --- a/modelquery/huggingface.go +++ b/modelquery/huggingface.go @@ -14,16 +14,16 @@ type HuggingFaceModel struct { Author string `json:"author"` CreatedAt string `json:"createdAt"` LastModified string `json:"lastModified"` - Private bool `json:"private"` - Downloads int `json:"downloads"` - Guarded bool `json:"guarded"` - Likes int `json:"likes"` - Tags []string `json:"tags"` PipelineTag string `json:"pipeline_tag"` + Autotemp string `json:"__variant"` + Tags []string `json:"tags"` Siblings []struct { Rfilename string `json:"rfilename"` } `json:"siblings"` - Autotemp string `json:"__variant"` + Downloads int `json:"downloads"` + Likes int `json:"likes"` + Private bool `json:"private"` + Guarded bool `json:"guarded"` } // HuggingFaceResponse represents the response from HuggingFace API. diff --git a/modelquery/ollama.go b/modelquery/ollama.go index 55b1a21..1d7b128 100644 --- a/modelquery/ollama.go +++ b/modelquery/ollama.go @@ -15,19 +15,19 @@ type OllamaTagsResponse struct { type OllamaModel struct { Name string `json:"name"` Model string `json:"model"` - Size int64 `json:"size"` Digest string `json:"digest"` ModifiedAt string `json:"modified_at"` Details OllamaModelDetails `json:"details"` + Size int64 `json:"size"` } // OllamaModelDetails contains additional details about an Ollama model. type OllamaModelDetails struct { Format string `json:"format"` Family string `json:"family"` - Families []string `json:"families"` ParameterSize string `json:"parameter_size"` QuantizationLevel string `json:"quantization_level"` + Families []string `json:"families"` } // listOllamaModels queries a local Ollama instance for available models. diff --git a/modelquery/openrouter.go b/modelquery/openrouter.go index da0c20d..565978b 100644 --- a/modelquery/openrouter.go +++ b/modelquery/openrouter.go @@ -13,26 +13,26 @@ type OpenRouterModelsResponse struct { // OpenRouterModel represents a model from the OpenRouter API. type OpenRouterModel struct { + DefaultParams map[string]interface{} `json:"default_parameters"` + Pricing OpenRouterPricing `json:"pricing"` + Architecture OpenRouterArchitecture `json:"architecture"` ID string `json:"id"` CanonicalSlug string `json:"canonical_slug"` Name string `json:"name"` - Created int64 `json:"created"` Description string `json:"description"` - ContextLength int `json:"context_length"` - Architecture OpenRouterArchitecture `json:"architecture"` - Pricing OpenRouterPricing `json:"pricing"` - TopProvider OpenRouterTopProvider `json:"top_provider"` - SupportedParams []string `json:"supported_parameters"` - DefaultParams map[string]any `json:"default_parameters"` ExpirationDate string `json:"expiration_date"` + SupportedParams []string `json:"supported_parameters"` + TopProvider OpenRouterTopProvider `json:"top_provider"` + Created int64 `json:"created"` + ContextLength int `json:"context_length"` } // OpenRouterArchitecture describes the model's technical capabilities. type OpenRouterArchitecture struct { - InputModalities []string `json:"input_modalities"` - OutputModalities []string `json:"output_modalities"` Tokenizer string `json:"tokenizer"` InstructType string `json:"instruct_type"` + InputModalities []string `json:"input_modalities"` + OutputModalities []string `json:"output_modalities"` } // OpenRouterPricing contains pricing information for the model.