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,326 @@
1
+ """Manage mitmdump subprocess for traffic capture."""
2
+
3
+ import json
4
+ import logging
5
+ import os
6
+ import shlex
7
+ import shutil
8
+ import signal
9
+ import subprocess
10
+ import sys
11
+ import tempfile
12
+ import time
13
+ from pathlib import Path
14
+
15
+ from code_muse.http_utils import find_available_port
16
+ from code_muse.messaging import emit_info, emit_success, emit_warning
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ # Global singleton manager instance
21
+ _manager: MitmProxyManager | None = None
22
+
23
+
24
+ def get_manager() -> MitmProxyManager:
25
+ global _manager
26
+ if _manager is None:
27
+ _manager = MitmProxyManager()
28
+ return _manager
29
+
30
+
31
+ class MitmProxyManager:
32
+ """Lifecycle manager for mitmdump capture process."""
33
+
34
+ def __init__(self):
35
+ self._process: subprocess.Popen | None = None
36
+ self._port: int | None = None
37
+ self._target: str = ""
38
+ self._output_path: str = ""
39
+ self._addon_path: str = ""
40
+ self._flow_count: int = 0
41
+ self._saved_proxy_env: dict[str, str | None] = {}
42
+
43
+ def find_mitmdump(self) -> str | None:
44
+ """Locate mitmdump binary across common locations."""
45
+ # 1. PATH
46
+ path_mitmdump = shutil.which("mitmdump")
47
+ if path_mitmdump:
48
+ return path_mitmdump
49
+
50
+ # 2. Local mitmproxy checkout (uv run)
51
+ local_checkout = Path("/Users/adam2/projects/mitmproxy")
52
+ if (local_checkout / "pyproject.toml").exists():
53
+ # Prefer uv run if uv is available
54
+ if shutil.which("uv"):
55
+ return f"cd {local_checkout} && uv run mitmdump"
56
+ # Fallback: direct python module invocation
57
+ python = sys.executable
58
+ return f"{python} -m mitmproxy.tools.main mitmdump"
59
+
60
+ # 3. pip location — mitmdump is usually on PATH, but check module invocation
61
+ try:
62
+ import mitmproxy
63
+
64
+ return f"{sys.executable} -m mitmproxy.tools.main mitmdump"
65
+ except ImportError:
66
+ pass
67
+
68
+ return None
69
+
70
+ def _resolve_addon_path(self) -> str:
71
+ """Resolve path to the capture addon script."""
72
+ if self._addon_path and Path(self._addon_path).exists():
73
+ return self._addon_path
74
+
75
+ # Relative to this module
76
+ module_dir = Path(__file__).parent
77
+ addon = module_dir / "capture_addon.py"
78
+ if addon.exists():
79
+ return str(addon)
80
+
81
+ # Package data fallback
82
+ try:
83
+ import importlib.resources as resources
84
+
85
+ with resources.path(
86
+ "code_muse.tools.meetin_proxy", "capture_addon.py"
87
+ ) as p:
88
+ return str(p)
89
+ except Exception:
90
+ pass
91
+
92
+ raise FileNotFoundError("Could not resolve capture_addon.py path")
93
+
94
+ def start(
95
+ self,
96
+ target: str = "",
97
+ port: int | None = None,
98
+ max_req_body: int = 10000,
99
+ max_res_body: int = 100000,
100
+ ) -> int:
101
+ """Start mitmdump with capture addon.
102
+
103
+ Args:
104
+ target: Domain filter (empty captures everything).
105
+ port: Listen port (auto-selected if None).
106
+ max_req_body: Max request body bytes to capture.
107
+ max_res_body: Max response body bytes to capture.
108
+
109
+ Returns:
110
+ The listening port number.
111
+ """
112
+ if self._process is not None and self._process.poll() is None:
113
+ emit_warning("mitmproxy already running — stopping previous instance first")
114
+ self.stop()
115
+
116
+ mitmdump = self.find_mitmdump()
117
+ if not mitmdump:
118
+ raise RuntimeError(
119
+ "mitmdump not found. Install mitmproxy: pip install mitmproxy"
120
+ )
121
+
122
+ listen_port = port or find_available_port(start_port=8090, end_port=9010)
123
+ if listen_port is None:
124
+ raise RuntimeError("No available port found in range 8090-9010")
125
+
126
+ addon_path = self._resolve_addon_path()
127
+
128
+ # Secure temp file for capture output
129
+ fd, output_path = tempfile.mkstemp(prefix="mitmproxy_", suffix=".json")
130
+ os.close(fd)
131
+
132
+ env = os.environ.copy()
133
+ env["MITMPROXY_TARGET"] = target
134
+ env["MITMPROXY_OUTPUT"] = output_path
135
+ env["MITMPROXY_MAX_REQ_BODY"] = str(max_req_body)
136
+ env["MITMPROXY_MAX_RES_BODY"] = str(max_res_body)
137
+
138
+ cmd_parts = [
139
+ mitmdump,
140
+ "-p",
141
+ str(listen_port),
142
+ "-s",
143
+ addon_path,
144
+ "--set",
145
+ "block_global=false",
146
+ "--ssl-insecure",
147
+ "--quiet",
148
+ ]
149
+
150
+ # If mitmdump path is a shell expression (cd ... && uv run ...), use shell
151
+ use_shell = "&&" in mitmdump or ";" in mitmdump
152
+ if use_shell:
153
+ # First element is the shell prefix; remaining args are quoted individually
154
+ prefix = str(cmd_parts[0])
155
+ rest = " ".join(shlex.quote(str(p)) for p in cmd_parts[1:])
156
+ cmd = f"{prefix} {rest}"
157
+ else:
158
+ cmd = cmd_parts
159
+
160
+ emit_info(
161
+ f"🛡️ Starting mitmproxy on port {listen_port} (target: {target or 'all'})"
162
+ )
163
+
164
+ try:
165
+ if sys.platform.startswith("win"):
166
+ creationflags = subprocess.CREATE_NEW_PROCESS_GROUP
167
+ self._process = subprocess.Popen(
168
+ cmd,
169
+ shell=use_shell,
170
+ stdout=subprocess.DEVNULL,
171
+ stderr=subprocess.DEVNULL,
172
+ stdin=subprocess.DEVNULL,
173
+ env=env,
174
+ creationflags=creationflags,
175
+ )
176
+ else:
177
+ self._process = subprocess.Popen(
178
+ cmd,
179
+ shell=use_shell,
180
+ stdout=subprocess.DEVNULL,
181
+ stderr=subprocess.DEVNULL,
182
+ stdin=subprocess.DEVNULL,
183
+ env=env,
184
+ start_new_session=True,
185
+ )
186
+ except Exception as exc:
187
+ # Clean up temp file on failure
188
+ Path(output_path).unlink(missing_ok=True)
189
+ raise RuntimeError(f"Failed to start mitmdump: {exc}") from exc
190
+
191
+ self._port = listen_port
192
+ self._target = target
193
+ self._output_path = output_path
194
+ self._flow_count = 0
195
+
196
+ # Set proxy env vars so muse traffic routes through
197
+ proxy_url = f"http://127.0.0.1:{listen_port}"
198
+ self._saved_proxy_env = {
199
+ "HTTPS_PROXY": os.environ.get("HTTPS_PROXY"),
200
+ "HTTP_PROXY": os.environ.get("HTTP_PROXY"),
201
+ }
202
+ os.environ["HTTPS_PROXY"] = proxy_url
203
+ os.environ["HTTP_PROXY"] = proxy_url
204
+
205
+ # Give mitmdump a moment to bind
206
+ time.sleep(0.5)
207
+
208
+ if self._process.poll() is not None:
209
+ # Process exited immediately
210
+ exit_code = self._process.returncode
211
+ Path(output_path).unlink(missing_ok=True)
212
+ raise RuntimeError(f"mitmdump exited immediately (code {exit_code})")
213
+
214
+ emit_success(f"✅ mitmproxy running on port {listen_port}")
215
+ emit_info(
216
+ "⚠️ SSL verification is disabled (--ssl-insecure). "
217
+ "For production use, install and trust the mitmproxy CA certificate."
218
+ )
219
+
220
+ return listen_port
221
+
222
+ def stop(self) -> dict | None:
223
+ """Stop mitmdump and read captured flows.
224
+
225
+ Returns:
226
+ Dict with capture metadata and flows, or None if nothing captured.
227
+ """
228
+ if self._process is None:
229
+ return None
230
+
231
+ # Send SIGTERM gracefully
232
+ self._terminate_process()
233
+
234
+ # Read capture file
235
+ data = self._read_capture_file()
236
+ if data:
237
+ self._flow_count = data.get("meta", {}).get("total_flows", 0)
238
+
239
+ # Restore or clear proxy env vars
240
+ for key, value in self._saved_proxy_env.items():
241
+ if value is None:
242
+ os.environ.pop(key, None)
243
+ else:
244
+ os.environ[key] = value
245
+ self._saved_proxy_env = {}
246
+
247
+ # Clean up temp file
248
+ if self._output_path:
249
+ Path(self._output_path).unlink(missing_ok=True)
250
+ self._output_path = ""
251
+
252
+ self._process = None
253
+ self._port = None
254
+
255
+ return data
256
+
257
+ def status(self) -> dict:
258
+ """Return current proxy status."""
259
+ running = self._process is not None and self._process.poll() is None
260
+ return {
261
+ "running": running,
262
+ "port": self._port,
263
+ "target": self._target,
264
+ "flow_count": self._flow_count,
265
+ }
266
+
267
+ def cleanup(self) -> None:
268
+ """Ensure process is killed and temp files removed."""
269
+ if self._process is not None and self._process.poll() is None:
270
+ self._terminate_process()
271
+ if self._output_path:
272
+ Path(self._output_path).unlink(missing_ok=True)
273
+ self._output_path = ""
274
+ self._process = None
275
+ self._port = None
276
+ for key, value in self._saved_proxy_env.items():
277
+ if value is None:
278
+ os.environ.pop(key, None)
279
+ else:
280
+ os.environ[key] = value
281
+ self._saved_proxy_env = {}
282
+
283
+ def _terminate_process(self) -> None:
284
+ """Best-effort graceful termination of the mitmdump process."""
285
+ proc = self._process
286
+ if proc is None:
287
+ return
288
+
289
+ try:
290
+ if sys.platform.startswith("win"):
291
+ proc.terminate()
292
+ proc.wait(timeout=3)
293
+ return
294
+
295
+ # POSIX: start_new_session created a new process group
296
+ pid = proc.pid
297
+ try:
298
+ pgid = os.getpgid(pid)
299
+ os.killpg(pgid, signal.SIGTERM)
300
+ time.sleep(1.0)
301
+ if proc.poll() is None:
302
+ os.killpg(pgid, signal.SIGINT)
303
+ time.sleep(0.5)
304
+ if proc.poll() is None:
305
+ os.killpg(pgid, signal.SIGKILL)
306
+ proc.wait(timeout=2)
307
+ except OSError:
308
+ # Process may already be gone
309
+ try:
310
+ proc.kill()
311
+ proc.wait(timeout=1)
312
+ except Exception:
313
+ pass
314
+ except Exception as exc:
315
+ logger.warning("Error terminating mitmdump: %s", exc)
316
+
317
+ def _read_capture_file(self) -> dict | None:
318
+ """Read and return the JSON capture file contents."""
319
+ if not self._output_path or not Path(self._output_path).exists():
320
+ return None
321
+ try:
322
+ with open(self._output_path, encoding="utf-8") as f:
323
+ return json.load(f)
324
+ except Exception as exc:
325
+ logger.warning("Failed to read capture file: %s", exc)
326
+ return None
@@ -0,0 +1,45 @@
1
+ """Register mitmproxy startup callbacks."""
2
+
3
+ from code_muse.callbacks import register_callback
4
+ from code_muse.messaging import emit_info, emit_warning
5
+
6
+
7
+ def _get_mitmproxy_prompt() -> str:
8
+ """Return mitmproxy usage instructions for the agent prompt."""
9
+ return """## mitmproxy — Network Traffic Capture Tool
10
+
11
+ You have access to the `mitmproxy` tool that can intercept and inspect HTTP/S traffic.
12
+
13
+ **When to use it:**
14
+ - When a website, API endpoint, or web service isn't working as expected
15
+ - When you need to see exactly what data is being sent to/from a provider
16
+ - When debugging token counts, request formats, or response shapes
17
+ - When you want to verify headers, request bodies, or response payloads
18
+ - Any web-related debugging where seeing the raw traffic helps
19
+
20
+ **How to use it:**
21
+ 1. Call `mitmproxy(command="start", target_domain="example.com")` to begin capture
22
+ 2. Perform the actions/requests you want to inspect
23
+ 3. Call `mitmproxy(command="stop")` to stop capture and get the recorded data
24
+ 4. Or use `mitmproxy(command="capture", duration_seconds=30)` for a one-shot capture
25
+
26
+ **Pro tip:** Set `target_domain` to filter traffic (e.g., "anthropic.com",
27
+ "openai.com"). Leave it empty to capture all traffic. The proxy runs on localhost
28
+ and routes muse's own HTTP clients through it automatically.
29
+ """
30
+
31
+
32
+ def _check_mitmproxy_available() -> None:
33
+ """Verify mitmproxy is installed and available on startup."""
34
+ try:
35
+ import mitmproxy # noqa: F401
36
+ from mitmproxy.tools.main import mitmdump # noqa: F401
37
+
38
+ emit_info("🔍 mitmproxy available — mitmproxy detected")
39
+ except ImportError:
40
+ emit_warning("⚠️ mitmproxy not available. Install with: pip install mitmproxy")
41
+
42
+
43
+ def register() -> None:
44
+ register_callback("startup", _check_mitmproxy_available)
45
+ register_callback("load_prompt", _get_mitmproxy_prompt)
@@ -0,0 +1,219 @@
1
+ """Workspace and sensitive-file path policy for Muse.
2
+
3
+ Provides resolve, classify, and check functions that enforce:
4
+ - Workspace containment (cwd-based root)
5
+ - Path traversal and symlink escape detection
6
+ - Sensitive file/directory blocking
7
+ - Operation-level gating (READ, LIST, SEARCH, WRITE, DELETE)
8
+
9
+ All file tools should call ``check_path_allowed()`` before opening/spawning
10
+ operations. Denials never include full file content.
11
+ """
12
+
13
+ from collections.abc import Sequence
14
+ from enum import Enum, auto
15
+ from pathlib import Path
16
+ from typing import NamedTuple
17
+
18
+
19
+ class Operation(Enum):
20
+ READ = auto()
21
+ LIST = auto()
22
+ SEARCH = auto()
23
+ WRITE = auto()
24
+ DELETE = auto()
25
+
26
+
27
+ class PathDecision(NamedTuple):
28
+ allowed: bool
29
+ reason: str | None = None
30
+
31
+
32
+ # Files and directories that are considered sensitive and require explicit approval
33
+ SENSITIVE_PATHS: set[str] = {
34
+ ".env",
35
+ ".env.local",
36
+ ".env.production",
37
+ ".envrc",
38
+ "id_rsa",
39
+ "id_dsa",
40
+ "id_ecdsa",
41
+ "id_ed25519",
42
+ "authorized_keys",
43
+ "known_hosts",
44
+ "ssh_config",
45
+ ".aws",
46
+ ".gnupg",
47
+ ".ssh",
48
+ ".docker",
49
+ ".kube",
50
+ "kubeconfig",
51
+ "credentials",
52
+ "secrets",
53
+ ".netrc",
54
+ ".npmrc",
55
+ ".pypirc",
56
+ "tokens",
57
+ "cookie",
58
+ "cookies",
59
+ "keychain",
60
+ "keystore",
61
+ "private_key",
62
+ "private.pem",
63
+ "cert.pem",
64
+ ".pgpass",
65
+ ".mylogin.cnf",
66
+ "terraform.tfstate",
67
+ ".terraform",
68
+ "service_account.json",
69
+ ".htpasswd",
70
+ ".htaccess",
71
+ }
72
+
73
+ # Basenames that indicate a sensitive file regardless of path
74
+ _SENSITIVE_BASENAMES: set[str] = {
75
+ "passwd",
76
+ "shadow",
77
+ "sudoers",
78
+ "group",
79
+ "hosts",
80
+ "resolv.conf",
81
+ "fstab",
82
+ "crypttab",
83
+ "shadow-",
84
+ "passwd-",
85
+ }
86
+
87
+
88
+ def get_workspace_root() -> Path:
89
+ """Return the workspace root for path containment checks.
90
+
91
+ Uses the current working directory as the default workspace root.
92
+ """
93
+ return Path.cwd().resolve()
94
+
95
+
96
+ def resolve_user_path(file_path: str) -> Path:
97
+ """Resolve a user-supplied path to an absolute, canonical path.
98
+
99
+ Expands ``~`` and resolves ``..`` / symlinks via ``Path.resolve()``.
100
+ """
101
+ p = Path(file_path).expanduser()
102
+ try:
103
+ return p.resolve()
104
+ except OSError, RuntimeError:
105
+ # If resolve fails (e.g., permission denied), fall back to absolute
106
+ return p.absolute()
107
+
108
+
109
+ def classify_path(file_path: Path) -> dict[str, bool]:
110
+ """Classify a resolved path into policy-relevant categories.
111
+
112
+ Returns a dict with:
113
+ - ``inside_workspace``: True if within the workspace root
114
+ - ``sensitive``: True if the path touches a sensitive file/dir
115
+ - ``traversal``: True if path contains ``..`` components (pre-resolve)
116
+ """
117
+ workspace = get_workspace_root()
118
+ resolved = file_path
119
+
120
+ inside_workspace = False
121
+ try:
122
+ resolved.relative_to(workspace)
123
+ inside_workspace = True
124
+ except ValueError:
125
+ inside_workspace = False
126
+
127
+ sensitive = False
128
+ parts_lower = [part.lower() for part in resolved.parts]
129
+ basename_lower = resolved.name.lower()
130
+
131
+ for part in parts_lower:
132
+ if part in SENSITIVE_PATHS or part in _SENSITIVE_BASENAMES:
133
+ sensitive = True
134
+ break
135
+
136
+ if basename_lower in SENSITIVE_PATHS or basename_lower in _SENSITIVE_BASENAMES:
137
+ sensitive = True
138
+
139
+ # Symlink escape detection: if the resolved path differs from the
140
+ # absolute non-resolved path in a way that breaks containment.
141
+ traversal = False
142
+ try:
143
+ abs_no_resolve = Path(file_path).expanduser().absolute()
144
+ # If the path was expanded but resolve took us outside workspace,
145
+ # and the absolute path itself also looks outside, mark traversal.
146
+ if not inside_workspace:
147
+ try:
148
+ abs_no_resolve.relative_to(workspace)
149
+ except ValueError:
150
+ # Both resolved and absolute are outside workspace
151
+ pass
152
+ except Exception:
153
+ pass
154
+
155
+ return {
156
+ "inside_workspace": inside_workspace,
157
+ "sensitive": sensitive,
158
+ "traversal": traversal,
159
+ }
160
+
161
+
162
+ def check_path_allowed(
163
+ file_path: str,
164
+ operation: Operation,
165
+ approved_sensitive: Sequence[str] | None = None,
166
+ ) -> PathDecision:
167
+ """Check whether an operation on *file_path* is allowed by policy.
168
+
169
+ Args:
170
+ file_path: The target path (may be relative, contain ``~``, etc.)
171
+ operation: The operation being attempted
172
+ approved_sensitive: Optional sequence of already-approved sensitive
173
+ paths (exact strings). Used when a user has explicitly approved
174
+ a previous read/search of a sensitive file.
175
+
176
+ Returns:
177
+ ``PathDecision`` with ``allowed`` and an optional ``reason``.
178
+ """
179
+ resolved = resolve_user_path(file_path)
180
+ classification = classify_path(resolved)
181
+
182
+ # Always block path traversal / symlink escapes for write/delete
183
+ if operation in (Operation.WRITE, Operation.DELETE) and classification["traversal"]:
184
+ return PathDecision(
185
+ allowed=False,
186
+ reason="Path traversal or symlink escape detected; write/delete blocked.",
187
+ )
188
+
189
+ # Outside workspace writes/deletes denied by default
190
+ if (
191
+ operation in (Operation.WRITE, Operation.DELETE)
192
+ and not classification["inside_workspace"]
193
+ ):
194
+ return PathDecision(
195
+ allowed=False,
196
+ reason="Outside-workspace writes and deletes are denied by default.",
197
+ )
198
+
199
+ # Sensitive file reads/search require approval
200
+ if (
201
+ operation in (Operation.READ, Operation.LIST, Operation.SEARCH)
202
+ and classification["sensitive"]
203
+ ):
204
+ if approved_sensitive and str(resolved) in approved_sensitive:
205
+ return PathDecision(allowed=True)
206
+ return PathDecision(
207
+ allowed=False,
208
+ reason="Sensitive file or directory access requires explicit user approval.",
209
+ )
210
+
211
+ # Outside-workspace reads/search: warn but allow (existing semantics)
212
+ if (
213
+ operation in (Operation.READ, Operation.LIST, Operation.SEARCH)
214
+ and not classification["inside_workspace"]
215
+ ):
216
+ # We allow but don't include content in denial messages
217
+ return PathDecision(allowed=True)
218
+
219
+ return PathDecision(allowed=True)