aria-code 0.79.0__tar.gz → 0.81.0__tar.gz

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 (738) hide show
  1. {aria_code-0.79.0/src/aria_code.egg-info → aria_code-0.81.0}/PKG-INFO +1 -1
  2. {aria_code-0.79.0 → aria_code-0.81.0}/pyproject.toml +1 -1
  3. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/_version.py +1 -1
  4. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/analysis_cmds.py +6 -1
  5. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/market_context.py +7 -0
  6. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/deterministic.py +7 -1
  7. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/handlers/market_handlers.py +94 -42
  8. aria_code-0.81.0/src/aria_code/apps/cli/market_hours.py +100 -0
  9. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/utils/market_detect.py +43 -10
  10. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/aria_cli.py +62 -23
  11. {aria_code-0.79.0 → aria_code-0.81.0/src/aria_code.egg-info}/PKG-INFO +1 -1
  12. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code.egg-info/SOURCES.txt +3 -0
  13. aria_code-0.81.0/tests/test_market_answers_in_english.py +210 -0
  14. aria_code-0.81.0/tests/test_market_hours.py +73 -0
  15. {aria_code-0.79.0 → aria_code-0.81.0}/LICENSE +0 -0
  16. {aria_code-0.79.0 → aria_code-0.81.0}/NOTICE +0 -0
  17. {aria_code-0.79.0 → aria_code-0.81.0}/README.md +0 -0
  18. {aria_code-0.79.0 → aria_code-0.81.0}/setup.cfg +0 -0
  19. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/__init__.py +0 -0
  20. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/adk_apps/__init__.py +0 -0
  21. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/adk_apps/aria_code_review/__init__.py +0 -0
  22. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/adk_apps/aria_code_review/agent.py +0 -0
  23. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/adk_apps/aria_research/__init__.py +0 -0
  24. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/adk_apps/aria_research/agent.py +0 -0
  25. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/__init__.py +0 -0
  26. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/base.py +0 -0
  27. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/code_review.py +0 -0
  28. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/deep/__init__.py +0 -0
  29. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/deep/calibration_loop.py +0 -0
  30. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/deep/critic.py +0 -0
  31. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/deep/deepen.py +0 -0
  32. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/deep/models.py +0 -0
  33. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/deep/pipeline.py +0 -0
  34. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/deep/quant_fusion.py +0 -0
  35. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/deep/themes.py +0 -0
  36. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/deep/tiers.py +0 -0
  37. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/engineering/__init__.py +0 -0
  38. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/engineering/coder.py +0 -0
  39. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/engineering/tester.py +0 -0
  40. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/__init__.py +0 -0
  41. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/cashflow_burn.py +0 -0
  42. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/catalyst.py +0 -0
  43. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/corporate_finance.py +0 -0
  44. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/debate.py +0 -0
  45. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/earnings.py +0 -0
  46. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/fundamental.py +0 -0
  47. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/macro.py +0 -0
  48. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/news.py +0 -0
  49. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/risk.py +0 -0
  50. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/sector.py +0 -0
  51. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/strategist.py +0 -0
  52. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/stripe_revenue.py +0 -0
  53. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/synthesis.py +0 -0
  54. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/financial/technical.py +0 -0
  55. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/orchestrator.py +0 -0
  56. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/portfolio_agent.py +0 -0
  57. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/realty/__init__.py +0 -0
  58. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/realty/asset_diagnosis.py +0 -0
  59. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/realty/business_match.py +0 -0
  60. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/realty/cashflow_verify.py +0 -0
  61. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/realty/contract_rules.py +0 -0
  62. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/realty/energy_anomaly.py +0 -0
  63. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/realty/exit_settlement.py +0 -0
  64. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/realty/fulfillment_risk.py +0 -0
  65. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/realty/ops_optimize.py +0 -0
  66. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/realty/revenue_share.py +0 -0
  67. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/registry.py +0 -0
  68. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/signal_scheme.py +0 -0
  69. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/sports/__init__.py +0 -0
  70. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/sports/football_agent.py +0 -0
  71. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/supervisor.py +0 -0
  72. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/team.py +0 -0
  73. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/warehouse/__init__.py +0 -0
  74. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/warehouse/contracts.py +0 -0
  75. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/warehouse/dashboard.py +0 -0
  76. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/warehouse/fulfillment_leadtime.py +0 -0
  77. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/warehouse/inbound_exceptions.py +0 -0
  78. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/warehouse/inventory_health.py +0 -0
  79. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/warehouse/local_run.py +0 -0
  80. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/warehouse/local_snapshot.py +0 -0
  81. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/warehouse/logistics_cost.py +0 -0
  82. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/warehouse/logistics_sync.py +0 -0
  83. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/agents/warehouse/workflow.py +0 -0
  84. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/aliyun_data_client.py +0 -0
  85. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/README.md +0 -0
  86. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/__init__.py +0 -0
  87. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/channels/README.md +0 -0
  88. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/channels/__init__.py +0 -0
  89. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/channels/approvals.py +0 -0
  90. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/channels/conversation.py +0 -0
  91. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/channels/digest.py +0 -0
  92. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/channels/intake.py +0 -0
  93. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/channels/registry.py +0 -0
  94. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/channels/tradingview.py +0 -0
  95. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/README.md +0 -0
  96. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/__init__.py +0 -0
  97. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/_optional.py +0 -0
  98. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/bootstrap.py +0 -0
  99. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/broker_render.py +0 -0
  100. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/codegen_paths.py +0 -0
  101. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/__init__.py +0 -0
  102. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/_business_render.py +0 -0
  103. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/_ui.py +0 -0
  104. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/ashare_prediction_cmds.py +0 -0
  105. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/auth_cmds.py +0 -0
  106. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/backtest_cmds.py +0 -0
  107. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/broker_cmds.py +0 -0
  108. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/business_workflow_cmds.py +0 -0
  109. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/canvas_cmds.py +0 -0
  110. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/catalog.py +0 -0
  111. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/core_cmds.py +0 -0
  112. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/data_cmds.py +0 -0
  113. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/diagnostic_cmds.py +0 -0
  114. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/diagnostic_ops_cmds.py +0 -0
  115. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/file_cmds.py +0 -0
  116. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/finance_service_cmds.py +0 -0
  117. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/fx_commodity_cmds.py +0 -0
  118. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/market.py +0 -0
  119. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/market_cmds.py +0 -0
  120. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/market_render.py +0 -0
  121. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/model_cmds.py +0 -0
  122. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/ops_cmds.py +0 -0
  123. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/orchestrator_cmds.py +0 -0
  124. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/pdf_export_cmds.py +0 -0
  125. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/portfolio_cmds.py +0 -0
  126. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/report.py +0 -0
  127. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/scaffold_templates.py +0 -0
  128. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/session_cmds.py +0 -0
  129. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/session_ux_cmds.py +0 -0
  130. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/team.py +0 -0
  131. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/team_render.py +0 -0
  132. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/ui_cmds.py +0 -0
  133. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/warehouse_cmds.py +0 -0
  134. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/workflow_cmds.py +0 -0
  135. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/commands/workspace_cmds.py +0 -0
  136. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/config_paths.py +0 -0
  137. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/config_store.py +0 -0
  138. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/constants.py +0 -0
  139. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/context.py +0 -0
  140. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/direct.py +0 -0
  141. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/finance_service_catalog.py +0 -0
  142. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/football_reports.py +0 -0
  143. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/github_app_auth.py +0 -0
  144. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/google_login.py +0 -0
  145. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/handlers/__init__.py +0 -0
  146. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/handlers/broker_handlers.py +0 -0
  147. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/handlers/chart_handlers.py +0 -0
  148. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/handlers/realty_handlers.py +0 -0
  149. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/handlers/sports_handlers.py +0 -0
  150. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/handlers/strategy_advice.py +0 -0
  151. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/helpers.py +0 -0
  152. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/hooks.py +0 -0
  153. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/i18n.py +0 -0
  154. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/intent.py +0 -0
  155. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/intent_router.py +0 -0
  156. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/intent_signals.py +0 -0
  157. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/lifecycle_hooks.py +0 -0
  158. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/local_tool_schemas.py +0 -0
  159. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/main.py +0 -0
  160. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/market_metadata.py +0 -0
  161. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/market_universe.py +0 -0
  162. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/message_processing.py +0 -0
  163. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/model_catalog.py +0 -0
  164. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/pdf_report.py +0 -0
  165. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/plan_mode.py +0 -0
  166. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/plotly_html.py +0 -0
  167. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/prediction_feedback.py +0 -0
  168. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/preflight.py +0 -0
  169. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/project_aria.py +0 -0
  170. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/prompt_assembly.py +0 -0
  171. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/prompts/__init__.py +0 -0
  172. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/prompts/coding.py +0 -0
  173. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/prompts/select.py +0 -0
  174. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/prompts/system_prompts.py +0 -0
  175. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/prompts/ui.py +0 -0
  176. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/provider_endpoints.py +0 -0
  177. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/provider_keys.py +0 -0
  178. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/providers/__init__.py +0 -0
  179. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/providers/base.py +0 -0
  180. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/providers/chat_routing.py +0 -0
  181. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/providers/collaboration.py +0 -0
  182. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/providers/llm/__init__.py +0 -0
  183. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/providers/llm/offline_responses.py +0 -0
  184. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/providers/llm/ollama_stream.py +0 -0
  185. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/providers/llm/response_cache.py +0 -0
  186. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/providers/llm/sse_stream.py +0 -0
  187. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/providers/runtime_bridge.py +0 -0
  188. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/providers/vertexai_stream.py +0 -0
  189. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/review_runner.py +0 -0
  190. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/runtime_consumer.py +0 -0
  191. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/sandbox.py +0 -0
  192. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/session_export.py +0 -0
  193. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/session_jsonl.py +0 -0
  194. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/session_store.py +0 -0
  195. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/skills_catalog.py +0 -0
  196. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/todo_tracker.py +0 -0
  197. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/tool_executor.py +0 -0
  198. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/tool_registry.py +0 -0
  199. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/tool_scope.py +0 -0
  200. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/tools/__init__.py +0 -0
  201. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/tools/context.py +0 -0
  202. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/tools/file_tools.py +0 -0
  203. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/tools/market_tools.py +0 -0
  204. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/tools/notebook_tools.py +0 -0
  205. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/tools/system_tools.py +0 -0
  206. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/tools/write_tools.py +0 -0
  207. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/tradingview_bridge.py +0 -0
  208. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/turn_planning.py +0 -0
  209. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/update_check.py +0 -0
  210. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/updater.py +0 -0
  211. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/cli/utils/__init__.py +0 -0
  212. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/daemon/README.md +0 -0
  213. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/vscode/README.md +0 -0
  214. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/apps/vscode/package.json +0 -0
  215. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/aria_daemon.py +0 -0
  216. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/aria_feishu_bot.py +0 -0
  217. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/aria_mcp_server.py +0 -0
  218. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/aria_relay_client.py +0 -0
  219. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/aria_relay_server.py +0 -0
  220. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/aria_telegram_bot.py +0 -0
  221. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ariarc.py +0 -0
  222. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/artifacts.py +0 -0
  223. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/backtest_engine.py +0 -0
  224. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/backtest_report.py +0 -0
  225. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/__init__.py +0 -0
  226. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/automation.py +0 -0
  227. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/base.py +0 -0
  228. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/capabilities.py +0 -0
  229. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/cn/__init__.py +0 -0
  230. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/cn/easytrader_broker.py +0 -0
  231. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/cn/futu_broker.py +0 -0
  232. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/cn/longbridge_broker.py +0 -0
  233. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/cn/tiger_broker.py +0 -0
  234. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/cn/xtquant_broker.py +0 -0
  235. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/config.py +0 -0
  236. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/intl/__init__.py +0 -0
  237. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/intl/alpaca_broker.py +0 -0
  238. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/intl/ibkr_broker.py +0 -0
  239. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/intl/trading212_broker.py +0 -0
  240. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/intl/webull_broker.py +0 -0
  241. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/paper_broker.py +0 -0
  242. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/planning.py +0 -0
  243. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/registry.py +0 -0
  244. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/brokers/trading.py +0 -0
  245. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/canva_client.py +0 -0
  246. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/change_store.py +0 -0
  247. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/clients/__init__.py +0 -0
  248. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/clients/aliyun_data_client.py +0 -0
  249. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/clients/aria_relay_client.py +0 -0
  250. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/clients/canva_client.py +0 -0
  251. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/clients/figma_client.py +0 -0
  252. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/clients/football_data_client.py +0 -0
  253. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/clients/kling_video_client.py +0 -0
  254. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/clients/market_data_client.py +0 -0
  255. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/clients/openai_image_client.py +0 -0
  256. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/clients/runway_video_client.py +0 -0
  257. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/clients/warehouse_erp_client.py +0 -0
  258. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/cloud_memory.py +0 -0
  259. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/command_safety.py +0 -0
  260. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/computer_use_tools.py +0 -0
  261. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/dashboard_generator.py +0 -0
  262. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/data_analysis_tools.py +0 -0
  263. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/data_cleaner.py +0 -0
  264. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/data_service.py +0 -0
  265. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/datasources/__init__.py +0 -0
  266. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/datasources/base.py +0 -0
  267. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/datasources/router.py +0 -0
  268. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/datasources/sources/__init__.py +0 -0
  269. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/datasources/sources/akshare_source.py +0 -0
  270. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/datasources/sources/alpha_vantage_source.py +0 -0
  271. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/datasources/sources/edgar_source.py +0 -0
  272. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/datasources/sources/finnhub_source.py +0 -0
  273. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/datasources/sources/fred_source.py +0 -0
  274. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/datasources/sources/tushare_source.py +0 -0
  275. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/datasources/sources/web_scraper_source.py +0 -0
  276. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/datasources/sources/world_bank_source.py +0 -0
  277. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/datasources/sources/yfinance_source.py +0 -0
  278. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/demo_player.py +0 -0
  279. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/doctor.py +0 -0
  280. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/domain/__init__.py +0 -0
  281. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/domain/backtest_engine.py +0 -0
  282. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/domain/backtest_report.py +0 -0
  283. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/domain/finance_formulas.py +0 -0
  284. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/domain/portfolio_ledger.py +0 -0
  285. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/domain/strategy_vault.py +0 -0
  286. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/evals/__init__.py +0 -0
  287. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/evals/harness.py +0 -0
  288. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/evals/runner.py +0 -0
  289. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/external_agent_runner.py +0 -0
  290. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/figma_client.py +0 -0
  291. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/file_analysis_tools.py +0 -0
  292. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/finance_formulas.py +0 -0
  293. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/football_data_client.py +0 -0
  294. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/image_gen_tools.py +0 -0
  295. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/intent_classifier.py +0 -0
  296. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/kling_video_client.py +0 -0
  297. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/licensing.py +0 -0
  298. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/local_finance_tools.py +0 -0
  299. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/local_image_provider.py +0 -0
  300. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/local_llm_provider.py +0 -0
  301. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/macro_tools.py +0 -0
  302. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/markdown_pdf.py +0 -0
  303. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/market_data_client.py +0 -0
  304. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/mcp_client.py +0 -0
  305. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/memory_manager.py +0 -0
  306. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/model_capability.py +0 -0
  307. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/notification_tools.py +0 -0
  308. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/openai_image_client.py +0 -0
  309. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/__init__.py +0 -0
  310. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/adk_bridge/__init__.py +0 -0
  311. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/adk_bridge/code_review_tools.py +0 -0
  312. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/adk_bridge/market_tools.py +0 -0
  313. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_agents/__init__.py +0 -0
  314. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_agents/manifest.py +0 -0
  315. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_core/__init__.py +0 -0
  316. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_core/architecture.py +0 -0
  317. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_core/export.py +0 -0
  318. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_core/manifest.py +0 -0
  319. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_core/paths.py +0 -0
  320. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_core/secure_file.py +0 -0
  321. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_infra/__init__.py +0 -0
  322. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_infra/arthera.py +0 -0
  323. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_infra/doctor.py +0 -0
  324. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_infra/product.py +0 -0
  325. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_mcp/__init__.py +0 -0
  326. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_mcp/bridge.py +0 -0
  327. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_mcp/circuit.py +0 -0
  328. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_mcp/config.py +0 -0
  329. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_mcp/installer.py +0 -0
  330. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_mcp/server.py +0 -0
  331. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_mcp/tools.py +0 -0
  332. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_sdk/__init__.py +0 -0
  333. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_sdk/client.py +0 -0
  334. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_sdk/providers.py +0 -0
  335. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_sdk/streaming.py +0 -0
  336. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_sdk/types.py +0 -0
  337. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_services/__init__.py +0 -0
  338. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_services/cache.py +0 -0
  339. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_services/context.py +0 -0
  340. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_services/context_checkpoints.py +0 -0
  341. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_services/data.py +0 -0
  342. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_services/provider_health.py +0 -0
  343. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_services/references.py +0 -0
  344. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_services/registry.py +0 -0
  345. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_services/research_protocol.py +0 -0
  346. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_services/research_quality.py +0 -0
  347. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_services/settings.py +0 -0
  348. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_services/usage.py +0 -0
  349. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_skills/__init__.py +0 -0
  350. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_skills/catalog.py +0 -0
  351. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_skills/loader.py +0 -0
  352. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_skills/registry.py +0 -0
  353. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_tools/__init__.py +0 -0
  354. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_tools/financial/__init__.py +0 -0
  355. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_tools/financial/_paths.py +0 -0
  356. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_tools/financial/compliance.py +0 -0
  357. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_tools/financial/factors.py +0 -0
  358. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_tools/financial/risk_tools.py +0 -0
  359. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_tools/financial/strategy.py +0 -0
  360. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/aria_tools/registry.py +0 -0
  361. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/__init__.py +0 -0
  362. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/_namespace.py +0 -0
  363. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/backtest/__init__.py +0 -0
  364. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/backtest/core.py +0 -0
  365. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/backtest/engine.py +0 -0
  366. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/portfolio/__init__.py +0 -0
  367. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/portfolio/optimizer.py +0 -0
  368. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/sports/__init__.py +0 -0
  369. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/sports/calibrator.py +0 -0
  370. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/sports/dixon_coles.py +0 -0
  371. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/sports/elo.py +0 -0
  372. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/sports/form.py +0 -0
  373. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/sports/h2h.py +0 -0
  374. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/sports/ml_model.py +0 -0
  375. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/sports/predictor.py +0 -0
  376. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/sports/tracker.py +0 -0
  377. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/stochastic/__init__.py +0 -0
  378. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +0 -0
  379. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/stochastic/ito_calculus.py +0 -0
  380. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/stochastic/kelly_criterion.py +0 -0
  381. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +0 -0
  382. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/stochastic/options_pricing.py +0 -0
  383. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packages/quant_engine/stochastic/stochastic_processes.py +0 -0
  384. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packs/__init__.py +0 -0
  385. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packs/base.py +0 -0
  386. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packs/finance/__init__.py +0 -0
  387. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packs/logistics/__init__.py +0 -0
  388. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packs/payments/__init__.py +0 -0
  389. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packs/realty/__init__.py +0 -0
  390. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packs/registry.py +0 -0
  391. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/packs/rules.py +0 -0
  392. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/plan_utils.py +0 -0
  393. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/plugin_loader.py +0 -0
  394. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/portfolio_ledger.py +0 -0
  395. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/preview_server.py +0 -0
  396. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/privacy/__init__.py +0 -0
  397. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/privacy/feedback.py +0 -0
  398. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/project_review.py +0 -0
  399. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/project_review_api.py +0 -0
  400. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/project_review_server.py +0 -0
  401. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/project_tools.py +0 -0
  402. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/providers/__init__.py +0 -0
  403. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/providers/llm/__init__.py +0 -0
  404. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/providers/llm/anthropic.py +0 -0
  405. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/providers/llm/autoconfig.py +0 -0
  406. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/providers/llm/base.py +0 -0
  407. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/providers/llm/custom.py +0 -0
  408. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/providers/llm/ollama.py +0 -0
  409. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/providers/llm/openai_compat.py +0 -0
  410. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/providers/llm/registry.py +0 -0
  411. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/providers/local_image_provider.py +0 -0
  412. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/providers/local_llm_provider.py +0 -0
  413. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/providers/tool_messages.py +0 -0
  414. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/realty_data_tools.py +0 -0
  415. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/relay_store.py +0 -0
  416. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/report_exporters.py +0 -0
  417. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/report_generator.py +0 -0
  418. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/review_service.py +0 -0
  419. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/__init__.py +0 -0
  420. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/acceptance.py +0 -0
  421. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/agent_loop.py +0 -0
  422. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/approval.py +0 -0
  423. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/budget.py +0 -0
  424. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/checkpoints.py +0 -0
  425. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/crash_report.py +0 -0
  426. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/events.py +0 -0
  427. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/gateway.py +0 -0
  428. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/lsp.py +0 -0
  429. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/orchestrator.py +0 -0
  430. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/repo_map.py +0 -0
  431. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/run_state.py +0 -0
  432. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/run_store.py +0 -0
  433. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/self_healing.py +0 -0
  434. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/subagent.py +0 -0
  435. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/task_ledger.py +0 -0
  436. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/task_orchestrator.py +0 -0
  437. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/tool_executor.py +0 -0
  438. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/tool_policy.py +0 -0
  439. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runtime/worktrees.py +0 -0
  440. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/runway_video_client.py +0 -0
  441. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/safety/__init__.py +0 -0
  442. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/safety/permissions.py +0 -0
  443. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/safety/service.py +0 -0
  444. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/setup_wizard.py +0 -0
  445. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/spreadsheet_tools.py +0 -0
  446. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/strategy_vault.py +0 -0
  447. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/__init__.py +0 -0
  448. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/artifact_tools.py +0 -0
  449. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/broker_tools.py +0 -0
  450. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/build_quant_engine.py +0 -0
  451. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/code_audit_tools.py +0 -0
  452. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/computer_use_tools.py +0 -0
  453. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/data_analysis_tools.py +0 -0
  454. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/enterprise_finance_tools.py +0 -0
  455. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/extended_tools.py +0 -0
  456. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/file_analysis_tools.py +0 -0
  457. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/image_gen_tools.py +0 -0
  458. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/local_finance_tools.py +0 -0
  459. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/logistics_carriers.py +0 -0
  460. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/logistics_inventory.py +0 -0
  461. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/logistics_io.py +0 -0
  462. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/logistics_tenancy.py +0 -0
  463. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/logistics_tools.py +0 -0
  464. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/macro_tools.py +0 -0
  465. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/notification_tools.py +0 -0
  466. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/project_tools.py +0 -0
  467. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/realty_data_tools.py +0 -0
  468. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/spreadsheet_tools.py +0 -0
  469. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/tools/stripe_tools.py +0 -0
  470. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/__init__.py +0 -0
  471. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/banner.py +0 -0
  472. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/completer.py +0 -0
  473. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/console.py +0 -0
  474. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/image_render.py +0 -0
  475. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/input_box.py +0 -0
  476. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/picker.py +0 -0
  477. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/render/__init__.py +0 -0
  478. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/render/finance.py +0 -0
  479. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/render/market.py +0 -0
  480. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/render/output.py +0 -0
  481. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/render/responsive.py +0 -0
  482. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/render/team.py +0 -0
  483. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/robot.py +0 -0
  484. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/ui/startup_dashboard.py +0 -0
  485. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/utils/vscode_uri.py +0 -0
  486. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/video_analysis.py +0 -0
  487. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/video_editor.py +0 -0
  488. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/workspace/__init__.py +0 -0
  489. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/workspace/files.py +0 -0
  490. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/workspace/verify.py +0 -0
  491. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/workspace_changes.py +0 -0
  492. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/workspace_context.py +0 -0
  493. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/workspace_service.py +0 -0
  494. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code/workspace_tools.py +0 -0
  495. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code.egg-info/dependency_links.txt +0 -0
  496. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code.egg-info/entry_points.txt +0 -0
  497. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code.egg-info/requires.txt +0 -0
  498. {aria_code-0.79.0 → aria_code-0.81.0}/src/aria_code.egg-info/top_level.txt +0 -0
  499. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_adk_market_tools.py +0 -0
  500. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_agent_team_fallback.py +0 -0
  501. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_analyze_file_tool.py +0 -0
  502. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_architecture_ledger_is_true.py +0 -0
  503. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_architecture_report.py +0 -0
  504. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_aria_cli_core.py +0 -0
  505. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_aria_mcp_server.py +0 -0
  506. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_aria_sdk.py +0 -0
  507. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_artifact_publishing.py +0 -0
  508. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_artifacts_and_reports.py +0 -0
  509. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_ashare_prediction_cmds.py +0 -0
  510. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_backtest_cmds.py +0 -0
  511. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_backtest_engine.py +0 -0
  512. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_backtest_report.py +0 -0
  513. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_binary_bundles_runtime_imports.py +0 -0
  514. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_broken_akshare_is_optional.py +0 -0
  515. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_broker_automation.py +0 -0
  516. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_broker_chat_confirm_gate.py +0 -0
  517. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_broker_planning.py +0 -0
  518. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_broker_safety.py +0 -0
  519. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_broker_tools.py +0 -0
  520. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_budget.py +0 -0
  521. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_business_workflow_cmds.py +0 -0
  522. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_canva_client.py +0 -0
  523. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_canvas_cmds.py +0 -0
  524. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_card_approvals.py +0 -0
  525. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_channel_intake.py +0 -0
  526. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_channels.py +0 -0
  527. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_chart_handlers.py +0 -0
  528. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_chat_bots_fail_closed.py +0 -0
  529. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_chat_routing.py +0 -0
  530. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_ci_security_workflow.py +0 -0
  531. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_cli_app_split.py +0 -0
  532. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_cli_bootstrap.py +0 -0
  533. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_cli_config_store.py +0 -0
  534. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_cli_lifecycle_hooks.py +0 -0
  535. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_cli_runtime_consumer.py +0 -0
  536. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_cli_tool_executor_module.py +0 -0
  537. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_cli_updater.py +0 -0
  538. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_cloud_memory.py +0 -0
  539. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_code_audit_tools.py +0 -0
  540. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_code_review_agent.py +0 -0
  541. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_codegen_output.py +0 -0
  542. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_coder_tester_self_healing.py +0 -0
  543. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_coder_tool_safety.py +0 -0
  544. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_collaboration.py +0 -0
  545. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_command_loggers.py +0 -0
  546. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_command_safety.py +0 -0
  547. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_completions_builder.py +0 -0
  548. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_config_paths.py +0 -0
  549. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_configured_provider.py +0 -0
  550. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_container_entrypoint.py +0 -0
  551. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_container_entrypoints.py +0 -0
  552. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_context_checkpoints.py +0 -0
  553. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_context_references.py +0 -0
  554. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_context_service.py +0 -0
  555. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_conversation_core.py +0 -0
  556. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_crash_report.py +0 -0
  557. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_credential_file_permissions.py +0 -0
  558. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_custom_providers.py +0 -0
  559. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_daemon_gateway_config.py +0 -0
  560. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_dashboard_generator.py +0 -0
  561. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_data_service.py +0 -0
  562. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_data_service_imports.py +0 -0
  563. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_datasource_routing.py +0 -0
  564. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_deep_analysis.py +0 -0
  565. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_degrades_without_quant_engine.py +0 -0
  566. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_dispatcher_pins_match_the_release.py +0 -0
  567. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_doctor.py +0 -0
  568. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_doctor_describes_the_current_install.py +0 -0
  569. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_doctor_npm_scope.py +0 -0
  570. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_engine_boundary.py +0 -0
  571. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_enterprise_tool_honesty.py +0 -0
  572. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_env_switch_docs.py +0 -0
  573. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_evals_harness.py +0 -0
  574. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_event_import_roots.py +0 -0
  575. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_extended_tools.py +0 -0
  576. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_feishu_swarm_config.py +0 -0
  577. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_finalize_release.py +0 -0
  578. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_finance_renderers.py +0 -0
  579. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_finance_service_catalog.py +0 -0
  580. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_first_run_works.py +0 -0
  581. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_football_agent.py +0 -0
  582. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_football_prediction_output.py +0 -0
  583. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_google_cloud_models.py +0 -0
  584. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_google_cloud_routing.py +0 -0
  585. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_google_login.py +0 -0
  586. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_google_search_provider.py +0 -0
  587. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_headless_is_agentic.py +0 -0
  588. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_honest_surfaces.py +0 -0
  589. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_image_gen_tools.py +0 -0
  590. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_image_inputs.py +0 -0
  591. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_import_graph_budget.py +0 -0
  592. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_intent_router.py +0 -0
  593. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_intent_signals.py +0 -0
  594. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_kling_video_client.py +0 -0
  595. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_lazy_rebind.py +0 -0
  596. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_legacy_module_imports.py +0 -0
  597. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_license_consistency.py +0 -0
  598. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_licensing.py +0 -0
  599. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_local_image_provider.py +0 -0
  600. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_logistics_3pl.py +0 -0
  601. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_logistics_and_finance_agents.py +0 -0
  602. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_lsp.py +0 -0
  603. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_markdown_pdf.py +0 -0
  604. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_market_data_client.py +0 -0
  605. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_market_history_inheritance.py +0 -0
  606. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_market_history_tool.py +0 -0
  607. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_market_questions_on_backend.py +0 -0
  608. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_market_symbol_extraction.py +0 -0
  609. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_market_universe.py +0 -0
  610. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_mcp_circuit.py +0 -0
  611. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_mcp_client.py +0 -0
  612. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_model_capability_registry.py +0 -0
  613. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_model_choice_is_the_users.py +0 -0
  614. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_model_selection_state.py +0 -0
  615. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_native_binary_entrypoints.py +0 -0
  616. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_native_installer.py +0 -0
  617. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_new_modules.py +0 -0
  618. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_no_hardcoded_developer_paths.py +0 -0
  619. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_no_uncommitted_imports.py +0 -0
  620. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_ollama_stream_imports.py +0 -0
  621. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_ollama_stream_tools.py +0 -0
  622. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_openai_image_client.py +0 -0
  623. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_operations_suite.py +0 -0
  624. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_output_rendering.py +0 -0
  625. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_packages_facade.py +0 -0
  626. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_packaging_constraints.py +0 -0
  627. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_packaging_manifest.py +0 -0
  628. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_packs_domains.py +0 -0
  629. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_pdf_report.py +0 -0
  630. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_pick_best_installed_model.py +0 -0
  631. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_plan_mode.py +0 -0
  632. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_platform_package_assembly.py +0 -0
  633. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_platform_packages.py +0 -0
  634. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_plotly_html_output.py +0 -0
  635. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_portfolio_ledger.py +0 -0
  636. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_post_turn_context_decision.py +0 -0
  637. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_preflight.py +0 -0
  638. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_preview_server.py +0 -0
  639. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_privacy_feedback.py +0 -0
  640. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_project_aria.py +0 -0
  641. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_project_review.py +0 -0
  642. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_project_review_api.py +0 -0
  643. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_prompt_assembly.py +0 -0
  644. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_prompt_selection.py +0 -0
  645. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_provider_autoconfig.py +0 -0
  646. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_provider_error_messages.py +0 -0
  647. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_provider_integration.py +0 -0
  648. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_provider_registry.py +0 -0
  649. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_public_service_status.py +0 -0
  650. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_quant_engine_namespace.py +0 -0
  651. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_rebind_contract.py +0 -0
  652. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_rebind_namespace_contract.py +0 -0
  653. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_relay_client_credentials.py +0 -0
  654. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_relay_event_verification.py +0 -0
  655. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_relay_sends_for_clients.py +0 -0
  656. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_relay_store.py +0 -0
  657. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_relay_url.py +0 -0
  658. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_release_chain.py +0 -0
  659. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_release_commit_identity.py +0 -0
  660. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_release_push_is_atomic.py +0 -0
  661. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_release_reaches_the_registries.py +0 -0
  662. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_release_verification_waits.py +0 -0
  663. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_release_workflow_permissions.py +0 -0
  664. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_report_charts.py +0 -0
  665. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_report_generator.py +0 -0
  666. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_research_protocol.py +0 -0
  667. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_research_quality.py +0 -0
  668. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_responsive_rendering.py +0 -0
  669. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_review_service.py +0 -0
  670. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_root_module_budget.py +0 -0
  671. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_rsi_without_pandas_ta.py +0 -0
  672. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_runtime_acceptance.py +0 -0
  673. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_runtime_agent_loop.py +0 -0
  674. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_runtime_approval.py +0 -0
  675. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_runtime_bridge.py +0 -0
  676. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_runtime_bridge_fallback.py +0 -0
  677. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_runtime_checkpoints.py +0 -0
  678. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_runtime_event_identity.py +0 -0
  679. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_runtime_gateway.py +0 -0
  680. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_runtime_repo_map.py +0 -0
  681. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_runtime_run_store.py +0 -0
  682. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_runtime_tool_executor.py +0 -0
  683. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_runtime_worktrees.py +0 -0
  684. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_runway_video_client.py +0 -0
  685. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_safety_permissions.py +0 -0
  686. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_safety_service.py +0 -0
  687. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_safety_service_adoption.py +0 -0
  688. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_service_diagnostics_security.py +0 -0
  689. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_session_search.py +0 -0
  690. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_settings_service.py +0 -0
  691. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_shipper_digest.py +0 -0
  692. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_single_import_root.py +0 -0
  693. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_skill_agent_binding.py +0 -0
  694. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_skill_catalog.py +0 -0
  695. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_skill_loader.py +0 -0
  696. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_spreadsheet_tools.py +0 -0
  697. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_sse_stream_contract.py +0 -0
  698. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_startup_dashboard.py +0 -0
  699. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_startup_latency.py +0 -0
  700. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_streaming_pipeline.py +0 -0
  701. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_stripe_agent.py +0 -0
  702. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_subagent.py +0 -0
  703. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_supervisor_routing.py +0 -0
  704. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_system_prompts.py +0 -0
  705. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_system_tools_output.py +0 -0
  706. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_task_orchestrator.py +0 -0
  707. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_team_synthesis.py +0 -0
  708. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_tls_trust_store.py +0 -0
  709. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_tool_policy.py +0 -0
  710. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_tool_rounds_on_openai_apis.py +0 -0
  711. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_tool_scope.py +0 -0
  712. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_trading_service.py +0 -0
  713. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_tradingview_bridge.py +0 -0
  714. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_turn_planning.py +0 -0
  715. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_ui_completer_references.py +0 -0
  716. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_ui_console_theme.py +0 -0
  717. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_ui_input_box.py +0 -0
  718. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_ui_language_and_model.py +0 -0
  719. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_ui_robot_banner.py +0 -0
  720. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_update_health_routes.py +0 -0
  721. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_verification_hint.py +0 -0
  722. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_verification_policy.py +0 -0
  723. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_version_consistency.py +0 -0
  724. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_version_counter.py +0 -0
  725. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_video_analysis.py +0 -0
  726. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_video_editor.py +0 -0
  727. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_vscode_mcp.py +0 -0
  728. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_warehouse_agents.py +0 -0
  729. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_warehouse_cli_registration.py +0 -0
  730. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_warehouse_erp_client.py +0 -0
  731. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_warehouse_workflow.py +0 -0
  732. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_wheel_is_installable.py +0 -0
  733. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_workspace_changes.py +0 -0
  734. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_workspace_context.py +0 -0
  735. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_workspace_files.py +0 -0
  736. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_workspace_scope.py +0 -0
  737. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_workspace_service.py +0 -0
  738. {aria_code-0.79.0 → aria_code-0.81.0}/tests/test_workspace_verify.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aria-code
3
- Version: 0.79.0
3
+ Version: 0.81.0
4
4
  Summary: Open-source AI agent for coding, financial analysis and logistics operations: numbers you can check, client data kept apart, actions a person approves
5
5
  License: Apache-2.0
6
6
  Project-URL: Homepage, https://github.com/artheras/aria-code
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "aria-code"
7
- version = "0.79.0"
7
+ version = "0.81.0"
8
8
  description = "Open-source AI agent for coding, financial analysis and logistics operations: numbers you can check, client data kept apart, actions a person approves"
9
9
  readme = "README.md"
10
10
  license = { text = "Apache-2.0" }
@@ -17,4 +17,4 @@ from __future__ import annotations
17
17
 
18
18
  __all__ = ["__version__"]
19
19
 
20
- __version__ = "0.79.0"
20
+ __version__ = "0.81.0"
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from aria_code.apps.cli.commands.market import parse_analysis_args
6
+ from aria_code.apps.cli.commands.market_context import context_has_price
6
7
 
7
8
 
8
9
  import logging
@@ -121,7 +122,11 @@ class AnalysisCommandsMixin:
121
122
  label = "Focus on" if response_lang == "en" else "重点分析"
122
123
  ctx += f"\n\n### {heading}\n- {label}: {parsed.focus}"
123
124
 
124
- await self.terminal.send_message(build_analyze_prompt(symbol, ctx, is_cn, response_lang=response_lang))
125
+ # The prompt carries the fetched data, so the evidence gate must not
126
+ # refuse the answer for want of a tool call: "analyze Apple stock"
127
+ # lands here, and on the backend route there are no tools to call.
128
+ await self.terminal.send_message(build_analyze_prompt(symbol, ctx, is_cn, response_lang=response_lang),
129
+ evidence_grounded=context_has_price(ctx))
125
130
  try:
126
131
  _resp = next((m["content"] for m in reversed(self.terminal.conversation)
127
132
  if m.get("role") == "assistant" and m.get("content")), "")
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import asyncio
6
6
  import logging
7
+ import re
7
8
  import time
8
9
  from typing import Any, Callable, Optional
9
10
 
@@ -14,6 +15,12 @@ TA_SESSION_CACHE: dict[str, dict[str, Any]] = {}
14
15
  TA_SESSION_CACHE_TTL = 600
15
16
 
16
17
 
18
+ def context_has_price(context: str) -> bool:
19
+ """Whether an /analyze context carries a fetched price — the header line
20
+ build_analyze_context writes as "- Price: 333.69" ("- 价格: 333.69")."""
21
+ return re.search(r"^- (?:Price|价格): \d", context or "", re.MULTILINE) is not None
22
+
23
+
17
24
  def _cached_ta(symbol: str) -> dict[str, Any]:
18
25
  cached = TA_SESSION_CACHE.get(symbol)
19
26
  if cached and (time.time() - float(cached.get("ts", 0))) < TA_SESSION_CACHE_TTL:
@@ -26,6 +26,7 @@ from aria_code.apps.cli.utils.market_detect import (
26
26
  _is_realty_query,
27
27
  _is_stock_chart_analysis_request,
28
28
  )
29
+ from aria_code.packages.aria_services.research_protocol import requires_financial_evidence
29
30
 
30
31
 
31
32
  BrokerRegistryFactory = Callable[[], Any]
@@ -178,8 +179,13 @@ def run_deterministic_chain(
178
179
  if not deterministic.get("success") and not config.model_has_tools:
179
180
  deterministic = _try_handle_market_overview(message)
180
181
 
182
+ # The evidence gate refuses a market answer given without data, and a
183
+ # model with no tools cannot fetch any — so whatever the gate will demand
184
+ # data for is fetched here, in any wording ("How's NVDA this week?" as
185
+ # well as "分析苹果股票").
181
186
  if not deterministic.get("success") and not config.model_has_tools:
182
- deterministic = _try_handle_market_snapshot_analysis(message, history=history)
187
+ deterministic = _try_handle_market_snapshot_analysis(
188
+ message, history=history, evidence_required=requires_financial_evidence(message))
183
189
 
184
190
  return deterministic
185
191
 
@@ -7,6 +7,7 @@ _HAS_MDC and _get_mdc are resolved via lazy import to avoid circular deps.
7
7
  from __future__ import annotations
8
8
  import json
9
9
  import os
10
+ import re
10
11
  import sys
11
12
  from datetime import datetime
12
13
  from pathlib import Path
@@ -22,6 +23,7 @@ from aria_code.apps.cli.utils.market_detect import (
22
23
  _detect_market_overview,
23
24
  _PRIVATE_COMPANY_PROFILES,
24
25
  )
26
+ from aria_code.apps.cli.market_hours import market_session
25
27
  from aria_code.apps.cli.market_metadata import enrich_market_quote, market_display_label
26
28
  from aria_code.packages.aria_core.paths import aria_home
27
29
 
@@ -133,6 +135,14 @@ def _snapshot_signal(price, change_pct, rsi, macd_hist, ma20, ma60) -> tuple[str
133
135
  return signal, score, confidence, label
134
136
 
135
137
 
138
+ # _snapshot_signal's labels, for a reply in English.
139
+ _SIGNAL_LABELS_EN = {
140
+ "强势多头": "strongly bullish", "偏多": "bullish", "短线偏强": "short-term firm",
141
+ "震荡观察": "range-bound", "短线偏弱": "short-term soft", "偏空": "bearish",
142
+ "强势空头": "strongly bearish", "指标不足": "insufficient data",
143
+ }
144
+
145
+
136
146
  def _support_resistance_for_row(currency: str, price, ma20, ma60, bb_lower, bb_upper) -> tuple[str, str]:
137
147
  p = _num_or_none(price)
138
148
  if p is None:
@@ -374,7 +384,7 @@ def _append_timeframe_levels(
374
384
  raw_name = str(row.get("name") or "—")
375
385
  name = _timeframe_display_name(raw_name, english=english)
376
386
  source = _timeframe_source_label(str(row.get("source") or ""), english=english)
377
- horizon = str(row.get("horizon") or "—")
387
+ horizon = _horizon_label(str(row.get("horizon") or "—"), english=english)
378
388
  support = row.get("support") or []
379
389
  resistance = row.get("resistance") or []
380
390
  action = _level_action_line(name, support, resistance, currency, english=english)
@@ -397,6 +407,18 @@ def _append_timeframe_levels(
397
407
  lines.append(f" - 用法:{action}")
398
408
 
399
409
 
410
+ _HORIZON_UNITS_EN = {"日": "days", "周": "weeks", "月": "months"}
411
+
412
+
413
+ def _horizon_label(horizon: str, *, english: bool) -> str:
414
+ if not english:
415
+ return horizon
416
+ if horizon == "快照":
417
+ return "snapshot"
418
+ match = re.fullmatch(r"\s*(\d+\s*-\s*\d+)\s*([日周月])\s*", horizon)
419
+ return f"{match.group(1)} {_HORIZON_UNITS_EN[match.group(2)]}" if match else horizon
420
+
421
+
400
422
  def _build_timeframe_levels(
401
423
  mdc,
402
424
  symbol: str,
@@ -1058,6 +1080,8 @@ def _try_handle_multi_market_snapshot(message: str, symbols: list[str]) -> dict:
1058
1080
  macd_text = f"{row['macd_hist']:.4f}" if row.get("macd_hist") is not None else "—"
1059
1081
  sig = row.get("signal") or "—"
1060
1082
  sig_label = row.get("signal_label") or ""
1083
+ if _en:
1084
+ sig_label = _SIGNAL_LABELS_EN.get(sig_label, sig_label)
1061
1085
  sig_text = f"{sig} / {sig_label}" if sig_label and sig != "—" else sig
1062
1086
  table.append(
1063
1087
  f"| {row['symbol']} | {row.get('name') or row['symbol']} | {price} | "
@@ -1104,6 +1128,8 @@ def _try_handle_multi_market_snapshot(message: str, symbols: list[str]) -> dict:
1104
1128
  vol = _fmt_int(row.get("volume")) if row.get("volume") else ""
1105
1129
  sig = row.get("signal") or "—"
1106
1130
  sig_label = row.get("signal_label") or "指标不足"
1131
+ if _en:
1132
+ sig_label = _SIGNAL_LABELS_EN.get(sig_label, sig_label)
1107
1133
  score = int(row.get("signal_score") or 0)
1108
1134
  conf = float(row.get("signal_confidence") or 0)
1109
1135
  table.append("")
@@ -1417,14 +1443,18 @@ def _try_handle_market_overview(message: str) -> dict:
1417
1443
  "tools_used": ["market_overview"]}
1418
1444
 
1419
1445
 
1420
- def _try_handle_market_snapshot_analysis(message: str, history: list = None) -> dict:
1446
+ def _try_handle_market_snapshot_analysis(message: str, history: list = None, *,
1447
+ evidence_required: bool = False) -> dict:
1421
1448
  """Deterministic path for simple market analysis.
1422
1449
 
1423
1450
  Local small models tend to mangle injected quote fields into fragments like
1424
1451
  "N/A/N/A/-1.24%". For snapshot requests, format the data directly.
1452
+ ``evidence_required``: see ``_is_market_snapshot_request``.
1425
1453
  """
1426
- if not _is_market_snapshot_request(message, history):
1454
+ if not _is_market_snapshot_request(message, history, evidence_required=evidence_required):
1427
1455
  return {"success": False, "error": "not_market_snapshot"}
1456
+ # The reply is in the language of the question, failures included.
1457
+ _en = _detect_lang(message) == "en"
1428
1458
 
1429
1459
  _etf_symbols = _resolve_etf_snapshot_symbols(message)
1430
1460
  if len(_etf_symbols) >= 2:
@@ -1447,6 +1477,15 @@ def _try_handle_market_snapshot_analysis(message: str, history: list = None) ->
1447
1477
  return {
1448
1478
  "success": True,
1449
1479
  "response": (
1480
+ "## ❓ Unrecognised stock\n\n"
1481
+ "The company or brand in your message did not resolve to a known ticker.\n\n"
1482
+ "Try again with the ticker, for example:\n"
1483
+ "- China A-shares: `/quote 600519` (Kweichow Moutai)\n"
1484
+ "- Hong Kong: `/quote 0700.HK` (Tencent)\n"
1485
+ "- US: `/quote AAPL`\n"
1486
+ "- Europe: `/quote MC.PA` (LVMH)\n\n"
1487
+ "*Tip: `/ta <ticker>` gives the full technical analysis.*"
1488
+ ) if _en else (
1450
1489
  "## ❓ 无法识别的股票\n\n"
1451
1490
  "未能将消息中提到的公司/品牌解析为已知股票代码。\n\n"
1452
1491
  "请提供具体代码后重试,例如:\n"
@@ -1474,6 +1513,10 @@ def _try_handle_market_snapshot_analysis(message: str, history: list = None) ->
1474
1513
  return {
1475
1514
  "success": True,
1476
1515
  "response": (
1516
+ f"## {symbol} market snapshot\n\n"
1517
+ "The local market data client is not loaded, so there is no live quote.\n\n"
1518
+ f"Run `/quote {symbol}` to retry."
1519
+ ) if _en else (
1477
1520
  f"## {symbol} 市场快照\n\n"
1478
1521
  "当前本地行情客户端未加载,无法获取实时行情。\n\n"
1479
1522
  f"可运行 `/quote {symbol}` 重试。"
@@ -1485,18 +1528,22 @@ def _try_handle_market_snapshot_analysis(message: str, history: list = None) ->
1485
1528
  import time as _time_snap
1486
1529
 
1487
1530
  def _clean_network_error(raw: str) -> str:
1488
- """Convert raw exception strings to readable Chinese messages."""
1531
+ """Convert raw exception strings to readable messages."""
1489
1532
  if "Connection aborted" in raw or "RemoteDisconnected" in raw:
1490
- return "网络连接被中断(服务器关闭连接),请稍后重试"
1533
+ return ("the server closed the connection; try again shortly" if _en
1534
+ else "网络连接被中断(服务器关闭连接),请稍后重试")
1491
1535
  if "Connection refused" in raw:
1492
- return "连接被拒绝,数据服务暂时不可用"
1536
+ return ("connection refused; the data service is unavailable for now" if _en
1537
+ else "连接被拒绝,数据服务暂时不可用")
1493
1538
  if "timeout" in raw.lower() or "timed out" in raw.lower():
1494
- return "连接超时,请稍后重试"
1539
+ return "the connection timed out; try again shortly" if _en else "连接超时,请稍后重试"
1495
1540
  if "NoneType" in raw or raw.strip() in ("None", ""):
1496
- return "数据源未返回有效价格"
1541
+ return _no_price
1497
1542
  return raw
1498
1543
 
1499
- quote = {"success": False, "error": "未初始化"}
1544
+ _no_price = "the data source returned no valid price" if _en else "当前数据源未返回有效价格"
1545
+
1546
+ quote = {"success": False, "error": "not initialised" if _en else "未初始化"}
1500
1547
  _snapshot_quality = {}
1501
1548
  import contextlib as _ctxlib_snapshot
1502
1549
  import io as _io_snapshot
@@ -1653,20 +1700,26 @@ def _try_handle_market_snapshot_analysis(message: str, history: list = None) ->
1653
1700
  price = _num(quote.get("price"))
1654
1701
 
1655
1702
  if not quote.get("success") or price is None or price == 0:
1656
- err = quote.get("error") or "当前数据源未返回有效价格"
1703
+ err = quote.get("error") or _no_price
1657
1704
  if "NoneType" in str(err):
1658
- err = "当前数据源未返回有效价格"
1705
+ err = _no_price
1659
1706
  is_rate_limit = "rate" in str(err).lower() or "429" in str(err) or "too many" in str(err).lower()
1660
1707
  if is_rate_limit:
1661
1708
  if _fh_tried:
1662
1709
  # Finnhub was tried but also failed — both sources exhausted
1663
- _hint = "\n\n[提示] yfinance 和 Finnhub 均触发频率限制,请稍等 30 秒后重试。"
1710
+ _hint = ("\n\n[Note] yfinance and Finnhub are both rate-limited; wait 30 seconds and retry."
1711
+ if _en else "\n\n[提示] yfinance 和 Finnhub 均触发频率限制,请稍等 30 秒后重试。")
1664
1712
  elif _fh_key:
1665
1713
  # Key configured but Finnhub wasn't tried (shouldn't happen, but defensive)
1666
- _hint = "\n\n[提示] 数据源请求频率受限,请稍等 30 秒后重试。"
1714
+ _hint = ("\n\n[Note] The data source is rate-limited; wait 30 seconds and retry."
1715
+ if _en else "\n\n[提示] 数据源请求频率受限,请稍等 30 秒后重试。")
1667
1716
  else:
1668
1717
  # No Finnhub key — suggest configuring one
1669
1718
  _hint = (
1719
+ "\n\n[Note] The data source is rate-limited: wait 30 seconds and retry, "
1720
+ "or add a Finnhub key as a fallback source: `/apikey set finnhub <key>` "
1721
+ "(sign up: https://finnhub.io/register)"
1722
+ ) if _en else (
1670
1723
  "\n\n[提示] 数据源请求频率受限:请稍等 30 秒后重试,"
1671
1724
  "或配置 Finnhub key 使用备用数据源:`/apikey set finnhub <key>`"
1672
1725
  "(注册:https://finnhub.io/register)"
@@ -1676,6 +1729,10 @@ def _try_handle_market_snapshot_analysis(message: str, history: list = None) ->
1676
1729
  return {
1677
1730
  "success": True,
1678
1731
  "response": (
1732
+ f"## {symbol} market snapshot\n\n"
1733
+ f"No valid quote right now: {err}{_hint}\n\n"
1734
+ f"Run `/quote {symbol}` to retry; RSI, MACD and support/resistance are withheld until data is back."
1735
+ ) if _en else (
1679
1736
  f"## {symbol} 市场快照\n\n"
1680
1737
  f"当前无法获取有效行情:{err}{_hint}\n\n"
1681
1738
  f"可运行 `/quote {symbol}` 重试;在数据恢复前不输出 RSI、MACD 或支撑/阻力位。"
@@ -2085,22 +2142,8 @@ def _try_handle_market_snapshot_analysis(message: str, history: list = None) ->
2085
2142
  _price_pos = int((price - low) / _range_size * 100) if _range_size and _range_size > 0 else None
2086
2143
  _swing_pct = round(_range_size / price * 100, 2) if _range_size and price else None
2087
2144
  _chg_abs = abs(chg) if chg is not None else None
2088
- _pa_lines = []
2089
- if _price_pos is not None:
2090
- _pos_label = "日内高位" if _price_pos >= 70 else ("日内低位" if _price_pos <= 30 else "日内中段")
2091
- _pa_lines.append(f"价格位置:{_pos_label}(日内第 {_price_pos} 百分位)")
2092
- if _swing_pct:
2093
- _pa_lines.append(f"日内振幅:{_swing_pct:.1f}%{'(波动偏大)' if _swing_pct > 3 else ''}")
2094
- if chg is not None and _chg_abs is not None:
2095
- if _chg_abs < 0.01:
2096
- _pa_lines.append("今日动能:持平")
2097
- else:
2098
- _mo = "上涨" if chg > 0 else "下跌"
2099
- _strength = "(大幅)" if _chg_abs > 2 else ("(温和)" if _chg_abs < 0.5 else "")
2100
- _pa_lines.append(f"今日动能:{_mo} {_chg_abs:.2f}%{_strength}")
2101
2145
 
2102
2146
  # ── Build output ──────────────────────────────────────────────────────
2103
- weekday = datetime.now().weekday()
2104
2147
  ti_provider = ti.get("provider", "")
2105
2148
  quote_chain = quote.get("provider_chain") or [provider]
2106
2149
  data_src = " -> ".join(str(p) for p in quote_chain if p)
@@ -2117,8 +2160,11 @@ def _try_handle_market_snapshot_analysis(message: str, history: list = None) ->
2117
2160
  signal_str = _SIGNAL_LABELS.get(_lang, _SIGNAL_LABELS["zh"])[_sig_key]
2118
2161
  _L = {
2119
2162
  "disclaimer": "Not investment advice" if _en else "不构成投资建议",
2120
- "after_hours": "After-hours" if _en else "休市/盘后",
2121
- "market_open": "Market open" if _en else "盘中",
2163
+ "session_open": "Market open" if _en else "盘中",
2164
+ "session_pre": "Pre-market" if _en else "盘前",
2165
+ "session_post": "After-hours" if _en else "盘后",
2166
+ "session_closed": "Market closed" if _en else "休市",
2167
+ "session_24/7": "24/7 market" if _en else "全天交易",
2122
2168
  "price_hdr": "Metric" if _en else "指标",
2123
2169
  "value_hdr": "Value" if _en else "数值",
2124
2170
  "latest": "Last price" if _en else "最新价",
@@ -2163,7 +2209,7 @@ def _try_handle_market_snapshot_analysis(message: str, history: list = None) ->
2163
2209
  "pos_low": "Lower range" if _en else "日内低位",
2164
2210
  "pos_mid": "Mid range" if _en else "日内中段",
2165
2211
  "pos_pct": "day percentile" if _en else "百分位",
2166
- "swing_high": "(high volatility)" if _en else "(波动偏大)",
2212
+ "swing_high": " (high volatility)" if _en else "(波动偏大)",
2167
2213
  "flat": "Flat" if _en else "持平",
2168
2214
  "rising": "Up" if _en else "上涨",
2169
2215
  "falling": "Down" if _en else "下跌",
@@ -2174,7 +2220,10 @@ def _try_handle_market_snapshot_analysis(message: str, history: list = None) ->
2174
2220
  "day_swing": "Day swing" if _en else "日内振幅",
2175
2221
  }
2176
2222
 
2177
- session_note = _L["after_hours"] if weekday >= 5 else _L["market_open"]
2223
+ _sep = ": " if _en else ":"
2224
+ # On the exchange's clock, not this machine's; nothing when it is unknown.
2225
+ _session = market_session(symbol)
2226
+ session_note = _L.get(f"session_{_session}", "") if _session else ""
2178
2227
 
2179
2228
  def _money(v: float | int | None) -> str:
2180
2229
  try:
@@ -2270,10 +2319,10 @@ def _try_handle_market_snapshot_analysis(message: str, history: list = None) ->
2270
2319
  lines.append(f"## {_header_name} `{symbol}`")
2271
2320
  else:
2272
2321
  lines.append(f"## `{symbol}`")
2273
- lines.append(f"*{data_src} · {_now_str} · {session_note} · {_L['disclaimer']}*")
2322
+ lines.append("*" + " · ".join(p for p in (data_src, _now_str, session_note, _L["disclaimer"]) if p) + "*")
2274
2323
  lines.append("")
2275
- lines.append(f"**{'Takeaway' if _en else '结论'}**:{_summary_line}")
2276
- lines.append(f"**{'Watch' if _en else '观察位'}**:{_watch_line}")
2324
+ lines.append(f"**{'Takeaway' if _en else '结论'}**{_sep}{_summary_line}")
2325
+ lines.append(f"**{'Watch' if _en else '观察位'}**{_sep}{_watch_line}")
2277
2326
  lines.append("")
2278
2327
 
2279
2328
  # ── Price table ──
@@ -2295,7 +2344,8 @@ def _try_handle_market_snapshot_analysis(message: str, history: list = None) ->
2295
2344
  lines.append("|---------|------|------|")
2296
2345
  if rsi is not None:
2297
2346
  _rsi_meaning = _L["overbought"] if rsi >= 70 else (_L["oversold"] if rsi <= 30 else _L["neutral"])
2298
- lines.append(f"| RSI(14) | {rsi_view} | {_rsi_meaning} |")
2347
+ # rsi_view carries a Chinese gloss; the Meaning column says it in English.
2348
+ lines.append(f"| RSI(14) | {f'{rsi:.1f}' if _en else rsi_view} | {_rsi_meaning} |")
2299
2349
  else:
2300
2350
  lines.append("| RSI(14) | — | — |")
2301
2351
  if mhist is not None:
@@ -2318,17 +2368,19 @@ def _try_handle_market_snapshot_analysis(message: str, history: list = None) ->
2318
2368
  _pa_lines_l10n = []
2319
2369
  if _price_pos is not None:
2320
2370
  _pos_label = _L["pos_high"] if _price_pos >= 70 else (_L["pos_low"] if _price_pos <= 30 else _L["pos_mid"])
2321
- _pa_lines_l10n.append(f"{_L['day_pos']}:{_pos_label}({_en and 'day' or '日内第'} {_price_pos} {_L['pos_pct']})")
2371
+ _pa_lines_l10n.append(
2372
+ f"{_L['day_pos']}: {_pos_label} ({_price_pos}th percentile of the day's range)" if _en else
2373
+ f"{_L['day_pos']}:{_pos_label}(日内第 {_price_pos} {_L['pos_pct']})")
2322
2374
  if _swing_pct:
2323
2375
  _swing_note = _L["swing_high"] if _swing_pct > 3 else ""
2324
- _pa_lines_l10n.append(f"{_L['day_swing']}:{_swing_pct:.1f}%{_swing_note}")
2376
+ _pa_lines_l10n.append(f"{_L['day_swing']}{_sep}{_swing_pct:.1f}%{_swing_note}")
2325
2377
  if chg is not None and _chg_abs is not None:
2326
2378
  if _chg_abs < 0.01:
2327
- _pa_lines_l10n.append(f"{_L['day_momentum']}:{_L['flat']}")
2379
+ _pa_lines_l10n.append(f"{_L['day_momentum']}{_sep}{_L['flat']}")
2328
2380
  else:
2329
2381
  _mo = _L["rising"] if chg > 0 else _L["falling"]
2330
2382
  _strength = _L["strong"] if _chg_abs > 2 else (_L["mild"] if _chg_abs < 0.5 else "")
2331
- _pa_lines_l10n.append(f"{_L['day_momentum']}:{_mo} {_chg_abs:.2f}%{_strength}")
2383
+ _pa_lines_l10n.append(f"{_L['day_momentum']}{_sep}{_mo} {_chg_abs:.2f}%{_strength}")
2332
2384
 
2333
2385
  # ── Signal ──
2334
2386
  lines.append("")
@@ -2338,7 +2390,7 @@ def _try_handle_market_snapshot_analysis(message: str, history: list = None) ->
2338
2390
  if _en else
2339
2391
  f" · 量化分 {_signal_score:+d} · 置信度 {_signal_confidence:.0%}"
2340
2392
  )
2341
- lines.append(f"{_L['signal_lbl']}:`{signal}` — {signal_str}{_score_detail}")
2393
+ lines.append(f"{_L['signal_lbl']}{_sep}`{signal}` — {signal_str}{_score_detail}")
2342
2394
  _reason_parts = []
2343
2395
  if _positive_reasons:
2344
2396
  _reason_parts.append(("support: " if _en else "支撑:") + _join_reasons(_positive_reasons[:3]))
@@ -2347,13 +2399,13 @@ def _try_handle_market_snapshot_analysis(message: str, history: list = None) ->
2347
2399
  if _neutral_reasons:
2348
2400
  _reason_parts.append(("neutral: " if _en else "中性:") + _join_reasons(_neutral_reasons[:2]))
2349
2401
  if _reason_parts:
2350
- lines.append(f"**{'Signal drivers' if _en else '信号拆解'}**:" + ("; ".join(_reason_parts) if _en else ";".join(_reason_parts)))
2402
+ lines.append(f"**{'Signal drivers' if _en else '信号拆解'}**{_sep}" + ("; ".join(_reason_parts) if _en else ";".join(_reason_parts)))
2351
2403
  else:
2352
2404
  lines.append(_L["pa_hdr"])
2353
2405
  for _pal in _pa_lines_l10n:
2354
2406
  lines.append(f"- {_pal}")
2355
2407
  lines.append("")
2356
- lines.append(f"{_L['signal_lbl']}:`{signal}` — {_L['sig_no_ta']}")
2408
+ lines.append(f"{_L['signal_lbl']}{_sep}`{signal}` — {_L['sig_no_ta']}")
2357
2409
 
2358
2410
  # ── Config hint (show only when TA missing) ──
2359
2411
  if not _enough_data:
@@ -0,0 +1,100 @@
1
+ """Whether a symbol's exchange is in session, judged on the exchange's clock.
2
+
3
+ Two places judged it on the clock of the machine running Aria. The snapshot
4
+ header said "Market open" on any local weekday, so at 09:00 on Monday in
5
+ Shanghai — Sunday evening in New York — AAPL was "Market open". The context
6
+ sent to the model compared local hours with New York's 09:30–16:00, so a user
7
+ in Beijing had the US market "open" through the New York night.
8
+
9
+ Exchange holidays are not known here: on a holiday the usual hours still read
10
+ as a session. An unknown exchange, or a time zone this machine lacks, gives
11
+ ``None``, and callers then say nothing rather than guess.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import re
17
+ from datetime import datetime, time, timezone
18
+
19
+ try:
20
+ from zoneinfo import ZoneInfo
21
+ except ImportError: # pragma: no cover - Python < 3.9
22
+ ZoneInfo = None # type: ignore[assignment]
23
+
24
+ _EU = ((time(9, 0), time(17, 30)),)
25
+
26
+ # Exchange -> (time zone, regular sessions in local time).
27
+ _EXCHANGES: dict[str, tuple[str, tuple[tuple[time, time], ...]]] = {
28
+ "US": ("America/New_York", ((time(9, 30), time(16, 0)),)),
29
+ "CN": ("Asia/Shanghai", ((time(9, 30), time(11, 30)), (time(13, 0), time(15, 0)))),
30
+ "HK": ("Asia/Hong_Kong", ((time(9, 30), time(12, 0)), (time(13, 0), time(16, 0)))),
31
+ "JP": ("Asia/Tokyo", ((time(9, 0), time(11, 30)), (time(12, 30), time(15, 30)))),
32
+ "UK": ("Europe/London", ((time(8, 0), time(16, 30)),)),
33
+ "FR": ("Europe/Paris", _EU),
34
+ "DE": ("Europe/Berlin", _EU),
35
+ "NL": ("Europe/Amsterdam", _EU),
36
+ "IT": ("Europe/Rome", _EU),
37
+ "ES": ("Europe/Madrid", _EU),
38
+ }
39
+
40
+ _SUFFIXES = {
41
+ ".HK": "HK", ".SS": "CN", ".SZ": "CN", ".SH": "CN", ".T": "JP", ".L": "UK",
42
+ ".PA": "FR", ".DE": "DE", ".AS": "NL", ".MI": "IT", ".MC": "ES",
43
+ }
44
+
45
+ # US extended hours, New York time.
46
+ _US_PRE = (time(4, 0), time(9, 30))
47
+ _US_POST = (time(16, 0), time(20, 0))
48
+
49
+
50
+ def exchange_for(symbol: str) -> str | None:
51
+ """"US", "CN", "HK", … for a symbol; "CRYPTO" for a coin pair; None if unknown."""
52
+ s = str(symbol or "").strip().upper()
53
+ if not s or s.startswith("^") or s.endswith(("=X", "=F")):
54
+ return None
55
+ if re.fullmatch(r"[A-Z0-9]{2,10}-(USD|USDT|USDC|EUR)", s):
56
+ return "CRYPTO"
57
+ for suffix, exchange in _SUFFIXES.items():
58
+ if s.endswith(suffix):
59
+ return exchange
60
+ if re.fullmatch(r"(SH|SZ)?\d{6}", s):
61
+ return "CN"
62
+ if re.fullmatch(r"[A-Z]{1,5}([.-][A-Z])?", s):
63
+ return "US"
64
+ return None
65
+
66
+
67
+ def _local_now(exchange: str, now: datetime | None) -> datetime | None:
68
+ if ZoneInfo is None:
69
+ return None
70
+ try:
71
+ zone = ZoneInfo(_EXCHANGES[exchange][0])
72
+ except Exception: # no tz database on this machine
73
+ return None
74
+ moment = now or datetime.now(timezone.utc)
75
+ if moment.tzinfo is None:
76
+ moment = moment.astimezone() # a naive time is this machine's local time
77
+ return moment.astimezone(zone)
78
+
79
+
80
+ def market_session(symbol: str, now: datetime | None = None) -> str | None:
81
+ """"open", "pre", "post", "closed" or "24/7" for the symbol's exchange; None if unknown."""
82
+ exchange = exchange_for(symbol)
83
+ if exchange == "CRYPTO":
84
+ return "24/7"
85
+ if exchange is None:
86
+ return None
87
+ local = _local_now(exchange, now)
88
+ if local is None:
89
+ return None
90
+ if local.weekday() >= 5:
91
+ return "closed"
92
+ clock = local.time()
93
+ if any(start <= clock < end for start, end in _EXCHANGES[exchange][1]):
94
+ return "open"
95
+ if exchange == "US":
96
+ if _US_PRE[0] <= clock < _US_PRE[1]:
97
+ return "pre"
98
+ if _US_POST[0] <= clock < _US_POST[1]:
99
+ return "post"
100
+ return "closed"
@@ -1231,6 +1231,33 @@ def _is_blocked_market_symbol_candidate(symbol: str) -> bool:
1231
1231
  )
1232
1232
 
1233
1233
 
1234
+ def _is_english_function_word(message: str, match) -> bool:
1235
+ """"I" the pronoun and "A" the article, read as one-letter tickers.
1236
+
1237
+ "Should I sell my Tesla shares?" came back as a comparison of ``I`` and
1238
+ TSLA, and "I think AAPL is cheap" as a quote for ``I``. "A" is skipped only
1239
+ before a lowercase word ("A good time to buy MSFT?"), so "A股" is still
1240
+ the A-share market; F, T, C and the other one-letter tickers are untouched.
1241
+ """
1242
+ symbol = match.group(1)
1243
+ if symbol == "I":
1244
+ return True
1245
+ return symbol == "A" and _re_sym.match(r"A [a-z]", message[match.start(1):match.start(1) + 3]) is not None
1246
+
1247
+
1248
+ def _first_bare_ticker(pattern: str, message: str) -> str:
1249
+ """The first capitalised word the pattern finds, unless it is a blocked term.
1250
+
1251
+ English function words are passed over; a blocked term still ends the
1252
+ search, as it always has, so "Run the API tests for CI" stays no ticker.
1253
+ """
1254
+ for match in _re_sym.finditer(pattern, message):
1255
+ if _is_english_function_word(message, match):
1256
+ continue
1257
+ return "" if _is_blocked_market_symbol_candidate(match.group(1)) else match.group(1)
1258
+ return ""
1259
+
1260
+
1234
1261
  def _extract_market_symbol(message: str) -> str:
1235
1262
  """Extract a likely market symbol from Chinese company names or tickers."""
1236
1263
  resolved = _resolve_market_symbol(message)
@@ -1248,15 +1275,12 @@ def _extract_market_symbol(message: str) -> str:
1248
1275
  m = _re_sym.search(r'(?<![A-Za-z0-9])(\^[A-Z0-9]{2,10}|[A-Z]{2,8}=F|[A-Z]{6}=X|DX-Y\.NYB)(?![A-Za-z0-9])', message, _re_sym.I)
1249
1276
  if m:
1250
1277
  return m.group(1).upper()
1251
- m = _re_sym.search(r'\b([A-Z]{1,5}(?:\.(?:HK|SH|SZ))?)\b', message)
1252
- if m and not _is_blocked_market_symbol_candidate(m.group(1)):
1253
- return m.group(1)
1278
+ symbol = _first_bare_ticker(r'\b([A-Z]{1,5}(?:\.(?:HK|SH|SZ))?)\b', message)
1279
+ if symbol:
1280
+ return symbol
1254
1281
  # Chinese text immediately after a ticker ("AAPL的市场") prevents \b from
1255
1282
  # matching because Unicode word-boundary rules treat 的 as a word char.
1256
- m = _re_sym.search(r'(?<![A-Za-z])([A-Z]{1,5}(?:\.(?:HK|SH|SZ))?)(?![A-Za-z])', message)
1257
- if m and not _is_blocked_market_symbol_candidate(m.group(1)):
1258
- return m.group(1)
1259
- return ""
1283
+ return _first_bare_ticker(r'(?<![A-Za-z])([A-Z]{1,5}(?:\.(?:HK|SH|SZ))?)(?![A-Za-z])', message)
1260
1284
 
1261
1285
  def _extract_market_symbols(message: str, limit: int = 6) -> list[str]:
1262
1286
  """Extract all likely market symbols, preserving mention order."""
@@ -1289,12 +1313,12 @@ def _extract_market_symbols(message: str, limit: int = 6) -> list[str]:
1289
1313
 
1290
1314
  for match in _re_sym.finditer(r'\b([A-Z]{1,5}(?:\.(?:HK|SH|SZ))?)\b', message):
1291
1315
  symbol = match.group(1)
1292
- if not _is_blocked_market_symbol_candidate(symbol):
1316
+ if not _is_blocked_market_symbol_candidate(symbol) and not _is_english_function_word(message, match):
1293
1317
  add_hit(match.start(), symbol)
1294
1318
 
1295
1319
  for match in _re_sym.finditer(r'(?<![A-Za-z])([A-Z]{1,5}(?:\.(?:HK|SH|SZ))?)(?![A-Za-z])', message):
1296
1320
  symbol = match.group(1)
1297
- if not _is_blocked_market_symbol_candidate(symbol):
1321
+ if not _is_blocked_market_symbol_candidate(symbol) and not _is_english_function_word(message, match):
1298
1322
  add_hit(match.start(), symbol)
1299
1323
 
1300
1324
  ordered: list[str] = []
@@ -1507,12 +1531,19 @@ def _detect_market_overview(message: str):
1507
1531
  return None
1508
1532
 
1509
1533
 
1510
- def _is_market_snapshot_request(message: str, history: list = None) -> bool:
1534
+ def _is_market_snapshot_request(message: str, history: list = None, *,
1535
+ evidence_required: bool = False) -> bool:
1511
1536
  """Return True for simple quote / market snapshot analysis requests.
1512
1537
 
1513
1538
  跟进问题("现在的股票和趋势呢"):当前消息无标的时回溯会话历史继承。
1514
1539
  但如果消息中包含未能识别的公司名,则不视为跟进问题(不继承历史标的)。
1515
1540
  房价/楼市类问题直接拒绝,防止继承上一个股票代码。
1541
+
1542
+ ``evidence_required`` is the evidence gate's verdict on this message. When
1543
+ the gate will refuse an answer without data and the message names an
1544
+ instrument, it is a snapshot request whatever its wording: the word lists
1545
+ below were written for Chinese, so "How's NVDA this week?" matched none of
1546
+ them, nothing fetched data on a route without tools, and the gate refused.
1516
1547
  """
1517
1548
  # Real-estate questions must never be routed to the stock snapshot path
1518
1549
  if _is_realty_query(message):
@@ -1528,6 +1559,8 @@ def _is_market_snapshot_request(message: str, history: list = None) -> bool:
1528
1559
  _is_coding = any(k in message.lower() for k in _coding_kw)
1529
1560
  if _is_coding or _is_stock_chart_analysis_request(message) or _is_visual_market_artifact_request(message):
1530
1561
  return False
1562
+ if evidence_required and _extract_market_symbol(message):
1563
+ return True
1531
1564
  low = message.lower()
1532
1565
  # Unambiguously market-specific wording. These carry enough intent on their
1533
1566
  # own to inherit a symbol from an earlier turn ("行情呢" / "现价多少").