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,385 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CCT — workspace_index.py: AI Workspace Understanding (v0.7.7 Workspace
|
|
3
|
+
Management Preview, spec section 6).
|
|
4
|
+
|
|
5
|
+
Whenever the workspace changes, CCT indexes it: scans the file tree,
|
|
6
|
+
reads the README and configuration files, detects the programming
|
|
7
|
+
language(s) and package managers, understands dependencies, and builds
|
|
8
|
+
a compact project context the AI (and the header) can use.
|
|
9
|
+
|
|
10
|
+
The scan is honest and bounded:
|
|
11
|
+
|
|
12
|
+
- Never follows .git / node_modules / venv / __pycache__ / dist /
|
|
13
|
+
build (the classic noise folders);
|
|
14
|
+
- file/dir counts are capped; the structure sample is capped;
|
|
15
|
+
- dependency parsing reads real manifests (requirements.txt,
|
|
16
|
+
package.json, Cargo.toml, go.mod, pyproject.toml) and takes the
|
|
17
|
+
top-level names only;
|
|
18
|
+
- every failure degrades to "unknown/empty" — no fabricated data.
|
|
19
|
+
|
|
20
|
+
Progress is reported through an optional `on_progress(stage,
|
|
21
|
+
message)` callback with the spec's exact stages:
|
|
22
|
+
"scanning" -> "Reading Files..." -> "building" -> "ready".
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
print("This is a library file and is not meant to be run directly.")
|
|
27
|
+
import sys
|
|
28
|
+
sys.exit(1)
|
|
29
|
+
|
|
30
|
+
import os
|
|
31
|
+
|
|
32
|
+
PROGRESS_STAGES = ("scanning", "reading", "building", "ready")
|
|
33
|
+
|
|
34
|
+
STAGE_LABELS = {
|
|
35
|
+
"scanning": "\U0001f50d Scanning Workspace...",
|
|
36
|
+
"reading": "\U0001f4d6 Reading Files...",
|
|
37
|
+
"building": "\U0001f9f1 Building Context...",
|
|
38
|
+
"ready": "\u2705 Ready",
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
_SKIP_DIRS = {
|
|
42
|
+
".git", "node_modules", "__pycache__", ".venv", "venv", "env",
|
|
43
|
+
"dist", "build", ".idea", ".vscode", ".tox", ".mypy_cache",
|
|
44
|
+
".pytest_cache", "target", "bin", "obj", ".next", "out",
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
_LANGUAGE_BY_EXT = {
|
|
48
|
+
".py": "Python", ".pyw": "Python", ".ipynb": "Python",
|
|
49
|
+
".js": "JavaScript", ".jsx": "JavaScript", ".mjs": "JavaScript",
|
|
50
|
+
".ts": "TypeScript", ".tsx": "TypeScript",
|
|
51
|
+
".html": "HTML", ".css": "CSS", ".scss": "SCSS", ".sass": "Sass",
|
|
52
|
+
".json": "JSON", ".yaml": "YAML", ".yml": "YAML", ".toml": "TOML",
|
|
53
|
+
".xml": "XML", ".md": "Markdown", ".rst": "reStructuredText",
|
|
54
|
+
".c": "C", ".h": "C", ".cpp": "C++", ".cc": "C++", ".hpp": "C++",
|
|
55
|
+
".cs": "C#", ".java": "Java", ".kt": "Kotlin", ".kts": "Kotlin",
|
|
56
|
+
".go": "Go", ".rs": "Rust", ".rb": "Ruby", ".php": "PHP",
|
|
57
|
+
".swift": "Swift", ".m": "Objective-C", ".scala": "Scala",
|
|
58
|
+
".sh": "Shell", ".bat": "Batch", ".ps1": "PowerShell",
|
|
59
|
+
".sql": "SQL", ".r": "R", ".lua": "Lua", ".pl": "Perl",
|
|
60
|
+
".dart": "Dart", ".vue": "Vue", ".svelte": "Svelte",
|
|
61
|
+
".ex": "Elixir", ".exs": "Elixir", ".erl": "Erlang",
|
|
62
|
+
".hs": "Haskell", ".clj": "Clojure", ".zig": "Zig",
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# Top-level manifest files that reveal package managers / deps.
|
|
66
|
+
_CONFIG_FILES = {
|
|
67
|
+
"pyproject.toml": "pyproject.toml (PEP 621)",
|
|
68
|
+
"requirements.txt": "requirements.txt",
|
|
69
|
+
"setup.py": "setup.py",
|
|
70
|
+
"setup.cfg": "setup.cfg",
|
|
71
|
+
"Pipfile": "Pipfile",
|
|
72
|
+
"poetry.lock": "poetry.lock",
|
|
73
|
+
"uv.lock": "uv.lock",
|
|
74
|
+
"package.json": "package.json",
|
|
75
|
+
"package-lock.json": "package-lock.json",
|
|
76
|
+
"pnpm-lock.yaml": "pnpm-lock.yaml",
|
|
77
|
+
"yarn.lock": "yarn.lock",
|
|
78
|
+
"Cargo.toml": "Cargo.toml",
|
|
79
|
+
"go.mod": "go.mod",
|
|
80
|
+
"composer.json": "composer.json",
|
|
81
|
+
"Gemfile": "Gemfile",
|
|
82
|
+
"build.gradle": "build.gradle",
|
|
83
|
+
"pom.xml": "pom.xml",
|
|
84
|
+
"Dockerfile": "Dockerfile",
|
|
85
|
+
"docker-compose.yml": "docker-compose.yml",
|
|
86
|
+
"Makefile": "Makefile",
|
|
87
|
+
".env.example": ".env.example",
|
|
88
|
+
".editorconfig": ".editorconfig",
|
|
89
|
+
"tsconfig.json": "tsconfig.json",
|
|
90
|
+
".eslintrc": ".eslintrc",
|
|
91
|
+
"vite.config.js": "vite.config.js",
|
|
92
|
+
"vite.config.ts": "vite.config.ts",
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
_README_NAMES = ("README.md", "README", "Readme.md", "readme.md",
|
|
96
|
+
"README.txt", "README.rst")
|
|
97
|
+
|
|
98
|
+
_MAX_SCAN_FILES = 20000
|
|
99
|
+
_MAX_DEPENDENCIES = 40
|
|
100
|
+
_MAX_STRUCTURE = 40
|
|
101
|
+
_MAX_README_CHARS = 2000
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _scan(path, on_progress=None):
|
|
105
|
+
"""Walks the tree once, collecting counts, extension histogram,
|
|
106
|
+
top-level structure, config files, and readmes."""
|
|
107
|
+
file_count = 0
|
|
108
|
+
dir_count = 0
|
|
109
|
+
total_size = 0
|
|
110
|
+
ext_counts = {}
|
|
111
|
+
structure = []
|
|
112
|
+
configs = []
|
|
113
|
+
readme_path = None
|
|
114
|
+
root = path
|
|
115
|
+
for base, dirs, files in os.walk(path):
|
|
116
|
+
dirs[:] = sorted(d for d in dirs if d not in _SKIP_DIRS)
|
|
117
|
+
rel = os.path.relpath(base, root)
|
|
118
|
+
if rel != ".":
|
|
119
|
+
dir_count += 1
|
|
120
|
+
if rel != "." and len(structure) < _MAX_STRUCTURE:
|
|
121
|
+
structure.append({"type": "dir", "path": rel})
|
|
122
|
+
for name in sorted(files):
|
|
123
|
+
full = os.path.join(base, name)
|
|
124
|
+
try:
|
|
125
|
+
size = os.path.getsize(full)
|
|
126
|
+
except OSError:
|
|
127
|
+
continue
|
|
128
|
+
total_size += size
|
|
129
|
+
file_count += 1
|
|
130
|
+
ext = os.path.splitext(name)[1].lower()
|
|
131
|
+
ext_counts[ext] = ext_counts.get(ext, 0) + 1
|
|
132
|
+
if file_count > _MAX_SCAN_FILES:
|
|
133
|
+
return None
|
|
134
|
+
rel_name = name if rel == "." else os.path.join(rel, name)
|
|
135
|
+
if rel == "." and name in _CONFIG_FILES:
|
|
136
|
+
configs.append(name)
|
|
137
|
+
if len(structure) < _MAX_STRUCTURE and rel == "." and name:
|
|
138
|
+
structure.append({"type": "file", "path": name})
|
|
139
|
+
if readme_path is None and name in _README_NAMES:
|
|
140
|
+
readme_path = full
|
|
141
|
+
return {
|
|
142
|
+
"file_count": file_count,
|
|
143
|
+
"dir_count": dir_count,
|
|
144
|
+
"total_size": total_size,
|
|
145
|
+
"ext_counts": ext_counts,
|
|
146
|
+
"structure": structure,
|
|
147
|
+
"configs": sorted(set(configs)),
|
|
148
|
+
"readme_path": readme_path,
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _languages(ext_counts):
|
|
153
|
+
by_lang = {}
|
|
154
|
+
for ext, count in ext_counts.items():
|
|
155
|
+
lang = _LANGUAGE_BY_EXT.get(ext)
|
|
156
|
+
if lang:
|
|
157
|
+
by_lang[lang] = by_lang.get(lang, 0) + count
|
|
158
|
+
ordered = sorted(by_lang.items(), key=lambda kv: -kv[1])
|
|
159
|
+
return [lang for lang, _n in ordered[:6]]
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _read_readme(readme_path):
|
|
163
|
+
if not readme_path:
|
|
164
|
+
return None
|
|
165
|
+
try:
|
|
166
|
+
with open(readme_path, "r", encoding="utf-8", errors="replace") as f:
|
|
167
|
+
text = f.read(200000)
|
|
168
|
+
lines = [ln.strip() for ln in text.splitlines() if ln.strip()]
|
|
169
|
+
summary_lines = []
|
|
170
|
+
for ln in lines:
|
|
171
|
+
if ln.startswith("#"):
|
|
172
|
+
continue
|
|
173
|
+
if ln.startswith("```"):
|
|
174
|
+
break
|
|
175
|
+
summary_lines.append(ln)
|
|
176
|
+
if len(summary_lines) >= 6:
|
|
177
|
+
break
|
|
178
|
+
snippet = " \u00b7 ".join(summary_lines)
|
|
179
|
+
return snippet[:_MAX_README_CHARS] if snippet else None
|
|
180
|
+
except Exception:
|
|
181
|
+
return None
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _dependencies(path):
|
|
185
|
+
"""Top-level dependency names from real manifests. Capped, honest:
|
|
186
|
+
only names that can actually be parsed are listed."""
|
|
187
|
+
deps = []
|
|
188
|
+
|
|
189
|
+
def _reqs(full):
|
|
190
|
+
try:
|
|
191
|
+
with open(full, "r", encoding="utf-8", errors="replace") as f:
|
|
192
|
+
for line in f:
|
|
193
|
+
line = line.split("#")[0].strip()
|
|
194
|
+
if not line:
|
|
195
|
+
continue
|
|
196
|
+
name = line.split("==")[0].split(">=")[0].split("<")[0] \
|
|
197
|
+
.split("[")[0].strip().replace("_", "-")
|
|
198
|
+
if name and name not in deps:
|
|
199
|
+
deps.append(name)
|
|
200
|
+
except Exception:
|
|
201
|
+
pass
|
|
202
|
+
|
|
203
|
+
def _json(full, keys):
|
|
204
|
+
try:
|
|
205
|
+
with open(full, "r", encoding="utf-8", errors="replace") as f:
|
|
206
|
+
import json
|
|
207
|
+
data = json.load(f)
|
|
208
|
+
for key in keys:
|
|
209
|
+
block = data.get(key) or {}
|
|
210
|
+
if isinstance(block, dict):
|
|
211
|
+
for name in block:
|
|
212
|
+
if name and name not in deps:
|
|
213
|
+
deps.append(name)
|
|
214
|
+
except Exception:
|
|
215
|
+
pass
|
|
216
|
+
|
|
217
|
+
_METADATA_KEYS = {
|
|
218
|
+
"name", "version", "description", "requires-python",
|
|
219
|
+
"authors", "maintainers", "license", "readme", "homepage",
|
|
220
|
+
"repository", "keywords", "classifiers", "dependencies",
|
|
221
|
+
"optional-dependencies", "url", "author", "license-file",
|
|
222
|
+
"documentation", "issues", "changelog", "build-backend",
|
|
223
|
+
"requires", "build-system", "module", "bin", "edition",
|
|
224
|
+
"rust-version", "publish", "go", "toolchain",
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
def _kv(full):
|
|
228
|
+
try:
|
|
229
|
+
with open(full, "r", encoding="utf-8", errors="replace") as f:
|
|
230
|
+
for line in f:
|
|
231
|
+
line = line.strip()
|
|
232
|
+
if line.startswith("[") or not line or "=" not in line:
|
|
233
|
+
continue
|
|
234
|
+
key = line.split("=")[0].strip().strip('"')
|
|
235
|
+
if not key or key in _METADATA_KEYS or key.startswith("."):
|
|
236
|
+
continue
|
|
237
|
+
if key not in deps:
|
|
238
|
+
deps.append(key)
|
|
239
|
+
except Exception:
|
|
240
|
+
pass
|
|
241
|
+
|
|
242
|
+
for name, full in (("requirements.txt", None), ("pyproject.toml", None)):
|
|
243
|
+
p = os.path.join(path, name)
|
|
244
|
+
if os.path.isfile(p):
|
|
245
|
+
_reqs(p) if name == "requirements.txt" else _kv(p)
|
|
246
|
+
pkg = os.path.join(path, "package.json")
|
|
247
|
+
if os.path.isfile(pkg):
|
|
248
|
+
_json(pkg, ("dependencies", "devDependencies", "peerDependencies"))
|
|
249
|
+
go_mod = os.path.join(path, "go.mod")
|
|
250
|
+
if os.path.isfile(go_mod):
|
|
251
|
+
_kv(go_mod)
|
|
252
|
+
cargo = os.path.join(path, "Cargo.toml")
|
|
253
|
+
if os.path.isfile(cargo):
|
|
254
|
+
_kv(cargo)
|
|
255
|
+
return deps[:_MAX_DEPENDENCIES]
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _package_managers(path):
|
|
259
|
+
found = []
|
|
260
|
+
names = set(os.listdir(path)) if os.path.isdir(path) else set()
|
|
261
|
+
if "requirements.txt" in names or "pyproject.toml" in names or "setup.py" in names:
|
|
262
|
+
found.append("pip")
|
|
263
|
+
if "Pipfile" in names or "poetry.lock" in names:
|
|
264
|
+
found.append("poetry")
|
|
265
|
+
if "uv.lock" in names:
|
|
266
|
+
found.append("uv")
|
|
267
|
+
if "package.json" in names or "yarn.lock" in names or "pnpm-lock.yaml" in names:
|
|
268
|
+
found.append("npm")
|
|
269
|
+
if "Cargo.toml" in names or "Cargo.lock" in names:
|
|
270
|
+
found.append("cargo")
|
|
271
|
+
if "go.mod" in names:
|
|
272
|
+
found.append("go")
|
|
273
|
+
if "composer.json" in names:
|
|
274
|
+
found.append("composer")
|
|
275
|
+
if "Gemfile" in names:
|
|
276
|
+
found.append("bundler")
|
|
277
|
+
if "pom.xml" in names or "build.gradle" in names:
|
|
278
|
+
found.append("maven")
|
|
279
|
+
return found
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def index_project(path, on_progress=None):
|
|
283
|
+
"""Builds the project context for `path` (spec section 6). Returns
|
|
284
|
+
a dict with keys: languages, file_count, dir_count, structure,
|
|
285
|
+
configs, readme, package_managers, dependencies, git, description.
|
|
286
|
+
`on_progress(stage, message)` fires once per stage in order:
|
|
287
|
+
scanning -> reading -> building -> ready. Never raises for
|
|
288
|
+
filesystem problems — a broken path yields an honest minimal
|
|
289
|
+
context."""
|
|
290
|
+
import time
|
|
291
|
+
|
|
292
|
+
def _progress(stage):
|
|
293
|
+
if on_progress:
|
|
294
|
+
try:
|
|
295
|
+
on_progress(stage, STAGE_LABELS[stage])
|
|
296
|
+
except Exception:
|
|
297
|
+
pass
|
|
298
|
+
|
|
299
|
+
ctx = {"path": os.path.abspath(path), "ok": False,
|
|
300
|
+
"languages": [], "file_count": 0, "dir_count": 0,
|
|
301
|
+
"structure": [], "configs": [], "readme": None,
|
|
302
|
+
"package_managers": [], "dependencies": [],
|
|
303
|
+
"git": None, "description": "", "elapsed": 0.0}
|
|
304
|
+
if not os.path.isdir(path):
|
|
305
|
+
return ctx
|
|
306
|
+
_progress("scanning")
|
|
307
|
+
t0 = time.time()
|
|
308
|
+
scan = _scan(path, on_progress)
|
|
309
|
+
if scan is None:
|
|
310
|
+
scan = {"file_count": 0, "dir_count": 0, "total_size": 0,
|
|
311
|
+
"ext_counts": {}, "structure": [], "configs": [],
|
|
312
|
+
"readme_path": None}
|
|
313
|
+
_progress("reading")
|
|
314
|
+
readme = _read_readme(scan["readme_path"])
|
|
315
|
+
_progress("building")
|
|
316
|
+
from . import workspace as ws
|
|
317
|
+
branch = ws.git_branch(path)
|
|
318
|
+
git_status = ws.git_status_summary(path)
|
|
319
|
+
ctx.update({
|
|
320
|
+
"ok": True,
|
|
321
|
+
"languages": _languages(scan["ext_counts"]),
|
|
322
|
+
"file_count": scan["file_count"],
|
|
323
|
+
"dir_count": scan["dir_count"],
|
|
324
|
+
"total_size": scan["total_size"],
|
|
325
|
+
"structure": [s["path"] for s in scan["structure"]],
|
|
326
|
+
"configs": scan["configs"],
|
|
327
|
+
"readme": readme,
|
|
328
|
+
"package_managers": _package_managers(path),
|
|
329
|
+
"dependencies": _dependencies(path),
|
|
330
|
+
"git": {"branch": branch, "status": git_status},
|
|
331
|
+
"elapsed": round(time.time() - t0, 2),
|
|
332
|
+
})
|
|
333
|
+
_progress("ready")
|
|
334
|
+
return ctx
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def describe(ctx):
|
|
338
|
+
"""One-line human description of an indexed project, for the
|
|
339
|
+
header and the 'Ready' summary."""
|
|
340
|
+
if not ctx or not ctx.get("ok"):
|
|
341
|
+
return "Workspace not indexed"
|
|
342
|
+
langs = ", ".join(ctx["languages"][:3]) if ctx["languages"] else "unknown"
|
|
343
|
+
deps = len(ctx["dependencies"])
|
|
344
|
+
files = ctx["file_count"]
|
|
345
|
+
branch = (ctx.get("git") or {}).get("branch")
|
|
346
|
+
bits = [f"{langs} \u00b7 {files} files"]
|
|
347
|
+
if deps:
|
|
348
|
+
bits.append(f"{deps} dependencies")
|
|
349
|
+
if branch:
|
|
350
|
+
bits.append(f"\U0001f33f {branch}")
|
|
351
|
+
return " \u00b7 ".join(bits)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def summarize_context(ctx):
|
|
355
|
+
"""A compact markdown block the AI/chat can show after indexing
|
|
356
|
+
(spec section 6's 'Ready' state, with real content)."""
|
|
357
|
+
if not ctx or not ctx.get("ok"):
|
|
358
|
+
return ("*\u26a0 Couldn't index this workspace (missing or unreadable folder). "
|
|
359
|
+
"The AI will work without project context.*")
|
|
360
|
+
lines = ["\U0001f4c2 **Project Context** \u2014 ready", ""]
|
|
361
|
+
lines.append(f"- **Files**: {ctx['file_count']} files, {ctx['dir_count']} folders")
|
|
362
|
+
if ctx["languages"]:
|
|
363
|
+
lines.append("- **Languages**: " + ", ".join(ctx["languages"]))
|
|
364
|
+
if ctx["package_managers"]:
|
|
365
|
+
lines.append("- **Package managers**: " + ", ".join(ctx["package_managers"]))
|
|
366
|
+
if ctx["dependencies"]:
|
|
367
|
+
deps = ", ".join(ctx["dependencies"][:12])
|
|
368
|
+
more = f" (+{len(ctx['dependencies']) - 12} more)" if len(ctx["dependencies"]) > 12 else ""
|
|
369
|
+
lines.append(f"- **Dependencies**: {deps}{more}")
|
|
370
|
+
if ctx["configs"]:
|
|
371
|
+
lines.append("- **Config files**: " + ", ".join(ctx["configs"][:8]))
|
|
372
|
+
if ctx["readme"]:
|
|
373
|
+
lines.append(f"- **README**: {ctx['readme']}")
|
|
374
|
+
git = ctx.get("git") or {}
|
|
375
|
+
if git.get("branch"):
|
|
376
|
+
lines.append(f"- **Git**: branch `{git['branch']}`")
|
|
377
|
+
st = git.get("status")
|
|
378
|
+
if st:
|
|
379
|
+
summary = f"{st['changed']} modified, {st['added']} added, {st['deleted']} deleted"
|
|
380
|
+
lines.append(f"- **Git status**: {summary}")
|
|
381
|
+
if ctx["structure"]:
|
|
382
|
+
top = ", ".join(ctx["structure"][:12])
|
|
383
|
+
lines.append(f"- **Structure**: {top}")
|
|
384
|
+
lines.append(f"- **Indexed in**: {ctx['elapsed']}s")
|
|
385
|
+
return "\n".join(lines)
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cct-cli
|
|
3
|
+
Version: 0.7.9.0
|
|
4
|
+
Summary: CAT v0.7.9.0 — Coding Agent Terminal / terminal AI coding agent
|
|
5
|
+
Author: Kazi Zillani
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/kazizillani-oss/CAT_v0.7.9
|
|
8
|
+
Project-URL: Repository, https://github.com/kazizillani-oss/CAT_v0.7.9
|
|
9
|
+
Project-URL: Changelog, https://github.com/kazizillani-oss/CAT_v0.7.9/blob/main/CAT_v0.7.4/CHANGELOG_v0.7.9.md
|
|
10
|
+
Keywords: cat,cct-cli,cct,ai,agent,terminal,tui,cli,coding-agent
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Operating System :: MacOS
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Software Development
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: textual[syntax]>=0.60
|
|
28
|
+
Requires-Dist: rich>=13.0
|
|
29
|
+
Requires-Dist: requests>=2.31.0
|
|
30
|
+
Requires-Dist: colorama>=0.4.6; sys_platform == "win32"
|
|
31
|
+
Requires-Dist: watchdog>=4.0
|
|
32
|
+
Requires-Dist: plyer>=2.1
|
|
33
|
+
Provides-Extra: web
|
|
34
|
+
Requires-Dist: fastapi>=0.100.0; extra == "web"
|
|
35
|
+
Requires-Dist: uvicorn>=0.20.0; extra == "web"
|
|
36
|
+
Requires-Dist: pydantic>=2.0; extra == "web"
|
|
37
|
+
Requires-Dist: python-multipart>=0.0.6; extra == "web"
|
|
38
|
+
Provides-Extra: science
|
|
39
|
+
Requires-Dist: sympy>=1.12; extra == "science"
|
|
40
|
+
Requires-Dist: matplotlib>=3.7; extra == "science"
|
|
41
|
+
Requires-Dist: numpy>=1.24; extra == "science"
|
|
42
|
+
Requires-Dist: reportlab>=4.0; extra == "science"
|
|
43
|
+
Requires-Dist: pyperclip>=1.8.2; extra == "science"
|
|
44
|
+
Requires-Dist: prompt_toolkit>=3.0.43; extra == "science"
|
|
45
|
+
Provides-Extra: host
|
|
46
|
+
Requires-Dist: PySide6>=6.6; extra == "host"
|
|
47
|
+
Provides-Extra: browser
|
|
48
|
+
Requires-Dist: PySide6>=6.6; extra == "browser"
|
|
49
|
+
Requires-Dist: pywebview>=4.4; extra == "browser"
|
|
50
|
+
Requires-Dist: playwright>=1.40; extra == "browser"
|
|
51
|
+
Provides-Extra: all
|
|
52
|
+
Requires-Dist: cct-cli[browser,science,web]; extra == "all"
|
|
53
|
+
Dynamic: license-file
|
|
54
|
+
|
|
55
|
+
# Coding Agent Terminal (CAT)
|
|
56
|
+
|
|
57
|
+
<div align="center">
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
██████╗ █████╗ ████████╗
|
|
61
|
+
██╔════╝██╔══██╗╚══██╔══╝
|
|
62
|
+
██║ ███████║ ██║
|
|
63
|
+
██║ ██╔══██║ ██║
|
|
64
|
+
╚██████╗██║ ██║ ██║
|
|
65
|
+
╚═════╝╚═╝ ╚═╝ ╚═╝
|
|
66
|
+
|
|
67
|
+
CODING AGENT TERMINAL · v0.7.9.0
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
[](https://github.com/kazizillani-oss/CAT_v0.7.9/actions/workflows/ci.yml)
|
|
71
|
+
[](https://github.com/kazizillani-oss/CAT_v0.7.9)
|
|
72
|
+
[](LICENSE)
|
|
73
|
+
[]()
|
|
74
|
+
|
|
75
|
+
*An autonomous AI developer terminal and chemical computation environment styled like OpenCode, Claude Code, and Warp in the Tokyo Night theme.*
|
|
76
|
+
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## ⚡ Quick Install
|
|
82
|
+
|
|
83
|
+
CAT is distributed across multiple channels. Choose the method that best fits your workflow:
|
|
84
|
+
|
|
85
|
+
### Option 1: Install from PyPI (Recommended for most users)
|
|
86
|
+
|
|
87
|
+
CAT is published as `cct-cli` on PyPI. The PyPI distribution name and the
|
|
88
|
+
terminal command are intentionally different:
|
|
89
|
+
|
|
90
|
+
```text
|
|
91
|
+
PyPI package: cct-cli
|
|
92
|
+
CLI command: cat (plus aliases catx and cct)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Install and launch from any terminal (no need to clone the repository):
|
|
96
|
+
|
|
97
|
+
```powershell
|
|
98
|
+
python -m pip install cct-cli
|
|
99
|
+
cat --version
|
|
100
|
+
cat
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Notes:
|
|
104
|
+
|
|
105
|
+
- `cat` is the canonical command. `catx` is provided for Unix systems where
|
|
106
|
+
`cat` collides with GNU coreutils, and for Windows PowerShell where `cat`
|
|
107
|
+
is a built-in alias for `Get-Content` (use `cat.exe` or `catx` if `cat`
|
|
108
|
+
resolves to the alias in your shell).
|
|
109
|
+
- `cct` is kept as a historic alias so existing installs and docs keep working.
|
|
110
|
+
- Branding is CAT everywhere. Never install anything named `cot-ai-ide`
|
|
111
|
+
(typo) — the only official PyPI distribution is `cct-cli`.
|
|
112
|
+
- Optional extras: `pip install "cct-cli[web]"` (Fatty CAT web server),
|
|
113
|
+
`pip install "cct-cli[science]"` (calculator/graph/export features),
|
|
114
|
+
`pip install "cct-cli[browser]"` (embedded browser), or
|
|
115
|
+
`pip install "cct-cli[all]"` for everything.
|
|
116
|
+
- Requires Python 3.10 or newer (tested on 3.10–3.13).
|
|
117
|
+
|
|
118
|
+
### Option 2: Windows Installer (Native Windows experience)
|
|
119
|
+
|
|
120
|
+
Download and run the native installer:
|
|
121
|
+
- **`CAT-Setup.exe`** from [Latest Releases](https://github.com/kazizillani-oss/CAT_v0.7.9/releases/latest).
|
|
122
|
+
- Per-user installation to `%LOCALAPPDATA%\Programs\CAT` (no administrator privileges required).
|
|
123
|
+
- Automatically adds `cat`, `catx`, and `cct` to your `PATH` and configures PowerShell aliases cleanly.
|
|
124
|
+
|
|
125
|
+
Or via PowerShell:
|
|
126
|
+
```powershell
|
|
127
|
+
powershell -ExecutionPolicy Bypass -File installer/windows/scripts/install.ps1 -Install
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Option 3: Local Development / Editable Install
|
|
131
|
+
If you are developing or running from source:
|
|
132
|
+
```bash
|
|
133
|
+
git clone https://github.com/kazizillani-oss/CAT_v0.7.9.git
|
|
134
|
+
cd CAT_v0.7.9
|
|
135
|
+
pip install -e .
|
|
136
|
+
cat
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
For contributors, install with test/build tooling:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
pip install -e ".[web,science]"
|
|
143
|
+
pip install build twine pytest
|
|
144
|
+
python -m build
|
|
145
|
+
python -m twine check dist/*
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## 🚀 CLI Commands & Subcommands
|
|
151
|
+
|
|
152
|
+
| Command | Purpose |
|
|
153
|
+
| :--- | :--- |
|
|
154
|
+
| `cat` / `catx` / `cct` | Launch the interactive CAT terminal & UI. |
|
|
155
|
+
| `cat update` | Check for and install the latest CAT version from GitHub Releases. |
|
|
156
|
+
| `cat update --check` | Check if a newer version is available without installing. |
|
|
157
|
+
| `cat rollback` | Roll back to the previously installed version. |
|
|
158
|
+
| `cat repair` | Self-heal corrupted configurations, repair directory structures and file permissions. |
|
|
159
|
+
| `cat --debug` | Display detailed environment, paths, platform, and runtime debugging information. |
|
|
160
|
+
| `cat --doctor` | Run diagnostic health checks across Python, terminal capabilities, and AI providers. |
|
|
161
|
+
| `cat --version` | Display the current installed CAT version. |
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## 🛠️ Key Features
|
|
166
|
+
|
|
167
|
+
- **Tokyo Night Terminal UI**: Rich ASCII styling, 24-bit ANSI colors, split-pane Textual layout, animated spinners, and sound effects.
|
|
168
|
+
- **Autonomous Development & Workspace Management**: Detects git roots, VS Code workspaces, parses manifests, and indexes files with live progress indicators.
|
|
169
|
+
- **Universal Formula & Science Calculator**: 39+ symbolic formulas, 2D/3D animated graphs, and live Bohr/quantum orbital simulations.
|
|
170
|
+
- **Multi-Provider AI Orchestrator**: Supports OpenAI, Anthropic, Gemini, Groq, OpenRouter, and Ollama with automatic failover and tool execution.
|
|
171
|
+
- **Extensible Architecture**: `.cat` chats store and `.catxt` extension registry for custom modules and extensions.
|
|
172
|
+
- **Fomoji Server Integration**: Optional bundled local web services with automated lifecycle management.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 📦 Universal Distribution Architecture
|
|
177
|
+
|
|
178
|
+
CAT's distribution system decouples lightweight public launchers from private source code:
|
|
179
|
+
- **Zero Source Leakage**: npm and PyPI packages contain strictly minimal launchers (~4 kB) that pull platform-native binaries verified by SHA256 checksums from `release/manifest/releases.json`.
|
|
180
|
+
- **Atomic Updates & Rollbacks**: Update artifacts are validated against signed manifests before replacing running binaries, with automated snapshotting into `~/.cat/versions/`.
|
|
181
|
+
- **Command Collision Prevention**: Provides both `cat` and `catx` commands to prevent collisions with GNU coreutils `cat` on Unix and handles PowerShell's built-in `Get-Content` alias automatically.
|
|
182
|
+
|
|
183
|
+
For detailed documentation:
|
|
184
|
+
- [Distribution Architecture](docs/DISTRIBUTION.md)
|
|
185
|
+
- [Maintainer Releasing Guide](docs/RELEASING.md)
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 🧪 Testing & Verification
|
|
190
|
+
|
|
191
|
+
Run the test suite locally:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Verify release isolation, security, and version sync
|
|
195
|
+
python scripts/verify_release.py
|
|
196
|
+
|
|
197
|
+
# Run distribution integration unit tests
|
|
198
|
+
python scripts/test_distribution.py
|
|
199
|
+
|
|
200
|
+
# Test runtime builder in dry-run mode
|
|
201
|
+
python scripts/build_runtime.py --dry-run
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## 📄 License
|
|
207
|
+
|
|
208
|
+
MIT © [Kazi Zillani](https://github.com/kazizillani-oss)
|
|
209
|
+
|
|
210
|
+
|