aria-code 0.52.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (478) hide show
  1. aria_code/__init__.py +42 -0
  2. aria_code/_version.py +20 -0
  3. aria_code/adk_apps/__init__.py +1 -0
  4. aria_code/adk_apps/aria_code_review/__init__.py +1 -0
  5. aria_code/adk_apps/aria_code_review/agent.py +32 -0
  6. aria_code/adk_apps/aria_research/__init__.py +1 -0
  7. aria_code/adk_apps/aria_research/agent.py +31 -0
  8. aria_code/agents/__init__.py +34 -0
  9. aria_code/agents/base.py +318 -0
  10. aria_code/agents/code_review.py +200 -0
  11. aria_code/agents/deep/__init__.py +37 -0
  12. aria_code/agents/deep/calibration_loop.py +144 -0
  13. aria_code/agents/deep/critic.py +125 -0
  14. aria_code/agents/deep/deepen.py +193 -0
  15. aria_code/agents/deep/models.py +149 -0
  16. aria_code/agents/deep/pipeline.py +164 -0
  17. aria_code/agents/deep/quant_fusion.py +192 -0
  18. aria_code/agents/deep/themes.py +95 -0
  19. aria_code/agents/deep/tiers.py +106 -0
  20. aria_code/agents/engineering/__init__.py +14 -0
  21. aria_code/agents/engineering/coder.py +222 -0
  22. aria_code/agents/engineering/tester.py +145 -0
  23. aria_code/agents/financial/__init__.py +21 -0
  24. aria_code/agents/financial/cashflow_burn.py +119 -0
  25. aria_code/agents/financial/catalyst.py +279 -0
  26. aria_code/agents/financial/corporate_finance.py +175 -0
  27. aria_code/agents/financial/debate.py +224 -0
  28. aria_code/agents/financial/earnings.py +303 -0
  29. aria_code/agents/financial/fundamental.py +191 -0
  30. aria_code/agents/financial/macro.py +99 -0
  31. aria_code/agents/financial/news.py +207 -0
  32. aria_code/agents/financial/risk.py +165 -0
  33. aria_code/agents/financial/sector.py +279 -0
  34. aria_code/agents/financial/strategist.py +121 -0
  35. aria_code/agents/financial/stripe_revenue.py +127 -0
  36. aria_code/agents/financial/synthesis.py +274 -0
  37. aria_code/agents/financial/technical.py +258 -0
  38. aria_code/agents/orchestrator.py +44 -0
  39. aria_code/agents/portfolio_agent.py +363 -0
  40. aria_code/agents/realty/__init__.py +62 -0
  41. aria_code/agents/realty/asset_diagnosis.py +152 -0
  42. aria_code/agents/realty/business_match.py +166 -0
  43. aria_code/agents/realty/cashflow_verify.py +209 -0
  44. aria_code/agents/realty/contract_rules.py +210 -0
  45. aria_code/agents/realty/energy_anomaly.py +189 -0
  46. aria_code/agents/realty/exit_settlement.py +208 -0
  47. aria_code/agents/realty/fulfillment_risk.py +206 -0
  48. aria_code/agents/realty/ops_optimize.py +160 -0
  49. aria_code/agents/realty/revenue_share.py +215 -0
  50. aria_code/agents/registry.py +158 -0
  51. aria_code/agents/signal_scheme.py +111 -0
  52. aria_code/agents/sports/__init__.py +0 -0
  53. aria_code/agents/sports/football_agent.py +197 -0
  54. aria_code/agents/supervisor.py +113 -0
  55. aria_code/agents/team.py +492 -0
  56. aria_code/agents/warehouse/__init__.py +25 -0
  57. aria_code/agents/warehouse/contracts.py +26 -0
  58. aria_code/agents/warehouse/dashboard.py +155 -0
  59. aria_code/agents/warehouse/fulfillment_leadtime.py +95 -0
  60. aria_code/agents/warehouse/inbound_exceptions.py +25 -0
  61. aria_code/agents/warehouse/inventory_health.py +24 -0
  62. aria_code/agents/warehouse/local_run.py +71 -0
  63. aria_code/agents/warehouse/local_snapshot.py +132 -0
  64. aria_code/agents/warehouse/logistics_cost.py +84 -0
  65. aria_code/agents/warehouse/logistics_sync.py +21 -0
  66. aria_code/agents/warehouse/workflow.py +31 -0
  67. aria_code/aliyun_data_client.py +4 -0
  68. aria_code/apps/README.md +12 -0
  69. aria_code/apps/__init__.py +2 -0
  70. aria_code/apps/channels/README.md +15 -0
  71. aria_code/apps/channels/__init__.py +17 -0
  72. aria_code/apps/channels/intake.py +92 -0
  73. aria_code/apps/channels/registry.py +95 -0
  74. aria_code/apps/channels/tradingview.py +94 -0
  75. aria_code/apps/cli/README.md +13 -0
  76. aria_code/apps/cli/__init__.py +2 -0
  77. aria_code/apps/cli/_optional.py +120 -0
  78. aria_code/apps/cli/bootstrap.py +145 -0
  79. aria_code/apps/cli/broker_render.py +206 -0
  80. aria_code/apps/cli/codegen_paths.py +29 -0
  81. aria_code/apps/cli/commands/__init__.py +16 -0
  82. aria_code/apps/cli/commands/_business_render.py +78 -0
  83. aria_code/apps/cli/commands/_ui.py +71 -0
  84. aria_code/apps/cli/commands/analysis_cmds.py +369 -0
  85. aria_code/apps/cli/commands/ashare_prediction_cmds.py +327 -0
  86. aria_code/apps/cli/commands/auth_cmds.py +239 -0
  87. aria_code/apps/cli/commands/backtest_cmds.py +2543 -0
  88. aria_code/apps/cli/commands/broker_cmds.py +1234 -0
  89. aria_code/apps/cli/commands/business_workflow_cmds.py +319 -0
  90. aria_code/apps/cli/commands/canvas_cmds.py +77 -0
  91. aria_code/apps/cli/commands/catalog.py +87 -0
  92. aria_code/apps/cli/commands/core_cmds.py +2520 -0
  93. aria_code/apps/cli/commands/data_cmds.py +457 -0
  94. aria_code/apps/cli/commands/diagnostic_cmds.py +230 -0
  95. aria_code/apps/cli/commands/diagnostic_ops_cmds.py +813 -0
  96. aria_code/apps/cli/commands/file_cmds.py +312 -0
  97. aria_code/apps/cli/commands/finance_service_cmds.py +60 -0
  98. aria_code/apps/cli/commands/fx_commodity_cmds.py +123 -0
  99. aria_code/apps/cli/commands/market.py +434 -0
  100. aria_code/apps/cli/commands/market_cmds.py +1381 -0
  101. aria_code/apps/cli/commands/market_context.py +425 -0
  102. aria_code/apps/cli/commands/market_render.py +7 -0
  103. aria_code/apps/cli/commands/model_cmds.py +2153 -0
  104. aria_code/apps/cli/commands/ops_cmds.py +721 -0
  105. aria_code/apps/cli/commands/orchestrator_cmds.py +179 -0
  106. aria_code/apps/cli/commands/pdf_export_cmds.py +125 -0
  107. aria_code/apps/cli/commands/portfolio_cmds.py +1278 -0
  108. aria_code/apps/cli/commands/report.py +437 -0
  109. aria_code/apps/cli/commands/scaffold_templates.py +617 -0
  110. aria_code/apps/cli/commands/session_cmds.py +236 -0
  111. aria_code/apps/cli/commands/session_ux_cmds.py +359 -0
  112. aria_code/apps/cli/commands/team.py +669 -0
  113. aria_code/apps/cli/commands/team_render.py +8 -0
  114. aria_code/apps/cli/commands/ui_cmds.py +401 -0
  115. aria_code/apps/cli/commands/warehouse_cmds.py +79 -0
  116. aria_code/apps/cli/commands/workflow_cmds.py +480 -0
  117. aria_code/apps/cli/commands/workspace_cmds.py +1494 -0
  118. aria_code/apps/cli/config_paths.py +73 -0
  119. aria_code/apps/cli/config_store.py +78 -0
  120. aria_code/apps/cli/constants.py +88 -0
  121. aria_code/apps/cli/context.py +34 -0
  122. aria_code/apps/cli/deterministic.py +191 -0
  123. aria_code/apps/cli/direct.py +48 -0
  124. aria_code/apps/cli/finance_service_catalog.py +111 -0
  125. aria_code/apps/cli/football_reports.py +231 -0
  126. aria_code/apps/cli/github_app_auth.py +135 -0
  127. aria_code/apps/cli/google_login.py +196 -0
  128. aria_code/apps/cli/handlers/__init__.py +11 -0
  129. aria_code/apps/cli/handlers/broker_handlers.py +122 -0
  130. aria_code/apps/cli/handlers/chart_handlers.py +1309 -0
  131. aria_code/apps/cli/handlers/market_handlers.py +2513 -0
  132. aria_code/apps/cli/handlers/realty_handlers.py +114 -0
  133. aria_code/apps/cli/handlers/sports_handlers.py +22 -0
  134. aria_code/apps/cli/handlers/strategy_advice.py +82 -0
  135. aria_code/apps/cli/helpers.py +302 -0
  136. aria_code/apps/cli/hooks.py +180 -0
  137. aria_code/apps/cli/i18n.py +297 -0
  138. aria_code/apps/cli/intent.py +136 -0
  139. aria_code/apps/cli/intent_router.py +276 -0
  140. aria_code/apps/cli/intent_signals.py +344 -0
  141. aria_code/apps/cli/lifecycle_hooks.py +48 -0
  142. aria_code/apps/cli/local_tool_schemas.py +536 -0
  143. aria_code/apps/cli/main.py +29 -0
  144. aria_code/apps/cli/market_metadata.py +135 -0
  145. aria_code/apps/cli/market_universe.py +487 -0
  146. aria_code/apps/cli/message_processing.py +310 -0
  147. aria_code/apps/cli/model_catalog.py +620 -0
  148. aria_code/apps/cli/pdf_report.py +977 -0
  149. aria_code/apps/cli/plan_mode.py +139 -0
  150. aria_code/apps/cli/plotly_html.py +15 -0
  151. aria_code/apps/cli/prediction_feedback.py +202 -0
  152. aria_code/apps/cli/preflight.py +502 -0
  153. aria_code/apps/cli/project_aria.py +60 -0
  154. aria_code/apps/cli/prompt_assembly.py +59 -0
  155. aria_code/apps/cli/prompts/__init__.py +0 -0
  156. aria_code/apps/cli/prompts/coding.py +53 -0
  157. aria_code/apps/cli/prompts/select.py +142 -0
  158. aria_code/apps/cli/prompts/system_prompts.py +552 -0
  159. aria_code/apps/cli/prompts/ui.py +436 -0
  160. aria_code/apps/cli/provider_endpoints.py +237 -0
  161. aria_code/apps/cli/provider_keys.py +73 -0
  162. aria_code/apps/cli/providers/__init__.py +1 -0
  163. aria_code/apps/cli/providers/base.py +521 -0
  164. aria_code/apps/cli/providers/chat_routing.py +128 -0
  165. aria_code/apps/cli/providers/collaboration.py +98 -0
  166. aria_code/apps/cli/providers/llm/__init__.py +1 -0
  167. aria_code/apps/cli/providers/llm/offline_responses.py +68 -0
  168. aria_code/apps/cli/providers/llm/ollama_stream.py +1594 -0
  169. aria_code/apps/cli/providers/llm/response_cache.py +60 -0
  170. aria_code/apps/cli/providers/llm/sse_stream.py +257 -0
  171. aria_code/apps/cli/providers/runtime_bridge.py +353 -0
  172. aria_code/apps/cli/providers/vertexai_stream.py +316 -0
  173. aria_code/apps/cli/runtime_consumer.py +657 -0
  174. aria_code/apps/cli/sandbox.py +32 -0
  175. aria_code/apps/cli/session_export.py +120 -0
  176. aria_code/apps/cli/session_jsonl.py +208 -0
  177. aria_code/apps/cli/session_store.py +112 -0
  178. aria_code/apps/cli/skills_catalog.py +273 -0
  179. aria_code/apps/cli/todo_tracker.py +190 -0
  180. aria_code/apps/cli/tool_executor.py +823 -0
  181. aria_code/apps/cli/tool_registry.py +34 -0
  182. aria_code/apps/cli/tool_scope.py +106 -0
  183. aria_code/apps/cli/tools/__init__.py +40 -0
  184. aria_code/apps/cli/tools/context.py +46 -0
  185. aria_code/apps/cli/tools/file_tools.py +180 -0
  186. aria_code/apps/cli/tools/market_tools.py +620 -0
  187. aria_code/apps/cli/tools/notebook_tools.py +111 -0
  188. aria_code/apps/cli/tools/system_tools.py +726 -0
  189. aria_code/apps/cli/tools/write_tools.py +845 -0
  190. aria_code/apps/cli/tradingview_bridge.py +529 -0
  191. aria_code/apps/cli/turn_planning.py +137 -0
  192. aria_code/apps/cli/update_check.py +153 -0
  193. aria_code/apps/cli/utils/__init__.py +0 -0
  194. aria_code/apps/cli/utils/market_detect.py +1597 -0
  195. aria_code/apps/daemon/README.md +14 -0
  196. aria_code/apps/vscode/README.md +115 -0
  197. aria_code/apps/vscode/package.json +70 -0
  198. aria_code/aria_cli.py +6743 -0
  199. aria_code/aria_daemon.py +1398 -0
  200. aria_code/aria_feishu_bot.py +1423 -0
  201. aria_code/aria_mcp_server.py +7 -0
  202. aria_code/aria_relay_client.py +4 -0
  203. aria_code/aria_relay_server.py +490 -0
  204. aria_code/aria_telegram_bot.py +202 -0
  205. aria_code/ariarc.py +385 -0
  206. aria_code/artifacts.py +581 -0
  207. aria_code/backtest_engine.py +4 -0
  208. aria_code/backtest_report.py +4 -0
  209. aria_code/brokers/__init__.py +78 -0
  210. aria_code/brokers/automation.py +193 -0
  211. aria_code/brokers/base.py +231 -0
  212. aria_code/brokers/capabilities.py +264 -0
  213. aria_code/brokers/cn/__init__.py +10 -0
  214. aria_code/brokers/cn/easytrader_broker.py +193 -0
  215. aria_code/brokers/cn/futu_broker.py +194 -0
  216. aria_code/brokers/cn/longbridge_broker.py +190 -0
  217. aria_code/brokers/cn/tiger_broker.py +196 -0
  218. aria_code/brokers/cn/xtquant_broker.py +225 -0
  219. aria_code/brokers/config.py +414 -0
  220. aria_code/brokers/intl/__init__.py +5 -0
  221. aria_code/brokers/intl/alpaca_broker.py +183 -0
  222. aria_code/brokers/intl/ibkr_broker.py +215 -0
  223. aria_code/brokers/intl/trading212_broker.py +183 -0
  224. aria_code/brokers/intl/webull_broker.py +156 -0
  225. aria_code/brokers/paper_broker.py +266 -0
  226. aria_code/brokers/planning.py +296 -0
  227. aria_code/brokers/registry.py +213 -0
  228. aria_code/brokers/trading.py +267 -0
  229. aria_code/canva_client.py +4 -0
  230. aria_code/change_store.py +127 -0
  231. aria_code/clients/__init__.py +0 -0
  232. aria_code/clients/aliyun_data_client.py +660 -0
  233. aria_code/clients/aria_relay_client.py +182 -0
  234. aria_code/clients/canva_client.py +284 -0
  235. aria_code/clients/figma_client.py +100 -0
  236. aria_code/clients/football_data_client.py +1671 -0
  237. aria_code/clients/kling_video_client.py +182 -0
  238. aria_code/clients/market_data_client.py +1976 -0
  239. aria_code/clients/openai_image_client.py +242 -0
  240. aria_code/clients/runway_video_client.py +157 -0
  241. aria_code/clients/warehouse_erp_client.py +105 -0
  242. aria_code/cloud_memory.py +181 -0
  243. aria_code/command_safety.py +19 -0
  244. aria_code/computer_use_tools.py +4 -0
  245. aria_code/dashboard_generator.py +579 -0
  246. aria_code/data_analysis_tools.py +4 -0
  247. aria_code/data_cleaner.py +483 -0
  248. aria_code/data_service.py +513 -0
  249. aria_code/datasources/__init__.py +23 -0
  250. aria_code/datasources/base.py +166 -0
  251. aria_code/datasources/router.py +253 -0
  252. aria_code/datasources/sources/__init__.py +15 -0
  253. aria_code/datasources/sources/akshare_source.py +269 -0
  254. aria_code/datasources/sources/alpha_vantage_source.py +203 -0
  255. aria_code/datasources/sources/edgar_source.py +219 -0
  256. aria_code/datasources/sources/finnhub_source.py +198 -0
  257. aria_code/datasources/sources/fred_source.py +223 -0
  258. aria_code/datasources/sources/tushare_source.py +143 -0
  259. aria_code/datasources/sources/web_scraper_source.py +278 -0
  260. aria_code/datasources/sources/world_bank_source.py +206 -0
  261. aria_code/datasources/sources/yfinance_source.py +152 -0
  262. aria_code/demo_player.py +207 -0
  263. aria_code/doctor.py +813 -0
  264. aria_code/domain/__init__.py +0 -0
  265. aria_code/domain/backtest_engine.py +354 -0
  266. aria_code/domain/backtest_report.py +472 -0
  267. aria_code/domain/finance_formulas.py +389 -0
  268. aria_code/domain/portfolio_ledger.py +307 -0
  269. aria_code/domain/strategy_vault.py +421 -0
  270. aria_code/evals/__init__.py +37 -0
  271. aria_code/evals/harness.py +598 -0
  272. aria_code/evals/runner.py +238 -0
  273. aria_code/external_agent_runner.py +115 -0
  274. aria_code/figma_client.py +4 -0
  275. aria_code/file_analysis_tools.py +4 -0
  276. aria_code/finance_formulas.py +4 -0
  277. aria_code/football_data_client.py +4 -0
  278. aria_code/image_gen_tools.py +4 -0
  279. aria_code/intent_classifier.py +386 -0
  280. aria_code/kling_video_client.py +4 -0
  281. aria_code/licensing.py +151 -0
  282. aria_code/local_finance_tools.py +4 -0
  283. aria_code/local_image_provider.py +4 -0
  284. aria_code/local_llm_provider.py +4 -0
  285. aria_code/macro_tools.py +4 -0
  286. aria_code/markdown_pdf.py +289 -0
  287. aria_code/market_data_client.py +4 -0
  288. aria_code/mcp_client.py +639 -0
  289. aria_code/memory_manager.py +246 -0
  290. aria_code/model_capability.py +486 -0
  291. aria_code/notification_tools.py +4 -0
  292. aria_code/openai_image_client.py +4 -0
  293. aria_code/packages/__init__.py +23 -0
  294. aria_code/packages/adk_bridge/__init__.py +11 -0
  295. aria_code/packages/adk_bridge/code_review_tools.py +49 -0
  296. aria_code/packages/adk_bridge/market_tools.py +125 -0
  297. aria_code/packages/aria_agents/__init__.py +5 -0
  298. aria_code/packages/aria_agents/manifest.py +78 -0
  299. aria_code/packages/aria_core/__init__.py +34 -0
  300. aria_code/packages/aria_core/architecture.py +269 -0
  301. aria_code/packages/aria_core/export.py +147 -0
  302. aria_code/packages/aria_core/manifest.py +65 -0
  303. aria_code/packages/aria_core/paths.py +57 -0
  304. aria_code/packages/aria_core/secure_file.py +68 -0
  305. aria_code/packages/aria_infra/__init__.py +15 -0
  306. aria_code/packages/aria_infra/arthera.py +52 -0
  307. aria_code/packages/aria_infra/doctor.py +246 -0
  308. aria_code/packages/aria_infra/product.py +40 -0
  309. aria_code/packages/aria_mcp/__init__.py +25 -0
  310. aria_code/packages/aria_mcp/bridge.py +201 -0
  311. aria_code/packages/aria_mcp/circuit.py +82 -0
  312. aria_code/packages/aria_mcp/config.py +111 -0
  313. aria_code/packages/aria_mcp/installer.py +95 -0
  314. aria_code/packages/aria_mcp/server.py +1550 -0
  315. aria_code/packages/aria_mcp/tools.py +81 -0
  316. aria_code/packages/aria_sdk/__init__.py +19 -0
  317. aria_code/packages/aria_sdk/client.py +396 -0
  318. aria_code/packages/aria_sdk/providers.py +70 -0
  319. aria_code/packages/aria_sdk/streaming.py +79 -0
  320. aria_code/packages/aria_sdk/types.py +86 -0
  321. aria_code/packages/aria_services/__init__.py +92 -0
  322. aria_code/packages/aria_services/cache.py +60 -0
  323. aria_code/packages/aria_services/context.py +356 -0
  324. aria_code/packages/aria_services/context_checkpoints.py +157 -0
  325. aria_code/packages/aria_services/data.py +11 -0
  326. aria_code/packages/aria_services/provider_health.py +268 -0
  327. aria_code/packages/aria_services/references.py +247 -0
  328. aria_code/packages/aria_services/registry.py +249 -0
  329. aria_code/packages/aria_services/research_protocol.py +57 -0
  330. aria_code/packages/aria_services/research_quality.py +186 -0
  331. aria_code/packages/aria_services/settings.py +157 -0
  332. aria_code/packages/aria_services/usage.py +151 -0
  333. aria_code/packages/aria_skills/__init__.py +46 -0
  334. aria_code/packages/aria_skills/catalog.py +149 -0
  335. aria_code/packages/aria_skills/loader.py +455 -0
  336. aria_code/packages/aria_skills/registry.py +84 -0
  337. aria_code/packages/aria_tools/__init__.py +5 -0
  338. aria_code/packages/aria_tools/financial/__init__.py +8 -0
  339. aria_code/packages/aria_tools/financial/_paths.py +130 -0
  340. aria_code/packages/aria_tools/financial/compliance.py +31 -0
  341. aria_code/packages/aria_tools/financial/factors.py +33 -0
  342. aria_code/packages/aria_tools/financial/risk_tools.py +33 -0
  343. aria_code/packages/aria_tools/financial/strategy.py +31 -0
  344. aria_code/packages/aria_tools/registry.py +128 -0
  345. aria_code/packages/quant_engine/__init__.py +34 -0
  346. aria_code/packages/quant_engine/_namespace.py +62 -0
  347. aria_code/packages/quant_engine/backtest/__init__.py +14 -0
  348. aria_code/packages/quant_engine/backtest/core.py +53 -0
  349. aria_code/packages/quant_engine/backtest/engine.py +96 -0
  350. aria_code/packages/quant_engine/portfolio/__init__.py +13 -0
  351. aria_code/packages/quant_engine/portfolio/optimizer.py +85 -0
  352. aria_code/packages/quant_engine/sports/__init__.py +80 -0
  353. aria_code/packages/quant_engine/sports/calibrator.py +354 -0
  354. aria_code/packages/quant_engine/sports/dixon_coles.py +234 -0
  355. aria_code/packages/quant_engine/sports/elo.py +300 -0
  356. aria_code/packages/quant_engine/sports/form.py +188 -0
  357. aria_code/packages/quant_engine/sports/h2h.py +195 -0
  358. aria_code/packages/quant_engine/sports/ml_model.py +377 -0
  359. aria_code/packages/quant_engine/sports/predictor.py +312 -0
  360. aria_code/packages/quant_engine/sports/tracker.py +665 -0
  361. aria_code/packages/quant_engine/stochastic/__init__.py +35 -0
  362. aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +195 -0
  363. aria_code/packages/quant_engine/stochastic/ito_calculus.py +477 -0
  364. aria_code/packages/quant_engine/stochastic/kelly_criterion.py +181 -0
  365. aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +95 -0
  366. aria_code/packages/quant_engine/stochastic/options_pricing.py +576 -0
  367. aria_code/packages/quant_engine/stochastic/stochastic_processes.py +90 -0
  368. aria_code/packs/__init__.py +85 -0
  369. aria_code/packs/base.py +168 -0
  370. aria_code/packs/finance/__init__.py +250 -0
  371. aria_code/packs/logistics/__init__.py +169 -0
  372. aria_code/packs/payments/__init__.py +139 -0
  373. aria_code/packs/realty/__init__.py +190 -0
  374. aria_code/packs/registry.py +202 -0
  375. aria_code/packs/rules.py +90 -0
  376. aria_code/plan_utils.py +194 -0
  377. aria_code/plugin_loader.py +328 -0
  378. aria_code/portfolio_ledger.py +4 -0
  379. aria_code/preview_server.py +449 -0
  380. aria_code/privacy/__init__.py +5 -0
  381. aria_code/privacy/feedback.py +123 -0
  382. aria_code/project_review.py +278 -0
  383. aria_code/project_review_api.py +235 -0
  384. aria_code/project_review_server.py +18 -0
  385. aria_code/project_tools.py +4 -0
  386. aria_code/providers/__init__.py +30 -0
  387. aria_code/providers/llm/__init__.py +19 -0
  388. aria_code/providers/llm/anthropic.py +184 -0
  389. aria_code/providers/llm/autoconfig.py +213 -0
  390. aria_code/providers/llm/base.py +139 -0
  391. aria_code/providers/llm/custom.py +158 -0
  392. aria_code/providers/llm/ollama.py +129 -0
  393. aria_code/providers/llm/openai_compat.py +313 -0
  394. aria_code/providers/llm/registry.py +444 -0
  395. aria_code/providers/local_image_provider.py +202 -0
  396. aria_code/providers/local_llm_provider.py +589 -0
  397. aria_code/realty_data_tools.py +4 -0
  398. aria_code/report_exporters.py +150 -0
  399. aria_code/report_generator.py +1764 -0
  400. aria_code/runtime/__init__.py +169 -0
  401. aria_code/runtime/acceptance.py +481 -0
  402. aria_code/runtime/agent_loop.py +1520 -0
  403. aria_code/runtime/approval.py +57 -0
  404. aria_code/runtime/budget.py +232 -0
  405. aria_code/runtime/checkpoints.py +432 -0
  406. aria_code/runtime/crash_report.py +174 -0
  407. aria_code/runtime/events.py +113 -0
  408. aria_code/runtime/gateway.py +150 -0
  409. aria_code/runtime/lsp.py +484 -0
  410. aria_code/runtime/orchestrator.py +55 -0
  411. aria_code/runtime/repo_map.py +700 -0
  412. aria_code/runtime/run_state.py +127 -0
  413. aria_code/runtime/run_store.py +450 -0
  414. aria_code/runtime/self_healing.py +422 -0
  415. aria_code/runtime/subagent.py +547 -0
  416. aria_code/runtime/task_ledger.py +86 -0
  417. aria_code/runtime/task_orchestrator.py +90 -0
  418. aria_code/runtime/tool_executor.py +217 -0
  419. aria_code/runtime/tool_policy.py +107 -0
  420. aria_code/runtime/worktrees.py +215 -0
  421. aria_code/runway_video_client.py +4 -0
  422. aria_code/safety/__init__.py +23 -0
  423. aria_code/safety/permissions.py +306 -0
  424. aria_code/safety/service.py +102 -0
  425. aria_code/setup_wizard.py +673 -0
  426. aria_code/spreadsheet_tools.py +4 -0
  427. aria_code/strategy_vault.py +4 -0
  428. aria_code/tools/__init__.py +0 -0
  429. aria_code/tools/artifact_tools.py +252 -0
  430. aria_code/tools/broker_tools.py +92 -0
  431. aria_code/tools/build_quant_engine.py +97 -0
  432. aria_code/tools/code_audit_tools.py +192 -0
  433. aria_code/tools/computer_use_tools.py +504 -0
  434. aria_code/tools/data_analysis_tools.py +809 -0
  435. aria_code/tools/enterprise_finance_tools.py +156 -0
  436. aria_code/tools/extended_tools.py +240 -0
  437. aria_code/tools/file_analysis_tools.py +885 -0
  438. aria_code/tools/image_gen_tools.py +114 -0
  439. aria_code/tools/local_finance_tools.py +3417 -0
  440. aria_code/tools/logistics_tools.py +135 -0
  441. aria_code/tools/macro_tools.py +369 -0
  442. aria_code/tools/notification_tools.py +249 -0
  443. aria_code/tools/project_tools.py +525 -0
  444. aria_code/tools/realty_data_tools.py +659 -0
  445. aria_code/tools/spreadsheet_tools.py +388 -0
  446. aria_code/tools/stripe_tools.py +115 -0
  447. aria_code/ui/__init__.py +105 -0
  448. aria_code/ui/banner.py +508 -0
  449. aria_code/ui/completer.py +501 -0
  450. aria_code/ui/console.py +281 -0
  451. aria_code/ui/image_render.py +243 -0
  452. aria_code/ui/input_box.py +488 -0
  453. aria_code/ui/picker.py +201 -0
  454. aria_code/ui/render/__init__.py +11 -0
  455. aria_code/ui/render/finance.py +1705 -0
  456. aria_code/ui/render/market.py +225 -0
  457. aria_code/ui/render/output.py +775 -0
  458. aria_code/ui/render/responsive.py +75 -0
  459. aria_code/ui/render/team.py +354 -0
  460. aria_code/ui/robot.py +235 -0
  461. aria_code/ui/startup_dashboard.py +109 -0
  462. aria_code/utils/vscode_uri.py +37 -0
  463. aria_code/video_analysis.py +147 -0
  464. aria_code/video_editor.py +271 -0
  465. aria_code/workspace/__init__.py +6 -0
  466. aria_code/workspace/files.py +193 -0
  467. aria_code/workspace/verify.py +113 -0
  468. aria_code/workspace_changes.py +199 -0
  469. aria_code/workspace_context.py +233 -0
  470. aria_code/workspace_service.py +196 -0
  471. aria_code/workspace_tools.py +150 -0
  472. aria_code-0.52.0.dist-info/METADATA +237 -0
  473. aria_code-0.52.0.dist-info/RECORD +478 -0
  474. aria_code-0.52.0.dist-info/WHEEL +5 -0
  475. aria_code-0.52.0.dist-info/entry_points.txt +3 -0
  476. aria_code-0.52.0.dist-info/licenses/LICENSE +201 -0
  477. aria_code-0.52.0.dist-info/licenses/NOTICE +49 -0
  478. aria_code-0.52.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,139 @@
1
+ """Payments — Stripe objects.
2
+
3
+ The cleanest case the pack contract has. Stripe object ids carry a typed
4
+ prefix (``ch_`` charge, ``pi_`` payment intent, ``cus_`` customer, ``sub_``
5
+ subscription…) followed by a long opaque suffix, so recognising one is a
6
+ resolution rather than a guess: nothing else in an English or Chinese sentence
7
+ looks like ``pi_3PqR8s2eZvKYlo2C0aBcDeFg``.
8
+
9
+ That precision is what lets this pack stay registered permanently at no cost.
10
+ It cannot fire on domain vocabulary — the words "payment", "refund" and
11
+ "订阅" never activate it — so a payments deployment adds nothing to the latency
12
+ or the failure surface of a session about anything else.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import re
18
+ from typing import Sequence
19
+
20
+ from aria_code.packs.base import BaseDomainPack, EntityMatch, PackActivation
21
+
22
+ PACK_NAME = "payments"
23
+
24
+ PAYMENT_TOOLS = (
25
+ "analyze_stripe_data",
26
+ )
27
+
28
+ _RESOLVED = 0.95
29
+
30
+ # prefix → what the object is. Kept explicit rather than matching a generic
31
+ # `\w+_[A-Za-z0-9]{14,}` because an unknown prefix is far more likely to be
32
+ # someone's own snake_case identifier than a Stripe object.
33
+ _OBJECT_PREFIXES: dict[str, str] = {
34
+ "ch": "charge",
35
+ "pi": "payment_intent",
36
+ "cus": "customer",
37
+ "sub": "subscription",
38
+ "in": "invoice",
39
+ "il": "invoice_item",
40
+ "price": "price",
41
+ "prod": "product",
42
+ "acct": "account",
43
+ "evt": "event",
44
+ "re": "refund",
45
+ "txn": "balance_transaction",
46
+ "po": "payout",
47
+ "seti": "setup_intent",
48
+ "pm": "payment_method",
49
+ "cs": "checkout_session",
50
+ "dp": "dispute",
51
+ "sk": "secret_key",
52
+ "rk": "restricted_key",
53
+ }
54
+
55
+ # Stripe ids are prefix + '_' + at least 14 base62 characters, optionally with
56
+ # a `test_` segment in live-vs-test form (`sk_test_…`, `ch_test_…`).
57
+ _OBJECT_ID = re.compile(
58
+ r"\b(" + "|".join(sorted(_OBJECT_PREFIXES, key=len, reverse=True)) + r")_"
59
+ r"(?:test_|live_)?([A-Za-z0-9]{14,})\b"
60
+ )
61
+
62
+
63
+ class PaymentsPack(BaseDomainPack):
64
+ """Recognises Stripe object ids and owns the payments workflows."""
65
+
66
+ name = PACK_NAME
67
+
68
+ def resolve_entities(self, message: str) -> Sequence[EntityMatch]:
69
+ text = message or ""
70
+ if "_" not in text:
71
+ # Every id this pack knows contains an underscore, so this one
72
+ # check skips the regex entirely for the overwhelming majority of
73
+ # messages — the resolver runs on every message, for every pack.
74
+ return ()
75
+
76
+ seen: set[str] = set()
77
+ entities: list[EntityMatch] = []
78
+ for match in _OBJECT_ID.finditer(text):
79
+ value = match.group(0)
80
+ if value in seen:
81
+ continue
82
+ seen.add(value)
83
+ entities.append(EntityMatch(
84
+ pack=PACK_NAME,
85
+ kind=_OBJECT_PREFIXES[match.group(1)],
86
+ value=value,
87
+ surface=value,
88
+ position=match.start(),
89
+ confidence=_RESOLVED,
90
+ ))
91
+ return tuple(entities)
92
+
93
+ def tool_names(self) -> Sequence[str]:
94
+ return PAYMENT_TOOLS
95
+
96
+ def prompt_fragment(self, activation: PackActivation) -> str:
97
+ kinds = ", ".join(sorted({e.kind for e in activation.entities}))
98
+ has_key = any(e.kind.endswith("_key") for e in activation.entities)
99
+ text = (
100
+ f"Stripe 对象已识别({kinds})。\n"
101
+ "用工具取回的账务数据回答,不要凭记忆推断金额、状态或结算周期;"
102
+ "涉及退款、扣款、订阅变更等写操作时,先说明将要发生什么并等待确认。"
103
+ )
104
+ if has_key:
105
+ # The one case where the right move is to stop rather than help.
106
+ text += (
107
+ "\n⚠ 消息中疑似包含 Stripe 密钥。不要复述它、不要写入文件、"
108
+ "不要用它发起请求;提醒用户立即在 Stripe 后台轮换该密钥。"
109
+ )
110
+ return text
111
+
112
+ def acceptance_commands(self, activation: PackActivation) -> Sequence[str]:
113
+ # Looked up through the module rather than a name bound at import, so
114
+ # what this workspace declares is read when the turn runs — a .ariarc
115
+ # edited mid-session takes effect on the next message, not the next
116
+ # process.
117
+ from aria_code.packs import rules
118
+
119
+ return rules.acceptance_commands_for(PACK_NAME)
120
+
121
+
122
+ PAYMENTS_PACK = PaymentsPack()
123
+
124
+
125
+ def register() -> PaymentsPack:
126
+ """Register the payments pack. Idempotent."""
127
+ from aria_code.packs.registry import register_pack
128
+
129
+ register_pack(PAYMENTS_PACK)
130
+ return PAYMENTS_PACK
131
+
132
+
133
+ __all__ = [
134
+ "PACK_NAME",
135
+ "PAYMENTS_PACK",
136
+ "PAYMENT_TOOLS",
137
+ "PaymentsPack",
138
+ "register",
139
+ ]
@@ -0,0 +1,190 @@
1
+ """Real estate — a city's housing market.
2
+
3
+ This pack is the contract's hard case, and worth reading as one. Its domain
4
+ has no ``AAPL`` and no ``ch_3Pq…``: the thing a housing question is *about* is
5
+ a city, and a city name on its own is a perfectly ordinary word. "北京" appears
6
+ in travel plans, in address parsing, in a comment about a datacenter region.
7
+
8
+ So the entity this pack resolves is not the city. It is **this city's housing
9
+ market**, which takes two parts to name: a city from a real table, and a
10
+ housing term in the same message. A city alone resolves at a confidence below
11
+ the activation threshold — reported, so the UI can ask, but never enough to
12
+ answer a code question with a house-price index on its own initiative.
13
+
14
+ That is the same rule finance applies to a bare uppercase run, arrived at from
15
+ the opposite direction: finance has to *demote* a shape that looks like an
16
+ identifier, and realty has to *combine* two things neither of which is one.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from typing import Sequence
22
+
23
+ from aria_code.packs.base import BaseDomainPack, EntityMatch, PackActivation
24
+
25
+ PACK_NAME = "realty"
26
+
27
+ # Empty on purpose. get_house_price_index/get_re_investment exist as functions
28
+ # in realty_data_tools but have no register_* wrapper, so they are not in
29
+ # LOCAL_TOOLS. Naming them here told the model about a capability it does not
30
+ # have, which costs a wasted round and a confusing "unknown tool" error.
31
+ # The pack still contributes its handler and its prompt guidance.
32
+ REALTY_TOOLS: tuple[str, ...] = ()
33
+
34
+ _RESOLVED = 0.95
35
+ _CITY_ONLY = 0.3
36
+
37
+ # Terms that name a housing market by themselves, with no city attached.
38
+ # "全国房价走势" is a real question about a real market, and refusing it would
39
+ # lose behaviour the ungated chain used to provide.
40
+ #
41
+ # The line drawn here is narrower than the handler's keyword list on purpose.
42
+ # "房价" and "楼市" name a market; "房产", "地产" and "物业" name a *topic*, and
43
+ # they appear in the source of any property-management codebase — which is
44
+ # exactly the kind of message that must not come back as a price index.
45
+ _NATIONAL_MARKET_TERMS = (
46
+ "房价", "楼市", "楼价", "二手房", "新房",
47
+ "house price", "home price", "housing market", "property price",
48
+ )
49
+
50
+
51
+ def _tables() -> tuple[tuple[str, ...], tuple[str, ...], tuple[str, ...]]:
52
+ """City and keyword tables, borrowed rather than duplicated.
53
+
54
+ They live in ``market_detect`` because the legacy chain used them; a copy
55
+ here would drift, and the failure that drift produces (a city Aria stopped
56
+ recognising after someone edited one list) is silent.
57
+ """
58
+ try:
59
+ from aria_code.apps.cli.utils.market_detect import (
60
+ _CN_CITIES,
61
+ _INTL_CITIES,
62
+ _REALTY_QUERY_KEYWORDS,
63
+ )
64
+ except Exception:
65
+ return (), (), ()
66
+ return tuple(_CN_CITIES), tuple(_INTL_CITIES), tuple(_REALTY_QUERY_KEYWORDS)
67
+
68
+
69
+ class RealtyPack(BaseDomainPack):
70
+ """Recognises a named city's housing market."""
71
+
72
+ name = PACK_NAME
73
+
74
+ def resolve_entities(self, message: str) -> Sequence[EntityMatch]:
75
+ text = message or ""
76
+ if not text.strip():
77
+ return ()
78
+
79
+ cn_cities, intl_cities, keywords = _tables()
80
+ if not cn_cities and not intl_cities:
81
+ return ()
82
+
83
+ lowered = text.lower()
84
+ has_housing_term = any(keyword in lowered for keyword in keywords)
85
+
86
+ found: list[tuple[str, int]] = []
87
+ for city in cn_cities:
88
+ position = text.find(city)
89
+ if position >= 0:
90
+ found.append((city, position))
91
+ for city in intl_cities:
92
+ position = lowered.find(city)
93
+ if position >= 0:
94
+ found.append((city, position))
95
+
96
+ if not found:
97
+ # No city named, but the message may still name the national
98
+ # market outright.
99
+ for term in _NATIONAL_MARKET_TERMS:
100
+ position = lowered.find(term)
101
+ if position >= 0:
102
+ return (EntityMatch(
103
+ pack=PACK_NAME, kind="housing_market", value="全国",
104
+ surface=term, position=position, confidence=_RESOLVED,
105
+ ),)
106
+ return ()
107
+
108
+ # Earliest mention first, and cap it: a message listing fifteen cities
109
+ # is a table, not a question about a housing market.
110
+ found.sort(key=lambda item: item[1])
111
+ confidence = _RESOLVED if has_housing_term else _CITY_ONLY
112
+
113
+ seen: set[str] = set()
114
+ entities: list[EntityMatch] = []
115
+ for city, position in found[:6]:
116
+ if city in seen:
117
+ continue
118
+ seen.add(city)
119
+ entities.append(EntityMatch(
120
+ pack=PACK_NAME, kind="housing_market", value=city,
121
+ surface=city, position=position, confidence=confidence,
122
+ ))
123
+ return tuple(entities)
124
+
125
+ def handlers(self) -> Sequence[object]:
126
+ """The realty handler, now reachable only when a market is named."""
127
+ try:
128
+ from aria_code.apps.cli.handlers.realty_handlers import handle_realty_query
129
+ from aria_code.apps.cli.utils.market_detect import (
130
+ _CN_CITIES,
131
+ _INTL_CITIES,
132
+ _is_realty_query,
133
+ )
134
+ except Exception:
135
+ return ()
136
+
137
+ def _handle(message: str) -> dict:
138
+ return handle_realty_query(
139
+ message,
140
+ is_realty_query=_is_realty_query,
141
+ cn_cities=_CN_CITIES,
142
+ intl_cities=_INTL_CITIES,
143
+ )
144
+
145
+ return (_handle,)
146
+
147
+ def tool_names(self) -> Sequence[str]:
148
+ return REALTY_TOOLS
149
+
150
+ def prompt_fragment(self, activation: PackActivation) -> str:
151
+ cities = ", ".join(sorted({e.value for e in activation.entities}))
152
+ # No tool instruction here: this pack exposes none. The price index is
153
+ # fetched by the deterministic handler above, so if the model is the one
154
+ # answering, it has no data source and must say so rather than produce
155
+ # a plausible number.
156
+ return (
157
+ f"房地产市场已识别:{cities}。\n"
158
+ "你没有房价数据工具。除非上文已给出取回的数据,否则不要给出具体房价、"
159
+ "涨跌幅或指数值——说明数据不可得,并建议用 /realty 命令获取;"
160
+ "标注统计口径(新房/二手房、环比/同比)与数据时间;输出不构成投资建议。"
161
+ )
162
+
163
+ def acceptance_commands(self, activation: PackActivation) -> Sequence[str]:
164
+ # Looked up through the module rather than a name bound at import, so
165
+ # what this workspace declares is read when the turn runs — a .ariarc
166
+ # edited mid-session takes effect on the next message, not the next
167
+ # process.
168
+ from aria_code.packs import rules
169
+
170
+ return rules.acceptance_commands_for(PACK_NAME)
171
+
172
+
173
+ REALTY_PACK = RealtyPack()
174
+
175
+
176
+ def register() -> RealtyPack:
177
+ """Register the realty pack. Idempotent."""
178
+ from aria_code.packs.registry import register_pack
179
+
180
+ register_pack(REALTY_PACK)
181
+ return REALTY_PACK
182
+
183
+
184
+ __all__ = [
185
+ "PACK_NAME",
186
+ "REALTY_PACK",
187
+ "REALTY_TOOLS",
188
+ "RealtyPack",
189
+ "register",
190
+ ]
@@ -0,0 +1,202 @@
1
+ """Domain pack registration and entity-gated activation.
2
+
3
+ Activation is the whole point of this module. A pack is switched on for a
4
+ message only when it resolves a concrete entity *from that message*, at or
5
+ above a confidence threshold. Three consequences follow, each of which fixes a
6
+ failure this codebase actually shipped:
7
+
8
+ - **Domain vocabulary cannot activate a pack.** "根据以上分析和建议开始完善"
9
+ contains 分析 but names nothing; no pack claims it, so no market handler,
10
+ no quote, no ticker.
11
+ - **Conversation history cannot activate a pack.** Only the user's current
12
+ message is offered to resolvers. An assistant reply that mentioned
13
+ "Cassandra/MongoDB" can no longer donate the ticker MDB to the next turn.
14
+ - **An inactive pack costs nothing.** It contributes no handlers, no tools
15
+ and no prompt text, so adding a clinical or logistics pack does not slow
16
+ down or perturb a finance user, and vice versa.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import logging
22
+ from typing import Iterable, Sequence
23
+
24
+ from aria_code.packs.base import (
25
+ DEFAULT_ACTIVATION_THRESHOLD,
26
+ DomainPack,
27
+ EntityMatch,
28
+ PackActivation,
29
+ )
30
+
31
+ logger = logging.getLogger(__name__)
32
+
33
+ _REGISTRY: dict[str, DomainPack] = {}
34
+
35
+
36
+ def register_pack(pack: DomainPack) -> None:
37
+ """Register *pack* under its name, replacing any earlier registration."""
38
+ name = getattr(pack, "name", "")
39
+ if not name:
40
+ raise ValueError("a domain pack must declare a non-empty name")
41
+ if not hasattr(pack, "resolve_entities"):
42
+ raise TypeError(f"pack {name!r} does not implement resolve_entities()")
43
+ _REGISTRY[name] = pack
44
+
45
+
46
+ def unregister_pack(name: str) -> None:
47
+ _REGISTRY.pop(name, None)
48
+
49
+
50
+ def registered_packs() -> tuple[DomainPack, ...]:
51
+ return tuple(_REGISTRY.values())
52
+
53
+
54
+ def get_pack(name: str) -> DomainPack | None:
55
+ return _REGISTRY.get(name)
56
+
57
+
58
+ def clear_registry() -> None:
59
+ """Drop every registration (tests)."""
60
+ _REGISTRY.clear()
61
+
62
+
63
+ def _entities_from(pack: DomainPack, message: str) -> list[EntityMatch]:
64
+ """Ask one pack what it recognises, never letting it break the request.
65
+
66
+ A resolver runs on every message; a pack that raises, or that returns
67
+ something malformed, must degrade to "recognises nothing" rather than take
68
+ the CLI down with it.
69
+ """
70
+ try:
71
+ found = pack.resolve_entities(message) or ()
72
+ except Exception:
73
+ logger.debug("pack %r failed to resolve entities", getattr(pack, "name", "?"),
74
+ exc_info=True)
75
+ return []
76
+ out: list[EntityMatch] = []
77
+ for entity in found:
78
+ if isinstance(entity, EntityMatch):
79
+ out.append(entity)
80
+ return out
81
+
82
+
83
+ def activate_packs(
84
+ message: str,
85
+ *,
86
+ packs: Iterable[DomainPack] | None = None,
87
+ threshold: float = DEFAULT_ACTIVATION_THRESHOLD,
88
+ ) -> tuple[PackActivation, ...]:
89
+ """Return the packs that claim *message*, most confident first.
90
+
91
+ Only the current user message is considered. Callers must not pass
92
+ conversation history here: inheriting an entity across turns is what
93
+ produced a stock quote in reply to "根据以上分析和建议开始完善".
94
+ """
95
+ if not (message or "").strip():
96
+ return ()
97
+
98
+ candidates = tuple(packs) if packs is not None else registered_packs()
99
+ activations: list[PackActivation] = []
100
+ for pack in candidates:
101
+ entities = [
102
+ e for e in _entities_from(pack, message) if e.confidence >= threshold
103
+ ]
104
+ if entities:
105
+ activations.append(
106
+ PackActivation(
107
+ pack=getattr(pack, "name", ""),
108
+ entities=tuple(entities),
109
+ )
110
+ )
111
+ activations.sort(key=lambda a: -a.confidence)
112
+ return tuple(activations)
113
+
114
+
115
+ def active_handlers(activations: Sequence[PackActivation]) -> tuple[object, ...]:
116
+ """Deterministic handlers contributed by the active packs, in order."""
117
+ handlers: list[object] = []
118
+ for activation in activations:
119
+ pack = get_pack(activation.pack)
120
+ if pack is None:
121
+ continue
122
+ try:
123
+ handlers.extend(pack.handlers() or ())
124
+ except Exception:
125
+ logger.debug("pack %r failed to provide handlers", activation.pack,
126
+ exc_info=True)
127
+ return tuple(handlers)
128
+
129
+
130
+ def active_tool_names(activations: Sequence[PackActivation]) -> tuple[str, ...]:
131
+ """Tool names to expose to the model for this message."""
132
+ names: list[str] = []
133
+ for activation in activations:
134
+ pack = get_pack(activation.pack)
135
+ if pack is None:
136
+ continue
137
+ try:
138
+ for name in pack.tool_names() or ():
139
+ if name and name not in names:
140
+ names.append(str(name))
141
+ except Exception:
142
+ logger.debug("pack %r failed to provide tool names", activation.pack,
143
+ exc_info=True)
144
+ return tuple(names)
145
+
146
+
147
+ def active_prompt_fragments(activations: Sequence[PackActivation]) -> tuple[str, ...]:
148
+ """Domain guidance to append to the system prompt for this message."""
149
+ fragments: list[str] = []
150
+ for activation in activations:
151
+ pack = get_pack(activation.pack)
152
+ if pack is None:
153
+ continue
154
+ try:
155
+ fragment = pack.prompt_fragment(activation) or ""
156
+ except Exception:
157
+ logger.debug("pack %r failed to provide a prompt fragment", activation.pack,
158
+ exc_info=True)
159
+ continue
160
+ if fragment.strip():
161
+ fragments.append(fragment.strip())
162
+ return tuple(fragments)
163
+
164
+
165
+ def active_acceptance_commands(activations: Sequence[PackActivation]) -> tuple[str, ...]:
166
+ """Verification commands contributed by the active packs, deduplicated.
167
+
168
+ Order follows activation confidence, so the pack that most clearly owns
169
+ the message gets its check run first — and the acceptance gate stops at
170
+ the first red, which makes that ordering the difference between a useful
171
+ failure and a confusing one.
172
+ """
173
+ commands: list[str] = []
174
+ for activation in activations:
175
+ pack = get_pack(activation.pack)
176
+ if pack is None:
177
+ continue
178
+ try:
179
+ found = pack.acceptance_commands(activation) or ()
180
+ except Exception:
181
+ logger.debug("pack %r failed to provide acceptance commands", activation.pack,
182
+ exc_info=True)
183
+ continue
184
+ for command in found:
185
+ text = str(command or "").strip()
186
+ if text and text not in commands:
187
+ commands.append(text)
188
+ return tuple(commands)
189
+
190
+
191
+ __all__ = [
192
+ "activate_packs",
193
+ "active_acceptance_commands",
194
+ "active_handlers",
195
+ "active_prompt_fragments",
196
+ "active_tool_names",
197
+ "clear_registry",
198
+ "get_pack",
199
+ "register_pack",
200
+ "registered_packs",
201
+ "unregister_pack",
202
+ ]
@@ -0,0 +1,90 @@
1
+ """Where a pack learns what "correct" means in *this* workspace.
2
+
3
+ A pack knows the shape of its domain — that a waybill is a waybill, that
4
+ ``ch_3P…`` is a Stripe charge. It cannot know how a particular company checks
5
+ that work on those things was done right: which script reconciles their ledger,
6
+ which job validates their schema, what their build is called. That knowledge
7
+ belongs to the workspace, not to the pack, and it is the one thing that has to
8
+ come from outside for the closed loop to mean anything in a domain the core
9
+ never learned.
10
+
11
+ So packs read it from the project's own ``.ariarc``::
12
+
13
+ "acceptance": {
14
+ "default": ["python3 -m pytest -q"],
15
+ "logistics": ["python3 scripts/reconcile_waybills.py"],
16
+ "payments": ["python3 scripts/verify_stripe_sync.py"]
17
+ }
18
+
19
+ ``default`` applies to every turn. A pack-named list applies only when that
20
+ pack resolved a concrete entity from the user's message — the same activation
21
+ rule that governs everything else a pack contributes, so declaring a logistics
22
+ check cannot slow down or perturb a payments question.
23
+
24
+ This is the whole productisation story for a new industry: a company does not
25
+ extend Aria to adopt it, they declare what green looks like and the loop they
26
+ already have starts holding that line.
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ import logging
32
+ from typing import Sequence
33
+
34
+ logger = logging.getLogger(__name__)
35
+
36
+ DEFAULT_KEY = "default"
37
+
38
+
39
+ def _coerce(value: object) -> tuple[str, ...]:
40
+ """Accept a string or a list of them; ignore anything else.
41
+
42
+ Hand-edited config is the input here, so a single command written as a
43
+ bare string is the expected mistake, not an error worth failing a turn
44
+ over.
45
+ """
46
+ if isinstance(value, str):
47
+ text = value.strip()
48
+ return (text,) if text else ()
49
+ if isinstance(value, (list, tuple)):
50
+ out: list[str] = []
51
+ for item in value:
52
+ if isinstance(item, str) and item.strip():
53
+ out.append(item.strip())
54
+ return tuple(out)
55
+ return ()
56
+
57
+
58
+ def acceptance_commands_for(pack_name: str, *, rc: object = None) -> tuple[str, ...]:
59
+ """Commands this workspace declares for *pack_name*.
60
+
61
+ Never raises: a malformed or missing ``.ariarc`` means "nothing declared",
62
+ which falls back to inference from the workspace — the behaviour before
63
+ any of this existed.
64
+ """
65
+ config = rc
66
+ if config is None:
67
+ try:
68
+ from aria_code.ariarc import get_ariarc
69
+
70
+ config = get_ariarc()
71
+ except Exception:
72
+ logger.debug("could not load .ariarc for acceptance commands", exc_info=True)
73
+ return ()
74
+
75
+ table = getattr(config, "acceptance", None)
76
+ if not isinstance(table, dict):
77
+ return ()
78
+ return _coerce(table.get(pack_name))
79
+
80
+
81
+ def default_acceptance_commands(*, rc: object = None) -> tuple[str, ...]:
82
+ """Commands this workspace declares for every turn, pack or not."""
83
+ return acceptance_commands_for(DEFAULT_KEY, rc=rc)
84
+
85
+
86
+ __all__ = [
87
+ "DEFAULT_KEY",
88
+ "acceptance_commands_for",
89
+ "default_acceptance_commands",
90
+ ]