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,563 @@
1
+ """
2
+ Interactive TUI for managing Claude Code hooks.
3
+
4
+ Launch with /hooks to browse, enable/disable, inspect, and delete hooks
5
+ from both global (~/.muse/hooks.json) and project (.claude/settings.json) sources.
6
+
7
+ Built with prompt_toolkit to match the existing skills_menu aesthetic exactly
8
+ (VSplit, FormattedTextControl, Frame).
9
+ """
10
+
11
+ import sys
12
+ import time
13
+
14
+ from prompt_toolkit.application import Application
15
+ from prompt_toolkit.key_binding import KeyBindings
16
+ from prompt_toolkit.layout import Dimension, Layout, VSplit, Window
17
+ from prompt_toolkit.layout.controls import FormattedTextControl
18
+ from prompt_toolkit.widgets import Frame
19
+
20
+ from code_muse.messaging import emit_error
21
+
22
+ from .config import (
23
+ HookEntry,
24
+ _load_global_hooks_config,
25
+ _load_project_hooks_config,
26
+ delete_hook,
27
+ flatten_all_hooks,
28
+ save_global_hooks_config,
29
+ save_hooks_config,
30
+ toggle_hook_enabled,
31
+ )
32
+
33
+ PAGE_SIZE = 12
34
+
35
+ # Colour palette (matches skills_menu palette)
36
+ _C_ENABLED = "fg:ansigreen"
37
+ _C_DISABLED = "fg:ansired"
38
+ _C_SELECTED_BG = "bold"
39
+ _C_DIM = "fg:ansibrightblack"
40
+ _C_CYAN = "fg:ansicyan"
41
+ _C_YELLOW = "fg:ansiyellow"
42
+ _C_MAGENTA = "fg:ansimagenta"
43
+ _C_HEADER = "dim cyan"
44
+ _C_GLOBAL = "fg:ansiblue"
45
+ _C_PROJECT = "fg:ansigreen"
46
+
47
+
48
+ class HooksMenu:
49
+ """Interactive TUI for managing hooks from both global and project sources."""
50
+
51
+ def __init__(self) -> None:
52
+ self.entries: list[HookEntry] = []
53
+ self.selected_idx: int = 0
54
+ self.current_page: int = 0
55
+ self.result: str | None = None
56
+ self.status_message: str = ""
57
+
58
+ # prompt_toolkit controls (set during run())
59
+ self.list_control: FormattedTextControl | None = None
60
+ self.detail_control: FormattedTextControl | None = None
61
+
62
+ self._refresh_data()
63
+
64
+ # ------------------------------------------------------------------
65
+ # Data helpers
66
+ # ------------------------------------------------------------------
67
+
68
+ def _refresh_data(self) -> None:
69
+ """Reload hooks from both global and project sources."""
70
+ try:
71
+ self.entries = flatten_all_hooks()
72
+ # Clamp selection
73
+ if self.entries:
74
+ self.selected_idx = min(self.selected_idx, len(self.entries) - 1)
75
+ else:
76
+ self.selected_idx = 0
77
+ except Exception as exc:
78
+ emit_error(f"Failed to refresh hooks data: {exc}")
79
+ self.entries = []
80
+
81
+ def _current_entry(self) -> HookEntry | None:
82
+ if 0 <= self.selected_idx < len(self.entries):
83
+ return self.entries[self.selected_idx]
84
+ return None
85
+
86
+ def _save_current_entry(
87
+ self, entry: HookEntry, new_enabled: bool | None = None
88
+ ) -> None:
89
+ """Persist changes to the current entry's source file."""
90
+ if entry.source == "global":
91
+ global_config = _load_global_hooks_config()
92
+ if new_enabled is not None:
93
+ global_config = toggle_hook_enabled(
94
+ global_config,
95
+ entry.event_type,
96
+ entry._group_index,
97
+ entry._hook_index,
98
+ new_enabled,
99
+ )
100
+ save_global_hooks_config(global_config)
101
+ else: # project
102
+ project_config = _load_project_hooks_config()
103
+ if new_enabled is not None:
104
+ project_config = toggle_hook_enabled(
105
+ project_config,
106
+ entry.event_type,
107
+ entry._group_index,
108
+ entry._hook_index,
109
+ new_enabled,
110
+ )
111
+ save_hooks_config(project_config)
112
+
113
+ # ------------------------------------------------------------------
114
+ # Actions triggered by key bindings
115
+ # ------------------------------------------------------------------
116
+
117
+ def _toggle_current(self) -> None:
118
+ """Toggle enabled/disabled on the selected hook."""
119
+ entry = self._current_entry()
120
+ if entry is None:
121
+ return
122
+ new_enabled = not entry.enabled
123
+ self._save_current_entry(entry, new_enabled)
124
+ self._refresh_data()
125
+ self.status_message = (
126
+ f"Hook {'enabled' if new_enabled else 'disabled'}: {entry.display_command}"
127
+ )
128
+ self.update_display()
129
+
130
+ def _delete_current(self) -> None:
131
+ """Delete the selected hook (with guard against empty config)."""
132
+ entry = self._current_entry()
133
+ if entry is None:
134
+ return
135
+
136
+ if entry.source == "global":
137
+ global_config = _load_global_hooks_config()
138
+ global_config = delete_hook(
139
+ global_config,
140
+ entry.event_type,
141
+ entry._group_index,
142
+ entry._hook_index,
143
+ )
144
+ save_global_hooks_config(global_config)
145
+ else: # project
146
+ project_config = _load_project_hooks_config()
147
+ project_config = delete_hook(
148
+ project_config,
149
+ entry.event_type,
150
+ entry._group_index,
151
+ entry._hook_index,
152
+ )
153
+ save_hooks_config(project_config)
154
+
155
+ self._refresh_data()
156
+ self.status_message = f"Deleted hook: {entry.display_command}"
157
+ self.update_display()
158
+
159
+ def _enable_all(self) -> None:
160
+ """Enable every hook in both project and global configs."""
161
+ import copy
162
+
163
+ # Enable all project hooks
164
+ project_config = _load_project_hooks_config()
165
+ project_cfg = copy.deepcopy(project_config)
166
+ for groups in project_cfg.values():
167
+ if not isinstance(groups, list):
168
+ continue
169
+ for group in groups:
170
+ for hook in group.get("hooks", []):
171
+ hook["enabled"] = True
172
+ save_hooks_config(project_cfg)
173
+
174
+ # Enable all global hooks
175
+ global_config = _load_global_hooks_config()
176
+ global_cfg = copy.deepcopy(global_config)
177
+ for groups in global_cfg.values():
178
+ if not isinstance(groups, list):
179
+ continue
180
+ for group in groups:
181
+ for hook in group.get("hooks", []):
182
+ hook["enabled"] = True
183
+ save_global_hooks_config(global_cfg)
184
+
185
+ self._refresh_data()
186
+ self.status_message = "All hooks enabled."
187
+ self.update_display()
188
+
189
+ def _disable_all(self) -> None:
190
+ """Disable every hook in both project and global configs."""
191
+ import copy
192
+
193
+ # Disable all project hooks
194
+ project_config = _load_project_hooks_config()
195
+ project_cfg = copy.deepcopy(project_config)
196
+ for groups in project_cfg.values():
197
+ if not isinstance(groups, list):
198
+ continue
199
+ for group in groups:
200
+ for hook in group.get("hooks", []):
201
+ hook["enabled"] = False
202
+ save_hooks_config(project_cfg)
203
+
204
+ # Disable all global hooks
205
+ global_config = _load_global_hooks_config()
206
+ global_cfg = copy.deepcopy(global_config)
207
+ for groups in global_cfg.values():
208
+ if not isinstance(groups, list):
209
+ continue
210
+ for group in groups:
211
+ for hook in group.get("hooks", []):
212
+ hook["enabled"] = False
213
+ save_global_hooks_config(global_cfg)
214
+
215
+ self._refresh_data()
216
+ self.status_message = "All hooks disabled."
217
+ self.update_display()
218
+
219
+ # ------------------------------------------------------------------
220
+ # Rendering helpers
221
+ # ------------------------------------------------------------------
222
+
223
+ def _render_list(self) -> list:
224
+ """Render the left-hand hooks list panel."""
225
+ lines: list = []
226
+
227
+ total = len(self.entries)
228
+ enabled_count = sum(1 for e in self.entries if e.enabled)
229
+ project_count = sum(1 for e in self.entries if e.source == "project")
230
+ global_count = sum(1 for e in self.entries if e.source == "global")
231
+
232
+ header_color = _C_ENABLED if enabled_count > 0 else _C_DISABLED
233
+ lines.append((header_color, f" Hooks: {enabled_count}/{total} enabled"))
234
+ lines.append(("", f" ({project_count} project, {global_count} global)\n\n"))
235
+
236
+ if not self.entries:
237
+ lines.append((_C_YELLOW, " No hooks configured."))
238
+ lines.append(("", "\n"))
239
+ lines.append((_C_DIM, " Add hooks to .claude/settings.json (project)"))
240
+ lines.append(("", "\n"))
241
+ lines.append((_C_DIM, " or ~/.muse/hooks.json (global)"))
242
+ lines.append(("", "\n\n"))
243
+ self._render_nav_hints(lines)
244
+ return lines
245
+
246
+ total_pages = max(1, (total + PAGE_SIZE - 1) // PAGE_SIZE)
247
+ start = self.current_page * PAGE_SIZE
248
+ end = min(start + PAGE_SIZE, total)
249
+ for i in range(start, end):
250
+ entry = self.entries[i]
251
+ is_selected = i == self.selected_idx
252
+ status_icon = "✓" if entry.enabled else "✗"
253
+ status_style = _C_ENABLED if entry.enabled else _C_DISABLED
254
+ source_indicator = "🌍" if entry.source == "global" else "📁"
255
+ prefix = " > " if is_selected else " "
256
+
257
+ if is_selected:
258
+ lines.append((_C_SELECTED_BG, prefix))
259
+ lines.append((status_style + " bold", status_icon))
260
+ lines.append(
261
+ (_C_SELECTED_BG, f" {source_indicator} [{entry.event_type}]")
262
+ )
263
+ lines.append((_C_SELECTED_BG, f" {entry.display_matcher}"))
264
+ else:
265
+ lines.append(("", prefix))
266
+ lines.append((status_style, status_icon))
267
+ source_color = _C_GLOBAL if entry.source == "global" else _C_PROJECT
268
+ lines.append((source_color, f" {source_indicator}"))
269
+ lines.append((_C_DIM, f" [{entry.event_type}]"))
270
+ lines.append(("", f" {entry.display_matcher}"))
271
+ lines.append(("", "\n"))
272
+
273
+ lines.append(("", "\n"))
274
+ lines.append((_C_DIM, f" Page {self.current_page + 1}/{total_pages}"))
275
+ lines.append(("", "\n"))
276
+
277
+ # Status message (shows result of last action)
278
+ if self.status_message:
279
+ lines.append(("", "\n"))
280
+ lines.append((_C_CYAN, f" {self.status_message}"))
281
+ lines.append(("", "\n"))
282
+
283
+ self._render_nav_hints(lines)
284
+ return lines
285
+
286
+ def _render_nav_hints(self, lines: list) -> None:
287
+ """Append keyboard shortcut hints to lines."""
288
+ lines.append(("", "\n"))
289
+ lines.append((_C_DIM, " ↑/↓ j/k "))
290
+ lines.append(("", "Navigate\n"))
291
+ lines.append((_C_ENABLED, " Enter "))
292
+ lines.append(("", "Toggle enable/disable\n"))
293
+ lines.append((_C_DISABLED, " d "))
294
+ lines.append(("", "Delete hook\n"))
295
+ lines.append((_C_YELLOW, " A "))
296
+ lines.append(("", "Enable all\n"))
297
+ lines.append((_C_MAGENTA, " D "))
298
+ lines.append(("", "Disable all\n"))
299
+ lines.append((_C_YELLOW, " r "))
300
+ lines.append(("", "Refresh\n"))
301
+ lines.append((_C_DISABLED, " q/Esc "))
302
+ lines.append(("", "Exit"))
303
+
304
+ def _render_detail(self) -> list:
305
+ """Render the right-hand hook detail panel."""
306
+ lines: list = []
307
+ lines.append((_C_HEADER, " HOOK DETAILS"))
308
+ lines.append(("", "\n\n"))
309
+
310
+ entry = self._current_entry()
311
+ if entry is None:
312
+ lines.append((_C_YELLOW, " No hook selected."))
313
+ lines.append(("", "\n\n"))
314
+ lines.append((_C_DIM, " Select a hook from the list"))
315
+ lines.append(("", "\n"))
316
+ lines.append((_C_DIM, " to view its details."))
317
+ return lines
318
+
319
+ # Status badge
320
+ status_text = "Enabled" if entry.enabled else "Disabled"
321
+ status_style = _C_ENABLED + " bold" if entry.enabled else _C_DISABLED + " bold"
322
+ lines.append(("bold", " Status: "))
323
+ lines.append((status_style, status_text))
324
+ lines.append(("", "\n\n"))
325
+
326
+ # Source indicator
327
+ source_label = (
328
+ "Global (~/.muse/hooks.json)"
329
+ if entry.source == "global"
330
+ else "Project (.claude/settings.json)"
331
+ )
332
+ source_color = _C_GLOBAL if entry.source == "global" else _C_PROJECT
333
+ lines.append(("bold", " Source: "))
334
+ lines.append((source_color, source_label))
335
+ lines.append(("", "\n\n"))
336
+
337
+ # Event type
338
+ lines.append(("bold", " Event: "))
339
+ lines.append((_C_CYAN, entry.event_type))
340
+ lines.append(("", "\n\n"))
341
+
342
+ # Matcher
343
+ lines.append(("bold", " Matcher: "))
344
+ lines.append(("", "\n"))
345
+ for chunk in _wrap(entry.matcher, 50):
346
+ lines.append((_C_YELLOW, f" {chunk}"))
347
+ lines.append(("", "\n"))
348
+ lines.append(("", "\n"))
349
+
350
+ # Type
351
+ lines.append(("bold", " Type: "))
352
+ lines.append((_C_DIM, entry.hook_type))
353
+ lines.append(("", "\n\n"))
354
+
355
+ # Command / prompt
356
+ label = "Command:" if entry.hook_type == "command" else "Prompt: "
357
+ lines.append(("bold", f" {label}"))
358
+ lines.append(("", "\n"))
359
+ for chunk in _wrap(entry.command, 50):
360
+ lines.append((_C_DIM, f" {chunk}"))
361
+ lines.append(("", "\n"))
362
+ lines.append(("", "\n"))
363
+
364
+ # Timeout
365
+ lines.append(("bold", " Timeout: "))
366
+ lines.append((_C_DIM, f"{entry.timeout} ms"))
367
+ lines.append(("", "\n\n"))
368
+
369
+ # Hook ID
370
+ if entry.hook_id:
371
+ lines.append(("bold", " ID: "))
372
+ lines.append((_C_DIM, entry.hook_id))
373
+ lines.append(("", "\n\n"))
374
+
375
+ # Config location hint
376
+ lines.append((_C_DIM, f" Stored in {source_label}"))
377
+ lines.append(("", "\n"))
378
+ lines.append(
379
+ (_C_DIM, f" group #{entry._group_index} hook #{entry._hook_index}")
380
+ )
381
+ lines.append(("", "\n"))
382
+
383
+ return lines
384
+
385
+ def update_display(self) -> None:
386
+ """Push freshly rendered text into the prompt_toolkit controls."""
387
+ if self.list_control:
388
+ self.list_control.text = self._render_list()
389
+ if self.detail_control:
390
+ self.detail_control.text = self._render_detail()
391
+
392
+ # ------------------------------------------------------------------
393
+ # Main entry point
394
+ # ------------------------------------------------------------------
395
+
396
+ def run(self) -> str | None:
397
+ """Launch the interactive TUI. Returns the exit reason string."""
398
+ self.result = None
399
+
400
+ self.list_control = FormattedTextControl(text="")
401
+ self.detail_control = FormattedTextControl(text="")
402
+
403
+ list_window = Window(
404
+ content=self.list_control, wrap_lines=True, width=Dimension(weight=40)
405
+ )
406
+ detail_window = Window(
407
+ content=self.detail_control, wrap_lines=True, width=Dimension(weight=60)
408
+ )
409
+
410
+ list_frame = Frame(list_window, width=Dimension(weight=40), title="Hooks")
411
+ detail_frame = Frame(detail_window, width=Dimension(weight=60), title="Details")
412
+
413
+ root_container = VSplit([list_frame, detail_frame])
414
+ kb = KeyBindings()
415
+
416
+ # --- Navigation ---
417
+ @kb.add("up")
418
+ @kb.add("c-p")
419
+ @kb.add("k")
420
+ def _move_up(event):
421
+ if self.selected_idx > 0:
422
+ self.selected_idx -= 1
423
+ self.current_page = self.selected_idx // PAGE_SIZE
424
+ self.update_display()
425
+
426
+ @kb.add("down")
427
+ @kb.add("c-n")
428
+ @kb.add("j")
429
+ def _move_down(event):
430
+ if self.selected_idx < len(self.entries) - 1:
431
+ self.selected_idx += 1
432
+ self.current_page = self.selected_idx // PAGE_SIZE
433
+ self.update_display()
434
+
435
+ @kb.add("left")
436
+ def _prev_page(event):
437
+ if self.current_page > 0:
438
+ self.current_page -= 1
439
+ self.selected_idx = self.current_page * PAGE_SIZE
440
+ self.update_display()
441
+
442
+ @kb.add("right")
443
+ def _next_page(event):
444
+ total_pages = max(1, (len(self.entries) + PAGE_SIZE - 1) // PAGE_SIZE)
445
+ if self.current_page < total_pages - 1:
446
+ self.current_page += 1
447
+ self.selected_idx = self.current_page * PAGE_SIZE
448
+ self.update_display()
449
+
450
+ # --- Actions ---
451
+ @kb.add("enter")
452
+ def _toggle(event):
453
+ self._toggle_current()
454
+ self.result = "changed"
455
+
456
+ @kb.add("d")
457
+ def _delete(event):
458
+ self._delete_current()
459
+ self.result = "changed"
460
+
461
+ @kb.add("A") # capital A = enable ALL
462
+ def _enable_all(event):
463
+ self._enable_all()
464
+ self.result = "changed"
465
+
466
+ @kb.add("D") # capital D = disable ALL
467
+ def _disable_all(event):
468
+ self._disable_all()
469
+ self.result = "changed"
470
+
471
+ @kb.add("r")
472
+ def _refresh(event):
473
+ self._refresh_data()
474
+ self.status_message = "Refreshed."
475
+ self.update_display()
476
+
477
+ # --- Exit ---
478
+ @kb.add("q")
479
+ @kb.add("escape")
480
+ def _quit(event):
481
+ self.result = "quit"
482
+ event.app.exit()
483
+
484
+ @kb.add("c-c")
485
+ def _quit_ctrl_c(event):
486
+ self.result = "quit"
487
+ event.app.exit()
488
+
489
+ layout = Layout(root_container)
490
+ app = Application(
491
+ layout=layout,
492
+ key_bindings=kb,
493
+ full_screen=False,
494
+ mouse_support=False,
495
+ )
496
+
497
+ try:
498
+ from code_muse.tools.command_runner import set_awaiting_user_input
499
+
500
+ set_awaiting_user_input(True)
501
+ except Exception:
502
+ pass
503
+
504
+ # Enter alternate screen buffer
505
+ sys.stdout.write("\033[?1049h")
506
+ sys.stdout.write("\033[2J\033[H")
507
+ sys.stdout.flush()
508
+ time.sleep(0.05)
509
+
510
+ try:
511
+ self.update_display()
512
+ sys.stdout.write("\033[2J\033[H")
513
+ sys.stdout.flush()
514
+ app.run(in_thread=True)
515
+ finally:
516
+ sys.stdout.write("\033[?1049l")
517
+ sys.stdout.flush()
518
+ try:
519
+ import termios
520
+
521
+ termios.tcflush(sys.stdin.fileno(), termios.TCIFLUSH)
522
+ except Exception:
523
+ pass # ImportError on Windows, termios.error, or not a tty
524
+ time.sleep(0.1)
525
+ try:
526
+ from code_muse.tools.command_runner import set_awaiting_user_input
527
+
528
+ set_awaiting_user_input(False)
529
+ except Exception:
530
+ pass
531
+
532
+ return self.result
533
+
534
+
535
+ # ---------------------------------------------------------------------------
536
+ # Helpers
537
+ # ---------------------------------------------------------------------------
538
+
539
+
540
+ def _wrap(text: str, width: int) -> list[str]:
541
+ """Wrap text to *width* characters, splitting on whitespace."""
542
+ words = text.split()
543
+ lines: list[str] = []
544
+ current: list[str] = []
545
+ length = 0
546
+ for word in words:
547
+ if length + len(word) + (1 if current else 0) <= width:
548
+ current.append(word)
549
+ length += len(word) + (1 if len(current) > 1 else 0)
550
+ else:
551
+ if current:
552
+ lines.append(" ".join(current))
553
+ current = [word]
554
+ length = len(word)
555
+ if current:
556
+ lines.append(" ".join(current))
557
+ return lines or [""]
558
+
559
+
560
+ def show_hooks_menu() -> None:
561
+ """Public entry point called from register_callbacks.py."""
562
+ menu = HooksMenu()
563
+ menu.run()