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,115 @@
|
|
|
1
|
+
"""Keep a Windows background command's descendants in one owned Job Object.
|
|
2
|
+
|
|
3
|
+
Lazy-imported only on Windows. Closing the last handle kills descendants,
|
|
4
|
+
including those still running after the command's original parent exited.
|
|
5
|
+
This manages lifetime; it is not a filesystem/network sandbox.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import ctypes as c
|
|
10
|
+
from ctypes import wintypes as w
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class _Limits(c.Structure):
|
|
14
|
+
_fields_ = [("process_time", c.c_longlong), ("job_time", c.c_longlong),
|
|
15
|
+
("flags", w.DWORD), ("min_working", c.c_size_t), ("max_working", c.c_size_t),
|
|
16
|
+
("active_limit", w.DWORD), ("affinity", c.c_size_t),
|
|
17
|
+
("priority", w.DWORD), ("scheduling", w.DWORD)]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class _IOCounters(c.Structure):
|
|
21
|
+
_fields_ = [(name, c.c_ulonglong) for name in ("read_ops", "write_ops", "other_ops",
|
|
22
|
+
"read_bytes", "write_bytes", "other_bytes")]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class _ExtendedLimits(c.Structure):
|
|
26
|
+
_fields_ = [("basic", _Limits), ("io", _IOCounters), ("process_memory", c.c_size_t),
|
|
27
|
+
("job_memory", c.c_size_t), ("peak_process_memory", c.c_size_t),
|
|
28
|
+
("peak_job_memory", c.c_size_t)]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class _Accounting(c.Structure):
|
|
32
|
+
_fields_ = [(name, c.c_longlong) for name in ("user_time", "kernel_time", "period_user", "period_kernel")]
|
|
33
|
+
_fields_ += [(name, w.DWORD) for name in ("page_faults", "total", "active", "terminated")]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class _ThreadEntry(c.Structure):
|
|
37
|
+
_fields_ = [("size", w.DWORD), ("usage", w.DWORD), ("thread_id", w.DWORD),
|
|
38
|
+
("owner_pid", w.DWORD), ("priority", w.LONG), ("delta", w.LONG), ("flags", w.DWORD)]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class WindowsJob:
|
|
42
|
+
def __init__(self, popen):
|
|
43
|
+
self.api = c.WinDLL("kernel32", use_last_error=True)
|
|
44
|
+
signatures = {
|
|
45
|
+
"CreateJobObjectW": ([c.c_void_p, w.LPCWSTR], w.HANDLE),
|
|
46
|
+
"SetInformationJobObject": ([w.HANDLE, c.c_int, c.c_void_p, w.DWORD], w.BOOL),
|
|
47
|
+
"AssignProcessToJobObject": ([w.HANDLE, w.HANDLE], w.BOOL),
|
|
48
|
+
"QueryInformationJobObject": ([w.HANDLE, c.c_int, c.c_void_p, w.DWORD, c.c_void_p], w.BOOL),
|
|
49
|
+
"TerminateJobObject": ([w.HANDLE, w.UINT], w.BOOL),
|
|
50
|
+
"CloseHandle": ([w.HANDLE], w.BOOL),
|
|
51
|
+
"CreateToolhelp32Snapshot": ([w.DWORD, w.DWORD], w.HANDLE),
|
|
52
|
+
"Thread32First": ([w.HANDLE, c.POINTER(_ThreadEntry)], w.BOOL),
|
|
53
|
+
"Thread32Next": ([w.HANDLE, c.POINTER(_ThreadEntry)], w.BOOL),
|
|
54
|
+
"OpenThread": ([w.DWORD, w.BOOL, w.DWORD], w.HANDLE),
|
|
55
|
+
"ResumeThread": ([w.HANDLE], w.DWORD),
|
|
56
|
+
}
|
|
57
|
+
for name, (args, result) in signatures.items():
|
|
58
|
+
fn = getattr(self.api, name)
|
|
59
|
+
fn.argtypes, fn.restype = args, result
|
|
60
|
+
self.handle = self.api.CreateJobObjectW(None, None)
|
|
61
|
+
if not self.handle:
|
|
62
|
+
raise c.WinError(c.get_last_error())
|
|
63
|
+
try:
|
|
64
|
+
limits = _ExtendedLimits()
|
|
65
|
+
limits.basic.flags = 0x2000 # JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
|
|
66
|
+
if not self.api.SetInformationJobObject(self.handle, 9, c.byref(limits), c.sizeof(limits)):
|
|
67
|
+
raise c.WinError(c.get_last_error())
|
|
68
|
+
if not self.api.AssignProcessToJobObject(self.handle, int(popen._handle)):
|
|
69
|
+
raise c.WinError(c.get_last_error())
|
|
70
|
+
except BaseException:
|
|
71
|
+
self.close()
|
|
72
|
+
raise
|
|
73
|
+
|
|
74
|
+
def resume(self, pid: int) -> None:
|
|
75
|
+
# Popen closes CreateProcess's thread handle. Find the sole suspended
|
|
76
|
+
# initial thread using the documented Toolhelp API, then resume it.
|
|
77
|
+
snapshot = self.api.CreateToolhelp32Snapshot(0x4, 0) # TH32CS_SNAPTHREAD
|
|
78
|
+
if snapshot == c.c_void_p(-1).value:
|
|
79
|
+
raise c.WinError(c.get_last_error())
|
|
80
|
+
try:
|
|
81
|
+
entry = _ThreadEntry()
|
|
82
|
+
entry.size = c.sizeof(entry)
|
|
83
|
+
more = self.api.Thread32First(snapshot, c.byref(entry))
|
|
84
|
+
while more:
|
|
85
|
+
if entry.owner_pid == pid:
|
|
86
|
+
thread = self.api.OpenThread(0x2, False, entry.thread_id) # THREAD_SUSPEND_RESUME
|
|
87
|
+
if not thread:
|
|
88
|
+
raise c.WinError(c.get_last_error())
|
|
89
|
+
try:
|
|
90
|
+
if self.api.ResumeThread(thread) == 0xFFFFFFFF:
|
|
91
|
+
raise c.WinError(c.get_last_error())
|
|
92
|
+
return
|
|
93
|
+
finally:
|
|
94
|
+
self.api.CloseHandle(thread)
|
|
95
|
+
more = self.api.Thread32Next(snapshot, c.byref(entry))
|
|
96
|
+
raise OSError("Cannot find the background command's suspended thread")
|
|
97
|
+
finally:
|
|
98
|
+
self.api.CloseHandle(snapshot)
|
|
99
|
+
|
|
100
|
+
def running(self) -> bool:
|
|
101
|
+
if not self.handle:
|
|
102
|
+
return False
|
|
103
|
+
info = _Accounting()
|
|
104
|
+
if not self.api.QueryInformationJobObject(self.handle, 1, c.byref(info), c.sizeof(info), None):
|
|
105
|
+
raise c.WinError(c.get_last_error())
|
|
106
|
+
return bool(info.active)
|
|
107
|
+
|
|
108
|
+
def terminate(self) -> None:
|
|
109
|
+
if self.handle and not self.api.TerminateJobObject(self.handle, 1):
|
|
110
|
+
raise c.WinError(c.get_last_error())
|
|
111
|
+
|
|
112
|
+
def close(self) -> None:
|
|
113
|
+
if self.handle:
|
|
114
|
+
self.api.CloseHandle(self.handle)
|
|
115
|
+
self.handle = None
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"""User-defined workflows: ``.aria/workflows/<name>.yaml``, run as ``/<name>``.
|
|
2
|
+
|
|
3
|
+
A release is the same five steps every time — test, build, review, write
|
|
4
|
+
the changelog, open the PR — and typing them is where one gets skipped. A
|
|
5
|
+
workflow file names them once::
|
|
6
|
+
|
|
7
|
+
# .aria/workflows/release.yaml
|
|
8
|
+
description: Test, build, review, changelog, PR
|
|
9
|
+
steps:
|
|
10
|
+
- name: Tests
|
|
11
|
+
run: python -m pytest -q
|
|
12
|
+
- name: Build
|
|
13
|
+
run: python -m build
|
|
14
|
+
timeout: 600
|
|
15
|
+
- name: Security review
|
|
16
|
+
command: /review --base main
|
|
17
|
+
- name: Changelog
|
|
18
|
+
prompt: Add a CHANGELOG.md entry for the changes since the last tag. {{args}}
|
|
19
|
+
- name: Open the PR
|
|
20
|
+
run: gh pr create --fill
|
|
21
|
+
confirm: true
|
|
22
|
+
|
|
23
|
+
A step has exactly one of ``run`` (a shell command, through the same
|
|
24
|
+
``run_command`` tool, policy and sandbox as the model's commands),
|
|
25
|
+
``prompt`` (a full Aria turn with tools — its checks decide whether it
|
|
26
|
+
passed) or ``command`` (any slash command). ``confirm`` asks before the step,
|
|
27
|
+
``continue_on_error`` keeps going past a failure, ``timeout`` bounds a
|
|
28
|
+
``run``. ``{{args}}`` is what followed the command, ``{{date}}`` today.
|
|
29
|
+
|
|
30
|
+
The file comes with the repository, so whoever wrote it chose those
|
|
31
|
+
commands. The first run of a workflow — and the first after its file
|
|
32
|
+
changes — shows every step and asks; the answer is remembered by content
|
|
33
|
+
hash in ``<aria home>/trusted_workflows.json``.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
from __future__ import annotations
|
|
37
|
+
|
|
38
|
+
import datetime as _dt
|
|
39
|
+
import hashlib
|
|
40
|
+
import json
|
|
41
|
+
import os
|
|
42
|
+
import re
|
|
43
|
+
from dataclasses import dataclass, field
|
|
44
|
+
from pathlib import Path
|
|
45
|
+
from typing import Optional
|
|
46
|
+
|
|
47
|
+
STEP_KINDS = ("run", "prompt", "command")
|
|
48
|
+
_STEP_KEYS = {"name", "run", "prompt", "command", "confirm", "continue_on_error", "timeout"}
|
|
49
|
+
_TOP_KEYS = {"name", "description", "steps"}
|
|
50
|
+
_NAME = re.compile(r"^[a-z0-9][a-z0-9_-]*$")
|
|
51
|
+
_PLACEHOLDER = re.compile(r"\{\{\s*(\w+)\s*\}\}")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class WorkflowError(ValueError):
|
|
55
|
+
"""A workflow file that cannot be run, with the reason."""
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass(frozen=True)
|
|
59
|
+
class WorkflowStep:
|
|
60
|
+
name: str
|
|
61
|
+
kind: str # run | prompt | command
|
|
62
|
+
body: str
|
|
63
|
+
confirm: bool = False
|
|
64
|
+
continue_on_error: bool = False
|
|
65
|
+
timeout: int = 300
|
|
66
|
+
|
|
67
|
+
def render(self, variables: dict) -> str:
|
|
68
|
+
return _PLACEHOLDER.sub(lambda m: str(variables.get(m.group(1), m.group(0))), self.body).strip()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass(frozen=True)
|
|
72
|
+
class Workflow:
|
|
73
|
+
name: str
|
|
74
|
+
path: str
|
|
75
|
+
description: str
|
|
76
|
+
steps: tuple[WorkflowStep, ...]
|
|
77
|
+
digest: str = ""
|
|
78
|
+
|
|
79
|
+
def outline(self) -> list[str]:
|
|
80
|
+
lines = [f"/{self.name} — {self.description}" if self.description else f"/{self.name}",
|
|
81
|
+
f" from {self.path}"]
|
|
82
|
+
for index, step in enumerate(self.steps, 1):
|
|
83
|
+
flags = [flag for flag, on in (("asks first", step.confirm),
|
|
84
|
+
("continues on error", step.continue_on_error)) if on]
|
|
85
|
+
suffix = f" ({', '.join(flags)})" if flags else ""
|
|
86
|
+
body = " ".join(step.body.split())
|
|
87
|
+
lines.append(f" {index}. {step.name} — {step.kind}: {body[:90]}{suffix}")
|
|
88
|
+
return lines
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def workflow_dirs(workspace: Path | str) -> list[Path]:
|
|
92
|
+
"""``.aria/workflows`` in the workspace, then in its git root if different."""
|
|
93
|
+
start = Path(workspace).expanduser().resolve()
|
|
94
|
+
dirs = [start / ".aria" / "workflows"]
|
|
95
|
+
for parent in start.parents:
|
|
96
|
+
if (parent / ".git").exists():
|
|
97
|
+
if parent / ".aria" / "workflows" not in dirs:
|
|
98
|
+
dirs.append(parent / ".aria" / "workflows")
|
|
99
|
+
break
|
|
100
|
+
return [d for d in dirs if d.is_dir()]
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _files(workspace: Path | str) -> dict[str, Path]:
|
|
104
|
+
found: dict[str, Path] = {}
|
|
105
|
+
for directory in workflow_dirs(workspace):
|
|
106
|
+
for path in sorted(directory.glob("*.y*ml")):
|
|
107
|
+
if path.suffix in (".yaml", ".yml"):
|
|
108
|
+
found.setdefault(path.stem.lower(), path)
|
|
109
|
+
return found
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def names(workspace: Path | str) -> list[str]:
|
|
113
|
+
return sorted(_files(workspace))
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _parse_step(index: int, raw: object, path: Path) -> WorkflowStep:
|
|
117
|
+
where = f"{path.name}, step {index}"
|
|
118
|
+
if not isinstance(raw, dict):
|
|
119
|
+
raise WorkflowError(f"{where}: a step is a mapping with run, prompt or command")
|
|
120
|
+
unknown = set(raw) - _STEP_KEYS
|
|
121
|
+
if unknown:
|
|
122
|
+
raise WorkflowError(f"{where}: unknown key {', '.join(sorted(unknown))}")
|
|
123
|
+
kinds = [kind for kind in STEP_KINDS if raw.get(kind) not in (None, "")]
|
|
124
|
+
if len(kinds) != 1:
|
|
125
|
+
raise WorkflowError(f"{where}: needs exactly one of run, prompt, command")
|
|
126
|
+
kind = kinds[0]
|
|
127
|
+
body = str(raw[kind])
|
|
128
|
+
if kind == "command" and not body.lstrip().startswith("/"):
|
|
129
|
+
raise WorkflowError(f"{where}: command must be a slash command, e.g. /review")
|
|
130
|
+
try:
|
|
131
|
+
timeout = int(raw.get("timeout", 300))
|
|
132
|
+
except (TypeError, ValueError):
|
|
133
|
+
raise WorkflowError(f"{where}: timeout must be a number of seconds") from None
|
|
134
|
+
default_name = " ".join(body.split())[:40]
|
|
135
|
+
return WorkflowStep(name=str(raw.get("name") or default_name), kind=kind, body=body,
|
|
136
|
+
confirm=bool(raw.get("confirm", False)),
|
|
137
|
+
continue_on_error=bool(raw.get("continue_on_error", False)),
|
|
138
|
+
timeout=max(1, timeout))
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def parse(path: Path | str) -> Workflow:
|
|
142
|
+
path = Path(path)
|
|
143
|
+
try:
|
|
144
|
+
text = path.read_text(encoding="utf-8")
|
|
145
|
+
except OSError as exc:
|
|
146
|
+
raise WorkflowError(f"{path}: cannot read: {exc}") from exc
|
|
147
|
+
try:
|
|
148
|
+
import yaml
|
|
149
|
+
|
|
150
|
+
data = yaml.safe_load(text)
|
|
151
|
+
except Exception as exc:
|
|
152
|
+
raise WorkflowError(f"{path.name}: not valid YAML: {exc}") from exc
|
|
153
|
+
if not isinstance(data, dict):
|
|
154
|
+
raise WorkflowError(f"{path.name}: expected a mapping with steps")
|
|
155
|
+
unknown = set(data) - _TOP_KEYS
|
|
156
|
+
if unknown:
|
|
157
|
+
raise WorkflowError(f"{path.name}: unknown key {', '.join(sorted(unknown))}")
|
|
158
|
+
steps = data.get("steps")
|
|
159
|
+
if not isinstance(steps, list) or not steps:
|
|
160
|
+
raise WorkflowError(f"{path.name}: steps must be a non-empty list")
|
|
161
|
+
name = str(data.get("name") or path.stem).lower()
|
|
162
|
+
if not _NAME.match(name):
|
|
163
|
+
raise WorkflowError(f"{path.name}: name '{name}' must be lowercase letters, digits, - or _")
|
|
164
|
+
return Workflow(
|
|
165
|
+
name=name, path=str(path), description=str(data.get("description") or ""),
|
|
166
|
+
steps=tuple(_parse_step(i, raw, path) for i, raw in enumerate(steps, 1)),
|
|
167
|
+
digest=hashlib.sha256(text.encode("utf-8")).hexdigest(),
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def find(workspace: Path | str, name: str) -> Optional[Workflow]:
|
|
172
|
+
"""The workflow called ``name`` (``/name`` works too), or None. Invalid files raise."""
|
|
173
|
+
path = _files(workspace).get(name.lstrip("/").lower())
|
|
174
|
+
return parse(path) if path is not None else None
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def variables(workflow: Workflow, args: str) -> dict:
|
|
178
|
+
return {"args": args.strip(), "date": _dt.date.today().isoformat(), "workflow": workflow.name}
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
# ── trust ──────────────────────────────────────────────────────────────────
|
|
182
|
+
|
|
183
|
+
@dataclass
|
|
184
|
+
class TrustStore:
|
|
185
|
+
path: Path
|
|
186
|
+
entries: dict = field(default_factory=dict)
|
|
187
|
+
|
|
188
|
+
@classmethod
|
|
189
|
+
def load(cls, path: Optional[Path] = None) -> "TrustStore":
|
|
190
|
+
if path is None:
|
|
191
|
+
from ..packages.aria_core.paths import aria_home
|
|
192
|
+
|
|
193
|
+
path = aria_home() / "trusted_workflows.json"
|
|
194
|
+
try:
|
|
195
|
+
entries = json.loads(Path(path).read_text(encoding="utf-8"))
|
|
196
|
+
except (OSError, ValueError):
|
|
197
|
+
entries = {}
|
|
198
|
+
return cls(Path(path), entries if isinstance(entries, dict) else {})
|
|
199
|
+
|
|
200
|
+
def trusted(self, workflow: Workflow) -> bool:
|
|
201
|
+
return self.entries.get(str(Path(workflow.path).resolve())) == workflow.digest
|
|
202
|
+
|
|
203
|
+
def trust(self, workflow: Workflow) -> None:
|
|
204
|
+
self.entries[str(Path(workflow.path).resolve())] = workflow.digest
|
|
205
|
+
self.path.parent.mkdir(parents=True, exist_ok=True)
|
|
206
|
+
temp = self.path.with_suffix(".tmp")
|
|
207
|
+
temp.write_text(json.dumps(self.entries, indent=2, sort_keys=True), encoding="utf-8")
|
|
208
|
+
os.replace(temp, self.path)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
TEMPLATE = """\
|
|
212
|
+
# /{name} — run with /{name} [args]; {{{{args}}}} is what you type after it.
|
|
213
|
+
description: Test, review and summarise the current change
|
|
214
|
+
steps:
|
|
215
|
+
- name: Tests
|
|
216
|
+
run: python -m pytest -q
|
|
217
|
+
- name: Review
|
|
218
|
+
command: /review
|
|
219
|
+
- name: Summary
|
|
220
|
+
prompt: Summarise the current change for a pull request description. {{{{args}}}}
|
|
221
|
+
continue_on_error: true
|
|
222
|
+
"""
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"""Git worktree isolation for write-capable background agents."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import shutil
|
|
6
|
+
import subprocess
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class WorktreeError(RuntimeError):
|
|
12
|
+
"""Raised when an isolated worktree cannot be created safely."""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class WorktreeSpec:
|
|
17
|
+
task_id: str
|
|
18
|
+
repository: str
|
|
19
|
+
path: str
|
|
20
|
+
branch: str
|
|
21
|
+
base_revision: str
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class WorktreeApplyResult:
|
|
26
|
+
paths: tuple[str, ...]
|
|
27
|
+
tracked_paths: tuple[str, ...]
|
|
28
|
+
untracked_paths: tuple[str, ...]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class WorktreeManager:
|
|
32
|
+
"""Create task-specific worktrees without changing the caller's cwd."""
|
|
33
|
+
|
|
34
|
+
def __init__(self, root: Path | str) -> None:
|
|
35
|
+
self.root = Path(root).expanduser().resolve()
|
|
36
|
+
self.root.mkdir(parents=True, exist_ok=True)
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def _git(*args: str, cwd: Path) -> str:
|
|
40
|
+
try:
|
|
41
|
+
completed = subprocess.run(
|
|
42
|
+
["git", *args],
|
|
43
|
+
cwd=str(cwd),
|
|
44
|
+
text=True,
|
|
45
|
+
capture_output=True,
|
|
46
|
+
timeout=30,
|
|
47
|
+
check=False,
|
|
48
|
+
)
|
|
49
|
+
except (OSError, subprocess.SubprocessError) as exc:
|
|
50
|
+
raise WorktreeError(f"Unable to run git: {exc}") from exc
|
|
51
|
+
if completed.returncode != 0:
|
|
52
|
+
detail = (completed.stderr or completed.stdout).strip()
|
|
53
|
+
raise WorktreeError(detail or f"git {' '.join(args)} failed")
|
|
54
|
+
return completed.stdout.strip()
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def repository_root(cls, workspace: Path | str) -> Path:
|
|
58
|
+
path = Path(workspace).expanduser().resolve()
|
|
59
|
+
output = cls._git("rev-parse", "--show-toplevel", cwd=path)
|
|
60
|
+
return Path(output).resolve()
|
|
61
|
+
|
|
62
|
+
@classmethod
|
|
63
|
+
def is_clean(cls, repository: Path | str) -> bool:
|
|
64
|
+
repo = Path(repository).expanduser().resolve()
|
|
65
|
+
return not cls._git("status", "--porcelain", "--untracked-files=all", cwd=repo)
|
|
66
|
+
|
|
67
|
+
def create(
|
|
68
|
+
self,
|
|
69
|
+
*,
|
|
70
|
+
task_id: str,
|
|
71
|
+
workspace: Path | str,
|
|
72
|
+
require_clean: bool = True,
|
|
73
|
+
) -> WorktreeSpec:
|
|
74
|
+
repository = self.repository_root(workspace)
|
|
75
|
+
if require_clean and not self.is_clean(repository):
|
|
76
|
+
raise WorktreeError(
|
|
77
|
+
"The repository has uncommitted changes. Commit or stash them before "
|
|
78
|
+
"starting a write-capable isolated subagent."
|
|
79
|
+
)
|
|
80
|
+
base_revision = self._git("rev-parse", "HEAD", cwd=repository)
|
|
81
|
+
branch = f"aria/task-{task_id}"
|
|
82
|
+
destination = (self.root / repository.name / task_id).resolve()
|
|
83
|
+
if destination.exists():
|
|
84
|
+
raise WorktreeError(f"Worktree path already exists: {destination}")
|
|
85
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
86
|
+
try:
|
|
87
|
+
self._git(
|
|
88
|
+
"worktree",
|
|
89
|
+
"add",
|
|
90
|
+
"-b",
|
|
91
|
+
branch,
|
|
92
|
+
str(destination),
|
|
93
|
+
base_revision,
|
|
94
|
+
cwd=repository,
|
|
95
|
+
)
|
|
96
|
+
except Exception:
|
|
97
|
+
if destination.exists():
|
|
98
|
+
shutil.rmtree(destination, ignore_errors=True)
|
|
99
|
+
raise
|
|
100
|
+
return WorktreeSpec(
|
|
101
|
+
task_id=task_id,
|
|
102
|
+
repository=str(repository),
|
|
103
|
+
path=str(destination),
|
|
104
|
+
branch=branch,
|
|
105
|
+
base_revision=base_revision,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
def remove(self, spec: WorktreeSpec, *, force: bool = False) -> None:
|
|
109
|
+
repository = Path(spec.repository)
|
|
110
|
+
path = Path(spec.path)
|
|
111
|
+
args = ["worktree", "remove"]
|
|
112
|
+
if force:
|
|
113
|
+
args.append("--force")
|
|
114
|
+
args.append(str(path))
|
|
115
|
+
self._git(*args, cwd=repository)
|
|
116
|
+
|
|
117
|
+
def delete_branch(self, spec: WorktreeSpec, *, force: bool = False) -> None:
|
|
118
|
+
flag = "-D" if force else "-d"
|
|
119
|
+
self._git("branch", flag, spec.branch, cwd=Path(spec.repository))
|
|
120
|
+
|
|
121
|
+
@classmethod
|
|
122
|
+
def diff(cls, spec: WorktreeSpec) -> str:
|
|
123
|
+
worktree = Path(spec.path)
|
|
124
|
+
diff_stat = cls._git("diff", "--stat", spec.base_revision, cwd=worktree)
|
|
125
|
+
untracked = cls._git("ls-files", "--others", "--exclude-standard", cwd=worktree)
|
|
126
|
+
parts = [part for part in (diff_stat, untracked) if part]
|
|
127
|
+
return "\n".join(parts)
|
|
128
|
+
|
|
129
|
+
@staticmethod
|
|
130
|
+
def _git_binary(*args: str, cwd: Path, input_data: bytes | None = None) -> bytes:
|
|
131
|
+
try:
|
|
132
|
+
completed = subprocess.run(
|
|
133
|
+
["git", *args],
|
|
134
|
+
cwd=str(cwd),
|
|
135
|
+
input=input_data,
|
|
136
|
+
capture_output=True,
|
|
137
|
+
timeout=30,
|
|
138
|
+
check=False,
|
|
139
|
+
)
|
|
140
|
+
except (OSError, subprocess.SubprocessError) as exc:
|
|
141
|
+
raise WorktreeError(f"Unable to run git: {exc}") from exc
|
|
142
|
+
if completed.returncode != 0:
|
|
143
|
+
detail = (completed.stderr or completed.stdout).decode("utf-8", errors="replace").strip()
|
|
144
|
+
raise WorktreeError(detail or f"git {' '.join(args)} failed")
|
|
145
|
+
return completed.stdout
|
|
146
|
+
|
|
147
|
+
def apply(self, spec: WorktreeSpec) -> WorktreeApplyResult:
|
|
148
|
+
"""Apply an isolated worktree's unstaged result to a clean main worktree."""
|
|
149
|
+
repository = Path(spec.repository)
|
|
150
|
+
worktree = Path(spec.path)
|
|
151
|
+
if not self.is_clean(repository):
|
|
152
|
+
raise WorktreeError(
|
|
153
|
+
"The target workspace changed after the subagent started. "
|
|
154
|
+
"Commit or stash those changes before applying the task result."
|
|
155
|
+
)
|
|
156
|
+
target_revision = self._git("rev-parse", "HEAD", cwd=repository)
|
|
157
|
+
if target_revision != spec.base_revision:
|
|
158
|
+
raise WorktreeError(
|
|
159
|
+
"The target branch advanced after the subagent started. "
|
|
160
|
+
"Review or rebase the task worktree before applying it."
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
tracked, untracked = self.changed_paths(spec)
|
|
164
|
+
if not tracked and not untracked:
|
|
165
|
+
raise WorktreeError("The subagent worktree contains no changes to apply.")
|
|
166
|
+
|
|
167
|
+
for relative in untracked:
|
|
168
|
+
destination = repository / relative
|
|
169
|
+
if destination.exists():
|
|
170
|
+
raise WorktreeError(
|
|
171
|
+
f"Refusing to overwrite an existing untracked path: {destination}"
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
patch = self._git_binary(
|
|
175
|
+
"diff", "--binary", spec.base_revision, cwd=worktree
|
|
176
|
+
)
|
|
177
|
+
if patch:
|
|
178
|
+
self._git_binary("apply", "--check", "-", cwd=repository, input_data=patch)
|
|
179
|
+
|
|
180
|
+
copied: list[Path] = []
|
|
181
|
+
patch_applied = False
|
|
182
|
+
try:
|
|
183
|
+
if patch:
|
|
184
|
+
self._git_binary("apply", "-", cwd=repository, input_data=patch)
|
|
185
|
+
patch_applied = True
|
|
186
|
+
for relative in untracked:
|
|
187
|
+
source = worktree / relative
|
|
188
|
+
destination = repository / relative
|
|
189
|
+
if source.is_symlink():
|
|
190
|
+
raise WorktreeError(f"Refusing to copy an untracked symlink: {source}")
|
|
191
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
192
|
+
shutil.copy2(source, destination)
|
|
193
|
+
copied.append(destination)
|
|
194
|
+
except Exception:
|
|
195
|
+
for destination in reversed(copied):
|
|
196
|
+
if destination.exists():
|
|
197
|
+
destination.unlink()
|
|
198
|
+
if patch_applied:
|
|
199
|
+
self._git_binary("apply", "--reverse", "-", cwd=repository, input_data=patch)
|
|
200
|
+
raise
|
|
201
|
+
|
|
202
|
+
paths = tuple(dict.fromkeys([*tracked, *untracked]))
|
|
203
|
+
return WorktreeApplyResult(paths, tracked, untracked)
|
|
204
|
+
|
|
205
|
+
def changed_paths(self, spec: WorktreeSpec) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
206
|
+
worktree = Path(spec.path)
|
|
207
|
+
tracked_text = self._git(
|
|
208
|
+
"diff", "--name-only", spec.base_revision, cwd=worktree
|
|
209
|
+
)
|
|
210
|
+
tracked = tuple(path for path in tracked_text.splitlines() if path)
|
|
211
|
+
untracked_text = self._git(
|
|
212
|
+
"ls-files", "--others", "--exclude-standard", cwd=worktree
|
|
213
|
+
)
|
|
214
|
+
untracked = tuple(path for path in untracked_text.splitlines() if path)
|
|
215
|
+
return tracked, untracked
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Safety and permission primitives for Aria Code."""
|
|
2
|
+
|
|
3
|
+
from .service import SafetyService
|
|
4
|
+
from .permissions import (
|
|
5
|
+
PermissionDecision,
|
|
6
|
+
PermissionMode,
|
|
7
|
+
PermissionService,
|
|
8
|
+
PolicyDecision,
|
|
9
|
+
classify_command_risk,
|
|
10
|
+
evaluate_command_policy,
|
|
11
|
+
normalize_command,
|
|
12
|
+
)
|
|
13
|
+
from .risk import RiskAssessment, assess_command, assess_tool
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"SafetyService",
|
|
17
|
+
"PermissionDecision",
|
|
18
|
+
"PermissionMode",
|
|
19
|
+
"PermissionService",
|
|
20
|
+
"PolicyDecision",
|
|
21
|
+
"classify_command_risk",
|
|
22
|
+
"RiskAssessment",
|
|
23
|
+
"assess_command",
|
|
24
|
+
"assess_tool",
|
|
25
|
+
"evaluate_command_policy",
|
|
26
|
+
"normalize_command",
|
|
27
|
+
]
|