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,242 @@
1
+ """OpenAI image generation/editing client — the execution backend for prompts
2
+ compiled by the `minimal-editorial-poster` / `minimal-editorial-exports`
3
+ skills.
4
+
5
+ Two capabilities, matching OpenAI's two endpoints (verified against the
6
+ official openai-python SDK source, since the public docs page 403s to
7
+ scrapers):
8
+ generate_image() -> POST /v1/images/generations (text -> new image)
9
+ edit_image() -> POST /v1/images/edits (existing photo + prompt
10
+ -> transformed image; multipart, not JSON)
11
+
12
+ Both use gpt-image-1, which always returns base64 (no response_format /
13
+ url option for GPT image models, only for dall-e-2/3).
14
+
15
+ Key resolution mirrors aria_cli.py's _get_provider_key(): env var
16
+ OPENAI_API_KEY first, then providers.json's "llm" then "data" sections
17
+ under "openai" — so a key already set via `/apikey set openai sk-...` for
18
+ chat is reused here, no separate setup needed.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import base64
24
+ import json
25
+ import os
26
+ from pathlib import Path
27
+ from typing import Any, Dict, Optional
28
+
29
+ API_BASE = "https://api.openai.com/v1"
30
+ DEFAULT_MODEL = "gpt-image-1"
31
+
32
+ # Per-image USD cost by (quality, size), verified against OpenAI's published
33
+ # gpt-image-1 output-token pricing (developers.openai.com/api/docs/guides/
34
+ # image-generation) — output tokens only; input text/image tokens add a few
35
+ # thousandths of a cent and are ignored here as noise.
36
+ _COST_USD: Dict[str, Dict[str, float]] = {
37
+ "low": {"1024x1024": 0.011, "1024x1536": 0.016, "1536x1024": 0.016},
38
+ "medium": {"1024x1024": 0.042, "1024x1536": 0.063, "1536x1024": 0.063},
39
+ "high": {"1024x1024": 0.167, "1024x1536": 0.25, "1536x1024": 0.25},
40
+ }
41
+
42
+
43
+ def estimate_cost(size: str = "1024x1536", quality: str = "high") -> Dict[str, Any]:
44
+ """Rough cost estimate — call before generate_image()/edit_image(),
45
+ not a live quote. "auto" quality/size can't be priced ahead of time
46
+ (OpenAI picks the actual value), so it's reported as unknown rather
47
+ than guessed."""
48
+ per_image = (_COST_USD.get(quality) or {}).get(size)
49
+ return {
50
+ "provider": "openai",
51
+ "model": DEFAULT_MODEL,
52
+ "size": size,
53
+ "quality": quality,
54
+ "estimated_cost_usd": per_image,
55
+ "note": (
56
+ "Illustrative estimate from OpenAI's published per-image pricing; "
57
+ "verify current pricing at platform.openai.com/docs/pricing."
58
+ if per_image is not None
59
+ else "'auto' size/quality is resolved by OpenAI at request time and can't be priced ahead of submission."
60
+ ),
61
+ }
62
+
63
+
64
+ def _providers_path() -> Path:
65
+ from apps.cli.config_paths import resolve_paths
66
+ return resolve_paths().providers_file
67
+
68
+
69
+ def _api_key() -> str:
70
+ env = os.getenv("OPENAI_API_KEY", "").strip()
71
+ if env:
72
+ return env
73
+ path = _providers_path()
74
+ if not path.exists():
75
+ return ""
76
+ try:
77
+ raw = json.loads(path.read_text(encoding="utf-8"))
78
+ except Exception:
79
+ return ""
80
+ for section in ("llm", "data"):
81
+ entry = raw.get(section, {}).get("openai", {}) or {}
82
+ if entry.get("api_key"):
83
+ return entry["api_key"]
84
+ return ""
85
+
86
+
87
+ def _require_key() -> str:
88
+ key = _api_key()
89
+ if not key:
90
+ raise RuntimeError(
91
+ "No OpenAI API key found. Set one with `/apikey set openai sk-...` "
92
+ "or export OPENAI_API_KEY."
93
+ )
94
+ return key
95
+
96
+
97
+ def _save_b64_image(b64_data: str, dest: Path) -> Path:
98
+ dest.write_bytes(base64.b64decode(b64_data))
99
+ return dest
100
+
101
+
102
+ def _normalize_image_for_upload(path: Path, *, keep_alpha: bool = False) -> tuple[str, bytes]:
103
+ """Re-encode an arbitrary local image file into a clean single-frame PNG
104
+ before uploading to OpenAI's edits endpoint.
105
+
106
+ Two real problems this fixes, not just defensive coding — both
107
+ reproduced directly against real iPhone photos:
108
+ 1. iPhones commonly save JPEGs as MPO (Multi-Picture Object — an
109
+ embedded-stereo-frame container, not a plain single-frame JPEG)
110
+ even with a plain .jpg extension. OpenAI's edit endpoint rejects
111
+ these with a 400 "Invalid image file or mode" even though the
112
+ extension and declared docs (png/webp/jpg) suggest it should work.
113
+ 2. A portrait photo is commonly stored as landscape pixels plus an
114
+ EXIF orientation tag telling viewers to rotate on display — the
115
+ raw bytes, uploaded as-is, are genuinely sideways. Reproduced: a
116
+ raw PIL open() of a real orientation=6 photo, no exif_transpose,
117
+ is visibly sideways.
118
+ Re-saving through PIL with exif_transpose applied produces a single-
119
+ frame PNG immune to both, regardless of the source container/orientation.
120
+ """
121
+ import io
122
+
123
+ from PIL import Image, ImageOps
124
+
125
+ img = ImageOps.exif_transpose(Image.open(path))
126
+ img = img.convert("RGBA" if keep_alpha else "RGB")
127
+ buf = io.BytesIO()
128
+ img.save(buf, format="PNG")
129
+ return f"{path.stem}.png", buf.getvalue()
130
+
131
+
132
+ def generate_image(
133
+ prompt: str,
134
+ *,
135
+ size: str = "1024x1536",
136
+ quality: str = "high",
137
+ confirmed: bool = False,
138
+ ) -> Dict[str, Any]:
139
+ """Generate a new image from a text prompt (e.g. minimal-editorial-poster's
140
+ compiled prompt) via POST /v1/images/generations — real per-call cost,
141
+ billed by OpenAI the instant this succeeds (see estimate_cost()).
142
+
143
+ Blocking (uses requests) — callers on an event loop should run this in
144
+ an executor, same as every other client in this codebase.
145
+ """
146
+ if not confirmed:
147
+ return {
148
+ "success": False,
149
+ "error": (
150
+ "confirmed must be true to generate a real (paid) image. "
151
+ "Call estimate_cost() first to see the cost, then resubmit with confirmed=true."
152
+ ),
153
+ }
154
+
155
+ import requests
156
+
157
+ from artifacts import create_user_artifact
158
+
159
+ key = _require_key()
160
+ resp = requests.post(
161
+ f"{API_BASE}/images/generations",
162
+ headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
163
+ json={"model": DEFAULT_MODEL, "prompt": prompt, "size": size, "quality": quality},
164
+ timeout=120,
165
+ )
166
+ if resp.status_code != 200:
167
+ return {"success": False, "error": f"OpenAI image generation failed: {resp.status_code} {resp.text[:300]}"}
168
+ data = (resp.json().get("data") or [{}])[0]
169
+ b64 = data.get("b64_json")
170
+ if not b64:
171
+ return {"success": False, "error": "OpenAI response had no b64_json image data"}
172
+
173
+ artifact = create_user_artifact("image", "generated", "poster", ".png")
174
+ _save_b64_image(b64, artifact.path)
175
+ return {"success": True, "path": str(artifact.path)}
176
+
177
+
178
+ def edit_image(
179
+ image_path: str,
180
+ prompt: str,
181
+ *,
182
+ size: str = "1024x1536",
183
+ quality: str = "high",
184
+ mask_path: Optional[str] = None,
185
+ confirmed: bool = False,
186
+ ) -> Dict[str, Any]:
187
+ """Transform an existing local photo per `prompt` (e.g. "convert to duotone,
188
+ simplify background to negative space, add scan-noise texture...") via
189
+ POST /v1/images/edits — the execution path for a real user-provided photo
190
+ run through the minimal-editorial-poster skill. Real per-call cost,
191
+ billed by OpenAI the instant this succeeds (see estimate_cost()).
192
+
193
+ Blocking (uses requests) — same threading note as generate_image.
194
+ """
195
+ if not confirmed:
196
+ return {
197
+ "success": False,
198
+ "error": (
199
+ "confirmed must be true to generate a real (paid) image edit. "
200
+ "Call estimate_cost() first to see the cost, then resubmit with confirmed=true."
201
+ ),
202
+ }
203
+
204
+ import requests
205
+
206
+ from artifacts import create_user_artifact
207
+
208
+ src = Path(image_path)
209
+ if not src.exists():
210
+ return {"success": False, "error": f"File not found: {image_path}"}
211
+
212
+ key = _require_key()
213
+ try:
214
+ files = {"image": _normalize_image_for_upload(src)}
215
+ except Exception as exc:
216
+ return {"success": False, "error": f"Could not read image_path: {exc}"}
217
+ if mask_path:
218
+ mask = Path(mask_path)
219
+ if not mask.exists():
220
+ return {"success": False, "error": f"Mask file not found: {mask_path}"}
221
+ try:
222
+ files["mask"] = _normalize_image_for_upload(mask, keep_alpha=True)
223
+ except Exception as exc:
224
+ return {"success": False, "error": f"Could not read mask_path: {exc}"}
225
+
226
+ resp = requests.post(
227
+ f"{API_BASE}/images/edits",
228
+ headers={"Authorization": f"Bearer {key}"},
229
+ data={"model": DEFAULT_MODEL, "prompt": prompt, "size": size, "quality": quality},
230
+ files=files,
231
+ timeout=180,
232
+ )
233
+ if resp.status_code != 200:
234
+ return {"success": False, "error": f"OpenAI image edit failed: {resp.status_code} {resp.text[:300]}"}
235
+ data = (resp.json().get("data") or [{}])[0]
236
+ b64 = data.get("b64_json")
237
+ if not b64:
238
+ return {"success": False, "error": "OpenAI response had no b64_json image data"}
239
+
240
+ artifact = create_user_artifact("image", "edited", f"{src.stem}_edited", ".png")
241
+ _save_b64_image(b64, artifact.path)
242
+ return {"success": True, "path": str(artifact.path)}
@@ -0,0 +1,157 @@
1
+ """Runway video generation client — Layer 3 (cloud AI generation) of the
2
+ video architecture, one of two provider clients (see also
3
+ kling_video_client.py) behind the same submit/poll shape so
4
+ packages/aria_mcp/server.py can route to either without provider-specific
5
+ logic outside these two files.
6
+
7
+ Verified against Runway's own generated SDK source
8
+ (github.com/runwayml/sdk-python), not the public docs page (which returned
9
+ an unfetchable error) — same discipline as openai_image_client.py and
10
+ canva_client.py: primary-source field names, not guessed ones.
11
+
12
+ base_url: https://api.dev.runwayml.com
13
+ auth: Authorization: Bearer {api_key}, X-Runway-Version: 2024-11-06
14
+ submit: POST /v1/text_to_video {model, promptText, ratio, duration?, ...}
15
+ poll: GET /v1/tasks/{id} -> status PENDING|THROTTLED|RUNNING|FAILED|SUCCEEDED
16
+ (SUCCEEDED carries `output`: a list of video URLs, valid 24-48h)
17
+
18
+ Real per-request cost — every submission is a genuine payment. This module
19
+ never gates that itself (no local "confirmed" concept); the MCP server layer
20
+ enforces the confirm-after-estimate gate, matching the broker order-preview
21
+ pattern's reasoning: submission is the moment money is spent, so the caller
22
+ must have deliberately opted in.
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ import os
28
+ from pathlib import Path
29
+ from typing import Any, Dict, Optional
30
+
31
+ API_BASE = "https://api.dev.runwayml.com"
32
+ API_VERSION = "2024-11-06"
33
+
34
+ # Rough, illustrative-only pricing — Runway doesn't publish a stable public
35
+ # per-second API rate the way Kling does; verify current pricing on your
36
+ # account dashboard before relying on this for a real cost decision.
37
+ APPROX_COST_PER_SECOND_USD = 0.25
38
+
39
+
40
+ def _providers_path() -> Path:
41
+ from apps.cli.config_paths import resolve_paths
42
+ return resolve_paths().providers_file
43
+
44
+
45
+ def _api_key() -> str:
46
+ env = os.getenv("RUNWAYML_API_SECRET", "").strip()
47
+ if env:
48
+ return env
49
+ path = _providers_path()
50
+ if not path.exists():
51
+ return ""
52
+ try:
53
+ import json
54
+ raw = json.loads(path.read_text(encoding="utf-8"))
55
+ except Exception:
56
+ return ""
57
+ for section in ("llm", "data"):
58
+ entry = raw.get(section, {}).get("runway", {}) or {}
59
+ if entry.get("api_key"):
60
+ return entry["api_key"]
61
+ return ""
62
+
63
+
64
+ def _require_key() -> str:
65
+ key = _api_key()
66
+ if not key:
67
+ raise RuntimeError(
68
+ "No Runway API key found. Set one with `/apikey set runway <key>` "
69
+ "or export RUNWAYML_API_SECRET."
70
+ )
71
+ return key
72
+
73
+
74
+ def _headers() -> Dict[str, str]:
75
+ return {
76
+ "Authorization": f"Bearer {_require_key()}",
77
+ "X-Runway-Version": API_VERSION,
78
+ "Content-Type": "application/json",
79
+ }
80
+
81
+
82
+ def estimate_cost(duration: int) -> Dict[str, Any]:
83
+ """Rough cost estimate — call before submit_video(), not a live quote."""
84
+ return {
85
+ "provider": "runway",
86
+ "duration_sec": duration,
87
+ "estimated_cost_usd": round(duration * APPROX_COST_PER_SECOND_USD, 2),
88
+ "note": "Illustrative estimate — verify current pricing on your Runway account dashboard.",
89
+ }
90
+
91
+
92
+ def submit_video(
93
+ prompt: str,
94
+ *,
95
+ model: str = "gen4.5",
96
+ duration: int = 5,
97
+ ratio: str = "1280:720",
98
+ ) -> Dict[str, Any]:
99
+ """Submit a text-to-video generation job. Returns immediately with a
100
+ task id — this does NOT wait for the video, since generation takes
101
+ minutes; poll with poll_video().
102
+
103
+ duration must be 2-10 for gen4.5; ratio must be one of the values that
104
+ model supports ("1280:720"/"720:1280" for gen4.5; veo3.1/veo3.1_fast
105
+ additionally support "1080:1920"/"1920:1080" — see Runway's docs for the
106
+ full per-model matrix, verified in this repo only for gen4.5's basic
107
+ shape).
108
+ """
109
+ import requests
110
+
111
+ body = {"model": model, "promptText": prompt, "ratio": ratio, "duration": duration}
112
+ try:
113
+ resp = requests.post(f"{API_BASE}/v1/text_to_video", headers=_headers(), json=body, timeout=30)
114
+ except Exception as exc:
115
+ return {"success": False, "error": str(exc)}
116
+ if resp.status_code not in (200, 201, 202):
117
+ return {"success": False, "error": f"Runway submission failed: {resp.status_code} {resp.text[:400]}"}
118
+ data = resp.json()
119
+ task_id = data.get("id", "")
120
+ if not task_id:
121
+ return {"success": False, "error": "Runway did not return a task id"}
122
+ return {"success": True, "task_id": task_id, "provider": "runway"}
123
+
124
+
125
+ def poll_video(task_id: str, *, download: bool = True) -> Dict[str, Any]:
126
+ """Check a submitted task's status. On SUCCEEDED, optionally downloads
127
+ the first output video to the artifacts folder."""
128
+ import requests
129
+
130
+ try:
131
+ resp = requests.get(f"{API_BASE}/v1/tasks/{task_id}", headers=_headers(), timeout=30)
132
+ except Exception as exc:
133
+ return {"success": False, "error": str(exc)}
134
+ if resp.status_code != 200:
135
+ return {"success": False, "error": f"Runway task lookup failed: {resp.status_code} {resp.text[:400]}"}
136
+ data = resp.json()
137
+ status = data.get("status", "")
138
+
139
+ if status == "SUCCEEDED":
140
+ outputs = data.get("output") or []
141
+ if not outputs:
142
+ return {"success": False, "status": status, "error": "SUCCEEDED but no output URLs present"}
143
+ result = {"success": True, "status": status, "video_url": outputs[0]}
144
+ if download:
145
+ from artifacts import create_user_artifact
146
+
147
+ video_resp = requests.get(outputs[0], timeout=120)
148
+ if video_resp.status_code == 200:
149
+ artifact = create_user_artifact("video", "runway", "runway_video", ".mp4")
150
+ artifact.path.write_bytes(video_resp.content)
151
+ result["path"] = str(artifact.path)
152
+ return result
153
+
154
+ if status == "FAILED":
155
+ return {"success": False, "status": status, "error": data.get("failure", "generation failed")}
156
+
157
+ return {"success": True, "status": status, "progress": data.get("progress")}
@@ -0,0 +1,105 @@
1
+ """Read-only client for the warehouse ERP agent snapshot endpoint.
2
+
3
+ The client intentionally exposes one narrow endpoint instead of a generic ERP
4
+ proxy. That keeps the agent boundary auditable: the CLI can only retrieve the
5
+ small operational snapshot required for analysis and has no write capability.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import os
11
+ from collections.abc import Mapping
12
+ from typing import Any
13
+ from urllib.parse import quote, urlparse
14
+
15
+ import httpx
16
+
17
+
18
+ class WarehouseERPConfigurationError(ValueError):
19
+ """Raised when the local ERP integration configuration is invalid."""
20
+
21
+
22
+ class WarehouseERPRequestError(RuntimeError):
23
+ """Raised with a safe, user-facing ERP request error."""
24
+
25
+
26
+ _DEFAULT_SNAPSHOT_PATH = "/api/v1/warehouses/{warehouse_id}/agent-snapshot"
27
+ _RECORD_LISTS = ("connectors", "inbounds", "skus", "locations")
28
+
29
+
30
+ class WarehouseERPClient:
31
+ """Fetch a minimal, read-only warehouse snapshot over HTTPS or HTTP."""
32
+
33
+ def __init__(
34
+ self,
35
+ base_url: str,
36
+ token: str = "",
37
+ snapshot_path: str = _DEFAULT_SNAPSHOT_PATH,
38
+ timeout_seconds: float = 10.0,
39
+ transport: httpx.AsyncBaseTransport | None = None,
40
+ ) -> None:
41
+ parsed = urlparse(str(base_url or "").strip())
42
+ if parsed.scheme not in {"http", "https"} or not parsed.netloc:
43
+ raise WarehouseERPConfigurationError("ARIA_WAREHOUSE_ERP_URL 必须是完整的 http(s) URL")
44
+ if not snapshot_path.startswith("/") or "{warehouse_id}" not in snapshot_path:
45
+ raise WarehouseERPConfigurationError(
46
+ "ARIA_WAREHOUSE_ERP_SNAPSHOT_PATH 必须是包含 {warehouse_id} 的相对路径"
47
+ )
48
+ self.base_url = str(base_url).rstrip("/")
49
+ self.token = str(token or "").strip()
50
+ self.snapshot_path = snapshot_path
51
+ self.timeout_seconds = float(timeout_seconds)
52
+ self.transport = transport
53
+
54
+ @classmethod
55
+ def from_env(cls) -> "WarehouseERPClient":
56
+ return cls(
57
+ base_url=os.environ.get("ARIA_WAREHOUSE_ERP_URL", ""),
58
+ token=os.environ.get("ARIA_WAREHOUSE_ERP_TOKEN", ""),
59
+ snapshot_path=os.environ.get("ARIA_WAREHOUSE_ERP_SNAPSHOT_PATH", _DEFAULT_SNAPSHOT_PATH),
60
+ )
61
+
62
+ def _snapshot_url(self, warehouse_id: str) -> str:
63
+ cleaned = str(warehouse_id or "").strip()
64
+ if not cleaned:
65
+ raise WarehouseERPConfigurationError("仓库编号不能为空")
66
+ return self.base_url + self.snapshot_path.format(warehouse_id=quote(cleaned, safe=""))
67
+
68
+ async def fetch_snapshot(self, warehouse_id: str) -> dict[str, Any]:
69
+ headers = {"Accept": "application/json"}
70
+ if self.token:
71
+ headers["Authorization"] = f"Bearer {self.token}"
72
+
73
+ try:
74
+ async with httpx.AsyncClient(
75
+ timeout=self.timeout_seconds,
76
+ follow_redirects=False,
77
+ transport=self.transport,
78
+ ) as client:
79
+ response = await client.get(self._snapshot_url(warehouse_id), headers=headers)
80
+ except httpx.TimeoutException as exc:
81
+ raise WarehouseERPRequestError("ERP 请求超时,请稍后重试。") from exc
82
+ except httpx.HTTPError as exc:
83
+ raise WarehouseERPRequestError("无法连接 ERP 服务,请检查网络或服务状态。") from exc
84
+
85
+ if response.status_code != 200:
86
+ raise WarehouseERPRequestError(f"ERP 服务返回 HTTP {response.status_code}。")
87
+ try:
88
+ payload = response.json()
89
+ except ValueError as exc:
90
+ raise WarehouseERPRequestError("ERP 服务返回的不是有效 JSON。") from exc
91
+ return self._normalise_snapshot(warehouse_id, payload)
92
+
93
+ @staticmethod
94
+ def _normalise_snapshot(warehouse_id: str, payload: Any) -> dict[str, Any]:
95
+ root = payload.get("data", payload) if isinstance(payload, Mapping) else None
96
+ if not isinstance(root, Mapping):
97
+ raise WarehouseERPRequestError("ERP 快照必须是 JSON 对象。")
98
+
99
+ snapshot: dict[str, Any] = {
100
+ "warehouse_id": str(root.get("warehouse_id") or warehouse_id),
101
+ }
102
+ for key in _RECORD_LISTS:
103
+ value = root.get(key, [])
104
+ snapshot[key] = [dict(item) for item in value if isinstance(item, Mapping)] if isinstance(value, list) else []
105
+ return snapshot