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/__init__.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Aria Code.
|
|
2
|
+
|
|
3
|
+
This package is importable under two roots by design, and has been since the
|
|
4
|
+
src/ restructure: ``aria_code.X`` and a bare ``X``. The tree uses both — 399
|
|
5
|
+
modules import each other bare (``from market_data_client import get_mdc``)
|
|
6
|
+
while others use the package path, and the tests patch whichever root the code
|
|
7
|
+
under test actually uses. tests/test_single_import_root.py exists to keep a
|
|
8
|
+
single *file* from mixing the two.
|
|
9
|
+
|
|
10
|
+
In development both roots resolve because pyproject's
|
|
11
|
+
``pythonpath = [".", "src", "src/aria_code"]`` and tests/conftest.py put them
|
|
12
|
+
there. An installed wheel has neither, so only ``aria_code`` resolved and the
|
|
13
|
+
console script died immediately:
|
|
14
|
+
|
|
15
|
+
$ aria-code --version
|
|
16
|
+
ModuleNotFoundError: No module named 'aria_cli'
|
|
17
|
+
|
|
18
|
+
4.4.1 did not hit this because its wheel predates the restructure — it shipped
|
|
19
|
+
``aria_cli.py`` and 56 other modules at top level, so the bare root *was* the
|
|
20
|
+
package. After the move, nothing put the inner directory on the path.
|
|
21
|
+
|
|
22
|
+
Adding it here rather than shipping a .pth file keeps it inside the package, so
|
|
23
|
+
it applies to `pip install`, `pip install -e .`, a zipapp and a PyInstaller
|
|
24
|
+
bundle alike, and it is visible to anyone reading the package rather than hidden
|
|
25
|
+
in site-packages.
|
|
26
|
+
|
|
27
|
+
This is a bridge, not the destination. One root is the goal — v4.4.2 converted
|
|
28
|
+
the tree to ``aria_code.*`` throughout — but converting it means moving every
|
|
29
|
+
test's patch target with it, and doing that silently under a release is how the
|
|
30
|
+
bare-root bugs in this history were introduced.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
import os as _os
|
|
34
|
+
import sys as _sys
|
|
35
|
+
|
|
36
|
+
_HERE = _os.path.dirname(_os.path.abspath(__file__))
|
|
37
|
+
if _HERE not in _sys.path:
|
|
38
|
+
# Appended, not inserted: a module that legitimately shadows one of these
|
|
39
|
+
# names in the user's own project must keep winning.
|
|
40
|
+
_sys.path.append(_HERE)
|
|
41
|
+
|
|
42
|
+
del _os, _sys, _HERE
|
aria_code/_version.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Single source of truth for the package version.
|
|
2
|
+
|
|
3
|
+
__version__ used to live in aria_cli.py, which meant anything wanting the
|
|
4
|
+
version string had to import the whole interactive CLI — prompt_toolkit,
|
|
5
|
+
bootstrap hooks, the tool registry, all of it. The three consumers each worked
|
|
6
|
+
around that differently: crash_report and a diagnostics accessor imported
|
|
7
|
+
aria_cli anyway, and the MCP server went to importlib.metadata instead, with a
|
|
8
|
+
comment explaining that pulling in aria_cli was too heavy for a binary whose
|
|
9
|
+
job is speaking JSON-RPC over stdio.
|
|
10
|
+
|
|
11
|
+
Keeping it here costs nothing to import and gives all three the same answer.
|
|
12
|
+
Note that importlib.metadata reports what was *installed*, which is not the
|
|
13
|
+
same thing when running from a source checkout.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
__all__ = ["__version__"]
|
|
19
|
+
|
|
20
|
+
__version__ = "0.52.0"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""ADK application packages shipped as optional Aria Code integrations."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Google ADK entrypoint package for Aria's read-only code reviewer."""
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Google ADK entrypoint: a bounded reviewer for pasted code."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
from google.adk.agents.llm_agent import Agent
|
|
8
|
+
|
|
9
|
+
from aria_code.packages.adk_bridge import CodeReviewTools
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
_tools = CodeReviewTools()
|
|
13
|
+
|
|
14
|
+
root_agent = Agent(
|
|
15
|
+
model=os.getenv("ARIA_ADK_MODEL", "gemini-3.5-flash"),
|
|
16
|
+
name="aria_code_review",
|
|
17
|
+
description="A read-only code reviewer for user-submitted source text.",
|
|
18
|
+
instruction="""You are Aria Code Review, a careful software reviewer.
|
|
19
|
+
|
|
20
|
+
Ask the user to paste the relevant source code when it has not been supplied.
|
|
21
|
+
Use review_code for deterministic findings and preserve its severity, line,
|
|
22
|
+
rule, and limitations. Never claim to have opened a local path, accessed a
|
|
23
|
+
repository, run a command, changed a file, or executed tests: this ADK agent
|
|
24
|
+
has none of those capabilities.
|
|
25
|
+
|
|
26
|
+
Explain only findings supported by the submitted code. Separate deterministic
|
|
27
|
+
findings from suggestions, and recommend a test or validation step where
|
|
28
|
+
appropriate. Do not expose credentials appearing in source; tell the user to
|
|
29
|
+
revoke and rotate any exposed credential instead.
|
|
30
|
+
""",
|
|
31
|
+
tools=[_tools.review_code],
|
|
32
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Read-only Aria market-research agent for Google ADK."""
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Google ADK entrypoint: ``adk web adk_apps`` discovers ``aria_research``."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
from google.adk.agents.llm_agent import Agent
|
|
8
|
+
|
|
9
|
+
from aria_code.packages.adk_bridge import MarketResearchTools
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
_tools = MarketResearchTools()
|
|
13
|
+
|
|
14
|
+
root_agent = Agent(
|
|
15
|
+
model=os.getenv("ARIA_ADK_MODEL", "gemini-3.5-flash"),
|
|
16
|
+
name="aria_research",
|
|
17
|
+
description="A read-only market-research assistant for Aria Code and Arthera.",
|
|
18
|
+
instruction="""You are Aria Research, a careful financial-research assistant.
|
|
19
|
+
|
|
20
|
+
Use get_market_snapshot for live market facts and explicitly identify its data
|
|
21
|
+
quality, timestamp, warnings, and source limitations. Use get_market_data_health
|
|
22
|
+
when a data result is missing, stale, or conflicting. Do not invent prices,
|
|
23
|
+
returns, news, citations, positions, or tool output.
|
|
24
|
+
|
|
25
|
+
This agent is research-only. Never claim to execute, recommend, place, modify,
|
|
26
|
+
or schedule trades. Do not request credentials. State clearly that your output
|
|
27
|
+
is research assistance, not investment advice. For quantitative conclusions,
|
|
28
|
+
separate observed facts from hypotheses and mention material uncertainty.
|
|
29
|
+
""",
|
|
30
|
+
tools=[_tools.get_market_snapshot, _tools.get_market_data_health],
|
|
31
|
+
)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""
|
|
2
|
+
agents/ — Aria Code 可组合多智能体系统
|
|
3
|
+
=======================================
|
|
4
|
+
用户可在项目根放置 aria_agents/ 目录,其中的 Agent 类自动被发现。
|
|
5
|
+
|
|
6
|
+
内置 Agent:
|
|
7
|
+
macro → 宏观环境、利率、行业周期
|
|
8
|
+
fundamental → 财务指标、估值、竞争壁垒
|
|
9
|
+
technical → 图形形态、动量、关键价位
|
|
10
|
+
risk → 风险评分、仓位建议
|
|
11
|
+
synthesis → 汇总以上,输出可操作建议
|
|
12
|
+
|
|
13
|
+
自定义 Agent 示例 (aria_agents/northbound_agent.py):
|
|
14
|
+
from agents.base import BaseAgent, AgentResult
|
|
15
|
+
|
|
16
|
+
class NorthboundAgent(BaseAgent):
|
|
17
|
+
name = "northbound"
|
|
18
|
+
description = "北向资金分析专家"
|
|
19
|
+
|
|
20
|
+
async def analyze(self, symbol: str, data: dict) -> AgentResult:
|
|
21
|
+
...
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from .base import BaseAgent, AgentResult
|
|
25
|
+
from .registry import AgentRegistry, get_registry
|
|
26
|
+
from .team import AgentTeam, run_team
|
|
27
|
+
from .signal_scheme import SignalScheme, FINANCIAL_SCHEME, REALTY_SCHEME
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"BaseAgent", "AgentResult",
|
|
31
|
+
"AgentRegistry", "get_registry",
|
|
32
|
+
"AgentTeam", "run_team",
|
|
33
|
+
"SignalScheme", "FINANCIAL_SCHEME", "REALTY_SCHEME",
|
|
34
|
+
]
|
aria_code/agents/base.py
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
"""
|
|
2
|
+
agents/base.py — Agent 统一抽象基类
|
|
3
|
+
=====================================
|
|
4
|
+
所有 agent 继承 BaseAgent,实现 analyze() 方法。
|
|
5
|
+
LLM provider 和数据源从外部注入,agent 本身不关心底层实现。
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from typing import Any, Callable, Dict, List, Optional, Generator, AsyncGenerator
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class AgentResult:
|
|
20
|
+
"""Agent 分析结果,统一输出格式"""
|
|
21
|
+
agent: str # agent 名称
|
|
22
|
+
symbol: str # 分析标的
|
|
23
|
+
analysis: str # 核心分析文本
|
|
24
|
+
confidence: float # 置信度 0.0-1.0
|
|
25
|
+
signal: str = "HOLD" # BUY / HOLD / SELL / STRONG_BUY / STRONG_SELL
|
|
26
|
+
key_points: List[str] = field(default_factory=list) # 关键结论(用于 synthesis)
|
|
27
|
+
data_used: Dict[str, Any] = field(default_factory=dict) # 使用的原始数据
|
|
28
|
+
error: Optional[str] = None # 失败时的错误信息
|
|
29
|
+
degraded: bool = False # True when a deterministic fallback was used
|
|
30
|
+
provenance: List[str] = field(default_factory=list)
|
|
31
|
+
limitations: List[str] = field(default_factory=list)
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def success(self) -> bool:
|
|
35
|
+
return self.error is None
|
|
36
|
+
|
|
37
|
+
def to_dict(self) -> Dict:
|
|
38
|
+
return {
|
|
39
|
+
"agent": self.agent,
|
|
40
|
+
"symbol": self.symbol,
|
|
41
|
+
"analysis": self.analysis,
|
|
42
|
+
"confidence": self.confidence,
|
|
43
|
+
"signal": self.signal,
|
|
44
|
+
"key_points": self.key_points,
|
|
45
|
+
"error": self.error,
|
|
46
|
+
"degraded": self.degraded,
|
|
47
|
+
"provenance": list(self.provenance),
|
|
48
|
+
"limitations": list(self.limitations),
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class BaseAgent(ABC):
|
|
53
|
+
"""
|
|
54
|
+
所有 Agent 的抽象基类。
|
|
55
|
+
|
|
56
|
+
子类必须声明:
|
|
57
|
+
name: str — 唯一标识(用于 /team --agents macro,fundamental)
|
|
58
|
+
description: str — 简短描述(显示在 /help 中)
|
|
59
|
+
|
|
60
|
+
子类必须实现:
|
|
61
|
+
analyze(symbol, data) → AgentResult
|
|
62
|
+
|
|
63
|
+
可选覆盖:
|
|
64
|
+
fetch_data(symbol) → dict — 自定义数据获取逻辑
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
name: str = "base"
|
|
68
|
+
description: str = "基础 Agent"
|
|
69
|
+
|
|
70
|
+
# Time-sensitive claims must come from a tool result with a timestamp, not
|
|
71
|
+
# from a hard-coded prompt. This is appended to every agent because a
|
|
72
|
+
# wrong IPO/symbol/event claim can otherwise contaminate all specialisms.
|
|
73
|
+
_TIME_SENSITIVE_FACT_POLICY = (
|
|
74
|
+
"\n\n## Time-sensitive fact policy\n"
|
|
75
|
+
"- Do not treat examples, aliases, model memory, or internal notes as current facts.\n"
|
|
76
|
+
"- Verify ticker identity, IPO/listing status, prices, corporate events, sports results, "
|
|
77
|
+
"and dates with an appropriate tool or source before stating them as facts.\n"
|
|
78
|
+
"- If a current fact cannot be verified, say that it is unverified instead of guessing.\n"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Language rule injected per-call based on detected user language
|
|
82
|
+
_LANG_RULES = {
|
|
83
|
+
"zh": "\n\n## Language rule\nRespond in Chinese (中文). Technical terms (RSI, MACD, P/E, EPS) may stay in English.\n",
|
|
84
|
+
"en": "\n\n## Language rule\nRespond in English.\n",
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
def __init__(
|
|
88
|
+
self,
|
|
89
|
+
llm_provider=None, # BaseLLMProvider 实例(可选,None 则用模板生成)
|
|
90
|
+
data_router=None, # DataRouter 实例(可选)
|
|
91
|
+
on_token: Optional[Callable[[str], None]] = None, # 流式 token 回调
|
|
92
|
+
on_thought: Optional[Callable[[str], None]] = None, # 思考过程回调
|
|
93
|
+
on_tool_start: Optional[Callable[[str, Dict], None]] = None, # 工具调用开始回调
|
|
94
|
+
on_tool_end: Optional[Callable[[str, Any], None]] = None, # 工具调用结束回调
|
|
95
|
+
config: Optional[Dict] = None,
|
|
96
|
+
lang: str = "zh", # user language: "zh" | "en"
|
|
97
|
+
):
|
|
98
|
+
self.llm = llm_provider
|
|
99
|
+
self.data = data_router
|
|
100
|
+
self.on_token = on_token
|
|
101
|
+
self.on_thought = on_thought
|
|
102
|
+
self.on_tool_start = on_tool_start
|
|
103
|
+
self.on_tool_end = on_tool_end
|
|
104
|
+
self.config = config or {}
|
|
105
|
+
self.lang = lang
|
|
106
|
+
self.memory = [] # Short-term conversation history for multi-turn context
|
|
107
|
+
|
|
108
|
+
async def fetch_data(self, symbol: str) -> Dict[str, Any]:
|
|
109
|
+
"""
|
|
110
|
+
从数据路由器获取分析所需数据。
|
|
111
|
+
子类可覆盖此方法以自定义数据获取逻辑。
|
|
112
|
+
"""
|
|
113
|
+
if not self.data:
|
|
114
|
+
return {}
|
|
115
|
+
result = {}
|
|
116
|
+
try:
|
|
117
|
+
q = self.data.quote(symbol)
|
|
118
|
+
if q:
|
|
119
|
+
result["quote"] = q.to_dict()
|
|
120
|
+
except Exception as e:
|
|
121
|
+
logger.debug(f"[{self.name}] fetch quote {symbol}: {e}")
|
|
122
|
+
return result
|
|
123
|
+
|
|
124
|
+
def _data_guard(self, quote: Dict[str, Any]) -> str:
|
|
125
|
+
"""Return a warning string if real data is unavailable; empty string if data is present."""
|
|
126
|
+
price = quote.get("price") if quote else None
|
|
127
|
+
if not price or float(price) == 0:
|
|
128
|
+
return (
|
|
129
|
+
"\n\n## ⛔ DATA UNAVAILABLE — STRICT RULES\n"
|
|
130
|
+
"Real market data could not be fetched (price=0 or missing).\n"
|
|
131
|
+
"You MUST:\n"
|
|
132
|
+
"1. State clearly that no real data is available.\n"
|
|
133
|
+
"2. NEVER invent specific prices, P/E ratios, EPS, revenue, RSI, MACD, or any numbers.\n"
|
|
134
|
+
"3. NEVER give specific price targets, stop-loss levels, or entry prices.\n"
|
|
135
|
+
"4. Give only qualitative analysis based on publicly known company characteristics.\n"
|
|
136
|
+
"5. End with the signal word (BUY/HOLD/SELL) but with low confidence (≤40%).\n"
|
|
137
|
+
)
|
|
138
|
+
return ""
|
|
139
|
+
|
|
140
|
+
async def _execute_tool(self, tool_name: str, tool_args: Dict[str, Any]) -> str:
|
|
141
|
+
"""
|
|
142
|
+
执行本地工具或 MCP 工具(可被子类重写扩展)。
|
|
143
|
+
实际项目中可将 aria-skills 暴露为工具。
|
|
144
|
+
"""
|
|
145
|
+
if self.on_tool_start:
|
|
146
|
+
self.on_tool_start(tool_name, tool_args)
|
|
147
|
+
|
|
148
|
+
result = None
|
|
149
|
+
try:
|
|
150
|
+
# 路由到数据层或其他 MCP Client 执行
|
|
151
|
+
if self.data and hasattr(self.data, "execute_tool"):
|
|
152
|
+
result = await self.data.execute_tool(tool_name, tool_args)
|
|
153
|
+
else:
|
|
154
|
+
result = f"Error: Tool {tool_name} not implemented or data router unavailable."
|
|
155
|
+
except Exception as e:
|
|
156
|
+
result = f"Error executing {tool_name}: {e}"
|
|
157
|
+
|
|
158
|
+
if self.on_tool_end:
|
|
159
|
+
self.on_tool_end(tool_name, result)
|
|
160
|
+
|
|
161
|
+
import json
|
|
162
|
+
return json.dumps(result, ensure_ascii=False) if not isinstance(result, str) else result
|
|
163
|
+
|
|
164
|
+
async def _call_llm(
|
|
165
|
+
self,
|
|
166
|
+
system: str,
|
|
167
|
+
user: str,
|
|
168
|
+
max_tokens: int = 800,
|
|
169
|
+
quote: Optional[Dict[str, Any]] = None,
|
|
170
|
+
max_tool_loops: int = 5,
|
|
171
|
+
) -> str:
|
|
172
|
+
"""调用 LLM 生成分析文本,内置 Tool Calling 的执行循环"""
|
|
173
|
+
if not self.llm:
|
|
174
|
+
return ""
|
|
175
|
+
# Inject language rule + time-sensitive fact policy + data guard.
|
|
176
|
+
_lang_rule = self._LANG_RULES.get(self.lang, self._LANG_RULES["zh"])
|
|
177
|
+
_data_warn = self._data_guard(quote or {})
|
|
178
|
+
system = system + self._TIME_SENSITIVE_FACT_POLICY + _lang_rule + _data_warn
|
|
179
|
+
from aria_code.providers.llm.base import Message
|
|
180
|
+
|
|
181
|
+
# 自动注入 DAG pipeline 中的 upstream context
|
|
182
|
+
if hasattr(self, "_current_data") and self._current_data:
|
|
183
|
+
upstream = self._current_data.get("upstream_context")
|
|
184
|
+
if upstream:
|
|
185
|
+
user += "\n\n## ⬆️ 团队/上游 Agent 提供的背景上下文 (Upstream Insights)\n"
|
|
186
|
+
user += "请在分析中参考以下来自其他专家 Agent 的核心观点:\n"
|
|
187
|
+
user += "\n".join(upstream)
|
|
188
|
+
|
|
189
|
+
# 融入历史记忆
|
|
190
|
+
if not self.memory:
|
|
191
|
+
messages = [
|
|
192
|
+
Message(role="system", content=system),
|
|
193
|
+
Message(role="user", content=user),
|
|
194
|
+
]
|
|
195
|
+
else:
|
|
196
|
+
messages = list(self.memory)
|
|
197
|
+
messages.append(Message(role="user", content=user))
|
|
198
|
+
|
|
199
|
+
full_text = ""
|
|
200
|
+
loop_count = 0
|
|
201
|
+
|
|
202
|
+
while loop_count < max_tool_loops:
|
|
203
|
+
loop_count += 1
|
|
204
|
+
current_text = ""
|
|
205
|
+
tool_calls = []
|
|
206
|
+
|
|
207
|
+
try:
|
|
208
|
+
async for event in self.llm.stream(
|
|
209
|
+
messages, max_tokens=max_tokens
|
|
210
|
+
):
|
|
211
|
+
t = event.get("type")
|
|
212
|
+
if t == "token":
|
|
213
|
+
tok = event.get("text", "")
|
|
214
|
+
current_text += tok
|
|
215
|
+
full_text += tok
|
|
216
|
+
if self.on_token:
|
|
217
|
+
self.on_token(tok)
|
|
218
|
+
elif t == "thought" and self.on_thought:
|
|
219
|
+
self.on_thought(event.get("text", ""))
|
|
220
|
+
elif t == "tool_call":
|
|
221
|
+
# 记录工具调用意图
|
|
222
|
+
tool_calls.append({
|
|
223
|
+
"name": event.get("name"),
|
|
224
|
+
"args": event.get("args", {})
|
|
225
|
+
})
|
|
226
|
+
elif t == "tool_start" and self.on_tool_start:
|
|
227
|
+
self.on_tool_start(event.get("tool_name", ""), event.get("tool_args", {}))
|
|
228
|
+
elif t == "tool_end" and self.on_tool_end:
|
|
229
|
+
self.on_tool_end(event.get("tool_name", ""), event.get("tool_result", None))
|
|
230
|
+
elif t == "error":
|
|
231
|
+
logger.warning(f"[{self.name}] LLM 错误: {event.get('message')}")
|
|
232
|
+
break
|
|
233
|
+
except Exception as e:
|
|
234
|
+
logger.warning(f"[{self.name}] LLM 调用失败: {e}")
|
|
235
|
+
break
|
|
236
|
+
|
|
237
|
+
# 将当前 Assistant 的回复加入消息流
|
|
238
|
+
messages.append(Message(role="assistant", content=current_text))
|
|
239
|
+
|
|
240
|
+
# 如果没有工具调用,说明 LLM 完成了最终回答,跳出循环
|
|
241
|
+
|
|
242
|
+
# If provider didn't emit native tool_calls, fallback to ReAct JSON parsing
|
|
243
|
+
if not tool_calls:
|
|
244
|
+
import re
|
|
245
|
+
import json
|
|
246
|
+
|
|
247
|
+
# Check for explicit JSON tool calls outputted as text
|
|
248
|
+
matches = re.finditer(r'```json\s*({"type":\s*"tool_call".*?})\s*```', current_text, re.DOTALL)
|
|
249
|
+
for match in matches:
|
|
250
|
+
try:
|
|
251
|
+
parsed = json.loads(match.group(1))
|
|
252
|
+
tool_calls.append({
|
|
253
|
+
"name": parsed.get("name"),
|
|
254
|
+
"args": parsed.get("args", {})
|
|
255
|
+
})
|
|
256
|
+
except Exception as e:
|
|
257
|
+
logger.warning(f"Failed to parse ReAct tool call: {e}")
|
|
258
|
+
|
|
259
|
+
# Also check inline unformatted JSON
|
|
260
|
+
if not tool_calls:
|
|
261
|
+
matches_raw = re.finditer(r'{"type":\s*"tool_call",\s*"name":\s*"([^"]+)",\s*"args":\s*({.*?})}', current_text, re.DOTALL)
|
|
262
|
+
for match in matches_raw:
|
|
263
|
+
try:
|
|
264
|
+
args_dict = json.loads(match.group(2))
|
|
265
|
+
tool_calls.append({
|
|
266
|
+
"name": match.group(1),
|
|
267
|
+
"args": args_dict
|
|
268
|
+
})
|
|
269
|
+
except Exception:
|
|
270
|
+
pass
|
|
271
|
+
|
|
272
|
+
if not tool_calls:
|
|
273
|
+
break
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
# 有工具调用,则逐一执行,并把结果喂回 LLM
|
|
277
|
+
for tc in tool_calls:
|
|
278
|
+
tool_res = await self._execute_tool(tc["name"], tc["args"])
|
|
279
|
+
# 注意:实际 provider 中 Message 结构可能需要 tool_call_id
|
|
280
|
+
# 这里假设通用 Message 能够携带 role="tool"
|
|
281
|
+
messages.append(Message(role="tool", name=tc["name"], content=tool_res))
|
|
282
|
+
|
|
283
|
+
# 更新短期记忆
|
|
284
|
+
self.memory = messages
|
|
285
|
+
|
|
286
|
+
return full_text.strip()
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
@abstractmethod
|
|
290
|
+
async def analyze(self, symbol: str, data: Dict[str, Any]) -> AgentResult:
|
|
291
|
+
"""
|
|
292
|
+
核心分析方法。
|
|
293
|
+
|
|
294
|
+
Args:
|
|
295
|
+
symbol: 股票/资产代码
|
|
296
|
+
data: 由 fetch_data() 预取的数据字典
|
|
297
|
+
|
|
298
|
+
Returns:
|
|
299
|
+
AgentResult
|
|
300
|
+
"""
|
|
301
|
+
...
|
|
302
|
+
|
|
303
|
+
async def run(self, symbol: str) -> AgentResult:
|
|
304
|
+
"""完整执行:fetch_data → analyze,异常自动捕获。"""
|
|
305
|
+
try:
|
|
306
|
+
data = await self.fetch_data(symbol)
|
|
307
|
+
result = await self.analyze(symbol, data)
|
|
308
|
+
return result
|
|
309
|
+
except Exception as e:
|
|
310
|
+
logger.error(f"[{self.name}] run({symbol}) 失败: {e}", exc_info=True)
|
|
311
|
+
return AgentResult(
|
|
312
|
+
agent=self.name, symbol=symbol,
|
|
313
|
+
analysis="", confidence=0.0,
|
|
314
|
+
error=str(e),
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
def __repr__(self) -> str:
|
|
318
|
+
return f"{self.__class__.__name__}(name={self.name!r})"
|