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,185 @@
1
+ """Image loading tool for visual analysis.
2
+
3
+ Provides ``load_image_for_analysis`` — a tiny generic tool that reads an image
4
+ from disk, validates it, downsizes it if it's billboard-sized, and returns it
5
+ as a ``ToolReturn`` with ``BinaryContent`` so multimodal models can see it.
6
+
7
+ Lives outside the browser package because it has nothing to do with browsers.
8
+ """
9
+
10
+ import io
11
+ import logging
12
+ import mimetypes
13
+ import time
14
+ from pathlib import Path
15
+ from typing import Any
16
+
17
+ from PIL import Image, UnidentifiedImageError
18
+ from pydantic_ai import BinaryContent, RunContext, ToolReturn
19
+
20
+ from code_muse.messaging import emit_error, emit_info, emit_success
21
+ from code_muse.tools.common import generate_group_id
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+ # Bigger than this on either edge and we resize to save tokens.
26
+ MAX_IMAGE_EDGE = 2048
27
+ DEFAULT_MAX_HEIGHT = 768 # kept for backward-compat in tool signature
28
+
29
+
30
+ def _validate_and_prepare_image(
31
+ image_bytes: bytes,
32
+ source_path: str | None = None,
33
+ max_edge: int | None = None,
34
+ ) -> dict[str, Any]:
35
+ """Verify image bytes, determine the real MIME type, and optionally resize.
36
+
37
+ The MIME type is determined from the decoded image content, not from the
38
+ file extension. If the image is resized, the output is normalized to PNG so
39
+ the returned bytes and MIME type stay in sync like civilized software.
40
+ """
41
+ try:
42
+ with Image.open(io.BytesIO(image_bytes)) as verified_image:
43
+ verified_image.verify()
44
+ except UnidentifiedImageError as exc:
45
+ raise ValueError("File is not a valid image") from exc
46
+ except Exception as exc:
47
+ raise ValueError(f"Failed to verify image: {exc}") from exc
48
+
49
+ with Image.open(io.BytesIO(image_bytes)) as image:
50
+ image.load()
51
+ original_width, original_height = image.size
52
+ image_format = image.format
53
+ actual_media_type = Image.MIME.get(image_format or "")
54
+
55
+ if not actual_media_type or not actual_media_type.startswith("image/"):
56
+ raise ValueError("Could not determine a valid image MIME type")
57
+
58
+ guessed_media_type = None
59
+ if source_path:
60
+ guessed_media_type, _ = mimetypes.guess_type(source_path)
61
+
62
+ largest_edge = max(original_width, original_height)
63
+ was_resized = False
64
+ output_bytes = image_bytes
65
+ output_media_type = actual_media_type
66
+ output_width = original_width
67
+ output_height = original_height
68
+
69
+ if max_edge and largest_edge > max_edge:
70
+ ratio = max_edge / largest_edge
71
+ output_width = max(1, int(round(original_width * ratio)))
72
+ output_height = max(1, int(round(original_height * ratio)))
73
+ resized = image.resize(
74
+ (output_width, output_height), Image.Resampling.LANCZOS
75
+ )
76
+ output = io.BytesIO()
77
+ resized.save(output, format="PNG", optimize=True)
78
+ output.seek(0)
79
+ output_bytes = output.read()
80
+ output_media_type = "image/png"
81
+ was_resized = True
82
+
83
+ return {
84
+ "image_bytes": output_bytes,
85
+ "media_type": output_media_type,
86
+ "actual_media_type": actual_media_type,
87
+ "guessed_media_type": guessed_media_type,
88
+ "mime_type_matches_extension": guessed_media_type
89
+ in (None, output_media_type),
90
+ "original_width": original_width,
91
+ "original_height": original_height,
92
+ "output_width": output_width,
93
+ "output_height": output_height,
94
+ "was_resized": was_resized,
95
+ }
96
+
97
+
98
+ async def load_image(
99
+ image_path: str,
100
+ max_height: int = DEFAULT_MAX_HEIGHT,
101
+ ) -> ToolReturn | dict[str, Any]:
102
+ """Load an image from the filesystem for visual analysis."""
103
+ group_id = generate_group_id("load_image", image_path)
104
+ emit_info(f"LOAD IMAGE 🖼️ {image_path}", message_group=group_id)
105
+
106
+ try:
107
+ image_file = Path(image_path)
108
+
109
+ if not image_file.exists():
110
+ error_msg = f"Image file not found: {image_path}"
111
+ emit_error(error_msg, message_group=group_id)
112
+ return {"success": False, "error": error_msg, "image_path": image_path}
113
+
114
+ if not image_file.is_file():
115
+ error_msg = f"Path is not a file: {image_path}"
116
+ emit_error(error_msg, message_group=group_id)
117
+ return {"success": False, "error": error_msg, "image_path": image_path}
118
+
119
+ image_bytes = image_file.read_bytes()
120
+ prepared_image = _validate_and_prepare_image(
121
+ image_bytes,
122
+ source_path=str(image_file),
123
+ max_edge=MAX_IMAGE_EDGE,
124
+ )
125
+
126
+ emit_success(f"Loaded image: {image_path}", message_group=group_id)
127
+
128
+ return ToolReturn(
129
+ return_value=f"Image loaded from: {image_path}",
130
+ content=[
131
+ f"Here's the image from {image_file.name}:",
132
+ BinaryContent(
133
+ data=prepared_image["image_bytes"],
134
+ media_type=prepared_image["media_type"],
135
+ ),
136
+ "Please analyze what you see in this image.",
137
+ ],
138
+ metadata={
139
+ "success": True,
140
+ "image_path": image_path,
141
+ "media_type": prepared_image["media_type"],
142
+ "actual_media_type": prepared_image["actual_media_type"],
143
+ "guessed_media_type": prepared_image["guessed_media_type"],
144
+ "mime_type_matches_extension": prepared_image[
145
+ "mime_type_matches_extension"
146
+ ],
147
+ "was_resized": prepared_image["was_resized"],
148
+ "original_size": [
149
+ prepared_image["original_width"],
150
+ prepared_image["original_height"],
151
+ ],
152
+ "output_size": [
153
+ prepared_image["output_width"],
154
+ prepared_image["output_height"],
155
+ ],
156
+ "max_height": max_height,
157
+ "max_edge": MAX_IMAGE_EDGE,
158
+ "timestamp": time.time(),
159
+ },
160
+ )
161
+
162
+ except Exception as e:
163
+ error_msg = f"Failed to load image: {str(e)}"
164
+ emit_error(error_msg, message_group=group_id)
165
+ logger.exception("Error loading image")
166
+ return {"success": False, "error": error_msg, "image_path": image_path}
167
+
168
+
169
+ def register_load_image(agent):
170
+ """Register the image loading tool."""
171
+
172
+ @agent.tool
173
+ async def load_image_for_analysis(
174
+ context: RunContext,
175
+ image_path: str,
176
+ ) -> ToolReturn | dict[str, Any]:
177
+ """Load an image file so you can see and analyze it.
178
+
179
+ Args:
180
+ image_path: Path to the image file.
181
+
182
+ Returns:
183
+ ToolReturn with the image, or error dict.
184
+ """
185
+ return await load_image(image_path=image_path)
@@ -0,0 +1,243 @@
1
+ """mitmproxy — MITM proxy for provider traffic capture and analysis."""
2
+
3
+ import json
4
+ from typing import Any
5
+
6
+ from pydantic import BaseModel
7
+ from pydantic_ai import RunContext
8
+
9
+ from code_muse.messaging import emit_error, emit_info, emit_success
10
+ from code_muse.tools.meetin_proxy.proxy_manager import get_manager
11
+
12
+
13
+ class MitmproxyConfig(BaseModel):
14
+ """Configuration for mitmproxy capture session."""
15
+
16
+ target_domain: str = ""
17
+ listen_port: int | None = None
18
+ max_req_body: int = 10000
19
+ max_res_body: int = 100000
20
+
21
+
22
+ class MitmproxyResult(BaseModel):
23
+ """Result of a mitmproxy capture session."""
24
+
25
+ proxy_port: int
26
+ flow_count: int
27
+ output_path: str
28
+ captured_at: str
29
+
30
+
31
+ class MitmproxyStatus(BaseModel):
32
+ """Current status of the mitmproxy instance."""
33
+
34
+ running: bool
35
+ port: int | None = None
36
+ target: str = ""
37
+ flow_count: int = 0
38
+
39
+
40
+ def register_mitmproxy(agent):
41
+ """Register the mitmproxy tool."""
42
+
43
+ @agent.tool
44
+ async def mitmproxy(
45
+ context: RunContext,
46
+ command: str,
47
+ target_domain: str = "",
48
+ listen_port: int | None = None,
49
+ max_req_body: int = 10000,
50
+ max_res_body: int = 100000,
51
+ duration_seconds: int | None = None,
52
+ ) -> MitmproxyResult | MitmproxyStatus | dict[str, Any]:
53
+ """Control the mitmproxy MITM capture proxy.
54
+
55
+ Commands:
56
+ start — Spawn mitmdump, set proxy env vars, begin capture.
57
+ stop — Stop mitmdump, read flows, unset env vars, return results.
58
+ status — Return current proxy status.
59
+ capture — Convenience: start, optionally wait, then stop and return data.
60
+
61
+ Args:
62
+ command: Action to perform — "start", "stop", "status", or "capture".
63
+ target_domain: Only capture traffic matching this domain.
64
+ listen_port: Port to listen on (auto-selected if omitted).
65
+ max_req_body: Maximum request body bytes to record.
66
+ max_res_body: Maximum response body bytes to record.
67
+ duration_seconds: For "capture", seconds to wait before auto-stopping.
68
+
69
+ Returns:
70
+ MitmproxyResult on stop/capture, MitmproxyStatus on status/start.
71
+ """
72
+ manager = get_manager()
73
+ config = MitmproxyConfig(
74
+ target_domain=target_domain,
75
+ listen_port=listen_port,
76
+ max_req_body=max_req_body,
77
+ max_res_body=max_res_body,
78
+ )
79
+
80
+ if command == "start":
81
+ try:
82
+ port = manager.start(
83
+ target=config.target_domain,
84
+ port=config.listen_port,
85
+ max_req_body=config.max_req_body,
86
+ max_res_body=config.max_res_body,
87
+ )
88
+ return MitmproxyStatus(
89
+ running=True,
90
+ port=port,
91
+ target=config.target_domain,
92
+ flow_count=0,
93
+ )
94
+ except Exception as exc:
95
+ emit_error(f"Failed to start mitmproxy: {exc}")
96
+ return {
97
+ "success": False,
98
+ "error": str(exc),
99
+ "command": command,
100
+ }
101
+
102
+ elif command == "stop":
103
+ data = manager.stop()
104
+ status = manager.status()
105
+ # After stop, status will show not running
106
+ flow_count = 0
107
+ output_path = ""
108
+ captured_at = ""
109
+ if data and isinstance(data, dict):
110
+ meta = data.get("meta", {})
111
+ flow_count = meta.get("total_flows", 0)
112
+ captured_at = meta.get("captured_at", "")
113
+ # Write a safe temp copy so caller can inspect flows
114
+ import tempfile
115
+
116
+ fd, output_path = tempfile.mkstemp(
117
+ prefix="mitmproxy_result_", suffix=".json"
118
+ )
119
+ with open(fd, "w", encoding="utf-8") as f:
120
+ json.dump(data, f, indent=2, default=str)
121
+
122
+ if data:
123
+ emit_success(
124
+ f"mitmproxy stopped. Captured {flow_count} flow(s). "
125
+ f"Data written to {output_path}"
126
+ )
127
+ return MitmproxyResult(
128
+ proxy_port=status.get("port") or 0,
129
+ flow_count=flow_count,
130
+ output_path=output_path,
131
+ captured_at=captured_at,
132
+ )
133
+ else:
134
+ emit_info("mitmproxy stopped. No capture data found.")
135
+ return MitmproxyResult(
136
+ proxy_port=status.get("port") or 0,
137
+ flow_count=0,
138
+ output_path="",
139
+ captured_at="",
140
+ )
141
+
142
+ elif command == "status":
143
+ st = manager.status()
144
+ return MitmproxyStatus(
145
+ running=st["running"],
146
+ port=st["port"],
147
+ target=st["target"],
148
+ flow_count=st["flow_count"],
149
+ )
150
+
151
+ elif command == "capture":
152
+ try:
153
+ port = manager.start(
154
+ target=config.target_domain,
155
+ port=config.listen_port,
156
+ max_req_body=config.max_req_body,
157
+ max_res_body=config.max_res_body,
158
+ )
159
+ except Exception as exc:
160
+ emit_error(f"Failed to start mitmproxy: {exc}")
161
+ return {
162
+ "success": False,
163
+ "error": str(exc),
164
+ "command": command,
165
+ }
166
+
167
+ if duration_seconds and duration_seconds > 0:
168
+ emit_info(
169
+ f"mitmproxy capturing for {duration_seconds}s on port {port}..."
170
+ )
171
+ await _async_sleep(duration_seconds)
172
+ else:
173
+ emit_info(
174
+ f"mitmproxy capturing on port {port}. "
175
+ "Call mitmproxy with command='stop' when finished."
176
+ )
177
+ return MitmproxyStatus(
178
+ running=True,
179
+ port=port,
180
+ target=config.target_domain,
181
+ flow_count=0,
182
+ )
183
+
184
+ data = manager.stop()
185
+ flow_count = 0
186
+ output_path = ""
187
+ captured_at = ""
188
+ if data and isinstance(data, dict):
189
+ meta = data.get("meta", {})
190
+ flow_count = meta.get("total_flows", 0)
191
+ captured_at = meta.get("captured_at", "")
192
+ import tempfile
193
+
194
+ fd, output_path = tempfile.mkstemp(
195
+ prefix="mitmproxy_result_", suffix=".json"
196
+ )
197
+ with open(fd, "w", encoding="utf-8") as f:
198
+ json.dump(data, f, indent=2, default=str)
199
+
200
+ if data:
201
+ emit_success(
202
+ f"mitmproxy capture complete. {flow_count} flow(s). "
203
+ f"Data: {output_path}"
204
+ )
205
+ return MitmproxyResult(
206
+ proxy_port=port,
207
+ flow_count=flow_count,
208
+ output_path=output_path,
209
+ captured_at=captured_at,
210
+ )
211
+ else:
212
+ emit_info("mitmproxy capture complete. No data captured.")
213
+ return MitmproxyResult(
214
+ proxy_port=port,
215
+ flow_count=0,
216
+ output_path="",
217
+ captured_at="",
218
+ )
219
+
220
+ else:
221
+ return {
222
+ "success": False,
223
+ "error": (
224
+ f"Unknown command: {command}. Use start, stop, status, or capture."
225
+ ),
226
+ }
227
+
228
+ return mitmproxy
229
+
230
+
231
+ async def _async_sleep(seconds: float) -> None:
232
+ """Async sleep helper."""
233
+ import asyncio
234
+
235
+ await asyncio.sleep(seconds)
236
+
237
+
238
+ # Register startup callback for mitmproxy availability check
239
+ from code_muse.tools.meetin_proxy.register_callbacks import ( # noqa: E402
240
+ register as _register_mitmproxy_callbacks,
241
+ )
242
+
243
+ _register_mitmproxy_callbacks()
@@ -0,0 +1,82 @@
1
+ """mitmproxy capture addon — injected into mitmdump via -s flag."""
2
+
3
+ import json
4
+ import os
5
+ from datetime import UTC, datetime
6
+
7
+
8
+ class TrafficCapture:
9
+ def __init__(self):
10
+ self.flows = []
11
+ self.target = os.environ.get("MITMPROXY_TARGET", "")
12
+ self.output = os.environ.get("MITMPROXY_OUTPUT", "/tmp/mitmproxy_capture.json")
13
+ self.max_req_body = int(os.environ.get("MITMPROXY_MAX_REQ_BODY", "10000"))
14
+ self.max_res_body = int(os.environ.get("MITMPROXY_MAX_RES_BODY", "100000"))
15
+
16
+ def _should_capture(self, flow) -> bool:
17
+ if not self.target:
18
+ return True
19
+ return self.target in flow.request.pretty_host
20
+
21
+ def response(self, flow):
22
+ if not self._should_capture(flow):
23
+ return
24
+ try:
25
+ req_body = flow.request.get_text(strict=False) or ""
26
+ res_body = flow.response.get_text(strict=False) or ""
27
+ except Exception:
28
+ req_body = f"<binary: {len(flow.request.content)} bytes>"
29
+ res_body = f"<binary: {len(flow.response.content)} bytes>"
30
+
31
+ if len(req_body) > self.max_req_body:
32
+ req_body = req_body[: self.max_req_body] + "\n... <truncated>"
33
+ if len(res_body) > self.max_res_body:
34
+ res_body = res_body[: self.max_res_body] + "\n... <truncated>"
35
+
36
+ entry = {
37
+ "url": flow.request.pretty_url,
38
+ "method": flow.request.method,
39
+ "host": flow.request.pretty_host,
40
+ "path": flow.request.path,
41
+ "request_headers": dict(flow.request.headers),
42
+ "request_body": req_body,
43
+ "status_code": flow.response.status_code,
44
+ "response_headers": dict(flow.response.headers),
45
+ "response_body": res_body,
46
+ "timestamp": datetime.now(UTC).isoformat(),
47
+ "content_type": flow.response.headers.get("content-type", ""),
48
+ }
49
+ self.flows.append(entry)
50
+
51
+ def error(self, flow):
52
+ if not self._should_capture(flow):
53
+ return
54
+ entry = {
55
+ "url": flow.request.pretty_url if flow.request else "N/A",
56
+ "method": flow.request.method if flow.request else "N/A",
57
+ "error": str(flow.error.msg) if flow.error else "Unknown error",
58
+ "timestamp": datetime.now(UTC).isoformat(),
59
+ }
60
+ self.flows.append(entry)
61
+
62
+ def done(self):
63
+ out_dir = os.path.dirname(self.output)
64
+ if out_dir:
65
+ os.makedirs(out_dir, exist_ok=True)
66
+ with open(self.output, "w") as f:
67
+ json.dump(
68
+ {
69
+ "meta": {
70
+ "captured_at": datetime.now(UTC).isoformat(),
71
+ "target_filter": self.target,
72
+ "total_flows": len(self.flows),
73
+ },
74
+ "flows": self.flows,
75
+ },
76
+ f,
77
+ indent=2,
78
+ default=str,
79
+ )
80
+
81
+
82
+ addons = [TrafficCapture()]