alysis-code 0.13.0__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 (458) hide show
  1. alysis_code/__init__.py +3 -0
  2. alysis_code/__main__.py +4 -0
  3. alysis_code/_build_info.py +14 -0
  4. alysis_code/account_login.py +468 -0
  5. alysis_code/agent/README.md +35 -0
  6. alysis_code/agent/__init__.py +11 -0
  7. alysis_code/agent/acceptance_contract.py +2217 -0
  8. alysis_code/agent/blast_radius.py +1403 -0
  9. alysis_code/agent/cache_keepalive.py +227 -0
  10. alysis_code/agent/completion_certificate.py +366 -0
  11. alysis_code/agent/completion_gate.py +306 -0
  12. alysis_code/agent/empty_response_stall.py +403 -0
  13. alysis_code/agent/errors.py +28 -0
  14. alysis_code/agent/llm_calls.py +475 -0
  15. alysis_code/agent/mutation_classification.py +227 -0
  16. alysis_code/agent/prompt_context.py +2508 -0
  17. alysis_code/agent/read_ledger.py +253 -0
  18. alysis_code/agent/regression_baseline.py +642 -0
  19. alysis_code/agent/reproduction_first.py +610 -0
  20. alysis_code/agent/sensitive_output.py +629 -0
  21. alysis_code/agent/session.py +3218 -0
  22. alysis_code/agent/steering.py +191 -0
  23. alysis_code/agent/subagent_execution.py +5177 -0
  24. alysis_code/agent/subagent_workspace.py +666 -0
  25. alysis_code/agent/tools_assembly.py +4728 -0
  26. alysis_code/agent/turn/__init__.py +101 -0
  27. alysis_code/agent/turn/core.py +8483 -0
  28. alysis_code/agent/turn/events.py +113 -0
  29. alysis_code/agent/turn/exploration.py +590 -0
  30. alysis_code/agent/turn/interventions.py +65 -0
  31. alysis_code/agent/turn/read_cache.py +420 -0
  32. alysis_code/agent/turn/snapshot.py +179 -0
  33. alysis_code/agent/turn_contract.py +661 -0
  34. alysis_code/agent/turn_path.py +129 -0
  35. alysis_code/agent/verification.py +2885 -0
  36. alysis_code/agent/verification_commands.py +512 -0
  37. alysis_code/agent/verification_evidence.py +738 -0
  38. alysis_code/agent_loop.py +693 -0
  39. alysis_code/agent_runtimes/__init__.py +51 -0
  40. alysis_code/agent_runtimes/base.py +114 -0
  41. alysis_code/agent_runtimes/builtins.py +129 -0
  42. alysis_code/agent_runtimes/codex_cli.py +664 -0
  43. alysis_code/agent_runtimes/host.py +263 -0
  44. alysis_code/agent_runtimes/registry.py +64 -0
  45. alysis_code/agent_runtimes/service.py +150 -0
  46. alysis_code/agentbox_client.py +416 -0
  47. alysis_code/agentbox_integration.py +310 -0
  48. alysis_code/alysis_cloud.py +152 -0
  49. alysis_code/approval_scope.py +276 -0
  50. alysis_code/assets/README.md +33 -0
  51. alysis_code/assets/__init__.py +126 -0
  52. alysis_code/assets/asset_read_core.py +281 -0
  53. alysis_code/assets/budget_allocator.py +456 -0
  54. alysis_code/assets/comprehender.py +759 -0
  55. alysis_code/assets/index.py +654 -0
  56. alysis_code/assets/ingestion.py +275 -0
  57. alysis_code/assets/legacy_migration.py +413 -0
  58. alysis_code/assets/models.py +263 -0
  59. alysis_code/assets/ocr.py +239 -0
  60. alysis_code/assets/owl/ascii/f-000.txt +13 -0
  61. alysis_code/assets/owl/ascii/f-001.txt +13 -0
  62. alysis_code/assets/owl/ascii/f-002.txt +13 -0
  63. alysis_code/assets/owl/ascii/f-003.txt +13 -0
  64. alysis_code/assets/owl/ascii/f-004.txt +13 -0
  65. alysis_code/assets/owl/ascii/f-005.txt +13 -0
  66. alysis_code/assets/owl/ascii/f-006.txt +13 -0
  67. alysis_code/assets/owl/ascii/f-007.txt +13 -0
  68. alysis_code/assets/owl/ascii/f-008.txt +13 -0
  69. alysis_code/assets/owl/ascii/f-009.txt +13 -0
  70. alysis_code/assets/owl/ascii/f-010.txt +13 -0
  71. alysis_code/assets/owl/ascii/f-011.txt +13 -0
  72. alysis_code/assets/owl/ascii/f-012.txt +13 -0
  73. alysis_code/assets/owl/ascii/f-013.txt +13 -0
  74. alysis_code/assets/owl/ascii/f-014.txt +13 -0
  75. alysis_code/assets/owl/ascii/f-015.txt +13 -0
  76. alysis_code/assets/owl/ascii/f-016.txt +13 -0
  77. alysis_code/assets/owl/ascii/f-017.txt +13 -0
  78. alysis_code/assets/owl/ascii/f-018.txt +13 -0
  79. alysis_code/assets/owl/ascii/f-019.txt +13 -0
  80. alysis_code/assets/owl/ascii/f-020.txt +13 -0
  81. alysis_code/assets/owl/index.html +98 -0
  82. alysis_code/assets/owl/show-owl.sh +761 -0
  83. alysis_code/assets/paths.py +49 -0
  84. alysis_code/assets/plan_binding.py +326 -0
  85. alysis_code/assets/planner_context.py +466 -0
  86. alysis_code/assets/planner_tools.py +184 -0
  87. alysis_code/assets/prompts.py +101 -0
  88. alysis_code/assets/replanner_context.py +239 -0
  89. alysis_code/assets/surface.py +521 -0
  90. alysis_code/assets/untrusted_content.py +48 -0
  91. alysis_code/assets/usage_logger.py +94 -0
  92. alysis_code/assets/worker_mirror.py +428 -0
  93. alysis_code/assets/worker_section.py +303 -0
  94. alysis_code/assets/worker_tools.py +468 -0
  95. alysis_code/atomic_io.py +83 -0
  96. alysis_code/auth_diagnostics.py +272 -0
  97. alysis_code/background_runner.py +366 -0
  98. alysis_code/branding.py +270 -0
  99. alysis_code/budget_policy.py +390 -0
  100. alysis_code/build_identity.py +465 -0
  101. alysis_code/builtin_hooks/__init__.py +7 -0
  102. alysis_code/builtin_hooks/notify_done_windows.py +65 -0
  103. alysis_code/bwrap_etc.py +76 -0
  104. alysis_code/cancellation.py +41 -0
  105. alysis_code/capabilities.py +137 -0
  106. alysis_code/chatgpt_codex_static_provider.py +133 -0
  107. alysis_code/cli.py +51 -0
  108. alysis_code/cli_impl/__init__.py +1 -0
  109. alysis_code/cli_impl/assets_cli.py +537 -0
  110. alysis_code/cli_impl/assets_modal.py +412 -0
  111. alysis_code/cli_impl/chat/__init__.py +156 -0
  112. alysis_code/cli_impl/chat/commands.py +2616 -0
  113. alysis_code/cli_impl/chat/loop.py +4508 -0
  114. alysis_code/cli_impl/chat/mid_turn_policy.py +125 -0
  115. alysis_code/cli_impl/chat/rendering.py +444 -0
  116. alysis_code/cli_impl/chat/state.py +124 -0
  117. alysis_code/cli_impl/chat_resume.py +830 -0
  118. alysis_code/cli_impl/chat_slash_completer.py +258 -0
  119. alysis_code/cli_impl/commands/__init__.py +11 -0
  120. alysis_code/cli_impl/commands/_shared.py +89 -0
  121. alysis_code/cli_impl/commands/auth.py +623 -0
  122. alysis_code/cli_impl/commands/chat_resume_helpers.py +1531 -0
  123. alysis_code/cli_impl/commands/chat_state.py +158 -0
  124. alysis_code/cli_impl/commands/chat_status.py +1248 -0
  125. alysis_code/cli_impl/commands/chat_terminal.py +942 -0
  126. alysis_code/cli_impl/commands/chat_tui_panels.py +1018 -0
  127. alysis_code/cli_impl/commands/cli_common.py +1223 -0
  128. alysis_code/cli_impl/commands/cli_surface.py +77 -0
  129. alysis_code/cli_impl/commands/config.py +131 -0
  130. alysis_code/cli_impl/commands/conventions.py +85 -0
  131. alysis_code/cli_impl/commands/execution_helpers.py +350 -0
  132. alysis_code/cli_impl/commands/extensions.py +401 -0
  133. alysis_code/cli_impl/commands/forge.py +1282 -0
  134. alysis_code/cli_impl/commands/forge_asset_view.py +121 -0
  135. alysis_code/cli_impl/commands/forge_helpers.py +1215 -0
  136. alysis_code/cli_impl/commands/hooks.py +737 -0
  137. alysis_code/cli_impl/commands/ide_bridge.py +31 -0
  138. alysis_code/cli_impl/commands/mcp.py +700 -0
  139. alysis_code/cli_impl/commands/profile.py +453 -0
  140. alysis_code/cli_impl/commands/prompt_helpers.py +307 -0
  141. alysis_code/cli_impl/commands/report.py +88 -0
  142. alysis_code/cli_impl/commands/root.py +1118 -0
  143. alysis_code/cli_impl/commands/sandbox.py +184 -0
  144. alysis_code/cli_impl/commands/server.py +54 -0
  145. alysis_code/cli_impl/commands/sessions.py +252 -0
  146. alysis_code/cli_impl/commands/skills.py +404 -0
  147. alysis_code/cli_impl/commands/startup.py +946 -0
  148. alysis_code/cli_impl/commands/tools.py +335 -0
  149. alysis_code/cli_impl/commands/update.py +364 -0
  150. alysis_code/cli_impl/commands/welcome.py +972 -0
  151. alysis_code/cli_impl/config_menu.py +3882 -0
  152. alysis_code/cli_impl/forge.py +4509 -0
  153. alysis_code/cli_impl/forge_recovery.py +485 -0
  154. alysis_code/cli_impl/setup_wizard.py +2409 -0
  155. alysis_code/cli_impl/tui/__init__.py +58 -0
  156. alysis_code/cli_impl/tui/app.py +4551 -0
  157. alysis_code/cli_impl/tui/config.py +32 -0
  158. alysis_code/cli_impl/tui/config_flow.py +2754 -0
  159. alysis_code/cli_impl/tui/config_overlay.py +566 -0
  160. alysis_code/cli_impl/tui/content.py +78 -0
  161. alysis_code/cli_impl/tui/footer.py +218 -0
  162. alysis_code/cli_impl/tui/forge_status.py +136 -0
  163. alysis_code/cli_impl/tui/markdown.py +244 -0
  164. alysis_code/cli_impl/tui/owl.py +109 -0
  165. alysis_code/cli_impl/tui/plan_meta.py +477 -0
  166. alysis_code/cli_impl/tui/setup_app.py +519 -0
  167. alysis_code/cli_impl/tui/setup_flow.py +1622 -0
  168. alysis_code/cli_impl/tui/state.py +101 -0
  169. alysis_code/cli_impl/tui/subagent_identity.py +66 -0
  170. alysis_code/cli_impl/tui/subagent_panel.py +186 -0
  171. alysis_code/cli_impl/tui/surface.py +796 -0
  172. alysis_code/cli_impl/tui/transcript.py +514 -0
  173. alysis_code/cli_impl/tui/update_prompt.py +79 -0
  174. alysis_code/cli_impl/tui/workspace_guard.py +384 -0
  175. alysis_code/clipboard.py +172 -0
  176. alysis_code/code_review.py +1211 -0
  177. alysis_code/compaction/__init__.py +28 -0
  178. alysis_code/compaction/conversation_compactor.py +2932 -0
  179. alysis_code/compaction/importance.py +177 -0
  180. alysis_code/compaction/settings.py +297 -0
  181. alysis_code/compaction/tool_output_offload.py +447 -0
  182. alysis_code/config.py +3509 -0
  183. alysis_code/conflict_auto_resolver.py +895 -0
  184. alysis_code/context/__init__.py +1 -0
  185. alysis_code/context/tool_schema_budgeter.py +220 -0
  186. alysis_code/crash_diagnostics.py +282 -0
  187. alysis_code/custom_tools/README.md +34 -0
  188. alysis_code/custom_tools/__init__.py +43 -0
  189. alysis_code/custom_tools/discovery.py +903 -0
  190. alysis_code/custom_tools/runtime.py +1516 -0
  191. alysis_code/custom_tools/session.py +227 -0
  192. alysis_code/custom_tools/trust.py +232 -0
  193. alysis_code/diff_paths.py +113 -0
  194. alysis_code/direction_change.py +293 -0
  195. alysis_code/dispatch_timing.py +306 -0
  196. alysis_code/durable_service_manager.py +1236 -0
  197. alysis_code/edit_discipline.py +659 -0
  198. alysis_code/error_text.py +73 -0
  199. alysis_code/execution_budget.py +411 -0
  200. alysis_code/execution_context.py +915 -0
  201. alysis_code/execution_deadline.py +1065 -0
  202. alysis_code/execution_shared.py +1904 -0
  203. alysis_code/extensions/README.md +30 -0
  204. alysis_code/extensions/__init__.py +93 -0
  205. alysis_code/extensions/activation.py +138 -0
  206. alysis_code/extensions/install.py +1436 -0
  207. alysis_code/extensions/manifest.py +487 -0
  208. alysis_code/extensions/models.py +74 -0
  209. alysis_code/extensions/paths.py +56 -0
  210. alysis_code/extensions/registry.json +4 -0
  211. alysis_code/extensions/registry.py +52 -0
  212. alysis_code/extensions/state.py +83 -0
  213. alysis_code/extensions/workspace_trust.py +101 -0
  214. alysis_code/failed_task_evidence.py +369 -0
  215. alysis_code/failure_category.py +315 -0
  216. alysis_code/feedback_report.py +1647 -0
  217. alysis_code/file_classification.py +485 -0
  218. alysis_code/forge.py +2064 -0
  219. alysis_code/forge_completion.py +362 -0
  220. alysis_code/forge_events.py +475 -0
  221. alysis_code/frontmatter_utils.py +95 -0
  222. alysis_code/git_evidence.py +1181 -0
  223. alysis_code/git_ops.py +560 -0
  224. alysis_code/git_safe.py +62 -0
  225. alysis_code/git_worktrees.py +190 -0
  226. alysis_code/hooks/README.md +33 -0
  227. alysis_code/hooks/__init__.py +67 -0
  228. alysis_code/hooks/audit.py +171 -0
  229. alysis_code/hooks/config.py +225 -0
  230. alysis_code/hooks/dispatcher.py +1110 -0
  231. alysis_code/hooks/models.py +447 -0
  232. alysis_code/hooks/trust.py +202 -0
  233. alysis_code/host_actions.py +543 -0
  234. alysis_code/host_browser.py +103 -0
  235. alysis_code/ide/__init__.py +5 -0
  236. alysis_code/ide/activity_events.py +399 -0
  237. alysis_code/ide/approvals.py +337 -0
  238. alysis_code/ide/artifacts.py +153 -0
  239. alysis_code/ide/browser_egress_proxy.py +1076 -0
  240. alysis_code/ide/cdp_websocket_transport.py +1192 -0
  241. alysis_code/ide/change_ledger.py +1721 -0
  242. alysis_code/ide/context_blocks.py +979 -0
  243. alysis_code/ide/event_stream.py +531 -0
  244. alysis_code/ide/forge_protocol.py +3112 -0
  245. alysis_code/ide/forge_request_ledger.py +737 -0
  246. alysis_code/ide/health.py +965 -0
  247. alysis_code/ide/managed_browser.py +2251 -0
  248. alysis_code/ide/management_protocol.py +3414 -0
  249. alysis_code/ide/mcp_oauth_coordinator.py +744 -0
  250. alysis_code/ide/mcp_oauth_lifecycle.py +1504 -0
  251. alysis_code/ide/prompt_queue.py +1070 -0
  252. alysis_code/ide/protocol.py +191 -0
  253. alysis_code/ide/resumable_swarm.py +1543 -0
  254. alysis_code/ide/session_search.py +295 -0
  255. alysis_code/ide/stdio_bridge.py +9935 -0
  256. alysis_code/ide/structured_state.py +1579 -0
  257. alysis_code/ide/swarm_protocol.py +816 -0
  258. alysis_code/integration_gate.py +506 -0
  259. alysis_code/interactive_input_guard.py +39 -0
  260. alysis_code/interactive_plan_mode.py +26 -0
  261. alysis_code/internal_artifacts.py +179 -0
  262. alysis_code/knowledge_base.py +1409 -0
  263. alysis_code/knowledge_capture.py +1190 -0
  264. alysis_code/knowledge_librarian.py +605 -0
  265. alysis_code/language_policy.py +34 -0
  266. alysis_code/litellm_static_provider.py +535 -0
  267. alysis_code/llm/__init__.py +1 -0
  268. alysis_code/llm/anthropic_messages.py +2288 -0
  269. alysis_code/llm/base.py +71 -0
  270. alysis_code/llm/cache_capabilities.py +985 -0
  271. alysis_code/llm/cache_control_blocks.py +244 -0
  272. alysis_code/llm/cache_policy.py +388 -0
  273. alysis_code/llm/factory.py +373 -0
  274. alysis_code/llm/gemini_generate_content.py +2652 -0
  275. alysis_code/llm/gemini_interactions.py +739 -0
  276. alysis_code/llm/metadata.py +450 -0
  277. alysis_code/llm/openai_compat.py +2947 -0
  278. alysis_code/llm/openai_responses.py +2604 -0
  279. alysis_code/llm/protocols.py +609 -0
  280. alysis_code/llm/provider_limits.py +525 -0
  281. alysis_code/llm/request_plan.py +389 -0
  282. alysis_code/llm/request_shape.py +238 -0
  283. alysis_code/llm/streaming.py +108 -0
  284. alysis_code/llm/temperature_compat.py +78 -0
  285. alysis_code/llm/types.py +195 -0
  286. alysis_code/llm/usage_normalization.py +222 -0
  287. alysis_code/llm_error_display.py +315 -0
  288. alysis_code/logging_redaction.py +326 -0
  289. alysis_code/managed_host_deadline.py +196 -0
  290. alysis_code/mcp/README.md +33 -0
  291. alysis_code/mcp/__init__.py +24 -0
  292. alysis_code/mcp/client.py +1137 -0
  293. alysis_code/mcp/config.py +597 -0
  294. alysis_code/mcp/errors.py +113 -0
  295. alysis_code/mcp/forge_scope.py +154 -0
  296. alysis_code/mcp/jsonrpc.py +214 -0
  297. alysis_code/mcp/manager.py +2308 -0
  298. alysis_code/mcp/models.py +666 -0
  299. alysis_code/mcp/oauth.py +972 -0
  300. alysis_code/mcp/oauth_runtime.py +310 -0
  301. alysis_code/mcp/oauth_store.py +276 -0
  302. alysis_code/mcp/prompts.py +329 -0
  303. alysis_code/mcp/resources.py +295 -0
  304. alysis_code/mcp/roots.py +106 -0
  305. alysis_code/mcp/server_requests.py +75 -0
  306. alysis_code/mcp/token_store.py +859 -0
  307. alysis_code/mcp/transport_http.py +1338 -0
  308. alysis_code/mcp/transport_stdio.py +1267 -0
  309. alysis_code/mcp/untrusted_content.py +119 -0
  310. alysis_code/merge_conflict_reviewer.py +729 -0
  311. alysis_code/model_catalog/__init__.py +1 -0
  312. alysis_code/model_catalog/chatgpt_codex_subscription_snapshot.json +186 -0
  313. alysis_code/model_catalog/litellm_model_prices_snapshot.json +44715 -0
  314. alysis_code/model_catalog/litellm_model_prices_snapshot.meta.json +17 -0
  315. alysis_code/model_metadata_policy.py +223 -0
  316. alysis_code/model_metadata_utils.py +103 -0
  317. alysis_code/model_registry.py +1420 -0
  318. alysis_code/model_router.py +147 -0
  319. alysis_code/permission_policy.py +1016 -0
  320. alysis_code/personas.py +451 -0
  321. alysis_code/pipeline_facts.py +233 -0
  322. alysis_code/plan_assistant.py +4763 -0
  323. alysis_code/plan_mode.py +393 -0
  324. alysis_code/plan_reconciliation.py +1228 -0
  325. alysis_code/plan_repair.py +652 -0
  326. alysis_code/plan_validation.py +1099 -0
  327. alysis_code/planning_constraints.py +904 -0
  328. alysis_code/policy.py +95 -0
  329. alysis_code/preview_server.py +457 -0
  330. alysis_code/process_reaping.py +566 -0
  331. alysis_code/profile_presets.py +1834 -0
  332. alysis_code/profiles.py +666 -0
  333. alysis_code/provider_auth/__init__.py +29 -0
  334. alysis_code/provider_auth/base.py +99 -0
  335. alysis_code/provider_auth/openai_codex.py +951 -0
  336. alysis_code/provider_auth/registry.py +76 -0
  337. alysis_code/provider_auth/store.py +125 -0
  338. alysis_code/provider_diagnostics.py +1209 -0
  339. alysis_code/provider_model_catalog.py +685 -0
  340. alysis_code/provider_telemetry.py +1699 -0
  341. alysis_code/provider_url.py +75 -0
  342. alysis_code/reasoning_contracts.py +911 -0
  343. alysis_code/remote_sync.py +350 -0
  344. alysis_code/replanning.py +1195 -0
  345. alysis_code/repo_scan.py +1152 -0
  346. alysis_code/request_estimation.py +296 -0
  347. alysis_code/review_gate.py +617 -0
  348. alysis_code/run_lock.py +1141 -0
  349. alysis_code/run_outcome.py +58 -0
  350. alysis_code/run_provenance.py +774 -0
  351. alysis_code/run_state.py +445 -0
  352. alysis_code/runtime_artifacts.py +116 -0
  353. alysis_code/runtime_context_features.py +78 -0
  354. alysis_code/runtime_kind.py +52 -0
  355. alysis_code/safety/__init__.py +11 -0
  356. alysis_code/safety/mcp_sanitize.py +29 -0
  357. alysis_code/safety/safe_http.py +297 -0
  358. alysis_code/safety/subagent_report.py +184 -0
  359. alysis_code/sandbox_doctor.py +682 -0
  360. alysis_code/sandbox_runner.py +1025 -0
  361. alysis_code/sandbox_settings.py +423 -0
  362. alysis_code/serialized_paths.py +355 -0
  363. alysis_code/server/__init__.py +3 -0
  364. alysis_code/server/app.py +367 -0
  365. alysis_code/server/auth.py +34 -0
  366. alysis_code/server/job_config.py +30 -0
  367. alysis_code/server/settings.py +215 -0
  368. alysis_code/server/store.py +193 -0
  369. alysis_code/server/worker_runner.py +657 -0
  370. alysis_code/service_persistence.py +355 -0
  371. alysis_code/session_artifacts.py +108 -0
  372. alysis_code/session_metrics.py +331 -0
  373. alysis_code/session_store.py +624 -0
  374. alysis_code/skills/README.md +34 -0
  375. alysis_code/skills/__init__.py +104 -0
  376. alysis_code/skills/conventions.py +84 -0
  377. alysis_code/skills/discovery.py +176 -0
  378. alysis_code/skills/eval_models.py +232 -0
  379. alysis_code/skills/eval_runner.py +372 -0
  380. alysis_code/skills/evals.py +1344 -0
  381. alysis_code/skills/install.py +293 -0
  382. alysis_code/skills/loader.py +118 -0
  383. alysis_code/skills/matching.py +103 -0
  384. alysis_code/skills/models.py +71 -0
  385. alysis_code/skills/paths.py +56 -0
  386. alysis_code/skills/prompting.py +500 -0
  387. alysis_code/skills/scaffold.py +142 -0
  388. alysis_code/skills/state.py +441 -0
  389. alysis_code/skills/transactions.py +125 -0
  390. alysis_code/skills/validation.py +304 -0
  391. alysis_code/step_budget.py +238 -0
  392. alysis_code/subagent_labels.py +49 -0
  393. alysis_code/subagents.py +1072 -0
  394. alysis_code/surface/__init__.py +80 -0
  395. alysis_code/surface/base.py +305 -0
  396. alysis_code/surface/console.py +387 -0
  397. alysis_code/surface/events.py +372 -0
  398. alysis_code/surface/hidden_surface.py +529 -0
  399. alysis_code/surface/noop_surface.py +219 -0
  400. alysis_code/surface/rich_surface.py +1555 -0
  401. alysis_code/surface/styles.py +67 -0
  402. alysis_code/surface/theme.py +455 -0
  403. alysis_code/surface/types.py +100 -0
  404. alysis_code/swarm_backend.py +926 -0
  405. alysis_code/swarm_orchestrator.py +4020 -0
  406. alysis_code/swarm_scheduler.py +441 -0
  407. alysis_code/swarm_trace.py +429 -0
  408. alysis_code/swarm_worker.py +2119 -0
  409. alysis_code/swarm_write_guard.py +348 -0
  410. alysis_code/task_dependencies.py +170 -0
  411. alysis_code/task_readiness.py +992 -0
  412. alysis_code/task_scope.py +2148 -0
  413. alysis_code/terminal_manager.py +762 -0
  414. alysis_code/terminal_ownership.py +460 -0
  415. alysis_code/text_normalization.py +30 -0
  416. alysis_code/token_budget.py +97 -0
  417. alysis_code/tools/README.md +34 -0
  418. alysis_code/tools/__init__.py +1 -0
  419. alysis_code/tools/artifacts.py +127 -0
  420. alysis_code/tools/availability.py +188 -0
  421. alysis_code/tools/fs.py +1456 -0
  422. alysis_code/tools/git.py +461 -0
  423. alysis_code/tools/history.py +229 -0
  424. alysis_code/tools/http_timeout.py +78 -0
  425. alysis_code/tools/image_generation.py +552 -0
  426. alysis_code/tools/registry.py +2936 -0
  427. alysis_code/tools/repo_map.py +476 -0
  428. alysis_code/tools/search.py +563 -0
  429. alysis_code/tools/shell.py +135 -0
  430. alysis_code/tools/symbols.py +1350 -0
  431. alysis_code/tools/test_discovery.py +643 -0
  432. alysis_code/tools/web.py +482 -0
  433. alysis_code/tools/web_search.py +2012 -0
  434. alysis_code/tools/web_search_dashscope.py +557 -0
  435. alysis_code/tools/web_search_ddgs.py +221 -0
  436. alysis_code/tools/web_search_provider_adapters.py +1429 -0
  437. alysis_code/tools/web_search_tavily.py +194 -0
  438. alysis_code/updates.py +933 -0
  439. alysis_code/usage_tracker.py +1990 -0
  440. alysis_code/verification_command_analysis.py +1004 -0
  441. alysis_code/verification_contract.py +574 -0
  442. alysis_code/verification_failure_summary.py +273 -0
  443. alysis_code/verification_repair.py +385 -0
  444. alysis_code/verify_gate.py +3129 -0
  445. alysis_code/web_research.py +1872 -0
  446. alysis_code/web_search_adapters.py +66 -0
  447. alysis_code/web_search_policy.py +27 -0
  448. alysis_code/workspace_binding.py +389 -0
  449. alysis_code/workspace_binding_ui.py +408 -0
  450. alysis_code/workspace_context.py +273 -0
  451. alysis_code/workspace_isolation.py +138 -0
  452. alysis_code/workspace_provisioning.py +455 -0
  453. alysis_code-0.13.0.dist-info/METADATA +507 -0
  454. alysis_code-0.13.0.dist-info/RECORD +458 -0
  455. alysis_code-0.13.0.dist-info/WHEEL +4 -0
  456. alysis_code-0.13.0.dist-info/entry_points.txt +3 -0
  457. alysis_code-0.13.0.dist-info/licenses/LICENSE +176 -0
  458. alysis_code-0.13.0.dist-info/licenses/NOTICE +4 -0
@@ -0,0 +1,453 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+ import sys
6
+ from typing import Any
7
+
8
+ import typer
9
+
10
+ from ...config import (
11
+ AppConfig,
12
+ ConfigError,
13
+ clear_persisted_profile_key,
14
+ load_config,
15
+ rename_persisted_profile_key,
16
+ resolve_profile_api_key,
17
+ save_config,
18
+ save_persisted_profile_key,
19
+ )
20
+ from . import _patchable
21
+ from ._shared import _console, _Table
22
+
23
+
24
+ def _cli_module() -> Any:
25
+ module = sys.modules.get("alysis_code.cli")
26
+ if module is not None:
27
+ return module
28
+ from ... import cli
29
+
30
+ return cli
31
+
32
+
33
+ profile_app = typer.Typer(add_completion=False, help="Provider profile commands.")
34
+
35
+
36
+ def _ensure_generic_profile_mutation_allowed(
37
+ cfg: AppConfig,
38
+ name: str,
39
+ *,
40
+ operation: str,
41
+ ) -> None:
42
+ """Keep generic profile commands from taking ownership of auth profiles."""
43
+
44
+ from ...profiles import get_profile
45
+
46
+ existing = get_profile(cfg, name)
47
+ if existing is None or not existing.auth_provider:
48
+ return
49
+ raise ConfigError(
50
+ f"Profile {existing.name!r} is managed by the {existing.auth_provider!r} "
51
+ f"subscription connection and cannot be {operation} through generic profile "
52
+ "commands. Choose a different profile name or manage the connection through auth."
53
+ )
54
+
55
+
56
+ def _parse_profile_headers(header_values: list[str] | None) -> dict[str, str]:
57
+ headers: dict[str, str] = {}
58
+ for raw_value in header_values or []:
59
+ text = str(raw_value or "").strip()
60
+ if not text:
61
+ continue
62
+ if "=" not in text:
63
+ raise ConfigError("--header values must use k=v syntax.")
64
+ key, value = text.split("=", 1)
65
+ key = key.strip()
66
+ value = value.strip()
67
+ if not key or not value:
68
+ raise ConfigError("--header values must use non-empty k=v syntax.")
69
+ headers[key] = value
70
+ return headers
71
+
72
+
73
+ def _profile_api_key_status(cfg: AppConfig, profile_name: str) -> str:
74
+ resolved = resolve_profile_api_key(cfg, profile_name)
75
+ if not resolved.key:
76
+ return "missing"
77
+ return _cli_module()._api_key_source_label(resolved.source)
78
+
79
+
80
+ @profile_app.command("list")
81
+ def profile_list() -> None:
82
+ """List provider profiles."""
83
+ from ...profiles import list_profiles
84
+
85
+ console = _console()
86
+ cfg = _patchable("load_config", load_config)()
87
+ active = str((cfg.extra_fields or {}).get("active_profile") or "")
88
+ table = _Table(title="Provider Profiles")
89
+ table.add_column("name")
90
+ table.add_column("active")
91
+ table.add_column("protocol")
92
+ table.add_column("base_url")
93
+ table.add_column("api_key")
94
+ table.add_column("default_model")
95
+ table.add_column("web_search")
96
+ for profile in list_profiles(cfg):
97
+ table.add_row(
98
+ profile.name,
99
+ "✓" if profile.name == active else "",
100
+ profile.protocol,
101
+ profile.base_url,
102
+ _profile_api_key_status(cfg, profile.name),
103
+ profile.default_model,
104
+ profile.web_search_adapter,
105
+ )
106
+ console.print(table)
107
+
108
+
109
+ @profile_app.command("show")
110
+ def profile_show(name: str = typer.Argument(..., help="Profile name.")) -> None:
111
+ """Show one provider profile."""
112
+ from ...profiles import get_profile
113
+
114
+ console = _console()
115
+ cfg = _patchable("load_config", load_config)()
116
+ profile = get_profile(cfg, name)
117
+ if profile is None:
118
+ console.print(f"[red]Profile not found:[/red] {name}")
119
+ raise typer.Exit(code=2)
120
+ data = profile.to_dict()
121
+ data["name"] = profile.name
122
+ data["active"] = profile.name == str((cfg.extra_fields or {}).get("active_profile") or "")
123
+ data["api_key"] = _profile_api_key_status(cfg, profile.name)
124
+ console.print_json(json.dumps(data, indent=2, sort_keys=True))
125
+
126
+
127
+ @profile_app.command("add")
128
+ def profile_add(
129
+ name: str = typer.Argument(..., help="Profile name."),
130
+ base_url: str = typer.Option(..., "--base-url", help="OpenAI-compatible base URL."),
131
+ api_key_env: str | None = typer.Option(None, "--api-key-env", help="API key env var."),
132
+ header: list[str] | None = typer.Option(None, "--header", help="Extra request header k=v."),
133
+ default_model: str = typer.Option("", "--default-model", help="Default model."),
134
+ reasoning_trace_adapter: str = typer.Option(
135
+ "auto",
136
+ "--reasoning-trace-adapter",
137
+ help="Safe reasoning-summary adapter for this provider profile.",
138
+ ),
139
+ web_search_adapter: str = typer.Option(
140
+ "auto",
141
+ "--web-search-adapter",
142
+ help="web_search adapter for this profile.",
143
+ ),
144
+ web_search_model: str = typer.Option(
145
+ "",
146
+ "--web-search-model",
147
+ help="Optional model used only by web_search.",
148
+ ),
149
+ notes: str = typer.Option("", "--notes", help="Notes."),
150
+ protocol: str = typer.Option("openai_compat", "--protocol", help="Profile protocol."),
151
+ ) -> None:
152
+ """Add a custom provider profile."""
153
+ from ...profiles import ProfileSpec, add_profile
154
+
155
+ console = _console()
156
+ cfg = _patchable("load_config", load_config)()
157
+ try:
158
+ _ensure_generic_profile_mutation_allowed(cfg, name, operation="overwritten")
159
+ profile = ProfileSpec(
160
+ name=name,
161
+ protocol=protocol,
162
+ base_url=base_url,
163
+ api_key_env=api_key_env,
164
+ extra_headers=_parse_profile_headers(header),
165
+ default_model=default_model,
166
+ reasoning_trace_adapter=reasoning_trace_adapter,
167
+ web_search_adapter=web_search_adapter,
168
+ web_search_model=web_search_model,
169
+ notes=notes,
170
+ )
171
+ add_profile(cfg, profile)
172
+ save_config(cfg)
173
+ except ConfigError as exc:
174
+ console.print(f"[red]Profile error:[/red] {exc}")
175
+ raise typer.Exit(code=2) from exc
176
+ console.print(f"Added profile {profile.name}.")
177
+
178
+
179
+ @profile_app.command("remove")
180
+ def profile_remove(
181
+ name: str = typer.Argument(..., help="Profile name."),
182
+ yes: bool = typer.Option(False, "--yes", help="Skip confirmation."),
183
+ ) -> None:
184
+ """Remove a provider profile."""
185
+ from ...profiles import remove_profile
186
+
187
+ console = _console()
188
+ if not yes and not typer.confirm(f"Remove profile {name}?", default=False):
189
+ console.print("Cancelled.")
190
+ return
191
+ cfg = _patchable("load_config", load_config)()
192
+ try:
193
+ remove_profile(cfg, name)
194
+ clear_persisted_profile_key(name)
195
+ save_config(cfg)
196
+ except ConfigError as exc:
197
+ console.print(f"[red]Profile error:[/red] {exc}")
198
+ raise typer.Exit(code=2) from exc
199
+ console.print(f"Removed profile {name}.")
200
+
201
+
202
+ @profile_app.command("use")
203
+ def profile_use(name: str = typer.Argument(..., help="Profile name.")) -> None:
204
+ """Switch the active provider profile."""
205
+ from ...profiles import set_active_profile
206
+
207
+ console = _console()
208
+ cfg = _patchable("load_config", load_config)()
209
+ try:
210
+ set_active_profile(cfg, name)
211
+ save_config(cfg)
212
+ except ConfigError as exc:
213
+ console.print(f"[red]Profile error:[/red] {exc}")
214
+ raise typer.Exit(code=2) from exc
215
+ console.print(f"Active profile: {name}")
216
+
217
+
218
+ @profile_app.command("rename")
219
+ def profile_rename(
220
+ old: str = typer.Argument(..., help="Current profile name."),
221
+ new: str = typer.Argument(..., help="New profile name."),
222
+ ) -> None:
223
+ """Rename a provider profile."""
224
+ from ...profiles import rename_profile
225
+
226
+ console = _console()
227
+ cfg = _patchable("load_config", load_config)()
228
+ try:
229
+ rename_profile(cfg, old, new)
230
+ rename_persisted_profile_key(old, new)
231
+ save_config(cfg)
232
+ except ConfigError as exc:
233
+ console.print(f"[red]Profile error:[/red] {exc}")
234
+ raise typer.Exit(code=2) from exc
235
+ console.print(f"Renamed profile {old} to {new}.")
236
+
237
+
238
+ @profile_app.command("preset")
239
+ def profile_preset(
240
+ preset_key: str = typer.Argument(..., help="Preset key."),
241
+ profile_name_as: str | None = typer.Option(None, "--as", help="Profile name to create."),
242
+ api_key: str | None = typer.Option(None, "--api-key", help="API key to store."),
243
+ api_key_stdin: bool = typer.Option(False, "--api-key-stdin", help="Read API key from stdin."),
244
+ yes: bool = typer.Option(False, "--yes", help="Overwrite without confirmation."),
245
+ ) -> None:
246
+ """Clone a provider preset into a profile."""
247
+ from ...profile_presets import get_preset, make_profile_from_preset
248
+ from ...profiles import add_profile, get_profile, update_profile
249
+
250
+ console = _console()
251
+ preset = get_preset(preset_key)
252
+ if preset is None:
253
+ console.print(f"[red]Unknown preset:[/red] {preset_key}")
254
+ raise typer.Exit(code=2)
255
+ cfg = _patchable("load_config", load_config)()
256
+ name = str(profile_name_as or preset.key).strip().lower()
257
+ existing = get_profile(cfg, name)
258
+ try:
259
+ _ensure_generic_profile_mutation_allowed(cfg, name, operation="overwritten")
260
+ except ConfigError as exc:
261
+ console.print(f"[red]Profile error:[/red] {exc}")
262
+ raise typer.Exit(code=2) from exc
263
+ if existing is not None and not yes:
264
+ if not typer.confirm(f"Overwrite profile {name}?", default=False):
265
+ console.print("Cancelled.")
266
+ return
267
+ base_url = preset.base_url
268
+ if not base_url:
269
+ base_url = str(typer.prompt("Base URL", default="", show_default=False)).strip()
270
+ try:
271
+ profile = make_profile_from_preset(preset, name=name)
272
+ if base_url != profile.base_url:
273
+ profile = make_profile_from_preset(preset, name=name)
274
+ add_profile(cfg, profile)
275
+ update_profile(cfg, profile.name, base_url=base_url)
276
+ else:
277
+ add_profile(cfg, profile)
278
+ save_config(cfg)
279
+ key_value = ""
280
+ if api_key_stdin:
281
+ key_value = sys.stdin.read().strip()
282
+ elif api_key is not None:
283
+ key_value = api_key.strip()
284
+ if key_value:
285
+ save_persisted_profile_key(profile.name, key_value)
286
+ except ConfigError as exc:
287
+ console.print(f"[red]Profile error:[/red] {exc}")
288
+ raise typer.Exit(code=2) from exc
289
+ console.print(f"Added profile {name} from preset {preset.key}.")
290
+
291
+
292
+ @profile_app.command("convert")
293
+ def profile_convert(
294
+ name: str | None = typer.Argument(
295
+ None,
296
+ help="Profile name. Defaults to the active profile.",
297
+ ),
298
+ target: str = typer.Option(
299
+ ...,
300
+ "--to",
301
+ help="Conversion target: native or compatibility.",
302
+ ),
303
+ yes: bool = typer.Option(False, "--yes", help="Skip confirmation."),
304
+ ) -> None:
305
+ """Convert a first-party profile between native and compatibility protocols."""
306
+ from ...profile_presets import (
307
+ convert_profile_to_preset,
308
+ normalize_conversion_target,
309
+ target_preset_for_profile_conversion,
310
+ )
311
+ from ...profiles import add_profile, get_profile, set_active_profile
312
+
313
+ console = _console()
314
+ cfg = _patchable("load_config", load_config)()
315
+ profile_name = str(name or (cfg.extra_fields or {}).get("active_profile") or "").strip()
316
+ if not profile_name:
317
+ console.print(
318
+ "[red]Profile error:[/red] No profile name supplied and no active profile set."
319
+ )
320
+ raise typer.Exit(code=2)
321
+ profile = get_profile(cfg, profile_name)
322
+ if profile is None:
323
+ console.print(f"[red]Profile not found:[/red] {profile_name}")
324
+ raise typer.Exit(code=2)
325
+ try:
326
+ _ensure_generic_profile_mutation_allowed(cfg, profile.name, operation="converted")
327
+ normalized_target = normalize_conversion_target(target)
328
+ except (ConfigError, ValueError) as exc:
329
+ console.print(f"[red]Profile error:[/red] {exc}")
330
+ raise typer.Exit(code=2) from exc
331
+ preset = target_preset_for_profile_conversion(profile, target=normalized_target)
332
+ if preset is None:
333
+ console.print(
334
+ "[red]Profile error:[/red] Only OpenAI, Anthropic, and Gemini profiles can be "
335
+ "converted between native and compatibility protocols."
336
+ )
337
+ raise typer.Exit(code=2)
338
+ converted = convert_profile_to_preset(profile, preset)
339
+ if converted.to_dict() == profile.to_dict():
340
+ console.print(
341
+ f"Profile {profile.name} is already using the {normalized_target} preset "
342
+ f"({preset.key})."
343
+ )
344
+ return
345
+
346
+ table = _Table(title=f"Convert profile {profile.name}")
347
+ table.add_column("field")
348
+ table.add_column("before")
349
+ table.add_column("after")
350
+ table.add_row("preset", profile.name, preset.key)
351
+ table.add_row("protocol", profile.protocol, converted.protocol)
352
+ table.add_row("base_url", profile.base_url, converted.base_url)
353
+ table.add_row(
354
+ "default_model", profile.default_model or "(empty)", converted.default_model or "(empty)"
355
+ )
356
+ table.add_row("web_search_adapter", profile.web_search_adapter, converted.web_search_adapter)
357
+ table.add_row(
358
+ "web_search_model",
359
+ profile.web_search_model or "(empty)",
360
+ converted.web_search_model or "(empty)",
361
+ )
362
+ table.add_row(
363
+ "api_key",
364
+ _profile_api_key_status(cfg, profile.name),
365
+ _profile_api_key_status(cfg, profile.name),
366
+ )
367
+ console.print(table)
368
+
369
+ if not yes and not typer.confirm(
370
+ f"Convert profile {profile.name} to {normalized_target}?", default=False
371
+ ):
372
+ console.print("Cancelled.")
373
+ return
374
+
375
+ add_profile(cfg, converted)
376
+ if str((cfg.extra_fields or {}).get("active_profile") or "") == profile.name:
377
+ set_active_profile(cfg, profile.name)
378
+ save_config(cfg)
379
+ console.print(f"Converted profile {profile.name} to {normalized_target} ({preset.key}).")
380
+
381
+
382
+ @profile_app.command("presets")
383
+ def profile_presets() -> None:
384
+ """List available provider presets."""
385
+ from ...profile_presets import PROFILE_PRESETS, preset_protocol_kind, preset_selection_label
386
+
387
+ table = _Table(title="Provider Presets")
388
+ table.add_column("key")
389
+ table.add_column("label")
390
+ table.add_column("kind")
391
+ table.add_column("protocol")
392
+ table.add_column("base_url")
393
+ table.add_column("web_search")
394
+ for preset in PROFILE_PRESETS:
395
+ table.add_row(
396
+ preset.key,
397
+ preset_selection_label(preset),
398
+ preset_protocol_kind(preset),
399
+ preset.protocol,
400
+ preset.base_url,
401
+ preset.web_search_adapter,
402
+ )
403
+ _console().print(table)
404
+
405
+
406
+ @profile_app.command("set-key")
407
+ def profile_set_key(
408
+ name: str = typer.Argument(..., help="Profile name."),
409
+ stdin: bool = typer.Option(False, "--stdin", help="Read API key from stdin."),
410
+ from_env: str | None = typer.Option(None, "--from-env", help="Copy key from env var."),
411
+ key: str | None = typer.Option(None, "--key", help="Inline key; avoid shell history."),
412
+ ) -> None:
413
+ """Store an API key for one profile."""
414
+ from ...profiles import get_profile
415
+
416
+ console = _console()
417
+ cfg = _patchable("load_config", load_config)()
418
+ profile = get_profile(cfg, name)
419
+ if profile is None:
420
+ console.print(f"[red]Profile not found:[/red] {name}")
421
+ raise typer.Exit(code=2)
422
+ sources = sum(1 for value in (stdin, bool(from_env), key is not None) if value)
423
+ if sources > 1:
424
+ console.print("[red]Profile error:[/red] Use only one key source.")
425
+ raise typer.Exit(code=2)
426
+ if stdin:
427
+ key_value = sys.stdin.read().strip()
428
+ elif from_env:
429
+ key_value = str(os.environ.get(from_env) or "").strip()
430
+ if not key_value:
431
+ console.print(f"[red]Profile error:[/red] Environment variable {from_env} is not set.")
432
+ raise typer.Exit(code=2)
433
+ elif key is not None:
434
+ key_value = key.strip()
435
+ console.print("[yellow]Warning:[/yellow] inline keys may be stored in shell history.")
436
+ else:
437
+ key_value = typer.prompt("API key", hide_input=True).strip()
438
+ try:
439
+ save_persisted_profile_key(profile.name, key_value)
440
+ except ConfigError as exc:
441
+ console.print(f"[red]Profile error:[/red] {exc}")
442
+ raise typer.Exit(code=2) from exc
443
+ console.print(f"Saved API key for profile {profile.name}.")
444
+
445
+
446
+ @profile_app.command("clear-key")
447
+ def profile_clear_key(name: str = typer.Argument(..., help="Profile name.")) -> None:
448
+ """Remove a stored API key for one profile."""
449
+ removed = clear_persisted_profile_key(name)
450
+ if removed:
451
+ _console().print(f"Removed API key for profile {name}.")
452
+ return
453
+ _console().print(f"No stored API key found for profile {name}.")