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,586 @@
1
+ """Skills tools - dedicated tools for Agent Skills integration."""
2
+
3
+ import asyncio
4
+ import logging
5
+ import shlex
6
+ import shutil
7
+ import subprocess
8
+ import tempfile
9
+ import uuid
10
+ from pathlib import Path
11
+
12
+ from pydantic import BaseModel
13
+ from pydantic_ai import RunContext
14
+
15
+ from code_muse.callbacks import register_callback
16
+ from code_muse.config import get_global_model_name
17
+ from code_muse.messaging import (
18
+ SkillActivateMessage,
19
+ SkillBackgroundMessage,
20
+ SkillDeactivateMessage,
21
+ SkillEntry,
22
+ SkillListMessage,
23
+ get_message_bus,
24
+ )
25
+ from code_muse.plugins.agent_skills.register_callbacks import _deactivated_skills
26
+
27
+ logger = logging.getLogger(__name__)
28
+
29
+ # Background job store: job_id -> metadata dict
30
+ _background_jobs: dict[str, dict] = {}
31
+
32
+
33
+ # Output models
34
+ class SkillListOutput(BaseModel):
35
+ """Output for list_or_search_skills tool."""
36
+
37
+ skills: list[dict] # Each has: name, description, path, tags
38
+ total_count: int
39
+ query: str | None = None # The search query if provided
40
+ error: str | None = None
41
+
42
+
43
+ class SkillActivateOutput(BaseModel):
44
+ """Output for activate_skill tool."""
45
+
46
+ skill_name: str
47
+ content: str # Full SKILL.md content
48
+ resources: list[str] # Available resource files
49
+ error: str | None = None
50
+ consent_required: bool = False
51
+ message: str = ""
52
+
53
+
54
+ def register_activate_skill(agent):
55
+ """Register the activate_skill tool."""
56
+
57
+ @agent.tool
58
+ async def activate_skill(
59
+ context: RunContext,
60
+ skill_name: str = "",
61
+ consent_confirmed: bool = False,
62
+ ) -> SkillActivateOutput:
63
+ """Activate a skill by loading its full SKILL.md instructions."""
64
+ # Import from plugin
65
+
66
+ from code_muse.plugins.agent_skills.config import (
67
+ get_skill_directories,
68
+ get_skills_enabled,
69
+ )
70
+ from code_muse.plugins.agent_skills.discovery import discover_skills
71
+ from code_muse.plugins.agent_skills.metadata import (
72
+ get_skill_resources,
73
+ load_full_skill_content,
74
+ )
75
+
76
+ # Check if skills enabled
77
+ if not get_skills_enabled():
78
+ return SkillActivateOutput(
79
+ skill_name=skill_name,
80
+ content="",
81
+ resources=[],
82
+ error="Skills integration is disabled. Enable it with /set skills_enabled=true",
83
+ )
84
+
85
+ # Discover skills
86
+ try:
87
+ skill_dirs = get_skill_directories()
88
+ discovered = discover_skills(skill_dirs)
89
+ except Exception as e:
90
+ logger.error(f"Failed to discover skills: {e}")
91
+ return SkillActivateOutput(
92
+ skill_name=skill_name,
93
+ content="",
94
+ resources=[],
95
+ error=f"Failed to discover skills: {e}",
96
+ )
97
+
98
+ # Find skill by name
99
+ skill_path = None
100
+ for skill_info in discovered:
101
+ if skill_info.name == skill_name and skill_info.has_skill_md:
102
+ skill_path = skill_info.path
103
+ break
104
+
105
+ if not skill_path:
106
+ return SkillActivateOutput(
107
+ skill_name=skill_name,
108
+ content="",
109
+ resources=[],
110
+ error=f"Skill '{skill_name}' not found. Use list_or_search_skills to see available skills.",
111
+ )
112
+
113
+ # Consent gating
114
+ if not consent_confirmed:
115
+ return SkillActivateOutput(
116
+ skill_name=skill_name,
117
+ content="",
118
+ resources=[],
119
+ error=None,
120
+ consent_required=True,
121
+ message=f"To activate '{skill_name}', please ask the user: 'May I activate the {skill_name} skill?' and call activate_skill again with consent_confirmed=True after they agree.",
122
+ )
123
+
124
+ # Load full content
125
+ content = load_full_skill_content(skill_path)
126
+ if content is None:
127
+ return SkillActivateOutput(
128
+ skill_name=skill_name,
129
+ content="",
130
+ resources=[],
131
+ error=f"Failed to load content for skill '{skill_name}'",
132
+ )
133
+
134
+ # Get resource list
135
+ resource_paths = get_skill_resources(skill_path)
136
+ resources = [str(p) for p in resource_paths]
137
+
138
+ # Emit message for UI
139
+ content_preview = content[:200] if content else ""
140
+ skill_msg = SkillActivateMessage(
141
+ skill_name=skill_name,
142
+ skill_path=str(skill_path),
143
+ content_preview=content_preview,
144
+ resource_count=len(resources),
145
+ success=True,
146
+ )
147
+ get_message_bus().emit(skill_msg)
148
+
149
+ return SkillActivateOutput(
150
+ skill_name=skill_name,
151
+ content=content,
152
+ resources=resources,
153
+ error=None,
154
+ )
155
+
156
+ return activate_skill
157
+
158
+
159
+ def register_list_or_search_skills(agent):
160
+ """Register the list_or_search_skills tool."""
161
+
162
+ @agent.tool
163
+ async def list_or_search_skills(
164
+ context: RunContext, query: str | None = None
165
+ ) -> SkillListOutput:
166
+ """List available skills, optionally filtered by search query.
167
+
168
+ Args:
169
+ query: Optional search term to filter skills by name/description/tags.
170
+ If None, returns all available skills.
171
+ """
172
+ # Import from plugin
173
+
174
+ from code_muse.plugins.agent_skills.config import (
175
+ get_disabled_skills,
176
+ get_skill_directories,
177
+ get_skills_enabled,
178
+ )
179
+ from code_muse.plugins.agent_skills.discovery import discover_skills
180
+ from code_muse.plugins.agent_skills.metadata import parse_skill_metadata
181
+
182
+ # Check if skills enabled
183
+ if not get_skills_enabled():
184
+ return SkillListOutput(
185
+ skills=[],
186
+ total_count=0,
187
+ query=query,
188
+ error="Skills integration is disabled. Enable it with /set skills_enabled=true",
189
+ )
190
+
191
+ # Get disabled skills
192
+ disabled_skills = get_disabled_skills()
193
+
194
+ # Discover all skills
195
+ try:
196
+ skill_dirs = get_skill_directories()
197
+ discovered = discover_skills(skill_dirs)
198
+ except Exception as e:
199
+ logger.error(f"Failed to discover skills: {e}")
200
+ return SkillListOutput(
201
+ skills=[],
202
+ total_count=0,
203
+ query=query,
204
+ error=f"Failed to discover skills: {e}",
205
+ )
206
+
207
+ # Parse metadata for each skill
208
+ skills_list = []
209
+ for skill_info in discovered:
210
+ # Skip disabled skills
211
+ if skill_info.name in disabled_skills:
212
+ continue
213
+
214
+ # Only include skills with valid SKILL.md
215
+ if not skill_info.has_skill_md:
216
+ continue
217
+
218
+ metadata = parse_skill_metadata(skill_info.path)
219
+ if metadata:
220
+ skill_dict = {
221
+ "name": metadata.name,
222
+ "description": metadata.description,
223
+ "path": str(metadata.path),
224
+ "tags": metadata.tags,
225
+ "version": metadata.version,
226
+ "author": metadata.author,
227
+ "source": metadata.source or skill_info.source,
228
+ "trust": metadata.trust or skill_info.trust,
229
+ "hash": metadata.skill_md_hash or skill_info.skill_md_hash,
230
+ }
231
+ # Filter out None values for cleanliness
232
+ skill_dict = {k: v for k, v in skill_dict.items() if v is not None}
233
+ skills_list.append(skill_dict)
234
+
235
+ # Filter by query if provided
236
+ if query:
237
+ query_lower = query.lower()
238
+ filtered = []
239
+ for skill in skills_list:
240
+ # Check name (case-insensitive)
241
+ if query_lower in skill["name"].lower():
242
+ filtered.append(skill)
243
+ continue
244
+
245
+ # Check description (case-insensitive)
246
+ if query_lower in skill["description"].lower():
247
+ filtered.append(skill)
248
+ continue
249
+
250
+ # Check tags (case-insensitive)
251
+ for tag in skill["tags"]:
252
+ if query_lower in tag.lower():
253
+ filtered.append(skill)
254
+ break
255
+ skills_list = filtered
256
+
257
+ # Emit message for UI
258
+ skill_entries = [
259
+ SkillEntry(
260
+ name=s["name"],
261
+ description=s["description"],
262
+ path=s["path"],
263
+ tags=s["tags"],
264
+ enabled=s["name"] not in disabled_skills,
265
+ )
266
+ for s in skills_list
267
+ ]
268
+ skill_msg = SkillListMessage(
269
+ skills=skill_entries,
270
+ query=query,
271
+ total_count=len(skills_list),
272
+ )
273
+ get_message_bus().emit(skill_msg)
274
+
275
+ return SkillListOutput(
276
+ skills=skills_list, total_count=len(skills_list), query=query, error=None
277
+ )
278
+
279
+ return list_or_search_skills
280
+
281
+
282
+ # Output models for new tools
283
+ class SkillDeactivateOutput(BaseModel):
284
+ """Output for deactivate_skill tool."""
285
+
286
+ skill_name: str
287
+ success: bool
288
+ message: str
289
+
290
+
291
+ class SkillBackgroundOutput(BaseModel):
292
+ """Output for background skill job tools."""
293
+
294
+ job_id: str
295
+ skill_name: str
296
+ status: str # "started" | "running" | "complete" | "error"
297
+ result: str = ""
298
+ log_file: str = ""
299
+
300
+
301
+ def register_deactivate_skill(agent):
302
+ """Register the deactivate_skill tool."""
303
+
304
+ @agent.tool
305
+ async def deactivate_skill(
306
+ context: RunContext, skill_name: str = ""
307
+ ) -> SkillDeactivateOutput:
308
+ """Deactivate a skill so it is excluded from prompt injection."""
309
+ _deactivated_skills.add(skill_name)
310
+ message = f"Skill '{skill_name}' has been deactivated for this session."
311
+ skill_msg = SkillDeactivateMessage(
312
+ skill_name=skill_name, success=True, message=message
313
+ )
314
+ get_message_bus().emit(skill_msg)
315
+ return SkillDeactivateOutput(
316
+ skill_name=skill_name, success=True, message=message
317
+ )
318
+
319
+ return deactivate_skill
320
+
321
+
322
+ def register_run_skill_background(agent):
323
+ """Register the run_skill_background tool."""
324
+
325
+ @agent.tool
326
+ async def run_skill_background(
327
+ context: RunContext, skill_name: str = "", task: str = ""
328
+ ) -> SkillBackgroundOutput:
329
+ """Launch a headless background agent with a skill as system prompt."""
330
+ from code_muse.plugins.agent_skills.config import (
331
+ get_skill_directories,
332
+ get_skills_enabled,
333
+ )
334
+ from code_muse.plugins.agent_skills.discovery import discover_skills
335
+ from code_muse.plugins.agent_skills.metadata import (
336
+ load_full_skill_content,
337
+ parse_yaml_frontmatter,
338
+ )
339
+
340
+ if not get_skills_enabled():
341
+ return SkillBackgroundOutput(
342
+ job_id="",
343
+ skill_name=skill_name,
344
+ status="error",
345
+ result="Skills integration is disabled.",
346
+ log_file="",
347
+ )
348
+
349
+ try:
350
+ skill_dirs = get_skill_directories()
351
+ discovered = discover_skills(skill_dirs)
352
+ except Exception as e:
353
+ logger.error(f"Failed to discover skills: {e}")
354
+ return SkillBackgroundOutput(
355
+ job_id="",
356
+ skill_name=skill_name,
357
+ status="error",
358
+ result=f"Failed to discover skills: {e}",
359
+ log_file="",
360
+ )
361
+
362
+ skill_path = None
363
+ for skill_info in discovered:
364
+ if skill_info.name == skill_name and skill_info.has_skill_md:
365
+ skill_path = skill_info.path
366
+ break
367
+
368
+ if not skill_path:
369
+ return SkillBackgroundOutput(
370
+ job_id="",
371
+ skill_name=skill_name,
372
+ status="error",
373
+ result=f"Skill '{skill_name}' not found.",
374
+ log_file="",
375
+ )
376
+
377
+ content = load_full_skill_content(skill_path)
378
+ if content is None:
379
+ return SkillBackgroundOutput(
380
+ job_id="",
381
+ skill_name=skill_name,
382
+ status="error",
383
+ result=f"Failed to load content for skill '{skill_name}'.",
384
+ log_file="",
385
+ )
386
+
387
+ # Parse frontmatter for worktree flag
388
+ frontmatter = parse_yaml_frontmatter(content)
389
+ use_worktree = bool(frontmatter and frontmatter.get("worktree"))
390
+
391
+ # Prepare ephemeral worktree / cwd
392
+ if use_worktree:
393
+ worktree_dir = tempfile.mkdtemp(prefix=f"skill_bg_{skill_name}_")
394
+ # Attempt git worktree if inside a git repo
395
+ try:
396
+ git_proc = await asyncio.create_subprocess_exec(
397
+ "git",
398
+ "rev-parse",
399
+ "--show-toplevel",
400
+ stdout=asyncio.subprocess.PIPE,
401
+ stderr=asyncio.subprocess.PIPE,
402
+ )
403
+ git_stdout, _ = await git_proc.communicate()
404
+ if git_proc.returncode != 0:
405
+ raise subprocess.CalledProcessError(
406
+ git_proc.returncode, ["git", "rev-parse", "--show-toplevel"]
407
+ )
408
+ git_root = git_stdout.decode().strip()
409
+ branch_name = f"skill-bg-{uuid.uuid4().hex[:8]}"
410
+ worktree_proc = await asyncio.create_subprocess_exec(
411
+ "git",
412
+ "worktree",
413
+ "add",
414
+ worktree_dir,
415
+ "-b",
416
+ branch_name,
417
+ cwd=git_root,
418
+ stdout=asyncio.subprocess.PIPE,
419
+ stderr=asyncio.subprocess.PIPE,
420
+ )
421
+ await worktree_proc.wait()
422
+ if worktree_proc.returncode != 0:
423
+ raise subprocess.CalledProcessError(
424
+ worktree_proc.returncode,
425
+ ["git", "worktree", "add", worktree_dir, "-b", branch_name],
426
+ )
427
+ except Exception:
428
+ # Fallback: just use the temp dir as plain cwd
429
+ pass
430
+ cwd = worktree_dir
431
+ else:
432
+ cwd = Path.cwd()
433
+
434
+ # Write skill content and task to temp files
435
+ skill_content_file = tempfile.mktemp(
436
+ prefix=f"skill_{skill_name}_", suffix=".md"
437
+ )
438
+ Path(skill_content_file).write_text(content, encoding="utf-8")
439
+
440
+ task_file = tempfile.mktemp(prefix="skill_task_", suffix=".txt")
441
+ Path(task_file).write_text(task, encoding="utf-8")
442
+
443
+ job_id = uuid.uuid4().hex[:8]
444
+ # TODO: PEP 750 t-string — use templatelib when stable
445
+ log_file = f"/tmp/skill_bg_{job_id}.log"
446
+
447
+ # Build and launch command
448
+ model = get_global_model_name() or "gemini"
449
+ cmd = (
450
+ # TODO: PEP 750 t-string — use templatelib when stable
451
+ f"cat {shlex.quote(task_file)} | code-muse --headless "
452
+ # TODO: PEP 750 t-string — use templatelib when stable
453
+ f"--system-prompt {shlex.quote(skill_content_file)} "
454
+ # TODO: PEP 750 t-string — use templatelib when stable
455
+ f"--model {shlex.quote(model)} --cwd {shlex.quote(str(cwd))} "
456
+ # TODO: PEP 750 t-string — use templatelib when stable
457
+ f"> {shlex.quote(log_file)} 2>&1"
458
+ )
459
+
460
+ try:
461
+ process = subprocess.Popen(cmd, shell=True, cwd=cwd)
462
+ except Exception as e:
463
+ return SkillBackgroundOutput(
464
+ job_id=job_id,
465
+ skill_name=skill_name,
466
+ status="error",
467
+ result=f"Failed to start background job: {e}",
468
+ log_file=log_file,
469
+ )
470
+
471
+ _background_jobs[job_id] = {
472
+ "process": process,
473
+ "log_file": log_file,
474
+ "skill_name": skill_name,
475
+ "task": task,
476
+ "skill_content_file": skill_content_file,
477
+ "task_file": task_file,
478
+ "cwd": cwd,
479
+ }
480
+
481
+ bus_msg = SkillBackgroundMessage(
482
+ job_id=job_id,
483
+ skill_name=skill_name,
484
+ status="started",
485
+ result="",
486
+ log_file=log_file,
487
+ )
488
+ get_message_bus().emit(bus_msg)
489
+
490
+ return SkillBackgroundOutput(
491
+ job_id=job_id,
492
+ skill_name=skill_name,
493
+ status="started",
494
+ result="Background job started.",
495
+ log_file=log_file,
496
+ )
497
+
498
+ return run_skill_background
499
+
500
+
501
+ def register_check_skill_background(agent):
502
+ """Register the check_skill_background tool."""
503
+
504
+ @agent.tool
505
+ async def check_skill_background(
506
+ context: RunContext, job_id: str = ""
507
+ ) -> SkillBackgroundOutput:
508
+ """Check the status of a background skill job."""
509
+ job = _background_jobs.get(job_id)
510
+ if not job:
511
+ return SkillBackgroundOutput(
512
+ job_id=job_id,
513
+ skill_name="",
514
+ status="error",
515
+ result=f"Job '{job_id}' not found.",
516
+ log_file="",
517
+ )
518
+
519
+ process = job["process"]
520
+ log_file = job["log_file"]
521
+ skill_name = job["skill_name"]
522
+
523
+ poll_result = process.poll()
524
+ if poll_result is None:
525
+ return SkillBackgroundOutput(
526
+ job_id=job_id,
527
+ skill_name=skill_name,
528
+ status="running",
529
+ result="Job is still running.",
530
+ log_file=log_file,
531
+ )
532
+
533
+ # Process finished – read log
534
+ try:
535
+ result_text = Path(log_file).read_text(encoding="utf-8")
536
+ except Exception:
537
+ result_text = ""
538
+
539
+ status = "complete" if poll_result == 0 else "error"
540
+ return SkillBackgroundOutput(
541
+ job_id=job_id,
542
+ skill_name=skill_name,
543
+ status=status,
544
+ result=result_text,
545
+ log_file=log_file,
546
+ )
547
+
548
+ return check_skill_background
549
+
550
+
551
+ def _cleanup_skill_temp_files() -> None:
552
+ """Clean up background skill jobs and temp files on shutdown."""
553
+ count = len(_background_jobs)
554
+ if not count:
555
+ return
556
+
557
+ for _job_id, job in list(_background_jobs.items()):
558
+ process = job.get("process")
559
+ if process and process.poll() is None:
560
+ try:
561
+ process.terminate()
562
+ process.wait(timeout=5)
563
+ except Exception:
564
+ try:
565
+ process.kill()
566
+ process.wait(timeout=2)
567
+ except Exception:
568
+ pass
569
+
570
+ cwd = job.get("cwd")
571
+ if cwd and "skill_bg_" in str(cwd):
572
+ shutil.rmtree(cwd, ignore_errors=True)
573
+
574
+ skill_content_file = job.get("skill_content_file")
575
+ if skill_content_file and Path(skill_content_file).exists():
576
+ Path(skill_content_file).unlink(missing_ok=True)
577
+
578
+ task_file = job.get("task_file")
579
+ if task_file and Path(task_file).exists():
580
+ Path(task_file).unlink(missing_ok=True)
581
+
582
+ _background_jobs.clear()
583
+ logger.info("Cleaned up %s background skill job(s)", count)
584
+
585
+
586
+ register_callback("shutdown", _cleanup_skill_temp_files)