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,326 @@
1
+ """Stateless helpers lifted out of aria_cli.py.
2
+
3
+ These twelve functions never touched aria_cli's module state — no console, no
4
+ HAS_RICH, no tool registry — yet twelve command mixins reached back into a
5
+ 7000-line module to call them, because that is simply where they happened to
6
+ be defined. Nothing about them needs to live there.
7
+
8
+ aria_cli re-exports them under their original names, so its own callers and the
9
+ globals-rebind for the modules that still rely on it are unaffected.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import json
15
+ import pathlib
16
+ from typing import Optional
17
+
18
+ __all__ = [
19
+ "detect_ollama_models",
20
+ "detect_ollama_models_rich",
21
+ "_load_project_context",
22
+ "_display_value",
23
+ "_chart_display_label",
24
+ "_chart_period_from_ta_days",
25
+ "_copy_text_to_clipboard",
26
+ "_reveal_path_in_finder",
27
+ "_open_path_or_url",
28
+ "_extract_code_block",
29
+ "_clean_tool_error_message",
30
+ "_fuzzy_match",
31
+ "_is_ashare_symbol",
32
+ "format_sparkline",
33
+ ]
34
+
35
+
36
+ # Per directory: the AGENTS.md family (the convention Codex and other agents
37
+ # share) and Aria's own ARIA.md are both read; CLAUDE.md only when neither is
38
+ # there. AGENTS.override.md stands in for AGENTS.md, as in Codex.
39
+ _AGENTS_NAMES = ("AGENTS.override.md", "AGENTS.md")
40
+ _ARIA_NAMES = ("ARIA.md", ".aria.md")
41
+ _FALLBACK_NAMES = ("CLAUDE.md",)
42
+
43
+
44
+ def _project_rule_files(directory: pathlib.Path) -> list[pathlib.Path]:
45
+ picked = []
46
+ for family in (_AGENTS_NAMES, _ARIA_NAMES):
47
+ hit = next((directory / n for n in family if (directory / n).is_file()), None)
48
+ if hit:
49
+ picked.append(hit)
50
+ if not picked:
51
+ picked = [directory / n for n in _FALLBACK_NAMES if (directory / n).is_file()][:1]
52
+ return picked
53
+
54
+
55
+ def _load_project_context() -> str:
56
+ """Load AGENTS.md / ARIA.md / CLAUDE.md by walking up from cwd.
57
+
58
+ Only ARIA.md and CLAUDE.md were read, so a repository set up for Codex
59
+ and other agents through AGENTS.md gave Aria none of its rules. The walk
60
+ now stops at the repository root (a parent of the repository is not part
61
+ of the project), files nearer the working directory come first and get
62
+ first claim on the size cap, and ~/.arthera/ARIA.md comes last. It came
63
+ first, so a long global profile could crowd the project's rules out.
64
+ """
65
+ _MAX_BYTES = 12288
66
+ _MAX_LEVELS = 5
67
+
68
+ home = pathlib.Path.home()
69
+ cwd = pathlib.Path.cwd().resolve()
70
+
71
+ found: list[tuple[pathlib.Path, str]] = [] # nearest first
72
+ seen_text: set[str] = set()
73
+
74
+ def add(path: pathlib.Path) -> None:
75
+ try:
76
+ content = path.read_text(encoding="utf-8")
77
+ except Exception:
78
+ return
79
+ key = content.strip()
80
+ if key and key not in seen_text: # a CLAUDE.md copied to AGENTS.md, a symlink
81
+ seen_text.add(key)
82
+ found.append((path, content))
83
+
84
+ current = cwd
85
+ for _ in range(_MAX_LEVELS):
86
+ for path in _project_rule_files(current):
87
+ add(path)
88
+ if current == home or current.parent == current or (current / ".git").exists():
89
+ break
90
+ current = current.parent
91
+
92
+ # Global user file — lowest priority; /memory edit global edits it.
93
+ from aria_code.account_session import profile_path, read_config, account_id
94
+ _global_aria = profile_path()
95
+ # Signed-in personal facts come from the cloud snapshot/outbox, so a fact
96
+ # deleted on Web cannot be reintroduced by an old local profile file.
97
+ _include_personal_file = account_id(read_config()) is None
98
+ if _include_personal_file and _global_aria.is_file() and not any(f == _global_aria for f, _ in found):
99
+ add(_global_aria)
100
+
101
+ if not found:
102
+ return ""
103
+
104
+ blocks: list[str] = []
105
+ total = 0
106
+ for fpath, content in found:
107
+ rel = fpath.relative_to(home) if fpath.is_relative_to(home) else fpath
108
+ snippet = content[:(_MAX_BYTES - total)]
109
+ blocks.append(f"### {rel}\n{snippet}")
110
+ total += len(snippet)
111
+ if total >= _MAX_BYTES:
112
+ break
113
+
114
+ header = ("\n\n## Project Context\n"
115
+ "Where these files disagree, the one listed first (nearest the working directory) wins.\n\n")
116
+ return header + "\n\n".join(blocks)
117
+
118
+
119
+ def _display_value(value, digits: int = 2, suffix: str = "") -> str:
120
+ try:
121
+ if value in (None, "", "N/A", "-", "nan"):
122
+ return "—"
123
+ if isinstance(value, (int, float)):
124
+ return f"{float(value):,.{digits}f}{suffix}"
125
+ return str(value)
126
+ except Exception:
127
+ return "—"
128
+
129
+
130
+ def _chart_display_label(raw: str, resolved: str, result: dict | None = None) -> str:
131
+ result = result or {}
132
+ name = str(result.get("name") or result.get("display_name") or "").strip()
133
+ resolved = str(resolved or "").strip().upper()
134
+ raw_label = str(raw or "").strip().upper()
135
+ if name and name.upper() != resolved:
136
+ return f"{name} ({resolved})"
137
+ if raw_label and raw_label != resolved and not raw_label.startswith(resolved):
138
+ return f"{raw_label} ({resolved})"
139
+ return resolved or raw_label or "chart"
140
+
141
+
142
+ def _chart_period_from_ta_days(days: int) -> str:
143
+ try:
144
+ d = int(days)
145
+ except Exception:
146
+ return "1y"
147
+ if d <= 45:
148
+ return "1mo"
149
+ if d <= 110:
150
+ return "3mo"
151
+ if d <= 220:
152
+ return "6mo"
153
+ if d <= 430:
154
+ return "1y"
155
+ if d <= 800:
156
+ return "2y"
157
+ return "3y"
158
+
159
+
160
+ def _copy_text_to_clipboard(text: str) -> tuple[bool, str]:
161
+ try:
162
+ import subprocess as _sp
163
+ _sp.run(["pbcopy"], input=text.encode("utf-8"), check=True, timeout=3)
164
+ return True, ""
165
+ except Exception as exc:
166
+ return False, str(exc)
167
+
168
+
169
+ def _reveal_path_in_finder(path: str) -> tuple[bool, str]:
170
+ try:
171
+ import subprocess as _sp
172
+ _sp.Popen(["open", "-R", path])
173
+ return True, ""
174
+ except Exception as exc:
175
+ return False, str(exc)
176
+
177
+
178
+ def _open_path_or_url(target: str) -> tuple[bool, str]:
179
+ try:
180
+ import subprocess as _sp
181
+ _sp.Popen(["open", target])
182
+ return True, ""
183
+ except Exception as exc:
184
+ return False, str(exc)
185
+
186
+
187
+ def _extract_code_block(text: str) -> Optional[str]:
188
+ """Extract the first code block from markdown-formatted text."""
189
+ import re
190
+ # Match ```python ... ``` or ``` ... ```
191
+ pattern = r'```(?:python|py)?\s*\n(.*?)```'
192
+ match = re.search(pattern, text, re.DOTALL)
193
+ if match:
194
+ return match.group(1).strip()
195
+ # Fallback: try to find any code block
196
+ pattern2 = r'```\w*\s*\n(.*?)```'
197
+ match2 = re.search(pattern2, text, re.DOTALL)
198
+ if match2:
199
+ return match2.group(1).strip()
200
+ return None
201
+
202
+
203
+ def _clean_tool_error_message(error: object) -> str:
204
+ from ui.render.output import clean_tool_error_message as _ctm
205
+ return _ctm(error)
206
+
207
+
208
+ def _fuzzy_match(query: str, candidates: list, max_results: int = 3) -> list:
209
+ """Find closest matches using simple edit distance."""
210
+ def _edit_dist(a, b):
211
+ if len(a) > len(b):
212
+ a, b = b, a
213
+ dists = range(len(a) + 1)
214
+ for j, cb in enumerate(b):
215
+ new_dists = [j + 1]
216
+ for i, ca in enumerate(a):
217
+ cost = 0 if ca == cb else 1
218
+ new_dists.append(min(new_dists[-1] + 1, dists[i + 1] + 1, dists[i] + cost))
219
+ dists = new_dists
220
+ return dists[-1]
221
+
222
+ scored = [(c, _edit_dist(query.lower(), c.lower())) for c in candidates]
223
+ scored.sort(key=lambda x: x[1])
224
+ # Only suggest if edit distance is reasonable (< half the length)
225
+ threshold = max(3, len(query) // 2)
226
+ return [c for c, d in scored[:max_results] if d <= threshold]
227
+
228
+
229
+ def _is_ashare_symbol(symbol: str) -> bool:
230
+ """Quick check whether a symbol looks like a Chinese A-share code."""
231
+ s = symbol.strip().lower()
232
+ return (
233
+ s.startswith("sh") or s.startswith("sz")
234
+ or (len(s) == 6 and s.isdigit())
235
+ or s.endswith(".ss") or s.endswith(".sz")
236
+ )
237
+
238
+
239
+ def format_sparkline(prices: list, width: int = 30) -> str:
240
+ """Generate Unicode sparkline from price data."""
241
+ if not prices or len(prices) < 2:
242
+ return ""
243
+ blocks = "▁▂▃▄▅▆▇█"
244
+ mn, mx = min(prices), max(prices)
245
+ rng = mx - mn or 1
246
+ result = ""
247
+ step = max(1, len(prices) // width)
248
+ for i in range(0, len(prices), step):
249
+ idx = int((prices[i] - mn) / rng * (len(blocks) - 1))
250
+ result += blocks[idx]
251
+ return result[:width]
252
+
253
+
254
+ def detect_ollama_models(ollama_url: str = "http://localhost:11434") -> list:
255
+ """Query Ollama /api/tags and return list of available model names.
256
+
257
+ Always bypasses HTTP_PROXY so localhost is reached directly even when a
258
+ system proxy (VPN / clash / surge) is active.
259
+ """
260
+ import urllib.request
261
+ # Force direct connection — bypass any HTTP_PROXY / HTTPS_PROXY env vars
262
+ _opener = urllib.request.build_opener(urllib.request.ProxyHandler({}))
263
+ try:
264
+ with _opener.open(f"{ollama_url}/api/tags", timeout=5) as r:
265
+ data = json.loads(r.read())
266
+ return [m["name"] for m in data.get("models", [])]
267
+ except Exception:
268
+ # Also try 127.0.0.1 if hostname is "localhost" (IPv6 resolution fallback)
269
+ if "localhost" in ollama_url:
270
+ try:
271
+ fallback = ollama_url.replace("localhost", "127.0.0.1")
272
+ with _opener.open(f"{fallback}/api/tags", timeout=5) as r:
273
+ data = json.loads(r.read())
274
+ return [m["name"] for m in data.get("models", [])]
275
+ except Exception:
276
+ pass
277
+ return []
278
+
279
+
280
+ def detect_ollama_models_rich(ollama_url: str = "http://localhost:11434") -> tuple:
281
+ """Return (models_list, error_str) where each entry in models_list is a dict:
282
+ {"name": str, "size_label": str, "family": str, "quant": str,
283
+ "execution": "local" | "remote", "remote_host": str,
284
+ "context_window": int, "capabilities": list[str]}
285
+ error_str is None on success, or a short human-readable reason on failure.
286
+ """
287
+ import urllib.request
288
+ _opener = urllib.request.build_opener(urllib.request.ProxyHandler({}))
289
+
290
+ def _try(url: str):
291
+ with _opener.open(f"{url}/api/tags", timeout=5) as r:
292
+ return json.loads(r.read())
293
+
294
+ data = None
295
+ last_err = None
296
+ for u in [ollama_url] + ([ollama_url.replace("localhost", "127.0.0.1")]
297
+ if "localhost" in ollama_url else []):
298
+ try:
299
+ data = _try(u)
300
+ break
301
+ except OSError as e:
302
+ last_err = str(e)
303
+ except Exception as e:
304
+ last_err = str(e)
305
+
306
+ if data is None:
307
+ return [], last_err or "connection failed"
308
+
309
+ results = []
310
+ for m in data.get("models", []):
311
+ det = m.get("details", {})
312
+ size = det.get("parameter_size", "")
313
+ fam = det.get("family", "")
314
+ qnt = det.get("quantization_level", "")
315
+ results.append({
316
+ "name": m["name"],
317
+ "size_label": size, # e.g. "1.5B", "7B", "671.0B"
318
+ "family": fam, # e.g. "qwen2", "deepseek2"
319
+ "quant": qnt, # e.g. "Q4_K_M", "MXFP4"
320
+ "execution": "remote" if m.get("remote_host") else "local",
321
+ "remote_model": m.get("remote_model", ""),
322
+ "remote_host": m.get("remote_host", ""),
323
+ "context_window": int(det.get("context_length") or 0),
324
+ "capabilities": list(m.get("capabilities") or []),
325
+ })
326
+ return results, None
@@ -0,0 +1,180 @@
1
+ """Aria Code lifecycle hooks — JSON-configurable, shell-executable.
2
+
3
+ Config file: ~/.arthera/hooks.json
4
+ Project-local override: .aria/hooks.json (takes precedence)
5
+
6
+ Schema
7
+ ------
8
+ {
9
+ "PreToolUse": [{"tool": "run_command", "command": "echo $ARIA_TOOL"}],
10
+ "PostToolUse": [{"command": "notify-send 'done'"}],
11
+ "ResponseDone": [{"command": "afplay /System/Sounds/Glass.aiff"}],
12
+ "SessionStart": [{"command": "echo starting $ARIA_SESSION"}],
13
+ "SessionEnd": [{"command": "echo ended"}]
14
+ }
15
+
16
+ Each hook entry:
17
+ command — shell command to execute (required)
18
+ tool — if set, only fires when tool name matches (PreToolUse / PostToolUse)
19
+ timeout — seconds before the hook is killed (default 10)
20
+ blocking — if true AND exit code != 0, execution is blocked (PreToolUse only)
21
+
22
+ Env vars injected into every hook:
23
+ ARIA_EVENT — hook event name
24
+ ARIA_TOOL — tool name (Pre/PostToolUse only)
25
+ ARIA_TOOL_PARAMS — JSON-encoded params (Pre/PostToolUse only)
26
+ ARIA_RESULT — JSON-encoded result (PostToolUse only)
27
+ ARIA_RESPONSE — first 500 chars of response (ResponseDone)
28
+ ARIA_SESSION — session ID
29
+ """
30
+ from __future__ import annotations
31
+
32
+ import json
33
+ import logging
34
+ import os
35
+ import subprocess
36
+ from pathlib import Path
37
+ from typing import Optional
38
+
39
+ from aria_code.apps.cli.config_paths import resolve_config_dir
40
+
41
+ logger = logging.getLogger(__name__)
42
+
43
+ _CONFIG_DIR = resolve_config_dir()
44
+ _GLOBAL_HOOKS_FILE = _CONFIG_DIR / "hooks.json"
45
+ _LOCAL_HOOKS_FILE = Path.cwd() / ".aria" / "hooks.json"
46
+
47
+ _VALID_EVENTS = frozenset([
48
+ "PreToolUse", "PostToolUse",
49
+ "ResponseDone",
50
+ "SessionStart", "SessionEnd",
51
+ ])
52
+
53
+
54
+ def load_hooks() -> dict:
55
+ """Load and merge global + project-local hooks config."""
56
+ merged: dict[str, list] = {e: [] for e in _VALID_EVENTS}
57
+
58
+ for path in (_GLOBAL_HOOKS_FILE, _LOCAL_HOOKS_FILE):
59
+ if path.exists():
60
+ try:
61
+ data = json.loads(path.read_text(encoding="utf-8"))
62
+ for event, entries in data.items():
63
+ if event in _VALID_EVENTS and isinstance(entries, list):
64
+ merged[event].extend(entries)
65
+ except Exception as exc:
66
+ logger.debug("hooks.json parse error (%s): %s", path, exc)
67
+
68
+ return merged
69
+
70
+
71
+ def fire(
72
+ event: str,
73
+ *,
74
+ tool: Optional[str] = None,
75
+ params: Optional[dict] = None,
76
+ result: Optional[dict] = None,
77
+ response: str = "",
78
+ session_id: str = "",
79
+ hooks: Optional[dict] = None,
80
+ ) -> bool:
81
+ """Fire all matching hooks for an event.
82
+
83
+ Returns False if any *blocking* PreToolUse hook exits non-zero
84
+ (meaning the tool call should be suppressed). Returns True otherwise.
85
+ """
86
+ if hooks is None:
87
+ hooks = load_hooks()
88
+
89
+ entries = hooks.get(event, [])
90
+ if not entries:
91
+ return True
92
+
93
+ base_env = dict(os.environ)
94
+ base_env["ARIA_EVENT"] = event
95
+ base_env["ARIA_SESSION"] = session_id or ""
96
+ if tool:
97
+ base_env["ARIA_TOOL"] = tool
98
+ if params is not None:
99
+ base_env["ARIA_TOOL_PARAMS"] = json.dumps(params, ensure_ascii=False)[:2000]
100
+ if result is not None:
101
+ base_env["ARIA_RESULT"] = json.dumps(result, ensure_ascii=False)[:2000]
102
+ if response:
103
+ base_env["ARIA_RESPONSE"] = response[:500]
104
+
105
+ blocked = False
106
+ for entry in entries:
107
+ if not isinstance(entry, dict):
108
+ continue
109
+ cmd = entry.get("command", "").strip()
110
+ if not cmd:
111
+ continue
112
+
113
+ # Tool filter: skip if hook is scoped to a different tool
114
+ if entry.get("tool") and tool and entry["tool"] != tool:
115
+ continue
116
+
117
+ timeout = int(entry.get("timeout", 10))
118
+ is_blocking = bool(entry.get("blocking", False))
119
+
120
+ try:
121
+ proc = subprocess.run(
122
+ cmd,
123
+ shell=True,
124
+ env=base_env,
125
+ timeout=timeout,
126
+ capture_output=True,
127
+ text=True,
128
+ )
129
+ if is_blocking and proc.returncode != 0 and event == "PreToolUse":
130
+ logger.info(
131
+ "Blocking hook vetoed tool '%s': exit %d — %s",
132
+ tool, proc.returncode, proc.stderr[:120],
133
+ )
134
+ blocked = True
135
+ except subprocess.TimeoutExpired:
136
+ logger.debug("Hook timed out after %ds: %s", timeout, cmd[:60])
137
+ except Exception as exc:
138
+ logger.debug("Hook error: %s", exc)
139
+
140
+ return not blocked
141
+
142
+
143
+ def list_hooks() -> list[dict]:
144
+ """Return a flat list of configured hooks for display."""
145
+ hooks = load_hooks()
146
+ rows = []
147
+ for event, entries in hooks.items():
148
+ for entry in entries:
149
+ if isinstance(entry, dict) and entry.get("command"):
150
+ rows.append({
151
+ "event": event,
152
+ "tool": entry.get("tool", "*"),
153
+ "command": entry["command"][:80],
154
+ "blocking": entry.get("blocking", False),
155
+ "timeout": entry.get("timeout", 10),
156
+ })
157
+ return rows
158
+
159
+
160
+ def hooks_file_path(scope: str = "global") -> Path:
161
+ """Return the hooks.json path for a given scope."""
162
+ if scope == "local":
163
+ return Path.cwd() / ".aria" / "hooks.json"
164
+ return _GLOBAL_HOOKS_FILE
165
+
166
+
167
+ def create_example_hooks(path: Path) -> None:
168
+ """Write an annotated example hooks.json if it doesn't exist."""
169
+ if path.exists():
170
+ return
171
+ path.parent.mkdir(parents=True, exist_ok=True)
172
+ example = {
173
+ "_comment": "Aria Code hooks — schema: https://github.com/artheras/aria-code/blob/main/src/aria_code/apps/cli/hooks.py",
174
+ "PreToolUse": [],
175
+ "PostToolUse": [],
176
+ "ResponseDone": [],
177
+ "SessionStart": [],
178
+ "SessionEnd": [],
179
+ }
180
+ path.write_text(json.dumps(example, indent=2, ensure_ascii=False), encoding="utf-8")