aria-code 0.52.0__py3-none-any.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_code/__init__.py +42 -0
- aria_code/_version.py +20 -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 +34 -0
- aria_code/agents/base.py +318 -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 +303 -0
- aria_code/agents/financial/fundamental.py +191 -0
- aria_code/agents/financial/macro.py +99 -0
- aria_code/agents/financial/news.py +207 -0
- aria_code/agents/financial/risk.py +165 -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 +258 -0
- aria_code/agents/orchestrator.py +44 -0
- aria_code/agents/portfolio_agent.py +363 -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 +158 -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 +492 -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/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 +15 -0
- aria_code/apps/channels/__init__.py +17 -0
- aria_code/apps/channels/intake.py +92 -0
- aria_code/apps/channels/registry.py +95 -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/bootstrap.py +145 -0
- aria_code/apps/cli/broker_render.py +206 -0
- aria_code/apps/cli/codegen_paths.py +29 -0
- aria_code/apps/cli/commands/__init__.py +16 -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 +369 -0
- aria_code/apps/cli/commands/ashare_prediction_cmds.py +327 -0
- aria_code/apps/cli/commands/auth_cmds.py +239 -0
- aria_code/apps/cli/commands/backtest_cmds.py +2543 -0
- aria_code/apps/cli/commands/broker_cmds.py +1234 -0
- aria_code/apps/cli/commands/business_workflow_cmds.py +319 -0
- aria_code/apps/cli/commands/canvas_cmds.py +77 -0
- aria_code/apps/cli/commands/catalog.py +87 -0
- aria_code/apps/cli/commands/core_cmds.py +2520 -0
- aria_code/apps/cli/commands/data_cmds.py +457 -0
- aria_code/apps/cli/commands/diagnostic_cmds.py +230 -0
- aria_code/apps/cli/commands/diagnostic_ops_cmds.py +813 -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 +434 -0
- aria_code/apps/cli/commands/market_cmds.py +1381 -0
- aria_code/apps/cli/commands/market_context.py +425 -0
- aria_code/apps/cli/commands/market_render.py +7 -0
- aria_code/apps/cli/commands/model_cmds.py +2153 -0
- aria_code/apps/cli/commands/ops_cmds.py +721 -0
- aria_code/apps/cli/commands/orchestrator_cmds.py +179 -0
- aria_code/apps/cli/commands/pdf_export_cmds.py +125 -0
- aria_code/apps/cli/commands/portfolio_cmds.py +1278 -0
- aria_code/apps/cli/commands/report.py +437 -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 +669 -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 +79 -0
- aria_code/apps/cli/commands/workflow_cmds.py +480 -0
- aria_code/apps/cli/commands/workspace_cmds.py +1494 -0
- aria_code/apps/cli/config_paths.py +73 -0
- aria_code/apps/cli/config_store.py +78 -0
- aria_code/apps/cli/constants.py +88 -0
- aria_code/apps/cli/context.py +34 -0
- aria_code/apps/cli/deterministic.py +191 -0
- aria_code/apps/cli/direct.py +48 -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 +196 -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 +1309 -0
- aria_code/apps/cli/handlers/market_handlers.py +2513 -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/helpers.py +302 -0
- aria_code/apps/cli/hooks.py +180 -0
- aria_code/apps/cli/i18n.py +297 -0
- aria_code/apps/cli/intent.py +136 -0
- aria_code/apps/cli/intent_router.py +276 -0
- aria_code/apps/cli/intent_signals.py +344 -0
- aria_code/apps/cli/lifecycle_hooks.py +48 -0
- aria_code/apps/cli/local_tool_schemas.py +536 -0
- aria_code/apps/cli/main.py +29 -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/model_catalog.py +620 -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 +59 -0
- aria_code/apps/cli/prompts/__init__.py +0 -0
- aria_code/apps/cli/prompts/coding.py +53 -0
- aria_code/apps/cli/prompts/select.py +142 -0
- aria_code/apps/cli/prompts/system_prompts.py +552 -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 +521 -0
- aria_code/apps/cli/providers/chat_routing.py +128 -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 +1594 -0
- aria_code/apps/cli/providers/llm/response_cache.py +60 -0
- aria_code/apps/cli/providers/llm/sse_stream.py +257 -0
- aria_code/apps/cli/providers/runtime_bridge.py +353 -0
- aria_code/apps/cli/providers/vertexai_stream.py +316 -0
- aria_code/apps/cli/runtime_consumer.py +657 -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_store.py +112 -0
- aria_code/apps/cli/skills_catalog.py +273 -0
- aria_code/apps/cli/todo_tracker.py +190 -0
- aria_code/apps/cli/tool_executor.py +823 -0
- aria_code/apps/cli/tool_registry.py +34 -0
- aria_code/apps/cli/tool_scope.py +106 -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 +180 -0
- aria_code/apps/cli/tools/market_tools.py +620 -0
- aria_code/apps/cli/tools/notebook_tools.py +111 -0
- aria_code/apps/cli/tools/system_tools.py +726 -0
- aria_code/apps/cli/tools/write_tools.py +845 -0
- aria_code/apps/cli/tradingview_bridge.py +529 -0
- aria_code/apps/cli/turn_planning.py +137 -0
- aria_code/apps/cli/update_check.py +153 -0
- aria_code/apps/cli/utils/__init__.py +0 -0
- aria_code/apps/cli/utils/market_detect.py +1597 -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 +6743 -0
- aria_code/aria_daemon.py +1398 -0
- aria_code/aria_feishu_bot.py +1423 -0
- aria_code/aria_mcp_server.py +7 -0
- aria_code/aria_relay_client.py +4 -0
- aria_code/aria_relay_server.py +490 -0
- aria_code/aria_telegram_bot.py +202 -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 +182 -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 +1976 -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 +181 -0
- aria_code/command_safety.py +19 -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/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/demo_player.py +207 -0
- aria_code/doctor.py +813 -0
- aria_code/domain/__init__.py +0 -0
- aria_code/domain/backtest_engine.py +354 -0
- aria_code/domain/backtest_report.py +472 -0
- aria_code/domain/finance_formulas.py +389 -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/harness.py +598 -0
- aria_code/evals/runner.py +238 -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 +386 -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 +639 -0
- aria_code/memory_manager.py +246 -0
- aria_code/model_capability.py +486 -0
- aria_code/notification_tools.py +4 -0
- aria_code/openai_image_client.py +4 -0
- aria_code/packages/__init__.py +23 -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 +52 -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 +201 -0
- aria_code/packages/aria_mcp/circuit.py +82 -0
- aria_code/packages/aria_mcp/config.py +111 -0
- aria_code/packages/aria_mcp/installer.py +95 -0
- aria_code/packages/aria_mcp/server.py +1550 -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 +396 -0
- aria_code/packages/aria_sdk/providers.py +70 -0
- aria_code/packages/aria_sdk/streaming.py +79 -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 +268 -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 +57 -0
- aria_code/packages/aria_services/research_quality.py +186 -0
- aria_code/packages/aria_services/settings.py +157 -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 +8 -0
- aria_code/packages/aria_tools/financial/_paths.py +130 -0
- aria_code/packages/aria_tools/financial/compliance.py +31 -0
- aria_code/packages/aria_tools/financial/factors.py +33 -0
- aria_code/packages/aria_tools/financial/risk_tools.py +33 -0
- aria_code/packages/aria_tools/financial/strategy.py +31 -0
- aria_code/packages/aria_tools/registry.py +128 -0
- aria_code/packages/quant_engine/__init__.py +34 -0
- aria_code/packages/quant_engine/_namespace.py +62 -0
- aria_code/packages/quant_engine/backtest/__init__.py +14 -0
- aria_code/packages/quant_engine/backtest/core.py +53 -0
- aria_code/packages/quant_engine/backtest/engine.py +96 -0
- aria_code/packages/quant_engine/portfolio/__init__.py +13 -0
- aria_code/packages/quant_engine/portfolio/optimizer.py +85 -0
- aria_code/packages/quant_engine/sports/__init__.py +80 -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/ml_model.py +377 -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 +35 -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/logistics/__init__.py +169 -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/llm/__init__.py +19 -0
- aria_code/providers/llm/anthropic.py +184 -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 +129 -0
- aria_code/providers/llm/openai_compat.py +313 -0
- aria_code/providers/llm/registry.py +444 -0
- aria_code/providers/local_image_provider.py +202 -0
- aria_code/providers/local_llm_provider.py +589 -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/runtime/__init__.py +169 -0
- aria_code/runtime/acceptance.py +481 -0
- aria_code/runtime/agent_loop.py +1520 -0
- aria_code/runtime/approval.py +57 -0
- aria_code/runtime/budget.py +232 -0
- aria_code/runtime/checkpoints.py +432 -0
- aria_code/runtime/crash_report.py +174 -0
- aria_code/runtime/events.py +113 -0
- aria_code/runtime/gateway.py +150 -0
- aria_code/runtime/lsp.py +484 -0
- aria_code/runtime/orchestrator.py +55 -0
- aria_code/runtime/repo_map.py +700 -0
- aria_code/runtime/run_state.py +127 -0
- aria_code/runtime/run_store.py +450 -0
- aria_code/runtime/self_healing.py +422 -0
- aria_code/runtime/subagent.py +547 -0
- aria_code/runtime/task_ledger.py +86 -0
- aria_code/runtime/task_orchestrator.py +90 -0
- aria_code/runtime/tool_executor.py +217 -0
- aria_code/runtime/tool_policy.py +107 -0
- aria_code/runtime/worktrees.py +215 -0
- aria_code/runway_video_client.py +4 -0
- aria_code/safety/__init__.py +23 -0
- aria_code/safety/permissions.py +306 -0
- aria_code/safety/service.py +102 -0
- aria_code/setup_wizard.py +673 -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 +504 -0
- aria_code/tools/data_analysis_tools.py +809 -0
- aria_code/tools/enterprise_finance_tools.py +156 -0
- aria_code/tools/extended_tools.py +240 -0
- aria_code/tools/file_analysis_tools.py +885 -0
- aria_code/tools/image_gen_tools.py +114 -0
- aria_code/tools/local_finance_tools.py +3417 -0
- aria_code/tools/logistics_tools.py +135 -0
- aria_code/tools/macro_tools.py +369 -0
- aria_code/tools/notification_tools.py +249 -0
- aria_code/tools/project_tools.py +525 -0
- aria_code/tools/realty_data_tools.py +659 -0
- aria_code/tools/spreadsheet_tools.py +388 -0
- aria_code/tools/stripe_tools.py +115 -0
- aria_code/ui/__init__.py +105 -0
- aria_code/ui/banner.py +508 -0
- aria_code/ui/completer.py +501 -0
- aria_code/ui/console.py +281 -0
- aria_code/ui/image_render.py +243 -0
- aria_code/ui/input_box.py +488 -0
- aria_code/ui/picker.py +201 -0
- aria_code/ui/render/__init__.py +11 -0
- aria_code/ui/render/finance.py +1705 -0
- aria_code/ui/render/market.py +225 -0
- aria_code/ui/render/output.py +775 -0
- aria_code/ui/render/responsive.py +75 -0
- aria_code/ui/render/team.py +354 -0
- aria_code/ui/robot.py +235 -0
- aria_code/ui/startup_dashboard.py +109 -0
- aria_code/utils/vscode_uri.py +37 -0
- aria_code/video_analysis.py +147 -0
- aria_code/video_editor.py +271 -0
- aria_code/workspace/__init__.py +6 -0
- aria_code/workspace/files.py +193 -0
- aria_code/workspace/verify.py +113 -0
- aria_code/workspace_changes.py +199 -0
- aria_code/workspace_context.py +233 -0
- aria_code/workspace_service.py +196 -0
- aria_code/workspace_tools.py +150 -0
- aria_code-0.52.0.dist-info/METADATA +237 -0
- aria_code-0.52.0.dist-info/RECORD +478 -0
- aria_code-0.52.0.dist-info/WHEEL +5 -0
- aria_code-0.52.0.dist-info/entry_points.txt +3 -0
- aria_code-0.52.0.dist-info/licenses/LICENSE +201 -0
- aria_code-0.52.0.dist-info/licenses/NOTICE +49 -0
- aria_code-0.52.0.dist-info/top_level.txt +1 -0
aria_code/artifacts.py
ADDED
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
"""Local artifact paths for reports, charts, projects, and strategy output."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
import re
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Dict, Optional
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def slugify_topic(topic: Optional[str], fallback: str = "general") -> str:
|
|
15
|
+
raw = str(topic or "").strip()
|
|
16
|
+
if not raw:
|
|
17
|
+
raw = fallback
|
|
18
|
+
raw = re.sub(r"[^A-Za-z0-9._\-\u4e00-\u9fff]+", "-", raw)
|
|
19
|
+
raw = raw.strip("-._")
|
|
20
|
+
return raw[:80] or fallback
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True)
|
|
24
|
+
class ArtifactRecord:
|
|
25
|
+
"""Resolved paths for one generated artifact bundle."""
|
|
26
|
+
|
|
27
|
+
category: str
|
|
28
|
+
topic: str
|
|
29
|
+
directory: Path
|
|
30
|
+
path: Path
|
|
31
|
+
metadata_path: Path
|
|
32
|
+
raw_data_path: Path
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True)
|
|
36
|
+
class ArtifactEntry:
|
|
37
|
+
"""Parsed artifact metadata with resolved paths and file state."""
|
|
38
|
+
|
|
39
|
+
metadata_path: Path
|
|
40
|
+
path: Path
|
|
41
|
+
raw_data_path: Path
|
|
42
|
+
kind: str
|
|
43
|
+
status: str
|
|
44
|
+
topic: str
|
|
45
|
+
created_at: str
|
|
46
|
+
mtime: float
|
|
47
|
+
size_bytes: int
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _safe_stat(path: Path) -> Optional[os.stat_result]:
|
|
51
|
+
try:
|
|
52
|
+
return path.stat()
|
|
53
|
+
except Exception:
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _artifact_entry_from_metadata(path: Path) -> Optional[ArtifactEntry]:
|
|
58
|
+
try:
|
|
59
|
+
data = json.loads(path.read_text(encoding="utf-8"))
|
|
60
|
+
artifact = data.get("artifact") or {}
|
|
61
|
+
output_path = Path(str(artifact.get("path") or ""))
|
|
62
|
+
metadata_path = Path(str(artifact.get("metadata_path") or path))
|
|
63
|
+
raw_path = Path(str(artifact.get("raw_data_path") or path.with_suffix(".raw_data.json")))
|
|
64
|
+
output_stat = _safe_stat(output_path)
|
|
65
|
+
meta_stat = _safe_stat(metadata_path)
|
|
66
|
+
raw_stat = _safe_stat(raw_path)
|
|
67
|
+
mtime = 0.0
|
|
68
|
+
for stat in (output_stat, meta_stat, raw_stat):
|
|
69
|
+
if stat is not None:
|
|
70
|
+
mtime = max(mtime, float(stat.st_mtime))
|
|
71
|
+
size_bytes = 0
|
|
72
|
+
for stat in (output_stat, meta_stat, raw_stat):
|
|
73
|
+
if stat is not None:
|
|
74
|
+
size_bytes += int(stat.st_size)
|
|
75
|
+
return ArtifactEntry(
|
|
76
|
+
metadata_path=metadata_path,
|
|
77
|
+
path=output_path,
|
|
78
|
+
raw_data_path=raw_path,
|
|
79
|
+
kind=str(data.get("kind") or artifact.get("category") or "artifact"),
|
|
80
|
+
status=str(data.get("status") or "unknown"),
|
|
81
|
+
topic=str(artifact.get("topic") or data.get("symbol") or ""),
|
|
82
|
+
created_at=str(data.get("created_at") or ""),
|
|
83
|
+
mtime=mtime or float(meta_stat.st_mtime if meta_stat else 0),
|
|
84
|
+
size_bytes=size_bytes,
|
|
85
|
+
)
|
|
86
|
+
except Exception:
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _cleanup_empty_dirs(start: Path, stop: Path) -> None:
|
|
91
|
+
current = start
|
|
92
|
+
try:
|
|
93
|
+
stop = stop.resolve()
|
|
94
|
+
except Exception:
|
|
95
|
+
return
|
|
96
|
+
while True:
|
|
97
|
+
try:
|
|
98
|
+
current = current.resolve()
|
|
99
|
+
except Exception:
|
|
100
|
+
break
|
|
101
|
+
if current == stop or stop not in current.parents:
|
|
102
|
+
break
|
|
103
|
+
try:
|
|
104
|
+
current.rmdir()
|
|
105
|
+
except Exception:
|
|
106
|
+
break
|
|
107
|
+
current = current.parent
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _project_artifact_root() -> Optional[Path]:
|
|
111
|
+
"""Return project-level artifact root from .ariarc when configured."""
|
|
112
|
+
try:
|
|
113
|
+
from aria_code.ariarc import AriaRC
|
|
114
|
+
|
|
115
|
+
rc = AriaRC.load()
|
|
116
|
+
source = rc.source_path
|
|
117
|
+
if not source:
|
|
118
|
+
return None
|
|
119
|
+
data = getattr(rc, "_data", None)
|
|
120
|
+
if not isinstance(data, dict):
|
|
121
|
+
text = source.read_text(encoding="utf-8")
|
|
122
|
+
import json as _json
|
|
123
|
+
import re as _re
|
|
124
|
+
text = _re.sub(r"/\*.*?\*/", "", text, flags=_re.DOTALL)
|
|
125
|
+
text = _re.sub(r'(?<!:)(?<!https)//[^\n]*', "", text)
|
|
126
|
+
data = _json.loads(text)
|
|
127
|
+
configured = data.get("artifact_root") or data.get("output_dir")
|
|
128
|
+
if configured:
|
|
129
|
+
path = Path(str(configured)).expanduser()
|
|
130
|
+
if not path.is_absolute():
|
|
131
|
+
path = source.parent / path
|
|
132
|
+
return path
|
|
133
|
+
return source.parent / "aria-output"
|
|
134
|
+
except Exception:
|
|
135
|
+
return None
|
|
136
|
+
return None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def artifact_root() -> Path:
|
|
140
|
+
"""Return the per-user local artifact root.
|
|
141
|
+
|
|
142
|
+
Override with ARIA_ARTIFACT_ROOT when a user wants reports/projects under a
|
|
143
|
+
specific workspace. Defaults to a product-owned folder under that user's
|
|
144
|
+
Documents directory, not the developer's Arthera repo.
|
|
145
|
+
"""
|
|
146
|
+
configured = os.getenv("ARIA_ARTIFACT_ROOT")
|
|
147
|
+
if configured:
|
|
148
|
+
return Path(configured).expanduser()
|
|
149
|
+
project_root = _project_artifact_root()
|
|
150
|
+
if project_root:
|
|
151
|
+
return project_root
|
|
152
|
+
return Path.home() / "Documents" / "Aria Code"
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def user_output_root() -> Path:
|
|
156
|
+
"""Return a user-owned output root that never falls back to project cwd.
|
|
157
|
+
|
|
158
|
+
Use this for generated code, strategies, and project scaffolds. Reports and
|
|
159
|
+
charts may still honor project `.ariarc` via `artifact_root()`, but user
|
|
160
|
+
code should not silently land in the Aria source checkout.
|
|
161
|
+
"""
|
|
162
|
+
configured = os.getenv("ARIA_USER_OUTPUT_ROOT")
|
|
163
|
+
if configured:
|
|
164
|
+
return Path(configured).expanduser()
|
|
165
|
+
return Path.home() / "Documents" / "Aria Code"
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def user_projects_dir(create: bool = True) -> Path:
|
|
169
|
+
path = user_output_root() / "projects"
|
|
170
|
+
if create:
|
|
171
|
+
path.mkdir(parents=True, exist_ok=True)
|
|
172
|
+
return path
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def user_generated_dir(create: bool = True) -> Path:
|
|
176
|
+
path = user_output_root() / "generated"
|
|
177
|
+
if create:
|
|
178
|
+
path.mkdir(parents=True, exist_ok=True)
|
|
179
|
+
return path
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def artifact_roots(*, include_user_generated: bool = True) -> list[Path]:
|
|
183
|
+
"""Return unique artifact roots that should be visible to users."""
|
|
184
|
+
roots: list[Path] = []
|
|
185
|
+
for root in (artifact_root(), user_generated_dir(create=False) if include_user_generated else None):
|
|
186
|
+
if root is None:
|
|
187
|
+
continue
|
|
188
|
+
try:
|
|
189
|
+
resolved = root.expanduser().resolve()
|
|
190
|
+
except Exception:
|
|
191
|
+
resolved = root.expanduser()
|
|
192
|
+
if not any(existing == resolved for existing in roots):
|
|
193
|
+
roots.append(resolved)
|
|
194
|
+
return roots
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def artifact_dir(category: str, topic: Optional[str] = None, create: bool = True) -> Path:
|
|
198
|
+
parts = [slugify_topic(part) for part in str(category or "artifacts").split("/") if part]
|
|
199
|
+
base = artifact_root().joinpath(*parts)
|
|
200
|
+
if topic:
|
|
201
|
+
base = base / slugify_topic(topic)
|
|
202
|
+
if create:
|
|
203
|
+
base.mkdir(parents=True, exist_ok=True)
|
|
204
|
+
return base
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def create_artifact(
|
|
208
|
+
category: str,
|
|
209
|
+
topic: Optional[str],
|
|
210
|
+
stem: str,
|
|
211
|
+
suffix: str,
|
|
212
|
+
*,
|
|
213
|
+
timestamp: Optional[datetime] = None,
|
|
214
|
+
create: bool = True,
|
|
215
|
+
) -> ArtifactRecord:
|
|
216
|
+
"""Create a dated artifact bundle path and its sidecar metadata paths.
|
|
217
|
+
|
|
218
|
+
Output layout:
|
|
219
|
+
|
|
220
|
+
<root>/<category>/<topic>/YYYY-MM-DD/<HHMMSS>_<stem><suffix>
|
|
221
|
+
<root>/<category>/<topic>/YYYY-MM-DD/<HHMMSS>_<stem>.metadata.json
|
|
222
|
+
<root>/<category>/<topic>/YYYY-MM-DD/<HHMMSS>_<stem>.raw_data.json
|
|
223
|
+
"""
|
|
224
|
+
|
|
225
|
+
ts = timestamp or datetime.now()
|
|
226
|
+
topic_slug = slugify_topic(topic)
|
|
227
|
+
stem_slug = slugify_topic(stem, fallback="artifact")
|
|
228
|
+
suffix = suffix if suffix.startswith(".") else f".{suffix}"
|
|
229
|
+
directory = artifact_dir(category, topic_slug, create=False) / ts.strftime("%Y-%m-%d")
|
|
230
|
+
prefix = ts.strftime("%H%M%S")
|
|
231
|
+
base_name = f"{prefix}_{stem_slug}"
|
|
232
|
+
if create:
|
|
233
|
+
directory.mkdir(parents=True, exist_ok=True)
|
|
234
|
+
return ArtifactRecord(
|
|
235
|
+
category=category,
|
|
236
|
+
topic=topic_slug,
|
|
237
|
+
directory=directory,
|
|
238
|
+
path=directory / f"{base_name}{suffix}",
|
|
239
|
+
metadata_path=directory / f"{base_name}.metadata.json",
|
|
240
|
+
raw_data_path=directory / f"{base_name}.raw_data.json",
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def create_user_artifact(
|
|
245
|
+
category: str,
|
|
246
|
+
topic: Optional[str],
|
|
247
|
+
stem: str,
|
|
248
|
+
suffix: str,
|
|
249
|
+
*,
|
|
250
|
+
timestamp: Optional[datetime] = None,
|
|
251
|
+
create: bool = True,
|
|
252
|
+
) -> ArtifactRecord:
|
|
253
|
+
"""Create an artifact under the user-owned output root.
|
|
254
|
+
|
|
255
|
+
Unlike `create_artifact`, this intentionally ignores project `.ariarc`
|
|
256
|
+
output settings. Use it for charts, scripts, and generated assets the user
|
|
257
|
+
expects to find in their local Aria output folder rather than the source
|
|
258
|
+
checkout.
|
|
259
|
+
"""
|
|
260
|
+
ts = timestamp or datetime.now()
|
|
261
|
+
parts = [slugify_topic(part) for part in str(category or "generated").split("/") if part]
|
|
262
|
+
topic_slug = slugify_topic(topic)
|
|
263
|
+
stem_slug = slugify_topic(stem, fallback="artifact")
|
|
264
|
+
suffix = suffix if suffix.startswith(".") else f".{suffix}"
|
|
265
|
+
directory = user_generated_dir(create=False).joinpath(*parts, topic_slug, ts.strftime("%Y-%m-%d"))
|
|
266
|
+
prefix = ts.strftime("%H%M%S")
|
|
267
|
+
base_name = f"{prefix}_{stem_slug}"
|
|
268
|
+
if create:
|
|
269
|
+
directory.mkdir(parents=True, exist_ok=True)
|
|
270
|
+
return ArtifactRecord(
|
|
271
|
+
category=f"generated/{'/'.join(parts)}" if parts else "generated",
|
|
272
|
+
topic=topic_slug,
|
|
273
|
+
directory=directory,
|
|
274
|
+
path=directory / f"{base_name}{suffix}",
|
|
275
|
+
metadata_path=directory / f"{base_name}.metadata.json",
|
|
276
|
+
raw_data_path=directory / f"{base_name}.raw_data.json",
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def write_artifact_metadata(record: ArtifactRecord, metadata: Dict[str, Any]) -> Path:
|
|
281
|
+
payload = {
|
|
282
|
+
"artifact": {
|
|
283
|
+
"category": record.category,
|
|
284
|
+
"topic": record.topic,
|
|
285
|
+
"path": str(record.path),
|
|
286
|
+
"metadata_path": str(record.metadata_path),
|
|
287
|
+
"raw_data_path": str(record.raw_data_path),
|
|
288
|
+
},
|
|
289
|
+
**metadata,
|
|
290
|
+
}
|
|
291
|
+
record.metadata_path.write_text(
|
|
292
|
+
json.dumps(payload, ensure_ascii=False, indent=2, default=str),
|
|
293
|
+
encoding="utf-8",
|
|
294
|
+
)
|
|
295
|
+
_notify_preview_session(record)
|
|
296
|
+
return record.metadata_path
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def _notify_preview_session(record: ArtifactRecord) -> None:
|
|
300
|
+
"""Best-effort notification to a running /canvas preview session, if
|
|
301
|
+
any (see preview_server.py). A true no-op in the overwhelmingly common
|
|
302
|
+
case — no session running, e.g. every headless MCP tool call — must
|
|
303
|
+
never let a preview-notification failure break artifact writing, hence
|
|
304
|
+
the blanket except."""
|
|
305
|
+
try:
|
|
306
|
+
import asyncio
|
|
307
|
+
|
|
308
|
+
# Bare root: tests/test_preview_server.py patches `preview_server`,
|
|
309
|
+
# and the packaged root is a different module object — importing it
|
|
310
|
+
# here notified a session nothing was watching.
|
|
311
|
+
from preview_server import get_active_session, thread_id_for
|
|
312
|
+
|
|
313
|
+
session = get_active_session()
|
|
314
|
+
if session is None:
|
|
315
|
+
return
|
|
316
|
+
loop = asyncio.get_running_loop()
|
|
317
|
+
loop.create_task(session.notify_new_version(thread_id_for(record), record))
|
|
318
|
+
except Exception:
|
|
319
|
+
pass
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def write_artifact_raw_data(record: ArtifactRecord, data: Any) -> Path:
|
|
323
|
+
record.raw_data_path.write_text(
|
|
324
|
+
json.dumps(data, ensure_ascii=False, indent=2, default=str),
|
|
325
|
+
encoding="utf-8",
|
|
326
|
+
)
|
|
327
|
+
return record.raw_data_path
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
_ARTIFACT_KINDS_BY_SUFFIX = {
|
|
331
|
+
".md": "markdown_document",
|
|
332
|
+
".markdown": "markdown_document",
|
|
333
|
+
".html": "html_document",
|
|
334
|
+
".htm": "html_document",
|
|
335
|
+
".pdf": "pdf_document",
|
|
336
|
+
".docx": "word_document",
|
|
337
|
+
".xlsx": "spreadsheet",
|
|
338
|
+
".xls": "spreadsheet",
|
|
339
|
+
".csv": "data_file",
|
|
340
|
+
".json": "data_file",
|
|
341
|
+
".py": "code_file",
|
|
342
|
+
".ipynb": "notebook",
|
|
343
|
+
".png": "image",
|
|
344
|
+
".jpg": "image",
|
|
345
|
+
".jpeg": "image",
|
|
346
|
+
".svg": "image",
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def register_existing_artifact(
|
|
351
|
+
path: Path | str,
|
|
352
|
+
*,
|
|
353
|
+
kind: str = "",
|
|
354
|
+
topic: str = "",
|
|
355
|
+
status: str = "complete",
|
|
356
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
357
|
+
) -> Optional[ArtifactRecord]:
|
|
358
|
+
"""Register a generated file so it appears in the unified artifact list.
|
|
359
|
+
|
|
360
|
+
Only files under :func:`user_generated_dir` are registered. This keeps
|
|
361
|
+
ordinary source-code edits out of the user's generated-output inventory.
|
|
362
|
+
Registration is best-effort and never changes the generated file itself.
|
|
363
|
+
"""
|
|
364
|
+
try:
|
|
365
|
+
output_path = Path(path).expanduser().resolve()
|
|
366
|
+
generated_root = user_generated_dir(create=False).expanduser().resolve()
|
|
367
|
+
output_path.relative_to(generated_root)
|
|
368
|
+
except (OSError, RuntimeError, ValueError):
|
|
369
|
+
return None
|
|
370
|
+
|
|
371
|
+
lowered_name = output_path.name.lower()
|
|
372
|
+
if lowered_name.endswith((".metadata.json", ".raw_data.json")):
|
|
373
|
+
return None
|
|
374
|
+
|
|
375
|
+
record = ArtifactRecord(
|
|
376
|
+
category="generated/files",
|
|
377
|
+
topic=slugify_topic(topic or output_path.stem),
|
|
378
|
+
directory=output_path.parent,
|
|
379
|
+
path=output_path,
|
|
380
|
+
# Keep the output extension in sidecar names so report.md and
|
|
381
|
+
# report.html can coexist without overwriting each other's metadata.
|
|
382
|
+
metadata_path=output_path.with_name(f"{output_path.name}.metadata.json"),
|
|
383
|
+
raw_data_path=output_path.with_name(f"{output_path.name}.raw_data.json"),
|
|
384
|
+
)
|
|
385
|
+
payload: Dict[str, Any] = {
|
|
386
|
+
"kind": kind or _ARTIFACT_KINDS_BY_SUFFIX.get(output_path.suffix.lower(), "generated_file"),
|
|
387
|
+
"status": status,
|
|
388
|
+
"created_at": datetime.now().astimezone().isoformat(timespec="seconds"),
|
|
389
|
+
}
|
|
390
|
+
if metadata:
|
|
391
|
+
payload.update(metadata)
|
|
392
|
+
write_artifact_metadata(record, payload)
|
|
393
|
+
return record
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def recent_artifacts(limit: int = 20, root: Optional[Path] = None) -> list[Dict[str, Any]]:
|
|
397
|
+
"""Return recent artifact metadata records, newest first."""
|
|
398
|
+
base = root or artifact_root()
|
|
399
|
+
if not base.exists():
|
|
400
|
+
return []
|
|
401
|
+
items: list[Dict[str, Any]] = []
|
|
402
|
+
for path in base.rglob("*.metadata.json"):
|
|
403
|
+
entry = _artifact_entry_from_metadata(path)
|
|
404
|
+
if entry is None:
|
|
405
|
+
continue
|
|
406
|
+
items.append({
|
|
407
|
+
"kind": entry.kind,
|
|
408
|
+
"status": entry.status,
|
|
409
|
+
"topic": entry.topic,
|
|
410
|
+
"path": str(entry.path) if str(entry.path) else "",
|
|
411
|
+
"metadata_path": str(entry.metadata_path),
|
|
412
|
+
"raw_data_path": str(entry.raw_data_path),
|
|
413
|
+
"created_at": entry.created_at,
|
|
414
|
+
"mtime": entry.mtime,
|
|
415
|
+
"size_bytes": entry.size_bytes,
|
|
416
|
+
})
|
|
417
|
+
items.sort(key=lambda item: item.get("mtime") or 0, reverse=True)
|
|
418
|
+
return items[: max(0, int(limit))]
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
def recent_artifacts_all(limit: int = 20) -> list[Dict[str, Any]]:
|
|
422
|
+
"""Return recent artifacts across project and user-generated roots."""
|
|
423
|
+
items: list[Dict[str, Any]] = []
|
|
424
|
+
seen: set[str] = set()
|
|
425
|
+
for root in artifact_roots(include_user_generated=True):
|
|
426
|
+
for item in recent_artifacts(limit=max(limit, 20), root=root):
|
|
427
|
+
marker = str(item.get("metadata_path") or item.get("path") or "")
|
|
428
|
+
if marker and marker in seen:
|
|
429
|
+
continue
|
|
430
|
+
if marker:
|
|
431
|
+
seen.add(marker)
|
|
432
|
+
item = dict(item)
|
|
433
|
+
item["root"] = str(root)
|
|
434
|
+
items.append(item)
|
|
435
|
+
items.sort(key=lambda item: item.get("mtime") or 0, reverse=True)
|
|
436
|
+
return items[: max(0, int(limit))]
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def artifact_summary(root: Optional[Path] = None) -> Dict[str, Any]:
|
|
440
|
+
"""Return a lightweight inventory of artifacts under root."""
|
|
441
|
+
base = root or artifact_root()
|
|
442
|
+
if not base.exists():
|
|
443
|
+
return {
|
|
444
|
+
"root": str(base),
|
|
445
|
+
"total": 0,
|
|
446
|
+
"total_size_bytes": 0,
|
|
447
|
+
"by_kind": {},
|
|
448
|
+
"newest_mtime": 0.0,
|
|
449
|
+
"oldest_mtime": 0.0,
|
|
450
|
+
}
|
|
451
|
+
entries: list[ArtifactEntry] = []
|
|
452
|
+
for path in base.rglob("*.metadata.json"):
|
|
453
|
+
entry = _artifact_entry_from_metadata(path)
|
|
454
|
+
if entry is not None:
|
|
455
|
+
entries.append(entry)
|
|
456
|
+
by_kind: Dict[str, int] = {}
|
|
457
|
+
newest = 0.0
|
|
458
|
+
oldest = 0.0
|
|
459
|
+
total_size = 0
|
|
460
|
+
for entry in entries:
|
|
461
|
+
by_kind[entry.kind] = by_kind.get(entry.kind, 0) + 1
|
|
462
|
+
total_size += entry.size_bytes
|
|
463
|
+
if entry.mtime:
|
|
464
|
+
newest = max(newest, entry.mtime)
|
|
465
|
+
oldest = entry.mtime if not oldest else min(oldest, entry.mtime)
|
|
466
|
+
return {
|
|
467
|
+
"root": str(base),
|
|
468
|
+
"total": len(entries),
|
|
469
|
+
"total_size_bytes": total_size,
|
|
470
|
+
"by_kind": dict(sorted(by_kind.items(), key=lambda item: (-item[1], item[0]))),
|
|
471
|
+
"newest_mtime": newest,
|
|
472
|
+
"oldest_mtime": oldest,
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def artifact_summary_all() -> Dict[str, Any]:
|
|
477
|
+
"""Return artifact inventory across project and user-generated roots."""
|
|
478
|
+
roots = artifact_roots(include_user_generated=True)
|
|
479
|
+
summaries = [artifact_summary(root) for root in roots]
|
|
480
|
+
by_kind: Dict[str, int] = {}
|
|
481
|
+
total = 0
|
|
482
|
+
total_size = 0
|
|
483
|
+
newest = 0.0
|
|
484
|
+
oldest = 0.0
|
|
485
|
+
for summary in summaries:
|
|
486
|
+
total += int(summary.get("total") or 0)
|
|
487
|
+
total_size += int(summary.get("total_size_bytes") or 0)
|
|
488
|
+
newest = max(newest, float(summary.get("newest_mtime") or 0))
|
|
489
|
+
old = float(summary.get("oldest_mtime") or 0)
|
|
490
|
+
if old:
|
|
491
|
+
oldest = old if not oldest else min(oldest, old)
|
|
492
|
+
for kind, count in (summary.get("by_kind") or {}).items():
|
|
493
|
+
by_kind[str(kind)] = by_kind.get(str(kind), 0) + int(count)
|
|
494
|
+
return {
|
|
495
|
+
"roots": [str(root) for root in roots],
|
|
496
|
+
"total": total,
|
|
497
|
+
"total_size_bytes": total_size,
|
|
498
|
+
"by_kind": dict(sorted(by_kind.items(), key=lambda item: (-item[1], item[0]))),
|
|
499
|
+
"newest_mtime": newest,
|
|
500
|
+
"oldest_mtime": oldest,
|
|
501
|
+
"summaries": summaries,
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
def prune_artifacts(keep: int = 20, root: Optional[Path] = None, dry_run: bool = False) -> Dict[str, Any]:
|
|
506
|
+
"""Delete artifact bundles older than the newest `keep` entries."""
|
|
507
|
+
base = root or artifact_root()
|
|
508
|
+
keep = max(0, int(keep))
|
|
509
|
+
if not base.exists():
|
|
510
|
+
return {
|
|
511
|
+
"root": str(base),
|
|
512
|
+
"keep": keep,
|
|
513
|
+
"scanned": 0,
|
|
514
|
+
"removed": 0,
|
|
515
|
+
"dry_run": dry_run,
|
|
516
|
+
"deleted": [],
|
|
517
|
+
}
|
|
518
|
+
entries: list[ArtifactEntry] = []
|
|
519
|
+
for path in base.rglob("*.metadata.json"):
|
|
520
|
+
entry = _artifact_entry_from_metadata(path)
|
|
521
|
+
if entry is not None:
|
|
522
|
+
entries.append(entry)
|
|
523
|
+
entries.sort(key=lambda entry: entry.mtime, reverse=True)
|
|
524
|
+
to_remove = entries[keep:]
|
|
525
|
+
deleted: list[Dict[str, Any]] = []
|
|
526
|
+
for entry in to_remove:
|
|
527
|
+
targets = [entry.path, entry.metadata_path, entry.raw_data_path]
|
|
528
|
+
removed_files: list[str] = []
|
|
529
|
+
if not dry_run:
|
|
530
|
+
for target in targets:
|
|
531
|
+
try:
|
|
532
|
+
if target.exists():
|
|
533
|
+
target.unlink()
|
|
534
|
+
removed_files.append(str(target))
|
|
535
|
+
except Exception:
|
|
536
|
+
continue
|
|
537
|
+
for target in targets:
|
|
538
|
+
if target.exists():
|
|
539
|
+
continue
|
|
540
|
+
_cleanup_empty_dirs(target.parent, base)
|
|
541
|
+
else:
|
|
542
|
+
removed_files = [str(target) for target in targets if target.exists()]
|
|
543
|
+
deleted.append(
|
|
544
|
+
{
|
|
545
|
+
"kind": entry.kind,
|
|
546
|
+
"status": entry.status,
|
|
547
|
+
"topic": entry.topic,
|
|
548
|
+
"metadata_path": str(entry.metadata_path),
|
|
549
|
+
"path": str(entry.path) if str(entry.path) else "",
|
|
550
|
+
"removed_files": removed_files,
|
|
551
|
+
}
|
|
552
|
+
)
|
|
553
|
+
return {
|
|
554
|
+
"root": str(base),
|
|
555
|
+
"keep": keep,
|
|
556
|
+
"scanned": len(entries),
|
|
557
|
+
"removed": len(deleted),
|
|
558
|
+
"dry_run": dry_run,
|
|
559
|
+
"deleted": deleted,
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
def prune_artifacts_all(keep: int = 20, dry_run: bool = False) -> Dict[str, Any]:
|
|
564
|
+
"""Prune artifact bundles in every visible artifact root."""
|
|
565
|
+
results = [prune_artifacts(keep=keep, root=root, dry_run=dry_run) for root in artifact_roots(include_user_generated=True)]
|
|
566
|
+
deleted: list[Dict[str, Any]] = []
|
|
567
|
+
for result in results:
|
|
568
|
+
root = result.get("root") or ""
|
|
569
|
+
for item in result.get("deleted") or []:
|
|
570
|
+
item = dict(item)
|
|
571
|
+
item["root"] = root
|
|
572
|
+
deleted.append(item)
|
|
573
|
+
return {
|
|
574
|
+
"roots": [result.get("root") for result in results],
|
|
575
|
+
"keep": max(0, int(keep)),
|
|
576
|
+
"scanned": sum(int(result.get("scanned") or 0) for result in results),
|
|
577
|
+
"removed": sum(int(result.get("removed") or 0) for result in results),
|
|
578
|
+
"dry_run": dry_run,
|
|
579
|
+
"deleted": deleted,
|
|
580
|
+
"results": results,
|
|
581
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""
|
|
2
|
+
brokers/ — Aria Code 券商接入层
|
|
3
|
+
================================
|
|
4
|
+
统一接口连接中国和国际主流券商,支持账户查询、持仓管理和下单。
|
|
5
|
+
|
|
6
|
+
快速使用::
|
|
7
|
+
|
|
8
|
+
from brokers.registry import get_registry
|
|
9
|
+
|
|
10
|
+
reg = get_registry()
|
|
11
|
+
broker = reg.connect("xt_main") # 从 ~/.arthera/brokers.json 读取
|
|
12
|
+
acct = broker.account_info()
|
|
13
|
+
pos = broker.positions()
|
|
14
|
+
|
|
15
|
+
支持券商
|
|
16
|
+
--------
|
|
17
|
+
中国:
|
|
18
|
+
xtquant 迅投 XTQuant(中信/华鑫/浙商等QMT平台)
|
|
19
|
+
easytrader EasyTrader(同花顺/通达信/华泰/国君 等客户端)
|
|
20
|
+
futu 富途牛牛 OpenAPI(港/美/A股)
|
|
21
|
+
tiger 老虎证券 OpenAPI(美/港/A股)
|
|
22
|
+
longbridge 长桥证券 OpenAPI(港/美/A股)
|
|
23
|
+
|
|
24
|
+
国际:
|
|
25
|
+
ibkr Interactive Brokers TWS/Gateway
|
|
26
|
+
alpaca Alpaca Markets(美股 + 模拟盘)
|
|
27
|
+
webull Webull(美股,只读模式)
|
|
28
|
+
|
|
29
|
+
配置文件:~/.arthera/brokers.json
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
from .base import BrokerBase, AccountInfo, Position, Order, OrderResult, PortfolioSummary
|
|
33
|
+
from .config import (
|
|
34
|
+
load_config, list_broker_configs, get_broker_config,
|
|
35
|
+
add_broker_config, remove_broker_config, set_default_broker,
|
|
36
|
+
validate_broker_config, supported_broker_types, get_config_template,
|
|
37
|
+
BROKERS_CONFIG_PATH,
|
|
38
|
+
)
|
|
39
|
+
from .registry import BrokerRegistry, get_registry
|
|
40
|
+
from .planning import (
|
|
41
|
+
PortfolioSnapshot, StrategyIntent, RiskRuleSet, PlannedOrder, OrderPlan,
|
|
42
|
+
snapshot_from_broker, infer_intent_from_backtest, plan_order,
|
|
43
|
+
evaluate_risk, plans_from_strategy_results,
|
|
44
|
+
)
|
|
45
|
+
from .capabilities import (
|
|
46
|
+
BrokerCapability, broker_connection_plan, broker_dependency_state,
|
|
47
|
+
broker_service_playbook, filter_capabilities, get_broker_capability,
|
|
48
|
+
list_broker_capabilities,
|
|
49
|
+
)
|
|
50
|
+
from .paper_broker import PaperBroker, reset_paper_account
|
|
51
|
+
from .trading import (
|
|
52
|
+
OrderIntent, TradingPolicy, build_order_preview, execute_order_preview,
|
|
53
|
+
list_order_previews, load_order_preview, policy_from_config, resolve_trading_mode,
|
|
54
|
+
global_dry_run,
|
|
55
|
+
)
|
|
56
|
+
from .automation import (
|
|
57
|
+
AutoExecutePolicy, AutoExecuteDecision, evaluate_auto_execute, run_auto_execute,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
__all__ = [
|
|
61
|
+
"BrokerBase", "AccountInfo", "Position", "Order", "OrderResult", "PortfolioSummary",
|
|
62
|
+
"load_config", "list_broker_configs", "get_broker_config",
|
|
63
|
+
"add_broker_config", "remove_broker_config", "set_default_broker",
|
|
64
|
+
"validate_broker_config", "supported_broker_types", "get_config_template",
|
|
65
|
+
"BROKERS_CONFIG_PATH",
|
|
66
|
+
"BrokerRegistry", "get_registry",
|
|
67
|
+
"PortfolioSnapshot", "StrategyIntent", "RiskRuleSet", "PlannedOrder", "OrderPlan",
|
|
68
|
+
"snapshot_from_broker", "infer_intent_from_backtest", "plan_order",
|
|
69
|
+
"evaluate_risk", "plans_from_strategy_results",
|
|
70
|
+
"BrokerCapability", "broker_connection_plan", "broker_dependency_state",
|
|
71
|
+
"broker_service_playbook", "filter_capabilities", "get_broker_capability",
|
|
72
|
+
"list_broker_capabilities",
|
|
73
|
+
"PaperBroker", "reset_paper_account",
|
|
74
|
+
"OrderIntent", "TradingPolicy", "build_order_preview", "execute_order_preview",
|
|
75
|
+
"list_order_previews", "load_order_preview", "policy_from_config", "resolve_trading_mode",
|
|
76
|
+
"global_dry_run",
|
|
77
|
+
"AutoExecutePolicy", "AutoExecuteDecision", "evaluate_auto_execute", "run_auto_execute",
|
|
78
|
+
]
|