aria-code 0.52.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (478) hide show
  1. aria_code/__init__.py +42 -0
  2. aria_code/_version.py +20 -0
  3. aria_code/adk_apps/__init__.py +1 -0
  4. aria_code/adk_apps/aria_code_review/__init__.py +1 -0
  5. aria_code/adk_apps/aria_code_review/agent.py +32 -0
  6. aria_code/adk_apps/aria_research/__init__.py +1 -0
  7. aria_code/adk_apps/aria_research/agent.py +31 -0
  8. aria_code/agents/__init__.py +34 -0
  9. aria_code/agents/base.py +318 -0
  10. aria_code/agents/code_review.py +200 -0
  11. aria_code/agents/deep/__init__.py +37 -0
  12. aria_code/agents/deep/calibration_loop.py +144 -0
  13. aria_code/agents/deep/critic.py +125 -0
  14. aria_code/agents/deep/deepen.py +193 -0
  15. aria_code/agents/deep/models.py +149 -0
  16. aria_code/agents/deep/pipeline.py +164 -0
  17. aria_code/agents/deep/quant_fusion.py +192 -0
  18. aria_code/agents/deep/themes.py +95 -0
  19. aria_code/agents/deep/tiers.py +106 -0
  20. aria_code/agents/engineering/__init__.py +14 -0
  21. aria_code/agents/engineering/coder.py +222 -0
  22. aria_code/agents/engineering/tester.py +145 -0
  23. aria_code/agents/financial/__init__.py +21 -0
  24. aria_code/agents/financial/cashflow_burn.py +119 -0
  25. aria_code/agents/financial/catalyst.py +279 -0
  26. aria_code/agents/financial/corporate_finance.py +175 -0
  27. aria_code/agents/financial/debate.py +224 -0
  28. aria_code/agents/financial/earnings.py +303 -0
  29. aria_code/agents/financial/fundamental.py +191 -0
  30. aria_code/agents/financial/macro.py +99 -0
  31. aria_code/agents/financial/news.py +207 -0
  32. aria_code/agents/financial/risk.py +165 -0
  33. aria_code/agents/financial/sector.py +279 -0
  34. aria_code/agents/financial/strategist.py +121 -0
  35. aria_code/agents/financial/stripe_revenue.py +127 -0
  36. aria_code/agents/financial/synthesis.py +274 -0
  37. aria_code/agents/financial/technical.py +258 -0
  38. aria_code/agents/orchestrator.py +44 -0
  39. aria_code/agents/portfolio_agent.py +363 -0
  40. aria_code/agents/realty/__init__.py +62 -0
  41. aria_code/agents/realty/asset_diagnosis.py +152 -0
  42. aria_code/agents/realty/business_match.py +166 -0
  43. aria_code/agents/realty/cashflow_verify.py +209 -0
  44. aria_code/agents/realty/contract_rules.py +210 -0
  45. aria_code/agents/realty/energy_anomaly.py +189 -0
  46. aria_code/agents/realty/exit_settlement.py +208 -0
  47. aria_code/agents/realty/fulfillment_risk.py +206 -0
  48. aria_code/agents/realty/ops_optimize.py +160 -0
  49. aria_code/agents/realty/revenue_share.py +215 -0
  50. aria_code/agents/registry.py +158 -0
  51. aria_code/agents/signal_scheme.py +111 -0
  52. aria_code/agents/sports/__init__.py +0 -0
  53. aria_code/agents/sports/football_agent.py +197 -0
  54. aria_code/agents/supervisor.py +113 -0
  55. aria_code/agents/team.py +492 -0
  56. aria_code/agents/warehouse/__init__.py +25 -0
  57. aria_code/agents/warehouse/contracts.py +26 -0
  58. aria_code/agents/warehouse/dashboard.py +155 -0
  59. aria_code/agents/warehouse/fulfillment_leadtime.py +95 -0
  60. aria_code/agents/warehouse/inbound_exceptions.py +25 -0
  61. aria_code/agents/warehouse/inventory_health.py +24 -0
  62. aria_code/agents/warehouse/local_run.py +71 -0
  63. aria_code/agents/warehouse/local_snapshot.py +132 -0
  64. aria_code/agents/warehouse/logistics_cost.py +84 -0
  65. aria_code/agents/warehouse/logistics_sync.py +21 -0
  66. aria_code/agents/warehouse/workflow.py +31 -0
  67. aria_code/aliyun_data_client.py +4 -0
  68. aria_code/apps/README.md +12 -0
  69. aria_code/apps/__init__.py +2 -0
  70. aria_code/apps/channels/README.md +15 -0
  71. aria_code/apps/channels/__init__.py +17 -0
  72. aria_code/apps/channels/intake.py +92 -0
  73. aria_code/apps/channels/registry.py +95 -0
  74. aria_code/apps/channels/tradingview.py +94 -0
  75. aria_code/apps/cli/README.md +13 -0
  76. aria_code/apps/cli/__init__.py +2 -0
  77. aria_code/apps/cli/_optional.py +120 -0
  78. aria_code/apps/cli/bootstrap.py +145 -0
  79. aria_code/apps/cli/broker_render.py +206 -0
  80. aria_code/apps/cli/codegen_paths.py +29 -0
  81. aria_code/apps/cli/commands/__init__.py +16 -0
  82. aria_code/apps/cli/commands/_business_render.py +78 -0
  83. aria_code/apps/cli/commands/_ui.py +71 -0
  84. aria_code/apps/cli/commands/analysis_cmds.py +369 -0
  85. aria_code/apps/cli/commands/ashare_prediction_cmds.py +327 -0
  86. aria_code/apps/cli/commands/auth_cmds.py +239 -0
  87. aria_code/apps/cli/commands/backtest_cmds.py +2543 -0
  88. aria_code/apps/cli/commands/broker_cmds.py +1234 -0
  89. aria_code/apps/cli/commands/business_workflow_cmds.py +319 -0
  90. aria_code/apps/cli/commands/canvas_cmds.py +77 -0
  91. aria_code/apps/cli/commands/catalog.py +87 -0
  92. aria_code/apps/cli/commands/core_cmds.py +2520 -0
  93. aria_code/apps/cli/commands/data_cmds.py +457 -0
  94. aria_code/apps/cli/commands/diagnostic_cmds.py +230 -0
  95. aria_code/apps/cli/commands/diagnostic_ops_cmds.py +813 -0
  96. aria_code/apps/cli/commands/file_cmds.py +312 -0
  97. aria_code/apps/cli/commands/finance_service_cmds.py +60 -0
  98. aria_code/apps/cli/commands/fx_commodity_cmds.py +123 -0
  99. aria_code/apps/cli/commands/market.py +434 -0
  100. aria_code/apps/cli/commands/market_cmds.py +1381 -0
  101. aria_code/apps/cli/commands/market_context.py +425 -0
  102. aria_code/apps/cli/commands/market_render.py +7 -0
  103. aria_code/apps/cli/commands/model_cmds.py +2153 -0
  104. aria_code/apps/cli/commands/ops_cmds.py +721 -0
  105. aria_code/apps/cli/commands/orchestrator_cmds.py +179 -0
  106. aria_code/apps/cli/commands/pdf_export_cmds.py +125 -0
  107. aria_code/apps/cli/commands/portfolio_cmds.py +1278 -0
  108. aria_code/apps/cli/commands/report.py +437 -0
  109. aria_code/apps/cli/commands/scaffold_templates.py +617 -0
  110. aria_code/apps/cli/commands/session_cmds.py +236 -0
  111. aria_code/apps/cli/commands/session_ux_cmds.py +359 -0
  112. aria_code/apps/cli/commands/team.py +669 -0
  113. aria_code/apps/cli/commands/team_render.py +8 -0
  114. aria_code/apps/cli/commands/ui_cmds.py +401 -0
  115. aria_code/apps/cli/commands/warehouse_cmds.py +79 -0
  116. aria_code/apps/cli/commands/workflow_cmds.py +480 -0
  117. aria_code/apps/cli/commands/workspace_cmds.py +1494 -0
  118. aria_code/apps/cli/config_paths.py +73 -0
  119. aria_code/apps/cli/config_store.py +78 -0
  120. aria_code/apps/cli/constants.py +88 -0
  121. aria_code/apps/cli/context.py +34 -0
  122. aria_code/apps/cli/deterministic.py +191 -0
  123. aria_code/apps/cli/direct.py +48 -0
  124. aria_code/apps/cli/finance_service_catalog.py +111 -0
  125. aria_code/apps/cli/football_reports.py +231 -0
  126. aria_code/apps/cli/github_app_auth.py +135 -0
  127. aria_code/apps/cli/google_login.py +196 -0
  128. aria_code/apps/cli/handlers/__init__.py +11 -0
  129. aria_code/apps/cli/handlers/broker_handlers.py +122 -0
  130. aria_code/apps/cli/handlers/chart_handlers.py +1309 -0
  131. aria_code/apps/cli/handlers/market_handlers.py +2513 -0
  132. aria_code/apps/cli/handlers/realty_handlers.py +114 -0
  133. aria_code/apps/cli/handlers/sports_handlers.py +22 -0
  134. aria_code/apps/cli/handlers/strategy_advice.py +82 -0
  135. aria_code/apps/cli/helpers.py +302 -0
  136. aria_code/apps/cli/hooks.py +180 -0
  137. aria_code/apps/cli/i18n.py +297 -0
  138. aria_code/apps/cli/intent.py +136 -0
  139. aria_code/apps/cli/intent_router.py +276 -0
  140. aria_code/apps/cli/intent_signals.py +344 -0
  141. aria_code/apps/cli/lifecycle_hooks.py +48 -0
  142. aria_code/apps/cli/local_tool_schemas.py +536 -0
  143. aria_code/apps/cli/main.py +29 -0
  144. aria_code/apps/cli/market_metadata.py +135 -0
  145. aria_code/apps/cli/market_universe.py +487 -0
  146. aria_code/apps/cli/message_processing.py +310 -0
  147. aria_code/apps/cli/model_catalog.py +620 -0
  148. aria_code/apps/cli/pdf_report.py +977 -0
  149. aria_code/apps/cli/plan_mode.py +139 -0
  150. aria_code/apps/cli/plotly_html.py +15 -0
  151. aria_code/apps/cli/prediction_feedback.py +202 -0
  152. aria_code/apps/cli/preflight.py +502 -0
  153. aria_code/apps/cli/project_aria.py +60 -0
  154. aria_code/apps/cli/prompt_assembly.py +59 -0
  155. aria_code/apps/cli/prompts/__init__.py +0 -0
  156. aria_code/apps/cli/prompts/coding.py +53 -0
  157. aria_code/apps/cli/prompts/select.py +142 -0
  158. aria_code/apps/cli/prompts/system_prompts.py +552 -0
  159. aria_code/apps/cli/prompts/ui.py +436 -0
  160. aria_code/apps/cli/provider_endpoints.py +237 -0
  161. aria_code/apps/cli/provider_keys.py +73 -0
  162. aria_code/apps/cli/providers/__init__.py +1 -0
  163. aria_code/apps/cli/providers/base.py +521 -0
  164. aria_code/apps/cli/providers/chat_routing.py +128 -0
  165. aria_code/apps/cli/providers/collaboration.py +98 -0
  166. aria_code/apps/cli/providers/llm/__init__.py +1 -0
  167. aria_code/apps/cli/providers/llm/offline_responses.py +68 -0
  168. aria_code/apps/cli/providers/llm/ollama_stream.py +1594 -0
  169. aria_code/apps/cli/providers/llm/response_cache.py +60 -0
  170. aria_code/apps/cli/providers/llm/sse_stream.py +257 -0
  171. aria_code/apps/cli/providers/runtime_bridge.py +353 -0
  172. aria_code/apps/cli/providers/vertexai_stream.py +316 -0
  173. aria_code/apps/cli/runtime_consumer.py +657 -0
  174. aria_code/apps/cli/sandbox.py +32 -0
  175. aria_code/apps/cli/session_export.py +120 -0
  176. aria_code/apps/cli/session_jsonl.py +208 -0
  177. aria_code/apps/cli/session_store.py +112 -0
  178. aria_code/apps/cli/skills_catalog.py +273 -0
  179. aria_code/apps/cli/todo_tracker.py +190 -0
  180. aria_code/apps/cli/tool_executor.py +823 -0
  181. aria_code/apps/cli/tool_registry.py +34 -0
  182. aria_code/apps/cli/tool_scope.py +106 -0
  183. aria_code/apps/cli/tools/__init__.py +40 -0
  184. aria_code/apps/cli/tools/context.py +46 -0
  185. aria_code/apps/cli/tools/file_tools.py +180 -0
  186. aria_code/apps/cli/tools/market_tools.py +620 -0
  187. aria_code/apps/cli/tools/notebook_tools.py +111 -0
  188. aria_code/apps/cli/tools/system_tools.py +726 -0
  189. aria_code/apps/cli/tools/write_tools.py +845 -0
  190. aria_code/apps/cli/tradingview_bridge.py +529 -0
  191. aria_code/apps/cli/turn_planning.py +137 -0
  192. aria_code/apps/cli/update_check.py +153 -0
  193. aria_code/apps/cli/utils/__init__.py +0 -0
  194. aria_code/apps/cli/utils/market_detect.py +1597 -0
  195. aria_code/apps/daemon/README.md +14 -0
  196. aria_code/apps/vscode/README.md +115 -0
  197. aria_code/apps/vscode/package.json +70 -0
  198. aria_code/aria_cli.py +6743 -0
  199. aria_code/aria_daemon.py +1398 -0
  200. aria_code/aria_feishu_bot.py +1423 -0
  201. aria_code/aria_mcp_server.py +7 -0
  202. aria_code/aria_relay_client.py +4 -0
  203. aria_code/aria_relay_server.py +490 -0
  204. aria_code/aria_telegram_bot.py +202 -0
  205. aria_code/ariarc.py +385 -0
  206. aria_code/artifacts.py +581 -0
  207. aria_code/backtest_engine.py +4 -0
  208. aria_code/backtest_report.py +4 -0
  209. aria_code/brokers/__init__.py +78 -0
  210. aria_code/brokers/automation.py +193 -0
  211. aria_code/brokers/base.py +231 -0
  212. aria_code/brokers/capabilities.py +264 -0
  213. aria_code/brokers/cn/__init__.py +10 -0
  214. aria_code/brokers/cn/easytrader_broker.py +193 -0
  215. aria_code/brokers/cn/futu_broker.py +194 -0
  216. aria_code/brokers/cn/longbridge_broker.py +190 -0
  217. aria_code/brokers/cn/tiger_broker.py +196 -0
  218. aria_code/brokers/cn/xtquant_broker.py +225 -0
  219. aria_code/brokers/config.py +414 -0
  220. aria_code/brokers/intl/__init__.py +5 -0
  221. aria_code/brokers/intl/alpaca_broker.py +183 -0
  222. aria_code/brokers/intl/ibkr_broker.py +215 -0
  223. aria_code/brokers/intl/trading212_broker.py +183 -0
  224. aria_code/brokers/intl/webull_broker.py +156 -0
  225. aria_code/brokers/paper_broker.py +266 -0
  226. aria_code/brokers/planning.py +296 -0
  227. aria_code/brokers/registry.py +213 -0
  228. aria_code/brokers/trading.py +267 -0
  229. aria_code/canva_client.py +4 -0
  230. aria_code/change_store.py +127 -0
  231. aria_code/clients/__init__.py +0 -0
  232. aria_code/clients/aliyun_data_client.py +660 -0
  233. aria_code/clients/aria_relay_client.py +182 -0
  234. aria_code/clients/canva_client.py +284 -0
  235. aria_code/clients/figma_client.py +100 -0
  236. aria_code/clients/football_data_client.py +1671 -0
  237. aria_code/clients/kling_video_client.py +182 -0
  238. aria_code/clients/market_data_client.py +1976 -0
  239. aria_code/clients/openai_image_client.py +242 -0
  240. aria_code/clients/runway_video_client.py +157 -0
  241. aria_code/clients/warehouse_erp_client.py +105 -0
  242. aria_code/cloud_memory.py +181 -0
  243. aria_code/command_safety.py +19 -0
  244. aria_code/computer_use_tools.py +4 -0
  245. aria_code/dashboard_generator.py +579 -0
  246. aria_code/data_analysis_tools.py +4 -0
  247. aria_code/data_cleaner.py +483 -0
  248. aria_code/data_service.py +513 -0
  249. aria_code/datasources/__init__.py +23 -0
  250. aria_code/datasources/base.py +166 -0
  251. aria_code/datasources/router.py +253 -0
  252. aria_code/datasources/sources/__init__.py +15 -0
  253. aria_code/datasources/sources/akshare_source.py +269 -0
  254. aria_code/datasources/sources/alpha_vantage_source.py +203 -0
  255. aria_code/datasources/sources/edgar_source.py +219 -0
  256. aria_code/datasources/sources/finnhub_source.py +198 -0
  257. aria_code/datasources/sources/fred_source.py +223 -0
  258. aria_code/datasources/sources/tushare_source.py +143 -0
  259. aria_code/datasources/sources/web_scraper_source.py +278 -0
  260. aria_code/datasources/sources/world_bank_source.py +206 -0
  261. aria_code/datasources/sources/yfinance_source.py +152 -0
  262. aria_code/demo_player.py +207 -0
  263. aria_code/doctor.py +813 -0
  264. aria_code/domain/__init__.py +0 -0
  265. aria_code/domain/backtest_engine.py +354 -0
  266. aria_code/domain/backtest_report.py +472 -0
  267. aria_code/domain/finance_formulas.py +389 -0
  268. aria_code/domain/portfolio_ledger.py +307 -0
  269. aria_code/domain/strategy_vault.py +421 -0
  270. aria_code/evals/__init__.py +37 -0
  271. aria_code/evals/harness.py +598 -0
  272. aria_code/evals/runner.py +238 -0
  273. aria_code/external_agent_runner.py +115 -0
  274. aria_code/figma_client.py +4 -0
  275. aria_code/file_analysis_tools.py +4 -0
  276. aria_code/finance_formulas.py +4 -0
  277. aria_code/football_data_client.py +4 -0
  278. aria_code/image_gen_tools.py +4 -0
  279. aria_code/intent_classifier.py +386 -0
  280. aria_code/kling_video_client.py +4 -0
  281. aria_code/licensing.py +151 -0
  282. aria_code/local_finance_tools.py +4 -0
  283. aria_code/local_image_provider.py +4 -0
  284. aria_code/local_llm_provider.py +4 -0
  285. aria_code/macro_tools.py +4 -0
  286. aria_code/markdown_pdf.py +289 -0
  287. aria_code/market_data_client.py +4 -0
  288. aria_code/mcp_client.py +639 -0
  289. aria_code/memory_manager.py +246 -0
  290. aria_code/model_capability.py +486 -0
  291. aria_code/notification_tools.py +4 -0
  292. aria_code/openai_image_client.py +4 -0
  293. aria_code/packages/__init__.py +23 -0
  294. aria_code/packages/adk_bridge/__init__.py +11 -0
  295. aria_code/packages/adk_bridge/code_review_tools.py +49 -0
  296. aria_code/packages/adk_bridge/market_tools.py +125 -0
  297. aria_code/packages/aria_agents/__init__.py +5 -0
  298. aria_code/packages/aria_agents/manifest.py +78 -0
  299. aria_code/packages/aria_core/__init__.py +34 -0
  300. aria_code/packages/aria_core/architecture.py +269 -0
  301. aria_code/packages/aria_core/export.py +147 -0
  302. aria_code/packages/aria_core/manifest.py +65 -0
  303. aria_code/packages/aria_core/paths.py +57 -0
  304. aria_code/packages/aria_core/secure_file.py +68 -0
  305. aria_code/packages/aria_infra/__init__.py +15 -0
  306. aria_code/packages/aria_infra/arthera.py +52 -0
  307. aria_code/packages/aria_infra/doctor.py +246 -0
  308. aria_code/packages/aria_infra/product.py +40 -0
  309. aria_code/packages/aria_mcp/__init__.py +25 -0
  310. aria_code/packages/aria_mcp/bridge.py +201 -0
  311. aria_code/packages/aria_mcp/circuit.py +82 -0
  312. aria_code/packages/aria_mcp/config.py +111 -0
  313. aria_code/packages/aria_mcp/installer.py +95 -0
  314. aria_code/packages/aria_mcp/server.py +1550 -0
  315. aria_code/packages/aria_mcp/tools.py +81 -0
  316. aria_code/packages/aria_sdk/__init__.py +19 -0
  317. aria_code/packages/aria_sdk/client.py +396 -0
  318. aria_code/packages/aria_sdk/providers.py +70 -0
  319. aria_code/packages/aria_sdk/streaming.py +79 -0
  320. aria_code/packages/aria_sdk/types.py +86 -0
  321. aria_code/packages/aria_services/__init__.py +92 -0
  322. aria_code/packages/aria_services/cache.py +60 -0
  323. aria_code/packages/aria_services/context.py +356 -0
  324. aria_code/packages/aria_services/context_checkpoints.py +157 -0
  325. aria_code/packages/aria_services/data.py +11 -0
  326. aria_code/packages/aria_services/provider_health.py +268 -0
  327. aria_code/packages/aria_services/references.py +247 -0
  328. aria_code/packages/aria_services/registry.py +249 -0
  329. aria_code/packages/aria_services/research_protocol.py +57 -0
  330. aria_code/packages/aria_services/research_quality.py +186 -0
  331. aria_code/packages/aria_services/settings.py +157 -0
  332. aria_code/packages/aria_services/usage.py +151 -0
  333. aria_code/packages/aria_skills/__init__.py +46 -0
  334. aria_code/packages/aria_skills/catalog.py +149 -0
  335. aria_code/packages/aria_skills/loader.py +455 -0
  336. aria_code/packages/aria_skills/registry.py +84 -0
  337. aria_code/packages/aria_tools/__init__.py +5 -0
  338. aria_code/packages/aria_tools/financial/__init__.py +8 -0
  339. aria_code/packages/aria_tools/financial/_paths.py +130 -0
  340. aria_code/packages/aria_tools/financial/compliance.py +31 -0
  341. aria_code/packages/aria_tools/financial/factors.py +33 -0
  342. aria_code/packages/aria_tools/financial/risk_tools.py +33 -0
  343. aria_code/packages/aria_tools/financial/strategy.py +31 -0
  344. aria_code/packages/aria_tools/registry.py +128 -0
  345. aria_code/packages/quant_engine/__init__.py +34 -0
  346. aria_code/packages/quant_engine/_namespace.py +62 -0
  347. aria_code/packages/quant_engine/backtest/__init__.py +14 -0
  348. aria_code/packages/quant_engine/backtest/core.py +53 -0
  349. aria_code/packages/quant_engine/backtest/engine.py +96 -0
  350. aria_code/packages/quant_engine/portfolio/__init__.py +13 -0
  351. aria_code/packages/quant_engine/portfolio/optimizer.py +85 -0
  352. aria_code/packages/quant_engine/sports/__init__.py +80 -0
  353. aria_code/packages/quant_engine/sports/calibrator.py +354 -0
  354. aria_code/packages/quant_engine/sports/dixon_coles.py +234 -0
  355. aria_code/packages/quant_engine/sports/elo.py +300 -0
  356. aria_code/packages/quant_engine/sports/form.py +188 -0
  357. aria_code/packages/quant_engine/sports/h2h.py +195 -0
  358. aria_code/packages/quant_engine/sports/ml_model.py +377 -0
  359. aria_code/packages/quant_engine/sports/predictor.py +312 -0
  360. aria_code/packages/quant_engine/sports/tracker.py +665 -0
  361. aria_code/packages/quant_engine/stochastic/__init__.py +35 -0
  362. aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +195 -0
  363. aria_code/packages/quant_engine/stochastic/ito_calculus.py +477 -0
  364. aria_code/packages/quant_engine/stochastic/kelly_criterion.py +181 -0
  365. aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +95 -0
  366. aria_code/packages/quant_engine/stochastic/options_pricing.py +576 -0
  367. aria_code/packages/quant_engine/stochastic/stochastic_processes.py +90 -0
  368. aria_code/packs/__init__.py +85 -0
  369. aria_code/packs/base.py +168 -0
  370. aria_code/packs/finance/__init__.py +250 -0
  371. aria_code/packs/logistics/__init__.py +169 -0
  372. aria_code/packs/payments/__init__.py +139 -0
  373. aria_code/packs/realty/__init__.py +190 -0
  374. aria_code/packs/registry.py +202 -0
  375. aria_code/packs/rules.py +90 -0
  376. aria_code/plan_utils.py +194 -0
  377. aria_code/plugin_loader.py +328 -0
  378. aria_code/portfolio_ledger.py +4 -0
  379. aria_code/preview_server.py +449 -0
  380. aria_code/privacy/__init__.py +5 -0
  381. aria_code/privacy/feedback.py +123 -0
  382. aria_code/project_review.py +278 -0
  383. aria_code/project_review_api.py +235 -0
  384. aria_code/project_review_server.py +18 -0
  385. aria_code/project_tools.py +4 -0
  386. aria_code/providers/__init__.py +30 -0
  387. aria_code/providers/llm/__init__.py +19 -0
  388. aria_code/providers/llm/anthropic.py +184 -0
  389. aria_code/providers/llm/autoconfig.py +213 -0
  390. aria_code/providers/llm/base.py +139 -0
  391. aria_code/providers/llm/custom.py +158 -0
  392. aria_code/providers/llm/ollama.py +129 -0
  393. aria_code/providers/llm/openai_compat.py +313 -0
  394. aria_code/providers/llm/registry.py +444 -0
  395. aria_code/providers/local_image_provider.py +202 -0
  396. aria_code/providers/local_llm_provider.py +589 -0
  397. aria_code/realty_data_tools.py +4 -0
  398. aria_code/report_exporters.py +150 -0
  399. aria_code/report_generator.py +1764 -0
  400. aria_code/runtime/__init__.py +169 -0
  401. aria_code/runtime/acceptance.py +481 -0
  402. aria_code/runtime/agent_loop.py +1520 -0
  403. aria_code/runtime/approval.py +57 -0
  404. aria_code/runtime/budget.py +232 -0
  405. aria_code/runtime/checkpoints.py +432 -0
  406. aria_code/runtime/crash_report.py +174 -0
  407. aria_code/runtime/events.py +113 -0
  408. aria_code/runtime/gateway.py +150 -0
  409. aria_code/runtime/lsp.py +484 -0
  410. aria_code/runtime/orchestrator.py +55 -0
  411. aria_code/runtime/repo_map.py +700 -0
  412. aria_code/runtime/run_state.py +127 -0
  413. aria_code/runtime/run_store.py +450 -0
  414. aria_code/runtime/self_healing.py +422 -0
  415. aria_code/runtime/subagent.py +547 -0
  416. aria_code/runtime/task_ledger.py +86 -0
  417. aria_code/runtime/task_orchestrator.py +90 -0
  418. aria_code/runtime/tool_executor.py +217 -0
  419. aria_code/runtime/tool_policy.py +107 -0
  420. aria_code/runtime/worktrees.py +215 -0
  421. aria_code/runway_video_client.py +4 -0
  422. aria_code/safety/__init__.py +23 -0
  423. aria_code/safety/permissions.py +306 -0
  424. aria_code/safety/service.py +102 -0
  425. aria_code/setup_wizard.py +673 -0
  426. aria_code/spreadsheet_tools.py +4 -0
  427. aria_code/strategy_vault.py +4 -0
  428. aria_code/tools/__init__.py +0 -0
  429. aria_code/tools/artifact_tools.py +252 -0
  430. aria_code/tools/broker_tools.py +92 -0
  431. aria_code/tools/build_quant_engine.py +97 -0
  432. aria_code/tools/code_audit_tools.py +192 -0
  433. aria_code/tools/computer_use_tools.py +504 -0
  434. aria_code/tools/data_analysis_tools.py +809 -0
  435. aria_code/tools/enterprise_finance_tools.py +156 -0
  436. aria_code/tools/extended_tools.py +240 -0
  437. aria_code/tools/file_analysis_tools.py +885 -0
  438. aria_code/tools/image_gen_tools.py +114 -0
  439. aria_code/tools/local_finance_tools.py +3417 -0
  440. aria_code/tools/logistics_tools.py +135 -0
  441. aria_code/tools/macro_tools.py +369 -0
  442. aria_code/tools/notification_tools.py +249 -0
  443. aria_code/tools/project_tools.py +525 -0
  444. aria_code/tools/realty_data_tools.py +659 -0
  445. aria_code/tools/spreadsheet_tools.py +388 -0
  446. aria_code/tools/stripe_tools.py +115 -0
  447. aria_code/ui/__init__.py +105 -0
  448. aria_code/ui/banner.py +508 -0
  449. aria_code/ui/completer.py +501 -0
  450. aria_code/ui/console.py +281 -0
  451. aria_code/ui/image_render.py +243 -0
  452. aria_code/ui/input_box.py +488 -0
  453. aria_code/ui/picker.py +201 -0
  454. aria_code/ui/render/__init__.py +11 -0
  455. aria_code/ui/render/finance.py +1705 -0
  456. aria_code/ui/render/market.py +225 -0
  457. aria_code/ui/render/output.py +775 -0
  458. aria_code/ui/render/responsive.py +75 -0
  459. aria_code/ui/render/team.py +354 -0
  460. aria_code/ui/robot.py +235 -0
  461. aria_code/ui/startup_dashboard.py +109 -0
  462. aria_code/utils/vscode_uri.py +37 -0
  463. aria_code/video_analysis.py +147 -0
  464. aria_code/video_editor.py +271 -0
  465. aria_code/workspace/__init__.py +6 -0
  466. aria_code/workspace/files.py +193 -0
  467. aria_code/workspace/verify.py +113 -0
  468. aria_code/workspace_changes.py +199 -0
  469. aria_code/workspace_context.py +233 -0
  470. aria_code/workspace_service.py +196 -0
  471. aria_code/workspace_tools.py +150 -0
  472. aria_code-0.52.0.dist-info/METADATA +237 -0
  473. aria_code-0.52.0.dist-info/RECORD +478 -0
  474. aria_code-0.52.0.dist-info/WHEEL +5 -0
  475. aria_code-0.52.0.dist-info/entry_points.txt +3 -0
  476. aria_code-0.52.0.dist-info/licenses/LICENSE +201 -0
  477. aria_code-0.52.0.dist-info/licenses/NOTICE +49 -0
  478. aria_code-0.52.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,501 @@
1
+ """prompt_toolkit completer and base style for the Aria REPL.
2
+
3
+ Improvements over the original:
4
+ - Instant popup: triggers as soon as "/" is typed (no extra keypress needed)
5
+ - Fuzzy match: "/ch" matches /chart, /check, /watch; "/ta" matches /stat-arb
6
+ - Matched chars highlighted in amber so they're visible in all rows
7
+ - Results ranked: exact-prefix > fuzzy-command > description-fuzzy
8
+ - Category tag shown in display_meta (市场 / 分析 / 量化 / 数据源 …)
9
+
10
+ from ui.completer import AriaPTCompleter, ARIA_PT_STYLE
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import re
16
+ from pathlib import Path
17
+ from typing import Iterator, List, Tuple
18
+
19
+ from aria_code.ui.console import HAS_PT
20
+ from aria_code.packages.aria_services.references import REFERENCE_KINDS, reference_search_roots
21
+
22
+ _REFERENCE_KIND_NAMES = frozenset(item.name for item in REFERENCE_KINDS)
23
+
24
+ # ── Category map ────────────────────────────────────────────────────────────
25
+ # Keyed on command name fragments; first match wins.
26
+ _CATS: List[Tuple[Tuple[str, ...], str]] = [
27
+ (("/quote", "/market", "/macro", "/watch", "/alert", "/hot", "/indices",
28
+ "/cn", "/hk", "/crypto", "/forex", "/commodity", "/funding", "/feargreed",
29
+ "/edgar", "/datasource"), "市场"),
30
+ (("/team", "/analyze", "/options", "/factor", "/ta", "/ichimoku",
31
+ "/peer", "/quality", "/risk", "/signal", "/predict", "/earnings",
32
+ "/insights", "/deep", "/morning", "/trade-idea", "/research"), "分析"),
33
+ (("/backtest", "/wf", "/compare", "/execution", "/stat-arb",
34
+ "/ptbt", "/corr", "/optimize", "/stress", "/auto-strategy",
35
+ "/portfolio", "/journal"), "量化"),
36
+ (("/chart", "/report", "/shortterm", "/longterm", "/cloudbt"), "图表"),
37
+ (("/project", "/file", "/run", "/code", "/scaffold", "/init",
38
+ "/review", "/vision", "/browser", "/web"), "工具"),
39
+ (("/config", "/model", "/apikey", "/setup", "/local", "/mcp",
40
+ "/memory", "/cost", "/version"), "设置"),
41
+ (("/help", "/clear", "/btw", "/recap", "/exit", "/quit", "/history", "/session",
42
+ "/bug", "/feedback", "/privacy"), "系统"),
43
+ ]
44
+
45
+ _CAT_BADGE: dict[str, str] = {
46
+ "市场": "mkt",
47
+ "分析": "ana",
48
+ "量化": "qnt",
49
+ "图表": "viz",
50
+ "工具": "dev",
51
+ "设置": "cfg",
52
+ "系统": "sys",
53
+ }
54
+
55
+
56
+ def _get_cat(name: str) -> str:
57
+ for prefixes, cat in _CATS:
58
+ for p in prefixes:
59
+ if name.startswith(p):
60
+ return cat
61
+ return ""
62
+
63
+
64
+ # ── Fuzzy matching ───────────────────────────────────────────────────────────
65
+
66
+ def _fuzzy(pattern: str, text: str) -> Tuple[bool, List[int]]:
67
+ """
68
+ Sequential fuzzy match — pattern chars must appear in order in text.
69
+ Returns (matched, indices_of_matched_chars_in_text).
70
+ Consecutive matches score higher because they produce a compact index list.
71
+ """
72
+ if not pattern:
73
+ return True, []
74
+ pi = 0
75
+ indices: List[int] = []
76
+ for i, ch in enumerate(text):
77
+ if ch.lower() == pattern[pi].lower():
78
+ indices.append(i)
79
+ pi += 1
80
+ if pi == len(pattern):
81
+ return True, indices
82
+ return False, []
83
+
84
+
85
+ def _score(name: str, pattern: str, indices: List[int]) -> int:
86
+ """
87
+ Lower score = better.
88
+ 0 exact match
89
+ 1 exact prefix (/ch → /chart)
90
+ 5 word-segment exact match (/arb → /stat-arb because '-arb' segment)
91
+ 10 consecutive run from position 0
92
+ 12+ consecutive run from a word boundary
93
+ 15+ consecutive run from elsewhere
94
+ 20+ non-consecutive from a word boundary
95
+ 30+ scattered fuzzy match
96
+ """
97
+ if name == pattern:
98
+ return 0
99
+ if name.startswith(pattern):
100
+ return 1
101
+ if not indices:
102
+ return 99
103
+
104
+ # Word-segment exact match: pattern matches a whole segment after "-" or "_"
105
+ bare = name.lstrip("/")
106
+ pat_bare = pattern.lstrip("/")
107
+ for sep in ("-", "_"):
108
+ for seg in bare.split(sep)[1:]: # skip first segment (already caught by prefix)
109
+ if seg == pat_bare or seg.startswith(pat_bare):
110
+ return 5 + len(sep) # score 6 for "-", 6 for "_"
111
+
112
+ start = indices[0]
113
+ consecutive = (indices == list(range(start, start + len(indices))))
114
+ at_boundary = start == 0 or (start > 0 and bare[start - 1] in "-_")
115
+
116
+ if consecutive:
117
+ if start == 0:
118
+ return 10
119
+ if at_boundary:
120
+ return 12 + start
121
+ return 15 + start
122
+ if at_boundary:
123
+ return 20 + start
124
+ return 30 + start
125
+
126
+
127
+ # ── FormattedText display builder ────────────────────────────────────────────
128
+
129
+ def _highlighted(name: str, matched_indices: List[int]) -> List[Tuple[str, str]]:
130
+ """
131
+ Build a FormattedText list: matched chars get 'class:fz-hi', rest are plain.
132
+ """
133
+ idx_set = set(matched_indices)
134
+ parts: List[Tuple[str, str]] = []
135
+ for i, ch in enumerate(name):
136
+ if i in idx_set:
137
+ parts.append(("class:fz-hi", ch))
138
+ else:
139
+ parts.append(("", ch))
140
+ return parts
141
+
142
+
143
+ if HAS_PT:
144
+ import os as _os
145
+ from prompt_toolkit.completion import Completer, Completion
146
+ from prompt_toolkit.formatted_text import FormattedText
147
+ from prompt_toolkit.styles import Style as PTStyle
148
+
149
+ class AriaPTCompleter(Completer):
150
+ """
151
+ Slash-command completer with instant popup + fuzzy search.
152
+
153
+ Activates the moment the user types "/" (complete_while_typing=True
154
+ is already set in PromptSession, so no extra keypress is needed).
155
+
156
+ Triggers:
157
+ / → show ALL slash commands (fuzzy matched)
158
+ @ → file/directory path autocomplete (@ anywhere in input)
159
+ ! → shell history autocomplete (first word after !)
160
+
161
+ Matching:
162
+ / → show ALL commands sorted by category order
163
+ /ch → fuzzy-match "ch" against command names, highlight hits
164
+ /stat → matches /stat-arb even though it's not a prefix
165
+ /team AAPL → only complete the command part (stop after first space)
166
+ """
167
+
168
+ def __init__(
169
+ self,
170
+ commands_dict: dict,
171
+ skills: list,
172
+ watchlist: list,
173
+ *,
174
+ workspace: Path | str | None = None,
175
+ output_root: Path | str | None = None,
176
+ lang: str = "en",
177
+ ):
178
+ self.commands = commands_dict
179
+ self.skills = skills
180
+ self.workspace = Path(workspace or Path.cwd()).expanduser().resolve()
181
+ self.output_root = Path(output_root).expanduser().resolve() if output_root else None
182
+ self.lang = "zh" if str(lang).lower().startswith("zh") else "en"
183
+ self._shell_history: list[str] = [] # populated by REPL after ! commands
184
+ self.symbols = sorted(set([
185
+ "AAPL", "MSFT", "GOOGL", "AMZN", "TSLA", "NVDA", "META",
186
+ "NFLX", "AMD", "INTC", "SPY", "QQQ", "DIA", "IWM",
187
+ "BTC-USD", "ETH-USD", "SOL-USD",
188
+ "JPM", "BAC", "GS", "V", "MA", "UNH", "JNJ", "XOM",
189
+ "GLD", "SLV", "USO", "TLT", "HYG",
190
+ ] + list(watchlist)))
191
+
192
+ # Pre-compute category for each command
193
+ self._cmd_cat: dict[str, str] = {}
194
+ for name in self.commands:
195
+ self._cmd_cat[name] = _get_cat(name)
196
+ for s in self.skills:
197
+ self._cmd_cat[s["command"]] = _get_cat(s["command"])
198
+
199
+ def get_completions(self, document, complete_event) -> Iterator[Completion]:
200
+ text = document.text_before_cursor
201
+ ltext = text.lstrip()
202
+
203
+ # ── @ context reference autocomplete ───────────────────────────
204
+ # References work anywhere in a prompt. Email addresses do not.
205
+ ref_match = re.search(r"(?<![\w@])@([^\s@]*)$", text)
206
+ if ref_match:
207
+ yield from self._reference_completions(ref_match.group(1))
208
+ return
209
+
210
+ # ── ! shell command autocomplete ────────────────────────────────
211
+ if ltext.startswith("!"):
212
+ shell_frag = ltext[1:].lstrip()
213
+ if shell_frag:
214
+ for hist_cmd in reversed(self._shell_history):
215
+ if hist_cmd.startswith(shell_frag) and hist_cmd != shell_frag:
216
+ yield Completion(
217
+ hist_cmd,
218
+ start_position=-(len(ltext) - 1),
219
+ display=FormattedText([("class:fz-hi", hist_cmd)]),
220
+ display_meta="shell history",
221
+ )
222
+ return
223
+
224
+ # Only activate for slash commands
225
+ if not ltext.startswith("/"):
226
+ return
227
+
228
+ # Don't complete after first space — user is typing arguments
229
+ if " " in ltext:
230
+ return
231
+
232
+ # The typed prefix after "/"
233
+ pattern = ltext # includes leading "/"
234
+
235
+ # --- Build candidate list with scores ---
236
+ candidates: list[tuple[int, str, list[int], str, str]] = []
237
+ # (score, name, matched_indices, desc, category)
238
+
239
+ all_cmds = list(self.commands.items())
240
+ for name, (_, desc) in all_cmds:
241
+ cmd_part = name # e.g. "/chart"
242
+ matched, indices = _fuzzy(pattern.lstrip("/"), cmd_part.lstrip("/"))
243
+ if not matched and pattern != "/":
244
+ # Also try matching with the slash included
245
+ matched2, indices2 = _fuzzy(pattern, cmd_part)
246
+ if not matched2:
247
+ continue
248
+ indices = indices2
249
+ score = _score(cmd_part, pattern, indices)
250
+ cat = self._cmd_cat.get(name, "")
251
+ candidates.append((score, name, indices, desc, cat))
252
+
253
+ for s in self.skills:
254
+ cmd = s["command"]
255
+ desc = s.get("description", "")
256
+ matched, indices = _fuzzy(pattern.lstrip("/"), cmd.lstrip("/"))
257
+ if not matched and pattern != "/":
258
+ continue
259
+ score = _score(cmd, pattern, indices)
260
+ cat = self._cmd_cat.get(cmd, "")
261
+ candidates.append((score, cmd, indices, desc, cat))
262
+
263
+ # Sort: primary = score, secondary = name
264
+ candidates.sort(key=lambda x: (x[0], x[1]))
265
+
266
+ # Emit Completions
267
+ for score, name, indices, desc, cat in candidates:
268
+ # Build highlighted display (amber on matched chars)
269
+ display_parts = _highlighted(name, indices if pattern != "/" else [])
270
+
271
+ # Category badge as short suffix in display
272
+ badge = _CAT_BADGE.get(cat, "")
273
+ if badge:
274
+ display_parts += [("class:fz-cat", f" {badge}")]
275
+
276
+ # Truncate description to ~45 chars for meta column
277
+ cat_label = {
278
+ "市场": "市场" if self.lang == "zh" else "Market",
279
+ "分析": "研究" if self.lang == "zh" else "Research",
280
+ "量化": "量化" if self.lang == "zh" else "Quant",
281
+ "图表": "可视化" if self.lang == "zh" else "Visualize",
282
+ "工具": "开发工具" if self.lang == "zh" else "Developer",
283
+ "设置": "运行设置" if self.lang == "zh" else "Runtime",
284
+ "系统": "会话" if self.lang == "zh" else "Session",
285
+ }.get(cat, "")
286
+ meta_body = desc[:38] + ("…" if len(desc) > 38 else "")
287
+ meta_str = f"{cat_label} · {meta_body}" if cat_label else meta_body
288
+
289
+ # start_position: replace the entire typed prefix
290
+ start = -len(pattern)
291
+
292
+ yield Completion(
293
+ text = name,
294
+ start_position = start,
295
+ display = FormattedText(display_parts),
296
+ display_meta = meta_str,
297
+ )
298
+
299
+ def _reference_completions(self, frag: str) -> Iterator[Completion]:
300
+ """Complete typed reference namespaces and their values."""
301
+ if ":" not in frag:
302
+ lowered = frag.lower()
303
+ for kind in REFERENCE_KINDS:
304
+ if kind.name.startswith(lowered):
305
+ label = kind.label_zh if self.lang == "zh" else kind.label_en
306
+ yield Completion(
307
+ f"{kind.name}:",
308
+ start_position=-len(frag),
309
+ display=FormattedText([
310
+ ("class:fz-hi", f"@{kind.name}"),
311
+ ("class:fz-cat", ":"),
312
+ ]),
313
+ display_meta=label,
314
+ )
315
+ # Keep the first-level @ menu semantic and compact. Plain-path
316
+ # completion remains available only after an explicit path
317
+ # prefix; normal discovery goes through @file:/@folder:.
318
+ if frag and (frag.startswith((".", "/", "~")) or "/" in frag):
319
+ yield from self._file_completions(frag)
320
+ return
321
+
322
+ kind, value_frag = frag.split(":", 1)
323
+ kind = kind.lower()
324
+ if kind == "asset":
325
+ for symbol in self.symbols:
326
+ if symbol.lower().startswith(value_frag.lower()):
327
+ yield Completion(
328
+ f"asset:{symbol}",
329
+ start_position=-len(frag),
330
+ display=FormattedText([("class:fz-hi", symbol)]),
331
+ display_meta="市场资产" if self.lang == "zh" else "market asset",
332
+ )
333
+ return
334
+ if kind in {"file", "folder"}:
335
+ yield from self._file_completions(
336
+ value_frag,
337
+ value_prefix=f"{kind}:",
338
+ directories_only=(kind == "folder"),
339
+ )
340
+ return
341
+ if kind in _REFERENCE_KIND_NAMES:
342
+ yield from self._named_resource_completions(kind, value_frag)
343
+
344
+ def _file_completions(
345
+ self,
346
+ frag: str,
347
+ *,
348
+ value_prefix: str = "",
349
+ directories_only: bool = False,
350
+ ) -> Iterator[Completion]:
351
+ """Yield workspace-relative file/directory reference completions."""
352
+ try:
353
+ expanded = _os.path.expanduser(frag) if frag.startswith("~") else frag
354
+ base_fragment = _os.path.dirname(expanded) or "."
355
+ base_dir = Path(base_fragment)
356
+ if not base_dir.is_absolute():
357
+ base_dir = self.workspace / base_dir
358
+ prefix = _os.path.basename(frag)
359
+ if not base_dir.is_dir():
360
+ return
361
+ for entry in sorted(_os.listdir(base_dir))[:60]:
362
+ if entry.startswith("."):
363
+ continue
364
+ if not entry.lower().startswith(prefix.lower()):
365
+ continue
366
+ candidate = base_dir / entry
367
+ is_dir = candidate.is_dir()
368
+ if directories_only and not is_dir:
369
+ continue
370
+ if Path(expanded).is_absolute():
371
+ full = str(candidate)
372
+ else:
373
+ parent = _os.path.dirname(frag)
374
+ full = _os.path.join(parent, entry) if parent else entry
375
+ display_parts = [("class:fz-hi", prefix), ("", entry[len(prefix):])]
376
+ if is_dir:
377
+ display_parts.append(("class:fz-cat", "/"))
378
+ yield Completion(
379
+ value_prefix + full + ("/" if is_dir else ""),
380
+ start_position=-(len(value_prefix) + len(frag)),
381
+ display=FormattedText(display_parts),
382
+ display_meta="dir" if is_dir else "file",
383
+ )
384
+ except Exception:
385
+ pass
386
+
387
+ def _named_resource_completions(self, kind: str, frag: str) -> Iterator[Completion]:
388
+ seen: set[str] = set()
389
+ emitted = 0
390
+ for root in reference_search_roots(kind, self.workspace, self.output_root):
391
+ if not root.is_dir():
392
+ continue
393
+ try:
394
+ for path in root.rglob("*"):
395
+ if not path.is_file() or any(part.startswith(".") for part in path.relative_to(root).parts):
396
+ continue
397
+ name = path.stem
398
+ if name in seen or not name.lower().startswith(frag.lower()):
399
+ continue
400
+ seen.add(name)
401
+ yield Completion(
402
+ f"{kind}:{name}",
403
+ start_position=-(len(kind) + 1 + len(frag)),
404
+ display=FormattedText([("class:fz-hi", name)]),
405
+ display_meta=kind,
406
+ )
407
+ emitted += 1
408
+ if emitted >= 40:
409
+ return
410
+ except OSError:
411
+ continue
412
+
413
+ def add_shell_history(self, cmd: str) -> None:
414
+ """Called by REPL after each ! command to update shell autocomplete."""
415
+ cmd = cmd.strip()
416
+ if cmd and cmd not in self._shell_history:
417
+ self._shell_history.append(cmd)
418
+ if len(self._shell_history) > 200:
419
+ self._shell_history = self._shell_history[-200:]
420
+
421
+ # ── Style ────────────────────────────────────────────────────────────────
422
+ # Theme-aware completion menu in the 5-color palette.
423
+ # Selection + fuzzy highlight use copper (brand); the menu surface
424
+ # matches the terminal theme so it never floats as a dark popup on a
425
+ # light terminal (or vice-versa).
426
+
427
+ # Copper-palette menu colors per theme.
428
+ # bg = menu surface (sits clearly above terminal bg)
429
+ # fg = row text
430
+ # sel_bg = selected row (copper tint)
431
+ # sel_fg = selected row text (copper, bold-applied at use site)
432
+ # meta = description column (dim)
433
+ # hi = fuzzy-matched chars (copper)
434
+ _MENU_THEMES = {
435
+ "dark": dict(
436
+ bg="#161b22", fg="#c9d1d9",
437
+ sel_bg="#3a2e20", sel_fg="#e8c9a6",
438
+ meta="#6e7681", meta_cur="#c0a585",
439
+ scroll_bg="#161b22", scroll_btn="#C08050", # copper position handle
440
+ hi="#C08050", cat="#6e7681",
441
+ base_bg="#0d1117", prompt="#8b949e", ph="#484f58",
442
+ tb_fg="#8b949e", tb_bg="#161b22",
443
+ ),
444
+ "light": dict(
445
+ bg="#f2eee4", fg="#24292f", # warm surface, high contrast
446
+ sel_bg="#e7e1d3", sel_fg="#8a5a00", # stronger copper selection
447
+ meta="#6e7781", meta_cur="#8a5a00",
448
+ scroll_bg="#e7e1d3", scroll_btn="#9a6700", # copper position handle
449
+ hi="#9a6700", cat="#6e7781",
450
+ base_bg="default", prompt="#57606a", ph="#6e7781",
451
+ tb_fg="#57606a", tb_bg="#e7e1d3",
452
+ ),
453
+ }
454
+
455
+ def _detect_theme() -> str:
456
+ try:
457
+ from ui.input_box import detect_terminal_theme
458
+ return detect_terminal_theme()
459
+ except Exception:
460
+ return "dark"
461
+
462
+ def build_aria_pt_style(theme: str = "auto") -> "PTStyle":
463
+ """Build a theme-aware PromptSession style in the copper palette."""
464
+ if theme == "auto":
465
+ theme = _detect_theme()
466
+ c = _MENU_THEMES.get(theme, _MENU_THEMES["dark"])
467
+ base = f"{c['fg']} bg:{c['base_bg']}" if c["base_bg"] != "default" else c["fg"]
468
+ return PTStyle.from_dict({
469
+ "": base,
470
+ "prompt": c["prompt"],
471
+ "placeholder": c["ph"],
472
+ "input-bg": base,
473
+ "bottom-toolbar": f"noreverse {c['tb_fg']} bg:{c['tb_bg']}",
474
+ "bottom-toolbar.text":f"noreverse {c['tb_fg']} bg:{c['tb_bg']}",
475
+
476
+ # Completion menu — theme-aware surface, copper selection
477
+ "completion-menu": f"bg:{c['bg']} {c['fg']}",
478
+ "completion-menu.completion": f"bg:{c['bg']} {c['fg']}",
479
+ "completion-menu.completion.current": f"bg:{c['sel_bg']} {c['sel_fg']} bold",
480
+ "completion-menu.meta.completion": f"bg:{c['bg']} {c['meta']}",
481
+ "completion-menu.meta.completion.current": f"bg:{c['sel_bg']} {c['meta_cur']}",
482
+ "completion-menu.multi-column-meta": f"bg:{c['bg']} {c['meta']}",
483
+ "scrollbar.background": f"bg:{c['scroll_bg']}",
484
+ "scrollbar.button": f"bg:{c['scroll_btn']}",
485
+
486
+ # Fuzzy highlight classes — copper
487
+ "fz-hi": f"bold {c['hi']}",
488
+ "fz-cat": c["cat"],
489
+ })
490
+
491
+ # Back-compat default (dark). Prefer build_aria_pt_style(theme) at call sites.
492
+ ARIA_PT_STYLE = build_aria_pt_style("dark")
493
+
494
+ else:
495
+ def build_aria_pt_style(theme: str = "auto"): # type: ignore
496
+ return None
497
+ class AriaPTCompleter: # type: ignore
498
+ def __init__(self, *a, **kw): pass
499
+ def get_completions(self, *a, **kw): return iter([])
500
+
501
+ ARIA_PT_STYLE = None