code-muse 0.0.1__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.
- code_muse/__init__.py +26 -0
- code_muse/__main__.py +10 -0
- code_muse/agents/__init__.py +31 -0
- code_muse/agents/_builder.py +214 -0
- code_muse/agents/_compaction.py +506 -0
- code_muse/agents/_diagnostics.py +171 -0
- code_muse/agents/_history.py +382 -0
- code_muse/agents/_key_listeners.py +148 -0
- code_muse/agents/_non_streaming_render.py +148 -0
- code_muse/agents/_runtime.py +596 -0
- code_muse/agents/agent_creator_agent.py +603 -0
- code_muse/agents/agent_helios.py +47 -0
- code_muse/agents/agent_manager.py +740 -0
- code_muse/agents/agent_muse.py +78 -0
- code_muse/agents/agent_planning.py +44 -0
- code_muse/agents/agent_qa_melpomene.py +207 -0
- code_muse/agents/base_agent.py +194 -0
- code_muse/agents/event_stream_handler.py +361 -0
- code_muse/agents/json_agent.py +201 -0
- code_muse/agents/prompt_v3.py +521 -0
- code_muse/agents/subagent_stream_handler.py +273 -0
- code_muse/callbacks.py +941 -0
- code_muse/chatgpt_codex_client.py +333 -0
- code_muse/claude_cache_client.py +853 -0
- code_muse/cli_runner/__init__.py +319 -0
- code_muse/cli_runner/args.py +63 -0
- code_muse/cli_runner/loop.py +510 -0
- code_muse/cli_runner/resume.py +72 -0
- code_muse/cli_runner/runner.py +161 -0
- code_muse/command_line/__init__.py +1 -0
- code_muse/command_line/add_model_menu.py +1331 -0
- code_muse/command_line/agent_menu.py +674 -0
- code_muse/command_line/attachments.py +397 -0
- code_muse/command_line/autosave_menu.py +709 -0
- code_muse/command_line/clipboard.py +528 -0
- code_muse/command_line/colors_menu.py +530 -0
- code_muse/command_line/command_handler.py +262 -0
- code_muse/command_line/command_registry.py +150 -0
- code_muse/command_line/config_commands.py +711 -0
- code_muse/command_line/core_commands.py +740 -0
- code_muse/command_line/diff_menu.py +865 -0
- code_muse/command_line/file_path_completion.py +73 -0
- code_muse/command_line/load_context_completion.py +57 -0
- code_muse/command_line/model_picker_completion.py +512 -0
- code_muse/command_line/model_settings_menu.py +983 -0
- code_muse/command_line/onboarding_slides.py +162 -0
- code_muse/command_line/onboarding_wizard.py +337 -0
- code_muse/command_line/pagination.py +41 -0
- code_muse/command_line/pin_command_completion.py +329 -0
- code_muse/command_line/prompt_toolkit_completion.py +886 -0
- code_muse/command_line/session_commands.py +304 -0
- code_muse/command_line/shell_passthrough.py +145 -0
- code_muse/command_line/skills_completion.py +158 -0
- code_muse/command_line/types.py +18 -0
- code_muse/command_line/uc_menu.py +908 -0
- code_muse/command_line/utils.py +105 -0
- code_muse/command_line/wiggum_state.py +77 -0
- code_muse/config.py +1138 -0
- code_muse/config_agent.py +168 -0
- code_muse/config_appearance.py +241 -0
- code_muse/config_model.py +357 -0
- code_muse/config_security.py +73 -0
- code_muse/error_logging.py +132 -0
- code_muse/evals/__init__.py +35 -0
- code_muse/evals/eval_helpers.py +81 -0
- code_muse/evals/eval_runner.py +299 -0
- code_muse/evals/sample_evals/__init__.py +1 -0
- code_muse/evals/sample_evals/eval_frugal_reads.py +59 -0
- code_muse/evals/sample_evals/eval_memory_planning.py +31 -0
- code_muse/evals/sample_evals/eval_shell_efficiency.py +39 -0
- code_muse/evals/sample_evals/eval_tool_masking.py +33 -0
- code_muse/fs_scan_cache/__init__.py +31 -0
- code_muse/fs_scan_cache/invalidation_hooks.py +89 -0
- code_muse/fs_scan_cache/scan_cache_core.cpython-314-darwin.so +0 -0
- code_muse/fs_scan_cache/scan_cache_core.pyx +203 -0
- code_muse/fs_scan_cache/tool_integration.py +309 -0
- code_muse/fs_scan_cache/ttl_policy.py +44 -0
- code_muse/gemini_code_assist.py +383 -0
- code_muse/gemini_model.py +838 -0
- code_muse/hook_engine/README.md +105 -0
- code_muse/hook_engine/__init__.py +21 -0
- code_muse/hook_engine/aliases.py +153 -0
- code_muse/hook_engine/engine.py +221 -0
- code_muse/hook_engine/executor.py +347 -0
- code_muse/hook_engine/matcher.py +154 -0
- code_muse/hook_engine/models.py +245 -0
- code_muse/hook_engine/registry.py +114 -0
- code_muse/hook_engine/trust.py +268 -0
- code_muse/hook_engine/validator.py +144 -0
- code_muse/http_utils.py +360 -0
- code_muse/keymap.py +128 -0
- code_muse/list_filtering.py +26 -0
- code_muse/main.py +10 -0
- code_muse/messaging/__init__.py +259 -0
- code_muse/messaging/bus.py +621 -0
- code_muse/messaging/commands.py +166 -0
- code_muse/messaging/markdown_patches.py +57 -0
- code_muse/messaging/message_queue.py +397 -0
- code_muse/messaging/messages.py +591 -0
- code_muse/messaging/queue_console.py +269 -0
- code_muse/messaging/renderers.py +308 -0
- code_muse/messaging/rich_renderer.py +1158 -0
- code_muse/messaging/shimmer.py +154 -0
- code_muse/messaging/spinner/__init__.py +87 -0
- code_muse/messaging/spinner/console_spinner.py +250 -0
- code_muse/messaging/spinner/spinner_base.py +82 -0
- code_muse/messaging/subagent_console.py +458 -0
- code_muse/model_factory.py +1203 -0
- code_muse/model_switching.py +59 -0
- code_muse/model_utils.py +156 -0
- code_muse/models.json +66 -0
- code_muse/models_cache/__init__.py +26 -0
- code_muse/models_cache/blocking_lru_cache.py +98 -0
- code_muse/models_cache/cache_writer.py +86 -0
- code_muse/models_cache/sha256_hash.cpython-314-darwin.so +0 -0
- code_muse/models_cache/sha256_hash.pyx +34 -0
- code_muse/models_cache/startup_integration.py +75 -0
- code_muse/models_dev_api.json +1 -0
- code_muse/models_dev_parser.py +590 -0
- code_muse/motion.py +126 -0
- code_muse/plugins/__init__.py +471 -0
- code_muse/plugins/agent_skills/__init__.py +32 -0
- code_muse/plugins/agent_skills/config.py +176 -0
- code_muse/plugins/agent_skills/discovery.py +309 -0
- code_muse/plugins/agent_skills/downloader.py +389 -0
- code_muse/plugins/agent_skills/installer.py +19 -0
- code_muse/plugins/agent_skills/metadata.py +293 -0
- code_muse/plugins/agent_skills/prompt_builder.py +66 -0
- code_muse/plugins/agent_skills/register_callbacks.py +298 -0
- code_muse/plugins/agent_skills/remote_catalog.py +320 -0
- code_muse/plugins/agent_skills/skill_catalog.py +254 -0
- code_muse/plugins/agent_skills/skills_install_menu.py +690 -0
- code_muse/plugins/agent_skills/skills_menu.py +791 -0
- code_muse/plugins/autonomous_memory/__init__.py +39 -0
- code_muse/plugins/autonomous_memory/bm25_scorer.cpython-314-darwin.so +0 -0
- code_muse/plugins/autonomous_memory/bm25_scorer.cpython-314-x86_64-linux-gnu.so +0 -0
- code_muse/plugins/autonomous_memory/bm25_scorer.pyx +291 -0
- code_muse/plugins/autonomous_memory/consolidation.py +82 -0
- code_muse/plugins/autonomous_memory/extraction.py +382 -0
- code_muse/plugins/autonomous_memory/lease_lock.py +105 -0
- code_muse/plugins/autonomous_memory/memory_injection.py +59 -0
- code_muse/plugins/autonomous_memory/register_callbacks.py +268 -0
- code_muse/plugins/autonomous_memory/secret_scanner.py +62 -0
- code_muse/plugins/autonomous_memory/session_scanner.py +163 -0
- code_muse/plugins/aws_bedrock/__init__.py +14 -0
- code_muse/plugins/aws_bedrock/config.py +99 -0
- code_muse/plugins/aws_bedrock/register_callbacks.py +241 -0
- code_muse/plugins/aws_bedrock/utils.py +153 -0
- code_muse/plugins/azure_foundry/README.md +238 -0
- code_muse/plugins/azure_foundry/__init__.py +15 -0
- code_muse/plugins/azure_foundry/config.py +125 -0
- code_muse/plugins/azure_foundry/discovery.py +187 -0
- code_muse/plugins/azure_foundry/register_callbacks.py +495 -0
- code_muse/plugins/azure_foundry/token.py +180 -0
- code_muse/plugins/azure_foundry/utils.py +345 -0
- code_muse/plugins/build_filter/__init__.py +1 -0
- code_muse/plugins/build_filter/register_callbacks.py +201 -0
- code_muse/plugins/build_filter/strategies/__init__.py +1 -0
- code_muse/plugins/build_filter/strategies/build.py +397 -0
- code_muse/plugins/chatgpt_oauth/__init__.py +6 -0
- code_muse/plugins/chatgpt_oauth/config.py +52 -0
- code_muse/plugins/chatgpt_oauth/oauth_flow.py +338 -0
- code_muse/plugins/chatgpt_oauth/register_callbacks.py +172 -0
- code_muse/plugins/chatgpt_oauth/test_plugin.py +301 -0
- code_muse/plugins/chatgpt_oauth/utils.py +538 -0
- code_muse/plugins/checkpointing/__init__.py +29 -0
- code_muse/plugins/checkpointing/checkpoint_hook.py +51 -0
- code_muse/plugins/checkpointing/conversation_snapshots.py +117 -0
- code_muse/plugins/checkpointing/register_callbacks.py +51 -0
- code_muse/plugins/checkpointing/restore_command.py +263 -0
- code_muse/plugins/checkpointing/rewind_shortcut.py +88 -0
- code_muse/plugins/checkpointing/shadow_git.py +90 -0
- code_muse/plugins/claude_code_hooks/__init__.py +1 -0
- code_muse/plugins/claude_code_hooks/config.py +188 -0
- code_muse/plugins/claude_code_hooks/register_callbacks.py +208 -0
- code_muse/plugins/claude_code_oauth/README.md +167 -0
- code_muse/plugins/claude_code_oauth/SETUP.md +93 -0
- code_muse/plugins/claude_code_oauth/__init__.py +25 -0
- code_muse/plugins/claude_code_oauth/config.py +52 -0
- code_muse/plugins/claude_code_oauth/fast_mode.py +124 -0
- code_muse/plugins/claude_code_oauth/prompt_handler.py +63 -0
- code_muse/plugins/claude_code_oauth/register_callbacks.py +547 -0
- code_muse/plugins/claude_code_oauth/test_fast_mode.py +165 -0
- code_muse/plugins/claude_code_oauth/test_plugin.py +283 -0
- code_muse/plugins/claude_code_oauth/token_refresh_heartbeat.py +237 -0
- code_muse/plugins/claude_code_oauth/utils.py +664 -0
- code_muse/plugins/copilot_auth/__init__.py +11 -0
- code_muse/plugins/copilot_auth/config.py +91 -0
- code_muse/plugins/copilot_auth/reasoning_client.py +409 -0
- code_muse/plugins/copilot_auth/register_callbacks.py +461 -0
- code_muse/plugins/copilot_auth/utils.py +584 -0
- code_muse/plugins/custom_commands/__init__.py +14 -0
- code_muse/plugins/custom_commands/args_injection.py +82 -0
- code_muse/plugins/custom_commands/command_discovery.py +89 -0
- code_muse/plugins/custom_commands/command_toml_schema.py +71 -0
- code_muse/plugins/custom_commands/register_callbacks.py +176 -0
- code_muse/plugins/customizable_commands/__init__.py +0 -0
- code_muse/plugins/customizable_commands/register_callbacks.py +136 -0
- code_muse/plugins/destructive_command_guard/__init__.py +14 -0
- code_muse/plugins/destructive_command_guard/detector.py +375 -0
- code_muse/plugins/destructive_command_guard/register_callbacks.py +148 -0
- code_muse/plugins/example_custom_command/README.md +280 -0
- code_muse/plugins/example_custom_command/register_callbacks.py +51 -0
- code_muse/plugins/file_permission_handler/__init__.py +4 -0
- code_muse/plugins/file_permission_handler/register_callbacks.py +441 -0
- code_muse/plugins/filter_engine/__init__.py +30 -0
- code_muse/plugins/filter_engine/classifier.py +153 -0
- code_muse/plugins/filter_engine/content_detector.py +184 -0
- code_muse/plugins/filter_engine/dispatcher.py +244 -0
- code_muse/plugins/filter_engine/register_callbacks.py +188 -0
- code_muse/plugins/filter_engine/registry.py +279 -0
- code_muse/plugins/filter_engine/strategies/__init__.py +8 -0
- code_muse/plugins/filter_engine/strategies/ast_compressor.cpython-314-darwin.so +0 -0
- code_muse/plugins/filter_engine/strategies/ast_compressor.cpython-314-x86_64-linux-gnu.so +0 -0
- code_muse/plugins/filter_engine/strategies/ast_compressor.pyx +348 -0
- code_muse/plugins/filter_engine/strategies/ast_parser.py +167 -0
- code_muse/plugins/filter_engine/strategies/code.cpython-314-darwin.so +0 -0
- code_muse/plugins/filter_engine/strategies/code.cpython-314-x86_64-linux-gnu.so +0 -0
- code_muse/plugins/filter_engine/strategies/code.pyx +584 -0
- code_muse/plugins/filter_engine/strategies/git.cpython-314-darwin.so +0 -0
- code_muse/plugins/filter_engine/strategies/git.cpython-314-x86_64-linux-gnu.so +0 -0
- code_muse/plugins/filter_engine/strategies/git.pyx +438 -0
- code_muse/plugins/filter_engine/strategies/json_compressor.cpython-314-darwin.so +0 -0
- code_muse/plugins/filter_engine/strategies/json_compressor.pyx +253 -0
- code_muse/plugins/filter_engine/strategies/json_patterns.cpython-314-darwin.so +0 -0
- code_muse/plugins/filter_engine/strategies/json_patterns.pyx +178 -0
- code_muse/plugins/filter_engine/strategies/lint.cpython-314-darwin.so +0 -0
- code_muse/plugins/filter_engine/strategies/lint.cpython-314-x86_64-linux-gnu.so +0 -0
- code_muse/plugins/filter_engine/strategies/lint.pyx +626 -0
- code_muse/plugins/filter_engine/strategies/test.cpython-314-darwin.so +0 -0
- code_muse/plugins/filter_engine/strategies/test.cpython-314-x86_64-linux-gnu.so +0 -0
- code_muse/plugins/filter_engine/strategies/test.pyx +431 -0
- code_muse/plugins/filter_engine/verbosity.py +63 -0
- code_muse/plugins/force_push_guard/__init__.py +5 -0
- code_muse/plugins/force_push_guard/detector.py +96 -0
- code_muse/plugins/force_push_guard/register_callbacks.py +144 -0
- code_muse/plugins/force_push_guard/test_detector.py +143 -0
- code_muse/plugins/frontend_emitter/__init__.py +25 -0
- code_muse/plugins/frontend_emitter/emitter.py +121 -0
- code_muse/plugins/frontend_emitter/register_callbacks.py +259 -0
- code_muse/plugins/gac/__init__.py +4 -0
- code_muse/plugins/gac/git_ops.py +136 -0
- code_muse/plugins/gac/prompt.py +191 -0
- code_muse/plugins/gac/register_callbacks.py +82 -0
- code_muse/plugins/hook_creator/__init__.py +1 -0
- code_muse/plugins/hook_creator/register_callbacks.py +34 -0
- code_muse/plugins/hook_manager/__init__.py +1 -0
- code_muse/plugins/hook_manager/config.py +289 -0
- code_muse/plugins/hook_manager/hooks_menu.py +563 -0
- code_muse/plugins/hook_manager/register_callbacks.py +227 -0
- code_muse/plugins/hook_monitor/register_callbacks.py +36 -0
- code_muse/plugins/mindpack/__init__.py +0 -0
- code_muse/plugins/mindpack/factory.py +930 -0
- code_muse/plugins/mindpack/judge.py +573 -0
- code_muse/plugins/mindpack/memory.py +100 -0
- code_muse/plugins/mindpack/mindpack_menu.py +1552 -0
- code_muse/plugins/mindpack/orchestration.py +605 -0
- code_muse/plugins/mindpack/register_callbacks.py +175 -0
- code_muse/plugins/mindpack/schemas.py +358 -0
- code_muse/plugins/mindpack/tools.py +387 -0
- code_muse/plugins/oauth_muse_html.py +226 -0
- code_muse/plugins/ollama_setup/__init__.py +5 -0
- code_muse/plugins/ollama_setup/completer.py +36 -0
- code_muse/plugins/ollama_setup/register_callbacks.py +410 -0
- code_muse/plugins/plan_command/__init__.py +0 -0
- code_muse/plugins/plan_command/register_callbacks.py +206 -0
- code_muse/plugins/plan_mode/__init__.py +37 -0
- code_muse/plugins/plan_mode/mode_cycling.py +40 -0
- code_muse/plugins/plan_mode/plan_generation.py +68 -0
- code_muse/plugins/plan_mode/plan_hooks.py +74 -0
- code_muse/plugins/plan_mode/plan_mode_tools.py +138 -0
- code_muse/plugins/plan_mode/register_callbacks.py +121 -0
- code_muse/plugins/plugin_trust/register_callbacks.py +140 -0
- code_muse/plugins/policy_engine/__init__.py +46 -0
- code_muse/plugins/policy_engine/approval_flow_integration.py +59 -0
- code_muse/plugins/policy_engine/policy_evaluator.py +75 -0
- code_muse/plugins/policy_engine/policy_file_discovery.py +90 -0
- code_muse/plugins/policy_engine/policy_toml_schema.py +115 -0
- code_muse/plugins/policy_engine/register_callbacks.py +112 -0
- code_muse/plugins/pop_command/__init__.py +1 -0
- code_muse/plugins/pop_command/register_callbacks.py +189 -0
- code_muse/plugins/prompt_newline/__init__.py +13 -0
- code_muse/plugins/prompt_newline/config.py +19 -0
- code_muse/plugins/prompt_newline/register_callbacks.py +159 -0
- code_muse/plugins/safety_status/__init__.py +0 -0
- code_muse/plugins/safety_status/register_callbacks.py +113 -0
- code_muse/plugins/semantic_compression/__init__.py +6 -0
- code_muse/plugins/semantic_compression/compressor.py +295 -0
- code_muse/plugins/semantic_compression/config.py +123 -0
- code_muse/plugins/semantic_compression/register_callbacks.py +320 -0
- code_muse/plugins/shell_minimizer/__init__.py +50 -0
- code_muse/plugins/shell_minimizer/builtin_filters.toml +393 -0
- code_muse/plugins/shell_minimizer/pipeline.py +556 -0
- code_muse/plugins/shell_minimizer/primitives.py +482 -0
- code_muse/plugins/shell_minimizer/register_callbacks.py +276 -0
- code_muse/plugins/shell_safety/__init__.py +6 -0
- code_muse/plugins/shell_safety/agent_shell_safety.py +69 -0
- code_muse/plugins/shell_safety/command_cache.py +149 -0
- code_muse/plugins/shell_safety/register_callbacks.py +202 -0
- code_muse/plugins/synthetic_status/__init__.py +1 -0
- code_muse/plugins/synthetic_status/register_callbacks.py +128 -0
- code_muse/plugins/synthetic_status/status_api.py +145 -0
- code_muse/plugins/token_caching/__init__.py +21 -0
- code_muse/plugins/token_caching/cache_hit_tracking.py +128 -0
- code_muse/plugins/token_caching/cacheable_prefix_detection.py +28 -0
- code_muse/plugins/token_caching/register_callbacks.py +54 -0
- code_muse/plugins/token_caching/stats_display.py +35 -0
- code_muse/plugins/token_tracking/__init__.py +26 -0
- code_muse/plugins/token_tracking/database.py +381 -0
- code_muse/plugins/token_tracking/edit_analyzer.py +97 -0
- code_muse/plugins/token_tracking/record.py +55 -0
- code_muse/plugins/token_tracking/register_callbacks.py +277 -0
- code_muse/plugins/token_tracking/reports.py +329 -0
- code_muse/plugins/universal_constructor/__init__.py +13 -0
- code_muse/plugins/universal_constructor/models.py +136 -0
- code_muse/plugins/universal_constructor/register_callbacks.py +47 -0
- code_muse/plugins/universal_constructor/registry.py +390 -0
- code_muse/plugins/universal_constructor/runner.py +474 -0
- code_muse/plugins/universal_constructor/safety.py +440 -0
- code_muse/plugins/universal_constructor/sandbox.py +584 -0
- code_muse/provider_identity.py +105 -0
- code_muse/pydantic_patches.py +410 -0
- code_muse/reopenable_async_client.py +233 -0
- code_muse/round_robin_model.py +151 -0
- code_muse/secret_storage.py +74 -0
- code_muse/security/__init__.py +1 -0
- code_muse/security/redaction.cpython-314-darwin.so +0 -0
- code_muse/security/redaction.cpython-314-x86_64-linux-gnu.so +0 -0
- code_muse/security/redaction.pyx +135 -0
- code_muse/session_storage.py +565 -0
- code_muse/status_display.py +261 -0
- code_muse/stream_parser/__init__.py +76 -0
- code_muse/stream_parser/assistant_text_parser.py +90 -0
- code_muse/stream_parser/citation_parser.py +76 -0
- code_muse/stream_parser/inline_hidden_tag_parser.py +236 -0
- code_muse/stream_parser/proposed_plan_parser.py +158 -0
- code_muse/stream_parser/stream_text_chunk.py +23 -0
- code_muse/stream_parser/stream_text_parser.py +27 -0
- code_muse/stream_parser/tagged_line_parser.cpython-314-darwin.so +0 -0
- code_muse/stream_parser/tagged_line_parser.pyx +251 -0
- code_muse/stream_parser/utf8_stream_parser.cpython-314-darwin.so +0 -0
- code_muse/stream_parser/utf8_stream_parser.pyx +206 -0
- code_muse/summarization_agent.py +308 -0
- code_muse/terminal_utils.cpython-314-darwin.so +0 -0
- code_muse/terminal_utils.cpython-314-x86_64-linux-gnu.so +0 -0
- code_muse/terminal_utils.pyx +483 -0
- code_muse/tools/__init__.py +459 -0
- code_muse/tools/agent_tools.py +613 -0
- code_muse/tools/ask_user_question/__init__.py +26 -0
- code_muse/tools/ask_user_question/constants.py +73 -0
- code_muse/tools/ask_user_question/demo_tui.py +55 -0
- code_muse/tools/ask_user_question/handler.py +232 -0
- code_muse/tools/ask_user_question/models.py +302 -0
- code_muse/tools/ask_user_question/registration.py +37 -0
- code_muse/tools/ask_user_question/renderers.py +336 -0
- code_muse/tools/ask_user_question/terminal_ui.py +327 -0
- code_muse/tools/ask_user_question/theme.py +156 -0
- code_muse/tools/ask_user_question/tui_loop.py +422 -0
- code_muse/tools/background_jobs.py +99 -0
- code_muse/tools/browser/__init__.py +37 -0
- code_muse/tools/browser/browser_control.py +289 -0
- code_muse/tools/browser/browser_interactions.py +545 -0
- code_muse/tools/browser/browser_locators.py +640 -0
- code_muse/tools/browser/browser_manager.py +376 -0
- code_muse/tools/browser/browser_navigation.py +251 -0
- code_muse/tools/browser/browser_screenshot.py +180 -0
- code_muse/tools/browser/browser_scripts.py +462 -0
- code_muse/tools/browser/browser_workflows.py +222 -0
- code_muse/tools/chrome_cdp/__init__.py +1070 -0
- code_muse/tools/chrome_cdp/register_callbacks.py +61 -0
- code_muse/tools/command_runner.py +1401 -0
- code_muse/tools/common.py +1407 -0
- code_muse/tools/display.py +87 -0
- code_muse/tools/file_modifications.py +1099 -0
- code_muse/tools/file_operations.py +860 -0
- code_muse/tools/image_tools.py +185 -0
- code_muse/tools/meetin_proxy/__init__.py +243 -0
- code_muse/tools/meetin_proxy/capture_addon.py +82 -0
- code_muse/tools/meetin_proxy/proxy_manager.py +326 -0
- code_muse/tools/meetin_proxy/register_callbacks.py +45 -0
- code_muse/tools/path_policy.py +219 -0
- code_muse/tools/skills_tools.py +586 -0
- code_muse/tools/subagent_context.py +158 -0
- code_muse/tools/tools_content.py +50 -0
- code_muse/tools/universal_constructor.py +965 -0
- code_muse/uvx_detection.py +241 -0
- code_muse/version_checker.py +86 -0
- code_muse-0.0.1.data/data/code_muse/models.json +66 -0
- code_muse-0.0.1.data/data/code_muse/models_dev_api.json +1 -0
- code_muse-0.0.1.dist-info/METADATA +845 -0
- code_muse-0.0.1.dist-info/RECORD +394 -0
- code_muse-0.0.1.dist-info/WHEEL +4 -0
- code_muse-0.0.1.dist-info/entry_points.txt +2 -0
- code_muse-0.0.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"""Strategy registry for the filter engine.
|
|
2
|
+
|
|
3
|
+
Maps command categories to compression strategy functions. Handles
|
|
4
|
+
registration, duplicate detection, and priority-based overrides.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import logging
|
|
9
|
+
import re
|
|
10
|
+
from collections.abc import Callable
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class StrategyRegistry:
|
|
17
|
+
"""Registry mapping category names to compression strategy functions."""
|
|
18
|
+
|
|
19
|
+
def __init__(self) -> None:
|
|
20
|
+
"""Initialize the registry with the built-in ``unknown`` passthrough."""
|
|
21
|
+
self._strategies: dict[str, tuple[Callable, int]] = {}
|
|
22
|
+
self._register_passthrough()
|
|
23
|
+
|
|
24
|
+
def _register_passthrough(self) -> None:
|
|
25
|
+
"""Register the built-in passthrough strategy for ``unknown``."""
|
|
26
|
+
|
|
27
|
+
def _passthrough(
|
|
28
|
+
command: str,
|
|
29
|
+
stdout: str,
|
|
30
|
+
stderr: str,
|
|
31
|
+
exit_code: int,
|
|
32
|
+
verbosity: Any, # noqa: ANN401
|
|
33
|
+
) -> Any: # noqa: ANN401
|
|
34
|
+
"""Return None to signal that normal execution should proceed."""
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
self._strategies["unknown"] = (_passthrough, -1)
|
|
38
|
+
|
|
39
|
+
def register(
|
|
40
|
+
self,
|
|
41
|
+
category: str,
|
|
42
|
+
strategy_fn: Callable,
|
|
43
|
+
priority: int = 0,
|
|
44
|
+
) -> None:
|
|
45
|
+
"""Register a strategy function for a category.
|
|
46
|
+
|
|
47
|
+
If a strategy is already registered for the category, the new one
|
|
48
|
+
wins only when *priority* is greater than the existing priority.
|
|
49
|
+
A warning is logged on collision regardless.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
category: The command category (e.g. ``"git"``).
|
|
53
|
+
strategy_fn: Callable that accepts
|
|
54
|
+
``(command, stdout, stderr, exit_code, verbosity)`` and returns
|
|
55
|
+
a ``ShellCommandOutput`` or ``None``.
|
|
56
|
+
priority: Higher values win on collision. Defaults to ``0``.
|
|
57
|
+
"""
|
|
58
|
+
existing = self._strategies.get(category)
|
|
59
|
+
if existing is not None:
|
|
60
|
+
_, existing_priority = existing
|
|
61
|
+
if priority > existing_priority:
|
|
62
|
+
logger.warning(
|
|
63
|
+
"StrategyRegistry: overriding '%s' strategy (priority %d > %d)",
|
|
64
|
+
category,
|
|
65
|
+
priority,
|
|
66
|
+
existing_priority,
|
|
67
|
+
)
|
|
68
|
+
self._strategies[category] = (strategy_fn, priority)
|
|
69
|
+
else:
|
|
70
|
+
logger.warning(
|
|
71
|
+
"StrategyRegistry: ignoring '%s' strategy registration "
|
|
72
|
+
"(priority %d <= %d)",
|
|
73
|
+
category,
|
|
74
|
+
priority,
|
|
75
|
+
existing_priority,
|
|
76
|
+
)
|
|
77
|
+
else:
|
|
78
|
+
self._strategies[category] = (strategy_fn, priority)
|
|
79
|
+
|
|
80
|
+
def get_strategy(self, category: str) -> Callable | None:
|
|
81
|
+
"""Return the strategy function for *category*, or ``None``.
|
|
82
|
+
|
|
83
|
+
The built-in ``unknown`` passthrough always returns a callable that
|
|
84
|
+
itself returns ``None``.
|
|
85
|
+
"""
|
|
86
|
+
entry = self._strategies.get(category)
|
|
87
|
+
if entry is None:
|
|
88
|
+
return None
|
|
89
|
+
return entry[0]
|
|
90
|
+
|
|
91
|
+
def list_categories(self) -> list[str]:
|
|
92
|
+
"""Return a sorted list of all registered category names."""
|
|
93
|
+
return sorted(self._strategies.keys())
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# Module-level singleton instance
|
|
97
|
+
_registry_instance: StrategyRegistry | None = None
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_registry() -> StrategyRegistry:
|
|
101
|
+
"""Return the module-level singleton registry."""
|
|
102
|
+
global _registry_instance
|
|
103
|
+
if _registry_instance is None:
|
|
104
|
+
_registry_instance = StrategyRegistry()
|
|
105
|
+
return _registry_instance
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
# ---------------------------------------------------------------------------
|
|
109
|
+
# Content-type stub strategies (filled by Epics 020–021)
|
|
110
|
+
# ---------------------------------------------------------------------------
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _register_content_stubs() -> None:
|
|
114
|
+
"""Register passthrough stubs for content-type strategies."""
|
|
115
|
+
registry = get_registry()
|
|
116
|
+
|
|
117
|
+
def _json_smartcrusher(
|
|
118
|
+
command: str,
|
|
119
|
+
stdout: str,
|
|
120
|
+
stderr: str,
|
|
121
|
+
exit_code: int,
|
|
122
|
+
verbosity: Any, # noqa: ANN401
|
|
123
|
+
) -> Any: # noqa: ANN401
|
|
124
|
+
"""SmartCrusher JSON compression strategy."""
|
|
125
|
+
if not stdout or not stdout.strip():
|
|
126
|
+
return None
|
|
127
|
+
try:
|
|
128
|
+
data = json.loads(stdout)
|
|
129
|
+
except ValueError:
|
|
130
|
+
# Not valid JSON — let passthrough handle it
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
from code_muse.plugins.filter_engine.strategies.json_compressor import (
|
|
134
|
+
compress_json,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
compressed = compress_json(data, verbosity)
|
|
138
|
+
|
|
139
|
+
from code_muse.tools.command_runner import ShellCommandOutput
|
|
140
|
+
|
|
141
|
+
return ShellCommandOutput(
|
|
142
|
+
success=True,
|
|
143
|
+
command=command,
|
|
144
|
+
stdout=compressed,
|
|
145
|
+
stderr=stderr,
|
|
146
|
+
exit_code=exit_code,
|
|
147
|
+
execution_time=0.0,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
def _diff_stub(
|
|
151
|
+
command: str,
|
|
152
|
+
stdout: str,
|
|
153
|
+
stderr: str,
|
|
154
|
+
exit_code: int,
|
|
155
|
+
verbosity: Any, # noqa: ANN401
|
|
156
|
+
) -> Any: # noqa: ANN401
|
|
157
|
+
"""Stub — basic diff compaction, keeps headers only."""
|
|
158
|
+
lines = stdout.splitlines()
|
|
159
|
+
header_lines = [
|
|
160
|
+
line
|
|
161
|
+
for line in lines
|
|
162
|
+
if line.startswith("@@")
|
|
163
|
+
or line.startswith("diff ")
|
|
164
|
+
or line.startswith("---")
|
|
165
|
+
or line.startswith("+++")
|
|
166
|
+
]
|
|
167
|
+
if not header_lines:
|
|
168
|
+
return None
|
|
169
|
+
from code_muse.tools.command_runner import ShellCommandOutput
|
|
170
|
+
|
|
171
|
+
return ShellCommandOutput(
|
|
172
|
+
success=True,
|
|
173
|
+
command=command,
|
|
174
|
+
stdout="\n".join(header_lines) + f"\n[{len(lines)} lines in full diff]",
|
|
175
|
+
stderr=stderr,
|
|
176
|
+
exit_code=exit_code,
|
|
177
|
+
execution_time=0.0,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
def _log_stub(
|
|
181
|
+
command: str,
|
|
182
|
+
stdout: str,
|
|
183
|
+
stderr: str,
|
|
184
|
+
exit_code: int,
|
|
185
|
+
verbosity: Any, # noqa: ANN401
|
|
186
|
+
) -> Any: # noqa: ANN401
|
|
187
|
+
"""Stub — basic log dedup, groups repeated lines."""
|
|
188
|
+
lines = stdout.splitlines()
|
|
189
|
+
if len(lines) < 10:
|
|
190
|
+
return None
|
|
191
|
+
# Simple: just count unique patterns
|
|
192
|
+
from collections import Counter
|
|
193
|
+
|
|
194
|
+
# Keep first 3 and last 3 lines, dedup middle
|
|
195
|
+
if len(lines) <= 6:
|
|
196
|
+
return None
|
|
197
|
+
head = lines[:3]
|
|
198
|
+
tail = lines[-3:]
|
|
199
|
+
middle_patterns = Counter(re.sub(r"\d+", "<N>", line) for line in lines[3:-3])
|
|
200
|
+
compact = (
|
|
201
|
+
head
|
|
202
|
+
+ [f"[{len(lines) - 6} lines, {len(middle_patterns)} unique patterns]"]
|
|
203
|
+
+ tail
|
|
204
|
+
)
|
|
205
|
+
from code_muse.tools.command_runner import ShellCommandOutput
|
|
206
|
+
|
|
207
|
+
return ShellCommandOutput(
|
|
208
|
+
success=True,
|
|
209
|
+
command=command,
|
|
210
|
+
stdout="\n".join(compact),
|
|
211
|
+
stderr=stderr,
|
|
212
|
+
exit_code=exit_code,
|
|
213
|
+
execution_time=0.0,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
def _html_stub(
|
|
217
|
+
command: str,
|
|
218
|
+
stdout: str,
|
|
219
|
+
stderr: str,
|
|
220
|
+
exit_code: int,
|
|
221
|
+
verbosity: Any, # noqa: ANN401
|
|
222
|
+
) -> Any: # noqa: ANN401
|
|
223
|
+
"""Stub — basic HTML tag strip."""
|
|
224
|
+
# Strip all tags, keep text content
|
|
225
|
+
text = re.sub(r"<[^>]+>", " ", stdout)
|
|
226
|
+
text = re.sub(r"\s+", " ", text).strip()
|
|
227
|
+
if not text or len(text) < 10:
|
|
228
|
+
return None
|
|
229
|
+
from code_muse.tools.command_runner import ShellCommandOutput
|
|
230
|
+
|
|
231
|
+
return ShellCommandOutput(
|
|
232
|
+
success=True,
|
|
233
|
+
command=command,
|
|
234
|
+
stdout=text[:2000] + ("..." if len(text) > 2000 else ""),
|
|
235
|
+
stderr=stderr,
|
|
236
|
+
exit_code=exit_code,
|
|
237
|
+
execution_time=0.0,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
def _search_stub(
|
|
241
|
+
command: str,
|
|
242
|
+
stdout: str,
|
|
243
|
+
stderr: str,
|
|
244
|
+
exit_code: int,
|
|
245
|
+
verbosity: Any, # noqa: ANN401
|
|
246
|
+
) -> Any: # noqa: ANN401
|
|
247
|
+
"""Stub — basic search result compaction."""
|
|
248
|
+
# Keep only filename:line:match lines, drop context
|
|
249
|
+
lines = stdout.splitlines()
|
|
250
|
+
match_lines = [
|
|
251
|
+
line
|
|
252
|
+
for line in lines
|
|
253
|
+
if re.match(r"^\S+\.\w+:\d+:", line) or line.startswith("Found ")
|
|
254
|
+
]
|
|
255
|
+
if not match_lines and lines:
|
|
256
|
+
match_lines = lines[:10] # keep first 10 if no matches identified
|
|
257
|
+
from code_muse.tools.command_runner import ShellCommandOutput
|
|
258
|
+
|
|
259
|
+
return ShellCommandOutput(
|
|
260
|
+
success=True,
|
|
261
|
+
command=command,
|
|
262
|
+
stdout="\n".join(match_lines)
|
|
263
|
+
+ (
|
|
264
|
+
f"\n[{len(lines)} total lines]" if len(lines) > len(match_lines) else ""
|
|
265
|
+
),
|
|
266
|
+
stderr=stderr,
|
|
267
|
+
exit_code=exit_code,
|
|
268
|
+
execution_time=0.0,
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
registry.register("json", _json_smartcrusher, priority=10)
|
|
272
|
+
registry.register("diff", _diff_stub, priority=10)
|
|
273
|
+
registry.register("log", _log_stub, priority=10)
|
|
274
|
+
registry.register("html", _html_stub, priority=10)
|
|
275
|
+
registry.register("search", _search_stub, priority=10)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
# Call at module load time
|
|
279
|
+
_register_content_stubs()
|
|
Binary file
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
"""AST-aware code compressors for Python, JavaScript, and Go.
|
|
2
|
+
|
|
3
|
+
Keeps semantic essentials (signatures, imports, error paths), drops
|
|
4
|
+
bodies, docstrings, and whitespace.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import bisect
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from code_muse.plugins.filter_engine.strategies.ast_parser import (
|
|
12
|
+
ASTNode,
|
|
13
|
+
CodeLanguage,
|
|
14
|
+
LanguageParser,
|
|
15
|
+
)
|
|
16
|
+
from code_muse.plugins.filter_engine.verbosity import VerbosityLevel
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# ---------------------------------------------------------------------------
|
|
22
|
+
# Node importance classification
|
|
23
|
+
# ---------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
# Python node types to KEEP (structural/signature)
|
|
26
|
+
PYTHON_KEEP_TYPES: set[str] = {
|
|
27
|
+
"function_definition",
|
|
28
|
+
"class_definition",
|
|
29
|
+
"import_statement",
|
|
30
|
+
"import_from_statement",
|
|
31
|
+
"try_statement",
|
|
32
|
+
"except_clause",
|
|
33
|
+
"raise_statement",
|
|
34
|
+
"return_statement",
|
|
35
|
+
"decorated_definition",
|
|
36
|
+
"parameters",
|
|
37
|
+
"lambda",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# JavaScript/TypeScript node types to KEEP
|
|
41
|
+
JS_KEEP_TYPES: set[str] = {
|
|
42
|
+
"function_declaration",
|
|
43
|
+
"method_definition",
|
|
44
|
+
"class_declaration",
|
|
45
|
+
"export_statement",
|
|
46
|
+
"import_statement",
|
|
47
|
+
"try_statement",
|
|
48
|
+
"catch_clause",
|
|
49
|
+
"throw_statement",
|
|
50
|
+
"return_statement",
|
|
51
|
+
"arrow_function",
|
|
52
|
+
"variable_declarator",
|
|
53
|
+
"lexical_declaration",
|
|
54
|
+
"interface_declaration",
|
|
55
|
+
"type_alias_declaration",
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# Go node types to KEEP
|
|
59
|
+
GO_KEEP_TYPES: set[str] = {
|
|
60
|
+
"function_declaration",
|
|
61
|
+
"method_declaration",
|
|
62
|
+
"type_declaration",
|
|
63
|
+
"import_declaration",
|
|
64
|
+
"return_statement",
|
|
65
|
+
"if_statement",
|
|
66
|
+
"for_statement",
|
|
67
|
+
"call_expression",
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# ---------------------------------------------------------------------------
|
|
72
|
+
# Line-collection helpers
|
|
73
|
+
# ---------------------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _build_line_map(source: str) -> list[int]:
|
|
77
|
+
"""Return a list of byte offsets for the start of every line."""
|
|
78
|
+
offsets = [0]
|
|
79
|
+
for i, ch in enumerate(source):
|
|
80
|
+
if ch == "\n":
|
|
81
|
+
offsets.append(i + 1)
|
|
82
|
+
return offsets
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _byte_to_line(byte_offset: int, line_map: list[int]) -> int:
|
|
86
|
+
"""Return the 0-based line number for a given byte offset."""
|
|
87
|
+
return bisect.bisect_right(line_map, byte_offset) - 1
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
cdef int _byte_to_line_c(int byte_offset, list line_map):
|
|
91
|
+
"""Cython-typed binary search — logic identical to _byte_to_line."""
|
|
92
|
+
cdef int lo = 0
|
|
93
|
+
cdef int hi = len(line_map)
|
|
94
|
+
cdef int mid
|
|
95
|
+
while lo < hi:
|
|
96
|
+
mid = (lo + hi) // 2
|
|
97
|
+
if line_map[mid] <= byte_offset:
|
|
98
|
+
lo = mid + 1
|
|
99
|
+
else:
|
|
100
|
+
hi = mid
|
|
101
|
+
return lo - 1
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _walk_cython(
|
|
105
|
+
object node,
|
|
106
|
+
int depth,
|
|
107
|
+
object keep_types,
|
|
108
|
+
int level,
|
|
109
|
+
list lines,
|
|
110
|
+
set kept_lines,
|
|
111
|
+
list line_map,
|
|
112
|
+
object extra_handler,
|
|
113
|
+
):
|
|
114
|
+
"""Cython-typed AST walker — logic identical to the pure-Python _walk."""
|
|
115
|
+
cdef str node_type
|
|
116
|
+
cdef int start_line
|
|
117
|
+
cdef int end_line
|
|
118
|
+
cdef int i
|
|
119
|
+
cdef int j
|
|
120
|
+
cdef int n_lines = len(lines)
|
|
121
|
+
|
|
122
|
+
node_type = node.type
|
|
123
|
+
start_line = _byte_to_line_c(node.start_byte, line_map)
|
|
124
|
+
end_line = _byte_to_line_c(node.end_byte, line_map)
|
|
125
|
+
|
|
126
|
+
if node_type in keep_types:
|
|
127
|
+
for i in range(start_line, min(end_line + 1, n_lines)):
|
|
128
|
+
if node_type == "function_definition" and i == start_line:
|
|
129
|
+
kept_lines.add(i)
|
|
130
|
+
if level >= 3:
|
|
131
|
+
for j in range(start_line + 1, min(start_line + 4, n_lines)):
|
|
132
|
+
kept_lines.add(j)
|
|
133
|
+
elif level >= 1:
|
|
134
|
+
kept_lines.add(start_line + 1)
|
|
135
|
+
break
|
|
136
|
+
elif node_type in ("class_definition", "decorated_definition"):
|
|
137
|
+
kept_lines.add(i)
|
|
138
|
+
if level >= 2:
|
|
139
|
+
for j in range(start_line + 1, min(start_line + 3, n_lines)):
|
|
140
|
+
kept_lines.add(j)
|
|
141
|
+
break
|
|
142
|
+
elif (
|
|
143
|
+
node_type in ("import_statement", "import_from_statement")
|
|
144
|
+
or node_type == "try_statement"
|
|
145
|
+
or node_type == "except_clause"
|
|
146
|
+
or node_type == "raise_statement"
|
|
147
|
+
or node_type == "return_statement"
|
|
148
|
+
):
|
|
149
|
+
kept_lines.add(i)
|
|
150
|
+
else:
|
|
151
|
+
kept_lines.add(i)
|
|
152
|
+
|
|
153
|
+
if extra_handler is not None:
|
|
154
|
+
extra_handler(node, start_line, end_line, kept_lines, lines, level)
|
|
155
|
+
|
|
156
|
+
for child in node.children:
|
|
157
|
+
_walk_cython(child, depth + 1, keep_types, level, lines, kept_lines, line_map, extra_handler)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _collect_lines(
|
|
161
|
+
source: str,
|
|
162
|
+
ast: ASTNode,
|
|
163
|
+
keep_types: set[str],
|
|
164
|
+
level: int,
|
|
165
|
+
extra_handler: Any | None = None,
|
|
166
|
+
) -> set[int]:
|
|
167
|
+
"""Walk an AST and collect line numbers to keep."""
|
|
168
|
+
lines = source.split("\n")
|
|
169
|
+
kept_lines: set[int] = set()
|
|
170
|
+
line_map = _build_line_map(source)
|
|
171
|
+
|
|
172
|
+
_walk_cython(ast, 0, keep_types, level, lines, kept_lines, line_map, extra_handler)
|
|
173
|
+
return kept_lines
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _build_output(source: str, kept_lines: set[int], comment_prefix: str = "#") -> str:
|
|
177
|
+
"""Build compressed output from kept line numbers."""
|
|
178
|
+
lines = source.split("\n")
|
|
179
|
+
if not kept_lines:
|
|
180
|
+
return source[:200] + "..." if len(source) > 200 else source
|
|
181
|
+
|
|
182
|
+
result_lines: list[str] = []
|
|
183
|
+
last_kept = -1
|
|
184
|
+
for i in sorted(kept_lines):
|
|
185
|
+
if i >= len(lines):
|
|
186
|
+
continue
|
|
187
|
+
if last_kept >= 0 and i > last_kept + 1:
|
|
188
|
+
gap = i - last_kept - 1
|
|
189
|
+
result_lines.append(f"{comment_prefix} ... {gap} lines omitted ...")
|
|
190
|
+
result_lines.append(lines[i])
|
|
191
|
+
last_kept = i
|
|
192
|
+
|
|
193
|
+
if last_kept < len(lines) - 1:
|
|
194
|
+
remaining = len(lines) - 1 - last_kept
|
|
195
|
+
if remaining > 1:
|
|
196
|
+
result_lines.append(f"{comment_prefix} ... {remaining} lines omitted ...")
|
|
197
|
+
elif remaining == 1:
|
|
198
|
+
result_lines.append(lines[-1])
|
|
199
|
+
|
|
200
|
+
return "\n".join(result_lines)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
# ---------------------------------------------------------------------------
|
|
204
|
+
# Compressors
|
|
205
|
+
# ---------------------------------------------------------------------------
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def compress_python(
|
|
209
|
+
source: str, verbosity: VerbosityLevel | int = VerbosityLevel.COMPACT
|
|
210
|
+
) -> str:
|
|
211
|
+
"""Compress Python source code — keep signatures, drop bodies.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
source: Python source code string.
|
|
215
|
+
verbosity: 0 = signatures only, 4 = keep brief bodies.
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
Compressed Python code.
|
|
219
|
+
"""
|
|
220
|
+
level = verbosity.value if isinstance(verbosity, VerbosityLevel) else verbosity
|
|
221
|
+
|
|
222
|
+
ast = LanguageParser.parse(source, CodeLanguage.PYTHON)
|
|
223
|
+
if ast is None:
|
|
224
|
+
return _fallback_compress(source)
|
|
225
|
+
|
|
226
|
+
kept_lines = _collect_lines(source, ast, PYTHON_KEEP_TYPES, level)
|
|
227
|
+
return _build_output(source, kept_lines, comment_prefix="#")
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def compress_javascript(
|
|
231
|
+
source: str, verbosity: VerbosityLevel | int = VerbosityLevel.COMPACT
|
|
232
|
+
) -> str:
|
|
233
|
+
"""Compress JavaScript/TypeScript — keep signatures, drop bodies."""
|
|
234
|
+
level = verbosity.value if isinstance(verbosity, VerbosityLevel) else verbosity
|
|
235
|
+
|
|
236
|
+
lang = LanguageParser.detect_language(source)
|
|
237
|
+
ast = LanguageParser.parse(source, lang)
|
|
238
|
+
if ast is None:
|
|
239
|
+
return _fallback_compress(source)
|
|
240
|
+
|
|
241
|
+
lines = source.split("\n")
|
|
242
|
+
kept_lines: set[int] = set()
|
|
243
|
+
line_map = _build_line_map(source)
|
|
244
|
+
|
|
245
|
+
def _walk(node: ASTNode, depth: int = 0) -> None:
|
|
246
|
+
start_line = _byte_to_line(node.start_byte, line_map)
|
|
247
|
+
|
|
248
|
+
if node.type in JS_KEEP_TYPES:
|
|
249
|
+
for i in range(start_line, min(start_line + 1, len(lines))):
|
|
250
|
+
kept_lines.add(i)
|
|
251
|
+
if level >= 3:
|
|
252
|
+
for j in range(start_line + 1, min(start_line + 3, len(lines))):
|
|
253
|
+
kept_lines.add(j)
|
|
254
|
+
|
|
255
|
+
for child in node.children:
|
|
256
|
+
_walk(child, depth + 1)
|
|
257
|
+
|
|
258
|
+
_walk(ast)
|
|
259
|
+
return _build_output(source, kept_lines, comment_prefix="//")
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def compress_go(
|
|
263
|
+
source: str, verbosity: VerbosityLevel | int = VerbosityLevel.COMPACT
|
|
264
|
+
) -> str:
|
|
265
|
+
"""Compress Go source — keep func/method/type signatures, drop bodies."""
|
|
266
|
+
level = verbosity.value if isinstance(verbosity, VerbosityLevel) else verbosity
|
|
267
|
+
|
|
268
|
+
ast = LanguageParser.parse(source, CodeLanguage.GO)
|
|
269
|
+
if ast is None:
|
|
270
|
+
return _fallback_compress(source)
|
|
271
|
+
|
|
272
|
+
kept_lines: set[int] = set()
|
|
273
|
+
|
|
274
|
+
def _extra_handler(
|
|
275
|
+
node: ASTNode,
|
|
276
|
+
start_line: int,
|
|
277
|
+
end_line: int,
|
|
278
|
+
kept: set[int],
|
|
279
|
+
lines: list[str],
|
|
280
|
+
level: int,
|
|
281
|
+
) -> None:
|
|
282
|
+
if node.type in ("function_declaration", "method_declaration"):
|
|
283
|
+
for i in range(start_line, min(start_line + 2, len(lines))):
|
|
284
|
+
kept.add(i)
|
|
285
|
+
for i in range(start_line, min(end_line + 1, len(lines))):
|
|
286
|
+
if "{" in lines[i]:
|
|
287
|
+
kept.add(i)
|
|
288
|
+
break
|
|
289
|
+
if level >= 3:
|
|
290
|
+
for j in range(start_line + 1, min(start_line + 4, len(lines))):
|
|
291
|
+
kept.add(j)
|
|
292
|
+
|
|
293
|
+
kept_lines = _collect_lines(
|
|
294
|
+
source, ast, GO_KEEP_TYPES, level, extra_handler=_extra_handler
|
|
295
|
+
)
|
|
296
|
+
return _build_output(source, kept_lines, comment_prefix="//")
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def _fallback_compress(source: str) -> str:
|
|
300
|
+
"""Fallback: strip comments when AST parsing fails."""
|
|
301
|
+
lines = source.split("\n")
|
|
302
|
+
result: list[str] = []
|
|
303
|
+
for line in lines:
|
|
304
|
+
stripped = line.strip()
|
|
305
|
+
if stripped.startswith("#") or stripped.startswith("//"):
|
|
306
|
+
continue
|
|
307
|
+
if "#" in line and not line.startswith("#"):
|
|
308
|
+
line = line[: line.index("#")].rstrip()
|
|
309
|
+
if "//" in line and not line.startswith("//"):
|
|
310
|
+
line = line[: line.index("//")].rstrip()
|
|
311
|
+
result.append(line)
|
|
312
|
+
return "\n".join(result)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def compress_ast_code(
|
|
316
|
+
source: str,
|
|
317
|
+
language: CodeLanguage | None = None,
|
|
318
|
+
verbosity: VerbosityLevel | int = VerbosityLevel.COMPACT,
|
|
319
|
+
filename: str | None = None,
|
|
320
|
+
) -> str:
|
|
321
|
+
"""Compress source code using the appropriate language compressor.
|
|
322
|
+
|
|
323
|
+
Args:
|
|
324
|
+
source: Source code string.
|
|
325
|
+
language: Optional pre-detected language.
|
|
326
|
+
verbosity: Compression level.
|
|
327
|
+
filename: Optional filename for language detection.
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
Compressed source code.
|
|
331
|
+
"""
|
|
332
|
+
if language is None and filename:
|
|
333
|
+
language = LanguageParser.detect_language(source, filename)
|
|
334
|
+
elif language is None:
|
|
335
|
+
language = LanguageParser.detect_language(source)
|
|
336
|
+
|
|
337
|
+
compressors = {
|
|
338
|
+
CodeLanguage.PYTHON: compress_python,
|
|
339
|
+
CodeLanguage.JAVASCRIPT: compress_javascript,
|
|
340
|
+
CodeLanguage.TYPESCRIPT: compress_javascript,
|
|
341
|
+
CodeLanguage.GO: compress_go,
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
compressor = compressors.get(language)
|
|
345
|
+
if compressor:
|
|
346
|
+
return compressor(source, verbosity)
|
|
347
|
+
|
|
348
|
+
return _fallback_compress(source)
|