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,297 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SuperQode Provider Health Check - Check provider connectivity on startup.
|
|
3
|
+
|
|
4
|
+
Features:
|
|
5
|
+
- Async health checks for all configured providers
|
|
6
|
+
- Caching of results
|
|
7
|
+
- Status display
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
from superqode.providers.health import HealthChecker, get_health_checker
|
|
11
|
+
|
|
12
|
+
checker = get_health_checker()
|
|
13
|
+
results = await checker.check_all()
|
|
14
|
+
|
|
15
|
+
for provider_id, status in results.items():
|
|
16
|
+
print(f"{provider_id}: {status.status}")
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import asyncio
|
|
22
|
+
import os
|
|
23
|
+
from dataclasses import dataclass, field
|
|
24
|
+
from datetime import datetime, timedelta
|
|
25
|
+
from enum import Enum
|
|
26
|
+
from typing import Dict, List, Optional, Tuple
|
|
27
|
+
|
|
28
|
+
from superqode.providers.registry import PROVIDERS, ProviderDef
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# ============================================================================
|
|
32
|
+
# STATUS
|
|
33
|
+
# ============================================================================
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ProviderStatus(Enum):
|
|
37
|
+
"""Provider health status."""
|
|
38
|
+
|
|
39
|
+
UNKNOWN = "unknown"
|
|
40
|
+
READY = "ready"
|
|
41
|
+
NOT_CONFIGURED = "not_configured"
|
|
42
|
+
ERROR = "error"
|
|
43
|
+
RATE_LIMITED = "rate_limited"
|
|
44
|
+
AUTH_ERROR = "auth_error"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class HealthResult:
|
|
49
|
+
"""Health check result for a provider."""
|
|
50
|
+
|
|
51
|
+
provider_id: str
|
|
52
|
+
status: ProviderStatus
|
|
53
|
+
message: str = ""
|
|
54
|
+
latency_ms: float = 0.0
|
|
55
|
+
checked_at: datetime = field(default_factory=datetime.now)
|
|
56
|
+
model_available: str = ""
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def is_ready(self) -> bool:
|
|
60
|
+
return self.status == ProviderStatus.READY
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def status_icon(self) -> str:
|
|
64
|
+
icons = {
|
|
65
|
+
ProviderStatus.READY: "✓",
|
|
66
|
+
ProviderStatus.NOT_CONFIGURED: "○",
|
|
67
|
+
ProviderStatus.ERROR: "✗",
|
|
68
|
+
ProviderStatus.RATE_LIMITED: "⏳",
|
|
69
|
+
ProviderStatus.AUTH_ERROR: "🔐",
|
|
70
|
+
ProviderStatus.UNKNOWN: "?",
|
|
71
|
+
}
|
|
72
|
+
return icons.get(self.status, "?")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# ============================================================================
|
|
76
|
+
# HEALTH CHECKER
|
|
77
|
+
# ============================================================================
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class HealthChecker:
|
|
81
|
+
"""
|
|
82
|
+
Checks provider health/connectivity.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
CACHE_TTL = timedelta(minutes=5)
|
|
86
|
+
|
|
87
|
+
def __init__(self):
|
|
88
|
+
self._cache: Dict[str, HealthResult] = {}
|
|
89
|
+
self._checking: bool = False
|
|
90
|
+
|
|
91
|
+
async def check_all(self, force: bool = False) -> Dict[str, HealthResult]:
|
|
92
|
+
"""
|
|
93
|
+
Check all configured providers.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
force: Force refresh, ignore cache
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Dictionary of provider_id -> HealthResult
|
|
100
|
+
"""
|
|
101
|
+
if self._checking:
|
|
102
|
+
# Return cached results if check is in progress
|
|
103
|
+
return self._cache
|
|
104
|
+
|
|
105
|
+
self._checking = True
|
|
106
|
+
results = {}
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
# Get all providers that are configured (have env vars set)
|
|
110
|
+
configured_providers = []
|
|
111
|
+
|
|
112
|
+
for provider_id, provider_def in PROVIDERS.items():
|
|
113
|
+
result = self._check_configuration(provider_id, provider_def)
|
|
114
|
+
|
|
115
|
+
if result.status == ProviderStatus.NOT_CONFIGURED:
|
|
116
|
+
results[provider_id] = result
|
|
117
|
+
else:
|
|
118
|
+
configured_providers.append((provider_id, provider_def))
|
|
119
|
+
|
|
120
|
+
# For configured providers, check connectivity (in parallel)
|
|
121
|
+
if configured_providers:
|
|
122
|
+
tasks = [
|
|
123
|
+
self._check_provider(pid, pdef, force) for pid, pdef in configured_providers
|
|
124
|
+
]
|
|
125
|
+
check_results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
126
|
+
|
|
127
|
+
for (pid, _), result in zip(configured_providers, check_results):
|
|
128
|
+
if isinstance(result, Exception):
|
|
129
|
+
results[pid] = HealthResult(
|
|
130
|
+
provider_id=pid,
|
|
131
|
+
status=ProviderStatus.ERROR,
|
|
132
|
+
message=str(result),
|
|
133
|
+
)
|
|
134
|
+
else:
|
|
135
|
+
results[pid] = result
|
|
136
|
+
|
|
137
|
+
self._cache = results
|
|
138
|
+
|
|
139
|
+
finally:
|
|
140
|
+
self._checking = False
|
|
141
|
+
|
|
142
|
+
return results
|
|
143
|
+
|
|
144
|
+
async def check_provider(
|
|
145
|
+
self,
|
|
146
|
+
provider_id: str,
|
|
147
|
+
force: bool = False,
|
|
148
|
+
) -> HealthResult:
|
|
149
|
+
"""Check a specific provider."""
|
|
150
|
+
provider_def = PROVIDERS.get(provider_id)
|
|
151
|
+
if not provider_def:
|
|
152
|
+
return HealthResult(
|
|
153
|
+
provider_id=provider_id,
|
|
154
|
+
status=ProviderStatus.ERROR,
|
|
155
|
+
message="Provider not found",
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Check cache
|
|
159
|
+
if not force and provider_id in self._cache:
|
|
160
|
+
cached = self._cache[provider_id]
|
|
161
|
+
if datetime.now() - cached.checked_at < self.CACHE_TTL:
|
|
162
|
+
return cached
|
|
163
|
+
|
|
164
|
+
return await self._check_provider(provider_id, provider_def, force)
|
|
165
|
+
|
|
166
|
+
def _check_configuration(
|
|
167
|
+
self,
|
|
168
|
+
provider_id: str,
|
|
169
|
+
provider_def: ProviderDef,
|
|
170
|
+
) -> HealthResult:
|
|
171
|
+
"""Check if provider is configured (has API key)."""
|
|
172
|
+
# Local providers are always configured
|
|
173
|
+
if not provider_def.env_vars:
|
|
174
|
+
return HealthResult(
|
|
175
|
+
provider_id=provider_id,
|
|
176
|
+
status=ProviderStatus.UNKNOWN, # Need connectivity check
|
|
177
|
+
message="Local provider",
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# Check if any required env var is set
|
|
181
|
+
for env_var in provider_def.env_vars:
|
|
182
|
+
if os.environ.get(env_var):
|
|
183
|
+
return HealthResult(
|
|
184
|
+
provider_id=provider_id,
|
|
185
|
+
status=ProviderStatus.UNKNOWN, # Need connectivity check
|
|
186
|
+
message=f"Configured via {env_var}",
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
return HealthResult(
|
|
190
|
+
provider_id=provider_id,
|
|
191
|
+
status=ProviderStatus.NOT_CONFIGURED,
|
|
192
|
+
message=f"Set {provider_def.env_vars[0]} to enable",
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
async def _check_provider(
|
|
196
|
+
self,
|
|
197
|
+
provider_id: str,
|
|
198
|
+
provider_def: ProviderDef,
|
|
199
|
+
force: bool = False,
|
|
200
|
+
) -> HealthResult:
|
|
201
|
+
"""Actually check provider connectivity."""
|
|
202
|
+
import time
|
|
203
|
+
|
|
204
|
+
# Check cache
|
|
205
|
+
if not force and provider_id in self._cache:
|
|
206
|
+
cached = self._cache[provider_id]
|
|
207
|
+
if datetime.now() - cached.checked_at < self.CACHE_TTL:
|
|
208
|
+
return cached
|
|
209
|
+
|
|
210
|
+
start = time.time()
|
|
211
|
+
|
|
212
|
+
try:
|
|
213
|
+
# For now, just check if the provider is configured
|
|
214
|
+
# A full check would make a test API call
|
|
215
|
+
config_result = self._check_configuration(provider_id, provider_def)
|
|
216
|
+
|
|
217
|
+
if config_result.status == ProviderStatus.NOT_CONFIGURED:
|
|
218
|
+
return config_result
|
|
219
|
+
|
|
220
|
+
# Provider is configured, mark as ready
|
|
221
|
+
# (In production, would make a test API call here)
|
|
222
|
+
latency = (time.time() - start) * 1000
|
|
223
|
+
|
|
224
|
+
model = provider_def.example_models[0] if provider_def.example_models else ""
|
|
225
|
+
|
|
226
|
+
result = HealthResult(
|
|
227
|
+
provider_id=provider_id,
|
|
228
|
+
status=ProviderStatus.READY,
|
|
229
|
+
message="API key configured",
|
|
230
|
+
latency_ms=latency,
|
|
231
|
+
model_available=model,
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
self._cache[provider_id] = result
|
|
235
|
+
return result
|
|
236
|
+
|
|
237
|
+
except Exception as e:
|
|
238
|
+
error_msg = str(e).lower()
|
|
239
|
+
|
|
240
|
+
if "rate" in error_msg or "429" in error_msg:
|
|
241
|
+
status = ProviderStatus.RATE_LIMITED
|
|
242
|
+
elif "auth" in error_msg or "401" in error_msg or "403" in error_msg:
|
|
243
|
+
status = ProviderStatus.AUTH_ERROR
|
|
244
|
+
else:
|
|
245
|
+
status = ProviderStatus.ERROR
|
|
246
|
+
|
|
247
|
+
return HealthResult(
|
|
248
|
+
provider_id=provider_id,
|
|
249
|
+
status=status,
|
|
250
|
+
message=str(e)[:100],
|
|
251
|
+
latency_ms=(time.time() - start) * 1000,
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
def get_ready_providers(self) -> List[str]:
|
|
255
|
+
"""Get list of ready provider IDs."""
|
|
256
|
+
return [pid for pid, result in self._cache.items() if result.is_ready]
|
|
257
|
+
|
|
258
|
+
def get_cached_result(self, provider_id: str) -> Optional[HealthResult]:
|
|
259
|
+
"""Get cached result for a provider."""
|
|
260
|
+
return self._cache.get(provider_id)
|
|
261
|
+
|
|
262
|
+
def clear_cache(self):
|
|
263
|
+
"""Clear all cached results."""
|
|
264
|
+
self._cache.clear()
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
# ============================================================================
|
|
268
|
+
# GLOBAL INSTANCE
|
|
269
|
+
# ============================================================================
|
|
270
|
+
|
|
271
|
+
_health_checker: Optional[HealthChecker] = None
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def get_health_checker() -> HealthChecker:
|
|
275
|
+
"""Get the global health checker instance."""
|
|
276
|
+
global _health_checker
|
|
277
|
+
if _health_checker is None:
|
|
278
|
+
_health_checker = HealthChecker()
|
|
279
|
+
return _health_checker
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
async def check_providers_health() -> Dict[str, HealthResult]:
|
|
283
|
+
"""Quick helper to check all providers."""
|
|
284
|
+
return await get_health_checker().check_all()
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
# ============================================================================
|
|
288
|
+
# EXPORTS
|
|
289
|
+
# ============================================================================
|
|
290
|
+
|
|
291
|
+
__all__ = [
|
|
292
|
+
"ProviderStatus",
|
|
293
|
+
"HealthResult",
|
|
294
|
+
"HealthChecker",
|
|
295
|
+
"get_health_checker",
|
|
296
|
+
"check_providers_health",
|
|
297
|
+
]
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""HuggingFace ecosystem integration for SuperQode.
|
|
2
|
+
|
|
3
|
+
This module provides comprehensive HuggingFace support including:
|
|
4
|
+
- HF Hub API for model discovery and download
|
|
5
|
+
- HF Inference API for serverless inference
|
|
6
|
+
- HF Inference Endpoints for dedicated deployments
|
|
7
|
+
- Local transformers runner for pure Python inference
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from superqode.providers.huggingface.hub import (
|
|
11
|
+
HFModel,
|
|
12
|
+
GGUFFile,
|
|
13
|
+
HuggingFaceHub,
|
|
14
|
+
get_hf_hub,
|
|
15
|
+
)
|
|
16
|
+
from superqode.providers.huggingface.inference import (
|
|
17
|
+
InferenceResponse,
|
|
18
|
+
HFInferenceClient,
|
|
19
|
+
get_hf_inference_client,
|
|
20
|
+
RECOMMENDED_MODELS,
|
|
21
|
+
)
|
|
22
|
+
from superqode.providers.huggingface.endpoints import (
|
|
23
|
+
EndpointState,
|
|
24
|
+
EndpointType,
|
|
25
|
+
InferenceEndpoint,
|
|
26
|
+
EndpointResponse,
|
|
27
|
+
HFEndpointsClient,
|
|
28
|
+
get_hf_endpoints_client,
|
|
29
|
+
)
|
|
30
|
+
from superqode.providers.huggingface.transformers_runner import (
|
|
31
|
+
TransformersConfig,
|
|
32
|
+
GenerationResult,
|
|
33
|
+
LoadedModel,
|
|
34
|
+
TransformersRunner,
|
|
35
|
+
get_transformers_runner,
|
|
36
|
+
)
|
|
37
|
+
from superqode.providers.huggingface.downloader import (
|
|
38
|
+
DownloadProgress,
|
|
39
|
+
DownloadResult,
|
|
40
|
+
HFDownloader,
|
|
41
|
+
get_hf_downloader,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
__all__ = [
|
|
45
|
+
# Data classes
|
|
46
|
+
"HFModel",
|
|
47
|
+
"GGUFFile",
|
|
48
|
+
"InferenceResponse",
|
|
49
|
+
"InferenceEndpoint",
|
|
50
|
+
"EndpointResponse",
|
|
51
|
+
"EndpointState",
|
|
52
|
+
"EndpointType",
|
|
53
|
+
"TransformersConfig",
|
|
54
|
+
"GenerationResult",
|
|
55
|
+
"LoadedModel",
|
|
56
|
+
# Hub client
|
|
57
|
+
"HuggingFaceHub",
|
|
58
|
+
"get_hf_hub",
|
|
59
|
+
# Inference client
|
|
60
|
+
"HFInferenceClient",
|
|
61
|
+
"get_hf_inference_client",
|
|
62
|
+
"RECOMMENDED_MODELS",
|
|
63
|
+
# Endpoints client
|
|
64
|
+
"HFEndpointsClient",
|
|
65
|
+
"get_hf_endpoints_client",
|
|
66
|
+
# Transformers runner
|
|
67
|
+
"TransformersRunner",
|
|
68
|
+
"get_transformers_runner",
|
|
69
|
+
# Downloader
|
|
70
|
+
"DownloadProgress",
|
|
71
|
+
"DownloadResult",
|
|
72
|
+
"HFDownloader",
|
|
73
|
+
"get_hf_downloader",
|
|
74
|
+
]
|