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,157 @@
1
+ """Compaction checkpoints — persist the pre-compaction conversation.
2
+
3
+ Resolves the context layer's long-standing blocker (artifact schema and
4
+ retention policy, decided 2026-07): every compaction first appends a
5
+ full-snapshot checkpoint, so the conversation state that compaction is about
6
+ to destroy becomes restorable instead of gone.
7
+
8
+ Schema ``aria.context_checkpoint.v1`` — one JSON object per line:
9
+ schema, ts, session_id, seq, kind ("compact" | "hard" | "fallback"),
10
+ message_count, truncated, envelope (optional compaction metadata),
11
+ messages (the full pre-compaction conversation; oldest messages dropped
12
+ first if the serialized snapshot would exceed the per-record byte cap).
13
+
14
+ Storage ``<root>/<session_id>.jsonl`` (append-only, crash-safe, greppable —
15
+ same conventions as the session JSONL store and the durable run store).
16
+
17
+ Retention (enforced on every write, config-overridable by the caller):
18
+ keep the newest ``keep_per_session`` records per session, and delete
19
+ sibling session files untouched for ``max_age_days``.
20
+
21
+ Pure besides filesystem writes under ``root``; clock injectable for tests.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import json
27
+ import time
28
+ from pathlib import Path
29
+ from typing import Any, Callable, Dict, List, Optional
30
+ from aria_code.packages.aria_core.paths import aria_home
31
+
32
+ CHECKPOINT_SCHEMA = "aria.context_checkpoint.v1"
33
+ DEFAULT_KEEP_PER_SESSION = 5
34
+ DEFAULT_MAX_AGE_DAYS = 30
35
+ DEFAULT_MAX_SNAPSHOT_BYTES = 2 * 1024 * 1024
36
+
37
+
38
+ class ContextCheckpointStore:
39
+ def __init__(
40
+ self,
41
+ root: Path,
42
+ *,
43
+ keep_per_session: int = DEFAULT_KEEP_PER_SESSION,
44
+ max_age_days: int = DEFAULT_MAX_AGE_DAYS,
45
+ max_snapshot_bytes: int = DEFAULT_MAX_SNAPSHOT_BYTES,
46
+ clock: Callable[[], float] = time.time,
47
+ ) -> None:
48
+ self.root = Path(root)
49
+ self.keep_per_session = max(1, int(keep_per_session))
50
+ self.max_age_days = max(1, int(max_age_days))
51
+ self.max_snapshot_bytes = max(64 * 1024, int(max_snapshot_bytes))
52
+ self.clock = clock
53
+
54
+ # ── write path ───────────────────────────────────────────────────────────
55
+
56
+ def record(
57
+ self,
58
+ session_id: str,
59
+ messages: List[dict],
60
+ *,
61
+ kind: str = "compact",
62
+ envelope: Optional[Dict[str, Any]] = None,
63
+ ) -> Dict[str, Any]:
64
+ """Append one checkpoint for *session_id*; returns the written record."""
65
+ self.root.mkdir(parents=True, exist_ok=True)
66
+ existing = self.list(session_id)
67
+ seq = (existing[-1]["seq"] + 1) if existing else 1
68
+
69
+ snapshot, truncated = self._bounded_snapshot(list(messages or []))
70
+ record = {
71
+ "schema": CHECKPOINT_SCHEMA,
72
+ "ts": self.clock(),
73
+ "session_id": str(session_id),
74
+ "seq": seq,
75
+ "kind": kind,
76
+ "message_count": len(messages or []),
77
+ "truncated": truncated,
78
+ "envelope": dict(envelope) if envelope else {},
79
+ "messages": snapshot,
80
+ }
81
+
82
+ kept = (existing + [record])[-self.keep_per_session:]
83
+ path = self._path(session_id)
84
+ tmp = path.with_suffix(".jsonl.tmp")
85
+ tmp.write_text(
86
+ "".join(json.dumps(r, ensure_ascii=False, default=str) + "\n" for r in kept),
87
+ encoding="utf-8",
88
+ )
89
+ tmp.replace(path)
90
+ self._expire_old_files()
91
+ return record
92
+
93
+ def _bounded_snapshot(self, messages: List[dict]) -> tuple:
94
+ """Drop oldest messages until the serialized snapshot fits the cap."""
95
+ truncated = False
96
+ while messages:
97
+ blob = json.dumps(messages, ensure_ascii=False, default=str)
98
+ if len(blob.encode("utf-8")) <= self.max_snapshot_bytes:
99
+ return messages, truncated
100
+ drop = max(1, len(messages) // 10)
101
+ messages = messages[drop:]
102
+ truncated = True
103
+ return [], truncated
104
+
105
+ def _expire_old_files(self) -> None:
106
+ cutoff = self.clock() - self.max_age_days * 86400
107
+ try:
108
+ for f in self.root.glob("*.jsonl"):
109
+ if f.stat().st_mtime < cutoff:
110
+ f.unlink(missing_ok=True)
111
+ except Exception:
112
+ pass # retention is best-effort; never break the write path
113
+
114
+ # ── read path ────────────────────────────────────────────────────────────
115
+
116
+ def list(self, session_id: str) -> List[Dict[str, Any]]:
117
+ path = self._path(session_id)
118
+ if not path.exists():
119
+ return []
120
+ records: List[Dict[str, Any]] = []
121
+ for line in path.read_text(encoding="utf-8").splitlines():
122
+ line = line.strip()
123
+ if not line:
124
+ continue
125
+ try:
126
+ obj = json.loads(line)
127
+ except json.JSONDecodeError:
128
+ continue
129
+ if isinstance(obj, dict) and obj.get("schema") == CHECKPOINT_SCHEMA:
130
+ records.append(obj)
131
+ return records
132
+
133
+ def latest(self, session_id: str) -> Optional[Dict[str, Any]]:
134
+ records = self.list(session_id)
135
+ return records[-1] if records else None
136
+
137
+ @staticmethod
138
+ def restore_messages(record: Dict[str, Any]) -> List[dict]:
139
+ """The conversation as it stood before that compaction."""
140
+ msgs = record.get("messages")
141
+ return [dict(m) for m in msgs] if isinstance(msgs, list) else []
142
+
143
+ def _path(self, session_id: str) -> Path:
144
+ safe = "".join(c if c.isalnum() or c in "-_" else "_" for c in str(session_id)) or "session"
145
+ return self.root / f"{safe}.jsonl"
146
+
147
+
148
+ def default_checkpoint_root() -> Path:
149
+ """Same home-resolution rule as the durable run store."""
150
+ import os
151
+ configured = os.getenv("ARIA_HOME")
152
+ if configured:
153
+ root = Path(configured).expanduser()
154
+ else:
155
+ legacy = aria_home()
156
+ root = legacy if legacy.exists() else Path.home() / ".aria-code"
157
+ return root / "runtime" / "context_checkpoints"
@@ -0,0 +1,11 @@
1
+ """Data service facade for package-level imports."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from aria_code.data_service import DataBundle, DataService, DataServiceResult
6
+
7
+ __all__ = [
8
+ "DataBundle",
9
+ "DataService",
10
+ "DataServiceResult",
11
+ ]
@@ -0,0 +1,304 @@
1
+ """Provider error classification and lightweight health state."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import time
6
+ import re
7
+ from dataclasses import asdict, dataclass
8
+ from typing import Any, Dict, List
9
+
10
+
11
+ @dataclass(frozen=True)
12
+ class ProviderIssue:
13
+ provider: str
14
+ category: str
15
+ message: str
16
+ retryable: bool = True
17
+ cooldown_seconds: int = 0
18
+
19
+ def to_dict(self) -> Dict[str, Any]:
20
+ return asdict(self)
21
+
22
+
23
+ @dataclass
24
+ class ProviderState:
25
+ provider: str
26
+ status: str = "ok"
27
+ last_error_category: str = ""
28
+ last_error: str = ""
29
+ failures: int = 0
30
+ cooldown_until: float = 0.0
31
+ last_seen_at: float = 0.0
32
+ last_success_at: float = 0.0
33
+
34
+ def to_dict(self) -> Dict[str, Any]:
35
+ data = asdict(self)
36
+ data["cooldown_active"] = self.cooldown_until > time.time()
37
+ data["cooldown_remaining_seconds"] = max(0, int(self.cooldown_until - time.time()))
38
+ return data
39
+
40
+
41
+ @dataclass(frozen=True)
42
+ class ProviderHealthSummary:
43
+ schema: str
44
+ total: int
45
+ ok: int
46
+ warn: int
47
+ err: int
48
+ cooldown: int
49
+ auth_errors: int
50
+ providers: List[str]
51
+ status: str
52
+ detail: str
53
+ suggestion: str
54
+
55
+ def to_dict(self) -> Dict[str, Any]:
56
+ return asdict(self)
57
+
58
+
59
+ _PUBLIC_SERVICE_LABELS = {
60
+ "market_data": "市场数据",
61
+ "ai": "AI 助手",
62
+ }
63
+
64
+
65
+ @dataclass(frozen=True)
66
+ class PublicServiceStatus:
67
+ """A safe, product-facing view of internal provider health."""
68
+
69
+ schema: str
70
+ service: str
71
+ state: str
72
+ label: str
73
+ message: str
74
+ can_retry: bool
75
+
76
+ def to_dict(self) -> Dict[str, Any]:
77
+ return asdict(self)
78
+
79
+
80
+ def public_service_status(
81
+ service: str, snapshot: List[Dict[str, Any]] | None = None
82
+ ) -> PublicServiceStatus:
83
+ """Project provider health into copy that is safe to render in the product.
84
+
85
+ Provider names, endpoint details and raw failures remain internal diagnostics.
86
+ """
87
+
88
+ service_key = str(service or "").strip().lower() or "service"
89
+ label = _PUBLIC_SERVICE_LABELS.get(service_key, "服务")
90
+ rows = list(snapshot or [])
91
+
92
+ if not rows:
93
+ return PublicServiceStatus(
94
+ schema="aria.public_service_status.v1",
95
+ service=service_key,
96
+ state="unknown",
97
+ label=label,
98
+ message=f"{label}状态将在首次使用后更新。",
99
+ can_retry=False,
100
+ )
101
+
102
+ states = [str(row.get("status") or "unknown") for row in rows]
103
+ categories = [str(row.get("last_error_category") or "") for row in rows]
104
+ available_count = sum(state == "ok" for state in states)
105
+
106
+ if available_count == len(rows):
107
+ state, message, can_retry = "available", f"{label}可用。", False
108
+ elif available_count:
109
+ state, message, can_retry = (
110
+ "degraded",
111
+ f"{label}已自动切换到可用服务。",
112
+ True,
113
+ )
114
+ elif any(category in {"auth", "configuration", "model_unavailable"} for category in categories):
115
+ state, message, can_retry = (
116
+ "unavailable",
117
+ f"{label}暂不可用,需要检查连接设置。",
118
+ False,
119
+ )
120
+ else:
121
+ state, message, can_retry = "unavailable", f"{label}暂不可用,请稍后重试。", True
122
+
123
+ return PublicServiceStatus(
124
+ schema="aria.public_service_status.v1",
125
+ service=service_key,
126
+ state=state,
127
+ label=label,
128
+ message=message,
129
+ can_retry=can_retry,
130
+ )
131
+
132
+
133
+ def _error_status(error: Any, text: str) -> int | None:
134
+ """Prefer structured HTTP/SDK status over incidental words in a URL."""
135
+ for source in (error, getattr(error, "response", None)):
136
+ for key in ("status_code", "status", "code"):
137
+ value = source.get(key) if isinstance(source, dict) else getattr(source, key, None)
138
+ if callable(value):
139
+ try:
140
+ value = value()
141
+ except Exception:
142
+ continue
143
+ if isinstance(value, int) and 400 <= value <= 599:
144
+ return value
145
+ name = str(getattr(value, "name", value) or "").upper()
146
+ mapped = {"UNAUTHENTICATED": 401, "PERMISSION_DENIED": 403,
147
+ "NOT_FOUND": 404, "RESOURCE_EXHAUSTED": 429,
148
+ "DEADLINE_EXCEEDED": 504}.get(name)
149
+ if mapped:
150
+ return mapped
151
+ match = re.search(r"(?:^\s*|\b(?:http|status(?:_code)?|code)\s*[:=]?\s*)([45]\d{2})\b", text, re.I)
152
+ return int(match.group(1)) if match else None
153
+
154
+
155
+ def classify_provider_error(provider: str, error: Any) -> ProviderIssue:
156
+ text = str(error or "").strip()
157
+ low = text.lower()
158
+ if not text:
159
+ return ProviderIssue(provider, "unavailable", "provider returned no usable data", True, 30)
160
+ status = _error_status(error, text)
161
+ if status in {401, 403} or (status is None and (
162
+ any(token in low for token in (
163
+ "unauthorized", "forbidden", "missing_api_key", "invalid credentials",
164
+ "needs_credentials", "permission_denied", "unauthenticated",
165
+ "vertex_not_logged_in",
166
+ )) or re.search(r"(?:invalid|missing|expired).*api[ _]key|api[ _]key.*(?:invalid|missing|expired)", low)
167
+ )):
168
+ return ProviderIssue(provider, "auth", "provider authentication failed", False, 0)
169
+ if "vertex_needs_project" in low:
170
+ return ProviderIssue(provider, "configuration", "Google Cloud project is not configured", False, 0)
171
+ if (status == 404 and any(token in low for token in ("model", "generatecontent"))) or (status is None and re.search(
172
+ r"\bmodel\b.*\b(?:not found|unavailable|does not exist|not supported)\b", low
173
+ )):
174
+ return ProviderIssue(provider, "model_unavailable", "selected model is unavailable", False, 0)
175
+ if status == 429 or (status is None and re.search(r"\brate[\s_-]*limit(?:ed|ing)?\b|\btoo many requests\b|\bquota (?:exceeded|exhausted)\b", low)):
176
+ return ProviderIssue(provider, "rate_limited", "provider rate limited the request", True, 60)
177
+ if status in {408, 504} or any(token in low for token in ("timeout", "timed out", "curl: (28)", "read timed out")):
178
+ return ProviderIssue(provider, "timeout", "provider request timed out", True, 30)
179
+ if any(token in low for token in ("connection", "network", "refused", "remote", "dns", "name resolution")):
180
+ return ProviderIssue(provider, "network", "provider network connection failed", True, 30)
181
+ if any(token in low for token in ("empty", "no data", "no market data", "not found", "none", "null")):
182
+ return ProviderIssue(provider, "no_data", "provider returned no market data", True, 15)
183
+ # Do not retain raw provider errors here. They can contain URLs, request
184
+ # headers, or tokens and this state is consumed by product diagnostics.
185
+ return ProviderIssue(provider, "error", "provider request failed", True, 30)
186
+
187
+
188
+ class ProviderHealthRegistry:
189
+ """In-process health state for data providers."""
190
+
191
+ def __init__(self) -> None:
192
+ self._states: Dict[str, ProviderState] = {}
193
+
194
+ def mark_success(self, provider: str) -> None:
195
+ if not provider:
196
+ return
197
+ state = self._states.setdefault(provider, ProviderState(provider=provider))
198
+ state.status = "ok"
199
+ state.last_error_category = ""
200
+ state.last_error = ""
201
+ state.failures = 0
202
+ state.cooldown_until = 0.0
203
+ now = time.time()
204
+ state.last_seen_at = now
205
+ state.last_success_at = now
206
+
207
+ def mark_issue(self, issue: ProviderIssue) -> None:
208
+ if not issue.provider:
209
+ return
210
+ state = self._states.setdefault(issue.provider, ProviderState(provider=issue.provider))
211
+ now = time.time()
212
+ state.status = issue.category
213
+ state.last_error_category = issue.category
214
+ state.last_error = issue.message
215
+ state.failures += 1
216
+ state.last_seen_at = now
217
+ if issue.cooldown_seconds:
218
+ state.cooldown_until = max(state.cooldown_until, now + issue.cooldown_seconds)
219
+
220
+ def provider_in_cooldown(self, provider: str) -> bool:
221
+ state = self._states.get(provider)
222
+ return bool(state and state.cooldown_until > time.time())
223
+
224
+ def snapshot(self) -> List[Dict[str, Any]]:
225
+ return [self._states[name].to_dict() for name in sorted(self._states)]
226
+
227
+ def summary(self) -> ProviderHealthSummary:
228
+ return summarize_provider_health(self.snapshot())
229
+
230
+ def public_status(self, service: str) -> PublicServiceStatus:
231
+ return public_service_status(service, self.snapshot())
232
+
233
+
234
+ GLOBAL_PROVIDER_HEALTH = ProviderHealthRegistry()
235
+
236
+
237
+ def summarize_provider_health(snapshot: List[Dict[str, Any]] | None = None) -> ProviderHealthSummary:
238
+ rows = list(snapshot or [])
239
+ if not rows:
240
+ return ProviderHealthSummary(
241
+ schema="aria.provider_health_summary.v1",
242
+ total=0,
243
+ ok=0,
244
+ warn=0,
245
+ err=0,
246
+ cooldown=0,
247
+ auth_errors=0,
248
+ providers=[],
249
+ status="warn",
250
+ detail="no provider calls recorded in this session",
251
+ suggestion="Run /quote, /ta, /analyze, or /report to populate provider health.",
252
+ )
253
+
254
+ ok = warn = err = cooldown = auth_errors = 0
255
+ providers: list[str] = []
256
+ for row in rows:
257
+ provider = str(row.get("provider") or "provider")
258
+ providers.append(provider)
259
+ status = str(row.get("status") or "unknown")
260
+ error_category = str(row.get("last_error_category") or "")
261
+ if status == "ok":
262
+ ok += 1
263
+ elif error_category == "auth":
264
+ err += 1
265
+ auth_errors += 1
266
+ else:
267
+ warn += 1
268
+ if row.get("cooldown_active"):
269
+ cooldown += 1
270
+
271
+ if err:
272
+ status = "err"
273
+ elif warn or cooldown:
274
+ status = "warn"
275
+ else:
276
+ status = "ok"
277
+
278
+ parts = [f"{len(rows)} providers"]
279
+ if ok:
280
+ parts.append(f"{ok} ok")
281
+ if warn:
282
+ parts.append(f"{warn} warn")
283
+ if err:
284
+ parts.append(f"{err} err")
285
+ if cooldown:
286
+ parts.append(f"{cooldown} cooldown")
287
+
288
+ suggestion = "Run /doctor --network or inspect /apikey." if status != "ok" else "All providers healthy."
289
+ if auth_errors:
290
+ suggestion = "Fix API keys first, then retry /doctor or /cloud health."
291
+
292
+ return ProviderHealthSummary(
293
+ schema="aria.provider_health_summary.v1",
294
+ total=len(rows),
295
+ ok=ok,
296
+ warn=warn,
297
+ err=err,
298
+ cooldown=cooldown,
299
+ auth_errors=auth_errors,
300
+ providers=providers,
301
+ status=status,
302
+ detail=", ".join(parts),
303
+ suggestion=suggestion,
304
+ )