aria-code 0.167.0__py3-none-win_amd64.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 (601) hide show
  1. aria_bots/__init__.py +7 -0
  2. aria_bots/channels/README.md +97 -0
  3. aria_bots/channels/__init__.py +1 -0
  4. aria_bots/channels/approvals.py +263 -0
  5. aria_bots/channels/conversation.py +280 -0
  6. aria_bots/channels/digest.py +186 -0
  7. aria_bots/channels/registry.py +95 -0
  8. aria_bots/engine.py +144 -0
  9. aria_bots/feishu_bot.py +1385 -0
  10. aria_bots/logistics/__init__.py +1 -0
  11. aria_bots/logistics/carriers.py +253 -0
  12. aria_bots/logistics/freight.py +154 -0
  13. aria_bots/logistics/inventory.py +242 -0
  14. aria_bots/logistics/mcp_server.py +156 -0
  15. aria_bots/logistics/records.py +119 -0
  16. aria_bots/logistics/tenancy.py +152 -0
  17. aria_bots/market.py +91 -0
  18. aria_bots/relay_client.py +326 -0
  19. aria_bots/telegram_bot.py +299 -0
  20. aria_code/__init__.py +111 -0
  21. aria_code/_bin/aria-native.exe +0 -0
  22. aria_code/_bin/aria-runtime.exe +0 -0
  23. aria_code/_version.py +20 -0
  24. aria_code/account_memory.py +296 -0
  25. aria_code/account_session.py +166 -0
  26. aria_code/adk_apps/__init__.py +1 -0
  27. aria_code/adk_apps/aria_code_review/__init__.py +1 -0
  28. aria_code/adk_apps/aria_code_review/agent.py +32 -0
  29. aria_code/adk_apps/aria_research/__init__.py +1 -0
  30. aria_code/adk_apps/aria_research/agent.py +31 -0
  31. aria_code/agents/__init__.py +49 -0
  32. aria_code/agents/base.py +329 -0
  33. aria_code/agents/code_review.py +200 -0
  34. aria_code/agents/deep/__init__.py +37 -0
  35. aria_code/agents/deep/calibration_loop.py +144 -0
  36. aria_code/agents/deep/critic.py +125 -0
  37. aria_code/agents/deep/deepen.py +193 -0
  38. aria_code/agents/deep/models.py +149 -0
  39. aria_code/agents/deep/pipeline.py +164 -0
  40. aria_code/agents/deep/quant_fusion.py +192 -0
  41. aria_code/agents/deep/themes.py +95 -0
  42. aria_code/agents/deep/tiers.py +106 -0
  43. aria_code/agents/engineering/__init__.py +14 -0
  44. aria_code/agents/engineering/coder.py +222 -0
  45. aria_code/agents/engineering/tester.py +145 -0
  46. aria_code/agents/financial/__init__.py +21 -0
  47. aria_code/agents/financial/cashflow_burn.py +119 -0
  48. aria_code/agents/financial/catalyst.py +279 -0
  49. aria_code/agents/financial/corporate_finance.py +175 -0
  50. aria_code/agents/financial/debate.py +224 -0
  51. aria_code/agents/financial/earnings.py +315 -0
  52. aria_code/agents/financial/fundamental.py +178 -0
  53. aria_code/agents/financial/macro.py +111 -0
  54. aria_code/agents/financial/news.py +231 -0
  55. aria_code/agents/financial/risk.py +146 -0
  56. aria_code/agents/financial/sector.py +279 -0
  57. aria_code/agents/financial/strategist.py +121 -0
  58. aria_code/agents/financial/stripe_revenue.py +127 -0
  59. aria_code/agents/financial/synthesis.py +274 -0
  60. aria_code/agents/financial/technical.py +277 -0
  61. aria_code/agents/orchestrator.py +44 -0
  62. aria_code/agents/portfolio_agent.py +392 -0
  63. aria_code/agents/realty/__init__.py +62 -0
  64. aria_code/agents/realty/asset_diagnosis.py +152 -0
  65. aria_code/agents/realty/business_match.py +166 -0
  66. aria_code/agents/realty/cashflow_verify.py +209 -0
  67. aria_code/agents/realty/contract_rules.py +210 -0
  68. aria_code/agents/realty/energy_anomaly.py +189 -0
  69. aria_code/agents/realty/exit_settlement.py +208 -0
  70. aria_code/agents/realty/fulfillment_risk.py +206 -0
  71. aria_code/agents/realty/ops_optimize.py +160 -0
  72. aria_code/agents/realty/revenue_share.py +215 -0
  73. aria_code/agents/registry.py +168 -0
  74. aria_code/agents/signal_scheme.py +111 -0
  75. aria_code/agents/sports/__init__.py +0 -0
  76. aria_code/agents/sports/football_agent.py +197 -0
  77. aria_code/agents/supervisor.py +113 -0
  78. aria_code/agents/team.py +500 -0
  79. aria_code/agents/video/__init__.py +16 -0
  80. aria_code/agents/video/director.py +376 -0
  81. aria_code/agents/video/qa_agent.py +143 -0
  82. aria_code/agents/video/script_doctor.py +112 -0
  83. aria_code/agents/warehouse/__init__.py +25 -0
  84. aria_code/agents/warehouse/contracts.py +26 -0
  85. aria_code/agents/warehouse/dashboard.py +155 -0
  86. aria_code/agents/warehouse/fulfillment_leadtime.py +95 -0
  87. aria_code/agents/warehouse/inbound_exceptions.py +25 -0
  88. aria_code/agents/warehouse/inventory_health.py +24 -0
  89. aria_code/agents/warehouse/local_run.py +71 -0
  90. aria_code/agents/warehouse/local_snapshot.py +132 -0
  91. aria_code/agents/warehouse/logistics_cost.py +84 -0
  92. aria_code/agents/warehouse/logistics_sync.py +21 -0
  93. aria_code/agents/warehouse/navigation.schema.json +110 -0
  94. aria_code/agents/warehouse/task_agent.py +172 -0
  95. aria_code/agents/warehouse/workflow.py +31 -0
  96. aria_code/aliyun_data_client.py +4 -0
  97. aria_code/apps/README.md +12 -0
  98. aria_code/apps/__init__.py +2 -0
  99. aria_code/apps/channels/README.md +9 -0
  100. aria_code/apps/channels/__init__.py +17 -0
  101. aria_code/apps/channels/approvals.py +11 -0
  102. aria_code/apps/channels/conversation.py +11 -0
  103. aria_code/apps/channels/digest.py +11 -0
  104. aria_code/apps/channels/intake.py +92 -0
  105. aria_code/apps/channels/registry.py +11 -0
  106. aria_code/apps/channels/tradingview.py +94 -0
  107. aria_code/apps/cli/README.md +13 -0
  108. aria_code/apps/cli/__init__.py +2 -0
  109. aria_code/apps/cli/_optional.py +120 -0
  110. aria_code/apps/cli/app_server.py +656 -0
  111. aria_code/apps/cli/auto_update.py +125 -0
  112. aria_code/apps/cli/bootstrap.py +206 -0
  113. aria_code/apps/cli/broker_render.py +206 -0
  114. aria_code/apps/cli/chat_turn.py +1327 -0
  115. aria_code/apps/cli/cloud_models.py +231 -0
  116. aria_code/apps/cli/codegen_paths.py +29 -0
  117. aria_code/apps/cli/commands/__init__.py +34 -0
  118. aria_code/apps/cli/commands/_business_render.py +78 -0
  119. aria_code/apps/cli/commands/_ui.py +71 -0
  120. aria_code/apps/cli/commands/analysis_cmds.py +378 -0
  121. aria_code/apps/cli/commands/ashare_prediction_cmds.py +327 -0
  122. aria_code/apps/cli/commands/auth_cmds.py +215 -0
  123. aria_code/apps/cli/commands/backtest_cmds.py +2518 -0
  124. aria_code/apps/cli/commands/broker_cmds.py +1236 -0
  125. aria_code/apps/cli/commands/business_workflow_cmds.py +379 -0
  126. aria_code/apps/cli/commands/canvas_cmds.py +77 -0
  127. aria_code/apps/cli/commands/catalog.py +189 -0
  128. aria_code/apps/cli/commands/core_cmds.py +2748 -0
  129. aria_code/apps/cli/commands/data_cmds.py +521 -0
  130. aria_code/apps/cli/commands/diagnostic_cmds.py +285 -0
  131. aria_code/apps/cli/commands/diagnostic_ops_cmds.py +813 -0
  132. aria_code/apps/cli/commands/engineering_cmds.py +399 -0
  133. aria_code/apps/cli/commands/file_cmds.py +312 -0
  134. aria_code/apps/cli/commands/finance_service_cmds.py +60 -0
  135. aria_code/apps/cli/commands/fx_commodity_cmds.py +123 -0
  136. aria_code/apps/cli/commands/market.py +544 -0
  137. aria_code/apps/cli/commands/market_cmds.py +1419 -0
  138. aria_code/apps/cli/commands/market_context.py +432 -0
  139. aria_code/apps/cli/commands/market_render.py +7 -0
  140. aria_code/apps/cli/commands/model_cmds.py +2374 -0
  141. aria_code/apps/cli/commands/ops_cmds.py +721 -0
  142. aria_code/apps/cli/commands/orchestrator_cmds.py +181 -0
  143. aria_code/apps/cli/commands/pdf_export_cmds.py +125 -0
  144. aria_code/apps/cli/commands/portfolio_cmds.py +1316 -0
  145. aria_code/apps/cli/commands/report.py +476 -0
  146. aria_code/apps/cli/commands/scaffold_templates.py +617 -0
  147. aria_code/apps/cli/commands/session_cmds.py +236 -0
  148. aria_code/apps/cli/commands/session_ux_cmds.py +359 -0
  149. aria_code/apps/cli/commands/team.py +723 -0
  150. aria_code/apps/cli/commands/team_render.py +8 -0
  151. aria_code/apps/cli/commands/ui_cmds.py +401 -0
  152. aria_code/apps/cli/commands/warehouse_cmds.py +297 -0
  153. aria_code/apps/cli/commands/workflow_cmds.py +629 -0
  154. aria_code/apps/cli/commands/workspace_cmds.py +1543 -0
  155. aria_code/apps/cli/config_paths.py +73 -0
  156. aria_code/apps/cli/config_store.py +158 -0
  157. aria_code/apps/cli/constants.py +88 -0
  158. aria_code/apps/cli/context.py +34 -0
  159. aria_code/apps/cli/conversation_policy.py +53 -0
  160. aria_code/apps/cli/deterministic.py +200 -0
  161. aria_code/apps/cli/direct.py +48 -0
  162. aria_code/apps/cli/earnings_view.py +172 -0
  163. aria_code/apps/cli/endpoint_migration.py +64 -0
  164. aria_code/apps/cli/exec_events.py +255 -0
  165. aria_code/apps/cli/file_references.py +155 -0
  166. aria_code/apps/cli/finance_service_catalog.py +111 -0
  167. aria_code/apps/cli/football_reports.py +231 -0
  168. aria_code/apps/cli/github_app_auth.py +135 -0
  169. aria_code/apps/cli/google_login.py +239 -0
  170. aria_code/apps/cli/handlers/__init__.py +11 -0
  171. aria_code/apps/cli/handlers/broker_handlers.py +122 -0
  172. aria_code/apps/cli/handlers/chart_handlers.py +1314 -0
  173. aria_code/apps/cli/handlers/market_handlers.py +2570 -0
  174. aria_code/apps/cli/handlers/realty_handlers.py +114 -0
  175. aria_code/apps/cli/handlers/sports_handlers.py +22 -0
  176. aria_code/apps/cli/handlers/strategy_advice.py +82 -0
  177. aria_code/apps/cli/headless.py +352 -0
  178. aria_code/apps/cli/helpers.py +326 -0
  179. aria_code/apps/cli/hooks.py +180 -0
  180. aria_code/apps/cli/i18n.py +310 -0
  181. aria_code/apps/cli/intent.py +136 -0
  182. aria_code/apps/cli/intent_router.py +305 -0
  183. aria_code/apps/cli/intent_shadow.py +72 -0
  184. aria_code/apps/cli/intent_signals.py +347 -0
  185. aria_code/apps/cli/lifecycle_hooks.py +48 -0
  186. aria_code/apps/cli/local_tool_schemas.py +550 -0
  187. aria_code/apps/cli/main.py +39 -0
  188. aria_code/apps/cli/market_hours.py +100 -0
  189. aria_code/apps/cli/market_metadata.py +135 -0
  190. aria_code/apps/cli/market_universe.py +487 -0
  191. aria_code/apps/cli/message_processing.py +310 -0
  192. aria_code/apps/cli/mixin_binding.py +32 -0
  193. aria_code/apps/cli/model_catalog.py +652 -0
  194. aria_code/apps/cli/model_probe.py +169 -0
  195. aria_code/apps/cli/model_retirement.py +65 -0
  196. aria_code/apps/cli/native_branding.py +12 -0
  197. aria_code/apps/cli/native_bridge.py +118 -0
  198. aria_code/apps/cli/native_entry.py +58 -0
  199. aria_code/apps/cli/pdf_report.py +977 -0
  200. aria_code/apps/cli/plan_mode.py +139 -0
  201. aria_code/apps/cli/plotly_html.py +15 -0
  202. aria_code/apps/cli/prediction_feedback.py +202 -0
  203. aria_code/apps/cli/preflight.py +502 -0
  204. aria_code/apps/cli/project_aria.py +60 -0
  205. aria_code/apps/cli/prompt_assembly.py +78 -0
  206. aria_code/apps/cli/prompts/__init__.py +0 -0
  207. aria_code/apps/cli/prompts/coding.py +71 -0
  208. aria_code/apps/cli/prompts/select.py +193 -0
  209. aria_code/apps/cli/prompts/system_prompts.py +562 -0
  210. aria_code/apps/cli/prompts/ui.py +436 -0
  211. aria_code/apps/cli/provider_endpoints.py +237 -0
  212. aria_code/apps/cli/provider_keys.py +73 -0
  213. aria_code/apps/cli/providers/__init__.py +1 -0
  214. aria_code/apps/cli/providers/base.py +775 -0
  215. aria_code/apps/cli/providers/chat_routing.py +139 -0
  216. aria_code/apps/cli/providers/collaboration.py +98 -0
  217. aria_code/apps/cli/providers/llm/__init__.py +1 -0
  218. aria_code/apps/cli/providers/llm/offline_responses.py +68 -0
  219. aria_code/apps/cli/providers/llm/ollama_stream.py +1574 -0
  220. aria_code/apps/cli/providers/llm/response_cache.py +60 -0
  221. aria_code/apps/cli/providers/llm/sse_stream.py +298 -0
  222. aria_code/apps/cli/providers/runtime_bridge.py +586 -0
  223. aria_code/apps/cli/providers/vertexai_stream.py +592 -0
  224. aria_code/apps/cli/release_download.py +159 -0
  225. aria_code/apps/cli/review_runner.py +111 -0
  226. aria_code/apps/cli/runtime_consumer.py +769 -0
  227. aria_code/apps/cli/sandbox.py +32 -0
  228. aria_code/apps/cli/session_export.py +120 -0
  229. aria_code/apps/cli/session_jsonl.py +208 -0
  230. aria_code/apps/cli/session_refresh.py +123 -0
  231. aria_code/apps/cli/session_store.py +125 -0
  232. aria_code/apps/cli/skills_catalog.py +273 -0
  233. aria_code/apps/cli/task_isolation.py +211 -0
  234. aria_code/apps/cli/terminal_chrome.py +412 -0
  235. aria_code/apps/cli/todo_tracker.py +190 -0
  236. aria_code/apps/cli/tool_executor.py +932 -0
  237. aria_code/apps/cli/tool_registry.py +34 -0
  238. aria_code/apps/cli/tool_scope.py +113 -0
  239. aria_code/apps/cli/tools/__init__.py +40 -0
  240. aria_code/apps/cli/tools/context.py +46 -0
  241. aria_code/apps/cli/tools/file_tools.py +181 -0
  242. aria_code/apps/cli/tools/market_tools.py +626 -0
  243. aria_code/apps/cli/tools/notebook_tools.py +111 -0
  244. aria_code/apps/cli/tools/system_tools.py +656 -0
  245. aria_code/apps/cli/tools/write_tools.py +961 -0
  246. aria_code/apps/cli/tradingview_bridge.py +529 -0
  247. aria_code/apps/cli/transactions.py +269 -0
  248. aria_code/apps/cli/turn_planning.py +137 -0
  249. aria_code/apps/cli/update_check.py +257 -0
  250. aria_code/apps/cli/updater.py +373 -0
  251. aria_code/apps/cli/utils/__init__.py +0 -0
  252. aria_code/apps/cli/utils/market_detect.py +1663 -0
  253. aria_code/apps/cli/web_login.py +136 -0
  254. aria_code/apps/cli/workflow_runner.py +127 -0
  255. aria_code/apps/cli/workspace_route.py +121 -0
  256. aria_code/apps/daemon/README.md +14 -0
  257. aria_code/apps/vscode/README.md +115 -0
  258. aria_code/apps/vscode/package.json +70 -0
  259. aria_code/aria_cli.py +5244 -0
  260. aria_code/aria_daemon.py +1372 -0
  261. aria_code/aria_feishu_bot.py +16 -0
  262. aria_code/aria_mcp_server.py +61 -0
  263. aria_code/aria_relay_client.py +4 -0
  264. aria_code/aria_telegram_bot.py +11 -0
  265. aria_code/ariarc.py +385 -0
  266. aria_code/artifacts.py +581 -0
  267. aria_code/backtest_engine.py +4 -0
  268. aria_code/backtest_report.py +4 -0
  269. aria_code/brokers/__init__.py +78 -0
  270. aria_code/brokers/automation.py +193 -0
  271. aria_code/brokers/base.py +231 -0
  272. aria_code/brokers/capabilities.py +264 -0
  273. aria_code/brokers/cn/__init__.py +10 -0
  274. aria_code/brokers/cn/easytrader_broker.py +193 -0
  275. aria_code/brokers/cn/futu_broker.py +194 -0
  276. aria_code/brokers/cn/longbridge_broker.py +190 -0
  277. aria_code/brokers/cn/tiger_broker.py +196 -0
  278. aria_code/brokers/cn/xtquant_broker.py +225 -0
  279. aria_code/brokers/config.py +414 -0
  280. aria_code/brokers/intl/__init__.py +5 -0
  281. aria_code/brokers/intl/alpaca_broker.py +183 -0
  282. aria_code/brokers/intl/ibkr_broker.py +215 -0
  283. aria_code/brokers/intl/trading212_broker.py +183 -0
  284. aria_code/brokers/intl/webull_broker.py +156 -0
  285. aria_code/brokers/paper_broker.py +266 -0
  286. aria_code/brokers/planning.py +296 -0
  287. aria_code/brokers/registry.py +213 -0
  288. aria_code/brokers/trading.py +267 -0
  289. aria_code/canva_client.py +4 -0
  290. aria_code/change_store.py +127 -0
  291. aria_code/clients/__init__.py +0 -0
  292. aria_code/clients/aliyun_data_client.py +660 -0
  293. aria_code/clients/aria_relay_client.py +16 -0
  294. aria_code/clients/canva_client.py +284 -0
  295. aria_code/clients/figma_client.py +100 -0
  296. aria_code/clients/football_data_client.py +1671 -0
  297. aria_code/clients/kling_video_client.py +182 -0
  298. aria_code/clients/market_data_client.py +1985 -0
  299. aria_code/clients/openai_image_client.py +242 -0
  300. aria_code/clients/runway_video_client.py +157 -0
  301. aria_code/clients/warehouse_erp_client.py +105 -0
  302. aria_code/cloud_memory.py +190 -0
  303. aria_code/command_safety.py +19 -0
  304. aria_code/computer_use_server.py +276 -0
  305. aria_code/computer_use_tools.py +4 -0
  306. aria_code/dashboard_generator.py +579 -0
  307. aria_code/data_analysis_tools.py +4 -0
  308. aria_code/data_cleaner.py +483 -0
  309. aria_code/data_service.py +513 -0
  310. aria_code/datasources/__init__.py +23 -0
  311. aria_code/datasources/base.py +166 -0
  312. aria_code/datasources/router.py +253 -0
  313. aria_code/datasources/sec_statements.py +217 -0
  314. aria_code/datasources/sources/__init__.py +15 -0
  315. aria_code/datasources/sources/akshare_source.py +269 -0
  316. aria_code/datasources/sources/alpha_vantage_source.py +203 -0
  317. aria_code/datasources/sources/edgar_source.py +219 -0
  318. aria_code/datasources/sources/finnhub_source.py +198 -0
  319. aria_code/datasources/sources/fred_source.py +223 -0
  320. aria_code/datasources/sources/tushare_source.py +143 -0
  321. aria_code/datasources/sources/web_scraper_source.py +278 -0
  322. aria_code/datasources/sources/world_bank_source.py +206 -0
  323. aria_code/datasources/sources/yfinance_source.py +152 -0
  324. aria_code/doctor.py +860 -0
  325. aria_code/domain/__init__.py +0 -0
  326. aria_code/domain/_finance_core/__init__.py +5 -0
  327. aria_code/domain/_finance_core/backtest_engine.py +325 -0
  328. aria_code/domain/_finance_core/performance_stats.py +101 -0
  329. aria_code/domain/backtest_engine.py +75 -0
  330. aria_code/domain/backtest_report.py +488 -0
  331. aria_code/domain/finance_formulas.py +389 -0
  332. aria_code/domain/performance_stats.py +6 -0
  333. aria_code/domain/portfolio_ledger.py +307 -0
  334. aria_code/domain/strategy_vault.py +421 -0
  335. aria_code/evals/__init__.py +37 -0
  336. aria_code/evals/behavior.py +113 -0
  337. aria_code/evals/gap.py +93 -0
  338. aria_code/evals/harness.py +949 -0
  339. aria_code/evals/review_probe.py +132 -0
  340. aria_code/evals/runner.py +425 -0
  341. aria_code/evals/scorecard.py +322 -0
  342. aria_code/evals/summary.py +125 -0
  343. aria_code/external_agent_runner.py +115 -0
  344. aria_code/figma_client.py +4 -0
  345. aria_code/file_analysis_tools.py +4 -0
  346. aria_code/finance_formulas.py +4 -0
  347. aria_code/football_data_client.py +4 -0
  348. aria_code/image_gen_tools.py +4 -0
  349. aria_code/intent_classifier.py +459 -0
  350. aria_code/kling_video_client.py +4 -0
  351. aria_code/licensing.py +151 -0
  352. aria_code/local_finance_tools.py +4 -0
  353. aria_code/local_image_provider.py +4 -0
  354. aria_code/local_llm_provider.py +4 -0
  355. aria_code/macro_tools.py +4 -0
  356. aria_code/markdown_pdf.py +289 -0
  357. aria_code/market_data_client.py +4 -0
  358. aria_code/mcp_client.py +744 -0
  359. aria_code/memory_manager.py +273 -0
  360. aria_code/model_capability.py +512 -0
  361. aria_code/notification_tools.py +4 -0
  362. aria_code/openai_image_client.py +4 -0
  363. aria_code/packages/__init__.py +26 -0
  364. aria_code/packages/adk_bridge/__init__.py +11 -0
  365. aria_code/packages/adk_bridge/code_review_tools.py +49 -0
  366. aria_code/packages/adk_bridge/market_tools.py +125 -0
  367. aria_code/packages/aria_agents/__init__.py +5 -0
  368. aria_code/packages/aria_agents/manifest.py +78 -0
  369. aria_code/packages/aria_core/__init__.py +34 -0
  370. aria_code/packages/aria_core/architecture.py +269 -0
  371. aria_code/packages/aria_core/export.py +147 -0
  372. aria_code/packages/aria_core/manifest.py +65 -0
  373. aria_code/packages/aria_core/paths.py +57 -0
  374. aria_code/packages/aria_core/secure_file.py +68 -0
  375. aria_code/packages/aria_infra/__init__.py +15 -0
  376. aria_code/packages/aria_infra/arthera.py +58 -0
  377. aria_code/packages/aria_infra/doctor.py +246 -0
  378. aria_code/packages/aria_infra/product.py +40 -0
  379. aria_code/packages/aria_mcp/__init__.py +25 -0
  380. aria_code/packages/aria_mcp/bridge.py +232 -0
  381. aria_code/packages/aria_mcp/circuit.py +82 -0
  382. aria_code/packages/aria_mcp/config.py +162 -0
  383. aria_code/packages/aria_mcp/installer.py +95 -0
  384. aria_code/packages/aria_mcp/server.py +1705 -0
  385. aria_code/packages/aria_mcp/tools.py +81 -0
  386. aria_code/packages/aria_sdk/__init__.py +19 -0
  387. aria_code/packages/aria_sdk/client.py +393 -0
  388. aria_code/packages/aria_sdk/providers.py +70 -0
  389. aria_code/packages/aria_sdk/streaming.py +75 -0
  390. aria_code/packages/aria_sdk/types.py +86 -0
  391. aria_code/packages/aria_services/__init__.py +92 -0
  392. aria_code/packages/aria_services/cache.py +60 -0
  393. aria_code/packages/aria_services/context.py +356 -0
  394. aria_code/packages/aria_services/context_checkpoints.py +157 -0
  395. aria_code/packages/aria_services/data.py +11 -0
  396. aria_code/packages/aria_services/provider_health.py +304 -0
  397. aria_code/packages/aria_services/references.py +247 -0
  398. aria_code/packages/aria_services/registry.py +249 -0
  399. aria_code/packages/aria_services/research_protocol.py +137 -0
  400. aria_code/packages/aria_services/research_quality.py +186 -0
  401. aria_code/packages/aria_services/settings.py +160 -0
  402. aria_code/packages/aria_services/usage.py +151 -0
  403. aria_code/packages/aria_skills/__init__.py +46 -0
  404. aria_code/packages/aria_skills/catalog.py +149 -0
  405. aria_code/packages/aria_skills/loader.py +455 -0
  406. aria_code/packages/aria_skills/registry.py +84 -0
  407. aria_code/packages/aria_tools/__init__.py +5 -0
  408. aria_code/packages/aria_tools/financial/__init__.py +5 -0
  409. aria_code/packages/aria_tools/financial/_paths.py +92 -0
  410. aria_code/packages/aria_tools/registry.py +129 -0
  411. aria_code/packages/quant_engine/__init__.py +33 -0
  412. aria_code/packages/quant_engine/_namespace.py +24 -0
  413. aria_code/packages/quant_engine/backtest/__init__.py +10 -0
  414. aria_code/packages/quant_engine/backtest/core.py +53 -0
  415. aria_code/packages/quant_engine/backtest/engine.py +102 -0
  416. aria_code/packages/quant_engine/portfolio/__init__.py +9 -0
  417. aria_code/packages/quant_engine/portfolio/optimizer.py +85 -0
  418. aria_code/packages/quant_engine/sports/__init__.py +76 -0
  419. aria_code/packages/quant_engine/sports/calibrator.py +354 -0
  420. aria_code/packages/quant_engine/sports/dixon_coles.py +234 -0
  421. aria_code/packages/quant_engine/sports/elo.py +300 -0
  422. aria_code/packages/quant_engine/sports/form.py +188 -0
  423. aria_code/packages/quant_engine/sports/h2h.py +195 -0
  424. aria_code/packages/quant_engine/sports/predictor.py +312 -0
  425. aria_code/packages/quant_engine/sports/tracker.py +665 -0
  426. aria_code/packages/quant_engine/stochastic/__init__.py +31 -0
  427. aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +195 -0
  428. aria_code/packages/quant_engine/stochastic/ito_calculus.py +477 -0
  429. aria_code/packages/quant_engine/stochastic/kelly_criterion.py +181 -0
  430. aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +95 -0
  431. aria_code/packages/quant_engine/stochastic/options_pricing.py +576 -0
  432. aria_code/packages/quant_engine/stochastic/stochastic_processes.py +90 -0
  433. aria_code/packs/__init__.py +85 -0
  434. aria_code/packs/base.py +168 -0
  435. aria_code/packs/finance/__init__.py +250 -0
  436. aria_code/packs/healthcare/__init__.py +40 -0
  437. aria_code/packs/logistics/__init__.py +171 -0
  438. aria_code/packs/payments/__init__.py +139 -0
  439. aria_code/packs/realty/__init__.py +190 -0
  440. aria_code/packs/registry.py +202 -0
  441. aria_code/packs/rules.py +90 -0
  442. aria_code/plan_utils.py +194 -0
  443. aria_code/plugin_loader.py +328 -0
  444. aria_code/portfolio_ledger.py +4 -0
  445. aria_code/preview_server.py +449 -0
  446. aria_code/privacy/__init__.py +5 -0
  447. aria_code/privacy/feedback.py +123 -0
  448. aria_code/project_review.py +278 -0
  449. aria_code/project_review_api.py +235 -0
  450. aria_code/project_review_server.py +18 -0
  451. aria_code/project_tools.py +4 -0
  452. aria_code/providers/__init__.py +30 -0
  453. aria_code/providers/google_video_provider.py +256 -0
  454. aria_code/providers/llm/__init__.py +19 -0
  455. aria_code/providers/llm/anthropic.py +184 -0
  456. aria_code/providers/llm/arthera_gateway.py +90 -0
  457. aria_code/providers/llm/autoconfig.py +213 -0
  458. aria_code/providers/llm/base.py +139 -0
  459. aria_code/providers/llm/custom.py +158 -0
  460. aria_code/providers/llm/ollama.py +137 -0
  461. aria_code/providers/llm/openai_compat.py +350 -0
  462. aria_code/providers/llm/registry.py +457 -0
  463. aria_code/providers/local_image_provider.py +202 -0
  464. aria_code/providers/local_llm_provider.py +549 -0
  465. aria_code/providers/ollama_models.py +79 -0
  466. aria_code/providers/openai_params.py +32 -0
  467. aria_code/providers/tool_messages.py +100 -0
  468. aria_code/realty_data_tools.py +4 -0
  469. aria_code/report_exporters.py +150 -0
  470. aria_code/report_generator.py +1764 -0
  471. aria_code/review_service.py +497 -0
  472. aria_code/runtime/__init__.py +176 -0
  473. aria_code/runtime/acceptance.py +632 -0
  474. aria_code/runtime/agent_loop.py +1851 -0
  475. aria_code/runtime/agent_profiles.py +75 -0
  476. aria_code/runtime/approval.py +71 -0
  477. aria_code/runtime/baseline.py +219 -0
  478. aria_code/runtime/budget.py +232 -0
  479. aria_code/runtime/checkpoints.py +481 -0
  480. aria_code/runtime/consult.py +65 -0
  481. aria_code/runtime/contract.py +282 -0
  482. aria_code/runtime/delivery.py +432 -0
  483. aria_code/runtime/events.py +113 -0
  484. aria_code/runtime/gateway.py +167 -0
  485. aria_code/runtime/lsp.py +484 -0
  486. aria_code/runtime/native_index.py +153 -0
  487. aria_code/runtime/orchestrator.py +55 -0
  488. aria_code/runtime/processes.py +343 -0
  489. aria_code/runtime/project_graph.py +614 -0
  490. aria_code/runtime/repo_map.py +712 -0
  491. aria_code/runtime/research_bundle.py +105 -0
  492. aria_code/runtime/review.py +269 -0
  493. aria_code/runtime/run_state.py +127 -0
  494. aria_code/runtime/run_store.py +522 -0
  495. aria_code/runtime/scoped_runs.py +113 -0
  496. aria_code/runtime/self_healing.py +422 -0
  497. aria_code/runtime/semantic_diff.py +171 -0
  498. aria_code/runtime/subagent.py +721 -0
  499. aria_code/runtime/symbol_edit.py +117 -0
  500. aria_code/runtime/task_brief.py +46 -0
  501. aria_code/runtime/task_context.py +145 -0
  502. aria_code/runtime/task_ledger.py +108 -0
  503. aria_code/runtime/task_orchestrator.py +90 -0
  504. aria_code/runtime/task_outcome.py +33 -0
  505. aria_code/runtime/task_verification.py +266 -0
  506. aria_code/runtime/task_worktree.py +448 -0
  507. aria_code/runtime/tool_executor.py +329 -0
  508. aria_code/runtime/tool_policy.py +107 -0
  509. aria_code/runtime/transactions.py +216 -0
  510. aria_code/runtime/windows_job.py +115 -0
  511. aria_code/runtime/workflows.py +222 -0
  512. aria_code/runtime/worktrees.py +215 -0
  513. aria_code/runway_video_client.py +4 -0
  514. aria_code/safety/__init__.py +27 -0
  515. aria_code/safety/client_isolation.py +178 -0
  516. aria_code/safety/permissions.py +339 -0
  517. aria_code/safety/risk.py +699 -0
  518. aria_code/safety/sandbox.py +148 -0
  519. aria_code/safety/service.py +102 -0
  520. aria_code/service_endpoints.py +14 -0
  521. aria_code/setup_wizard.py +684 -0
  522. aria_code/spreadsheet_tools.py +4 -0
  523. aria_code/strategy_vault.py +4 -0
  524. aria_code/tools/__init__.py +0 -0
  525. aria_code/tools/artifact_tools.py +252 -0
  526. aria_code/tools/broker_tools.py +92 -0
  527. aria_code/tools/build_quant_engine.py +97 -0
  528. aria_code/tools/code_audit_tools.py +192 -0
  529. aria_code/tools/computer_use_tools.py +509 -0
  530. aria_code/tools/data_analysis_tools.py +831 -0
  531. aria_code/tools/enterprise_finance_tools.py +202 -0
  532. aria_code/tools/extended_tools.py +240 -0
  533. aria_code/tools/file_analysis_tools.py +880 -0
  534. aria_code/tools/image_gen_tools.py +114 -0
  535. aria_code/tools/local_finance_tools.py +3488 -0
  536. aria_code/tools/logistics_carriers.py +11 -0
  537. aria_code/tools/logistics_inventory.py +11 -0
  538. aria_code/tools/logistics_io.py +11 -0
  539. aria_code/tools/logistics_tenancy.py +11 -0
  540. aria_code/tools/logistics_tools.py +11 -0
  541. aria_code/tools/macro_tools.py +412 -0
  542. aria_code/tools/notification_tools.py +249 -0
  543. aria_code/tools/project_tools.py +525 -0
  544. aria_code/tools/realty_data_tools.py +662 -0
  545. aria_code/tools/spreadsheet_tools.py +399 -0
  546. aria_code/tools/stripe_tools.py +115 -0
  547. aria_code/tools/video_tools.py +500 -0
  548. aria_code/training/__init__.py +1 -0
  549. aria_code/training/compare.py +117 -0
  550. aria_code/training/prelude_commands.py +111 -0
  551. aria_code/training/prelude_eval.py +390 -0
  552. aria_code/training/prelude_real.py +183 -0
  553. aria_code/training/prelude_train.py +248 -0
  554. aria_code/training/sft_dataset.py +230 -0
  555. aria_code/training/trajectory_dataset.py +263 -0
  556. aria_code/ui/__init__.py +105 -0
  557. aria_code/ui/banner.py +404 -0
  558. aria_code/ui/completer.py +571 -0
  559. aria_code/ui/console.py +285 -0
  560. aria_code/ui/input_box.py +505 -0
  561. aria_code/ui/mentions.py +206 -0
  562. aria_code/ui/picker.py +248 -0
  563. aria_code/ui/render/__init__.py +11 -0
  564. aria_code/ui/render/actions.py +297 -0
  565. aria_code/ui/render/finance.py +1732 -0
  566. aria_code/ui/render/market.py +253 -0
  567. aria_code/ui/render/output.py +954 -0
  568. aria_code/ui/render/responsive.py +75 -0
  569. aria_code/ui/render/team.py +367 -0
  570. aria_code/ui/robot.py +239 -0
  571. aria_code/ui/startup_dashboard.py +110 -0
  572. aria_code/video_analysis.py +147 -0
  573. aria_code/video_editor.py +518 -0
  574. aria_code/video_workflow/__init__.py +8 -0
  575. aria_code/video_workflow/__main__.py +61 -0
  576. aria_code/video_workflow/engines/__init__.py +18 -0
  577. aria_code/video_workflow/engines/base.py +69 -0
  578. aria_code/video_workflow/engines/custom_model.py +204 -0
  579. aria_code/video_workflow/engines/google_veo.py +94 -0
  580. aria_code/video_workflow/engines/local_engine.py +71 -0
  581. aria_code/video_workflow/engines/registry.py +98 -0
  582. aria_code/video_workflow/google_models.py +278 -0
  583. aria_code/video_workflow/music/__init__.py +5 -0
  584. aria_code/video_workflow/music/foley_service.py +132 -0
  585. aria_code/video_workflow/music/service.py +212 -0
  586. aria_code/video_workflow/pipeline.py +620 -0
  587. aria_code/video_workflow/plan.py +202 -0
  588. aria_code/video_workflow/session.py +297 -0
  589. aria_code/workspace/__init__.py +6 -0
  590. aria_code/workspace/files.py +219 -0
  591. aria_code/workspace/verify.py +167 -0
  592. aria_code/workspace_changes.py +199 -0
  593. aria_code/workspace_service.py +196 -0
  594. aria_code/workspace_tools.py +150 -0
  595. aria_code-0.167.0.dist-info/METADATA +330 -0
  596. aria_code-0.167.0.dist-info/RECORD +601 -0
  597. aria_code-0.167.0.dist-info/WHEEL +5 -0
  598. aria_code-0.167.0.dist-info/entry_points.txt +5 -0
  599. aria_code-0.167.0.dist-info/licenses/LICENSE +201 -0
  600. aria_code-0.167.0.dist-info/licenses/NOTICE +49 -0
  601. aria_code-0.167.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,105 @@
1
+ """Static research evidence inventory. Integrity and scope are not scientific truth."""
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import hashlib
6
+ import json
7
+
8
+ from .task_verification import _read_file, _json_object, _json_float, _json_constant
9
+
10
+ KINDS = {'design', 'public_data', 'synthetic_data', 'analysis', 'code', 'simulation'}
11
+ SCOPES = {
12
+ 'proposal': KINDS,
13
+ 'analytical': {'analysis'},
14
+ 'software': {'code'},
15
+ 'simulation': {'simulation'},
16
+ 'real_world': set(),
17
+ }
18
+
19
+
20
+ def _text(value, limit=4096):
21
+ if not isinstance(value, str) or not value.strip() or len(value) > limit:
22
+ raise ValueError('Missing or oversized research field')
23
+ return value
24
+
25
+
26
+ def audit_bundle(workspace: str, manifest_path: str) -> dict:
27
+ """Read bounded workspace artifacts without executing code or opening URLs.
28
+
29
+ All provenance kinds are declarations, not authenticated source attestations.
30
+ This no-hardware inventory never establishes a real-world result.
31
+ """
32
+ manifest = json.loads(_read_file(workspace, manifest_path), object_pairs_hook=_json_object,
33
+ parse_float=_json_float, parse_constant=_json_constant)
34
+ if not isinstance(manifest, dict) or type(manifest.get('version')) is not int or manifest['version'] != 1:
35
+ raise ValueError('Unsupported research bundle version')
36
+ _text(manifest.get('question'))
37
+ _text(manifest.get('hypothesis'))
38
+ limitations = manifest.get('limitations')
39
+ if not isinstance(limitations, list) or not 1 <= len(limitations) <= 32:
40
+ raise ValueError('Explicit research limitations are required')
41
+ for item in limitations:
42
+ _text(item)
43
+ artifacts = manifest.get('artifacts')
44
+ claims = manifest.get('claims')
45
+ if not isinstance(artifacts, list) or not 1 <= len(artifacts) <= 16:
46
+ raise ValueError('Expected 1..16 artifacts')
47
+ if not isinstance(claims, list) or not 1 <= len(claims) <= 32:
48
+ raise ValueError('Expected 1..32 claims')
49
+ inventory = {}
50
+ reports = []
51
+ for item in artifacts:
52
+ if not isinstance(item, dict):
53
+ raise ValueError('Invalid artifact declaration')
54
+ ident = _text(item.get('id'), 128)
55
+ if ident in inventory or not isinstance(item.get('kind'), str) or item['kind'] not in KINDS:
56
+ raise ValueError('Duplicate artifact ID or unsupported evidence kind')
57
+ digest = item.get('sha256')
58
+ if not isinstance(digest, str) or len(digest) != 64 or any(c not in '0123456789abcdef' for c in digest):
59
+ raise ValueError('Artifact requires a SHA-256 digest')
60
+ data = _read_file(workspace, item.get('path'))
61
+ matched = hashlib.sha256(data).hexdigest() == digest
62
+ inventory[ident] = item['kind']
63
+ reports.append({'id': ident, 'kind': item['kind'], 'digest_matches': matched})
64
+ claim_ids = set()
65
+ dispositions = []
66
+ for claim in claims:
67
+ if not isinstance(claim, dict):
68
+ raise ValueError('Invalid claim declaration')
69
+ ident = _text(claim.get('id'), 128)
70
+ _text(claim.get('text'))
71
+ scope = claim.get('scope')
72
+ refs = claim.get('evidence')
73
+ if ident in claim_ids or not isinstance(scope, str) or scope not in SCOPES:
74
+ raise ValueError('Duplicate claim ID or unsupported claim scope')
75
+ claim_ids.add(ident)
76
+ if (not isinstance(refs, list) or not 1 <= len(refs) <= 16
77
+ or any(not isinstance(ref, str) or ref not in inventory for ref in refs)):
78
+ raise ValueError('Claim requires known evidence IDs')
79
+ compatible = any(inventory[ref] in SCOPES[scope] for ref in refs)
80
+ dispositions.append({'id': ident, 'scope': scope,
81
+ 'scope_supported': compatible, 'scientifically_verified': None})
82
+ integrity = all(report['digest_matches'] for report in reports)
83
+ return {'version': 1, 'success': integrity and all(c['scope_supported'] for c in dispositions),
84
+ 'integrity_verified': integrity, 'scientifically_verified': None,
85
+ 'real_world_validation': 'not_established', 'semantic_review_required': True,
86
+ 'coverage': 'artifact_hashes_and_declared_evidence_scope_only',
87
+ 'artifacts': reports, 'claims': dispositions}
88
+
89
+
90
+ def main():
91
+ parser = argparse.ArgumentParser(description=__doc__)
92
+ parser.add_argument('workspace')
93
+ parser.add_argument('manifest')
94
+ args = parser.parse_args()
95
+ try:
96
+ report = audit_bundle(args.workspace, args.manifest)
97
+ except (OSError, ValueError, TypeError, RecursionError):
98
+ report = {'success': False, 'error': 'Missing, unsafe or invalid research bundle',
99
+ 'scientifically_verified': None, 'real_world_validation': 'not_established'}
100
+ print(json.dumps(report, indent=2))
101
+ return 0 if report['success'] else 1
102
+
103
+
104
+ if __name__ == '__main__':
105
+ raise SystemExit(main())
@@ -0,0 +1,269 @@
1
+ """The review gate — an independent reviewer reads the change before "done".
2
+
3
+ Asking the model that wrote a change whether it is right gets the same
4
+ reasoning that produced it, mistakes included. The reviewer here is a separate
5
+ model call with a fresh context and no tools. It sees only what an outside
6
+ reviewer would: the user's goal, the change contract, the checks that ran and
7
+ their results, and the diff. Not the builder's reasoning, not the transcript.
8
+
9
+ It answers in JSON — a verdict and findings, each ``blocking`` or
10
+ ``suggestion``. Blocking means the change is wrong or unsafe for the goal: a
11
+ bug, a broken edge case, a security hole, a contract breach. Style never is.
12
+ When it blocks and an attempt is left, the findings go back to the builder as
13
+ the next message, the same way red checks do; otherwise they go into the
14
+ delivery report's *Review* section.
15
+
16
+ A reviewer that fails — no answer, no JSON — never blocks: the report says the
17
+ review did not complete, and the turn ends on its other evidence.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import dataclasses
23
+ import inspect
24
+ import json
25
+ import re
26
+ from dataclasses import dataclass, field
27
+ from typing import Any, Awaitable, Callable, Optional, Sequence, Union
28
+
29
+ REVIEWER_SYSTEM = (
30
+ "You are an independent code reviewer. You did not write the change in front "
31
+ "of you, and you cannot run or edit anything: you read and judge. Do not call "
32
+ "tools. Answer with one JSON object and nothing else."
33
+ )
34
+
35
+ _INSTRUCTIONS = """\
36
+ Review the change below against the goal.
37
+
38
+ Report as BLOCKING only what makes the change wrong or unsafe for the goal:
39
+ incorrect behaviour, a missed requirement, a broken edge case the goal implies,
40
+ a security problem, data loss, or a breach of the change contract. Everything
41
+ else — naming, style, structure, extra tests you would like — is a SUGGESTION.
42
+ Do not report problems in code the change did not touch. If you are unsure
43
+ whether something is a bug, it is a suggestion.
44
+
45
+ Answer with exactly this JSON shape:
46
+ {"verdict": "pass" | "blocking",
47
+ "summary": "<one sentence>",
48
+ "findings": [{"severity": "blocking" | "suggestion",
49
+ "file": "<path>", "line": <number or null>,
50
+ "issue": "<what is wrong and why, one or two sentences>"}],
51
+ "behaviour": {"before": "<what the code did before, one sentence>",
52
+ "after": "<what it does now>",
53
+ "why": "<why the change was needed, from the goal>",
54
+ "impact": "<callers, modules or users affected>"}}
55
+ "verdict" is "blocking" exactly when a finding is blocking. "behaviour" describes
56
+ the change in terms of behaviour, not lines; leave a field empty if the diff does
57
+ not say."""
58
+
59
+ Reviewer = Callable[[str], Union[str, Awaitable[str]]]
60
+
61
+
62
+ @dataclass(frozen=True)
63
+ class ReviewFinding:
64
+ severity: str
65
+ issue: str
66
+ file: str = ""
67
+ line: Optional[int] = None
68
+
69
+ @property
70
+ def blocking(self) -> bool:
71
+ return self.severity == "blocking"
72
+
73
+ def where(self) -> str:
74
+ if not self.file:
75
+ return ""
76
+ return f"{self.file}:{self.line}" if self.line else self.file
77
+
78
+ def as_dict(self) -> dict:
79
+ return {"severity": self.severity, "file": self.file, "line": self.line, "issue": self.issue}
80
+
81
+
82
+ @dataclass(frozen=True)
83
+ class ReviewReport:
84
+ verdict: str # "pass" | "blocking" | "error"
85
+ summary: str = ""
86
+ findings: tuple = ()
87
+ attempt: int = 1
88
+ error: str = ""
89
+ behaviour: Optional[dict] = None
90
+ # The model that read the diff, when it is not the one that wrote it
91
+ # (`review_model`); empty for a same-model review.
92
+ reviewer: str = ""
93
+
94
+ @property
95
+ def blocking(self) -> tuple:
96
+ return tuple(f for f in self.findings if f.blocking)
97
+
98
+ @property
99
+ def suggestions(self) -> tuple:
100
+ return tuple(f for f in self.findings if not f.blocking)
101
+
102
+ def headline(self) -> str:
103
+ if self.verdict == "error":
104
+ return f"Review did not complete: {self.error}"
105
+ if self.blocking:
106
+ count = len(self.blocking)
107
+ return f"Review: {count} blocking finding{'s' if count != 1 else ''}"
108
+ tail = f" · {len(self.suggestions)} suggestion{'s' if len(self.suggestions) != 1 else ''}" \
109
+ if self.suggestions else ""
110
+ return f"Review: no blocking findings{tail}"
111
+
112
+ def lines(self, limit: int = 5) -> list[str]:
113
+ """The Review section of the delivery report."""
114
+ if self.verdict == "error":
115
+ return [f"⚠ did not complete: {self.error}"]
116
+ by = f" (reviewed by {self.reviewer})" if self.reviewer else ""
117
+ out = [("✗ " if self.blocking else "✓ ") + self.headline().removeprefix("Review: ") + by]
118
+ for finding in (self.blocking + self.suggestions)[:limit]:
119
+ mark = "✗" if finding.blocking else "·"
120
+ where = f"{finding.where()} — " if finding.where() else ""
121
+ out.append(f" {mark} {where}{finding.issue}")
122
+ hidden = len(self.findings) - limit
123
+ if hidden > 0:
124
+ out.append(f" … +{hidden} more")
125
+ return out
126
+
127
+ def repair_directive(self) -> str:
128
+ items = "\n".join(
129
+ f"- {finding.where() + ': ' if finding.where() else ''}{finding.issue}" for finding in self.blocking
130
+ )
131
+ return (
132
+ "[Independent review]\n"
133
+ "A reviewer who saw only the goal, the contract, the checks and your diff "
134
+ f"found {len(self.blocking)} blocking problem{'s' if len(self.blocking) != 1 else ''}:\n"
135
+ f"{items}\n\n"
136
+ "Fix them, or — if a finding is wrong — say why in your final message. "
137
+ "The checks will run again after you change files."
138
+ )
139
+
140
+ def as_dict(self) -> dict:
141
+ data = {
142
+ "verdict": self.verdict,
143
+ "summary": self.summary,
144
+ "findings": [finding.as_dict() for finding in self.findings],
145
+ "attempt": self.attempt,
146
+ "error": self.error,
147
+ "headline": self.headline(),
148
+ "lines": self.lines(),
149
+ "behaviour": dict(self.behaviour) if self.behaviour else None,
150
+ }
151
+ # Only when another model reviewed: the Go runtime's report has no such field,
152
+ # and tests/test_native_go_review.py compares the two field by field.
153
+ if self.reviewer:
154
+ data["reviewer"] = self.reviewer
155
+ return data
156
+
157
+
158
+ def parse_review(text: str, *, attempt: int = 1) -> ReviewReport:
159
+ """The reviewer's answer as a report. Never raises; unparseable is an error."""
160
+ raw = str(text or "").strip()
161
+ if not raw:
162
+ return ReviewReport("error", attempt=attempt, error="the reviewer gave no answer")
163
+ fenced = re.search(r"```(?:json)?\s*(\{.*?\})\s*```", raw, re.DOTALL)
164
+ candidate = fenced.group(1) if fenced else raw[raw.find("{"): raw.rfind("}") + 1]
165
+ try:
166
+ data = json.loads(candidate)
167
+ except (ValueError, TypeError):
168
+ return ReviewReport("error", attempt=attempt, error="the reviewer's answer was not JSON")
169
+ if not isinstance(data, dict):
170
+ return ReviewReport("error", attempt=attempt, error="the reviewer's answer was not a JSON object")
171
+ findings = []
172
+ for item in data.get("findings") or []:
173
+ if not isinstance(item, dict) or not str(item.get("issue") or "").strip():
174
+ continue
175
+ severity = "blocking" if str(item.get("severity", "")).lower() == "blocking" else "suggestion"
176
+ line = item.get("line")
177
+ findings.append(ReviewFinding(
178
+ severity=severity,
179
+ issue=" ".join(str(item["issue"]).split()),
180
+ file=str(item.get("file") or "").strip(),
181
+ line=line if isinstance(line, int) and line > 0 else None,
182
+ ))
183
+ # The verdict follows the findings: a "blocking" verdict with no blocking
184
+ # finding gives the builder nothing to fix, and a "pass" over one would
185
+ # hide it.
186
+ verdict = "blocking" if any(f.blocking for f in findings) else "pass"
187
+ raw_behaviour = data.get("behaviour") or data.get("behavior")
188
+ behaviour = None
189
+ if isinstance(raw_behaviour, dict):
190
+ behaviour = {key: " ".join(str(raw_behaviour.get(key) or "").split())[:240]
191
+ for key in ("before", "after", "why", "impact")}
192
+ behaviour = {k: v for k, v in behaviour.items() if v} or None
193
+ return ReviewReport(verdict, summary=str(data.get("summary") or "").strip(),
194
+ findings=tuple(findings), attempt=attempt, behaviour=behaviour)
195
+
196
+
197
+ def build_review_prompt(*, goal: str, diff: str, checks: Sequence[dict] = (), contract: str = "",
198
+ max_diff_chars: int = 24_000) -> str:
199
+ if len(diff) > max_diff_chars:
200
+ omitted = len(diff) - max_diff_chars
201
+ diff = diff[:max_diff_chars] + f"\n… [{omitted:,} characters of diff omitted]"
202
+ check_lines = "\n".join(
203
+ f"{'PASS' if c.get('passed') else 'FAIL'} {c.get('command', '')}" for c in checks
204
+ ) or "(no checks ran)"
205
+ parts = [_INSTRUCTIONS, "", "GOAL", goal.strip() or "(not stated)"]
206
+ if contract:
207
+ parts += ["", "CONTRACT", contract.strip()]
208
+ parts += ["", "CHECKS", check_lines, "", "DIFF", diff.strip() or "(empty)"]
209
+ return "\n".join(parts)
210
+
211
+
212
+ @dataclass
213
+ class ReviewGate:
214
+ """Arms when a turn has changed files; reviews when the turn says it is done."""
215
+
216
+ reviewer: Reviewer
217
+ max_attempts: int = 1
218
+ max_diff_chars: int = 24_000
219
+ # Which model reviews, shown in the report; set when it differs from the builder.
220
+ reviewer_name: str = ""
221
+ reports: list = field(default_factory=list)
222
+
223
+ @property
224
+ def attempts(self) -> int:
225
+ return len(self.reports)
226
+
227
+ @property
228
+ def last(self) -> Optional[ReviewReport]:
229
+ return self.reports[-1] if self.reports else None
230
+
231
+ def should_run(self, *, changed: bool, reviewed_diff: str, diff: str) -> bool:
232
+ """Review a change once per distinct diff, up to max_attempts + 1 times."""
233
+ if not changed or not diff.strip():
234
+ return False
235
+ if self.reports and diff == reviewed_diff:
236
+ return False
237
+ return self.attempts <= self.max_attempts
238
+
239
+ def can_repair(self) -> bool:
240
+ return self.attempts <= self.max_attempts
241
+
242
+ async def run(self, *, goal: str, diff: str, checks: Sequence[dict] = (), contract: str = "") -> ReviewReport:
243
+ prompt = build_review_prompt(goal=goal, diff=diff, checks=checks, contract=contract,
244
+ max_diff_chars=self.max_diff_chars)
245
+ try:
246
+ answer = self.reviewer(prompt)
247
+ if inspect.isawaitable(answer):
248
+ answer = await answer
249
+ report = parse_review(str(answer or ""), attempt=self.attempts + 1)
250
+ if self.reviewer_name:
251
+ report = dataclasses.replace(report, reviewer=self.reviewer_name)
252
+ except Exception as exc:
253
+ report = ReviewReport("error", attempt=self.attempts + 1, error=f"{type(exc).__name__}: {exc}",
254
+ reviewer=self.reviewer_name)
255
+ self.reports.append(report)
256
+ return report
257
+
258
+ def summary(self) -> Optional[dict]:
259
+ return self.last.as_dict() if self.last else None
260
+
261
+
262
+ __all__ = [
263
+ "REVIEWER_SYSTEM",
264
+ "ReviewFinding",
265
+ "ReviewGate",
266
+ "ReviewReport",
267
+ "build_review_prompt",
268
+ "parse_review",
269
+ ]
@@ -0,0 +1,127 @@
1
+ """State machine for durable agent runs.
2
+
3
+ The model may suggest what to do next, but the runtime owns lifecycle state.
4
+ Keeping transitions explicit prevents a failed or interrupted turn from being
5
+ reported as successful merely because the generated text says it is done.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from enum import Enum
11
+ from typing import Dict, FrozenSet
12
+
13
+
14
+ class RunStatus(str, Enum):
15
+ QUEUED = "queued"
16
+ PLANNING = "planning"
17
+ RUNNING = "running"
18
+ WAITING_APPROVAL = "waiting_approval"
19
+ WAITING_USER = "waiting_user"
20
+ VERIFYING = "verifying"
21
+ SUCCEEDED = "succeeded"
22
+ FAILED = "failed"
23
+ CANCELLED = "cancelled"
24
+ INTERRUPTED = "interrupted"
25
+
26
+
27
+ TERMINAL_RUN_STATUSES: FrozenSet[RunStatus] = frozenset({
28
+ RunStatus.SUCCEEDED,
29
+ RunStatus.FAILED,
30
+ RunStatus.CANCELLED,
31
+ })
32
+
33
+ ACTIVE_RUN_STATUSES: FrozenSet[RunStatus] = frozenset({
34
+ RunStatus.QUEUED,
35
+ RunStatus.PLANNING,
36
+ RunStatus.RUNNING,
37
+ RunStatus.WAITING_APPROVAL,
38
+ RunStatus.WAITING_USER,
39
+ RunStatus.VERIFYING,
40
+ })
41
+
42
+ _TRANSITIONS: Dict[RunStatus, FrozenSet[RunStatus]] = {
43
+ RunStatus.QUEUED: frozenset({
44
+ RunStatus.PLANNING,
45
+ RunStatus.RUNNING,
46
+ RunStatus.FAILED,
47
+ RunStatus.CANCELLED,
48
+ RunStatus.INTERRUPTED,
49
+ }),
50
+ RunStatus.PLANNING: frozenset({
51
+ RunStatus.RUNNING,
52
+ RunStatus.WAITING_APPROVAL,
53
+ RunStatus.WAITING_USER,
54
+ RunStatus.FAILED,
55
+ RunStatus.CANCELLED,
56
+ RunStatus.INTERRUPTED,
57
+ }),
58
+ RunStatus.RUNNING: frozenset({
59
+ RunStatus.WAITING_APPROVAL,
60
+ RunStatus.WAITING_USER,
61
+ RunStatus.VERIFYING,
62
+ RunStatus.FAILED,
63
+ RunStatus.CANCELLED,
64
+ RunStatus.INTERRUPTED,
65
+ }),
66
+ RunStatus.WAITING_APPROVAL: frozenset({
67
+ RunStatus.RUNNING,
68
+ RunStatus.FAILED,
69
+ RunStatus.CANCELLED,
70
+ RunStatus.INTERRUPTED,
71
+ }),
72
+ RunStatus.WAITING_USER: frozenset({
73
+ RunStatus.RUNNING,
74
+ RunStatus.FAILED,
75
+ RunStatus.CANCELLED,
76
+ RunStatus.INTERRUPTED,
77
+ }),
78
+ RunStatus.VERIFYING: frozenset({
79
+ RunStatus.RUNNING,
80
+ RunStatus.SUCCEEDED,
81
+ RunStatus.FAILED,
82
+ RunStatus.CANCELLED,
83
+ RunStatus.INTERRUPTED,
84
+ }),
85
+ RunStatus.INTERRUPTED: frozenset({
86
+ RunStatus.PLANNING,
87
+ RunStatus.RUNNING,
88
+ RunStatus.FAILED,
89
+ RunStatus.CANCELLED,
90
+ }),
91
+ RunStatus.SUCCEEDED: frozenset(),
92
+ RunStatus.FAILED: frozenset(),
93
+ RunStatus.CANCELLED: frozenset(),
94
+ }
95
+
96
+
97
+ class InvalidRunTransition(ValueError):
98
+ """Raised when code attempts an unsupported lifecycle transition."""
99
+
100
+
101
+ def normalize_run_status(status: RunStatus | str) -> RunStatus:
102
+ if isinstance(status, RunStatus):
103
+ return status
104
+ try:
105
+ return RunStatus(str(status))
106
+ except ValueError as exc:
107
+ raise InvalidRunTransition(f"Unknown run status: {status!r}") from exc
108
+
109
+
110
+ def can_transition(current: RunStatus | str, target: RunStatus | str) -> bool:
111
+ source = normalize_run_status(current)
112
+ destination = normalize_run_status(target)
113
+ return source == destination or destination in _TRANSITIONS[source]
114
+
115
+
116
+ def require_transition(current: RunStatus | str, target: RunStatus | str) -> None:
117
+ source = normalize_run_status(current)
118
+ destination = normalize_run_status(target)
119
+ if not can_transition(source, destination):
120
+ raise InvalidRunTransition(
121
+ f"Invalid run transition: {source.value} -> {destination.value}"
122
+ )
123
+
124
+
125
+ def is_terminal(status: RunStatus | str) -> bool:
126
+ return normalize_run_status(status) in TERMINAL_RUN_STATUSES
127
+