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,274 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Hidden easter eggs for Chemistry Calc Terminal.
|
|
3
|
+
|
|
4
|
+
None of these are listed in /help or /shortcuts on purpose — /shortcuts
|
|
5
|
+
just teases that they exist. They're triggered by typing an exact
|
|
6
|
+
phrase at the home prompt (checked in App.handle before the normal
|
|
7
|
+
free-text question pipeline), so they never interfere with real
|
|
8
|
+
chemistry questions.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import random
|
|
12
|
+
import sys
|
|
13
|
+
import time
|
|
14
|
+
|
|
15
|
+
from . import theme
|
|
16
|
+
from . import sound
|
|
17
|
+
from . import keys
|
|
18
|
+
from . import identity
|
|
19
|
+
from . import aicore
|
|
20
|
+
from .atomsim import ELEMENTS
|
|
21
|
+
from .engine import WIDTH
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ------------------------------------------------------------- helpers --
|
|
25
|
+
def _panel(lines, title, color=theme.PURPLE, grad=None):
|
|
26
|
+
print()
|
|
27
|
+
print(theme.panel(lines, title=title, color=color, width=WIDTH, title_gradient=grad))
|
|
28
|
+
print()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _mark(app, key):
|
|
32
|
+
app.eggs_found.add(key)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# --------------------------------------------------------------- eggs --
|
|
36
|
+
def _egg_42(app):
|
|
37
|
+
_mark(app, "42")
|
|
38
|
+
sound.play("success")
|
|
39
|
+
_panel([
|
|
40
|
+
theme.gradient("THE ANSWER", theme.CYAN, theme.PURPLE, bold=True),
|
|
41
|
+
"",
|
|
42
|
+
theme.text("42 is the Answer to the Ultimate Question of Life,"),
|
|
43
|
+
theme.text("the Universe, and Everything."),
|
|
44
|
+
"",
|
|
45
|
+
theme.dim("It also happens to be the atomic number of ") + theme.orange("Molybdenum (Mo)", bold=True) + theme.dim("."),
|
|
46
|
+
theme.dim("Deep Thought would probably have appreciated a transition metal."),
|
|
47
|
+
], "\u2728 easter egg", grad=(theme.CYAN, theme.PURPLE))
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _egg_gold(app):
|
|
51
|
+
_mark(app, "gold")
|
|
52
|
+
sound.play("success")
|
|
53
|
+
bar = theme.gradient("\u2588" * 30, (201, 176, 55), (255, 223, 128), (201, 176, 55), bold=True)
|
|
54
|
+
_panel([
|
|
55
|
+
theme.orange("Au \u00b7 79 \u00b7 196.97 u", bold=True),
|
|
56
|
+
bar,
|
|
57
|
+
"",
|
|
58
|
+
theme.dim("Gold is so unreactive it's found in nature as the pure metal \u2014"),
|
|
59
|
+
theme.dim("which is exactly why alchemists never managed to make it from lead."),
|
|
60
|
+
], "\u2728 you struck gold", grad=((201, 176, 55), (255, 223, 128)))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _egg_avogadro(app):
|
|
64
|
+
_mark(app, "avogadro")
|
|
65
|
+
sound.play("success")
|
|
66
|
+
_panel([
|
|
67
|
+
theme.cyan("6.022 \u00d7 10\u00b2\u00b3", bold=True) + theme.dim(" \u2014 one mole, give or take."),
|
|
68
|
+
"",
|
|
69
|
+
theme.dim("That's roughly how many grains of sand would cover the entire"),
|
|
70
|
+
theme.dim("Earth in a layer several metres deep. Chemistry deals in numbers"),
|
|
71
|
+
theme.dim("so big they stop being numbers and start being vibes."),
|
|
72
|
+
], "\u2728 mole moment", grad=(theme.CYAN, theme.GREEN))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _egg_coffee(app):
|
|
76
|
+
_mark(app, "coffee")
|
|
77
|
+
sound.play("notify")
|
|
78
|
+
cup = [
|
|
79
|
+
" ( (",
|
|
80
|
+
" ) )",
|
|
81
|
+
" .______.",
|
|
82
|
+
" | |]",
|
|
83
|
+
" \\ /",
|
|
84
|
+
" `----'",
|
|
85
|
+
]
|
|
86
|
+
lines = [theme.dim(l) for l in cup]
|
|
87
|
+
lines.append("")
|
|
88
|
+
lines.append(theme.text("Caffeine", bold=True) + theme.dim(" \u2014 C\u2088H\u2081\u2080N\u2084O\u2082"))
|
|
89
|
+
lines.append(theme.dim("A methylxanthine alkaloid, and the reason this terminal exists."))
|
|
90
|
+
_panel(lines, "\u2728 brewed", grad=(theme.ORANGE, theme.PURPLE))
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _egg_sandwich(app):
|
|
94
|
+
_mark(app, "sandwich")
|
|
95
|
+
sound.play("success")
|
|
96
|
+
_panel([
|
|
97
|
+
theme.green("Sandwich synthesized.", bold=True),
|
|
98
|
+
theme.dim("Yield: 100% \u00b7 Byproducts: crumbs \u00b7 Reaction time: instantaneous"),
|
|
99
|
+
"",
|
|
100
|
+
theme.dim("(root privileges confirmed \u2014 you asked nicely, so it worked this time)"),
|
|
101
|
+
], "\u2728 sudo", grad=(theme.GREEN, theme.CYAN))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _egg_who(app):
|
|
105
|
+
_mark(app, "who")
|
|
106
|
+
sound.play("notify")
|
|
107
|
+
banner = theme.gradient("CHEMISTRY CALC TERMINAL", theme.CYAN, theme.PURPLE, theme.CYAN, bold=True)
|
|
108
|
+
try:
|
|
109
|
+
config = aicore.load_config()
|
|
110
|
+
except Exception:
|
|
111
|
+
config = None
|
|
112
|
+
_panel([
|
|
113
|
+
banner,
|
|
114
|
+
"",
|
|
115
|
+
theme.text(f"Created by {identity.CREATOR_NAME}, {identity.CREATOR_ROLE}."),
|
|
116
|
+
theme.dim(f"{identity.DEVELOPMENT_NOTE.capitalize()}. Built to look like a dev CLI,"),
|
|
117
|
+
theme.dim("but every calculation underneath is real \u2014 the fractions, the"),
|
|
118
|
+
theme.dim("derivations, the atoms, all of it."),
|
|
119
|
+
theme.faint(f"Stack: {identity.tech_stack_sentence(config)}."),
|
|
120
|
+
"",
|
|
121
|
+
theme.faint(f"You've now found {len(app.eggs_found) + 1} hidden thing(s). Keep looking."),
|
|
122
|
+
], "\u2728 credits", grad=(theme.CYAN, theme.PURPLE))
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _egg_model(app):
|
|
126
|
+
_mark(app, "model")
|
|
127
|
+
sound.play("notify")
|
|
128
|
+
try:
|
|
129
|
+
config = aicore.load_config()
|
|
130
|
+
except Exception:
|
|
131
|
+
config = None
|
|
132
|
+
_panel([
|
|
133
|
+
theme.gradient("ACTIVE MODEL", theme.CYAN, theme.PURPLE, bold=True),
|
|
134
|
+
"",
|
|
135
|
+
theme.text(identity.answer_model(config)),
|
|
136
|
+
], "\u2728 model", grad=(theme.CYAN, theme.PURPLE))
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _egg_god(app):
|
|
140
|
+
_mark(app, "god")
|
|
141
|
+
sound.play("sim_start")
|
|
142
|
+
_panel([
|
|
143
|
+
theme.gradient("\u2588\u2588 GOD MODE \u2588\u2588", theme.RED, theme.ORANGE, bold=True),
|
|
144
|
+
"",
|
|
145
|
+
theme.dim("Unlimited moles granted. Entropy locally reversed. Please use"),
|
|
146
|
+
theme.dim("responsibly \u2014 the second law of thermodynamics is watching."),
|
|
147
|
+
"",
|
|
148
|
+
theme.faint("(no actual cheats here \u2014 just a nod to every '90s game you know)"),
|
|
149
|
+
], "\u2728 iddqd", grad=(theme.RED, theme.ORANGE))
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _matrix_rain(app):
|
|
153
|
+
"""A Matrix-style falling-code effect, except the "code" is real
|
|
154
|
+
element symbols — press q to stop early."""
|
|
155
|
+
_mark(app, "matrix")
|
|
156
|
+
sound.play("sim_start")
|
|
157
|
+
width, height = WIDTH, 20
|
|
158
|
+
symbols = [v[0] for v in ELEMENTS.values()]
|
|
159
|
+
cols = [random.randint(-height, 0) for _ in range(width // 2)]
|
|
160
|
+
speeds = [random.choice([1, 1, 2]) for _ in cols]
|
|
161
|
+
theme.hide_cursor()
|
|
162
|
+
try:
|
|
163
|
+
for frame in range(90):
|
|
164
|
+
grid = [[" "] * width for _ in range(height)]
|
|
165
|
+
for ci, c in enumerate(cols):
|
|
166
|
+
x = ci * 2
|
|
167
|
+
head = c
|
|
168
|
+
for trail in range(10):
|
|
169
|
+
y = head - trail
|
|
170
|
+
if 0 <= y < height and 0 <= x < width:
|
|
171
|
+
sym = random.choice(symbols)
|
|
172
|
+
if trail == 0:
|
|
173
|
+
grid[y][x] = theme.fg(sym[0], (210, 255, 210), bold=True)
|
|
174
|
+
else:
|
|
175
|
+
fade = max(0, 1 - trail / 10)
|
|
176
|
+
col = theme.lerp((10, 40, 15), (80, 220, 110), fade)
|
|
177
|
+
grid[y][x] = theme.fg(sym[0], col)
|
|
178
|
+
cols[ci] += speeds[ci % len(speeds)]
|
|
179
|
+
if cols[ci] - 10 > height:
|
|
180
|
+
cols[ci] = random.randint(-height, -1)
|
|
181
|
+
theme.cursor_home()
|
|
182
|
+
out = "\n".join("".join(row) for row in grid)
|
|
183
|
+
sys.stdout.write(out + "\n")
|
|
184
|
+
sys.stdout.write(theme.faint(" press q to stop\u2026") + "\n")
|
|
185
|
+
sys.stdout.flush()
|
|
186
|
+
if keys.key_available():
|
|
187
|
+
k = keys.read_key()
|
|
188
|
+
if k and k.lower() == "q":
|
|
189
|
+
break
|
|
190
|
+
time.sleep(0.05)
|
|
191
|
+
finally:
|
|
192
|
+
theme.show_cursor()
|
|
193
|
+
print()
|
|
194
|
+
print(theme.gradient(" There is no calculator. Only chemistry.", theme.GREEN, theme.CYAN, bold=True))
|
|
195
|
+
print()
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _egg_3d(app):
|
|
199
|
+
_mark(app, "3d")
|
|
200
|
+
sound.play("notify")
|
|
201
|
+
art = [
|
|
202
|
+
" +---------+",
|
|
203
|
+
" /| /|",
|
|
204
|
+
" / | / |",
|
|
205
|
+
" +--+------+ /",
|
|
206
|
+
" | | | +",
|
|
207
|
+
" | +------+-|",
|
|
208
|
+
" | / |/",
|
|
209
|
+
" +---------+",
|
|
210
|
+
]
|
|
211
|
+
lines = [theme.gradient(l, theme.CYAN, theme.PURPLE) for l in art]
|
|
212
|
+
lines.insert(0, "")
|
|
213
|
+
lines.append("")
|
|
214
|
+
lines.append(theme.dim(" A glimpse into the third dimension..."))
|
|
215
|
+
_panel(lines, "\u2728 3d art", grad=(theme.CYAN, theme.PURPLE))
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
EGGS = {
|
|
219
|
+
"42": _egg_42,
|
|
220
|
+
"gold": _egg_gold,
|
|
221
|
+
"au": _egg_gold,
|
|
222
|
+
"avogadro": _egg_avogadro,
|
|
223
|
+
"avogadro's number": _egg_avogadro,
|
|
224
|
+
"avogadro number": _egg_avogadro,
|
|
225
|
+
"coffee": _egg_coffee,
|
|
226
|
+
"caffeine": _egg_coffee,
|
|
227
|
+
"sudo make me a sandwich": _egg_sandwich,
|
|
228
|
+
"make me a sandwich": _egg_sandwich,
|
|
229
|
+
"who made this": _egg_who,
|
|
230
|
+
"who made you": _egg_who,
|
|
231
|
+
"who are you": _egg_who,
|
|
232
|
+
"what are you": _egg_who,
|
|
233
|
+
"who built this": _egg_who,
|
|
234
|
+
"who built cct": _egg_who,
|
|
235
|
+
"who built you": _egg_who,
|
|
236
|
+
"who created this": _egg_who,
|
|
237
|
+
"who created you": _egg_who,
|
|
238
|
+
"who created cct": _egg_who,
|
|
239
|
+
"who developed this": _egg_who,
|
|
240
|
+
"who developed you": _egg_who,
|
|
241
|
+
"who developed cct": _egg_who,
|
|
242
|
+
"who owns this project": _egg_who,
|
|
243
|
+
"who owns cct": _egg_who,
|
|
244
|
+
"what is cct": _egg_who,
|
|
245
|
+
"iddqd": _egg_god,
|
|
246
|
+
"konami": _egg_god,
|
|
247
|
+
"/matrix": _matrix_rain,
|
|
248
|
+
"matrix": _matrix_rain,
|
|
249
|
+
"3d": _egg_3d,
|
|
250
|
+
"show me something 3d": _egg_3d,
|
|
251
|
+
"cube": _egg_3d,
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def check(low, app):
|
|
256
|
+
"""Return True if `low` (already lowercased/stripped) matched a
|
|
257
|
+
hidden easter egg and was handled."""
|
|
258
|
+
fn = EGGS.get(low)
|
|
259
|
+
if fn is not None:
|
|
260
|
+
fn(app)
|
|
261
|
+
return True
|
|
262
|
+
# Exact-match dict above misses natural phrasing variants ("who is
|
|
263
|
+
# the developer of cct?", "who owns this project?" with punctuation,
|
|
264
|
+
# etc.) — fall back to identity.py's looser matcher so those still
|
|
265
|
+
# land on the same, correct answer instead of falling through to the
|
|
266
|
+
# AI (or a "couldn't match that" error).
|
|
267
|
+
kind = identity.classify_identity_question(low)
|
|
268
|
+
if kind == "creator" or kind == "what":
|
|
269
|
+
_egg_who(app)
|
|
270
|
+
return True
|
|
271
|
+
if kind == "model":
|
|
272
|
+
_egg_model(app)
|
|
273
|
+
return True
|
|
274
|
+
return False
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""CAT Code Editor - Subsystem modules (commands, shortcuts, actions)."""
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
"""CAT Code Editor — Editor Actions (calc_terminal/editor/actions.py).
|
|
2
|
+
|
|
3
|
+
Concrete editor manipulation routines:
|
|
4
|
+
- Toggle line comment
|
|
5
|
+
- Delete line
|
|
6
|
+
- Move line up / down
|
|
7
|
+
- Copy line up / down
|
|
8
|
+
- Insert line below / above
|
|
9
|
+
- Select next matching occurrence
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from typing import Any, Optional
|
|
15
|
+
|
|
16
|
+
_COMMENT_PREFIXES = {
|
|
17
|
+
"python": "# ",
|
|
18
|
+
"bash": "# ",
|
|
19
|
+
"sh": "# ",
|
|
20
|
+
"yaml": "# ",
|
|
21
|
+
"yml": "# ",
|
|
22
|
+
"toml": "# ",
|
|
23
|
+
"javascript": "// ",
|
|
24
|
+
"typescript": "// ",
|
|
25
|
+
"json": "// ",
|
|
26
|
+
"rust": "// ",
|
|
27
|
+
"go": "// ",
|
|
28
|
+
"java": "// ",
|
|
29
|
+
"c": "// ",
|
|
30
|
+
"cpp": "// ",
|
|
31
|
+
"css": "/* ",
|
|
32
|
+
"sql": "-- ",
|
|
33
|
+
"html": "<!-- ",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def toggle_line_comment(area: Any, language: Optional[str] = None) -> bool:
|
|
38
|
+
"""Toggle comment on the current line or selection in a TextArea."""
|
|
39
|
+
if not hasattr(area, "text") or not hasattr(area, "cursor_location"):
|
|
40
|
+
return False
|
|
41
|
+
lang = (language or getattr(area, "language", "") or "").lower()
|
|
42
|
+
prefix = _COMMENT_PREFIXES.get(lang, "# ")
|
|
43
|
+
suffix = " -->" if prefix == "<!-- " else (" */" if prefix == "/* " else "")
|
|
44
|
+
|
|
45
|
+
lines = area.text.splitlines() or [""]
|
|
46
|
+
row, col = area.cursor_location
|
|
47
|
+
if row < 0 or row >= len(lines):
|
|
48
|
+
return False
|
|
49
|
+
|
|
50
|
+
line = lines[row]
|
|
51
|
+
stripped = line.lstrip()
|
|
52
|
+
indent = line[:len(line) - len(stripped)]
|
|
53
|
+
|
|
54
|
+
if suffix:
|
|
55
|
+
if stripped.startswith(prefix.strip()) and stripped.endswith(suffix.strip()):
|
|
56
|
+
uncommented = stripped[len(prefix.strip()):-len(suffix.strip())].strip()
|
|
57
|
+
lines[row] = indent + uncommented
|
|
58
|
+
else:
|
|
59
|
+
lines[row] = indent + prefix + stripped + suffix
|
|
60
|
+
else:
|
|
61
|
+
if stripped.startswith(prefix):
|
|
62
|
+
lines[row] = indent + stripped[len(prefix):]
|
|
63
|
+
elif stripped.startswith(prefix.strip()):
|
|
64
|
+
lines[row] = indent + stripped[len(prefix.strip()):]
|
|
65
|
+
else:
|
|
66
|
+
lines[row] = indent + prefix + stripped
|
|
67
|
+
|
|
68
|
+
new_text = "\n".join(lines)
|
|
69
|
+
area.text = new_text
|
|
70
|
+
try:
|
|
71
|
+
area.move_cursor((row, min(col, len(lines[row]))))
|
|
72
|
+
except Exception:
|
|
73
|
+
pass
|
|
74
|
+
return True
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def delete_line(area: Any) -> bool:
|
|
78
|
+
"""Delete the active line in a TextArea."""
|
|
79
|
+
if not hasattr(area, "text") or not hasattr(area, "cursor_location"):
|
|
80
|
+
return False
|
|
81
|
+
lines = area.text.splitlines() or [""]
|
|
82
|
+
row, col = area.cursor_location
|
|
83
|
+
if row < 0 or row >= len(lines):
|
|
84
|
+
return False
|
|
85
|
+
|
|
86
|
+
if len(lines) == 1:
|
|
87
|
+
lines = [""]
|
|
88
|
+
target_row = 0
|
|
89
|
+
else:
|
|
90
|
+
lines.pop(row)
|
|
91
|
+
target_row = min(row, len(lines) - 1)
|
|
92
|
+
|
|
93
|
+
area.text = "\n".join(lines)
|
|
94
|
+
try:
|
|
95
|
+
area.move_cursor((target_row, min(col, len(lines[target_row]))))
|
|
96
|
+
except Exception:
|
|
97
|
+
pass
|
|
98
|
+
return True
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def move_line_up(area: Any) -> bool:
|
|
102
|
+
"""Swap the active line with the line above it."""
|
|
103
|
+
if not hasattr(area, "text") or not hasattr(area, "cursor_location"):
|
|
104
|
+
return False
|
|
105
|
+
lines = area.text.splitlines() or [""]
|
|
106
|
+
row, col = area.cursor_location
|
|
107
|
+
if row <= 0 or row >= len(lines):
|
|
108
|
+
return False
|
|
109
|
+
|
|
110
|
+
lines[row - 1], lines[row] = lines[row], lines[row - 1]
|
|
111
|
+
area.text = "\n".join(lines)
|
|
112
|
+
try:
|
|
113
|
+
area.move_cursor((row - 1, min(col, len(lines[row - 1]))))
|
|
114
|
+
except Exception:
|
|
115
|
+
pass
|
|
116
|
+
return True
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def move_line_down(area: Any) -> bool:
|
|
120
|
+
"""Swap the active line with the line below it."""
|
|
121
|
+
if not hasattr(area, "text") or not hasattr(area, "cursor_location"):
|
|
122
|
+
return False
|
|
123
|
+
lines = area.text.splitlines() or [""]
|
|
124
|
+
row, col = area.cursor_location
|
|
125
|
+
if row < 0 or row >= len(lines) - 1:
|
|
126
|
+
return False
|
|
127
|
+
|
|
128
|
+
lines[row + 1], lines[row] = lines[row], lines[row + 1]
|
|
129
|
+
area.text = "\n".join(lines)
|
|
130
|
+
try:
|
|
131
|
+
area.move_cursor((row + 1, min(col, len(lines[row + 1]))))
|
|
132
|
+
except Exception:
|
|
133
|
+
pass
|
|
134
|
+
return True
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def copy_line_up(area: Any) -> bool:
|
|
138
|
+
"""Duplicate current line upwards."""
|
|
139
|
+
if not hasattr(area, "text") or not hasattr(area, "cursor_location"):
|
|
140
|
+
return False
|
|
141
|
+
lines = area.text.splitlines() or [""]
|
|
142
|
+
row, col = area.cursor_location
|
|
143
|
+
if row < 0 or row >= len(lines):
|
|
144
|
+
return False
|
|
145
|
+
|
|
146
|
+
lines.insert(row, lines[row])
|
|
147
|
+
area.text = "\n".join(lines)
|
|
148
|
+
try:
|
|
149
|
+
area.move_cursor((row, col))
|
|
150
|
+
except Exception:
|
|
151
|
+
pass
|
|
152
|
+
return True
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def copy_line_down(area: Any) -> bool:
|
|
156
|
+
"""Duplicate current line downwards."""
|
|
157
|
+
if not hasattr(area, "text") or not hasattr(area, "cursor_location"):
|
|
158
|
+
return False
|
|
159
|
+
lines = area.text.splitlines() or [""]
|
|
160
|
+
row, col = area.cursor_location
|
|
161
|
+
if row < 0 or row >= len(lines):
|
|
162
|
+
return False
|
|
163
|
+
|
|
164
|
+
lines.insert(row + 1, lines[row])
|
|
165
|
+
area.text = "\n".join(lines)
|
|
166
|
+
try:
|
|
167
|
+
area.move_cursor((row + 1, col))
|
|
168
|
+
except Exception:
|
|
169
|
+
pass
|
|
170
|
+
return True
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def insert_line_below(area: Any) -> bool:
|
|
174
|
+
"""Insert a new line below and move cursor to it."""
|
|
175
|
+
if not hasattr(area, "text") or not hasattr(area, "cursor_location"):
|
|
176
|
+
return False
|
|
177
|
+
lines = area.text.splitlines() or [""]
|
|
178
|
+
row, col = area.cursor_location
|
|
179
|
+
if row < 0 or row >= len(lines):
|
|
180
|
+
row = len(lines) - 1
|
|
181
|
+
|
|
182
|
+
current_line = lines[row] if row < len(lines) else ""
|
|
183
|
+
indent = current_line[:len(current_line) - len(current_line.lstrip())]
|
|
184
|
+
|
|
185
|
+
lines.insert(row + 1, indent)
|
|
186
|
+
area.text = "\n".join(lines)
|
|
187
|
+
try:
|
|
188
|
+
area.move_cursor((row + 1, len(indent)))
|
|
189
|
+
except Exception:
|
|
190
|
+
pass
|
|
191
|
+
return True
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def insert_line_above(area: Any) -> bool:
|
|
195
|
+
"""Insert a new line above and move cursor to it."""
|
|
196
|
+
if not hasattr(area, "text") or not hasattr(area, "cursor_location"):
|
|
197
|
+
return False
|
|
198
|
+
lines = area.text.splitlines() or [""]
|
|
199
|
+
row, col = area.cursor_location
|
|
200
|
+
if row < 0:
|
|
201
|
+
row = 0
|
|
202
|
+
|
|
203
|
+
current_line = lines[row] if row < len(lines) else ""
|
|
204
|
+
indent = current_line[:len(current_line) - len(current_line.lstrip())]
|
|
205
|
+
|
|
206
|
+
lines.insert(row, indent)
|
|
207
|
+
area.text = "\n".join(lines)
|
|
208
|
+
try:
|
|
209
|
+
area.move_cursor((row, len(indent)))
|
|
210
|
+
except Exception:
|
|
211
|
+
pass
|
|
212
|
+
return True
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def select_next_occurrence(area: Any) -> bool:
|
|
216
|
+
"""Select next matching occurrence of current selection or word under cursor."""
|
|
217
|
+
if not hasattr(area, "text") or not hasattr(area, "cursor_location"):
|
|
218
|
+
return False
|
|
219
|
+
sel = getattr(area, "selected_text", None)
|
|
220
|
+
if not sel:
|
|
221
|
+
# Get word under cursor
|
|
222
|
+
lines = area.text.splitlines() or [""]
|
|
223
|
+
row, col = area.cursor_location
|
|
224
|
+
if row < len(lines):
|
|
225
|
+
line = lines[row]
|
|
226
|
+
start = col
|
|
227
|
+
while start > 0 and (line[start - 1].isalnum() or line[start - 1] == "_"):
|
|
228
|
+
start -= 1
|
|
229
|
+
end = col
|
|
230
|
+
while end < len(line) and (line[end].isalnum() or line[end] == "_"):
|
|
231
|
+
end += 1
|
|
232
|
+
sel = line[start:end]
|
|
233
|
+
if sel and hasattr(area, "selection"):
|
|
234
|
+
try:
|
|
235
|
+
area.selection = area.selection.__class__((row, start), (row, end))
|
|
236
|
+
except Exception:
|
|
237
|
+
pass
|
|
238
|
+
|
|
239
|
+
if not sel:
|
|
240
|
+
return False
|
|
241
|
+
|
|
242
|
+
# Find next occurrence after cursor
|
|
243
|
+
full_text = area.text
|
|
244
|
+
lines = full_text.splitlines() or [""]
|
|
245
|
+
cur_row, cur_col = area.cursor_location
|
|
246
|
+
n = len(lines)
|
|
247
|
+
for i in range(n + 1):
|
|
248
|
+
row = (cur_row + i) % n if n else 0
|
|
249
|
+
line = lines[row] if row < len(lines) else ""
|
|
250
|
+
search_from = cur_col + len(sel) if i == 0 else 0
|
|
251
|
+
col = line.find(sel, search_from)
|
|
252
|
+
if col == -1 and i == 0:
|
|
253
|
+
col = line.find(sel)
|
|
254
|
+
if col != -1:
|
|
255
|
+
try:
|
|
256
|
+
area.move_cursor((row, col))
|
|
257
|
+
if hasattr(area, "selection"):
|
|
258
|
+
area.selection = area.selection.__class__((row, col), (row, col + len(sel)))
|
|
259
|
+
area.scroll_cursor_visible()
|
|
260
|
+
return True
|
|
261
|
+
except Exception:
|
|
262
|
+
pass
|
|
263
|
+
return False
|