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,154 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any
5
+
6
+ from ..config import ConfigError
7
+ from .models import normalize_server_id
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class ForgeAllowedMcpTool:
12
+ server_id: str
13
+ tool_name: str
14
+
15
+ def as_payload(self) -> dict[str, str]:
16
+ return {
17
+ "server_id": self.server_id,
18
+ "tool_name": self.tool_name,
19
+ }
20
+
21
+
22
+ @dataclass(frozen=True)
23
+ class ForgeTaskMcpScope:
24
+ allow_resources: bool = False
25
+ allowed_tools: tuple[ForgeAllowedMcpTool, ...] = ()
26
+
27
+ @property
28
+ def is_empty(self) -> bool:
29
+ return not self.allow_resources and not self.allowed_tools
30
+
31
+ def as_payload(self) -> dict[str, Any]:
32
+ payload: dict[str, Any] = {}
33
+ if self.allow_resources:
34
+ payload["allow_resources"] = True
35
+ if self.allowed_tools:
36
+ payload["allowed_tools"] = [item.as_payload() for item in self.allowed_tools]
37
+ return payload
38
+
39
+
40
+ def serialize_task_mcp_scope(scope: ForgeTaskMcpScope | None) -> dict[str, Any] | None:
41
+ if scope is None or scope.is_empty:
42
+ return None
43
+ return scope.as_payload()
44
+
45
+
46
+ def describe_task_mcp_scope(scope: ForgeTaskMcpScope | None) -> str:
47
+ if scope is None or scope.is_empty:
48
+ return "disabled (default deny-by-default)"
49
+ parts = [
50
+ (
51
+ "generic MCP resources allowed"
52
+ if scope.allow_resources
53
+ else "generic MCP resources blocked"
54
+ ),
55
+ (
56
+ "allowed live MCP tools: "
57
+ + ", ".join(f"{item.server_id}/{item.tool_name}" for item in scope.allowed_tools)
58
+ if scope.allowed_tools
59
+ else "allowed live MCP tools: (none)"
60
+ ),
61
+ ]
62
+ return "; ".join(parts)
63
+
64
+
65
+ def normalize_task_mcp_scope(
66
+ value: Any,
67
+ *,
68
+ warning_prefix: str,
69
+ ) -> tuple[ForgeTaskMcpScope | None, list[str]]:
70
+ if value is None:
71
+ return None, []
72
+
73
+ warnings: list[str] = []
74
+ if not isinstance(value, dict):
75
+ return None, [f"{warning_prefix}: dropped invalid mcp_scope: expected an object."]
76
+
77
+ allow_resources = False
78
+ if "allow_resources" in value:
79
+ raw_allow_resources = value.get("allow_resources")
80
+ if isinstance(raw_allow_resources, bool):
81
+ allow_resources = raw_allow_resources
82
+ else:
83
+ warnings.append(
84
+ f"{warning_prefix}: dropped invalid mcp_scope.allow_resources value; expected true/false."
85
+ )
86
+
87
+ allowed_tools: list[ForgeAllowedMcpTool] = []
88
+ seen_tool_keys: set[tuple[str, str]] = set()
89
+ if "allowed_tools" in value:
90
+ raw_allowed_tools = value.get("allowed_tools")
91
+ if not isinstance(raw_allowed_tools, list):
92
+ warnings.append(
93
+ f"{warning_prefix}: dropped invalid mcp_scope.allowed_tools value; expected an array."
94
+ )
95
+ else:
96
+ for index, raw_item in enumerate(raw_allowed_tools):
97
+ normalized_tool, tool_warnings = _normalize_allowed_tool_entry(
98
+ raw_item,
99
+ warning_prefix=warning_prefix,
100
+ index=index,
101
+ )
102
+ warnings.extend(tool_warnings)
103
+ if normalized_tool is None:
104
+ continue
105
+ dedupe_key = (
106
+ normalized_tool.server_id,
107
+ normalized_tool.tool_name.casefold(),
108
+ )
109
+ if dedupe_key in seen_tool_keys:
110
+ continue
111
+ seen_tool_keys.add(dedupe_key)
112
+ allowed_tools.append(normalized_tool)
113
+
114
+ scope = ForgeTaskMcpScope(
115
+ allow_resources=allow_resources,
116
+ allowed_tools=tuple(allowed_tools),
117
+ )
118
+ if scope.is_empty:
119
+ warnings.append(
120
+ f"{warning_prefix}: normalized empty mcp_scope; MCP execution remains deny-by-default."
121
+ )
122
+ return None, warnings
123
+ return scope, warnings
124
+
125
+
126
+ def _normalize_allowed_tool_entry(
127
+ raw_item: Any,
128
+ *,
129
+ warning_prefix: str,
130
+ index: int,
131
+ ) -> tuple[ForgeAllowedMcpTool | None, list[str]]:
132
+ item_label = f"{warning_prefix}: dropped invalid mcp_scope.allowed_tools[{index}] entry"
133
+ if not isinstance(raw_item, dict):
134
+ return None, [f"{item_label}: expected an object."]
135
+
136
+ raw_server_id = raw_item.get("server_id")
137
+ if not isinstance(raw_server_id, str):
138
+ return None, [f"{item_label}: server_id must be a string."]
139
+ server_id_value = raw_server_id.strip()
140
+ if not server_id_value:
141
+ return None, [f"{item_label}: server_id cannot be empty."]
142
+ try:
143
+ server_id = normalize_server_id(server_id_value)
144
+ except ConfigError as exc:
145
+ return None, [f"{item_label}: {exc}"]
146
+
147
+ raw_tool_name = raw_item.get("tool_name")
148
+ if not isinstance(raw_tool_name, str):
149
+ return None, [f"{item_label}: tool_name must be a string."]
150
+ tool_name = raw_tool_name.strip()
151
+ if not tool_name:
152
+ return None, [f"{item_label}: tool_name cannot be empty."]
153
+
154
+ return ForgeAllowedMcpTool(server_id=server_id, tool_name=tool_name), []
@@ -0,0 +1,214 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from dataclasses import dataclass
5
+ from typing import Any, TypeAlias
6
+
7
+ from .errors import McpProtocolError
8
+
9
+ JsonRpcId: TypeAlias = int | str
10
+
11
+
12
+ class JsonRpcProtocolError(McpProtocolError):
13
+ pass
14
+
15
+
16
+ def _validate_request_id(value: object, *, field_name: str = "id") -> JsonRpcId:
17
+ if isinstance(value, bool):
18
+ raise JsonRpcProtocolError(f"JSON-RPC {field_name} must be a string or integer.")
19
+ if isinstance(value, int):
20
+ return value
21
+ if isinstance(value, str):
22
+ cleaned = value.strip()
23
+ if not cleaned:
24
+ raise JsonRpcProtocolError(f"JSON-RPC {field_name} cannot be empty.")
25
+ return cleaned
26
+ raise JsonRpcProtocolError(f"JSON-RPC {field_name} must be a string or integer.")
27
+
28
+
29
+ def _validate_method(value: object) -> str:
30
+ if not isinstance(value, str):
31
+ raise JsonRpcProtocolError("JSON-RPC method must be a string.")
32
+ cleaned = value.strip()
33
+ if not cleaned:
34
+ raise JsonRpcProtocolError("JSON-RPC method cannot be empty.")
35
+ return cleaned
36
+
37
+
38
+ def _validate_envelope_version(payload: dict[str, Any]) -> None:
39
+ if payload.get("jsonrpc") != "2.0":
40
+ raise JsonRpcProtocolError("JSON-RPC envelope must include jsonrpc='2.0'.")
41
+
42
+
43
+ @dataclass(frozen=True)
44
+ class JsonRpcErrorObject:
45
+ code: int
46
+ message: str
47
+ data: Any | None = None
48
+
49
+ @classmethod
50
+ def from_payload(cls, payload: object) -> JsonRpcErrorObject:
51
+ if not isinstance(payload, dict):
52
+ raise JsonRpcProtocolError("JSON-RPC error payload must be an object.")
53
+ code = payload.get("code")
54
+ message = payload.get("message")
55
+ if isinstance(code, bool) or not isinstance(code, int):
56
+ raise JsonRpcProtocolError("JSON-RPC error.code must be an integer.")
57
+ if not isinstance(message, str) or not message.strip():
58
+ raise JsonRpcProtocolError("JSON-RPC error.message must be a non-empty string.")
59
+ return cls(code=code, message=message.strip(), data=payload.get("data"))
60
+
61
+ def as_payload(self) -> dict[str, Any]:
62
+ payload = {
63
+ "code": self.code,
64
+ "message": self.message,
65
+ }
66
+ if self.data is not None:
67
+ payload["data"] = self.data
68
+ return payload
69
+
70
+
71
+ @dataclass(frozen=True)
72
+ class JsonRpcRequest:
73
+ id: JsonRpcId
74
+ method: str
75
+ params: Any | None = None
76
+
77
+
78
+ @dataclass(frozen=True)
79
+ class JsonRpcNotification:
80
+ method: str
81
+ params: Any | None = None
82
+
83
+
84
+ @dataclass(frozen=True)
85
+ class JsonRpcResponse:
86
+ id: JsonRpcId
87
+ result: Any | None = None
88
+ error: JsonRpcErrorObject | None = None
89
+
90
+
91
+ JsonRpcMessage: TypeAlias = JsonRpcRequest | JsonRpcNotification | JsonRpcResponse
92
+
93
+
94
+ class JsonRpcIdGenerator:
95
+ def __init__(self, *, start: int = 1) -> None:
96
+ self._next_id = int(start)
97
+
98
+ def next(self) -> int:
99
+ request_id = self._next_id
100
+ self._next_id += 1
101
+ return request_id
102
+
103
+
104
+ def encode_jsonrpc_message(payload: dict[str, Any]) -> str:
105
+ return json.dumps(payload, ensure_ascii=True, separators=(",", ":"))
106
+
107
+
108
+ def build_jsonrpc_request(
109
+ *,
110
+ request_id: JsonRpcId,
111
+ method: str,
112
+ params: Any | None = None,
113
+ ) -> dict[str, Any]:
114
+ payload: dict[str, Any] = {
115
+ "jsonrpc": "2.0",
116
+ "id": _validate_request_id(request_id),
117
+ "method": _validate_method(method),
118
+ }
119
+ if params is not None:
120
+ payload["params"] = params
121
+ return payload
122
+
123
+
124
+ def build_jsonrpc_notification(
125
+ *,
126
+ method: str,
127
+ params: Any | None = None,
128
+ ) -> dict[str, Any]:
129
+ payload: dict[str, Any] = {
130
+ "jsonrpc": "2.0",
131
+ "method": _validate_method(method),
132
+ }
133
+ if params is not None:
134
+ payload["params"] = params
135
+ return payload
136
+
137
+
138
+ def build_jsonrpc_result_response(
139
+ *,
140
+ request_id: JsonRpcId,
141
+ result: Any,
142
+ ) -> dict[str, Any]:
143
+ return {
144
+ "jsonrpc": "2.0",
145
+ "id": _validate_request_id(request_id),
146
+ "result": result,
147
+ }
148
+
149
+
150
+ def build_jsonrpc_error_response(
151
+ *,
152
+ request_id: JsonRpcId,
153
+ code: int,
154
+ message: str,
155
+ data: Any | None = None,
156
+ ) -> dict[str, Any]:
157
+ error = JsonRpcErrorObject(code=code, message=str(message).strip(), data=data)
158
+ return {
159
+ "jsonrpc": "2.0",
160
+ "id": _validate_request_id(request_id),
161
+ "error": error.as_payload(),
162
+ }
163
+
164
+
165
+ def _parse_jsonrpc_message(payload: object) -> JsonRpcMessage:
166
+ if not isinstance(payload, dict):
167
+ raise JsonRpcProtocolError("JSON-RPC message must be an object.")
168
+ _validate_envelope_version(payload)
169
+
170
+ has_method = "method" in payload
171
+ has_id = "id" in payload
172
+ has_result = "result" in payload
173
+ has_error = "error" in payload
174
+
175
+ if has_method:
176
+ method = _validate_method(payload.get("method"))
177
+ if has_result or has_error:
178
+ raise JsonRpcProtocolError(
179
+ "JSON-RPC request/notification cannot include result or error fields."
180
+ )
181
+ params = payload.get("params")
182
+ if has_id:
183
+ return JsonRpcRequest(
184
+ id=_validate_request_id(payload.get("id")),
185
+ method=method,
186
+ params=params,
187
+ )
188
+ return JsonRpcNotification(method=method, params=params)
189
+
190
+ if not has_id:
191
+ raise JsonRpcProtocolError("JSON-RPC response must include an id field.")
192
+ if has_result == has_error:
193
+ raise JsonRpcProtocolError("JSON-RPC response must include exactly one of result or error.")
194
+ request_id = _validate_request_id(payload.get("id"))
195
+ if has_error:
196
+ return JsonRpcResponse(
197
+ id=request_id, error=JsonRpcErrorObject.from_payload(payload["error"])
198
+ )
199
+ return JsonRpcResponse(id=request_id, result=payload.get("result"))
200
+
201
+
202
+ def parse_jsonrpc_line(raw_line: str) -> tuple[JsonRpcMessage, ...]:
203
+ text = str(raw_line).strip()
204
+ if not text:
205
+ raise JsonRpcProtocolError("JSON-RPC line cannot be empty.")
206
+ try:
207
+ payload = json.loads(text)
208
+ except json.JSONDecodeError as exc:
209
+ raise JsonRpcProtocolError(f"Malformed JSON-RPC JSON: {exc.msg}") from exc
210
+ if isinstance(payload, list):
211
+ if not payload:
212
+ raise JsonRpcProtocolError("JSON-RPC batch payload cannot be empty.")
213
+ return tuple(_parse_jsonrpc_message(item) for item in payload)
214
+ return (_parse_jsonrpc_message(payload),)