aria-code 0.167.0__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) hide show
  1. aria_bots/__init__.py +7 -0
  2. aria_bots/channels/README.md +97 -0
  3. aria_bots/channels/__init__.py +1 -0
  4. aria_bots/channels/approvals.py +263 -0
  5. aria_bots/channels/conversation.py +280 -0
  6. aria_bots/channels/digest.py +186 -0
  7. aria_bots/channels/registry.py +95 -0
  8. aria_bots/engine.py +144 -0
  9. aria_bots/feishu_bot.py +1385 -0
  10. aria_bots/logistics/__init__.py +1 -0
  11. aria_bots/logistics/carriers.py +253 -0
  12. aria_bots/logistics/freight.py +154 -0
  13. aria_bots/logistics/inventory.py +242 -0
  14. aria_bots/logistics/mcp_server.py +156 -0
  15. aria_bots/logistics/records.py +119 -0
  16. aria_bots/logistics/tenancy.py +152 -0
  17. aria_bots/market.py +91 -0
  18. aria_bots/relay_client.py +326 -0
  19. aria_bots/telegram_bot.py +299 -0
  20. aria_code/__init__.py +111 -0
  21. aria_code/_bin/aria-native.exe +0 -0
  22. aria_code/_bin/aria-runtime.exe +0 -0
  23. aria_code/_version.py +20 -0
  24. aria_code/account_memory.py +296 -0
  25. aria_code/account_session.py +166 -0
  26. aria_code/adk_apps/__init__.py +1 -0
  27. aria_code/adk_apps/aria_code_review/__init__.py +1 -0
  28. aria_code/adk_apps/aria_code_review/agent.py +32 -0
  29. aria_code/adk_apps/aria_research/__init__.py +1 -0
  30. aria_code/adk_apps/aria_research/agent.py +31 -0
  31. aria_code/agents/__init__.py +49 -0
  32. aria_code/agents/base.py +329 -0
  33. aria_code/agents/code_review.py +200 -0
  34. aria_code/agents/deep/__init__.py +37 -0
  35. aria_code/agents/deep/calibration_loop.py +144 -0
  36. aria_code/agents/deep/critic.py +125 -0
  37. aria_code/agents/deep/deepen.py +193 -0
  38. aria_code/agents/deep/models.py +149 -0
  39. aria_code/agents/deep/pipeline.py +164 -0
  40. aria_code/agents/deep/quant_fusion.py +192 -0
  41. aria_code/agents/deep/themes.py +95 -0
  42. aria_code/agents/deep/tiers.py +106 -0
  43. aria_code/agents/engineering/__init__.py +14 -0
  44. aria_code/agents/engineering/coder.py +222 -0
  45. aria_code/agents/engineering/tester.py +145 -0
  46. aria_code/agents/financial/__init__.py +21 -0
  47. aria_code/agents/financial/cashflow_burn.py +119 -0
  48. aria_code/agents/financial/catalyst.py +279 -0
  49. aria_code/agents/financial/corporate_finance.py +175 -0
  50. aria_code/agents/financial/debate.py +224 -0
  51. aria_code/agents/financial/earnings.py +315 -0
  52. aria_code/agents/financial/fundamental.py +178 -0
  53. aria_code/agents/financial/macro.py +111 -0
  54. aria_code/agents/financial/news.py +231 -0
  55. aria_code/agents/financial/risk.py +146 -0
  56. aria_code/agents/financial/sector.py +279 -0
  57. aria_code/agents/financial/strategist.py +121 -0
  58. aria_code/agents/financial/stripe_revenue.py +127 -0
  59. aria_code/agents/financial/synthesis.py +274 -0
  60. aria_code/agents/financial/technical.py +277 -0
  61. aria_code/agents/orchestrator.py +44 -0
  62. aria_code/agents/portfolio_agent.py +392 -0
  63. aria_code/agents/realty/__init__.py +62 -0
  64. aria_code/agents/realty/asset_diagnosis.py +152 -0
  65. aria_code/agents/realty/business_match.py +166 -0
  66. aria_code/agents/realty/cashflow_verify.py +209 -0
  67. aria_code/agents/realty/contract_rules.py +210 -0
  68. aria_code/agents/realty/energy_anomaly.py +189 -0
  69. aria_code/agents/realty/exit_settlement.py +208 -0
  70. aria_code/agents/realty/fulfillment_risk.py +206 -0
  71. aria_code/agents/realty/ops_optimize.py +160 -0
  72. aria_code/agents/realty/revenue_share.py +215 -0
  73. aria_code/agents/registry.py +168 -0
  74. aria_code/agents/signal_scheme.py +111 -0
  75. aria_code/agents/sports/__init__.py +0 -0
  76. aria_code/agents/sports/football_agent.py +197 -0
  77. aria_code/agents/supervisor.py +113 -0
  78. aria_code/agents/team.py +500 -0
  79. aria_code/agents/video/__init__.py +16 -0
  80. aria_code/agents/video/director.py +376 -0
  81. aria_code/agents/video/qa_agent.py +143 -0
  82. aria_code/agents/video/script_doctor.py +112 -0
  83. aria_code/agents/warehouse/__init__.py +25 -0
  84. aria_code/agents/warehouse/contracts.py +26 -0
  85. aria_code/agents/warehouse/dashboard.py +155 -0
  86. aria_code/agents/warehouse/fulfillment_leadtime.py +95 -0
  87. aria_code/agents/warehouse/inbound_exceptions.py +25 -0
  88. aria_code/agents/warehouse/inventory_health.py +24 -0
  89. aria_code/agents/warehouse/local_run.py +71 -0
  90. aria_code/agents/warehouse/local_snapshot.py +132 -0
  91. aria_code/agents/warehouse/logistics_cost.py +84 -0
  92. aria_code/agents/warehouse/logistics_sync.py +21 -0
  93. aria_code/agents/warehouse/navigation.schema.json +110 -0
  94. aria_code/agents/warehouse/task_agent.py +172 -0
  95. aria_code/agents/warehouse/workflow.py +31 -0
  96. aria_code/aliyun_data_client.py +4 -0
  97. aria_code/apps/README.md +12 -0
  98. aria_code/apps/__init__.py +2 -0
  99. aria_code/apps/channels/README.md +9 -0
  100. aria_code/apps/channels/__init__.py +17 -0
  101. aria_code/apps/channels/approvals.py +11 -0
  102. aria_code/apps/channels/conversation.py +11 -0
  103. aria_code/apps/channels/digest.py +11 -0
  104. aria_code/apps/channels/intake.py +92 -0
  105. aria_code/apps/channels/registry.py +11 -0
  106. aria_code/apps/channels/tradingview.py +94 -0
  107. aria_code/apps/cli/README.md +13 -0
  108. aria_code/apps/cli/__init__.py +2 -0
  109. aria_code/apps/cli/_optional.py +120 -0
  110. aria_code/apps/cli/app_server.py +656 -0
  111. aria_code/apps/cli/auto_update.py +125 -0
  112. aria_code/apps/cli/bootstrap.py +206 -0
  113. aria_code/apps/cli/broker_render.py +206 -0
  114. aria_code/apps/cli/chat_turn.py +1327 -0
  115. aria_code/apps/cli/cloud_models.py +231 -0
  116. aria_code/apps/cli/codegen_paths.py +29 -0
  117. aria_code/apps/cli/commands/__init__.py +34 -0
  118. aria_code/apps/cli/commands/_business_render.py +78 -0
  119. aria_code/apps/cli/commands/_ui.py +71 -0
  120. aria_code/apps/cli/commands/analysis_cmds.py +378 -0
  121. aria_code/apps/cli/commands/ashare_prediction_cmds.py +327 -0
  122. aria_code/apps/cli/commands/auth_cmds.py +215 -0
  123. aria_code/apps/cli/commands/backtest_cmds.py +2518 -0
  124. aria_code/apps/cli/commands/broker_cmds.py +1236 -0
  125. aria_code/apps/cli/commands/business_workflow_cmds.py +379 -0
  126. aria_code/apps/cli/commands/canvas_cmds.py +77 -0
  127. aria_code/apps/cli/commands/catalog.py +189 -0
  128. aria_code/apps/cli/commands/core_cmds.py +2748 -0
  129. aria_code/apps/cli/commands/data_cmds.py +521 -0
  130. aria_code/apps/cli/commands/diagnostic_cmds.py +285 -0
  131. aria_code/apps/cli/commands/diagnostic_ops_cmds.py +813 -0
  132. aria_code/apps/cli/commands/engineering_cmds.py +399 -0
  133. aria_code/apps/cli/commands/file_cmds.py +312 -0
  134. aria_code/apps/cli/commands/finance_service_cmds.py +60 -0
  135. aria_code/apps/cli/commands/fx_commodity_cmds.py +123 -0
  136. aria_code/apps/cli/commands/market.py +544 -0
  137. aria_code/apps/cli/commands/market_cmds.py +1419 -0
  138. aria_code/apps/cli/commands/market_context.py +432 -0
  139. aria_code/apps/cli/commands/market_render.py +7 -0
  140. aria_code/apps/cli/commands/model_cmds.py +2374 -0
  141. aria_code/apps/cli/commands/ops_cmds.py +721 -0
  142. aria_code/apps/cli/commands/orchestrator_cmds.py +181 -0
  143. aria_code/apps/cli/commands/pdf_export_cmds.py +125 -0
  144. aria_code/apps/cli/commands/portfolio_cmds.py +1316 -0
  145. aria_code/apps/cli/commands/report.py +476 -0
  146. aria_code/apps/cli/commands/scaffold_templates.py +617 -0
  147. aria_code/apps/cli/commands/session_cmds.py +236 -0
  148. aria_code/apps/cli/commands/session_ux_cmds.py +359 -0
  149. aria_code/apps/cli/commands/team.py +723 -0
  150. aria_code/apps/cli/commands/team_render.py +8 -0
  151. aria_code/apps/cli/commands/ui_cmds.py +401 -0
  152. aria_code/apps/cli/commands/warehouse_cmds.py +297 -0
  153. aria_code/apps/cli/commands/workflow_cmds.py +629 -0
  154. aria_code/apps/cli/commands/workspace_cmds.py +1543 -0
  155. aria_code/apps/cli/config_paths.py +73 -0
  156. aria_code/apps/cli/config_store.py +158 -0
  157. aria_code/apps/cli/constants.py +88 -0
  158. aria_code/apps/cli/context.py +34 -0
  159. aria_code/apps/cli/conversation_policy.py +53 -0
  160. aria_code/apps/cli/deterministic.py +200 -0
  161. aria_code/apps/cli/direct.py +48 -0
  162. aria_code/apps/cli/earnings_view.py +172 -0
  163. aria_code/apps/cli/endpoint_migration.py +64 -0
  164. aria_code/apps/cli/exec_events.py +255 -0
  165. aria_code/apps/cli/file_references.py +155 -0
  166. aria_code/apps/cli/finance_service_catalog.py +111 -0
  167. aria_code/apps/cli/football_reports.py +231 -0
  168. aria_code/apps/cli/github_app_auth.py +135 -0
  169. aria_code/apps/cli/google_login.py +239 -0
  170. aria_code/apps/cli/handlers/__init__.py +11 -0
  171. aria_code/apps/cli/handlers/broker_handlers.py +122 -0
  172. aria_code/apps/cli/handlers/chart_handlers.py +1314 -0
  173. aria_code/apps/cli/handlers/market_handlers.py +2570 -0
  174. aria_code/apps/cli/handlers/realty_handlers.py +114 -0
  175. aria_code/apps/cli/handlers/sports_handlers.py +22 -0
  176. aria_code/apps/cli/handlers/strategy_advice.py +82 -0
  177. aria_code/apps/cli/headless.py +352 -0
  178. aria_code/apps/cli/helpers.py +326 -0
  179. aria_code/apps/cli/hooks.py +180 -0
  180. aria_code/apps/cli/i18n.py +310 -0
  181. aria_code/apps/cli/intent.py +136 -0
  182. aria_code/apps/cli/intent_router.py +305 -0
  183. aria_code/apps/cli/intent_shadow.py +72 -0
  184. aria_code/apps/cli/intent_signals.py +347 -0
  185. aria_code/apps/cli/lifecycle_hooks.py +48 -0
  186. aria_code/apps/cli/local_tool_schemas.py +550 -0
  187. aria_code/apps/cli/main.py +39 -0
  188. aria_code/apps/cli/market_hours.py +100 -0
  189. aria_code/apps/cli/market_metadata.py +135 -0
  190. aria_code/apps/cli/market_universe.py +487 -0
  191. aria_code/apps/cli/message_processing.py +310 -0
  192. aria_code/apps/cli/mixin_binding.py +32 -0
  193. aria_code/apps/cli/model_catalog.py +652 -0
  194. aria_code/apps/cli/model_probe.py +169 -0
  195. aria_code/apps/cli/model_retirement.py +65 -0
  196. aria_code/apps/cli/native_branding.py +12 -0
  197. aria_code/apps/cli/native_bridge.py +118 -0
  198. aria_code/apps/cli/native_entry.py +58 -0
  199. aria_code/apps/cli/pdf_report.py +977 -0
  200. aria_code/apps/cli/plan_mode.py +139 -0
  201. aria_code/apps/cli/plotly_html.py +15 -0
  202. aria_code/apps/cli/prediction_feedback.py +202 -0
  203. aria_code/apps/cli/preflight.py +502 -0
  204. aria_code/apps/cli/project_aria.py +60 -0
  205. aria_code/apps/cli/prompt_assembly.py +78 -0
  206. aria_code/apps/cli/prompts/__init__.py +0 -0
  207. aria_code/apps/cli/prompts/coding.py +71 -0
  208. aria_code/apps/cli/prompts/select.py +193 -0
  209. aria_code/apps/cli/prompts/system_prompts.py +562 -0
  210. aria_code/apps/cli/prompts/ui.py +436 -0
  211. aria_code/apps/cli/provider_endpoints.py +237 -0
  212. aria_code/apps/cli/provider_keys.py +73 -0
  213. aria_code/apps/cli/providers/__init__.py +1 -0
  214. aria_code/apps/cli/providers/base.py +775 -0
  215. aria_code/apps/cli/providers/chat_routing.py +139 -0
  216. aria_code/apps/cli/providers/collaboration.py +98 -0
  217. aria_code/apps/cli/providers/llm/__init__.py +1 -0
  218. aria_code/apps/cli/providers/llm/offline_responses.py +68 -0
  219. aria_code/apps/cli/providers/llm/ollama_stream.py +1574 -0
  220. aria_code/apps/cli/providers/llm/response_cache.py +60 -0
  221. aria_code/apps/cli/providers/llm/sse_stream.py +298 -0
  222. aria_code/apps/cli/providers/runtime_bridge.py +586 -0
  223. aria_code/apps/cli/providers/vertexai_stream.py +592 -0
  224. aria_code/apps/cli/release_download.py +159 -0
  225. aria_code/apps/cli/review_runner.py +111 -0
  226. aria_code/apps/cli/runtime_consumer.py +769 -0
  227. aria_code/apps/cli/sandbox.py +32 -0
  228. aria_code/apps/cli/session_export.py +120 -0
  229. aria_code/apps/cli/session_jsonl.py +208 -0
  230. aria_code/apps/cli/session_refresh.py +123 -0
  231. aria_code/apps/cli/session_store.py +125 -0
  232. aria_code/apps/cli/skills_catalog.py +273 -0
  233. aria_code/apps/cli/task_isolation.py +211 -0
  234. aria_code/apps/cli/terminal_chrome.py +412 -0
  235. aria_code/apps/cli/todo_tracker.py +190 -0
  236. aria_code/apps/cli/tool_executor.py +932 -0
  237. aria_code/apps/cli/tool_registry.py +34 -0
  238. aria_code/apps/cli/tool_scope.py +113 -0
  239. aria_code/apps/cli/tools/__init__.py +40 -0
  240. aria_code/apps/cli/tools/context.py +46 -0
  241. aria_code/apps/cli/tools/file_tools.py +181 -0
  242. aria_code/apps/cli/tools/market_tools.py +626 -0
  243. aria_code/apps/cli/tools/notebook_tools.py +111 -0
  244. aria_code/apps/cli/tools/system_tools.py +656 -0
  245. aria_code/apps/cli/tools/write_tools.py +961 -0
  246. aria_code/apps/cli/tradingview_bridge.py +529 -0
  247. aria_code/apps/cli/transactions.py +269 -0
  248. aria_code/apps/cli/turn_planning.py +137 -0
  249. aria_code/apps/cli/update_check.py +257 -0
  250. aria_code/apps/cli/updater.py +373 -0
  251. aria_code/apps/cli/utils/__init__.py +0 -0
  252. aria_code/apps/cli/utils/market_detect.py +1663 -0
  253. aria_code/apps/cli/web_login.py +136 -0
  254. aria_code/apps/cli/workflow_runner.py +127 -0
  255. aria_code/apps/cli/workspace_route.py +121 -0
  256. aria_code/apps/daemon/README.md +14 -0
  257. aria_code/apps/vscode/README.md +115 -0
  258. aria_code/apps/vscode/package.json +70 -0
  259. aria_code/aria_cli.py +5244 -0
  260. aria_code/aria_daemon.py +1372 -0
  261. aria_code/aria_feishu_bot.py +16 -0
  262. aria_code/aria_mcp_server.py +61 -0
  263. aria_code/aria_relay_client.py +4 -0
  264. aria_code/aria_telegram_bot.py +11 -0
  265. aria_code/ariarc.py +385 -0
  266. aria_code/artifacts.py +581 -0
  267. aria_code/backtest_engine.py +4 -0
  268. aria_code/backtest_report.py +4 -0
  269. aria_code/brokers/__init__.py +78 -0
  270. aria_code/brokers/automation.py +193 -0
  271. aria_code/brokers/base.py +231 -0
  272. aria_code/brokers/capabilities.py +264 -0
  273. aria_code/brokers/cn/__init__.py +10 -0
  274. aria_code/brokers/cn/easytrader_broker.py +193 -0
  275. aria_code/brokers/cn/futu_broker.py +194 -0
  276. aria_code/brokers/cn/longbridge_broker.py +190 -0
  277. aria_code/brokers/cn/tiger_broker.py +196 -0
  278. aria_code/brokers/cn/xtquant_broker.py +225 -0
  279. aria_code/brokers/config.py +414 -0
  280. aria_code/brokers/intl/__init__.py +5 -0
  281. aria_code/brokers/intl/alpaca_broker.py +183 -0
  282. aria_code/brokers/intl/ibkr_broker.py +215 -0
  283. aria_code/brokers/intl/trading212_broker.py +183 -0
  284. aria_code/brokers/intl/webull_broker.py +156 -0
  285. aria_code/brokers/paper_broker.py +266 -0
  286. aria_code/brokers/planning.py +296 -0
  287. aria_code/brokers/registry.py +213 -0
  288. aria_code/brokers/trading.py +267 -0
  289. aria_code/canva_client.py +4 -0
  290. aria_code/change_store.py +127 -0
  291. aria_code/clients/__init__.py +0 -0
  292. aria_code/clients/aliyun_data_client.py +660 -0
  293. aria_code/clients/aria_relay_client.py +16 -0
  294. aria_code/clients/canva_client.py +284 -0
  295. aria_code/clients/figma_client.py +100 -0
  296. aria_code/clients/football_data_client.py +1671 -0
  297. aria_code/clients/kling_video_client.py +182 -0
  298. aria_code/clients/market_data_client.py +1985 -0
  299. aria_code/clients/openai_image_client.py +242 -0
  300. aria_code/clients/runway_video_client.py +157 -0
  301. aria_code/clients/warehouse_erp_client.py +105 -0
  302. aria_code/cloud_memory.py +190 -0
  303. aria_code/command_safety.py +19 -0
  304. aria_code/computer_use_server.py +276 -0
  305. aria_code/computer_use_tools.py +4 -0
  306. aria_code/dashboard_generator.py +579 -0
  307. aria_code/data_analysis_tools.py +4 -0
  308. aria_code/data_cleaner.py +483 -0
  309. aria_code/data_service.py +513 -0
  310. aria_code/datasources/__init__.py +23 -0
  311. aria_code/datasources/base.py +166 -0
  312. aria_code/datasources/router.py +253 -0
  313. aria_code/datasources/sec_statements.py +217 -0
  314. aria_code/datasources/sources/__init__.py +15 -0
  315. aria_code/datasources/sources/akshare_source.py +269 -0
  316. aria_code/datasources/sources/alpha_vantage_source.py +203 -0
  317. aria_code/datasources/sources/edgar_source.py +219 -0
  318. aria_code/datasources/sources/finnhub_source.py +198 -0
  319. aria_code/datasources/sources/fred_source.py +223 -0
  320. aria_code/datasources/sources/tushare_source.py +143 -0
  321. aria_code/datasources/sources/web_scraper_source.py +278 -0
  322. aria_code/datasources/sources/world_bank_source.py +206 -0
  323. aria_code/datasources/sources/yfinance_source.py +152 -0
  324. aria_code/doctor.py +860 -0
  325. aria_code/domain/__init__.py +0 -0
  326. aria_code/domain/_finance_core/__init__.py +5 -0
  327. aria_code/domain/_finance_core/backtest_engine.py +325 -0
  328. aria_code/domain/_finance_core/performance_stats.py +101 -0
  329. aria_code/domain/backtest_engine.py +75 -0
  330. aria_code/domain/backtest_report.py +488 -0
  331. aria_code/domain/finance_formulas.py +389 -0
  332. aria_code/domain/performance_stats.py +6 -0
  333. aria_code/domain/portfolio_ledger.py +307 -0
  334. aria_code/domain/strategy_vault.py +421 -0
  335. aria_code/evals/__init__.py +37 -0
  336. aria_code/evals/behavior.py +113 -0
  337. aria_code/evals/gap.py +93 -0
  338. aria_code/evals/harness.py +949 -0
  339. aria_code/evals/review_probe.py +132 -0
  340. aria_code/evals/runner.py +425 -0
  341. aria_code/evals/scorecard.py +322 -0
  342. aria_code/evals/summary.py +125 -0
  343. aria_code/external_agent_runner.py +115 -0
  344. aria_code/figma_client.py +4 -0
  345. aria_code/file_analysis_tools.py +4 -0
  346. aria_code/finance_formulas.py +4 -0
  347. aria_code/football_data_client.py +4 -0
  348. aria_code/image_gen_tools.py +4 -0
  349. aria_code/intent_classifier.py +459 -0
  350. aria_code/kling_video_client.py +4 -0
  351. aria_code/licensing.py +151 -0
  352. aria_code/local_finance_tools.py +4 -0
  353. aria_code/local_image_provider.py +4 -0
  354. aria_code/local_llm_provider.py +4 -0
  355. aria_code/macro_tools.py +4 -0
  356. aria_code/markdown_pdf.py +289 -0
  357. aria_code/market_data_client.py +4 -0
  358. aria_code/mcp_client.py +744 -0
  359. aria_code/memory_manager.py +273 -0
  360. aria_code/model_capability.py +512 -0
  361. aria_code/notification_tools.py +4 -0
  362. aria_code/openai_image_client.py +4 -0
  363. aria_code/packages/__init__.py +26 -0
  364. aria_code/packages/adk_bridge/__init__.py +11 -0
  365. aria_code/packages/adk_bridge/code_review_tools.py +49 -0
  366. aria_code/packages/adk_bridge/market_tools.py +125 -0
  367. aria_code/packages/aria_agents/__init__.py +5 -0
  368. aria_code/packages/aria_agents/manifest.py +78 -0
  369. aria_code/packages/aria_core/__init__.py +34 -0
  370. aria_code/packages/aria_core/architecture.py +269 -0
  371. aria_code/packages/aria_core/export.py +147 -0
  372. aria_code/packages/aria_core/manifest.py +65 -0
  373. aria_code/packages/aria_core/paths.py +57 -0
  374. aria_code/packages/aria_core/secure_file.py +68 -0
  375. aria_code/packages/aria_infra/__init__.py +15 -0
  376. aria_code/packages/aria_infra/arthera.py +58 -0
  377. aria_code/packages/aria_infra/doctor.py +246 -0
  378. aria_code/packages/aria_infra/product.py +40 -0
  379. aria_code/packages/aria_mcp/__init__.py +25 -0
  380. aria_code/packages/aria_mcp/bridge.py +232 -0
  381. aria_code/packages/aria_mcp/circuit.py +82 -0
  382. aria_code/packages/aria_mcp/config.py +162 -0
  383. aria_code/packages/aria_mcp/installer.py +95 -0
  384. aria_code/packages/aria_mcp/server.py +1705 -0
  385. aria_code/packages/aria_mcp/tools.py +81 -0
  386. aria_code/packages/aria_sdk/__init__.py +19 -0
  387. aria_code/packages/aria_sdk/client.py +393 -0
  388. aria_code/packages/aria_sdk/providers.py +70 -0
  389. aria_code/packages/aria_sdk/streaming.py +75 -0
  390. aria_code/packages/aria_sdk/types.py +86 -0
  391. aria_code/packages/aria_services/__init__.py +92 -0
  392. aria_code/packages/aria_services/cache.py +60 -0
  393. aria_code/packages/aria_services/context.py +356 -0
  394. aria_code/packages/aria_services/context_checkpoints.py +157 -0
  395. aria_code/packages/aria_services/data.py +11 -0
  396. aria_code/packages/aria_services/provider_health.py +304 -0
  397. aria_code/packages/aria_services/references.py +247 -0
  398. aria_code/packages/aria_services/registry.py +249 -0
  399. aria_code/packages/aria_services/research_protocol.py +137 -0
  400. aria_code/packages/aria_services/research_quality.py +186 -0
  401. aria_code/packages/aria_services/settings.py +160 -0
  402. aria_code/packages/aria_services/usage.py +151 -0
  403. aria_code/packages/aria_skills/__init__.py +46 -0
  404. aria_code/packages/aria_skills/catalog.py +149 -0
  405. aria_code/packages/aria_skills/loader.py +455 -0
  406. aria_code/packages/aria_skills/registry.py +84 -0
  407. aria_code/packages/aria_tools/__init__.py +5 -0
  408. aria_code/packages/aria_tools/financial/__init__.py +5 -0
  409. aria_code/packages/aria_tools/financial/_paths.py +92 -0
  410. aria_code/packages/aria_tools/registry.py +129 -0
  411. aria_code/packages/quant_engine/__init__.py +33 -0
  412. aria_code/packages/quant_engine/_namespace.py +24 -0
  413. aria_code/packages/quant_engine/backtest/__init__.py +10 -0
  414. aria_code/packages/quant_engine/backtest/core.py +53 -0
  415. aria_code/packages/quant_engine/backtest/engine.py +102 -0
  416. aria_code/packages/quant_engine/portfolio/__init__.py +9 -0
  417. aria_code/packages/quant_engine/portfolio/optimizer.py +85 -0
  418. aria_code/packages/quant_engine/sports/__init__.py +76 -0
  419. aria_code/packages/quant_engine/sports/calibrator.py +354 -0
  420. aria_code/packages/quant_engine/sports/dixon_coles.py +234 -0
  421. aria_code/packages/quant_engine/sports/elo.py +300 -0
  422. aria_code/packages/quant_engine/sports/form.py +188 -0
  423. aria_code/packages/quant_engine/sports/h2h.py +195 -0
  424. aria_code/packages/quant_engine/sports/predictor.py +312 -0
  425. aria_code/packages/quant_engine/sports/tracker.py +665 -0
  426. aria_code/packages/quant_engine/stochastic/__init__.py +31 -0
  427. aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +195 -0
  428. aria_code/packages/quant_engine/stochastic/ito_calculus.py +477 -0
  429. aria_code/packages/quant_engine/stochastic/kelly_criterion.py +181 -0
  430. aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +95 -0
  431. aria_code/packages/quant_engine/stochastic/options_pricing.py +576 -0
  432. aria_code/packages/quant_engine/stochastic/stochastic_processes.py +90 -0
  433. aria_code/packs/__init__.py +85 -0
  434. aria_code/packs/base.py +168 -0
  435. aria_code/packs/finance/__init__.py +250 -0
  436. aria_code/packs/healthcare/__init__.py +40 -0
  437. aria_code/packs/logistics/__init__.py +171 -0
  438. aria_code/packs/payments/__init__.py +139 -0
  439. aria_code/packs/realty/__init__.py +190 -0
  440. aria_code/packs/registry.py +202 -0
  441. aria_code/packs/rules.py +90 -0
  442. aria_code/plan_utils.py +194 -0
  443. aria_code/plugin_loader.py +328 -0
  444. aria_code/portfolio_ledger.py +4 -0
  445. aria_code/preview_server.py +449 -0
  446. aria_code/privacy/__init__.py +5 -0
  447. aria_code/privacy/feedback.py +123 -0
  448. aria_code/project_review.py +278 -0
  449. aria_code/project_review_api.py +235 -0
  450. aria_code/project_review_server.py +18 -0
  451. aria_code/project_tools.py +4 -0
  452. aria_code/providers/__init__.py +30 -0
  453. aria_code/providers/google_video_provider.py +256 -0
  454. aria_code/providers/llm/__init__.py +19 -0
  455. aria_code/providers/llm/anthropic.py +184 -0
  456. aria_code/providers/llm/arthera_gateway.py +90 -0
  457. aria_code/providers/llm/autoconfig.py +213 -0
  458. aria_code/providers/llm/base.py +139 -0
  459. aria_code/providers/llm/custom.py +158 -0
  460. aria_code/providers/llm/ollama.py +137 -0
  461. aria_code/providers/llm/openai_compat.py +350 -0
  462. aria_code/providers/llm/registry.py +457 -0
  463. aria_code/providers/local_image_provider.py +202 -0
  464. aria_code/providers/local_llm_provider.py +549 -0
  465. aria_code/providers/ollama_models.py +79 -0
  466. aria_code/providers/openai_params.py +32 -0
  467. aria_code/providers/tool_messages.py +100 -0
  468. aria_code/realty_data_tools.py +4 -0
  469. aria_code/report_exporters.py +150 -0
  470. aria_code/report_generator.py +1764 -0
  471. aria_code/review_service.py +497 -0
  472. aria_code/runtime/__init__.py +176 -0
  473. aria_code/runtime/acceptance.py +632 -0
  474. aria_code/runtime/agent_loop.py +1851 -0
  475. aria_code/runtime/agent_profiles.py +75 -0
  476. aria_code/runtime/approval.py +71 -0
  477. aria_code/runtime/baseline.py +219 -0
  478. aria_code/runtime/budget.py +232 -0
  479. aria_code/runtime/checkpoints.py +481 -0
  480. aria_code/runtime/consult.py +65 -0
  481. aria_code/runtime/contract.py +282 -0
  482. aria_code/runtime/delivery.py +432 -0
  483. aria_code/runtime/events.py +113 -0
  484. aria_code/runtime/gateway.py +167 -0
  485. aria_code/runtime/lsp.py +484 -0
  486. aria_code/runtime/native_index.py +153 -0
  487. aria_code/runtime/orchestrator.py +55 -0
  488. aria_code/runtime/processes.py +343 -0
  489. aria_code/runtime/project_graph.py +614 -0
  490. aria_code/runtime/repo_map.py +712 -0
  491. aria_code/runtime/research_bundle.py +105 -0
  492. aria_code/runtime/review.py +269 -0
  493. aria_code/runtime/run_state.py +127 -0
  494. aria_code/runtime/run_store.py +522 -0
  495. aria_code/runtime/scoped_runs.py +113 -0
  496. aria_code/runtime/self_healing.py +422 -0
  497. aria_code/runtime/semantic_diff.py +171 -0
  498. aria_code/runtime/subagent.py +721 -0
  499. aria_code/runtime/symbol_edit.py +117 -0
  500. aria_code/runtime/task_brief.py +46 -0
  501. aria_code/runtime/task_context.py +145 -0
  502. aria_code/runtime/task_ledger.py +108 -0
  503. aria_code/runtime/task_orchestrator.py +90 -0
  504. aria_code/runtime/task_outcome.py +33 -0
  505. aria_code/runtime/task_verification.py +266 -0
  506. aria_code/runtime/task_worktree.py +448 -0
  507. aria_code/runtime/tool_executor.py +329 -0
  508. aria_code/runtime/tool_policy.py +107 -0
  509. aria_code/runtime/transactions.py +216 -0
  510. aria_code/runtime/windows_job.py +115 -0
  511. aria_code/runtime/workflows.py +222 -0
  512. aria_code/runtime/worktrees.py +215 -0
  513. aria_code/runway_video_client.py +4 -0
  514. aria_code/safety/__init__.py +27 -0
  515. aria_code/safety/client_isolation.py +178 -0
  516. aria_code/safety/permissions.py +339 -0
  517. aria_code/safety/risk.py +699 -0
  518. aria_code/safety/sandbox.py +148 -0
  519. aria_code/safety/service.py +102 -0
  520. aria_code/service_endpoints.py +14 -0
  521. aria_code/setup_wizard.py +684 -0
  522. aria_code/spreadsheet_tools.py +4 -0
  523. aria_code/strategy_vault.py +4 -0
  524. aria_code/tools/__init__.py +0 -0
  525. aria_code/tools/artifact_tools.py +252 -0
  526. aria_code/tools/broker_tools.py +92 -0
  527. aria_code/tools/build_quant_engine.py +97 -0
  528. aria_code/tools/code_audit_tools.py +192 -0
  529. aria_code/tools/computer_use_tools.py +509 -0
  530. aria_code/tools/data_analysis_tools.py +831 -0
  531. aria_code/tools/enterprise_finance_tools.py +202 -0
  532. aria_code/tools/extended_tools.py +240 -0
  533. aria_code/tools/file_analysis_tools.py +880 -0
  534. aria_code/tools/image_gen_tools.py +114 -0
  535. aria_code/tools/local_finance_tools.py +3488 -0
  536. aria_code/tools/logistics_carriers.py +11 -0
  537. aria_code/tools/logistics_inventory.py +11 -0
  538. aria_code/tools/logistics_io.py +11 -0
  539. aria_code/tools/logistics_tenancy.py +11 -0
  540. aria_code/tools/logistics_tools.py +11 -0
  541. aria_code/tools/macro_tools.py +412 -0
  542. aria_code/tools/notification_tools.py +249 -0
  543. aria_code/tools/project_tools.py +525 -0
  544. aria_code/tools/realty_data_tools.py +662 -0
  545. aria_code/tools/spreadsheet_tools.py +399 -0
  546. aria_code/tools/stripe_tools.py +115 -0
  547. aria_code/tools/video_tools.py +500 -0
  548. aria_code/training/__init__.py +1 -0
  549. aria_code/training/compare.py +117 -0
  550. aria_code/training/prelude_commands.py +111 -0
  551. aria_code/training/prelude_eval.py +390 -0
  552. aria_code/training/prelude_real.py +183 -0
  553. aria_code/training/prelude_train.py +248 -0
  554. aria_code/training/sft_dataset.py +230 -0
  555. aria_code/training/trajectory_dataset.py +263 -0
  556. aria_code/ui/__init__.py +105 -0
  557. aria_code/ui/banner.py +404 -0
  558. aria_code/ui/completer.py +571 -0
  559. aria_code/ui/console.py +285 -0
  560. aria_code/ui/input_box.py +505 -0
  561. aria_code/ui/mentions.py +206 -0
  562. aria_code/ui/picker.py +248 -0
  563. aria_code/ui/render/__init__.py +11 -0
  564. aria_code/ui/render/actions.py +297 -0
  565. aria_code/ui/render/finance.py +1732 -0
  566. aria_code/ui/render/market.py +253 -0
  567. aria_code/ui/render/output.py +954 -0
  568. aria_code/ui/render/responsive.py +75 -0
  569. aria_code/ui/render/team.py +367 -0
  570. aria_code/ui/robot.py +239 -0
  571. aria_code/ui/startup_dashboard.py +110 -0
  572. aria_code/video_analysis.py +147 -0
  573. aria_code/video_editor.py +518 -0
  574. aria_code/video_workflow/__init__.py +8 -0
  575. aria_code/video_workflow/__main__.py +61 -0
  576. aria_code/video_workflow/engines/__init__.py +18 -0
  577. aria_code/video_workflow/engines/base.py +69 -0
  578. aria_code/video_workflow/engines/custom_model.py +204 -0
  579. aria_code/video_workflow/engines/google_veo.py +94 -0
  580. aria_code/video_workflow/engines/local_engine.py +71 -0
  581. aria_code/video_workflow/engines/registry.py +98 -0
  582. aria_code/video_workflow/google_models.py +278 -0
  583. aria_code/video_workflow/music/__init__.py +5 -0
  584. aria_code/video_workflow/music/foley_service.py +132 -0
  585. aria_code/video_workflow/music/service.py +212 -0
  586. aria_code/video_workflow/pipeline.py +620 -0
  587. aria_code/video_workflow/plan.py +202 -0
  588. aria_code/video_workflow/session.py +297 -0
  589. aria_code/workspace/__init__.py +6 -0
  590. aria_code/workspace/files.py +219 -0
  591. aria_code/workspace/verify.py +167 -0
  592. aria_code/workspace_changes.py +199 -0
  593. aria_code/workspace_service.py +196 -0
  594. aria_code/workspace_tools.py +150 -0
  595. aria_code-0.167.0.dist-info/METADATA +330 -0
  596. aria_code-0.167.0.dist-info/RECORD +601 -0
  597. aria_code-0.167.0.dist-info/WHEEL +5 -0
  598. aria_code-0.167.0.dist-info/entry_points.txt +5 -0
  599. aria_code-0.167.0.dist-info/licenses/LICENSE +201 -0
  600. aria_code-0.167.0.dist-info/licenses/NOTICE +49 -0
  601. aria_code-0.167.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,206 @@
1
+ """One search behind "@": files, folders, market assets and saved resources.
2
+
3
+ "@" opened on a list of kinds — file:, folder:, asset:, portfolio: … — and a
4
+ file only appeared once a path character was typed, so attaching src/fx.py
5
+ took "@", "file:", then the path. Codex's "@" goes straight to results across
6
+ files, folders and plugins. Here "@fx" lists fx.py, test_fx.py and any asset,
7
+ strategy or report that matches, each labelled with its kind; "@file:" and the
8
+ other kind prefixes still narrow the list to one kind.
9
+
10
+ The inserted text is the canonical reference (@file:src/fx.py, @asset:AAPL),
11
+ so references.py resolves it unchanged. Nothing here imports prompt_toolkit.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import os
17
+ import subprocess
18
+ import time
19
+ from dataclasses import dataclass
20
+ from pathlib import Path
21
+ from typing import Iterable
22
+
23
+ from aria_code.packages.aria_services.references import reference_search_roots
24
+
25
+ # Directories a walk never enters when the workspace is not a git repository.
26
+ _SKIP_DIRS = frozenset({
27
+ ".git", ".hg", ".svn", ".venv", "venv", "env", "node_modules", "__pycache__", ".mypy_cache",
28
+ ".pytest_cache", ".ruff_cache", ".tox", "dist", "build", ".next", ".idea", ".vscode", "target",
29
+ })
30
+ MAX_INDEXED_FILES = 20000
31
+ INDEX_TTL_SECONDS = 30.0
32
+ RESOURCE_KINDS = ("portfolio", "strategy", "dataset", "run", "report")
33
+ # Within one match quality, this order breaks ties. A saved strategy or report
34
+ # is named on purpose, so it ranks above the file behind it; an asset ranks
35
+ # first only when the query is typed like a ticker ("@FX", not "@fx").
36
+ _KIND_ORDER = {"strategy": 1, "portfolio": 2, "report": 3, "dataset": 4, "run": 5, "file": 6, "folder": 7}
37
+
38
+
39
+ @dataclass(frozen=True)
40
+ class Mention:
41
+ kind: str
42
+ value: str # what follows "kind:" — a path, a symbol, a name
43
+ score: int # lower is better
44
+ matched: tuple[int, ...] = () # positions in `label` to highlight
45
+
46
+ @property
47
+ def label(self) -> str:
48
+ return self.value + ("/" if self.kind == "folder" else "")
49
+
50
+ @property
51
+ def insert_text(self) -> str:
52
+ value = f'"{self.value}"' if any(ch.isspace() for ch in self.value) else self.value
53
+ return f"{self.kind}:{value}"
54
+
55
+
56
+ def _match(query: str, text: str) -> tuple[int, tuple[int, ...]] | None:
57
+ """(score, positions) of query in text, or None. Case-insensitive."""
58
+ if not query:
59
+ return 50, ()
60
+ q, t = query.lower(), text.lower()
61
+ if t == q:
62
+ return 0, tuple(range(len(text)))
63
+ if t.startswith(q):
64
+ return 10, tuple(range(len(query)))
65
+ at = t.find(q)
66
+ if at >= 0:
67
+ return 20 + min(at, 9), tuple(range(at, at + len(query)))
68
+ positions, i = [], 0
69
+ for index, ch in enumerate(t):
70
+ if i < len(q) and ch == q[i]:
71
+ positions.append(index)
72
+ i += 1
73
+ if i == len(q):
74
+ spread = positions[-1] - positions[0]
75
+ return 40 + min(spread, 29), tuple(positions)
76
+ return None
77
+
78
+
79
+ def _match_path(query: str, path: str) -> tuple[int, tuple[int, ...]] | None:
80
+ """Prefer the file name; fall back to the whole relative path."""
81
+ name_start = path.rfind("/") + 1
82
+ name_hit = _match(query, path[name_start:])
83
+ if name_hit is not None:
84
+ score, positions = name_hit
85
+ return score, tuple(name_start + p for p in positions)
86
+ path_hit = _match(query, path)
87
+ if path_hit is not None:
88
+ return path_hit[0] + 5, path_hit[1]
89
+ return None
90
+
91
+
92
+ class MentionIndex:
93
+ """Searches everything "@" can attach, for one workspace."""
94
+
95
+ def __init__(self, workspace: Path | str, *, output_root: Path | str | None = None,
96
+ symbols: Iterable[str] = ()):
97
+ self.workspace = Path(workspace).expanduser().resolve()
98
+ self.output_root = Path(output_root).expanduser().resolve() if output_root else None
99
+ self.symbols = sorted({str(s).upper() for s in symbols if str(s).strip()})
100
+ self._files: list[str] = []
101
+ self._indexed_at = 0.0
102
+
103
+ # ── the file list ────────────────────────────────────────────────────────
104
+ def files(self) -> list[str]:
105
+ """Workspace-relative file paths, .gitignore respected when in a repository."""
106
+ if not self._files or time.monotonic() - self._indexed_at > INDEX_TTL_SECONDS:
107
+ self._files = self._git_files() or self._walk_files()
108
+ self._indexed_at = time.monotonic()
109
+ return self._files
110
+
111
+ def _git_files(self) -> list[str]:
112
+ try:
113
+ done = subprocess.run(
114
+ ["git", "ls-files", "--cached", "--others", "--exclude-standard"],
115
+ cwd=self.workspace, capture_output=True, text=True, timeout=3,
116
+ )
117
+ except (OSError, subprocess.SubprocessError):
118
+ return []
119
+ if done.returncode != 0:
120
+ return []
121
+ return [line for line in done.stdout.splitlines() if line][:MAX_INDEXED_FILES]
122
+
123
+ def _walk_files(self) -> list[str]:
124
+ found: list[str] = []
125
+ for root, dirs, names in os.walk(self.workspace):
126
+ dirs[:] = sorted(d for d in dirs if d not in _SKIP_DIRS and not d.startswith("."))
127
+ rel_root = os.path.relpath(root, self.workspace)
128
+ for name in sorted(names):
129
+ if name.startswith("."):
130
+ continue
131
+ found.append(name if rel_root == "." else f"{rel_root}/{name}".replace(os.sep, "/"))
132
+ if len(found) >= MAX_INDEXED_FILES:
133
+ return found
134
+ return found
135
+
136
+ def folders(self) -> list[str]:
137
+ seen: dict[str, None] = {}
138
+ for path in self.files():
139
+ parts = path.split("/")[:-1]
140
+ for depth in range(1, len(parts) + 1):
141
+ seen["/".join(parts[:depth])] = None
142
+ return list(seen)
143
+
144
+ def recent_files(self, limit: int = 5) -> list[str]:
145
+ stamped = []
146
+ for path in self.files()[:MAX_INDEXED_FILES]:
147
+ try:
148
+ stamped.append((os.stat(self.workspace / path).st_mtime, path))
149
+ except OSError:
150
+ continue
151
+ return [path for _, path in sorted(stamped, reverse=True)[:limit]]
152
+
153
+ def resources(self, kind: str) -> list[str]:
154
+ names: dict[str, None] = {}
155
+ for root in reference_search_roots(kind, self.workspace, self.output_root):
156
+ if not root.is_dir():
157
+ continue
158
+ try:
159
+ for path in root.rglob("*"):
160
+ if path.is_file() and not any(p.startswith(".") for p in path.relative_to(root).parts):
161
+ names[path.stem] = None
162
+ if len(names) >= 200:
163
+ break
164
+ except OSError:
165
+ continue
166
+ return list(names)
167
+
168
+ # ── search ───────────────────────────────────────────────────────────────
169
+ def search(self, query: str, *, kind: str | None = None, limit: int = 30) -> list[Mention]:
170
+ """Matches for `query`, best first; only `kind` when one is given."""
171
+ found: list[Mention] = []
172
+
173
+ def add(k: str, values: Iterable[str], matcher) -> None:
174
+ if kind and k != kind:
175
+ return
176
+ for value in values:
177
+ hit = matcher(query, value)
178
+ if hit is not None:
179
+ found.append(Mention(k, value, hit[0], hit[1]))
180
+
181
+ add("file", self.files(), _match_path)
182
+ add("folder", self.folders(), _match_path)
183
+ # Tickers by exact, prefix or substring only: "fx" scattered through
184
+ # NFLX is not a way anyone looks for Netflix.
185
+ add("asset", self.symbols, lambda q, v: (h if (h := _match(q, v)) and h[0] < 40 else None))
186
+ if query and _looks_like_symbol(query) and query.upper() not in self.symbols and kind in (None, "asset"):
187
+ found.append(Mention("asset", query.upper(), 30, tuple(range(len(query)))))
188
+ for resource in RESOURCE_KINDS:
189
+ add(resource, self.resources(resource), _match)
190
+ asset_rank = 0 if _looks_like_symbol(query) else 8
191
+ found.sort(key=lambda m: (m.score, asset_rank if m.kind == "asset" else _KIND_ORDER.get(m.kind, 9),
192
+ len(m.value), m.value))
193
+ # Letters scattered through a long path ("AAP" in providers/llm/ollama.py)
194
+ # are noise once there is a popup's worth of closer matches.
195
+ if sum(1 for m in found if m.score < 40) >= 8:
196
+ found = [m for m in found if m.score < 40]
197
+ return found[:limit]
198
+
199
+
200
+ def _looks_like_symbol(text: str) -> bool:
201
+ """A ticker someone is typing: "AAPL", "0700.HK", "BTC-USD" — not "fx" or "readme"."""
202
+ raw = text.strip()
203
+ return 1 <= len(raw) <= 12 and raw.upper() == raw and any(ch.isalnum() for ch in raw) and " " not in raw
204
+
205
+
206
+ __all__ = ["Mention", "MentionIndex"]
aria_code/ui/picker.py ADDED
@@ -0,0 +1,248 @@
1
+ """Arrow-key selector and async wrapper used by model/skill picker dialogs.
2
+
3
+ from ui.picker import arrow_select, run_picker_in_thread
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import asyncio
9
+ import os
10
+ import sys
11
+
12
+ from aria_code.ui.console import _HAS_TERMIOS, _esc_watcher
13
+
14
+ if _HAS_TERMIOS:
15
+ import termios
16
+ import tty
17
+ import select as _select
18
+
19
+
20
+ def arrow_select(options: list, selected: int = 0, title: str = "",
21
+ max_visible: int = 10,
22
+ controls_hint: str = "↑↓ Enter Esc/q Cancel",
23
+ collapse_to: str | None = None,
24
+ shortcuts: dict | None = None,
25
+ numbered: bool = False) -> int:
26
+ """Interactive arrow-key selector with scrolling.
27
+
28
+ Args:
29
+ options: list of ``(label, description)`` tuples or plain strings
30
+ selected: initially highlighted index
31
+ title: optional header line
32
+ max_visible: max rows shown at once; scrolls when list is larger
33
+ collapse_to: when given, the menu is erased once answered and one
34
+ line is left in its place — "✓ Yes fx.py" — instead of
35
+ the whole menu, as Codex leaves an answered approval.
36
+ The text names what was being approved.
37
+ shortcuts: ``{"y": 0, "n": 3}`` — one key answers with that option
38
+ at once; the key is shown after its label, "(y)".
39
+ numbered: show "1." … before labels; digits 1–9 answer directly.
40
+ Returns:
41
+ index of chosen option, or -1 if cancelled
42
+ """
43
+ if not options:
44
+ return -1
45
+ keys = {str(key): index for key, index in (shortcuts or {}).items()
46
+ if len(str(key)) == 1 and 0 <= index < len(options)}
47
+ key_of = {index: key for key, index in keys.items()}
48
+
49
+ def _label(index: int, label: str) -> str:
50
+ text = f"{index + 1}. {label}" if numbered else label
51
+ return f"{text} ({key_of[index]})" if index in key_of else text
52
+
53
+ if not _HAS_TERMIOS or not sys.stdin.isatty():
54
+ if title:
55
+ print(f"\n {title}\n")
56
+ for i, opt in enumerate(options):
57
+ label = opt[0] if isinstance(opt, tuple) else opt
58
+ marker = "❯" if i == selected else " "
59
+ print(f" {marker} {i + 1:2d}. {_label(i, label) if keys else label}")
60
+ try:
61
+ c = input("\n Enter number (or Enter to keep current): ").strip()
62
+ if not c:
63
+ return selected
64
+ if c in keys:
65
+ return keys[c]
66
+ idx = int(c) - 1
67
+ return idx if 0 <= idx < len(options) else -1
68
+ except (ValueError, EOFError, KeyboardInterrupt):
69
+ return -1
70
+
71
+ n = len(options)
72
+ visible = min(max_visible, n)
73
+ scroll = max(0, selected - visible + 1)
74
+
75
+ fd = sys.stdin.fileno()
76
+ old_settings = termios.tcgetattr(fd)
77
+
78
+ try:
79
+ _tcols = os.get_terminal_size(fd).columns
80
+ except Exception:
81
+ _tcols = 80
82
+
83
+ _rule = "─" * min(_tcols, 72)
84
+
85
+ def _display_width(s: str) -> int:
86
+ import re as _re
87
+ clean = _re.sub(r'\x1b\[[0-9;]*[mJKHABCDfGrs]', '', s)
88
+ w = 0
89
+ for ch in clean:
90
+ cp = ord(ch)
91
+ if (0x1100 <= cp <= 0x115F or 0x2E80 <= cp <= 0xA4CF or
92
+ 0xAC00 <= cp <= 0xD7AF or 0xF900 <= cp <= 0xFAFF or
93
+ 0xFE10 <= cp <= 0xFE1F or 0xFE30 <= cp <= 0xFE4F or
94
+ 0xFF01 <= cp <= 0xFF60 or 0xFFE0 <= cp <= 0xFFE6 or
95
+ 0x3000 <= cp <= 0x303F):
96
+ w += 2
97
+ else:
98
+ w += 1
99
+ return w
100
+
101
+ def _physical_lines(text: str) -> int:
102
+ dw = _display_width(text)
103
+ return max(1, (dw + _tcols - 1) // _tcols)
104
+
105
+ def _raw(s: str):
106
+ os.write(1, s.encode())
107
+
108
+ def _render():
109
+ nonlocal scroll
110
+ if selected < scroll:
111
+ scroll = selected
112
+ elif selected >= scroll + visible:
113
+ scroll = selected - visible + 1
114
+
115
+ buf = ""
116
+ if _render.drawn:
117
+ buf += f"\033[{_render.last_phys_height}A"
118
+
119
+ phys_height = 0
120
+ for row in range(visible):
121
+ idx = scroll + row
122
+ opt = options[idx]
123
+ label = opt[0] if isinstance(opt, tuple) else opt
124
+ desc = opt[1] if isinstance(opt, tuple) and len(opt) > 1 else ""
125
+ if not label.strip().startswith("──"):
126
+ label = _label(idx, label)
127
+ if label.strip().startswith("──"):
128
+ line = f" \033[2m{label}\033[0m"
129
+ elif idx == selected:
130
+ _accent = os.getenv("ARIA_ACCENT_COLOR", "192;128;80")
131
+ line = f" \033[1m\033[38;2;{_accent}m❯\033[0m \033[1m{label}\033[0m"
132
+ if desc:
133
+ line += f" \033[2m{desc}\033[0m"
134
+ else:
135
+ line = f" {label}"
136
+ if desc:
137
+ line += f" \033[2m{desc}\033[0m"
138
+ buf += f"\033[2K{line}\n"
139
+ phys_height += _physical_lines(line)
140
+
141
+ if n > visible:
142
+ hint = f" \033[2m{selected + 1}/{n}\033[0m"
143
+ buf += f"\033[2K{hint}\n"
144
+ else:
145
+ buf += "\033[2K\n"
146
+ phys_height += 1
147
+
148
+ _render.last_phys_height = phys_height
149
+ _raw(buf)
150
+ _render.drawn = True
151
+
152
+ _render.drawn = False
153
+ _render.last_phys_height = visible + 1
154
+ header_text = f" {title} {controls_hint}" if title else f" {controls_hint}"
155
+ # blank line + rule, then the title/hint line(s) + blank line
156
+ header_height = 2 + _physical_lines(header_text) + 1
157
+ result = -1
158
+
159
+ def _choose() -> int:
160
+ nonlocal selected
161
+ while True:
162
+ ch = os.read(fd, 1)
163
+ if ch == b'\x1b':
164
+ seq = b''
165
+ if _select.select([fd], [], [], 0.05)[0]:
166
+ seq = os.read(fd, 2)
167
+ if seq == b'[A':
168
+ selected = (selected - 1) % n; _render()
169
+ elif seq == b'[B':
170
+ selected = (selected + 1) % n; _render()
171
+ elif seq == b'[5~':
172
+ selected = max(0, selected - visible); _render()
173
+ elif seq == b'[6~':
174
+ selected = min(n - 1, selected + visible); _render()
175
+ elif not seq:
176
+ return -1
177
+ elif ch in (b'\r', b'\n'):
178
+ return selected
179
+ elif ch.decode(errors="ignore") in keys:
180
+ selected = keys[ch.decode(errors="ignore")]
181
+ return selected
182
+ elif numbered and ch.isdigit() and 1 <= int(ch) <= n:
183
+ selected = int(ch) - 1
184
+ return selected
185
+ elif ch == b'q':
186
+ return -1
187
+ elif ch == b'k':
188
+ selected = (selected - 1) % n; _render()
189
+ elif ch == b'j':
190
+ selected = (selected + 1) % n; _render()
191
+ elif ch == b'g':
192
+ selected = 0; _render()
193
+ elif ch == b'G':
194
+ selected = n - 1; _render()
195
+ elif ch in (b'\x03', b'\x04'):
196
+ return -1
197
+
198
+ try:
199
+ _esc_watcher.pause()
200
+ tty.setcbreak(fd)
201
+ sys.stdout.flush()
202
+
203
+ # Top boundary
204
+ _raw(f"\n \033[2m{_rule}\033[0m\n")
205
+ if title:
206
+ _raw(f" \033[1m{title}\033[0m \033[2m{controls_hint}\033[0m\n\n")
207
+ else:
208
+ _raw(f" \033[2m{controls_hint}\033[0m\n\n")
209
+
210
+ _render()
211
+ result = _choose()
212
+ return result
213
+ except (EOFError, KeyboardInterrupt, OSError):
214
+ return -1
215
+ finally:
216
+ termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
217
+ _esc_watcher.resume()
218
+ if collapse_to is not None and _render.drawn:
219
+ label = ""
220
+ if 0 <= result < n:
221
+ opt = options[result]
222
+ label = opt[0] if isinstance(opt, tuple) else opt
223
+ declined = result < 0 or label.strip().lower().startswith(("no", "否", "拒绝", "取消", "cancel"))
224
+ mark = "\033[31m✗\033[0m" if declined else "\033[32m✓\033[0m"
225
+ shown = label or "Cancelled"
226
+ subject = f" \033[2m{collapse_to}\033[0m" if collapse_to else ""
227
+ # Up over the header and the menu, clear to the end, one line instead.
228
+ _raw(f"\033[{header_height + _render.last_phys_height}A\r\033[J {mark} {shown}{subject}\n")
229
+ else:
230
+ _raw(f" \033[2m{_rule}\033[0m\n\n")
231
+
232
+
233
+ async def run_picker_in_thread(options: list, current_idx: int,
234
+ title: str, max_visible: int = 14,
235
+ controls_hint: str = "↑↓ Enter Esc/q Cancel") -> int:
236
+ """Run arrow_select in an executor thread to avoid kqueue conflicts on macOS."""
237
+ loop = asyncio.get_running_loop()
238
+ return await loop.run_in_executor(
239
+ None,
240
+ lambda: arrow_select(
241
+ options, current_idx, title, max_visible, controls_hint
242
+ ),
243
+ )
244
+
245
+
246
+ # Back-compat aliases used by aria_cli.py
247
+ _arrow_select = arrow_select
248
+ _run_picker_in_thread = run_picker_in_thread
@@ -0,0 +1,11 @@
1
+ """UI rendering helpers — team, finance, market output formatters."""
2
+
3
+ from .team import render_verdict_banner, render_team_table
4
+ from .finance import render_macro_result, render_cb_rates, render_econ_calendar
5
+ from .market import print_quote_result, print_ta_result
6
+
7
+ __all__ = [
8
+ "render_verdict_banner", "render_team_table",
9
+ "render_macro_result", "render_cb_rates", "render_econ_calendar",
10
+ "print_quote_result", "print_ta_result",
11
+ ]