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,386 @@
1
+ """
2
+ intent_classifier.py — Aria intent classification using Prelude model or keyword fallback.
3
+
4
+ Two-tier design:
5
+ Tier 1 (fast, accurate): aria-prelude via Ollama — the model trained specifically
6
+ for intent routing (adapters: intent-route-control,
7
+ intent-rag_gate, intent-upgrade_gate, intent-clarify).
8
+ Tier 2 (instant, offline): keyword regex — exact same logic as before, used when
9
+ Ollama / aria-prelude is not available.
10
+
11
+ Intent labels (matching CODING_SYSTEM_PROMPT routing in aria_cli.py):
12
+ "coding" → code generation, backtest scripts, chart scripts
13
+ "analysis" → stock/macro analysis, technical/fundamental research
14
+ "realtime" → live price / quote / market data queries (needs tool)
15
+ "general" → product, engineering, document, and general questions
16
+ "finance" → explicit finance chat with market-aware tool access
17
+
18
+ Usage::
19
+
20
+ from aria_code.intent_classifier import classify_intent, INTENT_CODING, INTENT_ANALYSIS
21
+
22
+ intent = await classify_intent_async("写一个 AAPL 动量策略", ollama_url)
23
+ # → "coding"
24
+
25
+ intent = classify_intent_sync("什么是夏普比率")
26
+ # → "general"
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ import asyncio
32
+ import json
33
+ import urllib.request
34
+ from typing import Optional
35
+
36
+ # ── Intent constants ──────────────────────────────────────────────────────────
37
+ INTENT_CODING = "coding"
38
+ INTENT_ANALYSIS = "analysis"
39
+ INTENT_REALTIME = "realtime"
40
+ INTENT_GENERAL = "general"
41
+ INTENT_FINANCE = "finance"
42
+
43
+ # ── Prelude model name ────────────────────────────────────────────────────────
44
+ _PRELUDE_MODEL = "aria-prelude"
45
+ _PRELUDE_TIMEOUT = 3.0 # seconds — must be fast; fallback on timeout
46
+
47
+ # ── Prelude system prompt (mirrors the adapter training format) ───────────────
48
+ _PRELUDE_SYSTEM = (
49
+ "You are an intent classifier for a general product and software-engineering AI assistant.\n"
50
+ "Classify the user message into EXACTLY ONE of these labels:\n"
51
+ " coding — code generation, debugging, repository review, product implementation\n"
52
+ " analysis — stock analysis, market research, technical/fundamental analysis\n"
53
+ " realtime — live price, current quote, today's market data\n"
54
+ " general — product review, architecture, UX, documentation, or general question\n"
55
+ " finance — explicit finance, portfolio, risk, or investment discussion\n"
56
+ "Reply with ONLY the label word, nothing else."
57
+ )
58
+
59
+
60
+ # ── Keyword fallback (tier-2, instant) ───────────────────────────────────────
61
+
62
+ _CODING_KW = (
63
+ "write", "generate", "create", "script", "code", "plot", "backtest",
64
+ "策略", "代码", "回测", "编写", "生成", "k线", "k-line", "kline",
65
+ "python", "dashboard", "写一个", "生成代码", "写代码", "编写代码",
66
+ "analyze and save", "analysis script",
67
+ "review code", "code review", "review project", "audit project", "audit code",
68
+ "repository", "repo", "codebase", "pull request", "debug", "refactor", "fix bug",
69
+ "implement", "implementation", "react", "next.js", "nextjs", "vue", "swiftui",
70
+ "flutter", "fastapi", "django", "express", "typescript", "frontend", "backend",
71
+ "审核代码", "代码审查", "审核项目", "项目审核", "审查项目", "代码库", "仓库",
72
+ "调试", "修复 bug", "重构", "实现", "实现功能", "开发产品", "编写应用",
73
+ "前端", "后端", "登录页面", "单元测试", "集成测试",
74
+ )
75
+
76
+ _VISUAL_ARTIFACT_KW = (
77
+ "图表", "走势图", "k线图", "k线", "k-line", "kline", "candlestick",
78
+ "chart", "plot", "dashboard", "看板", "晨报", "日报", "周报", "月报",
79
+ "report", "热力图", "heatmap",
80
+ )
81
+
82
+ _VISUAL_MARKET_CONTEXT_KW = (
83
+ "股票", "股价", "行情", "市场", "美股", "港股", "a股", "指数",
84
+ "持仓", "portfolio", "回测", "财报", "earnings", "基金", "etf",
85
+ "资产", "组合", "市场数据", "market data",
86
+ )
87
+ _ANALYSIS_KW = (
88
+ "analyze", "analysis", "分析", "研究", "评估", "研判",
89
+ "技术面", "基本面", "走势", "趋势", "行情",
90
+ "stock analysis", "technical analysis", "fundamental",
91
+ "valuation", "estimate", "outlook", "投资建议", "买入", "卖出",
92
+ )
93
+
94
+ # Topics that must NOT be classified as stock technical "analysis" even if they
95
+ # contain analysis keywords. They get routed to "finance" (general chat) instead,
96
+ # because the stock-analysis prompt requires injected market data that doesn't
97
+ # exist for real estate or pure macroeconomic questions.
98
+ _NON_STOCK_ANALYSIS_TOPICS = (
99
+ # Real-estate
100
+ "房价", "楼市", "房产", "房地产", "租金", "二手房", "折旧价", "商铺",
101
+ # Pure macro — "宏观角度分析" should be finance chat, not stock template
102
+ "宏观", "宏观经济", "宏观政策", "宏观角度",
103
+ "货币政策", "财政政策", "gdp", "通胀", "通货膨胀", "cpi", "ppi",
104
+ # Non-chartable commodities / currencies
105
+ "黄金走势", "原油走势", "汇率走势", "美元指数",
106
+ )
107
+
108
+ # Pure macro/conceptual topics — no live market data needed, route to GENERAL
109
+ # (no tools invoked). More specific than _NON_STOCK_ANALYSIS_TOPICS: real-estate
110
+ # still goes to FINANCE because the user might want live data, but "宏观角度" is
111
+ # clearly a discussion question, not a quote lookup.
112
+ _MACRO_GENERAL_TOPICS = (
113
+ "宏观", "宏观经济", "宏观政策", "宏观角度", "宏观分析",
114
+ "货币政策", "财政政策", "gdp", "通胀", "通货膨胀", "cpi", "ppi",
115
+ "值得投资吗", "应该投资吗", "是否值得", "投资逻辑",
116
+ "长期展望", "未来前景", "宏观前景",
117
+ # Interest rate / bond macro concepts
118
+ "利率", "加息", "降息", "美联储政策", "央行政策",
119
+ "债券市场", "利差", "收益率曲线", "国债收益",
120
+ # Structural/sector macro
121
+ "产业政策", "行业监管", "政策影响", "监管政策",
122
+ )
123
+ _REALTIME_KW = (
124
+ "今天", "today", "现在", "now", "current", "latest", "最新",
125
+ "市值", "price", "股价", "quote", "行情", "涨跌", "涨幅",
126
+ "market cap", "how much", "what is the price",
127
+ "是多少", "多少钱", "多少点", "多少美元", "多少港元",
128
+ )
129
+
130
+ # Question words that, when combined with finance concept terms, mean "explain X"
131
+ # rather than "look up X" — should route to general, not finance.
132
+ _QUESTION_PREFIX = (
133
+ "什么是", "什么叫", "how does", "what is", "what are",
134
+ "explain", "define", "解释", "定义", "概念", "原理", "介绍",
135
+ "是什么", "为什么", "区别", "difference", "如何理解", "怎么理解",
136
+ )
137
+
138
+ # Finance-metric terms that combined with realtime words → live lookup
139
+ _METRIC_KW = (
140
+ "pe", "pb", "ps", "市盈率", "市净率", "市销率",
141
+ "eps", "净利润", "营收", "市值", "股息", "分红",
142
+ "ebitda", "利润率", "毛利率", "roe", "roa",
143
+ )
144
+
145
+ # File path extensions — presence means it's a document/code task, not stock analysis
146
+ _FILE_EXT_RE = r'\S+\.(?:docx|pdf|xlsx|pptx|txt|csv|json|py|md|log)\b'
147
+
148
+ # Specific financial entity signals — must be present for "分析" to route as stock analysis.
149
+ # Keep to SPECIFIC company names and ticker symbols only.
150
+ # Generic market categories ("美股", "债券", "股市") must NOT be here — they appear in
151
+ # macro conceptual questions and would incorrectly block the → general route.
152
+ _FIN_ENTITY_KW = (
153
+ # Company names (CN)
154
+ "苹果", "谷歌", "英伟达", "微软", "特斯拉", "亚马逊", "腾讯",
155
+ "阿里", "百度", "比亚迪", "茅台", "招商银行", "中国平安", "恒生指数",
156
+ "华为", "小米", "美团", "京东", "字节", "滴滴",
157
+ # Company names (EN)
158
+ "apple", "google", "nvidia", "microsoft", "tesla", "amazon",
159
+ "meta", "netflix", "palantir", "snowflake",
160
+ # Common tickers (lowercase)
161
+ "aapl", "nvda", "msft", "tsla", "amzn", "googl", "meta", "baba",
162
+ "spy", "qqq", "iwm", "dia", "gld", "uso",
163
+ # Specific crypto coins (named assets, not generic "加密货币")
164
+ "比特币", "以太坊", "bitcoin", "ethereum", "btc", "eth", "sol", "bnb",
165
+ # Named indices (specific, not generic "指数")
166
+ "纳斯达克", "标普500", "道琼斯", "沪深300", "中证500",
167
+ )
168
+
169
+ # Broader market terms (generic) — used only to check for stock-analysis context,
170
+ # NOT used to block macro-general classification (avoid false negatives on conceptual Qs)
171
+ _MARKET_GENERAL_KW = (
172
+ "股票", "股市", "股价", "美股", "港股", "a股",
173
+ "etf", "基金", "指数", "期货", "期权", "加密", "数字货币",
174
+ )
175
+ _GENERAL_KW = (
176
+ "什么是", "what is", "what are", "how does", "explain", "define",
177
+ "解释", "定义", "概念", "原理", "介绍", "怎么", "如何理解",
178
+ "是什么", "为什么", "区别", "difference between",
179
+ "tell me about", "describe", "how to", "举例", "example",
180
+ )
181
+ _FINANCE_CONCEPT_KW = (
182
+ "dcf", "pe", "pb", "ps", "ev", "ebitda", "wacc", "capm",
183
+ "beta", "alpha", "sharpe", "sortino", "var", "cvar", "drawdown",
184
+ "black-scholes", "期权", "期货", "衍生品", "套利",
185
+ "量化", "quant", "回测", "因子", "ic值", "ir值",
186
+ "market cap", "市盈率", "市净率", "净利润", "估值", "valuation",
187
+ )
188
+
189
+
190
+ def is_visual_market_artifact_request(message: str) -> bool:
191
+ """Return True for finance-adjacent visual artifact requests.
192
+
193
+ These should prefer chart/dashboard/report workflows instead of generic
194
+ market-data prefetch.
195
+
196
+ Delegates to apps/cli/intent_signals, which matches CJK terms against a
197
+ whitespace-stripped message so "K 线图" and "K线图" behave identically.
198
+ The legacy body below is the fallback if that module is unavailable.
199
+ """
200
+ try:
201
+ from aria_code.apps.cli.intent_signals import is_visual_artifact_request
202
+ return is_visual_artifact_request(message)
203
+ except Exception:
204
+ pass
205
+ low = message.lower().strip()
206
+ if low.startswith(("/chart", "/dashboard", "/report")):
207
+ return True
208
+ if not any(k in low for k in _VISUAL_ARTIFACT_KW):
209
+ return False
210
+ if any(k in low for k in _VISUAL_MARKET_CONTEXT_KW):
211
+ return True
212
+ if any(k in low for k in _MARKET_GENERAL_KW):
213
+ return True
214
+ if any(e in low for e in _FIN_ENTITY_KW):
215
+ return True
216
+ return any(k in low for k in ("公司", "集团", "股份", "科技", "银行", "证券", "能源", "汽车"))
217
+
218
+
219
+ def classify_intent_sync(message: str) -> str:
220
+ """
221
+ Tier-2 classification (synchronous, always available).
222
+ Returns one of the INTENT_* constants.
223
+
224
+ Delegates to apps/cli/intent_signals, which extracts signals independently
225
+ and applies one explicit precedence table. The keyword cascade kept below
226
+ is the fallback if that module cannot be imported; it is the historical
227
+ implementation and is known to misclassify the cases listed in
228
+ tests/test_intent_signals.py.
229
+ """
230
+ try:
231
+ from aria_code.apps.cli.intent_signals import classify as _classify
232
+ return _classify(message)
233
+ except Exception:
234
+ pass
235
+
236
+ import re as _re
237
+ low = message.lower().strip()
238
+
239
+ if is_visual_market_artifact_request(message):
240
+ return INTENT_CODING
241
+
242
+ # Bug ⑥ — file path present → document/code task, never stock analysis template
243
+ if _re.search(_FILE_EXT_RE, low):
244
+ if any(k in low for k in _CODING_KW):
245
+ return INTENT_CODING # "帮我写一个解析这个 csv 的脚本"
246
+ return INTENT_GENERAL # document/product analysis without market tools
247
+
248
+ has_coding = any(k in low for k in _CODING_KW)
249
+ has_realtime = any(k in low for k in _REALTIME_KW)
250
+ has_question = any(q in low for q in _QUESTION_PREFIX)
251
+
252
+ # Coding intent — but skip if phrased as a conceptual question ("X的核心是什么")
253
+ if has_coding and not has_question:
254
+ return INTENT_CODING
255
+
256
+ # Bug ⑤ — "metric是多少/how much" → realtime lookup, not finance concept chat
257
+ if any(m in low for m in _METRIC_KW) and any(k in low for k in _REALTIME_KW):
258
+ return INTENT_REALTIME
259
+
260
+ # Live-data terms must win over broad analysis words. "分析苹果今天的市场"
261
+ # contains both "分析" and "今天"; routing it as generic analysis lets the
262
+ # model answer from memory instead of using market data.
263
+ if has_realtime:
264
+ return INTENT_REALTIME
265
+
266
+ # Bug ② — "什么是X" + finance concept → general (explain, not look up)
267
+ if any(q in low for q in _QUESTION_PREFIX) and any(k in low for k in _FINANCE_CONCEPT_KW):
268
+ return INTENT_GENERAL
269
+
270
+ # Stock/market analysis — but only if a financial entity is present.
271
+ if any(k in low for k in _ANALYSIS_KW):
272
+ # Bug ③ — macro topics check (also works independently below)
273
+ if any(t in low for t in _MACRO_GENERAL_TOPICS):
274
+ return INTENT_GENERAL
275
+ if any(t in low for t in _NON_STOCK_ANALYSIS_TOPICS):
276
+ return INTENT_GENERAL
277
+ # Bug ① — "分析" without a financial entity = general task (project, doc, etc.)
278
+ if not any(e in low for e in _FIN_ENTITY_KW):
279
+ # Check for uppercase ticker pattern (e.g. AAPL, BTC)
280
+ if not _re.search(r'\b[A-Z]{2,5}\b', message):
281
+ return INTENT_GENERAL
282
+ # Bug ④ — recommendation phrasing ("应该买入吗") → finance chat, not chart analysis
283
+ _rec_phrases = ("应该", "是否值得", "要不要", "该不该", "值不值", "建议买", "建议卖")
284
+ if any(p in low for p in _rec_phrases):
285
+ return INTENT_FINANCE
286
+ return INTENT_ANALYSIS
287
+
288
+ # Bug ③ (standalone) — macro conceptual topics, unless a SPECIFIC entity is named.
289
+ # Generic market terms like "股市"/"美股" don't block this — "宏观经济对美股的影响"
290
+ # is still a macro discussion, not a specific stock query.
291
+ if any(t in low for t in _MACRO_GENERAL_TOPICS):
292
+ _has_specific = (
293
+ any(e in low for e in _FIN_ENTITY_KW)
294
+ or _re.search(r'\b[A-Z]{2,5}\b', message)
295
+ )
296
+ if not _has_specific:
297
+ return INTENT_GENERAL
298
+
299
+ # Finance concept terms → keep full finance context, not general
300
+ if any(k in low for k in _FINANCE_CONCEPT_KW):
301
+ return INTENT_FINANCE
302
+
303
+ if any(k in low for k in _GENERAL_KW):
304
+ return INTENT_GENERAL
305
+
306
+ return INTENT_GENERAL
307
+
308
+
309
+ def _prelude_available(ollama_url: str) -> bool:
310
+ """Quick sync check: is aria-prelude loaded in Ollama?"""
311
+ try:
312
+ with urllib.request.urlopen(
313
+ ollama_url.rstrip("/") + "/api/tags", timeout=1
314
+ ) as r:
315
+ data = json.loads(r.read())
316
+ models = [m["name"] for m in data.get("models", [])]
317
+ return any(m.startswith(_PRELUDE_MODEL) for m in models)
318
+ except Exception:
319
+ return False
320
+
321
+
322
+ async def classify_intent_async(
323
+ message: str,
324
+ ollama_url: str = "http://localhost:11434",
325
+ *,
326
+ timeout: float = _PRELUDE_TIMEOUT,
327
+ ) -> str:
328
+ """
329
+ Tier-1 classification using aria-prelude via Ollama.
330
+ Falls back to tier-2 keyword classification on any error or timeout.
331
+ """
332
+ try:
333
+ import aiohttp
334
+ except ImportError:
335
+ return classify_intent_sync(message)
336
+
337
+ if is_visual_market_artifact_request(message):
338
+ return INTENT_CODING
339
+
340
+ if not _prelude_available(ollama_url):
341
+ return classify_intent_sync(message)
342
+
343
+ payload = {
344
+ "model": _PRELUDE_MODEL,
345
+ "messages": [
346
+ {"role": "system", "content": _PRELUDE_SYSTEM},
347
+ {"role": "user", "content": message},
348
+ ],
349
+ "stream": False,
350
+ "options": {"num_predict": 8, "temperature": 0.0},
351
+ }
352
+ url = ollama_url.rstrip("/") + "/api/chat"
353
+ try:
354
+ async with aiohttp.ClientSession() as sess:
355
+ async with sess.post(
356
+ url, json=payload,
357
+ timeout=aiohttp.ClientTimeout(total=timeout),
358
+ ) as resp:
359
+ if resp.status != 200:
360
+ return classify_intent_sync(message)
361
+ data = await resp.json()
362
+ raw = data.get("message", {}).get("content", "").strip().lower()
363
+ # Accept only known labels
364
+ for label in (INTENT_CODING, INTENT_ANALYSIS, INTENT_REALTIME,
365
+ INTENT_GENERAL, INTENT_FINANCE):
366
+ if label in raw:
367
+ if is_visual_market_artifact_request(message):
368
+ return INTENT_CODING
369
+ # Post-override: even if the prelude model says "analysis" or "finance",
370
+ # non-stock topics must not get the stock-analysis template.
371
+ if label == INTENT_ANALYSIS:
372
+ low_msg = message.lower()
373
+ if any(t in low_msg for t in _MACRO_GENERAL_TOPICS):
374
+ return INTENT_GENERAL # macro → educational, no tools
375
+ if any(t in low_msg for t in _NON_STOCK_ANALYSIS_TOPICS):
376
+ return INTENT_FINANCE # real-estate etc. → finance chat
377
+ if label == INTENT_FINANCE:
378
+ # Even a "finance" label from the model shouldn't invoke live tools
379
+ # for pure macro conceptual questions.
380
+ low_msg = message.lower()
381
+ if any(t in low_msg for t in _MACRO_GENERAL_TOPICS):
382
+ return INTENT_GENERAL
383
+ return label
384
+ except Exception:
385
+ pass
386
+ return classify_intent_sync(message)
@@ -0,0 +1,4 @@
1
+ """Compatibility import for :mod:`clients.kling_video_client`."""
2
+ from importlib import import_module as _import_module
3
+ import sys as _sys
4
+ _sys.modules[__name__] = _import_module("clients.kling_video_client")
aria_code/licensing.py ADDED
@@ -0,0 +1,151 @@
1
+ """licensing.py — feature entitlement gate for the open-core model.
2
+
3
+ FREE BY DEFAULT. The BSL-licensed CLI shell works fully with no license. Premium
4
+ features (the compiled quant engine, hosted services) call ``has_feature`` /
5
+ ``require_feature`` to gate access.
6
+
7
+ A license key here is an *entitlement* token, not the mechanism that protects
8
+ IP — IP protection comes from shipping the engine COMPILED (see
9
+ tools/build_quant_engine.py). This module just unlocks features and supports a
10
+ paid tier, with optional tamper-evident HMAC signatures.
11
+
12
+ License sources (first match wins):
13
+ 1. ARIA_LICENSE_KEY env var — raw key string (treated as the "pro" tier)
14
+ 2. ~/.arthera/license.json — {"key","tier","features":[...],"exp":"YYYY-MM-DD","sig"?}
15
+
16
+ If ARIA_LICENSE_PUBKEY (an HMAC secret distributed with the build) is set, the
17
+ license ``sig`` MUST verify or the license is rejected. Without it, licenses are
18
+ accepted unsigned (development / self-host).
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import hashlib
24
+ import hmac
25
+ import json
26
+ import os
27
+ from dataclasses import dataclass, field
28
+ from datetime import date, datetime
29
+ from pathlib import Path
30
+ from typing import List, Optional
31
+ from aria_code.packages.aria_core.paths import aria_home
32
+
33
+ # Features that are ALWAYS free (the BSL shell). Premium features are anything
34
+ # not listed here; they require a license that grants them.
35
+ FREE_FEATURES: frozenset[str] = frozenset({
36
+ "chat", "market_data", "market_history", "backtest", "portfolio_backtest",
37
+ "broker_read", "broker_trade", "paper_trade", "file_analysis", "web_search",
38
+ "alerts", "reports", "strategy_vault",
39
+ })
40
+
41
+ _LICENSE_PATHS = [
42
+ aria_home() / "license.json",
43
+ Path.home() / ".aria" / "license.json",
44
+ ]
45
+
46
+
47
+ @dataclass
48
+ class License:
49
+ key: str = ""
50
+ tier: str = "free"
51
+ features: List[str] = field(default_factory=list)
52
+ exp: str = "" # "YYYY-MM-DD"; empty = no expiry
53
+ valid: bool = True
54
+ reason: str = ""
55
+
56
+ @property
57
+ def expired(self) -> bool:
58
+ if not self.exp:
59
+ return False
60
+ try:
61
+ return datetime.strptime(self.exp, "%Y-%m-%d").date() < date.today()
62
+ except ValueError:
63
+ return False
64
+
65
+
66
+ def _signing_secret() -> str:
67
+ return str(os.getenv("ARIA_LICENSE_PUBKEY", "") or "").strip()
68
+
69
+
70
+ def _verify_sig(payload: dict) -> bool:
71
+ """Verify the license HMAC signature when a verification key is configured."""
72
+ secret = _signing_secret()
73
+ if not secret:
74
+ return True # unsigned mode (dev / self-host)
75
+ sig = str(payload.get("sig") or "")
76
+ body = {k: payload[k] for k in sorted(payload) if k != "sig"}
77
+ expected = hmac.new(secret.encode(), json.dumps(body, sort_keys=True).encode(),
78
+ hashlib.sha256).hexdigest()
79
+ return bool(sig) and hmac.compare_digest(sig, expected)
80
+
81
+
82
+ def _load_license() -> License:
83
+ env_key = str(os.getenv("ARIA_LICENSE_KEY", "") or "").strip()
84
+ if env_key:
85
+ return License(key=env_key, tier="pro", features=["*"], valid=True)
86
+ for p in _LICENSE_PATHS:
87
+ if not p.exists():
88
+ continue
89
+ try:
90
+ data = json.loads(p.read_text(encoding="utf-8"))
91
+ except Exception as e:
92
+ return License(valid=False, reason=f"license.json 解析失败: {e}")
93
+ if not _verify_sig(data):
94
+ return License(valid=False, reason="license 签名校验失败")
95
+ lic = License(
96
+ key=str(data.get("key", "")),
97
+ tier=str(data.get("tier", "pro")),
98
+ features=list(data.get("features", []) or []),
99
+ exp=str(data.get("exp", "") or ""),
100
+ )
101
+ if lic.expired:
102
+ lic.valid = False
103
+ lic.reason = f"license 已于 {lic.exp} 过期"
104
+ return lic
105
+ return License(tier="free")
106
+
107
+
108
+ # Cached singleton; refresh() re-reads (e.g. after the user installs a key).
109
+ _CACHE: Optional[License] = None
110
+
111
+
112
+ def current_license(refresh: bool = False) -> License:
113
+ global _CACHE
114
+ if _CACHE is None or refresh:
115
+ _CACHE = _load_license()
116
+ return _CACHE
117
+
118
+
119
+ def has_feature(name: str) -> bool:
120
+ """True if a feature is available (free, or granted by a valid license)."""
121
+ if name in FREE_FEATURES:
122
+ return True
123
+ lic = current_license()
124
+ if not lic.valid:
125
+ return False
126
+ return "*" in lic.features or name in lic.features
127
+
128
+
129
+ def require_feature(name: str) -> tuple[bool, str]:
130
+ """Gate a premium feature. Returns (allowed, user_message)."""
131
+ if has_feature(name):
132
+ return True, ""
133
+ lic = current_license()
134
+ if not lic.valid and lic.reason:
135
+ return False, f"功能 '{name}' 需要有效授权:{lic.reason}"
136
+ return False, (f"功能 '{name}' 属于专业版。请配置 ARIA_LICENSE_KEY 或 "
137
+ f"~/.arthera/license.json 解锁(当前: {lic.tier} 版)。")
138
+
139
+
140
+ def license_status() -> dict:
141
+ """Snapshot for a /license command."""
142
+ lic = current_license()
143
+ return {
144
+ "tier": lic.tier,
145
+ "valid": lic.valid,
146
+ "expired": lic.expired,
147
+ "exp": lic.exp,
148
+ "reason": lic.reason,
149
+ "features": lic.features,
150
+ "signed_mode": bool(_signing_secret()),
151
+ }
@@ -0,0 +1,4 @@
1
+ """Compatibility import for :mod:`tools.local_finance_tools`."""
2
+ from importlib import import_module as _import_module
3
+ import sys as _sys
4
+ _sys.modules[__name__] = _import_module("tools.local_finance_tools")
@@ -0,0 +1,4 @@
1
+ """Compatibility import for :mod:`providers.local_image_provider`."""
2
+ from importlib import import_module as _import_module
3
+ import sys as _sys
4
+ _sys.modules[__name__] = _import_module("providers.local_image_provider")
@@ -0,0 +1,4 @@
1
+ """Compatibility import for :mod:`providers.local_llm_provider`."""
2
+ from importlib import import_module as _import_module
3
+ import sys as _sys
4
+ _sys.modules[__name__] = _import_module("providers.local_llm_provider")
@@ -0,0 +1,4 @@
1
+ """Compatibility import for :mod:`tools.macro_tools`."""
2
+ from importlib import import_module as _import_module
3
+ import sys as _sys
4
+ _sys.modules[__name__] = _import_module("tools.macro_tools")