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,184 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any
4
+
5
+ import typer
6
+
7
+ from ...config import ConfigError, load_config
8
+ from ...sandbox_doctor import (
9
+ SandboxDiagnostic,
10
+ configured_sandbox_images,
11
+ diagnose_sandbox,
12
+ format_sandbox_problem_message,
13
+ pull_sandbox_images,
14
+ sandbox_env_summary,
15
+ )
16
+ from . import _patchable
17
+ from ._shared import _console, _Table
18
+
19
+ if TYPE_CHECKING:
20
+ from rich.table import Table
21
+
22
+
23
+ sandbox_app = typer.Typer(add_completion=False, help="Sandbox setup and diagnostics.")
24
+
25
+
26
+ def _sandbox_doctor_table(result: SandboxDiagnostic) -> Table:
27
+ table = _Table(title="alysis sandbox")
28
+ table.add_column("check")
29
+ table.add_column("status")
30
+ table.add_column("detail")
31
+ table.add_row("mode", result.configured_mode, "shell_sandbox.mode")
32
+ table.add_row("configured backend", result.configured_backend, "shell_sandbox.backend")
33
+ table.add_row("selected backend", result.selected_backend or "-", "")
34
+ table.add_row("sandbox image", result.docker_image, "dev shell/verify image")
35
+ table.add_row("server image", result.server_image, "server worker image")
36
+ for check in result.checks:
37
+ table.add_row(check.name, check.status, check.detail)
38
+ return table
39
+
40
+
41
+ def _print_sandbox_diagnostic(
42
+ *,
43
+ console: Any,
44
+ result: SandboxDiagnostic,
45
+ include_env: bool = False,
46
+ ) -> None:
47
+ console.print(_sandbox_doctor_table(result))
48
+ console.print()
49
+ message_style = "green" if result.ready else "yellow"
50
+ console.print(format_sandbox_problem_message(result), style=message_style, highlight=False)
51
+ if include_env:
52
+ env_rows = sandbox_env_summary()
53
+ env_table = _Table(title="sandbox environment")
54
+ env_table.add_column("variable")
55
+ env_table.add_column("value")
56
+ for key, value in env_rows.items():
57
+ env_table.add_row(key, value if value is not None else "(unset)")
58
+ console.print()
59
+ console.print(env_table)
60
+
61
+
62
+ def _run_sandbox_doctor_command(*, include_smoke: bool, include_env: bool = False) -> None:
63
+ console = _console()
64
+ try:
65
+ result = _patchable("diagnose_sandbox", diagnose_sandbox)(
66
+ _patchable("load_config", load_config)(),
67
+ include_smoke=include_smoke,
68
+ include_server_image=True,
69
+ )
70
+ except ConfigError as exc:
71
+ console.print(f"[red]Sandbox config error:[/red] {exc}")
72
+ raise typer.Exit(code=2) from exc
73
+ _print_sandbox_diagnostic(console=console, result=result, include_env=include_env)
74
+ if not result.ready:
75
+ raise typer.Exit(code=1)
76
+
77
+
78
+ def _run_sandbox_pull_command(
79
+ *,
80
+ images: list[str] | None = None,
81
+ include_server: bool = True,
82
+ timeout_s: int = 900,
83
+ ) -> None:
84
+ console = _console()
85
+ if images:
86
+ selected_images = tuple(images)
87
+ else:
88
+ try:
89
+ selected_images = _patchable("configured_sandbox_images", configured_sandbox_images)(
90
+ _patchable("load_config", load_config)(),
91
+ include_server=include_server,
92
+ )
93
+ except ConfigError as exc:
94
+ console.print(f"[red]Sandbox config error:[/red] {exc}")
95
+ raise typer.Exit(code=2) from exc
96
+ result = _patchable("pull_sandbox_images", pull_sandbox_images)(
97
+ selected_images, timeout_s=timeout_s
98
+ )
99
+ if result.error:
100
+ console.print(f"[red]Sandbox setup failed:[/red] {result.error}")
101
+ raise typer.Exit(code=1)
102
+ for item in result.results:
103
+ status = "pulled" if item.ok else "failed"
104
+ style = "green" if item.ok else "red"
105
+ console.print(f"[{style}]{status}[/{style}] {item.image}")
106
+ if not item.ok and item.output:
107
+ console.print(item.output)
108
+ if not result.ok:
109
+ raise typer.Exit(code=1)
110
+ _run_sandbox_doctor_command(include_smoke=True, include_env=False)
111
+
112
+
113
+ def _run_sandbox_setup_command(*, pull: bool = True) -> None:
114
+ console = _console()
115
+ try:
116
+ result = _patchable("diagnose_sandbox", diagnose_sandbox)(
117
+ _patchable("load_config", load_config)(),
118
+ include_smoke=False,
119
+ include_server_image=True,
120
+ )
121
+ except ConfigError as exc:
122
+ console.print(f"[red]Sandbox config error:[/red] {exc}")
123
+ raise typer.Exit(code=2) from exc
124
+ if result.ready:
125
+ _print_sandbox_diagnostic(console=console, result=result)
126
+ return
127
+ if pull and result.can_pull:
128
+ console.print("[bold]Downloading Alysis Code sandbox images...[/bold]")
129
+ _patchable("_run_sandbox_pull_command", _run_sandbox_pull_command)(include_server=True)
130
+ return
131
+ _print_sandbox_diagnostic(console=console, result=result)
132
+ raise typer.Exit(code=1)
133
+
134
+
135
+ @sandbox_app.command("doctor")
136
+ def sandbox_doctor(
137
+ smoke: bool = typer.Option(
138
+ True,
139
+ "--smoke/--no-smoke",
140
+ help="Run a sandbox smoke command.",
141
+ ),
142
+ env: bool = typer.Option(
143
+ False,
144
+ "--env",
145
+ help="Show sandbox-related environment variable overrides.",
146
+ ),
147
+ ) -> None:
148
+ """Check whether Alysis Code's safe command runner is ready."""
149
+ _run_sandbox_doctor_command(include_smoke=smoke, include_env=env)
150
+
151
+
152
+ @sandbox_app.command("setup")
153
+ def sandbox_setup(
154
+ pull: bool = typer.Option(
155
+ True,
156
+ "--pull/--no-pull",
157
+ help="Download missing Docker sandbox images when Docker is ready.",
158
+ ),
159
+ ) -> None:
160
+ """Prepare Alysis Code's safe command runner."""
161
+ _run_sandbox_setup_command(pull=pull)
162
+
163
+
164
+ @sandbox_app.command("pull")
165
+ def sandbox_pull(
166
+ image: list[str] | None = typer.Option(
167
+ None,
168
+ "--image",
169
+ help="Specific sandbox image to pull. Repeat to pull more than one.",
170
+ ),
171
+ include_server: bool = typer.Option(
172
+ True,
173
+ "--server/--no-server",
174
+ help="Also pull the server worker sandbox image.",
175
+ ),
176
+ timeout_s: int = typer.Option(
177
+ 900,
178
+ "--timeout",
179
+ min=1,
180
+ help="Per-image Docker pull timeout in seconds.",
181
+ ),
182
+ ) -> None:
183
+ """Download Alysis Code's Docker sandbox image(s)."""
184
+ _run_sandbox_pull_command(images=image, include_server=include_server, timeout_s=timeout_s)
@@ -0,0 +1,54 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+
5
+ import typer
6
+ from platformdirs import user_data_dir
7
+
8
+ from ...config import ConfigError
9
+ from ._shared import _console
10
+
11
+ server_app = typer.Typer(add_completion=False, help="Server mode commands.")
12
+
13
+
14
+ @server_app.command("start")
15
+ def server_start(
16
+ host: str = typer.Option("127.0.0.1", "--host", help="Host to bind."),
17
+ port: int = typer.Option(7070, "--port", min=1, help="Port to bind."),
18
+ data_dir: Path | None = typer.Option(
19
+ None,
20
+ "--data-dir",
21
+ help="Server data directory (default: platform app data dir).",
22
+ ),
23
+ ) -> None:
24
+ console = _console()
25
+ try:
26
+ import fastapi # noqa: F401
27
+ import uvicorn
28
+
29
+ from ...server.app import create_app
30
+ from ...server.settings import resolve_server_settings
31
+ except ModuleNotFoundError as e:
32
+ console.print(
33
+ "[red]Server dependencies missing.[/red] "
34
+ "Install server extras: [bold]pip install .[server][/bold]"
35
+ )
36
+ raise typer.Exit(code=2) from e
37
+
38
+ default_data_dir = Path(user_data_dir("alysis-code-server", "alysis"))
39
+ effective_data_dir = data_dir if data_dir is not None else default_data_dir
40
+
41
+ try:
42
+ settings = resolve_server_settings(
43
+ host=host,
44
+ port=port,
45
+ data_dir=effective_data_dir,
46
+ )
47
+ except ConfigError as e:
48
+ console.print(f"[red]Server config error:[/red] {e}")
49
+ raise typer.Exit(code=2) from e
50
+
51
+ def _app_factory(): # type: ignore[no-untyped-def]
52
+ return create_app(settings)
53
+
54
+ uvicorn.run(_app_factory, host=settings.host, port=settings.port, factory=True)
@@ -0,0 +1,252 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+ import sys
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ import typer
10
+
11
+ from ...config import load_config
12
+ from ...session_metrics import score_session_log
13
+ from ...session_store import (
14
+ filter_sessions_to_local_owner,
15
+ list_sessions,
16
+ read_session_events,
17
+ resolve_sessions_dir,
18
+ )
19
+ from ...usage_tracker import aggregate_usage_from_session_logs
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
+ sessions_app = typer.Typer(add_completion=False, help="Session log commands.")
34
+
35
+
36
+ def _usage_source_pair(row: dict[str, Any]) -> str:
37
+ provider = int(row.get("api_usage_calls") or 0)
38
+ fallback = int(row.get("estimate_usage_calls") or 0)
39
+ return f"{provider}/{fallback}"
40
+
41
+
42
+ def _print_hidden_owner_notice(console: Any, hidden_count: int) -> None:
43
+ """Say how many sessions the owner filter removed.
44
+
45
+ Silence here is what made "my session is gone" indistinguishable from "your
46
+ session is filtered": an empty list looks the same either way, so the count is
47
+ printed whenever anything was dropped -- including when nothing is left.
48
+ """
49
+ if hidden_count <= 0:
50
+ return
51
+ suffix = "" if hidden_count == 1 else "s"
52
+ console.print(
53
+ f"[dim]{hidden_count} session{suffix} from other accounts hidden. "
54
+ "Use --all-owners to include.[/dim]"
55
+ )
56
+
57
+
58
+ @sessions_app.command("list")
59
+ def sessions_list(
60
+ all_owners: bool = typer.Option(
61
+ False,
62
+ "--all-owners",
63
+ "--all",
64
+ help="Include sessions recorded by other accounts (hidden by default).",
65
+ ),
66
+ ) -> None:
67
+ console = _console()
68
+ cfg = _patchable("load_config", load_config)()
69
+ sessions_dir = resolve_sessions_dir(cfg)
70
+ all_infos = _patchable("list_sessions", list_sessions)(sessions_dir)
71
+ infos = all_infos if all_owners else filter_sessions_to_local_owner(all_infos)
72
+ hidden_count = len(all_infos) - len(infos)
73
+
74
+ table = _Table(title=f"Sessions ({sessions_dir})")
75
+ table.add_column("session_id")
76
+ table.add_column("path")
77
+ for info in infos[:200]:
78
+ table.add_row(info.session_id, os.fspath(info.path))
79
+ console.print(table)
80
+ _print_hidden_owner_notice(console, hidden_count)
81
+
82
+
83
+ @sessions_app.command("show")
84
+ def sessions_show(
85
+ session_id: str = typer.Argument(..., help="Session id (filename stem)."),
86
+ ) -> None:
87
+ console = _console()
88
+ cfg = _patchable("load_config", load_config)()
89
+ sessions_dir = resolve_sessions_dir(cfg)
90
+ path = sessions_dir / f"{session_id}.jsonl"
91
+ if not path.exists():
92
+ console.print(f"[red]Not found:[/red] {path}")
93
+ raise typer.Exit(code=2)
94
+ for ev in read_session_events(path):
95
+ console.print_json(json.dumps(ev))
96
+
97
+
98
+ @sessions_app.command("usage")
99
+ def sessions_usage(
100
+ session_id: str = typer.Argument(..., help="Session id (filename stem)."),
101
+ ) -> None:
102
+ console = _console()
103
+ cfg = _patchable("load_config", load_config)()
104
+ sessions_dir = resolve_sessions_dir(cfg)
105
+ path = sessions_dir / f"{session_id}.jsonl"
106
+ if not path.exists():
107
+ console.print(f"[red]Not found:[/red] {path}")
108
+ raise typer.Exit(code=2)
109
+ summary = _patchable("aggregate_usage_from_session_logs", aggregate_usage_from_session_logs)(
110
+ [path]
111
+ )
112
+ rows = summary.by_model_rows()
113
+ if not rows:
114
+ console.print("No llm_usage events found in this session log.")
115
+ return
116
+ table = _Table(title=f"Session Usage ({session_id})")
117
+ table.add_column("model")
118
+ table.add_column("prompt_tokens", justify="right")
119
+ table.add_column("completion_tokens", justify="right")
120
+ table.add_column("total_tokens", justify="right")
121
+ table.add_column("cost_usd", justify="right")
122
+ table.add_column("unknown_pricing", justify="right")
123
+ table.add_column("usage(provider/fallback)", justify="right")
124
+ for row in rows:
125
+ unknown_count = int(row.get("unknown_cost_count") or 0)
126
+ cost_display = _cli_module()._format_cost_with_unknown(
127
+ known_cost=_cli_module()._known_cost_value(row),
128
+ unknown_calls=unknown_count,
129
+ style="table",
130
+ )
131
+ table.add_row(
132
+ str(row.get("model") or "-"),
133
+ str(int(row.get("prompt_tokens") or 0)),
134
+ str(int(row.get("completion_tokens") or 0)),
135
+ str(int(row.get("total_tokens") or 0)),
136
+ cost_display,
137
+ str(unknown_count),
138
+ _usage_source_pair(row),
139
+ )
140
+ totals = summary.totals()
141
+ total_cost = _cli_module()._format_cost_with_unknown(
142
+ known_cost=_cli_module()._known_cost_value(totals),
143
+ unknown_calls=int(totals.get("unknown_cost_calls") or 0),
144
+ style="table",
145
+ )
146
+ table.add_row(
147
+ "TOTAL",
148
+ str(int(totals.get("prompt_tokens") or 0)),
149
+ str(int(totals.get("completion_tokens") or 0)),
150
+ str(int(totals.get("total_tokens") or 0)),
151
+ total_cost,
152
+ str(int(totals.get("unknown_cost_calls") or 0)),
153
+ _usage_source_pair(totals),
154
+ )
155
+ console.print(table)
156
+
157
+
158
+ @sessions_app.command("score")
159
+ def sessions_score(
160
+ session_id: str | None = typer.Argument(
161
+ None,
162
+ help="Session id (filename stem). If omitted, scores latest session(s).",
163
+ ),
164
+ latest: int = typer.Option(
165
+ 0,
166
+ "--latest",
167
+ min=0,
168
+ help="Score latest N sessions (ignored when session_id is provided).",
169
+ ),
170
+ all_owners: bool = typer.Option(
171
+ False,
172
+ "--all-owners",
173
+ help="Include sessions recorded by other accounts when picking the latest ones.",
174
+ ),
175
+ json_output: bool = typer.Option(False, "--json", help="Emit JSON output."),
176
+ ) -> None:
177
+ console = _console()
178
+ cfg = _patchable("load_config", load_config)()
179
+ sessions_dir = resolve_sessions_dir(cfg)
180
+
181
+ if session_id and latest > 0:
182
+ console.print("[red]Error:[/red] Use either session_id or --latest, not both.")
183
+ raise typer.Exit(code=2)
184
+
185
+ target_paths: list[Path] = []
186
+ if session_id:
187
+ path = sessions_dir / f"{session_id}.jsonl"
188
+ if not path.exists():
189
+ console.print(f"[red]Not found:[/red] {path}")
190
+ raise typer.Exit(code=2)
191
+ target_paths = [path]
192
+ else:
193
+ all_infos = _patchable("list_sessions", list_sessions)(sessions_dir)
194
+ infos = all_infos if all_owners else filter_sessions_to_local_owner(all_infos)
195
+ hidden_count = len(all_infos) - len(infos)
196
+ if not infos:
197
+ console.print(f"No sessions owned by this account found in {sessions_dir}")
198
+ _print_hidden_owner_notice(console, hidden_count)
199
+ return
200
+ _print_hidden_owner_notice(console, hidden_count)
201
+ count = latest if latest > 0 else 1
202
+ target_paths = [info.path for info in infos[:count]]
203
+
204
+ scores = [_patchable("score_session_log", score_session_log)(path) for path in target_paths]
205
+
206
+ if json_output:
207
+ payload: Any = scores[0] if len(scores) == 1 else scores
208
+ console.print_json(json.dumps(payload))
209
+ return
210
+
211
+ table = _Table(title=f"Session Score ({sessions_dir})")
212
+ table.add_column("session_id")
213
+ table.add_column("tools", justify="right")
214
+ table.add_column("errors", justify="right")
215
+ table.add_column("writes", justify="right")
216
+ table.add_column("blocked_writes", justify="right")
217
+ table.add_column("read_before_write")
218
+ table.add_column("shell_runs", justify="right")
219
+ table.add_column("test_runs", justify="right")
220
+ table.add_column("llm_calls", justify="right")
221
+ table.add_column("total_tokens", justify="right")
222
+
223
+ for score in scores:
224
+ rbw = score.get("read_before_first_write")
225
+ if isinstance(rbw, bool):
226
+ rbw_text = "yes" if rbw else "no"
227
+ else:
228
+ rbw_text = "n/a"
229
+ table.add_row(
230
+ str(score.get("session_id") or "-"),
231
+ str(int(score.get("tool_calls") or 0)),
232
+ str(int(score.get("tool_errors") or 0)),
233
+ str(int(score.get("write_calls") or 0)),
234
+ str(int(score.get("blocked_write_errors") or 0)),
235
+ rbw_text,
236
+ str(int(score.get("shell_runs") or 0)),
237
+ str(int(score.get("test_shell_runs") or 0)),
238
+ str(int(score.get("llm_usage_events") or 0)),
239
+ str(int(score.get("total_tokens") or 0)),
240
+ )
241
+ console.print(table)
242
+
243
+ if len(scores) == 1:
244
+ score = scores[0]
245
+ commands = score.get("test_shell_commands") or []
246
+ if commands:
247
+ console.print("Test commands: " + "; ".join(str(cmd) for cmd in commands))
248
+ repeated = score.get("repeated_tool_errors") or []
249
+ for item in repeated:
250
+ console.print(
251
+ f"Repeated tool error (x{int(item.get('count') or 0)}): {item.get('error') or ''}"
252
+ )