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,440 @@
1
+ """Universal Constructor safety and approval engine.
2
+
3
+ Validates tool names/namespaces, blocks dangerous code patterns,
4
+ and stores per-tool approval decisions keyed by code hash.
5
+ """
6
+
7
+ import ast
8
+ import contextlib
9
+ import hashlib
10
+ import json
11
+ import logging
12
+ import os
13
+ import re
14
+ from pathlib import Path
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+ # XDG state directory for private approval storage
19
+ _APPROVAL_DIR = (
20
+ Path(os.environ.get("XDG_STATE_HOME", Path.home() / ".local" / "state"))
21
+ / "code_muse"
22
+ )
23
+ _APPROVAL_FILE = _APPROVAL_DIR / "uc_approvals.json"
24
+
25
+ # Valid tool name: [a-zA-Z_][a-zA-Z0-9_]*
26
+ _VALID_NAME_RE = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$")
27
+
28
+ # Reserved module names that should not be used as tool names
29
+ _RESERVED_MODULE_NAMES: set[str] = {
30
+ "abc",
31
+ "ast",
32
+ "builtins",
33
+ "code",
34
+ "codecs",
35
+ "collections",
36
+ "copy",
37
+ "datetime",
38
+ "enum",
39
+ "fnmatch",
40
+ "functools",
41
+ "glob",
42
+ "hashlib",
43
+ "importlib",
44
+ "inspect",
45
+ "io",
46
+ "json",
47
+ "logging",
48
+ "math",
49
+ "os",
50
+ "pathlib",
51
+ "pickle",
52
+ "platform",
53
+ "random",
54
+ "re",
55
+ "shutil",
56
+ "signal",
57
+ "socket",
58
+ "sqlite3",
59
+ "string",
60
+ "subprocess",
61
+ "sys",
62
+ "tempfile",
63
+ "threading",
64
+ "time",
65
+ "traceback",
66
+ "types",
67
+ "typing",
68
+ "urllib",
69
+ "uuid",
70
+ "warnings",
71
+ "xml",
72
+ "zipfile",
73
+ }
74
+
75
+ # Dangerous patterns that should BLOCK tool creation/execution
76
+ _DANGEROUS_IMPORTS_BLOCK: set[str] = {
77
+ "subprocess",
78
+ "os.system",
79
+ "eval",
80
+ "exec",
81
+ "compile",
82
+ "__import__",
83
+ "pickle",
84
+ "marshal",
85
+ "socket",
86
+ "ctypes",
87
+ }
88
+
89
+ _DANGEROUS_CALLS_BLOCK: set[str] = {
90
+ "eval",
91
+ "exec",
92
+ "compile",
93
+ "__import__",
94
+ "system",
95
+ "popen",
96
+ "spawn",
97
+ "fork",
98
+ "globals",
99
+ "locals",
100
+ }
101
+
102
+ # Additional dangerous patterns that require explicit approval
103
+ _DANGEROUS_IMPORTS_APPROVAL: set[str] = {
104
+ "requests",
105
+ "urllib",
106
+ "http.client",
107
+ "ftplib",
108
+ "smtplib",
109
+ "paramiko",
110
+ }
111
+
112
+ _DANGEROUS_OPEN_MODES = {
113
+ "w",
114
+ "a",
115
+ "x",
116
+ "wb",
117
+ "ab",
118
+ "xb",
119
+ "w+",
120
+ "a+",
121
+ "r+",
122
+ "rb+",
123
+ "wb+",
124
+ }
125
+
126
+
127
+ def _ensure_private_dir(path: Path) -> Path:
128
+ """Ensure directory exists with 0o700 permissions."""
129
+ path.mkdir(parents=True, exist_ok=True)
130
+ with contextlib.suppress(OSError):
131
+ os.chmod(path, 0o700)
132
+ return path
133
+
134
+
135
+ def _atomic_write_private_json(file_path: Path, data: dict) -> None:
136
+ """Atomically write JSON with 0o600 permissions."""
137
+ tmp_path = file_path.with_suffix(".tmp")
138
+ try:
139
+ fd = os.open(
140
+ str(tmp_path),
141
+ os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
142
+ 0o600,
143
+ )
144
+ with os.fdopen(fd, "w", encoding="utf-8") as f:
145
+ json.dump(data, f, indent=2)
146
+ f.flush()
147
+ os.fsync(f.fileno())
148
+ os.replace(str(tmp_path), str(file_path))
149
+ with contextlib.suppress(OSError):
150
+ os.chmod(file_path, 0o600)
151
+ except Exception:
152
+ with contextlib.suppress(OSError):
153
+ tmp_path.unlink(missing_ok=True)
154
+ raise
155
+
156
+
157
+ def _load_approval_db() -> dict[str, dict]:
158
+ """Load the UC approval database from private storage."""
159
+ _ensure_private_dir(_APPROVAL_DIR)
160
+ if not _APPROVAL_FILE.exists():
161
+ return {}
162
+ try:
163
+ with open(_APPROVAL_FILE, encoding="utf-8") as f:
164
+ data = json.load(f)
165
+ if isinstance(data, dict):
166
+ return data
167
+ except json.JSONDecodeError, OSError:
168
+ pass
169
+ return {}
170
+
171
+
172
+ def _save_approval_db(db: dict[str, dict]) -> None:
173
+ """Save the UC approval database to private storage."""
174
+ _ensure_private_dir(_APPROVAL_DIR)
175
+ _atomic_write_private_json(_APPROVAL_FILE, db)
176
+
177
+
178
+ def compute_code_hash(code: str) -> str:
179
+ """Compute SHA-256 hash of tool source code."""
180
+ return hashlib.sha256(code.encode("utf-8")).hexdigest()
181
+
182
+
183
+ def validate_tool_name(name: str, *, check_reserved: bool = True) -> str | None:
184
+ """Strictly validate a tool name or namespace segment.
185
+
186
+ Args:
187
+ name: Tool name or namespace segment to validate.
188
+ check_reserved: If True, reject names matching Python stdlib modules.
189
+ Set to False for namespace segments that don't shadow modules
190
+ (e.g., "json" in "json.validate_files" is a namespace, not
191
+ an import target — the tool is invoked as "uc:json.validate_files").
192
+
193
+ Returns:
194
+ Error message if invalid, None if valid.
195
+ """
196
+ if not name:
197
+ return "Tool name cannot be empty"
198
+ if name.startswith(".") or name.startswith("_"):
199
+ return f"Tool name cannot start with '.' or '_': {name}"
200
+ if name.startswith("__") and name.endswith("__"):
201
+ return f"Dunder names are reserved: {name}"
202
+ if "/" in name or "\\" in name or ".." in name:
203
+ return f"Path traversal characters not allowed: {name}"
204
+ if not _VALID_NAME_RE.match(name):
205
+ return f"Invalid tool name '{name}': must match [a-zA-Z_][a-zA-Z0-9_]*"
206
+ if check_reserved and name.lower() in _RESERVED_MODULE_NAMES:
207
+ return f"Tool name '{name}' is a reserved module name"
208
+ return None
209
+
210
+
211
+ def validate_namespace(namespace: str) -> str | None:
212
+ """Validate a dot-separated namespace.
213
+
214
+ Namespace segments are not checked against reserved module names
215
+ because they don't shadow Python modules — the full tool is invoked
216
+ as "uc:namespace.tool_name", not "import namespace".
217
+
218
+ Returns:
219
+ Error message if invalid, None if valid.
220
+ """
221
+ if not namespace:
222
+ return None
223
+ parts = namespace.split(".")
224
+ for part in parts:
225
+ error = validate_tool_name(part, check_reserved=False)
226
+ if error:
227
+ return error
228
+ return None
229
+
230
+
231
+ def validate_full_tool_name(name: str) -> str | None:
232
+ """Validate a full tool name possibly including namespace.
233
+
234
+ Reserved module name checks only apply to the final (leaf) segment,
235
+ since namespace segments don't shadow Python modules — a tool named
236
+ "json.validate_files" is invoked as "uc:json.validate_files", not
237
+ "import json".
238
+
239
+ Returns:
240
+ Error message if invalid, None if valid.
241
+ """
242
+ if not name:
243
+ return "Tool name cannot be empty"
244
+ if name.startswith(".") or name.endswith("."):
245
+ return "Tool name cannot start or end with '.'"
246
+ parts = name.split(".")
247
+ last_index = len(parts) - 1
248
+ for i, part in enumerate(parts):
249
+ # Only the final (leaf) segment can shadow a module name;
250
+ # namespace segments like "json" in "json.validate_files"
251
+ # are always accessed via "uc:" prefix, so skip reserved check.
252
+ is_leaf = i == last_index
253
+ error = validate_tool_name(part, check_reserved=is_leaf)
254
+ if error:
255
+ return error
256
+ return None
257
+
258
+
259
+ class SafetyCheckResult:
260
+ """Result of a UC safety check."""
261
+
262
+ def __init__(
263
+ self,
264
+ safe: bool = True,
265
+ blocked: bool = False,
266
+ requires_approval: bool = False,
267
+ errors: list[str | None] = None,
268
+ warnings: list[str | None] = None,
269
+ code_hash: str | None = None,
270
+ ):
271
+ self.safe = safe
272
+ self.blocked = blocked
273
+ self.requires_approval = requires_approval
274
+ self.errors = errors or []
275
+ self.warnings = warnings or []
276
+ self.code_hash = code_hash
277
+
278
+
279
+ def check_code_safety(code: str) -> SafetyCheckResult:
280
+ """Perform strict safety analysis on UC tool code.
281
+
282
+ This is a BLOCKING check (not just advisory). Dangerous patterns
283
+ like eval, exec, subprocess, pickle, etc. cause the tool to be
284
+ rejected. Network-library usage requires explicit approval.
285
+
286
+ Args:
287
+ code: Python source code to analyze.
288
+
289
+ Returns:
290
+ SafetyCheckResult indicating whether the code is safe,
291
+ blocked, or requires approval.
292
+ """
293
+ result = SafetyCheckResult(code_hash=compute_code_hash(code))
294
+
295
+ # Parse AST
296
+ try:
297
+ tree = ast.parse(code)
298
+ except SyntaxError as e:
299
+ result.safe = False
300
+ result.errors.append(f"Syntax error: {e}")
301
+ return result
302
+
303
+ dangerous_found: list[str] = []
304
+ approval_required: list[str] = []
305
+
306
+ for node in ast.walk(tree):
307
+ # Check imports
308
+ if isinstance(node, ast.Import):
309
+ for alias in node.names:
310
+ if alias.name in _DANGEROUS_IMPORTS_BLOCK:
311
+ dangerous_found.append(f"import {alias.name}")
312
+ elif alias.name in _DANGEROUS_IMPORTS_APPROVAL:
313
+ approval_required.append(f"import {alias.name}")
314
+
315
+ elif isinstance(node, ast.ImportFrom):
316
+ module = node.module or ""
317
+ for alias in node.names:
318
+ full_name = f"{module}.{alias.name}"
319
+ if (
320
+ module in _DANGEROUS_IMPORTS_BLOCK
321
+ or full_name in _DANGEROUS_IMPORTS_BLOCK
322
+ ):
323
+ dangerous_found.append(f"from {module} import {alias.name}")
324
+ elif (
325
+ module in _DANGEROUS_IMPORTS_APPROVAL
326
+ or full_name in _DANGEROUS_IMPORTS_APPROVAL
327
+ ):
328
+ approval_required.append(f"from {module} import {alias.name}")
329
+
330
+ # Check function calls
331
+ elif isinstance(node, ast.Call):
332
+ func_name = _get_call_name(node)
333
+ if func_name in _DANGEROUS_CALLS_BLOCK:
334
+ line = getattr(node, "lineno", "?")
335
+ dangerous_found.append(f"{func_name}() call at line {line}")
336
+ elif func_name == "open":
337
+ if _is_dangerous_open_call(node):
338
+ line = getattr(node, "lineno", "?")
339
+ dangerous_found.append(f"open() with write mode at line {line}")
340
+
341
+ if dangerous_found:
342
+ result.blocked = True
343
+ result.safe = False
344
+ result.errors.append(
345
+ f"Blocked dangerous patterns: {', '.join(dangerous_found)}"
346
+ )
347
+
348
+ if approval_required and not result.blocked:
349
+ result.requires_approval = True
350
+ result.warnings.append(
351
+ f"Potentially dangerous patterns require approval: {', '.join(approval_required)}"
352
+ )
353
+
354
+ return result
355
+
356
+
357
+ def _get_call_name(node: ast.Call) -> str:
358
+ """Extract the function name from a Call node."""
359
+ if hasattr(node, "func"):
360
+ if isinstance(node.func, ast.Name):
361
+ return node.func.id
362
+ elif isinstance(node.func, ast.Attribute):
363
+ return node.func.attr
364
+ return ""
365
+
366
+
367
+ def _is_dangerous_open_call(node: ast.Call) -> bool:
368
+ """Check if an open() call uses a dangerous (write) mode."""
369
+ if len(node.args) >= 2:
370
+ mode_arg = node.args[1]
371
+ if isinstance(mode_arg, ast.Constant) and isinstance(mode_arg.value, str):
372
+ return mode_arg.value in _DANGEROUS_OPEN_MODES
373
+ for kw in node.keywords:
374
+ if kw.arg == "mode":
375
+ if isinstance(kw.value, ast.Constant) and isinstance(kw.value.value, str):
376
+ return kw.value.value in _DANGEROUS_OPEN_MODES
377
+ return False
378
+
379
+
380
+ class UCApprovalStore:
381
+ """Persistent store for UC tool approvals keyed by code hash."""
382
+
383
+ def __init__(self):
384
+ self._db: dict[str, dict] = {}
385
+ self._loaded = False
386
+
387
+ def _ensure_loaded(self) -> None:
388
+ if not self._loaded:
389
+ self._db = _load_approval_db()
390
+ self._loaded = True
391
+
392
+ def is_approved(self, tool_name: str, code_hash: str) -> bool:
393
+ """Check whether a specific code hash is approved for a tool."""
394
+ self._ensure_loaded()
395
+ key = f"{tool_name}:{code_hash}"
396
+ entry = self._db.get(key)
397
+ if entry is None:
398
+ return False
399
+ stored_hash = entry.get("code_hash")
400
+ if stored_hash != code_hash:
401
+ return False
402
+ return entry.get("approved", False)
403
+
404
+ def approve(self, tool_name: str, code_hash: str) -> None:
405
+ """Explicitly approve a tool code hash."""
406
+ self._ensure_loaded()
407
+ key = f"{tool_name}:{code_hash}"
408
+ self._db[key] = {
409
+ "tool_name": tool_name,
410
+ "code_hash": code_hash,
411
+ "approved": True,
412
+ }
413
+ _save_approval_db(self._db)
414
+ logger.info(f"UC tool approved: {tool_name} (hash={code_hash[:16]}...)")
415
+
416
+ def revoke(self, tool_name: str, code_hash: str) -> None:
417
+ """Revoke approval for a tool code hash."""
418
+ self._ensure_loaded()
419
+ key = f"{tool_name}:{code_hash}"
420
+ if key in self._db:
421
+ del self._db[key]
422
+ _save_approval_db(self._db)
423
+ logger.info(f"UC tool approval revoked: {tool_name}")
424
+
425
+
426
+ def is_path_within_uc_dir(file_path: Path, uc_dir: Path) -> bool:
427
+ """Verify that file_path is safely contained within uc_dir.
428
+
429
+ Resolves both paths and checks for symlink escape.
430
+
431
+ Returns:
432
+ True if file_path is within uc_dir, False otherwise.
433
+ """
434
+ try:
435
+ resolved_file = file_path.resolve()
436
+ resolved_dir = uc_dir.resolve()
437
+ resolved_file.relative_to(resolved_dir)
438
+ return True
439
+ except ValueError, OSError:
440
+ return False