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.
- aria_bots/__init__.py +7 -0
- aria_bots/channels/README.md +97 -0
- aria_bots/channels/__init__.py +1 -0
- aria_bots/channels/approvals.py +263 -0
- aria_bots/channels/conversation.py +280 -0
- aria_bots/channels/digest.py +186 -0
- aria_bots/channels/registry.py +95 -0
- aria_bots/engine.py +144 -0
- aria_bots/feishu_bot.py +1385 -0
- aria_bots/logistics/__init__.py +1 -0
- aria_bots/logistics/carriers.py +253 -0
- aria_bots/logistics/freight.py +154 -0
- aria_bots/logistics/inventory.py +242 -0
- aria_bots/logistics/mcp_server.py +156 -0
- aria_bots/logistics/records.py +119 -0
- aria_bots/logistics/tenancy.py +152 -0
- aria_bots/market.py +91 -0
- aria_bots/relay_client.py +326 -0
- aria_bots/telegram_bot.py +299 -0
- aria_code/__init__.py +111 -0
- aria_code/_bin/aria-native.exe +0 -0
- aria_code/_bin/aria-runtime.exe +0 -0
- aria_code/_version.py +20 -0
- aria_code/account_memory.py +296 -0
- aria_code/account_session.py +166 -0
- aria_code/adk_apps/__init__.py +1 -0
- aria_code/adk_apps/aria_code_review/__init__.py +1 -0
- aria_code/adk_apps/aria_code_review/agent.py +32 -0
- aria_code/adk_apps/aria_research/__init__.py +1 -0
- aria_code/adk_apps/aria_research/agent.py +31 -0
- aria_code/agents/__init__.py +49 -0
- aria_code/agents/base.py +329 -0
- aria_code/agents/code_review.py +200 -0
- aria_code/agents/deep/__init__.py +37 -0
- aria_code/agents/deep/calibration_loop.py +144 -0
- aria_code/agents/deep/critic.py +125 -0
- aria_code/agents/deep/deepen.py +193 -0
- aria_code/agents/deep/models.py +149 -0
- aria_code/agents/deep/pipeline.py +164 -0
- aria_code/agents/deep/quant_fusion.py +192 -0
- aria_code/agents/deep/themes.py +95 -0
- aria_code/agents/deep/tiers.py +106 -0
- aria_code/agents/engineering/__init__.py +14 -0
- aria_code/agents/engineering/coder.py +222 -0
- aria_code/agents/engineering/tester.py +145 -0
- aria_code/agents/financial/__init__.py +21 -0
- aria_code/agents/financial/cashflow_burn.py +119 -0
- aria_code/agents/financial/catalyst.py +279 -0
- aria_code/agents/financial/corporate_finance.py +175 -0
- aria_code/agents/financial/debate.py +224 -0
- aria_code/agents/financial/earnings.py +315 -0
- aria_code/agents/financial/fundamental.py +178 -0
- aria_code/agents/financial/macro.py +111 -0
- aria_code/agents/financial/news.py +231 -0
- aria_code/agents/financial/risk.py +146 -0
- aria_code/agents/financial/sector.py +279 -0
- aria_code/agents/financial/strategist.py +121 -0
- aria_code/agents/financial/stripe_revenue.py +127 -0
- aria_code/agents/financial/synthesis.py +274 -0
- aria_code/agents/financial/technical.py +277 -0
- aria_code/agents/orchestrator.py +44 -0
- aria_code/agents/portfolio_agent.py +392 -0
- aria_code/agents/realty/__init__.py +62 -0
- aria_code/agents/realty/asset_diagnosis.py +152 -0
- aria_code/agents/realty/business_match.py +166 -0
- aria_code/agents/realty/cashflow_verify.py +209 -0
- aria_code/agents/realty/contract_rules.py +210 -0
- aria_code/agents/realty/energy_anomaly.py +189 -0
- aria_code/agents/realty/exit_settlement.py +208 -0
- aria_code/agents/realty/fulfillment_risk.py +206 -0
- aria_code/agents/realty/ops_optimize.py +160 -0
- aria_code/agents/realty/revenue_share.py +215 -0
- aria_code/agents/registry.py +168 -0
- aria_code/agents/signal_scheme.py +111 -0
- aria_code/agents/sports/__init__.py +0 -0
- aria_code/agents/sports/football_agent.py +197 -0
- aria_code/agents/supervisor.py +113 -0
- aria_code/agents/team.py +500 -0
- aria_code/agents/video/__init__.py +16 -0
- aria_code/agents/video/director.py +376 -0
- aria_code/agents/video/qa_agent.py +143 -0
- aria_code/agents/video/script_doctor.py +112 -0
- aria_code/agents/warehouse/__init__.py +25 -0
- aria_code/agents/warehouse/contracts.py +26 -0
- aria_code/agents/warehouse/dashboard.py +155 -0
- aria_code/agents/warehouse/fulfillment_leadtime.py +95 -0
- aria_code/agents/warehouse/inbound_exceptions.py +25 -0
- aria_code/agents/warehouse/inventory_health.py +24 -0
- aria_code/agents/warehouse/local_run.py +71 -0
- aria_code/agents/warehouse/local_snapshot.py +132 -0
- aria_code/agents/warehouse/logistics_cost.py +84 -0
- aria_code/agents/warehouse/logistics_sync.py +21 -0
- aria_code/agents/warehouse/navigation.schema.json +110 -0
- aria_code/agents/warehouse/task_agent.py +172 -0
- aria_code/agents/warehouse/workflow.py +31 -0
- aria_code/aliyun_data_client.py +4 -0
- aria_code/apps/README.md +12 -0
- aria_code/apps/__init__.py +2 -0
- aria_code/apps/channels/README.md +9 -0
- aria_code/apps/channels/__init__.py +17 -0
- aria_code/apps/channels/approvals.py +11 -0
- aria_code/apps/channels/conversation.py +11 -0
- aria_code/apps/channels/digest.py +11 -0
- aria_code/apps/channels/intake.py +92 -0
- aria_code/apps/channels/registry.py +11 -0
- aria_code/apps/channels/tradingview.py +94 -0
- aria_code/apps/cli/README.md +13 -0
- aria_code/apps/cli/__init__.py +2 -0
- aria_code/apps/cli/_optional.py +120 -0
- aria_code/apps/cli/app_server.py +656 -0
- aria_code/apps/cli/auto_update.py +125 -0
- aria_code/apps/cli/bootstrap.py +206 -0
- aria_code/apps/cli/broker_render.py +206 -0
- aria_code/apps/cli/chat_turn.py +1327 -0
- aria_code/apps/cli/cloud_models.py +231 -0
- aria_code/apps/cli/codegen_paths.py +29 -0
- aria_code/apps/cli/commands/__init__.py +34 -0
- aria_code/apps/cli/commands/_business_render.py +78 -0
- aria_code/apps/cli/commands/_ui.py +71 -0
- aria_code/apps/cli/commands/analysis_cmds.py +378 -0
- aria_code/apps/cli/commands/ashare_prediction_cmds.py +327 -0
- aria_code/apps/cli/commands/auth_cmds.py +215 -0
- aria_code/apps/cli/commands/backtest_cmds.py +2518 -0
- aria_code/apps/cli/commands/broker_cmds.py +1236 -0
- aria_code/apps/cli/commands/business_workflow_cmds.py +379 -0
- aria_code/apps/cli/commands/canvas_cmds.py +77 -0
- aria_code/apps/cli/commands/catalog.py +189 -0
- aria_code/apps/cli/commands/core_cmds.py +2748 -0
- aria_code/apps/cli/commands/data_cmds.py +521 -0
- aria_code/apps/cli/commands/diagnostic_cmds.py +285 -0
- aria_code/apps/cli/commands/diagnostic_ops_cmds.py +813 -0
- aria_code/apps/cli/commands/engineering_cmds.py +399 -0
- aria_code/apps/cli/commands/file_cmds.py +312 -0
- aria_code/apps/cli/commands/finance_service_cmds.py +60 -0
- aria_code/apps/cli/commands/fx_commodity_cmds.py +123 -0
- aria_code/apps/cli/commands/market.py +544 -0
- aria_code/apps/cli/commands/market_cmds.py +1419 -0
- aria_code/apps/cli/commands/market_context.py +432 -0
- aria_code/apps/cli/commands/market_render.py +7 -0
- aria_code/apps/cli/commands/model_cmds.py +2374 -0
- aria_code/apps/cli/commands/ops_cmds.py +721 -0
- aria_code/apps/cli/commands/orchestrator_cmds.py +181 -0
- aria_code/apps/cli/commands/pdf_export_cmds.py +125 -0
- aria_code/apps/cli/commands/portfolio_cmds.py +1316 -0
- aria_code/apps/cli/commands/report.py +476 -0
- aria_code/apps/cli/commands/scaffold_templates.py +617 -0
- aria_code/apps/cli/commands/session_cmds.py +236 -0
- aria_code/apps/cli/commands/session_ux_cmds.py +359 -0
- aria_code/apps/cli/commands/team.py +723 -0
- aria_code/apps/cli/commands/team_render.py +8 -0
- aria_code/apps/cli/commands/ui_cmds.py +401 -0
- aria_code/apps/cli/commands/warehouse_cmds.py +297 -0
- aria_code/apps/cli/commands/workflow_cmds.py +629 -0
- aria_code/apps/cli/commands/workspace_cmds.py +1543 -0
- aria_code/apps/cli/config_paths.py +73 -0
- aria_code/apps/cli/config_store.py +158 -0
- aria_code/apps/cli/constants.py +88 -0
- aria_code/apps/cli/context.py +34 -0
- aria_code/apps/cli/conversation_policy.py +53 -0
- aria_code/apps/cli/deterministic.py +200 -0
- aria_code/apps/cli/direct.py +48 -0
- aria_code/apps/cli/earnings_view.py +172 -0
- aria_code/apps/cli/endpoint_migration.py +64 -0
- aria_code/apps/cli/exec_events.py +255 -0
- aria_code/apps/cli/file_references.py +155 -0
- aria_code/apps/cli/finance_service_catalog.py +111 -0
- aria_code/apps/cli/football_reports.py +231 -0
- aria_code/apps/cli/github_app_auth.py +135 -0
- aria_code/apps/cli/google_login.py +239 -0
- aria_code/apps/cli/handlers/__init__.py +11 -0
- aria_code/apps/cli/handlers/broker_handlers.py +122 -0
- aria_code/apps/cli/handlers/chart_handlers.py +1314 -0
- aria_code/apps/cli/handlers/market_handlers.py +2570 -0
- aria_code/apps/cli/handlers/realty_handlers.py +114 -0
- aria_code/apps/cli/handlers/sports_handlers.py +22 -0
- aria_code/apps/cli/handlers/strategy_advice.py +82 -0
- aria_code/apps/cli/headless.py +352 -0
- aria_code/apps/cli/helpers.py +326 -0
- aria_code/apps/cli/hooks.py +180 -0
- aria_code/apps/cli/i18n.py +310 -0
- aria_code/apps/cli/intent.py +136 -0
- aria_code/apps/cli/intent_router.py +305 -0
- aria_code/apps/cli/intent_shadow.py +72 -0
- aria_code/apps/cli/intent_signals.py +347 -0
- aria_code/apps/cli/lifecycle_hooks.py +48 -0
- aria_code/apps/cli/local_tool_schemas.py +550 -0
- aria_code/apps/cli/main.py +39 -0
- aria_code/apps/cli/market_hours.py +100 -0
- aria_code/apps/cli/market_metadata.py +135 -0
- aria_code/apps/cli/market_universe.py +487 -0
- aria_code/apps/cli/message_processing.py +310 -0
- aria_code/apps/cli/mixin_binding.py +32 -0
- aria_code/apps/cli/model_catalog.py +652 -0
- aria_code/apps/cli/model_probe.py +169 -0
- aria_code/apps/cli/model_retirement.py +65 -0
- aria_code/apps/cli/native_branding.py +12 -0
- aria_code/apps/cli/native_bridge.py +118 -0
- aria_code/apps/cli/native_entry.py +58 -0
- aria_code/apps/cli/pdf_report.py +977 -0
- aria_code/apps/cli/plan_mode.py +139 -0
- aria_code/apps/cli/plotly_html.py +15 -0
- aria_code/apps/cli/prediction_feedback.py +202 -0
- aria_code/apps/cli/preflight.py +502 -0
- aria_code/apps/cli/project_aria.py +60 -0
- aria_code/apps/cli/prompt_assembly.py +78 -0
- aria_code/apps/cli/prompts/__init__.py +0 -0
- aria_code/apps/cli/prompts/coding.py +71 -0
- aria_code/apps/cli/prompts/select.py +193 -0
- aria_code/apps/cli/prompts/system_prompts.py +562 -0
- aria_code/apps/cli/prompts/ui.py +436 -0
- aria_code/apps/cli/provider_endpoints.py +237 -0
- aria_code/apps/cli/provider_keys.py +73 -0
- aria_code/apps/cli/providers/__init__.py +1 -0
- aria_code/apps/cli/providers/base.py +775 -0
- aria_code/apps/cli/providers/chat_routing.py +139 -0
- aria_code/apps/cli/providers/collaboration.py +98 -0
- aria_code/apps/cli/providers/llm/__init__.py +1 -0
- aria_code/apps/cli/providers/llm/offline_responses.py +68 -0
- aria_code/apps/cli/providers/llm/ollama_stream.py +1574 -0
- aria_code/apps/cli/providers/llm/response_cache.py +60 -0
- aria_code/apps/cli/providers/llm/sse_stream.py +298 -0
- aria_code/apps/cli/providers/runtime_bridge.py +586 -0
- aria_code/apps/cli/providers/vertexai_stream.py +592 -0
- aria_code/apps/cli/release_download.py +159 -0
- aria_code/apps/cli/review_runner.py +111 -0
- aria_code/apps/cli/runtime_consumer.py +769 -0
- aria_code/apps/cli/sandbox.py +32 -0
- aria_code/apps/cli/session_export.py +120 -0
- aria_code/apps/cli/session_jsonl.py +208 -0
- aria_code/apps/cli/session_refresh.py +123 -0
- aria_code/apps/cli/session_store.py +125 -0
- aria_code/apps/cli/skills_catalog.py +273 -0
- aria_code/apps/cli/task_isolation.py +211 -0
- aria_code/apps/cli/terminal_chrome.py +412 -0
- aria_code/apps/cli/todo_tracker.py +190 -0
- aria_code/apps/cli/tool_executor.py +932 -0
- aria_code/apps/cli/tool_registry.py +34 -0
- aria_code/apps/cli/tool_scope.py +113 -0
- aria_code/apps/cli/tools/__init__.py +40 -0
- aria_code/apps/cli/tools/context.py +46 -0
- aria_code/apps/cli/tools/file_tools.py +181 -0
- aria_code/apps/cli/tools/market_tools.py +626 -0
- aria_code/apps/cli/tools/notebook_tools.py +111 -0
- aria_code/apps/cli/tools/system_tools.py +656 -0
- aria_code/apps/cli/tools/write_tools.py +961 -0
- aria_code/apps/cli/tradingview_bridge.py +529 -0
- aria_code/apps/cli/transactions.py +269 -0
- aria_code/apps/cli/turn_planning.py +137 -0
- aria_code/apps/cli/update_check.py +257 -0
- aria_code/apps/cli/updater.py +373 -0
- aria_code/apps/cli/utils/__init__.py +0 -0
- aria_code/apps/cli/utils/market_detect.py +1663 -0
- aria_code/apps/cli/web_login.py +136 -0
- aria_code/apps/cli/workflow_runner.py +127 -0
- aria_code/apps/cli/workspace_route.py +121 -0
- aria_code/apps/daemon/README.md +14 -0
- aria_code/apps/vscode/README.md +115 -0
- aria_code/apps/vscode/package.json +70 -0
- aria_code/aria_cli.py +5244 -0
- aria_code/aria_daemon.py +1372 -0
- aria_code/aria_feishu_bot.py +16 -0
- aria_code/aria_mcp_server.py +61 -0
- aria_code/aria_relay_client.py +4 -0
- aria_code/aria_telegram_bot.py +11 -0
- aria_code/ariarc.py +385 -0
- aria_code/artifacts.py +581 -0
- aria_code/backtest_engine.py +4 -0
- aria_code/backtest_report.py +4 -0
- aria_code/brokers/__init__.py +78 -0
- aria_code/brokers/automation.py +193 -0
- aria_code/brokers/base.py +231 -0
- aria_code/brokers/capabilities.py +264 -0
- aria_code/brokers/cn/__init__.py +10 -0
- aria_code/brokers/cn/easytrader_broker.py +193 -0
- aria_code/brokers/cn/futu_broker.py +194 -0
- aria_code/brokers/cn/longbridge_broker.py +190 -0
- aria_code/brokers/cn/tiger_broker.py +196 -0
- aria_code/brokers/cn/xtquant_broker.py +225 -0
- aria_code/brokers/config.py +414 -0
- aria_code/brokers/intl/__init__.py +5 -0
- aria_code/brokers/intl/alpaca_broker.py +183 -0
- aria_code/brokers/intl/ibkr_broker.py +215 -0
- aria_code/brokers/intl/trading212_broker.py +183 -0
- aria_code/brokers/intl/webull_broker.py +156 -0
- aria_code/brokers/paper_broker.py +266 -0
- aria_code/brokers/planning.py +296 -0
- aria_code/brokers/registry.py +213 -0
- aria_code/brokers/trading.py +267 -0
- aria_code/canva_client.py +4 -0
- aria_code/change_store.py +127 -0
- aria_code/clients/__init__.py +0 -0
- aria_code/clients/aliyun_data_client.py +660 -0
- aria_code/clients/aria_relay_client.py +16 -0
- aria_code/clients/canva_client.py +284 -0
- aria_code/clients/figma_client.py +100 -0
- aria_code/clients/football_data_client.py +1671 -0
- aria_code/clients/kling_video_client.py +182 -0
- aria_code/clients/market_data_client.py +1985 -0
- aria_code/clients/openai_image_client.py +242 -0
- aria_code/clients/runway_video_client.py +157 -0
- aria_code/clients/warehouse_erp_client.py +105 -0
- aria_code/cloud_memory.py +190 -0
- aria_code/command_safety.py +19 -0
- aria_code/computer_use_server.py +276 -0
- aria_code/computer_use_tools.py +4 -0
- aria_code/dashboard_generator.py +579 -0
- aria_code/data_analysis_tools.py +4 -0
- aria_code/data_cleaner.py +483 -0
- aria_code/data_service.py +513 -0
- aria_code/datasources/__init__.py +23 -0
- aria_code/datasources/base.py +166 -0
- aria_code/datasources/router.py +253 -0
- aria_code/datasources/sec_statements.py +217 -0
- aria_code/datasources/sources/__init__.py +15 -0
- aria_code/datasources/sources/akshare_source.py +269 -0
- aria_code/datasources/sources/alpha_vantage_source.py +203 -0
- aria_code/datasources/sources/edgar_source.py +219 -0
- aria_code/datasources/sources/finnhub_source.py +198 -0
- aria_code/datasources/sources/fred_source.py +223 -0
- aria_code/datasources/sources/tushare_source.py +143 -0
- aria_code/datasources/sources/web_scraper_source.py +278 -0
- aria_code/datasources/sources/world_bank_source.py +206 -0
- aria_code/datasources/sources/yfinance_source.py +152 -0
- aria_code/doctor.py +860 -0
- aria_code/domain/__init__.py +0 -0
- aria_code/domain/_finance_core/__init__.py +5 -0
- aria_code/domain/_finance_core/backtest_engine.py +325 -0
- aria_code/domain/_finance_core/performance_stats.py +101 -0
- aria_code/domain/backtest_engine.py +75 -0
- aria_code/domain/backtest_report.py +488 -0
- aria_code/domain/finance_formulas.py +389 -0
- aria_code/domain/performance_stats.py +6 -0
- aria_code/domain/portfolio_ledger.py +307 -0
- aria_code/domain/strategy_vault.py +421 -0
- aria_code/evals/__init__.py +37 -0
- aria_code/evals/behavior.py +113 -0
- aria_code/evals/gap.py +93 -0
- aria_code/evals/harness.py +949 -0
- aria_code/evals/review_probe.py +132 -0
- aria_code/evals/runner.py +425 -0
- aria_code/evals/scorecard.py +322 -0
- aria_code/evals/summary.py +125 -0
- aria_code/external_agent_runner.py +115 -0
- aria_code/figma_client.py +4 -0
- aria_code/file_analysis_tools.py +4 -0
- aria_code/finance_formulas.py +4 -0
- aria_code/football_data_client.py +4 -0
- aria_code/image_gen_tools.py +4 -0
- aria_code/intent_classifier.py +459 -0
- aria_code/kling_video_client.py +4 -0
- aria_code/licensing.py +151 -0
- aria_code/local_finance_tools.py +4 -0
- aria_code/local_image_provider.py +4 -0
- aria_code/local_llm_provider.py +4 -0
- aria_code/macro_tools.py +4 -0
- aria_code/markdown_pdf.py +289 -0
- aria_code/market_data_client.py +4 -0
- aria_code/mcp_client.py +744 -0
- aria_code/memory_manager.py +273 -0
- aria_code/model_capability.py +512 -0
- aria_code/notification_tools.py +4 -0
- aria_code/openai_image_client.py +4 -0
- aria_code/packages/__init__.py +26 -0
- aria_code/packages/adk_bridge/__init__.py +11 -0
- aria_code/packages/adk_bridge/code_review_tools.py +49 -0
- aria_code/packages/adk_bridge/market_tools.py +125 -0
- aria_code/packages/aria_agents/__init__.py +5 -0
- aria_code/packages/aria_agents/manifest.py +78 -0
- aria_code/packages/aria_core/__init__.py +34 -0
- aria_code/packages/aria_core/architecture.py +269 -0
- aria_code/packages/aria_core/export.py +147 -0
- aria_code/packages/aria_core/manifest.py +65 -0
- aria_code/packages/aria_core/paths.py +57 -0
- aria_code/packages/aria_core/secure_file.py +68 -0
- aria_code/packages/aria_infra/__init__.py +15 -0
- aria_code/packages/aria_infra/arthera.py +58 -0
- aria_code/packages/aria_infra/doctor.py +246 -0
- aria_code/packages/aria_infra/product.py +40 -0
- aria_code/packages/aria_mcp/__init__.py +25 -0
- aria_code/packages/aria_mcp/bridge.py +232 -0
- aria_code/packages/aria_mcp/circuit.py +82 -0
- aria_code/packages/aria_mcp/config.py +162 -0
- aria_code/packages/aria_mcp/installer.py +95 -0
- aria_code/packages/aria_mcp/server.py +1705 -0
- aria_code/packages/aria_mcp/tools.py +81 -0
- aria_code/packages/aria_sdk/__init__.py +19 -0
- aria_code/packages/aria_sdk/client.py +393 -0
- aria_code/packages/aria_sdk/providers.py +70 -0
- aria_code/packages/aria_sdk/streaming.py +75 -0
- aria_code/packages/aria_sdk/types.py +86 -0
- aria_code/packages/aria_services/__init__.py +92 -0
- aria_code/packages/aria_services/cache.py +60 -0
- aria_code/packages/aria_services/context.py +356 -0
- aria_code/packages/aria_services/context_checkpoints.py +157 -0
- aria_code/packages/aria_services/data.py +11 -0
- aria_code/packages/aria_services/provider_health.py +304 -0
- aria_code/packages/aria_services/references.py +247 -0
- aria_code/packages/aria_services/registry.py +249 -0
- aria_code/packages/aria_services/research_protocol.py +137 -0
- aria_code/packages/aria_services/research_quality.py +186 -0
- aria_code/packages/aria_services/settings.py +160 -0
- aria_code/packages/aria_services/usage.py +151 -0
- aria_code/packages/aria_skills/__init__.py +46 -0
- aria_code/packages/aria_skills/catalog.py +149 -0
- aria_code/packages/aria_skills/loader.py +455 -0
- aria_code/packages/aria_skills/registry.py +84 -0
- aria_code/packages/aria_tools/__init__.py +5 -0
- aria_code/packages/aria_tools/financial/__init__.py +5 -0
- aria_code/packages/aria_tools/financial/_paths.py +92 -0
- aria_code/packages/aria_tools/registry.py +129 -0
- aria_code/packages/quant_engine/__init__.py +33 -0
- aria_code/packages/quant_engine/_namespace.py +24 -0
- aria_code/packages/quant_engine/backtest/__init__.py +10 -0
- aria_code/packages/quant_engine/backtest/core.py +53 -0
- aria_code/packages/quant_engine/backtest/engine.py +102 -0
- aria_code/packages/quant_engine/portfolio/__init__.py +9 -0
- aria_code/packages/quant_engine/portfolio/optimizer.py +85 -0
- aria_code/packages/quant_engine/sports/__init__.py +76 -0
- aria_code/packages/quant_engine/sports/calibrator.py +354 -0
- aria_code/packages/quant_engine/sports/dixon_coles.py +234 -0
- aria_code/packages/quant_engine/sports/elo.py +300 -0
- aria_code/packages/quant_engine/sports/form.py +188 -0
- aria_code/packages/quant_engine/sports/h2h.py +195 -0
- aria_code/packages/quant_engine/sports/predictor.py +312 -0
- aria_code/packages/quant_engine/sports/tracker.py +665 -0
- aria_code/packages/quant_engine/stochastic/__init__.py +31 -0
- aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +195 -0
- aria_code/packages/quant_engine/stochastic/ito_calculus.py +477 -0
- aria_code/packages/quant_engine/stochastic/kelly_criterion.py +181 -0
- aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +95 -0
- aria_code/packages/quant_engine/stochastic/options_pricing.py +576 -0
- aria_code/packages/quant_engine/stochastic/stochastic_processes.py +90 -0
- aria_code/packs/__init__.py +85 -0
- aria_code/packs/base.py +168 -0
- aria_code/packs/finance/__init__.py +250 -0
- aria_code/packs/healthcare/__init__.py +40 -0
- aria_code/packs/logistics/__init__.py +171 -0
- aria_code/packs/payments/__init__.py +139 -0
- aria_code/packs/realty/__init__.py +190 -0
- aria_code/packs/registry.py +202 -0
- aria_code/packs/rules.py +90 -0
- aria_code/plan_utils.py +194 -0
- aria_code/plugin_loader.py +328 -0
- aria_code/portfolio_ledger.py +4 -0
- aria_code/preview_server.py +449 -0
- aria_code/privacy/__init__.py +5 -0
- aria_code/privacy/feedback.py +123 -0
- aria_code/project_review.py +278 -0
- aria_code/project_review_api.py +235 -0
- aria_code/project_review_server.py +18 -0
- aria_code/project_tools.py +4 -0
- aria_code/providers/__init__.py +30 -0
- aria_code/providers/google_video_provider.py +256 -0
- aria_code/providers/llm/__init__.py +19 -0
- aria_code/providers/llm/anthropic.py +184 -0
- aria_code/providers/llm/arthera_gateway.py +90 -0
- aria_code/providers/llm/autoconfig.py +213 -0
- aria_code/providers/llm/base.py +139 -0
- aria_code/providers/llm/custom.py +158 -0
- aria_code/providers/llm/ollama.py +137 -0
- aria_code/providers/llm/openai_compat.py +350 -0
- aria_code/providers/llm/registry.py +457 -0
- aria_code/providers/local_image_provider.py +202 -0
- aria_code/providers/local_llm_provider.py +549 -0
- aria_code/providers/ollama_models.py +79 -0
- aria_code/providers/openai_params.py +32 -0
- aria_code/providers/tool_messages.py +100 -0
- aria_code/realty_data_tools.py +4 -0
- aria_code/report_exporters.py +150 -0
- aria_code/report_generator.py +1764 -0
- aria_code/review_service.py +497 -0
- aria_code/runtime/__init__.py +176 -0
- aria_code/runtime/acceptance.py +632 -0
- aria_code/runtime/agent_loop.py +1851 -0
- aria_code/runtime/agent_profiles.py +75 -0
- aria_code/runtime/approval.py +71 -0
- aria_code/runtime/baseline.py +219 -0
- aria_code/runtime/budget.py +232 -0
- aria_code/runtime/checkpoints.py +481 -0
- aria_code/runtime/consult.py +65 -0
- aria_code/runtime/contract.py +282 -0
- aria_code/runtime/delivery.py +432 -0
- aria_code/runtime/events.py +113 -0
- aria_code/runtime/gateway.py +167 -0
- aria_code/runtime/lsp.py +484 -0
- aria_code/runtime/native_index.py +153 -0
- aria_code/runtime/orchestrator.py +55 -0
- aria_code/runtime/processes.py +343 -0
- aria_code/runtime/project_graph.py +614 -0
- aria_code/runtime/repo_map.py +712 -0
- aria_code/runtime/research_bundle.py +105 -0
- aria_code/runtime/review.py +269 -0
- aria_code/runtime/run_state.py +127 -0
- aria_code/runtime/run_store.py +522 -0
- aria_code/runtime/scoped_runs.py +113 -0
- aria_code/runtime/self_healing.py +422 -0
- aria_code/runtime/semantic_diff.py +171 -0
- aria_code/runtime/subagent.py +721 -0
- aria_code/runtime/symbol_edit.py +117 -0
- aria_code/runtime/task_brief.py +46 -0
- aria_code/runtime/task_context.py +145 -0
- aria_code/runtime/task_ledger.py +108 -0
- aria_code/runtime/task_orchestrator.py +90 -0
- aria_code/runtime/task_outcome.py +33 -0
- aria_code/runtime/task_verification.py +266 -0
- aria_code/runtime/task_worktree.py +448 -0
- aria_code/runtime/tool_executor.py +329 -0
- aria_code/runtime/tool_policy.py +107 -0
- aria_code/runtime/transactions.py +216 -0
- aria_code/runtime/windows_job.py +115 -0
- aria_code/runtime/workflows.py +222 -0
- aria_code/runtime/worktrees.py +215 -0
- aria_code/runway_video_client.py +4 -0
- aria_code/safety/__init__.py +27 -0
- aria_code/safety/client_isolation.py +178 -0
- aria_code/safety/permissions.py +339 -0
- aria_code/safety/risk.py +699 -0
- aria_code/safety/sandbox.py +148 -0
- aria_code/safety/service.py +102 -0
- aria_code/service_endpoints.py +14 -0
- aria_code/setup_wizard.py +684 -0
- aria_code/spreadsheet_tools.py +4 -0
- aria_code/strategy_vault.py +4 -0
- aria_code/tools/__init__.py +0 -0
- aria_code/tools/artifact_tools.py +252 -0
- aria_code/tools/broker_tools.py +92 -0
- aria_code/tools/build_quant_engine.py +97 -0
- aria_code/tools/code_audit_tools.py +192 -0
- aria_code/tools/computer_use_tools.py +509 -0
- aria_code/tools/data_analysis_tools.py +831 -0
- aria_code/tools/enterprise_finance_tools.py +202 -0
- aria_code/tools/extended_tools.py +240 -0
- aria_code/tools/file_analysis_tools.py +880 -0
- aria_code/tools/image_gen_tools.py +114 -0
- aria_code/tools/local_finance_tools.py +3488 -0
- aria_code/tools/logistics_carriers.py +11 -0
- aria_code/tools/logistics_inventory.py +11 -0
- aria_code/tools/logistics_io.py +11 -0
- aria_code/tools/logistics_tenancy.py +11 -0
- aria_code/tools/logistics_tools.py +11 -0
- aria_code/tools/macro_tools.py +412 -0
- aria_code/tools/notification_tools.py +249 -0
- aria_code/tools/project_tools.py +525 -0
- aria_code/tools/realty_data_tools.py +662 -0
- aria_code/tools/spreadsheet_tools.py +399 -0
- aria_code/tools/stripe_tools.py +115 -0
- aria_code/tools/video_tools.py +500 -0
- aria_code/training/__init__.py +1 -0
- aria_code/training/compare.py +117 -0
- aria_code/training/prelude_commands.py +111 -0
- aria_code/training/prelude_eval.py +390 -0
- aria_code/training/prelude_real.py +183 -0
- aria_code/training/prelude_train.py +248 -0
- aria_code/training/sft_dataset.py +230 -0
- aria_code/training/trajectory_dataset.py +263 -0
- aria_code/ui/__init__.py +105 -0
- aria_code/ui/banner.py +404 -0
- aria_code/ui/completer.py +571 -0
- aria_code/ui/console.py +285 -0
- aria_code/ui/input_box.py +505 -0
- aria_code/ui/mentions.py +206 -0
- aria_code/ui/picker.py +248 -0
- aria_code/ui/render/__init__.py +11 -0
- aria_code/ui/render/actions.py +297 -0
- aria_code/ui/render/finance.py +1732 -0
- aria_code/ui/render/market.py +253 -0
- aria_code/ui/render/output.py +954 -0
- aria_code/ui/render/responsive.py +75 -0
- aria_code/ui/render/team.py +367 -0
- aria_code/ui/robot.py +239 -0
- aria_code/ui/startup_dashboard.py +110 -0
- aria_code/video_analysis.py +147 -0
- aria_code/video_editor.py +518 -0
- aria_code/video_workflow/__init__.py +8 -0
- aria_code/video_workflow/__main__.py +61 -0
- aria_code/video_workflow/engines/__init__.py +18 -0
- aria_code/video_workflow/engines/base.py +69 -0
- aria_code/video_workflow/engines/custom_model.py +204 -0
- aria_code/video_workflow/engines/google_veo.py +94 -0
- aria_code/video_workflow/engines/local_engine.py +71 -0
- aria_code/video_workflow/engines/registry.py +98 -0
- aria_code/video_workflow/google_models.py +278 -0
- aria_code/video_workflow/music/__init__.py +5 -0
- aria_code/video_workflow/music/foley_service.py +132 -0
- aria_code/video_workflow/music/service.py +212 -0
- aria_code/video_workflow/pipeline.py +620 -0
- aria_code/video_workflow/plan.py +202 -0
- aria_code/video_workflow/session.py +297 -0
- aria_code/workspace/__init__.py +6 -0
- aria_code/workspace/files.py +219 -0
- aria_code/workspace/verify.py +167 -0
- aria_code/workspace_changes.py +199 -0
- aria_code/workspace_service.py +196 -0
- aria_code/workspace_tools.py +150 -0
- aria_code-0.167.0.dist-info/METADATA +330 -0
- aria_code-0.167.0.dist-info/RECORD +601 -0
- aria_code-0.167.0.dist-info/WHEEL +5 -0
- aria_code-0.167.0.dist-info/entry_points.txt +5 -0
- aria_code-0.167.0.dist-info/licenses/LICENSE +201 -0
- aria_code-0.167.0.dist-info/licenses/NOTICE +49 -0
- 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
|