aria-code 0.52.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (478) hide show
  1. aria_code/__init__.py +42 -0
  2. aria_code/_version.py +20 -0
  3. aria_code/adk_apps/__init__.py +1 -0
  4. aria_code/adk_apps/aria_code_review/__init__.py +1 -0
  5. aria_code/adk_apps/aria_code_review/agent.py +32 -0
  6. aria_code/adk_apps/aria_research/__init__.py +1 -0
  7. aria_code/adk_apps/aria_research/agent.py +31 -0
  8. aria_code/agents/__init__.py +34 -0
  9. aria_code/agents/base.py +318 -0
  10. aria_code/agents/code_review.py +200 -0
  11. aria_code/agents/deep/__init__.py +37 -0
  12. aria_code/agents/deep/calibration_loop.py +144 -0
  13. aria_code/agents/deep/critic.py +125 -0
  14. aria_code/agents/deep/deepen.py +193 -0
  15. aria_code/agents/deep/models.py +149 -0
  16. aria_code/agents/deep/pipeline.py +164 -0
  17. aria_code/agents/deep/quant_fusion.py +192 -0
  18. aria_code/agents/deep/themes.py +95 -0
  19. aria_code/agents/deep/tiers.py +106 -0
  20. aria_code/agents/engineering/__init__.py +14 -0
  21. aria_code/agents/engineering/coder.py +222 -0
  22. aria_code/agents/engineering/tester.py +145 -0
  23. aria_code/agents/financial/__init__.py +21 -0
  24. aria_code/agents/financial/cashflow_burn.py +119 -0
  25. aria_code/agents/financial/catalyst.py +279 -0
  26. aria_code/agents/financial/corporate_finance.py +175 -0
  27. aria_code/agents/financial/debate.py +224 -0
  28. aria_code/agents/financial/earnings.py +303 -0
  29. aria_code/agents/financial/fundamental.py +191 -0
  30. aria_code/agents/financial/macro.py +99 -0
  31. aria_code/agents/financial/news.py +207 -0
  32. aria_code/agents/financial/risk.py +165 -0
  33. aria_code/agents/financial/sector.py +279 -0
  34. aria_code/agents/financial/strategist.py +121 -0
  35. aria_code/agents/financial/stripe_revenue.py +127 -0
  36. aria_code/agents/financial/synthesis.py +274 -0
  37. aria_code/agents/financial/technical.py +258 -0
  38. aria_code/agents/orchestrator.py +44 -0
  39. aria_code/agents/portfolio_agent.py +363 -0
  40. aria_code/agents/realty/__init__.py +62 -0
  41. aria_code/agents/realty/asset_diagnosis.py +152 -0
  42. aria_code/agents/realty/business_match.py +166 -0
  43. aria_code/agents/realty/cashflow_verify.py +209 -0
  44. aria_code/agents/realty/contract_rules.py +210 -0
  45. aria_code/agents/realty/energy_anomaly.py +189 -0
  46. aria_code/agents/realty/exit_settlement.py +208 -0
  47. aria_code/agents/realty/fulfillment_risk.py +206 -0
  48. aria_code/agents/realty/ops_optimize.py +160 -0
  49. aria_code/agents/realty/revenue_share.py +215 -0
  50. aria_code/agents/registry.py +158 -0
  51. aria_code/agents/signal_scheme.py +111 -0
  52. aria_code/agents/sports/__init__.py +0 -0
  53. aria_code/agents/sports/football_agent.py +197 -0
  54. aria_code/agents/supervisor.py +113 -0
  55. aria_code/agents/team.py +492 -0
  56. aria_code/agents/warehouse/__init__.py +25 -0
  57. aria_code/agents/warehouse/contracts.py +26 -0
  58. aria_code/agents/warehouse/dashboard.py +155 -0
  59. aria_code/agents/warehouse/fulfillment_leadtime.py +95 -0
  60. aria_code/agents/warehouse/inbound_exceptions.py +25 -0
  61. aria_code/agents/warehouse/inventory_health.py +24 -0
  62. aria_code/agents/warehouse/local_run.py +71 -0
  63. aria_code/agents/warehouse/local_snapshot.py +132 -0
  64. aria_code/agents/warehouse/logistics_cost.py +84 -0
  65. aria_code/agents/warehouse/logistics_sync.py +21 -0
  66. aria_code/agents/warehouse/workflow.py +31 -0
  67. aria_code/aliyun_data_client.py +4 -0
  68. aria_code/apps/README.md +12 -0
  69. aria_code/apps/__init__.py +2 -0
  70. aria_code/apps/channels/README.md +15 -0
  71. aria_code/apps/channels/__init__.py +17 -0
  72. aria_code/apps/channels/intake.py +92 -0
  73. aria_code/apps/channels/registry.py +95 -0
  74. aria_code/apps/channels/tradingview.py +94 -0
  75. aria_code/apps/cli/README.md +13 -0
  76. aria_code/apps/cli/__init__.py +2 -0
  77. aria_code/apps/cli/_optional.py +120 -0
  78. aria_code/apps/cli/bootstrap.py +145 -0
  79. aria_code/apps/cli/broker_render.py +206 -0
  80. aria_code/apps/cli/codegen_paths.py +29 -0
  81. aria_code/apps/cli/commands/__init__.py +16 -0
  82. aria_code/apps/cli/commands/_business_render.py +78 -0
  83. aria_code/apps/cli/commands/_ui.py +71 -0
  84. aria_code/apps/cli/commands/analysis_cmds.py +369 -0
  85. aria_code/apps/cli/commands/ashare_prediction_cmds.py +327 -0
  86. aria_code/apps/cli/commands/auth_cmds.py +239 -0
  87. aria_code/apps/cli/commands/backtest_cmds.py +2543 -0
  88. aria_code/apps/cli/commands/broker_cmds.py +1234 -0
  89. aria_code/apps/cli/commands/business_workflow_cmds.py +319 -0
  90. aria_code/apps/cli/commands/canvas_cmds.py +77 -0
  91. aria_code/apps/cli/commands/catalog.py +87 -0
  92. aria_code/apps/cli/commands/core_cmds.py +2520 -0
  93. aria_code/apps/cli/commands/data_cmds.py +457 -0
  94. aria_code/apps/cli/commands/diagnostic_cmds.py +230 -0
  95. aria_code/apps/cli/commands/diagnostic_ops_cmds.py +813 -0
  96. aria_code/apps/cli/commands/file_cmds.py +312 -0
  97. aria_code/apps/cli/commands/finance_service_cmds.py +60 -0
  98. aria_code/apps/cli/commands/fx_commodity_cmds.py +123 -0
  99. aria_code/apps/cli/commands/market.py +434 -0
  100. aria_code/apps/cli/commands/market_cmds.py +1381 -0
  101. aria_code/apps/cli/commands/market_context.py +425 -0
  102. aria_code/apps/cli/commands/market_render.py +7 -0
  103. aria_code/apps/cli/commands/model_cmds.py +2153 -0
  104. aria_code/apps/cli/commands/ops_cmds.py +721 -0
  105. aria_code/apps/cli/commands/orchestrator_cmds.py +179 -0
  106. aria_code/apps/cli/commands/pdf_export_cmds.py +125 -0
  107. aria_code/apps/cli/commands/portfolio_cmds.py +1278 -0
  108. aria_code/apps/cli/commands/report.py +437 -0
  109. aria_code/apps/cli/commands/scaffold_templates.py +617 -0
  110. aria_code/apps/cli/commands/session_cmds.py +236 -0
  111. aria_code/apps/cli/commands/session_ux_cmds.py +359 -0
  112. aria_code/apps/cli/commands/team.py +669 -0
  113. aria_code/apps/cli/commands/team_render.py +8 -0
  114. aria_code/apps/cli/commands/ui_cmds.py +401 -0
  115. aria_code/apps/cli/commands/warehouse_cmds.py +79 -0
  116. aria_code/apps/cli/commands/workflow_cmds.py +480 -0
  117. aria_code/apps/cli/commands/workspace_cmds.py +1494 -0
  118. aria_code/apps/cli/config_paths.py +73 -0
  119. aria_code/apps/cli/config_store.py +78 -0
  120. aria_code/apps/cli/constants.py +88 -0
  121. aria_code/apps/cli/context.py +34 -0
  122. aria_code/apps/cli/deterministic.py +191 -0
  123. aria_code/apps/cli/direct.py +48 -0
  124. aria_code/apps/cli/finance_service_catalog.py +111 -0
  125. aria_code/apps/cli/football_reports.py +231 -0
  126. aria_code/apps/cli/github_app_auth.py +135 -0
  127. aria_code/apps/cli/google_login.py +196 -0
  128. aria_code/apps/cli/handlers/__init__.py +11 -0
  129. aria_code/apps/cli/handlers/broker_handlers.py +122 -0
  130. aria_code/apps/cli/handlers/chart_handlers.py +1309 -0
  131. aria_code/apps/cli/handlers/market_handlers.py +2513 -0
  132. aria_code/apps/cli/handlers/realty_handlers.py +114 -0
  133. aria_code/apps/cli/handlers/sports_handlers.py +22 -0
  134. aria_code/apps/cli/handlers/strategy_advice.py +82 -0
  135. aria_code/apps/cli/helpers.py +302 -0
  136. aria_code/apps/cli/hooks.py +180 -0
  137. aria_code/apps/cli/i18n.py +297 -0
  138. aria_code/apps/cli/intent.py +136 -0
  139. aria_code/apps/cli/intent_router.py +276 -0
  140. aria_code/apps/cli/intent_signals.py +344 -0
  141. aria_code/apps/cli/lifecycle_hooks.py +48 -0
  142. aria_code/apps/cli/local_tool_schemas.py +536 -0
  143. aria_code/apps/cli/main.py +29 -0
  144. aria_code/apps/cli/market_metadata.py +135 -0
  145. aria_code/apps/cli/market_universe.py +487 -0
  146. aria_code/apps/cli/message_processing.py +310 -0
  147. aria_code/apps/cli/model_catalog.py +620 -0
  148. aria_code/apps/cli/pdf_report.py +977 -0
  149. aria_code/apps/cli/plan_mode.py +139 -0
  150. aria_code/apps/cli/plotly_html.py +15 -0
  151. aria_code/apps/cli/prediction_feedback.py +202 -0
  152. aria_code/apps/cli/preflight.py +502 -0
  153. aria_code/apps/cli/project_aria.py +60 -0
  154. aria_code/apps/cli/prompt_assembly.py +59 -0
  155. aria_code/apps/cli/prompts/__init__.py +0 -0
  156. aria_code/apps/cli/prompts/coding.py +53 -0
  157. aria_code/apps/cli/prompts/select.py +142 -0
  158. aria_code/apps/cli/prompts/system_prompts.py +552 -0
  159. aria_code/apps/cli/prompts/ui.py +436 -0
  160. aria_code/apps/cli/provider_endpoints.py +237 -0
  161. aria_code/apps/cli/provider_keys.py +73 -0
  162. aria_code/apps/cli/providers/__init__.py +1 -0
  163. aria_code/apps/cli/providers/base.py +521 -0
  164. aria_code/apps/cli/providers/chat_routing.py +128 -0
  165. aria_code/apps/cli/providers/collaboration.py +98 -0
  166. aria_code/apps/cli/providers/llm/__init__.py +1 -0
  167. aria_code/apps/cli/providers/llm/offline_responses.py +68 -0
  168. aria_code/apps/cli/providers/llm/ollama_stream.py +1594 -0
  169. aria_code/apps/cli/providers/llm/response_cache.py +60 -0
  170. aria_code/apps/cli/providers/llm/sse_stream.py +257 -0
  171. aria_code/apps/cli/providers/runtime_bridge.py +353 -0
  172. aria_code/apps/cli/providers/vertexai_stream.py +316 -0
  173. aria_code/apps/cli/runtime_consumer.py +657 -0
  174. aria_code/apps/cli/sandbox.py +32 -0
  175. aria_code/apps/cli/session_export.py +120 -0
  176. aria_code/apps/cli/session_jsonl.py +208 -0
  177. aria_code/apps/cli/session_store.py +112 -0
  178. aria_code/apps/cli/skills_catalog.py +273 -0
  179. aria_code/apps/cli/todo_tracker.py +190 -0
  180. aria_code/apps/cli/tool_executor.py +823 -0
  181. aria_code/apps/cli/tool_registry.py +34 -0
  182. aria_code/apps/cli/tool_scope.py +106 -0
  183. aria_code/apps/cli/tools/__init__.py +40 -0
  184. aria_code/apps/cli/tools/context.py +46 -0
  185. aria_code/apps/cli/tools/file_tools.py +180 -0
  186. aria_code/apps/cli/tools/market_tools.py +620 -0
  187. aria_code/apps/cli/tools/notebook_tools.py +111 -0
  188. aria_code/apps/cli/tools/system_tools.py +726 -0
  189. aria_code/apps/cli/tools/write_tools.py +845 -0
  190. aria_code/apps/cli/tradingview_bridge.py +529 -0
  191. aria_code/apps/cli/turn_planning.py +137 -0
  192. aria_code/apps/cli/update_check.py +153 -0
  193. aria_code/apps/cli/utils/__init__.py +0 -0
  194. aria_code/apps/cli/utils/market_detect.py +1597 -0
  195. aria_code/apps/daemon/README.md +14 -0
  196. aria_code/apps/vscode/README.md +115 -0
  197. aria_code/apps/vscode/package.json +70 -0
  198. aria_code/aria_cli.py +6743 -0
  199. aria_code/aria_daemon.py +1398 -0
  200. aria_code/aria_feishu_bot.py +1423 -0
  201. aria_code/aria_mcp_server.py +7 -0
  202. aria_code/aria_relay_client.py +4 -0
  203. aria_code/aria_relay_server.py +490 -0
  204. aria_code/aria_telegram_bot.py +202 -0
  205. aria_code/ariarc.py +385 -0
  206. aria_code/artifacts.py +581 -0
  207. aria_code/backtest_engine.py +4 -0
  208. aria_code/backtest_report.py +4 -0
  209. aria_code/brokers/__init__.py +78 -0
  210. aria_code/brokers/automation.py +193 -0
  211. aria_code/brokers/base.py +231 -0
  212. aria_code/brokers/capabilities.py +264 -0
  213. aria_code/brokers/cn/__init__.py +10 -0
  214. aria_code/brokers/cn/easytrader_broker.py +193 -0
  215. aria_code/brokers/cn/futu_broker.py +194 -0
  216. aria_code/brokers/cn/longbridge_broker.py +190 -0
  217. aria_code/brokers/cn/tiger_broker.py +196 -0
  218. aria_code/brokers/cn/xtquant_broker.py +225 -0
  219. aria_code/brokers/config.py +414 -0
  220. aria_code/brokers/intl/__init__.py +5 -0
  221. aria_code/brokers/intl/alpaca_broker.py +183 -0
  222. aria_code/brokers/intl/ibkr_broker.py +215 -0
  223. aria_code/brokers/intl/trading212_broker.py +183 -0
  224. aria_code/brokers/intl/webull_broker.py +156 -0
  225. aria_code/brokers/paper_broker.py +266 -0
  226. aria_code/brokers/planning.py +296 -0
  227. aria_code/brokers/registry.py +213 -0
  228. aria_code/brokers/trading.py +267 -0
  229. aria_code/canva_client.py +4 -0
  230. aria_code/change_store.py +127 -0
  231. aria_code/clients/__init__.py +0 -0
  232. aria_code/clients/aliyun_data_client.py +660 -0
  233. aria_code/clients/aria_relay_client.py +182 -0
  234. aria_code/clients/canva_client.py +284 -0
  235. aria_code/clients/figma_client.py +100 -0
  236. aria_code/clients/football_data_client.py +1671 -0
  237. aria_code/clients/kling_video_client.py +182 -0
  238. aria_code/clients/market_data_client.py +1976 -0
  239. aria_code/clients/openai_image_client.py +242 -0
  240. aria_code/clients/runway_video_client.py +157 -0
  241. aria_code/clients/warehouse_erp_client.py +105 -0
  242. aria_code/cloud_memory.py +181 -0
  243. aria_code/command_safety.py +19 -0
  244. aria_code/computer_use_tools.py +4 -0
  245. aria_code/dashboard_generator.py +579 -0
  246. aria_code/data_analysis_tools.py +4 -0
  247. aria_code/data_cleaner.py +483 -0
  248. aria_code/data_service.py +513 -0
  249. aria_code/datasources/__init__.py +23 -0
  250. aria_code/datasources/base.py +166 -0
  251. aria_code/datasources/router.py +253 -0
  252. aria_code/datasources/sources/__init__.py +15 -0
  253. aria_code/datasources/sources/akshare_source.py +269 -0
  254. aria_code/datasources/sources/alpha_vantage_source.py +203 -0
  255. aria_code/datasources/sources/edgar_source.py +219 -0
  256. aria_code/datasources/sources/finnhub_source.py +198 -0
  257. aria_code/datasources/sources/fred_source.py +223 -0
  258. aria_code/datasources/sources/tushare_source.py +143 -0
  259. aria_code/datasources/sources/web_scraper_source.py +278 -0
  260. aria_code/datasources/sources/world_bank_source.py +206 -0
  261. aria_code/datasources/sources/yfinance_source.py +152 -0
  262. aria_code/demo_player.py +207 -0
  263. aria_code/doctor.py +813 -0
  264. aria_code/domain/__init__.py +0 -0
  265. aria_code/domain/backtest_engine.py +354 -0
  266. aria_code/domain/backtest_report.py +472 -0
  267. aria_code/domain/finance_formulas.py +389 -0
  268. aria_code/domain/portfolio_ledger.py +307 -0
  269. aria_code/domain/strategy_vault.py +421 -0
  270. aria_code/evals/__init__.py +37 -0
  271. aria_code/evals/harness.py +598 -0
  272. aria_code/evals/runner.py +238 -0
  273. aria_code/external_agent_runner.py +115 -0
  274. aria_code/figma_client.py +4 -0
  275. aria_code/file_analysis_tools.py +4 -0
  276. aria_code/finance_formulas.py +4 -0
  277. aria_code/football_data_client.py +4 -0
  278. aria_code/image_gen_tools.py +4 -0
  279. aria_code/intent_classifier.py +386 -0
  280. aria_code/kling_video_client.py +4 -0
  281. aria_code/licensing.py +151 -0
  282. aria_code/local_finance_tools.py +4 -0
  283. aria_code/local_image_provider.py +4 -0
  284. aria_code/local_llm_provider.py +4 -0
  285. aria_code/macro_tools.py +4 -0
  286. aria_code/markdown_pdf.py +289 -0
  287. aria_code/market_data_client.py +4 -0
  288. aria_code/mcp_client.py +639 -0
  289. aria_code/memory_manager.py +246 -0
  290. aria_code/model_capability.py +486 -0
  291. aria_code/notification_tools.py +4 -0
  292. aria_code/openai_image_client.py +4 -0
  293. aria_code/packages/__init__.py +23 -0
  294. aria_code/packages/adk_bridge/__init__.py +11 -0
  295. aria_code/packages/adk_bridge/code_review_tools.py +49 -0
  296. aria_code/packages/adk_bridge/market_tools.py +125 -0
  297. aria_code/packages/aria_agents/__init__.py +5 -0
  298. aria_code/packages/aria_agents/manifest.py +78 -0
  299. aria_code/packages/aria_core/__init__.py +34 -0
  300. aria_code/packages/aria_core/architecture.py +269 -0
  301. aria_code/packages/aria_core/export.py +147 -0
  302. aria_code/packages/aria_core/manifest.py +65 -0
  303. aria_code/packages/aria_core/paths.py +57 -0
  304. aria_code/packages/aria_core/secure_file.py +68 -0
  305. aria_code/packages/aria_infra/__init__.py +15 -0
  306. aria_code/packages/aria_infra/arthera.py +52 -0
  307. aria_code/packages/aria_infra/doctor.py +246 -0
  308. aria_code/packages/aria_infra/product.py +40 -0
  309. aria_code/packages/aria_mcp/__init__.py +25 -0
  310. aria_code/packages/aria_mcp/bridge.py +201 -0
  311. aria_code/packages/aria_mcp/circuit.py +82 -0
  312. aria_code/packages/aria_mcp/config.py +111 -0
  313. aria_code/packages/aria_mcp/installer.py +95 -0
  314. aria_code/packages/aria_mcp/server.py +1550 -0
  315. aria_code/packages/aria_mcp/tools.py +81 -0
  316. aria_code/packages/aria_sdk/__init__.py +19 -0
  317. aria_code/packages/aria_sdk/client.py +396 -0
  318. aria_code/packages/aria_sdk/providers.py +70 -0
  319. aria_code/packages/aria_sdk/streaming.py +79 -0
  320. aria_code/packages/aria_sdk/types.py +86 -0
  321. aria_code/packages/aria_services/__init__.py +92 -0
  322. aria_code/packages/aria_services/cache.py +60 -0
  323. aria_code/packages/aria_services/context.py +356 -0
  324. aria_code/packages/aria_services/context_checkpoints.py +157 -0
  325. aria_code/packages/aria_services/data.py +11 -0
  326. aria_code/packages/aria_services/provider_health.py +268 -0
  327. aria_code/packages/aria_services/references.py +247 -0
  328. aria_code/packages/aria_services/registry.py +249 -0
  329. aria_code/packages/aria_services/research_protocol.py +57 -0
  330. aria_code/packages/aria_services/research_quality.py +186 -0
  331. aria_code/packages/aria_services/settings.py +157 -0
  332. aria_code/packages/aria_services/usage.py +151 -0
  333. aria_code/packages/aria_skills/__init__.py +46 -0
  334. aria_code/packages/aria_skills/catalog.py +149 -0
  335. aria_code/packages/aria_skills/loader.py +455 -0
  336. aria_code/packages/aria_skills/registry.py +84 -0
  337. aria_code/packages/aria_tools/__init__.py +5 -0
  338. aria_code/packages/aria_tools/financial/__init__.py +8 -0
  339. aria_code/packages/aria_tools/financial/_paths.py +130 -0
  340. aria_code/packages/aria_tools/financial/compliance.py +31 -0
  341. aria_code/packages/aria_tools/financial/factors.py +33 -0
  342. aria_code/packages/aria_tools/financial/risk_tools.py +33 -0
  343. aria_code/packages/aria_tools/financial/strategy.py +31 -0
  344. aria_code/packages/aria_tools/registry.py +128 -0
  345. aria_code/packages/quant_engine/__init__.py +34 -0
  346. aria_code/packages/quant_engine/_namespace.py +62 -0
  347. aria_code/packages/quant_engine/backtest/__init__.py +14 -0
  348. aria_code/packages/quant_engine/backtest/core.py +53 -0
  349. aria_code/packages/quant_engine/backtest/engine.py +96 -0
  350. aria_code/packages/quant_engine/portfolio/__init__.py +13 -0
  351. aria_code/packages/quant_engine/portfolio/optimizer.py +85 -0
  352. aria_code/packages/quant_engine/sports/__init__.py +80 -0
  353. aria_code/packages/quant_engine/sports/calibrator.py +354 -0
  354. aria_code/packages/quant_engine/sports/dixon_coles.py +234 -0
  355. aria_code/packages/quant_engine/sports/elo.py +300 -0
  356. aria_code/packages/quant_engine/sports/form.py +188 -0
  357. aria_code/packages/quant_engine/sports/h2h.py +195 -0
  358. aria_code/packages/quant_engine/sports/ml_model.py +377 -0
  359. aria_code/packages/quant_engine/sports/predictor.py +312 -0
  360. aria_code/packages/quant_engine/sports/tracker.py +665 -0
  361. aria_code/packages/quant_engine/stochastic/__init__.py +35 -0
  362. aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +195 -0
  363. aria_code/packages/quant_engine/stochastic/ito_calculus.py +477 -0
  364. aria_code/packages/quant_engine/stochastic/kelly_criterion.py +181 -0
  365. aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +95 -0
  366. aria_code/packages/quant_engine/stochastic/options_pricing.py +576 -0
  367. aria_code/packages/quant_engine/stochastic/stochastic_processes.py +90 -0
  368. aria_code/packs/__init__.py +85 -0
  369. aria_code/packs/base.py +168 -0
  370. aria_code/packs/finance/__init__.py +250 -0
  371. aria_code/packs/logistics/__init__.py +169 -0
  372. aria_code/packs/payments/__init__.py +139 -0
  373. aria_code/packs/realty/__init__.py +190 -0
  374. aria_code/packs/registry.py +202 -0
  375. aria_code/packs/rules.py +90 -0
  376. aria_code/plan_utils.py +194 -0
  377. aria_code/plugin_loader.py +328 -0
  378. aria_code/portfolio_ledger.py +4 -0
  379. aria_code/preview_server.py +449 -0
  380. aria_code/privacy/__init__.py +5 -0
  381. aria_code/privacy/feedback.py +123 -0
  382. aria_code/project_review.py +278 -0
  383. aria_code/project_review_api.py +235 -0
  384. aria_code/project_review_server.py +18 -0
  385. aria_code/project_tools.py +4 -0
  386. aria_code/providers/__init__.py +30 -0
  387. aria_code/providers/llm/__init__.py +19 -0
  388. aria_code/providers/llm/anthropic.py +184 -0
  389. aria_code/providers/llm/autoconfig.py +213 -0
  390. aria_code/providers/llm/base.py +139 -0
  391. aria_code/providers/llm/custom.py +158 -0
  392. aria_code/providers/llm/ollama.py +129 -0
  393. aria_code/providers/llm/openai_compat.py +313 -0
  394. aria_code/providers/llm/registry.py +444 -0
  395. aria_code/providers/local_image_provider.py +202 -0
  396. aria_code/providers/local_llm_provider.py +589 -0
  397. aria_code/realty_data_tools.py +4 -0
  398. aria_code/report_exporters.py +150 -0
  399. aria_code/report_generator.py +1764 -0
  400. aria_code/runtime/__init__.py +169 -0
  401. aria_code/runtime/acceptance.py +481 -0
  402. aria_code/runtime/agent_loop.py +1520 -0
  403. aria_code/runtime/approval.py +57 -0
  404. aria_code/runtime/budget.py +232 -0
  405. aria_code/runtime/checkpoints.py +432 -0
  406. aria_code/runtime/crash_report.py +174 -0
  407. aria_code/runtime/events.py +113 -0
  408. aria_code/runtime/gateway.py +150 -0
  409. aria_code/runtime/lsp.py +484 -0
  410. aria_code/runtime/orchestrator.py +55 -0
  411. aria_code/runtime/repo_map.py +700 -0
  412. aria_code/runtime/run_state.py +127 -0
  413. aria_code/runtime/run_store.py +450 -0
  414. aria_code/runtime/self_healing.py +422 -0
  415. aria_code/runtime/subagent.py +547 -0
  416. aria_code/runtime/task_ledger.py +86 -0
  417. aria_code/runtime/task_orchestrator.py +90 -0
  418. aria_code/runtime/tool_executor.py +217 -0
  419. aria_code/runtime/tool_policy.py +107 -0
  420. aria_code/runtime/worktrees.py +215 -0
  421. aria_code/runway_video_client.py +4 -0
  422. aria_code/safety/__init__.py +23 -0
  423. aria_code/safety/permissions.py +306 -0
  424. aria_code/safety/service.py +102 -0
  425. aria_code/setup_wizard.py +673 -0
  426. aria_code/spreadsheet_tools.py +4 -0
  427. aria_code/strategy_vault.py +4 -0
  428. aria_code/tools/__init__.py +0 -0
  429. aria_code/tools/artifact_tools.py +252 -0
  430. aria_code/tools/broker_tools.py +92 -0
  431. aria_code/tools/build_quant_engine.py +97 -0
  432. aria_code/tools/code_audit_tools.py +192 -0
  433. aria_code/tools/computer_use_tools.py +504 -0
  434. aria_code/tools/data_analysis_tools.py +809 -0
  435. aria_code/tools/enterprise_finance_tools.py +156 -0
  436. aria_code/tools/extended_tools.py +240 -0
  437. aria_code/tools/file_analysis_tools.py +885 -0
  438. aria_code/tools/image_gen_tools.py +114 -0
  439. aria_code/tools/local_finance_tools.py +3417 -0
  440. aria_code/tools/logistics_tools.py +135 -0
  441. aria_code/tools/macro_tools.py +369 -0
  442. aria_code/tools/notification_tools.py +249 -0
  443. aria_code/tools/project_tools.py +525 -0
  444. aria_code/tools/realty_data_tools.py +659 -0
  445. aria_code/tools/spreadsheet_tools.py +388 -0
  446. aria_code/tools/stripe_tools.py +115 -0
  447. aria_code/ui/__init__.py +105 -0
  448. aria_code/ui/banner.py +508 -0
  449. aria_code/ui/completer.py +501 -0
  450. aria_code/ui/console.py +281 -0
  451. aria_code/ui/image_render.py +243 -0
  452. aria_code/ui/input_box.py +488 -0
  453. aria_code/ui/picker.py +201 -0
  454. aria_code/ui/render/__init__.py +11 -0
  455. aria_code/ui/render/finance.py +1705 -0
  456. aria_code/ui/render/market.py +225 -0
  457. aria_code/ui/render/output.py +775 -0
  458. aria_code/ui/render/responsive.py +75 -0
  459. aria_code/ui/render/team.py +354 -0
  460. aria_code/ui/robot.py +235 -0
  461. aria_code/ui/startup_dashboard.py +109 -0
  462. aria_code/utils/vscode_uri.py +37 -0
  463. aria_code/video_analysis.py +147 -0
  464. aria_code/video_editor.py +271 -0
  465. aria_code/workspace/__init__.py +6 -0
  466. aria_code/workspace/files.py +193 -0
  467. aria_code/workspace/verify.py +113 -0
  468. aria_code/workspace_changes.py +199 -0
  469. aria_code/workspace_context.py +233 -0
  470. aria_code/workspace_service.py +196 -0
  471. aria_code/workspace_tools.py +150 -0
  472. aria_code-0.52.0.dist-info/METADATA +237 -0
  473. aria_code-0.52.0.dist-info/RECORD +478 -0
  474. aria_code-0.52.0.dist-info/WHEEL +5 -0
  475. aria_code-0.52.0.dist-info/entry_points.txt +3 -0
  476. aria_code-0.52.0.dist-info/licenses/LICENSE +201 -0
  477. aria_code-0.52.0.dist-info/licenses/NOTICE +49 -0
  478. aria_code-0.52.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,206 @@
1
+ """券商账户 / 持仓 / 订单的终端渲染 —— 从 aria_cli.py 抽出的第二块。
2
+
3
+ 原本在 aria_cli.py 的 4399-4578 行。跟 football_reports 一样,这些函数依赖
4
+ aria_cli 的模块级状态(``console`` / ``HAS_RICH`` / ``Panel`` / ``rich_box``),
5
+ 所以必须由 aria_cli 用 ``_rebind_module_function_globals`` 绑回它自己的
6
+ globals,不能只是普通 import。
7
+
8
+ 调用方有两种形态,重绑后都成立:
9
+ - ``apps/cli/commands/broker_cmds.py`` 用显式 ``from aria_cli import
10
+ _print_broker_account`` —— 读的是 aria_cli 的命名空间;
11
+ - ``tests/test_responsive_rendering.py`` 用 ``aria_cli._print_broker_positions``
12
+ —— 同上。
13
+
14
+ (这一组不像 football 那样被 mixin 裸名调用,但依赖 aria_cli 模块级 rich
15
+ 状态,所以约束是一样的。)
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ __all__ = [
21
+ "_print_broker_account",
22
+ "_print_broker_positions",
23
+ "_print_broker_orders",
24
+ ]
25
+
26
+
27
+ def _print_broker_account(acct: "AccountInfo"):
28
+ """Render AccountInfo in a Rich Panel."""
29
+ if not HAS_RICH:
30
+ print(f"{acct.label} 总资产:{acct.total_assets:,.2f} 可用:{acct.cash:,.2f} 市值:{acct.market_value:,.2f}")
31
+ return
32
+ pnl_color = "green" if acct.pnl_today >= 0 else "red"
33
+ pnl_sign = "+" if acct.pnl_today >= 0 else ""
34
+ body = (
35
+ f"[dim]账户:[/dim] [bold]{acct.masked_account}[/bold] [dim]({acct.broker_type})[/dim]\n\n"
36
+ f" 总资产 [bold]{acct.currency} {acct.total_assets:>14,.2f}[/bold]\n"
37
+ f" 持仓市值 [bold]{acct.market_value:>14,.2f}[/bold]\n"
38
+ f" 可用现金 [bold]{acct.cash:>14,.2f}[/bold]\n"
39
+ f" 冻结资金 [dim]{acct.frozen:>14,.2f}[/dim]\n"
40
+ f" 当日盈亏 [{pnl_color}]{pnl_sign}{acct.pnl_today:>14,.2f}[/{pnl_color}]\n"
41
+ )
42
+ if acct.pnl_total:
43
+ tp_color = "green" if acct.pnl_total >= 0 else "red"
44
+ body += f" 累计盈亏 [{tp_color}]{pnl_sign}{acct.pnl_total:>14,.2f}[/{tp_color}]\n"
45
+ console.print(Panel(body, title=f"[bold]{acct.label}[/bold]",
46
+ border_style="dim", box=rich_box.ROUNDED, padding=(0, 1)))
47
+
48
+
49
+ def _print_broker_positions(positions: list, broker_label: str, currency: str = "CNY"):
50
+ """Render Position list as a Rich Table."""
51
+ if not HAS_RICH:
52
+ for p in positions:
53
+ print(f" {p.symbol:<8} {p.name:<12} 持仓:{p.quantity} 市值:{p.market_value:,.2f} 盈亏:{p.pnl:+,.2f} ({p.pnl_pct:+.2f}%)")
54
+ return
55
+ if not positions:
56
+ console.print(f"[dim]{broker_label} — 当前无持仓[/dim]")
57
+ return
58
+ from rich.markup import escape as _esc
59
+ from ui.render.responsive import StackedRecord, render_stacked_records, structured_layout
60
+
61
+ ordered = sorted(positions, key=lambda x: -abs(x.market_value))
62
+ total_mv = sum(p.market_value for p in positions)
63
+ total_pnl = sum(p.pnl for p in positions)
64
+ total_color = "green" if total_pnl >= 0 else "red"
65
+ layout = structured_layout(console)
66
+ if layout == "stacked":
67
+ records = []
68
+ for p in ordered:
69
+ pnl_color = "green" if p.pnl >= 0 else "red"
70
+ records.append(StackedRecord(
71
+ headline=f"{_esc(str(p.symbol))} {_esc(str(p.name or '—'))}",
72
+ lines=(
73
+ f"[dim]持仓[/dim] {p.quantity:,.0f} · [dim]可卖[/dim] {p.available_qty:,.0f}",
74
+ f"[dim]成本[/dim] {p.cost_price:.3f} · [dim]现价[/dim] {p.current_price:.3f}",
75
+ f"[dim]市值[/dim] {p.market_value:,.2f} · "
76
+ f"[dim]盈亏[/dim] [{pnl_color}]{p.pnl:+,.2f} ({p.pnl_pct:+.2f}%)[/{pnl_color}]",
77
+ ),
78
+ ))
79
+ render_stacked_records(
80
+ console,
81
+ title=f"{_esc(str(broker_label))} 持仓",
82
+ records=records,
83
+ footer=(
84
+ f"共 {len(positions)} 只 · 总市值 {currency} {total_mv:,.2f} · "
85
+ f"总盈亏 [{total_color}]{total_pnl:+,.2f}[/{total_color}]"
86
+ ),
87
+ )
88
+ return
89
+ from rich.table import Table
90
+ tbl = Table(title=f"[bold]{broker_label}[/bold] 持仓", show_header=True, header_style="bold")
91
+ tbl.add_column("代码", style="bold", no_wrap=True)
92
+ tbl.add_column("名称", max_width=12)
93
+ tbl.add_column("持仓", justify="right")
94
+ if layout == "full":
95
+ tbl.add_column("可卖", justify="right", style="dim")
96
+ tbl.add_column("成本", justify="right", style="dim")
97
+ tbl.add_column("现价", justify="right")
98
+ tbl.add_column("市值", justify="right")
99
+ tbl.add_column("盈亏", justify="right")
100
+ tbl.add_column("盈亏%", justify="right")
101
+ for p in ordered:
102
+ pnl_color = "green" if p.pnl >= 0 else "red"
103
+ pnl_sign = "+" if p.pnl >= 0 else ""
104
+ row = [p.symbol, p.name[:12] or "—", f"{p.quantity:,.0f}"]
105
+ if layout == "full":
106
+ row.extend([
107
+ f"{p.available_qty:,.0f}",
108
+ f"{p.cost_price:.3f}",
109
+ f"{p.current_price:.3f}",
110
+ ])
111
+ row.extend([
112
+ f"{p.market_value:,.2f}",
113
+ f"[{pnl_color}]{pnl_sign}{p.pnl:,.2f}[/{pnl_color}]",
114
+ f"[{pnl_color}]{pnl_sign}{p.pnl_pct:.2f}%[/{pnl_color}]",
115
+ ])
116
+ tbl.add_row(*row)
117
+ console.print(tbl)
118
+ console.print(
119
+ f" [dim]共 {len(positions)} 只 总市值 {total_mv:,.2f} "
120
+ f"总盈亏 [{total_color}]{'+' if total_pnl>=0 else ''}{total_pnl:,.2f}[/{total_color}][/dim]"
121
+ )
122
+
123
+
124
+ def _print_broker_orders(orders: list, broker_label: str, status_filter: str = "all"):
125
+ """Render Order list as a Rich Table."""
126
+ if not HAS_RICH:
127
+ for o in orders:
128
+ print(f" {o.order_id[:8]} {o.symbol:<8} {o.side:<4} {o.quantity:>8.0f} @ {o.price:.3f} {o.status}")
129
+ return
130
+ if not orders:
131
+ console.print(f"[dim]{broker_label} — 无 {status_filter} 订单[/dim]")
132
+ return
133
+ from rich.markup import escape as _esc
134
+ from ui.render.responsive import StackedRecord, render_stacked_records, structured_layout
135
+
136
+ layout = structured_layout(console)
137
+ _STATUS_STYLE = {"filled":"[green]成交[/green]","partial":"[yellow]部成[/yellow]",
138
+ "open":"[cyan]委托中[/cyan]","cancelled":"[dim]已撤[/dim]"}
139
+ _SIDE_STYLE = {"buy":"[green]买入[/green]","sell":"[red]卖出[/red]"}
140
+ if layout == "stacked":
141
+ records = []
142
+ for o in orders:
143
+ avg_price = f"{o.avg_price:.3f}" if o.avg_price else "—"
144
+ records.append(StackedRecord(
145
+ headline=(
146
+ f"{_esc(str(o.symbol))} {_esc(str(o.name or '—'))} "
147
+ f"[dim]#{_esc(str(o.order_id[-8:]))}[/dim]"
148
+ ),
149
+ lines=(
150
+ f"[dim]方向[/dim] {_SIDE_STYLE.get(o.side, _esc(str(o.side)))} · "
151
+ f"[dim]状态[/dim] {_STATUS_STYLE.get(o.status, _esc(str(o.status)))}",
152
+ f"[dim]委托[/dim] {o.quantity:,.0f} @ {o.price:.3f}",
153
+ f"[dim]成交[/dim] {o.filled_qty:,.0f} @ {avg_price}",
154
+ f"[dim]时间[/dim] {_esc(str(o.created_at[:16] if o.created_at else '—'))}",
155
+ ),
156
+ ))
157
+ render_stacked_records(
158
+ console,
159
+ title=f"{_esc(str(broker_label))} 订单 · {_esc(str(status_filter))}",
160
+ records=records,
161
+ footer=f"共 {len(orders)} 笔",
162
+ )
163
+ return
164
+ from rich.table import Table
165
+ tbl = Table(title=f"[bold]{broker_label}[/bold] 订单 [dim]({status_filter})[/dim]",
166
+ show_header=True, header_style="bold")
167
+ if layout == "full":
168
+ tbl.add_column("订单号", style="dim", max_width=12)
169
+ tbl.add_column("代码", style="bold", no_wrap=True)
170
+ tbl.add_column("名称", max_width=10)
171
+ tbl.add_column("方向", justify="center")
172
+ tbl.add_column("类型", style="dim")
173
+ tbl.add_column("委托量", justify="right")
174
+ tbl.add_column("成交量", justify="right")
175
+ tbl.add_column("委托价", justify="right", style="dim")
176
+ tbl.add_column("均价", justify="right")
177
+ tbl.add_column("状态")
178
+ tbl.add_column("时间", style="dim", max_width=16)
179
+ else:
180
+ tbl.add_column("代码", style="bold", no_wrap=True)
181
+ tbl.add_column("方向", justify="center")
182
+ tbl.add_column("委托量", justify="right")
183
+ tbl.add_column("委托价", justify="right", style="dim")
184
+ tbl.add_column("状态")
185
+ tbl.add_column("时间", style="dim", max_width=16)
186
+ for o in orders:
187
+ if layout == "full":
188
+ row = [
189
+ o.order_id[-8:], o.symbol, o.name[:10] or "—",
190
+ _SIDE_STYLE.get(o.side, o.side), o.order_type,
191
+ f"{o.quantity:,.0f}", f"{o.filled_qty:,.0f}",
192
+ f"{o.price:.3f}", f"{o.avg_price:.3f}" if o.avg_price else "—",
193
+ _STATUS_STYLE.get(o.status, o.status),
194
+ o.created_at[:16] if o.created_at else "—",
195
+ ]
196
+ else:
197
+ row = [
198
+ o.symbol, _SIDE_STYLE.get(o.side, o.side),
199
+ f"{o.quantity:,.0f}", f"{o.price:.3f}",
200
+ _STATUS_STYLE.get(o.status, o.status),
201
+ o.created_at[:16] if o.created_at else "—",
202
+ ]
203
+ tbl.add_row(*row)
204
+ console.print(tbl)
205
+
206
+
@@ -0,0 +1,29 @@
1
+ """Path helpers for generated code and strategy artifacts."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+
7
+
8
+ def resolve_user_code_path(
9
+ description: str,
10
+ save_path: str | None = None,
11
+ *,
12
+ user_generated_dir: Path,
13
+ ) -> Path:
14
+ """Resolve a code output path into the user's generated workspace."""
15
+ from artifacts import slugify_topic
16
+
17
+ if save_path:
18
+ p = Path(save_path).expanduser()
19
+ if not p.is_absolute():
20
+ p = user_generated_dir / p
21
+ if p.suffix != ".py":
22
+ p = p.with_suffix(".py")
23
+ return p
24
+
25
+ desc_slug = slugify_topic(description, fallback="generated_code")
26
+ if any(k in description.lower() for k in ("backtest", "strategy", "quant", "portfolio")):
27
+ desc_slug = f"strategy_{desc_slug}"
28
+ return user_generated_dir / f"{desc_slug}.py"
29
+
@@ -0,0 +1,16 @@
1
+ """CLI command metadata and thin command adapters."""
2
+ from .broker_cmds import BrokerCommandsMixin
3
+ from .backtest_cmds import BacktestCommandsMixin
4
+ from .workspace_cmds import WorkspaceCommandsMixin
5
+ from .model_cmds import ModelCommandsMixin
6
+ from .market_cmds import MarketCommandsMixin
7
+ from .portfolio_cmds import PortfolioCommandsMixin
8
+
9
+ __all__ = [
10
+ "BrokerCommandsMixin",
11
+ "BacktestCommandsMixin",
12
+ "WorkspaceCommandsMixin",
13
+ "ModelCommandsMixin",
14
+ "MarketCommandsMixin",
15
+ "PortfolioCommandsMixin",
16
+ ]
@@ -0,0 +1,78 @@
1
+ """Business-workflow renderers, taking the context instead of aria_cli's globals.
2
+
3
+ These three drew through aria_cli's module-level ``console`` and ``HAS_RICH``,
4
+ so business_workflow_cmds reached into a 7000-line module for three functions
5
+ totalling 56 lines. The state they need is on ``self.context`` already — the
6
+ same move print_error made in _ui.py.
7
+
8
+ Names lost their leading underscore on the way over: they are this module's
9
+ public surface now, not aria_cli privates borrowed by bare name.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from typing import Any
15
+
16
+ __all__ = ["p", "print_realty_result", "print_risk_scan"]
17
+
18
+
19
+ def p(context, msg: str, style: str = ""):
20
+ """快速打印辅助(rich 可用时带样式)"""
21
+ if context.has_rich:
22
+ tag = {"dim": "dim", "error": "red", "ok": "green"}.get(style, style)
23
+ context.console.print(f"[{tag}]{msg}[/{tag}]" if tag else msg)
24
+ else:
25
+ print(msg)
26
+
27
+
28
+ def print_realty_result(context, result, agent_name: str):
29
+ """格式化打印 realty Agent 结果(地产健康度词汇,见 agents/signal_scheme.py::REALTY_SCHEME)"""
30
+ _SIGNAL_LABELS = {
31
+ "GOOD": "[green]正常/推荐[/green]",
32
+ "WATCH": "[yellow]需观察[/yellow]",
33
+ "CONCERN": "[red]警示[/red]",
34
+ "SEVERE": "[bold red]极高风险[/bold red]",
35
+ }
36
+ if not context.has_rich:
37
+ print(f"\n[{agent_name}] Signal: {result.signal} Confidence: {result.confidence:.0%}")
38
+ print(result.analysis)
39
+ return
40
+
41
+ context.console.print()
42
+ context.console.print(f" [bold]{agent_name.upper().replace('_',' ')}[/bold]"
43
+ f" {_SIGNAL_LABELS.get(result.signal, result.signal)}"
44
+ f" [dim]置信度 {result.confidence:.0%}[/dim]")
45
+ context.console.print()
46
+ for pt in (result.key_points or []):
47
+ context.console.print(f" • {pt}")
48
+ if result.analysis:
49
+ context.console.print()
50
+ text = result.analysis[:1200] + ("…" if len(result.analysis) > 1200 else "")
51
+ context.console.print(f" [dim]{text}[/dim]")
52
+ context.console.print()
53
+
54
+
55
+ def print_risk_scan(context, data: dict):
56
+ """格式化打印风险扫描结果"""
57
+ if not context.has_rich:
58
+ print(f"Risk scan: {data.get('overall_level','?')} "
59
+ f"(score={data.get('risk_score',0)})")
60
+ for alert in data.get("alerts", []):
61
+ print(f" [{alert['level']}] {alert['desc']}")
62
+ return
63
+
64
+ level = data.get("overall_level", "未知")
65
+ score = data.get("risk_score", 0)
66
+ color = {"低": "green", "中": "yellow", "高": "red", "极高": "bold red"}.get(level, "white")
67
+ context.console.print()
68
+ context.console.print(f" 风险等级: [{color}]{level}[/{color}] "
69
+ f"风险分值: {score} "
70
+ f"预警项: {data.get('alert_count',0)}")
71
+ context.console.print()
72
+ for alert in data.get("alerts", []):
73
+ ac = {"低": "dim", "中": "yellow", "高": "red", "极高": "bold red"}.get(
74
+ alert["level"], "white")
75
+ context.console.print(f" [{ac}][{alert['level']}][/{ac}] {alert['desc']}")
76
+ if data.get("suggestion"):
77
+ context.console.print(f"\n [dim]建议: {data['suggestion']}[/dim]")
78
+ context.console.print()
@@ -0,0 +1,71 @@
1
+ """Rendering helpers for the command mixins.
2
+
3
+ Two different things used to come from aria_cli's module globals, and only one
4
+ of them was ever state:
5
+
6
+ * ``console`` / ``HAS_RICH`` are per-session state. They belong on
7
+ ``self.context`` — which 40f23c8 started and this package is finishing.
8
+ * ``rich_box`` and ``Panel`` are not state at all. They are ``rich.box`` and
9
+ ``rich.panel.Panel``, sitting behind aria_cli's guarded import purely because
10
+ that is where the try/except happened to live. Reaching into a 7000-line
11
+ module for them bought nothing, so they are resolved here instead.
12
+
13
+ ``print_error`` takes the context explicitly rather than reading a global, so a
14
+ mixin can render without knowing anything about aria_cli.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from contextlib import contextmanager
20
+ from typing import Any
21
+
22
+ __all__ = ["Panel", "Syntax", "null_ctx", "print_error", "rich_box", "has_rich"]
23
+
24
+ try: # Optional: the CLI degrades to plain print when rich is absent.
25
+ from rich import box as rich_box
26
+ from rich.panel import Panel
27
+ from rich.syntax import Syntax
28
+ except ImportError: # pragma: no cover - exercised only without rich installed
29
+ rich_box = None # type: ignore[assignment]
30
+ Panel = None # type: ignore[assignment]
31
+ Syntax = None # type: ignore[assignment]
32
+
33
+
34
+ @contextmanager
35
+ def null_ctx():
36
+ """No-op context manager, for `with x if cond else null_ctx():`.
37
+
38
+ Three lines with no dependencies, defined in aria_cli only because that is
39
+ where the first caller was. Note the *theme* these renderers use
40
+ (_SYNTAX_THEME) is deliberately not here: it is read from user config and
41
+ changes with /theme, so it is session state and belongs on the context.
42
+ """
43
+ yield
44
+
45
+
46
+ def has_rich() -> bool:
47
+ """Whether rich is importable.
48
+
49
+ For module-level helpers that have no ``self`` and so cannot read
50
+ ``self.context.has_rich``. Anything with a context should use that instead —
51
+ a session can be configured without a console even where rich is installed.
52
+ """
53
+ return rich_box is not None
54
+
55
+
56
+ def print_error(context: Any, msg: str, hint: str = "") -> None:
57
+ """Render an error through the context's console.
58
+
59
+ ``context`` is an AriaContext, or anything exposing ``console`` and
60
+ ``has_rich``; the renderer already falls back to plain print when console is
61
+ None, so a context built without one still works.
62
+ """
63
+ from aria_code.ui.render.output import print_error as _render
64
+
65
+ _render(
66
+ msg,
67
+ hint,
68
+ console=getattr(context, "console", None),
69
+ has_rich=bool(getattr(context, "has_rich", False)),
70
+ rich_box=rich_box,
71
+ )