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,206 @@
1
+ # cython: language_level=3
2
+ """UTF-8 byte-stream adapter that wraps a StreamTextParser.
3
+
4
+ Buffers partial code points across chunk boundaries and rolls back entire
5
+ chunks on invalid UTF-8 so the wrapped parser never sees malformed text.
6
+ """
7
+
8
+ from typing import TypeVar
9
+
10
+ from code_muse.stream_parser.stream_text_chunk import StreamTextChunk
11
+ from code_muse.stream_parser.stream_text_parser import StreamTextParser
12
+
13
+ T = TypeVar("T")
14
+
15
+
16
+ class Utf8StreamParserError(Exception):
17
+ """Base error for Utf8StreamParser."""
18
+
19
+ pass
20
+
21
+
22
+ class InvalidUtf8(Utf8StreamParserError):
23
+ """Raised when a pushed byte chunk contains an invalid UTF-8 sequence.
24
+
25
+ The chunk is rolled back; the parser's pending buffer is restored to its
26
+ state before the chunk was pushed.
27
+ """
28
+
29
+ def __init__(self, valid_up_to: int, error_len: int) -> None:
30
+ self.valid_up_to = valid_up_to
31
+ self.error_len = error_len
32
+ super().__init__(
33
+ f"invalid UTF-8 in streamed bytes at offset {valid_up_to} "
34
+ f"(error length {error_len})"
35
+ )
36
+
37
+
38
+ class IncompleteUtf8AtEof(Utf8StreamParserError):
39
+ """Raised at finish() or into_inner() when an incomplete code point remains."""
40
+
41
+ def __init__(self) -> None:
42
+ super().__init__("incomplete UTF-8 code point at end of stream")
43
+
44
+
45
+ class Utf8StreamParser:
46
+ """Wraps a StreamTextParser and accepts raw bytes.
47
+
48
+ * Buffers incomplete UTF-8 code points across chunk boundaries.
49
+ * On invalid UTF-8, rolls back the **entire** chunk and raises.
50
+ * On incomplete-but-valid UTF-8, processes the valid prefix and keeps
51
+ the incomplete tail buffered.
52
+ * ``finish()`` flushes pending bytes; raises if a code point is incomplete.
53
+ * ``into_inner()`` returns the wrapped parser only when no bytes are pending.
54
+ * ``into_inner_lossy()`` returns the wrapped parser, dropping pending bytes.
55
+
56
+ The wrapped parser never receives malformed text.
57
+ """
58
+
59
+ def __init__(self, inner: StreamTextParser[T]) -> None:
60
+ self.inner = inner
61
+ self._pending_utf8: bytearray = bytearray()
62
+
63
+ def push_bytes(self, const unsigned char[:] chunk) -> StreamTextChunk[T]:
64
+ """Feed a new byte chunk.
65
+
66
+ Args:
67
+ chunk: Raw bytes to decode and forward to the inner parser.
68
+
69
+ Returns:
70
+ Visible text and extracted payloads from the inner parser.
71
+
72
+ Raises:
73
+ InvalidUtf8: If the chunk (combined with any previously buffered
74
+ partial code point) contains an invalid UTF-8 sequence. The
75
+ entire chunk is rolled back so the buffer is restored to its
76
+ pre-call state.
77
+ """
78
+ cdef int old_len
79
+ cdef int valid_up_to
80
+ cdef bint is_incomplete
81
+
82
+ # Fast path: no pending bytes and chunk decodes cleanly.
83
+ if not self._pending_utf8:
84
+ try:
85
+ text = bytes(chunk).decode("utf-8")
86
+ return self.inner.push_str(text)
87
+ except UnicodeDecodeError as err:
88
+ is_incomplete = (
89
+ err.reason == "unexpected end of data" and err.end == len(chunk)
90
+ )
91
+ if not is_incomplete:
92
+ raise InvalidUtf8(err.start, err.end - err.start) from err
93
+ # Buffer the chunk; valid prefix will be consumed below.
94
+ self._pending_utf8.extend(chunk)
95
+ valid_up_to = err.start
96
+ if valid_up_to == 0:
97
+ return StreamTextChunk()
98
+ text = bytes(chunk[:valid_up_to]).decode("utf-8")
99
+ out = self.inner.push_str(text)
100
+ del self._pending_utf8[:valid_up_to]
101
+ return out
102
+
103
+ # Slow path: append to existing pending buffer.
104
+ old_len = len(self._pending_utf8)
105
+ self._pending_utf8.extend(chunk)
106
+
107
+ try:
108
+ text = self._pending_utf8.decode("utf-8")
109
+ except UnicodeDecodeError as err:
110
+ # Distinguish "invalid byte sequence" from "incomplete at end".
111
+ # In Python an incomplete sequence at the very end reports
112
+ # ``reason == "unexpected end of data"`` and ``err.end`` equals
113
+ # ``len(self._pending_utf8)``. Anything else is an actual error.
114
+ is_incomplete = err.reason == "unexpected end of data" and err.end == len(
115
+ self._pending_utf8
116
+ )
117
+
118
+ if not is_incomplete:
119
+ # Invalid sequence somewhere in the buffer. Roll back the
120
+ # entire chunk so the inner parser never sees malformed data.
121
+ del self._pending_utf8[old_len:]
122
+ raise InvalidUtf8(err.start, err.end - err.start) from err
123
+
124
+ # Incomplete code point at the end of the buffer.
125
+ valid_up_to = err.start
126
+ if valid_up_to == 0:
127
+ # Nothing valid to forward yet.
128
+ return StreamTextChunk()
129
+
130
+ # Process the valid prefix. Defend against the edge case where
131
+ # the prefix itself fails to decode (nested error).
132
+ try:
133
+ text = bytes(self._pending_utf8[:valid_up_to]).decode("utf-8")
134
+ except UnicodeDecodeError as nested_err:
135
+ del self._pending_utf8[old_len:]
136
+ raise InvalidUtf8(
137
+ nested_err.start, nested_err.end - nested_err.start
138
+ ) from nested_err
139
+
140
+ out = self.inner.push_str(text)
141
+ del self._pending_utf8[:valid_up_to]
142
+ return out
143
+
144
+ # Full buffer decoded cleanly.
145
+ out = self.inner.push_str(text)
146
+ self._pending_utf8.clear()
147
+ return out
148
+
149
+ def finish(self) -> StreamTextChunk[T]:
150
+ """Flush any buffered bytes at end-of-stream.
151
+
152
+ Returns:
153
+ Any visible text and extracted payloads produced by the inner
154
+ parser for the final pending bytes.
155
+
156
+ Raises:
157
+ IncompleteUtf8AtEof: If an incomplete UTF-8 code point remains
158
+ in the buffer. The bytes are **not** consumed; they stay
159
+ buffered so the caller can decide what to do next.
160
+ """
161
+ if not self._pending_utf8:
162
+ return self.inner.finish()
163
+
164
+ # Attempt to decode whatever is left. If it is incomplete, raise.
165
+ try:
166
+ text = self._pending_utf8.decode("utf-8")
167
+ except UnicodeDecodeError as err:
168
+ if err.reason == "unexpected end of data" and err.end == len(
169
+ self._pending_utf8
170
+ ):
171
+ raise IncompleteUtf8AtEof() from err
172
+ # Should be unreachable for a previously-validated buffer, but
173
+ # treat it as invalid UTF-8.
174
+ raise InvalidUtf8(err.start, err.end - err.start) from err
175
+
176
+ out = self.inner.push_str(text)
177
+ self._pending_utf8.clear()
178
+ tail = self.inner.finish()
179
+ return StreamTextChunk(
180
+ visible_text=out.visible_text + tail.visible_text,
181
+ extracted=out.extracted + tail.extracted,
182
+ )
183
+
184
+ def into_inner(self) -> StreamTextParser[T]:
185
+ """Return the wrapped parser only if no bytes are pending.
186
+
187
+ Returns:
188
+ The inner StreamTextParser instance.
189
+
190
+ Raises:
191
+ IncompleteUtf8AtEof: If there are pending bytes (incomplete code
192
+ point) in the buffer.
193
+ """
194
+ if self._pending_utf8:
195
+ raise IncompleteUtf8AtEof()
196
+ return self.inner
197
+
198
+ def into_inner_lossy(self) -> StreamTextParser[T]:
199
+ """Return the wrapped parser, discarding any pending bytes.
200
+
201
+ Returns:
202
+ The inner StreamTextParser instance. Any incomplete UTF-8 code
203
+ point buffered across previous chunks is silently dropped.
204
+ """
205
+ self._pending_utf8.clear()
206
+ return self.inner
@@ -0,0 +1,308 @@
1
+ import asyncio
2
+ import atexit
3
+ import hashlib
4
+ import logging
5
+ import pathlib
6
+ import threading
7
+
8
+ # FREE-THREADED: ThreadPoolExecutor is compatible with free-threaded Python 3.14 —
9
+ # no GIL contention for I/O-bound summarization work.
10
+ from concurrent.futures import ThreadPoolExecutor
11
+ from typing import Any
12
+
13
+ from pydantic_ai import Agent
14
+
15
+ from code_muse.config import get_summarization_model_name
16
+ from code_muse.model_factory import ModelFactory, make_model_settings
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ # Keep a module-level agent reference to avoid rebuilding per call
21
+ _summarization_agent = None
22
+ # FREE-THREADED: _agent_lock guards sync-only agent cache access.
23
+ _agent_lock = threading.Lock()
24
+
25
+ # P2-05/PERF-05: track the model name the cached agent was built for
26
+ _cached_model_name: str | None = None
27
+
28
+ # Safe sync runner for async agent.run calls
29
+ # Avoids "event loop is already running" by offloading to a separate thread loop when needed
30
+ _thread_pool: ThreadPoolExecutor | None = None
31
+
32
+ # Reload counter
33
+ _reload_count = 0
34
+
35
+
36
+ # ---------------------------------------------------------------------------
37
+ # P2-05/PERF-05: Model config cache with mtime invalidation
38
+ # ---------------------------------------------------------------------------
39
+
40
+
41
+ def _models_config_fingerprint() -> tuple[float, str]:
42
+ """Compute a lightweight fingerprint of all model config sources.
43
+
44
+ Returns (max_mtime, content_hash) — if either changes, the cached
45
+ config is stale and must be reloaded.
46
+ """
47
+ source_paths: list[pathlib.Path] = []
48
+
49
+ # Bundled models.json is always loaded
50
+ bundled = pathlib.Path(__file__).parent / "models.json"
51
+ source_paths.append(bundled)
52
+
53
+ # Extra model sources (mirrors ModelFactory.load_config)
54
+ try:
55
+ from code_muse.config import (
56
+ CHATGPT_MODELS_FILE,
57
+ CLAUDE_MODELS_FILE,
58
+ COPILOT_MODELS_FILE,
59
+ EXTRA_MODELS_FILE,
60
+ GEMINI_MODELS_FILE,
61
+ MODELS_FILE,
62
+ )
63
+
64
+ for p in (
65
+ MODELS_FILE,
66
+ EXTRA_MODELS_FILE,
67
+ CHATGPT_MODELS_FILE,
68
+ CLAUDE_MODELS_FILE,
69
+ GEMINI_MODELS_FILE,
70
+ COPILOT_MODELS_FILE,
71
+ ):
72
+ source_paths.append(pathlib.Path(p))
73
+ except Exception:
74
+ pass
75
+
76
+ max_mtime = 0.0
77
+ hasher = hashlib.md5(usedforsecurity=False)
78
+ for sp in source_paths:
79
+ try:
80
+ if sp.exists():
81
+ stat = sp.stat()
82
+ max_mtime = max(max_mtime, stat.st_mtime)
83
+ # Hash file contents (or just size+mtime as a cheap proxy)
84
+ hasher.update(f"{sp}:{stat.st_size}:{stat.st_mtime}".encode())
85
+ except OSError:
86
+ pass
87
+
88
+ return max_mtime, hasher.hexdigest()
89
+
90
+
91
+ # Module-level model config cache: (config_dict, fingerprint)
92
+ _models_config_cache: tuple[dict[str, Any | None], tuple[float, str | None]] = (
93
+ None,
94
+ None,
95
+ )
96
+ # FREE-THREADED: _models_config_lock guards sync-only config cache access.
97
+ _models_config_lock = threading.Lock()
98
+
99
+
100
+ def get_cached_models_config() -> dict[str, Any]:
101
+ """Return the models config, using a cache invalidated by mtime/hash changes.
102
+
103
+ This avoids re-reading ``models.json`` and extra model files on every call
104
+ to ``ModelFactory.load_config()`` when nothing has changed. The cache is
105
+ invalidated when any source file's mtime changes.
106
+
107
+ Falls back to ``ModelFactory.load_config()`` on any error.
108
+ """
109
+ global _models_config_cache
110
+
111
+ fingerprint = _models_config_fingerprint()
112
+
113
+ with _models_config_lock:
114
+ cached_config, cached_fp = _models_config_cache
115
+ if cached_config is not None and cached_fp == fingerprint:
116
+ return cached_config
117
+
118
+ # Cache miss — reload. Let exceptions propagate so callers
119
+ # (including reload_summarization_agent) see the same errors they
120
+ # would have seen without the cache.
121
+ config = ModelFactory.load_config()
122
+ _models_config_cache = (config, fingerprint)
123
+ return config
124
+
125
+
126
+ def invalidate_models_config_cache() -> None:
127
+ """Force the next ``get_cached_models_config()`` call to reload.
128
+
129
+ Call this when settings or model files are known to have changed
130
+ (e.g. after a ``/set`` command that modifies model config).
131
+ """
132
+ global _models_config_cache
133
+ with _models_config_lock:
134
+ _models_config_cache = (None, None)
135
+
136
+
137
+ def _ensure_thread_pool():
138
+ global _thread_pool
139
+ # Check if pool is None OR if it's been shutdown
140
+ if _thread_pool is None or _thread_pool._shutdown:
141
+ # FREE-THREADED: ThreadPoolExecutor is compatible with free-threaded Python 3.14.
142
+ _thread_pool = ThreadPoolExecutor(
143
+ max_workers=1, thread_name_prefix="summarizer-loop"
144
+ )
145
+ return _thread_pool
146
+
147
+
148
+ def _shutdown_thread_pool():
149
+ global _thread_pool
150
+ if _thread_pool is not None:
151
+ _thread_pool.shutdown(wait=False)
152
+ _thread_pool = None
153
+
154
+
155
+ atexit.register(_shutdown_thread_pool)
156
+
157
+
158
+ async def _run_agent_async(agent: Agent, prompt: str, message_history: list):
159
+ return await agent.run(prompt, message_history=message_history)
160
+
161
+
162
+ class SummarizationError(Exception):
163
+ """Raised when summarization fails with details about the failure."""
164
+
165
+ def __init__(self, message: str, original_error: Exception | None = None):
166
+ self.original_error = original_error
167
+ super().__init__(message)
168
+
169
+
170
+ def run_summarization_sync(prompt: str, message_history: list) -> list:
171
+ """Run the summarization agent synchronously.
172
+
173
+ Raises:
174
+ SummarizationError: If summarization fails for any reason.
175
+ """
176
+ try:
177
+ agent = get_summarization_agent()
178
+ except Exception as e:
179
+ raise SummarizationError(
180
+ f"Failed to initialize summarization agent: {type(e).__name__}: {e}",
181
+ original_error=e,
182
+ ) from e
183
+
184
+ # Handle claude-code models: prepend system prompt to user prompt
185
+ from code_muse.model_utils import prepare_prompt_for_model
186
+
187
+ model_name = get_summarization_model_name()
188
+ prepared = prepare_prompt_for_model(
189
+ model_name, _get_summarization_instructions(), prompt
190
+ )
191
+ prompt = prepared.user_prompt
192
+
193
+ def _run_in_thread():
194
+ """
195
+ Run the async agent in a dedicated thread with its own event loop.
196
+ Uses run_until_complete instead of asyncio.run to avoid shutting down
197
+ the default executor (which may break plugins in the main thread).
198
+ Does NOT touch global event loop state.
199
+ """
200
+ loop = asyncio.new_event_loop()
201
+ try:
202
+ coro = agent.run(prompt, message_history=message_history)
203
+ return loop.run_until_complete(coro)
204
+ finally:
205
+ # Clean up without shutting down the default executor
206
+ try:
207
+ # Cancel pending tasks
208
+ pending = asyncio.all_tasks(loop)
209
+ for task in pending:
210
+ task.cancel()
211
+ if pending:
212
+ # NOTE: asyncio.gather for already-running tasks; TaskGroup cannot adopt existing tasks.
213
+ loop.run_until_complete(
214
+ asyncio.gather(*pending, return_exceptions=True)
215
+ )
216
+ loop.run_until_complete(loop.shutdown_asyncgens())
217
+ finally:
218
+ loop.close()
219
+
220
+ try:
221
+ # Always use thread pool since we're likely in an existing event loop
222
+ pool = _ensure_thread_pool()
223
+ result = pool.submit(_run_in_thread).result()
224
+ return result.new_messages()
225
+ except Exception as e:
226
+ error_type = type(e).__name__
227
+ error_msg = str(e) if str(e) else "(no details available)"
228
+ raise SummarizationError(
229
+ f"LLM call failed during summarization: [{error_type}] {error_msg}",
230
+ original_error=e,
231
+ ) from e
232
+
233
+
234
+ def _get_summarization_instructions() -> str:
235
+ """Get the system instructions for the summarization agent."""
236
+ return """You are a message summarization expert. Your task is to summarize conversation messages
237
+ while preserving important context and information. The summaries should be concise but capture the essential content
238
+ and intent of the original messages. This is to help manage token usage in a conversation history
239
+ while maintaining context for the AI to continue the conversation effectively.
240
+
241
+ When summarizing:
242
+ 1. Keep summary concise but informative
243
+ 2. Preserve important context and key information and decisions
244
+ 3. Keep any important technical details
245
+ 4. Don't summarize the system message
246
+ 5. Make sure all tool calls and responses are summarized, as they are vital
247
+ 6. Focus on token usage efficiency and system message preservation"""
248
+
249
+
250
+ def reload_summarization_agent():
251
+ """Create a specialized agent for summarizing messages when context limit is reached."""
252
+ from code_muse.model_utils import prepare_prompt_for_model
253
+
254
+ # Always bust the cache on explicit reload — the caller expects fresh config
255
+ invalidate_models_config_cache()
256
+ models_config = get_cached_models_config()
257
+ model_name = get_summarization_model_name()
258
+ model = ModelFactory.get_model(model_name, models_config)
259
+
260
+ # Handle claude-code models: swap instructions (prompt prepending happens in run_summarization_sync)
261
+ instructions = _get_summarization_instructions()
262
+ prepared = prepare_prompt_for_model(
263
+ model_name, instructions, "", prepend_system_to_user=False
264
+ )
265
+ instructions = prepared.instructions
266
+
267
+ model_settings = make_model_settings(model_name)
268
+
269
+ agent = Agent(
270
+ model=model,
271
+ instructions=instructions,
272
+ output_type=str,
273
+ retries=1, # Fewer retries for summarization
274
+ model_settings=model_settings,
275
+ )
276
+ # NOTE: We intentionally don't wrap the summarization agent.
277
+ # Summarization is a simple one-shot call that doesn't need durable execution,
278
+ # and wrapping can cause async event loop conflicts with run_sync().
279
+ return agent
280
+
281
+
282
+ def get_summarization_agent(force_reload=False):
283
+ """Retrieve the summarization agent, caching across calls.
284
+
285
+ P2-05/PERF-05: The default is now ``force_reload=False``. The agent is
286
+ rebuilt only when:
287
+ - ``force_reload=True`` is explicitly passed
288
+ - The summarization model name has changed since the last build
289
+ - No agent has been built yet (first call)
290
+
291
+ Args:
292
+ force_reload: When True, unconditionally rebuild the agent.
293
+
294
+ Returns:
295
+ A ``pydantic_ai.Agent`` configured for summarization.
296
+ """
297
+ global _summarization_agent, _cached_model_name
298
+ current_model = get_summarization_model_name()
299
+ with _agent_lock:
300
+ needs_reload = (
301
+ force_reload
302
+ or _summarization_agent is None
303
+ or _cached_model_name != current_model
304
+ )
305
+ if needs_reload:
306
+ _summarization_agent = reload_summarization_agent()
307
+ _cached_model_name = current_model
308
+ return _summarization_agent