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,322 @@
|
|
|
1
|
+
"""A model scorecard: how each model does on Aria's verifiable tasks, and what routing could save.
|
|
2
|
+
|
|
3
|
+
python3 -m aria_code.evals.scorecard run \\
|
|
4
|
+
--model aria=google/gemini-3.8-flash --model claude=anthropic/claude-sonnet-5-5 \\
|
|
5
|
+
--suite evals/suites/core.yaml --suite evals/suites/operations.yaml --repeat 3 --out scorecard/
|
|
6
|
+
python3 -m aria_code.evals.scorecard run ... --yes # without --yes it only prints the plan
|
|
7
|
+
python3 -m aria_code.evals.scorecard report scorecard/ --cost aria=0.02 --cost claude=0.30
|
|
8
|
+
|
|
9
|
+
Before training a router (or anything else) the question is whether routing is
|
|
10
|
+
worth anything: on the tasks Aria is actually given, does a cheaper model succeed
|
|
11
|
+
often enough that sending it there beats always using the strongest one? Nobody
|
|
12
|
+
knows until the same tasks have been run on several models and checked by the same
|
|
13
|
+
verifiers. This does that, keeps each run's trajectories (the first training
|
|
14
|
+
material), and answers the question with a number.
|
|
15
|
+
|
|
16
|
+
The routing figure is an upper bound. It assumes the router knows in advance which
|
|
17
|
+
model will pass; a real one has to guess, and a failed cheap attempt costs money
|
|
18
|
+
before the strong model starts. If even the upper bound is small, a learned router
|
|
19
|
+
is not worth building.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import argparse
|
|
25
|
+
import json
|
|
26
|
+
import math
|
|
27
|
+
import subprocess
|
|
28
|
+
import sys
|
|
29
|
+
from pathlib import Path
|
|
30
|
+
from typing import Dict, List, Mapping, Optional, Sequence, Tuple
|
|
31
|
+
|
|
32
|
+
#: A model "passes" a task when it passes at least this share of its scored attempts.
|
|
33
|
+
PASS_SHARE = 0.5
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def wilson(passed: int, scored: int, z: float = 1.96) -> Tuple[float, float]:
|
|
37
|
+
"""95% Wilson interval for a pass rate; (0, 1) when nothing was scored."""
|
|
38
|
+
if scored <= 0:
|
|
39
|
+
return 0.0, 1.0
|
|
40
|
+
p = passed / scored
|
|
41
|
+
denom = 1 + z * z / scored
|
|
42
|
+
centre = (p + z * z / (2 * scored)) / denom
|
|
43
|
+
half = z * math.sqrt(p * (1 - p) / scored + z * z / (4 * scored * scored)) / denom
|
|
44
|
+
return max(0.0, centre - half), min(1.0, centre + half)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def parse_labelled(items: Sequence[str], what: str) -> Dict[str, str]:
|
|
48
|
+
"""`["aria=google/x", "claude=anthropic/y"]` as an ordered {label: value}."""
|
|
49
|
+
out: Dict[str, str] = {}
|
|
50
|
+
for item in items:
|
|
51
|
+
label, sep, value = item.partition("=")
|
|
52
|
+
if not sep or not label.strip() or not value.strip():
|
|
53
|
+
raise ValueError(f"{what} must look like label=value, got {item!r}")
|
|
54
|
+
out[label.strip()] = value.strip()
|
|
55
|
+
return out
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def load_reports(root: Path) -> Dict[str, Dict[str, dict]]:
|
|
59
|
+
"""`root/<label>/<suite>.json` as {label: {suite: report}}, labels in directory order."""
|
|
60
|
+
reports: Dict[str, Dict[str, dict]] = {}
|
|
61
|
+
for label_dir in sorted(p for p in Path(root).iterdir() if p.is_dir()):
|
|
62
|
+
for path in sorted(label_dir.glob("*.json")):
|
|
63
|
+
try:
|
|
64
|
+
data = json.loads(path.read_text(encoding="utf-8"))
|
|
65
|
+
except (OSError, ValueError):
|
|
66
|
+
continue
|
|
67
|
+
if isinstance(data, dict) and "results" in data:
|
|
68
|
+
reports.setdefault(label_dir.name, {})[str(data.get("suite") or path.stem)] = data
|
|
69
|
+
return reports
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _scored(result: Mapping) -> bool:
|
|
73
|
+
return str(result.get("outcome", "")).lower() in ("pass", "fail")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def model_stats(by_suite: Mapping[str, dict]) -> dict:
|
|
77
|
+
"""Overall and per-domain (tag) numbers for one model across the suites it ran."""
|
|
78
|
+
passed = scored = errored = invalid = timed_out = 0
|
|
79
|
+
seconds: List[float] = []
|
|
80
|
+
domains: Dict[str, List[int]] = {}
|
|
81
|
+
for report in by_suite.values():
|
|
82
|
+
for result in report.get("results") or []:
|
|
83
|
+
outcome = str(result.get("outcome", "")).lower()
|
|
84
|
+
errored += outcome == "error"
|
|
85
|
+
timed_out += outcome == "error" and bool(result.get("timed_out"))
|
|
86
|
+
invalid += outcome == "invalid"
|
|
87
|
+
if not _scored(result):
|
|
88
|
+
continue
|
|
89
|
+
scored += 1
|
|
90
|
+
passed += outcome == "pass"
|
|
91
|
+
seconds.append(float(result.get("seconds") or 0))
|
|
92
|
+
for tag in result.get("tags") or []:
|
|
93
|
+
stats = domains.setdefault(str(tag), [0, 0])
|
|
94
|
+
stats[0] += outcome == "pass"
|
|
95
|
+
stats[1] += 1
|
|
96
|
+
low, high = wilson(passed, scored)
|
|
97
|
+
return {
|
|
98
|
+
"passed": passed, "scored": scored, "errored": errored, "invalid": invalid,
|
|
99
|
+
"timed_out": timed_out,
|
|
100
|
+
"pass_rate": passed / scored if scored else 0.0, "ci95": (low, high),
|
|
101
|
+
"mean_seconds": sum(seconds) / len(seconds) if seconds else 0.0,
|
|
102
|
+
"domains": {tag: {"passed": p, "scored": n, "pass_rate": p / n if n else 0.0}
|
|
103
|
+
for tag, (p, n) in sorted(domains.items())},
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def task_matrix(reports: Mapping[str, Mapping[str, dict]]) -> Dict[str, Dict[str, Tuple[int, int]]]:
|
|
108
|
+
"""{"suite/task": {label: (passed, scored)}} over every attempt of every model."""
|
|
109
|
+
matrix: Dict[str, Dict[str, List[int]]] = {}
|
|
110
|
+
for label, by_suite in reports.items():
|
|
111
|
+
for suite, report in by_suite.items():
|
|
112
|
+
for result in report.get("results") or []:
|
|
113
|
+
if not _scored(result):
|
|
114
|
+
continue
|
|
115
|
+
cell = matrix.setdefault(f"{suite}/{result.get('task_id')}", {}).setdefault(label, [0, 0])
|
|
116
|
+
cell[0] += str(result.get("outcome", "")).lower() == "pass"
|
|
117
|
+
cell[1] += 1
|
|
118
|
+
return {task: {label: (p, n) for label, (p, n) in cells.items()} for task, cells in matrix.items()}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def passes(cell: Optional[Tuple[int, int]]) -> bool:
|
|
122
|
+
return bool(cell) and cell[1] > 0 and cell[0] / cell[1] >= PASS_SHARE
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def routing_analysis(matrix: Mapping[str, Mapping[str, Tuple[int, int]]], order: Sequence[str],
|
|
126
|
+
costs: Optional[Mapping[str, float]] = None, strong: str = "") -> dict:
|
|
127
|
+
"""What an oracle router would have scored and spent, against always using one model.
|
|
128
|
+
|
|
129
|
+
`order` is cheapest first (or by `costs` when given). The oracle sends each task
|
|
130
|
+
to the cheapest model that passes it; `strong` (default: the model with the best
|
|
131
|
+
pass rate) is the always-use-it baseline. Costs are per task attempt, supplied by
|
|
132
|
+
the caller, because the eval reports do not carry token counts.
|
|
133
|
+
"""
|
|
134
|
+
labels = sorted({l for cells in matrix.values() for l in cells}, key=lambda l: (
|
|
135
|
+
(costs or {}).get(l, float("inf")) if costs else 0.0, list(order).index(l) if l in order else len(order)))
|
|
136
|
+
if not labels or not matrix:
|
|
137
|
+
return {}
|
|
138
|
+
rates = {l: sum(passes(cells.get(l)) for cells in matrix.values()) for l in labels}
|
|
139
|
+
strong = strong if strong in labels else max(labels, key=lambda l: (rates[l], -labels.index(l)))
|
|
140
|
+
cost = lambda l: float((costs or {}).get(l, 0.0)) # noqa: E731
|
|
141
|
+
chosen: Dict[str, str] = {}
|
|
142
|
+
for task, cells in matrix.items():
|
|
143
|
+
for label in labels:
|
|
144
|
+
if passes(cells.get(label)):
|
|
145
|
+
chosen[task] = label
|
|
146
|
+
break
|
|
147
|
+
tasks = len(matrix)
|
|
148
|
+
# A task nobody solved still gets tried on the strongest model, so it is charged there.
|
|
149
|
+
oracle_cost = sum(cost(l) for l in chosen.values()) + cost(strong) * (tasks - len(chosen))
|
|
150
|
+
strong_solved = sum(passes(cells.get(strong)) for cells in matrix.values())
|
|
151
|
+
by_label: Dict[str, int] = {}
|
|
152
|
+
for label in chosen.values():
|
|
153
|
+
by_label[label] = by_label.get(label, 0) + 1
|
|
154
|
+
return {
|
|
155
|
+
"tasks": tasks, "strong": strong, "order": labels,
|
|
156
|
+
"strong_solved": strong_solved, "oracle_solved": len(chosen),
|
|
157
|
+
"strong_cost": cost(strong) * tasks, "oracle_cost": oracle_cost,
|
|
158
|
+
"sent_to": dict(sorted(by_label.items(), key=lambda kv: labels.index(kv[0]))),
|
|
159
|
+
"unsolved": sorted(t for t in matrix if t not in chosen),
|
|
160
|
+
"only_one_model": sorted(t for t, cells in matrix.items() if sum(passes(c) for c in cells.values()) == 1),
|
|
161
|
+
"has_costs": bool(costs),
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def render_markdown(reports: Mapping[str, Mapping[str, dict]], costs: Optional[Mapping[str, float]] = None,
|
|
166
|
+
strong: str = "") -> str:
|
|
167
|
+
stats = {label: model_stats(by_suite) for label, by_suite in reports.items()}
|
|
168
|
+
domains = sorted({d for s in stats.values() for d in s["domains"]})
|
|
169
|
+
lines = ["## Model scorecard", "",
|
|
170
|
+
"| Model | Pass rate | 95% CI | Scored | Not scored | Timed out | Mean seconds |",
|
|
171
|
+
"|---|---:|---:|---:|---:|---:|---:|"]
|
|
172
|
+
for label, s in stats.items():
|
|
173
|
+
low, high = s["ci95"]
|
|
174
|
+
lines.append(f"| {label} | {s['pass_rate']:.0%} | {low:.0%}–{high:.0%} | {s['scored']} | "
|
|
175
|
+
f"{s['errored'] + s['invalid']} | {s['timed_out']} | {s['mean_seconds']:.0f} |")
|
|
176
|
+
if domains:
|
|
177
|
+
lines += ["", "### By domain", "", "| Model | " + " | ".join(domains) + " |", "|---|" + "---:|" * len(domains)]
|
|
178
|
+
for label, s in stats.items():
|
|
179
|
+
cells = [f"{s['domains'][d]['passed']}/{s['domains'][d]['scored']}" if d in s["domains"] else "-" for d in domains]
|
|
180
|
+
lines.append(f"| {label} | " + " | ".join(cells) + " |")
|
|
181
|
+
analysis = routing_analysis(task_matrix(reports), list(reports), costs, strong)
|
|
182
|
+
if analysis:
|
|
183
|
+
n = analysis["tasks"]
|
|
184
|
+
lines += ["", "### Would routing pay?", "",
|
|
185
|
+
f"{n} tasks. Always `{analysis['strong']}`: {analysis['strong_solved']}/{n} solved. "
|
|
186
|
+
f"An oracle that sends each task to the cheapest model that passes it: {analysis['oracle_solved']}/{n} solved."]
|
|
187
|
+
if analysis["sent_to"]:
|
|
188
|
+
lines.append("Sent to: " + ", ".join(f"{label} {count}" for label, count in analysis["sent_to"].items()) + ".")
|
|
189
|
+
if analysis["has_costs"]:
|
|
190
|
+
saved = analysis["strong_cost"] - analysis["oracle_cost"]
|
|
191
|
+
share = saved / analysis["strong_cost"] if analysis["strong_cost"] else 0.0
|
|
192
|
+
lines.append(f"Cost per run of all tasks: ${analysis['strong_cost']:.2f} always-strong vs "
|
|
193
|
+
f"${analysis['oracle_cost']:.2f} oracle ({share:.0%} less).")
|
|
194
|
+
else:
|
|
195
|
+
lines.append("No `--cost` given, so no spend comparison; add `--cost label=USD_per_task`.")
|
|
196
|
+
if analysis["only_one_model"]:
|
|
197
|
+
lines.append("Passed by exactly one model (where choosing matters): " + ", ".join(analysis["only_one_model"][:12]) + ".")
|
|
198
|
+
if analysis["unsolved"]:
|
|
199
|
+
lines.append("Solved by none: " + ", ".join(analysis["unsolved"][:12]) + ".")
|
|
200
|
+
lines += ["", "This is an upper bound: the oracle knows which model will pass before trying, "
|
|
201
|
+
"and a real router pays for the cheap attempts that fail. If it is small here, "
|
|
202
|
+
"a learned router will not recover it."]
|
|
203
|
+
return "\n".join(lines) + "\n"
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
# ── running ──────────────────────────────────────────────────────────────────
|
|
207
|
+
|
|
208
|
+
def plan(models: Mapping[str, str], suites: Sequence[str], repeat: int, out: Path, force: bool) -> List[dict]:
|
|
209
|
+
"""Every (model, suite) run to make, skipping the ones already reported unless forced."""
|
|
210
|
+
jobs = []
|
|
211
|
+
for label, model in models.items():
|
|
212
|
+
for suite in suites:
|
|
213
|
+
report = Path(out) / label / f"{Path(suite).stem}.json"
|
|
214
|
+
jobs.append({"label": label, "model": model, "suite": suite, "report": report,
|
|
215
|
+
"skip": report.exists() and not force})
|
|
216
|
+
return jobs
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def task_ids(suite: str) -> List[str]:
|
|
220
|
+
from .harness import load_suite
|
|
221
|
+
|
|
222
|
+
return [str(task.id) for task in load_suite(Path(suite))[1]]
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def task_count(suite: str) -> int:
|
|
226
|
+
return len(task_ids(suite))
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def unknown_tasks(suites: Sequence[str], only: Sequence[str]) -> List[str]:
|
|
230
|
+
"""Ids in `only` that no named suite contains. The runner would run nothing and
|
|
231
|
+
report 0/0, which reads as a result; a typo has to be an error instead."""
|
|
232
|
+
known = {tid for suite in suites for tid in task_ids(suite)}
|
|
233
|
+
return [tid for tid in only if tid not in known]
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def command_for(job: Mapping, repeat: int, out: Path, timeout: int, runtime: str, only: Sequence[str],
|
|
237
|
+
local: Sequence[str] = ()) -> List[str]:
|
|
238
|
+
command = [sys.executable, "-m", "aria_code.evals.runner", str(job["suite"]), "--model", job["model"],
|
|
239
|
+
"--repeat", str(repeat), "--report", str(job["report"]), "--solve-timeout", str(timeout),
|
|
240
|
+
"--trajectories", str(Path(out) / job["label"] / "trajectories")]
|
|
241
|
+
if runtime != "python":
|
|
242
|
+
command.extend(["--runtime", runtime])
|
|
243
|
+
if job["label"] in local:
|
|
244
|
+
command.append("--local") # Ollama only, no cloud: for a model on this machine
|
|
245
|
+
if only:
|
|
246
|
+
command.extend(["--only", *only])
|
|
247
|
+
return command
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
251
|
+
parser = argparse.ArgumentParser(prog="aria-scorecard", description=__doc__,
|
|
252
|
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
253
|
+
sub = parser.add_subparsers(dest="action", required=True)
|
|
254
|
+
run = sub.add_parser("run", help="run the suites on several models (prints the plan unless --yes)")
|
|
255
|
+
run.add_argument("--model", action="append", default=[], metavar="LABEL=MODEL", help="repeatable, cheapest first")
|
|
256
|
+
run.add_argument("--suite", action="append", default=[], metavar="PATH", help="repeatable")
|
|
257
|
+
run.add_argument("--repeat", type=int, default=3)
|
|
258
|
+
run.add_argument("--out", default="scorecard")
|
|
259
|
+
run.add_argument("--only", nargs="*", default=[], help="limit to these task ids (a smoke test)")
|
|
260
|
+
run.add_argument("--solve-timeout", type=int, default=900)
|
|
261
|
+
run.add_argument("--runtime", choices=("python", "native"), default="python")
|
|
262
|
+
run.add_argument("--local", action="append", default=[], metavar="LABEL",
|
|
263
|
+
help="run this label's model on this machine (Ollama), free; repeatable")
|
|
264
|
+
run.add_argument("--force", action="store_true", help="redo runs that already have a report")
|
|
265
|
+
run.add_argument("--yes", action="store_true", help="actually run; this calls the models and costs money")
|
|
266
|
+
rep = sub.add_parser("report", help="summarise the reports under a folder")
|
|
267
|
+
rep.add_argument("root")
|
|
268
|
+
rep.add_argument("--cost", action="append", default=[], metavar="LABEL=USD", help="estimated USD per task attempt")
|
|
269
|
+
rep.add_argument("--strong", default="", help="the always-use baseline (default: the best pass rate)")
|
|
270
|
+
args = parser.parse_args(argv)
|
|
271
|
+
|
|
272
|
+
try:
|
|
273
|
+
if args.action == "report":
|
|
274
|
+
costs = {k: float(v) for k, v in parse_labelled(args.cost, "--cost").items()}
|
|
275
|
+
reports = load_reports(Path(args.root))
|
|
276
|
+
if not reports:
|
|
277
|
+
print(f"no reports under {args.root}", file=sys.stderr)
|
|
278
|
+
return 2
|
|
279
|
+
print(render_markdown(reports, costs or None, args.strong))
|
|
280
|
+
return 0
|
|
281
|
+
models = parse_labelled(args.model, "--model")
|
|
282
|
+
except ValueError as exc:
|
|
283
|
+
print(str(exc), file=sys.stderr)
|
|
284
|
+
return 2
|
|
285
|
+
if not models or not args.suite:
|
|
286
|
+
print("give at least one --model and one --suite", file=sys.stderr)
|
|
287
|
+
return 2
|
|
288
|
+
missing = unknown_tasks(args.suite, args.only)
|
|
289
|
+
if missing:
|
|
290
|
+
print(f"no such task in the suites: {', '.join(missing)}", file=sys.stderr)
|
|
291
|
+
return 2
|
|
292
|
+
out = Path(args.out)
|
|
293
|
+
jobs = plan(models, args.suite, args.repeat, out, args.force)
|
|
294
|
+
attempts = 0
|
|
295
|
+
print(f"\n{len(models)} model(s) x {len(args.suite)} suite(s), {args.repeat} attempt(s) per task:")
|
|
296
|
+
for job in jobs:
|
|
297
|
+
tasks = len(args.only) if args.only else task_count(job["suite"])
|
|
298
|
+
calls = tasks * args.repeat
|
|
299
|
+
attempts += 0 if job["skip"] else calls
|
|
300
|
+
print(f" {job['label']:<12} {Path(job['suite']).stem:<12} {tasks} tasks x {args.repeat} = {calls} agent runs"
|
|
301
|
+
f"{' (already done, skipped)' if job['skip'] else ''}")
|
|
302
|
+
print(f"\n{attempts} agent runs in all. Each is a full coding session on the model, so this spends real money.")
|
|
303
|
+
if not args.yes:
|
|
304
|
+
print("Nothing was run. Add --yes to run it (try --only <task-id> first as a smoke test).")
|
|
305
|
+
return 0
|
|
306
|
+
failures = 0
|
|
307
|
+
for job in jobs:
|
|
308
|
+
if job["skip"]:
|
|
309
|
+
continue
|
|
310
|
+
Path(job["report"]).parent.mkdir(parents=True, exist_ok=True)
|
|
311
|
+
print(f"\n== {job['label']} · {Path(job['suite']).stem}")
|
|
312
|
+
# A task the model gets wrong exits 1; only a runner that could not start is a failure here.
|
|
313
|
+
done = subprocess.run(command_for(job, args.repeat, out, args.solve_timeout, args.runtime, args.only, args.local), check=False)
|
|
314
|
+
if done.returncode not in (0, 1) or not Path(job["report"]).exists():
|
|
315
|
+
failures += 1
|
|
316
|
+
print(f"!! {job['label']} · {Path(job['suite']).stem} did not produce a report (exit {done.returncode})")
|
|
317
|
+
print(f"\nnext: python3 -m aria_code.evals.scorecard report {out}")
|
|
318
|
+
return 1 if failures else 0
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
if __name__ == "__main__":
|
|
322
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""Turn eval reports into a Markdown scoreboard, and decide whether the run is healthy.
|
|
2
|
+
|
|
3
|
+
python3 -m aria_code.evals.summary evals-core.json evals-operations.json [--private evals-holdout.json]
|
|
4
|
+
|
|
5
|
+
Each suite's score comes with the mean per-task pass rate and its standard
|
|
6
|
+
error, so two runs can be told apart from noise. A report passed after
|
|
7
|
+
``--private`` (the holdout suites, kept in a private repository) is shown as
|
|
8
|
+
counts only: no task ids, details or logs, because the summary is public.
|
|
9
|
+
|
|
10
|
+
The suites ran in CI only with ``--check``: every fixture still starts red,
|
|
11
|
+
but no model ever attempted them, so nothing measured whether Aria can fix
|
|
12
|
+
code. The weekly workflow (.github/workflows/evals.yml) runs them with a real
|
|
13
|
+
model and writes this summary.
|
|
14
|
+
|
|
15
|
+
A task the model gets wrong is a result, not a broken build: the exit code is
|
|
16
|
+
1 only when a task could not run (ERROR) or no longer measures anything
|
|
17
|
+
(INVALID), the two outcomes that mean the harness, not the model, needs work.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import json
|
|
23
|
+
import math
|
|
24
|
+
import sys
|
|
25
|
+
from collections import defaultdict
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def mean_sem(report: dict) -> tuple[float, float, int] | None:
|
|
30
|
+
"""Mean per-task pass rate over scored attempts, its standard error, and the task count."""
|
|
31
|
+
passed: dict[str, int] = defaultdict(int)
|
|
32
|
+
scored: dict[str, int] = defaultdict(int)
|
|
33
|
+
for r in report.get("results") or []:
|
|
34
|
+
if str(r.get("outcome", "")).lower() in ("pass", "fail"):
|
|
35
|
+
scored[str(r.get("task_id"))] += 1
|
|
36
|
+
passed[str(r.get("task_id"))] += str(r.get("outcome")).lower() == "pass"
|
|
37
|
+
rates = [passed[t] / scored[t] for t in scored]
|
|
38
|
+
if not rates:
|
|
39
|
+
return None
|
|
40
|
+
mean = sum(rates) / len(rates)
|
|
41
|
+
if len(rates) < 2:
|
|
42
|
+
return mean, 0.0, 1
|
|
43
|
+
var = sum((x - mean) ** 2 for x in rates) / (len(rates) - 1)
|
|
44
|
+
return mean, math.sqrt(var / len(rates)), len(rates)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def summarise(reports: list[dict], model: str = "", private: list[dict] | None = None) -> tuple[str, int]:
|
|
48
|
+
"""Markdown for the reports, and the exit code the run should have."""
|
|
49
|
+
lines = [f"## Aria eval scoreboard{f' · {model}' if model else ''}", ""]
|
|
50
|
+
unhealthy = 0
|
|
51
|
+
for report in [*reports, *(private or [])]:
|
|
52
|
+
is_private = any(report is p for p in private or [])
|
|
53
|
+
suite = report.get("suite", "?")
|
|
54
|
+
lines.append(f"### {suite}{' (holdout)' if is_private else ''}: "
|
|
55
|
+
f"{report.get('passed', 0)}/{report.get('scored', 0)} ({report.get('pass_rate', 0):.0%})")
|
|
56
|
+
stats = mean_sem(report)
|
|
57
|
+
if stats:
|
|
58
|
+
mean, sem, n = stats
|
|
59
|
+
lines.append(f"Mean task pass rate {mean:.0%} ± {sem:.0%} (SEM over {n} task{'s' if n != 1 else ''}).")
|
|
60
|
+
extras = [f"{report[k]} {k}" for k in ("errored", "invalid") if report.get(k)]
|
|
61
|
+
if report.get("timed_out"):
|
|
62
|
+
# Timeouts are ERROR and drop out of the rate; say how many, or a
|
|
63
|
+
# suite where most attempts timed out reads like a high score.
|
|
64
|
+
extras.append(f"{report['timed_out']} of the errors timed out")
|
|
65
|
+
if extras:
|
|
66
|
+
lines.append(f"Not scored: {', '.join(extras)}.")
|
|
67
|
+
unhealthy += int(report.get("errored", 0)) + int(report.get("invalid", 0))
|
|
68
|
+
if is_private:
|
|
69
|
+
lines += ["Task ids, details and logs are not published for holdout suites.", ""]
|
|
70
|
+
continue
|
|
71
|
+
lines += ["", "| Task | Outcome | Seconds | Detail |", "|---|---|---:|---|"]
|
|
72
|
+
for result in report.get("results", []):
|
|
73
|
+
detail = str(result.get("detail") or "").replace("|", "\\|")[:120]
|
|
74
|
+
lines.append(f"| {result.get('task_id')} | {result.get('outcome')} | "
|
|
75
|
+
f"{result.get('seconds', 0):.0f} | {detail} |")
|
|
76
|
+
for result in report.get("results", []):
|
|
77
|
+
tail = result.get("log_tail") or []
|
|
78
|
+
if tail and str(result.get("outcome", "")).lower() != "pass":
|
|
79
|
+
body = "\n".join(tail).replace("```", "` ` `")
|
|
80
|
+
lines += ["", f"<details><summary>{result.get('task_id')}: last lines of the log</summary>",
|
|
81
|
+
"", "```", body, "```", "</details>"]
|
|
82
|
+
checks = report.get("behavior") or {}
|
|
83
|
+
if checks:
|
|
84
|
+
lines += ["", "| Behaviour check | Passed |", "|---|---:|"]
|
|
85
|
+
lines += [f"| {name.replace('|', '/')} | {s['passed']}/{s['runs']} |" for name, s in checks.items()]
|
|
86
|
+
by_tag = report.get("by_tag") or {}
|
|
87
|
+
if by_tag:
|
|
88
|
+
tags = ", ".join(f"{tag} {s['passed']}/{s['scored']}" for tag, s in by_tag.items() if s.get("scored"))
|
|
89
|
+
if tags:
|
|
90
|
+
lines += ["", f"By tag: {tags}"]
|
|
91
|
+
lines.append("")
|
|
92
|
+
return "\n".join(lines), (1 if unhealthy else 0)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def main(argv: list[str] | None = None) -> int:
|
|
96
|
+
args = list(sys.argv[1:] if argv is None else argv)
|
|
97
|
+
model = ""
|
|
98
|
+
if args[:1] == ["--model"] and len(args) > 1:
|
|
99
|
+
model, args = args[1], args[2:]
|
|
100
|
+
public_names, private_names = args, []
|
|
101
|
+
if "--private" in args:
|
|
102
|
+
i = args.index("--private")
|
|
103
|
+
public_names, private_names = args[:i], args[i + 1:]
|
|
104
|
+
|
|
105
|
+
def load(names: list[str]) -> list[dict]:
|
|
106
|
+
out = []
|
|
107
|
+
for name in names:
|
|
108
|
+
path = Path(name)
|
|
109
|
+
if path.exists():
|
|
110
|
+
out.append(json.loads(path.read_text(encoding="utf-8")))
|
|
111
|
+
else:
|
|
112
|
+
print(f"(no report at {name})", file=sys.stderr)
|
|
113
|
+
return out
|
|
114
|
+
|
|
115
|
+
reports, private = load(public_names), load(private_names)
|
|
116
|
+
if not reports and not private:
|
|
117
|
+
print("no eval reports to summarise", file=sys.stderr)
|
|
118
|
+
return 1
|
|
119
|
+
text, code = summarise(reports, model, private)
|
|
120
|
+
print(text)
|
|
121
|
+
return code
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
if __name__ == "__main__":
|
|
125
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Delegate a task to the Claude Code or Codex CLI as an external headless agent.
|
|
2
|
+
|
|
3
|
+
Complements runtime/subagent.py's spawn_task system: by default a spawned
|
|
4
|
+
task runs inside aria-code's own LLM loop, but a task can instead be
|
|
5
|
+
delegated to another agentic coding CLI already installed on the machine
|
|
6
|
+
(``backend="claude"`` / ``backend="codex"``), reusing whatever coding
|
|
7
|
+
capability that tool has. Both runners return plain text — a success/failure
|
|
8
|
+
string, never a raised exception — so a missing binary or a CLI-side failure
|
|
9
|
+
degrades the same way a normal subagent failure does (task.status="failed"
|
|
10
|
+
with .error set), and never crashes the background task loop.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import asyncio
|
|
16
|
+
import json
|
|
17
|
+
import shutil
|
|
18
|
+
from typing import Optional
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
async def _run_cli(
|
|
22
|
+
binary: str,
|
|
23
|
+
args: list[str],
|
|
24
|
+
*,
|
|
25
|
+
cwd: Optional[str],
|
|
26
|
+
timeout: float,
|
|
27
|
+
) -> tuple[bool, str]:
|
|
28
|
+
"""Run one CLI invocation. Returns (ok, text) — never raises."""
|
|
29
|
+
if not shutil.which(binary):
|
|
30
|
+
return False, f"{binary} CLI not found on PATH. Install it first."
|
|
31
|
+
try:
|
|
32
|
+
proc = await asyncio.create_subprocess_exec(
|
|
33
|
+
binary, *args,
|
|
34
|
+
cwd=cwd,
|
|
35
|
+
stdout=asyncio.subprocess.PIPE,
|
|
36
|
+
stderr=asyncio.subprocess.PIPE,
|
|
37
|
+
)
|
|
38
|
+
except Exception as exc:
|
|
39
|
+
return False, f"Failed to launch {binary}: {exc}"
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=timeout)
|
|
43
|
+
except asyncio.TimeoutError:
|
|
44
|
+
proc.kill()
|
|
45
|
+
return False, f"{binary} CLI timed out after {timeout:.0f}s."
|
|
46
|
+
|
|
47
|
+
out_text = stdout.decode("utf-8", errors="replace")
|
|
48
|
+
if proc.returncode != 0:
|
|
49
|
+
err_text = stderr.decode("utf-8", errors="replace")[:500]
|
|
50
|
+
return False, f"{binary} CLI exited {proc.returncode}: {err_text or out_text[:500]}"
|
|
51
|
+
return True, out_text
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _extract_json_result(raw: str, *keys: str) -> str:
|
|
55
|
+
"""Best-effort pull of the human-readable result out of a CLI's JSON output.
|
|
56
|
+
|
|
57
|
+
Both CLIs' exact JSON shapes can vary by version, so this tries each
|
|
58
|
+
candidate key and falls back to the raw text — a schema drift should
|
|
59
|
+
degrade to "less clean output", not a crash or an empty result.
|
|
60
|
+
"""
|
|
61
|
+
raw = raw.strip()
|
|
62
|
+
if not raw:
|
|
63
|
+
return "(no output)"
|
|
64
|
+
try:
|
|
65
|
+
data = json.loads(raw)
|
|
66
|
+
except json.JSONDecodeError:
|
|
67
|
+
return raw
|
|
68
|
+
if isinstance(data, dict):
|
|
69
|
+
for key in keys:
|
|
70
|
+
value = data.get(key)
|
|
71
|
+
if isinstance(value, str) and value:
|
|
72
|
+
return value
|
|
73
|
+
return raw
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
async def run_claude_code_headless(
|
|
77
|
+
prompt: str,
|
|
78
|
+
*,
|
|
79
|
+
cwd: Optional[str] = None,
|
|
80
|
+
timeout: float = 600.0,
|
|
81
|
+
) -> str:
|
|
82
|
+
"""Delegate `prompt` to `claude -p` (Claude Code headless mode)."""
|
|
83
|
+
ok, text = await _run_cli(
|
|
84
|
+
"claude",
|
|
85
|
+
["-p", prompt, "--output-format", "json"],
|
|
86
|
+
cwd=cwd,
|
|
87
|
+
timeout=timeout,
|
|
88
|
+
)
|
|
89
|
+
if not ok:
|
|
90
|
+
return f"错误: {text}"
|
|
91
|
+
return _extract_json_result(text, "result", "response")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
async def run_codex_headless(
|
|
95
|
+
prompt: str,
|
|
96
|
+
*,
|
|
97
|
+
cwd: Optional[str] = None,
|
|
98
|
+
timeout: float = 600.0,
|
|
99
|
+
) -> str:
|
|
100
|
+
"""Delegate `prompt` to `codex exec` (OpenAI Codex CLI headless mode)."""
|
|
101
|
+
ok, text = await _run_cli(
|
|
102
|
+
"codex",
|
|
103
|
+
["exec", prompt, "--json"],
|
|
104
|
+
cwd=cwd,
|
|
105
|
+
timeout=timeout,
|
|
106
|
+
)
|
|
107
|
+
if not ok:
|
|
108
|
+
return f"错误: {text}"
|
|
109
|
+
return _extract_json_result(text, "result", "message", "output")
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
RUNNERS = {
|
|
113
|
+
"claude": run_claude_code_headless,
|
|
114
|
+
"codex": run_codex_headless,
|
|
115
|
+
}
|