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,721 @@
1
+ """Background subagent task system.
2
+
3
+ Allows the main agent to spawn independent sub-tasks that run concurrently.
4
+ Tasks are tracked in memory; code checkpoints and applied worktree changes are
5
+ persisted by the shared runtime store.
6
+
7
+ Tool functions exposed to the LLM:
8
+ spawn_task(prompt, context?) → {"task_id": "abc123", "status": "pending"}
9
+ task_status(task_id) → {"status": "running|done|failed", ...}
10
+ task_result(task_id) → {"result": "...", "success": bool}
11
+ task_list() → [{"task_id": ..., "status": ...}, ...]
12
+ task_cancel(task_id) → {"cancelled": bool}
13
+
14
+ Background execution is wired up in aria_cli.py via _subagent_runner().
15
+ If no runner is registered, spawn_task stores the task for manual execution.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import asyncio
21
+ import inspect
22
+ import json
23
+ import re
24
+ import time
25
+ import uuid
26
+ from dataclasses import dataclass, field
27
+ from pathlib import Path
28
+ from typing import Any, Callable, Dict, Optional
29
+
30
+ from .task_ledger import TaskLedger
31
+ from .task_context import ContextBundle, ContextError, load_context, tool_list_task_context, validate_refs
32
+ from .task_verification import capture_baseline, validate_checks, verify_checks
33
+ from .agent_profiles import PROFILES, get_profile, tool_list_agents
34
+
35
+ _TASKS: Dict[str, "SubagentTask"] = {}
36
+ _RUNNER: Optional[Callable] = None # set by aria_cli.py
37
+ _LEDGER: Optional[TaskLedger] = None
38
+
39
+
40
+ @dataclass
41
+ class SubagentTask:
42
+ task_id: str
43
+ prompt: str
44
+ context: str = ""
45
+ status: str = "pending" # pending | running | done | failed | cancelled
46
+ result: str = ""
47
+ error: str = ""
48
+ agent: str = "general"
49
+ success_criteria: str = ""
50
+ max_rounds: int = 30
51
+ timeout_seconds: int = 300
52
+ mode: str = "read-only"
53
+ isolation: str = "shared"
54
+ backend: str = "aria" # aria | claude | codex — which agent actually runs the task
55
+ workspace: str = ""
56
+ session_id: str = ""
57
+ branch: str = ""
58
+ diff_summary: str = ""
59
+ applied: bool = False
60
+ applied_paths: tuple[str, ...] = ()
61
+ created_at: float = field(default_factory=time.time)
62
+ completed_at: float = 0.0
63
+ handoff: dict[str, Any] = field(default_factory=dict)
64
+ context_refs: list[str] = field(default_factory=list)
65
+ context_sources: list[dict] = field(default_factory=list)
66
+ _context_block: str = field(default="", repr=False)
67
+ checks: list[dict] = field(default_factory=list)
68
+ evidence: list[dict] = field(default_factory=list)
69
+ evidence_truncated: bool = False
70
+ verification_baseline: dict = field(default_factory=dict)
71
+ verification: dict = field(default_factory=dict)
72
+ async_task: Optional[asyncio.Task] = field(default=None, repr=False, compare=False)
73
+ worktree_spec: Optional[Any] = field(default=None, repr=False, compare=False)
74
+
75
+ def age_str(self) -> str:
76
+ elapsed = time.time() - self.created_at
77
+ if elapsed < 60:
78
+ return f"{int(elapsed)}s"
79
+ if elapsed < 3600:
80
+ return f"{elapsed/60:.1f}m"
81
+ return f"{elapsed/3600:.1f}h"
82
+
83
+ def to_dict(self) -> dict:
84
+ return {
85
+ "agent": self.agent,
86
+ "context_refs": self.context_refs,
87
+ "context_sources": self.context_sources,
88
+ "success_criteria": self.success_criteria,
89
+ "max_rounds": self.max_rounds,
90
+ "timeout_seconds": self.timeout_seconds,
91
+ "task_id": self.task_id,
92
+ "status": self.status,
93
+ "prompt": self.prompt[:200] + ("…" if len(self.prompt) > 200 else ""),
94
+ "age": self.age_str(),
95
+ "mode": self.mode,
96
+ "isolation": self.isolation,
97
+ "backend": self.backend,
98
+ "workspace": self.workspace or None,
99
+ "branch": self.branch or None,
100
+ "applied": self.applied,
101
+ "handoff": self.handoff or None,
102
+ "verification": self.verification or None,
103
+ "verified": self.verification.get("verified"),
104
+ }
105
+
106
+ def snapshot(self) -> dict[str, Any]:
107
+ """Return the serializable task contract and latest outcome."""
108
+ return {
109
+ "agent": self.agent,
110
+ "context_refs": self.context_refs,
111
+ "context_sources": self.context_sources,
112
+ "success_criteria": self.success_criteria,
113
+ "max_rounds": self.max_rounds,
114
+ "timeout_seconds": self.timeout_seconds,
115
+ "task_id": self.task_id, "prompt": self.prompt, "context": self.context,
116
+ "status": self.status, "result": self.result, "error": self.error,
117
+ "mode": self.mode, "isolation": self.isolation, "backend": self.backend,
118
+ "workspace": self.workspace, "session_id": self.session_id,
119
+ "branch": self.branch, "diff_summary": self.diff_summary,
120
+ "applied": self.applied, "applied_paths": list(self.applied_paths),
121
+ "created_at": self.created_at, "completed_at": self.completed_at,
122
+ "handoff": self.handoff,
123
+ "checks": self.checks, "evidence": self.evidence,
124
+ "evidence_truncated": self.evidence_truncated,
125
+ "verification_baseline": self.verification_baseline,
126
+ "verification": self.verification,
127
+ }
128
+
129
+
130
+ def _ledger() -> TaskLedger:
131
+ global _LEDGER
132
+ if _LEDGER is None:
133
+ _LEDGER = TaskLedger()
134
+ return _LEDGER
135
+
136
+
137
+ def _persist(task: SubagentTask) -> None:
138
+ """A ledger write must never make a live task fail."""
139
+ try:
140
+ _ledger().upsert(task.snapshot())
141
+ except Exception:
142
+ pass
143
+
144
+
145
+ def restore_tasks() -> int:
146
+ """Restore prior task records after a CLI restart.
147
+
148
+ A running coroutine cannot safely be resumed, so it is retained as an
149
+ explicit interrupted task rather than silently disappearing.
150
+ """
151
+ restored = 0
152
+ interrupted = []
153
+ for record in _ledger().restore():
154
+ task_id = str(record.get("task_id") or "").strip()
155
+ if not task_id or task_id in _TASKS:
156
+ continue
157
+ saved_status = str(record.get("status") or "pending")
158
+ status = saved_status
159
+ error = str(record.get("error") or "")
160
+ if status == "running":
161
+ status = "interrupted"
162
+ error = "CLI restarted before this task completed; rerun or delegate it again."
163
+ elif status == "pending":
164
+ # Nothing picks up a queued task later: it was spawned with no
165
+ # runner registered, and the process that queued it is gone. Left
166
+ # as pending it never changes, and these piled up by the thousand.
167
+ status = "interrupted"
168
+ error = "Queued without a runner and never started; rerun or delegate it again."
169
+ task = SubagentTask(
170
+ task_id=task_id, prompt=str(record.get("prompt") or ""),
171
+ agent=str(record.get("agent") or "general"),
172
+ success_criteria=str(record.get("success_criteria") or ""),
173
+ max_rounds=int(record.get("max_rounds") or 30),
174
+ timeout_seconds=int(record.get("timeout_seconds") or 300),
175
+ context=str(record.get("context") or ""), status=status,
176
+ context_refs=list(record.get("context_refs") or []),
177
+ context_sources=list(record.get("context_sources") or []),
178
+ result=str(record.get("result") or ""), error=error,
179
+ mode=str(record.get("mode") or "read-only"),
180
+ isolation=str(record.get("isolation") or "shared"),
181
+ backend=str(record.get("backend") or "aria"),
182
+ workspace=str(record.get("workspace") or ""),
183
+ session_id=str(record.get("session_id") or ""),
184
+ branch=str(record.get("branch") or ""),
185
+ diff_summary=str(record.get("diff_summary") or ""),
186
+ applied=bool(record.get("applied")),
187
+ applied_paths=tuple(record.get("applied_paths") or ()),
188
+ created_at=float(record.get("created_at") or time.time()),
189
+ completed_at=float(record.get("completed_at") or 0.0),
190
+ handoff=dict(record.get("handoff") or {}),
191
+ checks=list(record.get("checks") or []),
192
+ evidence=list(record.get("evidence") or [])[:256],
193
+ evidence_truncated=bool(record.get("evidence_truncated")),
194
+ verification_baseline=dict(record.get("verification_baseline") or {}),
195
+ verification={**dict(record.get("verification") or {}), "status": "stale", "verified": None},
196
+ )
197
+ _TASKS[task_id] = task
198
+ if status != saved_status:
199
+ interrupted.append(task.snapshot())
200
+ restored += 1
201
+ if interrupted:
202
+ # Completed/queued records have not changed. Persist all interrupted
203
+ # records together; per-task upserts made restoration quadratic.
204
+ try:
205
+ _ledger().upsert_many(interrupted)
206
+ except Exception:
207
+ pass # Persistence failure must not discard restored live state.
208
+ return restored
209
+
210
+
211
+ def register_runner(runner: Callable) -> None:
212
+ """Register the async runner function from aria_cli.py."""
213
+ global _RUNNER
214
+ _RUNNER = runner
215
+
216
+
217
+ # ── Tool functions ─────────────────────────────────────────────────────────────
218
+
219
+ def tool_spawn_task(params: dict) -> dict:
220
+ """Spawn an independent background agent task."""
221
+ prompt = params.get("prompt", "")
222
+ context = params.get("context", "")
223
+ if not prompt:
224
+ return {"success": False, "error": "Missing 'prompt'"}
225
+
226
+ mode = str(params.get("mode") or "read-only").lower()
227
+ isolation = str(params.get("isolation") or "auto").lower()
228
+ backend = str(params.get("backend") or "aria").lower()
229
+ if mode not in {"read-only", "workspace-write"}:
230
+ return {"success": False, "error": "mode must be read-only or workspace-write"}
231
+ if isolation not in {"auto", "worktree", "shared"}:
232
+ return {"success": False, "error": "isolation must be auto, worktree, or shared"}
233
+ if backend not in {"aria", "claude", "codex"}:
234
+ return {"success": False, "error": "backend must be aria, claude, or codex"}
235
+ try:
236
+ profile = get_profile(str(params.get("agent") or "general"))
237
+ checks = validate_checks(params.get("checks", []))
238
+ max_rounds = params.get("max_rounds", profile.max_rounds)
239
+ timeout_seconds = params.get("timeout_seconds", profile.timeout_seconds)
240
+ if type(max_rounds) is not int or not 1 <= max_rounds <= profile.max_rounds:
241
+ raise ValueError(f"max_rounds must be 1–{profile.max_rounds}")
242
+ if type(timeout_seconds) is not int or not 1 <= timeout_seconds <= profile.timeout_seconds:
243
+ raise ValueError(f"timeout_seconds must be 1–{profile.timeout_seconds}")
244
+ if mode == "workspace-write" and not profile.writable:
245
+ raise ValueError(f"{profile.name} is a read-only role")
246
+ if mode == "workspace-write" and params.get("_parent_permission_mode") in {"read-only", "readonly", "read_only", "plan"}:
247
+ raise ValueError("A child cannot exceed the parent's read-only permissions")
248
+ if profile.name != "general" and backend != "aria":
249
+ raise ValueError("Restricted profiles currently require the aria backend")
250
+ if sum(t.status in {"pending", "running"} for t in _TASKS.values()) >= 8:
251
+ raise ValueError("Active task limit reached (8); wait or cancel a task first")
252
+ if profile.name != "general" and _RUNNER is None:
253
+ raise ValueError("No Aria runner is registered; this role cannot start")
254
+ except ValueError as exc:
255
+ return {"success": False, "error": str(exc)}
256
+ success_criteria = str(params.get("success_criteria") or "")
257
+ if len(str(prompt)) > 32000 or len(str(context)) > 32000 or len(success_criteria) > 4000:
258
+ return {"success": False, "error": "Task brief exceeds bounded context limits"}
259
+ if isolation == "auto":
260
+ isolation = "worktree" if mode == "workspace-write" else "shared"
261
+ if mode == "read-only" and isolation == "worktree":
262
+ isolation = "shared"
263
+ if mode == "workspace-write" and isolation == "shared":
264
+ return {
265
+ "success": False,
266
+ "error": "workspace-write tasks require worktree isolation",
267
+ }
268
+
269
+ workspace = str(params.get("_workspace") or params.get("_spawn_workspace") or Path.cwd())
270
+ session_id = str(params.get("_session_id") or "")
271
+ refs = params.get("context_refs", [])
272
+ try:
273
+ refs = validate_refs(refs)
274
+ if params.get("_task_context_enabled", True) is False:
275
+ if refs:
276
+ raise ContextError("Project task context is disabled by the host")
277
+ bundle = ContextBundle([])
278
+ else:
279
+ bundle = load_context(workspace, profile.name, session_id, refs)
280
+ if bundle.sources and backend != "aria":
281
+ raise ContextError("Scoped project task context currently requires the aria backend")
282
+ except ContextError as exc:
283
+ return {"success": False, "error": str(exc)}
284
+ task_id = uuid.uuid4().hex[:8]
285
+ task = SubagentTask(
286
+ task_id=task_id,
287
+ prompt=prompt,
288
+ context=context,
289
+ agent=profile.name, success_criteria=success_criteria,
290
+ context_refs=list(refs), context_sources=bundle.sources, _context_block=bundle.prompt_block,
291
+ checks=checks, verification={"status": "pending" if checks else "not_requested", "verified": None},
292
+ max_rounds=max_rounds, timeout_seconds=timeout_seconds,
293
+ mode=mode,
294
+ isolation=isolation,
295
+ backend=backend,
296
+ workspace=workspace,
297
+ session_id=session_id,
298
+ )
299
+ _TASKS[task_id] = task
300
+ _persist(task)
301
+
302
+ # An external backend (claude/codex) always has a runner (the CLI itself);
303
+ # the "aria" backend needs one registered via register_runner().
304
+ if backend != "aria" or _RUNNER is not None:
305
+ try:
306
+ try:
307
+ loop = asyncio.get_event_loop()
308
+ except RuntimeError:
309
+ loop = None
310
+ if loop is not None and loop.is_running():
311
+ task.async_task = asyncio.ensure_future(_run_background(task))
312
+ else:
313
+ asyncio.run(_run_background(task))
314
+ except Exception as exc:
315
+ task.status = "failed"
316
+ task.error = str(exc)
317
+ task.completed_at = time.time()
318
+ _persist(task)
319
+ else:
320
+ # No runner — task stays in "pending" for manual execution
321
+ task.status = "pending"
322
+
323
+ return {
324
+ "success": True,
325
+ "task_id": task_id,
326
+ "agent": task.agent,
327
+ "context_sources": task.context_sources,
328
+ "success_criteria": task.success_criteria,
329
+ "status": task.status,
330
+ "mode": task.mode,
331
+ "isolation": task.isolation,
332
+ "message": (
333
+ f"Task {task_id}: {task.status}. Use task_status/task_result to inspect the outcome."
334
+ ),
335
+ }
336
+
337
+
338
+ async def _run_background(task: SubagentTask) -> None:
339
+ try:
340
+ await asyncio.wait_for(_run_task(task), timeout=task.timeout_seconds)
341
+ except asyncio.TimeoutError:
342
+ task.status = "failed"
343
+ task.error = "Task execution deadline exceeded; inspect any partial artifacts before retrying."
344
+ task.completed_at = time.time()
345
+ _persist(task)
346
+
347
+
348
+ async def _run_task(task: SubagentTask) -> None:
349
+ task.status = "running"
350
+ _persist(task)
351
+ try:
352
+ if task.mode == "workspace-write" and task.isolation == "worktree":
353
+ from apps.cli.config_paths import resolve_config_dir
354
+ from .worktrees import WorktreeManager
355
+
356
+ manager = WorktreeManager(resolve_config_dir() / "worktrees")
357
+ spec = manager.create(task_id=task.task_id, workspace=task.workspace)
358
+ task.worktree_spec = spec
359
+ task.workspace = spec.path
360
+ task.branch = spec.branch
361
+
362
+ task.verification_baseline = capture_baseline(task.workspace, task.checks)
363
+ full_prompt = task.prompt
364
+ if task._context_block:
365
+ full_prompt = f"{task._context_block}\n\n[Delegated user task]\n{full_prompt}"
366
+ if task.context:
367
+ full_prompt = f"{task.context}\n\n{task.prompt}"
368
+ execution_contract = (
369
+ "[Subagent execution contract]\n"
370
+ f"Mode: {task.mode}\n"
371
+ f"Workspace: {task.workspace}\n"
372
+ f"Isolation: {task.isolation}\n"
373
+ "Keep every file and command operation inside this workspace. "
374
+ "Do not spawn another subagent or push changes. End with a structured "
375
+ "handoff: FINDINGS: ...; CHANGED_FILES: ...; VERIFICATION: ...; BLOCKERS: ..."
376
+ )
377
+ profile = get_profile(task.agent)
378
+ full_prompt = (f"{execution_contract}\nRole: {profile.name}\n{profile.instructions}\n"
379
+ f"Acceptance criteria: {task.success_criteria or 'Report observable evidence and unresolved blockers.'}\n"
380
+ f"Declared predicates (not permission grants): {json.dumps(task.checks, ensure_ascii=False)}\n\n{full_prompt}")
381
+ if task.backend != "aria":
382
+ from external_agent_runner import RUNNERS
383
+
384
+ result_text = await RUNNERS[task.backend](full_prompt, cwd=task.workspace or None)
385
+ else:
386
+ runner_parameters = inspect.signature(_RUNNER).parameters
387
+ if len(runner_parameters) >= 2:
388
+ result_text = await _RUNNER(full_prompt, task)
389
+ else:
390
+ result_text = await _RUNNER(full_prompt)
391
+ task.result = result_text or ""
392
+ task.handoff = _extract_handoff(task.result)
393
+ task.status = "done"
394
+ _refresh_verification(task)
395
+ if task.worktree_spec is not None:
396
+ from .worktrees import WorktreeManager
397
+ task.diff_summary = WorktreeManager.diff(task.worktree_spec)
398
+ except asyncio.CancelledError:
399
+ task.status = "cancelled"
400
+ raise
401
+ except Exception as exc:
402
+ task.error = str(exc)
403
+ task.status = "failed"
404
+ finally:
405
+ if task.status != "done":
406
+ task.verification = {"status": "execution_incomplete", "verified": False if task.checks else None}
407
+ task.completed_at = time.time()
408
+ _persist(task)
409
+
410
+
411
+ def _refresh_verification(task: SubagentTask) -> None:
412
+ try:
413
+ task.verification = verify_checks(task.workspace, task.checks, task.evidence,
414
+ task.verification_baseline, receipts_truncated=task.evidence_truncated)
415
+ except (ValueError, TypeError, OSError):
416
+ task.verification = {"status": "unavailable", "verified": False, "checked_at": time.time()}
417
+
418
+
419
+ def _extract_handoff(result: str) -> dict[str, str]:
420
+ """Extract a compact handoff when the agent supplied the task contract."""
421
+ text = str(result or "")
422
+ # Models commonly return Markdown headings or title case even when the
423
+ # contract asks for uppercase labels. Preserve the reported text; parsing
424
+ # it is not independent verification of the claims.
425
+ pattern = r"(?im)(?:^|[;\n])[ \t]*(?:\*\*)?(FINDINGS|CHANGED[ _]FILES|VERIFICATION|BLOCKERS)[ \t]*:[ \t]*(?:\*\*)?"
426
+ matches = list(re.finditer(pattern, text))
427
+ out: dict[str, str] = {}
428
+ for index, match in enumerate(matches):
429
+ end = matches[index + 1].start() if index + 1 < len(matches) else len(text)
430
+ key = match.group(1).lower().replace(" ", "_")
431
+ out[key] = text[match.end():end].strip().strip(";")
432
+ return out
433
+
434
+
435
+ def tool_task_status(params: dict) -> dict:
436
+ """Check the status of a background task."""
437
+ task_id = params.get("task_id", "")
438
+ if not task_id:
439
+ return {"success": False, "error": "Missing 'task_id'"}
440
+ task = _TASKS.get(task_id)
441
+ if not task:
442
+ return {"success": False, "error": f"Task '{task_id}' not found"}
443
+ return {
444
+ "success": True,
445
+ "task_id": task_id,
446
+ "agent": task.agent,
447
+ "context_sources": task.context_sources,
448
+ "success_criteria": task.success_criteria,
449
+ "status": task.status,
450
+ "verified": task.verification.get("verified"),
451
+ "verification": task.verification or None,
452
+ "age": task.age_str(),
453
+ "prompt_preview": task.prompt[:100],
454
+ "error": task.error or None,
455
+ "mode": task.mode,
456
+ "isolation": task.isolation,
457
+ "workspace": task.workspace or None,
458
+ "branch": task.branch or None,
459
+ }
460
+
461
+
462
+ def tool_task_result(params: dict) -> dict:
463
+ """Retrieve the result of a completed background task."""
464
+ task_id = params.get("task_id", "")
465
+ if not task_id:
466
+ return {"success": False, "error": "Missing 'task_id'"}
467
+ task = _TASKS.get(task_id)
468
+ if not task:
469
+ return {"success": False, "error": f"Task '{task_id}' not found"}
470
+ if task.status == "running":
471
+ return {"success": False, "error": "Task is still running", "status": "running"}
472
+ if task.status == "failed":
473
+ return {"success": False, "error": task.error, "status": "failed"}
474
+ if task.status in ("pending", "cancelled", "interrupted"):
475
+ return {"success": False, "error": f"Task status is '{task.status}'", "status": task.status}
476
+ # Re-read declared artifacts on retrieval; a prior green must not survive
477
+ # deletion or modification of the artifact. Command receipts remain historical.
478
+ _refresh_verification(task)
479
+ _persist(task)
480
+ return {
481
+ "success": task.verification.get("verified") is not False,
482
+ "error": "Declared acceptance checks did not pass" if task.verification.get("verified") is False else None,
483
+ "task_id": task_id,
484
+ "agent": task.agent,
485
+ "context_sources": task.context_sources,
486
+ "success_criteria": task.success_criteria,
487
+ "status": task.status,
488
+ "verified": task.verification.get("verified"),
489
+ "verification": task.verification,
490
+ "result": task.result,
491
+ "age": task.age_str(),
492
+ "workspace": task.workspace or None,
493
+ "branch": task.branch or None,
494
+ "diff_summary": task.diff_summary or None,
495
+ "applied": task.applied,
496
+ "applied_paths": list(task.applied_paths),
497
+ "handoff": task.handoff or None,
498
+ }
499
+
500
+
501
+ def tool_task_list(params: dict) -> dict:
502
+ """List all tracked background tasks."""
503
+ tasks = [t.to_dict() for t in _TASKS.values()]
504
+ if not tasks:
505
+ return {"success": True, "tasks": [], "message": "No active tasks."}
506
+ by_status: dict = {}
507
+ for t in tasks:
508
+ s = t["status"]
509
+ by_status.setdefault(s, []).append(t)
510
+ return {
511
+ "success": True,
512
+ "total": len(tasks),
513
+ "tasks": tasks,
514
+ "summary": {s: len(v) for s, v in by_status.items()},
515
+ }
516
+
517
+
518
+ def clear_finished_tasks() -> int:
519
+ """Forget every task that can no longer change, in memory and on disk."""
520
+ finished = [
521
+ task_id for task_id, task in _TASKS.items()
522
+ if task.status in ("done", "failed", "cancelled", "interrupted")
523
+ ]
524
+ for task_id in finished:
525
+ del _TASKS[task_id]
526
+ try:
527
+ _ledger().remove_many(finished)
528
+ except Exception:
529
+ pass
530
+ return len(finished)
531
+
532
+
533
+ def tool_task_cancel(params: dict) -> dict:
534
+ """Cancel a pending or running background task."""
535
+ task_id = params.get("task_id", "")
536
+ if not task_id:
537
+ return {"success": False, "error": "Missing 'task_id'"}
538
+ task = _TASKS.get(task_id)
539
+ if not task:
540
+ return {"success": False, "error": f"Task '{task_id}' not found"}
541
+ if task.status in ("done", "failed", "cancelled"):
542
+ return {"success": False, "error": f"Task already in terminal state: {task.status}"}
543
+ task.status = "cancelled"
544
+ task.completed_at = time.time()
545
+ if task.async_task is not None and not task.async_task.done():
546
+ task.async_task.cancel()
547
+ _persist(task)
548
+ return {"success": True, "task_id": task_id, "cancelled": True}
549
+
550
+
551
+ def apply_task_worktree(task_id: str, *, cleanup: bool = True) -> dict:
552
+ """Apply a completed isolated task to the original clean workspace."""
553
+ task = _TASKS.get(task_id)
554
+ if not task:
555
+ return {"success": False, "error": f"Task '{task_id}' not found"}
556
+ if task.status != "done":
557
+ return {"success": False, "error": f"Task status is '{task.status}', expected 'done'"}
558
+ if task.applied:
559
+ return {"success": False, "error": "Task changes were already applied"}
560
+ if task.worktree_spec is None:
561
+ return {"success": False, "error": "Task has no isolated worktree changes"}
562
+ try:
563
+ from .worktrees import WorktreeManager
564
+ from apps.cli.config_paths import resolve_config_dir
565
+
566
+ manager = WorktreeManager(resolve_config_dir() / "worktrees")
567
+ tracked, untracked = manager.changed_paths(task.worktree_spec)
568
+ target_root = Path(task.worktree_spec.repository)
569
+ snapshots = {}
570
+ for relative in (*tracked, *untracked):
571
+ target = target_root / relative
572
+ if target.is_file():
573
+ try:
574
+ content = target.read_text(encoding="utf-8")
575
+ except UnicodeDecodeError:
576
+ continue
577
+ snapshots[relative] = (
578
+ True,
579
+ content,
580
+ target.stat().st_mode & 0o777,
581
+ )
582
+ elif not target.exists():
583
+ snapshots[relative] = (False, "", None)
584
+ result = manager.apply(task.worktree_spec)
585
+ checkpoint_errors = []
586
+ try:
587
+ from .checkpoints import CheckpointStore
588
+ checkpoint_store = CheckpointStore()
589
+ for relative in result.paths:
590
+ target = target_root / relative
591
+ before = snapshots.get(relative)
592
+ if before is None or not target.is_file():
593
+ continue
594
+ try:
595
+ after_content = target.read_text(encoding="utf-8")
596
+ except UnicodeDecodeError:
597
+ continue
598
+ checkpoint_store.record_change(
599
+ path=target,
600
+ before_content=before[1],
601
+ after_content=after_content,
602
+ existed_before=before[0],
603
+ before_mode=before[2],
604
+ source="subagent_apply",
605
+ session_id=task.session_id,
606
+ label=f"task {task.task_id}: {relative}",
607
+ metadata={"task_id": task.task_id, "branch": task.branch},
608
+ )
609
+ except Exception as exc:
610
+ checkpoint_errors.append(str(exc))
611
+ task.applied = True
612
+ task.applied_paths = result.paths
613
+ _persist(task)
614
+ cleanup_error = ""
615
+ if cleanup:
616
+ try:
617
+ manager.remove(task.worktree_spec, force=True)
618
+ manager.delete_branch(task.worktree_spec, force=True)
619
+ except Exception as exc:
620
+ cleanup_error = str(exc)
621
+ return {
622
+ "success": True,
623
+ "task_id": task_id,
624
+ "paths": list(result.paths),
625
+ "cleanup_error": cleanup_error or None,
626
+ "checkpoint_errors": checkpoint_errors,
627
+ }
628
+ except Exception as exc:
629
+ return {"success": False, "error": str(exc)}
630
+
631
+
632
+ # ── Tool registry (added to LOCAL_TOOLS in aria_cli.py) ───────────────────────
633
+
634
+ SUBAGENT_TOOLS = {
635
+ "list_task_context": (tool_list_task_context, "Discover eligible project skill/memory metadata for a target role"),
636
+ "list_agents": (tool_list_agents, "Discover general-purpose task roles, limits and tool policies"),
637
+ "spawn_task": (tool_spawn_task, "Spawn a background sub-task; returns task_id"),
638
+ "task_status": (tool_task_status, "Check status of a background task by task_id"),
639
+ "task_result": (tool_task_result, "Retrieve result of a completed background task"),
640
+ "task_list": (tool_task_list, "List all active background tasks"),
641
+ "task_cancel": (tool_task_cancel, "Cancel a pending or running background task"),
642
+ }
643
+
644
+ SUBAGENT_SCHEMAS = [
645
+ {"name": "list_task_context", "description": "List project-local skill and memory IDs eligible for the planned target agent. Returns descriptions, not source contents; does not scan user/global memory. Select IDs through spawn_task.context_refs.", "parameters": {"type": "object", "properties": {"agent": {"type": "string", "enum": list(PROFILES)}}, "additionalProperties": False}},
646
+ {"name": "list_agents", "description": "Discover task roles for exploration, planning, research, implementation, review, data inspection and writing. Does not start tasks or connect services.", "parameters": {"type": "object", "properties": {}, "additionalProperties": False}},
647
+ {
648
+ "name": "spawn_task",
649
+ "description": "Delegate a bounded task to a role. Put executable acceptance predicates in the checks argument, not only in prompt/context. For example checks=[{kind:tool,tool:read_file,path:brief.md},{kind:artifact,path:brief.md,format:text,min_bytes:1}]. Retrieve task_result: verified=true covers these predicates, null means no checks, false means failure. A child saying VERIFIED is not machine evidence.",
650
+ "parameters": {
651
+ "type": "object",
652
+ "properties": {
653
+ "agent": {"type": "string", "enum": list(PROFILES), "description": "Use explorer for sources, planner for plans, researcher for sourced research, implementer for changes, reviewer for independent review, data_analyst for datasets, writer for documents. general is the fallback. Specialized roles use aria."},
654
+ "context_refs": {"type": "array", "items": {"type": "string"}, "maxItems": 8, "description": "Project skill/memory IDs from list_task_context for this agent. Do not pass paths, global memories or session IDs. Only project-declared auto entries load without explicit IDs."},
655
+ "checks": {"type": "array", "maxItems": 16, "items": {"type": "object", "properties": {"kind": {"type": "string", "enum": ["artifact", "tool", "command"]}, "path": {"type": "string"}, "format": {"type": "string", "enum": ["binary", "text", "json", "csv"]}, "min_bytes": {"type": "integer", "minimum": 0, "maximum": 1048576}, "min_rows": {"type": "integer", "minimum": 0, "maximum": 10000}, "required_keys": {"type": "array", "items": {"type": "string"}, "maxItems": 32}, "contains": {"type": "string", "maxLength": 256}, "sha256": {"type": "string"}, "changed": {"type": "boolean"}, "tool": {"type": "string"}, "command": {"type": "string"}, "cwd": {"type": "string"}}, "required": ["kind"], "additionalProperties": False}, "description": "Declared acceptance predicates: artifact(path, optional format/min_bytes/required_keys/min_rows/contains/sha256/changed), tool(tool, optional path), command(command, optional cwd). Paths are workspace-relative. Commands are matched to actual executor receipts, never run by this verifier. Checks verify only their predicates, not every aspect of the user goal."},
656
+ "success_criteria": {"type": "string", "description": "Observable acceptance conditions; a completion message alone is not evidence."},
657
+ "max_rounds": {"type": "integer", "minimum": 1, "maximum": 30},
658
+ "timeout_seconds": {"type": "integer", "minimum": 1, "maximum": 300},
659
+ "prompt": {"type": "string", "description": "The task for the sub-agent to perform"},
660
+ "context": {"type": "string", "description": "Optional background context to inject into the sub-agent's system prompt"},
661
+ "mode": {
662
+ "type": "string",
663
+ "enum": ["read-only", "workspace-write"],
664
+ "description": "Use workspace-write only for requested file changes or checks requiring writes. A draft returned in chat is read-only. Default: read-only.",
665
+ },
666
+ "isolation": {
667
+ "type": "string",
668
+ "enum": ["auto", "worktree", "shared"],
669
+ "description": "auto uses a Git worktree for write tasks; shared is only valid for read-only tasks.",
670
+ },
671
+ "backend": {
672
+ "type": "string",
673
+ "enum": ["aria", "claude", "codex"],
674
+ "description": "Which agent actually runs the task. 'aria' (default) uses this session's own loop. 'claude'/'codex' shell out to the Claude Code or Codex CLI (must be installed and on PATH) headlessly — use for coding tasks you want a different coding agent to own.",
675
+ },
676
+ },
677
+ "required": ["prompt"],
678
+ },
679
+ },
680
+ {
681
+ "name": "task_status",
682
+ "description": "Check the status of a background task spawned with spawn_task.",
683
+ "parameters": {
684
+ "type": "object",
685
+ "properties": {
686
+ "task_id": {"type": "string", "description": "The task_id returned by spawn_task"},
687
+ },
688
+ "required": ["task_id"],
689
+ },
690
+ },
691
+ {
692
+ "name": "task_result",
693
+ "description": "Retrieve the full result text of a completed background task.",
694
+ "parameters": {
695
+ "type": "object",
696
+ "properties": {
697
+ "task_id": {"type": "string", "description": "The task_id returned by spawn_task"},
698
+ },
699
+ "required": ["task_id"],
700
+ },
701
+ },
702
+ {
703
+ "name": "task_list",
704
+ "description": "List all active and completed background tasks with their statuses.",
705
+ "parameters": {
706
+ "type": "object",
707
+ "properties": {},
708
+ },
709
+ },
710
+ {
711
+ "name": "task_cancel",
712
+ "description": "Cancel a pending or running background task.",
713
+ "parameters": {
714
+ "type": "object",
715
+ "properties": {
716
+ "task_id": {"type": "string", "description": "The task_id to cancel"},
717
+ },
718
+ "required": ["task_id"],
719
+ },
720
+ },
721
+ ]