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,91 @@
1
+ """Configuration constants for the GitHub Copilot auth plugin."""
2
+
3
+ from pathlib import Path
4
+ from typing import Any
5
+
6
+ from code_muse import config
7
+
8
+ # GitHub Copilot auth configuration
9
+ COPILOT_AUTH_CONFIG: dict[str, Any] = {
10
+ # Copilot session-token endpoints
11
+ "github_token_url": "https://api.github.com/copilot_internal/v2/token",
12
+ # GHE template: replace {host}
13
+ "ghe_token_url_template": "https://{host}/api/v3/copilot_internal/v2/token",
14
+ # OpenAI-compatible Copilot chat API (default; overridden per-host at runtime)
15
+ "api_base_url": "https://api.githubcopilot.com",
16
+ # Model prefix in Muse
17
+ "prefix": "copilot-",
18
+ "default_context_length": 128000,
19
+ # Headers expected by the Copilot API
20
+ "editor_version": "JetBrains-IU/2024.3",
21
+ "editor_plugin_version": "copilot/2.0.0",
22
+ "copilot_integration_id": "vscode-chat",
23
+ "openai_intent": "conversation-panel",
24
+ }
25
+
26
+ # GitHub Device Flow configuration — browser-based auth with no IDE required.
27
+ # Uses the VS Code Copilot extension's public client ID which supports Device Flow.
28
+ DEVICE_FLOW_CONFIG: dict[str, Any] = {
29
+ "client_id": "Iv1.b507a08c87ecfe98",
30
+ "scope": "read:user",
31
+ # Endpoint templates — {host} is replaced at runtime
32
+ "device_code_url": "https://{host}/login/device/code",
33
+ "access_token_url": "https://{host}/login/oauth/access_token",
34
+ # Polling defaults (server may override via response)
35
+ "default_poll_interval": 5,
36
+ "grant_type": "urn:ietf:params:oauth:grant-type:device_code",
37
+ }
38
+
39
+ # Models known to be available via Copilot (costs are $0 via Copilot).
40
+ # The /copilot-login flow will also try to fetch the live model list.
41
+ DEFAULT_COPILOT_MODELS = [
42
+ "gpt-4o",
43
+ "gpt-4.1",
44
+ "gpt-4.1-mini",
45
+ "o4-mini",
46
+ "o3",
47
+ "claude-opus-4.6",
48
+ "claude-opus-4",
49
+ "claude-sonnet-4",
50
+ "claude-sonnet-4.5",
51
+ "claude-haiku-4.5",
52
+ "gemini-2.5-pro",
53
+ "gemini-2.5-flash",
54
+ ]
55
+
56
+ # Per-model context-length overrides (tokens).
57
+ COPILOT_MODEL_CONTEXT_LENGTHS: dict[str, int] = {
58
+ "gpt-4o": 64000,
59
+ "gpt-4.1": 128000,
60
+ "gpt-4.1-mini": 128000,
61
+ "o4-mini": 128000,
62
+ "o3": 128000,
63
+ "claude-opus-4.6": 200000,
64
+ "claude-opus-4": 200000,
65
+ "claude-sonnet-4": 128000,
66
+ "claude-sonnet-4.5": 128000,
67
+ "claude-haiku-4.5": 128000,
68
+ "gemini-2.5-pro": 128000,
69
+ "gemini-2.5-flash": 128000,
70
+ }
71
+
72
+
73
+ def get_copilot_models_path() -> Path:
74
+ """Return path for persisted copilot_models.json (XDG_DATA_HOME)."""
75
+ data_dir = Path(config.DATA_DIR)
76
+ data_dir.mkdir(parents=True, exist_ok=True, mode=0o700)
77
+ return data_dir / "copilot_models.json"
78
+
79
+
80
+ def get_session_cache_path() -> Path:
81
+ """Return path for caching the short-lived Copilot session token."""
82
+ data_dir = Path(config.DATA_DIR)
83
+ data_dir.mkdir(parents=True, exist_ok=True, mode=0o700)
84
+ return data_dir / "copilot_session.json"
85
+
86
+
87
+ def get_device_token_storage_path() -> Path:
88
+ """Return path for storing tokens obtained via the GitHub Device Flow."""
89
+ data_dir = Path(config.DATA_DIR)
90
+ data_dir.mkdir(parents=True, exist_ok=True, mode=0o700)
91
+ return data_dir / "copilot_device_tokens.json"
@@ -0,0 +1,409 @@
1
+ """Reasoning-opaque round-trip interceptor for Copilot Claude models.
2
+
3
+ The Copilot API returns two fields on Claude assistant messages:
4
+
5
+ - ``reasoning_text``: the model's chain-of-thought (human-readable)
6
+ - ``reasoning_opaque``: encrypted round-trip blob (**must** be echoed back)
7
+
8
+ pydantic-ai's ``openai_chat_send_back_thinking_parts="field"`` mode preserves
9
+ ``reasoning_text`` across tool calls, but it doesn't know about
10
+ ``reasoning_opaque``. The Copilot API returns **400 Bad Request** if
11
+ ``reasoning_text`` is sent without the accompanying ``reasoning_opaque``.
12
+
13
+ This module monkey-patches the httpx client to transparently:
14
+
15
+ 1. Capture ``reasoning_opaque`` (keyed by ``reasoning_text``) from responses
16
+ 2. Inject the matching ``reasoning_opaque`` into outgoing request messages
17
+
18
+ The approach mirrors the ``ChatGPTCodexAsyncClient`` pattern already in the codebase.
19
+ """
20
+
21
+ import hashlib
22
+ import json
23
+ import logging
24
+ from typing import Any
25
+
26
+ import httpx
27
+ from httpx import AsyncByteStream
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+ # Cap the cache so it can't grow forever across long sessions.
32
+ _MAX_CACHE_ENTRIES = 256
33
+
34
+
35
+ # ---------------------------------------------------------------------------
36
+ # Helpers
37
+ # ---------------------------------------------------------------------------
38
+
39
+
40
+ def _text_key(text: str) -> str:
41
+ """Short SHA-256 prefix — enough to avoid collisions in practice."""
42
+ return hashlib.sha256(text.encode("utf-8")).hexdigest()[:32]
43
+
44
+
45
+ # ---------------------------------------------------------------------------
46
+ # Stream wrapper — captures opaque data as SSE events flow through
47
+ # ---------------------------------------------------------------------------
48
+
49
+
50
+ class _OpaqueCapturingStream(AsyncByteStream):
51
+ """Async byte-stream wrapper that taps ``reasoning_opaque`` from SSE.
52
+
53
+ Yields every byte unchanged so downstream consumers (the OpenAI SDK)
54
+ see the exact same data. Internally it buffers bytes, splits SSE
55
+ lines, parses JSON, and pairs ``reasoning_text`` chunks with
56
+ ``reasoning_opaque`` chunks for storage in *opaque_cache*.
57
+
58
+ Inherits from ``httpx.AsyncByteStream`` so that
59
+ ``httpx.Response.aclose()`` recognises us as an async stream and
60
+ doesn't blow up with *"Attempted to call an async close on an sync
61
+ stream"*. Ask me how I know.
62
+ """
63
+
64
+ def __init__(
65
+ self,
66
+ inner_stream: Any,
67
+ opaque_cache: dict[str, str],
68
+ thinking_field: str,
69
+ ):
70
+ self._inner = inner_stream
71
+ self._opaque_cache = opaque_cache
72
+ self._thinking_field = thinking_field
73
+ self._buffer = ""
74
+ self._text_parts: list[str] = []
75
+ self._opaque_parts: list[str] = []
76
+
77
+ # -- async-iterator protocol ------------------------------------------
78
+
79
+ def __aiter__(self):
80
+ return self._iter_impl()
81
+
82
+ async def _iter_impl(self):
83
+ try:
84
+ async for chunk in self._inner:
85
+ self._feed(chunk)
86
+ yield chunk
87
+ finally:
88
+ self._flush()
89
+
90
+ async def aclose(self):
91
+ self._flush()
92
+ if hasattr(self._inner, "aclose"):
93
+ await self._inner.aclose()
94
+
95
+ # Fallback for any attributes we don't explicitly handle.
96
+ def __getattr__(self, name: str):
97
+ return getattr(self._inner, name)
98
+
99
+ # -- SSE parsing -------------------------------------------------------
100
+
101
+ def _feed(self, chunk: bytes) -> None:
102
+ self._buffer += chunk.decode("utf-8", errors="replace")
103
+ self._process_buffer()
104
+
105
+ def _process_buffer(self) -> None:
106
+ while "\n" in self._buffer:
107
+ line, self._buffer = self._buffer.split("\n", 1)
108
+ line = line.strip()
109
+ if not line.startswith("data: "):
110
+ continue
111
+ data_str = line[6:]
112
+ if data_str == "[DONE]":
113
+ self._flush()
114
+ continue
115
+ try:
116
+ event = json.loads(data_str)
117
+ self._extract_from_event(event)
118
+ except json.JSONDecodeError, TypeError:
119
+ pass
120
+
121
+ def _extract_from_event(self, event: dict) -> None:
122
+ for choice in event.get("choices", []):
123
+ # Streaming deltas
124
+ delta = choice.get("delta") or {}
125
+ self._collect(delta)
126
+ # Non-streaming message (fallback)
127
+ message = choice.get("message") or {}
128
+ self._collect(message)
129
+ # Flush when the model signals it's done with this turn
130
+ if choice.get("finish_reason"):
131
+ self._flush()
132
+
133
+ def _collect(self, obj: dict) -> None:
134
+ text_chunk = obj.get(self._thinking_field)
135
+ if text_chunk:
136
+ self._text_parts.append(text_chunk)
137
+ opaque_chunk = obj.get("reasoning_opaque")
138
+ if opaque_chunk:
139
+ self._opaque_parts.append(opaque_chunk)
140
+
141
+ def _flush(self) -> None:
142
+ if self._opaque_parts and self._text_parts:
143
+ text = "".join(self._text_parts)
144
+ opaque = "".join(self._opaque_parts)
145
+ key = _text_key(text)
146
+ self._opaque_cache[key] = opaque
147
+ logger.debug(
148
+ "Captured reasoning_opaque (%d chars) for key %.8s…",
149
+ len(opaque),
150
+ key,
151
+ )
152
+ # Evict oldest entry if we exceed the cap.
153
+ while len(self._opaque_cache) > _MAX_CACHE_ENTRIES:
154
+ first_key = next(iter(self._opaque_cache))
155
+ del self._opaque_cache[first_key]
156
+ self._text_parts = []
157
+ self._opaque_parts = []
158
+
159
+
160
+ # ---------------------------------------------------------------------------
161
+ # Non-streaming capture (safety net)
162
+ # ---------------------------------------------------------------------------
163
+
164
+
165
+ def _capture_from_content(
166
+ content: bytes,
167
+ opaque_cache: dict[str, str],
168
+ thinking_field: str,
169
+ ) -> None:
170
+ """Extract ``reasoning_opaque`` from an already-read response body."""
171
+ try:
172
+ data = json.loads(content)
173
+ for choice in data.get("choices", []):
174
+ msg = choice.get("message") or {}
175
+ text = msg.get(thinking_field)
176
+ opaque = msg.get("reasoning_opaque")
177
+ if text and opaque:
178
+ opaque_cache[_text_key(text)] = opaque
179
+ except json.JSONDecodeError, TypeError, AttributeError:
180
+ pass
181
+
182
+
183
+ # ---------------------------------------------------------------------------
184
+ # Request-side injection
185
+ # ---------------------------------------------------------------------------
186
+
187
+
188
+ def _rebuild_request_body(
189
+ request: httpx.Request,
190
+ body: dict,
191
+ client: httpx.AsyncClient,
192
+ ) -> None:
193
+ """Replace the request body in-place (mirrors ChatGPTCodexAsyncClient)."""
194
+ new_body = json.dumps(body).encode("utf-8")
195
+ rebuilt = client.build_request(
196
+ method=request.method,
197
+ url=request.url,
198
+ headers=request.headers,
199
+ content=new_body,
200
+ )
201
+ if hasattr(rebuilt, "_content"):
202
+ request._content = rebuilt._content # type: ignore[attr-defined]
203
+ if hasattr(rebuilt, "stream"):
204
+ request.stream = rebuilt.stream
205
+ if hasattr(rebuilt, "extensions"):
206
+ request.extensions = rebuilt.extensions
207
+ request.headers["Content-Length"] = str(len(new_body))
208
+
209
+
210
+ def _inject_opaque_into_request(
211
+ request: httpx.Request,
212
+ opaque_cache: dict[str, str],
213
+ client: httpx.AsyncClient,
214
+ thinking_field: str,
215
+ ) -> None:
216
+ """Add stored ``reasoning_opaque`` to assistant messages that need it.
217
+
218
+ **Prevention layer**: if we can't find a matching opaque for a
219
+ ``reasoning_text``, we strip that field entirely rather than sending
220
+ it bare (which would trigger a 400).
221
+ """
222
+ try:
223
+ body_bytes = request.content
224
+ if not body_bytes:
225
+ return
226
+
227
+ body = json.loads(body_bytes)
228
+ if not isinstance(body, dict):
229
+ return
230
+
231
+ messages = body.get("messages")
232
+ if not messages:
233
+ return
234
+
235
+ modified = False
236
+ injected = 0
237
+ stripped = 0
238
+
239
+ for msg in messages:
240
+ if not isinstance(msg, dict):
241
+ continue
242
+ if msg.get("role") != "assistant":
243
+ continue
244
+ if thinking_field not in msg:
245
+ continue
246
+ if "reasoning_opaque" in msg:
247
+ # Already has opaque — don't touch.
248
+ continue
249
+
250
+ key = _text_key(msg[thinking_field])
251
+ opaque = opaque_cache.get(key)
252
+ if opaque:
253
+ msg["reasoning_opaque"] = opaque
254
+ modified = True
255
+ injected += 1
256
+ else:
257
+ # SAFETY: No matching opaque → strip reasoning_text to
258
+ # prevent the 400. Losing thinking context is better
259
+ # than crashing the conversation.
260
+ del msg[thinking_field]
261
+ modified = True
262
+ stripped += 1
263
+ logger.debug(
264
+ "Stripped orphaned %s (no opaque in cache)",
265
+ thinking_field,
266
+ )
267
+
268
+ if not modified:
269
+ return
270
+
271
+ _rebuild_request_body(request, body, client)
272
+
273
+ if injected:
274
+ logger.debug(
275
+ "Injected reasoning_opaque into %d assistant message(s)",
276
+ injected,
277
+ )
278
+ if stripped:
279
+ logger.debug(
280
+ "Stripped %d orphaned %s field(s) (cache miss)",
281
+ stripped,
282
+ thinking_field,
283
+ )
284
+ except Exception as exc:
285
+ # Never crash the real request.
286
+ logger.debug("Failed to inject reasoning_opaque: %s", exc)
287
+
288
+
289
+ def _strip_all_reasoning_fields(
290
+ request: httpx.Request,
291
+ client: httpx.AsyncClient,
292
+ thinking_field: str,
293
+ ) -> bool:
294
+ """Remove ALL reasoning fields from the request body.
295
+
296
+ **Recovery layer**: called after a 400 to retry without any reasoning
297
+ context. Degrades gracefully to the old ``send_back_thinking_parts=False``
298
+ behaviour — thinking disappears after tool calls, but the conversation
299
+ keeps working.
300
+
301
+ Returns True if the body was modified.
302
+ """
303
+ try:
304
+ body_bytes = request.content
305
+ if not body_bytes:
306
+ return False
307
+
308
+ body = json.loads(body_bytes)
309
+ if not isinstance(body, dict):
310
+ return False
311
+
312
+ messages = body.get("messages")
313
+ if not messages:
314
+ return False
315
+
316
+ modified = False
317
+ for msg in messages:
318
+ if not isinstance(msg, dict):
319
+ continue
320
+ if msg.get("role") != "assistant":
321
+ continue
322
+ for field in (thinking_field, "reasoning_opaque"):
323
+ if field in msg:
324
+ del msg[field]
325
+ modified = True
326
+
327
+ if modified:
328
+ _rebuild_request_body(request, body, client)
329
+
330
+ return modified
331
+ except Exception as exc:
332
+ logger.debug("Failed to strip reasoning fields: %s", exc)
333
+ return False
334
+
335
+
336
+ # ---------------------------------------------------------------------------
337
+ # Public API — single entry-point
338
+ # ---------------------------------------------------------------------------
339
+
340
+
341
+ def patch_client_for_reasoning_opaque(
342
+ client: httpx.AsyncClient,
343
+ thinking_field: str = "reasoning_text",
344
+ ) -> None:
345
+ """Monkey-patch *client* to round-trip ``reasoning_opaque`` transparently.
346
+
347
+ Call **after** creating the client but **before** handing it to
348
+ ``OpenAIProvider``. Works with plain ``httpx.AsyncClient`` and the
349
+ ``RetryingAsyncClient`` subclass returned by ``create_async_client``.
350
+
351
+ Args:
352
+ client: The httpx async client to patch.
353
+ thinking_field: JSON field name that carries the thinking content
354
+ (default ``"reasoning_text"`` — the Copilot Claude convention).
355
+ """
356
+ opaque_cache: dict[str, str] = {}
357
+ original_send = client.send
358
+
359
+ async def _patched_send(
360
+ request: httpx.Request, *args: Any, **kwargs: Any
361
+ ) -> httpx.Response:
362
+ # 1) Inject reasoning_opaque into outgoing POST bodies.
363
+ # Also strips orphaned reasoning_text with no cached opaque.
364
+ if request.method == "POST":
365
+ _inject_opaque_into_request(request, opaque_cache, client, thinking_field)
366
+
367
+ # 2) Let the real send (incl. auth + retries) run.
368
+ response = await original_send(request, *args, **kwargs)
369
+
370
+ # 3) RECOVERY: If the API still returns 400, it's likely because
371
+ # our reasoning fields are wrong/stale. Strip them all and
372
+ # retry once. This degrades to "no thinking after tool calls"
373
+ # but keeps the conversation alive.
374
+ if response.status_code == 400 and request.method == "POST":
375
+ # Read the error body for diagnostics before retrying.
376
+ try:
377
+ err_body = response.content.decode("utf-8", errors="replace")
378
+ except Exception:
379
+ err_body = "<unreadable>"
380
+ logger.warning(
381
+ "Copilot 400 — attempting recovery by stripping reasoning "
382
+ "fields and retrying. Error: %.300s",
383
+ err_body,
384
+ )
385
+ if _strip_all_reasoning_fields(request, client, thinking_field):
386
+ response = await original_send(request, *args, **kwargs)
387
+ if response.status_code == 200:
388
+ logger.info(
389
+ "Recovery succeeded — reasoning stripped, "
390
+ "conversation continues without thinking context."
391
+ )
392
+ else:
393
+ logger.warning(
394
+ "Recovery retry also failed (%d) — returning retry response.",
395
+ response.status_code,
396
+ )
397
+
398
+ # 4) Capture reasoning_opaque from successful responses.
399
+ if response.status_code == 200:
400
+ if response.is_stream_consumed:
401
+ _capture_from_content(response.content, opaque_cache, thinking_field)
402
+ elif hasattr(response, "stream") and response.stream is not None:
403
+ response.stream = _OpaqueCapturingStream(
404
+ response.stream, opaque_cache, thinking_field
405
+ )
406
+
407
+ return response
408
+
409
+ client.send = _patched_send # type: ignore[method-assign]