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,265 @@
1
+ """
2
+ CCT first-run initialization system.
3
+
4
+ Global-install lifecycle:
5
+
6
+ cct
7
+ -> main() (calc_terminal.cli)
8
+ -> ensure_first_run() (this module)
9
+ -> initialize_first_run() (the one-time setup; also exposed to
10
+ the world as model.initialize_model()
11
+ in the source tree's model.py)
12
+ -> .initialized marker (written ONLY after success)
13
+ -> existing CCT startup (calc_terminal.cli._launch)
14
+
15
+ Every later `cct` launch sees the marker and skips straight to launch.
16
+ A failed initialization writes NO marker, so the next launch retries —
17
+ never silently claiming success.
18
+
19
+ Nothing here runs during `pip install`: the package installs code and
20
+ resources only; initialization happens inside the application lifecycle,
21
+ the first time the user actually runs `cct`.
22
+
23
+ Storage: a platform-aware application-data directory (never the source
24
+ tree, never hard-coded Windows paths). Override for testing/power users
25
+ with the CCT_DATA_DIR environment variable:
26
+
27
+ Windows %LOCALAPPDATA%\\CCT
28
+ Linux $XDG_CONFIG_HOME/cct (default ~/.config/cct)
29
+ macOS ~/Library/Application Support/CCT
30
+
31
+ <data dir>/
32
+ |-- config.json seeded defaults (never clobbers user edits)
33
+ |-- models.json seed copy of the packaged model metadata
34
+ |-- providers.json seed copy of the packaged provider registry
35
+ |-- cache/ model cache / runtime resources
36
+ |-- logs/ startup + initialization logs
37
+ `-- .initialized marker; created only by a SUCCESSFUL init
38
+ """
39
+
40
+ import json
41
+ import os
42
+ import sys
43
+ import time
44
+
45
+ _MARKER_NAME = ".initialized"
46
+ _MARKER_VERSION = 1
47
+
48
+
49
+ # ------------------------------------------------------------- paths ----
50
+
51
+ def data_dir():
52
+ """The CCT application-data directory for this platform.
53
+
54
+ CCT_DATA_DIR (if set) wins — that's how tests simulate a clean
55
+ machine without touching the real profile. Otherwise the directory
56
+ follows each OS's convention: %LOCALAPPDATA% on Windows,
57
+ $XDG_CONFIG_HOME (or ~/.config) on Linux, ~/Library/Application
58
+ Support on macOS. All three match the CCT application-data layout
59
+ (config.json / models.json / providers.json / cache / logs /
60
+ .initialized)."""
61
+ override = os.environ.get("CCT_DATA_DIR", "").strip()
62
+ if override:
63
+ return os.path.abspath(override)
64
+ if sys.platform == "win32":
65
+ base = os.environ.get("LOCALAPPDATA") or os.path.join(
66
+ os.path.expanduser("~"), "AppData", "Local")
67
+ return os.path.join(base, "CCT")
68
+ if sys.platform == "darwin":
69
+ return os.path.join(
70
+ os.path.expanduser("~"), "Library", "Application Support", "CCT")
71
+ # Linux / BSD / other Unix
72
+ xdg = os.environ.get("XDG_CONFIG_HOME", "").strip()
73
+ base = xdg or os.path.join(os.path.expanduser("~"), ".config")
74
+ return os.path.join(base, "cct")
75
+
76
+
77
+ def initialized_path():
78
+ return os.path.join(data_dir(), _MARKER_NAME)
79
+
80
+
81
+ def cache_dir():
82
+ return os.path.join(data_dir(), "cache")
83
+
84
+
85
+ def logs_dir():
86
+ return os.path.join(data_dir(), "logs")
87
+
88
+
89
+ def is_initialized():
90
+ """True when a successful first-run initialization has completed."""
91
+ return os.path.isfile(initialized_path())
92
+
93
+
94
+ def mark_initialized():
95
+ """Write the marker. Called ONLY after initialization succeeded."""
96
+ path = initialized_path()
97
+ payload = {
98
+ "version": _MARKER_VERSION,
99
+ "cct_version": _cct_version(),
100
+ "timestamp": time.strftime("%Y-%m-%dT%H:%M:%S"),
101
+ }
102
+ tmp = path + ".tmp"
103
+ with open(tmp, "w", encoding="utf-8") as f:
104
+ json.dump(payload, f, indent=2)
105
+ os.replace(tmp, path)
106
+
107
+
108
+ def _cct_version():
109
+ try:
110
+ from .app import VERSION
111
+ return VERSION
112
+ except Exception:
113
+ return "0.0.0"
114
+
115
+
116
+ # ------------------------------------------------------------ seeding ----
117
+
118
+ def _package_resource(relpath):
119
+ """Resolve a packaged resource file to an absolute path. The
120
+ resources live inside the calc_terminal package itself, so this
121
+ works identically from a source checkout and from site-packages."""
122
+ base = os.path.dirname(os.path.abspath(__file__))
123
+ return os.path.join(base, relpath)
124
+
125
+
126
+ def _write_json_if_missing(path, data):
127
+ if os.path.exists(path):
128
+ return False
129
+ with open(path, "w", encoding="utf-8") as f:
130
+ json.dump(data, f, indent=2)
131
+ return True
132
+
133
+
134
+ def _copy_resource_if_missing(dst, src):
135
+ if os.path.exists(dst) or not os.path.exists(src):
136
+ return
137
+ with open(src, "r", encoding="utf-8") as r, \
138
+ open(dst, "w", encoding="utf-8") as w:
139
+ w.write(r.read())
140
+
141
+
142
+ def seed_defaults():
143
+ """Create the application-data structure and seed the reference
144
+ files. Existing files are never overwritten — the seeds are
145
+ factory defaults, user edits win."""
146
+ root = data_dir()
147
+ os.makedirs(cache_dir(), exist_ok=True)
148
+ os.makedirs(logs_dir(), exist_ok=True)
149
+ try:
150
+ from .config import load_config
151
+ _write_json_if_missing(
152
+ os.path.join(root, "config.json"), load_config().to_dict())
153
+ except Exception:
154
+ # config seeding is best-effort; a broken one must not fail the
155
+ # whole first run
156
+ pass
157
+ _copy_resource_if_missing(
158
+ os.path.join(root, "models.json"),
159
+ _package_resource(os.path.join("models", "model_metadata.json")))
160
+ _copy_resource_if_missing(
161
+ os.path.join(root, "providers.json"),
162
+ _package_resource(os.path.join("providers", "providers.json")))
163
+
164
+
165
+ # ------------------------------------------------------ initialization --
166
+
167
+ def initialize_first_run():
168
+ """The one-time initialization (exposed from model.py as
169
+ initialize_model()). Returns (ok, message).
170
+
171
+ Creates the application-data tree, seeds config/models/providers
172
+ reference files, and — only if every step succeeded — writes the
173
+ .initialized marker. Any failure returns (False, reason) with NO
174
+ marker, so the next `cct` launch retries."""
175
+ try:
176
+ seed_defaults()
177
+ mark_initialized()
178
+ return True, "initialization complete"
179
+ except OSError as e:
180
+ return False, f"cannot prepare application data: {e}"
181
+ except Exception as e:
182
+ return False, f"unexpected error: {type(e).__name__}: {e}"
183
+
184
+
185
+ def print_environment_card():
186
+ """Print the Intelligent First-Run Diagnostic & Environment Card."""
187
+ import shutil
188
+ import platform
189
+ print("=" * 72)
190
+ print(" CAT INTELLIGENT ENVIRONMENT DETECTION")
191
+ print("=" * 72)
192
+
193
+ py_ver = platform.python_version()
194
+ os_desc = f"{platform.system()} {platform.release()} ({platform.machine()})"
195
+ git_installed = bool(shutil.which("git"))
196
+ print(f" Operating System : {os_desc}")
197
+ print(f" Python Runtime : {py_ver}")
198
+ print(f" Git Version Control: {'Installed (Available)' if git_installed else 'Missing (Optional)'}")
199
+
200
+ prof = None
201
+ try:
202
+ from .hardware_analyzer import HardwareAnalyzer
203
+ prof = HardwareAnalyzer.analyze()
204
+ print(f" CPU Compute : {prof.cpu_model} ({prof.cpu_threads} logical threads)")
205
+ print(f" System RAM : {prof.ram_total_gb:.1f} GB ({prof.ram_available_gb:.1f} GB available)")
206
+ if prof.has_gpu:
207
+ print(f" GPU Compute : {prof.gpu_name} ({prof.vram_gb:.1f} GB VRAM via {prof.gpu_backend})")
208
+ else:
209
+ print(" GPU Compute : CPU / Integrated Memory")
210
+ print(f" Local AI Tier : {prof.local_ai_tier.value}")
211
+ except Exception as e:
212
+ print(f" Hardware Detection : Basic ({e})")
213
+
214
+ try:
215
+ from .ollama_download import is_ollama_running, is_ollama_installed
216
+ if is_ollama_running():
217
+ ollama_st = "Running (Active on port 11434)"
218
+ elif is_ollama_installed():
219
+ ollama_st = "Installed (Offline — will auto-launch when needed)"
220
+ else:
221
+ ollama_st = "Not Detected (Optional: install from https://ollama.com)"
222
+ print(f" Local Ollama Engine: {ollama_st}")
223
+ except Exception:
224
+ pass
225
+
226
+ try:
227
+ from .compatibility_engine import ModelCompatibilityEngine
228
+ from .ollama_catalog import all_models
229
+ engine = ModelCompatibilityEngine()
230
+ recs = engine.recommend_models(all_models(include_dynamic=True))
231
+ best_code = recs.get("best_coding", [{}])[0].get("model", {}).get("name", "qwen2.5-coder:3b")
232
+ best_fast = recs.get("best_fast", [{}])[0].get("model", {}).get("name", "smollm2:1.7b")
233
+ ram_tag = f"{prof.ram_total_gb:.0f}GB RAM" if prof else "your device"
234
+ print("-" * 72)
235
+ print(" RECOMMENDED STARTER SETUP FOR YOUR HARDWARE:")
236
+ print(f" * Primary Coding Model : {best_code} (Optimized for {ram_tag})")
237
+ print(f" * Fast Edge Autocomplete: {best_fast}")
238
+ print(f" * Quick Download Command : cat models install {best_code}")
239
+ except Exception:
240
+ pass
241
+ print("=" * 72)
242
+
243
+
244
+ def ensure_first_run():
245
+ """CLI-level first-run orchestrator. Prints the startup banner and
246
+ runs the one-time initialization when needed. Returns an exit code
247
+ (0 = continue to launch, non-zero = stop with an error)."""
248
+ if is_initialized():
249
+ print("Starting CAT...")
250
+ return 0
251
+ print("CAT — Coding Agent Terminal")
252
+ print("Creator: Kazi Zillani")
253
+ print("First-time initialization...")
254
+ print_environment_card()
255
+ print("Preparing required resources...")
256
+ ok, msg = initialize_first_run()
257
+ if not ok:
258
+ print(f"ERROR: first-run initialization failed ({msg}).")
259
+ print("Nothing was marked as initialized — the next launch will retry.")
260
+ print(f"Application data directory: {data_dir()}")
261
+ return 1
262
+ print("Initialization complete.")
263
+ print()
264
+ print("Starting CAT...")
265
+ return 0