superqode 0.1.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- superqode/__init__.py +33 -0
- superqode/acp/__init__.py +23 -0
- superqode/acp/client.py +913 -0
- superqode/acp/permission_screen.py +457 -0
- superqode/acp/types.py +480 -0
- superqode/acp_discovery.py +856 -0
- superqode/agent/__init__.py +22 -0
- superqode/agent/edit_strategies.py +334 -0
- superqode/agent/loop.py +892 -0
- superqode/agent/qe_report_templates.py +39 -0
- superqode/agent/system_prompts.py +353 -0
- superqode/agent_output.py +721 -0
- superqode/agent_stream.py +953 -0
- superqode/agents/__init__.py +59 -0
- superqode/agents/acp_registry.py +305 -0
- superqode/agents/client.py +249 -0
- superqode/agents/data/augmentcode.com.toml +51 -0
- superqode/agents/data/cagent.dev.toml +51 -0
- superqode/agents/data/claude.com.toml +60 -0
- superqode/agents/data/codeassistant.dev.toml +51 -0
- superqode/agents/data/codex.openai.com.toml +57 -0
- superqode/agents/data/fastagent.ai.toml +66 -0
- superqode/agents/data/geminicli.com.toml +77 -0
- superqode/agents/data/goose.block.xyz.toml +54 -0
- superqode/agents/data/junie.jetbrains.com.toml +56 -0
- superqode/agents/data/kimi.moonshot.cn.toml +57 -0
- superqode/agents/data/llmlingagent.dev.toml +51 -0
- superqode/agents/data/molt.bot.toml +49 -0
- superqode/agents/data/opencode.ai.toml +60 -0
- superqode/agents/data/stakpak.dev.toml +51 -0
- superqode/agents/data/vtcode.dev.toml +51 -0
- superqode/agents/discovery.py +266 -0
- superqode/agents/messaging.py +160 -0
- superqode/agents/persona.py +166 -0
- superqode/agents/registry.py +421 -0
- superqode/agents/schema.py +72 -0
- superqode/agents/unified.py +367 -0
- superqode/app/__init__.py +111 -0
- superqode/app/constants.py +314 -0
- superqode/app/css.py +366 -0
- superqode/app/models.py +118 -0
- superqode/app/suggester.py +125 -0
- superqode/app/widgets.py +1591 -0
- superqode/app_enhanced.py +399 -0
- superqode/app_main.py +17187 -0
- superqode/approval.py +312 -0
- superqode/atomic.py +296 -0
- superqode/commands/__init__.py +1 -0
- superqode/commands/acp.py +965 -0
- superqode/commands/agents.py +180 -0
- superqode/commands/auth.py +278 -0
- superqode/commands/config.py +374 -0
- superqode/commands/init.py +826 -0
- superqode/commands/providers.py +819 -0
- superqode/commands/qe.py +1145 -0
- superqode/commands/roles.py +380 -0
- superqode/commands/serve.py +172 -0
- superqode/commands/suggestions.py +127 -0
- superqode/commands/superqe.py +460 -0
- superqode/config/__init__.py +51 -0
- superqode/config/loader.py +812 -0
- superqode/config/schema.py +498 -0
- superqode/core/__init__.py +111 -0
- superqode/core/roles.py +281 -0
- superqode/danger.py +386 -0
- superqode/data/superqode-template.yaml +1522 -0
- superqode/design_system.py +1080 -0
- superqode/dialogs/__init__.py +6 -0
- superqode/dialogs/base.py +39 -0
- superqode/dialogs/model.py +130 -0
- superqode/dialogs/provider.py +870 -0
- superqode/diff_view.py +919 -0
- superqode/enterprise.py +21 -0
- superqode/evaluation/__init__.py +25 -0
- superqode/evaluation/adapters.py +93 -0
- superqode/evaluation/behaviors.py +89 -0
- superqode/evaluation/engine.py +209 -0
- superqode/evaluation/scenarios.py +96 -0
- superqode/execution/__init__.py +36 -0
- superqode/execution/linter.py +538 -0
- superqode/execution/modes.py +347 -0
- superqode/execution/resolver.py +283 -0
- superqode/execution/runner.py +642 -0
- superqode/file_explorer.py +811 -0
- superqode/file_viewer.py +471 -0
- superqode/flash.py +183 -0
- superqode/guidance/__init__.py +58 -0
- superqode/guidance/config.py +203 -0
- superqode/guidance/prompts.py +71 -0
- superqode/harness/__init__.py +54 -0
- superqode/harness/accelerator.py +291 -0
- superqode/harness/config.py +319 -0
- superqode/harness/validator.py +147 -0
- superqode/history.py +279 -0
- superqode/integrations/superopt_runner.py +124 -0
- superqode/logging/__init__.py +49 -0
- superqode/logging/adapters.py +219 -0
- superqode/logging/formatter.py +923 -0
- superqode/logging/integration.py +341 -0
- superqode/logging/sinks.py +170 -0
- superqode/logging/unified_log.py +417 -0
- superqode/lsp/__init__.py +26 -0
- superqode/lsp/client.py +544 -0
- superqode/main.py +1069 -0
- superqode/mcp/__init__.py +89 -0
- superqode/mcp/auth_storage.py +380 -0
- superqode/mcp/client.py +1236 -0
- superqode/mcp/config.py +319 -0
- superqode/mcp/integration.py +337 -0
- superqode/mcp/oauth.py +436 -0
- superqode/mcp/oauth_callback.py +385 -0
- superqode/mcp/types.py +290 -0
- superqode/memory/__init__.py +31 -0
- superqode/memory/feedback.py +342 -0
- superqode/memory/store.py +522 -0
- superqode/notifications.py +369 -0
- superqode/optimization/__init__.py +5 -0
- superqode/optimization/config.py +33 -0
- superqode/permissions/__init__.py +25 -0
- superqode/permissions/rules.py +488 -0
- superqode/plan.py +323 -0
- superqode/providers/__init__.py +33 -0
- superqode/providers/gateway/__init__.py +165 -0
- superqode/providers/gateway/base.py +228 -0
- superqode/providers/gateway/litellm_gateway.py +1170 -0
- superqode/providers/gateway/openresponses_gateway.py +436 -0
- superqode/providers/health.py +297 -0
- superqode/providers/huggingface/__init__.py +74 -0
- superqode/providers/huggingface/downloader.py +472 -0
- superqode/providers/huggingface/endpoints.py +442 -0
- superqode/providers/huggingface/hub.py +531 -0
- superqode/providers/huggingface/inference.py +394 -0
- superqode/providers/huggingface/transformers_runner.py +516 -0
- superqode/providers/local/__init__.py +100 -0
- superqode/providers/local/base.py +438 -0
- superqode/providers/local/discovery.py +418 -0
- superqode/providers/local/lmstudio.py +256 -0
- superqode/providers/local/mlx.py +457 -0
- superqode/providers/local/ollama.py +486 -0
- superqode/providers/local/sglang.py +268 -0
- superqode/providers/local/tgi.py +260 -0
- superqode/providers/local/tool_support.py +477 -0
- superqode/providers/local/vllm.py +258 -0
- superqode/providers/manager.py +1338 -0
- superqode/providers/models.py +1016 -0
- superqode/providers/models_dev.py +578 -0
- superqode/providers/openresponses/__init__.py +87 -0
- superqode/providers/openresponses/converters/__init__.py +17 -0
- superqode/providers/openresponses/converters/messages.py +343 -0
- superqode/providers/openresponses/converters/tools.py +268 -0
- superqode/providers/openresponses/schema/__init__.py +56 -0
- superqode/providers/openresponses/schema/models.py +585 -0
- superqode/providers/openresponses/streaming/__init__.py +5 -0
- superqode/providers/openresponses/streaming/parser.py +338 -0
- superqode/providers/openresponses/tools/__init__.py +21 -0
- superqode/providers/openresponses/tools/apply_patch.py +352 -0
- superqode/providers/openresponses/tools/code_interpreter.py +290 -0
- superqode/providers/openresponses/tools/file_search.py +333 -0
- superqode/providers/openresponses/tools/mcp_adapter.py +252 -0
- superqode/providers/registry.py +716 -0
- superqode/providers/usage.py +332 -0
- superqode/pure_mode.py +384 -0
- superqode/qr/__init__.py +23 -0
- superqode/qr/dashboard.py +781 -0
- superqode/qr/generator.py +1018 -0
- superqode/qr/templates.py +135 -0
- superqode/safety/__init__.py +41 -0
- superqode/safety/sandbox.py +413 -0
- superqode/safety/warnings.py +256 -0
- superqode/server/__init__.py +33 -0
- superqode/server/lsp_server.py +775 -0
- superqode/server/web.py +250 -0
- superqode/session/__init__.py +25 -0
- superqode/session/persistence.py +580 -0
- superqode/session/sharing.py +477 -0
- superqode/session.py +475 -0
- superqode/sidebar.py +2991 -0
- superqode/stream_view.py +648 -0
- superqode/styles/__init__.py +3 -0
- superqode/superqe/__init__.py +184 -0
- superqode/superqe/acp_runner.py +1064 -0
- superqode/superqe/constitution/__init__.py +62 -0
- superqode/superqe/constitution/evaluator.py +308 -0
- superqode/superqe/constitution/loader.py +432 -0
- superqode/superqe/constitution/schema.py +250 -0
- superqode/superqe/events.py +591 -0
- superqode/superqe/frameworks/__init__.py +65 -0
- superqode/superqe/frameworks/base.py +234 -0
- superqode/superqe/frameworks/e2e.py +263 -0
- superqode/superqe/frameworks/executor.py +237 -0
- superqode/superqe/frameworks/javascript.py +409 -0
- superqode/superqe/frameworks/python.py +373 -0
- superqode/superqe/frameworks/registry.py +92 -0
- superqode/superqe/mcp_tools/__init__.py +47 -0
- superqode/superqe/mcp_tools/core_tools.py +418 -0
- superqode/superqe/mcp_tools/registry.py +230 -0
- superqode/superqe/mcp_tools/testing_tools.py +167 -0
- superqode/superqe/noise.py +89 -0
- superqode/superqe/orchestrator.py +778 -0
- superqode/superqe/roles.py +609 -0
- superqode/superqe/session.py +713 -0
- superqode/superqe/skills/__init__.py +57 -0
- superqode/superqe/skills/base.py +106 -0
- superqode/superqe/skills/core_skills.py +899 -0
- superqode/superqe/skills/registry.py +90 -0
- superqode/superqe/verifier.py +101 -0
- superqode/superqe_cli.py +76 -0
- superqode/tool_call.py +358 -0
- superqode/tools/__init__.py +93 -0
- superqode/tools/agent_tools.py +496 -0
- superqode/tools/base.py +324 -0
- superqode/tools/batch_tool.py +133 -0
- superqode/tools/diagnostics.py +311 -0
- superqode/tools/edit_tools.py +653 -0
- superqode/tools/enhanced_base.py +515 -0
- superqode/tools/file_tools.py +269 -0
- superqode/tools/file_tracking.py +45 -0
- superqode/tools/lsp_tools.py +610 -0
- superqode/tools/network_tools.py +350 -0
- superqode/tools/permissions.py +400 -0
- superqode/tools/question_tool.py +324 -0
- superqode/tools/search_tools.py +598 -0
- superqode/tools/shell_tools.py +259 -0
- superqode/tools/todo_tools.py +121 -0
- superqode/tools/validation.py +80 -0
- superqode/tools/web_tools.py +639 -0
- superqode/tui.py +1152 -0
- superqode/tui_integration.py +875 -0
- superqode/tui_widgets/__init__.py +27 -0
- superqode/tui_widgets/widgets/__init__.py +18 -0
- superqode/tui_widgets/widgets/progress.py +185 -0
- superqode/tui_widgets/widgets/tool_display.py +188 -0
- superqode/undo_manager.py +574 -0
- superqode/utils/__init__.py +5 -0
- superqode/utils/error_handling.py +323 -0
- superqode/utils/fuzzy.py +257 -0
- superqode/widgets/__init__.py +477 -0
- superqode/widgets/agent_collab.py +390 -0
- superqode/widgets/agent_store.py +936 -0
- superqode/widgets/agent_switcher.py +395 -0
- superqode/widgets/animation_manager.py +284 -0
- superqode/widgets/code_context.py +356 -0
- superqode/widgets/command_palette.py +412 -0
- superqode/widgets/connection_status.py +537 -0
- superqode/widgets/conversation_history.py +470 -0
- superqode/widgets/diff_indicator.py +155 -0
- superqode/widgets/enhanced_status_bar.py +385 -0
- superqode/widgets/enhanced_toast.py +476 -0
- superqode/widgets/file_browser.py +809 -0
- superqode/widgets/file_reference.py +585 -0
- superqode/widgets/issue_timeline.py +340 -0
- superqode/widgets/leader_key.py +264 -0
- superqode/widgets/mode_switcher.py +445 -0
- superqode/widgets/model_picker.py +234 -0
- superqode/widgets/permission_preview.py +1205 -0
- superqode/widgets/prompt.py +358 -0
- superqode/widgets/provider_connect.py +725 -0
- superqode/widgets/pty_shell.py +587 -0
- superqode/widgets/qe_dashboard.py +321 -0
- superqode/widgets/resizable_sidebar.py +377 -0
- superqode/widgets/response_changes.py +218 -0
- superqode/widgets/response_display.py +528 -0
- superqode/widgets/rich_tool_display.py +613 -0
- superqode/widgets/sidebar_panels.py +1180 -0
- superqode/widgets/slash_complete.py +356 -0
- superqode/widgets/split_view.py +612 -0
- superqode/widgets/status_bar.py +273 -0
- superqode/widgets/superqode_display.py +786 -0
- superqode/widgets/thinking_display.py +815 -0
- superqode/widgets/throbber.py +87 -0
- superqode/widgets/toast.py +206 -0
- superqode/widgets/unified_output.py +1073 -0
- superqode/workspace/__init__.py +75 -0
- superqode/workspace/artifacts.py +472 -0
- superqode/workspace/coordinator.py +353 -0
- superqode/workspace/diff_tracker.py +429 -0
- superqode/workspace/git_guard.py +373 -0
- superqode/workspace/git_snapshot.py +526 -0
- superqode/workspace/manager.py +750 -0
- superqode/workspace/snapshot.py +357 -0
- superqode/workspace/watcher.py +535 -0
- superqode/workspace/worktree.py +440 -0
- superqode-0.1.5.dist-info/METADATA +204 -0
- superqode-0.1.5.dist-info/RECORD +288 -0
- superqode-0.1.5.dist-info/WHEEL +5 -0
- superqode-0.1.5.dist-info/entry_points.txt +3 -0
- superqode-0.1.5.dist-info/licenses/LICENSE +648 -0
- superqode-0.1.5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1016 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SuperQode Model Database - Model pricing, features, and metadata.
|
|
3
|
+
|
|
4
|
+
Provides detailed information about LLM models including:
|
|
5
|
+
- Pricing (input/output per 1M tokens)
|
|
6
|
+
- Context window size
|
|
7
|
+
- Feature support (tools, vision, etc.)
|
|
8
|
+
- Recommendations
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
from superqode.providers.models import get_model_info, MODELS
|
|
12
|
+
|
|
13
|
+
info = get_model_info("anthropic", "claude-sonnet-4")
|
|
14
|
+
print(f"Price: ${info.input_price}/${info.output_price} per 1M tokens")
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from dataclasses import dataclass, field
|
|
20
|
+
from enum import Enum, auto
|
|
21
|
+
from typing import Dict, List, Optional, Tuple
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ============================================================================
|
|
25
|
+
# MODEL INFO
|
|
26
|
+
# ============================================================================
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ModelCapability(Enum):
|
|
30
|
+
"""Model capabilities."""
|
|
31
|
+
|
|
32
|
+
TOOLS = auto() # Function calling / tools
|
|
33
|
+
VISION = auto() # Image input
|
|
34
|
+
STREAMING = auto() # Streaming output
|
|
35
|
+
JSON_MODE = auto() # Structured JSON output
|
|
36
|
+
REASONING = auto() # Extended thinking / reasoning
|
|
37
|
+
CODE = auto() # Optimized for code
|
|
38
|
+
LONG_CONTEXT = auto() # > 100K context
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class ModelInfo:
|
|
43
|
+
"""Detailed model information."""
|
|
44
|
+
|
|
45
|
+
id: str # Model identifier
|
|
46
|
+
name: str # Human-readable name
|
|
47
|
+
provider: str # Provider ID
|
|
48
|
+
|
|
49
|
+
# Pricing (per 1M tokens, USD)
|
|
50
|
+
input_price: float = 0.0
|
|
51
|
+
output_price: float = 0.0
|
|
52
|
+
|
|
53
|
+
# Context
|
|
54
|
+
context_window: int = 128000 # Max tokens
|
|
55
|
+
max_output: int = 4096 # Max output tokens
|
|
56
|
+
|
|
57
|
+
# Capabilities
|
|
58
|
+
capabilities: List[ModelCapability] = field(default_factory=list)
|
|
59
|
+
|
|
60
|
+
# Metadata
|
|
61
|
+
description: str = ""
|
|
62
|
+
recommended_for: List[str] = field(default_factory=list)
|
|
63
|
+
released: str = "" # Release date
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def supports_tools(self) -> bool:
|
|
67
|
+
return ModelCapability.TOOLS in self.capabilities
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def supports_vision(self) -> bool:
|
|
71
|
+
return ModelCapability.VISION in self.capabilities
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def supports_reasoning(self) -> bool:
|
|
75
|
+
return ModelCapability.REASONING in self.capabilities
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def is_code_optimized(self) -> bool:
|
|
79
|
+
return ModelCapability.CODE in self.capabilities
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def price_display(self) -> str:
|
|
83
|
+
"""Display-friendly pricing."""
|
|
84
|
+
if self.input_price == 0 and self.output_price == 0:
|
|
85
|
+
return "Free"
|
|
86
|
+
return f"${self.input_price:.2f}/${self.output_price:.2f}"
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def context_display(self) -> str:
|
|
90
|
+
"""Display-friendly context window."""
|
|
91
|
+
if self.context_window >= 1000000:
|
|
92
|
+
return f"{self.context_window // 1000000}M"
|
|
93
|
+
elif self.context_window >= 1000:
|
|
94
|
+
return f"{self.context_window // 1000}K"
|
|
95
|
+
return str(self.context_window)
|
|
96
|
+
|
|
97
|
+
def estimate_cost(self, input_tokens: int, output_tokens: int) -> float:
|
|
98
|
+
"""Estimate cost for given token counts."""
|
|
99
|
+
input_cost = (input_tokens / 1_000_000) * self.input_price
|
|
100
|
+
output_cost = (output_tokens / 1_000_000) * self.output_price
|
|
101
|
+
return input_cost + output_cost
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# ============================================================================
|
|
105
|
+
# MODEL DATABASE
|
|
106
|
+
# ============================================================================
|
|
107
|
+
|
|
108
|
+
MODELS: Dict[str, Dict[str, ModelInfo]] = {
|
|
109
|
+
# =========================================================================
|
|
110
|
+
# ANTHROPIC
|
|
111
|
+
# =========================================================================
|
|
112
|
+
"anthropic": {
|
|
113
|
+
"claude-opus-4-5-20251101": ModelInfo(
|
|
114
|
+
id="claude-opus-4-5-20251101",
|
|
115
|
+
name="Claude Opus 4.5",
|
|
116
|
+
provider="anthropic",
|
|
117
|
+
input_price=15.0,
|
|
118
|
+
output_price=75.0,
|
|
119
|
+
context_window=200000,
|
|
120
|
+
max_output=8192,
|
|
121
|
+
capabilities=[
|
|
122
|
+
ModelCapability.TOOLS,
|
|
123
|
+
ModelCapability.VISION,
|
|
124
|
+
ModelCapability.STREAMING,
|
|
125
|
+
ModelCapability.JSON_MODE,
|
|
126
|
+
ModelCapability.REASONING,
|
|
127
|
+
ModelCapability.CODE,
|
|
128
|
+
ModelCapability.LONG_CONTEXT,
|
|
129
|
+
],
|
|
130
|
+
description="Most capable Claude model - latest flagship",
|
|
131
|
+
recommended_for=["complex reasoning", "research", "difficult coding"],
|
|
132
|
+
released="2025-11",
|
|
133
|
+
),
|
|
134
|
+
"claude-sonnet-4-5-20250929": ModelInfo(
|
|
135
|
+
id="claude-sonnet-4-5-20250929",
|
|
136
|
+
name="Claude Sonnet 4.5",
|
|
137
|
+
provider="anthropic",
|
|
138
|
+
input_price=3.0,
|
|
139
|
+
output_price=15.0,
|
|
140
|
+
context_window=200000,
|
|
141
|
+
max_output=8192,
|
|
142
|
+
capabilities=[
|
|
143
|
+
ModelCapability.TOOLS,
|
|
144
|
+
ModelCapability.VISION,
|
|
145
|
+
ModelCapability.STREAMING,
|
|
146
|
+
ModelCapability.JSON_MODE,
|
|
147
|
+
ModelCapability.CODE,
|
|
148
|
+
ModelCapability.LONG_CONTEXT,
|
|
149
|
+
],
|
|
150
|
+
description="Best balance of intelligence and speed",
|
|
151
|
+
recommended_for=["coding", "analysis", "general"],
|
|
152
|
+
released="2025-09",
|
|
153
|
+
),
|
|
154
|
+
"claude-haiku-4-5-20251001": ModelInfo(
|
|
155
|
+
id="claude-haiku-4-5-20251001",
|
|
156
|
+
name="Claude Haiku 4.5",
|
|
157
|
+
provider="anthropic",
|
|
158
|
+
input_price=0.25,
|
|
159
|
+
output_price=1.25,
|
|
160
|
+
context_window=200000,
|
|
161
|
+
max_output=8192,
|
|
162
|
+
capabilities=[
|
|
163
|
+
ModelCapability.TOOLS,
|
|
164
|
+
ModelCapability.VISION,
|
|
165
|
+
ModelCapability.STREAMING,
|
|
166
|
+
ModelCapability.JSON_MODE,
|
|
167
|
+
ModelCapability.LONG_CONTEXT,
|
|
168
|
+
],
|
|
169
|
+
description="Fastest and most cost-effective",
|
|
170
|
+
recommended_for=["quick tasks", "high volume"],
|
|
171
|
+
released="2025-10",
|
|
172
|
+
),
|
|
173
|
+
"claude-sonnet-4-20250514": ModelInfo(
|
|
174
|
+
id="claude-sonnet-4-20250514",
|
|
175
|
+
name="Claude Sonnet 4",
|
|
176
|
+
provider="anthropic",
|
|
177
|
+
input_price=3.0,
|
|
178
|
+
output_price=15.0,
|
|
179
|
+
context_window=200000,
|
|
180
|
+
max_output=8192,
|
|
181
|
+
capabilities=[
|
|
182
|
+
ModelCapability.TOOLS,
|
|
183
|
+
ModelCapability.VISION,
|
|
184
|
+
ModelCapability.STREAMING,
|
|
185
|
+
ModelCapability.JSON_MODE,
|
|
186
|
+
ModelCapability.CODE,
|
|
187
|
+
ModelCapability.LONG_CONTEXT,
|
|
188
|
+
],
|
|
189
|
+
description="Previous Sonnet generation",
|
|
190
|
+
recommended_for=["coding", "analysis", "general"],
|
|
191
|
+
released="2025-05",
|
|
192
|
+
),
|
|
193
|
+
"claude-opus-4-20250514": ModelInfo(
|
|
194
|
+
id="claude-opus-4-20250514",
|
|
195
|
+
name="Claude Opus 4",
|
|
196
|
+
provider="anthropic",
|
|
197
|
+
input_price=15.0,
|
|
198
|
+
output_price=75.0,
|
|
199
|
+
context_window=200000,
|
|
200
|
+
max_output=8192,
|
|
201
|
+
capabilities=[
|
|
202
|
+
ModelCapability.TOOLS,
|
|
203
|
+
ModelCapability.VISION,
|
|
204
|
+
ModelCapability.STREAMING,
|
|
205
|
+
ModelCapability.JSON_MODE,
|
|
206
|
+
ModelCapability.REASONING,
|
|
207
|
+
ModelCapability.CODE,
|
|
208
|
+
ModelCapability.LONG_CONTEXT,
|
|
209
|
+
],
|
|
210
|
+
description="Previous Opus generation",
|
|
211
|
+
recommended_for=["complex reasoning", "research", "difficult coding"],
|
|
212
|
+
released="2025-05",
|
|
213
|
+
),
|
|
214
|
+
"claude-haiku-4-20250514": ModelInfo(
|
|
215
|
+
id="claude-haiku-4-20250514",
|
|
216
|
+
name="Claude Haiku 4",
|
|
217
|
+
provider="anthropic",
|
|
218
|
+
input_price=0.25,
|
|
219
|
+
output_price=1.25,
|
|
220
|
+
context_window=200000,
|
|
221
|
+
max_output=8192,
|
|
222
|
+
capabilities=[
|
|
223
|
+
ModelCapability.TOOLS,
|
|
224
|
+
ModelCapability.VISION,
|
|
225
|
+
ModelCapability.STREAMING,
|
|
226
|
+
ModelCapability.JSON_MODE,
|
|
227
|
+
ModelCapability.LONG_CONTEXT,
|
|
228
|
+
],
|
|
229
|
+
description="Previous Haiku generation",
|
|
230
|
+
recommended_for=["quick tasks", "high volume"],
|
|
231
|
+
released="2025-05",
|
|
232
|
+
),
|
|
233
|
+
},
|
|
234
|
+
# =========================================================================
|
|
235
|
+
# OPENAI
|
|
236
|
+
# =========================================================================
|
|
237
|
+
"openai": {
|
|
238
|
+
"gpt-5.2": ModelInfo(
|
|
239
|
+
id="gpt-5.2",
|
|
240
|
+
name="GPT-5.2",
|
|
241
|
+
provider="openai",
|
|
242
|
+
input_price=5.0,
|
|
243
|
+
output_price=20.0,
|
|
244
|
+
context_window=256000,
|
|
245
|
+
max_output=32768,
|
|
246
|
+
capabilities=[
|
|
247
|
+
ModelCapability.TOOLS,
|
|
248
|
+
ModelCapability.VISION,
|
|
249
|
+
ModelCapability.STREAMING,
|
|
250
|
+
ModelCapability.JSON_MODE,
|
|
251
|
+
ModelCapability.REASONING,
|
|
252
|
+
ModelCapability.CODE,
|
|
253
|
+
ModelCapability.LONG_CONTEXT,
|
|
254
|
+
],
|
|
255
|
+
description="Latest GPT-5 flagship with reasoning",
|
|
256
|
+
recommended_for=["complex reasoning", "coding", "research"],
|
|
257
|
+
released="2025-12",
|
|
258
|
+
),
|
|
259
|
+
"gpt-5.2-pro": ModelInfo(
|
|
260
|
+
id="gpt-5.2-pro",
|
|
261
|
+
name="GPT-5.2 Pro",
|
|
262
|
+
provider="openai",
|
|
263
|
+
input_price=6.0,
|
|
264
|
+
output_price=24.0,
|
|
265
|
+
context_window=256000,
|
|
266
|
+
max_output=32768,
|
|
267
|
+
capabilities=[
|
|
268
|
+
ModelCapability.TOOLS,
|
|
269
|
+
ModelCapability.VISION,
|
|
270
|
+
ModelCapability.STREAMING,
|
|
271
|
+
ModelCapability.JSON_MODE,
|
|
272
|
+
ModelCapability.REASONING,
|
|
273
|
+
ModelCapability.CODE,
|
|
274
|
+
ModelCapability.LONG_CONTEXT,
|
|
275
|
+
],
|
|
276
|
+
description="GPT-5.2 Pro variant - enhanced capabilities",
|
|
277
|
+
recommended_for=["complex reasoning", "coding", "research"],
|
|
278
|
+
released="2025-12",
|
|
279
|
+
),
|
|
280
|
+
"gpt-5.2-codex": ModelInfo(
|
|
281
|
+
id="gpt-5.2-codex",
|
|
282
|
+
name="GPT-5.2 Codex",
|
|
283
|
+
provider="openai",
|
|
284
|
+
input_price=5.5,
|
|
285
|
+
output_price=22.0,
|
|
286
|
+
context_window=256000,
|
|
287
|
+
max_output=32768,
|
|
288
|
+
capabilities=[
|
|
289
|
+
ModelCapability.TOOLS,
|
|
290
|
+
ModelCapability.VISION,
|
|
291
|
+
ModelCapability.STREAMING,
|
|
292
|
+
ModelCapability.JSON_MODE,
|
|
293
|
+
ModelCapability.REASONING,
|
|
294
|
+
ModelCapability.CODE,
|
|
295
|
+
ModelCapability.LONG_CONTEXT,
|
|
296
|
+
],
|
|
297
|
+
description="GPT-5.2 Codex variant - optimized for code",
|
|
298
|
+
recommended_for=["coding", "code generation", "code review"],
|
|
299
|
+
released="2025-12",
|
|
300
|
+
),
|
|
301
|
+
"gpt-5.1": ModelInfo(
|
|
302
|
+
id="gpt-5.1",
|
|
303
|
+
name="GPT-5.1",
|
|
304
|
+
provider="openai",
|
|
305
|
+
input_price=4.0,
|
|
306
|
+
output_price=16.0,
|
|
307
|
+
context_window=200000,
|
|
308
|
+
max_output=32768,
|
|
309
|
+
capabilities=[
|
|
310
|
+
ModelCapability.TOOLS,
|
|
311
|
+
ModelCapability.VISION,
|
|
312
|
+
ModelCapability.STREAMING,
|
|
313
|
+
ModelCapability.JSON_MODE,
|
|
314
|
+
ModelCapability.REASONING,
|
|
315
|
+
ModelCapability.CODE,
|
|
316
|
+
ModelCapability.LONG_CONTEXT,
|
|
317
|
+
],
|
|
318
|
+
description="GPT-5 series - highly capable",
|
|
319
|
+
recommended_for=["general", "coding", "analysis"],
|
|
320
|
+
released="2025-11",
|
|
321
|
+
),
|
|
322
|
+
"gpt-5.1-codex": ModelInfo(
|
|
323
|
+
id="gpt-5.1-codex",
|
|
324
|
+
name="GPT-5.1 Codex",
|
|
325
|
+
provider="openai",
|
|
326
|
+
input_price=4.5,
|
|
327
|
+
output_price=18.0,
|
|
328
|
+
context_window=200000,
|
|
329
|
+
max_output=32768,
|
|
330
|
+
capabilities=[
|
|
331
|
+
ModelCapability.TOOLS,
|
|
332
|
+
ModelCapability.VISION,
|
|
333
|
+
ModelCapability.STREAMING,
|
|
334
|
+
ModelCapability.JSON_MODE,
|
|
335
|
+
ModelCapability.REASONING,
|
|
336
|
+
ModelCapability.CODE,
|
|
337
|
+
ModelCapability.LONG_CONTEXT,
|
|
338
|
+
],
|
|
339
|
+
description="GPT-5.1 Codex variant - optimized for code",
|
|
340
|
+
recommended_for=["coding", "code generation"],
|
|
341
|
+
released="2025-11",
|
|
342
|
+
),
|
|
343
|
+
"gpt-5.1-codex-mini": ModelInfo(
|
|
344
|
+
id="gpt-5.1-codex-mini",
|
|
345
|
+
name="GPT-5.1 Codex Mini",
|
|
346
|
+
provider="openai",
|
|
347
|
+
input_price=2.0,
|
|
348
|
+
output_price=8.0,
|
|
349
|
+
context_window=200000,
|
|
350
|
+
max_output=16384,
|
|
351
|
+
capabilities=[
|
|
352
|
+
ModelCapability.TOOLS,
|
|
353
|
+
ModelCapability.VISION,
|
|
354
|
+
ModelCapability.STREAMING,
|
|
355
|
+
ModelCapability.JSON_MODE,
|
|
356
|
+
ModelCapability.CODE,
|
|
357
|
+
ModelCapability.LONG_CONTEXT,
|
|
358
|
+
],
|
|
359
|
+
description="GPT-5.1 Codex Mini - fast and efficient for code",
|
|
360
|
+
recommended_for=["quick coding", "code completion"],
|
|
361
|
+
released="2025-11",
|
|
362
|
+
),
|
|
363
|
+
"gpt-4o-2024-11-20": ModelInfo(
|
|
364
|
+
id="gpt-4o-2024-11-20",
|
|
365
|
+
name="GPT-4o (Nov 2024)",
|
|
366
|
+
provider="openai",
|
|
367
|
+
input_price=2.50,
|
|
368
|
+
output_price=10.0,
|
|
369
|
+
context_window=128000,
|
|
370
|
+
max_output=16384,
|
|
371
|
+
capabilities=[
|
|
372
|
+
ModelCapability.TOOLS,
|
|
373
|
+
ModelCapability.VISION,
|
|
374
|
+
ModelCapability.STREAMING,
|
|
375
|
+
ModelCapability.JSON_MODE,
|
|
376
|
+
ModelCapability.CODE,
|
|
377
|
+
ModelCapability.LONG_CONTEXT,
|
|
378
|
+
],
|
|
379
|
+
description="GPT-4o latest stable version",
|
|
380
|
+
recommended_for=["general", "coding", "vision"],
|
|
381
|
+
released="2024-11",
|
|
382
|
+
),
|
|
383
|
+
"gpt-4o": ModelInfo(
|
|
384
|
+
id="gpt-4o",
|
|
385
|
+
name="GPT-4o",
|
|
386
|
+
provider="openai",
|
|
387
|
+
input_price=2.50,
|
|
388
|
+
output_price=10.0,
|
|
389
|
+
context_window=128000,
|
|
390
|
+
max_output=16384,
|
|
391
|
+
capabilities=[
|
|
392
|
+
ModelCapability.TOOLS,
|
|
393
|
+
ModelCapability.VISION,
|
|
394
|
+
ModelCapability.STREAMING,
|
|
395
|
+
ModelCapability.JSON_MODE,
|
|
396
|
+
ModelCapability.CODE,
|
|
397
|
+
ModelCapability.LONG_CONTEXT,
|
|
398
|
+
],
|
|
399
|
+
description="Most capable GPT-4 variant",
|
|
400
|
+
recommended_for=["general", "coding", "vision"],
|
|
401
|
+
released="2024-05",
|
|
402
|
+
),
|
|
403
|
+
"gpt-4o-mini": ModelInfo(
|
|
404
|
+
id="gpt-4o-mini",
|
|
405
|
+
name="GPT-4o Mini",
|
|
406
|
+
provider="openai",
|
|
407
|
+
input_price=0.15,
|
|
408
|
+
output_price=0.60,
|
|
409
|
+
context_window=128000,
|
|
410
|
+
max_output=16384,
|
|
411
|
+
capabilities=[
|
|
412
|
+
ModelCapability.TOOLS,
|
|
413
|
+
ModelCapability.VISION,
|
|
414
|
+
ModelCapability.STREAMING,
|
|
415
|
+
ModelCapability.JSON_MODE,
|
|
416
|
+
ModelCapability.LONG_CONTEXT,
|
|
417
|
+
],
|
|
418
|
+
description="Fast and cost-effective",
|
|
419
|
+
recommended_for=["quick tasks", "high volume"],
|
|
420
|
+
released="2024-07",
|
|
421
|
+
),
|
|
422
|
+
"o1": ModelInfo(
|
|
423
|
+
id="o1",
|
|
424
|
+
name="o1",
|
|
425
|
+
provider="openai",
|
|
426
|
+
input_price=15.0,
|
|
427
|
+
output_price=60.0,
|
|
428
|
+
context_window=200000,
|
|
429
|
+
max_output=100000,
|
|
430
|
+
capabilities=[
|
|
431
|
+
ModelCapability.REASONING,
|
|
432
|
+
ModelCapability.CODE,
|
|
433
|
+
ModelCapability.LONG_CONTEXT,
|
|
434
|
+
],
|
|
435
|
+
description="Advanced reasoning model",
|
|
436
|
+
recommended_for=["complex reasoning", "math", "science"],
|
|
437
|
+
released="2024-09",
|
|
438
|
+
),
|
|
439
|
+
"o1-mini": ModelInfo(
|
|
440
|
+
id="o1-mini",
|
|
441
|
+
name="o1-mini",
|
|
442
|
+
provider="openai",
|
|
443
|
+
input_price=3.0,
|
|
444
|
+
output_price=12.0,
|
|
445
|
+
context_window=128000,
|
|
446
|
+
max_output=65536,
|
|
447
|
+
capabilities=[
|
|
448
|
+
ModelCapability.REASONING,
|
|
449
|
+
ModelCapability.CODE,
|
|
450
|
+
ModelCapability.LONG_CONTEXT,
|
|
451
|
+
],
|
|
452
|
+
description="Smaller reasoning model",
|
|
453
|
+
recommended_for=["coding", "math"],
|
|
454
|
+
released="2024-09",
|
|
455
|
+
),
|
|
456
|
+
},
|
|
457
|
+
# =========================================================================
|
|
458
|
+
# GOOGLE
|
|
459
|
+
# =========================================================================
|
|
460
|
+
"google": {
|
|
461
|
+
"gemini-3-pro-preview": ModelInfo(
|
|
462
|
+
id="gemini-3-pro-preview",
|
|
463
|
+
name="Gemini 3 Pro Preview",
|
|
464
|
+
provider="google",
|
|
465
|
+
input_price=2.0,
|
|
466
|
+
output_price=8.0,
|
|
467
|
+
context_window=2000000,
|
|
468
|
+
max_output=16384,
|
|
469
|
+
capabilities=[
|
|
470
|
+
ModelCapability.TOOLS,
|
|
471
|
+
ModelCapability.VISION,
|
|
472
|
+
ModelCapability.STREAMING,
|
|
473
|
+
ModelCapability.JSON_MODE,
|
|
474
|
+
ModelCapability.REASONING,
|
|
475
|
+
ModelCapability.CODE,
|
|
476
|
+
ModelCapability.LONG_CONTEXT,
|
|
477
|
+
],
|
|
478
|
+
description="Latest Gemini 3 flagship - most capable (2M context)",
|
|
479
|
+
recommended_for=["complex reasoning", "large codebases", "research"],
|
|
480
|
+
released="2025-12",
|
|
481
|
+
),
|
|
482
|
+
"gemini-3-flash-preview": ModelInfo(
|
|
483
|
+
id="gemini-3-flash-preview",
|
|
484
|
+
name="Gemini 3 Flash Preview",
|
|
485
|
+
provider="google",
|
|
486
|
+
input_price=0.15,
|
|
487
|
+
output_price=0.60,
|
|
488
|
+
context_window=1000000,
|
|
489
|
+
max_output=8192,
|
|
490
|
+
capabilities=[
|
|
491
|
+
ModelCapability.TOOLS,
|
|
492
|
+
ModelCapability.VISION,
|
|
493
|
+
ModelCapability.STREAMING,
|
|
494
|
+
ModelCapability.JSON_MODE,
|
|
495
|
+
ModelCapability.CODE,
|
|
496
|
+
ModelCapability.LONG_CONTEXT,
|
|
497
|
+
],
|
|
498
|
+
description="Gemini 3 fast model - 1M context (Latest)",
|
|
499
|
+
recommended_for=["quick tasks", "high volume", "coding"],
|
|
500
|
+
released="2025-12",
|
|
501
|
+
),
|
|
502
|
+
"gemini-2.5-pro": ModelInfo(
|
|
503
|
+
id="gemini-2.5-pro",
|
|
504
|
+
name="Gemini 2.5 Pro",
|
|
505
|
+
provider="google",
|
|
506
|
+
input_price=1.25,
|
|
507
|
+
output_price=5.0,
|
|
508
|
+
context_window=2000000,
|
|
509
|
+
max_output=8192,
|
|
510
|
+
capabilities=[
|
|
511
|
+
ModelCapability.TOOLS,
|
|
512
|
+
ModelCapability.VISION,
|
|
513
|
+
ModelCapability.STREAMING,
|
|
514
|
+
ModelCapability.JSON_MODE,
|
|
515
|
+
ModelCapability.REASONING,
|
|
516
|
+
ModelCapability.CODE,
|
|
517
|
+
ModelCapability.LONG_CONTEXT,
|
|
518
|
+
],
|
|
519
|
+
description="Gemini 2.5 Pro with 2M context",
|
|
520
|
+
recommended_for=["large codebases", "long documents"],
|
|
521
|
+
released="2025-01",
|
|
522
|
+
),
|
|
523
|
+
"gemini-2.5-flash": ModelInfo(
|
|
524
|
+
id="gemini-2.5-flash",
|
|
525
|
+
name="Gemini 2.5 Flash",
|
|
526
|
+
provider="google",
|
|
527
|
+
input_price=0.075,
|
|
528
|
+
output_price=0.30,
|
|
529
|
+
context_window=1000000,
|
|
530
|
+
max_output=8192,
|
|
531
|
+
capabilities=[
|
|
532
|
+
ModelCapability.TOOLS,
|
|
533
|
+
ModelCapability.VISION,
|
|
534
|
+
ModelCapability.STREAMING,
|
|
535
|
+
ModelCapability.JSON_MODE,
|
|
536
|
+
ModelCapability.CODE,
|
|
537
|
+
ModelCapability.LONG_CONTEXT,
|
|
538
|
+
],
|
|
539
|
+
description="Fast and efficient with 1M context",
|
|
540
|
+
recommended_for=["quick tasks", "high volume"],
|
|
541
|
+
released="2025-01",
|
|
542
|
+
),
|
|
543
|
+
"gemini-2.0-flash": ModelInfo(
|
|
544
|
+
id="gemini-2.0-flash",
|
|
545
|
+
name="Gemini 2.0 Flash",
|
|
546
|
+
provider="google",
|
|
547
|
+
input_price=0.10,
|
|
548
|
+
output_price=0.40,
|
|
549
|
+
context_window=1000000,
|
|
550
|
+
max_output=8192,
|
|
551
|
+
capabilities=[
|
|
552
|
+
ModelCapability.TOOLS,
|
|
553
|
+
ModelCapability.VISION,
|
|
554
|
+
ModelCapability.STREAMING,
|
|
555
|
+
ModelCapability.JSON_MODE,
|
|
556
|
+
ModelCapability.CODE,
|
|
557
|
+
ModelCapability.LONG_CONTEXT,
|
|
558
|
+
],
|
|
559
|
+
description="Previous Flash generation",
|
|
560
|
+
recommended_for=["general tasks"],
|
|
561
|
+
released="2024-12",
|
|
562
|
+
),
|
|
563
|
+
},
|
|
564
|
+
# =========================================================================
|
|
565
|
+
# DEEPSEEK
|
|
566
|
+
# =========================================================================
|
|
567
|
+
"deepseek": {
|
|
568
|
+
"deepseek-ai/DeepSeek-V3.2": ModelInfo(
|
|
569
|
+
id="deepseek-ai/DeepSeek-V3.2",
|
|
570
|
+
name="DeepSeek V3.2",
|
|
571
|
+
provider="deepseek",
|
|
572
|
+
input_price=0.27,
|
|
573
|
+
output_price=1.10,
|
|
574
|
+
context_window=128000,
|
|
575
|
+
max_output=16384,
|
|
576
|
+
capabilities=[
|
|
577
|
+
ModelCapability.TOOLS,
|
|
578
|
+
ModelCapability.STREAMING,
|
|
579
|
+
ModelCapability.JSON_MODE,
|
|
580
|
+
ModelCapability.REASONING,
|
|
581
|
+
ModelCapability.CODE,
|
|
582
|
+
ModelCapability.LONG_CONTEXT,
|
|
583
|
+
],
|
|
584
|
+
description="Latest DeepSeek V3.2 - most capable",
|
|
585
|
+
recommended_for=["complex reasoning", "coding", "research"],
|
|
586
|
+
released="2025-12",
|
|
587
|
+
),
|
|
588
|
+
"deepseek-ai/DeepSeek-R1": ModelInfo(
|
|
589
|
+
id="deepseek-ai/DeepSeek-R1",
|
|
590
|
+
name="DeepSeek R1",
|
|
591
|
+
provider="deepseek",
|
|
592
|
+
input_price=0.55,
|
|
593
|
+
output_price=2.19,
|
|
594
|
+
context_window=64000,
|
|
595
|
+
max_output=8192,
|
|
596
|
+
capabilities=[
|
|
597
|
+
ModelCapability.STREAMING,
|
|
598
|
+
ModelCapability.REASONING,
|
|
599
|
+
ModelCapability.CODE,
|
|
600
|
+
],
|
|
601
|
+
description="Advanced reasoning model - R1 series",
|
|
602
|
+
recommended_for=["complex reasoning", "math", "coding"],
|
|
603
|
+
released="2025-01",
|
|
604
|
+
),
|
|
605
|
+
"deepseek-chat": ModelInfo(
|
|
606
|
+
id="deepseek-chat",
|
|
607
|
+
name="DeepSeek Chat (V3)",
|
|
608
|
+
provider="deepseek",
|
|
609
|
+
input_price=0.14,
|
|
610
|
+
output_price=0.28,
|
|
611
|
+
context_window=64000,
|
|
612
|
+
max_output=8192,
|
|
613
|
+
capabilities=[
|
|
614
|
+
ModelCapability.TOOLS,
|
|
615
|
+
ModelCapability.STREAMING,
|
|
616
|
+
ModelCapability.JSON_MODE,
|
|
617
|
+
ModelCapability.CODE,
|
|
618
|
+
],
|
|
619
|
+
description="Very cost-effective general model",
|
|
620
|
+
recommended_for=["general", "budget-conscious"],
|
|
621
|
+
released="2024-12",
|
|
622
|
+
),
|
|
623
|
+
"deepseek-coder": ModelInfo(
|
|
624
|
+
id="deepseek-coder",
|
|
625
|
+
name="DeepSeek Coder",
|
|
626
|
+
provider="deepseek",
|
|
627
|
+
input_price=0.14,
|
|
628
|
+
output_price=0.28,
|
|
629
|
+
context_window=64000,
|
|
630
|
+
max_output=8192,
|
|
631
|
+
capabilities=[
|
|
632
|
+
ModelCapability.TOOLS,
|
|
633
|
+
ModelCapability.STREAMING,
|
|
634
|
+
ModelCapability.JSON_MODE,
|
|
635
|
+
ModelCapability.CODE,
|
|
636
|
+
],
|
|
637
|
+
description="Specialized for coding tasks",
|
|
638
|
+
recommended_for=["coding", "code review"],
|
|
639
|
+
released="2024-12",
|
|
640
|
+
),
|
|
641
|
+
"deepseek-reasoner": ModelInfo(
|
|
642
|
+
id="deepseek-reasoner",
|
|
643
|
+
name="DeepSeek Reasoner",
|
|
644
|
+
provider="deepseek",
|
|
645
|
+
input_price=0.55,
|
|
646
|
+
output_price=2.19,
|
|
647
|
+
context_window=64000,
|
|
648
|
+
max_output=8192,
|
|
649
|
+
capabilities=[
|
|
650
|
+
ModelCapability.STREAMING,
|
|
651
|
+
ModelCapability.REASONING,
|
|
652
|
+
ModelCapability.CODE,
|
|
653
|
+
],
|
|
654
|
+
description="Advanced reasoning model",
|
|
655
|
+
recommended_for=["complex reasoning", "math"],
|
|
656
|
+
released="2025-01",
|
|
657
|
+
),
|
|
658
|
+
},
|
|
659
|
+
# =========================================================================
|
|
660
|
+
# GROQ
|
|
661
|
+
# =========================================================================
|
|
662
|
+
"groq": {
|
|
663
|
+
"llama-3.3-70b-versatile": ModelInfo(
|
|
664
|
+
id="llama-3.3-70b-versatile",
|
|
665
|
+
name="Llama 3.3 70B",
|
|
666
|
+
provider="groq",
|
|
667
|
+
input_price=0.59,
|
|
668
|
+
output_price=0.79,
|
|
669
|
+
context_window=128000,
|
|
670
|
+
max_output=32768,
|
|
671
|
+
capabilities=[
|
|
672
|
+
ModelCapability.TOOLS,
|
|
673
|
+
ModelCapability.STREAMING,
|
|
674
|
+
ModelCapability.JSON_MODE,
|
|
675
|
+
ModelCapability.CODE,
|
|
676
|
+
ModelCapability.LONG_CONTEXT,
|
|
677
|
+
],
|
|
678
|
+
description="Very fast inference via Groq LPU",
|
|
679
|
+
recommended_for=["speed-critical", "coding"],
|
|
680
|
+
released="2024-12",
|
|
681
|
+
),
|
|
682
|
+
"llama-3.1-8b-instant": ModelInfo(
|
|
683
|
+
id="llama-3.1-8b-instant",
|
|
684
|
+
name="Llama 3.1 8B Instant",
|
|
685
|
+
provider="groq",
|
|
686
|
+
input_price=0.05,
|
|
687
|
+
output_price=0.08,
|
|
688
|
+
context_window=128000,
|
|
689
|
+
max_output=8192,
|
|
690
|
+
capabilities=[
|
|
691
|
+
ModelCapability.TOOLS,
|
|
692
|
+
ModelCapability.STREAMING,
|
|
693
|
+
ModelCapability.LONG_CONTEXT,
|
|
694
|
+
],
|
|
695
|
+
description="Ultra-fast small model",
|
|
696
|
+
recommended_for=["quick tasks", "prototyping"],
|
|
697
|
+
released="2024-07",
|
|
698
|
+
),
|
|
699
|
+
},
|
|
700
|
+
# =========================================================================
|
|
701
|
+
# OPENROUTER
|
|
702
|
+
# =========================================================================
|
|
703
|
+
"openrouter": {
|
|
704
|
+
"anthropic/claude-sonnet-4": ModelInfo(
|
|
705
|
+
id="anthropic/claude-sonnet-4",
|
|
706
|
+
name="Claude Sonnet 4 (via OpenRouter)",
|
|
707
|
+
provider="openrouter",
|
|
708
|
+
input_price=3.0,
|
|
709
|
+
output_price=15.0,
|
|
710
|
+
context_window=200000,
|
|
711
|
+
max_output=8192,
|
|
712
|
+
capabilities=[
|
|
713
|
+
ModelCapability.TOOLS,
|
|
714
|
+
ModelCapability.VISION,
|
|
715
|
+
ModelCapability.STREAMING,
|
|
716
|
+
ModelCapability.CODE,
|
|
717
|
+
ModelCapability.LONG_CONTEXT,
|
|
718
|
+
],
|
|
719
|
+
description="Claude via OpenRouter",
|
|
720
|
+
recommended_for=["coding", "general"],
|
|
721
|
+
),
|
|
722
|
+
"openai/gpt-4o": ModelInfo(
|
|
723
|
+
id="openai/gpt-4o",
|
|
724
|
+
name="GPT-4o (via OpenRouter)",
|
|
725
|
+
provider="openrouter",
|
|
726
|
+
input_price=2.50,
|
|
727
|
+
output_price=10.0,
|
|
728
|
+
context_window=128000,
|
|
729
|
+
max_output=16384,
|
|
730
|
+
capabilities=[
|
|
731
|
+
ModelCapability.TOOLS,
|
|
732
|
+
ModelCapability.VISION,
|
|
733
|
+
ModelCapability.STREAMING,
|
|
734
|
+
ModelCapability.CODE,
|
|
735
|
+
ModelCapability.LONG_CONTEXT,
|
|
736
|
+
],
|
|
737
|
+
description="GPT-4o via OpenRouter",
|
|
738
|
+
recommended_for=["general", "coding"],
|
|
739
|
+
),
|
|
740
|
+
"google/gemini-2.0-flash": ModelInfo(
|
|
741
|
+
id="google/gemini-2.0-flash",
|
|
742
|
+
name="Gemini 2.0 Flash (via OpenRouter)",
|
|
743
|
+
provider="openrouter",
|
|
744
|
+
input_price=0.10,
|
|
745
|
+
output_price=0.40,
|
|
746
|
+
context_window=1000000,
|
|
747
|
+
max_output=8192,
|
|
748
|
+
capabilities=[
|
|
749
|
+
ModelCapability.TOOLS,
|
|
750
|
+
ModelCapability.VISION,
|
|
751
|
+
ModelCapability.STREAMING,
|
|
752
|
+
ModelCapability.LONG_CONTEXT,
|
|
753
|
+
],
|
|
754
|
+
description="Gemini via OpenRouter",
|
|
755
|
+
recommended_for=["long context"],
|
|
756
|
+
),
|
|
757
|
+
},
|
|
758
|
+
# =========================================================================
|
|
759
|
+
# OLLAMA (Local - Free)
|
|
760
|
+
# =========================================================================
|
|
761
|
+
"ollama": {
|
|
762
|
+
"llama3.2:3b": ModelInfo(
|
|
763
|
+
id="llama3.2:3b",
|
|
764
|
+
name="Llama 3.2 3B",
|
|
765
|
+
provider="ollama",
|
|
766
|
+
input_price=0.0,
|
|
767
|
+
output_price=0.0,
|
|
768
|
+
context_window=128000,
|
|
769
|
+
max_output=4096,
|
|
770
|
+
capabilities=[
|
|
771
|
+
ModelCapability.STREAMING,
|
|
772
|
+
],
|
|
773
|
+
description="Small local model",
|
|
774
|
+
recommended_for=["quick local tasks"],
|
|
775
|
+
),
|
|
776
|
+
"qwen2.5-coder:7b": ModelInfo(
|
|
777
|
+
id="qwen2.5-coder:7b",
|
|
778
|
+
name="Qwen 2.5 Coder 7B",
|
|
779
|
+
provider="ollama",
|
|
780
|
+
input_price=0.0,
|
|
781
|
+
output_price=0.0,
|
|
782
|
+
context_window=32000,
|
|
783
|
+
max_output=4096,
|
|
784
|
+
capabilities=[
|
|
785
|
+
ModelCapability.STREAMING,
|
|
786
|
+
ModelCapability.CODE,
|
|
787
|
+
],
|
|
788
|
+
description="Local coding model",
|
|
789
|
+
recommended_for=["local coding"],
|
|
790
|
+
),
|
|
791
|
+
"qwen2.5-coder:32b": ModelInfo(
|
|
792
|
+
id="qwen2.5-coder:32b",
|
|
793
|
+
name="Qwen 2.5 Coder 32B",
|
|
794
|
+
provider="ollama",
|
|
795
|
+
input_price=0.0,
|
|
796
|
+
output_price=0.0,
|
|
797
|
+
context_window=32000,
|
|
798
|
+
max_output=4096,
|
|
799
|
+
capabilities=[
|
|
800
|
+
ModelCapability.STREAMING,
|
|
801
|
+
ModelCapability.CODE,
|
|
802
|
+
],
|
|
803
|
+
description="Larger local coding model",
|
|
804
|
+
recommended_for=["local coding", "complex tasks"],
|
|
805
|
+
),
|
|
806
|
+
},
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
# ============================================================================
|
|
811
|
+
# LIVE DATA INTEGRATION (models.dev)
|
|
812
|
+
# ============================================================================
|
|
813
|
+
|
|
814
|
+
# Flag to track if live data is available
|
|
815
|
+
_live_models: Optional[Dict[str, Dict[str, ModelInfo]]] = None
|
|
816
|
+
_use_live_data: bool = False
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
def set_live_models(models: Dict[str, Dict[str, ModelInfo]]) -> None:
|
|
820
|
+
"""
|
|
821
|
+
Set live model data from models.dev.
|
|
822
|
+
|
|
823
|
+
Called by the models_dev module after fetching fresh data.
|
|
824
|
+
"""
|
|
825
|
+
global _live_models, _use_live_data
|
|
826
|
+
_live_models = models
|
|
827
|
+
_use_live_data = True
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
def get_effective_models() -> Dict[str, Dict[str, ModelInfo]]:
|
|
831
|
+
"""
|
|
832
|
+
Get the effective models database.
|
|
833
|
+
|
|
834
|
+
Returns live data if available, otherwise falls back to hardcoded MODELS.
|
|
835
|
+
"""
|
|
836
|
+
if _use_live_data and _live_models:
|
|
837
|
+
# Merge: live data takes precedence, but keep hardcoded for missing providers
|
|
838
|
+
merged = MODELS.copy()
|
|
839
|
+
for provider_id, models in _live_models.items():
|
|
840
|
+
if provider_id in merged:
|
|
841
|
+
# Merge models within provider (live takes precedence)
|
|
842
|
+
merged[provider_id] = {**merged[provider_id], **models}
|
|
843
|
+
else:
|
|
844
|
+
merged[provider_id] = models
|
|
845
|
+
return merged
|
|
846
|
+
return MODELS
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
# ============================================================================
|
|
850
|
+
# HELPER FUNCTIONS
|
|
851
|
+
# ============================================================================
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
def get_model_info(provider_id: str, model_id: str) -> Optional[ModelInfo]:
|
|
855
|
+
"""Get model info by provider and model ID."""
|
|
856
|
+
models = get_effective_models()
|
|
857
|
+
provider_models = models.get(provider_id, {})
|
|
858
|
+
|
|
859
|
+
# Try exact match first
|
|
860
|
+
if model_id in provider_models:
|
|
861
|
+
return provider_models[model_id]
|
|
862
|
+
|
|
863
|
+
# Try fuzzy match (partial ID match)
|
|
864
|
+
for mid, info in provider_models.items():
|
|
865
|
+
if model_id in mid or mid in model_id:
|
|
866
|
+
return info
|
|
867
|
+
|
|
868
|
+
return None
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
def get_models_for_provider(provider_id: str) -> Dict[str, ModelInfo]:
|
|
872
|
+
"""Get all models for a provider, filtered to ensure they belong to that provider."""
|
|
873
|
+
models = get_effective_models().get(provider_id, {})
|
|
874
|
+
|
|
875
|
+
# Filter models to ensure they actually belong to this provider
|
|
876
|
+
# This prevents models from other providers (e.g., GPT OSS) from appearing in Google's list
|
|
877
|
+
filtered = {}
|
|
878
|
+
for model_id, model_info in models.items():
|
|
879
|
+
# Ensure the model's provider field matches the requested provider
|
|
880
|
+
if model_info.provider == provider_id:
|
|
881
|
+
filtered[model_id] = model_info
|
|
882
|
+
# Special case for Google: only include Gemini models
|
|
883
|
+
elif provider_id == "google":
|
|
884
|
+
model_id_lower = model_id.lower()
|
|
885
|
+
model_name_lower = model_info.name.lower() if model_info.name else ""
|
|
886
|
+
# Only include if it's clearly a Gemini model
|
|
887
|
+
if (
|
|
888
|
+
("gemini" in model_id_lower or "gemini" in model_name_lower)
|
|
889
|
+
and "gpt" not in model_id_lower
|
|
890
|
+
and "gpt" not in model_name_lower
|
|
891
|
+
):
|
|
892
|
+
filtered[model_id] = model_info
|
|
893
|
+
|
|
894
|
+
return filtered
|
|
895
|
+
|
|
896
|
+
|
|
897
|
+
def get_all_models() -> List[ModelInfo]:
|
|
898
|
+
"""Get all models across all providers."""
|
|
899
|
+
all_models = []
|
|
900
|
+
for provider_models in get_effective_models().values():
|
|
901
|
+
all_models.extend(provider_models.values())
|
|
902
|
+
return all_models
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
def get_all_providers() -> List[str]:
|
|
906
|
+
"""Get all available provider IDs."""
|
|
907
|
+
return list(get_effective_models().keys())
|
|
908
|
+
|
|
909
|
+
|
|
910
|
+
def get_cheapest_models(limit: int = 5) -> List[ModelInfo]:
|
|
911
|
+
"""Get the cheapest models by input price."""
|
|
912
|
+
all_models = get_all_models()
|
|
913
|
+
sorted_models = sorted(all_models, key=lambda m: m.input_price)
|
|
914
|
+
return sorted_models[:limit]
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
def get_models_with_capability(capability: ModelCapability) -> List[ModelInfo]:
|
|
918
|
+
"""Get models that have a specific capability."""
|
|
919
|
+
return [m for m in get_all_models() if capability in m.capabilities]
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
def get_recommended_for_coding() -> List[ModelInfo]:
|
|
923
|
+
"""Get models recommended for coding."""
|
|
924
|
+
return [m for m in get_all_models() if "coding" in m.recommended_for or m.is_code_optimized]
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
def search_models(query: str, limit: int = 20) -> List[ModelInfo]:
|
|
928
|
+
"""
|
|
929
|
+
Search models by name, ID, or provider.
|
|
930
|
+
|
|
931
|
+
Args:
|
|
932
|
+
query: Search string (case-insensitive)
|
|
933
|
+
limit: Maximum results to return
|
|
934
|
+
"""
|
|
935
|
+
query_lower = query.lower()
|
|
936
|
+
results = []
|
|
937
|
+
|
|
938
|
+
for model in get_all_models():
|
|
939
|
+
score = 0
|
|
940
|
+
# Exact ID match
|
|
941
|
+
if query_lower == model.id.lower():
|
|
942
|
+
score = 100
|
|
943
|
+
# ID contains query
|
|
944
|
+
elif query_lower in model.id.lower():
|
|
945
|
+
score = 80
|
|
946
|
+
# Name contains query
|
|
947
|
+
elif query_lower in model.name.lower():
|
|
948
|
+
score = 60
|
|
949
|
+
# Provider contains query
|
|
950
|
+
elif query_lower in model.provider.lower():
|
|
951
|
+
score = 40
|
|
952
|
+
# Description contains query
|
|
953
|
+
elif model.description and query_lower in model.description.lower():
|
|
954
|
+
score = 20
|
|
955
|
+
|
|
956
|
+
if score > 0:
|
|
957
|
+
results.append((score, model))
|
|
958
|
+
|
|
959
|
+
# Sort by score descending, then by name
|
|
960
|
+
results.sort(key=lambda x: (-x[0], x[1].name))
|
|
961
|
+
return [model for _, model in results[:limit]]
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
def estimate_session_cost(
|
|
965
|
+
provider_id: str,
|
|
966
|
+
model_id: str,
|
|
967
|
+
input_tokens: int,
|
|
968
|
+
output_tokens: int,
|
|
969
|
+
) -> Tuple[float, str]:
|
|
970
|
+
"""
|
|
971
|
+
Estimate cost for a session.
|
|
972
|
+
|
|
973
|
+
Returns:
|
|
974
|
+
(cost, formatted_string)
|
|
975
|
+
"""
|
|
976
|
+
info = get_model_info(provider_id, model_id)
|
|
977
|
+
if info:
|
|
978
|
+
cost = info.estimate_cost(input_tokens, output_tokens)
|
|
979
|
+
return cost, f"${cost:.4f}"
|
|
980
|
+
return 0.0, "Unknown"
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
def is_using_live_data() -> bool:
|
|
984
|
+
"""Check if live models.dev data is being used."""
|
|
985
|
+
return _use_live_data and _live_models is not None
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
def get_data_source() -> str:
|
|
989
|
+
"""Get a description of the current data source."""
|
|
990
|
+
if is_using_live_data():
|
|
991
|
+
return "models.dev (live)"
|
|
992
|
+
return "built-in (offline)"
|
|
993
|
+
|
|
994
|
+
|
|
995
|
+
# ============================================================================
|
|
996
|
+
# EXPORTS
|
|
997
|
+
# ============================================================================
|
|
998
|
+
|
|
999
|
+
__all__ = [
|
|
1000
|
+
"ModelInfo",
|
|
1001
|
+
"ModelCapability",
|
|
1002
|
+
"MODELS",
|
|
1003
|
+
"get_model_info",
|
|
1004
|
+
"get_models_for_provider",
|
|
1005
|
+
"get_all_models",
|
|
1006
|
+
"get_all_providers",
|
|
1007
|
+
"get_cheapest_models",
|
|
1008
|
+
"get_models_with_capability",
|
|
1009
|
+
"get_recommended_for_coding",
|
|
1010
|
+
"search_models",
|
|
1011
|
+
"estimate_session_cost",
|
|
1012
|
+
"set_live_models",
|
|
1013
|
+
"get_effective_models",
|
|
1014
|
+
"is_using_live_data",
|
|
1015
|
+
"get_data_source",
|
|
1016
|
+
]
|