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,544 @@
1
+ """Market command parsing and top-level routing helpers.
2
+
3
+ Keep this module independent from the terminal UI and market data providers so
4
+ CLI, Feishu, and future gateway adapters can share the same command semantics.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import re
10
+ from dataclasses import dataclass
11
+ from typing import Mapping
12
+
13
+ from aria_code.apps.cli.utils.market_detect import (
14
+ _extract_market_symbol,
15
+ _extract_market_symbols,
16
+ _is_blocked_market_symbol_candidate,
17
+ )
18
+
19
+
20
+ TOP_LEVEL_ROUTES: Mapping[str, str] = {
21
+ # quant workflow keywords -> slash command name
22
+ "analyze": "/analyze",
23
+ "analysis": "/analyze",
24
+ "分析": "/analyze",
25
+ "backtest": "/backtest",
26
+ "回测": "/backtest",
27
+ "risk": "/risk",
28
+ "风险": "/risk",
29
+ "report": "/report",
30
+ "报告": "/report",
31
+ "market": "/market",
32
+ "行情": "/market",
33
+ "screen": "/screen",
34
+ "筛选": "/screen",
35
+ "strategy": "/strategy",
36
+ "策略": "/strategy",
37
+ "signal": "/signal",
38
+ "信号": "/signal",
39
+ "chart": "/chart",
40
+ "图表": "/chart",
41
+ "news": "/news",
42
+ "新闻": "/news",
43
+ "predict": "/predict",
44
+ "预测": "/predict",
45
+ }
46
+
47
+ _VISUAL_ROUTE_PATTERNS: tuple[tuple[tuple[str, ...], str], ...] = (
48
+ (("晨报", "日报", "周报", "月报", "看板", "dashboard", "heatmap"), "/dashboard"),
49
+ (("报告", "report", "研报"), "/report"),
50
+ (("图表", "走势图", "k线图", "k线", "k-line", "kline", "candlestick", "chart", "plot"), "/chart"),
51
+ )
52
+
53
+ _DASHBOARD_MODE_HINTS: tuple[tuple[tuple[str, ...], str], ...] = (
54
+ (("持仓", "portfolio", "仓位", "组合", "资产"), "portfolio"),
55
+ (("市场", "行情", "quote", "prices", "watchlist", "热力图", "heatmap"), "market"),
56
+ (("晨报", "日报", "brief"), "brief"),
57
+ )
58
+
59
+ _CHART_PERIOD_HINTS: tuple[tuple[tuple[str, ...], str], ...] = (
60
+ (("近三个月", "三个月", "3m", "3个月", "3 months", "three months", "3-month", "quarter"), "3m"),
61
+ (("近六个月", "六个月", "6m", "6个月", "6 months", "six months", "6-month", "half a year"), "6m"),
62
+ (("年初至今", "ytd", "year to date"), "ytd"),
63
+ (("两年", "2y", "2 years", "two years"), "2y"),
64
+ (("三年", "3y", "3 years", "three years"), "3y"),
65
+ (("五年", "5y", "5 years", "five years"), "5y"),
66
+ (("近一年", "一年", "1y", "1年", "1 year", "one year", "a year", "12 months"), "1y"),
67
+ )
68
+
69
+ _REPORT_TYPE_HINTS: tuple[tuple[tuple[str, ...], str], ...] = (
70
+ (("深度", "详细", "deep"), "deep"),
71
+ (("简评", "简报", "brief"), "brief"),
72
+ (("研究报告", "投研报告", "研究", "report"), "standard"),
73
+ )
74
+
75
+ _TRADINGVIEW_HINTS = ("tradingview", "trading view", "pine")
76
+ _TRADINGVIEW_ZH_HINTS = ("用tradingview", "打开tradingview", "tradingview打开", "用 tv", "tv打开", "pine脚本")
77
+ _TRADINGVIEW_BULLISH_HINTS = ("看涨", "偏多", "多头", "上涨", "bullish", "bull", "upside")
78
+ _TRADINGVIEW_BEARISH_HINTS = ("看跌", "偏空", "空头", "下跌", "bearish", "bear", "downside")
79
+ _TRADINGVIEW_ANALYSIS_HINTS = (
80
+ "分析", "怎么看", "怎么判断", "哪些数据", "根据其的数据", "根据数据",
81
+ "指标", "信号", "analyze", "analysis", "data", "indicator", "signal",
82
+ )
83
+
84
+ _ROUTE_SYMBOL_BLOCKLIST = {
85
+ "K", "LINE", "CHART", "PLOT",
86
+ # Product and engineering acronyms, typed in capitals and almost never a
87
+ # ticker in a message: "news app UI design ideas" ran `/news UI`.
88
+ "UI", "UX", "API", "CLI", "SDK", "URL", "PDF", "CSS", "HTML", "SQL", "JSON", "CSV", "IDE",
89
+ "OS", "PR", "QA", "CI", "CD", "MVP", "LLM", "GPU", "CPU", "RAM", "SSD", "DB",
90
+ }
91
+ _CHART_CONTEXT_TOKEN_BLOCKLIST = {
92
+ "ABOVE", "BELOW", "INC", "TTM", "RATIO", "SIGNAL", "SUPPORT", "RESIST",
93
+ "RESISTANCE", "LEVEL", "LEVELS", "HIGH", "LOW", "OPEN", "CLOSE", "AVG",
94
+ "AVERAGE", "RETURN", "RETURNS", "TREND", "MOMENTUM",
95
+ }
96
+
97
+ _NEWS_DISCUSSION_HINTS = (
98
+ "新闻面", "技术面", "还有用吗", "是否有用", "你觉得", "怎么看",
99
+ "区别", "关系", "怎么结合", "如何结合", "为什么",
100
+ )
101
+ _NEWS_LOOKUP_HINTS = (
102
+ "最新新闻", "最近新闻", "相关新闻", "今日新闻", "新闻有哪些",
103
+ "查新闻", "搜新闻", "搜索新闻", "找新闻", "获取新闻",
104
+ "latest news", "recent news", "find news", "search news",
105
+ )
106
+
107
+
108
+ def _is_news_discussion(text: str) -> bool:
109
+ """True when 'news' is a discussion topic rather than a lookup request."""
110
+ low = (text or "").lower()
111
+ if any(hint in low for hint in _NEWS_LOOKUP_HINTS):
112
+ return False
113
+ return "新闻" in low and any(hint in low for hint in _NEWS_DISCUSSION_HINTS)
114
+
115
+
116
+ def _news_topic(text: str, symbols: list[str]) -> str:
117
+ low = text.lower()
118
+ if "spacex" in low:
119
+ return "SpaceX"
120
+ if "lvmh" in low or "路易威登" in text:
121
+ return "LVMH"
122
+ return symbols[0] if symbols else text
123
+
124
+
125
+ def _known_tickers() -> frozenset[str]:
126
+ """Tickers Aria knows by name — the company table's values."""
127
+ global _KNOWN_TICKERS
128
+ if _KNOWN_TICKERS is None:
129
+ try:
130
+ from aria_code.apps.cli.utils.market_detect import _COMPANY_TO_TICKER
131
+
132
+ _KNOWN_TICKERS = frozenset(str(v).upper() for v in _COMPANY_TO_TICKER.values() if v)
133
+ except Exception:
134
+ _KNOWN_TICKERS = frozenset()
135
+ return _KNOWN_TICKERS
136
+
137
+
138
+ _KNOWN_TICKERS: frozenset[str] | None = None
139
+
140
+
141
+ def _route_symbols(text: str, *, limit: int = 6) -> list[str]:
142
+ """Resolve ticker/company mentions for natural-language command routing.
143
+
144
+ The second pass reads the message upper-cased so "aapl" is found — and it
145
+ used to accept anything that came out of it, so every English word became
146
+ a ticker: "what's the latest version of python?" ran `/news WHAT`, "write a
147
+ report generator script" ran `/report WRITE`. That pass now adds only
148
+ tickers Aria knows; the message as typed is read as before.
149
+ """
150
+ seen: set[str] = set()
151
+ out: list[str] = []
152
+ for source in (text, text.upper()):
153
+ for symbol in _extract_market_symbols(source, limit=limit):
154
+ normalized = str(symbol or "").upper()
155
+ if (
156
+ not normalized
157
+ or normalized in _ROUTE_SYMBOL_BLOCKLIST
158
+ or _is_blocked_market_symbol_candidate(normalized)
159
+ or (source is not text and normalized not in _known_tickers()
160
+ and normalized not in text)
161
+ ):
162
+ continue
163
+ if len(normalized) == 1 and "." not in normalized:
164
+ continue
165
+ if normalized not in seen:
166
+ seen.add(normalized)
167
+ out.append(normalized)
168
+ if len(out) >= limit:
169
+ return out
170
+ single = _extract_market_symbol(text)
171
+ if not single:
172
+ upper = _extract_market_symbol(text.upper())
173
+ single = upper if str(upper or "").upper() in _known_tickers() else ""
174
+ normalized = str(single or "").upper()
175
+ if (
176
+ normalized
177
+ and normalized not in seen
178
+ and normalized not in _ROUTE_SYMBOL_BLOCKLIST
179
+ and not _is_blocked_market_symbol_candidate(normalized)
180
+ ):
181
+ out.append(normalized)
182
+ return out
183
+
184
+
185
+ @dataclass(frozen=True)
186
+ class RoutedCommand:
187
+ command: str
188
+ args: str = ""
189
+
190
+ @property
191
+ def text(self) -> str:
192
+ return f"{self.command} {self.args}".strip()
193
+
194
+
195
+ @dataclass(frozen=True)
196
+ class TechnicalArgs:
197
+ symbol: str
198
+ days: int = 120
199
+
200
+
201
+ @dataclass(frozen=True)
202
+ class AnalysisArgs:
203
+ symbol: str
204
+ focus: str = ""
205
+ lang: str = ""
206
+
207
+
208
+ _ANALYSIS_FOCUS_HINTS: tuple[tuple[tuple[str, ...], str], ...] = (
209
+ (("成交量", "交易量", "量价", "放量", "缩量", "volume", "volumes"), "volume"),
210
+ (("市值", "market cap", "marketcap", "capitalization"), "market_cap"),
211
+ (("基本面", "fundamental", "fundamentals", "valuation", "估值"), "fundamentals"),
212
+ (("技术面", "technical", "rsi", "macd", "支撑", "阻力"), "technical"),
213
+ )
214
+
215
+
216
+ def _analysis_focus_from_text(text: str) -> str:
217
+ low = text.lower()
218
+ for keywords, focus in _ANALYSIS_FOCUS_HINTS:
219
+ if any(k in low for k in keywords):
220
+ return focus
221
+ return ""
222
+
223
+
224
+ def parse_analysis_args(args: str, *, default_symbol: str = "AAPL") -> AnalysisArgs:
225
+ """Resolve natural-language /analyze args to one clean symbol plus focus."""
226
+ raw = (args or "").strip()
227
+ focus = ""
228
+ lang = ""
229
+ parts = raw.split()
230
+ cleaned_parts: list[str] = []
231
+ skip_next = False
232
+ for idx, part in enumerate(parts):
233
+ if skip_next:
234
+ skip_next = False
235
+ continue
236
+ token = part.strip()
237
+ low = token.lower()
238
+ if low.startswith("--focus="):
239
+ focus = low.split("=", 1)[1].strip()
240
+ continue
241
+ if low == "--focus" and idx + 1 < len(parts):
242
+ focus = parts[idx + 1].strip().lower()
243
+ skip_next = True
244
+ continue
245
+ if low.startswith("--lang="):
246
+ lang = low.split("=", 1)[1].strip().lower()
247
+ continue
248
+ if low == "--lang" and idx + 1 < len(parts):
249
+ lang = parts[idx + 1].strip().lower()
250
+ skip_next = True
251
+ continue
252
+ cleaned_parts.append(token)
253
+
254
+ cleaned = " ".join(cleaned_parts).strip()
255
+ if not focus:
256
+ focus = _analysis_focus_from_text(raw)
257
+
258
+ symbols = _route_symbols(cleaned or raw, limit=1)
259
+ symbol = symbols[0] if symbols else ""
260
+ if not symbol:
261
+ symbol = _extract_market_symbol(cleaned) or _extract_market_symbol((cleaned or raw).upper())
262
+ if not symbol:
263
+ for token in cleaned_parts:
264
+ candidate = token.strip(",,.。::;;()()[]【】").upper()
265
+ if candidate and not candidate.startswith("-") and not _is_blocked_market_symbol_candidate(candidate):
266
+ symbol = candidate
267
+ break
268
+ if lang not in ("zh", "en"):
269
+ zh_chars = sum(1 for c in raw if "\u4e00" <= c <= "\u9fff")
270
+ lang = "zh" if zh_chars else ""
271
+ return AnalysisArgs(symbol=(symbol or default_symbol).upper(), focus=focus, lang=lang)
272
+
273
+
274
+ _DATA_FILE_RE = re.compile(r"(?<![\w/.-])([\w./-]+\.(?:csv|tsv|xlsx|xls|json))(?![\w.])", re.I)
275
+ _CODE_FILE_RE = re.compile(r"\b[\w./-]+\.(?:py|js|ts|tsx|jsx|go|rs|java|rb|php|c|cc|cpp|h|cs|swift|kt|sh|"
276
+ r"md|txt|toml|ya?ml|html|css|sql|ipynb|csv|tsv|json|xlsx?)\b", re.I)
277
+ _CODE_WORDS = (
278
+ "script", "function", "class", "method", "refactor", "repo", "repository", "stack trace", "traceback",
279
+ "test coverage", "unit test", "pattern", "code", "compile", "debug", "regex", "api", "endpoint",
280
+ "代码", "脚本", "函数", "重构", "仓库", "测试", "报错", "调试", "接口",
281
+ )
282
+ # English words match whole words ("repo" is not in "report"); Chinese has no
283
+ # spaces, so it matches as a substring.
284
+ _CODE_WORD_RE = re.compile(
285
+ r"\b(?:" + "|".join(re.escape(w) for w in _CODE_WORDS if w.isascii()) + r")(?:s|es)?\b", re.I)
286
+ _INVENTORY_WORDS = ("inventory", "reorder", "re-order", "safety stock", "stockout", "sku", "库存", "补货", "安全库存", "断货")
287
+ _CARRIER_WORDS = ("carrier", "freight", "waybill", "shipping cost", "lane", "承运商", "运单", "运费", "物流成本")
288
+ _FINANCE_WORDS = ("market", "stock", "finance", "financial", "earnings", "市场", "股", "财经", "金融", "财报")
289
+ # Commands that act on one instrument and must not guess one.
290
+ _SYMBOL_COMMANDS = {"/analyze", "/risk", "/strategy", "/signal", "/predict", "/report", "/news", "/chart",
291
+ "/backtest"}
292
+
293
+
294
+ def _logistics_route(text: str, low: str, available_commands: set[str]) -> RoutedCommand | None:
295
+ """ "Which SKUs in skus.csv need reordering?" → /inventory skus.csv, when that file exists."""
296
+ import os
297
+
298
+ files = [m.group(1) for m in _DATA_FILE_RE.finditer(text) if os.path.isfile(m.group(1))]
299
+ if not files:
300
+ return None
301
+ if "/inventory" in available_commands and any(w in low for w in _INVENTORY_WORDS):
302
+ return RoutedCommand(command="/inventory", args=files[0])
303
+ if "/carriers" in available_commands and any(w in low for w in _CARRIER_WORDS):
304
+ return RoutedCommand(command="/carriers", args=files[0])
305
+ return None
306
+
307
+
308
+ def _looks_like_code_work(text: str, low: str) -> bool:
309
+ """A message about code or a data file, which is the model's to answer.
310
+
311
+ "plot a histogram of ages in data.csv" ran `/chart OF AGES GE IN CSV`,
312
+ "analyze this stack trace" ran `/analyze`, "strategy pattern in python"
313
+ ran `/strategy`. None of them is a market request.
314
+ """
315
+ return (bool(_CODE_FILE_RE.search(text)) or bool(_CODE_WORD_RE.search(low))
316
+ or any(word in low for word in _CODE_WORDS if not word.isascii()))
317
+
318
+
319
+ def route_top_level_text(user_input: str, available_commands: set[str]) -> RoutedCommand | None:
320
+ """Translate bare workflow text into a slash command when possible.
321
+
322
+ Only requests this can answer with certainty run a command; anything else
323
+ — code, data files, a keyword with no instrument — goes to the model,
324
+ which has the same tools and can ask.
325
+ """
326
+
327
+ stripped = user_input.strip()
328
+ from aria_code.apps.cli.conversation_policy import is_capability_question
329
+ if is_capability_question(stripped):
330
+ return None
331
+ if not stripped or stripped.startswith("/"):
332
+ return None
333
+ logistics = _logistics_route(stripped, stripped.lower(), available_commands)
334
+ if logistics is not None:
335
+ return logistics
336
+ if _looks_like_code_work(stripped, stripped.lower()):
337
+ return None
338
+
339
+ low = stripped.lower()
340
+
341
+ # ── Auto-Intercept SWE / Coding Intents ─────────────────
342
+ # If the user asks for coding tasks, instantly route to orchestrator (/route)
343
+ # allowing zero-friction natural language without typing /route.
344
+ swe_keywords = ["修 bug", "写代码", "写个", "写一个", "脚本", "bug", "代码", "报错", "前端", "后端", "测试", "项目", "github", "issue", "截图", "页面"]
345
+ if any(k in low for k in swe_keywords) and len(stripped) > 5:
346
+ if "/route" in available_commands:
347
+ return RoutedCommand(command="/route", args=stripped)
348
+ low = stripped.lower()
349
+ compact_low = low.replace(" ", "")
350
+ low_words = {part.strip(".,,。::;;") for part in low.split()}
351
+ if "/tv" in available_commands and (
352
+ any(k in low for k in _TRADINGVIEW_HINTS)
353
+ or "tv" in low_words
354
+ or any(k in compact_low for k in _TRADINGVIEW_ZH_HINTS)
355
+ or ("tradingview" in compact_low)
356
+ ):
357
+ symbols = _route_symbols(stripped)
358
+ symbol = symbols[0] if symbols else ""
359
+ if symbol:
360
+ opts: list[str] = []
361
+ if any(k in low for k in ("pine", "strategy", "策略")):
362
+ opts.append("--pine")
363
+ if any(k in low for k in ("copy", "clipboard", "复制", "剪贴板")):
364
+ opts.append("--copy")
365
+ if any(k in low for k in ("reveal", "finder", "所在目录", "访达", "目录")):
366
+ opts.append("--reveal")
367
+ if any(k in low for k in ("txt", "text file", "文本副本", "文本")):
368
+ opts.append("--txt")
369
+ if any(k in low for k in ("打开", "open")) and "--pine" not in opts:
370
+ opts.append("--open")
371
+ if "--pine" not in opts:
372
+ if any(k in low for k in _TRADINGVIEW_BULLISH_HINTS):
373
+ opts.append("--bullish")
374
+ elif any(k in low for k in _TRADINGVIEW_BEARISH_HINTS):
375
+ opts.append("--bearish")
376
+ elif any(k in low for k in _TRADINGVIEW_ANALYSIS_HINTS):
377
+ opts.append("--analyze")
378
+ return RoutedCommand(command="/tv", args=" ".join([symbol, *opts]).strip())
379
+ for keywords, command in _VISUAL_ROUTE_PATTERNS:
380
+ if command not in available_commands:
381
+ continue
382
+ if any(k in low for k in keywords):
383
+ symbols = _route_symbols(stripped)
384
+ symbol = symbols[0] if symbols else ""
385
+ if command == "/dashboard":
386
+ mode = next(
387
+ (
388
+ dashboard_mode
389
+ for mode_kw, dashboard_mode in _DASHBOARD_MODE_HINTS
390
+ if any(k in low for k in mode_kw)
391
+ ),
392
+ "brief",
393
+ )
394
+ return RoutedCommand(command=command, args=mode)
395
+ if command == "/chart":
396
+ if not symbols:
397
+ # A chart keyword with no resolvable symbol is a question
398
+ # ABOUT charting ("你会制作图表吗"), not a chart request.
399
+ # Routing the raw sentence produced `/chart <whole question>`
400
+ # and a guaranteed data-fetch failure; let the LLM answer.
401
+ continue
402
+ period = next(
403
+ (
404
+ period
405
+ for period_kw, period in _CHART_PERIOD_HINTS
406
+ if any(k in low for k in period_kw)
407
+ ),
408
+ "1y",
409
+ )
410
+ rest = " ".join(symbols)
411
+ return RoutedCommand(command=command, args=f"{rest} {period}".strip())
412
+ if command == "/report":
413
+ report_type = next(
414
+ (
415
+ report_type
416
+ for type_kw, report_type in _REPORT_TYPE_HINTS
417
+ if any(k in low for k in type_kw)
418
+ ),
419
+ "standard",
420
+ )
421
+ fmt = "html"
422
+ if any(k in low for k in ("markdown", "md")):
423
+ fmt = "md"
424
+ if not symbol:
425
+ continue # same rule as /chart: no symbol → not a report request
426
+ args = " ".join(part for part in [symbol, f"--type {report_type}" if report_type else "", f"--format {fmt}" if fmt else ""] if part)
427
+ return RoutedCommand(command=command, args=args)
428
+ if "/news" in available_commands and not _is_news_discussion(stripped) and any(k in low for k in (
429
+ "新闻", "消息", "最新进展", "最近进展", "news", "latest", "recent",
430
+ )):
431
+ symbols = _route_symbols(stripped)
432
+ topic = _news_topic(stripped, symbols)
433
+ # "latest"/"recent" alone are ordinary words ("the latest version of
434
+ # python"): without an instrument, only an explicit news request about
435
+ # markets is one ("今天有什么财经新闻", "market news today").
436
+ explicit = any(k in low for k in ("新闻", "news")) and any(k in low for k in _FINANCE_WORDS)
437
+ if symbols or topic in ("SpaceX", "LVMH") or explicit:
438
+ return RoutedCommand(command="/news", args=topic)
439
+ parts = stripped.split(maxsplit=1)
440
+ keyword = parts[0].lower()
441
+ rest = parts[1] if len(parts) > 1 else ""
442
+ command = TOP_LEVEL_ROUTES.get(keyword)
443
+ if not command or command not in available_commands:
444
+ return None
445
+ # "risk of this refactor?", "strategy pattern …", "analyze this …": these
446
+ # commands act on one instrument, and parse_analysis_args fell back to AAPL.
447
+ if command in _SYMBOL_COMMANDS and not _route_symbols(rest or stripped):
448
+ return None
449
+ if command == "/analyze":
450
+ parsed = parse_analysis_args(rest)
451
+ focus_arg = f" --focus {parsed.focus}" if parsed.focus else ""
452
+ zh_chars = sum(1 for c in stripped if "\u4e00" <= c <= "\u9fff")
453
+ lang_arg = f" --lang {'zh' if zh_chars else 'en'}"
454
+ return RoutedCommand(command=command, args=f"{parsed.symbol}{focus_arg}{lang_arg}".strip())
455
+ return RoutedCommand(command=command, args=rest)
456
+
457
+
458
+ def parse_symbols(args: str, fallback: list[str] | tuple[str, ...]) -> list[str]:
459
+ symbols = [part.upper() for part in args.split() if part.strip()]
460
+ return symbols or [str(item).upper() for item in fallback]
461
+
462
+
463
+ def sanitize_chart_symbol_args(raw_symbols: list[str] | tuple[str, ...]) -> list[str]:
464
+ """Drop analysis words that sometimes leak into chart symbol arguments."""
465
+ cleaned = [str(item or "").strip().strip(",,") for item in raw_symbols]
466
+ cleaned = [item for item in cleaned if item]
467
+ if not cleaned:
468
+ return []
469
+ if len(cleaned) == 1:
470
+ upper = cleaned[0].upper()
471
+ return [] if _is_blocked_market_symbol_candidate(upper) else cleaned
472
+
473
+ upper_tokens = [item.upper() for item in cleaned]
474
+ has_context_noise = any(
475
+ token in _CHART_CONTEXT_TOKEN_BLOCKLIST or _is_blocked_market_symbol_candidate(token)
476
+ for token in upper_tokens
477
+ )
478
+
479
+ out: list[str] = []
480
+ for raw, upper in zip(cleaned, upper_tokens):
481
+ if upper in _CHART_CONTEXT_TOKEN_BLOCKLIST:
482
+ continue
483
+ if _is_blocked_market_symbol_candidate(upper):
484
+ continue
485
+ # MA is a valid ticker (Mastercard), but in noisy generated chart args it
486
+ # usually comes from moving-average text next to TTM/above/below terms.
487
+ if upper == "MA" and has_context_noise and len(cleaned) > 2:
488
+ continue
489
+ out.append(raw)
490
+ return out
491
+
492
+
493
+ def parse_technical_args(args: str, *, default_symbol: str = "AAPL", default_days: int = 120) -> TechnicalArgs:
494
+ parts = args.strip().split()
495
+ symbol = default_symbol.upper()
496
+ days = default_days
497
+
498
+ if parts and not parts[0].startswith("-") and not parts[0].startswith("days="):
499
+ symbol = parts[0].upper()
500
+ option_parts = parts[1:]
501
+ else:
502
+ option_parts = parts
503
+
504
+ skip_next = False
505
+ for idx, part in enumerate(option_parts):
506
+ if skip_next:
507
+ skip_next = False
508
+ continue
509
+ raw = part.strip()
510
+ value = None
511
+ if raw.startswith("days="):
512
+ value = raw.split("=", 1)[1]
513
+ elif raw.startswith("--days="):
514
+ value = raw.split("=", 1)[1]
515
+ elif raw == "--days" and idx + 1 < len(option_parts):
516
+ value = option_parts[idx + 1]
517
+ skip_next = True
518
+
519
+ if value is not None:
520
+ try:
521
+ parsed = int(value)
522
+ if parsed > 0:
523
+ days = parsed
524
+ except ValueError:
525
+ pass
526
+
527
+ return TechnicalArgs(symbol=symbol, days=days)
528
+
529
+
530
+ async def try_top_level_route(user_input: str, commands, *, announce=None) -> bool:
531
+ """Execute a top-level routed slash command through a SlashCommands object.
532
+
533
+ ``announce`` is told the command first ("→ /news AAPL"): the interactive
534
+ loop routes here before send_message, so a routed message used to run its
535
+ command with nothing on screen saying which.
536
+ """
537
+
538
+ routed = route_top_level_text(user_input, set(commands.commands))
539
+ if routed is None:
540
+ return False
541
+ if announce is not None:
542
+ announce(routed.text)
543
+ await commands.execute(routed.text)
544
+ return True