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.
Files changed (325) hide show
  1. calc_terminal/__init__.py +14 -0
  2. calc_terminal/__main__.py +14 -0
  3. calc_terminal/activity.py +1334 -0
  4. calc_terminal/agent.py +3387 -0
  5. calc_terminal/agent_runtime.py +519 -0
  6. calc_terminal/ai_context.py +447 -0
  7. calc_terminal/ai_modes.py +752 -0
  8. calc_terminal/ai_personalization.py +286 -0
  9. calc_terminal/ai_preview_feedback.py +213 -0
  10. calc_terminal/aicore.py +2572 -0
  11. calc_terminal/anim.py +367 -0
  12. calc_terminal/app.py +3685 -0
  13. calc_terminal/art.py +639 -0
  14. calc_terminal/atomsim.py +368 -0
  15. calc_terminal/attachments.py +743 -0
  16. calc_terminal/benchmark_system.py +414 -0
  17. calc_terminal/browser/__init__.py +36 -0
  18. calc_terminal/browser/browser_state.py +346 -0
  19. calc_terminal/browser/devserver.py +176 -0
  20. calc_terminal/browser/engine.py +494 -0
  21. calc_terminal/browser/navigation.py +84 -0
  22. calc_terminal/browser/preview.py +429 -0
  23. calc_terminal/browser/preview_entry.py +95 -0
  24. calc_terminal/browser/project_detector.py +144 -0
  25. calc_terminal/browser/server.py +449 -0
  26. calc_terminal/browser/state.py +75 -0
  27. calc_terminal/browser/watcher.py +99 -0
  28. calc_terminal/browser_gui/__init__.py +1 -0
  29. calc_terminal/browser_gui/__main__.py +3 -0
  30. calc_terminal/browser_gui/launcher.py +173 -0
  31. calc_terminal/browser_gui/playwright_browser.py +117 -0
  32. calc_terminal/browser_gui/qt_browser.py +1501 -0
  33. calc_terminal/browser_gui/webview_browser.py +57 -0
  34. calc_terminal/capabilities/__init__.py +35 -0
  35. calc_terminal/capabilities/adapters/__init__.py +33 -0
  36. calc_terminal/capabilities/adapters/bioinformatics.py +204 -0
  37. calc_terminal/capabilities/adapters/browser_adapter.py +205 -0
  38. calc_terminal/capabilities/adapters/filesystem.py +206 -0
  39. calc_terminal/capabilities/adapters/git_adapter.py +202 -0
  40. calc_terminal/capabilities/adapters/jupyter_adapter.py +138 -0
  41. calc_terminal/capabilities/adapters/ml_frameworks.py +158 -0
  42. calc_terminal/capabilities/adapters/platforms.py +200 -0
  43. calc_terminal/capabilities/adapters/python_exec.py +93 -0
  44. calc_terminal/capabilities/adapters/quantum_adapter.py +150 -0
  45. calc_terminal/capabilities/adapters/scientific_comp.py +123 -0
  46. calc_terminal/capabilities/adapters/structural_bio.py +161 -0
  47. calc_terminal/capabilities/adapters/terminal.py +99 -0
  48. calc_terminal/capabilities/bus.py +178 -0
  49. calc_terminal/capabilities/discovery.py +207 -0
  50. calc_terminal/capabilities/schema.py +221 -0
  51. calc_terminal/cat.ico +0 -0
  52. calc_terminal/cat_browser.py +2018 -0
  53. calc_terminal/chat_store.py +703 -0
  54. calc_terminal/cli.py +1178 -0
  55. calc_terminal/code_editor.py +640 -0
  56. calc_terminal/collaboration.py +723 -0
  57. calc_terminal/commands_data.py +139 -0
  58. calc_terminal/compatibility_engine.py +352 -0
  59. calc_terminal/compute/__init__.py +31 -0
  60. calc_terminal/compute/fabric.py +350 -0
  61. calc_terminal/config.py +227 -0
  62. calc_terminal/core/__init__.py +41 -0
  63. calc_terminal/core/checkpoint.py +156 -0
  64. calc_terminal/core/input/__init__.py +45 -0
  65. calc_terminal/core/mode_registry.py +300 -0
  66. calc_terminal/core/project_graph.py +172 -0
  67. calc_terminal/core/recovery.py +129 -0
  68. calc_terminal/core/security_layer.py +112 -0
  69. calc_terminal/core/task_graph.py +202 -0
  70. calc_terminal/core/unified_runtime.py +184 -0
  71. calc_terminal/core/verification.py +257 -0
  72. calc_terminal/customization.py +1566 -0
  73. calc_terminal/derivations.py +153 -0
  74. calc_terminal/device_control.py +263 -0
  75. calc_terminal/diagnostics/__init__.py +27 -0
  76. calc_terminal/diagnostics/doctor_engine.py +382 -0
  77. calc_terminal/diagnostics/self_test.py +247 -0
  78. calc_terminal/doctor.py +519 -0
  79. calc_terminal/easter_eggs.py +274 -0
  80. calc_terminal/editor/__init__.py +1 -0
  81. calc_terminal/editor/actions.py +263 -0
  82. calc_terminal/editor/commands.py +160 -0
  83. calc_terminal/editor/shortcuts.py +226 -0
  84. calc_terminal/engine.py +259 -0
  85. calc_terminal/errors.py +120 -0
  86. calc_terminal/event_stream.py +146 -0
  87. calc_terminal/eventbus.py +133 -0
  88. calc_terminal/extensions.py +733 -0
  89. calc_terminal/fallback_cli.py +1321 -0
  90. calc_terminal/first_run.py +265 -0
  91. calc_terminal/fomoji_auth.py +1043 -0
  92. calc_terminal/formulas.py +82 -0
  93. calc_terminal/fs_cache.py +121 -0
  94. calc_terminal/fs_watcher.py +277 -0
  95. calc_terminal/game.py +193 -0
  96. calc_terminal/gen1.py +5 -0
  97. calc_terminal/generators.py +245 -0
  98. calc_terminal/gestures/__init__.py +42 -0
  99. calc_terminal/gestures/bindings.py +175 -0
  100. calc_terminal/gestures/manager.py +477 -0
  101. calc_terminal/goodbye.py +363 -0
  102. calc_terminal/gpu3d.py +290 -0
  103. calc_terminal/graphs.py +358 -0
  104. calc_terminal/hardware_analyzer.py +440 -0
  105. calc_terminal/host/__init__.py +30 -0
  106. calc_terminal/host/browser_manager.py +187 -0
  107. calc_terminal/host/desktop.py +1386 -0
  108. calc_terminal/host/launcher.py +395 -0
  109. calc_terminal/host/terminal.py +279 -0
  110. calc_terminal/identity.py +216 -0
  111. calc_terminal/input/__init__.py +54 -0
  112. calc_terminal/input/capabilities.py +258 -0
  113. calc_terminal/input/focus.py +87 -0
  114. calc_terminal/input/gestures.py +64 -0
  115. calc_terminal/input/pointer.py +114 -0
  116. calc_terminal/input/touch.py +345 -0
  117. calc_terminal/keys.py +84 -0
  118. calc_terminal/live_automation.py +165 -0
  119. calc_terminal/mathtext.py +433 -0
  120. calc_terminal/mcp.py +386 -0
  121. calc_terminal/memory.py +337 -0
  122. calc_terminal/memory_v2.py +479 -0
  123. calc_terminal/metrics.py +333 -0
  124. calc_terminal/mode_detection.py +146 -0
  125. calc_terminal/model.py +2431 -0
  126. calc_terminal/model_router.py +665 -0
  127. calc_terminal/models/__init__.py +0 -0
  128. calc_terminal/models/active_state.py +187 -0
  129. calc_terminal/models/dynamic_registry.py +584 -0
  130. calc_terminal/models/manager.py +781 -0
  131. calc_terminal/models/model_metadata.json +3526 -0
  132. calc_terminal/models/profiles.py +194 -0
  133. calc_terminal/models/registry.py +265 -0
  134. calc_terminal/models/schema.py +197 -0
  135. calc_terminal/models/validator.py +287 -0
  136. calc_terminal/models/verification_engine.py +368 -0
  137. calc_terminal/native_picker.py +215 -0
  138. calc_terminal/ollama_catalog.py +279 -0
  139. calc_terminal/ollama_download.py +233 -0
  140. calc_terminal/orchestrator.py +304 -0
  141. calc_terminal/package_research.py +322 -0
  142. calc_terminal/packages.py +1024 -0
  143. calc_terminal/pc_specs.py +116 -0
  144. calc_terminal/permissions.py +334 -0
  145. calc_terminal/pet.py +106 -0
  146. calc_terminal/pipeline.py +505 -0
  147. calc_terminal/platform/__init__.py +491 -0
  148. calc_terminal/platform/desktop.py +491 -0
  149. calc_terminal/platform/web.py +781 -0
  150. calc_terminal/preview/__init__.py +1 -0
  151. calc_terminal/preview/dev_server.py +303 -0
  152. calc_terminal/preview/diagnostics.py +131 -0
  153. calc_terminal/preview/live_reload.py +66 -0
  154. calc_terminal/preview/manager.py +129 -0
  155. calc_terminal/project_stats.py +209 -0
  156. calc_terminal/projects.py +328 -0
  157. calc_terminal/providers/__init__.py +0 -0
  158. calc_terminal/providers/adapters/__init__.py +80 -0
  159. calc_terminal/providers/adapters/anthropic_adapter.py +127 -0
  160. calc_terminal/providers/adapters/base.py +106 -0
  161. calc_terminal/providers/adapters/chinese_adapters.py +420 -0
  162. calc_terminal/providers/adapters/gemini_adapter.py +101 -0
  163. calc_terminal/providers/adapters/ollama_adapter.py +83 -0
  164. calc_terminal/providers/adapters/openai_adapter.py +159 -0
  165. calc_terminal/providers/adapters/other_adapters.py +246 -0
  166. calc_terminal/providers/anthropic_provider.py +172 -0
  167. calc_terminal/providers/auto_update.py +416 -0
  168. calc_terminal/providers/base_provider.py +105 -0
  169. calc_terminal/providers/discovery_manager.py +207 -0
  170. calc_terminal/providers/gemini_provider.py +178 -0
  171. calc_terminal/providers/lifecycle.py +767 -0
  172. calc_terminal/providers/ollama_adapter.py +707 -0
  173. calc_terminal/providers/openai_provider.py +254 -0
  174. calc_terminal/providers/provider_manager.py +1827 -0
  175. calc_terminal/providers/providers.json +4075 -0
  176. calc_terminal/reactionsim.py +279 -0
  177. calc_terminal/registry.py +337 -0
  178. calc_terminal/report.py +162 -0
  179. calc_terminal/research/__init__.py +45 -0
  180. calc_terminal/research/artifact_intel.py +126 -0
  181. calc_terminal/research/data_lineage.py +123 -0
  182. calc_terminal/research/experiment_ledger.py +303 -0
  183. calc_terminal/research/reproducibility.py +131 -0
  184. calc_terminal/resilience/__init__.py +47 -0
  185. calc_terminal/resilience/agent_state.py +121 -0
  186. calc_terminal/resilience/capability_matcher.py +174 -0
  187. calc_terminal/resilience/circuit_breaker.py +158 -0
  188. calc_terminal/resilience/failover_engine.py +230 -0
  189. calc_terminal/resilience/health_monitor.py +192 -0
  190. calc_terminal/resilience/ollama_adapter.py +125 -0
  191. calc_terminal/resilience/orchestrator.py +312 -0
  192. calc_terminal/resilience/types.py +134 -0
  193. calc_terminal/sandbox.py +98 -0
  194. calc_terminal/scires.py +558 -0
  195. calc_terminal/security_scanner.py +126 -0
  196. calc_terminal/session.py +294 -0
  197. calc_terminal/sim3d.py +206 -0
  198. calc_terminal/solver.py +276 -0
  199. calc_terminal/sound.py +127 -0
  200. calc_terminal/task_reports.py +287 -0
  201. calc_terminal/terminal_host.py +201 -0
  202. calc_terminal/terminal_identity.py +411 -0
  203. calc_terminal/test_ai_mode_reliability.py +344 -0
  204. calc_terminal/test_browser.py +368 -0
  205. calc_terminal/test_code_editor_upgrade.py +485 -0
  206. calc_terminal/test_customization.py +1148 -0
  207. calc_terminal/test_customization_ui.py +612 -0
  208. calc_terminal/test_dynamic_registry.py +304 -0
  209. calc_terminal/test_extensions.py +436 -0
  210. calc_terminal/test_overhaul.py +557 -0
  211. calc_terminal/test_project_detect.py +255 -0
  212. calc_terminal/test_root_cause_fix.py +527 -0
  213. calc_terminal/test_stability.py +532 -0
  214. calc_terminal/test_terminal_identity.py +132 -0
  215. calc_terminal/test_v079_speed.py +460 -0
  216. calc_terminal/theme.py +1107 -0
  217. calc_terminal/timeline.py +139 -0
  218. calc_terminal/todos.py +246 -0
  219. calc_terminal/tool_call_normalizer.py +419 -0
  220. calc_terminal/tui.py +104 -0
  221. calc_terminal/ui/__init__.py +8 -0
  222. calc_terminal/ui/activity_panel.py +231 -0
  223. calc_terminal/ui/activity_stream_panel.py +238 -0
  224. calc_terminal/ui/animations.py +122 -0
  225. calc_terminal/ui/app.py +7271 -0
  226. calc_terminal/ui/attach_panel.py +597 -0
  227. calc_terminal/ui/attachments.py +424 -0
  228. calc_terminal/ui/backup_panel.py +810 -0
  229. calc_terminal/ui/browser_shell.py +887 -0
  230. calc_terminal/ui/cat_agent.py +357 -0
  231. calc_terminal/ui/chats_panel.py +899 -0
  232. calc_terminal/ui/command_palette.py +125 -0
  233. calc_terminal/ui/command_palette_modal.py +166 -0
  234. calc_terminal/ui/composer.py +1141 -0
  235. calc_terminal/ui/context_menu.py +197 -0
  236. calc_terminal/ui/conversation.py +1435 -0
  237. calc_terminal/ui/customization_panel.py +1229 -0
  238. calc_terminal/ui/dashboard.py +404 -0
  239. calc_terminal/ui/design_system.py +557 -0
  240. calc_terminal/ui/diff_panel.py +213 -0
  241. calc_terminal/ui/editor.py +2102 -0
  242. calc_terminal/ui/empty_state.py +302 -0
  243. calc_terminal/ui/events.py +487 -0
  244. calc_terminal/ui/extensions_panel.py +815 -0
  245. calc_terminal/ui/footer.py +166 -0
  246. calc_terminal/ui/gestures_panel.py +383 -0
  247. calc_terminal/ui/goodbye_screen.py +100 -0
  248. calc_terminal/ui/header.py +1034 -0
  249. calc_terminal/ui/help_panel.py +254 -0
  250. calc_terminal/ui/live_activities.py +914 -0
  251. calc_terminal/ui/mcp_panel.py +570 -0
  252. calc_terminal/ui/memory_center.py +524 -0
  253. calc_terminal/ui/mode_colors_panel.py +525 -0
  254. calc_terminal/ui/nav_screens.py +747 -0
  255. calc_terminal/ui/ollama_panel.py +536 -0
  256. calc_terminal/ui/palette.py +221 -0
  257. calc_terminal/ui/permission_panel.py +269 -0
  258. calc_terminal/ui/personalization_panel.py +517 -0
  259. calc_terminal/ui/personalize_center.py +1568 -0
  260. calc_terminal/ui/preview_panel.py +441 -0
  261. calc_terminal/ui/resizers.py +402 -0
  262. calc_terminal/ui/sidebar.py +1285 -0
  263. calc_terminal/ui/statusbar.py +168 -0
  264. calc_terminal/ui/theme_css.py +1396 -0
  265. calc_terminal/ui/thinking.py +226 -0
  266. calc_terminal/ui/timeline_panel.py +102 -0
  267. calc_terminal/ui/todo_panel.py +193 -0
  268. calc_terminal/ui/viewport.py +136 -0
  269. calc_terminal/ui/vision_panel.py +489 -0
  270. calc_terminal/ui/welcome_modal.py +343 -0
  271. calc_terminal/ui/widgets.py +160 -0
  272. calc_terminal/ui/workspace.py +831 -0
  273. calc_terminal/viewers/__init__.py +1 -0
  274. calc_terminal/viewers/document_viewer.py +252 -0
  275. calc_terminal/viewers/image_viewer.py +241 -0
  276. calc_terminal/viewers/pdf_viewer.py +203 -0
  277. calc_terminal/viewers/presentation_viewer.py +164 -0
  278. calc_terminal/viewers/registry.py +120 -0
  279. calc_terminal/viewers/spreadsheet_viewer.py +204 -0
  280. calc_terminal/vision/__init__.py +89 -0
  281. calc_terminal/vision/analysis.py +194 -0
  282. calc_terminal/vision/annotations.py +297 -0
  283. calc_terminal/vision/capture.py +171 -0
  284. calc_terminal/vision/context.py +231 -0
  285. calc_terminal/vision/correlation.py +169 -0
  286. calc_terminal/vision/cursor.py +258 -0
  287. calc_terminal/vision/events.py +66 -0
  288. calc_terminal/vision/frame_pipeline.py +259 -0
  289. calc_terminal/vision/priority.py +218 -0
  290. calc_terminal/vision/provider.py +180 -0
  291. calc_terminal/vision/safety.py +149 -0
  292. calc_terminal/vision/session.py +281 -0
  293. calc_terminal/vision/verify.py +162 -0
  294. calc_terminal/vision.py +514 -0
  295. calc_terminal/vscode_integration.py +113 -0
  296. calc_terminal/web/__init__.py +8 -0
  297. calc_terminal/web/cat_runtime.py +710 -0
  298. calc_terminal/web/server.py +2891 -0
  299. calc_terminal/web/static/css/app.css +3152 -0
  300. calc_terminal/web/static/icons/badge-72.png +0 -0
  301. calc_terminal/web/static/icons/cat.ico +0 -0
  302. calc_terminal/web/static/icons/icon-128.png +0 -0
  303. calc_terminal/web/static/icons/icon-144.png +0 -0
  304. calc_terminal/web/static/icons/icon-152.png +0 -0
  305. calc_terminal/web/static/icons/icon-192.png +0 -0
  306. calc_terminal/web/static/icons/icon-384.png +0 -0
  307. calc_terminal/web/static/icons/icon-512.png +0 -0
  308. calc_terminal/web/static/icons/icon-72.png +0 -0
  309. calc_terminal/web/static/icons/icon-96.png +0 -0
  310. calc_terminal/web/static/icons/icon.svg +34 -0
  311. calc_terminal/web/static/icons/new-project.png +0 -0
  312. calc_terminal/web/static/icons/open-project.png +0 -0
  313. calc_terminal/web/static/index.html +734 -0
  314. calc_terminal/web/static/js/app.js +2403 -0
  315. calc_terminal/web/static/manifest.json +88 -0
  316. calc_terminal/web/static/sw.js +230 -0
  317. calc_terminal/workflow_engine.py +769 -0
  318. calc_terminal/workspace.py +593 -0
  319. calc_terminal/workspace_index.py +385 -0
  320. cct_cli-0.7.9.0.dist-info/METADATA +210 -0
  321. cct_cli-0.7.9.0.dist-info/RECORD +325 -0
  322. cct_cli-0.7.9.0.dist-info/WHEEL +5 -0
  323. cct_cli-0.7.9.0.dist-info/entry_points.txt +4 -0
  324. cct_cli-0.7.9.0.dist-info/licenses/LICENSE +21 -0
  325. 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