aria-code 0.52.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 (478) hide show
  1. aria_code/__init__.py +42 -0
  2. aria_code/_version.py +20 -0
  3. aria_code/adk_apps/__init__.py +1 -0
  4. aria_code/adk_apps/aria_code_review/__init__.py +1 -0
  5. aria_code/adk_apps/aria_code_review/agent.py +32 -0
  6. aria_code/adk_apps/aria_research/__init__.py +1 -0
  7. aria_code/adk_apps/aria_research/agent.py +31 -0
  8. aria_code/agents/__init__.py +34 -0
  9. aria_code/agents/base.py +318 -0
  10. aria_code/agents/code_review.py +200 -0
  11. aria_code/agents/deep/__init__.py +37 -0
  12. aria_code/agents/deep/calibration_loop.py +144 -0
  13. aria_code/agents/deep/critic.py +125 -0
  14. aria_code/agents/deep/deepen.py +193 -0
  15. aria_code/agents/deep/models.py +149 -0
  16. aria_code/agents/deep/pipeline.py +164 -0
  17. aria_code/agents/deep/quant_fusion.py +192 -0
  18. aria_code/agents/deep/themes.py +95 -0
  19. aria_code/agents/deep/tiers.py +106 -0
  20. aria_code/agents/engineering/__init__.py +14 -0
  21. aria_code/agents/engineering/coder.py +222 -0
  22. aria_code/agents/engineering/tester.py +145 -0
  23. aria_code/agents/financial/__init__.py +21 -0
  24. aria_code/agents/financial/cashflow_burn.py +119 -0
  25. aria_code/agents/financial/catalyst.py +279 -0
  26. aria_code/agents/financial/corporate_finance.py +175 -0
  27. aria_code/agents/financial/debate.py +224 -0
  28. aria_code/agents/financial/earnings.py +303 -0
  29. aria_code/agents/financial/fundamental.py +191 -0
  30. aria_code/agents/financial/macro.py +99 -0
  31. aria_code/agents/financial/news.py +207 -0
  32. aria_code/agents/financial/risk.py +165 -0
  33. aria_code/agents/financial/sector.py +279 -0
  34. aria_code/agents/financial/strategist.py +121 -0
  35. aria_code/agents/financial/stripe_revenue.py +127 -0
  36. aria_code/agents/financial/synthesis.py +274 -0
  37. aria_code/agents/financial/technical.py +258 -0
  38. aria_code/agents/orchestrator.py +44 -0
  39. aria_code/agents/portfolio_agent.py +363 -0
  40. aria_code/agents/realty/__init__.py +62 -0
  41. aria_code/agents/realty/asset_diagnosis.py +152 -0
  42. aria_code/agents/realty/business_match.py +166 -0
  43. aria_code/agents/realty/cashflow_verify.py +209 -0
  44. aria_code/agents/realty/contract_rules.py +210 -0
  45. aria_code/agents/realty/energy_anomaly.py +189 -0
  46. aria_code/agents/realty/exit_settlement.py +208 -0
  47. aria_code/agents/realty/fulfillment_risk.py +206 -0
  48. aria_code/agents/realty/ops_optimize.py +160 -0
  49. aria_code/agents/realty/revenue_share.py +215 -0
  50. aria_code/agents/registry.py +158 -0
  51. aria_code/agents/signal_scheme.py +111 -0
  52. aria_code/agents/sports/__init__.py +0 -0
  53. aria_code/agents/sports/football_agent.py +197 -0
  54. aria_code/agents/supervisor.py +113 -0
  55. aria_code/agents/team.py +492 -0
  56. aria_code/agents/warehouse/__init__.py +25 -0
  57. aria_code/agents/warehouse/contracts.py +26 -0
  58. aria_code/agents/warehouse/dashboard.py +155 -0
  59. aria_code/agents/warehouse/fulfillment_leadtime.py +95 -0
  60. aria_code/agents/warehouse/inbound_exceptions.py +25 -0
  61. aria_code/agents/warehouse/inventory_health.py +24 -0
  62. aria_code/agents/warehouse/local_run.py +71 -0
  63. aria_code/agents/warehouse/local_snapshot.py +132 -0
  64. aria_code/agents/warehouse/logistics_cost.py +84 -0
  65. aria_code/agents/warehouse/logistics_sync.py +21 -0
  66. aria_code/agents/warehouse/workflow.py +31 -0
  67. aria_code/aliyun_data_client.py +4 -0
  68. aria_code/apps/README.md +12 -0
  69. aria_code/apps/__init__.py +2 -0
  70. aria_code/apps/channels/README.md +15 -0
  71. aria_code/apps/channels/__init__.py +17 -0
  72. aria_code/apps/channels/intake.py +92 -0
  73. aria_code/apps/channels/registry.py +95 -0
  74. aria_code/apps/channels/tradingview.py +94 -0
  75. aria_code/apps/cli/README.md +13 -0
  76. aria_code/apps/cli/__init__.py +2 -0
  77. aria_code/apps/cli/_optional.py +120 -0
  78. aria_code/apps/cli/bootstrap.py +145 -0
  79. aria_code/apps/cli/broker_render.py +206 -0
  80. aria_code/apps/cli/codegen_paths.py +29 -0
  81. aria_code/apps/cli/commands/__init__.py +16 -0
  82. aria_code/apps/cli/commands/_business_render.py +78 -0
  83. aria_code/apps/cli/commands/_ui.py +71 -0
  84. aria_code/apps/cli/commands/analysis_cmds.py +369 -0
  85. aria_code/apps/cli/commands/ashare_prediction_cmds.py +327 -0
  86. aria_code/apps/cli/commands/auth_cmds.py +239 -0
  87. aria_code/apps/cli/commands/backtest_cmds.py +2543 -0
  88. aria_code/apps/cli/commands/broker_cmds.py +1234 -0
  89. aria_code/apps/cli/commands/business_workflow_cmds.py +319 -0
  90. aria_code/apps/cli/commands/canvas_cmds.py +77 -0
  91. aria_code/apps/cli/commands/catalog.py +87 -0
  92. aria_code/apps/cli/commands/core_cmds.py +2520 -0
  93. aria_code/apps/cli/commands/data_cmds.py +457 -0
  94. aria_code/apps/cli/commands/diagnostic_cmds.py +230 -0
  95. aria_code/apps/cli/commands/diagnostic_ops_cmds.py +813 -0
  96. aria_code/apps/cli/commands/file_cmds.py +312 -0
  97. aria_code/apps/cli/commands/finance_service_cmds.py +60 -0
  98. aria_code/apps/cli/commands/fx_commodity_cmds.py +123 -0
  99. aria_code/apps/cli/commands/market.py +434 -0
  100. aria_code/apps/cli/commands/market_cmds.py +1381 -0
  101. aria_code/apps/cli/commands/market_context.py +425 -0
  102. aria_code/apps/cli/commands/market_render.py +7 -0
  103. aria_code/apps/cli/commands/model_cmds.py +2153 -0
  104. aria_code/apps/cli/commands/ops_cmds.py +721 -0
  105. aria_code/apps/cli/commands/orchestrator_cmds.py +179 -0
  106. aria_code/apps/cli/commands/pdf_export_cmds.py +125 -0
  107. aria_code/apps/cli/commands/portfolio_cmds.py +1278 -0
  108. aria_code/apps/cli/commands/report.py +437 -0
  109. aria_code/apps/cli/commands/scaffold_templates.py +617 -0
  110. aria_code/apps/cli/commands/session_cmds.py +236 -0
  111. aria_code/apps/cli/commands/session_ux_cmds.py +359 -0
  112. aria_code/apps/cli/commands/team.py +669 -0
  113. aria_code/apps/cli/commands/team_render.py +8 -0
  114. aria_code/apps/cli/commands/ui_cmds.py +401 -0
  115. aria_code/apps/cli/commands/warehouse_cmds.py +79 -0
  116. aria_code/apps/cli/commands/workflow_cmds.py +480 -0
  117. aria_code/apps/cli/commands/workspace_cmds.py +1494 -0
  118. aria_code/apps/cli/config_paths.py +73 -0
  119. aria_code/apps/cli/config_store.py +78 -0
  120. aria_code/apps/cli/constants.py +88 -0
  121. aria_code/apps/cli/context.py +34 -0
  122. aria_code/apps/cli/deterministic.py +191 -0
  123. aria_code/apps/cli/direct.py +48 -0
  124. aria_code/apps/cli/finance_service_catalog.py +111 -0
  125. aria_code/apps/cli/football_reports.py +231 -0
  126. aria_code/apps/cli/github_app_auth.py +135 -0
  127. aria_code/apps/cli/google_login.py +196 -0
  128. aria_code/apps/cli/handlers/__init__.py +11 -0
  129. aria_code/apps/cli/handlers/broker_handlers.py +122 -0
  130. aria_code/apps/cli/handlers/chart_handlers.py +1309 -0
  131. aria_code/apps/cli/handlers/market_handlers.py +2513 -0
  132. aria_code/apps/cli/handlers/realty_handlers.py +114 -0
  133. aria_code/apps/cli/handlers/sports_handlers.py +22 -0
  134. aria_code/apps/cli/handlers/strategy_advice.py +82 -0
  135. aria_code/apps/cli/helpers.py +302 -0
  136. aria_code/apps/cli/hooks.py +180 -0
  137. aria_code/apps/cli/i18n.py +297 -0
  138. aria_code/apps/cli/intent.py +136 -0
  139. aria_code/apps/cli/intent_router.py +276 -0
  140. aria_code/apps/cli/intent_signals.py +344 -0
  141. aria_code/apps/cli/lifecycle_hooks.py +48 -0
  142. aria_code/apps/cli/local_tool_schemas.py +536 -0
  143. aria_code/apps/cli/main.py +29 -0
  144. aria_code/apps/cli/market_metadata.py +135 -0
  145. aria_code/apps/cli/market_universe.py +487 -0
  146. aria_code/apps/cli/message_processing.py +310 -0
  147. aria_code/apps/cli/model_catalog.py +620 -0
  148. aria_code/apps/cli/pdf_report.py +977 -0
  149. aria_code/apps/cli/plan_mode.py +139 -0
  150. aria_code/apps/cli/plotly_html.py +15 -0
  151. aria_code/apps/cli/prediction_feedback.py +202 -0
  152. aria_code/apps/cli/preflight.py +502 -0
  153. aria_code/apps/cli/project_aria.py +60 -0
  154. aria_code/apps/cli/prompt_assembly.py +59 -0
  155. aria_code/apps/cli/prompts/__init__.py +0 -0
  156. aria_code/apps/cli/prompts/coding.py +53 -0
  157. aria_code/apps/cli/prompts/select.py +142 -0
  158. aria_code/apps/cli/prompts/system_prompts.py +552 -0
  159. aria_code/apps/cli/prompts/ui.py +436 -0
  160. aria_code/apps/cli/provider_endpoints.py +237 -0
  161. aria_code/apps/cli/provider_keys.py +73 -0
  162. aria_code/apps/cli/providers/__init__.py +1 -0
  163. aria_code/apps/cli/providers/base.py +521 -0
  164. aria_code/apps/cli/providers/chat_routing.py +128 -0
  165. aria_code/apps/cli/providers/collaboration.py +98 -0
  166. aria_code/apps/cli/providers/llm/__init__.py +1 -0
  167. aria_code/apps/cli/providers/llm/offline_responses.py +68 -0
  168. aria_code/apps/cli/providers/llm/ollama_stream.py +1594 -0
  169. aria_code/apps/cli/providers/llm/response_cache.py +60 -0
  170. aria_code/apps/cli/providers/llm/sse_stream.py +257 -0
  171. aria_code/apps/cli/providers/runtime_bridge.py +353 -0
  172. aria_code/apps/cli/providers/vertexai_stream.py +316 -0
  173. aria_code/apps/cli/runtime_consumer.py +657 -0
  174. aria_code/apps/cli/sandbox.py +32 -0
  175. aria_code/apps/cli/session_export.py +120 -0
  176. aria_code/apps/cli/session_jsonl.py +208 -0
  177. aria_code/apps/cli/session_store.py +112 -0
  178. aria_code/apps/cli/skills_catalog.py +273 -0
  179. aria_code/apps/cli/todo_tracker.py +190 -0
  180. aria_code/apps/cli/tool_executor.py +823 -0
  181. aria_code/apps/cli/tool_registry.py +34 -0
  182. aria_code/apps/cli/tool_scope.py +106 -0
  183. aria_code/apps/cli/tools/__init__.py +40 -0
  184. aria_code/apps/cli/tools/context.py +46 -0
  185. aria_code/apps/cli/tools/file_tools.py +180 -0
  186. aria_code/apps/cli/tools/market_tools.py +620 -0
  187. aria_code/apps/cli/tools/notebook_tools.py +111 -0
  188. aria_code/apps/cli/tools/system_tools.py +726 -0
  189. aria_code/apps/cli/tools/write_tools.py +845 -0
  190. aria_code/apps/cli/tradingview_bridge.py +529 -0
  191. aria_code/apps/cli/turn_planning.py +137 -0
  192. aria_code/apps/cli/update_check.py +153 -0
  193. aria_code/apps/cli/utils/__init__.py +0 -0
  194. aria_code/apps/cli/utils/market_detect.py +1597 -0
  195. aria_code/apps/daemon/README.md +14 -0
  196. aria_code/apps/vscode/README.md +115 -0
  197. aria_code/apps/vscode/package.json +70 -0
  198. aria_code/aria_cli.py +6743 -0
  199. aria_code/aria_daemon.py +1398 -0
  200. aria_code/aria_feishu_bot.py +1423 -0
  201. aria_code/aria_mcp_server.py +7 -0
  202. aria_code/aria_relay_client.py +4 -0
  203. aria_code/aria_relay_server.py +490 -0
  204. aria_code/aria_telegram_bot.py +202 -0
  205. aria_code/ariarc.py +385 -0
  206. aria_code/artifacts.py +581 -0
  207. aria_code/backtest_engine.py +4 -0
  208. aria_code/backtest_report.py +4 -0
  209. aria_code/brokers/__init__.py +78 -0
  210. aria_code/brokers/automation.py +193 -0
  211. aria_code/brokers/base.py +231 -0
  212. aria_code/brokers/capabilities.py +264 -0
  213. aria_code/brokers/cn/__init__.py +10 -0
  214. aria_code/brokers/cn/easytrader_broker.py +193 -0
  215. aria_code/brokers/cn/futu_broker.py +194 -0
  216. aria_code/brokers/cn/longbridge_broker.py +190 -0
  217. aria_code/brokers/cn/tiger_broker.py +196 -0
  218. aria_code/brokers/cn/xtquant_broker.py +225 -0
  219. aria_code/brokers/config.py +414 -0
  220. aria_code/brokers/intl/__init__.py +5 -0
  221. aria_code/brokers/intl/alpaca_broker.py +183 -0
  222. aria_code/brokers/intl/ibkr_broker.py +215 -0
  223. aria_code/brokers/intl/trading212_broker.py +183 -0
  224. aria_code/brokers/intl/webull_broker.py +156 -0
  225. aria_code/brokers/paper_broker.py +266 -0
  226. aria_code/brokers/planning.py +296 -0
  227. aria_code/brokers/registry.py +213 -0
  228. aria_code/brokers/trading.py +267 -0
  229. aria_code/canva_client.py +4 -0
  230. aria_code/change_store.py +127 -0
  231. aria_code/clients/__init__.py +0 -0
  232. aria_code/clients/aliyun_data_client.py +660 -0
  233. aria_code/clients/aria_relay_client.py +182 -0
  234. aria_code/clients/canva_client.py +284 -0
  235. aria_code/clients/figma_client.py +100 -0
  236. aria_code/clients/football_data_client.py +1671 -0
  237. aria_code/clients/kling_video_client.py +182 -0
  238. aria_code/clients/market_data_client.py +1976 -0
  239. aria_code/clients/openai_image_client.py +242 -0
  240. aria_code/clients/runway_video_client.py +157 -0
  241. aria_code/clients/warehouse_erp_client.py +105 -0
  242. aria_code/cloud_memory.py +181 -0
  243. aria_code/command_safety.py +19 -0
  244. aria_code/computer_use_tools.py +4 -0
  245. aria_code/dashboard_generator.py +579 -0
  246. aria_code/data_analysis_tools.py +4 -0
  247. aria_code/data_cleaner.py +483 -0
  248. aria_code/data_service.py +513 -0
  249. aria_code/datasources/__init__.py +23 -0
  250. aria_code/datasources/base.py +166 -0
  251. aria_code/datasources/router.py +253 -0
  252. aria_code/datasources/sources/__init__.py +15 -0
  253. aria_code/datasources/sources/akshare_source.py +269 -0
  254. aria_code/datasources/sources/alpha_vantage_source.py +203 -0
  255. aria_code/datasources/sources/edgar_source.py +219 -0
  256. aria_code/datasources/sources/finnhub_source.py +198 -0
  257. aria_code/datasources/sources/fred_source.py +223 -0
  258. aria_code/datasources/sources/tushare_source.py +143 -0
  259. aria_code/datasources/sources/web_scraper_source.py +278 -0
  260. aria_code/datasources/sources/world_bank_source.py +206 -0
  261. aria_code/datasources/sources/yfinance_source.py +152 -0
  262. aria_code/demo_player.py +207 -0
  263. aria_code/doctor.py +813 -0
  264. aria_code/domain/__init__.py +0 -0
  265. aria_code/domain/backtest_engine.py +354 -0
  266. aria_code/domain/backtest_report.py +472 -0
  267. aria_code/domain/finance_formulas.py +389 -0
  268. aria_code/domain/portfolio_ledger.py +307 -0
  269. aria_code/domain/strategy_vault.py +421 -0
  270. aria_code/evals/__init__.py +37 -0
  271. aria_code/evals/harness.py +598 -0
  272. aria_code/evals/runner.py +238 -0
  273. aria_code/external_agent_runner.py +115 -0
  274. aria_code/figma_client.py +4 -0
  275. aria_code/file_analysis_tools.py +4 -0
  276. aria_code/finance_formulas.py +4 -0
  277. aria_code/football_data_client.py +4 -0
  278. aria_code/image_gen_tools.py +4 -0
  279. aria_code/intent_classifier.py +386 -0
  280. aria_code/kling_video_client.py +4 -0
  281. aria_code/licensing.py +151 -0
  282. aria_code/local_finance_tools.py +4 -0
  283. aria_code/local_image_provider.py +4 -0
  284. aria_code/local_llm_provider.py +4 -0
  285. aria_code/macro_tools.py +4 -0
  286. aria_code/markdown_pdf.py +289 -0
  287. aria_code/market_data_client.py +4 -0
  288. aria_code/mcp_client.py +639 -0
  289. aria_code/memory_manager.py +246 -0
  290. aria_code/model_capability.py +486 -0
  291. aria_code/notification_tools.py +4 -0
  292. aria_code/openai_image_client.py +4 -0
  293. aria_code/packages/__init__.py +23 -0
  294. aria_code/packages/adk_bridge/__init__.py +11 -0
  295. aria_code/packages/adk_bridge/code_review_tools.py +49 -0
  296. aria_code/packages/adk_bridge/market_tools.py +125 -0
  297. aria_code/packages/aria_agents/__init__.py +5 -0
  298. aria_code/packages/aria_agents/manifest.py +78 -0
  299. aria_code/packages/aria_core/__init__.py +34 -0
  300. aria_code/packages/aria_core/architecture.py +269 -0
  301. aria_code/packages/aria_core/export.py +147 -0
  302. aria_code/packages/aria_core/manifest.py +65 -0
  303. aria_code/packages/aria_core/paths.py +57 -0
  304. aria_code/packages/aria_core/secure_file.py +68 -0
  305. aria_code/packages/aria_infra/__init__.py +15 -0
  306. aria_code/packages/aria_infra/arthera.py +52 -0
  307. aria_code/packages/aria_infra/doctor.py +246 -0
  308. aria_code/packages/aria_infra/product.py +40 -0
  309. aria_code/packages/aria_mcp/__init__.py +25 -0
  310. aria_code/packages/aria_mcp/bridge.py +201 -0
  311. aria_code/packages/aria_mcp/circuit.py +82 -0
  312. aria_code/packages/aria_mcp/config.py +111 -0
  313. aria_code/packages/aria_mcp/installer.py +95 -0
  314. aria_code/packages/aria_mcp/server.py +1550 -0
  315. aria_code/packages/aria_mcp/tools.py +81 -0
  316. aria_code/packages/aria_sdk/__init__.py +19 -0
  317. aria_code/packages/aria_sdk/client.py +396 -0
  318. aria_code/packages/aria_sdk/providers.py +70 -0
  319. aria_code/packages/aria_sdk/streaming.py +79 -0
  320. aria_code/packages/aria_sdk/types.py +86 -0
  321. aria_code/packages/aria_services/__init__.py +92 -0
  322. aria_code/packages/aria_services/cache.py +60 -0
  323. aria_code/packages/aria_services/context.py +356 -0
  324. aria_code/packages/aria_services/context_checkpoints.py +157 -0
  325. aria_code/packages/aria_services/data.py +11 -0
  326. aria_code/packages/aria_services/provider_health.py +268 -0
  327. aria_code/packages/aria_services/references.py +247 -0
  328. aria_code/packages/aria_services/registry.py +249 -0
  329. aria_code/packages/aria_services/research_protocol.py +57 -0
  330. aria_code/packages/aria_services/research_quality.py +186 -0
  331. aria_code/packages/aria_services/settings.py +157 -0
  332. aria_code/packages/aria_services/usage.py +151 -0
  333. aria_code/packages/aria_skills/__init__.py +46 -0
  334. aria_code/packages/aria_skills/catalog.py +149 -0
  335. aria_code/packages/aria_skills/loader.py +455 -0
  336. aria_code/packages/aria_skills/registry.py +84 -0
  337. aria_code/packages/aria_tools/__init__.py +5 -0
  338. aria_code/packages/aria_tools/financial/__init__.py +8 -0
  339. aria_code/packages/aria_tools/financial/_paths.py +130 -0
  340. aria_code/packages/aria_tools/financial/compliance.py +31 -0
  341. aria_code/packages/aria_tools/financial/factors.py +33 -0
  342. aria_code/packages/aria_tools/financial/risk_tools.py +33 -0
  343. aria_code/packages/aria_tools/financial/strategy.py +31 -0
  344. aria_code/packages/aria_tools/registry.py +128 -0
  345. aria_code/packages/quant_engine/__init__.py +34 -0
  346. aria_code/packages/quant_engine/_namespace.py +62 -0
  347. aria_code/packages/quant_engine/backtest/__init__.py +14 -0
  348. aria_code/packages/quant_engine/backtest/core.py +53 -0
  349. aria_code/packages/quant_engine/backtest/engine.py +96 -0
  350. aria_code/packages/quant_engine/portfolio/__init__.py +13 -0
  351. aria_code/packages/quant_engine/portfolio/optimizer.py +85 -0
  352. aria_code/packages/quant_engine/sports/__init__.py +80 -0
  353. aria_code/packages/quant_engine/sports/calibrator.py +354 -0
  354. aria_code/packages/quant_engine/sports/dixon_coles.py +234 -0
  355. aria_code/packages/quant_engine/sports/elo.py +300 -0
  356. aria_code/packages/quant_engine/sports/form.py +188 -0
  357. aria_code/packages/quant_engine/sports/h2h.py +195 -0
  358. aria_code/packages/quant_engine/sports/ml_model.py +377 -0
  359. aria_code/packages/quant_engine/sports/predictor.py +312 -0
  360. aria_code/packages/quant_engine/sports/tracker.py +665 -0
  361. aria_code/packages/quant_engine/stochastic/__init__.py +35 -0
  362. aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +195 -0
  363. aria_code/packages/quant_engine/stochastic/ito_calculus.py +477 -0
  364. aria_code/packages/quant_engine/stochastic/kelly_criterion.py +181 -0
  365. aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +95 -0
  366. aria_code/packages/quant_engine/stochastic/options_pricing.py +576 -0
  367. aria_code/packages/quant_engine/stochastic/stochastic_processes.py +90 -0
  368. aria_code/packs/__init__.py +85 -0
  369. aria_code/packs/base.py +168 -0
  370. aria_code/packs/finance/__init__.py +250 -0
  371. aria_code/packs/logistics/__init__.py +169 -0
  372. aria_code/packs/payments/__init__.py +139 -0
  373. aria_code/packs/realty/__init__.py +190 -0
  374. aria_code/packs/registry.py +202 -0
  375. aria_code/packs/rules.py +90 -0
  376. aria_code/plan_utils.py +194 -0
  377. aria_code/plugin_loader.py +328 -0
  378. aria_code/portfolio_ledger.py +4 -0
  379. aria_code/preview_server.py +449 -0
  380. aria_code/privacy/__init__.py +5 -0
  381. aria_code/privacy/feedback.py +123 -0
  382. aria_code/project_review.py +278 -0
  383. aria_code/project_review_api.py +235 -0
  384. aria_code/project_review_server.py +18 -0
  385. aria_code/project_tools.py +4 -0
  386. aria_code/providers/__init__.py +30 -0
  387. aria_code/providers/llm/__init__.py +19 -0
  388. aria_code/providers/llm/anthropic.py +184 -0
  389. aria_code/providers/llm/autoconfig.py +213 -0
  390. aria_code/providers/llm/base.py +139 -0
  391. aria_code/providers/llm/custom.py +158 -0
  392. aria_code/providers/llm/ollama.py +129 -0
  393. aria_code/providers/llm/openai_compat.py +313 -0
  394. aria_code/providers/llm/registry.py +444 -0
  395. aria_code/providers/local_image_provider.py +202 -0
  396. aria_code/providers/local_llm_provider.py +589 -0
  397. aria_code/realty_data_tools.py +4 -0
  398. aria_code/report_exporters.py +150 -0
  399. aria_code/report_generator.py +1764 -0
  400. aria_code/runtime/__init__.py +169 -0
  401. aria_code/runtime/acceptance.py +481 -0
  402. aria_code/runtime/agent_loop.py +1520 -0
  403. aria_code/runtime/approval.py +57 -0
  404. aria_code/runtime/budget.py +232 -0
  405. aria_code/runtime/checkpoints.py +432 -0
  406. aria_code/runtime/crash_report.py +174 -0
  407. aria_code/runtime/events.py +113 -0
  408. aria_code/runtime/gateway.py +150 -0
  409. aria_code/runtime/lsp.py +484 -0
  410. aria_code/runtime/orchestrator.py +55 -0
  411. aria_code/runtime/repo_map.py +700 -0
  412. aria_code/runtime/run_state.py +127 -0
  413. aria_code/runtime/run_store.py +450 -0
  414. aria_code/runtime/self_healing.py +422 -0
  415. aria_code/runtime/subagent.py +547 -0
  416. aria_code/runtime/task_ledger.py +86 -0
  417. aria_code/runtime/task_orchestrator.py +90 -0
  418. aria_code/runtime/tool_executor.py +217 -0
  419. aria_code/runtime/tool_policy.py +107 -0
  420. aria_code/runtime/worktrees.py +215 -0
  421. aria_code/runway_video_client.py +4 -0
  422. aria_code/safety/__init__.py +23 -0
  423. aria_code/safety/permissions.py +306 -0
  424. aria_code/safety/service.py +102 -0
  425. aria_code/setup_wizard.py +673 -0
  426. aria_code/spreadsheet_tools.py +4 -0
  427. aria_code/strategy_vault.py +4 -0
  428. aria_code/tools/__init__.py +0 -0
  429. aria_code/tools/artifact_tools.py +252 -0
  430. aria_code/tools/broker_tools.py +92 -0
  431. aria_code/tools/build_quant_engine.py +97 -0
  432. aria_code/tools/code_audit_tools.py +192 -0
  433. aria_code/tools/computer_use_tools.py +504 -0
  434. aria_code/tools/data_analysis_tools.py +809 -0
  435. aria_code/tools/enterprise_finance_tools.py +156 -0
  436. aria_code/tools/extended_tools.py +240 -0
  437. aria_code/tools/file_analysis_tools.py +885 -0
  438. aria_code/tools/image_gen_tools.py +114 -0
  439. aria_code/tools/local_finance_tools.py +3417 -0
  440. aria_code/tools/logistics_tools.py +135 -0
  441. aria_code/tools/macro_tools.py +369 -0
  442. aria_code/tools/notification_tools.py +249 -0
  443. aria_code/tools/project_tools.py +525 -0
  444. aria_code/tools/realty_data_tools.py +659 -0
  445. aria_code/tools/spreadsheet_tools.py +388 -0
  446. aria_code/tools/stripe_tools.py +115 -0
  447. aria_code/ui/__init__.py +105 -0
  448. aria_code/ui/banner.py +508 -0
  449. aria_code/ui/completer.py +501 -0
  450. aria_code/ui/console.py +281 -0
  451. aria_code/ui/image_render.py +243 -0
  452. aria_code/ui/input_box.py +488 -0
  453. aria_code/ui/picker.py +201 -0
  454. aria_code/ui/render/__init__.py +11 -0
  455. aria_code/ui/render/finance.py +1705 -0
  456. aria_code/ui/render/market.py +225 -0
  457. aria_code/ui/render/output.py +775 -0
  458. aria_code/ui/render/responsive.py +75 -0
  459. aria_code/ui/render/team.py +354 -0
  460. aria_code/ui/robot.py +235 -0
  461. aria_code/ui/startup_dashboard.py +109 -0
  462. aria_code/utils/vscode_uri.py +37 -0
  463. aria_code/video_analysis.py +147 -0
  464. aria_code/video_editor.py +271 -0
  465. aria_code/workspace/__init__.py +6 -0
  466. aria_code/workspace/files.py +193 -0
  467. aria_code/workspace/verify.py +113 -0
  468. aria_code/workspace_changes.py +199 -0
  469. aria_code/workspace_context.py +233 -0
  470. aria_code/workspace_service.py +196 -0
  471. aria_code/workspace_tools.py +150 -0
  472. aria_code-0.52.0.dist-info/METADATA +237 -0
  473. aria_code-0.52.0.dist-info/RECORD +478 -0
  474. aria_code-0.52.0.dist-info/WHEEL +5 -0
  475. aria_code-0.52.0.dist-info/entry_points.txt +3 -0
  476. aria_code-0.52.0.dist-info/licenses/LICENSE +201 -0
  477. aria_code-0.52.0.dist-info/licenses/NOTICE +49 -0
  478. aria_code-0.52.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,73 @@
1
+ """Reading API keys from the environment and providers.json.
2
+
3
+ Both functions lived in aria_cli.py, so five mixins reached into it for them.
4
+ Neither touches CLI state — they read two constant maps and one file.
5
+
6
+ The file path is resolved on each call rather than snapshotted at import, and
7
+ that is deliberate. resolve_config_dir() reads ARIA_CONFIG_DIR when it runs, so
8
+ a module-level snapshot taken while this module is imported would be taken
9
+ before initialize_cli_environment() — these mixins are imported at aria_cli.py
10
+ line 31, that call happens at 106. config_paths.py records what that class of
11
+ mistake cost before: config landing in ~/.aria-code while credentials went to
12
+ ~/.arthera. Resolving at call time is always after the environment is set up.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import json
18
+ import os
19
+ from pathlib import Path
20
+ from typing import Dict
21
+
22
+ from aria_code.apps.cli.constants import _DATA_KEY_MAP, _PROVIDER_KEY_MAP
23
+
24
+ __all__ = ["get_provider_key", "load_data_keys", "providers_file"]
25
+
26
+
27
+ def providers_file() -> Path:
28
+ """Where providers.json lives, resolved now rather than at import."""
29
+ from aria_code.apps.cli.bootstrap import runtime_paths
30
+
31
+ return runtime_paths().providers_file
32
+
33
+
34
+ def get_provider_key(provider: str) -> str:
35
+ """Return the configured API key for a provider (env var takes priority)."""
36
+ env_var = (_PROVIDER_KEY_MAP.get(provider.lower())
37
+ or _DATA_KEY_MAP.get(provider.lower(), ""))
38
+ if env_var:
39
+ val = os.getenv(env_var, "")
40
+ if val:
41
+ return val
42
+ # Check providers.json under both "llm" and "data" sections
43
+ try:
44
+ if providers_file().exists():
45
+ raw = json.loads(providers_file().read_text(encoding="utf-8"))
46
+ for section in ("llm", "data"):
47
+ entry = raw.get(section, {}).get(provider.lower(), {})
48
+ if entry.get("api_key"):
49
+ return entry["api_key"]
50
+ except Exception:
51
+ pass
52
+ return ""
53
+
54
+
55
+ def load_data_keys() -> Dict[str, str]:
56
+ """Return a dict of {service: api_key} for all configured data services.
57
+ Merges environment variables (priority) and providers.json."""
58
+ result: Dict[str, str] = {}
59
+ # 1. Environment variables
60
+ for svc, env_var in _DATA_KEY_MAP.items():
61
+ val = os.getenv(env_var, "")
62
+ if val:
63
+ result[svc] = val
64
+ # 2. providers.json "data" section
65
+ try:
66
+ if providers_file().exists():
67
+ raw = json.loads(providers_file().read_text(encoding="utf-8"))
68
+ for svc, entry in raw.get("data", {}).items():
69
+ if svc not in result and entry.get("api_key"):
70
+ result[svc] = entry["api_key"]
71
+ except Exception:
72
+ pass
73
+ return result
@@ -0,0 +1 @@
1
+ """apps/cli/providers — LLM provider utilities."""
@@ -0,0 +1,521 @@
1
+ """LLM provider abstraction layer.
2
+
3
+ Defines the minimal Protocol that every provider must satisfy so the
4
+ agent loop can call any backend (Ollama, AriaSSE, DeepSeek, etc.)
5
+ without importing provider-specific code.
6
+
7
+ Usage
8
+ -----
9
+ Implement the protocol on any class or pass a coroutine that matches
10
+ ``stream()``'s signature as a bare ``provider_fn`` callable.
11
+ """
12
+ from __future__ import annotations
13
+
14
+ import asyncio
15
+ from dataclasses import dataclass, field
16
+ from typing import AsyncGenerator, Optional, Protocol, runtime_checkable
17
+
18
+
19
+ # ── Event types emitted by LLMProvider.stream() ──────────────────────────────
20
+
21
+ @dataclass(frozen=True)
22
+ class LLMToken:
23
+ """A single text token from the model."""
24
+ text: str
25
+
26
+
27
+ @dataclass(frozen=True)
28
+ class LLMThinking:
29
+ """One thinking/reasoning token (extended-thinking models)."""
30
+ content: str
31
+
32
+
33
+ @dataclass(frozen=True)
34
+ class LLMToolCall:
35
+ """Model requested a tool call."""
36
+ tool: str
37
+ params: dict
38
+
39
+
40
+ @dataclass(frozen=True)
41
+ class LLMToolResult:
42
+ """Provider reported a tool execution result summary."""
43
+ tool: str
44
+ summary: str
45
+
46
+
47
+ @dataclass(frozen=True)
48
+ class LLMStatus:
49
+ """Provider emitted a streaming status update."""
50
+ state: str
51
+ message: str
52
+
53
+
54
+ @dataclass(frozen=True)
55
+ class LLMDone:
56
+ """Stream finished. Carries the aggregated result."""
57
+ response: str
58
+ tool_calls_pending: list = field(default_factory=list)
59
+ usage: dict = field(default_factory=dict)
60
+ provider: str = "unknown"
61
+ success: bool = True
62
+ cancelled: bool = False
63
+ error: str = ""
64
+
65
+
66
+ # Union type for type-checkers
67
+ LLMEvent = LLMToken | LLMThinking | LLMToolCall | LLMToolResult | LLMStatus | LLMDone
68
+
69
+
70
+ def _resolve_ollama_stream():
71
+ """Prefer the aria_cli rebound stream_ollama when available."""
72
+ import sys
73
+
74
+ # Console entry points import ``aria_cli``; direct execution
75
+ # (``python aria_cli.py`` and the npm launcher) registers it as
76
+ # ``__main__``. Both own the rebound function whose globals include the
77
+ # CLI tool registry and cache helpers.
78
+ #
79
+ # ``aria_code.aria_cli`` is the same file reached through the package root
80
+ # rather than as a bare top-level module — the import the SDK and daemon
81
+ # use. Without it here they fell through to the raw extracted function,
82
+ # whose globals lack the borrowed CLI helpers, and the first cache-eligible
83
+ # turn died with ``NameError: name '_cache_key' is not defined``.
84
+ for module_name in ("aria_cli", "aria_code.aria_cli", "__main__"):
85
+ module = sys.modules.get(module_name)
86
+ rebound = getattr(module, "stream_ollama", None) if module else None
87
+ if callable(rebound):
88
+ return rebound
89
+ from aria_code.apps.cli.providers.llm.ollama_stream import stream_ollama
90
+
91
+ return stream_ollama
92
+
93
+
94
+ async def _stream_callback_provider(invoke, *, done_provider: str) -> AsyncGenerator[LLMEvent, None]:
95
+ """Convert a callback-based provider coroutine into a real async event stream."""
96
+
97
+ queue: asyncio.Queue[LLMEvent] = asyncio.Queue()
98
+
99
+ def _on_token(tok: str) -> None:
100
+ queue.put_nowait(LLMToken(text=tok))
101
+
102
+ def _on_thinking(content: str) -> None:
103
+ queue.put_nowait(LLMThinking(content=content))
104
+
105
+ def _on_tool_call(tool: str, params: dict) -> None:
106
+ queue.put_nowait(LLMToolCall(tool=tool, params=params))
107
+
108
+ def _on_tool_result(tool: str, summary: str) -> None:
109
+ queue.put_nowait(LLMToolResult(tool=tool, summary=summary))
110
+
111
+ def _on_status(state: str, message: str) -> None:
112
+ queue.put_nowait(LLMStatus(state=state, message=message))
113
+
114
+ task = asyncio.create_task(
115
+ invoke(_on_token, _on_thinking, _on_tool_call, _on_tool_result, _on_status)
116
+ )
117
+ while not task.done() or not queue.empty():
118
+ try:
119
+ yield await asyncio.wait_for(queue.get(), timeout=0.05)
120
+ except asyncio.TimeoutError:
121
+ continue
122
+
123
+ try:
124
+ result = await task
125
+ except Exception as exc:
126
+ yield LLMDone(response="", provider=done_provider, success=False, error=str(exc))
127
+ return
128
+
129
+ yield LLMDone(
130
+ response=result.get("response", ""),
131
+ tool_calls_pending=result.get("tool_calls_pending", []),
132
+ usage=result.get("usage", {}),
133
+ provider=result.get("provider", done_provider),
134
+ success=result.get("success", False),
135
+ cancelled=result.get("cancelled", False),
136
+ error=result.get("error", ""),
137
+ )
138
+
139
+
140
+ # ── Protocol ─────────────────────────────────────────────────────────────────
141
+
142
+ @runtime_checkable
143
+ class LLMProvider(Protocol):
144
+ """Minimal interface every LLM backend must implement.
145
+
146
+ ``stream()`` is an async generator that yields ``LLMEvent`` objects.
147
+ The final event is always ``LLMDone``; callers may break early on
148
+ ``LLMDone`` or consume the full stream.
149
+
150
+ Parameters
151
+ ----------
152
+ messages:
153
+ Full conversation history (list of {"role": …, "content": …} dicts).
154
+ tools:
155
+ OpenAI-format function schema list; empty list disables tool calls.
156
+ cancel_event:
157
+ asyncio.Event that, when set, signals the provider to stop.
158
+ """
159
+
160
+ async def stream(
161
+ self,
162
+ messages: list,
163
+ tools: list,
164
+ *,
165
+ cancel_event: Optional[asyncio.Event] = None,
166
+ ) -> AsyncGenerator[LLMEvent, None]:
167
+ ...
168
+
169
+
170
+ # ── Thin adapters (wrap existing callables as LLMProvider) ───────────────────
171
+
172
+ class OllamaProvider:
173
+ """Wraps ``stream_ollama`` as an ``LLMProvider``.
174
+
175
+ Import lazily to avoid circular dependencies — ``stream_ollama`` lives in
176
+ the same providers package and rebinds globals from aria_cli at startup.
177
+ """
178
+
179
+ def __init__(
180
+ self,
181
+ ollama_url: str,
182
+ model: str,
183
+ *,
184
+ system_override: Optional[str] = None,
185
+ show_market_prefetch_status: bool = True,
186
+ ) -> None:
187
+ self.ollama_url = ollama_url
188
+ self.model = model
189
+ self.system_override = system_override
190
+ self.show_market_prefetch_status = show_market_prefetch_status
191
+
192
+ async def stream(
193
+ self,
194
+ messages: list,
195
+ tools: list,
196
+ *,
197
+ cancel_event: Optional[asyncio.Event] = None,
198
+ ) -> AsyncGenerator[LLMEvent, None]:
199
+ stream_ollama = _resolve_ollama_stream()
200
+
201
+ # Extract last user message as the prompt; the rest is history
202
+ history = [m for m in messages if not (m.get("role") == "user" and m is messages[-1])]
203
+ prompt = messages[-1].get("content", "") if messages else ""
204
+
205
+ async def _invoke(on_token, on_thinking, on_tool_call, on_tool_result, _on_status):
206
+ return await stream_ollama(
207
+ self.ollama_url,
208
+ prompt,
209
+ history,
210
+ model=self.model,
211
+ on_token=on_token,
212
+ on_thinking=on_thinking,
213
+ on_tool_call=on_tool_call,
214
+ on_tool_result=on_tool_result,
215
+ cancel_event=cancel_event,
216
+ enable_tools=bool(tools),
217
+ tool_schemas=list(tools or []),
218
+ defer_tool_execution=True,
219
+ system_override=self.system_override,
220
+ show_market_prefetch_status=self.show_market_prefetch_status,
221
+ )
222
+
223
+ async for event in _stream_callback_provider(_invoke, done_provider="ollama"):
224
+ yield event
225
+
226
+
227
+ class AriaSSEProvider:
228
+ """Wraps ``stream_chat`` (Aria cloud SSE) as an ``LLMProvider``."""
229
+
230
+ def __init__(
231
+ self,
232
+ api_url: str,
233
+ model: str,
234
+ *,
235
+ auth_token: Optional[str] = None,
236
+ thinking_mode: str = "auto",
237
+ user_context: Optional[dict] = None,
238
+ system_override: Optional[str] = None,
239
+ project_context: str = "",
240
+ use_react_gateway: bool = False,
241
+ ) -> None:
242
+ self.api_url = api_url
243
+ self.model = model
244
+ self.auth_token = auth_token
245
+ self.thinking_mode = thinking_mode
246
+ self.user_context = user_context or {}
247
+ self.system_override = system_override
248
+ self.project_context = project_context
249
+ self.use_react_gateway = use_react_gateway
250
+
251
+ async def stream(
252
+ self,
253
+ messages: list,
254
+ tools: list,
255
+ *,
256
+ cancel_event: Optional[asyncio.Event] = None,
257
+ ) -> AsyncGenerator[LLMEvent, None]:
258
+ from aria_code.apps.cli.providers.llm.sse_stream import stream_chat
259
+
260
+ history = [m for m in messages if not (m.get("role") == "user" and m is messages[-1])]
261
+ prompt = messages[-1].get("content", "") if messages else ""
262
+
263
+ uctx = dict(self.user_context)
264
+ if self.system_override:
265
+ uctx["system_role_override"] = self.system_override
266
+
267
+ async def _invoke(on_token, on_thinking, on_tool_call, on_tool_result, on_status):
268
+ return await stream_chat(
269
+ self.api_url,
270
+ prompt,
271
+ history,
272
+ model=self.model,
273
+ thinking_mode=self.thinking_mode,
274
+ user_context=uctx or None,
275
+ auth_token=self.auth_token,
276
+ on_token=on_token,
277
+ on_thinking=on_thinking,
278
+ on_tool_call=on_tool_call,
279
+ on_tool_result=on_tool_result,
280
+ on_status=on_status,
281
+ cancel_event=cancel_event,
282
+ project_context=self.project_context,
283
+ use_react_gateway=self.use_react_gateway,
284
+ )
285
+
286
+ async for event in _stream_callback_provider(_invoke, done_provider="aria_sse"):
287
+ yield event
288
+
289
+
290
+ def _opt_in(config: dict, key: str, default: bool = True) -> bool:
291
+ """Read a tri-state boolean setting where "unset" means *default*.
292
+
293
+ ``config.get(key, default)`` is the wrong tool here and produced a real
294
+ failure: a config holding ``"use_vertexai": null`` returns None — the
295
+ stored value, not the default — so a Google model silently opted out of
296
+ Vertex and went down the OpenAI-compatible path instead. Settings that are
297
+ written as null by a config round-trip have to mean "not configured".
298
+ """
299
+ value = config.get(key)
300
+ return default if value is None else bool(value)
301
+
302
+
303
+ class ConfiguredProvider:
304
+ """Adapter for the provider selected by ``/model provider/model``.
305
+
306
+ Ollama keeps its dedicated CLI adapter because that path owns Aria's local
307
+ intent and tool orchestration. Other local runtimes use the shared
308
+ ``LocalLLMProvider`` OpenAI-compatible transport, while cloud APIs use the
309
+ provider registry (including Anthropic's native protocol).
310
+ """
311
+
312
+ LOCAL_OPENAI_BACKENDS = {"lmstudio", "vllm", "llamacpp", "jan", "custom"}
313
+ GENERIC_OPENAI_BACKENDS = {
314
+ "google", "gemini", "xai", "grok", "mistral", "cohere",
315
+ "perplexity", "baidu", "ernie", "qianfan", "bytedance",
316
+ "doubao", "ark", "minimax", "stepfun", "01ai", "yi",
317
+ }
318
+ GENERIC_ENV_KEYS = {
319
+ "google": "GOOGLE_API_KEY", "gemini": "GOOGLE_API_KEY",
320
+ "xai": "XAI_API_KEY", "grok": "XAI_API_KEY",
321
+ "mistral": "MISTRAL_API_KEY", "cohere": "COHERE_API_KEY",
322
+ "perplexity": "PERPLEXITY_API_KEY", "baidu": "QIANFAN_ACCESS_KEY",
323
+ "ernie": "QIANFAN_ACCESS_KEY", "qianfan": "QIANFAN_ACCESS_KEY",
324
+ "bytedance": "ARK_API_KEY", "doubao": "ARK_API_KEY",
325
+ "ark": "ARK_API_KEY", "minimax": "MINIMAX_API_KEY",
326
+ "stepfun": "STEPFUN_API_KEY", "01ai": "ONEAI_API_KEY",
327
+ "yi": "ONEAI_API_KEY",
328
+ }
329
+ GENERIC_BASE_URLS = {
330
+ "google": "https://generativelanguage.googleapis.com/v1beta/openai",
331
+ "gemini": "https://generativelanguage.googleapis.com/v1beta/openai",
332
+ "xai": "https://api.x.ai/v1", "grok": "https://api.x.ai/v1",
333
+ "mistral": "https://api.mistral.ai/v1",
334
+ "cohere": "https://api.cohere.ai/compatibility/v1",
335
+ "perplexity": "https://api.perplexity.ai",
336
+ "baidu": "https://qianfan.baidubce.com/v2",
337
+ "ernie": "https://qianfan.baidubce.com/v2",
338
+ "qianfan": "https://qianfan.baidubce.com/v2",
339
+ "bytedance": "https://ark.cn-beijing.volces.com/api/v3",
340
+ "doubao": "https://ark.cn-beijing.volces.com/api/v3",
341
+ "ark": "https://ark.cn-beijing.volces.com/api/v3",
342
+ "minimax": "https://api.minimax.chat/v1",
343
+ "stepfun": "https://api.stepfun.com/v1",
344
+ "01ai": "https://api.lingyiwanwu.com/v1",
345
+ "yi": "https://api.lingyiwanwu.com/v1",
346
+ }
347
+
348
+ def __init__(
349
+ self,
350
+ config: dict,
351
+ model: str,
352
+ *,
353
+ system_override: Optional[str] = None,
354
+ ) -> None:
355
+ self.config = dict(config or {})
356
+ from aria_code.apps.cli.providers.chat_routing import (
357
+ model_provider,
358
+ normalize_provider_name,
359
+ )
360
+
361
+ # A provider-qualified model id names its own backend and wins over
362
+ # local_provider — the default config pairs model="gemini-pro" with
363
+ # local_provider="ollama", so deriving the backend from local_provider
364
+ # alone sent every Gemini request to Ollama.
365
+ declared = model_provider(model)
366
+ self.backend = declared or normalize_provider_name(
367
+ self.config.get("local_provider") or "ollama"
368
+ )
369
+ # Downstream APIs expect the bare model name; "google/gemini-2.5-pro"
370
+ # would 404 against Google's endpoint and would be re-prefixed into
371
+ # "google/google/gemini-2.5-pro" by the registry path below.
372
+ self.model = model.split("/", 1)[1] if declared else model
373
+ self.config["local_provider"] = self.backend
374
+ self.system_override = system_override
375
+
376
+ def _messages(self, messages: list) -> list:
377
+ prepared = [dict(message) for message in messages]
378
+ if not self.system_override:
379
+ return prepared
380
+ if prepared and prepared[0].get("role") == "system":
381
+ prepared[0]["content"] = (
382
+ self.system_override + "\n\n" + str(prepared[0].get("content", ""))
383
+ )
384
+ else:
385
+ prepared.insert(0, {"role": "system", "content": self.system_override})
386
+ return prepared
387
+
388
+ async def stream(
389
+ self,
390
+ messages: list,
391
+ tools: list,
392
+ *,
393
+ cancel_event: Optional[asyncio.Event] = None,
394
+ ) -> AsyncGenerator[LLMEvent, None]:
395
+ prepared = self._messages(messages)
396
+
397
+ if self.backend in ("vertexai", "vertex-ai", "google-genai") or (
398
+ self.backend in ("google", "gemini") and _opt_in(self.config, "use_vertexai")
399
+ ):
400
+ from aria_code.apps.cli.providers.vertexai_stream import VertexAIProvider
401
+ provider = VertexAIProvider(
402
+ model=self.model,
403
+ config=self.config,
404
+ system_override=self.system_override,
405
+ )
406
+ async for evt in provider.stream(prepared, tools=tools, cancel_event=cancel_event):
407
+ yield evt
408
+ return
409
+
410
+ if self.backend in self.LOCAL_OPENAI_BACKENDS | self.GENERIC_OPENAI_BACKENDS:
411
+ from aria_code.local_llm_provider import LocalLLMProvider
412
+
413
+ cfg = dict(self.config)
414
+ cfg["model"] = self.model
415
+ if self.backend in self.GENERIC_OPENAI_BACKENDS:
416
+ import os
417
+ from aria_code.providers.llm.registry import _load_provider_cfg_from_file
418
+
419
+ file_cfg = _load_provider_cfg_from_file(self.backend)
420
+ api_key = (
421
+ os.getenv(self.GENERIC_ENV_KEYS[self.backend], "")
422
+ or str(file_cfg.get("api_key") or "")
423
+ )
424
+ base_url = file_cfg.get("base_url") or self.GENERIC_BASE_URLS[self.backend]
425
+ model_name = self.model
426
+
427
+ if not api_key and self.backend in ("google", "gemini"):
428
+ import subprocess
429
+ try:
430
+ api_key = subprocess.check_output(["gcloud", "auth", "print-access-token"], text=True).strip()
431
+ project = subprocess.check_output(["gcloud", "config", "get-value", "project"], text=True).strip()
432
+ region = "us-central1"
433
+ base_url = f"https://{region}-aiplatform.googleapis.com/v1beta1/projects/{project}/locations/{region}/endpoints/openapi"
434
+
435
+ if not model_name.startswith("google/"):
436
+ model_name = f"google/{model_name}"
437
+ except Exception:
438
+ pass
439
+
440
+ if not api_key:
441
+ yield LLMDone(
442
+ response="", provider=self.backend, success=False,
443
+ error=f"missing_api_key:{self.backend}",
444
+ )
445
+ return
446
+ cfg.update({
447
+ "local_provider": "custom",
448
+ "custom_endpoint": base_url,
449
+ "custom_model": model_name,
450
+ "local_api_key": api_key,
451
+ })
452
+ provider = LocalLLMProvider.from_config(cfg)
453
+ source = self.backend
454
+ event_stream = provider.stream(prepared, tools=tools, cancel_event=cancel_event)
455
+ else:
456
+ from aria_code.providers.llm.base import Message
457
+ from aria_code.providers.llm.registry import get_provider
458
+
459
+ try:
460
+ provider = get_provider(f"{self.backend}/{self.model}")
461
+ except Exception as exc:
462
+ yield LLMDone(
463
+ response="", provider=self.backend, success=False,
464
+ error=f"{self.backend}: {exc}",
465
+ )
466
+ return
467
+ source = self.backend
468
+ registry_messages = [
469
+ Message(
470
+ role=str(message.get("role", "user")),
471
+ content=str(message.get("content", "")),
472
+ name=message.get("name"),
473
+ tool_call_id=message.get("tool_call_id"),
474
+ )
475
+ for message in prepared
476
+ ]
477
+ # providers.llm accepts bare function schemas, while the CLI owns
478
+ # OpenAI envelopes. Normalize once at this adapter boundary.
479
+ registry_tools = [
480
+ item.get("function", item)
481
+ if isinstance(item, dict) and item.get("type") == "function"
482
+ else item
483
+ for item in tools
484
+ ]
485
+ event_stream = provider.stream(
486
+ registry_messages, tools=registry_tools, cancel_event=cancel_event
487
+ )
488
+
489
+ async for event in event_stream:
490
+ kind = event.get("type")
491
+ if kind == "token":
492
+ yield LLMToken(text=str(event.get("text", "")))
493
+ elif kind == "thinking":
494
+ yield LLMThinking(content=str(event.get("text", "")))
495
+ elif kind == "tool_call":
496
+ yield LLMToolCall(
497
+ tool=str(event.get("name", "")),
498
+ params=dict(event.get("arguments") or {}),
499
+ )
500
+ elif kind == "error":
501
+ yield LLMDone(
502
+ response="",
503
+ provider=source,
504
+ success=False,
505
+ error=str(event.get("message") or "provider_error"),
506
+ )
507
+ return
508
+ elif kind == "done":
509
+ stop_reason = str(event.get("stop_reason") or "")
510
+ yield LLMDone(
511
+ response=str(event.get("text") or ""),
512
+ usage=dict(event.get("usage") or {}),
513
+ provider=source,
514
+ success=True,
515
+ cancelled=stop_reason == "cancelled",
516
+ )
517
+ return
518
+
519
+ yield LLMDone(
520
+ response="", provider=source, success=False, error="empty_response"
521
+ )