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,775 @@
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 contextlib import suppress
16
+ from dataclasses import dataclass, field
17
+ from typing import AsyncGenerator, Optional, Protocol, runtime_checkable
18
+
19
+
20
+ # ── Event types emitted by LLMProvider.stream() ──────────────────────────────
21
+
22
+ @dataclass(frozen=True)
23
+ class LLMToken:
24
+ """A single text token from the model."""
25
+ text: str
26
+
27
+
28
+ @dataclass(frozen=True)
29
+ class LLMThinking:
30
+ """One thinking/reasoning token (extended-thinking models)."""
31
+ content: str
32
+
33
+
34
+ @dataclass(frozen=True)
35
+ class LLMToolCall:
36
+ """Model requested a tool call.
37
+
38
+ ``call_id`` and ``thought_signature`` are opaque values some backends
39
+ (Gemini) hand out with a call and require back, unchanged, when the call
40
+ is replayed in history. Providers that have no such thing leave them None.
41
+ The signature is base64 text, not bytes, because history is JSON.
42
+ """
43
+ tool: str
44
+ params: dict
45
+ call_id: Optional[str] = None
46
+ thought_signature: Optional[str] = None
47
+
48
+
49
+ @dataclass(frozen=True)
50
+ class LLMToolResult:
51
+ """Provider reported a tool execution result summary."""
52
+ tool: str
53
+ summary: str
54
+
55
+
56
+ @dataclass(frozen=True)
57
+ class LLMStatus:
58
+ """Provider emitted a streaming status update."""
59
+ state: str
60
+ message: str
61
+
62
+
63
+ @dataclass(frozen=True)
64
+ class LLMDone:
65
+ """Stream finished. Carries the aggregated result."""
66
+ response: str
67
+ tool_calls_pending: list = field(default_factory=list)
68
+ usage: dict = field(default_factory=dict)
69
+ provider: str = "unknown"
70
+ success: bool = True
71
+ cancelled: bool = False
72
+ error: str = ""
73
+
74
+
75
+ # Union type for type-checkers
76
+ LLMEvent = LLMToken | LLMThinking | LLMToolCall | LLMToolResult | LLMStatus | LLMDone
77
+
78
+
79
+ def event_kind(event: object) -> str:
80
+ """The event's type by name — use this, not isinstance, to dispatch events.
81
+
82
+ These modules are importable under two roots: ``aria_code.apps.cli…`` and
83
+ the bare ``apps.cli…`` that tests patch. Each root defines its own copy of
84
+ every event class, and runtime_bridge builds providers from the bare root
85
+ while the consumers checked against the packaged one. isinstance then
86
+ failed for every event: a provider streamed "ready", the consumer saw
87
+ nothing, and the turn ended as empty_response. That hit every chat turn
88
+ through ConfiguredProvider's own events — OpenAI-compatible endpoints,
89
+ LM Studio, the registry providers, and Gemini without ADC.
90
+ """
91
+ return type(event).__name__
92
+
93
+
94
+ def _resolve_ollama_stream():
95
+ """Prefer the aria_cli rebound stream_ollama when available."""
96
+ import sys
97
+
98
+ # Console entry points import ``aria_cli``; direct execution
99
+ # (``python aria_cli.py`` and the npm launcher) registers it as
100
+ # ``__main__``. Both own the rebound function whose globals include the
101
+ # CLI tool registry and cache helpers.
102
+ #
103
+ # ``aria_code.aria_cli`` is the same file reached through the package root
104
+ # rather than as a bare top-level module — the import the SDK and daemon
105
+ # use. Without it here they fell through to the raw extracted function,
106
+ # whose globals lack the borrowed CLI helpers, and the first cache-eligible
107
+ # turn died with ``NameError: name '_cache_key' is not defined``.
108
+ for module_name in ("aria_cli", "aria_code.aria_cli", "__main__"):
109
+ module = sys.modules.get(module_name)
110
+ rebound = getattr(module, "stream_ollama", None) if module else None
111
+ if callable(rebound):
112
+ return rebound
113
+ from aria_code.apps.cli.providers.llm.ollama_stream import stream_ollama
114
+
115
+ return stream_ollama
116
+
117
+
118
+ async def _stream_callback_provider(invoke, *, done_provider: str) -> AsyncGenerator[LLMEvent, None]:
119
+ """Convert a callback-based provider coroutine into a real async event stream."""
120
+
121
+ queue: asyncio.Queue[LLMEvent] = asyncio.Queue()
122
+
123
+ def _on_token(tok: str) -> None:
124
+ queue.put_nowait(LLMToken(text=tok))
125
+
126
+ def _on_thinking(content: str) -> None:
127
+ queue.put_nowait(LLMThinking(content=content))
128
+
129
+ def _on_tool_call(tool: str, params: dict) -> None:
130
+ queue.put_nowait(LLMToolCall(tool=tool, params=params))
131
+
132
+ def _on_tool_result(tool: str, summary: str) -> None:
133
+ queue.put_nowait(LLMToolResult(tool=tool, summary=summary))
134
+
135
+ def _on_status(state: str, message: str) -> None:
136
+ queue.put_nowait(LLMStatus(state=state, message=message))
137
+
138
+ task = asyncio.create_task(
139
+ invoke(_on_token, _on_thinking, _on_tool_call, _on_tool_result, _on_status)
140
+ )
141
+ try:
142
+ while not task.done() or not queue.empty():
143
+ try:
144
+ yield await asyncio.wait_for(queue.get(), timeout=0.05)
145
+ except asyncio.TimeoutError:
146
+ continue
147
+ try:
148
+ result = await task
149
+ except Exception as exc:
150
+ yield LLMDone(response="", provider=done_provider, success=False, error=str(exc))
151
+ return
152
+
153
+ yield LLMDone(
154
+ response=result.get("response", ""),
155
+ tool_calls_pending=result.get("tool_calls_pending", []),
156
+ usage=result.get("usage", {}),
157
+ provider=result.get("provider", done_provider),
158
+ success=result.get("success", False),
159
+ cancelled=result.get("cancelled", False),
160
+ error=result.get("error", ""),
161
+ )
162
+ finally:
163
+ # A deadline or an early-closing consumer must also stop the request
164
+ # behind this callback adapter, rather than leave it running invisibly.
165
+ if not task.done():
166
+ task.cancel()
167
+ with suppress(asyncio.CancelledError, Exception):
168
+ await task
169
+
170
+
171
+ # ── Protocol ─────────────────────────────────────────────────────────────────
172
+
173
+ @runtime_checkable
174
+ class LLMProvider(Protocol):
175
+ """Minimal interface every LLM backend must implement.
176
+
177
+ ``stream()`` is an async generator that yields ``LLMEvent`` objects.
178
+ The final event is always ``LLMDone``; callers may break early on
179
+ ``LLMDone`` or consume the full stream.
180
+
181
+ Parameters
182
+ ----------
183
+ messages:
184
+ Full conversation history (list of {"role": …, "content": …} dicts).
185
+ tools:
186
+ OpenAI-format function schema list; empty list disables tool calls.
187
+ cancel_event:
188
+ asyncio.Event that, when set, signals the provider to stop.
189
+ """
190
+
191
+ async def stream(
192
+ self,
193
+ messages: list,
194
+ tools: list,
195
+ *,
196
+ cancel_event: Optional[asyncio.Event] = None,
197
+ ) -> AsyncGenerator[LLMEvent, None]:
198
+ ...
199
+
200
+
201
+ # ── Thin adapters (wrap existing callables as LLMProvider) ───────────────────
202
+
203
+ class OllamaProvider:
204
+ """Wraps ``stream_ollama`` as an ``LLMProvider``.
205
+
206
+ Import lazily to avoid circular dependencies — ``stream_ollama`` lives in
207
+ the same providers package and rebinds globals from aria_cli at startup.
208
+ """
209
+
210
+ def __init__(
211
+ self,
212
+ ollama_url: str,
213
+ model: str,
214
+ *,
215
+ system_override: Optional[str] = None,
216
+ show_market_prefetch_status: bool = True,
217
+ include_ambient_context: bool = True,
218
+ ) -> None:
219
+ self.ollama_url = ollama_url
220
+ self.model = model
221
+ self.system_override = system_override
222
+ self.show_market_prefetch_status = show_market_prefetch_status
223
+ self.include_ambient_context = include_ambient_context
224
+
225
+ async def stream(
226
+ self,
227
+ messages: list,
228
+ tools: list,
229
+ *,
230
+ cancel_event: Optional[asyncio.Event] = None,
231
+ ) -> AsyncGenerator[LLMEvent, None]:
232
+ stream_ollama = _resolve_ollama_stream()
233
+
234
+ # Extract last user message as the prompt; the rest is history
235
+ history = [m for m in messages if not (m.get("role") == "user" and m is messages[-1])]
236
+ prompt = messages[-1].get("content", "") if messages else ""
237
+
238
+ async def _invoke(on_token, on_thinking, on_tool_call, on_tool_result, _on_status):
239
+ return await stream_ollama(
240
+ self.ollama_url,
241
+ prompt,
242
+ history,
243
+ model=self.model,
244
+ on_token=on_token,
245
+ on_thinking=on_thinking,
246
+ on_tool_call=on_tool_call,
247
+ on_tool_result=on_tool_result,
248
+ cancel_event=cancel_event,
249
+ enable_tools=bool(tools),
250
+ tool_schemas=list(tools or []),
251
+ defer_tool_execution=True,
252
+ system_override=self.system_override,
253
+ show_market_prefetch_status=self.show_market_prefetch_status,
254
+ **({"include_ambient_context": False} if not self.include_ambient_context else {}),
255
+ )
256
+
257
+ async for event in _stream_callback_provider(_invoke, done_provider="ollama"):
258
+ yield event
259
+
260
+
261
+ class AriaSSEProvider:
262
+ """Wraps ``stream_chat`` (Aria cloud SSE) as an ``LLMProvider``."""
263
+
264
+ def __init__(
265
+ self,
266
+ api_url: str,
267
+ model: str,
268
+ *,
269
+ auth_token: Optional[str] = None,
270
+ thinking_mode: str = "auto",
271
+ user_context: Optional[dict] = None,
272
+ system_override: Optional[str] = None,
273
+ project_context: str = "",
274
+ use_react_gateway: bool = False,
275
+ local_tools: bool = False,
276
+ ) -> None:
277
+ self.api_url = api_url
278
+ self.model = model
279
+ self.auth_token = auth_token
280
+ self.thinking_mode = thinking_mode
281
+ self.user_context = user_context or {}
282
+ self.system_override = system_override
283
+ self.project_context = project_context
284
+ self.use_react_gateway = use_react_gateway
285
+ self.local_tools = local_tools
286
+
287
+ async def stream(
288
+ self,
289
+ messages: list,
290
+ tools: list,
291
+ *,
292
+ cancel_event: Optional[asyncio.Event] = None,
293
+ ) -> AsyncGenerator[LLMEvent, None]:
294
+ from aria_code.apps.cli.providers.llm.sse_stream import stream_chat
295
+
296
+ history = [m for m in messages if not (m.get("role") == "user" and m is messages[-1])]
297
+ prompt = messages[-1].get("content", "") if messages else ""
298
+
299
+ uctx = dict(self.user_context)
300
+ if self.system_override:
301
+ uctx["system_role_override"] = self.system_override
302
+
303
+ async def _invoke(on_token, on_thinking, on_tool_call, on_tool_result, on_status):
304
+ return await stream_chat(
305
+ self.api_url,
306
+ prompt,
307
+ history,
308
+ model=self.model,
309
+ thinking_mode=self.thinking_mode,
310
+ user_context=uctx or None,
311
+ auth_token=self.auth_token,
312
+ on_token=on_token,
313
+ on_thinking=on_thinking,
314
+ on_tool_call=on_tool_call,
315
+ on_tool_result=on_tool_result,
316
+ on_status=on_status,
317
+ cancel_event=cancel_event,
318
+ project_context=self.project_context,
319
+ use_react_gateway=self.use_react_gateway,
320
+ tool_schemas=list(tools or []) if self.local_tools else None,
321
+ local_tool_execution=self.local_tools,
322
+ )
323
+
324
+ async for event in _stream_callback_provider(_invoke, done_provider="aria_sse"):
325
+ yield event
326
+
327
+
328
+ def _opt_in(config: dict, key: str, default: bool = True) -> bool:
329
+ """Read a tri-state boolean setting where "unset" means *default*.
330
+
331
+ ``config.get(key, default)`` is the wrong tool here and produced a real
332
+ failure: a config holding ``"use_vertexai": null`` returns None — the
333
+ stored value, not the default — so a Google model silently opted out of
334
+ Vertex and went down the OpenAI-compatible path instead. Settings that are
335
+ written as null by a config round-trip have to mean "not configured".
336
+ """
337
+ value = config.get(key)
338
+ return default if value is None else bool(value)
339
+
340
+
341
+ def _gcloud(*args: str, timeout: float = 20) -> str:
342
+ import subprocess
343
+
344
+ result = subprocess.run(["gcloud", *args], capture_output=True, text=True, timeout=timeout,
345
+ stdin=subprocess.DEVNULL)
346
+ return result.stdout.strip() if result.returncode == 0 else ""
347
+
348
+
349
+ def _adc_available() -> bool:
350
+ """Application-default credentials exist (file, env, or running on Google Cloud)."""
351
+ import os
352
+
353
+ if os.getenv("GOOGLE_APPLICATION_CREDENTIALS") or os.getenv("K_SERVICE") or os.getenv("GCE_METADATA_HOST"):
354
+ return True
355
+ if os.name == "nt":
356
+ folder = os.getenv("CLOUDSDK_CONFIG") or os.path.join(os.getenv("APPDATA", ""), "gcloud")
357
+ else:
358
+ folder = os.getenv("CLOUDSDK_CONFIG") or os.path.join(os.path.expanduser("~"), ".config", "gcloud")
359
+ return os.path.isfile(os.path.join(folder, "application_default_credentials.json"))
360
+
361
+
362
+ def google_cloud_available() -> bool:
363
+ """Credentials Vertex AI can use: application-default credentials or a gcloud CLI."""
364
+ import shutil
365
+
366
+ return _adc_available() or bool(shutil.which("gcloud"))
367
+
368
+
369
+ def _google_api_key(config: dict) -> str:
370
+ import os
371
+
372
+ from aria_code.providers.llm.registry import _load_provider_cfg_from_file
373
+
374
+ for value in (config.get("api_key"), config.get("gemini_key"), os.getenv("GEMINI_API_KEY"),
375
+ os.getenv("GOOGLE_API_KEY"), _load_provider_cfg_from_file("google").get("api_key")):
376
+ if str(value or "").strip():
377
+ return str(value).strip()
378
+ return ""
379
+
380
+
381
+ def _gcloud_login_only(config: dict) -> bool:
382
+ """No ADC and no Gemini key, but a gcloud CLI to borrow a token from."""
383
+ import shutil
384
+
385
+ return not _adc_available() and not _google_api_key(config) and bool(shutil.which("gcloud"))
386
+
387
+
388
+ def _gcloud_folder() -> str:
389
+ import os
390
+
391
+ if os.name == "nt":
392
+ return os.getenv("CLOUDSDK_CONFIG") or os.path.join(os.getenv("APPDATA", ""), "gcloud")
393
+ return os.getenv("CLOUDSDK_CONFIG") or os.path.join(os.path.expanduser("~"), ".config", "gcloud")
394
+
395
+
396
+ def _gcloud_default_project(folder: str) -> str:
397
+ """The active gcloud configuration's core/project, read from its file."""
398
+ import configparser
399
+ import os
400
+
401
+ try:
402
+ with open(os.path.join(folder, "active_config"), encoding="utf-8") as handle:
403
+ active = handle.read().strip() or "default"
404
+ except OSError:
405
+ active = "default"
406
+ parser = configparser.ConfigParser()
407
+ try:
408
+ parser.read(os.path.join(folder, "configurations", f"config_{active}"), encoding="utf-8")
409
+ return parser.get("core", "project", fallback="").strip()
410
+ except configparser.Error:
411
+ return ""
412
+
413
+
414
+ def google_readiness(config: dict) -> str:
415
+ """"" when a Gemini request can be attempted, else what is missing.
416
+
417
+ The banner said "Cloud model configured" for the default model on a
418
+ machine with no Google credentials at all, and the first question then
419
+ failed. This reads only the environment and gcloud's files — no
420
+ subprocess — so it is cheap enough for startup.
421
+ """
422
+ import os
423
+ import shutil
424
+
425
+ if _google_api_key(config) or _adc_available():
426
+ return ""
427
+ if not shutil.which("gcloud"):
428
+ return "no Google credentials"
429
+ # Same order as vertex_openai_endpoint, so the banner names the problem
430
+ # the first request will report.
431
+ folder = _gcloud_folder()
432
+ project = (os.getenv("GOOGLE_CLOUD_PROJECT") or str(config.get("gcp_project") or "")
433
+ or _gcloud_default_project(folder))
434
+ if not project or project == "(unset)":
435
+ return "no Google Cloud project"
436
+ if not any(os.path.isfile(os.path.join(folder, name)) for name in ("credentials.db", "access_tokens.db")):
437
+ return "gcloud not signed in"
438
+ return ""
439
+
440
+
441
+ def is_vertex_open_model(model: str) -> bool:
442
+ """A model Vertex serves through its OpenAI-compatible endpoint, not generateContent.
443
+
444
+ Gemma ("gemma-4-26b-a4b-it-maas", "gemma-3-27b-it") and other Model Garden
445
+ managed models ("…-maas") are open models: the Gemini API does not serve
446
+ them, and the native SDK path 404'd.
447
+ """
448
+ name = str(model or "").lower().split("/")[-1]
449
+ return name.startswith("gemma") or name.endswith("-maas")
450
+
451
+
452
+ def _adc_access_token() -> str:
453
+ """An access token from application-default credentials, or "" if there are none."""
454
+ try:
455
+ import google.auth
456
+ import google.auth.transport.requests
457
+
458
+ credentials, _ = google.auth.default(scopes=["https://www.googleapis.com/auth/cloud-platform"])
459
+ credentials.refresh(google.auth.transport.requests.Request())
460
+ return str(credentials.token or "")
461
+ except Exception:
462
+ return ""
463
+
464
+
465
+ def vertex_openai_endpoint(config: dict) -> dict:
466
+ """Vertex AI's OpenAI-compatible endpoint and a token from the gcloud login.
467
+
468
+ Returns {} when gcloud is not installed (the caller reports the missing
469
+ API key), {"error": …} when gcloud is there but the request cannot be
470
+ made, otherwise {"token", "base_url", "project", "location"}.
471
+
472
+ This path used to read the project from `gcloud config get-value project`
473
+ alone; with no default project set that is empty, and every request went
474
+ to ".../projects//locations/...". The region was fixed to us-central1,
475
+ and both gcloud calls ran without a timeout on the event loop.
476
+ """
477
+ import os
478
+ import shutil
479
+
480
+ # Application-default credentials first (a CI runner signed in with
481
+ # Workload Identity Federation, a service account, `gcloud auth
482
+ # application-default login`), then the gcloud CLI's own login.
483
+ adc_token = _adc_access_token() if _adc_available() else ""
484
+ if not adc_token and not shutil.which("gcloud"):
485
+ return {}
486
+ try:
487
+ project = (os.getenv("GOOGLE_CLOUD_PROJECT") or str(config.get("gcp_project") or "")).strip()
488
+ if not project and shutil.which("gcloud"):
489
+ project = _gcloud("config", "get-value", "project", timeout=10).strip()
490
+ if not project or project == "(unset)":
491
+ return {"error": "vertex_needs_project: set GOOGLE_CLOUD_PROJECT, /config set gcp_project=<id>, "
492
+ "or `gcloud config set project <id>`"}
493
+ location = (os.getenv("GOOGLE_CLOUD_LOCATION") or str(config.get("gcp_location") or "") or "global").strip()
494
+ token = adc_token or _gcloud("auth", "print-access-token")
495
+ except Exception as exc: # timeout, permissions: report, never hang the chat
496
+ return {"error": f"vertex_gcloud_failed: {type(exc).__name__}"}
497
+ if not token:
498
+ return {"error": "vertex_not_logged_in: run `gcloud auth login`"}
499
+ host = "aiplatform.googleapis.com" if location == "global" else f"{location}-aiplatform.googleapis.com"
500
+ return {"token": token, "project": project, "location": location,
501
+ "base_url": f"https://{host}/v1/projects/{project}/locations/{location}/endpoints/openapi"}
502
+
503
+
504
+ class ConfiguredProvider:
505
+ """Adapter for the provider selected by ``/model provider/model``.
506
+
507
+ Ollama keeps its dedicated CLI adapter because that path owns Aria's local
508
+ intent and tool orchestration. Other local runtimes use the shared
509
+ ``LocalLLMProvider`` OpenAI-compatible transport, while cloud APIs use the
510
+ provider registry (including Anthropic's native protocol).
511
+ """
512
+
513
+ LOCAL_OPENAI_BACKENDS = {"lmstudio", "vllm", "llamacpp", "jan", "custom"}
514
+ GENERIC_OPENAI_BACKENDS = {
515
+ "google", "gemini", "xai", "grok", "mistral", "cohere",
516
+ "perplexity", "baidu", "ernie", "qianfan", "bytedance",
517
+ "doubao", "ark", "minimax", "stepfun", "01ai", "yi",
518
+ }
519
+ GENERIC_ENV_KEYS = {
520
+ "google": "GOOGLE_API_KEY", "gemini": "GOOGLE_API_KEY",
521
+ "xai": "XAI_API_KEY", "grok": "XAI_API_KEY",
522
+ "mistral": "MISTRAL_API_KEY", "cohere": "COHERE_API_KEY",
523
+ "perplexity": "PERPLEXITY_API_KEY", "baidu": "QIANFAN_ACCESS_KEY",
524
+ "ernie": "QIANFAN_ACCESS_KEY", "qianfan": "QIANFAN_ACCESS_KEY",
525
+ "bytedance": "ARK_API_KEY", "doubao": "ARK_API_KEY",
526
+ "ark": "ARK_API_KEY", "minimax": "MINIMAX_API_KEY",
527
+ "stepfun": "STEPFUN_API_KEY", "01ai": "ONEAI_API_KEY",
528
+ "yi": "ONEAI_API_KEY",
529
+ }
530
+ GENERIC_BASE_URLS = {
531
+ "google": "https://generativelanguage.googleapis.com/v1beta/openai",
532
+ "gemini": "https://generativelanguage.googleapis.com/v1beta/openai",
533
+ "xai": "https://api.x.ai/v1", "grok": "https://api.x.ai/v1",
534
+ "mistral": "https://api.mistral.ai/v1",
535
+ "cohere": "https://api.cohere.ai/compatibility/v1",
536
+ "perplexity": "https://api.perplexity.ai",
537
+ "baidu": "https://qianfan.baidubce.com/v2",
538
+ "ernie": "https://qianfan.baidubce.com/v2",
539
+ "qianfan": "https://qianfan.baidubce.com/v2",
540
+ "bytedance": "https://ark.cn-beijing.volces.com/api/v3",
541
+ "doubao": "https://ark.cn-beijing.volces.com/api/v3",
542
+ "ark": "https://ark.cn-beijing.volces.com/api/v3",
543
+ "minimax": "https://api.minimax.chat/v1",
544
+ "stepfun": "https://api.stepfun.com/v1",
545
+ "01ai": "https://api.lingyiwanwu.com/v1",
546
+ "yi": "https://api.lingyiwanwu.com/v1",
547
+ }
548
+
549
+ def __init__(
550
+ self,
551
+ config: dict,
552
+ model: str,
553
+ *,
554
+ system_override: Optional[str] = None,
555
+ ) -> None:
556
+ self.config = dict(config or {})
557
+ from aria_code.apps.cli.providers.chat_routing import (
558
+ model_provider,
559
+ normalize_provider_name,
560
+ )
561
+
562
+ # A provider-qualified model id names its own backend and wins over
563
+ # local_provider — the default config pairs model="gemini-pro" with
564
+ # local_provider="ollama", so deriving the backend from local_provider
565
+ # alone sent every Gemini request to Ollama.
566
+ declared = model_provider(model)
567
+ self.backend = declared or normalize_provider_name(
568
+ self.config.get("local_provider") or "ollama"
569
+ )
570
+ # Downstream APIs expect the bare model name; "google/gemini-2.5-pro"
571
+ # would 404 against Google's endpoint and would be re-prefixed into
572
+ # "google/google/gemini-2.5-pro" by the registry path below.
573
+ self.model = model.split("/", 1)[1] if declared else model
574
+ self.config["local_provider"] = self.backend
575
+ self.system_override = system_override
576
+
577
+ async def _stream_vertex_open_model(self, prepared: list, tools: list, cancel_event):
578
+ """Gemma and other managed open models, through Vertex's OpenAI-compatible endpoint."""
579
+ from aria_code.local_llm_provider import LocalLLMProvider
580
+
581
+ vertex = await asyncio.to_thread(vertex_openai_endpoint, self.config)
582
+ if not vertex or vertex.get("error"):
583
+ yield LLMDone(response="", provider="vertexai", success=False,
584
+ error=(vertex or {}).get("error") or
585
+ "vertex_needs_credentials: run `gcloud auth application-default login` "
586
+ "or set GOOGLE_APPLICATION_CREDENTIALS")
587
+ return
588
+ cfg = dict(self.config)
589
+ cfg.update({
590
+ "model": f"google/{self.model}",
591
+ "local_provider": "custom",
592
+ "custom_endpoint": vertex["base_url"],
593
+ "custom_model": f"google/{self.model}",
594
+ "local_api_key": vertex["token"],
595
+ })
596
+ provider = LocalLLMProvider.from_config(cfg)
597
+ async for event in provider.stream(prepared, tools=tools, cancel_event=cancel_event):
598
+ kind = event.get("type")
599
+ if kind == "token":
600
+ yield LLMToken(text=str(event.get("text", "")))
601
+ elif kind == "thinking":
602
+ yield LLMThinking(content=str(event.get("text", "")))
603
+ elif kind == "tool_call":
604
+ yield LLMToolCall(tool=str(event.get("name", "")), params=dict(event.get("arguments") or {}))
605
+ elif kind == "error":
606
+ yield LLMDone(response="", provider="vertexai", success=False,
607
+ error=str(event.get("message") or "provider_error"))
608
+ return
609
+ elif kind == "done":
610
+ yield LLMDone(response=str(event.get("text") or ""), usage=dict(event.get("usage") or {}),
611
+ provider="vertexai", success=True,
612
+ cancelled=str(event.get("stop_reason") or "") == "cancelled")
613
+ return
614
+ yield LLMDone(response="", provider="vertexai", success=False, error="empty_response")
615
+
616
+ def _messages(self, messages: list) -> list:
617
+ prepared = [dict(message) for message in messages]
618
+ if not self.system_override:
619
+ return prepared
620
+ if prepared and prepared[0].get("role") == "system":
621
+ prepared[0]["content"] = (
622
+ self.system_override + "\n\n" + str(prepared[0].get("content", ""))
623
+ )
624
+ else:
625
+ prepared.insert(0, {"role": "system", "content": self.system_override})
626
+ return prepared
627
+
628
+ async def stream(
629
+ self,
630
+ messages: list,
631
+ tools: list,
632
+ *,
633
+ cancel_event: Optional[asyncio.Event] = None,
634
+ ) -> AsyncGenerator[LLMEvent, None]:
635
+ prepared = self._messages(messages)
636
+
637
+ native_vertex = self.backend in ("vertexai", "vertex-ai", "google-genai") or (
638
+ self.backend in ("google", "gemini") and _opt_in(self.config, "use_vertexai")
639
+ )
640
+ if self.backend in ("google", "gemini", "vertexai", "vertex-ai", "google-genai") \
641
+ and is_vertex_open_model(self.model):
642
+ async for evt in self._stream_vertex_open_model(prepared, tools, cancel_event):
643
+ yield evt
644
+ return
645
+ if native_vertex and self.backend in ("google", "gemini") and _gcloud_login_only(self.config):
646
+ # The SDK route accepts only application-default credentials. With
647
+ # just a `gcloud auth login` it failed outright, so a logged-in
648
+ # user could not reach Gemini; the OpenAI-compatible Vertex
649
+ # endpoint below takes the gcloud login's token instead.
650
+ native_vertex = False
651
+ if native_vertex:
652
+ from aria_code.apps.cli.providers.vertexai_stream import VertexAIProvider
653
+ provider = VertexAIProvider(
654
+ model=self.model,
655
+ config=self.config,
656
+ system_override=self.system_override,
657
+ )
658
+ async for evt in provider.stream(prepared, tools=tools, cancel_event=cancel_event):
659
+ yield evt
660
+ return
661
+
662
+ if self.backend in self.LOCAL_OPENAI_BACKENDS | self.GENERIC_OPENAI_BACKENDS:
663
+ from aria_code.local_llm_provider import LocalLLMProvider
664
+
665
+ cfg = dict(self.config)
666
+ cfg["model"] = self.model
667
+ if self.backend in self.GENERIC_OPENAI_BACKENDS:
668
+ import os
669
+ from aria_code.providers.llm.registry import _load_provider_cfg_from_file
670
+
671
+ file_cfg = _load_provider_cfg_from_file(self.backend)
672
+ api_key = (
673
+ os.getenv(self.GENERIC_ENV_KEYS[self.backend], "")
674
+ or str(file_cfg.get("api_key") or "")
675
+ )
676
+ base_url = file_cfg.get("base_url") or self.GENERIC_BASE_URLS[self.backend]
677
+ model_name = self.model
678
+
679
+ if not api_key and self.backend in ("google", "gemini"):
680
+ # No Gemini API key: use Vertex AI with the gcloud login.
681
+ vertex = await asyncio.to_thread(vertex_openai_endpoint, self.config)
682
+ if vertex.get("error"):
683
+ yield LLMDone(response="", provider="vertexai", success=False, error=vertex["error"])
684
+ return
685
+ if vertex:
686
+ api_key, base_url = vertex["token"], vertex["base_url"]
687
+ if not model_name.startswith("google/"):
688
+ model_name = f"google/{model_name}"
689
+
690
+ if not api_key:
691
+ yield LLMDone(
692
+ response="", provider=self.backend, success=False,
693
+ error=f"missing_api_key:{self.backend}",
694
+ )
695
+ return
696
+ cfg.update({
697
+ "local_provider": "custom",
698
+ "custom_endpoint": base_url,
699
+ "custom_model": model_name,
700
+ "local_api_key": api_key,
701
+ })
702
+ provider = LocalLLMProvider.from_config(cfg)
703
+ source = self.backend
704
+ event_stream = provider.stream(prepared, tools=tools, cancel_event=cancel_event)
705
+ else:
706
+ from aria_code.providers.llm.base import Message
707
+ from aria_code.providers.llm.registry import get_provider
708
+
709
+ try:
710
+ provider = get_provider(f"{self.backend}/{self.model}")
711
+ except Exception as exc:
712
+ yield LLMDone(
713
+ response="", provider=self.backend, success=False,
714
+ error=f"{self.backend}: {exc}",
715
+ )
716
+ return
717
+ source = self.backend
718
+ # The registry providers send role and content only; native tool
719
+ # history would reach them as "tool" messages with no call id.
720
+ from aria_code.providers.tool_messages import flatten_tool_turns
721
+
722
+ registry_messages = [
723
+ Message(
724
+ role=str(message.get("role", "user")),
725
+ content=str(message.get("content", "")),
726
+ name=message.get("name"),
727
+ tool_call_id=message.get("tool_call_id"),
728
+ )
729
+ for message in flatten_tool_turns(prepared)
730
+ ]
731
+ # providers.llm accepts bare function schemas, while the CLI owns
732
+ # OpenAI envelopes. Normalize once at this adapter boundary.
733
+ registry_tools = [
734
+ item.get("function", item)
735
+ if isinstance(item, dict) and item.get("type") == "function"
736
+ else item
737
+ for item in tools
738
+ ]
739
+ event_stream = provider.stream(
740
+ registry_messages, tools=registry_tools, cancel_event=cancel_event
741
+ )
742
+
743
+ async for event in event_stream:
744
+ kind = event.get("type")
745
+ if kind == "token":
746
+ yield LLMToken(text=str(event.get("text", "")))
747
+ elif kind == "thinking":
748
+ yield LLMThinking(content=str(event.get("text", "")))
749
+ elif kind == "tool_call":
750
+ yield LLMToolCall(
751
+ tool=str(event.get("name", "")),
752
+ params=dict(event.get("arguments") or {}),
753
+ )
754
+ elif kind == "error":
755
+ yield LLMDone(
756
+ response="",
757
+ provider=source,
758
+ success=False,
759
+ error=str(event.get("message") or "provider_error"),
760
+ )
761
+ return
762
+ elif kind == "done":
763
+ stop_reason = str(event.get("stop_reason") or "")
764
+ yield LLMDone(
765
+ response=str(event.get("text") or ""),
766
+ usage=dict(event.get("usage") or {}),
767
+ provider=source,
768
+ success=True,
769
+ cancelled=stop_reason == "cancelled",
770
+ )
771
+ return
772
+
773
+ yield LLMDone(
774
+ response="", provider=source, success=False, error="empty_response"
775
+ )