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,769 @@
1
+ """CLI consumers for runtime/model events.
2
+
3
+ The runtime core emits typed events and asks for approval decisions. This
4
+ module keeps terminal-specific rendering and prompts at the CLI adapter layer
5
+ instead of letting them spread through the agent loop.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import re
11
+ import sys
12
+ import time
13
+ from dataclasses import dataclass, field
14
+ from enum import Enum
15
+ from pathlib import Path
16
+ from typing import Any, Callable
17
+
18
+ from aria_code.runtime import (
19
+ AgentEventStatus,
20
+ AgentEventThinking,
21
+ AgentEventToken,
22
+ AgentEventToolCall,
23
+ AgentEventToolResult,
24
+ ApprovalDecision,
25
+ )
26
+
27
+
28
+ _REPETITION_MARKER = "*[model stopped — repetition detected]*"
29
+ _REPETITION_NOTICE = (
30
+ "\n\n> 已检测到模型开始重复输出,已自动停止展开。"
31
+ "上方结果仍然有效;如需继续,请指定要补充的部分。"
32
+ )
33
+
34
+
35
+ def _redact_activity_text(value: Any, limit: int = 90) -> str:
36
+ """One line, secrets masked — for anything echoed to the screen or a log.
37
+
38
+ Shell commands are now shown on their step line, so this also covers
39
+ "Authorization: Bearer …", credentials in URLs and the usual key shapes.
40
+ """
41
+ text = re.sub(r"\s+", " ", str(value or "")).strip()
42
+ text = re.sub(
43
+ r"(?i)(api[_-]?key|token|password|passwd|secret)(\s*[=:]\s*|\s+)[^\s]+",
44
+ r"\1\2***",
45
+ text,
46
+ )
47
+ text = re.sub(r"(?i)\b(bearer|basic)\s+[A-Za-z0-9._~+/=-]+", r"\1 ***", text)
48
+ text = re.sub(r"://[^/\s:@]+:[^@\s]+@", "://***@", text)
49
+ text = re.sub(r"\b(sk|pk|rk)-[A-Za-z0-9_-]{8,}|\bgh[pousr]_[A-Za-z0-9]{12,}|\bAIza[0-9A-Za-z_-]{20,}"
50
+ r"|\bxox[abposr]-[A-Za-z0-9-]{10,}", "***", text)
51
+ return text[:limit]
52
+
53
+
54
+ # How long the runtime measured a tool call to take, carried with its result.
55
+ MEASURED_ELAPSED_KEY = "_elapsed_s"
56
+
57
+
58
+ def with_measured_elapsed(result: Any, elapsed: Any) -> Any:
59
+ if isinstance(result, dict) and isinstance(elapsed, (int, float)):
60
+ return {**result, MEASURED_ELAPSED_KEY: float(elapsed)}
61
+ return result
62
+
63
+
64
+ def approval_subject(tool_name: str, params: dict[str, Any]) -> str:
65
+ """What an answered approval leaves behind: the file, or the command with secrets masked."""
66
+ if tool_name == "run_command":
67
+ return _redact_activity_text(params.get("command", ""), limit=80)
68
+ if tool_name == "computer_action":
69
+ return _desktop_subject(params)
70
+ for key in ("path", "file_path"):
71
+ if params.get(key):
72
+ return Path(str(params[key])).name
73
+ return tool_name.replace("_", " ")
74
+
75
+
76
+ def _desktop_subject(params: dict[str, Any]) -> str:
77
+ """What the mouse or keyboard is about to do; typed text is counted, never echoed."""
78
+ action = str(params.get("action") or "input").lower()
79
+ if action == "type":
80
+ return f"type {len(str(params.get('text') or ''))} characters"
81
+ if action == "key":
82
+ return f"press {str(params.get('key') or '?')[:40]}"
83
+ if action == "drag":
84
+ return f"drag ({params.get('x', 0)}, {params.get('y', 0)}) to ({params.get('ex', 0)}, {params.get('ey', 0)})"
85
+ return f"{action.replace('_', ' ')} at ({params.get('x', 0)}, {params.get('y', 0)})"
86
+
87
+
88
+ def _tool_activity_hint(tool: str, params: dict[str, Any]) -> str:
89
+ """Return one safe, useful argument for a compact activity row."""
90
+ if not isinstance(params, dict):
91
+ return ""
92
+ for key in ("path", "file_path", "filename", "file"):
93
+ if params.get(key):
94
+ return Path(str(params[key])).name[:90]
95
+ for key in ("symbol", "ticker", "query", "q", "command", "url", "task"):
96
+ if params.get(key):
97
+ return _redact_activity_text(params[key])
98
+ title = params.get("title")
99
+ return _redact_activity_text(title) if title else ""
100
+
101
+
102
+ class TurnPhase(str, Enum):
103
+ """User-visible lifecycle for one assistant turn."""
104
+
105
+ CONNECTING = "connecting"
106
+ THINKING = "thinking"
107
+ STREAMING = "streaming"
108
+ TOOL = "tool"
109
+ DONE = "done"
110
+ ERROR = "error"
111
+ CANCELLED = "cancelled"
112
+
113
+
114
+ @dataclass
115
+ class TurnLifecycle:
116
+ phase: TurnPhase = TurnPhase.CONNECTING
117
+ started_at: float = field(default_factory=time.time)
118
+ first_visible_at: float | None = None
119
+ ended_at: float | None = None
120
+
121
+ def transition(self, phase: TurnPhase) -> None:
122
+ self.phase = phase
123
+ now = time.time()
124
+ if phase is TurnPhase.STREAMING and self.first_visible_at is None:
125
+ self.first_visible_at = now
126
+ if phase in {TurnPhase.DONE, TurnPhase.ERROR, TurnPhase.CANCELLED}:
127
+ self.ended_at = now
128
+
129
+
130
+ class TerminalRuntimeEventConsumer:
131
+ """Consume runtime/provider events and render them to a terminal."""
132
+
133
+ action_view: Any = None
134
+
135
+ def __init__(
136
+ self,
137
+ *,
138
+ terminal: Any,
139
+ console: Any,
140
+ has_rich: bool,
141
+ markdown_cls: type | None,
142
+ live_cls: type | None,
143
+ strip_latex: Callable[[str], str],
144
+ set_robot_state: Callable[[Any], None] | None = None,
145
+ streaming_state: Any = None,
146
+ print_tool_call: Callable[[str, dict], None] | None = None,
147
+ print_tool_done: Callable[..., None] | None = None,
148
+ fallback_from: str = "local",
149
+ live_update_interval: float = 0.08,
150
+ ui_lang: str = "en",
151
+ on_response_start: Callable[[], None] | None = None,
152
+ on_phase_change: Callable[[TurnPhase], None] | None = None,
153
+ action_view: Any = None,
154
+ ) -> None:
155
+ self.terminal = terminal
156
+ self.console = console
157
+ self.has_rich = has_rich
158
+ self.markdown_cls = markdown_cls
159
+ self.live_cls = live_cls
160
+ self.strip_latex = strip_latex
161
+ self.set_robot_state = set_robot_state
162
+ self.streaming_state = streaming_state
163
+ self.print_tool_call = print_tool_call
164
+ self.print_tool_done = print_tool_done
165
+ self.fallback_from = fallback_from
166
+ self.live_update_interval = live_update_interval
167
+ self.ui_lang = ui_lang or "en"
168
+ self.on_response_start = on_response_start
169
+ self.on_phase_change = on_phase_change
170
+ # ui.render.actions.ActionView: tool events as Explored / Ran / Edit
171
+ # cells. None keeps the per-call ⏺ / ✓ lines.
172
+ self.action_view = action_view
173
+ self.lifecycle = TurnLifecycle()
174
+
175
+ self.response_text = ""
176
+ self.streamed_any = False
177
+ self.token_count = 0
178
+ self.thinking_tokens = 0
179
+ self.thinking_shown = False
180
+ self.thinking_start: float | None = None
181
+ self.thinking_finished = False
182
+ self.thinking_preview_buf: list[str] = []
183
+ self.thinking_full_buf: list[str] = []
184
+ self.tool_start_times: dict[str, list[float]] = {}
185
+ self.tool_params: dict[str, list[dict[str, Any]]] = {}
186
+ self.repetition_stopped = False
187
+ self.repetition_notice_printed = False
188
+ self.response_started = False
189
+
190
+ self.live_display = None
191
+ self.spinner = None
192
+ self.first_token_received_ref = [False]
193
+ self.token_start_time: float | None = None
194
+ self.last_live_update = 0.0
195
+ self.use_plain_print_ref = [False]
196
+ self.use_batch_render_ref = [False]
197
+ self.latex_buf_ref = [""]
198
+ self.in_latex_ref = [False]
199
+
200
+ @property
201
+ def first_token_received(self) -> bool:
202
+ return self.first_token_received_ref[0]
203
+
204
+ @first_token_received.setter
205
+ def first_token_received(self, value: bool) -> None:
206
+ self.first_token_received_ref[0] = value
207
+
208
+ @property
209
+ def use_plain_print(self) -> bool:
210
+ return self.use_plain_print_ref[0]
211
+
212
+ @use_plain_print.setter
213
+ def use_plain_print(self, value: bool) -> None:
214
+ self.use_plain_print_ref[0] = value
215
+
216
+ @property
217
+ def use_batch_render(self) -> bool:
218
+ return self.use_batch_render_ref[0]
219
+
220
+ @use_batch_render.setter
221
+ def use_batch_render(self, value: bool) -> None:
222
+ self.use_batch_render_ref[0] = value
223
+
224
+ @property
225
+ def latex_buf(self) -> str:
226
+ return self.latex_buf_ref[0]
227
+
228
+ @latex_buf.setter
229
+ def latex_buf(self, value: str) -> None:
230
+ self.latex_buf_ref[0] = value
231
+
232
+ @property
233
+ def in_latex(self) -> bool:
234
+ return self.in_latex_ref[0]
235
+
236
+ @in_latex.setter
237
+ def in_latex(self, value: bool) -> None:
238
+ self.in_latex_ref[0] = value
239
+
240
+ def start_spinner(self) -> None:
241
+ self.set_phase(TurnPhase.THINKING)
242
+ if self.has_rich and self.spinner is None and not self.first_token_received:
243
+ label = "思考中" if self.ui_lang.lower().startswith("zh") else "Thinking"
244
+ cancel = "esc 取消" if self.ui_lang.lower().startswith("zh") else "esc cancel"
245
+ self.spinner = self.console.status(
246
+ f"[dim]{label}… [/dim][dim italic]{cancel}[/dim italic]",
247
+ spinner="dots",
248
+ spinner_style="dim",
249
+ )
250
+ self.spinner.__enter__()
251
+
252
+ def set_phase(self, phase: TurnPhase) -> None:
253
+ if self.lifecycle.phase is phase:
254
+ return
255
+ self.lifecycle.transition(phase)
256
+ if self.on_phase_change is not None:
257
+ self.on_phase_change(phase)
258
+
259
+ def ensure_response_started(self) -> None:
260
+ """Render the response label only when visible answer text exists."""
261
+ if self.response_started:
262
+ return
263
+ self._finish_thinking()
264
+ self.stop_spinner()
265
+ self.flush_actions()
266
+ self.response_started = True
267
+ if self.on_response_start is not None:
268
+ self.on_response_start()
269
+
270
+ def finish(self, phase: TurnPhase = TurnPhase.DONE) -> None:
271
+ self._finish_thinking()
272
+ self.stop_spinner()
273
+ self.close_tool_spinner()
274
+ self.flush_actions()
275
+ self.set_phase(phase)
276
+
277
+ def print_action_lines(self, lines) -> None:
278
+ rich = self.has_rich and self.console is not None
279
+ for style, text in lines:
280
+ if text.startswith("⏺"): # a new cell: one blank line above it
281
+ self.console.print() if rich else print()
282
+ if rich:
283
+ from rich.markup import escape
284
+ body = f" {escape(text)}"
285
+ self.console.print(f"[{style}]{body}[/{style}]" if style else body, highlight=False)
286
+ else:
287
+ print(f" {text}")
288
+
289
+ def flush_actions(self) -> None:
290
+ """Print a pending Explored cell before anything else reaches the screen."""
291
+ if self.action_view is not None:
292
+ self.print_action_lines(self.action_view.flush())
293
+
294
+ def stop_spinner(self) -> None:
295
+ if self.spinner is not None:
296
+ try:
297
+ self.spinner.__exit__(None, None, None)
298
+ except Exception:
299
+ pass
300
+ self.spinner = None
301
+
302
+ def stop_live(self, discard: bool = False) -> None:
303
+ self.stop_spinner()
304
+ if self.live_display:
305
+ try:
306
+ if discard:
307
+ try:
308
+ from rich.text import Text as _RichText
309
+
310
+ self.live_display.update(_RichText(""))
311
+ self.live_display.refresh()
312
+ except Exception:
313
+ pass
314
+ self.live_display.stop()
315
+ except Exception:
316
+ pass
317
+ self.live_display = None
318
+ elif self.first_token_received and not discard and not self.use_batch_render:
319
+ print(flush=True)
320
+
321
+ def set_batch_render_mode(self, enabled: bool = True) -> None:
322
+ self.use_plain_print = enabled
323
+ self.use_batch_render = enabled
324
+
325
+ def reset_stream_state(self) -> None:
326
+ self.response_text = ""
327
+ self.streamed_any = False
328
+ self.token_count = 0
329
+ self.first_token_received = False
330
+ self.token_start_time = None
331
+ self.latex_buf = ""
332
+ self.in_latex = False
333
+
334
+ def flush_latex_buf(self) -> str:
335
+ raw = self.latex_buf
336
+ self.latex_buf = ""
337
+ self.in_latex = False
338
+ return self.strip_latex(raw) if raw.strip() else raw
339
+
340
+ def _show_repetition_notice(self) -> None:
341
+ if self.repetition_notice_printed or self.use_batch_render:
342
+ return
343
+ self.repetition_notice_printed = True
344
+ if self.live_display and self.has_rich and self.markdown_cls is not None:
345
+ clean_text = self.response_text.split(_REPETITION_MARKER, 1)[0].rstrip()
346
+ self.live_display.update(self.markdown_cls(self.strip_latex(clean_text + _REPETITION_NOTICE)))
347
+ self.live_display.refresh()
348
+ return
349
+ print(_REPETITION_NOTICE, end="", flush=True)
350
+
351
+ def finalize_text(self, final_text: str) -> str:
352
+ if self.in_latex and self.latex_buf:
353
+ leftover = self.flush_latex_buf()
354
+ final_text = (final_text or "") + leftover
355
+ if self.use_plain_print and not self.use_batch_render:
356
+ print(leftover, end="", flush=True)
357
+ return final_text
358
+
359
+ def _finish_thinking(self) -> None:
360
+ if not self.thinking_shown or self.thinking_finished:
361
+ return
362
+ self.thinking_finished = True
363
+ self.stop_spinner()
364
+ elapsed_t = time.time() - self.thinking_start if self.thinking_start else 0
365
+ self.terminal._last_thinking = "".join(self.thinking_full_buf).strip()
366
+ is_zh = self.ui_lang.lower().startswith("zh")
367
+ t_info = f"思考 {elapsed_t:.1f}s" if is_zh else f"Thought for {elapsed_t:.1f}s"
368
+ if self.thinking_tokens > 0:
369
+ t_info += f" · {self.thinking_tokens:,} tokens"
370
+ expand = "展开" if is_zh else "expand"
371
+ ctrlo = f" [dim]· Ctrl+O {expand}[/dim]" if self.terminal._last_thinking else ""
372
+ if self.has_rich:
373
+ sys.stdout.write("\r\033[K")
374
+ sys.stdout.flush()
375
+ self.console.print(f" [dim]✻[/dim] [dim]{t_info}[/dim]{ctrlo}")
376
+ if self.terminal.config.get("thinking_preview") and self.thinking_preview_buf:
377
+ preview_text = "".join(self.thinking_preview_buf)[:280].strip()
378
+ if len("".join(self.thinking_preview_buf)) > 280:
379
+ preview_text += "…"
380
+ self.console.print(f" [dim italic]{preview_text}[/dim italic]")
381
+ else:
382
+ print(f"\r ✻ {t_info}")
383
+
384
+ def on_token(self, token: str) -> None:
385
+ if "<|im_start|>" in token or "<|im_end|>" in token:
386
+ token = token.replace("<|im_start|>", "").replace("<|im_end|>", "")
387
+ if not token.strip():
388
+ return
389
+
390
+ meta_artifacts = (
391
+ "(注释:",
392
+ "(注释:",
393
+ "(提示:",
394
+ "(提示:",
395
+ "请使用实际注入的数据",
396
+ "请使用实际数据",
397
+ "实际注入的数据",
398
+ "[system]",
399
+ "[/system]",
400
+ "[INST]",
401
+ "[/INST]",
402
+ )
403
+ if any(a in token for a in meta_artifacts):
404
+ token = re.sub(
405
+ r"\(注[释释]:[^))]*[))]|(注[释释]:[^))]*[))]"
406
+ r"|\(提示:[^))]*[))]|(提示:[^))]*[))]"
407
+ r"|请使用实际(?:注入的)?数据[^。\n]*"
408
+ r"|\[/?(?:system|INST)\]",
409
+ "",
410
+ token,
411
+ )
412
+ if not token.strip():
413
+ return
414
+
415
+ if not self.first_token_received and not token.strip():
416
+ self.response_text += token
417
+ self.streamed_any = True
418
+ self.token_count += 1
419
+ return
420
+
421
+ if not self.first_token_received:
422
+ self.first_token_received = True
423
+ self.token_start_time = time.time()
424
+ self.set_phase(TurnPhase.STREAMING)
425
+ if self.set_robot_state is not None:
426
+ self.set_robot_state(self.streaming_state)
427
+ if not self.use_batch_render:
428
+ self.ensure_response_started()
429
+
430
+ if _REPETITION_MARKER in token:
431
+ if self.use_batch_render:
432
+ self.response_text += token
433
+ self.streamed_any = True
434
+ self.token_count += 1
435
+ self.repetition_stopped = True
436
+ return
437
+ before, _, _after = token.partition(_REPETITION_MARKER)
438
+ if before:
439
+ self.on_token(before)
440
+ self.response_text += _REPETITION_MARKER
441
+ self.streamed_any = True
442
+ self.token_count += 1
443
+ self.repetition_stopped = True
444
+ self._show_repetition_notice()
445
+ return
446
+
447
+ self._finish_thinking()
448
+
449
+ if self.use_batch_render:
450
+ self.response_text += token
451
+ self.streamed_any = True
452
+ self.token_count += 1
453
+ return
454
+
455
+ open_delims = (r"\(", r"\[", "$$")
456
+ close_delims = (r"\)", r"\]", "$$")
457
+ if not self.in_latex:
458
+ if any(d in token for d in open_delims):
459
+ self.in_latex = True
460
+ self.latex_buf = token
461
+ tail = token
462
+ for od, cd in zip(open_delims, close_delims):
463
+ if od in tail:
464
+ after = tail[tail.index(od) + len(od):]
465
+ if cd in after:
466
+ token = self.flush_latex_buf()
467
+ break
468
+ else:
469
+ self.response_text += self.latex_buf
470
+ self.streamed_any = True
471
+ self.token_count += 1
472
+ return
473
+ else:
474
+ token = self.strip_latex(token)
475
+ else:
476
+ self.latex_buf += token
477
+ if any(d in token for d in close_delims):
478
+ token = self.flush_latex_buf()
479
+ else:
480
+ self.response_text += token
481
+ self.streamed_any = True
482
+ self.token_count += 1
483
+ return
484
+
485
+ self.response_text += token
486
+ self.streamed_any = True
487
+ self.token_count += 1
488
+ can_live = (
489
+ self.has_rich
490
+ and not self.use_plain_print
491
+ and getattr(self.console, "is_terminal", False)
492
+ and not getattr(self.console, "is_dumb_terminal", True)
493
+ and self.markdown_cls is not None
494
+ and self.live_cls is not None
495
+ )
496
+ if can_live:
497
+ now = time.time()
498
+ if self.live_display is not None and now - self.last_live_update < self.live_update_interval:
499
+ return
500
+ md = self.markdown_cls(self.strip_latex(self.response_text))
501
+ if self.live_display is None:
502
+ self.live_display = self.live_cls(
503
+ md,
504
+ console=self.console,
505
+ refresh_per_second=12,
506
+ vertical_overflow="visible",
507
+ )
508
+ self.live_display.start()
509
+ self.last_live_update = now
510
+ elif now - self.last_live_update >= self.live_update_interval:
511
+ self.live_display.update(md)
512
+ self.last_live_update = now
513
+ else:
514
+ print(token, end="", flush=True)
515
+
516
+ def on_thinking(self, content: str) -> None:
517
+ self.set_phase(TurnPhase.THINKING)
518
+ if self.thinking_finished:
519
+ # 工具调用后的新一段思考:重置段状态,否则上一段的 finished 闩锁
520
+ # 让本段永远无法 finalize,"思考中 …(N tokens)"活行被冻结在滚动区
521
+ # (即多条思考行并存的根因)。full_buf 不清,Ctrl+O 展开保留全部段落。
522
+ self.thinking_finished = False
523
+ self.thinking_shown = False
524
+ self.thinking_tokens = 0
525
+ self.thinking_preview_buf = []
526
+ if not self.thinking_shown:
527
+ self.stop_spinner()
528
+ self.thinking_start = time.time()
529
+ self.thinking_shown = True
530
+ self.thinking_tokens += 1
531
+ if self.thinking_tokens % 30 == 1:
532
+ elapsed = time.time() - self.thinking_start
533
+ label = "思考中" if self.ui_lang.lower().startswith("zh") else "Thinking"
534
+ # 与 finalize 行(思考 Xs · N tokens)同格式,避免括号/点分隔两种样式并存
535
+ sys.stdout.write(
536
+ f"\r \033[2m✻\033[0m \033[2m{label} {elapsed:.1f}s"
537
+ f" · {self.thinking_tokens} tokens\033[0m "
538
+ )
539
+ sys.stdout.flush()
540
+ if len("".join(self.thinking_preview_buf)) < 300:
541
+ self.thinking_preview_buf.append(content)
542
+ if len("".join(self.thinking_full_buf)) < 8000:
543
+ self.thinking_full_buf.append(content)
544
+
545
+ def on_tool_call(self, tool: str, params: dict) -> None:
546
+ self.set_phase(TurnPhase.TOOL)
547
+ self._finish_thinking()
548
+
549
+ # Cursor/Windsurf 风格的实时加载动画
550
+ # One spinner at a time. /team's analysts can call tools in parallel;
551
+ # close the previous indicator before starting the next one.
552
+ self.close_tool_spinner()
553
+ if self.has_rich and hasattr(self, 'console'):
554
+ hint = _tool_activity_hint(tool, params)
555
+ verb = "调用工具" if str(self.ui_lang).lower().startswith("zh") else "Running"
556
+ label = f"[bold cyan]{verb}[/bold cyan] [green]{tool}[/green]"
557
+ if hint:
558
+ label += f" [dim]({hint})[/dim]"
559
+ self.tool_spinner = self.console.status(label, spinner="dots12", spinner_style="cyan")
560
+ self.tool_spinner.__enter__()
561
+
562
+ if self.action_view is not None:
563
+ self.print_action_lines(self.action_view.start(tool, params if isinstance(params, dict) else {}))
564
+ elif self.print_tool_call is not None:
565
+ self.print_tool_call(tool, params if isinstance(params, dict) else {})
566
+
567
+ self.tool_start_times.setdefault(tool, []).append(time.time())
568
+ safe_params = dict(params) if isinstance(params, dict) else {}
569
+ self.tool_params.setdefault(tool, []).append(safe_params)
570
+
571
+ def close_tool_spinner(self) -> None:
572
+ """Stop the tool spinner, if one is running."""
573
+ spinner = getattr(self, "tool_spinner", None)
574
+ if spinner is not None:
575
+ try:
576
+ spinner.__exit__(None, None, None)
577
+ except Exception:
578
+ pass
579
+ self.tool_spinner = None
580
+
581
+ def on_tool_result(self, tool: str, summary: Any) -> None:
582
+ # 关闭工具加载动画
583
+ self.close_tool_spinner()
584
+
585
+ starts = self.tool_start_times.get(tool) or []
586
+ started_at = starts.pop(0) if starts else time.time()
587
+ if not starts:
588
+ self.tool_start_times.pop(tool, None)
589
+ elapsed_ms = int((time.time() - started_at) * 1000)
590
+ # The runtime times each call itself. Measuring from the announcement
591
+ # counted the person reading an approval, and results of a batch
592
+ # arrive together — "✓ writing file test_fx.py 13.9s" for a 9ms write.
593
+ if isinstance(summary, dict) and isinstance(summary.get(MEASURED_ELAPSED_KEY), (int, float)):
594
+ elapsed_ms = int(summary[MEASURED_ELAPSED_KEY] * 1000)
595
+ params_queue = self.tool_params.get(tool) or []
596
+ params = params_queue.pop(0) if params_queue else {}
597
+ if not params_queue:
598
+ self.tool_params.pop(tool, None)
599
+ ok = not (isinstance(summary, dict) and not summary.get("success", True))
600
+ if self.action_view is not None:
601
+ self.print_action_lines(self.action_view.done(tool, params, summary, elapsed_ms / 1000))
602
+ elif self.print_tool_done is not None:
603
+ # Surface the failure reason on the ✗ line — a red cross with no
604
+ # explanation leaves both the user and the reviewer blind to WHY
605
+ # (observed in the channels drill: peer_comparison failed 4× with
606
+ # nothing on screen).
607
+ detail = ""
608
+ if not ok and isinstance(summary, dict):
609
+ detail = str(summary.get("error") or "")[:90]
610
+ elif ok:
611
+ # Name what was done: two bare "✓ writing file" lines in a row
612
+ # did not say which file each was.
613
+ detail = _tool_activity_hint(tool, params)
614
+ self.print_tool_done(tool, elapsed_ms, success=ok, summary=detail)
615
+
616
+ ts = time.strftime("%H:%M:%S")
617
+ icon = "✓" if ok else "✗"
618
+ hint = _tool_activity_hint(tool, params)
619
+ duration = f"{elapsed_ms}ms" if elapsed_ms < 1000 else f"{elapsed_ms / 1000:.1f}s"
620
+ entry = f"{ts} {icon} {tool}"
621
+ if hint:
622
+ entry += f" {hint}"
623
+ entry += f" · {duration}"
624
+ if not ok and isinstance(summary, dict):
625
+ error = _redact_activity_text(summary.get("error"), limit=100)
626
+ if error:
627
+ entry += f" · {error}"
628
+ self.terminal._transcript_log.append(entry)
629
+ if len(self.terminal._transcript_log) > 100:
630
+ self.terminal._transcript_log = self.terminal._transcript_log[-100:]
631
+
632
+ if tool in ("TaskCreate", "TaskUpdate") and isinstance(summary, dict):
633
+ tid = summary.get("id") or summary.get("task_id")
634
+ title = summary.get("title", "")
635
+ status = summary.get("status", "pending")
636
+ if tid:
637
+ existing = next((t for t in self.terminal._task_list if t.get("id") == tid), None)
638
+ if existing:
639
+ existing["status"] = status
640
+ if title:
641
+ existing["title"] = title
642
+ else:
643
+ self.terminal._task_list.append({"id": tid, "title": title, "status": status})
644
+
645
+ def on_status(self, state: str, message: str) -> None:
646
+ if state in ("acceptance_passed", "acceptance_failed"):
647
+ # The gate's verdict is the one piece of evidence behind "done", so
648
+ # it is printed rather than left in the turn result: a user who
649
+ # cannot see that the check went red will read the model's summary
650
+ # as if it had gone green.
651
+ passed = state == "acceptance_passed"
652
+ if self.has_rich and self.console is not None:
653
+ colour = "green" if passed else "yellow"
654
+ self.console.print(f" [{colour}]{'✓' if passed else '✗'} {message}[/{colour}]")
655
+ else:
656
+ print(f" {'✓' if passed else '✗'} {message}")
657
+ return
658
+ if state in ("review_passed", "review_blocking", "review_error"):
659
+ mark, colour = {"review_passed": ("✓", "green"), "review_blocking": ("✗", "yellow"),
660
+ "review_error": ("⚠", "dim")}[state]
661
+ if self.has_rich and self.console is not None:
662
+ from rich.markup import escape
663
+ self.console.print(f" [{colour}]{mark} {escape(message)}[/{colour}]")
664
+ else:
665
+ print(f" {mark} {message}")
666
+ return
667
+ if state in {"max_rounds", "budget_exhausted", "loop_guard", "checks_failed"}:
668
+ if self.has_rich and self.console is not None:
669
+ self.console.print(f" [yellow]Task incomplete: {message}[/yellow]")
670
+ else:
671
+ print(f" Task incomplete: {message}")
672
+ return
673
+ if state != "fallback":
674
+ return
675
+ match = re.search(r"(?:from\s+)?(\w+)\s*(?:→|->|to)\s*(\w+)", message or "", re.I)
676
+ if match:
677
+ from_provider, to_provider = match.group(1), match.group(2)
678
+ else:
679
+ from_provider, to_provider = self.fallback_from, "cloud"
680
+ from aria_code.ui.render.output import print_fallback_toast
681
+
682
+ print_fallback_toast(
683
+ from_provider,
684
+ to_provider,
685
+ message or "",
686
+ console=self.console,
687
+ has_rich=self.has_rich,
688
+ )
689
+
690
+ def handle_runtime_event(self, event: Any) -> None:
691
+ if isinstance(event, AgentEventToken):
692
+ self.on_token(event.text)
693
+ elif isinstance(event, AgentEventThinking):
694
+ self.on_thinking(event.content)
695
+ elif isinstance(event, AgentEventToolCall):
696
+ self.on_tool_call(event.tool, event.params)
697
+ elif isinstance(event, AgentEventToolResult):
698
+ self.on_tool_result(event.tool, with_measured_elapsed(event.result, getattr(event, "elapsed", None)))
699
+ elif isinstance(event, AgentEventStatus):
700
+ self.on_status(event.state, event.message)
701
+
702
+
703
+ class TerminalApprovalEventConsumer:
704
+ """Terminal-side approval prompt consumer for runtime tool execution."""
705
+
706
+ def __init__(
707
+ self,
708
+ *,
709
+ terminal: Any,
710
+ console: Any,
711
+ has_rich: bool,
712
+ confirm_decision: Callable[..., ApprovalDecision],
713
+ apply_decision: Callable[[dict, ApprovalDecision], dict],
714
+ save_config: Callable[[dict], None],
715
+ ) -> None:
716
+ self.terminal = terminal
717
+ self.console = console
718
+ self.has_rich = has_rich
719
+ self.confirm_decision = confirm_decision
720
+ self.apply_decision = apply_decision
721
+ self.save_config = save_config
722
+
723
+ async def approve(
724
+ self,
725
+ tool_name: str,
726
+ tool_params: dict,
727
+ *,
728
+ stop_before_prompt: Callable[[], None] | None = None,
729
+ ) -> ApprovalDecision:
730
+ if stop_before_prompt is not None:
731
+ stop_before_prompt()
732
+ try:
733
+ approval = self.confirm_decision(
734
+ tool_name,
735
+ tool_params,
736
+ config_policy=self.terminal.config.get("command_policy", "safe"),
737
+ )
738
+ except KeyboardInterrupt:
739
+ approval = ApprovalDecision.deny("KeyboardInterrupt")
740
+
741
+ self.terminal._record_feedback(
742
+ "tool_accept" if approval.approved else "tool_reject",
743
+ tool_name,
744
+ )
745
+ if not approval.approved:
746
+ from aria_code.ui.render.output import print_tool_blocked
747
+
748
+ zh = str(self.terminal.config.get("ui_lang", "en")).lower().startswith("zh")
749
+ print_tool_blocked(tool_name, "用户取消" if zh else "declined", console=self.console,
750
+ has_rich=self.has_rich)
751
+ return approval
752
+
753
+ def apply(self, tool_params: dict, approval: ApprovalDecision) -> dict:
754
+ self.apply_decision(tool_params, approval)
755
+ if approval.upgrade_policy:
756
+ tool_params.pop("_upgrade_policy", None)
757
+ self.terminal.config["command_policy"] = "balanced"
758
+ try:
759
+ self.save_config(self.terminal.config)
760
+ if self.has_rich:
761
+ zh = str(self.terminal.config.get("ui_lang", "en")).lower().startswith("zh")
762
+ self.console.print(" [dim]策略已升级为 balanced 并保存[/dim]" if zh else
763
+ " [dim]Policy set to balanced and saved[/dim]")
764
+ except Exception:
765
+ pass
766
+ return tool_params
767
+
768
+
769
+ __all__ = ["TerminalApprovalEventConsumer", "TerminalRuntimeEventConsumer"]