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,556 @@
1
+ """Declarative TOML-based pipeline engine for shell output minimisation.
2
+
3
+ Models a ``CompiledPipeline`` that chains together text-transform
4
+ primitives from :mod:`code_muse.plugins.shell_minimizer.primitives`,
5
+ gated by exit code, and driven by TOML configuration.
6
+
7
+ Stages are applied in this order (each is optional)::
8
+
9
+ 1. ``strip_ansi`` (bool)
10
+ 2. ``replace`` (list of {pattern, replacement} regex subs)
11
+ 3. ``match_output`` (list of {pattern, message, unless?})
12
+ 4. ``strip_lines_matching`` / ``keep_lines_matching`` (mutually exclusive)
13
+ 5. ``truncate_lines_at`` (int)
14
+ 6. ``head_lines`` / ``tail_lines`` (int)
15
+ 7. ``max_lines`` (int)
16
+ 8. ``on_empty`` (string sentinel)
17
+
18
+ Exit-code gating is declared per pipeline via ``only_on_exit`` or
19
+ ``except_on_exit``.
20
+
21
+ The module can be exercised standalone with ``python -m …`` for inline
22
+ tests (doctest-style).
23
+ """
24
+
25
+ import re
26
+ from dataclasses import dataclass, field
27
+
28
+ # ---------------------------------------------------------------------------
29
+ # Import primitives lazily so the module is importable without them.
30
+ # They are required at *compile* time and *apply* time, though.
31
+ # ---------------------------------------------------------------------------
32
+
33
+ _primitives = None
34
+
35
+
36
+ def _get_primitives():
37
+ """Lazy-load the primitives module once needed."""
38
+ global _primitives
39
+ if _primitives is None:
40
+ from code_muse.plugins.shell_minimizer import primitives as _p
41
+
42
+ _primitives = _p
43
+ return _primitives
44
+
45
+
46
+ # ---------------------------------------------------------------------------
47
+ # Models
48
+ # ---------------------------------------------------------------------------
49
+
50
+
51
+ @dataclass
52
+ class ReplaceStep:
53
+ """A regex-substitution step defined in TOML ``[[filters.xxx.replace]]``."""
54
+
55
+ pattern: str
56
+ replacement: str
57
+ _compiled: re.Pattern | None = field(default=None, repr=False)
58
+
59
+ def compile(self) -> None:
60
+ """Pre-compile the pattern (called by the pipeline compiler).
61
+
62
+ Uses ``re.MULTILINE`` so that ``^`` / ``$`` anchors match
63
+ line boundaries, not just the whole-string boundaries.
64
+ """
65
+ self._compiled = re.compile(self.pattern, re.MULTILINE)
66
+
67
+ def apply(self, text: str) -> str:
68
+ """Run this substitution across *text*."""
69
+ if self._compiled is None:
70
+ self.compile()
71
+ return self._compiled.sub(self.replacement, text)
72
+
73
+
74
+ @dataclass
75
+ class MatchOutputRule:
76
+ """Short-circuit rule: if the entire output matches *pattern*,
77
+ replace it with *message*. Optional *unless* pattern inverts
78
+ the match (only fires when *unless* does NOT match).
79
+ """
80
+
81
+ pattern: str
82
+ message: str
83
+ unless: str | None = None
84
+ _compiled_pattern: re.Pattern | None = field(default=None, repr=False)
85
+ _compiled_unless: re.Pattern | None = field(default=None, repr=False)
86
+
87
+ def compile(self) -> None:
88
+ self._compiled_pattern = re.compile(self.pattern, re.DOTALL)
89
+ if self.unless:
90
+ self._compiled_unless = re.compile(self.unless, re.DOTALL)
91
+
92
+ def matches(self, text: str) -> bool:
93
+ """Return True if this rule should fire."""
94
+ if self._compiled_pattern is None:
95
+ self.compile()
96
+ if not self._compiled_pattern.fullmatch(text):
97
+ return False
98
+ return not (self._compiled_unless and self._compiled_unless.fullmatch(text))
99
+
100
+
101
+ @dataclass
102
+ class PipelineDef:
103
+ """Raw pipeline definition as parsed from TOML (before compilation).
104
+
105
+ This is the intermediate representation that TOML tables map onto.
106
+ """
107
+
108
+ name: str = ""
109
+ match_command: str | None = None
110
+ match_subcommand: str | None = None
111
+
112
+ # Stage flags
113
+ strip_ansi: bool = False
114
+
115
+ # Replace steps
116
+ replace: list[dict] = field(default_factory=list) # [{pattern, replacement}, ...]
117
+
118
+ # Match-output rules
119
+ match_output: list[dict] = field(default_factory=list)
120
+
121
+ # Line-filtering (mutually exclusive)
122
+ strip_lines_matching: list[str] = field(default_factory=list)
123
+ keep_lines_matching: list[str] = field(default_factory=list)
124
+
125
+ # Truncation
126
+ truncate_lines_at: int | None = None
127
+
128
+ # Head / tail / max (only one should be set typically)
129
+ head_lines: int | None = None
130
+ tail_lines: int | None = None
131
+ max_lines: int | None = None
132
+
133
+ # Empty-output sentinel
134
+ on_empty: str | None = None
135
+
136
+ # Exit-code gating
137
+ only_on_exit: list[int] | None = None
138
+ except_on_exit: list[int] | None = None
139
+
140
+
141
+ @dataclass
142
+ class CompiledPipeline:
143
+ """A pipeline that has been compiled and is ready to apply.
144
+
145
+ All regex patterns are compiled, defaults are resolved, and the
146
+ stage list is flattened into an ordered list of callables.
147
+ """
148
+
149
+ name: str = ""
150
+ match_command: re.Pattern | None = None
151
+ match_subcommand: re.Pattern | None = None
152
+ only_on_exit: list[int] | None = None
153
+ except_on_exit: list[int] | None = None
154
+ on_empty: str | None = None
155
+
156
+ # Ordered pipeline stages, each is a callable (str, exit_code?) -> str
157
+ _stages: list = field(default_factory=list)
158
+
159
+ def matches_program(self, command: str) -> bool:
160
+ """Check whether *command* should be processed by this pipeline.
161
+
162
+ If neither ``match_command`` nor ``match_subcommand`` is set,
163
+ the pipeline is never auto-matched (must be invoked manually).
164
+ """
165
+ if self.match_command is None:
166
+ return True # Manual pipelines match everything
167
+
168
+ # Extract first two tokens: e.g. "git diff --cached" → ["git", "diff"]
169
+ tokens = command.strip().split()
170
+ prog = tokens[0] if tokens else ""
171
+ subcmd = tokens[1] if len(tokens) > 1 else ""
172
+
173
+ if not self.match_command.fullmatch(prog):
174
+ return False
175
+
176
+ if self.match_subcommand is not None:
177
+ if not self.match_subcommand.fullmatch(subcmd):
178
+ return False
179
+
180
+ return True
181
+
182
+ def gated_by_exit(self, exit_code: int) -> bool:
183
+ """Return True when the pipeline should be applied for *exit_code*."""
184
+ if self.only_on_exit is not None:
185
+ return exit_code in self.only_on_exit
186
+ if self.except_on_exit is not None:
187
+ return exit_code not in self.except_on_exit
188
+ return True # No gating — always apply
189
+
190
+ def apply(self, input: str, exit_code: int = 0) -> str:
191
+ """Run the compiled pipeline on *input*.
192
+
193
+ Exit-code gating is checked first; if the pipeline should not
194
+ run for this exit code the input is returned unchanged.
195
+ """
196
+ if not self.gated_by_exit(exit_code):
197
+ return input
198
+
199
+ text = input
200
+
201
+ for stage in self._stages:
202
+ try:
203
+ text = stage(text)
204
+ except Exception:
205
+ # Never crash on bad input; return what we have so far
206
+ pass
207
+
208
+ # Short-circuit: match_output rules (checked AFTER stages)
209
+ for rule in self._match_rules:
210
+ if rule.matches(text):
211
+ return rule.message
212
+
213
+ if not text.strip() and self.on_empty is not None:
214
+ return self.on_empty
215
+
216
+ return text
217
+
218
+
219
+ # ---------------------------------------------------------------------------
220
+ # Compiler
221
+ # ---------------------------------------------------------------------------
222
+
223
+
224
+ def compile_pipeline(name: str, raw: dict) -> CompiledPipeline:
225
+ """Compile a single pipeline definition dict into a ``CompiledPipeline``.
226
+
227
+ Unknown keys are silently ignored so that schema extensions don't
228
+ break existing definitions.
229
+
230
+ Args:
231
+ name: The pipeline name (used in logs and ``/minimizer`` display).
232
+ raw: A dict of pipeline config keys (the TOML table for the filter).
233
+
234
+ Returns:
235
+ A ready-to-use ``CompiledPipeline``.
236
+
237
+ Raises:
238
+ ValueError: When mutually-exclusive options are set together
239
+ (e.g. ``strip_lines_matching`` + ``keep_lines_matching``,
240
+ or ``head_lines`` + ``tail_lines``).
241
+ """
242
+ p = _get_primitives()
243
+
244
+ # --- Validate mutually-exclusive options --------------------------------
245
+
246
+ if raw.get("strip_lines_matching") and raw.get("keep_lines_matching"):
247
+ raise ValueError(
248
+ f"Pipeline '{name}': strip_lines_matching and keep_lines_matching "
249
+ "are mutually exclusive"
250
+ )
251
+
252
+ # --- Compile match patterns ----------------------------------------------
253
+
254
+ match_cmd = None
255
+ if raw.get("match_command"):
256
+ match_cmd = re.compile(raw["match_command"], re.IGNORECASE)
257
+
258
+ match_sub = None
259
+ if raw.get("match_subcommand"):
260
+ match_sub = re.compile(raw["match_subcommand"], re.IGNORECASE)
261
+
262
+ # --- Compile match-output rules ------------------------------------------
263
+
264
+ match_rules: list[MatchOutputRule] = []
265
+ for entry in raw.get("match_output", []) or []:
266
+ rule = MatchOutputRule(
267
+ pattern=entry["pattern"],
268
+ message=entry["message"],
269
+ unless=entry.get("unless"),
270
+ )
271
+ rule.compile()
272
+ match_rules.append(rule)
273
+
274
+ # --- Build ordered stage list --------------------------------------------
275
+
276
+ stages: list = []
277
+
278
+ # 1. strip_ansi
279
+ if raw.get("strip_ansi"):
280
+ stages.append(p.strip_ansi)
281
+
282
+ # 2. replace
283
+ replace_steps: list[ReplaceStep] = []
284
+ for entry in raw.get("replace", []) or []:
285
+ step = ReplaceStep(pattern=entry["pattern"], replacement=entry["replacement"])
286
+ step.compile()
287
+ replace_steps.append(step)
288
+
289
+ if replace_steps:
290
+
291
+ def _apply_replaces(text: str, _steps=replace_steps) -> str:
292
+ for step in _steps:
293
+ text = step.apply(text)
294
+ return text
295
+
296
+ stages.append(_apply_replaces)
297
+
298
+ # 3. match_output rules are checked in CompiledPipeline.apply(), not here
299
+
300
+ # 4. strip_lines_matching / keep_lines_matching
301
+ if raw.get("strip_lines_matching"):
302
+ patterns = list(raw["strip_lines_matching"])
303
+ stages.append(lambda t, pts=patterns: p.strip_lines_regex(t, pts))
304
+
305
+ if raw.get("keep_lines_matching"):
306
+ patterns = list(raw["keep_lines_matching"])
307
+ stages.append(lambda t, pts=patterns: p.keep_lines_regex(t, pts))
308
+
309
+ # 5. truncate_lines_at
310
+ if raw.get("truncate_lines_at") is not None:
311
+ max_chars = int(raw["truncate_lines_at"])
312
+
313
+ def _truncate_lines(text: str, _max=max_chars) -> str:
314
+ lines = text.splitlines()
315
+ truncated = [p.truncate_line(line, _max) for line in lines]
316
+ return "\n".join(truncated)
317
+
318
+ stages.append(_truncate_lines)
319
+
320
+ # 6. head_lines / tail_lines (or both, which uses head_tail_lines)
321
+ if raw.get("head_lines") is not None and raw.get("tail_lines") is not None:
322
+ head_n = int(raw["head_lines"])
323
+ tail_n = int(raw["tail_lines"])
324
+ stages.append(lambda t, h=head_n, t_n=tail_n: p.head_tail_lines(t, h, t_n))
325
+ elif raw.get("head_lines") is not None:
326
+ n = int(raw["head_lines"])
327
+ stages.append(lambda t, _n=n: p.head_lines_only(t, _n))
328
+ elif raw.get("tail_lines") is not None:
329
+ n = int(raw["tail_lines"])
330
+ stages.append(lambda t, _n=n: p.tail_lines_only(t, _n))
331
+
332
+ # 7. max_lines
333
+ if raw.get("max_lines") is not None:
334
+ n = int(raw["max_lines"])
335
+ stages.append(lambda t, _n=n: p.max_lines(t, _n))
336
+
337
+ # --- Assemble ------------------------------------------------------------
338
+
339
+ compiled = CompiledPipeline(
340
+ name=name,
341
+ match_command=match_cmd,
342
+ match_subcommand=match_sub,
343
+ only_on_exit=raw.get("only_on_exit"),
344
+ except_on_exit=raw.get("except_on_exit"),
345
+ on_empty=raw.get("on_empty"),
346
+ )
347
+ compiled._stages = stages
348
+ compiled._match_rules = match_rules # type: ignore[assignment]
349
+
350
+ return compiled
351
+
352
+
353
+ # ---------------------------------------------------------------------------
354
+ # TOML parser
355
+ # ---------------------------------------------------------------------------
356
+
357
+
358
+ def parse_pipeline_toml(
359
+ contents: str, source_label: str = "<string>"
360
+ ) -> list[CompiledPipeline]:
361
+ """Parse TOML-format pipeline definitions.
362
+
363
+ Expects a TOML document with ``schema_version = 1`` and one or more
364
+ ``[filters.<name>]`` tables. Returns a list of compiled pipelines
365
+ ready to apply.
366
+
367
+ Args:
368
+ contents: Raw TOML text.
369
+ source_label: Describes the source for error messages.
370
+
371
+ Returns:
372
+ List of ``CompiledPipeline`` instances (may be empty).
373
+
374
+ Raises:
375
+ ValueError: On parse errors, schema violations, or invalid pipeline
376
+ config (e.g. mutually-exclusive options).
377
+ """
378
+ import tomllib as toml_module
379
+
380
+ try:
381
+ data = toml_module.loads(contents)
382
+ except Exception as exc:
383
+ raise ValueError(f"TOML parse error in {source_label}: {exc}") from exc
384
+
385
+ schema = data.get("schema_version")
386
+ if schema != 1:
387
+ raise ValueError(f"{source_label}: expected schema_version=1, got {schema!r}")
388
+
389
+ filters = data.get("filters", {})
390
+ if not isinstance(filters, dict):
391
+ raise ValueError(f"{source_label}: [filters] must be a table")
392
+
393
+ compiled_pipelines: list[CompiledPipeline] = []
394
+ errors: list[str] = []
395
+
396
+ for name, raw in filters.items():
397
+ if not isinstance(raw, dict):
398
+ errors.append(f" {name}: value must be a table, got {type(raw).__name__}")
399
+ continue
400
+ try:
401
+ compiled = compile_pipeline(name, raw)
402
+ compiled_pipelines.append(compiled)
403
+ except ValueError as exc:
404
+ errors.append(f" {name}: {exc}")
405
+
406
+ if errors:
407
+ joined = "\n".join(errors)
408
+ raise ValueError(f"Pipeline compilation errors in {source_label}:\n{joined}")
409
+
410
+ return compiled_pipelines
411
+
412
+
413
+ # ---------------------------------------------------------------------------
414
+ # Top-level convenience
415
+ # ---------------------------------------------------------------------------
416
+
417
+
418
+ def apply_pipeline(pipeline: CompiledPipeline, input: str, exit_code: int = 0) -> str:
419
+ """Apply a compiled pipeline to *input* with optional exit-code gating.
420
+
421
+ Thin wrapper around ``CompiledPipeline.apply`` for external callers.
422
+ """
423
+ return pipeline.apply(input, exit_code)
424
+
425
+
426
+ # ---------------------------------------------------------------------------
427
+ # Inline tests (run with ``python -m code_muse.plugins.shell_minimizer.pipeline``)
428
+ # ---------------------------------------------------------------------------
429
+
430
+ if __name__ == "__main__":
431
+ # --- Test compile_pipeline basics ---------------------------------------
432
+
433
+ cp = compile_pipeline(
434
+ "test_basic",
435
+ {
436
+ "strip_ansi": True,
437
+ "truncate_lines_at": 80,
438
+ "head_lines": 5,
439
+ "on_empty": "(nothing)",
440
+ },
441
+ )
442
+ assert cp.name == "test_basic"
443
+ assert cp.on_empty == "(nothing)"
444
+ assert len(cp._stages) == 3 # strip_ansi, truncate, head_lines
445
+
446
+ # Apply to ANSI-laden text
447
+ ansi_input = "\x1b[32mgreen\x1b[0m\n" + "x" * 200
448
+ result = cp.apply(ansi_input)
449
+ assert "green" in result
450
+ assert "…" in result or "more" in result.lower()
451
+ print("✅ compile/apply basic")
452
+
453
+ # --- Test exit-code gating -----------------------------------------------
454
+
455
+ gated = compile_pipeline(
456
+ "gated_test",
457
+ {
458
+ "strip_ansi": True,
459
+ "only_on_exit": [0],
460
+ "on_empty": "(clean exit)",
461
+ },
462
+ )
463
+ assert gated.apply("some output", exit_code=0) == "some output"
464
+ assert gated.apply("some output", exit_code=1) == "some output" # unchanged
465
+ print("✅ exit-code gating")
466
+
467
+ # --- Test match_output short-circuit -------------------------------------
468
+
469
+ short = compile_pipeline(
470
+ "empty_match",
471
+ {
472
+ "match_output": [
473
+ {"pattern": r"^\s*$", "message": "(empty output)"},
474
+ ],
475
+ },
476
+ )
477
+ assert short.apply("\n \n") == "(empty output)"
478
+ assert short.apply("real data") == "real data"
479
+ print("✅ match_output short-circuit")
480
+
481
+ # --- Test mutual-exclusivity errors --------------------------------------
482
+
483
+ try:
484
+ compile_pipeline(
485
+ "bad",
486
+ {"strip_lines_matching": ["x"], "keep_lines_matching": ["y"]},
487
+ )
488
+ raise AssertionError("should have raised")
489
+ except ValueError as e:
490
+ assert "mutually exclusive" in str(e)
491
+ print("✅ mutual-exclusivity check")
492
+
493
+ # --- Test replace steps --------------------------------------------------
494
+
495
+ repl = compile_pipeline(
496
+ "replace_test",
497
+ {
498
+ "replace": [
499
+ {"pattern": r"error:", "replacement": "ERR:"},
500
+ {"pattern": r"\x1b\[[0-9;]*m", "replacement": ""},
501
+ ],
502
+ },
503
+ )
504
+ assert repl.apply("error: something") == "ERR: something"
505
+ assert repl.apply("\x1b[31merror:\x1b[0m fail") == "ERR: fail"
506
+ print("✅ replace steps")
507
+
508
+ # --- Test TOML parsing (inline) ------------------------------------------
509
+
510
+ toml_text = """\
511
+ schema_version = 1
512
+
513
+ [filters.git_diff]
514
+ match_command = "^git$"
515
+ match_subcommand = "^diff$"
516
+ strip_ansi = true
517
+ truncate_lines_at = 160
518
+ head_lines = 40
519
+ tail_lines = 20
520
+
521
+ [[filters.git_diff.match_output]]
522
+ pattern = "^$"
523
+ message = "(empty diff)"
524
+
525
+ [filters.cargo_build]
526
+ match_command = "^cargo$"
527
+ match_subcommand = "^(build|test|clippy)$"
528
+ strip_ansi = true
529
+ # Keep only error/warning/note lines
530
+ keep_lines_matching = ["^error", "^warning", "^note", "^Compiling", "^Finished", "^Running"]
531
+ truncate_lines_at = 120
532
+ head_lines = 30
533
+ """
534
+
535
+ pipelines = parse_pipeline_toml(toml_text, "<inline test>")
536
+ assert len(pipelines) == 2, f"expected 2, got {len(pipelines)}"
537
+
538
+ git_diff = pipelines[0]
539
+ assert git_diff.name == "git_diff"
540
+ assert git_diff.match_command is not None
541
+ assert git_diff.match_subcommand is not None
542
+ # Check it matches "git diff"
543
+ assert git_diff.matches_program("git diff --cached")
544
+ assert not git_diff.matches_program("git push")
545
+ print("✅ TOML parsing & program matching")
546
+
547
+ # --- Test program matching more thoroughly -------------------------------
548
+
549
+ cargo = pipelines[1]
550
+ assert cargo.matches_program("cargo build")
551
+ assert cargo.matches_program("cargo test")
552
+ assert cargo.matches_program("cargo clippy")
553
+ assert not cargo.matches_program("cargo run")
554
+ print("✅ cargo subcommand matching")
555
+
556
+ print("\n🎉 All pipeline tests passed!")