cct-cli 0.7.9.0__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.
- calc_terminal/__init__.py +14 -0
- calc_terminal/__main__.py +14 -0
- calc_terminal/activity.py +1334 -0
- calc_terminal/agent.py +3387 -0
- calc_terminal/agent_runtime.py +519 -0
- calc_terminal/ai_context.py +447 -0
- calc_terminal/ai_modes.py +752 -0
- calc_terminal/ai_personalization.py +286 -0
- calc_terminal/ai_preview_feedback.py +213 -0
- calc_terminal/aicore.py +2572 -0
- calc_terminal/anim.py +367 -0
- calc_terminal/app.py +3685 -0
- calc_terminal/art.py +639 -0
- calc_terminal/atomsim.py +368 -0
- calc_terminal/attachments.py +743 -0
- calc_terminal/benchmark_system.py +414 -0
- calc_terminal/browser/__init__.py +36 -0
- calc_terminal/browser/browser_state.py +346 -0
- calc_terminal/browser/devserver.py +176 -0
- calc_terminal/browser/engine.py +494 -0
- calc_terminal/browser/navigation.py +84 -0
- calc_terminal/browser/preview.py +429 -0
- calc_terminal/browser/preview_entry.py +95 -0
- calc_terminal/browser/project_detector.py +144 -0
- calc_terminal/browser/server.py +449 -0
- calc_terminal/browser/state.py +75 -0
- calc_terminal/browser/watcher.py +99 -0
- calc_terminal/browser_gui/__init__.py +1 -0
- calc_terminal/browser_gui/__main__.py +3 -0
- calc_terminal/browser_gui/launcher.py +173 -0
- calc_terminal/browser_gui/playwright_browser.py +117 -0
- calc_terminal/browser_gui/qt_browser.py +1501 -0
- calc_terminal/browser_gui/webview_browser.py +57 -0
- calc_terminal/capabilities/__init__.py +35 -0
- calc_terminal/capabilities/adapters/__init__.py +33 -0
- calc_terminal/capabilities/adapters/bioinformatics.py +204 -0
- calc_terminal/capabilities/adapters/browser_adapter.py +205 -0
- calc_terminal/capabilities/adapters/filesystem.py +206 -0
- calc_terminal/capabilities/adapters/git_adapter.py +202 -0
- calc_terminal/capabilities/adapters/jupyter_adapter.py +138 -0
- calc_terminal/capabilities/adapters/ml_frameworks.py +158 -0
- calc_terminal/capabilities/adapters/platforms.py +200 -0
- calc_terminal/capabilities/adapters/python_exec.py +93 -0
- calc_terminal/capabilities/adapters/quantum_adapter.py +150 -0
- calc_terminal/capabilities/adapters/scientific_comp.py +123 -0
- calc_terminal/capabilities/adapters/structural_bio.py +161 -0
- calc_terminal/capabilities/adapters/terminal.py +99 -0
- calc_terminal/capabilities/bus.py +178 -0
- calc_terminal/capabilities/discovery.py +207 -0
- calc_terminal/capabilities/schema.py +221 -0
- calc_terminal/cat.ico +0 -0
- calc_terminal/cat_browser.py +2018 -0
- calc_terminal/chat_store.py +703 -0
- calc_terminal/cli.py +1178 -0
- calc_terminal/code_editor.py +640 -0
- calc_terminal/collaboration.py +723 -0
- calc_terminal/commands_data.py +139 -0
- calc_terminal/compatibility_engine.py +352 -0
- calc_terminal/compute/__init__.py +31 -0
- calc_terminal/compute/fabric.py +350 -0
- calc_terminal/config.py +227 -0
- calc_terminal/core/__init__.py +41 -0
- calc_terminal/core/checkpoint.py +156 -0
- calc_terminal/core/input/__init__.py +45 -0
- calc_terminal/core/mode_registry.py +300 -0
- calc_terminal/core/project_graph.py +172 -0
- calc_terminal/core/recovery.py +129 -0
- calc_terminal/core/security_layer.py +112 -0
- calc_terminal/core/task_graph.py +202 -0
- calc_terminal/core/unified_runtime.py +184 -0
- calc_terminal/core/verification.py +257 -0
- calc_terminal/customization.py +1566 -0
- calc_terminal/derivations.py +153 -0
- calc_terminal/device_control.py +263 -0
- calc_terminal/diagnostics/__init__.py +27 -0
- calc_terminal/diagnostics/doctor_engine.py +382 -0
- calc_terminal/diagnostics/self_test.py +247 -0
- calc_terminal/doctor.py +519 -0
- calc_terminal/easter_eggs.py +274 -0
- calc_terminal/editor/__init__.py +1 -0
- calc_terminal/editor/actions.py +263 -0
- calc_terminal/editor/commands.py +160 -0
- calc_terminal/editor/shortcuts.py +226 -0
- calc_terminal/engine.py +259 -0
- calc_terminal/errors.py +120 -0
- calc_terminal/event_stream.py +146 -0
- calc_terminal/eventbus.py +133 -0
- calc_terminal/extensions.py +733 -0
- calc_terminal/fallback_cli.py +1321 -0
- calc_terminal/first_run.py +265 -0
- calc_terminal/fomoji_auth.py +1043 -0
- calc_terminal/formulas.py +82 -0
- calc_terminal/fs_cache.py +121 -0
- calc_terminal/fs_watcher.py +277 -0
- calc_terminal/game.py +193 -0
- calc_terminal/gen1.py +5 -0
- calc_terminal/generators.py +245 -0
- calc_terminal/gestures/__init__.py +42 -0
- calc_terminal/gestures/bindings.py +175 -0
- calc_terminal/gestures/manager.py +477 -0
- calc_terminal/goodbye.py +363 -0
- calc_terminal/gpu3d.py +290 -0
- calc_terminal/graphs.py +358 -0
- calc_terminal/hardware_analyzer.py +440 -0
- calc_terminal/host/__init__.py +30 -0
- calc_terminal/host/browser_manager.py +187 -0
- calc_terminal/host/desktop.py +1386 -0
- calc_terminal/host/launcher.py +395 -0
- calc_terminal/host/terminal.py +279 -0
- calc_terminal/identity.py +216 -0
- calc_terminal/input/__init__.py +54 -0
- calc_terminal/input/capabilities.py +258 -0
- calc_terminal/input/focus.py +87 -0
- calc_terminal/input/gestures.py +64 -0
- calc_terminal/input/pointer.py +114 -0
- calc_terminal/input/touch.py +345 -0
- calc_terminal/keys.py +84 -0
- calc_terminal/live_automation.py +165 -0
- calc_terminal/mathtext.py +433 -0
- calc_terminal/mcp.py +386 -0
- calc_terminal/memory.py +337 -0
- calc_terminal/memory_v2.py +479 -0
- calc_terminal/metrics.py +333 -0
- calc_terminal/mode_detection.py +146 -0
- calc_terminal/model.py +2431 -0
- calc_terminal/model_router.py +665 -0
- calc_terminal/models/__init__.py +0 -0
- calc_terminal/models/active_state.py +187 -0
- calc_terminal/models/dynamic_registry.py +584 -0
- calc_terminal/models/manager.py +781 -0
- calc_terminal/models/model_metadata.json +3526 -0
- calc_terminal/models/profiles.py +194 -0
- calc_terminal/models/registry.py +265 -0
- calc_terminal/models/schema.py +197 -0
- calc_terminal/models/validator.py +287 -0
- calc_terminal/models/verification_engine.py +368 -0
- calc_terminal/native_picker.py +215 -0
- calc_terminal/ollama_catalog.py +279 -0
- calc_terminal/ollama_download.py +233 -0
- calc_terminal/orchestrator.py +304 -0
- calc_terminal/package_research.py +322 -0
- calc_terminal/packages.py +1024 -0
- calc_terminal/pc_specs.py +116 -0
- calc_terminal/permissions.py +334 -0
- calc_terminal/pet.py +106 -0
- calc_terminal/pipeline.py +505 -0
- calc_terminal/platform/__init__.py +491 -0
- calc_terminal/platform/desktop.py +491 -0
- calc_terminal/platform/web.py +781 -0
- calc_terminal/preview/__init__.py +1 -0
- calc_terminal/preview/dev_server.py +303 -0
- calc_terminal/preview/diagnostics.py +131 -0
- calc_terminal/preview/live_reload.py +66 -0
- calc_terminal/preview/manager.py +129 -0
- calc_terminal/project_stats.py +209 -0
- calc_terminal/projects.py +328 -0
- calc_terminal/providers/__init__.py +0 -0
- calc_terminal/providers/adapters/__init__.py +80 -0
- calc_terminal/providers/adapters/anthropic_adapter.py +127 -0
- calc_terminal/providers/adapters/base.py +106 -0
- calc_terminal/providers/adapters/chinese_adapters.py +420 -0
- calc_terminal/providers/adapters/gemini_adapter.py +101 -0
- calc_terminal/providers/adapters/ollama_adapter.py +83 -0
- calc_terminal/providers/adapters/openai_adapter.py +159 -0
- calc_terminal/providers/adapters/other_adapters.py +246 -0
- calc_terminal/providers/anthropic_provider.py +172 -0
- calc_terminal/providers/auto_update.py +416 -0
- calc_terminal/providers/base_provider.py +105 -0
- calc_terminal/providers/discovery_manager.py +207 -0
- calc_terminal/providers/gemini_provider.py +178 -0
- calc_terminal/providers/lifecycle.py +767 -0
- calc_terminal/providers/ollama_adapter.py +707 -0
- calc_terminal/providers/openai_provider.py +254 -0
- calc_terminal/providers/provider_manager.py +1827 -0
- calc_terminal/providers/providers.json +4075 -0
- calc_terminal/reactionsim.py +279 -0
- calc_terminal/registry.py +337 -0
- calc_terminal/report.py +162 -0
- calc_terminal/research/__init__.py +45 -0
- calc_terminal/research/artifact_intel.py +126 -0
- calc_terminal/research/data_lineage.py +123 -0
- calc_terminal/research/experiment_ledger.py +303 -0
- calc_terminal/research/reproducibility.py +131 -0
- calc_terminal/resilience/__init__.py +47 -0
- calc_terminal/resilience/agent_state.py +121 -0
- calc_terminal/resilience/capability_matcher.py +174 -0
- calc_terminal/resilience/circuit_breaker.py +158 -0
- calc_terminal/resilience/failover_engine.py +230 -0
- calc_terminal/resilience/health_monitor.py +192 -0
- calc_terminal/resilience/ollama_adapter.py +125 -0
- calc_terminal/resilience/orchestrator.py +312 -0
- calc_terminal/resilience/types.py +134 -0
- calc_terminal/sandbox.py +98 -0
- calc_terminal/scires.py +558 -0
- calc_terminal/security_scanner.py +126 -0
- calc_terminal/session.py +294 -0
- calc_terminal/sim3d.py +206 -0
- calc_terminal/solver.py +276 -0
- calc_terminal/sound.py +127 -0
- calc_terminal/task_reports.py +287 -0
- calc_terminal/terminal_host.py +201 -0
- calc_terminal/terminal_identity.py +411 -0
- calc_terminal/test_ai_mode_reliability.py +344 -0
- calc_terminal/test_browser.py +368 -0
- calc_terminal/test_code_editor_upgrade.py +485 -0
- calc_terminal/test_customization.py +1148 -0
- calc_terminal/test_customization_ui.py +612 -0
- calc_terminal/test_dynamic_registry.py +304 -0
- calc_terminal/test_extensions.py +436 -0
- calc_terminal/test_overhaul.py +557 -0
- calc_terminal/test_project_detect.py +255 -0
- calc_terminal/test_root_cause_fix.py +527 -0
- calc_terminal/test_stability.py +532 -0
- calc_terminal/test_terminal_identity.py +132 -0
- calc_terminal/test_v079_speed.py +460 -0
- calc_terminal/theme.py +1107 -0
- calc_terminal/timeline.py +139 -0
- calc_terminal/todos.py +246 -0
- calc_terminal/tool_call_normalizer.py +419 -0
- calc_terminal/tui.py +104 -0
- calc_terminal/ui/__init__.py +8 -0
- calc_terminal/ui/activity_panel.py +231 -0
- calc_terminal/ui/activity_stream_panel.py +238 -0
- calc_terminal/ui/animations.py +122 -0
- calc_terminal/ui/app.py +7271 -0
- calc_terminal/ui/attach_panel.py +597 -0
- calc_terminal/ui/attachments.py +424 -0
- calc_terminal/ui/backup_panel.py +810 -0
- calc_terminal/ui/browser_shell.py +887 -0
- calc_terminal/ui/cat_agent.py +357 -0
- calc_terminal/ui/chats_panel.py +899 -0
- calc_terminal/ui/command_palette.py +125 -0
- calc_terminal/ui/command_palette_modal.py +166 -0
- calc_terminal/ui/composer.py +1141 -0
- calc_terminal/ui/context_menu.py +197 -0
- calc_terminal/ui/conversation.py +1435 -0
- calc_terminal/ui/customization_panel.py +1229 -0
- calc_terminal/ui/dashboard.py +404 -0
- calc_terminal/ui/design_system.py +557 -0
- calc_terminal/ui/diff_panel.py +213 -0
- calc_terminal/ui/editor.py +2102 -0
- calc_terminal/ui/empty_state.py +302 -0
- calc_terminal/ui/events.py +487 -0
- calc_terminal/ui/extensions_panel.py +815 -0
- calc_terminal/ui/footer.py +166 -0
- calc_terminal/ui/gestures_panel.py +383 -0
- calc_terminal/ui/goodbye_screen.py +100 -0
- calc_terminal/ui/header.py +1034 -0
- calc_terminal/ui/help_panel.py +254 -0
- calc_terminal/ui/live_activities.py +914 -0
- calc_terminal/ui/mcp_panel.py +570 -0
- calc_terminal/ui/memory_center.py +524 -0
- calc_terminal/ui/mode_colors_panel.py +525 -0
- calc_terminal/ui/nav_screens.py +747 -0
- calc_terminal/ui/ollama_panel.py +536 -0
- calc_terminal/ui/palette.py +221 -0
- calc_terminal/ui/permission_panel.py +269 -0
- calc_terminal/ui/personalization_panel.py +517 -0
- calc_terminal/ui/personalize_center.py +1568 -0
- calc_terminal/ui/preview_panel.py +441 -0
- calc_terminal/ui/resizers.py +402 -0
- calc_terminal/ui/sidebar.py +1285 -0
- calc_terminal/ui/statusbar.py +168 -0
- calc_terminal/ui/theme_css.py +1396 -0
- calc_terminal/ui/thinking.py +226 -0
- calc_terminal/ui/timeline_panel.py +102 -0
- calc_terminal/ui/todo_panel.py +193 -0
- calc_terminal/ui/viewport.py +136 -0
- calc_terminal/ui/vision_panel.py +489 -0
- calc_terminal/ui/welcome_modal.py +343 -0
- calc_terminal/ui/widgets.py +160 -0
- calc_terminal/ui/workspace.py +831 -0
- calc_terminal/viewers/__init__.py +1 -0
- calc_terminal/viewers/document_viewer.py +252 -0
- calc_terminal/viewers/image_viewer.py +241 -0
- calc_terminal/viewers/pdf_viewer.py +203 -0
- calc_terminal/viewers/presentation_viewer.py +164 -0
- calc_terminal/viewers/registry.py +120 -0
- calc_terminal/viewers/spreadsheet_viewer.py +204 -0
- calc_terminal/vision/__init__.py +89 -0
- calc_terminal/vision/analysis.py +194 -0
- calc_terminal/vision/annotations.py +297 -0
- calc_terminal/vision/capture.py +171 -0
- calc_terminal/vision/context.py +231 -0
- calc_terminal/vision/correlation.py +169 -0
- calc_terminal/vision/cursor.py +258 -0
- calc_terminal/vision/events.py +66 -0
- calc_terminal/vision/frame_pipeline.py +259 -0
- calc_terminal/vision/priority.py +218 -0
- calc_terminal/vision/provider.py +180 -0
- calc_terminal/vision/safety.py +149 -0
- calc_terminal/vision/session.py +281 -0
- calc_terminal/vision/verify.py +162 -0
- calc_terminal/vision.py +514 -0
- calc_terminal/vscode_integration.py +113 -0
- calc_terminal/web/__init__.py +8 -0
- calc_terminal/web/cat_runtime.py +710 -0
- calc_terminal/web/server.py +2891 -0
- calc_terminal/web/static/css/app.css +3152 -0
- calc_terminal/web/static/icons/badge-72.png +0 -0
- calc_terminal/web/static/icons/cat.ico +0 -0
- calc_terminal/web/static/icons/icon-128.png +0 -0
- calc_terminal/web/static/icons/icon-144.png +0 -0
- calc_terminal/web/static/icons/icon-152.png +0 -0
- calc_terminal/web/static/icons/icon-192.png +0 -0
- calc_terminal/web/static/icons/icon-384.png +0 -0
- calc_terminal/web/static/icons/icon-512.png +0 -0
- calc_terminal/web/static/icons/icon-72.png +0 -0
- calc_terminal/web/static/icons/icon-96.png +0 -0
- calc_terminal/web/static/icons/icon.svg +34 -0
- calc_terminal/web/static/icons/new-project.png +0 -0
- calc_terminal/web/static/icons/open-project.png +0 -0
- calc_terminal/web/static/index.html +734 -0
- calc_terminal/web/static/js/app.js +2403 -0
- calc_terminal/web/static/manifest.json +88 -0
- calc_terminal/web/static/sw.js +230 -0
- calc_terminal/workflow_engine.py +769 -0
- calc_terminal/workspace.py +593 -0
- calc_terminal/workspace_index.py +385 -0
- cct_cli-0.7.9.0.dist-info/METADATA +210 -0
- cct_cli-0.7.9.0.dist-info/RECORD +325 -0
- cct_cli-0.7.9.0.dist-info/WHEEL +5 -0
- cct_cli-0.7.9.0.dist-info/entry_points.txt +4 -0
- cct_cli-0.7.9.0.dist-info/licenses/LICENSE +21 -0
- cct_cli-0.7.9.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CAT Environment & Capability Discovery per §34, §35, §36, §46, §57, §86.
|
|
3
|
+
Performs real runtime environment inspection.
|
|
4
|
+
Never returns fake capabilities or simulated states.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import importlib
|
|
10
|
+
import importlib.util
|
|
11
|
+
import os
|
|
12
|
+
import shutil
|
|
13
|
+
import subprocess
|
|
14
|
+
import sys
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
17
|
+
|
|
18
|
+
from .schema import AvailabilityStatus
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class EnvironmentSnapshot:
|
|
23
|
+
"""Snapshot of discovered execution targets and software availability."""
|
|
24
|
+
python_version: str
|
|
25
|
+
virtual_env: Optional[str]
|
|
26
|
+
git_installed: bool
|
|
27
|
+
git_version: str
|
|
28
|
+
jupyter_installed: bool
|
|
29
|
+
playwright_installed: bool
|
|
30
|
+
chromium_installed: bool
|
|
31
|
+
torch_installed: bool
|
|
32
|
+
cuda_available: bool
|
|
33
|
+
gpu_name: str
|
|
34
|
+
vram_gb: float
|
|
35
|
+
matlab_available: bool
|
|
36
|
+
pymol_available: bool
|
|
37
|
+
chimerax_available: bool
|
|
38
|
+
blast_available: bool
|
|
39
|
+
kaggle_configured: bool
|
|
40
|
+
huggingface_configured: bool
|
|
41
|
+
github_configured: bool
|
|
42
|
+
qiskit_installed: bool
|
|
43
|
+
cirq_installed: bool
|
|
44
|
+
pennylane_installed: bool
|
|
45
|
+
discovered_packages: Dict[str, str] = field(default_factory=dict)
|
|
46
|
+
|
|
47
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
48
|
+
return {
|
|
49
|
+
"python_version": self.python_version,
|
|
50
|
+
"virtual_env": self.virtual_env,
|
|
51
|
+
"git_installed": self.git_installed,
|
|
52
|
+
"git_version": self.git_version,
|
|
53
|
+
"jupyter_installed": self.jupyter_installed,
|
|
54
|
+
"playwright_installed": self.playwright_installed,
|
|
55
|
+
"chromium_installed": self.chromium_installed,
|
|
56
|
+
"torch_installed": self.torch_installed,
|
|
57
|
+
"cuda_available": self.cuda_available,
|
|
58
|
+
"gpu_name": self.gpu_name,
|
|
59
|
+
"vram_gb": self.vram_gb,
|
|
60
|
+
"matlab_available": self.matlab_available,
|
|
61
|
+
"pymol_available": self.pymol_available,
|
|
62
|
+
"chimerax_available": self.chimerax_available,
|
|
63
|
+
"blast_available": self.blast_available,
|
|
64
|
+
"kaggle_configured": self.kaggle_configured,
|
|
65
|
+
"huggingface_configured": self.huggingface_configured,
|
|
66
|
+
"github_configured": self.github_configured,
|
|
67
|
+
"qiskit_installed": self.qiskit_installed,
|
|
68
|
+
"cirq_installed": self.cirq_installed,
|
|
69
|
+
"pennylane_installed": self.pennylane_installed,
|
|
70
|
+
"discovered_packages": self.discovered_packages,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _pkg_version(pkg_name: str) -> Optional[str]:
|
|
75
|
+
"""Return installed package version if present, else None."""
|
|
76
|
+
try:
|
|
77
|
+
mod = importlib.import_module(pkg_name)
|
|
78
|
+
return getattr(mod, "__version__", "installed")
|
|
79
|
+
except Exception:
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _has_command(cmd: str) -> bool:
|
|
84
|
+
"""Check if command is on system PATH."""
|
|
85
|
+
return shutil.which(cmd) is not None
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _get_command_output(cmd: List[str], timeout: float = 3.0) -> str:
|
|
89
|
+
"""Execute command and return stdout safely."""
|
|
90
|
+
try:
|
|
91
|
+
res = subprocess.run(
|
|
92
|
+
cmd,
|
|
93
|
+
stdout=subprocess.PIPE,
|
|
94
|
+
stderr=subprocess.PIPE,
|
|
95
|
+
text=True,
|
|
96
|
+
timeout=timeout,
|
|
97
|
+
shell=False,
|
|
98
|
+
)
|
|
99
|
+
return res.stdout.strip()
|
|
100
|
+
except Exception:
|
|
101
|
+
return ""
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def discover_environment() -> EnvironmentSnapshot:
|
|
105
|
+
"""Perform real discovery of local runtime tools, libraries, and hardware."""
|
|
106
|
+
py_ver = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
107
|
+
venv = os.environ.get("VIRTUAL_ENV") or os.environ.get("CONDA_PREFIX")
|
|
108
|
+
|
|
109
|
+
# Git
|
|
110
|
+
git_installed = _has_command("git")
|
|
111
|
+
git_ver = _get_command_output(["git", "--version"]) if git_installed else ""
|
|
112
|
+
|
|
113
|
+
# Jupyter
|
|
114
|
+
jupyter_installed = _has_command("jupyter") or (_pkg_version("jupyter") is not None) or (_pkg_version("notebook") is not None)
|
|
115
|
+
|
|
116
|
+
# Playwright & Chromium
|
|
117
|
+
playwright_installed = _pkg_version("playwright") is not None
|
|
118
|
+
chromium_installed = False
|
|
119
|
+
if playwright_installed:
|
|
120
|
+
try:
|
|
121
|
+
from ..browser.engine import PLAYWRIGHT_AVAILABLE
|
|
122
|
+
chromium_installed = PLAYWRIGHT_AVAILABLE
|
|
123
|
+
except Exception:
|
|
124
|
+
chromium_installed = False
|
|
125
|
+
|
|
126
|
+
# PyTorch & Accelerators
|
|
127
|
+
torch_ver = _pkg_version("torch")
|
|
128
|
+
torch_installed = torch_ver is not None
|
|
129
|
+
cuda_avail = False
|
|
130
|
+
gpu_name = ""
|
|
131
|
+
vram_gb = 0.0
|
|
132
|
+
|
|
133
|
+
if torch_installed:
|
|
134
|
+
try:
|
|
135
|
+
import torch
|
|
136
|
+
cuda_avail = torch.cuda.is_available()
|
|
137
|
+
if cuda_avail:
|
|
138
|
+
gpu_name = torch.cuda.get_device_name(0)
|
|
139
|
+
vram_gb = round(torch.cuda.get_device_properties(0).total_memory / (1024**3), 2)
|
|
140
|
+
except Exception:
|
|
141
|
+
pass
|
|
142
|
+
|
|
143
|
+
if not gpu_name and _has_command("nvidia-smi"):
|
|
144
|
+
smi = _get_command_output(["nvidia-smi", "--query-gpu=gpu_name,memory.total", "--format=csv,noheader,nounits"])
|
|
145
|
+
if smi and "," in smi:
|
|
146
|
+
parts = smi.split(",")
|
|
147
|
+
gpu_name = parts[0].strip()
|
|
148
|
+
try:
|
|
149
|
+
vram_gb = round(float(parts[1].strip()) / 1024.0, 2)
|
|
150
|
+
except Exception:
|
|
151
|
+
pass
|
|
152
|
+
|
|
153
|
+
# Scientific packages
|
|
154
|
+
pkgs = {}
|
|
155
|
+
candidate_pkgs = [
|
|
156
|
+
"numpy", "scipy", "pandas", "sympy", "matplotlib", "sklearn",
|
|
157
|
+
"transformers", "biopython", "qiskit", "cirq", "pennylane",
|
|
158
|
+
"requests", "textual", "rich"
|
|
159
|
+
]
|
|
160
|
+
for p in candidate_pkgs:
|
|
161
|
+
v = _pkg_version(p)
|
|
162
|
+
if v:
|
|
163
|
+
pkgs[p] = v
|
|
164
|
+
|
|
165
|
+
# MATLAB
|
|
166
|
+
matlab_available = _has_command("matlab") or (_pkg_version("matlab") is not None)
|
|
167
|
+
|
|
168
|
+
# PyMOL / ChimeraX
|
|
169
|
+
pymol_available = _has_command("pymol") or os.path.exists(r"C:\Program Files\PyMOL\PyMOLWin.exe") or os.path.exists(r"C:\Program Files (x86)\Schrodinger\PyMOL")
|
|
170
|
+
chimerax_available = _has_command("chimerax") or os.path.exists(r"C:\Program Files\ChimeraX\bin\ChimeraX.exe")
|
|
171
|
+
|
|
172
|
+
# BLAST
|
|
173
|
+
blast_available = _has_command("blastn") or _has_command("blastp") or (_pkg_version("Bio") is not None)
|
|
174
|
+
|
|
175
|
+
# Platforms / Credentials
|
|
176
|
+
kaggle_path = os.path.expanduser(os.path.join("~", ".kaggle", "kaggle.json"))
|
|
177
|
+
kaggle_configured = os.path.exists(kaggle_path) or bool(os.environ.get("KAGGLE_USERNAME") and os.environ.get("KAGGLE_KEY"))
|
|
178
|
+
|
|
179
|
+
hf_token_path = os.path.expanduser(os.path.join("~", ".cache", "huggingface", "token"))
|
|
180
|
+
hf_configured = os.path.exists(hf_token_path) or bool(os.environ.get("HF_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN"))
|
|
181
|
+
|
|
182
|
+
github_configured = bool(os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN") or _has_command("gh"))
|
|
183
|
+
|
|
184
|
+
return EnvironmentSnapshot(
|
|
185
|
+
python_version=py_ver,
|
|
186
|
+
virtual_env=venv,
|
|
187
|
+
git_installed=git_installed,
|
|
188
|
+
git_version=git_ver,
|
|
189
|
+
jupyter_installed=jupyter_installed,
|
|
190
|
+
playwright_installed=playwright_installed,
|
|
191
|
+
chromium_installed=chromium_installed,
|
|
192
|
+
torch_installed=torch_installed,
|
|
193
|
+
cuda_available=cuda_avail,
|
|
194
|
+
gpu_name=gpu_name,
|
|
195
|
+
vram_gb=vram_gb,
|
|
196
|
+
matlab_available=matlab_available,
|
|
197
|
+
pymol_available=pymol_available,
|
|
198
|
+
chimerax_available=chimerax_available,
|
|
199
|
+
blast_available=blast_available,
|
|
200
|
+
kaggle_configured=kaggle_configured,
|
|
201
|
+
huggingface_configured=hf_configured,
|
|
202
|
+
github_configured=github_configured,
|
|
203
|
+
qiskit_installed="qiskit" in pkgs,
|
|
204
|
+
cirq_installed="cirq" in pkgs,
|
|
205
|
+
pennylane_installed="pennylane" in pkgs,
|
|
206
|
+
discovered_packages=pkgs,
|
|
207
|
+
)
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CAT Capability System — Core Schemas and Contracts.
|
|
3
|
+
Defines:
|
|
4
|
+
- AvailabilityStatus: honest capability states per §4, §57, §86
|
|
5
|
+
- CapabilityCategory: functional domain
|
|
6
|
+
- CapabilitySpec: complete capability manifest
|
|
7
|
+
- ExecutionResult / ExecutionError: structured result and error models per §83
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import time
|
|
13
|
+
from dataclasses import dataclass, field
|
|
14
|
+
from enum import Enum
|
|
15
|
+
from typing import Any, Callable, Dict, List, Optional, Union
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AvailabilityStatus(str, Enum):
|
|
19
|
+
AVAILABLE = "AVAILABLE"
|
|
20
|
+
UNAVAILABLE = "UNAVAILABLE"
|
|
21
|
+
AUTHENTICATION_REQUIRED = "AUTHENTICATION_REQUIRED"
|
|
22
|
+
SOFTWARE_NOT_FOUND = "SOFTWARE_NOT_FOUND"
|
|
23
|
+
LICENSE_REQUIRED = "LICENSE_REQUIRED"
|
|
24
|
+
PERMISSION_DENIED = "PERMISSION_DENIED"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class CapabilityCategory(str, Enum):
|
|
28
|
+
FILESYSTEM = "filesystem"
|
|
29
|
+
TERMINAL = "terminal"
|
|
30
|
+
PYTHON = "python"
|
|
31
|
+
BROWSER = "browser"
|
|
32
|
+
JUPYTER = "jupyter"
|
|
33
|
+
GIT = "git"
|
|
34
|
+
ML = "ml"
|
|
35
|
+
BIO = "bio"
|
|
36
|
+
SCIENTIFIC = "scientific"
|
|
37
|
+
PLATFORMS = "platforms"
|
|
38
|
+
QUANTUM = "quantum"
|
|
39
|
+
CUSTOM = "custom"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class CapabilitySpec:
|
|
44
|
+
"""Full specification contract for a CAT capability."""
|
|
45
|
+
name: str
|
|
46
|
+
version: str
|
|
47
|
+
category: CapabilityCategory
|
|
48
|
+
description: str
|
|
49
|
+
input_schema: Dict[str, Any] = field(default_factory=dict)
|
|
50
|
+
output_schema: Dict[str, Any] = field(default_factory=dict)
|
|
51
|
+
error_schema: Dict[str, Any] = field(default_factory=dict)
|
|
52
|
+
permissions: List[str] = field(default_factory=list)
|
|
53
|
+
auth_required: bool = False
|
|
54
|
+
environment_requirements: List[str] = field(default_factory=list)
|
|
55
|
+
documentation: str = ""
|
|
56
|
+
tags: List[str] = field(default_factory=list)
|
|
57
|
+
|
|
58
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
59
|
+
return {
|
|
60
|
+
"name": self.name,
|
|
61
|
+
"version": self.version,
|
|
62
|
+
"category": self.category.value if isinstance(self.category, CapabilityCategory) else str(self.category),
|
|
63
|
+
"description": self.description,
|
|
64
|
+
"input_schema": self.input_schema,
|
|
65
|
+
"output_schema": self.output_schema,
|
|
66
|
+
"error_schema": self.error_schema,
|
|
67
|
+
"permissions": self.permissions,
|
|
68
|
+
"auth_required": self.auth_required,
|
|
69
|
+
"environment_requirements": self.environment_requirements,
|
|
70
|
+
"documentation": self.documentation,
|
|
71
|
+
"tags": self.tags,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class ExecutionError(Exception):
|
|
76
|
+
"""Structured error raised during capability execution per §83."""
|
|
77
|
+
|
|
78
|
+
def __init__(
|
|
79
|
+
self,
|
|
80
|
+
message: str,
|
|
81
|
+
tool: str = "",
|
|
82
|
+
task_id: str = "",
|
|
83
|
+
retryable: bool = False,
|
|
84
|
+
error_type: str = "ToolExecutionError",
|
|
85
|
+
details: Optional[Dict[str, Any]] = None,
|
|
86
|
+
):
|
|
87
|
+
super().__init__(message)
|
|
88
|
+
self.message = message
|
|
89
|
+
self.tool = tool
|
|
90
|
+
self.task_id = task_id
|
|
91
|
+
self.retryable = retryable
|
|
92
|
+
self.error_type = error_type
|
|
93
|
+
self.details = details or {}
|
|
94
|
+
|
|
95
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
96
|
+
return {
|
|
97
|
+
"type": self.error_type,
|
|
98
|
+
"tool": self.tool,
|
|
99
|
+
"task_id": self.task_id,
|
|
100
|
+
"message": self.message,
|
|
101
|
+
"retryable": self.retryable,
|
|
102
|
+
"details": self.details,
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@dataclass
|
|
107
|
+
class ExecutionResult:
|
|
108
|
+
"""Standard execution result returned by all capability adapters."""
|
|
109
|
+
success: bool
|
|
110
|
+
output: Any = None
|
|
111
|
+
error: Optional[str] = None
|
|
112
|
+
status: AvailabilityStatus = AvailabilityStatus.AVAILABLE
|
|
113
|
+
duration_ms: float = 0.0
|
|
114
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
115
|
+
provenance: Dict[str, Any] = field(default_factory=dict)
|
|
116
|
+
timestamp: float = field(default_factory=time.time)
|
|
117
|
+
|
|
118
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
119
|
+
return {
|
|
120
|
+
"success": self.success,
|
|
121
|
+
"output": self.output,
|
|
122
|
+
"error": self.error,
|
|
123
|
+
"status": self.status.value if isinstance(self.status, AvailabilityStatus) else str(self.status),
|
|
124
|
+
"duration_ms": self.duration_ms,
|
|
125
|
+
"metadata": self.metadata,
|
|
126
|
+
"provenance": self.provenance,
|
|
127
|
+
"timestamp": self.timestamp,
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class Capability:
|
|
132
|
+
"""Callable unit representing a concrete capability implementation."""
|
|
133
|
+
|
|
134
|
+
def __init__(
|
|
135
|
+
self,
|
|
136
|
+
spec: CapabilitySpec,
|
|
137
|
+
handler: Callable[[Dict[str, Any], Optional[Dict[str, Any]]], ExecutionResult],
|
|
138
|
+
health_checker: Optional[Callable[[], Tuple[AvailabilityStatus, str]]] = None,
|
|
139
|
+
):
|
|
140
|
+
self.spec = spec
|
|
141
|
+
self.handler = handler
|
|
142
|
+
self.health_checker = health_checker
|
|
143
|
+
self._last_status: AvailabilityStatus = AvailabilityStatus.AVAILABLE
|
|
144
|
+
self._last_status_message: str = "Ready"
|
|
145
|
+
self._last_check_time: float = 0.0
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def name(self) -> str:
|
|
149
|
+
return self.spec.name
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def status(self) -> AvailabilityStatus:
|
|
153
|
+
return self._last_status
|
|
154
|
+
|
|
155
|
+
def check_health(self, force: bool = False) -> Tuple[AvailabilityStatus, str]:
|
|
156
|
+
"""Check capability availability and return (status, message)."""
|
|
157
|
+
now = time.time()
|
|
158
|
+
if not force and (now - self._last_check_time < 15.0) and self._last_check_time > 0:
|
|
159
|
+
return self._last_status, self._last_status_message
|
|
160
|
+
|
|
161
|
+
if self.health_checker:
|
|
162
|
+
try:
|
|
163
|
+
st, msg = self.health_checker()
|
|
164
|
+
self._last_status = st
|
|
165
|
+
self._last_status_message = msg
|
|
166
|
+
except Exception as e:
|
|
167
|
+
self._last_status = AvailabilityStatus.UNAVAILABLE
|
|
168
|
+
self._last_status_message = f"Health check failed: {e}"
|
|
169
|
+
else:
|
|
170
|
+
self._last_status = AvailabilityStatus.AVAILABLE
|
|
171
|
+
self._last_status_message = "Ready"
|
|
172
|
+
|
|
173
|
+
self._last_check_time = now
|
|
174
|
+
return self._last_status, self._last_status_message
|
|
175
|
+
|
|
176
|
+
def execute(self, args: Dict[str, Any], context: Optional[Dict[str, Any]] = None) -> ExecutionResult:
|
|
177
|
+
"""Run the capability handler with error handling and timing."""
|
|
178
|
+
t0 = time.perf_counter()
|
|
179
|
+
# Fast health check if unknown
|
|
180
|
+
if self._last_check_time == 0:
|
|
181
|
+
self.check_health()
|
|
182
|
+
|
|
183
|
+
if self._last_status in (
|
|
184
|
+
AvailabilityStatus.SOFTWARE_NOT_FOUND,
|
|
185
|
+
AvailabilityStatus.AUTHENTICATION_REQUIRED,
|
|
186
|
+
AvailabilityStatus.LICENSE_REQUIRED,
|
|
187
|
+
AvailabilityStatus.UNAVAILABLE,
|
|
188
|
+
):
|
|
189
|
+
elapsed = (time.perf_counter() - t0) * 1000.0
|
|
190
|
+
return ExecutionResult(
|
|
191
|
+
success=False,
|
|
192
|
+
error=f"Capability '{self.name}' not available: {self._last_status_message}",
|
|
193
|
+
status=self._last_status,
|
|
194
|
+
duration_ms=round(elapsed, 2),
|
|
195
|
+
metadata={"reason": self._last_status_message},
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
try:
|
|
199
|
+
res = self.handler(args, context)
|
|
200
|
+
if not isinstance(res, ExecutionResult):
|
|
201
|
+
res = ExecutionResult(success=True, output=res)
|
|
202
|
+
res.duration_ms = round((time.perf_counter() - t0) * 1000.0, 2)
|
|
203
|
+
return res
|
|
204
|
+
except ExecutionError as ee:
|
|
205
|
+
elapsed = (time.perf_counter() - t0) * 1000.0
|
|
206
|
+
return ExecutionResult(
|
|
207
|
+
success=False,
|
|
208
|
+
error=ee.message,
|
|
209
|
+
status=AvailabilityStatus.UNAVAILABLE,
|
|
210
|
+
duration_ms=round(elapsed, 2),
|
|
211
|
+
metadata=ee.to_dict(),
|
|
212
|
+
)
|
|
213
|
+
except Exception as e:
|
|
214
|
+
elapsed = (time.perf_counter() - t0) * 1000.0
|
|
215
|
+
return ExecutionResult(
|
|
216
|
+
success=False,
|
|
217
|
+
error=str(e),
|
|
218
|
+
status=AvailabilityStatus.UNAVAILABLE,
|
|
219
|
+
duration_ms=round(elapsed, 2),
|
|
220
|
+
metadata={"exception": type(e).__name__},
|
|
221
|
+
)
|
calc_terminal/cat.ico
ADDED
|
Binary file
|