aria-code 0.167.0__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aria_bots/__init__.py +7 -0
- aria_bots/channels/README.md +97 -0
- aria_bots/channels/__init__.py +1 -0
- aria_bots/channels/approvals.py +263 -0
- aria_bots/channels/conversation.py +280 -0
- aria_bots/channels/digest.py +186 -0
- aria_bots/channels/registry.py +95 -0
- aria_bots/engine.py +144 -0
- aria_bots/feishu_bot.py +1385 -0
- aria_bots/logistics/__init__.py +1 -0
- aria_bots/logistics/carriers.py +253 -0
- aria_bots/logistics/freight.py +154 -0
- aria_bots/logistics/inventory.py +242 -0
- aria_bots/logistics/mcp_server.py +156 -0
- aria_bots/logistics/records.py +119 -0
- aria_bots/logistics/tenancy.py +152 -0
- aria_bots/market.py +91 -0
- aria_bots/relay_client.py +326 -0
- aria_bots/telegram_bot.py +299 -0
- aria_code/__init__.py +111 -0
- aria_code/_bin/aria-native.exe +0 -0
- aria_code/_bin/aria-runtime.exe +0 -0
- aria_code/_version.py +20 -0
- aria_code/account_memory.py +296 -0
- aria_code/account_session.py +166 -0
- aria_code/adk_apps/__init__.py +1 -0
- aria_code/adk_apps/aria_code_review/__init__.py +1 -0
- aria_code/adk_apps/aria_code_review/agent.py +32 -0
- aria_code/adk_apps/aria_research/__init__.py +1 -0
- aria_code/adk_apps/aria_research/agent.py +31 -0
- aria_code/agents/__init__.py +49 -0
- aria_code/agents/base.py +329 -0
- aria_code/agents/code_review.py +200 -0
- aria_code/agents/deep/__init__.py +37 -0
- aria_code/agents/deep/calibration_loop.py +144 -0
- aria_code/agents/deep/critic.py +125 -0
- aria_code/agents/deep/deepen.py +193 -0
- aria_code/agents/deep/models.py +149 -0
- aria_code/agents/deep/pipeline.py +164 -0
- aria_code/agents/deep/quant_fusion.py +192 -0
- aria_code/agents/deep/themes.py +95 -0
- aria_code/agents/deep/tiers.py +106 -0
- aria_code/agents/engineering/__init__.py +14 -0
- aria_code/agents/engineering/coder.py +222 -0
- aria_code/agents/engineering/tester.py +145 -0
- aria_code/agents/financial/__init__.py +21 -0
- aria_code/agents/financial/cashflow_burn.py +119 -0
- aria_code/agents/financial/catalyst.py +279 -0
- aria_code/agents/financial/corporate_finance.py +175 -0
- aria_code/agents/financial/debate.py +224 -0
- aria_code/agents/financial/earnings.py +315 -0
- aria_code/agents/financial/fundamental.py +178 -0
- aria_code/agents/financial/macro.py +111 -0
- aria_code/agents/financial/news.py +231 -0
- aria_code/agents/financial/risk.py +146 -0
- aria_code/agents/financial/sector.py +279 -0
- aria_code/agents/financial/strategist.py +121 -0
- aria_code/agents/financial/stripe_revenue.py +127 -0
- aria_code/agents/financial/synthesis.py +274 -0
- aria_code/agents/financial/technical.py +277 -0
- aria_code/agents/orchestrator.py +44 -0
- aria_code/agents/portfolio_agent.py +392 -0
- aria_code/agents/realty/__init__.py +62 -0
- aria_code/agents/realty/asset_diagnosis.py +152 -0
- aria_code/agents/realty/business_match.py +166 -0
- aria_code/agents/realty/cashflow_verify.py +209 -0
- aria_code/agents/realty/contract_rules.py +210 -0
- aria_code/agents/realty/energy_anomaly.py +189 -0
- aria_code/agents/realty/exit_settlement.py +208 -0
- aria_code/agents/realty/fulfillment_risk.py +206 -0
- aria_code/agents/realty/ops_optimize.py +160 -0
- aria_code/agents/realty/revenue_share.py +215 -0
- aria_code/agents/registry.py +168 -0
- aria_code/agents/signal_scheme.py +111 -0
- aria_code/agents/sports/__init__.py +0 -0
- aria_code/agents/sports/football_agent.py +197 -0
- aria_code/agents/supervisor.py +113 -0
- aria_code/agents/team.py +500 -0
- aria_code/agents/video/__init__.py +16 -0
- aria_code/agents/video/director.py +376 -0
- aria_code/agents/video/qa_agent.py +143 -0
- aria_code/agents/video/script_doctor.py +112 -0
- aria_code/agents/warehouse/__init__.py +25 -0
- aria_code/agents/warehouse/contracts.py +26 -0
- aria_code/agents/warehouse/dashboard.py +155 -0
- aria_code/agents/warehouse/fulfillment_leadtime.py +95 -0
- aria_code/agents/warehouse/inbound_exceptions.py +25 -0
- aria_code/agents/warehouse/inventory_health.py +24 -0
- aria_code/agents/warehouse/local_run.py +71 -0
- aria_code/agents/warehouse/local_snapshot.py +132 -0
- aria_code/agents/warehouse/logistics_cost.py +84 -0
- aria_code/agents/warehouse/logistics_sync.py +21 -0
- aria_code/agents/warehouse/navigation.schema.json +110 -0
- aria_code/agents/warehouse/task_agent.py +172 -0
- aria_code/agents/warehouse/workflow.py +31 -0
- aria_code/aliyun_data_client.py +4 -0
- aria_code/apps/README.md +12 -0
- aria_code/apps/__init__.py +2 -0
- aria_code/apps/channels/README.md +9 -0
- aria_code/apps/channels/__init__.py +17 -0
- aria_code/apps/channels/approvals.py +11 -0
- aria_code/apps/channels/conversation.py +11 -0
- aria_code/apps/channels/digest.py +11 -0
- aria_code/apps/channels/intake.py +92 -0
- aria_code/apps/channels/registry.py +11 -0
- aria_code/apps/channels/tradingview.py +94 -0
- aria_code/apps/cli/README.md +13 -0
- aria_code/apps/cli/__init__.py +2 -0
- aria_code/apps/cli/_optional.py +120 -0
- aria_code/apps/cli/app_server.py +656 -0
- aria_code/apps/cli/auto_update.py +125 -0
- aria_code/apps/cli/bootstrap.py +206 -0
- aria_code/apps/cli/broker_render.py +206 -0
- aria_code/apps/cli/chat_turn.py +1327 -0
- aria_code/apps/cli/cloud_models.py +231 -0
- aria_code/apps/cli/codegen_paths.py +29 -0
- aria_code/apps/cli/commands/__init__.py +34 -0
- aria_code/apps/cli/commands/_business_render.py +78 -0
- aria_code/apps/cli/commands/_ui.py +71 -0
- aria_code/apps/cli/commands/analysis_cmds.py +378 -0
- aria_code/apps/cli/commands/ashare_prediction_cmds.py +327 -0
- aria_code/apps/cli/commands/auth_cmds.py +215 -0
- aria_code/apps/cli/commands/backtest_cmds.py +2518 -0
- aria_code/apps/cli/commands/broker_cmds.py +1236 -0
- aria_code/apps/cli/commands/business_workflow_cmds.py +379 -0
- aria_code/apps/cli/commands/canvas_cmds.py +77 -0
- aria_code/apps/cli/commands/catalog.py +189 -0
- aria_code/apps/cli/commands/core_cmds.py +2748 -0
- aria_code/apps/cli/commands/data_cmds.py +521 -0
- aria_code/apps/cli/commands/diagnostic_cmds.py +285 -0
- aria_code/apps/cli/commands/diagnostic_ops_cmds.py +813 -0
- aria_code/apps/cli/commands/engineering_cmds.py +399 -0
- aria_code/apps/cli/commands/file_cmds.py +312 -0
- aria_code/apps/cli/commands/finance_service_cmds.py +60 -0
- aria_code/apps/cli/commands/fx_commodity_cmds.py +123 -0
- aria_code/apps/cli/commands/market.py +544 -0
- aria_code/apps/cli/commands/market_cmds.py +1419 -0
- aria_code/apps/cli/commands/market_context.py +432 -0
- aria_code/apps/cli/commands/market_render.py +7 -0
- aria_code/apps/cli/commands/model_cmds.py +2374 -0
- aria_code/apps/cli/commands/ops_cmds.py +721 -0
- aria_code/apps/cli/commands/orchestrator_cmds.py +181 -0
- aria_code/apps/cli/commands/pdf_export_cmds.py +125 -0
- aria_code/apps/cli/commands/portfolio_cmds.py +1316 -0
- aria_code/apps/cli/commands/report.py +476 -0
- aria_code/apps/cli/commands/scaffold_templates.py +617 -0
- aria_code/apps/cli/commands/session_cmds.py +236 -0
- aria_code/apps/cli/commands/session_ux_cmds.py +359 -0
- aria_code/apps/cli/commands/team.py +723 -0
- aria_code/apps/cli/commands/team_render.py +8 -0
- aria_code/apps/cli/commands/ui_cmds.py +401 -0
- aria_code/apps/cli/commands/warehouse_cmds.py +297 -0
- aria_code/apps/cli/commands/workflow_cmds.py +629 -0
- aria_code/apps/cli/commands/workspace_cmds.py +1543 -0
- aria_code/apps/cli/config_paths.py +73 -0
- aria_code/apps/cli/config_store.py +158 -0
- aria_code/apps/cli/constants.py +88 -0
- aria_code/apps/cli/context.py +34 -0
- aria_code/apps/cli/conversation_policy.py +53 -0
- aria_code/apps/cli/deterministic.py +200 -0
- aria_code/apps/cli/direct.py +48 -0
- aria_code/apps/cli/earnings_view.py +172 -0
- aria_code/apps/cli/endpoint_migration.py +64 -0
- aria_code/apps/cli/exec_events.py +255 -0
- aria_code/apps/cli/file_references.py +155 -0
- aria_code/apps/cli/finance_service_catalog.py +111 -0
- aria_code/apps/cli/football_reports.py +231 -0
- aria_code/apps/cli/github_app_auth.py +135 -0
- aria_code/apps/cli/google_login.py +239 -0
- aria_code/apps/cli/handlers/__init__.py +11 -0
- aria_code/apps/cli/handlers/broker_handlers.py +122 -0
- aria_code/apps/cli/handlers/chart_handlers.py +1314 -0
- aria_code/apps/cli/handlers/market_handlers.py +2570 -0
- aria_code/apps/cli/handlers/realty_handlers.py +114 -0
- aria_code/apps/cli/handlers/sports_handlers.py +22 -0
- aria_code/apps/cli/handlers/strategy_advice.py +82 -0
- aria_code/apps/cli/headless.py +352 -0
- aria_code/apps/cli/helpers.py +326 -0
- aria_code/apps/cli/hooks.py +180 -0
- aria_code/apps/cli/i18n.py +310 -0
- aria_code/apps/cli/intent.py +136 -0
- aria_code/apps/cli/intent_router.py +305 -0
- aria_code/apps/cli/intent_shadow.py +72 -0
- aria_code/apps/cli/intent_signals.py +347 -0
- aria_code/apps/cli/lifecycle_hooks.py +48 -0
- aria_code/apps/cli/local_tool_schemas.py +550 -0
- aria_code/apps/cli/main.py +39 -0
- aria_code/apps/cli/market_hours.py +100 -0
- aria_code/apps/cli/market_metadata.py +135 -0
- aria_code/apps/cli/market_universe.py +487 -0
- aria_code/apps/cli/message_processing.py +310 -0
- aria_code/apps/cli/mixin_binding.py +32 -0
- aria_code/apps/cli/model_catalog.py +652 -0
- aria_code/apps/cli/model_probe.py +169 -0
- aria_code/apps/cli/model_retirement.py +65 -0
- aria_code/apps/cli/native_branding.py +12 -0
- aria_code/apps/cli/native_bridge.py +118 -0
- aria_code/apps/cli/native_entry.py +58 -0
- aria_code/apps/cli/pdf_report.py +977 -0
- aria_code/apps/cli/plan_mode.py +139 -0
- aria_code/apps/cli/plotly_html.py +15 -0
- aria_code/apps/cli/prediction_feedback.py +202 -0
- aria_code/apps/cli/preflight.py +502 -0
- aria_code/apps/cli/project_aria.py +60 -0
- aria_code/apps/cli/prompt_assembly.py +78 -0
- aria_code/apps/cli/prompts/__init__.py +0 -0
- aria_code/apps/cli/prompts/coding.py +71 -0
- aria_code/apps/cli/prompts/select.py +193 -0
- aria_code/apps/cli/prompts/system_prompts.py +562 -0
- aria_code/apps/cli/prompts/ui.py +436 -0
- aria_code/apps/cli/provider_endpoints.py +237 -0
- aria_code/apps/cli/provider_keys.py +73 -0
- aria_code/apps/cli/providers/__init__.py +1 -0
- aria_code/apps/cli/providers/base.py +775 -0
- aria_code/apps/cli/providers/chat_routing.py +139 -0
- aria_code/apps/cli/providers/collaboration.py +98 -0
- aria_code/apps/cli/providers/llm/__init__.py +1 -0
- aria_code/apps/cli/providers/llm/offline_responses.py +68 -0
- aria_code/apps/cli/providers/llm/ollama_stream.py +1574 -0
- aria_code/apps/cli/providers/llm/response_cache.py +60 -0
- aria_code/apps/cli/providers/llm/sse_stream.py +298 -0
- aria_code/apps/cli/providers/runtime_bridge.py +586 -0
- aria_code/apps/cli/providers/vertexai_stream.py +592 -0
- aria_code/apps/cli/release_download.py +159 -0
- aria_code/apps/cli/review_runner.py +111 -0
- aria_code/apps/cli/runtime_consumer.py +769 -0
- aria_code/apps/cli/sandbox.py +32 -0
- aria_code/apps/cli/session_export.py +120 -0
- aria_code/apps/cli/session_jsonl.py +208 -0
- aria_code/apps/cli/session_refresh.py +123 -0
- aria_code/apps/cli/session_store.py +125 -0
- aria_code/apps/cli/skills_catalog.py +273 -0
- aria_code/apps/cli/task_isolation.py +211 -0
- aria_code/apps/cli/terminal_chrome.py +412 -0
- aria_code/apps/cli/todo_tracker.py +190 -0
- aria_code/apps/cli/tool_executor.py +932 -0
- aria_code/apps/cli/tool_registry.py +34 -0
- aria_code/apps/cli/tool_scope.py +113 -0
- aria_code/apps/cli/tools/__init__.py +40 -0
- aria_code/apps/cli/tools/context.py +46 -0
- aria_code/apps/cli/tools/file_tools.py +181 -0
- aria_code/apps/cli/tools/market_tools.py +626 -0
- aria_code/apps/cli/tools/notebook_tools.py +111 -0
- aria_code/apps/cli/tools/system_tools.py +656 -0
- aria_code/apps/cli/tools/write_tools.py +961 -0
- aria_code/apps/cli/tradingview_bridge.py +529 -0
- aria_code/apps/cli/transactions.py +269 -0
- aria_code/apps/cli/turn_planning.py +137 -0
- aria_code/apps/cli/update_check.py +257 -0
- aria_code/apps/cli/updater.py +373 -0
- aria_code/apps/cli/utils/__init__.py +0 -0
- aria_code/apps/cli/utils/market_detect.py +1663 -0
- aria_code/apps/cli/web_login.py +136 -0
- aria_code/apps/cli/workflow_runner.py +127 -0
- aria_code/apps/cli/workspace_route.py +121 -0
- aria_code/apps/daemon/README.md +14 -0
- aria_code/apps/vscode/README.md +115 -0
- aria_code/apps/vscode/package.json +70 -0
- aria_code/aria_cli.py +5244 -0
- aria_code/aria_daemon.py +1372 -0
- aria_code/aria_feishu_bot.py +16 -0
- aria_code/aria_mcp_server.py +61 -0
- aria_code/aria_relay_client.py +4 -0
- aria_code/aria_telegram_bot.py +11 -0
- aria_code/ariarc.py +385 -0
- aria_code/artifacts.py +581 -0
- aria_code/backtest_engine.py +4 -0
- aria_code/backtest_report.py +4 -0
- aria_code/brokers/__init__.py +78 -0
- aria_code/brokers/automation.py +193 -0
- aria_code/brokers/base.py +231 -0
- aria_code/brokers/capabilities.py +264 -0
- aria_code/brokers/cn/__init__.py +10 -0
- aria_code/brokers/cn/easytrader_broker.py +193 -0
- aria_code/brokers/cn/futu_broker.py +194 -0
- aria_code/brokers/cn/longbridge_broker.py +190 -0
- aria_code/brokers/cn/tiger_broker.py +196 -0
- aria_code/brokers/cn/xtquant_broker.py +225 -0
- aria_code/brokers/config.py +414 -0
- aria_code/brokers/intl/__init__.py +5 -0
- aria_code/brokers/intl/alpaca_broker.py +183 -0
- aria_code/brokers/intl/ibkr_broker.py +215 -0
- aria_code/brokers/intl/trading212_broker.py +183 -0
- aria_code/brokers/intl/webull_broker.py +156 -0
- aria_code/brokers/paper_broker.py +266 -0
- aria_code/brokers/planning.py +296 -0
- aria_code/brokers/registry.py +213 -0
- aria_code/brokers/trading.py +267 -0
- aria_code/canva_client.py +4 -0
- aria_code/change_store.py +127 -0
- aria_code/clients/__init__.py +0 -0
- aria_code/clients/aliyun_data_client.py +660 -0
- aria_code/clients/aria_relay_client.py +16 -0
- aria_code/clients/canva_client.py +284 -0
- aria_code/clients/figma_client.py +100 -0
- aria_code/clients/football_data_client.py +1671 -0
- aria_code/clients/kling_video_client.py +182 -0
- aria_code/clients/market_data_client.py +1985 -0
- aria_code/clients/openai_image_client.py +242 -0
- aria_code/clients/runway_video_client.py +157 -0
- aria_code/clients/warehouse_erp_client.py +105 -0
- aria_code/cloud_memory.py +190 -0
- aria_code/command_safety.py +19 -0
- aria_code/computer_use_server.py +276 -0
- aria_code/computer_use_tools.py +4 -0
- aria_code/dashboard_generator.py +579 -0
- aria_code/data_analysis_tools.py +4 -0
- aria_code/data_cleaner.py +483 -0
- aria_code/data_service.py +513 -0
- aria_code/datasources/__init__.py +23 -0
- aria_code/datasources/base.py +166 -0
- aria_code/datasources/router.py +253 -0
- aria_code/datasources/sec_statements.py +217 -0
- aria_code/datasources/sources/__init__.py +15 -0
- aria_code/datasources/sources/akshare_source.py +269 -0
- aria_code/datasources/sources/alpha_vantage_source.py +203 -0
- aria_code/datasources/sources/edgar_source.py +219 -0
- aria_code/datasources/sources/finnhub_source.py +198 -0
- aria_code/datasources/sources/fred_source.py +223 -0
- aria_code/datasources/sources/tushare_source.py +143 -0
- aria_code/datasources/sources/web_scraper_source.py +278 -0
- aria_code/datasources/sources/world_bank_source.py +206 -0
- aria_code/datasources/sources/yfinance_source.py +152 -0
- aria_code/doctor.py +860 -0
- aria_code/domain/__init__.py +0 -0
- aria_code/domain/_finance_core/__init__.py +5 -0
- aria_code/domain/_finance_core/backtest_engine.py +325 -0
- aria_code/domain/_finance_core/performance_stats.py +101 -0
- aria_code/domain/backtest_engine.py +75 -0
- aria_code/domain/backtest_report.py +488 -0
- aria_code/domain/finance_formulas.py +389 -0
- aria_code/domain/performance_stats.py +6 -0
- aria_code/domain/portfolio_ledger.py +307 -0
- aria_code/domain/strategy_vault.py +421 -0
- aria_code/evals/__init__.py +37 -0
- aria_code/evals/behavior.py +113 -0
- aria_code/evals/gap.py +93 -0
- aria_code/evals/harness.py +949 -0
- aria_code/evals/review_probe.py +132 -0
- aria_code/evals/runner.py +425 -0
- aria_code/evals/scorecard.py +322 -0
- aria_code/evals/summary.py +125 -0
- aria_code/external_agent_runner.py +115 -0
- aria_code/figma_client.py +4 -0
- aria_code/file_analysis_tools.py +4 -0
- aria_code/finance_formulas.py +4 -0
- aria_code/football_data_client.py +4 -0
- aria_code/image_gen_tools.py +4 -0
- aria_code/intent_classifier.py +459 -0
- aria_code/kling_video_client.py +4 -0
- aria_code/licensing.py +151 -0
- aria_code/local_finance_tools.py +4 -0
- aria_code/local_image_provider.py +4 -0
- aria_code/local_llm_provider.py +4 -0
- aria_code/macro_tools.py +4 -0
- aria_code/markdown_pdf.py +289 -0
- aria_code/market_data_client.py +4 -0
- aria_code/mcp_client.py +744 -0
- aria_code/memory_manager.py +273 -0
- aria_code/model_capability.py +512 -0
- aria_code/notification_tools.py +4 -0
- aria_code/openai_image_client.py +4 -0
- aria_code/packages/__init__.py +26 -0
- aria_code/packages/adk_bridge/__init__.py +11 -0
- aria_code/packages/adk_bridge/code_review_tools.py +49 -0
- aria_code/packages/adk_bridge/market_tools.py +125 -0
- aria_code/packages/aria_agents/__init__.py +5 -0
- aria_code/packages/aria_agents/manifest.py +78 -0
- aria_code/packages/aria_core/__init__.py +34 -0
- aria_code/packages/aria_core/architecture.py +269 -0
- aria_code/packages/aria_core/export.py +147 -0
- aria_code/packages/aria_core/manifest.py +65 -0
- aria_code/packages/aria_core/paths.py +57 -0
- aria_code/packages/aria_core/secure_file.py +68 -0
- aria_code/packages/aria_infra/__init__.py +15 -0
- aria_code/packages/aria_infra/arthera.py +58 -0
- aria_code/packages/aria_infra/doctor.py +246 -0
- aria_code/packages/aria_infra/product.py +40 -0
- aria_code/packages/aria_mcp/__init__.py +25 -0
- aria_code/packages/aria_mcp/bridge.py +232 -0
- aria_code/packages/aria_mcp/circuit.py +82 -0
- aria_code/packages/aria_mcp/config.py +162 -0
- aria_code/packages/aria_mcp/installer.py +95 -0
- aria_code/packages/aria_mcp/server.py +1705 -0
- aria_code/packages/aria_mcp/tools.py +81 -0
- aria_code/packages/aria_sdk/__init__.py +19 -0
- aria_code/packages/aria_sdk/client.py +393 -0
- aria_code/packages/aria_sdk/providers.py +70 -0
- aria_code/packages/aria_sdk/streaming.py +75 -0
- aria_code/packages/aria_sdk/types.py +86 -0
- aria_code/packages/aria_services/__init__.py +92 -0
- aria_code/packages/aria_services/cache.py +60 -0
- aria_code/packages/aria_services/context.py +356 -0
- aria_code/packages/aria_services/context_checkpoints.py +157 -0
- aria_code/packages/aria_services/data.py +11 -0
- aria_code/packages/aria_services/provider_health.py +304 -0
- aria_code/packages/aria_services/references.py +247 -0
- aria_code/packages/aria_services/registry.py +249 -0
- aria_code/packages/aria_services/research_protocol.py +137 -0
- aria_code/packages/aria_services/research_quality.py +186 -0
- aria_code/packages/aria_services/settings.py +160 -0
- aria_code/packages/aria_services/usage.py +151 -0
- aria_code/packages/aria_skills/__init__.py +46 -0
- aria_code/packages/aria_skills/catalog.py +149 -0
- aria_code/packages/aria_skills/loader.py +455 -0
- aria_code/packages/aria_skills/registry.py +84 -0
- aria_code/packages/aria_tools/__init__.py +5 -0
- aria_code/packages/aria_tools/financial/__init__.py +5 -0
- aria_code/packages/aria_tools/financial/_paths.py +92 -0
- aria_code/packages/aria_tools/registry.py +129 -0
- aria_code/packages/quant_engine/__init__.py +33 -0
- aria_code/packages/quant_engine/_namespace.py +24 -0
- aria_code/packages/quant_engine/backtest/__init__.py +10 -0
- aria_code/packages/quant_engine/backtest/core.py +53 -0
- aria_code/packages/quant_engine/backtest/engine.py +102 -0
- aria_code/packages/quant_engine/portfolio/__init__.py +9 -0
- aria_code/packages/quant_engine/portfolio/optimizer.py +85 -0
- aria_code/packages/quant_engine/sports/__init__.py +76 -0
- aria_code/packages/quant_engine/sports/calibrator.py +354 -0
- aria_code/packages/quant_engine/sports/dixon_coles.py +234 -0
- aria_code/packages/quant_engine/sports/elo.py +300 -0
- aria_code/packages/quant_engine/sports/form.py +188 -0
- aria_code/packages/quant_engine/sports/h2h.py +195 -0
- aria_code/packages/quant_engine/sports/predictor.py +312 -0
- aria_code/packages/quant_engine/sports/tracker.py +665 -0
- aria_code/packages/quant_engine/stochastic/__init__.py +31 -0
- aria_code/packages/quant_engine/stochastic/gbm_enhanced.py +195 -0
- aria_code/packages/quant_engine/stochastic/ito_calculus.py +477 -0
- aria_code/packages/quant_engine/stochastic/kelly_criterion.py +181 -0
- aria_code/packages/quant_engine/stochastic/monte_carlo_advanced.py +95 -0
- aria_code/packages/quant_engine/stochastic/options_pricing.py +576 -0
- aria_code/packages/quant_engine/stochastic/stochastic_processes.py +90 -0
- aria_code/packs/__init__.py +85 -0
- aria_code/packs/base.py +168 -0
- aria_code/packs/finance/__init__.py +250 -0
- aria_code/packs/healthcare/__init__.py +40 -0
- aria_code/packs/logistics/__init__.py +171 -0
- aria_code/packs/payments/__init__.py +139 -0
- aria_code/packs/realty/__init__.py +190 -0
- aria_code/packs/registry.py +202 -0
- aria_code/packs/rules.py +90 -0
- aria_code/plan_utils.py +194 -0
- aria_code/plugin_loader.py +328 -0
- aria_code/portfolio_ledger.py +4 -0
- aria_code/preview_server.py +449 -0
- aria_code/privacy/__init__.py +5 -0
- aria_code/privacy/feedback.py +123 -0
- aria_code/project_review.py +278 -0
- aria_code/project_review_api.py +235 -0
- aria_code/project_review_server.py +18 -0
- aria_code/project_tools.py +4 -0
- aria_code/providers/__init__.py +30 -0
- aria_code/providers/google_video_provider.py +256 -0
- aria_code/providers/llm/__init__.py +19 -0
- aria_code/providers/llm/anthropic.py +184 -0
- aria_code/providers/llm/arthera_gateway.py +90 -0
- aria_code/providers/llm/autoconfig.py +213 -0
- aria_code/providers/llm/base.py +139 -0
- aria_code/providers/llm/custom.py +158 -0
- aria_code/providers/llm/ollama.py +137 -0
- aria_code/providers/llm/openai_compat.py +350 -0
- aria_code/providers/llm/registry.py +457 -0
- aria_code/providers/local_image_provider.py +202 -0
- aria_code/providers/local_llm_provider.py +549 -0
- aria_code/providers/ollama_models.py +79 -0
- aria_code/providers/openai_params.py +32 -0
- aria_code/providers/tool_messages.py +100 -0
- aria_code/realty_data_tools.py +4 -0
- aria_code/report_exporters.py +150 -0
- aria_code/report_generator.py +1764 -0
- aria_code/review_service.py +497 -0
- aria_code/runtime/__init__.py +176 -0
- aria_code/runtime/acceptance.py +632 -0
- aria_code/runtime/agent_loop.py +1851 -0
- aria_code/runtime/agent_profiles.py +75 -0
- aria_code/runtime/approval.py +71 -0
- aria_code/runtime/baseline.py +219 -0
- aria_code/runtime/budget.py +232 -0
- aria_code/runtime/checkpoints.py +481 -0
- aria_code/runtime/consult.py +65 -0
- aria_code/runtime/contract.py +282 -0
- aria_code/runtime/delivery.py +432 -0
- aria_code/runtime/events.py +113 -0
- aria_code/runtime/gateway.py +167 -0
- aria_code/runtime/lsp.py +484 -0
- aria_code/runtime/native_index.py +153 -0
- aria_code/runtime/orchestrator.py +55 -0
- aria_code/runtime/processes.py +343 -0
- aria_code/runtime/project_graph.py +614 -0
- aria_code/runtime/repo_map.py +712 -0
- aria_code/runtime/research_bundle.py +105 -0
- aria_code/runtime/review.py +269 -0
- aria_code/runtime/run_state.py +127 -0
- aria_code/runtime/run_store.py +522 -0
- aria_code/runtime/scoped_runs.py +113 -0
- aria_code/runtime/self_healing.py +422 -0
- aria_code/runtime/semantic_diff.py +171 -0
- aria_code/runtime/subagent.py +721 -0
- aria_code/runtime/symbol_edit.py +117 -0
- aria_code/runtime/task_brief.py +46 -0
- aria_code/runtime/task_context.py +145 -0
- aria_code/runtime/task_ledger.py +108 -0
- aria_code/runtime/task_orchestrator.py +90 -0
- aria_code/runtime/task_outcome.py +33 -0
- aria_code/runtime/task_verification.py +266 -0
- aria_code/runtime/task_worktree.py +448 -0
- aria_code/runtime/tool_executor.py +329 -0
- aria_code/runtime/tool_policy.py +107 -0
- aria_code/runtime/transactions.py +216 -0
- aria_code/runtime/windows_job.py +115 -0
- aria_code/runtime/workflows.py +222 -0
- aria_code/runtime/worktrees.py +215 -0
- aria_code/runway_video_client.py +4 -0
- aria_code/safety/__init__.py +27 -0
- aria_code/safety/client_isolation.py +178 -0
- aria_code/safety/permissions.py +339 -0
- aria_code/safety/risk.py +699 -0
- aria_code/safety/sandbox.py +148 -0
- aria_code/safety/service.py +102 -0
- aria_code/service_endpoints.py +14 -0
- aria_code/setup_wizard.py +684 -0
- aria_code/spreadsheet_tools.py +4 -0
- aria_code/strategy_vault.py +4 -0
- aria_code/tools/__init__.py +0 -0
- aria_code/tools/artifact_tools.py +252 -0
- aria_code/tools/broker_tools.py +92 -0
- aria_code/tools/build_quant_engine.py +97 -0
- aria_code/tools/code_audit_tools.py +192 -0
- aria_code/tools/computer_use_tools.py +509 -0
- aria_code/tools/data_analysis_tools.py +831 -0
- aria_code/tools/enterprise_finance_tools.py +202 -0
- aria_code/tools/extended_tools.py +240 -0
- aria_code/tools/file_analysis_tools.py +880 -0
- aria_code/tools/image_gen_tools.py +114 -0
- aria_code/tools/local_finance_tools.py +3488 -0
- aria_code/tools/logistics_carriers.py +11 -0
- aria_code/tools/logistics_inventory.py +11 -0
- aria_code/tools/logistics_io.py +11 -0
- aria_code/tools/logistics_tenancy.py +11 -0
- aria_code/tools/logistics_tools.py +11 -0
- aria_code/tools/macro_tools.py +412 -0
- aria_code/tools/notification_tools.py +249 -0
- aria_code/tools/project_tools.py +525 -0
- aria_code/tools/realty_data_tools.py +662 -0
- aria_code/tools/spreadsheet_tools.py +399 -0
- aria_code/tools/stripe_tools.py +115 -0
- aria_code/tools/video_tools.py +500 -0
- aria_code/training/__init__.py +1 -0
- aria_code/training/compare.py +117 -0
- aria_code/training/prelude_commands.py +111 -0
- aria_code/training/prelude_eval.py +390 -0
- aria_code/training/prelude_real.py +183 -0
- aria_code/training/prelude_train.py +248 -0
- aria_code/training/sft_dataset.py +230 -0
- aria_code/training/trajectory_dataset.py +263 -0
- aria_code/ui/__init__.py +105 -0
- aria_code/ui/banner.py +404 -0
- aria_code/ui/completer.py +571 -0
- aria_code/ui/console.py +285 -0
- aria_code/ui/input_box.py +505 -0
- aria_code/ui/mentions.py +206 -0
- aria_code/ui/picker.py +248 -0
- aria_code/ui/render/__init__.py +11 -0
- aria_code/ui/render/actions.py +297 -0
- aria_code/ui/render/finance.py +1732 -0
- aria_code/ui/render/market.py +253 -0
- aria_code/ui/render/output.py +954 -0
- aria_code/ui/render/responsive.py +75 -0
- aria_code/ui/render/team.py +367 -0
- aria_code/ui/robot.py +239 -0
- aria_code/ui/startup_dashboard.py +110 -0
- aria_code/video_analysis.py +147 -0
- aria_code/video_editor.py +518 -0
- aria_code/video_workflow/__init__.py +8 -0
- aria_code/video_workflow/__main__.py +61 -0
- aria_code/video_workflow/engines/__init__.py +18 -0
- aria_code/video_workflow/engines/base.py +69 -0
- aria_code/video_workflow/engines/custom_model.py +204 -0
- aria_code/video_workflow/engines/google_veo.py +94 -0
- aria_code/video_workflow/engines/local_engine.py +71 -0
- aria_code/video_workflow/engines/registry.py +98 -0
- aria_code/video_workflow/google_models.py +278 -0
- aria_code/video_workflow/music/__init__.py +5 -0
- aria_code/video_workflow/music/foley_service.py +132 -0
- aria_code/video_workflow/music/service.py +212 -0
- aria_code/video_workflow/pipeline.py +620 -0
- aria_code/video_workflow/plan.py +202 -0
- aria_code/video_workflow/session.py +297 -0
- aria_code/workspace/__init__.py +6 -0
- aria_code/workspace/files.py +219 -0
- aria_code/workspace/verify.py +167 -0
- aria_code/workspace_changes.py +199 -0
- aria_code/workspace_service.py +196 -0
- aria_code/workspace_tools.py +150 -0
- aria_code-0.167.0.dist-info/METADATA +330 -0
- aria_code-0.167.0.dist-info/RECORD +601 -0
- aria_code-0.167.0.dist-info/WHEEL +5 -0
- aria_code-0.167.0.dist-info/entry_points.txt +5 -0
- aria_code-0.167.0.dist-info/licenses/LICENSE +201 -0
- aria_code-0.167.0.dist-info/licenses/NOTICE +49 -0
- aria_code-0.167.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
# Keep the public analysis-agent API, without eager registration of every domain.
|
|
25
|
+
# Task-agent capabilities must not initialize finance/vendor SDKs on import.
|
|
26
|
+
from importlib import import_module
|
|
27
|
+
|
|
28
|
+
_EXPORTS = {
|
|
29
|
+
"BaseAgent": (".base", "BaseAgent"), "AgentResult": (".base", "AgentResult"),
|
|
30
|
+
"AgentRegistry": (".registry", "AgentRegistry"), "get_registry": (".registry", "get_registry"),
|
|
31
|
+
"AgentTeam": (".team", "AgentTeam"), "run_team": (".team", "run_team"),
|
|
32
|
+
"SignalScheme": (".signal_scheme", "SignalScheme"),
|
|
33
|
+
"FINANCIAL_SCHEME": (".signal_scheme", "FINANCIAL_SCHEME"),
|
|
34
|
+
"REALTY_SCHEME": (".signal_scheme", "REALTY_SCHEME"),
|
|
35
|
+
}
|
|
36
|
+
__all__ = list(_EXPORTS)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def __getattr__(name):
|
|
40
|
+
if name not in _EXPORTS:
|
|
41
|
+
raise AttributeError(name)
|
|
42
|
+
module, attribute = _EXPORTS[name]
|
|
43
|
+
value = getattr(import_module(module, __name__), attribute)
|
|
44
|
+
globals()[name] = value
|
|
45
|
+
return value
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def __dir__():
|
|
49
|
+
return sorted(set(globals()) | set(__all__))
|
aria_code/agents/base.py
ADDED
|
@@ -0,0 +1,329 @@
|
|
|
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.llm_error: Optional[str] = None # why the last model call gave nothing, if it failed
|
|
107
|
+
self.memory = [] # Short-term conversation history for multi-turn context
|
|
108
|
+
|
|
109
|
+
async def fetch_data(self, symbol: str) -> Dict[str, Any]:
|
|
110
|
+
"""
|
|
111
|
+
从数据路由器获取分析所需数据。
|
|
112
|
+
子类可覆盖此方法以自定义数据获取逻辑。
|
|
113
|
+
"""
|
|
114
|
+
if not self.data:
|
|
115
|
+
return {}
|
|
116
|
+
result = {}
|
|
117
|
+
try:
|
|
118
|
+
q = self.data.quote(symbol)
|
|
119
|
+
if q:
|
|
120
|
+
result["quote"] = q.to_dict()
|
|
121
|
+
except Exception as e:
|
|
122
|
+
logger.debug(f"[{self.name}] fetch quote {symbol}: {e}")
|
|
123
|
+
return result
|
|
124
|
+
|
|
125
|
+
def _data_guard(self, quote: Dict[str, Any]) -> str:
|
|
126
|
+
"""Return a warning string if real data is unavailable; empty string if data is present."""
|
|
127
|
+
price = quote.get("price") if quote else None
|
|
128
|
+
if not price or float(price) == 0:
|
|
129
|
+
return (
|
|
130
|
+
"\n\n## ⛔ DATA UNAVAILABLE — STRICT RULES\n"
|
|
131
|
+
"Real market data could not be fetched (price=0 or missing).\n"
|
|
132
|
+
"You MUST:\n"
|
|
133
|
+
"1. State clearly that no real data is available.\n"
|
|
134
|
+
"2. NEVER invent specific prices, P/E ratios, EPS, revenue, RSI, MACD, or any numbers.\n"
|
|
135
|
+
"3. NEVER give specific price targets, stop-loss levels, or entry prices.\n"
|
|
136
|
+
"4. Give only qualitative analysis based on publicly known company characteristics.\n"
|
|
137
|
+
"5. End with the signal word (BUY/HOLD/SELL) but with low confidence (≤40%).\n"
|
|
138
|
+
)
|
|
139
|
+
return ""
|
|
140
|
+
|
|
141
|
+
async def _execute_tool(self, tool_name: str, tool_args: Dict[str, Any]) -> str:
|
|
142
|
+
"""
|
|
143
|
+
执行本地工具或 MCP 工具(可被子类重写扩展)。
|
|
144
|
+
实际项目中可将 aria-skills 暴露为工具。
|
|
145
|
+
"""
|
|
146
|
+
if self.on_tool_start:
|
|
147
|
+
self.on_tool_start(tool_name, tool_args)
|
|
148
|
+
|
|
149
|
+
result = None
|
|
150
|
+
try:
|
|
151
|
+
# 路由到数据层或其他 MCP Client 执行
|
|
152
|
+
if self.data and hasattr(self.data, "execute_tool"):
|
|
153
|
+
result = await self.data.execute_tool(tool_name, tool_args)
|
|
154
|
+
else:
|
|
155
|
+
result = f"Error: Tool {tool_name} not implemented or data router unavailable."
|
|
156
|
+
except Exception as e:
|
|
157
|
+
result = f"Error executing {tool_name}: {e}"
|
|
158
|
+
|
|
159
|
+
if self.on_tool_end:
|
|
160
|
+
self.on_tool_end(tool_name, result)
|
|
161
|
+
|
|
162
|
+
import json
|
|
163
|
+
return json.dumps(result, ensure_ascii=False) if not isinstance(result, str) else result
|
|
164
|
+
|
|
165
|
+
async def _call_llm(
|
|
166
|
+
self,
|
|
167
|
+
system: str,
|
|
168
|
+
user: str,
|
|
169
|
+
max_tokens: int = 800,
|
|
170
|
+
quote: Optional[Dict[str, Any]] = None,
|
|
171
|
+
max_tool_loops: int = 5,
|
|
172
|
+
) -> str:
|
|
173
|
+
"""调用 LLM 生成分析文本,内置 Tool Calling 的执行循环"""
|
|
174
|
+
if not self.llm:
|
|
175
|
+
return ""
|
|
176
|
+
# Inject language rule + time-sensitive fact policy + data guard.
|
|
177
|
+
_lang_rule = self._LANG_RULES.get(self.lang, self._LANG_RULES["zh"])
|
|
178
|
+
_data_warn = self._data_guard(quote or {})
|
|
179
|
+
system = system + self._TIME_SENSITIVE_FACT_POLICY + _lang_rule + _data_warn
|
|
180
|
+
if self.lang == "en":
|
|
181
|
+
# The agents' own prompts and much of their data are Chinese. A rule
|
|
182
|
+
# appended at the end lost to them: an English /team synthesis on
|
|
183
|
+
# Gemini came back in Chinese. Say it first as well.
|
|
184
|
+
system = ("Write your entire answer in English, even though the instructions and data "
|
|
185
|
+
"below may be in Chinese.\n\n" + system)
|
|
186
|
+
from aria_code.providers.llm.base import Message
|
|
187
|
+
|
|
188
|
+
# 自动注入 DAG pipeline 中的 upstream context
|
|
189
|
+
if hasattr(self, "_current_data") and self._current_data:
|
|
190
|
+
upstream = self._current_data.get("upstream_context")
|
|
191
|
+
if upstream:
|
|
192
|
+
user += "\n\n## ⬆️ 团队/上游 Agent 提供的背景上下文 (Upstream Insights)\n"
|
|
193
|
+
user += "请在分析中参考以下来自其他专家 Agent 的核心观点:\n"
|
|
194
|
+
user += "\n".join(upstream)
|
|
195
|
+
|
|
196
|
+
# 融入历史记忆
|
|
197
|
+
if not self.memory:
|
|
198
|
+
messages = [
|
|
199
|
+
Message(role="system", content=system),
|
|
200
|
+
Message(role="user", content=user),
|
|
201
|
+
]
|
|
202
|
+
else:
|
|
203
|
+
messages = list(self.memory)
|
|
204
|
+
messages.append(Message(role="user", content=user))
|
|
205
|
+
|
|
206
|
+
full_text = ""
|
|
207
|
+
loop_count = 0
|
|
208
|
+
|
|
209
|
+
while loop_count < max_tool_loops:
|
|
210
|
+
loop_count += 1
|
|
211
|
+
current_text = ""
|
|
212
|
+
tool_calls = []
|
|
213
|
+
|
|
214
|
+
try:
|
|
215
|
+
async for event in self.llm.stream(
|
|
216
|
+
messages, max_tokens=max_tokens
|
|
217
|
+
):
|
|
218
|
+
t = event.get("type")
|
|
219
|
+
if t == "token":
|
|
220
|
+
tok = event.get("text", "")
|
|
221
|
+
current_text += tok
|
|
222
|
+
full_text += tok
|
|
223
|
+
if self.on_token:
|
|
224
|
+
self.on_token(tok)
|
|
225
|
+
elif t == "thought" and self.on_thought:
|
|
226
|
+
self.on_thought(event.get("text", ""))
|
|
227
|
+
elif t == "tool_call":
|
|
228
|
+
# 记录工具调用意图
|
|
229
|
+
tool_calls.append({
|
|
230
|
+
"name": event.get("name"),
|
|
231
|
+
"args": event.get("args", {})
|
|
232
|
+
})
|
|
233
|
+
elif t == "tool_start" and self.on_tool_start:
|
|
234
|
+
self.on_tool_start(event.get("tool_name", ""), event.get("tool_args", {}))
|
|
235
|
+
elif t == "tool_end" and self.on_tool_end:
|
|
236
|
+
self.on_tool_end(event.get("tool_name", ""), event.get("tool_result", None))
|
|
237
|
+
elif t == "error":
|
|
238
|
+
# The caller falls back to a template and says so; a
|
|
239
|
+
# WARNING here went to the terminal as a raw log line.
|
|
240
|
+
self.llm_error = str(event.get("message") or "error")
|
|
241
|
+
logger.info(f"[{self.name}] LLM 错误: {event.get('message')}")
|
|
242
|
+
break
|
|
243
|
+
except Exception as e:
|
|
244
|
+
self.llm_error = str(e) or type(e).__name__
|
|
245
|
+
logger.info(f"[{self.name}] LLM 调用失败: {e}")
|
|
246
|
+
break
|
|
247
|
+
|
|
248
|
+
# 将当前 Assistant 的回复加入消息流
|
|
249
|
+
messages.append(Message(role="assistant", content=current_text))
|
|
250
|
+
|
|
251
|
+
# 如果没有工具调用,说明 LLM 完成了最终回答,跳出循环
|
|
252
|
+
|
|
253
|
+
# If provider didn't emit native tool_calls, fallback to ReAct JSON parsing
|
|
254
|
+
if not tool_calls:
|
|
255
|
+
import re
|
|
256
|
+
import json
|
|
257
|
+
|
|
258
|
+
# Check for explicit JSON tool calls outputted as text
|
|
259
|
+
matches = re.finditer(r'```json\s*({"type":\s*"tool_call".*?})\s*```', current_text, re.DOTALL)
|
|
260
|
+
for match in matches:
|
|
261
|
+
try:
|
|
262
|
+
parsed = json.loads(match.group(1))
|
|
263
|
+
tool_calls.append({
|
|
264
|
+
"name": parsed.get("name"),
|
|
265
|
+
"args": parsed.get("args", {})
|
|
266
|
+
})
|
|
267
|
+
except Exception as e:
|
|
268
|
+
logger.warning(f"Failed to parse ReAct tool call: {e}")
|
|
269
|
+
|
|
270
|
+
# Also check inline unformatted JSON
|
|
271
|
+
if not tool_calls:
|
|
272
|
+
matches_raw = re.finditer(r'{"type":\s*"tool_call",\s*"name":\s*"([^"]+)",\s*"args":\s*({.*?})}', current_text, re.DOTALL)
|
|
273
|
+
for match in matches_raw:
|
|
274
|
+
try:
|
|
275
|
+
args_dict = json.loads(match.group(2))
|
|
276
|
+
tool_calls.append({
|
|
277
|
+
"name": match.group(1),
|
|
278
|
+
"args": args_dict
|
|
279
|
+
})
|
|
280
|
+
except Exception:
|
|
281
|
+
pass
|
|
282
|
+
|
|
283
|
+
if not tool_calls:
|
|
284
|
+
break
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
# 有工具调用,则逐一执行,并把结果喂回 LLM
|
|
288
|
+
for tc in tool_calls:
|
|
289
|
+
tool_res = await self._execute_tool(tc["name"], tc["args"])
|
|
290
|
+
# 注意:实际 provider 中 Message 结构可能需要 tool_call_id
|
|
291
|
+
# 这里假设通用 Message 能够携带 role="tool"
|
|
292
|
+
messages.append(Message(role="tool", name=tc["name"], content=tool_res))
|
|
293
|
+
|
|
294
|
+
# 更新短期记忆
|
|
295
|
+
self.memory = messages
|
|
296
|
+
|
|
297
|
+
return full_text.strip()
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
@abstractmethod
|
|
301
|
+
async def analyze(self, symbol: str, data: Dict[str, Any]) -> AgentResult:
|
|
302
|
+
"""
|
|
303
|
+
核心分析方法。
|
|
304
|
+
|
|
305
|
+
Args:
|
|
306
|
+
symbol: 股票/资产代码
|
|
307
|
+
data: 由 fetch_data() 预取的数据字典
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
AgentResult
|
|
311
|
+
"""
|
|
312
|
+
...
|
|
313
|
+
|
|
314
|
+
async def run(self, symbol: str) -> AgentResult:
|
|
315
|
+
"""完整执行:fetch_data → analyze,异常自动捕获。"""
|
|
316
|
+
try:
|
|
317
|
+
data = await self.fetch_data(symbol)
|
|
318
|
+
result = await self.analyze(symbol, data)
|
|
319
|
+
return result
|
|
320
|
+
except Exception as e:
|
|
321
|
+
logger.error(f"[{self.name}] run({symbol}) 失败: {e}", exc_info=True)
|
|
322
|
+
return AgentResult(
|
|
323
|
+
agent=self.name, symbol=symbol,
|
|
324
|
+
analysis="", confidence=0.0,
|
|
325
|
+
error=str(e),
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
def __repr__(self) -> str:
|
|
329
|
+
return f"{self.__class__.__name__}(name={self.name!r})"
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"""Deterministic, read-only code review agent.
|
|
2
|
+
|
|
3
|
+
The agent deliberately reviews caller-supplied text only. It never resolves a
|
|
4
|
+
path, invokes a shell, or changes a workspace, so it can be used safely from
|
|
5
|
+
both the CLI and a Google ADK function tool.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import ast
|
|
11
|
+
import re
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from pathlib import PurePath
|
|
14
|
+
from typing import Any, Dict, Iterable, List
|
|
15
|
+
|
|
16
|
+
from .base import AgentResult, BaseAgent
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True)
|
|
20
|
+
class CodeReviewFinding:
|
|
21
|
+
"""A stable, evidence-bearing static-review finding."""
|
|
22
|
+
|
|
23
|
+
severity: str
|
|
24
|
+
rule: str
|
|
25
|
+
message: str
|
|
26
|
+
line: int | None
|
|
27
|
+
evidence: str
|
|
28
|
+
|
|
29
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
30
|
+
return {
|
|
31
|
+
"severity": self.severity,
|
|
32
|
+
"rule": self.rule,
|
|
33
|
+
"message": self.message,
|
|
34
|
+
"line": self.line,
|
|
35
|
+
"evidence": self.evidence,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class CodeReviewAgent(BaseAgent):
|
|
40
|
+
"""Find high-signal correctness and security hazards without an LLM."""
|
|
41
|
+
|
|
42
|
+
name = "code_review"
|
|
43
|
+
description = "Read-only deterministic code review for user-supplied snippets and diffs"
|
|
44
|
+
MAX_SOURCE_CHARS = 48_000
|
|
45
|
+
_SEVERITY_ORDER = {"critical": 0, "high": 1, "medium": 2, "low": 3}
|
|
46
|
+
_SECRET_ASSIGNMENT = re.compile(
|
|
47
|
+
r"\b(?:api[_-]?key|secret|token|password)\b\s*=\s*['\"][^'\"]{8,}['\"]",
|
|
48
|
+
re.IGNORECASE,
|
|
49
|
+
)
|
|
50
|
+
_TOKEN_LITERAL = re.compile(r"\b(?:(?:ghp|github_pat)_[A-Za-z0-9_-]{12,}|sk-[A-Za-z0-9_-]{12,})\b", re.IGNORECASE)
|
|
51
|
+
_SHELL_TRUE = re.compile(r"\b(?:subprocess\.[A-Za-z_]+|os\.system)\b.*\bshell\s*=\s*True", re.IGNORECASE)
|
|
52
|
+
_EVAL_EXEC = re.compile(r"\b(?:eval|exec)\s*\(")
|
|
53
|
+
_PICKLE = re.compile(r"\bpickle\.loads?\s*\(")
|
|
54
|
+
_UNSAFE_YAML = re.compile(r"\byaml\.load\s*\(")
|
|
55
|
+
_TLS_DISABLED = re.compile(r"\brequests\.[A-Za-z_]+\s*\(.*\bverify\s*=\s*False", re.IGNORECASE)
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def _safe_filename(filename: str) -> str:
|
|
59
|
+
name = PurePath(str(filename or "snippet.py")).name
|
|
60
|
+
return name[:160] or "snippet.py"
|
|
61
|
+
|
|
62
|
+
@classmethod
|
|
63
|
+
def _append(
|
|
64
|
+
cls,
|
|
65
|
+
findings: List[CodeReviewFinding],
|
|
66
|
+
severity: str,
|
|
67
|
+
rule: str,
|
|
68
|
+
message: str,
|
|
69
|
+
line: int | None,
|
|
70
|
+
evidence: str,
|
|
71
|
+
) -> None:
|
|
72
|
+
if rule == "hardcoded-secret":
|
|
73
|
+
evidence = "<credential value redacted>"
|
|
74
|
+
findings.append(
|
|
75
|
+
CodeReviewFinding(
|
|
76
|
+
severity=severity,
|
|
77
|
+
rule=rule,
|
|
78
|
+
message=message,
|
|
79
|
+
line=line,
|
|
80
|
+
evidence=evidence.strip()[:240],
|
|
81
|
+
)
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def _scan_lines(cls, lines: Iterable[str], findings: List[CodeReviewFinding]) -> None:
|
|
86
|
+
for number, line in enumerate(lines, start=1):
|
|
87
|
+
if cls._SECRET_ASSIGNMENT.search(line) or cls._TOKEN_LITERAL.search(line):
|
|
88
|
+
cls._append(
|
|
89
|
+
findings, "high", "hardcoded-secret",
|
|
90
|
+
"疑似硬编码凭据;改用环境变量或受管密钥,并立即轮换已暴露的值。",
|
|
91
|
+
number, line,
|
|
92
|
+
)
|
|
93
|
+
if cls._SHELL_TRUE.search(line):
|
|
94
|
+
cls._append(
|
|
95
|
+
findings, "high", "shell-true",
|
|
96
|
+
"shell=True 会把不可信输入交给 shell 解释;改用参数列表和严格的输入校验。",
|
|
97
|
+
number, line,
|
|
98
|
+
)
|
|
99
|
+
if cls._EVAL_EXEC.search(line):
|
|
100
|
+
cls._append(
|
|
101
|
+
findings, "high", "dynamic-execution",
|
|
102
|
+
"eval/exec 可执行不可信文本;使用受限解析器或显式分发表。",
|
|
103
|
+
number, line,
|
|
104
|
+
)
|
|
105
|
+
if cls._PICKLE.search(line):
|
|
106
|
+
cls._append(
|
|
107
|
+
findings, "high", "unsafe-deserialization",
|
|
108
|
+
"pickle 反序列化不可信数据可执行任意代码;改用 JSON 或签名的可信工件。",
|
|
109
|
+
number, line,
|
|
110
|
+
)
|
|
111
|
+
if cls._UNSAFE_YAML.search(line) and "Loader=" not in line:
|
|
112
|
+
cls._append(
|
|
113
|
+
findings, "high", "unsafe-yaml-load",
|
|
114
|
+
"yaml.load 未指定安全 Loader;使用 yaml.safe_load。",
|
|
115
|
+
number, line,
|
|
116
|
+
)
|
|
117
|
+
if cls._TLS_DISABLED.search(line):
|
|
118
|
+
cls._append(
|
|
119
|
+
findings, "high", "tls-verification-disabled",
|
|
120
|
+
"TLS 证书校验被关闭;除受控测试外不得使用 verify=False。",
|
|
121
|
+
number, line,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
@classmethod
|
|
125
|
+
def review_source(
|
|
126
|
+
cls,
|
|
127
|
+
source: str,
|
|
128
|
+
*,
|
|
129
|
+
filename: str = "snippet.py",
|
|
130
|
+
language: str = "python",
|
|
131
|
+
is_diff: bool = False,
|
|
132
|
+
) -> List[CodeReviewFinding]:
|
|
133
|
+
"""Review source text or an already-provided diff without touching disk."""
|
|
134
|
+
if not isinstance(source, str) or not source.strip():
|
|
135
|
+
return [CodeReviewFinding("medium", "empty-input", "没有可审查的代码内容。", None, "")]
|
|
136
|
+
if len(source) > cls.MAX_SOURCE_CHARS:
|
|
137
|
+
return [CodeReviewFinding(
|
|
138
|
+
"medium", "input-truncated",
|
|
139
|
+
f"审查输入超过 {cls.MAX_SOURCE_CHARS} 字符;请按文件或提交拆分后复查。",
|
|
140
|
+
None, "",
|
|
141
|
+
)]
|
|
142
|
+
|
|
143
|
+
findings: List[CodeReviewFinding] = []
|
|
144
|
+
lines = source.splitlines()
|
|
145
|
+
scan_lines = [line[1:] for line in lines if line.startswith("+") and not line.startswith("+++")] if is_diff else lines
|
|
146
|
+
cls._scan_lines(scan_lines, findings)
|
|
147
|
+
|
|
148
|
+
inferred_python = language.lower() in {"py", "python"} or cls._safe_filename(filename).endswith(".py")
|
|
149
|
+
if inferred_python and not is_diff:
|
|
150
|
+
try:
|
|
151
|
+
tree = ast.parse(source, filename=cls._safe_filename(filename))
|
|
152
|
+
except SyntaxError as exc:
|
|
153
|
+
cls._append(
|
|
154
|
+
findings, "critical", "python-syntax-error",
|
|
155
|
+
"Python 代码无法解析,运行前会失败。",
|
|
156
|
+
exc.lineno, (exc.text or "").strip(),
|
|
157
|
+
)
|
|
158
|
+
else:
|
|
159
|
+
for node in ast.walk(tree):
|
|
160
|
+
if isinstance(node, ast.ExceptHandler) and node.type is None:
|
|
161
|
+
cls._append(
|
|
162
|
+
findings, "medium", "bare-except",
|
|
163
|
+
"裸 except 会吞掉系统退出和中断;至少捕获 Exception,并记录或处理错误。",
|
|
164
|
+
node.lineno, "except:",
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
unique = {(item.rule, item.line, item.evidence): item for item in findings}
|
|
168
|
+
return sorted(unique.values(), key=lambda item: (cls._SEVERITY_ORDER[item.severity], item.line or 0, item.rule))
|
|
169
|
+
|
|
170
|
+
@classmethod
|
|
171
|
+
def format_findings(cls, findings: List[CodeReviewFinding]) -> str:
|
|
172
|
+
if not findings:
|
|
173
|
+
return "确定性检查未发现已覆盖规则中的问题;仍需执行测试并进行语义审查。"
|
|
174
|
+
rows = []
|
|
175
|
+
for finding in findings:
|
|
176
|
+
location = f"第 {finding.line} 行" if finding.line else "输入级"
|
|
177
|
+
rows.append(f"[{finding.severity.upper()}] {location} {finding.rule}: {finding.message}")
|
|
178
|
+
return "\n".join(rows)
|
|
179
|
+
|
|
180
|
+
async def analyze(self, symbol: str, data: Dict[str, Any]) -> AgentResult:
|
|
181
|
+
source = str(data.get("source") or data.get("content") or data.get("diff") or "")
|
|
182
|
+
filename = self._safe_filename(str(data.get("filename") or symbol or "snippet.py"))
|
|
183
|
+
findings = self.review_source(
|
|
184
|
+
source,
|
|
185
|
+
filename=filename,
|
|
186
|
+
language=str(data.get("language") or "python"),
|
|
187
|
+
is_diff=bool(data.get("is_diff")),
|
|
188
|
+
)
|
|
189
|
+
return AgentResult(
|
|
190
|
+
agent=self.name,
|
|
191
|
+
symbol=filename,
|
|
192
|
+
analysis=self.format_findings(findings),
|
|
193
|
+
confidence=0.99 if source else 0.0,
|
|
194
|
+
signal="HOLD",
|
|
195
|
+
key_points=[f"{item.severity}: {item.rule}" for item in findings[:8]],
|
|
196
|
+
data_used={"filename": filename, "finding_count": len(findings)},
|
|
197
|
+
degraded=False,
|
|
198
|
+
provenance=["deterministic_static_review"],
|
|
199
|
+
limitations=["只审查调用方提供的文本;不会读取文件、执行命令或运行测试。"],
|
|
200
|
+
)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Deep analysis pipeline — Claude-Code-style layered research on top of AgentTeam.
|
|
2
|
+
|
|
3
|
+
Adds the four "deep" layers the flat team pipeline was missing:
|
|
4
|
+
|
|
5
|
+
P0 deepen — tool-augmented evidence gathering for material/uncertain findings
|
|
6
|
+
P1 hierarchical + critic — theme-grouped sub-synthesis, then a self-check pass
|
|
7
|
+
P2 quant fusion — fuse ML/backtest/risk signals as ground truth + calibrate confidence
|
|
8
|
+
P3 tiered output + provenance — brief / standard / deep reports with data lineage
|
|
9
|
+
|
|
10
|
+
Everything degrades gracefully: any layer whose dependency (LLM, quant tools, data
|
|
11
|
+
cleaner) is unavailable is skipped, never raised. The deterministic parts (theme
|
|
12
|
+
grouping, calibration math, critic rules, tier rendering) run with no LLM/network,
|
|
13
|
+
which keeps the pipeline testable.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from .models import (
|
|
19
|
+
Critique,
|
|
20
|
+
CritiqueIssue,
|
|
21
|
+
DeepAnalysisResult,
|
|
22
|
+
Provenance,
|
|
23
|
+
QuantEvidence,
|
|
24
|
+
ThemeGroup,
|
|
25
|
+
)
|
|
26
|
+
from .pipeline import DeepAnalysisPipeline, run_deep_analysis
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"Critique",
|
|
30
|
+
"CritiqueIssue",
|
|
31
|
+
"DeepAnalysisResult",
|
|
32
|
+
"Provenance",
|
|
33
|
+
"QuantEvidence",
|
|
34
|
+
"ThemeGroup",
|
|
35
|
+
"DeepAnalysisPipeline",
|
|
36
|
+
"run_deep_analysis",
|
|
37
|
+
]
|