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.
Files changed (394) hide show
  1. code_muse/__init__.py +26 -0
  2. code_muse/__main__.py +10 -0
  3. code_muse/agents/__init__.py +31 -0
  4. code_muse/agents/_builder.py +214 -0
  5. code_muse/agents/_compaction.py +506 -0
  6. code_muse/agents/_diagnostics.py +171 -0
  7. code_muse/agents/_history.py +382 -0
  8. code_muse/agents/_key_listeners.py +148 -0
  9. code_muse/agents/_non_streaming_render.py +148 -0
  10. code_muse/agents/_runtime.py +596 -0
  11. code_muse/agents/agent_creator_agent.py +603 -0
  12. code_muse/agents/agent_helios.py +47 -0
  13. code_muse/agents/agent_manager.py +740 -0
  14. code_muse/agents/agent_muse.py +78 -0
  15. code_muse/agents/agent_planning.py +44 -0
  16. code_muse/agents/agent_qa_melpomene.py +207 -0
  17. code_muse/agents/base_agent.py +194 -0
  18. code_muse/agents/event_stream_handler.py +361 -0
  19. code_muse/agents/json_agent.py +201 -0
  20. code_muse/agents/prompt_v3.py +521 -0
  21. code_muse/agents/subagent_stream_handler.py +273 -0
  22. code_muse/callbacks.py +941 -0
  23. code_muse/chatgpt_codex_client.py +333 -0
  24. code_muse/claude_cache_client.py +853 -0
  25. code_muse/cli_runner/__init__.py +319 -0
  26. code_muse/cli_runner/args.py +63 -0
  27. code_muse/cli_runner/loop.py +510 -0
  28. code_muse/cli_runner/resume.py +72 -0
  29. code_muse/cli_runner/runner.py +161 -0
  30. code_muse/command_line/__init__.py +1 -0
  31. code_muse/command_line/add_model_menu.py +1331 -0
  32. code_muse/command_line/agent_menu.py +674 -0
  33. code_muse/command_line/attachments.py +397 -0
  34. code_muse/command_line/autosave_menu.py +709 -0
  35. code_muse/command_line/clipboard.py +528 -0
  36. code_muse/command_line/colors_menu.py +530 -0
  37. code_muse/command_line/command_handler.py +262 -0
  38. code_muse/command_line/command_registry.py +150 -0
  39. code_muse/command_line/config_commands.py +711 -0
  40. code_muse/command_line/core_commands.py +740 -0
  41. code_muse/command_line/diff_menu.py +865 -0
  42. code_muse/command_line/file_path_completion.py +73 -0
  43. code_muse/command_line/load_context_completion.py +57 -0
  44. code_muse/command_line/model_picker_completion.py +512 -0
  45. code_muse/command_line/model_settings_menu.py +983 -0
  46. code_muse/command_line/onboarding_slides.py +162 -0
  47. code_muse/command_line/onboarding_wizard.py +337 -0
  48. code_muse/command_line/pagination.py +41 -0
  49. code_muse/command_line/pin_command_completion.py +329 -0
  50. code_muse/command_line/prompt_toolkit_completion.py +886 -0
  51. code_muse/command_line/session_commands.py +304 -0
  52. code_muse/command_line/shell_passthrough.py +145 -0
  53. code_muse/command_line/skills_completion.py +158 -0
  54. code_muse/command_line/types.py +18 -0
  55. code_muse/command_line/uc_menu.py +908 -0
  56. code_muse/command_line/utils.py +105 -0
  57. code_muse/command_line/wiggum_state.py +77 -0
  58. code_muse/config.py +1138 -0
  59. code_muse/config_agent.py +168 -0
  60. code_muse/config_appearance.py +241 -0
  61. code_muse/config_model.py +357 -0
  62. code_muse/config_security.py +73 -0
  63. code_muse/error_logging.py +132 -0
  64. code_muse/evals/__init__.py +35 -0
  65. code_muse/evals/eval_helpers.py +81 -0
  66. code_muse/evals/eval_runner.py +299 -0
  67. code_muse/evals/sample_evals/__init__.py +1 -0
  68. code_muse/evals/sample_evals/eval_frugal_reads.py +59 -0
  69. code_muse/evals/sample_evals/eval_memory_planning.py +31 -0
  70. code_muse/evals/sample_evals/eval_shell_efficiency.py +39 -0
  71. code_muse/evals/sample_evals/eval_tool_masking.py +33 -0
  72. code_muse/fs_scan_cache/__init__.py +31 -0
  73. code_muse/fs_scan_cache/invalidation_hooks.py +89 -0
  74. code_muse/fs_scan_cache/scan_cache_core.cpython-314-darwin.so +0 -0
  75. code_muse/fs_scan_cache/scan_cache_core.pyx +203 -0
  76. code_muse/fs_scan_cache/tool_integration.py +309 -0
  77. code_muse/fs_scan_cache/ttl_policy.py +44 -0
  78. code_muse/gemini_code_assist.py +383 -0
  79. code_muse/gemini_model.py +838 -0
  80. code_muse/hook_engine/README.md +105 -0
  81. code_muse/hook_engine/__init__.py +21 -0
  82. code_muse/hook_engine/aliases.py +153 -0
  83. code_muse/hook_engine/engine.py +221 -0
  84. code_muse/hook_engine/executor.py +347 -0
  85. code_muse/hook_engine/matcher.py +154 -0
  86. code_muse/hook_engine/models.py +245 -0
  87. code_muse/hook_engine/registry.py +114 -0
  88. code_muse/hook_engine/trust.py +268 -0
  89. code_muse/hook_engine/validator.py +144 -0
  90. code_muse/http_utils.py +360 -0
  91. code_muse/keymap.py +128 -0
  92. code_muse/list_filtering.py +26 -0
  93. code_muse/main.py +10 -0
  94. code_muse/messaging/__init__.py +259 -0
  95. code_muse/messaging/bus.py +621 -0
  96. code_muse/messaging/commands.py +166 -0
  97. code_muse/messaging/markdown_patches.py +57 -0
  98. code_muse/messaging/message_queue.py +397 -0
  99. code_muse/messaging/messages.py +591 -0
  100. code_muse/messaging/queue_console.py +269 -0
  101. code_muse/messaging/renderers.py +308 -0
  102. code_muse/messaging/rich_renderer.py +1158 -0
  103. code_muse/messaging/shimmer.py +154 -0
  104. code_muse/messaging/spinner/__init__.py +87 -0
  105. code_muse/messaging/spinner/console_spinner.py +250 -0
  106. code_muse/messaging/spinner/spinner_base.py +82 -0
  107. code_muse/messaging/subagent_console.py +458 -0
  108. code_muse/model_factory.py +1203 -0
  109. code_muse/model_switching.py +59 -0
  110. code_muse/model_utils.py +156 -0
  111. code_muse/models.json +66 -0
  112. code_muse/models_cache/__init__.py +26 -0
  113. code_muse/models_cache/blocking_lru_cache.py +98 -0
  114. code_muse/models_cache/cache_writer.py +86 -0
  115. code_muse/models_cache/sha256_hash.cpython-314-darwin.so +0 -0
  116. code_muse/models_cache/sha256_hash.pyx +34 -0
  117. code_muse/models_cache/startup_integration.py +75 -0
  118. code_muse/models_dev_api.json +1 -0
  119. code_muse/models_dev_parser.py +590 -0
  120. code_muse/motion.py +126 -0
  121. code_muse/plugins/__init__.py +471 -0
  122. code_muse/plugins/agent_skills/__init__.py +32 -0
  123. code_muse/plugins/agent_skills/config.py +176 -0
  124. code_muse/plugins/agent_skills/discovery.py +309 -0
  125. code_muse/plugins/agent_skills/downloader.py +389 -0
  126. code_muse/plugins/agent_skills/installer.py +19 -0
  127. code_muse/plugins/agent_skills/metadata.py +293 -0
  128. code_muse/plugins/agent_skills/prompt_builder.py +66 -0
  129. code_muse/plugins/agent_skills/register_callbacks.py +298 -0
  130. code_muse/plugins/agent_skills/remote_catalog.py +320 -0
  131. code_muse/plugins/agent_skills/skill_catalog.py +254 -0
  132. code_muse/plugins/agent_skills/skills_install_menu.py +690 -0
  133. code_muse/plugins/agent_skills/skills_menu.py +791 -0
  134. code_muse/plugins/autonomous_memory/__init__.py +39 -0
  135. code_muse/plugins/autonomous_memory/bm25_scorer.cpython-314-darwin.so +0 -0
  136. code_muse/plugins/autonomous_memory/bm25_scorer.cpython-314-x86_64-linux-gnu.so +0 -0
  137. code_muse/plugins/autonomous_memory/bm25_scorer.pyx +291 -0
  138. code_muse/plugins/autonomous_memory/consolidation.py +82 -0
  139. code_muse/plugins/autonomous_memory/extraction.py +382 -0
  140. code_muse/plugins/autonomous_memory/lease_lock.py +105 -0
  141. code_muse/plugins/autonomous_memory/memory_injection.py +59 -0
  142. code_muse/plugins/autonomous_memory/register_callbacks.py +268 -0
  143. code_muse/plugins/autonomous_memory/secret_scanner.py +62 -0
  144. code_muse/plugins/autonomous_memory/session_scanner.py +163 -0
  145. code_muse/plugins/aws_bedrock/__init__.py +14 -0
  146. code_muse/plugins/aws_bedrock/config.py +99 -0
  147. code_muse/plugins/aws_bedrock/register_callbacks.py +241 -0
  148. code_muse/plugins/aws_bedrock/utils.py +153 -0
  149. code_muse/plugins/azure_foundry/README.md +238 -0
  150. code_muse/plugins/azure_foundry/__init__.py +15 -0
  151. code_muse/plugins/azure_foundry/config.py +125 -0
  152. code_muse/plugins/azure_foundry/discovery.py +187 -0
  153. code_muse/plugins/azure_foundry/register_callbacks.py +495 -0
  154. code_muse/plugins/azure_foundry/token.py +180 -0
  155. code_muse/plugins/azure_foundry/utils.py +345 -0
  156. code_muse/plugins/build_filter/__init__.py +1 -0
  157. code_muse/plugins/build_filter/register_callbacks.py +201 -0
  158. code_muse/plugins/build_filter/strategies/__init__.py +1 -0
  159. code_muse/plugins/build_filter/strategies/build.py +397 -0
  160. code_muse/plugins/chatgpt_oauth/__init__.py +6 -0
  161. code_muse/plugins/chatgpt_oauth/config.py +52 -0
  162. code_muse/plugins/chatgpt_oauth/oauth_flow.py +338 -0
  163. code_muse/plugins/chatgpt_oauth/register_callbacks.py +172 -0
  164. code_muse/plugins/chatgpt_oauth/test_plugin.py +301 -0
  165. code_muse/plugins/chatgpt_oauth/utils.py +538 -0
  166. code_muse/plugins/checkpointing/__init__.py +29 -0
  167. code_muse/plugins/checkpointing/checkpoint_hook.py +51 -0
  168. code_muse/plugins/checkpointing/conversation_snapshots.py +117 -0
  169. code_muse/plugins/checkpointing/register_callbacks.py +51 -0
  170. code_muse/plugins/checkpointing/restore_command.py +263 -0
  171. code_muse/plugins/checkpointing/rewind_shortcut.py +88 -0
  172. code_muse/plugins/checkpointing/shadow_git.py +90 -0
  173. code_muse/plugins/claude_code_hooks/__init__.py +1 -0
  174. code_muse/plugins/claude_code_hooks/config.py +188 -0
  175. code_muse/plugins/claude_code_hooks/register_callbacks.py +208 -0
  176. code_muse/plugins/claude_code_oauth/README.md +167 -0
  177. code_muse/plugins/claude_code_oauth/SETUP.md +93 -0
  178. code_muse/plugins/claude_code_oauth/__init__.py +25 -0
  179. code_muse/plugins/claude_code_oauth/config.py +52 -0
  180. code_muse/plugins/claude_code_oauth/fast_mode.py +124 -0
  181. code_muse/plugins/claude_code_oauth/prompt_handler.py +63 -0
  182. code_muse/plugins/claude_code_oauth/register_callbacks.py +547 -0
  183. code_muse/plugins/claude_code_oauth/test_fast_mode.py +165 -0
  184. code_muse/plugins/claude_code_oauth/test_plugin.py +283 -0
  185. code_muse/plugins/claude_code_oauth/token_refresh_heartbeat.py +237 -0
  186. code_muse/plugins/claude_code_oauth/utils.py +664 -0
  187. code_muse/plugins/copilot_auth/__init__.py +11 -0
  188. code_muse/plugins/copilot_auth/config.py +91 -0
  189. code_muse/plugins/copilot_auth/reasoning_client.py +409 -0
  190. code_muse/plugins/copilot_auth/register_callbacks.py +461 -0
  191. code_muse/plugins/copilot_auth/utils.py +584 -0
  192. code_muse/plugins/custom_commands/__init__.py +14 -0
  193. code_muse/plugins/custom_commands/args_injection.py +82 -0
  194. code_muse/plugins/custom_commands/command_discovery.py +89 -0
  195. code_muse/plugins/custom_commands/command_toml_schema.py +71 -0
  196. code_muse/plugins/custom_commands/register_callbacks.py +176 -0
  197. code_muse/plugins/customizable_commands/__init__.py +0 -0
  198. code_muse/plugins/customizable_commands/register_callbacks.py +136 -0
  199. code_muse/plugins/destructive_command_guard/__init__.py +14 -0
  200. code_muse/plugins/destructive_command_guard/detector.py +375 -0
  201. code_muse/plugins/destructive_command_guard/register_callbacks.py +148 -0
  202. code_muse/plugins/example_custom_command/README.md +280 -0
  203. code_muse/plugins/example_custom_command/register_callbacks.py +51 -0
  204. code_muse/plugins/file_permission_handler/__init__.py +4 -0
  205. code_muse/plugins/file_permission_handler/register_callbacks.py +441 -0
  206. code_muse/plugins/filter_engine/__init__.py +30 -0
  207. code_muse/plugins/filter_engine/classifier.py +153 -0
  208. code_muse/plugins/filter_engine/content_detector.py +184 -0
  209. code_muse/plugins/filter_engine/dispatcher.py +244 -0
  210. code_muse/plugins/filter_engine/register_callbacks.py +188 -0
  211. code_muse/plugins/filter_engine/registry.py +279 -0
  212. code_muse/plugins/filter_engine/strategies/__init__.py +8 -0
  213. code_muse/plugins/filter_engine/strategies/ast_compressor.cpython-314-darwin.so +0 -0
  214. code_muse/plugins/filter_engine/strategies/ast_compressor.cpython-314-x86_64-linux-gnu.so +0 -0
  215. code_muse/plugins/filter_engine/strategies/ast_compressor.pyx +348 -0
  216. code_muse/plugins/filter_engine/strategies/ast_parser.py +167 -0
  217. code_muse/plugins/filter_engine/strategies/code.cpython-314-darwin.so +0 -0
  218. code_muse/plugins/filter_engine/strategies/code.cpython-314-x86_64-linux-gnu.so +0 -0
  219. code_muse/plugins/filter_engine/strategies/code.pyx +584 -0
  220. code_muse/plugins/filter_engine/strategies/git.cpython-314-darwin.so +0 -0
  221. code_muse/plugins/filter_engine/strategies/git.cpython-314-x86_64-linux-gnu.so +0 -0
  222. code_muse/plugins/filter_engine/strategies/git.pyx +438 -0
  223. code_muse/plugins/filter_engine/strategies/json_compressor.cpython-314-darwin.so +0 -0
  224. code_muse/plugins/filter_engine/strategies/json_compressor.pyx +253 -0
  225. code_muse/plugins/filter_engine/strategies/json_patterns.cpython-314-darwin.so +0 -0
  226. code_muse/plugins/filter_engine/strategies/json_patterns.pyx +178 -0
  227. code_muse/plugins/filter_engine/strategies/lint.cpython-314-darwin.so +0 -0
  228. code_muse/plugins/filter_engine/strategies/lint.cpython-314-x86_64-linux-gnu.so +0 -0
  229. code_muse/plugins/filter_engine/strategies/lint.pyx +626 -0
  230. code_muse/plugins/filter_engine/strategies/test.cpython-314-darwin.so +0 -0
  231. code_muse/plugins/filter_engine/strategies/test.cpython-314-x86_64-linux-gnu.so +0 -0
  232. code_muse/plugins/filter_engine/strategies/test.pyx +431 -0
  233. code_muse/plugins/filter_engine/verbosity.py +63 -0
  234. code_muse/plugins/force_push_guard/__init__.py +5 -0
  235. code_muse/plugins/force_push_guard/detector.py +96 -0
  236. code_muse/plugins/force_push_guard/register_callbacks.py +144 -0
  237. code_muse/plugins/force_push_guard/test_detector.py +143 -0
  238. code_muse/plugins/frontend_emitter/__init__.py +25 -0
  239. code_muse/plugins/frontend_emitter/emitter.py +121 -0
  240. code_muse/plugins/frontend_emitter/register_callbacks.py +259 -0
  241. code_muse/plugins/gac/__init__.py +4 -0
  242. code_muse/plugins/gac/git_ops.py +136 -0
  243. code_muse/plugins/gac/prompt.py +191 -0
  244. code_muse/plugins/gac/register_callbacks.py +82 -0
  245. code_muse/plugins/hook_creator/__init__.py +1 -0
  246. code_muse/plugins/hook_creator/register_callbacks.py +34 -0
  247. code_muse/plugins/hook_manager/__init__.py +1 -0
  248. code_muse/plugins/hook_manager/config.py +289 -0
  249. code_muse/plugins/hook_manager/hooks_menu.py +563 -0
  250. code_muse/plugins/hook_manager/register_callbacks.py +227 -0
  251. code_muse/plugins/hook_monitor/register_callbacks.py +36 -0
  252. code_muse/plugins/mindpack/__init__.py +0 -0
  253. code_muse/plugins/mindpack/factory.py +930 -0
  254. code_muse/plugins/mindpack/judge.py +573 -0
  255. code_muse/plugins/mindpack/memory.py +100 -0
  256. code_muse/plugins/mindpack/mindpack_menu.py +1552 -0
  257. code_muse/plugins/mindpack/orchestration.py +605 -0
  258. code_muse/plugins/mindpack/register_callbacks.py +175 -0
  259. code_muse/plugins/mindpack/schemas.py +358 -0
  260. code_muse/plugins/mindpack/tools.py +387 -0
  261. code_muse/plugins/oauth_muse_html.py +226 -0
  262. code_muse/plugins/ollama_setup/__init__.py +5 -0
  263. code_muse/plugins/ollama_setup/completer.py +36 -0
  264. code_muse/plugins/ollama_setup/register_callbacks.py +410 -0
  265. code_muse/plugins/plan_command/__init__.py +0 -0
  266. code_muse/plugins/plan_command/register_callbacks.py +206 -0
  267. code_muse/plugins/plan_mode/__init__.py +37 -0
  268. code_muse/plugins/plan_mode/mode_cycling.py +40 -0
  269. code_muse/plugins/plan_mode/plan_generation.py +68 -0
  270. code_muse/plugins/plan_mode/plan_hooks.py +74 -0
  271. code_muse/plugins/plan_mode/plan_mode_tools.py +138 -0
  272. code_muse/plugins/plan_mode/register_callbacks.py +121 -0
  273. code_muse/plugins/plugin_trust/register_callbacks.py +140 -0
  274. code_muse/plugins/policy_engine/__init__.py +46 -0
  275. code_muse/plugins/policy_engine/approval_flow_integration.py +59 -0
  276. code_muse/plugins/policy_engine/policy_evaluator.py +75 -0
  277. code_muse/plugins/policy_engine/policy_file_discovery.py +90 -0
  278. code_muse/plugins/policy_engine/policy_toml_schema.py +115 -0
  279. code_muse/plugins/policy_engine/register_callbacks.py +112 -0
  280. code_muse/plugins/pop_command/__init__.py +1 -0
  281. code_muse/plugins/pop_command/register_callbacks.py +189 -0
  282. code_muse/plugins/prompt_newline/__init__.py +13 -0
  283. code_muse/plugins/prompt_newline/config.py +19 -0
  284. code_muse/plugins/prompt_newline/register_callbacks.py +159 -0
  285. code_muse/plugins/safety_status/__init__.py +0 -0
  286. code_muse/plugins/safety_status/register_callbacks.py +113 -0
  287. code_muse/plugins/semantic_compression/__init__.py +6 -0
  288. code_muse/plugins/semantic_compression/compressor.py +295 -0
  289. code_muse/plugins/semantic_compression/config.py +123 -0
  290. code_muse/plugins/semantic_compression/register_callbacks.py +320 -0
  291. code_muse/plugins/shell_minimizer/__init__.py +50 -0
  292. code_muse/plugins/shell_minimizer/builtin_filters.toml +393 -0
  293. code_muse/plugins/shell_minimizer/pipeline.py +556 -0
  294. code_muse/plugins/shell_minimizer/primitives.py +482 -0
  295. code_muse/plugins/shell_minimizer/register_callbacks.py +276 -0
  296. code_muse/plugins/shell_safety/__init__.py +6 -0
  297. code_muse/plugins/shell_safety/agent_shell_safety.py +69 -0
  298. code_muse/plugins/shell_safety/command_cache.py +149 -0
  299. code_muse/plugins/shell_safety/register_callbacks.py +202 -0
  300. code_muse/plugins/synthetic_status/__init__.py +1 -0
  301. code_muse/plugins/synthetic_status/register_callbacks.py +128 -0
  302. code_muse/plugins/synthetic_status/status_api.py +145 -0
  303. code_muse/plugins/token_caching/__init__.py +21 -0
  304. code_muse/plugins/token_caching/cache_hit_tracking.py +128 -0
  305. code_muse/plugins/token_caching/cacheable_prefix_detection.py +28 -0
  306. code_muse/plugins/token_caching/register_callbacks.py +54 -0
  307. code_muse/plugins/token_caching/stats_display.py +35 -0
  308. code_muse/plugins/token_tracking/__init__.py +26 -0
  309. code_muse/plugins/token_tracking/database.py +381 -0
  310. code_muse/plugins/token_tracking/edit_analyzer.py +97 -0
  311. code_muse/plugins/token_tracking/record.py +55 -0
  312. code_muse/plugins/token_tracking/register_callbacks.py +277 -0
  313. code_muse/plugins/token_tracking/reports.py +329 -0
  314. code_muse/plugins/universal_constructor/__init__.py +13 -0
  315. code_muse/plugins/universal_constructor/models.py +136 -0
  316. code_muse/plugins/universal_constructor/register_callbacks.py +47 -0
  317. code_muse/plugins/universal_constructor/registry.py +390 -0
  318. code_muse/plugins/universal_constructor/runner.py +474 -0
  319. code_muse/plugins/universal_constructor/safety.py +440 -0
  320. code_muse/plugins/universal_constructor/sandbox.py +584 -0
  321. code_muse/provider_identity.py +105 -0
  322. code_muse/pydantic_patches.py +410 -0
  323. code_muse/reopenable_async_client.py +233 -0
  324. code_muse/round_robin_model.py +151 -0
  325. code_muse/secret_storage.py +74 -0
  326. code_muse/security/__init__.py +1 -0
  327. code_muse/security/redaction.cpython-314-darwin.so +0 -0
  328. code_muse/security/redaction.cpython-314-x86_64-linux-gnu.so +0 -0
  329. code_muse/security/redaction.pyx +135 -0
  330. code_muse/session_storage.py +565 -0
  331. code_muse/status_display.py +261 -0
  332. code_muse/stream_parser/__init__.py +76 -0
  333. code_muse/stream_parser/assistant_text_parser.py +90 -0
  334. code_muse/stream_parser/citation_parser.py +76 -0
  335. code_muse/stream_parser/inline_hidden_tag_parser.py +236 -0
  336. code_muse/stream_parser/proposed_plan_parser.py +158 -0
  337. code_muse/stream_parser/stream_text_chunk.py +23 -0
  338. code_muse/stream_parser/stream_text_parser.py +27 -0
  339. code_muse/stream_parser/tagged_line_parser.cpython-314-darwin.so +0 -0
  340. code_muse/stream_parser/tagged_line_parser.pyx +251 -0
  341. code_muse/stream_parser/utf8_stream_parser.cpython-314-darwin.so +0 -0
  342. code_muse/stream_parser/utf8_stream_parser.pyx +206 -0
  343. code_muse/summarization_agent.py +308 -0
  344. code_muse/terminal_utils.cpython-314-darwin.so +0 -0
  345. code_muse/terminal_utils.cpython-314-x86_64-linux-gnu.so +0 -0
  346. code_muse/terminal_utils.pyx +483 -0
  347. code_muse/tools/__init__.py +459 -0
  348. code_muse/tools/agent_tools.py +613 -0
  349. code_muse/tools/ask_user_question/__init__.py +26 -0
  350. code_muse/tools/ask_user_question/constants.py +73 -0
  351. code_muse/tools/ask_user_question/demo_tui.py +55 -0
  352. code_muse/tools/ask_user_question/handler.py +232 -0
  353. code_muse/tools/ask_user_question/models.py +302 -0
  354. code_muse/tools/ask_user_question/registration.py +37 -0
  355. code_muse/tools/ask_user_question/renderers.py +336 -0
  356. code_muse/tools/ask_user_question/terminal_ui.py +327 -0
  357. code_muse/tools/ask_user_question/theme.py +156 -0
  358. code_muse/tools/ask_user_question/tui_loop.py +422 -0
  359. code_muse/tools/background_jobs.py +99 -0
  360. code_muse/tools/browser/__init__.py +37 -0
  361. code_muse/tools/browser/browser_control.py +289 -0
  362. code_muse/tools/browser/browser_interactions.py +545 -0
  363. code_muse/tools/browser/browser_locators.py +640 -0
  364. code_muse/tools/browser/browser_manager.py +376 -0
  365. code_muse/tools/browser/browser_navigation.py +251 -0
  366. code_muse/tools/browser/browser_screenshot.py +180 -0
  367. code_muse/tools/browser/browser_scripts.py +462 -0
  368. code_muse/tools/browser/browser_workflows.py +222 -0
  369. code_muse/tools/chrome_cdp/__init__.py +1070 -0
  370. code_muse/tools/chrome_cdp/register_callbacks.py +61 -0
  371. code_muse/tools/command_runner.py +1401 -0
  372. code_muse/tools/common.py +1407 -0
  373. code_muse/tools/display.py +87 -0
  374. code_muse/tools/file_modifications.py +1099 -0
  375. code_muse/tools/file_operations.py +860 -0
  376. code_muse/tools/image_tools.py +185 -0
  377. code_muse/tools/meetin_proxy/__init__.py +243 -0
  378. code_muse/tools/meetin_proxy/capture_addon.py +82 -0
  379. code_muse/tools/meetin_proxy/proxy_manager.py +326 -0
  380. code_muse/tools/meetin_proxy/register_callbacks.py +45 -0
  381. code_muse/tools/path_policy.py +219 -0
  382. code_muse/tools/skills_tools.py +586 -0
  383. code_muse/tools/subagent_context.py +158 -0
  384. code_muse/tools/tools_content.py +50 -0
  385. code_muse/tools/universal_constructor.py +965 -0
  386. code_muse/uvx_detection.py +241 -0
  387. code_muse/version_checker.py +86 -0
  388. code_muse-0.0.1.data/data/code_muse/models.json +66 -0
  389. code_muse-0.0.1.data/data/code_muse/models_dev_api.json +1 -0
  390. code_muse-0.0.1.dist-info/METADATA +845 -0
  391. code_muse-0.0.1.dist-info/RECORD +394 -0
  392. code_muse-0.0.1.dist-info/WHEEL +4 -0
  393. code_muse-0.0.1.dist-info/entry_points.txt +2 -0
  394. code_muse-0.0.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,159 @@
1
+ """Register callbacks for the prompt_newline plugin.
2
+
3
+ This plugin is a tiny ergonomics hack: it places the user's input cursor on a
4
+ *new line* below the muse/agent/model/cwd chrome, so long working-directory
5
+ paths don't squeeze the typing area.
6
+
7
+ It hooks two things:
8
+
9
+ * ``startup`` — wraps ``get_prompt_with_active_model`` so the FormattedText it
10
+ returns gets a trailing ``\\n`` appended **at call time** (so the slash
11
+ command toggle takes effect immediately, no restart needed).
12
+ * ``custom_command`` / ``custom_command_help`` — exposes ``/prompt_newline``
13
+ for runtime on/off, persisted via ``muse.cfg``.
14
+
15
+ Default: OFF. Opt-in only.
16
+ """
17
+
18
+ from code_muse.callbacks import register_callback
19
+ from code_muse.plugins.prompt_newline.config import is_enabled, set_enabled
20
+
21
+ _COMMAND_NAME = "prompt_newline"
22
+ _PATCH_ATTR = "_prompt_newline_original"
23
+
24
+
25
+ def _emit_info(message: str) -> None:
26
+ from code_muse.messaging import emit_info
27
+
28
+ emit_info(message)
29
+
30
+
31
+ def _emit_error(message: str) -> None:
32
+ from code_muse.messaging import emit_error
33
+
34
+ emit_error(message)
35
+
36
+
37
+ def _emit_success(message: str) -> None:
38
+ from code_muse.messaging import emit_success
39
+
40
+ emit_success(message)
41
+
42
+
43
+ def _append_newline(formatted_text):
44
+ """Return a new FormattedText with a trailing newline tuple.
45
+
46
+ ``FormattedText`` is a ``list`` subclass of ``(style, text)`` tuples, so we
47
+ rebuild it rather than mutating in place — the upstream caller may cache
48
+ or reuse the returned object.
49
+ """
50
+ from prompt_toolkit.formatted_text import FormattedText
51
+
52
+ try:
53
+ return FormattedText(list(formatted_text) + [("", "\n")])
54
+ except Exception:
55
+ # Defensive: never break the prompt if the upstream shape changes.
56
+ return formatted_text
57
+
58
+
59
+ def _install_prompt_patch() -> None:
60
+ """Monkey-patch ``get_prompt_with_active_model`` to honor ``is_enabled()``.
61
+
62
+ Idempotent: re-running won't double-wrap.
63
+ """
64
+ from code_muse.command_line import prompt_toolkit_completion as ptc
65
+
66
+ if getattr(ptc, _PATCH_ATTR, None) is not None:
67
+ return # Already patched
68
+
69
+ original = ptc.get_prompt_with_active_model
70
+ setattr(ptc, _PATCH_ATTR, original)
71
+
72
+ def patched(base: str = ">>> "):
73
+ result = original(base)
74
+ if is_enabled():
75
+ return _append_newline(result)
76
+ return result
77
+
78
+ ptc.get_prompt_with_active_model = patched
79
+
80
+
81
+ def _on_startup() -> None:
82
+ try:
83
+ _install_prompt_patch()
84
+ except Exception as exc:
85
+ # Plugins must fail gracefully — never crash the app.
86
+ _emit_error(f"prompt_newline: failed to install prompt patch — {exc}")
87
+
88
+
89
+ def _custom_help() -> list[tuple[str, str]]:
90
+ return [
91
+ (
92
+ _COMMAND_NAME,
93
+ "Toggle placing user input on a new line below the prompt chrome",
94
+ )
95
+ ]
96
+
97
+
98
+ def _parse_toggle_arg(command: str) -> bool | None:
99
+ """Parse ``/prompt_newline [on|off|true|false|toggle]``.
100
+
101
+ Returns:
102
+ True/False for an explicit set, or ``None`` to mean "flip current".
103
+ """
104
+ tokens = command.strip().split()
105
+ if len(tokens) < 2:
106
+ return None # bare /prompt_newline → flip
107
+ arg = tokens[1].lower()
108
+ if arg in ("on", "true", "1", "yes", "enable", "enabled"):
109
+ return True
110
+ if arg in ("off", "false", "0", "no", "disable", "disabled"):
111
+ return False
112
+ if arg in ("toggle",):
113
+ return None
114
+ raise ValueError(arg)
115
+
116
+
117
+ def _handle_prompt_newline_command(command: str) -> bool:
118
+ try:
119
+ target = _parse_toggle_arg(command)
120
+ except ValueError as exc:
121
+ _emit_error(
122
+ f"/{_COMMAND_NAME}: unknown argument '{exc.args[0]}'. "
123
+ "Usage: /prompt_newline [on|off|toggle]"
124
+ )
125
+ return True
126
+
127
+ if target is None:
128
+ target = not is_enabled()
129
+
130
+ set_enabled(target)
131
+ state = "ON" if target else "OFF"
132
+ _emit_success(f"[Run] prompt_newline is now {state}")
133
+ if target:
134
+ _emit_info("Your input will appear on a fresh line below the prompt chrome.")
135
+ else:
136
+ _emit_info("Prompt is back to single-line mode.")
137
+ return True
138
+
139
+
140
+ def _handle_custom_command(command: str, name: str):
141
+ if name != _COMMAND_NAME:
142
+ return None
143
+ return _handle_prompt_newline_command(command)
144
+
145
+
146
+ register_callback("startup", _on_startup)
147
+ register_callback("custom_command", _handle_custom_command)
148
+ register_callback("custom_command_help", _custom_help)
149
+
150
+
151
+ __all__ = [
152
+ "_append_newline",
153
+ "_custom_help",
154
+ "_handle_custom_command",
155
+ "_handle_prompt_newline_command",
156
+ "_install_prompt_patch",
157
+ "_on_startup",
158
+ "_parse_toggle_arg",
159
+ ]
File without changes
@@ -0,0 +1,113 @@
1
+ """Safety status plugin — concise /safety and /status slash commands.
2
+
3
+ Shows the current risk posture without exposing secret values.
4
+ """
5
+
6
+ from pathlib import Path
7
+
8
+ from rich.panel import Panel
9
+
10
+ from code_muse.callbacks import count_callbacks, register_callback
11
+ from code_muse.messaging import emit_info
12
+
13
+
14
+ def _custom_help() -> list[tuple[str, str]]:
15
+ return [
16
+ ("safety", "Show safety and trust status (risk posture)"),
17
+ ("status", "Alias for /safety"),
18
+ ]
19
+
20
+
21
+ def _get_status_lines() -> list[str]:
22
+ """Build a list of safety-status lines. All values are redacted or safe."""
23
+ lines: list[str] = []
24
+
25
+ # Yolo mode
26
+ try:
27
+ from code_muse.config import get_yolo_mode
28
+
29
+ yolo = get_yolo_mode()
30
+ except Exception:
31
+ yolo = False
32
+ lines.append(f"Yolo mode : {'on' if yolo else 'off'}")
33
+
34
+ # Shell safety
35
+ try:
36
+ from code_muse.config import get_safety_permission_level
37
+
38
+ level = get_safety_permission_level()
39
+ except Exception:
40
+ level = "unknown"
41
+ lines.append(f"Shell safety : {level}")
42
+
43
+ # Workspace root
44
+ try:
45
+ from code_muse.tools.path_policy import get_workspace_root
46
+
47
+ ws = get_workspace_root()
48
+ except Exception:
49
+ ws = Path.cwd()
50
+ lines.append(f"Workspace : {ws}")
51
+
52
+ # Sensitive-file policy
53
+ try:
54
+ from code_muse.tools.path_policy import SENSITIVE_PATHS
55
+
56
+ policy = f"{len(SENSITIVE_PATHS)} sensitive patterns"
57
+ except Exception:
58
+ policy = "active"
59
+ lines.append(f"Sensitive policy: {policy}")
60
+
61
+ # Hook trust
62
+ try:
63
+ from code_muse.hook_engine.trust import _load_trust_db
64
+
65
+ db = _load_trust_db()
66
+ hook_count = len(db)
67
+ except Exception:
68
+ hook_count = 0
69
+ lines.append(f"Hook trust : {hook_count} trusted project(s)")
70
+
71
+ # Plugin / callback activity
72
+ try:
73
+ total_callbacks = count_callbacks()
74
+ except Exception:
75
+ total_callbacks = 0
76
+ lines.append(f"Callbacks active: {total_callbacks}")
77
+
78
+ # Universal Constructor
79
+ try:
80
+ from code_muse.config import get_universal_constructor_enabled
81
+
82
+ uc = get_universal_constructor_enabled()
83
+ except Exception:
84
+ uc = True
85
+ lines.append(f"UC enabled : {'yes' if uc else 'no'}")
86
+
87
+ # Environment redaction hint
88
+ lines.append("")
89
+ lines.append("Secret values are redacted in logs and status displays.")
90
+
91
+ return lines
92
+
93
+
94
+ def _render_panel(lines: list[str]) -> Panel:
95
+ body = "\n".join(lines)
96
+ return Panel(body, title="Safety Status", border_style="cyan")
97
+
98
+
99
+ def _handle_custom_command(command: str, name: str) -> bool | None:
100
+ if not name:
101
+ return None
102
+
103
+ if name in ("safety", "status"):
104
+ lines = _get_status_lines()
105
+ panel = _render_panel(lines)
106
+ emit_info(panel)
107
+ return True
108
+
109
+ return None
110
+
111
+
112
+ register_callback("custom_command_help", _custom_help)
113
+ register_callback("custom_command", _handle_custom_command)
@@ -0,0 +1,6 @@
1
+ """Semantic Compression Plugin.
2
+
3
+ Lossy text compression that strips predictable grammar while
4
+ preserving semantic content. Works on tool outputs and provides
5
+ a ``/compress`` slash command for manual use.
6
+ """
@@ -0,0 +1,295 @@
1
+ """Semantic Compression Engine.
2
+
3
+ Lossy text compression that removes predictable grammar while preserving
4
+ semantic payload. LLMs reconstruct grammar from content words, so we
5
+ strip the glue and keep the meaning.
6
+
7
+ Rules are applied in tiers:
8
+ - Tier 1 (always safe): articles, copulas, filler phrases, intensifiers,
9
+ complementizer "that"
10
+ - Tier 2 (aggressive): auxiliaries, modals (except must), pronouns,
11
+ relative pronouns
12
+ - Structural: passive→active, nominalization→verb, redundant pairs,
13
+ clause→modifier
14
+
15
+ Always preserved: nouns, main verbs, meaning-bearing modifiers, numbers,
16
+ uncertainty markers, negation, temporal markers, causality, requirements,
17
+ proper nouns, and technical terms.
18
+
19
+ Code blocks (``` fenced ```) are detected and left untouched.
20
+ """
21
+
22
+ import re
23
+
24
+ # ---------------------------------------------------------------------------
25
+ # Tier 1 — always safe deletions
26
+ # ---------------------------------------------------------------------------
27
+
28
+ # Articles: a, an, the (standalone, word boundary)
29
+ _RE_ARTICLES = re.compile(r"\b(a|an|the)\b", re.IGNORECASE)
30
+
31
+ # Copulas: is, are, was, were, am, be, been, being
32
+ _RE_COPULAS = re.compile(r"\b(is|are|was|were|am|be|been|being)\b", re.IGNORECASE)
33
+
34
+ # Pure intensifiers: very, quite, rather, really, extremely, somewhat
35
+ _RE_INTENSIFIERS = re.compile(
36
+ r"\b(very|quite|rather|really|extremely|somewhat)\b", re.IGNORECASE
37
+ )
38
+
39
+ # Filler phrase → replacement
40
+ _FILLER_PHRASES: list[tuple[re.Pattern, str]] = [
41
+ (re.compile(r"\bin order to\b", re.IGNORECASE), "to"),
42
+ (re.compile(r"\bdue to the fact that\b", re.IGNORECASE), "because"),
43
+ (re.compile(r"\bin terms of\b", re.IGNORECASE), ""),
44
+ (re.compile(r"\bin the process of\b", re.IGNORECASE), ""),
45
+ (re.compile(r"\bin the context of\b", re.IGNORECASE), ""),
46
+ (re.compile(r"\bit is worth noting that\b", re.IGNORECASE), ""),
47
+ (re.compile(r"\bneedless to say\b", re.IGNORECASE), ""),
48
+ (re.compile(r"\bwhat is called\b", re.IGNORECASE), ""),
49
+ (re.compile(r"\bas a matter of fact\b", re.IGNORECASE), ""),
50
+ ]
51
+
52
+ # Complementizer "that" after bridge verbs.
53
+ # Matches stems with regular -s/-ed/-ing plus common irregulars.
54
+ # e.g. "report/reports/reported/reporting that X" → "report X"
55
+ _BRIDGE_STEMS = (
56
+ r"know|think|believe|say|see|find|show|note|ensure|suggest"
57
+ r"|indicate|report|state|claim|argue|feel|suspect|realize"
58
+ r"|learn|discover|remember|forget|understand|assume"
59
+ )
60
+ # Captures bridge verb (stem + optional -s/-ed/-ing, or irregular)
61
+ # Suffix handles regular -s/-ed/-ing and e-dropping -d (e.g. assume→assumed)
62
+ _RE_COMPLEMENTIZER = re.compile(
63
+ rf"\b((?:{_BRIDGE_STEMS})(?:s|e?d|ing)?"
64
+ r"|knew|thought|said|saw|seen|found|showed|shown"
65
+ r"|felt|learnt|learnt|forgot|forgotten|understood"
66
+ r")\s+that\b",
67
+ re.IGNORECASE,
68
+ )
69
+
70
+ # ---------------------------------------------------------------------------
71
+ # Tier 2 — aggressive (only when aggressive=True)
72
+ # ---------------------------------------------------------------------------
73
+
74
+ # Auxiliary verbs: have/has/had, do/does/did, will/would
75
+ _RE_AUXILIARIES = re.compile(
76
+ r"\b(have|has|had|do|does|did|will|would)\b", re.IGNORECASE
77
+ )
78
+
79
+ # Modal verbs except "must"
80
+ _RE_MODALS = re.compile(r"\b(can|could|may|might|should)\b", re.IGNORECASE)
81
+
82
+ # Pronouns (subject/object, when referent is obvious)
83
+ _RE_PRONOUNS = re.compile(
84
+ r"\b(it|this|that|these|those|he|she|they|him|her|them)\b",
85
+ re.IGNORECASE,
86
+ )
87
+
88
+ # Relative pronouns
89
+ _RE_RELATIVES = re.compile(r"\b(which|that|who|whom)\b", re.IGNORECASE)
90
+
91
+ # ---------------------------------------------------------------------------
92
+ # Structural compression patterns
93
+ # ---------------------------------------------------------------------------
94
+
95
+ # Passive → active: "was eaten by dog" → "dog ate"
96
+ # Pattern captures: group 1 = past participle, group 2 = agent noun
97
+ # Handles regular -ed/-en and irregulars like made, gone, done, known
98
+ _PASSIVE_BY_RE = re.compile(
99
+ r"\b(?:is|are|was|were|be|been|being)\s+"
100
+ r"(\w+(?:ed|en|[dt]e?|wn|own))"
101
+ r"\s+by\s+(?:the\s+)?(\w+)",
102
+ re.IGNORECASE,
103
+ )
104
+
105
+ # Nominalization → verb (common patterns)
106
+ _NOMINALIZATIONS: list[tuple[re.Pattern, str]] = [
107
+ (re.compile(r"\bmade? a decision\b", re.IGNORECASE), "decided"),
108
+ (re.compile(r"\bmade? an? analysis\b", re.IGNORECASE), "analyzed"),
109
+ (re.compile(r"\bgave? consideration\b", re.IGNORECASE), "considered"),
110
+ (re.compile(r"\btook? into account\b", re.IGNORECASE), "considered"),
111
+ (re.compile(r"\bmade? an? assessment\b", re.IGNORECASE), "assessed"),
112
+ (re.compile(r"\bmade? an? evaluation\b", re.IGNORECASE), "evaluated"),
113
+ (re.compile(r"\bmade? a recommendation\b", re.IGNORECASE), "recommended"),
114
+ (re.compile(r"\bmade? an? observation\b", re.IGNORECASE), "observed"),
115
+ (re.compile(r"\bmade? a prediction\b", re.IGNORECASE), "predicted"),
116
+ (re.compile(r"\bmade? a statement\b", re.IGNORECASE), "stated"),
117
+ (re.compile(r"\bgave? permission\b", re.IGNORECASE), "permitted"),
118
+ (re.compile(r"\bconducted an? investigation\b", re.IGNORECASE), "investigated"),
119
+ (re.compile(r"\bperformed an? analysis\b", re.IGNORECASE), "analyzed"),
120
+ (re.compile(r"\btook? a look\b", re.IGNORECASE), "looked"),
121
+ (re.compile(r"\breached a conclusion\b", re.IGNORECASE), "concluded"),
122
+ (re.compile(r"\bcame to the conclusion\b", re.IGNORECASE), "concluded"),
123
+ (re.compile(r"\bprovided an? explanation\b", re.IGNORECASE), "explained"),
124
+ ]
125
+
126
+ # Redundant pairs → single
127
+ _REDUNDANT_PAIRS: list[tuple[re.Pattern, str]] = [
128
+ (re.compile(r"\beach and every\b", re.IGNORECASE), "every"),
129
+ (re.compile(r"\bfirst and foremost\b", re.IGNORECASE), "first"),
130
+ (re.compile(r"\bbasic and fundamental\b", re.IGNORECASE), "fundamental"),
131
+ (re.compile(r"\bnull and void\b", re.IGNORECASE), "void"),
132
+ (re.compile(r"\btrue and accurate\b", re.IGNORECASE), "accurate"),
133
+ (re.compile(r"\bfull and complete\b", re.IGNORECASE), "complete"),
134
+ (re.compile(r"\bany and all\b", re.IGNORECASE), "all"),
135
+ (re.compile(r"\bvarious and sundry\b", re.IGNORECASE), "various"),
136
+ ]
137
+
138
+ # Clause → modifier: "anomaly that was reported" → "reported anomaly"
139
+ # Pattern: noun + relative pronoun + copula + past participle → past participle + noun
140
+ _CLAUSE_TO_MODIFIER_RE = re.compile(
141
+ r"\b(\w+)\s+(?:that|which|who)\s+(?:is|are|was|were|be|been|being)\s+"
142
+ r"(\w+(?:ed|en|[dt]e?|wn|own))\b",
143
+ re.IGNORECASE,
144
+ )
145
+
146
+ # ---------------------------------------------------------------------------
147
+ # Code block handling
148
+ # ---------------------------------------------------------------------------
149
+
150
+ _FENCE_RE = re.compile(r"```[\s\S]*?```")
151
+
152
+
153
+ def _split_code_blocks(text: str) -> list[tuple[bool, str]]:
154
+ """Split *text* into (is_code, segment) tuples.
155
+
156
+ Code fences (``` ... ```) are marked as code and left untouched.
157
+ Everything else is non-code and eligible for compression.
158
+ """
159
+ segments: list[tuple[bool, str]] = []
160
+ pos = 0
161
+ for match in _FENCE_RE.finditer(text):
162
+ start = match.start()
163
+ if start > pos:
164
+ segments.append((False, text[pos:start]))
165
+ segments.append((True, match.group()))
166
+ pos = match.end()
167
+ if pos < len(text):
168
+ segments.append((False, text[pos:]))
169
+ return segments
170
+
171
+
172
+ # ---------------------------------------------------------------------------
173
+ # Core compression pipeline
174
+ # ---------------------------------------------------------------------------
175
+
176
+
177
+ def compress_semantic(text: str, aggressive: bool = False) -> str:
178
+ """Apply semantic compression to *text*.
179
+
180
+ Parameters
181
+ ----------
182
+ text:
183
+ The input text to compress.
184
+ aggressive:
185
+ If ``True``, also apply Tier 2 deletions (auxiliaries, modals,
186
+ pronouns, relatives) in addition to Tier 1.
187
+
188
+ Returns
189
+ -------
190
+ str
191
+ The compressed text with code blocks preserved.
192
+ """
193
+ if not text or not text.strip():
194
+ return text
195
+
196
+ # Split into code and non-code segments
197
+ segments = _split_code_blocks(text)
198
+
199
+ result_parts: list[str] = []
200
+ for is_code, segment in segments:
201
+ if is_code:
202
+ result_parts.append(segment)
203
+ else:
204
+ result_parts.append(_compress_segment(segment, aggressive))
205
+
206
+ return "".join(result_parts)
207
+
208
+
209
+ def _compress_segment(segment: str, aggressive: bool) -> str:
210
+ """Compress a single non-code text segment.
211
+
212
+ Order matters: structural transformations run *before* Tier 1
213
+ deletions so patterns like passive→active can see the copulas
214
+ before they are stripped.
215
+ """
216
+ s = segment
217
+
218
+ # --- Structural compression (before Tier 1) ---
219
+
220
+ # Passive → active: "was eaten by dog" → "dog ate"
221
+ s = _PASSIVE_BY_RE.sub(r"\2 \1", s)
222
+
223
+ # Clause → modifier: "anomaly that was reported" → "reported anomaly"
224
+ s = _CLAUSE_TO_MODIFIER_RE.sub(r"\2 \1", s)
225
+
226
+ # Nominalizations → verb
227
+ for pattern, replacement in _NOMINALIZATIONS:
228
+ s = pattern.sub(replacement, s)
229
+
230
+ # Redundant pairs → single
231
+ for pattern, replacement in _REDUNDANT_PAIRS:
232
+ s = pattern.sub(replacement, s)
233
+
234
+ # --- Tier 1 (always safe deletions) ---
235
+
236
+ # Filler phrases first (they may contain articles/copulas)
237
+ for pattern, replacement in _FILLER_PHRASES:
238
+ s = pattern.sub(replacement, s)
239
+
240
+ # Complementizer "that" after bridge verbs
241
+ s = _RE_COMPLEMENTIZER.sub(r"\1", s)
242
+
243
+ # Articles
244
+ s = _RE_ARTICLES.sub("", s)
245
+
246
+ # Copulas (after structural pass, so passive→active already fired)
247
+ s = _RE_COPULAS.sub("", s)
248
+
249
+ # Pure intensifiers
250
+ s = _RE_INTENSIFIERS.sub("", s)
251
+
252
+ # --- Tier 2 (aggressive only) ---
253
+ if aggressive:
254
+ s = _RE_AUXILIARIES.sub("", s)
255
+ s = _RE_MODALS.sub("", s)
256
+ s = _RE_PRONOUNS.sub("", s)
257
+ s = _RE_RELATIVES.sub("", s)
258
+
259
+ # --- Post-processing ---
260
+
261
+ # Collapse multiple spaces into one
262
+ s = re.sub(r" {2,}", " ", s)
263
+
264
+ # Remove space before punctuation
265
+ s = re.sub(r" +([.,!?;:])", r"\1", s)
266
+
267
+ # Remove leading/trailing whitespace per line
268
+ lines = [ln.strip() for ln in s.splitlines()]
269
+ s = "\n".join(ln for ln in lines if ln)
270
+
271
+ # Collapse 3+ consecutive newlines into 2
272
+ s = re.sub(r"\n{3,}", "\n\n", s)
273
+
274
+ return s
275
+
276
+
277
+ # ---------------------------------------------------------------------------
278
+ # Convenience: compress known patterns in one shot
279
+ # ---------------------------------------------------------------------------
280
+
281
+
282
+ def compress_for_llm(text: str) -> str:
283
+ """Compress text intended for LLM consumption (aggressive mode).
284
+
285
+ Equivalent to ``compress_semantic(text, aggressive=True)``.
286
+ """
287
+ return compress_semantic(text, aggressive=True)
288
+
289
+
290
+ def compress_for_display(text: str) -> str:
291
+ """Compress text for human display (safe mode only, Tier 1).
292
+
293
+ Equivalent to ``compress_semantic(text, aggressive=False)``.
294
+ """
295
+ return compress_semantic(text, aggressive=False)
@@ -0,0 +1,123 @@
1
+ """Plugin-level config helpers for semantic_compression."""
2
+
3
+ import json
4
+ import logging
5
+
6
+ from code_muse.config import get_value, set_config_value
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+ _CONFIG_KEY_ENABLED = "semantic_compression_enabled"
11
+ _CONFIG_KEY_ALLOWLIST = "semantic_compression_allowlist"
12
+ _CONFIG_KEY_BLOCKLIST = "semantic_compression_blocklist"
13
+ _TRUTHY = ("true", "1", "yes", "on")
14
+
15
+
16
+ def get_semantic_compression_enabled() -> bool:
17
+ """Check if automatic semantic compression of tool output is enabled.
18
+
19
+ Returns:
20
+ True if enabled, False otherwise. Default: False (opt-in).
21
+ """
22
+ cfg_val = get_value(_CONFIG_KEY_ENABLED)
23
+ if cfg_val is None:
24
+ return False
25
+ return str(cfg_val).strip().lower() in _TRUTHY
26
+
27
+
28
+ def set_semantic_compression_enabled(enabled: bool) -> None:
29
+ """Enable or disable automatic semantic compression of tool output.
30
+
31
+ Args:
32
+ enabled: True to enable, False to disable.
33
+ """
34
+ set_config_value(_CONFIG_KEY_ENABLED, "true" if enabled else "false")
35
+ logger.info("Semantic compression %s", "enabled" if enabled else "disabled")
36
+
37
+
38
+ def _parse_json_tool_list(config_value: str | None) -> set[str]:
39
+ """Parse a JSON list of tool names from config.
40
+
41
+ Returns:
42
+ Set of tool names. Empty set if config is missing or invalid.
43
+ """
44
+ if not config_value:
45
+ return set()
46
+ try:
47
+ parsed = json.loads(config_value)
48
+ if isinstance(parsed, list):
49
+ return {str(item).strip() for item in parsed if item}
50
+ except json.JSONDecodeError as e:
51
+ logger.error("Failed to parse tool list config: %s", e)
52
+ return set()
53
+
54
+
55
+ def _serialize_tool_list(tool_names: set[str]) -> str:
56
+ """Serialize a set of tool names to a JSON list string."""
57
+ return json.dumps(sorted(tool_names))
58
+
59
+
60
+ def get_compression_allowlist() -> set[str]:
61
+ """Get the set of tool names explicitly allowed for compression.
62
+
63
+ Returns:
64
+ Set of tool names. If non-empty, ONLY these tools will have
65
+ their output compressed (when enabled). Empty means all tools
66
+ are allowed unless blocked.
67
+ """
68
+ return _parse_json_tool_list(get_value(_CONFIG_KEY_ALLOWLIST))
69
+
70
+
71
+ def set_compression_allowlist(tool_names: set[str]) -> None:
72
+ """Set the allowlist of tool names for compression.
73
+
74
+ Args:
75
+ tool_names: Set of tool names to allow. Empty set clears the allowlist.
76
+ """
77
+ set_config_value(_CONFIG_KEY_ALLOWLIST, _serialize_tool_list(tool_names))
78
+ logger.info("Compression allowlist updated: %s", sorted(tool_names) or "(empty)")
79
+
80
+
81
+ def get_compression_blocklist() -> set[str]:
82
+ """Get the set of tool names explicitly blocked from compression.
83
+
84
+ Returns:
85
+ Set of tool names that will never have their output compressed,
86
+ even when compression is enabled.
87
+ """
88
+ return _parse_json_tool_list(get_value(_CONFIG_KEY_BLOCKLIST))
89
+
90
+
91
+ def set_compression_blocklist(tool_names: set[str]) -> None:
92
+ """Set the blocklist of tool names for compression.
93
+
94
+ Args:
95
+ tool_names: Set of tool names to block. Empty set clears the blocklist.
96
+ """
97
+ set_config_value(_CONFIG_KEY_BLOCKLIST, _serialize_tool_list(tool_names))
98
+ logger.info("Compression blocklist updated: %s", sorted(tool_names) or "(empty)")
99
+
100
+
101
+ def is_tool_allowed(tool_name: str) -> bool:
102
+ """Check if a specific tool's output should be compressed.
103
+
104
+ Logic:
105
+ 1. If blocklist contains the tool name → False.
106
+ 2. If allowlist is non-empty and does NOT contain the tool → False.
107
+ 3. Otherwise → True.
108
+
109
+ Args:
110
+ tool_name: Name of the tool to check.
111
+
112
+ Returns:
113
+ True if the tool's output may be compressed, False otherwise.
114
+ """
115
+ blocklist = get_compression_blocklist()
116
+ if tool_name in blocklist:
117
+ return False
118
+
119
+ allowlist = get_compression_allowlist()
120
+ if allowlist and tool_name not in allowlist:
121
+ return False
122
+
123
+ return True