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,338 @@
1
+ """ChatGPT OAuth flow closely matching the ChatMock implementation."""
2
+
3
+ import datetime
4
+ import threading
5
+ import time
6
+ import urllib.parse
7
+ from dataclasses import dataclass
8
+ from http.server import BaseHTTPRequestHandler, HTTPServer
9
+ from typing import Any
10
+
11
+ import httpx
12
+
13
+ from code_muse.messaging import emit_error, emit_info, emit_success, emit_warning
14
+
15
+ from ..oauth_muse_html import oauth_failure_html, oauth_success_html
16
+ from .config import CHATGPT_OAUTH_CONFIG
17
+ from .utils import (
18
+ add_models_to_extra_config,
19
+ assign_redirect_uri,
20
+ load_stored_tokens,
21
+ parse_jwt_claims,
22
+ prepare_oauth_context,
23
+ save_tokens,
24
+ )
25
+
26
+ REQUIRED_PORT = CHATGPT_OAUTH_CONFIG["required_port"]
27
+ URL_BASE = f"http://127.0.0.1:{REQUIRED_PORT}"
28
+
29
+
30
+ @dataclass
31
+ class TokenData:
32
+ id_token: str
33
+ access_token: str
34
+ refresh_token: str
35
+ account_id: str
36
+
37
+
38
+ @dataclass
39
+ class AuthBundle:
40
+ api_key: str | None
41
+ token_data: TokenData
42
+ last_refresh: str
43
+
44
+ @property
45
+ def success_url(self) -> str:
46
+ """The URL to redirect to after successful auth."""
47
+ return f"{URL_BASE}/success"
48
+
49
+ def __iter__(self):
50
+ """Allow unpacking as ``bundle, success_url = exchange_code(...)``."""
51
+ yield self
52
+ yield self.success_url
53
+
54
+
55
+ class _OAuthServer(HTTPServer):
56
+ allow_reuse_address = True # Reduce port-in-use flakes in tests
57
+
58
+ def __init__(
59
+ self,
60
+ *,
61
+ client_id: str,
62
+ verbose: bool = False,
63
+ ) -> None:
64
+ super().__init__(
65
+ ("127.0.0.1", REQUIRED_PORT), _CallbackHandler, bind_and_activate=True
66
+ )
67
+ self.exit_code = 1
68
+ self.verbose = verbose
69
+ self.client_id = client_id
70
+ self.issuer = CHATGPT_OAUTH_CONFIG["issuer"]
71
+ self.token_endpoint = CHATGPT_OAUTH_CONFIG["token_url"]
72
+
73
+ # Create fresh OAuth context for this server instance
74
+ context = prepare_oauth_context()
75
+ self.redirect_uri = assign_redirect_uri(context, REQUIRED_PORT)
76
+ self.context = context
77
+
78
+ def auth_url(self) -> str:
79
+ params = {
80
+ "response_type": "code",
81
+ "client_id": self.client_id,
82
+ "redirect_uri": self.redirect_uri,
83
+ "scope": CHATGPT_OAUTH_CONFIG["scope"],
84
+ "code_challenge": self.context.code_challenge,
85
+ "code_challenge_method": "S256",
86
+ "id_token_add_organizations": "true",
87
+ "codex_cli_simplified_flow": "true",
88
+ "state": self.context.state,
89
+ }
90
+ return f"{self.issuer}/oauth/authorize?" + urllib.parse.urlencode(params)
91
+
92
+ def exchange_code(self, code: str) -> AuthBundle:
93
+ data = {
94
+ "grant_type": "authorization_code",
95
+ "code": code,
96
+ "redirect_uri": self.redirect_uri,
97
+ "client_id": self.client_id,
98
+ "code_verifier": self.context.code_verifier,
99
+ }
100
+
101
+ response = httpx.post(
102
+ self.token_endpoint,
103
+ data=data,
104
+ headers={"Content-Type": "application/x-www-form-urlencoded"},
105
+ timeout=30,
106
+ )
107
+ response.raise_for_status()
108
+ payload = response.json()
109
+
110
+ id_token = payload.get("id_token", "")
111
+ access_token = payload.get("access_token", "")
112
+ refresh_token = payload.get("refresh_token", "")
113
+
114
+ id_token_claims = parse_jwt_claims(id_token) or {}
115
+
116
+ auth_claims = id_token_claims.get("https://api.openai.com/auth") or {}
117
+ chatgpt_account_id = auth_claims.get("chatgpt_account_id", "")
118
+ # Extract org_id from nested auth structure like ChatMock
119
+ organizations = auth_claims.get("organizations", [])
120
+ org_id = None
121
+ if organizations:
122
+ default_org = next(
123
+ (org for org in organizations if org.get("is_default")),
124
+ organizations[0],
125
+ )
126
+ org_id = default_org.get("id")
127
+ # Fallback to top-level org_id if still not found
128
+ if not org_id:
129
+ org_id = id_token_claims.get("organization_id")
130
+
131
+ token_data = TokenData(
132
+ id_token=id_token,
133
+ access_token=access_token,
134
+ refresh_token=refresh_token,
135
+ account_id=chatgpt_account_id,
136
+ )
137
+
138
+ # Use access_token directly as the API key (ChatMock behaviour)
139
+ api_key = token_data.access_token
140
+
141
+ last_refresh = (
142
+ datetime.datetime.now(datetime.UTC).isoformat().replace("+00:00", "Z")
143
+ )
144
+ return AuthBundle(
145
+ api_key=api_key, token_data=token_data, last_refresh=last_refresh
146
+ )
147
+
148
+
149
+ class _CallbackHandler(BaseHTTPRequestHandler):
150
+ server: _OAuthServer
151
+
152
+ def do_GET(self) -> None: # noqa: N802
153
+ path = urllib.parse.urlparse(self.path).path
154
+ if path == "/success":
155
+ success_html = oauth_success_html(
156
+ "ChatGPT",
157
+ "You can now close this window and return to Muse.",
158
+ )
159
+ self._send_html(success_html)
160
+ self._shutdown_after_delay(2.0)
161
+ return
162
+
163
+ if path != "/auth/callback":
164
+ self._send_failure(404, "Callback endpoint not found for the Muse parade.")
165
+ self._shutdown()
166
+ return
167
+
168
+ query = urllib.parse.urlparse(self.path).query
169
+ params = urllib.parse.parse_qs(query)
170
+
171
+ code = params.get("code", [None])[0]
172
+ if not code:
173
+ self._send_failure(400, "Missing auth code — the token treat rolled away.")
174
+ self._shutdown()
175
+ return
176
+
177
+ state = params.get("state", [None])[0]
178
+ if state != self.server.context.state:
179
+ self._send_failure(400, "Invalid state parameter — possible CSRF attack.")
180
+ self._shutdown()
181
+ return
182
+
183
+ try:
184
+ auth_bundle = self.server.exchange_code(code)
185
+ except Exception as exc: # noqa: BLE001
186
+ self._send_failure(500, f"Token exchange failed: {exc}")
187
+ self._shutdown()
188
+ return
189
+
190
+ tokens = {
191
+ "id_token": auth_bundle.token_data.id_token,
192
+ "access_token": auth_bundle.token_data.access_token,
193
+ "refresh_token": auth_bundle.token_data.refresh_token,
194
+ "account_id": auth_bundle.token_data.account_id,
195
+ "last_refresh": auth_bundle.last_refresh,
196
+ }
197
+ if auth_bundle.api_key:
198
+ tokens["api_key"] = auth_bundle.api_key
199
+
200
+ if save_tokens(tokens):
201
+ self.server.exit_code = 0
202
+ # Redirect to a token-free success URL
203
+ self._send_redirect(f"{URL_BASE}/success")
204
+ else:
205
+ self._send_failure(
206
+ 500, "Unable to persist auth file — a Muse probably misplaced it."
207
+ )
208
+ self._shutdown()
209
+ self._shutdown_after_delay(2.0)
210
+
211
+ def do_POST(self) -> None: # noqa: N802
212
+ self._send_failure(
213
+ 404, "POST not supported — the pups only fetch GET requests."
214
+ )
215
+ self._shutdown()
216
+
217
+ def log_message(self, fmt: str, *args: Any) -> None: # noqa: A003
218
+ if getattr(self.server, "verbose", False):
219
+ safe_args = []
220
+ for arg in args:
221
+ arg_str = str(arg)
222
+ if "?" in arg_str:
223
+ parsed = urllib.parse.urlparse(arg_str)
224
+ if parsed.query:
225
+ arg_str = urllib.parse.urlunparse(
226
+ parsed._replace(query="<redacted>")
227
+ )
228
+ safe_args.append(arg_str)
229
+ super().log_message(fmt, *safe_args)
230
+
231
+ def _send_redirect(self, url: str) -> None:
232
+ self.send_response(302)
233
+ self.send_header("Location", url)
234
+ self.end_headers()
235
+
236
+ def _send_html(self, body: str, status: int = 200) -> None:
237
+ encoded = body.encode("utf-8")
238
+ self.send_response(status)
239
+ self.send_header("Content-Type", "text/html; charset=utf-8")
240
+ self.send_header("Content-Length", str(len(encoded)))
241
+ self.end_headers()
242
+ self.wfile.write(encoded)
243
+
244
+ def _send_failure(self, status: int, reason: str) -> None:
245
+ failure_html = oauth_failure_html("ChatGPT", reason)
246
+ self._send_html(failure_html, status)
247
+
248
+ def _shutdown(self) -> None:
249
+ threading.Thread(target=self.server.shutdown, daemon=True).start()
250
+
251
+ def _shutdown_after_delay(self, seconds: float = 2.0) -> None:
252
+ def _later() -> None:
253
+ try:
254
+ time.sleep(seconds)
255
+ finally:
256
+ self._shutdown()
257
+
258
+ threading.Thread(target=_later, daemon=True).start()
259
+
260
+
261
+ def run_oauth_flow() -> None:
262
+ existing_tokens = load_stored_tokens()
263
+ if existing_tokens and existing_tokens.get("access_token"):
264
+ emit_warning("Existing ChatGPT tokens will be overwritten.")
265
+
266
+ try:
267
+ server = _OAuthServer(client_id=CHATGPT_OAUTH_CONFIG["client_id"])
268
+ except OSError as exc:
269
+ emit_error(f"Could not start OAuth server on port {REQUIRED_PORT}: {exc}")
270
+ emit_info(f"Use `lsof -ti:{REQUIRED_PORT} | xargs kill` to free the port.")
271
+ return
272
+
273
+ auth_url = server.auth_url()
274
+ emit_info(f"Open this URL in your browser: {auth_url}")
275
+
276
+ server_thread = threading.Thread(target=server.serve_forever, daemon=True)
277
+ server_thread.start()
278
+
279
+ webbrowser_opened = False
280
+ try:
281
+ import webbrowser
282
+
283
+ from code_muse.tools.common import should_suppress_browser
284
+
285
+ if should_suppress_browser():
286
+ emit_info(f"[HEADLESS MODE] Would normally open: {auth_url}")
287
+ else:
288
+ webbrowser_opened = webbrowser.open(auth_url)
289
+ except Exception as exc: # noqa: BLE001
290
+ emit_warning(f"Could not open browser automatically: {exc}")
291
+
292
+ if not webbrowser_opened and not should_suppress_browser():
293
+ emit_warning("Please open the URL manually if the browser did not open.")
294
+
295
+ emit_info("Waiting for authentication callback…")
296
+
297
+ elapsed = 0.0
298
+ timeout = CHATGPT_OAUTH_CONFIG["callback_timeout"]
299
+ interval = 0.25
300
+ while elapsed < timeout:
301
+ time.sleep(interval)
302
+ elapsed += interval
303
+ if server.exit_code == 0:
304
+ break
305
+
306
+ server.shutdown()
307
+ server_thread.join(timeout=5)
308
+
309
+ if server.exit_code != 0:
310
+ emit_error("Authentication failed or timed out.")
311
+ return
312
+
313
+ tokens = load_stored_tokens()
314
+ if not tokens:
315
+ emit_error("Tokens saved during OAuth flow could not be loaded.")
316
+ return
317
+
318
+ api_key = tokens.get("api_key")
319
+ if api_key:
320
+ emit_success("Successfully obtained OAuth access token for API access.")
321
+ emit_info(
322
+ f"Access token saved and available via {CHATGPT_OAUTH_CONFIG['api_key_env_var']}"
323
+ )
324
+ else:
325
+ emit_warning(
326
+ "No API key obtained. You may need to configure projects at platform.openai.com."
327
+ )
328
+
329
+ if api_key:
330
+ emit_info("Registering ChatGPT Codex models…")
331
+ from .utils import fetch_chatgpt_models
332
+
333
+ account_id = tokens.get("account_id", "")
334
+ models = fetch_chatgpt_models(api_key, account_id)
335
+ if models and add_models_to_extra_config(models):
336
+ emit_success(
337
+ "ChatGPT models registered. Use the `chatgpt-` prefix in /model."
338
+ )
@@ -0,0 +1,172 @@
1
+ """ChatGPT OAuth plugin callbacks aligned with ChatMock flow.
2
+
3
+ Provides OAuth authentication for ChatGPT models and registers
4
+ the 'chatgpt_oauth' model type handler.
5
+ """
6
+
7
+ import os
8
+ from typing import Any
9
+
10
+ from code_muse.callbacks import register_callback
11
+ from code_muse.messaging import emit_info, emit_success, emit_warning
12
+ from code_muse.model_switching import set_model_and_reload_agent
13
+
14
+ from .config import CHATGPT_OAUTH_CONFIG, get_token_storage_path
15
+ from .oauth_flow import run_oauth_flow
16
+ from .utils import (
17
+ get_valid_access_token,
18
+ load_chatgpt_models,
19
+ load_stored_tokens,
20
+ remove_chatgpt_models,
21
+ )
22
+
23
+
24
+ def _custom_help() -> list[tuple[str, str]]:
25
+ return [
26
+ (
27
+ "chatgpt-auth",
28
+ "Authenticate with ChatGPT via OAuth and import available models",
29
+ ),
30
+ (
31
+ "chatgpt-status",
32
+ "Check ChatGPT OAuth authentication status and configured models",
33
+ ),
34
+ ("chatgpt-logout", "Remove ChatGPT OAuth tokens and imported models"),
35
+ ]
36
+
37
+
38
+ def _handle_chatgpt_status() -> None:
39
+ tokens = load_stored_tokens()
40
+ if tokens and tokens.get("access_token"):
41
+ emit_success("🔐 ChatGPT OAuth: Authenticated")
42
+
43
+ api_key = tokens.get("api_key")
44
+ if api_key:
45
+ os.environ[CHATGPT_OAUTH_CONFIG["api_key_env_var"]] = api_key
46
+ emit_info("✅ OAuth access token available for API requests")
47
+ else:
48
+ emit_warning("⚠️ No access token obtained. Authentication may have failed.")
49
+
50
+ chatgpt_models = [
51
+ name
52
+ for name, cfg in load_chatgpt_models().items()
53
+ if cfg.get("oauth_source") == "chatgpt-oauth-plugin"
54
+ ]
55
+ if chatgpt_models:
56
+ emit_info(f"🎯 Configured ChatGPT models: {', '.join(chatgpt_models)}")
57
+ else:
58
+ emit_warning("⚠️ No ChatGPT models configured yet.")
59
+ else:
60
+ emit_warning("🔓 ChatGPT OAuth: Not authenticated")
61
+ emit_info("🌐 Run /chatgpt-auth to launch the browser sign-in flow.")
62
+
63
+
64
+ def _handle_chatgpt_logout() -> None:
65
+ token_path = get_token_storage_path()
66
+ if token_path.exists():
67
+ token_path.unlink()
68
+ emit_info("Removed ChatGPT OAuth tokens")
69
+
70
+ if CHATGPT_OAUTH_CONFIG["api_key_env_var"] in os.environ:
71
+ del os.environ[CHATGPT_OAUTH_CONFIG["api_key_env_var"]]
72
+
73
+ removed = remove_chatgpt_models()
74
+ if removed:
75
+ emit_info(f"Removed {removed} ChatGPT models from configuration")
76
+
77
+ emit_success("ChatGPT logout complete")
78
+
79
+
80
+ def _handle_custom_command(command: str, name: str) -> bool | None:
81
+ if not name:
82
+ return None
83
+
84
+ if name == "chatgpt-auth":
85
+ run_oauth_flow()
86
+ set_model_and_reload_agent("chatgpt-gpt-5.4")
87
+ return True
88
+
89
+ if name == "chatgpt-status":
90
+ _handle_chatgpt_status()
91
+ return True
92
+
93
+ if name == "chatgpt-logout":
94
+ _handle_chatgpt_logout()
95
+ return True
96
+
97
+ return None
98
+
99
+
100
+ def _create_chatgpt_oauth_model(
101
+ model_name: str, model_config: dict, config: dict
102
+ ) -> Any:
103
+ """Create a ChatGPT OAuth model instance.
104
+
105
+ This handler is registered via the 'register_model_type' callback to handle
106
+ models with type='chatgpt_oauth'.
107
+ """
108
+ from pydantic_ai.models.openai import OpenAIResponsesModel
109
+ from pydantic_ai.providers.openai import OpenAIProvider
110
+
111
+ from code_muse.chatgpt_codex_client import create_codex_async_client
112
+ from code_muse.http_utils import get_cert_bundle_path
113
+
114
+ # Get a valid access token (refreshing if needed)
115
+ access_token = get_valid_access_token()
116
+ if not access_token:
117
+ emit_warning(
118
+ f"Failed to get valid ChatGPT OAuth token; skipping model '{model_config.get('name')}'. "
119
+ "Run /chatgpt-auth to authenticate."
120
+ )
121
+ return None
122
+
123
+ # Get account_id from stored tokens (required for ChatGPT-Account-Id header)
124
+ tokens = load_stored_tokens()
125
+ account_id = tokens.get("account_id", "") if tokens else ""
126
+ if not account_id:
127
+ emit_warning(
128
+ f"No account_id found in ChatGPT OAuth tokens; skipping model '{model_config.get('name')}'. "
129
+ "Run /chatgpt-auth to re-authenticate."
130
+ )
131
+ return None
132
+
133
+ # Build headers for ChatGPT Codex API
134
+ originator = CHATGPT_OAUTH_CONFIG.get("originator", "codex_cli_rs")
135
+ client_version = CHATGPT_OAUTH_CONFIG.get("client_version", "0.72.0")
136
+
137
+ headers = {
138
+ "ChatGPT-Account-Id": account_id,
139
+ "originator": originator,
140
+ "User-Agent": f"{originator}/{client_version}",
141
+ }
142
+ # Merge with any headers from model config
143
+ config_headers = model_config.get("custom_endpoint", {}).get("headers", {})
144
+ headers.update(config_headers)
145
+
146
+ # Get base URL - Codex API uses chatgpt.com, not api.openai.com
147
+ base_url = model_config.get("custom_endpoint", {}).get(
148
+ "url", CHATGPT_OAUTH_CONFIG["api_base_url"]
149
+ )
150
+
151
+ # Create HTTP client with Codex interceptor for store=false injection
152
+ verify = get_cert_bundle_path()
153
+ client = create_codex_async_client(headers=headers, verify=verify)
154
+
155
+ provider = OpenAIProvider(
156
+ api_key=access_token,
157
+ base_url=base_url,
158
+ http_client=client,
159
+ )
160
+
161
+ # ChatGPT Codex API only supports Responses format
162
+ return OpenAIResponsesModel(model_name=model_config["name"], provider=provider)
163
+
164
+
165
+ def _register_model_types() -> list[dict[str, Any]]:
166
+ """Register the chatgpt_oauth model type handler."""
167
+ return [{"type": "chatgpt_oauth", "handler": _create_chatgpt_oauth_model}]
168
+
169
+
170
+ register_callback("custom_command_help", _custom_help)
171
+ register_callback("custom_command", _handle_custom_command)
172
+ register_callback("register_model_type", _register_model_types)