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,422 @@
1
+ """
2
+ runtime/self_healing.py — Lightweight Static Pre-flight & Traceback Patch Self-Healing Engine
3
+ ===========================================================================================
4
+ 1. Fast Static Syntax Compilation (<10ms via compile / py_compile)
5
+ 2. Sandbox Dry-run Execution
6
+ 3. Traceback Parsing (Error Type, Offending Line, Context)
7
+ 4. Surgical Differential Patch Repair (Never rewrites entire file)
8
+ 5. Metric Extraction & Deliverable Packaging (No terminal log flooding)
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import ast
14
+ import json
15
+ import logging
16
+ import os
17
+ import pathlib
18
+ import re
19
+ import subprocess
20
+ import sys
21
+ from dataclasses import dataclass, field
22
+ from typing import Any, Callable, Dict, List, Optional, Tuple
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ @dataclass
28
+ class TracebackInfo:
29
+ file_path: str
30
+ line_number: int
31
+ error_type: str
32
+ error_message: str
33
+ code_snippet: str
34
+ full_traceback: str
35
+
36
+
37
+ @dataclass
38
+ class SelfHealingResult:
39
+ success: bool
40
+ retries_used: int
41
+ final_output: str
42
+ error: Optional[str] = None
43
+ metrics: Dict[str, Any] = field(default_factory=dict)
44
+ artifact_paths: List[str] = field(default_factory=list)
45
+ patches_applied: List[Dict[str, Any]] = field(default_factory=list)
46
+
47
+ def to_dict(self) -> Dict[str, Any]:
48
+ return {
49
+ "success": self.success,
50
+ "retries_used": self.retries_used,
51
+ "error": self.error,
52
+ "metrics": self.metrics,
53
+ "artifact_paths": self.artifact_paths,
54
+ "patches_applied": self.patches_applied,
55
+ }
56
+
57
+
58
+ class SelfHealingEngine:
59
+ """
60
+ Automated execution, diagnostics, and patch self-healing engine.
61
+ """
62
+
63
+ def __init__(
64
+ self,
65
+ python_executable: str = sys.executable,
66
+ max_retries: int = 3,
67
+ llm_fixer: Optional[Callable[[TracebackInfo, str], Any]] = None,
68
+ ) -> None:
69
+ self.python_executable = python_executable
70
+ self.max_retries = max_retries
71
+ self.llm_fixer = llm_fixer
72
+
73
+ def verify_syntax(self, file_path: pathlib.Path) -> Tuple[bool, Optional[str], Optional[int]]:
74
+ """
75
+ Fast static syntax check using AST compilation (<10ms).
76
+ """
77
+ try:
78
+ content = file_path.read_text(encoding="utf-8")
79
+ compile(content, str(file_path), "exec")
80
+ return True, None, None
81
+ except SyntaxError as exc:
82
+ line = exc.lineno or 1
83
+ msg = f"SyntaxError: {exc.msg} at line {line}"
84
+ return False, msg, line
85
+ except Exception as exc:
86
+ return False, str(exc), None
87
+
88
+ def run_sandbox_execution(
89
+ self,
90
+ file_path: pathlib.Path,
91
+ timeout: float = 30.0,
92
+ cwd: Optional[pathlib.Path] = None,
93
+ ) -> Tuple[int, str, str]:
94
+ """
95
+ Run the Python script in a dry-run subprocess sandbox.
96
+ """
97
+ work_dir = cwd or file_path.parent
98
+ env = dict(os.environ)
99
+ env["PYTHONPATH"] = f"{work_dir}:{env.get('PYTHONPATH', '')}"
100
+
101
+ try:
102
+ proc = subprocess.run(
103
+ [self.python_executable, str(file_path)],
104
+ cwd=str(work_dir),
105
+ capture_output=True,
106
+ text=True,
107
+ timeout=timeout,
108
+ env=env,
109
+ )
110
+ return proc.returncode, proc.stdout, proc.stderr
111
+ except subprocess.TimeoutExpired:
112
+ return -1, "", f"Execution timed out after {timeout}s"
113
+ except Exception as exc:
114
+ return -1, "", f"Failed to execute script: {exc}"
115
+
116
+ def parse_traceback(self, stderr: str, target_file: pathlib.Path) -> Optional[TracebackInfo]:
117
+ """
118
+ Extract exact error line, error type, and snippet from python stderr.
119
+ """
120
+ if not stderr:
121
+ return None
122
+
123
+ # Look for standard Python traceback lines: File "path", line X, in Y
124
+ lines = stderr.strip().splitlines()
125
+ target_name = target_file.name
126
+
127
+ target_line = None
128
+ snippet = ""
129
+ error_type = "UnknownError"
130
+ error_msg = ""
131
+
132
+ for i, line in enumerate(lines):
133
+ if "File " in line and target_name in line:
134
+ m = re.search(r'line (\d+)', line)
135
+ if m:
136
+ target_line = int(m.group(1))
137
+ if i + 1 < len(lines) and not lines[i + 1].strip().startswith("File "):
138
+ snippet = lines[i + 1].strip()
139
+
140
+ # The last non-empty line usually contains ErrorType: message
141
+ for line in reversed(lines):
142
+ line_str = line.strip()
143
+ if ":" in line_str and not line_str.startswith("File "):
144
+ parts = line_str.split(":", 1)
145
+ error_type = parts[0].strip()
146
+ error_msg = parts[1].strip()
147
+ break
148
+
149
+ if target_line is None:
150
+ # Check if any line number is mentioned
151
+ m = re.search(r'line (\d+)', stderr)
152
+ if m:
153
+ target_line = int(m.group(1))
154
+
155
+ if target_line is None:
156
+ target_line = 1
157
+
158
+ return TracebackInfo(
159
+ file_path=str(target_file),
160
+ line_number=target_line,
161
+ error_type=error_type,
162
+ error_message=error_msg,
163
+ code_snippet=snippet,
164
+ full_traceback=stderr,
165
+ )
166
+
167
+ def apply_patch(
168
+ self,
169
+ file_path: pathlib.Path,
170
+ target_line: int,
171
+ replacement_code: str,
172
+ context_radius: int = 0,
173
+ ) -> bool:
174
+ """
175
+ Surgically edit the target file at target_line (1-indexed).
176
+ Never rewrites the entire file.
177
+ """
178
+ try:
179
+ content = file_path.read_text(encoding="utf-8")
180
+ lines = content.splitlines(keepends=True)
181
+
182
+ if not (1 <= target_line <= len(lines) + 1):
183
+ logger.error(f"Target line {target_line} out of range for {file_path}")
184
+ return False
185
+
186
+ start_idx = max(0, target_line - 1 - context_radius)
187
+ end_idx = min(len(lines), target_line + context_radius)
188
+
189
+ # Format replacement lines
190
+ if not replacement_code.endswith("\n"):
191
+ replacement_code += "\n"
192
+
193
+ # Replace slice
194
+ lines[start_idx:end_idx] = [replacement_code]
195
+ file_path.write_text("".join(lines), encoding="utf-8")
196
+ return True
197
+ except Exception as exc:
198
+ logger.error(f"Failed to apply patch on {file_path}: {exc}")
199
+ return False
200
+
201
+ def generate_heuristic_fix(
202
+ self,
203
+ tb: TracebackInfo,
204
+ file_content: str,
205
+ ) -> Optional[Tuple[int, str, int]]:
206
+ """
207
+ Rule-based heuristic patch generator for common quant/python runtime issues.
208
+ Returns: (target_line, replacement_content, context_radius)
209
+ """
210
+ lines = file_content.splitlines()
211
+ if not (1 <= tb.line_number <= len(lines)):
212
+ return None
213
+
214
+ offending_line = lines[tb.line_number - 1]
215
+ indent = len(offending_line) - len(offending_line.lstrip())
216
+ indent_str = " " * indent
217
+
218
+ # Case 1: ZeroDivisionError (e.g. sharpe ratio or return calculation)
219
+ if "ZeroDivisionError" in tb.error_type or "division by zero" in tb.error_message:
220
+ if "/" in offending_line:
221
+ # Add safe division
222
+ fixed = offending_line.replace("/", " / max(1e-9, ")
223
+ fixed += ")"
224
+ return tb.line_number, fixed, 0
225
+
226
+ # Case 2: Column KeyError (e.g. 'Adj Close' vs 'Close' vs 'close')
227
+ if "KeyError" in tb.error_type:
228
+ col_match = re.search(r"['\"]([^'\"]+)['\"]", tb.error_message)
229
+ if col_match:
230
+ missing_col = col_match.group(1)
231
+ # Replace df['missing'] with df.get(missing, df.get('close', df.get('Close', 0)))
232
+ pattern = rf"\[['\"]{re.escape(missing_col)}['\"]\]"
233
+ replacement = f".get('{missing_col.lower()}', df.get('{missing_col}', df.get('close', df.get('Close'))))"
234
+ if re.search(pattern, offending_line):
235
+ fixed = re.sub(pattern, replacement, offending_line)
236
+ return tb.line_number, fixed, 0
237
+
238
+ # Case 3: Missing Import (NameError)
239
+ if "NameError" in tb.error_type:
240
+ m = re.search(r"name ['\"]([^'\"]+)['\"] is not defined", tb.error_message)
241
+ if m:
242
+ missing_name = m.group(1)
243
+ if missing_name in {"np", "numpy"}:
244
+ return 1, "import numpy as np\n" + lines[0], 0
245
+ elif missing_name in {"pd", "pandas"}:
246
+ return 1, "import pandas as pd\n" + lines[0], 0
247
+ elif missing_name in {"math", "json", "os", "sys"}:
248
+ return 1, f"import {missing_name}\n" + lines[0], 0
249
+
250
+ # Case 4: IndexError on empty dataframe/array
251
+ if "IndexError" in tb.error_type:
252
+ fixed = f"{indent_str}if len(df) > 0 and len(data) > 0:\n{indent_str} {offending_line.strip()}"
253
+ return tb.line_number, fixed, 0
254
+
255
+ # Case 5: SyntaxError near line
256
+ if "SyntaxError" in tb.error_type:
257
+ # Clean common syntax typos (e.g. mismatched parentheses or quotes)
258
+ stripped = offending_line.strip()
259
+ if stripped.count("(") > stripped.count(")"):
260
+ fixed = offending_line + ")" * (stripped.count("(") - stripped.count(")"))
261
+ return tb.line_number, fixed, 0
262
+
263
+ return None
264
+
265
+ async def execute_and_heal(
266
+ self,
267
+ file_path: pathlib.Path,
268
+ timeout: float = 30.0,
269
+ ) -> SelfHealingResult:
270
+ """
271
+ Full pre-flight verification, execution, and multi-round patch self-healing loop.
272
+ """
273
+ file_path = file_path.resolve()
274
+ patches: List[Dict[str, Any]] = []
275
+
276
+ for attempt in range(self.max_retries + 1):
277
+ # 1. Pre-flight Static Syntax Check
278
+ valid_syntax, syn_err, syn_line = self.verify_syntax(file_path)
279
+ if not valid_syntax:
280
+ if attempt >= self.max_retries:
281
+ return SelfHealingResult(
282
+ success=False,
283
+ retries_used=attempt,
284
+ final_output="",
285
+ error=f"Syntax pre-flight check failed: {syn_err}",
286
+ patches_applied=patches,
287
+ )
288
+ # Attempt syntax fix
289
+ content = file_path.read_text(encoding="utf-8")
290
+ tb_synth = TracebackInfo(
291
+ file_path=str(file_path),
292
+ line_number=syn_line or 1,
293
+ error_type="SyntaxError",
294
+ error_message=syn_err or "SyntaxError",
295
+ code_snippet="",
296
+ full_traceback=syn_err or "",
297
+ )
298
+ fix = self.generate_heuristic_fix(tb_synth, content)
299
+ if fix:
300
+ t_line, rep, rad = fix
301
+ self.apply_patch(file_path, t_line, rep, rad)
302
+ patches.append({"round": attempt + 1, "type": "syntax_fix", "line": t_line})
303
+ continue
304
+
305
+ # 2. Dry-Run Execution
306
+ ret_code, stdout, stderr = self.run_sandbox_execution(file_path, timeout=timeout)
307
+
308
+ if ret_code == 0:
309
+ # Success! Extract metrics and artifacts
310
+ metrics, artifacts = self._extract_results(file_path, stdout)
311
+ return SelfHealingResult(
312
+ success=True,
313
+ retries_used=attempt,
314
+ final_output=stdout,
315
+ metrics=metrics,
316
+ artifact_paths=artifacts,
317
+ patches_applied=patches,
318
+ )
319
+
320
+ # Failure occurred: inspect traceback
321
+ if attempt >= self.max_retries:
322
+ return SelfHealingResult(
323
+ success=False,
324
+ retries_used=attempt,
325
+ final_output=stdout,
326
+ error=f"Execution failed after {attempt} retries: {stderr[:300]}",
327
+ patches_applied=patches,
328
+ )
329
+
330
+ tb = self.parse_traceback(stderr, file_path)
331
+ if not tb:
332
+ return SelfHealingResult(
333
+ success=False,
334
+ retries_used=attempt,
335
+ final_output=stdout,
336
+ error=f"Execution failed with no traceback: {stderr[:300]}",
337
+ patches_applied=patches,
338
+ )
339
+
340
+ content = file_path.read_text(encoding="utf-8")
341
+ fix = None
342
+
343
+ # Try LLM fixer if available
344
+ if self.llm_fixer:
345
+ try:
346
+ fix = await self.llm_fixer(tb, content)
347
+ except Exception as exc:
348
+ logger.debug(f"LLM fixer failed: {exc}")
349
+
350
+ # Fallback to heuristic fixer
351
+ if not fix:
352
+ fix = self.generate_heuristic_fix(tb, content)
353
+
354
+ if fix:
355
+ t_line, rep, rad = fix
356
+ self.apply_patch(file_path, t_line, rep, rad)
357
+ patches.append({
358
+ "round": attempt + 1,
359
+ "error_type": tb.error_type,
360
+ "line": t_line,
361
+ "message": tb.error_message,
362
+ })
363
+ else:
364
+ # Could not determine patch
365
+ return SelfHealingResult(
366
+ success=False,
367
+ retries_used=attempt,
368
+ final_output=stdout,
369
+ error=f"Unresolvable {tb.error_type} at line {tb.line_number}: {tb.error_message}",
370
+ patches_applied=patches,
371
+ )
372
+
373
+ return SelfHealingResult(
374
+ success=False,
375
+ retries_used=self.max_retries,
376
+ final_output="",
377
+ error="Exceeded max healing retries",
378
+ patches_applied=patches,
379
+ )
380
+
381
+ def _extract_results(self, file_path: pathlib.Path, stdout: str) -> Tuple[Dict[str, Any], List[str]]:
382
+ """
383
+ Extract backtest metrics and generated files from output.
384
+ """
385
+ metrics: Dict[str, Any] = {}
386
+ artifacts: List[str] = [str(file_path)]
387
+
388
+ # 1. Look for companion metrics JSON file (e.g. strategy_nvda_metrics.json)
389
+ json_candidate = file_path.with_name(f"{file_path.stem}_metrics.json")
390
+ if json_candidate.exists():
391
+ try:
392
+ metrics = json.loads(json_candidate.read_text(encoding="utf-8"))
393
+ artifacts.append(str(json_candidate))
394
+ except Exception:
395
+ pass
396
+
397
+ # 2. Look for JSON in stdout lines or blocks
398
+ if not metrics and stdout:
399
+ for line in stdout.splitlines():
400
+ line_str = line.strip()
401
+ if line_str.startswith("{") and line_str.endswith("}"):
402
+ try:
403
+ parsed = json.loads(line_str)
404
+ if isinstance(parsed, dict):
405
+ metrics = parsed
406
+ break
407
+ except Exception:
408
+ pass
409
+ if not metrics and "{" in stdout and "}" in stdout:
410
+ try:
411
+ m = re.search(r"(\{.*\"[a-zA-Z0-9_-]+\"\s*:.*\})", stdout, re.DOTALL)
412
+ if m:
413
+ metrics = json.loads(m.group(1))
414
+ except Exception:
415
+ pass
416
+
417
+ # 3. Look for generated images or plots in the same folder
418
+ plot_candidate = file_path.with_name(f"{file_path.stem}_backtest.png")
419
+ if plot_candidate.exists():
420
+ artifacts.append(str(plot_candidate))
421
+
422
+ return metrics, artifacts
@@ -0,0 +1,171 @@
1
+ """Semantic diff — which definitions a change touched, not which lines.
2
+
3
+ "+43 -18 in session.py" says how much changed. What a reviewer reads first is
4
+ *what*: ``refresh_session()`` was modified, ``SessionManager`` added,
5
+ ``legacy_refresh()`` removed. This module works that out per file, in any
6
+ language ``repo_map`` can parse (Python by AST, the rest by pattern):
7
+
8
+ 1. Read the file as it is now.
9
+ 2. Undo this turn's diffs, newest first, to get it as it was. A diff that does
10
+ not apply — the file was changed some other way in between — means no
11
+ answer for that file rather than a wrong one.
12
+ 3. Extract definitions from both versions and compare each one's text.
13
+
14
+ A definition counts as modified when its own text changed; a class whose only
15
+ changes are inside its methods reports the methods, not itself.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import re
21
+ from dataclasses import dataclass
22
+ from pathlib import Path
23
+ from typing import Iterable, Optional, Sequence
24
+
25
+ _HUNK = re.compile(r"^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@")
26
+
27
+
28
+ @dataclass(frozen=True)
29
+ class SymbolChange:
30
+ kind: str # "added" | "modified" | "removed"
31
+ name: str # qualified: "SessionManager.refresh"
32
+ symbol_kind: str # "def", "class", "function", …
33
+
34
+ def label(self) -> str:
35
+ callable_kinds = {"def", "async def", "function", "method", "func", "fn"}
36
+ suffix = "()" if self.symbol_kind in callable_kinds else ""
37
+ return f"{self.name}{suffix} {self.kind}"
38
+
39
+
40
+ def reverse_apply(after: str, diff: str) -> Optional[str]:
41
+ """The text *diff* was made from, given the text it produced. None if it does not fit."""
42
+ from . import native_index
43
+
44
+ native = native_index.reverse_apply(after, diff)
45
+ if native is not native_index.UNAVAILABLE:
46
+ return native
47
+ lines = after.splitlines(keepends=True)
48
+ hunks = []
49
+ current = None
50
+ for raw in diff.splitlines(keepends=True):
51
+ match = _HUNK.match(raw)
52
+ if match:
53
+ current = {"new_start": int(match.group(3)), "old": [], "new": []}
54
+ hunks.append(current)
55
+ continue
56
+ if current is None or raw.startswith(("---", "+++", "\\")):
57
+ continue
58
+ tag, body = raw[:1], raw[1:]
59
+ if tag == " ":
60
+ current["old"].append(body)
61
+ current["new"].append(body)
62
+ elif tag == "-":
63
+ current["old"].append(body)
64
+ elif tag == "+":
65
+ current["new"].append(body)
66
+ elif raw.strip() == "": # a context line whose leading space was trimmed
67
+ current["old"].append(raw)
68
+ current["new"].append(raw)
69
+ if not hunks:
70
+ return None
71
+ for hunk in reversed(hunks):
72
+ start = max(0, hunk["new_start"] - 1) if hunk["new"] else hunk["new_start"]
73
+ end = start + len(hunk["new"])
74
+ if [l.rstrip("\r\n") for l in lines[start:end]] != [l.rstrip("\r\n") for l in hunk["new"]]:
75
+ return None
76
+ lines[start:end] = hunk["old"]
77
+ return "".join(lines)
78
+
79
+
80
+ def _bodies(source: str, language: str) -> dict:
81
+ """qualified name → (kind, text) for each definition."""
82
+ from .repo_map import extract_symbols
83
+
84
+ symbols = sorted(extract_symbols(source, language), key=lambda s: s.line)
85
+ lines = source.splitlines()
86
+ out = {}
87
+ for index, symbol in enumerate(symbols):
88
+ # A definition runs to the next one at the same or an outer level.
89
+ end = len(lines)
90
+ for later in symbols[index + 1:]:
91
+ if later.parent != symbol.qualified and not later.parent.startswith(symbol.qualified + "."):
92
+ end = later.line - 1
93
+ break
94
+ children = {s.line for s in symbols[index + 1:] if s.parent == symbol.qualified}
95
+ own = [line for number, line in enumerate(lines[symbol.line - 1:end], start=symbol.line)
96
+ if not _inside_child(number, children, symbols)]
97
+ # Blank and comment-only lines at the end belong to whatever follows;
98
+ # counting them made a comment above the next definition "modify"
99
+ # the one before it.
100
+ while own and (not own[-1].strip() or own[-1].lstrip().startswith(("#", "//"))):
101
+ own.pop()
102
+ out[symbol.qualified] = (symbol.kind, "\n".join(own))
103
+ return out
104
+
105
+
106
+ def _inside_child(number: int, child_lines: set, symbols: Sequence) -> bool:
107
+ if not child_lines:
108
+ return False
109
+ starts = sorted(child_lines)
110
+ for start in starts:
111
+ nxt = next((s.line for s in symbols if s.line > start), None)
112
+ if start <= number < (nxt or 10 ** 9):
113
+ return True
114
+ return False
115
+
116
+
117
+ def _parent(name: str) -> str:
118
+ return name.rsplit(".", 1)[0] if "." in name else ""
119
+
120
+
121
+ def symbol_changes(before: str, after: str, language: str) -> list[SymbolChange]:
122
+ from . import native_index
123
+
124
+ native = native_index.symbol_changes(before, after, language)
125
+ if native is not None:
126
+ return [SymbolChange(kind, name, symbol_kind) for kind, name, symbol_kind in native]
127
+ old, new = _bodies(before, language), _bodies(after, language)
128
+ changes = []
129
+ for name, (kind, text) in new.items():
130
+ if name not in old:
131
+ parent = _parent(name)
132
+ if parent and parent in new and parent not in old:
133
+ continue # inside an added class: the class says it
134
+ changes.append(SymbolChange("added", name, kind))
135
+ elif old[name][1] != text:
136
+ changes.append(SymbolChange("modified", name, kind))
137
+ for name, (kind, _) in old.items():
138
+ if name not in new:
139
+ parent = _parent(name)
140
+ if parent and parent in old and parent not in new:
141
+ continue # inside a removed class
142
+ changes.append(SymbolChange("removed", name, kind))
143
+ order = {"added": 0, "modified": 1, "removed": 2}
144
+ return sorted(changes, key=lambda c: (order[c.kind], c.name))
145
+
146
+
147
+ def file_symbol_changes(path: str | Path, diffs: Iterable[str]) -> Optional[list[SymbolChange]]:
148
+ """What this turn's *diffs* (oldest first) did to the definitions in *path*. None if unknown."""
149
+ from .repo_map import LANGUAGES
150
+
151
+ path = Path(path)
152
+ language = LANGUAGES.get(path.suffix.lower(), "")
153
+ if not language:
154
+ return None
155
+ try:
156
+ after = path.read_text(encoding="utf-8")
157
+ except (OSError, UnicodeDecodeError):
158
+ return None
159
+ before = after
160
+ for diff in reversed(list(diffs)):
161
+ if "--- /dev/null" in diff:
162
+ before = ""
163
+ break
164
+ previous = reverse_apply(before, diff)
165
+ if previous is None:
166
+ return None
167
+ before = previous
168
+ return symbol_changes(before, after, language)
169
+
170
+
171
+ __all__ = ["SymbolChange", "file_symbol_changes", "reverse_apply", "symbol_changes"]